Compare commits

..

121 commits

Author SHA1 Message Date
Carlos Diaz 1759b774a9
ST7789: LVGL rotation support (#182)
* TFT/Kconfig: Update orientation values

* ST7789: Use lv_disp_drv_t rotation field instead of the configured from menuconfig

* ST7789: Update orientation at runtime

* ST7789: Apply workaround to detect orientation change at runtime

* ST7789: Add helper to get display size in v7 and v8

* ST7789: Fix compilation errors

* ST7789: Handle rotation of display with 135x240 dimension

* ST7789: Handle v8 when getting lv_disp_t from lv_disp_drv_t
2022-05-12 22:15:34 -05:00
Rashed Talukder 8d9f6e2548
Update to support ESP-IDF v5 in develop branch (#186)
* Update to support ESP-IDF v5 in develop branch

* Remove the need for rom includes while providing IDF v5 compatibility

* Fix missing '(' typo

* Remove unnecessarily addded rom header files

* Add missing version include

* Fix another forgotten ')'
2022-05-12 22:15:06 -05:00
Tomas Rezucha bd8a7e3edd
Merge pull request #191 from tore-espressif/develop
Merge master into develop
2022-04-19 08:03:36 +02:00
Tomas Rezucha 9fd1634a08 ci: Update build job to v4.4 2022-04-11 16:14:36 +02:00
Tomas Rezucha ef108457c7 Merge branch 'master' into develop
Resolving conflicts
2022-04-11 10:28:15 +02:00
Carlos Diaz 7c6bdc5635
Allow user to configure custom SPI mode (#181)
Fixes #178
2022-02-15 00:51:37 -06:00
C47D fc81c6da5a README: Update peripherals and display gpios helpers 2022-02-02 21:28:34 -06:00
Carlos Diaz 28d663f6b6
Moving ESP-IDF specific files to lv_port (#175)
* Move disp_spi.c and tp_spi.c to lv_port

* Move esp_lcd_backlight to lv_port

* Move disp_spi.h and tp_spi.h to lv_port
2022-02-02 16:51:28 -06:00
Carlos Diaz 463721e291
Cleanup lvgl_helpers (#171)
* lvgl_spi_conf: Define TFT_SPI_HOST even when no SPI is choosen

* lvgl_helpers: Let the SPI driver choose SPI DMA Channel

Use SPI_DMA_CH1 only on ESP32 target.

* lvgl_helpers: Move FT81X initialization to helper

* lvgl_interface_init: Initial cleanup

* lvgl_helpers: Replace spi_common_dma_t values with integers

This enum was introduced in ESP-IDF v4.3 and can't be used in older versions
of ESP-IDF.

* lvgl_helpers: Rearrange includes

* lvgl_tft: Remove gpio_pad_select_gpio from drivers init functions

* lvgl_helpers: Use spi_host_device_t from v4.3 onwards

* esp_backlight: Replace gpio with esp_rom API

* il3820: Remove GPIO initialization from driver init

* FT81x: Replace gpio_pad_select_gpio with esp_rom alias

* Fix esp_rom_gpio.h path

* FT81x: Fix esp_rom_gpio.h path

* adcraw: Disable usage of gpio_pad_select_gpio

* GC9A01: Remove usage of gpio_pad_select_gpio

* ra8875: Remove usage of gpio_pad_select_gpio

* Revert "esp_backlight: Replace gpio with esp_rom API"

This reverts commit 24e4bf0b88.

* Revert "FT81x: Replace gpio_pad_select_gpio with esp_rom alias"

This reverts commit 8c7bc42140.

* esp_lcd_backlight: Handle different versions of ESP-IDF

* esp_lcd_backlight: Add missing header

* lvgl_spi_conf: Add missing include

* uc8151d/jd79653a: Fix compilation error when logging is enabled

* FT81x: Handle ESP-IDF v4.3 rom_gpio

* FT81x: Add missing include

* Compilation error when SPI Host is not selected

* lvgl_helpers.c: Enable init_ft81x only when FT81X is selected

* adcraw: Handle gpio_pad_selection on multiple ESP-IDF versions

* esp_lcd_backlight: Remove esp_rom functions

* FT81x: Remove esp_rom functions

* adcraw: Remove esp_rom functions
2022-02-02 16:45:52 -06:00
Carlos Diaz 8dda9ded4f
Cleanup lvgl_spi_config (#174)
* lvgl_spi_conf: Arrange SPI host pins section

* lvgl_spi_conf: Arrange touch pins section

* lvgl_spi_conf: Arrange SPI host section

* lvgl_spi_conf: Arrange SHARED_SPI_BUS section
2022-01-26 09:49:27 -06:00
C47D 9b4eedd00f disp_driver: Pass pointer to lv_disp_drv_t to pcd8544_init 2022-01-11 18:17:09 -06:00
C47D 6418f805bb display_config: Add missing defined 2022-01-11 18:15:22 -06:00
C47D 11f9c2b93f pcd8544: Update driver 2022-01-11 18:14:57 -06:00
C47D 6af2ab1f1c EVE_commands: Remove unused code 2022-01-07 18:30:56 -06:00
C47D 62704efd08 Remove semicolon from preprocessor 2022-01-07 17:38:08 -06:00
C47D ff055b629e ili9488: Fix typo 2022-01-07 17:27:12 -06:00
Carlos Diaz 17eb416ef8
Update helpers and drivers to handle LVGLv7 and v8 versions (#161)
* [lvgl_helpers] Cleanup and misc code cleanup

Checks for SPI_HOST_MAX symbol before using it.

Rename lvgl_driver_init to lvgl_interface_init because it now only initialize
the interface bus for display drivers, we still need to remove the indev
drivers from here.

Use types defined in spi_types.h for spi host (spi_host_device_t) and
spi dma channels (spi_dma_chan_t).

Also add a couple of symbols to avoid using magic numbers

* [lvgl_helpers] Reduce usage of if defined in lvgl_interface_init

* [lvgl_helpers] Fix spi dma channel for ESP-IDF versions <= 4.2

* [examples] Update hello_world to call lvgl_interface_init

* Add lvgl_get_display_buffer_size helper

This helper will allow us to get the calculated display buffer size instead of using a global symbol.

* Implement lvgl_get_display_buffer_size

This API will be used to get the calculation of display buffer size.

* Delete DISP_BUF_SIZE symbols

The same functionality is handled by lvgl_get_display_buffer_size

* Move SPI max transfer size calculation to helper

Use calculate_spi_max_transfer_size to calculate the SPI max transfer size for the SPI master configuration

* Remove SPI_BUS_MAX_TRANSFER_SZ definition

Same functionality is now handled in calculate_spi_max_transfer_size

* Update display buffer size calculation

Use lvgl_get_display_buffer_size helper instead of DISP_BUF_SIZE symbol

* Update example to LVGL v8

Add comments about changes from:
- LVGL v7 to LVGL v8
- Configuration helpers and display drivers

* Update lvgl_helpers.c

* Update sh1107 driver

* Update EVE driver

Check for symbols used in previous implementations before trying to use them
and add a fallback temporary implementation when not found.

The falback implementation isn't tested with hardware.

Symbols:
- DISP_BUF_SIZE
- SPI_TRANSFER_SIZE

* Update uc8151d driver

* Update jd79653a driver

* Update ra8875 driver

* Update il3820.h

Check for LV_HOR_RES_MAX and LV_VER_RES_MAX before trying to use them

* Update lvgl_helpers.c

Check for ESP-IDF version before trying to use spi_dma_chan_t type
2022-01-07 17:22:11 -06:00
C47D bb0e3a1f27 Check for LV_USE_LOG when logging orientation 2022-01-07 15:26:39 -06:00
C47D dcff9a7f11 ili9481: Add missing braces 2022-01-07 15:26:39 -06:00
C47D f669a09b19 jd79653a: Remove unused code 2022-01-07 15:26:39 -06:00
C47D d0376e705c uc8151d: Remove unused code 2022-01-07 15:26:39 -06:00
C47D 35d2d3a5af Add LV_DISP_USE_BUSY symbol to enable busy signal 2022-01-07 13:23:28 -06:00
C47D 9ee177b684 ST7789: Display offsets are now runtime configurable
We don't change previous functionality by adding a helper function that sets the user offsets when initializing the display
2022-01-07 13:23:28 -06:00
Carlos Diaz 31399e012a Make SPI3 not available for ESP32C3
The ESP32C3 device doesn't have SPI3
2022-01-06 18:53:34 -06:00
Carlos Diaz 79d8989b2a Update display Kconfig
Remove IDF_TARGET_ESP32S2 checks on TFT SPI Bus choice
2022-01-06 18:53:34 -06:00
C47D 1a8a610b05 Display Kconfig: Fix TTGO default SPI bus and display orientation checks 2022-01-06 18:53:34 -06:00
arktrin 26272b08f0 clarify the 52/53 px offset oddity 2022-01-05 23:47:03 -06:00
arktrin fbb4ebe409 add offset for 240x135 displays based on ST7789 2022-01-05 23:46:35 -06:00
arktrin a2a13f1a5f replace hardcoded SPI DMA parameter 2022-01-05 23:46:10 -06:00
arktrin b9377200a6 fix SPI names for touch
with ESP32-C3 specific auto-dma proper selection
2022-01-05 23:45:54 -06:00
Carlos Diaz c78e9fe169
Migrate hello_world example to LVGL v8
Update example to LVGL v8.
2021-12-29 23:10:08 -06:00
Tomas Rezucha d0eca96cd7 fix SPI names 2021-12-16 13:40:00 +01:00
Tomas Rezucha 385421fe06
Merge branch 'master' into develop 2021-12-14 17:46:46 +01:00
Carlos Diaz c7607e93d8
ili9488: Start updating to new display port interface (#137)
ILI9488: Start updating to new display port interface
2021-11-17 21:00:07 -06:00
Rashed Talukder 2dad083264 Extern the queue handle and add definition in source file. Add macro condition for dependencies. 2021-10-27 19:12:09 -05:00
Rashed Talukder ac6cde35c9 Add kconfig symbol for optional coordinates queue 2021-10-27 19:10:31 -05:00
Rashed Talukder 919d644dc8 Add touch input values to a FreeRTOS queue 2021-10-27 19:07:41 -05:00
Rop Gonggrijp 3625deb36d Addresses confusion: I2C manager component install only when others need I2C too.
See #115
2021-10-22 18:57:08 -05:00
Rop Gonggrijp 86e3f259ba Fixes potential ESP-IDF config editor crash (#115) 2021-10-22 18:56:59 -05:00
Carlos Diaz ec944af90f
Merge pull request #131 from lvgl/fix/use_lvgl_logging
Replace ESP_LOG with LVGL logging
2021-10-22 18:51:15 -05:00
C47D ea37784f08 Remove TAG from LVGL log API in touch drivers
The filename is appended at the beginning of the log output by default, we don't need to do it.
2021-10-22 18:45:52 -05:00
C47D a0e915eebc Remove TAG from LVGL log API
The filename is appended at the beginning of the log output by default, we don't need to do it.
2021-10-22 18:41:47 -05:00
C47D 9c886307b2 xpt2046: Replace ESP_LOG with LVGL logging 2021-10-13 23:32:12 -05:00
C47D 1ededabf99 stmpe610: Replace ESP_LOG with LVGL logging 2021-10-13 23:30:45 -05:00
C47D 6b6b756da3 ra8875: Replace ESP_LOG with LVGL logging 2021-10-13 23:29:34 -05:00
C47D 18569b6c17 gt911: Replace ESP_LOG with LVGL logging 2021-10-13 23:28:50 -05:00
C47D 5d55edc37c ft6x36: Replace ESP_LOG with LVGL logging 2021-10-13 23:27:31 -05:00
C47D 4a9cfeb6fb EVE_commands: Replace ESP_LOG with LVGL logging 2021-10-13 23:23:56 -05:00
C47D 83875cc6bd hx8357: Replace ESP_LOG with LVGL logging 2021-10-13 23:21:40 -05:00
C47D 94244ad432 il3820: Replace ESP_LOG with LVGL logging 2021-10-13 23:20:31 -05:00
C47D 44b552758e ili9163c: Replace ESP_LOG with LVGL logging 2021-10-13 23:19:51 -05:00
C47D b9c381a07d ili9488: Replace ESP_LOG with LVGL logging 2021-10-13 23:17:24 -05:00
C47D e51f475263 ili9486: Replace ESP_LOG with LVGL logging 2021-10-13 23:15:27 -05:00
C47D e1c18c13b9 jd79653a: Replace ESP_LOG with LVGL logging 2021-10-13 23:14:03 -05:00
C47D 83d5486207 uc8151d: Remove typo 2021-10-13 23:09:17 -05:00
C47D 1a8d0d91e2 ra8875: Replace ESP_LOG with LVGL logging 2021-10-13 23:04:44 -05:00
C47D 81abc17904 st7735s: Replace ESP_LOG with LVGL logging 2021-10-13 23:02:47 -05:00
C47D ef0946a6cc st7796s: Replace ESP_LOG with LVGL logging 2021-10-13 23:01:26 -05:00
C47D f1e1f0d9fd uc8151d: Replace ESP_LOG with LVGL logging 2021-10-13 23:00:18 -05:00
C47D 12cf92da81 Merge branch 'develop' into fix/use_lvgl_logging 2021-10-13 22:55:11 -05:00
C47D d116dfd87d display_bsp_init_io: Fix macro names must be identifiers 2021-10-13 22:54:54 -05:00
C47D 6a76078ba8 ili9481: Fix TAG 2021-10-13 22:53:00 -05:00
C47D 5fbce2a3bf Merge branch 'develop' into fix/use_lvgl_logging 2021-10-13 22:47:33 -05:00
C47D 0b8d488867 Check for CONFIG_LV_DISP_PIN_BCKL before using it 2021-10-13 22:47:12 -05:00
C47D 364349dbf8 ili9481: Replace ESP_LOG with LVGL logging 2021-10-13 22:43:57 -05:00
C47D 4b01564076 ili9481: Replace ESP_LOG with LVGL logging 2021-10-13 22:39:32 -05:00
Carlos Diaz f7b34f8a3e
Merge pull request #125 from lvgl/fix/update_ili9341
ili9341: Update driver to use new port interface
2021-10-13 19:19:03 -05:00
Carlos Diaz 3d775fadd1
Merge pull request #127 from lvgl/fix/dont_use_rst_when_not_defined
Fix compilation break when hardware reset is not enabled
2021-10-13 19:16:37 -05:00
Carlos Diaz 0a924fc1b6
Merge pull request #129 from lvgl/feat/add_gpio_helper
Update (initialization) helpers
2021-10-13 19:15:22 -05:00
C47D 4255e3005b feat(lvgl_helpers): Add function to initialize GPIOs
Adds helper function to initialize GPIOs, this avoids having to configure and initialize GPIOs in the drivers init function.

Closes #128
2021-10-06 23:17:03 -05:00
C47D 52f89b10e1 fix(uc8151d): Fix break when hardware reset is disabled
CONFIG_LV_DISP_USE_RST is not defined when hardware reset is disabled
2021-10-05 18:58:47 -05:00
C47D 3b33c04585 fix(jd79653a): Fix break when hardware reset is disabled
CONFIG_LV_DISP_USE_RST is not defined when hardware reset is disabled
2021-10-05 18:58:29 -05:00
C47D 152582e9f8 fix(ili9163c): Fix break when hardware reset is disabled
CONFIG_LV_DISP_USE_RST is not defined when hardware reset is disabled
2021-10-05 18:57:58 -05:00
C47D f7164ff22a ili9341: Update driver to use new port interface 2021-10-05 00:03:02 -05:00
Carlos Diaz f6999a52fe
Merge pull request #112 from lvgl/feat-add_busy_signal_handler_to_generic_driver
feat(lv_port): Add abstraction for busy signal
2021-10-01 15:11:47 -05:00
C47D d627884887 Replace display_port_busy_t with bool 2021-10-01 12:11:28 -05:00
C47D e5b7ef9de2 FT6X36: Fix coordinates invesion
The coordinates need to be swapped before inveting them when swapping is enabled.

Suggested in #118 by @wreyford
2021-09-28 20:58:56 -05:00
C47D 3c5a4061d9 feat(lv_port): Add abstraction for busy signal
This signal can be used when driving eink displays
2021-09-18 20:14:35 -05:00
Carlos Diaz 2006d5e449
Merge pull request #92 from lvgl/feat-mcu_independent_bsp
Display hardware abstraction for IOs
2021-09-17 21:50:38 -05:00
C47D cd999e34cd fix(lvgl_helpers): Remove all references to disp_driver_init in lvgl_driver_init 2021-09-14 19:13:42 -05:00
C47D 85f70cb688 feat(disp_driver): Move backlight configuration to it's own API 2021-09-14 19:13:42 -05:00
C47D 3980e51f07 fix(st7789): Remove backlight control from driver
Use backlight control introduced in #95
2021-09-14 19:13:41 -05:00
C47D 9d9fadf450 fix(display_port): Rename display_hal_* to display_port_*
Also updates the display drivers that used it
2021-09-14 19:13:41 -05:00
C47D 359dcb92ba feat(st7789.c): Add delay after sending software reset command 2021-09-14 19:13:40 -05:00
C47D 20438187b1 Revert "feat(st7789.c): Initial support for display rotation control using LVGL"
This reverts commit 704f9a2c7f65dac47ba9b1a69aaf4d8dfe5c53ee.
2021-09-14 19:13:39 -05:00
C47D 0e29128b3b feat(st7789.c): Initial support for display rotation control using LVGL 2021-09-14 19:13:39 -05:00
C47D ffae578a39 chore(st7789.h): Add note to st7789_update_cb 2021-09-14 19:13:38 -05:00
C47D 9b1e3d1198 fix(disp_driver): Update disp_driver_init API signature
The signature was changed when I was rebasing master into this branch, this commit fixes it :)
2021-09-14 19:13:37 -05:00
C47D 2134cdcfb5 fix(st7789.h): Add missing ; to st7789_update_cb 2021-09-14 19:13:37 -05:00
C47D b6e1f91ed1 ST7789: Use new configuration option for software reset 2021-09-14 19:13:36 -05:00
C47D 2a3157b8fc ST7789: Move configuration to display_config.h 2021-09-14 19:13:36 -05:00
C47D d79b68bdf6 ST7789: Cleanup
Remove logging and unneccesary includes
2021-09-14 19:13:35 -05:00
C47D dfe54e8573 ST7789: Add template for update_cb
We might use this callback to be able to rotate the display at runtime using the displa controller configuration bytes
2021-09-14 19:13:34 -05:00
C47D 83c08f6a2a st7789: Remove unused symbols
Removed `ST7789_DC` and `ST7789_RST` symbols as they are no longer used.
2021-09-14 19:13:34 -05:00
C47D f6307afabc Rename display_espressif_hal.c to lv_port_display_espressif.c 2021-09-14 19:13:33 -05:00
C47D c797562321 port; Move display_espressif_hal to new lv_port directory 2021-09-14 19:13:33 -05:00
C47D aa8a78f72a helpers: Remove display initialization when using SPI 2021-09-14 19:13:32 -05:00
C47D 64832c4136 fix(st7789): Remove extra parameter on disp_spi_send_colors and disp_spi_send_data 2021-09-14 19:13:32 -05:00
C47D e314c7563b disp_driver: Add pointer to lv_disp_drv_t as parameter to disp_driver_init 2021-09-14 19:13:31 -05:00
C47D 0c6975954f helpers: Remove display initialization from lvgl_driver_init 2021-09-14 19:13:31 -05:00
C47D 0ae3f76097 hal: Fix typo on function signatures 2021-09-14 19:13:30 -05:00
C47D 37da744873 cmake: Add initial display hal implementation for espressif MCUs to the build 2021-09-14 19:13:30 -05:00
C47D 0f1a6d490e Add pointer to lv_disp_drv_t as first parameter to HAL functions 2021-09-14 19:13:29 -05:00
C47D 413721182c Remove GPIO initialization from display init, they must be initialized by the user in main.c 2021-09-14 19:13:28 -05:00
C47D 7cebfdd671 Rename display_bsp to display_hal
The implementation of display hal is MCU dependant, in this example we implement it using the ESP-IDF framework
2021-09-14 19:13:28 -05:00
C47D 2629b6d86a Update to use display_bsp 2021-09-14 19:13:27 -05:00
C47D 6122d139de display_bsp: Move IO initialization here 2021-09-14 19:13:26 -05:00
C47D 49a3ba84b4 display bsp: Move ESP32 pin specific code to display_bsp 2021-09-14 19:13:26 -05:00
C47D 0b09769dcc ST7789: Hardware abstraction layer prototype 2021-09-14 19:13:25 -05:00
Kevin Sidwar 31f340d864 Change config naming for ssd1306 to use LV_ prefix 2021-09-14 19:13:25 -05:00
Kevin Sidwar 7c956f1442 Fix orientation config define 2021-09-14 19:13:24 -05:00
chenghongyao e3347e3cb5 fix data length overflow 2021-09-14 19:13:24 -05:00
Tomas Rezucha 56208791b2
Merge pull request #100 from lvgl/feature/examples-folder
Examples folder and build
2021-08-25 16:07:02 +02:00
Tomas Rezucha 7d9527b6e1 Add automated build of examples 2021-08-11 22:35:49 +02:00
Tomas Rezucha 568dce244a Add OLED example project 2021-08-11 22:30:02 +02:00
Tomas Rezucha 40ec379b2d Merge branch 'fix/backlight-off' into develop 2021-08-11 22:29:24 +02:00
Tomas Rezucha 72a5d3da79 Merge branch 'fix/backlight-off' into develop 2021-08-11 21:02:57 +02:00
Tomas Rezucha 4e0355ec30 Fix RA8875 build with monochrome settings 2021-08-11 09:45:28 +02:00
Tomas Rezucha 280bebf52e
Merge pull request #96 from lvgl/feature/build-all-drivers
Build all display drivers
2021-08-10 07:37:11 +02:00
Tomas Rezucha 01dc1259f8 Don't fire compiler warnings on missing driver configuration 2021-08-04 10:11:18 +02:00
Tomas Rezucha 803c58774c Remove display driver dependancies on Kconfig 2021-08-04 09:48:06 +02:00
61 changed files with 2056 additions and 1445 deletions

31
.github/workflows/build_examples.yml vendored Normal file
View file

@ -0,0 +1,31 @@
name: 'build'
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
idf_ver: ["v4.1", "v4.2", "v4.3", "v4.4"]
idf_target: ["esp32", "esp32s2", "esp32c3"]
exclude:
- idf_ver: "v4.1"
idf_target: esp32s2
- idf_ver: "v4.1"
idf_target: esp32c3
- idf_ver: "v4.2"
idf_target: esp32c3
runs-on: ubuntu-20.04
container: espressif/idf:release-${{ matrix.idf_ver }}
steps:
- uses: actions/checkout@v1
with:
submodules: recursive
- name: Build ESP examples
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
run: |
cd examples/wemos_lolin_oled/hello_world
. ${IDF_PATH}/export.sh
idf.py build

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "examples/common_components/lvgl"]
path = examples/common_components/lvgl
url = https://github.com/lvgl/lvgl.git

View file

@ -3,55 +3,38 @@ if(ESP_PLATFORM)
file(GLOB SOURCES *.c) file(GLOB SOURCES *.c)
set(LVGL_INCLUDE_DIRS . lvgl_tft) set(LVGL_INCLUDE_DIRS . lvgl_tft)
list(APPEND SOURCES "lvgl_tft/disp_driver.c") list(APPEND SOURCES "lvgl_tft/disp_driver.c")
list(APPEND SOURCES "lvgl_tft/esp_lcd_backlight.c") list(APPEND SOURCES "lv_port/esp_lcd_backlight.c")
# Include only the source file of the selected # This are the source files used for mcu abstraction
# display controller. set(LV_PORT_PATH "lv_port")
if(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341)
list(APPEND SOURCES "${LV_PORT_PATH}/lv_port_display_espressif.c")
#@todo add SimleInclude macro here
# Build all display drivers
list(APPEND SOURCES "lvgl_tft/ili9341.c") list(APPEND SOURCES "lvgl_tft/ili9341.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481)
list(APPEND SOURCES "lvgl_tft/ili9481.c") list(APPEND SOURCES "lvgl_tft/ili9481.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486)
list(APPEND SOURCES "lvgl_tft/ili9486.c") list(APPEND SOURCES "lvgl_tft/ili9486.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488)
list(APPEND SOURCES "lvgl_tft/ili9488.c") list(APPEND SOURCES "lvgl_tft/ili9488.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789)
list(APPEND SOURCES "lvgl_tft/st7789.c") list(APPEND SOURCES "lvgl_tft/st7789.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S)
list(APPEND SOURCES "lvgl_tft/st7735s.c") list(APPEND SOURCES "lvgl_tft/st7735s.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S)
list(APPEND SOURCES "lvgl_tft/st7796s.c") list(APPEND SOURCES "lvgl_tft/st7796s.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357)
list(APPEND SOURCES "lvgl_tft/hx8357.c") list(APPEND SOURCES "lvgl_tft/hx8357.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107)
list(APPEND SOURCES "lvgl_tft/sh1107.c") list(APPEND SOURCES "lvgl_tft/sh1107.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306)
list(APPEND SOURCES "lvgl_tft/ssd1306.c") list(APPEND SOURCES "lvgl_tft/ssd1306.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
list(APPEND SOURCES "lvgl_tft/EVE_commands.c") list(APPEND SOURCES "lvgl_tft/EVE_commands.c")
list(APPEND SOURCES "lvgl_tft/FT81x.c") list(APPEND SOURCES "lvgl_tft/FT81x.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820)
list(APPEND SOURCES "lvgl_tft/il3820.c") list(APPEND SOURCES "lvgl_tft/il3820.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A)
list(APPEND SOURCES "lvgl_tft/jd79653a.c") list(APPEND SOURCES "lvgl_tft/jd79653a.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D)
list(APPEND SOURCES "lvgl_tft/uc8151d.c") list(APPEND SOURCES "lvgl_tft/uc8151d.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875)
list(APPEND SOURCES "lvgl_tft/ra8875.c") list(APPEND SOURCES "lvgl_tft/ra8875.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01)
list(APPEND SOURCES "lvgl_tft/GC9A01.c") list(APPEND SOURCES "lvgl_tft/GC9A01.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C)
list(APPEND SOURCES "lvgl_tft/ili9163c.c") list(APPEND SOURCES "lvgl_tft/ili9163c.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544)
list(APPEND SOURCES "lvgl_tft/pcd8544.c") list(APPEND SOURCES "lvgl_tft/pcd8544.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_SCHMITT)
list(APPEND SOURCES "lvgl_tft/schmitt.c")
else()
message(WARNING "LVGL ESP32 drivers: Display controller not defined.")
endif()
if(CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI) if(CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI)
list(APPEND SOURCES "lvgl_tft/disp_spi.c") list(APPEND SOURCES "lv_port/disp_spi.c")
endif() endif()
# Add touch driver to compilation only if it is selected in menuconfig # Add touch driver to compilation only if it is selected in menuconfig
@ -78,7 +61,7 @@ if(CONFIG_LV_TOUCH_CONTROLLER)
endif() endif()
if(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI) if(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI)
list(APPEND SOURCES "lvgl_touch/tp_spi.c") list(APPEND SOURCES "lv_port/tp_spi.c")
endif() endif()
endif() endif()
@ -86,9 +69,11 @@ if(CONFIG_LV_I2C)
list(APPEND SOURCES "lvgl_i2c/i2c_manager.c") list(APPEND SOURCES "lvgl_i2c/i2c_manager.c")
endif() endif()
list(APPEND LVGL_INCLUDE_DIRS lv_port)
idf_component_register(SRCS ${SOURCES} idf_component_register(SRCS ${SOURCES}
INCLUDE_DIRS ${LVGL_INCLUDE_DIRS} INCLUDE_DIRS ${LVGL_INCLUDE_DIRS}
REQUIRES lvgl driver esp_common log freertos esp_rom soc) REQUIRES lvgl)
target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DLV_LVGL_H_INCLUDE_SIMPLE") target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DLV_LVGL_H_INCLUDE_SIMPLE")

View file

@ -12,6 +12,11 @@ For a ready to use ESP32 project take look at the [lv_port_esp32](https://github
**NOTE:** You need to set the display horizontal and vertical size, color depth and **NOTE:** You need to set the display horizontal and vertical size, color depth and
swap of RGB565 color on the LVGL configuration menuconfig (it's not handled automatically). swap of RGB565 color on the LVGL configuration menuconfig (it's not handled automatically).
## MCU Configuration
Example of SPI/I2C configuration peripherals is done with `lvgl_interface_init`.
Example of display gpios configuration, such as the DC, RST, Backlight is done with `lvgl_display_gpios_init`
## Supported display controllers ## Supported display controllers

43
display_config.h Normal file
View file

@ -0,0 +1,43 @@
#ifndef DISPLAY_CONFIG_H_
#define DISPLAY_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "sdkconfig.h"
/* Configuration options for ST7789 display controllers */
#if defined CONFIG_LV_DISP_USE_RST
#if defined CONFIG_LV_DISP_ST7789_SOFT_RESET
#define ST7789_SOFT_RST
#endif
#else
#define ST7789_SOFT_RST
#endif
#if defined (CONFIG_LV_INVERT_COLORS)
#define ST7789_INVERT_COLORS 1U
#define ILI9341_INVERT_COLORS 1U
#endif
#define ST7789_INITIAL_ORIENTATION CONFIG_LV_DISPLAY_ORIENTATION
#if CONFIG_LV_DISP_USE_RST
#define ILI9341_USE_RST
#endif
#define ILI9341_INITIAL_ORIENTATION CONFIG_LV_DISPLAY_ORIENTATION
/* ILI9488 Configuration */
#if CONFIG_LV_DISP_USE_RST
#define ILI9488_USE_RST
#endif
#define ILI9488_INITIAL_ORIENTATION CONFIG_LV_DISPLAY_ORIENTATION
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* DISPLAY_CONFIG_H_ */

@ -0,0 +1 @@
Subproject commit 2e942060f077de19667ec200afcfd2b32352064b

View file

@ -0,0 +1,9 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS ../../common_components ../../..)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(hello_world)

View file

@ -0,0 +1,2 @@
idf_component_register(SRCS "hello_world.c"
INCLUDE_DIRS ".")

View file

@ -0,0 +1,110 @@
/* Hello world on Wemos Lolin32 board
*
* This example code is in the Public Domain (or CC0 licensed, at your option.)
*
* Unless required by applicable law or agreed to in writing, this
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_freertos_hooks.h"
#include "freertos/semphr.h"
#include "esp_system.h"
#include "driver/gpio.h"
/* Littlevgl specific */
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#include "lvgl_helpers.h"
/*********************
* DEFINES
*********************/
#define LV_TICK_PERIOD_MS 1
/**********************
* STATIC PROTOTYPES
**********************/
static void lvgl_tick_inc(void *arg);
static void guiTask(void *pvParameter);
/**********************
* APPLICATION MAIN
**********************/
void app_main()
{
xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 0, NULL, 1);
}
static void guiTask(void *pvParameter)
{
(void) pvParameter;
lv_init();
/* Initialize the needed peripherals */
lvgl_interface_init();
/* Initialize needed GPIOs, e.g. backlight, reset GPIOs */
lvgl_display_gpios_init();
/* ToDo Initialize used display driver passing registered lv_disp_drv_t as parameter */
size_t display_buffer_size = lvgl_get_display_buffer_size();
lv_color_t* buf1 = heap_caps_malloc(display_buffer_size * sizeof(lv_color_t), MALLOC_CAP_DMA);
assert(buf1 != NULL);
static lv_disp_draw_buf_t disp_buf;
lv_disp_draw_buf_init(&disp_buf, buf1, NULL, display_buffer_size * 8);
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.flush_cb = disp_driver_flush;
disp_drv.rounder_cb = disp_driver_rounder;
disp_drv.set_px_cb = disp_driver_set_px;
disp_drv.draw_buf = &disp_buf;
/* LVGL v8: Set display horizontal and vertical resolution (in pixels), it's no longer done with lv_conf.h */
disp_drv.hor_res = 128u;
disp_drv.ver_res = 64u;
lv_disp_drv_register(&disp_drv);
/* Create and start a periodic timer interrupt to call lv_tick_inc */
const esp_timer_create_args_t periodic_timer_args = {
.callback = &lvgl_tick_inc,
.name = "lvgl_tick"
};
esp_timer_handle_t periodic_timer;
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, LV_TICK_PERIOD_MS * 1000));
/* Create a Hellow World label on the currently active screen */
lv_obj_t *scr = lv_disp_get_scr_act(NULL);
/* LVGL v8 lv_label_create no longer takes 2 parameters */
lv_obj_t *label1 = lv_label_create(scr);
lv_label_set_text(label1, "Hello\nworld");
/* Align the Label to the center
* NULL means align on parent (which is the screen now)
* 0, 0 at the end means an x, y offset after alignment*/
lv_obj_align(label1, LV_ALIGN_CENTER, 0, 0);
while (1) {
vTaskDelay(pdMS_TO_TICKS(10));
lv_task_handler();
}
free(buf1);
}
static void lvgl_tick_inc(void *arg) {
(void) arg;
lv_tick_inc(LV_TICK_PERIOD_MS);
}

View file

@ -0,0 +1,11 @@
CONFIG_LV_HOR_RES_MAX=128
CONFIG_LV_VER_RES_MAX=64
CONFIG_LV_COLOR_DEPTH_1=y
CONFIG_LV_THEME_MONO=y
CONFIG_LV_PREDEFINED_DISPLAY_WEMOS_LOLIN=y
CONFIG_I2C_MANAGER_0_ENABLED=y
CONFIG_I2C_MANAGER_0_SDA=5
CONFIG_I2C_MANAGER_0_SCL=4
CONFIG_I2C_MANAGER_0_FREQ_HZ=100000

View file

@ -8,11 +8,14 @@
*********************/ *********************/
#include "esp_lcd_backlight.h" #include "esp_lcd_backlight.h"
#include "driver/ledc.h" #include "driver/ledc.h"
#include "rom/gpio.h" #include "driver/gpio.h"
#include "esp_log.h" #include "esp_log.h"
#include "soc/ledc_periph.h" // to invert LEDC output on IDF version < v4.3 #include "soc/ledc_periph.h" // to invert LEDC output on IDF version < v4.3
#include "esp_idf_version.h"
#define SIG_GPIO_OUT_IDX 128 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
#include "soc/gpio_sig_map.h"
#endif
typedef struct { typedef struct {
bool pwm_control; // true: LEDC is used, false: GPIO is used bool pwm_control; // true: LEDC is used, false: GPIO is used
@ -51,22 +54,32 @@ disp_backlight_h disp_backlight_new(const disp_backlight_config_t *config)
}; };
const ledc_timer_config_t LCD_backlight_timer = { const ledc_timer_config_t LCD_backlight_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE, .speed_mode = LEDC_LOW_SPEED_MODE,
.duty_resolution = LEDC_TIMER_10_BIT, .bit_num = LEDC_TIMER_10_BIT,
.timer_num = config->timer_idx, .timer_num = config->timer_idx,
.freq_hz = 5000, .freq_hz = 5000,
.clk_cfg = LEDC_AUTO_CLK}; .clk_cfg = LEDC_AUTO_CLK};
ESP_ERROR_CHECK(ledc_timer_config(&LCD_backlight_timer)); ESP_ERROR_CHECK(ledc_timer_config(&LCD_backlight_timer));
ESP_ERROR_CHECK(ledc_channel_config(&LCD_backlight_channel)); ESP_ERROR_CHECK(ledc_channel_config(&LCD_backlight_channel));
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
esp_rom_gpio_connect_out_signal(config->gpio_num, ledc_periph_signal[LEDC_LOW_SPEED_MODE].sig_out0_idx + config->channel_idx, config->output_invert, 0);
#else
gpio_matrix_out(config->gpio_num, ledc_periph_signal[LEDC_LOW_SPEED_MODE].sig_out0_idx + config->channel_idx, config->output_invert, 0); gpio_matrix_out(config->gpio_num, ledc_periph_signal[LEDC_LOW_SPEED_MODE].sig_out0_idx + config->channel_idx, config->output_invert, 0);
#endif
} }
else else
{ {
// Configure GPIO for output // Configure GPIO for output
bckl_dev->index = config->gpio_num; bckl_dev->index = config->gpio_num;
gpio_pad_select_gpio(config->gpio_num);
ESP_ERROR_CHECK(gpio_set_direction(config->gpio_num, GPIO_MODE_OUTPUT)); ESP_ERROR_CHECK(gpio_set_direction(config->gpio_num, GPIO_MODE_OUTPUT));
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
esp_rom_gpio_pad_select_gpio(config->gpio_num);
esp_rom_gpio_connect_out_signal(config->gpio_num, SIG_GPIO_OUT_IDX, config->output_invert, false);
#else
gpio_pad_select_gpio(config->gpio_num);
gpio_matrix_out(config->gpio_num, SIG_GPIO_OUT_IDX, config->output_invert, false); gpio_matrix_out(config->gpio_num, SIG_GPIO_OUT_IDX, config->output_invert, false);
#endif
} }
return (disp_backlight_h)bckl_dev; return (disp_backlight_h)bckl_dev;

View file

@ -0,0 +1,57 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "display_port.h"
#include "sdkconfig.h"
#include "driver/gpio.h"
void display_port_delay(lv_disp_drv_t *drv, uint32_t delay_ms)
{
(void) drv;
vTaskDelay(pdMS_TO_TICKS(delay_ms));
}
void display_port_backlight(lv_disp_drv_t *drv, uint8_t state)
{
(void) drv;
#ifdef CONFIG_LV_DISP_PIN_BCKL
gpio_set_level(CONFIG_LV_DISP_PIN_BCKL, state);
#endif
}
void display_port_gpio_dc(lv_disp_drv_t *drv, uint8_t state)
{
(void) drv;
#ifdef CONFIG_LV_DISPLAY_USE_DC
gpio_set_level(CONFIG_LV_DISP_PIN_DC, state);
#endif
}
void display_port_gpio_rst(lv_disp_drv_t *drv, uint8_t state)
{
(void) drv;
#ifdef CONFIG_LV_DISP_USE_RST
gpio_set_level(CONFIG_LV_DISP_PIN_RST, state);
#endif
}
bool display_port_gpio_is_busy(lv_disp_drv_t *drv)
{
(void) drv;
bool device_busy = false;
#ifdef CONFIG_LV_DISP_PIN_BUSY
/* FIXME Assuming the busy signal in logic 1 means the device is busy */
if (gpio_get_level(CONFIG_LV_DISP_PIN_BUSY) == 1) {
device_busy = true;
}
#endif
return device_busy;
}

View file

@ -6,12 +6,16 @@
/********************* /*********************
* INCLUDES * INCLUDES
*********************/ *********************/
#include "sdkconfig.h"
#include "lvgl_helpers.h" #include "lvgl_helpers.h"
#include "esp_log.h"
#include "lvgl_tft/disp_spi.h" #include "sdkconfig.h"
#include "lvgl_touch/tp_spi.h"
#include "driver/spi_common.h"
#include "esp_log.h"
#include "esp_idf_version.h"
#include "disp_spi.h"
#include "tp_spi.h"
#include "lvgl_spi_conf.h" #include "lvgl_spi_conf.h"
@ -29,6 +33,8 @@
#define TAG "lvgl_helpers" #define TAG "lvgl_helpers"
#define GPIO_NOT_USED (-1)
#define DMA_DEFAULT_TRANSFER_SIZE (0u)
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
@ -37,6 +43,20 @@
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
/**
* Calculates the SPI max transfer size based on the display buffer size
*
* @return SPI max transfer size in bytes
*/
static int calculate_spi_max_transfer_size(const int display_buffer_size);
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
/**
* Handle FT81X initialization as it's a particular case
*/
static void init_ft81x(int dma_channel);
#endif
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
@ -49,8 +69,8 @@
* GLOBAL FUNCTIONS * GLOBAL FUNCTIONS
**********************/ **********************/
/* Interface and driver initialization */ /* Interface (SPI, I2C) initialization */
void lvgl_driver_init(void) void lvgl_interface_init(void)
{ {
/* Since LVGL v8 LV_HOR_RES_MAX and LV_VER_RES_MAX are not defined, so /* Since LVGL v8 LV_HOR_RES_MAX and LV_VER_RES_MAX are not defined, so
* print it only if they are defined. */ * print it only if they are defined. */
@ -58,87 +78,174 @@ void lvgl_driver_init(void)
ESP_LOGI(TAG, "Display hor size: %d, ver size: %d", LV_HOR_RES_MAX, LV_VER_RES_MAX); ESP_LOGI(TAG, "Display hor size: %d, ver size: %d", LV_HOR_RES_MAX, LV_VER_RES_MAX);
#endif #endif
ESP_LOGI(TAG, "Display buffer size: %d", DISP_BUF_SIZE); size_t display_buffer_size = lvgl_get_display_buffer_size();
ESP_LOGI(TAG, "Display buffer size: %d", display_buffer_size);
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) #if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
ESP_LOGI(TAG, "Initializing SPI master for FT81X"); init_ft81x(dma_channel);
lvgl_spi_driver_init(TFT_SPI_HOST,
DISP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK,
SPI_BUS_MAX_TRANSFER_SZ, 1,
DISP_SPI_IO2, DISP_SPI_IO3);
disp_spi_add_device(TFT_SPI_HOST);
disp_driver_init();
#if defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
touch_driver_init();
#endif
return;
#endif
#if defined (SHARED_SPI_BUS)
ESP_LOGI(TAG, "Initializing shared SPI master");
lvgl_spi_driver_init(TFT_SPI_HOST,
TP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK,
SPI_BUS_MAX_TRANSFER_SZ, 1,
-1, -1);
disp_spi_add_device(TFT_SPI_HOST);
tp_spi_add_device(TOUCH_SPI_HOST);
disp_driver_init();
touch_driver_init();
return; return;
#endif #endif
/* Display controller initialization */ /* Display controller initialization */
#if defined CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI #if defined (CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI) || defined (SHARED_SPI_BUS)
ESP_LOGI(TAG, "Initializing SPI master for display"); ESP_LOGI(TAG, "Initializing SPI master");
lvgl_spi_driver_init(TFT_SPI_HOST, int miso = DISP_SPI_MISO;
DISP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK, int spi_max_transfer_size = calculate_spi_max_transfer_size(display_buffer_size);
SPI_BUS_MAX_TRANSFER_SZ, 1,
DISP_SPI_IO2, DISP_SPI_IO3); /* Set the miso signal to be the selected for the touch driver */
#if defined (SHARED_SPI_BUS)
miso = TP_SPI_MISO;
#endif
// We use DMA channel 1 for all cases
lvgl_spi_driver_init(TFT_SPI_HOST, miso, DISP_SPI_MOSI, DISP_SPI_CLK,
spi_max_transfer_size, 1, DISP_SPI_IO2, DISP_SPI_IO3);
disp_spi_add_device(TFT_SPI_HOST); disp_spi_add_device(TFT_SPI_HOST);
disp_driver_init(); /* Add device for touch driver */
#if defined (SHARED_SPI_BUS)
tp_spi_add_device(TOUCH_SPI_HOST);
touch_driver_init();
return;
#endif
#elif defined (CONFIG_LV_I2C_DISPLAY) #elif defined (CONFIG_LV_I2C_DISPLAY)
disp_driver_init();
#else #else
#error "No protocol defined for display controller" #error "No protocol defined for display controller"
#endif #endif
/* Touch controller initialization */ /* Touch controller initialization */
#if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONE #if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONE
#if defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI) #if defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI)
ESP_LOGI(TAG, "Initializing SPI master for touch"); ESP_LOGI(TAG, "Initializing SPI master for touch");
lvgl_spi_driver_init(TOUCH_SPI_HOST, #if defined (CONFIG_IDF_TARGET_ESP32)
TP_SPI_MISO, TP_SPI_MOSI, TP_SPI_CLK, dma_channel = 2;
0 /* Defaults to 4094 */, 2, #endif
-1, -1);
lvgl_spi_driver_init(TOUCH_SPI_HOST, TP_SPI_MISO, TP_SPI_MOSI, TP_SPI_CLK,
DMA_DEFAULT_TRANSFER_SIZE, dma_channel, GPIO_NOT_USED, GPIO_NOT_USED);
tp_spi_add_device(TOUCH_SPI_HOST); tp_spi_add_device(TOUCH_SPI_HOST);
touch_driver_init(); touch_driver_init();
#elif defined (CONFIG_LV_I2C_TOUCH) #elif defined (CONFIG_LV_I2C_TOUCH)
touch_driver_init(); touch_driver_init();
#elif defined (CONFIG_LV_TOUCH_DRIVER_ADC) #elif defined (CONFIG_LV_TOUCH_DRIVER_ADC)
touch_driver_init(); touch_driver_init();
#elif defined (CONFIG_LV_TOUCH_DRIVER_DISPLAY) #elif defined (CONFIG_LV_TOUCH_DRIVER_DISPLAY)
touch_driver_init(); touch_driver_init();
#else #else
#error "No protocol defined for touch controller" #error "No protocol defined for touch controller"
#endif #endif
#else #else
#endif #endif
} }
void lvgl_display_gpios_init(void)
{
esp_err_t err = ESP_OK;
gpio_config_t io_conf = {
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE,
};
#ifdef CONFIG_LV_DISPLAY_USE_DC
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << CONFIG_LV_DISP_PIN_DC);
err = gpio_config(&io_conf);
ESP_ERROR_CHECK(err);
#endif
#ifdef CONFIG_LV_DISP_USE_RST
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << CONFIG_LV_DISP_PIN_RST);
err = gpio_config(&io_conf);
ESP_ERROR_CHECK(err);
#endif
#if !defined(CONFIG_LV_DISP_BACKLIGHT_OFF) && defined(CONFIG_LV_DISP_PIN_BCKL) && \
(CONFIG_LV_DISP_PIN_BCKL > 0)
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << CONFIG_LV_DISP_PIN_BCKL);
err = gpio_config(&io_conf);
ESP_ERROR_CHECK(err);
#endif
#ifdef CONFIG_LV_DISP_USE_BUSY
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = (1ULL << CONFIG_LV_DISP_PIN_BUSY);
err = gpio_config(&io_conf);
ESP_ERROR_CHECK(err);
#endif
}
/* DISP_BUF_SIZE value doesn't have an special meaning, but it's the size
* of the buffer(s) passed to LVGL as display buffers. The default values used
* were the values working for the contributor of the display controller.
*
* As LVGL supports partial display updates the DISP_BUF_SIZE doesn't
* necessarily need to be equal to the display size.
*
* When using RGB displays the display buffer size will also depends on the
* color format being used, for RGB565 each pixel needs 2 bytes.
* When using the mono theme, the display pixels can be represented in one bit,
* so the buffer size can be divided by 8, e.g. see SSD1306 display size. */
size_t lvgl_get_display_buffer_size(void)
{
size_t disp_buffer_size = 0;
#if LVGL_VERSION_MAJOR < 8
#if defined (CONFIG_CUSTOM_DISPLAY_BUFFER_SIZE)
disp_buffer_size = CONFIG_CUSTOM_DISPLAY_BUFFER_BYTES;
#else
/* Calculate total of 40 lines of display horizontal size */
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C)
disp_buffer_size = LV_HOR_RES_MAX * 40;
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107
disp_buffer_size = LV_HOR_RES_MAX * LV_VER_RES_MAX;
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306
#if defined (CONFIG_LV_THEME_MONO)
disp_buffer_size = LV_HOR_RES_MAX * (LV_VER_RES_MAX / 8);
#else
disp_buffer_size = LV_HOR_RES_MAX * LV_VER_RES_MAX);
#endif
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820)
disp_buffer_size = LV_VER_RES_MAX * IL3820_COLUMNS;
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A)
disp_buffer_size = ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8); // 5KB
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D)
disp_buffer_size = ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8); // 2888 bytes
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544)
disp_buffer_size = (LV_HOR_RES_MAX * (LV_VER_RES_MAX / 8));
#else
#error "No display controller selected"
#endif
#endif
#else /* LVGL v8 */
/* ToDo: Implement display buffer size calculation with configuration values from the display driver */
disp_buffer_size = 320*40; // Reasonable for start
#endif
return disp_buffer_size;
}
/* Initialize spi bus master /* Initialize spi bus master
* *
@ -154,7 +261,6 @@ bool lvgl_spi_driver_init(int host,
int dma_channel, int dma_channel,
int quadwp_pin, int quadhd_pin) int quadwp_pin, int quadhd_pin)
{ {
assert((0 <= host) && (3 > host));
const char *spi_names[] = { const char *spi_names[] = {
"SPI1_HOST", "SPI2_HOST", "SPI3_HOST" "SPI1_HOST", "SPI2_HOST", "SPI3_HOST"
}; };
@ -175,11 +281,49 @@ bool lvgl_spi_driver_init(int host,
}; };
ESP_LOGI(TAG, "Initializing SPI bus..."); ESP_LOGI(TAG, "Initializing SPI bus...");
#if defined (CONFIG_IDF_TARGET_ESP32C3) esp_err_t ret = spi_bus_initialize((spi_host_device_t) host, &buscfg, dma_channel);
dma_channel = SPI_DMA_CH_AUTO;
#endif
esp_err_t ret = spi_bus_initialize(host, &buscfg, (spi_dma_chan_t)dma_channel);
assert(ret == ESP_OK); assert(ret == ESP_OK);
return ESP_OK != ret; return ESP_OK != ret;
} }
static int calculate_spi_max_transfer_size(const int display_buffer_size)
{
int retval = 0;
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488)
retval = display_buffer_size * 3;
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C)
retval = display_buffer_size * 2;
#else
retval = display_buffer_size * 2;
#endif
return retval;
}
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
static void init_ft81x(int dma_channel)
{
size_t display_buffer_size = lvgl_get_display_buffer_size();
int spi_max_transfer_size = calculate_spi_max_transfer_size(display_buffer_size);
lvgl_spi_driver_init(TFT_SPI_HOST, DISP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK,
spi_max_transfer_size, dma_channel, DISP_SPI_IO2, DISP_SPI_IO3);
disp_spi_add_device(TFT_SPI_HOST);
#if defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
touch_driver_init();
#endif
}
#endif

View file

@ -23,68 +23,6 @@ extern "C" {
* DEFINES * DEFINES
*********************/ *********************/
/* DISP_BUF_SIZE value doesn't have an special meaning, but it's the size
* of the buffer(s) passed to LVGL as display buffers. The default values used
* were the values working for the contributor of the display controller.
*
* As LVGL supports partial display updates the DISP_BUF_SIZE doesn't
* necessarily need to be equal to the display size.
*
* When using RGB displays the display buffer size will also depends on the
* color format being used, for RGB565 each pixel needs 2 bytes.
* When using the mono theme, the display pixels can be represented in one bit,
* so the buffer size can be divided by 8, e.g. see SSD1306 display size. */
#if defined (CONFIG_CUSTOM_DISPLAY_BUFFER_SIZE)
#define DISP_BUF_SIZE CONFIG_CUSTOM_DISPLAY_BUFFER_BYTES
#else
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789)
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * LV_VER_RES_MAX)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306
#if defined (CONFIG_LV_THEME_MONO)
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * (LV_VER_RES_MAX / 8))
#else
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * LV_VER_RES_MAX)
#endif
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
#define DISP_BUF_LINES 40
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * DISP_BUF_LINES)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820)
#define DISP_BUF_SIZE (LV_VER_RES_MAX * IL3820_COLUMNS)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01)
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A)
#define DISP_BUF_SIZE ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8) // 5KB
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D)
#define DISP_BUF_SIZE ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8) // 2888 bytes
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544)
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * (LV_VER_RES_MAX / 8))
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_SCHMITT)
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * LV_VER_RES_MAX)
#else
#error "No display controller selected"
#endif
#endif
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
@ -96,12 +34,18 @@ extern "C" {
void lvgl_i2c_locking(void* leader); void lvgl_i2c_locking(void* leader);
/* Initialize detected SPI and I2C bus and devices */ /* Initialize detected SPI and I2C bus and devices */
void lvgl_driver_init(void); void lvgl_interface_init(void);
/* Initialize SPI master */ /* Initialize SPI master */
bool lvgl_spi_driver_init(int host, int miso_pin, int mosi_pin, int sclk_pin, bool lvgl_spi_driver_init(int host, int miso_pin, int mosi_pin, int sclk_pin,
int max_transfer_sz, int dma_channel, int quadwp_pin, int quadhd_pin); int max_transfer_sz, int dma_channel, int quadwp_pin, int quadhd_pin);
/* Initialize display GPIOs, e.g. DC and RST pins */
void lvgl_display_gpios_init(void);
/* Get display buffer size */
size_t lvgl_get_display_buffer_size(void);
/********************** /**********************
* MACROS * MACROS
**********************/ **********************/

View file

@ -66,8 +66,8 @@ static const uint8_t ACK_CHECK_EN = 1;
#define I2C_MANAGER_0_PULLUPS false #define I2C_MANAGER_0_PULLUPS false
#endif #endif
#define I2C_MANAGER_0_TIMEOUT ( CONFIG_I2C_MANAGER_0_TIMEOUT / portTICK_RATE_MS ) #define I2C_MANAGER_0_TIMEOUT ( pdMS_TO_TICKS( CONFIG_I2C_MANAGER_0_TIMEOUT ) )
#define I2C_MANAGER_0_LOCK_TIMEOUT ( CONFIG_I2C_MANAGER_0_LOCK_TIMEOUT / portTICK_RATE_MS ) #define I2C_MANAGER_0_LOCK_TIMEOUT ( pdMS_TO_TICKS( CONFIG_I2C_MANAGER_0_LOCK_TIMEOUT ) )
#endif #endif
@ -79,8 +79,8 @@ static const uint8_t ACK_CHECK_EN = 1;
#define I2C_MANAGER_1_PULLUPS false #define I2C_MANAGER_1_PULLUPS false
#endif #endif
#define I2C_MANAGER_1_TIMEOUT ( CONFIG_I2C_MANAGER_1_TIMEOUT / portTICK_RATE_MS ) #define I2C_MANAGER_1_TIMEOUT ( pdMS_TO_TICKS( CONFIG_I2C_MANAGER_1_TIMEOUT ) )
#define I2C_MANAGER_1_LOCK_TIMEOUT ( CONFIG_I2C_MANAGER_1_LOCK_TIMEOUT / portTICK_RATE_MS ) #define I2C_MANAGER_1_LOCK_TIMEOUT ( pdMS_TO_TICKS( CONFIG_I2C_MANAGER_1_LOCK_TIMEOUT ) )
#endif #endif
#define ERROR_PORT(port, fail) { \ #define ERROR_PORT(port, fail) { \
@ -222,7 +222,7 @@ esp_err_t I2C_FN(_read)(i2c_port_t port, uint16_t addr, uint32_t reg, uint8_t *b
} }
if (result != ESP_OK) { if (result != ESP_OK) {
ESP_LOGW(TAG, "Error: %d", result); ESP_LOGD(TAG, "Error: %d", result);
} }
ESP_LOG_BUFFER_HEX_LEVEL(TAG, buffer, size, ESP_LOG_VERBOSE); ESP_LOG_BUFFER_HEX_LEVEL(TAG, buffer, size, ESP_LOG_VERBOSE);
@ -244,12 +244,12 @@ esp_err_t I2C_FN(_write)(i2c_port_t port, uint16_t addr, uint32_t reg, const uin
TickType_t timeout = 0; TickType_t timeout = 0;
#if defined (I2C_ZERO) #if defined (I2C_ZERO)
if (port == I2C_NUM_0) { if (port == I2C_NUM_0) {
timeout = (CONFIG_I2C_MANAGER_0_TIMEOUT) / portTICK_RATE_MS; timeout = pdMS_TO_TICKS( CONFIG_I2C_MANAGER_0_TIMEOUT );
} }
#endif #endif
#if defined (I2C_ONE) #if defined (I2C_ONE)
if (port == I2C_NUM_1) { if (port == I2C_NUM_1) {
timeout = (CONFIG_I2C_MANAGER_1_TIMEOUT) / portTICK_RATE_MS; timeout = pdMS_TO_TICKS( CONFIG_I2C_MANAGER_1_TIMEOUT );
} }
#endif #endif
@ -271,7 +271,7 @@ esp_err_t I2C_FN(_write)(i2c_port_t port, uint16_t addr, uint32_t reg, const uin
} }
if (result != ESP_OK) { if (result != ESP_OK) {
ESP_LOGW(TAG, "Error: %d", result); ESP_LOGD(TAG, "Error: %d", result);
} }
ESP_LOG_BUFFER_HEX_LEVEL(TAG, buffer, size, ESP_LOG_VERBOSE); ESP_LOG_BUFFER_HEX_LEVEL(TAG, buffer, size, ESP_LOG_VERBOSE);
@ -294,12 +294,12 @@ esp_err_t I2C_FN(_lock)(i2c_port_t port) {
TickType_t timeout; TickType_t timeout;
#if defined (I2C_ZERO) #if defined (I2C_ZERO)
if (port == I2C_NUM_0) { if (port == I2C_NUM_0) {
timeout = (CONFIG_I2C_MANAGER_0_LOCK_TIMEOUT) / portTICK_RATE_MS; timeout = pdMS_TO_TICKS( CONFIG_I2C_MANAGER_0_LOCK_TIMEOUT );
} }
#endif #endif
#if defined (I2C_ONE) #if defined (I2C_ONE)
if (port == I2C_NUM_1) { if (port == I2C_NUM_1) {
timeout = (CONFIG_I2C_MANAGER_1_LOCK_TIMEOUT) / portTICK_RATE_MS; timeout = pdMS_TO_TICKS( CONFIG_I2C_MANAGER_1_LOCK_TIMEOUT );
} }
#endif #endif

View file

@ -6,6 +6,8 @@
#ifndef LVGL_SPI_CONF_H #ifndef LVGL_SPI_CONF_H
#define LVGL_SPI_CONF_H #define LVGL_SPI_CONF_H
#include <sdkconfig.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -18,25 +20,32 @@ extern "C" {
* DEFINES * DEFINES
*********************/ *********************/
// DISPLAY PINS // DISPLAY PINS
/* Mandatory pins are MOSI and CLK */
#define DISP_SPI_MOSI CONFIG_LV_DISP_SPI_MOSI #define DISP_SPI_MOSI CONFIG_LV_DISP_SPI_MOSI
#define DISP_SPI_CLK CONFIG_LV_DISP_SPI_CLK
/* Optional pins */
#if defined (CONFIG_LV_DISPLAY_USE_SPI_MISO) #if defined (CONFIG_LV_DISPLAY_USE_SPI_MISO)
#define DISP_SPI_MISO CONFIG_LV_DISP_SPI_MISO #define DISP_SPI_MISO CONFIG_LV_DISP_SPI_MISO
#define DISP_SPI_INPUT_DELAY_NS CONFIG_LV_DISP_SPI_INPUT_DELAY_NS #define DISP_SPI_INPUT_DELAY_NS CONFIG_LV_DISP_SPI_INPUT_DELAY_NS
#else #else
#define DISP_SPI_MISO (-1) #define DISP_SPI_MISO (-1)
#define DISP_SPI_INPUT_DELAY_NS (0) #define DISP_SPI_INPUT_DELAY_NS (0U)
#endif #endif
#if defined(CONFIG_LV_DISP_SPI_IO2) #if defined(CONFIG_LV_DISP_SPI_IO2)
#define DISP_SPI_IO2 CONFIG_LV_DISP_SPI_IO2 #define DISP_SPI_IO2 CONFIG_LV_DISP_SPI_IO2
#else #else
#define DISP_SPI_IO2 (-1) #define DISP_SPI_IO2 (-1)
#endif #endif
#if defined(CONFIG_LV_DISP_SPI_IO3) #if defined(CONFIG_LV_DISP_SPI_IO3)
#define DISP_SPI_IO3 CONFIG_LV_DISP_SPI_IO3 #define DISP_SPI_IO3 CONFIG_LV_DISP_SPI_IO3
#else #else
#define DISP_SPI_IO3 (-1) #define DISP_SPI_IO3 (-1)
#endif #endif
#define DISP_SPI_CLK CONFIG_LV_DISP_SPI_CLK
#if defined (CONFIG_LV_DISPLAY_USE_SPI_CS) #if defined (CONFIG_LV_DISPLAY_USE_SPI_CS)
#define DISP_SPI_CS CONFIG_LV_DISP_SPI_CS #define DISP_SPI_CS CONFIG_LV_DISP_SPI_CS
#else #else
@ -50,24 +59,38 @@ extern "C" {
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) && \ #if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) && \
defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X) defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
#define TP_SPI_MOSI CONFIG_LV_DISP_SPI_MOSI #define SHARED_SPI_BUS
#define TP_SPI_MISO CONFIG_LV_DISP_SPI_MISO
#define TP_SPI_CLK CONFIG_LV_DISP_SPI_CLK #define TP_SPI_MOSI CONFIG_LV_DISP_SPI_MOSI
#define TP_SPI_CS CONFIG_LV_DISP_SPI_CS #define TP_SPI_MISO CONFIG_LV_DISP_SPI_MISO
#define TP_SPI_CLK CONFIG_LV_DISP_SPI_CLK
#define TP_SPI_CS CONFIG_LV_DISP_SPI_CS
#else #else
#define TP_SPI_MOSI CONFIG_LV_TOUCH_SPI_MOSI #define TP_SPI_MOSI CONFIG_LV_TOUCH_SPI_MOSI
#define TP_SPI_MISO CONFIG_LV_TOUCH_SPI_MISO #define TP_SPI_MISO CONFIG_LV_TOUCH_SPI_MISO
#define TP_SPI_CLK CONFIG_LV_TOUCH_SPI_CLK #define TP_SPI_CLK CONFIG_LV_TOUCH_SPI_CLK
#define TP_SPI_CS CONFIG_LV_TOUCH_SPI_CS #define TP_SPI_CS CONFIG_LV_TOUCH_SPI_CS
#endif #endif
#endif #endif
#define ENABLE_TOUCH_INPUT CONFIG_LV_ENABLE_TOUCH #define ENABLE_TOUCH_INPUT CONFIG_LV_ENABLE_TOUCH
#if defined (CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI)
/* Display controller SPI host configuration */
#if defined (CONFIG_LV_TFT_DISPLAY_SPI2_HOST) #if defined (CONFIG_LV_TFT_DISPLAY_SPI2_HOST)
#define TFT_SPI_HOST SPI2_HOST #define TFT_SPI_HOST SPI2_HOST
#elif defined (CONFIG_LV_TFT_DISPLAY_SPI3_HOST) #elif defined (CONFIG_LV_TFT_DISPLAY_SPI3_HOST)
#define TFT_SPI_HOST SPI3_HOST #define TFT_SPI_HOST SPI3_HOST
#else
#error SPI host not defined
#endif
#endif
/* Touch controller SPI host configuration */
#if defined (CONFIG_LV_TOUCH_CONTROLLER_SPI2_HOST)
#define TOUCH_SPI_HOST SPI2_HOST
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_SPI3_HOST)
#define TOUCH_SPI_HOST SPI3_HOST
#endif #endif
#if defined (CONFIG_LV_TFT_DISPLAY_SPI_HALF_DUPLEX) #if defined (CONFIG_LV_TFT_DISPLAY_SPI_HALF_DUPLEX)
@ -84,61 +107,34 @@ extern "C" {
#define DISP_SPI_TRANS_MODE_SIO #define DISP_SPI_TRANS_MODE_SIO
#endif #endif
/* Detect usage of shared SPI bus between display and indev controllers
*
* If the user sets the same MOSI and CLK pins for both display and indev
* controllers then we can assume the user is using the same SPI bus
* If so verify the user specified the same SPI bus for both */
#if defined (CONFIG_LV_TOUCH_CONTROLLER_SPI2_HOST) #if defined (CONFIG_LV_TOUCH_CONTROLLER_SPI2_HOST)
#define TOUCH_SPI_HOST SPI2_HOST #define TOUCH_SPI_HOST SPI2_HOST
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_SPI3_HOST) #elif defined (CONFIG_LV_TOUCH_CONTROLLER_SPI3_HOST)
#define TOUCH_SPI_HOST SPI3_HOST #define TOUCH_SPI_HOST SPI3_HOST
#endif #endif
/* Handle the FT81X Special case */ #if defined (CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI) && \
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) (CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI == 1) && \
defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI) && \
(TP_SPI_MOSI == DISP_SPI_MOSI) && (TP_SPI_CLK == DISP_SPI_CLK)
#if defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
#define SHARED_SPI_BUS
#else
/* Empty */
#endif
#else
// Detect the use of a shared SPI Bus and verify the user specified the same SPI bus for both touch and tft
#if defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI) && TP_SPI_MOSI == DISP_SPI_MOSI && TP_SPI_CLK == DISP_SPI_CLK
#if TFT_SPI_HOST != TOUCH_SPI_HOST #if TFT_SPI_HOST != TOUCH_SPI_HOST
#error You must specify the same SPI host (SPIx_HOST) for both display and touch driver #error You must specify the same SPI host (SPIx_HOST) for both display and touch driver
#endif #else
#define SHARED_SPI_BUS #define SHARED_SPI_BUS
#endif #endif
#endif
#endif #endif
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_SCHMITT)
#define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 4)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488)
#define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 3)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C)
#define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 2)
#else
#define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 2)
#endif
#if defined (CONFIG_LV_TFT_USE_CUSTOM_SPI_CLK_DIVIDER) #if defined (CONFIG_LV_TFT_USE_CUSTOM_SPI_CLK_DIVIDER)
#define SPI_TFT_CLOCK_SPEED_HZ ((80 * 1000 * 1000) / CONFIG_LV_TFT_CUSTOM_SPI_CLK_DIVIDER) #define SPI_TFT_CLOCK_SPEED_HZ ((80 * 1000 * 1000) / CONFIG_LV_TFT_CUSTOM_SPI_CLK_DIVIDER)
#else #else
@ -159,31 +155,33 @@ extern "C" {
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341) #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341)
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000) #define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
#elif defined(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C) #elif defined(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C)
#define SPI_TFT_CLOCK_SPEED_HZ (40 * 1000 * 1000) #define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
#elif defined(CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) #elif defined(CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
#define SPI_TFT_CLOCK_SPEED_HZ (32*1000*1000) #define SPI_TFT_CLOCK_SPEED_HZ (32*1000*1000)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544) #elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544)
#define SPI_TFT_CLOCK_SPEED_HZ (4*1000*1000) #define SPI_TFT_CLOCK_SPEED_HZ (4*1000*1000)
#else #else
#define SPI_TFT_CLOCK_SPEED_HZ (5*1000*1000) // Set to 40 later #define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
#endif #endif
#endif #endif /* CONFIG_LV_TFT_USE_CUSTOM_SPI_CLK_DIVIDER */
#if defined (CONFIG_LV_TFT_DISPLAY_USE_CUSTOM_SPI_MODE)
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789) #define SPI_TFT_SPI_MODE (CONFIG_LV_TFT_DISPLAY_CUSTOM_SPI_MODE)
#define SPI_TFT_SPI_MODE (2)
#else #else
#define SPI_TFT_SPI_MODE (0) #if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789)
#define SPI_TFT_SPI_MODE (2U)
#else
#define SPI_TFT_SPI_MODE (0U)
#endif #endif
/* Touch driver */ /* Touch driver */
#if (CONFIG_LV_TOUCH_CONTROLLER == TOUCH_CONTROLLER_STMPE610) #if (CONFIG_LV_TOUCH_CONTROLLER == TOUCH_CONTROLLER_STMPE610)
#define SPI_TOUCH_CLOCK_SPEED_HZ (1*1000*1000) #define SPI_TOUCH_CLOCK_SPEED_HZ (1*1000*1000)
#define SPI_TOUCH_SPI_MODE (1) #define SPI_TOUCH_SPI_MODE (1U)
#else #else
#define SPI_TOUCH_CLOCK_SPEED_HZ (2*1000*1000) #define SPI_TOUCH_CLOCK_SPEED_HZ (2*1000*1000)
#define SPI_TOUCH_SPI_MODE (0) #define SPI_TOUCH_SPI_MODE (0U)
#endif #endif
/********************** /**********************

View file

@ -41,6 +41,11 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
#include <stdio.h> #include <stdio.h>
#include <string.h>
#if defined (BT81X_ENABLE)
#include <stdarg.h>
#endif
#include "EVE.h" #include "EVE.h"
#include "EVE_commands.h" #include "EVE_commands.h"
@ -50,19 +55,8 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_log.h" #include "esp_log.h"
#include "soc/soc_memory_layout.h" #include "soc/soc_memory_layout.h"
#include "esp_log.h"
#include "disp_spi.h" #include "disp_spi.h"
#include <string.h>
#if defined (BT81X_ENABLE)
#include <stdarg.h>
#endif
#define TAG_LOG "FT81X"
/* data structure for SPI reading that has (optional) space for inserted dummy byte */ /* data structure for SPI reading that has (optional) space for inserted dummy byte */
typedef struct _spi_read_data { typedef struct _spi_read_data {
#if defined(DISP_SPI_FULL_DUPLEX) #if defined(DISP_SPI_FULL_DUPLEX)
@ -273,7 +267,13 @@ void EVE_memWrite_buffer(uint32_t ftAddress, const uint8_t *data, uint32_t len,
uint32_t bytes_left = len; uint32_t bytes_left = len;
while(bytes_left > 0) while(bytes_left > 0)
{ {
uint32_t block_len = (bytes_left > SPI_TRANSER_SIZE ? SPI_TRANSER_SIZE : bytes_left); uint32_t block_len = 0;
#if defined (SPI_TRANSFER_SIZE)
block_len = (bytes_left > SPI_TRANSER_SIZE ? SPI_TRANSER_SIZE : bytes_left);
#else
/* ToDo Update SPI_TRANSFER_SIZE calculation, it's based on the DISP_BUF_SIZE */
#endif
// only send flush on last chunk // only send flush on last chunk
disp_spi_send_flag_t flush_flag = 0; disp_spi_send_flag_t flush_flag = 0;
@ -334,7 +334,6 @@ uint8_t EVE_busy(void)
cmdOffset += 8; cmdOffset += 8;
BUFFER_SPI_BYTE
BUFFER_SPI_BYTE(MEM_WRITE | 0x30); /* send Memory Write plus high address byte of REG_CMD_WRITE for EVE81x */ BUFFER_SPI_BYTE(MEM_WRITE | 0x30); /* send Memory Write plus high address byte of REG_CMD_WRITE for EVE81x */
BUFFER_SPI_BYTE(0x20); /* send middle address byte of REG_CMD_WRITE for EVE81x */ BUFFER_SPI_BYTE(0x20); /* send middle address byte of REG_CMD_WRITE for EVE81x */
BUFFER_SPI_BYTE(0xfc); /* send low address byte of REG_CMD_WRITE for EVE81x */ BUFFER_SPI_BYTE(0xfc); /* send low address byte of REG_CMD_WRITE for EVE81x */
@ -875,13 +874,13 @@ uint8_t EVE_init(void)
/* The most reliable DIO/QIO switching point is after EVE start up but before reading the ChipID. */ /* The most reliable DIO/QIO switching point is after EVE start up but before reading the ChipID. */
#if defined(DISP_SPI_TRANS_MODE_DIO) #if defined(DISP_SPI_TRANS_MODE_DIO)
ESP_LOGI(TAG_LOG, "Switching to DIO mode"); LV_LOG_INFO("Switching to DIO mode");
DELAY_MS(20); /* different boards may take a different delay but this generally seems to work */ DELAY_MS(20); /* different boards may take a different delay but this generally seems to work */
EVE_memWrite16(REG_SPI_WIDTH, SPI_WIDTH_DIO); EVE_memWrite16(REG_SPI_WIDTH, SPI_WIDTH_DIO);
SPIInherentSendFlags = DISP_SPI_MODE_DIO | DISP_SPI_MODE_DIOQIO_ADDR; SPIInherentSendFlags = DISP_SPI_MODE_DIO | DISP_SPI_MODE_DIOQIO_ADDR;
SPIDummyReadBits = 4; /* Esp32 DMA SPI transaction dummy_bits works more like clock cycles, so in DIO 4 dummy_bits == 8 total bits */ SPIDummyReadBits = 4; /* Esp32 DMA SPI transaction dummy_bits works more like clock cycles, so in DIO 4 dummy_bits == 8 total bits */
#elif defined(DISP_SPI_TRANS_MODE_QIO) #elif defined(DISP_SPI_TRANS_MODE_QIO)
ESP_LOGI(TAG_LOG, "Switching to QIO mode"); LV_LOG_INFO("Switching to QIO mode");
DELAY_MS(20); /* different boards may take a different delay but this generally seems to work */ DELAY_MS(20); /* different boards may take a different delay but this generally seems to work */
EVE_memWrite16(REG_SPI_WIDTH, SPI_WIDTH_QIO); EVE_memWrite16(REG_SPI_WIDTH, SPI_WIDTH_QIO);
SPIInherentSendFlags = DISP_SPI_MODE_QIO | DISP_SPI_MODE_DIOQIO_ADDR; SPIInherentSendFlags = DISP_SPI_MODE_QIO | DISP_SPI_MODE_DIOQIO_ADDR;
@ -897,7 +896,7 @@ uint8_t EVE_init(void)
timeout++; timeout++;
if(timeout > 400) if(timeout > 400)
{ {
ESP_LOGI(TAG_LOG, "Failed to read ChipID...aborting initialization."); LV_LOG_WARN("Failed to read ChipID...aborting initialization.");
return 0; return 0;
} }
} }
@ -909,7 +908,7 @@ uint8_t EVE_init(void)
timeout++; timeout++;
if(timeout > 50) /* experimental, 10 was the lowest value to get the BT815 started with, the touch-controller was the last to get out of reset */ if(timeout > 50) /* experimental, 10 was the lowest value to get the BT815 started with, the touch-controller was the last to get out of reset */
{ {
ESP_LOGI(TAG_LOG, "Failed to read CPU status...aborting initialization."); LV_LOG_WARN("Failed to read CPU status...aborting initialization.");
return 0; return 0;
} }
} }

View file

@ -51,7 +51,11 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
#define EVE_PDN CONFIG_LV_DISP_PIN_RST // grey #define EVE_PDN CONFIG_LV_DISP_PIN_RST // grey
#define EVE_USE_PDN CONFIG_LV_DISP_USE_RST #define EVE_USE_PDN CONFIG_LV_DISP_USE_RST
#if defined (DISP_BUF_SIZE)
#define SPI_TRANSER_SIZE (DISP_BUF_SIZE * (LV_COLOR_DEPTH / 8)) #define SPI_TRANSER_SIZE (DISP_BUF_SIZE * (LV_COLOR_DEPTH / 8))
#else
/* ToDo Update using new API */
#endif
#define BYTES_PER_PIXEL (LV_COLOR_DEPTH / 8) // bytes per pixel for (16 for RGB565) #define BYTES_PER_PIXEL (LV_COLOR_DEPTH / 8) // bytes per pixel for (16 for RGB565)
#define BYTES_PER_LINE (EVE_HSIZE * BYTES_PER_PIXEL) #define BYTES_PER_LINE (EVE_HSIZE * BYTES_PER_PIXEL)
@ -208,6 +212,8 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
#define EVE_SUNFLOWER #define EVE_SUNFLOWER
#elif defined(CONFIG_LV_FT81X_CONFIG_EVE_CONNECTEVE) #elif defined(CONFIG_LV_FT81X_CONFIG_EVE_CONNECTEVE)
#define EVE_CONNECTEVE #define EVE_CONNECTEVE
#else
#define EVE_EVE2_35 // Define something if there is no Kconfig option selected
#endif #endif
/* display timing parameters below */ /* display timing parameters below */

View file

@ -2,6 +2,7 @@
#include <stdio.h> #include <stdio.h>
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_idf_version.h"
#include "FT81x.h" #include "FT81x.h"
@ -263,7 +264,11 @@ void TFT_bitmap_display(void)
void FT81x_init(void) void FT81x_init(void)
{ {
#if EVE_USE_PDN #if EVE_USE_PDN
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
esp_rom_gpio_pad_select_gpio(EVE_PDN);
#else
gpio_pad_select_gpio(EVE_PDN); gpio_pad_select_gpio(EVE_PDN);
#endif
#endif #endif
gpio_set_level(EVE_CS, 1); gpio_set_level(EVE_CS, 1);

View file

@ -16,7 +16,6 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "GC9A01"
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@ -37,6 +36,7 @@ static void GC9A01_set_orientation(uint8_t orientation);
static void GC9A01_send_cmd(uint8_t cmd); static void GC9A01_send_cmd(uint8_t cmd);
static void GC9A01_send_data(void * data, uint16_t length); static void GC9A01_send_data(void * data, uint16_t length);
static void GC9A01_send_color(void * data, uint16_t length); static void GC9A01_send_color(void * data, uint16_t length);
static void GC9A01_reset(void);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@ -111,22 +111,9 @@ void GC9A01_init(void)
}; };
//Initialize non-SPI GPIOs GC9A01_reset();
gpio_pad_select_gpio(GC9A01_DC);
gpio_set_direction(GC9A01_DC, GPIO_MODE_OUTPUT);
#if GC9A01_USE_RST LV_LOG_INFO("Initialization.");
gpio_pad_select_gpio(GC9A01_RST);
gpio_set_direction(GC9A01_RST, GPIO_MODE_OUTPUT);
//Reset the display
gpio_set_level(GC9A01_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(GC9A01_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
ESP_LOGI(TAG, "Initialization.");
//Send all the commands //Send all the commands
uint16_t cmd = 0; uint16_t cmd = 0;
@ -134,7 +121,7 @@ void GC9A01_init(void)
GC9A01_send_cmd(GC_init_cmds[cmd].cmd); GC9A01_send_cmd(GC_init_cmds[cmd].cmd);
GC9A01_send_data(GC_init_cmds[cmd].data, GC_init_cmds[cmd].databytes&0x1F); GC9A01_send_data(GC_init_cmds[cmd].data, GC_init_cmds[cmd].databytes&0x1F);
if (GC_init_cmds[cmd].databytes & 0x80) { if (GC_init_cmds[cmd].databytes & 0x80) {
vTaskDelay(100 / portTICK_RATE_MS); vTaskDelay(pdMS_TO_TICKS(100));
} }
cmd++; cmd++;
} }
@ -220,24 +207,36 @@ static void GC9A01_send_color(void * data, uint16_t length)
static void GC9A01_set_orientation(uint8_t orientation) static void GC9A01_set_orientation(uint8_t orientation)
{ {
// ESP_ASSERT(orientation < 4); assert(orientation < 4);
#if defined CONFIG_LV_PREDEFINED_DISPLAY_M5STACK
const uint8_t data[] = {0x68, 0x68, 0x08, 0x08};
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_WROVER4)
const uint8_t data[] = {0x4C, 0x88, 0x28, 0xE8};
#else
const uint8_t data[] = {0x08, 0xC8, 0x68, 0xA8};
#endif
#if (LV_USE_LOG == 1)
const char *orientation_str[] = { const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED" "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
}; };
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); LV_LOG_INFO("Display orientation: %s", orientation_str[orientation]);
LV_LOG_INFO("0x36 command value: 0x%02X", data[orientation]);
#if defined CONFIG_LV_PREDEFINED_DISPLAY_M5STACK
uint8_t data[] = {0x68, 0x68, 0x08, 0x08}; ///
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_WROVER4)
uint8_t data[] = {0x4C, 0x88, 0x28, 0xE8}; ///
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE)
uint8_t data[] = {0x08, 0xC8, 0x68, 0xA8}; ///ggggg
#endif #endif
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]);
GC9A01_send_cmd(0x36); GC9A01_send_cmd(0x36);
GC9A01_send_data((void *) &data[orientation], 1); GC9A01_send_data((void *) &data[orientation], 1);
} }
static void GC9A01_reset(void)
{
#if GC9A01_USE_RST
//Reset the display
gpio_set_level(GC9A01_RST, 0);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(GC9A01_RST, 1);
vTaskDelay(pdMS_TO_TICKS(100));
#endif
}

