From c1053d19630a65f26b0214265309721f1be575af Mon Sep 17 00:00:00 2001 From: Gregor Riepl Date: Sat, 6 Mar 2021 13:21:23 +0100 Subject: [PATCH] Added display firmware skeleton --- display/firmware/Makefile | 116 ++++++++++++++++++++++++++++++++++ display/firmware/can_config.h | 79 +++++++++++++++++++++++ display/firmware/main.c | 96 ++++++++++++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 display/firmware/Makefile create mode 100644 display/firmware/can_config.h create mode 100644 display/firmware/main.c diff --git a/display/firmware/Makefile b/display/firmware/Makefile new file mode 100644 index 0000000..00a3a27 --- /dev/null +++ b/display/firmware/Makefile @@ -0,0 +1,116 @@ +PRG = display +PROJ_ROOT = ../.. +AVRCANLIB_PATH = $(PROJ_ROOT)/avr-can-lib +OBJ = main.o \ + $(AVRCANLIB_PATH)/src/at90can_buffer.o \ + $(AVRCANLIB_PATH)/src/at90can.o \ + $(AVRCANLIB_PATH)/src/at90can_disable_dyn_filter.o \ + $(AVRCANLIB_PATH)/src/at90can_error_register.o \ + $(AVRCANLIB_PATH)/src/at90can_get_buf_message.o \ + $(AVRCANLIB_PATH)/src/at90can_get_dyn_filter.o \ + $(AVRCANLIB_PATH)/src/at90can_get_message.o \ + $(AVRCANLIB_PATH)/src/at90can_send_buf_message.o \ + $(AVRCANLIB_PATH)/src/at90can_send_message.o \ + $(AVRCANLIB_PATH)/src/at90can_set_dyn_filter.o \ + $(AVRCANLIB_PATH)/src/at90can_set_mode.o \ + $(AVRCANLIB_PATH)/src/can_buffer.o +# These were defined for the avr-can-lib, but they really, really +# shouldn't be used there because they affect the whole program. +OPTIMIZE = -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +PROGRAMMER = usbtiny + +MCU_TARGET = atmega32m1 +DEFS = -DF_CPU=16000000UL -DHAS_CAN_CONFIG_H + +INCLUDES = -I. -I$(PROJ_ROOT) -I$(AVRCANLIB_PATH) +LIBS = + +LFUSE = 0xdf +HFUSE = 0xd9 +EFUSE = 0xfe + +EXTRA_CLEAN_FILES = + +# You should not have to change anything below here. + +CC = avr-gcc +DUDE = avrdude + +HOST_CC = gcc +HOST_CFLAGS = -O0 -g +HOST_LDFLAGS = + +# Override is only needed by avr-lib build system. + +override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) $(INCLUDES) +override LDFLAGS = -Wl,-Map,$(PRG).map + +DUDEFLAGS = -c $(PROGRAMMER) -p $(MCU_TARGET) + +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump + +all: $(PRG).elf lst text eeprom + +$(PRG).elf: $(OBJ) $(LIBS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + +clean: + rm -f $(OBJ) $(PRG).elf $(PRG).lst $(PRG).map $(PRG).bin $(PRG).hex $(PRG).srec $(PRG)_eeprom.bin $(PRG)_eeprom.hex $(PRG)_eeprom.srec $(EXTRA_CLEAN_FILES) + +lst: $(PRG).lst + +%.lst: %.elf + $(OBJDUMP) -h -S $< > $@ + +# Rules for flashing, EEPROM writing and fuse bit setting + +flash: $(PRG).hex $(PRG)_eeprom.hex + $(DUDE) $(DUDEFLAGS) -U eeprom:w:$(PRG)_eeprom.hex:i -U flash:w:$(PRG).hex:i + +flashprg: $(PRG).hex + $(DUDE) $(DUDEFLAGS) -U flash:w:$(PRG).hex:i + +flasheep: $(PRG)_eeprom.hex + $(DUDE) $(DUDEFLAGS) -U eeprom:w:$(PRG)_eeprom.hex:i + +fuse: + $(DUDE) $(DUDEFLAGS) -U hfuse:w:$(HFUSE):m -U lfuse:w:$(LFUSE):m -U efuse:w:$(EFUSE):m + +# Rules for building the .text rom images + +text: hex bin srec + +hex: $(PRG).hex +bin: $(PRG).bin +srec: $(PRG).srec + +%.hex: %.elf + $(OBJCOPY) -j .text -j .data -O ihex $< $@ + +%.srec: %.elf + $(OBJCOPY) -j .text -j .data -O srec $< $@ + +%.bin: %.elf + $(OBJCOPY) -j .text -j .data -O binary $< $@ + +# Rules for building the .eeprom rom images + +eeprom: ehex ebin esrec + +ehex: $(PRG)_eeprom.hex +ebin: $(PRG)_eeprom.bin +esrec: $(PRG)_eeprom.srec + +%_eeprom.hex: %.elf + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ \ + || { echo empty $@ not generated; exit 0; } + +%_eeprom.srec: %.elf + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@ \ + || { echo empty $@ not generated; exit 0; } + +%_eeprom.bin: %.elf + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@ \ + || { echo empty $@ not generated; exit 0; } + diff --git a/display/firmware/can_config.h b/display/firmware/can_config.h new file mode 100644 index 0000000..547b9db --- /dev/null +++ b/display/firmware/can_config.h @@ -0,0 +1,79 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define CAN_CONFIG_LOADED + +// ----------------------------------------------------------------------------- +/* Global settings for building the can-lib and application program. + * + * The following two #defines must be set identically for the can-lib and + * your application program. They control the underlying CAN struct. If the + * settings disagree, the underlying CAN struct will be broken, with + * unpredictable results. + * If can.h detects that any of the #defines is not defined, it will set them + * to the default values shown here, so it is in your own interest to have a + * consistent setting. Ommiting the #defines in both can-lib and application + * program will apply the defaults in a consistent way too. + * + * Select if you want to use 29 bit identifiers. + */ +#define SUPPORT_EXTENDED_CANID 1 + +/* Select if you want to use timestamps. + * Timestamps are sourced from a register internal to the AT90CAN. + * Selecting them on any other controller will have no effect, they will + * be 0 all the time. + */ +#define SUPPORT_TIMESTAMPS 0 + + +// ----------------------------------------------------------------------------- +/* Global settings for building the can-lib. + * + * Select ONE CAN controller for which you are building the can-lib. + */ +#define SUPPORT_MCP2515 0 +#define SUPPORT_AT90CAN 1 +#define SUPPORT_SJA1000 0 + + +// ----------------------------------------------------------------------------- +/* Setting for MCP2515 + * + * Declare which pins you are using for communication. + * Remember NOT to use them in your application! + * It is a good idea to use bits from the port that carries MOSI, MISO, SCK. + */ +#define MCP2515_CS B,4 +#define MCP2515_INT B,2 + +// ----------------------------------------------------------------------------- +// Setting for SJA1000 + +#define SJA1000_INT E,0 +#define SJA1000_MEMORY_MAPPED 1 + +// memory-mapped interface +#define SJA1000_BASE_ADDR 0x8000 // for ATMega162 + +/* +// port-interface +#define SJA1000_WR D,6 +#define SJA1000_RD D,7 + +#define SJA1000_ALE E,1 +#define SJA1000_CS C,0 +#define SJA1000_DATA A +*/ + +// ----------------------------------------------------------------------------- +// Setting for AT90CAN + +// Number of CAN messages which are buffered in RAM additinally to the MObs +#define CAN_RX_BUFFER_SIZE 16 +#define CAN_TX_BUFFER_SIZE 8 + +// only available if CAN_TX_BUFFER_SIZE > 0 +#define CAN_FORCE_TX_ORDER 1 + +#endif // CONFIG_H diff --git a/display/firmware/main.c b/display/firmware/main.c new file mode 100644 index 0000000..ec84362 --- /dev/null +++ b/display/firmware/main.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include +#include + +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)); + + // 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 = 0; + + if (can_check_free_buffer()) { + can_t msg = { + .id = CAN_MSG_DISPLAY_STATUS, + .flags = { + .rtr = 0, + }, + .length = 2, + .data = { (uint8_t) (status >> 8), (uint8_t) status, }, + }; + can_send_message(&msg); + } +} + +static void write_display(uint8_t command, const uint8_t *data, uint8_t length) { + +} + +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) { + write_display(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(); + } +}