The mbed code for our second prototype

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
smcqueen
Date:
Mon Nov 17 01:09:06 2014 +0000
Commit message:
Final code for prototype 2

Changed in this revision

PN532/Adafruit_PN532.cpp Show annotated file Show diff for this revision Revisions of this file
PN532/Adafruit_PN532.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 76b77ec0a86d PN532/Adafruit_PN532.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PN532/Adafruit_PN532.cpp	Mon Nov 17 01:09:06 2014 +0000
@@ -0,0 +1,1035 @@
+/**************************************************************************/
+/*! 
+    @file     Adafruit_PN532.cpp
+    @author   Adafruit Industries
+    @license  BSD (see license.txt)
+    
+    SPI Driver for NXP's PN532 NFC/13.56MHz RFID Transceiver
+
+    This is a library for the Adafruit PN532 NFC/RFID breakout boards
+    This library works with the Adafruit NFC breakout 
+    ----> https://www.adafruit.com/products/364
+    
+    Check out the links above for our tutorials and wiring diagrams 
+    These chips use SPI to communicate, 4 required to interface
+    
+    Adafruit invests time and resources providing this open source code, 
+    please support Adafruit and open-source hardware by purchasing 
+    products from Adafruit!
+
+
+    @section  HISTORY
+
+    v1.4 - Added setPassiveActivationRetries()
+    
+    v1.2 - Added writeGPIO()
+         - Added readGPIO()
+
+    v1.1 - Changed readPassiveTargetID() to handle multiple UID sizes
+         - Added the following helper functions for text display
+             static void PrintHex(const uint8_t * data, const uint32_t numuint8_ts)
+             static void PrintHexChar(const uint8_t * pbtData, const uint32_t numuint8_ts)
+         - Added the following Mifare Classic functions:
+             bool mifareclassic_IsFirstBlock (uint32_t uiBlock)
+             bool mifareclassic_IsTrailerBlock (uint32_t uiBlock)
+             uint8_t mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData)
+             uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data)
+             uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data)
+         - Added the following Mifare Ultalight functions:
+             uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t * buffer) 
+*/
+/**************************************************************************/
+
+#include "Adafruit_PN532.h"
+
+uint8_t pn532ack[] = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00};
+uint8_t pn532response_firmwarevers[] = {0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03};
+
+// Uncomment these lines to enable debug output for PN532(SPI) and/or MIFARE related code
+// #define PN532DEBUG
+// #define MIFAREDEBUG
+
+Serial serial(USBTX, USBRX);
+#define SERIAL_PRINT serial.printf
+
+#define _BV(bit) (1 << (bit))
+#define PN532_PACKBUFFSIZ 64
+uint8_t pn532_packetbuffer[PN532_PACKBUFFSIZ];
+
+void delay(int delayInMS) {
+  wait(1.0 * delayInMS / 1000);
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Instantiates a new PN532 class
+
+    @param  clk       SPI clock pin (SCK)
+    @param  miso      SPI MISO pin 
+    @param  mosi      SPI MOSI pin
+    @param  ss        SPI chip select pin (CS/SSEL)
+*/
+/**************************************************************************/
+Adafruit_PN532::Adafruit_PN532(DigitalOut clk, DigitalIn miso,
+                               DigitalOut mosi, DigitalOut ss)
+    : _clk(clk), _miso(miso), _mosi(mosi), _ss(ss) {}
+
+Adafruit_PN532::Adafruit_PN532(PinName clk_pin, PinName miso_pin,
+                               PinName mosi_pin, PinName ss_pin)
+    : _clk(DigitalOut(clk_pin)), _miso(DigitalIn(miso_pin)),
+      _mosi(DigitalOut(mosi_pin)), _ss(DigitalOut(ss_pin)) {}
+
+/**************************************************************************/
+/*! 
+    @brief  Setups the HW
+*/
+/**************************************************************************/
+void Adafruit_PN532::begin() {
+  _ss = 0;  
+  delay(1000);
+
+  // not exactly sure why but we have to send a dummy command to get synced up
+  pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
+  sendCommandCheckAck(pn532_packetbuffer, 1);
+
+  // ignore response!
+}
+ 
+/**************************************************************************/
+/*! 
+    @brief  Prints a hexadecimal value in plain characters
+
+    @param  data      Pointer to the uint8_t data
+    @param  numuint8_ts  Data length in uint8_ts
+*/
+/**************************************************************************/
+void Adafruit_PN532::PrintHex(const uint8_t * data, const uint32_t numuint8_ts)
+{
+  uint32_t szPos;
+  for (szPos=0; szPos < numuint8_ts; szPos++) 
+  {
+    SERIAL_PRINT("0x");
+    // Append leading 0 for small values
+    if (data[szPos] <= 0xF)
+      SERIAL_PRINT("0");
+    SERIAL_PRINT("%d", data[szPos]);
+    if ((numuint8_ts > 1) && (szPos != numuint8_ts - 1))
+    {
+      SERIAL_PRINT(" ");
+    }
+  }
+  SERIAL_PRINT("\n");
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Prints a hexadecimal value in plain characters, along with
+            the char equivalents in the following format
+
+            00 00 00 00 00 00  ......
+
+    @param  data      Pointer to the uint8_t data
+    @param  numuint8_ts  Data length in uint8_ts
+*/
+/**************************************************************************/
+void Adafruit_PN532::PrintHexChar(const uint8_t * data, const uint32_t numuint8_ts)
+{
+  uint32_t szPos;
+  for (szPos=0; szPos < numuint8_ts; szPos++) 
+  {
+    // Append leading 0 for small values
+    if (data[szPos] <= 0xF)
+      SERIAL_PRINT("0");
+    SERIAL_PRINT("%x", data[szPos]);
+    if ((numuint8_ts > 1) && (szPos != numuint8_ts - 1))
+    {
+      SERIAL_PRINT(" ");
+    }
+  }
+  SERIAL_PRINT(" ");
+  for (szPos=0; szPos < numuint8_ts; szPos++) 
+  {
+    if (data[szPos] <= 0x1F)
+      SERIAL_PRINT(".");
+    else
+      SERIAL_PRINT("%c", data[szPos]);
+  }
+  SERIAL_PRINT("");
+}
+ 
+/**************************************************************************/
+/*! 
+    @brief  Checks the firmware version of the PN5xx chip
+
+    @returns  The chip's firmware version and ID
+*/
+/**************************************************************************/
+uint32_t Adafruit_PN532::getFirmwareVersion(void) {
+  uint32_t response;
+
+  pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
+  
+  if (! sendCommandCheckAck(pn532_packetbuffer, 1))
+    return 0;
+  
+  // read data packet
+  readspidata(pn532_packetbuffer, 12);
+  
+  // check some basic stuff
+  if (0 != strncmp((char *)pn532_packetbuffer, (char *)pn532response_firmwarevers, 6)) {
+    return 0;
+  }
+  
+  response = pn532_packetbuffer[6];
+  response <<= 8;
+  response |= pn532_packetbuffer[7];
+  response <<= 8;
+  response |= pn532_packetbuffer[8];
+  response <<= 8;
+  response |= pn532_packetbuffer[9];
+
+  return response;
+}
+
+
+/**************************************************************************/
+/*! 
+    @brief  Sends a command and waits a specified period for the ACK
+
+    @param  cmd       Pointer to the command buffer
+    @param  cmdlen    The size of the command in uint8_ts 
+    @param  timeout   timeout before giving up
+    
+    @returns  1 if everything is OK, 0 if timeout occured before an
+              ACK was recieved
+*/
+/**************************************************************************/
+// default timeout of one second
+bool Adafruit_PN532::sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout) {
+  uint16_t timer = 0;
+  
+  // write the command
+  spiwritecommand(cmd, cmdlen);
+  
+  // Wait for chip to say its ready!
+  while (readspistatus() != PN532_SPI_READY) {
+    if (timeout != 0) {
+      timer+=10;
+      if (timer > timeout)  
+        return false;
+    }
+    delay(10);
+  }
+  
+  // read acknowledgement
+  if (!spi_readack()) {
+    return false;
+  }
+  
+  timer = 0;
+  // Wait for chip to say its ready!
+  while (readspistatus() != PN532_SPI_READY) {
+    if (timeout != 0) {
+      timer+=10;
+      if (timer > timeout)  
+        return false;
+    }
+    delay(10);
+  }
+  
+  return true; // ack'd command
+}
+
+/**************************************************************************/
+/*! 
+    Writes an 8-bit value that sets the state of the PN532's GPIO pins
+    
+    @warning This function is provided exclusively for board testing and
+             is dangerous since it will throw an error if any pin other
+             than the ones marked "Can be used as GPIO" are modified!  All
+             pins that can not be used as GPIO should ALWAYS be left high
+             (value = 1) or the system will become unstable and a HW reset
+             will be required to recover the PN532.
+    
+             pinState[0]  = P30     Can be used as GPIO
+             pinState[1]  = P31     Can be used as GPIO
+             pinState[2]  = P32     *** RESERVED (Must be 1!) ***
+             pinState[3]  = P33     Can be used as GPIO
+             pinState[4]  = P34     *** RESERVED (Must be 1!) ***
+             pinState[5]  = P35     Can be used as GPIO
+    
+    @returns 1 if everything executed properly, 0 for an error
+*/
+/**************************************************************************/
+bool Adafruit_PN532::writeGPIO(uint8_t pinstate) {
+  // Make sure pinstate does not try to toggle P32 or P34
+  pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34);
+  
+  // Fill command buffer
+  pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO;
+  pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate;  // P3 Pins
+  pn532_packetbuffer[2] = 0x00;    // P7 GPIO Pins (not used ... taken by SPI)
+
+  #ifdef PN532DEBUG
+    SERIAL_PRINT("Writing P3 GPIO: "); SERIAL_PRINTln(pn532_packetbuffer[1], HEX);
+  #endif
+
+  // Send the WRITEGPIO command (0x0E)  
+  if (! sendCommandCheckAck(pn532_packetbuffer, 3))
+    return 0x0;
+  
+  // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0F) DATACHECKSUM 00)
+  readspidata(pn532_packetbuffer, 8);
+
+  #ifdef PN532DEBUG
+    SERIAL_PRINT("Received: ");
+    PrintHex(pn532_packetbuffer, 8);
+    SERIAL_PRINTln("");
+  #endif  
+  
+  return  (pn532_packetbuffer[5] == 0x0F);
+}
+
+/**************************************************************************/
+/*! 
+    Reads the state of the PN532's GPIO pins
+    
+    @returns An 8-bit value containing the pin state where:
+    
+             pinState[0]  = P30     
+             pinState[1]  = P31     
+             pinState[2]  = P32     
+             pinState[3]  = P33     
+             pinState[4]  = P34     
+             pinState[5]  = P35     
+*/
+/**************************************************************************/
+uint8_t Adafruit_PN532::readGPIO(void) {
+  pn532_packetbuffer[0] = PN532_COMMAND_READGPIO;
+
+  // Send the READGPIO command (0x0C)  
+  if (! sendCommandCheckAck(pn532_packetbuffer, 1))
+    return 0x0;
+  
+  // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0D) P3 P7 IO1 DATACHECKSUM 00)
+  readspidata(pn532_packetbuffer, 11);
+
+  /* READGPIO response should be in the following format:
+  
+    uint8_t            Description
+    -------------   ------------------------------------------
+    b0..5           Frame header and preamble
+    b6              P3 GPIO Pins
+    b7              P7 GPIO Pins (not used ... taken by SPI)
+    b8              Interface Mode Pins (not used ... bus select pins) 
+    b9..10          checksum */
+  
+  #ifdef PN532DEBUG
+    SERIAL_PRINT("Received: ");
+    PrintHex(pn532_packetbuffer, 11);
+    SERIAL_PRINTln("");
+    SERIAL_PRINT("P3 GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[6], HEX);
+    SERIAL_PRINT("P7 GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[7], HEX);
+    SERIAL_PRINT("IO GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[8], HEX);
+    // Note: You can use the IO GPIO value to detect the serial bus being used
+    switch(pn532_packetbuffer[8])
+    {
+      case 0x00:    // Using UART
+        SERIAL_PRINTln("Using UART (IO = 0x00)");
+        break;
+      case 0x01:    // Using I2C 
+        SERIAL_PRINTln("Using I2C (IO = 0x01)");
+        break;
+      case 0x02:    // Using SPI
+        SERIAL_PRINTln("Using SPI (IO = 0x02)");
+        break;
+    }
+  #endif
+
+  return pn532_packetbuffer[6];
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Configures the SAM (Secure Access Module)
+*/
+/**************************************************************************/
+bool Adafruit_PN532::SAMConfig(void) {
+  pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
+  pn532_packetbuffer[1] = 0x01; // normal mode;
+  pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
+  pn532_packetbuffer[3] = 0x01; // use IRQ pin!
+  
+  if (! sendCommandCheckAck(pn532_packetbuffer, 4))
+     return false;
+
+  // read data packet
+  readspidata(pn532_packetbuffer, 8);
+  
+  return  (pn532_packetbuffer[5] == 0x15);
+}
+
+/**************************************************************************/
+/*! 
+    Sets the MxRtyPassiveActivation uint8_t of the RFConfiguration register
+    
+    @param  maxRetries    0xFF to wait forever, 0x00..0xFE to timeout
+                          after mxRetries
+    
+    @returns 1 if everything executed properly, 0 for an error
+*/
+/**************************************************************************/
+bool Adafruit_PN532::setPassiveActivationRetries(uint8_t maxRetries) {
+  pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION;
+  pn532_packetbuffer[1] = 5;    // Config item 5 (MaxRetries)
+  pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF)
+  pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01)
+  pn532_packetbuffer[4] = maxRetries;
+
+#ifdef MIFAREDEBUG
+  SERIAL_PRINT("Setting MxRtyPassiveActivation to "); SERIAL_PRINT(maxRetries, DEC); SERIAL_PRINTln(" ");
+#endif
+  
+  if (! sendCommandCheckAck(pn532_packetbuffer, 5))
+    return 0x0;  // no ACK
+  
+  return 1;
+}
+
+/***** ISO14443A Commands ******/
+
+/**************************************************************************/
+/*! 
+    Waits for an ISO14443A target to enter the field
+    
+    @param  cardBaudRate  Baud rate of the card
+    @param  uid           Pointer to the array that will be populated
+                          with the card's UID (up to 7 uint8_ts)
+    @param  uidLength     Pointer to the variable that will hold the
+                          length of the card's UID.
+    
+    @returns 1 if everything executed properly, 0 for an error
+*/
+/**************************************************************************/
+bool Adafruit_PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength) {
+  pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
+  pn532_packetbuffer[1] = 1;  // max 1 cards at once (we can set this to 2 later)
+  pn532_packetbuffer[2] = cardbaudrate;
+  
+  if (! sendCommandCheckAck(pn532_packetbuffer, 3))
+    return 0x0;  // no cards read
+  
+  // read data packet
+  readspidata(pn532_packetbuffer, 20);
+  // check some basic stuff
+
+  /* ISO14443A card response should be in the following format:
+  
+    uint8_t            Description
+    -------------   ------------------------------------------
+    b0..6           Frame header and preamble
+    b7              Tags Found
+    b8              Tag Number (only one used in this example)
+    b9..10          SENS_RES
+    b11             SEL_RES
+    b12             NFCID Length
+    b13..NFCIDLen   NFCID                                      */
+  
+#ifdef MIFAREDEBUG
+    SERIAL_PRINT("Found "); SERIAL_PRINT(pn532_packetbuffer[7], DEC); SERIAL_PRINTln(" tags");
+#endif
+  if (pn532_packetbuffer[7] != 1) 
+    return 0;
+    
+  uint16_t sens_res = pn532_packetbuffer[9];
+  sens_res <<= 8;
+  sens_res |= pn532_packetbuffer[10];
+#ifdef MIFAREDEBUG
+    SERIAL_PRINT("ATQA: 0x");  SERIAL_PRINTln(sens_res, HEX); 
+    SERIAL_PRINT("SAK: 0x");  SERIAL_PRINTln(pn532_packetbuffer[11], HEX); 
+#endif
+  
+  /* Card appears to be Mifare Classic */
+  *uidLength = pn532_packetbuffer[12];
+#ifdef MIFAREDEBUG
+    SERIAL_PRINT("UID:"); 
+#endif
+  for (uint8_t i=0; i < pn532_packetbuffer[12]; i++) 
+  {
+    uid[i] = pn532_packetbuffer[13+i];
+#ifdef MIFAREDEBUG
+      SERIAL_PRINT(" 0x");SERIAL_PRINT(uid[i], HEX); 
+#endif
+  }
+#ifdef MIFAREDEBUG
+    SERIAL_PRINTln();
+#endif
+
+  uint8_t bTestDeselect[2];
+  bTestDeselect[0] = PN532_COMMAND_INDESELECT;
+  bTestDeselect[1] = pn532_packetbuffer[8];
+  sendCommandCheckAck(bTestDeselect,2);
+
+  return 1;
+}
+
+
+/***** Mifare Classic Functions ******/
+
+/**************************************************************************/
+/*! 
+      Indicates whether the specified block number is the first block
+      in the sector (block 0 relative to the current sector)
+*/
+/**************************************************************************/
+bool Adafruit_PN532::mifareclassic_IsFirstBlock (uint32_t uiBlock)
+{
+  // Test if we are in the small or big sectors
+  if (uiBlock < 128)
+    return ((uiBlock) % 4 == 0);
+  else
+    return ((uiBlock) % 16 == 0);
+}
+
+/**************************************************************************/
+/*! 
+      Indicates whether the specified block number is the sector trailer
+*/
+/**************************************************************************/
+bool Adafruit_PN532::mifareclassic_IsTrailerBlock (uint32_t uiBlock)
+{
+  // Test if we are in the small or big sectors
+  if (uiBlock < 128)
+    return ((uiBlock + 1) % 4 == 0);
+  else
+    return ((uiBlock + 1) % 16 == 0);
+}
+
+/**************************************************************************/
+/*! 
+    Tries to authenticate a block of memory on a MIFARE card using the
+    INDATAEXCHANGE command.  See section 7.3.8 of the PN532 User Manual
+    for more information on sending MIFARE and other commands.
+
+    @param  uid           Pointer to a uint8_t array containing the card UID
+    @param  uidLen        The length (in uint8_ts) of the card's UID (Should
+                          be 4 for MIFARE Classic)
+    @param  blockNumber   The block number to authenticate.  (0..63 for
+                          1KB cards, and 0..255 for 4KB cards).
+    @param  keyNumber     Which key type to use during authentication
+                          (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B)
+    @param  keyData       Pointer to a uint8_t array containing the 6 uint8_t
+                          key value
+    
+    @returns 1 if everything executed properly, 0 for an error
+*/
+/**************************************************************************/
+uint8_t Adafruit_PN532::mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData)
+{
+  uint8_t i;
+  
+  // Hang on to the key and uid data
+  memcpy (_key, keyData, 6); 
+  memcpy (_uid, uid, uidLen); 
+  _uidLen = uidLen;  
+
+  #ifdef MIFAREDEBUG
+  SERIAL_PRINT("Trying to authenticate card ");
+  Adafruit_PN532::PrintHex(_uid, _uidLen);
+  SERIAL_PRINT("Using authentication KEY ");SERIAL_PRINT(keyNumber ? 'B' : 'A');SERIAL_PRINT(": ");
+  Adafruit_PN532::PrintHex(_key, 6);
+  #endif
+  
+  // Prepare the authentication command //
+  pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;   /* Data Exchange Header */
+  pn532_packetbuffer[1] = 1;                              /* Max card numbers */
+  pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
+  pn532_packetbuffer[3] = blockNumber;                    /* Block Number (1K = 0..63, 4K = 0..255 */
+  memcpy (pn532_packetbuffer+4, _key, 6);
+  for (i = 0; i < _uidLen; i++)
+  {
+    pn532_packetbuffer[10+i] = _uid[i];                /* 4 uint8_t card ID */
+  }
+
+  if (! sendCommandCheckAck(pn532_packetbuffer, 10+_uidLen))
+    return 0;
+
+  // Read the response packet
+  readspidata(pn532_packetbuffer, 12);
+  // check if the response is valid and we are authenticated???
+  // for an auth success it should be uint8_ts 5-7: 0xD5 0x41 0x00
+  // Mifare auth error is technically uint8_t 7: 0x14 but anything other and 0x00 is not good
+  if (pn532_packetbuffer[7] != 0x00)
+  {
+    #ifdef PN532DEBUG
+    SERIAL_PRINT("Authentification failed: ");
+    Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 12);
+    #endif
+    return 0;
+  }
+
+  return 1;
+}
+
+/**************************************************************************/
+/*! 
+    Tries to read an entire 16-uint8_t data block at the specified block
+    address.
+
+    @param  blockNumber   The block number to authenticate.  (0..63 for
+                          1KB cards, and 0..255 for 4KB cards).
+    @param  data          Pointer to the uint8_t array that will hold the
+                          retrieved data (if any)
+    
+    @returns 1 if everything executed properly, 0 for an error
+*/
+/**************************************************************************/
+uint8_t Adafruit_PN532::mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data)
+{
+  #ifdef MIFAREDEBUG
+  SERIAL_PRINT("Trying to read 16 uint8_ts from block ");SERIAL_PRINTln(blockNumber);
+  #endif
+  
+  /* Prepare the command */
+  pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
+  pn532_packetbuffer[1] = 1;                      /* Card number */
+  pn532_packetbuffer[2] = MIFARE_CMD_READ;        /* Mifare Read command = 0x30 */
+  pn532_packetbuffer[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */
+
+  /* Send the command */
+  if (! sendCommandCheckAck(pn532_packetbuffer, 4))
+  {
+    #ifdef MIFAREDEBUG
+    SERIAL_PRINTln("Failed to receive ACK for read command");
+    #endif
+    return 0;
+  }
+
+  /* Read the response packet */
+  readspidata(pn532_packetbuffer, 26);
+
+  /* If uint8_t 8 isn't 0x00 we probably have an error */
+  if (pn532_packetbuffer[7] != 0x00)
+  {
+    //#ifdef MIFAREDEBUG
+    SERIAL_PRINT("Unexpected response");
+    Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26);
+    //#endif
+    return 0;
+  }
+    
+  /* Copy the 16 data uint8_ts to the output buffer        */
+  /* Block content starts at uint8_t 9 of a valid response */
+  memcpy (data, pn532_packetbuffer+8, 16);
+
+  /* Display data for debug if requested */
+  #ifdef MIFAREDEBUG
+    SERIAL_PRINT("Block ");
+    SERIAL_PRINTln(blockNumber);
+    Adafruit_PN532::PrintHexChar(data, 16);
+  #endif
+
+  return 1;  
+}
+
+/**************************************************************************/
+/*! 
+    Tries to write an entire 16-uint8_t data block at the specified block
+    address.
+
+    @param  blockNumber   The block number to authenticate.  (0..63 for
+                          1KB cards, and 0..255 for 4KB cards).
+    @param  data          The uint8_t array that contains the data to write.
+    
+    @returns 1 if everything executed properly, 0 for an error
+*/
+/**************************************************************************/
+uint8_t Adafruit_PN532::mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data)
+{
+  #ifdef MIFAREDEBUG
+  SERIAL_PRINT("Trying to write 16 uint8_ts to block ");SERIAL_PRINTln(blockNumber);
+  #endif
+  
+  /* Prepare the first command */
+  pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
+  pn532_packetbuffer[1] = 1;                      /* Card number */
+  pn532_packetbuffer[2] = MIFARE_CMD_WRITE;       /* Mifare Write command = 0xA0 */
+  pn532_packetbuffer[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */
+  memcpy (pn532_packetbuffer+4, data, 16);          /* Data Payload */
+
+  /* Send the command */
+  if (! sendCommandCheckAck(pn532_packetbuffer, 20))
+  {
+    #ifdef MIFAREDEBUG
+    SERIAL_PRINTln("Failed to receive ACK for write command");
+    #endif
+    return 0;
+  }  
+  delay(10);
+  
+  /* Read the response packet */
+  readspidata(pn532_packetbuffer, 26);
+
+  return 1;  
+}
+
+/**************************************************************************/
+/*! 
+    Formats a Mifare Classic card to store NDEF Records 
+    
+    @returns 1 if everything executed properly, 0 for an error
+*/
+/**************************************************************************/
+uint8_t Adafruit_PN532::mifareclassic_FormatNDEF (void)
+{
+  uint8_t sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
+  uint8_t sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
+  uint8_t sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+  // Write block 1 and 2 to the card
+  if (!(mifareclassic_WriteDataBlock (1, sectorbuffer1)))
+    return 0;
+  if (!(mifareclassic_WriteDataBlock (2, sectorbuffer2)))
+    return 0;
+  // Write key A and access rights card
+  if (!(mifareclassic_WriteDataBlock (3, sectorbuffer3)))
+    return 0;
+
+  // Seems that everything was OK (?!)
+  return 1;
+}
+
+/**************************************************************************/
+/*! 
+    Writes an NDEF URI Record to the specified sector (1..15)
+    
+    Note that this function assumes that the Mifare Classic card is
+    already formatted to work as an "NFC Forum Tag" and uses a MAD1
+    file system.  You can use the NXP TagWriter app on Android to
+    properly format cards for this.
+
+    @param  sectorNumber  The sector that the URI record should be written
+                          to (can be 1..15 for a 1K card)
+    @param  uriIdentifier The uri identifier code (0 = none, 0x01 = 
+                          "http://www.", etc.)
+    @param  url           The uri text to write (max 38 characters).
+    
+    @returns 1 if everything executed properly, 0 for an error
+*/
+/**************************************************************************/
+uint8_t Adafruit_PN532::mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char * url)
+{
+  // Figure out how long the string is
+  uint8_t len = strlen(url);
+  
+  // Make sure we're within a 1K limit for the sector number
+  if ((sectorNumber < 1) || (sectorNumber > 15))
+    return 0;
+  
+  // Make sure the URI payload is between 1 and 38 chars
+  if ((len < 1) || (len > 38))
+    return 0;
+    
+  // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message)
+  uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, len+5, 0xD1, 0x01, len+1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+  uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+  uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+  uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+  if (len <= 6)
+  {
+    // Unlikely we'll get a url this short, but why not ...
+    memcpy (sectorbuffer1+9, url, len);
+    sectorbuffer1[len+9] = 0xFE;
+  }
+  else if (len == 7)
+  {
+    // 0xFE needs to be wrapped around to next block
+    memcpy (sectorbuffer1+9, url, len);
+    sectorbuffer2[0] = 0xFE;
+  }
+  else if ((len > 7) || (len <= 22))
+  {
+    // Url fits in two blocks
+    memcpy (sectorbuffer1+9, url, 7);
+    memcpy (sectorbuffer2, url+7, len-7);
+    sectorbuffer2[len-7] = 0xFE;
+  }
+  else if (len == 23)
+  {
+    // 0xFE needs to be wrapped around to final block
+    memcpy (sectorbuffer1+9, url, 7);
+    memcpy (sectorbuffer2, url+7, len-7);
+    sectorbuffer3[0] = 0xFE;
+  }
+  else
+  {
+    // Url fits in three blocks
+    memcpy (sectorbuffer1+9, url, 7);
+    memcpy (sectorbuffer2, url+7, 16);
+    memcpy (sectorbuffer3, url+23, len-24);
+    sectorbuffer3[len-22] = 0xFE;
+  }
+  
+  // Now write all three blocks back to the card
+  if (!(mifareclassic_WriteDataBlock (sectorNumber*4, sectorbuffer1)))
+    return 0;
+  if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+1, sectorbuffer2)))
+    return 0;
+  if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+2, sectorbuffer3)))
+    return 0;
+  if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+3, sectorbuffer4)))
+    return 0;
+
+  // Seems that everything was OK (?!)
+  return 1;
+}
+
+/***** Mifare Ultralight Functions ******/
+
+/**************************************************************************/
+/*! 
+    Tries to read an entire 4-uint8_t page at the specified address.
+
+    @param  page        The page number (0..63 in most cases)
+    @param  buffer      Pointer to the uint8_t array that will hold the
+                        retrieved data (if any)
+*/
+/**************************************************************************/
+uint8_t Adafruit_PN532::mifareultralight_ReadPage (uint8_t page, uint8_t * buffer)
+{
+  if (page >= 64)
+  {
+    #ifdef MIFAREDEBUG
+    SERIAL_PRINTln("Page value out of range");
+    #endif
+    return 0;
+  }
+
+  #ifdef MIFAREDEBUG
+    SERIAL_PRINT("Reading page ");SERIAL_PRINTln(page);
+  #endif
+
+  /* Prepare the command */
+  pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
+  pn532_packetbuffer[1] = 1;                   /* Card number */
+  pn532_packetbuffer[2] = MIFARE_CMD_READ;     /* Mifare Read command = 0x30 */
+  pn532_packetbuffer[3] = page;                /* Page Number (0..63 in most cases) */
+
+  /* Send the command */
+  if (! sendCommandCheckAck(pn532_packetbuffer, 4))
+  {
+    #ifdef MIFAREDEBUG
+    SERIAL_PRINTln("Failed to receive ACK for write command");
+    #endif
+    return 0;
+  }
+  
+  /* Read the response packet */
+  readspidata(pn532_packetbuffer, 26);
+  #ifdef MIFAREDEBUG
+    SERIAL_PRINTln("Received: ");
+    Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26);
+  #endif
+
+  /* If uint8_t 8 isn't 0x00 we probably have an error */
+  if (pn532_packetbuffer[7] == 0x00)
+  {
+    /* Copy the 4 data uint8_ts to the output buffer         */
+    /* Block content starts at uint8_t 9 of a valid response */
+    /* Note that the command actually reads 16 uint8_t or 4  */
+    /* pages at a time ... we simply discard the last 12  */
+    /* uint8_ts                                              */
+    memcpy (buffer, pn532_packetbuffer+8, 4);
+  }
+  else
+  {
+    #ifdef MIFAREDEBUG
+      SERIAL_PRINTln("Unexpected response reading block: ");
+      Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26);
+    #endif
+    return 0;
+  }
+
+  /* Display data for debug if requested */
+  #ifdef MIFAREDEBUG
+    SERIAL_PRINT("Page ");SERIAL_PRINT(page);SERIAL_PRINTln(":");
+    Adafruit_PN532::PrintHexChar(buffer, 4);
+  #endif
+
+  // Return OK signal
+  return 1;
+}
+
+
+
+/************** high level SPI */
+
+
+/**************************************************************************/
+/*! 
+    @brief  Tries to read the SPI ACK signal
+*/
+/**************************************************************************/
+bool Adafruit_PN532::spi_readack() {
+  uint8_t ackbuff[6];
+  
+  readspidata(ackbuff, 6);
+  
+  return (0 == strncmp((char *)ackbuff, (char *)pn532ack, 6));
+}
+
+/************** mid level SPI */
+
+/**************************************************************************/
+/*! 
+    @brief  Reads the SPI status register (to know if the PN532 is ready)
+*/
+/**************************************************************************/
+uint8_t Adafruit_PN532::readspistatus(void) {
+  _ss = 0;
+  delay(2);
+  spiwrite(PN532_SPI_STATREAD);
+  // read uint8_t
+  uint8_t x = spiread();
+  
+  _ss = 1;
+  return x;
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Reads n uint8_ts of data from the PN532 via SPI
+
+    @param  buff      Pointer to the buffer where data will be written
+    @param  n         Number of uint8_ts to be read
+*/
+/**************************************************************************/
+void Adafruit_PN532::readspidata(uint8_t* buff, uint8_t n) {
+  _ss = 0;
+  delay(2); 
+  spiwrite(PN532_SPI_DATAREAD);
+
+#ifdef PN532DEBUG
+  SERIAL_PRINT("Reading: ");
+#endif
+  for (uint8_t i=0; i<n; i++) {
+    delay(1);
+    buff[i] = spiread();
+#ifdef PN532DEBUG
+    SERIAL_PRINT(" 0x");
+    SERIAL_PRINT(buff[i], HEX);
+#endif
+  }
+
+#ifdef PN532DEBUG
+  SERIAL_PRINTln();
+#endif
+
+  _ss = 1;
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Writes a command to the PN532, automatically inserting the
+            preamble and required frame details (checksum, len, etc.)
+
+    @param  cmd       Pointer to the command buffer
+    @param  cmdlen    Command length in uint8_ts 
+*/
+/**************************************************************************/
+void Adafruit_PN532::spiwritecommand(uint8_t* cmd, uint8_t cmdlen) {
+  uint8_t checksum;
+
+  cmdlen++;
+  
+#ifdef PN532DEBUG
+  SERIAL_PRINT("\nSending: ");
+#endif
+
+  _ss = 0;
+  delay(2);     // or whatever the delay is for waking up the board
+  spiwrite(PN532_SPI_DATAWRITE);
+
+  checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2;
+  spiwrite(PN532_PREAMBLE);
+  spiwrite(PN532_PREAMBLE);
+  spiwrite(PN532_STARTCODE2);
+
+  spiwrite(cmdlen);
+  spiwrite(~cmdlen + 1);
+ 
+  spiwrite(PN532_HOSTTOPN532);
+  checksum += PN532_HOSTTOPN532;
+
+#ifdef PN532DEBUG
+  SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_PREAMBLE, HEX);
+  SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_PREAMBLE, HEX);
+  SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_STARTCODE2, HEX);
+  SERIAL_PRINT(" 0x"); SERIAL_PRINT(cmdlen, HEX);
+  SERIAL_PRINT(" 0x"); SERIAL_PRINT(~cmdlen + 1, HEX);
+  SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_HOSTTOPN532, HEX);
+#endif
+
+  for (uint8_t i=0; i<cmdlen-1; i++) {
+   spiwrite(cmd[i]);
+   checksum += cmd[i];
+#ifdef PN532DEBUG
+   SERIAL_PRINT(" 0x"); SERIAL_PRINT(cmd[i], HEX);
+#endif
+  }
+  
+  spiwrite(~checksum);
+  spiwrite(PN532_POSTAMBLE);
+  _ss = 1;
+
+#ifdef PN532DEBUG
+  SERIAL_PRINT(" 0x"); SERIAL_PRINT(~checksum, HEX);
+  SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_POSTAMBLE, HEX);
+  SERIAL_PRINTln();
+#endif
+} 
+/************** low level SPI */
+
+/**************************************************************************/
+/*! 
+    @brief  Low-level SPI write wrapper
+
+    @param  c       8-bit command to write to the SPI bus
+*/
+/**************************************************************************/
+void Adafruit_PN532::spiwrite(uint8_t c) {
+  int8_t i;
+  _clk = 1;
+  
+  for (i=0; i<8; i++) {
+    _clk = 0;
+    if (c & _BV(i)) {
+      _mosi = 1;
+    } else {
+      _mosi = 0;
+    }
+    _clk = 1;
+  }
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Low-level SPI read wrapper
+
+    @returns The 8-bit value that was read from the SPI bus
+*/
+/**************************************************************************/
+uint8_t Adafruit_PN532::spiread(void) {
+  int8_t i, x;
+  x = 0;
+  _clk = 1;
+
+  for (i=0; i<8; i++) {
+    if (_miso.read()) {
+      x |= _BV(i);
+    }
+    _clk = 0;
+    _clk = 1;
+  }
+  return x;
+}
\ No newline at end of file
diff -r 000000000000 -r 76b77ec0a86d PN532/Adafruit_PN532.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PN532/Adafruit_PN532.h	Mon Nov 17 01:09:06 2014 +0000
@@ -0,0 +1,191 @@
+/**************************************************************************/
+/*! 
+    @file     Adafruit_PN532.h
+    @author   Adafruit Industries
+    @license  BSD (see license.txt)
+    
+
+    This is a library for the Adafruit PN532 NFC/RFID breakout boards
+    This library works with the Adafruit NFC breakout 
+    ----> https://www.adafruit.com/products/364
+    
+    Check out the links above for our tutorials and wiring diagrams 
+    These chips use SPI to communicate, 4 required to interface
+    
+    Adafruit invests time and resources providing this open source code, 
+    please support Adafruit and open-source hardware by purchasing 
+    products from Adafruit!
+
+    @section  HISTORY
+
+    v1.1  - Added full command list
+          - Added 'verbose' mode flag to constructor to toggle debug output
+          - Changed readPassiveTargetID() to return variable length values
+    
+*/
+/**************************************************************************/
+
+#ifndef _PN532_ADAFRUIT_PN532_H_
+#define _PN532_ADAFRUIT_PN532_H_
+
+#include <stdint.h>
+
+#include "mbed.h"
+
+#define PN532_PREAMBLE                      (0x00)
+#define PN532_STARTCODE1                    (0x00)
+#define PN532_STARTCODE2                    (0xFF)
+#define PN532_POSTAMBLE                     (0x00)
+
+#define PN532_HOSTTOPN532                   (0xD4)
+
+// PN532 Commands
+#define PN532_COMMAND_DIAGNOSE              (0x00)
+#define PN532_COMMAND_GETFIRMWAREVERSION    (0x02)
+#define PN532_COMMAND_GETGENERALSTATUS      (0x04)
+#define PN532_COMMAND_READREGISTER          (0x06)
+#define PN532_COMMAND_WRITEREGISTER         (0x08)
+#define PN532_COMMAND_READGPIO              (0x0C)
+#define PN532_COMMAND_WRITEGPIO             (0x0E)
+#define PN532_COMMAND_SETSERIALBAUDRATE     (0x10)
+#define PN532_COMMAND_SETPARAMETERS         (0x12)
+#define PN532_COMMAND_SAMCONFIGURATION      (0x14)
+#define PN532_COMMAND_POWERDOWN             (0x16)
+#define PN532_COMMAND_RFCONFIGURATION       (0x32)
+#define PN532_COMMAND_RFREGULATIONTEST      (0x58)
+#define PN532_COMMAND_INJUMPFORDEP          (0x56)
+#define PN532_COMMAND_INJUMPFORPSL          (0x46)
+#define PN532_COMMAND_INLISTPASSIVETARGET   (0x4A)
+#define PN532_COMMAND_INATR                 (0x50)
+#define PN532_COMMAND_INPSL                 (0x4E)
+#define PN532_COMMAND_INDATAEXCHANGE        (0x40)
+#define PN532_COMMAND_INCOMMUNICATETHRU     (0x42)
+#define PN532_COMMAND_INDESELECT            (0x44)
+#define PN532_COMMAND_INRELEASE             (0x52)
+#define PN532_COMMAND_INSELECT              (0x54)
+#define PN532_COMMAND_INAUTOPOLL            (0x60)
+#define PN532_COMMAND_TGINITASTARGET        (0x8C)
+#define PN532_COMMAND_TGSETGENERALBYTES     (0x92)
+#define PN532_COMMAND_TGGETDATA             (0x86)
+#define PN532_COMMAND_TGSETDATA             (0x8E)
+#define PN532_COMMAND_TGSETMETADATA         (0x94)
+#define PN532_COMMAND_TGGETINITIATORCOMMAND (0x88)
+#define PN532_COMMAND_TGRESPONSETOINITIATOR (0x90)
+#define PN532_COMMAND_TGGETTARGETSTATUS     (0x8A)
+
+#define PN532_WAKEUP                        (0x55)
+
+#define PN532_SPI_STATREAD                  (0x02)
+#define PN532_SPI_DATAWRITE                 (0x01)
+#define PN532_SPI_DATAREAD                  (0x03)
+#define PN532_SPI_READY                     (0x01)
+
+#define PN532_MIFARE_ISO14443A              (0x00)
+
+// Mifare Commands
+#define MIFARE_CMD_AUTH_A                   (0x60)
+#define MIFARE_CMD_AUTH_B                   (0x61)
+#define MIFARE_CMD_READ                     (0x30)
+#define MIFARE_CMD_WRITE                    (0xA0)
+#define MIFARE_CMD_TRANSFER                 (0xB0)
+#define MIFARE_CMD_DECREMENT                (0xC0)
+#define MIFARE_CMD_INCREMENT                (0xC1)
+#define MIFARE_CMD_STORE                    (0xC2)
+
+// Prefixes for NDEF Records (to identify record type)
+#define NDEF_URIPREFIX_NONE                 (0x00)
+#define NDEF_URIPREFIX_HTTP_WWWDOT          (0x01)
+#define NDEF_URIPREFIX_HTTPS_WWWDOT         (0x02)
+#define NDEF_URIPREFIX_HTTP                 (0x03)
+#define NDEF_URIPREFIX_HTTPS                (0x04)
+#define NDEF_URIPREFIX_TEL                  (0x05)
+#define NDEF_URIPREFIX_MAILTO               (0x06)
+#define NDEF_URIPREFIX_FTP_ANONAT           (0x07)
+#define NDEF_URIPREFIX_FTP_FTPDOT           (0x08)
+#define NDEF_URIPREFIX_FTPS                 (0x09)
+#define NDEF_URIPREFIX_SFTP                 (0x0A)
+#define NDEF_URIPREFIX_SMB                  (0x0B)
+#define NDEF_URIPREFIX_NFS                  (0x0C)
+#define NDEF_URIPREFIX_FTP                  (0x0D)
+#define NDEF_URIPREFIX_DAV                  (0x0E)
+#define NDEF_URIPREFIX_NEWS                 (0x0F)
+#define NDEF_URIPREFIX_TELNET               (0x10)
+#define NDEF_URIPREFIX_IMAP                 (0x11)
+#define NDEF_URIPREFIX_RTSP                 (0x12)
+#define NDEF_URIPREFIX_URN                  (0x13)
+#define NDEF_URIPREFIX_POP                  (0x14)
+#define NDEF_URIPREFIX_SIP                  (0x15)
+#define NDEF_URIPREFIX_SIPS                 (0x16)
+#define NDEF_URIPREFIX_TFTP                 (0x17)
+#define NDEF_URIPREFIX_BTSPP                (0x18)
+#define NDEF_URIPREFIX_BTL2CAP              (0x19)
+#define NDEF_URIPREFIX_BTGOEP               (0x1A)
+#define NDEF_URIPREFIX_TCPOBEX              (0x1B)
+#define NDEF_URIPREFIX_IRDAOBEX             (0x1C)
+#define NDEF_URIPREFIX_FILE                 (0x1D)
+#define NDEF_URIPREFIX_URN_EPC_ID           (0x1E)
+#define NDEF_URIPREFIX_URN_EPC_TAG          (0x1F)
+#define NDEF_URIPREFIX_URN_EPC_PAT          (0x20)
+#define NDEF_URIPREFIX_URN_EPC_RAW          (0x21)
+#define NDEF_URIPREFIX_URN_EPC              (0x22)
+#define NDEF_URIPREFIX_URN_NFC              (0x23)
+
+#define PN532_GPIO_VALIDATIONBIT            (0x80)
+#define PN532_GPIO_P30                      (0)
+#define PN532_GPIO_P31                      (1)
+#define PN532_GPIO_P32                      (2)
+#define PN532_GPIO_P33                      (3)
+#define PN532_GPIO_P34                      (4)
+#define PN532_GPIO_P35                      (5)
+
+class Adafruit_PN532{
+ public:
+  Adafruit_PN532(DigitalOut clk, DigitalIn miso, DigitalOut mosi, DigitalOut ss);
+  Adafruit_PN532(PinName clk_pin, PinName miso_pin, PinName mosi_pin, PinName ss_pin);
+  
+  void begin(void);
+  
+  // Generic PN532 functions
+  bool SAMConfig(void);
+  uint32_t getFirmwareVersion(void);
+  bool sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout = 1000);  
+  bool writeGPIO(uint8_t pinstate);
+  uint8_t readGPIO(void);
+  bool setPassiveActivationRetries(uint8_t maxRetries);
+  
+  // ISO14443A functions
+  bool readPassiveTargetID(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength);
+  
+  // Mifare Classic functions
+  bool mifareclassic_IsFirstBlock (uint32_t uiBlock);
+  bool mifareclassic_IsTrailerBlock (uint32_t uiBlock);
+  uint8_t mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData);
+  uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data);
+  uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data);
+  uint8_t mifareclassic_FormatNDEF (void);
+  uint8_t mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char * url);
+  
+  // Mifare Ultralight functions
+  uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t * buffer);
+  
+  // Help functions to display formatted text
+  static void PrintHex(const uint8_t * data, const uint32_t numBytes);
+  static void PrintHexChar(const uint8_t * pbtData, const uint32_t numBytes);
+
+ private:
+  DigitalOut _clk;
+  DigitalIn _miso;
+  DigitalOut _mosi, _ss;
+  uint8_t _uid[7];  // ISO14443A uid
+  uint8_t _uidLen;  // uid len
+  uint8_t _key[6];  // Mifare Classic key
+
+  bool spi_readack();
+  uint8_t readspistatus(void);
+  void readspidata(uint8_t* buff, uint8_t n);
+  void spiwritecommand(uint8_t* cmd, uint8_t cmdlen);
+  void spiwrite(uint8_t c);
+  uint8_t spiread(void);
+};
+
+#endif  // _PN532_ADAFRUIT_PN532_H_
\ No newline at end of file
diff -r 000000000000 -r 76b77ec0a86d main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Nov 17 01:09:06 2014 +0000
@@ -0,0 +1,54 @@
+#include "mbed.h"
+#include "Adafruit_PN532.h"
+
+#define SS   PTD0
+// PTD1 is also LED_BLUE, it will blink during SPI communication.
+#define SCK  PTD1
+#define MOSI PTD2
+#define MISO PTD3
+
+Serial id(PTA2, PTA1);
+int previous = 0;
+
+Adafruit_PN532 nfc(SCK, MISO, MOSI, SS);
+
+void loop(void);
+
+int main() {
+  id.baud(9600);
+  nfc.begin();
+
+  uint32_t versiondata = nfc.getFirmwareVersion();
+  if (! versiondata) {
+    while (1); // halt
+  }
+
+  nfc.SAMConfig();
+  
+  while(1) { loop(); }
+}
+
+
+void loop(void) {
+  uint8_t success;
+  uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  
+  uint8_t uidLength;                        
+  
+  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
+  
+  if (success) {
+    previous = 1;
+
+    if (uidLength == 4)
+    {
+        uint8_t tag_1 = 250;
+        uint8_t tag_2 = 186;
+        uint8_t tag_3 = 106;
+        uint8_t tag_4 = 10;
+        id.printf("%d", uid[0]);
+    }
+  } else if (previous == 0){
+     } else {
+     previous = 0; 
+    }
+}
\ No newline at end of file
diff -r 000000000000 -r 76b77ec0a86d mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Nov 17 01:09:06 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/552587b429a1
\ No newline at end of file