AppNearMe µNFC stack for the NXP PN532 chip License: You can use the stack free of charge to prototype with mbed; if you want to use the stack with your commercial product, get in touch!

Dependents:   IOT_sensor_nfc AppNearMe_MuNFC_PN532_Test p2p_nfc_test NFCMoodLamp ... more

License

You can use the stack free of charge to prototype with mbed; if you want to use the stack with your commercial product, get in touch!

PN532/MuNFCMbedPlatform.cpp

Committer:
AppNearMe
Date:
2013-01-15
Revision:
13:6f98851e025b
Parent:
11:5be631376e5b

File content as of revision 13:6f98851e025b:

/*
 MuNFCMbedPlatform.cpp
 Copyright (c) Donatien Garnier 2012
 donatien.garnier@appnearme.com
 http://www.appnearme.com/
 */

#include "mbed.h"

#include "MuNFCConfig.h"
#include "munfc/nfc_config.h"

#if MUNFC_RTOS
#include "rtos/rtos.h"
#endif

InterruptIn* nfc_irq_pin_isr;
DigitalOut* nfc_cs_pin;
SPI* nfc_spi;

extern "C"
{
#if NFC_CONTROLLER == PN512
#include "munfc/platform/pn512_platform.h"
#elif NFC_CONTROLLER == PN532
#include "munfc/platform/pn532_platform.h"
#endif
#include "munfc/platform/platform_rtos.h"

#if NFC_CONTROLLER == PN512
void pn512_io_init()
{
  nfc_irq_pin_isr->rise(pn512_irq);
  *nfc_cs_pin = 1;
}

/*
 * Get the IRQ pin's state
 */
bool pn512_irq_pin_get()
{
  //return (nfc_irq_pin_int->read() ? true : false);
  return (nfc_irq_pin_isr->read() ? true : false);
}

/*
 * Set the CS pin to 0 (active low)
 */
void pn512_cs_set()
{
  *nfc_cs_pin = 0;
}

/*
 * Set the CS pin to 1 (active high)
 */
void pn512_cs_clear()
{
  *nfc_cs_pin = 1;
}

/*
 * You MUST call pn512_irq() on each raising front of IRQ pin
 */
#endif

#if NFC_CONTROLLER == PN532
/*
 * Init
 */
void pn532_io_init(void)
{
  nfc_irq_pin_isr->mode(PullUp);
  nfc_irq_pin_isr->fall(pn532_irq);
  *nfc_cs_pin = 1;
}

/*
 * Get the IRQ pin's state
 */
bool pn532_irq_pin_get(void)
{
  return (nfc_irq_pin_isr->read() ? false : true);
}

/*
 * Set the CS pin to 0 (active low)
 */
void pn532_cs_set(void)
{
  *nfc_cs_pin = 0;
}

/*
 * Set the CS pin to 1 (active high)
 */
void pn532_cs_clear(void)
{
  *nfc_cs_pin = 1;
}

/*
 * You MUST call pn532_irq() on each falling front of IRQ pin
 */
#endif

#if MUNFC_RTOS
struct rtos_semaphore //To be defined by impl
{
  Semaphore* s;
};

struct rtos_semaphore* rtos_semaphore_new() //Should return NULL if fails
{
  struct rtos_semaphore* pSem;
  pSem = new struct rtos_semaphore;
  pSem->s = new Semaphore(1);
  pSem->s->wait(osWaitForever);
  return pSem;
}

int rtos_semaphore_produce(struct rtos_semaphore* pSem)
{
    pSem->s->release();
    return OK;
}

int rtos_semaphore_consume(struct rtos_semaphore* pSem, int timeout)
{
    int resid;
    if(timeout == -1)
    {
      resid = pSem->s->wait(osWaitForever);
    }
    else
    {
      resid = pSem->s->wait(timeout);
    }
    if(resid>0)
    {
      while( pSem->s->wait(0) > 0 );
      return OK;
    }
    else
    {
      return ERR_TIMEOUT;
    }
}
#else
struct rtos_semaphore //To be defined by impl
{
    volatile int p;
};

struct rtos_semaphore* rtos_semaphore_new() //Should return NULL if fails
{
  struct rtos_semaphore* pSem;
  pSem = new struct rtos_semaphore;
  pSem->p = 1;
  return pSem;
}

//Will only be called from ISR
int rtos_semaphore_produce(struct rtos_semaphore* pSem)
{
    pSem->p++;
    return OK;
}

void ___voidf(void)
{

}

int rtos_semaphore_consume(struct rtos_semaphore* pSem, int timeout)
{
   if(timeout == -1)
    {
      while(!pSem->p)
      {
        __WFI();
      }
      pSem->p--;
    }
    else if(timeout == 0)
    {
      if(pSem->p)
      {
        pSem->p--;
      }
      else
      {
        return ERR_TIMEOUT;
      }
    }
    else
    {
      Timer t;
      t.start();
      Ticker t_isr;
      t_isr.attach_us(&___voidf, 1000); //Just to generate an interrupt periodically
      while(!pSem->p)
      {
        __WFI();
        if(t.read_ms()>=timeout)
        {
            return ERR_TIMEOUT;
        }
      }
      pSem->p--;
    }
    return OK;
}
#endif


//These functions must be implemented for each platform

#if NFC_CONTROLLER == PN512
/*
 * Initialize SPI
 */
int pn512_spi_init()
{
  nfc_spi->format(8, 3);
  nfc_spi->frequency(10000000); //To change to 10000000
  return 0;
}
#endif

#if NFC_CONTROLLER == PN532
/*
 * Initialize SPI
 */
int pn532_spi_init()
{
  nfc_spi->format(8, 0);
  nfc_spi->frequency(5000000);
  return 0;
}
#endif

#define reverse(x) ( (x & 0x01) << 7 \
                    | (x & 0x02) << 5 \
                    | (x & 0x04) << 3 \
                    | (x & 0x08) << 1 \
                    | (x & 0x10) >> 1 \
                    | (x & 0x20) >> 3 \
                    | (x & 0x40) >> 5 \
                    | (x & 0x80) >> 7 )

