change platform at AtMega164A and add spicomm stuff from candle

This commit is contained in:
Stefan Rupp 2014-03-01 18:03:19 +01:00
parent 4d41456906
commit e200301122
11 changed files with 451 additions and 8 deletions

View File

@ -1,6 +1,6 @@
PRG = rgbyteclock PRG = rgbyteclock
OBJ = rgbyteclock.o timer.o lcd.o main.o rtc.o OBJ = rgbyteclock.o timer.o lcd.o main.o rtc.o spi.o ringbuffer.o crc.o
MCU_TARGET = atmega16 MCU_TARGET = atmega164a
OPTIMIZE = -Os OPTIMIZE = -Os
DEFS = DEFS =
@ -30,6 +30,10 @@ main.o: rgbyteclock.o
timer.o:timer.h timer.o:timer.h
lcd.o: lcd.h lcd.o: lcd.h
rtc.o: rtc.h rtc.o: rtc.h
spi.o: spi.h
ringbuffer.o: ringbuffer.h
crc.o: crc.h
clean: clean:
rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak

38
crc.c Normal file
View File

@ -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};

27
crc.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef CRC_H_
#define CRC_H_
#include <stdint.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#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_

3
main.c
View File

@ -13,12 +13,13 @@
#include "timer.h" #include "timer.h"
#include "lcd.h" #include "lcd.h"
#include "rgbyteclock.h" #include "rgbyteclock.h"
#include "spi.h"
int main(void) int main(void)
{ {
timer_init(); timer_init();
spi_slave_init();
lcd_init(); lcd_init();
rgbyteclock(); rgbyteclock();

98
ringbuffer.c Normal file
View File

@ -0,0 +1,98 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <struppi@struppi.name> 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 <stdlib.h>
#include <inttypes.h>
#include <util/atomic.h>
#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;
}

26
ringbuffer.h Normal file
View File

@ -0,0 +1,26 @@
#if !defined __RINGBUFFER_H
#define __RINGBUFFER_H
#include <inttypes.h>
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

3
rtc.c
View File

@ -7,6 +7,8 @@
* (c) 2014 Stefan Rupp * (c) 2014 Stefan Rupp
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
#if 0
#include <avr/io.h> #include <avr/io.h>
#include "rtc.h" #include "rtc.h"
@ -129,4 +131,5 @@ void timer_validate(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint16_t
*/ */
#endif #endif
#endif

215
spi.c Normal file
View File

@ -0,0 +1,215 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <struppi@struppi.name> 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 <stdlib.h>
#include <string.h>
#include <avr/interrupt.h>
#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<<PC7);
else PORTC &= ~(1<<PC7);
}
static void set_crc(void* const buf)
{
uint8_t* const data = buf;
uint8_t len = data[0];
uint16_t crc = CRC_INIT_VALUE;
uint16_t *crc_ptr;
for (int i=1; i<=len; ++i) {
crc = crc_step(crc, data[i]);
}
crc_ptr = buf + len + 1;
*crc_ptr = crc;
len += 2;
data[0] = len;
}
static inline uint8_t get_ack_mosi(void)
{
#if 0
return (PINB & (1<<PB5))?1:0;
#else
return 1;
#endif
}
ISR(SPI_STC_vect)
{
SPDR = spi_comm.txout_buf[spi_comm.count+1];
spi_comm.rxin_buf[spi_comm.count] = SPDR;
spi_comm.crc = crc_step(spi_comm.crc, spi_comm.rxin_buf[spi_comm.count]);
spi_comm.count++;
}
// This is the interrupt handler for the CS line.
// in case of a falling edge, we prepare for the
// SPI transfer that is about to come in in 100uS.
// in case of an rising edge, we do some cleanup.
ISR(PCINT1_vect)
{
uint8_t tx_obj, rx_obj;
if (PINC & (1<<PC1)) {
// rising edge
if ( spi_comm.rxin_buf[0] != SPI_COMM_PADDING ) {
uint8_t len = spi_comm.rxin_buf[0];
uint8_t data_valid = (spi_comm.crc == 0x0000);
data_valid = 1; // FIXME: CRC not implemented on python side, so ignore for now
set_ack_miso(data_valid);
if (data_valid && ringbuf_get_nb(rbuff_unused, &rx_obj)) {
spi_comm.rxin_buf[0] = len-2; // strip CRC from data
if (len > 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<NUM_COMM_OBJECTS; i++) {
ringbuf_put_nb(rbuff_unused, i);
}
PCMSK1 |= (1<<PCINT9);
PCICR |= (1<<PCIE1);
/* Set MISO output, all others input */
DDRD |= (1<<PD2);
DDRD &= ~((1<<PD3)|(1<<PD4));
/* Enable SPI */
SPCR = (1<<SPE) | (1<<SPIE); // enable SPI
DDRB &= ~(1<<PB5); // ACK_MOSI
PORTB &= ~(1<<PB5);
DDRC |= (1<<PC7); // ACK_MISO
set_ack_miso(0);
return 1;
}
int8_t spi_prepare_to_send(void *data)
{
uint8_t tx_object;
uint8_t len = ((uint8_t *)data)[0];
if ((len + LEN_SIZE + CRC_LEN) > 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<<PB3);
}
}
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);
//PORTB ^= (1<<PB3);
}
}
else {
return -127;
}
}

15
spi.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef SPI_H_
#define SPI_H_
#include <stdint.h>
#include <avr/io.h>
int8_t spi_slave_init();
int8_t spi_prepare_to_send(void *data);
int8_t spi_receive(void *data);
#endif // SPI_H_

11
timer.c
View File

@ -19,7 +19,7 @@
*/ */
static volatile uint32_t timer_time; static volatile uint32_t timer_time;
ISR(TIMER0_COMP_vect) { ISR(TIMER0_COMPA_vect) {
++timer_time; ++timer_time;
return; return;
} }
@ -46,11 +46,12 @@ void timer_init(void)
// - Set Timer/Counter0 prescaler to 64 ==> (1<<CS01)|(1<<CS00) // - Set Timer/Counter0 prescaler to 64 ==> (1<<CS01)|(1<<CS00)
// - Set OCR2 to 249 // - Set OCR2 to 249
// - CTC ( i.e. clear counter, when COUNTER == OCR0A) ==> (1<<WGM01) // - CTC ( i.e. clear counter, when COUNTER == OCR0A) ==> (1<<WGM01)
OCR0 = 249; OCR0A = 249;
TCCR0 = (1<<CS01)|(1<<CS00)|(1<<WGM01); TCCR0B = (1<<WGM02);
TCCR0A = (1<<CS01)|(1<<CS00);
// Interrupts setzen // Interrupts setzen
TIMSK |= (1<<OCIE0); TIMSK0 |= (1<<OCIE0A);
// Allow interrupts // Allow interrupts
sei(); sei();

15
tos.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef TOS_H_
#define TOS_H_
#include <stdint.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#define TOS_CONFIG (0x11)
#define TOS_CANFRAME (0x21)
#define TOS_PRINT (0xef)
#endif // TOS_H_