1 // ********************************************************************************* 2 // Custom DPA Handler code example - User peripheral implementation - I2C master * 3 // ********************************************************************************* 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: CustomDpaHandler-UserPeripheral-I2Cmaster.c,v $ 7 // Version: $Revision: 1.19 $ 8 // Date: $Date: 2022/02/25 09:41:25 $ 9 // 10 // Revision history: 11 // 2022/02/24 Release for DPA 4.17 12 // 2021/08/20 Release for DPA 4.16 13 // 2020/01/02 Release for DPA 4.11 14 // 2019/10/09 Release for DPA 4.10 15 // 16 // ********************************************************************* 17 18 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 19 20 // This example implements Master I2C as a user peripheral 21 22 // Default IQRF include (modify the path according to your setup) 23 #include "IQRF.h" 24 25 // Default DPA header (modify the path according to your setup) 26 #include "DPA.h" 27 // Default Custom DPA Handler header (modify the path according to your setup) 28 #include "DPAcustomHandler.h" 29 30 /********************************************************************* 31 I2C master is controlled by DPA Request data sent to the user peripheral PNUM=0x20, PCMD=0x00. 32 The command allows to (optionally) write bytes to the I2C bus and then (optionally) read bytes from the bus. 33 34 *** DPA Request format *** 35 Byte index | Description 36 --------------------------------------------------------------------------------------------------------------------------- 37 0 | I2C 8-bit device address to write/read data to/from (bit.0 of the address is set when reading from the I2C bus). 38 1 | Number of bytes to read from I2C after data are written to the I2C bus. 39 2-55 | Optional bytes to write to the I2C before data are read from I2C bus. 40 41 *** DPA Response format *** 42 Byte index | Description 43 --------------------------------------------------------------------------------------------------------------------------- 44 0-55 | Byte read from I2C bus. If no bytes are read, no data is returned i.e. DPA Response is empty. 45 46 47 *** Example #1 *** 48 Configuring MCP9802 temperature sensor in the DDC-SE-01 connected to the DK-EVAL-04x for the 12-bit ADC, i.e. 0.0625 °C resolution. 49 50 DPA Request: 51 Byte index | Value [hex] | Description 52 --------------------------------------------------------------------------------------------------------------------------- 53 0 | 96 | MCP9802 I2C 8-bit address 54 1 | 00 | Read no data 55 2 | 01 | Write MCP9802 configuration register address 56 3 | 60 | Write MCP9802 configuration register value: 12-bit ADC, i.e. 0.0625°C resolution 57 58 DPA Response: 59 Empty as no data is read. 60 61 62 *** Example #2 *** 63 Reading temperature from MCP9802 temperature sensor in the DDC-SE-01 connected to the DK-EVAL-04x. 64 65 DPA Request: 66 Byte index | Value [hex] | Description 67 --------------------------------------------------------------------------------------------------------------------------- 68 0 | 96 | MCP9802 I2C 8-bit address 69 1 | 02 | Read 2 bytes with the temperature value 70 2 | 00 | Write MCP9802 ambient temperature register address 71 72 DPA Response: 73 Byte index | Value [hex] | Description 74 --------------------------------------------------------------------------------------------------------------------------- 75 0 | 17 | Upper half of the temperature register 76 1 | E0 | Lower half of the temperature register (0x17E0 = 23.875 °C) 77 78 ********************************************************************* 79 80 I2C signals to PIN assignment: 81 82 TR module pin | DK-EVAL-04x pin | I2C 83 ------------------------------------- 84 C7 | 2 | SDA 85 C6 | 3 | SCL 86 C4 | 7 | GND 87 88 ! Do not forget to connect pull-up resistors (e.g. 10k) between SDA and SCL and Vcc = 3 Volts preferably at I2C master side! 89 90 *********************************************************************/ 91 92 // I2C SCL frequency [Hz] 93 #define I2Cfrequency 100000 94 95 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location! 96 //############################################################################################ 97 bit CustomDpaHandler() 98 //############################################################################################ 99 { 100 // I2C master peripheral command data structure 101 typedef struct 102 { 103 uns8 I2Caddress; 104 uns8 ReadDataCount; 105 uns8 WriteData[DPA_MAX_DATA_LENGTH - 2 * sizeof( uns8 )]; 106 } TI2Crequest; 107 108 // Handler presence mark 109 clrwdt(); 110 111 // Detect DPA event to handle 112 switch ( GetDpaEvent() ) 113 { 114 // ------------------------------------------------- 115 case DpaEvent_Interrupt: 116 // Do an extra quick background interrupt work 117 return Carry; 118 119 // ------------------------------------------------- 120 case DpaEvent_DpaRequest: 121 // Called to interpret DPA request for peripherals 122 // ------------------------------------------------- 123 // Peripheral enumeration 124 if ( IsDpaEnumPeripheralsRequest() ) 125 { 126 // We implement 1 user peripheral 127 _DpaMessage.EnumPeripheralsAnswer.UserPerNr |= 1; 128 FlagUserPer( _DpaMessage.EnumPeripheralsAnswer.UserPer, PNUM_USER + 0 ); 129 _DpaMessage.EnumPeripheralsAnswer.HWPID |= 0x123F; 130 _DpaMessage.EnumPeripheralsAnswer.HWPIDver |= 0xABCD; 131 132 DpaHandleReturnTRUE: 133 return TRUE; 134 } 135 // ------------------------------------------------- 136 // Get information about peripheral 137 else if ( IsDpaPeripheralInfoRequest() ) 138 { 139 if ( _PNUM == PNUM_USER + 0 ) 140 { 141 _DpaMessage.PeripheralInfoAnswer.PerT = PERIPHERAL_TYPE_USER_AREA; 142 _DpaMessage.PeripheralInfoAnswer.PerTE = PERIPHERAL_TYPE_EXTENDED_READ_WRITE; 143 goto DpaHandleReturnTRUE; 144 } 145 146 break; 147 } 148 // ------------------------------------------------- 149 else 150 { 151 // Handle peripheral command 152 if ( _PNUM == PNUM_USER + 0 && _PCMD == 0 ) 153 { 154 // Check for minimum request data length 155 if ( _DpaDataLength < offsetof( TI2Crequest, WriteData ) ) 156 DpaApiReturnPeripheralError( ERROR_DATA_LEN ); 157 158 // Looping variable 159 uns8 loop; 160 // Count of bytes to write to I2C 161 loop = _DpaDataLength - offsetof( TI2Crequest, WriteData ); 162 // Anything to write to I2C? 163 if ( loop != 0 ) 164 { 165 // Start I2C writing 166 _DpaApiI2Cstart( FSR0[offsetof( TI2Crequest, I2Caddress )] ); 167 // Pointer to the data to write 168 FSR1 += offsetof( TI2Crequest, WriteData ); 169 // Now write byte by byte to the I2C 170 do 171 { 172 DpaApiI2Cwrite( *FSR1++ ); 173 } while ( --loop != 0 ); 174 // Stop I2C 175 _DpaApiI2Cstop(); 176 } 177 178 // FSR1 points to the DPA response/request data buffer 179 FSR1 = _DpaMessage.Response.PData; 180 // Number of bytes to read from I2C 181 loop = _DpaDataLength = FSR1[offsetof( TI2Crequest, ReadDataCount )]; 182 // Anything to read from I2C? 183 if ( loop == 0 ) 184 { 185 // No, return with empty DPA response 186 goto DpaHandleReturnTRUE; 187 } 188 189 // Start I2C reading 190 _DpaApiI2Cstart( FSR1[offsetof( TI2Crequest, I2Caddress )] | 1 ); 191 // Read byte by byte from I2C 192 do 193 { 194 // Only very last read byte is not acknowledged 195 setINDF1( DpaApiI2Cread( loop != 1 ) ); 196 FSR1++; 197 } while ( --loop != 0 ); 198 // Stop I2C 199 _DpaApiI2Cstop(); 200 201 goto DpaHandleReturnTRUE; 202 } 203 break; 204 } 205 206 // ------------------------------------------------- 207 case DpaEvent_Init: 208 // Do a one time initialization before main loop starts 209 // Fall through! 210 // ------------------------------------------------- 211 case DpaEvent_AfterSleep: 212 // Called after woken up after sleep 213 // Enable I2C master 214 215 #if defined( TR7xG ) 216 // Do PPS for I2C 217 unlockPPS(); 218 SSP1CLKPPS = 0x13; // RC3 219 SSP1DATPPS = 0x14; // RC4 220 RC3PPS = 0x14; // SCK1/SCL1 221 RC4PPS = 0x15; // SD01/SDA1 222 lockPPS(); 223 #endif 224 225 DpaApiI2Cinit( I2CcomputeFrequency( I2Cfrequency ) ); 226 return Carry; 227 228 // ------------------------------------------------- 229 case DpaEvent_BeforeSleep: 230 // Called before going to sleep 231 // Disable I2C master 232 DpaApiI2Cshutdown(); 233 return Carry; 234 } 235 236 return FALSE; 237 } 238 239 //############################################################################################ 240 // Default Custom DPA Handler header; 2nd include implementing a Code bumper to detect too long code of the Custom DPA Handler (modify the path according to your setup) 241 #include "DPAcustomHandler.h" 242 //############################################################################################