st25r3916.c 30 KB

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