src/spi.c
changeset 55 04c625712e35
child 56 3b837eaf1b6d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/spi.c	Fri Apr 04 00:26:16 2014 +0300
@@ -0,0 +1,106 @@
+#define SPI_DDR     DDRB
+#define SPI_PORT    PORTB
+
+#define SPI_SCK     PORTB5
+#define SPI_MISO    PORTB4
+#define SPI_MOSI    PORTB3
+#define SPI_SS      PORTB2
+
+/* State */
+#define SPI_COUNT   1
+
+static char spi_rx[SPI_COUNT], spi_tx[SPI_COUNT];
+
+enum {
+    SPI_DORD_MSB        = 0b0,
+
+    SPI_DORD            = SPI_DORD_MSB
+};
+
+enum {
+    SPI_CPOL_RISING     = 0b0,
+
+    SPI_CPOL            = SPI_CPOL_RISING
+};
+
+enum {
+    SPI_CPHA_SAMPLE     = 0b0,
+
+    SPI_CPHA            = SPI_CPHA_SAMPLE
+};
+
+enum {
+    SPI_CLOCK_4         = 0b000,
+    SPI_CLOCK_16        = 0b001,
+    SPI_CLOCK_64        = 0b010,
+    SPI_CLOCK_128       = 0b011,
+
+    SPI_CLOCK           = SPI_CLOCK_16
+};
+
+/*
+ * Initialize in SPI master mode.
+ */
+void spi_init ()
+{
+    // set output modes
+    sbi(&SPI_DDR, SPI_SCK);     // out
+    sbi(&SPI_DDR, SPI_MOSI);    // out
+    sbi(&SPI_DDR, SPI_SS);      // out
+
+    // initialize bus
+    sbi(&SPI_PORT, SPI_SS);     // high (off)
+
+    // set mode
+    SPCR = (
+            // SPI Interrupt Enable
+            (0b0 << SPIE) // disable
+
+            // SPI Enable
+        |   (0b1 << SPE) // enable
+            
+            // Data Order
+        |   (SPI_DORD << DORD)
+
+            // Master/Slave Select
+        |   (0b1 << MSTR) // master
+
+            // Clock Polarity
+        |   (SPI_CPOL << CPOL)
+
+            // Clock Phase
+        |   (SPI_CPHA << CPHA)
+            
+            // SPI Clock Rate Select
+        |   ((SPI_CLOCK & 0b11) << SPR0)
+    );
+    SPSR = (
+            (((SPI_CLOCK & 0b100) >> 2) << SPI2X)
+    );
+}
+
+/*
+ * Perform an SPI bus update.
+ */
+void spi_update ()
+{
+    char i;
+    char *rx = spi_rx + SPI_COUNT, *tx = spi_tx + SPI_COUNT;
+
+    // start of packet
+    cbi(&SPI_PORT, SPI_SS); // low
+
+    for (i = SPI_COUNT; i > 0; i--) {
+        // out
+        SPDR = *--tx;
+
+        // sync
+        while (!tbi(&SPSR, SPIF))
+            ;
+
+        *--rx = SPDR;
+    }
+
+    // end of packet
+    sbi(&SPI_PORT, SPI_SS); // high
+}