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

PN532_HSU.cpp

00001 ////////////////////////////////////////////////////////////////////////////////
00002 // pn532 hsu interface for mbed platform
00003 // 
00004 // by dotnfc@163.com
00005 // 2016/09/10 18:16:00
00006 
00007 #include "PN532_HSU.h"
00008 #include "PN532_debug.h"
00009 
00010 
00011 PN532_HSU::PN532_HSU(HardwareSerial &serial)
00012 {
00013     _serial = &serial;
00014     command = 0;
00015 }
00016 
00017 void PN532_HSU::begin()
00018 {
00019     _serial->baud(115200);
00020 }
00021 
00022 void PN532_HSU::wakeup()
00023 {
00024     const uint8_t wakeup_cmd[] = { 0x55, 0x55, 0x00, 0x00, 0x00,     0x00, 0x00, 0xFF, 0x05, 0xFB,  0xD4, 0x14, 0x01, 0x00, 0x01,  0x16, 0x00 };
00025     _serial->write(wakeup_cmd, sizeof(wakeup_cmd));
00026     
00027     delay (50);
00028     
00029     /** dump serial buffer */
00030     if(_serial->readable()){
00031         DMSG("Dump sperial buffer: ");
00032     }
00033     while(_serial->readable()){
00034         uint8_t ret = _serial->getc();
00035         DMSG_HEX(ret);
00036     }
00037     DMSG("\n");
00038 }
00039 
00040 int8_t PN532_HSU::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
00041 {
00042     /** dump serial buffer */
00043     if(_serial->readable()){
00044         DMSG("Dump sperial buffer: ");
00045     }
00046     while(_serial->readable()){
00047         uint8_t ret = _serial->getc();
00048         DMSG_HEX(ret);
00049     }
00050     DMSG("\n");
00051     
00052     command = header[0];
00053     
00054     _serial->write(PN532_PREAMBLE);
00055     _serial->write(PN532_STARTCODE1);
00056     _serial->write(PN532_STARTCODE2);
00057     
00058     uint8_t length = hlen + blen + 1;   // length of data field: TFI + DATA
00059     _serial->write(length);
00060     _serial->write(~length + 1);         // checksum of length
00061     
00062     _serial->write(PN532_HOSTTOPN532);
00063     uint8_t sum = PN532_HOSTTOPN532;    // sum of TFI + DATA
00064 
00065     DMSG("\nWrite: ");
00066     
00067     _serial->write(header, hlen);
00068     for (uint8_t i = 0; i < hlen; i++) {
00069         sum += header[i];
00070 
00071         DMSG_HEX(header[i]);
00072     }
00073 
00074     _serial->write(body, blen);
00075     for (uint8_t i = 0; i < blen; i++) {
00076         sum += body[i];
00077 
00078         DMSG_HEX(body[i]);
00079     }
00080     
00081     uint8_t checksum = ~sum + 1;            // checksum of TFI + DATA
00082     _serial->write(checksum);
00083     _serial->write(PN532_POSTAMBLE);
00084 
00085     delay (50);
00086     return readAckFrame();
00087 }
00088 
00089 int16_t PN532_HSU::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout)
00090 {
00091     uint8_t tmp[3];
00092     
00093     delay(100);
00094     
00095     DMSG("\nRead:  ");
00096     
00097     /** Frame Preamble and Start Code */
00098     if(receive(tmp, 3, timeout)<=0){
00099         return PN532_TIMEOUT;
00100     }
00101     if(0 != tmp[0] || 0!= tmp[1] || 0xFF != tmp[2]){
00102         DMSG("Preamble error");
00103         return PN532_INVALID_FRAME;
00104     }
00105     
00106     /** receive length and check */
00107     uint8_t length[2];
00108     if(receive(length, 2, timeout) <= 0){
00109         return PN532_TIMEOUT;
00110     }
00111     if( 0 != (uint8_t)(length[0] + length[1]) ){
00112         DMSG("Length error\n");
00113         return PN532_INVALID_FRAME;
00114     }
00115     length[0] -= 2;
00116     if( length[0] > len){
00117         return PN532_NO_SPACE;
00118     }
00119     
00120     /** receive command byte */
00121     uint8_t cmd = command + 1;               // response command
00122     if(receive(tmp, 2, timeout) <= 0){
00123         return PN532_TIMEOUT;
00124     }
00125     if( PN532_PN532TOHOST != tmp[0] || cmd != tmp[1]){
00126         DMSG("Command error\n");
00127         return PN532_INVALID_FRAME;
00128     }
00129     
00130     if(receive(buf, length[0], timeout) != length[0]){
00131         return PN532_TIMEOUT;
00132     }
00133     uint8_t sum = PN532_PN532TOHOST + cmd;
00134     for(uint8_t i=0; i<length[0]; i++){
00135         sum += buf[i];
00136     }
00137     
00138     /** checksum and postamble */
00139     if(receive(tmp, 2, timeout) <= 0){
00140         return PN532_TIMEOUT;
00141     }
00142     if( 0 != (uint8_t)(sum + tmp[0]) || 0 != tmp[1] ){
00143         DMSG("Checksum error\n");
00144         return PN532_INVALID_FRAME;
00145     }
00146     
00147     DMSG ("\n");
00148     return length[0];
00149 }
00150 
00151 int8_t PN532_HSU::readAckFrame()
00152 {
00153     const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0};
00154     uint8_t ackBuf[sizeof(PN532_ACK)];
00155     
00156     delay(100);
00157     
00158     DMSG("\nAck: ");
00159     
00160     if( receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0 ){
00161         DMSG("Timeout\n");
00162         return PN532_TIMEOUT;
00163     }
00164     
00165     if( memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK)) ){
00166         DMSG("Invalid\n");
00167         return PN532_INVALID_ACK;
00168     }
00169     return 0;
00170 }
00171 
00172 /**
00173     @brief receive data .
00174     @param buf --> return value buffer.
00175            len --> length expect to receive.
00176            timeout --> time of reveiving
00177     @retval number of received bytes, 0 means no data received.
00178 */
00179 int8_t PN532_HSU::receive(uint8_t *buf, int len, uint16_t timeout)
00180 {
00181   int read_bytes = 0;
00182   int ret;
00183   Timer tmr_hsu;
00184   unsigned long start_millis;
00185     
00186   tmr_hsu.start();
00187   while (read_bytes < len) {
00188     start_millis = tmr_hsu.read_ms(); // millis();
00189     do {
00190       ret = _serial->getc();
00191       if (ret >= 0) {
00192         break;
00193      }
00194      delay(10);
00195     } while((timeout == 0) || ((tmr_hsu.read_ms() /* millis() */ - start_millis ) < timeout));
00196     
00197     if (ret < 0) {
00198         if(read_bytes){
00199             tmr_hsu.stop ();
00200             return read_bytes;
00201         }else{
00202             tmr_hsu.stop ();
00203             return PN532_TIMEOUT;
00204         }
00205     }
00206     buf[read_bytes] = (uint8_t)ret;
00207     DMSG_HEX(ret);
00208     read_bytes++;
00209   }
00210   
00211   tmr_hsu.stop ();
00212   return read_bytes;
00213 }