+++ /dev/null
-#include <avr/io.h>
-#include <avr/interrupt.h>
-
-#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<<i;
- if(toggled&~state&bit)
- {
- if(i==0)
- write_serial('N');
- else if(i==1)
- write_serial('P');
- else
- {
- uint8_t f = i-2;
- uint16_t fbit = 1<<f;
- funcs ^= fbit;
- write_serial((funcs&fbit) ? 'H' : 'L');
- write_serial('0'+f);
- }
- }
- }
- }
-}
-
-uint16_t read_input(void)
-{
- uint8_t row;
- uint16_t input = 0;
-
- for(row=0; row<4; ++row)
- {
- uint8_t pins;
-
- PORTB = (PORTB|0x0F)&~(1<<row);
- NOP();
- NOP();
- NOP();
- NOP();
- NOP();
- NOP();
- pins = PIND>>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<<UDRE0))) ;
- UDR0 = c;
-}
-
-void write_7seg(uint8_t n)
-{
- uint8_t segs = ~digits[n];
- uint8_t i;
- for(i=0; i<8; ++i)
- {
- PORTB &= ~0x20;
- if(segs&0x80)
- PORTB |= 0x10;
- else
- PORTB &= ~0x10;
- PORTB |= 0x20;
- segs <<= 1;
- }
-}