View file

@ -178,10 +178,6 @@ menu "LVGL TFT Display controller"
bool bool
help help
PCD8544 display controller (Nokia 3110/5110) PCD8544 display controller (Nokia 3110/5110)
config LV_TFT_DISPLAY_CONTROLLER_SCHMITT
bool
help
Schmitt's display controller
# Display controller communication protocol # Display controller communication protocol
# #
# This symbols define the communication protocol used by the # This symbols define the communication protocol used by the
@ -218,8 +214,8 @@ menu "LVGL TFT Display controller"
config LV_DISPLAY_ORIENTATION config LV_DISPLAY_ORIENTATION
int int
default 0 if LV_DISPLAY_ORIENTATION_PORTRAIT default 0 if LV_DISPLAY_ORIENTATION_PORTRAIT
default 1 if LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED default 2 if LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED
default 2 if LV_DISPLAY_ORIENTATION_LANDSCAPE default 1 if LV_DISPLAY_ORIENTATION_LANDSCAPE
default 3 if LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED default 3 if LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED
config LV_TFT_DISPLAY_OFFSETS config LV_TFT_DISPLAY_OFFSETS
@ -230,15 +226,15 @@ menu "LVGL TFT Display controller"
config LV_TFT_DISPLAY_X_OFFSET config LV_TFT_DISPLAY_X_OFFSET
depends on LV_TFT_DISPLAY_OFFSETS depends on LV_TFT_DISPLAY_OFFSETS
int "X offset" int "X offset"
default 40 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) default 40 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_LANDSCAPE || DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
default 53 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED) default 53 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_PORTRAIT || DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
default 0 default 0
config LV_TFT_DISPLAY_Y_OFFSET config LV_TFT_DISPLAY_Y_OFFSET
depends on LV_TFT_DISPLAY_OFFSETS depends on LV_TFT_DISPLAY_OFFSETS
int "Y offset" int "Y offset"
default 53 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) default 53 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_LANDSCAPE || DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
default 40 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED) default 40 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_PORTRAIT || DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
default 0 default 0
@ -353,10 +349,6 @@ menu "LVGL TFT Display controller"
select LV_TFT_DISPLAY_CONTROLLER_PCD8544 select LV_TFT_DISPLAY_CONTROLLER_PCD8544
select LV_TFT_DISPLAY_PROTOCOL_SPI select LV_TFT_DISPLAY_PROTOCOL_SPI
select LV_TFT_DISPLAY_MONOCHROME select LV_TFT_DISPLAY_MONOCHROME
config LV_TFT_DISPLAY_USER_CONTROLLER_SCHMITT
bool "SCHMITT"
select LV_TFT_DISPLAY_CONTROLLER_SCHMITT
select LV_TFT_DISPLAY_PROTOCOL_SPI
endchoice endchoice
config CUSTOM_DISPLAY_BUFFER_SIZE config CUSTOM_DISPLAY_BUFFER_SIZE
@ -484,7 +476,9 @@ menu "LVGL TFT Display controller"
config LV_TFT_DISPLAY_SPI2_HOST config LV_TFT_DISPLAY_SPI2_HOST
bool "SPI2_HOST" bool "SPI2_HOST"
config LV_TFT_DISPLAY_SPI3_HOST config LV_TFT_DISPLAY_SPI3_HOST
bool "SPI3_HOST" bool "SPI3_HOST" if !IDF_TARGET_ESP32C3
help
Select the SPI Bus the TFT Display is attached to.
endchoice endchoice
choice choice
@ -501,6 +495,18 @@ menu "LVGL TFT Display controller"
bool "QIO (4-bit Quad SPI)" bool "QIO (4-bit Quad SPI)"
endchoice endchoice
config LV_TFT_DISPLAY_USE_CUSTOM_SPI_MODE
bool "Use custom SPI Mode" if LV_TFT_DISPLAY_PROTOCOL_SPI
help
Allow user to choose a custom SPI mode
config LV_TFT_DISPLAY_CUSTOM_SPI_MODE
int "Custom SPI Mode"
range 0 3
depends on LV_TFT_DISPLAY_USE_CUSTOM_SPI_MODE
help
Custom SPI mode, representing a pair of (CPOL, CPHA) configuration.
choice choice
prompt "TFT SPI Duplex Mode" if LV_TFT_DISPLAY_PROTOCOL_SPI prompt "TFT SPI Duplex Mode" if LV_TFT_DISPLAY_PROTOCOL_SPI
default LV_TFT_DISPLAY_SPI_FULL_DUPLEX if LV_PREDEFINED_DISPLAY_RPI_RA8875 || LV_TFT_DISPLAY_CONTROLLER_FT81X default LV_TFT_DISPLAY_SPI_FULL_DUPLEX if LV_PREDEFINED_DISPLAY_RPI_RA8875 || LV_TFT_DISPLAY_CONTROLLER_FT81X
@ -914,6 +920,13 @@ menu "LVGL TFT Display controller"
help help
Configure the display Reset pin here. Configure the display Reset pin here.
config LV_DISP_USE_BUSY
bool "Use a GPIO for busy signal" if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D
default y if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D
default n
help
Use a GPIO for busy signal available in e-ink display controllers.
config LV_DISP_PIN_BUSY config LV_DISP_PIN_BUSY
int "GPIO for Busy" if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D int "GPIO for Busy" if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D
default 35 if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D default 35 if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D

