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.18 $ 8 // Date: $Date: 2022/05/13 15:14:48 $ 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 // 15 // ********************************************************************* 16 17 #ifndef __I2C_NFC_LIB__ 18 #define __I2C_NFC_LIB__ 19 20 //############################################################################################ 21 22 // Define to avoid deadlock when the NFC chip is not connect to the I2C bus. Pull-up resistors are required anyway! 23 // #define NFC_UPDATE_IGNORE_IF_MISSING 24 25 // I2C chips addresses 26 #define I2C_ADDRESS_NFC 0b1010.0110 27 #define I2C_ADDRESS_NFC_SYS 0b1010.1110 28 29 // NFC chip ID 30 #ifndef NFC_IC_REF 31 #define NFC_IC_REF 0x24 // = ST25DV04K 32 #endif 33 34 // NFC routines 35 bit NfcIsPresent(); 36 bit NfcUpdateIQRFcode(); 37 bit NfcConfigure(); 38 void NfcWaitIsReady(); 39 40 // NFC low level routines 41 uns8 NfcReadByte( uns16 addr, uns8 device ); 42 void NfcSysWriteByte( uns8 addrLow, uns8 data ); 43 // Reads bytes to bufferRF 44 void NfcReadBytes( uns16 addr, uns8 length, uns8 device ); 45 // Writes bytes from bufferRF 46 void NfcWriteBytes( uns16 addr, uns8 length, uns8 device ); 47 48 #ifndef USE_FSRx 49 void setINDF1inc( uns8 data ); 50 #else 51 #define setINDF1inc( data ) do { *FSR1++ = data; } while(0) 52 #endif 53 54 #if DPA_VERSION_MASTER >= 0x0416 55 #define _i2c_start _DpaApiI2Cstart 56 #define _i2c_stop _DpaApiI2Cstop 57 #define _i2c_read _DpaApiI2Cread 58 #define _i2c_write _DpaApiI2Cwrite 59 #define _i2c_waitForIdle _DpaApiI2CwaitForIdle 60 #define _i2c_shutdown _DpaApiI2Cshutdown 61 #else 62 #define _i2c_start i2c_start 63 #define _i2c_stop i2c_stop 64 #define _i2c_read i2c_read 65 #define _i2c_write i2c_write 66 #define _i2c_waitForIdle i2c_waitForIdle 67 #define _i2c_shutdown i2c_shutdown 68 69 #ifndef __I2C_MASTER__ 70 #define __INCLUDE__I2C_MASTER__ 71 #include "lib/I2Cmaster.c" 72 #endif 73 74 #endif 75 76 //############################################################################################ 77 #else 78 79 #pragma library 1 // Compile only used methods 80 81 #ifdef __INCLUDE__I2C_MASTER__ 82 #include "lib/I2Cmaster.c" 83 #endif 84 85 #ifndef USE_FSRx 86 // ############################################################################################ 87 void setINDF1inc( uns8 data @ W ) 88 // ############################################################################################ 89 { 90 #pragma updateBank exit = UserBank_01 91 setINDF1( data ); 92 FSR1++; 93 } 94 #endif 95 96 // ############################################################################################ 97 uns8 NfcCfgByte( uns8 addr @ W ) 98 // ############################################################################################ 99 { 100 skip( addr ); 101 #pragma computedGoto 1 102 return 0xC6; // GPO-generuje impuls pokud dojde k RF zapisu do EEPROM a RF command EOF to response EOF. 103 return 0x00; // IT_TIME-delka pulsu GPO 301us - (0x00 * 37.5us) 104 return 0x01; // EH_MODE-energy harvesting 0x01 na vyzadani 105 return 0x00; // RF_MNGT-RF komunikace povolena 106 return 0x0C; // RFA1SS-Area1 bez hesla a povoleno pouze RF cteni, RF zapis je zakazany (tam prave ulozim IQRF code) 107 return 0x03; // ENDA1-Area1 adresa 0 až 127B 108 return 0x06; // RFA2SS-Area2 RF cteni bez hesla a RF zapis s heslem RF_PWD1 (zde je mozne zapsat pouze pomoci RF hesla) 109 return 0x07; // ENDA2-Area2 adresa 128 až 255B 110 return 0x00; // RFA3SS-Area3 RF cteni/RF zapis bez hesla 111 return 0x0B; // ENDA3-Area3 adresa 256 až 383B, zbytek je Area4 384 až 512B 112 return 0x00; // RFA4SS-Area4 RF cteni/RF zapis bez hesla 113 return 0x00; // I2CSS-I2C pristup do pameti bez hesla 114 #pragma computedGoto 0 115 } 116 117 //############################################################################################ 118 void nfcConfigureInternal() 119 //############################################################################################ 120 { 121 // Enter I2C password (8x zero) 122 clearBufferRF(); 123 // I2C password validation code between 2 repeated passwords 124 bufferRF[8] = 0x09; 125 // Write password (password+0x90+password) 126 NfcWriteBytes( 0x0900, 8 + 1 + 8, I2C_ADDRESS_NFC_SYS ); 127 128 // Check the password was correct (I2C_SSO_Dyn register) 129 if ( NfcReadByte( 0x2004, I2C_ADDRESS_NFC ) != 1 ) 130 { 131 _NfcError: 132 // No, pulse both LEDs 133 userReg0 = 0; 134 do 135 { 136 clrwdt(); 137 pulseLEDR(); 138 pulseLEDG(); 139 waitDelay( 20 ); 140 } while ( --userReg0 != 0 ); 141 return; 142 } 143 144 // Now configure NFC 145 uns8 addr = 0; // System configuration memory address 146 do { 147 uns8 cfgByte = NfcCfgByte( addr ); 148 NfcSysWriteByte( addr, cfgByte ); 149 // Check the configuration was written 150 if ( NfcReadByte( addr, I2C_ADDRESS_NFC_SYS ) != cfgByte ) 151 goto _NfcError; 152 } while ( ++addr != ( 0x0B /* I2CSS-I2C register */ + 1 ) ); 153 } 154 155 //############################################################################################ 156 bit NfcIsPresent() 157 //############################################################################################ 158 { 159 return NfcReadByte( 0x0017 /* IC_REF */, I2C_ADDRESS_NFC_SYS ) == NFC_IC_REF; 160 } 161 162 //############################################################################################ 163 bit NfcConfigure() 164 //############################################################################################ 165 { 166 #pragma updateBank exit = UserBank_01 167 168 #ifdef NFC_UPDATE_IGNORE_IF_MISSING 169 if ( !NfcIsPresent() ) 170 return Carry; 171 #endif 172 173 nfcConfigureInternal(); 174 175 return TRUE; 176 } 177 178 //############################################################################################ 179 bit NfcUpdateIQRFcode() 180 //############################################################################################ 181 { 182 #ifdef NFC_UPDATE_IGNORE_IF_MISSING 183 if ( !NfcIsPresent() ) 184 return Carry; 185 #endif 186 187 // 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 188 uns8 addr = 1 + sizeof( ModuleInfo.MID ); 189 // My MID address to the FSR1 190 #if &ModuleInfo.MID[0] == &bufferINFO[0] 191 moduleInfo(); 192 setFSR1( _FSR_INFO ); 193 #else 194 #error Cannot optimize FSR to MID address 195 #endif 196 do 197 { 198 // MID matches? 199 if ( NfcReadByte( --addr, I2C_ADDRESS_NFC ) != *FSR1 ) 200 { 201 // No, configure NFC and write IQRF Code 202 nfcConfigureInternal(); 203 204 // Writes IQRF Code to the EEPROM to the address 0, prepare it at bufferRF 205 206 // Prepare MID reversed, i.e. MSB first 207 setFSR01( _FSR_INFO, _FSR_RF ); 208 FSR0 += offsetof( TModuleInfo, MID ) + sizeof( ModuleInfo.MID ); 209 // Example: 0x15 ,0x81,0x11,0x2f,0x0e 210 setINDF1inc( 0x15 ); // Nop tag + MID tag 211 uns8 loop = sizeof( ModuleInfo.MID ); 212 do { 213 setINDF1inc( *--FSR0 ); 214 } while ( --loop != 0 ); 215 216 // Prepare IBK 217 memoryOffsetFrom |= 16; 218 moduleInfo(); // FSR0 = BUFFER_INFO = IBK 219 setFSR01( _FSR_INFO, _FSR_RF ); 220 FSR1 += 1 + sizeof( ModuleInfo.MID ); 221 // Example: 0x25 ,0xb6,0x03,0x3e,0x8f,0xb0,0x8c,0x9b,0xd1,0x74,0xa1,0x9f,0xc0,0x91,0xb8,0xb9,0xbf 222 setINDF1inc( 0x25 ); // Nop tag + IBK tag 223 loop = 16; // IBK size 224 do { 225 setINDF1inc( *FSR0++ ); 226 } while ( --loop != 0 ); 227 228 // Prepare HWPID 229 // Example: 0x35 ,0x50,0x02 230 setINDF1inc( 0x35 ); // Nop tag + HWPID tag 231 setINDF1inc( _HWPID_ >> 8 ); 232 setINDF1inc( _HWPID_ & 0xFF ); 233 234 // End tag 235 setINDF1inc( 0 ); 236 237 // Write prepared IQRF Code to NFC EEPROM at address 0 238 NfcWriteBytes( 0, 1 + sizeof( ModuleInfo.MID ) + 1 + 16 + 1 + sizeof( _HWPID ) + 1, I2C_ADDRESS_NFC ); 239 240 break; 241 } 242 243 // Note: *FSR1++ cannot be used in the "if" condition above, because CC5X cannot generate code 244 FSR1++; 245 } while ( addr != 1 ); 246 247 return TRUE; 248 } 249 250 //############################################################################################ 251 void NfcWaitIsReady() 252 //############################################################################################ 253 { 254 _i2c_stop(); 255 do 256 { 257 _i2c_start( I2C_ADDRESS_NFC ); 258 _i2c_waitForIdle(); 259 #ifdef TR7xG 260 } while ( SSP1CON2.6 /*ACKSTAT*/ ); 261 #else 262 } while ( ACKSTAT ); 263 #endif 264 _i2c_stop(); 265 } 266 267 //############################################################################################ 268 void NfcSysWriteByte( uns8 addrLow, uns8 data ) 269 //############################################################################################ 270 { 271 _i2c_start( I2C_ADDRESS_NFC_SYS ); 272 _i2c_write( 0 ); 273 _i2c_write( addrLow ); 274 _i2c_write( data ); 275 NfcWaitIsReady(); 276 } 277 278 //############################################################################################ 279 uns8 NfcReadByte( uns16 addr, uns8 device ) 280 //############################################################################################ 281 { 282 #pragma updateBank exit = UserBank_01 283 _i2c_start( device ); 284 _i2c_write( addr.high8 ); 285 _i2c_write( addr.low8 ); 286 _i2c_start( device | 1 ); 287 uns8 data = _i2c_read( FALSE ); 288 _i2c_stop(); 289 return data; 290 } 291 292 //############################################################################################ 293 void NfcWriteBytes( uns16 addr, uns8 length, uns8 device @ W ) 294 //############################################################################################ 295 { 296 _i2c_start( device ); 297 _i2c_write( addr.high8 ); 298 _i2c_write( addr.low8 ); 299 setFSR1( _FSR_RF ); 300 do { 301 _i2c_write( *FSR1++ ); 302 } while ( --length != 0 ); 303 NfcWaitIsReady(); 304 } 305 306 //############################################################################################ 307 void NfcReadBytes( uns16 addr, uns8 length, uns8 device ) 308 //############################################################################################ 309 { 310 _i2c_start( device ); 311 _i2c_write( addr.high8 ); 312 _i2c_write( addr.low8 ); 313 _i2c_start( device | 1 ); 314 setFSR1( _FSR_RF ); 315 do { 316 setINDF1inc( _i2c_read( length != 1 ) ); 317 } while ( --length != 0 ); 318 _i2c_stop(); 319 } 320 //############################################################################################ 321 322 #pragma library 0 323 324 #endif 325 //############################################################################################