From 2f2f4b033b701026bc1e6743e5795b60f768b793 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 29 Sep 2023 14:48:11 +0200 Subject: [PATCH 1/3] lvgl: Add i2c interface driver Driver for display that have I2C interface (SDD1306) Signed-off-by: Jerzy Kasenberg --- hw/drivers/display/lcd_itf/itf_i2c/pkg.yml | 29 ++++++ .../display/lcd_itf/itf_i2c/src/itf_i2c.c | 96 +++++++++++++++++++ hw/drivers/display/lcd_itf/itf_i2c/syscfg.yml | 34 +++++++ hw/drivers/display/lcd_itf/pkg.yml | 2 + hw/drivers/display/lcd_itf/syscfg.yml | 1 + 5 files changed, 162 insertions(+) create mode 100644 hw/drivers/display/lcd_itf/itf_i2c/pkg.yml create mode 100644 hw/drivers/display/lcd_itf/itf_i2c/src/itf_i2c.c create mode 100644 hw/drivers/display/lcd_itf/itf_i2c/syscfg.yml diff --git a/hw/drivers/display/lcd_itf/itf_i2c/pkg.yml b/hw/drivers/display/lcd_itf/itf_i2c/pkg.yml new file mode 100644 index 0000000000..e3e20384cd --- /dev/null +++ b/hw/drivers/display/lcd_itf/itf_i2c/pkg.yml @@ -0,0 +1,29 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: hw/drivers/display/lcd_itf/itf_i2c +pkg.description: LCD Standard I2C interface +pkg.keywords: + - display + +pkg.apis: + - lcd_interface + +pkg.deps: +# - "@apache-mynewt-core/hw/bus/drivers/i2c_common" diff --git a/hw/drivers/display/lcd_itf/itf_i2c/src/itf_i2c.c b/hw/drivers/display/lcd_itf/itf_i2c/src/itf_i2c.c new file mode 100644 index 0000000000..b98457b844 --- /dev/null +++ b/hw/drivers/display/lcd_itf/itf_i2c/src/itf_i2c.c @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#if MYNEWT_PKG_apache_mynewt_core__hw_bus_drivers_i2c_common +#include +#else +#include +#endif + +#include +#include + +#if MYNEWT_PKG_apache_mynewt_core__hw_bus_drivers_i2c_common +static struct bus_i2c_node lcd; +static struct bus_i2c_node_cfg lcd_i2c_cfg = { + .node_cfg.bus_name = MYNEWT_VAL(LCD_I2C_DEV_NAME), + .addr = MYNEWT_VAL(LCD_I2C_ADDR), + .freq = MYNEWT_VAL(LCD_I2C_FREQ), +}; +static struct os_dev *lcd_dev; +#else +#endif + +void +lcd_itf_write_color_data(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void *pixels) +{ + uint8_t *color_data = pixels; + size_t size = ((x2 - x1 + 1) * (y2 - y1 + 1)) >> 3; + +#if MYNEWT_PKG_apache_mynewt_core__hw_bus_drivers_i2c_common + color_data[-1] = 0x40; + bus_node_write(lcd_dev, color_data - 1, size + 1, 1000, 0); +#else + color_data[-1] = 0x40; + struct hal_i2c_master_data data = { + .address = MYNEWT_VAL(LCD_I2C_ADDR), + .buffer = color_data - 1, + .len = size + 1, + }; + hal_i2c_master_write(0, &data, 1000, 1); +#endif +} + +void +lcd_ift_write_cmd(const uint8_t *cmd, int cmd_length) +{ + uint8_t buf[cmd_length + 1]; + + buf[0] = 0; + for (int i = 0; i < cmd_length; ++i) { + buf[i + 1] = cmd[i]; + } +#if MYNEWT_PKG_apache_mynewt_core__hw_bus_drivers_i2c_common + bus_node_write(lcd_dev, buf, cmd_length + 1, 1000, 0); +#else + struct hal_i2c_master_data data = { + .address = MYNEWT_VAL(LCD_I2C_ADDR), + .buffer = buf, + .len = cmd_length + 1, + }; + hal_i2c_master_write(0, &data, 1000, 1); +#endif +} + + +void +lcd_itf_init(void) +{ +#if MYNEWT_PKG_apache_mynewt_core__hw_bus_drivers_i2c_common + int rc; + struct bus_node_callbacks cbs = {}; + + bus_node_set_callbacks((struct os_dev *)&lcd, &cbs); + + rc = bus_i2c_node_create("display", &lcd, &lcd_i2c_cfg, NULL); + assert(rc == 0); + lcd_dev = os_dev_open("display", 0, NULL); +#endif +} diff --git a/hw/drivers/display/lcd_itf/itf_i2c/syscfg.yml b/hw/drivers/display/lcd_itf/itf_i2c/syscfg.yml new file mode 100644 index 0000000000..68baf072b9 --- /dev/null +++ b/hw/drivers/display/lcd_itf/itf_i2c/syscfg.yml @@ -0,0 +1,34 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + LCD_I2C_DEV_NAME: + description: I2C device name that LCD is connected to. + value: '"i2c0"' + LCD_I2C_ADDR: + description: LCD I2C address. + value: + restriction: $notnull + LCD_I2C_FREQ: + description: I2C device frequency for LCD (typical 100/400 kHz) + value: 100 + LCD_I2C_MAX_TRANSFER: + description: Maximum nuber of bytes that I2C interface supports + value: + +syscfg.restrictions: diff --git a/hw/drivers/display/lcd_itf/pkg.yml b/hw/drivers/display/lcd_itf/pkg.yml index 006dd9b2b8..809d26927e 100644 --- a/hw/drivers/display/lcd_itf/pkg.yml +++ b/hw/drivers/display/lcd_itf/pkg.yml @@ -28,6 +28,8 @@ pkg.req_apis: pkg.deps.'LCD_ITF == "spi"': - "@apache-mynewt-core/hw/drivers/display/lcd_itf/itf_spi" +pkg.deps.'LCD_ITF == "i2c"': + - "@apache-mynewt-core/hw/drivers/display/lcd_itf/itf_i2c" pkg.deps.'LCD_ITF == "8080_II_8_bit"': - "@apache-mynewt-core/hw/drivers/display/lcd_itf/itf_8080" pkg.deps.'LCD_ITF == "8080_II_16_bit"': diff --git a/hw/drivers/display/lcd_itf/syscfg.yml b/hw/drivers/display/lcd_itf/syscfg.yml index 4fed89ea4f..973a09232d 100644 --- a/hw/drivers/display/lcd_itf/syscfg.yml +++ b/hw/drivers/display/lcd_itf/syscfg.yml @@ -23,6 +23,7 @@ syscfg.defs: choices: - custom - spi + - i2c - 8080_II_8_bit - 8080_II_16_bit value: spi From 348d9a1ea743f76d6626e81d9170727581cea432 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 29 Sep 2023 14:50:06 +0200 Subject: [PATCH 2/3] lvgl: Add driver for SSD1306 This adds driver for SSD1306 display controller. Signed-off-by: Jerzy Kasenberg --- hw/drivers/display/lvgl/oled/ssd1306/pkg.yml | 28 +++ .../display/lvgl/oled/ssd1306/src/ssd1306.c | 206 ++++++++++++++++++ .../display/lvgl/oled/ssd1306/syscfg.yml | 26 +++ hw/drivers/display/lvgl/pkg.yml | 2 + hw/drivers/display/lvgl/syscfg.yml | 3 + 5 files changed, 265 insertions(+) create mode 100644 hw/drivers/display/lvgl/oled/ssd1306/pkg.yml create mode 100644 hw/drivers/display/lvgl/oled/ssd1306/src/ssd1306.c create mode 100644 hw/drivers/display/lvgl/oled/ssd1306/syscfg.yml diff --git a/hw/drivers/display/lvgl/oled/ssd1306/pkg.yml b/hw/drivers/display/lvgl/oled/ssd1306/pkg.yml new file mode 100644 index 0000000000..33f7aa2770 --- /dev/null +++ b/hw/drivers/display/lvgl/oled/ssd1306/pkg.yml @@ -0,0 +1,28 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: hw/drivers/display/lvgl/oled/ssd1306 +pkg.description: LVGL display driver for SSD1306 +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + +pkg.cflags: + +pkg.deps: + - "@apache-mynewt-core/hw/drivers/display/lcd_itf" diff --git a/hw/drivers/display/lvgl/oled/ssd1306/src/ssd1306.c b/hw/drivers/display/lvgl/oled/ssd1306/src/ssd1306.c new file mode 100644 index 0000000000..c8c737ca66 --- /dev/null +++ b/hw/drivers/display/lvgl/oled/ssd1306/src/ssd1306.c @@ -0,0 +1,206 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include + +/* + * Fundamental Command Table + */ +#define SSD1306_SET_LOWER_COL_ADDRESS 0x00 +#define SSD1306_SET_LOWER_COL_ADDRESS_MASK 0x0f + +#define SSD1306_SET_HIGHER_COL_ADDRESS 0x10 +#define SSD1306_SET_HIGHER_COL_ADDRESS_MASK 0x0f + +#define SSD1306_SET_MEM_ADDRESSING_MODE 0x20 +#define SSD1306_SET_MEM_ADDRESSING_HORIZONTAL 0x00 +#define SSD1306_SET_MEM_ADDRESSING_VERTICAL 0x01 +#define SSD1306_SET_MEM_ADDRESSING_PAGE 0x02 + +#define SSD1306_SET_COLUMN_ADDRESS 0x21 + +#define SSD1306_SET_PAGE_ADDRESS 0x22 + +#define SSD1306_HORIZONTAL_SCROLL_SETUP 0x26 + +#define SSD1306_CONTINUOUS_VERTICAL_AND_HORIZONTAL_SCROLL_SETUP 0x29 + +#define SSD1306_DEACTIVATE_SCROLL 0x2e + +#define SSD1306_ACTIVATE_SCROLL 0x2f + +#define SSD1306_SET_START_LINE 0x40 +#define SSD1306_SET_START_LINE_MASK 0x3f + +#define SSD1306_SET_CONTRAST_CTRL 0x81 + +#define SDD1406_CHARGE_PUMP_SETTING 0x8d +#define SDD1406_CHARGE_PUMP_SETTING_DISABLE 0x10 +#define SDD1406_CHARGE_PUMP_SETTING_ENABLE 0x14 + +#define SSD1306_SET_SEGMENT_MAP_NORMAL 0xa0 +#define SSD1306_SET_SEGMENT_MAP_REMAPED 0xa1 + +#define SSD1306_SET_VERTICAL_SCROLL_AREA 0xa3 + +#define SSD1306_SET_ENTIRE_DISPLAY_OFF 0xa4 +#define SSD1306_SET_ENTIRE_DISPLAY_ON 0xa5 + +#define SSD1306_SET_NORMAL_DISPLAY 0xa6 +#define SSD1306_SET_REVERSE_DISPLAY 0xa7 + +#define SSD1306_SET_MULTIPLEX_RATIO 0xa8 + +#define SSD1306_DISPLAY_OFF 0xae +#define SSD1306_DISPLAY_ON 0xaf + +#define SSD1306_SET_PAGE_START_ADDRESS 0xb0 +#define SSD1306_SET_PAGE_START_ADDRESS_MASK 0x07 + +#define SSD1306_SET_COM_OUTPUT_SCAN_NORMAL 0xc0 +#define SSD1306_SET_COM_OUTPUT_SCAN_FLIPPED 0xc8 + +#define SSD1306_SET_DISPLAY_OFFSET 0xd3 + +#define SSD1306_SET_CLOCK_DIV_RATIO 0xd5 + +#define SSD1306_SET_CHARGE_PERIOD 0xd9 + +#define SSD1306_SET_PADS_HW_CONFIG 0xda + +#define SSD1306_SET_VCOM_DESELECT_LEVEL 0xdb + +#define SSD1306_NOP 0xe3 + +#define SSD1306_SET_PADS_HW_SEQUENTIAL 0x02 +#define SSD1306_SET_PADS_HW_ALTERNATIVE 0x12 + +#define SSD1306_SET_CHARGE_PUMP_ON 0x8d +#define SSD1306_SET_CHARGE_PUMP_ON_DISABLED 0x10 +#define SSD1306_SET_CHARGE_PUMP_ON_ENABLED 0x14 + +#define SH1106_SET_DCDC_MODE 0xad +#define SH1106_SET_DCDC_DISABLED 0x8a +#define SH1106_SET_DCDC_ENABLED 0x8b + +#define SSD1306_SET_PUMP_VOLTAGE_64 0x30 +#define SSD1306_SET_PUMP_VOLTAGE_74 0x31 +#define SSD1306_SET_PUMP_VOLTAGE_80 0x32 +#define SSD1306_SET_PUMP_VOLTAGE_90 0x33 + +#define SSD1306_READ_MODIFY_WRITE_START 0xe0 +#define SSD1306_READ_MODIFY_WRITE_END 0xee + +#define SSD1306_CLOCK_DIV_RATIO 0x0 +#define SSD1306_CLOCK_FREQUENCY 0x8 +#define SSD1306_PANEL_VCOM_DESEL_LEVEL 0x20 +#define SSD1306_PANEL_PUMP_VOLTAGE SSD1306_SET_PUMP_VOLTAGE_90 + +LCD_SEQUENCE(init_cmds) + LCD_SEQUENCE_LCD_CS_INACTIVATE(), + LCD_SEQUENCE_LCD_DC_DATA(), + /* command length, command, args */ + 1, SSD1306_DISPLAY_OFF, + 2, SSD1306_SET_CLOCK_DIV_RATIO, (SSD1306_CLOCK_FREQUENCY << 4) | SSD1306_CLOCK_DIV_RATIO, + 2, SSD1306_SET_MULTIPLEX_RATIO, 0x3f, + 2, SSD1306_SET_DISPLAY_OFFSET, 0, + 1, SSD1306_SET_START_LINE + 0, + 2, SDD1406_CHARGE_PUMP_SETTING, SDD1406_CHARGE_PUMP_SETTING_ENABLE, + 2, SSD1306_SET_MEM_ADDRESSING_MODE, SSD1306_SET_MEM_ADDRESSING_HORIZONTAL, + 1, SSD1306_SET_SEGMENT_MAP_REMAPED, + 1, SSD1306_SET_COM_OUTPUT_SCAN_FLIPPED, + + 2, SSD1306_SET_PADS_HW_CONFIG, 0x12, + 2, SSD1306_SET_CONTRAST_CTRL, 0xcf, + + 2, SSD1306_SET_CHARGE_PERIOD, 0xF1, + + 2, SSD1306_SET_VCOM_DESELECT_LEVEL, 0x40, + + 1, SSD1306_DEACTIVATE_SCROLL, + + 1, SSD1306_SET_ENTIRE_DISPLAY_OFF, + 1, SSD1306_SET_NORMAL_DISPLAY, + 1, SSD1306_SET_START_LINE + 0, + + 3, SSD1306_SET_HIGHER_COL_ADDRESS, 0, 0xb0, + + 1, SSD1306_DISPLAY_ON, +LCD_SEQUENCE_END + +/** + * Initialize the SSD1306 display controller + */ +void +ssd1306_init(lv_disp_drv_t *driver) +{ + lcd_command_sequence(init_cmds); +} + +void +ssd1306_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p) +{ + uint8_t page1 = area->y1 >> 3; + uint8_t page2 = area->y2 >> 3; + uint8_t *buf = (uint8_t *)color_p; + uint8_t b[3]; + + b[0] = SSD1306_SET_COLUMN_ADDRESS; + b[1] = (uint8_t)area->x1; + b[2] = (uint8_t)area->x2; + lcd_ift_write_cmd(b, 3); + + b[0] = SSD1306_SET_PAGE_ADDRESS; + b[1] = page1; + b[2] = page2; + lcd_ift_write_cmd(b, 3); + + lcd_itf_write_color_data(area->x1, area->y1, area->x2, area->y2, buf); + + lv_disp_flush_ready(drv); +} + +void +ssd1306_set_px_cb(struct _lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t color, lv_opa_t opa) +{ + uint16_t byte_index = x + ((y >> 3) * buf_w); + uint8_t bit_index = y & 0x7; + + if (color.full == 0) { + buf[byte_index] |= 1 << bit_index; + } else { + buf[byte_index] &= ~(1 << bit_index); + } +} + +void +mynewt_lv_drv_init(lv_disp_drv_t *driver) +{ + lcd_itf_init(); + driver->flush_cb = ssd1306_flush; + driver->set_px_cb = ssd1306_set_px_cb; + driver->hor_res = MYNEWT_VAL(LVGL_DISPLAY_HORIZONTAL_RESOLUTION); + driver->ver_res = MYNEWT_VAL(LVGL_DISPLAY_VERTICAL_RESOLUTION); + + ssd1306_init(driver); +} diff --git a/hw/drivers/display/lvgl/oled/ssd1306/syscfg.yml b/hw/drivers/display/lvgl/oled/ssd1306/syscfg.yml new file mode 100644 index 0000000000..31244235ea --- /dev/null +++ b/hw/drivers/display/lvgl/oled/ssd1306/syscfg.yml @@ -0,0 +1,26 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + +syscfg.vals: + LVGL_DISPLAY_HORIZONTAL_RESOLUTION: 128 + LVGL_DISPLAY_VERTICAL_RESOLUTION: 64 + +syscfg.restrictions: + - LV_DISP_Y_ALIGN == 3 diff --git a/hw/drivers/display/lvgl/pkg.yml b/hw/drivers/display/lvgl/pkg.yml index 10bc372b86..846b23da14 100644 --- a/hw/drivers/display/lvgl/pkg.yml +++ b/hw/drivers/display/lvgl/pkg.yml @@ -58,6 +58,8 @@ pkg.deps: - "@apache-mynewt-core/hw/hal" - "@apache-mynewt-core/hw/drivers/display/lcd_itf" +pkg.deps.LVGL_SSD1306: + - "@apache-mynewt-core/hw/drivers/display/lvgl/oled/ssd1306" pkg.deps.LVGL_GC9A01: - "@apache-mynewt-core/hw/drivers/display/lvgl/tft/gc9a01" pkg.deps.LVGL_ILI9341: diff --git a/hw/drivers/display/lvgl/syscfg.yml b/hw/drivers/display/lvgl/syscfg.yml index 61ecf72cf9..3af9a62147 100644 --- a/hw/drivers/display/lvgl/syscfg.yml +++ b/hw/drivers/display/lvgl/syscfg.yml @@ -22,6 +22,9 @@ syscfg.defs: LV_COLOR_16_SWAP changes order of 16 bit RGB value to better match 8 bit SPI protocol. value: 0 + LVGL_SSD1306: + description: Enable SSD1306 display driver. + value: LVGL_GC9A01: description: Enable GC9A01 display driver. value: From 95deb08284af6c2214eb1d0d5753ab2baf2aa42d Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 3 Nov 2023 10:36:53 +0100 Subject: [PATCH 3/3] lvgl/ssd1306: Add support for page addressing Only horizontal addressing mode was supported. There are many variants that only work with page addressing mode. Now addressing mode can be changed to page (which is less efficient from I2C point of view). Signed-off-by: Jerzy Kasenberg --- .../display/lvgl/oled/ssd1306/src/ssd1306.c | 36 ++++++++++++++++++- .../display/lvgl/oled/ssd1306/syscfg.yml | 6 ++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/hw/drivers/display/lvgl/oled/ssd1306/src/ssd1306.c b/hw/drivers/display/lvgl/oled/ssd1306/src/ssd1306.c index c8c737ca66..e6ddaf9236 100644 --- a/hw/drivers/display/lvgl/oled/ssd1306/src/ssd1306.c +++ b/hw/drivers/display/lvgl/oled/ssd1306/src/ssd1306.c @@ -115,6 +115,12 @@ #define SSD1306_PANEL_VCOM_DESEL_LEVEL 0x20 #define SSD1306_PANEL_PUMP_VOLTAGE SSD1306_SET_PUMP_VOLTAGE_90 +#if MYNEWT_VAL_CHOICE(SSD1306_ADDRESSING_MODE, horizontal) +#define ADDRESSING_MODE SSD1306_SET_MEM_ADDRESSING_HORIZONTAL +#else +#define ADDRESSING_MODE SSD1306_SET_MEM_ADDRESSING_PAGE +#endif + LCD_SEQUENCE(init_cmds) LCD_SEQUENCE_LCD_CS_INACTIVATE(), LCD_SEQUENCE_LCD_DC_DATA(), @@ -125,7 +131,7 @@ LCD_SEQUENCE(init_cmds) 2, SSD1306_SET_DISPLAY_OFFSET, 0, 1, SSD1306_SET_START_LINE + 0, 2, SDD1406_CHARGE_PUMP_SETTING, SDD1406_CHARGE_PUMP_SETTING_ENABLE, - 2, SSD1306_SET_MEM_ADDRESSING_MODE, SSD1306_SET_MEM_ADDRESSING_HORIZONTAL, + 2, SSD1306_SET_MEM_ADDRESSING_MODE, ADDRESSING_MODE, 1, SSD1306_SET_SEGMENT_MAP_REMAPED, 1, SSD1306_SET_COM_OUTPUT_SCAN_FLIPPED, @@ -156,6 +162,7 @@ ssd1306_init(lv_disp_drv_t *driver) lcd_command_sequence(init_cmds); } +#if MYNEWT_VAL_CHOICE(SSD1306_ADDRESSING_MODE, horizontal) void ssd1306_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p) { @@ -178,6 +185,30 @@ ssd1306_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p) lv_disp_flush_ready(drv); } +#else +void +ssd1306_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p) +{ + uint8_t page1 = area->y1 >> 3; + uint8_t page2 = area->y2 >> 3; + + uint8_t *buf = (uint8_t *)color_p; + int width = area->x2 - area->x1 + 1; + uint8_t b[3]; + + for (; page1 <= page2; ++page1, buf += width) { + b[0] = SSD1306_SET_PAGE_START_ADDRESS + page1; + lcd_ift_write_cmd(b, 1); + b[0] = SSD1306_SET_LOWER_COL_ADDRESS + (area->x1 & 0xF); + lcd_ift_write_cmd(b, 1); + b[0] = SSD1306_SET_HIGHER_COL_ADDRESS + ((area->x1 >> 4) & 0xF); + lcd_ift_write_cmd(b, 1); + + lcd_itf_write_color_data(area->x1, area->x2, page1 << 3, ((page1 + 1) << 3) - 1, buf); + } + lv_disp_flush_ready(drv); +} +#endif void ssd1306_set_px_cb(struct _lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, @@ -196,6 +227,9 @@ ssd1306_set_px_cb(struct _lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_ void mynewt_lv_drv_init(lv_disp_drv_t *driver) { + if (MYNEWT_VAL(LCD_RESET_PIN) >= 0) { + hal_gpio_init_out(MYNEWT_VAL(LCD_RESET_PIN), 1); + } lcd_itf_init(); driver->flush_cb = ssd1306_flush; driver->set_px_cb = ssd1306_set_px_cb; diff --git a/hw/drivers/display/lvgl/oled/ssd1306/syscfg.yml b/hw/drivers/display/lvgl/oled/ssd1306/syscfg.yml index 31244235ea..b33efc284b 100644 --- a/hw/drivers/display/lvgl/oled/ssd1306/syscfg.yml +++ b/hw/drivers/display/lvgl/oled/ssd1306/syscfg.yml @@ -17,6 +17,12 @@ # syscfg.defs: + SSD1306_ADDRESSING_MODE: + description: Addressing mode. + choices: + - horizontal + - page + value: horizontal syscfg.vals: LVGL_DISPLAY_HORIZONTAL_RESOLUTION: 128