The mbed code for our second prototype

Dependencies:   mbed

Committer:
smcqueen
Date:
Mon Nov 17 01:09:06 2014 +0000
Revision:
0:76b77ec0a86d
Final code for prototype 2

Who changed what in which revision?

UserRevisionLine numberNew contents of line
smcqueen 0:76b77ec0a86d 1 /**************************************************************************/
smcqueen 0:76b77ec0a86d 2 /*!
smcqueen 0:76b77ec0a86d 3 @file Adafruit_PN532.cpp
smcqueen 0:76b77ec0a86d 4 @author Adafruit Industries
smcqueen 0:76b77ec0a86d 5 @license BSD (see license.txt)
smcqueen 0:76b77ec0a86d 6
smcqueen 0:76b77ec0a86d 7 SPI Driver for NXP's PN532 NFC/13.56MHz RFID Transceiver
smcqueen 0:76b77ec0a86d 8
smcqueen 0:76b77ec0a86d 9 This is a library for the Adafruit PN532 NFC/RFID breakout boards
smcqueen 0:76b77ec0a86d 10 This library works with the Adafruit NFC breakout
smcqueen 0:76b77ec0a86d 11 ----> https://www.adafruit.com/products/364
smcqueen 0:76b77ec0a86d 12
smcqueen 0:76b77ec0a86d 13 Check out the links above for our tutorials and wiring diagrams
smcqueen 0:76b77ec0a86d 14 These chips use SPI to communicate, 4 required to interface
smcqueen 0:76b77ec0a86d 15
smcqueen 0:76b77ec0a86d 16 Adafruit invests time and resources providing this open source code,
smcqueen 0:76b77ec0a86d 17 please support Adafruit and open-source hardware by purchasing
smcqueen 0:76b77ec0a86d 18 products from Adafruit!
smcqueen 0:76b77ec0a86d 19
smcqueen 0:76b77ec0a86d 20
smcqueen 0:76b77ec0a86d 21 @section HISTORY
smcqueen 0:76b77ec0a86d 22
smcqueen 0:76b77ec0a86d 23 v1.4 - Added setPassiveActivationRetries()
smcqueen 0:76b77ec0a86d 24
smcqueen 0:76b77ec0a86d 25 v1.2 - Added writeGPIO()
smcqueen 0:76b77ec0a86d 26 - Added readGPIO()
smcqueen 0:76b77ec0a86d 27
smcqueen 0:76b77ec0a86d 28 v1.1 - Changed readPassiveTargetID() to handle multiple UID sizes
smcqueen 0:76b77ec0a86d 29 - Added the following helper functions for text display
smcqueen 0:76b77ec0a86d 30 static void PrintHex(const uint8_t * data, const uint32_t numuint8_ts)
smcqueen 0:76b77ec0a86d 31 static void PrintHexChar(const uint8_t * pbtData, const uint32_t numuint8_ts)
smcqueen 0:76b77ec0a86d 32 - Added the following Mifare Classic functions:
smcqueen 0:76b77ec0a86d 33 bool mifareclassic_IsFirstBlock (uint32_t uiBlock)
smcqueen 0:76b77ec0a86d 34 bool mifareclassic_IsTrailerBlock (uint32_t uiBlock)
smcqueen 0:76b77ec0a86d 35 uint8_t mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData)
smcqueen 0:76b77ec0a86d 36 uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data)
smcqueen 0:76b77ec0a86d 37 uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data)
smcqueen 0:76b77ec0a86d 38 - Added the following Mifare Ultalight functions:
smcqueen 0:76b77ec0a86d 39 uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t * buffer)
smcqueen 0:76b77ec0a86d 40 */
smcqueen 0:76b77ec0a86d 41 /**************************************************************************/
smcqueen 0:76b77ec0a86d 42
smcqueen 0:76b77ec0a86d 43 #include "Adafruit_PN532.h"
smcqueen 0:76b77ec0a86d 44
smcqueen 0:76b77ec0a86d 45 uint8_t pn532ack[] = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00};
smcqueen 0:76b77ec0a86d 46 uint8_t pn532response_firmwarevers[] = {0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03};
smcqueen 0:76b77ec0a86d 47
smcqueen 0:76b77ec0a86d 48 // Uncomment these lines to enable debug output for PN532(SPI) and/or MIFARE related code
smcqueen 0:76b77ec0a86d 49 // #define PN532DEBUG
smcqueen 0:76b77ec0a86d 50 // #define MIFAREDEBUG
smcqueen 0:76b77ec0a86d 51
smcqueen 0:76b77ec0a86d 52 Serial serial(USBTX, USBRX);
smcqueen 0:76b77ec0a86d 53 #define SERIAL_PRINT serial.printf
smcqueen 0:76b77ec0a86d 54
smcqueen 0:76b77ec0a86d 55 #define _BV(bit) (1 << (bit))
smcqueen 0:76b77ec0a86d 56 #define PN532_PACKBUFFSIZ 64
smcqueen 0:76b77ec0a86d 57 uint8_t pn532_packetbuffer[PN532_PACKBUFFSIZ];
smcqueen 0:76b77ec0a86d 58
smcqueen 0:76b77ec0a86d 59 void delay(int delayInMS) {
smcqueen 0:76b77ec0a86d 60 wait(1.0 * delayInMS / 1000);
smcqueen 0:76b77ec0a86d 61 }
smcqueen 0:76b77ec0a86d 62
smcqueen 0:76b77ec0a86d 63 /**************************************************************************/
smcqueen 0:76b77ec0a86d 64 /*!
smcqueen 0:76b77ec0a86d 65 @brief Instantiates a new PN532 class
smcqueen 0:76b77ec0a86d 66
smcqueen 0:76b77ec0a86d 67 @param clk SPI clock pin (SCK)
smcqueen 0:76b77ec0a86d 68 @param miso SPI MISO pin
smcqueen 0:76b77ec0a86d 69 @param mosi SPI MOSI pin
smcqueen 0:76b77ec0a86d 70 @param ss SPI chip select pin (CS/SSEL)
smcqueen 0:76b77ec0a86d 71 */
smcqueen 0:76b77ec0a86d 72 /**************************************************************************/
smcqueen 0:76b77ec0a86d 73 Adafruit_PN532::Adafruit_PN532(DigitalOut clk, DigitalIn miso,
smcqueen 0:76b77ec0a86d 74 DigitalOut mosi, DigitalOut ss)
smcqueen 0:76b77ec0a86d 75 : _clk(clk), _miso(miso), _mosi(mosi), _ss(ss) {}
smcqueen 0:76b77ec0a86d 76
smcqueen 0:76b77ec0a86d 77 Adafruit_PN532::Adafruit_PN532(PinName clk_pin, PinName miso_pin,
smcqueen 0:76b77ec0a86d 78 PinName mosi_pin, PinName ss_pin)
smcqueen 0:76b77ec0a86d 79 : _clk(DigitalOut(clk_pin)), _miso(DigitalIn(miso_pin)),
smcqueen 0:76b77ec0a86d 80 _mosi(DigitalOut(mosi_pin)), _ss(DigitalOut(ss_pin)) {}
smcqueen 0:76b77ec0a86d 81
smcqueen 0:76b77ec0a86d 82 /**************************************************************************/
smcqueen 0:76b77ec0a86d 83 /*!
smcqueen 0:76b77ec0a86d 84 @brief Setups the HW
smcqueen 0:76b77ec0a86d 85 */
smcqueen 0:76b77ec0a86d 86 /**************************************************************************/
smcqueen 0:76b77ec0a86d 87 void Adafruit_PN532::begin() {
smcqueen 0:76b77ec0a86d 88 _ss = 0;
smcqueen 0:76b77ec0a86d 89 delay(1000);
smcqueen 0:76b77ec0a86d 90
smcqueen 0:76b77ec0a86d 91 // not exactly sure why but we have to send a dummy command to get synced up
smcqueen 0:76b77ec0a86d 92 pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
smcqueen 0:76b77ec0a86d 93 sendCommandCheckAck(pn532_packetbuffer, 1);
smcqueen 0:76b77ec0a86d 94
smcqueen 0:76b77ec0a86d 95 // ignore response!
smcqueen 0:76b77ec0a86d 96 }
smcqueen 0:76b77ec0a86d 97
smcqueen 0:76b77ec0a86d 98 /**************************************************************************/
smcqueen 0:76b77ec0a86d 99 /*!
smcqueen 0:76b77ec0a86d 100 @brief Prints a hexadecimal value in plain characters
smcqueen 0:76b77ec0a86d 101
smcqueen 0:76b77ec0a86d 102 @param data Pointer to the uint8_t data
smcqueen 0:76b77ec0a86d 103 @param numuint8_ts Data length in uint8_ts
smcqueen 0:76b77ec0a86d 104 */
smcqueen 0:76b77ec0a86d 105 /**************************************************************************/
smcqueen 0:76b77ec0a86d 106 void Adafruit_PN532::PrintHex(const uint8_t * data, const uint32_t numuint8_ts)
smcqueen 0:76b77ec0a86d 107 {
smcqueen 0:76b77ec0a86d 108 uint32_t szPos;
smcqueen 0:76b77ec0a86d 109 for (szPos=0; szPos < numuint8_ts; szPos++)
smcqueen 0:76b77ec0a86d 110 {
smcqueen 0:76b77ec0a86d 111 SERIAL_PRINT("0x");
smcqueen 0:76b77ec0a86d 112 // Append leading 0 for small values
smcqueen 0:76b77ec0a86d 113 if (data[szPos] <= 0xF)
smcqueen 0:76b77ec0a86d 114 SERIAL_PRINT("0");
smcqueen 0:76b77ec0a86d 115 SERIAL_PRINT("%d", data[szPos]);
smcqueen 0:76b77ec0a86d 116 if ((numuint8_ts > 1) && (szPos != numuint8_ts - 1))
smcqueen 0:76b77ec0a86d 117 {
smcqueen 0:76b77ec0a86d 118 SERIAL_PRINT(" ");
smcqueen 0:76b77ec0a86d 119 }
smcqueen 0:76b77ec0a86d 120 }
smcqueen 0:76b77ec0a86d 121 SERIAL_PRINT("\n");
smcqueen 0:76b77ec0a86d 122 }
smcqueen 0:76b77ec0a86d 123
smcqueen 0:76b77ec0a86d 124 /**************************************************************************/
smcqueen 0:76b77ec0a86d 125 /*!
smcqueen 0:76b77ec0a86d 126 @brief Prints a hexadecimal value in plain characters, along with
smcqueen 0:76b77ec0a86d 127 the char equivalents in the following format
smcqueen 0:76b77ec0a86d 128
smcqueen 0:76b77ec0a86d 129 00 00 00 00 00 00 ......
smcqueen 0:76b77ec0a86d 130
smcqueen 0:76b77ec0a86d 131 @param data Pointer to the uint8_t data
smcqueen 0:76b77ec0a86d 132 @param numuint8_ts Data length in uint8_ts
smcqueen 0:76b77ec0a86d 133 */
smcqueen 0:76b77ec0a86d 134 /**************************************************************************/
smcqueen 0:76b77ec0a86d 135 void Adafruit_PN532::PrintHexChar(const uint8_t * data, const uint32_t numuint8_ts)
smcqueen 0:76b77ec0a86d 136 {
smcqueen 0:76b77ec0a86d 137 uint32_t szPos;
smcqueen 0:76b77ec0a86d 138 for (szPos=0; szPos < numuint8_ts; szPos++)
smcqueen 0:76b77ec0a86d 139 {
smcqueen 0:76b77ec0a86d 140 // Append leading 0 for small values
smcqueen 0:76b77ec0a86d 141 if (data[szPos] <= 0xF)
smcqueen 0:76b77ec0a86d 142 SERIAL_PRINT("0");
smcqueen 0:76b77ec0a86d 143 SERIAL_PRINT("%x", data[szPos]);
smcqueen 0:76b77ec0a86d 144 if ((numuint8_ts > 1) && (szPos != numuint8_ts - 1))
smcqueen 0:76b77ec0a86d 145 {
smcqueen 0:76b77ec0a86d 146 SERIAL_PRINT(" ");
smcqueen 0:76b77ec0a86d 147 }
smcqueen 0:76b77ec0a86d 148 }
smcqueen 0:76b77ec0a86d 149 SERIAL_PRINT(" ");
smcqueen 0:76b77ec0a86d 150 for (szPos=0; szPos < numuint8_ts; szPos++)
smcqueen 0:76b77ec0a86d 151 {
smcqueen 0:76b77ec0a86d 152 if (data[szPos] <= 0x1F)
smcqueen 0:76b77ec0a86d 153 SERIAL_PRINT(".");
smcqueen 0:76b77ec0a86d 154 else
smcqueen 0:76b77ec0a86d 155 SERIAL_PRINT("%c", data[szPos]);
smcqueen 0:76b77ec0a86d 156 }
smcqueen 0:76b77ec0a86d 157 SERIAL_PRINT("");
smcqueen 0:76b77ec0a86d 158 }
smcqueen 0:76b77ec0a86d 159
smcqueen 0:76b77ec0a86d 160 /**************************************************************************/
smcqueen 0:76b77ec0a86d 161 /*!
smcqueen 0:76b77ec0a86d 162 @brief Checks the firmware version of the PN5xx chip
smcqueen 0:76b77ec0a86d 163
smcqueen 0:76b77ec0a86d 164 @returns The chip's firmware version and ID
smcqueen 0:76b77ec0a86d 165 */
smcqueen 0:76b77ec0a86d 166 /**************************************************************************/
smcqueen 0:76b77ec0a86d 167 uint32_t Adafruit_PN532::getFirmwareVersion(void) {
smcqueen 0:76b77ec0a86d 168 uint32_t response;
smcqueen 0:76b77ec0a86d 169
smcqueen 0:76b77ec0a86d 170 pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
smcqueen 0:76b77ec0a86d 171
smcqueen 0:76b77ec0a86d 172 if (! sendCommandCheckAck(pn532_packetbuffer, 1))
smcqueen 0:76b77ec0a86d 173 return 0;
smcqueen 0:76b77ec0a86d 174
smcqueen 0:76b77ec0a86d 175 // read data packet
smcqueen 0:76b77ec0a86d 176 readspidata(pn532_packetbuffer, 12);
smcqueen 0:76b77ec0a86d 177
smcqueen 0:76b77ec0a86d 178 // check some basic stuff
smcqueen 0:76b77ec0a86d 179 if (0 != strncmp((char *)pn532_packetbuffer, (char *)pn532response_firmwarevers, 6)) {
smcqueen 0:76b77ec0a86d 180 return 0;
smcqueen 0:76b77ec0a86d 181 }
smcqueen 0:76b77ec0a86d 182
smcqueen 0:76b77ec0a86d 183 response = pn532_packetbuffer[6];
smcqueen 0:76b77ec0a86d 184 response <<= 8;
smcqueen 0:76b77ec0a86d 185 response |= pn532_packetbuffer[7];
smcqueen 0:76b77ec0a86d 186 response <<= 8;
smcqueen 0:76b77ec0a86d 187 response |= pn532_packetbuffer[8];
smcqueen 0:76b77ec0a86d 188 response <<= 8;
smcqueen 0:76b77ec0a86d 189 response |= pn532_packetbuffer[9];
smcqueen 0:76b77ec0a86d 190
smcqueen 0:76b77ec0a86d 191 return response;
smcqueen 0:76b77ec0a86d 192 }
smcqueen 0:76b77ec0a86d 193
smcqueen 0:76b77ec0a86d 194
smcqueen 0:76b77ec0a86d 195 /**************************************************************************/
smcqueen 0:76b77ec0a86d 196 /*!
smcqueen 0:76b77ec0a86d 197 @brief Sends a command and waits a specified period for the ACK
smcqueen 0:76b77ec0a86d 198
smcqueen 0:76b77ec0a86d 199 @param cmd Pointer to the command buffer
smcqueen 0:76b77ec0a86d 200 @param cmdlen The size of the command in uint8_ts
smcqueen 0:76b77ec0a86d 201 @param timeout timeout before giving up
smcqueen 0:76b77ec0a86d 202
smcqueen 0:76b77ec0a86d 203 @returns 1 if everything is OK, 0 if timeout occured before an
smcqueen 0:76b77ec0a86d 204 ACK was recieved
smcqueen 0:76b77ec0a86d 205 */
smcqueen 0:76b77ec0a86d 206 /**************************************************************************/
smcqueen 0:76b77ec0a86d 207 // default timeout of one second
smcqueen 0:76b77ec0a86d 208 bool Adafruit_PN532::sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout) {
smcqueen 0:76b77ec0a86d 209 uint16_t timer = 0;
smcqueen 0:76b77ec0a86d 210
smcqueen 0:76b77ec0a86d 211 // write the command
smcqueen 0:76b77ec0a86d 212 spiwritecommand(cmd, cmdlen);
smcqueen 0:76b77ec0a86d 213
smcqueen 0:76b77ec0a86d 214 // Wait for chip to say its ready!
smcqueen 0:76b77ec0a86d 215 while (readspistatus() != PN532_SPI_READY) {
smcqueen 0:76b77ec0a86d 216 if (timeout != 0) {
smcqueen 0:76b77ec0a86d 217 timer+=10;
smcqueen 0:76b77ec0a86d 218 if (timer > timeout)
smcqueen 0:76b77ec0a86d 219 return false;
smcqueen 0:76b77ec0a86d 220 }
smcqueen 0:76b77ec0a86d 221 delay(10);
smcqueen 0:76b77ec0a86d 222 }
smcqueen 0:76b77ec0a86d 223
smcqueen 0:76b77ec0a86d 224 // read acknowledgement
smcqueen 0:76b77ec0a86d 225 if (!spi_readack()) {
smcqueen 0:76b77ec0a86d 226 return false;
smcqueen 0:76b77ec0a86d 227 }
smcqueen 0:76b77ec0a86d 228
smcqueen 0:76b77ec0a86d 229 timer = 0;
smcqueen 0:76b77ec0a86d 230 // Wait for chip to say its ready!
smcqueen 0:76b77ec0a86d 231 while (readspistatus() != PN532_SPI_READY) {
smcqueen 0:76b77ec0a86d 232 if (timeout != 0) {
smcqueen 0:76b77ec0a86d 233 timer+=10;
smcqueen 0:76b77ec0a86d 234 if (timer > timeout)
smcqueen 0:76b77ec0a86d 235 return false;
smcqueen 0:76b77ec0a86d 236 }
smcqueen 0:76b77ec0a86d 237 delay(10);
smcqueen 0:76b77ec0a86d 238 }
smcqueen 0:76b77ec0a86d 239
smcqueen 0:76b77ec0a86d 240 return true; // ack'd command
smcqueen 0:76b77ec0a86d 241 }
smcqueen 0:76b77ec0a86d 242
smcqueen 0:76b77ec0a86d 243 /**************************************************************************/
smcqueen 0:76b77ec0a86d 244 /*!
smcqueen 0:76b77ec0a86d 245 Writes an 8-bit value that sets the state of the PN532's GPIO pins
smcqueen 0:76b77ec0a86d 246
smcqueen 0:76b77ec0a86d 247 @warning This function is provided exclusively for board testing and
smcqueen 0:76b77ec0a86d 248 is dangerous since it will throw an error if any pin other
smcqueen 0:76b77ec0a86d 249 than the ones marked "Can be used as GPIO" are modified! All
smcqueen 0:76b77ec0a86d 250 pins that can not be used as GPIO should ALWAYS be left high
smcqueen 0:76b77ec0a86d 251 (value = 1) or the system will become unstable and a HW reset
smcqueen 0:76b77ec0a86d 252 will be required to recover the PN532.
smcqueen 0:76b77ec0a86d 253
smcqueen 0:76b77ec0a86d 254 pinState[0] = P30 Can be used as GPIO
smcqueen 0:76b77ec0a86d 255 pinState[1] = P31 Can be used as GPIO
smcqueen 0:76b77ec0a86d 256 pinState[2] = P32 *** RESERVED (Must be 1!) ***
smcqueen 0:76b77ec0a86d 257 pinState[3] = P33 Can be used as GPIO
smcqueen 0:76b77ec0a86d 258 pinState[4] = P34 *** RESERVED (Must be 1!) ***
smcqueen 0:76b77ec0a86d 259 pinState[5] = P35 Can be used as GPIO
smcqueen 0:76b77ec0a86d 260
smcqueen 0:76b77ec0a86d 261 @returns 1 if everything executed properly, 0 for an error
smcqueen 0:76b77ec0a86d 262 */
smcqueen 0:76b77ec0a86d 263 /**************************************************************************/
smcqueen 0:76b77ec0a86d 264 bool Adafruit_PN532::writeGPIO(uint8_t pinstate) {
smcqueen 0:76b77ec0a86d 265 // Make sure pinstate does not try to toggle P32 or P34
smcqueen 0:76b77ec0a86d 266 pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34);
smcqueen 0:76b77ec0a86d 267
smcqueen 0:76b77ec0a86d 268 // Fill command buffer
smcqueen 0:76b77ec0a86d 269 pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO;
smcqueen 0:76b77ec0a86d 270 pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate; // P3 Pins
smcqueen 0:76b77ec0a86d 271 pn532_packetbuffer[2] = 0x00; // P7 GPIO Pins (not used ... taken by SPI)
smcqueen 0:76b77ec0a86d 272
smcqueen 0:76b77ec0a86d 273 #ifdef PN532DEBUG
smcqueen 0:76b77ec0a86d 274 SERIAL_PRINT("Writing P3 GPIO: "); SERIAL_PRINTln(pn532_packetbuffer[1], HEX);
smcqueen 0:76b77ec0a86d 275 #endif
smcqueen 0:76b77ec0a86d 276
smcqueen 0:76b77ec0a86d 277 // Send the WRITEGPIO command (0x0E)
smcqueen 0:76b77ec0a86d 278 if (! sendCommandCheckAck(pn532_packetbuffer, 3))
smcqueen 0:76b77ec0a86d 279 return 0x0;
smcqueen 0:76b77ec0a86d 280
smcqueen 0:76b77ec0a86d 281 // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0F) DATACHECKSUM 00)
smcqueen 0:76b77ec0a86d 282 readspidata(pn532_packetbuffer, 8);
smcqueen 0:76b77ec0a86d 283
smcqueen 0:76b77ec0a86d 284 #ifdef PN532DEBUG
smcqueen 0:76b77ec0a86d 285 SERIAL_PRINT("Received: ");
smcqueen 0:76b77ec0a86d 286 PrintHex(pn532_packetbuffer, 8);
smcqueen 0:76b77ec0a86d 287 SERIAL_PRINTln("");
smcqueen 0:76b77ec0a86d 288 #endif
smcqueen 0:76b77ec0a86d 289
smcqueen 0:76b77ec0a86d 290 return (pn532_packetbuffer[5] == 0x0F);
smcqueen 0:76b77ec0a86d 291 }
smcqueen 0:76b77ec0a86d 292
smcqueen 0:76b77ec0a86d 293 /**************************************************************************/
smcqueen 0:76b77ec0a86d 294 /*!
smcqueen 0:76b77ec0a86d 295 Reads the state of the PN532's GPIO pins
smcqueen 0:76b77ec0a86d 296
smcqueen 0:76b77ec0a86d 297 @returns An 8-bit value containing the pin state where:
smcqueen 0:76b77ec0a86d 298
smcqueen 0:76b77ec0a86d 299 pinState[0] = P30
smcqueen 0:76b77ec0a86d 300 pinState[1] = P31
smcqueen 0:76b77ec0a86d 301 pinState[2] = P32
smcqueen 0:76b77ec0a86d 302 pinState[3] = P33
smcqueen 0:76b77ec0a86d 303 pinState[4] = P34
smcqueen 0:76b77ec0a86d 304 pinState[5] = P35
smcqueen 0:76b77ec0a86d 305 */
smcqueen 0:76b77ec0a86d 306 /**************************************************************************/
smcqueen 0:76b77ec0a86d 307 uint8_t Adafruit_PN532::readGPIO(void) {
smcqueen 0:76b77ec0a86d 308 pn532_packetbuffer[0] = PN532_COMMAND_READGPIO;
smcqueen 0:76b77ec0a86d 309
smcqueen 0:76b77ec0a86d 310 // Send the READGPIO command (0x0C)
smcqueen 0:76b77ec0a86d 311 if (! sendCommandCheckAck(pn532_packetbuffer, 1))
smcqueen 0:76b77ec0a86d 312 return 0x0;
smcqueen 0:76b77ec0a86d 313
smcqueen 0:76b77ec0a86d 314 // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0D) P3 P7 IO1 DATACHECKSUM 00)
smcqueen 0:76b77ec0a86d 315 readspidata(pn532_packetbuffer, 11);
smcqueen 0:76b77ec0a86d 316
smcqueen 0:76b77ec0a86d 317 /* READGPIO response should be in the following format:
smcqueen 0:76b77ec0a86d 318
smcqueen 0:76b77ec0a86d 319 uint8_t Description
smcqueen 0:76b77ec0a86d 320 ------------- ------------------------------------------
smcqueen 0:76b77ec0a86d 321 b0..5 Frame header and preamble
smcqueen 0:76b77ec0a86d 322 b6 P3 GPIO Pins
smcqueen 0:76b77ec0a86d 323 b7 P7 GPIO Pins (not used ... taken by SPI)
smcqueen 0:76b77ec0a86d 324 b8 Interface Mode Pins (not used ... bus select pins)
smcqueen 0:76b77ec0a86d 325 b9..10 checksum */
smcqueen 0:76b77ec0a86d 326
smcqueen 0:76b77ec0a86d 327 #ifdef PN532DEBUG
smcqueen 0:76b77ec0a86d 328 SERIAL_PRINT("Received: ");
smcqueen 0:76b77ec0a86d 329 PrintHex(pn532_packetbuffer, 11);
smcqueen 0:76b77ec0a86d 330 SERIAL_PRINTln("");
smcqueen 0:76b77ec0a86d 331 SERIAL_PRINT("P3 GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[6], HEX);
smcqueen 0:76b77ec0a86d 332 SERIAL_PRINT("P7 GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[7], HEX);
smcqueen 0:76b77ec0a86d 333 SERIAL_PRINT("IO GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[8], HEX);
smcqueen 0:76b77ec0a86d 334 // Note: You can use the IO GPIO value to detect the serial bus being used
smcqueen 0:76b77ec0a86d 335 switch(pn532_packetbuffer[8])
smcqueen 0:76b77ec0a86d 336 {
smcqueen 0:76b77ec0a86d 337 case 0x00: // Using UART
smcqueen 0:76b77ec0a86d 338 SERIAL_PRINTln("Using UART (IO = 0x00)");
smcqueen 0:76b77ec0a86d 339 break;
smcqueen 0:76b77ec0a86d 340 case 0x01: // Using I2C
smcqueen 0:76b77ec0a86d 341 SERIAL_PRINTln("Using I2C (IO = 0x01)");
smcqueen 0:76b77ec0a86d 342 break;
smcqueen 0:76b77ec0a86d 343 case 0x02: // Using SPI
smcqueen 0:76b77ec0a86d 344 SERIAL_PRINTln("Using SPI (IO = 0x02)");
smcqueen 0:76b77ec0a86d 345 break;
smcqueen 0:76b77ec0a86d 346 }
smcqueen 0:76b77ec0a86d 347 #endif
smcqueen 0:76b77ec0a86d 348
smcqueen 0:76b77ec0a86d 349 return pn532_packetbuffer[6];
smcqueen 0:76b77ec0a86d 350 }
smcqueen 0:76b77ec0a86d 351
smcqueen 0:76b77ec0a86d 352 /**************************************************************************/
smcqueen 0:76b77ec0a86d 353 /*!
smcqueen 0:76b77ec0a86d 354 @brief Configures the SAM (Secure Access Module)
smcqueen 0:76b77ec0a86d 355 */
smcqueen 0:76b77ec0a86d 356 /**************************************************************************/
smcqueen 0:76b77ec0a86d 357 bool Adafruit_PN532::SAMConfig(void) {
smcqueen 0:76b77ec0a86d 358 pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
smcqueen 0:76b77ec0a86d 359 pn532_packetbuffer[1] = 0x01; // normal mode;
smcqueen 0:76b77ec0a86d 360 pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
smcqueen 0:76b77ec0a86d 361 pn532_packetbuffer[3] = 0x01; // use IRQ pin!
smcqueen 0:76b77ec0a86d 362
smcqueen 0:76b77ec0a86d 363 if (! sendCommandCheckAck(pn532_packetbuffer, 4))
smcqueen 0:76b77ec0a86d 364 return false;
smcqueen 0:76b77ec0a86d 365
smcqueen 0:76b77ec0a86d 366 // read data packet
smcqueen 0:76b77ec0a86d 367 readspidata(pn532_packetbuffer, 8);
smcqueen 0:76b77ec0a86d 368
smcqueen 0:76b77ec0a86d 369 return (pn532_packetbuffer[5] == 0x15);
smcqueen 0:76b77ec0a86d 370 }
smcqueen 0:76b77ec0a86d 371
smcqueen 0:76b77ec0a86d 372 /**************************************************************************/
smcqueen 0:76b77ec0a86d 373 /*!
smcqueen 0:76b77ec0a86d 374 Sets the MxRtyPassiveActivation uint8_t of the RFConfiguration register
smcqueen 0:76b77ec0a86d 375
smcqueen 0:76b77ec0a86d 376 @param maxRetries 0xFF to wait forever, 0x00..0xFE to timeout
smcqueen 0:76b77ec0a86d 377 after mxRetries
smcqueen 0:76b77ec0a86d 378
smcqueen 0:76b77ec0a86d 379 @returns 1 if everything executed properly, 0 for an error
smcqueen 0:76b77ec0a86d 380 */
smcqueen 0:76b77ec0a86d 381 /**************************************************************************/
smcqueen 0:76b77ec0a86d 382 bool Adafruit_PN532::setPassiveActivationRetries(uint8_t maxRetries) {
smcqueen 0:76b77ec0a86d 383 pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION;
smcqueen 0:76b77ec0a86d 384 pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries)
smcqueen 0:76b77ec0a86d 385 pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF)
smcqueen 0:76b77ec0a86d 386 pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01)
smcqueen 0:76b77ec0a86d 387 pn532_packetbuffer[4] = maxRetries;
smcqueen 0:76b77ec0a86d 388
smcqueen 0:76b77ec0a86d 389 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 390 SERIAL_PRINT("Setting MxRtyPassiveActivation to "); SERIAL_PRINT(maxRetries, DEC); SERIAL_PRINTln(" ");
smcqueen 0:76b77ec0a86d 391 #endif
smcqueen 0:76b77ec0a86d 392
smcqueen 0:76b77ec0a86d 393 if (! sendCommandCheckAck(pn532_packetbuffer, 5))
smcqueen 0:76b77ec0a86d 394 return 0x0; // no ACK
smcqueen 0:76b77ec0a86d 395
smcqueen 0:76b77ec0a86d 396 return 1;
smcqueen 0:76b77ec0a86d 397 }
smcqueen 0:76b77ec0a86d 398
smcqueen 0:76b77ec0a86d 399 /***** ISO14443A Commands ******/
smcqueen 0:76b77ec0a86d 400
smcqueen 0:76b77ec0a86d 401 /**************************************************************************/
smcqueen 0:76b77ec0a86d 402 /*!
smcqueen 0:76b77ec0a86d 403 Waits for an ISO14443A target to enter the field
smcqueen 0:76b77ec0a86d 404
smcqueen 0:76b77ec0a86d 405 @param cardBaudRate Baud rate of the card
smcqueen 0:76b77ec0a86d 406 @param uid Pointer to the array that will be populated
smcqueen 0:76b77ec0a86d 407 with the card's UID (up to 7 uint8_ts)
smcqueen 0:76b77ec0a86d 408 @param uidLength Pointer to the variable that will hold the
smcqueen 0:76b77ec0a86d 409 length of the card's UID.
smcqueen 0:76b77ec0a86d 410
smcqueen 0:76b77ec0a86d 411 @returns 1 if everything executed properly, 0 for an error
smcqueen 0:76b77ec0a86d 412 */
smcqueen 0:76b77ec0a86d 413 /**************************************************************************/
smcqueen 0:76b77ec0a86d 414 bool Adafruit_PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength) {
smcqueen 0:76b77ec0a86d 415 pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
smcqueen 0:76b77ec0a86d 416 pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later)
smcqueen 0:76b77ec0a86d 417 pn532_packetbuffer[2] = cardbaudrate;
smcqueen 0:76b77ec0a86d 418
smcqueen 0:76b77ec0a86d 419 if (! sendCommandCheckAck(pn532_packetbuffer, 3))
smcqueen 0:76b77ec0a86d 420 return 0x0; // no cards read
smcqueen 0:76b77ec0a86d 421
smcqueen 0:76b77ec0a86d 422 // read data packet
smcqueen 0:76b77ec0a86d 423 readspidata(pn532_packetbuffer, 20);
smcqueen 0:76b77ec0a86d 424 // check some basic stuff
smcqueen 0:76b77ec0a86d 425
smcqueen 0:76b77ec0a86d 426 /* ISO14443A card response should be in the following format:
smcqueen 0:76b77ec0a86d 427
smcqueen 0:76b77ec0a86d 428 uint8_t Description
smcqueen 0:76b77ec0a86d 429 ------------- ------------------------------------------
smcqueen 0:76b77ec0a86d 430 b0..6 Frame header and preamble
smcqueen 0:76b77ec0a86d 431 b7 Tags Found
smcqueen 0:76b77ec0a86d 432 b8 Tag Number (only one used in this example)
smcqueen 0:76b77ec0a86d 433 b9..10 SENS_RES
smcqueen 0:76b77ec0a86d 434 b11 SEL_RES
smcqueen 0:76b77ec0a86d 435 b12 NFCID Length
smcqueen 0:76b77ec0a86d 436 b13..NFCIDLen NFCID */
smcqueen 0:76b77ec0a86d 437
smcqueen 0:76b77ec0a86d 438 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 439 SERIAL_PRINT("Found "); SERIAL_PRINT(pn532_packetbuffer[7], DEC); SERIAL_PRINTln(" tags");
smcqueen 0:76b77ec0a86d 440 #endif
smcqueen 0:76b77ec0a86d 441 if (pn532_packetbuffer[7] != 1)
smcqueen 0:76b77ec0a86d 442 return 0;
smcqueen 0:76b77ec0a86d 443
smcqueen 0:76b77ec0a86d 444 uint16_t sens_res = pn532_packetbuffer[9];
smcqueen 0:76b77ec0a86d 445 sens_res <<= 8;
smcqueen 0:76b77ec0a86d 446 sens_res |= pn532_packetbuffer[10];
smcqueen 0:76b77ec0a86d 447 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 448 SERIAL_PRINT("ATQA: 0x"); SERIAL_PRINTln(sens_res, HEX);
smcqueen 0:76b77ec0a86d 449 SERIAL_PRINT("SAK: 0x"); SERIAL_PRINTln(pn532_packetbuffer[11], HEX);
smcqueen 0:76b77ec0a86d 450 #endif
smcqueen 0:76b77ec0a86d 451
smcqueen 0:76b77ec0a86d 452 /* Card appears to be Mifare Classic */
smcqueen 0:76b77ec0a86d 453 *uidLength = pn532_packetbuffer[12];
smcqueen 0:76b77ec0a86d 454 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 455 SERIAL_PRINT("UID:");
smcqueen 0:76b77ec0a86d 456 #endif
smcqueen 0:76b77ec0a86d 457 for (uint8_t i=0; i < pn532_packetbuffer[12]; i++)
smcqueen 0:76b77ec0a86d 458 {
smcqueen 0:76b77ec0a86d 459 uid[i] = pn532_packetbuffer[13+i];
smcqueen 0:76b77ec0a86d 460 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 461 SERIAL_PRINT(" 0x");SERIAL_PRINT(uid[i], HEX);
smcqueen 0:76b77ec0a86d 462 #endif
smcqueen 0:76b77ec0a86d 463 }
smcqueen 0:76b77ec0a86d 464 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 465 SERIAL_PRINTln();
smcqueen 0:76b77ec0a86d 466 #endif
smcqueen 0:76b77ec0a86d 467
smcqueen 0:76b77ec0a86d 468 uint8_t bTestDeselect[2];
smcqueen 0:76b77ec0a86d 469 bTestDeselect[0] = PN532_COMMAND_INDESELECT;
smcqueen 0:76b77ec0a86d 470 bTestDeselect[1] = pn532_packetbuffer[8];
smcqueen 0:76b77ec0a86d 471 sendCommandCheckAck(bTestDeselect,2);
smcqueen 0:76b77ec0a86d 472
smcqueen 0:76b77ec0a86d 473 return 1;
smcqueen 0:76b77ec0a86d 474 }
smcqueen 0:76b77ec0a86d 475
smcqueen 0:76b77ec0a86d 476
smcqueen 0:76b77ec0a86d 477 /***** Mifare Classic Functions ******/
smcqueen 0:76b77ec0a86d 478
smcqueen 0:76b77ec0a86d 479 /**************************************************************************/
smcqueen 0:76b77ec0a86d 480 /*!
smcqueen 0:76b77ec0a86d 481 Indicates whether the specified block number is the first block
smcqueen 0:76b77ec0a86d 482 in the sector (block 0 relative to the current sector)
smcqueen 0:76b77ec0a86d 483 */
smcqueen 0:76b77ec0a86d 484 /**************************************************************************/
smcqueen 0:76b77ec0a86d 485 bool Adafruit_PN532::mifareclassic_IsFirstBlock (uint32_t uiBlock)
smcqueen 0:76b77ec0a86d 486 {
smcqueen 0:76b77ec0a86d 487 // Test if we are in the small or big sectors
smcqueen 0:76b77ec0a86d 488 if (uiBlock < 128)
smcqueen 0:76b77ec0a86d 489 return ((uiBlock) % 4 == 0);
smcqueen 0:76b77ec0a86d 490 else
smcqueen 0:76b77ec0a86d 491 return ((uiBlock) % 16 == 0);
smcqueen 0:76b77ec0a86d 492 }
smcqueen 0:76b77ec0a86d 493
smcqueen 0:76b77ec0a86d 494 /**************************************************************************/
smcqueen 0:76b77ec0a86d 495 /*!
smcqueen 0:76b77ec0a86d 496 Indicates whether the specified block number is the sector trailer
smcqueen 0:76b77ec0a86d 497 */
smcqueen 0:76b77ec0a86d 498 /**************************************************************************/
smcqueen 0:76b77ec0a86d 499 bool Adafruit_PN532::mifareclassic_IsTrailerBlock (uint32_t uiBlock)
smcqueen 0:76b77ec0a86d 500 {
smcqueen 0:76b77ec0a86d 501 // Test if we are in the small or big sectors
smcqueen 0:76b77ec0a86d 502 if (uiBlock < 128)
smcqueen 0:76b77ec0a86d 503 return ((uiBlock + 1) % 4 == 0);
smcqueen 0:76b77ec0a86d 504 else
smcqueen 0:76b77ec0a86d 505 return ((uiBlock + 1) % 16 == 0);
smcqueen 0:76b77ec0a86d 506 }
smcqueen 0:76b77ec0a86d 507
smcqueen 0:76b77ec0a86d 508 /**************************************************************************/
smcqueen 0:76b77ec0a86d 509 /*!
smcqueen 0:76b77ec0a86d 510 Tries to authenticate a block of memory on a MIFARE card using the
smcqueen 0:76b77ec0a86d 511 INDATAEXCHANGE command. See section 7.3.8 of the PN532 User Manual
smcqueen 0:76b77ec0a86d 512 for more information on sending MIFARE and other commands.
smcqueen 0:76b77ec0a86d 513
smcqueen 0:76b77ec0a86d 514 @param uid Pointer to a uint8_t array containing the card UID
smcqueen 0:76b77ec0a86d 515 @param uidLen The length (in uint8_ts) of the card's UID (Should
smcqueen 0:76b77ec0a86d 516 be 4 for MIFARE Classic)
smcqueen 0:76b77ec0a86d 517 @param blockNumber The block number to authenticate. (0..63 for
smcqueen 0:76b77ec0a86d 518 1KB cards, and 0..255 for 4KB cards).
smcqueen 0:76b77ec0a86d 519 @param keyNumber Which key type to use during authentication
smcqueen 0:76b77ec0a86d 520 (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B)
smcqueen 0:76b77ec0a86d 521 @param keyData Pointer to a uint8_t array containing the 6 uint8_t
smcqueen 0:76b77ec0a86d 522 key value
smcqueen 0:76b77ec0a86d 523
smcqueen 0:76b77ec0a86d 524 @returns 1 if everything executed properly, 0 for an error
smcqueen 0:76b77ec0a86d 525 */
smcqueen 0:76b77ec0a86d 526 /**************************************************************************/
smcqueen 0:76b77ec0a86d 527 uint8_t Adafruit_PN532::mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData)
smcqueen 0:76b77ec0a86d 528 {
smcqueen 0:76b77ec0a86d 529 uint8_t i;
smcqueen 0:76b77ec0a86d 530
smcqueen 0:76b77ec0a86d 531 // Hang on to the key and uid data
smcqueen 0:76b77ec0a86d 532 memcpy (_key, keyData, 6);
smcqueen 0:76b77ec0a86d 533 memcpy (_uid, uid, uidLen);
smcqueen 0:76b77ec0a86d 534 _uidLen = uidLen;
smcqueen 0:76b77ec0a86d 535
smcqueen 0:76b77ec0a86d 536 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 537 SERIAL_PRINT("Trying to authenticate card ");
smcqueen 0:76b77ec0a86d 538 Adafruit_PN532::PrintHex(_uid, _uidLen);
smcqueen 0:76b77ec0a86d 539 SERIAL_PRINT("Using authentication KEY ");SERIAL_PRINT(keyNumber ? 'B' : 'A');SERIAL_PRINT(": ");
smcqueen 0:76b77ec0a86d 540 Adafruit_PN532::PrintHex(_key, 6);
smcqueen 0:76b77ec0a86d 541 #endif
smcqueen 0:76b77ec0a86d 542
smcqueen 0:76b77ec0a86d 543 // Prepare the authentication command //
smcqueen 0:76b77ec0a86d 544 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */
smcqueen 0:76b77ec0a86d 545 pn532_packetbuffer[1] = 1; /* Max card numbers */
smcqueen 0:76b77ec0a86d 546 pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
smcqueen 0:76b77ec0a86d 547 pn532_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */
smcqueen 0:76b77ec0a86d 548 memcpy (pn532_packetbuffer+4, _key, 6);
smcqueen 0:76b77ec0a86d 549 for (i = 0; i < _uidLen; i++)
smcqueen 0:76b77ec0a86d 550 {
smcqueen 0:76b77ec0a86d 551 pn532_packetbuffer[10+i] = _uid[i]; /* 4 uint8_t card ID */
smcqueen 0:76b77ec0a86d 552 }
smcqueen 0:76b77ec0a86d 553
smcqueen 0:76b77ec0a86d 554 if (! sendCommandCheckAck(pn532_packetbuffer, 10+_uidLen))
smcqueen 0:76b77ec0a86d 555 return 0;
smcqueen 0:76b77ec0a86d 556
smcqueen 0:76b77ec0a86d 557 // Read the response packet
smcqueen 0:76b77ec0a86d 558 readspidata(pn532_packetbuffer, 12);
smcqueen 0:76b77ec0a86d 559 // check if the response is valid and we are authenticated???
smcqueen 0:76b77ec0a86d 560 // for an auth success it should be uint8_ts 5-7: 0xD5 0x41 0x00
smcqueen 0:76b77ec0a86d 561 // Mifare auth error is technically uint8_t 7: 0x14 but anything other and 0x00 is not good
smcqueen 0:76b77ec0a86d 562 if (pn532_packetbuffer[7] != 0x00)
smcqueen 0:76b77ec0a86d 563 {
smcqueen 0:76b77ec0a86d 564 #ifdef PN532DEBUG
smcqueen 0:76b77ec0a86d 565 SERIAL_PRINT("Authentification failed: ");
smcqueen 0:76b77ec0a86d 566 Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 12);
smcqueen 0:76b77ec0a86d 567 #endif
smcqueen 0:76b77ec0a86d 568 return 0;
smcqueen 0:76b77ec0a86d 569 }
smcqueen 0:76b77ec0a86d 570
smcqueen 0:76b77ec0a86d 571 return 1;
smcqueen 0:76b77ec0a86d 572 }
smcqueen 0:76b77ec0a86d 573
smcqueen 0:76b77ec0a86d 574 /**************************************************************************/
smcqueen 0:76b77ec0a86d 575 /*!
smcqueen 0:76b77ec0a86d 576 Tries to read an entire 16-uint8_t data block at the specified block
smcqueen 0:76b77ec0a86d 577 address.
smcqueen 0:76b77ec0a86d 578
smcqueen 0:76b77ec0a86d 579 @param blockNumber The block number to authenticate. (0..63 for
smcqueen 0:76b77ec0a86d 580 1KB cards, and 0..255 for 4KB cards).
smcqueen 0:76b77ec0a86d 581 @param data Pointer to the uint8_t array that will hold the
smcqueen 0:76b77ec0a86d 582 retrieved data (if any)
smcqueen 0:76b77ec0a86d 583
smcqueen 0:76b77ec0a86d 584 @returns 1 if everything executed properly, 0 for an error
smcqueen 0:76b77ec0a86d 585 */
smcqueen 0:76b77ec0a86d 586 /**************************************************************************/
smcqueen 0:76b77ec0a86d 587 uint8_t Adafruit_PN532::mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data)
smcqueen 0:76b77ec0a86d 588 {
smcqueen 0:76b77ec0a86d 589 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 590 SERIAL_PRINT("Trying to read 16 uint8_ts from block ");SERIAL_PRINTln(blockNumber);
smcqueen 0:76b77ec0a86d 591 #endif
smcqueen 0:76b77ec0a86d 592
smcqueen 0:76b77ec0a86d 593 /* Prepare the command */
smcqueen 0:76b77ec0a86d 594 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
smcqueen 0:76b77ec0a86d 595 pn532_packetbuffer[1] = 1; /* Card number */
smcqueen 0:76b77ec0a86d 596 pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */
smcqueen 0:76b77ec0a86d 597 pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
smcqueen 0:76b77ec0a86d 598
smcqueen 0:76b77ec0a86d 599 /* Send the command */
smcqueen 0:76b77ec0a86d 600 if (! sendCommandCheckAck(pn532_packetbuffer, 4))
smcqueen 0:76b77ec0a86d 601 {
smcqueen 0:76b77ec0a86d 602 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 603 SERIAL_PRINTln("Failed to receive ACK for read command");
smcqueen 0:76b77ec0a86d 604 #endif
smcqueen 0:76b77ec0a86d 605 return 0;
smcqueen 0:76b77ec0a86d 606 }
smcqueen 0:76b77ec0a86d 607
smcqueen 0:76b77ec0a86d 608 /* Read the response packet */
smcqueen 0:76b77ec0a86d 609 readspidata(pn532_packetbuffer, 26);
smcqueen 0:76b77ec0a86d 610
smcqueen 0:76b77ec0a86d 611 /* If uint8_t 8 isn't 0x00 we probably have an error */
smcqueen 0:76b77ec0a86d 612 if (pn532_packetbuffer[7] != 0x00)
smcqueen 0:76b77ec0a86d 613 {
smcqueen 0:76b77ec0a86d 614 //#ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 615 SERIAL_PRINT("Unexpected response");
smcqueen 0:76b77ec0a86d 616 Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26);
smcqueen 0:76b77ec0a86d 617 //#endif
smcqueen 0:76b77ec0a86d 618 return 0;
smcqueen 0:76b77ec0a86d 619 }
smcqueen 0:76b77ec0a86d 620
smcqueen 0:76b77ec0a86d 621 /* Copy the 16 data uint8_ts to the output buffer */
smcqueen 0:76b77ec0a86d 622 /* Block content starts at uint8_t 9 of a valid response */
smcqueen 0:76b77ec0a86d 623 memcpy (data, pn532_packetbuffer+8, 16);
smcqueen 0:76b77ec0a86d 624
smcqueen 0:76b77ec0a86d 625 /* Display data for debug if requested */
smcqueen 0:76b77ec0a86d 626 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 627 SERIAL_PRINT("Block ");
smcqueen 0:76b77ec0a86d 628 SERIAL_PRINTln(blockNumber);
smcqueen 0:76b77ec0a86d 629 Adafruit_PN532::PrintHexChar(data, 16);
smcqueen 0:76b77ec0a86d 630 #endif
smcqueen 0:76b77ec0a86d 631
smcqueen 0:76b77ec0a86d 632 return 1;
smcqueen 0:76b77ec0a86d 633 }
smcqueen 0:76b77ec0a86d 634
smcqueen 0:76b77ec0a86d 635 /**************************************************************************/
smcqueen 0:76b77ec0a86d 636 /*!
smcqueen 0:76b77ec0a86d 637 Tries to write an entire 16-uint8_t data block at the specified block
smcqueen 0:76b77ec0a86d 638 address.
smcqueen 0:76b77ec0a86d 639
smcqueen 0:76b77ec0a86d 640 @param blockNumber The block number to authenticate. (0..63 for
smcqueen 0:76b77ec0a86d 641 1KB cards, and 0..255 for 4KB cards).
smcqueen 0:76b77ec0a86d 642 @param data The uint8_t array that contains the data to write.
smcqueen 0:76b77ec0a86d 643
smcqueen 0:76b77ec0a86d 644 @returns 1 if everything executed properly, 0 for an error
smcqueen 0:76b77ec0a86d 645 */
smcqueen 0:76b77ec0a86d 646 /**************************************************************************/
smcqueen 0:76b77ec0a86d 647 uint8_t Adafruit_PN532::mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data)
smcqueen 0:76b77ec0a86d 648 {
smcqueen 0:76b77ec0a86d 649 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 650 SERIAL_PRINT("Trying to write 16 uint8_ts to block ");SERIAL_PRINTln(blockNumber);
smcqueen 0:76b77ec0a86d 651 #endif
smcqueen 0:76b77ec0a86d 652
smcqueen 0:76b77ec0a86d 653 /* Prepare the first command */
smcqueen 0:76b77ec0a86d 654 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
smcqueen 0:76b77ec0a86d 655 pn532_packetbuffer[1] = 1; /* Card number */
smcqueen 0:76b77ec0a86d 656 pn532_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */
smcqueen 0:76b77ec0a86d 657 pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
smcqueen 0:76b77ec0a86d 658 memcpy (pn532_packetbuffer+4, data, 16); /* Data Payload */
smcqueen 0:76b77ec0a86d 659
smcqueen 0:76b77ec0a86d 660 /* Send the command */
smcqueen 0:76b77ec0a86d 661 if (! sendCommandCheckAck(pn532_packetbuffer, 20))
smcqueen 0:76b77ec0a86d 662 {
smcqueen 0:76b77ec0a86d 663 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 664 SERIAL_PRINTln("Failed to receive ACK for write command");
smcqueen 0:76b77ec0a86d 665 #endif
smcqueen 0:76b77ec0a86d 666 return 0;
smcqueen 0:76b77ec0a86d 667 }
smcqueen 0:76b77ec0a86d 668 delay(10);
smcqueen 0:76b77ec0a86d 669
smcqueen 0:76b77ec0a86d 670 /* Read the response packet */
smcqueen 0:76b77ec0a86d 671 readspidata(pn532_packetbuffer, 26);
smcqueen 0:76b77ec0a86d 672
smcqueen 0:76b77ec0a86d 673 return 1;
smcqueen 0:76b77ec0a86d 674 }
smcqueen 0:76b77ec0a86d 675
smcqueen 0:76b77ec0a86d 676 /**************************************************************************/
smcqueen 0:76b77ec0a86d 677 /*!
smcqueen 0:76b77ec0a86d 678 Formats a Mifare Classic card to store NDEF Records
smcqueen 0:76b77ec0a86d 679
smcqueen 0:76b77ec0a86d 680 @returns 1 if everything executed properly, 0 for an error
smcqueen 0:76b77ec0a86d 681 */
smcqueen 0:76b77ec0a86d 682 /**************************************************************************/
smcqueen 0:76b77ec0a86d 683 uint8_t Adafruit_PN532::mifareclassic_FormatNDEF (void)
smcqueen 0:76b77ec0a86d 684 {
smcqueen 0:76b77ec0a86d 685 uint8_t sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
smcqueen 0:76b77ec0a86d 686 uint8_t sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
smcqueen 0:76b77ec0a86d 687 uint8_t sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
smcqueen 0:76b77ec0a86d 688
smcqueen 0:76b77ec0a86d 689 // Write block 1 and 2 to the card
smcqueen 0:76b77ec0a86d 690 if (!(mifareclassic_WriteDataBlock (1, sectorbuffer1)))
smcqueen 0:76b77ec0a86d 691 return 0;
smcqueen 0:76b77ec0a86d 692 if (!(mifareclassic_WriteDataBlock (2, sectorbuffer2)))
smcqueen 0:76b77ec0a86d 693 return 0;
smcqueen 0:76b77ec0a86d 694 // Write key A and access rights card
smcqueen 0:76b77ec0a86d 695 if (!(mifareclassic_WriteDataBlock (3, sectorbuffer3)))
smcqueen 0:76b77ec0a86d 696 return 0;
smcqueen 0:76b77ec0a86d 697
smcqueen 0:76b77ec0a86d 698 // Seems that everything was OK (?!)
smcqueen 0:76b77ec0a86d 699 return 1;
smcqueen 0:76b77ec0a86d 700 }
smcqueen 0:76b77ec0a86d 701
smcqueen 0:76b77ec0a86d 702 /**************************************************************************/
smcqueen 0:76b77ec0a86d 703 /*!
smcqueen 0:76b77ec0a86d 704 Writes an NDEF URI Record to the specified sector (1..15)
smcqueen 0:76b77ec0a86d 705
smcqueen 0:76b77ec0a86d 706 Note that this function assumes that the Mifare Classic card is
smcqueen 0:76b77ec0a86d 707 already formatted to work as an "NFC Forum Tag" and uses a MAD1
smcqueen 0:76b77ec0a86d 708 file system. You can use the NXP TagWriter app on Android to
smcqueen 0:76b77ec0a86d 709 properly format cards for this.
smcqueen 0:76b77ec0a86d 710
smcqueen 0:76b77ec0a86d 711 @param sectorNumber The sector that the URI record should be written
smcqueen 0:76b77ec0a86d 712 to (can be 1..15 for a 1K card)
smcqueen 0:76b77ec0a86d 713 @param uriIdentifier The uri identifier code (0 = none, 0x01 =
smcqueen 0:76b77ec0a86d 714 "http://www.", etc.)
smcqueen 0:76b77ec0a86d 715 @param url The uri text to write (max 38 characters).
smcqueen 0:76b77ec0a86d 716
smcqueen 0:76b77ec0a86d 717 @returns 1 if everything executed properly, 0 for an error
smcqueen 0:76b77ec0a86d 718 */
smcqueen 0:76b77ec0a86d 719 /**************************************************************************/
smcqueen 0:76b77ec0a86d 720 uint8_t Adafruit_PN532::mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char * url)
smcqueen 0:76b77ec0a86d 721 {
smcqueen 0:76b77ec0a86d 722 // Figure out how long the string is
smcqueen 0:76b77ec0a86d 723 uint8_t len = strlen(url);
smcqueen 0:76b77ec0a86d 724
smcqueen 0:76b77ec0a86d 725 // Make sure we're within a 1K limit for the sector number
smcqueen 0:76b77ec0a86d 726 if ((sectorNumber < 1) || (sectorNumber > 15))
smcqueen 0:76b77ec0a86d 727 return 0;
smcqueen 0:76b77ec0a86d 728
smcqueen 0:76b77ec0a86d 729 // Make sure the URI payload is between 1 and 38 chars
smcqueen 0:76b77ec0a86d 730 if ((len < 1) || (len > 38))
smcqueen 0:76b77ec0a86d 731 return 0;
smcqueen 0:76b77ec0a86d 732
smcqueen 0:76b77ec0a86d 733 // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message)
smcqueen 0:76b77ec0a86d 734 uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, len+5, 0xD1, 0x01, len+1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
smcqueen 0:76b77ec0a86d 735 uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
smcqueen 0:76b77ec0a86d 736 uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
smcqueen 0:76b77ec0a86d 737 uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
smcqueen 0:76b77ec0a86d 738 if (len <= 6)
smcqueen 0:76b77ec0a86d 739 {
smcqueen 0:76b77ec0a86d 740 // Unlikely we'll get a url this short, but why not ...
smcqueen 0:76b77ec0a86d 741 memcpy (sectorbuffer1+9, url, len);
smcqueen 0:76b77ec0a86d 742 sectorbuffer1[len+9] = 0xFE;
smcqueen 0:76b77ec0a86d 743 }
smcqueen 0:76b77ec0a86d 744 else if (len == 7)
smcqueen 0:76b77ec0a86d 745 {
smcqueen 0:76b77ec0a86d 746 // 0xFE needs to be wrapped around to next block
smcqueen 0:76b77ec0a86d 747 memcpy (sectorbuffer1+9, url, len);
smcqueen 0:76b77ec0a86d 748 sectorbuffer2[0] = 0xFE;
smcqueen 0:76b77ec0a86d 749 }
smcqueen 0:76b77ec0a86d 750 else if ((len > 7) || (len <= 22))
smcqueen 0:76b77ec0a86d 751 {
smcqueen 0:76b77ec0a86d 752 // Url fits in two blocks
smcqueen 0:76b77ec0a86d 753 memcpy (sectorbuffer1+9, url, 7);
smcqueen 0:76b77ec0a86d 754 memcpy (sectorbuffer2, url+7, len-7);
smcqueen 0:76b77ec0a86d 755 sectorbuffer2[len-7] = 0xFE;
smcqueen 0:76b77ec0a86d 756 }
smcqueen 0:76b77ec0a86d 757 else if (len == 23)
smcqueen 0:76b77ec0a86d 758 {
smcqueen 0:76b77ec0a86d 759 // 0xFE needs to be wrapped around to final block
smcqueen 0:76b77ec0a86d 760 memcpy (sectorbuffer1+9, url, 7);
smcqueen 0:76b77ec0a86d 761 memcpy (sectorbuffer2, url+7, len-7);
smcqueen 0:76b77ec0a86d 762 sectorbuffer3[0] = 0xFE;
smcqueen 0:76b77ec0a86d 763 }
smcqueen 0:76b77ec0a86d 764 else
smcqueen 0:76b77ec0a86d 765 {
smcqueen 0:76b77ec0a86d 766 // Url fits in three blocks
smcqueen 0:76b77ec0a86d 767 memcpy (sectorbuffer1+9, url, 7);
smcqueen 0:76b77ec0a86d 768 memcpy (sectorbuffer2, url+7, 16);
smcqueen 0:76b77ec0a86d 769 memcpy (sectorbuffer3, url+23, len-24);
smcqueen 0:76b77ec0a86d 770 sectorbuffer3[len-22] = 0xFE;
smcqueen 0:76b77ec0a86d 771 }
smcqueen 0:76b77ec0a86d 772
smcqueen 0:76b77ec0a86d 773 // Now write all three blocks back to the card
smcqueen 0:76b77ec0a86d 774 if (!(mifareclassic_WriteDataBlock (sectorNumber*4, sectorbuffer1)))
smcqueen 0:76b77ec0a86d 775 return 0;
smcqueen 0:76b77ec0a86d 776 if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+1, sectorbuffer2)))
smcqueen 0:76b77ec0a86d 777 return 0;
smcqueen 0:76b77ec0a86d 778 if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+2, sectorbuffer3)))
smcqueen 0:76b77ec0a86d 779 return 0;
smcqueen 0:76b77ec0a86d 780 if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+3, sectorbuffer4)))
smcqueen 0:76b77ec0a86d 781 return 0;
smcqueen 0:76b77ec0a86d 782
smcqueen 0:76b77ec0a86d 783 // Seems that everything was OK (?!)
smcqueen 0:76b77ec0a86d 784 return 1;
smcqueen 0:76b77ec0a86d 785 }
smcqueen 0:76b77ec0a86d 786
smcqueen 0:76b77ec0a86d 787 /***** Mifare Ultralight Functions ******/
smcqueen 0:76b77ec0a86d 788
smcqueen 0:76b77ec0a86d 789 /**************************************************************************/
smcqueen 0:76b77ec0a86d 790 /*!
smcqueen 0:76b77ec0a86d 791 Tries to read an entire 4-uint8_t page at the specified address.
smcqueen 0:76b77ec0a86d 792
smcqueen 0:76b77ec0a86d 793 @param page The page number (0..63 in most cases)
smcqueen 0:76b77ec0a86d 794 @param buffer Pointer to the uint8_t array that will hold the
smcqueen 0:76b77ec0a86d 795 retrieved data (if any)
smcqueen 0:76b77ec0a86d 796 */
smcqueen 0:76b77ec0a86d 797 /**************************************************************************/
smcqueen 0:76b77ec0a86d 798 uint8_t Adafruit_PN532::mifareultralight_ReadPage (uint8_t page, uint8_t * buffer)
smcqueen 0:76b77ec0a86d 799 {
smcqueen 0:76b77ec0a86d 800 if (page >= 64)
smcqueen 0:76b77ec0a86d 801 {
smcqueen 0:76b77ec0a86d 802 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 803 SERIAL_PRINTln("Page value out of range");
smcqueen 0:76b77ec0a86d 804 #endif
smcqueen 0:76b77ec0a86d 805 return 0;
smcqueen 0:76b77ec0a86d 806 }
smcqueen 0:76b77ec0a86d 807
smcqueen 0:76b77ec0a86d 808 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 809 SERIAL_PRINT("Reading page ");SERIAL_PRINTln(page);
smcqueen 0:76b77ec0a86d 810 #endif
smcqueen 0:76b77ec0a86d 811
smcqueen 0:76b77ec0a86d 812 /* Prepare the command */
smcqueen 0:76b77ec0a86d 813 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
smcqueen 0:76b77ec0a86d 814 pn532_packetbuffer[1] = 1; /* Card number */
smcqueen 0:76b77ec0a86d 815 pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */
smcqueen 0:76b77ec0a86d 816 pn532_packetbuffer[3] = page; /* Page Number (0..63 in most cases) */
smcqueen 0:76b77ec0a86d 817
smcqueen 0:76b77ec0a86d 818 /* Send the command */
smcqueen 0:76b77ec0a86d 819 if (! sendCommandCheckAck(pn532_packetbuffer, 4))
smcqueen 0:76b77ec0a86d 820 {
smcqueen 0:76b77ec0a86d 821 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 822 SERIAL_PRINTln("Failed to receive ACK for write command");
smcqueen 0:76b77ec0a86d 823 #endif
smcqueen 0:76b77ec0a86d 824 return 0;
smcqueen 0:76b77ec0a86d 825 }
smcqueen 0:76b77ec0a86d 826
smcqueen 0:76b77ec0a86d 827 /* Read the response packet */
smcqueen 0:76b77ec0a86d 828 readspidata(pn532_packetbuffer, 26);
smcqueen 0:76b77ec0a86d 829 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 830 SERIAL_PRINTln("Received: ");
smcqueen 0:76b77ec0a86d 831 Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26);
smcqueen 0:76b77ec0a86d 832 #endif
smcqueen 0:76b77ec0a86d 833
smcqueen 0:76b77ec0a86d 834 /* If uint8_t 8 isn't 0x00 we probably have an error */
smcqueen 0:76b77ec0a86d 835 if (pn532_packetbuffer[7] == 0x00)
smcqueen 0:76b77ec0a86d 836 {
smcqueen 0:76b77ec0a86d 837 /* Copy the 4 data uint8_ts to the output buffer */
smcqueen 0:76b77ec0a86d 838 /* Block content starts at uint8_t 9 of a valid response */
smcqueen 0:76b77ec0a86d 839 /* Note that the command actually reads 16 uint8_t or 4 */
smcqueen 0:76b77ec0a86d 840 /* pages at a time ... we simply discard the last 12 */
smcqueen 0:76b77ec0a86d 841 /* uint8_ts */
smcqueen 0:76b77ec0a86d 842 memcpy (buffer, pn532_packetbuffer+8, 4);
smcqueen 0:76b77ec0a86d 843 }
smcqueen 0:76b77ec0a86d 844 else
smcqueen 0:76b77ec0a86d 845 {
smcqueen 0:76b77ec0a86d 846 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 847 SERIAL_PRINTln("Unexpected response reading block: ");
smcqueen 0:76b77ec0a86d 848 Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26);
smcqueen 0:76b77ec0a86d 849 #endif
smcqueen 0:76b77ec0a86d 850 return 0;
smcqueen 0:76b77ec0a86d 851 }
smcqueen 0:76b77ec0a86d 852
smcqueen 0:76b77ec0a86d 853 /* Display data for debug if requested */
smcqueen 0:76b77ec0a86d 854 #ifdef MIFAREDEBUG
smcqueen 0:76b77ec0a86d 855 SERIAL_PRINT("Page ");SERIAL_PRINT(page);SERIAL_PRINTln(":");
smcqueen 0:76b77ec0a86d 856 Adafruit_PN532::PrintHexChar(buffer, 4);
smcqueen 0:76b77ec0a86d 857 #endif
smcqueen 0:76b77ec0a86d 858
smcqueen 0:76b77ec0a86d 859 // Return OK signal
smcqueen 0:76b77ec0a86d 860 return 1;
smcqueen 0:76b77ec0a86d 861 }
smcqueen 0:76b77ec0a86d 862
smcqueen 0:76b77ec0a86d 863
smcqueen 0:76b77ec0a86d 864
smcqueen 0:76b77ec0a86d 865 /************** high level SPI */
smcqueen 0:76b77ec0a86d 866
smcqueen 0:76b77ec0a86d 867
smcqueen 0:76b77ec0a86d 868 /**************************************************************************/
smcqueen 0:76b77ec0a86d 869 /*!
smcqueen 0:76b77ec0a86d 870 @brief Tries to read the SPI ACK signal
smcqueen 0:76b77ec0a86d 871 */
smcqueen 0:76b77ec0a86d 872 /**************************************************************************/
smcqueen 0:76b77ec0a86d 873 bool Adafruit_PN532::spi_readack() {
smcqueen 0:76b77ec0a86d 874 uint8_t ackbuff[6];
smcqueen 0:76b77ec0a86d 875
smcqueen 0:76b77ec0a86d 876 readspidata(ackbuff, 6);
smcqueen 0:76b77ec0a86d 877
smcqueen 0:76b77ec0a86d 878 return (0 == strncmp((char *)ackbuff, (char *)pn532ack, 6));
smcqueen 0:76b77ec0a86d 879 }
smcqueen 0:76b77ec0a86d 880
smcqueen 0:76b77ec0a86d 881 /************** mid level SPI */
smcqueen 0:76b77ec0a86d 882
smcqueen 0:76b77ec0a86d 883 /**************************************************************************/
smcqueen 0:76b77ec0a86d 884 /*!
smcqueen 0:76b77ec0a86d 885 @brief Reads the SPI status register (to know if the PN532 is ready)
smcqueen 0:76b77ec0a86d 886 */
smcqueen 0:76b77ec0a86d 887 /**************************************************************************/
smcqueen 0:76b77ec0a86d 888 uint8_t Adafruit_PN532::readspistatus(void) {
smcqueen 0:76b77ec0a86d 889 _ss = 0;
smcqueen 0:76b77ec0a86d 890 delay(2);
smcqueen 0:76b77ec0a86d 891 spiwrite(PN532_SPI_STATREAD);
smcqueen 0:76b77ec0a86d 892 // read uint8_t
smcqueen 0:76b77ec0a86d 893 uint8_t x = spiread();
smcqueen 0:76b77ec0a86d 894
smcqueen 0:76b77ec0a86d 895 _ss = 1;
smcqueen 0:76b77ec0a86d 896 return x;
smcqueen 0:76b77ec0a86d 897 }
smcqueen 0:76b77ec0a86d 898
smcqueen 0:76b77ec0a86d 899 /**************************************************************************/
smcqueen 0:76b77ec0a86d 900 /*!
smcqueen 0:76b77ec0a86d 901 @brief Reads n uint8_ts of data from the PN532 via SPI
smcqueen 0:76b77ec0a86d 902
smcqueen 0:76b77ec0a86d 903 @param buff Pointer to the buffer where data will be written
smcqueen 0:76b77ec0a86d 904 @param n Number of uint8_ts to be read
smcqueen 0:76b77ec0a86d 905 */
smcqueen 0:76b77ec0a86d 906 /**************************************************************************/
smcqueen 0:76b77ec0a86d 907 void Adafruit_PN532::readspidata(uint8_t* buff, uint8_t n) {
smcqueen 0:76b77ec0a86d 908 _ss = 0;
smcqueen 0:76b77ec0a86d 909 delay(2);
smcqueen 0:76b77ec0a86d 910 spiwrite(PN532_SPI_DATAREAD);
smcqueen 0:76b77ec0a86d 911
smcqueen 0:76b77ec0a86d 912 #ifdef PN532DEBUG
smcqueen 0:76b77ec0a86d 913 SERIAL_PRINT("Reading: ");
smcqueen 0:76b77ec0a86d 914 #endif
smcqueen 0:76b77ec0a86d 915 for (uint8_t i=0; i<n; i++) {
smcqueen 0:76b77ec0a86d 916 delay(1);
smcqueen 0:76b77ec0a86d 917 buff[i] = spiread();
smcqueen 0:76b77ec0a86d 918 #ifdef PN532DEBUG
smcqueen 0:76b77ec0a86d 919 SERIAL_PRINT(" 0x");
smcqueen 0:76b77ec0a86d 920 SERIAL_PRINT(buff[i], HEX);
smcqueen 0:76b77ec0a86d 921 #endif
smcqueen 0:76b77ec0a86d 922 }
smcqueen 0:76b77ec0a86d 923
smcqueen 0:76b77ec0a86d 924 #ifdef PN532DEBUG
smcqueen 0:76b77ec0a86d 925 SERIAL_PRINTln();
smcqueen 0:76b77ec0a86d 926 #endif
smcqueen 0:76b77ec0a86d 927
smcqueen 0:76b77ec0a86d 928 _ss = 1;
smcqueen 0:76b77ec0a86d 929 }
smcqueen 0:76b77ec0a86d 930
smcqueen 0:76b77ec0a86d 931 /**************************************************************************/
smcqueen 0:76b77ec0a86d 932 /*!
smcqueen 0:76b77ec0a86d 933 @brief Writes a command to the PN532, automatically inserting the
smcqueen 0:76b77ec0a86d 934 preamble and required frame details (checksum, len, etc.)
smcqueen 0:76b77ec0a86d 935
smcqueen 0:76b77ec0a86d 936 @param cmd Pointer to the command buffer
smcqueen 0:76b77ec0a86d 937 @param cmdlen Command length in uint8_ts
smcqueen 0:76b77ec0a86d 938 */
smcqueen 0:76b77ec0a86d 939 /**************************************************************************/
smcqueen 0:76b77ec0a86d 940 void Adafruit_PN532::spiwritecommand(uint8_t* cmd, uint8_t cmdlen) {
smcqueen 0:76b77ec0a86d 941 uint8_t checksum;
smcqueen 0:76b77ec0a86d 942
smcqueen 0:76b77ec0a86d 943 cmdlen++;
smcqueen 0:76b77ec0a86d 944
smcqueen 0:76b77ec0a86d 945 #ifdef PN532DEBUG
smcqueen 0:76b77ec0a86d 946 SERIAL_PRINT("\nSending: ");
smcqueen 0:76b77ec0a86d 947 #endif
smcqueen 0:76b77ec0a86d 948
smcqueen 0:76b77ec0a86d 949 _ss = 0;
smcqueen 0:76b77ec0a86d 950 delay(2); // or whatever the delay is for waking up the board
smcqueen 0:76b77ec0a86d 951 spiwrite(PN532_SPI_DATAWRITE);
smcqueen 0:76b77ec0a86d 952
smcqueen 0:76b77ec0a86d 953 checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2;
smcqueen 0:76b77ec0a86d 954 spiwrite(PN532_PREAMBLE);
smcqueen 0:76b77ec0a86d 955 spiwrite(PN532_PREAMBLE);
smcqueen 0:76b77ec0a86d 956 spiwrite(PN532_STARTCODE2);
smcqueen 0:76b77ec0a86d 957
smcqueen 0:76b77ec0a86d 958 spiwrite(cmdlen);
smcqueen 0:76b77ec0a86d 959 spiwrite(~cmdlen + 1);
smcqueen 0:76b77ec0a86d 960
smcqueen 0:76b77ec0a86d 961 spiwrite(PN532_HOSTTOPN532);
smcqueen 0:76b77ec0a86d 962 checksum += PN532_HOSTTOPN532;
smcqueen 0:76b77ec0a86d 963
smcqueen 0:76b77ec0a86d 964 #ifdef PN532DEBUG
smcqueen 0:76b77ec0a86d 965 SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_PREAMBLE, HEX);
smcqueen 0:76b77ec0a86d 966 SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_PREAMBLE, HEX);
smcqueen 0:76b77ec0a86d 967 SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_STARTCODE2, HEX);
smcqueen 0:76b77ec0a86d 968 SERIAL_PRINT(" 0x"); SERIAL_PRINT(cmdlen, HEX);
smcqueen 0:76b77ec0a86d 969 SERIAL_PRINT(" 0x"); SERIAL_PRINT(~cmdlen + 1, HEX);
smcqueen 0:76b77ec0a86d 970 SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_HOSTTOPN532, HEX);
smcqueen 0:76b77ec0a86d 971 #endif
smcqueen 0:76b77ec0a86d 972
smcqueen 0:76b77ec0a86d 973 for (uint8_t i=0; i<cmdlen-1; i++) {
smcqueen 0:76b77ec0a86d 974 spiwrite(cmd[i]);
smcqueen 0:76b77ec0a86d 975 checksum += cmd[i];
smcqueen 0:76b77ec0a86d 976 #ifdef PN532DEBUG
smcqueen 0:76b77ec0a86d 977 SERIAL_PRINT(" 0x"); SERIAL_PRINT(cmd[i], HEX);
smcqueen 0:76b77ec0a86d 978 #endif
smcqueen 0:76b77ec0a86d 979 }
smcqueen 0:76b77ec0a86d 980
smcqueen 0:76b77ec0a86d 981 spiwrite(~checksum);
smcqueen 0:76b77ec0a86d 982 spiwrite(PN532_POSTAMBLE);
smcqueen 0:76b77ec0a86d 983 _ss = 1;
smcqueen 0:76b77ec0a86d 984
smcqueen 0:76b77ec0a86d 985 #ifdef PN532DEBUG
smcqueen 0:76b77ec0a86d 986 SERIAL_PRINT(" 0x"); SERIAL_PRINT(~checksum, HEX);
smcqueen 0:76b77ec0a86d 987 SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_POSTAMBLE, HEX);
smcqueen 0:76b77ec0a86d 988 SERIAL_PRINTln();
smcqueen 0:76b77ec0a86d 989 #endif
smcqueen 0:76b77ec0a86d 990 }
smcqueen 0:76b77ec0a86d 991 /************** low level SPI */
smcqueen 0:76b77ec0a86d 992
smcqueen 0:76b77ec0a86d 993 /**************************************************************************/
smcqueen 0:76b77ec0a86d 994 /*!
smcqueen 0:76b77ec0a86d 995 @brief Low-level SPI write wrapper
smcqueen 0:76b77ec0a86d 996
smcqueen 0:76b77ec0a86d 997 @param c 8-bit command to write to the SPI bus
smcqueen 0:76b77ec0a86d 998 */
smcqueen 0:76b77ec0a86d 999 /**************************************************************************/
smcqueen 0:76b77ec0a86d 1000 void Adafruit_PN532::spiwrite(uint8_t c) {
smcqueen 0:76b77ec0a86d 1001 int8_t i;
smcqueen 0:76b77ec0a86d 1002 _clk = 1;
smcqueen 0:76b77ec0a86d 1003
smcqueen 0:76b77ec0a86d 1004 for (i=0; i<8; i++) {
smcqueen 0:76b77ec0a86d 1005 _clk = 0;
smcqueen 0:76b77ec0a86d 1006 if (c & _BV(i)) {
smcqueen 0:76b77ec0a86d 1007 _mosi = 1;
smcqueen 0:76b77ec0a86d 1008 } else {
smcqueen 0:76b77ec0a86d 1009 _mosi = 0;
smcqueen 0:76b77ec0a86d 1010 }
smcqueen 0:76b77ec0a86d 1011 _clk = 1;
smcqueen 0:76b77ec0a86d 1012 }
smcqueen 0:76b77ec0a86d 1013 }
smcqueen 0:76b77ec0a86d 1014
smcqueen 0:76b77ec0a86d 1015 /**************************************************************************/
smcqueen 0:76b77ec0a86d 1016 /*!
smcqueen 0:76b77ec0a86d 1017 @brief Low-level SPI read wrapper
smcqueen 0:76b77ec0a86d 1018
smcqueen 0:76b77ec0a86d 1019 @returns The 8-bit value that was read from the SPI bus
smcqueen 0:76b77ec0a86d 1020 */
smcqueen 0:76b77ec0a86d 1021 /**************************************************************************/
smcqueen 0:76b77ec0a86d 1022 uint8_t Adafruit_PN532::spiread(void) {
smcqueen 0:76b77ec0a86d 1023 int8_t i, x;
smcqueen 0:76b77ec0a86d 1024 x = 0;
smcqueen 0:76b77ec0a86d 1025 _clk = 1;
smcqueen 0:76b77ec0a86d 1026
smcqueen 0:76b77ec0a86d 1027 for (i=0; i<8; i++) {
smcqueen 0:76b77ec0a86d 1028 if (_miso.read()) {
smcqueen 0:76b77ec0a86d 1029 x |= _BV(i);
smcqueen 0:76b77ec0a86d 1030 }
smcqueen 0:76b77ec0a86d 1031 _clk = 0;
smcqueen 0:76b77ec0a86d 1032 _clk = 1;
smcqueen 0:76b77ec0a86d 1033 }
smcqueen 0:76b77ec0a86d 1034 return x;
smcqueen 0:76b77ec0a86d 1035 }