--- /dev/null
+#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
--- /dev/null
+#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;
+ }
+}
#include <LiquidCrystal.h>
-// 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;
"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;
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;
}
void loop()
{
- led_tasks();
+ leds_tasks();
button_tasks();
bl_tasks();