Added I2C
[hackover2013-badge-firmware.git] / drivers / sensors / pn532 / pn532_bus_i2c.c
1 /**************************************************************************/
2 /*!
3 @file pn532_bus_i2c.c
4 @author Kevin Townsend
5 @copyright Kevin Townsend 2012
6 */
7 /**************************************************************************/
8 #include <string.h>
9
10 #include "pn532.h"
11 #include "pn532_bus.h"
12
13 #ifdef PN532_BUS_I2C
14
15 #include "core/systick/systick.h"
16 #include "core/gpio/gpio.h"
17 #include "core/i2c/i2c.h"
18
19 extern volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
20 extern volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
21 extern volatile uint32_t I2CReadLength, I2CWriteLength;
22
23 /**************************************************************************/
24 /*!
25 @brief Writes an 8 bit value over I2C
26
27 @note Possible error messages are:
28
29 - PN532_ERROR_I2C_NACK
30 */
31 /**************************************************************************/
32 pn532_error_t pn532_bus_i2c_WriteData (const byte_t * pbtData, const size_t szData)
33 {
34 uint32_t i2cState;
35
36 // Clear write buffers
37 uint32_t i;
38 for ( i = 0; i < I2C_BUFSIZE; i++ )
39 {
40 I2CMasterBuffer[i] = 0x00;
41 }
42
43 // Send the specified bytes
44 I2CWriteLength = szData+1;
45 I2CReadLength = 0;
46 I2CMasterBuffer[0] = PN532_I2C_ADDRESS; // I2C device address
47 for ( i = 0; i < szData; i++ )
48 {
49 I2CMasterBuffer[i+1] = pbtData[i];
50 }
51 i2cState = i2cEngine();
52
53 // Check if we got an ACK
54 if ((i2cState == I2CSTATE_NACK) || (i2cState == I2CSTATE_SLA_NACK))
55 {
56 // I2C slave didn't acknowledge the master transfer
57 // The PN532 probably isn't connected properly or the
58 // bus select pins are in the wrong state
59 return PN532_ERROR_I2C_NACK;
60 }
61
62 return PN532_ERROR_NONE;
63 }
64
65 /**************************************************************************/
66 /*!
67 @brief Checks the 'IRQ' pin to know if the PN532 is ready to send
68 a response or not
69
70 @note The IRQ bit may stay high intentionally, and this isn't
71 always an error condition. When PN532_COMMAND_INLISTPASSIVETARGET
72 is sent, for example, the PN532 will wait until a card
73 enters the magnetic field, and IRQ will remain high since
74 there is no response ready yet. The IRQ pin will go low
75 as soon as a card enters the magentic field and the data
76 has been retrieved from it.
77
78 @returns 1 if a response is ready, 0 if the PN532 is still busy or a
79 timeout occurred
80 */
81 /**************************************************************************/
82 uint8_t pn532_bus_i2c_WaitForReady(void)
83 {
84 uint8_t busy = 1;
85 // uint8_t busyTimeout = 0;
86
87 while (busy)
88 {
89 // For now, we wait forever until a command is ready
90 // ToDo: Add user-specified timeout
91 busy = gpioGetValue(PN532_I2C_IRQPORT, PN532_I2C_IRQPIN);
92 systickDelay(1);
93 // busyTimeout++;
94 // if (busyTimeout == PN532_I2C_READYTIMEOUT)
95 // {
96 // return false;
97 // }
98 }
99
100 return true;
101 }
102
103 /**************************************************************************/
104 /*!
105 @brief Builds a standard PN532 frame using the supplied data
106
107 @param pbtFrame Pointer to the field that will hold the frame data
108 @param pszFrame Pointer to the field that will hold the frame length
109 @param pbtData Pointer to the data to insert in a frame
110 @param swData Length of the data to insert in bytes
111
112 @note Possible error messages are:
113
114 - PN532_ERROR_EXTENDEDFRAME
115 */
116 /**************************************************************************/
117 pn532_error_t pn532_bus_BuildFrame(byte_t * pbtFrame, size_t * pszFrame, const byte_t * pbtData, const size_t szData)
118 {
119 if (szData > PN532_NORMAL_FRAME__DATA_MAX_LEN)
120 {
121 // Extended frames currently unsupported
122 return PN532_ERROR_EXTENDEDFRAME;
123 }
124
125 // LEN - Packet length = data length (len) + checksum (1) + end of stream marker (1)
126 pbtFrame[3] = szData + 1;
127 // LCS - Packet length checksum
128 pbtFrame[4] = 256 - (szData + 1);
129 // TFI
130 pbtFrame[5] = 0xD4;
131 // DATA - Copy the PN53X command into the packet buffer
132 memcpy (pbtFrame + 6, pbtData, szData);
133
134 // DCS - Calculate data payload checksum
135 byte_t btDCS = (256 - 0xD4);
136 size_t szPos;
137 for (szPos = 0; szPos < szData; szPos++)
138 {
139 btDCS -= pbtData[szPos];
140 }
141 pbtFrame[6 + szData] = btDCS;
142
143 // 0x00 - End of stream marker
144 pbtFrame[szData + 7] = 0x00;
145
146 (*pszFrame) = szData + PN532_NORMAL_FRAME__OVERHEAD;
147
148 return PN532_ERROR_NONE;
149 }
150
151 /**************************************************************************/
152 /*!
153 @brief Initialises I2C and configures the PN532 HW
154 */
155 /**************************************************************************/
156 void pn532_bus_HWInit(void)
157 {
158 #ifdef PN532_DEBUGMODE
159 PN532_DEBUG("Initialising I2C %s", CFG_PRINTF_NEWLINE);
160 #endif
161 i2cInit(I2CMASTER);
162
163 // Set IRQ pin to input
164 gpioSetDir(PN532_I2C_IRQPORT, PN532_I2C_IRQPIN, gpioDirection_Input);
165
166 // Set reset pin as output and reset device
167 gpioSetDir(PN532_RSTPD_PORT, PN532_RSTPD_PIN, gpioDirection_Output);
168 #ifdef PN532_DEBUGMODE
169 PN532_DEBUG("Resetting the PN532...\r\n");
170 #endif
171 gpioSetValue(PN532_RSTPD_PORT, PN532_RSTPD_PIN, 0);
172 systickDelay(400);
173 gpioSetValue(PN532_RSTPD_PORT, PN532_RSTPD_PIN, 1);
174
175 // Wait for the PN532 to finish booting
176 systickDelay(100);
177 }
178
179 /**************************************************************************/
180 /*!
181 @brief Sends the specified command to the PN532, automatically
182 creating an appropriate frame for it
183
184 @param pdbData Pointer to the byte data to send
185 @param szData Length in bytes of the data to send
186
187 @note Possible error messages are:
188
189 - PN532_ERROR_EXTENDEDFRAME // Extended frames not supported
190 - PN532_ERROR_BUSY // Already busy with a command
191 - PN532_ERROR_I2C_NACK // No ACK on I2C
192 - PN532_ERROR_READYSTATUSTIMEOUT // Timeout waiting for ready bit
193 - PN532_ERROR_INVALIDACK // No ACK frame received
194 */
195 /**************************************************************************/
196 pn532_error_t pn532_bus_SendCommand(const byte_t * pbtData, const size_t szData)
197 {
198 pn532_error_t error = PN532_ERROR_NONE;
199 pn532_pcb_t *pn532 = pn532GetPCB();
200 uint32_t ready_timeout = 0;
201
202 // Check if we're busy
203 if (pn532->state == PN532_STATE_BUSY)
204 {
205 return PN532_ERROR_BUSY;
206 }
207
208 // Flag the stack as busy
209 pn532->state = PN532_STATE_BUSY;
210
211 // --------------------------------------------------------------------
212 // Send the command frame
213 // --------------------------------------------------------------------
214 byte_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff };
215 size_t szFrame = 0;
216
217 // Build the frame
218 pn532_bus_BuildFrame (abtFrame, &szFrame, pbtData, szData);
219
220 // Keep track of the last command that was sent
221 pn532->lastCommand = pbtData[0];
222
223 // Output the frame data for debugging if requested
224 #ifdef PN532_DEBUGMODE
225 PN532_DEBUG("Sending (%02d): ", szFrame);
226 pn532PrintHex(abtFrame, szFrame);
227 #endif
228
229 // Send data to the PN532
230 error = pn532_bus_i2c_WriteData(abtFrame, szFrame);
231
232 if (error == PN532_ERROR_I2C_NACK)
233 {
234 // Most likely error is PN532_ERROR_I2C_NACK
235 // meaning no I2C ACK received from the PN532
236 #ifdef PN532_DEBUGMODE
237 PN532_DEBUG ("No ACK received on I2C bus%s", CFG_PRINTF_NEWLINE);
238 #endif
239 pn532->state = PN532_STATE_READY;
240 return error;
241 }
242
243 // --------------------------------------------------------------------
244 // Wait for the IRQ/Ready flag
245 // --------------------------------------------------------------------
246 if (!(pn532_bus_i2c_WaitForReady()))
247 {
248 pn532->state = PN532_STATE_READY;
249 #ifdef PN532_DEBUGMODE
250 PN532_DEBUG ("Timed out waiting for IRQ/Ready%s", CFG_PRINTF_NEWLINE);
251 #endif
252 return PN532_ERROR_READYSTATUSTIMEOUT;
253 }
254
255 // --------------------------------------------------------------------
256 // Read the ACK frame
257 // --------------------------------------------------------------------
258 uint32_t i;
259 // Clear buffer
260 for ( i = 0; i < I2C_BUFSIZE; i++ )
261 {
262 I2CMasterBuffer[i] = 0x00;
263 }
264 I2CWriteLength = 0;
265 I2CReadLength = 7; // ACK + Ready bit = 7
266 I2CMasterBuffer[0] = PN532_I2C_ADDRESS | PN532_I2C_READBIT;
267 i2cEngine();
268
269 // Make sure the received ACK matches the prototype
270 const byte_t abtAck[6] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
271 byte_t abtRxBuf[6];
272 memcpy(abtRxBuf, I2CSlaveBuffer+1, 6);
273 if (0 != (memcmp (abtRxBuf, abtAck, 6)))
274 {
275 #ifdef PN532_DEBUGMODE
276 PN532_DEBUG ("Invalid ACK: ");
277 pn532PrintHex(abtRxBuf, 6);
278 PN532_DEBUG("%s", CFG_PRINTF_NEWLINE);
279 #endif
280 pn532->state = PN532_STATE_READY;
281 return PN532_ERROR_INVALIDACK;
282 }
283
284 // --------------------------------------------------------------------
285 // Wait for the post-ACK IRQ/Ready flag
286 // --------------------------------------------------------------------
287 if (!(pn532_bus_i2c_WaitForReady()))
288 {
289 pn532->state = PN532_STATE_READY;
290 #ifdef PN532_DEBUGMODE
291 PN532_DEBUG ("Timed out waiting for IRQ/Ready%s", CFG_PRINTF_NEWLINE);
292 #endif
293 return PN532_ERROR_READYSTATUSTIMEOUT;
294 }
295
296 pn532->state = PN532_STATE_READY;
297 return PN532_ERROR_NONE;
298 }
299
300 /**************************************************************************/
301 /*!
302 @brief Reads a response from the PN532
303
304 @note Possible error message are:
305
306 - PN532_ERROR_BUSY
307 - PN532_ERROR_RESPONSEBUFFEREMPTY
308 - PN532_ERROR_PREAMBLEMISMATCH
309 - PN532_ERROR_APPLEVELERROR
310 - PN532_ERROR_EXTENDEDFRAME
311 - PN532_ERROR_LENCHECKSUMMISMATCH
312 */
313 /**************************************************************************/
314 pn532_error_t pn532_bus_ReadResponse(byte_t * pbtResponse, size_t * pszRxLen)
315 {
316 pn532_pcb_t *pn532 = pn532GetPCB();
317
318 // Check if we're busy
319 if (pn532->state == PN532_STATE_BUSY)
320 {
321 return PN532_ERROR_BUSY;
322 }
323
324 // Flag the stack as busy
325 pn532->state = PN532_STATE_BUSY;
326
327 // Reset the app error flag
328 pn532->appError = PN532_APPERROR_NONE;
329
330 uint32_t i;
331 for ( i = 0; i < I2C_BUFSIZE; i++ )
332 {
333 I2CMasterBuffer[i] = 0x00;
334 }
335 I2CWriteLength = 0;
336 I2CReadLength = I2C_BUFSIZE;
337 I2CMasterBuffer[0] = PN532_I2C_ADDRESS | PN532_I2C_READBIT;
338 i2cEngine();
339
340 // Display the raw response data for debugging if requested
341 #ifdef PN532_DEBUGMODE
342 PN532_DEBUG("Received (%02d): ", I2C_BUFSIZE-1);
343 pn532PrintHex(pbtResponse, I2C_BUFSIZE-1);
344 #endif
345
346 // Use the full I2C buffer size for now (until we're sure we have a good frame)
347 *pszRxLen = I2C_BUFSIZE - 1;
348
349 // Fill the response buffer from I2C (skipping the leading 'ready' bit when using I2C)
350 memcpy(pbtResponse, I2CSlaveBuffer+1, I2C_BUFSIZE-1);
351
352 // Check the frame type
353 if ((0x01 == pbtResponse[3]) && (0xff == pbtResponse[4]))
354 {
355 // Error frame
356 #ifdef PN532_DEBUGMODE
357 PN532_DEBUG("Application level error (0x%02x)%s", pbtResponse[5], CFG_PRINTF_NEWLINE);
358 #endif
359 // Set application error message ID
360 pn532->appError = pbtResponse[5];
361 pn532->state = PN532_STATE_READY;
362 return PN532_ERROR_APPLEVELERROR;
363 }
364 else if ((0xff == pbtResponse[3]) && (0xff == pbtResponse[4]))
365 {
366 // Extended frame
367 #ifdef PN532_DEBUGMODE
368 PN532_DEBUG("Extended frames currently unsupported%s", CFG_PRINTF_NEWLINE);
369 #endif
370 pn532->state = PN532_STATE_READY;
371 return PN532_ERROR_EXTENDEDFRAME;
372 }
373 else
374 {
375 // Normal frame
376 if (256 != (pbtResponse[3] + pbtResponse[4]))
377 {
378 // TODO: Retry
379 #ifdef PN532_DEBUGMODE
380 PN532_DEBUG("Length checksum mismatch%s", CFG_PRINTF_NEWLINE);
381 #endif
382 pn532->state = PN532_STATE_READY;
383 return PN532_ERROR_LENCHECKSUMMISMATCH;
384 }
385 }
386
387 // Figure out how large the response really is
388 // Response Frame Len = pbtResponse[3] + 7 (00 00 FF LEN LCS TFI [DATA] DCS)
389 *pszRxLen = pbtResponse[3] + 7;
390
391 pn532->state = PN532_STATE_READY;
392 return PN532_ERROR_NONE;
393 }
394
395 /**************************************************************************/
396 /*!
397 @brief Sends the wakeup sequence to the PN532.
398
399 @note Possible error message are:
400
401 - PN532_ERROR_BUSY
402 - PN532_ERROR_I2C_NACK // No I2C ACK
403 - PN532_ERROR_READYSTATUSTIMEOUT // Timed out waiting for ready bit
404 */
405 /**************************************************************************/
406 pn532_error_t pn532_bus_Wakeup(void)
407 {
408 size_t szLen;
409 pn532_error_t error = PN532_ERROR_NONE;
410 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 };
411 uint32_t i;
412
413 pn532_pcb_t *pn532 = pn532GetPCB();
414
415 #ifdef PN532_DEBUGMODE
416 PN532_DEBUG("Sending Wakeup Sequence%s", CFG_PRINTF_NEWLINE);
417 #endif
418 error = pn532_bus_i2c_WriteData(abtWakeUp,sizeof(abtWakeUp));
419 systickDelay(100);
420
421 // Wait for the IRQ/Ready flag to indicate a response is ready
422 if (!(pn532_bus_i2c_WaitForReady()))
423 {
424 error = PN532_ERROR_READYSTATUSTIMEOUT;
425 }
426
427 // Read and discard the ACK frame
428 for ( i = 0; i < I2C_BUFSIZE; i++ )
429 {
430 I2CMasterBuffer[i] = 0x00;
431 }
432 I2CWriteLength = 0;
433 I2CReadLength = 7; // ACK + Ready bit = 7
434 I2CMasterBuffer[0] = PN532_I2C_ADDRESS | PN532_I2C_READBIT;
435 i2cEngine();
436 systickDelay(1);
437
438 // Wait for the IRQ/Ready flag to indicate a response is ready
439 if (!(pn532_bus_i2c_WaitForReady()))
440 {
441 error = PN532_ERROR_READYSTATUSTIMEOUT;
442 }
443
444 pn532->state = PN532_STATE_READY;
445 return error;
446 }
447
448 #endif // #ifdef PN532_BUS_I2C
This page took 0.064371 seconds and 5 git commands to generate.