1 // ********************************************************************************* 2 // Custom DPA Handler code example - User peripheral implementation - I2C master * 3 // ********************************************************************************* 4 // Copyright (c) IQRF Tech s.r.o. 5 // 6 // File: $RCSfile: CustomDpaHandler-UserPeripheral-I2Cmaster.c,v $ 7 // Version: $Revision: 1.6 $ 8 // Date: $Date: 2020/02/20 17:18:58 $ 9 // 10 // Revision history: 11 // 2020/01/02 Release for DPA 4.11 12 // 2019/10/09 Release for DPA 4.10 13 // 14 // ********************************************************************* 15 16 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 17 18 // This example implements Master I2C as a user peripheral 19 20 // Default IQRF include (modify the path according to your setup) 21 #include "IQRF.h" 22 23 // Default DPA header (modify the path according to your setup) 24 #include "DPA.h" 25 // Default Custom DPA Handler header (modify the path according to your setup) 26 #include "DPAcustomHandler.h" 27 // I2C Master library 28 #include "lib/I2Cmaster.c" 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 ) 153 { 154 // Check DPA command value 155 if ( _PCMD != 0 ) 156 DpaApiReturnPeripheralError( ERROR_PCMD ); 157 158 // Check for minimum request data length 159 if ( _DpaDataLength < offsetof( TI2Crequest, WriteData ) ) 160 DpaApiReturnPeripheralError( ERROR_DATA_LEN ); 161 162 // Looping variable 163 uns8 loop; 164 // Count of bytes to write to I2C 165 loop = _DpaDataLength - offsetof( TI2Crequest, WriteData ); 166 // Anything to write to I2C? 167 if ( loop != 0 ) 168 { 169 // Start I2C writing 170 i2c_start( FSR0[offsetof( TI2Crequest, I2Caddress )] ); 171 // Pointer to the data to write 172 FSR1 += offsetof( TI2Crequest, WriteData ); 173 // Now write byte by byte to the I2C 174 do 175 { 176 i2c_write( *FSR1++ ); 177 } while ( --loop != 0 ); 178 // Stop I2C 179 i2c_stop(); 180 } 181 182 // FSR1 points to the DPA response/request data buffer 183 FSR1 = _DpaMessage.Response.PData; 184 // Number of bytes to read from I2C 185 loop = _DpaDataLength = FSR1[offsetof( TI2Crequest, ReadDataCount )]; 186 // Anything to read from I2C? 187 if ( loop == 0 ) 188 { 189 // No, return with empty DPA response 190 goto DpaHandleReturnTRUE; 191 } 192 193 // Start I2C reading 194 i2c_start( FSR1[offsetof( TI2Crequest, I2Caddress )] | 1 ); 195 // Read byte by byte from I2C 196 do 197 { 198 // Only very last read byte is not acknowledged 199 setINDF1( i2c_read( loop != 1 ) ); 200 FSR1++; 201 } while ( --loop != 0 ); 202 // Stop I2C 203 i2c_stop(); 204 205 goto DpaHandleReturnTRUE; 206 } 207 } 208 209 // ------------------------------------------------- 210 case DpaEvent_Init: 211 // Do a one time initialization before main loop starts 212 // Fall through! 213 // ------------------------------------------------- 214 case DpaEvent_AfterSleep: 215 // Called after woken up after sleep 216 // Enable I2C master 217 i2c_init(); 218 return Carry; 219 220 // ------------------------------------------------- 221 case DpaEvent_BeforeSleep: 222 // Called before going to sleep 223 // Disable I2C master 224 i2c_shutdown(); 225 return Carry; 226 } 227 228 return FALSE; 229 } 230 231 //############################################################################################ 232 // I2C Master library 233 #include "lib/I2Cmaster.c" 234 // Default Custom DPA Handler header; 2nd include to implement Code bumper to detect too long code of the Custom DPA Handler (modify the path according to your setup) 235 #include "DPAcustomHandler.h" 236 //############################################################################################