├── .gitignore ├── README.MD ├── examples ├── install_example.sh ├── lv_conf.h ├── platformio.ini └── ui_example │ ├── main.cpp │ ├── ui.c │ └── ui.h ├── library.json └── src ├── TRGBSuppport.cpp ├── TRGBSuppport.h ├── XL9535_driver.cpp ├── XL9535_driver.h ├── img.h └── pin_config.h /.gitignore: -------------------------------------------------------------------------------- 1 | /include/ 2 | platformio.ini 3 | src/main.cpp 4 | src/ui.c 5 | src/ui.h 6 | .pio 7 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | Installation: [![PlatformIO Registry](https://badges.registry.platformio.org/packages/ianh/library/TRGBArduinoSupport.svg)](https://registry.platformio.org/libraries/ianh/TRGBArduinoSupport) 2 | 3 | This repo adds support for T-RGB device to use with arduino framework and platformio. 4 | 5 | It's just a copy of the official example code into a sufficient structure. Some functions were reordered or newly combined. 6 | There is also one bugfix to the touchpad-integration. 7 | 8 | ## Why we created this library? 9 | 10 | While looking for a better display for Ian's bluetooth bicycle computer (see https://github.com/euphi/ESP32_BTTacho), Ian discovered the 11 | LilyGO T-RGB device which has almost everthing needed already on-board: 12 | 13 | * An ESP32 chip (so Wifi and Bluetooth, a lot of computing power, RAM, Flash etc.) 14 | * 8 MB PSRAM (so even more RAM!) 15 | * a SD Card reader 16 | * I2C connector (groove) for more peripherals (like acceleration sensor) 17 | * A lithium-battery connector, so the ESP32-integrated RTC can be used as clock. 18 | * a great 480px round touch display 19 | 20 | ### What's missing: 21 | 22 | * Ian still thinks that it would be useful to also have some RGB leds or input buttons connected to his bike computer. 23 | The T-RGB does not have any spare GPIO (except the ones used for groove I2C). 24 | There are 8 spare inputs on the XL9535 device, maybe he will solder a cable with connector to it. 25 | 26 | ## License 27 | 28 | The code is using the same license as the original files: 29 | * [MIT License](https://choosealicense.com/licenses/mit/) for the initilization code and XL9535 driver 30 | * [Apache 2.0 licence](https://www.apache.org/licenses/LICENSE-2.0) for the touchpad ft3267 driver (by Espressif Systems (Shanghai) Co. Ltd.) 31 | 32 | ## How to use 33 | 34 | The idea is that you can start right away and don't need to care about copying code from the examples 35 | to build your own applications. Therefore we copied the necessary code together and encapsulated it in 36 | this libary. 37 | 38 | You need [platformio](https://platformio.org/platformio-ide) to install and run this libary. 39 | 40 | So, create your own project with: 41 | 42 | `platformio init --board=esp32-s3-devkitc-1` 43 | 44 | Adapt the `platformio.ini` file to contain this section: 45 | 46 | ``` 47 | [env:esp32-s3-devkitc-1] 48 | platform = platformio/espressif32 49 | board = esp32-s3-devkitc-1 50 | framework = arduino 51 | build_flags = 52 | -DARDUINO_USB_MODE=1 53 | -DARDUINO_USB_CDC_ON_BOOT=1 54 | -DBOARD_HAS_PSRAM 55 | -DLV_CONF_PATH=${platformio.include_dir}/lv_conf.h 56 | board_build.cpu = esp32s3 57 | board_build.arduino.memory_type = qio_opi 58 | lib_deps = 59 | IanH/TRGBArduinoSupport 60 | ``` 61 | 62 | Important options: 63 | 64 | * `-DARDUINO_USB_CDC_ON_BOOT=1`: Use onboard USB as serial device (for debug output). (See Caveats below!) 65 | * `-DBOARD_HAS_PSRAM` - default platformio configuration for esp32-s3 does not enable PSRAM support, so enable it here 66 | * `-DLV_CONF_PATH=${platformio.include_dir}/lv_conf.h`- If you want to use the lvgl library there are issues to find the configuration file. So explicitly state where it is located 67 | 68 | Create `src/main.cpp`: 69 | 70 | ```C++ 71 | #include 72 | 73 | TRGBSuppport trgb; 74 | void setup() { 75 | Serial.begin(115200); 76 | Serial.setTxTimeoutMs(1); // workaround for blocking output if no host is connected to native USB CDC 77 | delay(100); // Rumors say it helps avoid sporadical crashes after wakeup from deep-sleep 78 | trgb.init(); 79 | 80 | // load your UI etc. (see example https://github.com/fablabnbg/TRGBArduinoSupport/tree/main/examples/ui_example) 81 | } 82 | 83 | void loop() { 84 | 85 | // your loop code 86 | 87 | } 88 | 89 | ``` 90 | 91 | Create `include/lv_conf.h`: 92 | 93 | * The library comes with integrated dependencies to [lvgl graphics library](https://lvgl.io) to simplify using it. 94 | * Therefore it is necessary to have an `lv_conf.h` file. So please copy the example from the example directory to your include path. There is no direct need to adapt it, but you can if you want so (e.g. to enable/disable other fonts). 95 | 96 | * Under Linux, the easiest way to do this: (in the projects main directory) 97 | 98 | ``` 99 | cp .pio/libdeps/esp32-s3-devkitc-1/TRGBArduinoSupport/examples/lv_conf.h include/ 100 | ``` 101 | 102 | * You also can download the file (https://raw.githubusercontent.com/fablabnbg/TRGBArduinoSupport/main/examples/lv_conf.h) and save it to the include directory. 103 | 104 | ## UI Example 105 | 106 | There is an example UI in https://github.com/fablabnbg/TRGBArduinoSupport/tree/main/examples/ui_example . 107 | It shows a chart with battery voltage, the current time and IP adress of WiFi connection. There is also a "Standby" button to send the device into deep-sleep. It can be woken up again by touch. 108 | You can copy it to your platformio project `src`directory, e.g. (Linux) by 109 | ``` 110 | cp .pio/libdeps/esp32-s3-devkitc-1/TRGBArduinoSupport/examples/ui_example/* src/ 111 | ``` 112 | There is also an example `platformio.ini` file: 113 | ``` 114 | cp .pio/libdeps/esp32-s3-devkitc-1/TRGBArduinoSupport/examples/platformio.ini . 115 | ``` 116 | 117 | Adapt `src/main.cpp` to your needs (change Wifi SSID and password) and then build and upload it with `platformio run -t upload`. 118 | 119 | ## Caveats 120 | 121 | ### USB CDC 122 | 123 | The T-RGB has no UART/UART to USB interface. Instead it uses ESP32's native USB support. The onboard USB-C connector is connected directly to corresponding GPIOS. Firmware upload is possible using this USB interface in any case (at least in boot mode which can be manually entered with the Boot-pushbutton pressed during reset). 124 | 125 | To use the USB as Serial device, you must set these two configuration options: 126 | 127 | -DARDUINO_USB_MODE=1 128 | -DARDUINO_USB_CDC_ON_BOOT=1 129 | 130 | The first one activates the USB support in general, the second one activates the support for USB as `Serial` device. 131 | Unfortunately the direct USB support has big disadvantage: 132 | **Output to `Serial` blocks when the output buffer is full.** As long as there is no terminal emulator (like miniterm.py) connected to the ESP32, the buffer will run full quickly and the device gets laggy. If you use `Serial.flush()` somewhere in your code, it will block until the Serial device is read from terminal. 133 | 134 | * So, you should connect a terminal emulator OR set `ARDUINO_USB_CDC_ON_BOOT` to 0. 135 | * As a workaround you can set the tx timeout to a low value (`Serial.setTxTimeoutMs(1);`) and you must avoid using `Serial.flush()`. 136 | 137 | CDC also means that not all debug output from ESP-IDF/freeRTOS can be written to Serial output. This especially affects crashes/resets: 138 | **You won't see a reset reason**, so it can be hard to find issues like stack overflows, heap corruption or watchdog timeouts. 139 | You can install the Espressif IDF locally and use the coredump.py utility provided by Espressif. We recommend to install it in a seperate directory, e.g. by following the instructions from Espressif: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html 140 | 141 | When IDF is installed and setup, you can get debug output with: `esp-coredump --port /dev/ttyACM0 info_corefile .pio/build/trgb-esp32-s3/firmware.elf` 142 | 143 | This will show a long dump of registers, threads and stack trace per thread. 144 | 145 | Example for crash due to nullptr access ("LoadProhibitedCause" as reset cause) in `src/BLEDevices.cpp:142` 146 | 147 | ``` 148 | espcoredump.py v1.4.2 149 | INFO: Invoke parttool to read image. 150 | INFO: esptool.py v4.5.1 151 | Serial port /dev/ttyACM0 152 | Connecting... 153 | Detecting chip type... ESP32-S3 154 | Chip is ESP32-S3 (revision v0.1) 155 | 156 | [..more device info..] 157 | 158 | =============================================================== 159 | ==================== ESP32 CORE DUMP START ==================== 160 | 161 | Crashed task handle: 0x3fcf34f4, name: 'esp_timer', GDB name: 'process 1070544116' 162 | 163 | ================== CURRENT THREAD REGISTERS =================== 164 | exccause 0x1c (LoadProhibitedCause) 165 | excvaddr 0x34 166 | epc1 0x420e2fd1 167 | epc2 0x0 168 | epc3 0x0 169 | epc4 0x0 170 | epc5 0x0 171 | epc6 0x0 172 | eps2 0x0 173 | eps3 0x0 174 | eps4 0x0 175 | eps5 0x0 176 | eps6 0x0 177 | pc 0x42049ff6 0x42049ff6 178 | 179 | [.. more registers..] 180 | [.. Stack trace of crashed thread followed by a list of all threads:] 181 | 182 | ==================== CURRENT THREAD STACK ===================== 183 | #0 BLERemoteService::getCharacteristic (this=0x0, uuid=...) at /home/ian/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src/BLERemoteService.cpp:142 184 | #1 0x42005080 in BLEDevices::connectToServer (this=, ctype=) at src/BLEDevices.cpp:142 185 | #2 0x420059d5 in BLEDevices::connCheckLoop (this=0x3fca0eb8 ) at src/BLEDevices.cpp:305 186 | #3 BLEDevices::connCheckLoop (this=0x3fca0eb8 ) at src/BLEDevices.cpp:300 187 | #4 0x42005a80 in BLEDevices::::operator() (__closure=0x0, thisInstance=0x3fca0eb8 ) at src/BLEDevices.cpp:183 188 | #5 BLEDevices::::_FUN(BLEDevices *) () at src/BLEDevices.cpp:183 189 | #6 0x42076d51 in timer_process_alarm (dispatch_method=ESP_TIMER_TASK) at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_timer/src/esp_timer.c:360 190 | #7 timer_task (arg=) at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_timer/src/esp_timer.c:386 191 | 192 | ======================== THREADS INFO ========================= 193 | Id Target Id Frame 194 | * 1 process 1070544116 BLERemoteService::getCharacteristic (this=0x0, uuid=...) at /home/ian/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src/BLERemoteService.cpp:142 195 | 2 process 1070319624 0x400559e0 in ?? () 196 | 3 process 1070516268 0x400559e0 in ?? () 197 | 4 process 1070552712 0x4215b05e in esp_pm_impl_waiti () at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_pm/pm_impl.c:839 198 | 5 process 1070551312 0x4215b05e in esp_pm_impl_waiti () at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_pm/pm_impl.c:839 199 | 6 process 1070274428 UIFacade::updateHandler (this=0x3fca0bb0 ) at src/UIFacade.cpp:89 200 | 7 process 1070523172 0x40381e9a in vPortEnterCritical (mux=0x3fced67c) at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/port/xtensa/include/freertos/portmacro.h:578 201 | 8 process 1070536660 0x40382002 in vPortEnterCritical (mux=0x3fcf13ac) at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/port/xtensa/include/freertos/portmacro.h:578 202 | 9 process 1070524764 0x40381e9a in vPortEnterCritical (mux=0x3fcee6e0) at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/port/xtensa/include/freertos/portmacro.h:578 203 | 10 process 1070538360 vPortEnterCritical (mux=0x3fcf1a50) at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/port/xtensa/include/freertos/portmacro.h:578 204 | 11 process 1070525124 0x40381e9a in vPortEnterCritical (mux=0x3fcee5d4) at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/port/xtensa/include/freertos/portmacro.h:578 205 | 12 process 1070324868 0x40382004 in vPortEnterCritical (mux=0x3fcbd194) at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/port/xtensa/include/freertos/portmacro.h:578 206 | 13 process 1070306488 0x40382004 in vPortEnterCritical (mux=0x3fcb8414) at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/port/xtensa/include/freertos/portmacro.h:578 207 | 14 process 1070333008 0x40382004 in vPortEnterCritical (mux=0x3fcbe960) at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/port/xtensa/include/freertos/portmacro.h:578 208 | 15 process 1070559724 0x40381e9a in vPortEnterCritical (mux=0x3fcf6b94) at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/port/xtensa/include/freertos/portmacro.h:578 209 | 210 | 211 | [.. stack trace of all threads + information about memory regions] 212 | 213 | ``` 214 | 215 | ### Touchpad 216 | 217 | The examples from LilyGo for touchpad are quite confusing. I changed the code to use only the ft3267 touch controller and fixed a bug in the callback functions. The original code does not correctly behave when touch is released: It sends a position 0,0 once after release. This is fixed in the TRGBArduinoSupport code. 218 | 219 | **It seems that the FT3267 is only used on the "oval" variant of the T-RGB device.** The round variant is therefore not yet supported. 220 | -------------------------------------------------------------------------------- /examples/install_example.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir ../include 4 | cp lv_conf.h ../include 5 | cp ui_example/* ../src 6 | cp platformio.ini .. 7 | -------------------------------------------------------------------------------- /examples/lv_conf.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_conf.h 3 | * Configuration file for v8.3.4 adapted to T-RGB device (ESP32-S3 and RGB display) 4 | */ 5 | 6 | /* 7 | * Copy this file as `lv_conf.h` 8 | * 1. simply next to the `lvgl` folder 9 | * 2. or any other places and 10 | * - define `LV_CONF_INCLUDE_SIMPLE` 11 | * - add the path as include path 12 | */ 13 | 14 | /* clang-format off */ 15 | #if 1 /*Set it to "1" to enable content*/ 16 | 17 | #ifndef LV_CONF_H 18 | #define LV_CONF_H 19 | 20 | 21 | #include 22 | 23 | /*==================== 24 | COLOR SETTINGS 25 | *====================*/ 26 | 27 | /*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/ 28 | #define LV_COLOR_DEPTH 16 29 | 30 | /*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/ 31 | // Note: T-RGB has 16bit interface, so no swap needed 32 | #define LV_COLOR_16_SWAP 0 33 | 34 | /*Enable features to draw on transparent background. 35 | *It's required if opa, and transform_* style properties are used. 36 | *Can be also used if the UI is above another layer, e.g. an OSD menu or video player.*/ 37 | #define LV_COLOR_SCREEN_TRANSP 1 38 | 39 | /* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. 40 | * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ 41 | #define LV_COLOR_MIX_ROUND_OFS 0 42 | 43 | /*Images pixels with this color will not be drawn if they are chroma keyed)*/ 44 | #define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ 45 | 46 | /*========================= 47 | MEMORY SETTINGS 48 | *=========================*/ 49 | 50 | /*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/ 51 | #define LV_MEM_CUSTOM 1 52 | #if LV_MEM_CUSTOM == 0 53 | /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/ 54 | #define LV_MEM_SIZE (48U * 1024U) /*[bytes]*/ 55 | 56 | /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/ 57 | #define LV_MEM_ADR 0 /*0: unused*/ 58 | /*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/ 59 | #if LV_MEM_ADR == 0 60 | #undef LV_MEM_POOL_INCLUDE 61 | #undef LV_MEM_POOL_ALLOC 62 | #endif 63 | 64 | #else /*LV_MEM_CUSTOM*/ 65 | #define LV_MEM_CUSTOM_INCLUDE "esp32-hal-psram.h"// /*Header for the dynamic memory function*/ 66 | #define LV_MEM_CUSTOM_ALLOC ps_malloc 67 | #define LV_MEM_CUSTOM_FREE free 68 | #define LV_MEM_CUSTOM_REALLOC ps_realloc 69 | #endif /*LV_MEM_CUSTOM*/ 70 | 71 | /*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms. 72 | *You will see an error log message if there wasn't enough buffers. */ 73 | #define LV_MEM_BUF_MAX_NUM 16 74 | 75 | /*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/ 76 | #define LV_MEMCPY_MEMSET_STD 0 77 | 78 | /*==================== 79 | HAL SETTINGS 80 | *====================*/ 81 | 82 | /*Default display refresh period. LVG will redraw changed areas with this period time*/ 83 | #define LV_DISP_DEF_REFR_PERIOD 16 /*[ms]*/ 84 | 85 | /*Input device read period in milliseconds*/ 86 | #define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/ 87 | 88 | /*Use a custom tick source that tells the elapsed time in milliseconds. 89 | *It removes the need to manually update the tick with `lv_tick_inc()`)*/ 90 | #define LV_TICK_CUSTOM 1 91 | #if LV_TICK_CUSTOM 92 | #define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ 93 | #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ 94 | #endif /*LV_TICK_CUSTOM*/ 95 | 96 | /*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings. 97 | *(Not so important, you can adjust it to modify default sizes and spaces)*/ 98 | #define LV_DPI_DEF 130 /*[px/inch]*/ 99 | 100 | /*======================= 101 | * FEATURE CONFIGURATION 102 | *=======================*/ 103 | 104 | /*------------- 105 | * Drawing 106 | *-----------*/ 107 | 108 | /*Enable complex draw engine. 109 | *Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/ 110 | #define LV_DRAW_COMPLEX 1 111 | #if LV_DRAW_COMPLEX != 0 112 | 113 | /*Allow buffering some shadow calculation. 114 | *LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` 115 | *Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/ 116 | #define LV_SHADOW_CACHE_SIZE 0 117 | 118 | /* Set number of maximally cached circle data. 119 | * The circumference of 1/4 circle are saved for anti-aliasing 120 | * radius * 4 bytes are used per circle (the most often used radiuses are saved) 121 | * 0: to disable caching */ 122 | #define LV_CIRCLE_CACHE_SIZE 4 123 | #endif /*LV_DRAW_COMPLEX*/ 124 | 125 | /** 126 | * "Simple layers" are used when a widget has `style_opa < 255` to buffer the widget into a layer 127 | * and blend it as an image with the given opacity. 128 | * Note that `bg_opa`, `text_opa` etc don't require buffering into layer) 129 | * The widget can be buffered in smaller chunks to avoid using large buffers. 130 | * 131 | * - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it 132 | * - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated. 133 | * 134 | * Both buffer sizes are in bytes. 135 | * "Transformed layers" (where transform_angle/zoom properties are used) use larger buffers 136 | * and can't be drawn in chunks. So these settings affects only widgets with opacity. 137 | */ 138 | #define LV_LAYER_SIMPLE_BUF_SIZE (24 * 1024) 139 | #define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024) 140 | 141 | /*Default image cache size. Image caching keeps the images opened. 142 | *If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added) 143 | *With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. 144 | *However the opened images might consume additional RAM. 145 | *0: to disable caching*/ 146 | #define LV_IMG_CACHE_DEF_SIZE 0 147 | 148 | /*Number of stops allowed per gradient. Increase this to allow more stops. 149 | *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ 150 | #define LV_GRADIENT_MAX_STOPS 2 151 | 152 | /*Default gradient buffer size. 153 | *When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again. 154 | *LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes. 155 | *If the cache is too small the map will be allocated only while it's required for the drawing. 156 | *0 mean no caching.*/ 157 | #define LV_GRAD_CACHE_DEF_SIZE 0 158 | 159 | /*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display) 160 | *LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface 161 | *The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */ 162 | #define LV_DITHER_GRADIENT 0 163 | #if LV_DITHER_GRADIENT 164 | /*Add support for error diffusion dithering. 165 | *Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing. 166 | *The increase in memory consumption is (24 bits * object's width)*/ 167 | #define LV_DITHER_ERROR_DIFFUSION 0 168 | #endif 169 | 170 | /*Maximum buffer size to allocate for rotation. 171 | *Only used if software rotation is enabled in the display driver.*/ 172 | #define LV_DISP_ROT_MAX_BUF (10*1024) 173 | 174 | /*------------- 175 | * GPU 176 | *-----------*/ 177 | 178 | /*Use Arm's 2D acceleration library Arm-2D */ 179 | #define LV_USE_GPU_ARM2D 0 180 | 181 | /*Use STM32's DMA2D (aka Chrom Art) GPU*/ 182 | #define LV_USE_GPU_STM32_DMA2D 0 183 | #if LV_USE_GPU_STM32_DMA2D 184 | /*Must be defined to include path of CMSIS header of target processor 185 | e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ 186 | #define LV_GPU_DMA2D_CMSIS_INCLUDE 187 | #endif 188 | 189 | /*Use SWM341's DMA2D GPU*/ 190 | #define LV_USE_GPU_SWM341_DMA2D 0 191 | #if LV_USE_GPU_SWM341_DMA2D 192 | #define LV_GPU_SWM341_DMA2D_INCLUDE "SWM341.h" 193 | #endif 194 | 195 | /*Use NXP's PXP GPU iMX RTxxx platforms*/ 196 | #define LV_USE_GPU_NXP_PXP 0 197 | #if LV_USE_GPU_NXP_PXP 198 | /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) 199 | * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS 200 | * has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. 201 | *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init() 202 | */ 203 | #define LV_USE_GPU_NXP_PXP_AUTO_INIT 0 204 | #endif 205 | 206 | /*Use NXP's VG-Lite GPU iMX RTxxx platforms*/ 207 | #define LV_USE_GPU_NXP_VG_LITE 0 208 | 209 | /*Use SDL renderer API*/ 210 | #define LV_USE_GPU_SDL 0 211 | #if LV_USE_GPU_SDL 212 | #define LV_GPU_SDL_INCLUDE_PATH 213 | /*Texture cache size, 8MB by default*/ 214 | #define LV_GPU_SDL_LRU_SIZE (1024 * 1024 * 8) 215 | /*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/ 216 | #define LV_GPU_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6)) 217 | #endif 218 | 219 | /*------------- 220 | * Logging 221 | *-----------*/ 222 | 223 | /*Enable the log module*/ 224 | #define LV_USE_LOG 0 225 | #if LV_USE_LOG 226 | 227 | /*How important log should be added: 228 | *LV_LOG_LEVEL_TRACE A lot of logs to give detailed information 229 | *LV_LOG_LEVEL_INFO Log important events 230 | *LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem 231 | *LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail 232 | *LV_LOG_LEVEL_USER Only logs added by the user 233 | *LV_LOG_LEVEL_NONE Do not log anything*/ 234 | #define LV_LOG_LEVEL LV_LOG_LEVEL_WARN 235 | 236 | /*1: Print the log with 'printf'; 237 | *0: User need to register a callback with `lv_log_register_print_cb()`*/ 238 | #define LV_LOG_PRINTF 0 239 | 240 | /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/ 241 | #define LV_LOG_TRACE_MEM 1 242 | #define LV_LOG_TRACE_TIMER 1 243 | #define LV_LOG_TRACE_INDEV 1 244 | #define LV_LOG_TRACE_DISP_REFR 1 245 | #define LV_LOG_TRACE_EVENT 1 246 | #define LV_LOG_TRACE_OBJ_CREATE 1 247 | #define LV_LOG_TRACE_LAYOUT 1 248 | #define LV_LOG_TRACE_ANIM 1 249 | 250 | #endif /*LV_USE_LOG*/ 251 | 252 | /*------------- 253 | * Asserts 254 | *-----------*/ 255 | 256 | /*Enable asserts if an operation is failed or an invalid data is found. 257 | *If LV_USE_LOG is enabled an error message will be printed on failure*/ 258 | #define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/ 259 | #define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/ 260 | #define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/ 261 | #define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/ 262 | #define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/ 263 | 264 | /*Add a custom handler when assert happens e.g. to restart the MCU*/ 265 | #define LV_ASSERT_HANDLER_INCLUDE 266 | #define LV_ASSERT_HANDLER while(1); /*Halt by default*/ 267 | 268 | /*------------- 269 | * Others 270 | *-----------*/ 271 | 272 | /*1: Show CPU usage and FPS count*/ 273 | #define LV_USE_PERF_MONITOR 0 274 | #if LV_USE_PERF_MONITOR 275 | #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT 276 | #endif 277 | 278 | /*1: Show the used memory and the memory fragmentation 279 | * Requires LV_MEM_CUSTOM = 0*/ 280 | #define LV_USE_MEM_MONITOR 0 281 | #if LV_USE_MEM_MONITOR 282 | #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT 283 | #endif 284 | 285 | /*1: Draw random colored rectangles over the redrawn areas*/ 286 | #define LV_USE_REFR_DEBUG 0 287 | 288 | /*Change the built in (v)snprintf functions*/ 289 | #define LV_SPRINTF_CUSTOM 1 290 | #if LV_SPRINTF_CUSTOM 291 | #define LV_SPRINTF_INCLUDE 292 | #define lv_snprintf snprintf 293 | #define lv_vsnprintf vsnprintf 294 | #else /*LV_SPRINTF_CUSTOM*/ 295 | #define LV_SPRINTF_USE_FLOAT 0 296 | #endif /*LV_SPRINTF_CUSTOM*/ 297 | 298 | #define LV_USE_USER_DATA 1 299 | 300 | /*Garbage Collector settings 301 | *Used if lvgl is bound to higher level language and the memory is managed by that language*/ 302 | #define LV_ENABLE_GC 0 303 | #if LV_ENABLE_GC != 0 304 | #define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ 305 | #endif /*LV_ENABLE_GC*/ 306 | 307 | /*===================== 308 | * COMPILER SETTINGS 309 | *====================*/ 310 | 311 | /*For big endian systems set to 1*/ 312 | #define LV_BIG_ENDIAN_SYSTEM 0 313 | 314 | /*Define a custom attribute to `lv_tick_inc` function*/ 315 | #define LV_ATTRIBUTE_TICK_INC 316 | 317 | /*Define a custom attribute to `lv_timer_handler` function*/ 318 | #define LV_ATTRIBUTE_TIMER_HANDLER 319 | 320 | /*Define a custom attribute to `lv_disp_flush_ready` function*/ 321 | #define LV_ATTRIBUTE_FLUSH_READY 322 | 323 | /*Required alignment size for buffers*/ 324 | #define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1 325 | 326 | /*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default). 327 | * E.g. __attribute__((aligned(4)))*/ 328 | #define LV_ATTRIBUTE_MEM_ALIGN 329 | 330 | /*Attribute to mark large constant arrays for example font's bitmaps*/ 331 | #define LV_ATTRIBUTE_LARGE_CONST 332 | 333 | /*Compiler prefix for a big array declaration in RAM*/ 334 | #define LV_ATTRIBUTE_LARGE_RAM_ARRAY 335 | 336 | /*Place performance critical functions into a faster memory (e.g RAM)*/ 337 | #define LV_ATTRIBUTE_FAST_MEM 338 | 339 | /*Prefix variables that are used in GPU accelerated operations, often these need to be placed in RAM sections that are DMA accessible*/ 340 | #define LV_ATTRIBUTE_DMA 341 | 342 | /*Export integer constant to binding. This macro is used with constants in the form of LV_ that 343 | *should also appear on LVGL binding API such as Micropython.*/ 344 | #define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/ 345 | 346 | /*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/ 347 | #define LV_USE_LARGE_COORD 0 348 | 349 | /*================== 350 | * FONT USAGE 351 | *===================*/ 352 | 353 | /*Montserrat fonts with ASCII range and some symbols using bpp = 4 354 | *https://fonts.google.com/specimen/Montserrat*/ 355 | #define LV_FONT_MONTSERRAT_8 0 356 | #define LV_FONT_MONTSERRAT_10 0 357 | #define LV_FONT_MONTSERRAT_12 1 358 | #define LV_FONT_MONTSERRAT_14 1 359 | #define LV_FONT_MONTSERRAT_16 1 360 | #define LV_FONT_MONTSERRAT_18 0 361 | #define LV_FONT_MONTSERRAT_20 0 362 | #define LV_FONT_MONTSERRAT_22 0 363 | #define LV_FONT_MONTSERRAT_24 1 364 | #define LV_FONT_MONTSERRAT_26 0 365 | #define LV_FONT_MONTSERRAT_28 1 366 | #define LV_FONT_MONTSERRAT_30 0 367 | #define LV_FONT_MONTSERRAT_32 0 368 | #define LV_FONT_MONTSERRAT_34 0 369 | #define LV_FONT_MONTSERRAT_36 1 370 | #define LV_FONT_MONTSERRAT_38 0 371 | #define LV_FONT_MONTSERRAT_40 0 372 | #define LV_FONT_MONTSERRAT_42 0 373 | #define LV_FONT_MONTSERRAT_44 0 374 | #define LV_FONT_MONTSERRAT_46 0 375 | #define LV_FONT_MONTSERRAT_48 1 376 | 377 | /*Demonstrate special features*/ 378 | #define LV_FONT_MONTSERRAT_12_SUBPX 0 379 | #define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/ 380 | #define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Persian letters and all their forms*/ 381 | #define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/ 382 | 383 | /*Pixel perfect monospace fonts*/ 384 | #define LV_FONT_UNSCII_8 0 385 | #define LV_FONT_UNSCII_16 0 386 | 387 | /*Optionally declare custom fonts here. 388 | *You can use these fonts as default font too and they will be available globally. 389 | *E.g. #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) LV_FONT_DECLARE(my_font_2)*/ 390 | #define LV_FONT_CUSTOM_DECLARE 391 | 392 | /*Always set a default font*/ 393 | #define LV_FONT_DEFAULT &lv_font_montserrat_14 394 | 395 | /*Enable handling large font and/or fonts with a lot of characters. 396 | *The limit depends on the font size, font face and bpp. 397 | *Compiler error will be triggered if a font needs it.*/ 398 | #define LV_FONT_FMT_TXT_LARGE 0 399 | 400 | /*Enables/disables support for compressed fonts.*/ 401 | #define LV_USE_FONT_COMPRESSED 0 402 | 403 | /*Enable subpixel rendering*/ 404 | #define LV_USE_FONT_SUBPX 0 405 | #if LV_USE_FONT_SUBPX 406 | /*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/ 407 | #define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ 408 | #endif 409 | 410 | /*Enable drawing placeholders when glyph dsc is not found*/ 411 | #define LV_USE_FONT_PLACEHOLDER 1 412 | 413 | /*================= 414 | * TEXT SETTINGS 415 | *=================*/ 416 | 417 | /** 418 | * Select a character encoding for strings. 419 | * Your IDE or editor should have the same character encoding 420 | * - LV_TXT_ENC_UTF8 421 | * - LV_TXT_ENC_ASCII 422 | */ 423 | #define LV_TXT_ENC LV_TXT_ENC_UTF8 424 | 425 | /*Can break (wrap) texts on these chars*/ 426 | #define LV_TXT_BREAK_CHARS " ,.;:-_" 427 | 428 | /*If a word is at least this long, will break wherever "prettiest" 429 | *To disable, set to a value <= 0*/ 430 | #define LV_TXT_LINE_BREAK_LONG_LEN 0 431 | 432 | /*Minimum number of characters in a long word to put on a line before a break. 433 | *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/ 434 | #define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 435 | 436 | /*Minimum number of characters in a long word to put on a line after a break. 437 | *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/ 438 | #define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 439 | 440 | /*The control character to use for signalling text recoloring.*/ 441 | #define LV_TXT_COLOR_CMD "#" 442 | 443 | /*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts. 444 | *The direction will be processed according to the Unicode Bidirectional Algorithm: 445 | *https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ 446 | #define LV_USE_BIDI 0 447 | #if LV_USE_BIDI 448 | /*Set the default direction. Supported values: 449 | *`LV_BASE_DIR_LTR` Left-to-Right 450 | *`LV_BASE_DIR_RTL` Right-to-Left 451 | *`LV_BASE_DIR_AUTO` detect texts base direction*/ 452 | #define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO 453 | #endif 454 | 455 | /*Enable Arabic/Persian processing 456 | *In these languages characters should be replaced with an other form based on their position in the text*/ 457 | #define LV_USE_ARABIC_PERSIAN_CHARS 0 458 | 459 | /*================== 460 | * WIDGET USAGE 461 | *================*/ 462 | 463 | /*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/ 464 | 465 | #define LV_USE_ARC 1 466 | 467 | #define LV_USE_BAR 1 468 | 469 | #define LV_USE_BTN 1 470 | 471 | #define LV_USE_BTNMATRIX 1 472 | 473 | #define LV_USE_CANVAS 1 474 | 475 | #define LV_USE_CHECKBOX 1 476 | 477 | #define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ 478 | 479 | #define LV_USE_IMG 1 /*Requires: lv_label*/ 480 | 481 | #define LV_USE_LABEL 1 482 | #if LV_USE_LABEL 483 | #define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ 484 | #define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ 485 | #endif 486 | 487 | #define LV_USE_LINE 1 488 | 489 | #define LV_USE_ROLLER 1 /*Requires: lv_label*/ 490 | #if LV_USE_ROLLER 491 | #define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/ 492 | #endif 493 | 494 | #define LV_USE_SLIDER 1 /*Requires: lv_bar*/ 495 | 496 | #define LV_USE_SWITCH 1 497 | 498 | #define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ 499 | #if LV_USE_TEXTAREA != 0 500 | #define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ 501 | #endif 502 | 503 | #define LV_USE_TABLE 1 504 | 505 | /*================== 506 | * EXTRA COMPONENTS 507 | *==================*/ 508 | 509 | /*----------- 510 | * Widgets 511 | *----------*/ 512 | #define LV_USE_ANIMIMG 1 513 | 514 | #define LV_USE_CALENDAR 1 515 | #if LV_USE_CALENDAR 516 | #define LV_CALENDAR_WEEK_STARTS_MONDAY 0 517 | #if LV_CALENDAR_WEEK_STARTS_MONDAY 518 | #define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"} 519 | #else 520 | #define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"} 521 | #endif 522 | 523 | #define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} 524 | #define LV_USE_CALENDAR_HEADER_ARROW 1 525 | #define LV_USE_CALENDAR_HEADER_DROPDOWN 1 526 | #endif /*LV_USE_CALENDAR*/ 527 | 528 | #define LV_USE_CHART 1 529 | 530 | #define LV_USE_COLORWHEEL 1 531 | 532 | #define LV_USE_IMGBTN 1 533 | 534 | #define LV_USE_KEYBOARD 1 535 | 536 | #define LV_USE_LED 1 537 | 538 | #define LV_USE_LIST 1 539 | 540 | #define LV_USE_MENU 1 541 | 542 | #define LV_USE_METER 1 543 | 544 | #define LV_USE_MSGBOX 1 545 | 546 | #define LV_USE_SPAN 1 547 | #if LV_USE_SPAN 548 | /*A line text can contain maximum num of span descriptor */ 549 | #define LV_SPAN_SNIPPET_STACK_SIZE 64 550 | #endif 551 | 552 | #define LV_USE_SPINBOX 1 553 | 554 | #define LV_USE_SPINNER 1 555 | 556 | #define LV_USE_TABVIEW 1 557 | 558 | #define LV_USE_TILEVIEW 1 559 | 560 | #define LV_USE_WIN 1 561 | 562 | /*----------- 563 | * Themes 564 | *----------*/ 565 | 566 | /*A simple, impressive and very complete theme*/ 567 | #define LV_USE_THEME_DEFAULT 1 568 | #if LV_USE_THEME_DEFAULT 569 | 570 | /*0: Light mode; 1: Dark mode*/ 571 | #define LV_THEME_DEFAULT_DARK 0 572 | 573 | /*1: Enable grow on press*/ 574 | #define LV_THEME_DEFAULT_GROW 1 575 | 576 | /*Default transition time in [ms]*/ 577 | #define LV_THEME_DEFAULT_TRANSITION_TIME 80 578 | #endif /*LV_USE_THEME_DEFAULT*/ 579 | 580 | /*A very simple theme that is a good starting point for a custom theme*/ 581 | #define LV_USE_THEME_BASIC 1 582 | 583 | /*A theme designed for monochrome displays*/ 584 | #define LV_USE_THEME_MONO 1 585 | 586 | /*----------- 587 | * Layouts 588 | *----------*/ 589 | 590 | /*A layout similar to Flexbox in CSS.*/ 591 | #define LV_USE_FLEX 1 592 | 593 | /*A layout similar to Grid in CSS.*/ 594 | #define LV_USE_GRID 1 595 | 596 | /*--------------------- 597 | * 3rd party libraries 598 | *--------------------*/ 599 | 600 | /*File system interfaces for common APIs */ 601 | 602 | /*API for fopen, fread, etc*/ 603 | #define LV_USE_FS_STDIO 0 604 | #if LV_USE_FS_STDIO 605 | #define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ 606 | #define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ 607 | #define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ 608 | #endif 609 | 610 | /*API for open, read, etc*/ 611 | #define LV_USE_FS_POSIX 0 612 | #if LV_USE_FS_POSIX 613 | #define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ 614 | #define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ 615 | #define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ 616 | #endif 617 | 618 | /*API for CreateFile, ReadFile, etc*/ 619 | #define LV_USE_FS_WIN32 0 620 | #if LV_USE_FS_WIN32 621 | #define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ 622 | #define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ 623 | #define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ 624 | #endif 625 | 626 | /*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/ 627 | #define LV_USE_FS_FATFS 0 628 | #if LV_USE_FS_FATFS 629 | #define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ 630 | #define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ 631 | #endif 632 | 633 | /*PNG decoder library*/ 634 | #define LV_USE_PNG 0 635 | 636 | /*BMP decoder library*/ 637 | #define LV_USE_BMP 0 638 | 639 | /* JPG + split JPG decoder library. 640 | * Split JPG is a custom format optimized for embedded systems. */ 641 | #define LV_USE_SJPG 0 642 | 643 | /*GIF decoder library*/ 644 | #define LV_USE_GIF 0 645 | 646 | /*QR code library*/ 647 | #define LV_USE_QRCODE 0 648 | 649 | /*FreeType library*/ 650 | #define LV_USE_FREETYPE 0 651 | #if LV_USE_FREETYPE 652 | /*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/ 653 | #define LV_FREETYPE_CACHE_SIZE (16 * 1024) 654 | #if LV_FREETYPE_CACHE_SIZE >= 0 655 | /* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */ 656 | /* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */ 657 | /* if font size >= 256, must be configured as image cache */ 658 | #define LV_FREETYPE_SBIT_CACHE 0 659 | /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */ 660 | /* (0:use system defaults) */ 661 | #define LV_FREETYPE_CACHE_FT_FACES 0 662 | #define LV_FREETYPE_CACHE_FT_SIZES 0 663 | #endif 664 | #endif 665 | 666 | /*Rlottie library*/ 667 | #define LV_USE_RLOTTIE 0 668 | 669 | /*FFmpeg library for image decoding and playing videos 670 | *Supports all major image formats so do not enable other image decoder with it*/ 671 | #define LV_USE_FFMPEG 0 672 | #if LV_USE_FFMPEG 673 | /*Dump input information to stderr*/ 674 | #define LV_FFMPEG_DUMP_FORMAT 0 675 | #endif 676 | 677 | /*----------- 678 | * Others 679 | *----------*/ 680 | 681 | /*1: Enable API to take snapshot for object*/ 682 | #define LV_USE_SNAPSHOT 0 683 | 684 | /*1: Enable Monkey test*/ 685 | #define LV_USE_MONKEY 0 686 | 687 | /*1: Enable grid navigation*/ 688 | #define LV_USE_GRIDNAV 0 689 | 690 | /*1: Enable lv_obj fragment*/ 691 | #define LV_USE_FRAGMENT 0 692 | 693 | /*1: Support using images as font in label or span widgets */ 694 | #define LV_USE_IMGFONT 0 695 | 696 | /*1: Enable a published subscriber based messaging system */ 697 | #define LV_USE_MSG 1 698 | 699 | /*1: Enable Pinyin input method*/ 700 | /*Requires: lv_keyboard*/ 701 | #define LV_USE_IME_PINYIN 0 702 | #if LV_USE_IME_PINYIN 703 | /*1: Use default thesaurus*/ 704 | /*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/ 705 | #define LV_IME_PINYIN_USE_DEFAULT_DICT 1 706 | /*Set the maximum number of candidate panels that can be displayed*/ 707 | /*This needs to be adjusted according to the size of the screen*/ 708 | #define LV_IME_PINYIN_CAND_TEXT_NUM 6 709 | 710 | /*Use 9 key input(k9)*/ 711 | #define LV_IME_PINYIN_USE_K9_MODE 1 712 | #if LV_IME_PINYIN_USE_K9_MODE == 1 713 | #define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3 714 | #endif // LV_IME_PINYIN_USE_K9_MODE 715 | #endif 716 | 717 | /*================== 718 | * EXAMPLES 719 | *==================*/ 720 | 721 | /*Enable the examples to be built with the library*/ 722 | #define LV_BUILD_EXAMPLES 0 723 | 724 | /*=================== 725 | * DEMO USAGE 726 | ====================*/ 727 | 728 | /*Show some widget. It might be required to increase `LV_MEM_SIZE` */ 729 | #define LV_USE_DEMO_WIDGETS 0 730 | #if LV_USE_DEMO_WIDGETS 731 | #define LV_DEMO_WIDGETS_SLIDESHOW 0 732 | #endif 733 | 734 | /*Demonstrate the usage of encoder and keyboard*/ 735 | #define LV_USE_DEMO_KEYPAD_AND_ENCODER 0 736 | 737 | /*Benchmark your system*/ 738 | #define LV_USE_DEMO_BENCHMARK 0 739 | #if LV_USE_DEMO_BENCHMARK 740 | /*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/ 741 | #define LV_DEMO_BENCHMARK_RGB565A8 0 742 | #endif 743 | 744 | /*Stress test for LVGL*/ 745 | #define LV_USE_DEMO_STRESS 0 746 | 747 | /*Music player demo*/ 748 | #define LV_USE_DEMO_MUSIC 0 749 | #if LV_USE_DEMO_MUSIC 750 | #define LV_DEMO_MUSIC_SQUARE 0 751 | #define LV_DEMO_MUSIC_LANDSCAPE 0 752 | #define LV_DEMO_MUSIC_ROUND 0 753 | #define LV_DEMO_MUSIC_LARGE 0 754 | #define LV_DEMO_MUSIC_AUTO_PLAY 0 755 | #endif 756 | 757 | /*--END OF LV_CONF_H--*/ 758 | 759 | #endif /*LV_CONF_H*/ 760 | 761 | #endif /*End of "Content enable"*/ 762 | -------------------------------------------------------------------------------- /examples/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:esp32-s3-trgb] 12 | platform = espressif32 13 | board = esp32-s3-devkitc-1 14 | framework = arduino 15 | 16 | ;platform_packages = 17 | ; framework-arduinoespressif32@https://github.com/espressif/arduino-esp32.git#2.0.5 18 | build_flags = 19 | -DARDUINO_USB_MODE=1 20 | -DARDUINO_USB_CDC_ON_BOOT=1 21 | -DBOARD_HAS_PSRAM 22 | -DLV_CONF_PATH=${platformio.include_dir}/lv_conf.h 23 | board_build.cpu = esp32s3 24 | board_build.arduino.memory_type = qio_opi 25 | lib_deps = 26 | ianh/TRGBArduinoSupport 27 | mcxiaoke/ESPDateTime 28 | -------------------------------------------------------------------------------- /examples/ui_example/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ui.h" 4 | #include "WiFi.h" 5 | #include 6 | 7 | const char* ntpServer = "pool.ntp.org"; 8 | const char* ssid = "fablabnbg"; 9 | const char* password = "askForIt!"; 10 | 11 | // Callback from UI if Standby-Button is pressed 12 | void ui_ev_standby(lv_event_t * e) { 13 | trgb.deepSleep(); 14 | } 15 | 16 | void updateIP(const String &str) { 17 | lv_label_set_text(ui_SWifiLabelIPAddr, ("IP: " + str).c_str()); 18 | } 19 | 20 | void updateClock(const String &str) { 21 | lv_label_set_text(ui_S1LabelClock, str.c_str()); 22 | } 23 | 24 | 25 | void setup() { 26 | delay(100); // Rumors say it helps avoid sporadical crashes after wakeup from deep-sleep 27 | trgb.init(); 28 | 29 | // Print some info to Serial 30 | TRGBSuppport::print_chip_info(); 31 | TRGBSuppport::scan_iic(); 32 | 33 | // Initialize SD Card. It can be accessed by SD_MMC object. 34 | trgb.SD_init(); 35 | 36 | // Connect to WiFi 37 | WiFi.mode(WIFI_MODE_STA); 38 | WiFi.begin(ssid, password); 39 | configTime(3600, 3600, ntpServer); // Configure Timezone and NTP 40 | 41 | // load UI 42 | ui_init(); 43 | 44 | // add your own stuff .. 45 | } 46 | 47 | void loop() { 48 | static uint32_t Millis = 0; 49 | static bool wifiInitialized = false; 50 | static uint16_t time_counter = 0; 51 | lv_timer_handler(); 52 | if (millis() - Millis > 500) { // every 500ms 53 | time_counter++; 54 | Millis=millis(); 55 | float v = trgb.getBatVoltage(); 56 | chart_add_voltage(v); 57 | Serial.print(WiFi.status()); 58 | // Handle Wifi 59 | if (!wifiInitialized) { 60 | if (WiFi.status() == WL_CONNECTED) { 61 | wifiInitialized = true; 62 | updateIP(WiFi.localIP().toString()); 63 | } else if (time_counter > 30 /*15s*/) { 64 | // wifiInitialized = true; 65 | // Serial.println("Not connected to Wifi - disabling it"); 66 | // updateIP(String("WiFi disabled")); 67 | // WiFi.mode(WIFI_MODE_NULL); 68 | // WiFi.setSleep(WIFI_PS_MAX_MODEM); 69 | // WiFi.setSleep(true); 70 | WiFi.begin(ssid, password); // retry 71 | updateIP(String("Timeout - retrying..")); 72 | } else { 73 | delay(10); 74 | } 75 | } else if (WiFi.status() == WL_CONNECTION_LOST) { 76 | updateIP(String("connection lost")); 77 | Serial.println("Wifi connection lost - disabling it to save power"); 78 | WiFi.mode(WIFI_MODE_NULL); 79 | WiFi.setSleep(WIFI_PS_MAX_MODEM); 80 | WiFi.setSleep(true); 81 | } 82 | time_t now; 83 | time(&now); 84 | 85 | // To use the DateFormatter, add to platformio.ini lib_deps the library ESPDateTime 86 | String time_str = DateFormatter::format(DateFormatter::TIME_ONLY,now); 87 | updateClock(time_str); 88 | } else { 89 | delay(2); 90 | } 91 | } 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /examples/ui_example/ui.c: -------------------------------------------------------------------------------- 1 | #include "ui.h" 2 | //#include "ui_helpers.h" 3 | 4 | ///////////////////// VARIABLES //////////////////// 5 | lv_obj_t * ui_S1Main; 6 | lv_obj_t * ui_S1LabelTitle; 7 | lv_obj_t * ui_S1LabelClock; 8 | lv_obj_t * ui_SWifiLabelIPAddr; 9 | void ui_event_SWifiButtonStandby(lv_event_t * e); 10 | lv_obj_t * ui_SWifiButtonStandby; 11 | lv_obj_t * ui_ScreenWifiButtonLabelStandby; 12 | lv_obj_t * ui_ScreenChart_Chart1; 13 | 14 | ///////////////////// TEST LVGL SETTINGS //////////////////// 15 | #if LV_COLOR_DEPTH != 16 16 | #error "LV_COLOR_DEPTH should be 16bit to match SquareLine Studio's settings" 17 | #endif 18 | #if LV_COLOR_16_SWAP !=0 19 | #error "LV_COLOR_16_SWAP should be 0 to match SquareLine Studio's settings" 20 | #endif 21 | 22 | ///////////////////// ANIMATIONS //////////////////// 23 | 24 | ///////////////////// FUNCTIONS //////////////////// 25 | 26 | void ui_event_SWifiButtonStandby(lv_event_t * e) 27 | { 28 | lv_event_code_t event_code = lv_event_get_code(e); 29 | lv_obj_t * target = lv_event_get_target(e); 30 | if(event_code == LV_EVENT_LONG_PRESSED) { 31 | ui_ev_standby(e); 32 | } 33 | } 34 | 35 | ///////////////////// SCREENS //////////////////// 36 | void ui_S1Main_screen_init(void) 37 | { 38 | ui_S1Main = lv_obj_create(NULL); 39 | lv_obj_clear_flag(ui_S1Main, LV_OBJ_FLAG_SCROLLABLE); /// Flags 40 | 41 | ui_S1LabelTitle = lv_label_create(ui_S1Main); 42 | lv_obj_set_width(ui_S1LabelTitle, LV_SIZE_CONTENT); /// 1 43 | lv_obj_set_height(ui_S1LabelTitle, LV_SIZE_CONTENT); /// 1 44 | lv_obj_set_x(ui_S1LabelTitle, 0); 45 | lv_obj_set_y(ui_S1LabelTitle, -200); 46 | lv_obj_set_align(ui_S1LabelTitle, LV_ALIGN_CENTER); 47 | lv_label_set_text(ui_S1LabelTitle, "T-RGB Demo"); 48 | lv_obj_set_style_text_font(ui_S1LabelTitle, &lv_font_montserrat_24, LV_PART_MAIN | LV_STATE_DEFAULT); 49 | // lv_obj_clear_flag(ui_ScreenWifi, LV_OBJ_FLAG_SCROLLABLE); /// Flags 50 | // lv_obj_set_style_bg_img_src(ui_ScreenWifi, &ui_img_1672050212073_png, LV_PART_MAIN | LV_STATE_DEFAULT); 51 | 52 | ui_SWifiLabelIPAddr = lv_label_create(ui_S1Main); 53 | lv_obj_set_width(ui_SWifiLabelIPAddr, LV_SIZE_CONTENT); /// 1 54 | lv_obj_set_height(ui_SWifiLabelIPAddr, LV_SIZE_CONTENT); /// 1 55 | lv_obj_set_x(ui_SWifiLabelIPAddr, 0); 56 | lv_obj_set_y(ui_SWifiLabelIPAddr, lv_pct(-35)); 57 | lv_obj_set_align(ui_SWifiLabelIPAddr, LV_ALIGN_CENTER); 58 | lv_label_set_text(ui_SWifiLabelIPAddr, "IP: n/a"); 59 | lv_obj_set_style_text_font(ui_SWifiLabelIPAddr, &lv_font_montserrat_36, LV_PART_MAIN | LV_STATE_DEFAULT); 60 | 61 | ui_S1LabelClock = lv_label_create(ui_S1Main); 62 | lv_obj_set_width(ui_S1LabelClock, 180); 63 | lv_obj_set_height(ui_S1LabelClock, LV_SIZE_CONTENT); /// 1 64 | lv_obj_set_x(ui_S1LabelClock, 0); 65 | lv_obj_set_y(ui_S1LabelClock, 133); 66 | lv_obj_set_align(ui_S1LabelClock, LV_ALIGN_CENTER); 67 | lv_label_set_long_mode(ui_S1LabelClock, LV_LABEL_LONG_DOT); 68 | lv_label_set_text(ui_S1LabelClock, "xx:yy:zz"); 69 | lv_obj_set_style_text_align(ui_S1LabelClock, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); 70 | lv_obj_set_style_text_font(ui_S1LabelClock, &lv_font_montserrat_36, LV_PART_MAIN | LV_STATE_DEFAULT); 71 | 72 | 73 | // ui_ScreenWifi_Slider1 = lv_slider_create(ui_ScreenWifi); 74 | // lv_slider_set_range(ui_ScreenWifi_Slider1, 45, 255); 75 | // lv_slider_set_value(ui_ScreenWifi_Slider1, 220, LV_ANIM_OFF); 76 | // if(lv_slider_get_mode(ui_ScreenWifi_Slider1) == LV_SLIDER_MODE_RANGE) lv_slider_set_left_value(ui_ScreenWifi_Slider1, 0, 77 | // LV_ANIM_OFF); 78 | // lv_obj_set_width(ui_ScreenWifi_Slider1, 320); 79 | // lv_obj_set_height(ui_ScreenWifi_Slider1, 25); 80 | // lv_obj_set_x(ui_ScreenWifi_Slider1, 0); 81 | // lv_obj_set_y(ui_ScreenWifi_Slider1, lv_pct(25)); 82 | // lv_obj_set_align(ui_ScreenWifi_Slider1, LV_ALIGN_CENTER); 83 | // lv_obj_clear_flag(ui_ScreenWifi_Slider1, LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags 84 | 85 | // ui_ScreenWifi_Label8 = lv_label_create(ui_ScreenWifi); 86 | // lv_obj_set_width(ui_ScreenWifi_Label8, LV_SIZE_CONTENT); /// 1 87 | // lv_obj_set_height(ui_ScreenWifi_Label8, LV_SIZE_CONTENT); /// 1 88 | // lv_obj_set_x(ui_ScreenWifi_Label8, 0); 89 | // lv_obj_set_y(ui_ScreenWifi_Label8, lv_pct(25)); 90 | // lv_obj_set_align(ui_ScreenWifi_Label8, LV_ALIGN_CENTER); 91 | // lv_label_set_text(ui_ScreenWifi_Label8, "Helligkeit"); 92 | // lv_obj_set_style_text_color(ui_ScreenWifi_Label8, lv_color_hex(0x00ECBB), LV_PART_MAIN | LV_STATE_DEFAULT); 93 | // lv_obj_set_style_text_opa(ui_ScreenWifi_Label8, 255, LV_PART_MAIN | LV_STATE_DEFAULT); 94 | // lv_obj_set_style_text_font(ui_ScreenWifi_Label8, &lv_font_montserrat_24, LV_PART_MAIN | LV_STATE_DEFAULT); 95 | // lv_obj_set_style_blend_mode(ui_ScreenWifi_Label8, LV_BLEND_MODE_ADDITIVE, LV_PART_MAIN | LV_STATE_DEFAULT); 96 | 97 | ui_SWifiButtonStandby = lv_btn_create(ui_S1Main); 98 | lv_obj_set_width(ui_SWifiButtonStandby, 169); 99 | lv_obj_set_height(ui_SWifiButtonStandby, 50); 100 | lv_obj_set_x(ui_SWifiButtonStandby, 0); 101 | lv_obj_set_y(ui_SWifiButtonStandby, lv_pct(38)); 102 | lv_obj_set_align(ui_SWifiButtonStandby, LV_ALIGN_CENTER); 103 | lv_obj_add_flag(ui_SWifiButtonStandby, LV_OBJ_FLAG_SCROLL_ON_FOCUS); /// Flags 104 | lv_obj_clear_flag(ui_SWifiButtonStandby, LV_OBJ_FLAG_SCROLLABLE); /// Flags 105 | lv_obj_set_style_radius(ui_SWifiButtonStandby, 15, LV_PART_MAIN | LV_STATE_DEFAULT); 106 | lv_obj_set_style_bg_color(ui_SWifiButtonStandby, lv_color_hex(0x5D0000), LV_PART_MAIN | LV_STATE_DEFAULT); 107 | lv_obj_set_style_bg_opa(ui_SWifiButtonStandby, 255, LV_PART_MAIN | LV_STATE_DEFAULT); 108 | lv_obj_set_style_border_color(ui_SWifiButtonStandby, lv_color_hex(0x595959), LV_PART_MAIN | LV_STATE_DEFAULT); 109 | lv_obj_set_style_border_opa(ui_SWifiButtonStandby, 255, LV_PART_MAIN | LV_STATE_DEFAULT); 110 | lv_obj_set_style_border_width(ui_SWifiButtonStandby, 2, LV_PART_MAIN | LV_STATE_DEFAULT); 111 | 112 | ui_ScreenWifiButtonLabelStandby = lv_label_create(ui_SWifiButtonStandby); 113 | lv_obj_set_width(ui_ScreenWifiButtonLabelStandby, LV_SIZE_CONTENT); /// 1 114 | lv_obj_set_height(ui_ScreenWifiButtonLabelStandby, LV_SIZE_CONTENT); /// 1 115 | lv_obj_set_align(ui_ScreenWifiButtonLabelStandby, LV_ALIGN_CENTER); 116 | lv_label_set_text(ui_ScreenWifiButtonLabelStandby, "Standby"); 117 | lv_obj_set_style_text_font(ui_ScreenWifiButtonLabelStandby, &lv_font_montserrat_36, LV_PART_MAIN | LV_STATE_DEFAULT); 118 | 119 | // lv_obj_add_event_cb(ui_ScreenWifi_Slider1, ui_event_ScreenWifi_Slider1, LV_EVENT_ALL, NULL); 120 | lv_obj_add_event_cb(ui_SWifiButtonStandby, ui_event_SWifiButtonStandby, LV_EVENT_ALL, NULL); 121 | 122 | ui_ScreenChart_Chart1 = lv_chart_create(ui_S1Main); 123 | lv_obj_set_width(ui_ScreenChart_Chart1, lv_pct(85)); 124 | lv_obj_set_height(ui_ScreenChart_Chart1, lv_pct(50)); 125 | lv_obj_set_align(ui_ScreenChart_Chart1, LV_ALIGN_CENTER); 126 | 127 | lv_obj_set_style_line_color(ui_ScreenChart_Chart1, lv_color_hex(0x4040FF), LV_PART_ITEMS | LV_STATE_DEFAULT); 128 | lv_obj_set_style_line_opa(ui_ScreenChart_Chart1, 255, LV_PART_ITEMS | LV_STATE_DEFAULT); 129 | lv_obj_set_style_line_color(ui_ScreenChart_Chart1, lv_color_hex(0x4040FF), LV_PART_ITEMS | LV_STATE_DEFAULT); 130 | lv_obj_set_style_line_opa(ui_ScreenChart_Chart1, 255, LV_PART_ITEMS | LV_STATE_DEFAULT); 131 | lv_obj_set_style_line_width(ui_ScreenChart_Chart1, 5, LV_PART_ITEMS | LV_STATE_DEFAULT); 132 | lv_obj_set_style_line_width(ui_ScreenChart_Chart1, 5, LV_PART_ITEMS | LV_STATE_DEFAULT); 133 | } 134 | 135 | static lv_chart_series_t * ser_v; 136 | 137 | void ui_init(void) 138 | { 139 | lv_disp_t * dispp = lv_disp_get_default(); 140 | lv_theme_t * theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), 141 | true, LV_FONT_DEFAULT); 142 | lv_disp_set_theme(dispp, theme); 143 | ui_S1Main_screen_init(); 144 | lv_disp_load_scr(ui_S1Main); 145 | 146 | lv_obj_t* chart = ui_ScreenChart_Chart1; 147 | lv_chart_set_point_count(chart, 120); // Size 120 data points (1 per 30sec) 148 | lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_SHIFT); 149 | lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 400, 460); 150 | ser_v = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y); 151 | } 152 | 153 | 154 | void chart_add_voltage(const float v) { 155 | lv_obj_t* chart = ui_ScreenChart_Chart1; 156 | lv_chart_set_next_value(chart, ser_v, (int16_t) (v * 100)); 157 | lv_chart_refresh(chart); 158 | } 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /examples/ui_example/ui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #if defined __has_include 8 | #if __has_include("lvgl.h") 9 | #include "lvgl.h" 10 | #elif __has_include("lvgl/lvgl.h") 11 | #include "lvgl/lvgl.h" 12 | #else 13 | #include "lvgl.h" 14 | #endif 15 | #else 16 | #include "lvgl.h" 17 | #endif 18 | 19 | extern lv_obj_t * ui_S1Main; 20 | extern lv_obj_t * ui_SWifiLabelIPAddr; 21 | extern lv_obj_t * ui_S1LabelClock; 22 | 23 | //void ui_event_ScreenWifi_Slider1(lv_event_t * e); 24 | //extern lv_obj_t * ui_ScreenWifi_Slider1; 25 | //extern lv_obj_t * ui_ScreenWifi_Label8; 26 | void ui_event_SWifiButtonStandby(lv_event_t * e); 27 | extern lv_obj_t * ui_SWifiButtonStandby; 28 | extern lv_obj_t * ui_ScreenWifiButtonLabelStandby; 29 | void ui_event_ScreenChart(lv_event_t * e); 30 | extern lv_obj_t * ui_ScreenChart_Chart1; 31 | 32 | void ui_ev_bright(lv_event_t * e); 33 | void ui_ev_standby(lv_event_t * e); 34 | 35 | void chart_init(); 36 | void chart_add_voltage(const float v); 37 | 38 | void ui_init(void); 39 | 40 | #ifdef __cplusplus 41 | } /*extern "C"*/ 42 | #endif 43 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TRGBArduinoSupport", 3 | "version": "0.0.4", 4 | "description": "T-RGB device support", 5 | "keywords": "T-RGB, FT3267, XL9535, LilyGO", 6 | "repository": 7 | { 8 | "type": "git", 9 | "url": "https://github.com/fablabnbg/TRGBArduinoSupport" 10 | }, 11 | "authors": 12 | [ 13 | { 14 | "name": "Ian Hubbertz", 15 | "email": "ian@fabmail.org" 16 | }, 17 | { 18 | "name": "FabLab Region Nürnberg e. V.", 19 | "email": "info@fablab-nuernberg.de", 20 | "homepage": "https://fablab-nuernberg.de" 21 | } 22 | ], 23 | "license": "MIT", 24 | "dependencies": { 25 | "lvgl": "^8.3.0", 26 | "TouchLib": "https://github.com/mmMicky/TouchLib.git" 27 | }, 28 | "frameworks": "arduino", 29 | "platforms": "espressif32" 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/TRGBSuppport.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TRGBSuppport.cpp 3 | * 4 | * Created on: 29.12.2022 5 | * Author: ian 6 | * 7 | * Code is copied from official examples (https://github.com/Xinyuan-LilyGO/T-RGB/tree/main/example/factory). 8 | * No logic changes, but restructured for easier use. 9 | * 10 | * License: MIT 11 | */ 12 | 13 | #include 14 | 15 | #include "img.h" //unsern Logo 16 | 17 | // WiFi include needed for deep sleep support. 18 | #include "WiFi.h" 19 | 20 | TRGBSuppport trgb; 21 | 22 | static bool touch_pin_get_int=false; 23 | 24 | static RTC_DATA_ATTR uint16_t bootCount = 0; 25 | uint16_t TRGBSuppport::getBootCount() { return bootCount; } 26 | 27 | 28 | static void lv_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) { 29 | if (touch_pin_get_int) { 30 | uint8_t touch_points_num; 31 | uint16_t x, y; 32 | TouchLib& touch = trgb.getTouch(); 33 | touch.read(); 34 | if (touch.getPointNum() > 0) { 35 | TP_Point t = touch.getPoint(0); 36 | data->point.x = t.x; 37 | data->point.y = t.y; 38 | data->state = LV_INDEV_STATE_PRESSED; 39 | } else { 40 | data->state = LV_INDEV_STATE_RELEASED; 41 | } 42 | touch_pin_get_int = false; 43 | } else { 44 | data->state = LV_INDEV_STATE_RELEASED; 45 | } 46 | } 47 | 48 | static void lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) { 49 | esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)drv->user_data; 50 | int offsetx1 = area->x1; 51 | int offsetx2 = area->x2; 52 | int offsety1 = area->y1; 53 | int offsety2 = area->y2; 54 | esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map); 55 | lv_disp_flush_ready(drv); 56 | } 57 | 58 | 59 | TRGBSuppport::TRGBSuppport(): 60 | touch(Wire, IIC_SDA_PIN, IIC_SCL_PIN) 61 | { 62 | bootCount++; 63 | } 64 | 65 | esp_lcd_panel_handle_t TRGBSuppport::register_tft() { 66 | esp_lcd_panel_handle_t panel_handle = NULL; 67 | esp_lcd_rgb_panel_config_t panel_config = { .clk_src = LCD_CLK_SRC_PLL160M, 68 | .timings = { .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ, .h_res = 69 | EXAMPLE_LCD_H_RES, 70 | .v_res = EXAMPLE_LCD_V_RES, // The following parameters should refer to LCD spec 71 | .hsync_pulse_width = 1, .hsync_back_porch = 30, 72 | .hsync_front_porch = 50, .vsync_pulse_width = 1, 73 | .vsync_back_porch = 30, .vsync_front_porch = 20, .flags = { 74 | .pclk_active_neg = 1 } }, 75 | .data_width = 16, // RGB565 in parallel mode, thus 16bit in width 76 | .psram_trans_align = 64, .hsync_gpio_num = EXAMPLE_PIN_NUM_HSYNC, 77 | .vsync_gpio_num = EXAMPLE_PIN_NUM_VSYNC, .de_gpio_num = 78 | EXAMPLE_PIN_NUM_DE, .pclk_gpio_num = EXAMPLE_PIN_NUM_PCLK, 79 | .data_gpio_nums = { // EXAMPLE_PIN_NUM_DATA0, 80 | EXAMPLE_PIN_NUM_DATA13, EXAMPLE_PIN_NUM_DATA14, 81 | EXAMPLE_PIN_NUM_DATA15, EXAMPLE_PIN_NUM_DATA16, 82 | EXAMPLE_PIN_NUM_DATA17, EXAMPLE_PIN_NUM_DATA6, 83 | EXAMPLE_PIN_NUM_DATA7, EXAMPLE_PIN_NUM_DATA8, 84 | EXAMPLE_PIN_NUM_DATA9, EXAMPLE_PIN_NUM_DATA10, 85 | EXAMPLE_PIN_NUM_DATA11, // EXAMPLE_PIN_NUM_DATA12, 86 | EXAMPLE_PIN_NUM_DATA1, EXAMPLE_PIN_NUM_DATA2, 87 | EXAMPLE_PIN_NUM_DATA3, EXAMPLE_PIN_NUM_DATA4, 88 | EXAMPLE_PIN_NUM_DATA5 }, .disp_gpio_num = 89 | EXAMPLE_PIN_NUM_DISP_EN, .on_frame_trans_done = NULL, 90 | .user_ctx = NULL, .flags = { .fb_in_psram = 1 } }; 91 | // allocate frame buffer in PSRAM 92 | ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle)); 93 | ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); 94 | ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); 95 | return panel_handle; 96 | } 97 | 98 | void TRGBSuppport::init() { 99 | Serial.begin(115200); 100 | Serial.setTxTimeoutMs(1); // workaround to minimize blocking time for output to HWCDCSerial (Serial), if no host is connected. 101 | Serial.print("Init T-RGB device. Bootcount:"); 102 | Serial.println(getBootCount()); 103 | Wire.begin(IIC_SDA_PIN, IIC_SCL_PIN, (uint32_t) 400000); 104 | xl.begin(); 105 | uint8_t pin = (1 << PWR_EN_PIN) | (1 << LCD_CS_PIN) | (1 << TP_RES_PIN) 106 | | (1 << LCD_SDA_PIN) | (1 << LCD_CLK_PIN) | (1 << LCD_RST_PIN) 107 | | (1 << SD_CS_PIN); 108 | 109 | xl.pinMode8(0, pin, OUTPUT); 110 | xl.digitalWrite(PWR_EN_PIN, 1); 111 | 112 | // Enable CS for SD card 113 | xl.digitalWrite(SD_CS_PIN, 1); // To use SDIO one-line mode, you need to pull the CS pin high 114 | 115 | tft_init(); 116 | esp_lcd_panel_handle_t panel_handle = register_tft(); 117 | 118 | // Draw a start logo (before init of LVGL) 119 | esp_lcd_panel_draw_bitmap(panel_handle, 0, 0, 480, 480, logo_img); 120 | 121 | // Initialize touch 122 | pinMode(TP_INT_PIN, INPUT_PULLUP); 123 | attachInterrupt(TP_INT_PIN, [] { touch_pin_get_int = true; }, CHANGE); 124 | touch.init(); 125 | 126 | 127 | pinMode(BAT_VOLT_PIN, ANALOG); 128 | 129 | 130 | lv_init(); 131 | // alloc draw buffers used by LVGL from PSRAM 132 | lv_color_t *buf1 = (lv_color_t*) heap_caps_malloc( 133 | EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES * sizeof(lv_color_t), MALLOC_CAP_SPIRAM); 134 | assert(buf1); 135 | lv_color_t *buf2 = (lv_color_t*) heap_caps_malloc( 136 | EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES * sizeof(lv_color_t), MALLOC_CAP_SPIRAM); 137 | assert(buf2); 138 | lv_disp_draw_buf_init(&disp_buf, buf1, buf2, EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES); 139 | 140 | Serial.println("Register display driver to LVGL"); 141 | lv_disp_drv_init(&disp_drv); 142 | disp_drv.hor_res = EXAMPLE_LCD_H_RES; 143 | disp_drv.ver_res = EXAMPLE_LCD_V_RES; 144 | disp_drv.flush_cb = lvgl_flush_cb; 145 | disp_drv.draw_buf = &disp_buf; 146 | disp_drv.user_data = panel_handle; 147 | lv_disp_t *disp = lv_disp_drv_register(&disp_drv); 148 | 149 | lv_indev_drv_init(&indev_drv); 150 | indev_drv.type = LV_INDEV_TYPE_POINTER; 151 | indev_drv.read_cb = lv_touchpad_read; 152 | lv_indev_drv_register(&indev_drv); 153 | } 154 | 155 | 156 | void TRGBSuppport::deepSleep(void) { 157 | WiFi.disconnect(); 158 | detachInterrupt(TP_INT_PIN); 159 | xl.pinMode8(0, 0xff, INPUT); 160 | xl.pinMode8(1, 0xff, INPUT); 161 | xl.read_all_reg(); 162 | // If the SD card is initialized, it needs to be unmounted. 163 | if (SD_MMC.cardSize()) SD_MMC.end(); 164 | 165 | digitalWrite(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL); 166 | 167 | Serial.println("Enter deep sleep"); 168 | delay(2000); 169 | 170 | esp_sleep_enable_ext0_wakeup((gpio_num_t)TP_INT_PIN, 0); // Wakeup by touch 171 | pinMode(GPIO_NUM_0, INPUT_PULLUP); 172 | //esp_sleep_enable_ext0_wakeup((gpio_num_t) GPIO_NUM_0, 0); // Wakeup by boot-pin (TODO: not really useful for now, because display is not initialized correctly) 173 | esp_deep_sleep_start(); 174 | } 175 | 176 | void TRGBSuppport::restart(void) { 177 | WiFi.disconnect(); 178 | if (SD_MMC.cardSize()) SD_MMC.end(); 179 | Serial.println("Restart"); 180 | delay(500); 181 | esp_restart(); 182 | } 183 | 184 | void TRGBSuppport::lcd_send_data(uint8_t data) { 185 | uint8_t n; 186 | for (n = 0; n < 8; n++) { 187 | if (data & 0x80) 188 | xl.digitalWrite(LCD_SDA_PIN, 1); 189 | else 190 | xl.digitalWrite(LCD_SDA_PIN, 0); 191 | 192 | data <<= 1; 193 | xl.digitalWrite(LCD_CLK_PIN, 0); 194 | xl.digitalWrite(LCD_CLK_PIN, 1); 195 | } 196 | } 197 | 198 | void TRGBSuppport::lcd_cmd(const uint8_t cmd) { 199 | xl.digitalWrite(LCD_CS_PIN, 0); 200 | xl.digitalWrite(LCD_SDA_PIN, 0); 201 | xl.digitalWrite(LCD_CLK_PIN, 0); 202 | xl.digitalWrite(LCD_CLK_PIN, 1); 203 | lcd_send_data(cmd); 204 | xl.digitalWrite(LCD_CS_PIN, 1); 205 | } 206 | 207 | void TRGBSuppport::lcd_data(const uint8_t *data, int len) { 208 | uint32_t i = 0; 209 | if (len == 0) 210 | return; // no need to send anything 211 | do { 212 | xl.digitalWrite(LCD_CS_PIN, 0); 213 | xl.digitalWrite(LCD_SDA_PIN, 1); 214 | xl.digitalWrite(LCD_CLK_PIN, 0); 215 | xl.digitalWrite(LCD_CLK_PIN, 1); 216 | lcd_send_data(*(data + i)); 217 | xl.digitalWrite(LCD_CS_PIN, 1); 218 | i++; 219 | } while (len--); 220 | } 221 | 222 | void TRGBSuppport::tft_init(void) { 223 | xl.digitalWrite(LCD_CS_PIN, 1); 224 | xl.digitalWrite(LCD_SDA_PIN, 1); 225 | xl.digitalWrite(LCD_CLK_PIN, 1); 226 | 227 | // Reset the display and touch 228 | 229 | // xl.digitalWrite(LCD_RST_PIN, 1); 230 | // vTaskDelay(200 / portTICK_PERIOD_MS); 231 | xl.digitalWrite(LCD_RST_PIN, 0); 232 | xl.digitalWrite(TP_RES_PIN, 0); 233 | vTaskDelay(100 / portTICK_PERIOD_MS); 234 | xl.digitalWrite(LCD_RST_PIN, 1); 235 | xl.digitalWrite(TP_RES_PIN, 1); 236 | vTaskDelay(100 / portTICK_PERIOD_MS); 237 | 238 | // Switch on backlight 239 | pinMode(EXAMPLE_PIN_NUM_BK_LIGHT, OUTPUT); 240 | digitalWrite(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL); 241 | 242 | int cmd = 0; 243 | while (st_init_cmds[cmd].databytes != 0xff) { 244 | lcd_cmd(st_init_cmds[cmd].cmd); 245 | lcd_data(st_init_cmds[cmd].data, st_init_cmds[cmd].databytes & 0x1F); 246 | if (st_init_cmds[cmd].databytes & 0x80) { 247 | vTaskDelay(50 / portTICK_PERIOD_MS); 248 | } 249 | cmd++; 250 | } 251 | Serial.println("Register setup complete"); 252 | // Switch on backlight 253 | pinMode(EXAMPLE_PIN_NUM_BK_LIGHT, OUTPUT); 254 | digitalWrite(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL); 255 | 256 | } 257 | 258 | 259 | void TRGBSuppport::SD_init(void) { 260 | SD_MMC.setPins(SD_CLK_PIN, SD_CMD_PIN, SD_D0_PIN); 261 | if (!SD_MMC.begin("/sdcard", true, true, BOARD_MAX_SDMMC_FREQ, 10)) { // max 10 open files (need more than the default 5 due to logging, replay, webserver etc.) 262 | Serial.println("Card Mount Failed"); 263 | return; 264 | } 265 | 266 | uint8_t cardType = SD_MMC.cardType(); 267 | if (cardType == CARD_NONE) { 268 | Serial.println("No SD card attached"); 269 | return; 270 | } 271 | 272 | Serial.print("SD Card Type: "); 273 | 274 | if (cardType == CARD_MMC) 275 | Serial.println("MMC"); 276 | else if (cardType == CARD_SD) 277 | Serial.println("SDSC"); 278 | else if (cardType == CARD_SDHC) 279 | Serial.println("SDHC"); 280 | else 281 | Serial.println("UNKNOWN"); 282 | 283 | uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024); 284 | Serial.printf("SD Card Size: %lluMB\n", cardSize); 285 | } 286 | 287 | 288 | void TRGBSuppport::scan_iic(void) { 289 | byte error, address; 290 | int nDevices = 0; 291 | Serial.println("Scanning for I2C devices ..."); 292 | for (address = 0x01; address < 0x7f; address++) { 293 | Wire.beginTransmission(address); 294 | error = Wire.endTransmission(); 295 | if (error == 0) { 296 | Serial.printf("I2C device found at address 0x%02X\n", address); 297 | nDevices++; 298 | } else if (error != 2) { 299 | Serial.printf("Error %d at address 0x%02X\n", error, address); 300 | } 301 | } 302 | if (nDevices == 0) { 303 | Serial.println("No I2C devices found"); 304 | } 305 | } 306 | 307 | void TRGBSuppport::print_chip_info(void) { 308 | Serial.print("Chip: "); 309 | Serial.println(ESP.getChipModel()); 310 | Serial.print("ChipRevision: "); 311 | Serial.println(ESP.getChipRevision()); 312 | Serial.print("Psram size: "); 313 | Serial.print(ESP.getPsramSize() / 1024); 314 | Serial.println("KB"); 315 | Serial.print("Flash size: "); 316 | Serial.print(ESP.getFlashChipSize() / 1024); 317 | Serial.println("KB"); 318 | Serial.print("CPU frequency: "); 319 | Serial.print(ESP.getCpuFreqMHz()); 320 | Serial.println("MHz"); 321 | } 322 | -------------------------------------------------------------------------------- /src/TRGBSuppport.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TRGBSuppport.h 3 | * 4 | * Created on: 29.12.2022 5 | * Author: ian 6 | * 7 | * Code is copied from official examples (https://github.com/Xinyuan-LilyGO/T-RGB/tree/main/example/factory). 8 | * No logic changes, but restructured for easier use. 9 | * 10 | * License: MIT 11 | * 12 | */ 13 | 14 | #pragma once 15 | 16 | #include "XL9535_driver.h" // I/O extionsion via I2C 17 | 18 | #if defined TRGB_OVAL 19 | #define TOUCH_MODULES_FT3267 20 | #elif defined TRGB_ROUND 21 | #define TOUCH_MODULES_CST_SELF 22 | #elif defined TRGB_ROUND_LARGE 23 | #define TOUCH_MODULES_GT911 24 | #endif 25 | 26 | 27 | //#define TOUCH_MODULES_GT911 28 | //#define TOUCH_MODULES_CST_SELF 29 | //#define TOUCH_MODULES_CST_MUTUAL 30 | //#define TOUCH_MODULES_ZTW622 31 | //#define TOUCH_MODULES_L58 32 | //#define TOUCH_MODULES_FT3267 33 | //#define TOUCH_MODULES_FT5x06 34 | 35 | #include "TouchLib.h" 36 | 37 | #include "lvgl.h" // LVGL library 38 | #include "pin_config.h" 39 | #include 40 | 41 | #include "esp_lcd_panel_io.h" 42 | #include "esp_lcd_panel_ops.h" 43 | #include "esp_lcd_panel_rgb.h" 44 | #include "esp_lcd_panel_vendor.h" 45 | 46 | #include 47 | 48 | typedef struct { 49 | uint8_t cmd; 50 | uint8_t data[16]; 51 | uint8_t databytes; // No of data in data; bit 7 = delay after set; 0xFF = end of cmds. 52 | } lcd_init_cmd_t; 53 | 54 | DRAM_ATTR static const lcd_init_cmd_t st_init_cmds[] = { 55 | {0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}, 0x05}, 56 | {0xC0, {0x3b, 0x00}, 0x02}, 57 | {0xC1, {0x0b, 0x02}, 0x02}, 58 | {0xC2, {0x07, 0x02}, 0x02}, 59 | {0xCC, {0x10}, 0x01}, 60 | {0xCD, {0x08}, 0x01}, // 用565时屏蔽 666打开 61 | {0xb0, {0x00, 0x11, 0x16, 0x0e, 0x11, 0x06, 0x05, 0x09, 0x08, 0x21, 0x06, 0x13, 0x10, 0x29, 0x31, 0x18}, 0x10}, 62 | {0xb1, {0x00, 0x11, 0x16, 0x0e, 0x11, 0x07, 0x05, 0x09, 0x09, 0x21, 0x05, 0x13, 0x11, 0x2a, 0x31, 0x18}, 0x10}, 63 | {0xFF, {0x77, 0x01, 0x00, 0x00, 0x11}, 0x05}, 64 | {0xb0, {0x6d}, 0x01}, 65 | {0xb1, {0x37}, 0x01}, 66 | {0xb2, {0x81}, 0x01}, 67 | {0xb3, {0x80}, 0x01}, 68 | {0xb5, {0x43}, 0x01}, 69 | {0xb7, {0x85}, 0x01}, 70 | {0xb8, {0x20}, 0x01}, 71 | {0xc1, {0x78}, 0x01}, 72 | {0xc2, {0x78}, 0x01}, 73 | {0xc3, {0x8c}, 0x01}, 74 | {0xd0, {0x88}, 0x01}, 75 | {0xe0, {0x00, 0x00, 0x02}, 0x03}, 76 | {0xe1, {0x03, 0xa0, 0x00, 0x00, 0x04, 0xa0, 0x00, 0x00, 0x00, 0x20, 0x20}, 0x0b}, 77 | {0xe2, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0x0d}, 78 | {0xe3, {0x00, 0x00, 0x11, 0x00}, 0x04}, 79 | {0xe4, {0x22, 0x00}, 0x02}, 80 | {0xe5, {0x05, 0xec, 0xa0, 0xa0, 0x07, 0xee, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0x10}, 81 | {0xe6, {0x00, 0x00, 0x11, 0x00}, 0x04}, 82 | {0xe7, {0x22, 0x00}, 0x02}, 83 | {0xe8, {0x06, 0xed, 0xa0, 0xa0, 0x08, 0xef, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0x10}, 84 | {0xeb, {0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00}, 0x07}, 85 | {0xed, {0xff, 0xff, 0xff, 0xba, 0x0a, 0xbf, 0x45, 0xff, 0xff, 0x54, 0xfb, 0xa0, 0xab, 0xff, 0xff, 0xff}, 0x10}, 86 | {0xef, {0x10, 0x0d, 0x04, 0x08, 0x3f, 0x1f}, 0x06}, 87 | {0xFF, {0x77, 0x01, 0x00, 0x00, 0x13}, 0x05}, 88 | {0xef, {0x08}, 0x01}, 89 | {0xFF, {0x77, 0x01, 0x00, 0x00, 0x00}, 0x05}, 90 | {0x36, {0x08}, 0x01}, 91 | {0x3a, {0x66}, 0x01}, 92 | {0x11, {0x00}, 0x80}, 93 | // {0xFF, {0x77, 0x01, 0x00, 0x00, 0x12}, 0x05}, 94 | // {0xd1, {0x81}, 0x01}, 95 | // {0xd2, {0x06}, 0x01}, 96 | {0x29, {0x00}, 0x80}, 97 | {0, {0}, 0xff}}; 98 | 99 | 100 | 101 | class TRGBSuppport { 102 | 103 | private: 104 | XL9535 xl; // I/O Extender 105 | TouchLib touch; 106 | 107 | lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s) 108 | lv_disp_drv_t disp_drv; // contains callback functions 109 | lv_indev_drv_t indev_drv; 110 | void tft_init(void); 111 | void lcd_cmd(const uint8_t cmd); 112 | void lcd_data(const uint8_t *data, int len); 113 | void lcd_send_data(uint8_t data); 114 | static esp_lcd_panel_handle_t register_tft(); 115 | 116 | public: 117 | TRGBSuppport(); 118 | TouchLib& getTouch(){return touch;}; 119 | void deepSleep(); 120 | void restart(); 121 | void init(); 122 | void SD_init(); //could be static, but I guess it is too confusing. 123 | 124 | float getBatVoltage() const {return (analogRead(BAT_VOLT_PIN) * 2 * 3.3) / 4096;} 125 | bool isBatCharging() const {return getBatVoltage() > 4.1;} // LiIon end-of-charge voltage ~ 4.2V, so charger voltage is approx this voltage. 126 | uint16_t getBootCount(); 127 | 128 | // **** functions from official example that give some useful information **** 129 | static void print_chip_info(); // ESP32 hardware details 130 | 131 | // Scan I2C (Groove connector) for devices. 132 | // 0x20: I/O extension (XL9535) 133 | // 0x38: Touchpad-controller (FT3267) 134 | static void scan_iic(); 135 | 136 | }; 137 | 138 | extern TRGBSuppport trgb; 139 | 140 | -------------------------------------------------------------------------------- /src/XL9535_driver.cpp: -------------------------------------------------------------------------------- 1 | #include "XL9535_driver.h" 2 | #include "Wire.h" 3 | 4 | void XL9535::writeRegister(uint8_t reg, uint8_t *data, uint8_t len) { 5 | _wire->beginTransmission(_address); 6 | _wire->write(reg); 7 | for (uint8_t i = 0; i < len; i++) { 8 | _wire->write(data[i]); 9 | } 10 | _wire->endTransmission(); 11 | } 12 | uint8_t XL9535::readRegister(uint8_t reg, uint8_t *data, uint8_t len) { 13 | _wire->beginTransmission(_address); 14 | _wire->write(reg); 15 | _wire->endTransmission(); 16 | _wire->requestFrom(_address, len); 17 | uint8_t index = 0; 18 | while (index < len) 19 | data[index++] = _wire->read(); 20 | return 0; 21 | } 22 | 23 | void XL9535::begin(bool A0, bool A1, bool A2, TwoWire *wire) { 24 | _address = XL9535_IIC_ADDRESS | (A2 << 3) | (A1 << 2) | (A0 << 1); 25 | _wire = wire; 26 | is_found = true; 27 | _wire->beginTransmission(_address); 28 | if (!_wire->endTransmission()) { 29 | Serial.println("Found xl9535"); 30 | } else { 31 | Serial.println("xl9535 not found"); 32 | is_found = false; 33 | } 34 | } 35 | void XL9535::pinMode(uint8_t pin, uint8_t mode) { 36 | if (is_found) { 37 | uint8_t port = 0; 38 | if (pin > 7) { 39 | readRegister(XL9535_CONFIG_PORT_1_REG, &port, 1); 40 | if (mode == OUTPUT) { 41 | port = port & (~(1 << (pin - 10))); 42 | } else { 43 | port = port | (1 << (pin - 10)); 44 | } 45 | writeRegister(XL9535_CONFIG_PORT_1_REG, &port, 1); 46 | 47 | } else { 48 | readRegister(XL9535_CONFIG_PORT_0_REG, &port, 1); 49 | if (mode == OUTPUT) { 50 | port = port & (~(1 << pin)); 51 | } else { 52 | port = port | (1 << pin); 53 | } 54 | writeRegister(XL9535_CONFIG_PORT_0_REG, &port, 1); 55 | } 56 | } else { 57 | Serial.println("xl9535 not found"); 58 | } 59 | } 60 | void XL9535::pinMode8(uint8_t port, uint8_t pin, uint8_t mode) { 61 | if (is_found) { 62 | uint8_t _pin = (mode != OUTPUT) ? pin : ~pin; 63 | if (port) { 64 | writeRegister(XL9535_CONFIG_PORT_1_REG, &_pin, 1); 65 | } else { 66 | writeRegister(XL9535_CONFIG_PORT_0_REG, &_pin, 1); 67 | } 68 | } else { 69 | Serial.println("xl9535 not found"); 70 | } 71 | } 72 | 73 | void XL9535::digitalWrite(uint8_t pin, uint8_t val) { 74 | if (is_found) { 75 | uint8_t port = 0; 76 | uint8_t reg_data = 0; 77 | if (pin > 7) { 78 | readRegister(XL9535_OUTPUT_PORT_1_REG, ®_data, 1); 79 | reg_data = reg_data & (~(1 << (pin - 10))); 80 | port = reg_data | val << (pin - 10); 81 | writeRegister(XL9535_OUTPUT_PORT_1_REG, &port, 1); 82 | } else { 83 | readRegister(XL9535_OUTPUT_PORT_0_REG, ®_data, 1); 84 | reg_data = reg_data & (~(1 << pin)); 85 | port = reg_data | val << pin; 86 | writeRegister(XL9535_OUTPUT_PORT_0_REG, &port, 1); 87 | } 88 | } else { 89 | Serial.println("xl9535 not found"); 90 | } 91 | } 92 | 93 | int XL9535::digitalRead(uint8_t pin) { 94 | if (is_found) { 95 | int state = 0; 96 | uint8_t port = 0; 97 | if (pin > 7) { 98 | readRegister(XL9535_INPUT_PORT_1_REG, &port, 1); 99 | state = port & (pin - 10) ? 1 : 0; 100 | } else { 101 | readRegister(XL9535_INPUT_PORT_0_REG, &port, 1); 102 | state = port & pin ? 1 : 0; 103 | } 104 | return state; 105 | } else { 106 | Serial.println("xl9535 not found"); 107 | } 108 | return 0; 109 | } 110 | 111 | void XL9535::read_all_reg() { 112 | uint8_t data; 113 | for (uint8_t i = 0; i < 8; i++) { 114 | readRegister(i, &data, 1); 115 | Serial.printf("0x%02x : 0x%02X \r\n", i, data); 116 | } 117 | } -------------------------------------------------------------------------------- /src/XL9535_driver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Arduino.h" 4 | #include "Wire.h" 5 | 6 | #define XL9535_IIC_ADDRESS 0X20 7 | 8 | #define XL9535_INPUT_PORT_0_REG 0X00 9 | #define XL9535_INPUT_PORT_1_REG 0X01 10 | #define XL9535_OUTPUT_PORT_0_REG 0X02 11 | #define XL9535_OUTPUT_PORT_1_REG 0X03 12 | #define XL9535_INVERSION_PORT_0_REG 0X04 13 | #define XL9535_INVERSION_PORT_1_REG 0X05 14 | #define XL9535_CONFIG_PORT_0_REG 0X06 15 | #define XL9535_CONFIG_PORT_1_REG 0X07 16 | 17 | class XL9535 { 18 | public: 19 | XL9535(){}; 20 | ~XL9535(){}; 21 | 22 | void begin(bool A0 = 0, bool A1 = 0, bool A2 = 0, TwoWire *wire = &Wire); 23 | void pinMode(uint8_t pin, uint8_t mode); 24 | void pinMode8(uint8_t port, uint8_t pin, uint8_t mode); 25 | 26 | void digitalWrite(uint8_t pin, uint8_t val); 27 | int digitalRead(uint8_t pin); 28 | void read_all_reg(); 29 | 30 | protected: 31 | void writeRegister(uint8_t reg, uint8_t *data, uint8_t len); 32 | uint8_t readRegister(uint8_t reg, uint8_t *data, uint8_t len); 33 | 34 | uint8_t _address; 35 | TwoWire *_wire; 36 | bool is_found; 37 | }; -------------------------------------------------------------------------------- /src/pin_config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define EXAMPLE_LCD_PIXEL_CLOCK_HZ (8 * 1000 * 1000) 4 | #define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 1 5 | #define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 6 | #define EXAMPLE_PIN_NUM_BK_LIGHT 46 7 | #define EXAMPLE_PIN_NUM_HSYNC 47 8 | #define EXAMPLE_PIN_NUM_VSYNC 41 9 | #define EXAMPLE_PIN_NUM_DE 45 10 | #define EXAMPLE_PIN_NUM_PCLK 42 11 | // #define EXAMPLE_PIN_NUM_DATA0 44 12 | #define EXAMPLE_PIN_NUM_DATA1 21 13 | #define EXAMPLE_PIN_NUM_DATA2 18 14 | #define EXAMPLE_PIN_NUM_DATA3 17 15 | #define EXAMPLE_PIN_NUM_DATA4 16 16 | #define EXAMPLE_PIN_NUM_DATA5 15 17 | #define EXAMPLE_PIN_NUM_DATA6 14 18 | #define EXAMPLE_PIN_NUM_DATA7 13 19 | #define EXAMPLE_PIN_NUM_DATA8 12 20 | #define EXAMPLE_PIN_NUM_DATA9 11 21 | #define EXAMPLE_PIN_NUM_DATA10 10 22 | #define EXAMPLE_PIN_NUM_DATA11 9 23 | // #define EXAMPLE_PIN_NUM_DATA12 43 24 | #define EXAMPLE_PIN_NUM_DATA13 7 25 | #define EXAMPLE_PIN_NUM_DATA14 6 26 | #define EXAMPLE_PIN_NUM_DATA15 5 27 | #define EXAMPLE_PIN_NUM_DATA16 3 28 | #define EXAMPLE_PIN_NUM_DATA17 2 29 | #define EXAMPLE_PIN_NUM_DISP_EN -1 30 | 31 | // The pixel number in horizontal and vertical 32 | #define EXAMPLE_LCD_H_RES 480 33 | #define EXAMPLE_LCD_V_RES 480 34 | 35 | #define IIC_SCL_PIN 48 36 | #define IIC_SDA_PIN 8 37 | 38 | #define SD_CLK_PIN 39 39 | #define SD_CMD_PIN 40 40 | #define SD_D0_PIN 38 41 | 42 | #define BAT_VOLT_PIN 4 43 | #define TP_INT_PIN 1 44 | 45 | #define BOOT_BTN_PIN 0 46 | 47 | /* XL9535 --- PIN - P0*/ 48 | #define TP_RES_PIN 1 49 | #define PWR_EN_PIN 2 50 | #define LCD_CS_PIN 3 51 | #define LCD_SDA_PIN 4 52 | #define LCD_CLK_PIN 5 53 | #define LCD_RST_PIN 6 54 | #define SD_CS_PIN 7 55 | --------------------------------------------------------------------------------