A very simple software SPI library for the MAX32630FTHR board. It was designed to support the max31865 and RadioHead libraries I ported for my Rocket mbed project.

Dependents:   Rocket

Files at this revision

API Documentation at this revision

Comitter:
danjulio
Date:
Sun Jun 11 04:04:19 2017 +0000
Commit message:
Initial commit

Changed in this revision

swspi.cpp Show annotated file Show diff for this revision Revisions of this file
swspi.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 8a4db0f083fc swspi.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/swspi.cpp	Sun Jun 11 04:04:19 2017 +0000
@@ -0,0 +1,125 @@
+// Software (bit-banged) SPI Module supporting two modes.
+// Each mode consists of a CS and CPHA mode 
+//
+
+#include <swspi.h>
+#include "mbed.h"
+
+
+swspi::swspi(PinName mosiPin, PinName misoPin, PinName sckPin, PinName ss1Pin, PinName ss2Pin)
+{
+    mosiP = new DigitalOut(mosiPin);
+    misoP = new DigitalIn(misoPin);
+    sckP = new DigitalOut(sckPin);
+    ss1P = new DigitalOut(ss1Pin);
+    ss2P = new DigitalOut(ss2Pin);
+}
+
+void swspi::init()
+{
+    sckP->write(0);
+    mosiP->write(0);
+    ss1P->write(1);
+    ss2P->write(1);
+}
+
+uint8_t swspi::spiRead(uint8_t reg, int cpha, int ss)
+{
+    uint8_t val;
+    
+    _spi_mutex.lock();
+    _cpha = cpha;
+    _ss = ss;
+    _setSlaveSelect(0);
+    _transfer(reg & ~SPI_WRITE_MASK); // Send the address with the write mask off
+    val = _transfer(0); // The written value is ignored, reg value is read
+    _setSlaveSelect(1);
+    _spi_mutex.unlock();
+    
+    return val;
+}
+
+uint8_t swspi::spiWrite(uint8_t reg, uint8_t val, int cpha, int ss)
+{
+    uint8_t status = 0;
+    
+    _spi_mutex.lock();
+    _cpha = cpha;
+    _ss = ss;
+    _setSlaveSelect(0);
+    status = _transfer(reg | SPI_WRITE_MASK); // Send the address with the write mask on
+    _transfer(val); // New value follows
+    _setSlaveSelect(1);
+    _spi_mutex.unlock();
+    
+    return status;
+}
+
+uint8_t swspi::spiBurstRead(uint8_t reg, uint8_t* dest, uint8_t len, int cpha, int ss)
+{
+    uint8_t status = 0;
+    
+    _spi_mutex.lock();
+    _cpha = cpha;
+    _ss = ss;
+    _setSlaveSelect(0);
+    status = _transfer(reg & ~SPI_WRITE_MASK); // Send the start address with the write mask off
+    while (len--)
+        *dest++ = _transfer(0);
+    _setSlaveSelect(1);
+    _spi_mutex.unlock();
+    
+    return status;
+}
+
+uint8_t swspi::spiBurstWrite(uint8_t reg, const uint8_t* src, uint8_t len, int cpha, int ss)
+{
+    uint8_t status = 0;
+    
+    _spi_mutex.lock();
+    _cpha = cpha;
+    _ss = ss;
+    _setSlaveSelect(0);
+    status = _transfer(reg | SPI_WRITE_MASK); // Send the start address with the write mask on
+    while (len--)
+        _transfer(*src++);
+    _setSlaveSelect(1);
+    _spi_mutex.unlock();
+    
+    return status;
+}
+
+void swspi::_setSlaveSelect(int v)
+{
+    if (_ss == 1)
+      ss1P->write(v);
+    else
+      ss2P->write(v);
+}
+
+uint8_t swspi::_transfer(uint8_t v)
+{
+    uint8_t reply = 0;
+
+    if (_cpha == 0) {
+        // Sample on rising clock edge
+        for (int i=7; i>=0; i--) {
+            reply <<= 1;
+            mosiP->write( (v & (1<<i)) != 0 ? 1 : 0 );
+            sckP->write(1);
+            if (misoP->read() == 1) reply |= 1;
+            sckP->write(0);
+        }
+    } else {
+        // Sample on falling clock edge
+        for (int i=7; i>=0; i--) {
+            reply <<= 1;
+            sckP->write(1);
+            mosiP->write( (v & (1<<i)) != 0 ? 1 : 0 );
+            sckP->write(0);
+            if (misoP->read() == 1) reply |= 1;
+        }
+    }
+
+    return reply;
+}
diff -r 000000000000 -r 8a4db0f083fc swspi.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/swspi.h	Sun Jun 11 04:04:19 2017 +0000
@@ -0,0 +1,84 @@
+// Software (bit-banged) SPI Module supporting two CPHA modes and two
+// chip select signals.  Yields to allow use by different threads.
+//
+
+#ifndef sw_spi_h
+#define sw_spi_h
+
+#include "mbed.h"
+#include <stdint.h>
+
+// This is the bit in the SPI address that marks it as a write
+#define SPI_WRITE_MASK 0x80
+
+
+/////////////////////////////////////////////////////////////////////
+/// \class swspi swspi.h <swspi.h>
+/// \brief bit-banged SPI
+
+class swspi
+{
+public:
+    /// Constructor
+    /// \param[in] mosiPin pin number for MOSI
+    /// \param[in] misoPin pin number for MISO
+    /// \param[in] sckPin pin number for SCK
+    /// \param[in] ss1Pin pin number for Slave Select 1
+    /// \param[in] ss2Pin pin number for Slave Select 2
+    swspi(PinName mosiPin, PinName misoPin, PinName sckPin, PinName ss1Pin, PinName ss2Pin);
+
+    /// Initialise the Driver transport hardware and software.
+    /// Make sure the Driver is properly configured before calling init().
+    void           init();
+
+    /// Reads a single register from the SPI device
+    /// \param[in] reg Register number
+    /// \return The value of the register
+    uint8_t        spiRead(uint8_t reg, int cpha, int ss);
+
+    /// Writes a single byte to the SPI device
+    /// \param[in] reg Register number
+    /// \param[in] val The value to write
+    /// \return Some devices return a status byte during the first data transfer. This byte is returned.
+    ///  it may or may not be meaningfule depending on the the type of device being accessed.
+    uint8_t           spiWrite(uint8_t reg, uint8_t val, int cpha, int ss);
+
+    /// Reads a number of consecutive registers from the SPI device using burst read mode
+    /// \param[in] reg Register number of the first register
+    /// \param[in] dest Array to write the register values to. Must be at least len bytes
+    /// \param[in] len Number of bytes to read
+    /// \return Some devices return a status byte during the first data transfer. This byte is returned.
+    ///  it may or may not be meaningfule depending on the the type of device being accessed.
+    uint8_t           spiBurstRead(uint8_t reg, uint8_t* dest, uint8_t len, int cpha, int ss);
+
+    /// Write a number of consecutive registers using burst write mode
+    /// \param[in] reg Register number of the first register
+    /// \param[in] src Array of new register values to write. Must be at least len bytes
+    /// \param[in] len Number of bytes to write
+    /// \return Some devices return a status byte during the first data transfer. This byte is returned.
+    ///  it may or may not be meaningfule depending on the the type of device being accessed.
+    uint8_t           spiBurstWrite(uint8_t reg, const uint8_t* src, uint8_t len, int cpha, int ss);
+
+protected:
+
+    void _setSlaveSelect(int v);
+    uint8_t _transfer(uint8_t v);
+    
+    /// Pins
+    DigitalOut* mosiP;
+    DigitalIn* misoP;
+    DigitalOut* sckP;
+    DigitalOut* ss1P;
+    DigitalOut* ss2P;
+    
+    /// The current transfer data phase
+    int                 _cpha;
+    
+    /// The current transfer slave select
+    uint8_t             _ss;
+    
+    // Access control
+    Mutex               _spi_mutex;
+};
+
+#endif