1 /**************************************************************************/
4 @author K. Townsend (microBuilder.eu)
8 Software License Agreement (BSD License)
10 Copyright (c) 2012, microBuilder SARL
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions are met:
15 1. Redistributions of source code must retain the above copyright
16 notice, this list of conditions and the following disclaimer.
17 2. Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
20 3. Neither the name of the copyright holders nor the
21 names of its contributors may be used to endorse or promote products
22 derived from this software without specific prior written permission.
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
25 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
28 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 /**************************************************************************/
39 #include "pn532_bus.h"
43 #include "core/systick/systick.h"
44 #include "core/gpio/gpio.h"
45 #include "core/i2c/i2c.h"
47 extern volatile uint8_t I2CMasterBuffer
[I2C_BUFSIZE
];
48 extern volatile uint8_t I2CSlaveBuffer
[I2C_BUFSIZE
];
49 extern volatile uint32_t I2CReadLength
, I2CWriteLength
;
51 /* ======================================================================
53 ====================================================================== */
55 /**************************************************************************/
57 @brief Writes an 8 bit value over I2C
59 @note Possible error messages are:
61 - PN532_ERROR_I2C_NACK
63 /**************************************************************************/
64 pn532_error_t
pn532_bus_i2c_WriteData (const byte_t
* pbtData
, const size_t szData
)
68 // Clear write buffers
70 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
72 I2CMasterBuffer
[i
] = 0x00;
75 // Send the specified bytes
76 I2CWriteLength
= szData
+1;
78 I2CMasterBuffer
[0] = PN532_I2C_ADDRESS
; // I2C device address
79 for ( i
= 0; i
< szData
; i
++ )
81 I2CMasterBuffer
[i
+1] = pbtData
[i
];
83 i2cState
= i2cEngine();
85 // Check if we got an ACK
86 if ((i2cState
== I2CSTATE_NACK
) || (i2cState
== I2CSTATE_SLA_NACK
))
88 // I2C slave didn't acknowledge the master transfer
89 // The PN532 probably isn't connected properly or the
90 // bus select pins are in the wrong state
91 return PN532_ERROR_I2C_NACK
;
94 return PN532_ERROR_NONE
;
97 /**************************************************************************/
99 @brief Checks the 'IRQ' pin to know if the PN532 is ready to send
102 @note The IRQ bit may stay high intentionally, and this isn't
103 always an error condition. When PN532_COMMAND_INLISTPASSIVETARGET
104 is sent, for example, the PN532 will wait until a card
105 enters the magnetic field, and IRQ will remain high since
106 there is no response ready yet. The IRQ pin will go low
107 as soon as a card enters the magentic field and the data
108 has been retrieved from it.
110 @returns 1 if a response is ready, 0 if the PN532 is still busy or a
113 /**************************************************************************/
114 uint8_t pn532_bus_i2c_WaitForReady(void)
117 // uint8_t busyTimeout = 0;
121 // For now, we wait forever until a command is ready
122 // ToDo: Add user-specified timeout
123 busy
= gpioGetValue(PN532_I2C_IRQPORT
, PN532_I2C_IRQPIN
);
126 // if (busyTimeout == PN532_I2C_READYTIMEOUT)
135 /**************************************************************************/
137 @brief Builds a standard PN532 frame using the supplied data
139 @param pbtFrame Pointer to the field that will hold the frame data
140 @param pszFrame Pointer to the field that will hold the frame length
141 @param pbtData Pointer to the data to insert in a frame
142 @param swData Length of the data to insert in bytes
144 @note Possible error messages are:
146 - PN532_ERROR_EXTENDEDFRAME
148 /**************************************************************************/
149 pn532_error_t
pn532_bus_i2c_BuildFrame(byte_t
* pbtFrame
, size_t * pszFrame
, const byte_t
* pbtData
, const size_t szData
)
151 if (szData
> PN532_NORMAL_FRAME__DATA_MAX_LEN
)
153 // Extended frames currently unsupported
154 return PN532_ERROR_EXTENDEDFRAME
;
157 // LEN - Packet length = data length (len) + checksum (1) + end of stream marker (1)
158 pbtFrame
[3] = szData
+ 1;
159 // LCS - Packet length checksum
160 pbtFrame
[4] = 256 - (szData
+ 1);
163 // DATA - Copy the PN53X command into the packet buffer
164 memcpy (pbtFrame
+ 6, pbtData
, szData
);
166 // DCS - Calculate data payload checksum
167 byte_t btDCS
= (256 - 0xD4);
169 for (szPos
= 0; szPos
< szData
; szPos
++)
171 btDCS
-= pbtData
[szPos
];
173 pbtFrame
[6 + szData
] = btDCS
;
175 // 0x00 - End of stream marker
176 pbtFrame
[szData
+ 7] = 0x00;
178 (*pszFrame
) = szData
+ PN532_NORMAL_FRAME__OVERHEAD
;
180 return PN532_ERROR_NONE
;
183 /* ======================================================================
185 ====================================================================== */
187 /**************************************************************************/
189 @brief Initialises I2C and configures the PN532 HW
191 /**************************************************************************/
192 void pn532_bus_HWInit(void)
194 #ifdef PN532_DEBUGMODE
195 PN532_DEBUG("Initialising I2C %s", CFG_PRINTF_NEWLINE
);
199 // Set IRQ pin to input
200 gpioSetDir(PN532_I2C_IRQPORT
, PN532_I2C_IRQPIN
, gpioDirection_Input
);
202 // Set reset pin as output and reset device
203 gpioSetDir(PN532_RSTPD_PORT
, PN532_RSTPD_PIN
, gpioDirection_Output
);
204 #ifdef PN532_DEBUGMODE
205 PN532_DEBUG("Resetting the PN532...\r\n");
207 gpioSetValue(PN532_RSTPD_PORT
, PN532_RSTPD_PIN
, 0);
209 gpioSetValue(PN532_RSTPD_PORT
, PN532_RSTPD_PIN
, 1);
211 // Wait for the PN532 to finish booting
215 /**************************************************************************/
217 @brief Sends the specified command to the PN532, automatically
218 creating an appropriate frame for it
220 @param pdbData Pointer to the byte data to send
221 @param szData Length in bytes of the data to send
223 @note Possible error messages are:
225 - PN532_ERROR_EXTENDEDFRAME // Extended frames not supported
226 - PN532_ERROR_BUSY // Already busy with a command
227 - PN532_ERROR_I2C_NACK // No ACK on I2C
228 - PN532_ERROR_READYSTATUSTIMEOUT // Timeout waiting for ready bit
229 - PN532_ERROR_INVALIDACK // No ACK frame received
231 /**************************************************************************/
232 pn532_error_t
pn532_bus_SendCommand(const byte_t
* pbtData
, const size_t szData
)
234 pn532_error_t error
= PN532_ERROR_NONE
;
235 pn532_pcb_t
*pn532
= pn532GetPCB();
237 // Check if we're busy
238 if (pn532
->state
== PN532_STATE_BUSY
)
240 return PN532_ERROR_BUSY
;
243 // Flag the stack as busy
244 pn532
->state
= PN532_STATE_BUSY
;
246 // --------------------------------------------------------------------
247 // Send the command frame
248 // --------------------------------------------------------------------
249 byte_t abtFrame
[PN532_BUFFER_LEN
] = { 0x00, 0x00, 0xff };
253 pn532_bus_i2c_BuildFrame (abtFrame
, &szFrame
, pbtData
, szData
);
255 // Keep track of the last command that was sent
256 pn532
->lastCommand
= pbtData
[0];
258 // Output the frame data for debugging if requested
259 #ifdef PN532_DEBUGMODE
260 PN532_DEBUG("Sending (%02d): ", szFrame
);
261 pn532PrintHex(abtFrame
, szFrame
);
264 // Send data to the PN532
265 error
= pn532_bus_i2c_WriteData(abtFrame
, szFrame
);
267 if (error
== PN532_ERROR_I2C_NACK
)
269 // Most likely error is PN532_ERROR_I2C_NACK
270 // meaning no I2C ACK received from the PN532
271 #ifdef PN532_DEBUGMODE
272 PN532_DEBUG ("No ACK received on I2C bus%s", CFG_PRINTF_NEWLINE
);
274 pn532
->state
= PN532_STATE_READY
;
278 // --------------------------------------------------------------------
279 // Wait for the IRQ/Ready flag
280 // --------------------------------------------------------------------
281 if (!(pn532_bus_i2c_WaitForReady()))
283 pn532
->state
= PN532_STATE_READY
;
284 #ifdef PN532_DEBUGMODE
285 PN532_DEBUG ("Timed out waiting for IRQ/Ready%s", CFG_PRINTF_NEWLINE
);
287 return PN532_ERROR_READYSTATUSTIMEOUT
;
290 // --------------------------------------------------------------------
291 // Read the ACK frame
292 // --------------------------------------------------------------------
295 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
297 I2CMasterBuffer
[i
] = 0x00;
300 I2CReadLength
= 7; // ACK + Ready bit = 7
301 I2CMasterBuffer
[0] = PN532_I2C_ADDRESS
| PN532_I2C_READBIT
;
304 // Make sure the received ACK matches the prototype
305 const byte_t abtAck
[6] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
307 // memcpy(abtRxBuf, I2CSlaveBuffer+1, 6);
308 for ( i
= 0; i
< 6; i
++ )
310 abtRxBuf
[i
] = I2CSlaveBuffer
[i
+1];
312 if (0 != (memcmp (abtRxBuf
, abtAck
, 6)))
314 #ifdef PN532_DEBUGMODE
315 PN532_DEBUG ("Invalid ACK: ");
316 pn532PrintHex(abtRxBuf
, 6);
317 PN532_DEBUG("%s", CFG_PRINTF_NEWLINE
);
319 pn532
->state
= PN532_STATE_READY
;
320 return PN532_ERROR_INVALIDACK
;
323 // --------------------------------------------------------------------
324 // Wait for the post-ACK IRQ/Ready flag
325 // --------------------------------------------------------------------
326 if (!(pn532_bus_i2c_WaitForReady()))
328 pn532
->state
= PN532_STATE_READY
;
329 #ifdef PN532_DEBUGMODE
330 PN532_DEBUG ("Timed out waiting for IRQ/Ready%s", CFG_PRINTF_NEWLINE
);
332 return PN532_ERROR_READYSTATUSTIMEOUT
;
335 pn532
->state
= PN532_STATE_READY
;
336 return PN532_ERROR_NONE
;
339 /**************************************************************************/
341 @brief Reads a response from the PN532
343 @note Possible error message are:
346 - PN532_ERROR_RESPONSEBUFFEREMPTY
347 - PN532_ERROR_PREAMBLEMISMATCH
348 - PN532_ERROR_APPLEVELERROR
349 - PN532_ERROR_EXTENDEDFRAME
350 - PN532_ERROR_LENCHECKSUMMISMATCH
352 /**************************************************************************/
353 pn532_error_t
pn532_bus_ReadResponse(byte_t
* pbtResponse
, size_t * pszRxLen
)
355 pn532_pcb_t
*pn532
= pn532GetPCB();
357 // Check if we're busy
358 if (pn532
->state
== PN532_STATE_BUSY
)
360 return PN532_ERROR_BUSY
;
363 // Flag the stack as busy
364 pn532
->state
= PN532_STATE_BUSY
;
366 // Reset the app error flag
367 pn532
->appError
= PN532_APPERROR_NONE
;
370 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
372 I2CMasterBuffer
[i
] = 0x00;
375 I2CReadLength
= I2C_BUFSIZE
;
376 I2CMasterBuffer
[0] = PN532_I2C_ADDRESS
| PN532_I2C_READBIT
;
379 // Display the raw response data for debugging if requested
380 #ifdef PN532_DEBUGMODE
381 PN532_DEBUG("Received (%02d): ", I2C_BUFSIZE
-1);
382 pn532PrintHex(pbtResponse
, I2C_BUFSIZE
-1);
385 // Use the full I2C buffer size for now (until we're sure we have a good frame)
386 *pszRxLen
= I2C_BUFSIZE
- 1;
388 // Fill the response buffer from I2C (skipping the leading 'ready' bit when using I2C)
389 // memcpy(pbtResponse, I2CSlaveBuffer+1, I2C_BUFSIZE-1);
390 for ( i
= 0; i
< I2C_BUFSIZE
-1; i
++ )
392 pbtResponse
[i
] = I2CSlaveBuffer
[i
+1];
395 // Check the frame type
396 if ((0x01 == pbtResponse
[3]) && (0xff == pbtResponse
[4]))
399 #ifdef PN532_DEBUGMODE
400 PN532_DEBUG("Application level error (0x%02x)%s", pbtResponse
[5], CFG_PRINTF_NEWLINE
);
402 // Set application error message ID
403 pn532
->appError
= pbtResponse
[5];
404 pn532
->state
= PN532_STATE_READY
;
405 return PN532_ERROR_APPLEVELERROR
;
407 else if ((0xff == pbtResponse
[3]) && (0xff == pbtResponse
[4]))
410 #ifdef PN532_DEBUGMODE
411 PN532_DEBUG("Extended frames currently unsupported%s", CFG_PRINTF_NEWLINE
);
413 pn532
->state
= PN532_STATE_READY
;
414 return PN532_ERROR_EXTENDEDFRAME
;
419 if (256 != (pbtResponse
[3] + pbtResponse
[4]))
422 #ifdef PN532_DEBUGMODE
423 PN532_DEBUG("Length checksum mismatch%s", CFG_PRINTF_NEWLINE
);
425 pn532
->state
= PN532_STATE_READY
;
426 return PN532_ERROR_LENCHECKSUMMISMATCH
;
430 // Figure out how large the response really is
431 // Response Frame Len = pbtResponse[3] + 7 (00 00 FF LEN LCS TFI [DATA] DCS)
432 *pszRxLen
= pbtResponse
[3] + 7;
434 pn532
->state
= PN532_STATE_READY
;
435 return PN532_ERROR_NONE
;
438 /**************************************************************************/
440 @brief Sends the wakeup sequence to the PN532.
442 @note Possible error message are:
445 - PN532_ERROR_I2C_NACK // No I2C ACK
446 - PN532_ERROR_READYSTATUSTIMEOUT // Timed out waiting for ready bit
448 /**************************************************************************/
449 pn532_error_t
pn532_bus_Wakeup(void)
451 pn532_error_t error
= PN532_ERROR_NONE
;
452 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 };
455 pn532_pcb_t
*pn532
= pn532GetPCB();
457 #ifdef PN532_DEBUGMODE
458 PN532_DEBUG("Sending Wakeup Sequence%s", CFG_PRINTF_NEWLINE
);
460 error
= pn532_bus_i2c_WriteData(abtWakeUp
,sizeof(abtWakeUp
));
463 // Wait for the IRQ/Ready flag to indicate a response is ready
464 if (!(pn532_bus_i2c_WaitForReady()))
466 error
= PN532_ERROR_READYSTATUSTIMEOUT
;
469 // Read and discard the ACK frame
470 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
472 I2CMasterBuffer
[i
] = 0x00;
475 I2CReadLength
= 7; // ACK + Ready bit = 7
476 I2CMasterBuffer
[0] = PN532_I2C_ADDRESS
| PN532_I2C_READBIT
;
480 // Wait for the IRQ/Ready flag to indicate a response is ready
481 if (!(pn532_bus_i2c_WaitForReady()))
483 error
= PN532_ERROR_READYSTATUSTIMEOUT
;
486 pn532
->state
= PN532_STATE_READY
;
490 #endif // #ifdef PN532_BUS_I2C