From: Mikko Rasa Date: Sat, 3 Apr 2010 09:49:02 +0000 (+0000) Subject: Add a program for serial port control and associated Arduino firmware X-Git-Url: http://git.tdb.fi/?p=model-railway-devices.git;a=commitdiff_plain;h=fd3352aba49e455947bdcbfccc8a37e165564ba3 Add a program for serial port control and associated Arduino firmware --- fd3352aba49e455947bdcbfccc8a37e165564ba3 diff --git a/firmware/Makefile b/firmware/Makefile new file mode 100644 index 0000000..68d6f4c --- /dev/null +++ b/firmware/Makefile @@ -0,0 +1,23 @@ +# $Id$ + +MCU = atmega328p +CLOCK = 16000000 +CFLAGS = -Wall -Os -ffunction-sections -fdata-sections -mmcu=$(MCU) -DF_CPU=$(CLOCK) +LDFLAGS = -Os -Wl,--gc-sections -mmcu=$(MCU) + +help: + @echo "Targets:" + @echo " %.hex: Build firmware from %.c" + @echo " upload-%: Upload firmware to AVR" + +%.hex: %.elf + avr-objcopy -O ihex $< $@ + +%.elf: %.o + avr-gcc $(LDFLAGS) -o $@ $< + +%.o: %.c + avr-gcc -c $(CFLAGS) -o $@ $< + +upload-%: %.hex + avrdude -p$(MCU) -cstk500v1 -P/dev/ttyUSB0 -b57600 -D -Uflash:w:$<:i diff --git a/firmware/ctrl.c b/firmware/ctrl.c new file mode 100644 index 0000000..523c702 --- /dev/null +++ b/firmware/ctrl.c @@ -0,0 +1,228 @@ +/* $Id$ + +This file is part of the MSP Märklin suite +Copyright © 2010 Mikkosoft Productions, Mikko Rasa +Distributed under the GPL +*/ + +#include +#include + +#define BIT(n) (1<<(n)) +#define NOP() __asm__("nop"); + +uint8_t digits[11] = +{ + 0x3F, + 0x06, + 0x5B, + 0x4F, + 0x66, + 0x6D, + 0x7D, + 0x07, + 0x7F, + 0x6F, + 0x40 +}; + +uint16_t read_input(void); +uint16_t read_input_filtered(void); +void write_serial(uint8_t); +void write_7seg(uint8_t); + +uint8_t speed = 0; +uint16_t funcs = 0; +volatile uint8_t ticks = 0; +volatile uint8_t rx_buf[3]; +volatile uint8_t rx_fill = 0; + +ISR(TIMER1_COMPA_vect) +{ + if(ticks<255) + ++ticks; +} + +ISR(USART_RX_vect) +{ + uint8_t c = UDR0; + if(rx_fill==0) + { + if(c=='A' || c=='S') + rx_buf[rx_fill++] = c; + } + else + { + rx_buf[rx_fill++] = c; + if(rx_buf[0]=='A' && rx_fill==3) + { + uint8_t n = (rx_buf[1]-'0')*10+(rx_buf[2]-'0'); + write_7seg(n/10); + write_7seg(n%10); + rx_fill = 0; + } + else if(rx_buf[0]=='S' && rx_fill==3) + { + speed = (rx_buf[1]-'0')*10+(rx_buf[2]-'0'); + rx_fill = 0; + } + } +} + +int main() +{ + uint16_t state = 0; + + DDRD = 0x02; // 00000010 + PORTD = 0xFC; // 11111100 + DDRB = 0x3F; // 00111111 + PORTB = 0x0F; // 00001111 + + write_7seg(10); + write_7seg(10); + + // 9600 baud, 8N1 + UBRR0H = 0; + UBRR0L = 103; + UCSR0C = BIT(UCSZ00) | BIT(UCSZ01); + UCSR0B = BIT(RXEN0) | BIT(TXEN0) | BIT(RXCIE0); + + TCCR1A = 0; + TCCR1B = BIT(WGM12) | BIT(CS12); + OCR1AH = 24; + OCR1AL = 106; + TIMSK1 = BIT(OCIE1A); + + sei(); + + while(1) + { + uint16_t toggled; + uint8_t i; + uint16_t input; + + input = read_input_filtered(); + input ^= 0xFFFC; + + toggled = state^input; + state = input; + + if((toggled&3)==2 && (state&1)) + { + uint8_t action = 0; + if(state&2) + { + if(speed<14) + { + ++speed; + action = 1; + } + } + else + { + if(speed>0) + { + --speed; + action = 1; + } + else if(ticks>10) + action = 2; + } + + if(action==1) + { + write_serial('S'); + write_serial('0'+speed/10); + write_serial('0'+speed%10); + } + else if(action==2) + write_serial('R'); + + ticks = 0; + } + + for(i=0; i<14; ++i) + { + uint16_t bit = 4<>2; + input |= pins&3; + input |= (pins&0x3C)<<(row*4); + } + + return input; +} + +uint16_t read_input_filtered(void) +{ + uint16_t valid = 0xFFFF; + uint16_t prev; + uint16_t input; + uint8_t i; + + prev = read_input(); + for(i=0; i<20; ++i) + { + input = read_input(); + valid &= ~(input^prev); + prev = input; + } + + return input&valid; +} + +void write_serial(uint8_t c) +{ + while(!(UCSR0A&(1<