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.20 $ 8 // Date: $Date: 2023/01/03 08:29:20 $ 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 return TRUE; 175 } 176 177 //############################################################################################ 178 bit NfcUpdateIQRFcode() 179 //############################################################################################ 180 { 181 #ifdef NFC_UPDATE_IGNORE_IF_MISSING 182 if ( !NfcIsPresent() ) 183 return Carry; 184 #endif 185 186 // 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 187 uns8 addr = 1 + sizeof( ModuleInfo.MID ); 188 // My MID address to the FSR1 189 #if &ModuleInfo.MID[0] == &bufferINFO[0] 190 moduleInfo(); 191 setFSR1( _FSR_INFO ); 192 #else 193 #error Cannot optimize FSR to MID address 194 #endif 195 do 196 { 197 // MID matches? 198 if ( NfcReadByte( --addr, I2C_ADDRESS_NFC ) != *FSR1 ) 199 { 200 // No, configure NFC and write IQRF Code 201 nfcConfigureInternal(); 202 203 // Writes IQRF Code to the EEPROM to the address 0, prepare it at bufferRF 204 205 // Prepare MID reversed, i.e. MSB first 206 setFSR01( _FSR_INFO, _FSR_RF ); 207 FSR0 += offsetof( TModuleInfo, MID ) + sizeof( ModuleInfo.MID ); 208 // Example: 0x15 ,0x81,0x11,0x2f,0x0e 209 setINDF1inc( 0x15 ); // Nop tag + MID tag 210 uns8 loop = sizeof( ModuleInfo.MID ); 211 do { 212 setINDF1inc( *--FSR0 ); 213 } while ( --loop != 0 ); 214 215 // Prepare IBK 216 memoryOffsetFrom |= 16; 217 moduleInfo(); // FSR0 = BUFFER_INFO = IBK 218 setFSR01( _FSR_INFO, _FSR_RF ); 219 FSR1 += 1 + sizeof( ModuleInfo.MID ); 220 // Example: 0x25 ,0xb6,0x03,0x3e,0x8f,0xb0,0x8c,0x9b,0xd1,0x74,0xa1,0x9f,0xc0,0x91,0xb8,0xb9,0xbf 221 setINDF1inc( 0x25 ); // Nop tag + IBK tag 222 loop = 16; // IBK size 223 do { 224 setINDF1inc( *FSR0++ ); 225 } while ( --loop != 0 ); 226 227 // Prepare HWPID 228 // Example: 0x35 ,0x50,0x02 229 setINDF1inc( 0x35 ); // Nop tag + HWPID tag 230 setINDF1inc( _HWPID_ >> 8 ); 231 setINDF1inc( _HWPID_ & 0xFF ); 232 233 // End tag 234 setINDF1inc( 0 ); 235 236 // Write prepared IQRF Code to NFC EEPROM at address 0 237 NfcWriteBytes( 0, 1 + sizeof( ModuleInfo.MID ) + 1 + 16 + 1 + sizeof( _HWPID ) + 1, I2C_ADDRESS_NFC ); 238 239 break; 240 } 241 242 // Note: *FSR1++ cannot be used in the "if" condition above, because CC5X cannot generate code 243 FSR1++; 244 } while ( addr != 1 ); 245 246 return TRUE; 247 } 248 249 //############################################################################################ 250 void NfcWaitIsReady() 251 //############################################################################################ 252 { 253 _i2c_stop(); 254 do 255 { 256 _i2c_start( I2C_ADDRESS_NFC ); 257 _i2c_waitForIdle(); 258 #if defined( TR7xG ) || defined( TR8xG ) 259 } while ( SSP1CON2.6 /*ACKSTAT*/ ); 260 #else 261 } while ( ACKSTAT ); 262 #endif 263 _i2c_stop(); 264 } 265 266 //############################################################################################ 267 void NfcSysWriteByte( uns8 addrLow, uns8 data ) 268 //############################################################################################ 269 { 270 _i2c_start( I2C_ADDRESS_NFC_SYS ); 271 _i2c_write( 0 ); 272 _i2c_write( addrLow ); 273 _i2c_write( data ); 274 NfcWaitIsReady(); 275 } 276 277 //############################################################################################ 278 uns8 NfcReadByte( uns16 addr, uns8 device ) 279 //############################################################################################ 280 { 281 #pragma updateBank exit = UserBank_01 282 _i2c_start( device ); 283 _i2c_write( addr.high8 ); 284 _i2c_write( addr.low8 ); 285 _i2c_start( device | 1 ); 286 uns8 data = _i2c_read( FALSE ); 287 _i2c_stop(); 288 return data; 289 } 290 291 //############################################################################################ 292 void NfcWriteBytes( uns16 addr, uns8 length, uns8 device @ W ) 293 //############################################################################################ 294 { 295 _i2c_start( device ); 296 _i2c_write( addr.high8 ); 297 _i2c_write( addr.low8 ); 298 setFSR1( _FSR_RF ); 299 do { 300 _i2c_write( *FSR1++ ); 301 } while ( --length != 0 ); 302 NfcWaitIsReady(); 303 } 304 305 //############################################################################################ 306 void NfcReadBytes( uns16 addr, uns8 length, uns8 device ) 307 //############################################################################################ 308 { 309 _i2c_start( device ); 310 _i2c_write( addr.high8 ); 311 _i2c_write( addr.low8 ); 312 _i2c_start( device | 1 ); 313 setFSR1( _FSR_RF ); 314 do { 315 setINDF1inc( _i2c_read( length != 1 ) ); 316 } while ( --length != 0 ); 317 _i2c_stop(); 318 } 319 //############################################################################################ 320 321 #pragma library 0 322 323 #endif 324 //############################################################################################