/* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. * (c) 2013,2014 Stefan Rupp * ---------------------------------------------------------------------------- */ #include "spi.h" #include "ringbuffer.h" #include "crc.h" #include #include #include #define COMM_OBJECT_SIZE (16) #define NUM_COMM_OBJECTS (4) #define RB_SIZE (NUM_COMM_OBJECTS) #define SPI_COMM_PADDING (0x00) #define LEN_SIZE (1) // LEN is 1 byte long static uint8_t rbuff_used_rx[RB_BUFSIZE(RB_SIZE)]; static uint8_t rbuff_used_tx[RB_BUFSIZE(RB_SIZE)]; static uint8_t rbuff_unused[RB_BUFSIZE(RB_SIZE)]; static uint8_t comm_objects[NUM_COMM_OBJECTS][COMM_OBJECT_SIZE]; struct spi_comm_t { uint8_t txout_buf[COMM_OBJECT_SIZE]; uint8_t rxin_buf[COMM_OBJECT_SIZE]; uint16_t crc; uint8_t count; }; static struct spi_comm_t spi_comm; static inline void set_ack_miso(uint8_t ack) { if (ack) PORTC |= (1< COMM_OBJECT_SIZE) {len = COMM_OBJECT_SIZE;} memcpy(comm_objects[rx_obj], spi_comm.rxin_buf, len); ringbuf_put_nb(rbuff_used_rx, rx_obj); } } } else { // falling edge spi_comm.crc = CRC_INIT_VALUE; spi_comm.count = 0; uint8_t ack_mosi = get_ack_mosi(); if (ack_mosi) { if ( ringbuf_get_nb(rbuff_used_tx, &tx_obj) ) { uint8_t len = comm_objects[tx_obj][0]; if (len > COMM_OBJECT_SIZE) {len = COMM_OBJECT_SIZE;} memcpy(spi_comm.txout_buf, comm_objects[tx_obj], len); SPDR = comm_objects[tx_obj][0]; ringbuf_put_nb(rbuff_unused, tx_obj); // there ought always be enough space in this ringbuffer } else { memset(spi_comm.txout_buf, SPI_COMM_PADDING, COMM_OBJECT_SIZE-1); SPDR = SPI_COMM_PADDING; } } else { // no ACK from master, so retransmit same frame once more. no need to copy anything, as txbuf wasn't touched. SPDR = spi_comm.txout_buf[0]; } } } int8_t spi_slave_init() { ringbuf_init(rbuff_used_rx, RB_SIZE, NULL); ringbuf_init(rbuff_used_tx, RB_SIZE, NULL); ringbuf_init(rbuff_unused, RB_SIZE, NULL); for (uint8_t i=0; i COMM_OBJECT_SIZE) { return -1; } if ( ringbuf_get_nb(rbuff_unused, &tx_object) ) { set_crc(data); memcpy(comm_objects[tx_object], data, len); if ( ringbuf_put_nb(rbuff_used_tx, tx_object) ) { return tx_object; } else { return -tx_object; } } else { return (-127); } } int8_t spi_receive(void *data) { uint8_t rx_object; if ( ringbuf_get_nb(rbuff_used_rx, &rx_object) ) { memcpy(data, comm_objects[rx_object], COMM_OBJECT_SIZE); if ( ringbuf_put_nb(rbuff_unused, rx_object) ) { return rx_object; } else { return (-rx_object); } } else { return -127; } }