From 65caaa0a507ed3845ba43b7f82a16d310fc0a100 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sun, 26 Jun 2022 12:40:04 -0400 Subject: [PATCH] Hugely refactor the display --- display/display.c | 155 +++++++++++++++++++++ display/display.h | 50 +++++++ flake.nix | 7 +- lcd/main.c | 80 ++--------- shift_register/{reg.c => shift_register.c} | 0 shift_register/{reg.h => shift_register.h} | 0 6 files changed, 217 insertions(+), 75 deletions(-) create mode 100644 display/display.c create mode 100644 display/display.h rename shift_register/{reg.c => shift_register.c} (100%) rename shift_register/{reg.h => shift_register.h} (100%) diff --git a/display/display.c b/display/display.c new file mode 100644 index 0000000..759af0f --- /dev/null +++ b/display/display.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include + +/* +struct CHAR { + char c; + uint8_t bits; +}; + +struct CHAR CHARSET[96] = { + { .c = ' ', .bits = 0x20 }, + { .c = '!', .bits = 0x21 }, + { .c = '"', .bits = 0x22 }, + { .c = '#', .bits = 0x23 }, + { .c = '$', .bits = 0x24 }, + { .c = '%', .bits = 0x25 }, + { .c = '&', .bits = 0x26 }, + { .c = ''', .bits = 0x27 }, + { .c = '(', .bits = 0x28 }, + { .c = ')', .bits = 0x29 }, + { .c = '*', .bits = 0x2a }, + { .c = '+', .bits = 0x2b }, + { .c = ',', .bits = 0x2c }, + { .c = '-', .bits = 0x2d }, + { .c = '.', .bits = 0x2e }, + { .c = '/', .bits = 0x2f }, + { .c = '0', .bits = 0x30 }, + { .c = '1', .bits = 0x31 }, + { .c = '2', .bits = 0x32 }, + { .c = '3', .bits = 0x33 }, + { .c = '4', .bits = 0x34 }, + { .c = '5', .bits = 0x35 }, + { .c = '6', .bits = 0x36 }, + { .c = '7', .bits = 0x37 }, + { .c = '8', .bits = 0x38 }, + { .c = '9', .bits = 0x39 }, + { .c = ':', .bits = 0x3a }, + { .c = ';', .bits = 0x3b }, + { .c = '<', .bits = 0x3c }, + { .c = '=', .bits = 0x3d }, + { .c = '>', .bits = 0x3e }, + { .c = '?', .bits = 0x3f }, + { .c = '@', .bits = 0x40 }, + { .c = 'A', .bits = 0x41 }, + { .c = 'B', .bits = 0x42 }, + { .c = 'C', .bits = 0x43 }, + { .c = 'D', .bits = 0x44 }, + { .c = 'E', .bits = 0x45 }, + { .c = 'F', .bits = 0x46 }, + { .c = 'G', .bits = 0x47 }, + { .c = 'H', .bits = 0x48 }, + { .c = 'I', .bits = 0x49 }, + { .c = 'J', .bits = 0x4a }, + { .c = 'K', .bits = 0x4b }, + { .c = 'L', .bits = 0x4c }, + { .c = 'M', .bits = 0x4d }, + { .c = 'N', .bits = 0x4e }, + { .c = 'O', .bits = 0x4f }, + { .c = 'P', .bits = 0x50 }, + { .c = 'Q', .bits = 0x51 }, + { .c = 'R', .bits = 0x52 }, + { .c = 'S', .bits = 0x53 }, + { .c = 'T', .bits = 0x54 }, + { .c = 'U', .bits = 0x55 }, + { .c = 'V', .bits = 0x56 }, + { .c = 'W', .bits = 0x57 }, + { .c = 'X', .bits = 0x58 }, + { .c = 'Y', .bits = 0x59 }, + { .c = 'Z', .bits = 0x5a }, + { .c = '[', .bits = 0x5b }, + { .c = ' ', .bits = 0x5c }, + { .c = ']', .bits = 0x5d }, + { .c = '^', .bits = 0x5e }, + { .c = '_', .bits = 0x5f }, + { .c = '`', .bits = 0x60 }, + { .c = 'a', .bits = 0x61 }, + { .c = 'b', .bits = 0x62 }, + { .c = 'c', .bits = 0x63 }, + { .c = 'd', .bits = 0x64 }, + { .c = 'e', .bits = 0x65 }, + { .c = 'f', .bits = 0x66 }, + { .c = 'g', .bits = 0x67 }, + { .c = 'h', .bits = 0x68 }, + { .c = 'i', .bits = 0x69 }, + { .c = 'j', .bits = 0x6a }, + { .c = 'k', .bits = 0x6b }, + { .c = 'l', .bits = 0x6c }, + { .c = 'm', .bits = 0x6d }, + { .c = 'n', .bits = 0x6e }, + { .c = 'o', .bits = 0x6f }, + { .c = 'p', .bits = 0 }, + { .c = 'q', .bits = 0 }, + { .c = 'r', .bits = 0 }, + { .c = 's', .bits = 0 }, + { .c = 't', .bits = 0 }, + { .c = 'u', .bits = 0 }, + { .c = 'v', .bits = 0 }, + { .c = 'w', .bits = 0 }, + { .c = 'x', .bits = 0 }, + { .c = 'y', .bits = 0 }, + { .c = 'z', .bits = 0 }, + { .c = ' ', .bits = 0 }, + { .c = ' ', .bits = 0 }, + { .c = ' ', .bits = 0 }, + { .c = ' ', .bits = 0 }, + { .c = ' ', .bits = 0 }, +}; +*/ + +void display_strobe_line(gpio_t *line) { + set_line(line); + _delay_us(100); + clear_line(line); + _delay_us(100); +} + +void write_instruction(display_t *disp, uint8_t bitcode) { + clear_line(&disp->register_select); + sr_send_msb(&disp->reg, bitcode); + _delay_ms(1); + display_strobe_line(&disp->enable); +} + +void write_char(display_t *disp, uint8_t bitcode) { + set_line(&disp->register_select); + sr_send_msb(&disp->reg, bitcode); + _delay_ms(1); + display_strobe_line(&disp->enable); +} + +void display_init(display_t *disp) { + sr_initialize(&disp->reg); + set_line_direction(&disp->register_select, LINE_OUT); + set_line_direction(&disp->enable, LINE_OUT); + write_instruction(disp, 0b00111100); +} + +void display_clear(display_t *disp) { + write_instruction(disp, 0x01); + write_instruction(disp, 0x02); +} + +void display_enable(display_t *disp) { + write_instruction(disp, 0x0e); +} + +void display_write_message(display_t *disp, const char *msg) { + for (size_t i = 0; msg[i] != 0; i++) { + write_char(disp, msg[i]); + } +} + + diff --git a/display/display.h b/display/display.h new file mode 100644 index 0000000..6745b23 --- /dev/null +++ b/display/display.h @@ -0,0 +1,50 @@ +/* This library covers a five-wire diagnostic display board. + * + * Hardware: + * 74HC595 shift register + * Adafruit HD44780 LCD + * + * Input pins: + * SDI -- Serial data in. This leads to the 74HC595, pin 14 (A). + * CLK -- Clock pulse. One bit will be shifted into the device on each rising + * edge. This leads to the 74HC595, pin 11 (Shift Clock). + * LS -- Latch pulse. All data in the shift register will be sent to the + * output on a rising edge. This leads to the 74HC595, pin 12 (Latch Clock); + * RS -- Register select. 0 to write an instruction to the display, 1 to write + * data to the display. + * E -- Enable. This tells the display to read the data. The display will get + * the data on the shift register outputs, so be sure to send LS before + * sending E. + * + * 74HC595 -> HD44780 + * Qa -> D0 + * Qb -> D1 + * Qc -> D2 + * Qd -> D3 + * Qe -> D4 + * Qf -> D5 + * Qg -> D6 + * Qh -> D7 + */ + +#ifndef __DISPLAY_H__ +#define __DISPLAY_H__ + +#include + +typedef struct DISPLAY { + shift_register_t reg; + gpio_t register_select; + gpio_t enable; +} display_t; + +void display_init(display_t *); + +void display_clear(display_t *); + +void display_enable(display_t *); + +void display_write_message(display_t *, const char *); + +#endif + diff --git a/flake.nix b/flake.nix index 255f076..b215a46 100644 --- a/flake.nix +++ b/flake.nix @@ -106,7 +106,7 @@ name = "lcd"; src = ./.; - includes = [ "base" "shift_register" "spi" ]; + includes = [ "base" "display" "shift_register" "spi" ]; MCU = "atmega32u4"; CHIP_SELECT = "AVR_ATmega32u4"; @@ -117,9 +117,10 @@ buildPhase = '' ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o base.o -c ${src}/base/base.c ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o spi.o -c ${src}/spi/spi.c - ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o reg.o -c ${src}/shift_register/reg.c + ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o reg.o -c ${src}/shift_register/shift_register.c + ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o display.o -c ${src}/display/display.c ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o main.o -c ${src}/lcd/main.c - ${avr.gcc}/bin/avr-gcc ${CFLAGS} -o main.elf main.o reg.o spi.o base.o + ${avr.gcc}/bin/avr-gcc ${CFLAGS} -o main.elf main.o display.o reg.o spi.o base.o $OBJCOPY -O ihex main.elf main.hex ''; installPhase = '' diff --git a/lcd/main.c b/lcd/main.c index 85bb654..91cea63 100644 --- a/lcd/main.c +++ b/lcd/main.c @@ -2,76 +2,11 @@ #include #include #include -#include - -typedef struct HD44780 { - shift_register_t reg; - gpio_t register_select; - gpio_t enable; -} hd44780_t; - -void strobe_line(gpio_t *line) { - set_line(line); - _delay_ms(1); - clear_line(line); - _delay_ms(1); -} - -void hd44780_init(hd44780_t *disp) { - spi_initialize(disp); - set_line_direction(&disp->register_select, LINE_OUT); - set_line_direction(&disp->enable, LINE_OUT); - send_msb(&disp->reg, 0b00111100); -} - -void hd44780_clear(hd44780_t *disp) { - clear_line(&disp->register_select); - send_msb(&disp->reg, 0b00000001); - _delay_ms(1); - strobe_line(&disp->enable); - - send_msb(&disp->reg, 0b00000010); - _delay_ms(1); - strobe_line(&disp->enable); -} - -void hd44780_display(hd44780_t *disp) { - clear_line(&disp->register_select); - send_msb(&disp->reg, 0b00001110); - _delay_ms(1); - strobe_line(&disp->enable); -} - -void hd44780_write_char(hd44780_t *disp, uint8_t bitcode) { - set_line(&disp->register_select); - send_msb(&disp->reg, bitcode); - strobe_line(&disp->enable); -} - -void hd44780_write(hd44780_t *disp) { - set_line(&disp->register_select); - - hd44780_write_char(disp, 0b01001000); - hd44780_write_char(disp, 0b01000101); - hd44780_write_char(disp, 0b01001100); - hd44780_write_char(disp, 0b01001100); - hd44780_write_char(disp, 0b01001111); - hd44780_write_char(disp, 0b00101100); - - hd44780_write_char(disp, 0b00100000); - - hd44780_write_char(disp, 0b01001101); - hd44780_write_char(disp, 0b01011001); - - hd44780_write_char(disp, 0b00100000); - - hd44780_write_char(disp, 0b01000010); - hd44780_write_char(disp, 0b01000001); - hd44780_write_char(disp, 0b01010100); -} +#include +#include int main(void) { - hd44780_t display = { + display_t display = { .reg = { .output = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 5 }, .latch_clock = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 6 }, @@ -85,13 +20,14 @@ int main(void) { set_line_direction(&light, LINE_OUT); clear_line(&light); - hd44780_init(&display); + display_init(&display); - hd44780_clear(&display); + display_clear(&display); _delay_ms(500); - hd44780_write(&display); - hd44780_display(&display); + const char msg[] = "Hello, my bat"; + display_write_message(&display, msg); + display_enable(&display); set_line(&light); diff --git a/shift_register/reg.c b/shift_register/shift_register.c similarity index 100% rename from shift_register/reg.c rename to shift_register/shift_register.c diff --git a/shift_register/reg.h b/shift_register/shift_register.h similarity index 100% rename from shift_register/reg.h rename to shift_register/shift_register.h