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_I2C.cpp Source File

PN532_I2C.cpp

00001 ////////////////////////////////////////////////////////////////////////////////
00002 // pn532 i2c interface for mbed platform
00003 // 
00004 // by dotnfc@163.com
00005 // 2016/09/10 18:16:00
00006 
00007 #include "PN532_I2C.h"
00008 #include "PN532_debug.h"
00009 #include "Arduino.h"
00010 
00011 
00012 PN532_I2C::PN532_I2C(mbed::I2C &wire)
00013 {
00014     _wire = &wire;
00015     command = 0;
00016 }
00017 
00018 void PN532_I2C::begin()
00019 {
00020 
00021 }
00022 
00023 void PN532_I2C::wakeup()
00024 {
00025 
00026 }
00027 
00028 int8_t PN532_I2C::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
00029 {
00030     command = header[0];
00031     MyBuffer <uint8_t> tBuf;
00032         
00033     tBuf.put (PN532_PREAMBLE);
00034     tBuf.put (PN532_STARTCODE1);
00035     tBuf.put (PN532_STARTCODE2);
00036     
00037     uint8_t length = hlen + blen + 1;   // length of data field: TFI + DATA
00038     tBuf.put (length);
00039     tBuf.put (~length + 1);                 // checksum of length
00040     
00041     tBuf.put (PN532_HOSTTOPN532);
00042     uint8_t sum = PN532_HOSTTOPN532;    // sum of TFI + DATA
00043     
00044     DMSG("write: ");
00045        
00046     for (uint8_t i = 0; i < hlen; i++) {
00047         tBuf.put (header[i]);
00048         sum += header[i];
00049         DMSG_HEX(header[i]);
00050     }
00051 
00052     for (uint8_t i = 0; i < blen; i++) {
00053         tBuf.put (body[i]);
00054         sum += body[i];
00055         DMSG_HEX(body[i]);
00056     }
00057   
00058     uint8_t checksum = ~sum + 1;            // checksum of TFI + DATA
00059     tBuf.put (checksum);
00060     tBuf.put (PN532_POSTAMBLE);
00061     
00062     _wire->write (PN532_I2C_ADDRESS, (const char *)tBuf.head(), tBuf.getLength());
00063     
00064     DMSG("\n");
00065 
00066     return readAckFrame();
00067 }
00068 
00069 
00070 int16_t PN532_I2C::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout)
00071 {
00072     uint8_t stat;
00073     uint16_t tlen = 256 + 5;
00074     MyBuffer <uint8_t> tBuf(256 + 5);
00075     Timer timer;
00076     if (timeout !=0) {
00077         timer.start();
00078     }
00079     
00080     do {
00081         if (_wire->read (PN532_I2C_ADDRESS, (char *)&stat, 1) == 0) {
00082 
00083             if (stat & 1) { // check the STATUS byte
00084                 wait_ms (2);
00085                 
00086                 if (tlen > len)
00087                     tlen = len;
00088                     
00089                 if (_wire->read(PN532_I2C_ADDRESS, (char *)tBuf.head(), tlen) == 0) {
00090                     break;
00091                 }
00092             }
00093         }
00094         
00095         if (0 != timeout) {
00096             if (timer.read_ms() > timeout) {
00097                 timer.stop ();
00098                 return -1;
00099             }
00100         }
00101 
00102     } while (1); 
00103     
00104     if (0x01 != tBuf.get()      ||       // STATUS
00105         0x00 != tBuf.get()      ||       // PREAMBLE
00106         0x00 != tBuf.get()      ||       // STARTCODE1
00107         0xFF != tBuf.get()               // STARTCODE2
00108         ) {
00109         
00110         return PN532_INVALID_FRAME;
00111     }
00112     
00113     uint8_t length = tBuf.get();
00114     if (0 != (uint8_t)(length + tBuf.get())) {   // checksum of length
00115         return PN532_INVALID_FRAME;
00116     }
00117     
00118     uint8_t cmd = command + 1;               // response command
00119     if (PN532_PN532TOHOST != tBuf.get() || (cmd) != tBuf.get()) {
00120         return PN532_INVALID_FRAME;
00121     }
00122     
00123     length -= 2;
00124     if (length > len) {
00125         return PN532_NO_SPACE;  // not enough space
00126     }
00127     
00128     DMSG("read:  ");
00129     DMSG_HEX(cmd);
00130     
00131     uint8_t sum = PN532_PN532TOHOST + cmd;
00132     for (uint8_t i = 0; i < length; i++) {
00133         buf[i] = tBuf.get();
00134         sum += buf[i];
00135         
00136         DMSG_HEX(buf[i]);
00137     }
00138     DMSG("\n");
00139     
00140     uint8_t checksum = tBuf.get();
00141     if (0 != (uint8_t)(sum + checksum)) {
00142         DMSG("checksum is not ok\n");
00143         return PN532_INVALID_FRAME;
00144     }
00145     //tBuf.get();         // POSTAMBLE
00146     
00147     return length;
00148 }
00149 
00150 int8_t PN532_I2C::readAckFrame()
00151 {
00152     const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0};
00153     MyBuffer <uint8_t> ackBuf(sizeof(PN532_ACK) + 1);
00154     
00155     Timer timer;
00156     timer.start();
00157     
00158     do {
00159         // if (_wire->requestFrom(PN532_I2C_ADDRESS,  sizeof(PN532_ACK) + 1)) {
00160         if (_wire->read(PN532_I2C_ADDRESS, (char *)ackBuf.head(), sizeof(PN532_ACK) + 1) == 0) {
00161             if (ackBuf.get() & 1) {  // check first byte --- status
00162                 break;         // PN532 is ready
00163             }
00164         }
00165 
00166         if (timer.read_ms() > PN532_ACK_WAIT_TIME) {
00167             DMSG("Time out when waiting for ACK\n");
00168             timer.stop ();
00169             return PN532_TIMEOUT;
00170         }
00171     } while (1);
00172     
00173     for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) {
00174         if (ackBuf.get() != PN532_ACK[i])
00175             return PN532_INVALID_ACK;
00176     }
00177     
00178     return 0;
00179 }