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

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;
}