--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/spi.c Wed Oct 08 23:20:19 2014 +0300
@@ -0,0 +1,88 @@
+#include "spi.h"
+
+static char spi_rx[SPI_COUNT], spi_tx[SPI_COUNT];
+
+static const enum spi_dord spi_dord = SPI_DORD;
+static const enum spi_cpol spi_cpol = SPI_CPOL;
+static const enum spi_cpha spi_cpha = SPI_CPHA;
+static const enum spi_clock spi_clock = SPI_CLOCK;
+
+void spi_init ()
+{
+ // set output modes
+ sbi(SPI_DDR, SPI_SCK); // out
+ cbi(SPI_DDR, SPI_MISO); // in
+ 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)
+ );
+}
+
+byte spi_readwrite (byte value)
+{
+ // out
+ SPDR = value;
+
+ // sync
+ while (!tbi(&SPSR, SPIF))
+ ;
+
+ return SPDR;
+}
+/*
+ * 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--) {
+ *--rx = spi_readwrite(*--tx);
+ }
+
+ // end of packet
+ sbi(SPI_PORT, SPI_SS); // high
+}
+
+void spi_set (byte index, byte value)
+{
+ spi_tx[index] = value;
+}
+
+byte spi_get (byte index)
+{
+ return spi_rx[index];
+}
+