summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/avr/spi_master.c123
-rw-r--r--drivers/avr/spi_master.h10
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