View file

@ -7,16 +7,16 @@
#include "esp_lcd_backlight.h" #include "esp_lcd_backlight.h"
#include "sdkconfig.h" #include "sdkconfig.h"
void *disp_driver_init(void) void *disp_driver_init(lv_disp_drv_t *drv)
{ {
#if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341 #if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341
ili9341_init(); ili9341_init(drv);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481 #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
ili9481_init(); ili9481_init();
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488 #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
ili9488_init(); ili9488_init(drv);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789 #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789
st7789_init(); st7789_init(drv);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S
st7796s_init(); st7796s_init();
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S
@ -44,11 +44,14 @@ void *disp_driver_init(void)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
ili9163c_init(); ili9163c_init();
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544 #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
pcd8544_init(); pcd8544_init(drv);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SCHMITT
schmitt_init();
#endif #endif
return disp_backlight_init();
}
void *disp_backlight_init(void)
{
// We still use menuconfig for these settings // We still use menuconfig for these settings
// It will be set up during runtime in the future // It will be set up during runtime in the future
#if (defined(CONFIG_LV_DISP_BACKLIGHT_SWITCH) || defined(CONFIG_LV_DISP_BACKLIGHT_PWM)) #if (defined(CONFIG_LV_DISP_BACKLIGHT_SWITCH) || defined(CONFIG_LV_DISP_BACKLIGHT_PWM))
@ -113,8 +116,6 @@ void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t *
ili9163c_flush(drv, area, color_map); ili9163c_flush(drv, area, color_map);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544 #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
pcd8544_flush(drv, area, color_map); pcd8544_flush(drv, area, color_map);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SCHMITT
schmitt_flush(drv, area, color_map);
#endif #endif
} }

View file

@ -54,8 +54,6 @@ extern "C" {
#include "ili9163c.h" #include "ili9163c.h"
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544 #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
#include "pcd8544.h" #include "pcd8544.h"
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SCHMITT
#include "schmitt.h"
#endif #endif
/********************* /*********************
@ -71,7 +69,7 @@ extern "C" {
**********************/ **********************/
/* Initialize display */ /* Initialize display */
void *disp_driver_init(void); void *disp_driver_init(lv_disp_drv_t *drv);
/* Display flush callback */ /* Display flush callback */
void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
@ -83,6 +81,8 @@ void disp_driver_rounder(lv_disp_drv_t * disp_drv, lv_area_t * area);
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, 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,
lv_color_t color, lv_opa_t opa); lv_color_t color, lv_opa_t opa);
/* Display backlight configuration */
void *disp_backlight_init(void);
/********************** /**********************
* MACROS * MACROS
**********************/ **********************/

63
lvgl_tft/display_port.h Normal file
View file

@ -0,0 +1,63 @@
#ifndef DISPLAY_PORT_H_
#define DISPLAY_PORT_H_
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#include <stdint.h>
#include <stdbool.h>
/**
* Busy wait delay port
*
* @param drv Pointer to driver See @ref lv_disp_drv_t
* @param delay_ms Delay duration in milliseconds
*/
void display_port_delay(lv_disp_drv_t *drv, uint32_t delay_ms);
/**
* Backlight control port
*
* @param drv Pointer to driver See @ref lv_disp_drv_t
* @param state State of the backlight signal
*/
void display_port_backlight(lv_disp_drv_t *drv, uint8_t state);
/**
* DC signal control port
*
* @param drv Pointer to driver See @ref lv_disp_drv_t
* @param state State of the DC signal, 1 for logic high, 0 for logic low
*/
void display_port_gpio_dc(lv_disp_drv_t *drv, uint8_t state);
/**
* Hardware reset control port
*
* @param drv Pointer to driver See @ref lv_disp_drv_t
* @param state State of the reset signal, 1 for logic high, 0 for logic low
*/
void display_port_gpio_rst(lv_disp_drv_t *drv, uint8_t state);
/**
* Display is busy port
*
* @param drv Pointer to driver See @ref lv_disp_drv_t
*
* @retval Returns false when display is not busy, true otherwise.
*/
bool display_port_gpio_is_busy(lv_disp_drv_t *drv);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View file

