X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=firmware%2Fs88w-r.c;h=b537584c19ddb698fe9e44ecc4904de47a44568f;hb=a99e18c8e7ec3276ba6a881d1eaccf2d7fc26ea6;hp=dac0cfcaf85948eeebd70f2eaebae030d9fe3ac6;hpb=af6a469f761ceec44e94bea5fe8e5345fd368966;p=model-railway-devices.git diff --git a/firmware/s88w-r.c b/firmware/s88w-r.c index dac0cfc..b537584 100644 --- a/firmware/s88w-r.c +++ b/firmware/s88w-r.c @@ -1,6 +1,6 @@ /* $Id$ -This file is part of the MSP Märklin suite +This file is part of R²C² Copyright © 2010 Mikkosoft Productions, Mikko Rasa Distributed under the GPL @@ -25,43 +25,54 @@ D5 - S88 RESET #include #include +#include "lcd.h" +#include "serial.h" +#include "delay.h" #define DATA_OUT PORTD2 #define CLOCK PIND3 #define LOAD PIND4 #define RESET PIND5 +#define LCD_DISABLE PINB4 + #define BIT(n) (1<<(n)) +void receive(uint8_t); +uint8_t hexdigit(uint8_t); uint8_t decode_hex(uint8_t); -volatile uint8_t rx_buf[3]; -volatile uint8_t rx_fill = 0; -volatile uint8_t input = 0; -volatile uint8_t latch = 0; +volatile uint8_t rx_buf[7]; +volatile uint8_t rx_fill = 0xFF; +volatile uint8_t input[128] = { 0 }; +volatile uint8_t latch[128] = { 0 }; +volatile uint8_t lcd_enabled = 0; +uint8_t log_row = 0; +uint8_t log_col = 0; int main() { uint8_t clock_high = 0; uint8_t bits = 0; + uint8_t n_bits = 8; + uint8_t offset = 0; + uint8_t i; - DDRD = 0x06; // 00000110 - PIND = 0xC0; // 11000000 - DDRB = 0x20; // 00100000 - PINB = 0x1F; // 00011111 + DDRD = 0x06; // 00000110 + PORTD = 0xC0; // 11000000 + DDRB = 0x20; // 00100000 + PORTB = 0x1F; // 00011111 - // 9600 baud, 8N1 - UBRR0H = 0; - UBRR0L = 103; - UCSR0C = BIT(UCSZ00) | BIT(UCSZ01); - UCSR0B = BIT(RXEN0) | BIT(TXEN0) | BIT(RXCIE0); + serial_init(9600); + lcd_init(); sei(); while(1) { - uint8_t d_pins; + uint8_t b_pins, d_pins; + b_pins = PINB; d_pins = PIND; if(d_pins&BIT(CLOCK)) @@ -69,9 +80,21 @@ int main() if(!clock_high) { if(d_pins&BIT(LOAD)) - bits = latch; + { + offset = 0; + bits = latch[0]; + n_bits = 8; + } else + { bits >>= 1; + if(!--n_bits) + { + ++offset; + bits = latch[offset]; + n_bits = 8; + } + } if(bits&1) PORTD |= BIT(DATA_OUT); @@ -85,30 +108,111 @@ int main() clock_high = 0; if(d_pins&BIT(RESET)) - latch = input; + { + uint8_t i; + for(i=0; i<128; ++i) + latch[i] = input[i]; + } + + if(b_pins&BIT(LCD_DISABLE)) + { + if(lcd_enabled) + { + lcd_enabled = 0; + + lcd_clear(); + } + } + else if(!lcd_enabled) + { + lcd_enabled = 1; + log_row = 0; + log_col = 0; + + lcd_clear(); + for(i=0; i<20; ++i) + lcd_write(hexdigit(input[9-i/2]>>(4-i%2*4))); + lcd_gotoxy(0, 1); + lcd_write(255); + } } } -ISR(USART_RX_vect) +void receive(uint8_t c) { - uint8_t c = UDR0; - if(rx_fill==0) + if(rx_fill==0xFF) { if(c==':') - rx_buf[rx_fill++] = c; + rx_fill = 0; + } + else if(c=='.') + { + if(rx_fill>=4) + { + uint16_t offset; + uint8_t nibbles; + uint8_t i; + + offset = (decode_hex(rx_buf[0])<<8) | (decode_hex(rx_buf[1])<<4) | decode_hex(rx_buf[2]); + nibbles = (offset&3); + offset >>= 2; + if(rx_fill>3+nibbles) + { + for(i=0; i<=nibbles; ++i) + { + uint16_t j = offset+nibbles-i; + uint8_t shift = 4*(j&1); + uint8_t bits = decode_hex(rx_buf[3+i]); + input[j/2] = (input[j/2]&~(0xF<=20) { - input = (decode_hex(rx_buf[1])<<4) | decode_hex(rx_buf[2]); - latch |= input; - rx_fill = 0; + log_col = 0; + ++log_row; + if(log_row>=3) + log_row = 0; + lcd_gotoxy(log_col, 1+log_row); } + lcd_write(255); } } +SERIAL_SET_CALLBACK(receive) + +uint8_t hexdigit(uint8_t n) +{ + n &= 0xF; + if(n<10) + return '0'+n; + else + return 'A'+(n-0xA); +} + uint8_t decode_hex(uint8_t c) { if(c>='0' && c<='9')