2015-07-10 06:01:56 -07:00
|
|
|
/**
|
2021-05-16 03:01:00 -07:00
|
|
|
* @file HD44780.cpp
|
2015-07-10 06:01:56 -07:00
|
|
|
* @brief HD44780 character display driver
|
|
|
|
*
|
|
|
|
* see http://en.wikipedia.org/wiki/Hitachi_HD44780_LCD_controller
|
|
|
|
* @date 13.12.2013
|
2020-01-13 18:57:43 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
|
2021-08-03 19:05:01 -07:00
|
|
|
#include "pch.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
#if EFI_HD44780_LCD
|
|
|
|
|
2021-05-16 03:01:00 -07:00
|
|
|
#include "HD44780.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
#include "string.h"
|
|
|
|
|
|
|
|
enum {
|
|
|
|
LCD_HD44780_DISPLAY_CLEAR = 0x01,
|
|
|
|
LCD_HD44780_SHIFT_CURSOR_RIGHT = 0x06,
|
|
|
|
LCD_HD44780_DISPLAY_ON = 0x0C,
|
|
|
|
LCD_HD44780_4_BIT_BUS = 0x20,
|
|
|
|
LCD_HD44780_RESET = 0x30,
|
|
|
|
LCD_HD44780_DDRAM_ADDR = 0x80,
|
|
|
|
|
|
|
|
// LCD_2X16_8_BIT_BUS = 0x30,
|
|
|
|
// LCD_2X16_LINE_ONE = 0x20,
|
|
|
|
// LCD_2X16_LINES_TWO = 0x28,
|
|
|
|
// LCD_2X16_FONT_5X8 = 0x20,
|
|
|
|
// LCD_2X16_FONT_5X10 = 0x24,
|
|
|
|
// LCD_2X16_DISPLAY_HOME = 0x02,
|
|
|
|
// LCD_2X16_DISPLAY_RIGHT = 0x1C,
|
|
|
|
// LCD_2X16_DISPLAY_LEFT = 0x18,
|
|
|
|
// LCD_2X16_DISPLAY_SHIFT = 0x05,
|
|
|
|
// LCD_2X16_CURSOR_ON = 0x0A,
|
|
|
|
// LCD_2X16_CURSOR_BLINK = 0x09,
|
|
|
|
// LCD_2X16_CURSOR_RIGHT = 0x14,
|
|
|
|
// LCD_2X16_CURSOR_LEFT = 0x10,
|
|
|
|
// LCD_2X16_SHIFT_LEFT = 0x04,
|
|
|
|
// LCD_2X16_CGRAM_ADDR = 0x40,
|
|
|
|
// LCD_2X16_BUSY_FLAG = 0x80,
|
|
|
|
// LCD_2X16_COMMAND = 0x01,
|
|
|
|
// LCD_2X16_DATA = 0x00,
|
2020-11-23 06:43:16 -08:00
|
|
|
} /*lcd_HD44780_command*/;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
// http://web.alfredstate.edu/weimandn/lcd/lcd_addressing/lcd_addressing_index.html
|
|
|
|
static const int lineStart[] = { 0, 0x40, 0x14, 0x54 };
|
|
|
|
|
|
|
|
static int BUSY_WAIT_DELAY = FALSE;
|
|
|
|
static int currentRow = 0;
|
|
|
|
static int currentColumn = 0;
|
|
|
|
|
|
|
|
static void lcdSleep(int period) {
|
|
|
|
if (BUSY_WAIT_DELAY) {
|
|
|
|
// this mode is useful for displaying messages to report OS fatal issues
|
|
|
|
|
2018-12-23 21:15:00 -08:00
|
|
|
int ticks = CORE_CLOCK / 1000000 * period;
|
2015-07-10 06:01:56 -07:00
|
|
|
int a = 0;
|
|
|
|
for (int i = 0; i < ticks; i++)
|
|
|
|
a += i;
|
|
|
|
// the purpose of this code is to fool the compiler so that the loop is not optimized away
|
2018-07-25 20:03:04 -07:00
|
|
|
efiAssertVoid(CUSTOM_ERR_6656, a != 0, "true");
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
} else {
|
|
|
|
chThdSleepMicroseconds(period);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//static char txbuf[1];
|
|
|
|
#define LCD_PORT_EXP_ADDR 0x20
|
|
|
|
|
2021-11-15 04:02:34 -08:00
|
|
|
static bool lcd_HD44780_is_enabled() {
|
2021-01-09 14:16:10 -08:00
|
|
|
/* check for valid LCD setting */
|
|
|
|
return ((engineConfiguration->displayMode == DM_HD44780) &&
|
2021-11-17 00:54:21 -08:00
|
|
|
(isBrainPinValid(engineConfiguration->HD44780_rs)) &&
|
|
|
|
(isBrainPinValid(engineConfiguration->HD44780_e)) &&
|
|
|
|
(isBrainPinValid(engineConfiguration->HD44780_db4)) &&
|
|
|
|
(isBrainPinValid(engineConfiguration->HD44780_db5)) &&
|
|
|
|
(isBrainPinValid(engineConfiguration->HD44780_db6)) &&
|
|
|
|
(isBrainPinValid(engineConfiguration->HD44780_db7)));
|
2021-01-09 14:16:10 -08:00
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static void lcd_HD44780_write(uint8_t data) {
|
|
|
|
if (engineConfiguration->displayMode == DM_HD44780) {
|
2021-11-17 00:54:21 -08:00
|
|
|
writePad("lcd", engineConfiguration->HD44780_db7,
|
2015-07-10 06:01:56 -07:00
|
|
|
data & 0x80 ? 1 : 0);
|
2021-11-17 00:54:21 -08:00
|
|
|
writePad("lcd", engineConfiguration->HD44780_db6,
|
2015-07-10 06:01:56 -07:00
|
|
|
data & 0x40 ? 1 : 0);
|
2021-11-17 00:54:21 -08:00
|
|
|
writePad("lcd", engineConfiguration->HD44780_db5,
|
2015-07-10 06:01:56 -07:00
|
|
|
data & 0x20 ? 1 : 0);
|
2021-11-17 00:54:21 -08:00
|
|
|
writePad("lcd", engineConfiguration->HD44780_db4,
|
2015-07-10 06:01:56 -07:00
|
|
|
data & 0x10 ? 1 : 0);
|
|
|
|
|
2021-11-17 00:54:21 -08:00
|
|
|
writePad("lcd", engineConfiguration->HD44780_e, 1); // En high
|
2015-07-10 06:01:56 -07:00
|
|
|
lcdSleep(10); // enable pulse must be >450ns
|
2021-11-17 00:54:21 -08:00
|
|
|
writePad("lcd", engineConfiguration->HD44780_e, 0); // En low
|
2015-07-10 06:01:56 -07:00
|
|
|
lcdSleep(40); // commands need > 37us to settle
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// LCD D4_pin -> P4
|
|
|
|
// LCD D5_pin -> P5
|
|
|
|
// LCD D6_pin -> P6
|
|
|
|
// LCD D7_pin -> P7
|
|
|
|
// LCD Pin RS -> P0
|
|
|
|
// LCD Pin RW -> P1
|
|
|
|
// LCD Pin E -> P2
|
|
|
|
|
|
|
|
// todo: finish all this stuff
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2021-01-08 17:01:26 -08:00
|
|
|
static void lcd_HD44780_write_command(uint8_t data) {
|
2021-11-17 00:54:21 -08:00
|
|
|
palClearPad(getHwPort("lcd", engineConfiguration->HD44780_rs), getHwPin("lcd", engineConfiguration->HD44780_rs));
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
lcd_HD44780_write(data);
|
|
|
|
lcd_HD44780_write(data << 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2021-01-08 17:01:26 -08:00
|
|
|
static void lcd_HD44780_write_data(uint8_t data) {
|
2021-11-17 00:54:21 -08:00
|
|
|
palSetPad(getHwPort("lcd", engineConfiguration->HD44780_rs), getHwPin("lcd", engineConfiguration->HD44780_rs));
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
lcd_HD44780_write(data);
|
|
|
|
lcd_HD44780_write(data << 4);
|
|
|
|
currentColumn++;
|
|
|
|
|
2021-11-17 00:54:21 -08:00
|
|
|
palClearPad(getHwPort("lcd", engineConfiguration->HD44780_rs), getHwPin("lcd", engineConfiguration->HD44780_rs));
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void lcd_HD44780_set_position(uint8_t row, uint8_t column) {
|
2021-01-09 14:16:10 -08:00
|
|
|
if (!lcd_HD44780_is_enabled())
|
2021-01-08 17:01:26 -08:00
|
|
|
return;
|
|
|
|
|
2018-07-25 20:03:04 -07:00
|
|
|
efiAssertVoid(CUSTOM_ERR_6657, row <= engineConfiguration->HD44780height, "invalid row");
|
2015-07-10 06:01:56 -07:00
|
|
|
currentRow = row;
|
|
|
|
currentColumn = column;
|
|
|
|
lcd_HD44780_write_command(LCD_HD44780_DDRAM_ADDR + lineStart[row] + column);
|
|
|
|
}
|
|
|
|
|
|
|
|
int getCurrentHD44780row(void) {
|
2021-01-09 14:16:10 -08:00
|
|
|
if (!lcd_HD44780_is_enabled())
|
2021-01-08 17:01:26 -08:00
|
|
|
return 0;
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
return currentRow;
|
|
|
|
}
|
|
|
|
|
|
|
|
int getCurrentHD44780column(void) {
|
2021-01-09 14:16:10 -08:00
|
|
|
if (!lcd_HD44780_is_enabled())
|
2021-01-08 17:01:26 -08:00
|
|
|
return 0;
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
return currentColumn;
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcd_HD44780_print_char(char data) {
|
2021-01-09 14:16:10 -08:00
|
|
|
if (!lcd_HD44780_is_enabled())
|
2021-01-08 17:01:26 -08:00
|
|
|
return;
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
if (data == '\n') {
|
|
|
|
lcd_HD44780_set_position(++currentRow, 0);
|
|
|
|
} else {
|
|
|
|
lcd_HD44780_write_data(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcd_HD44780_print_string(const char* string) {
|
2021-01-09 14:16:10 -08:00
|
|
|
if (!lcd_HD44780_is_enabled())
|
2021-01-08 17:01:26 -08:00
|
|
|
return;
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
while (*string != 0x00)
|
|
|
|
lcd_HD44780_print_char(*string++);
|
|
|
|
}
|
2019-01-09 19:57:33 -08:00
|
|
|
|
2021-11-17 00:54:21 -08:00
|
|
|
//getHwPin(engineConfiguration->HD44780_db7)
|
2021-11-16 01:15:29 -08:00
|
|
|
static void lcdInfo() {
|
2021-11-17 00:54:21 -08:00
|
|
|
efiPrintf("HD44780 RS=%s", hwPortname(engineConfiguration->HD44780_rs));
|
|
|
|
efiPrintf("HD44780 E=%s", hwPortname(engineConfiguration->HD44780_e));
|
|
|
|
efiPrintf("HD44780 D4=%s", hwPortname(engineConfiguration->HD44780_db4));
|
|
|
|
efiPrintf("HD44780 D5=%s", hwPortname(engineConfiguration->HD44780_db5));
|
|
|
|
efiPrintf("HD44780 D6=%s", hwPortname(engineConfiguration->HD44780_db6));
|
|
|
|
efiPrintf("HD44780 D7=%s", hwPortname(engineConfiguration->HD44780_db7));
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2019-04-19 09:42:21 -07:00
|
|
|
void stopHD44780_pins() {
|
2020-11-26 07:55:39 -08:00
|
|
|
efiSetPadUnused(activeConfiguration.HD44780_rs);
|
|
|
|
efiSetPadUnused(activeConfiguration.HD44780_e);
|
|
|
|
efiSetPadUnused(activeConfiguration.HD44780_db4);
|
|
|
|
efiSetPadUnused(activeConfiguration.HD44780_db5);
|
|
|
|
efiSetPadUnused(activeConfiguration.HD44780_db6);
|
|
|
|
efiSetPadUnused(activeConfiguration.HD44780_db7);
|
2019-04-19 09:42:21 -07:00
|
|
|
}
|
|
|
|
|
2021-01-09 14:16:10 -08:00
|
|
|
void startHD44780_pins() {
|
|
|
|
if (lcd_HD44780_is_enabled()) {
|
2015-07-10 06:01:56 -07:00
|
|
|
// initialize hardware lines
|
2021-11-17 00:54:21 -08:00
|
|
|
efiSetPadMode("lcd RS", engineConfiguration->HD44780_rs, PAL_MODE_OUTPUT_PUSHPULL);
|
|
|
|
efiSetPadMode("lcd E", engineConfiguration->HD44780_e, PAL_MODE_OUTPUT_PUSHPULL);
|
|
|
|
efiSetPadMode("lcd DB4", engineConfiguration->HD44780_db4, PAL_MODE_OUTPUT_PUSHPULL);
|
|
|
|
efiSetPadMode("lcd DB5", engineConfiguration->HD44780_db5, PAL_MODE_OUTPUT_PUSHPULL);
|
|
|
|
efiSetPadMode("lcd DB6", engineConfiguration->HD44780_db6, PAL_MODE_OUTPUT_PUSHPULL);
|
|
|
|
efiSetPadMode("lcd DB7", engineConfiguration->HD44780_db7, PAL_MODE_OUTPUT_PUSHPULL);
|
2015-07-10 06:01:56 -07:00
|
|
|
// and zero values
|
2021-11-17 00:54:21 -08:00
|
|
|
writePad("lcd", engineConfiguration->HD44780_rs, 0);
|
|
|
|
writePad("lcd", engineConfiguration->HD44780_e, 0);
|
|
|
|
writePad("lcd", engineConfiguration->HD44780_db4, 0);
|
|
|
|
writePad("lcd", engineConfiguration->HD44780_db5, 0);
|
|
|
|
writePad("lcd", engineConfiguration->HD44780_db6, 0);
|
|
|
|
writePad("lcd", engineConfiguration->HD44780_db7, 0);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
2019-04-19 11:12:13 -07:00
|
|
|
}
|
|
|
|
|
2021-04-21 11:28:48 -07:00
|
|
|
void lcd_HD44780_init() {
|
2019-04-19 11:12:13 -07:00
|
|
|
addConsoleAction("lcdinfo", lcdInfo);
|
|
|
|
|
2021-01-08 17:01:26 -08:00
|
|
|
if (engineConfiguration->displayMode == DM_NONE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-04-19 11:12:13 -07:00
|
|
|
if (engineConfiguration->displayMode > DM_HD44780_OVER_PCF8574) {
|
|
|
|
warning(CUSTOM_ERR_DISPLAY_MODE, "Unexpected displayMode %d", engineConfiguration->displayMode);
|
|
|
|
// I2C pins need initialization, code needs more work & testing
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-21 09:53:13 -07:00
|
|
|
efiPrintf("lcd_HD44780_init %d", engineConfiguration->displayMode);
|
2019-04-19 11:12:13 -07:00
|
|
|
|
2021-01-09 14:16:10 -08:00
|
|
|
if (!lcd_HD44780_is_enabled())
|
2021-01-08 17:01:26 -08:00
|
|
|
return;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-04-21 12:33:58 -07:00
|
|
|
startHD44780_pins();
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
chThdSleepMilliseconds(20); // LCD needs some time to wake up
|
|
|
|
lcd_HD44780_write(LCD_HD44780_RESET); // reset 1x
|
|
|
|
chThdSleepMilliseconds(1);
|
|
|
|
lcd_HD44780_write(LCD_HD44780_RESET); // reset 2x
|
|
|
|
lcd_HD44780_write(LCD_HD44780_RESET); // reset 3x
|
|
|
|
|
|
|
|
lcd_HD44780_write(LCD_HD44780_4_BIT_BUS); // 4 bit, 2 line
|
|
|
|
chThdSleepMicroseconds(40);
|
|
|
|
|
|
|
|
lcd_HD44780_write(LCD_HD44780_4_BIT_BUS); // 4 bit, 2 line
|
|
|
|
lcd_HD44780_write(0x80);
|
|
|
|
chThdSleepMicroseconds(40);
|
|
|
|
|
|
|
|
lcd_HD44780_write_command(0x08); // display and cursor control
|
|
|
|
chThdSleepMicroseconds(40);
|
|
|
|
|
|
|
|
lcd_HD44780_write_command(LCD_HD44780_DISPLAY_CLEAR);
|
|
|
|
chThdSleepMilliseconds(2);
|
|
|
|
|
|
|
|
lcd_HD44780_write_command(LCD_HD44780_SHIFT_CURSOR_RIGHT);
|
|
|
|
chThdSleepMilliseconds(2);
|
|
|
|
|
|
|
|
lcd_HD44780_write_command(LCD_HD44780_DISPLAY_ON);
|
|
|
|
|
|
|
|
lcd_HD44780_set_position(0, 0);
|
2021-04-21 09:53:13 -07:00
|
|
|
efiPrintf("lcd_HD44780_init() done");
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2017-04-21 19:47:50 -07:00
|
|
|
void lcdShowPanicMessage(char *message) {
|
2021-01-09 14:16:10 -08:00
|
|
|
/* this is not a good idea to access config data
|
|
|
|
* when everything goes wrong... */
|
|
|
|
if (!lcd_HD44780_is_enabled())
|
|
|
|
return;
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
BUSY_WAIT_DELAY = TRUE;
|
|
|
|
lcd_HD44780_set_position(0, 0);
|
2017-04-21 19:47:50 -07:00
|
|
|
lcd_HD44780_print_string("PANIC\n");
|
2015-07-10 06:01:56 -07:00
|
|
|
lcd_HD44780_print_string(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* EFI_HD44780_LCD */
|