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();
201 // Check if we're busy
202 if (pn532
->state
== PN532_STATE_BUSY
)
204 return PN532_ERROR_BUSY
;
207 // Flag the stack as busy
208 pn532
->state
= PN532_STATE_BUSY
;
210 // --------------------------------------------------------------------
211 // Send the command frame
212 // --------------------------------------------------------------------
213 byte_t abtFrame
[PN532_BUFFER_LEN
] = { 0x00, 0x00, 0xff };
217 pn532_bus_BuildFrame (abtFrame
, &szFrame
, pbtData
, szData
);
219 // Keep track of the last command that was sent
220 pn532
->lastCommand
= pbtData
[0];
222 // Output the frame data for debugging if requested
223 #ifdef PN532_DEBUGMODE
224 PN532_DEBUG("Sending (%02d): ", szFrame
);
225 pn532PrintHex(abtFrame
, szFrame
);
228 // Send data to the PN532
229 error
= pn532_bus_i2c_WriteData(abtFrame
, szFrame
);
231 if (error
== PN532_ERROR_I2C_NACK
)
233 // Most likely error is PN532_ERROR_I2C_NACK
234 // meaning no I2C ACK received from the PN532
235 #ifdef PN532_DEBUGMODE
236 PN532_DEBUG ("No ACK received on I2C bus%s", CFG_PRINTF_NEWLINE
);
238 pn532
->state
= PN532_STATE_READY
;
242 // --------------------------------------------------------------------
243 // Wait for the IRQ/Ready flag
244 // --------------------------------------------------------------------
245 if (!(pn532_bus_i2c_WaitForReady()))
247 pn532
->state
= PN532_STATE_READY
;
248 #ifdef PN532_DEBUGMODE
249 PN532_DEBUG ("Timed out waiting for IRQ/Ready%s", CFG_PRINTF_NEWLINE
);
251 return PN532_ERROR_READYSTATUSTIMEOUT
;
254 // --------------------------------------------------------------------
255 // Read the ACK frame
256 // --------------------------------------------------------------------
259 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
261 I2CMasterBuffer
[i
] = 0x00;
264 I2CReadLength
= 7; // ACK + Ready bit = 7
265 I2CMasterBuffer
[0] = PN532_I2C_ADDRESS
| PN532_I2C_READBIT
;
268 // Make sure the received ACK matches the prototype
269 const byte_t abtAck
[6] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
271 memcpy(abtRxBuf
, I2CSlaveBuffer
+1, 6);
272 if (0 != (memcmp (abtRxBuf
, abtAck
, 6)))
274 #ifdef PN532_DEBUGMODE
275 PN532_DEBUG ("Invalid ACK: ");
276 pn532PrintHex(abtRxBuf
, 6);
277 PN532_DEBUG("%s", CFG_PRINTF_NEWLINE
);
279 pn532
->state
= PN532_STATE_READY
;
280 return PN532_ERROR_INVALIDACK
;
283 // --------------------------------------------------------------------
284 // Wait for the post-ACK IRQ/Ready flag
285 // --------------------------------------------------------------------
286 if (!(pn532_bus_i2c_WaitForReady()))
288 pn532
->state
= PN532_STATE_READY
;
289 #ifdef PN532_DEBUGMODE
290 PN532_DEBUG ("Timed out waiting for IRQ/Ready%s", CFG_PRINTF_NEWLINE
);
292 return PN532_ERROR_READYSTATUSTIMEOUT
;
295 pn532
->state
= PN532_STATE_READY
;
296 return PN532_ERROR_NONE
;
299 /**************************************************************************/
301 @brief Reads a response from the PN532
303 @note Possible error message are:
306 - PN532_ERROR_RESPONSEBUFFEREMPTY
307 - PN532_ERROR_PREAMBLEMISMATCH
308 - PN532_ERROR_APPLEVELERROR
309 - PN532_ERROR_EXTENDEDFRAME
310 - PN532_ERROR_LENCHECKSUMMISMATCH
312 /**************************************************************************/
313 pn532_error_t
pn532_bus_ReadResponse(byte_t
* pbtResponse
, size_t * pszRxLen
)
315 pn532_pcb_t
*pn532
= pn532GetPCB();
317 // Check if we're busy
318 if (pn532
->state
== PN532_STATE_BUSY
)
320 return PN532_ERROR_BUSY
;
323 // Flag the stack as busy
324 pn532
->state
= PN532_STATE_BUSY
;
326 // Reset the app error flag
327 pn532
->appError
= PN532_APPERROR_NONE
;
330 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
332 I2CMasterBuffer
[i
] = 0x00;
335 I2CReadLength
= I2C_BUFSIZE
;
336 I2CMasterBuffer
[0] = PN532_I2C_ADDRESS
| PN532_I2C_READBIT
;
339 // Display the raw response data for debugging if requested
340 #ifdef PN532_DEBUGMODE
341 PN532_DEBUG("Received (%02d): ", I2C_BUFSIZE
-1);
342 pn532PrintHex(pbtResponse
, I2C_BUFSIZE
-1);
345 // Use the full I2C buffer size for now (until we're sure we have a good frame)
346 *pszRxLen
= I2C_BUFSIZE
- 1;
348 // Fill the response buffer from I2C (skipping the leading 'ready' bit when using I2C)
349 memcpy(pbtResponse
, I2CSlaveBuffer
+1, I2C_BUFSIZE
-1);
351 // Check the frame type
352 if ((0x01 == pbtResponse
[3]) && (0xff == pbtResponse
[4]))
355 #ifdef PN532_DEBUGMODE
356 PN532_DEBUG("Application level error (0x%02x)%s", pbtResponse
[5], CFG_PRINTF_NEWLINE
);
358 // Set application error message ID
359 pn532
->appError
= pbtResponse
[5];
360 pn532
->state
= PN532_STATE_READY
;
361 return PN532_ERROR_APPLEVELERROR
;
363 else if ((0xff == pbtResponse
[3]) && (0xff == pbtResponse
[4]))
366 #ifdef PN532_DEBUGMODE
367 PN532_DEBUG("Extended frames currently unsupported%s", CFG_PRINTF_NEWLINE
);
369 pn532
->state
= PN532_STATE_READY
;
370 return PN532_ERROR_EXTENDEDFRAME
;
375 if (256 != (pbtResponse
[3] + pbtResponse
[4]))
378 #ifdef PN532_DEBUGMODE
379 PN532_DEBUG("Length checksum mismatch%s", CFG_PRINTF_NEWLINE
);
381 pn532
->state
= PN532_STATE_READY
;
382 return PN532_ERROR_LENCHECKSUMMISMATCH
;
386 // Figure out how large the response really is
387 // Response Frame Len = pbtResponse[3] + 7 (00 00 FF LEN LCS TFI [DATA] DCS)
388 *pszRxLen
= pbtResponse
[3] + 7;
390 pn532
->state
= PN532_STATE_READY
;
391 return PN532_ERROR_NONE
;
394 /**************************************************************************/
396 @brief Sends the wakeup sequence to the PN532.
398 @note Possible error message are:
401 - PN532_ERROR_I2C_NACK // No I2C ACK
402 - PN532_ERROR_READYSTATUSTIMEOUT // Timed out waiting for ready bit
404 /**************************************************************************/
405 pn532_error_t
pn532_bus_Wakeup(void)
407 pn532_error_t error
= PN532_ERROR_NONE
;
408 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 pn532_pcb_t
*pn532
= pn532GetPCB();
413 #ifdef PN532_DEBUGMODE
414 PN532_DEBUG("Sending Wakeup Sequence%s", CFG_PRINTF_NEWLINE
);
416 error
= pn532_bus_i2c_WriteData(abtWakeUp
,sizeof(abtWakeUp
));
419 // Wait for the IRQ/Ready flag to indicate a response is ready
420 if (!(pn532_bus_i2c_WaitForReady()))
422 error
= PN532_ERROR_READYSTATUSTIMEOUT
;
425 // Read and discard the ACK frame
426 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
428 I2CMasterBuffer
[i
] = 0x00;
431 I2CReadLength
= 7; // ACK + Ready bit = 7
432 I2CMasterBuffer
[0] = PN532_I2C_ADDRESS
| PN532_I2C_READBIT
;
436 // Wait for the IRQ/Ready flag to indicate a response is ready
437 if (!(pn532_bus_i2c_WaitForReady()))
439 error
= PN532_ERROR_READYSTATUSTIMEOUT
;
442 pn532
->state
= PN532_STATE_READY
;
446 #endif // #ifdef PN532_BUS_I2C