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