1 // ******************************************************************* 2 // NFC Library for Custom DPA Handlers, chip is ST25DV04K * 3 // ******************************************************************* 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: NFC.c,v $ 7 // Version: $Revision: 1.23 $ 8 // Date: $Date: 2024/12/02 17:46:59 $ 9 // 10 // Revision history: 11 // 2024/11/29 Release for DPA 4.3x 12 // 2022/02/24 Release for DPA 4.17 13 // 2021/08/20 Release for DPA 4.16 14 // 2020/01/02 Release for DPA 4.11 15 // 16 // ********************************************************************* 17 18 #ifndef __I2C_NFC_LIB__ 19 #define __I2C_NFC_LIB__ 20 21 //############################################################################################ 22 23 // Define to avoid deadlock when the NFC chip is not connect to the I2C bus. Pull-up resistors are required anyway! 24 // #define NFC_UPDATE_IGNORE_IF_MISSING 25 26 // I2C chips addresses 27 #define I2C_ADDRESS_NFC 0b1010.0110 28 #define I2C_ADDRESS_NFC_SYS 0b1010.1110 29 30 // NFC chip ID 31 #ifndef NFC_IC_REF 32 #define NFC_IC_REF 0x24 // = ST25DV04K 33 #endif 34 35 // NFC routines 36 bit NfcIsPresent(); 37 bit NfcUpdateIQRFcode(); 38 bit NfcConfigure(); 39 void NfcWaitIsReady(); 40 41 // NFC low level routines 42 uns8 NfcReadByte( uns16 addr, uns8 device ); 43 void NfcSysWriteByte( uns8 addrLow, uns8 data ); 44 // Reads bytes to bufferRF 45 void NfcReadBytes( uns16 addr, uns8 length, uns8 device ); 46 // Writes bytes from bufferRF 47 void NfcWriteBytes( uns16 addr, uns8 length, uns8 device ); 48 49 #ifndef USE_FSRx 50 void setINDF1inc( uns8 data ); 51 #else 52 #define setINDF1inc( data ) do { *FSR1++ = data; } while(0) 53 #endif 54 55 #if DPA_VERSION_MASTER >= 0x0416 56 #define _i2c_start _DpaApiI2Cstart 57 #define _i2c_stop _DpaApiI2Cstop 58 #define _i2c_read _DpaApiI2Cread 59 #define _i2c_write _DpaApiI2Cwrite 60 #define _i2c_waitForIdle _DpaApiI2CwaitForIdle 61 #define _i2c_shutdown _DpaApiI2Cshutdown 62 #else 63 #define _i2c_start i2c_start 64 #define _i2c_stop i2c_stop 65 #define _i2c_read i2c_read 66 #define _i2c_write i2c_write 67 #define _i2c_waitForIdle i2c_waitForIdle 68 #define _i2c_shutdown i2c_shutdown 69 70 #ifndef __I2C_MASTER__ 71 #define __INCLUDE__I2C_MASTER__ 72 #include "lib/I2Cmaster.c" 73 #endif 74 75 #endif 76 77 //############################################################################################ 78 #else 79 80 #pragma library 1 // Compile only used methods 81 82 #ifdef __INCLUDE__I2C_MASTER__ 83 #include "lib/I2Cmaster.c" 84 #endif 85 86 #ifndef USE_FSRx 87 // ############################################################################################ 88 void setINDF1inc( uns8 data @ W ) 89 // ############################################################################################ 90 { 91 #pragma updateBank exit = UserBank_01 92 setINDF1( data ); 93 FSR1++; 94 } 95 #endif 96 97 // ############################################################################################ 98 uns8 NfcCfgByte( uns8 addr @ W ) 99 // ############################################################################################ 100 { 101 skip( addr ); 102 #pragma computedGoto 1 103 return 0xC6; // GPO-generuje impuls pokud dojde k RF zapisu do EEPROM a RF command EOF to response EOF. 104 return 0x00; // IT_TIME-delka pulsu GPO 301us - (0x00 * 37.5us) 105 return 0x01; // EH_MODE-energy harvesting 0x01 na vyzadani 106 return 0x00; // RF_MNGT-RF komunikace povolena 107 return 0x0C; // RFA1SS-Area1 bez hesla a povoleno pouze RF cteni, RF zapis je zakazany (tam prave ulozim IQRF code) 108 return 0x03; // ENDA1-Area1 adresa 0 až 127B 109 return 0x06; // RFA2SS-Area2 RF cteni bez hesla a RF zapis s heslem RF_PWD1 (zde je mozne zapsat pouze pomoci RF hesla) 110 return 0x07; // ENDA2-Area2 adresa 128 až 255B 111 return 0x00; // RFA3SS-Area3 RF cteni/RF zapis bez hesla 112 return 0x0B; // ENDA3-Area3 adresa 256 až 383B, zbytek je Area4 384 až 512B 113 return 0x00; // RFA4SS-Area4 RF cteni/RF zapis bez hesla 114 return 0x00; // I2CSS-I2C pristup do pameti bez hesla 115 #pragma computedGoto 0 116 } 117 118 //############################################################################################ 119 void nfcConfigureInternal() 120 //############################################################################################ 121 { 122 // Enter I2C password (8x zero) 123 clearBufferRF(); 124 // I2C password validation code between 2 repeated passwords 125 bufferRF[8] = 0x09; 126 // Write password (password+0x90+password) 127 NfcWriteBytes( 0x0900, 8 + 1 + 8, I2C_ADDRESS_NFC_SYS ); 128 129 // Check the password was correct (I2C_SSO_Dyn register) 130 if ( NfcReadByte( 0x2004, I2C_ADDRESS_NFC ) != 1 ) 131 { 132 _NfcError: 133 // No, pulse both LEDs 134 userReg0 = 0; 135 do 136 { 137 clrwdt(); 138 pulseLEDR(); 139 pulseLEDG(); 140 waitDelay( 20 ); 141 } while ( --userReg0 != 0 ); 142 return; 143 } 144 145 // Now configure NFC 146 uns8 addr = 0; // System configuration memory address 147 do { 148 uns8 cfgByte = NfcCfgByte( addr ); 149 NfcSysWriteByte( addr, cfgByte ); 150 // Check the configuration was written 151 if ( NfcReadByte( addr, I2C_ADDRESS_NFC_SYS ) != cfgByte ) 152 goto _NfcError; 153 } while ( ++addr != ( 0x0B /* I2CSS-I2C register */ + 1 ) ); 154 } 155 156 //############################################################################################ 157 bit NfcIsPresent() 158 //############################################################################################ 159 { 160 return NfcReadByte( 0x0017 /* IC_REF */, I2C_ADDRESS_NFC_SYS ) == NFC_IC_REF; 161 } 162 163 //############################################################################################ 164 bit NfcConfigure() 165 //############################################################################################ 166 { 167 #pragma updateBank exit = UserBank_01 168 169 #ifdef NFC_UPDATE_IGNORE_IF_MISSING 170 if ( !NfcIsPresent() ) 171 return Carry; 172 #endif 173 174 nfcConfigureInternal(); 175 return TRUE; 176 } 177 178 //############################################################################################ 179 void moduleInfoAndSetFSRs () 180 //############################################################################################ 181 { 182 moduleInfo(); 183 setFSR01( _FSR_INFO, _FSR_RF ); 184 } 185 186 //############################################################################################ 187 bit NfcUpdateIQRFcode() 188 //############################################################################################ 189 { 190 #if _HWPID_ > 0xFfFf 191 #error _HWPID_ > 0xFfFf 192 #endif 193 194 #if _HWPIDver_ > 0xFfFf 195 #error _HWPIDver_ > 0xFfFf 196 #endif 197 198 #ifdef NFC_UPDATE_IGNORE_IF_MISSING 199 if ( !NfcIsPresent() ) 200 return Carry; 201 #endif 202 203 // ---------------------------------------------------- 204 #if !defined( TR7xG ) && !defined( NFC_FULL_IQRF_Code ) 205 // Old "D" style, when only MID is checked 206 #define IQRFcodeLength ( 1/*Nop+tag*/ + sizeof( ModuleInfo.MID ) + 1/*Nop+tag*/ + 16/*IBK*/ + 1/*Nop+tag*/ + sizeof( uns16 )/*HWPID*/ + 1/*End*/ ) 207 208 // Check MID for the valid IQRF Code at the NFC EEPROM, read user area from address 1 where the reversed (Big Endian) MID is supposed to be 209 uns8 addr = 1 + sizeof( ModuleInfo.MID ); 210 // My MID address to the FSR1 211 #if &ModuleInfo.MID[0] == &bufferINFO[0] 212 moduleInfoAndSetFSRs(); 213 #else 214 #error Cannot optimize FSR to MID address 215 #endif 216 do 217 { 218 // MID matches? 219 if ( NfcReadByte( --addr, I2C_ADDRESS_NFC ) != *FSR0 ) 220 { 221 // No, configure NFC and write IQRF Code 222 nfcConfigureInternal(); 223 224 // Writes IQRF Code to the EEPROM to the address 0, prepare it at bufferRF 225 226 // Prepare MID reversed, i.e. MSB first 227 moduleInfoAndSetFSRs(); 228 FSR0 += offsetof( TModuleInfo, MID ) + sizeof( ModuleInfo.MID ); 229 // Example: 0x15 ,0x81,0x11,0x2f,0x0e 230 setINDF1inc( 0x15 ); // Nop tag + MID tag 231 uns8 loop = sizeof( ModuleInfo.MID ); 232 do { 233 setINDF1inc( *--FSR0 ); 234 } while ( --loop != 0 ); 235 236 // Prepare IBK 237 memoryOffsetFrom |= 16; 238 moduleInfoAndSetFSRs(); 239 FSR1 += 1 + sizeof( ModuleInfo.MID ); 240 // Example: 0x25 ,0xb6,0x03,0x3e,0x8f,0xb0,0x8c,0x9b,0xd1,0x74,0xa1,0x9f,0xc0,0x91,0xb8,0xb9,0xbf 241 setINDF1inc( 0x25 ); // Nop tag + IBK tag 242 loop |= 16; // IBK size 243 do { 244 setINDF1inc( *FSR0++ ); 245 } while ( --loop != 0 ); 246 247 // Prepare HWPID 248 // Example: 0x35 ,0x50,0x02 249 setINDF1inc( 0x35 ); // Nop tag + HWPID tag 250 setINDF1inc( _HWPID_ >> 8 ); 251 setINDF1inc( _HWPID_ & 0xFF ); 252 253 // End tag 254 setINDF1inc( 0 ); 255 256 // Write prepared IQRF Code to NFC EEPROM at address 0 257 NfcWriteBytes( 0, IQRFcodeLength, I2C_ADDRESS_NFC ); 258 259 break; 260 } 261 262 // Note: *FSR0++ cannot be used in the "if" condition above, because CC5X cannot generate code 263 FSR0++; 264 } while ( addr != 1 ); 265 266 #else 267 // ---------------------------------------------------- 268 // non-D line, full IQRF Code is compared, construct IQRF Code at bufferRF 269 #define IQRFcodeLength ( 1/*tags HWPID+MID*/ + sizeof( uns16 )/*HWPID*/ + sizeof( ModuleInfo.MID ) + 1/*tags HWPIDver+IBK*/ + sizeof( uns16 )/*HWPIDver*/ + 16/*IBK*/ + 1/*tags Nop+LogicalAddress*/ + sizeof( ntwADDR )/*LogicalAddress*/ + 1/*End*/ ) 270 271 moduleInfoAndSetFSRs(); 272 273 //// Prepare HWPID 274 // Example: HwpId:ABCD => 0xB3, 0xDA, 0x1C 275 setINDF1inc( ( ( _HWPID_ >> 4 ) & 0xF0 ) | 0x03 ); // HWPID.8-11 + HWPID tag 276 setINDF1inc( ( ( (uns8)_HWPID_ << 4 ) & 0xF0 ) | ( _HWPID_ >> 12 ) ); // HWPID.0-3 + HWPID.12-15 277 setINDF1inc( 0x10 | ( ( _HWPID_ >> 4 ) & 0x0F ) ); // MID tag + HWPID.4-7 278 279 //// Prepare MID reversed, i.e. MSB first 280 FSR0 += offsetof( TModuleInfo, MID ) + sizeof( ModuleInfo.MID ); 281 uns8 loop = sizeof( ModuleInfo.MID ); 282 do { 283 setINDF1inc( *--FSR0 ); 284 } while ( --loop != 0 ); 285 286 //// Prepare HWPIDver 287 // Example: HwpIdver:ABCDE => 0xB8, 0xDA, 0x2C 288 setINDF1inc( ( ( _HWPIDver_ >> 4 ) & 0xF0 ) | 0x08 ); // HWPIDver.8-11 + HWPIDver tag 289 setINDF1inc( ( ( (uns8)_HWPIDver_ << 4 ) & 0xF0 ) | ( _HWPIDver_ >> 12 ) ); // HWPIDver.0-3 + HWPIDver.12-15 290 setINDF1inc( 0x20 | ( ( _HWPIDver_ >> 4 ) & 0x0F ) ); // IBK tag + HWPIDver.4-7 291 292 //// Prepare IBK 293 memoryOffsetFrom |= 16; 294 moduleInfoAndSetFSRs(); 295 FSR1 += 1/*tags HWPID+MID*/ + sizeof( uns16 )/*HWPID*/ + sizeof( ModuleInfo.MID ) + 1/*tags HWPIDver+IBK*/ + sizeof( uns16 )/*HWPIDver*/; 296 loop |= 16; // IBK size (loop was 0) 297 do { 298 setINDF1inc( *FSR0++ ); 299 } while ( --loop != 0 ); 300 301 //// Prepare logical address 302 setINDF1inc( 0x45 ); // Nop tag + Logical address tag 303 W = 0; // Coordinator address 304 // Not Coordinator( _networkingMode == 1 && _networkTwo == 0 ) ? 305 if ( _networkingMode != 1 || _networkTwo != 0 ) // Note: must not modify W 306 { 307 Carry = amIBonded(); 308 W = ntwADDR; // Bonded value, Note: must not modify Carry 309 if ( !Carry ) // Note: must not modify W 310 W = 0xFF; // Not bonded value 311 } 312 setINDF1inc( W ); 313 314 //// End tag 315 setINDF1inc( 0 ); 316 // FSR1 is behind the end of generated IQRF Code 317 318 // loop used both as counter and NFC address 319 loop = IQRFcodeLength; 320 do 321 { 322 FSR1--; 323 // IQRF Code matches byte by byte? 324 if ( NfcReadByte( --loop, I2C_ADDRESS_NFC ) != *FSR1 ) 325 { 326 // No, set IQRF Code aside 327 copyBufferRF2INFO(); 328 // Configure NFC chip 329 nfcConfigureInternal(); 330 // Get IQRF Code back 331 copyBufferINFO2RF(); 332 // Write prepared IQRF Code to NFC EEPROM at address 0 333 NfcWriteBytes( 0, IQRFcodeLength, I2C_ADDRESS_NFC ); 334 break; 335 } 336 } while ( loop != 0 ); 337 #endif 338 // ---------------------------------------------------- 339 340 #undef IQRFcodeLength 341 return TRUE; 342 } 343 344 //############################################################################################ 345 void NfcWaitIsReady() 346 //############################################################################################ 347 { 348 _i2c_stop(); 349 do 350 { 351 _i2c_start( I2C_ADDRESS_NFC ); 352 _i2c_waitForIdle(); 353 #if defined( TR7xG ) || defined( TR8xG ) 354 } while ( SSP1CON2.6 /*ACKSTAT*/ ); 355 #else 356 } while ( ACKSTAT ); 357 #endif 358 _i2c_stop(); 359 } 360 361 //############################################################################################ 362 void NfcSysWriteByte( uns8 addrLow, uns8 data ) 363 //############################################################################################ 364 { 365 _i2c_start( I2C_ADDRESS_NFC_SYS ); 366 _i2c_write( 0 ); 367 _i2c_write( addrLow ); 368 _i2c_write( data ); 369 NfcWaitIsReady(); 370 } 371 372 //############################################################################################ 373 uns8 NfcReadByte( uns16 addr, uns8 device ) 374 //############################################################################################ 375 { 376 #pragma updateBank exit = UserBank_01 377 _i2c_start( device ); 378 _i2c_write( addr.high8 ); 379 _i2c_write( addr.low8 ); 380 _i2c_start( device | 1 ); 381 uns8 data = _i2c_read( FALSE ); 382 _i2c_stop(); 383 return data; 384 } 385 386 //############################################################################################ 387 void NfcWriteBytes( uns16 addr, uns8 length, uns8 device @ W ) 388 //############################################################################################ 389 { 390 _i2c_start( device ); 391 _i2c_write( addr.high8 ); 392 _i2c_write( addr.low8 ); 393 setFSR1( _FSR_RF ); 394 do { 395 _i2c_write( *FSR1++ ); 396 } while ( --length != 0 ); 397 NfcWaitIsReady(); 398 } 399 400 //############################################################################################ 401 void NfcReadBytes( uns16 addr, uns8 length, uns8 device ) 402 //############################################################################################ 403 { 404 _i2c_start( device ); 405 _i2c_write( addr.high8 ); 406 _i2c_write( addr.low8 ); 407 _i2c_start( device | 1 ); 408 setFSR1( _FSR_RF ); 409 do { 410 setINDF1inc( _i2c_read( length != 1 ) ); 411 } while ( --length != 0 ); 412 _i2c_stop(); 413 } 414 //############################################################################################ 415 416 #pragma library 0 417 418 #endif 419 //############################################################################################