diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/avr/spi_master.c | 123 | ||||
-rw-r--r-- | drivers/avr/spi_master.h | 10 |
2 files changed, 73 insertions, 60 deletions
diff --git a/drivers/avr/spi_master.c b/drivers/avr/spi_master.c index 3f405ddf5c..32cc55c836 100644 --- a/drivers/avr/spi_master.c +++ b/drivers/avr/spi_master.c @@ -34,6 +34,10 @@ # define SPI_MISO_PIN B4 #endif +#ifndef SPI_TIMEOUT +# define SPI_TIMEOUT 100 +#endif + static pin_t currentSlavePin = NO_PIN; static uint8_t currentSlaveConfig = 0; static bool currentSlave2X = false; @@ -47,65 +51,74 @@ void spi_init(void) { SPCR = (_BV(SPE) | _BV(MSTR)); } -void spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint8_t divisor) { - if (currentSlavePin == NO_PIN && slavePin != NO_PIN) { - if (lsbFirst) { - currentSlaveConfig |= _BV(DORD); - } +bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { + if (currentSlavePin != NO_PIN || slavePin == NO_PIN) { + return false; + } - switch (mode) { - case 1: - currentSlaveConfig |= _BV(CPHA); - break; - case 2: - currentSlaveConfig |= _BV(CPOL); - break; - case 3: - currentSlaveConfig |= (_BV(CPOL) | _BV(CPHA)); - break; - } + currentSlaveConfig = 0; - uint8_t roundedDivisor = 1; - while (roundedDivisor < divisor) { - roundedDivisor <<= 1; - } + if (lsbFirst) { + currentSlaveConfig |= _BV(DORD); + } - switch (roundedDivisor) { - case 16: - currentSlaveConfig |= _BV(SPR0); - break; - case 64: - currentSlaveConfig |= _BV(SPR1); - break; - case 128: - currentSlaveConfig |= (_BV(SPR1) | _BV(SPR0)); - break; - case 2: - currentSlave2X = true; - break; - case 8: - currentSlave2X = true; - currentSlaveConfig |= _BV(SPR0); - break; - case 32: - currentSlave2X = true; - currentSlaveConfig |= _BV(SPR1); - break; - } + switch (mode) { + case 1: + currentSlaveConfig |= _BV(CPHA); + break; + case 2: + currentSlaveConfig |= _BV(CPOL); + break; + case 3: + currentSlaveConfig |= (_BV(CPOL) | _BV(CPHA)); + break; + } - SPSR |= currentSlaveConfig; - currentSlavePin = slavePin; - setPinOutput(currentSlavePin); - writePinLow(currentSlavePin); + uint16_t roundedDivisor = 1; + while (roundedDivisor < divisor) { + roundedDivisor <<= 1; + } + + switch (roundedDivisor) { + case 16: + currentSlaveConfig |= _BV(SPR0); + break; + case 64: + currentSlaveConfig |= _BV(SPR1); + break; + case 128: + currentSlaveConfig |= (_BV(SPR1) | _BV(SPR0)); + break; + case 2: + currentSlave2X = true; + break; + case 8: + currentSlave2X = true; + currentSlaveConfig |= _BV(SPR0); + break; + case 32: + currentSlave2X = true; + currentSlaveConfig |= _BV(SPR1); + break; } + + SPCR |= currentSlaveConfig; + if (currentSlave2X) { + SPSR |= _BV(SPI2X); + } + currentSlavePin = slavePin; + setPinOutput(currentSlavePin); + writePinLow(currentSlavePin); + + return true; } -spi_status_t spi_write(uint8_t data, uint16_t timeout) { +spi_status_t spi_write(uint8_t data) { SPDR = data; uint16_t timeout_timer = timer_read(); while (!(SPSR & _BV(SPIF))) { - if ((timeout != SPI_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { + if ((timer_read() - timeout_timer) >= SPI_TIMEOUT) { return SPI_STATUS_TIMEOUT; } } @@ -113,12 +126,12 @@ spi_status_t spi_write(uint8_t data, uint16_t timeout) { return SPDR; } -spi_status_t spi_read(uint16_t timeout) { +spi_status_t spi_read() { SPDR = 0x00; // Dummy uint16_t timeout_timer = timer_read(); while (!(SPSR & _BV(SPIF))) { - if ((timeout != SPI_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { + if ((timer_read() - timeout_timer) >= SPI_TIMEOUT) { return SPI_STATUS_TIMEOUT; } } @@ -126,21 +139,21 @@ spi_status_t spi_read(uint16_t timeout) { return SPDR; } -spi_status_t spi_transmit(const uint8_t *data, uint16_t length, uint16_t timeout) { +spi_status_t spi_transmit(const uint8_t *data, uint16_t length) { spi_status_t status = SPI_STATUS_ERROR; for (uint16_t i = 0; i < length; i++) { - status = spi_write(data[i], timeout); + status = spi_write(data[i]); } return status; } -spi_status_t spi_receive(uint8_t *data, uint16_t length, uint16_t timeout) { +spi_status_t spi_receive(uint8_t *data, uint16_t length) { spi_status_t status = SPI_STATUS_ERROR; for (uint16_t i = 0; i < length; i++) { - status = spi_read(timeout); + status = spi_read(); if (status > 0) { data[i] = status; @@ -155,9 +168,9 @@ void spi_stop(void) { setPinOutput(currentSlavePin); writePinHigh(currentSlavePin); currentSlavePin = NO_PIN; + SPSR &= ~(_BV(SPI2X)); SPCR &= ~(currentSlaveConfig); currentSlaveConfig = 0; - SPSR = 0; currentSlave2X = false; } } diff --git a/drivers/avr/spi_master.h b/drivers/avr/spi_master.h index 0bab2dc24e..b69c1cbd66 100644 --- a/drivers/avr/spi_master.h +++ b/drivers/avr/spi_master.h @@ -41,15 +41,15 @@ extern "C" { #endif void spi_init(void); -void spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint8_t divisor); +bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); -spi_status_t spi_write(uint8_t data, uint16_t timeout); +spi_status_t spi_write(uint8_t data); -spi_status_t spi_read(uint16_t timeout); +spi_status_t spi_read(void); -spi_status_t spi_transmit(const uint8_t *data, uint16_t length, uint16_t timeout); +spi_status_t spi_transmit(const uint8_t *data, uint16_t length); -spi_status_t spi_receive(uint8_t *data, uint16_t length, uint16_t timeout); +spi_status_t spi_receive(uint8_t *data, uint16_t length); void spi_stop(void); #ifdef __cplusplus |