1 /**************************************************************************/
5 @copyright Kevin Townsend 2012
7 /**************************************************************************/
11 #include "pn532_bus.h"
15 #include "core/systick/systick.h"
16 #include "core/gpio/gpio.h"
17 #include "core/i2c/i2c.h"
19 extern volatile uint8_t I2CMasterBuffer
[I2C_BUFSIZE
];
20 extern volatile uint8_t I2CSlaveBuffer
[I2C_BUFSIZE
];
21 extern volatile uint32_t I2CReadLength
, I2CWriteLength
;
23 /**************************************************************************/
25 @brief Writes an 8 bit value over I2C
27 @note Possible error messages are:
29 - PN532_ERROR_I2C_NACK
31 /**************************************************************************/
32 pn532_error_t
pn532_bus_i2c_WriteData (const byte_t
* pbtData
, const size_t szData
)
36 // Clear write buffers
38 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
40 I2CMasterBuffer
[i
] = 0x00;
43 // Send the specified bytes
44 I2CWriteLength
= szData
+1;
46 I2CMasterBuffer
[0] = PN532_I2C_ADDRESS
; // I2C device address
47 for ( i
= 0; i
< szData
; i
++ )
49 I2CMasterBuffer
[i
+1] = pbtData
[i
];
51 i2cState
= i2cEngine();
53 // Check if we got an ACK
54 if ((i2cState
== I2CSTATE_NACK
) || (i2cState
== I2CSTATE_SLA_NACK
))
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
;
62 return PN532_ERROR_NONE
;
65 /**************************************************************************/
67 @brief Checks the 'IRQ' pin to know if the PN532 is ready to send
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.
78 @returns 1 if a response is ready, 0 if the PN532 is still busy or a
81 /**************************************************************************/
82 uint8_t pn532_bus_i2c_WaitForReady(void)
85 // uint8_t busyTimeout = 0;
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
);
94 // if (busyTimeout == PN532_I2C_READYTIMEOUT)
103 /**************************************************************************/
105 @brief Builds a standard PN532 frame using the supplied data
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
112 @note Possible error messages are:
114 - PN532_ERROR_EXTENDEDFRAME
116 /**************************************************************************/
117 pn532_error_t
pn532_bus_BuildFrame(byte_t
* pbtFrame
, size_t * pszFrame
, const byte_t
* pbtData
, const size_t szData
)
119 if (szData
> PN532_NORMAL_FRAME__DATA_MAX_LEN
)
121 // Extended frames currently unsupported
122 return PN532_ERROR_EXTENDEDFRAME
;
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);
131 // DATA - Copy the PN53X command into the packet buffer
132 memcpy (pbtFrame
+ 6, pbtData
, szData
);
134 // DCS - Calculate data payload checksum
135 byte_t btDCS
= (256 - 0xD4);
137 for (szPos
= 0; szPos
< szData
; szPos
++)
139 btDCS
-= pbtData
[szPos
];
141 pbtFrame
[6 + szData
] = btDCS
;
143 // 0x00 - End of stream marker
144 pbtFrame
[szData
+ 7] = 0x00;
146 (*pszFrame
) = szData
+ PN532_NORMAL_FRAME__OVERHEAD
;
148 return PN532_ERROR_NONE
;
151 /**************************************************************************/
153 @brief Initialises I2C and configures the PN532 HW
155 /**************************************************************************/
156 void pn532_bus_HWInit(void)
158 #ifdef PN532_DEBUGMODE
159 PN532_DEBUG("Initialising I2C %s", CFG_PRINTF_NEWLINE
);
163 // Set IRQ pin to input
164 gpioSetDir(PN532_I2C_IRQPORT
, PN532_I2C_IRQPIN
, gpioDirection_Input
);
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");
171 gpioSetValue(PN532_RSTPD_PORT
, PN532_RSTPD_PIN
, 0);
173 gpioSetValue(PN532_RSTPD_PORT
, PN532_RSTPD_PIN
, 1);
175 // Wait for the PN532 to finish booting
179 /**************************************************************************/
181 @brief Sends the specified command to the PN532, automatically
182 creating an appropriate frame for it
184 @param pdbData Pointer to the byte data to send
185 @param szData Length in bytes of the data to send
187 @note Possible error messages are:
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
195 /**************************************************************************/
196 pn532_error_t
pn532_bus_SendCommand(const byte_t
* pbtData
, const size_t szData
)
198 pn532_error_t error
= PN532_ERROR_NONE
;
199 pn532_pcb_t
*pn532
= pn532GetPCB();
200 uint32_t ready_timeout
= 0;
202 // Check if we're busy
203 if (pn532
->state
== PN532_STATE_BUSY
)
205 return PN532_ERROR_BUSY
;
208 // Flag the stack as busy
209 pn532
->state
= PN532_STATE_BUSY
;
211 // --------------------------------------------------------------------
212 // Send the command frame
213 // --------------------------------------------------------------------
214 byte_t abtFrame
[PN532_BUFFER_LEN
] = { 0x00, 0x00, 0xff };
218 pn532_bus_BuildFrame (abtFrame
, &szFrame
, pbtData
, szData
);
220 // Keep track of the last command that was sent
221 pn532
->lastCommand
= pbtData
[0];
223 // Output the frame data for debugging if requested
224 #ifdef PN532_DEBUGMODE
225 PN532_DEBUG("Sending (%02d): ", szFrame
);
226 pn532PrintHex(abtFrame
, szFrame
);
229 // Send data to the PN532
230 error
= pn532_bus_i2c_WriteData(abtFrame
, szFrame
);
232 if (error
== PN532_ERROR_I2C_NACK
)
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
);
239 pn532
->state
= PN532_STATE_READY
;
243 // --------------------------------------------------------------------
244 // Wait for the IRQ/Ready flag
245 // --------------------------------------------------------------------
246 if (!(pn532_bus_i2c_WaitForReady()))
248 pn532
->state
= PN532_STATE_READY
;
249 #ifdef PN532_DEBUGMODE
250 PN532_DEBUG ("Timed out waiting for IRQ/Ready%s", CFG_PRINTF_NEWLINE
);
252 return PN532_ERROR_READYSTATUSTIMEOUT
;
255 // --------------------------------------------------------------------
256 // Read the ACK frame
257 // --------------------------------------------------------------------
260 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
262 I2CMasterBuffer
[i
] = 0x00;
265 I2CReadLength
= 7; // ACK + Ready bit = 7
266 I2CMasterBuffer
[0] = PN532_I2C_ADDRESS
| PN532_I2C_READBIT
;
269 // Make sure the received ACK matches the prototype
270 const byte_t abtAck
[6] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
272 memcpy(abtRxBuf
, I2CSlaveBuffer
+1, 6);
273 if (0 != (memcmp (abtRxBuf
, abtAck
, 6)))
275 #ifdef PN532_DEBUGMODE
276 PN532_DEBUG ("Invalid ACK: ");
277 pn532PrintHex(abtRxBuf
, 6);
278 PN532_DEBUG("%s", CFG_PRINTF_NEWLINE
);
280 pn532
->state
= PN532_STATE_READY
;
281 return PN532_ERROR_INVALIDACK
;
284 // --------------------------------------------------------------------
285 // Wait for the post-ACK IRQ/Ready flag
286 // --------------------------------------------------------------------
287 if (!(pn532_bus_i2c_WaitForReady()))
289 pn532
->state
= PN532_STATE_READY
;
290 #ifdef PN532_DEBUGMODE
291 PN532_DEBUG ("Timed out waiting for IRQ/Ready%s", CFG_PRINTF_NEWLINE
);
293 return PN532_ERROR_READYSTATUSTIMEOUT
;
296 pn532
->state
= PN532_STATE_READY
;
297 return PN532_ERROR_NONE
;
300 /**************************************************************************/
302 @brief Reads a response from the PN532
304 @note Possible error message are:
307 - PN532_ERROR_RESPONSEBUFFEREMPTY
308 - PN532_ERROR_PREAMBLEMISMATCH
309 - PN532_ERROR_APPLEVELERROR
310 - PN532_ERROR_EXTENDEDFRAME
311 - PN532_ERROR_LENCHECKSUMMISMATCH
313 /**************************************************************************/
314 pn532_error_t
pn532_bus_ReadResponse(byte_t
* pbtResponse
, size_t * pszRxLen
)
316 pn532_pcb_t
*pn532
= pn532GetPCB();
318 // Check if we're busy
319 if (pn532
->state
== PN532_STATE_BUSY
)
321 return PN532_ERROR_BUSY
;
324 // Flag the stack as busy
325 pn532
->state
= PN532_STATE_BUSY
;
327 // Reset the app error flag
328 pn532
->appError
= PN532_APPERROR_NONE
;
331 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
333 I2CMasterBuffer
[i
] = 0x00;
336 I2CReadLength
= I2C_BUFSIZE
;
337 I2CMasterBuffer
[0] = PN532_I2C_ADDRESS
| PN532_I2C_READBIT
;
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);
346 // Use the full I2C buffer size for now (until we're sure we have a good frame)
347 *pszRxLen
= I2C_BUFSIZE
- 1;
349 // Fill the response buffer from I2C (skipping the leading 'ready' bit when using I2C)
350 memcpy(pbtResponse
, I2CSlaveBuffer
+1, I2C_BUFSIZE
-1);
352 // Check the frame type
353 if ((0x01 == pbtResponse
[3]) && (0xff == pbtResponse
[4]))
356 #ifdef PN532_DEBUGMODE
357 PN532_DEBUG("Application level error (0x%02x)%s", pbtResponse
[5], CFG_PRINTF_NEWLINE
);
359 // Set application error message ID
360 pn532
->appError
= pbtResponse
[5];
361 pn532
->state
= PN532_STATE_READY
;
362 return PN532_ERROR_APPLEVELERROR
;
364 else if ((0xff == pbtResponse
[3]) && (0xff == pbtResponse
[4]))
367 #ifdef PN532_DEBUGMODE
368 PN532_DEBUG("Extended frames currently unsupported%s", CFG_PRINTF_NEWLINE
);
370 pn532
->state
= PN532_STATE_READY
;
371 return PN532_ERROR_EXTENDEDFRAME
;
376 if (256 != (pbtResponse
[3] + pbtResponse
[4]))
379 #ifdef PN532_DEBUGMODE
380 PN532_DEBUG("Length checksum mismatch%s", CFG_PRINTF_NEWLINE
);
382 pn532
->state
= PN532_STATE_READY
;
383 return PN532_ERROR_LENCHECKSUMMISMATCH
;
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;
391 pn532
->state
= PN532_STATE_READY
;
392 return PN532_ERROR_NONE
;
395 /**************************************************************************/
397 @brief Sends the wakeup sequence to the PN532.
399 @note Possible error message are:
402 - PN532_ERROR_I2C_NACK // No I2C ACK
403 - PN532_ERROR_READYSTATUSTIMEOUT // Timed out waiting for ready bit
405 /**************************************************************************/
406 pn532_error_t
pn532_bus_Wakeup(void)
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 };
413 pn532_pcb_t
*pn532
= pn532GetPCB();
415 #ifdef PN532_DEBUGMODE
416 PN532_DEBUG("Sending Wakeup Sequence%s", CFG_PRINTF_NEWLINE
);
418 error
= pn532_bus_i2c_WriteData(abtWakeUp
,sizeof(abtWakeUp
));
421 // Wait for the IRQ/Ready flag to indicate a response is ready
422 if (!(pn532_bus_i2c_WaitForReady()))
424 error
= PN532_ERROR_READYSTATUSTIMEOUT
;
427 // Read and discard the ACK frame
428 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
430 I2CMasterBuffer
[i
] = 0x00;
433 I2CReadLength
= 7; // ACK + Ready bit = 7
434 I2CMasterBuffer
[0] = PN532_I2C_ADDRESS
| PN532_I2C_READBIT
;
438 // Wait for the IRQ/Ready flag to indicate a response is ready
439 if (!(pn532_bus_i2c_WaitForReady()))
441 error
= PN532_ERROR_READYSTATUSTIMEOUT
;
444 pn532
->state
= PN532_STATE_READY
;
448 #endif // #ifdef PN532_BUS_I2C