| | /* spis.c D.J.Whale 19/07/2014 |
---|
| | * |
---|
| | * Software SPI driver built on top of gpio |
---|
| | */ |
---|
| | |
---|
| | |
---|
| | /***** INCLUDES *****/ |
---|
| | |
---|
| | #include <stdio.h> |
---|
| | #include <stdlib.h> |
---|
| | #include <string.h> |
---|
| | |
---|
| | #include "system.h" |
---|
| | #include "spi.h" |
---|
| | #include "gpio.h" |
---|
| | #include "delay.h" |
---|
| | |
---|
| | |
---|
| | /***** MACROS *****/ |
---|
| | |
---|
| | #define CLOCK_ACTIVE() gpio_write(config.sclk, config.cpol?0:1) |
---|
| | #define CLOCK_IDLE() gpio_write(config.sclk, config.cpol?1:0) |
---|
| | |
---|
| | #define SELECTED() gpio_write(config.cs, config.spol?1:0) |
---|
| | #define NOT_SELECTED() gpio_write(config.cs, config.spol?0:1) |
---|
| | |
---|
| | //TODO: Posix specific, won't work on Arduino |
---|
| | #define FAIL(msg) do { \ |
---|
| | fprintf(stderr, "%s", msg); \ |
---|
| | exit(-1); \ |
---|
| | } while (0) |
---|
| | |
---|
| | |
---|
| | /***** VARIABLES *****/ |
---|
| | |
---|
| | static SPI_CONFIG config; |
---|
| | |
---|
| | |
---|
| | void spi_init_defaults(void) |
---|
| | { |
---|
| | #define CS 7 //CE1 |
---|
| | #define SCLK 11 |
---|
| | #define MOSI 10 |
---|
| | #define MISO 9 |
---|
| | |
---|
| | /* ms */ |
---|
| | #define TSETTLE (1) /* us settle */ |
---|
| | #define THOLD (1) /* us hold */ |
---|
| | #define TFREQ (1) /* us half clock */ |
---|
| | |
---|
| | SPI_CONFIG defaultConfig = {CS, SCLK, MOSI, MISO, SPI_SPOL0, SPI_CPOL0, SPI_CPHA0, |
---|
| | TSETTLE, THOLD, TFREQ}; |
---|
| | |
---|
| | spi_init(&defaultConfig); |
---|
| | } |
---|
| | |
---|
| | |
---|
| | void spi_init(SPI_CONFIG* pConfig) |
---|
| | { |
---|
| | /* It's a standalone library, so init GPIO also */ |
---|
| | gpio_init(); |
---|
| | memcpy(&config, pConfig, sizeof(SPI_CONFIG)); |
---|
| | |
---|
| | //TODO: Implement CPHA1 |
---|
| | if (config.cpha != 0) |
---|
| | { |
---|
| | FAIL("error: CPHA 1 not yet supported"); |
---|
| | } |
---|
| | |
---|
| | gpio_setout(config.sclk); |
---|
| | CLOCK_IDLE(); |
---|
| | |
---|
| | gpio_setout(config.mosi); |
---|
| | gpio_low(config.mosi); |
---|
| | gpio_setin(config.miso); |
---|
| | |
---|
| | gpio_setout(config.cs); |
---|
| | NOT_SELECTED(); |
---|
| | } |
---|
| | |
---|
| | |
---|
| | void spi_finished(void) |
---|
| | { |
---|
| | gpio_setin(config.mosi); |
---|
| | gpio_setin(config.sclk); |
---|
| | gpio_setin(config.cs); |
---|
| | } |
---|
| | |
---|
| | |
---|
| | void spi_select(void) |
---|
| | { |
---|
| | SELECTED(); |
---|
| | delayus(config.tSettle); |
---|
| | } |
---|
| | |
---|
| | |
---|
| | void spi_deselect(void) |
---|
| | { |
---|
| | NOT_SELECTED(); |
---|
| | delayus(config.tSettle); |
---|
| | } |
---|
| | |
---|
| | |
---|
| | int spi_byte(uint8_t txbyte) |
---|
| | { |
---|
| | uint8_t rxbyte = 0; |
---|
| | uint8_t bitno; |
---|
| | uint8_t bit ; |
---|
| | |
---|
| | //TODO: Implement CPHA1 |
---|
| | |
---|
| | for (bitno=0; bitno<8; bitno++) |
---|
| | { |
---|
| | /* Transmit MSB first */ |
---|
| | bit = ((txbyte & 0x80) != 0x00); |
---|
| | txbyte <<= 1; |
---|
| | gpio_write(config.mosi, bit); |
---|
| | delayus(config.tSettle); |
---|
| | CLOCK_ACTIVE(); |
---|
| | delayus(config.tHold); |
---|
| | delayus(config.tFreq); |
---|
| | |
---|
| | /* Read MSB first */ |
---|
| | bit = gpio_read(config.miso); |
---|
| | rxbyte = (rxbyte<<1) | bit; |
---|
| | |
---|
| | CLOCK_IDLE(); |
---|
| | delayus(config.tFreq); |
---|
| | } |
---|
| | return rxbyte; |
---|
| | } |
---|
| | |
---|
| | |
---|
| | void spi_frame(uint8_t* pTx, uint8_t* pRx, uint8_t count) |
---|
| | { |
---|
| | uint8_t tx = 0; |
---|
| | uint8_t rx; |
---|
| | |
---|
| | while (count > 0) |
---|
| | { |
---|
| | if (pTx != NULL) |
---|
| | { |
---|
| | tx = *(pTx++); |
---|
| | } |
---|
| | rx = spi_byte(tx); |
---|
| | if (pRx != NULL) |
---|
| | { |
---|
| | *(pRx++) = rx; |
---|
| | } |
---|
| | count--; |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | |
---|
| | /***** END OF FILE *****/ |
---|
| | |
---|
| | |