#include #include #include #include #include #include #include #include "display.h" #include "button.h" static bool report_change = false; static uint8_t last_buttons = 0; static void init(); static void send_status(); static void loop(); /* I/O map version 1 (non-working): 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 */ /* I/O map version 1 (patched): PB0 VFDDB2 PB1 VFDDB3 PB2 BUTTON0 PB3 BUTTON1 PB4 BUTTON2 PB5 BUTTON3 PB6 BUTTON4 PB7 VFDDB4 PC0 BUTTON5 PC1 BUTTON6 PC2 CANTX PC3 CANRX PC4 BUTTON7 PC5 VFDRS PC6 VFDRW PC7 VFDE PD0 VFDDB0 PD1 VFDDB1 PD2 - PD3 - PD4 - PD5 VFDDB5 PD6 VFDDB6 PD7 VFDDB7 */ /* I/O map version 2: PB0 VFDDB0 PB1 VFDDB1 PB2 VFDDB2 PB3 VFDDB3 PB4 VFDDB4 PB5 VFDDB5 PB6 VFDDB6 PB7 VFDDB7 PC0 BUTTON5 PC1 BUTTON7 PC2 CANTX PC3 CANRX PC4 BUTTON6 PC5 VFDRS PC6 VFDRW PC7 VFDE PD0 BUTTON0 PD1 BUTTON1 PD2 - PD3 - PD4 - PD5 BUTTON2 PD6 BUTTON3 PD7 BUTTON4 */ static void init() { // initialize buttons button_init(); last_buttons = button_get(); // initialize VFD display_init(); // clear display_write(0x01, 0, 0); // display on, no cursor display_write(0x0c, 0, 0); // Initialize CAN interface can_init(BITRATE_125_KBPS); // Regular receive/transmit mode can_set_mode(NORMAL_MODE); // Filter for messages addressed to us (RTR on) can_filter_t us = { .id = CAN_HOSTID_DISPLAY, .mask = CAN_HOSTID_MASK, .flags = { .rtr = 1, .extended = 0, }, }; can_set_filter(0, &us); // Filter for public messages (RTR off) can_filter_t pub = { .id = CAN_HOSTID_BROADCAST, .mask = CAN_HOSTID_MASK, .flags = { .rtr = 0, .extended = 0, }, }; can_set_filter(1, &pub); // Enable interrupts to start reception sei(); } static void send_status() { uint8_t status = button_get(); if (can_check_free_buffer()) { can_t msg = { .id = CAN_MSG_DISPLAY_STATUS, .flags = { .rtr = 0, }, .length = 1, .data = { (uint8_t) status, }, }; can_send_message(&msg); } } static void loop() { // Report button state changes first if (report_change) { uint8_t current = button_get(); if (current != last_buttons) { send_status(); last_buttons = current; } } // Check for new messages if (can_check_message()) { can_t msg = { 0 }; uint8_t status = can_get_message(&msg); if (status != 0) { switch (msg.id) { case CAN_MSG_DISPLAY_STATUS: send_status(); break; case CAN_MSG_DISPLAY_CMD: if (msg.length >= 1) { display_write(msg.data[0], &msg.data[1], msg.length - 1); } break; case CAN_MSG_AUTO_STATUS: if (msg.length == 1) { report_change = msg.data[0] ? true : false; } break; } } } } static void test() { static uint8_t test_char = 0; display_write(0x80, (const uint8_t *) "Hello, world", 12); display_write(0xc0, (const uint8_t *) &test_char, 1); test_char++; _delay_ms(100); } static void test2() { // PC5, PC6, PC7: output (VFD RS, RW, E), RS=0, RW=1, E=1 // PD0, PD1, PB0, PB1, PB7, PD5, PD6, PD7: output (VFD DB) - can be switched to input (pullup not needed) PORTC &= ~(_BV(PC5) | _BV(PC6) | _BV(PC7)); PORTB &= ~(_BV(PB0) | _BV(PB1) | _BV(PB7)); PORTD &= ~(_BV(PD0) | _BV(PD1) | _BV(PD5) | _BV(PD6) | _BV(PD7)); PORTC |= _BV(PC5); _delay_us(10); PORTC &= ~_BV(PC5); PORTC |= _BV(PC6); _delay_us(10); PORTC &= ~_BV(PC6); PORTC |= _BV(PC7); _delay_us(10); PORTC &= ~_BV(PC7); PORTD |= _BV(PD0); _delay_us(10); PORTD &= ~_BV(PD0); PORTD |= _BV(PD1); _delay_us(10); PORTD &= ~_BV(PD1); PORTB |= _BV(PB0); _delay_us(10); PORTB &= ~_BV(PB0); PORTB |= _BV(PB1); _delay_us(10); PORTB &= ~_BV(PB1); PORTB |= _BV(PB7); _delay_us(10); PORTB &= ~_BV(PB7); PORTD |= _BV(PD5); _delay_us(10); PORTD &= ~_BV(PD5); PORTD |= _BV(PD6); _delay_us(10); PORTD &= ~_BV(PD6); PORTD |= _BV(PD7); _delay_us(10); PORTD &= ~_BV(PD7); } int main() { init(); while (1) { test(); loop(); } }