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