rfal_iso15693_2.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  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 "../include/rfal_iso15693_2.h"
  39. #include "../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 \
  75. 1000 /*!< size of the receiving buffer. Might be adjusted if longer datastreams are expected. */
  76. /*
  77. ******************************************************************************
  78. * LOCAL VARIABLES
  79. ******************************************************************************
  80. */
  81. static iso15693PhyConfig_t iso15693PhyConfig; /*!< current phy configuration */
  82. /*
  83. ******************************************************************************
  84. * LOCAL FUNCTION PROTOTYPES
  85. ******************************************************************************
  86. */
  87. static ReturnCode iso15693PhyVCDCode1Of4(
  88. const uint8_t data,
  89. uint8_t* outbuffer,
  90. uint16_t maxOutBufLen,
  91. uint16_t* outBufLen);
  92. static ReturnCode iso15693PhyVCDCode1Of256(
  93. const uint8_t data,
  94. uint8_t* outbuffer,
  95. uint16_t maxOutBufLen,
  96. uint16_t* outBufLen);
  97. /*
  98. ******************************************************************************
  99. * GLOBAL FUNCTIONS
  100. ******************************************************************************
  101. */
  102. ReturnCode iso15693PhyConfigure(
  103. const iso15693PhyConfig_t* config,
  104. const struct iso15693StreamConfig** needed_stream_config) {
  105. static struct iso15693StreamConfig stream_config = {
  106. /* MISRA 8.9 */
  107. .useBPSK = 0, /* 0: subcarrier, 1:BPSK */
  108. .din = 5, /* 2^5*fc = 423750 Hz: divider for the in subcarrier frequency */
  109. .dout = 7, /*!< 2^7*fc = 105937 : divider for the in subcarrier frequency */
  110. .report_period_length = 3, /*!< 8=2^3 the length of the reporting period */
  111. };
  112. /* make a copy of the configuration */
  113. ST_MEMCPY((uint8_t*)&iso15693PhyConfig, (const uint8_t*)config, sizeof(iso15693PhyConfig_t));
  114. if(config->speedMode <= 3U) { /* If valid speed mode adjust report period accordingly */
  115. stream_config.report_period_length = (3U - (uint8_t)config->speedMode);
  116. } else { /* If invalid default to normal (high) speed */
  117. stream_config.report_period_length = 3;
  118. }
  119. *needed_stream_config = &stream_config;
  120. return ERR_NONE;
  121. }
  122. ReturnCode iso15693PhyGetConfiguration(iso15693PhyConfig_t* config) {
  123. ST_MEMCPY(config, &iso15693PhyConfig, sizeof(iso15693PhyConfig_t));
  124. return ERR_NONE;
  125. }
  126. ReturnCode iso15693VCDCode(
  127. uint8_t* buffer,
  128. uint16_t length,
  129. bool sendCrc,
  130. bool sendFlags,
  131. bool picopassMode,
  132. uint16_t* subbit_total_length,
  133. uint16_t* offset,
  134. uint8_t* outbuf,
  135. uint16_t outBufSize,
  136. uint16_t* actOutBufSize) {
  137. ReturnCode err = ERR_NONE;
  138. uint8_t eof, sof;
  139. uint8_t transbuf[2];
  140. uint16_t crc = 0;
  141. ReturnCode (*txFunc)(
  142. const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen);
  143. uint8_t crc_len;
  144. uint8_t* outputBuf;
  145. uint16_t outputBufSize;
  146. crc_len = (uint8_t)((sendCrc) ? 2 : 0);
  147. *actOutBufSize = 0;
  148. if(ISO15693_VCD_CODING_1_4 == iso15693PhyConfig.coding) {
  149. sof = ISO15693_DAT_SOF_1_4;
  150. eof = ISO15693_DAT_EOF_1_4;
  151. txFunc = iso15693PhyVCDCode1Of4;
  152. *subbit_total_length =
  153. ((1U /* SOF */
  154. + ((length + (uint16_t)crc_len) * 4U) + 1U) /* EOF */
  155. );
  156. if(outBufSize < 5U) { /* 5 should be safe: enough for sof + 1byte data in 1of4 */
  157. return ERR_NOMEM;
  158. }
  159. } else {
  160. sof = ISO15693_DAT_SOF_1_256;
  161. eof = ISO15693_DAT_EOF_1_256;
  162. txFunc = iso15693PhyVCDCode1Of256;
  163. *subbit_total_length =
  164. ((1U /* SOF */
  165. + ((length + (uint16_t)crc_len) * 64U) + 1U) /* EOF */
  166. );
  167. if(*offset != 0U) {
  168. if(outBufSize < 64U) { /* 64 should be safe: enough a single byte data in 1of256 */
  169. return ERR_NOMEM;
  170. }
  171. } else {
  172. if(outBufSize <
  173. 65U) { /* At beginning of a frame we need at least 65 bytes to start: enough for sof + 1byte data in 1of256 */
  174. return ERR_NOMEM;
  175. }
  176. }
  177. }
  178. if(length == 0U) {
  179. *subbit_total_length = 1;
  180. }
  181. if((length != 0U) && (0U == *offset) && sendFlags && !picopassMode) {
  182. /* set high datarate flag */
  183. buffer[0] |= (uint8_t)ISO15693_REQ_FLAG_HIGH_DATARATE;
  184. /* clear sub-carrier flag - we only support single sub-carrier */
  185. buffer[0] = (uint8_t)(buffer[0] & ~ISO15693_REQ_FLAG_TWO_SUBCARRIERS); /* MISRA 10.3 */
  186. }
  187. outputBuf = outbuf; /* MISRA 17.8: Use intermediate variable */
  188. outputBufSize = outBufSize; /* MISRA 17.8: Use intermediate variable */
  189. /* Send SOF if at 0 offset */
  190. if((length != 0U) && (0U == *offset)) {
  191. *outputBuf = sof;
  192. (*actOutBufSize)++;
  193. outputBufSize--;
  194. outputBuf++;
  195. }
  196. while((*offset < length) && (err == ERR_NONE)) {
  197. uint16_t filled_size;
  198. /* send data */
  199. err = txFunc(buffer[*offset], outputBuf, outputBufSize, &filled_size);
  200. (*actOutBufSize) += filled_size;
  201. outputBuf = &outputBuf[filled_size]; /* MISRA 18.4: Avoid pointer arithmetic */
  202. outputBufSize -= filled_size;
  203. if(err == ERR_NONE) {
  204. (*offset)++;
  205. }
  206. }
  207. if(err != ERR_NONE) {
  208. return ERR_AGAIN;
  209. }
  210. while((err == ERR_NONE) && sendCrc && (*offset < (length + 2U))) {
  211. uint16_t filled_size;
  212. if(0U == crc) {
  213. crc = rfalCrcCalculateCcitt(
  214. (uint16_t)((picopassMode) ?
  215. 0xE012U :
  216. 0xFFFFU), /* In PicoPass Mode a different Preset Value is used */
  217. ((picopassMode) ?
  218. (buffer + 1U) :
  219. buffer), /* CMD byte is not taken into account in PicoPass mode */
  220. ((picopassMode) ?
  221. (length - 1U) :
  222. length)); /* CMD byte is not taken into account in PicoPass mode */
  223. crc = (uint16_t)((picopassMode) ? crc : ~crc);
  224. }
  225. /* send crc */
  226. transbuf[0] = (uint8_t)(crc & 0xffU);
  227. transbuf[1] = (uint8_t)((crc >> 8) & 0xffU);
  228. err = txFunc(transbuf[*offset - length], outputBuf, outputBufSize, &filled_size);
  229. (*actOutBufSize) += filled_size;
  230. outputBuf = &outputBuf[filled_size]; /* MISRA 18.4: Avoid pointer arithmetic */
  231. outputBufSize -= filled_size;
  232. if(err == ERR_NONE) {
  233. (*offset)++;
  234. }
  235. }
  236. if(err != ERR_NONE) {
  237. return ERR_AGAIN;
  238. }
  239. if((!sendCrc && (*offset == length)) || (sendCrc && (*offset == (length + 2U)))) {
  240. *outputBuf = eof;
  241. (*actOutBufSize)++;
  242. outputBufSize--;
  243. outputBuf++;
  244. } else {
  245. return ERR_AGAIN;
  246. }
  247. return err;
  248. }
  249. ReturnCode iso15693VICCDecode(
  250. const uint8_t* inBuf,
  251. uint16_t inBufLen,
  252. uint8_t* outBuf,
  253. uint16_t outBufLen,
  254. uint16_t* outBufPos,
  255. uint16_t* bitsBeforeCol,
  256. uint16_t ignoreBits,
  257. bool picopassMode) {
  258. ReturnCode err = ERR_NONE;
  259. uint16_t crc;
  260. uint16_t mp; /* Current bit position in manchester bit inBuf*/
  261. uint16_t bp; /* Current bit position in outBuf */
  262. *bitsBeforeCol = 0;
  263. *outBufPos = 0;
  264. /* first check for valid SOF. Since it starts with 3 unmodulated pulses it is 0x17. */
  265. if((inBuf[0] & 0x1fU) != 0x17U) {
  266. ISO_15693_DEBUG("0x%x\n", iso15693PhyBitBuffer[0]);
  267. return ERR_FRAMING;
  268. }
  269. ISO_15693_DEBUG("SOF\n");
  270. if(outBufLen == 0U) {
  271. return ERR_NONE;
  272. }
  273. mp = 5; /* 5 bits were SOF, now manchester starts: 2 bits per payload bit */
  274. bp = 0;
  275. ST_MEMSET(outBuf, 0, outBufLen);
  276. if(inBufLen == 0U) {
  277. return ERR_CRC;
  278. }
  279. for(; mp < ((inBufLen * 8U) - 2U); mp += 2U) {
  280. bool isEOF = false;
  281. uint8_t man;
  282. man = (inBuf[mp / 8U] >> (mp % 8U)) & 0x1U;
  283. man |= ((inBuf[(mp + 1U) / 8U] >> ((mp + 1U) % 8U)) & 0x1U) << 1;
  284. if(1U == man) {
  285. bp++;
  286. }
  287. if(2U == man) {
  288. outBuf[bp / 8U] = (uint8_t)(outBuf[bp / 8U] | (1U << (bp % 8U))); /* MISRA 10.3 */
  289. bp++;
  290. }
  291. if((bp % 8U) == 0U) { /* Check for EOF */
  292. ISO_15693_DEBUG("ceof %hhx %hhx\n", inBuf[mp / 8U], inBuf[mp / 8 + 1]);
  293. if(((inBuf[mp / 8U] & 0xe0U) == 0xa0U) &&
  294. (inBuf[(mp / 8U) + 1U] == 0x03U)) { /* Now we know that it was 10111000 = EOF */
  295. ISO_15693_DEBUG("EOF\n");
  296. isEOF = true;
  297. }
  298. }
  299. if(((0U == man) || (3U == man)) && !isEOF) {
  300. if(bp >= ignoreBits) {
  301. err = ERR_RF_COLLISION;
  302. } else {
  303. /* ignored collision: leave as 0 */
  304. bp++;
  305. }
  306. }
  307. if((bp >= (outBufLen * 8U)) || (err == ERR_RF_COLLISION) ||
  308. isEOF) { /* Don't write beyond the end */
  309. break;
  310. }
  311. }
  312. *outBufPos = (bp / 8U);
  313. *bitsBeforeCol = bp;
  314. if(err != ERR_NONE) {
  315. return err;
  316. }
  317. if((bp % 8U) != 0U) {
  318. return ERR_CRC;
  319. }
  320. if(*outBufPos > 2U) {
  321. /* finally, check crc */
  322. ISO_15693_DEBUG("Calculate CRC, val: 0x%x, outBufLen: ", *outBuf);
  323. ISO_15693_DEBUG("0x%x ", *outBufPos - 2);
  324. crc = rfalCrcCalculateCcitt(((picopassMode) ? 0xE012U : 0xFFFFU), outBuf, *outBufPos - 2U);
  325. crc = (uint16_t)((picopassMode) ? crc : ~crc);
  326. if(((crc & 0xffU) == outBuf[*outBufPos - 2U]) &&
  327. (((crc >> 8U) & 0xffU) == outBuf[*outBufPos - 1U])) {
  328. err = ERR_NONE;
  329. ISO_15693_DEBUG("OK\n");
  330. } else {
  331. ISO_15693_DEBUG("error! Expected: 0x%x, got ", crc);
  332. ISO_15693_DEBUG("0x%hhx 0x%hhx\n", outBuf[*outBufPos - 2], outBuf[*outBufPos - 1]);
  333. err = ERR_CRC;
  334. }
  335. } else {
  336. err = ERR_CRC;
  337. }
  338. return err;
  339. }
  340. /*
  341. ******************************************************************************
  342. * LOCAL FUNCTIONS
  343. ******************************************************************************
  344. */
  345. /*!
  346. *****************************************************************************
  347. * \brief Perform 1 of 4 coding and send coded data
  348. *
  349. * This function takes \a length bytes from \a buffer, perform 1 of 4 coding
  350. * (see ISO15693-2 specification) and sends the data using stream mode.
  351. *
  352. * \param[in] sendSof : send SOF prior to data.
  353. * \param[in] buffer : data to send.
  354. * \param[in] length : number of bytes to send.
  355. *
  356. * \return ERR_IO : Error during communication.
  357. * \return ERR_NONE : No error.
  358. *
  359. *****************************************************************************
  360. */
  361. static ReturnCode iso15693PhyVCDCode1Of4(
  362. const uint8_t data,
  363. uint8_t* outbuffer,
  364. uint16_t maxOutBufLen,
  365. uint16_t* outBufLen) {
  366. uint8_t tmp;
  367. ReturnCode err = ERR_NONE;
  368. uint16_t a;
  369. uint8_t* outbuf = outbuffer;
  370. *outBufLen = 0;
  371. if(maxOutBufLen < 4U) {
  372. return ERR_NOMEM;
  373. }
  374. tmp = data;
  375. for(a = 0; a < 4U; a++) {
  376. switch(tmp & 0x3U) {
  377. case 0:
  378. *outbuf = ISO15693_DAT_00_1_4;
  379. break;
  380. case 1:
  381. *outbuf = ISO15693_DAT_01_1_4;
  382. break;
  383. case 2:
  384. *outbuf = ISO15693_DAT_10_1_4;
  385. break;
  386. case 3:
  387. *outbuf = ISO15693_DAT_11_1_4;
  388. break;
  389. default:
  390. /* MISRA 16.4: mandatory default statement */
  391. break;
  392. }
  393. outbuf++;
  394. (*outBufLen)++;
  395. tmp >>= 2;
  396. }
  397. return err;
  398. }
  399. /*!
  400. *****************************************************************************
  401. * \brief Perform 1 of 256 coding and send coded data
  402. *
  403. * This function takes \a length bytes from \a buffer, perform 1 of 256 coding
  404. * (see ISO15693-2 specification) and sends the data using stream mode.
  405. * \note This function sends SOF prior to the data.
  406. *
  407. * \param[in] sendSof : send SOF prior to data.
  408. * \param[in] buffer : data to send.
  409. * \param[in] length : number of bytes to send.
  410. *
  411. * \return ERR_IO : Error during communication.
  412. * \return ERR_NONE : No error.
  413. *
  414. *****************************************************************************
  415. */
  416. static ReturnCode iso15693PhyVCDCode1Of256(
  417. const uint8_t data,
  418. uint8_t* outbuffer,
  419. uint16_t maxOutBufLen,
  420. uint16_t* outBufLen) {
  421. uint8_t tmp;
  422. ReturnCode err = ERR_NONE;
  423. uint16_t a;
  424. uint8_t* outbuf = outbuffer;
  425. *outBufLen = 0;
  426. if(maxOutBufLen < 64U) {
  427. return ERR_NOMEM;
  428. }
  429. tmp = data;
  430. for(a = 0; a < 64U; a++) {
  431. switch(tmp) {
  432. case 0:
  433. *outbuf = ISO15693_DAT_SLOT0_1_256;
  434. break;
  435. case 1:
  436. *outbuf = ISO15693_DAT_SLOT1_1_256;
  437. break;
  438. case 2:
  439. *outbuf = ISO15693_DAT_SLOT2_1_256;
  440. break;
  441. case 3:
  442. *outbuf = ISO15693_DAT_SLOT3_1_256;
  443. break;
  444. default:
  445. *outbuf = 0;
  446. break;
  447. }
  448. outbuf++;
  449. (*outBufLen)++;
  450. tmp -= 4U;
  451. }
  452. return err;
  453. }
  454. #endif /* RFAL_FEATURE_NFCV */