rfal_iso15693_2.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. /******************************************************************************
  2. * \attention
  3. *
  4. * <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
  5. *
  6. * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
  7. * You may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at:
  9. *
  10. * www.st.com/myliberty
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
  15. * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. *
  20. ******************************************************************************/
  21. /*
  22. * PROJECT: ST25R391x firmware
  23. * Revision:
  24. * LANGUAGE: ISO C99
  25. */
  26. /*! \file rfal_iso15693_2.c
  27. *
  28. * \author Ulrich Herrmann
  29. *
  30. * \brief Implementation of ISO-15693-2
  31. *
  32. */
  33. /*
  34. ******************************************************************************
  35. * INCLUDES
  36. ******************************************************************************
  37. */
  38. #include "rfal_iso15693_2.h"
  39. #include "rfal_crc.h"
  40. #include "utils.h"
  41. /*
  42. ******************************************************************************
  43. * ENABLE SWITCH
  44. ******************************************************************************
  45. */
  46. #ifndef RFAL_FEATURE_NFCV
  47. #define RFAL_FEATURE_NFCV false /* NFC-V module configuration missing. Disabled by default */
  48. #endif
  49. #if RFAL_FEATURE_NFCV
  50. /*
  51. ******************************************************************************
  52. * LOCAL MACROS
  53. ******************************************************************************
  54. */
  55. #define ISO_15693_DEBUG(...) /*!< Macro for the log method */
  56. /*
  57. ******************************************************************************
  58. * LOCAL DEFINES
  59. ******************************************************************************
  60. */
  61. #define ISO15693_DAT_SOF_1_4 0x21 /* LSB constants */
  62. #define ISO15693_DAT_EOF_1_4 0x04
  63. #define ISO15693_DAT_00_1_4 0x02
  64. #define ISO15693_DAT_01_1_4 0x08
  65. #define ISO15693_DAT_10_1_4 0x20
  66. #define ISO15693_DAT_11_1_4 0x80
  67. #define ISO15693_DAT_SOF_1_256 0x81
  68. #define ISO15693_DAT_EOF_1_256 0x04
  69. #define ISO15693_DAT_SLOT0_1_256 0x02
  70. #define ISO15693_DAT_SLOT1_1_256 0x08
  71. #define ISO15693_DAT_SLOT2_1_256 0x20
  72. #define ISO15693_DAT_SLOT3_1_256 0x80
  73. #define ISO15693_PHY_DAT_MANCHESTER_1 0xaaaa
  74. #define ISO15693_PHY_BIT_BUFFER_SIZE 1000 /*!< size of the receiving buffer. Might be adjusted if longer datastreams are expected. */
  75. /*
  76. ******************************************************************************
  77. * LOCAL VARIABLES
  78. ******************************************************************************
  79. */
  80. static iso15693PhyConfig_t iso15693PhyConfig; /*!< current phy configuration */
  81. /*
  82. ******************************************************************************
  83. * LOCAL FUNCTION PROTOTYPES
  84. ******************************************************************************
  85. */
  86. static ReturnCode iso15693PhyVCDCode1Of4(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen);
  87. static ReturnCode iso15693PhyVCDCode1Of256(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen);
  88. /*
  89. ******************************************************************************
  90. * GLOBAL FUNCTIONS
  91. ******************************************************************************
  92. */
  93. ReturnCode iso15693PhyConfigure(const iso15693PhyConfig_t* config, const struct iso15693StreamConfig ** needed_stream_config )
  94. {
  95. static struct iso15693StreamConfig stream_config = { /* MISRA 8.9 */
  96. .useBPSK = 0, /* 0: subcarrier, 1:BPSK */
  97. .din = 5, /* 2^5*fc = 423750 Hz: divider for the in subcarrier frequency */
  98. .dout = 7, /*!< 2^7*fc = 105937 : divider for the in subcarrier frequency */
  99. .report_period_length = 3, /*!< 8=2^3 the length of the reporting period */
  100. };
  101. /* make a copy of the configuration */
  102. ST_MEMCPY( (uint8_t*)&iso15693PhyConfig, (const uint8_t*)config, sizeof(iso15693PhyConfig_t));
  103. if ( config->speedMode <= 3U)
  104. { /* If valid speed mode adjust report period accordingly */
  105. stream_config.report_period_length = (3U - (uint8_t)config->speedMode);
  106. }
  107. else
  108. { /* If invalid default to normal (high) speed */
  109. stream_config.report_period_length = 3;
  110. }
  111. *needed_stream_config = &stream_config;
  112. return ERR_NONE;
  113. }
  114. ReturnCode iso15693PhyGetConfiguration(iso15693PhyConfig_t* config)
  115. {
  116. ST_MEMCPY(config, &iso15693PhyConfig, sizeof(iso15693PhyConfig_t));
  117. return ERR_NONE;
  118. }
  119. ReturnCode iso15693VCDCode(uint8_t* buffer, uint16_t length, bool sendCrc, bool sendFlags, bool picopassMode,
  120. uint16_t *subbit_total_length, uint16_t *offset,
  121. uint8_t* outbuf, uint16_t outBufSize, uint16_t* actOutBufSize)
  122. {
  123. ReturnCode err = ERR_NONE;
  124. uint8_t eof, sof;
  125. uint8_t transbuf[2];
  126. uint16_t crc = 0;
  127. ReturnCode (*txFunc)(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen);
  128. uint8_t crc_len;
  129. uint8_t* outputBuf;
  130. uint16_t outputBufSize;
  131. crc_len = (uint8_t)((sendCrc)?2:0);
  132. *actOutBufSize = 0;
  133. if (ISO15693_VCD_CODING_1_4 == iso15693PhyConfig.coding)
  134. {
  135. sof = ISO15693_DAT_SOF_1_4;
  136. eof = ISO15693_DAT_EOF_1_4;
  137. txFunc = iso15693PhyVCDCode1Of4;
  138. *subbit_total_length = (
  139. ( 1U /* SOF */
  140. + ((length + (uint16_t)crc_len) * 4U)
  141. + 1U) /* EOF */
  142. );
  143. if (outBufSize < 5U) { /* 5 should be safe: enough for sof + 1byte data in 1of4 */
  144. return ERR_NOMEM;
  145. }
  146. }
  147. else
  148. {
  149. sof = ISO15693_DAT_SOF_1_256;
  150. eof = ISO15693_DAT_EOF_1_256;
  151. txFunc = iso15693PhyVCDCode1Of256;
  152. *subbit_total_length = (
  153. ( 1U /* SOF */
  154. + ((length + (uint16_t)crc_len) * 64U)
  155. + 1U) /* EOF */
  156. );
  157. if (*offset != 0U)
  158. {
  159. if (outBufSize < 64U) { /* 64 should be safe: enough a single byte data in 1of256 */
  160. return ERR_NOMEM;
  161. }
  162. }
  163. else
  164. {
  165. if (outBufSize < 65U) { /* At beginning of a frame we need at least 65 bytes to start: enough for sof + 1byte data in 1of256 */
  166. return ERR_NOMEM;
  167. }
  168. }
  169. }
  170. if (length == 0U)
  171. {
  172. *subbit_total_length = 1;
  173. }
  174. if ((length != 0U) && (0U == *offset) && sendFlags && !picopassMode)
  175. {
  176. /* set high datarate flag */
  177. buffer[0] |= (uint8_t)ISO15693_REQ_FLAG_HIGH_DATARATE;
  178. /* clear sub-carrier flag - we only support single sub-carrier */
  179. buffer[0] = (uint8_t)(buffer[0] & ~ISO15693_REQ_FLAG_TWO_SUBCARRIERS); /* MISRA 10.3 */
  180. }
  181. outputBuf = outbuf; /* MISRA 17.8: Use intermediate variable */
  182. outputBufSize = outBufSize; /* MISRA 17.8: Use intermediate variable */
  183. /* Send SOF if at 0 offset */
  184. if ((length != 0U) && (0U == *offset))
  185. {
  186. *outputBuf = sof;
  187. (*actOutBufSize)++;
  188. outputBufSize--;
  189. outputBuf++;
  190. }
  191. while ((*offset < length) && (err == ERR_NONE))
  192. {
  193. uint16_t filled_size;
  194. /* send data */
  195. err = txFunc(buffer[*offset], outputBuf, outputBufSize, &filled_size);
  196. (*actOutBufSize) += filled_size;
  197. outputBuf = &outputBuf[filled_size]; /* MISRA 18.4: Avoid pointer arithmetic */
  198. outputBufSize -= filled_size;
  199. if (err == ERR_NONE) {
  200. (*offset)++;
  201. }
  202. }
  203. if (err != ERR_NONE) {
  204. return ERR_AGAIN;
  205. }
  206. while ((err == ERR_NONE) && sendCrc && (*offset < (length + 2U)))
  207. {
  208. uint16_t filled_size;
  209. if (0U==crc)
  210. {
  211. crc = rfalCrcCalculateCcitt( (uint16_t) ((picopassMode) ? 0xE012U : 0xFFFFU), /* In PicoPass Mode a different Preset Value is used */
  212. ((picopassMode) ? (buffer + 1U) : buffer), /* CMD byte is not taken into account in PicoPass mode */
  213. ((picopassMode) ? (length - 1U) : length)); /* CMD byte is not taken into account in PicoPass mode */
  214. crc = (uint16_t)((picopassMode) ? crc : ~crc);
  215. }
  216. /* send crc */
  217. transbuf[0] = (uint8_t)(crc & 0xffU);
  218. transbuf[1] = (uint8_t)((crc >> 8) & 0xffU);
  219. err = txFunc(transbuf[*offset - length], outputBuf, outputBufSize, &filled_size);
  220. (*actOutBufSize) += filled_size;
  221. outputBuf = &outputBuf[filled_size]; /* MISRA 18.4: Avoid pointer arithmetic */
  222. outputBufSize -= filled_size;
  223. if (err == ERR_NONE) {
  224. (*offset)++;
  225. }
  226. }
  227. if (err != ERR_NONE) {
  228. return ERR_AGAIN;
  229. }
  230. if ((!sendCrc && (*offset == length))
  231. || (sendCrc && (*offset == (length + 2U))))
  232. {
  233. *outputBuf = eof;
  234. (*actOutBufSize)++;
  235. outputBufSize--;
  236. outputBuf++;
  237. }
  238. else
  239. {
  240. return ERR_AGAIN;
  241. }
  242. return err;
  243. }
  244. ReturnCode iso15693VICCDecode(const uint8_t *inBuf,
  245. uint16_t inBufLen,
  246. uint8_t* outBuf,
  247. uint16_t outBufLen,
  248. uint16_t* outBufPos,
  249. uint16_t* bitsBeforeCol,
  250. uint16_t ignoreBits,
  251. bool picopassMode )
  252. {
  253. ReturnCode err = ERR_NONE;
  254. uint16_t crc;
  255. uint16_t mp; /* Current bit position in manchester bit inBuf*/
  256. uint16_t bp; /* Current bit position in outBuf */
  257. *bitsBeforeCol = 0;
  258. *outBufPos = 0;
  259. /* first check for valid SOF. Since it starts with 3 unmodulated pulses it is 0x17. */
  260. if ((inBuf[0] & 0x1fU) != 0x17U)
  261. {
  262. ISO_15693_DEBUG("0x%x\n", iso15693PhyBitBuffer[0]);
  263. return ERR_FRAMING;
  264. }
  265. ISO_15693_DEBUG("SOF\n");
  266. if (outBufLen == 0U)
  267. {
  268. return ERR_NONE;
  269. }
  270. mp = 5; /* 5 bits were SOF, now manchester starts: 2 bits per payload bit */
  271. bp = 0;
  272. ST_MEMSET(outBuf,0,outBufLen);
  273. if (inBufLen == 0U)
  274. {
  275. return ERR_CRC;
  276. }
  277. for ( ; mp < ((inBufLen * 8U) - 2U); mp+=2U )
  278. {
  279. bool isEOF = false;
  280. uint8_t man;
  281. man = (inBuf[mp/8U] >> (mp%8U)) & 0x1U;
  282. man |= ((inBuf[(mp+1U)/8U] >> ((mp+1U)%8U)) & 0x1U) << 1;
  283. if (1U == man)
  284. {
  285. bp++;
  286. }
  287. if (2U == man)
  288. {
  289. outBuf[bp/8U] = (uint8_t)(outBuf[bp/8U] | (1U <<(bp%8U))); /* MISRA 10.3 */
  290. bp++;
  291. }
  292. if ((bp%8U) == 0U)
  293. { /* Check for EOF */
  294. ISO_15693_DEBUG("ceof %hhx %hhx\n", inBuf[mp/8U], inBuf[mp/8+1]);
  295. if ( ((inBuf[mp/8U] & 0xe0U) == 0xa0U)
  296. &&(inBuf[(mp/8U)+1U] == 0x03U))
  297. { /* Now we know that it was 10111000 = EOF */
  298. ISO_15693_DEBUG("EOF\n");
  299. isEOF = true;
  300. }
  301. }
  302. if ( ((0U == man) || (3U == man)) && !isEOF )
  303. {
  304. if (bp >= ignoreBits)
  305. {
  306. err = ERR_RF_COLLISION;
  307. }
  308. else
  309. {
  310. /* ignored collision: leave as 0 */
  311. bp++;
  312. }
  313. }
  314. if ( (bp >= (outBufLen * 8U)) || (err == ERR_RF_COLLISION) || isEOF )
  315. { /* Don't write beyond the end */
  316. break;
  317. }
  318. }
  319. *outBufPos = (bp / 8U);
  320. *bitsBeforeCol = bp;
  321. if (err != ERR_NONE)
  322. {
  323. return err;
  324. }
  325. if ((bp%8U) != 0U)
  326. {
  327. return ERR_CRC;
  328. }
  329. if (*outBufPos > 2U)
  330. {
  331. /* finally, check crc */
  332. ISO_15693_DEBUG("Calculate CRC, val: 0x%x, outBufLen: ", *outBuf);
  333. ISO_15693_DEBUG("0x%x ", *outBufPos - 2);
  334. crc = rfalCrcCalculateCcitt(((picopassMode) ? 0xE012U : 0xFFFFU), outBuf, *outBufPos - 2U);
  335. crc = (uint16_t)((picopassMode) ? crc : ~crc);
  336. if (((crc & 0xffU) == outBuf[*outBufPos-2U]) &&
  337. (((crc >> 8U) & 0xffU) == outBuf[*outBufPos-1U]))
  338. {
  339. err = ERR_NONE;
  340. ISO_15693_DEBUG("OK\n");
  341. }
  342. else
  343. {
  344. ISO_15693_DEBUG("error! Expected: 0x%x, got ", crc);
  345. ISO_15693_DEBUG("0x%hhx 0x%hhx\n", outBuf[*outBufPos-2], outBuf[*outBufPos-1]);
  346. err = ERR_CRC;
  347. }
  348. }
  349. else
  350. {
  351. err = ERR_CRC;
  352. }
  353. return err;
  354. }
  355. /*
  356. ******************************************************************************
  357. * LOCAL FUNCTIONS
  358. ******************************************************************************
  359. */
  360. /*!
  361. *****************************************************************************
  362. * \brief Perform 1 of 4 coding and send coded data
  363. *
  364. * This function takes \a length bytes from \a buffer, perform 1 of 4 coding
  365. * (see ISO15693-2 specification) and sends the data using stream mode.
  366. *
  367. * \param[in] sendSof : send SOF prior to data.
  368. * \param[in] buffer : data to send.
  369. * \param[in] length : number of bytes to send.
  370. *
  371. * \return ERR_IO : Error during communication.
  372. * \return ERR_NONE : No error.
  373. *
  374. *****************************************************************************
  375. */
  376. static ReturnCode iso15693PhyVCDCode1Of4(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen)
  377. {
  378. uint8_t tmp;
  379. ReturnCode err = ERR_NONE;
  380. uint16_t a;
  381. uint8_t* outbuf = outbuffer;
  382. *outBufLen = 0;
  383. if (maxOutBufLen < 4U) {
  384. return ERR_NOMEM;
  385. }
  386. tmp = data;
  387. for (a = 0; a < 4U; a++)
  388. {
  389. switch (tmp & 0x3U)
  390. {
  391. case 0:
  392. *outbuf = ISO15693_DAT_00_1_4;
  393. break;
  394. case 1:
  395. *outbuf = ISO15693_DAT_01_1_4;
  396. break;
  397. case 2:
  398. *outbuf = ISO15693_DAT_10_1_4;
  399. break;
  400. case 3:
  401. *outbuf = ISO15693_DAT_11_1_4;
  402. break;
  403. default:
  404. /* MISRA 16.4: mandatory default statement */
  405. break;
  406. }
  407. outbuf++;
  408. (*outBufLen)++;
  409. tmp >>= 2;
  410. }
  411. return err;
  412. }
  413. /*!
  414. *****************************************************************************
  415. * \brief Perform 1 of 256 coding and send coded data
  416. *
  417. * This function takes \a length bytes from \a buffer, perform 1 of 256 coding
  418. * (see ISO15693-2 specification) and sends the data using stream mode.
  419. * \note This function sends SOF prior to the data.
  420. *
  421. * \param[in] sendSof : send SOF prior to data.
  422. * \param[in] buffer : data to send.
  423. * \param[in] length : number of bytes to send.
  424. *
  425. * \return ERR_IO : Error during communication.
  426. * \return ERR_NONE : No error.
  427. *
  428. *****************************************************************************
  429. */
  430. static ReturnCode iso15693PhyVCDCode1Of256(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen)
  431. {
  432. uint8_t tmp;
  433. ReturnCode err = ERR_NONE;
  434. uint16_t a;
  435. uint8_t* outbuf = outbuffer;
  436. *outBufLen = 0;
  437. if (maxOutBufLen < 64U) {
  438. return ERR_NOMEM;
  439. }
  440. tmp = data;
  441. for (a = 0; a < 64U; a++)
  442. {
  443. switch (tmp)
  444. {
  445. case 0:
  446. *outbuf = ISO15693_DAT_SLOT0_1_256;
  447. break;
  448. case 1:
  449. *outbuf = ISO15693_DAT_SLOT1_1_256;
  450. break;
  451. case 2:
  452. *outbuf = ISO15693_DAT_SLOT2_1_256;
  453. break;
  454. case 3:
  455. *outbuf = ISO15693_DAT_SLOT3_1_256;
  456. break;
  457. default:
  458. *outbuf = 0;
  459. break;
  460. }
  461. outbuf++;
  462. (*outBufLen)++;
  463. tmp -= 4U;
  464. }
  465. return err;
  466. }
  467. #endif /* RFAL_FEATURE_NFCV */