1 /**************************************************************************/
3 @file pn532_drvr_uart.c
5 /**************************************************************************/
9 #include "pn532_drvr.h"
13 #include "core/systick/systick.h"
14 #include "core/gpio/gpio.h"
15 #include "core/uart/uart.h"
17 /**************************************************************************/
19 @brief Initialises UART and configures the PN532
21 /**************************************************************************/
22 void pn532HWInit(void)
24 PN532_DEBUG("Initialising UART (%d)%s", PN532_UART_BAUDRATE
, CFG_PRINTF_NEWLINE
);
25 uartInit(PN532_UART_BAUDRATE
);
27 // Set reset pin as output and reset device
28 gpioSetDir(PN532_RSTPD_PORT
, PN532_RSTPD_PIN
, gpioDirection_Output
);
29 PN532_DEBUG("Resetting the PN532...\r\n");
30 gpioSetValue(PN532_RSTPD_PORT
, PN532_RSTPD_PIN
, 0);
32 gpioSetValue(PN532_RSTPD_PORT
, PN532_RSTPD_PIN
, 1);
34 // Wait for the PN532 to finish booting
38 /**************************************************************************/
40 @brief Builds a standard PN532 frame using the supplied data
42 @param pbtFrame Pointer to the field that will hold the frame data
43 @param pszFrame Pointer to the field that will hold the frame length
44 @param pbtData Pointer to the data to insert in a frame
45 @param swData Length of the data to insert in bytes
47 @note Possible error messages are:
49 - PN532_ERROR_EXTENDEDFRAME
51 /**************************************************************************/
52 pn532_error_t
pn532BuildFrame(byte_t
* pbtFrame
, size_t * pszFrame
, const byte_t
* pbtData
, const size_t szData
)
54 if (szData
> PN532_NORMAL_FRAME__DATA_MAX_LEN
)
56 // Extended frames currently unsupported
57 return PN532_ERROR_EXTENDEDFRAME
;
60 // LEN - Packet length = data length (len) + checksum (1) + end of stream marker (1)
61 pbtFrame
[3] = szData
+ 1;
62 // LCS - Packet length checksum
63 pbtFrame
[4] = 256 - (szData
+ 1);
66 // DATA - Copy the PN53X command into the packet buffer
67 memcpy (pbtFrame
+ 6, pbtData
, szData
);
69 // DCS - Calculate data payload checksum
70 byte_t btDCS
= (256 - 0xD4);
72 for (szPos
= 0; szPos
< szData
; szPos
++)
74 btDCS
-= pbtData
[szPos
];
76 pbtFrame
[6 + szData
] = btDCS
;
78 // 0x00 - End of stream marker
79 pbtFrame
[szData
+ 7] = 0x00;
81 (*pszFrame
) = szData
+ PN532_NORMAL_FRAME__OVERHEAD
;
83 return PN532_ERROR_NONE
;
86 /**************************************************************************/
88 @brief Sends the specified command to the PN532, automatically
89 creating an appropriate frame for it
91 @param pdbData Pointer to the byte data to send
92 @param szData Length in bytes of the data to send
94 @note Possible error messages are:
98 - PN532_ERROR_INVALIDACK
100 /**************************************************************************/
101 pn532_error_t
pn532SendCommand(const byte_t
* pbtData
, const size_t szData
)
103 pn532_pcb_t
*pn532
= pn532GetPCB();
105 // Check if we're busy
106 if (pn532
->state
== PN532_STATE_BUSY
)
108 return PN532_ERROR_BUSY
;
111 // Flag the stack as busy
112 pn532
->state
= PN532_STATE_BUSY
;
114 // Every packet must start with "00 00 ff"
115 byte_t abtFrame
[PN532_BUFFER_LEN
] = { 0x00, 0x00, 0xff };
119 pn532BuildFrame (abtFrame
, &szFrame
, pbtData
, szData
);
121 // Keep track of the last command that was sent
122 pn532
->lastCommand
= pbtData
[0];
124 // Output the frame data for debugging if requested
125 PN532_DEBUG("Sending (%02d): ", szFrame
);
126 pn532PrintHex(abtFrame
, szFrame
);
128 // Send data to the PN532
129 uartSend (abtFrame
, szFrame
);
133 uart_pcb_t
*uart
= uartGetPCB();
134 systickDelay(10); // FIXME: How long should we wait for ACK?
135 if (uart
->rxfifo
.len
< 6)
137 // Unable to read ACK
138 PN532_DEBUG ("Unable to read ACK%s", CFG_PRINTF_NEWLINE
);
139 pn532
->state
= PN532_STATE_READY
;
140 return PN532_ERROR_NOACK
;
143 // Read ACK ... this will also remove it from the buffer
144 const byte_t abtAck
[6] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
145 abtRxBuf
[0] = uartRxBufferRead();
146 abtRxBuf
[1] = uartRxBufferRead();
147 abtRxBuf
[2] = uartRxBufferRead();
148 abtRxBuf
[3] = uartRxBufferRead();
149 abtRxBuf
[4] = uartRxBufferRead();
150 abtRxBuf
[5] = uartRxBufferRead();
152 // Make sure the received ACK matches the prototype
153 if (0 != (memcmp (abtRxBuf
, abtAck
, 6)))
155 PN532_DEBUG ("Invalid ACK: ");
156 pn532PrintHex(abtRxBuf
, 6);
157 PN532_DEBUG("%s", CFG_PRINTF_NEWLINE
);
158 pn532
->state
= PN532_STATE_READY
;
159 return PN532_ERROR_INVALIDACK
;
162 pn532
->state
= PN532_STATE_READY
;
163 return PN532_ERROR_NONE
;
166 /**************************************************************************/
168 @brief Reads a response from the PN532
170 @note Possible error message are:
173 - PN532_ERROR_RESPONSEBUFFEREMPTY
174 - PN532_ERROR_PREAMBLEMISMATCH
175 - PN532_ERROR_APPLEVELERROR
176 - PN532_ERROR_EXTENDEDFRAME
177 - PN532_ERROR_LENCHECKSUMMISMATCH
179 /**************************************************************************/
180 pn532_error_t
pn532ReadResponse(byte_t
* pbtResponse
, size_t * pszRxLen
)
182 pn532_pcb_t
*pn532
= pn532GetPCB();
184 // Check if we're busy
185 if (pn532
->state
== PN532_STATE_BUSY
)
187 return PN532_ERROR_BUSY
;
190 // Flag the stack as busy
191 pn532
->state
= PN532_STATE_BUSY
;
193 // Reset the app error flag
194 pn532
->appError
= PN532_APPERROR_NONE
;
196 // Read response from uart
197 if (!uartRxBufferReadArray(pbtResponse
, pszRxLen
))
199 pn532
->state
= PN532_STATE_READY
;
200 return PN532_ERROR_RESPONSEBUFFEREMPTY
;
203 // Display the raw response data for debugging if requested
204 PN532_DEBUG("Received (%02d): ", *pszRxLen
);
205 pn532PrintHex(pbtResponse
, *pszRxLen
);
208 const byte_t pn53x_preamble
[3] = { 0x00, 0x00, 0xff };
209 if (0 != (memcmp (pbtResponse
, pn53x_preamble
, 3)))
211 PN532_DEBUG("Frame preamble + start code mismatch%s", CFG_PRINTF_NEWLINE
);
212 pn532
->state
= PN532_STATE_READY
;
213 return PN532_ERROR_PREAMBLEMISMATCH
;
216 // Check the frame type
217 if ((0x01 == pbtResponse
[3]) && (0xff == pbtResponse
[4]))
220 PN532_DEBUG("Application level error (%02d)%s", pbtResponse
[5], CFG_PRINTF_NEWLINE
);
221 // Set application error message ID
222 pn532
->appError
= pbtResponse
[5];
223 pn532
->state
= PN532_STATE_READY
;
224 return PN532_ERROR_APPLEVELERROR
;
226 else if ((0xff == pbtResponse
[3]) && (0xff == pbtResponse
[4]))
229 PN532_DEBUG("Extended frames currently unsupported%s", CFG_PRINTF_NEWLINE
);
230 pn532
->state
= PN532_STATE_READY
;
231 return PN532_ERROR_EXTENDEDFRAME
;
236 if (256 != (pbtResponse
[3] + pbtResponse
[4]))
239 PN532_DEBUG("Length checksum mismatch%s", CFG_PRINTF_NEWLINE
);
240 pn532
->state
= PN532_STATE_READY
;
241 return PN532_ERROR_LENCHECKSUMMISMATCH
;
243 // size_t szPayloadLen = abtRx[3] - 2;
246 pn532
->state
= PN532_STATE_READY
;
247 return PN532_ERROR_NONE
;
250 /**************************************************************************/
252 @brief Sends the wakeup sequence to the PN532.
254 /**************************************************************************/
255 pn532_error_t
pn532Wakeup(void)
258 byte_t abtWakeUp
[] = { 0x55,0x55,0x00,0x00,0x00,0x00,0x00,0xff,0x03,0xfd,0xd4,0x14,0x01,0x17,0x00,0x00,0xff,0x03,0xfd,0xd4,0x14,0x01,0x17,0x00 };
260 pn532_pcb_t
*pn532
= pn532GetPCB();
262 PN532_DEBUG("Sending Wakeup Sequence%s", CFG_PRINTF_NEWLINE
);
263 uartSend(abtWakeUp
,sizeof(abtWakeUp
));
267 pn532ReadResponse(response
, &szLen
);
269 // Todo: Check for error ... currently throws a checksum error
270 // that isn't really an error
272 pn532
->state
= PN532_STATE_READY
;
273 return PN532_ERROR_NONE
;
276 #endif // #ifdef PN532_UART