]> git.tdb.fi Git - model-railway-devices.git/blobdiff - firmware/s88w-r.c
Add some utility functions for interfacing with hardware
[model-railway-devices.git] / firmware / s88w-r.c
index dac0cfcaf85948eeebd70f2eaebae030d9fe3ac6..f64445d81c5a33f12b8f82ef1cae2ea21c7fba5d 100644 (file)
@@ -25,6 +25,8 @@ D5 - S88 RESET
 
 #include <avr/io.h>
 #include <avr/interrupt.h>
+#include "lcd.h"
+#include "serial.h"
 
 #define DATA_OUT PORTD2
 #define CLOCK    PIND3
@@ -33,28 +35,33 @@ D5 - S88 RESET
 
 #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 };
+uint8_t log_pos = 0;
 
 int main()
 {
        uint8_t clock_high = 0;
        uint8_t bits = 0;
+       uint8_t n_bits = 8;
+       uint8_t offset = 0;
 
        DDRD = 0x06;  // 00000110
        PIND = 0xC0;  // 11000000
        DDRB = 0x20;  // 00100000
        PINB = 0x1F;  // 00011111
 
-       // 9600 baud, 8N1
-       UBRR0H = 0;
-       UBRR0L = 103;
-       UCSR0C = BIT(UCSZ00) | BIT(UCSZ01);
-       UCSR0B = BIT(RXEN0) | BIT(TXEN0) | BIT(RXCIE0);
+       serial_init(9600);
+       serial_set_callback(receive);
+       lcd_init();
+       lcd_on();
+       lcd_clear();
 
        sei();
 
@@ -69,9 +76,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,28 +104,77 @@ 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];
+               }
        }
 }
 
-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
+       else if(c=='.')
        {
-               rx_buf[rx_fill++] = c;
-               if(rx_buf[0]==':' && rx_fill==3)
+               if(rx_fill>=4)
                {
-                       input = (decode_hex(rx_buf[1])<<4) | decode_hex(rx_buf[2]);
-                       latch |= input;
-                       rx_fill = 0;
+                       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<<shift)) | (bits<<shift);
+                                       latch[j/2] = input[j/2];
+                               }
+                       }
+
+                       lcd_gotoxy(0, 0);
+                       for(i=10; i--;)
+                       {
+                               lcd_write(hexdigit(input[i]>>4));
+                               lcd_write(hexdigit(input[i]));
+                       }
                }
+               rx_fill = 0xFF;
+       }
+       else
+       {
+               if(rx_fill<sizeof(rx_buf))
+                       rx_buf[rx_fill++] = c;
+               else
+                       rx_fill = 0xFF;
        }
+
+       lcd_gotoxy(log_pos%20, 1+log_pos/20);
+       lcd_write(c);
+       ++log_pos;
+       if(log_pos>=60)
+               log_pos = 0;
+       lcd_gotoxy(log_pos%20, 1+log_pos/20);
+       lcd_write(255);
+}
+
+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)