diff --git a/module_spi_master/src/spi_master.h b/module_spi_master/src/spi_master.h
index 4567f5f..f0b7f82 100644
--- a/module_spi_master/src/spi_master.h
+++ b/module_spi_master/src/spi_master.h
@@ -3,19 +3,6 @@
// University of Illinois/NCSA Open Source License posted in
// LICENSE.txt and at
-///////////////////////////////////////////////////////////////////////////////
-//
-// SPI master
-//
-// SPI modes:
-// +------+------+------+-----------+
-// | Mode | CPOL | CPHA | Supported |
-// +------+------+------+-----------+
-// | 0 | 0 | 0 | Yes |
-// | 1 | 0 | 1 | Yes |
-// | 2 | 1 | 0 | Yes |
-// | 3 | 1 | 1 | Yes |
-// +------+------+------+-----------+
#ifndef _spi_master_h_
#define _spi_master_h_
@@ -30,13 +17,39 @@
* which depend on how many slaves there are and how they're connected.
*
*/
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// SPI master
+//
+// SPI modes:
+// +------+------+------+-----------+
+// | Mode | CPOL | CPHA | Supported |
+// +------+------+------+-----------+
+// | 0 | 0 | 0 | Yes |
+// | 1 | 0 | 1 | Yes |
+// | 2 | 1 | 0 | Yes |
+// | 3 | 1 | 1 | Yes |
+// +------+------+------+-----------+
+typedef enum
+{
+ SPI_MASTER_MODE_0,
+ SPI_MASTER_MODE_1,
+ SPI_MASTER_MODE_2,
+ SPI_MASTER_MODE_3
+}spi_master_mode_t;
+
typedef struct spi_master_interface
{
clock blk1;
clock blk2;
out buffered port:8 mosi;
out buffered port:8 sclk;
- in buffered port:8 miso;
+ in buffered port:8 ?miso; //nullable resource (if you are "just" sending you can supply NULL here)
+ spi_master_mode_t master_mode;
+ unsigned mosi_high; //SD-CARD compatible setting, pulls MOSI high if true
+
+ unsigned sclk_val; //Internal usage will be set by init
} spi_master_interface;
#ifdef __spi_conf_h_exists__
@@ -55,24 +68,6 @@ typedef struct spi_master_interface
#define DEFAULT_SPI_CLOCK_DIV 8
#endif
-#ifndef SPI_MASTER_MODE
-/** This constant defines the SPI mode that the master operates in.
- *
- * See :ref:`sec_spi_modes` for the modes supported by this master, and
- * the clock polarity and phase used for each.
- */
-#define SPI_MASTER_MODE 3
-#endif
-
-#ifndef SPI_MASTER_SD_CARD_COMPAT
-/** This constant defines the behaviour of the SPI master while receiving data.
- *
- * When defined as '1' the SPI master will drive the MOSI line high before
- * clocking data in from the slave on the MISO line, as required by SD cards.
- */
-#define SPI_MASTER_SD_CARD_COMPAT 0
-#endif
-
/** Configure ports and clocks, clearing port buffers.
*
* Must be called before any SPI data input or output functions are used.
@@ -190,4 +185,6 @@ void spi_master_out_word(spi_master_interface &spi_if, unsigned int data);
*/
void spi_master_out_buffer(spi_master_interface &spi_if, const unsigned char buffer[], int num_bytes);
+char spi_master_out_in_byte(spi_master_interface &spi_if, unsigned char data);
+
#endif
diff --git a/module_spi_master/src/spi_master.xc b/module_spi_master/src/spi_master.xc
index 5202e13..f165727 100644
--- a/module_spi_master/src/spi_master.xc
+++ b/module_spi_master/src/spi_master.xc
@@ -9,34 +9,56 @@
#include
#include "spi_master.h"
-unsigned sclk_val;
-
void spi_master_init(spi_master_interface &spi_if, int spi_clock_div)
{
// configure ports and clock blocks
configure_clock_rate(spi_if.blk1, 100, spi_clock_div);
-#if SPI_MASTER_MODE == 0
- set_port_no_inv(spi_if.sclk);
- configure_out_port(spi_if.sclk, spi_if.blk1, 0);
- sclk_val = 0x55;
-#elif SPI_MASTER_MODE == 1
- set_port_inv(spi_if.sclk); // invert port and values used
- configure_out_port(spi_if.sclk, spi_if.blk1, 1);
- sclk_val = 0xAA;
-#elif SPI_MASTER_MODE == 2
- set_port_inv(spi_if.sclk); // invert port and values used
- configure_out_port(spi_if.sclk, spi_if.blk1, 0);
- sclk_val = 0x55;
-#elif SPI_MASTER_MODE == 3
- set_port_no_inv(spi_if.sclk);
- configure_out_port(spi_if.sclk, spi_if.blk1, 1);
- sclk_val = 0xAA;
-#else
- #error "Unrecognised SPI mode."
-#endif
+
+ //Save some function call space ...
+ unsigned out_port_conf;
+ unsigned inv;
+
+ switch(spi_if.master_mode)
+ {
+ case 0:
+ inv=0;
+ out_port_conf=0;
+ spi_if.sclk_val = 0x55;
+ break;
+
+ case 1:
+ inv=1;
+ out_port_conf=1;
+ spi_if.sclk_val = 0xAA;
+ break;
+
+ case 2:
+ inv=1;
+ out_port_conf=0;
+ spi_if.sclk_val = 0x55;
+ break;
+
+ case 3:
+ inv=0;
+ out_port_conf=1;
+ spi_if.sclk_val = 0xAA;
+ break;
+ }
+
+ if(inv)
+ {
+ set_port_inv(spi_if.sclk);
+ }
+ else
+ {
+ set_port_no_inv(spi_if.sclk);
+ }
+
+ configure_out_port(spi_if.sclk, spi_if.blk1, out_port_conf);
configure_clock_src(spi_if.blk2, spi_if.sclk);
configure_out_port(spi_if.mosi, spi_if.blk2, 0);
- configure_in_port(spi_if.miso, spi_if.blk2);
+ if(!isnull(spi_if.miso))
+ configure_in_port(spi_if.miso, spi_if.blk2);
clearbuf(spi_if.mosi);
clearbuf(spi_if.sclk);
start_clock(spi_if.blk1);
@@ -48,7 +70,7 @@ void spi_master_shutdown(spi_master_interface &spi_if)
set_clock_off(spi_if.blk2);
set_clock_off(spi_if.blk1);
set_port_use_off(spi_if.mosi);
- set_port_use_off(spi_if.miso);
+ if(!isnull(spi_if.miso)) set_port_use_off(spi_if.miso);
set_port_use_off(spi_if.sclk);
}
@@ -57,15 +79,15 @@ static inline unsigned char spi_master_in_byte_internal(spi_master_interface &sp
// MSb-first bit order - SPI standard
unsigned x;
- if (SPI_MASTER_SD_CARD_COMPAT)
+ if (spi_if.mosi_high)
{
spi_if.mosi <: 0xFF; // Pull MOSI high
}
- clearbuf(spi_if.miso);
- spi_if.sclk <: sclk_val;
- spi_if.sclk <: sclk_val;
+ if(!isnull(spi_if.miso)) clearbuf(spi_if.miso);
+ spi_if.sclk <: spi_if.sclk_val;
+ spi_if.sclk <: spi_if.sclk_val;
sync(spi_if.sclk);
- spi_if.miso :> x;
+ if(!isnull(spi_if.miso)) spi_if.miso :> x;
return bitrev(x) >> 24;
}
@@ -108,27 +130,63 @@ static inline void spi_master_out_byte_internal(spi_master_interface &spi_if, un
// MSb-first bit order - SPI standard
unsigned x = bitrev(data) >> 24;
-#if (SPI_MASTER_MODE == 0 || SPI_MASTER_MODE == 2) // modes where CPHA == 0
- // handle first bit
- asm("setc res[%0], 8" :: "r"(spi_if.mosi)); // reset port
- spi_if.mosi <: x; // output first bit
- asm("setc res[%0], 8" :: "r"(spi_if.mosi)); // reset port
- asm("setc res[%0], 0x200f" :: "r"(spi_if.mosi)); // set to buffering
- asm("settw res[%0], %1" :: "r"(spi_if.mosi), "r"(32)); // set transfer width to 32
- stop_clock(spi_if.blk2);
- configure_clock_src(spi_if.blk2, spi_if.sclk);
- configure_out_port(spi_if.mosi, spi_if.blk2, x);
- start_clock(spi_if.blk2);
- // output remaining data
- spi_if.mosi <: (x >> 1);
-#else
- spi_if.mosi <: x;
-#endif
- spi_if.sclk <: sclk_val;
- spi_if.sclk <: sclk_val;
+ if(spi_if.master_mode==0 || spi_if.master_mode==2)
+ { // handle first bit
+ asm("setc res[%0], 8" :: "r"(spi_if.mosi)); // reset port
+ spi_if.mosi <: x; // output first bit
+ asm("setc res[%0], 8" :: "r"(spi_if.mosi)); // reset port
+ asm("setc res[%0], 0x200f" :: "r"(spi_if.mosi)); // set to buffering
+ asm("settw res[%0], %1" :: "r"(spi_if.mosi), "r"(32)); // set transfer width to 32
+ stop_clock(spi_if.blk2);
+ configure_clock_src(spi_if.blk2, spi_if.sclk);
+ configure_out_port(spi_if.mosi, spi_if.blk2, x);
+ start_clock(spi_if.blk2);
+
+ // output remaining data
+ spi_if.mosi <: (x >> 1);
+ }
+ else
+ {
+ spi_if.mosi <: x;
+ }
+
+ spi_if.sclk <: spi_if.sclk_val;
+ spi_if.sclk <: spi_if.sclk_val;
+ sync(spi_if.sclk);
+ if(!isnull(spi_if.miso)) spi_if.miso :> void;
+}
+
+unsigned char spi_master_out_in_byte(spi_master_interface &spi_if, unsigned char data)
+{
+ // MSb-first bit order - SPI standard
+ unsigned x = bitrev(data) >> 24;
+
+ if (spi_if.master_mode == 0 || spi_if.master_mode == 2) // modes where CPHA == 0
+ { // handle first bit
+ asm("setc res[%0], 8" :: "r"(spi_if.mosi)); // reset port
+ spi_if.mosi <: x; // output first bit
+ asm("setc res[%0], 8" :: "r"(spi_if.mosi)); // reset port
+ asm("setc res[%0], 0x200f" :: "r"(spi_if.mosi)); // set to buffering
+ asm("settw res[%0], %1" :: "r"(spi_if.mosi), "r"(32)); // set transfer width to 32
+ stop_clock(spi_if.blk2);
+ configure_clock_src(spi_if.blk2, spi_if.sclk);
+ configure_out_port(spi_if.mosi, spi_if.blk2, x);
+ start_clock(spi_if.blk2);
+
+ // output remaining data
+ spi_if.mosi <: (x >> 1);
+ }
+ else
+ {
+ spi_if.mosi <: x;
+ }
+ spi_if.sclk <: spi_if.sclk_val;
+ spi_if.sclk <: spi_if.sclk_val;
sync(spi_if.sclk);
- spi_if.miso :> void;
+ unsigned char data_out;
+ spi_if.miso :> data_out;
+ return data_out;
}
void spi_master_out_byte(spi_master_interface &spi_if, unsigned char data)