@ -18,15 +18,12 @@
#include "hx8357.h" #include "hx8357.h"
#include "disp_spi.h" #include "disp_spi.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include <esp_log.h>
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "HX8357"
#define MADCTL_MY 0x80 ///< Bottom to top #define MADCTL_MY 0x80 ///< Bottom to top
#define MADCTL_MX 0x40 ///< Right to left #define MADCTL_MX 0x40 ///< Right to left
#define MADCTL_MV 0x20 ///< Reverse Mode #define MADCTL_MV 0x20 ///< Reverse Mode
@ -52,7 +49,7 @@ typedef struct {
static void hx8357_send_cmd(uint8_t cmd); static void hx8357_send_cmd(uint8_t cmd);
static void hx8357_send_data(void * data, uint16_t length); static void hx8357_send_data(void * data, uint16_t length);
static void hx8357_send_color(void * data, uint16_t length); static void hx8357_send_color(void * data, uint16_t length);
static void hx8357_reset(void);
/********************** /**********************
* INITIALIZATION ARRAYS * INITIALIZATION ARRAYS
@ -159,22 +156,9 @@ static uint8_t displayType = HX8357D;
void hx8357_init(void) void hx8357_init(void)
{ {
//Initialize non-SPI GPIOs hx8357_reset();
gpio_pad_select_gpio(HX8357_DC);
gpio_set_direction(HX8357_DC, GPIO_MODE_OUTPUT);
#if HX8357_USE_RST LV_LOG_INFO("Initialization.");
gpio_pad_select_gpio(HX8357_RST);
gpio_set_direction(HX8357_RST, GPIO_MODE_OUTPUT);
//Reset the display
gpio_set_level(HX8357_RST, 0);
vTaskDelay(10 / portTICK_RATE_MS);
gpio_set_level(HX8357_RST, 1);
vTaskDelay(120 / portTICK_RATE_MS);
#endif
ESP_LOGI(TAG, "Initialization.");
//Send all the commands //Send all the commands
const uint8_t *addr = (displayType == HX8357B) ? initb : initd; const uint8_t *addr = (displayType == HX8357B) ? initb : initd;
@ -192,7 +176,7 @@ void hx8357_init(void)
} }
} }
if (x & 0x80) { // If high bit set... if (x & 0x80) { // If high bit set...
vTaskDelay(numArgs * 5 / portTICK_RATE_MS); // numArgs is actually a delay time (5ms units) vTaskDelay(numArgs * pdMS_TO_TICKS(5)); // numArgs is actually a delay time (5ms units)
} }
} }
@ -289,3 +273,13 @@ static void hx8357_send_color(void * data, uint16_t length)
gpio_set_level(HX8357_DC, 1); /*Data mode*/ gpio_set_level(HX8357_DC, 1); /*Data mode*/
disp_spi_send_colors(data, length); disp_spi_send_colors(data, length);
} }
static void hx8357_reset(void)
{
#if HX8357_USE_RST
gpio_set_level(HX8357_RST, 0);
vTaskDelay(pdMS_TO_TICKS(10));
gpio_set_level(HX8357_RST, 1);
vTaskDelay(pdMS_TO_TICKS(120));
#endif
}

View file

@ -30,7 +30,6 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
*********************/ *********************/
#include "disp_spi.h" #include "disp_spi.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
@ -39,7 +38,6 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "IL3820"
/** /**
* SSD1673, SSD1608 compatible EPD controller driver. * SSD1673, SSD1608 compatible EPD controller driver.
@ -102,6 +100,7 @@ static inline void il3820_set_window( uint16_t sx, uint16_t ex, uint16_t ys, uin
static inline void il3820_set_cursor(uint16_t sx, uint16_t ys); static inline void il3820_set_cursor(uint16_t sx, uint16_t ys);
static void il3820_update_display(void); static void il3820_update_display(void);
static void il3820_clear_cntlr_mem(uint8_t ram_cmd, bool update); static void il3820_clear_cntlr_mem(uint8_t ram_cmd, bool update);
static void il3820_reset(void);
/* Required by LVGL */ /* Required by LVGL */
void il3820_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) void il3820_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
@ -180,7 +179,9 @@ void il3820_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t* buf,
BIT_CLEAR(buf[byte_index], 7 - bit_index); BIT_CLEAR(buf[byte_index], 7 - bit_index);
} }
#else #else
#error "Unsupported orientation used" (void)byte_index;
(void)bit_index;
assert(false); // Unsupported orientation configured. Crash if we get here, but allow compilation for CI
#endif #endif
} }
@ -195,26 +196,7 @@ void il3820_init(void)
{ {
uint8_t tmp[3] = {0}; uint8_t tmp[3] = {0};
/* Initialize non-SPI GPIOs */ il3820_reset();
gpio_pad_select_gpio(IL3820_DC_PIN);
gpio_set_direction(IL3820_DC_PIN, GPIO_MODE_OUTPUT);
gpio_pad_select_gpio(IL3820_BUSY_PIN);
gpio_set_direction(IL3820_BUSY_PIN, GPIO_MODE_INPUT);
#if IL3820_USE_RST
gpio_pad_select_gpio(IL3820_RST_PIN);
gpio_set_direction(IL3820_RST_PIN, GPIO_MODE_OUTPUT);
/* Harware reset */
gpio_set_level( IL3820_RST_PIN, 0);
vTaskDelay(IL3820_RESET_DELAY / portTICK_RATE_MS);
gpio_set_level( IL3820_RST_PIN, 1);
vTaskDelay(IL3820_RESET_DELAY / portTICK_RATE_MS);
#endif
/* Software reset */
il3820_write_cmd(IL3820_CMD_SW_RESET, NULL, 0);
/* Busy wait for the BUSY signal to go low */ /* Busy wait for the BUSY signal to go low */
il3820_waitbusy(IL3820_WAIT); il3820_waitbusy(IL3820_WAIT);
@ -267,17 +249,17 @@ static void il3820_waitbusy(int wait_ms)
{ {
int i = 0; int i = 0;
vTaskDelay(10 / portTICK_RATE_MS); // 10ms delay vTaskDelay(pdMS_TO_TICKS(10)); // 10ms delay
for(i = 0; i < (wait_ms * 10); i++) { for(i = 0; i < (wait_ms * 10); i++) {
if(gpio_get_level(IL3820_BUSY_PIN) != IL3820_BUSY_LEVEL) { if(gpio_get_level(IL3820_BUSY_PIN) != IL3820_BUSY_LEVEL) {
return; return;
} }
vTaskDelay(10 / portTICK_RATE_MS); vTaskDelay(pdMS_TO_TICKS(10));
} }
ESP_LOGE( TAG, "busy exceeded %dms", i*10 ); LV_LOG_ERROR("Busy exceeded %dms", i*10 );
} }
/* Set DC signal to command mode */ /* Set DC signal to command mode */
@ -416,3 +398,17 @@ static void il3820_clear_cntlr_mem(uint8_t ram_cmd, bool update)
il3820_update_display(); il3820_update_display();
} }
} }
static void il3820_reset(void)
{
#if IL3820_USE_RST
/* Harware reset */
gpio_set_level( IL3820_RST_PIN, 0);
vTaskDelay(pdMS_TO_TICKS(IL3820_RESET_DELAY));
gpio_set_level( IL3820_RST_PIN, 1);
vTaskDelay(pdMS_TO_TICKS(IL3820_RESET_DELAY));
#endif
/* Software reset */
il3820_write_cmd(IL3820_CMD_SW_RESET, NULL, 0);
}

View file

@ -20,8 +20,19 @@ extern "C"
/* Values for Waveshare 2.9inch e-Paper Module, this values shouldn't be /* Values for Waveshare 2.9inch e-Paper Module, this values shouldn't be
* swapped to change display orientation */ * swapped to change display orientation */
#if defined (LV_HOR_RES_MAX)
#define EPD_PANEL_WIDTH LV_HOR_RES_MAX /* 128 */ #define EPD_PANEL_WIDTH LV_HOR_RES_MAX /* 128 */
#else
/* Fallback to default value */
#define EPD_PANEL_WIDTH 128u
#endif
#if defined (LV_VER_RES_MAX)
#define EPD_PANEL_HEIGHT LV_VER_RES_MAX /* 296 */ #define EPD_PANEL_HEIGHT LV_VER_RES_MAX /* 296 */
#else
/* Fallback to default value */
#define EPD_PANEL_HEIGHT 296u
#endif
/* 128 = panel width */ /* 128 = panel width */
#define IL3820_COLUMNS (EPD_PANEL_WIDTH / 8) #define IL3820_COLUMNS (EPD_PANEL_WIDTH / 8)

View file

@ -9,7 +9,6 @@
#include "ili9163c.h" #include "ili9163c.h"
#include "disp_spi.h" #include "disp_spi.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "assert.h" #include "assert.h"
@ -17,8 +16,6 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "ILI9163C"
// ILI9163C specific commands used in init // ILI9163C specific commands used in init
#define ILI9163C_NOP 0x00 #define ILI9163C_NOP 0x00
#define ILI9163C_SWRESET 0x01 #define ILI9163C_SWRESET 0x01
@ -69,7 +66,7 @@
#define ST77XX_MADCTL_MY 0x80 #define ST77XX_MADCTL_MY 0x80
#define ST77XX_MADCTL_MX 0x40 #define ST77XX_MADCTL_MX 0x40
#define ST77XX_MADCTL_MV 0x20 #define #define ST77XX_MADCTL_MV 0x20
#define ST77XX_MADCTL_ML 0x10 #define ST77XX_MADCTL_ML 0x10
#define ST77XX_MADCTL_RGB 0x00 #define ST77XX_MADCTL_RGB 0x00
#define ST77XX_MADCTL_BGR 0x08 #define ST77XX_MADCTL_BGR 0x08
@ -94,7 +91,7 @@ static void ili9163c_set_orientation(uint8_t orientation);
static void ili9163c_send_cmd(uint8_t cmd); static void ili9163c_send_cmd(uint8_t cmd);
static void ili9163c_send_data(void *data, uint16_t length); static void ili9163c_send_data(void *data, uint16_t length);
static void ili9163c_send_color(void *data, uint16_t length); static void ili9163c_send_color(void *data, uint16_t length);
static void ili9163c_reset(void);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
@ -109,7 +106,7 @@ static void ili9163c_send_color(void *data, uint16_t length);
void ili9163c_init(void) void ili9163c_init(void)
{ {
ESP_LOGD(TAG, "Init"); LV_LOG_INFO("Init");
lcd_init_cmd_t ili_init_cmds[] = { lcd_init_cmd_t ili_init_cmds[] = {
{ILI9163C_SWRESET, {0}, 0x80}, // Software reset, 0 args, w/delay 120ms {ILI9163C_SWRESET, {0}, 0x80}, // Software reset, 0 args, w/delay 120ms
@ -137,17 +134,7 @@ void ili9163c_init(void)
{0, {0}, 0xff} {0, {0}, 0xff}
}; };
//Initialize non-SPI GPIOs ili9163c_reset();
gpio_pad_select_gpio(ILI9163C_DC);
gpio_set_direction(ILI9163C_DC, GPIO_MODE_OUTPUT);
gpio_pad_select_gpio(ILI9163C_RST);
gpio_set_direction(ILI9163C_RST, GPIO_MODE_OUTPUT);
//Reset the display
gpio_set_level(ILI9163C_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ILI9163C_RST, 1);
vTaskDelay(150 / portTICK_RATE_MS);
//Send all the commands //Send all the commands
uint16_t cmd = 0; uint16_t cmd = 0;
@ -157,7 +144,7 @@ void ili9163c_init(void)
ili9163c_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes & 0x1F); ili9163c_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes & 0x1F);
if (ili_init_cmds[cmd].databytes & 0x80) if (ili_init_cmds[cmd].databytes & 0x80)
{ {
vTaskDelay(150 / portTICK_RATE_MS); vTaskDelay(pdMS_TO_TICKS(150));
} }
cmd++; cmd++;
} }
@ -236,13 +223,25 @@ static void ili9163c_set_orientation(uint8_t orientation)
{ {
assert(orientation < 4); assert(orientation < 4);
#if (LV_USE_LOG == 1)
const char *orientation_str[] = { const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"}; "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"};
ESP_LOGD(TAG, "Display orientation: %s", orientation_str[orientation]); LV_LOG_INFO("Display orientation: %s", orientation_str[orientation]);
#endif
uint8_t data[] = {0x48, 0x88, 0xA8, 0x68}; uint8_t data[] = {0x48, 0x88, 0xA8, 0x68};
ili9163c_send_cmd(ILI9163C_MADCTL); ili9163c_send_cmd(ILI9163C_MADCTL);
ili9163c_send_data((void *)&data[orientation], 1); ili9163c_send_data((void *)&data[orientation], 1);
} }
static void ili9163c_reset(void)
{
#if CONFIG_LV_DISP_USE_RST
gpio_set_level(ILI9163C_RST, 0);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(ILI9163C_RST, 1);
vTaskDelay(pdMS_TO_TICKS(150));
#else
#endif
}

View file

@ -7,22 +7,24 @@
* INCLUDES * INCLUDES
*********************/ *********************/
#include "ili9341.h" #include "ili9341.h"
#include "disp_spi.h" #include "disp_spi.h"
#include "driver/gpio.h" #include "display_port.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "ILI9341" #define END_OF_CMD_MARKER 0xFFU
#define MEMORY_ACCESS_CONTROL_REG 0x36U
#define SOFTWARE_RESET_REG 0x01U
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
/*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */ /*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */
typedef struct { typedef struct {
uint8_t cmd; uint8_t cmd;
uint8_t data[16]; uint8_t data[16];
@ -32,12 +34,13 @@ typedef struct {
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
static void ili9341_set_orientation(uint8_t orientation); static void ili9341_set_orientation(lv_disp_drv_t * drv, uint8_t orientation);
static void ili9341_send_cmd(uint8_t cmd); static void ili9341_send_cmd(lv_disp_drv_t * drv, uint8_t cmd);
static void ili9341_send_data(void * data, uint16_t length); static void ili9341_send_data(lv_disp_drv_t * drv, void * data, uint16_t length);
static void ili9341_send_color(void * data, uint16_t length); static void ili9341_send_color(lv_disp_drv_t * drv, void * data, uint16_t length);
static void ili9341_reset(lv_disp_drv_t * drv);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
@ -50,21 +53,27 @@ static void ili9341_send_color(void * data, uint16_t length);
* GLOBAL FUNCTIONS * GLOBAL FUNCTIONS
**********************/ **********************/
void ili9341_init(void) void ili9341_init(lv_disp_drv_t * drv)
{ {
lcd_init_cmd_t ili_init_cmds[]={ lcd_init_cmd_t ili_init_cmds[] = {
{0xCF, {0x00, 0x83, 0X30}, 3}, {0xCF, {0x00, 0x83, 0X30}, 3},
{0xED, {0x64, 0x03, 0X12, 0X81}, 4}, {0xED, {0x64, 0x03, 0X12, 0X81}, 4},
{0xE8, {0x85, 0x01, 0x79}, 3}, {0xE8, {0x85, 0x01, 0x79}, 3},
{0xCB, {0x39, 0x2C, 0x00, 0x34, 0x02}, 5}, {0xCB, {0x39, 0x2C, 0x00, 0x34, 0x02}, 5},
{0xF7, {0x20}, 1}, {0xF7, {0x20}, 1},
{0xEA, {0x00, 0x00}, 2}, {0xEA, {0x00, 0x00}, 2},
{0xC0, {0x26}, 1}, /*Power control*/ /* Power control */
{0xC1, {0x11}, 1}, /*Power control */ {0xC0, {0x26}, 1},
{0xC5, {0x35, 0x3E}, 2}, /*VCOM control*/ /* Power control */
{0xC7, {0xBE}, 1}, /*VCOM control*/ {0xC1, {0x11}, 1},
{0x36, {0x28}, 1}, /*Memory Access Control*/ /* VCOM control */
{0x3A, {0x55}, 1}, /*Pixel Format Set*/ {0xC5, {0x35, 0x3E}, 2},
/* VCOM control */
{0xC7, {0xBE}, 1},
/* Memory Access Control */
{0x36, {0x28}, 1},
/* Pixel Format Set */
{0x3A, {0x55}, 1},
{0xB1, {0x00, 0x1B}, 2}, {0xB1, {0x00, 0x1B}, 2},
{0xF2, {0x08}, 1}, {0xF2, {0x08}, 1},
{0x26, {0x01}, 1}, {0x26, {0x01}, 1},
@ -77,135 +86,139 @@ void ili9341_init(void)
{0xB6, {0x0A, 0x82, 0x27, 0x00}, 4}, {0xB6, {0x0A, 0x82, 0x27, 0x00}, 4},
{0x11, {0}, 0x80}, {0x11, {0}, 0x80},
{0x29, {0}, 0x80}, {0x29, {0}, 0x80},
{0, {0}, 0xff}, {0, {0}, END_OF_CMD_MARKER},
}; };
//Initialize non-SPI GPIOs ili9341_reset(drv);
gpio_pad_select_gpio(ILI9341_DC);
gpio_set_direction(ILI9341_DC, GPIO_MODE_OUTPUT);
#if ILI9341_USE_RST
gpio_pad_select_gpio(ILI9341_RST);
gpio_set_direction(ILI9341_RST, GPIO_MODE_OUTPUT);
//Reset the display
gpio_set_level(ILI9341_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ILI9341_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
ESP_LOGI(TAG, "Initialization.");
//Send all the commands //Send all the commands
uint16_t cmd = 0; uint16_t cmd = 0;
while (ili_init_cmds[cmd].databytes!=0xff) { while (ili_init_cmds[cmd].databytes != END_OF_CMD_MARKER) {
ili9341_send_cmd(ili_init_cmds[cmd].cmd); ili9341_send_cmd(drv, ili_init_cmds[cmd].cmd);
ili9341_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F); ili9341_send_data(drv, ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes & 0x1F);
if (ili_init_cmds[cmd].databytes & 0x80) { if (ili_init_cmds[cmd].databytes & 0x80) {
vTaskDelay(100 / portTICK_RATE_MS); display_port_delay(drv, 100);
} }
cmd++; cmd++;
} }
ili9341_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION); ili9341_set_orientation(drv, ILI9341_INITIAL_ORIENTATION);
#if ILI9341_INVERT_COLORS == 1 #if ILI9341_INVERT_COLORS == 1U
ili9341_send_cmd(0x21); ili9341_send_cmd(drv, 0x21);
#else #else
ili9341_send_cmd(0x20); ili9341_send_cmd(drv, 0x20);
#endif #endif
} }
void ili9341_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map) void ili9341_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
{ {
uint8_t data[4]; uint8_t data[4] = {0};
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
/*Column addresses*/ /*Column addresses*/
ili9341_send_cmd(0x2A);
data[0] = (area->x1 >> 8) & 0xFF; data[0] = (area->x1 >> 8) & 0xFF;
data[1] = area->x1 & 0xFF; data[1] = area->x1 & 0xFF;
data[2] = (area->x2 >> 8) & 0xFF; data[2] = (area->x2 >> 8) & 0xFF;
data[3] = area->x2 & 0xFF; data[3] = area->x2 & 0xFF;
ili9341_send_data(data, 4);
/*Page addresses*/ ili9341_send_cmd(drv, 0x2A);
ili9341_send_cmd(0x2B); ili9341_send_data(drv, data, 4);
/* Page addresses */
data[0] = (area->y1 >> 8) & 0xFF; data[0] = (area->y1 >> 8) & 0xFF;
data[1] = area->y1 & 0xFF; data[1] = area->y1 & 0xFF;
data[2] = (area->y2 >> 8) & 0xFF; data[2] = (area->y2 >> 8) & 0xFF;
data[3] = area->y2 & 0xFF; data[3] = area->y2 & 0xFF;
ili9341_send_data(data, 4);
/*Memory write*/ ili9341_send_cmd(drv, 0x2B);
ili9341_send_cmd(0x2C); ili9341_send_data(drv, data, 4);
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
ili9341_send_color((void*)color_map, size * 2); /* Memory write */
ili9341_send_cmd(drv, 0x2C);
ili9341_send_color(drv, (void*)color_map, size * 2);
} }
void ili9341_sleep_in() void ili9341_sleep_in(lv_disp_drv_t * drv)
{ {
uint8_t data[] = {0x08}; uint8_t data[] = {0x08};
ili9341_send_cmd(0x10); ili9341_send_cmd(drv, 0x10);
ili9341_send_data(&data, 1); ili9341_send_data(drv, data, 1);
} }
void ili9341_sleep_out() void ili9341_sleep_out(lv_disp_drv_t * drv)
{ {
uint8_t data[] = {0x08}; uint8_t data[] = {0x08};
ili9341_send_cmd(0x11); ili9341_send_cmd(drv, 0x11);
ili9341_send_data(&data, 1); ili9341_send_data(drv, data, 1);
} }
/********************** /**********************
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
static inline void set_cmd_mode(lv_disp_drv_t * drv)
{
display_port_gpio_dc(drv, 0);
}
static void ili9341_send_cmd(uint8_t cmd) static inline void set_data_mode(lv_disp_drv_t * drv)
{
display_port_gpio_dc(drv, 1);
}
static void ili9341_send_cmd(lv_disp_drv_t * drv, uint8_t cmd)
{ {
disp_wait_for_pending_transactions(); disp_wait_for_pending_transactions();
gpio_set_level(ILI9341_DC, 0); /*Command mode*/ set_cmd_mode(drv);
disp_spi_send_data(&cmd, 1); disp_spi_send_data(&cmd, 1);
} }
static void ili9341_send_data(void * data, uint16_t length) static void ili9341_send_data(lv_disp_drv_t *drv, void * data, uint16_t length)
{ {
disp_wait_for_pending_transactions(); disp_wait_for_pending_transactions();
gpio_set_level(ILI9341_DC, 1); /*Data mode*/ set_data_mode(drv);
disp_spi_send_data(data, length); disp_spi_send_data(data, length);
} }
static void ili9341_send_color(void * data, uint16_t length) static void ili9341_send_color(lv_disp_drv_t *drv, void * data, uint16_t length)
{ {
disp_wait_for_pending_transactions(); disp_wait_for_pending_transactions();
gpio_set_level(ILI9341_DC, 1); /*Data mode*/ set_data_mode(drv);
disp_spi_send_colors(data, length); disp_spi_send_colors(data, length);
} }
static void ili9341_set_orientation(uint8_t orientation) static void ili9341_set_orientation(lv_disp_drv_t *drv, uint8_t orientation)
{ {
// ESP_ASSERT(orientation < 4); assert(orientation < 4);
const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
};
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]);
#if defined CONFIG_LV_PREDEFINED_DISPLAY_M5STACK #if defined CONFIG_LV_PREDEFINED_DISPLAY_M5STACK
uint8_t data[] = {0x68, 0x68, 0x08, 0x08}; const uint8_t data[] = {0x68, 0x68, 0x08, 0x08};
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_M5CORE2) #elif defined (CONFIG_LV_PREDEFINED_DISPLAY_M5CORE2)
uint8_t data[] = {0x08, 0x88, 0x28, 0xE8}; const uint8_t data[] = {0x08, 0x88, 0x28, 0xE8};
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_WROVER4) #elif defined (CONFIG_LV_PREDEFINED_DISPLAY_WROVER4)
uint8_t data[] = {0x6C, 0xEC, 0xCC, 0x4C}; const uint8_t data[] = {0x6C, 0xEC, 0xCC, 0x4C};
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE) #else
uint8_t data[] = {0x48, 0x88, 0x28, 0xE8}; const uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
#endif #endif
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]); ili9341_send_cmd(drv, MEMORY_ACCESS_CONTROL_REG);
ili9341_send_data(drv, (void *) &data[orientation], 1);
ili9341_send_cmd(0x36); }
ili9341_send_data((void *) &data[orientation], 1);
/* Reset the display, if we don't have a reset pin we use software reset */
static void ili9341_reset(lv_disp_drv_t *drv)
{
#if defined(ILI9341_USE_RST)
display_port_gpio_rst(drv, 0);
display_port_delay(drv, 100);
display_port_gpio_rst(drv, 1);
display_port_delay(drv, 100);
#else
ili9341_send_cmd(drv, SOFTWARE_RESET_REG);
display_port_delay(drv, 5);
#endif
} }

View file

@ -13,23 +13,17 @@ extern "C" {
/********************* /*********************
* INCLUDES * INCLUDES
*********************/ *********************/
#include <stdbool.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE #ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h" #include "lvgl.h"
#else #else
#include "lvgl/lvgl.h" #include "lvgl/lvgl.h"
#endif #endif
#include "sdkconfig.h" #include "display_config.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define ILI9341_DC CONFIG_LV_DISP_PIN_DC
#define ILI9341_USE_RST CONFIG_LV_DISP_USE_RST
#define ILI9341_RST CONFIG_LV_DISP_PIN_RST
#define ILI9341_INVERT_COLORS CONFIG_LV_INVERT_COLORS
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@ -39,10 +33,10 @@ extern "C" {
* GLOBAL PROTOTYPES * GLOBAL PROTOTYPES
**********************/ **********************/
void ili9341_init(void); void ili9341_init(lv_disp_drv_t * drv);
void ili9341_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); void ili9341_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
void ili9341_sleep_in(void); void ili9341_sleep_in(lv_disp_drv_t * drv);
void ili9341_sleep_out(void); void ili9341_sleep_out(lv_disp_drv_t *drv);
/********************** /**********************
* MACROS * MACROS

View file

@ -8,16 +8,13 @@
#include "ili9481.h" #include "ili9481.h"
#include "disp_spi.h" #include "disp_spi.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_log.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "ILI9481"
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@ -38,6 +35,7 @@ static void ili9481_set_orientation(uint8_t orientation);
static void ili9481_send_cmd(uint8_t cmd); static void ili9481_send_cmd(uint8_t cmd);
static void ili9481_send_data(void * data, uint16_t length); static void ili9481_send_data(void * data, uint16_t length);
static void ili9481_send_color(void * data, uint16_t length); static void ili9481_send_color(void * data, uint16_t length);
static void ili9481_reset(void);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@ -73,26 +71,9 @@ void ili9481_init(void)
{0, {0}, 0xff}, {0, {0}, 0xff},
}; };
//Initialize non-SPI GPIOs ili9481_reset();
gpio_pad_select_gpio(ILI9481_DC);
gpio_set_direction(ILI9481_DC, GPIO_MODE_OUTPUT);
#if ILI9481_USE_RST LV_LOG_INFO("Initialization.");
gpio_pad_select_gpio(ILI9481_RST);
gpio_set_direction(ILI9481_RST, GPIO_MODE_OUTPUT);
//Reset the display
gpio_set_level(ILI9481_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ILI9481_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
ESP_LOGI(TAG, "ILI9481 initialization.");
// Exit sleep
ili9481_send_cmd(0x01); /* Software reset */
vTaskDelay(100 / portTICK_RATE_MS);
//Send all the commands //Send all the commands
uint16_t cmd = 0; uint16_t cmd = 0;
@ -100,7 +81,7 @@ void ili9481_init(void)
ili9481_send_cmd(ili_init_cmds[cmd].cmd); ili9481_send_cmd(ili_init_cmds[cmd].cmd);
ili9481_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F); ili9481_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F);
if (ili_init_cmds[cmd].databytes & 0x80) { if (ili_init_cmds[cmd].databytes & 0x80) {
vTaskDelay(100 / portTICK_RATE_MS); vTaskDelay(pdMS_TO_TICKS(100));
} }
cmd++; cmd++;
} }
@ -111,13 +92,16 @@ void ili9481_init(void)
// Flush function based on mvturnho repo // Flush function based on mvturnho repo
void ili9481_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map) void ili9481_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
{ {
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area); /* 3 is number of bytes in lv_color_t */
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area) * 3;
lv_color16_t *buffer_16bit = (lv_color16_t *) color_map; lv_color16_t *buffer_16bit = (lv_color16_t *) color_map;
uint8_t *mybuf; uint8_t *mybuf;
do { do {
mybuf = (uint8_t *) heap_caps_malloc(3 * size * sizeof(uint8_t), MALLOC_CAP_DMA); mybuf = (uint8_t *) heap_caps_malloc(3 * size * sizeof(uint8_t), MALLOC_CAP_DMA);
if (mybuf == NULL) ESP_LOGW(TAG, "Could not allocate enough DMA memory!"); if (mybuf == NULL) {
LV_LOG_WARN("Could not allocate enough DMA memory!");
}
} while (mybuf == NULL); } while (mybuf == NULL);
uint32_t LD = 0; uint32_t LD = 0;
@ -160,7 +144,9 @@ void ili9481_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * col
/*Memory write*/ /*Memory write*/
ili9481_send_cmd(ILI9481_CMD_MEMORY_WRITE); ili9481_send_cmd(ILI9481_CMD_MEMORY_WRITE);
ili9481_send_color((void *) mybuf, size * 3); ili9481_send_color((void *) mybuf, size);
/* FIXME: Can we free the memory even when it's being transferred? */
heap_caps_free(mybuf); heap_caps_free(mybuf);
} }
@ -192,13 +178,29 @@ static void ili9481_send_color(void * data, uint16_t length)
static void ili9481_set_orientation(uint8_t orientation) static void ili9481_set_orientation(uint8_t orientation)
{ {
#if (LV_USE_LOG == 1)
const char *orientation_str[] = { const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED" "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
}; };
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); LV_LOG_INFO("Display orientation: %s", orientation_str[orientation]);
#endif
uint8_t data[] = {0x48, 0x4B, 0x28, 0x2B}; uint8_t data[] = {0x48, 0x4B, 0x28, 0x2B};
ili9481_send_cmd(ILI9481_CMD_MEMORY_ACCESS_CONTROL); ili9481_send_cmd(ILI9481_CMD_MEMORY_ACCESS_CONTROL);
ili9481_send_data((void *) &data[orientation], 1); ili9481_send_data((void *) &data[orientation], 1);
} }
static void ili9481_reset(void)
{
#if ILI9481_USE_RST
gpio_set_level(ILI9481_RST, 0);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(ILI9481_RST, 1);
vTaskDelay(pdMS_TO_TICKS(100));
#else
// Exit sleep, software reset
ili9481_send_cmd(0x01);
vTaskDelay(pdMS_TO_TICKS(100));
#endif
}