/*
 * After skipping outSkip bytes, write outLen bytes
 * After skipping inSkip bytes, read inLen bytes
 * This will generate MAX(outSkip + outLen, inSkip + inLen) transfers on the SPI bus
 */
int spi_transfer(uint8_t* outBuf, size_t outLen, size_t outSkip, uint8_t* inBuf,
    size_t inLen, size_t inSkip)
{
  int len;
  int writeb;
  int readb;
  int outPos;
  int inPos;

  outPos = inPos = 0;

  len =
      (outSkip + outLen) > (inSkip + inLen) ? (outSkip + outLen) :
          (inSkip + inLen);

  while (len--)
  {
    if (outSkip)
    {
      writeb = 0x00;
      outSkip--;
    }
    else if (outPos < outLen)
    {
      writeb = outBuf[outPos];
      outPos++;
    }
    else
    {
      writeb = 0x00;
    }

#if NFC_CONTROLLER == PN532
    writeb = reverse(writeb);
#endif

    readb = nfc_spi->write(writeb);

#if NFC_CONTROLLER == PN532
    readb = reverse(readb);
#endif

    if (inSkip)
    {
      inSkip--;
    }
    else if (inPos < inLen)
    {
      inBuf[inPos] = readb;
      inPos++;
    }
  }
  return 0;
}

/*
 * Write outLen bytes
 */
int spi_write(uint8_t* outBuf, size_t outLen)
{
  return spi_transfer(outBuf, outLen, 0, (uint8_t*) NULL, 0, 0);
}

/*
 * Read inLen bytes
 */
int spi_read(uint8_t* inBuf, size_t inLen)
{
  return spi_transfer((uint8_t*) NULL, 0, 0, inBuf, inLen, 0);
}

/*
 * Skip len bytes
 */
int spi_skip(size_t len)
{
  return spi_transfer((uint8_t*) NULL, 0, len, (uint8_t*) NULL, 0, len);
}

}