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

Dependencies:   mbed

Committer:
marius90
Date:
Fri Nov 15 12:58:57 2013 +0000
Revision:
0:f07ca719c12e
working;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marius90 0:f07ca719c12e 1 #include "mbed.h"
marius90 0:f07ca719c12e 2 #include "PN532.h"
marius90 0:f07ca719c12e 3 #include "string.h"
marius90 0:f07ca719c12e 4
marius90 0:f07ca719c12e 5 #define PN532_PACK_BUFF_SIZE 64
marius90 0:f07ca719c12e 6 uint8_t pn532_packetbuffer[PN532_PACK_BUFF_SIZE];
marius90 0:f07ca719c12e 7
marius90 0:f07ca719c12e 8 uint8_t pn532ack[] = {
marius90 0:f07ca719c12e 9 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00
marius90 0:f07ca719c12e 10 };
marius90 0:f07ca719c12e 11 uint8_t pn532response_firmwarevers[] = {
marius90 0:f07ca719c12e 12 0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03
marius90 0:f07ca719c12e 13 };
marius90 0:f07ca719c12e 14
marius90 0:f07ca719c12e 15 PN532::PN532(PinName mosi, PinName miso, PinName sclk, PinName ss)
marius90 0:f07ca719c12e 16 {
marius90 0:f07ca719c12e 17 _spi = new SPI(mosi, miso, sclk);
marius90 0:f07ca719c12e 18 _spi->frequency(5000000);
marius90 0:f07ca719c12e 19 _spi->format(8, 0);
marius90 0:f07ca719c12e 20 _ss = new DigitalOut(ss);
marius90 0:f07ca719c12e 21 *_ss = 1;
marius90 0:f07ca719c12e 22 }
marius90 0:f07ca719c12e 23
marius90 0:f07ca719c12e 24 void PN532::begin(void)
marius90 0:f07ca719c12e 25 {
marius90 0:f07ca719c12e 26 _spi->frequency(5000000);
marius90 0:f07ca719c12e 27 _spi->format(8, 0);
marius90 0:f07ca719c12e 28 pn532_packetbuffer[0] = PN532_FIRMWAREVERSION;
marius90 0:f07ca719c12e 29 printf("begin");
marius90 0:f07ca719c12e 30 /*Ignore response!*/
marius90 0:f07ca719c12e 31 sendCommandCheckAck(pn532_packetbuffer, 1);
marius90 0:f07ca719c12e 32 }
marius90 0:f07ca719c12e 33
marius90 0:f07ca719c12e 34 uint32_t PN532::getFirmwareVersion(void)
marius90 0:f07ca719c12e 35 {
marius90 0:f07ca719c12e 36 uint32_t response;
marius90 0:f07ca719c12e 37
marius90 0:f07ca719c12e 38 pn532_packetbuffer[0] = PN532_FIRMWAREVERSION;
marius90 0:f07ca719c12e 39
marius90 0:f07ca719c12e 40 if (!sendCommandCheckAck(pn532_packetbuffer, 1))
marius90 0:f07ca719c12e 41 return 0;
marius90 0:f07ca719c12e 42
marius90 0:f07ca719c12e 43 //Read data packet
marius90 0:f07ca719c12e 44 read(pn532_packetbuffer, 12);
marius90 0:f07ca719c12e 45 //Check some basic stuff
marius90 0:f07ca719c12e 46 if (0 != strncmp((char *)pn532_packetbuffer, (char *)pn532response_firmwarevers, 6)) {
marius90 0:f07ca719c12e 47 return 0;
marius90 0:f07ca719c12e 48 }
marius90 0:f07ca719c12e 49 response = pn532_packetbuffer[6];
marius90 0:f07ca719c12e 50 response <<= 8;
marius90 0:f07ca719c12e 51 response |= pn532_packetbuffer[7];
marius90 0:f07ca719c12e 52 response <<= 8;
marius90 0:f07ca719c12e 53 response |= pn532_packetbuffer[8];
marius90 0:f07ca719c12e 54 response <<= 8;
marius90 0:f07ca719c12e 55 response |= pn532_packetbuffer[9];
marius90 0:f07ca719c12e 56 return response;
marius90 0:f07ca719c12e 57 }
marius90 0:f07ca719c12e 58
marius90 0:f07ca719c12e 59 bool PN532::SAMConfig(void)
marius90 0:f07ca719c12e 60 {
marius90 0:f07ca719c12e 61 pn532_packetbuffer[0] = PN532_SAMCONFIGURATION;
marius90 0:f07ca719c12e 62 pn532_packetbuffer[1] = 0x01; // normal mode;
marius90 0:f07ca719c12e 63 pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
marius90 0:f07ca719c12e 64 pn532_packetbuffer[3] = 0x01; // use IRQ pin!
marius90 0:f07ca719c12e 65
marius90 0:f07ca719c12e 66 if (! sendCommandCheckAck(pn532_packetbuffer, 4))
marius90 0:f07ca719c12e 67 return false;
marius90 0:f07ca719c12e 68
marius90 0:f07ca719c12e 69 // read data packet
marius90 0:f07ca719c12e 70 read(pn532_packetbuffer, 8);
marius90 0:f07ca719c12e 71
marius90 0:f07ca719c12e 72 return (pn532_packetbuffer[5] == 0x15);
marius90 0:f07ca719c12e 73 }
marius90 0:f07ca719c12e 74
marius90 0:f07ca719c12e 75
marius90 0:f07ca719c12e 76 uint32_t PN532::configurePeerAsInitiator(void)
marius90 0:f07ca719c12e 77 {
marius90 0:f07ca719c12e 78 pn532_packetbuffer[0] = PN532_INJUMPFORDEP;
marius90 0:f07ca719c12e 79 pn532_packetbuffer[1] = 0x01; //Active Mode
marius90 0:f07ca719c12e 80 pn532_packetbuffer[2] = 2;// Use 1 or 2 424 kb/s.
marius90 0:f07ca719c12e 81 pn532_packetbuffer[3] = 0x01; //Indicates Optional Payload is present
marius90 0:f07ca719c12e 82
marius90 0:f07ca719c12e 83 //Polling request payload
marius90 0:f07ca719c12e 84 pn532_packetbuffer[4] = 0x00;
marius90 0:f07ca719c12e 85 pn532_packetbuffer[5] = 0xFF;
marius90 0:f07ca719c12e 86 pn532_packetbuffer[6] = 0xFF;
marius90 0:f07ca719c12e 87 pn532_packetbuffer[7] = 0x00;
marius90 0:f07ca719c12e 88 pn532_packetbuffer[8] = 0x00;
marius90 0:f07ca719c12e 89
marius90 0:f07ca719c12e 90 if (!sendCommandCheckAck(pn532_packetbuffer, 9)) {
marius90 0:f07ca719c12e 91 return false;
marius90 0:f07ca719c12e 92 }
marius90 0:f07ca719c12e 93 // read data packet
marius90 0:f07ca719c12e 94 read(pn532_packetbuffer, 19+6);
marius90 0:f07ca719c12e 95
marius90 0:f07ca719c12e 96 // check the response
marius90 0:f07ca719c12e 97
marius90 0:f07ca719c12e 98 return (pn532_packetbuffer[7] == 0x00); //No error
marius90 0:f07ca719c12e 99
marius90 0:f07ca719c12e 100 }
marius90 0:f07ca719c12e 101
marius90 0:f07ca719c12e 102 uint32_t PN532::configurePeerAsTarget()
marius90 0:f07ca719c12e 103 {
marius90 0:f07ca719c12e 104 uint8_t pbuffer[38] = {
marius90 0:f07ca719c12e 105 PN532_TGINITASTARGET,
marius90 0:f07ca719c12e 106 0x00,
marius90 0:f07ca719c12e 107 0x08, 0x00, //SENS_RES
marius90 0:f07ca719c12e 108 0x12, 0x34, 0x56, //NFCID1
marius90 0:f07ca719c12e 109 0x40, //SEL_RES
marius90 0:f07ca719c12e 110 0x01, 0xFE, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, // POL_RES
marius90 0:f07ca719c12e 111 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
marius90 0:f07ca719c12e 112 0xFF, 0xFF,
marius90 0:f07ca719c12e 113 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, //NFCID3t: Change this to desired value
marius90 0:f07ca719c12e 114 0x00, 0x00 //Length of general and historical bytes
marius90 0:f07ca719c12e 115 };
marius90 0:f07ca719c12e 116 for(uint8_t i = 0; i < 38; i ++) {
marius90 0:f07ca719c12e 117 pn532_packetbuffer[i] = pbuffer[i];
marius90 0:f07ca719c12e 118 }
marius90 0:f07ca719c12e 119
marius90 0:f07ca719c12e 120 if (! sendCommandCheckAck(pn532_packetbuffer, 38)) {
marius90 0:f07ca719c12e 121 return false;
marius90 0:f07ca719c12e 122
marius90 0:f07ca719c12e 123 }
marius90 0:f07ca719c12e 124 // read data packet
marius90 0:f07ca719c12e 125 read(pn532_packetbuffer, 18+6);
marius90 0:f07ca719c12e 126 return (pn532_packetbuffer[23] == 0x00); //No error as it received all response
marius90 0:f07ca719c12e 127 }
marius90 0:f07ca719c12e 128
marius90 0:f07ca719c12e 129 bool PN532::initiatorTxRx(char* dataOut,char* dataIn)
marius90 0:f07ca719c12e 130 {
marius90 0:f07ca719c12e 131 pn532_packetbuffer[0] = PN532_INDATAEXCHANGE;
marius90 0:f07ca719c12e 132 pn532_packetbuffer[1] = 0x01; //Target 01
marius90 0:f07ca719c12e 133
marius90 0:f07ca719c12e 134 for(uint8_t iter=(2+0); iter<(2+16); iter++) {
marius90 0:f07ca719c12e 135 pn532_packetbuffer[iter] = dataOut[iter-2]; //pack the data to send to target
marius90 0:f07ca719c12e 136 }
marius90 0:f07ca719c12e 137
marius90 0:f07ca719c12e 138 if (! sendCommandCheckAck(pn532_packetbuffer, 18))
marius90 0:f07ca719c12e 139 return false;
marius90 0:f07ca719c12e 140
marius90 0:f07ca719c12e 141 // read data packet
marius90 0:f07ca719c12e 142 read(pn532_packetbuffer, 18+6);
marius90 0:f07ca719c12e 143
marius90 0:f07ca719c12e 144 for(uint8_t iter=8; iter<(8+16); iter++) {
marius90 0:f07ca719c12e 145 dataIn[iter-8] = pn532_packetbuffer[iter]; //data received from target
marius90 0:f07ca719c12e 146 }
marius90 0:f07ca719c12e 147
marius90 0:f07ca719c12e 148 return (pn532_packetbuffer[7] == 0x00); //No error
marius90 0:f07ca719c12e 149 }
marius90 0:f07ca719c12e 150
marius90 0:f07ca719c12e 151 uint32_t PN532::targetTxRx(char* dataOut,char* dataIn)
marius90 0:f07ca719c12e 152 {
marius90 0:f07ca719c12e 153 /* Receiving from Initiator */
marius90 0:f07ca719c12e 154 pn532_packetbuffer[0] = PN532_TGGETDATA;
marius90 0:f07ca719c12e 155 if (! sendCommandCheckAck(pn532_packetbuffer, 1))
marius90 0:f07ca719c12e 156 return false;
marius90 0:f07ca719c12e 157
marius90 0:f07ca719c12e 158 // read data packet
marius90 0:f07ca719c12e 159 read(pn532_packetbuffer, 18+6);
marius90 0:f07ca719c12e 160
marius90 0:f07ca719c12e 161 for(uint8_t iter=8; iter<(8+16); iter++) {
marius90 0:f07ca719c12e 162 dataIn[iter-8] = pn532_packetbuffer[iter]; //data received from initiator
marius90 0:f07ca719c12e 163 }
marius90 0:f07ca719c12e 164
marius90 0:f07ca719c12e 165 /* Sending to Initiator */
marius90 0:f07ca719c12e 166 if(pn532_packetbuffer[7] == 0x00) { //If no errors in receiving, send data.
marius90 0:f07ca719c12e 167 pn532_packetbuffer[0] = PN532_TGSETDATA;
marius90 0:f07ca719c12e 168 for(uint8_t iter=(1+0); iter<(1+16); iter++) {
marius90 0:f07ca719c12e 169 pn532_packetbuffer[iter] = dataOut[iter-1]; //pack the data to send to target
marius90 0:f07ca719c12e 170 }
marius90 0:f07ca719c12e 171
marius90 0:f07ca719c12e 172 if (! sendCommandCheckAck(pn532_packetbuffer, 17))
marius90 0:f07ca719c12e 173 return false;
marius90 0:f07ca719c12e 174
marius90 0:f07ca719c12e 175 // read data packet
marius90 0:f07ca719c12e 176 read(pn532_packetbuffer, 2+6);
marius90 0:f07ca719c12e 177
marius90 0:f07ca719c12e 178 return (pn532_packetbuffer[7] == 0x00); //No error
marius90 0:f07ca719c12e 179 }
marius90 0:f07ca719c12e 180 return true;
marius90 0:f07ca719c12e 181 }
marius90 0:f07ca719c12e 182
marius90 0:f07ca719c12e 183 bool PN532::sendCommandCheckAck(uint8_t* cmd, uint8_t cmd_len, uint16_t timeout)
marius90 0:f07ca719c12e 184 {
marius90 0:f07ca719c12e 185 uint16_t timer = 0;
marius90 0:f07ca719c12e 186 // write the command
marius90 0:f07ca719c12e 187 writeCommand(cmd, cmd_len);
marius90 0:f07ca719c12e 188 // Wait for chip to say it's ready!
marius90 0:f07ca719c12e 189
marius90 0:f07ca719c12e 190
marius90 0:f07ca719c12e 191 while (readSpiStatus() != PN532_SPI_READY) {
marius90 0:f07ca719c12e 192
marius90 0:f07ca719c12e 193 if (timeout != 0) {
marius90 0:f07ca719c12e 194 timer+=10;
marius90 0:f07ca719c12e 195 if (timer > timeout)
marius90 0:f07ca719c12e 196 return false;
marius90 0:f07ca719c12e 197 }
marius90 0:f07ca719c12e 198 wait_ms(10);
marius90 0:f07ca719c12e 199 }
marius90 0:f07ca719c12e 200
marius90 0:f07ca719c12e 201
marius90 0:f07ca719c12e 202 // read acknowledgement
marius90 0:f07ca719c12e 203 if (!checkSpiAck()) {
marius90 0:f07ca719c12e 204 return false;
marius90 0:f07ca719c12e 205 }
marius90 0:f07ca719c12e 206
marius90 0:f07ca719c12e 207 timer = 0;
marius90 0:f07ca719c12e 208 // Wait for chip to say its ready!
marius90 0:f07ca719c12e 209 while (readSpiStatus() != PN532_SPI_READY) {
marius90 0:f07ca719c12e 210
marius90 0:f07ca719c12e 211 if (timeout != 0) {
marius90 0:f07ca719c12e 212 timer+=10;
marius90 0:f07ca719c12e 213 if (timer > timeout)
marius90 0:f07ca719c12e 214 return false;
marius90 0:f07ca719c12e 215 }
marius90 0:f07ca719c12e 216 wait_ms(10);
marius90 0:f07ca719c12e 217 }
marius90 0:f07ca719c12e 218 return true; // ack'd command
marius90 0:f07ca719c12e 219 }
marius90 0:f07ca719c12e 220
marius90 0:f07ca719c12e 221 void PN532::writeCommand(uint8_t buf[], uint8_t len)
marius90 0:f07ca719c12e 222 {
marius90 0:f07ca719c12e 223 uint8_t checksum;
marius90 0:f07ca719c12e 224 len++;
marius90 0:f07ca719c12e 225 checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2;
marius90 0:f07ca719c12e 226
marius90 0:f07ca719c12e 227 *_ss=0;
marius90 0:f07ca719c12e 228
marius90 0:f07ca719c12e 229 write(PN532_SPI_DATAWRITE);
marius90 0:f07ca719c12e 230 write(PN532_PREAMBLE);
marius90 0:f07ca719c12e 231 write(PN532_STARTCODE1);
marius90 0:f07ca719c12e 232 write(PN532_STARTCODE2);
marius90 0:f07ca719c12e 233 write(len);
marius90 0:f07ca719c12e 234 uint8_t cmdlen_1=~len + 1;
marius90 0:f07ca719c12e 235 write(cmdlen_1);
marius90 0:f07ca719c12e 236 write(PN532_HOSTTOPN532);
marius90 0:f07ca719c12e 237 checksum += PN532_HOSTTOPN532;
marius90 0:f07ca719c12e 238
marius90 0:f07ca719c12e 239 for (uint8_t i=0; i<len-1; i++) {
marius90 0:f07ca719c12e 240 write(buf[i]);
marius90 0:f07ca719c12e 241 checksum += buf[i];
marius90 0:f07ca719c12e 242 }
marius90 0:f07ca719c12e 243 uint8_t checksum_1=~checksum;
marius90 0:f07ca719c12e 244 write(checksum_1);
marius90 0:f07ca719c12e 245 write(PN532_POSTAMBLE);
marius90 0:f07ca719c12e 246 *_ss = 1;
marius90 0:f07ca719c12e 247 }
marius90 0:f07ca719c12e 248
marius90 0:f07ca719c12e 249 uint8_t PN532::read(uint8_t buff[], uint8_t n)
marius90 0:f07ca719c12e 250 {
marius90 0:f07ca719c12e 251 uint8_t response;
marius90 0:f07ca719c12e 252 *_ss = 0;
marius90 0:f07ca719c12e 253 write(PN532_SPI_DATAREAD);
marius90 0:f07ca719c12e 254 for (uint8_t i=0; i < n; i ++) {
marius90 0:f07ca719c12e 255 wait_ms(1);
marius90 0:f07ca719c12e 256 buff[i] = read();
marius90 0:f07ca719c12e 257 }
marius90 0:f07ca719c12e 258 *_ss= 1;
marius90 0:f07ca719c12e 259 response = read();
marius90 0:f07ca719c12e 260 return response;
marius90 0:f07ca719c12e 261 }
marius90 0:f07ca719c12e 262
marius90 0:f07ca719c12e 263
marius90 0:f07ca719c12e 264 bool PN532::checkSpiAck(void)
marius90 0:f07ca719c12e 265 {
marius90 0:f07ca719c12e 266 uint8_t ackbuff[6];
marius90 0:f07ca719c12e 267 read(ackbuff, 6);
marius90 0:f07ca719c12e 268 return (0 == strncmp((char *)ackbuff, (char *)pn532ack, 6));
marius90 0:f07ca719c12e 269 }
marius90 0:f07ca719c12e 270
marius90 0:f07ca719c12e 271 uint8_t PN532::readSpiStatus(void)
marius90 0:f07ca719c12e 272 {
marius90 0:f07ca719c12e 273 *_ss = 0;
marius90 0:f07ca719c12e 274 wait_ms(2);
marius90 0:f07ca719c12e 275 write(PN532_SPI_STATREAD);
marius90 0:f07ca719c12e 276 uint8_t status = read();
marius90 0:f07ca719c12e 277 *_ss=1;
marius90 0:f07ca719c12e 278 return status;
marius90 0:f07ca719c12e 279 }