This is an automated email from the ASF dual-hosted git repository. jerzy pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit ea8db0f5bd11a6409afe970b22b4ff1eef5f5f66 Author: Jerzy Kasenberg <[email protected]> AuthorDate: Mon May 19 12:00:07 2025 +0200 lvgl/st7796s: Add initial support for ST7796S TFT Initial support for ST7798S displays with 320x480 resolution. Signed-off-by: Jerzy Kasenberg <[email protected]> --- hw/drivers/display/lvgl/pkg.yml | 2 + hw/drivers/display/lvgl/syscfg.yml | 3 + hw/drivers/display/lvgl/tft/st7796S/pkg.yml | 23 ++ hw/drivers/display/lvgl/tft/st7796S/src/st7796s.c | 275 ++++++++++++++++++++++ hw/drivers/display/lvgl/tft/st7796S/syscfg.yml | 26 ++ 5 files changed, 329 insertions(+) diff --git a/hw/drivers/display/lvgl/pkg.yml b/hw/drivers/display/lvgl/pkg.yml index 9e37327b2..d1ddf73a4 100644 --- a/hw/drivers/display/lvgl/pkg.yml +++ b/hw/drivers/display/lvgl/pkg.yml @@ -68,6 +68,8 @@ pkg.deps.LVGL_ST7735S: - "@apache-mynewt-core/hw/drivers/display/lvgl/tft/st7735s" pkg.deps.LVGL_ST7789: - "@apache-mynewt-core/hw/drivers/display/lvgl/tft/st7789" +pkg.deps.LVGL_ST7796S: + - "@apache-mynewt-core/hw/drivers/display/lvgl/tft/st7796S" pkg.deps.LVGL_CST816S: - "@apache-mynewt-core/hw/drivers/display/lvgl/indev/cst816s" diff --git a/hw/drivers/display/lvgl/syscfg.yml b/hw/drivers/display/lvgl/syscfg.yml index 7acf04ffd..411dc7b1c 100644 --- a/hw/drivers/display/lvgl/syscfg.yml +++ b/hw/drivers/display/lvgl/syscfg.yml @@ -37,6 +37,9 @@ syscfg.defs: LVGL_ST7789: description: Enable ST7789 display driver. value: + LVGL_ST7796S: + description: Enable ST7796S display driver. + value: LVGL_XPT2046: description: Enable XPT2046 touchscreen driver. value: diff --git a/hw/drivers/display/lvgl/tft/st7796S/pkg.yml b/hw/drivers/display/lvgl/tft/st7796S/pkg.yml new file mode 100644 index 000000000..a288c59b4 --- /dev/null +++ b/hw/drivers/display/lvgl/tft/st7796S/pkg.yml @@ -0,0 +1,23 @@ +# 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/tft/st7796S +pkg.description: LVGL display driver for ST7796S +pkg.author: "Apache Mynewt <[email protected]>" +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: diff --git a/hw/drivers/display/lvgl/tft/st7796S/src/st7796s.c b/hw/drivers/display/lvgl/tft/st7796S/src/st7796s.c new file mode 100644 index 000000000..4a498deeb --- /dev/null +++ b/hw/drivers/display/lvgl/tft/st7796S/src/st7796s.c @@ -0,0 +1,275 @@ +/* + * 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 <bsp/bsp.h> +#include <lv_glue.h> +#include <hal/lv_hal_disp.h> +#include <hal/hal_gpio.h> +#include <lcd_itf.h> + +/* Magic numbers used to lock/unlock command settings */ +#define ST7796S_UNLOCK_1 0xC3 +#define ST7796S_UNLOCK_2 0x96 + +#define ST7796S_LOCK_1 0x3C +#define ST7796S_LOCK_2 0x69 + +#define ST7796S_NOP 0x00 +#define ST7796S_SWRESET 0x01 +#define ST7796S_RDDID 0x04 +#define ST7796S_RDDST 0x09 +#define ST7796S_RDDPM 0x0A +#define ST7796S_RDDDMADCTL 0x0B +#define ST7796S_RDDCOLMOD 0x0C +#define ST7796S_RDDIM 0x0D +#define ST7796S_RDDSM 0x0E +#define ST7796S_RDDSDR 0x0F + +#define ST7796S_SLPIN 0x10 +#define ST7796S_SLPOUT 0x11 +#define ST7796S_PTLON 0x12 +#define ST7796S_NORON 0x13 + +#define ST7796S_INVOFF 0x20 +#define ST7796S_INVON 0x21 +#define ST7796S_DISPOFF 0x28 +#define ST7796S_DISPON 0x29 +#define ST7796S_CASET 0x2A +#define ST7796S_RASET 0x2B +#define ST7796S_RAMWR 0x2C +#define ST7796S_RAMRD 0x2E + +#define ST7796S_PTLAR 0x30 +#define ST7796S_VSCRDEF 0x33 +#define ST7796S_TEOFF 0x34 +#define ST7796S_TEON 0x35 +#define ST7796S_MADCTL 0x36 +#define ST7796S_VSCRSADD 0x37 +#define ST7796S_IDMOFF 0x38 +#define ST7796S_IDMON 0x39 +#define ST7796S_COLMOD 0x3A +#define ST7796S_WRMEMC 0x3C +#define ST7796S_RDMEMC 0x3E +#define ST7796S_STE 0x44 +#define ST7796S_GSCAN 0x45 +#define ST7796S_WRDISBV 0x51 +#define ST7796S_RDDISBV 0x52 +#define ST7796S_WRCTRLD 0x53 +#define ST7796S_RDCTRLD 0x54 +#define ST7796S_WRCACE 0x55 +#define ST7796S_RDCABC 0x56 +#define ST7796S_WRCABCMB 0x5E +#define ST7796S_RDCABCMB 0x5F +#define ST7796S_RDABCSDR 0x68 + +#define ST7796S_IFMODE 0xB0 +#define ST7796S_FRMCTR1 0xB1 +#define ST7796S_FRMCTR2 0xB2 +#define ST7796S_FRMCTR3 0xB3 +#define ST7796S_DIC 0xB4 +#define ST7796S_BPC 0xB5 +#define ST7796S_DFC 0xB6 +#define ST7796S_EM 0xB7 + +#define ST7796S_DGMEN 0xBA +#define ST7796S_VCOMS 0xBB +#define ST7796S_POWSAVE 0xBC +#define ST7796S_DLPOFFSAVE 0xBD + +#define ST7796S_PWR1 0xC0 +#define ST7796S_PWR2 0xC1 +#define ST7796S_PWR3 0xC2 + +#define ST7796S_VCMPCTL 0xC5 + +#define ST7796S_NVMADW 0xD0 +#define ST7796S_NVMBPROG 0xD1 +#define ST7796S_NVM 0xD2 +#define ST7796S_RDID4 0xD3 + +#define ST7796S_PGC 0xE0 +#define ST7796S_NGC 0xE1 +#define ST7796S_DGC1 0xE2 +#define ST7796S_DGC2 0xE3 + +#define ST7796S_DOCA 0xE8 + +#define ST7796S_PROMCTRL 0xEC + +#define ST7796S_CSCON 0xF0 +#define ST7796S_PROMEN 0xFA + +#define ST7796S_NVMSET 0xFC + +#define ST7796S_PROMCAT 0xFE + +#define ST7796S_MADCTL_MY 0x80 +#define ST7796S_MADCTL_MX 0x40 +#define ST7796S_MADCTL_MV 0x20 +#define ST7796S_MADCTL_ML 0x10 +#define ST7796S_MADCTL_RGB 0x00 +#define ST7796S_MADCTL_BGR 0x08 +#define ST7796S_MADCTL_0 ST7796S_MADCTL_MX +#define ST7796S_MADCTL_90 (ST7796S_MADCTL_MV) +#define ST7796S_MADCTL_180 (ST7796S_MADCTL_MY | ST7796S_MADCTL_ML) +#define ST7796S_MADCTL_270 (ST7796S_MADCTL_MY | ST7796S_MADCTL_ML | ST7796S_MADCTL_MV | ST7796S_MADCTL_MX) + +#define ST7796S_HOR_RES MYNEWT_VAL(LVGL_DISPLAY_HORIZONTAL_RESOLUTION) +#define ST7796S_VER_RES MYNEWT_VAL(LVGL_DISPLAY_VERTICAL_RESOLUTION) + +void +st7789_rotate(lv_disp_rot_t rotation) +{ + uint8_t madcmd[2] = { ST7796S_MADCTL, ST7796S_MADCTL_BGR }; + + switch (rotation) { + case LV_DISP_ROT_270: + madcmd[1] |= ST7796S_MADCTL_270; + break; + case LV_DISP_ROT_180: + madcmd[1] |= ST7796S_MADCTL_180; + break; + case LV_DISP_ROT_90: + madcmd[1] |= ST7796S_MADCTL_90; + break; + case LV_DISP_ROT_NONE: + madcmd[1] |= ST7796S_MADCTL_0; + break; + } + lcd_ift_write_cmd(madcmd, 2); +} + +LCD_SEQUENCE(init_cmds) + LCD_SEQUENCE_LCD_CS_INACTIVATE(), + LCD_SEQUENCE_LCD_DC_DATA(), + 1, ST7796S_NOP, +#if MYNEWT_VAL(LCD_RESET_PIN) < 0 + 1, ST7796S_SWRESET, + LCD_SEQUENCE_DELAY(5), +#else + LCD_SEQUENCE_LCD_RESET_ACTIVATE(), + LCD_SEQUENCE_DELAY_US(100), + LCD_SEQUENCE_LCD_RESET_INACTIVATE(), + LCD_SEQUENCE_DELAY(5), +#endif + 2, ST7796S_CSCON, ST7796S_UNLOCK_1, + 2, ST7796S_CSCON, ST7796S_UNLOCK_2, + 2, ST7796S_MADCTL, ST7796S_MADCTL_0 | ST7796S_MADCTL_BGR, + 2, ST7796S_COLMOD, 0x55, + 4, ST7796S_DFC, 0x8A, 0x07, 0x3B, + 5, ST7796S_BPC, 2, 3, 0, 4, + 3, ST7796S_FRMCTR1, 0x80, 0x10, + 2, ST7796S_DIC, 0, + 2, ST7796S_EM, 0xc6, + 2, ST7796S_VCMPCTL, 0x24, + 9, ST7796S_DOCA, 0x40, 0x8A, 0x00, 0x00, 0x29, 0x19, 0xA5, 0x33, + 2, ST7796S_PWR3, 0xA7, + 15, ST7796S_PGC, 0xF0, 0x09, 0x13, 0x12, 0x12, 0x2B, 0x3C, 0x44, 0x4B, 0x1B, 0x18, 0x17, 0x1D, 0x21, + 15, ST7796S_NGC, 0xF0, 0x09, 0x13, 0x0C, 0x0D, 0x27, 0x3B, 0x44, 0x4D, 0x0B, 0x17, 0x17, 0x1D, 0x21, + 2, ST7796S_CSCON, ST7796S_LOCK_1, + 2, ST7796S_CSCON, ST7796S_LOCK_2, + 1, ST7796S_NORON, +#if MYNEWT_VAL(ST7796S_INVERSION_ON) + 1, ST7796S_INVON, +#else + 1, ST7796S_INVOFF, +#endif + 1, ST7796S_SLPOUT, + LCD_SEQUENCE_DELAY(15), + 1, ST7796S_DISPON, +LCD_SEQUENCE_END + +/** + * + * Initialize the ST7789 display controller + */ +void +st7789_init(lv_disp_drv_t *driver) +{ + (void)driver; + + lcd_command_sequence(init_cmds); +} + +static void +st7789_drv_update(struct _lv_disp_drv_t *drv) +{ + st7789_rotate(drv->rotated); +} + +void +st7789_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p) +{ + uint8_t cmd[5]; + lv_disp_t *disp = lv_disp_get_default(); + lv_coord_t hor_res = lv_disp_get_hor_res(disp); + lv_coord_t ver_res = lv_disp_get_ver_res(disp); + + if (area->x2 < 0 || area->y2 < 0 || area->x1 >= hor_res || area->y1 >= ver_res) { + lv_disp_flush_ready(drv); + return; + } + + /* Truncate the area to the screen */ + int32_t act_x1 = area->x1 < 0 ? 0 : area->x1; + int32_t act_y1 = area->y1 < 0 ? 0 : area->y1; + int32_t act_x2 = area->x2 >= hor_res ? hor_res - 1 : area->x2; + int32_t act_y2 = area->y2 >= ver_res ? ver_res - 1 : area->y2; + + /* Column addresses */ + cmd[0] = ST7796S_CASET; + cmd[1] = (uint8_t)(act_x1 >> 8); + cmd[2] = (uint8_t)act_x1; + cmd[3] = (uint8_t)(act_x2 >> 8); + cmd[4] = (uint8_t)act_x2; + lcd_ift_write_cmd(cmd, 5); + + /* Page address */ + cmd[0] = ST7796S_RASET; + cmd[1] = (uint8_t)(act_y1 >> 8); + cmd[2] = (uint8_t)act_y1; + cmd[3] = (uint8_t)(act_y2 >> 8); + cmd[4] = (uint8_t)act_y2; + lcd_ift_write_cmd(cmd, 5); + + cmd[0] = ST7796S_RAMWR; + lcd_ift_write_cmd(cmd, 1); + + lcd_itf_write_color_data(act_x1, act_x2, act_y1, act_y2, color_p); + + lv_disp_flush_ready(drv); +} + +void +mynewt_lv_drv_init(lv_disp_drv_t *driver) +{ + if (MYNEWT_VAL(LCD_BL_PIN) >= 0) { + hal_gpio_init_out(MYNEWT_VAL(LCD_BL_PIN), MYNEWT_VAL(LCD_BL_PIN_ACTIVE_LEVEL)); + } + if (MYNEWT_VAL(LCD_RESET_PIN) >= 0) { + hal_gpio_init_out(MYNEWT_VAL(LCD_RESET_PIN), 1); + } + lcd_itf_init(); + driver->flush_cb = st7789_flush; + driver->drv_update_cb = st7789_drv_update; + driver->hor_res = ST7796S_HOR_RES; + driver->ver_res = ST7796S_VER_RES; + + st7789_init(driver); +} diff --git a/hw/drivers/display/lvgl/tft/st7796S/syscfg.yml b/hw/drivers/display/lvgl/tft/st7796S/syscfg.yml new file mode 100644 index 000000000..69d93d64e --- /dev/null +++ b/hw/drivers/display/lvgl/tft/st7796S/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: + ST7796S_INVERSION_ON: + description: ST7796S enable display inversion. + value: 0 + +syscfg.vals: + LVGL_DISPLAY_HORIZONTAL_RESOLUTION: 320 + LVGL_DISPLAY_VERTICAL_RESOLUTION: 480
