This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NFC Tag reading unreliable

Hi,

Sometimes our custom board is not readable with the reader uTrust3700 from Identive and it might be related to this post. We are usind SDK 14.2 with our custom board, but after some investigation the problem does also exist with the Nordic DK (PCA10040, V1.1.1) and SDK16. We have tested with writable_ndef_msg example. We have logged received messages  in the nrfx_nfct_irq_handler in NRFX_NFCT_EVT_ACTIVE(RXFRAMEEND) and found out that when this problem occurs the first received Byte (either 0x02 or 0x03) is missing in the nfct_evt.params.rx_frameend.rx_data.p_data of the nrfx_nfct.c driver. The reader is continously polling for cards and when everything works fine we ge the following sequence of received Messages with RXFRAMEEND, each line is a received Message, with the first byte containing the Message size, the message itself and with the last two bytes as crc :

11 02 00 a4 04 00 0b a0 00 00 03 97 43 49 44 5f 01 00 05 65
06 03 00 ca 7f 68 00 33 bd
08 02 00 a4 00 00 02 3f 00 e9 4e
0f 03 00 a4 04 00 09 a0 00 00 03 08 00 00 10 00 69 66
0f 02 00 a4 04 00 09 a0 00 00 03 97 42 54 46 59 8a fd

When the problem occurs, we get following sequence, the first line contains the last correctly received message, followed by some single byte receptions. After the single byte receptions the received messages are one byte shorter then previously and the first byte (either 02 or 03 is missing). all other data is the same except the crc bytes.

0f 02 00 a4 04 00 09 a0 00 00 03 08 00 00 10 00 43 2e
01 b2 67 c7
01 b2 67 c7
01 c2 e0 b4
01 c2 e0 b4
01 c2 e0 b4
01 c2 e0 b4
0e 00 a4 04 00 09 a0 00 00 03 97 42 54 46 59 cd bb
10 00 a4 04 00 0b a0 00 00 03 97 43 49 44 5f 01 00 59 49
05 00 ca 7f 68 00 ab 86
07 00 a4 00 00 02 3f 00 9b 97
0e 00 a4 04 00 09 a0 00 00 03 08 00 00 10 00 04 68
0e 00 a4 04 00 09 a0 00 00 03 97 42 54 46 59 cd bb

Logging was quite difficult, as using NRF_LOG_HEXDUMP_INFO forces that the problem always to occurs. So we implemented a buffer for storing the received messages and reading them in debugger.

I suspect this is a timing Issue in the Driver, as when using HEX_DUMP it always fails. Do you have a solution or a workaround for this problem?

Kind Regards

