xref: /nrf52832-nimble/nordic/nrfx/drivers/src/nrfx_nfct.c (revision 150812a83cab50279bd772ef6db1bfaf255f2c5b)
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