├── .editorconfig ├── .github └── auto-comment.yml ├── .gitignore ├── CMakeLists.txt ├── CONTRIBUTE_CONTROLLER_SUPPORT.md ├── Kconfig ├── LICENSE ├── README.md ├── component.mk ├── lvgl_helpers.c ├── lvgl_helpers.h ├── lvgl_i2c ├── Kconfig ├── README.md ├── i2c_manager.c └── i2c_manager.h ├── lvgl_spi_conf.h ├── lvgl_tft ├── EVE.h ├── EVE_commands.c ├── EVE_commands.h ├── EVE_config.h ├── FT81x.c ├── FT81x.h ├── GC9A01.c ├── GC9A01.h ├── Kconfig ├── disp_driver.c ├── disp_driver.h ├── disp_spi.c ├── disp_spi.h ├── esp_lcd_backlight.c ├── esp_lcd_backlight.h ├── hx8357.c ├── hx8357.h ├── il3820.c ├── il3820.h ├── ili9163c.c ├── ili9163c.h ├── ili9341.c ├── ili9341.h ├── ili9481.c ├── ili9481.h ├── ili9486.c ├── ili9486.h ├── ili9488.c ├── ili9488.h ├── jd79653a.c ├── jd79653a.h ├── pcd8544.c ├── pcd8544.h ├── ra8875.c ├── ra8875.h ├── sh1107.c ├── sh1107.h ├── ssd1306.c ├── ssd1306.h ├── st7735s.c ├── st7735s.h ├── st7789.c ├── st7789.h ├── st7796s.c ├── st7796s.h ├── uc8151d.c └── uc8151d.h └── lvgl_touch ├── FT81x.c ├── FT81x.h ├── Kconfig ├── adcraw.c ├── adcraw.h ├── ft6x36.c ├── ft6x36.h ├── gt911.c ├── gt911.h ├── ra8875_touch.c ├── ra8875_touch.h ├── stmpe610.c ├── stmpe610.h ├── touch_driver.c ├── touch_driver.h ├── tp_spi.c ├── tp_spi.h ├── xpt2046.c └── xpt2046.h /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # http://editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | indent_style = space 9 | indent_size = 4 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | 15 | [{*.md,*.rst}] 16 | trim_trailing_whitespace = false 17 | 18 | [{Makefile,*.mk,*.bat}] 19 | indent_style = tab 20 | indent_size = 2 21 | 22 | [{*.cmake,CMakeLists.txt}] 23 | indent_style = space 24 | indent_size = 4 25 | max_line_length = 120 26 | 27 | [{*.sh,*.yml}] 28 | indent_style = space 29 | indent_size = 2 30 | -------------------------------------------------------------------------------- /.github/auto-comment.yml: -------------------------------------------------------------------------------- 1 | # Comment to a new issue. 2 | pullRequestOpened: | 3 | Thank you for raising your pull request. 4 | 5 | To ensure that all licensing criteria is met all repositories of the LVGL project apply a process called DCO (Developer's Certificate of Origin). 6 | 7 | The text of DCO can be read here: https://developercertificate.org/ 8 | For a more detailed description see the [Documentation](https://docs.lvgl.io/latest/en/html/contributing/index.html#developer-certification-of-origin-dco) site. 9 | 10 | By contributing to any repositories of the LVGL project you state that your contribution corresponds with the DCO. 11 | 12 | No further action is required if your contribution fulfills the DCO. If you are not sure about it feel free to ask us in a comment. 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | 54 | # MacOS 55 | .DS_Store 56 | 57 | # ESP-IDF build dir 58 | build 59 | 60 | # Kconfig files 61 | sdkconfig 62 | sdkconfig.old -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(ESP_PLATFORM) 2 | 3 | file(GLOB SOURCES *.c) 4 | set(LVGL_INCLUDE_DIRS . lvgl_tft) 5 | list(APPEND SOURCES "lvgl_tft/disp_driver.c") 6 | list(APPEND SOURCES "lvgl_tft/esp_lcd_backlight.c") 7 | 8 | # Include only the source file of the selected 9 | # display controller. 10 | if(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341) 11 | list(APPEND SOURCES "lvgl_tft/ili9341.c") 12 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481) 13 | list(APPEND SOURCES "lvgl_tft/ili9481.c") 14 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486) 15 | list(APPEND SOURCES "lvgl_tft/ili9486.c") 16 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488) 17 | list(APPEND SOURCES "lvgl_tft/ili9488.c") 18 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789) 19 | list(APPEND SOURCES "lvgl_tft/st7789.c") 20 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S) 21 | list(APPEND SOURCES "lvgl_tft/st7735s.c") 22 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S) 23 | list(APPEND SOURCES "lvgl_tft/st7796s.c") 24 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357) 25 | list(APPEND SOURCES "lvgl_tft/hx8357.c") 26 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107) 27 | list(APPEND SOURCES "lvgl_tft/sh1107.c") 28 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306) 29 | list(APPEND SOURCES "lvgl_tft/ssd1306.c") 30 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) 31 | list(APPEND SOURCES "lvgl_tft/EVE_commands.c") 32 | list(APPEND SOURCES "lvgl_tft/FT81x.c") 33 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820) 34 | list(APPEND SOURCES "lvgl_tft/il3820.c") 35 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A) 36 | list(APPEND SOURCES "lvgl_tft/jd79653a.c") 37 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D) 38 | list(APPEND SOURCES "lvgl_tft/uc8151d.c") 39 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875) 40 | list(APPEND SOURCES "lvgl_tft/ra8875.c") 41 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01) 42 | list(APPEND SOURCES "lvgl_tft/GC9A01.c") 43 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C) 44 | list(APPEND SOURCES "lvgl_tft/ili9163c.c") 45 | elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544) 46 | list(APPEND SOURCES "lvgl_tft/pcd8544.c") 47 | else() 48 | message(WARNING "LVGL ESP32 drivers: Display controller not defined.") 49 | endif() 50 | 51 | if(CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI) 52 | list(APPEND SOURCES "lvgl_tft/disp_spi.c") 53 | endif() 54 | 55 | # Add touch driver to compilation only if it is selected in menuconfig 56 | if(CONFIG_LV_TOUCH_CONTROLLER) 57 | list(APPEND SOURCES "lvgl_touch/touch_driver.c") 58 | list(APPEND LVGL_INCLUDE_DIRS lvgl_touch) 59 | 60 | # Include only the source file of the selected 61 | # touch controller. 62 | if(CONFIG_LV_TOUCH_CONTROLLER_XPT2046) 63 | list(APPEND SOURCES "lvgl_touch/xpt2046.c") 64 | elseif(CONFIG_LV_TOUCH_CONTROLLER_FT6X06) 65 | list(APPEND SOURCES "lvgl_touch/ft6x36.c") 66 | elseif(CONFIG_LV_TOUCH_CONTROLLER_STMPE610) 67 | list(APPEND SOURCES "lvgl_touch/stmpe610.c") 68 | elseif(CONFIG_LV_TOUCH_CONTROLLER_ADCRAW) 69 | list(APPEND SOURCES "lvgl_touch/adcraw.c") 70 | elseif(CONFIG_LV_TOUCH_CONTROLLER_FT81X) 71 | list(APPEND SOURCES "lvgl_touch/FT81x.c") 72 | elseif(CONFIG_LV_TOUCH_CONTROLLER_RA8875) 73 | list(APPEND SOURCES "lvgl_touch/ra8875_touch.c") 74 | elseif(CONFIG_LV_TOUCH_CONTROLLER_GT911) 75 | list(APPEND SOURCES "lvgl_touch/gt911.c") 76 | endif() 77 | 78 | if(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI) 79 | list(APPEND SOURCES "lvgl_touch/tp_spi.c") 80 | endif() 81 | endif() 82 | 83 | if(CONFIG_LV_I2C) 84 | list(APPEND SOURCES "lvgl_i2c/i2c_manager.c") 85 | endif() 86 | 87 | idf_component_register(SRCS ${SOURCES} 88 | INCLUDE_DIRS ${LVGL_INCLUDE_DIRS} 89 | REQUIRES lvgl) 90 | 91 | target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DLV_LVGL_H_INCLUDE_SIMPLE") 92 | 93 | else() 94 | message(FATAL_ERROR "LVGL ESP32 drivers: ESP_PLATFORM is not defined. Try reinstalling ESP-IDF.") 95 | endif() 96 | -------------------------------------------------------------------------------- /CONTRIBUTE_CONTROLLER_SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Is your driver not listed on the supported drivers list? 2 | 3 | Consider contributing to this demo project by adding support to your driver. 4 | 5 | ## Display driver. 6 | 7 | To enable LVGL to work with your display you would need to implement from one up to three callback functions (one function for RGB TFT displays, three functions for monochrome display controllers), you can add more functions to enable backlight control, etc. 8 | 9 | All display controller code is stored on the `components/lvgl_esp32_drivers/lvgl_tft` directory, see `disp_driver` and `CMakeLists.txt` to add your code into the idf project. 10 | 11 | Create a header and source file named after the display controller (in lowercase). On the header file declare the necessary functions, such as: 12 | 13 | ```c 14 | /* Configure your display */ 15 | void x_init(void); 16 | 17 | /* LVGL callbacks */ 18 | void x_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); 19 | /* Only for monochrome displays */ 20 | void x_rounder(lv_disp_drv_t *disp_drv, lv_area_t *area); 21 | void x_set_px(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); 22 | ``` 23 | 24 | Where x is the controller name. 25 | 26 | For more information on the function callbacks check LVGL documentation: (Display driver)[https://docs.lvgl.io/v7/en/html/porting/display.html#display-driver]. 27 | 28 | Add your display functions on `disp_driver_init`, `disp_driver_flush`, `disp_driver_rounder` and `disp_driver_set_px` on the `disp_driver.c` file. 29 | 30 | ## Input device driver. 31 | 32 | To enable LVGL to work with your touch controller you would need to implement an initialization function and one function to get the data out from your touch controller. 33 | 34 | All touch controller code is stored on the `components/lvgl_esp32_drivers/lvgl_touch` directory. 35 | 36 | Create a header and source file named after the display controller (in lowercase). On the header file declare the necessary functions, such as: 37 | 38 | ```c 39 | /* Configure your display */ 40 | void x_init(void); 41 | 42 | /* LVGL callbacks */ 43 | bool x_read(lv_disp_drv_t *drv, lv_indev_data_t *data); 44 | ``` 45 | 46 | Where x is the controller name. 47 | 48 | For more information on the function callbacks check LVGL documentation: (Display driver)[https://docs.lvgl.io/v7/en/html/porting/indev.html]. 49 | 50 | ## Kconfig and Project Configuration 51 | 52 | The ESP32 SDK (ESP-IDF) uses [kconfiglib](https://github.com/ulfalizer/Kconfiglib) which is a Python-based extension to the [Kconfig](https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt) system which provides a compile-time project configuration mechanism. Using `idf.py menuconfig` will update the file sdkconfig and, during build, provide the file sdkconfig.h. 53 | -------------------------------------------------------------------------------- /Kconfig: -------------------------------------------------------------------------------- 1 | menu "LVGL ESP Drivers" 2 | 3 | rsource "lvgl_tft/Kconfig" 4 | 5 | rsource "lvgl_touch/Kconfig" 6 | 7 | endmenu 8 | 9 | menu "I2C Port Settings" 10 | depends on LV_I2C && !HAVE_I2C_MANAGER 11 | 12 | rsource "lvgl_i2c/Kconfig" 13 | 14 | endmenu 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 LVGL 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Display and touchpad drivers for ESP32 using LVGL 2 | 3 | For a ready to use ESP32 project take look at the [lv_port_esp32](https://github.com/lvgl/lv_port_esp32) repository. 4 | 5 | #### Table of content 6 | - [Supported display controllers](#supported-display-controllers) 7 | - [Supported indev controllers](#supported-indev-controllers) 8 | - [Support for predefined development kits](#support-for-predefined-development-kits) 9 | - [Thread-safe I2C with I2C Manager](#thread-safe-i2c-with-i2c-manager) 10 | - [Backlight control](#backlight-control) 11 | 12 | **NOTE:** You need to set the display horizontal and vertical size, color depth and 13 | swap of RGB565 color on the LVGL configuration menuconfig (it's not handled automatically). 14 | 15 | 16 | ## Supported display controllers 17 | 18 | 19 | | Display Controller | Type | Interface | Color depth (LV_COLOR_DEPTH) | Swap RGB565 color (LV_COLOR_16_SWAP) | 20 | |---------------------------------------------|------------|------------------------|------------------------------|----------------------------------------| 21 | | ILI9341 | TFT | SPI | 16: RGB565 | Yes | 22 | | ILI9163C | TFT | SPI | 16: RGB565 | Yes | 23 | | ILI9486 | TFT | SPI | 16: RGB565 | Yes | 24 | | ILI9488 | TFT | SPI | 16: RGB565 | No | 25 | | HX8357B/HX8357D | TFT | SPI | 16: RGB565 | Yes | 26 | | ST7789 | TFT | SPI | 16: RGB565 | Yes | 27 | | ST7735S | TFT | SPI | 16: RGB565 | Yes | 28 | | FT81x | TFT | Single, Dual, Quad SPI | 16: RGB565 | No | 29 | | GC9A01 | TFT | SPI | 16: RGB565 | Yes | 30 | | RA8875 | TFT | SPI | 16: RGB565 | Yes | 31 | | SH1107 | Monochrome | SPI | 1: 1byte per pixel | No | 32 | | SSD1306 | Monochrome | I2C | 1: 1byte per pixel | No | 33 | | PCD8544 | Monochrome | SPI | 1: 1byte per pixel | No | 34 | | IL3820 | e-Paper | SPI | 1: 1byte per pixel | No | 35 | | UC8151D/ GoodDisplay GDEW0154M10 DES | e-Paper | SPI | 1: 1byte per pixel | No | 36 | | FitiPower JD79653A/ GoodDisplay GDEW0154M09 | e-Paper | SPI | 1: 1byte per pixel | No | 37 | 38 | ## Supported indev controllers 39 | 40 | - XPT2046 41 | - FT3236, FT6X36 42 | - FT6206 controllers should work as well (not tested) 43 | - STMPE610 44 | - FT81x (Single, Dual, and Quad SPI) 45 | 46 | If your display or input device (touch) controller is not supported consider contributing to this repo by 47 | adding support to it! [Contribute controller support](CONTRIBUTE_CONTROLLER_SUPPORT.md) 48 | 49 | ## Support for predefined development kits 50 | 51 | You can also use the predefined kits, which selects the correct display controllers on the kit, 52 | and sets the gpio numbers for the interface. 53 | 54 | | Kit name | Display controller | Interface | Hor. Res. | Ver. Res. | 55 | |---------------------------|-----------------------|-----------|-----------|-----------| 56 | | ESP Wrover Kit v4.1 | ILI9341 | SPI | 240 | 320 | 57 | | M5Stack | ILI9341 | SPI | 240 | 320 | 58 | | M5Stack Core2 | ILI9341 | SPI | 240 | 320 | 59 | | M5Stick | SH1107 | SPI | - | - | 60 | | M5StickC | ST7735S | SPI | 80 | 160 | 61 | | Adafruit 3.5 Featherwing | HX8357 | SPI | 480 | 320 | 62 | | RPi MPI3501 | ILI9486 | SPI | - | - | 63 | | Wemos Lolin OLED | SSD1306 | SPI | 64 | 128 | 64 | | ER-TFT035-6 | ILI9488 | SPI | 480 | 320 | 65 | | AIRcable ATAGv3 | IL3820 | SPI | 128 | 296 | 66 | | TTGO T-Display | ST7789 | SPI | 135 | 240 | 67 | | TTGO Camera Plus | ST7789 | SPI | 240 | 240 | 68 | 69 | **NOTE:** See [Supported display controllers](#supported-display-controllers) for more information on display configuration. 70 | **NOTE:** See [Supported indev controllers](#supported-indev-controllers) for more information about indev configuration. 71 | 72 | 73 | ## Thread-safe I2C with I2C Manager 74 | 75 | LVGL can use I2C to read from a touch sensor or write to a display, possibly 76 | many times a second. Meanwhile, other tasks may also want to read from i2c 77 | devices on the same bus. I2C using the ESP-IDF is not thread-safe. 78 | 79 | I2C Manager (`i2c_manager`) is a component that will let code in multiple threads 80 | talk to devices on the I2C ports without getting in each other's way. These drivers 81 | use a built-in copy of I2C Manager to talk to the I2C port, but you can also use 82 | the I2C Manager component itself and have others play nice with LVGL and vice-versa. 83 | [Click here](i2c_manager/README.md) for details. 84 | 85 | 86 | ## Backlight control 87 | 88 | Control of LCD's backlight is provided by separate module that is independent from the display driver. 89 | Configuration of the backlight controller can be found in menuconfig `LVGL ESP Drivers -> LVGL TFT Display controller`. 90 | 91 | There are three modes of operation: 92 | 1. Off - No backlight control 93 | 2. Switch - Allows ON/OFF control 94 | 3. PWM - Allows brightness control (by Pulse-Width-Modulated signal) 95 | -------------------------------------------------------------------------------- /component.mk: -------------------------------------------------------------------------------- 1 | # LVGL ESP32 drivers 2 | 3 | # Define sources and include dirs 4 | COMPONENT_SRCDIRS := . lvgl_tft lvgl_touch lvgl_i2c 5 | COMPONENT_ADD_INCLUDEDIRS := . 6 | 7 | # LVGL is supposed to be used as a ESP-IDF component 8 | # -> lvlg is already in the include path 9 | # -> we use simple include 10 | CFLAGS += -DLV_LVGL_H_INCLUDE_SIMPLE 11 | 12 | # TFT display drivers 13 | COMPONENT_ADD_INCLUDEDIRS += lvgl_tft 14 | 15 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341),lvgl_tft/ili9341.o) 16 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481),lvgl_tft/ili9481.o) 17 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486),lvgl_tft/ili9486.o) 18 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488),lvgl_tft/ili9488.o) 19 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789),lvgl_tft/st7789.o) 20 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S),lvgl_tft/st7735s.o) 21 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S),lvgl_tft/st7796s.o) 22 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357),lvgl_tft/hx8357.o) 23 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107),lvgl_tft/sh1107.o) 24 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306),lvgl_tft/ssd1306.o) 25 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X),lvgl_tft/EVE_commands.o) 26 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X),lvgl_tft/FT81x.o) 27 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820),lvgl_tft/il3820.o) 28 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A),lvgl_tft/jd79653a.o) 29 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D),lvgl_tft/uc8151d.o) 30 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875),lvgl_tft/ra8875.o) 31 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01),lvgl_tft/GC9A01.o) 32 | 33 | $(call compile_only_if,$(CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI),lvgl_tft/disp_spi.o) 34 | 35 | # Touch controller drivers 36 | COMPONENT_ADD_INCLUDEDIRS += lvgl_touch 37 | 38 | $(call compile_only_if,$(CONFIG_LV_TOUCH_CONTROLLER),lvgl_touch/touch_driver.o) 39 | $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_CONTROLLER_XPT2046)), lvgl_touch/xpt2046.o) 40 | $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_CONTROLLER_FT6X06)), lvgl_touch/ft6x36.o) 41 | $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_CONTROLLER_STMPE610)), lvgl_touch/stmpe610.o) 42 | $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_CONTROLLER_ADCRAW)), lvgl_touch/adcraw.o) 43 | $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_CONTROLLER_FT81X)), lvgl_touch/FT81x.o) 44 | $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_CONTROLLER_RA8875)), lvgl_touch/ra8875_touch.o) 45 | 46 | $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI)), lvgl_touch/tp_spi.o) 47 | 48 | # I2C Manager 49 | $(call compile_only_if,$(CONFIG_LV_I2C), lvgl_i2c/i2c_manager.o) 50 | -------------------------------------------------------------------------------- /lvgl_helpers.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lvgl_helpers.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "sdkconfig.h" 10 | #include "lvgl_helpers.h" 11 | #include "esp_log.h" 12 | 13 | #include "lvgl_tft/disp_spi.h" 14 | #include "lvgl_touch/tp_spi.h" 15 | 16 | #include "lvgl_spi_conf.h" 17 | 18 | #include "lvgl_i2c/i2c_manager.h" 19 | 20 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 21 | #include "lvgl.h" 22 | #else 23 | #include "lvgl/lvgl.h" 24 | #endif 25 | 26 | /********************* 27 | * DEFINES 28 | *********************/ 29 | 30 | #define TAG "lvgl_helpers" 31 | 32 | /********************** 33 | * TYPEDEFS 34 | **********************/ 35 | 36 | /********************** 37 | * STATIC PROTOTYPES 38 | **********************/ 39 | 40 | /********************** 41 | * STATIC VARIABLES 42 | **********************/ 43 | 44 | /********************** 45 | * MACROS 46 | **********************/ 47 | 48 | /********************** 49 | * GLOBAL FUNCTIONS 50 | **********************/ 51 | 52 | /* Interface and driver initialization */ 53 | void lvgl_driver_init(void) 54 | { 55 | /* Since LVGL v8 LV_HOR_RES_MAX and LV_VER_RES_MAX are not defined, so 56 | * print it only if they are defined. */ 57 | #if (LVGL_VERSION_MAJOR < 8) 58 | ESP_LOGI(TAG, "Display hor size: %d, ver size: %d", LV_HOR_RES_MAX, LV_VER_RES_MAX); 59 | #endif 60 | 61 | ESP_LOGI(TAG, "Display buffer size: %d", DISP_BUF_SIZE); 62 | 63 | #if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) 64 | ESP_LOGI(TAG, "Initializing SPI master for FT81X"); 65 | 66 | lvgl_spi_driver_init(TFT_SPI_HOST, 67 | DISP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK, 68 | SPI_BUS_MAX_TRANSFER_SZ, 1, 69 | DISP_SPI_IO2, DISP_SPI_IO3); 70 | 71 | disp_spi_add_device(TFT_SPI_HOST); 72 | disp_driver_init(); 73 | 74 | #if defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X) 75 | touch_driver_init(); 76 | #endif 77 | 78 | return; 79 | #endif 80 | 81 | #if defined (SHARED_SPI_BUS) 82 | ESP_LOGI(TAG, "Initializing shared SPI master"); 83 | 84 | lvgl_spi_driver_init(TFT_SPI_HOST, 85 | TP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK, 86 | SPI_BUS_MAX_TRANSFER_SZ, 1, 87 | -1, -1); 88 | 89 | disp_spi_add_device(TFT_SPI_HOST); 90 | tp_spi_add_device(TOUCH_SPI_HOST); 91 | 92 | disp_driver_init(); 93 | touch_driver_init(); 94 | 95 | return; 96 | #endif 97 | 98 | /* Display controller initialization */ 99 | #if defined CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI 100 | ESP_LOGI(TAG, "Initializing SPI master for display"); 101 | 102 | lvgl_spi_driver_init(TFT_SPI_HOST, 103 | DISP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK, 104 | SPI_BUS_MAX_TRANSFER_SZ, 1, 105 | DISP_SPI_IO2, DISP_SPI_IO3); 106 | 107 | disp_spi_add_device(TFT_SPI_HOST); 108 | 109 | disp_driver_init(); 110 | #elif defined (CONFIG_LV_I2C_DISPLAY) 111 | disp_driver_init(); 112 | #else 113 | #error "No protocol defined for display controller" 114 | #endif 115 | 116 | /* Touch controller initialization */ 117 | #if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONE 118 | #if defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI) 119 | ESP_LOGI(TAG, "Initializing SPI master for touch"); 120 | 121 | lvgl_spi_driver_init(TOUCH_SPI_HOST, 122 | TP_SPI_MISO, TP_SPI_MOSI, TP_SPI_CLK, 123 | 0 /* Defaults to 4094 */, 2, 124 | -1, -1); 125 | 126 | tp_spi_add_device(TOUCH_SPI_HOST); 127 | 128 | touch_driver_init(); 129 | #elif defined (CONFIG_LV_I2C_TOUCH) 130 | touch_driver_init(); 131 | #elif defined (CONFIG_LV_TOUCH_DRIVER_ADC) 132 | touch_driver_init(); 133 | #elif defined (CONFIG_LV_TOUCH_DRIVER_DISPLAY) 134 | touch_driver_init(); 135 | #else 136 | #error "No protocol defined for touch controller" 137 | #endif 138 | #else 139 | #endif 140 | } 141 | 142 | 143 | /* Initialize spi bus master 144 | * 145 | * NOTE: dma_chan type and value changed to int instead of spi_dma_chan_t 146 | * for backwards compatibility with ESP-IDF versions prior v4.3. 147 | * 148 | * We could use the ESP_IDF_VERSION_VAL macro available in the "esp_idf_version.h" 149 | * header available since ESP-IDF v4. 150 | */ 151 | bool lvgl_spi_driver_init(int host, 152 | int miso_pin, int mosi_pin, int sclk_pin, 153 | int max_transfer_sz, 154 | int dma_channel, 155 | int quadwp_pin, int quadhd_pin) 156 | { 157 | assert((0 <= host) && (SPI_HOST_MAX > host)); 158 | const char *spi_names[] = { 159 | "SPI1_HOST", "SPI2_HOST", "SPI3_HOST" 160 | }; 161 | 162 | ESP_LOGI(TAG, "Configuring SPI host %s", spi_names[host]); 163 | ESP_LOGI(TAG, "MISO pin: %d, MOSI pin: %d, SCLK pin: %d, IO2/WP pin: %d, IO3/HD pin: %d", 164 | miso_pin, mosi_pin, sclk_pin, quadwp_pin, quadhd_pin); 165 | 166 | ESP_LOGI(TAG, "Max transfer size: %d (bytes)", max_transfer_sz); 167 | 168 | spi_bus_config_t buscfg = { 169 | .miso_io_num = miso_pin, 170 | .mosi_io_num = mosi_pin, 171 | .sclk_io_num = sclk_pin, 172 | .quadwp_io_num = quadwp_pin, 173 | .quadhd_io_num = quadhd_pin, 174 | .max_transfer_sz = max_transfer_sz 175 | }; 176 | 177 | ESP_LOGI(TAG, "Initializing SPI bus..."); 178 | #if defined (CONFIG_IDF_TARGET_ESP32C3) 179 | dma_channel = SPI_DMA_CH_AUTO; 180 | #endif 181 | esp_err_t ret = spi_bus_initialize(host, &buscfg, (spi_dma_chan_t)dma_channel); 182 | assert(ret == ESP_OK); 183 | 184 | return ESP_OK != ret; 185 | } 186 | -------------------------------------------------------------------------------- /lvgl_helpers.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lvgl_helpers.h 3 | */ 4 | 5 | #ifndef LVGL_HELPERS_H 6 | #define LVGL_HELPERS_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /********************* 13 | * INCLUDES 14 | *********************/ 15 | #include 16 | 17 | #include "lvgl_spi_conf.h" 18 | #include "lvgl_tft/disp_driver.h" 19 | #include "lvgl_tft/esp_lcd_backlight.h" 20 | #include "lvgl_touch/touch_driver.h" 21 | 22 | /********************* 23 | * DEFINES 24 | *********************/ 25 | 26 | /* DISP_BUF_SIZE value doesn't have an special meaning, but it's the size 27 | * of the buffer(s) passed to LVGL as display buffers. The default values used 28 | * were the values working for the contributor of the display controller. 29 | * 30 | * As LVGL supports partial display updates the DISP_BUF_SIZE doesn't 31 | * necessarily need to be equal to the display size. 32 | * 33 | * When using RGB displays the display buffer size will also depends on the 34 | * color format being used, for RGB565 each pixel needs 2 bytes. 35 | * When using the mono theme, the display pixels can be represented in one bit, 36 | * so the buffer size can be divided by 8, e.g. see SSD1306 display size. */ 37 | #if defined (CONFIG_CUSTOM_DISPLAY_BUFFER_SIZE) 38 | #define DISP_BUF_SIZE CONFIG_CUSTOM_DISPLAY_BUFFER_BYTES 39 | #else 40 | #if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789) 41 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) 42 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S 43 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) 44 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S 45 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) 46 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357 47 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) 48 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107 49 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * LV_VER_RES_MAX) 50 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481 51 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) 52 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486 53 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) 54 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488 55 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) 56 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341 57 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) 58 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306 59 | #if defined (CONFIG_LV_THEME_MONO) 60 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * (LV_VER_RES_MAX / 8)) 61 | #else 62 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * LV_VER_RES_MAX) 63 | #endif 64 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) 65 | #define DISP_BUF_LINES 40 66 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * DISP_BUF_LINES) 67 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820) 68 | #define DISP_BUF_SIZE (LV_VER_RES_MAX * IL3820_COLUMNS) 69 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875 70 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) 71 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01) 72 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) 73 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A) 74 | #define DISP_BUF_SIZE ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8) // 5KB 75 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D) 76 | #define DISP_BUF_SIZE ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8) // 2888 bytes 77 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C 78 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) 79 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544) 80 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * (LV_VER_RES_MAX / 8)) 81 | #else 82 | #error "No display controller selected" 83 | #endif 84 | #endif 85 | 86 | /********************** 87 | * TYPEDEFS 88 | **********************/ 89 | 90 | /********************** 91 | * GLOBAL PROTOTYPES 92 | **********************/ 93 | 94 | void lvgl_i2c_locking(void* leader); 95 | 96 | /* Initialize detected SPI and I2C bus and devices */ 97 | void lvgl_driver_init(void); 98 | 99 | /* Initialize SPI master */ 100 | bool lvgl_spi_driver_init(int host, int miso_pin, int mosi_pin, int sclk_pin, 101 | int max_transfer_sz, int dma_channel, int quadwp_pin, int quadhd_pin); 102 | 103 | /********************** 104 | * MACROS 105 | **********************/ 106 | 107 | 108 | #ifdef __cplusplus 109 | } /* extern "C" */ 110 | #endif 111 | 112 | #endif /* LVGL_HELPERS_H */ 113 | -------------------------------------------------------------------------------- /lvgl_i2c/Kconfig: -------------------------------------------------------------------------------- 1 | menu "I2C Port 0" 2 | 3 | config I2C_MANAGER_0_ENABLED 4 | bool "Enable I2C port 0" 5 | 6 | if I2C_MANAGER_0_ENABLED 7 | config I2C_MANAGER_0_SDA 8 | int "SDA (GPIO pin)" 9 | default 0 10 | config I2C_MANAGER_0_SCL 11 | int "SCL (GPIO pin)" 12 | default 0 13 | config I2C_MANAGER_0_FREQ_HZ 14 | int "Frequency (Hz)" 15 | default 400000 16 | range 100000 5000000 17 | help 18 | The clock speed in Hz. Ranges from 100000 (100 kHz) to 19 | 5000000 (5 Mhz). I2C busses that involve external wires may 20 | have to be slower, and the real maximum speed the bus will 21 | support depends on the value of the pullup resistors and the 22 | design of the overall circuit. 23 | config I2C_MANAGER_0_TIMEOUT 24 | int "R/W timeout (ms)" 25 | default 20 26 | range 10 1000 27 | help 28 | Timeout for I2C read and write operations. This does not 29 | include the time waiting for a lock. 30 | config I2C_MANAGER_0_LOCK_TIMEOUT 31 | int "Stale lock override (ms)" 32 | default 50 33 | range 10 1000 34 | help 35 | Timeout at which point an operation waiting for its turn on 36 | the port will assume that whatever set the lock has died and 37 | overrides it. Set this somewhat larger than the previous 38 | timeout. 39 | config I2C_MANAGER_0_PULLUPS 40 | bool "Use ESP32 built-in bus pull-up resistors" 41 | help 42 | The I2C bus needs resistors to make sure it's in a defined 43 | state when nobody is talking. Many circuits have external 44 | pullup resistors already and turning these on will increase 45 | power consumption slightly and may limit the speed your bus 46 | can attain. Try with these off first if you don't know. 47 | endif 48 | 49 | endmenu 50 | 51 | 52 | menu "I2C Port 1" 53 | 54 | config I2C_MANAGER_1_ENABLED 55 | bool "Enable I2C port 1" 56 | 57 | if I2C_MANAGER_1_ENABLED 58 | config I2C_MANAGER_1_SDA 59 | int "SDA (GPIO pin)" 60 | config I2C_MANAGER_1_SCL 61 | int "SCL (GPIO pin)" 62 | config I2C_MANAGER_1_FREQ_HZ 63 | int "Frequency (Hz)" 64 | default 1000000 65 | range 100000 5000000 66 | help 67 | The clock speed in Hz. Ranges from 100000 (100 kHz) to 68 | 5000000 (5 Mhz). I2C busses that involve external wires may 69 | have to be slower, and the real maximum speed the bus will 70 | support depends on the value of the pullup resistors and the 71 | design of the overall circuit. 72 | config I2C_MANAGER_1_TIMEOUT 73 | int "R/W timeout (ms)" 74 | default 20 75 | range 10 1000 76 | help 77 | Timeout for I2C read and write operations. This does not 78 | include the time waiting for a lock. Default should be fine. 79 | config I2C_MANAGER_1_LOCK_TIMEOUT 80 | int "Stale lock override (ms)" 81 | default 50 82 | help 83 | Timeout at which point an operation waiting for its turn on 84 | the port will assume that whatever set the lock has died and 85 | overrides it. Set this somewhat larger than the previous 86 | timeout. Default should be fine. 87 | range 30 1000 88 | config I2C_MANAGER_1_PULLUPS 89 | bool "Use ESP32 built-in bus pull-up resistors" 90 | help 91 | The I2C bus needs resistors to make sure it's in a defined 92 | state when nobody is talking. Many circuits have external 93 | pullup resistors already and turning these on will increase 94 | power consumption slightly and may limit the speed your bus 95 | can attain. Try with these off first if you don't know. 96 | endif 97 | 98 | endmenu 99 | -------------------------------------------------------------------------------- /lvgl_i2c/README.md: -------------------------------------------------------------------------------- 1 | # I2C in `lvgl_esp32_drivers` 2 | 3 | 4 |   5 | 6 | 7 | ## Information for users 8 | 9 | ### I2C Manager support 10 | 11 | `lvgl_esp32_drivers` integrates [I2C Manager](https://github.com/ropg/i2c_manager), which is used in case you select a touch sensor or screen that uses the I2C bus. 12 | 13 | I2C Manager is also available as a separate ESP-IDF component and can help if you are in a situation where you want to avoid "bus conflicts" on the I2C bus. **If in your application nothing outside of LVGL needs to talk to the I2C bus, you can stop reading here.** 14 | 15 | Suppose you use LVGL with a touch sensor that uses I2C, and your device also has another I2C device that needs to be read frequently, such as a 3D-accelerometer. ESP-IDF is not inherently "thread-safe". So if you read that from another task than the one LVGL uses to read the touch data, you need some kind of mechanism to keep these communications from interfering. 16 | 17 | If you have (or write) a driver for that 3D-accelerometer that can use I2C Manager (or the I2C HAL and i2cdev abstraction layers that I2C Manager is compatible with) then put I2C Manager in your components directory by cloning the repository from below and in your main program do: 18 | 19 | ```c 20 | #include "i2c_manager.h" 21 | #include "lvgl_helpers.h" 22 | 23 | [...] 24 | 25 | lvgl_i2c_locking(i2c_manager_locking()); 26 | lv_init(); 27 | lvgl_driver_init(); 28 | ``` 29 | 30 | The `lvgl_i2c_locking` part will cause the LVGL I2C driver to play nice with anything else that uses the I2C port(s) through I2C Manager. 31 | 32 | 33 |   34 | 35 | 36 | ## Information for LVGL driver developers 37 | 38 | I2C support in the LVGL ESP drivers is provided exclusively by the files in this directory. Driver code that uses I2C communicates through the functions provided in `i2c_manager.h`. 39 | 40 | 41 |   42 | 43 | 44 | ### Using I2C in an LVGL driver, a multi-step guide 45 | 46 |
47 | 48 |
Step 1
49 | 50 |
51 | The Kconfig entries for your driver only need to specify that you will be using I2C. This is done by adding `select LV_I2C_DISPLAY` or `select LV_I2C_TOUCH`. 52 |
53 | 54 | 55 |
Step 2
56 | 57 |
58 | To use the I2C port in your code you would do something like: 59 | 60 | 61 | ```c 62 | #include "lvgl_i2c/i2c_manager.h" 63 | 64 | uint8_t data[2]; 65 | lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, 0x23, 0x42, &data, 2); 66 | ``` 67 | 68 | This causes a touch driver to read two bytes at register `0x42` from the IC at address `0x23`. Replace `CONFIG_LV_I2C_TOUCH_PORT` by `CONFIG_LV_I2C_DISPLAY_PORT` when this is a display instead of a touch driver. `lvgl_i2c_write` works much the same way, except it writes the bytes from the buffer instead of reading them. _(It's ignored above but these functions return `esp_err_t` so you can check if the I2C communication worked.)_ 69 |
70 | 71 |
Step 3
72 | 73 |
74 | There is no step 3, you are already done. 75 |
76 | 77 |
78 | 79 | 80 | ### Meanwhile, behind the scenes ... 81 | 82 | If any of the drivers selected by the user uses I2C, the menuconfig system will show an extra menu to select I2C port(s) for screen and/or touch sensor. An additional menu allows for setting of GPIO pins and bus speed of any port selected for use with LVGL. It's perfectly fine for a display and a touch sensor to be on the same I2C port or different ones. 83 | 84 | 85 |   86 | 87 | 88 | ## More information 89 | 90 | If you need more documentation, please refer to the [I2C Manager GitHub repository](https://github.com/ropg/i2c_manager) for more detailed information on how I2C manager works. There are features not in the simple example above, such as reads and writes without specifying a register, 16-bit registers, 10-bit I2C addressing and more. 91 | -------------------------------------------------------------------------------- /lvgl_i2c/i2c_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef _I2C_MANAGER_H 2 | #define _I2C_MANAGER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /* 10 | 11 | If you copy the i2c_manager files to your own component instead of 12 | depending on i2c_manager, you MUST uncomment the define below 13 | and put in some short string that identifies your component (such 14 | as 'xyz'). This will cause i2c_manager to create functions named 15 | xyz_i2c_* instead of i2c_manager_*. See README.md for details. 16 | 17 | */ 18 | 19 | #define I2C_OEM lvgl 20 | 21 | 22 | // Only here to get the I2C_NUM_0 and I2C_NUM_1 defines. 23 | #include 24 | 25 | #define CONCATX(A, B) A ## B 26 | #define CONCAT(A, B) CONCATX(A, B) 27 | #define STR_LITERAL(s) # s 28 | #define STR_EXPAND(s) STR_LITERAL(s) 29 | #define STR_QUOTE(s) STR_EXPAND(STR_EXPAND(s)) 30 | 31 | #ifdef I2C_OEM 32 | #define I2C_NAME_PREFIX CONCAT(I2C_OEM, _i2c) 33 | #else 34 | #define I2C_NAME_PREFIX i2c_manager 35 | #endif 36 | #define I2C_TAG STR_EXPAND(I2C_NAME_PREFIX) 37 | 38 | #define I2C_FN(s) CONCAT(I2C_NAME_PREFIX, s) 39 | 40 | 41 | #define I2C_ADDR_10 ( 1 << 15 ) 42 | #define I2C_REG_16 ( 1 << 31 ) 43 | #define I2C_NO_REG ( 1 << 30 ) 44 | 45 | esp_err_t I2C_FN(_init)(i2c_port_t port); 46 | esp_err_t I2C_FN(_read)(i2c_port_t port, uint16_t addr, uint32_t reg, uint8_t *buffer, uint16_t size); 47 | esp_err_t I2C_FN(_write)(i2c_port_t port, uint16_t addr, uint32_t reg, const uint8_t *buffer, uint16_t size); 48 | esp_err_t I2C_FN(_close)(i2c_port_t port); 49 | esp_err_t I2C_FN(_lock)(i2c_port_t port); 50 | esp_err_t I2C_FN(_unlock)(i2c_port_t port); 51 | esp_err_t I2C_FN(_force_unlock)(i2c_port_t port); 52 | 53 | 54 | #ifdef I2C_OEM 55 | 56 | void I2C_FN(_locking)(void* leader); 57 | 58 | #else 59 | 60 | void* i2c_manager_locking(); 61 | 62 | typedef struct { 63 | int32_t (* read)(void *handle, uint8_t address, uint8_t reg, uint8_t *buffer, uint16_t size); 64 | int32_t (* write)(void *handle, uint8_t address, uint8_t reg, const uint8_t *buffer, uint16_t size); 65 | void *handle; 66 | } i2c_hal_t; 67 | 68 | void* i2c_hal(i2c_port_t port); 69 | 70 | #endif 71 | 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | #endif 77 | -------------------------------------------------------------------------------- /lvgl_spi_conf.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lvgl_spi_conf.h 3 | * 4 | */ 5 | 6 | #ifndef LVGL_SPI_CONF_H 7 | #define LVGL_SPI_CONF_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | 17 | /********************* 18 | * DEFINES 19 | *********************/ 20 | // DISPLAY PINS 21 | #define DISP_SPI_MOSI CONFIG_LV_DISP_SPI_MOSI 22 | #if defined (CONFIG_LV_DISPLAY_USE_SPI_MISO) 23 | #define DISP_SPI_MISO CONFIG_LV_DISP_SPI_MISO 24 | #define DISP_SPI_INPUT_DELAY_NS CONFIG_LV_DISP_SPI_INPUT_DELAY_NS 25 | #else 26 | #define DISP_SPI_MISO (-1) 27 | #define DISP_SPI_INPUT_DELAY_NS (0) 28 | #endif 29 | #if defined(CONFIG_LV_DISP_SPI_IO2) 30 | #define DISP_SPI_IO2 CONFIG_LV_DISP_SPI_IO2 31 | #else 32 | #define DISP_SPI_IO2 (-1) 33 | #endif 34 | #if defined(CONFIG_LV_DISP_SPI_IO3) 35 | #define DISP_SPI_IO3 CONFIG_LV_DISP_SPI_IO3 36 | #else 37 | #define DISP_SPI_IO3 (-1) 38 | #endif 39 | #define DISP_SPI_CLK CONFIG_LV_DISP_SPI_CLK 40 | #if defined (CONFIG_LV_DISPLAY_USE_SPI_CS) 41 | #define DISP_SPI_CS CONFIG_LV_DISP_SPI_CS 42 | #else 43 | #define DISP_SPI_CS (-1) 44 | #endif 45 | 46 | /* Define TOUCHPAD PINS when selecting a touch controller */ 47 | #if !defined (CONFIG_LV_TOUCH_CONTROLLER_NONE) 48 | 49 | /* Handle FT81X special case */ 50 | #if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) && \ 51 | defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X) 52 | 53 | #define TP_SPI_MOSI CONFIG_LV_DISP_SPI_MOSI 54 | #define TP_SPI_MISO CONFIG_LV_DISP_SPI_MISO 55 | #define TP_SPI_CLK CONFIG_LV_DISP_SPI_CLK 56 | #define TP_SPI_CS CONFIG_LV_DISP_SPI_CS 57 | #else 58 | #define TP_SPI_MOSI CONFIG_LV_TOUCH_SPI_MOSI 59 | #define TP_SPI_MISO CONFIG_LV_TOUCH_SPI_MISO 60 | #define TP_SPI_CLK CONFIG_LV_TOUCH_SPI_CLK 61 | #define TP_SPI_CS CONFIG_LV_TOUCH_SPI_CS 62 | #endif 63 | #endif 64 | 65 | #define ENABLE_TOUCH_INPUT CONFIG_LV_ENABLE_TOUCH 66 | 67 | #if defined (CONFIG_LV_TFT_DISPLAY_SPI2_HOST) 68 | #define TFT_SPI_HOST SPI2_HOST 69 | #elif defined (CONFIG_LV_TFT_DISPLAY_SPI3_HOST) 70 | #define TFT_SPI_HOST SPI3_HOST 71 | #endif 72 | 73 | #if defined (CONFIG_LV_TFT_DISPLAY_SPI_HALF_DUPLEX) 74 | #define DISP_SPI_HALF_DUPLEX 75 | #else 76 | #define DISP_SPI_FULL_DUPLEX 77 | #endif 78 | 79 | #if defined (CONFIG_LV_TFT_DISPLAY_SPI_TRANS_MODE_DIO) 80 | #define DISP_SPI_TRANS_MODE_DIO 81 | #elif defined (CONFIG_LV_TFT_DISPLAY_SPI_TRANS_MODE_QIO) 82 | #define DISP_SPI_TRANS_MODE_QIO 83 | #else 84 | #define DISP_SPI_TRANS_MODE_SIO 85 | #endif 86 | 87 | #if defined (CONFIG_LV_TOUCH_CONTROLLER_SPI2_HOST) 88 | #define TOUCH_SPI_HOST SPI2_HOST 89 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_SPI3_HOST) 90 | #define TOUCH_SPI_HOST SPI3_HOST 91 | #endif 92 | 93 | /* Handle the FT81X Special case */ 94 | #if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) 95 | 96 | #if defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X) 97 | #define SHARED_SPI_BUS 98 | #else 99 | /* Empty */ 100 | #endif 101 | 102 | #else 103 | // Detect the use of a shared SPI Bus and verify the user specified the same SPI bus for both touch and tft 104 | #if defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI) && TP_SPI_MOSI == DISP_SPI_MOSI && TP_SPI_CLK == DISP_SPI_CLK 105 | #if TFT_SPI_HOST != TOUCH_SPI_HOST 106 | #error You must specify the same SPI host (SPIx_HOST) for both display and touch driver 107 | #endif 108 | 109 | #define SHARED_SPI_BUS 110 | #endif 111 | 112 | #endif 113 | 114 | /********************** 115 | * TYPEDEFS 116 | **********************/ 117 | #if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481) || \ 118 | defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488) 119 | 120 | #define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 3) 121 | 122 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341) || \ 123 | defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789) || \ 124 | defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S) || \ 125 | defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357) || \ 126 | defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107) || \ 127 | defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) || \ 128 | defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820) || \ 129 | defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A) || \ 130 | defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C) 131 | 132 | #define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 2) 133 | 134 | #else 135 | #define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 2) 136 | #endif 137 | 138 | #if defined (CONFIG_LV_TFT_USE_CUSTOM_SPI_CLK_DIVIDER) 139 | #define SPI_TFT_CLOCK_SPEED_HZ ((80 * 1000 * 1000) / CONFIG_LV_TFT_CUSTOM_SPI_CLK_DIVIDER) 140 | #else 141 | #if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789) 142 | #define SPI_TFT_CLOCK_SPEED_HZ (20*1000*1000) 143 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S) 144 | #define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000) 145 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357) 146 | #define SPI_TFT_CLOCK_SPEED_HZ (26*1000*1000) 147 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107) 148 | #define SPI_TFT_CLOCK_SPEED_HZ (8*1000*1000) 149 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481) 150 | #define SPI_TFT_CLOCK_SPEED_HZ (16*1000*1000) 151 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486) 152 | #define SPI_TFT_CLOCK_SPEED_HZ (20*1000*1000) 153 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488) 154 | #define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000) 155 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341) 156 | #define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000) 157 | #elif defined(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C) 158 | #define SPI_TFT_CLOCK_SPEED_HZ (40 * 1000 * 1000) 159 | #elif defined(CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) 160 | #define SPI_TFT_CLOCK_SPEED_HZ (32*1000*1000) 161 | #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544) 162 | #define SPI_TFT_CLOCK_SPEED_HZ (4*1000*1000) 163 | #else 164 | #define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000) 165 | #endif 166 | 167 | #endif 168 | 169 | 170 | #if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789) 171 | #define SPI_TFT_SPI_MODE (2) 172 | #else 173 | #define SPI_TFT_SPI_MODE (0) 174 | #endif 175 | 176 | /* Touch driver */ 177 | #if (CONFIG_LV_TOUCH_CONTROLLER == TOUCH_CONTROLLER_STMPE610) 178 | #define SPI_TOUCH_CLOCK_SPEED_HZ (1*1000*1000) 179 | #define SPI_TOUCH_SPI_MODE (1) 180 | #else 181 | #define SPI_TOUCH_CLOCK_SPEED_HZ (2*1000*1000) 182 | #define SPI_TOUCH_SPI_MODE (0) 183 | #endif 184 | 185 | /********************** 186 | * GLOBAL PROTOTYPES 187 | **********************/ 188 | 189 | 190 | /********************** 191 | * MACROS 192 | **********************/ 193 | 194 | 195 | #ifdef __cplusplus 196 | } /* extern "C" */ 197 | #endif 198 | 199 | #endif /*LVGL_SPI_CONF_H*/ 200 | -------------------------------------------------------------------------------- /lvgl_tft/FT81x.h: -------------------------------------------------------------------------------- 1 | #ifndef FT81X_H_ 2 | #define FT81X_H_ 3 | 4 | #include 5 | 6 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 7 | #include "lvgl.h" 8 | #else 9 | #include "lvgl/lvgl.h" 10 | #endif 11 | #include "../lvgl_helpers.h" 12 | 13 | void FT81x_init(void); 14 | 15 | void FT81x_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 16 | 17 | #endif /* FT81X_H_ */ 18 | -------------------------------------------------------------------------------- /lvgl_tft/GC9A01.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file GC9A01.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "GC9A01.h" 10 | #include "disp_spi.h" 11 | #include "driver/gpio.h" 12 | #include "esp_log.h" 13 | #include "freertos/FreeRTOS.h" 14 | #include "freertos/task.h" 15 | 16 | /********************* 17 | * DEFINES 18 | *********************/ 19 | #define TAG "GC9A01" 20 | 21 | /********************** 22 | * TYPEDEFS 23 | **********************/ 24 | 25 | /*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */ 26 | typedef struct { 27 | uint8_t cmd; 28 | uint8_t data[16]; 29 | uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds. 30 | } lcd_init_cmd_t; 31 | 32 | /********************** 33 | * STATIC PROTOTYPES 34 | **********************/ 35 | static void GC9A01_set_orientation(uint8_t orientation); 36 | 37 | static void GC9A01_send_cmd(uint8_t cmd); 38 | static void GC9A01_send_data(void * data, uint16_t length); 39 | static void GC9A01_send_color(void * data, uint16_t length); 40 | 41 | /********************** 42 | * STATIC VARIABLES 43 | **********************/ 44 | 45 | /********************** 46 | * MACROS 47 | **********************/ 48 | 49 | /********************** 50 | * GLOBAL FUNCTIONS 51 | **********************/ 52 | 53 | void GC9A01_init(void) 54 | { 55 | lcd_init_cmd_t GC_init_cmds[]={ 56 | //////////////////////////////////////////// 57 | {0xEF, {0}, 0}, 58 | {0xEB, {0x14}, 1}, 59 | 60 | {0xFE, {0}, 0}, 61 | {0xEF, {0}, 0}, 62 | 63 | {0xEB, {0x14}, 1}, 64 | {0x84, {0x40}, 1}, 65 | {0x85, {0xFF}, 1}, 66 | {0x86, {0xFF}, 1}, 67 | {0x87, {0xFF}, 1}, 68 | {0x88, {0x0A}, 1}, 69 | {0x89, {0x21}, 1}, 70 | {0x8A, {0x00}, 1}, 71 | {0x8B, {0x80}, 1}, 72 | {0x8C, {0x01}, 1}, 73 | {0x8D, {0x01}, 1}, 74 | {0x8E, {0xFF}, 1}, 75 | {0x8F, {0xFF}, 1}, 76 | {0xB6, {0x00, 0x20}, 2}, 77 | //call orientation 78 | {0x3A, {0x05}, 1}, 79 | {0x90, {0x08, 0x08, 0X08, 0X08}, 4}, 80 | {0xBD, {0x06}, 1}, 81 | {0xBC, {0x00}, 1}, 82 | {0xFF, {0x60, 0x01, 0x04}, 3}, 83 | {0xC3, {0x13}, 1}, 84 | {0xC4, {0x13}, 1}, 85 | {0xC9, {0x22}, 1}, 86 | {0xBE, {0x11}, 1}, 87 | {0xE1, {0x10, 0x0E}, 2}, 88 | {0xDF, {0x21, 0x0C, 0x02}, 3}, 89 | {0xF0, {0x45, 0x09, 0x08, 0x08, 0x26, 0x2A}, 6}, 90 | {0xF1, {0x43, 0x70, 0x72, 0x36, 0x37, 0x6F}, 6}, 91 | {0xF2, {0x45, 0x09, 0x08, 0x08, 0x26, 0x2A}, 6}, 92 | {0xF3, {0x43, 0x70, 0x72, 0x36, 0x37, 0x6F}, 6}, 93 | {0xED, {0x1B, 0x0B}, 2}, 94 | {0xAE, {0x77}, 1}, 95 | {0xCD, {0x63}, 1}, 96 | {0x70, {0x07, 0x07, 0x04, 0x0E, 0x0F, 0x09, 0x07, 0X08, 0x03}, 9}, 97 | {0xE8, {0x34}, 1}, 98 | {0x62, {0x18, 0x0D, 0x71, 0xED, 0x70, 0x70, 0x18, 0X0F, 0x71, 0xEF, 0x70, 0x70}, 12}, 99 | {0x63, {0x18, 0x11, 0x71, 0xF1, 0x70, 0x70, 0x18, 0X13, 0x71, 0xF3, 0x70, 0x70}, 12}, 100 | {0x64, {0x28, 0x29, 0xF1, 0x01, 0xF1, 0x00, 0x07}, 7}, 101 | {0x66, {0x3C, 0x00, 0xCD, 0x67, 0x45, 0x45, 0x10, 0X00, 0x00, 0x00}, 10}, 102 | {0x67, {0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x54, 0X10, 0x32, 0x98}, 10}, 103 | {0x74, {0x10, 0x85, 0x80, 0x00, 0x00, 0x4E, 0x00}, 7}, 104 | {0x98, {0x3E, 0x07}, 2}, 105 | {0x35, {0}, 0}, 106 | {0x21, {0}, 0}, 107 | {0x11, {0}, 0x80}, //0x80 delay flag 108 | {0x29, {0}, 0x80}, //0x80 delay flag 109 | {0, {0}, 0xff}, //init end flag 110 | //////////////////////////////////////////// 111 | 112 | }; 113 | 114 | //Initialize non-SPI GPIOs 115 | gpio_pad_select_gpio(GC9A01_DC); 116 | gpio_set_direction(GC9A01_DC, GPIO_MODE_OUTPUT); 117 | 118 | #if GC9A01_USE_RST 119 | gpio_pad_select_gpio(GC9A01_RST); 120 | gpio_set_direction(GC9A01_RST, GPIO_MODE_OUTPUT); 121 | 122 | //Reset the display 123 | gpio_set_level(GC9A01_RST, 0); 124 | vTaskDelay(100 / portTICK_RATE_MS); 125 | gpio_set_level(GC9A01_RST, 1); 126 | vTaskDelay(100 / portTICK_RATE_MS); 127 | #endif 128 | 129 | ESP_LOGI(TAG, "Initialization."); 130 | 131 | //Send all the commands 132 | uint16_t cmd = 0; 133 | while (GC_init_cmds[cmd].databytes!=0xff) { 134 | GC9A01_send_cmd(GC_init_cmds[cmd].cmd); 135 | GC9A01_send_data(GC_init_cmds[cmd].data, GC_init_cmds[cmd].databytes&0x1F); 136 | if (GC_init_cmds[cmd].databytes & 0x80) { 137 | vTaskDelay(100 / portTICK_RATE_MS); 138 | } 139 | cmd++; 140 | } 141 | 142 | GC9A01_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION); 143 | 144 | #if GC9A01_INVERT_COLORS == 1 145 | GC9A01_send_cmd(0x21); 146 | #else 147 | GC9A01_send_cmd(0x20); 148 | #endif 149 | } 150 | 151 | 152 | void GC9A01_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map) 153 | { 154 | uint8_t data[4]; 155 | 156 | /*Column addresses*/ 157 | GC9A01_send_cmd(0x2A); //0x2A 158 | data[0] = (area->x1 >> 8) & 0xFF; 159 | data[1] = area->x1 & 0xFF; 160 | data[2] = (area->x2 >> 8) & 0xFF; 161 | data[3] = area->x2 & 0xFF; 162 | GC9A01_send_data(data, 4); 163 | 164 | /*Page addresses*/ 165 | GC9A01_send_cmd(0x2B); //0x2B 166 | data[0] = (area->y1 >> 8) & 0xFF; 167 | data[1] = area->y1 & 0xFF; 168 | data[2] = (area->y2 >> 8) & 0xFF; 169 | data[3] = area->y2 & 0xFF; 170 | GC9A01_send_data(data, 4); 171 | 172 | /*Memory write*/ 173 | GC9A01_send_cmd(0x2C); //0x2C 174 | 175 | 176 | uint32_t size = lv_area_get_width(area) * lv_area_get_height(area); 177 | 178 | GC9A01_send_color((void*)color_map, size * 2); 179 | } 180 | 181 | void GC9A01_sleep_in() 182 | { 183 | uint8_t data[] = {0x08}; 184 | GC9A01_send_cmd(0x10); //0x10 Enter Sleep Mode 185 | GC9A01_send_data(&data, 1); 186 | } 187 | 188 | void GC9A01_sleep_out() 189 | { 190 | uint8_t data[] = {0x08}; 191 | GC9A01_send_cmd(0x11); //0x11 Sleep OUT 192 | GC9A01_send_data(&data, 1); 193 | } 194 | 195 | /********************** 196 | * STATIC FUNCTIONS 197 | **********************/ 198 | 199 | 200 | static void GC9A01_send_cmd(uint8_t cmd) 201 | { 202 | disp_wait_for_pending_transactions(); 203 | gpio_set_level(GC9A01_DC, 0); /*Command mode*/ 204 | disp_spi_send_data(&cmd, 1); 205 | } 206 | 207 | static void GC9A01_send_data(void * data, uint16_t length) 208 | { 209 | disp_wait_for_pending_transactions(); 210 | gpio_set_level(GC9A01_DC, 1); /*Data mode*/ 211 | disp_spi_send_data(data, length); 212 | } 213 | 214 | static void GC9A01_send_color(void * data, uint16_t length) 215 | { 216 | disp_wait_for_pending_transactions(); 217 | gpio_set_level(GC9A01_DC, 1); /*Data mode*/ 218 | disp_spi_send_colors(data, length); 219 | } 220 | 221 | static void GC9A01_set_orientation(uint8_t orientation) 222 | { 223 | // ESP_ASSERT(orientation < 4); 224 | 225 | const char *orientation_str[] = { 226 | "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED" 227 | }; 228 | 229 | ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); 230 | 231 | #if defined CONFIG_LV_PREDEFINED_DISPLAY_M5STACK 232 | uint8_t data[] = {0x68, 0x68, 0x08, 0x08}; /// 233 | #elif defined (CONFIG_LV_PREDEFINED_DISPLAY_WROVER4) 234 | uint8_t data[] = {0x4C, 0x88, 0x28, 0xE8}; /// 235 | #elif defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE) 236 | uint8_t data[] = {0x08, 0xC8, 0x68, 0xA8}; ///ggggg 237 | #endif 238 | 239 | ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]); 240 | 241 | GC9A01_send_cmd(0x36); 242 | GC9A01_send_data((void *) &data[orientation], 1); 243 | } 244 | -------------------------------------------------------------------------------- /lvgl_tft/GC9A01.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_templ.h 3 | * 4 | */ 5 | 6 | #ifndef GC9A01_H 7 | #define GC9A01_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #include 17 | 18 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 19 | #include "lvgl.h" 20 | #else 21 | #include "lvgl/lvgl.h" 22 | #endif 23 | #include "../lvgl_helpers.h" 24 | 25 | /********************* 26 | * DEFINES 27 | *********************/ 28 | #define GC9A01_DC CONFIG_LV_DISP_PIN_DC 29 | #define GC9A01_RST CONFIG_LV_DISP_PIN_RST 30 | #define GC9A01_USE_RST CONFIG_LV_DISP_USE_RST 31 | #define GC9A01_INVERT_COLORS CONFIG_LV_INVERT_COLORS 32 | 33 | /********************** 34 | * TYPEDEFS 35 | **********************/ 36 | 37 | /********************** 38 | * GLOBAL PROTOTYPES 39 | **********************/ 40 | 41 | void GC9A01_init(void); 42 | void GC9A01_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 43 | void GC9A01_sleep_in(void); 44 | void GC9A01_sleep_out(void); 45 | 46 | /********************** 47 | * MACROS 48 | **********************/ 49 | 50 | 51 | #ifdef __cplusplus 52 | } /* extern "C" */ 53 | #endif 54 | 55 | #endif /*GC9A01_H*/ 56 | -------------------------------------------------------------------------------- /lvgl_tft/disp_driver.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file disp_driver.c 3 | */ 4 | 5 | #include "disp_driver.h" 6 | #include "disp_spi.h" 7 | #include "esp_lcd_backlight.h" 8 | #include "sdkconfig.h" 9 | 10 | void *disp_driver_init(void) 11 | { 12 | #if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341 13 | ili9341_init(); 14 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481 15 | ili9481_init(); 16 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488 17 | ili9488_init(); 18 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789 19 | st7789_init(); 20 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S 21 | st7796s_init(); 22 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S 23 | st7735s_init(); 24 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357 25 | hx8357_init(); 26 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486 27 | ili9486_init(); 28 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107 29 | sh1107_init(); 30 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306 31 | ssd1306_init(); 32 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X 33 | FT81x_init(); 34 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820 35 | il3820_init(); 36 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875 37 | ra8875_init(); 38 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01 39 | GC9A01_init(); 40 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A 41 | jd79653a_init(); 42 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D 43 | uc8151d_init(); 44 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C 45 | ili9163c_init(); 46 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544 47 | pcd8544_init(); 48 | #endif 49 | 50 | // We still use menuconfig for these settings 51 | // It will be set up during runtime in the future 52 | #if (defined(CONFIG_LV_DISP_BACKLIGHT_SWITCH) || defined(CONFIG_LV_DISP_BACKLIGHT_PWM)) 53 | const disp_backlight_config_t bckl_config = { 54 | .gpio_num = CONFIG_LV_DISP_PIN_BCKL, 55 | #if defined CONFIG_LV_DISP_BACKLIGHT_PWM 56 | .pwm_control = true, 57 | #else 58 | .pwm_control = false, 59 | #endif 60 | #if defined CONFIG_LV_BACKLIGHT_ACTIVE_LVL 61 | .output_invert = false, // Backlight on high 62 | #else 63 | .output_invert = true, // Backlight on low 64 | #endif 65 | .timer_idx = 0, 66 | .channel_idx = 0 // @todo this prevents us from having two PWM controlled displays 67 | }; 68 | disp_backlight_h bckl_handle = disp_backlight_new(&bckl_config); 69 | disp_backlight_set(bckl_handle, 100); 70 | return bckl_handle; 71 | #else 72 | return NULL; 73 | #endif 74 | } 75 | 76 | void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map) 77 | { 78 | #if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341 79 | ili9341_flush(drv, area, color_map); 80 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481 81 | ili9481_flush(drv, area, color_map); 82 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488 83 | ili9488_flush(drv, area, color_map); 84 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789 85 | st7789_flush(drv, area, color_map); 86 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S 87 | st7796s_flush(drv, area, color_map); 88 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S 89 | st7735s_flush(drv, area, color_map); 90 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357 91 | hx8357_flush(drv, area, color_map); 92 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486 93 | ili9486_flush(drv, area, color_map); 94 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107 95 | sh1107_flush(drv, area, color_map); 96 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306 97 | ssd1306_flush(drv, area, color_map); 98 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X 99 | FT81x_flush(drv, area, color_map); 100 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820 101 | il3820_flush(drv, area, color_map); 102 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875 103 | ra8875_flush(drv, area, color_map); 104 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01 105 | GC9A01_flush(drv, area, color_map); 106 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A 107 | jd79653a_lv_fb_flush(drv, area, color_map); 108 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D 109 | uc8151d_lv_fb_flush(drv, area, color_map); 110 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C 111 | ili9163c_flush(drv, area, color_map); 112 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544 113 | pcd8544_flush(drv, area, color_map); 114 | #endif 115 | } 116 | 117 | void disp_driver_rounder(lv_disp_drv_t * disp_drv, lv_area_t * area) 118 | { 119 | #if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306 120 | ssd1306_rounder(disp_drv, area); 121 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107 122 | sh1107_rounder(disp_drv, area); 123 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820 124 | il3820_rounder(disp_drv, area); 125 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A 126 | jd79653a_lv_rounder_cb(disp_drv, area); 127 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D 128 | uc8151d_lv_rounder_cb(disp_drv, area); 129 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544 130 | pcd8544_rounder(disp_drv, area); 131 | #endif 132 | } 133 | 134 | void disp_driver_set_px(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, 135 | lv_color_t color, lv_opa_t opa) 136 | { 137 | #if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306 138 | ssd1306_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa); 139 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107 140 | sh1107_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa); 141 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820 142 | il3820_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa); 143 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A 144 | jd79653a_lv_set_fb_cb(disp_drv, buf, buf_w, x, y, color, opa); 145 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D 146 | uc8151d_lv_set_fb_cb(disp_drv, buf, buf_w, x, y, color, opa); 147 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544 148 | pcd8544_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa); 149 | #endif 150 | } 151 | -------------------------------------------------------------------------------- /lvgl_tft/disp_driver.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file disp_driver.h 3 | */ 4 | 5 | #ifndef DISP_DRIVER_H 6 | #define DISP_DRIVER_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /********************* 13 | * INCLUDES 14 | *********************/ 15 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 16 | #include "lvgl.h" 17 | #else 18 | #include "lvgl/lvgl.h" 19 | #endif 20 | 21 | #if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341 22 | #include "ili9341.h" 23 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481 24 | #include "ili9481.h" 25 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488 26 | #include "ili9488.h" 27 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789 28 | #include "st7789.h" 29 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S 30 | #include "st7796s.h" 31 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S 32 | #include "st7735s.h" 33 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357 34 | #include "hx8357.h" 35 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486 36 | #include "ili9486.h" 37 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107 38 | #include "sh1107.h" 39 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306 40 | #include "ssd1306.h" 41 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X 42 | #include "FT81x.h" 43 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820 44 | #include "il3820.h" 45 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875 46 | #include "ra8875.h" 47 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01 48 | #include "GC9A01.h" 49 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A 50 | #include "jd79653a.h" 51 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D 52 | #include "uc8151d.h" 53 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C 54 | #include "ili9163c.h" 55 | #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544 56 | #include "pcd8544.h" 57 | #endif 58 | 59 | /********************* 60 | * DEFINES 61 | *********************/ 62 | 63 | /********************** 64 | * TYPEDEFS 65 | **********************/ 66 | 67 | /********************** 68 | * GLOBAL PROTOTYPES 69 | **********************/ 70 | 71 | /* Initialize display */ 72 | void *disp_driver_init(void); 73 | 74 | /* Display flush callback */ 75 | void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 76 | 77 | /* Display rounder callback, used with monochrome dispays */ 78 | void disp_driver_rounder(lv_disp_drv_t * disp_drv, lv_area_t * area); 79 | 80 | /* Display set_px callback, used with monochrome dispays */ 81 | void disp_driver_set_px(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, 82 | lv_color_t color, lv_opa_t opa); 83 | 84 | /********************** 85 | * MACROS 86 | **********************/ 87 | 88 | #ifdef __cplusplus 89 | } /* extern "C" */ 90 | #endif 91 | 92 | #endif /*DISP_DRIVER_H*/ 93 | -------------------------------------------------------------------------------- /lvgl_tft/disp_spi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file disp_spi.h 3 | * 4 | */ 5 | 6 | #ifndef DISP_SPI_H 7 | #define DISP_SPI_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #include 17 | #include 18 | #include 19 | 20 | /********************* 21 | * DEFINES 22 | *********************/ 23 | 24 | /********************** 25 | * TYPEDEFS 26 | **********************/ 27 | typedef enum _disp_spi_send_flag_t { 28 | DISP_SPI_SEND_QUEUED = 0x00000000, 29 | DISP_SPI_SEND_POLLING = 0x00000001, 30 | DISP_SPI_SEND_SYNCHRONOUS = 0x00000002, 31 | DISP_SPI_SIGNAL_FLUSH = 0x00000004, 32 | DISP_SPI_RECEIVE = 0x00000008, 33 | DISP_SPI_CMD_8 = 0x00000010, /* Reserved */ 34 | DISP_SPI_CMD_16 = 0x00000020, /* Reserved */ 35 | DISP_SPI_ADDRESS_8 = 0x00000040, 36 | DISP_SPI_ADDRESS_16 = 0x00000080, 37 | DISP_SPI_ADDRESS_24 = 0x00000100, 38 | DISP_SPI_ADDRESS_32 = 0x00000200, 39 | DISP_SPI_MODE_DIO = 0x00000400, 40 | DISP_SPI_MODE_QIO = 0x00000800, 41 | DISP_SPI_MODE_DIOQIO_ADDR = 0x00001000, 42 | DISP_SPI_VARIABLE_DUMMY = 0x00002000, 43 | } disp_spi_send_flag_t; 44 | 45 | 46 | /********************** 47 | * GLOBAL PROTOTYPES 48 | **********************/ 49 | void disp_spi_add_device(spi_host_device_t host); 50 | void disp_spi_add_device_config(spi_host_device_t host, spi_device_interface_config_t *devcfg); 51 | void disp_spi_add_device_with_speed(spi_host_device_t host, int clock_speed_hz); 52 | void disp_spi_change_device_speed(int clock_speed_hz); 53 | void disp_spi_remove_device(); 54 | 55 | /* Important! 56 | All buffers should also be 32-bit aligned and DMA capable to prevent extra allocations and copying. 57 | When DMA reading (even in polling mode) the ESP32 always read in 4-byte chunks even if less is requested. 58 | Extra space will be zero filled. Always ensure the out buffer is large enough to hold at least 4 bytes! 59 | */ 60 | void disp_spi_transaction(const uint8_t *data, size_t length, 61 | disp_spi_send_flag_t flags, uint8_t *out, uint64_t addr, uint8_t dummy_bits); 62 | 63 | void disp_wait_for_pending_transactions(void); 64 | void disp_spi_acquire(void); 65 | void disp_spi_release(void); 66 | 67 | static inline void disp_spi_send_data(uint8_t *data, size_t length) { 68 | disp_spi_transaction(data, length, DISP_SPI_SEND_POLLING, NULL, 0, 0); 69 | } 70 | 71 | static inline void disp_spi_send_colors(uint8_t *data, size_t length) { 72 | disp_spi_transaction(data, length, 73 | DISP_SPI_SEND_QUEUED | DISP_SPI_SIGNAL_FLUSH, 74 | NULL, 0, 0); 75 | } 76 | 77 | #ifdef __cplusplus 78 | } /* extern "C" */ 79 | #endif 80 | 81 | #endif /*DISP_SPI_H*/ 82 | -------------------------------------------------------------------------------- /lvgl_tft/esp_lcd_backlight.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file esp_lcd_backlight.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "esp_lcd_backlight.h" 10 | #include "driver/ledc.h" 11 | #include "driver/gpio.h" 12 | #include "esp_log.h" 13 | #include "soc/ledc_periph.h" // to invert LEDC output on IDF version < v4.3 14 | 15 | typedef struct { 16 | bool pwm_control; // true: LEDC is used, false: GPIO is used 17 | int index; // Either GPIO or LEDC channel 18 | } disp_backlight_t; 19 | 20 | static const char *TAG = "disp_backlight"; 21 | 22 | disp_backlight_h disp_backlight_new(const disp_backlight_config_t *config) 23 | { 24 | // Check input parameters 25 | if (config == NULL) 26 | return NULL; 27 | if (!GPIO_IS_VALID_OUTPUT_GPIO(config->gpio_num)) { 28 | ESP_LOGW(TAG, "Invalid GPIO number"); 29 | return NULL; 30 | } 31 | disp_backlight_t *bckl_dev = calloc(1, sizeof(disp_backlight_t)); 32 | if (bckl_dev == NULL){ 33 | ESP_LOGW(TAG, "Not enough memory"); 34 | return NULL; 35 | } 36 | 37 | if (config->pwm_control){ 38 | // Configure LED (Backlight) pin as PWM for Brightness control. 39 | bckl_dev->pwm_control = true; 40 | bckl_dev->index = config->channel_idx; 41 | const ledc_channel_config_t LCD_backlight_channel = { 42 | .gpio_num = config->gpio_num, 43 | .speed_mode = LEDC_LOW_SPEED_MODE, 44 | .channel = config->channel_idx, 45 | .intr_type = LEDC_INTR_DISABLE, 46 | .timer_sel = config->timer_idx, 47 | .duty = 0, 48 | .hpoint = 0 49 | }; 50 | const ledc_timer_config_t LCD_backlight_timer = { 51 | .speed_mode = LEDC_LOW_SPEED_MODE, 52 | .bit_num = LEDC_TIMER_10_BIT, 53 | .timer_num = config->timer_idx, 54 | .freq_hz = 5000, 55 | .clk_cfg = LEDC_AUTO_CLK}; 56 | 57 | ESP_ERROR_CHECK(ledc_timer_config(&LCD_backlight_timer)); 58 | ESP_ERROR_CHECK(ledc_channel_config(&LCD_backlight_channel)); 59 | gpio_matrix_out(config->gpio_num, ledc_periph_signal[LEDC_LOW_SPEED_MODE].sig_out0_idx + config->channel_idx, config->output_invert, 0); 60 | } 61 | else 62 | { 63 | // Configure GPIO for output 64 | bckl_dev->index = config->gpio_num; 65 | gpio_pad_select_gpio(config->gpio_num); 66 | ESP_ERROR_CHECK(gpio_set_direction(config->gpio_num, GPIO_MODE_OUTPUT)); 67 | gpio_matrix_out(config->gpio_num, SIG_GPIO_OUT_IDX, config->output_invert, false); 68 | } 69 | 70 | return (disp_backlight_h)bckl_dev; 71 | } 72 | 73 | void disp_backlight_set(disp_backlight_h bckl, int brightness_percent) 74 | { 75 | // Check input paramters 76 | if (bckl == NULL) 77 | return; 78 | if (brightness_percent > 100) 79 | brightness_percent = 100; 80 | if (brightness_percent < 0) 81 | brightness_percent = 0; 82 | 83 | disp_backlight_t *bckl_dev = (disp_backlight_t *) bckl; 84 | ESP_LOGI(TAG, "Setting LCD backlight: %d%%", brightness_percent); 85 | 86 | if (bckl_dev->pwm_control) { 87 | uint32_t duty_cycle = (1023 * brightness_percent) / 100; // LEDC resolution set to 10bits, thus: 100% = 1023 88 | ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, bckl_dev->index, duty_cycle)); 89 | ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, bckl_dev->index)); 90 | } else { 91 | ESP_ERROR_CHECK(gpio_set_level(bckl_dev->index, brightness_percent)); 92 | } 93 | } 94 | 95 | void disp_backlight_delete(disp_backlight_h bckl) 96 | { 97 | if (bckl == NULL) 98 | return; 99 | 100 | disp_backlight_t *bckl_dev = (disp_backlight_t *) bckl; 101 | if (bckl_dev->pwm_control) { 102 | ledc_stop(LEDC_LOW_SPEED_MODE, bckl_dev->index, 0); 103 | } else { 104 | gpio_reset_pin(bckl_dev->index); 105 | } 106 | free (bckl); 107 | } 108 | -------------------------------------------------------------------------------- /lvgl_tft/esp_lcd_backlight.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file esp_lcd_backlight.h 3 | */ 4 | 5 | #ifndef ESP_LCD_BACKLIGHT_H 6 | #define ESP_LCD_BACKLIGHT_H 7 | 8 | /********************* 9 | * INCLUDES 10 | *********************/ 11 | #include 12 | 13 | #ifdef __cplusplus 14 | extern "C" { /* extern "C" */ 15 | #endif 16 | 17 | /********************** 18 | * GLOBAL PROTOTYPES 19 | **********************/ 20 | 21 | /** 22 | * @brief Display backlight controller handle 23 | * 24 | */ 25 | typedef void * disp_backlight_h; 26 | 27 | /** 28 | * @brief Configuration structure of backlight controller 29 | * 30 | * Must be passed to disp_backlight_new() for correct configuration 31 | */ 32 | typedef struct { 33 | bool pwm_control; 34 | bool output_invert; 35 | int gpio_num; // see gpio_num_t 36 | 37 | // Relevant only for PWM controlled backlight 38 | // Ignored for switch (ON/OFF) backlight control 39 | int timer_idx; // ledc_timer_t 40 | int channel_idx; // ledc_channel_t 41 | } disp_backlight_config_t; 42 | 43 | /** 44 | * @brief Create new backlight controller 45 | * 46 | * @param[in] config Configuration structure of backlight controller 47 | * @return Display backlight controller handle 48 | */ 49 | disp_backlight_h disp_backlight_new(const disp_backlight_config_t *config); 50 | 51 | /** 52 | * @brief Set backlight 53 | * 54 | * Brightness parameter can be 0-100 for PWM controlled backlight. 55 | * GPIO controlled backlight (ON/OFF) is turned off witch value 0 and turned on with any positive value. 56 | * 57 | * @param bckl Backlight controller handle 58 | * @param[in] brightness_percent Brightness in [%] 59 | */ 60 | void disp_backlight_set(disp_backlight_h bckl, int brightness_percent); 61 | void disp_backlight_delete(disp_backlight_h bckl); 62 | 63 | #ifdef __cplusplus 64 | } /* extern "C" */ 65 | #endif 66 | 67 | #endif /*ESP_LCD_BACKLIGHT_H*/ 68 | -------------------------------------------------------------------------------- /lvgl_tft/hx8357.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file HX8357.h 3 | * 4 | * Roughly based on the Adafruit_HX8357_Library 5 | * 6 | * This library should work with: 7 | * Adafruit 3.5" TFT 320x480 + Touchscreen Breakout 8 | * http://www.adafruit.com/products/2050 9 | * 10 | * Adafruit TFT FeatherWing - 3.5" 480x320 Touchscreen for Feathers 11 | * https://www.adafruit.com/product/3651 12 | * 13 | */ 14 | 15 | #ifndef HX8357_H 16 | #define HX8357_H 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | /********************* 23 | * INCLUDES 24 | *********************/ 25 | #include 26 | #include 27 | 28 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 29 | #include "lvgl.h" 30 | #else 31 | #include "lvgl/lvgl.h" 32 | #endif 33 | #include "../lvgl_helpers.h" 34 | 35 | /********************* 36 | * DEFINES 37 | *********************/ 38 | #define HX8357_DC CONFIG_LV_DISP_PIN_DC 39 | #define HX8357_RST CONFIG_LV_DISP_PIN_RST 40 | #define HX8357_USE_RST CONFIG_LV_DISP_USE_RST 41 | #define HX8357_INVERT_COLORS CONFIG_LV_INVERT_COLORS 42 | 43 | 44 | /******************* 45 | * HX8357B/D REGS 46 | *********************/ 47 | #define HX8357D 0xD ///< Our internal const for D type 48 | #define HX8357B 0xB ///< Our internal const for B type 49 | 50 | #define HX8357_TFTWIDTH 320 ///< 320 pixels wide 51 | #define HX8357_TFTHEIGHT 480 ///< 480 pixels tall 52 | 53 | #define HX8357_NOP 0x00 ///< No op 54 | #define HX8357_SWRESET 0x01 ///< software reset 55 | #define HX8357_RDDID 0x04 ///< Read ID 56 | #define HX8357_RDDST 0x09 ///< (unknown) 57 | 58 | #define HX8357_RDPOWMODE 0x0A ///< Read power mode Read power mode 59 | #define HX8357_RDMADCTL 0x0B ///< Read MADCTL 60 | #define HX8357_RDCOLMOD 0x0C ///< Column entry mode 61 | #define HX8357_RDDIM 0x0D ///< Read display image mode 62 | #define HX8357_RDDSDR 0x0F ///< Read dosplay signal mode 63 | 64 | #define HX8357_SLPIN 0x10 ///< Enter sleep mode 65 | #define HX8357_SLPOUT 0x11 ///< Exit sleep mode 66 | #define HX8357B_PTLON 0x12 ///< Partial mode on 67 | #define HX8357B_NORON 0x13 ///< Normal mode 68 | 69 | #define HX8357_INVOFF 0x20 ///< Turn off invert 70 | #define HX8357_INVON 0x21 ///< Turn on invert 71 | #define HX8357_DISPOFF 0x28 ///< Display on 72 | #define HX8357_DISPON 0x29 ///< Display off 73 | 74 | #define HX8357_CASET 0x2A ///< Column addr set 75 | #define HX8357_PASET 0x2B ///< Page addr set 76 | #define HX8357_RAMWR 0x2C ///< Write VRAM 77 | #define HX8357_RAMRD 0x2E ///< Read VRAm 78 | 79 | #define HX8357B_PTLAR 0x30 ///< (unknown) 80 | #define HX8357_TEON 0x35 ///< Tear enable on 81 | #define HX8357_TEARLINE 0x44 ///< (unknown) 82 | #define HX8357_MADCTL 0x36 ///< Memory access control 83 | #define HX8357_COLMOD 0x3A ///< Color mode 84 | 85 | #define HX8357_SETOSC 0xB0 ///< Set oscillator 86 | #define HX8357_SETPWR1 0xB1 ///< Set power control 87 | #define HX8357B_SETDISPLAY 0xB2 ///< Set display mode 88 | #define HX8357_SETRGB 0xB3 ///< Set RGB interface 89 | #define HX8357D_SETCOM 0xB6 ///< Set VCOM voltage 90 | 91 | #define HX8357B_SETDISPMODE 0xB4 ///< Set display mode 92 | #define HX8357D_SETCYC 0xB4 ///< Set display cycle reg 93 | #define HX8357B_SETOTP 0xB7 ///< Set OTP memory 94 | #define HX8357D_SETC 0xB9 ///< Enable extension command 95 | 96 | #define HX8357B_SET_PANEL_DRIVING 0xC0 ///< Set panel drive mode 97 | #define HX8357D_SETSTBA 0xC0 ///< Set source option 98 | #define HX8357B_SETDGC 0xC1 ///< Set DGC settings 99 | #define HX8357B_SETID 0xC3 ///< Set ID 100 | #define HX8357B_SETDDB 0xC4 ///< Set DDB 101 | #define HX8357B_SETDISPLAYFRAME 0xC5 ///< Set display frame 102 | #define HX8357B_GAMMASET 0xC8 ///< Set Gamma correction 103 | #define HX8357B_SETCABC 0xC9 ///< Set CABC 104 | #define HX8357_SETPANEL 0xCC ///< Set Panel 105 | 106 | #define HX8357B_SETPOWER 0xD0 ///< Set power control 107 | #define HX8357B_SETVCOM 0xD1 ///< Set VCOM 108 | #define HX8357B_SETPWRNORMAL 0xD2 ///< Set power normal 109 | 110 | #define HX8357B_RDID1 0xDA ///< Read ID #1 111 | #define HX8357B_RDID2 0xDB ///< Read ID #2 112 | #define HX8357B_RDID3 0xDC ///< Read ID #3 113 | #define HX8357B_RDID4 0xDD ///< Read ID #4 114 | 115 | #define HX8357D_SETGAMMA 0xE0 ///< Set Gamma 116 | 117 | #define HX8357B_SETGAMMA 0xC8 ///< Set Gamma 118 | #define HX8357B_SETPANELRELATED 0xE9 ///< Set panel related 119 | 120 | /********************** 121 | * TYPEDEFS 122 | **********************/ 123 | 124 | /********************** 125 | * GLOBAL PROTOTYPES 126 | **********************/ 127 | 128 | void hx8357_init(void); 129 | void hx8357_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 130 | void hx8357_set_rotation(uint8_t r); 131 | 132 | /********************** 133 | * MACROS 134 | **********************/ 135 | 136 | #ifdef __cplusplus 137 | } /* extern "C" */ 138 | #endif 139 | 140 | #endif /*HX8357_H*/ 141 | -------------------------------------------------------------------------------- /lvgl_tft/il3820.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file il3820.h 3 | * 4 | */ 5 | 6 | #ifndef IL3820_H 7 | #define IL3820_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" 11 | { 12 | #endif 13 | 14 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 15 | #include "lvgl.h" 16 | #else 17 | #include "lvgl/lvgl.h" 18 | #endif 19 | #include "sdkconfig.h" 20 | 21 | /* Values for Waveshare 2.9inch e-Paper Module, this values shouldn't be 22 | * swapped to change display orientation */ 23 | #define EPD_PANEL_WIDTH LV_HOR_RES_MAX /* 128 */ 24 | #define EPD_PANEL_HEIGHT LV_VER_RES_MAX /* 296 */ 25 | 26 | /* 128 = panel width */ 27 | #define IL3820_COLUMNS (EPD_PANEL_WIDTH / 8) 28 | 29 | #define IL3820_DC_PIN CONFIG_LV_DISP_PIN_DC 30 | #define IL3820_RST_PIN CONFIG_LV_DISP_PIN_RST 31 | #define IL3820_USE_RST CONFIG_LV_DISP_USE_RST 32 | #define IL3820_BUSY_PIN CONFIG_LV_DISP_PIN_BUSY 33 | #define IL3820_BUSY_LEVEL 1 34 | 35 | /* IL3820 commands */ 36 | #define IL3820_CMD_GDO_CTRL 0x01 37 | #define IL3820_CMD_GDV_CTRL 0x03 38 | #define IL3820_CMD_SDV_CTRL 0x04 39 | #define IL3820_CMD_SOFTSTART 0x0c 40 | #define IL3820_CMD_GSCAN_START 0x0f 41 | #define IL3820_CMD_SLEEP_MODE 0x10 42 | #define IL3820_CMD_ENTRY_MODE 0x11 43 | #define IL3820_CMD_SW_RESET 0x12 44 | #define IL3820_CMD_TSENS_CTRL 0x1a 45 | #define IL3820_CMD_MASTER_ACTIVATION 0x20 46 | #define IL3820_CMD_UPDATE_CTRL1 0x21 47 | #define IL3820_CMD_UPDATE_CTRL2 0x22 48 | #define IL3820_CMD_WRITE_RAM 0x24 49 | #define IL3820_CMD_WRITE_RED_RAM 0x26 50 | #define IL3820_CMD_VCOM_SENSE 0x28 51 | #define IL3820_CMD_VCOM_SENSE_DURATON 0x29 52 | #define IL3820_CMD_PRGM_VCOM_OTP 0x2a 53 | #define IL3820_CMD_VCOM_VOLTAGE 0x2c 54 | #define IL3820_CMD_PRGM_WS_OTP 0x30 55 | #define IL3820_CMD_UPDATE_LUT 0x32 56 | #define IL3820_CMD_PRGM_OTP_SELECTION 0x36 57 | #define IL3820_CMD_OTP_SELECTION_CTRL 0x37 58 | #define IL3820_CMD_DUMMY_LINE 0x3a 59 | #define IL3820_CMD_GATE_LINE_WIDTH 0x3b 60 | #define IL3820_CMD_BWF_CTRL 0x3c 61 | #define IL3820_CMD_RAM_XPOS_CTRL 0x44 62 | #define IL3820_CMD_RAM_YPOS_CTRL 0x45 63 | #define IL3820_CMD_RAM_XPOS_CNTR 0x4e 64 | #define IL3820_CMD_RAM_YPOS_CNTR 0x4f 65 | #define IL3820_CMD_TERMINATE_FRAME_RW 0xff 66 | 67 | /* Data entry sequence modes */ 68 | #define IL3820_DATA_ENTRY_MASK 0x07 69 | #define IL3820_DATA_ENTRY_XDYDX 0x00 70 | #define IL3820_DATA_ENTRY_XIYDX 0x01 71 | #define IL3820_DATA_ENTRY_XDYIX 0x02 72 | #define IL3820_DATA_ENTRY_XIYIX 0x03 73 | #define IL3820_DATA_ENTRY_XDYDY 0x04 74 | #define IL3820_DATA_ENTRY_XIYDY 0x05 75 | #define IL3820_DATA_ENTRY_XDYIY 0x06 76 | #define IL3820_DATA_ENTRY_XIYIY 0x07 77 | 78 | /* Options for display update */ 79 | #define IL3820_CTRL1_INITIAL_UPDATE_LL 0x00 80 | #define IL3820_CTRL1_INITIAL_UPDATE_LH 0x01 81 | #define IL3820_CTRL1_INITIAL_UPDATE_HL 0x02 82 | #define IL3820_CTRL1_INITIAL_UPDATE_HH 0x03 83 | 84 | /* Options for display update sequence */ 85 | #define IL3820_CTRL2_ENABLE_CLK 0x80 86 | #define IL3820_CTRL2_ENABLE_ANALOG 0x40 87 | #define IL3820_CTRL2_TO_INITIAL 0x08 88 | #define IL3820_CTRL2_TO_PATTERN 0x04 89 | #define IL3820_CTRL2_DISABLE_ANALOG 0x02 90 | #define IL3820_CTRL2_DISABLE_CLK 0x01 91 | 92 | #define IL3820_SLEEP_MODE_DSM 0x01 93 | #define IL3820_SLEEP_MODE_PON 0x00 94 | 95 | /* time constants in ms */ 96 | #define IL3820_RESET_DELAY 20 97 | #define IL3820_BUSY_DELAY 1 98 | // normal wait time max 200ms 99 | #define IL3820_WAIT 20 100 | 101 | void il3820_init(void); 102 | void il3820_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); 103 | void il3820_fullflush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); 104 | void il3820_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area); 105 | void il3820_set_px_cb(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); 106 | void il3820_sleep_in(void); 107 | 108 | #ifdef __cplusplus 109 | } /* extern "C" */ 110 | #endif 111 | 112 | 113 | #endif /* __IL3820_REGS_H__ */ 114 | 115 | -------------------------------------------------------------------------------- /lvgl_tft/ili9163c.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_templ.h 3 | * 4 | */ 5 | 6 | #ifndef ILI9163C_H 7 | #define ILI9163C_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" 11 | { 12 | #endif 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include 18 | 19 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 20 | #include "lvgl.h" 21 | #else 22 | #include "lvgl/lvgl.h" 23 | #endif 24 | #include "../lvgl_helpers.h" 25 | 26 | /********************* 27 | * DEFINES 28 | *********************/ 29 | #define ILI9163C_DC CONFIG_LV_DISP_PIN_DC 30 | #define ILI9163C_RST CONFIG_LV_DISP_PIN_RST 31 | #define ILI9163C_INVERT_COLORS CONFIG_LV_INVERT_COLORS 32 | 33 | /********************** 34 | * TYPEDEFS 35 | **********************/ 36 | 37 | /********************** 38 | * GLOBAL PROTOTYPES 39 | **********************/ 40 | 41 | void ili9163c_init(void); 42 | void ili9163c_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); 43 | void ili9163c_sleep_in(void); 44 | void ili9163c_sleep_out(void); 45 | 46 | /********************** 47 | * MACROS 48 | **********************/ 49 | 50 | #ifdef __cplusplus 51 | } /* extern "C" */ 52 | #endif 53 | 54 | #endif /*ILI9163C_H*/ 55 | -------------------------------------------------------------------------------- /lvgl_tft/ili9341.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ili9341.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "ili9341.h" 10 | #include "disp_spi.h" 11 | #include "driver/gpio.h" 12 | #include "esp_log.h" 13 | #include "freertos/FreeRTOS.h" 14 | #include "freertos/task.h" 15 | 16 | /********************* 17 | * DEFINES 18 | *********************/ 19 | #define TAG "ILI9341" 20 | 21 | /********************** 22 | * TYPEDEFS 23 | **********************/ 24 | 25 | /*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */ 26 | typedef struct { 27 | uint8_t cmd; 28 | uint8_t data[16]; 29 | uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds. 30 | } lcd_init_cmd_t; 31 | 32 | /********************** 33 | * STATIC PROTOTYPES 34 | **********************/ 35 | static void ili9341_set_orientation(uint8_t orientation); 36 | 37 | static void ili9341_send_cmd(uint8_t cmd); 38 | static void ili9341_send_data(void * data, uint16_t length); 39 | static void ili9341_send_color(void * data, uint16_t length); 40 | 41 | /********************** 42 | * STATIC VARIABLES 43 | **********************/ 44 | 45 | /********************** 46 | * MACROS 47 | **********************/ 48 | 49 | /********************** 50 | * GLOBAL FUNCTIONS 51 | **********************/ 52 | 53 | void ili9341_init(void) 54 | { 55 | lcd_init_cmd_t ili_init_cmds[]={ 56 | {0xCF, {0x00, 0x83, 0X30}, 3}, 57 | {0xED, {0x64, 0x03, 0X12, 0X81}, 4}, 58 | {0xE8, {0x85, 0x01, 0x79}, 3}, 59 | {0xCB, {0x39, 0x2C, 0x00, 0x34, 0x02}, 5}, 60 | {0xF7, {0x20}, 1}, 61 | {0xEA, {0x00, 0x00}, 2}, 62 | {0xC0, {0x26}, 1}, /*Power control*/ 63 | {0xC1, {0x11}, 1}, /*Power control */ 64 | {0xC5, {0x35, 0x3E}, 2}, /*VCOM control*/ 65 | {0xC7, {0xBE}, 1}, /*VCOM control*/ 66 | {0x36, {0x28}, 1}, /*Memory Access Control*/ 67 | {0x3A, {0x55}, 1}, /*Pixel Format Set*/ 68 | {0xB1, {0x00, 0x1B}, 2}, 69 | {0xF2, {0x08}, 1}, 70 | {0x26, {0x01}, 1}, 71 | {0xE0, {0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0X87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00}, 15}, 72 | {0XE1, {0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F}, 15}, 73 | {0x2A, {0x00, 0x00, 0x00, 0xEF}, 4}, 74 | {0x2B, {0x00, 0x00, 0x01, 0x3f}, 4}, 75 | {0x2C, {0}, 0}, 76 | {0xB7, {0x07}, 1}, 77 | {0xB6, {0x0A, 0x82, 0x27, 0x00}, 4}, 78 | {0x11, {0}, 0x80}, 79 | {0x29, {0}, 0x80}, 80 | {0, {0}, 0xff}, 81 | }; 82 | 83 | //Initialize non-SPI GPIOs 84 | gpio_pad_select_gpio(ILI9341_DC); 85 | gpio_set_direction(ILI9341_DC, GPIO_MODE_OUTPUT); 86 | 87 | #if ILI9341_USE_RST 88 | gpio_pad_select_gpio(ILI9341_RST); 89 | gpio_set_direction(ILI9341_RST, GPIO_MODE_OUTPUT); 90 | 91 | //Reset the display 92 | gpio_set_level(ILI9341_RST, 0); 93 | vTaskDelay(100 / portTICK_RATE_MS); 94 | gpio_set_level(ILI9341_RST, 1); 95 | vTaskDelay(100 / portTICK_RATE_MS); 96 | #endif 97 | 98 | ESP_LOGI(TAG, "Initialization."); 99 | 100 | //Send all the commands 101 | uint16_t cmd = 0; 102 | while (ili_init_cmds[cmd].databytes!=0xff) { 103 | ili9341_send_cmd(ili_init_cmds[cmd].cmd); 104 | ili9341_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F); 105 | if (ili_init_cmds[cmd].databytes & 0x80) { 106 | vTaskDelay(100 / portTICK_RATE_MS); 107 | } 108 | cmd++; 109 | } 110 | 111 | ili9341_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION); 112 | 113 | #if ILI9341_INVERT_COLORS == 1 114 | ili9341_send_cmd(0x21); 115 | #else 116 | ili9341_send_cmd(0x20); 117 | #endif 118 | } 119 | 120 | 121 | void ili9341_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map) 122 | { 123 | uint8_t data[4]; 124 | 125 | /*Column addresses*/ 126 | ili9341_send_cmd(0x2A); 127 | data[0] = (area->x1 >> 8) & 0xFF; 128 | data[1] = area->x1 & 0xFF; 129 | data[2] = (area->x2 >> 8) & 0xFF; 130 | data[3] = area->x2 & 0xFF; 131 | ili9341_send_data(data, 4); 132 | 133 | /*Page addresses*/ 134 | ili9341_send_cmd(0x2B); 135 | data[0] = (area->y1 >> 8) & 0xFF; 136 | data[1] = area->y1 & 0xFF; 137 | data[2] = (area->y2 >> 8) & 0xFF; 138 | data[3] = area->y2 & 0xFF; 139 | ili9341_send_data(data, 4); 140 | 141 | /*Memory write*/ 142 | ili9341_send_cmd(0x2C); 143 | uint32_t size = lv_area_get_width(area) * lv_area_get_height(area); 144 | ili9341_send_color((void*)color_map, size * 2); 145 | } 146 | 147 | void ili9341_sleep_in() 148 | { 149 | uint8_t data[] = {0x08}; 150 | ili9341_send_cmd(0x10); 151 | ili9341_send_data(&data, 1); 152 | } 153 | 154 | void ili9341_sleep_out() 155 | { 156 | uint8_t data[] = {0x08}; 157 | ili9341_send_cmd(0x11); 158 | ili9341_send_data(&data, 1); 159 | } 160 | 161 | /********************** 162 | * STATIC FUNCTIONS 163 | **********************/ 164 | 165 | 166 | static void ili9341_send_cmd(uint8_t cmd) 167 | { 168 | disp_wait_for_pending_transactions(); 169 | gpio_set_level(ILI9341_DC, 0); /*Command mode*/ 170 | disp_spi_send_data(&cmd, 1); 171 | } 172 | 173 | static void ili9341_send_data(void * data, uint16_t length) 174 | { 175 | disp_wait_for_pending_transactions(); 176 | gpio_set_level(ILI9341_DC, 1); /*Data mode*/ 177 | disp_spi_send_data(data, length); 178 | } 179 | 180 | static void ili9341_send_color(void * data, uint16_t length) 181 | { 182 | disp_wait_for_pending_transactions(); 183 | gpio_set_level(ILI9341_DC, 1); /*Data mode*/ 184 | disp_spi_send_colors(data, length); 185 | } 186 | 187 | static void ili9341_set_orientation(uint8_t orientation) 188 | { 189 | // ESP_ASSERT(orientation < 4); 190 | 191 | const char *orientation_str[] = { 192 | "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED" 193 | }; 194 | 195 | ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); 196 | 197 | #if defined CONFIG_LV_PREDEFINED_DISPLAY_M5STACK 198 | uint8_t data[] = {0x68, 0x68, 0x08, 0x08}; 199 | #elif defined (CONFIG_LV_PREDEFINED_DISPLAY_M5CORE2) 200 | uint8_t data[] = {0x08, 0x88, 0x28, 0xE8}; 201 | #elif defined (CONFIG_LV_PREDEFINED_DISPLAY_WROVER4) 202 | uint8_t data[] = {0x6C, 0xEC, 0xCC, 0x4C}; 203 | #elif defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE) 204 | uint8_t data[] = {0x48, 0x88, 0x28, 0xE8}; 205 | #endif 206 | 207 | ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]); 208 | 209 | ili9341_send_cmd(0x36); 210 | ili9341_send_data((void *) &data[orientation], 1); 211 | } 212 | -------------------------------------------------------------------------------- /lvgl_tft/ili9341.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_templ.h 3 | * 4 | */ 5 | 6 | #ifndef ILI9341_H 7 | #define ILI9341_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #include 17 | 18 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 19 | #include "lvgl.h" 20 | #else 21 | #include "lvgl/lvgl.h" 22 | #endif 23 | 24 | #include "sdkconfig.h" 25 | 26 | /********************* 27 | * DEFINES 28 | *********************/ 29 | #define ILI9341_DC CONFIG_LV_DISP_PIN_DC 30 | #define ILI9341_USE_RST CONFIG_LV_DISP_USE_RST 31 | #define ILI9341_RST CONFIG_LV_DISP_PIN_RST 32 | #define ILI9341_INVERT_COLORS CONFIG_LV_INVERT_COLORS 33 | 34 | /********************** 35 | * TYPEDEFS 36 | **********************/ 37 | 38 | /********************** 39 | * GLOBAL PROTOTYPES 40 | **********************/ 41 | 42 | void ili9341_init(void); 43 | void ili9341_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 44 | void ili9341_sleep_in(void); 45 | void ili9341_sleep_out(void); 46 | 47 | /********************** 48 | * MACROS 49 | **********************/ 50 | 51 | 52 | #ifdef __cplusplus 53 | } /* extern "C" */ 54 | #endif 55 | 56 | #endif /*ILI9341_H*/ 57 | -------------------------------------------------------------------------------- /lvgl_tft/ili9481.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ili9481.c 3 | */ 4 | 5 | /********************* 6 | * INCLUDES 7 | *********************/ 8 | #include "ili9481.h" 9 | #include "disp_spi.h" 10 | #include "driver/gpio.h" 11 | #include "esp_log.h" 12 | #include "esp_heap_caps.h" 13 | 14 | #include "freertos/FreeRTOS.h" 15 | #include "freertos/task.h" 16 | 17 | /********************* 18 | * DEFINES 19 | *********************/ 20 | #define TAG "ILI9481" 21 | 22 | /********************** 23 | * TYPEDEFS 24 | **********************/ 25 | 26 | /*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */ 27 | typedef struct { 28 | uint8_t cmd; 29 | uint8_t data[16]; 30 | uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds. 31 | } lcd_init_cmd_t; 32 | 33 | /********************** 34 | * STATIC PROTOTYPES 35 | **********************/ 36 | 37 | static void ili9481_set_orientation(uint8_t orientation); 38 | static void ili9481_send_cmd(uint8_t cmd); 39 | static void ili9481_send_data(void * data, uint16_t length); 40 | static void ili9481_send_color(void * data, uint16_t length); 41 | 42 | /********************** 43 | * STATIC VARIABLES 44 | **********************/ 45 | 46 | /********************** 47 | * MACROS 48 | **********************/ 49 | 50 | /********************** 51 | * GLOBAL FUNCTIONS 52 | **********************/ 53 | 54 | void ili9481_init(void) 55 | { 56 | lcd_init_cmd_t ili_init_cmds[]={ 57 | {ILI9481_CMD_SLEEP_OUT, {0x00}, 0x80}, 58 | {ILI9481_CMD_POWER_SETTING, {0x07, 0x42, 0x18}, 3}, 59 | {ILI9481_CMD_VCOM_CONTROL, {0x00, 0x07, 0x10}, 3}, 60 | {ILI9481_CMD_POWER_CONTROL_NORMAL, {0x01, 0x02}, 2}, 61 | {ILI9481_CMD_PANEL_DRIVE, {0x10, 0x3B, 0x00, 0x02, 0x11}, 5}, 62 | {ILI9481_CMD_FRAME_RATE, {0x03}, 1}, 63 | {ILI9481_CMD_FRAME_MEMORY_ACCESS, {0x0, 0x0, 0x0, 0x0}, 4}, 64 | //{ILI9481_CMD_DISP_TIMING_NORMAL, {0x10, 0x10, 0x22}, 3}, 65 | {ILI9481_CMD_GAMMA_SETTING, {0x00, 0x32, 0x36, 0x45, 0x06, 0x16, 0x37, 0x75, 0x77, 0x54, 0x0C, 0x00}, 12}, 66 | {ILI9481_CMD_MEMORY_ACCESS_CONTROL, {0x0A}, 1}, 67 | #if ILI9481_INVERT_COLORS 68 | {ILI9481_CMD_DISP_INVERSION_ON, {}, 0}, 69 | #endif 70 | {ILI9481_CMD_COLMOD_PIXEL_FORMAT_SET, {0x66}, 1}, 71 | {ILI9481_CMD_NORMAL_DISP_MODE_ON, {}, 0x80}, 72 | {ILI9481_CMD_DISPLAY_ON, {}, 0x80}, 73 | {0, {0}, 0xff}, 74 | }; 75 | 76 | //Initialize non-SPI GPIOs 77 | gpio_pad_select_gpio(ILI9481_DC); 78 | gpio_set_direction(ILI9481_DC, GPIO_MODE_OUTPUT); 79 | 80 | #if ILI9481_USE_RST 81 | gpio_pad_select_gpio(ILI9481_RST); 82 | gpio_set_direction(ILI9481_RST, GPIO_MODE_OUTPUT); 83 | 84 | //Reset the display 85 | gpio_set_level(ILI9481_RST, 0); 86 | vTaskDelay(100 / portTICK_RATE_MS); 87 | gpio_set_level(ILI9481_RST, 1); 88 | vTaskDelay(100 / portTICK_RATE_MS); 89 | #endif 90 | 91 | ESP_LOGI(TAG, "ILI9481 initialization."); 92 | 93 | // Exit sleep 94 | ili9481_send_cmd(0x01); /* Software reset */ 95 | vTaskDelay(100 / portTICK_RATE_MS); 96 | 97 | //Send all the commands 98 | uint16_t cmd = 0; 99 | while (ili_init_cmds[cmd].databytes!=0xff) { 100 | ili9481_send_cmd(ili_init_cmds[cmd].cmd); 101 | ili9481_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F); 102 | if (ili_init_cmds[cmd].databytes & 0x80) { 103 | vTaskDelay(100 / portTICK_RATE_MS); 104 | } 105 | cmd++; 106 | } 107 | 108 | ili9481_set_orientation(ILI9481_DISPLAY_ORIENTATION); 109 | } 110 | 111 | // Flush function based on mvturnho repo 112 | void ili9481_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map) 113 | { 114 | uint32_t size = lv_area_get_width(area) * lv_area_get_height(area); 115 | 116 | lv_color16_t *buffer_16bit = (lv_color16_t *) color_map; 117 | uint8_t *mybuf; 118 | do { 119 | mybuf = (uint8_t *) heap_caps_malloc(3 * size * sizeof(uint8_t), MALLOC_CAP_DMA); 120 | if (mybuf == NULL) ESP_LOGW(TAG, "Could not allocate enough DMA memory!"); 121 | } while (mybuf == NULL); 122 | 123 | uint32_t LD = 0; 124 | uint32_t j = 0; 125 | 126 | for (uint32_t i = 0; i < size; i++) { 127 | LD = buffer_16bit[i].full; 128 | mybuf[j] = (uint8_t) (((LD & 0xF800) >> 8) | ((LD & 0x8000) >> 13)); 129 | j++; 130 | mybuf[j] = (uint8_t) ((LD & 0x07E0) >> 3); 131 | j++; 132 | mybuf[j] = (uint8_t) (((LD & 0x001F) << 3) | ((LD & 0x0010) >> 2)); 133 | j++; 134 | } 135 | 136 | /* Column addresses */ 137 | uint8_t xb[] = { 138 | (uint8_t) (area->x1 >> 8) & 0xFF, 139 | (uint8_t) (area->x1) & 0xFF, 140 | (uint8_t) (area->x2 >> 8) & 0xFF, 141 | (uint8_t) (area->x2) & 0xFF, 142 | }; 143 | 144 | /* Page addresses */ 145 | uint8_t yb[] = { 146 | (uint8_t) (area->y1 >> 8) & 0xFF, 147 | (uint8_t) (area->y1) & 0xFF, 148 | (uint8_t) (area->y2 >> 8) & 0xFF, 149 | (uint8_t) (area->y2) & 0xFF, 150 | }; 151 | 152 | /*Column addresses*/ 153 | ili9481_send_cmd(ILI9481_CMD_COLUMN_ADDRESS_SET); 154 | ili9481_send_data(xb, 4); 155 | 156 | /*Page addresses*/ 157 | ili9481_send_cmd(ILI9481_CMD_PAGE_ADDRESS_SET); 158 | ili9481_send_data(yb, 4); 159 | 160 | /*Memory write*/ 161 | ili9481_send_cmd(ILI9481_CMD_MEMORY_WRITE); 162 | 163 | ili9481_send_color((void *) mybuf, size * 3); 164 | heap_caps_free(mybuf); 165 | } 166 | 167 | /********************** 168 | * STATIC FUNCTIONS 169 | **********************/ 170 | 171 | 172 | static void ili9481_send_cmd(uint8_t cmd) 173 | { 174 | disp_wait_for_pending_transactions(); 175 | gpio_set_level(ILI9481_DC, 0); /*Command mode*/ 176 | disp_spi_send_data(&cmd, 1); 177 | } 178 | 179 | static void ili9481_send_data(void * data, uint16_t length) 180 | { 181 | disp_wait_for_pending_transactions(); 182 | gpio_set_level(ILI9481_DC, 1); /*Data mode*/ 183 | disp_spi_send_data(data, length); 184 | } 185 | 186 | static void ili9481_send_color(void * data, uint16_t length) 187 | { 188 | disp_wait_for_pending_transactions(); 189 | gpio_set_level(ILI9481_DC, 1); /*Data mode*/ 190 | disp_spi_send_colors(data, length); 191 | } 192 | 193 | static void ili9481_set_orientation(uint8_t orientation) 194 | { 195 | const char *orientation_str[] = { 196 | "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED" 197 | }; 198 | 199 | ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); 200 | 201 | uint8_t data[] = {0x48, 0x4B, 0x28, 0x2B}; 202 | ili9481_send_cmd(ILI9481_CMD_MEMORY_ACCESS_CONTROL); 203 | ili9481_send_data((void *) &data[orientation], 1); 204 | } 205 | -------------------------------------------------------------------------------- /lvgl_tft/ili9481.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ili9481.h 3 | */ 4 | 5 | #ifndef ILI9481_H 6 | #define ILI9481_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /********************* 13 | * INCLUDES 14 | *********************/ 15 | #include 16 | #include 17 | 18 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 19 | #include "lvgl.h" 20 | #else 21 | #include "lvgl/lvgl.h" 22 | #endif 23 | #include "../lvgl_helpers.h" 24 | 25 | /********************* 26 | * DEFINES 27 | *********************/ 28 | #define ILI9481_DC CONFIG_LV_DISP_PIN_DC 29 | #define ILI9481_RST CONFIG_LV_DISP_PIN_RST 30 | #define ILI9481_USE_RST CONFIG_LV_DISP_USE_RST 31 | #define ILI9481_INVERT_COLORS CONFIG_LV_INVERT_COLORS 32 | #define ILI9481_DISPLAY_ORIENTATION CONFIG_LV_DISPLAY_ORIENTATION 33 | 34 | 35 | /******************* 36 | * ILI9481 REGS 37 | *********************/ 38 | 39 | /* MIPI DCS Type1 */ 40 | #define ILI9481_CMD_NOP 0x00 41 | #define ILI9481_CMD_SOFTWARE_RESET 0x01 42 | #define ILI9481_CMD_READ_DISP_POWER_MODE 0x0A 43 | #define ILI9481_CMD_READ_DISP_MADCTRL 0x0B // bits 7:3 only 44 | #define ILI9481_CMD_READ_DISP_PIXEL_FORMAT 0x0C 45 | #define ILI9481_CMD_READ_DISP_IMAGE_MODE 0x0D 46 | #define ILI9481_CMD_READ_DISP_SIGNAL_MODE 0x0E 47 | #define ILI9481_CMD_READ_DISP_SELF_DIAGNOSTIC 0x0F // bits 7:6 only 48 | #define ILI9481_CMD_ENTER_SLEEP_MODE 0x10 49 | #define ILI9481_CMD_SLEEP_OUT 0x11 50 | #define ILI9481_CMD_PARTIAL_MODE_ON 0x12 51 | #define ILI9481_CMD_NORMAL_DISP_MODE_ON 0x13 52 | #define ILI9481_CMD_DISP_INVERSION_OFF 0x20 53 | #define ILI9481_CMD_DISP_INVERSION_ON 0x21 54 | #define ILI9481_CMD_DISPLAY_OFF 0x28 55 | #define ILI9481_CMD_DISPLAY_ON 0x29 56 | #define ILI9481_CMD_COLUMN_ADDRESS_SET 0x2A 57 | #define ILI9481_CMD_PAGE_ADDRESS_SET 0x2B 58 | #define ILI9481_CMD_MEMORY_WRITE 0x2C 59 | #define ILI9481_CMD_MEMORY_READ 0x2E 60 | #define ILI9481_CMD_PARTIAL_AREA 0x30 61 | #define ILI9481_CMD_VERT_SCROLL_DEFINITION 0x33 62 | #define ILI9481_CMD_TEARING_EFFECT_LINE_OFF 0x34 63 | #define ILI9481_CMD_TEARING_EFFECT_LINE_ON 0x35 64 | #define ILI9481_CMD_MEMORY_ACCESS_CONTROL 0x36 // bits 7:3,1:0 only 65 | #define ILI9481_CMD_VERT_SCROLL_START_ADDRESS 0x37 66 | #define ILI9481_CMD_IDLE_MODE_OFF 0x38 67 | #define ILI9481_CMD_IDLE_MODE_ON 0x39 68 | #define ILI9481_CMD_COLMOD_PIXEL_FORMAT_SET 0x3A 69 | #define ILI9481_CMD_WRITE_MEMORY_CONTINUE 0x3C 70 | #define ILI9481_CMD_READ_MEMORY_CONTINUE 0x3E 71 | #define ILI9481_CMD_SET_TEAR_SCANLINE 0x44 72 | #define ILI9481_CMD_GET_SCANLINE 0x45 73 | 74 | #define ILI9481_DDB_START 0xA1 75 | #define ILI9481_DDB_CONTINUE 0xA8 76 | 77 | /* other */ 78 | #define ILI9481_CMD_ACCESS_PROTECT 0xB0 79 | #define ILI9481_CMD_LOW_POWER_CONTROL 0xB1 80 | #define ILI9481_CMD_FRAME_MEMORY_ACCESS 0xB3 81 | #define ILI9481_CMD_DISPLAY_MODE 0xB4 82 | #define ILI9481_CMD_DEVICE_CODE 0xBF 83 | 84 | #define ILI9481_CMD_PANEL_DRIVE 0xC0 85 | #define ILI9481_CMD_DISP_TIMING_NORMAL 0xC1 86 | #define ILI9481_CMD_DISP_TIMING_PARTIAL 0xC2 87 | #define ILI9481_CMD_DISP_TIMING_IDLE 0xC3 88 | #define ILI9481_CMD_FRAME_RATE 0xC5 89 | #define ILI9481_CMD_INTERFACE_CONTROL 0xC6 90 | #define ILI9481_CMD_GAMMA_SETTING 0xC8 91 | 92 | #define ILI9481_CMD_POWER_SETTING 0xD0 93 | #define ILI9481_CMD_VCOM_CONTROL 0xD1 94 | #define ILI9481_CMD_POWER_CONTROL_NORMAL 0xD2 95 | #define ILI9481_CMD_POWER_CONTROL_IDEL 0xD3 96 | #define ILI9481_CMD_POWER_CONTROL_PARTIAL 0xD4 97 | 98 | #define ILI9481_CMD_NVMEM_WRITE 0xE0 99 | #define ILI9481_CMD_NVMEM_PROTECTION_KEY 0xE1 100 | #define ILI9481_CMD_NVMEM_STATUS_READ 0xE2 101 | #define ILI9481_CMD_NVMEM_PROTECTION 0xE3 102 | 103 | /********************** 104 | * TYPEDEFS 105 | **********************/ 106 | 107 | /********************** 108 | * GLOBAL PROTOTYPES 109 | **********************/ 110 | 111 | void ili9481_init(void); 112 | void ili9481_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 113 | 114 | /********************** 115 | * MACROS 116 | **********************/ 117 | 118 | #ifdef __cplusplus 119 | } /* extern "C" */ 120 | #endif 121 | 122 | #endif /*ILI9481_H*/ 123 | -------------------------------------------------------------------------------- /lvgl_tft/ili9486.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mpi3501.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "ili9486.h" 10 | #include "disp_spi.h" 11 | #include "driver/gpio.h" 12 | #include "esp_log.h" 13 | #include "freertos/FreeRTOS.h" 14 | #include "freertos/task.h" 15 | 16 | /********************* 17 | * DEFINES 18 | *********************/ 19 | #define TAG "ILI9486" 20 | 21 | /********************** 22 | * TYPEDEFS 23 | **********************/ 24 | 25 | /*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */ 26 | typedef struct { 27 | uint8_t cmd; 28 | uint8_t data[16]; 29 | uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds. 30 | } lcd_init_cmd_t; 31 | 32 | /********************** 33 | * STATIC PROTOTYPES 34 | **********************/ 35 | static void ili9486_set_orientation(uint8_t orientation); 36 | 37 | static void ili9486_send_cmd(uint8_t cmd); 38 | static void ili9486_send_data(void * data, uint16_t length); 39 | static void ili9486_send_color(void * data, uint16_t length); 40 | 41 | /********************** 42 | * STATIC VARIABLES 43 | **********************/ 44 | 45 | /********************** 46 | * MACROS 47 | **********************/ 48 | 49 | /********************** 50 | * GLOBAL FUNCTIONS 51 | **********************/ 52 | 53 | void ili9486_init(void) 54 | { 55 | lcd_init_cmd_t ili_init_cmds[]={ 56 | {0x11, {0}, 0x80}, 57 | {0x3A, {0x55}, 1}, 58 | {0x2C, {0x44}, 1}, 59 | {0xC5, {0x00, 0x00, 0x00, 0x00}, 4}, 60 | {0xE0, {0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00}, 15}, 61 | {0XE1, {0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00}, 15}, 62 | {0x20, {0}, 0}, /* display inversion OFF */ 63 | {0x36, {0x48}, 1}, 64 | {0x29, {0}, 0x80}, /* display on */ 65 | {0x00, {0}, 0xff}, 66 | }; 67 | 68 | //Initialize non-SPI GPIOs 69 | gpio_pad_select_gpio(ILI9486_DC); 70 | gpio_set_direction(ILI9486_DC, GPIO_MODE_OUTPUT); 71 | 72 | #if ILI9486_USE_RST 73 | gpio_pad_select_gpio(ILI9486_RST); 74 | gpio_set_direction(ILI9486_RST, GPIO_MODE_OUTPUT); 75 | 76 | //Reset the display 77 | gpio_set_level(ILI9486_RST, 0); 78 | vTaskDelay(100 / portTICK_RATE_MS); 79 | gpio_set_level(ILI9486_RST, 1); 80 | vTaskDelay(100 / portTICK_RATE_MS); 81 | #endif 82 | 83 | ESP_LOGI(TAG, "ILI9486 Initialization."); 84 | 85 | //Send all the commands 86 | uint16_t cmd = 0; 87 | while (ili_init_cmds[cmd].databytes!=0xff) { 88 | ili9486_send_cmd(ili_init_cmds[cmd].cmd); 89 | ili9486_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F); 90 | if (ili_init_cmds[cmd].databytes & 0x80) { 91 | vTaskDelay(100 / portTICK_RATE_MS); 92 | } 93 | cmd++; 94 | } 95 | 96 | ili9486_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION); 97 | } 98 | 99 | void ili9486_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map) 100 | { 101 | uint8_t data[4] = {0}; 102 | uint32_t size = 0; 103 | 104 | /*Column addresses*/ 105 | ili9486_send_cmd(0x2A); 106 | data[0] = (area->x1 >> 8) & 0xFF; 107 | data[1] = area->x1 & 0xFF; 108 | data[2] = (area->x2 >> 8) & 0xFF; 109 | data[3] = area->x2 & 0xFF; 110 | ili9486_send_data(data, 4); 111 | 112 | /*Page addresses*/ 113 | ili9486_send_cmd(0x2B); 114 | data[0] = (area->y1 >> 8) & 0xFF; 115 | data[1] = area->y1 & 0xFF; 116 | data[2] = (area->y2 >> 8) & 0xFF; 117 | data[3] = area->y2 & 0xFF; 118 | ili9486_send_data(data, 4); 119 | 120 | /*Memory write*/ 121 | ili9486_send_cmd(0x2C); 122 | 123 | size = lv_area_get_width(area) * lv_area_get_height(area); 124 | 125 | ili9486_send_color((void*) color_map, size * 2); 126 | } 127 | 128 | /********************** 129 | * STATIC FUNCTIONS 130 | **********************/ 131 | static void ili9486_send_cmd(uint8_t cmd) 132 | { 133 | uint8_t to16bit[] = { 134 | 0x00, cmd 135 | }; 136 | 137 | disp_wait_for_pending_transactions(); 138 | gpio_set_level(ILI9486_DC, 0); /*Command mode*/ 139 | disp_spi_send_data(to16bit, sizeof to16bit); 140 | } 141 | 142 | static void ili9486_send_data(void * data, uint16_t length) 143 | { 144 | uint32_t i; 145 | uint8_t to16bit[32]; 146 | uint8_t * dummy = data; 147 | 148 | for(i=0; i < (length); i++) 149 | { 150 | to16bit[2*i+1] = dummy[i]; 151 | to16bit[2*i] = 0x00; 152 | } 153 | 154 | disp_wait_for_pending_transactions(); 155 | gpio_set_level(ILI9486_DC, 1); /*Data mode*/ 156 | disp_spi_send_data(to16bit, (length*2)); 157 | } 158 | 159 | static void ili9486_send_color(void * data, uint16_t length) 160 | { 161 | disp_wait_for_pending_transactions(); 162 | gpio_set_level(ILI9486_DC, 1); /*Data mode*/ 163 | disp_spi_send_colors(data, length); 164 | } 165 | 166 | static void ili9486_set_orientation(uint8_t orientation) 167 | { 168 | // ESP_ASSERT(orientation < 4); 169 | 170 | const char *orientation_str[] = { 171 | "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED" 172 | }; 173 | 174 | ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); 175 | 176 | #if defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE) 177 | uint8_t data[] = {0x48, 0x88, 0x28, 0xE8}; 178 | #endif 179 | 180 | ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]); 181 | 182 | ili9486_send_cmd(0x36); 183 | ili9486_send_data((void *) &data[orientation], 1); 184 | } 185 | -------------------------------------------------------------------------------- /lvgl_tft/ili9486.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ili9486.h 3 | * 4 | */ 5 | 6 | #ifndef ILI9486_H 7 | #define ILI9486_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #include 17 | 18 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 19 | #include "lvgl.h" 20 | #else 21 | #include "lvgl/lvgl.h" 22 | #endif 23 | #include "../lvgl_helpers.h" 24 | 25 | /********************* 26 | * DEFINES 27 | *********************/ 28 | #define ILI9486_DC CONFIG_LV_DISP_PIN_DC 29 | #define ILI9486_RST CONFIG_LV_DISP_PIN_RST 30 | #define ILI9486_USE_RST CONFIG_LV_DISP_USE_RST 31 | 32 | 33 | /********************** 34 | * TYPEDEFS 35 | **********************/ 36 | 37 | /********************** 38 | * GLOBAL PROTOTYPES 39 | **********************/ 40 | 41 | void ili9486_init(void); 42 | void ili9486_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 43 | 44 | /********************** 45 | * MACROS 46 | **********************/ 47 | 48 | 49 | #ifdef __cplusplus 50 | } /* extern "C" */ 51 | #endif 52 | 53 | #endif /* ILI9486_H*/ 54 | -------------------------------------------------------------------------------- /lvgl_tft/ili9488.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ili9488.c 3 | */ 4 | 5 | /********************* 6 | * INCLUDES 7 | *********************/ 8 | #include "ili9488.h" 9 | #include "disp_spi.h" 10 | #include "driver/gpio.h" 11 | #include "esp_log.h" 12 | #include "esp_heap_caps.h" 13 | 14 | #include "freertos/FreeRTOS.h" 15 | #include "freertos/task.h" 16 | 17 | /********************* 18 | * DEFINES 19 | *********************/ 20 | #define TAG "ILI9488" 21 | 22 | /********************** 23 | * TYPEDEFS 24 | **********************/ 25 | 26 | /*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */ 27 | typedef struct { 28 | uint8_t cmd; 29 | uint8_t data[16]; 30 | uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds. 31 | } lcd_init_cmd_t; 32 | 33 | /********************** 34 | * STATIC PROTOTYPES 35 | **********************/ 36 | static void ili9488_set_orientation(uint8_t orientation); 37 | 38 | static void ili9488_send_cmd(uint8_t cmd); 39 | static void ili9488_send_data(void * data, uint16_t length); 40 | static void ili9488_send_color(void * data, uint16_t length); 41 | 42 | /********************** 43 | * STATIC VARIABLES 44 | **********************/ 45 | 46 | /********************** 47 | * MACROS 48 | **********************/ 49 | 50 | /********************** 51 | * GLOBAL FUNCTIONS 52 | **********************/ 53 | // From github.com/jeremyjh/ESP32_TFT_library 54 | // From github.com/mvturnho/ILI9488-lvgl-ESP32-WROVER-B 55 | void ili9488_init(void) 56 | { 57 | lcd_init_cmd_t ili_init_cmds[]={ 58 | {ILI9488_CMD_SLEEP_OUT, {0x00}, 0x80}, 59 | {ILI9488_CMD_POSITIVE_GAMMA_CORRECTION, {0x00, 0x03, 0x09, 0x08, 0x16, 0x0A, 0x3F, 0x78, 0x4C, 0x09, 0x0A, 0x08, 0x16, 0x1A, 0x0F}, 15}, 60 | {ILI9488_CMD_NEGATIVE_GAMMA_CORRECTION, {0x00, 0x16, 0x19, 0x03, 0x0F, 0x05, 0x32, 0x45, 0x46, 0x04, 0x0E, 0x0D, 0x35, 0x37, 0x0F}, 15}, 61 | {ILI9488_CMD_POWER_CONTROL_1, {0x17, 0x15}, 2}, 62 | {ILI9488_CMD_POWER_CONTROL_2, {0x41}, 1}, 63 | {ILI9488_CMD_VCOM_CONTROL_1, {0x00, 0x12, 0x80}, 3}, 64 | {ILI9488_CMD_MEMORY_ACCESS_CONTROL, {(0x20 | 0x08)}, 1}, 65 | {ILI9488_CMD_COLMOD_PIXEL_FORMAT_SET, {0x66}, 1}, 66 | {ILI9488_CMD_INTERFACE_MODE_CONTROL, {0x00}, 1}, 67 | {ILI9488_CMD_FRAME_RATE_CONTROL_NORMAL, {0xA0}, 1}, 68 | {ILI9488_CMD_DISPLAY_INVERSION_CONTROL, {0x02}, 1}, 69 | {ILI9488_CMD_DISPLAY_FUNCTION_CONTROL, {0x02, 0x02}, 2}, 70 | {ILI9488_CMD_SET_IMAGE_FUNCTION, {0x00}, 1}, 71 | {ILI9488_CMD_WRITE_CTRL_DISPLAY, {0x28}, 1}, 72 | {ILI9488_CMD_WRITE_DISPLAY_BRIGHTNESS, {0x7F}, 1}, 73 | {ILI9488_CMD_ADJUST_CONTROL_3, {0xA9, 0x51, 0x2C, 0x02}, 4}, 74 | {ILI9488_CMD_DISPLAY_ON, {0x00}, 0x80}, 75 | {0, {0}, 0xff}, 76 | }; 77 | 78 | //Initialize non-SPI GPIOs 79 | gpio_pad_select_gpio(ILI9488_DC); 80 | gpio_set_direction(ILI9488_DC, GPIO_MODE_OUTPUT); 81 | 82 | #if ILI9488_USE_RST 83 | gpio_pad_select_gpio(ILI9488_RST); 84 | gpio_set_direction(ILI9488_RST, GPIO_MODE_OUTPUT); 85 | 86 | //Reset the display 87 | gpio_set_level(ILI9488_RST, 0); 88 | vTaskDelay(100 / portTICK_RATE_MS); 89 | gpio_set_level(ILI9488_RST, 1); 90 | vTaskDelay(100 / portTICK_RATE_MS); 91 | #endif 92 | 93 | ESP_LOGI(TAG, "ILI9488 initialization."); 94 | 95 | // Exit sleep 96 | ili9488_send_cmd(0x01); /* Software reset */ 97 | vTaskDelay(100 / portTICK_RATE_MS); 98 | 99 | //Send all the commands 100 | uint16_t cmd = 0; 101 | while (ili_init_cmds[cmd].databytes!=0xff) { 102 | ili9488_send_cmd(ili_init_cmds[cmd].cmd); 103 | ili9488_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F); 104 | if (ili_init_cmds[cmd].databytes & 0x80) { 105 | vTaskDelay(100 / portTICK_RATE_MS); 106 | } 107 | cmd++; 108 | } 109 | 110 | ili9488_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION); 111 | } 112 | 113 | // Flush function based on mvturnho repo 114 | void ili9488_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map) 115 | { 116 | uint32_t size = lv_area_get_width(area) * lv_area_get_height(area); 117 | 118 | lv_color16_t *buffer_16bit = (lv_color16_t *) color_map; 119 | uint8_t *mybuf; 120 | do { 121 | mybuf = (uint8_t *) heap_caps_malloc(3 * size * sizeof(uint8_t), MALLOC_CAP_DMA); 122 | if (mybuf == NULL) ESP_LOGW(TAG, "Could not allocate enough DMA memory!"); 123 | } while (mybuf == NULL); 124 | 125 | uint32_t LD = 0; 126 | uint32_t j = 0; 127 | 128 | for (uint32_t i = 0; i < size; i++) { 129 | LD = buffer_16bit[i].full; 130 | mybuf[j] = (uint8_t) (((LD & 0xF800) >> 8) | ((LD & 0x8000) >> 13)); 131 | j++; 132 | mybuf[j] = (uint8_t) ((LD & 0x07E0) >> 3); 133 | j++; 134 | mybuf[j] = (uint8_t) (((LD & 0x001F) << 3) | ((LD & 0x0010) >> 2)); 135 | j++; 136 | } 137 | 138 | /* Column addresses */ 139 | uint8_t xb[] = { 140 | (uint8_t) (area->x1 >> 8) & 0xFF, 141 | (uint8_t) (area->x1) & 0xFF, 142 | (uint8_t) (area->x2 >> 8) & 0xFF, 143 | (uint8_t) (area->x2) & 0xFF, 144 | }; 145 | 146 | /* Page addresses */ 147 | uint8_t yb[] = { 148 | (uint8_t) (area->y1 >> 8) & 0xFF, 149 | (uint8_t) (area->y1) & 0xFF, 150 | (uint8_t) (area->y2 >> 8) & 0xFF, 151 | (uint8_t) (area->y2) & 0xFF, 152 | }; 153 | 154 | /*Column addresses*/ 155 | ili9488_send_cmd(ILI9488_CMD_COLUMN_ADDRESS_SET); 156 | ili9488_send_data(xb, 4); 157 | 158 | /*Page addresses*/ 159 | ili9488_send_cmd(ILI9488_CMD_PAGE_ADDRESS_SET); 160 | ili9488_send_data(yb, 4); 161 | 162 | /*Memory write*/ 163 | ili9488_send_cmd(ILI9488_CMD_MEMORY_WRITE); 164 | 165 | ili9488_send_color((void *) mybuf, size * 3); 166 | heap_caps_free(mybuf); 167 | } 168 | 169 | /********************** 170 | * STATIC FUNCTIONS 171 | **********************/ 172 | 173 | 174 | static void ili9488_send_cmd(uint8_t cmd) 175 | { 176 | disp_wait_for_pending_transactions(); 177 | gpio_set_level(ILI9488_DC, 0); /*Command mode*/ 178 | disp_spi_send_data(&cmd, 1); 179 | } 180 | 181 | static void ili9488_send_data(void * data, uint16_t length) 182 | { 183 | disp_wait_for_pending_transactions(); 184 | gpio_set_level(ILI9488_DC, 1); /*Data mode*/ 185 | disp_spi_send_data(data, length); 186 | } 187 | 188 | static void ili9488_send_color(void * data, uint16_t length) 189 | { 190 | disp_wait_for_pending_transactions(); 191 | gpio_set_level(ILI9488_DC, 1); /*Data mode*/ 192 | disp_spi_send_colors(data, length); 193 | } 194 | 195 | static void ili9488_set_orientation(uint8_t orientation) 196 | { 197 | // ESP_ASSERT(orientation < 4); 198 | 199 | const char *orientation_str[] = { 200 | "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED" 201 | }; 202 | 203 | ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); 204 | 205 | #if defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE) 206 | uint8_t data[] = {0x48, 0x88, 0x28, 0xE8}; 207 | #endif 208 | 209 | ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]); 210 | 211 | ili9488_send_cmd(0x36); 212 | ili9488_send_data((void *) &data[orientation], 1); 213 | } 214 | -------------------------------------------------------------------------------- /lvgl_tft/ili9488.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ili9488.h 3 | */ 4 | 5 | #ifndef ILI9844_H 6 | #define ILI9844_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /********************* 13 | * INCLUDES 14 | *********************/ 15 | #include 16 | #include 17 | 18 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 19 | #include "lvgl.h" 20 | #else 21 | #include "lvgl/lvgl.h" 22 | #endif 23 | #include "../lvgl_helpers.h" 24 | 25 | /********************* 26 | * DEFINES 27 | *********************/ 28 | #define ILI9488_DC CONFIG_LV_DISP_PIN_DC 29 | #define ILI9488_RST CONFIG_LV_DISP_PIN_RST 30 | #define ILI9488_USE_RST CONFIG_LV_DISP_USE_RSTS 31 | 32 | /******************* 33 | * ILI9488 REGS 34 | *********************/ 35 | 36 | /* Level 1 Commands (from the display Datasheet) */ 37 | #define ILI9488_CMD_NOP 0x00 38 | #define ILI9488_CMD_SOFTWARE_RESET 0x01 39 | #define ILI9488_CMD_READ_DISP_ID 0x04 40 | #define ILI9488_CMD_READ_ERROR_DSI 0x05 41 | #define ILI9488_CMD_READ_DISP_STATUS 0x09 42 | #define ILI9488_CMD_READ_DISP_POWER_MODE 0x0A 43 | #define ILI9488_CMD_READ_DISP_MADCTRL 0x0B 44 | #define ILI9488_CMD_READ_DISP_PIXEL_FORMAT 0x0C 45 | #define ILI9488_CMD_READ_DISP_IMAGE_MODE 0x0D 46 | #define ILI9488_CMD_READ_DISP_SIGNAL_MODE 0x0E 47 | #define ILI9488_CMD_READ_DISP_SELF_DIAGNOSTIC 0x0F 48 | #define ILI9488_CMD_ENTER_SLEEP_MODE 0x10 49 | #define ILI9488_CMD_SLEEP_OUT 0x11 50 | #define ILI9488_CMD_PARTIAL_MODE_ON 0x12 51 | #define ILI9488_CMD_NORMAL_DISP_MODE_ON 0x13 52 | #define ILI9488_CMD_DISP_INVERSION_OFF 0x20 53 | #define ILI9488_CMD_DISP_INVERSION_ON 0x21 54 | #define ILI9488_CMD_PIXEL_OFF 0x22 55 | #define ILI9488_CMD_PIXEL_ON 0x23 56 | #define ILI9488_CMD_DISPLAY_OFF 0x28 57 | #define ILI9488_CMD_DISPLAY_ON 0x29 58 | #define ILI9488_CMD_COLUMN_ADDRESS_SET 0x2A 59 | #define ILI9488_CMD_PAGE_ADDRESS_SET 0x2B 60 | #define ILI9488_CMD_MEMORY_WRITE 0x2C 61 | #define ILI9488_CMD_MEMORY_READ 0x2E 62 | #define ILI9488_CMD_PARTIAL_AREA 0x30 63 | #define ILI9488_CMD_VERT_SCROLL_DEFINITION 0x33 64 | #define ILI9488_CMD_TEARING_EFFECT_LINE_OFF 0x34 65 | #define ILI9488_CMD_TEARING_EFFECT_LINE_ON 0x35 66 | #define ILI9488_CMD_MEMORY_ACCESS_CONTROL 0x36 67 | #define ILI9488_CMD_VERT_SCROLL_START_ADDRESS 0x37 68 | #define ILI9488_CMD_IDLE_MODE_OFF 0x38 69 | #define ILI9488_CMD_IDLE_MODE_ON 0x39 70 | #define ILI9488_CMD_COLMOD_PIXEL_FORMAT_SET 0x3A 71 | #define ILI9488_CMD_WRITE_MEMORY_CONTINUE 0x3C 72 | #define ILI9488_CMD_READ_MEMORY_CONTINUE 0x3E 73 | #define ILI9488_CMD_SET_TEAR_SCANLINE 0x44 74 | #define ILI9488_CMD_GET_SCANLINE 0x45 75 | #define ILI9488_CMD_WRITE_DISPLAY_BRIGHTNESS 0x51 76 | #define ILI9488_CMD_READ_DISPLAY_BRIGHTNESS 0x52 77 | #define ILI9488_CMD_WRITE_CTRL_DISPLAY 0x53 78 | #define ILI9488_CMD_READ_CTRL_DISPLAY 0x54 79 | #define ILI9488_CMD_WRITE_CONTENT_ADAPT_BRIGHTNESS 0x55 80 | #define ILI9488_CMD_READ_CONTENT_ADAPT_BRIGHTNESS 0x56 81 | #define ILI9488_CMD_WRITE_MIN_CAB_LEVEL 0x5E 82 | #define ILI9488_CMD_READ_MIN_CAB_LEVEL 0x5F 83 | #define ILI9488_CMD_READ_ABC_SELF_DIAG_RES 0x68 84 | #define ILI9488_CMD_READ_ID1 0xDA 85 | #define ILI9488_CMD_READ_ID2 0xDB 86 | #define ILI9488_CMD_READ_ID3 0xDC 87 | 88 | /* Level 2 Commands (from the display Datasheet) */ 89 | #define ILI9488_CMD_INTERFACE_MODE_CONTROL 0xB0 90 | #define ILI9488_CMD_FRAME_RATE_CONTROL_NORMAL 0xB1 91 | #define ILI9488_CMD_FRAME_RATE_CONTROL_IDLE_8COLOR 0xB2 92 | #define ILI9488_CMD_FRAME_RATE_CONTROL_PARTIAL 0xB3 93 | #define ILI9488_CMD_DISPLAY_INVERSION_CONTROL 0xB4 94 | #define ILI9488_CMD_BLANKING_PORCH_CONTROL 0xB5 95 | #define ILI9488_CMD_DISPLAY_FUNCTION_CONTROL 0xB6 96 | #define ILI9488_CMD_ENTRY_MODE_SET 0xB7 97 | #define ILI9488_CMD_BACKLIGHT_CONTROL_1 0xB9 98 | #define ILI9488_CMD_BACKLIGHT_CONTROL_2 0xBA 99 | #define ILI9488_CMD_HS_LANES_CONTROL 0xBE 100 | #define ILI9488_CMD_POWER_CONTROL_1 0xC0 101 | #define ILI9488_CMD_POWER_CONTROL_2 0xC1 102 | #define ILI9488_CMD_POWER_CONTROL_NORMAL_3 0xC2 103 | #define ILI9488_CMD_POWER_CONTROL_IDEL_4 0xC3 104 | #define ILI9488_CMD_POWER_CONTROL_PARTIAL_5 0xC4 105 | #define ILI9488_CMD_VCOM_CONTROL_1 0xC5 106 | #define ILI9488_CMD_CABC_CONTROL_1 0xC6 107 | #define ILI9488_CMD_CABC_CONTROL_2 0xC8 108 | #define ILI9488_CMD_CABC_CONTROL_3 0xC9 109 | #define ILI9488_CMD_CABC_CONTROL_4 0xCA 110 | #define ILI9488_CMD_CABC_CONTROL_5 0xCB 111 | #define ILI9488_CMD_CABC_CONTROL_6 0xCC 112 | #define ILI9488_CMD_CABC_CONTROL_7 0xCD 113 | #define ILI9488_CMD_CABC_CONTROL_8 0xCE 114 | #define ILI9488_CMD_CABC_CONTROL_9 0xCF 115 | #define ILI9488_CMD_NVMEM_WRITE 0xD0 116 | #define ILI9488_CMD_NVMEM_PROTECTION_KEY 0xD1 117 | #define ILI9488_CMD_NVMEM_STATUS_READ 0xD2 118 | #define ILI9488_CMD_READ_ID4 0xD3 119 | #define ILI9488_CMD_ADJUST_CONTROL_1 0xD7 120 | #define ILI9488_CMD_READ_ID_VERSION 0xD8 121 | #define ILI9488_CMD_POSITIVE_GAMMA_CORRECTION 0xE0 122 | #define ILI9488_CMD_NEGATIVE_GAMMA_CORRECTION 0xE1 123 | #define ILI9488_CMD_DIGITAL_GAMMA_CONTROL_1 0xE2 124 | #define ILI9488_CMD_DIGITAL_GAMMA_CONTROL_2 0xE3 125 | #define ILI9488_CMD_SET_IMAGE_FUNCTION 0xE9 126 | #define ILI9488_CMD_ADJUST_CONTROL_2 0xF2 127 | #define ILI9488_CMD_ADJUST_CONTROL_3 0xF7 128 | #define ILI9488_CMD_ADJUST_CONTROL_4 0xF8 129 | #define ILI9488_CMD_ADJUST_CONTROL_5 0xF9 130 | #define ILI9488_CMD_SPI_READ_SETTINGS 0xFB 131 | #define ILI9488_CMD_ADJUST_CONTROL_6 0xFC 132 | #define ILI9488_CMD_ADJUST_CONTROL_7 0xFF 133 | 134 | /********************** 135 | * TYPEDEFS 136 | **********************/ 137 | typedef struct { 138 | uint8_t red; 139 | uint8_t green; 140 | uint8_t blue; 141 | } lv_color_custom_t; 142 | 143 | /********************** 144 | * GLOBAL PROTOTYPES 145 | **********************/ 146 | 147 | void ili9488_init(void); 148 | void ili9488_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 149 | 150 | /********************** 151 | * MACROS 152 | **********************/ 153 | 154 | #ifdef __cplusplus 155 | } /* extern "C" */ 156 | #endif 157 | 158 | #endif /*ILI9488_H*/ 159 | -------------------------------------------------------------------------------- /lvgl_tft/jd79653a.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file il3820.h 3 | * 4 | */ 5 | 6 | #ifndef JD79653A_H 7 | #define JD79653A_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" 11 | { 12 | #endif 13 | 14 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 15 | #include "lvgl.h" 16 | #else 17 | #include "lvgl/lvgl.h" 18 | #endif 19 | 20 | void jd79653a_init(); 21 | void jd79653a_deep_sleep(); 22 | 23 | void jd79653a_lv_set_fb_cb(struct _disp_drv_t * disp_drv, uint8_t* buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, 24 | lv_color_t color, lv_opa_t opa); 25 | void jd79653a_lv_rounder_cb(struct _disp_drv_t * disp_drv, lv_area_t *area); 26 | void jd79653a_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); 27 | 28 | void jd79653a_fb_set_full_color(uint8_t color); 29 | void jd79653a_fb_full_update(uint8_t *data, size_t len); 30 | 31 | 32 | #ifdef __cplusplus 33 | } /* extern "C" */ 34 | #endif 35 | 36 | #endif // JD79653A_H 37 | -------------------------------------------------------------------------------- /lvgl_tft/pcd8544.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file pcd8544.c 3 | * 4 | * Roughly based on: 5 | * https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library 6 | * https://github.com/olikraus/u8g2 7 | */ 8 | 9 | #include "disp_spi.h" 10 | #include "driver/gpio.h" 11 | 12 | #include 13 | #include "freertos/FreeRTOS.h" 14 | #include "freertos/task.h" 15 | 16 | #include "pcd8544.h" 17 | 18 | #define TAG "lv_pcd8544" 19 | 20 | /********************** 21 | * MACROS 22 | **********************/ 23 | 24 | #define BIT_SET(a,b) ((a) |= (1U<<(b))) 25 | #define BIT_CLEAR(a,b) ((a) &= ~(1U<<(b))) 26 | 27 | /********************** 28 | * STATIC FUNCTIONS 29 | **********************/ 30 | 31 | static void pcd8544_send_cmd(uint8_t cmd) 32 | { 33 | disp_wait_for_pending_transactions(); 34 | gpio_set_level(PCD8544_DC, 0); /*Command mode*/ 35 | disp_spi_send_data(&cmd, 1); 36 | } 37 | 38 | static void pcd8544_send_data(void * data, uint16_t length) 39 | { 40 | disp_wait_for_pending_transactions(); 41 | gpio_set_level(PCD8544_DC, 1); /*Data mode*/ 42 | disp_spi_send_data(data, length); 43 | } 44 | 45 | static void pcd8544_send_colors(void * data, uint16_t length) 46 | { 47 | gpio_set_level(PCD8544_DC, 1); /*Data mode*/ 48 | disp_spi_send_colors(data, length); 49 | } 50 | 51 | /********************** 52 | * GLOBAL FUNCTIONS 53 | **********************/ 54 | 55 | void pcd8544_init(void){ 56 | 57 | // TODO: orientation 58 | 59 | // Initialize non-SPI GPIOs 60 | gpio_pad_select_gpio(PCD8544_DC); 61 | gpio_set_direction(PCD8544_DC, GPIO_MODE_OUTPUT); 62 | gpio_pad_select_gpio(PCD8544_RST); 63 | gpio_set_direction(PCD8544_RST, GPIO_MODE_OUTPUT); 64 | 65 | // Reset the display 66 | gpio_set_level(PCD8544_RST, 0); 67 | vTaskDelay(100 / portTICK_RATE_MS); 68 | gpio_set_level(PCD8544_RST, 1); 69 | vTaskDelay(100 / portTICK_RATE_MS); 70 | 71 | pcd8544_send_cmd(0x21); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */ 72 | pcd8544_send_cmd(0x06); /* temp. control: b10 = 2 */ 73 | pcd8544_send_cmd(0x13); /* bias system 1:48 */ 74 | pcd8544_send_cmd(0xc0); /* medium Vop = Contrast 0x40 = 64 */ 75 | 76 | pcd8544_send_cmd(0x20); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=0) */ 77 | pcd8544_send_cmd(0x0c); /* display mode normal */ 78 | } 79 | 80 | void pcd8544_set_contrast (uint8_t contrast){ 81 | if (contrast > 0x7f){ 82 | contrast = 0x7f; 83 | } 84 | pcd8544_send_cmd(0x21); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */ 85 | pcd8544_send_cmd(0x80 | contrast); /* medium Vop = Contrast */ 86 | } 87 | 88 | void pcd8544_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area){ 89 | uint8_t hor_max = disp_drv->hor_res; 90 | uint8_t ver_max = disp_drv->ver_res; 91 | 92 | area->x1 = 0; 93 | area->y1 = 0; 94 | area->x2 = hor_max - 1; 95 | area->y2 = ver_max - 1; 96 | } 97 | 98 | void pcd8544_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, 99 | lv_color_t color, lv_opa_t opa){ 100 | 101 | uint8_t set = (color.full == 0) && (LV_OPA_TRANSP != opa); 102 | 103 | uint16_t byte_index = x + (( y>>3 ) * buf_w); 104 | uint8_t bit_index = y & 0x7; 105 | 106 | if (set) { 107 | BIT_SET(buf[byte_index], bit_index); 108 | } else { 109 | BIT_CLEAR(buf[byte_index], bit_index); 110 | } 111 | } 112 | 113 | void pcd8544_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_map){ 114 | 115 | pcd8544_send_cmd(0x20); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=0) */ 116 | 117 | uint8_t * buf = (uint8_t *) color_map; 118 | 119 | // Check if the whole frame buffer can be sent in a single SPI transaction 120 | 121 | if ((area->x1 == 0) && (area->y1 == 0) && (area->x2 == (disp_drv->hor_res - 1)) && (area->y2 == (disp_drv->ver_res - 1))){ 122 | 123 | // send complete frame buffer at once. 124 | // NOTE: disp_spi_send_colors triggers lv_disp_flush_ready 125 | 126 | pcd8544_send_cmd(0x40); /* set Y address */ 127 | pcd8544_send_cmd(0x80); /* set X address */ 128 | pcd8544_send_colors(buf, disp_drv->hor_res * disp_drv->ver_res / 8); 129 | 130 | } else { 131 | 132 | // send horizontal tiles 133 | 134 | uint16_t bank_start = area->y1 / 8; 135 | uint16_t bank_end = area->y2 / 8; 136 | 137 | uint16_t bank; 138 | uint16_t cols_to_update = area->x2 - area->x1 + 1; 139 | for (bank = bank_start ; bank <= bank_end ; bank++ ){ 140 | pcd8544_send_cmd(0x40 | bank ); /* set Y address */ 141 | pcd8544_send_cmd(0x80 | area->x1 ); /* set X address */ 142 | uint16_t offset = bank * disp_drv->hor_res + area->x1; 143 | pcd8544_send_data(&buf[offset], cols_to_update); 144 | } 145 | 146 | lv_disp_flush_ready(disp_drv); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /lvgl_tft/pcd8544.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file pcd8544.h 4 | * 5 | */ 6 | 7 | #ifndef PCD8544_H 8 | #define PCD8544_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include 18 | 19 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 20 | #include "lvgl.h" 21 | #else 22 | #include "lvgl/lvgl.h" 23 | #endif 24 | 25 | /********************* 26 | * DEFINES 27 | *********************/ 28 | 29 | #define PCD8544_DC CONFIG_LV_DISP_PIN_DC 30 | #define PCD8544_RST CONFIG_LV_DISP_PIN_RST 31 | #define PCD8544_BCKL CONFIG_LV_DISP_PIN_BCKL 32 | 33 | /********************** 34 | * TYPEDEFS 35 | **********************/ 36 | 37 | /********************** 38 | * GLOBAL PROTOTYPES 39 | **********************/ 40 | 41 | void pcd8544_init(void); 42 | void pcd8544_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 43 | void pcd8544_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area); 44 | void pcd8544_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, 45 | lv_color_t color, lv_opa_t opa); 46 | void pcd8544_set_contrast(uint8_t contrast); 47 | 48 | /********************** 49 | * MACROS 50 | **********************/ 51 | 52 | 53 | #ifdef __cplusplus 54 | } /* extern "C" */ 55 | #endif 56 | 57 | #endif /*PCD8544_H*/ 58 | -------------------------------------------------------------------------------- /lvgl_tft/ra8875.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ra8875.h 3 | * 4 | */ 5 | 6 | #ifndef RA8875_H 7 | #define RA8875_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #include 17 | 18 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 19 | #include "lvgl.h" 20 | #else 21 | #include "lvgl/lvgl.h" 22 | #endif 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | #define RA8875_RST CONFIG_LV_DISP_PIN_RST 28 | #define RA8875_USE_RST CONFIG_LV_DISP_USE_RST 29 | 30 | // System & Configuration Registers 31 | #define RA8875_REG_PWRR (0x01) // Power and Display Control Register (PWRR) 32 | #define RA8875_REG_MRWC (0x02) // Memory Read/Write Command (MRWC) 33 | #define RA8875_REG_PCSR (0x04) // Pixel Clock Setting Register (PCSR) 34 | #define RA8875_REG_SYSR (0x10) // System Configuration Register (SYSR) 35 | #define RA8875_REG_HDWR (0x14) // LCD Horizontal Display Width Register (HDWR) 36 | #define RA8875_REG_HNDFTR (0x15) // Horizontal Non-Display Period Fine Tuning Option Register (HNDFTR) 37 | #define RA8875_REG_HNDR (0x16) // LCD Horizontal Non-Display Period Register (HNDR) 38 | #define RA8875_REG_HSTR (0x17) // HSYNC Start Position Register (HSTR) 39 | #define RA8875_REG_HPWR (0x18) // HSYNC Pulse Width Register (HPWR) 40 | #define RA8875_REG_VDHR0 (0x19) // LCD Vertical Display Height Register (VDHR0) 41 | #define RA8875_REG_VDHR1 (0x1A) // LCD Vertical Display Height Register (VDHR1) 42 | #define RA8875_REG_VNDR0 (0x1B) // LCD Vertical Non-Display Period Register (VNDR0) 43 | #define RA8875_REG_VNDR1 (0x1C) // LCD Vertical Non-Display Period Register (VNDR1) 44 | #define RA8875_REG_VSTR0 (0x1D) // VSYNC Start Position Register (VSTR0) 45 | #define RA8875_REG_VSTR1 (0x1E) // VSYNC Start Position Register (VSTR1) 46 | #define RA8875_REG_VPWR (0x1F) // VSYNC Pulse Width Register (VPWR) 47 | 48 | // LCD Display Control Registers 49 | #define RA8875_REG_DPCR (0x20) // Display Configuration Register (DPCR) 50 | 51 | // Active Window & Scroll Window Setting Registers 52 | #define RA8875_REG_HSAW0 (0x30) // Horizontal Start Point 0 of Active Window (HSAW0) 53 | #define RA8875_REG_HSAW1 (0x31) // Horizontal Start Point 1 of Active Window (HSAW1) 54 | #define RA8875_REG_VSAW0 (0x32) // Vertical Start Point 0 of Active Window (VSAW0) 55 | #define RA8875_REG_VSAW1 (0x33) // Vertical Start Point 1 of Active Window (VSAW1) 56 | #define RA8875_REG_HEAW0 (0x34) // Horizontal End Point 0 of Active Window (HEAW0) 57 | #define RA8875_REG_HEAW1 (0x35) // Horizontal End Point 1 of Active Window (HEAW1) 58 | #define RA8875_REG_VEAW0 (0x36) // Vertical End Point 0 of Active Window (VEAW0) 59 | #define RA8875_REG_VEAW1 (0x37) // Vertical End Point 1 of Active Window (VEAW1) 60 | 61 | // Cursor Setting Registers 62 | #define RA8875_REG_MWCR0 (0x40) // Memory Write Control Register 0 (MWCR0) 63 | #define RA8875_REG_MWCR1 (0x41) // Memory Write Control Register 1 (MWCR1) 64 | #define RA8875_REG_CURH0 (0x46) // Memory Write Cursor Horizontal Position Register 0 (CURH0) 65 | #define RA8875_REG_CURH1 (0x47) // Memory Write Cursor Horizontal Position Register 1 (CURH1) 66 | #define RA8875_REG_CURV0 (0x48) // Memory Write Cursor Vertical Position Register 0 (CURV0) 67 | #define RA8875_REG_CURV1 (0x49) // Memory Write Cursor Vertical Position Register 1 (CURV1) 68 | 69 | // Block Transfer Engine(BTE) Control Registers 70 | #define RA8875_REG_LTPR0 (0x52) // Layer Transparency Register 0 (LTPR0) 71 | #define RA8875_REG_LTPR1 (0x53) // Layer Transparency Register 1 (LTPR1) 72 | 73 | // Touch Panel Control Registers 74 | #define RA8875_REG_TPCR0 (0x70) // Touch Panel Control Register 0 (TPCR0) 75 | #define RA8875_REG_TPCR1 (0x71) // Touch Panel Control Register 1 (TPCR1) 76 | #define RA8875_REG_TPXH (0x72) // Touch Panel X High Byte Data Register (TPXH) 77 | #define RA8875_REG_TPYH (0x73) // Touch Panel Y High Byte Data Register (TPYH) 78 | #define RA8875_REG_TPXYL (0x74) // Touch Panel X/Y Low Byte Data Register (TPXYL) 79 | 80 | // PLL Setting Registers 81 | #define RA8875_REG_PLLC1 (0x88) // PLL Control Register 1 (PLLC1) 82 | #define RA8875_REG_PLLC2 (0x89) // PLL Control Register 2 (PLLC2) 83 | 84 | // Memory Clear Register 85 | #define RA8875_REG_MCLR (0x8E) // Memory Clear Control Register (MCLR) 86 | 87 | // Interrupt Control Registers 88 | #define RA8875_REG_INTC1 (0xF0) // Interrupt Control Register1 (INTC1) 89 | #define RA8875_REG_INTC2 (0xF1) // Interrupt Control Register1 (INTC2) 90 | 91 | /********************** 92 | * TYPEDEFS 93 | **********************/ 94 | 95 | /********************** 96 | * GLOBAL PROTOTYPES 97 | **********************/ 98 | 99 | void ra8875_init(void); 100 | void ra8875_enable_display(bool enable); 101 | void ra8875_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 102 | 103 | void ra8875_sleep_in(void); 104 | void ra8875_sleep_out(void); 105 | 106 | uint8_t ra8875_read_cmd(uint8_t cmd); 107 | void ra8875_write_cmd(uint8_t cmd, uint8_t data); 108 | 109 | /********************** 110 | * MACROS 111 | **********************/ 112 | 113 | 114 | #ifdef __cplusplus 115 | } /* extern "C" */ 116 | #endif 117 | 118 | #endif /*RA8875_H*/ 119 | -------------------------------------------------------------------------------- /lvgl_tft/sh1107.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sh1107.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "sh1107.h" 10 | #include "disp_spi.h" 11 | #include "driver/gpio.h" 12 | #include "esp_log.h" 13 | #include "freertos/FreeRTOS.h" 14 | #include "freertos/task.h" 15 | 16 | /********************* 17 | * DEFINES 18 | *********************/ 19 | #define TAG "SH1107" 20 | 21 | /********************** 22 | * TYPEDEFS 23 | **********************/ 24 | 25 | /*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */ 26 | typedef struct { 27 | uint8_t cmd; 28 | uint8_t data[16]; 29 | uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds. 30 | } lcd_init_cmd_t; 31 | 32 | /********************** 33 | * STATIC PROTOTYPES 34 | **********************/ 35 | static void sh1107_send_cmd(uint8_t cmd); 36 | static void sh1107_send_data(void * data, uint16_t length); 37 | static void sh1107_send_color(void * data, uint16_t length); 38 | 39 | /********************** 40 | * STATIC VARIABLES 41 | **********************/ 42 | 43 | /********************** 44 | * MACROS 45 | **********************/ 46 | 47 | #define BIT_SET(a,b) ((a) |= (1U<<(b))) 48 | #define BIT_CLEAR(a,b) ((a) &= ~(1U<<(b))) 49 | 50 | /********************** 51 | * GLOBAL FUNCTIONS 52 | **********************/ 53 | 54 | void sh1107_init(void) 55 | { 56 | // Use Double Bytes Commands if necessary, but not Command+Data 57 | // Initialization taken from https://github.com/nopnop2002/esp-idf-m5stick 58 | lcd_init_cmd_t init_cmds[]={ 59 | {0xAE, {0}, 0}, // Turn display off 60 | {0xDC, {0}, 0}, // Set display start line 61 | {0x00, {0}, 0}, // ...value 62 | {0x81, {0}, 0}, // Set display contrast 63 | {0x2F, {0}, 0}, // ...value 64 | {0x20, {0}, 0}, // Set memory mode 65 | {0xA0, {0}, 0}, // Non-rotated display 66 | #if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE 67 | {0xC8, {0}, 0}, // flipped vertical 68 | #elif defined CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT 69 | {0xC7, {0}, 0}, // flipped vertical 70 | #endif 71 | {0xA8, {0}, 0}, // Set multiplex ratio 72 | {0x7F, {0}, 0}, // ...value 73 | {0xD3, {0}, 0}, // Set display offset to zero 74 | {0x60, {0}, 0}, // ...value 75 | {0xD5, {0}, 0}, // Set display clock divider 76 | {0x51, {0}, 0}, // ...value 77 | {0xD9, {0}, 0}, // Set pre-charge 78 | {0x22, {0}, 0}, // ...value 79 | {0xDB, {0}, 0}, // Set com detect 80 | {0x35, {0}, 0}, // ...value 81 | {0xB0, {0}, 0}, // Set page address 82 | {0xDA, {0}, 0}, // Set com pins 83 | {0x12, {0}, 0}, // ...value 84 | {0xA4, {0}, 0}, // output ram to display 85 | #if defined CONFIG_LV_INVERT_COLORS 86 | {0xA7, {0}, 0}, // inverted display 87 | #else 88 | {0xA6, {0}, 0}, // Non-inverted display 89 | #endif 90 | {0xAF, {0}, 0}, // Turn display on 91 | {0, {0}, 0xff}, 92 | }; 93 | 94 | //Initialize non-SPI GPIOs 95 | gpio_pad_select_gpio(SH1107_DC); 96 | gpio_set_direction(SH1107_DC, GPIO_MODE_OUTPUT); 97 | 98 | #if SH1107_USE_RST 99 | gpio_pad_select_gpio(SH1107_RST); 100 | gpio_set_direction(SH1107_RST, GPIO_MODE_OUTPUT); 101 | 102 | //Reset the display 103 | gpio_set_level(SH1107_RST, 0); 104 | vTaskDelay(100 / portTICK_RATE_MS); 105 | gpio_set_level(SH1107_RST, 1); 106 | vTaskDelay(100 / portTICK_RATE_MS); 107 | #endif 108 | 109 | //Send all the commands 110 | uint16_t cmd = 0; 111 | while (init_cmds[cmd].databytes!=0xff) { 112 | sh1107_send_cmd(init_cmds[cmd].cmd); 113 | sh1107_send_data(init_cmds[cmd].data, init_cmds[cmd].databytes&0x1F); 114 | if (init_cmds[cmd].databytes & 0x80) { 115 | vTaskDelay(100 / portTICK_RATE_MS); 116 | } 117 | cmd++; 118 | } 119 | } 120 | 121 | void sh1107_set_px_cb(struct _disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, 122 | lv_color_t color, lv_opa_t opa) 123 | { 124 | /* buf_w will be ignored, the configured CONFIG_LV_DISPLAY_HEIGHT and _WIDTH, 125 | and CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE and _PORTRAIT will be used. */ 126 | uint16_t byte_index = 0; 127 | uint8_t bit_index = 0; 128 | 129 | #if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE 130 | byte_index = y + (( x>>3 ) * LV_VER_RES_MAX); 131 | bit_index = x & 0x7; 132 | #elif defined CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT 133 | byte_index = x + (( y>>3 ) * LV_HOR_RES_MAX); 134 | bit_index = y & 0x7; 135 | #endif 136 | 137 | if ((color.full == 0) && (LV_OPA_TRANSP != opa)) { 138 | BIT_SET(buf[byte_index], bit_index); 139 | } else { 140 | BIT_CLEAR(buf[byte_index], bit_index); 141 | } 142 | } 143 | 144 | void sh1107_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map) 145 | { 146 | uint8_t columnLow = area->x1 & 0x0F; 147 | uint8_t columnHigh = (area->x1 >> 4) & 0x0F; 148 | uint8_t row1 = 0, row2 = 0; 149 | uint32_t size = 0; 150 | void *ptr; 151 | 152 | #if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE 153 | row1 = area->x1>>3; 154 | row2 = area->x2>>3; 155 | #else 156 | row1 = area->y1>>3; 157 | row2 = area->y2>>3; 158 | #endif 159 | for(int i = row1; i < row2+1; i++){ 160 | sh1107_send_cmd(0x10 | columnHigh); // Set Higher Column Start Address for Page Addressing Mode 161 | sh1107_send_cmd(0x00 | columnLow); // Set Lower Column Start Address for Page Addressing Mode 162 | sh1107_send_cmd(0xB0 | i); // Set Page Start Address for Page Addressing Mode 163 | size = area->y2 - area->y1 + 1; 164 | #if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE 165 | ptr = color_map + i * LV_VER_RES_MAX; 166 | #else 167 | ptr = color_map + i * LV_HOR_RES_MAX; 168 | #endif 169 | if(i != row2){ 170 | sh1107_send_data( (void *) ptr, size); 171 | } else { 172 | // complete sending data by sh1107_send_color() and thus call lv_flush_ready() 173 | sh1107_send_color( (void *) ptr, size); 174 | } 175 | } 176 | } 177 | 178 | void sh1107_rounder(struct _disp_drv_t * disp_drv, lv_area_t *area) 179 | { 180 | // workaround: always send complete size display buffer 181 | area->x1 = 0; 182 | area->y1 = 0; 183 | area->x2 = LV_HOR_RES_MAX-1; 184 | area->y2 = LV_VER_RES_MAX-1; 185 | } 186 | 187 | void sh1107_sleep_in() 188 | { 189 | sh1107_send_cmd(0xAE); 190 | } 191 | 192 | void sh1107_sleep_out() 193 | { 194 | sh1107_send_cmd(0xAF); 195 | } 196 | 197 | /********************** 198 | * STATIC FUNCTIONS 199 | **********************/ 200 | 201 | 202 | static void sh1107_send_cmd(uint8_t cmd) 203 | { 204 | disp_wait_for_pending_transactions(); 205 | gpio_set_level(SH1107_DC, 0); /*Command mode*/ 206 | disp_spi_send_data(&cmd, 1); 207 | } 208 | 209 | static void sh1107_send_data(void * data, uint16_t length) 210 | { 211 | disp_wait_for_pending_transactions(); 212 | gpio_set_level(SH1107_DC, 1); /*Data mode*/ 213 | disp_spi_send_data(data, length); 214 | } 215 | 216 | static void sh1107_send_color(void * data, uint16_t length) 217 | { 218 | disp_wait_for_pending_transactions(); 219 | gpio_set_level(SH1107_DC, 1); /*Data mode*/ 220 | disp_spi_send_colors(data, length); 221 | } 222 | -------------------------------------------------------------------------------- /lvgl_tft/sh1107.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_templ.h 3 | * 4 | */ 5 | 6 | #ifndef SH1107_H 7 | #define SH1107_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #include 17 | 18 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 19 | #include "lvgl.h" 20 | #else 21 | #include "lvgl/lvgl.h" 22 | #endif 23 | #include "../lvgl_helpers.h" 24 | 25 | /********************* 26 | * DEFINES 27 | *********************/ 28 | #define SH1107_DC CONFIG_LV_DISP_PIN_DC 29 | #define SH1107_RST CONFIG_LV_DISP_PIN_RST 30 | #define SH1107_USE_RST CONFIG_LV_DISP_USE_RST 31 | 32 | /********************** 33 | * TYPEDEFS 34 | **********************/ 35 | 36 | /********************** 37 | * GLOBAL PROTOTYPES 38 | **********************/ 39 | 40 | void sh1107_init(void); 41 | void sh1107_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 42 | void sh1107_rounder(struct _disp_drv_t * disp_drv, lv_area_t *area); 43 | void sh1107_set_px_cb(struct _disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, 44 | lv_color_t color, lv_opa_t opa); 45 | void sh1107_sleep_in(void); 46 | void sh1107_sleep_out(void); 47 | 48 | /********************** 49 | * MACROS 50 | **********************/ 51 | 52 | #ifdef __cplusplus 53 | } /* extern "C" */ 54 | #endif 55 | 56 | #endif /*SH1107_H*/ 57 | -------------------------------------------------------------------------------- /lvgl_tft/ssd1306.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_templ.h 3 | * 4 | */ 5 | 6 | #ifndef SSD1306_H 7 | #define SSD1306_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #include 17 | 18 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 19 | #include "lvgl.h" 20 | #else 21 | #include "lvgl/lvgl.h" 22 | #endif 23 | #include "../lvgl_helpers.h" 24 | 25 | /********************* 26 | * DEFINES 27 | *********************/ 28 | #define SSD1306_DISPLAY_ORIENTATION TFT_ORIENTATION_LANDSCAPE 29 | 30 | /********************** 31 | * TYPEDEFS 32 | **********************/ 33 | 34 | /********************** 35 | * GLOBAL PROTOTYPES 36 | **********************/ 37 | void ssd1306_init(void); 38 | void ssd1306_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 39 | void ssd1306_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area); 40 | void ssd1306_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, 41 | lv_color_t color, lv_opa_t opa); 42 | 43 | void ssd1306_sleep_in(void); 44 | void ssd1306_sleep_out(void); 45 | 46 | /********************** 47 | * MACROS 48 | **********************/ 49 | 50 | 51 | #ifdef __cplusplus 52 | } /* extern "C" */ 53 | #endif 54 | 55 | #endif /*SSD1306_H*/ 56 | -------------------------------------------------------------------------------- /lvgl_tft/st7735s.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_templ.h 3 | * 4 | */ 5 | 6 | #ifndef ST7735S_H 7 | #define ST7735S_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #include 17 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 18 | #include "lvgl.h" 19 | #else 20 | #include "lvgl/lvgl.h" 21 | #endif 22 | 23 | /********************* 24 | * DEFINES 25 | *********************/ 26 | #define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) 27 | 28 | #define ST7735S_DC CONFIG_LV_DISP_PIN_DC 29 | #define ST7735S_RST CONFIG_LV_DISP_PIN_RST 30 | #define ST7735S_USE_RST CONFIG_LV_DISP_USE_RST 31 | 32 | #define ST7735S_INVERT_COLORS CONFIG_LV_INVERT_COLORS 33 | 34 | // Defines are taken from 35 | // https://raw.githubusercontent.com/m5stack/M5StickC/master/src/utility/ST7735_Defines.h 36 | // and are modified to fit to the M5StickC device, and are taken from 37 | // https://github.com/adafruit/Adafruit-ST7735-Library 38 | // 39 | #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 / 1 offset) 40 | #define COLSTART 26 41 | #define ROWSTART 1 42 | 43 | // Delay between some initialisation commands 44 | #define TFT_INIT_DELAY 0x80 45 | 46 | #define TFT_NOP 0x00 47 | #define TFT_SWRST 0x01 48 | 49 | #define TFT_CASET 0x2A 50 | #define TFT_PASET 0x2B 51 | #define TFT_RAMWR 0x2C 52 | 53 | #define TFT_RAMRD 0x2E 54 | #define TFT_IDXRD 0x00 55 | 56 | #define TFT_MADCTL 0x36 57 | #define TFT_MAD_MY 0x80 58 | #define TFT_MAD_MX 0x40 59 | #define TFT_MAD_MV 0x20 60 | #define TFT_MAD_ML 0x10 61 | #define TFT_MAD_BGR 0x08 62 | #define TFT_MAD_MH 0x04 63 | #define TFT_MAD_RGB 0x00 64 | 65 | #define TFT_INVOFF 0x20 66 | #define TFT_INVON 0x21 67 | 68 | // ST7735 specific commands used in init 69 | #define ST7735_NOP 0x00 70 | #define ST7735_SWRESET 0x01 71 | #define ST7735_RDDID 0x04 72 | #define ST7735_RDDST 0x09 73 | 74 | #define ST7735_SLPIN 0x10 75 | #define ST7735_SLPOUT 0x11 76 | #define ST7735_PTLON 0x12 77 | #define ST7735_NORON 0x13 78 | 79 | #define ST7735_INVOFF 0x20 80 | #define ST7735_INVON 0x21 81 | #define ST7735_DISPOFF 0x28 82 | #define ST7735_DISPON 0x29 83 | #define ST7735_CASET 0x2A 84 | #define ST7735_RASET 0x2B 85 | #define ST7735_RAMWR 0x2C 86 | #define ST7735_RAMRD 0x2E 87 | 88 | #define ST7735_PTLAR 0x30 89 | #define ST7735_VSCRDEF 0x33 90 | #define ST7735_COLMOD 0x3A 91 | #define ST7735_MADCTL 0x36 92 | #define ST7735_VSCRSADD 0x37 93 | 94 | #define ST7735_FRMCTR1 0xB1 95 | #define ST7735_FRMCTR2 0xB2 96 | #define ST7735_FRMCTR3 0xB3 97 | #define ST7735_INVCTR 0xB4 98 | #define ST7735_DISSET5 0xB6 99 | 100 | #define ST7735_PWCTR1 0xC0 101 | #define ST7735_PWCTR2 0xC1 102 | #define ST7735_PWCTR3 0xC2 103 | #define ST7735_PWCTR4 0xC3 104 | #define ST7735_PWCTR5 0xC4 105 | #define ST7735_VMCTR1 0xC5 106 | 107 | #define ST7735_RDID1 0xDA 108 | #define ST7735_RDID2 0xDB 109 | #define ST7735_RDID3 0xDC 110 | #define ST7735_RDID4 0xDD 111 | 112 | #define ST7735_PWCTR6 0xFC 113 | 114 | #define ST7735_GMCTRP1 0xE0 115 | #define ST7735_GMCTRN1 0xE1 116 | 117 | #define ST77XX_MADCTL_MY 0x80 118 | #define ST77XX_MADCTL_MX 0x40 119 | #define ST77XX_MADCTL_MV 0x20 120 | #define ST77XX_MADCTL_ML 0x10 121 | #define ST77XX_MADCTL_RGB 0x00 122 | #define ST77XX_MADCTL_BGR 0x08 123 | 124 | /********************** 125 | * TYPEDEFS 126 | **********************/ 127 | 128 | /********************** 129 | * GLOBAL PROTOTYPES 130 | **********************/ 131 | 132 | void st7735s_init(void); 133 | void st7735s_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); 134 | void st7735s_sleep_in(void); 135 | void st7735s_sleep_out(void); 136 | 137 | /********************** 138 | * MACROS 139 | **********************/ 140 | 141 | #ifdef __cplusplus 142 | } /* extern "C" */ 143 | #endif 144 | 145 | #endif /*ST7735S_H*/ 146 | -------------------------------------------------------------------------------- /lvgl_tft/st7789.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file st7789.h 3 | * 4 | * Mostly taken from lbthomsen/esp-idf-littlevgl github. 5 | */ 6 | 7 | #ifndef ST7789_H 8 | #define ST7789_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" 12 | { 13 | #endif 14 | 15 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 16 | #include "lvgl.h" 17 | #else 18 | #include "lvgl/lvgl.h" 19 | #endif 20 | #include "../lvgl_helpers.h" 21 | 22 | #include "sdkconfig.h" 23 | 24 | #define ST7789_DC CONFIG_LV_DISP_PIN_DC 25 | #define ST7789_RST CONFIG_LV_DISP_PIN_RST 26 | 27 | #if CONFIG_LV_DISP_USE_RST 28 | #if CONFIG_LV_DISP_ST7789_SOFT_RESET 29 | #define ST7789_SOFT_RST 30 | #endif 31 | #else 32 | #define ST7789_SOFT_RST 33 | #endif 34 | 35 | #define ST7789_INVERT_COLORS CONFIG_LV_INVERT_COLORS 36 | 37 | /* ST7789 commands */ 38 | #define ST7789_NOP 0x00 39 | #define ST7789_SWRESET 0x01 40 | #define ST7789_RDDID 0x04 41 | #define ST7789_RDDST 0x09 42 | 43 | #define ST7789_RDDPM 0x0A // Read display power mode 44 | #define ST7789_RDD_MADCTL 0x0B // Read display MADCTL 45 | #define ST7789_RDD_COLMOD 0x0C // Read display pixel format 46 | #define ST7789_RDDIM 0x0D // Read display image mode 47 | #define ST7789_RDDSM 0x0E // Read display signal mode 48 | #define ST7789_RDDSR 0x0F // Read display self-diagnostic result (ST7789V) 49 | 50 | #define ST7789_SLPIN 0x10 51 | #define ST7789_SLPOUT 0x11 52 | #define ST7789_PTLON 0x12 53 | #define ST7789_NORON 0x13 54 | 55 | #define ST7789_INVOFF 0x20 56 | #define ST7789_INVON 0x21 57 | #define ST7789_GAMSET 0x26 // Gamma set 58 | #define ST7789_DISPOFF 0x28 59 | #define ST7789_DISPON 0x29 60 | #define ST7789_CASET 0x2A 61 | #define ST7789_RASET 0x2B 62 | #define ST7789_RAMWR 0x2C 63 | #define ST7789_RGBSET 0x2D // Color setting for 4096, 64K and 262K colors 64 | #define ST7789_RAMRD 0x2E 65 | 66 | #define ST7789_PTLAR 0x30 67 | #define ST7789_VSCRDEF 0x33 // Vertical scrolling definition (ST7789V) 68 | #define ST7789_TEOFF 0x34 // Tearing effect line off 69 | #define ST7789_TEON 0x35 // Tearing effect line on 70 | #define ST7789_MADCTL 0x36 // Memory data access control 71 | #define ST7789_IDMOFF 0x38 // Idle mode off 72 | #define ST7789_IDMON 0x39 // Idle mode on 73 | #define ST7789_RAMWRC 0x3C // Memory write continue (ST7789V) 74 | #define ST7789_RAMRDC 0x3E // Memory read continue (ST7789V) 75 | #define ST7789_COLMOD 0x3A 76 | 77 | #define ST7789_RAMCTRL 0xB0 // RAM control 78 | #define ST7789_RGBCTRL 0xB1 // RGB control 79 | #define ST7789_PORCTRL 0xB2 // Porch control 80 | #define ST7789_FRCTRL1 0xB3 // Frame rate control 81 | #define ST7789_PARCTRL 0xB5 // Partial mode control 82 | #define ST7789_GCTRL 0xB7 // Gate control 83 | #define ST7789_GTADJ 0xB8 // Gate on timing adjustment 84 | #define ST7789_DGMEN 0xBA // Digital gamma enable 85 | #define ST7789_VCOMS 0xBB // VCOMS setting 86 | #define ST7789_LCMCTRL 0xC0 // LCM control 87 | #define ST7789_IDSET 0xC1 // ID setting 88 | #define ST7789_VDVVRHEN 0xC2 // VDV and VRH command enable 89 | #define ST7789_VRHS 0xC3 // VRH set 90 | #define ST7789_VDVSET 0xC4 // VDV setting 91 | #define ST7789_VCMOFSET 0xC5 // VCOMS offset set 92 | #define ST7789_FRCTR2 0xC6 // FR Control 2 93 | #define ST7789_CABCCTRL 0xC7 // CABC control 94 | #define ST7789_REGSEL1 0xC8 // Register value section 1 95 | #define ST7789_REGSEL2 0xCA // Register value section 2 96 | #define ST7789_PWMFRSEL 0xCC // PWM frequency selection 97 | #define ST7789_PWCTRL1 0xD0 // Power control 1 98 | #define ST7789_VAPVANEN 0xD2 // Enable VAP/VAN signal output 99 | #define ST7789_CMD2EN 0xDF // Command 2 enable 100 | #define ST7789_PVGAMCTRL 0xE0 // Positive voltage gamma control 101 | #define ST7789_NVGAMCTRL 0xE1 // Negative voltage gamma control 102 | #define ST7789_DGMLUTR 0xE2 // Digital gamma look-up table for red 103 | #define ST7789_DGMLUTB 0xE3 // Digital gamma look-up table for blue 104 | #define ST7789_GATECTRL 0xE4 // Gate control 105 | #define ST7789_SPI2EN 0xE7 // SPI2 enable 106 | #define ST7789_PWCTRL2 0xE8 // Power control 2 107 | #define ST7789_EQCTRL 0xE9 // Equalize time control 108 | #define ST7789_PROMCTRL 0xEC // Program control 109 | #define ST7789_PROMEN 0xFA // Program mode enable 110 | #define ST7789_NVMSET 0xFC // NVM setting 111 | #define ST7789_PROMACT 0xFE // Program action 112 | 113 | void st7789_init(void); 114 | void st7789_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); 115 | 116 | void st7789_send_cmd(uint8_t cmd); 117 | void st7789_send_data(void *data, uint16_t length); 118 | 119 | #ifdef __cplusplus 120 | } /* extern "C" */ 121 | #endif 122 | 123 | #endif /* ST7789_H */ 124 | -------------------------------------------------------------------------------- /lvgl_tft/st7796s.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file st7796s.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "st7796s.h" 10 | #include "disp_spi.h" 11 | #include "driver/gpio.h" 12 | #include "esp_log.h" 13 | #include "freertos/FreeRTOS.h" 14 | #include "freertos/task.h" 15 | 16 | /********************* 17 | * DEFINES 18 | *********************/ 19 | #define TAG "ST7796S" 20 | 21 | /********************** 22 | * TYPEDEFS 23 | **********************/ 24 | 25 | /*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */ 26 | typedef struct 27 | { 28 | uint8_t cmd; 29 | uint8_t data[16]; 30 | uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds. 31 | } lcd_init_cmd_t; 32 | 33 | /********************** 34 | * STATIC PROTOTYPES 35 | **********************/ 36 | static void st7796s_set_orientation(uint8_t orientation); 37 | 38 | static void st7796s_send_cmd(uint8_t cmd); 39 | static void st7796s_send_data(void *data, uint16_t length); 40 | static void st7796s_send_color(void *data, uint16_t length); 41 | 42 | /********************** 43 | * STATIC VARIABLES 44 | **********************/ 45 | 46 | /********************** 47 | * MACROS 48 | **********************/ 49 | 50 | /********************** 51 | * GLOBAL FUNCTIONS 52 | **********************/ 53 | 54 | void st7796s_init(void) 55 | { 56 | lcd_init_cmd_t init_cmds[] = { 57 | {0xCF, {0x00, 0x83, 0X30}, 3}, 58 | {0xED, {0x64, 0x03, 0X12, 0X81}, 4}, 59 | {0xE8, {0x85, 0x01, 0x79}, 3}, 60 | {0xCB, {0x39, 0x2C, 0x00, 0x34, 0x02}, 5}, 61 | {0xF7, {0x20}, 1}, 62 | {0xEA, {0x00, 0x00}, 2}, 63 | {0xC0, {0x26}, 1}, /*Power control*/ 64 | {0xC1, {0x11}, 1}, /*Power control */ 65 | {0xC5, {0x35, 0x3E}, 2}, /*VCOM control*/ 66 | {0xC7, {0xBE}, 1}, /*VCOM control*/ 67 | {0x36, {0x28}, 1}, /*Memory Access Control*/ 68 | {0x3A, {0x55}, 1}, /*Pixel Format Set*/ 69 | {0xB1, {0x00, 0x1B}, 2}, 70 | {0xF2, {0x08}, 1}, 71 | {0x26, {0x01}, 1}, 72 | {0xE0, {0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0X87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00}, 15}, 73 | {0XE1, {0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F}, 15}, 74 | {0x2A, {0x00, 0x00, 0x00, 0xEF}, 4}, 75 | {0x2B, {0x00, 0x00, 0x01, 0x3f}, 4}, 76 | {0x2C, {0}, 0}, 77 | {0xB7, {0x07}, 1}, 78 | {0xB6, {0x0A, 0x82, 0x27, 0x00}, 4}, 79 | {0x11, {0}, 0x80}, 80 | {0x29, {0}, 0x80}, 81 | {0, {0}, 0xff}, 82 | }; 83 | 84 | //Initialize non-SPI GPIOs 85 | gpio_pad_select_gpio(ST7796S_DC); 86 | gpio_set_direction(ST7796S_DC, GPIO_MODE_OUTPUT); 87 | 88 | #if ST7796S_USE_RST 89 | gpio_pad_select_gpio(ST7796S_RST); 90 | gpio_set_direction(ST7796S_RST, GPIO_MODE_OUTPUT); 91 | 92 | //Reset the display 93 | gpio_set_level(ST7796S_RST, 0); 94 | vTaskDelay(100 / portTICK_RATE_MS); 95 | gpio_set_level(ST7796S_RST, 1); 96 | vTaskDelay(100 / portTICK_RATE_MS); 97 | #endif 98 | 99 | ESP_LOGI(TAG, "Initialization."); 100 | 101 | //Send all the commands 102 | uint16_t cmd = 0; 103 | while (init_cmds[cmd].databytes != 0xff) 104 | { 105 | st7796s_send_cmd(init_cmds[cmd].cmd); 106 | st7796s_send_data(init_cmds[cmd].data, init_cmds[cmd].databytes & 0x1F); 107 | if (init_cmds[cmd].databytes & 0x80) 108 | { 109 | vTaskDelay(100 / portTICK_RATE_MS); 110 | } 111 | cmd++; 112 | } 113 | 114 | st7796s_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION); 115 | 116 | #if ST7796S_INVERT_COLORS == 1 117 | st7796s_send_cmd(0x21); 118 | #else 119 | st7796s_send_cmd(0x20); 120 | #endif 121 | } 122 | 123 | void st7796s_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) 124 | { 125 | uint8_t data[4]; 126 | 127 | /*Column addresses*/ 128 | st7796s_send_cmd(0x2A); 129 | data[0] = (area->x1 >> 8) & 0xFF; 130 | data[1] = area->x1 & 0xFF; 131 | data[2] = (area->x2 >> 8) & 0xFF; 132 | data[3] = area->x2 & 0xFF; 133 | st7796s_send_data(data, 4); 134 | 135 | /*Page addresses*/ 136 | st7796s_send_cmd(0x2B); 137 | data[0] = (area->y1 >> 8) & 0xFF; 138 | data[1] = area->y1 & 0xFF; 139 | data[2] = (area->y2 >> 8) & 0xFF; 140 | data[3] = area->y2 & 0xFF; 141 | st7796s_send_data(data, 4); 142 | 143 | /*Memory write*/ 144 | st7796s_send_cmd(0x2C); 145 | 146 | uint32_t size = lv_area_get_width(area) * lv_area_get_height(area); 147 | 148 | st7796s_send_color((void *)color_map, size * 2); 149 | } 150 | 151 | void st7796s_sleep_in() 152 | { 153 | uint8_t data[] = {0x08}; 154 | st7796s_send_cmd(0x10); 155 | st7796s_send_data(&data, 1); 156 | } 157 | 158 | void st7796s_sleep_out() 159 | { 160 | uint8_t data[] = {0x08}; 161 | st7796s_send_cmd(0x11); 162 | st7796s_send_data(&data, 1); 163 | } 164 | 165 | /********************** 166 | * STATIC FUNCTIONS 167 | **********************/ 168 | 169 | static void st7796s_send_cmd(uint8_t cmd) 170 | { 171 | disp_wait_for_pending_transactions(); 172 | gpio_set_level(ST7796S_DC, 0); /*Command mode*/ 173 | disp_spi_send_data(&cmd, 1); 174 | } 175 | 176 | static void st7796s_send_data(void *data, uint16_t length) 177 | { 178 | disp_wait_for_pending_transactions(); 179 | gpio_set_level(ST7796S_DC, 1); /*Data mode*/ 180 | disp_spi_send_data(data, length); 181 | } 182 | 183 | static void st7796s_send_color(void *data, uint16_t length) 184 | { 185 | disp_wait_for_pending_transactions(); 186 | gpio_set_level(ST7796S_DC, 1); /*Data mode*/ 187 | disp_spi_send_colors(data, length); 188 | } 189 | 190 | static void st7796s_set_orientation(uint8_t orientation) 191 | { 192 | // ESP_ASSERT(orientation < 4); 193 | 194 | const char *orientation_str[] = { 195 | "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"}; 196 | 197 | ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); 198 | 199 | #if defined CONFIG_LV_PREDEFINED_DISPLAY_M5STACK 200 | uint8_t data[] = {0x68, 0x68, 0x08, 0x08}; 201 | #elif defined(CONFIG_LV_PREDEFINED_DISPLAY_WROVER4) 202 | uint8_t data[] = {0x4C, 0x88, 0x28, 0xE8}; 203 | #elif defined(CONFIG_LV_PREDEFINED_DISPLAY_WT32_SC01) 204 | uint8_t data[] = {0x48, 0x88, 0x28, 0xE8}; 205 | #elif defined(CONFIG_LV_PREDEFINED_DISPLAY_NONE) 206 | uint8_t data[] = {0x48, 0x88, 0x28, 0xE8}; 207 | #endif 208 | 209 | ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]); 210 | 211 | st7796s_send_cmd(0x36); 212 | st7796s_send_data((void *)&data[orientation], 1); 213 | } 214 | -------------------------------------------------------------------------------- /lvgl_tft/st7796s.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file st7796s.h 3 | */ 4 | 5 | #ifndef ST7796S_H 6 | #define ST7796S_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" 10 | { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #include 17 | #include 18 | 19 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 20 | #include "lvgl.h" 21 | #else 22 | #include "lvgl/lvgl.h" 23 | #endif 24 | #include "../lvgl_helpers.h" 25 | 26 | /********************* 27 | * DEFINES 28 | *********************/ 29 | #define ST7796S_DC CONFIG_LV_DISP_PIN_DC 30 | #define ST7796S_RST CONFIG_LV_DISP_PIN_RST 31 | #define ST7796S_USE_RST CONFIG_LV_DISP_USE_RST 32 | #define ST7796S_INVERT_COLORS CONFIG_LV_INVERT_COLORS 33 | #define ST7796S_DISPLAY_ORIENTATION CONFIG_LV_DISPLAY_ORIENTATION 34 | 35 | 36 | /******************* 37 | * ST7796S REGS 38 | *********************/ 39 | 40 | /* MIPI DCS Type1 */ 41 | #define ST7796S_CMD_NOP 0x00 42 | #define ST7796S_CMD_SOFTWARE_RESET 0x01 43 | #define ST7796S_CMD_READ_DISP_POWER_MODE 0x0A 44 | #define ST7796S_CMD_READ_DISP_MADCTRL 0x0B // bits 7:3 only 45 | #define ST7796S_CMD_READ_DISP_PIXEL_FORMAT 0x0C 46 | #define ST7796S_CMD_READ_DISP_IMAGE_MODE 0x0D 47 | #define ST7796S_CMD_READ_DISP_SIGNAL_MODE 0x0E 48 | #define ST7796S_CMD_READ_DISP_SELF_DIAGNOSTIC 0x0F // bits 7:6 only 49 | #define ST7796S_CMD_ENTER_SLEEP_MODE 0x10 50 | #define ST7796S_CMD_SLEEP_OUT 0x11 51 | #define ST7796S_CMD_PARTIAL_MODE_ON 0x12 52 | #define ST7796S_CMD_NORMAL_DISP_MODE_ON 0x13 53 | #define ST7796S_CMD_DISP_INVERSION_OFF 0x20 54 | #define ST7796S_CMD_DISP_INVERSION_ON 0x21 55 | #define ST7796S_CMD_DISPLAY_OFF 0x28 56 | #define ST7796S_CMD_DISPLAY_ON 0x29 57 | #define ST7796S_CMD_COLUMN_ADDRESS_SET 0x2A 58 | #define ST7796S_CMD_PAGE_ADDRESS_SET 0x2B 59 | #define ST7796S_CMD_MEMORY_WRITE 0x2C 60 | #define ST7796S_CMD_MEMORY_READ 0x2E 61 | #define ST7796S_CMD_PARTIAL_AREA 0x30 62 | #define ST7796S_CMD_VERT_SCROLL_DEFINITION 0x33 63 | #define ST7796S_CMD_TEARING_EFFECT_LINE_OFF 0x34 64 | #define ST7796S_CMD_TEARING_EFFECT_LINE_ON 0x35 65 | #define ST7796S_CMD_MEMORY_ACCESS_CONTROL 0x36 // bits 7:3,1:0 only 66 | #define ST7796S_CMD_VERT_SCROLL_START_ADDRESS 0x37 67 | #define ST7796S_CMD_IDLE_MODE_OFF 0x38 68 | #define ST7796S_CMD_IDLE_MODE_ON 0x39 69 | #define ST7796S_CMD_COLMOD_PIXEL_FORMAT_SET 0x3A 70 | #define ST7796S_CMD_WRITE_MEMORY_CONTINUE 0x3C 71 | #define ST7796S_CMD_READ_MEMORY_CONTINUE 0x3E 72 | #define ST7796S_CMD_SET_TEAR_SCANLINE 0x44 73 | #define ST7796S_CMD_GET_SCANLINE 0x45 74 | 75 | #define ST7796S_DDB_START 0xA1 76 | #define ST7796S_DDB_CONTINUE 0xA8 77 | 78 | /* other */ 79 | #define ST7796S_CMD_ACCESS_PROTECT 0xB0 80 | #define ST7796S_CMD_LOW_POWER_CONTROL 0xB1 81 | #define ST7796S_CMD_FRAME_MEMORY_ACCESS 0xB3 82 | #define ST7796S_CMD_DISPLAY_MODE 0xB4 83 | #define ST7796S_CMD_DEVICE_CODE 0xBF 84 | 85 | #define ST7796S_CMD_PANEL_DRIVE 0xC0 86 | #define ST7796S_CMD_DISP_TIMING_NORMAL 0xC1 87 | #define ST7796S_CMD_DISP_TIMING_PARTIAL 0xC2 88 | #define ST7796S_CMD_DISP_TIMING_IDLE 0xC3 89 | #define ST7796S_CMD_FRAME_RATE 0xC5 90 | #define ST7796S_CMD_INTERFACE_CONTROL 0xC6 91 | #define ST7796S_CMD_GAMMA_SETTING 0xC8 92 | 93 | #define ST7796S_CMD_POWER_SETTING 0xD0 94 | #define ST7796S_CMD_VCOM_CONTROL 0xD1 95 | #define ST7796S_CMD_POWER_CONTROL_NORMAL 0xD2 96 | #define ST7796S_CMD_POWER_CONTROL_IDEL 0xD3 97 | #define ST7796S_CMD_POWER_CONTROL_PARTIAL 0xD4 98 | 99 | #define ST7796S_CMD_NVMEM_WRITE 0xE0 100 | #define ST7796S_CMD_NVMEM_PROTECTION_KEY 0xE1 101 | #define ST7796S_CMD_NVMEM_STATUS_READ 0xE2 102 | #define ST7796S_CMD_NVMEM_PROTECTION 0xE3 103 | 104 | /********************** 105 | * TYPEDEFS 106 | **********************/ 107 | 108 | /********************** 109 | * GLOBAL PROTOTYPES 110 | **********************/ 111 | 112 | void st7796s_init(void); 113 | void st7796s_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); 114 | 115 | /********************** 116 | * MACROS 117 | **********************/ 118 | 119 | #ifdef __cplusplus 120 | } /* extern "C" */ 121 | #endif 122 | 123 | #endif /*ST7796S_H*/ 124 | -------------------------------------------------------------------------------- /lvgl_tft/uc8151d.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file uc8151d.h 3 | @brief GoodDisplay GDEW0154M09 e-paper display w/ FitiPower JD79653A 4 | @version 1.0 5 | @date 2020-08-28 6 | @author Jackson Ming Hu 7 | 8 | 9 | @section LICENSE 10 | 11 | MIT License 12 | 13 | Copyright (c) 2020 Jackson Ming Hu 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 16 | to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, 17 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | #ifndef LVGL_DEMO_UC8151D_H 28 | #define LVGL_DEMO_UC8151D_H 29 | 30 | #include 31 | 32 | void uc8151d_init(); 33 | void uc8151d_lv_set_fb_cb(struct _disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, 34 | lv_color_t color, lv_opa_t opa); 35 | 36 | void uc8151d_lv_rounder_cb(struct _disp_drv_t *disp_drv, lv_area_t *area); 37 | void uc8151d_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); 38 | 39 | #endif //LVGL_DEMO_UC8151D_H 40 | -------------------------------------------------------------------------------- /lvgl_touch/FT81x.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file FT81x.c 3 | */ 4 | 5 | /********************* 6 | * INCLUDES 7 | *********************/ 8 | #include "esp_system.h" 9 | #include "esp_log.h" 10 | #include "freertos/FreeRTOS.h" 11 | #include "freertos/task.h" 12 | #include "driver/gpio.h" 13 | 14 | #include 15 | 16 | #include "FT81x.h" 17 | 18 | #include "../lvgl_tft/EVE.h" 19 | #include "../lvgl_tft/EVE_commands.h" 20 | 21 | 22 | /********************* 23 | * DEFINES 24 | *********************/ 25 | 26 | /********************** 27 | * TYPEDEFS 28 | **********************/ 29 | 30 | /********************** 31 | * STATIC PROTOTYPES 32 | **********************/ 33 | 34 | /********************** 35 | * STATIC VARIABLES 36 | **********************/ 37 | 38 | /********************** 39 | * MACROS 40 | **********************/ 41 | 42 | /********************** 43 | * GLOBAL FUNCTIONS 44 | **********************/ 45 | 46 | 47 | /** 48 | * Get the current position and state of the touchpad 49 | * @param data store the read data here 50 | * @return false: because no more data to be read 51 | */ 52 | bool FT81x_read(lv_indev_drv_t * drv, lv_indev_data_t * data) 53 | { 54 | static int16_t last_x = 0; 55 | static int16_t last_y = 0; 56 | bool touched = true; 57 | 58 | uint32_t XY = EVE_memRead32(REG_TOUCH_SCREEN_XY); 59 | uint16_t Y = XY & 0xffff; 60 | uint16_t X = XY >> 16; 61 | 62 | // is it not touched (or invalid because of calibration range) 63 | if(X == 0x8000 || Y == 0x8000 || X > LV_HOR_RES_MAX || Y > LV_VER_RES_MAX) 64 | { 65 | touched = false; 66 | X = last_x; 67 | Y = last_y; 68 | } 69 | else 70 | { 71 | last_x = X; 72 | last_y = Y; 73 | } 74 | 75 | data->point.x = X; 76 | data->point.y = Y; 77 | data->state = (touched == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR); 78 | 79 | return false; 80 | } 81 | 82 | 83 | /********************** 84 | * STATIC FUNCTIONS 85 | **********************/ 86 | -------------------------------------------------------------------------------- /lvgl_touch/FT81x.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file STMPE610.h 3 | */ 4 | 5 | #ifndef FT81X_TOUCH__H 6 | #define FT81X_TOUCH__H 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /********************* 13 | * INCLUDES 14 | *********************/ 15 | 16 | #include 17 | #include 18 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 19 | #include "lvgl.h" 20 | #else 21 | #include "lvgl/lvgl.h" 22 | #endif 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | 28 | /********************** 29 | * TYPEDEFS 30 | **********************/ 31 | 32 | /********************** 33 | * GLOBAL PROTOTYPES 34 | **********************/ 35 | ; 36 | bool FT81x_read(lv_indev_drv_t * drv, lv_indev_data_t * data); 37 | 38 | /********************** 39 | * MACROS 40 | **********************/ 41 | 42 | #ifdef __cplusplus 43 | } /* extern "C" */ 44 | #endif 45 | 46 | #endif /* FT81X_TOUCH__H */ 47 | -------------------------------------------------------------------------------- /lvgl_touch/adcraw.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ADCRAW.h 3 | */ 4 | 5 | #ifndef ADCRAW_H 6 | #define ADCRAW_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #include 13 | #include 14 | #include "driver/gpio.h" 15 | #include "driver/adc.h" 16 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 17 | #include "lvgl.h" 18 | #else 19 | #include "lvgl/lvgl.h" 20 | #endif 21 | 22 | #define TOUCHSCREEN_RESISTIVE_PIN_YU CONFIG_LV_TOUCHSCREEN_RESSITIVE_PIN_YU // Y+ any gpio 23 | #define TOUCHSCREEN_RESISTIVE_PIN_YD CONFIG_LV_TOUCHSCREEN_RESISTIVE_PIN_YD // Y- also ADC 24 | #define TOUCHSCREEN_RESISTIVE_PIN_XL CONFIG_LV_TOUCHSCREEN_RESISTIVE_PIN_XL // X- any gpio 25 | #define TOUCHSCREEN_RESISTIVE_PIN_XR CONFIG_LV_TOUCHSCREEN_RESISTIVE_PIN_XR // X+ also ADC 26 | 27 | // Default calibration points 28 | #define TOUCHCAL_ULX 29 // Upper Left X 29 | #define TOUCHCAL_ULY 84 // Upper Left Y 30 | #define TOUCHCAL_URX 828 // Upper Right X 31 | #define TOUCHCAL_URY 60 // Upper Right Y 32 | #define TOUCHCAL_LLX 29 // Lower Left X 33 | #define TOUCHCAL_LLY 928 // Lower Left Y 34 | #define TOUCHCAL_LRX 828 // Lower Right X 35 | #define TOUCHCAL_LRY 928 // Lower Right Y 36 | 37 | #define TOUCHSCREEN_RESISTIVE_PRESS_THRESHOLD 1023 38 | 39 | /*GetMaxX Macro*/ 40 | #if CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE 41 | #define GetMaxX() (LV_HOR_RES_MAX - 1) 42 | #else 43 | #define GetMaxX() (LV_VER_RES_MAX - 1) 44 | #endif 45 | 46 | /*GetMaxY Macro*/ 47 | #if CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE 48 | #define GetMaxY() (LV_VER_RES_MAX - 1) 49 | #else 50 | #define GetMaxY() (LV_HOR_RES_MAX - 1) 51 | #endif 52 | 53 | #ifndef CONCAT3 54 | #define _CONCAT3(a,b,c) a ## b ## c 55 | #define CONCAT3(a,b,c) _CONCAT3(a,b,c) 56 | #endif 57 | 58 | #define GPIO_TO_ADC_ELEMENT(x) [x] = CONCAT3(ADC1_GPIO, x, _CHANNEL) 59 | 60 | typedef enum { 61 | IDLE, 62 | SET_X, 63 | SET_Y, 64 | SET_Z1, 65 | SET_Z2, 66 | READ_X, 67 | READ_Y, 68 | READ_Z1, 69 | READ_Z2 70 | } TOUCH_STATES; 71 | 72 | void adcraw_init(void); 73 | bool adcraw_read(lv_indev_drv_t * drv, lv_indev_data_t * data); 74 | 75 | #ifdef __cplusplus 76 | } /* extern "C" */ 77 | #endif 78 | 79 | #endif /* ADCRAW_H */ 80 | -------------------------------------------------------------------------------- /lvgl_touch/ft6x36.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2020 Wolfgang Christl 3 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this 5 | * software and associated documentation files (the “Software”), to deal in the Software 6 | * without restriction, including without limitation the rights to use, copy, modify, merge, 7 | * publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 8 | * to whom the Software is furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or 11 | * substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 14 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 15 | * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 16 | * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 17 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 18 | * SOFTWARE. 19 | */ 20 | 21 | #include 22 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 23 | #include 24 | #else 25 | #include 26 | #endif 27 | #include "ft6x36.h" 28 | #include "lvgl_i2c/i2c_manager.h" 29 | 30 | #define TAG "FT6X36" 31 | #define FT6X36_TOUCH_QUEUE_ELEMENTS 1 32 | 33 | 34 | static ft6x36_status_t ft6x36_status; 35 | static uint8_t current_dev_addr; // set during init 36 | static ft6x36_touch_t touch_inputs = { -1, -1, LV_INDEV_STATE_REL }; // -1 coordinates to designate it was never touched 37 | #if CONFIG_LV_FT6X36_COORDINATES_QUEUE 38 | QueueHandle_t ft6x36_touch_queue_handle; 39 | #endif 40 | 41 | static esp_err_t ft6x06_i2c_read8(uint8_t slave_addr, uint8_t register_addr, uint8_t *data_buf) { 42 | return lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, slave_addr, register_addr, data_buf, 1); 43 | } 44 | 45 | /** 46 | * @brief Read the FT6x36 gesture ID. Initialize first! 47 | * @param dev_addr: I2C FT6x36 Slave address. 48 | * @retval The gesture ID or 0x00 in case of failure 49 | */ 50 | uint8_t ft6x36_get_gesture_id() { 51 | if (!ft6x36_status.inited) { 52 | ESP_LOGE(TAG, "Init first!"); 53 | return 0x00; 54 | } 55 | uint8_t data_buf; 56 | esp_err_t ret; 57 | if ((ret = ft6x06_i2c_read8(current_dev_addr, FT6X36_GEST_ID_REG, &data_buf) != ESP_OK)) 58 | ESP_LOGE(TAG, "Error reading from device: %s", esp_err_to_name(ret)); 59 | return data_buf; 60 | } 61 | 62 | /** 63 | * @brief Initialize for FT6x36 communication via I2C 64 | * @param dev_addr: Device address on communication Bus (I2C slave address of FT6X36). 65 | * @retval None 66 | */ 67 | void ft6x06_init(uint16_t dev_addr) { 68 | 69 | ft6x36_status.inited = true; 70 | current_dev_addr = dev_addr; 71 | uint8_t data_buf; 72 | esp_err_t ret; 73 | ESP_LOGI(TAG, "Found touch panel controller"); 74 | if ((ret = ft6x06_i2c_read8(dev_addr, FT6X36_PANEL_ID_REG, &data_buf) != ESP_OK)) 75 | ESP_LOGE(TAG, "Error reading from device: %s", 76 | esp_err_to_name(ret)); // Only show error the first time 77 | ESP_LOGI(TAG, "\tDevice ID: 0x%02x", data_buf); 78 | 79 | ft6x06_i2c_read8(dev_addr, FT6X36_CHIPSELECT_REG, &data_buf); 80 | ESP_LOGI(TAG, "\tChip ID: 0x%02x", data_buf); 81 | 82 | ft6x06_i2c_read8(dev_addr, FT6X36_DEV_MODE_REG, &data_buf); 83 | ESP_LOGI(TAG, "\tDevice mode: 0x%02x", data_buf); 84 | 85 | ft6x06_i2c_read8(dev_addr, FT6X36_FIRMWARE_ID_REG, &data_buf); 86 | ESP_LOGI(TAG, "\tFirmware ID: 0x%02x", data_buf); 87 | 88 | ft6x06_i2c_read8(dev_addr, FT6X36_RELEASECODE_REG, &data_buf); 89 | ESP_LOGI(TAG, "\tRelease code: 0x%02x", data_buf); 90 | 91 | #if CONFIG_LV_FT6X36_COORDINATES_QUEUE 92 | ft6x36_touch_queue_handle = xQueueCreate( FT6X36_TOUCH_QUEUE_ELEMENTS, sizeof( ft6x36_touch_t ) ); 93 | if( ft6x36_touch_queue_handle == NULL ) 94 | { 95 | ESP_LOGE( TAG, "\tError creating touch input FreeRTOS queue" ); 96 | return; 97 | } 98 | xQueueSend( ft6x36_touch_queue_handle, &touch_inputs, 0 ); 99 | #endif 100 | } 101 | 102 | /** 103 | * @brief Get the touch screen X and Y positions values. Ignores multi touch 104 | * @param drv: 105 | * @param data: Store data here 106 | * @retval Always false 107 | */ 108 | bool ft6x36_read(lv_indev_drv_t *drv, lv_indev_data_t *data) { 109 | if (!ft6x36_status.inited) { 110 | ESP_LOGE(TAG, "Init first!"); 111 | return 0x00; 112 | } 113 | uint8_t data_buf[5]; // 1 byte status, 2 bytes X, 2 bytes Y 114 | 115 | esp_err_t ret = lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, current_dev_addr, FT6X36_TD_STAT_REG, &data_buf[0], 5); 116 | if (ret != ESP_OK) { 117 | ESP_LOGE(TAG, "Error talking to touch IC: %s", esp_err_to_name(ret)); 118 | } 119 | uint8_t touch_pnt_cnt = data_buf[0]; // Number of detected touch points 120 | 121 | if (ret != ESP_OK || touch_pnt_cnt != 1) { // ignore no touch & multi touch 122 | if ( touch_inputs.current_state != LV_INDEV_STATE_REL) 123 | { 124 | touch_inputs.current_state = LV_INDEV_STATE_REL; 125 | #if CONFIG_LV_FT6X36_COORDINATES_QUEUE 126 | xQueueOverwrite( ft6x36_touch_queue_handle, &touch_inputs ); 127 | #endif 128 | } 129 | data->point.x = touch_inputs.last_x; 130 | data->point.y = touch_inputs.last_y; 131 | data->state = touch_inputs.current_state; 132 | return false; 133 | } 134 | 135 | touch_inputs.current_state = LV_INDEV_STATE_PR; 136 | touch_inputs.last_x = ((data_buf[1] & FT6X36_MSB_MASK) << 8) | (data_buf[2] & FT6X36_LSB_MASK); 137 | touch_inputs.last_y = ((data_buf[3] & FT6X36_MSB_MASK) << 8) | (data_buf[4] & FT6X36_LSB_MASK); 138 | 139 | #if CONFIG_LV_FT6X36_SWAPXY 140 | int16_t swap_buf = touch_inputs.last_x; 141 | touch_inputs.last_x = touch_inputs.last_y; 142 | touch_inputs.last_y = swap_buf; 143 | #endif 144 | #if CONFIG_LV_FT6X36_INVERT_X 145 | touch_inputs.last_x = LV_HOR_RES - touch_inputs.last_x; 146 | #endif 147 | #if CONFIG_LV_FT6X36_INVERT_Y 148 | touch_inputs.last_y = LV_VER_RES - touch_inputs.last_y; 149 | #endif 150 | data->point.x = touch_inputs.last_x; 151 | data->point.y = touch_inputs.last_y; 152 | data->state = touch_inputs.current_state; 153 | ESP_LOGD(TAG, "X=%u Y=%u", data->point.x, data->point.y); 154 | 155 | #if CONFIG_LV_FT6X36_COORDINATES_QUEUE 156 | xQueueOverwrite( ft6x36_touch_queue_handle, &touch_inputs ); 157 | #endif 158 | 159 | return false; 160 | } 161 | -------------------------------------------------------------------------------- /lvgl_touch/gt911.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2021 Sturnus Inc. 3 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this 5 | * software and associated documentation files (the “Software”), to deal in the Software 6 | * without restriction, including without limitation the rights to use, copy, modify, merge, 7 | * publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 8 | * to whom the Software is furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or 11 | * substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 14 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 15 | * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 16 | * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 17 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 18 | * SOFTWARE. 19 | */ 20 | 21 | #include 22 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 23 | #include 24 | #else 25 | #include 26 | #endif 27 | #include "gt911.h" 28 | 29 | #include "lvgl_i2c/i2c_manager.h" 30 | 31 | #define TAG "GT911" 32 | 33 | gt911_status_t gt911_status; 34 | 35 | //TODO: handle multibyte read and refactor to just one read transaction 36 | esp_err_t gt911_i2c_read(uint8_t slave_addr, uint16_t register_addr, uint8_t *data_buf, uint8_t len) { 37 | return lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, slave_addr, register_addr | I2C_REG_16, data_buf, len); 38 | } 39 | 40 | esp_err_t gt911_i2c_write8(uint8_t slave_addr, uint16_t register_addr, uint8_t data) { 41 | uint8_t buffer = data; 42 | return lvgl_i2c_write(CONFIG_LV_I2C_TOUCH_PORT, slave_addr, register_addr | I2C_REG_16, &buffer, 1); 43 | } 44 | 45 | /** 46 | * @brief Initialize for GT911 communication via I2C 47 | * @param dev_addr: Device address on communication Bus (I2C slave address of GT911). 48 | * @retval None 49 | */ 50 | void gt911_init(uint8_t dev_addr) { 51 | if (!gt911_status.inited) { 52 | gt911_status.i2c_dev_addr = dev_addr; 53 | uint8_t data_buf; 54 | esp_err_t ret; 55 | 56 | ESP_LOGI(TAG, "Checking for GT911 Touch Controller"); 57 | if ((ret = gt911_i2c_read(dev_addr, GT911_PRODUCT_ID1, &data_buf, 1) != ESP_OK)) { 58 | ESP_LOGE(TAG, "Error reading from device: %s", 59 | esp_err_to_name(ret)); // Only show error the first time 60 | return; 61 | } 62 | 63 | // Read 4 bytes for Product ID in ASCII 64 | for (int i = 0; i < GT911_PRODUCT_ID_LEN; i++) { 65 | gt911_i2c_read(dev_addr, (GT911_PRODUCT_ID1 + i), (uint8_t *)&(gt911_status.product_id[i]), 1); 66 | } 67 | ESP_LOGI(TAG, "\tProduct ID: %s", gt911_status.product_id); 68 | 69 | gt911_i2c_read(dev_addr, GT911_VENDOR_ID, &data_buf, 1); 70 | ESP_LOGI(TAG, "\tVendor ID: 0x%02x", data_buf); 71 | 72 | gt911_i2c_read(dev_addr, GT911_X_COORD_RES_L, &data_buf, 1); 73 | gt911_status.max_x_coord = data_buf; 74 | gt911_i2c_read(dev_addr, GT911_X_COORD_RES_H, &data_buf, 1); 75 | gt911_status.max_x_coord |= ((uint16_t)data_buf << 8); 76 | ESP_LOGI(TAG, "\tX Resolution: %d", gt911_status.max_x_coord); 77 | 78 | gt911_i2c_read(dev_addr, GT911_Y_COORD_RES_L, &data_buf, 1); 79 | gt911_status.max_y_coord = data_buf; 80 | gt911_i2c_read(dev_addr, GT911_Y_COORD_RES_H, &data_buf, 1); 81 | gt911_status.max_y_coord |= ((uint16_t)data_buf << 8); 82 | ESP_LOGI(TAG, "\tY Resolution: %d", gt911_status.max_y_coord); 83 | gt911_status.inited = true; 84 | } 85 | } 86 | 87 | /** 88 | * @brief Get the touch screen X and Y positions values. Ignores multi touch 89 | * @param drv: 90 | * @param data: Store data here 91 | * @retval Always false 92 | */ 93 | bool gt911_read(lv_indev_drv_t *drv, lv_indev_data_t *data) { 94 | uint8_t touch_pnt_cnt; // Number of detected touch points 95 | static int16_t last_x = 0; // 12bit pixel value 96 | static int16_t last_y = 0; // 12bit pixel value 97 | uint8_t data_buf; 98 | uint8_t status_reg; 99 | 100 | gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_STATUS_REG, &status_reg, 1); 101 | // ESP_LOGI(TAG, "\tstatus: 0x%02x", status_reg); 102 | touch_pnt_cnt = status_reg & 0x0F; 103 | if ((status_reg & 0x80) || (touch_pnt_cnt < 6)) { 104 | //Reset Status Reg Value 105 | gt911_i2c_write8(gt911_status.i2c_dev_addr, GT911_STATUS_REG, 0x00); 106 | } 107 | if (touch_pnt_cnt != 1) { // ignore no touch & multi touch 108 | data->point.x = last_x; 109 | data->point.y = last_y; 110 | data->state = LV_INDEV_STATE_REL; 111 | return false; 112 | } 113 | 114 | // gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_TRACK_ID1, &data_buf, 1); 115 | // ESP_LOGI(TAG, "\ttrack_id: %d", data_buf); 116 | 117 | gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_PT1_X_COORD_L, &data_buf, 1); 118 | last_x = data_buf; 119 | gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_PT1_X_COORD_H, &data_buf, 1); 120 | last_x |= ((uint16_t)data_buf << 8); 121 | 122 | gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_PT1_Y_COORD_L, &data_buf, 1); 123 | last_y = data_buf; 124 | gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_PT1_Y_COORD_H, &data_buf, 1); 125 | last_y |= ((uint16_t)data_buf << 8); 126 | 127 | #if CONFIG_LV_GT911_INVERT_X 128 | last_x = gt911_status.max_x_coord - last_x; 129 | #endif 130 | #if CONFIG_LV_GT911_INVERT_Y 131 | last_y = gt911_status.max_y_coord - last_y; 132 | #endif 133 | #if CONFIG_LV_GT911_SWAPXY 134 | int16_t swap_buf = last_x; 135 | last_x = last_y; 136 | last_y = swap_buf; 137 | #endif 138 | data->point.x = last_x; 139 | data->point.y = last_y; 140 | data->state = LV_INDEV_STATE_PR; 141 | ESP_LOGI(TAG, "X=%u Y=%u", data->point.x, data->point.y); 142 | ESP_LOGV(TAG, "X=%u Y=%u", data->point.x, data->point.y); 143 | return false; 144 | } 145 | -------------------------------------------------------------------------------- /lvgl_touch/gt911.h: -------------------------------------------------------------------------------- 1 | #ifndef __GT911_H 2 | /* 3 | * Copyright © 2021 Sturnus Inc. 4 | 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this 6 | * software and associated documentation files (the “Software”), to deal in the Software 7 | * without restriction, including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 9 | * to whom the Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all copies or 12 | * substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 15 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 16 | * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 17 | * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #define __GT911_H 23 | 24 | #include 25 | #include 26 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 27 | #include "lvgl.h" 28 | #else 29 | #include "lvgl/lvgl.h" 30 | #endif 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | #define GT911_I2C_SLAVE_ADDR 0x5D 37 | 38 | #define GT911_PRODUCT_ID_LEN 4 39 | 40 | /* Register Map of GT911 */ 41 | #define GT911_PRODUCT_ID1 0x8140 42 | #define GT911_PRODUCT_ID2 0x8141 43 | #define GT911_PRODUCT_ID3 0x8142 44 | #define GT911_PRODUCT_ID4 0x8143 45 | #define GT911_FIRMWARE_VER_L 0x8144 46 | #define GT911_FIRMWARE_VER_H 0x8145 47 | #define GT911_X_COORD_RES_L 0x8146 48 | #define GT911_X_COORD_RES_H 0x8147 49 | #define GT911_Y_COORD_RES_L 0x8148 50 | #define GT911_Y_COORD_RES_H 0x8149 51 | #define GT911_VENDOR_ID 0x814A 52 | 53 | #define GT911_STATUS_REG 0x814E 54 | #define GT911_STATUS_REG_BUF 0x80 55 | #define GT911_STATUS_REG_LARGE 0x40 56 | #define GT911_STATUS_REG_PROX_VALID 0x20 57 | #define GT911_STATUS_REG_HAVEKEY 0x10 58 | #define GT911_STATUS_REG_PT_MASK 0x0F 59 | 60 | #define GT911_TRACK_ID1 0x814F 61 | #define GT911_PT1_X_COORD_L 0x8150 62 | #define GT911_PT1_X_COORD_H 0x8151 63 | #define GT911_PT1_Y_COORD_L 0x8152 64 | #define GT911_PT1_Y_COORD_H 0x8153 65 | #define GT911_PT1_X_SIZE_L 0x8154 66 | #define GT911_PT1_X_SIZE_H 0x8155 67 | 68 | typedef struct { 69 | bool inited; 70 | char product_id[GT911_PRODUCT_ID_LEN]; 71 | uint16_t max_x_coord; 72 | uint16_t max_y_coord; 73 | uint8_t i2c_dev_addr; 74 | } gt911_status_t; 75 | 76 | /** 77 | * @brief Initialize for GT911 communication via I2C 78 | * @param dev_addr: Device address on communication Bus (I2C slave address of GT911). 79 | * @retval None 80 | */ 81 | void gt911_init(uint8_t dev_addr); 82 | 83 | /** 84 | * @brief Get the touch screen X and Y positions values. Ignores multi touch 85 | * @param drv: 86 | * @param data: Store data here 87 | * @retval Always false 88 | */ 89 | bool gt911_read(lv_indev_drv_t *drv, lv_indev_data_t *data); 90 | 91 | #ifdef __cplusplus 92 | } 93 | #endif 94 | #endif /* __GT911_H */ 95 | -------------------------------------------------------------------------------- /lvgl_touch/ra8875_touch.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file RA8875_TOUCH.c 3 | */ 4 | 5 | /********************* 6 | * INCLUDES 7 | *********************/ 8 | #include "esp_log.h" 9 | #include "freertos/FreeRTOS.h" 10 | #include "freertos/task.h" 11 | 12 | #include 13 | 14 | #include "ra8875_touch.h" 15 | 16 | #include "../lvgl_tft/ra8875.h" 17 | 18 | #ifndef CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875 19 | #error "Display controller must be RA8875" 20 | #endif 21 | 22 | /********************* 23 | * DEFINES 24 | *********************/ 25 | #define DEBUG false 26 | #define TAG "RA8875-Touch" 27 | 28 | #define DIV_ROUND_UP(n, d) (((n)+(d)-1)/(d)) 29 | 30 | #define INTC2_TP_INT (0x04) 31 | 32 | #define TPCR0_ADC_TIMING ((CONFIG_LV_TOUCH_RA8875_SAMPLE_TIME << 4) | CONFIG_LV_TOUCH_RA8875_ADC_CLOCK) 33 | #if LVGL_TOUCH_RA8875_WAKEUP_ENABLE 34 | #define TPCR0_VAL (0x08 | TPCR0_ADC_TIMING) 35 | #else 36 | #define TPCR0_VAL (TPCR0_ADC_TIMING) 37 | #endif 38 | 39 | #if LVGL_TOUCH_RA8875_EXTERNAL_VREF 40 | #if LVGL_TOUCH_RA8875_DEBOUNCE_ENABLE 41 | #define TPCR1_VAL (0x24) 42 | #else 43 | #define TPCR1_VAL (0x20) 44 | #endif 45 | #else 46 | #if LVGL_TOUCH_RA8875_DEBOUNCE_ENABLE 47 | #define TPCR1_VAL (0x04) 48 | #else 49 | #define TPCR1_VAL (0x00) 50 | #endif 51 | #endif 52 | 53 | /********************** 54 | * TYPEDEFS 55 | **********************/ 56 | 57 | /********************** 58 | * STATIC PROTOTYPES 59 | **********************/ 60 | 61 | static void ra8875_corr(int * x, int * y); 62 | 63 | /********************** 64 | * STATIC VARIABLES 65 | **********************/ 66 | 67 | /********************** 68 | * MACROS 69 | **********************/ 70 | 71 | /********************** 72 | * GLOBAL FUNCTIONS 73 | **********************/ 74 | 75 | void ra8875_touch_init(void) 76 | { 77 | struct { 78 | uint8_t cmd; // Register address of command 79 | uint8_t data; // Value to write to register 80 | } init_cmds[] = { 81 | {RA8875_REG_TPCR0, TPCR0_VAL}, // Touch Panel Control Register 0 (TPCR0) 82 | {RA8875_REG_TPCR1, TPCR1_VAL}, // Touch Panel Control Register 1 (TPCR1) 83 | }; 84 | #define INIT_CMDS_SIZE (sizeof(init_cmds)/sizeof(init_cmds[0])) 85 | 86 | ESP_LOGI(TAG, "Initializing RA8875 Touch..."); 87 | 88 | // Send all the commands 89 | for (unsigned int i = 0; i < INIT_CMDS_SIZE; i++) { 90 | ra8875_write_cmd(init_cmds[i].cmd, init_cmds[i].data); 91 | } 92 | ra8875_touch_enable(true); 93 | } 94 | 95 | void ra8875_touch_enable(bool enable) 96 | { 97 | ESP_LOGI(TAG, "%s touch.", enable ? "Enabling" : "Disabling"); 98 | uint8_t val = enable ? (0x80 | TPCR0_VAL) : (TPCR0_VAL); 99 | ra8875_write_cmd(RA8875_REG_TPCR0, val); 100 | } 101 | 102 | /** 103 | * Get the current position and state of the touchscreen 104 | * @param data store the read data here 105 | * @return false: because no more data to be read 106 | */ 107 | bool ra8875_touch_read(lv_indev_drv_t * drv, lv_indev_data_t * data) 108 | { 109 | static int x = 0; 110 | static int y = 0; 111 | 112 | int intr = ra8875_read_cmd(RA8875_REG_INTC2); // Interrupt Control Register2 (INTC2) 113 | 114 | data->state = (intr & INTC2_TP_INT) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; 115 | 116 | if (data->state == LV_INDEV_STATE_PR) { 117 | x = ra8875_read_cmd(RA8875_REG_TPXH); // Touch Panel X High Byte Data Register (TPXH) 118 | y = ra8875_read_cmd(RA8875_REG_TPYH); // Touch Panel Y High Byte Data Register (TPYH) 119 | int xy = ra8875_read_cmd(RA8875_REG_TPXYL); // Touch Panel X/Y Low Byte Data Register (TPXYL) 120 | 121 | x = (x << 2) | (xy & 0x03); 122 | y = (y << 2) | ((xy >> 2) & 0x03); 123 | 124 | #if DEBUG 125 | ESP_LOGI(TAG, "Touch Poll Raw: %d,%d", x, y); 126 | #endif 127 | 128 | // Convert to display coordinates 129 | ra8875_corr(&x, &y); 130 | 131 | // Clear interrupt 132 | ra8875_write_cmd(RA8875_REG_INTC2, INTC2_TP_INT); // Interrupt Control Register2 (INTC2) 133 | } 134 | 135 | data->point.x = x; 136 | data->point.y = y; 137 | 138 | #if DEBUG 139 | ESP_LOGI(TAG, "Touch Poll - Event: %d; %d,%d", data->state, data->point.x, data->point.y); 140 | #endif 141 | 142 | return false; 143 | } 144 | 145 | 146 | /********************** 147 | * STATIC FUNCTIONS 148 | **********************/ 149 | 150 | static void ra8875_corr(int * x, int * y) 151 | { 152 | #if RA8875_XY_SWAP != 0 153 | int tmp = *x; 154 | *x = *y; 155 | *y = tmp; 156 | #endif 157 | 158 | if ((*x) <= RA8875_X_MIN) { 159 | (*x) = 0; 160 | } else if ((*x) >= RA8875_X_MAX) { 161 | (*x) = LV_HOR_RES-1; 162 | } else { 163 | (*x) = (((*x) - RA8875_X_MIN) * (LV_HOR_RES-1)) / (RA8875_X_MAX - RA8875_X_MIN); 164 | } 165 | 166 | if ((*y) <= RA8875_Y_MIN) { 167 | (*y) = 0; 168 | } else if ((*y) >= RA8875_Y_MAX) { 169 | (*y) = LV_VER_RES-1; 170 | } else { 171 | (*y) = (((*y) - RA8875_Y_MIN) * (LV_VER_RES-1)) / (RA8875_Y_MAX - RA8875_Y_MIN); 172 | } 173 | 174 | #if RA8875_X_INV != 0 175 | (*x) = (LV_HOR_RES-1) - (*x); 176 | #endif 177 | 178 | #if RA8875_Y_INV != 0 179 | (*y) = (LV_VER_RES-1) - (*y); 180 | #endif 181 | } 182 | -------------------------------------------------------------------------------- /lvgl_touch/ra8875_touch.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file RA8875_TOUCH.h 3 | */ 4 | 5 | #ifndef RA8875X_TOUCH__H 6 | #define RA8875X_TOUCH__H 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /********************* 13 | * INCLUDES 14 | *********************/ 15 | 16 | #include 17 | #include 18 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 19 | #include "lvgl.h" 20 | #else 21 | #include "lvgl/lvgl.h" 22 | #endif 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | 28 | #define RA8875_X_MIN CONFIG_LV_TOUCH_X_MIN 29 | #define RA8875_Y_MIN CONFIG_LV_TOUCH_Y_MIN 30 | #define RA8875_X_MAX CONFIG_LV_TOUCH_X_MAX 31 | #define RA8875_Y_MAX CONFIG_LV_TOUCH_Y_MAX 32 | #define RA8875_X_INV CONFIG_LV_TOUCH_INVERT_X 33 | #define RA8875_Y_INV CONFIG_LV_TOUCH_INVERT_Y 34 | #define RA8875_XY_SWAP CONFIG_LV_TOUCH_XY_SWAP 35 | 36 | /********************** 37 | * TYPEDEFS 38 | **********************/ 39 | 40 | /********************** 41 | * GLOBAL PROTOTYPES 42 | **********************/ 43 | 44 | void ra8875_touch_init(void); 45 | void ra8875_touch_enable(bool enable); 46 | bool ra8875_touch_read(lv_indev_drv_t * drv, lv_indev_data_t * data); 47 | 48 | /********************** 49 | * MACROS 50 | **********************/ 51 | 52 | #ifdef __cplusplus 53 | } /* extern "C" */ 54 | #endif 55 | 56 | #endif /* RA8875_TOUCH__H */ 57 | -------------------------------------------------------------------------------- /lvgl_touch/stmpe610.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file STMPE610.c 3 | */ 4 | 5 | /********************* 6 | * INCLUDES 7 | *********************/ 8 | #include "stmpe610.h" 9 | #include "esp_system.h" 10 | #include "esp_log.h" 11 | #include "freertos/FreeRTOS.h" 12 | #include "freertos/task.h" 13 | #include "driver/gpio.h" 14 | #include "tp_spi.h" 15 | #include 16 | 17 | /********************* 18 | * DEFINES 19 | *********************/ 20 | #define TAG "STMPE610" 21 | 22 | 23 | /********************** 24 | * TYPEDEFS 25 | **********************/ 26 | 27 | /********************** 28 | * STATIC PROTOTYPES 29 | **********************/ 30 | static void write_8bit_reg(uint8_t reg, uint8_t val); 31 | static uint16_t read_16bit_reg(uint8_t reg); 32 | static uint8_t read_8bit_reg(uint8_t reg); 33 | static void read_data(int16_t *x, int16_t *y, uint8_t *z); 34 | static bool buffer_empty(); 35 | static void adjust_data(int16_t * x, int16_t * y); 36 | 37 | 38 | /********************** 39 | * STATIC VARIABLES 40 | **********************/ 41 | 42 | /********************** 43 | * MACROS 44 | **********************/ 45 | 46 | /********************** 47 | * GLOBAL FUNCTIONS 48 | **********************/ 49 | 50 | /** 51 | * Initialize the STMPE610 52 | */ 53 | void stmpe610_init(void) 54 | { 55 | uint8_t u8; 56 | uint16_t u16; 57 | 58 | ESP_LOGI(TAG, "Initialization."); 59 | 60 | // Get the initial SPI configuration 61 | //u8 = read_8bit_reg(STMPE_SPI_CFG); 62 | //ESP_LOGI(TAG, "SPI_CFG = 0x%x", u8); 63 | 64 | // Attempt a software reset 65 | write_8bit_reg(STMPE_SYS_CTRL1, STMPE_SYS_CTRL1_RESET); 66 | vTaskDelay(10 / portTICK_RATE_MS); 67 | 68 | // Reset the SPI configuration, making sure auto-increment is set 69 | u8 = read_8bit_reg(STMPE_SPI_CFG); 70 | write_8bit_reg(STMPE_SPI_CFG, u8 | STMPE_SPI_CFG_AA); 71 | u8 = read_8bit_reg(STMPE_SPI_CFG); 72 | ESP_LOGI(TAG, "SPI_CFG = 0x%x", u8); 73 | 74 | // Verify SPI communication 75 | u16 = read_16bit_reg(STMPE_CHIP_ID); 76 | if (u16 != 0x811) { 77 | ESP_LOGE(TAG, "Incorrect version: 0x%x", u16); 78 | } 79 | 80 | write_8bit_reg(STMPE_SYS_CTRL2, 0x00); // Disable clocks 81 | write_8bit_reg(STMPE_TSC_CTRL, 0); // Disable to allow writing 82 | 83 | write_8bit_reg(STMPE_TSC_CTRL, 84 | STEMP_TSC_CTRL_TRACK_0 | 85 | STMPE_TSC_CTRL_XYZ | 86 | STMPE_TSC_CTRL_EN); 87 | 88 | write_8bit_reg(STMPE_TSC_CFG, STMPE_TSC_CFG_4SAMPLE | 89 | STMPE_TSC_CFG_DELAY_1MS | 90 | STMPE_TSC_CFG_SETTLE_1MS); 91 | 92 | write_8bit_reg(STMPE_TSC_FRACTION_Z, 0x7); 93 | write_8bit_reg(STMPE_TSC_I_DRIVE, STMPE_TSC_I_DRIVE_50MA); 94 | 95 | write_8bit_reg(STMPE_SYS_CTRL2, 0x04); // GPIO clock off, TSC clock on, ADC clock on 96 | 97 | write_8bit_reg(STMPE_ADC_CTRL1, STMPE_ADC_CTRL1_12BIT | STMPE_ADC_CTRL1_80CLK); 98 | write_8bit_reg(STMPE_ADC_CTRL2, STMPE_ADC_CTRL2_3_25MHZ); 99 | 100 | write_8bit_reg(STMPE_GPIO_ALT_FUNCT, 0x00); // Disable GPIO 101 | 102 | write_8bit_reg(STMPE_FIFO_TH, 1); // Set FIFO threshold 103 | write_8bit_reg(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET); // Assert FIFO reset 104 | write_8bit_reg(STMPE_FIFO_STA, 0); // Deassert FIFO reset 105 | 106 | write_8bit_reg(STMPE_INT_EN, 0x00); // No interrupts 107 | write_8bit_reg(STMPE_INT_STA, 0xFF); // reset all ints 108 | } 109 | 110 | /** 111 | * Get the current position and state of the touchpad 112 | * @param data store the read data here 113 | * @return false: because no more data to be read 114 | */ 115 | bool stmpe610_read(lv_indev_drv_t * drv, lv_indev_data_t * data) 116 | { 117 | static int16_t last_x = 0; 118 | static int16_t last_y = 0; 119 | bool valid = true; 120 | int c = 0; 121 | int16_t x = 0; 122 | int16_t y = 0; 123 | uint8_t z; 124 | 125 | if ((read_8bit_reg(STMPE_TSC_CTRL) & STMPE_TSC_TOUCHED) == STMPE_TSC_TOUCHED) { 126 | // Making sure that we read all data and return the latest point 127 | while (!buffer_empty()) { 128 | read_data(&x, &y, &z); 129 | c++; 130 | } 131 | 132 | if (c > 0) { 133 | //ESP_LOGI(TAG, "%d: %d %d %d", c, x, y, z); 134 | 135 | adjust_data(&x, &y); 136 | last_x = x; 137 | last_y = y; 138 | //ESP_LOGI(TAG, " ==> %d %d", x, y); 139 | } 140 | 141 | z = read_8bit_reg(STMPE_INT_STA); // Clear interrupts 142 | z = read_8bit_reg(STMPE_FIFO_STA); 143 | if ((z & STMPE_FIFO_STA_OFLOW) == STMPE_FIFO_STA_OFLOW) { 144 | // Clear the FIFO if we discover an overflow 145 | write_8bit_reg(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET); 146 | write_8bit_reg(STMPE_FIFO_STA, 0); // unreset 147 | ESP_LOGE(TAG, "Fifo overflow"); 148 | } 149 | } 150 | 151 | if (c == 0) { 152 | x = last_x; 153 | y = last_y; 154 | valid = false; 155 | } 156 | 157 | data->point.x = (int16_t) x; 158 | data->point.y = (int16_t) y; 159 | data->state = valid == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR; 160 | 161 | return false; 162 | } 163 | 164 | 165 | /********************** 166 | * STATIC FUNCTIONS 167 | **********************/ 168 | static void write_8bit_reg(uint8_t reg, uint8_t val) 169 | { 170 | uint8_t data_send[2]; 171 | 172 | data_send[0] = reg; 173 | data_send[1] = val; 174 | tp_spi_write_reg(data_send, 2); 175 | } 176 | 177 | 178 | static uint16_t read_16bit_reg(uint8_t reg) 179 | { 180 | uint8_t data_recv[2]; 181 | 182 | tp_spi_read_reg(0x80 | reg, data_recv, 2); 183 | 184 | return data_recv[0] << 8 | data_recv[1]; 185 | } 186 | 187 | 188 | static uint8_t read_8bit_reg(uint8_t reg) 189 | { 190 | uint8_t data_recv; 191 | 192 | tp_spi_read_reg(0x80 | reg, &data_recv, 1); 193 | 194 | return data_recv; 195 | } 196 | 197 | 198 | static void read_data(int16_t *x, int16_t *y, uint8_t *z) 199 | { 200 | *x = read_16bit_reg(STMPE_TSC_DATA_X); 201 | *y = read_16bit_reg(STMPE_TSC_DATA_Y); 202 | *z = read_8bit_reg(STMPE_TSC_DATA_Z); 203 | } 204 | 205 | 206 | static bool buffer_empty() 207 | { 208 | return ((read_8bit_reg(STMPE_FIFO_STA) & STMPE_FIFO_STA_EMPTY) == STMPE_FIFO_STA_EMPTY); 209 | } 210 | 211 | 212 | static void adjust_data(int16_t * x, int16_t * y) 213 | { 214 | #if STMPE610_XY_SWAP != 0 215 | int16_t swap_tmp; 216 | swap_tmp = *x; 217 | *x = *y; 218 | *y = swap_tmp; 219 | #endif 220 | 221 | if((*x) > STMPE610_X_MIN)(*x) -= STMPE610_X_MIN; 222 | else(*x) = 0; 223 | 224 | if((*y) > STMPE610_Y_MIN)(*y) -= STMPE610_Y_MIN; 225 | else(*y) = 0; 226 | 227 | (*x) = (uint32_t)((uint32_t)(*x) * LV_HOR_RES) / 228 | (STMPE610_X_MAX - STMPE610_X_MIN); 229 | 230 | (*y) = (uint32_t)((uint32_t)(*y) * LV_VER_RES) / 231 | (STMPE610_Y_MAX - STMPE610_Y_MIN); 232 | 233 | #if STMPE610_X_INV != 0 234 | (*x) = LV_HOR_RES - (*x); 235 | #endif 236 | 237 | #if STMPE610_Y_INV != 0 238 | (*y) = LV_VER_RES - (*y); 239 | #endif 240 | 241 | } 242 | 243 | -------------------------------------------------------------------------------- /lvgl_touch/stmpe610.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file STMPE610.h 3 | */ 4 | 5 | #ifndef STMPE610_H 6 | #define STMPE610_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /********************* 13 | * INCLUDES 14 | *********************/ 15 | 16 | #include 17 | #include 18 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 19 | #include "lvgl.h" 20 | #else 21 | #include "lvgl/lvgl.h" 22 | #endif 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | /** 16-bit Chip Version **/ 28 | #define STMPE_CHIP_ID 0x00 29 | 30 | /** Reset Control **/ 31 | #define STMPE_SYS_CTRL1 0x03 32 | #define STMPE_SYS_CTRL1_RESET 0x02 33 | 34 | /** Clock Contrl **/ 35 | #define STMPE_SYS_CTRL2 0x04 36 | 37 | /** SPI Config **/ 38 | #define STMPE_SPI_CFG 0x08 39 | #define STMPE_SPI_CFG_MODE0 0x00 40 | #define STMPE_SPI_CFG_MODE1 0x01 41 | #define STMPE_SPI_CFG_MODE2 0x02 42 | #define STMPE_SPI_CFG_MODE3 0x03 43 | #define STMPE_SPI_CFG_AA 0x04 44 | 45 | /** Touchscreen controller setup **/ 46 | #define STMPE_TSC_CTRL 0x40 47 | #define STMPE_TSC_CTRL_EN 0x01 48 | #define STMPE_TSC_CTRL_XYZ 0x00 49 | #define STMPE_TSC_CTRL_XY 0x02 50 | #define STEMP_TSC_CTRL_TRACK_0 0x00 51 | #define STEMP_TSC_CTRL_TRACK_4 0x10 52 | #define STEMP_TSC_CTRL_TRACK_8 0x20 53 | #define STEMP_TSC_CTRL_TRACK_16 0x30 54 | #define STEMP_TSC_CTRL_TRACK_32 0x40 55 | #define STEMP_TSC_CTRL_TRACK_64 0x50 56 | #define STEMP_TSC_CTRL_TRACK_92 0x60 57 | #define STEMP_TSC_CTRL_TRACK_127 0x70 58 | #define STMPE_TSC_TOUCHED 0x80 59 | 60 | /** Interrupt control **/ 61 | #define STMPE_INT_CTRL 0x09 62 | #define STMPE_INT_CTRL_POL_HIGH 0x04 63 | #define STMPE_INT_CTRL_POL_LOW 0x00 64 | #define STMPE_INT_CTRL_EDGE 0x02 65 | #define STMPE_INT_CTRL_LEVEL 0x00 66 | #define STMPE_INT_CTRL_ENABLE 0x01 67 | #define STMPE_INT_CTRL_DISABLE 0x00 68 | 69 | /** Interrupt enable **/ 70 | #define STMPE_INT_EN 0x0A 71 | #define STMPE_INT_EN_TOUCHDET 0x01 72 | #define STMPE_INT_EN_FIFOTH 0x02 73 | #define STMPE_INT_EN_FIFOOF 0x04 74 | #define STMPE_INT_EN_FIFOFULL 0x08 75 | #define STMPE_INT_EN_FIFOEMPTY 0x10 76 | #define STMPE_INT_EN_ADC 0x40 77 | #define STMPE_INT_EN_GPIO 0x80 78 | 79 | /** Interrupt status **/ 80 | #define STMPE_INT_STA 0x0B 81 | #define STMPE_INT_STA_TOUCHDET 0x01 82 | 83 | /** ADC control **/ 84 | #define STMPE_ADC_CTRL1 0x20 85 | #define STMPE_ADC_CTRL1_INT 0x00 86 | #define STMPE_ADC_CTRL1_EXT 0x02 87 | #define STMPE_ADC_CTRL1_12BIT 0x08 88 | #define STMPE_ADC_CTRL1_10BIT 0x00 89 | #define STMPE_ADC_CTRL1_36CLK 0x00 90 | #define STMPE_ADC_CTRL1_44CLK 0x10 91 | #define STMPE_ADC_CTRL1_56CLK 0x20 92 | #define STMPE_ADC_CTRL1_64CLK 0x30 93 | #define STMPE_ADC_CTRL1_80CLK 0x40 94 | #define STMPE_ADC_CTRL1_96CLK 0x50 95 | #define STMPE_ADC_CTRL1_124CLK 0x60 96 | 97 | /** ADC control **/ 98 | #define STMPE_ADC_CTRL2 0x21 99 | #define STMPE_ADC_CTRL2_1_625MHZ 0x00 100 | #define STMPE_ADC_CTRL2_3_25MHZ 0x01 101 | #define STMPE_ADC_CTRL2_6_5MHZ 0x02 102 | 103 | /** Touchscreen controller configuration **/ 104 | #define STMPE_TSC_CFG 0x41 105 | #define STMPE_TSC_CFG_1SAMPLE 0x00 106 | #define STMPE_TSC_CFG_2SAMPLE 0x40 107 | #define STMPE_TSC_CFG_4SAMPLE 0x80 108 | #define STMPE_TSC_CFG_8SAMPLE 0xC0 109 | #define STMPE_TSC_CFG_DELAY_10US 0x00 110 | #define STMPE_TSC_CFG_DELAY_50US 0x08 111 | #define STMPE_TSC_CFG_DELAY_100US 0x10 112 | #define STMPE_TSC_CFG_DELAY_500US 0x18 113 | #define STMPE_TSC_CFG_DELAY_1MS 0x20 114 | #define STMPE_TSC_CFG_DELAY_5MS 0x28 115 | #define STMPE_TSC_CFG_DELAY_10MS 0x30 116 | #define STMPE_TSC_CFG_DELAY_50MS 0x38 117 | #define STMPE_TSC_CFG_SETTLE_10US 0x00 118 | #define STMPE_TSC_CFG_SETTLE_100US 0x01 119 | #define STMPE_TSC_CFG_SETTLE_500US 0x02 120 | #define STMPE_TSC_CFG_SETTLE_1MS 0x03 121 | #define STMPE_TSC_CFG_SETTLE_5MS 0x04 122 | #define STMPE_TSC_CFG_SETTLE_10MS 0x05 123 | #define STMPE_TSC_CFG_SETTLE_50MS 0x06 124 | #define STMPE_TSC_CFG_SETTLE_100MS 0x07 125 | 126 | /** FIFO level to generate interrupt **/ 127 | #define STMPE_FIFO_TH 0x4A 128 | 129 | /** Current filled level of FIFO **/ 130 | #define STMPE_FIFO_SIZE 0x4C 131 | 132 | /** Current status of FIFO **/ 133 | #define STMPE_FIFO_STA 0x4B 134 | #define STMPE_FIFO_STA_RESET 0x01 135 | #define STMPE_FIFO_STA_OFLOW 0x80 136 | #define STMPE_FIFO_STA_FULL 0x40 137 | #define STMPE_FIFO_STA_EMPTY 0x20 138 | #define STMPE_FIFO_STA_THTRIG 0x10 139 | 140 | /** Touchscreen controller drive I **/ 141 | #define STMPE_TSC_I_DRIVE 0x58 142 | #define STMPE_TSC_I_DRIVE_20MA 0x00 143 | #define STMPE_TSC_I_DRIVE_50MA 0x01 144 | 145 | /** Data port for TSC data address **/ 146 | #define STMPE_TSC_DATA_X 0x4D 147 | #define STMPE_TSC_DATA_Y 0x4F 148 | #define STMPE_TSC_DATA_Z 0x51 149 | #define STMPE_TSC_FRACTION_Z 0x56 150 | 151 | /** GPIO **/ 152 | #define STMPE_GPIO_SET_PIN 0x10 153 | #define STMPE_GPIO_CLR_PIN 0x11 154 | #define STMPE_GPIO_DIR 0x13 155 | #define STMPE_GPIO_ALT_FUNCT 0x17 156 | 157 | 158 | /** Calibration Constants **/ 159 | #define STMPE610_X_MIN CONFIG_LV_TOUCH_X_MIN 160 | #define STMPE610_Y_MIN CONFIG_LV_TOUCH_Y_MIN 161 | #define STMPE610_X_MAX CONFIG_LV_TOUCH_X_MAX 162 | #define STMPE610_Y_MAX CONFIG_LV_TOUCH_Y_MAX 163 | #define STMPE610_XY_SWAP CONFIG_LV_TOUCH_XY_SWAP 164 | #define STMPE610_X_INV CONFIG_LV_TOUCH_INVERT_X 165 | #define STMPE610_Y_INV CONFIG_LV_TOUCH_INVERT_Y 166 | 167 | /********************** 168 | * TYPEDEFS 169 | **********************/ 170 | 171 | /********************** 172 | * GLOBAL PROTOTYPES 173 | **********************/ 174 | void stmpe610_init(void); 175 | bool stmpe610_read(lv_indev_drv_t * drv, lv_indev_data_t * data); 176 | 177 | /********************** 178 | * MACROS 179 | **********************/ 180 | 181 | #ifdef __cplusplus 182 | } /* extern "C" */ 183 | #endif 184 | 185 | #endif /* STMPE610_H */ 186 | -------------------------------------------------------------------------------- /lvgl_touch/touch_driver.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file touch_driver.c 3 | */ 4 | 5 | #include "touch_driver.h" 6 | #include "tp_spi.h" 7 | 8 | 9 | void touch_driver_init(void) 10 | { 11 | #if defined (CONFIG_LV_TOUCH_CONTROLLER_XPT2046) 12 | xpt2046_init(); 13 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT6X06) 14 | ft6x06_init(FT6236_I2C_SLAVE_ADDR); 15 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_STMPE610) 16 | stmpe610_init(); 17 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_ADCRAW) 18 | adcraw_init(); 19 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X) 20 | /* nothing to do */ 21 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_RA8875) 22 | ra8875_touch_init(); 23 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_GT911) 24 | gt911_init(GT911_I2C_SLAVE_ADDR); 25 | #endif 26 | } 27 | 28 | #if LVGL_VERSION_MAJOR >= 8 29 | void touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data) 30 | #else 31 | bool touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data) 32 | #endif 33 | { 34 | bool res = false; 35 | 36 | #if defined (CONFIG_LV_TOUCH_CONTROLLER_XPT2046) 37 | res = xpt2046_read(drv, data); 38 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT6X06) 39 | res = ft6x36_read(drv, data); 40 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_STMPE610) 41 | res = stmpe610_read(drv, data); 42 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_ADCRAW) 43 | res = adcraw_read(drv, data); 44 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X) 45 | res = FT81x_read(drv, data); 46 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_RA8875) 47 | res = ra8875_touch_read(drv, data); 48 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_GT911) 49 | res = gt911_read(drv, data); 50 | #endif 51 | 52 | #if LVGL_VERSION_MAJOR >= 8 53 | data->continue_reading = res; 54 | #else 55 | return res; 56 | #endif 57 | } 58 | 59 | -------------------------------------------------------------------------------- /lvgl_touch/touch_driver.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file touch_driver.h 3 | */ 4 | 5 | #ifndef TOUCH_DRIVER_H 6 | #define TOUCH_DRIVER_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /********************* 13 | * INCLUDES 14 | *********************/ 15 | #include 16 | #include 17 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 18 | #include "lvgl.h" 19 | #else 20 | #include "lvgl/lvgl.h" 21 | #endif 22 | 23 | #if defined (CONFIG_LV_TOUCH_CONTROLLER_XPT2046) 24 | #include "xpt2046.h" 25 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT6X06) 26 | #include "ft6x36.h" 27 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_STMPE610) 28 | #include "stmpe610.h" 29 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_ADCRAW) 30 | #include "adcraw.h" 31 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X) 32 | #include "FT81x.h" 33 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_RA8875) 34 | #include "ra8875_touch.h" 35 | #elif defined (CONFIG_LV_TOUCH_CONTROLLER_GT911) 36 | #include "gt911.h" 37 | #endif 38 | 39 | /********************* 40 | * DEFINES 41 | *********************/ 42 | 43 | /********************** 44 | * GLOBAL PROTOTYPES 45 | **********************/ 46 | void touch_driver_init(void); 47 | 48 | #if LVGL_VERSION_MAJOR >= 8 49 | void touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data); 50 | #else 51 | bool touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data); 52 | #endif 53 | 54 | #ifdef __cplusplus 55 | } /* extern "C" */ 56 | #endif 57 | 58 | #endif /* TOUCH_DRIVER_H */ 59 | 60 | -------------------------------------------------------------------------------- /lvgl_touch/tp_spi.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file tp_spi.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "tp_spi.h" 10 | #include "touch_driver.h" 11 | #include "esp_system.h" 12 | #include "driver/gpio.h" 13 | #include "driver/spi_master.h" 14 | #include 15 | 16 | #include "../lvgl_helpers.h" 17 | #include "../lvgl_spi_conf.h" 18 | 19 | /********************* 20 | * DEFINES 21 | *********************/ 22 | 23 | /********************** 24 | * TYPEDEFS 25 | **********************/ 26 | 27 | 28 | /********************** 29 | * STATIC PROTOTYPES 30 | **********************/ 31 | static spi_device_handle_t spi; 32 | 33 | /********************** 34 | * STATIC VARIABLES 35 | **********************/ 36 | 37 | /********************** 38 | * MACROS 39 | **********************/ 40 | 41 | /********************** 42 | * GLOBAL FUNCTIONS 43 | **********************/ 44 | void tp_spi_add_device_config(spi_host_device_t host, spi_device_interface_config_t *devcfg) 45 | { 46 | esp_err_t ret=spi_bus_add_device(host, devcfg, &spi); 47 | assert(ret==ESP_OK); 48 | } 49 | 50 | void tp_spi_add_device(spi_host_device_t host) 51 | { 52 | spi_device_interface_config_t devcfg={ 53 | .clock_speed_hz = SPI_TOUCH_CLOCK_SPEED_HZ, 54 | .mode = SPI_TOUCH_SPI_MODE, 55 | .spics_io_num=TP_SPI_CS, //CS pin 56 | .queue_size=1, 57 | .pre_cb=NULL, 58 | .post_cb=NULL, 59 | .command_bits = 8, 60 | .address_bits = 0, 61 | .dummy_bits = 0, 62 | .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_NO_DUMMY, 63 | }; 64 | 65 | //Attach the Touch controller to the SPI bus 66 | tp_spi_add_device_config(host, &devcfg); 67 | } 68 | 69 | void tp_spi_xchg(uint8_t* data_send, uint8_t* data_recv, uint8_t byte_count) 70 | { 71 | spi_transaction_t t = { 72 | .length = byte_count * 8, // SPI transaction length is in bits 73 | .tx_buffer = data_send, 74 | .rx_buffer = data_recv}; 75 | 76 | esp_err_t ret = spi_device_transmit(spi, &t); 77 | assert(ret == ESP_OK); 78 | } 79 | 80 | void tp_spi_write_reg(uint8_t* data, uint8_t byte_count) 81 | { 82 | spi_transaction_t t = { 83 | .length = byte_count * 8, 84 | .tx_buffer = data, 85 | .flags = 0 86 | }; 87 | 88 | esp_err_t ret = spi_device_transmit(spi, &t); 89 | assert(ret == ESP_OK); 90 | } 91 | 92 | void tp_spi_read_reg(uint8_t reg, uint8_t* data, uint8_t byte_count) 93 | { 94 | spi_transaction_t t = { 95 | .length = (byte_count + sizeof(reg)) * 8, 96 | .rxlength = byte_count * 8, 97 | .cmd = reg, 98 | .rx_buffer = data, 99 | .flags = 0 100 | }; 101 | 102 | // Read - send first byte as command 103 | esp_err_t ret = spi_device_transmit(spi, &t); 104 | assert(ret == ESP_OK); 105 | } 106 | 107 | /********************** 108 | * STATIC FUNCTIONS 109 | **********************/ 110 | -------------------------------------------------------------------------------- /lvgl_touch/tp_spi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file tp_spi.h 3 | * 4 | */ 5 | 6 | #ifndef TP_SPI_H 7 | #define TP_SPI_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #include 17 | #include 18 | 19 | /********************* 20 | * DEFINES 21 | *********************/ 22 | 23 | /********************** 24 | * TYPEDEFS 25 | **********************/ 26 | 27 | /********************** 28 | * GLOBAL PROTOTYPES 29 | **********************/ 30 | void tp_spi_add_device(spi_host_device_t host); 31 | void tp_spi_add_device_config(spi_host_device_t host, spi_device_interface_config_t *config); 32 | void tp_spi_xchg(uint8_t* data_send, uint8_t* data_recv, uint8_t byte_count); 33 | void tp_spi_write_reg(uint8_t* data, uint8_t byte_count); 34 | void tp_spi_read_reg(uint8_t reg, uint8_t* data, uint8_t byte_count); 35 | 36 | /********************** 37 | * MACROS 38 | **********************/ 39 | 40 | 41 | #ifdef __cplusplus 42 | } /* extern "C" */ 43 | #endif 44 | 45 | #endif /*TP_SPI_H*/ 46 | -------------------------------------------------------------------------------- /lvgl_touch/xpt2046.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file XPT2046.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "xpt2046.h" 10 | #include "esp_system.h" 11 | #include "esp_log.h" 12 | #include "driver/gpio.h" 13 | #include "tp_spi.h" 14 | #include 15 | 16 | /********************* 17 | * DEFINES 18 | *********************/ 19 | #define TAG "XPT2046" 20 | 21 | #define CMD_X_READ 0b10010000 // NOTE: XPT2046 data sheet says this is actually Y 22 | #define CMD_Y_READ 0b11010000 // NOTE: XPT2046 data sheet says this is actually X 23 | #define CMD_Z1_READ 0b10110000 24 | #define CMD_Z2_READ 0b11000000 25 | 26 | /********************** 27 | * TYPEDEFS 28 | **********************/ 29 | typedef enum { 30 | TOUCH_NOT_DETECTED = 0, 31 | TOUCH_DETECTED = 1, 32 | } xpt2046_touch_detect_t; 33 | 34 | /********************** 35 | * STATIC PROTOTYPES 36 | **********************/ 37 | static void xpt2046_corr(int16_t * x, int16_t * y); 38 | static void xpt2046_avg(int16_t * x, int16_t * y); 39 | static int16_t xpt2046_cmd(uint8_t cmd); 40 | static xpt2046_touch_detect_t xpt2048_is_touch_detected(); 41 | 42 | /********************** 43 | * STATIC VARIABLES 44 | **********************/ 45 | int16_t avg_buf_x[XPT2046_AVG]; 46 | int16_t avg_buf_y[XPT2046_AVG]; 47 | uint8_t avg_last; 48 | 49 | /********************** 50 | * MACROS 51 | **********************/ 52 | 53 | /********************** 54 | * GLOBAL FUNCTIONS 55 | **********************/ 56 | 57 | /** 58 | * Initialize the XPT2046 59 | */ 60 | void xpt2046_init(void) 61 | { 62 | ESP_LOGI(TAG, "XPT2046 Initialization"); 63 | 64 | #if XPT2046_TOUCH_IRQ || XPT2046_TOUCH_IRQ_PRESS 65 | gpio_config_t irq_config = { 66 | .pin_bit_mask = BIT64(XPT2046_IRQ), 67 | .mode = GPIO_MODE_INPUT, 68 | .pull_up_en = GPIO_PULLUP_DISABLE, 69 | .pull_down_en = GPIO_PULLDOWN_DISABLE, 70 | .intr_type = GPIO_INTR_DISABLE, 71 | }; 72 | 73 | esp_err_t ret = gpio_config(&irq_config); 74 | assert(ret == ESP_OK); 75 | #endif 76 | } 77 | 78 | /** 79 | * Get the current position and state of the touchpad 80 | * @param data store the read data here 81 | * @return false: because no more data to be read 82 | */ 83 | bool xpt2046_read(lv_indev_drv_t * drv, lv_indev_data_t * data) 84 | { 85 | static int16_t last_x = 0; 86 | static int16_t last_y = 0; 87 | bool valid = false; 88 | 89 | int16_t x = last_x; 90 | int16_t y = last_y; 91 | if (xpt2048_is_touch_detected() == TOUCH_DETECTED) 92 | { 93 | valid = true; 94 | 95 | x = xpt2046_cmd(CMD_X_READ); 96 | y = xpt2046_cmd(CMD_Y_READ); 97 | ESP_LOGI(TAG, "P(%d,%d)", x, y); 98 | 99 | /*Normalize Data back to 12-bits*/ 100 | x = x >> 4; 101 | y = y >> 4; 102 | ESP_LOGI(TAG, "P_norm(%d,%d)", x, y); 103 | 104 | xpt2046_corr(&x, &y); 105 | xpt2046_avg(&x, &y); 106 | last_x = x; 107 | last_y = y; 108 | 109 | ESP_LOGI(TAG, "x = %d, y = %d", x, y); 110 | } 111 | else 112 | { 113 | avg_last = 0; 114 | } 115 | 116 | data->point.x = x; 117 | data->point.y = y; 118 | data->state = valid == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR; 119 | 120 | return false; 121 | } 122 | 123 | /********************** 124 | * STATIC FUNCTIONS 125 | **********************/ 126 | static xpt2046_touch_detect_t xpt2048_is_touch_detected() 127 | { 128 | // check IRQ pin if we IRQ or IRQ and preessure 129 | #if XPT2046_TOUCH_IRQ || XPT2046_TOUCH_IRQ_PRESS 130 | uint8_t irq = gpio_get_level(XPT2046_IRQ); 131 | 132 | if (irq != 0) { 133 | return TOUCH_NOT_DETECTED; 134 | } 135 | #endif 136 | // check pressure if we are pressure or IRQ and pressure 137 | #if XPT2046_TOUCH_PRESS || XPT2046_TOUCH_IRQ_PRESS 138 | int16_t z1 = xpt2046_cmd(CMD_Z1_READ) >> 3; 139 | int16_t z2 = xpt2046_cmd(CMD_Z2_READ) >> 3; 140 | 141 | // this is not what the confusing datasheet says but it seems to 142 | // be enough to detect real touches on the panel 143 | int16_t z = z1 + 4096 - z2; 144 | 145 | if (z < XPT2046_TOUCH_THRESHOLD) 146 | { 147 | return TOUCH_NOT_DETECTED; 148 | } 149 | #endif 150 | 151 | return TOUCH_DETECTED; 152 | } 153 | 154 | static int16_t xpt2046_cmd(uint8_t cmd) 155 | { 156 | uint8_t data[2]; 157 | tp_spi_read_reg(cmd, data, 2); 158 | int16_t val = (data[0] << 8) | data[1]; 159 | return val; 160 | } 161 | 162 | static void xpt2046_corr(int16_t * x, int16_t * y) 163 | { 164 | #if XPT2046_XY_SWAP != 0 165 | int16_t swap_tmp; 166 | swap_tmp = *x; 167 | *x = *y; 168 | *y = swap_tmp; 169 | #endif 170 | 171 | if((*x) > XPT2046_X_MIN)(*x) -= XPT2046_X_MIN; 172 | else(*x) = 0; 173 | 174 | if((*y) > XPT2046_Y_MIN)(*y) -= XPT2046_Y_MIN; 175 | else(*y) = 0; 176 | 177 | (*x) = (uint32_t)((uint32_t)(*x) * LV_HOR_RES) / 178 | (XPT2046_X_MAX - XPT2046_X_MIN); 179 | 180 | (*y) = (uint32_t)((uint32_t)(*y) * LV_VER_RES) / 181 | (XPT2046_Y_MAX - XPT2046_Y_MIN); 182 | 183 | #if XPT2046_X_INV != 0 184 | (*x) = LV_HOR_RES - (*x); 185 | #endif 186 | 187 | #if XPT2046_Y_INV != 0 188 | (*y) = LV_VER_RES - (*y); 189 | #endif 190 | 191 | 192 | } 193 | 194 | 195 | static void xpt2046_avg(int16_t * x, int16_t * y) 196 | { 197 | /*Shift out the oldest data*/ 198 | uint8_t i; 199 | for(i = XPT2046_AVG - 1; i > 0 ; i--) { 200 | avg_buf_x[i] = avg_buf_x[i - 1]; 201 | avg_buf_y[i] = avg_buf_y[i - 1]; 202 | } 203 | 204 | /*Insert the new point*/ 205 | avg_buf_x[0] = *x; 206 | avg_buf_y[0] = *y; 207 | if(avg_last < XPT2046_AVG) avg_last++; 208 | 209 | /*Sum the x and y coordinates*/ 210 | int32_t x_sum = 0; 211 | int32_t y_sum = 0; 212 | for(i = 0; i < avg_last ; i++) { 213 | x_sum += avg_buf_x[i]; 214 | y_sum += avg_buf_y[i]; 215 | } 216 | 217 | /*Normalize the sums*/ 218 | (*x) = (int32_t)x_sum / avg_last; 219 | (*y) = (int32_t)y_sum / avg_last; 220 | } 221 | -------------------------------------------------------------------------------- /lvgl_touch/xpt2046.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file XPT2046.h 3 | * 4 | */ 5 | 6 | #ifndef XPT2046_H 7 | #define XPT2046_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | 17 | #include 18 | #include 19 | #ifdef LV_LVGL_H_INCLUDE_SIMPLE 20 | #include "lvgl.h" 21 | #else 22 | #include "lvgl/lvgl.h" 23 | #endif 24 | 25 | /********************* 26 | * DEFINES 27 | *********************/ 28 | #define XPT2046_IRQ CONFIG_LV_TOUCH_PIN_IRQ 29 | 30 | #define XPT2046_AVG 4 31 | #define XPT2046_X_MIN CONFIG_LV_TOUCH_X_MIN 32 | #define XPT2046_Y_MIN CONFIG_LV_TOUCH_Y_MIN 33 | #define XPT2046_X_MAX CONFIG_LV_TOUCH_X_MAX 34 | #define XPT2046_Y_MAX CONFIG_LV_TOUCH_Y_MAX 35 | #define XPT2046_X_INV CONFIG_LV_TOUCH_INVERT_X 36 | #define XPT2046_Y_INV CONFIG_LV_TOUCH_INVERT_Y 37 | #define XPT2046_XY_SWAP CONFIG_LV_TOUCH_XY_SWAP 38 | #define XPT2046_TOUCH_THRESHOLD 400 // Threshold for touch detection 39 | #define XPT2046_TOUCH_IRQ CONFIG_LV_TOUCH_DETECT_IRQ 40 | #define XPT2046_TOUCH_IRQ_PRESS CONFIG_LV_TOUCH_DETECT_IRQ_PRESSURE 41 | #define XPT2046_TOUCH_PRESS CONFIG_LV_TOUCH_DETECT_PRESSURE 42 | 43 | /********************** 44 | * TYPEDEFS 45 | **********************/ 46 | 47 | /********************** 48 | * GLOBAL PROTOTYPES 49 | **********************/ 50 | void xpt2046_init(void); 51 | bool xpt2046_read(lv_indev_drv_t * drv, lv_indev_data_t * data); 52 | 53 | /********************** 54 | * MACROS 55 | **********************/ 56 | 57 | #ifdef __cplusplus 58 | } /* extern "C" */ 59 | #endif 60 | 61 | #endif /* XPT2046_H */ 62 | --------------------------------------------------------------------------------