Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
rfal_iso15693_2.cpp
00001 00002 /****************************************************************************** 00003 * @attention 00004 * 00005 * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> 00006 * 00007 * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); 00008 * You may not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at: 00010 * 00011 * http://www.st.com/myliberty 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, 00015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, 00016 * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, 00017 * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. 00018 * See the License for the specific language governing permissions and 00019 * limitations under the License. 00020 * 00021 ******************************************************************************/ 00022 00023 /* 00024 * PROJECT: ST25R391x firmware 00025 * $Revision: $ 00026 * LANGUAGE: ISO C99 00027 */ 00028 00029 /*! \file rfal_iso15693_2.c 00030 * 00031 * \author Ulrich Herrmann 00032 * 00033 * \brief Implementation of ISO-15693-2 00034 * 00035 */ 00036 00037 /* 00038 ****************************************************************************** 00039 * INCLUDES 00040 ****************************************************************************** 00041 */ 00042 #include "rfal_iso15693_2.h" 00043 #include "rfal_crc.h" 00044 #include "utils.h" 00045 #include "platform1.h" 00046 00047 /* 00048 ****************************************************************************** 00049 * ENABLE SWITCH 00050 ****************************************************************************** 00051 */ 00052 00053 #ifndef RFAL_FEATURE_NFCV 00054 #error " RFAL: Module configuration missing. Please enable/disable NFC-V module by setting: RFAL_FEATURE_NFCV " 00055 #endif 00056 00057 #if RFAL_FEATURE_NFCV 00058 00059 /* 00060 ****************************************************************************** 00061 * LOCAL MACROS 00062 ****************************************************************************** 00063 */ 00064 00065 /* #define ISO_15693_DEBUG dbgLog */ 00066 #define ISO_15693_DEBUG(...) /*!< Macro for the log method */ 00067 00068 /* 00069 ****************************************************************************** 00070 * LOCAL DEFINES 00071 ****************************************************************************** 00072 */ 00073 #define ISO15693_DAT_SOF_1_4 0x21 /* LSB constants */ 00074 #define ISO15693_DAT_EOF_1_4 0x04 00075 #define ISO15693_DAT_00_1_4 0x02 00076 #define ISO15693_DAT_01_1_4 0x08 00077 #define ISO15693_DAT_10_1_4 0x20 00078 #define ISO15693_DAT_11_1_4 0x80 00079 00080 #define ISO15693_DAT_SOF_1_256 0x81 00081 #define ISO15693_DAT_EOF_1_256 0x04 00082 #define ISO15693_DAT_SLOT0_1_256 0x02 00083 #define ISO15693_DAT_SLOT1_1_256 0x08 00084 #define ISO15693_DAT_SLOT2_1_256 0x20 00085 #define ISO15693_DAT_SLOT3_1_256 0x80 00086 00087 #define ISO15693_PHY_DAT_MANCHESTER_1 0xaaaa 00088 00089 #define ISO15693_PHY_BIT_BUFFER_SIZE 1000 /*!< 00090 size of the receiving buffer. Might be adjusted 00091 if longer datastreams are expected. */ 00092 00093 00094 /* 00095 ****************************************************************************** 00096 * LOCAL VARIABLES 00097 ****************************************************************************** 00098 */ 00099 static iso15693PhyConfig_t iso15693PhyConfig; /*!< current phy configuration */ 00100 00101 /* 00102 ****************************************************************************** 00103 * LOCAL FUNCTION PROTOTYPES 00104 ****************************************************************************** 00105 */ 00106 static ReturnCode iso15693PhyVCDCode1Of4(const uint8_t data, uint8_t* outbuf, uint16_t maxOutBufLen, uint16_t* outBufLen); 00107 static ReturnCode iso15693PhyVCDCode1Of256(const uint8_t data, uint8_t* outbuf, uint16_t maxOutBufLen, uint16_t* outBufLen); 00108 00109 static struct iso15693StreamConfig stream_config = { 00110 .useBPSK = 0, /* 0: subcarrier, 1:BPSK */ 00111 .din = 5, /* 2^5*fc = 423750 Hz: divider for the in subcarrier frequency */ 00112 .dout = 7, /*!< 2^7*fc = 105937 : divider for the in subcarrier frequency */ 00113 .report_period_length = 3, /*!< 8=2^3 the length of the reporting period */ 00114 }; 00115 00116 /* 00117 ****************************************************************************** 00118 * GLOBAL FUNCTIONS 00119 ****************************************************************************** 00120 */ 00121 ReturnCode iso15693PhyConfigure(const iso15693PhyConfig_t * config, const struct iso15693StreamConfig ** needed_stream_config ) 00122 { 00123 00124 /* make a copy of the configuration */ 00125 ST_MEMCPY(&iso15693PhyConfig, (uint8_t*)config, sizeof(iso15693PhyConfig_t )); 00126 00127 /* If in fast mode the report period is half: 4=2^2 */ 00128 stream_config.report_period_length = ( config->fastMode ? 2 : 3 ); 00129 00130 *needed_stream_config = &stream_config; 00131 00132 return ERR_NONE; 00133 } 00134 00135 ReturnCode iso15693PhyGetConfiguration(iso15693PhyConfig_t * config) 00136 { 00137 ST_MEMCPY(config, &iso15693PhyConfig, sizeof(iso15693PhyConfig_t )); 00138 00139 return ERR_NONE; 00140 } 00141 00142 ReturnCode iso15693VCDCode(uint8_t* buffer, uint16_t length, bool sendCrc, bool sendFlags, bool picopassMode, 00143 uint16_t *subbit_total_length, uint16_t *offset, 00144 uint8_t* outbuf, uint16_t outBufSize, uint16_t* actOutBufSize) 00145 { 00146 ReturnCode err = ERR_NONE; 00147 uint8_t eof, sof; 00148 uint8_t transbuf[2]; 00149 uint16_t crc = 0; 00150 ReturnCode (*txFunc)(const uint8_t, uint8_t*, uint16_t, uint16_t*); 00151 uint8_t crc_len; 00152 00153 crc_len = ((sendCrc)?2:0); 00154 00155 *actOutBufSize = 0; 00156 00157 if (ISO15693_VCD_CODING_1_4 == iso15693PhyConfig.coding ) 00158 { 00159 sof = ISO15693_DAT_SOF_1_4; 00160 eof = ISO15693_DAT_EOF_1_4; 00161 txFunc = iso15693PhyVCDCode1Of4; 00162 *subbit_total_length = ( 00163 ( 1 /* SOF */ 00164 + (length + crc_len) * 4 00165 + 1) /* EOF */ 00166 ); 00167 if (outBufSize < 5) /* 5 should be safe: enough for sof + 1byte data in 1of4 */ 00168 return ERR_NOMEM; 00169 } 00170 else 00171 { 00172 sof = ISO15693_DAT_SOF_1_256; 00173 eof = ISO15693_DAT_EOF_1_256; 00174 txFunc = iso15693PhyVCDCode1Of256; 00175 *subbit_total_length = ( 00176 ( 1 /* SOF */ 00177 + (length + crc_len) * 64 00178 + 1) /* EOF */ 00179 ); 00180 00181 if (*offset) 00182 { 00183 if (outBufSize < 64) /* 64 should be safe: enough a single byte data in 1of256 */ 00184 return ERR_NOMEM; 00185 } 00186 else 00187 { 00188 if (outBufSize < 65) /* At beginning of a frame we need at least 65 bytes to start: enough for sof + 1byte data in 1of256 */ 00189 return ERR_NOMEM; 00190 } 00191 } 00192 00193 if (length == 0) 00194 { 00195 *subbit_total_length = 1; 00196 } 00197 00198 if (length && (0 == *offset) && sendFlags && !picopassMode) 00199 { 00200 /* set high datarate flag */ 00201 buffer[0] |= ISO15693_REQ_FLAG_HIGH_DATARATE; 00202 /* clear sub-carrier flag - we only support single sub-carrier */ 00203 buffer[0] &= ~ISO15693_REQ_FLAG_TWO_SUBCARRIERS; 00204 } 00205 00206 /* Send SOF if at 0 offset */ 00207 if (length && 0 == *offset) 00208 { 00209 *outbuf = sof; 00210 (*actOutBufSize)++; 00211 outBufSize--; 00212 outbuf++; 00213 } 00214 00215 while (*offset < length && err == ERR_NONE) 00216 { 00217 uint16_t filled_size; 00218 /* send data */ 00219 err = txFunc(buffer[*offset], outbuf, outBufSize, &filled_size); 00220 (*actOutBufSize) += filled_size; 00221 outbuf+=filled_size; 00222 outBufSize -= filled_size; 00223 if (!err) (*offset)++; 00224 } 00225 if (err) return ERR_AGAIN; 00226 00227 while (!err && sendCrc && *offset < length + 2) 00228 { 00229 uint16_t filled_size; 00230 if (0==crc) 00231 { 00232 crc = rfalCrcCalculateCcitt( ((picopassMode) ? 0xE012 : 0xFFFF), /* In PicoPass Mode a different Preset Value is used */ 00233 ((picopassMode) ? (buffer + 1) : buffer), /* CMD byte is not taken into account in PicoPass mode */ 00234 ((picopassMode) ? (length - 1) : length)); /* CMD byte is not taken into account in PicoPass mode */ 00235 00236 crc = ((picopassMode) ? crc : ~crc); 00237 } 00238 /* send crc */ 00239 transbuf[0] = crc & 0xff; 00240 transbuf[1] = (crc >> 8) & 0xff; 00241 err = txFunc(transbuf[*offset - length], outbuf, outBufSize, &filled_size); 00242 (*actOutBufSize) += filled_size; 00243 outbuf+=filled_size; 00244 outBufSize -= filled_size; 00245 if(!err) (*offset)++; 00246 } 00247 if (err) return ERR_AGAIN; 00248 00249 if ((!sendCrc && (*offset) == length) 00250 || (sendCrc && (*offset) == length + 2)) 00251 { 00252 *outbuf = eof; 00253 (*actOutBufSize)++; 00254 outBufSize--; 00255 outbuf++; 00256 } 00257 else return ERR_AGAIN; 00258 00259 return err; 00260 } 00261 00262 ReturnCode iso15693VICCDecode(uint8_t *inBuf, 00263 uint16_t inBufLen, 00264 uint8_t* outBuf, 00265 uint16_t outBufLen, 00266 uint16_t* outBufPos, 00267 uint16_t* bitsBeforeCol, 00268 uint16_t ignoreBits, 00269 bool picopassMode ) 00270 { 00271 ReturnCode err = ERR_NONE; 00272 uint16_t crc; 00273 uint16_t mp; /* Current bit position in manchester bit inBuf*/ 00274 uint16_t bp; /* Current bit postion in outBuf */ 00275 00276 *bitsBeforeCol = 0; 00277 *outBufPos = 0; 00278 00279 /* first check for valid SOF. Since it starts with 3 unmodulated pulses it is 0x17. */ 00280 if ((inBuf[0] & 0x1f) != 0x17) 00281 { 00282 ISO_15693_DEBUG("0x%x\n", iso15693PhyBitBuffer[0]); 00283 err = ERR_FRAMING; 00284 goto out; 00285 } 00286 ISO_15693_DEBUG("SOF\n"); 00287 00288 if (!outBufLen) 00289 { 00290 goto out; 00291 } 00292 00293 mp = 5; /* 5 bits were SOF, now manchester starts: 2 bits per payload bit */ 00294 bp = 0; 00295 00296 memset(outBuf,0,outBufLen); 00297 00298 for ( ; mp < inBufLen * 8 - 2; mp+=2 ) 00299 { 00300 uint8_t man; 00301 man = (inBuf[mp/8] >> mp%8) & 0x1; 00302 man |= ((inBuf[(mp+1)/8] >> (mp+1)%8) & 0x1) << 1; 00303 if (1 == man) 00304 { 00305 bp++; 00306 } 00307 if (2 == man) 00308 { 00309 outBuf[bp/8] |= 1 << (bp%8); 00310 bp++; 00311 } 00312 if (bp%8 == 0) 00313 { /* Check for EOF */ 00314 ISO_15693_DEBUG("ceof %hhx %hhx\n", inBuf[mp/8], inBuf[mp/8+1]); 00315 if ( ((inBuf[mp/8] & 0xe0) == 0xa0) 00316 &&(inBuf[mp/8+1] == 0x03)) 00317 { /* Now we know that it was 10111000 = EOF */ 00318 ISO_15693_DEBUG("EOF\n"); 00319 break; 00320 } 00321 } 00322 if (0 == man || 3 == man) 00323 { 00324 if (bp >= ignoreBits) 00325 { 00326 err = ERR_RF_COLLISION; 00327 break; 00328 } 00329 /* ignored collision: leave as 0 */ 00330 bp++; 00331 } 00332 if (bp >= outBufLen * 8) 00333 { /* Don't write beyond the end */ 00334 break; 00335 } 00336 } 00337 00338 *outBufPos = bp / 8; 00339 *bitsBeforeCol = bp; 00340 00341 if (err) goto out; 00342 00343 if (bp%8 != 0) 00344 { 00345 err = ERR_CRC; 00346 goto out; 00347 } 00348 00349 if (*outBufPos > 2) 00350 { 00351 /* finally, check crc */ 00352 ISO_15693_DEBUG("Calculate CRC, val: 0x%x, outBufLen: ", *outBuf); 00353 ISO_15693_DEBUG("0x%x ", *outBufPos - 2); 00354 00355 crc = rfalCrcCalculateCcitt( ((picopassMode) ? 0xE012 : 0xFFFF), outBuf, *outBufPos - 2); 00356 crc = ((picopassMode) ? crc : ~crc); 00357 00358 if (((crc & 0xff) == outBuf[*outBufPos-2]) && 00359 (((crc >> 8) & 0xff) == outBuf[*outBufPos-1])) 00360 { 00361 err = ERR_NONE; 00362 ISO_15693_DEBUG("OK\n"); 00363 } 00364 else 00365 { 00366 ISO_15693_DEBUG("error! Expected: 0x%x, got ", crc); 00367 ISO_15693_DEBUG("0x%hhx 0x%hhx\n", outBuf[*outBufPos-2], outBuf[*outBufPos-1]); 00368 err = ERR_CRC; 00369 } 00370 } 00371 else 00372 { 00373 err = ERR_CRC; 00374 } 00375 out: 00376 return err; 00377 } 00378 00379 /* 00380 ****************************************************************************** 00381 * LOCAL FUNCTIONS 00382 ****************************************************************************** 00383 */ 00384 /*! 00385 ***************************************************************************** 00386 * \brief Perform 1 of 4 coding and send coded data 00387 * 00388 * This function takes \a length bytes from \a buffer, perform 1 of 4 coding 00389 * (see ISO15693-2 specification) and sends the data using stream mode. 00390 * 00391 * \param[in] sendSof : send SOF prior to data. 00392 * \param[in] buffer : data to send. 00393 * \param[in] length : number of bytes to send. 00394 * 00395 * \return ERR_IO : Error during communication. 00396 * \return ERR_NONE : No error. 00397 * 00398 ***************************************************************************** 00399 */ 00400 static ReturnCode iso15693PhyVCDCode1Of4(const uint8_t data, uint8_t* outbuf, uint16_t maxOutBufLen, uint16_t* outBufLen) 00401 { 00402 uint8_t tmp; 00403 ReturnCode err = ERR_NONE; 00404 uint16_t a; 00405 00406 *outBufLen = 0; 00407 00408 if (maxOutBufLen < 4) 00409 return ERR_NOMEM; 00410 00411 tmp = data; 00412 for (a = 0; a < 4; a++) 00413 { 00414 switch (tmp & 0x3) 00415 { 00416 case 0: 00417 *outbuf = ISO15693_DAT_00_1_4; 00418 break; 00419 case 1: 00420 *outbuf = ISO15693_DAT_01_1_4; 00421 break; 00422 case 2: 00423 *outbuf = ISO15693_DAT_10_1_4; 00424 break; 00425 case 3: 00426 *outbuf = ISO15693_DAT_11_1_4; 00427 break; 00428 } 00429 outbuf++; 00430 (*outBufLen)++; 00431 tmp >>= 2; 00432 } 00433 return err; 00434 } 00435 00436 /*! 00437 ***************************************************************************** 00438 * \brief Perform 1 of 256 coding and send coded data 00439 * 00440 * This function takes \a length bytes from \a buffer, perform 1 of 256 coding 00441 * (see ISO15693-2 specification) and sends the data using stream mode. 00442 * \note This function sends SOF prior to the data. 00443 * 00444 * \param[in] sendSof : send SOF prior to data. 00445 * \param[in] buffer : data to send. 00446 * \param[in] length : number of bytes to send. 00447 * 00448 * \return ERR_IO : Error during communication. 00449 * \return ERR_NONE : No error. 00450 * 00451 ***************************************************************************** 00452 */ 00453 static ReturnCode iso15693PhyVCDCode1Of256(const uint8_t data, uint8_t* outbuf, uint16_t maxOutBufLen, uint16_t* outBufLen) 00454 { 00455 uint8_t tmp; 00456 ReturnCode err = ERR_NONE; 00457 uint16_t a; 00458 00459 *outBufLen = 0; 00460 00461 if (maxOutBufLen < 64) 00462 return ERR_NOMEM; 00463 00464 tmp = data; 00465 for (a = 0; a < 64; a++) 00466 { 00467 switch (tmp) 00468 { 00469 case 0: 00470 *outbuf = ISO15693_DAT_SLOT0_1_256; 00471 break; 00472 case 1: 00473 *outbuf = ISO15693_DAT_SLOT1_1_256; 00474 break; 00475 case 2: 00476 *outbuf = ISO15693_DAT_SLOT2_1_256; 00477 break; 00478 case 3: 00479 *outbuf = ISO15693_DAT_SLOT3_1_256; 00480 break; 00481 default: 00482 *outbuf = 0; 00483 } 00484 outbuf++; 00485 (*outBufLen)++; 00486 tmp -= 4; 00487 } 00488 00489 return err; 00490 } 00491 00492 #endif /* RFAL_FEATURE_NFCV */
Generated on Sat Jul 16 2022 13:00:53 by
1.7.2