From d097dd835524516df0e9b7cb9c776a815150d2f3 Mon Sep 17 00:00:00 2001 From: suda-morris <362953310@qq.com> Date: Thu, 6 Apr 2023 13:14:51 +0800 Subject: [PATCH] lcd: add st7796 lcd driver --- .github/workflows/upload_component.yml | 2 +- LCD.md | 9 +- components/lcd/esp_lcd_st7796/CMakeLists.txt | 4 + components/lcd/esp_lcd_st7796/README.md | 78 +++++ .../lcd/esp_lcd_st7796/esp_lcd_st7796.c | 304 ++++++++++++++++++ .../lcd/esp_lcd_st7796/idf_component.yml | 5 + .../esp_lcd_st7796/include/esp_lcd_st7796.h | 34 ++ components/lcd/esp_lcd_st7796/license.txt | 202 ++++++++++++ docu/pics/st7796.jpg | Bin 0 -> 47056 bytes 9 files changed, 633 insertions(+), 5 deletions(-) create mode 100644 components/lcd/esp_lcd_st7796/CMakeLists.txt create mode 100644 components/lcd/esp_lcd_st7796/README.md create mode 100644 components/lcd/esp_lcd_st7796/esp_lcd_st7796.c create mode 100644 components/lcd/esp_lcd_st7796/idf_component.yml create mode 100644 components/lcd/esp_lcd_st7796/include/esp_lcd_st7796.h create mode 100644 components/lcd/esp_lcd_st7796/license.txt create mode 100644 docu/pics/st7796.jpg diff --git a/.github/workflows/upload_component.yml b/.github/workflows/upload_component.yml index 5bad6ef3..d1ef43a3 100644 --- a/.github/workflows/upload_component.yml +++ b/.github/workflows/upload_component.yml @@ -18,7 +18,7 @@ jobs: esp32_azure_iot_kit;esp32_s2_kaluga_kit;esp_wrover_kit;esp-box;esp32_s3_usb_otg;esp32_s3_eye;esp32_s3_lcd_ev_board;esp32_s3_korvo_2;esp-box-lite; components/bh1750;components/es8311;components/es7210;components/fbm320;components/hts221;components/mag3110;components/mpu6050;components/ssd1306;components/esp_lvgl_port; components/lcd_touch/esp_lcd_touch;components/lcd_touch/esp_lcd_touch_ft5x06;components/lcd_touch/esp_lcd_touch_gt911;components/lcd_touch/esp_lcd_touch_tt21100;components/lcd_touch/esp_lcd_touch_gt1151;components/lcd_touch/esp_lcd_touch_cst816s; - components/lcd/esp_lcd_gc9a01;components/lcd/esp_lcd_ili9341;components/lcd/esp_lcd_ra8875;components/lcd_touch/esp_lcd_touch_stmpe610;components/lcd/esp_lcd_sh1107; + components/lcd/esp_lcd_gc9a01;components/lcd/esp_lcd_ili9341;components/lcd/esp_lcd_ra8875;components/lcd_touch/esp_lcd_touch_stmpe610;components/lcd/esp_lcd_sh1107;components/lcd/esp_lcd_st7796; components/io_expander/esp_io_expander;components/io_expander/esp_io_expander_tca9554; namespace: "espressif" api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} diff --git a/LCD.md b/LCD.md index 4f018c08..334f4d7d 100644 --- a/LCD.md +++ b/LCD.md @@ -4,11 +4,11 @@ The list of available LCD displays and links to LCD driver component and touch d | Picture | Name | LCD Controller | LCD Driver | Touch Controller | Touch Driver | Notes | | ---------------------------------------- | ---- | -------------- | ---------- | ---------------- | ------------ | ----- | -| | [ESP-WROVER-KIT](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-wrover-kit.html) | ST7789 | [IDF](https://github.com/espressif/esp-idf/tree/master/components/esp_lcd) | - | - | | -| | [ESP-WROVER-KIT](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-wrover-kit.html) | ILI9341 | [IDF](https://github.com/espressif/esp-idf/tree/master/components/esp_lcd) | -| - | | +| | [ESP-WROVER-KIT](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-wrover-kit.html) | ST7789 | [IDF](https://github.com/espressif/esp-idf/tree/master/components/esp_lcd) | - | - | | +| | [ESP-WROVER-KIT](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-wrover-kit.html) | ILI9341 | [IDF](https://github.com/espressif/esp-idf/tree/master/components/esp_lcd) | -| - | | | | ESP-BOX | ST7789 | [IDF](https://github.com/espressif/esp-idf/tree/master/components/esp_lcd) | TT21100 | [Component Manager](https://components.espressif.com/component/espressif/esp_lcd_touch_tt21100) | | -| | [ESP32-S2-Kaluga Kit](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-esp32-s2-kaluga-1-kit.html) | ST7789 | [IDF](https://github.com/espressif/esp-idf/tree/master/components/esp_lcd) | - | - | | -| | [ESP32-S3-USB-OTG](https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32s3/esp32-s3-usb-otg/user_guide.html) | ST7789 | [IDF](https://github.com/espressif/esp-idf/tree/master/components/esp_lcd) | - | - | | +| | [ESP32-S2-Kaluga Kit](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-esp32-s2-kaluga-1-kit.html) | ST7789 | [IDF](https://github.com/espressif/esp-idf/tree/master/components/esp_lcd) | - | - | | +| | [ESP32-S3-USB-OTG](https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32s3/esp32-s3-usb-otg/user_guide.html) | ST7789 | [IDF](https://github.com/espressif/esp-idf/tree/master/components/esp_lcd) | - | - | | | | [ESP32-S2-HMI-DevKit-1](https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32s2/esp32-s2-hmi-devkit-1/user_guide.html#hardware-overview) | RM68120 | **IN PLAN** | FT5X06 | [Component Manager](https://components.espressif.com/component/espressif/esp_lcd_touch_ft5x06) | | | | [Waveshare 1.28" round LCD](https://www.waveshare.com/product/1.28inch-lcd-module.htm) | GC9A01 | [Component Manager](https://components.espressif.com/component/espressif/esp_lcd_gc9a01) | - | - | | | | [Waveshare 7" LCD](https://www.waveshare.com/7inch-capacitive-touch-lcd-c.htm) | RA8875 | [Component Manager](https://components.espressif.com/component/espressif/esp_lcd_ra8875) | GT911 | [Component Manager](https://components.espressif.com/component/espressif/esp_lcd_touch_gt911) | | @@ -17,3 +17,4 @@ The list of available LCD displays and links to LCD driver component and touch d | | [64×128 1.3" OLED](https://www.waveshare.com/1.3inch-oled-module-c.htm) | SH1107 | [Component Manager](https://components.espressif.com/component/espressif/esp_lcd_sh1107) | - | - | | | | 128x32 0,91" OLED | SSD1306 | [IDF](https://github.com/espressif/esp-idf/tree/master/components/esp_lcd) | - | - | | | | Parallel | SSD1963 | **N/A** | - | - | | +| | Parallel/SPI | ST7796 | [Component Manager](https://components.espressif.com/component/espressif/esp_lcd_st7796) | - | - | | diff --git a/components/lcd/esp_lcd_st7796/CMakeLists.txt b/components/lcd/esp_lcd_st7796/CMakeLists.txt new file mode 100644 index 00000000..d23f96c7 --- /dev/null +++ b/components/lcd/esp_lcd_st7796/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "esp_lcd_st7796.c" + INCLUDE_DIRS "include" + REQUIRES "esp_lcd" + PRIV_REQUIRES "driver") diff --git a/components/lcd/esp_lcd_st7796/README.md b/components/lcd/esp_lcd_st7796/README.md new file mode 100644 index 00000000..13d58e14 --- /dev/null +++ b/components/lcd/esp_lcd_st7796/README.md @@ -0,0 +1,78 @@ +# ESP LCD ST7796 + +[![Component Registry](https://components.espressif.com/components/espressif/esp_lcd_st7796/badge.svg)](https://components.espressif.com/components/espressif/esp_lcd_st7796) + +Implementation of the ST7796 LCD controller with esp_lcd component. + +| LCD controller | Communication interface | Component name | Link to datasheet | +| :------------: | :---------------------: | :------------: | :---------------: | +| ST7796 | SPI/I80 | esp_lcd_st7796 | [Specification](https://www.displayfuture.com/Display/datasheet/controller/ST7796s.pdf) | + +## Add to project + +Packages from this repository are uploaded to [Espressif's component service](https://components.espressif.com/). +You can add them to your project via `idf.py add-dependency`, e.g. + +```bash +compote manifest add-dependency espressif/esp_lcd_st7796==1.0.0 +``` + +Alternatively, you can create `idf_component.yml`. More is in [Espressif's documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html). + +## Initialization Code (i80 interface) + +```c +size_t draw_buffer_pixels = EXAMPLE_LCD_H_RES * 100; + +ESP_LOGI(TAG, "Initialize Intel 8080 bus"); +esp_lcd_i80_bus_handle_t i80_bus = NULL; +esp_lcd_i80_bus_config_t bus_config = { + .clk_src = LCD_CLK_SRC_DEFAULT, + .dc_gpio_num = EXAMPLE_PIN_NUM_DC, + .wr_gpio_num = EXAMPLE_PIN_NUM_PCLK, + .data_gpio_nums = { + EXAMPLE_PIN_NUM_DATA0, + EXAMPLE_PIN_NUM_DATA1, + EXAMPLE_PIN_NUM_DATA2, + EXAMPLE_PIN_NUM_DATA3, + EXAMPLE_PIN_NUM_DATA4, + EXAMPLE_PIN_NUM_DATA5, + EXAMPLE_PIN_NUM_DATA6, + EXAMPLE_PIN_NUM_DATA7, + }, + .bus_width = 8, + .max_transfer_bytes = draw_buffer_pixels * sizeof(uint16_t), +}; +ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); +esp_lcd_panel_io_handle_t io_handle = NULL; +esp_lcd_panel_io_i80_config_t io_config = { + .cs_gpio_num = EXAMPLE_PIN_NUM_CS, + .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ, + .trans_queue_depth = 10, + .dc_levels = { + .dc_idle_level = 0, + .dc_cmd_level = 0, + .dc_dummy_level = 0, + .dc_data_level = 1, + }, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, +}; +ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle)); + +ESP_LOGI(TAG, "Install st7796 LCD panel driver"); +esp_lcd_panel_handle_t panel_handle = NULL; +esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = EXAMPLE_PIN_NUM_RST, + .rgb_endian = LCD_RGB_ENDIAN_BGR, + .bits_per_pixel = 16, +}; +ESP_ERROR_CHECK(esp_lcd_new_panel_st7796(io_handle, &panel_config, &panel_handle)); + +esp_lcd_panel_reset(panel_handle); +esp_lcd_panel_init(panel_handle); +esp_lcd_panel_mirror(panel_handle, true, true); +esp_lcd_panel_swap_xy(panel_handle, true); + +ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); +``` diff --git a/components/lcd/esp_lcd_st7796/esp_lcd_st7796.c b/components/lcd/esp_lcd_st7796/esp_lcd_st7796.c new file mode 100644 index 00000000..2f0c4a5b --- /dev/null +++ b/components/lcd/esp_lcd_st7796/esp_lcd_st7796.c @@ -0,0 +1,304 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_lcd_panel_interface.h" +#include "esp_lcd_panel_io.h" +#include "esp_lcd_panel_vendor.h" +#include "esp_lcd_panel_ops.h" +#include "esp_lcd_panel_commands.h" +#include "driver/gpio.h" +#include "esp_log.h" +#include "esp_check.h" + +static const char *TAG = "st7796"; + +static esp_err_t panel_st7796_del(esp_lcd_panel_t *panel); +static esp_err_t panel_st7796_reset(esp_lcd_panel_t *panel); +static esp_err_t panel_st7796_init(esp_lcd_panel_t *panel); +static esp_err_t panel_st7796_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data); +static esp_err_t panel_st7796_invert_color(esp_lcd_panel_t *panel, bool invert_color_data); +static esp_err_t panel_st7796_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); +static esp_err_t panel_st7796_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); +static esp_err_t panel_st7796_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); +static esp_err_t panel_st7796_disp_on_off(esp_lcd_panel_t *panel, bool off); + +typedef struct { + esp_lcd_panel_t base; + esp_lcd_panel_io_handle_t io; + int reset_gpio_num; + bool reset_level; + int x_gap; + int y_gap; + uint8_t fb_bits_per_pixel; + uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register + uint8_t colmod_cal; // save surrent value of LCD_CMD_COLMOD register +} st7796_panel_t; + +esp_err_t esp_lcd_new_panel_st7796(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel) +{ + esp_err_t ret = ESP_OK; + st7796_panel_t *st7796 = NULL; + ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + st7796 = calloc(1, sizeof(st7796_panel_t)); + ESP_GOTO_ON_FALSE(st7796, ESP_ERR_NO_MEM, err, TAG, "no mem for st7796 panel"); + + if (panel_dev_config->reset_gpio_num >= 0) { + gpio_config_t io_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num, + }; + ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed"); + } + + switch (panel_dev_config->color_space) { + case ESP_LCD_COLOR_SPACE_RGB: + st7796->madctl_val = 0; + break; + case ESP_LCD_COLOR_SPACE_BGR: + st7796->madctl_val |= LCD_CMD_BGR_BIT; + break; + default: + ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space"); + break; + } + + uint8_t fb_bits_per_pixel = 0; + switch (panel_dev_config->bits_per_pixel) { + case 16: // RGB565 + st7796->colmod_cal = 0x55; + fb_bits_per_pixel = 16; + break; + case 18: // RGB666 + st7796->colmod_cal = 0x66; + // each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel + fb_bits_per_pixel = 24; + break; + default: + ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width"); + break; + } + + st7796->io = io; + st7796->fb_bits_per_pixel = fb_bits_per_pixel; + st7796->reset_gpio_num = panel_dev_config->reset_gpio_num; + st7796->reset_level = panel_dev_config->flags.reset_active_high; + st7796->base.del = panel_st7796_del; + st7796->base.reset = panel_st7796_reset; + st7796->base.init = panel_st7796_init; + st7796->base.draw_bitmap = panel_st7796_draw_bitmap; + st7796->base.invert_color = panel_st7796_invert_color; + st7796->base.set_gap = panel_st7796_set_gap; + st7796->base.mirror = panel_st7796_mirror; + st7796->base.swap_xy = panel_st7796_swap_xy; +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) + st7796->base.disp_off = panel_st7796_disp_on_off; +#else + st7796->base.disp_on_off = panel_st7796_disp_on_off; +#endif + *ret_panel = &(st7796->base); + ESP_LOGD(TAG, "new st7796 panel @%p", st7796); + + return ESP_OK; + +err: + if (st7796) { + if (panel_dev_config->reset_gpio_num >= 0) { + gpio_reset_pin(panel_dev_config->reset_gpio_num); + } + free(st7796); + } + return ret; +} + +static esp_err_t panel_st7796_del(esp_lcd_panel_t *panel) +{ + st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base); + + if (st7796->reset_gpio_num >= 0) { + gpio_reset_pin(st7796->reset_gpio_num); + } + ESP_LOGD(TAG, "del st7796 panel @%p", st7796); + free(st7796); + return ESP_OK; +} + +static esp_err_t panel_st7796_reset(esp_lcd_panel_t *panel) +{ + st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base); + esp_lcd_panel_io_handle_t io = st7796->io; + + // perform hardware reset + if (st7796->reset_gpio_num >= 0) { + gpio_set_level(st7796->reset_gpio_num, st7796->reset_level); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level(st7796->reset_gpio_num, !st7796->reset_level); + vTaskDelay(pdMS_TO_TICKS(10)); + } else { // perform software reset + esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0); + vTaskDelay(pdMS_TO_TICKS(20)); // spec, wait at least 5ms before sending new command + } + + return ESP_OK; +} + +typedef struct { + uint8_t cmd; + uint8_t data[16]; + uint8_t data_bytes; // Length of data in above data array; 0xFF = end of cmds. +} lcd_init_cmd_t; + +static const lcd_init_cmd_t vendor_specific_init[] = { + {0xf0, {0xc3}, 1}, + {0xf0, {0x96}, 1}, + {0xb4, {0x01}, 1}, + {0xb7, {0xc6}, 1}, + {0xe8, {0x40, 0x8a, 0x00, 0x00, 0x29, 0x19, 0xa5, 0x33}, 8}, + {0xc1, {0x06}, 1}, + {0xc2, {0xa7}, 1}, + {0xc5, {0x18}, 1}, + {0xe0, {0xf0, 0x09, 0x0b, 0x06, 0x04, 0x15, 0x2f, 0x54, 0x42, 0x3c, 0x17, 0x14, 0x18, 0x1b}, 14}, + {0xe1, {0xf0, 0x09, 0x0b, 0x06, 0x04, 0x03, 0x2d, 0x43, 0x42, 0x3b, 0x16, 0x14, 0x17, 0x1b}, 14}, + {0xf0, {0x3c}, 1}, + {0xf0, {0x69}, 1}, + {0, {0}, 0xff}, +}; + +static esp_err_t panel_st7796_init(esp_lcd_panel_t *panel) +{ + st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base); + esp_lcd_panel_io_handle_t io = st7796->io; + + // LCD goes into sleep mode and display will be turned off after power on reset, exit sleep mode first + esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0); + vTaskDelay(pdMS_TO_TICKS(100)); + esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) { + st7796->madctl_val, + }, 1); + esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) { + st7796->colmod_cal, + }, 1); + + // vendor specific initialization, it can be different between manufacturers + // should consult the LCD supplier for initialization sequence code + int cmd = 0; + while (vendor_specific_init[cmd].data_bytes != 0xff) { + esp_lcd_panel_io_tx_param(io, vendor_specific_init[cmd].cmd, vendor_specific_init[cmd].data, vendor_specific_init[cmd].data_bytes & 0x1F); + cmd++; + } + + return ESP_OK; +} + +static esp_err_t panel_st7796_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data) +{ + st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base); + assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position"); + esp_lcd_panel_io_handle_t io = st7796->io; + + x_start += st7796->x_gap; + x_end += st7796->x_gap; + y_start += st7796->y_gap; + y_end += st7796->y_gap; + + // define an area of frame memory where MCU can access + esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]) { + (x_start >> 8) & 0xFF, + x_start & 0xFF, + ((x_end - 1) >> 8) & 0xFF, + (x_end - 1) & 0xFF, + }, 4); + esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]) { + (y_start >> 8) & 0xFF, + y_start & 0xFF, + ((y_end - 1) >> 8) & 0xFF, + (y_end - 1) & 0xFF, + }, 4); + // transfer frame buffer + size_t len = (x_end - x_start) * (y_end - y_start) * st7796->fb_bits_per_pixel / 8; + esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len); + + return ESP_OK; +} + +static esp_err_t panel_st7796_invert_color(esp_lcd_panel_t *panel, bool invert_color_data) +{ + st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base); + esp_lcd_panel_io_handle_t io = st7796->io; + int command = 0; + if (invert_color_data) { + command = LCD_CMD_INVON; + } else { + command = LCD_CMD_INVOFF; + } + esp_lcd_panel_io_tx_param(io, command, NULL, 0); + return ESP_OK; +} + +static esp_err_t panel_st7796_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) +{ + st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base); + esp_lcd_panel_io_handle_t io = st7796->io; + if (mirror_x) { + st7796->madctl_val |= LCD_CMD_MX_BIT; + } else { + st7796->madctl_val &= ~LCD_CMD_MX_BIT; + } + if (mirror_y) { + st7796->madctl_val |= LCD_CMD_MY_BIT; + } else { + st7796->madctl_val &= ~LCD_CMD_MY_BIT; + } + esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) { + st7796->madctl_val + }, 1); + return ESP_OK; +} + +static esp_err_t panel_st7796_swap_xy(esp_lcd_panel_t *panel, bool swap_axes) +{ + st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base); + esp_lcd_panel_io_handle_t io = st7796->io; + if (swap_axes) { + st7796->madctl_val |= LCD_CMD_MV_BIT; + } else { + st7796->madctl_val &= ~LCD_CMD_MV_BIT; + } + esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) { + st7796->madctl_val + }, 1); + return ESP_OK; +} + +static esp_err_t panel_st7796_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap) +{ + st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base); + st7796->x_gap = x_gap; + st7796->y_gap = y_gap; + return ESP_OK; +} + +static esp_err_t panel_st7796_disp_on_off(esp_lcd_panel_t *panel, bool on_off) +{ + st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base); + esp_lcd_panel_io_handle_t io = st7796->io; + int command = 0; + +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) + on_off = !on_off; +#endif + + if (on_off) { + command = LCD_CMD_DISPON; + } else { + command = LCD_CMD_DISPOFF; + } + esp_lcd_panel_io_tx_param(io, command, NULL, 0); + return ESP_OK; +} diff --git a/components/lcd/esp_lcd_st7796/idf_component.yml b/components/lcd/esp_lcd_st7796/idf_component.yml new file mode 100644 index 00000000..b8f67dbd --- /dev/null +++ b/components/lcd/esp_lcd_st7796/idf_component.yml @@ -0,0 +1,5 @@ +version: "1.0.0" +description: ESP LCD ST7796 driver +url: https://github.com/espressif/esp-bsp/tree/master/components/lcd/esp_lcd_st7796 +dependencies: + idf: ">=4.4" diff --git a/components/lcd/esp_lcd_st7796/include/esp_lcd_st7796.h b/components/lcd/esp_lcd_st7796/include/esp_lcd_st7796.h new file mode 100644 index 00000000..c95f6bad --- /dev/null +++ b/components/lcd/esp_lcd_st7796/include/esp_lcd_st7796.h @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @file + * @brief ESP LCD: ST7796 + */ + +#pragma once + +#include "esp_lcd_panel_vendor.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Create LCD panel for model ST7796 + * + * @param[in] io LCD panel IO handle + * @param[in] panel_dev_config general panel device configuration + * @param[out] ret_panel Returned LCD panel handle + * @return + * - ESP_ERR_INVALID_ARG if parameter is invalid + * - ESP_ERR_NO_MEM if out of memory + * - ESP_OK on success + */ +esp_err_t esp_lcd_new_panel_st7796(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel); + +#ifdef __cplusplus +} +#endif diff --git a/components/lcd/esp_lcd_st7796/license.txt b/components/lcd/esp_lcd_st7796/license.txt new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/components/lcd/esp_lcd_st7796/license.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. diff --git a/docu/pics/st7796.jpg b/docu/pics/st7796.jpg new file mode 100644 index 0000000000000000000000000000000000000000..85dfab75bea4a53b12a5e8117fba7062e9acf8c5 GIT binary patch literal 47056 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 M4bHM?0Ds&6*~(1gwg3PC literal 0 HcmV?d00001