Spieler splodiert.
[hackover2013-badge-firmware.git] / drivers / rf / pn532 / pn532_bus_uart.c
1 /**************************************************************************/
2 /*!
3 @file pn532_bus_uart.c
4 */
5 /**************************************************************************/
6 #include <string.h>
7
8 #include "pn532.h"
9 #include "pn532_bus.h"
10
11 #ifdef PN532_BUS_UART
12
13 #include "core/systick/systick.h"
14 #include "core/gpio/gpio.h"
15 #include "core/uart/uart.h"
16
17 /**************************************************************************/
18 /*!
19 @brief Builds a standard PN532 frame using the supplied data
20
21 @param pbtFrame Pointer to the field that will hold the frame data
22 @param pszFrame Pointer to the field that will hold the frame length
23 @param pbtData Pointer to the data to insert in a frame
24 @param swData Length of the data to insert in bytes
25
26 @note Possible error messages are:
27
28 - PN532_ERROR_EXTENDEDFRAME
29 */
30 /**************************************************************************/
31 pn532_error_t pn532_bus_BuildFrame(byte_t * pbtFrame, size_t * pszFrame, const byte_t * pbtData, const size_t szData)
32 {
33 if (szData > PN532_NORMAL_FRAME__DATA_MAX_LEN)
34 {
35 // Extended frames currently unsupported
36 return PN532_ERROR_EXTENDEDFRAME;
37 }
38
39 // LEN - Packet length = data length (len) + checksum (1) + end of stream marker (1)
40 pbtFrame[3] = szData + 1;
41 // LCS - Packet length checksum
42 pbtFrame[4] = 256 - (szData + 1);
43 // TFI
44 pbtFrame[5] = 0xD4;
45 // DATA - Copy the PN53X command into the packet buffer
46 memcpy (pbtFrame + 6, pbtData, szData);
47
48 // DCS - Calculate data payload checksum
49 byte_t btDCS = (256 - 0xD4);
50 size_t szPos;
51 for (szPos = 0; szPos < szData; szPos++)
52 {
53 btDCS -= pbtData[szPos];
54 }
55 pbtFrame[6 + szData] = btDCS;
56
57 // 0x00 - End of stream marker
58 pbtFrame[szData + 7] = 0x00;
59
60 (*pszFrame) = szData + PN532_NORMAL_FRAME__OVERHEAD;
61
62 return PN532_ERROR_NONE;
63 }
64
65 /**************************************************************************/
66 /*!
67 @brief Initialises UART and configures the PN532
68 */
69 /**************************************************************************/
70 void pn532_bus_HWInit(void)
71 {
72 #ifdef PN532_DEBUGMODE
73 PN532_DEBUG("Initialising UART (%d)%s", PN532_UART_BAUDRATE, CFG_PRINTF_NEWLINE);
74 #endif
75 uartInit(PN532_UART_BAUDRATE);
76
77 // Set reset pin as output and reset device
78 gpioSetDir(PN532_RSTPD_PORT, PN532_RSTPD_PIN, gpioDirection_Output);
79 #ifdef PN532_DEBUGMODE
80 PN532_DEBUG("Resetting the PN532...\r\n");
81 #endif
82 gpioSetValue(PN532_RSTPD_PORT, PN532_RSTPD_PIN, 0);
83 systickDelay(400);
84 gpioSetValue(PN532_RSTPD_PORT, PN532_RSTPD_PIN, 1);
85
86 // Wait for the PN532 to finish booting
87 systickDelay(100);
88 }
89
90 /**************************************************************************/
91 /*!
92 @brief Sends the specified command to the PN532, automatically
93 creating an appropriate frame for it
94
95 @param pdbData Pointer to the byte data to send
96 @param szData Length in bytes of the data to send
97
98 @note Possible error messages are:
99
100 - PN532_ERROR_BUSY
101 - PN532_ERROR_NOACK
102 - PN532_ERROR_INVALIDACK
103 */
104 /**************************************************************************/
105 pn532_error_t pn532_bus_SendCommand(const byte_t * pbtData, const size_t szData)
106 {
107 pn532_pcb_t *pn532 = pn532GetPCB();
108
109 // Check if we're busy
110 if (pn532->state == PN532_STATE_BUSY)
111 {
112 return PN532_ERROR_BUSY;
113 }
114
115 // Flag the stack as busy
116 pn532->state = PN532_STATE_BUSY;
117
118 // Every packet must start with "00 00 ff"
119 byte_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff };
120 size_t szFrame = 0;
121
122 // Build the frame
123 pn532_bus_BuildFrame (abtFrame, &szFrame, pbtData, szData);
124
125 // Keep track of the last command that was sent
126 pn532->lastCommand = pbtData[0];
127
128 // Output the frame data for debugging if requested
129 #ifdef PN532_DEBUGMODE
130 PN532_DEBUG("Sending (%02d): ", szFrame);
131 pn532PrintHex(abtFrame, szFrame);
132 #endif
133
134 // Send data to the PN532
135 uartSend (abtFrame, szFrame);
136
137 // Wait for ACK
138 byte_t abtRxBuf[6];
139 uart_pcb_t *uart = uartGetPCB();
140 systickDelay(10); // FIXME: How long should we wait for ACK?
141 if (uart->rxfifo.len < 6)
142 {
143 // Unable to read ACK
144 #ifdef PN532_DEBUGMODE
145 PN532_DEBUG ("Unable to read ACK%s", CFG_PRINTF_NEWLINE);
146 #endif
147 pn532->state = PN532_STATE_READY;
148 return PN532_ERROR_NOACK;
149 }
150
151 // Read ACK ... this will also remove it from the buffer
152 const byte_t abtAck[6] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
153 abtRxBuf[0] = uartRxBufferRead();
154 abtRxBuf[1] = uartRxBufferRead();
155 abtRxBuf[2] = uartRxBufferRead();
156 abtRxBuf[3] = uartRxBufferRead();
157 abtRxBuf[4] = uartRxBufferRead();
158 abtRxBuf[5] = uartRxBufferRead();
159
160 // Make sure the received ACK matches the prototype
161 if (0 != (memcmp (abtRxBuf, abtAck, 6)))
162 {
163 #ifdef PN532_DEBUGMODE
164 PN532_DEBUG ("Invalid ACK: ");
165 pn532PrintHex(abtRxBuf, 6);
166 PN532_DEBUG("%s", CFG_PRINTF_NEWLINE);
167 #endif
168 pn532->state = PN532_STATE_READY;
169 return PN532_ERROR_INVALIDACK;
170 }
171
172 pn532->state = PN532_STATE_READY;
173 return PN532_ERROR_NONE;
174 }
175
176 /**************************************************************************/
177 /*!
178 @brief Reads a response from the PN532
179
180 @note Possible error message are:
181
182 - PN532_ERROR_BUSY
183 - PN532_ERROR_RESPONSEBUFFEREMPTY
184 - PN532_ERROR_PREAMBLEMISMATCH
185 - PN532_ERROR_APPLEVELERROR
186 - PN532_ERROR_EXTENDEDFRAME
187 - PN532_ERROR_LENCHECKSUMMISMATCH
188 */
189 /**************************************************************************/
190 pn532_error_t pn532_bus_ReadResponse(byte_t * pbtResponse, size_t * pszRxLen)
191 {
192 pn532_pcb_t *pn532 = pn532GetPCB();
193
194 // Check if we're busy
195 if (pn532->state == PN532_STATE_BUSY)
196 {
197 return PN532_ERROR_BUSY;
198 }
199
200 // Flag the stack as busy
201 pn532->state = PN532_STATE_BUSY;
202
203 // Reset the app error flag
204 pn532->appError = PN532_APPERROR_NONE;
205
206 // Read response from uart
207 if (!uartRxBufferReadArray(pbtResponse, pszRxLen))
208 {
209 pn532->state = PN532_STATE_READY;
210 return PN532_ERROR_RESPONSEBUFFEREMPTY;
211 }
212
213 // Display the raw response data for debugging if requested
214 #ifdef PN532_DEBUGMODE
215 PN532_DEBUG("Received (%02d): ", *pszRxLen);
216 pn532PrintHex(pbtResponse, *pszRxLen);
217 #endif
218
219 // Check preamble
220 const byte_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
221 if (0 != (memcmp (pbtResponse, pn53x_preamble, 3)))
222 {
223 #ifdef PN532_DEBUGMODE
224 PN532_DEBUG("Frame preamble + start code mismatch%s", CFG_PRINTF_NEWLINE);
225 #endif
226 pn532->state = PN532_STATE_READY;
227 return PN532_ERROR_PREAMBLEMISMATCH;
228 }
229
230 // Check the frame type
231 if ((0x01 == pbtResponse[3]) && (0xff == pbtResponse[4]))
232 {
233 // Error frame
234 #ifdef PN532_DEBUGMODE
235 PN532_DEBUG("Application level error (0x%02x)%s", pbtResponse[5], CFG_PRINTF_NEWLINE);
236 #endif
237 // Set application error message ID
238 pn532->appError = pbtResponse[5];
239 pn532->state = PN532_STATE_READY;
240 return PN532_ERROR_APPLEVELERROR;
241 }
242 else if ((0xff == pbtResponse[3]) && (0xff == pbtResponse[4]))
243 {
244 // Extended frame
245 #ifdef PN532_DEBUGMODE
246 PN532_DEBUG("Extended frames currently unsupported%s", CFG_PRINTF_NEWLINE);
247 #endif
248 pn532->state = PN532_STATE_READY;
249 return PN532_ERROR_EXTENDEDFRAME;
250 }
251 else
252 {
253 // Normal frame
254 if (256 != (pbtResponse[3] + pbtResponse[4]))
255 {
256 // TODO: Retry
257 #ifdef PN532_DEBUGMODE
258 PN532_DEBUG("Length checksum mismatch%s", CFG_PRINTF_NEWLINE);
259 #endif
260 pn532->state = PN532_STATE_READY;
261 return PN532_ERROR_LENCHECKSUMMISMATCH;
262 }
263 // size_t szPayloadLen = abtRx[3] - 2;
264 }
265
266 pn532->state = PN532_STATE_READY;
267 return PN532_ERROR_NONE;
268 }
269
270 /**************************************************************************/
271 /*!
272 @brief Sends the wakeup sequence to the PN532.
273 */
274 /**************************************************************************/
275 pn532_error_t pn532_bus_Wakeup(void)
276 {
277 size_t szLen;
278 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 };
279
280 pn532_pcb_t *pn532 = pn532GetPCB();
281
282 #ifdef PN532_DEBUGMODE
283 PN532_DEBUG("Sending Wakeup Sequence%s", CFG_PRINTF_NEWLINE);
284 #endif
285 uartSend(abtWakeUp,sizeof(abtWakeUp));
286 systickDelay(100);
287
288 byte_t response[32];
289 pn532_bus_ReadResponse(response, &szLen);
290
291 // Todo: Check for error ... currently throws a checksum error
292 // that isn't really an error
293
294 pn532->state = PN532_STATE_READY;
295 return PN532_ERROR_NONE;
296 }
297
298 #endif // #ifdef PN532_BUS_UART
This page took 0.062076 seconds and 5 git commands to generate.