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!

Files at this revision

API Documentation at this revision

Comitter:
AppNearMe
Date:
Thu Aug 16 15:35:56 2012 +0000
Parent:
4:6aa189c3aa19
Child:
7:15ca8e1584de
Commit message:
Fixes for LPC11U24 compatibility

Changed in this revision

PN532/LPC11U24/uARM/munfc.ar Show diff for this revision Revisions of this file
PN532/MuNFC.cpp Show annotated file Show diff for this revision Revisions of this file
PN532/MuNFCMbedPlatform.cpp Show annotated file Show diff for this revision Revisions of this file
Binary file PN532/LPC11U24/uARM/munfc.ar has changed
--- a/PN532/MuNFC.cpp	Wed Aug 15 13:48:43 2012 +0000
+++ b/PN532/MuNFC.cpp	Thu Aug 16 15:35:56 2012 +0000
@@ -1,109 +1,113 @@
-/*
-    MuNFC.cpp 
-    Copyright (c) Donatien Garnier 2012
-    donatien.garnier@appnearme.com
-    http://www.appnearme.com/
-*/
-
-
-#include "MuNFC.h"
-#include "MuNFCConfig.h"
-
-#include "mbed.h"
-#if MUNFC_RTOS
-#include "rtos/rtos.h"
-#endif
-
-#include "munfc/core/fwk.h"
-#include "munfc/target/event.h"
-#include "munfc/target/nfctype2.h"
-#include "munfc/target/nfctype4.h"
-#include "munfc/ndef/appnearme_ndef.h"
-#include "munfc/ndef/appnearme_ndef_tlv.h"
-
-#include <cstring> //For memcpy, strlen
-
-//TODO add handles in NFC stack to avoid ugly things like that
-//extern DigitalIn* nfc_irq_pin_int;
-extern InterruptIn* nfc_irq_pin_isr;
-extern DigitalOut* nfc_cs_pin;
-extern SPI* nfc_spi;
-
-#define SIGNAL_START 0x01
-
-MuNFC::MuNFC(char appHash[16], uint32_t version,
-    PinName mosi, PinName miso, PinName sclk, PinName cs, PinName isr) :
-   /* m_irq_pin_int(isr),*/ m_irq_pin_isr(isr), m_cs_pin(cs), m_spi(mosi, miso, sclk)
-#if MUNFC_RTOS
-  , m_pThread(NULL)//m_thread(MuNFC::staticCallback, (void*)this)
-#endif
-{
-  //nfc_irq_pin_int = &m_irq_pin_int;
-  nfc_irq_pin_isr = &m_irq_pin_isr;
-  nfc_cs_pin = &m_cs_pin;
-  nfc_spi = &m_spi;
-
-  appnearme_ndef_init(appHash, version);
-  m_eventCb.init(target_register_event_callback);
-  m_encodeCb.init(appnearme_ndef_register_encode_callback);
-  m_decodeCb.init(appnearme_ndef_register_decode_callback);
-}
-
-MuNFC::~MuNFC()
-{
-  if(m_pThread != NULL)
-  {
-    delete m_pThread;
-  }
-}
-
-bool MuNFC::init()
-{
-  if(m_pThread == NULL)
-  {
-    m_pThread = new Thread(MuNFC::staticCallback, (void*)this);
-  }
-#if NFC_CONTROLLER == PN512
-  int ret = target_nfctype2_start();
-#elif NFC_CONTROLLER == PN532
-  int ret = target_nfctype4_start();
-#endif
-  if(ret != OK)
-  {
-    return false;
-  }
-  return true;
-}
-
-#if MUNFC_RTOS
-void MuNFC::run()
-{
-  //Start NFC thread
-  m_pThread->signal_set(SIGNAL_START);
-}
-
-void MuNFC::process()
-{
-  Thread::signal_wait(SIGNAL_START);
-  do
-  {
-    poll(-1);
-  } while(true);
-}
-#endif
-
-void MuNFC::poll(int timeoutMs) //TODO add Timeout
-{
-#if NFC_CONTROLLER == PN512
-    target_nfctype2_process();
-#elif NFC_CONTROLLER == PN532
-    target_nfctype4_process();
-#endif
-}
-
-#if MUNFC_RTOS
-  /*static*/ void MuNFC::staticCallback(void const* p)
-  {
-    ((MuNFC*)p)->process();
-  }
-#endif
+/*
+    MuNFC.cpp 
+    Copyright (c) Donatien Garnier 2012
+    donatien.garnier@appnearme.com
+    http://www.appnearme.com/
+*/
+
+
+#include "MuNFC.h"
+#include "MuNFCConfig.h"
+
+#include "mbed.h"
+#if MUNFC_RTOS
+#include "rtos/rtos.h"
+#endif
+
+#include "munfc/core/fwk.h"
+#include "munfc/target/event.h"
+#include "munfc/target/nfctype2.h"
+#include "munfc/target/nfctype4.h"
+#include "munfc/ndef/appnearme_ndef.h"
+#include "munfc/ndef/appnearme_ndef_tlv.h"
+
+#include <cstring> //For memcpy, strlen
+
+//TODO add handles in NFC stack to avoid ugly things like that
+//extern DigitalIn* nfc_irq_pin_int;
+extern InterruptIn* nfc_irq_pin_isr;
+extern DigitalOut* nfc_cs_pin;
+extern SPI* nfc_spi;
+
+#define SIGNAL_START 0x01
+
+MuNFC::MuNFC(char appHash[16], uint32_t version,
+    PinName mosi, PinName miso, PinName sclk, PinName cs, PinName isr) :
+   /* m_irq_pin_int(isr),*/ m_irq_pin_isr(isr), m_cs_pin(cs), m_spi(mosi, miso, sclk)
+#if MUNFC_RTOS
+  , m_pThread(NULL)//m_thread(MuNFC::staticCallback, (void*)this)
+#endif
+{
+  //nfc_irq_pin_int = &m_irq_pin_int;
+  nfc_irq_pin_isr = &m_irq_pin_isr;
+  nfc_cs_pin = &m_cs_pin;
+  nfc_spi = &m_spi;
+
+  appnearme_ndef_init(appHash, version);
+  m_eventCb.init(target_register_event_callback);
+  m_encodeCb.init(appnearme_ndef_register_encode_callback);
+  m_decodeCb.init(appnearme_ndef_register_decode_callback);
+}
+
+MuNFC::~MuNFC()
+{
+  #if MUNFC_RTOS
+  if(m_pThread != NULL)
+  {
+    delete m_pThread;
+  }
+  #endif
+}
+
+bool MuNFC::init()
+{
+  #if MUNFC_RTOS
+  if(m_pThread == NULL)
+  {
+    m_pThread = new Thread(MuNFC::staticCallback, (void*)this, osPriorityHigh, 4*2048);
+  }
+  #endif
+#if NFC_CONTROLLER == PN512
+  int ret = target_nfctype2_start();
+#elif NFC_CONTROLLER == PN532
+  int ret = target_nfctype4_start();
+#endif
+  if(ret != OK)
+  {
+    return false;
+  }
+  return true;
+}
+
+#if MUNFC_RTOS
+void MuNFC::run()
+{
+  //Start NFC thread
+  m_pThread->signal_set(SIGNAL_START);
+}
+
+void MuNFC::process()
+{
+  Thread::signal_wait(SIGNAL_START);
+  do
+  {
+    poll(-1);
+  } while(true);
+}
+#endif
+
+void MuNFC::poll(int timeoutMs) //TODO add Timeout
+{
+#if NFC_CONTROLLER == PN512
+    target_nfctype2_process();
+#elif NFC_CONTROLLER == PN532
+    target_nfctype4_process();
+#endif
+}
+
+#if MUNFC_RTOS
+  /*static*/ void MuNFC::staticCallback(void const* p)
+  {
+    ((MuNFC*)p)->process();
+  }
+#endif
--- a/PN532/MuNFCMbedPlatform.cpp	Wed Aug 15 13:48:43 2012 +0000
+++ b/PN532/MuNFCMbedPlatform.cpp	Thu Aug 16 15:35:56 2012 +0000
@@ -1,339 +1,365 @@
-/*
- 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
-
-//DigitalIn* nfc_irq_pin_int;
-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/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->fall(pn532_irq);
-  *nfc_cs_pin = 1;
-}
-
-/*
- * Get the IRQ pin's state
- */
-bool pn532_irq_pin_get(void)
-{
-  //return (nfc_irq_pin_int->read() ? false : true);
-  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;
-  wait_us(10);
-}
-
-/*
- * 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)
-    {
-      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--;
-    }
-    printf("OK\n");
-    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);
-}
-
-}
-
+/*
+ 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
+
+//DigitalIn* nfc_irq_pin_int;
+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/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)
+{
+  #if defined( TARGET_LPC11U24 )
+  nfc_irq_pin_isr->rise(pn532_irq); //Cannot trigger on falling edge
+  #else
+  nfc_irq_pin_isr->fall(pn532_irq);
+  #endif
+  *nfc_cs_pin = 1;
+}
+
+/*
+ * Get the IRQ pin's state
+ */
+bool pn532_irq_pin_get(void)
+{
+  //return (nfc_irq_pin_int->read() ? false : true);
+  #if defined( TARGET_LPC11U24 )
+  return (nfc_irq_pin_isr->read() ? true : false);
+  #else
+  return (nfc_irq_pin_isr->read() ? false : true);
+  #endif
+}
+
+/*
+ * 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;
+  //wait_us(10);
+}
+
+/*
+ * 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;
+}
+
+DigitalOut led1(LED2);
+DigitalOut led2(LED3);
+DigitalOut led3(LED4);
+int rtos_semaphore_produce(struct rtos_semaphore* pSem)
+{
+   static int count = 0;
+   count ++;
+   if(count >= 8)
+     count = 0;
+   
+   led1 = (count&1)?1:0;    
+   led2 = (count&2)?1:0;
+   led3 = (count&4)?1:0;
+  
+    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 );
+      //printf("S\n");
+      return OK;
+    }
+    else
+    {
+      //printf("T\n");
+      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
+
+    #if defined( TARGET_LPC11U24 )
+    //wait_us(30);
+    #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);
+}
+
+}
+