PN532 Driver library This library provides an abstract API to drive the pn532 nfc chip, with I2C/HSU/SPI interface. Its based on the Seeed Studio's Arduino version.

Dependents:   PN532_ReadUid Nfctest2

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PN532_SPI.cpp Source File

PN532_SPI.cpp

00001 ////////////////////////////////////////////////////////////////////////////////
00002 // pn532 spi interface for mbed platform
00003 // 
00004 // by dotnfc@163.com
00005 // 2016/09/10 18:16:00
00006 
00007 #include "PN532_SPI.h"
00008 #include "PN532_debug.h"
00009 
00010 #define STATUS_READ     2
00011 #define DATA_WRITE      1
00012 #define DATA_READ       3
00013 
00014 PN532_SPI::PN532_SPI(SPI &spi, PinName ss) : _ss(ss)
00015 {
00016     command = 0;
00017     _spi = &spi;
00018     _spi->format(8, 0);
00019     _spi->frequency(2000000);
00020 
00021     _ss  = 1;
00022 }
00023 
00024 PN532_SPI::PN532_SPI(SPI *spi, PinName ss) : _ss(ss)
00025 {
00026     command = 0;
00027     _spi = spi;
00028     _spi->format(8, 0);
00029     _spi->frequency(2000000);
00030 
00031     _ss  = 1;
00032 }
00033 
00034 void PN532_SPI::begin()
00035 {
00036 
00037 }
00038 
00039 void PN532_SPI::wakeup()
00040 {
00041     _ss = 0;
00042     wait_ms(2);
00043     _ss = 1;
00044 }
00045 
00046 int8_t PN532_SPI::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
00047 {
00048     command = header[0];
00049     writeFrame(header, hlen, body, blen);
00050     
00051     Timer timer;
00052     timer.start();
00053 
00054     while (!isReady()) {
00055         if (timer.read_ms() > PN532_ACK_WAIT_TIME) {
00056             DMSG("Time out when waiting for ACK\n");
00057             timer.stop ();
00058             return -2;
00059         }
00060     }
00061     if (readAckFrame()) {
00062         DMSG("Invalid ACK\n");
00063         return PN532_INVALID_ACK;
00064     }
00065     return 0;
00066 }
00067 
00068 int16_t PN532_SPI::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout)
00069 {
00070     Timer timer;
00071     if (timeout > 0)
00072         timer.start();
00073     
00074     while (!isReady()) {
00075         
00076         if (timeout > 0){
00077             if (timer.read_ms() > timeout) {
00078                 timer.stop();
00079                 return PN532_TIMEOUT;
00080             }
00081         }
00082     }
00083 
00084     _ss = 0;
00085     wait_ms(1);
00086 
00087     int16_t result;
00088     do {
00089         write(DATA_READ);
00090 
00091         if (0x00 != read()      ||       // PREAMBLE
00092                 0x00 != read()  ||       // STARTCODE1
00093                 0xFF != read()           // STARTCODE2
00094            ) {
00095 
00096             result = PN532_INVALID_FRAME;
00097             break;
00098         }
00099 
00100         uint8_t length = read();
00101         if (0 != (uint8_t)(length + read())) {   // checksum of length
00102             result = PN532_INVALID_FRAME;
00103             break;
00104         }
00105 
00106         uint8_t cmd = command + 1;               // response command
00107         if (PN532_PN532TOHOST != read() || (cmd) != read()) {
00108             result = PN532_INVALID_FRAME;
00109             break;
00110         }
00111 
00112         DMSG("read:  ");
00113         DMSG_HEX(cmd);
00114 
00115         length -= 2;
00116         if (length > len) {
00117             for (uint8_t i = 0; i < length; i++) {
00118                 DMSG_HEX(read());                 // dump message
00119             }
00120             DMSG("\nNot enough space\n");
00121             read();
00122             read();
00123             result = PN532_NO_SPACE;  // not enough space
00124             break;
00125         }
00126 
00127         uint8_t sum = PN532_PN532TOHOST + cmd;
00128         for (uint8_t i = 0; i < length; i++) {
00129             buf[i] = read();
00130             sum += buf[i];
00131 
00132             DMSG_HEX(buf[i]);
00133         }
00134         DMSG("\n");
00135 
00136         uint8_t checksum = read();
00137         if (0 != (uint8_t)(sum + checksum)) {
00138             DMSG("checksum is not ok\n");
00139             result = PN532_INVALID_FRAME;
00140             break;
00141         }
00142         read();         // POSTAMBLE
00143 
00144         result = length;
00145     } while (0);
00146 
00147     _ss = 1;
00148 
00149     return result;
00150 }
00151 
00152 bool PN532_SPI::isReady()
00153 {
00154     _ss = 0;
00155 
00156     write(STATUS_READ);
00157     uint8_t status = read() & 1;
00158     _ss = 1;
00159     return status;
00160 }
00161 
00162 void PN532_SPI::writeFrame(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
00163 {
00164     _ss = 0;
00165     wait_ms(2);               // wake up PN532
00166 
00167     write(DATA_WRITE);
00168     write(PN532_PREAMBLE);
00169     write(PN532_STARTCODE1);
00170     write(PN532_STARTCODE2);
00171 
00172     uint8_t length = hlen + blen + 1;   // length of data field: TFI + DATA
00173     write(length);
00174     write(~length + 1);         // checksum of length
00175 
00176     write(PN532_HOSTTOPN532);
00177     uint8_t sum = PN532_HOSTTOPN532;    // sum of TFI + DATA
00178 
00179     DMSG("write: ");
00180 
00181     for (uint8_t i = 0; i < hlen; i++) {
00182         write(header[i]);
00183         sum += header[i];
00184 
00185         DMSG_HEX(header[i]);
00186     }
00187     for (uint8_t i = 0; i < blen; i++) {
00188         write(body[i]);
00189         sum += body[i];
00190         
00191         DMSG_HEX(header[i]);
00192     }
00193 
00194     uint8_t checksum = ~sum + 1;        // checksum of TFI + DATA
00195     write(checksum);
00196     write(PN532_POSTAMBLE);
00197 
00198     _ss = 1;
00199 
00200     DMSG("\n");
00201 }
00202 
00203 int8_t PN532_SPI::readAckFrame()
00204 {
00205     const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0};
00206 
00207     uint8_t ackBuf[sizeof(PN532_ACK)];
00208 
00209     _ss = 0;
00210     wait_ms(1);
00211     write(DATA_READ);
00212 
00213     for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) {
00214         ackBuf[i] = read();
00215     }
00216 
00217     _ss = 1;
00218 
00219     return memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK));
00220 }