diff --git a/Makefile b/Makefile index bd679c6..0e67b4a 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PRG = rgbyteclock -OBJ = rgbyteclock.o timer.o lcd.o main.o rtc.o -MCU_TARGET = atmega16 +OBJ = rgbyteclock.o timer.o lcd.o main.o rtc.o spi.o ringbuffer.o crc.o +MCU_TARGET = atmega164a OPTIMIZE = -Os DEFS = @@ -30,6 +30,10 @@ main.o: rgbyteclock.o timer.o:timer.h lcd.o: lcd.h rtc.o: rtc.h +spi.o: spi.h +ringbuffer.o: ringbuffer.h +crc.o: crc.h + clean: rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak diff --git a/crc.c b/crc.c new file mode 100644 index 0000000..b0833ef --- /dev/null +++ b/crc.c @@ -0,0 +1,38 @@ + +#include "crc.h" + + +const uint16_t crc16_table[256] PROGMEM = { +0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, +0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, +0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, +0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, +0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, +0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, +0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, +0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, +0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, +0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, +0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, +0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, +0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, +0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, +0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, +0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, +0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, +0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, +0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, +0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, +0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, +0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, +0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, +0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, +0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, +0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, +0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, +0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, +0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, +0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, +0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, +0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78}; + diff --git a/crc.h b/crc.h new file mode 100644 index 0000000..7e74288 --- /dev/null +++ b/crc.h @@ -0,0 +1,27 @@ + +#ifndef CRC_H_ +#define CRC_H_ + +#include +#include +#include + + +#define CRC_INIT_VALUE (0x0000) +#define CRC_LEN (2) + +extern const uint16_t crc16_table[] PROGMEM; + + +static inline uint16_t crc_step(uint16_t old_crc, uint8_t new_byte) +{ + uint16_t crc; + crc = (old_crc >> 8) ^ crc16_table[new_byte ^ (old_crc & 0xff)]; + return crc; +} + + + + + +#endif // CRC_H_ diff --git a/main.c b/main.c index 4d06f49..226e855 100644 --- a/main.c +++ b/main.c @@ -13,12 +13,13 @@ #include "timer.h" #include "lcd.h" #include "rgbyteclock.h" - +#include "spi.h" int main(void) { timer_init(); + spi_slave_init(); lcd_init(); rgbyteclock(); diff --git a/ringbuffer.c b/ringbuffer.c new file mode 100644 index 0000000..d84b07f --- /dev/null +++ b/ringbuffer.c @@ -0,0 +1,98 @@ +/* + * ---------------------------------------------------------------------------- + * "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) 2008-2014 Stefan Rupp + * ---------------------------------------------------------------------------- + */ + + + + +#include +#include + +#include + +#include "ringbuffer.h" + + +void ringbuf_init(void *ringbuffer, uint8_t rb_size, void (*idle_func)(void)) +{ + ringbuffer_t *rb = (ringbuffer_t *) ringbuffer; + + rb->size = rb_size; + rb->free = rb_size; + rb->write_idx = 0; + rb->read_idx = 0; + rb->idle_func = idle_func; + return; +} + + +int8_t ringbuf_get_nb(void *ringbuffer, uint8_t *ch) +{ + ringbuffer_t *rb = (ringbuffer_t *) ringbuffer; + if ( rb->size - rb->free == 0) { + *ch = 0xff; + return 0; + } + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + rb->free++; + *ch = rb->buffer[rb->read_idx++]; + if ( rb->read_idx >= rb->size ) { + rb->read_idx = 0; + } + } + return 1; +} + + +int8_t ringbuf_get(void *ringbuffer, uint8_t *ch) +{ + ringbuffer_t *rb = (ringbuffer_t *) ringbuffer; + while ( rb->size - rb->free == 0) { + if (rb->idle_func != NULL) { + rb->idle_func(); + } + } + rb->free++; + *ch = rb->buffer[rb->read_idx++]; + if ( rb->read_idx >= rb->size ) { + rb->read_idx = 0; + } + return 1; +} + + +int8_t ringbuf_put_nb(void * ringbuffer, uint8_t ch) +{ + ringbuffer_t *rb = (ringbuffer_t *) ringbuffer; + + if (rb->free > 0) { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + rb->free--; + rb->buffer[rb->write_idx++] = ch; + if (rb->write_idx >= rb->size) { + rb->write_idx = 0; + } + } + return 1; + } + return 0; +} + + + +int8_t ringbuf_get_num_waiting( void * ringbuffer) +{ + ringbuffer_t *rb = (ringbuffer_t *) ringbuffer; + uint8_t waiting; + + waiting = rb->size - rb->free; + + return waiting; +} + diff --git a/ringbuffer.h b/ringbuffer.h new file mode 100644 index 0000000..3cfed13 --- /dev/null +++ b/ringbuffer.h @@ -0,0 +1,26 @@ +#if !defined __RINGBUFFER_H +#define __RINGBUFFER_H + +#include + +typedef struct { + uint8_t size; + volatile uint8_t free; + volatile uint8_t write_idx; + volatile uint8_t read_idx; + + void (*idle_func)(void); + + uint8_t buffer[]; +} ringbuffer_t; + + +#define RB_BUFSIZE(queue_len) (sizeof(ringbuffer_t)+(queue_len)) + +void ringbuf_init(void *ringbuffer, uint8_t buf_size, void (*IdleFunc)(void)); +int8_t ringbuf_get(void *ringbuffer, uint8_t *ch); +int8_t ringbuf_get_nb(void *ringbuffer, uint8_t *ch); +int8_t ringbuf_put_nb(void *ringbuffer, uint8_t ch); +int8_t ringbuf_get_num_waiting(void * ringbuffer); + +#endif diff --git a/rtc.c b/rtc.c index 835b3fd..1147508 100644 --- a/rtc.c +++ b/rtc.c @@ -7,6 +7,8 @@ * (c) 2014 Stefan Rupp * ---------------------------------------------------------------------------- */ + +#if 0 #include #include "rtc.h" @@ -129,4 +131,5 @@ void timer_validate(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint16_t */ #endif +#endif diff --git a/spi.c b/spi.c new file mode 100644 index 0000000..8ed979a --- /dev/null +++ b/spi.c @@ -0,0 +1,215 @@ +/* + * ---------------------------------------------------------------------------- + * "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; + //PORTB ^= (1< +#include + + +int8_t spi_slave_init(); +int8_t spi_prepare_to_send(void *data); +int8_t spi_receive(void *data); + + +#endif // SPI_H_ + diff --git a/timer.c b/timer.c index ca9cec2..bda915c 100644 --- a/timer.c +++ b/timer.c @@ -19,7 +19,7 @@ */ static volatile uint32_t timer_time; -ISR(TIMER0_COMP_vect) { +ISR(TIMER0_COMPA_vect) { ++timer_time; return; } @@ -46,11 +46,12 @@ void timer_init(void) // - Set Timer/Counter0 prescaler to 64 ==> (1< (1< +#include +#include + + +#define TOS_CONFIG (0x11) +#define TOS_CANFRAME (0x21) +#define TOS_PRINT (0xef) + + +#endif // TOS_H_