View file

@ -9,14 +9,12 @@
#include "ili9486.h" #include "ili9486.h"
#include "disp_spi.h" #include "disp_spi.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "ILI9486"
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@ -37,7 +35,7 @@ static void ili9486_set_orientation(uint8_t orientation);
static void ili9486_send_cmd(uint8_t cmd); static void ili9486_send_cmd(uint8_t cmd);
static void ili9486_send_data(void * data, uint16_t length); static void ili9486_send_data(void * data, uint16_t length);
static void ili9486_send_color(void * data, uint16_t length); static void ili9486_send_color(void * data, uint16_t length);
static void ili9486_reset(void);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
@ -65,22 +63,9 @@ void ili9486_init(void)
{0x00, {0}, 0xff}, {0x00, {0}, 0xff},
}; };
//Initialize non-SPI GPIOs ili9486_reset();
gpio_pad_select_gpio(ILI9486_DC);
gpio_set_direction(ILI9486_DC, GPIO_MODE_OUTPUT);
#if ILI9486_USE_RST LV_LOG_INFO("ILI9486 Initialization.");
gpio_pad_select_gpio(ILI9486_RST);
gpio_set_direction(ILI9486_RST, GPIO_MODE_OUTPUT);
//Reset the display
gpio_set_level(ILI9486_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ILI9486_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
ESP_LOGI(TAG, "ILI9486 Initialization.");
//Send all the commands //Send all the commands
uint16_t cmd = 0; uint16_t cmd = 0;
@ -88,7 +73,7 @@ void ili9486_init(void)
ili9486_send_cmd(ili_init_cmds[cmd].cmd); ili9486_send_cmd(ili_init_cmds[cmd].cmd);
ili9486_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F); ili9486_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F);
if (ili_init_cmds[cmd].databytes & 0x80) { if (ili_init_cmds[cmd].databytes & 0x80) {
vTaskDelay(100 / portTICK_RATE_MS); vTaskDelay(pdMS_TO_TICKS(100));
} }
cmd++; cmd++;
} }
@ -99,7 +84,8 @@ void ili9486_init(void)
void ili9486_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map) void ili9486_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
{ {
uint8_t data[4] = {0}; uint8_t data[4] = {0};
uint32_t size = 0; /* 2 is the number of bytes in color depth */
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area) * 2;
/*Column addresses*/ /*Column addresses*/
ili9486_send_cmd(0x2A); ili9486_send_cmd(0x2A);
@ -119,10 +105,7 @@ void ili9486_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * col
/*Memory write*/ /*Memory write*/
ili9486_send_cmd(0x2C); ili9486_send_cmd(0x2C);
ili9486_send_color((void*) color_map, size);
size = lv_area_get_width(area) * lv_area_get_height(area);
ili9486_send_color((void*) color_map, size * 2);
} }
/********************** /**********************
@ -165,20 +148,29 @@ static void ili9486_send_color(void * data, uint16_t length)
static void ili9486_set_orientation(uint8_t orientation) static void ili9486_set_orientation(uint8_t orientation)
{ {
// ESP_ASSERT(orientation < 4); assert(orientation < 4);
const uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
#if (LV_USE_LOG == 1)
const char *orientation_str[] = { const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED" "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
}; };
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); LV_LOG_INFO("Display orientation: %s", orientation_str[orientation]);
LV_LOG_INFO("0x36 command value: 0x%02X", data[orientation]);
#if defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE)
uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
#endif #endif
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]);
ili9486_send_cmd(0x36); ili9486_send_cmd(0x36);
ili9486_send_data((void *) &data[orientation], 1); ili9486_send_data((void *) &data[orientation], 1);
} }
static void ili9486_reset(void)
{
#if ILI9486_USE_RST
gpio_set_level(ILI9486_RST, 0);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(ILI9486_RST, 1);
vTaskDelay(pdMS_TO_TICKS(100));
#endif
}

View file

@ -6,18 +6,14 @@
* INCLUDES * INCLUDES
*********************/ *********************/
#include "ili9488.h" #include "ili9488.h"
#include "disp_spi.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h" #include "disp_spi.h"
#include "freertos/task.h" #include "display_port.h"
#include "esp_heap_caps.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "ILI9488"
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@ -33,11 +29,12 @@ typedef struct {
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
static void ili9488_set_orientation(uint8_t orientation); static void ili9488_set_orientation(lv_disp_drv_t * drv, uint8_t orientation);
static void ili9488_send_cmd(uint8_t cmd); static void ili9488_send_cmd(lv_disp_drv_t * drv, uint8_t cmd);
static void ili9488_send_data(void * data, uint16_t length); static void ili9488_send_data(lv_disp_drv_t * drv, void * data, uint16_t length);
static void ili9488_send_color(void * data, uint16_t length); static void ili9488_send_color(lv_disp_drv_t * drv, void * data, uint16_t length);
static void ili9488_reset(lv_disp_drv_t * drv);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@ -52,7 +49,7 @@ static void ili9488_send_color(void * data, uint16_t length);
**********************/ **********************/
// From github.com/jeremyjh/ESP32_TFT_library // From github.com/jeremyjh/ESP32_TFT_library
// From github.com/mvturnho/ILI9488-lvgl-ESP32-WROVER-B // From github.com/mvturnho/ILI9488-lvgl-ESP32-WROVER-B
void ili9488_init(void) void ili9488_init(lv_disp_drv_t * drv)
{ {
lcd_init_cmd_t ili_init_cmds[]={ lcd_init_cmd_t ili_init_cmds[]={
{ILI9488_CMD_SLEEP_OUT, {0x00}, 0x80}, {ILI9488_CMD_SLEEP_OUT, {0x00}, 0x80},
@ -75,39 +72,24 @@ void ili9488_init(void)
{0, {0}, 0xff}, {0, {0}, 0xff},
}; };
//Initialize non-SPI GPIOs ili9488_reset(drv);
gpio_pad_select_gpio(ILI9488_DC);
gpio_set_direction(ILI9488_DC, GPIO_MODE_OUTPUT);
#if ILI9488_USE_RST LV_LOG_INFO("ILI9488 initialization.");
gpio_pad_select_gpio(ILI9488_RST);
gpio_set_direction(ILI9488_RST, GPIO_MODE_OUTPUT);
//Reset the display
gpio_set_level(ILI9488_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ILI9488_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
ESP_LOGI(TAG, "ILI9488 initialization.");
// Exit sleep
ili9488_send_cmd(0x01); /* Software reset */
vTaskDelay(100 / portTICK_RATE_MS);
//Send all the commands //Send all the commands
uint16_t cmd = 0; uint16_t cmd = 0;
while (ili_init_cmds[cmd].databytes!=0xff) { while (ili_init_cmds[cmd].databytes!=0xff) {
ili9488_send_cmd(ili_init_cmds[cmd].cmd); ili9488_send_cmd(drv, ili_init_cmds[cmd].cmd);
ili9488_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F); ili9488_send_data(drv, ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F);
if (ili_init_cmds[cmd].databytes & 0x80) { if (ili_init_cmds[cmd].databytes & 0x80) {
vTaskDelay(100 / portTICK_RATE_MS); display_port_delay(drv, 100);
} }
cmd++; cmd++;
} }
ili9488_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION); ili9488_set_orientation(drv, ILI9488_INITIAL_ORIENTATION);
} }
// Flush function based on mvturnho repo // Flush function based on mvturnho repo
@ -119,7 +101,9 @@ void ili9488_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * col
uint8_t *mybuf; uint8_t *mybuf;
do { do {
mybuf = (uint8_t *) heap_caps_malloc(3 * size * sizeof(uint8_t), MALLOC_CAP_DMA); mybuf = (uint8_t *) heap_caps_malloc(3 * size * sizeof(uint8_t), MALLOC_CAP_DMA);
if (mybuf == NULL) ESP_LOGW(TAG, "Could not allocate enough DMA memory!"); if (mybuf == NULL) {
LV_LOG_WARN("Could not allocate enough DMA memory!");
}
} while (mybuf == NULL); } while (mybuf == NULL);
uint32_t LD = 0; uint32_t LD = 0;
@ -152,17 +136,17 @@ void ili9488_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * col
}; };
/*Column addresses*/ /*Column addresses*/
ili9488_send_cmd(ILI9488_CMD_COLUMN_ADDRESS_SET); ili9488_send_cmd(drv, ILI9488_CMD_COLUMN_ADDRESS_SET);
ili9488_send_data(xb, 4); ili9488_send_data(drv, xb, 4);
/*Page addresses*/ /*Page addresses*/
ili9488_send_cmd(ILI9488_CMD_PAGE_ADDRESS_SET); ili9488_send_cmd(drv, ILI9488_CMD_PAGE_ADDRESS_SET);
ili9488_send_data(yb, 4); ili9488_send_data(drv, yb, 4);
/*Memory write*/ /*Memory write*/
ili9488_send_cmd(ILI9488_CMD_MEMORY_WRITE); ili9488_send_cmd(drv, ILI9488_CMD_MEMORY_WRITE);
ili9488_send_color((void *) mybuf, size * 3); ili9488_send_color(drv, (void *) mybuf, size * 3);
heap_caps_free(mybuf); heap_caps_free(mybuf);
} }
@ -170,44 +154,65 @@ void ili9488_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * col
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
static inline void set_cmd_mode(lv_disp_drv_t * drv)
{
display_port_gpio_dc(drv, 0);
}
static void ili9488_send_cmd(uint8_t cmd) static inline void set_data_mode(lv_disp_drv_t * drv)
{
display_port_gpio_dc(drv, 1);
}
static void ili9488_send_cmd(lv_disp_drv_t * drv, uint8_t cmd)
{ {
disp_wait_for_pending_transactions(); disp_wait_for_pending_transactions();
gpio_set_level(ILI9488_DC, 0); /*Command mode*/ set_cmd_mode(drv);
disp_spi_send_data(&cmd, 1); disp_spi_send_data(&cmd, 1);
} }
static void ili9488_send_data(void * data, uint16_t length) static void ili9488_send_data(lv_disp_drv_t * drv, void * data, uint16_t length)
{ {
disp_wait_for_pending_transactions(); disp_wait_for_pending_transactions();
gpio_set_level(ILI9488_DC, 1); /*Data mode*/ set_data_mode(drv);
disp_spi_send_data(data, length); disp_spi_send_data(data, length);
} }
static void ili9488_send_color(void * data, uint16_t length) static void ili9488_send_color(lv_disp_drv_t * drv, void * data, uint16_t length)
{ {
disp_wait_for_pending_transactions(); disp_wait_for_pending_transactions();
gpio_set_level(ILI9488_DC, 1); /*Data mode*/ set_data_mode(drv);
disp_spi_send_colors(data, length); disp_spi_send_colors(data, length);
} }
static void ili9488_set_orientation(uint8_t orientation) static void ili9488_set_orientation(lv_disp_drv_t * drv, uint8_t orientation)
{ {
// ESP_ASSERT(orientation < 4); assert(orientation < 4);
const uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
#if (LV_USE_LOG == 1)
const char *orientation_str[] = { const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED" "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
}; };
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); LV_LOG_INFO("Display orientation: %s", orientation_str[orientation]);
LV_LOG_INFO("0x36 command value: 0x%02X", data[orientation]);
#if defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE)
uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
#endif #endif
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]); ili9488_send_cmd(drv, 0x36);
ili9488_send_data(drv, (void *) &data[orientation], 1);
ili9488_send_cmd(0x36); }
ili9488_send_data((void *) &data[orientation], 1);
/* Reset the display, if we don't have a reset pin we use software reset */
static void ili9488_reset(lv_disp_drv_t *drv)
{
#if defined(ILI9488_USE_RST)
display_port_gpio_rst(drv, 0);
display_port_delay(drv, 100);
display_port_gpio_rst(drv, 1);
display_port_delay(drv, 100);
#else
ili9488_send_cmd(drv, 0x01);
display_port_delay(drv, 5);
#endif
} }

View file

