src/spi.c
author Tero Marttila <terom@paivola.fi>
Thu, 29 Jan 2015 23:11:44 +0200
changeset 107 05707929ff6f
parent 56 3b837eaf1b6d
permissions -rw-r--r--
qmsk.web.async: handle HTTPExceptions
#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   2

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
}