PN532 NFC library for Seeed Studio's NFC Shield

Fork of PN532 by Yihui Xiong

Committer:
yihui
Date:
Thu Oct 17 06:37:26 2013 +0000
Revision:
1:b8cab5222fd0
Parent:
0:9c6b9280c0e1
Child:
3:4189a10038e6
format code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 0:9c6b9280c0e1 1
yihui 0:9c6b9280c0e1 2 #include "PN532_SPI.h"
yihui 0:9c6b9280c0e1 3 #include "debug.h"
yihui 0:9c6b9280c0e1 4
yihui 0:9c6b9280c0e1 5 #define STATUS_READ 2
yihui 0:9c6b9280c0e1 6 #define DATA_WRITE 1
yihui 0:9c6b9280c0e1 7 #define DATA_READ 3
yihui 0:9c6b9280c0e1 8
yihui 0:9c6b9280c0e1 9 PN532_SPI::PN532_SPI(SPI &spi, PinName ss) : _ss(ss)
yihui 0:9c6b9280c0e1 10 {
yihui 0:9c6b9280c0e1 11 command = 0;
yihui 0:9c6b9280c0e1 12 _spi = &spi;
yihui 0:9c6b9280c0e1 13 _spi->format(8, 0);
yihui 0:9c6b9280c0e1 14 _spi->frequency(2000000);
yihui 1:b8cab5222fd0 15
yihui 0:9c6b9280c0e1 16 _ss = 1;
yihui 0:9c6b9280c0e1 17 }
yihui 0:9c6b9280c0e1 18
yihui 0:9c6b9280c0e1 19 PN532_SPI::PN532_SPI(SPI *spi, PinName ss) : _ss(ss)
yihui 0:9c6b9280c0e1 20 {
yihui 1:b8cab5222fd0 21 command = 0;
yihui 0:9c6b9280c0e1 22 _spi = spi;
yihui 0:9c6b9280c0e1 23 _spi->format(8, 0);
yihui 0:9c6b9280c0e1 24 _spi->frequency(2000000);
yihui 1:b8cab5222fd0 25
yihui 0:9c6b9280c0e1 26 _ss = 1;
yihui 0:9c6b9280c0e1 27 }
yihui 0:9c6b9280c0e1 28
yihui 0:9c6b9280c0e1 29 void PN532_SPI::begin()
yihui 0:9c6b9280c0e1 30 {
yihui 0:9c6b9280c0e1 31
yihui 0:9c6b9280c0e1 32 }
yihui 0:9c6b9280c0e1 33
yihui 0:9c6b9280c0e1 34 void PN532_SPI::wakeup()
yihui 0:9c6b9280c0e1 35 {
yihui 0:9c6b9280c0e1 36 _ss = 0;
yihui 0:9c6b9280c0e1 37 wait_ms(2);
yihui 0:9c6b9280c0e1 38 _ss = 1;
yihui 0:9c6b9280c0e1 39 }
yihui 0:9c6b9280c0e1 40
yihui 0:9c6b9280c0e1 41 int8_t PN532_SPI::writeCommand(const uint8_t buf[], uint8_t len)
yihui 0:9c6b9280c0e1 42 {
yihui 0:9c6b9280c0e1 43 command = buf[0];
yihui 0:9c6b9280c0e1 44 writeFrame(buf, len);
yihui 1:b8cab5222fd0 45
yihui 0:9c6b9280c0e1 46 uint8_t timeout = PN532_ACK_WAIT_TIME;
yihui 0:9c6b9280c0e1 47 while (!isReady()) {
yihui 0:9c6b9280c0e1 48 wait_ms(1);
yihui 0:9c6b9280c0e1 49 timeout--;
yihui 0:9c6b9280c0e1 50 if (0 == timeout) {
yihui 0:9c6b9280c0e1 51 DMSG("Time out when waiting for ACK\n");
yihui 0:9c6b9280c0e1 52 return -2;
yihui 0:9c6b9280c0e1 53 }
yihui 0:9c6b9280c0e1 54 }
yihui 0:9c6b9280c0e1 55 if (readAckFrame()) {
yihui 0:9c6b9280c0e1 56 DMSG("Invalid ACK\n");
yihui 0:9c6b9280c0e1 57 return PN532_INVALID_ACK;
yihui 0:9c6b9280c0e1 58 }
yihui 0:9c6b9280c0e1 59 return 0;
yihui 0:9c6b9280c0e1 60 }
yihui 0:9c6b9280c0e1 61
yihui 0:9c6b9280c0e1 62 int16_t PN532_SPI::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout)
yihui 0:9c6b9280c0e1 63 {
yihui 0:9c6b9280c0e1 64 uint16_t time = 0;
yihui 0:9c6b9280c0e1 65 while (!isReady()) {
yihui 0:9c6b9280c0e1 66 wait_ms(1);
yihui 0:9c6b9280c0e1 67 time++;
yihui 0:9c6b9280c0e1 68 if (timeout > 0 && time > timeout) {
yihui 0:9c6b9280c0e1 69 return PN532_TIMEOUT;
yihui 0:9c6b9280c0e1 70 }
yihui 0:9c6b9280c0e1 71 }
yihui 1:b8cab5222fd0 72
yihui 0:9c6b9280c0e1 73 _ss = 0;
yihui 0:9c6b9280c0e1 74 wait_ms(1);
yihui 0:9c6b9280c0e1 75
yihui 0:9c6b9280c0e1 76 int16_t result;
yihui 0:9c6b9280c0e1 77 do {
yihui 0:9c6b9280c0e1 78 write(DATA_READ);
yihui 1:b8cab5222fd0 79
yihui 0:9c6b9280c0e1 80 if (0x00 != read() || // PREAMBLE
yihui 0:9c6b9280c0e1 81 0x00 != read() || // STARTCODE1
yihui 0:9c6b9280c0e1 82 0xFF != read() // STARTCODE2
yihui 1:b8cab5222fd0 83 ) {
yihui 1:b8cab5222fd0 84
yihui 0:9c6b9280c0e1 85 result = PN532_INVALID_FRAME;
yihui 0:9c6b9280c0e1 86 break;
yihui 0:9c6b9280c0e1 87 }
yihui 1:b8cab5222fd0 88
yihui 0:9c6b9280c0e1 89 uint8_t length = read();
yihui 0:9c6b9280c0e1 90 if (0 != (uint8_t)(length + read())) { // checksum of length
yihui 0:9c6b9280c0e1 91 result = PN532_INVALID_FRAME;
yihui 0:9c6b9280c0e1 92 break;
yihui 0:9c6b9280c0e1 93 }
yihui 1:b8cab5222fd0 94
yihui 0:9c6b9280c0e1 95 uint8_t cmd = command + 1; // response command
yihui 0:9c6b9280c0e1 96 if (PN532_PN532TOHOST != read() || (cmd) != read()) {
yihui 0:9c6b9280c0e1 97 result = PN532_INVALID_FRAME;
yihui 0:9c6b9280c0e1 98 break;
yihui 0:9c6b9280c0e1 99 }
yihui 1:b8cab5222fd0 100
yihui 0:9c6b9280c0e1 101 DMSG("read: ");
yihui 0:9c6b9280c0e1 102 DMSG_HEX(cmd);
yihui 1:b8cab5222fd0 103
yihui 0:9c6b9280c0e1 104 length -= 2;
yihui 0:9c6b9280c0e1 105 if (length > len) {
yihui 0:9c6b9280c0e1 106 for (uint8_t i = 0; i < length; i++) {
yihui 0:9c6b9280c0e1 107 DMSG_HEX(read()); // dump message
yihui 0:9c6b9280c0e1 108 }
yihui 0:9c6b9280c0e1 109 DMSG("\nNot enough space\n");
yihui 1:b8cab5222fd0 110 read();
yihui 0:9c6b9280c0e1 111 read();
yihui 0:9c6b9280c0e1 112 result = PN532_NO_SPACE; // not enough space
yihui 0:9c6b9280c0e1 113 break;
yihui 0:9c6b9280c0e1 114 }
yihui 1:b8cab5222fd0 115
yihui 0:9c6b9280c0e1 116 uint8_t sum = PN532_PN532TOHOST + cmd;
yihui 0:9c6b9280c0e1 117 for (uint8_t i = 0; i < length; i++) {
yihui 0:9c6b9280c0e1 118 buf[i] = read();
yihui 0:9c6b9280c0e1 119 sum += buf[i];
yihui 1:b8cab5222fd0 120
yihui 0:9c6b9280c0e1 121 DMSG_HEX(buf[i]);
yihui 0:9c6b9280c0e1 122 }
yihui 0:9c6b9280c0e1 123 DMSG("\n");
yihui 1:b8cab5222fd0 124
yihui 0:9c6b9280c0e1 125 uint8_t checksum = read();
yihui 0:9c6b9280c0e1 126 if (0 != (uint8_t)(sum + checksum)) {
yihui 0:9c6b9280c0e1 127 DMSG("checksum is not ok\n");
yihui 0:9c6b9280c0e1 128 result = PN532_INVALID_FRAME;
yihui 0:9c6b9280c0e1 129 break;
yihui 0:9c6b9280c0e1 130 }
yihui 0:9c6b9280c0e1 131 read(); // POSTAMBLE
yihui 1:b8cab5222fd0 132
yihui 0:9c6b9280c0e1 133 result = length;
yihui 0:9c6b9280c0e1 134 } while (0);
yihui 1:b8cab5222fd0 135
yihui 0:9c6b9280c0e1 136 _ss = 1;
yihui 1:b8cab5222fd0 137
yihui 0:9c6b9280c0e1 138 return result;
yihui 0:9c6b9280c0e1 139 }
yihui 0:9c6b9280c0e1 140
yihui 0:9c6b9280c0e1 141 bool PN532_SPI::isReady()
yihui 0:9c6b9280c0e1 142 {
yihui 0:9c6b9280c0e1 143 _ss = 0;
yihui 1:b8cab5222fd0 144
yihui 0:9c6b9280c0e1 145 write(STATUS_READ);
yihui 0:9c6b9280c0e1 146 uint8_t status = read() & 1;
yihui 0:9c6b9280c0e1 147 _ss = 1;
yihui 0:9c6b9280c0e1 148 return status;
yihui 0:9c6b9280c0e1 149 }
yihui 0:9c6b9280c0e1 150
yihui 0:9c6b9280c0e1 151 void PN532_SPI::writeFrame(const uint8_t buf[], uint8_t len)
yihui 0:9c6b9280c0e1 152 {
yihui 0:9c6b9280c0e1 153 _ss = 0;
yihui 0:9c6b9280c0e1 154 wait_ms(2); // wake up PN532
yihui 1:b8cab5222fd0 155
yihui 0:9c6b9280c0e1 156 write(DATA_WRITE);
yihui 0:9c6b9280c0e1 157 write(PN532_PREAMBLE);
yihui 0:9c6b9280c0e1 158 write(PN532_STARTCODE1);
yihui 0:9c6b9280c0e1 159 write(PN532_STARTCODE2);
yihui 1:b8cab5222fd0 160
yihui 0:9c6b9280c0e1 161 uint8_t length = len + 1; // length of data field: TFI + DATA
yihui 0:9c6b9280c0e1 162 write(length);
yihui 0:9c6b9280c0e1 163 write(~length + 1); // checksum of length
yihui 1:b8cab5222fd0 164
yihui 0:9c6b9280c0e1 165 write(PN532_HOSTTOPN532);
yihui 0:9c6b9280c0e1 166 uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA
yihui 1:b8cab5222fd0 167
yihui 0:9c6b9280c0e1 168 DMSG("write: ");
yihui 1:b8cab5222fd0 169
yihui 0:9c6b9280c0e1 170 for (uint8_t i = 0; i < len; i++) {
yihui 0:9c6b9280c0e1 171 write(buf[i]);
yihui 0:9c6b9280c0e1 172 sum += buf[i];
yihui 1:b8cab5222fd0 173
yihui 0:9c6b9280c0e1 174 DMSG_HEX(buf[i]);
yihui 0:9c6b9280c0e1 175 }
yihui 1:b8cab5222fd0 176
yihui 0:9c6b9280c0e1 177 uint8_t checksum = ~sum + 1; // checksum of TFI + DATA
yihui 0:9c6b9280c0e1 178 write(checksum);
yihui 0:9c6b9280c0e1 179 write(PN532_POSTAMBLE);
yihui 1:b8cab5222fd0 180
yihui 1:b8cab5222fd0 181 _ss = 1;
yihui 1:b8cab5222fd0 182
yihui 0:9c6b9280c0e1 183 DMSG("\n");
yihui 0:9c6b9280c0e1 184 }
yihui 0:9c6b9280c0e1 185
yihui 0:9c6b9280c0e1 186 int8_t PN532_SPI::readAckFrame()
yihui 0:9c6b9280c0e1 187 {
yihui 0:9c6b9280c0e1 188 const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0};
yihui 1:b8cab5222fd0 189
yihui 0:9c6b9280c0e1 190 uint8_t ackBuf[sizeof(PN532_ACK)];
yihui 1:b8cab5222fd0 191
yihui 0:9c6b9280c0e1 192 _ss = 0;
yihui 0:9c6b9280c0e1 193 wait_ms(1);
yihui 0:9c6b9280c0e1 194 write(DATA_READ);
yihui 1:b8cab5222fd0 195
yihui 0:9c6b9280c0e1 196 for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) {
yihui 0:9c6b9280c0e1 197 ackBuf[i] = read();
yihui 0:9c6b9280c0e1 198 }
yihui 1:b8cab5222fd0 199
yihui 0:9c6b9280c0e1 200 _ss = 1;
yihui 1:b8cab5222fd0 201
yihui 0:9c6b9280c0e1 202 return memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK));
yihui 0:9c6b9280c0e1 203 }