Michael

  • We have not seen this in our DK, so I am suspecting this could be your custom board related. Have you tried replicating this error in the DK so that  I can try to reproduce it here and help in debugging?

  • I have reproduced it on my DK and the data above is all generated from replicating the Problem with the DK. It's a PCA 10040; V1.1.1; 2017.5; 682653462.

  • Hi Michael,

    I looked at your description and have a couple of comments (but I don't know what the exact problem is):

    • The one-byte frames from the Reader are: R(NAK) and S(DESELECT); R(NAK) is typically send by the Reader to trigger retransmission of the last frame from the Tag; S(DESELCT) is used to put the Tag in a sleep mode and search for other tags in the field
    • The frames displayed after the one-byte packets look invalid (they seem to be missing the block header called SoD), we haven't seen such a problem with our driver i.e. truncating the Rx frames
    • Possibly there is some problem with DID field handling - the 0x00 bytes seem to be DID field with DID value set to 0, which is e specific value and according to the spec this byte SHOULD not be transmitted by the Reader, anyways our stack supports such case and should continue communication without any problem (this specific issue was described in the linked, old Devzone post)

    To help understand the problem better do you think you could provide the following information?

    • it would be great to see the RATS command, which should come from the Reader, before the frames provided in the log in  the description - when activating the ISO-DEP protocol (they should ba available in the Rx data in the driver)
    • also it would be great to get some sniffer logs including responses that the Tag sends back to the Reader - like this we could analyze whether devices behave correctly vs specs

    Kind regards,

    Michał

  • Hi Michal,

    I've now switched to the nfc_uart_tag example, as this uses the ISO-DEP protocol. In main I've added two lines in the nfc_callback directly after case NFC_T4T_EVENT_DATA_IND: to log the data received. these lines are:

    case NFC_T4T_EVENT_DATA_IND:
                NRFX_LOG_INFO("NFC Data Indication:");
                NRFX_LOG_HEXDUMP_INFO(data, dataLength);

    in the nrfx_nfct.c file i've added a hexdump after Tx Start in the function nrfx_nfct_tx() for additional logging:

        NRFX_LOG_INFO("Tx start");
        NRFX_LOG_HEXDUMP_INFO(p_tx_data->p_data, p_tx_data->data_size);

    and also for logging RX i've added in the nrfx_nfct_irq_handler() whithin RXFRAMEEND:

              NRFX_LOG_INFO("Rx fend");
              NRFX_LOG_HEXDUMP_INFO(nfct_evt.params.rx_frameend.rx_data.p_data, nfct_evt.params.rx_frameend.rx_data.data_size);

    With this additional logging i could create two logfiles, the first one where everything works correct and the second one with the error. Both files are added, as well as the modified nrfx_nfct.c file. please let me know if i can do further investigations. I could even provide one of our Identive card readers to you.

    0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  E0 80                  |..      
     0> <info> NFCT: Tx start
     0> <info> NFCT:  05 78 80 42 02         |.x.B.   
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  C2                     |.       
     0> <info> NFCT: Tx start
     0> <info> NFCT:  C2                     |.       
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  E0 80                  |..      
     0> <info> NFCT: Tx start
     0> <info> NFCT:  05 78 80 42 02         |.x.B.   
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  02 00 A4 04 00 0B A0 00|........
     0> <info> NFCT:  00 03 97 43 49 44 5F 01|...CID_.
     0> <info> NFCT:  00                     |.       
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 04 00 0B A0 00 00|........
     0> <info> app:  03 97 43 49 44 5F 01 00|..CID_..
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  03 00 CA 7F 68 00      |....h.  
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 CA 7F 68 00         |...h.   
     0> <info> NFCT: Tx start
     0> <info> app:  00 A4 04 00 0B A0 00 00|........
     0> <info> app:  03 97 43 49 44 5F 01 00|..CID_..
     0> <info> NFCT: Tx start
     0> <info> NFCT:  03 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  02 00 CA 7F 68 00      |....h.  
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 CA 7F 68 00         |...h.   
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  03 00 A4 00 00 02 3F 00|......?.
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> NFCT: Tx start
     0> <info> app:  00 A4 04 00 09 A0 00 00|........
     0> <info> app:  03 08 00 00 10 00      |......  
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  03 00 A4 04 00 09 A0 00|........
     0> <info> NFCT:  00 03 97 42 54 46 59   |...BTFY 
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 04 00 09 A0 00 00|........
     0> <info> NFCT: Tx start
     0> <info> NFCT:  03 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  02 00 A4 04 00 0B A0 00|........
     0> <info> NFCT:  00 03 97 43 49 44 5F 01|...CID_.
     0> <info> NFCT:  00                     |.       
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 04 00 0B A0 00 00|........
     0> <info> app:  03 97 43 49 44 5F 01 00|..CID_..
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> app:  03 08 00 00 10 00      |......  
     0> <info> NFCT: Tx start
     0> <info> NFCT:  03 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  02 00 A4 04 00 09 A0 00|........
     0> <info> NFCT:  00 03 97 42 54 46 59   |...BTFY 
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  03 00 A4 04 00 0B A0 00|........
     0> <info> NFCT:  00 03 97 43 49 44 5F 01|...CID_.
     0> <info> NFCT:  00                     |.       
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  03 00 A4 00 00 02 3F 00|......?.
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 00 00 02 3F 00   |.....?. 
     0> <info> NFCT: Tx start
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 04 00 0B A0 00 00|........
     0> <info> app:  03 97 43 49 44 5F 01 00|..CID_..
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  03 00 CA 7F 68 00      |....h.  
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 CA 7F 68 00         |...h.   
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 00 00 02 3F 00   |.....?. 
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  03 00 A4 04 00 09 A0 00|........
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  B3                     |.       
     0> <info> NFCT: Tx start
     0> <info> NFCT:  A2                     |.       
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  B3                     |.       
     0> <info> NFCT: Tx start
     0> <info> NFCT:  A2                     |.       
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  B3                     |.       
     0> <info> NFCT: Tx start
     0> <info> NFCT:  A2                     |.       
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  B3                     |.       
     0> <info> NFCT: Tx start
     0> <info> NFCT:  A2                     |.       
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  E0 80                  |..      
     0> <info> NFCT: Tx start
     0> <info> NFCT:  05 78 80 42 02         |.x.B.   
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  02 00 A4 04 00 0B A0 00|........
     0> <info> NFCT:  00 03 97 43 49 44 5F 01|...CID_.
     0> <info> NFCT:  00                     |.       
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 04 00 0B A0 00 00|........
     0> <info> app:  03 97 43 49 44 5F 01 00|..CID_..
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 CA 7F 68 00         |...h.   
     0> <info> NFCT: Tx start
     0> <info> NFCT:  03 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 00 00 02 3F 00   |.....?. 
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  03 00 A4 04 00 09 A0 00|........
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 04 00 09 A0 00 00|........
     0> <info> app:  03 08 00 00 10 00      |......  
     0> <info> NFCT: Tx start
     0> <info> NFCT:  03 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  03 00 A4 04 00 0B A0 00|........
     0> <info> NFCT:  00 03 97 43 49 44 5F 01|...CID_.
     0> <info> NFCT:  00                     |.       
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> NFCT: Tx start
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  02 00 CA 7F 68 00      |....h.  
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 CA 7F 68 00         |...h.   
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  03 00 A4 00 00 02 3F 00|......?.
     0> <info> NFCT: Tx start
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 00 00 02 3F 00   |.....?. 
     0> <info> NFCT: Tx start
     0> <info> NFCT:  03 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 04 00 09 A0 00 00|........
     0> <info> app:  03 08 00 00 10 00      |......  
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 04 00 09 A0 00 00|........
     0> <info> app:  03 97 42 54 46 59      |..BTFY  
     0> <info> NFCT: Tx start
     0> <info> NFCT:  03 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  02 00 A4 04 00 0B A0 00|........
     0> <info> NFCT:  00                     |.       
     0> <info> NFCT: Tx start
     0> <info> NFCT:  F2 08                  |..      
     0> <info> app: NFC Data Indication:
     0> <info> app:  00 A4 04 00 0B A0 00 00|........
     0> <info> NFCT: Tx start
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  B2                     |.       
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  B2                     |.       
     0> <info> NFCT: Tx start
     0> <info> NFCT:  02 00                  |..      
     0> <info> NFCT: Rx fend
     0> <info> NFCT: Tx start
     0> <info> NFCT:  C2                     |.       
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 CA 7F 68 00         |...h.   
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 A4 00 00 02 3F 00   |.....?. 
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 A4 04 00 09 A0 00 00|........
     0> <info> NFCT:  03 08 00 00 10 00      |......  
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 A4 04 00 09 A0 00 00|........
     0> <info> NFCT:  03 97 42 54 46 59      |..BTFY  
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 A4 04 00 0B A0 00 00|........
     0> <info> NFCT:  03 97 43 49 44 5F 01 00|..CID_..
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 CA 7F 68 00         |...h.   
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 A4 00 00 02 3F 00   |.....?. 
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 A4 04 00 09 A0 00 00|........
     0> <info> NFCT:  03 08 00 00 10 00      |......  
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 A4 04 00 09 A0 00 00|........
     0> <info> NFCT:  03 97 42 54 46 59      |..BTFY  
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 A4 04 00 0B A0 00 00|........
     0> <info> NFCT:  03 97 43 49 44 5F 01 00|..CID_..
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 CA 7F 68 00         |...h.   
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 A4 00 00 02 3F 00   |.....?. 
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 A4 04 00 09 A0 00 00|........
     0> <info> NFCT:  03 08 00 00 10 00      |......  
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Rx fend
     0> <info> NFCT:  00 A4 04 00 09 A0 00 00|........
     0> <info> NFCT:  03 97 42 54 46 59      |..BTFY  
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> app: NFC Tag has been selected. UART transmission can start...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> NFCT: Reinitialize
     0> <info> app: NFC field lost. Data from UART will be discarded...
     0> <info> app: Button pressed
     0> <info> app: Button released
    
    # Logging stopped @ 05 Mar 2020 16:02:44
    
    /**
     * Copyright (c) 2018 - 2019, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    
    #include <nrfx.h>
    
    #if NRFX_CHECK(NRFX_NFCT_ENABLED)
    
    #include <nrfx_nfct.h>
    
    #define NRFX_LOG_MODULE NFCT
    #include <nrfx_log.h>
    
    #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || \
        defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
    #define USE_TIMER_WORKAROUND
    #endif
    
    #if defined(USE_TIMER_WORKAROUND)
    #include <nrfx_timer.h>
    
    typedef struct
    {
        const nrfx_timer_t timer;                     /**< Timer instance that supports the correct NFC field detection. */
    #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
        bool               fieldevents_filter_active; /**< Flag that indicates that the field events are ignored. */
        bool               is_hfclk_on;               /**< HFCLK has started - one of the NFC activation conditions. */
        bool               is_delayed;                /**< Required time delay has passed - one of the NFC activation conditions. */
    #else
        uint32_t           field_state_cnt;           /**< Counter of the FIELDLOST events. */
    #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
    } nrfx_nfct_timer_workaround_t;
    
    #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
        #define NRFX_NFCT_ACTIVATE_DELAY     1000 /**< Minimal delay in us between NFC field detection and activation of NFCT. */
        #define NRFX_NFCT_TIMER_PERIOD       NRFX_NFCT_ACTIVATE_DELAY
    #else
        #define NRFX_NFCT_FIELDLOST_THR      7
        #define NRFX_NFCT_FIELD_TIMER_PERIOD 100  /**< Field polling period in us. */
        #define NRFX_NFCT_TIMER_PERIOD       NRFX_NFCT_FIELD_TIMER_PERIOD
    #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
    #define NRFX_NFCT_TIMER_INSTANCE         4    /**< Timer instance used for various workarounds for the NFCT HW issues.*/
    
    static nrfx_nfct_timer_workaround_t m_timer_workaround = 
    {
        .timer = NRFX_TIMER_INSTANCE(NRFX_NFCT_TIMER_INSTANCE),
    };
    #endif // defined(USE_TIMER_WORKAROUND)
    
    #define NRFX_NFCT_FWT_MAX_DIFF         1u             /**< The maximal difference between the requested FWT and HW-limited FWT settings.*/
    #define NFCT_FRAMEDELAYMAX_DEFAULT     (0x00001000UL) /**< Default value of the FRAMEDELAYMAX. */
    
    /* Mask of all possible interrupts that are relevant for data reception. */
    #define NRFX_NFCT_RX_INT_MASK (NRF_NFCT_INT_RXFRAMESTART_MASK | \
                                   NRF_NFCT_INT_RXFRAMEEND_MASK   | \
                                   NRF_NFCT_INT_RXERROR_MASK)
    
    /* Mask of all possible interrupts that are relevant for data transmission. */
    #define NRFX_NFCT_TX_INT_MASK (NRF_NFCT_INT_TXFRAMESTART_MASK | \
                                   NRF_NFCT_INT_TXFRAMEEND_MASK)
    
    
    /* Mask of all possible errors from the @ref NRF_NFCT_EVENT_RXERROR event. */
    #define NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK (NRF_NFCT_RX_FRAME_STATUS_CRC_MASK    | \
                                                NRF_NFCT_RX_FRAME_STATUS_PARITY_MASK | \
                                                NRF_NFCT_RX_FRAME_STATUS_OVERRUN_MASK)
    
    /* Mask of all possible errors from the @ref NRF_NFCT_EVENT_ERROR event. */
    #if defined (NRF52832_XXAA) || defined(NRF52832_XXAB)
    #define NRFX_NFCT_ERROR_STATUS_ALL_MASK (NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK | \
                                             NRF_NFCT_ERROR_NFCFIELDTOOSTRONG_MASK | \
                                             NRF_NFCT_ERROR_NFCFIELDTOOWEAK_MASK)
    #else
    #define NRFX_NFCT_ERROR_STATUS_ALL_MASK (NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK)
    #endif
    
    /* Macros for conversion of bits to bytes. */
    #define NRFX_NFCT_BYTES_TO_BITS(_bytes) ((_bytes) << 3)
    #define NRFX_NFCT_BITS_TO_BYTES(_bits)  ((_bits)  >> 3)
    
    /* Macro for checking whether the NFCT interrupt is active. */
    #define NRFX_NFCT_EVT_ACTIVE(_name) (nrf_nfct_event_check(NRFX_CONCAT_2(NRF_NFCT_EVENT_, _name)) &&        \
                                         nrf_nfct_int_enable_check(NRFX_CONCAT_3(NRF_NFCT_INT_, _name, _MASK)))
    
    /* Macro for callback execution. */
    #define NRFX_NFCT_CB_HANDLE(_cb, _evt) \
        if (_cb != NULL)                   \
        {                                  \
            _cb(&_evt);                    \
        }
    
    typedef enum
    {
        NRFX_NFC_FIELD_STATE_NONE,   /**< Initial value that indicates no NFCT field events. */
        NRFX_NFC_FIELD_STATE_OFF,    /**< The NFCT FIELDLOST event has been set. */
        NRFX_NFC_FIELD_STATE_ON,     /**< The NFCT FIELDDETECTED event has been set. */
        NRFX_NFC_FIELD_STATE_UNKNOWN /**< Both NFCT field events have been set - ambiguous state. */
    } nrfx_nfct_field_state_t;
    
    /**@brief NFCT control block. */
    typedef struct
    {
        nrfx_nfct_config_t config;
        nrfx_drv_state_t   state;
        volatile bool      field_on;
        uint32_t           frame_delay_max;
    } nrfx_nfct_control_block_t;
    
    static nrfx_nfct_control_block_t m_nfct_cb;
    
    /**
     * @brief Common part of the setup used for the NFCT initialization and reinitialization.
     */
    static void nrfx_nfct_hw_init_setup(void)
    {
        // Use Window Grid frame delay mode.
        nrf_nfct_frame_delay_mode_set(NRF_NFCT_FRAME_DELAY_MODE_WINDOWGRID);
    
        /* Begin: Bugfix for FTPAN-25 (IC-9929) */
        /* Workaround for wrong SENSRES values require using SDD00001, but here SDD00100 is used
           because it is required to operate with Windows Phone */
        nrf_nfct_sensres_bit_frame_sdd_set(NRF_NFCT_SENSRES_BIT_FRAME_SDD_00100);
        /* End: Bugfix for FTPAN-25 (IC-9929) */
    }
    
    static void nrfx_nfct_frame_delay_max_set(bool default_delay)
    {
        if (default_delay)
        {
            nrf_nfct_frame_delay_max_set(NFCT_FRAMEDELAYMAX_DEFAULT);
        }
        else
        {
            nrf_nfct_frame_delay_max_set(m_nfct_cb.frame_delay_max);
        }
    }
    
    /**@brief Function for evaluating and handling the NFC field events.
     *
     * @param[in]  field_state  Current field state.
     */
    static void nrfx_nfct_field_event_handler(volatile nrfx_nfct_field_state_t field_state)
    {
        nrfx_nfct_evt_t nfct_evt;
    
    #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
        if(m_timer_workaround.fieldevents_filter_active)
        {
            return;
        }
    #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
    
        if (field_state == NRFX_NFC_FIELD_STATE_UNKNOWN)
        {
            /* Probe NFC field */
            field_state = (nrfx_nfct_field_check()) ? NRFX_NFC_FIELD_STATE_ON : NRFX_NFC_FIELD_STATE_OFF;
        }
    
        /* Field event service */
        switch (field_state)
        {
            case NRFX_NFC_FIELD_STATE_ON:
                if (!m_nfct_cb.field_on)
                {
    #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
                    /* Begin: Bugfix for FTPAN-190 */
                    m_timer_workaround.is_hfclk_on               = false;
                    m_timer_workaround.is_delayed                = false;
                    m_timer_workaround.fieldevents_filter_active = true;
    
                    nrfx_timer_clear(&m_timer_workaround.timer);
                    nrfx_timer_enable(&m_timer_workaround.timer);
                    /* END: Bugfix for FTPAN-190 */
    #elif defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
                    nrfx_timer_clear(&m_timer_workaround.timer);
                    nrfx_timer_enable(&m_timer_workaround.timer);
                    m_timer_workaround.field_state_cnt = 0;  
    #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
    
                    m_nfct_cb.field_on = true;
                    nfct_evt.evt_id    = NRFX_NFCT_EVT_FIELD_DETECTED;
                    NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
                }
                break;
    
            case NRFX_NFC_FIELD_STATE_OFF:
                nrfx_nfct_state_force(NRFX_NFCT_STATE_SENSING);
                nrf_nfct_int_disable(NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
                m_nfct_cb.field_on = false;
                nfct_evt.evt_id    = NRFX_NFCT_EVT_FIELD_LOST;
    
                /* Begin: Bugfix for FTPAN-218 */
                nrfx_nfct_frame_delay_max_set(true);
                /* End: Bugfix for FTPAN-218 */
    
                NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
                break;
    
            default:
                /* No implementation required */
                break;
        }
    }
    
    #if defined(USE_TIMER_WORKAROUND)
    
    #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
    static void nrfx_nfct_activate_check(void)
    {
        static bool is_field_validation_pending = false;
    
        if (is_field_validation_pending)
        {
            is_field_validation_pending                  = false;
            m_timer_workaround.fieldevents_filter_active = false;
    
            // Check the field status and take action if field is lost.
            nrfx_nfct_field_event_handler(NRFX_NFC_FIELD_STATE_UNKNOWN);
            return;
        }
    
        if ((m_timer_workaround.is_hfclk_on) && (m_timer_workaround.is_delayed))
        {
            nrf_nfct_task_trigger(NRF_NFCT_TASK_ACTIVATE);
            is_field_validation_pending = true;
    
            // Start the timer second time to validate whether the tag has locked to the field.
            nrfx_timer_clear(&m_timer_workaround.timer);
            nrfx_timer_enable(&m_timer_workaround.timer);
        }
    }
    #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
    
    #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
    static inline void nrfx_nfct_reset(void)
    {
        uint32_t                       fdm;
        uint32_t                       int_enabled;
        uint8_t                        nfcid1[NRF_NFCT_SENSRES_NFCID1_SIZE_TRIPLE];
        nrf_nfct_sensres_nfcid1_size_t nfcid1_size;
        nrf_nfct_selres_protocol_t     protocol;
    
        // Save parameter settings before the reset of the NFCT peripheral.
        fdm         = nrf_nfct_frame_delay_max_get();
        nfcid1_size = nrf_nfct_nfcid1_get(nfcid1);
        protocol    = nrf_nfct_selsres_protocol_get();
        int_enabled = nrf_nfct_int_enable_get();
    
        // Reset the NFCT peripheral.
        *(volatile uint32_t *)0x40005FFC = 0;
        *(volatile uint32_t *)0x40005FFC;
        *(volatile uint32_t *)0x40005FFC = 1;
    
        // Restore parameter settings after the reset of the NFCT peripheral.
        nrf_nfct_frame_delay_max_set(fdm);
        nrf_nfct_nfcid1_set(nfcid1, nfcid1_size);
        nrf_nfct_selres_protocol_set(protocol);
    
        // Restore general HW configuration.
        nrfx_nfct_hw_init_setup();
    
        // Restore interrupts.
        nrf_nfct_int_enable(int_enabled);
    
        // Disable interrupts associated with data exchange.
        nrf_nfct_int_disable(NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
    
        NRFX_LOG_INFO("Reinitialize");
    }
    
    static void nrfx_nfct_field_poll(void)
    {
        if (!nrfx_nfct_field_check())
        {
            if (++m_timer_workaround.field_state_cnt > NRFX_NFCT_FIELDLOST_THR)
            {
                nrfx_nfct_evt_t nfct_evt =
                {
                    .evt_id = NRFX_NFCT_EVT_FIELD_LOST,
                };
    
                nrfx_timer_disable(&m_timer_workaround.timer);
                m_nfct_cb.field_on = false;
    
                /* Begin: Bugfix for FTPAN-218 */
                nrfx_nfct_frame_delay_max_set(true);
                /* End: Bugfix for FTPAN-218 */
    
                /* Begin: Bugfix for FTPAN-116 */
                // resume the NFCT to initialized state
                nrfx_nfct_reset();
                /* End: Bugfix for FTPAN-116 */
    
                NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
            }
            return;
        }
    
        m_timer_workaround.field_state_cnt = 0;
    }
    #endif // defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
    
    static void nrfx_nfct_field_timer_handler(nrf_timer_event_t event_type, void * p_context)
    {
        (void)p_context;
    
        if (event_type != NRF_TIMER_EVENT_COMPARE0)
        {
            return;
        }
    
    #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
        m_timer_workaround.is_delayed = true;
    
        nrfx_timer_disable(&m_timer_workaround.timer);
        nrfx_nfct_activate_check();
    #else
        nrfx_nfct_field_poll();
    #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
    }
    
    static inline nrfx_err_t nrfx_nfct_field_timer_config(void)
    {
        nrfx_err_t          err_code;
        nrfx_timer_config_t timer_cfg = 
        {
            .frequency          = NRF_TIMER_FREQ_1MHz,
            .mode               = NRF_TIMER_MODE_TIMER,
            .bit_width          = NRF_TIMER_BIT_WIDTH_16,
            .interrupt_priority = NRFX_NFCT_CONFIG_IRQ_PRIORITY
        };
    
        err_code = nrfx_timer_init(&m_timer_workaround.timer, &timer_cfg, nrfx_nfct_field_timer_handler);
        if (err_code != NRFX_SUCCESS)
        {
            return err_code;
        }
    
        nrfx_timer_extended_compare(&m_timer_workaround.timer,
                                    NRF_TIMER_CC_CHANNEL0,
                                    nrfx_timer_us_to_ticks(&m_timer_workaround.timer, NRFX_NFCT_TIMER_PERIOD),
                                    NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                    true);
        return err_code;
    }
    
    #endif // defined(USE_TIMER_WORKAROUND)
    
    static inline nrf_nfct_sensres_nfcid1_size_t nrf_nfct_nfcid1_size_to_sensres_size(uint8_t nfcid1_size)
    {
        switch (nfcid1_size)
        {
            case NRFX_NFCT_NFCID1_SINGLE_SIZE:
                return NRF_NFCT_SENSRES_NFCID1_SIZE_SINGLE;
    
            case NRFX_NFCT_NFCID1_DOUBLE_SIZE:
                return NRF_NFCT_SENSRES_NFCID1_SIZE_DOUBLE;
    
            case NRFX_NFCT_NFCID1_TRIPLE_SIZE:
                return NRF_NFCT_SENSRES_NFCID1_SIZE_TRIPLE;
    
            default:
                return NRF_NFCT_SENSRES_NFCID1_SIZE_DOUBLE;
        }
    }
    
    static inline void nrfx_nfct_rxtx_int_enable(uint32_t rxtx_int_mask)
    {
        nrf_nfct_int_enable(rxtx_int_mask & m_nfct_cb.config.rxtx_int_mask);
    }
    
    nrfx_err_t nrfx_nfct_init(nrfx_nfct_config_t const * p_config)
    {
        NRFX_ASSERT(p_config);
    
        nrfx_err_t err_code = NRFX_SUCCESS;
    
        if (m_nfct_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
        {
            return NRFX_ERROR_INVALID_STATE;
        }
    
        m_nfct_cb.config = *p_config;
        nrfx_nfct_hw_init_setup();
    
        NRFX_IRQ_PENDING_CLEAR(NFCT_IRQn);
        NRFX_IRQ_PRIORITY_SET(NFCT_IRQn, NRFX_NFCT_CONFIG_IRQ_PRIORITY);
        NRFX_IRQ_ENABLE(NFCT_IRQn);
    
    #if defined(USE_TIMER_WORKAROUND)
        /* Initialize Timer module as the workaround for NFCT HW issues. */
        err_code = nrfx_nfct_field_timer_config();
    #endif // defined(USE_TIMER_WORKAROUND)
    
        if (err_code == NRFX_SUCCESS)
        {
            uint8_t default_nfcid1[NRFX_NFCT_NFCID1_DEFAULT_LEN];
            err_code = nrfx_nfct_nfcid1_default_bytes_get(default_nfcid1, sizeof(default_nfcid1));
            NRFX_ASSERT(err_code == NRFX_SUCCESS);
            nrf_nfct_nfcid1_set(default_nfcid1, NRF_NFCT_SENSRES_NFCID1_SIZE_DEFAULT);
        }
        else
        {
            return err_code;
        }
    
        m_nfct_cb.state           = NRFX_DRV_STATE_INITIALIZED;
        m_nfct_cb.frame_delay_max = NFCT_FRAMEDELAYMAX_DEFAULT;
    
        NRFX_LOG_INFO("Initialized");
        return err_code;
    }
    
    void nrfx_nfct_uninit(void)
    {
        nrfx_nfct_disable();
    
        NRFX_IRQ_DISABLE(NFCT_IRQn);
        NRFX_IRQ_PENDING_CLEAR(NFCT_IRQn);
    
    #if defined(USE_TIMER_WORKAROUND)
        /* De-initialize Timer module as the workaround for NFCT HW issues. */
            nrfx_timer_uninit(&m_timer_workaround.timer);
    #endif // defined(USE_TIMER_WORKAROUND)
    
        m_nfct_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
    }
    
    void nrfx_nfct_enable(void)
    {
        nrf_nfct_error_status_clear(NRFX_NFCT_ERROR_STATUS_ALL_MASK);
        nrf_nfct_task_trigger(NRF_NFCT_TASK_SENSE);
    
        nrf_nfct_int_enable(NRF_NFCT_INT_FIELDDETECTED_MASK | NRF_NFCT_INT_ERROR_MASK |
                            NRF_NFCT_INT_SELECTED_MASK);
    #if !defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
        nrf_nfct_int_enable(NRF_NFCT_INT_FIELDLOST_MASK);
    #endif //!defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
    
        NRFX_LOG_INFO("Start");
    }
    
    void nrfx_nfct_disable(void)
    {
        nrf_nfct_int_disable(NRF_NFCT_DISABLE_ALL_INT);
        nrf_nfct_task_trigger(NRF_NFCT_TASK_DISABLE);
    
        NRFX_LOG_INFO("Stop");
    }
    
    bool nrfx_nfct_field_check(void)
    {
        uint32_t const field_state = nrf_nfct_field_status_get();
    
        if (((field_state & NRF_NFCT_FIELD_STATE_PRESENT_MASK) == 0) &&
            ((field_state & NRF_NFCT_FIELD_STATE_LOCK_MASK) == 0))
        {
            // Field is not active
            return false;
        }
    
        return true;
    }
    
    void nrfx_nfct_rx(nrfx_nfct_data_desc_t const * p_tx_data)
    {
        NRFX_ASSERT(p_tx_data);
    
        nrf_nfct_rxtx_buffer_set((uint8_t *) p_tx_data->p_data, p_tx_data->data_size);
    
        nrfx_nfct_rxtx_int_enable(NRFX_NFCT_RX_INT_MASK);
        nrf_nfct_task_trigger(NRF_NFCT_TASK_ENABLERXDATA);
    }
    
    nrfx_err_t nrfx_nfct_tx(nrfx_nfct_data_desc_t const * p_tx_data,
                            nrf_nfct_frame_delay_mode_t   delay_mode)
    {
        NRFX_ASSERT(p_tx_data);
        NRFX_ASSERT(p_tx_data->p_data);
    
        if (p_tx_data->data_size == 0)
        {
            return NRFX_ERROR_INVALID_LENGTH;
        }
    
        nrf_nfct_rxtx_buffer_set((uint8_t *) p_tx_data->p_data, p_tx_data->data_size);
        nrf_nfct_tx_bits_set(NRFX_NFCT_BYTES_TO_BITS(p_tx_data->data_size));
        nrf_nfct_frame_delay_mode_set((nrf_nfct_frame_delay_mode_t) delay_mode);
    
        nrfx_nfct_rxtx_int_enable(NRFX_NFCT_TX_INT_MASK);
        nrf_nfct_task_trigger(NRF_NFCT_TASK_STARTTX);
    
        NRFX_LOG_INFO("Tx start");
        NRFX_LOG_HEXDUMP_INFO(p_tx_data->p_data, p_tx_data->data_size);
        return NRFX_SUCCESS;
    }
    
    void nrfx_nfct_state_force(nrfx_nfct_state_t state)
    {
    #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
        if (state == NRFX_NFCT_STATE_ACTIVATED)
        {
            m_timer_workaround.is_hfclk_on = true;
            nrfx_nfct_activate_check();
        }
    #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
        nrf_nfct_task_trigger((nrf_nfct_task_t) state);
    }
    
    void nrfx_nfct_init_substate_force(nrfx_nfct_active_state_t sub_state)
    {
        if (sub_state == NRFX_NFCT_ACTIVE_STATE_DEFAULT)
        {
    #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
            if (((*(uint32_t volatile *)(0x40005420)) & 0x1UL) == (1UL))
    #else
            if (nrf_nfct_sleep_state_get() == NRF_NFCT_SLEEP_STATE_SLEEP_A)
    #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
            {
                // Default state is SLEEP_A
                nrf_nfct_task_trigger(NRF_NFCT_TASK_GOSLEEP);
            }
            else
            {
                // Default state is IDLE
                nrf_nfct_task_trigger(NRF_NFCT_TASK_GOIDLE);
            }
        }
        else
        {
            nrf_nfct_task_trigger((nrf_nfct_task_t) sub_state);
        }
    
        /* Begin: Bugfix for FTPAN-218 */
        nrfx_nfct_frame_delay_max_set(true);
        /* End: Bugfix for FTPAN-218 */
    
        /* Disable TX/RX here (will be enabled at SELECTED) */
        nrf_nfct_int_disable(NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
    }
    
    nrfx_err_t nrfx_nfct_parameter_set(nrfx_nfct_param_t const * p_param)
    {
        NRFX_ASSERT(p_param);
    
        switch (p_param->id)
        {
            case NRFX_NFCT_PARAM_ID_FDT:
            {
                uint32_t delay     = p_param->data.fdt;
                uint32_t delay_thr = NFCT_FRAMEDELAYMAX_FRAMEDELAYMAX_Msk;
    
                // Delay validation.
                if (delay > (delay_thr + NRFX_NFCT_FWT_MAX_DIFF))
                {
                    return NRFX_ERROR_INVALID_PARAM;
                }
    
                delay = (delay > delay_thr) ? delay_thr : delay;
                m_nfct_cb.frame_delay_max = delay;
                break;
            }
    
            case NRFX_NFCT_PARAM_ID_SEL_RES:
                if (p_param->data.sel_res_protocol > NRF_NFCT_SELRES_PROTOCOL_NFCDEP_T4AT)
                {
                    return NRFX_ERROR_INVALID_PARAM;
                }
    
                nrf_nfct_selres_protocol_set((nrf_nfct_selres_protocol_t) p_param->data.sel_res_protocol);
                break;
    
            case NRFX_NFCT_PARAM_ID_NFCID1:
            {
                nrf_nfct_sensres_nfcid1_size_t id_size_mask;
    
                id_size_mask = nrf_nfct_nfcid1_size_to_sensres_size(p_param->data.nfcid1.id_size);
                nrf_nfct_nfcid1_set(p_param->data.nfcid1.p_id, id_size_mask);
                break;
            }
    
            default:
                break;
        }
    
        return NRFX_SUCCESS;
    }
    
    nrfx_err_t nrfx_nfct_nfcid1_default_bytes_get(uint8_t * const p_nfcid1_buff,
                                                  uint32_t        nfcid1_buff_len)
    {
        if ((nfcid1_buff_len != NRFX_NFCT_NFCID1_SINGLE_SIZE) &&
            (nfcid1_buff_len != NRFX_NFCT_NFCID1_DOUBLE_SIZE) &&
            (nfcid1_buff_len != NRFX_NFCT_NFCID1_TRIPLE_SIZE))
        {
            return NRFX_ERROR_INVALID_LENGTH;
        }
    
        uint32_t nfc_tag_header0 = NRF_FICR->NFC.TAGHEADER0;
        uint32_t nfc_tag_header1 = NRF_FICR->NFC.TAGHEADER1;
        uint32_t nfc_tag_header2 = NRF_FICR->NFC.TAGHEADER2;
    
        p_nfcid1_buff[0] = (uint8_t) (nfc_tag_header0 >> 0);
        p_nfcid1_buff[1] = (uint8_t) (nfc_tag_header0 >> 8);
        p_nfcid1_buff[2] = (uint8_t) (nfc_tag_header0 >> 16);
        p_nfcid1_buff[3] = (uint8_t) (nfc_tag_header1 >> 0);
    
        if (nfcid1_buff_len != NRFX_NFCT_NFCID1_SINGLE_SIZE)
        {
            p_nfcid1_buff[4] = (uint8_t) (nfc_tag_header1 >> 8);
            p_nfcid1_buff[5] = (uint8_t) (nfc_tag_header1 >> 16);
            p_nfcid1_buff[6] = (uint8_t) (nfc_tag_header1 >> 24);
    
            if (nfcid1_buff_len == NRFX_NFCT_NFCID1_TRIPLE_SIZE)
            {
                p_nfcid1_buff[7] = (uint8_t) (nfc_tag_header2 >> 0);
                p_nfcid1_buff[8] = (uint8_t) (nfc_tag_header2 >> 8);
                p_nfcid1_buff[9] = (uint8_t) (nfc_tag_header2 >> 16);
            }
            /* Begin: Bugfix for FTPAN-181. */
            /* Workaround for wrong value in NFCID1. Value 0x88 cannot be used as byte 3 
               of a double-size NFCID1, according to the NFC Forum Digital Protocol specification. */
            else if (p_nfcid1_buff[3] == 0x88)
            {
                p_nfcid1_buff[3] |= 0x11;
            }
            /* End: Bugfix for FTPAN-181 */
        }
    
        return NRFX_SUCCESS;
    }
    
    void nrfx_nfct_autocolres_enable(void)
    {
    #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
        (*(uint32_t *)(0x4000559C)) &= (~(0x1UL));
    #else
        nrf_nfct_autocolres_enable();
    #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
    }
    
    void nrfx_nfct_autocolres_disable(void)
    {
    #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
        (*(uint32_t *)(0x4000559C)) |= (0x1UL);
    #else
        nrf_nfct_autocolres_disable();
    #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
    }
    
    void nrfx_nfct_irq_handler(void)
    {
        nrfx_nfct_field_state_t current_field = NRFX_NFC_FIELD_STATE_NONE;
    
        if (NRFX_NFCT_EVT_ACTIVE(FIELDDETECTED))
        {
            nrf_nfct_event_clear(NRF_NFCT_EVENT_FIELDDETECTED);
            current_field = NRFX_NFC_FIELD_STATE_ON;
    
            NRFX_LOG_DEBUG("Field detected");
        }
    
    #if !defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
        if (NRFX_NFCT_EVT_ACTIVE(FIELDLOST))
        {
            nrf_nfct_event_clear(NRF_NFCT_EVENT_FIELDLOST);
            current_field = (current_field == NRFX_NFC_FIELD_STATE_NONE) ? 
                            NRFX_NFC_FIELD_STATE_OFF : NRFX_NFC_FIELD_STATE_UNKNOWN;
    
            NRFX_LOG_DEBUG("Field lost");
        }
    #endif //!defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
    
        /* Perform actions if any FIELD event is active */
        if (current_field != NRFX_NFC_FIELD_STATE_NONE)
        {
            nrfx_nfct_field_event_handler(current_field);
        }
    
        if (NRFX_NFCT_EVT_ACTIVE(RXFRAMEEND))
        {
            nrf_nfct_event_clear(NRF_NFCT_EVENT_RXFRAMEEND);
    
            nrfx_nfct_evt_t nfct_evt =
            {
                .evt_id = NRFX_NFCT_EVT_RX_FRAMEEND
            };
    
            /* Take into account only the number of whole bytes. */
            nfct_evt.params.rx_frameend.rx_status         = 0;
            nfct_evt.params.rx_frameend.rx_data.p_data    = nrf_nfct_rxtx_buffer_get();
            nfct_evt.params.rx_frameend.rx_data.data_size = NRFX_NFCT_BITS_TO_BYTES(nrf_nfct_rx_bits_get(true));
    
            if (NRFX_NFCT_EVT_ACTIVE(RXERROR))
            {
                nfct_evt.params.rx_frameend.rx_status = 
                    (nrf_nfct_rx_frame_status_get() & NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
                nrf_nfct_event_clear(NRF_NFCT_EVENT_RXERROR);
    
                NRFX_LOG_DEBUG("Rx error (0x%x)", (unsigned int) nfct_evt.params.rx_frameend.rx_status);
    
                /* Clear rx frame status */
                nrf_nfct_rx_frame_status_clear(NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
            } else {
              NRFX_LOG_INFO("Rx fend");
              NRFX_LOG_HEXDUMP_INFO(nfct_evt.params.rx_frameend.rx_data.p_data, nfct_evt.params.rx_frameend.rx_data.data_size);
            }
            
            NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
    
            /* Clear TXFRAMESTART EVENT so it can be checked in hal_nfc_send */
            nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMESTART);
    
            NRFX_LOG_DEBUG("Rx fend");
        }
    
        if (NRFX_NFCT_EVT_ACTIVE(TXFRAMEEND))
        {
            nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMEEND);
    
            nrfx_nfct_evt_t nfct_evt =
            {
                .evt_id = NRFX_NFCT_EVT_TX_FRAMEEND
            };
    
            /* Disable TX END event to ignore frame transmission other than READ response */
            nrf_nfct_int_disable(NRFX_NFCT_TX_INT_MASK);
    
            NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
    
            NRFX_LOG_DEBUG("Tx fend");
        }
    
        if (NRFX_NFCT_EVT_ACTIVE(SELECTED))
        {
            nrf_nfct_event_clear(NRF_NFCT_EVENT_SELECTED);
            /* Clear also RX END and RXERROR events because SW does not take care of 
               commands that were received before selecting the tag. */
            nrf_nfct_event_clear(NRF_NFCT_EVENT_RXFRAMEEND);
            nrf_nfct_event_clear(NRF_NFCT_EVENT_RXERROR);
            nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMESTART);
            nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMEEND);
    
            /* Begin: Bugfix for FTPAN-218 */
            nrfx_nfct_frame_delay_max_set(false);
            /* End: Bugfix for FTPAN-218 */
    
            /* At this point any previous error status can be ignored. */
            nrf_nfct_rx_frame_status_clear(NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
            nrf_nfct_error_status_clear(NRFX_NFCT_ERROR_STATUS_ALL_MASK);
    
            nrfx_nfct_evt_t nfct_evt =
            {
                .evt_id = NRFX_NFCT_EVT_SELECTED
            };
            NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
    
            NRFX_LOG_DEBUG("Selected");
        }
    
        if (NRFX_NFCT_EVT_ACTIVE(ERROR))
        {
            uint32_t err_status = nrf_nfct_error_status_get();
            nrf_nfct_event_clear(NRF_NFCT_EVENT_ERROR);
    
            nrfx_nfct_evt_t nfct_evt =
            {
                .evt_id = NRFX_NFCT_EVT_ERROR
            };
    
            /* Clear FRAMEDELAYTIMEOUT error (expected HW behaviour) when SLP_REQ command was received. */
            if (err_status & NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK)
            {
                nrf_nfct_error_status_clear(NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK);
    
                nfct_evt.params.error.reason = NRFX_NFCT_ERROR_FRAMEDELAYTIMEOUT;
                NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
            }
    
            /* Report any other error. */
            err_status &= ~NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK;
            if (err_status)
            {
                NRFX_LOG_DEBUG("Error (0x%x)", (unsigned int) err_status);
            }
    
            /* Clear error status. */
            nrf_nfct_error_status_clear(NRFX_NFCT_ERROR_STATUS_ALL_MASK);
        }
    
        if (NRFX_NFCT_EVT_ACTIVE(TXFRAMESTART))
        {
            nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMESTART);
    
            if (m_nfct_cb.config.cb != NULL)
            {
                nrfx_nfct_evt_t nfct_evt;
    
                nfct_evt.evt_id                                 = NRFX_NFCT_EVT_TX_FRAMESTART;
                nfct_evt.params.tx_framestart.tx_data.p_data    = nrf_nfct_rxtx_buffer_get();
                nfct_evt.params.tx_framestart.tx_data.data_size = NRFX_NFCT_BITS_TO_BYTES(nrf_nfct_tx_bits_get());
    
                m_nfct_cb.config.cb(&nfct_evt);
            }
        }
    }
    
    #endif // NRFX_CHECK(NRFX_NFCT_ENABLED)
    

  • Hi Michal,

    do you have further answers to my case? How can we proceed?

Related