1 // *********************************************************************************************************** 2 // Custom DPA Handler code example - OTK - Node * 3 // *********************************************************************************************************** 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: CustomDpaHandler-OTK-Node.c,v $ 7 // Version: $Revision: 1.28 $ 8 // Date: $Date: 2023/03/07 08:03:13 $ 9 // 10 // Revision history: 11 // 2023/03/07 Release for DPA 4.30 12 // 2022/10/05 Release for DPA 4.18 13 // 2022/02/24 Release for DPA 4.17 14 // 2021/08/20 Release for DPA 4.16 15 // 16 // ********************************************************************* 17 18 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 19 20 /* 21 This handler allows Node prebonding by NFC Reader "IQD-NFC-01" using OTK (One Time Key) stored at NFC EEPROM of the Node. 22 New OTK is generated upon [1] the restart/reset or when [2] there is an RF NFC activity detected. 23 The Current OTK is stored to the designated IQRF OS buffer to allow SmartConnect prebonding from the NFC Reader device. 24 Default DPA LED indication is unchanged. 25 */ 26 27 // NFC power pin definition 28 #define NFC_POWER_TRIS TRISC.2 29 #define NFC_POWER_LAT LATC.2 30 31 // Default IQRF include (modify the path according to your setup) 32 #include "IQRF.h" 33 34 // Default DPA header (modify the path according to your setup) 35 #include "DPA.h" 36 // Default Custom DPA Handler header (modify the path according to your setup) 37 #include "DPAcustomHandler.h" 38 // Libraries 39 #include "lib/NFC.c" 40 41 //############################################################################################ 42 43 // This HWPID 44 #define _HWPID_ 0x888F 45 #define _HWPIDver_ 0x0001 46 47 // I2C SCL frequency [Hz] 48 #define I2Cfrequency 100000 49 // Bonding button timeout [ms] before [N] goes to sleep 50 #define BONDING_BUTTON_TIMEOUT ( 5 * 1000 ) 51 52 // OTK address at NFC EEPROM 53 #define OTK_NFC_EE_ADDRESS 44 54 // OTK Length 55 #define OTK_Length 16 56 57 // Generates new OTK at NFC EEPROM and loads the old one to the IQRF OS place 58 void NewOtk(); 59 // Switches NFC on 60 void NFCon(); 61 // Switches NFC off 62 void NFCoff(); 63 // I2C initialization 64 void I2Cinit(); 65 66 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location! 67 //############################################################################################ 68 bit CustomDpaHandler() 69 //############################################################################################ 70 { 71 #pragma updateBank default=UserBank_01 72 73 // Handler presence mark 74 clrwdt(); 75 76 // Detect DPA event to handle 77 switch ( GetDpaEvent() ) 78 { 79 // ------------------------------------------------- 80 case DpaEvent_Interrupt: 81 // Do an extra quick background interrupt work 82 return Carry; 83 84 // ------------------------------------------------- 85 case DpaEvent_Reset: 86 // Do a one time initialization before main loop starts 87 { 88 static bit wasReset; 89 // It this a very first reset event? 90 if ( !wasReset ) 91 { 92 // Reset the flag 93 wasReset = TRUE; 94 // Start I2C 95 I2Cinit(); 96 // Switch NFC on 97 NFCon(); 98 // Update IQRF Code and configure NFC EEPROM if needed 99 if ( !amIBonded() ) 100 { 101 // Note: To save the code the next call can be omitted supposed it was called at least once, for example during product manufacturing/testing 102 NfcUpdateIQRFcode(); 103 // Or just the plain NFC configuration in case IQRF Code is not required for SmartConnect bonding 104 //NfcConfigure(); 105 106 // Generate fresh new OTK at NFC EEPROM and make sure the OS buffer does not contain even the last one 107 NewOtk(); 108 NewOtk(); 109 } 110 } 111 112 break; 113 } 114 115 // ------------------------------------------------- 116 case DpaEvent_DpaRequest: 117 // Called to interpret DPA request for peripherals 118 119 if ( IsDpaEnumPeripheralsRequest() ) 120 { 121 // ------------------------------------------------- 122 // Peripheral enumeration 123 _DpaMessage.EnumPeripheralsAnswer.HWPID |= _HWPID_; 124 _DpaMessage.EnumPeripheralsAnswer.HWPIDver |= _HWPIDver_; 125 return TRUE; 126 } 127 break; 128 129 // ------------------------------------------------- 130 case DpaEvent_Init: 131 // Do a one time initialization before main loop starts 132 133 // Optional Bonding/Unbonding is over so switch off NFC just in case it was on because of previous bonding 134 _NfcAndI2Coff: 135 NFCoff(); 136 // We do not need I2C any more (in this example) 137 _DpaApiI2Cshutdown(); 138 break; 139 140 // ------------------------------------------------- 141 #ifdef DpaEvent_BondingButton 142 case DpaEvent_BondingButton: 143 // Called to allow a bonding button customization 144 #else 145 #ifdef DpaEvent_MenuActivated 146 // ------------------------------------------------- 147 case DpaEvent_MenuActivated: 148 // Called to allow a menu customization 149 if ( userReg1 == DMENU_ReadyToBond ) 150 #else 151 #error DpaEvent_BondingButton or DpaEvent_MenuActivated must be defined 152 #endif 153 #endif 154 155 { 156 // Keep the NFC and I2C on during the bonding in order to keep value of IT_STS_Dyn _volatile_ register in the NFC chip 157 I2Cinit(); 158 NFCon(); 159 160 // Check, if there was an RF NFC activity detected by checking IT_STS_Dyn.RF_ACTIVITY 161 if ( NfcReadByte( 0x2005 /* IT_STS_Dyn */, I2C_ADDRESS_NFC ) & 0x02 /* b1=RF_ACTIVITY */ ) 162 { 163 // Yes there was an RF activity, hopefully OTK was read from the NFC EEPROM 164 // Generate new OTK in the NFC EEPROM 165 NewOtk(); 166 // Restart the full bonding timeout to keep the device up and ready for the prebonding from the NFC reader 167 goto _RestartBondingTimeout; 168 } 169 170 // We can inspect BondingSleepCountdown value to detect important moments 171 switch ( BondingSleepCountdown ) 172 { 173 // Was the BondingSleepCountdown just initiated? 174 case 0: 175 _RestartBondingTimeout: 176 // Yes, reset the timeout variable to BONDING_BUTTON_TIMEOUT 177 BondingSleepCountdown = BONDING_BUTTON_TIMEOUT / BONDING_SLEEP_COUNTDOWN_UNIT; 178 break; 179 180 // Are we very probably just about one decrement away to go to sleep because of bonding timeout value is close to 0? 181 case 0 + 1: 182 // Yes, switch off NFC and I2C in order to minimize power consumption during the sleep 183 goto _NfcAndI2Coff; 184 } 185 } 186 break; 187 } 188 189 return FALSE; 190 } 191 #pragma updateBank 1 192 193 //############################################################################################ 194 void NewOtk() 195 //############################################################################################ 196 { 197 // Read current OTK from NFC EEPROM to bufferRF 198 NfcReadBytes( OTK_NFC_EE_ADDRESS, OTK_Length, I2C_ADDRESS_NFC ); 199 // Set OTK to IQRF OS to allow prebonding via SmartConnect from NFC Reader device 200 DpaApiSetOTK(); 201 // Modify OTK bytes randomly 202 bufferRF[0] += Random.high8; 203 bufferRF[1] += Random.low8; 204 bufferRF[2] += TMR1L; 205 // "Encrypt" i.e. generate new OTK@RF using UserKey 206 // !!! Set your own UserKey from a default one in advance 207 decryptBufferRF( OTK_Length / 16 ); 208 // Store new OTK to NFC EE 209 NfcWriteBytes( OTK_NFC_EE_ADDRESS, OTK_Length, I2C_ADDRESS_NFC ); 210 } 211 212 //############################################################################################ 213 void NFCon() 214 //############################################################################################ 215 { 216 // Set the output pin to power NFC 217 NFC_POWER_TRIS = 0; 218 // NFC is on? 219 if ( NFC_POWER_LAT ) 220 return; 221 222 // No, switch it on 223 NFC_POWER_LAT = 1; 224 // Do a short power-up delay 225 waitMS( 1 ); 226 } 227 228 //############################################################################################ 229 void NFCoff() 230 //############################################################################################ 231 { 232 NFC_POWER_LAT = 0; 233 } 234 235 //############################################################################################ 236 void I2Cinit() 237 //############################################################################################ 238 { 239 #if defined( TR7xG ) 240 // Do PPS for I2C 241 unlockPPS(); 242 SSP1CLKPPS = 0x13; // RC3 243 SSP1DATPPS = 0x14; // RC4 244 RC3PPS = 0x14; // SCK1/SCL1 245 RC4PPS = 0x15; // SD01/SDA1 246 RC5PPS = 0x15; // SDO1/SDA1 247 lockPPS(); 248 #endif 249 250 I2Ctimeout = 0xFF; 251 _DpaApiI2Cinit( I2CcomputeFrequency( I2Cfrequency ) ); 252 } 253 254 //############################################################################################ 255 // Libraries 256 #include "lib/NFC.c" 257 // 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) 258 #include "DPAcustomHandler.h" 259 //############################################################################################