@ -20,14 +20,13 @@ extern "C" {
#else #else
#include "lvgl/lvgl.h" #include "lvgl/lvgl.h"
#endif #endif
#include "../lvgl_helpers.h" #include "../lvgl_helpers.h"
#include "display_config.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define ILI9488_DC CONFIG_LV_DISP_PIN_DC
#define ILI9488_RST CONFIG_LV_DISP_PIN_RST
#define ILI9488_USE_RST CONFIG_LV_DISP_USE_RSTS
/******************* /*******************
* ILI9488 REGS * ILI9488 REGS
@ -144,7 +143,7 @@ typedef struct {
* GLOBAL PROTOTYPES * GLOBAL PROTOTYPES
**********************/ **********************/
void ili9488_init(void); void ili9488_init(lv_disp_drv_t * drv);
void ili9488_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); void ili9488_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
/********************** /**********************

View file

@ -29,23 +29,39 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
#include <freertos/task.h> #include <freertos/task.h>
#include <freertos/event_groups.h> #include <freertos/event_groups.h>
#include <driver/gpio.h> #include <driver/gpio.h>
#include <esp_log.h>
#include "disp_spi.h" #include "disp_spi.h"
#include "jd79653a.h" #include "jd79653a.h"
#define TAG "lv_jd79653a"
#define PIN_DC CONFIG_LV_DISP_PIN_DC #define PIN_DC CONFIG_LV_DISP_PIN_DC
#define PIN_DC_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_DC))) #define PIN_DC_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_DC)))
#if defined CONFIG_LV_DISP_PIN_RST
#define PIN_RST CONFIG_LV_DISP_PIN_RST #define PIN_RST CONFIG_LV_DISP_PIN_RST
#define PIN_RST_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_RST))) #define PIN_RST_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_RST)))
#endif
#define PIN_BUSY CONFIG_LV_DISP_PIN_BUSY #define PIN_BUSY CONFIG_LV_DISP_PIN_BUSY
#define PIN_BUSY_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_BUSY))) #define PIN_BUSY_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_BUSY)))
#define EVT_BUSY (1UL << 0UL) #define EVT_BUSY (1UL << 0UL)
#if defined (LV_HOR_RES_MAX)
#define EPD_WIDTH LV_HOR_RES_MAX #define EPD_WIDTH LV_HOR_RES_MAX
#else
/* ToDo Remove magic number */
#define EPD_WIDTH 256u
#endif
#if defined (LV_VER_RES_MAX)
#define EPD_HEIGHT LV_VER_RES_MAX #define EPD_HEIGHT LV_VER_RES_MAX
#else
/* ToDo Remove magic number */
#define EPD_HEIGHT 128u
#endif
#define EPD_ROW_LEN (EPD_HEIGHT / 8u) #define EPD_ROW_LEN (EPD_HEIGHT / 8u)
/* ToDo Remove semicolon */
#define EPD_PARTIAL_CNT 5; #define EPD_PARTIAL_CNT 5;
#define BIT_SET(a, b) ((a) |= (1U << (b))) #define BIT_SET(a, b) ((a) |= (1U << (b)))
@ -123,10 +139,9 @@ static const uint8_t lut_bb1[] = {
static const jd79653a_seq_t init_seq[] = { static const jd79653a_seq_t init_seq[] = {
#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED) #if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
{0x00, {0xd3, 0x0e}, 2}, // Panel settings {0x00, {0xd3, 0x0e}, 2}, // Panel settings
#elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT) //#elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
{0x00, {0xdf, 0x0e}, 2}, // Panel settings
#else #else
#error "Unsupported orientation - only portrait modes are supported for now" {0x00, {0xdf, 0x0e}, 2}, // Panel settings
#endif #endif
{0x4d, {0x55}, 1}, // Undocumented secret from demo code {0x4d, {0x55}, 1}, // Undocumented secret from demo code
{0xaa, {0x0f}, 1}, // Undocumented secret from demo code {0xaa, {0x0f}, 1}, // Undocumented secret from demo code
@ -176,16 +191,9 @@ static void jd79653a_spi_send_data(uint8_t *data, size_t len)
disp_spi_send_data(data, len); disp_spi_send_data(data, len);
} }
static void jd79653a_spi_send_fb(uint8_t *data, size_t len)
{
disp_wait_for_pending_transactions();
gpio_set_level(PIN_DC, 1); // DC = 1 for data
disp_spi_send_colors(data, len);
}
static void jd79653a_spi_send_seq(const jd79653a_seq_t *seq, size_t len) static void jd79653a_spi_send_seq(const jd79653a_seq_t *seq, size_t len)
{ {
ESP_LOGD(TAG, "Writing cmd/data sequence, count %u", len); LV_LOG_INFO("Writing cmd/data sequence, count %u", len);
if (!seq || len < 1) return; if (!seq || len < 1) return;
for (size_t cmd_idx = 0; cmd_idx < len; cmd_idx++) { for (size_t cmd_idx = 0; cmd_idx < len; cmd_idx++) {
@ -207,21 +215,21 @@ static esp_err_t jd79653a_wait_busy(uint32_t timeout_ms)
return ((bits & EVT_BUSY) != 0) ? ESP_OK : ESP_ERR_TIMEOUT; return ((bits & EVT_BUSY) != 0) ? ESP_OK : ESP_ERR_TIMEOUT;
} }
static void jd79653a_power_on() static void jd79653a_power_on(void)
{ {
jd79653a_spi_send_seq(power_on_seq, EPD_SEQ_LEN(power_on_seq)); jd79653a_spi_send_seq(power_on_seq, EPD_SEQ_LEN(power_on_seq));
vTaskDelay(pdMS_TO_TICKS(10)); vTaskDelay(pdMS_TO_TICKS(10));
jd79653a_wait_busy(0); jd79653a_wait_busy(0);
} }
static void jd79653a_power_off() static void jd79653a_power_off(void)
{ {
jd79653a_spi_send_seq(power_off_seq, EPD_SEQ_LEN(power_off_seq)); jd79653a_spi_send_seq(power_off_seq, EPD_SEQ_LEN(power_off_seq));
vTaskDelay(pdMS_TO_TICKS(10)); vTaskDelay(pdMS_TO_TICKS(10));
jd79653a_wait_busy(0); jd79653a_wait_busy(0);
} }
static void jd79653a_load_partial_lut() static void jd79653a_load_partial_lut(void)
{ {
jd79653a_spi_send_cmd(0x20); // LUT VCOM register jd79653a_spi_send_cmd(0x20); // LUT VCOM register
jd79653a_spi_send_data((uint8_t *)lut_vcom_dc1, sizeof(lut_vcom_dc1)); jd79653a_spi_send_data((uint8_t *)lut_vcom_dc1, sizeof(lut_vcom_dc1));
@ -239,9 +247,9 @@ static void jd79653a_load_partial_lut()
jd79653a_spi_send_data((uint8_t *)lut_bb1, sizeof(lut_bb1)); jd79653a_spi_send_data((uint8_t *)lut_bb1, sizeof(lut_bb1));
} }
static void jd79653a_partial_in() static void jd79653a_partial_in(void)
{ {
ESP_LOGD(TAG, "Partial in!"); LV_LOG_INFO("Partial in!");
// Panel setting: accept LUT from registers instead of OTP // Panel setting: accept LUT from registers instead of OTP
#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED) #if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
@ -249,7 +257,8 @@ static void jd79653a_partial_in()
#elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT) #elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
uint8_t pst_use_reg_lut[] = { 0xff, 0x0e }; uint8_t pst_use_reg_lut[] = { 0xff, 0x0e };
#else #else
#error "Unsupported orientation - only portrait modes are supported for now" assert(false); // Unsupported orientation configured. Crash if we get here, but allow compilation for CI
uint8_t pst_use_reg_lut[] = { 0,0 };
#endif #endif
jd79653a_spi_send_cmd(0x00); jd79653a_spi_send_cmd(0x00);
jd79653a_spi_send_data(pst_use_reg_lut, sizeof(pst_use_reg_lut)); jd79653a_spi_send_data(pst_use_reg_lut, sizeof(pst_use_reg_lut));
@ -266,9 +275,9 @@ static void jd79653a_partial_in()
jd79653a_spi_send_cmd(0x91); jd79653a_spi_send_cmd(0x91);
} }
static void jd79653a_partial_out() static void jd79653a_partial_out(void)
{ {
ESP_LOGD(TAG, "Partial out!"); LV_LOG_INFO("Partial out!");
// Panel setting: use LUT from OTP // Panel setting: use LUT from OTP
#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED) #if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
@ -276,7 +285,8 @@ static void jd79653a_partial_out()
#elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT) #elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
uint8_t pst_use_otp_lut[] = { 0xdf, 0x0e }; uint8_t pst_use_otp_lut[] = { 0xdf, 0x0e };
#else #else
#error "Unsupported orientation - only portrait modes are supported for now" assert(false); // Unsupported orientation configured. Crash if we get here, but allow compilation for CI
uint8_t pst_use_otp_lut[] = { 0,0 };
#endif #endif
jd79653a_spi_send_cmd(0x00); jd79653a_spi_send_cmd(0x00);
jd79653a_spi_send_data(pst_use_otp_lut, sizeof(pst_use_otp_lut)); jd79653a_spi_send_data(pst_use_otp_lut, sizeof(pst_use_otp_lut));
@ -294,10 +304,10 @@ static void jd79653a_update_partial(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t
{ {
jd79653a_power_on(); jd79653a_power_on();
jd79653a_partial_in(); jd79653a_partial_in();
ESP_LOGD(TAG, "x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", x1, x2, y1, y2); LV_LOG_INFO("x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", x1, x2, y1, y2);
size_t len = ((x2 - x1 + 1) * (y2 - y1 + 1)) / 8; size_t len = ((x2 - x1 + 1) * (y2 - y1 + 1)) / 8;
ESP_LOGD(TAG, "Writing PARTIAL LVGL fb with len: %u", len); LV_LOG_INFO("Writing PARTIAL LVGL fb with len: %u", len);
// Set partial window // Set partial window
uint8_t ptl_setting[7] = { x1, x2, 0, y1, 0, y2, 0x01 }; uint8_t ptl_setting[7] = { x1, x2, 0, y1, 0, y2, 0x01 };
@ -313,16 +323,18 @@ static void jd79653a_update_partial(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t
len -= EPD_ROW_LEN; len -= EPD_ROW_LEN;
} }
ESP_LOGD(TAG, "Partial wait start"); LV_LOG_INFO("Partial wait start");
jd79653a_spi_send_cmd(0x12); jd79653a_spi_send_cmd(0x12);
jd79653a_wait_busy(0); jd79653a_wait_busy(0);
ESP_LOGD(TAG, "Partial updated"); LV_LOG_INFO("Partial updated");
jd79653a_partial_out(); jd79653a_partial_out();
jd79653a_power_off(); jd79653a_power_off();
} }
static void jd79653a_reset(void);
void jd79653a_fb_set_full_color(uint8_t color) void jd79653a_fb_set_full_color(uint8_t color)
{ {
jd79653a_power_on(); jd79653a_power_on();
@ -353,7 +365,7 @@ void jd79653a_fb_set_full_color(uint8_t color)
void jd79653a_fb_full_update(uint8_t *data, size_t len) void jd79653a_fb_full_update(uint8_t *data, size_t len)
{ {
jd79653a_power_on(); jd79653a_power_on();
ESP_LOGD(TAG, "Performing full update, len: %u", len); LV_LOG_INFO("Performing full update, len: %u", len);
uint8_t *data_ptr = data; uint8_t *data_ptr = data;
@ -372,7 +384,7 @@ void jd79653a_fb_full_update(uint8_t *data, size_t len)
len -= EPD_ROW_LEN; len -= EPD_ROW_LEN;
} }
ESP_LOGD(TAG, "Rest len: %u", len); LV_LOG_INFO("Rest len: %u", len);
jd79653a_spi_send_cmd(0x12); // Issue refresh command jd79653a_spi_send_cmd(0x12); // Issue refresh command
vTaskDelay(pdMS_TO_TICKS(100)); vTaskDelay(pdMS_TO_TICKS(100));
@ -381,7 +393,7 @@ void jd79653a_fb_full_update(uint8_t *data, size_t len)
jd79653a_power_off(); jd79653a_power_off();
} }
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, void jd79653a_lv_set_fb_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) lv_color_t color, lv_opa_t opa)
{ {
uint16_t byte_index = (x >> 3u) + (y * EPD_ROW_LEN); uint16_t byte_index = (x >> 3u) + (y * EPD_ROW_LEN);
@ -394,7 +406,7 @@ void jd79653a_lv_set_fb_cb(struct _disp_drv_t *disp_drv, uint8_t *buf, lv_coord_
} }
} }
void jd79653a_lv_rounder_cb(struct _disp_drv_t *disp_drv, lv_area_t *area) void jd79653a_lv_rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area)
{ {
// Always send full framebuffer if it's not in partial mode // Always send full framebuffer if it's not in partial mode
area->x1 = 0; area->x1 = 0;
@ -405,15 +417,16 @@ void jd79653a_lv_rounder_cb(struct _disp_drv_t *disp_drv, lv_area_t *area)
void jd79653a_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) void jd79653a_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
{ {
#if LV_USE_LOG
size_t len = ((area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1)) / 8; size_t len = ((area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1)) / 8;
LV_LOG_INFO("x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", area->x1, area->x2, area->y1, area->y2);
ESP_LOGD(TAG, "x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", area->x1, area->x2, area->y1, area->y2); LV_LOG_INFO("Writing LVGL fb with len: %u, partial counter: %u", len, partial_counter);
ESP_LOGD(TAG, "Writing LVGL fb with len: %u, partial counter: %u", len, partial_counter); #endif
uint8_t *buf = (uint8_t *) color_map; uint8_t *buf = (uint8_t *) color_map;
if (partial_counter == 0) { if (partial_counter == 0) {
ESP_LOGD(TAG, "Refreshing in FULL"); LV_LOG_INFO("Refreshing in FULL");
jd79653a_fb_full_update(buf, ((EPD_HEIGHT * EPD_WIDTH) / 8)); jd79653a_fb_full_update(buf, ((EPD_HEIGHT * EPD_WIDTH) / 8));
partial_counter = EPD_PARTIAL_CNT; // Reset partial counter here partial_counter = EPD_PARTIAL_CNT; // Reset partial counter here
} else { } else {
@ -424,7 +437,7 @@ void jd79653a_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t
lv_disp_flush_ready(drv); lv_disp_flush_ready(drv);
} }
void jd79653a_deep_sleep() void jd79653a_deep_sleep(void)
{ {
jd79653a_spi_send_seq(power_off_seq, EPD_SEQ_LEN(power_off_seq)); jd79653a_spi_send_seq(power_off_seq, EPD_SEQ_LEN(power_off_seq));
jd79653a_wait_busy(1000); jd79653a_wait_busy(1000);
@ -434,25 +447,15 @@ void jd79653a_deep_sleep()
jd79653a_spi_send_data(&check_code, sizeof(check_code)); jd79653a_spi_send_data(&check_code, sizeof(check_code));
} }
void jd79653a_init() void jd79653a_init(void)
{ {
// Initialise event group // Initialise event group
jd79653a_evts = xEventGroupCreate(); jd79653a_evts = xEventGroupCreate();
if (!jd79653a_evts) { if (!jd79653a_evts) {
ESP_LOGE(TAG, "Failed when initialising event group!"); LV_LOG_ERROR("Failed when initialising event group!");
return; return;
} }
// Setup output pins, output (PP)
gpio_config_t out_io_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = PIN_DC_BIT | PIN_RST_BIT,
.pull_down_en = 0,
.pull_up_en = 0,
};
ESP_ERROR_CHECK(gpio_config(&out_io_conf));
// Setup input pin, pull-up, input // Setup input pin, pull-up, input
gpio_config_t in_io_conf = { gpio_config_t in_io_conf = {
.intr_type = GPIO_INTR_POSEDGE, .intr_type = GPIO_INTR_POSEDGE,
@ -465,18 +468,25 @@ void jd79653a_init()
gpio_install_isr_service(0); gpio_install_isr_service(0);
gpio_isr_handler_add(PIN_BUSY, jd79653a_busy_intr, (void *) PIN_BUSY); gpio_isr_handler_add(PIN_BUSY, jd79653a_busy_intr, (void *) PIN_BUSY);
// Hardware reset jd79653a_reset();
gpio_set_level(PIN_RST, 0);
vTaskDelay(pdMS_TO_TICKS(15)); // At least 10ms, leave 15ms for now just in case...
gpio_set_level(PIN_RST, 1);
vTaskDelay(pdMS_TO_TICKS(120));
// Dump in initialise sequence // Dump in initialise sequence
jd79653a_spi_send_seq(init_seq, EPD_SEQ_LEN(init_seq)); jd79653a_spi_send_seq(init_seq, EPD_SEQ_LEN(init_seq));
ESP_LOGI(TAG, "Panel init sequence sent"); LV_LOG_INFO("Panel init sequence sent");
// Check BUSY status here // Check BUSY status here
jd79653a_wait_busy(0); jd79653a_wait_busy(0);
ESP_LOGI(TAG, "Panel is up!"); LV_LOG_INFO("Panel is up!");
}
static void jd79653a_reset(void)
{
#if defined CONFIG_LV_DISP_PIN_RST
gpio_set_level(PIN_RST, 0);
// At least 10ms, leave 15ms for now just in case...
vTaskDelay(pdMS_TO_TICKS(15));
gpio_set_level(PIN_RST, 1);
vTaskDelay(pdMS_TO_TICKS(120));
#endif
} }

View file

@ -17,12 +17,12 @@ extern "C"
#include "lvgl/lvgl.h" #include "lvgl/lvgl.h"
#endif #endif
void jd79653a_init(); void jd79653a_init(void);
void jd79653a_deep_sleep(); void jd79653a_deep_sleep(void);
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, void jd79653a_lv_set_fb_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); lv_color_t color, lv_opa_t opa);
void jd79653a_lv_rounder_cb(struct _disp_drv_t * disp_drv, lv_area_t *area); void jd79653a_lv_rounder_cb(lv_disp_drv_t * disp_drv, lv_area_t *area);
void jd79653a_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); void jd79653a_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map);
void jd79653a_fb_set_full_color(uint8_t color); void jd79653a_fb_set_full_color(uint8_t color);

View file

@ -6,15 +6,11 @@
* https://github.com/olikraus/u8g2 * https://github.com/olikraus/u8g2
*/ */
#include "disp_spi.h"
#include "driver/gpio.h"
#include <esp_log.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "pcd8544.h" #include "pcd8544.h"
#include "disp_spi.h"
#include "display_port.h"
#define TAG "lv_pcd8544" #define TAG "lv_pcd8544"
/********************** /**********************
@ -27,24 +23,33 @@
/********************** /**********************
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
static inline void set_cmd_mode(lv_disp_drv_t * drv)
{
display_port_gpio_dc(drv, 0);
}
static void pcd8544_send_cmd(uint8_t cmd) static inline void set_data_mode(lv_disp_drv_t * drv)
{
display_port_gpio_dc(drv, 1);
}
static void pcd8544_send_cmd(lv_disp_drv_t *drv, uint8_t cmd)
{ {
disp_wait_for_pending_transactions(); disp_wait_for_pending_transactions();
gpio_set_level(PCD8544_DC, 0); /*Command mode*/ set_cmd_mode(drv);
disp_spi_send_data(&cmd, 1); disp_spi_send_data(&cmd, 1);
} }
static void pcd8544_send_data(void * data, uint16_t length) static void pcd8544_send_data(lv_disp_drv_t *drv, void * data, uint16_t length)
{ {
disp_wait_for_pending_transactions(); disp_wait_for_pending_transactions();
gpio_set_level(PCD8544_DC, 1); /*Data mode*/ set_data_mode(drv);
disp_spi_send_data(data, length); disp_spi_send_data(data, length);
} }
static void pcd8544_send_colors(void * data, uint16_t length) static void pcd8544_send_colors(lv_disp_drv_t *drv, void * data, uint16_t length)
{ {
gpio_set_level(PCD8544_DC, 1); /*Data mode*/ set_data_mode(drv);
disp_spi_send_colors(data, length); disp_spi_send_colors(data, length);
} }
@ -52,37 +57,38 @@ static void pcd8544_send_colors(void * data, uint16_t length)
* GLOBAL FUNCTIONS * GLOBAL FUNCTIONS
**********************/ **********************/
void pcd8544_init(void){ void pcd8544_reset(lv_disp_drv_t *drv)
{
// TODO: orientation display_port_gpio_rst(drv, 0);
display_port_delay(drv, 100);
// Initialize non-SPI GPIOs display_port_gpio_rst(drv, 1);
gpio_pad_select_gpio(PCD8544_DC); display_port_delay(drv, 100);
gpio_set_direction(PCD8544_DC, GPIO_MODE_OUTPUT);
gpio_pad_select_gpio(PCD8544_RST);
gpio_set_direction(PCD8544_RST, GPIO_MODE_OUTPUT);
// Reset the display
gpio_set_level(PCD8544_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(PCD8544_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
pcd8544_send_cmd(0x21); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */
pcd8544_send_cmd(0x06); /* temp. control: b10 = 2 */
pcd8544_send_cmd(0x13); /* bias system 1:48 */
pcd8544_send_cmd(0xc0); /* medium Vop = Contrast 0x40 = 64 */
pcd8544_send_cmd(0x20); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=0) */
pcd8544_send_cmd(0x0c); /* display mode normal */
} }
void pcd8544_set_contrast (uint8_t contrast){ void pcd8544_init(lv_disp_drv_t *drv)
{
// TODO: orientation
// Reset the display
pcd8544_reset(drv);
pcd8544_send_cmd(drv, 0x21); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */
pcd8544_send_cmd(drv, 0x06); /* temp. control: b10 = 2 */
pcd8544_send_cmd(drv, 0x13); /* bias system 1:48 */
pcd8544_send_cmd(drv, 0xc0); /* medium Vop = Contrast 0x40 = 64 */
pcd8544_send_cmd(drv, 0x20); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=0) */
pcd8544_send_cmd(drv, 0x0c); /* display mode normal */
}
void pcd8544_set_contrast(lv_disp_drv_t *drv, uint8_t contrast)
{
if (contrast > 0x7f){ if (contrast > 0x7f){
contrast = 0x7f; contrast = 0x7f;
} }
pcd8544_send_cmd(0x21); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */
pcd8544_send_cmd(0x80 | contrast); /* medium Vop = Contrast */ pcd8544_send_cmd(drv, 0x21); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */
pcd8544_send_cmd(drv, 0x80 | contrast); /* medium Vop = Contrast */
} }
void pcd8544_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area){ void pcd8544_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area){
@ -112,7 +118,7 @@ void pcd8544_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w
void pcd8544_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_map){ void pcd8544_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_map){
pcd8544_send_cmd(0x20); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=0) */ pcd8544_send_cmd(disp_drv, 0x20); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=0) */
uint8_t * buf = (uint8_t *) color_map; uint8_t * buf = (uint8_t *) color_map;
@ -123,9 +129,9 @@ void pcd8544_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t
// send complete frame buffer at once. // send complete frame buffer at once.
// NOTE: disp_spi_send_colors triggers lv_disp_flush_ready // NOTE: disp_spi_send_colors triggers lv_disp_flush_ready
pcd8544_send_cmd(0x40); /* set Y address */ pcd8544_send_cmd(disp_drv, 0x40); /* set Y address */
pcd8544_send_cmd(0x80); /* set X address */ pcd8544_send_cmd(disp_drv, 0x80); /* set X address */
pcd8544_send_colors(buf, disp_drv->hor_res * disp_drv->ver_res / 8); pcd8544_send_colors(disp_drv, buf, disp_drv->hor_res * disp_drv->ver_res / 8);
} else { } else {
@ -136,11 +142,11 @@ void pcd8544_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t
uint16_t bank; uint16_t bank;
uint16_t cols_to_update = area->x2 - area->x1 + 1; uint16_t cols_to_update = area->x2 - area->x1 + 1;
for (bank = bank_start ; bank <= bank_end ; bank++ ){ for (bank = bank_start ; bank <= bank_end ; bank++){
pcd8544_send_cmd(0x40 | bank ); /* set Y address */ pcd8544_send_cmd(disp_drv, 0x40 | bank); /* set Y address */
pcd8544_send_cmd(0x80 | area->x1 ); /* set X address */ pcd8544_send_cmd(disp_drv, 0x80 | area->x1); /* set X address */
uint16_t offset = bank * disp_drv->hor_res + area->x1; uint16_t offset = bank * disp_drv->hor_res + area->x1;
pcd8544_send_data(&buf[offset], cols_to_update); pcd8544_send_data(disp_drv, &buf[offset], cols_to_update);
} }
lv_disp_flush_ready(disp_drv); lv_disp_flush_ready(disp_drv);

View file

@ -26,10 +26,6 @@ extern "C" {
* DEFINES * DEFINES
*********************/ *********************/
#define PCD8544_DC CONFIG_LV_DISP_PIN_DC
#define PCD8544_RST CONFIG_LV_DISP_PIN_RST
#define PCD8544_BCKL CONFIG_LV_DISP_PIN_BCKL
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
@ -38,12 +34,12 @@ extern "C" {
* GLOBAL PROTOTYPES * GLOBAL PROTOTYPES
**********************/ **********************/
void pcd8544_init(void); void pcd8544_init(lv_disp_drv_t *drv);
void pcd8544_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); void pcd8544_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
void pcd8544_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area); void pcd8544_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area);
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, 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,
lv_color_t color, lv_opa_t opa); lv_color_t color, lv_opa_t opa);
void pcd8544_set_contrast(uint8_t contrast); void pcd8544_set_contrast(lv_disp_drv_t *drv, uint8_t contrast);
/********************** /**********************
* MACROS * MACROS

View file

@ -9,16 +9,12 @@
#include "ra8875.h" #include "ra8875.h"
#include "disp_spi.h" #include "disp_spi.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define DEBUG false
#define TAG "RA8875"
#define DIV_ROUND_UP(n, d) (((n)+(d)-1)/(d)) #define DIV_ROUND_UP(n, d) (((n)+(d)-1)/(d))
#define SPI_CLOCK_SPEED_SLOW_HZ 1000000 #define SPI_CLOCK_SPEED_SLOW_HZ 1000000
@ -28,6 +24,45 @@
#define RA8875_MODE_CMD_WRITE (0x80) #define RA8875_MODE_CMD_WRITE (0x80)
#define RA8875_MODE_STATUS_READ (0xC0) #define RA8875_MODE_STATUS_READ (0xC0)
#define BYTES_PER_PIXEL (LV_COLOR_DEPTH / 8)
#if defined (LV_HOR_RES_MAX)
#define HDWR_VAL (LV_HOR_RES_MAX/8 - 1)
#else
/* ToDo Remove magic number 256u */
#define HDWR_VAL (256u/8u - 1u)
#endif
#if defined (LV_VER_RES_MAX)
#define VDHR_VAL (LV_VER_RES_MAX - 1)
#else
/* ToDo Remove magic number 128u */
#define VDHR_VAL (128u - 1u)
#endif
#define VDIR_MASK (1 << 2)
#define HDIR_MASK (1 << 3)
#ifndef CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875
// Use this settings if there is no Kconfig settings defined
#define SYSR_VAL (0x00)
#define DPCR_VAL (0x00)
#define PCSR_VAL (0x00)
#define HNDR_VAL (0x00)
#define HNDFTR_VAL (0x00)
#define HSTR_VAL (0x00)
#define HPW (0x00)
#define HPWR_VAL (0x00)
#define VNDR_VAL (0x00)
#define VSTR_VAL (0x00)
#define VPW (0x00)
#define VPWR_VAL (0x00)
#define CONFIG_LV_DISP_RA8875_PLLDIVM (0x00)
#define CONFIG_LV_DISP_RA8875_PLLDIVN (0x00)
#define CONFIG_LV_DISP_RA8875_PLLDIVK (0x00)
#else
#if (LV_COLOR_DEPTH == 8) #if (LV_COLOR_DEPTH == 8)
#define SYSR_VAL (0x00) #define SYSR_VAL (0x00)
#elif (LV_COLOR_DEPTH == 16) #elif (LV_COLOR_DEPTH == 16)
@ -35,13 +70,6 @@
#else #else
#error "Unsupported color depth (LV_COLOR_DEPTH)" #error "Unsupported color depth (LV_COLOR_DEPTH)"
#endif #endif
#define BYTES_PER_PIXEL (LV_COLOR_DEPTH / 8)
#define HDWR_VAL (LV_HOR_RES_MAX/8 - 1)
#define VDHR_VAL (LV_VER_RES_MAX - 1)
#define VDIR_MASK (1 << 2)
#define HDIR_MASK (1 << 3)
#if ( CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED || CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED ) #if ( CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED || CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED )
#if CONFIG_LV_INVERT_DISPLAY #if CONFIG_LV_INVERT_DISPLAY
@ -92,6 +120,7 @@
#else #else
#define VPWR_VAL (VPW) #define VPWR_VAL (VPW)
#endif #endif
#endif // CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@ -104,7 +133,7 @@ static void ra8875_configure_clocks(bool high_speed);
static void ra8875_set_memory_write_cursor(unsigned int x, unsigned int y); static void ra8875_set_memory_write_cursor(unsigned int x, unsigned int y);
static void ra8875_set_window(unsigned int xs, unsigned int xe, unsigned int ys, unsigned int ye); static void ra8875_set_window(unsigned int xs, unsigned int xe, unsigned int ys, unsigned int ye);
static void ra8875_send_buffer(uint8_t * data, size_t length, bool signal_flush); static void ra8875_send_buffer(uint8_t * data, size_t length, bool signal_flush);
static void ra8875_reset(void);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
@ -119,6 +148,9 @@ static void ra8875_send_buffer(uint8_t * data, size_t length, bool signal_flush)
void ra8875_init(void) void ra8875_init(void)
{ {
#ifndef CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875
assert(false); // This driver is not properly configured
#endif
unsigned int i = 0; unsigned int i = 0;
struct { struct {
@ -146,20 +178,9 @@ void ra8875_init(void)
}; };
#define INIT_CMDS_SIZE (sizeof(init_cmds)/sizeof(init_cmds[0])) #define INIT_CMDS_SIZE (sizeof(init_cmds)/sizeof(init_cmds[0]))
ESP_LOGI(TAG, "Initializing RA8875..."); LV_LOG_INFO("Initializing RA8875...");
// Initialize non-SPI GPIOs ra8875_reset();
#if RA8875_USE_RST
gpio_pad_select_gpio(RA8875_RST);
gpio_set_direction(RA8875_RST, GPIO_MODE_OUTPUT);
// Reset the RA8875
gpio_set_level(RA8875_RST, 0);
vTaskDelay(DIV_ROUND_UP(100, portTICK_RATE_MS));
gpio_set_level(RA8875_RST, 1);
vTaskDelay(DIV_ROUND_UP(100, portTICK_RATE_MS));
#endif
// Initalize RA8875 clocks (SPI must be decelerated before initializing clocks) // Initalize RA8875 clocks (SPI must be decelerated before initializing clocks)
disp_spi_change_device_speed(SPI_CLOCK_SPEED_SLOW_HZ); disp_spi_change_device_speed(SPI_CLOCK_SPEED_SLOW_HZ);
@ -180,7 +201,7 @@ void ra8875_init(void)
vTaskDelay(1); vTaskDelay(1);
} }
if (i == 0) { if (i == 0) {
ESP_LOGW(TAG, "WARNING: Memory clear timed out; RA8875 may be unresponsive."); LV_LOG_WARN("WARNING: Memory clear timed out; RA8875 may be unresponsive.");
} }
// Enable the display // Enable the display
@ -189,7 +210,7 @@ void ra8875_init(void)
void ra8875_enable_display(bool enable) void ra8875_enable_display(bool enable)
{ {
ESP_LOGI(TAG, "%s display.", enable ? "Enabling" : "Disabling"); LV_LOG_INFO("%s display.", enable ? "Enabling" : "Disabling");
uint8_t val = enable ? (0x80) : (0x00); uint8_t val = enable ? (0x80) : (0x00);
ra8875_write_cmd(RA8875_REG_PWRR, val); // Power and Display Control Register (PWRR) ra8875_write_cmd(RA8875_REG_PWRR, val); // Power and Display Control Register (PWRR)
} }
@ -205,35 +226,47 @@ void ra8875_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * colo
size_t linelen = (area->x2 - area->x1 + 1); size_t linelen = (area->x2 - area->x1 + 1);
uint8_t * buffer = (uint8_t*)color_map; uint8_t * buffer = (uint8_t*)color_map;
#if DEBUG LV_LOG_INFO("flush: %d,%d at %d,%d", area->x1, area->x2, area->y1, area->y2 );
ESP_LOGI(TAG, "flush: %d,%d at %d,%d", area->x1, area->x2, area->y1, area->y2 );
#endif
// Get lock // Get lock
disp_spi_acquire(); disp_spi_acquire();
// Set window if needed // Set window if needed
if ((x1 != area->x1) || (x2 != area->x2)) { if ((x1 != area->x1) || (x2 != area->x2)) {
#if DEBUG LV_LOG_INFO("flush: set window (x1,x2): %d,%d -> %d,%d", x1, x2, area->x1, area->x2);
ESP_LOGI(TAG, "flush: set window (x1,x2): %d,%d -> %d,%d", x1, x2, area->x1, area->x2); unsigned int ye = 0;
#if LVGL_VERSION_MAJOR < 8
ye = LV_VER_RES_MAX - 1;
#else
/* ToDo Get y end from driver information */
#endif #endif
ra8875_set_window(area->x1, area->x2, 0, LV_VER_RES_MAX-1);
ra8875_set_window(area->x1, area->x2, 0, ye);
x1 = area->x1; x1 = area->x1;
x2 = area->x2; x2 = area->x2;
} }
// Set cursor if needed // Set cursor if needed
if ((x != area->x1) || (y != area->y1)) { if ((x != area->x1) || (y != area->y1)) {
#if DEBUG LV_LOG_INFO("flush: set cursor (x,y): %d,%d -> %d,%d", x, y, area->x1, area->y1);
ESP_LOGI(TAG, "flush: set cursor (x,y): %d,%d -> %d,%d", x, y, area->x1, area->y1);
#endif
ra8875_set_memory_write_cursor(area->x1, area->y1); ra8875_set_memory_write_cursor(area->x1, area->y1);
x = area->x1; x = area->x1;
} }
// Update to future cursor location // Update to future cursor location
y = area->y2 + 1; y = area->y2 + 1;
if (y >= LV_VER_RES_MAX) { lv_coord_t ver_max = 0;
#if LVGL_VERSION_MAJOR < 8
ver_max = LV_VER_RES_MAX;
#else
/* ToDo Get vertical max from driver information */
ver_max = lv_disp_get_ver_res((lv_disp_t *) drv);
#endif
if (y >= ver_max) {
y = 0; y = 0;
} }
@ -251,21 +284,21 @@ void ra8875_sleep_in(void)
ra8875_configure_clocks(false); ra8875_configure_clocks(false);
ra8875_write_cmd(RA8875_REG_PWRR, 0x00); // Power and Display Control Register (PWRR) ra8875_write_cmd(RA8875_REG_PWRR, 0x00); // Power and Display Control Register (PWRR)
vTaskDelay(DIV_ROUND_UP(20, portTICK_RATE_MS)); vTaskDelay(DIV_ROUND_UP(20, portTICK_PERIOD_MS));
ra8875_write_cmd(RA8875_REG_PWRR, 0x02); // Power and Display Control Register (PWRR) ra8875_write_cmd(RA8875_REG_PWRR, 0x02); // Power and Display Control Register (PWRR)
} }
void ra8875_sleep_out(void) void ra8875_sleep_out(void)
{ {
ra8875_write_cmd(RA8875_REG_PWRR, 0x00); // Power and Display Control Register (PWRR) ra8875_write_cmd(RA8875_REG_PWRR, 0x00); // Power and Display Control Register (PWRR)
vTaskDelay(DIV_ROUND_UP(20, portTICK_RATE_MS)); vTaskDelay(DIV_ROUND_UP(20, portTICK_PERIOD_MS));
ra8875_configure_clocks(true); ra8875_configure_clocks(true);
disp_spi_change_device_speed(-1); disp_spi_change_device_speed(-1);
ra8875_write_cmd(RA8875_REG_PWRR, 0x80); // Power and Display Control Register (PWRR) ra8875_write_cmd(RA8875_REG_PWRR, 0x80); // Power and Display Control Register (PWRR)
vTaskDelay(DIV_ROUND_UP(20, portTICK_RATE_MS)); vTaskDelay(DIV_ROUND_UP(20, portTICK_PERIOD_MS));
} }
uint8_t ra8875_read_cmd(uint8_t cmd) uint8_t ra8875_read_cmd(uint8_t cmd)
@ -298,7 +331,7 @@ void ra8875_configure_clocks(bool high_speed)
vTaskDelay(1); vTaskDelay(1);
ra8875_write_cmd(RA8875_REG_PCSR, PCSR_VAL); // Pixel Clock Setting Register (PCSR) ra8875_write_cmd(RA8875_REG_PCSR, PCSR_VAL); // Pixel Clock Setting Register (PCSR)
vTaskDelay(DIV_ROUND_UP(20, portTICK_RATE_MS)); vTaskDelay(DIV_ROUND_UP(20, portTICK_PERIOD_MS));
} }
static void ra8875_set_window(unsigned int xs, unsigned int xe, unsigned int ys, unsigned int ye) static void ra8875_set_window(unsigned int xs, unsigned int xe, unsigned int ys, unsigned int ye)
@ -332,3 +365,13 @@ static void ra8875_send_buffer(uint8_t * data, size_t length, bool signal_flush)
| (RA8875_MODE_DATA_WRITE); // Data write mode | (RA8875_MODE_DATA_WRITE); // Data write mode
disp_spi_transaction(data, length, flags, NULL, prefix, 0); disp_spi_transaction(data, length, flags, NULL, prefix, 0);
} }
static void ra8875_reset(void)
{
#if RA8875_USE_RST
gpio_set_level(RA8875_RST, 0);
vTaskDelay(DIV_ROUND_UP(100, portTICK_PERIOD_MS));
gpio_set_level(RA8875_RST, 1);
vTaskDelay(DIV_ROUND_UP(100, portTICK_PERIOD_MS));
#endif
}

View file

@ -1,27 +0,0 @@
#include <stdio.h>
#include "schmitt.h"
#include "disp_spi.h"
#include "esp_log.h"
static const char* TAG = "SCHMITT_DIS";
void schmitt_init(void)
{
disp_spi_acquire();
// Do things
ESP_LOGI(TAG, "schmitt_init() called");
disp_spi_release();
}
void schmitt_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
{
disp_spi_acquire();
// Do things
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
disp_spi_send_colors(color_map, size * 4);
ESP_LOGI(TAG, "schmitt_flush() called");
disp_spi_release();
lv_disp_flush_ready(drv);
}

View file

@ -1,20 +0,0 @@
#ifndef SCHMITT_H_
#define SCHMITT_H_
#include <stdint.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#include "../lvgl_helpers.h"
#define LV_HOR_RES_MAX 64
#define LV_VER_RES_MAX 64
void schmitt_init(void);
void schmitt_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
#endif /* SCHMITT_H_ */

View file

@ -16,7 +16,6 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "SH1107"
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@ -35,6 +34,10 @@ typedef struct {
static void sh1107_send_cmd(uint8_t cmd); static void sh1107_send_cmd(uint8_t cmd);
static void sh1107_send_data(void * data, uint16_t length); static void sh1107_send_data(void * data, uint16_t length);
static void sh1107_send_color(void * data, uint16_t length); static void sh1107_send_color(void * data, uint16_t length);
static void sh1107_reset(void);
static lv_coord_t get_display_ver_res(lv_disp_drv_t *disp_drv);
static lv_coord_t get_display_hor_res(lv_disp_drv_t *disp_drv);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@ -91,20 +94,7 @@ void sh1107_init(void)
{0, {0}, 0xff}, {0, {0}, 0xff},
}; };
//Initialize non-SPI GPIOs sh1107_reset();
gpio_pad_select_gpio(SH1107_DC);
gpio_set_direction(SH1107_DC, GPIO_MODE_OUTPUT);
#if SH1107_USE_RST
gpio_pad_select_gpio(SH1107_RST);
gpio_set_direction(SH1107_RST, GPIO_MODE_OUTPUT);
//Reset the display
gpio_set_level(SH1107_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(SH1107_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
//Send all the commands //Send all the commands
uint16_t cmd = 0; uint16_t cmd = 0;
@ -112,13 +102,13 @@ void sh1107_init(void)
sh1107_send_cmd(init_cmds[cmd].cmd); sh1107_send_cmd(init_cmds[cmd].cmd);
sh1107_send_data(init_cmds[cmd].data, init_cmds[cmd].databytes&0x1F); sh1107_send_data(init_cmds[cmd].data, init_cmds[cmd].databytes&0x1F);
if (init_cmds[cmd].databytes & 0x80) { if (init_cmds[cmd].databytes & 0x80) {
vTaskDelay(100 / portTICK_RATE_MS); vTaskDelay(pdMS_TO_TICKS(100));
} }
cmd++; cmd++;
} }
} }
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, void sh1107_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) lv_color_t color, lv_opa_t opa)
{ {
/* buf_w will be ignored, the configured CONFIG_LV_DISPLAY_HEIGHT and _WIDTH, /* buf_w will be ignored, the configured CONFIG_LV_DISPLAY_HEIGHT and _WIDTH,
@ -127,10 +117,10 @@ void sh1107_set_px_cb(struct _disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t b
uint8_t bit_index = 0; uint8_t bit_index = 0;
#if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE #if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
byte_index = y + (( x>>3 ) * LV_VER_RES_MAX); byte_index = y + (( x>>3 ) * get_display_ver_res(disp_drv));
bit_index = x & 0x7; bit_index = x & 0x7;
#elif defined CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT #elif defined CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT
byte_index = x + (( y>>3 ) * LV_HOR_RES_MAX); byte_index = x + (( y>>3 ) * get_display_hor_res(disp_drv));
bit_index = y & 0x7; bit_index = y & 0x7;
#endif #endif
@ -162,9 +152,9 @@ void sh1107_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * colo
sh1107_send_cmd(0xB0 | i); // Set Page Start Address for Page Addressing Mode sh1107_send_cmd(0xB0 | i); // Set Page Start Address for Page Addressing Mode
size = area->y2 - area->y1 + 1; size = area->y2 - area->y1 + 1;
#if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE #if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
ptr = color_map + i * LV_VER_RES_MAX; ptr = color_map + i * get_display_ver_res(drv);
#else #else
ptr = color_map + i * LV_HOR_RES_MAX; ptr = color_map + i * get_display_hor_res(drv);
#endif #endif
if(i != row2){ if(i != row2){
sh1107_send_data( (void *) ptr, size); sh1107_send_data( (void *) ptr, size);
@ -175,21 +165,21 @@ void sh1107_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * colo
} }
} }
void sh1107_rounder(struct _disp_drv_t * disp_drv, lv_area_t *area) void sh1107_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area)
{ {
// workaround: always send complete size display buffer // workaround: always send complete size display buffer
area->x1 = 0; area->x1 = 0;
area->y1 = 0; area->y1 = 0;
area->x2 = LV_HOR_RES_MAX-1; area->x2 = get_display_hor_res(disp_drv) - 1;
area->y2 = LV_VER_RES_MAX-1; area->y2 = get_display_ver_res(disp_drv) - 1;
} }
void sh1107_sleep_in() void sh1107_sleep_in(void)
{ {
sh1107_send_cmd(0xAE); sh1107_send_cmd(0xAE);
} }
void sh1107_sleep_out() void sh1107_sleep_out(void)
{ {
sh1107_send_cmd(0xAF); sh1107_send_cmd(0xAF);
} }
@ -219,3 +209,49 @@ static void sh1107_send_color(void * data, uint16_t length)
gpio_set_level(SH1107_DC, 1); /*Data mode*/ gpio_set_level(SH1107_DC, 1); /*Data mode*/
disp_spi_send_colors(data, length); disp_spi_send_colors(data, length);
} }
static lv_coord_t get_display_ver_res(lv_disp_drv_t *disp_drv)
{
lv_coord_t val = 0;
#if LVGL_VERSION_MAJOR < 8
#if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
val = LV_VER_RES_MAX;
#endif
#else
/* ToDo Use display rotation API to get vertical size */
#if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
val = lv_disp_get_ver_res((lv_disp_t *) disp_drv);
#endif
#endif
return val;
}
static lv_coord_t get_display_hor_res(lv_disp_drv_t *disp_drv)
{
lv_coord_t val = 0;
#if LVGL_VERSION_MAJOR < 8
#if defined CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT
val = LV_HOR_RES_MAX;
#endif
#else
/* ToDo Use display rotation API to get horizontal size */
#if defined CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT
val = lv_disp_get_hor_res((lv_disp_t *) disp_drv);
#endif
#endif
return val;
}
static void sh1107_reset(void)
{
#if SH1107_USE_RST
gpio_set_level(SH1107_RST, 0);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(SH1107_RST, 1);
vTaskDelay(pdMS_TO_TICKS(100));
#endif
}

View file

@ -39,8 +39,8 @@ extern "C" {
void sh1107_init(void); void sh1107_init(void);
void sh1107_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); void sh1107_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
void sh1107_rounder(struct _disp_drv_t * disp_drv, lv_area_t *area); void sh1107_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area);
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, void sh1107_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); lv_color_t color, lv_opa_t opa);
void sh1107_sleep_in(void); void sh1107_sleep_in(void);
void sh1107_sleep_out(void); void sh1107_sleep_out(void);

View file

@ -22,8 +22,6 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "SSD1306"
#define OLED_I2C_PORT (CONFIG_LV_I2C_DISPLAY_PORT) #define OLED_I2C_PORT (CONFIG_LV_I2C_DISPLAY_PORT)
// SLA (0x3C) + WRITE_MODE (0x00) = 0x78 (0b01111000) // SLA (0x3C) + WRITE_MODE (0x00) = 0x78 (0b01111000)
#define OLED_I2C_ADDRESS 0x3C #define OLED_I2C_ADDRESS 0x3C
@ -106,7 +104,7 @@ void ssd1306_init(void)
orientation_1 = 0xA0; orientation_1 = 0xA0;
orientation_2 = OLED_CMD_SET_COM_SCAN_MODE_NORMAL; orientation_2 = OLED_CMD_SET_COM_SCAN_MODE_NORMAL;
#else #else
#error "Unsupported orientation" assert(false); // Invalid configuration of SSD1306 driver
#endif #endif
uint8_t display_mode = 0; uint8_t display_mode = 0;

View file

