1*150812a8SEvalZero /*
2*150812a8SEvalZero * Copyright (c) 2018, Nordic Semiconductor ASA
3*150812a8SEvalZero * All rights reserved.
4*150812a8SEvalZero *
5*150812a8SEvalZero * Redistribution and use in source and binary forms, with or without
6*150812a8SEvalZero * modification, are permitted provided that the following conditions are met:
7*150812a8SEvalZero *
8*150812a8SEvalZero * 1. Redistributions of source code must retain the above copyright notice, this
9*150812a8SEvalZero * list of conditions and the following disclaimer.
10*150812a8SEvalZero *
11*150812a8SEvalZero * 2. Redistributions in binary form must reproduce the above copyright
12*150812a8SEvalZero * notice, this list of conditions and the following disclaimer in the
13*150812a8SEvalZero * documentation and/or other materials provided with the distribution.
14*150812a8SEvalZero *
15*150812a8SEvalZero * 3. Neither the name of the copyright holder nor the names of its
16*150812a8SEvalZero * contributors may be used to endorse or promote products derived from this
17*150812a8SEvalZero * software without specific prior written permission.
18*150812a8SEvalZero *
19*150812a8SEvalZero * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20*150812a8SEvalZero * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*150812a8SEvalZero * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*150812a8SEvalZero * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23*150812a8SEvalZero * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*150812a8SEvalZero * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*150812a8SEvalZero * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*150812a8SEvalZero * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*150812a8SEvalZero * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*150812a8SEvalZero * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*150812a8SEvalZero * POSSIBILITY OF SUCH DAMAGE.
30*150812a8SEvalZero */
31*150812a8SEvalZero
32*150812a8SEvalZero #include <nrfx.h>
33*150812a8SEvalZero
34*150812a8SEvalZero #if NRFX_CHECK(NRFX_NFCT_ENABLED)
35*150812a8SEvalZero
36*150812a8SEvalZero #include <nrfx_nfct.h>
37*150812a8SEvalZero
38*150812a8SEvalZero #define NRFX_LOG_MODULE NFCT
39*150812a8SEvalZero #include <nrfx_log.h>
40*150812a8SEvalZero
41*150812a8SEvalZero #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || defined(NRF52840_XXAA)
42*150812a8SEvalZero #define USE_TIMER_WORKAROUND
43*150812a8SEvalZero #endif
44*150812a8SEvalZero
45*150812a8SEvalZero #ifdef USE_TIMER_WORKAROUND
46*150812a8SEvalZero #include <nrfx_timer.h>
47*150812a8SEvalZero
48*150812a8SEvalZero typedef struct
49*150812a8SEvalZero {
50*150812a8SEvalZero const nrfx_timer_t timer; /**< Timer instance that supports the correct NFC field detection. */
51*150812a8SEvalZero #ifdef NRF52840_XXAA
52*150812a8SEvalZero bool fieldevents_filter_active; /**< Flag that indicates that the field events are ignored. */
53*150812a8SEvalZero bool is_hfclk_on; /**< HFCLK has started - one of the NFC activation conditions. */
54*150812a8SEvalZero bool is_delayed; /**< Required time delay has passed - one of the NFC activation conditions. */
55*150812a8SEvalZero #else
56*150812a8SEvalZero uint32_t field_state_cnt; /**< Counter of the FIELDLOST events. */
57*150812a8SEvalZero #endif // NRF52840_XXAA
58*150812a8SEvalZero } nrfx_nfct_timer_workaround_t;
59*150812a8SEvalZero
60*150812a8SEvalZero #ifdef NRF52840_XXAA
61*150812a8SEvalZero #define NRFX_NFCT_ACTIVATE_DELAY 1000 /**< Minimal delay in us between NFC field detection and activation of NFCT. */
62*150812a8SEvalZero #define NRFX_NFCT_TIMER_PERIOD NRFX_NFCT_ACTIVATE_DELAY
63*150812a8SEvalZero #else
64*150812a8SEvalZero #define NRFX_NFCT_FIELDLOST_THR 7
65*150812a8SEvalZero #define NRFX_NFCT_FIELD_TIMER_PERIOD 100 /**< Field polling period in us. */
66*150812a8SEvalZero #define NRFX_NFCT_TIMER_PERIOD NRFX_NFCT_FIELD_TIMER_PERIOD
67*150812a8SEvalZero #endif // NRF52840_XXAA
68*150812a8SEvalZero #define NRFX_NFCT_TIMER_INSTANCE 4 /**< Timer instance used for various workarounds for the NFCT HW issues.*/
69*150812a8SEvalZero
70*150812a8SEvalZero static nrfx_nfct_timer_workaround_t m_timer_workaround =
71*150812a8SEvalZero {
72*150812a8SEvalZero .timer = NRFX_TIMER_INSTANCE(NRFX_NFCT_TIMER_INSTANCE),
73*150812a8SEvalZero };
74*150812a8SEvalZero #endif // USE_TIMER_WORKAROUND
75*150812a8SEvalZero
76*150812a8SEvalZero #define NRFX_NFCT_FRAMEDELAYMAX_52840S (0xFFFFUL) /**< Bit mask of the FRAMEDELAYMAX field for the first sample of 52840.*/
77*150812a8SEvalZero #define NRFX_NFCT_FWT_MAX_DIFF 1u /**< The maximal difference between the requested FWT and HW-limited FWT settings.*/
78*150812a8SEvalZero
79*150812a8SEvalZero /* Mask of all possible interrupts that are relevant for data reception. */
80*150812a8SEvalZero #define NRFX_NFCT_RX_INT_MASK (NRF_NFCT_INT_RXFRAMESTART_MASK | \
81*150812a8SEvalZero NRF_NFCT_INT_RXFRAMEEND_MASK | \
82*150812a8SEvalZero NRF_NFCT_INT_RXERROR_MASK)
83*150812a8SEvalZero
84*150812a8SEvalZero /* Mask of all possible interrupts that are relevant for data transmission. */
85*150812a8SEvalZero #define NRFX_NFCT_TX_INT_MASK (NRF_NFCT_INT_TXFRAMESTART_MASK | \
86*150812a8SEvalZero NRF_NFCT_INT_TXFRAMEEND_MASK)
87*150812a8SEvalZero
88*150812a8SEvalZero
89*150812a8SEvalZero /* Mask of all possible errors from the @ref NRF_NFCT_EVENT_RXERROR event. */
90*150812a8SEvalZero #define NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK (NRF_NFCT_RX_FRAME_STATUS_CRC_MASK | \
91*150812a8SEvalZero NRF_NFCT_RX_FRAME_STATUS_PARITY_MASK | \
92*150812a8SEvalZero NRF_NFCT_RX_FRAME_STATUS_OVERRUN_MASK)
93*150812a8SEvalZero
94*150812a8SEvalZero /* Mask of all possible errors from the @ref NRF_NFCT_EVENT_ERROR event. */
95*150812a8SEvalZero #if defined (NRF52832_XXAA) || defined(NRF52832_XXAB)
96*150812a8SEvalZero #define NRFX_NFCT_ERROR_STATUS_ALL_MASK (NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK | \
97*150812a8SEvalZero NRF_NFCT_ERROR_NFCFIELDTOOSTRONG_MASK | \
98*150812a8SEvalZero NRF_NFCT_ERROR_NFCFIELDTOOWEAK_MASK)
99*150812a8SEvalZero #else
100*150812a8SEvalZero #define NRFX_NFCT_ERROR_STATUS_ALL_MASK (NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK)
101*150812a8SEvalZero #endif
102*150812a8SEvalZero
103*150812a8SEvalZero /* Macros for conversion of bits to bytes. */
104*150812a8SEvalZero #define NRFX_NFCT_BYTES_TO_BITS(_bytes) ((_bytes) << 3)
105*150812a8SEvalZero #define NRFX_NFCT_BITS_TO_BYTES(_bits) ((_bits) >> 3)
106*150812a8SEvalZero
107*150812a8SEvalZero /* Macro for checking whether the NFCT interrupt is active. */
108*150812a8SEvalZero #define NRFX_NFCT_EVT_ACTIVE(_name) (nrf_nfct_event_check(NRFX_CONCAT_2(NRF_NFCT_EVENT_, _name)) && \
109*150812a8SEvalZero nrf_nfct_int_enable_check(NRFX_CONCAT_3(NRF_NFCT_INT_, _name, _MASK)))
110*150812a8SEvalZero
111*150812a8SEvalZero /* Macro for callback execution. */
112*150812a8SEvalZero #define NRFX_NFCT_CB_HANDLE(_cb, _evt) \
113*150812a8SEvalZero if (_cb != NULL) \
114*150812a8SEvalZero { \
115*150812a8SEvalZero _cb(&_evt); \
116*150812a8SEvalZero }
117*150812a8SEvalZero
118*150812a8SEvalZero typedef enum
119*150812a8SEvalZero {
120*150812a8SEvalZero NRFX_NFC_FIELD_STATE_NONE, /**< Initial value that indicates no NFCT field events. */
121*150812a8SEvalZero NRFX_NFC_FIELD_STATE_OFF, /**< The NFCT FIELDLOST event has been set. */
122*150812a8SEvalZero NRFX_NFC_FIELD_STATE_ON, /**< The NFCT FIELDDETECTED event has been set. */
123*150812a8SEvalZero NRFX_NFC_FIELD_STATE_UNKNOWN /**< Both NFCT field events have been set - ambiguous state. */
124*150812a8SEvalZero } nrfx_nfct_field_state_t;
125*150812a8SEvalZero
126*150812a8SEvalZero #ifdef NRF52840_XXAA
127*150812a8SEvalZero /**
128*150812a8SEvalZero * @brief Internal auxiliary function for checking whether the program is running on the NRF52840 chip.
129*150812a8SEvalZero *
130*150812a8SEvalZero * @retval true It is NRF52480 chip.
131*150812a8SEvalZero * @retval false It is an other chip.
132*150812a8SEvalZero */
nrfx_nfct_type_52840_check(void)133*150812a8SEvalZero static inline bool nrfx_nfct_type_52840_check(void)
134*150812a8SEvalZero {
135*150812a8SEvalZero return ((((*(uint32_t *)0xF0000FE0) & 0xFF) == 0x08) &&
136*150812a8SEvalZero (((*(uint32_t *)0xF0000FE4) & 0x0F) == 0x0));
137*150812a8SEvalZero }
138*150812a8SEvalZero
139*150812a8SEvalZero /**
140*150812a8SEvalZero * @brief Internal auxiliary function for checking whether the program is running on the first sample of
141*150812a8SEvalZero * the nRF52840 chip.
142*150812a8SEvalZero *
143*150812a8SEvalZero * @retval true It is the nRF52480 chip and it is the first sample version.
144*150812a8SEvalZero * @retval false It is an other chip.
145*150812a8SEvalZero */
nrfx_nfct_type_52840_sample_check(void)146*150812a8SEvalZero static inline bool nrfx_nfct_type_52840_sample_check(void)
147*150812a8SEvalZero {
148*150812a8SEvalZero return ( nrfx_nfct_type_52840_check() &&
149*150812a8SEvalZero ( ((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x00 ) &&
150*150812a8SEvalZero ( ((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00 ) );
151*150812a8SEvalZero }
152*150812a8SEvalZero
153*150812a8SEvalZero /**
154*150812a8SEvalZero * @brief Internal auxiliary function for checking whether the program is running on the final version of
155*150812a8SEvalZero * the nRF52840 chip.
156*150812a8SEvalZero *
157*150812a8SEvalZero * @retval true It is the nRF52480 chip and it is the final version.
158*150812a8SEvalZero * @retval false It is an other chip.
159*150812a8SEvalZero */
nrfx_nfct_type_52840_final_check(void)160*150812a8SEvalZero static inline bool nrfx_nfct_type_52840_final_check(void)
161*150812a8SEvalZero {
162*150812a8SEvalZero return ( nrfx_nfct_type_52840_check() &&
163*150812a8SEvalZero ( ( ((*(uint32_t *)0xF0000FE8) & 0xF0) != 0x00 ) ||
164*150812a8SEvalZero ( ((*(uint32_t *)0xF0000FEC) & 0xF0) != 0x00 ) ));
165*150812a8SEvalZero }
166*150812a8SEvalZero
167*150812a8SEvalZero typedef struct
168*150812a8SEvalZero {
169*150812a8SEvalZero bool eng_a; /**< Engineering sample A of the NRF52840 chip. */
170*150812a8SEvalZero bool eng_bc; /**< Engineering sample B, C of the NRF52840 chip, or its final version. */
171*150812a8SEvalZero } nrfx_nfct_nrf52840_ver_t;
172*150812a8SEvalZero
173*150812a8SEvalZero static nrfx_nfct_nrf52840_ver_t m_nrf52840;
174*150812a8SEvalZero #endif // NRF52840_XXAA
175*150812a8SEvalZero
176*150812a8SEvalZero /**@brief NFCT control block. */
177*150812a8SEvalZero typedef struct
178*150812a8SEvalZero {
179*150812a8SEvalZero nrfx_nfct_config_t config;
180*150812a8SEvalZero nrfx_drv_state_t state;
181*150812a8SEvalZero volatile bool field_on;
182*150812a8SEvalZero } nrfx_nfct_control_block_t;
183*150812a8SEvalZero
184*150812a8SEvalZero static nrfx_nfct_control_block_t m_nfct_cb;
185*150812a8SEvalZero
186*150812a8SEvalZero /**
187*150812a8SEvalZero * @brief Common part of the setup used for the NFCT initialization and reinitialization.
188*150812a8SEvalZero */
nrfx_nfct_hw_init_setup(void)189*150812a8SEvalZero static void nrfx_nfct_hw_init_setup(void)
190*150812a8SEvalZero {
191*150812a8SEvalZero #ifdef NRF52840_XXAA
192*150812a8SEvalZero if (m_nrf52840.eng_a)
193*150812a8SEvalZero {
194*150812a8SEvalZero /* Begin: Bugfix for FTPAN-98 */
195*150812a8SEvalZero *(volatile uint32_t *) 0x4000568C = 0x00038148;
196*150812a8SEvalZero /* End: Bugfix for FTPAN-98 */
197*150812a8SEvalZero /* Begin: Bugfix for FTPAN-144 */
198*150812a8SEvalZero *(volatile uint32_t *) 0x4000561c = 0x01;
199*150812a8SEvalZero *(volatile uint32_t *) 0x4000562c = 0x3F;
200*150812a8SEvalZero *(volatile uint32_t *) 0x4000563c = 0x0;
201*150812a8SEvalZero /* End: Bugfix for FTPAN-144 */
202*150812a8SEvalZero }
203*150812a8SEvalZero #endif // NRF52840_XXAA
204*150812a8SEvalZero
205*150812a8SEvalZero // Use Window Grid frame delay mode.
206*150812a8SEvalZero nrf_nfct_frame_delay_mode_set(NRF_NFCT_FRAME_DELAY_MODE_WINDOWGRID);
207*150812a8SEvalZero
208*150812a8SEvalZero /* Begin: Bugfix for FTPAN-25 (IC-9929) */
209*150812a8SEvalZero /* Workaround for wrong SENSRES values require using SDD00001, but here SDD00100 is used
210*150812a8SEvalZero because it is required to operate with Windows Phone */
211*150812a8SEvalZero nrf_nfct_sensres_bit_frame_sdd_set(NRF_NFCT_SENSRES_BIT_FRAME_SDD_00100);
212*150812a8SEvalZero /* End: Bugfix for FTPAN-25 (IC-9929) */
213*150812a8SEvalZero }
214*150812a8SEvalZero
215*150812a8SEvalZero /**@brief Function for evaluating and handling the NFC field events.
216*150812a8SEvalZero *
217*150812a8SEvalZero * @param[in] field_state Current field state.
218*150812a8SEvalZero */
nrfx_nfct_field_event_handler(volatile nrfx_nfct_field_state_t field_state)219*150812a8SEvalZero static void nrfx_nfct_field_event_handler(volatile nrfx_nfct_field_state_t field_state)
220*150812a8SEvalZero {
221*150812a8SEvalZero nrfx_nfct_evt_t nfct_evt;
222*150812a8SEvalZero
223*150812a8SEvalZero #ifdef NRF52840_XXAA
224*150812a8SEvalZero if((!m_nrf52840.eng_a) && (m_timer_workaround.fieldevents_filter_active))
225*150812a8SEvalZero {
226*150812a8SEvalZero return;
227*150812a8SEvalZero }
228*150812a8SEvalZero #endif // NRF52840_XXAA
229*150812a8SEvalZero
230*150812a8SEvalZero if (field_state == NRFX_NFC_FIELD_STATE_UNKNOWN)
231*150812a8SEvalZero {
232*150812a8SEvalZero /* Probe NFC field */
233*150812a8SEvalZero field_state = (nrfx_nfct_field_check()) ? NRFX_NFC_FIELD_STATE_ON : NRFX_NFC_FIELD_STATE_OFF;
234*150812a8SEvalZero }
235*150812a8SEvalZero
236*150812a8SEvalZero /* Field event service */
237*150812a8SEvalZero switch (field_state)
238*150812a8SEvalZero {
239*150812a8SEvalZero case NRFX_NFC_FIELD_STATE_ON:
240*150812a8SEvalZero if (!m_nfct_cb.field_on)
241*150812a8SEvalZero {
242*150812a8SEvalZero #ifdef NRF52840_XXAA
243*150812a8SEvalZero /* Begin: Bugfix for FTPAN-190 */
244*150812a8SEvalZero if (!m_nrf52840.eng_a)
245*150812a8SEvalZero {
246*150812a8SEvalZero m_timer_workaround.is_hfclk_on = false;
247*150812a8SEvalZero m_timer_workaround.is_delayed = false;
248*150812a8SEvalZero m_timer_workaround.fieldevents_filter_active = true;
249*150812a8SEvalZero
250*150812a8SEvalZero nrfx_timer_clear(&m_timer_workaround.timer);
251*150812a8SEvalZero nrfx_timer_enable(&m_timer_workaround.timer);
252*150812a8SEvalZero }
253*150812a8SEvalZero /* END: Bugfix for FTPAN-190 */
254*150812a8SEvalZero #elif defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
255*150812a8SEvalZero nrfx_timer_clear(&m_timer_workaround.timer);
256*150812a8SEvalZero nrfx_timer_enable(&m_timer_workaround.timer);
257*150812a8SEvalZero m_timer_workaround.field_state_cnt = 0;
258*150812a8SEvalZero #endif // NRF52840_XXAA
259*150812a8SEvalZero
260*150812a8SEvalZero m_nfct_cb.field_on = true;
261*150812a8SEvalZero nfct_evt.evt_id = NRFX_NFCT_EVT_FIELD_DETECTED;
262*150812a8SEvalZero NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
263*150812a8SEvalZero }
264*150812a8SEvalZero break;
265*150812a8SEvalZero
266*150812a8SEvalZero case NRFX_NFC_FIELD_STATE_OFF:
267*150812a8SEvalZero nrfx_nfct_state_force(NRFX_NFCT_STATE_SENSING);
268*150812a8SEvalZero #ifdef NRF52840_XXAA
269*150812a8SEvalZero /* Begin: Bugfix for FTPAN-116 (IC-12886) */
270*150812a8SEvalZero if (m_nrf52840.eng_a)
271*150812a8SEvalZero {
272*150812a8SEvalZero *(volatile uint32_t *)0x40005010 = 1;
273*150812a8SEvalZero }
274*150812a8SEvalZero /* END: Bugfix for FTPAN-116 (IC-12886) */
275*150812a8SEvalZero #endif // NRF52840_XXAA
276*150812a8SEvalZero nrf_nfct_int_disable(NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
277*150812a8SEvalZero m_nfct_cb.field_on = false;
278*150812a8SEvalZero nfct_evt.evt_id = NRFX_NFCT_EVT_FIELD_LOST;
279*150812a8SEvalZero
280*150812a8SEvalZero NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
281*150812a8SEvalZero break;
282*150812a8SEvalZero
283*150812a8SEvalZero default:
284*150812a8SEvalZero /* No implementation required */
285*150812a8SEvalZero break;
286*150812a8SEvalZero }
287*150812a8SEvalZero }
288*150812a8SEvalZero
289*150812a8SEvalZero #ifdef USE_TIMER_WORKAROUND
290*150812a8SEvalZero
291*150812a8SEvalZero #ifdef NRF52840_XXAA
nrfx_nfct_activate_check(void)292*150812a8SEvalZero static void nrfx_nfct_activate_check(void)
293*150812a8SEvalZero {
294*150812a8SEvalZero static bool is_field_validation_pending = false;
295*150812a8SEvalZero
296*150812a8SEvalZero if (is_field_validation_pending)
297*150812a8SEvalZero {
298*150812a8SEvalZero is_field_validation_pending = false;
299*150812a8SEvalZero m_timer_workaround.fieldevents_filter_active = false;
300*150812a8SEvalZero
301*150812a8SEvalZero // Check the field status and take action if field is lost.
302*150812a8SEvalZero nrfx_nfct_field_event_handler(NRFX_NFC_FIELD_STATE_UNKNOWN);
303*150812a8SEvalZero return;
304*150812a8SEvalZero }
305*150812a8SEvalZero
306*150812a8SEvalZero if ((m_timer_workaround.is_hfclk_on) && (m_timer_workaround.is_delayed))
307*150812a8SEvalZero {
308*150812a8SEvalZero nrf_nfct_task_trigger(NRF_NFCT_TASK_ACTIVATE);
309*150812a8SEvalZero is_field_validation_pending = true;
310*150812a8SEvalZero
311*150812a8SEvalZero // Start the timer second time to validate whether the tag has locked to the field.
312*150812a8SEvalZero nrfx_timer_clear(&m_timer_workaround.timer);
313*150812a8SEvalZero nrfx_timer_enable(&m_timer_workaround.timer);
314*150812a8SEvalZero }
315*150812a8SEvalZero }
316*150812a8SEvalZero #endif // NRF52840_XXAA
317*150812a8SEvalZero
318*150812a8SEvalZero #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
nrfx_nfct_reset(void)319*150812a8SEvalZero static inline void nrfx_nfct_reset(void)
320*150812a8SEvalZero {
321*150812a8SEvalZero uint32_t fdm;
322*150812a8SEvalZero uint32_t int_enabled;
323*150812a8SEvalZero uint8_t nfcid1[NRF_NFCT_SENSRES_NFCID1_SIZE_TRIPLE];
324*150812a8SEvalZero nrf_nfct_sensres_nfcid1_size_t nfcid1_size;
325*150812a8SEvalZero nrf_nfct_selres_protocol_t protocol;
326*150812a8SEvalZero
327*150812a8SEvalZero // Save parameter settings before the reset of the NFCT peripheral.
328*150812a8SEvalZero fdm = nrf_nfct_frame_delay_max_get();
329*150812a8SEvalZero nfcid1_size = nrf_nfct_nfcid1_get(nfcid1);
330*150812a8SEvalZero protocol = nrf_nfct_selsres_protocol_get();
331*150812a8SEvalZero int_enabled = nrf_nfct_int_enable_get();
332*150812a8SEvalZero
333*150812a8SEvalZero // Reset the NFCT peripheral.
334*150812a8SEvalZero *(volatile uint32_t *)0x40005FFC = 0;
335*150812a8SEvalZero *(volatile uint32_t *)0x40005FFC;
336*150812a8SEvalZero *(volatile uint32_t *)0x40005FFC = 1;
337*150812a8SEvalZero
338*150812a8SEvalZero // Restore parameter settings after the reset of the NFCT peripheral.
339*150812a8SEvalZero nrf_nfct_frame_delay_max_set(fdm);
340*150812a8SEvalZero nrf_nfct_nfcid1_set(nfcid1, nfcid1_size);
341*150812a8SEvalZero nrf_nfct_selres_protocol_set(protocol);
342*150812a8SEvalZero
343*150812a8SEvalZero // Restore general HW configuration.
344*150812a8SEvalZero nrfx_nfct_hw_init_setup();
345*150812a8SEvalZero
346*150812a8SEvalZero // Restore interrupts.
347*150812a8SEvalZero nrf_nfct_int_enable(int_enabled);
348*150812a8SEvalZero
349*150812a8SEvalZero NRFX_LOG_INFO("Reinitialize");
350*150812a8SEvalZero }
351*150812a8SEvalZero
nrfx_nfct_field_poll(void)352*150812a8SEvalZero static void nrfx_nfct_field_poll(void)
353*150812a8SEvalZero {
354*150812a8SEvalZero if (!nrfx_nfct_field_check())
355*150812a8SEvalZero {
356*150812a8SEvalZero if (++m_timer_workaround.field_state_cnt > NRFX_NFCT_FIELDLOST_THR)
357*150812a8SEvalZero {
358*150812a8SEvalZero nrfx_nfct_evt_t nfct_evt =
359*150812a8SEvalZero {
360*150812a8SEvalZero .evt_id = NRFX_NFCT_EVT_FIELD_LOST,
361*150812a8SEvalZero };
362*150812a8SEvalZero
363*150812a8SEvalZero nrfx_timer_disable(&m_timer_workaround.timer);
364*150812a8SEvalZero m_nfct_cb.field_on = false;
365*150812a8SEvalZero
366*150812a8SEvalZero /* Begin: Bugfix for FTPAN-116 */
367*150812a8SEvalZero // resume the NFCT to initialized state
368*150812a8SEvalZero nrfx_nfct_reset();
369*150812a8SEvalZero /* End: Bugfix for FTPAN-116 */
370*150812a8SEvalZero
371*150812a8SEvalZero NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
372*150812a8SEvalZero }
373*150812a8SEvalZero return;
374*150812a8SEvalZero }
375*150812a8SEvalZero
376*150812a8SEvalZero m_timer_workaround.field_state_cnt = 0;
377*150812a8SEvalZero }
378*150812a8SEvalZero #endif // defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
379*150812a8SEvalZero
nrfx_nfct_field_timer_handler(nrf_timer_event_t event_type,void * p_context)380*150812a8SEvalZero static void nrfx_nfct_field_timer_handler(nrf_timer_event_t event_type, void * p_context)
381*150812a8SEvalZero {
382*150812a8SEvalZero (void)p_context;
383*150812a8SEvalZero
384*150812a8SEvalZero if (event_type != NRF_TIMER_EVENT_COMPARE0)
385*150812a8SEvalZero {
386*150812a8SEvalZero return;
387*150812a8SEvalZero }
388*150812a8SEvalZero
389*150812a8SEvalZero #ifdef NRF52840_XXAA
390*150812a8SEvalZero m_timer_workaround.is_delayed = true;
391*150812a8SEvalZero
392*150812a8SEvalZero nrfx_timer_disable(&m_timer_workaround.timer);
393*150812a8SEvalZero nrfx_nfct_activate_check();
394*150812a8SEvalZero #else
395*150812a8SEvalZero nrfx_nfct_field_poll();
396*150812a8SEvalZero #endif //NRF52840_XXAA
397*150812a8SEvalZero }
398*150812a8SEvalZero
nrfx_nfct_field_timer_config(void)399*150812a8SEvalZero static inline nrfx_err_t nrfx_nfct_field_timer_config(void)
400*150812a8SEvalZero {
401*150812a8SEvalZero nrfx_err_t err_code;
402*150812a8SEvalZero nrfx_timer_config_t timer_cfg =
403*150812a8SEvalZero {
404*150812a8SEvalZero .frequency = NRF_TIMER_FREQ_1MHz,
405*150812a8SEvalZero .mode = NRF_TIMER_MODE_TIMER,
406*150812a8SEvalZero .bit_width = NRF_TIMER_BIT_WIDTH_16,
407*150812a8SEvalZero .interrupt_priority = NRFX_NFCT_CONFIG_IRQ_PRIORITY
408*150812a8SEvalZero };
409*150812a8SEvalZero
410*150812a8SEvalZero err_code = nrfx_timer_init(&m_timer_workaround.timer, &timer_cfg, nrfx_nfct_field_timer_handler);
411*150812a8SEvalZero if (err_code != NRFX_SUCCESS)
412*150812a8SEvalZero {
413*150812a8SEvalZero return err_code;
414*150812a8SEvalZero }
415*150812a8SEvalZero
416*150812a8SEvalZero nrfx_timer_extended_compare(&m_timer_workaround.timer,
417*150812a8SEvalZero NRF_TIMER_CC_CHANNEL0,
418*150812a8SEvalZero nrfx_timer_us_to_ticks(&m_timer_workaround.timer, NRFX_NFCT_TIMER_PERIOD),
419*150812a8SEvalZero NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
420*150812a8SEvalZero true);
421*150812a8SEvalZero return err_code;
422*150812a8SEvalZero }
423*150812a8SEvalZero
424*150812a8SEvalZero #endif // USE_TIMER_WORKAROUND
425*150812a8SEvalZero
nrf_nfct_nfcid1_size_to_sensres_size(uint8_t nfcid1_size)426*150812a8SEvalZero static inline nrf_nfct_sensres_nfcid1_size_t nrf_nfct_nfcid1_size_to_sensres_size(uint8_t nfcid1_size)
427*150812a8SEvalZero {
428*150812a8SEvalZero switch (nfcid1_size)
429*150812a8SEvalZero {
430*150812a8SEvalZero case NRFX_NFCT_NFCID1_SINGLE_SIZE:
431*150812a8SEvalZero return NRF_NFCT_SENSRES_NFCID1_SIZE_SINGLE;
432*150812a8SEvalZero
433*150812a8SEvalZero case NRFX_NFCT_NFCID1_DOUBLE_SIZE:
434*150812a8SEvalZero return NRF_NFCT_SENSRES_NFCID1_SIZE_DOUBLE;
435*150812a8SEvalZero
436*150812a8SEvalZero case NRFX_NFCT_NFCID1_TRIPLE_SIZE:
437*150812a8SEvalZero return NRF_NFCT_SENSRES_NFCID1_SIZE_TRIPLE;
438*150812a8SEvalZero
439*150812a8SEvalZero default:
440*150812a8SEvalZero return NRF_NFCT_SENSRES_NFCID1_SIZE_DOUBLE;
441*150812a8SEvalZero }
442*150812a8SEvalZero }
443*150812a8SEvalZero
nrfx_nfct_rxtx_int_enable(uint32_t rxtx_int_mask)444*150812a8SEvalZero static inline void nrfx_nfct_rxtx_int_enable(uint32_t rxtx_int_mask)
445*150812a8SEvalZero {
446*150812a8SEvalZero nrf_nfct_int_enable(rxtx_int_mask & m_nfct_cb.config.rxtx_int_mask);
447*150812a8SEvalZero }
448*150812a8SEvalZero
nrfx_nfct_init(nrfx_nfct_config_t const * p_config)449*150812a8SEvalZero nrfx_err_t nrfx_nfct_init(nrfx_nfct_config_t const * p_config)
450*150812a8SEvalZero {
451*150812a8SEvalZero NRFX_ASSERT(p_config);
452*150812a8SEvalZero
453*150812a8SEvalZero nrfx_err_t err_code = NRFX_SUCCESS;
454*150812a8SEvalZero
455*150812a8SEvalZero if (m_nfct_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
456*150812a8SEvalZero {
457*150812a8SEvalZero return NRFX_ERROR_INVALID_STATE;
458*150812a8SEvalZero }
459*150812a8SEvalZero
460*150812a8SEvalZero #ifdef NRF52840_XXAA
461*150812a8SEvalZero m_nrf52840.eng_a = nrfx_nfct_type_52840_sample_check();
462*150812a8SEvalZero m_nrf52840.eng_bc = nrfx_nfct_type_52840_final_check();
463*150812a8SEvalZero #endif // NRF52840_XXAA
464*150812a8SEvalZero
465*150812a8SEvalZero m_nfct_cb.config = *p_config;
466*150812a8SEvalZero nrfx_nfct_hw_init_setup();
467*150812a8SEvalZero
468*150812a8SEvalZero NRFX_IRQ_PENDING_CLEAR(NFCT_IRQn);
469*150812a8SEvalZero NRFX_IRQ_PRIORITY_SET(NFCT_IRQn, NRFX_NFCT_CONFIG_IRQ_PRIORITY);
470*150812a8SEvalZero NRFX_IRQ_ENABLE(NFCT_IRQn);
471*150812a8SEvalZero
472*150812a8SEvalZero #ifdef USE_TIMER_WORKAROUND
473*150812a8SEvalZero /* Initialize Timer module as the workaround for NFCT HW issues. */
474*150812a8SEvalZero #ifdef NRF52840_XXAA
475*150812a8SEvalZero if (!m_nrf52840.eng_a)
476*150812a8SEvalZero #endif // NRF52840_XXAA
477*150812a8SEvalZero {
478*150812a8SEvalZero err_code = nrfx_nfct_field_timer_config();
479*150812a8SEvalZero }
480*150812a8SEvalZero #endif // USE_TIMER_WORKAROUND
481*150812a8SEvalZero
482*150812a8SEvalZero if (err_code == NRFX_SUCCESS)
483*150812a8SEvalZero {
484*150812a8SEvalZero uint8_t default_nfcid1[NRFX_NFCT_NFCID1_DEFAULT_LEN];
485*150812a8SEvalZero err_code = nrfx_nfct_nfcid1_default_bytes_get(default_nfcid1, sizeof(default_nfcid1));
486*150812a8SEvalZero NRFX_ASSERT(err_code == NRFX_SUCCESS);
487*150812a8SEvalZero nrf_nfct_nfcid1_set(default_nfcid1, NRF_NFCT_SENSRES_NFCID1_SIZE_DEFAULT);
488*150812a8SEvalZero }
489*150812a8SEvalZero else
490*150812a8SEvalZero {
491*150812a8SEvalZero return err_code;
492*150812a8SEvalZero }
493*150812a8SEvalZero
494*150812a8SEvalZero m_nfct_cb.state = NRFX_DRV_STATE_INITIALIZED;
495*150812a8SEvalZero
496*150812a8SEvalZero NRFX_LOG_INFO("Initialized");
497*150812a8SEvalZero return err_code;
498*150812a8SEvalZero }
499*150812a8SEvalZero
nrfx_nfct_uninit(void)500*150812a8SEvalZero void nrfx_nfct_uninit(void)
501*150812a8SEvalZero {
502*150812a8SEvalZero nrfx_nfct_disable();
503*150812a8SEvalZero
504*150812a8SEvalZero NRFX_IRQ_DISABLE(NFCT_IRQn);
505*150812a8SEvalZero NRFX_IRQ_PENDING_CLEAR(NFCT_IRQn);
506*150812a8SEvalZero
507*150812a8SEvalZero #ifdef USE_TIMER_WORKAROUND
508*150812a8SEvalZero /* Initialize Timer module as the workaround for NFCT HW issues. */
509*150812a8SEvalZero #ifdef NRF52840_XXAA
510*150812a8SEvalZero if (!m_nrf52840.eng_a)
511*150812a8SEvalZero #endif // NRF52840_XXAA
512*150812a8SEvalZero {
513*150812a8SEvalZero nrfx_timer_uninit(&m_timer_workaround.timer);
514*150812a8SEvalZero }
515*150812a8SEvalZero #endif // USE_TIMER_WORKAROUND
516*150812a8SEvalZero
517*150812a8SEvalZero m_nfct_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
518*150812a8SEvalZero }
519*150812a8SEvalZero
nrfx_nfct_enable(void)520*150812a8SEvalZero void nrfx_nfct_enable(void)
521*150812a8SEvalZero {
522*150812a8SEvalZero nrf_nfct_error_status_clear(NRFX_NFCT_ERROR_STATUS_ALL_MASK);
523*150812a8SEvalZero nrf_nfct_task_trigger(NRF_NFCT_TASK_SENSE);
524*150812a8SEvalZero
525*150812a8SEvalZero nrf_nfct_int_enable(NRF_NFCT_INT_FIELDDETECTED_MASK | NRF_NFCT_INT_ERROR_MASK |
526*150812a8SEvalZero NRF_NFCT_INT_SELECTED_MASK);
527*150812a8SEvalZero #if !defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
528*150812a8SEvalZero nrf_nfct_int_enable(NRF_NFCT_INT_FIELDLOST_MASK);
529*150812a8SEvalZero #endif //!defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
530*150812a8SEvalZero
531*150812a8SEvalZero NRFX_LOG_INFO("Start");
532*150812a8SEvalZero }
533*150812a8SEvalZero
nrfx_nfct_disable(void)534*150812a8SEvalZero void nrfx_nfct_disable(void)
535*150812a8SEvalZero {
536*150812a8SEvalZero nrf_nfct_int_disable(NRF_NFCT_DISABLE_ALL_INT);
537*150812a8SEvalZero nrf_nfct_task_trigger(NRF_NFCT_TASK_DISABLE);
538*150812a8SEvalZero
539*150812a8SEvalZero NRFX_LOG_INFO("Stop");
540*150812a8SEvalZero }
541*150812a8SEvalZero
nrfx_nfct_field_check(void)542*150812a8SEvalZero bool nrfx_nfct_field_check(void)
543*150812a8SEvalZero {
544*150812a8SEvalZero uint32_t const field_state = nrf_nfct_field_status_get();
545*150812a8SEvalZero
546*150812a8SEvalZero if (((field_state & NRF_NFCT_FIELD_STATE_PRESENT_MASK) == 0) &&
547*150812a8SEvalZero ((field_state & NRF_NFCT_FIELD_STATE_LOCK_MASK) == 0))
548*150812a8SEvalZero {
549*150812a8SEvalZero // Field is not active
550*150812a8SEvalZero return false;
551*150812a8SEvalZero }
552*150812a8SEvalZero
553*150812a8SEvalZero return true;
554*150812a8SEvalZero }
555*150812a8SEvalZero
nrfx_nfct_rx(nrfx_nfct_data_desc_t const * p_tx_data)556*150812a8SEvalZero void nrfx_nfct_rx(nrfx_nfct_data_desc_t const * p_tx_data)
557*150812a8SEvalZero {
558*150812a8SEvalZero NRFX_ASSERT(p_tx_data);
559*150812a8SEvalZero
560*150812a8SEvalZero nrf_nfct_rxtx_buffer_set((uint8_t *) p_tx_data->p_data, p_tx_data->data_size);
561*150812a8SEvalZero
562*150812a8SEvalZero nrfx_nfct_rxtx_int_enable(NRFX_NFCT_RX_INT_MASK);
563*150812a8SEvalZero nrf_nfct_task_trigger(NRF_NFCT_TASK_ENABLERXDATA);
564*150812a8SEvalZero }
565*150812a8SEvalZero
nrfx_nfct_tx(nrfx_nfct_data_desc_t const * p_tx_data,nrf_nfct_frame_delay_mode_t delay_mode)566*150812a8SEvalZero nrfx_err_t nrfx_nfct_tx(nrfx_nfct_data_desc_t const * p_tx_data,
567*150812a8SEvalZero nrf_nfct_frame_delay_mode_t delay_mode)
568*150812a8SEvalZero {
569*150812a8SEvalZero NRFX_ASSERT(p_tx_data);
570*150812a8SEvalZero NRFX_ASSERT(p_tx_data->p_data);
571*150812a8SEvalZero
572*150812a8SEvalZero if (p_tx_data->data_size == 0)
573*150812a8SEvalZero {
574*150812a8SEvalZero return NRFX_ERROR_INVALID_LENGTH;
575*150812a8SEvalZero }
576*150812a8SEvalZero
577*150812a8SEvalZero nrf_nfct_rxtx_buffer_set((uint8_t *) p_tx_data->p_data, p_tx_data->data_size);
578*150812a8SEvalZero nrf_nfct_tx_bits_set(NRFX_NFCT_BYTES_TO_BITS(p_tx_data->data_size));
579*150812a8SEvalZero nrf_nfct_frame_delay_mode_set((nrf_nfct_frame_delay_mode_t) delay_mode);
580*150812a8SEvalZero
581*150812a8SEvalZero nrfx_nfct_rxtx_int_enable(NRFX_NFCT_TX_INT_MASK);
582*150812a8SEvalZero nrf_nfct_task_trigger(NRF_NFCT_TASK_STARTTX);
583*150812a8SEvalZero
584*150812a8SEvalZero NRFX_LOG_INFO("Tx start");
585*150812a8SEvalZero return NRFX_SUCCESS;
586*150812a8SEvalZero }
587*150812a8SEvalZero
nrfx_nfct_state_force(nrfx_nfct_state_t state)588*150812a8SEvalZero void nrfx_nfct_state_force(nrfx_nfct_state_t state)
589*150812a8SEvalZero {
590*150812a8SEvalZero #ifdef NRF52840_XXAA
591*150812a8SEvalZero if ((m_nrf52840.eng_bc) && (state == NRFX_NFCT_STATE_ACTIVATED))
592*150812a8SEvalZero {
593*150812a8SEvalZero m_timer_workaround.is_hfclk_on = true;
594*150812a8SEvalZero nrfx_nfct_activate_check();
595*150812a8SEvalZero }
596*150812a8SEvalZero #endif
597*150812a8SEvalZero {
598*150812a8SEvalZero nrf_nfct_task_trigger((nrf_nfct_task_t) state);
599*150812a8SEvalZero }
600*150812a8SEvalZero }
601*150812a8SEvalZero
nrfx_nfct_init_substate_force(nrfx_nfct_active_state_t sub_state)602*150812a8SEvalZero void nrfx_nfct_init_substate_force(nrfx_nfct_active_state_t sub_state)
603*150812a8SEvalZero {
604*150812a8SEvalZero if (sub_state == NRFX_NFCT_ACTIVE_STATE_DEFAULT)
605*150812a8SEvalZero {
606*150812a8SEvalZero #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
607*150812a8SEvalZero if (((*(uint32_t volatile *)(0x40005420)) & 0x1UL) == (1UL))
608*150812a8SEvalZero #else
609*150812a8SEvalZero if (nrf_nfct_sleep_state_get() == NRF_NFCT_SLEEP_STATE_SLEEP_A)
610*150812a8SEvalZero #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
611*150812a8SEvalZero {
612*150812a8SEvalZero // Default state is SLEEP_A
613*150812a8SEvalZero nrf_nfct_task_trigger(NRF_NFCT_TASK_GOSLEEP);
614*150812a8SEvalZero }
615*150812a8SEvalZero else
616*150812a8SEvalZero {
617*150812a8SEvalZero // Default state is IDLE
618*150812a8SEvalZero nrf_nfct_task_trigger(NRF_NFCT_TASK_GOIDLE);
619*150812a8SEvalZero }
620*150812a8SEvalZero }
621*150812a8SEvalZero else
622*150812a8SEvalZero {
623*150812a8SEvalZero nrf_nfct_task_trigger((nrf_nfct_task_t) sub_state);
624*150812a8SEvalZero }
625*150812a8SEvalZero
626*150812a8SEvalZero /* Disable TX/RX here (will be enabled at SELECTED) */
627*150812a8SEvalZero nrf_nfct_int_disable(NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
628*150812a8SEvalZero }
629*150812a8SEvalZero
nrfx_nfct_parameter_set(nrfx_nfct_param_t const * p_param)630*150812a8SEvalZero nrfx_err_t nrfx_nfct_parameter_set(nrfx_nfct_param_t const * p_param)
631*150812a8SEvalZero {
632*150812a8SEvalZero NRFX_ASSERT(p_param);
633*150812a8SEvalZero
634*150812a8SEvalZero switch (p_param->id)
635*150812a8SEvalZero {
636*150812a8SEvalZero case NRFX_NFCT_PARAM_ID_FDT:
637*150812a8SEvalZero {
638*150812a8SEvalZero uint32_t delay = p_param->data.fdt;
639*150812a8SEvalZero uint32_t delay_thr = NFCT_FRAMEDELAYMAX_FRAMEDELAYMAX_Msk;
640*150812a8SEvalZero
641*150812a8SEvalZero #ifdef NRF52840_XXAA
642*150812a8SEvalZero delay_thr = (m_nrf52840.eng_a) ? NRFX_NFCT_FRAMEDELAYMAX_52840S : delay_thr;
643*150812a8SEvalZero #endif // NRF52840_XXAA
644*150812a8SEvalZero
645*150812a8SEvalZero // Delay validation.
646*150812a8SEvalZero if (delay > (delay_thr + NRFX_NFCT_FWT_MAX_DIFF))
647*150812a8SEvalZero {
648*150812a8SEvalZero return NRFX_ERROR_INVALID_PARAM;
649*150812a8SEvalZero }
650*150812a8SEvalZero
651*150812a8SEvalZero delay = (delay > delay_thr) ? delay_thr : delay;
652*150812a8SEvalZero nrf_nfct_frame_delay_max_set(delay);
653*150812a8SEvalZero break;
654*150812a8SEvalZero }
655*150812a8SEvalZero
656*150812a8SEvalZero case NRFX_NFCT_PARAM_ID_SEL_RES:
657*150812a8SEvalZero if (p_param->data.sel_res_protocol > NRF_NFCT_SELRES_PROTOCOL_NFCDEP_T4AT)
658*150812a8SEvalZero {
659*150812a8SEvalZero return NRFX_ERROR_INVALID_PARAM;
660*150812a8SEvalZero }
661*150812a8SEvalZero
662*150812a8SEvalZero nrf_nfct_selres_protocol_set((nrf_nfct_selres_protocol_t) p_param->data.sel_res_protocol);
663*150812a8SEvalZero break;
664*150812a8SEvalZero
665*150812a8SEvalZero case NRFX_NFCT_PARAM_ID_NFCID1:
666*150812a8SEvalZero {
667*150812a8SEvalZero nrf_nfct_sensres_nfcid1_size_t id_size_mask;
668*150812a8SEvalZero
669*150812a8SEvalZero id_size_mask = nrf_nfct_nfcid1_size_to_sensres_size(p_param->data.nfcid1.id_size);
670*150812a8SEvalZero nrf_nfct_nfcid1_set(p_param->data.nfcid1.p_id, id_size_mask);
671*150812a8SEvalZero break;
672*150812a8SEvalZero }
673*150812a8SEvalZero
674*150812a8SEvalZero default:
675*150812a8SEvalZero break;
676*150812a8SEvalZero }
677*150812a8SEvalZero
678*150812a8SEvalZero return NRFX_SUCCESS;
679*150812a8SEvalZero }
680*150812a8SEvalZero
nrfx_nfct_nfcid1_default_bytes_get(uint8_t * const p_nfcid1_buff,uint32_t nfcid1_buff_len)681*150812a8SEvalZero nrfx_err_t nrfx_nfct_nfcid1_default_bytes_get(uint8_t * const p_nfcid1_buff,
682*150812a8SEvalZero uint32_t nfcid1_buff_len)
683*150812a8SEvalZero {
684*150812a8SEvalZero if ((nfcid1_buff_len != NRFX_NFCT_NFCID1_SINGLE_SIZE) &&
685*150812a8SEvalZero (nfcid1_buff_len != NRFX_NFCT_NFCID1_DOUBLE_SIZE) &&
686*150812a8SEvalZero (nfcid1_buff_len != NRFX_NFCT_NFCID1_TRIPLE_SIZE))
687*150812a8SEvalZero {
688*150812a8SEvalZero return NRFX_ERROR_INVALID_LENGTH;
689*150812a8SEvalZero }
690*150812a8SEvalZero
691*150812a8SEvalZero uint32_t nfc_tag_header0 = NRF_FICR->NFC.TAGHEADER0;
692*150812a8SEvalZero uint32_t nfc_tag_header1 = NRF_FICR->NFC.TAGHEADER1;
693*150812a8SEvalZero uint32_t nfc_tag_header2 = NRF_FICR->NFC.TAGHEADER2;
694*150812a8SEvalZero
695*150812a8SEvalZero p_nfcid1_buff[0] = (uint8_t) (nfc_tag_header0 >> 0);
696*150812a8SEvalZero p_nfcid1_buff[1] = (uint8_t) (nfc_tag_header0 >> 8);
697*150812a8SEvalZero p_nfcid1_buff[2] = (uint8_t) (nfc_tag_header0 >> 16);
698*150812a8SEvalZero p_nfcid1_buff[3] = (uint8_t) (nfc_tag_header1 >> 0);
699*150812a8SEvalZero
700*150812a8SEvalZero if (nfcid1_buff_len != NRFX_NFCT_NFCID1_SINGLE_SIZE)
701*150812a8SEvalZero {
702*150812a8SEvalZero p_nfcid1_buff[4] = (uint8_t) (nfc_tag_header1 >> 8);
703*150812a8SEvalZero p_nfcid1_buff[5] = (uint8_t) (nfc_tag_header1 >> 16);
704*150812a8SEvalZero p_nfcid1_buff[6] = (uint8_t) (nfc_tag_header1 >> 24);
705*150812a8SEvalZero
706*150812a8SEvalZero if (nfcid1_buff_len == NRFX_NFCT_NFCID1_TRIPLE_SIZE)
707*150812a8SEvalZero {
708*150812a8SEvalZero p_nfcid1_buff[7] = (uint8_t) (nfc_tag_header2 >> 0);
709*150812a8SEvalZero p_nfcid1_buff[8] = (uint8_t) (nfc_tag_header2 >> 8);
710*150812a8SEvalZero p_nfcid1_buff[9] = (uint8_t) (nfc_tag_header2 >> 16);
711*150812a8SEvalZero }
712*150812a8SEvalZero /* Begin: Bugfix for FTPAN-181. */
713*150812a8SEvalZero /* Workaround for wrong value in NFCID1. Value 0x88 cannot be used as byte 3
714*150812a8SEvalZero of a double-size NFCID1, according to the NFC Forum Digital Protocol specification. */
715*150812a8SEvalZero else if (p_nfcid1_buff[3] == 0x88)
716*150812a8SEvalZero {
717*150812a8SEvalZero p_nfcid1_buff[3] |= 0x11;
718*150812a8SEvalZero }
719*150812a8SEvalZero /* End: Bugfix for FTPAN-181 */
720*150812a8SEvalZero }
721*150812a8SEvalZero
722*150812a8SEvalZero return NRFX_SUCCESS;
723*150812a8SEvalZero }
724*150812a8SEvalZero
nrfx_nfct_autocolres_enable(void)725*150812a8SEvalZero void nrfx_nfct_autocolres_enable(void)
726*150812a8SEvalZero {
727*150812a8SEvalZero #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
728*150812a8SEvalZero (*(uint32_t *)(0x4000559C)) &= (~(0x1UL));
729*150812a8SEvalZero #else
730*150812a8SEvalZero nrf_nfct_autocolres_enable();
731*150812a8SEvalZero #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
732*150812a8SEvalZero }
733*150812a8SEvalZero
nrfx_nfct_autocolres_disable(void)734*150812a8SEvalZero void nrfx_nfct_autocolres_disable(void)
735*150812a8SEvalZero {
736*150812a8SEvalZero #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
737*150812a8SEvalZero (*(uint32_t *)(0x4000559C)) |= (0x1UL);
738*150812a8SEvalZero #else
739*150812a8SEvalZero nrf_nfct_autocolres_disable();
740*150812a8SEvalZero #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
741*150812a8SEvalZero }
742*150812a8SEvalZero
nrfx_nfct_irq_handler(void)743*150812a8SEvalZero void nrfx_nfct_irq_handler(void)
744*150812a8SEvalZero {
745*150812a8SEvalZero nrfx_nfct_field_state_t current_field = NRFX_NFC_FIELD_STATE_NONE;
746*150812a8SEvalZero
747*150812a8SEvalZero if (NRFX_NFCT_EVT_ACTIVE(FIELDDETECTED))
748*150812a8SEvalZero {
749*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_FIELDDETECTED);
750*150812a8SEvalZero current_field = NRFX_NFC_FIELD_STATE_ON;
751*150812a8SEvalZero
752*150812a8SEvalZero NRFX_LOG_DEBUG("Field detected");
753*150812a8SEvalZero }
754*150812a8SEvalZero
755*150812a8SEvalZero #if !defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
756*150812a8SEvalZero if (NRFX_NFCT_EVT_ACTIVE(FIELDLOST))
757*150812a8SEvalZero {
758*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_FIELDLOST);
759*150812a8SEvalZero current_field = (current_field == NRFX_NFC_FIELD_STATE_NONE) ?
760*150812a8SEvalZero NRFX_NFC_FIELD_STATE_OFF : NRFX_NFC_FIELD_STATE_UNKNOWN;
761*150812a8SEvalZero
762*150812a8SEvalZero NRFX_LOG_DEBUG("Field lost");
763*150812a8SEvalZero }
764*150812a8SEvalZero #endif //!defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
765*150812a8SEvalZero
766*150812a8SEvalZero /* Perform actions if any FIELD event is active */
767*150812a8SEvalZero if (current_field != NRFX_NFC_FIELD_STATE_NONE)
768*150812a8SEvalZero {
769*150812a8SEvalZero nrfx_nfct_field_event_handler(current_field);
770*150812a8SEvalZero }
771*150812a8SEvalZero
772*150812a8SEvalZero if (NRFX_NFCT_EVT_ACTIVE(RXFRAMEEND))
773*150812a8SEvalZero {
774*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_RXFRAMEEND);
775*150812a8SEvalZero
776*150812a8SEvalZero nrfx_nfct_evt_t nfct_evt =
777*150812a8SEvalZero {
778*150812a8SEvalZero .evt_id = NRFX_NFCT_EVT_RX_FRAMEEND
779*150812a8SEvalZero };
780*150812a8SEvalZero
781*150812a8SEvalZero /* Take into account only the number of whole bytes. */
782*150812a8SEvalZero nfct_evt.params.rx_frameend.rx_status = 0;
783*150812a8SEvalZero nfct_evt.params.rx_frameend.rx_data.p_data = nrf_nfct_rxtx_buffer_get();
784*150812a8SEvalZero nfct_evt.params.rx_frameend.rx_data.data_size = NRFX_NFCT_BITS_TO_BYTES(nrf_nfct_rx_bits_get(true));
785*150812a8SEvalZero
786*150812a8SEvalZero if (NRFX_NFCT_EVT_ACTIVE(RXERROR))
787*150812a8SEvalZero {
788*150812a8SEvalZero nfct_evt.params.rx_frameend.rx_status =
789*150812a8SEvalZero (nrf_nfct_rx_frame_status_get() & NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
790*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_RXERROR);
791*150812a8SEvalZero
792*150812a8SEvalZero NRFX_LOG_DEBUG("Rx error (0x%x)", (unsigned int) nfct_evt.params.rx_frameend.rx_status);
793*150812a8SEvalZero
794*150812a8SEvalZero /* Clear rx frame status */
795*150812a8SEvalZero nrf_nfct_rx_frame_status_clear(NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
796*150812a8SEvalZero }
797*150812a8SEvalZero
798*150812a8SEvalZero NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
799*150812a8SEvalZero
800*150812a8SEvalZero /* Clear TXFRAMESTART EVENT so it can be checked in hal_nfc_send */
801*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMESTART);
802*150812a8SEvalZero
803*150812a8SEvalZero NRFX_LOG_DEBUG("Rx fend");
804*150812a8SEvalZero }
805*150812a8SEvalZero
806*150812a8SEvalZero if (NRFX_NFCT_EVT_ACTIVE(TXFRAMEEND))
807*150812a8SEvalZero {
808*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMEEND);
809*150812a8SEvalZero
810*150812a8SEvalZero nrfx_nfct_evt_t nfct_evt =
811*150812a8SEvalZero {
812*150812a8SEvalZero .evt_id = NRFX_NFCT_EVT_TX_FRAMEEND
813*150812a8SEvalZero };
814*150812a8SEvalZero
815*150812a8SEvalZero /* Disable TX END event to ignore frame transmission other than READ response */
816*150812a8SEvalZero nrf_nfct_int_disable(NRFX_NFCT_TX_INT_MASK);
817*150812a8SEvalZero
818*150812a8SEvalZero NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
819*150812a8SEvalZero
820*150812a8SEvalZero NRFX_LOG_DEBUG("Tx fend");
821*150812a8SEvalZero }
822*150812a8SEvalZero
823*150812a8SEvalZero if (NRFX_NFCT_EVT_ACTIVE(SELECTED))
824*150812a8SEvalZero {
825*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_SELECTED);
826*150812a8SEvalZero /* Clear also RX END and RXERROR events because SW does not take care of
827*150812a8SEvalZero commands that were received before selecting the tag. */
828*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_RXFRAMEEND);
829*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_RXERROR);
830*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMESTART);
831*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMEEND);
832*150812a8SEvalZero
833*150812a8SEvalZero /* At this point any previous error status can be ignored. */
834*150812a8SEvalZero nrf_nfct_rx_frame_status_clear(NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
835*150812a8SEvalZero nrf_nfct_error_status_clear(NRFX_NFCT_ERROR_STATUS_ALL_MASK);
836*150812a8SEvalZero
837*150812a8SEvalZero nrfx_nfct_evt_t nfct_evt =
838*150812a8SEvalZero {
839*150812a8SEvalZero .evt_id = NRFX_NFCT_EVT_SELECTED
840*150812a8SEvalZero };
841*150812a8SEvalZero NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
842*150812a8SEvalZero
843*150812a8SEvalZero NRFX_LOG_DEBUG("Selected");
844*150812a8SEvalZero }
845*150812a8SEvalZero
846*150812a8SEvalZero if (NRFX_NFCT_EVT_ACTIVE(ERROR))
847*150812a8SEvalZero {
848*150812a8SEvalZero uint32_t err_status = nrf_nfct_error_status_get();
849*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_ERROR);
850*150812a8SEvalZero
851*150812a8SEvalZero nrfx_nfct_evt_t nfct_evt =
852*150812a8SEvalZero {
853*150812a8SEvalZero .evt_id = NRFX_NFCT_EVT_ERROR
854*150812a8SEvalZero };
855*150812a8SEvalZero
856*150812a8SEvalZero /* Clear FRAMEDELAYTIMEOUT error (expected HW behaviour) when SLP_REQ command was received. */
857*150812a8SEvalZero if (err_status & NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK)
858*150812a8SEvalZero {
859*150812a8SEvalZero nrf_nfct_error_status_clear(NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK);
860*150812a8SEvalZero
861*150812a8SEvalZero nfct_evt.params.error.reason = NRFX_NFCT_ERROR_FRAMEDELAYTIMEOUT;
862*150812a8SEvalZero NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
863*150812a8SEvalZero }
864*150812a8SEvalZero
865*150812a8SEvalZero /* Report any other error. */
866*150812a8SEvalZero err_status &= ~NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK;
867*150812a8SEvalZero if (err_status)
868*150812a8SEvalZero {
869*150812a8SEvalZero NRFX_LOG_DEBUG("Error (0x%x)", (unsigned int) err_status);
870*150812a8SEvalZero }
871*150812a8SEvalZero
872*150812a8SEvalZero /* Clear error status. */
873*150812a8SEvalZero nrf_nfct_error_status_clear(NRFX_NFCT_ERROR_STATUS_ALL_MASK);
874*150812a8SEvalZero }
875*150812a8SEvalZero
876*150812a8SEvalZero if (NRFX_NFCT_EVT_ACTIVE(TXFRAMESTART))
877*150812a8SEvalZero {
878*150812a8SEvalZero nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMESTART);
879*150812a8SEvalZero
880*150812a8SEvalZero if (m_nfct_cb.config.cb != NULL)
881*150812a8SEvalZero {
882*150812a8SEvalZero nrfx_nfct_evt_t nfct_evt;
883*150812a8SEvalZero
884*150812a8SEvalZero nfct_evt.evt_id = NRFX_NFCT_EVT_TX_FRAMESTART;
885*150812a8SEvalZero nfct_evt.params.tx_framestart.tx_data.p_data = nrf_nfct_rxtx_buffer_get();
886*150812a8SEvalZero nfct_evt.params.tx_framestart.tx_data.data_size = NRFX_NFCT_BITS_TO_BYTES(nrf_nfct_tx_bits_get());
887*150812a8SEvalZero
888*150812a8SEvalZero m_nfct_cb.config.cb(&nfct_evt);
889*150812a8SEvalZero }
890*150812a8SEvalZero }
891*150812a8SEvalZero }
892*150812a8SEvalZero
893*150812a8SEvalZero #endif // NRFX_CHECK(NRFX_NFCT_ENABLED)
894