X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src-avr%2Fao_spi_slave.c;h=9ef30ead7d19cab604b35ee8ff1e02e02ac5fcf0;hb=0beebf5b8659014c5e8ba194e42e5dcd9be1a2a6;hp=d44e4d0e0bafa81b0029b1475ed3185eaa77da3c;hpb=28a6127668a333f5d6a6234e2ee4527267c459d2;p=fw%2Faltos diff --git a/src-avr/ao_spi_slave.c b/src-avr/ao_spi_slave.c index d44e4d0e..9ef30ead 100644 --- a/src-avr/ao_spi_slave.c +++ b/src-avr/ao_spi_slave.c @@ -18,7 +18,8 @@ #include "ao.h" #include "ao_product.h" -static struct ao_companion_command ao_companion_command; +struct ao_companion_command ao_companion_command; + static const struct ao_companion_setup ao_companion_setup = { .board_id = AO_idProduct_NUMBER, .board_id_inverse = ~AO_idProduct_NUMBER, @@ -26,29 +27,46 @@ static const struct ao_companion_setup ao_companion_setup = { .channels = NUM_ADC }; -static uint8_t ao_spi_slave_recv(void) +static uint8_t +ao_spi_read(uint8_t *buf, uint8_t len) { - uint8_t *buf; - uint8_t len; - - len = sizeof (ao_companion_command); - buf = (uint8_t *) &ao_companion_command; while (len--) { while (!(SPSR & (1 << SPIF))) if ((PINB & (1 << PINB0))) return 0; *buf++ = SPDR; } + return 1; +} + +static void +ao_spi_write(uint8_t *buf, uint8_t len) +{ + while (len--) { + SPDR = *buf++; + while (!(SPSR & (1 << SPIF))) + if ((PINB & (1 << PINB0))) + return; + } + /* Clear pending SPIF bit by reading */ + (void) SPDR; +} + +static uint8_t ao_spi_slave_recv(void) +{ + if (!ao_spi_read((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) + return 0; /* Figure out the outbound data */ switch (ao_companion_command.command) { case AO_COMPANION_SETUP: - buf = (uint8_t *) &ao_companion_setup; - len = sizeof (ao_companion_setup); + ao_spi_write((uint8_t *) &ao_companion_setup, + sizeof (ao_companion_setup)); break; case AO_COMPANION_FETCH: - buf = (uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc; - len = NUM_ADC * sizeof (uint16_t); + ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_STATE: break; @@ -56,16 +74,6 @@ static uint8_t ao_spi_slave_recv(void) return 0; } - if (len) { - /* Send the outbound data */ - while (len--) { - SPDR = *buf++; - while (!(SPSR & (1 << SPIF))) - if ((PINB & (1 << PINB0))) - return 0; - } - (void) SPDR; - } ao_log_store.tm_tick = ao_companion_command.tick; if (ao_log_store.tm_state != ao_companion_command.flight_state) { ao_log_store.tm_state = ao_companion_command.flight_state; @@ -107,7 +115,24 @@ ao_spi_slave_init(void) PCMSK0 |= (1 << PCINT0); /* Enable PCINT0 pin change */ PCICR |= (1 << PCIE0); /* Enable pin change interrupt */ - DDRB = (DDRB & 0xf0) | (1 << 3); + DDRB = ((DDRB & 0xf0) | + (1 << 3) | /* MISO, output */ + (0 << 2) | /* MOSI, input */ + (0 << 1) | /* SCK, input */ + (0 << 0)); /* SS, input */ + + /* We'd like to have a pull-up on SS so that disconnecting the + * TM would cause any SPI transaction to abort. However, when + * I tried that, SPI transactions would spontaneously abort, + * making me assume that we needed a less aggressive pull-up + * than is offered inside the AVR + */ + PORTB = ((PORTB & 0xf0) | + (1 << 3) | /* MISO, output */ + (0 << 2) | /* MOSI, no pull-up */ + (0 << 1) | /* SCK, no pull-up */ + (0 << 0)); /* SS, no pull-up */ + SPCR = (0 << SPIE) | /* Disable SPI interrupts */ (1 << SPE) | /* Enable SPI */ (0 << DORD) | /* MSB first */