rfal_iso15693_2.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  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 \
  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) ? 0xE012U : 0xFFFFU), /* In PicoPass Mode a different Preset Value is used */
  215. ((picopassMode) ?
  216. (buffer + 1U) :
  217. buffer), /* CMD byte is not taken into account in PicoPass mode */
  218. ((picopassMode) ?
  219. (length - 1U) :
  220. length)); /* CMD byte is not taken into account in PicoPass mode */
  221. crc = (uint16_t)((picopassMode) ? crc : ~crc);
  222. }
  223. /* send crc */
  224. transbuf[0] = (uint8_t)(crc & 0xffU);
  225. transbuf[1] = (uint8_t)((crc >> 8) & 0xffU);
  226. err = txFunc(transbuf[*offset - length], outputBuf, outputBufSize, &filled_size);
  227. (*actOutBufSize) += filled_size;
  228. outputBuf = &outputBuf[filled_size]; /* MISRA 18.4: Avoid pointer arithmetic */
  229. outputBufSize -= filled_size;
  230. if(err == ERR_NONE) {
  231. (*offset)++;
  232. }
  233. }
  234. if(err != ERR_NONE) {
  235. return ERR_AGAIN;
  236. }
  237. if((!sendCrc && (*offset == length)) || (sendCrc && (*offset == (length + 2U)))) {
  238. *outputBuf = eof;
  239. (*actOutBufSize)++;
  240. outputBufSize--;
  241. outputBuf++;
  242. } else {
  243. return ERR_AGAIN;
  244. }
  245. return err;
  246. }
  247. ReturnCode iso15693VICCDecode(
  248. const uint8_t* inBuf,
  249. uint16_t inBufLen,
  250. uint8_t* outBuf,
  251. uint16_t outBufLen,
  252. uint16_t* outBufPos,
  253. uint16_t* bitsBeforeCol,
  254. uint16_t ignoreBits,
  255. bool picopassMode) {
  256. ReturnCode err = ERR_NONE;
  257. uint16_t crc;
  258. uint16_t mp; /* Current bit position in manchester bit inBuf*/
  259. uint16_t bp; /* Current bit position in outBuf */
  260. *bitsBeforeCol = 0;
  261. *outBufPos = 0;
  262. /* first check for valid SOF. Since it starts with 3 unmodulated pulses it is 0x17. */
  263. if((inBuf[0] & 0x1fU) != 0x17U) {
  264. ISO_15693_DEBUG("0x%x\n", iso15693PhyBitBuffer[0]);
  265. return ERR_FRAMING;
  266. }
  267. ISO_15693_DEBUG("SOF\n");
  268. if(outBufLen == 0U) {
  269. return ERR_NONE;
  270. }
  271. mp = 5; /* 5 bits were SOF, now manchester starts: 2 bits per payload bit */
  272. bp = 0;
  273. ST_MEMSET(outBuf, 0, outBufLen);
  274. if(inBufLen == 0U) {
  275. return ERR_CRC;
  276. }
  277. for(; mp < ((inBufLen * 8U) - 2U); mp += 2U) {
  278. bool isEOF = false;
  279. uint8_t man;
  280. man = (inBuf[mp / 8U] >> (mp % 8U)) & 0x1U;
  281. man |= ((inBuf[(mp + 1U) / 8U] >> ((mp + 1U) % 8U)) & 0x1U) << 1;
  282. if(1U == man) {
  283. bp++;
  284. }
  285. if(2U == man) {
  286. outBuf[bp / 8U] = (uint8_t)(outBuf[bp / 8U] | (1U << (bp % 8U))); /* MISRA 10.3 */
  287. bp++;
  288. }
  289. if((bp % 8U) == 0U) { /* Check for EOF */
  290. ISO_15693_DEBUG("ceof %hhx %hhx\n", inBuf[mp / 8U], inBuf[mp / 8 + 1]);
  291. if(((inBuf[mp / 8U] & 0xe0U) == 0xa0U) &&
  292. (inBuf[(mp / 8U) + 1U] == 0x03U)) { /* Now we know that it was 10111000 = EOF */
  293. ISO_15693_DEBUG("EOF\n");
  294. isEOF = true;
  295. }
  296. }
  297. if(((0U == man) || (3U == man)) && !isEOF) {
  298. if(bp >= ignoreBits) {
  299. err = ERR_RF_COLLISION;
  300. } else {
  301. /* ignored collision: leave as 0 */
  302. bp++;
  303. }
  304. }
  305. if((bp >= (outBufLen * 8U)) || (err == ERR_RF_COLLISION) ||
  306. isEOF) { /* Don't write beyond the end */
  307. break;
  308. }
  309. }
  310. *outBufPos = (bp / 8U);
  311. *bitsBeforeCol = bp;
  312. if(err != ERR_NONE) {
  313. return err;
  314. }
  315. if((bp % 8U) != 0U) {
  316. return ERR_CRC;
  317. }
  318. if(*outBufPos > 2U) {
  319. /* finally, check crc */
  320. ISO_15693_DEBUG("Calculate CRC, val: 0x%x, outBufLen: ", *outBuf);
  321. ISO_15693_DEBUG("0x%x ", *outBufPos - 2);
  322. crc = rfalCrcCalculateCcitt(((picopassMode) ? 0xE012U : 0xFFFFU), outBuf, *outBufPos - 2U);
  323. crc = (uint16_t)((picopassMode) ? crc : ~crc);
  324. if(((crc & 0xffU) == outBuf[*outBufPos - 2U]) &&
  325. (((crc >> 8U) & 0xffU) == outBuf[*outBufPos - 1U])) {
  326. err = ERR_NONE;
  327. ISO_15693_DEBUG("OK\n");
  328. } else {
  329. ISO_15693_DEBUG("error! Expected: 0x%x, got ", crc);
  330. ISO_15693_DEBUG("0x%hhx 0x%hhx\n", outBuf[*outBufPos - 2], outBuf[*outBufPos - 1]);
  331. err = ERR_CRC;
  332. }
  333. } else {
  334. err = ERR_CRC;
  335. }
  336. return err;
  337. }
  338. /*
  339. ******************************************************************************
  340. * LOCAL FUNCTIONS
  341. ******************************************************************************
  342. */
  343. /*!
  344. *****************************************************************************
  345. * \brief Perform 1 of 4 coding and send coded data
  346. *
  347. * This function takes \a length bytes from \a buffer, perform 1 of 4 coding
  348. * (see ISO15693-2 specification) and sends the data using stream mode.
  349. *
  350. * \param[in] sendSof : send SOF prior to data.
  351. * \param[in] buffer : data to send.
  352. * \param[in] length : number of bytes to send.
  353. *
  354. * \return ERR_IO : Error during communication.
  355. * \return ERR_NONE : No error.
  356. *
  357. *****************************************************************************
  358. */
  359. static ReturnCode iso15693PhyVCDCode1Of4(
  360. const uint8_t data,
  361. uint8_t* outbuffer,
  362. uint16_t maxOutBufLen,
  363. uint16_t* outBufLen) {
  364. uint8_t tmp;
  365. ReturnCode err = ERR_NONE;
  366. uint16_t a;
  367. uint8_t* outbuf = outbuffer;
  368. *outBufLen = 0;
  369. if(maxOutBufLen < 4U) {
  370. return ERR_NOMEM;
  371. }
  372. tmp = data;
  373. for(a = 0; a < 4U; a++) {
  374. switch(tmp & 0x3U) {
  375. case 0:
  376. *outbuf = ISO15693_DAT_00_1_4;
  377. break;
  378. case 1:
  379. *outbuf = ISO15693_DAT_01_1_4;
  380. break;
  381. case 2:
  382. *outbuf = ISO15693_DAT_10_1_4;
  383. break;
  384. case 3:
  385. *outbuf = ISO15693_DAT_11_1_4;
  386. break;
  387. default:
  388. /* MISRA 16.4: mandatory default statement */
  389. break;
  390. }
  391. outbuf++;
  392. (*outBufLen)++;
  393. tmp >>= 2;
  394. }
  395. return err;
  396. }
  397. /*!
  398. *****************************************************************************
  399. * \brief Perform 1 of 256 coding and send coded data
  400. *
  401. * This function takes \a length bytes from \a buffer, perform 1 of 256 coding
  402. * (see ISO15693-2 specification) and sends the data using stream mode.
  403. * \note This function sends SOF prior to the data.
  404. *
  405. * \param[in] sendSof : send SOF prior to data.
  406. * \param[in] buffer : data to send.
  407. * \param[in] length : number of bytes to send.
  408. *
  409. * \return ERR_IO : Error during communication.
  410. * \return ERR_NONE : No error.
  411. *
  412. *****************************************************************************
  413. */
  414. static ReturnCode iso15693PhyVCDCode1Of256(
  415. const uint8_t data,
  416. uint8_t* outbuffer,
  417. uint16_t maxOutBufLen,
  418. uint16_t* outBufLen) {
  419. uint8_t tmp;
  420. ReturnCode err = ERR_NONE;
  421. uint16_t a;
  422. uint8_t* outbuf = outbuffer;
  423. *outBufLen = 0;
  424. if(maxOutBufLen < 64U) {
  425. return ERR_NOMEM;
  426. }
  427. tmp = data;
  428. for(a = 0; a < 64U; a++) {
  429. switch(tmp) {
  430. case 0:
  431. *outbuf = ISO15693_DAT_SLOT0_1_256;
  432. break;
  433. case 1:
  434. *outbuf = ISO15693_DAT_SLOT1_1_256;
  435. break;
  436. case 2:
  437. *outbuf = ISO15693_DAT_SLOT2_1_256;
  438. break;
  439. case 3:
  440. *outbuf = ISO15693_DAT_SLOT3_1_256;
  441. break;
  442. default:
  443. *outbuf = 0;
  444. break;
  445. }
  446. outbuf++;
  447. (*outBufLen)++;
  448. tmp -= 4U;
  449. }
  450. return err;
  451. }
  452. #endif /* RFAL_FEATURE_NFCV */