@ -9,7 +9,6 @@
#include "st7735s.h" #include "st7735s.h"
#include "disp_spi.h" #include "disp_spi.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
@ -20,7 +19,6 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "ST7735S"
#define AXP192_I2C_ADDRESS 0x34 #define AXP192_I2C_ADDRESS 0x34
/********************** /**********************
@ -41,10 +39,14 @@ static void st7735s_send_cmd(uint8_t cmd);
static void st7735s_send_data(void * data, uint16_t length); static void st7735s_send_data(void * data, uint16_t length);
static void st7735s_send_color(void * data, uint16_t length); static void st7735s_send_color(void * data, uint16_t length);
static void st7735s_set_orientation(uint8_t orientation); static void st7735s_set_orientation(uint8_t orientation);
static void st7735s_reset(void);
#ifdef CONFIG_LV_M5STICKC_HANDLE_AXP192
static void axp192_write_byte(uint8_t addr, uint8_t data); static void axp192_write_byte(uint8_t addr, uint8_t data);
static void axp192_init(); static void axp192_init();
static void axp192_sleep_in(); static void axp192_sleep_in();
static void axp192_sleep_out(); static void axp192_sleep_out();
#endif
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@ -97,22 +99,9 @@ void st7735s_init(void)
{0, {0}, 0xff} {0, {0}, 0xff}
}; };
//Initialize non-SPI GPIOs st7735s_reset();
gpio_pad_select_gpio(ST7735S_DC);
gpio_set_direction(ST7735S_DC, GPIO_MODE_OUTPUT);
#if ST7735S_USE_RST LV_LOG_INFO("ST7735S initialization.");
gpio_pad_select_gpio(ST7735S_RST);
gpio_set_direction(ST7735S_RST, GPIO_MODE_OUTPUT);
//Reset the display
gpio_set_level(ST7735S_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ST7735S_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
ESP_LOGI(TAG, "ST7735S initialization.");
//Send all the commands //Send all the commands
uint16_t cmd = 0; uint16_t cmd = 0;
@ -120,7 +109,7 @@ void st7735s_init(void)
st7735s_send_cmd(init_cmds[cmd].cmd); st7735s_send_cmd(init_cmds[cmd].cmd);
st7735s_send_data(init_cmds[cmd].data, init_cmds[cmd].databytes&0x1F); st7735s_send_data(init_cmds[cmd].data, init_cmds[cmd].databytes&0x1F);
if (init_cmds[cmd].databytes & 0x80) { if (init_cmds[cmd].databytes & 0x80) {
vTaskDelay(100 / portTICK_RATE_MS); vTaskDelay(pdMS_TO_TICKS(100));
} }
cmd++; cmd++;
} }
@ -136,7 +125,7 @@ void st7735s_init(void)
void st7735s_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map) void st7735s_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
{ {
uint8_t data[4]; uint8_t data[4] = {0};
/*Column addresses*/ /*Column addresses*/
st7735s_send_cmd(0x2A); st7735s_send_cmd(0x2A);
@ -157,8 +146,8 @@ void st7735s_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * col
/*Memory write*/ /*Memory write*/
st7735s_send_cmd(0x2C); st7735s_send_cmd(0x2C);
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area); uint32_t size = lv_area_get_width(area) * lv_area_get_height(area) * 2;
st7735s_send_color((void*)color_map, size * 2); st7735s_send_color((void*)color_map, size);
} }
void st7735s_sleep_in() void st7735s_sleep_in()
@ -204,11 +193,7 @@ static void st7735s_send_color(void * data, uint16_t length)
static void st7735s_set_orientation(uint8_t orientation) static void st7735s_set_orientation(uint8_t orientation)
{ {
const char *orientation_str[] = { assert(orientation < 4);
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
};
ESP_LOGD(TAG, "Display orientation: %s", orientation_str[orientation]);
/* /*
Portrait: 0xC8 = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_BGR Portrait: 0xC8 = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_BGR
@ -217,41 +202,58 @@ static void st7735s_set_orientation(uint8_t orientation)
*/ */
uint8_t data[] = {0xC8, 0xC8, 0xA8, 0xA8}; uint8_t data[] = {0xC8, 0xC8, 0xA8, 0xA8};
ESP_LOGD(TAG, "0x36 command value: 0x%02X", data[orientation]); #if (LV_USE_LOG == 1)
const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
};
LV_LOG_INFO("Display orientation: %s", orientation_str[orientation]);
LV_LOG_INFO("0x36 command value: 0x%02X", data[orientation]);
#endif
st7735s_send_cmd(ST7735_MADCTL); st7735s_send_cmd(ST7735_MADCTL);
st7735s_send_data((void *) &data[orientation], 1); st7735s_send_data((void *) &data[orientation], 1);
} }
static void st7735s_reset(void)
{
#if ST7735S_USE_RST
gpio_set_level(ST7735S_RST, 0);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(ST7735S_RST, 1);
vTaskDelay(pdMS_TO_TICKS(100));
#endif
}
#ifdef CONFIG_LV_M5STICKC_HANDLE_AXP192 #ifdef CONFIG_LV_M5STICKC_HANDLE_AXP192
static void axp192_write_byte(uint8_t addr, uint8_t data) static void axp192_write_byte(uint8_t addr, uint8_t data)
{ {
err = lvgl_i2c_write(CONFIG_LV_I2C_DISPLAY_PORT, AXP192_I2C_ADDRESS, addr, &data, 1); err = lvgl_i2c_write(CONFIG_LV_I2C_DISPLAY_PORT, AXP192_I2C_ADDRESS, addr, &data, 1);
if (ret != ESP_OK) { if (ret != ESP_OK) {
ESP_LOGE(TAG, "AXP192 send failed. code: 0x%.2X", ret); LV_LOG_ERROR("AXP192 send failed. code: 0x%.2X", ret);
}
} }
}
static void axp192_init() static void axp192_init()
{ {
// information on how to init and use AXP192 ifor M5StickC taken from // information on how to init and use AXP192 ifor M5StickC taken from
// https://forum.m5stack.com/topic/1025/m5stickc-turn-off-screen-completely // https://forum.m5stack.com/topic/1025/m5stickc-turn-off-screen-completely
axp192_write_byte(0x10, 0xFF); // OLED_VPP Enable axp192_write_byte(0x10, 0xFF); // OLED_VPP Enable
axp192_write_byte(0x28, 0xCC); // Enable LDO2&LDO3, LED&TFT 3.0V axp192_write_byte(0x28, 0xCC); // Enable LDO2&LDO3, LED&TFT 3.0V
axp192_sleep_out(); axp192_sleep_out();
ESP_LOGI(TAG, "AXP192 initialized, power enabled for LDO2 and LDO3"); LV_LOG_INFO("AXP192 initialized, power enabled for LDO2 and LDO3");
} }
static void axp192_sleep_in() static void axp192_sleep_in()
{ {
axp192_write_byte(0x12, 0x4b); axp192_write_byte(0x12, 0x4b);
} }
static void axp192_sleep_out() static void axp192_sleep_out()
{ {
axp192_write_byte(0x12, 0x4d); axp192_write_byte(0x12, 0x4d);
} }
#endif #endif

View file

@ -4,21 +4,15 @@
* Mostly taken from lbthomsen/esp-idf-littlevgl github. * Mostly taken from lbthomsen/esp-idf-littlevgl github.
*/ */
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "st7789.h" #include "st7789.h"
#include "disp_spi.h" #include "disp_spi.h"
#include "driver/gpio.h" #include "display_port.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "st7789"
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
@ -33,13 +27,20 @@ typedef struct {
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
static void st7789_set_orientation(uint8_t orientation); static void st7789_set_orientation(lv_disp_drv_t *drv, uint8_t orientation);
static void st7789_send_cmd(lv_disp_drv_t * drv, uint8_t cmd);
static void st7789_send_color(void *data, size_t length); static void st7789_send_data(lv_disp_drv_t * drv, void *data, uint16_t length);
static void st7789_send_color(lv_disp_drv_t * drv, void *data, uint16_t length);
static void st7789_reset(lv_disp_drv_t * drv);
static void setup_initial_offsets(lv_disp_drv_t * drv);
static lv_coord_t get_display_hor_res(lv_disp_drv_t * drv);
static lv_coord_t get_display_ver_res(lv_disp_drv_t * drv);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
static uint16_t user_x_offset = 0u;
static uint16_t user_y_offset = 0u;
/********************** /**********************
* MACROS * MACROS
@ -48,8 +49,10 @@ static void st7789_send_color(void *data, size_t length);
/********************** /**********************
* GLOBAL FUNCTIONS * GLOBAL FUNCTIONS
**********************/ **********************/
void st7789_init(void) void st7789_init(lv_disp_drv_t *drv)
{ {
setup_initial_offsets(drv);
lcd_init_cmd_t st7789_init_cmds[] = { lcd_init_cmd_t st7789_init_cmds[] = {
{0xCF, {0x00, 0x83, 0X30}, 3}, {0xCF, {0x00, 0x83, 0X30}, 3},
{0xED, {0x64, 0x03, 0X12, 0X81}, 4}, {0xED, {0x64, 0x03, 0X12, 0X81}, 4},
@ -85,39 +88,28 @@ void st7789_init(void)
{0, {0}, 0xff}, {0, {0}, 0xff},
}; };
//Initialize non-SPI GPIOs st7789_reset(drv);
gpio_pad_select_gpio(ST7789_DC);
gpio_set_direction(ST7789_DC, GPIO_MODE_OUTPUT);
#if !defined(ST7789_SOFT_RST)
gpio_pad_select_gpio(ST7789_RST);
gpio_set_direction(ST7789_RST, GPIO_MODE_OUTPUT);
#endif
//Reset the display
#if !defined(ST7789_SOFT_RST)
gpio_set_level(ST7789_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ST7789_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#else
st7789_send_cmd(ST7789_SWRESET);
#endif
printf("ST7789 initialization.\n");
//Send all the commands //Send all the commands
uint16_t cmd = 0; uint16_t cmd = 0;
while (st7789_init_cmds[cmd].databytes!=0xff) { while (st7789_init_cmds[cmd].databytes!=0xff) {
st7789_send_cmd(st7789_init_cmds[cmd].cmd); st7789_send_cmd(drv, st7789_init_cmds[cmd].cmd);
st7789_send_data(st7789_init_cmds[cmd].data, st7789_init_cmds[cmd].databytes&0x1F); st7789_send_data(drv, st7789_init_cmds[cmd].data, st7789_init_cmds[cmd].databytes&0x1F);
if (st7789_init_cmds[cmd].databytes & 0x80) { if (st7789_init_cmds[cmd].databytes & 0x80) {
vTaskDelay(100 / portTICK_RATE_MS); display_port_delay(drv, 100);
} }
cmd++; cmd++;
} }
st7789_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION); /* NOTE: Setting rotation from lv_disp_drv_t instead of menuconfig */
lv_disp_rot_t rotation;
#if (LVGL_VERSION_MAJOR >= 8)
rotation = lv_disp_get_rotation((lv_disp_t *) &drv);
#else
rotation = lv_disp_get_rotation((lv_disp_t *) drv);
#endif
st7789_set_orientation(drv, rotation);
} }
/* The ST7789 display controller can drive up to 320*240 displays, when using a 240*240 or 240*135 /* The ST7789 display controller can drive up to 320*240 displays, when using a 240*240 or 240*135
@ -131,109 +123,219 @@ void st7789_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * colo
uint16_t offsetx2 = area->x2; uint16_t offsetx2 = area->x2;
uint16_t offsety1 = area->y1; uint16_t offsety1 = area->y1;
uint16_t offsety2 = area->y2; uint16_t offsety2 = area->y2;
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
#if (CONFIG_LV_TFT_DISPLAY_OFFSETS) /* On LVGLv7 we have to manually update the driver orientation,
offsetx1 += CONFIG_LV_TFT_DISPLAY_X_OFFSET; * in LVGLv8 we use the driver update callback. */
offsetx2 += CONFIG_LV_TFT_DISPLAY_X_OFFSET; #if (LVGL_VERSION_MAJOR < 8)
offsety1 += CONFIG_LV_TFT_DISPLAY_Y_OFFSET; static lv_disp_rot_t cached_rotation = LV_DISP_ROT_NONE;
offsety2 += CONFIG_LV_TFT_DISPLAY_Y_OFFSET; lv_disp_rot_t rotation = lv_disp_get_rotation((lv_disp_t *) drv);
if (cached_rotation != rotation) {
#elif (LV_HOR_RES_MAX == 240) && (LV_VER_RES_MAX == 240) st7789_set_orientation(drv, (uint8_t) rotation);
#if (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT) /* Update offset values */
offsetx1 += 80; setup_initial_offsets(drv);
offsetx2 += 80; cached_rotation = rotation;
#elif (CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) }
offsety1 += 80;
offsety2 += 80;
#endif
#elif (LV_HOR_RES_MAX == 240) && (LV_VER_RES_MAX == 135)
#if (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT) || \
(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
offsetx1 += 40;
offsetx2 += 40;
offsety1 += 53;
offsety2 += 53;
#endif
#elif (LV_HOR_RES_MAX == 135) && (LV_VER_RES_MAX == 240)
#if (CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE) || \
(CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
offsetx1 += 52;
offsetx2 += 52;
offsety1 += 40;
offsety2 += 40;
#endif
#endif #endif
offsetx1 += st7789_x_offset();
offsetx2 += st7789_x_offset();
offsety1 += st7789_y_offset();
offsety2 += st7789_y_offset();
/*Column addresses*/ /*Column addresses*/
st7789_send_cmd(ST7789_CASET); st7789_send_cmd(drv, ST7789_CASET);
data[0] = (offsetx1 >> 8) & 0xFF; data[0] = (offsetx1 >> 8) & 0xFF;
data[1] = offsetx1 & 0xFF; data[1] = offsetx1 & 0xFF;
data[2] = (offsetx2 >> 8) & 0xFF; data[2] = (offsetx2 >> 8) & 0xFF;
data[3] = offsetx2 & 0xFF; data[3] = offsetx2 & 0xFF;
st7789_send_data(data, 4); st7789_send_data(drv, data, 4);
/*Page addresses*/ /*Page addresses*/
st7789_send_cmd(ST7789_RASET); st7789_send_cmd(drv, ST7789_RASET);
data[0] = (offsety1 >> 8) & 0xFF; data[0] = (offsety1 >> 8) & 0xFF;
data[1] = offsety1 & 0xFF; data[1] = offsety1 & 0xFF;
data[2] = (offsety2 >> 8) & 0xFF; data[2] = (offsety2 >> 8) & 0xFF;
data[3] = offsety2 & 0xFF; data[3] = offsety2 & 0xFF;
st7789_send_data(data, 4); st7789_send_data(drv, data, 4);
/*Memory write*/ /*Memory write*/
st7789_send_cmd(ST7789_RAMWR); st7789_send_cmd(drv, ST7789_RAMWR);
st7789_send_color(drv, (void*) color_map, size * 2);
}
size_t size = (size_t)lv_area_get_width(area) * (size_t)lv_area_get_height(area); void st7789_set_x_offset(const uint16_t offset)
{
user_x_offset = offset;
}
st7789_send_color((void*)color_map, size * 2); void st7789_set_y_offset(const uint16_t offset)
{
user_y_offset = offset;
}
uint16_t st7789_x_offset(void)
{
return user_x_offset;
}
uint16_t st7789_y_offset(void)
{
return user_y_offset;
} }
/********************** /**********************
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
void st7789_send_cmd(uint8_t cmd) static void st7789_send_cmd(lv_disp_drv_t *drv, uint8_t cmd)
{ {
disp_wait_for_pending_transactions(); disp_wait_for_pending_transactions();
gpio_set_level(ST7789_DC, 0); display_port_gpio_dc(drv, 0);
disp_spi_send_data(&cmd, 1); disp_spi_send_data(&cmd, 1);
} }
void st7789_send_data(void * data, uint16_t length) static void st7789_send_data(lv_disp_drv_t *drv, void * data, uint16_t length)
{ {
disp_wait_for_pending_transactions(); disp_wait_for_pending_transactions();
gpio_set_level(ST7789_DC, 1); display_port_gpio_dc(drv, 1);
disp_spi_send_data(data, length); disp_spi_send_data(data, length);
} }
static void st7789_send_color(void * data, size_t length) static void st7789_send_color(lv_disp_drv_t *drv, void * data, uint16_t length)
{ {
disp_wait_for_pending_transactions(); disp_wait_for_pending_transactions();
gpio_set_level(ST7789_DC, 1); display_port_gpio_dc(drv, 1);
disp_spi_send_colors(data, length); disp_spi_send_colors(data, length);
} }
static void st7789_set_orientation(uint8_t orientation) /* Reset the display, if we don't have a reset pin we use software reset */
static void st7789_reset(lv_disp_drv_t *drv)
{ {
// ESP_ASSERT(orientation < 4); #if !defined(ST7789_SOFT_RST)
display_port_gpio_rst(drv, 0);
const char *orientation_str[] = { display_port_delay(drv, 100);
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED" display_port_gpio_rst(drv, 1);
}; display_port_delay(drv, 100);
#else
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); st7789_send_cmd(drv, ST7789_SWRESET);
display_port_delay(drv, 5);
#endif
}
static void st7789_set_orientation(lv_disp_drv_t *drv, uint8_t orientation)
{
uint8_t data[] = uint8_t data[] =
{ {
#if CONFIG_LV_PREDEFINED_DISPLAY_TTGO #if CONFIG_LV_PREDEFINED_DISPLAY_TTGO
0x60, 0xA0, 0x00, 0xC0 0x60, 0xA0, 0x00, 0xC0
#else #else
0xC0, 0x00, 0x60, 0xA0 0xC0, 0x60, 0x00, 0xA0
#endif #endif
}; };
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]); st7789_send_cmd(drv, ST7789_MADCTL);
st7789_send_data(drv, (void *) &data[orientation], 1);
st7789_send_cmd(ST7789_MADCTL); }
st7789_send_data((void *) &data[orientation], 1);
static void setup_initial_offsets(lv_disp_drv_t * drv)
{
lv_disp_rot_t rotation;
#if (LVGL_VERSION_MAJOR >= 8)
rotation = lv_disp_get_rotation((lv_disp_t *) &drv);
#else
rotation = lv_disp_get_rotation((lv_disp_t *) drv);
#endif
#if (CONFIG_LV_TFT_DISPLAY_OFFSETS)
st7789_set_x_offset(CONFIG_LV_TFT_DISPLAY_X_OFFSET);
st7789_set_y_offset(CONFIG_LV_TFT_DISPLAY_Y_OFFSET);
#else
if (240U == get_display_hor_res(drv) && 135U == get_display_ver_res(drv))
{
if (LV_DISP_ROT_NONE == rotation || LV_DISP_ROT_180 == rotation)
{
st7789_set_x_offset(40);
st7789_set_y_offset(53);
}
else
{
st7789_set_x_offset(0);
st7789_set_y_offset(0);
}
}
else if (135U == get_display_hor_res(drv) && 240U == get_display_ver_res(drv))
{
if (LV_DISP_ROT_90 == rotation || LV_DISP_ROT_270 == rotation)
{
st7789_set_x_offset(52);
st7789_set_y_offset(40);
}
else
{
st7789_set_x_offset(0);
st7789_set_y_offset(0);
}
}
else if (240U == get_display_hor_res(drv) && 240U == get_display_ver_res(drv))
{
if (LV_DISP_ROT_NONE == rotation)
{
st7789_set_x_offset(80);
st7789_set_y_offset(0);
}
else if (LV_DISP_ROT_90 == rotation || LV_DISP_ROT_180 == rotation)
{
st7789_set_x_offset(0);
st7789_set_y_offset(0);
}
else if (LV_DISP_ROT_270 == rotation)
{
st7789_set_x_offset(0);
st7789_set_y_offset(80);
}
}
#endif
}
/* Display update callback, we could update the orientation in here
* NOTE Available only for LVGL v8 */
void st7789_update_cb(lv_disp_drv_t *drv)
{
lv_disp_rot_t rotation;
#if (LVGL_VERSION_MAJOR >= 8)
rotation = lv_disp_get_rotation((lv_disp_t *) &drv);
#else
rotation = lv_disp_get_rotation((lv_disp_t *) drv);
#endif
st7789_set_orientation(drv, (uint8_t) rotation);
setup_initial_offsets(drv);
}
static lv_coord_t get_display_hor_res(lv_disp_drv_t * drv)
{
lv_coord_t retval = 0;
#if (LVGL_VERSION_MAJOR >= 8)
retval = drv->hor_res;
#else
(void) drv;
retval = LV_HOR_RES_MAX;
#endif
return retval;
}
static lv_coord_t get_display_ver_res(lv_disp_drv_t * drv)
{
lv_coord_t retval = 0;
#if (LVGL_VERSION_MAJOR >= 8)
retval = drv->ver_res;
#else
(void) drv;
retval = LV_VER_RES_MAX;
#endif
return retval;
} }

View file

@ -17,22 +17,11 @@ extern "C"
#else #else
#include "lvgl/lvgl.h" #include "lvgl/lvgl.h"
#endif #endif
#include "../lvgl_helpers.h"
#include "sdkconfig.h" /* For SPI transfers */
#include "lvgl_helpers.h"
#define ST7789_DC CONFIG_LV_DISP_PIN_DC /* For ST7789 particular configurations */
#define ST7789_RST CONFIG_LV_DISP_PIN_RST #include "display_config.h"
#if CONFIG_LV_DISP_USE_RST
#if CONFIG_LV_DISP_ST7789_SOFT_RESET
#define ST7789_SOFT_RST
#endif
#else
#define ST7789_SOFT_RST
#endif
#define ST7789_INVERT_COLORS CONFIG_LV_INVERT_COLORS
/* ST7789 commands */ /* ST7789 commands */
#define ST7789_NOP 0x00 #define ST7789_NOP 0x00
@ -110,11 +99,48 @@ extern "C"
#define ST7789_NVMSET 0xFC // NVM setting #define ST7789_NVMSET 0xFC // NVM setting
#define ST7789_PROMACT 0xFE // Program action #define ST7789_PROMACT 0xFE // Program action
void st7789_init(void); /**
* Initialize the ST7789 display controller with default configuration
*
* @param drv Pointer to lv_disp_drv_t being used
*/
void st7789_init(lv_disp_drv_t *drv);
/**
* Send buffer content to display
*
* @param drv Pointer to lv_disp_drv_t being used
* @param area Pointer to area to be sent
* @param color_map Pointer to color map
*/
void st7789_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); void st7789_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map);
void st7789_send_cmd(uint8_t cmd); /**
void st7789_send_data(void *data, uint16_t length); * Set display buffer offset at x axis
*/
void st7789_set_x_offset(const uint16_t offset);
/**
* Set display buffer offset at y axis
*/
void st7789_set_y_offset(const uint16_t offset);
/**
* Get display buffer offset at x axis
*/
uint16_t st7789_x_offset(void);
/**
* Get display buffer offset at y axis
*/
uint16_t st7789_y_offset(void);
/**
* Display updated callback
*
* @param drv Pointer to lv_disp_drv_t being used
*/
void st7789_update_cb(lv_disp_drv_t *drv);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View file

@ -9,14 +9,12 @@
#include "st7796s.h" #include "st7796s.h"
#include "disp_spi.h" #include "disp_spi.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "ST7796S"
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@ -38,6 +36,7 @@ static void st7796s_set_orientation(uint8_t orientation);
static void st7796s_send_cmd(uint8_t cmd); static void st7796s_send_cmd(uint8_t cmd);
static void st7796s_send_data(void *data, uint16_t length); static void st7796s_send_data(void *data, uint16_t length);
static void st7796s_send_color(void *data, uint16_t length); static void st7796s_send_color(void *data, uint16_t length);
static void st7796s_reset(void);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@ -81,22 +80,9 @@ void st7796s_init(void)
{0, {0}, 0xff}, {0, {0}, 0xff},
}; };
//Initialize non-SPI GPIOs st7796s_reset();
gpio_pad_select_gpio(ST7796S_DC);
gpio_set_direction(ST7796S_DC, GPIO_MODE_OUTPUT);
#if ST7796S_USE_RST LV_LOG_INFO("Initialization.");
gpio_pad_select_gpio(ST7796S_RST);
gpio_set_direction(ST7796S_RST, GPIO_MODE_OUTPUT);
//Reset the display
gpio_set_level(ST7796S_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ST7796S_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
ESP_LOGI(TAG, "Initialization.");
//Send all the commands //Send all the commands
uint16_t cmd = 0; uint16_t cmd = 0;
@ -106,7 +92,7 @@ void st7796s_init(void)
st7796s_send_data(init_cmds[cmd].data, init_cmds[cmd].databytes & 0x1F); st7796s_send_data(init_cmds[cmd].data, init_cmds[cmd].databytes & 0x1F);
if (init_cmds[cmd].databytes & 0x80) if (init_cmds[cmd].databytes & 0x80)
{ {
vTaskDelay(100 / portTICK_RATE_MS); vTaskDelay(pdMS_TO_TICKS(100));
} }
cmd++; cmd++;
} }
@ -189,25 +175,36 @@ static void st7796s_send_color(void *data, uint16_t length)
static void st7796s_set_orientation(uint8_t orientation) static void st7796s_set_orientation(uint8_t orientation)
{ {
// ESP_ASSERT(orientation < 4); assert(orientation < 4);
#if defined CONFIG_LV_PREDEFINED_DISPLAY_M5STACK
const uint8_t data[] = {0x68, 0x68, 0x08, 0x08};
#elif defined(CONFIG_LV_PREDEFINED_DISPLAY_WROVER4)
const uint8_t data[] = {0x4C, 0x88, 0x28, 0xE8};
#elif defined(CONFIG_LV_PREDEFINED_DISPLAY_WT32_SC01)
const uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
#else
const uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
#endif
#if (LV_USE_LOG == 1)
const char *orientation_str[] = { const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"}; "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"};
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); LV_LOG_INFO("Display orientation: %s", orientation_str[orientation]);
LV_LOG_INFO("0x36 command value: 0x%02X", data[orientation]);
#if defined CONFIG_LV_PREDEFINED_DISPLAY_M5STACK
uint8_t data[] = {0x68, 0x68, 0x08, 0x08};
#elif defined(CONFIG_LV_PREDEFINED_DISPLAY_WROVER4)
uint8_t data[] = {0x4C, 0x88, 0x28, 0xE8};
#elif defined(CONFIG_LV_PREDEFINED_DISPLAY_WT32_SC01)
uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
#elif defined(CONFIG_LV_PREDEFINED_DISPLAY_NONE)
uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
#endif #endif
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]);
st7796s_send_cmd(0x36); st7796s_send_cmd(0x36);
st7796s_send_data((void *)&data[orientation], 1); st7796s_send_data((void *)&data[orientation], 1);
} }
static void st7796s_reset(void)
{
#if ST7796S_USE_RST
gpio_set_level(ST7796S_RST, 0);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(ST7796S_RST, 1);
vTaskDelay(pdMS_TO_TICKS(100));
#endif
}

View file

