diff --git a/display/firmware/main.c b/display/firmware/main.c index ec84362..d3e91c7 100644 --- a/display/firmware/main.c +++ b/display/firmware/main.c @@ -9,9 +9,38 @@ static bool report_change = false; static void init() { - // Enable GPIO: PB2, PB3, PB4 output, low; PB5 input, pull-up on - PORTB = (PORTB & ~(_BV(PB2) | _BV(PB3) | _BV(PB4))) | _BV(PB5); - DDRB = (DDRB & ~_BV(PB5)) | (_BV(PB2) | _BV(PB3) | _BV(PB4)); + /* + PB2 BUTTON0 + PB3 BUTTON1 + PB4 BUTTON2 + PB5 BUTTON3 + PB6 BUTTON4 + PC0 BUTTON5 + PC1 BUTTON6 + PC2 CANTX + PC3 CANRX + PC4 BUTTON7 + PC5 VFDRS + PC6 VFDRW + PC7 VFDE + PD0 VFDDB0 + PD1 VFDDB1 + PD2 VFDDB2 + PD3 VFDDB3 + PD4 VFDDB4 + PD5 VFDDB5 + PD6 VFDDB6 + PD7 VFDDB7 + */ + // PB2, PB3, PB4, PB5, PB6, PC0, PC1, PC4: input, no pullup (button0..7) + // PC5, PC6, PC7: output (VFD RS, RW, E), RS=0, RW=H, E=H + // PD: output (VFD DB) - can be switched to input w/ pullup + PORTB = 0x00; + DDRB = 0x00; + PORTC = _BV(PC6) | _BV(PC7); + DDRC = _BV(PC5) | _BV(PC6) | _BV(PC7); + PORTD = 0x00; + DDRD = 0xff; // Initialize CAN interface can_init(BITRATE_125_KBPS); @@ -43,8 +72,23 @@ static void init() { sei(); } +static uint8_t get_buttons() { + uint8_t pinb = PINB; + uint8_t pinc = PINC; + uint8_t buttons = 0; + if (pinb & _BV(PB2)) buttons |= _BV(0); + if (pinb & _BV(PB3)) buttons |= _BV(1); + if (pinb & _BV(PB4)) buttons |= _BV(2); + if (pinb & _BV(PB5)) buttons |= _BV(3); + if (pinb & _BV(PB6)) buttons |= _BV(4); + if (pinc & _BV(PC0)) buttons |= _BV(5); + if (pinc & _BV(PC1)) buttons |= _BV(6); + if (pinc & _BV(PC4)) buttons |= _BV(7); + return buttons; +} + static void send_status() { - uint8_t status = 0; + uint8_t status = get_buttons(); if (can_check_free_buffer()) { can_t msg = { @@ -52,15 +96,98 @@ static void send_status() { .flags = { .rtr = 0, }, - .length = 2, - .data = { (uint8_t) (status >> 8), (uint8_t) status, }, + .length = 1, + .data = { (uint8_t) status, }, }; can_send_message(&msg); } } +static uint8_t read_ir() { + // switch PD to input + DDRD = 0x00; + // E=0 (enable/clock) RS=0 (IR) RW=1 (read) + PORTC = (PORTC & ~(_BV(PC5) | _BV(PC7))) | _BV(PC6); + _delay_us(0.23); + // E=1 (enable/clock) + PORTC |= _BV(PC7); + _delay_us(0.16); + uint8_t data = PIND; + _delay_us(0.23 - 0.16); + // E=0 (enable/clock) + PORTC &= ~_BV(PC7); + _delay_us(0.01); + // reset to idle + PORTC = _BV(PC6) | _BV(PC7); + DDRD = 0xff; + return data; +} + +static uint8_t read_dr() { + // switch PD to input + DDRD = 0x00; + // E=0 (enable/clock) RS=1 (IR) RW=1 (read) + PORTC = (PORTC & ~_BV(PC7)) | (_BV(PC5) | _BV(PC6)); + _delay_us(0.23); + // E=1 (enable/clock) + PORTC |= _BV(PC7); + _delay_us(0.16); + uint8_t data = PIND; + _delay_us(0.23 - 0.16); + // E=0 (enable/clock) + PORTC &= ~_BV(PC7); + _delay_us(0.01); + // reset to idle + PORTC = _BV(PC6) | _BV(PC7); + DDRD = 0xff; + return data; +} + +static void write_ir(uint8_t data) { + // E=0 (enable/clock) RS=0 (IR) RW=0 (write) + PORTC &= ~(_BV(PC5) | _BV(PC6) | _BV(PC7)); + _delay_us(0.23); + // E=1 (enable/clock) + PORTC |= _BV(PC7); + // data + PORTD = data; + _delay_us(0.23); + // E=0 (enable/clock) + PORTC &= ~_BV(PC7); + _delay_us(0.01); + // reset to idle + PORTC = _BV(PC6) | _BV(PC7); + PORTD = 0x00; +} + +static void write_dr(uint8_t data) { + // E=0 (enable/clock) RS=1 (IR) RW=0 (write) + PORTC = (PORTC & ~(_BV(PC6) | _BV(PC7))) | _BV(PC5); + _delay_us(0.23); + // E=1 (enable/clock) + PORTC |= _BV(PC7); + // data + PORTD = data; + _delay_us(0.23); + // E=0 (enable/clock) + PORTC &= ~_BV(PC7); + _delay_us(0.01); + // reset to idle + PORTC = _BV(PC6) | _BV(PC7); + PORTD = 0x00; +} + + +static void wait_ready() { + while (read_ir() & _BV(7)); +} + static void write_display(uint8_t command, const uint8_t *data, uint8_t length) { - + wait_ready(); + write_ir(command); + for (uint8_t i = 0; i < length; i++) { + write_dr(data[i]); + } } static void loop() {