src/spi.c
author Tero Marttila <terom@paivola.fi>
Wed, 08 Oct 2014 23:20:19 +0300
changeset 10 d485c5b3ab4d
permissions -rw-r--r--
spi: mixture of old spi_update and new spi_readwrite interfaces, using spi mode3 for adxl345
#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];
}