@ -29,23 +29,37 @@
#include <freertos/task.h> #include <freertos/task.h>
#include <freertos/event_groups.h> #include <freertos/event_groups.h>
#include <driver/gpio.h> #include <driver/gpio.h>
#include <esp_log.h>
#include "disp_spi.h" #include "disp_spi.h"
#include "disp_driver.h" #include "disp_driver.h"
#include "uc8151d.h" #include "uc8151d.h"
#define TAG "lv_uc8151d"
#define PIN_DC CONFIG_LV_DISP_PIN_DC #define PIN_DC CONFIG_LV_DISP_PIN_DC
#define PIN_DC_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_DC))) #define PIN_DC_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_DC)))
#if defined CONFIG_LV_DISP_PIN_RST
#define PIN_RST CONFIG_LV_DISP_PIN_RST #define PIN_RST CONFIG_LV_DISP_PIN_RST
#define PIN_RST_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_RST))) #define PIN_RST_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_RST)))
#endif
#define PIN_BUSY CONFIG_LV_DISP_PIN_BUSY #define PIN_BUSY CONFIG_LV_DISP_PIN_BUSY
#define PIN_BUSY_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_BUSY))) #define PIN_BUSY_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_BUSY)))
#define EVT_BUSY (1UL << 0UL) #define EVT_BUSY (1UL << 0UL)
#if defined (LV_HOR_RES_MAX)
#define EPD_WIDTH LV_HOR_RES_MAX #define EPD_WIDTH LV_HOR_RES_MAX
#else
/* ToDo Fix, 256 is just a magic number */
#define EPD_WIDTH 256u
#endif
#if defined (LV_VER_RES_MAX)
#define EPD_HEIGHT LV_VER_RES_MAX #define EPD_HEIGHT LV_VER_RES_MAX
#else
/* ToDo Fix, 128 is just a magic number */
#define EPD_HEIGHT 128u
#endif
#define EPD_ROW_LEN (EPD_HEIGHT / 8u) #define EPD_ROW_LEN (EPD_HEIGHT / 8u)
#define BIT_SET(a, b) ((a) |= (1U << (b))) #define BIT_SET(a, b) ((a) |= (1U << (b)))
@ -93,26 +107,6 @@ static void uc8151d_spi_send_data_byte(uint8_t data)
disp_spi_send_data(&data, 1); disp_spi_send_data(&data, 1);
} }
static void uc8151d_spi_send_fb(uint8_t *data, size_t len)
{
disp_wait_for_pending_transactions();
gpio_set_level(PIN_DC, 1); // DC = 1 for data
disp_spi_send_colors(data, len);
}
static void uc8151d_spi_send_seq(const uc8151d_seq_t *seq, size_t len)
{
ESP_LOGD(TAG, "Writing cmd/data sequence, count %u", len);
if (!seq || len < 1) return;
for (size_t cmd_idx = 0; cmd_idx < len; cmd_idx++) {
uc8151d_spi_send_cmd(seq[cmd_idx].cmd);
if (seq[cmd_idx].len > 0) {
uc8151d_spi_send_data((uint8_t *) seq[cmd_idx].data, seq[cmd_idx].len);
}
}
}
static esp_err_t uc8151d_wait_busy(uint32_t timeout_ms) static esp_err_t uc8151d_wait_busy(uint32_t timeout_ms)
{ {
uint32_t wait_ticks = (timeout_ms == 0 ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms)); uint32_t wait_ticks = (timeout_ms == 0 ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms));
@ -124,7 +118,7 @@ static esp_err_t uc8151d_wait_busy(uint32_t timeout_ms)
return ((bits & EVT_BUSY) != 0) ? ESP_OK : ESP_ERR_TIMEOUT; return ((bits & EVT_BUSY) != 0) ? ESP_OK : ESP_ERR_TIMEOUT;
} }
static void uc8151d_sleep() static void uc8151d_sleep(void)
{ {
// Set VCOM to 0xf7 // Set VCOM to 0xf7
uc8151d_spi_send_cmd(0x50); uc8151d_spi_send_cmd(0x50);
@ -139,14 +133,13 @@ static void uc8151d_sleep()
uc8151d_spi_send_data_byte(0xa5); uc8151d_spi_send_data_byte(0xa5);
} }
static void uc8151d_panel_init() static void uc8151d_reset(void);
static void uc8151d_panel_init(void)
{ {
// Hardware reset for 3 times - not sure why but it's from official demo code // Hardware reset for 3 times - not sure why but it's from official demo code
for (uint8_t cnt = 0; cnt < 3; cnt++) { for (uint8_t cnt = 0; cnt < 3; cnt++) {
gpio_set_level(PIN_RST, 0); uc8151d_reset();
vTaskDelay(pdMS_TO_TICKS(10)); // At least 10ms, leave 20ms for now just in case...
gpio_set_level(PIN_RST, 1);
vTaskDelay(pdMS_TO_TICKS(10));
} }
// Power up // Power up
@ -196,19 +189,20 @@ static void uc8151d_full_update(uint8_t *buf)
void uc8151d_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) void uc8151d_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
{ {
#if LV_USE_LOG
size_t len = ((area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1)) / 8; size_t len = ((area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1)) / 8;
LV_LOG_INFO("x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", area->x1, area->x2, area->y1, area->y2);
ESP_LOGD(TAG, "x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", area->x1, area->x2, area->y1, area->y2); LV_LOG_INFO("Writing LVGL fb with len: %u", len);
ESP_LOGD(TAG, "Writing LVGL fb with len: %u", len); #endif
uint8_t *buf = (uint8_t *) color_map; uint8_t *buf = (uint8_t *) color_map;
uc8151d_full_update(buf); uc8151d_full_update(buf);
lv_disp_flush_ready(drv); lv_disp_flush_ready(drv);
ESP_LOGD(TAG, "Ready"); LV_LOG_INFO("Ready");
} }
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, void uc8151d_lv_set_fb_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) lv_color_t color, lv_opa_t opa)
{ {
uint16_t byte_index = (x >> 3u) + (y * EPD_ROW_LEN); uint16_t byte_index = (x >> 3u) + (y * EPD_ROW_LEN);
@ -217,12 +211,12 @@ void uc8151d_lv_set_fb_cb(struct _disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t
if (color.full) { if (color.full) {
BIT_SET(buf[byte_index], 7 - bit_index); BIT_SET(buf[byte_index], 7 - bit_index);
} else { } else {
ESP_LOGD(TAG, "Clear at x: %u, y: %u", x, y); LV_LOG_INFO("Clear at x: %u, y: %u", x, y);
BIT_CLEAR(buf[byte_index], 7 - bit_index); BIT_CLEAR(buf[byte_index], 7 - bit_index);
} }
} }
void uc8151d_lv_rounder_cb(struct _disp_drv_t *disp_drv, lv_area_t *area) void uc8151d_lv_rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area)
{ {
// Always send full framebuffer if it's not in partial mode // Always send full framebuffer if it's not in partial mode
area->x1 = 0; area->x1 = 0;
@ -231,25 +225,15 @@ void uc8151d_lv_rounder_cb(struct _disp_drv_t *disp_drv, lv_area_t *area)
area->y2 = EPD_HEIGHT - 1; area->y2 = EPD_HEIGHT - 1;
} }
void uc8151d_init() void uc8151d_init(void)
{ {
// Initialise event group // Initialise event group
uc8151d_evts = xEventGroupCreate(); uc8151d_evts = xEventGroupCreate();
if (!uc8151d_evts) { if (!uc8151d_evts) {
ESP_LOGE(TAG, "Failed when initialising event group!"); LV_LOG_ERROR("Failed when initialising event group!");
return; return;
} }
// Setup output pins, output (PP)
gpio_config_t out_io_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = PIN_DC_BIT | PIN_RST_BIT,
.pull_down_en = 0,
.pull_up_en = 0,
};
ESP_ERROR_CHECK(gpio_config(&out_io_conf));
// Setup input pin, pull-up, input // Setup input pin, pull-up, input
gpio_config_t in_io_conf = { gpio_config_t in_io_conf = {
.intr_type = GPIO_INTR_POSEDGE, .intr_type = GPIO_INTR_POSEDGE,
@ -262,7 +246,18 @@ void uc8151d_init()
gpio_install_isr_service(0); gpio_install_isr_service(0);
gpio_isr_handler_add(PIN_BUSY, uc8151d_busy_intr, (void *) PIN_BUSY); gpio_isr_handler_add(PIN_BUSY, uc8151d_busy_intr, (void *) PIN_BUSY);
ESP_LOGI(TAG, "IO init finished"); LV_LOG_INFO("IO init finished");
uc8151d_panel_init(); uc8151d_panel_init();
ESP_LOGI(TAG, "Panel initialised"); LV_LOG_INFO("Panel initialised");
}
static void uc8151d_reset(void)
{
#if defined CONFIG_LV_DISP_USE_RST
gpio_set_level(PIN_RST, 0);
// At least 10ms, leave 20ms for now just in case...
vTaskDelay(pdMS_TO_TICKS(20));
gpio_set_level(PIN_RST, 1);
vTaskDelay(pdMS_TO_TICKS(10));
#endif
} }

View file

@ -29,11 +29,11 @@
#include <lvgl.h> #include <lvgl.h>
void uc8151d_init(); void uc8151d_init(void);
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, void uc8151d_lv_set_fb_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); lv_color_t color, lv_opa_t opa);
void uc8151d_lv_rounder_cb(struct _disp_drv_t *disp_drv, lv_area_t *area); void uc8151d_lv_rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area);
void uc8151d_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); void uc8151d_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map);
#endif //LVGL_DEMO_UC8151D_H #endif //LVGL_DEMO_UC8151D_H

View file

@ -8,11 +8,11 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_idf_version.h"
#include <stddef.h> #include <stddef.h>
#if CONFIG_LV_TOUCH_CONTROLLER_ADCRAW #if CONFIG_LV_TOUCH_CONTROLLER_ADCRAW
#define TAG "ADCRAW"
#define CALIBRATIONINSET 1 // range 0 <= CALIBRATIONINSET <= 40 #define CALIBRATIONINSET 1 // range 0 <= CALIBRATIONINSET <= 40
#define SAMPLE_CALIBRATION_POINTS 4 #define SAMPLE_CALIBRATION_POINTS 4
// use this scale factor to avoid working in floating point numbers // use this scale factor to avoid working in floating point numbers
@ -139,10 +139,19 @@ static void setup_axis(gpio_num_t plus, gpio_num_t minus, gpio_num_t measure, gp
{ {
// Set GPIOs: // Set GPIOs:
// - Float "ignore" and "measure" // - Float "ignore" and "measure"
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
esp_rom_gpio_pad_select_gpio(ignore);
#else
gpio_pad_select_gpio(ignore); gpio_pad_select_gpio(ignore);
#endif
gpio_set_direction(ignore, GPIO_MODE_DISABLE); gpio_set_direction(ignore, GPIO_MODE_DISABLE);
gpio_set_pull_mode(ignore, GPIO_FLOATING); gpio_set_pull_mode(ignore, GPIO_FLOATING);
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
esp_rom_gpio_pad_select_gpio(ignore);
#else
gpio_pad_select_gpio(measure); gpio_pad_select_gpio(measure);
#endif
gpio_set_direction(measure, GPIO_MODE_DISABLE); gpio_set_direction(measure, GPIO_MODE_DISABLE);
gpio_set_pull_mode(measure, GPIO_FLOATING); gpio_set_pull_mode(measure, GPIO_FLOATING);
// - Set "plus" to 1, "minus" to 0 // - Set "plus" to 1, "minus" to 0

View file

@ -18,22 +18,24 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include <esp_log.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE #ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include <lvgl.h> #include <lvgl.h>
#else #else
#include <lvgl/lvgl.h> #include <lvgl/lvgl.h>
#endif #endif
#include "ft6x36.h" #include "ft6x36.h"
#include "lvgl_i2c/i2c_manager.h" #include "lvgl_i2c/i2c_manager.h"
#define TAG "FT6X36" #define TAG "FT6X36"
#define FT6X36_TOUCH_QUEUE_ELEMENTS 1 #define FT6X36_TOUCH_QUEUE_ELEMENTS 1
static ft6x36_status_t ft6x36_status; static ft6x36_status_t ft6x36_status;
static uint8_t current_dev_addr; // set during init /* Set during initialization */
static ft6x36_touch_t touch_inputs = { -1, -1, LV_INDEV_STATE_REL }; // -1 coordinates to designate it was never touched static uint8_t current_dev_addr;
/* -1 coordinates to designate it was never touched */
static ft6x36_touch_t touch_inputs = { -1, -1, LV_INDEV_STATE_REL };
#if CONFIG_LV_FT6X36_COORDINATES_QUEUE #if CONFIG_LV_FT6X36_COORDINATES_QUEUE
QueueHandle_t ft6x36_touch_queue_handle; QueueHandle_t ft6x36_touch_queue_handle;
#endif #endif
@ -49,13 +51,13 @@ static esp_err_t ft6x06_i2c_read8(uint8_t slave_addr, uint8_t register_addr, uin
*/ */
uint8_t ft6x36_get_gesture_id() { uint8_t ft6x36_get_gesture_id() {
if (!ft6x36_status.inited) { if (!ft6x36_status.inited) {
ESP_LOGE(TAG, "Init first!"); LV_LOG_ERROR("Init first!");
return 0x00; return 0x00;
} }
uint8_t data_buf; uint8_t data_buf;
esp_err_t ret; esp_err_t ret;
if ((ret = ft6x06_i2c_read8(current_dev_addr, FT6X36_GEST_ID_REG, &data_buf) != ESP_OK)) if ((ret = ft6x06_i2c_read8(current_dev_addr, FT6X36_GEST_ID_REG, &data_buf) != ESP_OK))
ESP_LOGE(TAG, "Error reading from device: %s", esp_err_to_name(ret)); LV_LOG_ERROR("Error reading from device: %s", esp_err_to_name(ret));
return data_buf; return data_buf;
} }
@ -70,29 +72,29 @@ void ft6x06_init(uint16_t dev_addr) {
current_dev_addr = dev_addr; current_dev_addr = dev_addr;
uint8_t data_buf; uint8_t data_buf;
esp_err_t ret; esp_err_t ret;
ESP_LOGI(TAG, "Found touch panel controller"); LV_LOG_INFO("Found touch panel controller");
if ((ret = ft6x06_i2c_read8(dev_addr, FT6X36_PANEL_ID_REG, &data_buf) != ESP_OK)) if ((ret = ft6x06_i2c_read8(dev_addr, FT6X36_PANEL_ID_REG, &data_buf) != ESP_OK))
ESP_LOGE(TAG, "Error reading from device: %s", LV_LOG_ERROR("Error reading from device: %s",
esp_err_to_name(ret)); // Only show error the first time esp_err_to_name(ret)); // Only show error the first time
ESP_LOGI(TAG, "\tDevice ID: 0x%02x", data_buf); LV_LOG_INFO("\tDevice ID: 0x%02x", data_buf);
ft6x06_i2c_read8(dev_addr, FT6X36_CHIPSELECT_REG, &data_buf); ft6x06_i2c_read8(dev_addr, FT6X36_CHIPSELECT_REG, &data_buf);
ESP_LOGI(TAG, "\tChip ID: 0x%02x", data_buf); LV_LOG_INFO("\tChip ID: 0x%02x", data_buf);
ft6x06_i2c_read8(dev_addr, FT6X36_DEV_MODE_REG, &data_buf); ft6x06_i2c_read8(dev_addr, FT6X36_DEV_MODE_REG, &data_buf);
ESP_LOGI(TAG, "\tDevice mode: 0x%02x", data_buf); LV_LOG_INFO("\tDevice mode: 0x%02x", data_buf);
ft6x06_i2c_read8(dev_addr, FT6X36_FIRMWARE_ID_REG, &data_buf); ft6x06_i2c_read8(dev_addr, FT6X36_FIRMWARE_ID_REG, &data_buf);
ESP_LOGI(TAG, "\tFirmware ID: 0x%02x", data_buf); LV_LOG_INFO("\tFirmware ID: 0x%02x", data_buf);
ft6x06_i2c_read8(dev_addr, FT6X36_RELEASECODE_REG, &data_buf); ft6x06_i2c_read8(dev_addr, FT6X36_RELEASECODE_REG, &data_buf);
ESP_LOGI(TAG, "\tRelease code: 0x%02x", data_buf); LV_LOG_INFO("\tRelease code: 0x%02x", data_buf);
#if CONFIG_LV_FT6X36_COORDINATES_QUEUE #if CONFIG_LV_FT6X36_COORDINATES_QUEUE
ft6x36_touch_queue_handle = xQueueCreate( FT6X36_TOUCH_QUEUE_ELEMENTS, sizeof( ft6x36_touch_t ) ); ft6x36_touch_queue_handle = xQueueCreate( FT6X36_TOUCH_QUEUE_ELEMENTS, sizeof( ft6x36_touch_t ) );
if( ft6x36_touch_queue_handle == NULL ) if( ft6x36_touch_queue_handle == NULL )
{ {
ESP_LOGE( TAG, "\tError creating touch input FreeRTOS queue" ); LV_LOG_ERROR("\tError creating touch input FreeRTOS queue" );
return; return;
} }
xQueueSend( ft6x36_touch_queue_handle, &touch_inputs, 0 ); xQueueSend( ft6x36_touch_queue_handle, &touch_inputs, 0 );
@ -107,14 +109,14 @@ void ft6x06_init(uint16_t dev_addr) {
*/ */
bool ft6x36_read(lv_indev_drv_t *drv, lv_indev_data_t *data) { bool ft6x36_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
if (!ft6x36_status.inited) { if (!ft6x36_status.inited) {
ESP_LOGE(TAG, "Init first!"); LV_LOG_ERROR("Init first!");
return 0x00; return 0x00;
} }
uint8_t data_buf[5]; // 1 byte status, 2 bytes X, 2 bytes Y uint8_t data_buf[5]; // 1 byte status, 2 bytes X, 2 bytes Y
esp_err_t ret = lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, current_dev_addr, FT6X36_TD_STAT_REG, &data_buf[0], 5); esp_err_t ret = lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, current_dev_addr, FT6X36_TD_STAT_REG, &data_buf[0], 5);
if (ret != ESP_OK) { if (ret != ESP_OK) {
ESP_LOGE(TAG, "Error talking to touch IC: %s", esp_err_to_name(ret)); LV_LOG_ERROR("Error talking to touch IC: %s", esp_err_to_name(ret));
} }
uint8_t touch_pnt_cnt = data_buf[0]; // Number of detected touch points uint8_t touch_pnt_cnt = data_buf[0]; // Number of detected touch points
@ -150,7 +152,7 @@ bool ft6x36_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
data->point.x = touch_inputs.last_x; data->point.x = touch_inputs.last_x;
data->point.y = touch_inputs.last_y; data->point.y = touch_inputs.last_y;
data->state = touch_inputs.current_state; data->state = touch_inputs.current_state;
ESP_LOGD(TAG, "X=%u Y=%u", data->point.x, data->point.y); LV_LOG_INFO("X=%u Y=%u", data->point.x, data->point.y);
#if CONFIG_LV_FT6X36_COORDINATES_QUEUE #if CONFIG_LV_FT6X36_COORDINATES_QUEUE
xQueueOverwrite( ft6x36_touch_queue_handle, &touch_inputs ); xQueueOverwrite( ft6x36_touch_queue_handle, &touch_inputs );

View file

@ -18,7 +18,6 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include <esp_log.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE #ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include <lvgl.h> #include <lvgl.h>
#else #else
@ -28,8 +27,6 @@
#include "lvgl_i2c/i2c_manager.h" #include "lvgl_i2c/i2c_manager.h"
#define TAG "GT911"
gt911_status_t gt911_status; gt911_status_t gt911_status;
//TODO: handle multibyte read and refactor to just one read transaction //TODO: handle multibyte read and refactor to just one read transaction
@ -53,9 +50,9 @@ void gt911_init(uint8_t dev_addr) {
uint8_t data_buf; uint8_t data_buf;
esp_err_t ret; esp_err_t ret;
ESP_LOGI(TAG, "Checking for GT911 Touch Controller"); LV_LOG_INFO("Checking for GT911 Touch Controller");
if ((ret = gt911_i2c_read(dev_addr, GT911_PRODUCT_ID1, &data_buf, 1) != ESP_OK)) { if ((ret = gt911_i2c_read(dev_addr, GT911_PRODUCT_ID1, &data_buf, 1) != ESP_OK)) {
ESP_LOGE(TAG, "Error reading from device: %s", LV_LOG_ERROR("Error reading from device: %s",
esp_err_to_name(ret)); // Only show error the first time esp_err_to_name(ret)); // Only show error the first time
return; return;
} }
@ -64,22 +61,22 @@ void gt911_init(uint8_t dev_addr) {
for (int i = 0; i < GT911_PRODUCT_ID_LEN; i++) { for (int i = 0; i < GT911_PRODUCT_ID_LEN; i++) {
gt911_i2c_read(dev_addr, (GT911_PRODUCT_ID1 + i), (uint8_t *)&(gt911_status.product_id[i]), 1); gt911_i2c_read(dev_addr, (GT911_PRODUCT_ID1 + i), (uint8_t *)&(gt911_status.product_id[i]), 1);
} }
ESP_LOGI(TAG, "\tProduct ID: %s", gt911_status.product_id); LV_LOG_INFO("\tProduct ID: %s", gt911_status.product_id);
gt911_i2c_read(dev_addr, GT911_VENDOR_ID, &data_buf, 1); gt911_i2c_read(dev_addr, GT911_VENDOR_ID, &data_buf, 1);
ESP_LOGI(TAG, "\tVendor ID: 0x%02x", data_buf); LV_LOG_INFO("\tVendor ID: 0x%02x", data_buf);
gt911_i2c_read(dev_addr, GT911_X_COORD_RES_L, &data_buf, 1); gt911_i2c_read(dev_addr, GT911_X_COORD_RES_L, &data_buf, 1);
gt911_status.max_x_coord = data_buf; gt911_status.max_x_coord = data_buf;
gt911_i2c_read(dev_addr, GT911_X_COORD_RES_H, &data_buf, 1); gt911_i2c_read(dev_addr, GT911_X_COORD_RES_H, &data_buf, 1);
gt911_status.max_x_coord |= ((uint16_t)data_buf << 8); gt911_status.max_x_coord |= ((uint16_t)data_buf << 8);
ESP_LOGI(TAG, "\tX Resolution: %d", gt911_status.max_x_coord); LV_LOG_INFO("\tX Resolution: %d", gt911_status.max_x_coord);
gt911_i2c_read(dev_addr, GT911_Y_COORD_RES_L, &data_buf, 1); gt911_i2c_read(dev_addr, GT911_Y_COORD_RES_L, &data_buf, 1);
gt911_status.max_y_coord = data_buf; gt911_status.max_y_coord = data_buf;
gt911_i2c_read(dev_addr, GT911_Y_COORD_RES_H, &data_buf, 1); gt911_i2c_read(dev_addr, GT911_Y_COORD_RES_H, &data_buf, 1);
gt911_status.max_y_coord |= ((uint16_t)data_buf << 8); gt911_status.max_y_coord |= ((uint16_t)data_buf << 8);
ESP_LOGI(TAG, "\tY Resolution: %d", gt911_status.max_y_coord); LV_LOG_INFO("\tY Resolution: %d", gt911_status.max_y_coord);
gt911_status.inited = true; gt911_status.inited = true;
} }
} }
@ -98,7 +95,7 @@ bool gt911_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
uint8_t status_reg; uint8_t status_reg;
gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_STATUS_REG, &status_reg, 1); gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_STATUS_REG, &status_reg, 1);
// ESP_LOGI(TAG, "\tstatus: 0x%02x", status_reg); // LV_LOG_INFO("\tstatus: 0x%02x", status_reg);
touch_pnt_cnt = status_reg & 0x0F; touch_pnt_cnt = status_reg & 0x0F;
if ((status_reg & 0x80) || (touch_pnt_cnt < 6)) { if ((status_reg & 0x80) || (touch_pnt_cnt < 6)) {
//Reset Status Reg Value //Reset Status Reg Value
@ -112,7 +109,7 @@ bool gt911_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
} }
// gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_TRACK_ID1, &data_buf, 1); // gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_TRACK_ID1, &data_buf, 1);
// ESP_LOGI(TAG, "\ttrack_id: %d", data_buf); // LV_LOG_INFO("\ttrack_id: %d", data_buf);
gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_PT1_X_COORD_L, &data_buf, 1); gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_PT1_X_COORD_L, &data_buf, 1);
last_x = data_buf; last_x = data_buf;
@ -138,7 +135,7 @@ bool gt911_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
data->point.x = last_x; data->point.x = last_x;
data->point.y = last_y; data->point.y = last_y;
data->state = LV_INDEV_STATE_PR; data->state = LV_INDEV_STATE_PR;
ESP_LOGI(TAG, "X=%u Y=%u", data->point.x, data->point.y); LV_LOG_INFO("X=%u Y=%u", data->point.x, data->point.y);
ESP_LOGV(TAG, "X=%u Y=%u", data->point.x, data->point.y); LV_LOG_INFO("X=%u Y=%u", data->point.x, data->point.y);
return false; return false;
} }

View file

@ -5,7 +5,6 @@
/********************* /*********************
* INCLUDES * INCLUDES
*********************/ *********************/
#include "esp_log.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
@ -23,7 +22,6 @@
* DEFINES * DEFINES
*********************/ *********************/
#define DEBUG false #define DEBUG false
#define TAG "RA8875-Touch"
#define DIV_ROUND_UP(n, d) (((n)+(d)-1)/(d)) #define DIV_ROUND_UP(n, d) (((n)+(d)-1)/(d))
@ -83,7 +81,7 @@ void ra8875_touch_init(void)
}; };
#define INIT_CMDS_SIZE (sizeof(init_cmds)/sizeof(init_cmds[0])) #define INIT_CMDS_SIZE (sizeof(init_cmds)/sizeof(init_cmds[0]))
ESP_LOGI(TAG, "Initializing RA8875 Touch..."); LV_LOG_INFO("Initializing RA8875 Touch...");
// Send all the commands // Send all the commands
for (unsigned int i = 0; i < INIT_CMDS_SIZE; i++) { for (unsigned int i = 0; i < INIT_CMDS_SIZE; i++) {
@ -94,7 +92,7 @@ void ra8875_touch_init(void)
void ra8875_touch_enable(bool enable) void ra8875_touch_enable(bool enable)
{ {
ESP_LOGI(TAG, "%s touch.", enable ? "Enabling" : "Disabling"); LV_LOG_INFO("%s touch.", enable ? "Enabling" : "Disabling");
uint8_t val = enable ? (0x80 | TPCR0_VAL) : (TPCR0_VAL); uint8_t val = enable ? (0x80 | TPCR0_VAL) : (TPCR0_VAL);
ra8875_write_cmd(RA8875_REG_TPCR0, val); ra8875_write_cmd(RA8875_REG_TPCR0, val);
} }
@ -122,7 +120,7 @@ bool ra8875_touch_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
y = (y << 2) | ((xy >> 2) & 0x03); y = (y << 2) | ((xy >> 2) & 0x03);
#if DEBUG #if DEBUG
ESP_LOGI(TAG, "Touch Poll Raw: %d,%d", x, y); LV_LOG_INFO("Touch Poll Raw: %d,%d", x, y);
#endif #endif
// Convert to display coordinates // Convert to display coordinates
@ -136,7 +134,7 @@ bool ra8875_touch_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
data->point.y = y; data->point.y = y;
#if DEBUG #if DEBUG
ESP_LOGI(TAG, "Touch Poll - Event: %d; %d,%d", data->state, data->point.x, data->point.y); LV_LOG_INFO("Touch Poll - Event: %d; %d,%d", data->state, data->point.x, data->point.y);
#endif #endif
return false; return false;

View file

@ -7,7 +7,6 @@
*********************/ *********************/
#include "stmpe610.h" #include "stmpe610.h"
#include "esp_system.h" #include "esp_system.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "driver/gpio.h" #include "driver/gpio.h"
@ -17,8 +16,6 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "STMPE610"
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@ -55,26 +52,26 @@ void stmpe610_init(void)
uint8_t u8; uint8_t u8;
uint16_t u16; uint16_t u16;
ESP_LOGI(TAG, "Initialization."); LV_LOG_INFO("Initialization.");
// Get the initial SPI configuration // Get the initial SPI configuration
//u8 = read_8bit_reg(STMPE_SPI_CFG); //u8 = read_8bit_reg(STMPE_SPI_CFG);
//ESP_LOGI(TAG, "SPI_CFG = 0x%x", u8); //LV_LOG_INFO("SPI_CFG = 0x%x", u8);
// Attempt a software reset // Attempt a software reset
write_8bit_reg(STMPE_SYS_CTRL1, STMPE_SYS_CTRL1_RESET); write_8bit_reg(STMPE_SYS_CTRL1, STMPE_SYS_CTRL1_RESET);
vTaskDelay(10 / portTICK_RATE_MS); vTaskDelay(pdMS_TO_TICKS(10));
// Reset the SPI configuration, making sure auto-increment is set // Reset the SPI configuration, making sure auto-increment is set
u8 = read_8bit_reg(STMPE_SPI_CFG); u8 = read_8bit_reg(STMPE_SPI_CFG);
write_8bit_reg(STMPE_SPI_CFG, u8 | STMPE_SPI_CFG_AA); write_8bit_reg(STMPE_SPI_CFG, u8 | STMPE_SPI_CFG_AA);
u8 = read_8bit_reg(STMPE_SPI_CFG); u8 = read_8bit_reg(STMPE_SPI_CFG);
ESP_LOGI(TAG, "SPI_CFG = 0x%x", u8); LV_LOG_INFO("SPI_CFG = 0x%x", u8);
// Verify SPI communication // Verify SPI communication
u16 = read_16bit_reg(STMPE_CHIP_ID); u16 = read_16bit_reg(STMPE_CHIP_ID);
if (u16 != 0x811) { if (u16 != 0x811) {
ESP_LOGE(TAG, "Incorrect version: 0x%x", u16); LV_LOG_ERROR("Incorrect version: 0x%x", u16);
} }
write_8bit_reg(STMPE_SYS_CTRL2, 0x00); // Disable clocks write_8bit_reg(STMPE_SYS_CTRL2, 0x00); // Disable clocks
@ -130,12 +127,12 @@ bool stmpe610_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
} }
if (c > 0) { if (c > 0) {
//ESP_LOGI(TAG, "%d: %d %d %d", c, x, y, z); //LV_LOG_INFO("%d: %d %d %d", c, x, y, z);
adjust_data(&x, &y); adjust_data(&x, &y);
last_x = x; last_x = x;
last_y = y; last_y = y;
//ESP_LOGI(TAG, " ==> %d %d", x, y); //LV_LOG_INFO(" ==> %d %d", x, y);
} }
z = read_8bit_reg(STMPE_INT_STA); // Clear interrupts z = read_8bit_reg(STMPE_INT_STA); // Clear interrupts
@ -144,7 +141,7 @@ bool stmpe610_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
// Clear the FIFO if we discover an overflow // Clear the FIFO if we discover an overflow
write_8bit_reg(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET); write_8bit_reg(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET);
write_8bit_reg(STMPE_FIFO_STA, 0); // unreset write_8bit_reg(STMPE_FIFO_STA, 0); // unreset
ESP_LOGE(TAG, "Fifo overflow"); LV_LOG_ERROR("Fifo overflow");
} }
} }

View file

@ -8,7 +8,6 @@
*********************/ *********************/
#include "xpt2046.h" #include "xpt2046.h"
#include "esp_system.h" #include "esp_system.h"
#include "esp_log.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "tp_spi.h" #include "tp_spi.h"
#include <stddef.h> #include <stddef.h>
@ -16,8 +15,6 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define TAG "XPT2046"
#define CMD_X_READ 0b10010000 // NOTE: XPT2046 data sheet says this is actually Y #define CMD_X_READ 0b10010000 // NOTE: XPT2046 data sheet says this is actually Y
#define CMD_Y_READ 0b11010000 // NOTE: XPT2046 data sheet says this is actually X #define CMD_Y_READ 0b11010000 // NOTE: XPT2046 data sheet says this is actually X
#define CMD_Z1_READ 0b10110000 #define CMD_Z1_READ 0b10110000
@ -59,7 +56,7 @@ uint8_t avg_last;
*/ */
void xpt2046_init(void) void xpt2046_init(void)
{ {
ESP_LOGI(TAG, "XPT2046 Initialization"); LV_LOG_INFO("Initialization");
#if XPT2046_TOUCH_IRQ || XPT2046_TOUCH_IRQ_PRESS #if XPT2046_TOUCH_IRQ || XPT2046_TOUCH_IRQ_PRESS
gpio_config_t irq_config = { gpio_config_t irq_config = {
@ -94,19 +91,19 @@ bool xpt2046_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
x = xpt2046_cmd(CMD_X_READ); x = xpt2046_cmd(CMD_X_READ);
y = xpt2046_cmd(CMD_Y_READ); y = xpt2046_cmd(CMD_Y_READ);
ESP_LOGI(TAG, "P(%d,%d)", x, y); LV_LOG_INFO("P(%d,%d)", x, y);
/*Normalize Data back to 12-bits*/ /*Normalize Data back to 12-bits*/
x = x >> 4; x = x >> 4;
y = y >> 4; y = y >> 4;
ESP_LOGI(TAG, "P_norm(%d,%d)", x, y); LV_LOG_INFO("P_norm(%d,%d)", x, y);
xpt2046_corr(&x, &y); xpt2046_corr(&x, &y);
xpt2046_avg(&x, &y); xpt2046_avg(&x, &y);
last_x = x; last_x = x;
last_y = y; last_y = y;
ESP_LOGI(TAG, "x = %d, y = %d", x, y); LV_LOG_INFO("x = %d, y = %d", x, y);
} }
else else
{ {