SPI is a simple yet very common protocol used for communication between logic systems.

It uses only three shared digital lines: SCK (clock signal), MISO (Master-In-Slave-Out) and MOSI (Master-Out-Slave-In) to transmit serial data. An additional fourth signal called CS (Chip Select) is required for each individual slave device.

The CS signal is used to "select" the chip that should listen for communication. Master sends data on MOSI while slaves send data on MISO.

You can find more information about the protocol itself on Wikipedia.

Dooba provides an 'spi' library that you can use to easily communicate with devices using this technology.

How to use

First, we need to add the 'spi' library to our dependencies in dfe.conf:

name: example_app
type: app
mmcu: atmega1284p
freq: 10000000
  - spi


Before we can communicate, we need to initialize the library. If we're using the substrate, this is as trivial as adding the following to our 'substrate' file:

# Use SPI
uses :spi

If, however, we want to do this without substrate, we can do it manually from our C code:

#include <spi/spi.h>

void main()
    // Initialize SPI Subsystem

    // ...

Basic communication

Because SPI is a "full-duplex" protocol (separate MOSI / MISO lines), all transfers are inherently bi-directional. This means that for every byte that we send out, we also receive one byte at the same time.

The most basic way to exchange information is through the following, which will send the byte provided as argument, and return the byte that was received:

// Perform I/O
uint8_t spi_io(uint8_t d);

Some helper methods are also provided to facilitate large transfers:

// Fast Transmit
void spi_tx(void *d, uint16_t s);

// Fast Transmit - Single Byte
void spi_tx_s(uint8_t d, uint16_t s);

// Fast Receive
void spi_rx(void *d, uint16_t s);

Just don't forget to toggle the 'CS' signal for the appropriate chip!