summaryrefslogtreecommitdiff
path: root/board/fusb307bgevb/lcd.c
diff options
context:
space:
mode:
authorYun-chieh, Lee <lyunjie@google.com>2020-09-10 21:57:00 +0800
committerCommit Bot <commit-bot@chromium.org>2020-09-21 17:34:15 +0000
commitdb78abe0160364bf075e1595850407dfdd182297 (patch)
tree4a6a28dfbc18485285b90eca5a2be49e7a5b47b0 /board/fusb307bgevb/lcd.c
parentb7dc125ebb97fcc87ff606696f4fb5315b767c45 (diff)
downloadchrome-ec-db78abe0160364bf075e1595850407dfdd182297.tar.gz
ucsa: add lcd driver
LCD 2004A driver, show "USB-C Sink Advertiser" on screen. BUG=none TEST=make buildall BRANCH=master Signed-off-by: Yun-Chieh Lee <lyunjie@google.com> Change-Id: I4dc3932fba0077bc215f2e6c7855ba26995370ac Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2402852 Reviewed-by: Ting Shen <phoenixshen@chromium.org>
Diffstat (limited to 'board/fusb307bgevb/lcd.c')
-rw-r--r--board/fusb307bgevb/lcd.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/board/fusb307bgevb/lcd.c b/board/fusb307bgevb/lcd.c
new file mode 100644
index 0000000000..892888329e
--- /dev/null
+++ b/board/fusb307bgevb/lcd.c
@@ -0,0 +1,166 @@
+/* Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * LCD driver for I2C LCD 2004.
+ */
+
+#include "i2c.h"
+#include "lcd.h"
+#include "timer.h"
+
+struct lcd_state_info {
+ uint8_t addr;
+ uint8_t displayfunction;
+ uint8_t displaycontrol;
+ uint8_t backlightval;
+};
+
+static struct lcd_state_info state = {
+ .addr = LCD_SLAVE_ADDR,
+ .backlightval = LCD_BACKLIGHT,
+ .displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5X8DOTS,
+};
+
+/************ low level data pushing commands **********/
+/* write either command or data */
+static void expander_write(uint8_t data)
+{
+ i2c_write8(I2C_PORT_TCPC, LCD_SLAVE_ADDR, 0x00, data |
+ state.backlightval);
+}
+
+static void pulse_enable(uint8_t data)
+{
+ expander_write(data | LCD_EN);/* En high */
+ usleep(1); /* enable pulse must be >450ns */
+
+ expander_write(data & ~LCD_EN);/* En low */
+ usleep(50); /* commands need > 37us to settle */
+}
+
+static void write_4bits(uint8_t value)
+{
+ expander_write(value);
+ pulse_enable(value);
+}
+
+static void send(uint8_t value, uint8_t mode)
+{
+ uint8_t highnib = value & 0xf0;
+ uint8_t lownib = (value << 4) & 0xf0;
+
+ write_4bits(highnib | mode);
+ write_4bits(lownib | mode);
+}
+
+/*********** mid level commands, for sending data/cmds */
+static void command(uint8_t value)
+{
+ send(value, 0);
+}
+
+/********** high level commands, for the user! */
+void lcd_clear(void)
+{
+ command(LCD_CLEAR_DISPLAY);/* clear display, set cursor to zero */
+ usleep(2000); /* this command takes a long time! */
+}
+
+void lcd_set_cursor(uint8_t col, uint8_t row)
+{
+ int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
+
+ command(LCD_SET_DDRAMADDR | (col + row_offsets[row]));
+}
+
+void lcd_print_char(char data)
+{
+ send(data, LCD_RS);
+}
+
+void lcd_print_string(const char *str)
+{
+ while (*str)
+ lcd_print_char(*str++);
+}
+
+/* Turn the display on/off (quickly) */
+void lcd_disable_display(void)
+{
+ state.displaycontrol &= ~LCD_DISPLAY_ON;
+ command(LCD_DISPLAY_CONTROL | state.displaycontrol);
+}
+void lcd_enable_display(void)
+{
+ state.displaycontrol |= LCD_DISPLAY_ON;
+ command(LCD_DISPLAY_CONTROL | state.displaycontrol);
+}
+
+/* Turn the (optional) backlight off/on */
+void lcd_disable_backlight(void)
+{
+ state.backlightval = LCD_NO_BACKLIGHT;
+ expander_write(0);
+}
+
+void lcd_enable_backlight(void)
+{
+ state.backlightval = LCD_BACKLIGHT;
+ expander_write(0);
+}
+
+void lcd_init(uint8_t cols, uint8_t rows, uint8_t dotsize)
+{
+ if (rows > 1)
+ state.displayfunction |= LCD_2LINE;
+
+ /* for some 1 line displays you can select a 10 pixel high font */
+ if ((dotsize != 0) && (rows == 1))
+ state.displayfunction |= LCD_5X10DOTS;
+
+ /* SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
+ * according to datasheet, we need at least 40ms after power rises
+ * above 2.7V before sending commands. Arduino can turn on way
+ * before 4.5V so we'll wait 50
+ */
+ usleep(50);
+
+ /* Now we pull both RS and R/W low to begin commands */
+ /* reset expanderand turn backlight off (Bit 8 =1) */
+ expander_write(state.backlightval);
+ usleep(1000);
+
+ /* put the LCD into 4 bit mode
+ * this is according to the hitachi HD44780 datasheet
+ * figure 24, pg 46
+ * we start in 8bit mode, try to set 4 bit mode
+ */
+ write_4bits(0x03 << 4);
+ usleep(4500); /* wait min 4.1ms */
+ /*second try */
+ write_4bits(0x03 << 4);
+ usleep(4500); /* wait min 4.1ms */
+ /* third go! */
+ write_4bits(0x03 << 4);
+ usleep(150);
+ /* finally, set to 4-bit interface */
+ write_4bits(0x02 << 4);
+
+ /* set # lines, font size, etc. */
+ command(LCD_FUNCTION_SET | state.displayfunction);
+
+ /* turn the display on with no cursor or blinking default */
+ state.displaycontrol = LCD_DISPLAY_ON | LCD_CURSOR_OFF | LCD_BLINK_OFF;
+ lcd_enable_display();
+
+ /* clear it off */
+ lcd_clear();
+
+ /* Initialize to default text direction (for roman languages)
+ * and set the entry mode
+ */
+ command(LCD_ENTRYMODE_SET | LCD_ENTRY_LEFT | LCD_ENTRY_SHIFT_DECREMENT);
+
+ lcd_set_cursor(0, 0);
+}