From: Camil Staps Date: Sat, 17 Jun 2017 14:55:40 +0000 (+0000) Subject: Restructure X-Git-Url: https://git.martlubbers.net/?a=commitdiff_plain;h=630227a519f694d62fa02cf2a484e9ad37303823;p=liquid-crystal-terminal.git Restructure --- diff --git a/terminal/button.h b/terminal/button.h new file mode 100644 index 0000000..03ec868 --- /dev/null +++ b/terminal/button.h @@ -0,0 +1,10 @@ +#ifndef _H_BUTTON +#define _H_BUTTON + +// Button pin +#define BUTTON 14 // Analog 0; push button + +void button_setup(void); +void button_tasks(void); + +#endif diff --git a/terminal/button.ino b/terminal/button.ino new file mode 100644 index 0000000..f0b0be0 --- /dev/null +++ b/terminal/button.ino @@ -0,0 +1,13 @@ +#include "button.h" + +void button_setup(void) +{ + pinMode(BUTTON, INPUT); +} + +void button_tasks(void) +{ + if (digitalRead(BUTTON)) { + bl_set(BL_FLASH); + } +} diff --git a/terminal/lcd.h b/terminal/lcd.h new file mode 100644 index 0000000..ee284e1 --- /dev/null +++ b/terminal/lcd.h @@ -0,0 +1,57 @@ +#ifndef _H_LCD +#define _H_LCD + +// LCD pins +#define LCD_REGSEL 3 // Register select +#define LCD_ENABLE 4 // Chip enable +#define LCD_D4 5 // Data line +#define LCD_D5 6 // Data line +#define LCD_D6 7 // Data line +#define LCD_D7 8 // Data line +#define LCD_BL 2 // Backlight + +LiquidCrystal lcd(LCD_REGSEL, LCD_ENABLE, LCD_D4, LCD_D5, LCD_D6, LCD_D7); + +enum backlight_state { + BL_OFF, + BL_ON, + BL_FLASH +}; + +struct backlight { + enum backlight_state state; + unsigned int timer; +}; + +#define COLS 40 +#define ROWS 2 + +/** + * Special characters. + * See https://www.quinapalus.com/hd44780udg.html to make more. + * Define which ones are used (max. 8) in setup(). + * When they need to be changed at runtime, make sure the cursor is disabled + * and call setCursor afterwards. + */ +unsigned char char_music[8] = {0x02,0x03,0x02,0x0e,0x1e,0x0c,0x00}; +unsigned char char_smile[8] = {0x00,0x00,0x0a,0x00,0x11,0x0e,0x00}; +unsigned char char_bar_1[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1f}; +unsigned char char_bar_2[8] = {0x00,0x00,0x00,0x00,0x00,0x1f,0x1f}; +unsigned char char_bar_3[8] = {0x00,0x00,0x00,0x00,0x1f,0x1f,0x1f}; +unsigned char char_bar_4[8] = {0x00,0x00,0x00,0x1f,0x1f,0x1f,0x1f}; +unsigned char char_bar_5[8] = {0x00,0x00,0x1f,0x1f,0x1f,0x1f,0x1f}; +unsigned char char_bar_6[8] = {0x00,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f}; +unsigned char char_bar_7[8] = {0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f}; +unsigned char char_hbar_start_empty[8] = {0x1f,0x10,0x10,0x10,0x10,0x10,0x1f}; +unsigned char char_hbar_start_full[8] = {0x1f,0x10,0x17,0x17,0x17,0x10,0x1f}; +unsigned char char_hbar_inner_empty[8] = {0x1f,0x00,0x00,0x00,0x00,0x00,0x1f}; +unsigned char char_hbar_inner_half[8] = {0x1f,0x00,0x1c,0x1c,0x1c,0x00,0x1f}; +unsigned char char_hbar_inner_full[8] = {0x1f,0x00,0x1f,0x1f,0x1f,0x00,0x1f}; +unsigned char char_hbar_end_empty[8] = {0x1f,0x01,0x01,0x01,0x01,0x01,0x1f}; +unsigned char char_hbar_end_full[8] = {0x1f,0x01,0x1d,0x1d,0x1d,0x01,0x1f}; + +void lcd_setup(void); +void bl_tasks(void); +void bl_set(enum backlight_state); + +#endif diff --git a/terminal/lcd.ino b/terminal/lcd.ino new file mode 100644 index 0000000..61c352c --- /dev/null +++ b/terminal/lcd.ino @@ -0,0 +1,38 @@ +#include "lcd.h" + +struct backlight backlight; + +void lcd_setup(void) +{ + lcd.createChar(0, char_music); + lcd.createChar(1, char_smile); + + lcd.begin(COLS, ROWS); + lcd.blink(); + + pinMode(LCD_BL, OUTPUT); +} + +void bl_tasks(void) +{ + if (backlight.state == BL_FLASH) + if (!--backlight.timer) + backlight.state = BL_OFF; + + switch (backlight.state) { + case BL_OFF: + digitalWrite(LCD_BL, 0); + break; + case BL_FLASH: + case BL_ON: + digitalWrite(LCD_BL, 1); + break; + } +} + +void bl_set(enum backlight_state state) +{ + backlight.state = state; + if (state == BL_FLASH) + backlight.timer = (unsigned int) -1; +} diff --git a/terminal/leds.h b/terminal/leds.h new file mode 100644 index 0000000..9f529f2 --- /dev/null +++ b/terminal/leds.h @@ -0,0 +1,29 @@ +#ifndef _H_LEDS +#define _H_LEDS + +// LED pins +#define LEDS_GRN 15 // Analog 1; Common green anode +#define LEDS_RED 16 // Analog 2; Common red anode +#define LED1 13 // LED1 cathode +#define LED2 12 // LED2 cathode +#define LED3 11 // LED3 cathode +#define LED4 10 // LED4 cathode + +#define LED_OFF 0x00 +#define LED_GRN 0x01 +#define LED_RED 0x02 +#define LED_BLINK 0x04 + +struct leds { + unsigned char a:3; + unsigned char b:3; + unsigned char c:3; + unsigned char d:3; + unsigned int counter; +}; +struct leds leds; + +void leds_setup(void); +void leds_tasks(void); + +#endif diff --git a/terminal/leds.ino b/terminal/leds.ino new file mode 100644 index 0000000..785ce32 --- /dev/null +++ b/terminal/leds.ino @@ -0,0 +1,70 @@ +#include "leds.h" + +void leds_setup(void) +{ + pinMode(LEDS_GRN, OUTPUT); + pinMode(LEDS_RED, OUTPUT); + pinMode(LED1, OUTPUT); + pinMode(LED2, OUTPUT); + pinMode(LED3, OUTPUT); + pinMode(LED4, OUTPUT); +} + +/** + * Tasks for the LEDs. Needs to be called every few ms(?) for multiplexing. + * When an LED is blinking and in the off period, it is necessary to call + * digitalWrite() twice and set the cathode. This ensures that the function + * takes equally long to return on every iteration, s.t. the blinking duty + * cycle is exactly 50% and LEDs blink equally bright, regardless of the status + * of other LEDs. + */ +void leds_tasks(void) +{ + leds.counter++; + switch (leds.counter & 0x03) { + case 0: + digitalWrite(LED4, 1); + if ((leds.a & LED_BLINK) && leds.counter & 0x4000) { + digitalWrite(LEDS_GRN, 0); + digitalWrite(LEDS_RED, 0); + } else { + digitalWrite(LEDS_GRN, leds.a & 1); + digitalWrite(LEDS_RED, leds.a & 2); + } + digitalWrite(LED1, 0); + break; + case 1: + digitalWrite(LED1, 1); + if ((leds.b & LED_BLINK) && leds.counter & 0x4000) { + digitalWrite(LEDS_GRN, 0); + digitalWrite(LEDS_RED, 0); + } else { + digitalWrite(LEDS_GRN, leds.b & 1); + digitalWrite(LEDS_RED, leds.b & 2); + } + digitalWrite(LED2, 0); + break; + case 2: + digitalWrite(LED2, 1); + if ((leds.c & LED_BLINK) && leds.counter & 0x4000) { + digitalWrite(LEDS_GRN, 0); + digitalWrite(LEDS_RED, 0); + } else { + digitalWrite(LEDS_GRN, leds.c & 1); + digitalWrite(LEDS_RED, leds.c & 2); + } + digitalWrite(LED3, 0); + break; + case 3: + digitalWrite(LED3, 1); + if ((leds.d & LED_BLINK) && leds.counter & 0x4000) { + digitalWrite(LEDS_GRN, 0); + digitalWrite(LEDS_RED, 0); + } else { + digitalWrite(LEDS_GRN, leds.d & 1); + digitalWrite(LEDS_RED, leds.d & 2); + } + digitalWrite(LED4, 0); + break; + } +} diff --git a/terminal/term.h b/terminal/term.h new file mode 100644 index 0000000..72d04d2 --- /dev/null +++ b/terminal/term.h @@ -0,0 +1,14 @@ +#ifndef _H_TERM +#define _H_TERM + +struct terminal { + unsigned char x; + unsigned char y; + char contents[COLS * ROWS]; +}; + +void redraw(struct terminal *); +void scroll_up(struct terminal *); +void write(struct terminal *, char); + +#endif diff --git a/terminal/term.ino b/terminal/term.ino new file mode 100644 index 0000000..189735c --- /dev/null +++ b/terminal/term.ino @@ -0,0 +1,63 @@ +#include "term.h" + +void redraw(struct terminal *term) +{ + lcd.noCursor(); + lcd.clear(); + lcd.home(); + for (byte i = 0; i < COLS * ROWS; i++) { + if (i % COLS == 0) + lcd.setCursor(i % COLS, i / COLS); + lcd.write(term->contents[i]); + } + lcd.cursor(); +} + +void scroll_up(struct terminal *term) +{ + for (byte i = 0; i < COLS * (ROWS - 1); i++) + term->contents[i] = term->contents[i + COLS]; + for (byte i = COLS * (ROWS - 1); i < COLS * ROWS; i++) + term->contents[i] = ' '; + redraw(term); +} + +/** + * Special character meanings are defined here. + */ +void write(struct terminal *term, char ch) +{ + switch (ch) { + case '\r': + term->x = 0; + lcd.setCursor(term->x, term->y); + break; + case '\n': + if (++term->y >= ROWS) { + term->y--; + scroll_up(term); + } + lcd.setCursor(term->x, term->y); + break; + case 0x7f: + if (term->x != 0) { + term->x--; + term->contents[term->x + term->y * COLS] = 0x00; + lcd.setCursor(term->x, term->y); + lcd.write(' '); + lcd.setCursor(term->x, term->y); + } + break; + default: + term->contents[term->x + term->y * COLS] = ch; + lcd.write(ch); + if (++term->x >= COLS) { + term->x = 0; + if (++term->y >= ROWS) { + term->y--; + scroll_up(term); + } + lcd.setCursor(term->x, term->y); + } + } +} diff --git a/terminal/terminal.ino b/terminal/terminal.ino index 5880acf..7709be2 100644 --- a/terminal/terminal.ino +++ b/terminal/terminal.ino @@ -1,146 +1,9 @@ #include -// LED pins -#define LEDS_GRN 15 // Analog 1; Common green anode -#define LEDS_RED 16 // Analog 2; Common red anode -#define LED1 13 // LED1 cathode -#define LED2 12 // LED2 cathode -#define LED3 11 // LED3 cathode -#define LED4 10 // LED4 cathode - -#define LED_OFF 0x00 -#define LED_GRN 0x01 -#define LED_RED 0x02 -#define LED_BLINK 0x04 - -struct leds { - byte a:3; - byte b:3; - byte c:3; - byte d:3; - unsigned int counter; -}; -struct leds leds; - -// Button pin -#define BUTTON 14 // Analog 0; push button - -// LCD pins -#define LCD_REGSEL 3 // Register select -#define LCD_ENABLE 4 // Chip enable -#define LCD_D4 5 // Data line -#define LCD_D5 6 // Data line -#define LCD_D6 7 // Data line -#define LCD_D7 8 // Data line -#define LCD_BL 2 // Backlight - -LiquidCrystal lcd(LCD_REGSEL, LCD_ENABLE, LCD_D4, LCD_D5, LCD_D6, LCD_D7); - -enum backlight_state { - BL_OFF, - BL_ON, - BL_FLASH -}; -struct backlight { - enum backlight_state state; - unsigned int timer; -}; -struct backlight backlight; - -#define COLS 40 -#define ROWS 2 - -/** - * Special characters. - * See https://www.quinapalus.com/hd44780udg.html to make more. - * Define which ones are used (max. 8) in setup(). - * When they need to be changed at runtime, make sure the cursor is disabled - * and call setCursor afterwards. - */ -byte char_music[8] = {0x02,0x03,0x02,0x0e,0x1e,0x0c,0x00}; -byte char_smile[8] = {0x00,0x00,0x0a,0x00,0x11,0x0e,0x00}; -byte char_bar_1[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1f}; -byte char_bar_2[8] = {0x00,0x00,0x00,0x00,0x00,0x1f,0x1f}; -byte char_bar_3[8] = {0x00,0x00,0x00,0x00,0x1f,0x1f,0x1f}; -byte char_bar_4[8] = {0x00,0x00,0x00,0x1f,0x1f,0x1f,0x1f}; -byte char_bar_5[8] = {0x00,0x00,0x1f,0x1f,0x1f,0x1f,0x1f}; -byte char_bar_6[8] = {0x00,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f}; -byte char_bar_7[8] = {0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f}; -byte char_hbar_start_empty[8] = {0x1f,0x10,0x10,0x10,0x10,0x10,0x1f}; -byte char_hbar_start_full[8] = {0x1f,0x10,0x17,0x17,0x17,0x10,0x1f}; -byte char_hbar_inner_empty[8] = {0x1f,0x00,0x00,0x00,0x00,0x00,0x1f}; -byte char_hbar_inner_half[8] = {0x1f,0x00,0x1c,0x1c,0x1c,0x00,0x1f}; -byte char_hbar_inner_full[8] = {0x1f,0x00,0x1f,0x1f,0x1f,0x00,0x1f}; -byte char_hbar_end_empty[8] = {0x1f,0x01,0x01,0x01,0x01,0x01,0x1f}; -byte char_hbar_end_full[8] = {0x1f,0x01,0x1d,0x1d,0x1d,0x01,0x1f}; - -struct terminal { - byte x; - byte y; - char contents[COLS * ROWS]; -}; - -void redraw(struct terminal *term) -{ - lcd.noCursor(); - lcd.clear(); - lcd.home(); - for (byte i = 0; i < COLS * ROWS; i++) { - if (i % COLS == 0) - lcd.setCursor(i % COLS, i / COLS); - lcd.write(term->contents[i]); - } - lcd.cursor(); -} - -void scroll_up(struct terminal *term) -{ - for (byte i = 0; i < COLS * (ROWS - 1); i++) - term->contents[i] = term->contents[i + COLS]; - for (byte i = COLS * (ROWS - 1); i < COLS * ROWS; i++) - term->contents[i] = ' '; - redraw(term); -} - -/** - * Special character meanings are defined here. - */ -void write(struct terminal *term, char ch) -{ - switch (ch) { - case '\r': - term->x = 0; - lcd.setCursor(term->x, term->y); - break; - case '\n': - if (++term->y >= ROWS) { - term->y--; - scroll_up(term); - } - lcd.setCursor(term->x, term->y); - break; - case 0x7f: - if (term->x != 0) { - term->x--; - term->contents[term->x + term->y * COLS] = 0x00; - lcd.setCursor(term->x, term->y); - lcd.write(' '); - lcd.setCursor(term->x, term->y); - } - break; - default: - term->contents[term->x + term->y * COLS] = ch; - lcd.write(ch); - if (++term->x >= COLS) { - term->x = 0; - if (++term->y >= ROWS) { - term->y--; - scroll_up(term); - } - lcd.setCursor(term->x, term->y); - } - } -} +#include "button.h" +#include "lcd.h" +#include "leds.h" +#include "term.h" struct terminal term; @@ -148,121 +11,20 @@ char message[] = "Beste Mart, van harte gefeliciteerd! \x01\x00\r\n" "Hier een herprogrammeerbare terminal. "; -/** - * Tasks for the LEDs. Needs to be called every few ms(?) for multiplexing. - * When an LED is blinking and in the off period, it is necessary to call - * digitalWrite() twice and set the cathode. This ensures that the function - * takes equally long to return on every iteration, s.t. the blinking duty - * cycle is exactly 50% and LEDs blink equally bright, regardless of the status - * of other LEDs. - */ -void led_tasks() -{ - leds.counter++; - switch (leds.counter & 0x03) { - case 0: - digitalWrite(LED4, 1); - if ((leds.a & LED_BLINK) && leds.counter & 0x4000) { - digitalWrite(LEDS_GRN, 0); - digitalWrite(LEDS_RED, 0); - } else { - digitalWrite(LEDS_GRN, leds.a & 1); - digitalWrite(LEDS_RED, leds.a & 2); - } - digitalWrite(LED1, 0); - break; - case 1: - digitalWrite(LED1, 1); - if ((leds.b & LED_BLINK) && leds.counter & 0x4000) { - digitalWrite(LEDS_GRN, 0); - digitalWrite(LEDS_RED, 0); - } else { - digitalWrite(LEDS_GRN, leds.b & 1); - digitalWrite(LEDS_RED, leds.b & 2); - } - digitalWrite(LED2, 0); - break; - case 2: - digitalWrite(LED2, 1); - if ((leds.c & LED_BLINK) && leds.counter & 0x4000) { - digitalWrite(LEDS_GRN, 0); - digitalWrite(LEDS_RED, 0); - } else { - digitalWrite(LEDS_GRN, leds.c & 1); - digitalWrite(LEDS_RED, leds.c & 2); - } - digitalWrite(LED3, 0); - break; - case 3: - digitalWrite(LED3, 1); - if ((leds.d & LED_BLINK) && leds.counter & 0x4000) { - digitalWrite(LEDS_GRN, 0); - digitalWrite(LEDS_RED, 0); - } else { - digitalWrite(LEDS_GRN, leds.d & 1); - digitalWrite(LEDS_RED, leds.d & 2); - } - digitalWrite(LED4, 0); - break; - } -} - -void button_tasks() -{ - if (digitalRead(BUTTON)) { - bl_flash(); - } -} - -void bl_tasks() -{ - if (backlight.state == BL_FLASH) - if (!--backlight.timer) - backlight.state = BL_OFF; - - switch (backlight.state) { - case BL_OFF: - digitalWrite(LCD_BL, 0); - break; - case BL_FLASH: - case BL_ON: - digitalWrite(LCD_BL, 1); - break; - } -} - -void bl_flash() -{ - backlight.state = BL_FLASH; - backlight.timer = (unsigned int) -1; -} - void setup() { - lcd.createChar(0, char_music); - lcd.createChar(1, char_smile); - - lcd.begin(COLS, ROWS); - lcd.blink(); Serial.begin(115200); + lcd_setup(); + leds_setup(); + button_setup(); + for (byte i = 0; i < ROWS * COLS; i++) term.contents[i] = ' '; for (byte i = 0; i < sizeof(message) - 1; i++) write(&term, message[i]); - pinMode(LCD_BL, OUTPUT); - - pinMode(LEDS_GRN, OUTPUT); - pinMode(LEDS_RED, OUTPUT); - pinMode(LED1, OUTPUT); - pinMode(LED2, OUTPUT); - pinMode(LED3, OUTPUT); - pinMode(LED4, OUTPUT); - - pinMode(BUTTON, INPUT); - leds.a = LED_GRN | LED_BLINK; leds.b = LED_RED | LED_BLINK; leds.c = LED_GRN | LED_BLINK; @@ -304,10 +66,7 @@ void handle_character(char c) break; case S_BACKLIGHT: - if (c == 0x02) - bl_flash(); - else - backlight.state = (enum backlight_state) c; + bl_set((enum backlight_state) c); read_state = S_DEFAULT; break; } @@ -315,7 +74,7 @@ void handle_character(char c) void loop() { - led_tasks(); + leds_tasks(); button_tasks(); bl_tasks();