matemat/display/firmware/main.c
2021-03-09 12:09:48 +01:00

143 lines
2.7 KiB
C

#include <inttypes.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <can.h>
#include <messages.h>
#include "display.h"
static bool report_change = false;
static void init();
static uint8_t get_buttons();
static void send_status();
static void loop();
/* I/O map:
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
*/
static void init() {
// initialize buttons
// PB2, PB3, PB4, PB5, PB6, PC0, PC1, PC4: input, no pullup (button0..7)
PORTB &= ~(_BV(PB2) | _BV(PB3) | _BV(PB4) | _BV(PB5) | _BV(PB6));
DDRB &= ~(_BV(PB2) | _BV(PB3) | _BV(PB4) | _BV(PB5) | _BV(PB6));
PORTC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC4));
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC4));
// initialize VFD
display_init();
// 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 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 = get_buttons();
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() {
// 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;
}
}
}
}
int main() {
init();
while (1) {
loop();
}
}