nxp pn532 NFC SPI initiator code, with all functions minimized and made as fast as possible (code for target is also there, you just need to change the functions in the main). Code advises are welcome, i am an electronist not a programmer
Diff: lib/PN532.cpp
- Revision:
- 0:f07ca719c12e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/PN532.cpp Fri Nov 15 12:58:57 2013 +0000 @@ -0,0 +1,279 @@ +#include "mbed.h" +#include "PN532.h" +#include "string.h" + +#define PN532_PACK_BUFF_SIZE 64 +uint8_t pn532_packetbuffer[PN532_PACK_BUFF_SIZE]; + +uint8_t pn532ack[] = { + 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00 +}; +uint8_t pn532response_firmwarevers[] = { + 0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03 +}; + +PN532::PN532(PinName mosi, PinName miso, PinName sclk, PinName ss) +{ + _spi = new SPI(mosi, miso, sclk); + _spi->frequency(5000000); + _spi->format(8, 0); + _ss = new DigitalOut(ss); + *_ss = 1; +} + +void PN532::begin(void) +{ + _spi->frequency(5000000); + _spi->format(8, 0); + pn532_packetbuffer[0] = PN532_FIRMWAREVERSION; + printf("begin"); + /*Ignore response!*/ + sendCommandCheckAck(pn532_packetbuffer, 1); +} + +uint32_t PN532::getFirmwareVersion(void) +{ + uint32_t response; + + pn532_packetbuffer[0] = PN532_FIRMWAREVERSION; + + if (!sendCommandCheckAck(pn532_packetbuffer, 1)) + return 0; + + //Read data packet + read(pn532_packetbuffer, 12); + //Check some basic stuff + if (0 != strncmp((char *)pn532_packetbuffer, (char *)pn532response_firmwarevers, 6)) { + return 0; + } + response = pn532_packetbuffer[6]; + response <<= 8; + response |= pn532_packetbuffer[7]; + response <<= 8; + response |= pn532_packetbuffer[8]; + response <<= 8; + response |= pn532_packetbuffer[9]; + return response; +} + +bool PN532::SAMConfig(void) +{ + pn532_packetbuffer[0] = PN532_SAMCONFIGURATION; + pn532_packetbuffer[1] = 0x01; // normal mode; + pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second + pn532_packetbuffer[3] = 0x01; // use IRQ pin! + + if (! sendCommandCheckAck(pn532_packetbuffer, 4)) + return false; + + // read data packet + read(pn532_packetbuffer, 8); + + return (pn532_packetbuffer[5] == 0x15); +} + + +uint32_t PN532::configurePeerAsInitiator(void) +{ + pn532_packetbuffer[0] = PN532_INJUMPFORDEP; + pn532_packetbuffer[1] = 0x01; //Active Mode + pn532_packetbuffer[2] = 2;// Use 1 or 2 424 kb/s. + pn532_packetbuffer[3] = 0x01; //Indicates Optional Payload is present + + //Polling request payload + pn532_packetbuffer[4] = 0x00; + pn532_packetbuffer[5] = 0xFF; + pn532_packetbuffer[6] = 0xFF; + pn532_packetbuffer[7] = 0x00; + pn532_packetbuffer[8] = 0x00; + + if (!sendCommandCheckAck(pn532_packetbuffer, 9)) { + return false; + } + // read data packet + read(pn532_packetbuffer, 19+6); + + // check the response + + return (pn532_packetbuffer[7] == 0x00); //No error + +} + +uint32_t PN532::configurePeerAsTarget() +{ + uint8_t pbuffer[38] = { + PN532_TGINITASTARGET, + 0x00, + 0x08, 0x00, //SENS_RES + 0x12, 0x34, 0x56, //NFCID1 + 0x40, //SEL_RES + 0x01, 0xFE, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, // POL_RES + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xFF, 0xFF, + 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, //NFCID3t: Change this to desired value + 0x00, 0x00 //Length of general and historical bytes + }; + for(uint8_t i = 0; i < 38; i ++) { + pn532_packetbuffer[i] = pbuffer[i]; + } + + if (! sendCommandCheckAck(pn532_packetbuffer, 38)) { + return false; + + } + // read data packet + read(pn532_packetbuffer, 18+6); + return (pn532_packetbuffer[23] == 0x00); //No error as it received all response +} + +bool PN532::initiatorTxRx(char* dataOut,char* dataIn) +{ + pn532_packetbuffer[0] = PN532_INDATAEXCHANGE; + pn532_packetbuffer[1] = 0x01; //Target 01 + + for(uint8_t iter=(2+0); iter<(2+16); iter++) { + pn532_packetbuffer[iter] = dataOut[iter-2]; //pack the data to send to target + } + + if (! sendCommandCheckAck(pn532_packetbuffer, 18)) + return false; + + // read data packet + read(pn532_packetbuffer, 18+6); + + for(uint8_t iter=8; iter<(8+16); iter++) { + dataIn[iter-8] = pn532_packetbuffer[iter]; //data received from target + } + + return (pn532_packetbuffer[7] == 0x00); //No error +} + +uint32_t PN532::targetTxRx(char* dataOut,char* dataIn) +{ + /* Receiving from Initiator */ + pn532_packetbuffer[0] = PN532_TGGETDATA; + if (! sendCommandCheckAck(pn532_packetbuffer, 1)) + return false; + + // read data packet + read(pn532_packetbuffer, 18+6); + + for(uint8_t iter=8; iter<(8+16); iter++) { + dataIn[iter-8] = pn532_packetbuffer[iter]; //data received from initiator + } + + /* Sending to Initiator */ + if(pn532_packetbuffer[7] == 0x00) { //If no errors in receiving, send data. + pn532_packetbuffer[0] = PN532_TGSETDATA; + for(uint8_t iter=(1+0); iter<(1+16); iter++) { + pn532_packetbuffer[iter] = dataOut[iter-1]; //pack the data to send to target + } + + if (! sendCommandCheckAck(pn532_packetbuffer, 17)) + return false; + + // read data packet + read(pn532_packetbuffer, 2+6); + + return (pn532_packetbuffer[7] == 0x00); //No error + } + return true; +} + +bool PN532::sendCommandCheckAck(uint8_t* cmd, uint8_t cmd_len, uint16_t timeout) +{ + uint16_t timer = 0; + // write the command + writeCommand(cmd, cmd_len); + // Wait for chip to say it's ready! + + + while (readSpiStatus() != PN532_SPI_READY) { + + if (timeout != 0) { + timer+=10; + if (timer > timeout) + return false; + } + wait_ms(10); + } + + + // read acknowledgement + if (!checkSpiAck()) { + return false; + } + + timer = 0; + // Wait for chip to say its ready! + while (readSpiStatus() != PN532_SPI_READY) { + + if (timeout != 0) { + timer+=10; + if (timer > timeout) + return false; + } + wait_ms(10); + } + return true; // ack'd command +} + +void PN532::writeCommand(uint8_t buf[], uint8_t len) +{ + uint8_t checksum; + len++; + checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2; + + *_ss=0; + + write(PN532_SPI_DATAWRITE); + write(PN532_PREAMBLE); + write(PN532_STARTCODE1); + write(PN532_STARTCODE2); + write(len); + uint8_t cmdlen_1=~len + 1; + write(cmdlen_1); + write(PN532_HOSTTOPN532); + checksum += PN532_HOSTTOPN532; + + for (uint8_t i=0; i<len-1; i++) { + write(buf[i]); + checksum += buf[i]; + } + uint8_t checksum_1=~checksum; + write(checksum_1); + write(PN532_POSTAMBLE); + *_ss = 1; +} + +uint8_t PN532::read(uint8_t buff[], uint8_t n) +{ + uint8_t response; + *_ss = 0; + write(PN532_SPI_DATAREAD); + for (uint8_t i=0; i < n; i ++) { + wait_ms(1); + buff[i] = read(); + } + *_ss= 1; + response = read(); + return response; +} + + +bool PN532::checkSpiAck(void) +{ + uint8_t ackbuff[6]; + read(ackbuff, 6); + return (0 == strncmp((char *)ackbuff, (char *)pn532ack, 6)); +} + +uint8_t PN532::readSpiStatus(void) +{ + *_ss = 0; + wait_ms(2); + write(PN532_SPI_STATREAD); + uint8_t status = read(); + *_ss=1; + return status; +}