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
lib/PN532.cpp
- Committer:
- marius90
- Date:
- 2013-11-15
- Revision:
- 0:f07ca719c12e
File content as of revision 0:f07ca719c12e:
#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; }