st25r3916.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  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: ST25R3916 firmware
  23. * Revision:
  24. * LANGUAGE: ISO C99
  25. */
  26. /*! \file
  27. *
  28. * \author Gustavo Patricio
  29. *
  30. * \brief ST25R3916 high level interface
  31. *
  32. */
  33. /*
  34. ******************************************************************************
  35. * INCLUDES
  36. ******************************************************************************
  37. */
  38. #include "st25r3916.h"
  39. #include "st25r3916_com.h"
  40. #include "st25r3916_led.h"
  41. #include "st25r3916_irq.h"
  42. #include "utils.h"
  43. /*
  44. ******************************************************************************
  45. * LOCAL DEFINES
  46. ******************************************************************************
  47. */
  48. #define ST25R3916_SUPPLY_THRESHOLD \
  49. 3600U /*!< Power supply measure threshold between 3.3V or 5V */
  50. #define ST25R3916_NRT_MAX \
  51. 0xFFFFU /*!< Max Register value of NRT */
  52. #define ST25R3916_TOUT_MEASURE_VDD \
  53. 100U /*!< Max duration time of Measure Power Supply command Datasheet: 25us */
  54. #define ST25R3916_TOUT_MEASURE_AMPLITUDE \
  55. 10U /*!< Max duration time of Measure Amplitude command Datasheet: 25us */
  56. #define ST25R3916_TOUT_MEASURE_PHASE \
  57. 10U /*!< Max duration time of Measure Phase command Datasheet: 25us */
  58. #define ST25R3916_TOUT_MEASURE_CAPACITANCE \
  59. 10U /*!< Max duration time of Measure Capacitance command Datasheet: 25us */
  60. #define ST25R3916_TOUT_CALIBRATE_CAP_SENSOR \
  61. 4U /*!< Max duration Calibrate Capacitive Sensor command Datasheet: 3ms */
  62. #define ST25R3916_TOUT_ADJUST_REGULATORS \
  63. 6U /*!< Max duration time of Adjust Regulators command Datasheet: 5ms */
  64. #define ST25R3916_TOUT_CA \
  65. 10U /*!< Max duration time of Collision Avoidance command */
  66. #define ST25R3916_TEST_REG_PATTERN \
  67. 0x33U /*!< Register Read Write test pattern used during selftest */
  68. #define ST25R3916_TEST_WU_TOUT \
  69. 12U /*!< Timeout used on WU timer during self test */
  70. #define ST25R3916_TEST_TMR_TOUT \
  71. 20U /*!< Timeout used during self test */
  72. #define ST25R3916_TEST_TMR_TOUT_DELTA \
  73. 2U /*!< Timeout used during self test */
  74. #define ST25R3916_TEST_TMR_TOUT_8FC \
  75. (ST25R3916_TEST_TMR_TOUT * 16950U) /*!< Timeout in 8/fc */
  76. /*
  77. ******************************************************************************
  78. * LOCAL CONSTANTS
  79. ******************************************************************************
  80. */
  81. /*
  82. ******************************************************************************
  83. * LOCAL VARIABLES
  84. ******************************************************************************
  85. */
  86. static uint32_t gST25R3916NRT_64fcs;
  87. /*
  88. ******************************************************************************
  89. * LOCAL FUNCTION PROTOTYPES
  90. ******************************************************************************
  91. */
  92. /*
  93. ******************************************************************************
  94. * LOCAL FUNCTION
  95. ******************************************************************************
  96. */
  97. ReturnCode st25r3916ExecuteCommandAndGetResult(
  98. uint8_t cmd,
  99. uint8_t resReg,
  100. uint8_t tout,
  101. uint8_t* result) {
  102. /* Clear and enable Direct Command interrupt */
  103. st25r3916GetInterrupt(ST25R3916_IRQ_MASK_DCT);
  104. st25r3916EnableInterrupts(ST25R3916_IRQ_MASK_DCT);
  105. st25r3916ExecuteCommand(cmd);
  106. st25r3916WaitForInterruptsTimed(ST25R3916_IRQ_MASK_DCT, tout);
  107. st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_DCT);
  108. /* After execution read out the result if the pointer is not NULL */
  109. if(result != NULL) {
  110. st25r3916ReadRegister(resReg, result);
  111. }
  112. return ERR_NONE;
  113. }
  114. /*
  115. ******************************************************************************
  116. * GLOBAL FUNCTIONS
  117. ******************************************************************************
  118. */
  119. ReturnCode st25r3916Initialize(void) {
  120. uint16_t vdd_mV;
  121. ReturnCode ret;
  122. /* Set default state on the ST25R3916 */
  123. st25r3916ExecuteCommand(ST25R3916_CMD_SET_DEFAULT);
  124. #ifndef RFAL_USE_I2C
  125. /* Increase MISO driving level as SPI can go up to 10MHz */
  126. st25r3916WriteRegister(ST25R3916_REG_IO_CONF2, ST25R3916_REG_IO_CONF2_io_drv_lvl);
  127. #endif /* RFAL_USE_I2C */
  128. if(!st25r3916CheckChipID(NULL)) {
  129. platformErrorHandle();
  130. return ERR_HW_MISMATCH;
  131. }
  132. st25r3916InitInterrupts();
  133. st25r3916ledInit();
  134. gST25R3916NRT_64fcs = 0;
  135. #ifndef RFAL_USE_I2C
  136. /* Enable pull downs on MISO line */
  137. st25r3916SetRegisterBits(
  138. ST25R3916_REG_IO_CONF2,
  139. (ST25R3916_REG_IO_CONF2_miso_pd1 | ST25R3916_REG_IO_CONF2_miso_pd2));
  140. #endif /* RFAL_USE_I2C */
  141. /* Disable internal overheat protection */
  142. st25r3916ChangeTestRegisterBits(0x04, 0x10, 0x10);
  143. #ifdef ST25R_SELFTEST
  144. /******************************************************************************
  145. * Check communication interface:
  146. * - write a pattern in a register
  147. * - reads back the register value
  148. * - return ERR_IO in case the read value is different
  149. */
  150. st25r3916WriteRegister(ST25R3916_REG_BIT_RATE, ST25R3916_TEST_REG_PATTERN);
  151. if(!st25r3916CheckReg(
  152. ST25R3916_REG_BIT_RATE,
  153. (ST25R3916_REG_BIT_RATE_rxrate_mask | ST25R3916_REG_BIT_RATE_txrate_mask),
  154. ST25R3916_TEST_REG_PATTERN)) {
  155. platformErrorHandle();
  156. return ERR_IO;
  157. }
  158. /* Restore default value */
  159. st25r3916WriteRegister(ST25R3916_REG_BIT_RATE, 0x00);
  160. /*
  161. * Check IRQ Handling:
  162. * - use the Wake-up timer to trigger an IRQ
  163. * - wait the Wake-up timer interrupt
  164. * - return ERR_TIMEOUT when the Wake-up timer interrupt is not received
  165. */
  166. st25r3916WriteRegister(
  167. ST25R3916_REG_WUP_TIMER_CONTROL,
  168. ST25R3916_REG_WUP_TIMER_CONTROL_wur | ST25R3916_REG_WUP_TIMER_CONTROL_wto);
  169. st25r3916EnableInterrupts(ST25R3916_IRQ_MASK_WT);
  170. st25r3916ExecuteCommand(ST25R3916_CMD_START_WUP_TIMER);
  171. if(st25r3916WaitForInterruptsTimed(ST25R3916_IRQ_MASK_WT, ST25R3916_TEST_WU_TOUT) == 0U) {
  172. platformErrorHandle();
  173. return ERR_TIMEOUT;
  174. }
  175. st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_WT);
  176. st25r3916WriteRegister(ST25R3916_REG_WUP_TIMER_CONTROL, 0U);
  177. /*******************************************************************************/
  178. #endif /* ST25R_SELFTEST */
  179. /* Enable Oscillator and wait until it gets stable */
  180. ret = st25r3916OscOn();
  181. if(ret != ERR_NONE) {
  182. platformErrorHandle();
  183. return ret;
  184. }
  185. /* Measure VDD and set sup3V bit according to Power supplied */
  186. vdd_mV = st25r3916MeasureVoltage(ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd);
  187. st25r3916ChangeRegisterBits(
  188. ST25R3916_REG_IO_CONF2,
  189. ST25R3916_REG_IO_CONF2_sup3V,
  190. ((vdd_mV < ST25R3916_SUPPLY_THRESHOLD) ? ST25R3916_REG_IO_CONF2_sup3V_3V :
  191. ST25R3916_REG_IO_CONF2_sup3V_5V));
  192. /* Make sure Transmitter and Receiver are disabled */
  193. st25r3916TxRxOff();
  194. #ifdef ST25R_SELFTEST_TIMER
  195. /******************************************************************************
  196. * Check SW timer operation :
  197. * - use the General Purpose timer to measure an amount of time
  198. * - test whether an interrupt is seen when less time was given
  199. * - test whether an interrupt is seen when sufficient time was given
  200. */
  201. st25r3916EnableInterrupts(ST25R3916_IRQ_MASK_GPE);
  202. st25r3916SetStartGPTimer(
  203. (uint16_t)ST25R3916_TEST_TMR_TOUT_8FC, ST25R3916_REG_TIMER_EMV_CONTROL_gptc_no_trigger);
  204. if(st25r3916WaitForInterruptsTimed(
  205. ST25R3916_IRQ_MASK_GPE, (ST25R3916_TEST_TMR_TOUT - ST25R3916_TEST_TMR_TOUT_DELTA)) !=
  206. 0U) {
  207. platformErrorHandle();
  208. return ERR_SYSTEM;
  209. }
  210. /* Stop all activities to stop the GP timer */
  211. st25r3916ExecuteCommand(ST25R3916_CMD_STOP);
  212. st25r3916ClearAndEnableInterrupts(ST25R3916_IRQ_MASK_GPE);
  213. st25r3916SetStartGPTimer(
  214. (uint16_t)ST25R3916_TEST_TMR_TOUT_8FC, ST25R3916_REG_TIMER_EMV_CONTROL_gptc_no_trigger);
  215. if(st25r3916WaitForInterruptsTimed(
  216. ST25R3916_IRQ_MASK_GPE, (ST25R3916_TEST_TMR_TOUT + ST25R3916_TEST_TMR_TOUT_DELTA)) ==
  217. 0U) {
  218. platformErrorHandle();
  219. return ERR_SYSTEM;
  220. }
  221. /* Stop all activities to stop the GP timer */
  222. st25r3916ExecuteCommand(ST25R3916_CMD_STOP);
  223. /*******************************************************************************/
  224. #endif /* ST25R_SELFTEST_TIMER */
  225. /* After reset all interrupts are enabled, so disable them at first */
  226. st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_ALL);
  227. /* And clear them, just to be sure */
  228. st25r3916ClearInterrupts();
  229. return ERR_NONE;
  230. }
  231. /*******************************************************************************/
  232. void st25r3916Deinitialize(void) {
  233. st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_ALL);
  234. /* Disabe Tx and Rx, Keep OSC On */
  235. st25r3916TxRxOff();
  236. return;
  237. }
  238. /*******************************************************************************/
  239. ReturnCode st25r3916OscOn(void) {
  240. /* Check if oscillator is already turned on and stable */
  241. /* Use ST25R3916_REG_OP_CONTROL_en instead of ST25R3916_REG_AUX_DISPLAY_osc_ok to be on the safe side */
  242. if(!st25r3916CheckReg(
  243. ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_en, ST25R3916_REG_OP_CONTROL_en)) {
  244. /* Clear any eventual previous oscillator IRQ */
  245. st25r3916GetInterrupt(ST25R3916_IRQ_MASK_OSC);
  246. /* Enable oscillator frequency stable interrupt */
  247. st25r3916EnableInterrupts(ST25R3916_IRQ_MASK_OSC);
  248. /* Enable oscillator and regulator output */
  249. st25r3916SetRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_en);
  250. /* Wait for the oscillator interrupt */
  251. st25r3916WaitForInterruptsTimed(ST25R3916_IRQ_MASK_OSC, ST25R3916_TOUT_OSC_STABLE);
  252. st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_OSC);
  253. }
  254. if(!st25r3916CheckReg(
  255. ST25R3916_REG_AUX_DISPLAY,
  256. ST25R3916_REG_AUX_DISPLAY_osc_ok,
  257. ST25R3916_REG_AUX_DISPLAY_osc_ok)) {
  258. return ERR_SYSTEM;
  259. }
  260. return ERR_NONE;
  261. }
  262. /*******************************************************************************/
  263. uint8_t st25r3916MeasurePowerSupply(uint8_t mpsv) {
  264. uint8_t result;
  265. /* Set the source of direct command: Measure Power Supply Voltage */
  266. st25r3916ChangeRegisterBits(
  267. ST25R3916_REG_REGULATOR_CONTROL, ST25R3916_REG_REGULATOR_CONTROL_mpsv_mask, mpsv);
  268. /* Execute command: Measure Power Supply Voltage */
  269. st25r3916ExecuteCommandAndGetResult(
  270. ST25R3916_CMD_MEASURE_VDD, ST25R3916_REG_AD_RESULT, ST25R3916_TOUT_MEASURE_VDD, &result);
  271. return result;
  272. }
  273. /*******************************************************************************/
  274. uint16_t st25r3916MeasureVoltage(uint8_t mpsv) {
  275. uint8_t result;
  276. uint16_t mV;
  277. result = st25r3916MeasurePowerSupply(mpsv);
  278. /* Convert cmd output into mV (each step represents 23.4 mV )*/
  279. mV = ((uint16_t)result) * 23U;
  280. mV += (((((uint16_t)result) * 4U) + 5U) / 10U);
  281. return mV;
  282. }
  283. /*******************************************************************************/
  284. ReturnCode st25r3916AdjustRegulators(uint16_t* result_mV) {
  285. uint8_t result;
  286. /* Reset logic and set regulated voltages to be defined by result of Adjust Regulators command */
  287. st25r3916SetRegisterBits(
  288. ST25R3916_REG_REGULATOR_CONTROL, ST25R3916_REG_REGULATOR_CONTROL_reg_s);
  289. st25r3916ClrRegisterBits(
  290. ST25R3916_REG_REGULATOR_CONTROL, ST25R3916_REG_REGULATOR_CONTROL_reg_s);
  291. /* Execute Adjust regulators cmd and retrieve result */
  292. st25r3916ExecuteCommandAndGetResult(
  293. ST25R3916_CMD_ADJUST_REGULATORS,
  294. ST25R3916_REG_REGULATOR_RESULT,
  295. ST25R3916_TOUT_ADJUST_REGULATORS,
  296. &result);
  297. /* Calculate result in mV */
  298. result >>= ST25R3916_REG_REGULATOR_RESULT_reg_shift;
  299. if(result_mV != NULL) {
  300. if(st25r3916CheckReg(
  301. ST25R3916_REG_IO_CONF2,
  302. ST25R3916_REG_IO_CONF2_sup3V,
  303. ST25R3916_REG_IO_CONF2_sup3V)) {
  304. result = MIN(
  305. result,
  306. (uint8_t)(result - 5U)); /* In 3.3V mode [0,4] are not used */
  307. *result_mV = 2400U; /* Minimum regulated voltage 2.4V in case of 3.3V supply */
  308. } else {
  309. *result_mV = 3600U; /* Minimum regulated voltage 3.6V in case of 5V supply */
  310. }
  311. *result_mV +=
  312. (uint16_t)result * 100U; /* 100mV steps in both 3.3V and 5V supply */
  313. }
  314. return ERR_NONE;
  315. }
  316. /*******************************************************************************/
  317. ReturnCode st25r3916MeasureAmplitude(uint8_t* result) {
  318. return st25r3916ExecuteCommandAndGetResult(
  319. ST25R3916_CMD_MEASURE_AMPLITUDE,
  320. ST25R3916_REG_AD_RESULT,
  321. ST25R3916_TOUT_MEASURE_AMPLITUDE,
  322. result);
  323. }
  324. /*******************************************************************************/
  325. ReturnCode st25r3916MeasurePhase(uint8_t* result) {
  326. return st25r3916ExecuteCommandAndGetResult(
  327. ST25R3916_CMD_MEASURE_PHASE, ST25R3916_REG_AD_RESULT, ST25R3916_TOUT_MEASURE_PHASE, result);
  328. }
  329. /*******************************************************************************/
  330. ReturnCode st25r3916MeasureCapacitance(uint8_t* result) {
  331. return st25r3916ExecuteCommandAndGetResult(
  332. ST25R3916_CMD_MEASURE_CAPACITANCE,
  333. ST25R3916_REG_AD_RESULT,
  334. ST25R3916_TOUT_MEASURE_CAPACITANCE,
  335. result);
  336. }
  337. /*******************************************************************************/
  338. ReturnCode st25r3916CalibrateCapacitiveSensor(uint8_t* result) {
  339. ReturnCode ret;
  340. uint8_t res;
  341. /* Clear Manual calibration values to enable automatic calibration mode */
  342. st25r3916ClrRegisterBits(
  343. ST25R3916_REG_CAP_SENSOR_CONTROL, ST25R3916_REG_CAP_SENSOR_CONTROL_cs_mcal_mask);
  344. /* Execute automatic calibration */
  345. ret = st25r3916ExecuteCommandAndGetResult(
  346. ST25R3916_CMD_CALIBRATE_C_SENSOR,
  347. ST25R3916_REG_CAP_SENSOR_RESULT,
  348. ST25R3916_TOUT_CALIBRATE_CAP_SENSOR,
  349. &res);
  350. /* Check wether the calibration was successull */
  351. if(((res & ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_end) !=
  352. ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_end) ||
  353. ((res & ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_err) ==
  354. ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_err) ||
  355. (ret != ERR_NONE)) {
  356. return ERR_IO;
  357. }
  358. if(result != NULL) {
  359. (*result) = (uint8_t)(res >> ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_shift);
  360. }
  361. return ERR_NONE;
  362. }
  363. /*******************************************************************************/
  364. ReturnCode st25r3916SetBitrate(uint8_t txrate, uint8_t rxrate) {
  365. uint8_t reg;
  366. st25r3916ReadRegister(ST25R3916_REG_BIT_RATE, &reg);
  367. if(rxrate != ST25R3916_BR_DO_NOT_SET) {
  368. if(rxrate > ST25R3916_BR_848) {
  369. return ERR_PARAM;
  370. }
  371. reg = (uint8_t)(reg & ~ST25R3916_REG_BIT_RATE_rxrate_mask); /* MISRA 10.3 */
  372. reg |= rxrate << ST25R3916_REG_BIT_RATE_rxrate_shift;
  373. }
  374. if(txrate != ST25R3916_BR_DO_NOT_SET) {
  375. if(txrate > ST25R3916_BR_6780) {
  376. return ERR_PARAM;
  377. }
  378. reg = (uint8_t)(reg & ~ST25R3916_REG_BIT_RATE_txrate_mask); /* MISRA 10.3 */
  379. reg |= txrate << ST25R3916_REG_BIT_RATE_txrate_shift;
  380. }
  381. return st25r3916WriteRegister(ST25R3916_REG_BIT_RATE, reg);
  382. }
  383. /*******************************************************************************/
  384. ReturnCode st25r3916PerformCollisionAvoidance(
  385. uint8_t FieldONCmd,
  386. uint8_t pdThreshold,
  387. uint8_t caThreshold,
  388. uint8_t nTRFW) {
  389. uint8_t treMask;
  390. uint32_t irqs;
  391. ReturnCode err;
  392. if((FieldONCmd != ST25R3916_CMD_INITIAL_RF_COLLISION) &&
  393. (FieldONCmd != ST25R3916_CMD_RESPONSE_RF_COLLISION_N)) {
  394. return ERR_PARAM;
  395. }
  396. err = ERR_INTERNAL;
  397. /* Check if new thresholds are to be applied */
  398. if((pdThreshold != ST25R3916_THRESHOLD_DO_NOT_SET) ||
  399. (caThreshold != ST25R3916_THRESHOLD_DO_NOT_SET)) {
  400. treMask = 0;
  401. if(pdThreshold != ST25R3916_THRESHOLD_DO_NOT_SET) {
  402. treMask |= ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_mask;
  403. }
  404. if(caThreshold != ST25R3916_THRESHOLD_DO_NOT_SET) {
  405. treMask |= ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_mask;
  406. }
  407. /* Set Detection Threshold and|or Collision Avoidance Threshold */
  408. st25r3916ChangeRegisterBits(
  409. ST25R3916_REG_FIELD_THRESHOLD_ACTV,
  410. treMask,
  411. (pdThreshold & ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_mask) |
  412. (caThreshold & ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_mask));
  413. }
  414. /* Set n x TRFW */
  415. st25r3916ChangeRegisterBits(ST25R3916_REG_AUX, ST25R3916_REG_AUX_nfc_n_mask, nTRFW);
  416. /*******************************************************************************/
  417. /* Enable and clear CA specific interrupts and execute command */
  418. st25r3916GetInterrupt(
  419. (ST25R3916_IRQ_MASK_CAC | ST25R3916_IRQ_MASK_CAT | ST25R3916_IRQ_MASK_APON));
  420. st25r3916EnableInterrupts(
  421. (ST25R3916_IRQ_MASK_CAC | ST25R3916_IRQ_MASK_CAT | ST25R3916_IRQ_MASK_APON));
  422. st25r3916ExecuteCommand(FieldONCmd);
  423. /*******************************************************************************/
  424. /* Wait for initial APON interrupt, indicating anticollision avoidance done and ST25R3916's
  425. * field is now on, or a CAC indicating a collision */
  426. irqs = st25r3916WaitForInterruptsTimed(
  427. (ST25R3916_IRQ_MASK_CAC | ST25R3916_IRQ_MASK_APON), ST25R3916_TOUT_CA);
  428. if((ST25R3916_IRQ_MASK_CAC & irqs) != 0U) /* Collision occurred */
  429. {
  430. err = ERR_RF_COLLISION;
  431. } else if((ST25R3916_IRQ_MASK_APON & irqs) != 0U) {
  432. /* After APON wait for CAT interrupt, indication field was switched on minimum guard time has been fulfilled */
  433. irqs = st25r3916WaitForInterruptsTimed((ST25R3916_IRQ_MASK_CAT), ST25R3916_TOUT_CA);
  434. if((ST25R3916_IRQ_MASK_CAT & irqs) != 0U) /* No Collision detected, Field On */
  435. {
  436. err = ERR_NONE;
  437. }
  438. } else {
  439. /* MISRA 15.7 - Empty else */
  440. }
  441. /* Clear any previous External Field events and disable CA specific interrupts */
  442. st25r3916GetInterrupt((ST25R3916_IRQ_MASK_EOF | ST25R3916_IRQ_MASK_EON));
  443. st25r3916DisableInterrupts(
  444. (ST25R3916_IRQ_MASK_CAC | ST25R3916_IRQ_MASK_CAT | ST25R3916_IRQ_MASK_APON));
  445. return err;
  446. }
  447. /*******************************************************************************/
  448. void st25r3916SetNumTxBits(uint16_t nBits) {
  449. st25r3916WriteRegister(ST25R3916_REG_NUM_TX_BYTES2, (uint8_t)((nBits >> 0) & 0xFFU));
  450. st25r3916WriteRegister(ST25R3916_REG_NUM_TX_BYTES1, (uint8_t)((nBits >> 8) & 0xFFU));
  451. }
  452. /*******************************************************************************/
  453. uint16_t st25r3916GetNumFIFOBytes(void) {
  454. uint8_t reg;
  455. uint16_t result;
  456. st25r3916ReadRegister(ST25R3916_REG_FIFO_STATUS2, &reg);
  457. reg =
  458. ((reg & ST25R3916_REG_FIFO_STATUS2_fifo_b_mask) >>
  459. ST25R3916_REG_FIFO_STATUS2_fifo_b_shift);
  460. result = ((uint16_t)reg << 8);
  461. st25r3916ReadRegister(ST25R3916_REG_FIFO_STATUS1, &reg);
  462. result |= (((uint16_t)reg) & 0x00FFU);
  463. return result;
  464. }
  465. /*******************************************************************************/
  466. uint8_t st25r3916GetNumFIFOLastBits(void) {
  467. uint8_t reg;
  468. st25r3916ReadRegister(ST25R3916_REG_FIFO_STATUS2, &reg);
  469. return (
  470. (reg & ST25R3916_REG_FIFO_STATUS2_fifo_lb_mask) >>
  471. ST25R3916_REG_FIFO_STATUS2_fifo_lb_shift);
  472. }
  473. /*******************************************************************************/
  474. uint32_t st25r3916GetNoResponseTime(void) {
  475. return gST25R3916NRT_64fcs;
  476. }
  477. /*******************************************************************************/
  478. ReturnCode st25r3916SetNoResponseTime(uint32_t nrt_64fcs) {
  479. ReturnCode err;
  480. uint8_t nrt_step;
  481. uint32_t tmpNRT;
  482. tmpNRT = nrt_64fcs; /* MISRA 17.8 */
  483. err = ERR_NONE;
  484. gST25R3916NRT_64fcs = tmpNRT; /* Store given NRT value in 64/fc into local var */
  485. nrt_step =
  486. ST25R3916_REG_TIMER_EMV_CONTROL_nrt_step_64fc; /* Set default NRT in steps of 64/fc */
  487. if(tmpNRT > ST25R3916_NRT_MAX) /* Check if the given NRT value fits using 64/fc steps */
  488. {
  489. nrt_step =
  490. ST25R3916_REG_TIMER_EMV_CONTROL_nrt_step_4096_fc; /* If not, change NRT set to 4096/fc */
  491. tmpNRT = ((tmpNRT + 63U) / 64U); /* Calculate number of steps in 4096/fc */
  492. if(tmpNRT > ST25R3916_NRT_MAX) /* Check if the NRT value fits using 64/fc steps */
  493. {
  494. tmpNRT = ST25R3916_NRT_MAX; /* Assign the maximum possible */
  495. err = ERR_PARAM; /* Signal parameter error */
  496. }
  497. gST25R3916NRT_64fcs = (64U * tmpNRT);
  498. }
  499. /* Set the ST25R3916 NRT step units and the value */
  500. st25r3916ChangeRegisterBits(
  501. ST25R3916_REG_TIMER_EMV_CONTROL, ST25R3916_REG_TIMER_EMV_CONTROL_nrt_step, nrt_step);
  502. st25r3916WriteRegister(ST25R3916_REG_NO_RESPONSE_TIMER1, (uint8_t)(tmpNRT >> 8U));
  503. st25r3916WriteRegister(ST25R3916_REG_NO_RESPONSE_TIMER2, (uint8_t)(tmpNRT & 0xFFU));
  504. return err;
  505. }
  506. /*******************************************************************************/
  507. ReturnCode st25r3916SetStartNoResponseTimer(uint32_t nrt_64fcs) {
  508. ReturnCode err;
  509. err = st25r3916SetNoResponseTime(nrt_64fcs);
  510. if(err == ERR_NONE) {
  511. st25r3916ExecuteCommand(ST25R3916_CMD_START_NO_RESPONSE_TIMER);
  512. }
  513. return err;
  514. }
  515. /*******************************************************************************/
  516. void st25r3916SetGPTime(uint16_t gpt_8fcs) {
  517. st25r3916WriteRegister(ST25R3916_REG_GPT1, (uint8_t)(gpt_8fcs >> 8));
  518. st25r3916WriteRegister(ST25R3916_REG_GPT2, (uint8_t)(gpt_8fcs & 0xFFU));
  519. }
  520. /*******************************************************************************/
  521. ReturnCode st25r3916SetStartGPTimer(uint16_t gpt_8fcs, uint8_t trigger_source) {
  522. st25r3916SetGPTime(gpt_8fcs);
  523. st25r3916ChangeRegisterBits(
  524. ST25R3916_REG_TIMER_EMV_CONTROL,
  525. ST25R3916_REG_TIMER_EMV_CONTROL_gptc_mask,
  526. trigger_source);
  527. /* If there's no trigger source, start GPT immediately */
  528. if(trigger_source == ST25R3916_REG_TIMER_EMV_CONTROL_gptc_no_trigger) {
  529. st25r3916ExecuteCommand(ST25R3916_CMD_START_GP_TIMER);
  530. }
  531. return ERR_NONE;
  532. }
  533. /*******************************************************************************/
  534. bool st25r3916CheckChipID(uint8_t* rev) {
  535. uint8_t ID;
  536. ID = 0;
  537. st25r3916ReadRegister(ST25R3916_REG_IC_IDENTITY, &ID);
  538. /* Check if IC Identity Register contains ST25R3916's IC type code */
  539. if((ID & ST25R3916_REG_IC_IDENTITY_ic_type_mask) !=
  540. ST25R3916_REG_IC_IDENTITY_ic_type_st25r3916) {
  541. return false;
  542. }
  543. if(rev != NULL) {
  544. *rev = (ID & ST25R3916_REG_IC_IDENTITY_ic_rev_mask);
  545. }
  546. return true;
  547. }
  548. /*******************************************************************************/
  549. ReturnCode st25r3916GetRegsDump(t_st25r3916Regs* regDump) {
  550. uint8_t regIt;
  551. if(regDump == NULL) {
  552. return ERR_PARAM;
  553. }
  554. /* Dump Registers on space A */
  555. for(regIt = ST25R3916_REG_IO_CONF1; regIt <= ST25R3916_REG_IC_IDENTITY; regIt++) {
  556. st25r3916ReadRegister(regIt, &regDump->RsA[regIt]);
  557. }
  558. regIt = 0;
  559. /* Read non-consecutive Registers on space B */
  560. st25r3916ReadRegister(ST25R3916_REG_EMD_SUP_CONF, &regDump->RsB[regIt++]);
  561. st25r3916ReadRegister(ST25R3916_REG_SUBC_START_TIME, &regDump->RsB[regIt++]);
  562. st25r3916ReadRegister(ST25R3916_REG_P2P_RX_CONF, &regDump->RsB[regIt++]);
  563. st25r3916ReadRegister(ST25R3916_REG_CORR_CONF1, &regDump->RsB[regIt++]);
  564. st25r3916ReadRegister(ST25R3916_REG_CORR_CONF2, &regDump->RsB[regIt++]);
  565. st25r3916ReadRegister(ST25R3916_REG_SQUELCH_TIMER, &regDump->RsB[regIt++]);
  566. st25r3916ReadRegister(ST25R3916_REG_FIELD_ON_GT, &regDump->RsB[regIt++]);
  567. st25r3916ReadRegister(ST25R3916_REG_AUX_MOD, &regDump->RsB[regIt++]);
  568. st25r3916ReadRegister(ST25R3916_REG_TX_DRIVER_TIMING, &regDump->RsB[regIt++]);
  569. st25r3916ReadRegister(ST25R3916_REG_RES_AM_MOD, &regDump->RsB[regIt++]);
  570. st25r3916ReadRegister(ST25R3916_REG_TX_DRIVER_STATUS, &regDump->RsB[regIt++]);
  571. st25r3916ReadRegister(ST25R3916_REG_REGULATOR_RESULT, &regDump->RsB[regIt++]);
  572. st25r3916ReadRegister(ST25R3916_REG_OVERSHOOT_CONF1, &regDump->RsB[regIt++]);
  573. st25r3916ReadRegister(ST25R3916_REG_OVERSHOOT_CONF2, &regDump->RsB[regIt++]);
  574. st25r3916ReadRegister(ST25R3916_REG_UNDERSHOOT_CONF1, &regDump->RsB[regIt++]);
  575. st25r3916ReadRegister(ST25R3916_REG_UNDERSHOOT_CONF2, &regDump->RsB[regIt++]);
  576. return ERR_NONE;
  577. }
  578. /*******************************************************************************/
  579. bool st25r3916IsCmdValid(uint8_t cmd) {
  580. if(!((cmd >= ST25R3916_CMD_SET_DEFAULT) && (cmd <= ST25R3916_CMD_RESPONSE_RF_COLLISION_N)) &&
  581. !((cmd >= ST25R3916_CMD_GOTO_SENSE) && (cmd <= ST25R3916_CMD_GOTO_SLEEP)) &&
  582. !((cmd >= ST25R3916_CMD_MASK_RECEIVE_DATA) && (cmd <= ST25R3916_CMD_MEASURE_AMPLITUDE)) &&
  583. !((cmd >= ST25R3916_CMD_RESET_RXGAIN) && (cmd <= ST25R3916_CMD_ADJUST_REGULATORS)) &&
  584. !((cmd >= ST25R3916_CMD_CALIBRATE_DRIVER_TIMING) &&
  585. (cmd <= ST25R3916_CMD_START_PPON2_TIMER)) &&
  586. (cmd != ST25R3916_CMD_SPACE_B_ACCESS) && (cmd != ST25R3916_CMD_STOP_NRT)) {
  587. return false;
  588. }
  589. return true;
  590. }
  591. /*******************************************************************************/
  592. ReturnCode st25r3916StreamConfigure(const struct st25r3916StreamConfig* config) {
  593. uint8_t smd;
  594. uint8_t mode;
  595. smd = 0;
  596. if(config->useBPSK != 0U) {
  597. mode = ST25R3916_REG_MODE_om_bpsk_stream;
  598. if((config->din < 2U) || (config->din > 4U)) /* not in fc/4 .. fc/16 */
  599. {
  600. return ERR_PARAM;
  601. }
  602. smd |= ((4U - config->din) << ST25R3916_REG_STREAM_MODE_scf_shift);
  603. } else {
  604. mode = ST25R3916_REG_MODE_om_subcarrier_stream;
  605. if((config->din < 3U) || (config->din > 6U)) /* not in fc/8 .. fc/64 */
  606. {
  607. return ERR_PARAM;
  608. }
  609. smd |= ((6U - config->din) << ST25R3916_REG_STREAM_MODE_scf_shift);
  610. if(config->report_period_length == 0U) {
  611. return ERR_PARAM;
  612. }
  613. }
  614. if((config->dout < 1U) || (config->dout > 7U)) /* not in fc/2 .. fc/128 */
  615. {
  616. return ERR_PARAM;
  617. }
  618. smd |= (7U - config->dout) << ST25R3916_REG_STREAM_MODE_stx_shift;
  619. if(config->report_period_length > 3U) {
  620. return ERR_PARAM;
  621. }
  622. smd |= (config->report_period_length << ST25R3916_REG_STREAM_MODE_scp_shift);
  623. st25r3916WriteRegister(ST25R3916_REG_STREAM_MODE, smd);
  624. st25r3916ChangeRegisterBits(ST25R3916_REG_MODE, ST25R3916_REG_MODE_om_mask, mode);
  625. return ERR_NONE;
  626. }
  627. /*******************************************************************************/
  628. ReturnCode st25r3916GetRSSI(uint16_t* amRssi, uint16_t* pmRssi) {
  629. /*******************************************************************************/
  630. /* MISRA 8.9 An object should be defined at block scope if its identifier only appears in a single function */
  631. /*< ST25R3916 RSSI Display Reg values: 0 1 2 3 4 5 6 7 8 9 a b c d e f */
  632. static const uint16_t st25r3916Rssi2mV[] = {
  633. 0, 20, 27, 37, 52, 72, 99, 136, 190, 262, 357, 500, 686, 950, 1150, 1150};
  634. /* ST25R3916 2/3 stage gain reduction [dB] 0 0 0 0 0 3 6 9 12 15 18 na na na na na */
  635. static const uint16_t st25r3916Gain2Percent[] = {
  636. 100, 100, 100, 100, 100, 141, 200, 281, 398, 562, 794, 1, 1, 1, 1, 1};
  637. /*******************************************************************************/
  638. uint8_t rssi;
  639. uint8_t gainRed;
  640. st25r3916ReadRegister(ST25R3916_REG_RSSI_RESULT, &rssi);
  641. st25r3916ReadRegister(ST25R3916_REG_GAIN_RED_STATE, &gainRed);
  642. if(amRssi != NULL) {
  643. *amRssi =
  644. (uint16_t)(((uint32_t)st25r3916Rssi2mV[(rssi >> ST25R3916_REG_RSSI_RESULT_rssi_am_shift)] * (uint32_t)st25r3916Gain2Percent[(gainRed >> ST25R3916_REG_GAIN_RED_STATE_gs_am_shift)]) / 100U);
  645. }
  646. if(pmRssi != NULL) {
  647. *pmRssi =
  648. (uint16_t)(((uint32_t)st25r3916Rssi2mV[(rssi & ST25R3916_REG_RSSI_RESULT_rssi_pm_mask)] * (uint32_t)st25r3916Gain2Percent[(gainRed & ST25R3916_REG_GAIN_RED_STATE_gs_pm_mask)]) / 100U);
  649. }
  650. return ERR_NONE;
  651. }