Merge branch 'master' into feature/add_st7796s
This commit is contained in:
commit
fbdc247c25
52
CONTRIBUTE_CONTROLLER_SUPPORT.md
Normal file
52
CONTRIBUTE_CONTROLLER_SUPPORT.md
Normal file
|
@ -0,0 +1,52 @@
|
|||
# Is your driver not listed on the supported drivers list?
|
||||
|
||||
Consider contributing to this demo project by adding support to your driver.
|
||||
|
||||
## Display driver.
|
||||
|
||||
To enable LVGL to work with your display you would need to implement from one up to three callback functions (one function for RGB TFT displays, three functions for monochrome display controllers), you can add more functions to enable backlight control, etc.
|
||||
|
||||
All display controller code is stored on the `components/lvgl_esp32_drivers/lvgl_tft` directory, see `disp_driver` and `CMakeLists.txt` to add your code into the idf project.
|
||||
|
||||
Create a header and source file named after the display controller (in lowercase). On the header file declare the necessary functions, such as:
|
||||
|
||||
```c
|
||||
/* Configure your display */
|
||||
void x_init(void);
|
||||
|
||||
/* LVGL callbacks */
|
||||
void x_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map);
|
||||
/* Only for monochrome displays */
|
||||
void x_rounder(lv_disp_drv_t *disp_drv, lv_area_t *area);
|
||||
void x_set_px(lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa);
|
||||
```
|
||||
|
||||
Where x is the controller name.
|
||||
|
||||
For more information on the function callbacks check LVGL documentation: (Display driver)[https://docs.lvgl.io/v7/en/html/porting/display.html#display-driver].
|
||||
|
||||
Add your display functions on `disp_driver_init`, `disp_driver_flush`, `disp_driver_rounder` and `disp_driver_set_px` on the `disp_driver.c` file.
|
||||
|
||||
## Input device driver.
|
||||
|
||||
To enable LVGL to work with your touch controller you would need to implement an initialization function and one function to get the data out from your touch controller.
|
||||
|
||||
All touch controller code is stored on the `components/lvgl_esp32_drivers/lvgl_touch` directory.
|
||||
|
||||
Create a header and source file named after the display controller (in lowercase). On the header file declare the necessary functions, such as:
|
||||
|
||||
```c
|
||||
/* Configure your display */
|
||||
void x_init(void);
|
||||
|
||||
/* LVGL callbacks */
|
||||
bool x_read(lv_disp_drv_t *drv, lv_indev_data_t *data);
|
||||
```
|
||||
|
||||
Where x is the controller name.
|
||||
|
||||
For more information on the function callbacks check LVGL documentation: (Display driver)[https://docs.lvgl.io/v7/en/html/porting/indev.html].
|
||||
|
||||
## Kconfig and Project Configuration
|
||||
|
||||
The ESP32 SDK (ESP-IDF) uses [kconfiglib](https://github.com/ulfalizer/Kconfiglib) which is a Python-based extension to the [Kconfig](https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt) system which provides a compile-time project configuration mechanism. Using `idf.py menuconfig` will update the file sdkconfig and, during build, provide the file sdkconfig.h.
|
66
README.md
66
README.md
|
@ -1 +1,65 @@
|
|||
# lvgl esp32 drivers
|
||||
# Display and touchpad drivers for ESP32 using LVGL
|
||||
|
||||
For a ready to use ESP32 project take look at the [lv_port_esp32](https://github.com/lvgl/lv_port_esp32) repository.
|
||||
|
||||
#### Table of content
|
||||
- [Supported display controllers](#supported-display-controllers)
|
||||
- [Supported indev controllers](#supported-indev-controllers)
|
||||
- [Support for predefined development kits](#support-for-predefined-development-kits)
|
||||
|
||||
**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).
|
||||
|
||||
|
||||
## Supported display controllers
|
||||
|
||||
|
||||
| Display Controller | Type | Interface | Color depth (LV_COLOR_DEPTH) | Swap RGB565 color (LV_COLOR_16_SWAP) |
|
||||
|---------------------------------------------|------------|------------------------|------------------------------|----------------------------------------|
|
||||
| ILI9341 | TFT | SPI | 16: RGB565 | Yes |
|
||||
| ILI9486 | TFT | SPI | 16: RGB565 | Yes |
|
||||
| ILI9488 | TFT | SPI | 16: RGB565 | No |
|
||||
| HX8357B/HX8357D | TFT | SPI | 16: RGB565 | Yes |
|
||||
| ST7789 | TFT | SPI | 16: RGB565 | Yes |
|
||||
| ST7735S | TFT | SPI | 16: RGB565 | Yes |
|
||||
| FT81x | TFT | Single, Dual, Quad SPI | 16: RGB565 | No |
|
||||
| GC9A01 | TFT | SPI | 16: RGB565 | Yes |
|
||||
| RA8875 | TFT | SPI | 16: RGB565 | Yes |
|
||||
| SH1107 | Monochrome | SPI | 1: 1byte per pixel | No |
|
||||
| SSD1306 | Monochrome | I2C | 1: 1byte per pixel | No |
|
||||
| IL3820 | e-Paper | SPI | 1: 1byte per pixel | No |
|
||||
| UC8151D/ GoodDisplay GDEW0154M10 DES | e-Paper | SPI | 1: 1byte per pixel | No |
|
||||
| FitiPower JD79653A/ GoodDisplay GDEW0154M09 | e-Paper | SPI | 1: 1byte per pixel | No |
|
||||
|
||||
## Supported indev controllers
|
||||
|
||||
- XPT2046
|
||||
- FT3236
|
||||
- other FT6X36 or the FT6206 controllers should work as well (not tested)
|
||||
- STMPE610
|
||||
- FT81x (Single, Dual, and Quad SPI)
|
||||
|
||||
If your display or input device (touch) controller is not supported consider contributing to this repo by
|
||||
adding support to it! [Contribute controller support](CONTRIBUTE_CONTROLLER_SUPPORT.md)
|
||||
|
||||
## Support for predefined development kits
|
||||
|
||||
You can also use the predefined kits, which selects the correct display controllers on the kit,
|
||||
and sets the gpio numbers for the interface.
|
||||
|
||||
| Kit name | Display controller | Interface | Hor. Res. | Ver. Res. |
|
||||
|---------------------------|-----------------------|-----------|-----------|-----------|
|
||||
| ESP Wrover Kit v4.1 | ILI9341 | SPI | 240 | 320 |
|
||||
| M5Stack | ILI9341 | SPI | 240 | 320 |
|
||||
| M5Stick | SH1107 | SPI | - | - |
|
||||
| M5StickC | ST7735S | SPI | 80 | 160 |
|
||||
| Adafruit 3.5 Featherwing | HX8357 | SPI | 480 | 320 |
|
||||
| RPi MPI3501 | ILI9486 | SPI | - | - |
|
||||
| Wemos Lolin OLED | SSD1306 | SPI | 64 | 128 |
|
||||
| ER-TFT035-6 | ILI9488 | SPI | 480 | 320 |
|
||||
| AIRcable ATAGv3 | IL3820 | SPI | 128 | 296 |
|
||||
| TTGO T-Display | ST7789 | SPI | 135 | 240 |
|
||||
| TTGO Camera Plus | ST7789 | SPI | 240 | 240 |
|
||||
|
||||
**NOTE:** See [Supported display controllers](#supported-display-controllers) for more information on display configuration.
|
||||
**NOTE:** See [Supported indev controllers](#supported-indev-controllers) for more information about indev configuration.
|
||||
|
|
|
@ -30,7 +30,7 @@ extern "C" {
|
|||
#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 (CONFIG_LV_DISPLAY_WIDTH*CONFIG_LV_DISPLAY_HEIGHT)
|
||||
#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
|
||||
|
@ -40,20 +40,20 @@ extern "C" {
|
|||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341
|
||||
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 64)
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306
|
||||
#define DISP_BUF_SIZE (CONFIG_LV_DISPLAY_WIDTH*CONFIG_LV_DISPLAY_HEIGHT)
|
||||
#define DISP_BUF_SIZE (LV_HOR_RES_MAX*LV_VER_RES_MAX)
|
||||
#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 (CONFIG_LV_DISPLAY_HEIGHT * IL3820_COLUMNS)
|
||||
#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 ((CONFIG_LV_DISPLAY_HEIGHT * CONFIG_LV_DISPLAY_WIDTH) / 8) // 5KB
|
||||
#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 ((CONFIG_LV_DISPLAY_HEIGHT * CONFIG_LV_DISPLAY_WIDTH) / 8) // 2888 bytes
|
||||
#define DISP_BUF_SIZE ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8) // 2888 bytes
|
||||
#else
|
||||
#error "No display controller selected"
|
||||
#endif
|
||||
|
|
116
lvgl_tft/Kconfig
116
lvgl_tft/Kconfig
|
@ -183,6 +183,27 @@ menu "LVGL TFT Display controller"
|
|||
help
|
||||
Display controller protocol I2C
|
||||
|
||||
# Used in display init function to send display orientation commands
|
||||
choice DISPLAY_ORIENTATION
|
||||
prompt "Display orientation"
|
||||
default DISPLAY_ORIENTATION_PORTRAIT
|
||||
config DISPLAY_ORIENTATION_PORTRAIT
|
||||
bool "Portrait"
|
||||
config DISPLAY_ORIENTATION_PORTRAIT_INVERTED
|
||||
bool "Portrait inverted"
|
||||
config DISPLAY_ORIENTATION_LANDSCAPE
|
||||
bool "Landscape"
|
||||
config DISPLAY_ORIENTATION_LANDSCAPE_INVERTED
|
||||
bool "Landscape inverted"
|
||||
endchoice
|
||||
|
||||
config LV_DISPLAY_ORIENTATION
|
||||
int
|
||||
default 0 if DISPLAY_ORIENTATION_PORTRAIT
|
||||
default 1 if DISPLAY_ORIENTATION_PORTRAIT_INVERTED
|
||||
default 2 if DISPLAY_ORIENTATION_LANDSCAPE
|
||||
default 3 if DISPLAY_ORIENTATION_LANDSCAPE_INVERTED
|
||||
|
||||
config LV_TFT_DISPLAY_OFFSETS
|
||||
bool
|
||||
help
|
||||
|
@ -468,101 +489,6 @@ menu "LVGL TFT Display controller"
|
|||
bool "I2C PORT 1"
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Display orientation"
|
||||
depends on LV_TFT_DISPLAY_CONTROLLER_ILI9341 || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_ILI9481 || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_ILI9486 || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_ILI9488 || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_SH1107 || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_SSD1306 || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_FT81X || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_ST7789 || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_GC9A01 || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_ST7735S || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_IL3820 || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_RA8875 || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_JD79653A || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_UC8151D || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_ST7796S
|
||||
default LV_DISPLAY_ORIENTATION_LANDSCAPE \
|
||||
if !LV_TFT_DISPLAY_CONTROLLER_JD79653A || \
|
||||
!LV_TFT_DISPLAY_CONTROLLER_UC8151D
|
||||
default LV_DISPLAY_ORIENTATION_PORTRAIT if LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D
|
||||
help
|
||||
Display orientation.
|
||||
|
||||
config LV_DISPLAY_ORIENTATION_PORTRAIT
|
||||
bool "Portrait"
|
||||
config LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED
|
||||
bool "Inverted Portrait"
|
||||
depends on !LV_TFT_DISPLAY_CONTROLLER_IL3820
|
||||
config LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
bool "Landscape"
|
||||
depends on !LV_TFT_DISPLAY_CONTROLLER_JD79653A
|
||||
depends on !LV_TFT_DISPLAY_CONTROLLER_UC8151D
|
||||
config LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED
|
||||
bool "Inverted Landscape"
|
||||
depends on !LV_TFT_DISPLAY_CONTROLLER_IL3820
|
||||
depends on !LV_TFT_DISPLAY_CONTROLLER_JD79653A
|
||||
depends on !LV_TFT_DISPLAY_CONTROLLER_UC8151D
|
||||
endchoice
|
||||
|
||||
|
||||
# Display orientation
|
||||
# This symbol is meant to be used as parameter on the display_set_orientation
|
||||
# function at init.
|
||||
config LV_DISPLAY_ORIENTATION
|
||||
int
|
||||
default 0 if LV_DISPLAY_ORIENTATION_PORTRAIT
|
||||
default 1 if LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED
|
||||
default 2 if LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
default 3 if LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED
|
||||
|
||||
config LV_DISPLAY_WIDTH
|
||||
int "TFT display width in pixels." if LV_PREDEFINED_DISPLAY_NONE || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_FT81X
|
||||
default 240 if ( LV_PREDEFINED_DISPLAY_M5STACK || LV_PREDEFINED_DISPLAY_WROVER4 ) && (LV_DISPLAY_ORIENTATION_PORTRAIT)
|
||||
default 240 if ( LV_PREDEFINED_DISPLAY_M5STACK || LV_PREDEFINED_DISPLAY_WROVER4 ) && (LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
|
||||
default 320 if ( LV_PREDEFINED_DISPLAY_M5STACK || LV_PREDEFINED_DISPLAY_WROVER4 ) && (LV_DISPLAY_ORIENTATION_LANDSCAPE)
|
||||
default 320 if ( LV_PREDEFINED_DISPLAY_M5STACK || LV_PREDEFINED_DISPLAY_WROVER4 ) && (LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
|
||||
default 480 if LV_PREDEFINED_DISPLAY_WT32_SC01 && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
|
||||
default 320 if LV_PREDEFINED_DISPLAY_WT32_SC01 && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
|
||||
default 480 if LV_PREDEFINED_DISPLAY_ERTFT0356 || LV_PREDEFINED_DISPLAY_ADA_FEATHERWING
|
||||
default 64 if ( LV_PREDEFINED_DISPLAY_WEMOS_LOLIN || LV_PREDEFINED_DISPLAY_M5STICK ) && LV_DISPLAY_ORIENTATION_PORTRAIT
|
||||
default 128 if ( LV_PREDEFINED_DISPLAY_WEMOS_LOLIN || LV_PREDEFINED_DISPLAY_M5STICK ) && LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
default 800 if LV_TFT_DISPLAY_CONTROLLER_FT81X
|
||||
default 128 if LV_PREDEFINED_DISPLAY_ATAG && LV_DISPLAY_ORIENTATION_PORTRAIT
|
||||
default 296 if LV_PREDEFINED_DISPLAY_ATAG && LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
default 80 if LV_PREDEFINED_DISPLAY_M5STICKC && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
|
||||
default 160 if LV_PREDEFINED_DISPLAY_M5STICKC && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
|
||||
default 135 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
|
||||
default 240 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
|
||||
default 240 if LV_PREDEFINED_DISPLAY_TTGO_CAMERA_PLUS
|
||||
default 320
|
||||
|
||||
config LV_DISPLAY_HEIGHT
|
||||
int "TFT display height in pixels." if LV_PREDEFINED_DISPLAY_NONE || \
|
||||
LV_TFT_DISPLAY_CONTROLLER_FT81X
|
||||
default 320 if ( LV_PREDEFINED_DISPLAY_M5STACK || LV_PREDEFINED_DISPLAY_WROVER4 ) && (LV_DISPLAY_ORIENTATION_PORTRAIT)
|
||||
default 320 if ( LV_PREDEFINED_DISPLAY_M5STACK || LV_PREDEFINED_DISPLAY_WROVER4 ) && (LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
|
||||
default 240 if ( LV_PREDEFINED_DISPLAY_M5STACK || LV_PREDEFINED_DISPLAY_WROVER4 ) && (LV_DISPLAY_ORIENTATION_LANDSCAPE)
|
||||
default 240 if ( LV_PREDEFINED_DISPLAY_M5STACK || LV_PREDEFINED_DISPLAY_WROVER4 ) && (LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
|
||||
default 480 if LV_PREDEFINED_DISPLAY_WT32_SC01 && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
|
||||
default 320 if LV_PREDEFINED_DISPLAY_WT32_SC01 && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
|
||||
default 320 if LV_PREDEFINED_DISPLAY_ERTFT0356 || LV_PREDEFINED_DISPLAY_ADA_FEATHERWING
|
||||
default 128 if ( LV_PREDEFINED_DISPLAY_WEMOS_LOLIN || LV_PREDEFINED_DISPLAY_M5STICK ) && LV_DISPLAY_ORIENTATION_PORTRAIT
|
||||
default 64 if ( LV_PREDEFINED_DISPLAY_WEMOS_LOLIN || LV_PREDEFINED_DISPLAY_M5STICK ) && LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
default 480 if LV_TFT_DISPLAY_CONTROLLER_FT81X
|
||||
default 296 if LV_PREDEFINED_DISPLAY_ATAG && LV_DISPLAY_ORIENTATION_PORTRAIT
|
||||
default 128 if LV_PREDEFINED_DISPLAY_ATAG && LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
default 160 if LV_PREDEFINED_DISPLAY_M5STICKC && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
|
||||
default 80 if LV_PREDEFINED_DISPLAY_M5STICKC && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
|
||||
default 240 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
|
||||
default 135 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
|
||||
default 240 if LV_PREDEFINED_DISPLAY_TTGO_CAMERA_PLUS
|
||||
default 240
|
||||
|
||||
config LV_TFT_USE_CUSTOM_SPI_CLK_DIVIDER
|
||||
bool "Use custom SPI clock frequency." if LV_TFT_DISPLAY_PROTOCOL_SPI
|
||||
default n
|
||||
|
|
|
@ -49,7 +49,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
|
|||
#define BIT_CLEAR(a,b) ((a) &= ~(1U<<(b)))
|
||||
|
||||
/* Number of pixels? */
|
||||
#define IL3820_PIXEL (CONFIG_LV_DISPLAY_WIDTH * CONFIG_LV_DISPLAY_HEIGHT)
|
||||
#define IL3820_PIXEL (LV_HOR_RES_MAX * LV_VER_RES_MAX)
|
||||
|
||||
#define EPD_PANEL_NUMOF_COLUMS EPD_PANEL_WIDTH
|
||||
#define EPD_PANEL_NUMOF_ROWS_PER_PAGE 8
|
||||
|
|
|
@ -20,8 +20,8 @@ extern "C"
|
|||
|
||||
/* Values for Waveshare 2.9inch e-Paper Module, this values shouldn't be
|
||||
* swapped to change display orientation */
|
||||
#define EPD_PANEL_WIDTH CONFIG_LV_DISPLAY_WIDTH /* 128 */
|
||||
#define EPD_PANEL_HEIGHT CONFIG_LV_DISPLAY_HEIGHT /* 296 */
|
||||
#define EPD_PANEL_WIDTH LV_HOR_RES_MAX /* 128 */
|
||||
#define EPD_PANEL_HEIGHT LV_VER_RES_MAX /* 296 */
|
||||
|
||||
/* 128 = panel width */
|
||||
#define IL3820_COLUMNS (EPD_PANEL_WIDTH / 8)
|
||||
|
|
|
@ -43,8 +43,8 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
|
|||
#define PIN_BUSY CONFIG_LV_DISP_PIN_BUSY
|
||||
#define PIN_BUSY_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_BUSY)))
|
||||
#define EVT_BUSY (1UL << 0UL)
|
||||
#define EPD_WIDTH CONFIG_LV_DISPLAY_WIDTH
|
||||
#define EPD_HEIGHT CONFIG_LV_DISPLAY_HEIGHT
|
||||
#define EPD_WIDTH LV_HOR_RES_MAX
|
||||
#define EPD_HEIGHT LV_VER_RES_MAX
|
||||
#define EPD_ROW_LEN (EPD_HEIGHT / 8u)
|
||||
#define EPD_PARTIAL_CNT 5;
|
||||
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
#endif
|
||||
#define BYTES_PER_PIXEL (LV_COLOR_DEPTH / 8)
|
||||
|
||||
#define HDWR_VAL (CONFIG_LV_DISPLAY_WIDTH/8 - 1)
|
||||
#define VDHR_VAL (CONFIG_LV_DISPLAY_HEIGHT - 1)
|
||||
#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)
|
||||
|
@ -248,7 +248,7 @@ void ra8875_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * colo
|
|||
#if DEBUG
|
||||
ESP_LOGI(TAG, "flush: set window (x1,x2): %d,%d -> %d,%d", x1, x2, area->x1, area->x2);
|
||||
#endif
|
||||
ra8875_set_window(area->x1, area->x2, 0, CONFIG_LV_DISPLAY_HEIGHT-1);
|
||||
ra8875_set_window(area->x1, area->x2, 0, LV_VER_RES_MAX-1);
|
||||
x1 = area->x1;
|
||||
x2 = area->x2;
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ void ra8875_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * colo
|
|||
|
||||
// Update to future cursor location
|
||||
y = area->y2 + 1;
|
||||
if (y >= CONFIG_LV_DISPLAY_HEIGHT) {
|
||||
if (y >= LV_VER_RES_MAX) {
|
||||
y = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,10 +124,10 @@ void sh1107_set_px_cb(struct _disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t b
|
|||
uint8_t bit_index = 0;
|
||||
|
||||
#if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
byte_index = y + (( x>>3 ) * CONFIG_LV_DISPLAY_HEIGHT);
|
||||
byte_index = y + (( x>>3 ) * LV_VER_RES_MAX);
|
||||
bit_index = x & 0x7;
|
||||
#elif defined CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT
|
||||
byte_index = x + (( y>>3 ) * CONFIG_LV_DISPLAY_WIDTH);
|
||||
byte_index = x + (( y>>3 ) * LV_HOR_RES_MAX);
|
||||
bit_index = y & 0x7;
|
||||
#endif
|
||||
|
||||
|
@ -159,9 +159,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
|
||||
size = area->y2 - area->y1 + 1;
|
||||
#if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
ptr = color_map + i * CONFIG_LV_DISPLAY_HEIGHT;
|
||||
ptr = color_map + i * LV_VER_RES_MAX;
|
||||
#else
|
||||
ptr = color_map + i * CONFIG_LV_DISPLAY_WIDTH;
|
||||
ptr = color_map + i * LV_HOR_RES_MAX;
|
||||
#endif
|
||||
if(i != row2){
|
||||
sh1107_send_data( (void *) ptr, size);
|
||||
|
@ -177,8 +177,8 @@ void sh1107_rounder(struct _disp_drv_t * disp_drv, lv_area_t *area)
|
|||
// workaround: always send complete size display buffer
|
||||
area->x1 = 0;
|
||||
area->y1 = 0;
|
||||
area->x2 = CONFIG_LV_DISPLAY_WIDTH-1;
|
||||
area->y2 = CONFIG_LV_DISPLAY_HEIGHT-1;
|
||||
area->x2 = LV_HOR_RES_MAX-1;
|
||||
area->y2 = LV_VER_RES_MAX-1;
|
||||
}
|
||||
|
||||
void sh1107_sleep_in()
|
||||
|
|
|
@ -130,7 +130,7 @@ void ssd1306_init()
|
|||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
||||
void ssd1306_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 ssd1306_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t color, lv_opa_t opa) {
|
||||
uint16_t byte_index = x + (( y>>3 ) * buf_w);
|
||||
uint8_t bit_index = y & 0x7;
|
||||
|
@ -147,13 +147,9 @@ void ssd1306_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t
|
|||
uint8_t row1 = 0, row2 = 0;
|
||||
i2c_cmd_handle_t cmd;
|
||||
|
||||
#if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
row1 = area->y1>>3;
|
||||
row2 = area->y2>>3;
|
||||
#else
|
||||
row1 = area->y1>>3;
|
||||
row2 = area->y2>>3;
|
||||
#endif
|
||||
// Divide by 8
|
||||
row1 = area->y1 >> 3;
|
||||
row2 = area->y2 >> 3;
|
||||
|
||||
cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
|
@ -185,16 +181,19 @@ void ssd1306_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t
|
|||
lv_disp_flush_ready(disp_drv);
|
||||
}
|
||||
|
||||
void ssd1306_rounder(struct _disp_drv_t * disp_drv, lv_area_t *area)
|
||||
// workaround: always send complete size display buffer, no partial update
|
||||
void ssd1306_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area)
|
||||
{
|
||||
// area->y1 = (area->y1 & (~0x7));
|
||||
// area->y2 = (area->y2 & (~0x7)) + 7;
|
||||
|
||||
// workaround: always send complete size display buffer
|
||||
uint8_t hor_max = disp_drv->hor_res;
|
||||
uint8_t ver_max = disp_drv->ver_res;
|
||||
|
||||
area->x1 = 0;
|
||||
area->y1 = 0;
|
||||
area->x2 = CONFIG_LV_DISPLAY_WIDTH-1;
|
||||
area->y2 = CONFIG_LV_DISPLAY_HEIGHT-1;
|
||||
area->x2 = hor_max - 1;
|
||||
area->y2 = ver_max - 1;
|
||||
}
|
||||
|
||||
void ssd1306_sleep_in()
|
||||
|
|
|
@ -38,8 +38,8 @@ extern "C" {
|
|||
**********************/
|
||||
void ssd1306_init(void);
|
||||
void ssd1306_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
|
||||
void ssd1306_rounder(struct _disp_drv_t * disp_drv, lv_area_t *area);
|
||||
void ssd1306_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 ssd1306_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area);
|
||||
void ssd1306_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t color, lv_opa_t opa);
|
||||
|
||||
void ssd1306_sleep_in(void);
|
||||
|
|
|
@ -23,7 +23,6 @@ extern "C" {
|
|||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
// #define DISP_BUF_SIZE (CONFIG_LV_DISPLAY_WIDTH*CONFIG_LV_DISPLAY_HEIGHT)
|
||||
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
|
||||
|
||||
#define ST7735S_DC CONFIG_LV_DISP_PIN_DC
|
||||
|
|
|
@ -44,8 +44,8 @@
|
|||
#define PIN_BUSY CONFIG_LV_DISP_PIN_BUSY
|
||||
#define PIN_BUSY_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_BUSY)))
|
||||
#define EVT_BUSY (1UL << 0UL)
|
||||
#define EPD_WIDTH CONFIG_LV_DISPLAY_WIDTH
|
||||
#define EPD_HEIGHT CONFIG_LV_DISPLAY_HEIGHT
|
||||
#define EPD_WIDTH LV_HOR_RES_MAX
|
||||
#define EPD_HEIGHT LV_VER_RES_MAX
|
||||
#define EPD_ROW_LEN (EPD_HEIGHT / 8u)
|
||||
|
||||
#define BIT_SET(a, b) ((a) |= (1U << (b)))
|
||||
|
|
|
@ -99,7 +99,6 @@ menu "LVGL Touch controller"
|
|||
range 0 39
|
||||
default 35 if LV_PREDEFINED_PINS_38V1
|
||||
default 19
|
||||
|
||||
help
|
||||
Configure the touchpanel MISO pin here.
|
||||
|
||||
|
@ -109,7 +108,6 @@ menu "LVGL Touch controller"
|
|||
range 0 39
|
||||
default 32 if LV_PREDEFINED_PINS_38V1
|
||||
default 23
|
||||
|
||||
help
|
||||
Configure the touchpanel MOSI pin here.
|
||||
|
||||
|
@ -135,7 +133,7 @@ menu "LVGL Touch controller"
|
|||
default 27 if LV_PREDEFINED_PINS_38V4
|
||||
default 25
|
||||
help
|
||||
Configure the touchpanel CS pin here.
|
||||
Configure the touchpanel IRQ pin here.
|
||||
endmenu
|
||||
|
||||
menu "Touchpanel Configuration (XPT2046)"
|
||||
|
@ -180,6 +178,19 @@ menu "LVGL Touch controller"
|
|||
prompt "Invert Y coordinate value."
|
||||
default y
|
||||
|
||||
choice
|
||||
prompt "Select touch detection method."
|
||||
default LV_TOUCH_DETECT_IRQ
|
||||
help
|
||||
Select the controller for your touch panel.
|
||||
|
||||
config LV_TOUCH_DETECT_IRQ
|
||||
bool "IRQ pin only"
|
||||
config LV_TOUCH_DETECT_IRQ_PRESSURE
|
||||
bool "IRQ pin and pressure"
|
||||
config LV_TOUCH_DETECT_PRESSURE
|
||||
bool "Pressure only"
|
||||
endchoice
|
||||
endmenu
|
||||
|
||||
menu "Touchpanel (FT6X06) Pin Assignments"
|
||||
|
|
|
@ -38,16 +38,16 @@ extern "C" {
|
|||
|
||||
/*GetMaxX Macro*/
|
||||
#if CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
#define GetMaxX() (CONFIG_LV_DISPLAY_WIDTH - 1)
|
||||
#define GetMaxX() (LV_HOR_RES_MAX - 1)
|
||||
#else
|
||||
#define GetMaxX() (CONFIG_LV_DISPLAY_HEIGHT - 1)
|
||||
#define GetMaxX() (LV_VER_RES_MAX - 1)
|
||||
#endif
|
||||
|
||||
/*GetMaxY Macro*/
|
||||
#if CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
#define GetMaxY() (CONFIG_LV_DISPLAY_HEIGHT - 1)
|
||||
#define GetMaxY() (LV_VER_RES_MAX - 1)
|
||||
#else
|
||||
#define GetMaxY() (CONFIG_LV_DISPLAY_WIDTH - 1)
|
||||
#define GetMaxY() (LV_HOR_RES_MAX - 1)
|
||||
#endif
|
||||
|
||||
#ifndef CONCAT3
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#endif
|
||||
#include "ft6x36.h"
|
||||
#include "tp_i2c.h"
|
||||
#include "../lvgl_i2c_conf.h"
|
||||
|
||||
#define TAG "FT6X36"
|
||||
|
||||
|
@ -46,7 +47,7 @@ esp_err_t ft6x06_i2c_read8(uint8_t slave_addr, uint8_t register_addr, uint8_t *d
|
|||
|
||||
i2c_master_read_byte(i2c_cmd, data_buf, I2C_MASTER_NACK);
|
||||
i2c_master_stop(i2c_cmd);
|
||||
esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, i2c_cmd, 1000 / portTICK_RATE_MS);
|
||||
esp_err_t ret = i2c_master_cmd_begin(TOUCH_I2C_PORT, i2c_cmd, 1000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(i2c_cmd);
|
||||
return ret;
|
||||
}
|
||||
|
@ -145,7 +146,7 @@ bool ft6x36_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
|
|||
i2c_master_read_byte(i2c_cmd, &data_xy[0], I2C_MASTER_ACK); // reads FT6X36_P1_XH_REG
|
||||
i2c_master_read_byte(i2c_cmd, &data_xy[1], I2C_MASTER_NACK); // reads FT6X36_P1_XL_REG
|
||||
i2c_master_stop(i2c_cmd);
|
||||
esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, i2c_cmd, 1000 / portTICK_RATE_MS);
|
||||
esp_err_t ret = i2c_master_cmd_begin(TOUCH_I2C_PORT, i2c_cmd, 1000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(i2c_cmd);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error getting X coordinates: %s", esp_err_to_name(ret));
|
||||
|
@ -168,7 +169,7 @@ bool ft6x36_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
|
|||
i2c_master_read_byte(i2c_cmd, &data_xy[2], I2C_MASTER_ACK); // reads FT6X36_P1_YH_REG
|
||||
i2c_master_read_byte(i2c_cmd, &data_xy[3], I2C_MASTER_NACK); // reads FT6X36_P1_YL_REG
|
||||
i2c_master_stop(i2c_cmd);
|
||||
ret = i2c_master_cmd_begin(I2C_NUM_0, i2c_cmd, 1000 / portTICK_RATE_MS);
|
||||
ret = i2c_master_cmd_begin(TOUCH_I2C_PORT, i2c_cmd, 1000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(i2c_cmd);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error getting Y coordinates: %s", esp_err_to_name(ret));
|
||||
|
|
|
@ -18,18 +18,26 @@
|
|||
*********************/
|
||||
#define TAG "XPT2046"
|
||||
|
||||
#define CMD_X_READ 0b10010000
|
||||
#define CMD_Y_READ 0b11010000
|
||||
#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_Z1_READ 0b10110000
|
||||
#define CMD_Z2_READ 0b11000000
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef enum {
|
||||
TOUCH_NOT_DETECTED = 0,
|
||||
TOUCH_DETECTED = 1,
|
||||
} xpt2046_touch_detect_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void xpt2046_corr(int16_t * x, int16_t * y);
|
||||
static void xpt2046_avg(int16_t * x, int16_t * y);
|
||||
static int16_t xpt2046_cmd(uint8_t cmd);
|
||||
static xpt2046_touch_detect_t xpt2048_is_touch_detected();
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
|
@ -51,6 +59,9 @@ uint8_t avg_last;
|
|||
*/
|
||||
void xpt2046_init(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "XPT2046 Initialization");
|
||||
|
||||
#if XPT2046_TOUCH_IRQ || XPT2046_TOUCH_IRQ_PRESS
|
||||
gpio_config_t irq_config = {
|
||||
.pin_bit_mask = BIT64(XPT2046_IRQ),
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
|
@ -59,10 +70,9 @@ void xpt2046_init(void)
|
|||
.intr_type = GPIO_INTR_DISABLE,
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "XPT2046 Initialization");
|
||||
|
||||
esp_err_t ret = gpio_config(&irq_config);
|
||||
assert(ret == ESP_OK);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,21 +84,16 @@ bool xpt2046_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
|
|||
{
|
||||
static int16_t last_x = 0;
|
||||
static int16_t last_y = 0;
|
||||
bool valid = true;
|
||||
bool valid = false;
|
||||
|
||||
int16_t x = 0;
|
||||
int16_t y = 0;
|
||||
int16_t x = last_x;
|
||||
int16_t y = last_y;
|
||||
if (xpt2048_is_touch_detected() == TOUCH_DETECTED)
|
||||
{
|
||||
valid = true;
|
||||
|
||||
uint8_t irq = gpio_get_level(XPT2046_IRQ);
|
||||
|
||||
if (irq == 0) {
|
||||
uint8_t data[2];
|
||||
|
||||
tp_spi_read_reg(CMD_X_READ, data, 2);
|
||||
x = (data[0] << 8) | data[1];
|
||||
|
||||
tp_spi_read_reg(CMD_Y_READ, data, 2);
|
||||
y = (data[0] << 8) | data[1];
|
||||
x = xpt2046_cmd(CMD_X_READ);
|
||||
y = xpt2046_cmd(CMD_Y_READ);
|
||||
ESP_LOGI(TAG, "P(%d,%d)", x, y);
|
||||
|
||||
/*Normalize Data back to 12-bits*/
|
||||
|
@ -102,11 +107,10 @@ bool xpt2046_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
|
|||
last_y = y;
|
||||
|
||||
ESP_LOGI(TAG, "x = %d, y = %d", x, y);
|
||||
} else {
|
||||
x = last_x;
|
||||
y = last_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
avg_last = 0;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
data->point.x = x;
|
||||
|
@ -119,6 +123,42 @@ bool xpt2046_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
|
|||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
static xpt2046_touch_detect_t xpt2048_is_touch_detected()
|
||||
{
|
||||
// check IRQ pin if we IRQ or IRQ and preessure
|
||||
#if XPT2046_TOUCH_IRQ || XPT2046_TOUCH_IRQ_PRESS
|
||||
uint8_t irq = gpio_get_level(XPT2046_IRQ);
|
||||
|
||||
if (irq != 0) {
|
||||
return TOUCH_NOT_DETECTED;
|
||||
}
|
||||
#endif
|
||||
// check pressure if we are pressure or IRQ and pressure
|
||||
#if XPT2046_TOUCH_PRESS || XPT2046_TOUCH_IRQ_PRESS
|
||||
int16_t z1 = xpt2046_cmd(CMD_Z1_READ) >> 3;
|
||||
int16_t z2 = xpt2046_cmd(CMD_Z2_READ) >> 3;
|
||||
|
||||
// this is not what the confusing datasheet says but it seems to
|
||||
// be enough to detect real touches on the panel
|
||||
int16_t z = z1 + 4096 - z2;
|
||||
|
||||
if (z < XPT2046_TOUCH_THRESHOLD)
|
||||
{
|
||||
return TOUCH_NOT_DETECTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
return TOUCH_DETECTED;
|
||||
}
|
||||
|
||||
static int16_t xpt2046_cmd(uint8_t cmd)
|
||||
{
|
||||
uint8_t data[2];
|
||||
tp_spi_read_reg(cmd, data, 2);
|
||||
int16_t val = (data[0] << 8) | data[1];
|
||||
return val;
|
||||
}
|
||||
|
||||
static void xpt2046_corr(int16_t * x, int16_t * y)
|
||||
{
|
||||
#if XPT2046_XY_SWAP != 0
|
||||
|
|
|
@ -35,6 +35,10 @@ extern "C" {
|
|||
#define XPT2046_X_INV CONFIG_LV_TOUCH_INVERT_X
|
||||
#define XPT2046_Y_INV CONFIG_LV_TOUCH_INVERT_Y
|
||||
#define XPT2046_XY_SWAP CONFIG_LV_TOUCH_XY_SWAP
|
||||
#define XPT2046_TOUCH_THRESHOLD 400 // Threshold for touch detection
|
||||
#define XPT2046_TOUCH_IRQ CONFIG_LV_TOUCH_DETECT_IRQ
|
||||
#define XPT2046_TOUCH_IRQ_PRESS CONFIG_LV_TOUCH_DETECT_IRQ_PRESSURE
|
||||
#define XPT2046_TOUCH_PRESS CONFIG_LV_TOUCH_DETECT_PRESSURE
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
|
|
Loading…
Reference in a new issue