Move drivers from the lv_port_esp32 to here
This commit is contained in:
parent
5a32d98f83
commit
08384030b0
9
CMakeLists.txt
Normal file
9
CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
if(ESP_PLATFORM)
|
||||
|
||||
file(GLOB SOURCES *.c)
|
||||
|
||||
idf_component_register(SRCS ${SOURCES}
|
||||
INCLUDE_DIRS .
|
||||
REQUIRES lvgl)
|
||||
|
||||
endif()
|
4
component.mk
Normal file
4
component.mk
Normal file
|
@ -0,0 +1,4 @@
|
|||
# LVGL esp32 drivers
|
||||
|
||||
COMPONENT_SRCDIRS := .
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
236
lvgl_helpers.c
Normal file
236
lvgl_helpers.c
Normal file
|
@ -0,0 +1,236 @@
|
|||
/**
|
||||
* @file lvgl_helpers.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "sdkconfig.h"
|
||||
#include "lvgl_helpers.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "lvgl_tft/disp_spi.h"
|
||||
#include "lvgl_touch/tp_spi.h"
|
||||
|
||||
#include "lvgl_spi_conf.h"
|
||||
#include "lvgl_i2c_conf.h"
|
||||
|
||||
#include "driver/i2c.h"
|
||||
|
||||
#include "lvgl/src/lv_core/lv_refr.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define TAG "lvgl_helpers"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/* Interface and driver initialization */
|
||||
void lvgl_driver_init(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Display hor size: %d, ver size: %d", LV_HOR_RES_MAX, LV_VER_RES_MAX);
|
||||
ESP_LOGI(TAG, "Display buffer size: %d", DISP_BUF_SIZE);
|
||||
|
||||
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
|
||||
ESP_LOGI(TAG, "Initializing SPI master for FT81X");
|
||||
|
||||
lvgl_spi_driver_init(TFT_SPI_HOST,
|
||||
DISP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK,
|
||||
SPI_BUS_MAX_TRANSFER_SZ, 1,
|
||||
DISP_SPI_IO2, DISP_SPI_IO3);
|
||||
|
||||
disp_spi_add_device(TFT_SPI_HOST);
|
||||
disp_driver_init();
|
||||
|
||||
#if defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
|
||||
touch_driver_init();
|
||||
#endif
|
||||
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if defined (SHARED_SPI_BUS)
|
||||
ESP_LOGI(TAG, "Initializing shared SPI master");
|
||||
|
||||
lvgl_spi_driver_init(TFT_SPI_HOST,
|
||||
TP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK,
|
||||
SPI_BUS_MAX_TRANSFER_SZ, 1,
|
||||
-1, -1);
|
||||
|
||||
disp_spi_add_device(TFT_SPI_HOST);
|
||||
tp_spi_add_device(TOUCH_SPI_HOST);
|
||||
|
||||
disp_driver_init();
|
||||
touch_driver_init();
|
||||
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if defined (SHARED_I2C_BUS)
|
||||
ESP_LOGI(TAG, "Initializing shared I2C master");
|
||||
|
||||
lvgl_i2c_driver_init(DISP_I2C_PORT,
|
||||
DISP_I2C_SDA, DISP_I2C_SCL,
|
||||
DISP_I2C_SPEED_HZ);
|
||||
|
||||
disp_driver_init();
|
||||
touch_driver_init();
|
||||
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Display controller initialization */
|
||||
#if defined CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI
|
||||
ESP_LOGI(TAG, "Initializing SPI master for display");
|
||||
|
||||
lvgl_spi_driver_init(TFT_SPI_HOST,
|
||||
DISP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK,
|
||||
SPI_BUS_MAX_TRANSFER_SZ, 1,
|
||||
DISP_SPI_IO2, DISP_SPI_IO3);
|
||||
|
||||
disp_spi_add_device(TFT_SPI_HOST);
|
||||
|
||||
disp_driver_init();
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_PROTOCOL_I2C)
|
||||
ESP_LOGI(TAG, "Initializing I2C master for display");
|
||||
/* Init the i2c master on the display driver code */
|
||||
lvgl_i2c_driver_init(DISP_I2C_PORT,
|
||||
DISP_I2C_SDA, DISP_I2C_SCL,
|
||||
DISP_I2C_SPEED_HZ);
|
||||
|
||||
disp_driver_init();
|
||||
#else
|
||||
#error "No protocol defined for display controller"
|
||||
#endif
|
||||
|
||||
/* Touch controller initialization */
|
||||
#if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONE
|
||||
#if defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI)
|
||||
ESP_LOGI(TAG, "Initializing SPI master for touch");
|
||||
|
||||
lvgl_spi_driver_init(TOUCH_SPI_HOST,
|
||||
TP_SPI_MISO, TP_SPI_MOSI, TP_SPI_CLK,
|
||||
0 /* Defaults to 4094 */, 2,
|
||||
-1, -1);
|
||||
|
||||
tp_spi_add_device(TOUCH_SPI_HOST);
|
||||
|
||||
touch_driver_init();
|
||||
#elif defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_I2C)
|
||||
ESP_LOGI(TAG, "Initializing I2C master for touch");
|
||||
|
||||
lvgl_i2c_driver_init(TOUCH_I2C_PORT,
|
||||
TOUCH_I2C_SDA, TOUCH_I2C_SCL,
|
||||
TOUCH_I2C_SPEED_HZ);
|
||||
|
||||
touch_driver_init();
|
||||
#elif defined (CONFIG_LV_TOUCH_DRIVER_ADC)
|
||||
touch_driver_init();
|
||||
#elif defined (CONFIG_LV_TOUCH_DRIVER_DISPLAY)
|
||||
touch_driver_init();
|
||||
#else
|
||||
#error "No protocol defined for touch controller"
|
||||
#endif
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Config the i2c master
|
||||
*
|
||||
* This should init the i2c master to be used on display and touch controllers.
|
||||
* So we should be able to know if the display and touch controllers shares the
|
||||
* same i2c master.
|
||||
*/
|
||||
bool lvgl_i2c_driver_init(int port, int sda_pin, int scl_pin, int speed_hz)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
ESP_LOGI(TAG, "Initializing I2C master port %d...", port);
|
||||
ESP_LOGI(TAG, "SDA pin: %d, SCL pin: %d, Speed: %d (Hz)",
|
||||
sda_pin, scl_pin, speed_hz);
|
||||
|
||||
i2c_config_t conf = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = sda_pin,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_io_num = scl_pin,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = speed_hz,
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "Setting I2C master configuration...");
|
||||
err = i2c_param_config(port, &conf);
|
||||
assert(ESP_OK == err);
|
||||
|
||||
ESP_LOGI(TAG, "Installing I2C master driver...");
|
||||
err = i2c_driver_install(port,
|
||||
I2C_MODE_MASTER,
|
||||
0, 0 /*I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE */,
|
||||
0 /* intr_alloc_flags */);
|
||||
assert(ESP_OK == err);
|
||||
|
||||
return ESP_OK != err;
|
||||
}
|
||||
|
||||
/* Initialize spi bus master */
|
||||
bool lvgl_spi_driver_init(int host,
|
||||
int miso_pin, int mosi_pin, int sclk_pin,
|
||||
int max_transfer_sz,
|
||||
int dma_channel,
|
||||
int quadwp_pin, int quadhd_pin)
|
||||
{
|
||||
#if defined (CONFIG_IDF_TARGET_ESP32)
|
||||
assert((SPI_HOST <= host) && (VSPI_HOST >= host));
|
||||
const char *spi_names[] = {
|
||||
"SPI_HOST", "HSPI_HOST", "VSPI_HOST"
|
||||
};
|
||||
#elif defined (CONFIG_IDF_TARGET_ESP32S2)
|
||||
assert((SPI_HOST <= host) && (HSPI_HOST >= host));
|
||||
const char *spi_names[] = {
|
||||
"SPI_HOST", "", ""
|
||||
};
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Configuring SPI host %s (%d)", spi_names[host], host);
|
||||
ESP_LOGI(TAG, "MISO pin: %d, MOSI pin: %d, SCLK pin: %d, IO2/WP pin: %d, IO3/HD pin: %d",
|
||||
miso_pin, mosi_pin, sclk_pin, quadwp_pin, quadhd_pin);
|
||||
|
||||
ESP_LOGI(TAG, "Max transfer size: %d (bytes)", max_transfer_sz);
|
||||
|
||||
spi_bus_config_t buscfg = {
|
||||
.miso_io_num = miso_pin,
|
||||
.mosi_io_num = mosi_pin,
|
||||
.sclk_io_num = sclk_pin,
|
||||
.quadwp_io_num = quadwp_pin,
|
||||
.quadhd_io_num = quadhd_pin,
|
||||
.max_transfer_sz = max_transfer_sz
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "Initializing SPI bus...");
|
||||
esp_err_t ret = spi_bus_initialize(host, &buscfg, dma_channel);
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
return ESP_OK != ret;
|
||||
}
|
||||
|
85
lvgl_helpers.h
Normal file
85
lvgl_helpers.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* @file lvgl_helpers.h
|
||||
*/
|
||||
|
||||
#ifndef LVGL_HELPERS_H
|
||||
#define LVGL_HELPERS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "lvgl_spi_conf.h"
|
||||
#include "lvgl_tft/disp_driver.h"
|
||||
#include "lvgl_touch/touch_driver.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789)
|
||||
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S
|
||||
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_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)
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
|
||||
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486
|
||||
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
|
||||
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341
|
||||
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 64)
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306
|
||||
#define DISP_BUF_SIZE (CONFIG_LV_DISPLAY_WIDTH*CONFIG_LV_DISPLAY_HEIGHT)
|
||||
#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)
|
||||
#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
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D)
|
||||
#define DISP_BUF_SIZE ((CONFIG_LV_DISPLAY_HEIGHT * CONFIG_LV_DISPLAY_WIDTH) / 8) // 2888 bytes
|
||||
#else
|
||||
#error "No display controller selected"
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/* Initialize detected SPI and I2C bus and devices */
|
||||
void lvgl_driver_init(void);
|
||||
|
||||
/* Initialize SPI master */
|
||||
bool lvgl_spi_driver_init(int host, int miso_pin, int mosi_pin, int sclk_pin,
|
||||
int max_transfer_sz, int dma_channel, int quadwp_pin, int quadhd_pin);
|
||||
/* Initialize I2C master */
|
||||
bool lvgl_i2c_driver_init(int port, int sda_pin, int scl_pin, int speed);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* LVGL_HELPERS_H */
|
116
lvgl_i2c_conf.h
Normal file
116
lvgl_i2c_conf.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
* @file lvgl_i2c_config.h
|
||||
*/
|
||||
|
||||
#ifndef LVGL_I2C_CONF_H
|
||||
#define LVGL_I2C_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/* TODO: Define the I2C bus clock based on the selected display or touch
|
||||
* controllers. */
|
||||
|
||||
/* Do both display and touch controllers uses I2C? */
|
||||
#if defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_I2C) && \
|
||||
defined (CONFIG_LV_TFT_DISPLAY_PROTOCOL_I2C)
|
||||
|
||||
#if defined (CONFIG_LV_DISPLAY_I2C_PORT_0) && \
|
||||
defined (CONFIG_LV_TOUCH_I2C_PORT_0)
|
||||
#define SHARED_I2C_PORT
|
||||
#define DISP_I2C_PORT I2C_NUM_0
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_LV_DISPLAY_I2C_PORT_1) && \
|
||||
defined (CONFIG_LV_TOUCH_I2C_PORT_1)
|
||||
#define SHARED_I2C_PORT
|
||||
#define DISP_I2C_PORT I2C_NUM_1
|
||||
#endif
|
||||
|
||||
#if !defined (SHARED_I2C_PORT)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (SHARED_I2C_PORT)
|
||||
/* If the port is shared the display and touch controllers must use the same
|
||||
* SCL and SDA pins, otherwise let the user know with an error. */
|
||||
#if (CONFIG_LV_DISP_PIN_SDA != CONFIG_LV_TOUCH_I2C_SDA) || \
|
||||
(CONFIG_LV_DISP_PIN_SCL != CONFIG_LV_TOUCH_I2C_SCL)
|
||||
#error "To share I2C port you need to choose the same SDA and SCL pins on both display and touch configurations"
|
||||
#endif
|
||||
|
||||
#define DISP_I2C_SDA CONFIG_LV_DISP_PIN_SDA
|
||||
#define DISP_I2C_SCL CONFIG_LV_DISP_PIN_SCL
|
||||
#define DISP_I2C_ORIENTATION TFT_ORIENTATION_LANDSCAPE
|
||||
|
||||
/* Setting the I2C speed to the slowest one */
|
||||
#if DISP_I2C_SPEED_HZ < TOUCH_I2C_SPEED_HZ
|
||||
#define DISP_I2C_SPEED_HZ 400000 /* DISP_I2C_SPEED_HZ */
|
||||
#else
|
||||
#define DISP_I2C_SPEED_HZ 400000 /* DISP_I2C_SPEED_HZ */
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/* lets check if the touch controller uses I2C... */
|
||||
#if defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_I2C)
|
||||
#if defined (CONFIG_LV_TOUCH_I2C_PORT_0)
|
||||
#define TOUCH_I2C_PORT I2C_NUM_0
|
||||
#else
|
||||
#define TOUCH_I2C_PORT I2C_NUM_1
|
||||
#endif
|
||||
#define TOUCH_I2C_SDA CONFIG_LV_TOUCH_I2C_SDA
|
||||
#define TOUCH_I2C_SCL CONFIG_LV_TOUCH_I2C_SCL
|
||||
#define TOUCH_I2C_SPEED_HZ 400000
|
||||
#endif
|
||||
|
||||
/* lets check if the display controller uses I2C... */
|
||||
#if defined (CONFIG_LV_TFT_DISPLAY_PROTOCOL_I2C)
|
||||
#if defined (CONFIG_LV_DISPLAY_I2C_PORT_0)
|
||||
#define DISP_I2C_PORT I2C_NUM_0
|
||||
#else
|
||||
#define DISP_I2C_PORT I2C_NUM_1
|
||||
#endif
|
||||
|
||||
#define DISP_I2C_SDA CONFIG_LV_DISP_PIN_SDA
|
||||
#define DISP_I2C_SCL CONFIG_LV_DISP_PIN_SCL
|
||||
#define DISP_I2C_ORIENTATION TFT_ORIENTATION_LANDSCAPE
|
||||
#define DISP_I2C_SPEED_HZ 400000
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LVGL_I2C_CONF_H*/
|
198
lvgl_spi_conf.h
Normal file
198
lvgl_spi_conf.h
Normal file
|
@ -0,0 +1,198 @@
|
|||
/**
|
||||
* @file lvgl_spi_conf.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LVGL_SPI_CONF_H
|
||||
#define LVGL_SPI_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
// DISPLAY PINS
|
||||
#define DISP_SPI_MOSI CONFIG_LV_DISP_SPI_MOSI
|
||||
#if defined (CONFIG_LV_DISPLAY_USE_SPI_MISO)
|
||||
#define DISP_SPI_MISO CONFIG_LV_DISP_SPI_MISO
|
||||
#define DISP_SPI_INPUT_DELAY_NS CONFIG_LV_DISP_SPI_INPUT_DELAY_NS
|
||||
#else
|
||||
#define DISP_SPI_MISO (-1)
|
||||
#define DISP_SPI_INPUT_DELAY_NS (0)
|
||||
#endif
|
||||
#if defined(CONFIG_LV_DISP_SPI_IO2)
|
||||
#define DISP_SPI_IO2 CONFIG_LV_DISP_SPI_IO2
|
||||
#else
|
||||
#define DISP_SPI_IO2 (-1)
|
||||
#endif
|
||||
#if defined(CONFIG_LV_DISP_SPI_IO3)
|
||||
#define DISP_SPI_IO3 CONFIG_LV_DISP_SPI_IO3
|
||||
#else
|
||||
#define DISP_SPI_IO3 (-1)
|
||||
#endif
|
||||
#define DISP_SPI_CLK CONFIG_LV_DISP_SPI_CLK
|
||||
#if defined (CONFIG_LV_DISPLAY_USE_SPI_CS)
|
||||
#define DISP_SPI_CS CONFIG_LV_DISP_SPI_CS
|
||||
#else
|
||||
#define DISP_SPI_CS (-1)
|
||||
#endif
|
||||
|
||||
/* Define TOUCHPAD PINS when selecting a touch controller */
|
||||
#if !defined (CONFIG_LV_TOUCH_CONTROLLER_NONE)
|
||||
|
||||
/* Handle FT81X special case */
|
||||
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) && \
|
||||
defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
|
||||
|
||||
#define TP_SPI_MOSI CONFIG_LV_DISP_SPI_MOSI
|
||||
#define TP_SPI_MISO CONFIG_LV_DISP_SPI_MISO
|
||||
#define TP_SPI_CLK CONFIG_LV_DISP_SPI_CLK
|
||||
#define TP_SPI_CS CONFIG_LV_DISP_SPI_CS
|
||||
#else
|
||||
#define TP_SPI_MOSI CONFIG_LV_TOUCH_SPI_MOSI
|
||||
#define TP_SPI_MISO CONFIG_LV_TOUCH_SPI_MISO
|
||||
#define TP_SPI_CLK CONFIG_LV_TOUCH_SPI_CLK
|
||||
#define TP_SPI_CS CONFIG_LV_TOUCH_SPI_CS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define ENABLE_TOUCH_INPUT CONFIG_LV_ENABLE_TOUCH
|
||||
|
||||
#if defined (CONFIG_LV_TFT_DISPLAY_SPI_HSPI)
|
||||
#define TFT_SPI_HOST HSPI_HOST
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_SPI_VSPI)
|
||||
#define TFT_SPI_HOST VSPI_HOST
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_SPI_FSPI)
|
||||
#define TFT_SPI_HOST FSPI_HOST
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_LV_TFT_DISPLAY_SPI_HALF_DUPLEX)
|
||||
#define DISP_SPI_HALF_DUPLEX
|
||||
#else
|
||||
#define DISP_SPI_FULL_DUPLEX
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_LV_TFT_DISPLAY_SPI_TRANS_MODE_DIO)
|
||||
#define DISP_SPI_TRANS_MODE_DIO
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_SPI_TRANS_MODE_QIO)
|
||||
#define DISP_SPI_TRANS_MODE_QIO
|
||||
#else
|
||||
#define DISP_SPI_TRANS_MODE_SIO
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_LV_TOUCH_CONTROLLER_SPI_HSPI)
|
||||
#define TOUCH_SPI_HOST HSPI_HOST
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_SPI_VSPI)
|
||||
#define TOUCH_SPI_HOST VSPI_HOST
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_SPI_FSPI)
|
||||
#define TOUCH_SPI_HOST FSPI_HOST
|
||||
#endif
|
||||
|
||||
/* Handle the FT81X Special case */
|
||||
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
|
||||
|
||||
#if defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
|
||||
#define SHARED_SPI_BUS
|
||||
#else
|
||||
/* Empty */
|
||||
#endif
|
||||
|
||||
#else
|
||||
// Detect the use of a shared SPI Bus and verify the user specified the same SPI bus for both touch and tft
|
||||
#if defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI) && TP_SPI_MOSI == DISP_SPI_MOSI && TP_SPI_CLK == DISP_SPI_CLK
|
||||
#if TFT_SPI_HOST != TOUCH_SPI_HOST
|
||||
#error You must specify the same SPI host (HSPI, VSPI or FSPI) for both display and touch driver
|
||||
#endif
|
||||
|
||||
#define SHARED_SPI_BUS
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481) || \
|
||||
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488)
|
||||
|
||||
#define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 3)
|
||||
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341) || \
|
||||
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789) || \
|
||||
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S) || \
|
||||
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357) || \
|
||||
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107) || \
|
||||
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) || \
|
||||
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820) || \
|
||||
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A)
|
||||
|
||||
#define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 2)
|
||||
|
||||
#else
|
||||
#define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 2)
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_LV_TFT_USE_CUSTOM_SPI_CLK_DIVIDER)
|
||||
#define SPI_TFT_CLOCK_SPEED_HZ ((80 * 1000 * 1000) / CONFIG_LV_TFT_CUSTOM_SPI_CLK_DIVIDER)
|
||||
#else
|
||||
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789)
|
||||
#define SPI_TFT_CLOCK_SPEED_HZ (20*1000*1000)
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S)
|
||||
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357)
|
||||
#define SPI_TFT_CLOCK_SPEED_HZ (26*1000*1000)
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107)
|
||||
#define SPI_TFT_CLOCK_SPEED_HZ (8*1000*1000)
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481)
|
||||
#define SPI_TFT_CLOCK_SPEED_HZ (16*1000*1000)
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486)
|
||||
#define SPI_TFT_CLOCK_SPEED_HZ (20*1000*1000)
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488)
|
||||
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341)
|
||||
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
|
||||
#define SPI_TFT_CLOCK_SPEED_HZ (32*1000*1000)
|
||||
#else
|
||||
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789)
|
||||
#define SPI_TFT_SPI_MODE (2)
|
||||
#else
|
||||
#define SPI_TFT_SPI_MODE (0)
|
||||
#endif
|
||||
|
||||
/* Touch driver */
|
||||
#if (CONFIG_LV_TOUCH_CONTROLLER == TOUCH_CONTROLLER_STMPE610)
|
||||
#define SPI_TOUCH_CLOCK_SPEED_HZ (1*1000*1000)
|
||||
#define SPI_TOUCH_SPI_MODE (1)
|
||||
#else
|
||||
#define SPI_TOUCH_CLOCK_SPEED_HZ (2*1000*1000)
|
||||
#define SPI_TOUCH_SPI_MODE (0)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LVGL_SPI_CONF_H*/
|
53
lvgl_tft/CMakeLists.txt
Normal file
53
lvgl_tft/CMakeLists.txt
Normal file
|
@ -0,0 +1,53 @@
|
|||
if(ESP_PLATFORM)
|
||||
|
||||
set(SOURCES "disp_driver.c")
|
||||
|
||||
# Include only the source file of the selected
|
||||
# display controller.
|
||||
if(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341)
|
||||
list(APPEND SOURCES "ili9341.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481)
|
||||
list(APPEND SOURCES "ili9481.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486)
|
||||
list(APPEND SOURCES "ili9486.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488)
|
||||
list(APPEND SOURCES "ili9488.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789)
|
||||
list(APPEND SOURCES "st7789.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S)
|
||||
list(APPEND SOURCES "st7735s.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357)
|
||||
list(APPEND SOURCES "hx8357.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107)
|
||||
list(APPEND SOURCES "sh1107.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306)
|
||||
list(APPEND SOURCES "ssd1306.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
|
||||
list(APPEND SOURCES "EVE_commands.c")
|
||||
list(APPEND SOURCES "FT81x.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820)
|
||||
list(APPEND SOURCES "il3820.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A)
|
||||
list(APPEND SOURCES "jd79653a.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D)
|
||||
list(APPEND SOURCES "uc8151d.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875)
|
||||
list(APPEND SOURCES "ra8875.c")
|
||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01)
|
||||
list(APPEND SOURCES "GC9A01.c")
|
||||
else()
|
||||
message("DISPLAY CONTROLLER NOT DEFINED")
|
||||
endif()
|
||||
|
||||
if(CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI)
|
||||
list(APPEND SOURCES "disp_spi.c")
|
||||
endif()
|
||||
|
||||
# Print the included source files
|
||||
message("SOURCES contents: " "${SOURCES}")
|
||||
|
||||
idf_component_register(SRCS ${SOURCES}
|
||||
INCLUDE_DIRS .
|
||||
REQUIRES lvgl)
|
||||
|
||||
endif()
|
842
lvgl_tft/EVE.h
Normal file
842
lvgl_tft/EVE.h
Normal file
|
@ -0,0 +1,842 @@
|
|||
/*
|
||||
@file EVE.h
|
||||
@brief Contains FT80x/FT81x/BT81x API definitions
|
||||
@version 4.1 LvGL edition
|
||||
@date 2020-04-15
|
||||
@author Rudolph Riedel, David Jade
|
||||
|
||||
@section LICENSE
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016-2020 Rudolph Riedel and David Jade
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
@section History
|
||||
|
||||
4.1 LvGL edition
|
||||
|
||||
- This version is a heavily modified version of the MIT licensed FT81x code from https://github.com/RudolphRiedel/FT800-FT813
|
||||
This version is based on a fork by David Jade that added native SPI DMA support and stripped out non-ESP32 code.
|
||||
It has also been trimmed down to suit LvGL's needs. Extra features can be enabled by defining FT81X_FULL
|
||||
*/
|
||||
|
||||
#if defined (ESP_PLATFORM)
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "EVE_config.h"
|
||||
|
||||
#ifndef EVE_H_
|
||||
#define EVE_H_
|
||||
|
||||
|
||||
#define DL_CLEAR 0x26000000UL /* requires OR'd arguments */
|
||||
#define DL_CLEAR_RGB 0x02000000UL /* requires OR'd arguments */
|
||||
#define DL_COLOR_RGB 0x04000000UL /* requires OR'd arguments */
|
||||
#define DL_POINT_SIZE 0x0D000000UL /* requires OR'd arguments */
|
||||
#define DL_END 0x21000000UL
|
||||
#define DL_BEGIN 0x1F000000UL /* requires OR'd arguments */
|
||||
#define DL_DISPLAY 0x00000000UL
|
||||
|
||||
#define CLR_COL 0x4
|
||||
#define CLR_STN 0x2
|
||||
#define CLR_TAG 0x1
|
||||
|
||||
/* SPI SIO/DIO/QIO tranfer widths */
|
||||
#define SPI_WIDTH_SIO 0x0
|
||||
#define SPI_WIDTH_DIO 0x1
|
||||
#define SPI_WIDTH_QIO 0x2
|
||||
|
||||
|
||||
/* Host commands */
|
||||
#define EVE_ACTIVE 0x00 /* place FT8xx in active state */
|
||||
#define EVE_STANDBY 0x41 /* place FT8xx in Standby (clk running) */
|
||||
#define EVE_SLEEP 0x42 /* place FT8xx in Sleep (clk off) */
|
||||
#define EVE_PWRDOWN 0x50 /* place FT8xx in Power Down (core off) */
|
||||
#define EVE_CLKEXT 0x44 /* select external clock source */
|
||||
#define EVE_CLKINT 0x48 /* select internal clock source */
|
||||
#define EVE_CORERST 0x68 /* reset core - all registers default and processors reset */
|
||||
#define EVE_CLK48M 0x62 /* select 48MHz PLL output */
|
||||
#define EVE_CLK36M 0x61 /* select 36MHz PLL output */
|
||||
|
||||
|
||||
/* defines used for graphics commands */
|
||||
#define EVE_NEVER 0UL
|
||||
#define EVE_LESS 1UL
|
||||
#define EVE_LEQUAL 2UL
|
||||
#define EVE_GREATER 3UL
|
||||
#define EVE_GEQUAL 4UL
|
||||
#define EVE_EQUAL 5UL
|
||||
#define EVE_NOTEQUAL 6UL
|
||||
#define EVE_ALWAYS 7UL
|
||||
|
||||
|
||||
/* Bitmap formats */
|
||||
#define EVE_ARGB1555 0UL
|
||||
#define EVE_L1 1UL
|
||||
#define EVE_L4 2UL
|
||||
#define EVE_L8 3UL
|
||||
#define EVE_RGB332 4UL
|
||||
#define EVE_ARGB2 5UL
|
||||
#define EVE_ARGB4 6UL
|
||||
#define EVE_RGB565 7UL
|
||||
#define EVE_PALETTED 8UL
|
||||
#define EVE_TEXT8X8 9UL
|
||||
#define EVE_TEXTVGA 10UL
|
||||
#define EVE_BARGRAPH 11UL
|
||||
|
||||
|
||||
/* Bitmap filter types */
|
||||
#define EVE_NEAREST 0UL
|
||||
#define EVE_BILINEAR 1UL
|
||||
|
||||
|
||||
/* Bitmap wrap types */
|
||||
#define EVE_BORDER 0UL
|
||||
#define EVE_REPEAT 1UL
|
||||
|
||||
|
||||
/* Stencil defines */
|
||||
#define EVE_KEEP 1UL
|
||||
#define EVE_REPLACE 2UL
|
||||
#define EVE_INCR 3UL
|
||||
#define EVE_DECR 4UL
|
||||
#define EVE_INVERT 5UL
|
||||
|
||||
|
||||
/* Graphics display list swap defines */
|
||||
#define EVE_DLSWAP_DONE 0UL
|
||||
#define EVE_DLSWAP_LINE 1UL
|
||||
#define EVE_DLSWAP_FRAME 2UL
|
||||
|
||||
|
||||
/* Interrupt bits */
|
||||
#define EVE_INT_SWAP 0x01
|
||||
#define EVE_INT_TOUCH 0x02
|
||||
#define EVE_INT_TAG 0x04
|
||||
#define EVE_INT_SOUND 0x08
|
||||
#define EVE_INT_PLAYBACK 0x10
|
||||
#define EVE_INT_CMDEMPTY 0x20
|
||||
#define EVE_INT_CMDFLAG 0x40
|
||||
#define EVE_INT_CONVCOMPLETE 0x80
|
||||
|
||||
|
||||
/* Touch mode */
|
||||
#define EVE_TMODE_OFF 0
|
||||
#define EVE_TMODE_ONESHOT 1
|
||||
#define EVE_TMODE_FRAME 2
|
||||
#define EVE_TMODE_CONTINUOUS 3
|
||||
|
||||
|
||||
/* Alpha blending */
|
||||
#define EVE_ZERO 0UL
|
||||
#define EVE_ONE 1UL
|
||||
#define EVE_SRC_ALPHA 2UL
|
||||
#define EVE_DST_ALPHA 3UL
|
||||
#define EVE_ONE_MINUS_SRC_ALPHA 4UL
|
||||
#define EVE_ONE_MINUS_DST_ALPHA 5UL
|
||||
|
||||
|
||||
/* Graphics primitives */
|
||||
#define EVE_BITMAPS 1UL
|
||||
#define EVE_POINTS 2UL
|
||||
#define EVE_LINES 3UL
|
||||
#define EVE_LINE_STRIP 4UL
|
||||
#define EVE_EDGE_STRIP_R 5UL
|
||||
#define EVE_EDGE_STRIP_L 6UL
|
||||
#define EVE_EDGE_STRIP_A 7UL
|
||||
#define EVE_EDGE_STRIP_B 8UL
|
||||
#define EVE_RECTS 9UL
|
||||
|
||||
|
||||
/* Widget command */
|
||||
#define EVE_OPT_MONO 1
|
||||
#define EVE_OPT_NODL 2
|
||||
#define EVE_OPT_FLAT 256
|
||||
#define EVE_OPT_CENTERX 512
|
||||
#define EVE_OPT_CENTERY 1024
|
||||
#define EVE_OPT_CENTER (EVE_OPT_CENTERX | EVE_OPT_CENTERY)
|
||||
#define EVE_OPT_NOBACK 4096
|
||||
#define EVE_OPT_NOTICKS 8192
|
||||
#define EVE_OPT_NOHM 16384
|
||||
#define EVE_OPT_NOPOINTER 16384
|
||||
#define EVE_OPT_NOSECS 32768
|
||||
#define EVE_OPT_NOHANDS 49152
|
||||
#define EVE_OPT_RIGHTX 2048
|
||||
#define EVE_OPT_SIGNED 256
|
||||
|
||||
|
||||
/* Defines related to inbuilt font */
|
||||
#define EVE_NUMCHAR_PERFONT (128L) /* number of font characters per bitmap handle */
|
||||
#define EVE_FONT_TABLE_SIZE (148L) /* size of the font table - utilized for loopup by the graphics engine */
|
||||
#define EVE_FONT_TABLE_POINTER (0xFFFFCUL) /* pointer to the inbuilt font tables starting from bitmap handle 16 */
|
||||
|
||||
|
||||
/* Audio sample type defines */
|
||||
#define EVE_LINEAR_SAMPLES 0UL /* 8bit signed samples */
|
||||
#define EVE_ULAW_SAMPLES 1UL /* 8bit ulaw samples */
|
||||
#define EVE_ADPCM_SAMPLES 2UL /* 4bit ima adpcm samples */
|
||||
|
||||
|
||||
/* Synthesized sound */
|
||||
#define EVE_SILENCE 0x00
|
||||
#define EVE_SQUAREWAVE 0x01
|
||||
#define EVE_SINEWAVE 0x02
|
||||
#define EVE_SAWTOOTH 0x03
|
||||
#define EVE_TRIANGLE 0x04
|
||||
#define EVE_BEEPING 0x05
|
||||
#define EVE_ALARM 0x06
|
||||
#define EVE_WARBLE 0x07
|
||||
#define EVE_CAROUSEL 0x08
|
||||
#define EVE_PIPS(n) (0x0F + (n))
|
||||
#define EVE_HARP 0x40
|
||||
#define EVE_XYLOPHONE 0x41
|
||||
#define EVE_TUBA 0x42
|
||||
#define EVE_GLOCKENSPIEL 0x43
|
||||
#define EVE_ORGAN 0x44
|
||||
#define EVE_TRUMPET 0x45
|
||||
#define EVE_PIANO 0x46
|
||||
#define EVE_CHIMES 0x47
|
||||
#define EVE_MUSICBOX 0x48
|
||||
#define EVE_BELL 0x49
|
||||
#define EVE_CLICK 0x50
|
||||
#define EVE_SWITCH 0x51
|
||||
#define EVE_COWBELL 0x52
|
||||
#define EVE_NOTCH 0x53
|
||||
#define EVE_HIHAT 0x54
|
||||
#define EVE_KICKDRUM 0x55
|
||||
#define EVE_POP 0x56
|
||||
#define EVE_CLACK 0x57
|
||||
#define EVE_CHACK 0x58
|
||||
#define EVE_MUTE 0x60
|
||||
#define EVE_UNMUTE 0x61
|
||||
|
||||
|
||||
/* Synthesized sound frequencies, midi note */
|
||||
#define EVE_MIDI_A0 21
|
||||
#define EVE_MIDI_A_0 22
|
||||
#define EVE_MIDI_B0 23
|
||||
#define EVE_MIDI_C1 24
|
||||
#define EVE_MIDI_C_1 25
|
||||
#define EVE_MIDI_D1 26
|
||||
#define EVE_MIDI_D_1 27
|
||||
#define EVE_MIDI_E1 28
|
||||
#define EVE_MIDI_F1 29
|
||||
#define EVE_MIDI_F_1 30
|
||||
#define EVE_MIDI_G1 31
|
||||
#define EVE_MIDI_G_1 32
|
||||
#define EVE_MIDI_A1 33
|
||||
#define EVE_MIDI_A_1 34
|
||||
#define EVE_MIDI_B1 35
|
||||
#define EVE_MIDI_C2 36
|
||||
#define EVE_MIDI_C_2 37
|
||||
#define EVE_MIDI_D2 38
|
||||
#define EVE_MIDI_D_2 39
|
||||
#define EVE_MIDI_E2 40
|
||||
#define EVE_MIDI_F2 41
|
||||
#define EVE_MIDI_F_2 42
|
||||
#define EVE_MIDI_G2 43
|
||||
#define EVE_MIDI_G_2 44
|
||||
#define EVE_MIDI_A2 45
|
||||
#define EVE_MIDI_A_2 46
|
||||
#define EVE_MIDI_B2 47
|
||||
#define EVE_MIDI_C3 48
|
||||
#define EVE_MIDI_C_3 49
|
||||
#define EVE_MIDI_D3 50
|
||||
#define EVE_MIDI_D_3 51
|
||||
#define EVE_MIDI_E3 52
|
||||
#define EVE_MIDI_F3 53
|
||||
#define EVE_MIDI_F_3 54
|
||||
#define EVE_MIDI_G3 55
|
||||
#define EVE_MIDI_G_3 56
|
||||
#define EVE_MIDI_A3 57
|
||||
#define EVE_MIDI_A_3 58
|
||||
#define EVE_MIDI_B3 59
|
||||
#define EVE_MIDI_C4 60
|
||||
#define EVE_MIDI_C_4 61
|
||||
#define EVE_MIDI_D4 62
|
||||
#define EVE_MIDI_D_4 63
|
||||
#define EVE_MIDI_E4 64
|
||||
#define EVE_MIDI_F4 65
|
||||
#define EVE_MIDI_F_4 66
|
||||
#define EVE_MIDI_G4 67
|
||||
#define EVE_MIDI_G_4 68
|
||||
#define EVE_MIDI_A4 69
|
||||
#define EVE_MIDI_A_4 70
|
||||
#define EVE_MIDI_B4 71
|
||||
#define EVE_MIDI_C5 72
|
||||
#define EVE_MIDI_C_5 73
|
||||
#define EVE_MIDI_D5 74
|
||||
#define EVE_MIDI_D_5 75
|
||||
#define EVE_MIDI_E5 76
|
||||
#define EVE_MIDI_F5 77
|
||||
#define EVE_MIDI_F_5 78
|
||||
#define EVE_MIDI_G5 79
|
||||
#define EVE_MIDI_G_5 80
|
||||
#define EVE_MIDI_A5 81
|
||||
#define EVE_MIDI_A_5 82
|
||||
#define EVE_MIDI_B5 83
|
||||
#define EVE_MIDI_C6 84
|
||||
#define EVE_MIDI_C_6 85
|
||||
#define EVE_MIDI_D6 86
|
||||
#define EVE_MIDI_D_6 87
|
||||
#define EVE_MIDI_E6 88
|
||||
#define EVE_MIDI_F6 89
|
||||
#define EVE_MIDI_F_6 90
|
||||
#define EVE_MIDI_G6 91
|
||||
#define EVE_MIDI_G_6 92
|
||||
#define EVE_MIDI_A6 93
|
||||
#define EVE_MIDI_A_6 94
|
||||
#define EVE_MIDI_B6 95
|
||||
#define EVE_MIDI_C7 96
|
||||
#define EVE_MIDI_C_7 97
|
||||
#define EVE_MIDI_D7 98
|
||||
#define EVE_MIDI_D_7 99
|
||||
#define EVE_MIDI_E7 100
|
||||
#define EVE_MIDI_F7 101
|
||||
#define EVE_MIDI_F_7 102
|
||||
#define EVE_MIDI_G7 103
|
||||
#define EVE_MIDI_G_7 104
|
||||
#define EVE_MIDI_A7 105
|
||||
#define EVE_MIDI_A_7 106
|
||||
#define EVE_MIDI_B7 107
|
||||
#define EVE_MIDI_C8 108
|
||||
|
||||
|
||||
/* GPIO bits */
|
||||
#define EVE_GPIO0 0
|
||||
#define EVE_GPIO1 1 /* default gpio pin for audio shutdown, 1 - enable, 0 - disable */
|
||||
#define EVE_GPIO7 7 /* default gpio pin for display enable, 1 - enable, 0 - disable */
|
||||
|
||||
|
||||
/* Display rotation */
|
||||
#define EVE_DISPLAY_0 0 /* 0 degrees rotation */
|
||||
#define EVE_DISPLAY_180 1 /* 180 degrees rotation */
|
||||
|
||||
|
||||
/* commands common to EVE/EVE2/EVE3 */
|
||||
#define CMD_APPEND 0xFFFFFF1E
|
||||
#define CMD_BGCOLOR 0xFFFFFF09
|
||||
#define CMD_BUTTON 0xFFFFFF0D
|
||||
#define CMD_CALIBRATE 0xFFFFFF15
|
||||
#define CMD_CLOCK 0xFFFFFF14
|
||||
#define CMD_COLDSTART 0xFFFFFF32
|
||||
#define CMD_DIAL 0xFFFFFF2D
|
||||
#define CMD_DLSTART 0xFFFFFF00
|
||||
#define CMD_FGCOLOR 0xFFFFFF0A
|
||||
#define CMD_GAUGE 0xFFFFFF13
|
||||
#define CMD_GETMATRIX 0xFFFFFF33
|
||||
#define CMD_GETPROPS 0xFFFFFF25
|
||||
#define CMD_GETPTR 0xFFFFFF23
|
||||
#define CMD_GRADCOLOR 0xFFFFFF34
|
||||
#define CMD_GRADIENT 0xFFFFFF0B
|
||||
#define CMD_INFLATE 0xFFFFFF22
|
||||
#define CMD_INTERRUPT 0xFFFFFF02
|
||||
#define CMD_KEYS 0xFFFFFF0E
|
||||
#define CMD_LOADIDENTITY 0xFFFFFF26
|
||||
#define CMD_LOADIMAGE 0xFFFFFF24
|
||||
#define CMD_LOGO 0xFFFFFF31
|
||||
#define CMD_MEMCPY 0xFFFFFF1D
|
||||
#define CMD_MEMCRC 0xFFFFFF18
|
||||
#define CMD_MEMSET 0xFFFFFF1B
|
||||
#define CMD_MEMWRITE 0xFFFFFF1A
|
||||
#define CMD_MEMZERO 0xFFFFFF1C
|
||||
#define CMD_NUMBER 0xFFFFFF2E
|
||||
#define CMD_PROGRESS 0xFFFFFF0F
|
||||
#define CMD_REGREAD 0xFFFFFF19
|
||||
#define CMD_ROTATE 0xFFFFFF29
|
||||
#define CMD_SCALE 0xFFFFFF28
|
||||
#define CMD_SCREENSAVER 0xFFFFFF2F
|
||||
#define CMD_SCROLLBAR 0xFFFFFF11
|
||||
#define CMD_SETFONT 0xFFFFFF2B
|
||||
#define CMD_SETMATRIX 0xFFFFFF2A
|
||||
#define CMD_SKETCH 0xFFFFFF30
|
||||
#define CMD_SLIDER 0xFFFFFF10
|
||||
#define CMD_SNAPSHOT 0xFFFFFF1F
|
||||
#define CMD_SPINNER 0xFFFFFF16
|
||||
#define CMD_STOP 0xFFFFFF17
|
||||
#define CMD_SWAP 0xFFFFFF01
|
||||
#define CMD_TEXT 0xFFFFFF0C
|
||||
#define CMD_TOGGLE 0xFFFFFF12
|
||||
#define CMD_TRACK 0xFFFFFF2C
|
||||
#define CMD_TRANSLATE 0xFFFFFF27
|
||||
|
||||
|
||||
/* the following are undocumented commands that therefore should not be used */
|
||||
#if 0
|
||||
#define CMD_CRC 0xFFFFFF03
|
||||
#define CMD_HAMMERAUX 0xFFFFFF04
|
||||
#define CMD_MARCH 0xFFFFFF05
|
||||
#define CMD_IDCT 0xFFFFFF06
|
||||
#define CMD_EXECUTE 0xFFFFFF07
|
||||
#define CMD_GETPOINT 0xFFFFFF08
|
||||
#define CMD_TOUCH_TRANSFORM 0xFFFFFF20
|
||||
#endif
|
||||
|
||||
|
||||
/* FT8xx graphics engine specific macros useful for static display list generation */
|
||||
#define ALPHA_FUNC(func,ref) ((9UL<<24)|(((func)&7UL)<<8)|(((ref)&255UL)<<0))
|
||||
#define BEGIN(prim) ((31UL<<24)|(((prim)&15UL)<<0))
|
||||
#define BITMAP_HANDLE(handle) ((5UL<<24)|(((handle)&31UL)<<0))
|
||||
#define BITMAP_LAYOUT(format,linestride,height) ((7UL<<24)|(((format)&31UL)<<19)|(((linestride)&1023UL)<<9)|(((height)&511UL)<<0))
|
||||
#define BITMAP_SIZE(filter,wrapx,wrapy,width,height) ((8UL<<24)|(((filter)&1UL)<<20)|(((wrapx)&1UL)<<19)|(((wrapy)&1UL)<<18)|(((width)&511UL)<<9)|(((height)&511UL)<<0))
|
||||
#define BITMAP_TRANSFORM_A(a) ((21UL<<24)|(((a)&131071UL)<<0))
|
||||
#define BITMAP_TRANSFORM_B(b) ((22UL<<24)|(((b)&131071UL)<<0))
|
||||
#define BITMAP_TRANSFORM_C(c) ((23UL<<24)|(((c)&16777215UL)<<0))
|
||||
#define BITMAP_TRANSFORM_D(d) ((24UL<<24)|(((d)&131071UL)<<0))
|
||||
#define BITMAP_TRANSFORM_E(e) ((25UL<<24)|(((e)&131071UL)<<0))
|
||||
#define BITMAP_TRANSFORM_F(f) ((26UL<<24)|(((f)&16777215UL)<<0))
|
||||
#define BLEND_FUNC(src,dst) ((11UL<<24)|(((src)&7UL)<<3)|(((dst)&7UL)<<0))
|
||||
#define CALL(dest) ((29UL<<24)|(((dest)&65535UL)<<0))
|
||||
#define CELL(cell) ((6UL<<24)|(((cell)&127UL)<<0))
|
||||
#define CLEAR(c,s,t) ((38UL<<24)|(((c)&1UL)<<2)|(((s)&1UL)<<1)|(((t)&1UL)<<0))
|
||||
#define CLEAR_COLOR_A(alpha) ((15UL<<24)|(((alpha)&255UL)<<0))
|
||||
#define CLEAR_COLOR_RGB(red,green,blue) ((2UL<<24)|(((red)&255UL)<<16)|(((green)&255UL)<<8)|(((blue)&255UL)<<0))
|
||||
#define CLEAR_STENCIL(s) ((17UL<<24)|(((s)&255UL)<<0))
|
||||
#define CLEAR_TAG(s) ((18UL<<24)|(((s)&255UL)<<0))
|
||||
#define COLOR_A(alpha) ((16UL<<24)|(((alpha)&255UL)<<0))
|
||||
#define COLOR_MASK(r,g,b,a) ((32UL<<24)|(((r)&1UL)<<3)|(((g)&1UL)<<2)|(((b)&1UL)<<1)|(((a)&1UL)<<0))
|
||||
#define COLOR_RGB(red,green,blue) ((4UL<<24)|(((red)&255UL)<<16)|(((green)&255UL)<<8)|(((blue)&255UL)<<0))
|
||||
/* #define DISPLAY() ((0UL<<24)) */
|
||||
#define END() ((33UL<<24))
|
||||
#define JUMP(dest) ((30UL<<24)|(((dest)&65535UL)<<0))
|
||||
#define LINE_WIDTH(width) ((14UL<<24)|(((width)&4095UL)<<0))
|
||||
#define MACRO(m) ((37UL<<24)|(((m)&1UL)<<0))
|
||||
#define POINT_SIZE(size) ((13UL<<24)|(((size)&8191UL)<<0))
|
||||
#define RESTORE_CONTEXT() ((35UL<<24))
|
||||
#define RETURN() ((36UL<<24))
|
||||
#define SAVE_CONTEXT() ((34UL<<24))
|
||||
#define STENCIL_FUNC(func,ref,mask) ((10UL<<24)|(((func)&7UL)<<16)|(((ref)&255UL)<<8)|(((mask)&255UL)<<0))
|
||||
#define STENCIL_MASK(mask) ((19UL<<24)|(((mask)&255UL)<<0))
|
||||
#define STENCIL_OP(sfail,spass) ((12UL<<24)|(((sfail)&7UL)<<3)|(((spass)&7UL)<<0))
|
||||
#define TAG(s) ((3UL<<24)|(((s)&255UL)<<0))
|
||||
#define TAG_MASK(mask) ((20UL<<24)|(((mask)&1UL)<<0))
|
||||
#define VERTEX2F(x,y) ((1UL<<30)|(((x)&32767UL)<<15)|(((y)&32767UL)<<0))
|
||||
#define VERTEX2II(x,y,handle,cell) ((2UL<<30)|(((x)&511UL)<<21)|(((y)&511UL)<<12)|(((handle)&31UL)<<7)|(((cell)&127UL)<<0))
|
||||
|
||||
|
||||
/* ----------------- BT81x exclusive definitions -----------------*/
|
||||
#if defined (BT81X_ENABLE)
|
||||
|
||||
#define EVE_GLFORMAT 31UL /* used with BITMAP_LAYOUT to indicate bitmap-format is specified by BITMAP_EXT_FORMAT */
|
||||
|
||||
#define DL_BITMAP_EXT_FORMAT 0x2E000000 /* requires OR'd arguments */
|
||||
|
||||
/* extended Bitmap formats */
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_4x4_KHR 37808UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_5x4_KHR 37809UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_5x5_KHR 37810UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_6x5_KHR 37811UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_6x6_KHR 37812UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_8x5_KHR 37813UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_8x6_KHR 37814UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_8x8_KHR 37815UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_10x5_KHR 37816UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_10x6_KHR 37817UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_10x8_KHR 37818UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_10x10_KHR 37819UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_12x10_KHR 37820UL
|
||||
#define EVE_COMPRESSED_RGBA_ASTC_12x12_KHR 37821UL
|
||||
|
||||
|
||||
#define EVE_RAM_ERR_REPORT 0x309800UL /* max 128 bytes null terminated string */
|
||||
#define EVE_RAM_FLASH 0x800000UL
|
||||
#define EVE_RAM_FLASH_POSTBLOB 0x801000UL
|
||||
|
||||
#define EVE_OPT_FLASH 64UL
|
||||
#define EVE_OPT_FORMAT 4096UL
|
||||
#define EVE_OPT_FILL 8192UL
|
||||
|
||||
|
||||
/* additional commands for BT81x */
|
||||
#define CMD_BITMAP_TRANSFORM 0xFFFFFF21
|
||||
#define CMD_SYNC 0xFFFFFF42 /* does not need a dedicated function, just use EVE_cmd_dl(CMD_SYNC) */
|
||||
#define CMD_FLASHERASE 0xFFFFFF44 /* does not need a dedicated function, just use EVE_cmd_dl(CMD_FLASHERASE) */
|
||||
#define CMD_FLASHWRITE 0xFFFFFF45
|
||||
#define CMD_FLASHREAD 0xFFFFFF46
|
||||
#define CMD_FLASHUPDATE 0xFFFFFF47
|
||||
#define CMD_FLASHDETACH 0xFFFFFF48 /* does not need a dedicated function, just use EVE_cmd_dl(CMD_FLASHDETACH) */
|
||||
#define CMD_FLASHATTACH 0xFFFFFF49 /* does not need a dedicated function, just use EVE_cmd_dl(CMD_FLASHATTACH) */
|
||||
#define CMD_FLASHFAST 0xFFFFFF4A
|
||||
#define CMD_FLASHSPIDESEL 0xFFFFFF4B /* does not need a dedicated function, just use EVE_cmd_dl(CMD_FLASHSPIDESEL) */
|
||||
#define CMD_FLASHSPITX 0xFFFFFF4C
|
||||
#define CMD_FLASHSPIRX 0xFFFFFF4D
|
||||
#define CMD_FLASHSOURCE 0xFFFFFF4E
|
||||
#define CMD_CLEARCACHE 0xFFFFFF4F /* does not need a dedicated function, just use EVE_cmd_dl(CMD_CLEARCACHE) */
|
||||
#define CMD_INFLATE2 0xFFFFFF50
|
||||
#define CMD_ROTATEAROUND 0xFFFFFF51
|
||||
#define CMD_RESETFONTS 0xFFFFFF52 /* does not need a dedicated function, just use EVE_cmd_dl(CMD_RESETFONTS) */
|
||||
#define CMD_ANIMSTART 0xFFFFFF53
|
||||
#define CMD_ANIMSTOP 0xFFFFFF54
|
||||
#define CMD_ANIMXY 0xFFFFFF55
|
||||
#define CMD_ANIMDRAW 0xFFFFFF56
|
||||
#define CMD_GRADIENTA 0xFFFFFF57
|
||||
#define CMD_FILLWIDTH 0xFFFFFF58
|
||||
#define CMD_APPENDF 0xFFFFFF59
|
||||
#define CMD_ANIMFRAME 0xFFFFFF5A
|
||||
#define CMD_VIDEOSTARTF 0xFFFFFF5F /* does not need a dedicated function, just use EVE_cmd_dl(CMD_VIDEOSTARTF) */
|
||||
|
||||
#if 0
|
||||
/* some undocumented commands for BT81x */
|
||||
#define CMD_NOP 0xFFFFFF5B
|
||||
#define CMD_SHA1 0xFFFFFF5C
|
||||
#define CMD_HMAC 0xFFFFFF5D
|
||||
#define CMD_LAST_ 0xFFFFFF5E
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* additional registers for BT81x */
|
||||
#define REG_ADAPTIVE_FRAMERATE 0x30257cUL
|
||||
#define REG_PLAYBACK_PAUSE 0x3025ecUL
|
||||
#define REG_FLASH_STATUS 0x3025f0UL
|
||||
#define REG_FLASH_SIZE 0x309024UL
|
||||
#define REG_PLAY_CONTROL 0x30914eUL
|
||||
#define REG_COPRO_PATCH_DTR 0x309162UL
|
||||
|
||||
|
||||
/* BT81x graphics engine specific macros */
|
||||
#define BITMAP_EXT_FORMAT(format) ((46UL<<24)|(((format)&65535UL)<<0))
|
||||
#define BITMAP_SWIZZLE(r,g,b,a) ((47UL<<24)|(((r)&7UL)<<9)|(((g)&7UL)<<6)|(((b)&7UL)<<3)|(((a)&7UL)<<0))
|
||||
#define BITMAP_SOURCE2(flash_or_ram, addr) ((1UL<<24)|((flash_or_ram) << 23)|(((addr)&8388607UL)<<0))
|
||||
#define INT_FRR() ((48UL<<24))
|
||||
|
||||
#undef BITMAP_TRANSFORM_A
|
||||
#undef BITMAP_TRANSFORM_B
|
||||
#undef BITMAP_TRANSFORM_D
|
||||
#undef BITMAP_TRANSFORM_E
|
||||
|
||||
#define BITMAP_TRANSFORM_A_EXT(p,v) ((21UL<<24)|(((p)&1UL)<<17)|(((v)&131071UL)<<0))
|
||||
#define BITMAP_TRANSFORM_B_EXT(p,v) ((22UL<<24)|(((p)&1UL)<<17)|(((v)&131071UL)<<0))
|
||||
#define BITMAP_TRANSFORM_D_EXT(p,v) ((24UL<<24)|(((p)&1UL)<<17)|(((v)&131071UL)<<0))
|
||||
#define BITMAP_TRANSFORM_E_EXT(p,v) ((25UL<<24)|(((p)&1UL)<<17)|(((v)&131071UL)<<0))
|
||||
|
||||
#define BITMAP_TRANSFORM_A(a) BITMAP_TRANSFORM_A_EXT(0,a)
|
||||
#define BITMAP_TRANSFORM_B(b) BITMAP_TRANSFORM_B_EXT(0,b)
|
||||
#define BITMAP_TRANSFORM_D(d) BITMAP_TRANSFORM_D_EXT(0,d)
|
||||
#define BITMAP_TRANSFORM_E(e) BITMAP_TRANSFORM_E_EXT(0,e)
|
||||
|
||||
#endif
|
||||
|
||||
/* ----------------- FT81x / BT81x exclusive definitions -----------------*/
|
||||
#if defined (FT81X_ENABLE)
|
||||
|
||||
|
||||
/* Host commands */
|
||||
#define EVE_CLKSEL 0x61 /* configure system clock */
|
||||
#define EVE_RST_PULSE 0x68 /* reset core - all registers default and processors reset */
|
||||
#define EVE_PINDRIVE 0x70 /* setup drive strength for various pins */
|
||||
#define EVE_PIN_PD_STATE 0x71 /* setup how pins behave during power down */
|
||||
|
||||
|
||||
/* Memory definitions */
|
||||
#define EVE_RAM_G 0x000000UL
|
||||
#define EVE_ROM_CHIPID 0x0C0000UL
|
||||
#define EVE_ROM_FONT 0x1E0000UL
|
||||
#define EVE_ROM_FONT_ADDR 0x2FFFFCUL
|
||||
#define EVE_RAM_DL 0x300000UL
|
||||
#define EVE_RAM_REG 0x302000UL
|
||||
#define EVE_RAM_CMD 0x308000UL
|
||||
|
||||
|
||||
/* Memory buffer sizes */
|
||||
#define EVE_RAM_G_SIZE 1024*1024L
|
||||
#define EVE_CMDFIFO_SIZE 4*1024L
|
||||
#define EVE_RAM_DL_SIZE 8*1024L
|
||||
|
||||
|
||||
/* various additional defines for FT81x */
|
||||
#define EVE_ADC_DIFFERENTIAL 1UL
|
||||
#define EVE_ADC_SINGLE_ENDED 0UL
|
||||
|
||||
#define EVE_INT_G8 18UL
|
||||
#define EVE_INT_L8C 12UL
|
||||
#define EVE_INT_VGA 13UL
|
||||
|
||||
#define EVE_OPT_MEDIAFIFO 16UL
|
||||
#define EVE_OPT_FULLSCREEN 8UL
|
||||
#define EVE_OPT_NOTEAR 4UL
|
||||
#define EVE_OPT_SOUND 32UL
|
||||
|
||||
#define EVE_PALETTED565 14UL
|
||||
#define EVE_PALETTED4444 15UL
|
||||
#define EVE_PALETTED8 16UL
|
||||
#define EVE_L2 17UL
|
||||
|
||||
|
||||
/* additional commands for FT81x */
|
||||
#define CMD_MEDIAFIFO 0xFFFFFF39
|
||||
#define CMD_PLAYVIDEO 0xFFFFFF3A
|
||||
#define CMD_ROMFONT 0xFFFFFF3F
|
||||
#define CMD_SETBASE 0xFFFFFF38
|
||||
#define CMD_SETBITMAP 0xFFFFFF43
|
||||
#define CMD_SETFONT2 0xFFFFFF3B
|
||||
#define CMD_SETROTATE 0xFFFFFF36
|
||||
#define CMD_SETSCRATCH 0xFFFFFF3C
|
||||
#define CMD_SNAPSHOT2 0xFFFFFF37
|
||||
#define CMD_VIDEOFRAME 0xFFFFFF41
|
||||
#define CMD_VIDEOSTART 0xFFFFFF40
|
||||
|
||||
|
||||
/* the following are undocumented commands that therefore should not be used */
|
||||
#if 0
|
||||
#define CMD_CSKETCH 0xFFFFFF35
|
||||
#define CMD_INT_RAMSHARED 0xFFFFFF3D
|
||||
#define CMD_INT_SWLOADIMAGE 0xFFFFFF3E
|
||||
#endif
|
||||
|
||||
|
||||
/* Register definitions */
|
||||
#define REG_ANA_COMP 0x302184UL /* only listed in datasheet */
|
||||
#define REG_BIST_EN 0x302174UL /* only listed in datasheet */
|
||||
#define REG_CLOCK 0x302008UL
|
||||
#define REG_CMDB_SPACE 0x302574UL
|
||||
#define REG_CMDB_WRITE 0x302578UL
|
||||
#define REG_CMD_DL 0x302100UL
|
||||
#define REG_CMD_READ 0x3020f8UL
|
||||
#define REG_CMD_WRITE 0x3020fcUL
|
||||
#define REG_CPURESET 0x302020UL
|
||||
#define REG_CSPREAD 0x302068UL
|
||||
#define REG_CTOUCH_EXTENDED 0x302108UL
|
||||
#define REG_CTOUCH_TOUCH0_XY 0x302124UL /* only listed in datasheet */
|
||||
#define REG_CTOUCH_TOUCH4_X 0x30216cUL
|
||||
#define REG_CTOUCH_TOUCH4_Y 0x302120UL
|
||||
#define REG_CTOUCH_TOUCH1_XY 0x30211cUL
|
||||
#define REG_CTOUCH_TOUCH2_XY 0x30218cUL
|
||||
#define REG_CTOUCH_TOUCH3_XY 0x302190UL
|
||||
#define REG_TOUCH_CONFIG 0x302168UL
|
||||
#define REG_DATESTAMP 0x302564UL /* only listed in datasheet */
|
||||
#define REG_DITHER 0x302060UL
|
||||
#define REG_DLSWAP 0x302054UL
|
||||
#define REG_FRAMES 0x302004UL
|
||||
#define REG_FREQUENCY 0x30200cUL
|
||||
#define REG_GPIO 0x302094UL
|
||||
#define REG_GPIOX 0x30209cUL
|
||||
#define REG_GPIOX_DIR 0x302098UL
|
||||
#define REG_GPIO_DIR 0x302090UL
|
||||
#define REG_HCYCLE 0x30202cUL
|
||||
#define REG_HOFFSET 0x302030UL
|
||||
#define REG_HSIZE 0x302034UL
|
||||
#define REG_HSYNC0 0x302038UL
|
||||
#define REG_HSYNC1 0x30203cUL
|
||||
#define REG_ID 0x302000UL
|
||||
#define REG_INT_EN 0x3020acUL
|
||||
#define REG_INT_FLAGS 0x3020a8UL
|
||||
#define REG_INT_MASK 0x3020b0UL
|
||||
#define REG_MACRO_0 0x3020d8UL
|
||||
#define REG_MACRO_1 0x3020dcUL
|
||||
#define REG_MEDIAFIFO_READ 0x309014UL /* only listed in programmers guide */
|
||||
#define REG_MEDIAFIFO_WRITE 0x309018UL /* only listed in programmers guide */
|
||||
#define REG_OUTBITS 0x30205cUL
|
||||
#define REG_PCLK 0x302070UL
|
||||
#define REG_PCLK_POL 0x30206cUL
|
||||
#define REG_PLAY 0x30208cUL
|
||||
#define REG_PLAYBACK_FORMAT 0x3020c4UL
|
||||
#define REG_PLAYBACK_FREQ 0x3020c0UL
|
||||
#define REG_PLAYBACK_LENGTH 0x3020b8UL
|
||||
#define REG_PLAYBACK_LOOP 0x3020c8UL
|
||||
#define REG_PLAYBACK_PLAY 0x3020ccUL
|
||||
#define REG_PLAYBACK_READPTR 0x3020bcUL
|
||||
#define REG_PLAYBACK_START 0x3020b4UL
|
||||
#define REG_PWM_DUTY 0x3020d4UL
|
||||
#define REG_PWM_HZ 0x3020d0UL
|
||||
#define REG_RENDERMODE 0x302010UL /* only listed in datasheet */
|
||||
#define REG_ROTATE 0x302058UL
|
||||
#define REG_SNAPFORMAT 0x30201cUL /* only listed in datasheet */
|
||||
#define REG_SNAPSHOT 0x302018UL /* only listed in datasheet */
|
||||
#define REG_SNAPY 0x302014UL /* only listed in datasheet */
|
||||
#define REG_SOUND 0x302088UL
|
||||
#define REG_SPI_WIDTH 0x302188UL /* listed with false offset in programmers guide V1.1 */
|
||||
#define REG_SWIZZLE 0x302064UL
|
||||
#define REG_TAG 0x30207cUL
|
||||
#define REG_TAG_X 0x302074UL
|
||||
#define REG_TAG_Y 0x302078UL
|
||||
#define REG_TAP_CRC 0x302024UL /* only listed in datasheet */
|
||||
#define REG_TAP_MASK 0x302028UL /* only listed in datasheet */
|
||||
#define REG_TOUCH_ADC_MODE 0x302108UL
|
||||
#define REG_TOUCH_CHARGE 0x30210cUL
|
||||
#define REG_TOUCH_DIRECT_XY 0x30218cUL
|
||||
#define REG_TOUCH_DIRECT_Z1Z2 0x302190UL
|
||||
#define REG_TOUCH_MODE 0x302104UL
|
||||
#define REG_TOUCH_OVERSAMPLE 0x302114UL
|
||||
#define REG_TOUCH_RAW_XY 0x30211cUL
|
||||
#define REG_TOUCH_RZ 0x302120UL
|
||||
#define REG_TOUCH_RZTHRESH 0x302118UL
|
||||
#define REG_TOUCH_SCREEN_XY 0x302124UL
|
||||
#define REG_TOUCH_SETTLE 0x302110UL
|
||||
#define REG_TOUCH_TAG 0x30212cUL
|
||||
#define REG_TOUCH_TAG1 0x302134UL /* only listed in datasheet */
|
||||
#define REG_TOUCH_TAG1_XY 0x302130UL /* only listed in datasheet */
|
||||
#define REG_TOUCH_TAG2 0x30213cUL /* only listed in datasheet */
|
||||
#define REG_TOUCH_TAG2_XY 0x302138UL /* only listed in datasheet */
|
||||
#define REG_TOUCH_TAG3 0x302144UL /* only listed in datasheet */
|
||||
#define REG_TOUCH_TAG3_XY 0x302140UL /* only listed in datasheet */
|
||||
#define REG_TOUCH_TAG4 0x30214cUL /* only listed in datasheet */
|
||||
#define REG_TOUCH_TAG4_XY 0x302148UL /* only listed in datasheet */
|
||||
#define REG_TOUCH_TAG_XY 0x302128UL
|
||||
#define REG_TOUCH_TRANSFORM_A 0x302150UL
|
||||
#define REG_TOUCH_TRANSFORM_B 0x302154UL
|
||||
#define REG_TOUCH_TRANSFORM_C 0x302158UL
|
||||
#define REG_TOUCH_TRANSFORM_D 0x30215cUL
|
||||
#define REG_TOUCH_TRANSFORM_E 0x302160UL
|
||||
#define REG_TOUCH_TRANSFORM_F 0x302164UL
|
||||
#define REG_TRACKER 0x309000UL /* only listed in programmers guide */
|
||||
#define REG_TRACKER_1 0x309004UL /* only listed in programmers guide */
|
||||
#define REG_TRACKER_2 0x309008UL /* only listed in programmers guide */
|
||||
#define REG_TRACKER_3 0x30900cUL /* only listed in programmers guide */
|
||||
#define REG_TRACKER_4 0x309010UL /* only listed in programmers guide */
|
||||
#define REG_TRIM 0x302180UL
|
||||
#define REG_VCYCLE 0x302040UL
|
||||
#define REG_VOFFSET 0x302044UL
|
||||
#define REG_VOL_PB 0x302080UL
|
||||
#define REG_VOL_SOUND 0x302084UL
|
||||
#define REG_VSIZE 0x302048UL
|
||||
#define REG_VSYNC0 0x30204cUL
|
||||
#define REG_VSYNC1 0x302050UL
|
||||
|
||||
#if 0
|
||||
#define REG_BUSYBITS 0x3020e8UL /* only listed as "reserved" in datasheet */
|
||||
#define REG_CRC 0x302178UL /* only listed as "reserved" in datasheet */
|
||||
#define REG_SPI_EARLY_TX 0x30217cUL /* only listed as "reserved" in datasheet */
|
||||
#define REG_ROMSUB_SEL 0x3020f0UL /* only listed as "reserved" in datasheet */
|
||||
#define REG_TOUCH_FAULT 0x302170UL /* only listed as "reserved" in datasheet */
|
||||
#endif
|
||||
|
||||
|
||||
/* FT81x graphics engine specific macros useful for static display list generation */
|
||||
|
||||
/* beware, these are different to FTDIs implementation as these take the original values as parameters and not only the upper bits */
|
||||
#define BITMAP_LAYOUT_H(linestride,height) ((40UL<<24)|((((linestride&0xC00)>>10)&3UL)<<2)|((((height&0x600)>>9)&3UL)<<0))
|
||||
#define BITMAP_SIZE_H(width,height) ((41UL<<24)|((((width&0x600)>>9)&3UL)<<2)|((((height&0x600)>>9)&3UL)<<0))
|
||||
|
||||
#define BITMAP_SOURCE(addr) ((1UL<<24)|(((addr)&4194303UL)<<0))
|
||||
//#define NOP() ((45UL<<24))
|
||||
#define PALETTE_SOURCE(addr) ((42UL<<24)|(((addr)&4194303UL)<<0))
|
||||
#define SCISSOR_SIZE(width,height) ((28UL<<24)|(((width)&4095UL)<<12)|(((height)&4095UL)<<0))
|
||||
#define SCISSOR_XY(x,y) ((27UL<<24)|(((x)&2047UL)<<11)|(((y)&2047UL)<<0))
|
||||
#define VERTEX_FORMAT(frac) ((39UL<<24)|(((frac)&7UL)<<0))
|
||||
#define VERTEX_TRANSLATE_X(x) ((43UL<<24)|(((x)&131071UL)<<0))
|
||||
#define VERTEX_TRANSLATE_Y(y) ((44UL<<24)|(((y)&131071UL)<<0))
|
||||
|
||||
|
||||
|
||||
/* ----------------- FT80x exclusive definitions -----------------*/
|
||||
#else
|
||||
|
||||
/* Memory definitions */
|
||||
#define EVE_RAM_G 0x000000UL
|
||||
#define EVE_ROM_CHIPID 0x0C0000UL
|
||||
#define EVE_ROM_FONT 0x0BB23CUL
|
||||
#define EVE_ROM_FONT_ADDR 0x0FFFFCUL
|
||||
#define EVE_RAM_DL 0x100000UL
|
||||
#define EVE_RAM_PAL 0x102000UL
|
||||
#define EVE_RAM_CMD 0x108000UL
|
||||
#define EVE_RAM_SCREENSHOT 0x1C2000UL
|
||||
|
||||
|
||||
/* Memory buffer sizes */
|
||||
#define EVE_RAM_G_SIZE 256*1024L
|
||||
#define EVE_CMDFIFO_SIZE 4*1024L
|
||||
#define EVE_RAM_DL_SIZE 8*1024L
|
||||
#define EVE_RAM_PAL_SIZE 1*1024L
|
||||
|
||||
|
||||
/* Register definitions */
|
||||
#define REG_ID 0x102400UL
|
||||
#define REG_FRAMES 0x102404UL
|
||||
#define REG_CLOCK 0x102408UL
|
||||
#define REG_FREQUENCY 0x10240CUL
|
||||
#define REG_SCREENSHOT_EN 0x102410UL
|
||||
#define REG_SCREENSHOT_Y 0x102414UL
|
||||
#define REG_SCREENSHOT_START 0x102418UL
|
||||
#define REG_CPURESET 0x10241CUL
|
||||
#define REG_TAP_CRC 0x102420UL
|
||||
#define REG_TAP_MASK 0x102424UL
|
||||
#define REG_HCYCLE 0x102428UL
|
||||
#define REG_HOFFSET 0x10242CUL
|
||||
#define REG_HSIZE 0x102430UL
|
||||
#define REG_HSYNC0 0x102434UL
|
||||
#define REG_HSYNC1 0x102438UL
|
||||
#define REG_VCYCLE 0x10243CUL
|
||||
#define REG_VOFFSET 0x102440UL
|
||||
#define REG_VSIZE 0x102444UL
|
||||
#define REG_VSYNC0 0x102448UL
|
||||
#define REG_VSYNC1 0x10244CUL
|
||||
#define REG_DLSWAP 0x102450UL
|
||||
#define REG_ROTATE 0x102454UL
|
||||
#define REG_OUTBITS 0x102458UL
|
||||
#define REG_DITHER 0x10245CUL
|
||||
#define REG_SWIZZLE 0x102460UL
|
||||
#define REG_CSPREAD 0x102464UL
|
||||
#define REG_PCLK_POL 0x102468UL
|
||||
#define REG_PCLK 0x10246CUL
|
||||
#define REG_TAG_X 0x102470UL
|
||||
#define REG_TAG_Y 0x102474UL
|
||||
#define REG_TAG 0x102478UL
|
||||
#define REG_VOL_PB 0x10247CUL
|
||||
#define REG_VOL_SOUND 0x102480UL
|
||||
#define REG_SOUND 0x102484UL
|
||||
#define REG_PLAY 0x102488UL
|
||||
#define REG_GPIO_DIR 0x10248CUL
|
||||
#define REG_GPIO 0x102490UL
|
||||
#define REG_INT_FLAGS 0x102498UL
|
||||
#define REG_INT_EN 0x10249CUL
|
||||
#define REG_INT_MASK 0x1024A0UL
|
||||
#define REG_PLAYBACK_START 0x1024A4UL
|
||||
#define REG_PLAYBACK_LENGTH 0x1024A8UL
|
||||
#define REG_PLAYBACK_READPTR 0x1024ACUL
|
||||
#define REG_PLAYBACK_FREQ 0x1024B0UL
|
||||
#define REG_PLAYBACK_FORMAT 0x1024B4UL
|
||||
#define REG_PLAYBACK_LOOP 0x1024B8UL
|
||||
#define REG_PLAYBACK_PLAY 0x1024BCUL
|
||||
#define REG_PWM_HZ 0x1024C0UL
|
||||
#define REG_PWM_DUTY 0x1024C4UL
|
||||
#define REG_MACRO_0 0x1024C8UL
|
||||
#define REG_MACRO_1 0x1024CCUL
|
||||
#define REG_SCREENSHOT_BUSY 0x1024D8UL
|
||||
#define REG_CMD_READ 0x1024E4UL
|
||||
#define REG_CMD_WRITE 0x1024E8UL
|
||||
#define REG_CMD_DL 0x1024ECUL
|
||||
#define REG_TOUCH_MODE 0x1024F0UL
|
||||
#define REG_TOUCH_ADC_MODE 0x1024F4UL
|
||||
#define REG_TOUCH_CHARGE 0x1024F8UL
|
||||
#define REG_TOUCH_SETTLE 0x1024FCUL
|
||||
#define REG_TOUCH_OVERSAMPLE 0x102500UL
|
||||
#define REG_TOUCH_RZTHRESH 0x102504UL
|
||||
#define REG_TOUCH_RAW_XY 0x102508UL
|
||||
#define REG_TOUCH_RZ 0x10250CUL
|
||||
#define REG_TOUCH_SCREEN_XY 0x102510UL
|
||||
#define REG_TOUCH_TAG_XY 0x102514UL
|
||||
#define REG_TOUCH_TAG 0x102518UL
|
||||
#define REG_TOUCH_TRANSFORM_A 0x10251CUL
|
||||
#define REG_TOUCH_TRANSFORM_B 0x102520UL
|
||||
#define REG_TOUCH_TRANSFORM_C 0x102524UL
|
||||
#define REG_TOUCH_TRANSFORM_D 0x102528UL
|
||||
#define REG_TOUCH_TRANSFORM_E 0x10252CUL
|
||||
#define REG_TOUCH_TRANSFORM_F 0x102530UL
|
||||
#define REG_SCREENSHOT_READ 0x102554UL
|
||||
#define REG_TRIM 0x10256CUL
|
||||
#define REG_TOUCH_DIRECT_XY 0x102574UL
|
||||
#define REG_TOUCH_DIRECT_Z1Z2 0x102578UL
|
||||
#define REG_TRACKER 0x109000UL
|
||||
|
||||
/* FT80x graphics engine specific macros useful for static display list generation */
|
||||
#define BITMAP_SOURCE(addr) ((1UL<<24)|(((addr)&1048575UL)<<0))
|
||||
#define SCISSOR_SIZE(width,height) ((28UL<<24)|(((width)&1023UL)<<10)|(((height)&1023UL)<<0))
|
||||
#define SCISSOR_XY(x,y) ((27UL<<24)|(((x)&511UL)<<9)|(((y)&511UL)<<0))
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* EVE_H_ */
|
2313
lvgl_tft/EVE_commands.c
Normal file
2313
lvgl_tft/EVE_commands.c
Normal file
File diff suppressed because it is too large
Load diff
203
lvgl_tft/EVE_commands.h
Normal file
203
lvgl_tft/EVE_commands.h
Normal file
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
@file EVE_commands.h
|
||||
@brief contains FT8xx / BT8xx function prototypes
|
||||
@version 4.1 LvGL edition
|
||||
@date 2020-04-13
|
||||
@author Rudolph Riedel, David Jade
|
||||
|
||||
@section LICENSE
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016-2020 Rudolph Riedel and David Jade
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
@section History
|
||||
|
||||
4.1 LvGL edition
|
||||
|
||||
- This version is a heavily modified version of the MIT licensed FT81x code from https://github.com/RudolphRiedel/FT800-FT813
|
||||
This version is based on a fork by David Jade that added native SPI DMA support and stripped out non-ESP32 code.
|
||||
It has also been trimmed down to suit LvGL's needs. Extra features can be enabled by defining FT81X_FULL
|
||||
*/
|
||||
|
||||
#include "EVE.h"
|
||||
|
||||
#ifndef EVE_COMMANDS_H_
|
||||
#define EVE_COMMANDS_H_
|
||||
|
||||
#define BLOCK_TRANSFER_SIZE 3840 // block transfer size when write data to CMD buffer
|
||||
|
||||
void DELAY_MS(uint16_t ms);
|
||||
void EVE_pdn_set(void);
|
||||
void EVE_pdn_clear(void);
|
||||
void spi_acquire();
|
||||
void spi_release();
|
||||
|
||||
void EVE_cmdWrite(uint8_t command, uint8_t parameter);
|
||||
|
||||
uint8_t EVE_memRead8(uint32_t ftAddress);
|
||||
uint16_t EVE_memRead16(uint32_t ftAddress);
|
||||
uint32_t EVE_memRead32(uint32_t ftAddress);
|
||||
|
||||
void EVE_memWrite8(uint32_t ftAddress, uint8_t ftData8);
|
||||
void EVE_memWrite16(uint32_t ftAddress, uint16_t ftData16);
|
||||
void EVE_memWrite32(uint32_t ftAddress, uint32_t ftData32);
|
||||
|
||||
void EVE_memWrite_buffer(uint32_t ftAddress, const uint8_t *data, uint32_t len, bool LvGL_Flush);
|
||||
|
||||
uint8_t EVE_busy(void);
|
||||
|
||||
void EVE_get_cmdoffset(void);
|
||||
|
||||
|
||||
/* commands to operate on memory: */
|
||||
void EVE_cmd_memzero(uint32_t ptr, uint32_t num);
|
||||
void EVE_cmd_memset(uint32_t ptr, uint8_t value, uint32_t num);
|
||||
void EVE_cmd_memwrite(uint32_t dest, uint32_t num, const uint8_t *data);
|
||||
void EVE_cmd_memcpy(uint32_t dest, uint32_t src, uint32_t num);
|
||||
|
||||
#if FT81X_FULL
|
||||
/* commands for loading image data into FT8xx memory: */
|
||||
void EVE_cmd_inflate(uint32_t ptr, const uint8_t *data, uint16_t len);
|
||||
void EVE_cmd_loadimage(uint32_t ptr, uint32_t options, const uint8_t *data, uint16_t len);
|
||||
|
||||
#if defined (FT81X_ENABLE)
|
||||
void EVE_cmd_mediafifo(uint32_t ptr, uint32_t size);
|
||||
#endif
|
||||
#endif // FT81X_FULL
|
||||
|
||||
void EVE_cmd_start(void);
|
||||
void EVE_cmd_execute(void);
|
||||
|
||||
void EVE_start_cmd_burst(void);
|
||||
void EVE_end_cmd_burst(void);
|
||||
|
||||
void EVE_cmd_dl(uint32_t command);
|
||||
|
||||
|
||||
#if FT81X_FULL
|
||||
/* EVE3 commands */
|
||||
#if defined (BT81X_ENABLE)
|
||||
|
||||
void EVE_cmd_flashwrite(uint32_t ptr, uint32_t num, const uint8_t *data);
|
||||
void EVE_cmd_flashread(uint32_t dest, uint32_t src, uint32_t num);
|
||||
void EVE_cmd_flashupdate(uint32_t dest, uint32_t src, uint32_t num);
|
||||
void EVE_cmd_flasherase(void);
|
||||
void EVE_cmd_flashattach(void);
|
||||
void EVE_cmd_flashdetach(void);
|
||||
void EVE_cmd_flashspidesel(void);
|
||||
uint32_t EVE_cmd_flashfast(void);
|
||||
void EVE_cmd_flashspitx(uint32_t num, const uint8_t *data);
|
||||
void EVE_cmd_flashspirx(uint32_t dest, uint32_t num);
|
||||
void EVE_cmd_flashsource(uint32_t ptr);
|
||||
|
||||
void EVE_cmd_inflate2(uint32_t ptr, uint32_t options, const uint8_t *data, uint16_t len);
|
||||
void EVE_cmd_rotatearound(int32_t x0, int32_t y0, int32_t angle, int32_t scale);
|
||||
void EVE_cmd_animstart(int32_t ch, uint32_t aoptr, uint32_t loop);
|
||||
void EVE_cmd_animstop(int32_t ch);
|
||||
void EVE_cmd_animxy(int32_t ch, int16_t x0, int16_t y0);
|
||||
void EVE_cmd_animdraw(int32_t ch);
|
||||
void EVE_cmd_animframe(int16_t x0, int16_t y0, uint32_t aoptr, uint32_t frame);
|
||||
void EVE_cmd_gradienta(int16_t x0, int16_t y0, uint32_t argb0, int16_t x1, int16_t y1, uint32_t argb1);
|
||||
void EVE_cmd_fillwidth(uint32_t s);
|
||||
void EVE_cmd_appendf(uint32_t ptr, uint32_t num);
|
||||
|
||||
uint8_t EVE_init_flash(void);
|
||||
#endif
|
||||
|
||||
|
||||
/* commands to draw graphics objects: */
|
||||
|
||||
#if defined (BT81X_ENABLE)
|
||||
void EVE_cmd_text_var(int16_t x0, int16_t y0, int16_t font, uint16_t options, const char* text, uint8_t numargs, ...);
|
||||
void EVE_cmd_button_var(int16_t x0, int16_t y0, int16_t w0, int16_t h0, int16_t font, uint16_t options, const char* text, uint8_t num_args, ...);
|
||||
void EVE_cmd_toggle_var(int16_t x0, int16_t y0, int16_t w0, int16_t font, uint16_t options, uint16_t state, const char* text, uint8_t num_args, ...);
|
||||
#endif
|
||||
|
||||
void EVE_cmd_text(int16_t x0, int16_t y0, int16_t font, uint16_t options, const char* text);
|
||||
void EVE_cmd_button(int16_t x0, int16_t y0, int16_t w0, int16_t h0, int16_t font, uint16_t options, const char* text);
|
||||
void EVE_cmd_clock(int16_t x0, int16_t y0, int16_t r0, uint16_t options, uint16_t hours, uint16_t minutes, uint16_t seconds, uint16_t millisecs);
|
||||
void EVE_color_rgb(uint8_t red, uint8_t green, uint8_t blue);
|
||||
void EVE_cmd_bgcolor(uint32_t color);
|
||||
void EVE_cmd_fgcolor(uint32_t color);
|
||||
void EVE_cmd_gradcolor(uint32_t color);
|
||||
void EVE_cmd_gauge(int16_t x0, int16_t y0, int16_t r0, uint16_t options, uint16_t major, uint16_t minor, uint16_t val, uint16_t range);
|
||||
void EVE_cmd_gradient(int16_t x0, int16_t y0, uint32_t rgb0, int16_t x1, int16_t y1, uint32_t rgb1);
|
||||
void EVE_cmd_keys(int16_t x0, int16_t y0, int16_t w0, int16_t h0, int16_t font, uint16_t options, const char* text);
|
||||
void EVE_cmd_progress(int16_t x0, int16_t y0, int16_t w0, int16_t h0, uint16_t options, uint16_t val, uint16_t range);
|
||||
void EVE_cmd_scrollbar(int16_t x0, int16_t y0, int16_t w0, int16_t h0, uint16_t options, uint16_t val, uint16_t size, uint16_t range);
|
||||
void EVE_cmd_slider(int16_t x1, int16_t y1, int16_t w1, int16_t h1, uint16_t options, uint16_t val, uint16_t range);
|
||||
void EVE_cmd_dial(int16_t x0, int16_t y0, int16_t r0, uint16_t options, uint16_t val);
|
||||
void EVE_cmd_toggle(int16_t x0, int16_t y0, int16_t w0, int16_t font, uint16_t options, uint16_t state, const char* text);
|
||||
void EVE_cmd_number(int16_t x0, int16_t y0, int16_t font, uint16_t options, int32_t number);
|
||||
#endif // FT81X_FULL
|
||||
|
||||
#if defined (FT81X_ENABLE)
|
||||
#if FT81X_FULL
|
||||
void EVE_cmd_setbase(uint32_t base);
|
||||
#endif
|
||||
void EVE_cmd_setbitmap(uint32_t addr, uint16_t fmt, uint16_t width, uint16_t height);
|
||||
#endif
|
||||
|
||||
|
||||
#if FT81X_FULL
|
||||
void EVE_cmd_append(uint32_t ptr, uint32_t num);
|
||||
|
||||
|
||||
/* commands for setting the bitmap transform matrix: */
|
||||
void EVE_cmd_getmatrix(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, int32_t f);
|
||||
void EVE_cmd_translate(int32_t tx, int32_t ty);
|
||||
void EVE_cmd_scale(int32_t sx, int32_t sy);
|
||||
void EVE_cmd_rotate(int32_t ang);
|
||||
|
||||
|
||||
/* other commands: */
|
||||
void EVE_cmd_calibrate(void);
|
||||
void EVE_cmd_interrupt(uint32_t ms);
|
||||
void EVE_cmd_setfont(uint32_t font, uint32_t ptr);
|
||||
#if defined (FT81X_ENABLE)
|
||||
void EVE_cmd_romfont(uint32_t font, uint32_t romslot);
|
||||
void EVE_cmd_setfont2(uint32_t font, uint32_t ptr, uint32_t firstchar);
|
||||
void EVE_cmd_setrotate(uint32_t r);
|
||||
void EVE_cmd_setscratch(uint32_t handle);
|
||||
#endif
|
||||
void EVE_cmd_sketch(int16_t x0, int16_t y0, uint16_t w0, uint16_t h0, uint32_t ptr, uint16_t format);
|
||||
void EVE_cmd_snapshot(uint32_t ptr);
|
||||
#if defined (FT81X_ENABLE)
|
||||
void EVE_cmd_snapshot2(uint32_t fmt, uint32_t ptr, int16_t x0, int16_t y0, int16_t w0, int16_t h0);
|
||||
#endif
|
||||
void EVE_cmd_spinner(int16_t x0, int16_t y0, uint16_t style, uint16_t scale);
|
||||
void EVE_cmd_track(int16_t x0, int16_t y0, int16_t w0, int16_t h0, int16_t tag);
|
||||
|
||||
|
||||
/* commands that return values by writing to the command-fifo */
|
||||
uint32_t EVE_cmd_memcrc(uint32_t ptr, uint32_t num);
|
||||
uint32_t EVE_cmd_getptr(void);
|
||||
uint32_t EVE_cmd_regread(uint32_t ptr);
|
||||
void EVE_LIB_GetProps(uint32_t *pointer, uint32_t *width, uint32_t *height);
|
||||
|
||||
|
||||
/* meta-commands, sequences of several display-list entries condensed into simpler to use functions at the price of some overhead */
|
||||
void EVE_cmd_point(int16_t x0, int16_t y0, uint16_t size);
|
||||
void EVE_cmd_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t w0);
|
||||
void EVE_cmd_rect(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t corner);
|
||||
|
||||
void EVE_calibrate_manual(uint16_t height);
|
||||
#endif // FT81X_FULL
|
||||
|
||||
|
||||
/* startup FT8xx: */
|
||||
uint8_t EVE_init(void);
|
||||
|
||||
#endif /* EVE_COMMANDS_H_ */
|
1043
lvgl_tft/EVE_config.h
Normal file
1043
lvgl_tft/EVE_config.h
Normal file
File diff suppressed because it is too large
Load diff
323
lvgl_tft/FT81x.c
Normal file
323
lvgl_tft/FT81x.c
Normal file
|
@ -0,0 +1,323 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "FT81x.h"
|
||||
|
||||
#include "EVE.h"
|
||||
#include "EVE_commands.h"
|
||||
|
||||
/* some pre-definded colors */
|
||||
#define RED 0xff0000UL
|
||||
#define ORANGE 0xffa500UL
|
||||
#define GREEN 0x00ff00UL
|
||||
#define BLUE 0x0000ffUL
|
||||
#define BLUE_1 0x5dade2L
|
||||
#define YELLOW 0xffff00UL
|
||||
#define PINK 0xff00ffUL
|
||||
#define PURPLE 0x800080UL
|
||||
#define WHITE 0xffffffUL
|
||||
#define BLACK 0x000000UL
|
||||
|
||||
/* memory-map defines */
|
||||
#define SCREEN_BITMAP_ADDR 0x00000000 // full screen buffer (0x00000000 - 0x000BBE40)
|
||||
|
||||
uint8_t tft_active = 0;
|
||||
|
||||
void touch_calibrate(void)
|
||||
{
|
||||
|
||||
/* send pre-recorded touch calibration values, depending on the display the code is compiled for */
|
||||
|
||||
#if defined (EVE_CFAF240400C1_030SC)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x0000ed11);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0x00001139);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xfff76809);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0x00000000);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0x00010690);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0xfffadf2e);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_CFAF320240F_035T)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x00005614);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0x0000009e);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xfff43422);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0x0000001d);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0xffffbda4);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0x00f8f2ef);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_CFAF480128A0_039TC)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x00010485);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0x0000017f);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xfffb0bd3);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0x00000073);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0x0000e293);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0x00069904);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_CFAF800480E0_050SC)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x000107f9);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0xffffff8c);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xfff451ae);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0x000000d2);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0x0000feac);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0xfffcfaaf);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_PAF90)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x00000159);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0x0001019c);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xfff93625);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0x00010157);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0x00000000);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0x0000c101);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_RiTFT43)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x000062cd);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0xfffffe45);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xfff45e0a);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0x000001a3);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0x00005b33);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0xFFFbb870);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_EVE2_38)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x00007bed);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0x000001b0);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xfff60aa5);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0x00000095);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0xffffdcda);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0x00829c08);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_EVE2_35G)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x000109E4);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0x000007A6);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xFFEC1EBA);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0x0000072C);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0x0001096A);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0xFFF469CF);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_EVE2_43G)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x0000a1ff);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0x00000680);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xffe54cc2);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0xffffff53);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0x0000912c);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0xfffe628d);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_EVE2_50G)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x000109E4);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0x000007A6);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xFFEC1EBA);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0x0000072C);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0x0001096A);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0xFFF469CF);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_EVE2_70G)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x000105BC);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0xFFFFFA8A);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0x00004670);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0xFFFFFF75);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0x00010074);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0xFFFF14C8);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_NHD_35)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x0000f78b);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0x00000427);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xfffcedf8);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0xfffffba4);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0x0000f756);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0x0009279e);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_RVT70)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x000074df);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0x000000e6);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xfffd5474);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0x000001af);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0x00007e79);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0xffe9a63c);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_FT811CB_HY50HD)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 66353);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 712);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 4293876677);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 4294966157);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 67516);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 418276);
|
||||
#endif
|
||||
|
||||
#if defined (EVE_ADAM101)
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_A, 0x000101E3);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_B, 0x00000114);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_C, 0xFFF5EEBA);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_D, 0xFFFFFF5E);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_E, 0x00010226);
|
||||
EVE_memWrite32(REG_TOUCH_TRANSFORM_F, 0x0000C783);
|
||||
#endif
|
||||
|
||||
/* activate this if you are using a module for the first time or if you need to re-calibrate it */
|
||||
/* write down the numbers on the screen and either place them in one of the pre-defined blocks above or make a new block */
|
||||
// Note: requires FT81x_FULL to be defined
|
||||
#if 0
|
||||
/* calibrate touch and displays values to screen */
|
||||
EVE_cmd_dl(CMD_DLSTART);
|
||||
EVE_cmd_dl(DL_CLEAR_RGB | BLACK);
|
||||
EVE_cmd_dl(DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG);
|
||||
EVE_cmd_text((EVE_HSIZE/2), 50, 26, EVE_OPT_CENTER, "Please tap on the dot.");
|
||||
EVE_cmd_calibrate();
|
||||
EVE_cmd_dl(DL_DISPLAY);
|
||||
EVE_cmd_dl(CMD_SWAP);
|
||||
EVE_cmd_execute();
|
||||
|
||||
uint32_t touch_a, touch_b, touch_c, touch_d, touch_e, touch_f;
|
||||
|
||||
touch_a = EVE_memRead32(REG_TOUCH_TRANSFORM_A);
|
||||
touch_b = EVE_memRead32(REG_TOUCH_TRANSFORM_B);
|
||||
touch_c = EVE_memRead32(REG_TOUCH_TRANSFORM_C);
|
||||
touch_d = EVE_memRead32(REG_TOUCH_TRANSFORM_D);
|
||||
touch_e = EVE_memRead32(REG_TOUCH_TRANSFORM_E);
|
||||
touch_f = EVE_memRead32(REG_TOUCH_TRANSFORM_F);
|
||||
|
||||
EVE_cmd_dl(CMD_DLSTART);
|
||||
EVE_cmd_dl(DL_CLEAR_RGB | BLACK);
|
||||
EVE_cmd_dl(DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG);
|
||||
EVE_cmd_dl(TAG(0));
|
||||
|
||||
EVE_cmd_text(5, 15, 26, 0, "TOUCH_TRANSFORM_A:");
|
||||
EVE_cmd_text(5, 30, 26, 0, "TOUCH_TRANSFORM_B:");
|
||||
EVE_cmd_text(5, 45, 26, 0, "TOUCH_TRANSFORM_C:");
|
||||
EVE_cmd_text(5, 60, 26, 0, "TOUCH_TRANSFORM_D:");
|
||||
EVE_cmd_text(5, 75, 26, 0, "TOUCH_TRANSFORM_E:");
|
||||
EVE_cmd_text(5, 90, 26, 0, "TOUCH_TRANSFORM_F:");
|
||||
|
||||
#if defined (FT81X_ENABLE)
|
||||
EVE_cmd_setbase(16L); /* FT81x only */
|
||||
EVE_cmd_number(310, 15, 26, EVE_OPT_RIGHTX|8, touch_a);
|
||||
EVE_cmd_number(310, 30, 26, EVE_OPT_RIGHTX|8, touch_b);
|
||||
EVE_cmd_number(310, 45, 26, EVE_OPT_RIGHTX|8, touch_c);
|
||||
EVE_cmd_number(310, 60, 26, EVE_OPT_RIGHTX|8, touch_d);
|
||||
EVE_cmd_number(310, 75, 26, EVE_OPT_RIGHTX|8, touch_e);
|
||||
EVE_cmd_number(310, 90, 26, EVE_OPT_RIGHTX|8, touch_f);
|
||||
#else
|
||||
EVE_cmd_number(310, 15, 26, EVE_OPT_RIGHTX, touch_a);
|
||||
EVE_cmd_number(310, 30, 26, EVE_OPT_RIGHTX, touch_b);
|
||||
EVE_cmd_number(310, 45, 26, EVE_OPT_RIGHTX, touch_c);
|
||||
EVE_cmd_number(310, 60, 26, EVE_OPT_RIGHTX, touch_d);
|
||||
EVE_cmd_number(310, 75, 26, EVE_OPT_RIGHTX, touch_e);
|
||||
EVE_cmd_number(310, 90, 26, EVE_OPT_RIGHTX, touch_f);
|
||||
#endif
|
||||
|
||||
EVE_cmd_dl(DL_DISPLAY); /* instruct the graphics processor to show the list */
|
||||
EVE_cmd_dl(CMD_SWAP); /* make this list active */
|
||||
EVE_cmd_execute();
|
||||
|
||||
while(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// set up a display list for a fullscreen writable bitmap
|
||||
void TFT_bitmap_display(void)
|
||||
{
|
||||
if(tft_active != 0)
|
||||
{
|
||||
EVE_start_cmd_burst(); /* start writing to the cmd-fifo as one stream of bytes, only sending the address once */
|
||||
|
||||
EVE_cmd_dl(CMD_DLSTART); /* start the display list */
|
||||
|
||||
EVE_cmd_dl(DL_CLEAR_RGB | BLACK); /* set the default clear color to black */
|
||||
EVE_cmd_dl(DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG); /* clear the screen - this and the previous prevent artifacts between lists, Attributes are the color, stencil and tag buffers */
|
||||
|
||||
EVE_cmd_dl(TAG(0));
|
||||
|
||||
// fullscreen bitmap for memory-mapped direct access
|
||||
EVE_cmd_dl(TAG(20));
|
||||
EVE_cmd_setbitmap(SCREEN_BITMAP_ADDR, EVE_RGB565, EVE_HSIZE, EVE_VSIZE);
|
||||
EVE_cmd_dl(DL_BEGIN | EVE_BITMAPS);
|
||||
EVE_cmd_dl(VERTEX2F(0, 0));
|
||||
EVE_cmd_dl(DL_END);
|
||||
|
||||
EVE_cmd_dl(TAG(0));
|
||||
|
||||
EVE_cmd_dl(DL_DISPLAY); /* instruct the graphics processor to show the list */
|
||||
|
||||
EVE_cmd_dl(CMD_SWAP); /* make this list active */
|
||||
|
||||
EVE_end_cmd_burst(); /* stop writing to the cmd-fifo */
|
||||
|
||||
EVE_cmd_start(); /* order the command co-processor to start processing its FIFO queue but do not wait for completion */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FT81x_init(void)
|
||||
{
|
||||
gpio_pad_select_gpio(EVE_PDN);
|
||||
gpio_set_level(EVE_CS, 1);
|
||||
gpio_set_direction(EVE_PDN, GPIO_MODE_OUTPUT);
|
||||
|
||||
spi_acquire();
|
||||
|
||||
if(EVE_init())
|
||||
{
|
||||
tft_active = 1;
|
||||
|
||||
EVE_memWrite8(REG_PWM_DUTY, 0x30); /* setup backlight, range is from 0 = off to 0x80 = max */
|
||||
|
||||
touch_calibrate();
|
||||
|
||||
EVE_cmd_memset(SCREEN_BITMAP_ADDR, BLACK, SCREEN_BUFFER_SIZE); // clear screen buffer
|
||||
EVE_cmd_execute();
|
||||
|
||||
TFT_bitmap_display(); // set DL for fullscreen bitmap display
|
||||
}
|
||||
|
||||
spi_release();
|
||||
}
|
||||
|
||||
|
||||
// write fullscreen bitmap directly
|
||||
void TFT_WriteScreen(uint8_t* Bitmap)
|
||||
{
|
||||
EVE_memWrite_buffer(SCREEN_BITMAP_ADDR, Bitmap, SCREEN_BUFFER_SIZE, false);
|
||||
}
|
||||
|
||||
|
||||
// write bitmap directly, line-by-line
|
||||
void TFT_WriteBitmap(uint8_t* Bitmap, uint16_t X, uint16_t Y, uint16_t Width, uint16_t Height)
|
||||
{
|
||||
// calc base address
|
||||
uint32_t addr = SCREEN_BITMAP_ADDR + (Y * BYTES_PER_LINE) + (X * BYTES_PER_PIXEL);
|
||||
|
||||
// can we do a fast full width block transfer?
|
||||
if(X == 0 && Width == EVE_HSIZE)
|
||||
{
|
||||
EVE_memWrite_buffer(addr, Bitmap, (Height * BYTES_PER_LINE), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// line by line mode
|
||||
uint32_t bpl = Width * BYTES_PER_PIXEL;
|
||||
for (uint16_t i = 0; i < Height; i++)
|
||||
{
|
||||
EVE_memWrite_buffer(addr, Bitmap + (i * bpl), bpl, (i == Height - 1));
|
||||
addr += BYTES_PER_LINE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LittlevGL flush callback
|
||||
void FT81x_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
|
||||
{
|
||||
TFT_WriteBitmap((uint8_t*)color_map, area->x1, area->y1, lv_area_get_width(area), lv_area_get_height(area));
|
||||
}
|
17
lvgl_tft/FT81x.h
Normal file
17
lvgl_tft/FT81x.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef FT81X_H_
|
||||
#define FT81X_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
#include "../lvgl_helpers.h"
|
||||
|
||||
void FT81x_init(void);
|
||||
|
||||
void FT81x_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
|
||||
|
||||
#endif /* FT81X_H_ */
|
272
lvgl_tft/GC9A01.c
Normal file
272
lvgl_tft/GC9A01.c
Normal file
|
@ -0,0 +1,272 @@
|
|||
/**
|
||||
* @file GC9A01.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "GC9A01.h"
|
||||
#include "disp_spi.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "GC9A01"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */
|
||||
typedef struct {
|
||||
uint8_t cmd;
|
||||
uint8_t data[16];
|
||||
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
|
||||
} lcd_init_cmd_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void GC9A01_set_orientation(uint8_t orientation);
|
||||
|
||||
static void GC9A01_send_cmd(uint8_t cmd);
|
||||
static void GC9A01_send_data(void * data, uint16_t length);
|
||||
static void GC9A01_send_color(void * data, uint16_t length);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void GC9A01_init(void)
|
||||
{
|
||||
lcd_init_cmd_t GC_init_cmds[]={
|
||||
////////////////////////////////////////////
|
||||
{0xEF, {0}, 0},
|
||||
{0xEB, {0x14}, 1},
|
||||
|
||||
{0xFE, {0}, 0},
|
||||
{0xEF, {0}, 0},
|
||||
|
||||
{0xEB, {0x14}, 1},
|
||||
{0x84, {0x40}, 1},
|
||||
{0x85, {0xFF}, 1},
|
||||
{0x86, {0xFF}, 1},
|
||||
{0x87, {0xFF}, 1},
|
||||
{0x88, {0x0A}, 1},
|
||||
{0x89, {0x21}, 1},
|
||||
{0x8A, {0x00}, 1},
|
||||
{0x8B, {0x80}, 1},
|
||||
{0x8C, {0x01}, 1},
|
||||
{0x8D, {0x01}, 1},
|
||||
{0x8E, {0xFF}, 1},
|
||||
{0x8F, {0xFF}, 1},
|
||||
{0xB6, {0x00, 0x20}, 2},
|
||||
//call orientation
|
||||
{0x3A, {0x05}, 1},
|
||||
{0x90, {0x08, 0x08, 0X08, 0X08}, 4},
|
||||
{0xBD, {0x06}, 1},
|
||||
{0xBC, {0x00}, 1},
|
||||
{0xFF, {0x60, 0x01, 0x04}, 3},
|
||||
{0xC3, {0x13}, 1},
|
||||
{0xC4, {0x13}, 1},
|
||||
{0xC9, {0x22}, 1},
|
||||
{0xBE, {0x11}, 1},
|
||||
{0xE1, {0x10, 0x0E}, 2},
|
||||
{0xDF, {0x21, 0x0C, 0x02}, 3},
|
||||
{0xF0, {0x45, 0x09, 0x08, 0x08, 0x26, 0x2A}, 6},
|
||||
{0xF1, {0x43, 0x70, 0x72, 0x36, 0x37, 0x6F}, 6},
|
||||
{0xF2, {0x45, 0x09, 0x08, 0x08, 0x26, 0x2A}, 6},
|
||||
{0xF3, {0x43, 0x70, 0x72, 0x36, 0x37, 0x6F}, 6},
|
||||
{0xED, {0x1B, 0x0B}, 2},
|
||||
{0xAE, {0x77}, 1},
|
||||
{0xCD, {0x63}, 1},
|
||||
{0x70, {0x07, 0x07, 0x04, 0x0E, 0x0F, 0x09, 0x07, 0X08, 0x03}, 9},
|
||||
{0xE8, {0x34}, 1},
|
||||
{0x62, {0x18, 0x0D, 0x71, 0xED, 0x70, 0x70, 0x18, 0X0F, 0x71, 0xEF, 0x70, 0x70}, 12},
|
||||
{0x63, {0x18, 0x11, 0x71, 0xF1, 0x70, 0x70, 0x18, 0X13, 0x71, 0xF3, 0x70, 0x70}, 12},
|
||||
{0x64, {0x28, 0x29, 0xF1, 0x01, 0xF1, 0x00, 0x07}, 7},
|
||||
{0x66, {0x3C, 0x00, 0xCD, 0x67, 0x45, 0x45, 0x10, 0X00, 0x00, 0x00}, 10},
|
||||
{0x67, {0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x54, 0X10, 0x32, 0x98}, 10},
|
||||
{0x74, {0x10, 0x85, 0x80, 0x00, 0x00, 0x4E, 0x00}, 7},
|
||||
{0x98, {0x3E, 0x07}, 2},
|
||||
{0x35, {0}, 0},
|
||||
{0x21, {0}, 0},
|
||||
{0x11, {0}, 0x80}, //0x80 delay flag
|
||||
{0x29, {0}, 0x80}, //0x80 delay flag
|
||||
{0, {0}, 0xff}, //init end flag
|
||||
////////////////////////////////////////////
|
||||
|
||||
};
|
||||
|
||||
#if GC9A01_BCKL == 15
|
||||
gpio_config_t io_conf;
|
||||
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = GPIO_SEL_15;
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
gpio_config(&io_conf);
|
||||
#endif
|
||||
|
||||
//Initialize non-SPI GPIOs
|
||||
gpio_pad_select_gpio(GC9A01_DC);
|
||||
gpio_set_direction(GC9A01_DC, GPIO_MODE_OUTPUT);
|
||||
gpio_pad_select_gpio(GC9A01_RST);
|
||||
gpio_set_direction(GC9A01_RST, GPIO_MODE_OUTPUT);
|
||||
|
||||
#if GC9A01_ENABLE_BACKLIGHT_CONTROL
|
||||
gpio_pad_select_gpio(GC9A01_BCKL);
|
||||
gpio_set_direction(GC9A01_BCKL, GPIO_MODE_OUTPUT);
|
||||
#endif
|
||||
//Reset the display
|
||||
gpio_set_level(GC9A01_RST, 0);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
gpio_set_level(GC9A01_RST, 1);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
|
||||
ESP_LOGI(TAG, "Initialization.");
|
||||
|
||||
//Send all the commands
|
||||
uint16_t cmd = 0;
|
||||
while (GC_init_cmds[cmd].databytes!=0xff) {
|
||||
GC9A01_send_cmd(GC_init_cmds[cmd].cmd);
|
||||
GC9A01_send_data(GC_init_cmds[cmd].data, GC_init_cmds[cmd].databytes&0x1F);
|
||||
if (GC_init_cmds[cmd].databytes & 0x80) {
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
}
|
||||
cmd++;
|
||||
}
|
||||
|
||||
GC9A01_enable_backlight(true);
|
||||
|
||||
GC9A01_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION);
|
||||
|
||||
#if GC9A01_INVERT_COLORS == 1
|
||||
GC9A01_send_cmd(0x21);
|
||||
#else
|
||||
GC9A01_send_cmd(0x20);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void GC9A01_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
|
||||
{
|
||||
uint8_t data[4];
|
||||
|
||||
/*Column addresses*/
|
||||
GC9A01_send_cmd(0x2A); //0x2A
|
||||
data[0] = (area->x1 >> 8) & 0xFF;
|
||||
data[1] = area->x1 & 0xFF;
|
||||
data[2] = (area->x2 >> 8) & 0xFF;
|
||||
data[3] = area->x2 & 0xFF;
|
||||
GC9A01_send_data(data, 4);
|
||||
|
||||
/*Page addresses*/
|
||||
GC9A01_send_cmd(0x2B); //0x2B
|
||||
data[0] = (area->y1 >> 8) & 0xFF;
|
||||
data[1] = area->y1 & 0xFF;
|
||||
data[2] = (area->y2 >> 8) & 0xFF;
|
||||
data[3] = area->y2 & 0xFF;
|
||||
GC9A01_send_data(data, 4);
|
||||
|
||||
/*Memory write*/
|
||||
GC9A01_send_cmd(0x2C); //0x2C
|
||||
|
||||
|
||||
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
|
||||
|
||||
GC9A01_send_color((void*)color_map, size * 2);
|
||||
}
|
||||
|
||||
void GC9A01_enable_backlight(bool backlight)
|
||||
{
|
||||
#if GC9A01_ENABLE_BACKLIGHT_CONTROL
|
||||
ESP_LOGI(TAG, "%s backlight.", backlight ? "Enabling" : "Disabling");
|
||||
uint32_t tmp = 0;
|
||||
|
||||
#if (GC9A01_BCKL_ACTIVE_LVL==1)
|
||||
tmp = backlight ? 1 : 0;
|
||||
#else
|
||||
tmp = backlight ? 0 : 1;
|
||||
#endif
|
||||
|
||||
gpio_set_level(GC9A01_BCKL, tmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GC9A01_sleep_in()
|
||||
{
|
||||
uint8_t data[] = {0x08};
|
||||
GC9A01_send_cmd(0x10); //0x10 Enter Sleep Mode
|
||||
GC9A01_send_data(&data, 1);
|
||||
}
|
||||
|
||||
void GC9A01_sleep_out()
|
||||
{
|
||||
uint8_t data[] = {0x08};
|
||||
GC9A01_send_cmd(0x11); //0x11 Sleep OUT
|
||||
GC9A01_send_data(&data, 1);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
static void GC9A01_send_cmd(uint8_t cmd)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(GC9A01_DC, 0); /*Command mode*/
|
||||
disp_spi_send_data(&cmd, 1);
|
||||
}
|
||||
|
||||
static void GC9A01_send_data(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(GC9A01_DC, 1); /*Data mode*/
|
||||
disp_spi_send_data(data, length);
|
||||
}
|
||||
|
||||
static void GC9A01_send_color(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(GC9A01_DC, 1); /*Data mode*/
|
||||
disp_spi_send_colors(data, length);
|
||||
}
|
||||
|
||||
static void GC9A01_set_orientation(uint8_t orientation)
|
||||
{
|
||||
// ESP_ASSERT(orientation < 4);
|
||||
|
||||
const char *orientation_str[] = {
|
||||
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]);
|
||||
|
||||
#if defined CONFIG_LV_PREDEFINED_DISPLAY_M5STACK
|
||||
uint8_t data[] = {0x68, 0x68, 0x08, 0x08}; ///
|
||||
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_WROVER4)
|
||||
uint8_t data[] = {0x4C, 0x88, 0x28, 0xE8}; ///
|
||||
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE)
|
||||
uint8_t data[] = {0x08, 0xC8, 0x68, 0xA8}; ///ggggg
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]);
|
||||
|
||||
GC9A01_send_cmd(0x36);
|
||||
GC9A01_send_data((void *) &data[orientation], 1);
|
||||
}
|
65
lvgl_tft/GC9A01.h
Normal file
65
lvgl_tft/GC9A01.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* @file lv_templ.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GC9A01_H
|
||||
#define GC9A01_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
#include "../lvgl_helpers.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define GC9A01_DC CONFIG_LV_DISP_PIN_DC
|
||||
#define GC9A01_RST CONFIG_LV_DISP_PIN_RST
|
||||
#define GC9A01_BCKL CONFIG_LV_DISP_PIN_BCKL
|
||||
|
||||
#define GC9A01_ENABLE_BACKLIGHT_CONTROL CONFIG_LV_ENABLE_BACKLIGHT_CONTROL
|
||||
|
||||
#if CONFIG_LV_BACKLIGHT_ACTIVE_LVL
|
||||
#define GC9A01_BCKL_ACTIVE_LVL 1
|
||||
#else
|
||||
#define GC9A01_BCKL_ACTIVE_LVL 0
|
||||
#endif
|
||||
|
||||
#define GC9A01_INVERT_COLORS CONFIG_LV_INVERT_COLORS
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void GC9A01_init(void);
|
||||
void GC9A01_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
|
||||
void GC9A01_enable_backlight(bool backlight);
|
||||
void GC9A01_sleep_in(void);
|
||||
void GC9A01_sleep_out(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*GC9A01_H*/
|
1000
lvgl_tft/Kconfig
Normal file
1000
lvgl_tft/Kconfig
Normal file
File diff suppressed because it is too large
Load diff
4
lvgl_tft/component.mk
Normal file
4
lvgl_tft/component.mk
Normal file
|
@ -0,0 +1,4 @@
|
|||
# TFT drivers
|
||||
|
||||
COMPONENT_SRCDIRS := .
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
107
lvgl_tft/disp_driver.c
Normal file
107
lvgl_tft/disp_driver.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* @file disp_driver.c
|
||||
*/
|
||||
|
||||
#include "disp_driver.h"
|
||||
#include "disp_spi.h"
|
||||
|
||||
void disp_driver_init(void)
|
||||
{
|
||||
#if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341
|
||||
ili9341_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
|
||||
ili9481_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
|
||||
ili9488_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789
|
||||
st7789_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S
|
||||
st7735s_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357
|
||||
hx8357_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486
|
||||
ili9486_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107
|
||||
sh1107_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306
|
||||
ssd1306_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X
|
||||
FT81x_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820
|
||||
il3820_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875
|
||||
ra8875_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01
|
||||
GC9A01_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A
|
||||
jd79653a_init();
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D
|
||||
uc8151d_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
|
||||
{
|
||||
#if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341
|
||||
ili9341_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
|
||||
ili9481_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
|
||||
ili9488_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789
|
||||
st7789_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S
|
||||
st7735s_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357
|
||||
hx8357_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486
|
||||
ili9486_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107
|
||||
sh1107_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306
|
||||
ssd1306_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X
|
||||
FT81x_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820
|
||||
il3820_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875
|
||||
ra8875_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01
|
||||
GC9A01_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A
|
||||
jd79653a_lv_fb_flush(drv, area, color_map);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D
|
||||
uc8151d_lv_fb_flush(drv, area, color_map);
|
||||
#endif
|
||||
}
|
||||
|
||||
void disp_driver_rounder(lv_disp_drv_t * disp_drv, lv_area_t * area)
|
||||
{
|
||||
#if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306
|
||||
ssd1306_rounder(disp_drv, area);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107
|
||||
sh1107_rounder(disp_drv, area);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820
|
||||
il3820_rounder(disp_drv, area);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A
|
||||
jd79653a_lv_rounder_cb(disp_drv, area);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D
|
||||
uc8151d_lv_rounder_cb(disp_drv, area);
|
||||
#endif
|
||||
}
|
||||
|
||||
void disp_driver_set_px(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
#if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306
|
||||
ssd1306_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107
|
||||
sh1107_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820
|
||||
il3820_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A
|
||||
jd79653a_lv_set_fb_cb(disp_drv, buf, buf_w, x, y, color, opa);
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D
|
||||
uc8151d_lv_set_fb_cb(disp_drv, buf, buf_w, x, y, color, opa);
|
||||
#endif
|
||||
}
|
86
lvgl_tft/disp_driver.h
Normal file
86
lvgl_tft/disp_driver.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* @file disp_driver.h
|
||||
*/
|
||||
|
||||
#ifndef DISP_DRIVER_H
|
||||
#define DISP_DRIVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
#if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341
|
||||
#include "ili9341.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
|
||||
#include "ili9481.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
|
||||
#include "ili9488.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789
|
||||
#include "st7789.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S
|
||||
#include "st7735s.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357
|
||||
#include "hx8357.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486
|
||||
#include "ili9486.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107
|
||||
#include "sh1107.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306
|
||||
#include "ssd1306.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X
|
||||
#include "FT81x.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820
|
||||
#include "il3820.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875
|
||||
#include "ra8875.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01
|
||||
#include "GC9A01.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A
|
||||
#include "jd79653a.h"
|
||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D
|
||||
#include "uc8151d.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/* Initialize display */
|
||||
void disp_driver_init(void);
|
||||
|
||||
/* Display flush callback */
|
||||
void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
|
||||
|
||||
/* Display rounder callback, used with monochrome dispays */
|
||||
void disp_driver_rounder(lv_disp_drv_t * disp_drv, lv_area_t * area);
|
||||
|
||||
/* Display set_px callback, used with monochrome dispays */
|
||||
void disp_driver_set_px(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t color, lv_opa_t opa);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*DISP_DRIVER_H*/
|
320
lvgl_tft/disp_spi.c
Normal file
320
lvgl_tft/disp_spi.c
Normal file
|
@ -0,0 +1,320 @@
|
|||
/**
|
||||
* @file disp_spi.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "esp_system.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define TAG "disp_spi"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
#include "disp_spi.h"
|
||||
#include "disp_driver.h"
|
||||
|
||||
#include "../lvgl_helpers.h"
|
||||
#include "../lvgl_spi_conf.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Notes about DMA spi_transaction_ext_t structure pooling
|
||||
*
|
||||
* An xQueue is used to hold a pool of reusable SPI spi_transaction_ext_t
|
||||
* structures that get used for all DMA SPI transactions. While an xQueue may
|
||||
* seem like overkill it is an already built-in RTOS feature that comes at
|
||||
* little cost. xQueues are also ISR safe if it ever becomes necessary to
|
||||
* access the pool in the ISR callback.
|
||||
*
|
||||
* When a DMA request is sent, a transaction structure is removed from the
|
||||
* pool, filled out, and passed off to the esp32 SPI driver. Later, when
|
||||
* servicing pending SPI transaction results, the transaction structure is
|
||||
* recycled back into the pool for later reuse. This matches the DMA SPI
|
||||
* transaction life cycle requirements of the esp32 SPI driver.
|
||||
*
|
||||
* When polling or synchronously sending SPI requests, and as required by the
|
||||
* esp32 SPI driver, all pending DMA transactions are first serviced. Then the
|
||||
* polling SPI request takes place.
|
||||
*
|
||||
* When sending an asynchronous DMA SPI request, if the pool is empty, some
|
||||
* small percentage of pending transactions are first serviced before sending
|
||||
* any new DMA SPI transactions. Not too many and not too few as this balance
|
||||
* controls DMA transaction latency.
|
||||
*
|
||||
* It is therefore not the design that all pending transactions must be
|
||||
* serviced and placed back into the pool with DMA SPI requests - that
|
||||
* will happen eventually. The pool just needs to contain enough to float some
|
||||
* number of in-flight SPI requests to speed up the overall DMA SPI data rate
|
||||
* and reduce transaction latency. If however a display driver uses some
|
||||
* polling SPI requests or calls disp_wait_for_pending_transactions() directly,
|
||||
* the pool will reach the full state more often and speed up DMA queuing.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define SPI_TRANSACTION_POOL_SIZE 50 /* maximum number of DMA transactions simultaneously in-flight */
|
||||
|
||||
/* DMA Transactions to reserve before queueing additional DMA transactions. A 1/10th seems to be a good balance. Too many (or all) and it will increase latency. */
|
||||
#define SPI_TRANSACTION_POOL_RESERVE_PERCENTAGE 10
|
||||
#if SPI_TRANSACTION_POOL_SIZE >= SPI_TRANSACTION_POOL_RESERVE_PERCENTAGE
|
||||
#define SPI_TRANSACTION_POOL_RESERVE (SPI_TRANSACTION_POOL_SIZE / SPI_TRANSACTION_POOL_RESERVE_PERCENTAGE)
|
||||
#else
|
||||
#define SPI_TRANSACTION_POOL_RESERVE 1 /* defines minimum size */
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void IRAM_ATTR spi_ready (spi_transaction_t *trans);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static spi_host_device_t spi_host;
|
||||
static spi_device_handle_t spi;
|
||||
static QueueHandle_t TransactionPool = NULL;
|
||||
static transaction_cb_t chained_post_cb;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
void disp_spi_add_device_config(spi_host_device_t host, spi_device_interface_config_t *devcfg)
|
||||
{
|
||||
spi_host=host;
|
||||
chained_post_cb=devcfg->post_cb;
|
||||
devcfg->post_cb=spi_ready;
|
||||
esp_err_t ret=spi_bus_add_device(host, devcfg, &spi);
|
||||
assert(ret==ESP_OK);
|
||||
}
|
||||
|
||||
void disp_spi_add_device(spi_host_device_t host)
|
||||
{
|
||||
disp_spi_add_device_with_speed(host, SPI_TFT_CLOCK_SPEED_HZ);
|
||||
}
|
||||
|
||||
void disp_spi_add_device_with_speed(spi_host_device_t host, int clock_speed_hz)
|
||||
{
|
||||
ESP_LOGI(TAG, "Adding SPI device");
|
||||
ESP_LOGI(TAG, "Clock speed: %dHz, mode: %d, CS pin: %d",
|
||||
clock_speed_hz, SPI_TFT_SPI_MODE, DISP_SPI_CS);
|
||||
|
||||
spi_device_interface_config_t devcfg={
|
||||
.clock_speed_hz = clock_speed_hz,
|
||||
.mode = SPI_TFT_SPI_MODE,
|
||||
.spics_io_num=DISP_SPI_CS, // CS pin
|
||||
.input_delay_ns=DISP_SPI_INPUT_DELAY_NS,
|
||||
.queue_size=SPI_TRANSACTION_POOL_SIZE,
|
||||
.pre_cb=NULL,
|
||||
.post_cb=NULL,
|
||||
#if defined(DISP_SPI_HALF_DUPLEX)
|
||||
.flags = SPI_DEVICE_NO_DUMMY | SPI_DEVICE_HALFDUPLEX, /* dummy bits should be explicitly handled via DISP_SPI_VARIABLE_DUMMY as needed */
|
||||
#else
|
||||
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
|
||||
.flags = 0,
|
||||
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875)
|
||||
.flags = SPI_DEVICE_NO_DUMMY,
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
disp_spi_add_device_config(host, &devcfg);
|
||||
|
||||
/* create the transaction pool and fill it with ptrs to spi_transaction_ext_t to reuse */
|
||||
if(TransactionPool == NULL) {
|
||||
TransactionPool = xQueueCreate(SPI_TRANSACTION_POOL_SIZE, sizeof(spi_transaction_ext_t*));
|
||||
assert(TransactionPool != NULL);
|
||||
for (size_t i = 0; i < SPI_TRANSACTION_POOL_SIZE; i++)
|
||||
{
|
||||
spi_transaction_ext_t* pTransaction = (spi_transaction_ext_t*)heap_caps_malloc(sizeof(spi_transaction_ext_t), MALLOC_CAP_DMA);
|
||||
assert(pTransaction != NULL);
|
||||
memset(pTransaction, 0, sizeof(spi_transaction_ext_t));
|
||||
xQueueSend(TransactionPool, &pTransaction, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void disp_spi_change_device_speed(int clock_speed_hz)
|
||||
{
|
||||
if (clock_speed_hz <= 0) {
|
||||
clock_speed_hz = SPI_TFT_CLOCK_SPEED_HZ;
|
||||
}
|
||||
ESP_LOGI(TAG, "Changing SPI device clock speed: %d", clock_speed_hz);
|
||||
disp_spi_remove_device();
|
||||
disp_spi_add_device_with_speed(spi_host, clock_speed_hz);
|
||||
}
|
||||
|
||||
void disp_spi_remove_device()
|
||||
{
|
||||
/* Wait for previous pending transaction results */
|
||||
disp_wait_for_pending_transactions();
|
||||
|
||||
esp_err_t ret=spi_bus_remove_device(spi);
|
||||
assert(ret==ESP_OK);
|
||||
}
|
||||
|
||||
void disp_spi_transaction(const uint8_t *data, size_t length,
|
||||
disp_spi_send_flag_t flags, uint8_t *out,
|
||||
uint64_t addr, uint8_t dummy_bits)
|
||||
{
|
||||
if (0 == length) {
|
||||
return;
|
||||
}
|
||||
|
||||
spi_transaction_ext_t t = {0};
|
||||
|
||||
/* transaction length is in bits */
|
||||
t.base.length = length * 8;
|
||||
|
||||
if (length <= 4 && data != NULL) {
|
||||
t.base.flags = SPI_TRANS_USE_TXDATA;
|
||||
memcpy(t.base.tx_data, data, length);
|
||||
} else {
|
||||
t.base.tx_buffer = data;
|
||||
}
|
||||
|
||||
if (flags & DISP_SPI_RECEIVE) {
|
||||
assert(out != NULL && (flags & (DISP_SPI_SEND_POLLING | DISP_SPI_SEND_SYNCHRONOUS)));
|
||||
t.base.rx_buffer = out;
|
||||
|
||||
#if defined(DISP_SPI_HALF_DUPLEX)
|
||||
t.base.rxlength = t.base.length;
|
||||
t.base.length = 0; /* no MOSI phase in half-duplex reads */
|
||||
#else
|
||||
t.base.rxlength = 0; /* in full-duplex mode, zero means same as tx length */
|
||||
#endif
|
||||
}
|
||||
|
||||
if (flags & DISP_SPI_ADDRESS_8) {
|
||||
t.address_bits = 8;
|
||||
} else if (flags & DISP_SPI_ADDRESS_16) {
|
||||
t.address_bits = 16;
|
||||
} else if (flags & DISP_SPI_ADDRESS_24) {
|
||||
t.address_bits = 24;
|
||||
} else if (flags & DISP_SPI_ADDRESS_32) {
|
||||
t.address_bits = 32;
|
||||
}
|
||||
if (t.address_bits) {
|
||||
t.base.addr = addr;
|
||||
t.base.flags |= SPI_TRANS_VARIABLE_ADDR;
|
||||
}
|
||||
|
||||
#if defined(DISP_SPI_HALF_DUPLEX)
|
||||
if (flags & DISP_SPI_MODE_DIO) {
|
||||
t.base.flags |= SPI_TRANS_MODE_DIO;
|
||||
} else if (flags & DISP_SPI_MODE_QIO) {
|
||||
t.base.flags |= SPI_TRANS_MODE_QIO;
|
||||
}
|
||||
|
||||
if (flags & DISP_SPI_MODE_DIOQIO_ADDR) {
|
||||
t.base.flags |= SPI_TRANS_MODE_DIOQIO_ADDR;
|
||||
}
|
||||
|
||||
if ((flags & DISP_SPI_VARIABLE_DUMMY) && dummy_bits) {
|
||||
t.dummy_bits = dummy_bits;
|
||||
t.base.flags |= SPI_TRANS_VARIABLE_DUMMY;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Save flags for pre/post transaction processing */
|
||||
t.base.user = (void *) flags;
|
||||
|
||||
/* Poll/Complete/Queue transaction */
|
||||
if (flags & DISP_SPI_SEND_POLLING) {
|
||||
disp_wait_for_pending_transactions(); /* before polling, all previous pending transactions need to be serviced */
|
||||
spi_device_polling_transmit(spi, (spi_transaction_t *) &t);
|
||||
} else if (flags & DISP_SPI_SEND_SYNCHRONOUS) {
|
||||
disp_wait_for_pending_transactions(); /* before synchronous queueing, all previous pending transactions need to be serviced */
|
||||
spi_device_transmit(spi, (spi_transaction_t *) &t);
|
||||
} else {
|
||||
|
||||
/* if necessary, ensure we can queue new transactions by servicing some previous transactions */
|
||||
if(uxQueueMessagesWaiting(TransactionPool) == 0) {
|
||||
spi_transaction_t *presult;
|
||||
while(uxQueueMessagesWaiting(TransactionPool) < SPI_TRANSACTION_POOL_RESERVE) {
|
||||
if (spi_device_get_trans_result(spi, &presult, 1) == ESP_OK) {
|
||||
xQueueSend(TransactionPool, &presult, portMAX_DELAY); /* back to the pool to be reused */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spi_transaction_ext_t *pTransaction = NULL;
|
||||
xQueueReceive(TransactionPool, &pTransaction, portMAX_DELAY);
|
||||
memcpy(pTransaction, &t, sizeof(t));
|
||||
if (spi_device_queue_trans(spi, (spi_transaction_t *) pTransaction, portMAX_DELAY) != ESP_OK) {
|
||||
xQueueSend(TransactionPool, &pTransaction, portMAX_DELAY); /* send failed transaction back to the pool to be reused */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void disp_wait_for_pending_transactions(void)
|
||||
{
|
||||
spi_transaction_t *presult;
|
||||
|
||||
while(uxQueueMessagesWaiting(TransactionPool) < SPI_TRANSACTION_POOL_SIZE) { /* service until the transaction reuse pool is full again */
|
||||
if (spi_device_get_trans_result(spi, &presult, 1) == ESP_OK) {
|
||||
xQueueSend(TransactionPool, &presult, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void disp_spi_acquire(void)
|
||||
{
|
||||
esp_err_t ret = spi_device_acquire_bus(spi, portMAX_DELAY);
|
||||
assert(ret == ESP_OK);
|
||||
}
|
||||
|
||||
void disp_spi_release(void)
|
||||
{
|
||||
spi_device_release_bus(spi);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void IRAM_ATTR spi_ready(spi_transaction_t *trans)
|
||||
{
|
||||
disp_spi_send_flag_t flags = (disp_spi_send_flag_t) trans->user;
|
||||
|
||||
if (flags & DISP_SPI_SIGNAL_FLUSH) {
|
||||
lv_disp_t * disp = NULL;
|
||||
|
||||
#if (LVGL_VERSION_MAJOR >= 7)
|
||||
disp = _lv_refr_get_disp_refreshing();
|
||||
#else /* Before v7 */
|
||||
disp = lv_refr_get_disp_refreshing();
|
||||
#endif
|
||||
|
||||
lv_disp_flush_ready(&disp->driver);
|
||||
}
|
||||
|
||||
if (chained_post_cb) {
|
||||
chained_post_cb(trans);
|
||||
}
|
||||
}
|
||||
|
81
lvgl_tft/disp_spi.h
Normal file
81
lvgl_tft/disp_spi.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* @file disp_spi.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DISP_SPI_H
|
||||
#define DISP_SPI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <driver/spi_master.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef enum _disp_spi_send_flag_t {
|
||||
DISP_SPI_SEND_QUEUED = 0x00000000,
|
||||
DISP_SPI_SEND_POLLING = 0x00000001,
|
||||
DISP_SPI_SEND_SYNCHRONOUS = 0x00000002,
|
||||
DISP_SPI_SIGNAL_FLUSH = 0x00000004,
|
||||
DISP_SPI_RECEIVE = 0x00000008,
|
||||
DISP_SPI_CMD_8 = 0x00000010, /* Reserved */
|
||||
DISP_SPI_CMD_16 = 0x00000020, /* Reserved */
|
||||
DISP_SPI_ADDRESS_8 = 0x00000040,
|
||||
DISP_SPI_ADDRESS_16 = 0x00000080,
|
||||
DISP_SPI_ADDRESS_24 = 0x00000100,
|
||||
DISP_SPI_ADDRESS_32 = 0x00000200,
|
||||
DISP_SPI_MODE_DIO = 0x00000400,
|
||||
DISP_SPI_MODE_QIO = 0x00000800,
|
||||
DISP_SPI_MODE_DIOQIO_ADDR = 0x00001000,
|
||||
DISP_SPI_VARIABLE_DUMMY = 0x00002000,
|
||||
} disp_spi_send_flag_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void disp_spi_add_device(spi_host_device_t host);
|
||||
void disp_spi_add_device_config(spi_host_device_t host, spi_device_interface_config_t *devcfg);
|
||||
void disp_spi_add_device_with_speed(spi_host_device_t host, int clock_speed_hz);
|
||||
void disp_spi_change_device_speed(int clock_speed_hz);
|
||||
void disp_spi_remove_device();
|
||||
|
||||
/* Important!
|
||||
All buffers should also be 32-bit aligned and DMA capable to prevent extra allocations and copying.
|
||||
When DMA reading (even in polling mode) the ESP32 always read in 4-byte chunks even if less is requested.
|
||||
Extra space will be zero filled. Always ensure the out buffer is large enough to hold at least 4 bytes!
|
||||
*/
|
||||
void disp_spi_transaction(const uint8_t *data, size_t length,
|
||||
disp_spi_send_flag_t flags, uint8_t *out, uint64_t addr, uint8_t dummy_bits);
|
||||
|
||||
void disp_wait_for_pending_transactions(void);
|
||||
void disp_spi_acquire(void);
|
||||
void disp_spi_release(void);
|
||||
|
||||
static inline void disp_spi_send_data(uint8_t *data, size_t length) {
|
||||
disp_spi_transaction(data, length, DISP_SPI_SEND_POLLING, NULL, 0, 0);
|
||||
}
|
||||
|
||||
static inline void disp_spi_send_colors(uint8_t *data, size_t length) {
|
||||
disp_spi_transaction(data, length,
|
||||
DISP_SPI_SEND_QUEUED | DISP_SPI_SIGNAL_FLUSH,
|
||||
NULL, 0, 0);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*DISP_SPI_H*/
|
310
lvgl_tft/hx8357.c
Normal file
310
lvgl_tft/hx8357.c
Normal file
|
@ -0,0 +1,310 @@
|
|||
/**
|
||||
* @file HX8357.c
|
||||
*
|
||||
* Roughly based on the Adafruit_HX8357_Library
|
||||
*
|
||||
* This library should work with:
|
||||
* Adafruit 3.5" TFT 320x480 + Touchscreen Breakout
|
||||
* http://www.adafruit.com/products/2050
|
||||
*
|
||||
* Adafruit TFT FeatherWing - 3.5" 480x320 Touchscreen for Feathers
|
||||
* https://www.adafruit.com/product/3651
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "hx8357.h"
|
||||
#include "disp_spi.h"
|
||||
#include "driver/gpio.h"
|
||||
#include <esp_log.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "HX8357"
|
||||
|
||||
#define MADCTL_MY 0x80 ///< Bottom to top
|
||||
#define MADCTL_MX 0x40 ///< Right to left
|
||||
#define MADCTL_MV 0x20 ///< Reverse Mode
|
||||
#define MADCTL_ML 0x10 ///< LCD refresh Bottom to top
|
||||
#define MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order
|
||||
#define MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order
|
||||
#define MADCTL_MH 0x04 ///< LCD refresh right to left
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */
|
||||
typedef struct {
|
||||
uint8_t cmd;
|
||||
uint8_t data[16];
|
||||
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
|
||||
} lcd_init_cmd_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void hx8357_send_cmd(uint8_t cmd);
|
||||
static void hx8357_send_data(void * data, uint16_t length);
|
||||
static void hx8357_send_color(void * data, uint16_t length);
|
||||
|
||||
|
||||
/**********************
|
||||
* INITIALIZATION ARRAYS
|
||||
**********************/
|
||||
// Taken from the Adafruit driver
|
||||
static const uint8_t
|
||||
initb[] = {
|
||||
HX8357B_SETPOWER, 3,
|
||||
0x44, 0x41, 0x06,
|
||||
HX8357B_SETVCOM, 2,
|
||||
0x40, 0x10,
|
||||
HX8357B_SETPWRNORMAL, 2,
|
||||
0x05, 0x12,
|
||||
HX8357B_SET_PANEL_DRIVING, 5,
|
||||
0x14, 0x3b, 0x00, 0x02, 0x11,
|
||||
HX8357B_SETDISPLAYFRAME, 1,
|
||||
0x0c, // 6.8mhz
|
||||
HX8357B_SETPANELRELATED, 1,
|
||||
0x01, // BGR
|
||||
0xEA, 3, // seq_undefined1, 3 args
|
||||
0x03, 0x00, 0x00,
|
||||
0xEB, 4, // undef2, 4 args
|
||||
0x40, 0x54, 0x26, 0xdb,
|
||||
HX8357B_SETGAMMA, 12,
|
||||
0x00, 0x15, 0x00, 0x22, 0x00, 0x08, 0x77, 0x26, 0x66, 0x22, 0x04, 0x00,
|
||||
HX8357_MADCTL, 1,
|
||||
0xC0,
|
||||
HX8357_COLMOD, 1,
|
||||
0x55,
|
||||
HX8357_PASET, 4,
|
||||
0x00, 0x00, 0x01, 0xDF,
|
||||
HX8357_CASET, 4,
|
||||
0x00, 0x00, 0x01, 0x3F,
|
||||
HX8357B_SETDISPMODE, 1,
|
||||
0x00, // CPU (DBI) and internal oscillation ??
|
||||
HX8357_SLPOUT, 0x80 + 120/5, // Exit sleep, then delay 120 ms
|
||||
HX8357_DISPON, 0x80 + 10/5, // Main screen turn on, delay 10 ms
|
||||
0 // END OF COMMAND LIST
|
||||
}, initd[] = {
|
||||
HX8357_SWRESET, 0x80 + 100/5, // Soft reset, then delay 10 ms
|
||||
HX8357D_SETC, 3,
|
||||
0xFF, 0x83, 0x57,
|
||||
0xFF, 0x80 + 500/5, // No command, just delay 300 ms
|
||||
HX8357_SETRGB, 4,
|
||||
0x80, 0x00, 0x06, 0x06, // 0x80 enables SDO pin (0x00 disables)
|
||||
HX8357D_SETCOM, 1,
|
||||
0x25, // -1.52V
|
||||
HX8357_SETOSC, 1,
|
||||
0x68, // Normal mode 70Hz, Idle mode 55 Hz
|
||||
HX8357_SETPANEL, 1,
|
||||
0x05, // BGR, Gate direction swapped
|
||||
HX8357_SETPWR1, 6,
|
||||
0x00, // Not deep standby
|
||||
0x15, // BT
|
||||
0x1C, // VSPR
|
||||
0x1C, // VSNR
|
||||
0x83, // AP
|
||||
0xAA, // FS
|
||||
HX8357D_SETSTBA, 6,
|
||||
0x50, // OPON normal
|
||||
0x50, // OPON idle
|
||||
0x01, // STBA
|
||||
0x3C, // STBA
|
||||
0x1E, // STBA
|
||||
0x08, // GEN
|
||||
HX8357D_SETCYC, 7,
|
||||
0x02, // NW 0x02
|
||||
0x40, // RTN
|
||||
0x00, // DIV
|
||||
0x2A, // DUM
|
||||
0x2A, // DUM
|
||||
0x0D, // GDON
|
||||
0x78, // GDOFF
|
||||
HX8357D_SETGAMMA, 34,
|
||||
0x02, 0x0A, 0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b,
|
||||
0x42, 0x3A, 0x27, 0x1B, 0x08, 0x09, 0x03, 0x02, 0x0A,
|
||||
0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b, 0x42, 0x3A,
|
||||
0x27, 0x1B, 0x08, 0x09, 0x03, 0x00, 0x01,
|
||||
HX8357_COLMOD, 1,
|
||||
0x55, // 16 bit
|
||||
HX8357_MADCTL, 1,
|
||||
0xC0,
|
||||
HX8357_TEON, 1,
|
||||
0x00, // TW off
|
||||
HX8357_TEARLINE, 2,
|
||||
0x00, 0x02,
|
||||
HX8357_SLPOUT, 0x80 + 150/5, // Exit Sleep, then delay 150 ms
|
||||
HX8357_DISPON, 0x80 + 50/5, // Main screen turn on, delay 50 ms
|
||||
0, // END OF COMMAND LIST
|
||||
};
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
static uint8_t displayType = HX8357D;
|
||||
|
||||
void hx8357_init(void)
|
||||
{
|
||||
//Initialize non-SPI GPIOs
|
||||
gpio_pad_select_gpio(HX8357_DC);
|
||||
gpio_set_direction(HX8357_DC, GPIO_MODE_OUTPUT);
|
||||
gpio_pad_select_gpio(HX8357_RST);
|
||||
gpio_set_direction(HX8357_RST, GPIO_MODE_OUTPUT);
|
||||
|
||||
#if HX8357_ENABLE_BACKLIGHT_CONTROL
|
||||
gpio_pad_select_gpio(HX8357_BCKL);
|
||||
gpio_set_direction(HX8357_BCKL, GPIO_MODE_OUTPUT);
|
||||
#endif
|
||||
|
||||
//Reset the display
|
||||
gpio_set_level(HX8357_RST, 0);
|
||||
vTaskDelay(10 / portTICK_RATE_MS);
|
||||
gpio_set_level(HX8357_RST, 1);
|
||||
vTaskDelay(120 / portTICK_RATE_MS);
|
||||
|
||||
ESP_LOGI(TAG, "Initialization.");
|
||||
|
||||
//Send all the commands
|
||||
const uint8_t *addr = (displayType == HX8357B) ? initb : initd;
|
||||
uint8_t cmd, x, numArgs;
|
||||
while((cmd = *addr++) > 0) { // '0' command ends list
|
||||
x = *addr++;
|
||||
numArgs = x & 0x7F;
|
||||
if (cmd != 0xFF) { // '255' is ignored
|
||||
if (x & 0x80) { // If high bit set, numArgs is a delay time
|
||||
hx8357_send_cmd(cmd);
|
||||
} else {
|
||||
hx8357_send_cmd(cmd);
|
||||
hx8357_send_data((void *) addr, numArgs);
|
||||
addr += numArgs;
|
||||
}
|
||||
}
|
||||
if (x & 0x80) { // If high bit set...
|
||||
vTaskDelay(numArgs * 5 / portTICK_RATE_MS); // numArgs is actually a delay time (5ms units)
|
||||
}
|
||||
}
|
||||
|
||||
hx8357_set_rotation(1);
|
||||
|
||||
#if HX8357_INVERT_DISPLAY
|
||||
hx8357_send_cmd(HX8357_INVON);;
|
||||
#endif
|
||||
|
||||
hx8357_enable_backlight(true);
|
||||
}
|
||||
|
||||
|
||||
void hx8357_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
|
||||
{
|
||||
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
|
||||
|
||||
/* Column addresses */
|
||||
uint8_t xb[] = {
|
||||
(uint8_t) (area->x1 >> 8) & 0xFF,
|
||||
(uint8_t) (area->x1) & 0xFF,
|
||||
(uint8_t) (area->x2 >> 8) & 0xFF,
|
||||
(uint8_t) (area->x2) & 0xFF,
|
||||
};
|
||||
|
||||
/* Page addresses */
|
||||
uint8_t yb[] = {
|
||||
(uint8_t) (area->y1 >> 8) & 0xFF,
|
||||
(uint8_t) (area->y1) & 0xFF,
|
||||
(uint8_t) (area->y2 >> 8) & 0xFF,
|
||||
(uint8_t) (area->y2) & 0xFF,
|
||||
};
|
||||
|
||||
/*Column addresses*/
|
||||
hx8357_send_cmd(HX8357_CASET);
|
||||
hx8357_send_data(xb, 4);
|
||||
|
||||
/*Page addresses*/
|
||||
hx8357_send_cmd(HX8357_PASET);
|
||||
hx8357_send_data(yb, 4);
|
||||
|
||||
/*Memory write*/
|
||||
hx8357_send_cmd(HX8357_RAMWR);
|
||||
hx8357_send_color((void*)color_map, size * 2);
|
||||
}
|
||||
|
||||
void hx8357_enable_backlight(bool backlight)
|
||||
{
|
||||
#if HX8357_ENABLE_BACKLIGHT_CONTROL
|
||||
ESP_LOGD(TAG, "%s backlight.\n", backlight ? "Enabling" : "Disabling");
|
||||
uint32_t tmp = 0;
|
||||
|
||||
#if (HX8357_BCKL_ACTIVE_LVL==1)
|
||||
tmp = backlight ? 1 : 0;
|
||||
#else
|
||||
tmp = backlight ? 0 : 1;
|
||||
#endif
|
||||
|
||||
gpio_set_level(HX8357_BCKL, tmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void hx8357_set_rotation(uint8_t r)
|
||||
{
|
||||
r = r & 3; // can't be higher than 3
|
||||
|
||||
switch(r) {
|
||||
case 0:
|
||||
r = MADCTL_MX | MADCTL_MY | MADCTL_RGB;
|
||||
break;
|
||||
case 1:
|
||||
r = MADCTL_MV | MADCTL_MY | MADCTL_RGB;
|
||||
break;
|
||||
case 2:
|
||||
r = MADCTL_RGB;
|
||||
break;
|
||||
case 3:
|
||||
r = MADCTL_MX | MADCTL_MV | MADCTL_RGB;
|
||||
break;
|
||||
}
|
||||
|
||||
hx8357_send_cmd(HX8357_MADCTL);
|
||||
hx8357_send_data(&r, 1);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
static void hx8357_send_cmd(uint8_t cmd)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(HX8357_DC, 0); /*Command mode*/
|
||||
disp_spi_send_data(&cmd, 1);
|
||||
}
|
||||
|
||||
|
||||
static void hx8357_send_data(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(HX8357_DC, 1); /*Data mode*/
|
||||
disp_spi_send_data(data, length);
|
||||
}
|
||||
|
||||
|
||||
static void hx8357_send_color(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(HX8357_DC, 1); /*Data mode*/
|
||||
disp_spi_send_colors(data, length);
|
||||
}
|
151
lvgl_tft/hx8357.h
Normal file
151
lvgl_tft/hx8357.h
Normal file
|
@ -0,0 +1,151 @@
|
|||
/**
|
||||
* @file HX8357.h
|
||||
*
|
||||
* Roughly based on the Adafruit_HX8357_Library
|
||||
*
|
||||
* This library should work with:
|
||||
* Adafruit 3.5" TFT 320x480 + Touchscreen Breakout
|
||||
* http://www.adafruit.com/products/2050
|
||||
*
|
||||
* Adafruit TFT FeatherWing - 3.5" 480x320 Touchscreen for Feathers
|
||||
* https://www.adafruit.com/product/3651
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HX8357_H
|
||||
#define HX8357_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
#include "../lvgl_helpers.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define HX8357_DC CONFIG_LV_DISP_PIN_DC
|
||||
#define HX8357_RST CONFIG_LV_DISP_PIN_RST
|
||||
#define HX8357_BCKL CONFIG_LV_DISP_PIN_BCKL
|
||||
|
||||
#define HX8357_ENABLE_BACKLIGHT_CONTROL CONFIG_LV_ENABLE_BACKLIGHT_CONTROL
|
||||
|
||||
#if CONFIG_LV_BACKLIGHT_ACTIVE_LVL
|
||||
#define HX8357_BCKL_ACTIVE_LVL 1
|
||||
#else
|
||||
#define HX8357_BCKL_ACTIVE_LVL 0
|
||||
#endif
|
||||
|
||||
// if text/images are backwards, try setting this to 1
|
||||
#define HX8357_INVERT_DISPLAY CONFIG_LV_INVERT_DISPLAY
|
||||
|
||||
|
||||
/*******************
|
||||
* HX8357B/D REGS
|
||||
*********************/
|
||||
#define HX8357D 0xD ///< Our internal const for D type
|
||||
#define HX8357B 0xB ///< Our internal const for B type
|
||||
|
||||
#define HX8357_TFTWIDTH 320 ///< 320 pixels wide
|
||||
#define HX8357_TFTHEIGHT 480 ///< 480 pixels tall
|
||||
|
||||
#define HX8357_NOP 0x00 ///< No op
|
||||
#define HX8357_SWRESET 0x01 ///< software reset
|
||||
#define HX8357_RDDID 0x04 ///< Read ID
|
||||
#define HX8357_RDDST 0x09 ///< (unknown)
|
||||
|
||||
#define HX8357_RDPOWMODE 0x0A ///< Read power mode Read power mode
|
||||
#define HX8357_RDMADCTL 0x0B ///< Read MADCTL
|
||||
#define HX8357_RDCOLMOD 0x0C ///< Column entry mode
|
||||
#define HX8357_RDDIM 0x0D ///< Read display image mode
|
||||
#define HX8357_RDDSDR 0x0F ///< Read dosplay signal mode
|
||||
|
||||
#define HX8357_SLPIN 0x10 ///< Enter sleep mode
|
||||
#define HX8357_SLPOUT 0x11 ///< Exit sleep mode
|
||||
#define HX8357B_PTLON 0x12 ///< Partial mode on
|
||||
#define HX8357B_NORON 0x13 ///< Normal mode
|
||||
|
||||
#define HX8357_INVOFF 0x20 ///< Turn off invert
|
||||
#define HX8357_INVON 0x21 ///< Turn on invert
|
||||
#define HX8357_DISPOFF 0x28 ///< Display on
|
||||
#define HX8357_DISPON 0x29 ///< Display off
|
||||
|
||||
#define HX8357_CASET 0x2A ///< Column addr set
|
||||
#define HX8357_PASET 0x2B ///< Page addr set
|
||||
#define HX8357_RAMWR 0x2C ///< Write VRAM
|
||||
#define HX8357_RAMRD 0x2E ///< Read VRAm
|
||||
|
||||
#define HX8357B_PTLAR 0x30 ///< (unknown)
|
||||
#define HX8357_TEON 0x35 ///< Tear enable on
|
||||
#define HX8357_TEARLINE 0x44 ///< (unknown)
|
||||
#define HX8357_MADCTL 0x36 ///< Memory access control
|
||||
#define HX8357_COLMOD 0x3A ///< Color mode
|
||||
|
||||
#define HX8357_SETOSC 0xB0 ///< Set oscillator
|
||||
#define HX8357_SETPWR1 0xB1 ///< Set power control
|
||||
#define HX8357B_SETDISPLAY 0xB2 ///< Set display mode
|
||||
#define HX8357_SETRGB 0xB3 ///< Set RGB interface
|
||||
#define HX8357D_SETCOM 0xB6 ///< Set VCOM voltage
|
||||
|
||||
#define HX8357B_SETDISPMODE 0xB4 ///< Set display mode
|
||||
#define HX8357D_SETCYC 0xB4 ///< Set display cycle reg
|
||||
#define HX8357B_SETOTP 0xB7 ///< Set OTP memory
|
||||
#define HX8357D_SETC 0xB9 ///< Enable extension command
|
||||
|
||||
#define HX8357B_SET_PANEL_DRIVING 0xC0 ///< Set panel drive mode
|
||||
#define HX8357D_SETSTBA 0xC0 ///< Set source option
|
||||
#define HX8357B_SETDGC 0xC1 ///< Set DGC settings
|
||||
#define HX8357B_SETID 0xC3 ///< Set ID
|
||||
#define HX8357B_SETDDB 0xC4 ///< Set DDB
|
||||
#define HX8357B_SETDISPLAYFRAME 0xC5 ///< Set display frame
|
||||
#define HX8357B_GAMMASET 0xC8 ///< Set Gamma correction
|
||||
#define HX8357B_SETCABC 0xC9 ///< Set CABC
|
||||
#define HX8357_SETPANEL 0xCC ///< Set Panel
|
||||
|
||||
#define HX8357B_SETPOWER 0xD0 ///< Set power control
|
||||
#define HX8357B_SETVCOM 0xD1 ///< Set VCOM
|
||||
#define HX8357B_SETPWRNORMAL 0xD2 ///< Set power normal
|
||||
|
||||
#define HX8357B_RDID1 0xDA ///< Read ID #1
|
||||
#define HX8357B_RDID2 0xDB ///< Read ID #2
|
||||
#define HX8357B_RDID3 0xDC ///< Read ID #3
|
||||
#define HX8357B_RDID4 0xDD ///< Read ID #4
|
||||
|
||||
#define HX8357D_SETGAMMA 0xE0 ///< Set Gamma
|
||||
|
||||
#define HX8357B_SETGAMMA 0xC8 ///< Set Gamma
|
||||
#define HX8357B_SETPANELRELATED 0xE9 ///< Set panel related
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void hx8357_init(void);
|
||||
void hx8357_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
|
||||
void hx8357_enable_backlight(bool backlight);
|
||||
void hx8357_set_rotation(uint8_t r);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*HX8357_H*/
|
414
lvgl_tft/il3820.c
Normal file
414
lvgl_tft/il3820.c
Normal file
|
@ -0,0 +1,414 @@
|
|||
/**
|
||||
@file il3820.c
|
||||
@brief Waveshare e-paper 2.9in b/w display
|
||||
@version 1.0
|
||||
@date 2020-05-29
|
||||
@author Juergen Kienhoefer
|
||||
|
||||
|
||||
@section LICENSE
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Juergen Kienhoefer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "disp_spi.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "il3820.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "IL3820"
|
||||
|
||||
/**
|
||||
* SSD1673, SSD1608 compatible EPD controller driver.
|
||||
*/
|
||||
|
||||
#define BIT_SET(a,b) ((a) |= (1U<<(b)))
|
||||
#define BIT_CLEAR(a,b) ((a) &= ~(1U<<(b)))
|
||||
|
||||
/* Number of pixels? */
|
||||
#define IL3820_PIXEL (CONFIG_LV_DISPLAY_WIDTH * CONFIG_LV_DISPLAY_HEIGHT)
|
||||
|
||||
#define EPD_PANEL_NUMOF_COLUMS EPD_PANEL_WIDTH
|
||||
#define EPD_PANEL_NUMOF_ROWS_PER_PAGE 8
|
||||
|
||||
/* Are pages the number of bytes to represent the panel width? in bytes */
|
||||
#define EPD_PANEL_NUMOF_PAGES (EPD_PANEL_HEIGHT / EPD_PANEL_NUMOF_ROWS_PER_PAGE)
|
||||
|
||||
#define IL3820_PANEL_FIRST_PAGE 0
|
||||
#define IL3820_PANEL_LAST_PAGE (EPD_PANEL_NUMOF_PAGES - 1)
|
||||
#define IL3820_PANEL_FIRST_GATE 0
|
||||
#define IL3820_PANEL_LAST_GATE (EPD_PANEL_NUMOF_COLUMS - 1)
|
||||
|
||||
#define IL3820_PIXELS_PER_BYTE 8
|
||||
|
||||
uint8_t il3820_scan_mode = IL3820_DATA_ENTRY_XIYIY;
|
||||
|
||||
static uint8_t il3820_lut_initial[] = {
|
||||
0x50, 0xAA, 0x55, 0xAA, 0x11, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
static uint8_t il3820_lut_default[] = {
|
||||
0x10, 0x18, 0x18, 0x08, 0x18, 0x18,
|
||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x13, 0x14, 0x44, 0x12,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static uint8_t il3820_softstart[] = {0xd7, 0xd6, 0x9d};
|
||||
static uint8_t il3820_vcom[] = {0xa8};
|
||||
/* 4 dummy lines per gate */
|
||||
static uint8_t il3820_dummyline[] = {0x1a};
|
||||
/* 2us per line */
|
||||
static uint8_t il3820_gatetime[] = {0x08};
|
||||
static uint8_t il3820_border[] = {0x03};
|
||||
|
||||
static bool il3820_partial = false;
|
||||
|
||||
/* Static functions */
|
||||
static void il3820_clear_cntlr_mem(uint8_t ram_cmd, bool update);
|
||||
static void il3820_waitbusy(int wait_ms);
|
||||
static inline void il3820_command_mode(void);
|
||||
static inline void il3820_data_mode(void);
|
||||
static inline void il3820_write_cmd(uint8_t cmd, uint8_t *data, size_t len);
|
||||
static inline void il3820_send_cmd(uint8_t cmd);
|
||||
static void il3820_send_data(uint8_t *data, uint16_t length);
|
||||
static inline void il3820_set_window( uint16_t sx, uint16_t ex, uint16_t ys, uint16_t ye);
|
||||
static inline void il3820_set_cursor(uint16_t sx, uint16_t ys);
|
||||
static void il3820_update_display(void);
|
||||
static void il3820_clear_cntlr_mem(uint8_t ram_cmd, bool update);
|
||||
|
||||
/* Required by LVGL */
|
||||
void il3820_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
|
||||
{
|
||||
/* Each byte holds the data of 8 pixels, linelen is the number of bytes
|
||||
* we need to cover a line of the display. */
|
||||
size_t linelen = EPD_PANEL_WIDTH / 8;
|
||||
|
||||
uint8_t *buffer = (uint8_t*) color_map;
|
||||
uint16_t x_addr_counter = 0;
|
||||
uint16_t y_addr_counter = 0;
|
||||
|
||||
/* Configure entry mode */
|
||||
il3820_write_cmd(IL3820_CMD_ENTRY_MODE, &il3820_scan_mode, 1);
|
||||
|
||||
/* Configure the window based on the coordinates got from LVGL
|
||||
* It looks like this epaper display controller doesn't support partial update,
|
||||
* so the window is always the same, the display size. */
|
||||
il3820_set_window(0, EPD_PANEL_WIDTH - 1, 0, EPD_PANEL_HEIGHT - 1);
|
||||
|
||||
/* Set the cursor at the beginning of the graphic RAM */
|
||||
#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
|
||||
x_addr_counter = EPD_PANEL_WIDTH - 1;
|
||||
y_addr_counter = EPD_PANEL_HEIGHT - 1;
|
||||
#endif
|
||||
|
||||
il3820_set_cursor(x_addr_counter, y_addr_counter);
|
||||
|
||||
il3820_send_cmd(IL3820_CMD_WRITE_RAM);
|
||||
|
||||
/* Write the pixel data to graphic RAM, linelen bytes at the time. */
|
||||
for(size_t row = 0; row <= (EPD_PANEL_HEIGHT - 1); row++){
|
||||
il3820_send_data(buffer, linelen);
|
||||
buffer += IL3820_COLUMNS;
|
||||
}
|
||||
|
||||
il3820_set_window(0, EPD_PANEL_WIDTH - 1, 0, EPD_PANEL_HEIGHT - 1);
|
||||
|
||||
il3820_update_display();
|
||||
|
||||
/* IMPORTANT!!!
|
||||
* Inform the graphics library that you are ready with the flushing */
|
||||
lv_disp_flush_ready(drv);
|
||||
}
|
||||
|
||||
|
||||
/* Rotate the display by "software" when using PORTRAIT orientation.
|
||||
* BIT_SET(byte_index, bit_index) clears the bit_index pixel at byte_index of
|
||||
* the display buffer.
|
||||
* BIT_CLEAR(byte_index, bit_index) sets the bit_index pixel at the byte_index
|
||||
* of the display buffer. */
|
||||
void il3820_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,
|
||||
lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
uint16_t byte_index = 0;
|
||||
uint8_t bit_index = 0;
|
||||
|
||||
#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
|
||||
byte_index = x + ((y >> 3) * EPD_PANEL_HEIGHT);
|
||||
bit_index = y & 0x7;
|
||||
|
||||
if (color.full) {
|
||||
BIT_SET(buf[byte_index], 7 - bit_index);
|
||||
} else {
|
||||
uint16_t mirrored_idx = (EPD_PANEL_HEIGHT - x) + ((y >> 3) * EPD_PANEL_HEIGHT);
|
||||
BIT_CLEAR(buf[mirrored_idx], 7 - bit_index);
|
||||
}
|
||||
#elif defined (CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE)
|
||||
byte_index = y + ((x >> 3) * EPD_PANEL_HEIGHT);
|
||||
bit_index = x & 0x7;
|
||||
|
||||
if (color.full) {
|
||||
BIT_SET(buf[byte_index], 7 - bit_index);
|
||||
} else {
|
||||
BIT_CLEAR(buf[byte_index], 7 - bit_index);
|
||||
}
|
||||
#else
|
||||
#error "Unsupported orientation used"
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Required by LVGL */
|
||||
void il3820_rounder(struct _disp_drv_t * disp_drv, lv_area_t *area) {
|
||||
area->x1 = area->x1 & ~(0x7);
|
||||
area->x2 = area->x2 | (0x7);
|
||||
}
|
||||
|
||||
/* main initialization routine */
|
||||
void il3820_init(void)
|
||||
{
|
||||
uint8_t tmp[3] = {0};
|
||||
|
||||
/* Initialize non-SPI GPIOs */
|
||||
gpio_pad_select_gpio(IL3820_DC_PIN);
|
||||
gpio_set_direction(IL3820_DC_PIN, GPIO_MODE_OUTPUT);
|
||||
gpio_pad_select_gpio(IL3820_RST_PIN);
|
||||
gpio_set_direction(IL3820_RST_PIN, GPIO_MODE_OUTPUT);
|
||||
gpio_pad_select_gpio(IL3820_BUSY_PIN);
|
||||
gpio_set_direction(IL3820_BUSY_PIN, GPIO_MODE_INPUT);
|
||||
|
||||
/* Harware reset */
|
||||
gpio_set_level( IL3820_RST_PIN, 0);
|
||||
vTaskDelay(IL3820_RESET_DELAY / portTICK_RATE_MS);
|
||||
gpio_set_level( IL3820_RST_PIN, 1);
|
||||
vTaskDelay(IL3820_RESET_DELAY / portTICK_RATE_MS);
|
||||
|
||||
/* Software reset */
|
||||
il3820_write_cmd(IL3820_CMD_SW_RESET, NULL, 0);
|
||||
|
||||
/* Busy wait for the BUSY signal to go low */
|
||||
il3820_waitbusy(IL3820_WAIT);
|
||||
|
||||
/**/
|
||||
tmp[0] = ( EPD_PANEL_HEIGHT - 1) & 0xFF;
|
||||
tmp[1] = ( EPD_PANEL_HEIGHT >> 8 );
|
||||
tmp[2] = 0; // GD = 0; SM = 0; TB = 0;
|
||||
il3820_write_cmd(IL3820_CMD_GDO_CTRL, tmp, 3);
|
||||
|
||||
/**/
|
||||
il3820_write_cmd(IL3820_CMD_SOFTSTART, il3820_softstart, sizeof(il3820_softstart));
|
||||
|
||||
/* Write VCOM register */
|
||||
il3820_write_cmd(IL3820_CMD_VCOM_VOLTAGE, il3820_vcom, 1);
|
||||
/* Set dummy line period (in term of TGate) */
|
||||
il3820_write_cmd(IL3820_CMD_DUMMY_LINE, il3820_dummyline, 1);
|
||||
/* Set gate line width (TGate) in us */
|
||||
il3820_write_cmd(IL3820_CMD_GATE_LINE_WIDTH, il3820_gatetime, 1);
|
||||
/* Select border waveform for VBD */
|
||||
il3820_write_cmd(IL3820_CMD_BWF_CTRL, il3820_border, 1);
|
||||
/**/
|
||||
il3820_write_cmd(IL3820_CMD_UPDATE_LUT, il3820_lut_initial, sizeof(il3820_lut_initial));
|
||||
/* Clear control memory and update */
|
||||
il3820_clear_cntlr_mem(IL3820_CMD_WRITE_RAM, true);
|
||||
|
||||
// allow partial updates now
|
||||
il3820_partial = true;
|
||||
|
||||
/* Update LUT */
|
||||
il3820_write_cmd(IL3820_CMD_UPDATE_LUT, il3820_lut_default, sizeof(il3820_lut_default));
|
||||
|
||||
/* Clear control memory and update */
|
||||
il3820_clear_cntlr_mem(IL3820_CMD_WRITE_RAM, true);
|
||||
}
|
||||
|
||||
/* Enter deep sleep mode */
|
||||
void il3820_sleep_in(void)
|
||||
{
|
||||
uint8_t data[] = {0x01};
|
||||
|
||||
/* Wait for the BUSY signal to go low */
|
||||
il3820_waitbusy(IL3820_WAIT);
|
||||
|
||||
il3820_write_cmd(IL3820_CMD_SLEEP_MODE, data, 1);
|
||||
}
|
||||
|
||||
/* TODO: Remove the busy waiting */
|
||||
static void il3820_waitbusy(int wait_ms)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
vTaskDelay(10 / portTICK_RATE_MS); // 10ms delay
|
||||
|
||||
for(i = 0; i < (wait_ms * 10); i++) {
|
||||
if(gpio_get_level(IL3820_BUSY_PIN) != IL3820_BUSY_LEVEL) {
|
||||
return;
|
||||
}
|
||||
|
||||
vTaskDelay(10 / portTICK_RATE_MS);
|
||||
}
|
||||
|
||||
ESP_LOGE( TAG, "busy exceeded %dms", i*10 );
|
||||
}
|
||||
|
||||
/* Set DC signal to command mode */
|
||||
static inline void il3820_command_mode(void)
|
||||
{
|
||||
gpio_set_level(IL3820_DC_PIN, 0);
|
||||
}
|
||||
|
||||
/* Set DC signal to data mode */
|
||||
static inline void il3820_data_mode(void)
|
||||
{
|
||||
gpio_set_level(IL3820_DC_PIN, 1);
|
||||
}
|
||||
|
||||
static inline void il3820_write_cmd(uint8_t cmd, uint8_t *data, size_t len)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
|
||||
il3820_command_mode();
|
||||
disp_spi_send_data(&cmd, 1);
|
||||
|
||||
if (data != NULL) {
|
||||
il3820_data_mode();
|
||||
disp_spi_send_data(data, len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send cmd to the display */
|
||||
static inline void il3820_send_cmd(uint8_t cmd)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
|
||||
il3820_command_mode();
|
||||
disp_spi_send_data(&cmd, 1);
|
||||
}
|
||||
|
||||
/* Send length bytes of data to the display */
|
||||
static void il3820_send_data(uint8_t *data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
|
||||
il3820_data_mode();
|
||||
disp_spi_send_colors(data, length);
|
||||
}
|
||||
|
||||
/* Specify the start/end positions of the window address in the X and Y
|
||||
* directions by an address unit.
|
||||
*
|
||||
* @param sx: X Start position.
|
||||
* @param ex: X End position.
|
||||
* @param ys: Y Start position.
|
||||
* @param ye: Y End position.
|
||||
*/
|
||||
static inline void il3820_set_window( uint16_t sx, uint16_t ex, uint16_t ys, uint16_t ye)
|
||||
{
|
||||
uint8_t tmp[4] = {0};
|
||||
|
||||
tmp[0] = sx / 8;
|
||||
tmp[1] = ex / 8;
|
||||
|
||||
/* Set X address start/end */
|
||||
il3820_write_cmd(IL3820_CMD_RAM_XPOS_CTRL, tmp, 2);
|
||||
|
||||
tmp[0] = ys % 256;
|
||||
tmp[1] = ys / 256;
|
||||
tmp[2] = ye % 256;
|
||||
tmp[3] = ye / 256;
|
||||
/* Set Y address start/end */
|
||||
il3820_write_cmd(IL3820_CMD_RAM_YPOS_CTRL, tmp, 4);
|
||||
}
|
||||
|
||||
/* Make initial settings for the RAM X and Y addresses in the address counter
|
||||
* (AC).
|
||||
*
|
||||
* @param sx: RAM X address counter.
|
||||
* @param ys: RAM Y address counter.
|
||||
*/
|
||||
static inline void il3820_set_cursor(uint16_t sx, uint16_t ys)
|
||||
{
|
||||
uint8_t tmp[2] = {0};
|
||||
|
||||
tmp[0] = sx / 8;
|
||||
il3820_write_cmd(IL3820_CMD_RAM_XPOS_CNTR, tmp, 1);
|
||||
|
||||
tmp[0] = ys % 256;
|
||||
tmp[1] = ys / 256;
|
||||
il3820_write_cmd(IL3820_CMD_RAM_YPOS_CNTR, tmp, 2);
|
||||
}
|
||||
|
||||
/* After sending the RAM content we need to send the commands:
|
||||
* - Display Update Control 2
|
||||
* - Master Activation
|
||||
*
|
||||
* NOTE: Currently we poll for the BUSY signal to go inactive,
|
||||
* we might want not to do it. */
|
||||
static void il3820_update_display(void)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
|
||||
if(il3820_partial) {
|
||||
tmp = IL3820_CTRL2_TO_PATTERN;
|
||||
} else {
|
||||
tmp = (IL3820_CTRL2_ENABLE_CLK | IL3820_CTRL2_ENABLE_ANALOG | IL3820_CTRL2_TO_PATTERN);
|
||||
}
|
||||
|
||||
il3820_write_cmd(IL3820_CMD_UPDATE_CTRL2, &tmp, 1);
|
||||
|
||||
il3820_write_cmd(IL3820_CMD_MASTER_ACTIVATION, NULL, 0);
|
||||
/* Poll BUSY signal. */
|
||||
il3820_waitbusy(IL3820_WAIT);
|
||||
/* XXX: Figure out what does this command do. */
|
||||
il3820_write_cmd(IL3820_CMD_TERMINATE_FRAME_RW, NULL, 0);
|
||||
}
|
||||
|
||||
/* Clear the graphic RAM. */
|
||||
static void il3820_clear_cntlr_mem(uint8_t ram_cmd, bool update)
|
||||
{
|
||||
/* Arrays used by SPI must be word alligned */
|
||||
WORD_ALIGNED_ATTR uint8_t clear_page[IL3820_COLUMNS];
|
||||
memset(clear_page, 0xff, sizeof clear_page);
|
||||
|
||||
/* Configure entry mode */
|
||||
il3820_write_cmd(IL3820_CMD_ENTRY_MODE, &il3820_scan_mode, 1);
|
||||
|
||||
/* Configure the window */
|
||||
il3820_set_window(0, EPD_PANEL_WIDTH - 1, 0, EPD_PANEL_HEIGHT - 1);
|
||||
|
||||
/* Send clear_page buffer to the display */
|
||||
for(int j = 0; j < EPD_PANEL_HEIGHT; j++) {
|
||||
il3820_set_cursor(0, j);
|
||||
il3820_write_cmd(ram_cmd, clear_page, sizeof clear_page);
|
||||
}
|
||||
|
||||
if (update) {
|
||||
il3820_set_window( 0, EPD_PANEL_WIDTH - 1, 0, EPD_PANEL_HEIGHT - 1);
|
||||
il3820_update_display();
|
||||
}
|
||||
}
|
113
lvgl_tft/il3820.h
Normal file
113
lvgl_tft/il3820.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* @file il3820.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef IL3820_H
|
||||
#define IL3820_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* 128 = panel width */
|
||||
#define IL3820_COLUMNS (EPD_PANEL_WIDTH / 8)
|
||||
|
||||
#define IL3820_DC_PIN CONFIG_LV_DISP_PIN_DC
|
||||
#define IL3820_RST_PIN CONFIG_LV_DISP_PIN_RST
|
||||
#define IL3820_BUSY_PIN CONFIG_LV_DISP_PIN_BUSY
|
||||
#define IL3820_BUSY_LEVEL 1
|
||||
|
||||
/* IL3820 commands */
|
||||
#define IL3820_CMD_GDO_CTRL 0x01
|
||||
#define IL3820_CMD_GDV_CTRL 0x03
|
||||
#define IL3820_CMD_SDV_CTRL 0x04
|
||||
#define IL3820_CMD_SOFTSTART 0x0c
|
||||
#define IL3820_CMD_GSCAN_START 0x0f
|
||||
#define IL3820_CMD_SLEEP_MODE 0x10
|
||||
#define IL3820_CMD_ENTRY_MODE 0x11
|
||||
#define IL3820_CMD_SW_RESET 0x12
|
||||
#define IL3820_CMD_TSENS_CTRL 0x1a
|
||||
#define IL3820_CMD_MASTER_ACTIVATION 0x20
|
||||
#define IL3820_CMD_UPDATE_CTRL1 0x21
|
||||
#define IL3820_CMD_UPDATE_CTRL2 0x22
|
||||
#define IL3820_CMD_WRITE_RAM 0x24
|
||||
#define IL3820_CMD_WRITE_RED_RAM 0x26
|
||||
#define IL3820_CMD_VCOM_SENSE 0x28
|
||||
#define IL3820_CMD_VCOM_SENSE_DURATON 0x29
|
||||
#define IL3820_CMD_PRGM_VCOM_OTP 0x2a
|
||||
#define IL3820_CMD_VCOM_VOLTAGE 0x2c
|
||||
#define IL3820_CMD_PRGM_WS_OTP 0x30
|
||||
#define IL3820_CMD_UPDATE_LUT 0x32
|
||||
#define IL3820_CMD_PRGM_OTP_SELECTION 0x36
|
||||
#define IL3820_CMD_OTP_SELECTION_CTRL 0x37
|
||||
#define IL3820_CMD_DUMMY_LINE 0x3a
|
||||
#define IL3820_CMD_GATE_LINE_WIDTH 0x3b
|
||||
#define IL3820_CMD_BWF_CTRL 0x3c
|
||||
#define IL3820_CMD_RAM_XPOS_CTRL 0x44
|
||||
#define IL3820_CMD_RAM_YPOS_CTRL 0x45
|
||||
#define IL3820_CMD_RAM_XPOS_CNTR 0x4e
|
||||
#define IL3820_CMD_RAM_YPOS_CNTR 0x4f
|
||||
#define IL3820_CMD_TERMINATE_FRAME_RW 0xff
|
||||
|
||||
/* Data entry sequence modes */
|
||||
#define IL3820_DATA_ENTRY_MASK 0x07
|
||||
#define IL3820_DATA_ENTRY_XDYDX 0x00
|
||||
#define IL3820_DATA_ENTRY_XIYDX 0x01
|
||||
#define IL3820_DATA_ENTRY_XDYIX 0x02
|
||||
#define IL3820_DATA_ENTRY_XIYIX 0x03
|
||||
#define IL3820_DATA_ENTRY_XDYDY 0x04
|
||||
#define IL3820_DATA_ENTRY_XIYDY 0x05
|
||||
#define IL3820_DATA_ENTRY_XDYIY 0x06
|
||||
#define IL3820_DATA_ENTRY_XIYIY 0x07
|
||||
|
||||
/* Options for display update */
|
||||
#define IL3820_CTRL1_INITIAL_UPDATE_LL 0x00
|
||||
#define IL3820_CTRL1_INITIAL_UPDATE_LH 0x01
|
||||
#define IL3820_CTRL1_INITIAL_UPDATE_HL 0x02
|
||||
#define IL3820_CTRL1_INITIAL_UPDATE_HH 0x03
|
||||
|
||||
/* Options for display update sequence */
|
||||
#define IL3820_CTRL2_ENABLE_CLK 0x80
|
||||
#define IL3820_CTRL2_ENABLE_ANALOG 0x40
|
||||
#define IL3820_CTRL2_TO_INITIAL 0x08
|
||||
#define IL3820_CTRL2_TO_PATTERN 0x04
|
||||
#define IL3820_CTRL2_DISABLE_ANALOG 0x02
|
||||
#define IL3820_CTRL2_DISABLE_CLK 0x01
|
||||
|
||||
#define IL3820_SLEEP_MODE_DSM 0x01
|
||||
#define IL3820_SLEEP_MODE_PON 0x00
|
||||
|
||||
/* time constants in ms */
|
||||
#define IL3820_RESET_DELAY 20
|
||||
#define IL3820_BUSY_DELAY 1
|
||||
// normal wait time max 200ms
|
||||
#define IL3820_WAIT 20
|
||||
|
||||
void il3820_init(void);
|
||||
void il3820_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map);
|
||||
void il3820_fullflush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map);
|
||||
void il3820_rounder(struct _disp_drv_t * disp_drv, lv_area_t *area);
|
||||
void il3820_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, lv_color_t color, lv_opa_t opa);
|
||||
void il3820_sleep_in(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __IL3820_REGS_H__ */
|
||||
|
241
lvgl_tft/ili9341.c
Normal file
241
lvgl_tft/ili9341.c
Normal file
|
@ -0,0 +1,241 @@
|
|||
/**
|
||||
* @file ili9341.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "ili9341.h"
|
||||
#include "disp_spi.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "ILI9341"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */
|
||||
typedef struct {
|
||||
uint8_t cmd;
|
||||
uint8_t data[16];
|
||||
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
|
||||
} lcd_init_cmd_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void ili9341_set_orientation(uint8_t orientation);
|
||||
|
||||
static void ili9341_send_cmd(uint8_t cmd);
|
||||
static void ili9341_send_data(void * data, uint16_t length);
|
||||
static void ili9341_send_color(void * data, uint16_t length);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void ili9341_init(void)
|
||||
{
|
||||
lcd_init_cmd_t ili_init_cmds[]={
|
||||
{0xCF, {0x00, 0x83, 0X30}, 3},
|
||||
{0xED, {0x64, 0x03, 0X12, 0X81}, 4},
|
||||
{0xE8, {0x85, 0x01, 0x79}, 3},
|
||||
{0xCB, {0x39, 0x2C, 0x00, 0x34, 0x02}, 5},
|
||||
{0xF7, {0x20}, 1},
|
||||
{0xEA, {0x00, 0x00}, 2},
|
||||
{0xC0, {0x26}, 1}, /*Power control*/
|
||||
{0xC1, {0x11}, 1}, /*Power control */
|
||||
{0xC5, {0x35, 0x3E}, 2}, /*VCOM control*/
|
||||
{0xC7, {0xBE}, 1}, /*VCOM control*/
|
||||
{0x36, {0x28}, 1}, /*Memory Access Control*/
|
||||
{0x3A, {0x55}, 1}, /*Pixel Format Set*/
|
||||
{0xB1, {0x00, 0x1B}, 2},
|
||||
{0xF2, {0x08}, 1},
|
||||
{0x26, {0x01}, 1},
|
||||
{0xE0, {0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0X87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00}, 15},
|
||||
{0XE1, {0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F}, 15},
|
||||
{0x2A, {0x00, 0x00, 0x00, 0xEF}, 4},
|
||||
{0x2B, {0x00, 0x00, 0x01, 0x3f}, 4},
|
||||
{0x2C, {0}, 0},
|
||||
{0xB7, {0x07}, 1},
|
||||
{0xB6, {0x0A, 0x82, 0x27, 0x00}, 4},
|
||||
{0x11, {0}, 0x80},
|
||||
{0x29, {0}, 0x80},
|
||||
{0, {0}, 0xff},
|
||||
};
|
||||
|
||||
#if ILI9341_BCKL == 15
|
||||
gpio_config_t io_conf;
|
||||
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = GPIO_SEL_15;
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
gpio_config(&io_conf);
|
||||
#endif
|
||||
|
||||
//Initialize non-SPI GPIOs
|
||||
gpio_pad_select_gpio(ILI9341_DC);
|
||||
gpio_set_direction(ILI9341_DC, GPIO_MODE_OUTPUT);
|
||||
gpio_pad_select_gpio(ILI9341_RST);
|
||||
gpio_set_direction(ILI9341_RST, GPIO_MODE_OUTPUT);
|
||||
|
||||
#if ILI9341_ENABLE_BACKLIGHT_CONTROL
|
||||
gpio_pad_select_gpio(ILI9341_BCKL);
|
||||
gpio_set_direction(ILI9341_BCKL, GPIO_MODE_OUTPUT);
|
||||
#endif
|
||||
//Reset the display
|
||||
gpio_set_level(ILI9341_RST, 0);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
gpio_set_level(ILI9341_RST, 1);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
|
||||
ESP_LOGI(TAG, "Initialization.");
|
||||
|
||||
//Send all the commands
|
||||
uint16_t cmd = 0;
|
||||
while (ili_init_cmds[cmd].databytes!=0xff) {
|
||||
ili9341_send_cmd(ili_init_cmds[cmd].cmd);
|
||||
ili9341_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F);
|
||||
if (ili_init_cmds[cmd].databytes & 0x80) {
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
}
|
||||
cmd++;
|
||||
}
|
||||
|
||||
ili9341_enable_backlight(true);
|
||||
|
||||
ili9341_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION);
|
||||
|
||||
#if ILI9341_INVERT_COLORS == 1
|
||||
ili9341_send_cmd(0x21);
|
||||
#else
|
||||
ili9341_send_cmd(0x20);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ili9341_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
|
||||
{
|
||||
uint8_t data[4];
|
||||
|
||||
/*Column addresses*/
|
||||
ili9341_send_cmd(0x2A);
|
||||
data[0] = (area->x1 >> 8) & 0xFF;
|
||||
data[1] = area->x1 & 0xFF;
|
||||
data[2] = (area->x2 >> 8) & 0xFF;
|
||||
data[3] = area->x2 & 0xFF;
|
||||
ili9341_send_data(data, 4);
|
||||
|
||||
/*Page addresses*/
|
||||
ili9341_send_cmd(0x2B);
|
||||
data[0] = (area->y1 >> 8) & 0xFF;
|
||||
data[1] = area->y1 & 0xFF;
|
||||
data[2] = (area->y2 >> 8) & 0xFF;
|
||||
data[3] = area->y2 & 0xFF;
|
||||
ili9341_send_data(data, 4);
|
||||
|
||||
/*Memory write*/
|
||||
ili9341_send_cmd(0x2C);
|
||||
|
||||
|
||||
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
|
||||
|
||||
ili9341_send_color((void*)color_map, size * 2);
|
||||
}
|
||||
|
||||
void ili9341_enable_backlight(bool backlight)
|
||||
{
|
||||
#if ILI9341_ENABLE_BACKLIGHT_CONTROL
|
||||
ESP_LOGI(TAG, "%s backlight.", backlight ? "Enabling" : "Disabling");
|
||||
uint32_t tmp = 0;
|
||||
|
||||
#if (ILI9341_BCKL_ACTIVE_LVL==1)
|
||||
tmp = backlight ? 1 : 0;
|
||||
#else
|
||||
tmp = backlight ? 0 : 1;
|
||||
#endif
|
||||
|
||||
gpio_set_level(ILI9341_BCKL, tmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ili9341_sleep_in()
|
||||
{
|
||||
uint8_t data[] = {0x08};
|
||||
ili9341_send_cmd(0x10);
|
||||
ili9341_send_data(&data, 1);
|
||||
}
|
||||
|
||||
void ili9341_sleep_out()
|
||||
{
|
||||
uint8_t data[] = {0x08};
|
||||
ili9341_send_cmd(0x11);
|
||||
ili9341_send_data(&data, 1);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
static void ili9341_send_cmd(uint8_t cmd)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ILI9341_DC, 0); /*Command mode*/
|
||||
disp_spi_send_data(&cmd, 1);
|
||||
}
|
||||
|
||||
static void ili9341_send_data(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ILI9341_DC, 1); /*Data mode*/
|
||||
disp_spi_send_data(data, length);
|
||||
}
|
||||
|
||||
static void ili9341_send_color(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ILI9341_DC, 1); /*Data mode*/
|
||||
disp_spi_send_colors(data, length);
|
||||
}
|
||||
|
||||
static void ili9341_set_orientation(uint8_t orientation)
|
||||
{
|
||||
// ESP_ASSERT(orientation < 4);
|
||||
|
||||
const char *orientation_str[] = {
|
||||
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]);
|
||||
|
||||
#if defined CONFIG_LV_PREDEFINED_DISPLAY_M5STACK
|
||||
uint8_t data[] = {0x68, 0x68, 0x08, 0x08};
|
||||
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_WROVER4)
|
||||
uint8_t data[] = {0x4C, 0x88, 0x28, 0xE8};
|
||||
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE)
|
||||
uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]);
|
||||
|
||||
ili9341_send_cmd(0x36);
|
||||
ili9341_send_data((void *) &data[orientation], 1);
|
||||
}
|
65
lvgl_tft/ili9341.h
Normal file
65
lvgl_tft/ili9341.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* @file lv_templ.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILI9341_H
|
||||
#define ILI9341_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
#include "../lvgl_helpers.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define ILI9341_DC CONFIG_LV_DISP_PIN_DC
|
||||
#define ILI9341_RST CONFIG_LV_DISP_PIN_RST
|
||||
#define ILI9341_BCKL CONFIG_LV_DISP_PIN_BCKL
|
||||
|
||||
#define ILI9341_ENABLE_BACKLIGHT_CONTROL CONFIG_LV_ENABLE_BACKLIGHT_CONTROL
|
||||
|
||||
#if CONFIG_LV_BACKLIGHT_ACTIVE_LVL
|
||||
#define ILI9341_BCKL_ACTIVE_LVL 1
|
||||
#else
|
||||
#define ILI9341_BCKL_ACTIVE_LVL 0
|
||||
#endif
|
||||
|
||||
#define ILI9341_INVERT_COLORS CONFIG_LV_INVERT_COLORS
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void ili9341_init(void);
|
||||
void ili9341_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
|
||||
void ili9341_enable_backlight(bool backlight);
|
||||
void ili9341_sleep_in(void);
|
||||
void ili9341_sleep_out(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*ILI9341_H*/
|
224
lvgl_tft/ili9481.c
Normal file
224
lvgl_tft/ili9481.c
Normal file
|
@ -0,0 +1,224 @@
|
|||
/**
|
||||
* @file ili9481.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "ili9481.h"
|
||||
#include "disp_spi.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "ILI9481"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */
|
||||
typedef struct {
|
||||
uint8_t cmd;
|
||||
uint8_t data[16];
|
||||
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
|
||||
} lcd_init_cmd_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void ili9481_set_orientation(uint8_t orientation);
|
||||
static void ili9481_send_cmd(uint8_t cmd);
|
||||
static void ili9481_send_data(void * data, uint16_t length);
|
||||
static void ili9481_send_color(void * data, uint16_t length);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void ili9481_init(void)
|
||||
{
|
||||
lcd_init_cmd_t ili_init_cmds[]={
|
||||
{ILI9481_CMD_SLEEP_OUT, {0x00}, 0x80},
|
||||
{ILI9481_CMD_POWER_SETTING, {0x07, 0x42, 0x18}, 3},
|
||||
{ILI9481_CMD_VCOM_CONTROL, {0x00, 0x07, 0x10}, 3},
|
||||
{ILI9481_CMD_POWER_CONTROL_NORMAL, {0x01, 0x02}, 2},
|
||||
{ILI9481_CMD_PANEL_DRIVE, {0x10, 0x3B, 0x00, 0x02, 0x11}, 5},
|
||||
{ILI9481_CMD_FRAME_RATE, {0x03}, 1},
|
||||
{ILI9481_CMD_FRAME_MEMORY_ACCESS, {0x0, 0x0, 0x0, 0x0}, 4},
|
||||
//{ILI9481_CMD_DISP_TIMING_NORMAL, {0x10, 0x10, 0x22}, 3},
|
||||
{ILI9481_CMD_GAMMA_SETTING, {0x00, 0x32, 0x36, 0x45, 0x06, 0x16, 0x37, 0x75, 0x77, 0x54, 0x0C, 0x00}, 12},
|
||||
{ILI9481_CMD_MEMORY_ACCESS_CONTROL, {0x0A}, 1},
|
||||
#if ILI9481_INVERT_COLORS
|
||||
{ILI9481_CMD_DISP_INVERSION_ON, {}, 0},
|
||||
#endif
|
||||
{ILI9481_CMD_COLMOD_PIXEL_FORMAT_SET, {0x66}, 1},
|
||||
{ILI9481_CMD_NORMAL_DISP_MODE_ON, {}, 0x80},
|
||||
{ILI9481_CMD_DISPLAY_ON, {}, 0x80},
|
||||
{0, {0}, 0xff},
|
||||
};
|
||||
|
||||
//Initialize non-SPI GPIOs
|
||||
gpio_pad_select_gpio(ILI9481_DC);
|
||||
gpio_set_direction(ILI9481_DC, GPIO_MODE_OUTPUT);
|
||||
gpio_pad_select_gpio(ILI9481_RST);
|
||||
gpio_set_direction(ILI9481_RST, GPIO_MODE_OUTPUT);
|
||||
|
||||
#if ILI9481_ENABLE_BACKLIGHT_CONTROL
|
||||
gpio_pad_select_gpio(ILI9481_BCKL);
|
||||
gpio_set_direction(ILI9481_BCKL, GPIO_MODE_OUTPUT);
|
||||
#endif
|
||||
|
||||
//Reset the display
|
||||
gpio_set_level(ILI9481_RST, 0);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
gpio_set_level(ILI9481_RST, 1);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
|
||||
ESP_LOGI(TAG, "ILI9481 initialization.");
|
||||
|
||||
// Exit sleep
|
||||
ili9481_send_cmd(0x01); /* Software reset */
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
|
||||
//Send all the commands
|
||||
uint16_t cmd = 0;
|
||||
while (ili_init_cmds[cmd].databytes!=0xff) {
|
||||
ili9481_send_cmd(ili_init_cmds[cmd].cmd);
|
||||
ili9481_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F);
|
||||
if (ili_init_cmds[cmd].databytes & 0x80) {
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
}
|
||||
cmd++;
|
||||
}
|
||||
|
||||
ili9481_enable_backlight(true);
|
||||
|
||||
ili9481_set_orientation(ILI9481_DISPLAY_ORIENTATION);
|
||||
}
|
||||
|
||||
// Flush function based on mvturnho repo
|
||||
void ili9481_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
|
||||
{
|
||||
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
|
||||
|
||||
lv_color16_t *buffer_16bit = (lv_color16_t *) color_map;
|
||||
uint8_t *mybuf;
|
||||
do {
|
||||
mybuf = (uint8_t *) heap_caps_malloc(3 * size * sizeof(uint8_t), MALLOC_CAP_DMA);
|
||||
if (mybuf == NULL) ESP_LOGW(TAG, "Could not allocate enough DMA memory!");
|
||||
} while (mybuf == NULL);
|
||||
|
||||
uint32_t LD = 0;
|
||||
uint32_t j = 0;
|
||||
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
LD = buffer_16bit[i].full;
|
||||
mybuf[j] = (uint8_t) (((LD & 0xF800) >> 8) | ((LD & 0x8000) >> 13));
|
||||
j++;
|
||||
mybuf[j] = (uint8_t) ((LD & 0x07E0) >> 3);
|
||||
j++;
|
||||
mybuf[j] = (uint8_t) (((LD & 0x001F) << 3) | ((LD & 0x0010) >> 2));
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Column addresses */
|
||||
uint8_t xb[] = {
|
||||
(uint8_t) (area->x1 >> 8) & 0xFF,
|
||||
(uint8_t) (area->x1) & 0xFF,
|
||||
(uint8_t) (area->x2 >> 8) & 0xFF,
|
||||
(uint8_t) (area->x2) & 0xFF,
|
||||
};
|
||||
|
||||
/* Page addresses */
|
||||
uint8_t yb[] = {
|
||||
(uint8_t) (area->y1 >> 8) & 0xFF,
|
||||
(uint8_t) (area->y1) & 0xFF,
|
||||
(uint8_t) (area->y2 >> 8) & 0xFF,
|
||||
(uint8_t) (area->y2) & 0xFF,
|
||||
};
|
||||
|
||||
/*Column addresses*/
|
||||
ili9481_send_cmd(ILI9481_CMD_COLUMN_ADDRESS_SET);
|
||||
ili9481_send_data(xb, 4);
|
||||
|
||||
/*Page addresses*/
|
||||
ili9481_send_cmd(ILI9481_CMD_PAGE_ADDRESS_SET);
|
||||
ili9481_send_data(yb, 4);
|
||||
|
||||
/*Memory write*/
|
||||
ili9481_send_cmd(ILI9481_CMD_MEMORY_WRITE);
|
||||
|
||||
ili9481_send_color((void *) mybuf, size * 3);
|
||||
heap_caps_free(mybuf);
|
||||
}
|
||||
|
||||
void ili9481_enable_backlight(bool backlight)
|
||||
{
|
||||
#if ILI9481_ENABLE_BACKLIGHT_CONTROL
|
||||
ESP_LOGI(TAG, "%s backlight.", backlight ? "Enabling" : "Disabling");
|
||||
uint32_t tmp = 0;
|
||||
|
||||
#if (ILI9481_BCKL_ACTIVE_LVL==1)
|
||||
tmp = backlight ? 1 : 0;
|
||||
#else
|
||||
tmp = backlight ? 0 : 1;
|
||||
#endif
|
||||
|
||||
gpio_set_level(ILI9481_BCKL, tmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
static void ili9481_send_cmd(uint8_t cmd)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ILI9481_DC, 0); /*Command mode*/
|
||||
disp_spi_send_data(&cmd, 1);
|
||||
}
|
||||
|
||||
static void ili9481_send_data(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ILI9481_DC, 1); /*Data mode*/
|
||||
disp_spi_send_data(data, length);
|
||||
}
|
||||
|
||||
static void ili9481_send_color(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ILI9481_DC, 1); /*Data mode*/
|
||||
disp_spi_send_colors(data, length);
|
||||
}
|
||||
|
||||
static void ili9481_set_orientation(uint8_t orientation)
|
||||
{
|
||||
const char *orientation_str[] = {
|
||||
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]);
|
||||
|
||||
uint8_t data[] = {0x48, 0x4B, 0x28, 0x2B};
|
||||
ili9481_send_cmd(ILI9481_CMD_MEMORY_ACCESS_CONTROL);
|
||||
ili9481_send_data((void *) &data[orientation], 1);
|
||||
}
|
130
lvgl_tft/ili9481.h
Normal file
130
lvgl_tft/ili9481.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* @file ili9481.h
|
||||
*/
|
||||
|
||||
#ifndef ILI9481_H
|
||||
#define ILI9481_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
#include "../lvgl_helpers.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define ILI9481_DC CONFIG_LV_DISP_PIN_DC
|
||||
#define ILI9481_RST CONFIG_LV_DISP_PIN_RST
|
||||
#define ILI9481_BCKL CONFIG_LV_DISP_PIN_BCKL
|
||||
|
||||
#define ILI9481_ENABLE_BACKLIGHT_CONTROL CONFIG_LV_ENABLE_BACKLIGHT_CONTROL
|
||||
#define ILI9481_INVERT_COLORS CONFIG_LV_INVERT_COLORS
|
||||
#define ILI9481_DISPLAY_ORIENTATION CONFIG_LV_DISPLAY_ORIENTATION
|
||||
|
||||
#if CONFIG_LV_BACKLIGHT_ACTIVE_LVL
|
||||
#define ILI9481_BCKL_ACTIVE_LVL 1
|
||||
#else
|
||||
#define ILI9481_BCKL_ACTIVE_LVL 0
|
||||
#endif
|
||||
|
||||
/*******************
|
||||
* ILI9481 REGS
|
||||
*********************/
|
||||
|
||||
/* MIPI DCS Type1 */
|
||||
#define ILI9481_CMD_NOP 0x00
|
||||
#define ILI9481_CMD_SOFTWARE_RESET 0x01
|
||||
#define ILI9481_CMD_READ_DISP_POWER_MODE 0x0A
|
||||
#define ILI9481_CMD_READ_DISP_MADCTRL 0x0B // bits 7:3 only
|
||||
#define ILI9481_CMD_READ_DISP_PIXEL_FORMAT 0x0C
|
||||
#define ILI9481_CMD_READ_DISP_IMAGE_MODE 0x0D
|
||||
#define ILI9481_CMD_READ_DISP_SIGNAL_MODE 0x0E
|
||||
#define ILI9481_CMD_READ_DISP_SELF_DIAGNOSTIC 0x0F // bits 7:6 only
|
||||
#define ILI9481_CMD_ENTER_SLEEP_MODE 0x10
|
||||
#define ILI9481_CMD_SLEEP_OUT 0x11
|
||||
#define ILI9481_CMD_PARTIAL_MODE_ON 0x12
|
||||
#define ILI9481_CMD_NORMAL_DISP_MODE_ON 0x13
|
||||
#define ILI9481_CMD_DISP_INVERSION_OFF 0x20
|
||||
#define ILI9481_CMD_DISP_INVERSION_ON 0x21
|
||||
#define ILI9481_CMD_DISPLAY_OFF 0x28
|
||||
#define ILI9481_CMD_DISPLAY_ON 0x29
|
||||
#define ILI9481_CMD_COLUMN_ADDRESS_SET 0x2A
|
||||
#define ILI9481_CMD_PAGE_ADDRESS_SET 0x2B
|
||||
#define ILI9481_CMD_MEMORY_WRITE 0x2C
|
||||
#define ILI9481_CMD_MEMORY_READ 0x2E
|
||||
#define ILI9481_CMD_PARTIAL_AREA 0x30
|
||||
#define ILI9481_CMD_VERT_SCROLL_DEFINITION 0x33
|
||||
#define ILI9481_CMD_TEARING_EFFECT_LINE_OFF 0x34
|
||||
#define ILI9481_CMD_TEARING_EFFECT_LINE_ON 0x35
|
||||
#define ILI9481_CMD_MEMORY_ACCESS_CONTROL 0x36 // bits 7:3,1:0 only
|
||||
#define ILI9481_CMD_VERT_SCROLL_START_ADDRESS 0x37
|
||||
#define ILI9481_CMD_IDLE_MODE_OFF 0x38
|
||||
#define ILI9481_CMD_IDLE_MODE_ON 0x39
|
||||
#define ILI9481_CMD_COLMOD_PIXEL_FORMAT_SET 0x3A
|
||||
#define ILI9481_CMD_WRITE_MEMORY_CONTINUE 0x3C
|
||||
#define ILI9481_CMD_READ_MEMORY_CONTINUE 0x3E
|
||||
#define ILI9481_CMD_SET_TEAR_SCANLINE 0x44
|
||||
#define ILI9481_CMD_GET_SCANLINE 0x45
|
||||
|
||||
#define ILI9481_DDB_START 0xA1
|
||||
#define ILI9481_DDB_CONTINUE 0xA8
|
||||
|
||||
/* other */
|
||||
#define ILI9481_CMD_ACCESS_PROTECT 0xB0
|
||||
#define ILI9481_CMD_LOW_POWER_CONTROL 0xB1
|
||||
#define ILI9481_CMD_FRAME_MEMORY_ACCESS 0xB3
|
||||
#define ILI9481_CMD_DISPLAY_MODE 0xB4
|
||||
#define ILI9481_CMD_DEVICE_CODE 0xBF
|
||||
|
||||
#define ILI9481_CMD_PANEL_DRIVE 0xC0
|
||||
#define ILI9481_CMD_DISP_TIMING_NORMAL 0xC1
|
||||
#define ILI9481_CMD_DISP_TIMING_PARTIAL 0xC2
|
||||
#define ILI9481_CMD_DISP_TIMING_IDLE 0xC3
|
||||
#define ILI9481_CMD_FRAME_RATE 0xC5
|
||||
#define ILI9481_CMD_INTERFACE_CONTROL 0xC6
|
||||
#define ILI9481_CMD_GAMMA_SETTING 0xC8
|
||||
|
||||
#define ILI9481_CMD_POWER_SETTING 0xD0
|
||||
#define ILI9481_CMD_VCOM_CONTROL 0xD1
|
||||
#define ILI9481_CMD_POWER_CONTROL_NORMAL 0xD2
|
||||
#define ILI9481_CMD_POWER_CONTROL_IDEL 0xD3
|
||||
#define ILI9481_CMD_POWER_CONTROL_PARTIAL 0xD4
|
||||
|
||||
#define ILI9481_CMD_NVMEM_WRITE 0xE0
|
||||
#define ILI9481_CMD_NVMEM_PROTECTION_KEY 0xE1
|
||||
#define ILI9481_CMD_NVMEM_STATUS_READ 0xE2
|
||||
#define ILI9481_CMD_NVMEM_PROTECTION 0xE3
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void ili9481_init(void);
|
||||
void ili9481_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
|
||||
void ili9481_enable_backlight(bool backlight);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*ILI9481_H*/
|
214
lvgl_tft/ili9486.c
Normal file
214
lvgl_tft/ili9486.c
Normal file
|
@ -0,0 +1,214 @@
|
|||
/**
|
||||
* @file mpi3501.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "ili9486.h"
|
||||
#include "disp_spi.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "ILI9486"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */
|
||||
typedef struct {
|
||||
uint8_t cmd;
|
||||
uint8_t data[16];
|
||||
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
|
||||
} lcd_init_cmd_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void ili9486_set_orientation(uint8_t orientation);
|
||||
|
||||
static void ili9486_send_cmd(uint8_t cmd);
|
||||
static void ili9486_send_data(void * data, uint16_t length);
|
||||
static void ili9486_send_color(void * data, uint16_t length);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void ili9486_init(void)
|
||||
{
|
||||
lcd_init_cmd_t ili_init_cmds[]={
|
||||
{0x11, {0}, 0x80},
|
||||
{0x3A, {0x55}, 1},
|
||||
{0x2C, {0x44}, 1},
|
||||
{0xC5, {0x00, 0x00, 0x00, 0x00}, 4},
|
||||
{0xE0, {0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00}, 15},
|
||||
{0XE1, {0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00}, 15},
|
||||
{0x20, {0}, 0}, /* display inversion OFF */
|
||||
{0x36, {0x48}, 1},
|
||||
{0x29, {0}, 0x80}, /* display on */
|
||||
{0x00, {0}, 0xff},
|
||||
};
|
||||
|
||||
#if ILI9486_BCKL == 15
|
||||
gpio_config_t io_conf;
|
||||
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = GPIO_SEL_15;
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
gpio_config(&io_conf);
|
||||
#endif
|
||||
|
||||
//Initialize non-SPI GPIOs
|
||||
gpio_pad_select_gpio(ILI9486_DC);
|
||||
gpio_set_direction(ILI9486_DC, GPIO_MODE_OUTPUT);
|
||||
gpio_pad_select_gpio(ILI9486_RST);
|
||||
gpio_set_direction(ILI9486_RST, GPIO_MODE_OUTPUT);
|
||||
|
||||
#if ILI9486_ENABLE_BACKLIGHT_CONTROL
|
||||
gpio_pad_select_gpio(ILI9486_BCKL);
|
||||
gpio_set_direction(ILI9486_BCKL, GPIO_MODE_OUTPUT);
|
||||
#endif
|
||||
|
||||
//Reset the display
|
||||
gpio_set_level(ILI9486_RST, 0);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
gpio_set_level(ILI9486_RST, 1);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
|
||||
ESP_LOGI(TAG, "ILI9486 Initialization.");
|
||||
|
||||
//Send all the commands
|
||||
uint16_t cmd = 0;
|
||||
while (ili_init_cmds[cmd].databytes!=0xff) {
|
||||
ili9486_send_cmd(ili_init_cmds[cmd].cmd);
|
||||
ili9486_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F);
|
||||
if (ili_init_cmds[cmd].databytes & 0x80) {
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
}
|
||||
cmd++;
|
||||
}
|
||||
|
||||
ili9486_enable_backlight(true);
|
||||
|
||||
ili9486_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION);
|
||||
}
|
||||
|
||||
void ili9486_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
|
||||
{
|
||||
uint8_t data[4] = {0};
|
||||
uint32_t size = 0;
|
||||
|
||||
/*Column addresses*/
|
||||
ili9486_send_cmd(0x2A);
|
||||
data[0] = (area->x1 >> 8) & 0xFF;
|
||||
data[1] = area->x1 & 0xFF;
|
||||
data[2] = (area->x2 >> 8) & 0xFF;
|
||||
data[3] = area->x2 & 0xFF;
|
||||
ili9486_send_data(data, 4);
|
||||
|
||||
/*Page addresses*/
|
||||
ili9486_send_cmd(0x2B);
|
||||
data[0] = (area->y1 >> 8) & 0xFF;
|
||||
data[1] = area->y1 & 0xFF;
|
||||
data[2] = (area->y2 >> 8) & 0xFF;
|
||||
data[3] = area->y2 & 0xFF;
|
||||
ili9486_send_data(data, 4);
|
||||
|
||||
/*Memory write*/
|
||||
ili9486_send_cmd(0x2C);
|
||||
|
||||
size = lv_area_get_width(area) * lv_area_get_height(area);
|
||||
|
||||
ili9486_send_color((void*) color_map, size * 2);
|
||||
}
|
||||
|
||||
void ili9486_enable_backlight(bool backlight)
|
||||
{
|
||||
#if ILI9486_ENABLE_BACKLIGHT_CONTROL
|
||||
ESP_LOGI(TAG, "%s backlight.", backlight ? "Enabling" : "Disabling");
|
||||
uint32_t tmp = 0;
|
||||
|
||||
#if (ILI9486_BCKL_ACTIVE_LVL==1)
|
||||
tmp = backlight ? 1 : 0;
|
||||
#else
|
||||
tmp = backlight ? 0 : 1;
|
||||
#endif
|
||||
|
||||
gpio_set_level(ILI9486_BCKL, tmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
static void ili9486_send_cmd(uint8_t cmd)
|
||||
{
|
||||
uint8_t to16bit[] = {
|
||||
0x00, cmd
|
||||
};
|
||||
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ILI9486_DC, 0); /*Command mode*/
|
||||
disp_spi_send_data(to16bit, sizeof to16bit);
|
||||
}
|
||||
|
||||
static void ili9486_send_data(void * data, uint16_t length)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t to16bit[32];
|
||||
uint8_t * dummy = data;
|
||||
|
||||
for(i=0; i < (length); i++)
|
||||
{
|
||||
to16bit[2*i+1] = dummy[i];
|
||||
to16bit[2*i] = 0x00;
|
||||
}
|
||||
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ILI9486_DC, 1); /*Data mode*/
|
||||
disp_spi_send_data(to16bit, (length*2));
|
||||
}
|
||||
|
||||
static void ili9486_send_color(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ILI9486_DC, 1); /*Data mode*/
|
||||
disp_spi_send_colors(data, length);
|
||||
}
|
||||
|
||||
static void ili9486_set_orientation(uint8_t orientation)
|
||||
{
|
||||
// ESP_ASSERT(orientation < 4);
|
||||
|
||||
const char *orientation_str[] = {
|
||||
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]);
|
||||
|
||||
#if defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE)
|
||||
uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]);
|
||||
|
||||
ili9486_send_cmd(0x36);
|
||||
ili9486_send_data((void *) &data[orientation], 1);
|
||||
}
|
61
lvgl_tft/ili9486.h
Normal file
61
lvgl_tft/ili9486.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* @file ili9486.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILI9486_H
|
||||
#define ILI9486_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
#include "../lvgl_helpers.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define ILI9486_DC CONFIG_LV_DISP_PIN_DC
|
||||
#define ILI9486_RST CONFIG_LV_DISP_PIN_RST
|
||||
#define ILI9486_BCKL CONFIG_LV_DISP_PIN_BCKL
|
||||
|
||||
#define ILI9486_ENABLE_BACKLIGHT_CONTROL CONFIG_LV_ENABLE_BACKLIGHT_CONTROL
|
||||
|
||||
#if CONFIG_LV_BACKLIGHT_ACTIVE_LVL
|
||||
#define ILI9486_BCKL_ACTIVE_LVL 1
|
||||
#else
|
||||
#define ILI9486_BCKL_ACTIVE_LVL 0
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void ili9486_init(void);
|
||||
void ili9486_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
|
||||
void ili9486_enable_backlight(bool backlight);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* ILI9486_H*/
|
233
lvgl_tft/ili9488.c
Normal file
233
lvgl_tft/ili9488.c
Normal file
|
@ -0,0 +1,233 @@
|
|||
/**
|
||||
* @file ili9488.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "ili9488.h"
|
||||
#include "disp_spi.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "ILI9488"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */
|
||||
typedef struct {
|
||||
uint8_t cmd;
|
||||
uint8_t data[16];
|
||||
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
|
||||
} lcd_init_cmd_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void ili9488_set_orientation(uint8_t orientation);
|
||||
|
||||
static void ili9488_send_cmd(uint8_t cmd);
|
||||
static void ili9488_send_data(void * data, uint16_t length);
|
||||
static void ili9488_send_color(void * data, uint16_t length);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
// From github.com/jeremyjh/ESP32_TFT_library
|
||||
// From github.com/mvturnho/ILI9488-lvgl-ESP32-WROVER-B
|
||||
void ili9488_init(void)
|
||||
{
|
||||
lcd_init_cmd_t ili_init_cmds[]={
|
||||
{ILI9488_CMD_SLEEP_OUT, {0x00}, 0x80},
|
||||
{ILI9488_CMD_POSITIVE_GAMMA_CORRECTION, {0x00, 0x03, 0x09, 0x08, 0x16, 0x0A, 0x3F, 0x78, 0x4C, 0x09, 0x0A, 0x08, 0x16, 0x1A, 0x0F}, 15},
|
||||
{ILI9488_CMD_NEGATIVE_GAMMA_CORRECTION, {0x00, 0x16, 0x19, 0x03, 0x0F, 0x05, 0x32, 0x45, 0x46, 0x04, 0x0E, 0x0D, 0x35, 0x37, 0x0F}, 15},
|
||||
{ILI9488_CMD_POWER_CONTROL_1, {0x17, 0x15}, 2},
|
||||
{ILI9488_CMD_POWER_CONTROL_2, {0x41}, 1},
|
||||
{ILI9488_CMD_VCOM_CONTROL_1, {0x00, 0x12, 0x80}, 3},
|
||||
{ILI9488_CMD_MEMORY_ACCESS_CONTROL, {(0x20 | 0x08)}, 1},
|
||||
{ILI9488_CMD_COLMOD_PIXEL_FORMAT_SET, {0x66}, 1},
|
||||
{ILI9488_CMD_INTERFACE_MODE_CONTROL, {0x00}, 1},
|
||||
{ILI9488_CMD_FRAME_RATE_CONTROL_NORMAL, {0xA0}, 1},
|
||||
{ILI9488_CMD_DISPLAY_INVERSION_CONTROL, {0x02}, 1},
|
||||
{ILI9488_CMD_DISPLAY_FUNCTION_CONTROL, {0x02, 0x02}, 2},
|
||||
{ILI9488_CMD_SET_IMAGE_FUNCTION, {0x00}, 1},
|
||||
{ILI9488_CMD_WRITE_CTRL_DISPLAY, {0x28}, 1},
|
||||
{ILI9488_CMD_WRITE_DISPLAY_BRIGHTNESS, {0x7F}, 1},
|
||||
{ILI9488_CMD_ADJUST_CONTROL_3, {0xA9, 0x51, 0x2C, 0x02}, 4},
|
||||
{ILI9488_CMD_DISPLAY_ON, {0x00}, 0x80},
|
||||
{0, {0}, 0xff},
|
||||
};
|
||||
|
||||
//Initialize non-SPI GPIOs
|
||||
gpio_pad_select_gpio(ILI9488_DC);
|
||||
gpio_set_direction(ILI9488_DC, GPIO_MODE_OUTPUT);
|
||||
gpio_pad_select_gpio(ILI9488_RST);
|
||||
gpio_set_direction(ILI9488_RST, GPIO_MODE_OUTPUT);
|
||||
|
||||
#if ILI9488_ENABLE_BACKLIGHT_CONTROL
|
||||
gpio_pad_select_gpio(ILI9488_BCKL);
|
||||
gpio_set_direction(ILI9488_BCKL, GPIO_MODE_OUTPUT);
|
||||
#endif
|
||||
|
||||
//Reset the display
|
||||
gpio_set_level(ILI9488_RST, 0);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
gpio_set_level(ILI9488_RST, 1);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
|
||||
ESP_LOGI(TAG, "ILI9488 initialization.");
|
||||
|
||||
// Exit sleep
|
||||
ili9488_send_cmd(0x01); /* Software reset */
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
|
||||
//Send all the commands
|
||||
uint16_t cmd = 0;
|
||||
while (ili_init_cmds[cmd].databytes!=0xff) {
|
||||
ili9488_send_cmd(ili_init_cmds[cmd].cmd);
|
||||
ili9488_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F);
|
||||
if (ili_init_cmds[cmd].databytes & 0x80) {
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
}
|
||||
cmd++;
|
||||
}
|
||||
|
||||
ili9488_enable_backlight(true);
|
||||
|
||||
ili9488_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION);
|
||||
}
|
||||
|
||||
// Flush function based on mvturnho repo
|
||||
void ili9488_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
|
||||
{
|
||||
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
|
||||
|
||||
lv_color16_t *buffer_16bit = (lv_color16_t *) color_map;
|
||||
uint8_t *mybuf;
|
||||
do {
|
||||
mybuf = (uint8_t *) heap_caps_malloc(3 * size * sizeof(uint8_t), MALLOC_CAP_DMA);
|
||||
if (mybuf == NULL) ESP_LOGW(TAG, "Could not allocate enough DMA memory!");
|
||||
} while (mybuf == NULL);
|
||||
|
||||
uint32_t LD = 0;
|
||||
uint32_t j = 0;
|
||||
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
LD = buffer_16bit[i].full;
|
||||
mybuf[j] = (uint8_t) (((LD & 0xF800) >> 8) | ((LD & 0x8000) >> 13));
|
||||
j++;
|
||||
mybuf[j] = (uint8_t) ((LD & 0x07E0) >> 3);
|
||||
j++;
|
||||
mybuf[j] = (uint8_t) (((LD & 0x001F) << 3) | ((LD & 0x0010) >> 2));
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Column addresses */
|
||||
uint8_t xb[] = {
|
||||
(uint8_t) (area->x1 >> 8) & 0xFF,
|
||||
(uint8_t) (area->x1) & 0xFF,
|
||||
(uint8_t) (area->x2 >> 8) & 0xFF,
|
||||
(uint8_t) (area->x2) & 0xFF,
|
||||
};
|
||||
|
||||
/* Page addresses */
|
||||
uint8_t yb[] = {
|
||||
(uint8_t) (area->y1 >> 8) & 0xFF,
|
||||
(uint8_t) (area->y1) & 0xFF,
|
||||
(uint8_t) (area->y2 >> 8) & 0xFF,
|
||||
(uint8_t) (area->y2) & 0xFF,
|
||||
};
|
||||
|
||||
/*Column addresses*/
|
||||
ili9488_send_cmd(ILI9488_CMD_COLUMN_ADDRESS_SET);
|
||||
ili9488_send_data(xb, 4);
|
||||
|
||||
/*Page addresses*/
|
||||
ili9488_send_cmd(ILI9488_CMD_PAGE_ADDRESS_SET);
|
||||
ili9488_send_data(yb, 4);
|
||||
|
||||
/*Memory write*/
|
||||
ili9488_send_cmd(ILI9488_CMD_MEMORY_WRITE);
|
||||
|
||||
ili9488_send_color((void *) mybuf, size * 3);
|
||||
heap_caps_free(mybuf);
|
||||
}
|
||||
|
||||
void ili9488_enable_backlight(bool backlight)
|
||||
{
|
||||
#if ILI9488_ENABLE_BACKLIGHT_CONTROL
|
||||
ESP_LOGI(TAG, "%s backlight.", backlight ? "Enabling" : "Disabling");
|
||||
uint32_t tmp = 0;
|
||||
|
||||
#if (ILI9488_BCKL_ACTIVE_LVL==1)
|
||||
tmp = backlight ? 1 : 0;
|
||||
#else
|
||||
tmp = backlight ? 0 : 1;
|
||||
#endif
|
||||
|
||||
gpio_set_level(ILI9488_BCKL, tmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
static void ili9488_send_cmd(uint8_t cmd)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ILI9488_DC, 0); /*Command mode*/
|
||||
disp_spi_send_data(&cmd, 1);
|
||||
}
|
||||
|
||||
static void ili9488_send_data(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ILI9488_DC, 1); /*Data mode*/
|
||||
disp_spi_send_data(data, length);
|
||||
}
|
||||
|
||||
static void ili9488_send_color(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ILI9488_DC, 1); /*Data mode*/
|
||||
disp_spi_send_colors(data, length);
|
||||
}
|
||||
|
||||
static void ili9488_set_orientation(uint8_t orientation)
|
||||
{
|
||||
// ESP_ASSERT(orientation < 4);
|
||||
|
||||
const char *orientation_str[] = {
|
||||
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]);
|
||||
|
||||
#if defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE)
|
||||
uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]);
|
||||
|
||||
ili9488_send_cmd(0x36);
|
||||
ili9488_send_data((void *) &data[orientation], 1);
|
||||
}
|
167
lvgl_tft/ili9488.h
Normal file
167
lvgl_tft/ili9488.h
Normal file
|
@ -0,0 +1,167 @@
|
|||
/**
|
||||
* @file ili9488.h
|
||||
*/
|
||||
|
||||
#ifndef ILI9844_H
|
||||
#define ILI9844_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
#include "../lvgl_helpers.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define ILI9488_DC CONFIG_LV_DISP_PIN_DC
|
||||
#define ILI9488_RST CONFIG_LV_DISP_PIN_RST
|
||||
#define ILI9488_BCKL CONFIG_LV_DISP_PIN_BCKL
|
||||
|
||||
#define ILI9488_ENABLE_BACKLIGHT_CONTROL CONFIG_LV_ENABLE_BACKLIGHT_CONTROL
|
||||
|
||||
#if CONFIG_LV_BACKLIGHT_ACTIVE_LVL
|
||||
#define ILI9488_BCKL_ACTIVE_LVL 1
|
||||
#else
|
||||
#define ILI9488_BCKL_ACTIVE_LVL 0
|
||||
#endif
|
||||
|
||||
/*******************
|
||||
* ILI9488 REGS
|
||||
*********************/
|
||||
|
||||
/* Level 1 Commands (from the display Datasheet) */
|
||||
#define ILI9488_CMD_NOP 0x00
|
||||
#define ILI9488_CMD_SOFTWARE_RESET 0x01
|
||||
#define ILI9488_CMD_READ_DISP_ID 0x04
|
||||
#define ILI9488_CMD_READ_ERROR_DSI 0x05
|
||||
#define ILI9488_CMD_READ_DISP_STATUS 0x09
|
||||
#define ILI9488_CMD_READ_DISP_POWER_MODE 0x0A
|
||||
#define ILI9488_CMD_READ_DISP_MADCTRL 0x0B
|
||||
#define ILI9488_CMD_READ_DISP_PIXEL_FORMAT 0x0C
|
||||
#define ILI9488_CMD_READ_DISP_IMAGE_MODE 0x0D
|
||||
#define ILI9488_CMD_READ_DISP_SIGNAL_MODE 0x0E
|
||||
#define ILI9488_CMD_READ_DISP_SELF_DIAGNOSTIC 0x0F
|
||||
#define ILI9488_CMD_ENTER_SLEEP_MODE 0x10
|
||||
#define ILI9488_CMD_SLEEP_OUT 0x11
|
||||
#define ILI9488_CMD_PARTIAL_MODE_ON 0x12
|
||||
#define ILI9488_CMD_NORMAL_DISP_MODE_ON 0x13
|
||||
#define ILI9488_CMD_DISP_INVERSION_OFF 0x20
|
||||
#define ILI9488_CMD_DISP_INVERSION_ON 0x21
|
||||
#define ILI9488_CMD_PIXEL_OFF 0x22
|
||||
#define ILI9488_CMD_PIXEL_ON 0x23
|
||||
#define ILI9488_CMD_DISPLAY_OFF 0x28
|
||||
#define ILI9488_CMD_DISPLAY_ON 0x29
|
||||
#define ILI9488_CMD_COLUMN_ADDRESS_SET 0x2A
|
||||
#define ILI9488_CMD_PAGE_ADDRESS_SET 0x2B
|
||||
#define ILI9488_CMD_MEMORY_WRITE 0x2C
|
||||
#define ILI9488_CMD_MEMORY_READ 0x2E
|
||||
#define ILI9488_CMD_PARTIAL_AREA 0x30
|
||||
#define ILI9488_CMD_VERT_SCROLL_DEFINITION 0x33
|
||||
#define ILI9488_CMD_TEARING_EFFECT_LINE_OFF 0x34
|
||||
#define ILI9488_CMD_TEARING_EFFECT_LINE_ON 0x35
|
||||
#define ILI9488_CMD_MEMORY_ACCESS_CONTROL 0x36
|
||||
#define ILI9488_CMD_VERT_SCROLL_START_ADDRESS 0x37
|
||||
#define ILI9488_CMD_IDLE_MODE_OFF 0x38
|
||||
#define ILI9488_CMD_IDLE_MODE_ON 0x39
|
||||
#define ILI9488_CMD_COLMOD_PIXEL_FORMAT_SET 0x3A
|
||||
#define ILI9488_CMD_WRITE_MEMORY_CONTINUE 0x3C
|
||||
#define ILI9488_CMD_READ_MEMORY_CONTINUE 0x3E
|
||||
#define ILI9488_CMD_SET_TEAR_SCANLINE 0x44
|
||||
#define ILI9488_CMD_GET_SCANLINE 0x45
|
||||
#define ILI9488_CMD_WRITE_DISPLAY_BRIGHTNESS 0x51
|
||||
#define ILI9488_CMD_READ_DISPLAY_BRIGHTNESS 0x52
|
||||
#define ILI9488_CMD_WRITE_CTRL_DISPLAY 0x53
|
||||
#define ILI9488_CMD_READ_CTRL_DISPLAY 0x54
|
||||
#define ILI9488_CMD_WRITE_CONTENT_ADAPT_BRIGHTNESS 0x55
|
||||
#define ILI9488_CMD_READ_CONTENT_ADAPT_BRIGHTNESS 0x56
|
||||
#define ILI9488_CMD_WRITE_MIN_CAB_LEVEL 0x5E
|
||||
#define ILI9488_CMD_READ_MIN_CAB_LEVEL 0x5F
|
||||
#define ILI9488_CMD_READ_ABC_SELF_DIAG_RES 0x68
|
||||
#define ILI9488_CMD_READ_ID1 0xDA
|
||||
#define ILI9488_CMD_READ_ID2 0xDB
|
||||
#define ILI9488_CMD_READ_ID3 0xDC
|
||||
|
||||
/* Level 2 Commands (from the display Datasheet) */
|
||||
#define ILI9488_CMD_INTERFACE_MODE_CONTROL 0xB0
|
||||
#define ILI9488_CMD_FRAME_RATE_CONTROL_NORMAL 0xB1
|
||||
#define ILI9488_CMD_FRAME_RATE_CONTROL_IDLE_8COLOR 0xB2
|
||||
#define ILI9488_CMD_FRAME_RATE_CONTROL_PARTIAL 0xB3
|
||||
#define ILI9488_CMD_DISPLAY_INVERSION_CONTROL 0xB4
|
||||
#define ILI9488_CMD_BLANKING_PORCH_CONTROL 0xB5
|
||||
#define ILI9488_CMD_DISPLAY_FUNCTION_CONTROL 0xB6
|
||||
#define ILI9488_CMD_ENTRY_MODE_SET 0xB7
|
||||
#define ILI9488_CMD_BACKLIGHT_CONTROL_1 0xB9
|
||||
#define ILI9488_CMD_BACKLIGHT_CONTROL_2 0xBA
|
||||
#define ILI9488_CMD_HS_LANES_CONTROL 0xBE
|
||||
#define ILI9488_CMD_POWER_CONTROL_1 0xC0
|
||||
#define ILI9488_CMD_POWER_CONTROL_2 0xC1
|
||||
#define ILI9488_CMD_POWER_CONTROL_NORMAL_3 0xC2
|
||||
#define ILI9488_CMD_POWER_CONTROL_IDEL_4 0xC3
|
||||
#define ILI9488_CMD_POWER_CONTROL_PARTIAL_5 0xC4
|
||||
#define ILI9488_CMD_VCOM_CONTROL_1 0xC5
|
||||
#define ILI9488_CMD_CABC_CONTROL_1 0xC6
|
||||
#define ILI9488_CMD_CABC_CONTROL_2 0xC8
|
||||
#define ILI9488_CMD_CABC_CONTROL_3 0xC9
|
||||
#define ILI9488_CMD_CABC_CONTROL_4 0xCA
|
||||
#define ILI9488_CMD_CABC_CONTROL_5 0xCB
|
||||
#define ILI9488_CMD_CABC_CONTROL_6 0xCC
|
||||
#define ILI9488_CMD_CABC_CONTROL_7 0xCD
|
||||
#define ILI9488_CMD_CABC_CONTROL_8 0xCE
|
||||
#define ILI9488_CMD_CABC_CONTROL_9 0xCF
|
||||
#define ILI9488_CMD_NVMEM_WRITE 0xD0
|
||||
#define ILI9488_CMD_NVMEM_PROTECTION_KEY 0xD1
|
||||
#define ILI9488_CMD_NVMEM_STATUS_READ 0xD2
|
||||
#define ILI9488_CMD_READ_ID4 0xD3
|
||||
#define ILI9488_CMD_ADJUST_CONTROL_1 0xD7
|
||||
#define ILI9488_CMD_READ_ID_VERSION 0xD8
|
||||
#define ILI9488_CMD_POSITIVE_GAMMA_CORRECTION 0xE0
|
||||
#define ILI9488_CMD_NEGATIVE_GAMMA_CORRECTION 0xE1
|
||||
#define ILI9488_CMD_DIGITAL_GAMMA_CONTROL_1 0xE2
|
||||
#define ILI9488_CMD_DIGITAL_GAMMA_CONTROL_2 0xE3
|
||||
#define ILI9488_CMD_SET_IMAGE_FUNCTION 0xE9
|
||||
#define ILI9488_CMD_ADJUST_CONTROL_2 0xF2
|
||||
#define ILI9488_CMD_ADJUST_CONTROL_3 0xF7
|
||||
#define ILI9488_CMD_ADJUST_CONTROL_4 0xF8
|
||||
#define ILI9488_CMD_ADJUST_CONTROL_5 0xF9
|
||||
#define ILI9488_CMD_SPI_READ_SETTINGS 0xFB
|
||||
#define ILI9488_CMD_ADJUST_CONTROL_6 0xFC
|
||||
#define ILI9488_CMD_ADJUST_CONTROL_7 0xFF
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
} lv_color_custom_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void ili9488_init(void);
|
||||
void ili9488_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
|
||||
void ili9488_enable_backlight(bool backlight);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*ILI9488_H*/
|
482
lvgl_tft/jd79653a.c
Normal file
482
lvgl_tft/jd79653a.c
Normal file
|
@ -0,0 +1,482 @@
|
|||
/**
|
||||
@file jd79653a.c
|
||||
@brief GoodDisplay GDEW0154M09 e-paper display w/ FitiPower JD79653A
|
||||
@version 1.0
|
||||
@date 2020-08-28
|
||||
@author Jackson Ming Hu <huming2207@gmail.com>
|
||||
|
||||
|
||||
@section LICENSE
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Jackson Ming Hu
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/event_groups.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#include "disp_spi.h"
|
||||
#include "jd79653a.h"
|
||||
|
||||
#define TAG "lv_jd79653a"
|
||||
|
||||
#define PIN_DC CONFIG_LV_DISP_PIN_DC
|
||||
#define PIN_DC_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_DC)))
|
||||
#define PIN_RST CONFIG_LV_DISP_PIN_RST
|
||||
#define PIN_RST_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_RST)))
|
||||
#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_ROW_LEN (EPD_HEIGHT / 8u)
|
||||
#define EPD_PARTIAL_CNT 5;
|
||||
|
||||
#define BIT_SET(a, b) ((a) |= (1U << (b)))
|
||||
#define BIT_CLEAR(a, b) ((a) &= ~(1U << (b)))
|
||||
|
||||
static uint8_t partial_counter = 0;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint8_t data[3];
|
||||
size_t len;
|
||||
} jd79653a_seq_t;
|
||||
|
||||
#define EPD_SEQ_LEN(x) ((sizeof(x) / sizeof(jd79653a_seq_t)))
|
||||
|
||||
static const uint8_t lut_vcom_dc1[] = {
|
||||
0x01, 0x04, 0x04, 0x03, 0x01, 0x01, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t lut_ww1[] = {
|
||||
0x01, 0x04, 0x04, 0x03, 0x01, 0x01, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t lut_bw1[] = {
|
||||
0x01, 0x84, 0x84, 0x83, 0x01, 0x01, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t lut_wb1[] = {
|
||||
0x01, 0x44, 0x44, 0x43, 0x01, 0x01, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t lut_bb1[] = {
|
||||
0x01, 0x04, 0x04, 0x03, 0x01, 0x01, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
||||
static const jd79653a_seq_t init_seq[] = {
|
||||
#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
|
||||
{0x00, {0xd3, 0x0e}, 2}, // Panel settings
|
||||
#elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
|
||||
{0x00, {0xdf, 0x0e}, 2}, // Panel settings
|
||||
#else
|
||||
#error "Unsupported orientation - only portrait modes are supported for now"
|
||||
#endif
|
||||
{0x4d, {0x55}, 1}, // Undocumented secret from demo code
|
||||
{0xaa, {0x0f}, 1}, // Undocumented secret from demo code
|
||||
{0xe9, {0x02}, 1}, // Undocumented secret from demo code
|
||||
{0xb6, {0x11}, 1}, // Undocumented secret from demo code
|
||||
{0xf3, {0x0a}, 1}, // Undocumented secret from demo code
|
||||
{0x61, {0xc8, 0x00, 0xc8}, 3}, // Resolution settings
|
||||
{0x60, {0x00}, 1}, // TCON
|
||||
{0x50, {0x97}, 1}, // VCOM sequence
|
||||
{0xe3, {0x00}, 1}, // Power saving settings
|
||||
};
|
||||
|
||||
static const jd79653a_seq_t power_on_seq[] = {
|
||||
{0x50, {0x97}, 1}, // VCOM sequence
|
||||
{0x04, {}, 0}, // Power on
|
||||
};
|
||||
|
||||
|
||||
static const jd79653a_seq_t power_off_seq[] = {
|
||||
{0x50, {0xf7}, 1}, // VCOM sequence
|
||||
{0x02, {}, 0}, // Power off
|
||||
};
|
||||
|
||||
static EventGroupHandle_t jd79653a_evts = NULL;
|
||||
|
||||
static void IRAM_ATTR jd79653a_busy_intr(void *arg)
|
||||
{
|
||||
BaseType_t xResult;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xResult = xEventGroupSetBitsFromISR(jd79653a_evts, EVT_BUSY, &xHigherPriorityTaskWoken);
|
||||
if (xResult == pdPASS) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
static void jd79653a_spi_send_cmd(uint8_t cmd)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(PIN_DC, 0); // DC = 0 for command
|
||||
disp_spi_send_data(&cmd, 1);
|
||||
}
|
||||
|
||||
static void jd79653a_spi_send_data(uint8_t *data, size_t len)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(PIN_DC, 1); // DC = 1 for data
|
||||
disp_spi_send_data(data, len);
|
||||
}
|
||||
|
||||
static void jd79653a_spi_send_fb(uint8_t *data, size_t len)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(PIN_DC, 1); // DC = 1 for data
|
||||
disp_spi_send_colors(data, len);
|
||||
}
|
||||
|
||||
static void jd79653a_spi_send_seq(const jd79653a_seq_t *seq, size_t len)
|
||||
{
|
||||
ESP_LOGD(TAG, "Writing cmd/data sequence, count %u", len);
|
||||
|
||||
if (!seq || len < 1) return;
|
||||
for (size_t cmd_idx = 0; cmd_idx < len; cmd_idx++) {
|
||||
jd79653a_spi_send_cmd(seq[cmd_idx].cmd);
|
||||
if (seq[cmd_idx].len > 0) {
|
||||
jd79653a_spi_send_data((uint8_t *) seq[cmd_idx].data, seq[cmd_idx].len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t jd79653a_wait_busy(uint32_t timeout_ms)
|
||||
{
|
||||
uint32_t wait_ticks = (timeout_ms == 0 ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms));
|
||||
EventBits_t bits = xEventGroupWaitBits(jd79653a_evts,
|
||||
EVT_BUSY, // Wait for busy bit
|
||||
pdTRUE, pdTRUE, // Clear on exit, wait for all
|
||||
wait_ticks); // Timeout
|
||||
|
||||
return ((bits & EVT_BUSY) != 0) ? ESP_OK : ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
static void jd79653a_power_on()
|
||||
{
|
||||
jd79653a_spi_send_seq(power_on_seq, EPD_SEQ_LEN(power_on_seq));
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
jd79653a_wait_busy(0);
|
||||
}
|
||||
|
||||
static void jd79653a_power_off()
|
||||
{
|
||||
jd79653a_spi_send_seq(power_off_seq, EPD_SEQ_LEN(power_off_seq));
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
jd79653a_wait_busy(0);
|
||||
}
|
||||
|
||||
static void jd79653a_load_partial_lut()
|
||||
{
|
||||
jd79653a_spi_send_cmd(0x20); // LUT VCOM register
|
||||
jd79653a_spi_send_data((uint8_t *)lut_vcom_dc1, sizeof(lut_vcom_dc1));
|
||||
|
||||
jd79653a_spi_send_cmd(0x21); // LUT White-to-White
|
||||
jd79653a_spi_send_data((uint8_t *)lut_ww1, sizeof(lut_ww1));
|
||||
|
||||
jd79653a_spi_send_cmd(0x22); // LUT Black-to-White
|
||||
jd79653a_spi_send_data((uint8_t *)lut_bw1, sizeof(lut_bw1));
|
||||
|
||||
jd79653a_spi_send_cmd(0x23); // LUT White-to-Black
|
||||
jd79653a_spi_send_data((uint8_t *)lut_wb1,sizeof(lut_wb1));
|
||||
|
||||
jd79653a_spi_send_cmd(0x24); // LUT Black-to-Black
|
||||
jd79653a_spi_send_data((uint8_t *)lut_bb1, sizeof(lut_bb1));
|
||||
}
|
||||
|
||||
static void jd79653a_partial_in()
|
||||
{
|
||||
ESP_LOGD(TAG, "Partial in!");
|
||||
|
||||
// Panel setting: accept LUT from registers instead of OTP
|
||||
#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
|
||||
uint8_t pst_use_reg_lut[] = { 0xf3, 0x0e };
|
||||
#elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
|
||||
uint8_t pst_use_reg_lut[] = { 0xff, 0x0e };
|
||||
#else
|
||||
#error "Unsupported orientation - only portrait modes are supported for now"
|
||||
#endif
|
||||
jd79653a_spi_send_cmd(0x00);
|
||||
jd79653a_spi_send_data(pst_use_reg_lut, sizeof(pst_use_reg_lut));
|
||||
|
||||
// WORKAROUND: need to ignore OLD framebuffer or otherwise partial refresh won't work
|
||||
uint8_t vcom = 0xb7;
|
||||
jd79653a_spi_send_cmd(0x50);
|
||||
jd79653a_spi_send_data(&vcom, 1);
|
||||
|
||||
// Dump LUT in
|
||||
jd79653a_load_partial_lut();
|
||||
|
||||
// Go partial!
|
||||
jd79653a_spi_send_cmd(0x91);
|
||||
}
|
||||
|
||||
static void jd79653a_partial_out()
|
||||
{
|
||||
ESP_LOGD(TAG, "Partial out!");
|
||||
|
||||
// Panel setting: use LUT from OTP
|
||||
#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
|
||||
uint8_t pst_use_otp_lut[] = { 0xd3, 0x0e };
|
||||
#elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
|
||||
uint8_t pst_use_otp_lut[] = { 0xdf, 0x0e };
|
||||
#else
|
||||
#error "Unsupported orientation - only portrait modes are supported for now"
|
||||
#endif
|
||||
jd79653a_spi_send_cmd(0x00);
|
||||
jd79653a_spi_send_data(pst_use_otp_lut, sizeof(pst_use_otp_lut));
|
||||
|
||||
// WORKAROUND: re-enable OLD framebuffer to get a better full refresh
|
||||
uint8_t vcom = 0x97;
|
||||
jd79653a_spi_send_cmd(0x50);
|
||||
jd79653a_spi_send_data(&vcom, 1);
|
||||
|
||||
// Out from partial!
|
||||
jd79653a_spi_send_cmd(0x92);
|
||||
}
|
||||
|
||||
static void jd79653a_update_partial(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t *data)
|
||||
{
|
||||
jd79653a_power_on();
|
||||
jd79653a_partial_in();
|
||||
ESP_LOGD(TAG, "x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", x1, x2, y1, y2);
|
||||
|
||||
size_t len = ((x2 - x1 + 1) * (y2 - y1 + 1)) / 8;
|
||||
ESP_LOGD(TAG, "Writing PARTIAL LVGL fb with len: %u", len);
|
||||
|
||||
// Set partial window
|
||||
uint8_t ptl_setting[7] = { x1, x2, 0, y1, 0, y2, 0x01 };
|
||||
jd79653a_spi_send_cmd(0x90);
|
||||
jd79653a_spi_send_data(ptl_setting, sizeof(ptl_setting));
|
||||
|
||||
uint8_t *data_ptr = data;
|
||||
|
||||
jd79653a_spi_send_cmd(0x13);
|
||||
for (size_t h_idx = 0; h_idx < EPD_HEIGHT; h_idx++) {
|
||||
jd79653a_spi_send_data(data_ptr, EPD_ROW_LEN);
|
||||
data_ptr += EPD_ROW_LEN;
|
||||
len -= EPD_ROW_LEN;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Partial wait start");
|
||||
|
||||
jd79653a_spi_send_cmd(0x12);
|
||||
jd79653a_wait_busy(0);
|
||||
|
||||
ESP_LOGD(TAG, "Partial updated");
|
||||
jd79653a_partial_out();
|
||||
jd79653a_power_off();
|
||||
}
|
||||
|
||||
void jd79653a_fb_set_full_color(uint8_t color)
|
||||
{
|
||||
jd79653a_power_on();
|
||||
uint8_t old_data[EPD_ROW_LEN];
|
||||
memset(old_data, ~(color), EPD_ROW_LEN);
|
||||
|
||||
// Fill OLD data (maybe not necessary)
|
||||
jd79653a_spi_send_cmd(0x10);
|
||||
for (size_t idx = 0; idx < EPD_HEIGHT; idx++) {
|
||||
jd79653a_spi_send_data(old_data, EPD_ROW_LEN);
|
||||
}
|
||||
|
||||
// Fill NEW data
|
||||
jd79653a_spi_send_cmd(0x13);
|
||||
for (size_t h_idx = 0; h_idx < EPD_HEIGHT; h_idx++) {
|
||||
for (size_t w_idx = 0; w_idx < EPD_ROW_LEN; w_idx++) {
|
||||
jd79653a_spi_send_data(&color, sizeof(color));
|
||||
}
|
||||
}
|
||||
|
||||
jd79653a_spi_send_cmd(0x12); // Issue refresh command
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
jd79653a_wait_busy(0);
|
||||
|
||||
jd79653a_power_off();
|
||||
}
|
||||
|
||||
void jd79653a_fb_full_update(uint8_t *data, size_t len)
|
||||
{
|
||||
jd79653a_power_on();
|
||||
ESP_LOGD(TAG, "Performing full update, len: %u", len);
|
||||
|
||||
uint8_t *data_ptr = data;
|
||||
|
||||
// Fill OLD data (maybe not necessary)
|
||||
uint8_t old_data[EPD_ROW_LEN] = { 0 };
|
||||
jd79653a_spi_send_cmd(0x10);
|
||||
for (size_t idx = 0; idx < EPD_HEIGHT; idx++) {
|
||||
jd79653a_spi_send_data(old_data, EPD_ROW_LEN);
|
||||
}
|
||||
|
||||
// Fill NEW data
|
||||
jd79653a_spi_send_cmd(0x13);
|
||||
for (size_t h_idx = 0; h_idx < EPD_HEIGHT; h_idx++) {
|
||||
jd79653a_spi_send_data(data_ptr, EPD_ROW_LEN);
|
||||
data_ptr += EPD_ROW_LEN;
|
||||
len -= EPD_ROW_LEN;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Rest len: %u", len);
|
||||
|
||||
jd79653a_spi_send_cmd(0x12); // Issue refresh command
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
jd79653a_wait_busy(0);
|
||||
|
||||
jd79653a_power_off();
|
||||
}
|
||||
|
||||
void jd79653a_lv_set_fb_cb(struct _disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
uint16_t byte_index = (x >> 3u) + (y * EPD_ROW_LEN);
|
||||
uint8_t bit_index = x & 0x07u;
|
||||
|
||||
if (color.full) {
|
||||
BIT_SET(buf[byte_index], 7 - bit_index);
|
||||
} else {
|
||||
BIT_CLEAR(buf[byte_index], 7 - bit_index);
|
||||
}
|
||||
}
|
||||
|
||||
void jd79653a_lv_rounder_cb(struct _disp_drv_t *disp_drv, lv_area_t *area)
|
||||
{
|
||||
// Always send full framebuffer if it's not in partial mode
|
||||
area->x1 = 0;
|
||||
area->y1 = 0;
|
||||
area->x2 = EPD_WIDTH - 1;
|
||||
area->y2 = EPD_HEIGHT - 1;
|
||||
}
|
||||
|
||||
void jd79653a_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
|
||||
{
|
||||
size_t len = ((area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1)) / 8;
|
||||
|
||||
ESP_LOGD(TAG, "x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", area->x1, area->x2, area->y1, area->y2);
|
||||
ESP_LOGD(TAG, "Writing LVGL fb with len: %u, partial counter: %u", len, partial_counter);
|
||||
|
||||
uint8_t *buf = (uint8_t *) color_map;
|
||||
|
||||
if (partial_counter == 0) {
|
||||
ESP_LOGD(TAG, "Refreshing in FULL");
|
||||
jd79653a_fb_full_update(buf, ((EPD_HEIGHT * EPD_WIDTH) / 8));
|
||||
partial_counter = EPD_PARTIAL_CNT; // Reset partial counter here
|
||||
} else {
|
||||
jd79653a_update_partial(area->x1, area->y1, area->x2, area->y2, buf);
|
||||
partial_counter -= 1; // ...or otherwise, decrease 1
|
||||
}
|
||||
|
||||
lv_disp_flush_ready(drv);
|
||||
}
|
||||
|
||||
void jd79653a_deep_sleep()
|
||||
{
|
||||
jd79653a_spi_send_seq(power_off_seq, EPD_SEQ_LEN(power_off_seq));
|
||||
jd79653a_wait_busy(1000);
|
||||
|
||||
uint8_t check_code = 0xa5;
|
||||
jd79653a_spi_send_cmd(0x07);
|
||||
jd79653a_spi_send_data(&check_code, sizeof(check_code));
|
||||
}
|
||||
|
||||
void jd79653a_init()
|
||||
{
|
||||
// Initialise event group
|
||||
jd79653a_evts = xEventGroupCreate();
|
||||
if (!jd79653a_evts) {
|
||||
ESP_LOGE(TAG, "Failed when initialising event group!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup output pins, output (PP)
|
||||
gpio_config_t out_io_conf = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = PIN_DC_BIT | PIN_RST_BIT,
|
||||
.pull_down_en = 0,
|
||||
.pull_up_en = 0,
|
||||
};
|
||||
ESP_ERROR_CHECK(gpio_config(&out_io_conf));
|
||||
|
||||
// Setup input pin, pull-up, input
|
||||
gpio_config_t in_io_conf = {
|
||||
.intr_type = GPIO_INTR_POSEDGE,
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pin_bit_mask = PIN_BUSY_BIT,
|
||||
.pull_down_en = 0,
|
||||
.pull_up_en = 1,
|
||||
};
|
||||
ESP_ERROR_CHECK(gpio_config(&in_io_conf));
|
||||
gpio_install_isr_service(0);
|
||||
gpio_isr_handler_add(PIN_BUSY, jd79653a_busy_intr, (void *) PIN_BUSY);
|
||||
|
||||
// Hardware reset
|
||||
gpio_set_level(PIN_RST, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(15)); // At least 10ms, leave 15ms for now just in case...
|
||||
gpio_set_level(PIN_RST, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
|
||||
// Dump in initialise sequence
|
||||
jd79653a_spi_send_seq(init_seq, EPD_SEQ_LEN(init_seq));
|
||||
ESP_LOGI(TAG, "Panel init sequence sent");
|
||||
|
||||
// Check BUSY status here
|
||||
jd79653a_wait_busy(0);
|
||||
|
||||
ESP_LOGI(TAG, "Panel is up!");
|
||||
}
|
36
lvgl_tft/jd79653a.h
Normal file
36
lvgl_tft/jd79653a.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* @file il3820.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef JD79653A_H
|
||||
#define JD79653A_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
void jd79653a_init();
|
||||
void jd79653a_deep_sleep();
|
||||
|
||||
void jd79653a_lv_set_fb_cb(struct _disp_drv_t * disp_drv, uint8_t* buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t color, lv_opa_t opa);
|
||||
void jd79653a_lv_rounder_cb(struct _disp_drv_t * disp_drv, lv_area_t *area);
|
||||
void jd79653a_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map);
|
||||
|
||||
void jd79653a_fb_set_full_color(uint8_t color);
|
||||
void jd79653a_fb_full_update(uint8_t *data, size_t len);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif // JD79653A_H
|
365
lvgl_tft/ra8875.c
Normal file
365
lvgl_tft/ra8875.c
Normal file
|
@ -0,0 +1,365 @@
|
|||
/**
|
||||
* @file ra8875.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "ra8875.h"
|
||||
#include "disp_spi.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define DEBUG false
|
||||
#define TAG "RA8875"
|
||||
|
||||
#define DIV_ROUND_UP(n, d) (((n)+(d)-1)/(d))
|
||||
|
||||
#define SPI_CLOCK_SPEED_SLOW_HZ 1000000
|
||||
|
||||
#define RA8875_MODE_DATA_WRITE (0x00)
|
||||
#define RA8875_MODE_DATA_READ (0x40)
|
||||
#define RA8875_MODE_CMD_WRITE (0x80)
|
||||
#define RA8875_MODE_STATUS_READ (0xC0)
|
||||
|
||||
#if (LV_COLOR_DEPTH == 8)
|
||||
#define SYSR_VAL (0x00)
|
||||
#elif (LV_COLOR_DEPTH == 16)
|
||||
#define SYSR_VAL (0x08)
|
||||
#else
|
||||
#error "Unsupported color depth (LV_COLOR_DEPTH)"
|
||||
#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 VDIR_MASK (1 << 2)
|
||||
#define HDIR_MASK (1 << 3)
|
||||
|
||||
#if ( CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED || CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED )
|
||||
#if CONFIG_LV_INVERT_DISPLAY
|
||||
#define DPCR_VAL (VDIR_MASK)
|
||||
#else
|
||||
#define DPCR_VAL (VDIR_MASK | HDIR_MASK)
|
||||
#endif
|
||||
#else
|
||||
#if CONFIG_LV_INVERT_DISPLAY
|
||||
#define DPCR_VAL (HDIR_MASK)
|
||||
#else
|
||||
#define DPCR_VAL (0x00)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_LV_DISP_RA8875_PCLK_INVERT
|
||||
#define PCSR_VAL (0x80 | CONFIG_LV_DISP_RA8875_PCLK_MULTIPLIER)
|
||||
#else
|
||||
#define PCSR_VAL (CONFIG_LV_DISP_RA8875_PCLK_MULTIPLIER)
|
||||
#endif
|
||||
|
||||
// Calculate horizontal display parameters
|
||||
#if (CONFIG_LV_DISP_RA8875_HORI_NON_DISP_PERIOD >= 260)
|
||||
#define HNDR_VAL (31)
|
||||
#else
|
||||
#define HNDR_VAL ((CONFIG_LV_DISP_RA8875_HORI_NON_DISP_PERIOD-12) / 8)
|
||||
#endif
|
||||
#define HNDFT (CONFIG_LV_DISP_RA8875_HORI_NON_DISP_PERIOD-(8*HNDR_VAL)-12)
|
||||
#if LVGL_DISP_RA8875_DE_POLARITY
|
||||
#define HNDFTR_VAL (0x80 | HNDFT)
|
||||
#else
|
||||
#define HNDFTR_VAL (HNDFT)
|
||||
#endif
|
||||
#define HSTR_VAL (CONFIG_LV_DISP_RA8875_HSYNC_START/8 - 1)
|
||||
#define HPW (CONFIG_LV_DISP_RA8875_HSYNC_PW/8 - 1)
|
||||
#if LVGL_DISP_RA8875_HSYNC_POLARITY
|
||||
#define HPWR_VAL (0x80 | HPW)
|
||||
#else
|
||||
#define HPWR_VAL (HPW)
|
||||
#endif
|
||||
|
||||
// Calculate vertical display parameters
|
||||
#define VNDR_VAL (CONFIG_LV_DISP_RA8875_VERT_NON_DISP_PERIOD - 1)
|
||||
#define VSTR_VAL (CONFIG_LV_DISP_RA8875_VSYNC_START - 1)
|
||||
#define VPW (CONFIG_LV_DISP_RA8875_VSYNC_PW - 1)
|
||||
#if LVGL_DISP_RA8875_VSYNC_POLARITY
|
||||
#define VPWR_VAL (0x80 | VPW)
|
||||
#else
|
||||
#define VPWR_VAL (VPW)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void ra8875_configure_clocks(bool high_speed);
|
||||
static void ra8875_set_memory_write_cursor(unsigned int x, unsigned int y);
|
||||
static void ra8875_set_window(unsigned int xs, unsigned int xe, unsigned int ys, unsigned int ye);
|
||||
static void ra8875_send_buffer(uint8_t * data, size_t length, bool signal_flush);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void ra8875_init(void)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
struct {
|
||||
uint8_t cmd; // Register address of command
|
||||
uint8_t data; // Value to write to register
|
||||
} init_cmds[] = {
|
||||
{RA8875_REG_SYSR, SYSR_VAL}, // System Configuration Register (SYSR)
|
||||
{RA8875_REG_HDWR, HDWR_VAL}, // LCD Horizontal Display Width Register (HDWR)
|
||||
{RA8875_REG_HNDFTR, HNDFTR_VAL}, // Horizontal Non-Display Period Fine Tuning Option Register (HNDFTR)
|
||||
{RA8875_REG_HNDR, HNDR_VAL}, // Horizontal Non-Display Period Register (HNDR)
|
||||
{RA8875_REG_HSTR, HSTR_VAL}, // HSYNC Start Position Register (HSTR)
|
||||
{RA8875_REG_HPWR, HPWR_VAL}, // HSYNC Pulse Width Register (HPWR)
|
||||
{RA8875_REG_VDHR0, VDHR_VAL & 0x0FF}, // LCD Vertical Display Height Register (VDHR0)
|
||||
{RA8875_REG_VDHR1, VDHR_VAL >> 8}, // LCD Vertical Display Height Register0 (VDHR1)
|
||||
{RA8875_REG_VNDR0, VNDR_VAL & 0x0FF}, // LCD Vertical Non-Display Period Register (VNDR0)
|
||||
{RA8875_REG_VNDR1, VNDR_VAL >> 8}, // LCD Vertical Non-Display Period Register (VNDR1)
|
||||
{RA8875_REG_VSTR0, VSTR_VAL & 0x0FF}, // VSYNC Start Position Register (VSTR0)
|
||||
{RA8875_REG_VSTR1, VSTR_VAL >> 8}, // VSYNC Start Position Register (VSTR1)
|
||||
{RA8875_REG_VPWR, VPWR_VAL}, // VSYNC Pulse Width Register (VPWR)
|
||||
{RA8875_REG_DPCR, DPCR_VAL}, // Display Configuration Register (DPCR)
|
||||
{RA8875_REG_MWCR0, 0x00}, // Memory Write Control Register 0 (MWCR0)
|
||||
{RA8875_REG_MWCR1, 0x00}, // Memory Write Control Register 1 (MWCR1)
|
||||
{RA8875_REG_LTPR0, 0x00}, // Layer Transparency Register0 (LTPR0)
|
||||
{RA8875_REG_LTPR1, 0x00}, // Layer Transparency Register1 (LTPR1)
|
||||
};
|
||||
#define INIT_CMDS_SIZE (sizeof(init_cmds)/sizeof(init_cmds[0]))
|
||||
|
||||
ESP_LOGI(TAG, "Initializing RA8875...");
|
||||
|
||||
#if (CONFIG_LV_DISP_PIN_BCKL == 15)
|
||||
gpio_config_t io_conf;
|
||||
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = GPIO_SEL_15;
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
gpio_config(&io_conf);
|
||||
#endif
|
||||
|
||||
// Initialize non-SPI GPIOs
|
||||
gpio_pad_select_gpio(RA8875_RST);
|
||||
gpio_set_direction(RA8875_RST, GPIO_MODE_OUTPUT);
|
||||
#ifdef CONFIG_LV_DISP_PIN_BCKL
|
||||
gpio_pad_select_gpio(CONFIG_LV_DISP_PIN_BCKL);
|
||||
gpio_set_direction(CONFIG_LV_DISP_PIN_BCKL, GPIO_MODE_OUTPUT);
|
||||
#endif
|
||||
|
||||
// Reset the RA8875
|
||||
gpio_set_level(RA8875_RST, 0);
|
||||
vTaskDelay(DIV_ROUND_UP(100, portTICK_RATE_MS));
|
||||
gpio_set_level(RA8875_RST, 1);
|
||||
vTaskDelay(DIV_ROUND_UP(100, portTICK_RATE_MS));
|
||||
|
||||
// Initalize RA8875 clocks (SPI must be decelerated before initializing clocks)
|
||||
disp_spi_change_device_speed(SPI_CLOCK_SPEED_SLOW_HZ);
|
||||
ra8875_configure_clocks(true);
|
||||
disp_spi_change_device_speed(-1);
|
||||
|
||||
// Send all the commands
|
||||
for (i = 0; i < INIT_CMDS_SIZE; i++) {
|
||||
ra8875_write_cmd(init_cmds[i].cmd, init_cmds[i].data);
|
||||
}
|
||||
|
||||
// Perform a memory clear (wait maximum of 100 ticks)
|
||||
ra8875_write_cmd(RA8875_REG_MCLR, 0x80);
|
||||
for(i = 100; i != 0; i--) {
|
||||
if ((ra8875_read_cmd(RA8875_REG_MCLR) & 0x80) == 0x00) {
|
||||
break;
|
||||
}
|
||||
vTaskDelay(1);
|
||||
}
|
||||
if (i == 0) {
|
||||
ESP_LOGW(TAG, "WARNING: Memory clear timed out; RA8875 may be unresponsive.");
|
||||
}
|
||||
|
||||
// Enable the display and backlight
|
||||
ra8875_enable_display(true);
|
||||
ra8875_enable_backlight(true);
|
||||
}
|
||||
|
||||
void ra8875_enable_backlight(bool backlight)
|
||||
{
|
||||
#if CONFIG_LV_ENABLE_BACKLIGHT_CONTROL
|
||||
ESP_LOGI(TAG, "%s backlight.", backlight ? "Enabling" : "Disabling");
|
||||
uint32_t tmp = 0;
|
||||
|
||||
#if CONFIG_LV_BACKLIGHT_ACTIVE_LVL
|
||||
tmp = backlight ? 1 : 0;
|
||||
#else
|
||||
tmp = backlight ? 0 : 1;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LV_DISP_PIN_BCKL
|
||||
gpio_set_level(CONFIG_LV_DISP_PIN_BCKL, tmp);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void ra8875_enable_display(bool enable)
|
||||
{
|
||||
ESP_LOGI(TAG, "%s display.", enable ? "Enabling" : "Disabling");
|
||||
uint8_t val = enable ? (0x80) : (0x00);
|
||||
ra8875_write_cmd(RA8875_REG_PWRR, val); // Power and Display Control Register (PWRR)
|
||||
}
|
||||
|
||||
|
||||
void ra8875_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
|
||||
{
|
||||
static lv_coord_t x1 = LV_COORD_MIN;
|
||||
static lv_coord_t x2 = LV_COORD_MIN;
|
||||
static lv_coord_t x = LV_COORD_MIN;
|
||||
static lv_coord_t y = LV_COORD_MIN;
|
||||
|
||||
size_t linelen = (area->x2 - area->x1 + 1);
|
||||
uint8_t * buffer = (uint8_t*)color_map;
|
||||
|
||||
#if DEBUG
|
||||
ESP_LOGI(TAG, "flush: %d,%d at %d,%d", area->x1, area->x2, area->y1, area->y2 );
|
||||
#endif
|
||||
|
||||
// Get lock
|
||||
disp_spi_acquire();
|
||||
|
||||
// Set window if needed
|
||||
if ((x1 != area->x1) || (x2 != area->x2)) {
|
||||
#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);
|
||||
x1 = area->x1;
|
||||
x2 = area->x2;
|
||||
}
|
||||
|
||||
// Set cursor if needed
|
||||
if ((x != area->x1) || (y != area->y1)) {
|
||||
#if DEBUG
|
||||
ESP_LOGI(TAG, "flush: set cursor (x,y): %d,%d -> %d,%d", x, y, area->x1, area->y1);
|
||||
#endif
|
||||
ra8875_set_memory_write_cursor(area->x1, area->y1);
|
||||
x = area->x1;
|
||||
}
|
||||
|
||||
// Update to future cursor location
|
||||
y = area->y2 + 1;
|
||||
if (y >= CONFIG_LV_DISPLAY_HEIGHT) {
|
||||
y = 0;
|
||||
}
|
||||
|
||||
// Write data
|
||||
ra8875_send_buffer(buffer, (area->y2 - area->y1 + 1)*BYTES_PER_PIXEL*linelen, true);
|
||||
|
||||
// Release lock
|
||||
disp_spi_release();
|
||||
}
|
||||
|
||||
void ra8875_sleep_in(void)
|
||||
{
|
||||
disp_spi_change_device_speed(SPI_CLOCK_SPEED_SLOW_HZ);
|
||||
|
||||
ra8875_configure_clocks(false);
|
||||
|
||||
ra8875_write_cmd(RA8875_REG_PWRR, 0x00); // Power and Display Control Register (PWRR)
|
||||
vTaskDelay(DIV_ROUND_UP(20, portTICK_RATE_MS));
|
||||
ra8875_write_cmd(RA8875_REG_PWRR, 0x02); // Power and Display Control Register (PWRR)
|
||||
}
|
||||
|
||||
void ra8875_sleep_out(void)
|
||||
{
|
||||
ra8875_write_cmd(RA8875_REG_PWRR, 0x00); // Power and Display Control Register (PWRR)
|
||||
vTaskDelay(DIV_ROUND_UP(20, portTICK_RATE_MS));
|
||||
|
||||
ra8875_configure_clocks(true);
|
||||
|
||||
disp_spi_change_device_speed(-1);
|
||||
|
||||
ra8875_write_cmd(RA8875_REG_PWRR, 0x80); // Power and Display Control Register (PWRR)
|
||||
vTaskDelay(DIV_ROUND_UP(20, portTICK_RATE_MS));
|
||||
}
|
||||
|
||||
uint8_t ra8875_read_cmd(uint8_t cmd)
|
||||
{
|
||||
uint8_t buf[4] = {RA8875_MODE_CMD_WRITE, cmd, RA8875_MODE_DATA_READ, 0x00};
|
||||
disp_spi_transaction(buf, sizeof(buf), (disp_spi_send_flag_t)(DISP_SPI_RECEIVE | DISP_SPI_SEND_POLLING), buf, 0, 0);
|
||||
return buf[3];
|
||||
}
|
||||
|
||||
void ra8875_write_cmd(uint8_t cmd, uint8_t data)
|
||||
{
|
||||
uint8_t buf[4] = {RA8875_MODE_CMD_WRITE, cmd, RA8875_MODE_DATA_WRITE, data};
|
||||
disp_spi_send_data(buf, sizeof(buf));
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void ra8875_configure_clocks(bool high_speed)
|
||||
{
|
||||
uint8_t val;
|
||||
|
||||
val = high_speed ? ((CONFIG_LV_DISP_RA8875_PLLDIVM << 7) | CONFIG_LV_DISP_RA8875_PLLDIVN) : 0x07;
|
||||
ra8875_write_cmd(RA8875_REG_PLLC1, val); // PLL Control Register 1 (PLLC1)
|
||||
vTaskDelay(1);
|
||||
|
||||
val = high_speed ? CONFIG_LV_DISP_RA8875_PLLDIVK : 0x03;
|
||||
ra8875_write_cmd(RA8875_REG_PLLC2, val); // PLL Control Register 2 (PLLC2)
|
||||
vTaskDelay(1);
|
||||
|
||||
ra8875_write_cmd(RA8875_REG_PCSR, PCSR_VAL); // Pixel Clock Setting Register (PCSR)
|
||||
vTaskDelay(DIV_ROUND_UP(20, portTICK_RATE_MS));
|
||||
}
|
||||
|
||||
static void ra8875_set_window(unsigned int xs, unsigned int xe, unsigned int ys, unsigned int ye)
|
||||
{
|
||||
ra8875_write_cmd(RA8875_REG_HSAW0, (uint8_t)(xs & 0x0FF)); // Horizontal Start Point 0 of Active Window (HSAW0)
|
||||
ra8875_write_cmd(RA8875_REG_HSAW1, (uint8_t)(xs >> 8)); // Horizontal Start Point 1 of Active Window (HSAW1)
|
||||
ra8875_write_cmd(RA8875_REG_VSAW0, (uint8_t)(ys & 0x0FF)); // Vertical Start Point 0 of Active Window (VSAW0)
|
||||
ra8875_write_cmd(RA8875_REG_VSAW1, (uint8_t)(ys >> 8)); // Vertical Start Point 1 of Active Window (VSAW1)
|
||||
ra8875_write_cmd(RA8875_REG_HEAW0, (uint8_t)(xe & 0x0FF)); // Horizontal End Point 0 of Active Window (HEAW0)
|
||||
ra8875_write_cmd(RA8875_REG_HEAW1, (uint8_t)(xe >> 8)); // Horizontal End Point 1 of Active Window (HEAW1)
|
||||
ra8875_write_cmd(RA8875_REG_VEAW0, (uint8_t)(ye & 0x0FF)); // Vertical End Point of Active Window 0 (VEAW0)
|
||||
ra8875_write_cmd(RA8875_REG_VEAW1, (uint8_t)(ye >> 8)); // Vertical End Point of Active Window 1 (VEAW1)
|
||||
}
|
||||
|
||||
static void ra8875_set_memory_write_cursor(unsigned int x, unsigned int y)
|
||||
{
|
||||
ra8875_write_cmd(RA8875_REG_CURH0, (uint8_t)(x & 0x0FF)); // Memory Write Cursor Horizontal Position Register 0 (CURH0)
|
||||
ra8875_write_cmd(RA8875_REG_CURH1, (uint8_t)(x >> 8)); // Memory Write Cursor Horizontal Position Register 1 (CURH1)
|
||||
ra8875_write_cmd(RA8875_REG_CURV0, (uint8_t)(y & 0x0FF)); // Memory Write Cursor Vertical Position Register 0 (CURV0)
|
||||
ra8875_write_cmd(RA8875_REG_CURV1, (uint8_t)(y >> 8)); // Memory Write Cursor Vertical Position Register 1 (CURV1)
|
||||
}
|
||||
|
||||
static void ra8875_send_buffer(uint8_t * data, size_t length, bool signal_flush)
|
||||
{
|
||||
disp_spi_send_flag_t flags = DISP_SPI_SEND_QUEUED | DISP_SPI_ADDRESS_24;
|
||||
if (signal_flush) {
|
||||
flags |= DISP_SPI_SIGNAL_FLUSH;
|
||||
}
|
||||
const uint64_t prefix = (RA8875_MODE_CMD_WRITE << 16) // Command write mode
|
||||
| (RA8875_REG_MRWC << 8) // Memory Read/Write Command (MRWC)
|
||||
| (RA8875_MODE_DATA_WRITE); // Data write mode
|
||||
disp_spi_transaction(data, length, flags, NULL, prefix, 0);
|
||||
}
|
118
lvgl_tft/ra8875.h
Normal file
118
lvgl_tft/ra8875.h
Normal file
|
@ -0,0 +1,118 @@
|
|||
/**
|
||||
* @file ra8875.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RA8875_H
|
||||
#define RA8875_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define RA8875_RST CONFIG_LV_DISP_PIN_RST
|
||||
|
||||
// System & Configuration Registers
|
||||
#define RA8875_REG_PWRR (0x01) // Power and Display Control Register (PWRR)
|
||||
#define RA8875_REG_MRWC (0x02) // Memory Read/Write Command (MRWC)
|
||||
#define RA8875_REG_PCSR (0x04) // Pixel Clock Setting Register (PCSR)
|
||||
#define RA8875_REG_SYSR (0x10) // System Configuration Register (SYSR)
|
||||
#define RA8875_REG_HDWR (0x14) // LCD Horizontal Display Width Register (HDWR)
|
||||
#define RA8875_REG_HNDFTR (0x15) // Horizontal Non-Display Period Fine Tuning Option Register (HNDFTR)
|
||||
#define RA8875_REG_HNDR (0x16) // LCD Horizontal Non-Display Period Register (HNDR)
|
||||
#define RA8875_REG_HSTR (0x17) // HSYNC Start Position Register (HSTR)
|
||||
#define RA8875_REG_HPWR (0x18) // HSYNC Pulse Width Register (HPWR)
|
||||
#define RA8875_REG_VDHR0 (0x19) // LCD Vertical Display Height Register (VDHR0)
|
||||
#define RA8875_REG_VDHR1 (0x1A) // LCD Vertical Display Height Register (VDHR1)
|
||||
#define RA8875_REG_VNDR0 (0x1B) // LCD Vertical Non-Display Period Register (VNDR0)
|
||||
#define RA8875_REG_VNDR1 (0x1C) // LCD Vertical Non-Display Period Register (VNDR1)
|
||||
#define RA8875_REG_VSTR0 (0x1D) // VSYNC Start Position Register (VSTR0)
|
||||
#define RA8875_REG_VSTR1 (0x1E) // VSYNC Start Position Register (VSTR1)
|
||||
#define RA8875_REG_VPWR (0x1F) // VSYNC Pulse Width Register (VPWR)
|
||||
|
||||
// LCD Display Control Registers
|
||||
#define RA8875_REG_DPCR (0x20) // Display Configuration Register (DPCR)
|
||||
|
||||
// Active Window & Scroll Window Setting Registers
|
||||
#define RA8875_REG_HSAW0 (0x30) // Horizontal Start Point 0 of Active Window (HSAW0)
|
||||
#define RA8875_REG_HSAW1 (0x31) // Horizontal Start Point 1 of Active Window (HSAW1)
|
||||
#define RA8875_REG_VSAW0 (0x32) // Vertical Start Point 0 of Active Window (VSAW0)
|
||||
#define RA8875_REG_VSAW1 (0x33) // Vertical Start Point 1 of Active Window (VSAW1)
|
||||
#define RA8875_REG_HEAW0 (0x34) // Horizontal End Point 0 of Active Window (HEAW0)
|
||||
#define RA8875_REG_HEAW1 (0x35) // Horizontal End Point 1 of Active Window (HEAW1)
|
||||
#define RA8875_REG_VEAW0 (0x36) // Vertical End Point 0 of Active Window (VEAW0)
|
||||
#define RA8875_REG_VEAW1 (0x37) // Vertical End Point 1 of Active Window (VEAW1)
|
||||
|
||||
// Cursor Setting Registers
|
||||
#define RA8875_REG_MWCR0 (0x40) // Memory Write Control Register 0 (MWCR0)
|
||||
#define RA8875_REG_MWCR1 (0x41) // Memory Write Control Register 1 (MWCR1)
|
||||
#define RA8875_REG_CURH0 (0x46) // Memory Write Cursor Horizontal Position Register 0 (CURH0)
|
||||
#define RA8875_REG_CURH1 (0x47) // Memory Write Cursor Horizontal Position Register 1 (CURH1)
|
||||
#define RA8875_REG_CURV0 (0x48) // Memory Write Cursor Vertical Position Register 0 (CURV0)
|
||||
#define RA8875_REG_CURV1 (0x49) // Memory Write Cursor Vertical Position Register 1 (CURV1)
|
||||
|
||||
// Block Transfer Engine(BTE) Control Registers
|
||||
#define RA8875_REG_LTPR0 (0x52) // Layer Transparency Register 0 (LTPR0)
|
||||
#define RA8875_REG_LTPR1 (0x53) // Layer Transparency Register 1 (LTPR1)
|
||||
|
||||
// Touch Panel Control Registers
|
||||
#define RA8875_REG_TPCR0 (0x70) // Touch Panel Control Register 0 (TPCR0)
|
||||
#define RA8875_REG_TPCR1 (0x71) // Touch Panel Control Register 1 (TPCR1)
|
||||
#define RA8875_REG_TPXH (0x72) // Touch Panel X High Byte Data Register (TPXH)
|
||||
#define RA8875_REG_TPYH (0x73) // Touch Panel Y High Byte Data Register (TPYH)
|
||||
#define RA8875_REG_TPXYL (0x74) // Touch Panel X/Y Low Byte Data Register (TPXYL)
|
||||
|
||||
// PLL Setting Registers
|
||||
#define RA8875_REG_PLLC1 (0x88) // PLL Control Register 1 (PLLC1)
|
||||
#define RA8875_REG_PLLC2 (0x89) // PLL Control Register 2 (PLLC2)
|
||||
|
||||
// Memory Clear Register
|
||||
#define RA8875_REG_MCLR (0x8E) // Memory Clear Control Register (MCLR)
|
||||
|
||||
// Interrupt Control Registers
|
||||
#define RA8875_REG_INTC1 (0xF0) // Interrupt Control Register1 (INTC1)
|
||||
#define RA8875_REG_INTC2 (0xF1) // Interrupt Control Register1 (INTC2)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void ra8875_init(void);
|
||||
void ra8875_enable_backlight(bool backlight);
|
||||
void ra8875_enable_display(bool enable);
|
||||
void ra8875_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
|
||||
|
||||
void ra8875_sleep_in(void);
|
||||
void ra8875_sleep_out(void);
|
||||
|
||||
uint8_t ra8875_read_cmd(uint8_t cmd);
|
||||
void ra8875_write_cmd(uint8_t cmd, uint8_t data);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*RA8875_H*/
|
218
lvgl_tft/sh1107.c
Normal file
218
lvgl_tft/sh1107.c
Normal file
|
@ -0,0 +1,218 @@
|
|||
/**
|
||||
* @file sh1107.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "sh1107.h"
|
||||
#include "disp_spi.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "SH1107"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */
|
||||
typedef struct {
|
||||
uint8_t cmd;
|
||||
uint8_t data[16];
|
||||
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
|
||||
} lcd_init_cmd_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void sh1107_send_cmd(uint8_t cmd);
|
||||
static void sh1107_send_data(void * data, uint16_t length);
|
||||
static void sh1107_send_color(void * data, uint16_t length);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define BIT_SET(a,b) ((a) |= (1U<<(b)))
|
||||
#define BIT_CLEAR(a,b) ((a) &= ~(1U<<(b)))
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void sh1107_init(void)
|
||||
{
|
||||
// Use Double Bytes Commands if necessary, but not Command+Data
|
||||
// Initialization taken from https://github.com/nopnop2002/esp-idf-m5stick
|
||||
lcd_init_cmd_t init_cmds[]={
|
||||
{0xAE, {0}, 0}, // Turn display off
|
||||
{0xDC, {0}, 0}, // Set display start line
|
||||
{0x00, {0}, 0}, // ...value
|
||||
{0x81, {0}, 0}, // Set display contrast
|
||||
{0x2F, {0}, 0}, // ...value
|
||||
{0x20, {0}, 0}, // Set memory mode
|
||||
{0xA0, {0}, 0}, // Non-rotated display
|
||||
#if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
{0xC8, {0}, 0}, // flipped vertical
|
||||
#elif defined CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT
|
||||
{0xC7, {0}, 0}, // flipped vertical
|
||||
#endif
|
||||
{0xA8, {0}, 0}, // Set multiplex ratio
|
||||
{0x7F, {0}, 0}, // ...value
|
||||
{0xD3, {0}, 0}, // Set display offset to zero
|
||||
{0x60, {0}, 0}, // ...value
|
||||
{0xD5, {0}, 0}, // Set display clock divider
|
||||
{0x51, {0}, 0}, // ...value
|
||||
{0xD9, {0}, 0}, // Set pre-charge
|
||||
{0x22, {0}, 0}, // ...value
|
||||
{0xDB, {0}, 0}, // Set com detect
|
||||
{0x35, {0}, 0}, // ...value
|
||||
{0xB0, {0}, 0}, // Set page address
|
||||
{0xDA, {0}, 0}, // Set com pins
|
||||
{0x12, {0}, 0}, // ...value
|
||||
{0xA4, {0}, 0}, // output ram to display
|
||||
#if defined CONFIG_LV_INVERT_DISPLAY
|
||||
{0xA7, {0}, 0}, // inverted display
|
||||
#else
|
||||
{0xA6, {0}, 0}, // Non-inverted display
|
||||
#endif
|
||||
{0xAF, {0}, 0}, // Turn display on
|
||||
{0, {0}, 0xff},
|
||||
};
|
||||
|
||||
//Initialize non-SPI GPIOs
|
||||
gpio_pad_select_gpio(SH1107_DC);
|
||||
gpio_set_direction(SH1107_DC, GPIO_MODE_OUTPUT);
|
||||
gpio_pad_select_gpio(SH1107_RST);
|
||||
gpio_set_direction(SH1107_RST, GPIO_MODE_OUTPUT);
|
||||
|
||||
//Reset the display
|
||||
gpio_set_level(SH1107_RST, 0);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
gpio_set_level(SH1107_RST, 1);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
|
||||
//Send all the commands
|
||||
uint16_t cmd = 0;
|
||||
while (init_cmds[cmd].databytes!=0xff) {
|
||||
sh1107_send_cmd(init_cmds[cmd].cmd);
|
||||
sh1107_send_data(init_cmds[cmd].data, init_cmds[cmd].databytes&0x1F);
|
||||
if (init_cmds[cmd].databytes & 0x80) {
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
}
|
||||
cmd++;
|
||||
}
|
||||
}
|
||||
|
||||
void sh1107_set_px_cb(struct _disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
/* buf_w will be ignored, the configured CONFIG_LV_DISPLAY_HEIGHT and _WIDTH,
|
||||
and CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE and _PORTRAIT will be used. */
|
||||
uint16_t byte_index = 0;
|
||||
uint8_t bit_index = 0;
|
||||
|
||||
#if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
byte_index = y + (( x>>3 ) * CONFIG_LV_DISPLAY_HEIGHT);
|
||||
bit_index = x & 0x7;
|
||||
#elif defined CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT
|
||||
byte_index = x + (( y>>3 ) * CONFIG_LV_DISPLAY_WIDTH);
|
||||
bit_index = y & 0x7;
|
||||
#endif
|
||||
|
||||
if ((color.full == 0) && (LV_OPA_TRANSP != opa)) {
|
||||
BIT_SET(buf[byte_index], bit_index);
|
||||
} else {
|
||||
BIT_CLEAR(buf[byte_index], bit_index);
|
||||
}
|
||||
}
|
||||
|
||||
void sh1107_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
|
||||
{
|
||||
uint8_t columnLow = area->x1 & 0x0F;
|
||||
uint8_t columnHigh = (area->x1 >> 4) & 0x0F;
|
||||
uint8_t row1 = 0, row2 = 0;
|
||||
uint32_t size = 0;
|
||||
void *ptr;
|
||||
|
||||
#if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
row1 = area->x1>>3;
|
||||
row2 = area->x2>>3;
|
||||
#else
|
||||
row1 = area->y1>>3;
|
||||
row2 = area->y2>>3;
|
||||
#endif
|
||||
for(int i = row1; i < row2+1; i++){
|
||||
sh1107_send_cmd(0x10 | columnHigh); // Set Higher Column Start Address for Page Addressing Mode
|
||||
sh1107_send_cmd(0x00 | columnLow); // Set Lower Column Start Address for Page Addressing Mode
|
||||
sh1107_send_cmd(0xB0 | i); // Set Page Start Address for Page Addressing Mode
|
||||
size = area->y2 - area->y1 + 1;
|
||||
#if defined CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
ptr = color_map + i * CONFIG_LV_DISPLAY_HEIGHT;
|
||||
#else
|
||||
ptr = color_map + i * CONFIG_LV_DISPLAY_WIDTH;
|
||||
#endif
|
||||
if(i != row2){
|
||||
sh1107_send_data( (void *) ptr, size);
|
||||
} else {
|
||||
// complete sending data by sh1107_send_color() and thus call lv_flush_ready()
|
||||
sh1107_send_color( (void *) ptr, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void sh1107_sleep_in()
|
||||
{
|
||||
sh1107_send_cmd(0xAE);
|
||||
}
|
||||
|
||||
void sh1107_sleep_out()
|
||||
{
|
||||
sh1107_send_cmd(0xAF);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
static void sh1107_send_cmd(uint8_t cmd)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(SH1107_DC, 0); /*Command mode*/
|
||||
disp_spi_send_data(&cmd, 1);
|
||||
}
|
||||
|
||||
static void sh1107_send_data(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(SH1107_DC, 1); /*Data mode*/
|
||||
disp_spi_send_data(data, length);
|
||||
}
|
||||
|
||||
static void sh1107_send_color(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(SH1107_DC, 1); /*Data mode*/
|
||||
disp_spi_send_colors(data, length);
|
||||
}
|
55
lvgl_tft/sh1107.h
Normal file
55
lvgl_tft/sh1107.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* @file lv_templ.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SH1107_H
|
||||
#define SH1107_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
#include "../lvgl_helpers.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define SH1107_DC CONFIG_LV_DISP_PIN_DC
|
||||
#define SH1107_RST CONFIG_LV_DISP_PIN_RST
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void sh1107_init(void);
|
||||
void sh1107_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
|
||||
void sh1107_rounder(struct _disp_drv_t * disp_drv, lv_area_t *area);
|
||||
void sh1107_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,
|
||||
lv_color_t color, lv_opa_t opa);
|
||||
void sh1107_sleep_in(void);
|
||||
void sh1107_sleep_out(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*SH1107_H*/
|
240
lvgl_tft/ssd1306.c
Normal file
240
lvgl_tft/ssd1306.c
Normal file
|
@ -0,0 +1,240 @@
|
|||
/**
|
||||
* @file ssd1306.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "ssd1306.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "disp_spi.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "SSD1306"
|
||||
|
||||
// Code from https://github.com/yanbe/ssd1306-esp-idf-i2c.git is used as a starting point,
|
||||
// in addition to code from https://github.com/espressif/esp-iot-solution.
|
||||
// Following definitions are borrowed from
|
||||
// http://robotcantalk.blogspot.com/2015/03/interfacing-arduino-with-ssd1306-driven.html
|
||||
// For LittlevGL the forum has been used, in particular: https://blog.littlevgl.com/2019-05-06/oled
|
||||
|
||||
// SLA (0x3C) + WRITE_MODE (0x00) = 0x78 (0b01111000)
|
||||
#define OLED_I2C_ADDRESS 0x3C
|
||||
#define OLED_WIDTH 128
|
||||
#define OLED_HEIGHT 64
|
||||
#define OLED_COLUMNS 128
|
||||
#define OLED_PAGES 8
|
||||
#define OLED_PIXEL_PER_PAGE 8
|
||||
|
||||
// Control byte
|
||||
#define OLED_CONTROL_BYTE_CMD_SINGLE 0x80
|
||||
#define OLED_CONTROL_BYTE_CMD_STREAM 0x00
|
||||
#define OLED_CONTROL_BYTE_DATA_STREAM 0x40
|
||||
|
||||
// Fundamental commands (pg.28)
|
||||
#define OLED_CMD_SET_CONTRAST 0x81 // follow with 0x7F
|
||||
#define OLED_CMD_DISPLAY_RAM 0xA4
|
||||
#define OLED_CMD_DISPLAY_ALLON 0xA5
|
||||
#define OLED_CMD_DISPLAY_NORMAL 0xA6
|
||||
#define OLED_CMD_DISPLAY_INVERTED 0xA7
|
||||
#define OLED_CMD_DISPLAY_OFF 0xAE
|
||||
#define OLED_CMD_DISPLAY_ON 0xAF
|
||||
|
||||
// Addressing Command Table (pg.30)
|
||||
#define OLED_CMD_SET_MEMORY_ADDR_MODE 0x20 // follow with 0x00 = HORZ mode
|
||||
#define OLED_CMD_SET_COLUMN_RANGE 0x21 // can be used only in HORZ/VERT mode - follow with 0x00 and 0x7F = COL127
|
||||
#define OLED_CMD_SET_PAGE_RANGE 0x22 // can be used only in HORZ/VERT mode - follow with 0x00 and 0x07 = PAGE7
|
||||
|
||||
// Hardware Config (pg.31)
|
||||
#define OLED_CMD_SET_DISPLAY_START_LINE 0x40
|
||||
#define OLED_CMD_SET_SEGMENT_REMAP 0xA1
|
||||
#define OLED_CMD_SET_MUX_RATIO 0xA8 // follow with 0x3F = 64 MUX
|
||||
#define OLED_CMD_SET_COM_SCAN_MODE_NORMAL 0xC0
|
||||
#define OLED_CMD_SET_COM_SCAN_MODE_REMAP 0xC8
|
||||
#define OLED_CMD_SET_DISPLAY_OFFSET 0xD3 // follow with 0x00
|
||||
#define OLED_CMD_SET_COM_PIN_MAP 0xDA // follow with 0x12
|
||||
#define OLED_CMD_NOP 0xE3 // NOP
|
||||
|
||||
// Timing and Driving Scheme (pg.32)
|
||||
#define OLED_CMD_SET_DISPLAY_CLK_DIV 0xD5 // follow with 0x80
|
||||
#define OLED_CMD_SET_PRECHARGE 0xD9 // follow with 0xF1
|
||||
#define OLED_CMD_SET_VCOMH_DESELCT 0xDB // follow with 0x30
|
||||
|
||||
// Charge Pump (pg.62)
|
||||
#define OLED_CMD_SET_CHARGE_PUMP 0x8D // follow with 0x14
|
||||
|
||||
#define OLED_IIC_FREQ_HZ 400000 // I2C colock frequency
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define BIT_SET(a,b) ((a) |= (1U<<(b)))
|
||||
#define BIT_CLEAR(a,b) ((a) &= ~(1U<<(b)))
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
void ssd1306_init()
|
||||
{
|
||||
esp_err_t ret;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
||||
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
|
||||
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_CHARGE_PUMP, true);
|
||||
i2c_master_write_byte(cmd, 0x14, true);
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP, true);
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_COM_SCAN_MODE_REMAP, true);
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_CONTRAST, true);
|
||||
|
||||
#if defined CONFIG_LV_INVERT_DISPLAY
|
||||
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_INVERTED, true); // Inverted display
|
||||
#else
|
||||
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_NORMAL, true); // Non-inverted display
|
||||
#endif
|
||||
|
||||
|
||||
i2c_master_write_byte(cmd, 0xFF, true);
|
||||
|
||||
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_ON, true);
|
||||
i2c_master_stop(cmd);
|
||||
|
||||
ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI(TAG, "OLED configured successfully");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "OLED configuration failed. code: 0x%.2X", ret);
|
||||
}
|
||||
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,
|
||||
lv_color_t color, lv_opa_t opa) {
|
||||
uint16_t byte_index = x + (( y>>3 ) * buf_w);
|
||||
uint8_t bit_index = y & 0x7;
|
||||
|
||||
if ((color.full == 0) && (LV_OPA_TRANSP != opa)) {
|
||||
BIT_SET(buf[byte_index], bit_index);
|
||||
} else {
|
||||
BIT_CLEAR(buf[byte_index], bit_index);
|
||||
}
|
||||
}
|
||||
|
||||
void ssd1306_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
|
||||
{
|
||||
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
|
||||
|
||||
cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
||||
|
||||
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_MEMORY_ADDR_MODE, true);
|
||||
i2c_master_write_byte(cmd, 0x00, true);
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_COLUMN_RANGE, true);
|
||||
i2c_master_write_byte(cmd, area->x1, true);
|
||||
i2c_master_write_byte(cmd, area->x2, true);
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_PAGE_RANGE, true);
|
||||
i2c_master_write_byte(cmd, row1, true);
|
||||
i2c_master_write_byte(cmd, row2, true);
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
||||
|
||||
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true);
|
||||
i2c_master_write(cmd, (uint8_t *)color_p, OLED_COLUMNS * (1+row2-row1), true);
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
lv_disp_flush_ready(disp_drv);
|
||||
}
|
||||
|
||||
void ssd1306_rounder(struct _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
|
||||
area->x1 = 0;
|
||||
area->y1 = 0;
|
||||
area->x2 = CONFIG_LV_DISPLAY_WIDTH-1;
|
||||
area->y2 = CONFIG_LV_DISPLAY_HEIGHT-1;
|
||||
}
|
||||
|
||||
void ssd1306_sleep_in()
|
||||
{
|
||||
esp_err_t ret;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
||||
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
|
||||
|
||||
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_OFF, true);
|
||||
i2c_master_stop(cmd);
|
||||
|
||||
ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "ssd1306_display_off configuration failed. code: 0x%.2X", ret);
|
||||
}
|
||||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
||||
void ssd1306_sleep_out()
|
||||
{
|
||||
esp_err_t ret;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
||||
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
|
||||
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_ON, true);
|
||||
i2c_master_stop(cmd);
|
||||
|
||||
ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "ssd1306_display_on configuration failed. code: 0x%.2X", ret);
|
||||
}
|
||||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
57
lvgl_tft/ssd1306.h
Normal file
57
lvgl_tft/ssd1306.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* @file lv_templ.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SSD1306_H
|
||||
#define SSD1306_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
#include "../lvgl_helpers.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define SSD1306_SDA CONFIG_LV_DISP_PIN_SDA
|
||||
#define SSD1306_SCL CONFIG_LV_DISP_PIN_SCL
|
||||
#define SSD1306_DISPLAY_ORIENTATION TFT_ORIENTATION_LANDSCAPE
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
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,
|
||||
lv_color_t color, lv_opa_t opa);
|
||||
|
||||
void ssd1306_sleep_in(void);
|
||||
void ssd1306_sleep_out(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*SSD1306_H*/
|
269
lvgl_tft/st7735s.c
Normal file
269
lvgl_tft/st7735s.c
Normal file
|
@ -0,0 +1,269 @@
|
|||
/**
|
||||
* @file st7735s.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "st7735s.h"
|
||||
#include "disp_spi.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "ST7735S"
|
||||
#define AXP192_I2C_ADDRESS 0x34
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */
|
||||
typedef struct {
|
||||
uint8_t cmd;
|
||||
uint8_t data[16];
|
||||
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
|
||||
} lcd_init_cmd_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void st7735s_send_cmd(uint8_t cmd);
|
||||
static void st7735s_send_data(void * data, uint16_t length);
|
||||
static void st7735s_send_color(void * data, uint16_t length);
|
||||
static void st7735s_set_orientation(uint8_t orientation);
|
||||
static void i2c_master_init();
|
||||
static void axp192_write_byte(uint8_t addr, uint8_t data);
|
||||
static void axp192_init();
|
||||
static void axp192_sleep_in();
|
||||
static void axp192_sleep_out();
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
uint8_t st7735s_portrait_mode = 0;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void st7735s_init(void)
|
||||
{
|
||||
#ifdef CONFIG_LV_M5STICKC_HANDLE_AXP192
|
||||
i2c_master_init();
|
||||
axp192_init();
|
||||
#endif
|
||||
|
||||
lcd_init_cmd_t init_cmds[]={
|
||||
{ST7735_SWRESET, {0}, 0x80}, // Software reset, 0 args, w/delay 150
|
||||
{ST7735_SLPOUT, {0}, 0x80}, // Out of sleep mode, 0 args, w/delay 500
|
||||
{ST7735_FRMCTR1, {0x01, 0x2C, 0x2D}, 3}, // Frame rate ctrl - normal mode, 3 args: Rate = fosc/(1x2+40) * (LINE+2C+2D)
|
||||
{ST7735_FRMCTR2, {0x01, 0x2C, 0x2D}, 3}, // Frame rate control - idle mode, 3 args:Rate = fosc/(1x2+40) * (LINE+2C+2D)
|
||||
{ST7735_FRMCTR3, {0x01, 0x2C, 0x2D,0x01, 0x2C, 0x2D}, 6}, //Frame rate ctrl - partial mode, 6 args:Dot inversion mode. Line inversion mode
|
||||
{ST7735_INVCTR, {0x07}, 1}, // Display inversion ctrl, 1 arg, no delay:No inversion
|
||||
{ST7735_PWCTR1, {0xA2,0x02, 0x84}, 3}, // Power control, 3 args, no delay:-4.6V AUTO mode
|
||||
{ST7735_PWCTR2, {0xC5}, 1}, // Power control, 1 arg, no delay:VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
|
||||
{ST7735_PWCTR3, {0x0A, 0x00}, 2}, // Power control, 2 args, no delay: Opamp current small, Boost frequency
|
||||
{ST7735_PWCTR4, {0x8A,0x2A }, 2}, // Power control, 2 args, no delay: BCLK/2, Opamp current small & Medium low
|
||||
{ST7735_PWCTR5, {0x8A, 0xEE}, 2}, // Power control, 2 args, no delay:
|
||||
{ST7735_VMCTR1, {0x0E}, 1}, // Power control, 1 arg, no delay:
|
||||
#if ST7735S_INVERT_COLORS == 1
|
||||
{ST7735_INVON, {0}, 0}, // set inverted mode
|
||||
#else
|
||||
{ST7735_INVOFF, {0}, 0}, // set non-inverted mode
|
||||
#endif
|
||||
{ST7735_COLMOD, {0x05}, 1}, // set color mode, 1 arg, no delay: 16-bit color
|
||||
{ST7735_GMCTRP1, {0x02, 0x1c, 0x07, 0x12,
|
||||
0x37, 0x32, 0x29, 0x2d,
|
||||
0x29, 0x25, 0x2B, 0x39,
|
||||
0x00, 0x01, 0x03, 0x10}, 16}, // 16 args, no delay:
|
||||
{ST7735_GMCTRN1, {0x03, 0x1d, 0x07, 0x06,
|
||||
0x2E, 0x2C, 0x29, 0x2D,
|
||||
0x2E, 0x2E, 0x37, 0x3F,
|
||||
0x00, 0x00, 0x02, 0x10}, 16}, // 16 args, no delay:
|
||||
{ST7735_NORON, {0}, TFT_INIT_DELAY}, // Normal display on, no args, w/delay 10 ms delay
|
||||
{ST7735_DISPON, {0}, TFT_INIT_DELAY}, // Main screen turn on, no args w/delay 100 ms delay
|
||||
{0, {0}, 0xff}
|
||||
};
|
||||
|
||||
//Initialize non-SPI GPIOs
|
||||
gpio_pad_select_gpio(ST7735S_DC);
|
||||
gpio_set_direction(ST7735S_DC, GPIO_MODE_OUTPUT);
|
||||
gpio_pad_select_gpio(ST7735S_RST);
|
||||
gpio_set_direction(ST7735S_RST, GPIO_MODE_OUTPUT);
|
||||
|
||||
//Reset the display
|
||||
gpio_set_level(ST7735S_RST, 0);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
gpio_set_level(ST7735S_RST, 1);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
|
||||
ESP_LOGI(TAG, "ST7735S initialization.");
|
||||
|
||||
//Send all the commands
|
||||
uint16_t cmd = 0;
|
||||
while (init_cmds[cmd].databytes!=0xff) {
|
||||
st7735s_send_cmd(init_cmds[cmd].cmd);
|
||||
st7735s_send_data(init_cmds[cmd].data, init_cmds[cmd].databytes&0x1F);
|
||||
if (init_cmds[cmd].databytes & 0x80) {
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
}
|
||||
cmd++;
|
||||
}
|
||||
|
||||
#if (CONFIG_LV_DISPLAY_ORIENTATION == 0) || (CONFIG_LV_DISPLAY_ORIENTATION == 1)
|
||||
st7735s_portrait_mode = 1;
|
||||
#else
|
||||
st7735s_portrait_mode = 0;
|
||||
#endif
|
||||
|
||||
st7735s_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION);
|
||||
}
|
||||
|
||||
void st7735s_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
|
||||
{
|
||||
uint8_t data[4];
|
||||
|
||||
/*Column addresses*/
|
||||
st7735s_send_cmd(0x2A);
|
||||
data[0] = (area->x1 >> 8) & 0xFF;
|
||||
data[1] = (area->x1 & 0xFF) + (st7735s_portrait_mode ? COLSTART : ROWSTART);
|
||||
data[2] = (area->x2 >> 8) & 0xFF;
|
||||
data[3] = (area->x2 & 0xFF) + (st7735s_portrait_mode ? COLSTART : ROWSTART);
|
||||
st7735s_send_data(data, 4);
|
||||
|
||||
/*Page addresses*/
|
||||
st7735s_send_cmd(0x2B);
|
||||
data[0] = (area->y1 >> 8) & 0xFF;
|
||||
data[1] = (area->y1 & 0xFF) + (st7735s_portrait_mode ? ROWSTART : COLSTART);
|
||||
data[2] = (area->y2 >> 8) & 0xFF;
|
||||
data[3] = (area->y2 & 0xFF) + (st7735s_portrait_mode ? ROWSTART : COLSTART);
|
||||
st7735s_send_data(data, 4);
|
||||
|
||||
/*Memory write*/
|
||||
st7735s_send_cmd(0x2C);
|
||||
|
||||
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
|
||||
st7735s_send_color((void*)color_map, size * 2);
|
||||
}
|
||||
|
||||
void st7735s_sleep_in()
|
||||
{
|
||||
st7735s_send_cmd(0x10);
|
||||
axp192_sleep_in();
|
||||
}
|
||||
|
||||
void st7735s_sleep_out()
|
||||
{
|
||||
axp192_sleep_out();
|
||||
st7735s_send_cmd(0x11);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void st7735s_send_cmd(uint8_t cmd)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ST7735S_DC, 0); /*Command mode*/
|
||||
disp_spi_send_data(&cmd, 1);
|
||||
}
|
||||
|
||||
static void st7735s_send_data(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ST7735S_DC, 1); /*Data mode*/
|
||||
disp_spi_send_data(data, length);
|
||||
}
|
||||
|
||||
static void st7735s_send_color(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ST7735S_DC, 1); /*Data mode*/
|
||||
disp_spi_send_colors(data, length);
|
||||
}
|
||||
|
||||
static void st7735s_set_orientation(uint8_t orientation)
|
||||
{
|
||||
const char *orientation_str[] = {
|
||||
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
|
||||
};
|
||||
|
||||
ESP_LOGD(TAG, "Display orientation: %s", orientation_str[orientation]);
|
||||
|
||||
/*
|
||||
Portrait: 0xC8 = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_BGR
|
||||
Landscape: 0xA8 = ST77XX_MADCTL_MY | ST77XX_MADCTL_MV | ST77XX_MADCTL_BGR
|
||||
Remark: "inverted" is ignored here
|
||||
*/
|
||||
uint8_t data[] = {0xC8, 0xC8, 0xA8, 0xA8};
|
||||
|
||||
ESP_LOGD(TAG, "0x36 command value: 0x%02X", data[orientation]);
|
||||
|
||||
st7735s_send_cmd(ST7735_MADCTL);
|
||||
st7735s_send_data((void *) &data[orientation], 1);
|
||||
}
|
||||
|
||||
static void i2c_master_init()
|
||||
{
|
||||
i2c_config_t i2c_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = AXP192_SDA,
|
||||
.scl_io_num = AXP192_SCL,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = 400000
|
||||
};
|
||||
i2c_param_config(I2C_NUM_0, &i2c_config);
|
||||
i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0);
|
||||
}
|
||||
|
||||
static void axp192_write_byte(uint8_t addr, uint8_t data)
|
||||
{
|
||||
esp_err_t ret;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (AXP192_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
||||
i2c_master_write_byte(cmd, addr, true);
|
||||
i2c_master_write_byte(cmd, data, true);
|
||||
i2c_master_stop(cmd);
|
||||
|
||||
ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "AXP192 send failed. code: 0x%.2X", ret);
|
||||
}
|
||||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
||||
static void axp192_init()
|
||||
{
|
||||
// information on how to init and use AXP192 ifor M5StickC taken from
|
||||
// https://forum.m5stack.com/topic/1025/m5stickc-turn-off-screen-completely
|
||||
|
||||
axp192_write_byte(0x10, 0xFF); // OLED_VPP Enable
|
||||
axp192_write_byte(0x28, 0xCC); // Enable LDO2&LDO3, LED&TFT 3.0V
|
||||
axp192_sleep_out();
|
||||
ESP_LOGI(TAG, "AXP192 initialized, power enabled for LDO2 and LDO3");
|
||||
}
|
||||
|
||||
static void axp192_sleep_in()
|
||||
{
|
||||
axp192_write_byte(0x12, 0x4b);
|
||||
}
|
||||
|
||||
static void axp192_sleep_out()
|
||||
{
|
||||
axp192_write_byte(0x12, 0x4d);
|
||||
}
|
149
lvgl_tft/st7735s.h
Normal file
149
lvgl_tft/st7735s.h
Normal file
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* @file lv_templ.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ST7735S_H
|
||||
#define ST7735S_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* 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
|
||||
#define ST7735S_RST CONFIG_LV_DISP_PIN_RST
|
||||
|
||||
#define AXP192_SDA CONFIG_LV_AXP192_PIN_SDA
|
||||
#define AXP192_SCL CONFIG_LV_AXP192_PIN_SCL
|
||||
|
||||
#define ST7735S_INVERT_COLORS CONFIG_LV_INVERT_COLORS
|
||||
|
||||
// Defines are taken from
|
||||
// https://raw.githubusercontent.com/m5stack/M5StickC/master/src/utility/ST7735_Defines.h
|
||||
// and are modified to fit to the M5StickC device, and are taken from
|
||||
// https://github.com/adafruit/Adafruit-ST7735-Library
|
||||
//
|
||||
#define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 / 1 offset)
|
||||
#define COLSTART 26
|
||||
#define ROWSTART 1
|
||||
|
||||
// Delay between some initialisation commands
|
||||
#define TFT_INIT_DELAY 0x80
|
||||
|
||||
#define TFT_NOP 0x00
|
||||
#define TFT_SWRST 0x01
|
||||
|
||||
#define TFT_CASET 0x2A
|
||||
#define TFT_PASET 0x2B
|
||||
#define TFT_RAMWR 0x2C
|
||||
|
||||
#define TFT_RAMRD 0x2E
|
||||
#define TFT_IDXRD 0x00
|
||||
|
||||
#define TFT_MADCTL 0x36
|
||||
#define TFT_MAD_MY 0x80
|
||||
#define TFT_MAD_MX 0x40
|
||||
#define TFT_MAD_MV 0x20
|
||||
#define TFT_MAD_ML 0x10
|
||||
#define TFT_MAD_BGR 0x08
|
||||
#define TFT_MAD_MH 0x04
|
||||
#define TFT_MAD_RGB 0x00
|
||||
|
||||
#define TFT_INVOFF 0x20
|
||||
#define TFT_INVON 0x21
|
||||
|
||||
// ST7735 specific commands used in init
|
||||
#define ST7735_NOP 0x00
|
||||
#define ST7735_SWRESET 0x01
|
||||
#define ST7735_RDDID 0x04
|
||||
#define ST7735_RDDST 0x09
|
||||
|
||||
#define ST7735_SLPIN 0x10
|
||||
#define ST7735_SLPOUT 0x11
|
||||
#define ST7735_PTLON 0x12
|
||||
#define ST7735_NORON 0x13
|
||||
|
||||
#define ST7735_INVOFF 0x20
|
||||
#define ST7735_INVON 0x21
|
||||
#define ST7735_DISPOFF 0x28
|
||||
#define ST7735_DISPON 0x29
|
||||
#define ST7735_CASET 0x2A
|
||||
#define ST7735_RASET 0x2B
|
||||
#define ST7735_RAMWR 0x2C
|
||||
#define ST7735_RAMRD 0x2E
|
||||
|
||||
#define ST7735_PTLAR 0x30
|
||||
#define ST7735_VSCRDEF 0x33
|
||||
#define ST7735_COLMOD 0x3A
|
||||
#define ST7735_MADCTL 0x36
|
||||
#define ST7735_VSCRSADD 0x37
|
||||
|
||||
#define ST7735_FRMCTR1 0xB1
|
||||
#define ST7735_FRMCTR2 0xB2
|
||||
#define ST7735_FRMCTR3 0xB3
|
||||
#define ST7735_INVCTR 0xB4
|
||||
#define ST7735_DISSET5 0xB6
|
||||
|
||||
#define ST7735_PWCTR1 0xC0
|
||||
#define ST7735_PWCTR2 0xC1
|
||||
#define ST7735_PWCTR3 0xC2
|
||||
#define ST7735_PWCTR4 0xC3
|
||||
#define ST7735_PWCTR5 0xC4
|
||||
#define ST7735_VMCTR1 0xC5
|
||||
|
||||
#define ST7735_RDID1 0xDA
|
||||
#define ST7735_RDID2 0xDB
|
||||
#define ST7735_RDID3 0xDC
|
||||
#define ST7735_RDID4 0xDD
|
||||
|
||||
#define ST7735_PWCTR6 0xFC
|
||||
|
||||
#define ST7735_GMCTRP1 0xE0
|
||||
#define ST7735_GMCTRN1 0xE1
|
||||
|
||||
#define ST77XX_MADCTL_MY 0x80
|
||||
#define ST77XX_MADCTL_MX 0x40
|
||||
#define ST77XX_MADCTL_MV 0x20
|
||||
#define ST77XX_MADCTL_ML 0x10
|
||||
#define ST77XX_MADCTL_RGB 0x00
|
||||
#define ST77XX_MADCTL_BGR 0x08
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void st7735s_init(void);
|
||||
void st7735s_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
|
||||
void st7735s_enable_backlight(bool backlight);
|
||||
void st7735s_sleep_in(void);
|
||||
void st7735s_sleep_out(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*ST7735S_H*/
|
235
lvgl_tft/st7789.c
Normal file
235
lvgl_tft/st7789.c
Normal file
|
@ -0,0 +1,235 @@
|
|||
/**
|
||||
* @file st7789.c
|
||||
*
|
||||
* Mostly taken from lbthomsen/esp-idf-littlevgl github.
|
||||
*/
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "st7789.h"
|
||||
|
||||
#include "disp_spi.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "st7789"
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */
|
||||
typedef struct {
|
||||
uint8_t cmd;
|
||||
uint8_t data[16];
|
||||
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
|
||||
} lcd_init_cmd_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void st7789_set_orientation(uint8_t orientation);
|
||||
|
||||
static void st7789_send_cmd(uint8_t cmd);
|
||||
static void st7789_send_data(void *data, uint16_t length);
|
||||
static void st7789_send_color(void *data, uint16_t length);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
void st7789_init(void)
|
||||
{
|
||||
lcd_init_cmd_t st7789_init_cmds[] = {
|
||||
{0xCF, {0x00, 0x83, 0X30}, 3},
|
||||
{0xED, {0x64, 0x03, 0X12, 0X81}, 4},
|
||||
{ST7789_PWCTRL2, {0x85, 0x01, 0x79}, 3},
|
||||
{0xCB, {0x39, 0x2C, 0x00, 0x34, 0x02}, 5},
|
||||
{0xF7, {0x20}, 1},
|
||||
{0xEA, {0x00, 0x00}, 2},
|
||||
{ST7789_LCMCTRL, {0x26}, 1},
|
||||
{ST7789_IDSET, {0x11}, 1},
|
||||
{ST7789_VCMOFSET, {0x35, 0x3E}, 2},
|
||||
{ST7789_CABCCTRL, {0xBE}, 1},
|
||||
{ST7789_MADCTL, {0x00}, 1}, // Set to 0x28 if your display is flipped
|
||||
{ST7789_COLMOD, {0x55}, 1},
|
||||
{ST7789_INVON, {0}, 0},
|
||||
{ST7789_RGBCTRL, {0x00, 0x1B}, 2},
|
||||
{0xF2, {0x08}, 1},
|
||||
{ST7789_GAMSET, {0x01}, 1},
|
||||
{ST7789_PVGAMCTRL, {0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x32, 0x44, 0x42, 0x06, 0x0E, 0x12, 0x14, 0x17}, 14},
|
||||
{ST7789_NVGAMCTRL, {0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x31, 0x54, 0x47, 0x0E, 0x1C, 0x17, 0x1B, 0x1E}, 14},
|
||||
{ST7789_CASET, {0x00, 0x00, 0x00, 0xEF}, 4},
|
||||
{ST7789_RASET, {0x00, 0x00, 0x01, 0x3f}, 4},
|
||||
{ST7789_RAMWR, {0}, 0},
|
||||
{ST7789_GCTRL, {0x07}, 1},
|
||||
{0xB6, {0x0A, 0x82, 0x27, 0x00}, 4},
|
||||
{ST7789_SLPOUT, {0}, 0x80},
|
||||
{ST7789_DISPON, {0}, 0x80},
|
||||
{0, {0}, 0xff},
|
||||
};
|
||||
|
||||
//Initialize non-SPI GPIOs
|
||||
gpio_pad_select_gpio(ST7789_DC);
|
||||
gpio_set_direction(ST7789_DC, GPIO_MODE_OUTPUT);
|
||||
gpio_pad_select_gpio(ST7789_RST);
|
||||
gpio_set_direction(ST7789_RST, GPIO_MODE_OUTPUT);
|
||||
|
||||
#if ST7789_ENABLE_BACKLIGHT_CONTROL
|
||||
gpio_pad_select_gpio(ST7789_BCKL);
|
||||
gpio_set_direction(ST7789_BCKL, GPIO_MODE_OUTPUT);
|
||||
#endif
|
||||
|
||||
//Reset the display
|
||||
gpio_set_level(ST7789_RST, 0);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
gpio_set_level(ST7789_RST, 1);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
|
||||
printf("ST7789 initialization.\n");
|
||||
|
||||
//Send all the commands
|
||||
uint16_t cmd = 0;
|
||||
while (st7789_init_cmds[cmd].databytes!=0xff) {
|
||||
st7789_send_cmd(st7789_init_cmds[cmd].cmd);
|
||||
st7789_send_data(st7789_init_cmds[cmd].data, st7789_init_cmds[cmd].databytes&0x1F);
|
||||
if (st7789_init_cmds[cmd].databytes & 0x80) {
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
}
|
||||
cmd++;
|
||||
}
|
||||
|
||||
st7789_enable_backlight(true);
|
||||
|
||||
st7789_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION);
|
||||
}
|
||||
|
||||
void st7789_enable_backlight(bool backlight)
|
||||
{
|
||||
#if ST7789_ENABLE_BACKLIGHT_CONTROL
|
||||
printf("%s backlight.\n", backlight ? "Enabling" : "Disabling");
|
||||
uint32_t tmp = 0;
|
||||
|
||||
#if (ST7789_BCKL_ACTIVE_LVL==1)
|
||||
tmp = backlight ? 1 : 0;
|
||||
#else
|
||||
tmp = backlight ? 0 : 1;
|
||||
#endif
|
||||
|
||||
gpio_set_level(ST7789_BCKL, tmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* The ST7789 display controller can drive 320*240 displays, when using a 240*240
|
||||
* display there's a gap of 80px, we need to edit the coordinates to take into
|
||||
* account that gap, this is not necessary in all orientations. */
|
||||
void st7789_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
|
||||
{
|
||||
uint8_t data[4] = {0};
|
||||
|
||||
uint16_t offsetx1 = area->x1;
|
||||
uint16_t offsetx2 = area->x2;
|
||||
uint16_t offsety1 = area->y1;
|
||||
uint16_t offsety2 = area->y2;
|
||||
|
||||
#if (CONFIG_LV_TFT_DISPLAY_OFFSETS)
|
||||
offsetx1 += CONFIG_LV_TFT_DISPLAY_X_OFFSET;
|
||||
offsetx2 += CONFIG_LV_TFT_DISPLAY_X_OFFSET;
|
||||
offsety1 += CONFIG_LV_TFT_DISPLAY_Y_OFFSET;
|
||||
offsety2 += CONFIG_LV_TFT_DISPLAY_Y_OFFSET;
|
||||
|
||||
#elif (LV_HOR_RES_MAX == 240) && (LV_VER_RES_MAX == 240)
|
||||
#if (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
|
||||
offsetx1 += 80;
|
||||
offsetx2 += 80;
|
||||
#elif (CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
|
||||
offsety1 += 80;
|
||||
offsety2 += 80;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Column addresses*/
|
||||
st7789_send_cmd(ST7789_CASET);
|
||||
data[0] = (offsetx1 >> 8) & 0xFF;
|
||||
data[1] = offsetx1 & 0xFF;
|
||||
data[2] = (offsetx2 >> 8) & 0xFF;
|
||||
data[3] = offsetx2 & 0xFF;
|
||||
st7789_send_data(data, 4);
|
||||
|
||||
/*Page addresses*/
|
||||
st7789_send_cmd(ST7789_RASET);
|
||||
data[0] = (offsety1 >> 8) & 0xFF;
|
||||
data[1] = offsety1 & 0xFF;
|
||||
data[2] = (offsety2 >> 8) & 0xFF;
|
||||
data[3] = offsety2 & 0xFF;
|
||||
st7789_send_data(data, 4);
|
||||
|
||||
/*Memory write*/
|
||||
st7789_send_cmd(ST7789_RAMWR);
|
||||
|
||||
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
|
||||
|
||||
st7789_send_color((void*)color_map, size * 2);
|
||||
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
static void st7789_send_cmd(uint8_t cmd)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ST7789_DC, 0);
|
||||
disp_spi_send_data(&cmd, 1);
|
||||
}
|
||||
|
||||
static void st7789_send_data(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ST7789_DC, 1);
|
||||
disp_spi_send_data(data, length);
|
||||
}
|
||||
|
||||
static void st7789_send_color(void * data, uint16_t length)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(ST7789_DC, 1);
|
||||
disp_spi_send_colors(data, length);
|
||||
}
|
||||
|
||||
static void st7789_set_orientation(uint8_t orientation)
|
||||
{
|
||||
// ESP_ASSERT(orientation < 4);
|
||||
|
||||
const char *orientation_str[] = {
|
||||
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]);
|
||||
|
||||
uint8_t data[] =
|
||||
{
|
||||
#if CONFIG_LV_PREDEFINED_DISPLAY_TTGO
|
||||
0x60, 0xA0, 0x00, 0xC0
|
||||
#else
|
||||
0xC0, 0x00, 0x60, 0xA0
|
||||
#endif
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]);
|
||||
|
||||
st7789_send_cmd(ST7789_MADCTL);
|
||||
st7789_send_data((void *) &data[orientation], 1);
|
||||
}
|
120
lvgl_tft/st7789.h
Normal file
120
lvgl_tft/st7789.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/**
|
||||
* @file st7789.h
|
||||
*
|
||||
* Mostly taken from lbthomsen/esp-idf-littlevgl github.
|
||||
*/
|
||||
|
||||
#ifndef ST7789_H
|
||||
#define ST7789_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
#include "../lvgl_helpers.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define ST7789_DC CONFIG_LV_DISP_PIN_DC
|
||||
#define ST7789_RST CONFIG_LV_DISP_PIN_RST
|
||||
#define ST7789_BCKL CONFIG_LV_DISP_PIN_BCKL
|
||||
|
||||
#define ST7789_ENABLE_BACKLIGHT_CONTROL CONFIG_LV_ENABLE_BACKLIGHT_CONTROL
|
||||
|
||||
#if CONFIG_LV_BACKLIGHT_ACTIVE_LVL
|
||||
#define ST7789_BCKL_ACTIVE_LVL 1
|
||||
#else
|
||||
#define ST7789_BCKL_ACTIVE_LVL 0
|
||||
#endif
|
||||
|
||||
/* ST7789 commands */
|
||||
#define ST7789_NOP 0x00
|
||||
#define ST7789_SWRESET 0x01
|
||||
#define ST7789_RDDID 0x04
|
||||
#define ST7789_RDDST 0x09
|
||||
|
||||
#define ST7789_RDDPM 0x0A // Read display power mode
|
||||
#define ST7789_RDD_MADCTL 0x0B // Read display MADCTL
|
||||
#define ST7789_RDD_COLMOD 0x0C // Read display pixel format
|
||||
#define ST7789_RDDIM 0x0D // Read display image mode
|
||||
#define ST7789_RDDSM 0x0E // Read display signal mode
|
||||
#define ST7789_RDDSR 0x0F // Read display self-diagnostic result (ST7789V)
|
||||
|
||||
#define ST7789_SLPIN 0x10
|
||||
#define ST7789_SLPOUT 0x11
|
||||
#define ST7789_PTLON 0x12
|
||||
#define ST7789_NORON 0x13
|
||||
|
||||
#define ST7789_INVOFF 0x20
|
||||
#define ST7789_INVON 0x21
|
||||
#define ST7789_GAMSET 0x26 // Gamma set
|
||||
#define ST7789_DISPOFF 0x28
|
||||
#define ST7789_DISPON 0x29
|
||||
#define ST7789_CASET 0x2A
|
||||
#define ST7789_RASET 0x2B
|
||||
#define ST7789_RAMWR 0x2C
|
||||
#define ST7789_RGBSET 0x2D // Color setting for 4096, 64K and 262K colors
|
||||
#define ST7789_RAMRD 0x2E
|
||||
|
||||
#define ST7789_PTLAR 0x30
|
||||
#define ST7789_VSCRDEF 0x33 // Vertical scrolling definition (ST7789V)
|
||||
#define ST7789_TEOFF 0x34 // Tearing effect line off
|
||||
#define ST7789_TEON 0x35 // Tearing effect line on
|
||||
#define ST7789_MADCTL 0x36 // Memory data access control
|
||||
#define ST7789_IDMOFF 0x38 // Idle mode off
|
||||
#define ST7789_IDMON 0x39 // Idle mode on
|
||||
#define ST7789_RAMWRC 0x3C // Memory write continue (ST7789V)
|
||||
#define ST7789_RAMRDC 0x3E // Memory read continue (ST7789V)
|
||||
#define ST7789_COLMOD 0x3A
|
||||
|
||||
#define ST7789_RAMCTRL 0xB0 // RAM control
|
||||
#define ST7789_RGBCTRL 0xB1 // RGB control
|
||||
#define ST7789_PORCTRL 0xB2 // Porch control
|
||||
#define ST7789_FRCTRL1 0xB3 // Frame rate control
|
||||
#define ST7789_PARCTRL 0xB5 // Partial mode control
|
||||
#define ST7789_GCTRL 0xB7 // Gate control
|
||||
#define ST7789_GTADJ 0xB8 // Gate on timing adjustment
|
||||
#define ST7789_DGMEN 0xBA // Digital gamma enable
|
||||
#define ST7789_VCOMS 0xBB // VCOMS setting
|
||||
#define ST7789_LCMCTRL 0xC0 // LCM control
|
||||
#define ST7789_IDSET 0xC1 // ID setting
|
||||
#define ST7789_VDVVRHEN 0xC2 // VDV and VRH command enable
|
||||
#define ST7789_VRHS 0xC3 // VRH set
|
||||
#define ST7789_VDVSET 0xC4 // VDV setting
|
||||
#define ST7789_VCMOFSET 0xC5 // VCOMS offset set
|
||||
#define ST7789_FRCTR2 0xC6 // FR Control 2
|
||||
#define ST7789_CABCCTRL 0xC7 // CABC control
|
||||
#define ST7789_REGSEL1 0xC8 // Register value section 1
|
||||
#define ST7789_REGSEL2 0xCA // Register value section 2
|
||||
#define ST7789_PWMFRSEL 0xCC // PWM frequency selection
|
||||
#define ST7789_PWCTRL1 0xD0 // Power control 1
|
||||
#define ST7789_VAPVANEN 0xD2 // Enable VAP/VAN signal output
|
||||
#define ST7789_CMD2EN 0xDF // Command 2 enable
|
||||
#define ST7789_PVGAMCTRL 0xE0 // Positive voltage gamma control
|
||||
#define ST7789_NVGAMCTRL 0xE1 // Negative voltage gamma control
|
||||
#define ST7789_DGMLUTR 0xE2 // Digital gamma look-up table for red
|
||||
#define ST7789_DGMLUTB 0xE3 // Digital gamma look-up table for blue
|
||||
#define ST7789_GATECTRL 0xE4 // Gate control
|
||||
#define ST7789_SPI2EN 0xE7 // SPI2 enable
|
||||
#define ST7789_PWCTRL2 0xE8 // Power control 2
|
||||
#define ST7789_EQCTRL 0xE9 // Equalize time control
|
||||
#define ST7789_PROMCTRL 0xEC // Program control
|
||||
#define ST7789_PROMEN 0xFA // Program mode enable
|
||||
#define ST7789_NVMSET 0xFC // NVM setting
|
||||
#define ST7789_PROMACT 0xFE // Program action
|
||||
|
||||
void st7789_init(void);
|
||||
void st7789_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map);
|
||||
void st7789_enable_backlight(bool backlight);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* ST7789_H */
|
268
lvgl_tft/uc8151d.c
Normal file
268
lvgl_tft/uc8151d.c
Normal file
|
@ -0,0 +1,268 @@
|
|||
/**
|
||||
@file uc8151d.c
|
||||
@brief GoodDisplay GDEW0154M10 DES e-paper display w/ UltraChip UC8151D
|
||||
@version 1.0
|
||||
@date 2020-08-28
|
||||
@author Jackson Ming Hu <huming2207@gmail.com>
|
||||
|
||||
|
||||
@section LICENSE
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Jackson Ming Hu
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/event_groups.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#include "disp_spi.h"
|
||||
#include "disp_driver.h"
|
||||
#include "uc8151d.h"
|
||||
|
||||
#define TAG "lv_uc8151d"
|
||||
|
||||
#define PIN_DC CONFIG_LV_DISP_PIN_DC
|
||||
#define PIN_DC_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_DC)))
|
||||
#define PIN_RST CONFIG_LV_DISP_PIN_RST
|
||||
#define PIN_RST_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_RST)))
|
||||
#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_ROW_LEN (EPD_HEIGHT / 8u)
|
||||
|
||||
#define BIT_SET(a, b) ((a) |= (1U << (b)))
|
||||
#define BIT_CLEAR(a, b) ((a) &= ~(1U << (b)))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint8_t data[3];
|
||||
size_t len;
|
||||
} uc8151d_seq_t;
|
||||
|
||||
#define EPD_SEQ_LEN(x) ((sizeof(x) / sizeof(uc8151d_seq_t)))
|
||||
|
||||
static EventGroupHandle_t uc8151d_evts = NULL;
|
||||
|
||||
static void IRAM_ATTR uc8151d_busy_intr(void *arg)
|
||||
{
|
||||
BaseType_t xResult;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xResult = xEventGroupSetBitsFromISR(uc8151d_evts, EVT_BUSY, &xHigherPriorityTaskWoken);
|
||||
if (xResult == pdPASS) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
static void uc8151d_spi_send_cmd(uint8_t cmd)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(PIN_DC, 0); // DC = 0 for command
|
||||
disp_spi_send_data(&cmd, 1);
|
||||
}
|
||||
|
||||
static void uc8151d_spi_send_data(uint8_t *data, size_t len)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(PIN_DC, 1); // DC = 1 for data
|
||||
disp_spi_send_data(data, len);
|
||||
}
|
||||
|
||||
static void uc8151d_spi_send_data_byte(uint8_t data)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(PIN_DC, 1); // DC = 1 for data
|
||||
disp_spi_send_data(&data, 1);
|
||||
}
|
||||
|
||||
static void uc8151d_spi_send_fb(uint8_t *data, size_t len)
|
||||
{
|
||||
disp_wait_for_pending_transactions();
|
||||
gpio_set_level(PIN_DC, 1); // DC = 1 for data
|
||||
disp_spi_send_colors(data, len);
|
||||
}
|
||||
|
||||
static void uc8151d_spi_send_seq(const uc8151d_seq_t *seq, size_t len)
|
||||
{
|
||||
ESP_LOGD(TAG, "Writing cmd/data sequence, count %u", len);
|
||||
|
||||
if (!seq || len < 1) return;
|
||||
for (size_t cmd_idx = 0; cmd_idx < len; cmd_idx++) {
|
||||
uc8151d_spi_send_cmd(seq[cmd_idx].cmd);
|
||||
if (seq[cmd_idx].len > 0) {
|
||||
uc8151d_spi_send_data((uint8_t *) seq[cmd_idx].data, seq[cmd_idx].len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t uc8151d_wait_busy(uint32_t timeout_ms)
|
||||
{
|
||||
uint32_t wait_ticks = (timeout_ms == 0 ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms));
|
||||
EventBits_t bits = xEventGroupWaitBits(uc8151d_evts,
|
||||
EVT_BUSY, // Wait for busy bit
|
||||
pdTRUE, pdTRUE, // Clear on exit, wait for all
|
||||
wait_ticks); // Timeout
|
||||
|
||||
return ((bits & EVT_BUSY) != 0) ? ESP_OK : ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
static void uc8151d_sleep()
|
||||
{
|
||||
// Set VCOM to 0xf7
|
||||
uc8151d_spi_send_cmd(0x50);
|
||||
uc8151d_spi_send_data_byte(0xf7);
|
||||
|
||||
// Power off
|
||||
uc8151d_spi_send_cmd(0x02);
|
||||
uc8151d_wait_busy(0);
|
||||
|
||||
// Go to sleep
|
||||
uc8151d_spi_send_cmd(0x07);
|
||||
uc8151d_spi_send_data_byte(0xa5);
|
||||
}
|
||||
|
||||
static void uc8151d_panel_init()
|
||||
{
|
||||
// Hardware reset for 3 times - not sure why but it's from official demo code
|
||||
for (uint8_t cnt = 0; cnt < 3; cnt++) {
|
||||
gpio_set_level(PIN_RST, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(10)); // At least 10ms, leave 20ms for now just in case...
|
||||
gpio_set_level(PIN_RST, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
// Power up
|
||||
uc8151d_spi_send_cmd(0x04);
|
||||
uc8151d_wait_busy(0);
|
||||
|
||||
// Panel settings
|
||||
uc8151d_spi_send_cmd(0x00);
|
||||
#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
|
||||
uc8151d_spi_send_data_byte(0x13);
|
||||
#elif defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
|
||||
uc8151d_spi_send_data_byte(0x1f);
|
||||
#endif
|
||||
|
||||
// VCOM & Data intervals
|
||||
uc8151d_spi_send_cmd(0x50);
|
||||
uc8151d_spi_send_data_byte(0x97);
|
||||
}
|
||||
|
||||
static void uc8151d_full_update(uint8_t *buf)
|
||||
{
|
||||
uc8151d_panel_init();
|
||||
|
||||
uint8_t *buf_ptr = buf;
|
||||
uint8_t old_data[EPD_ROW_LEN] = { 0 };
|
||||
|
||||
// Fill old data
|
||||
uc8151d_spi_send_cmd(0x10);
|
||||
for (size_t h_idx = 0; h_idx < EPD_HEIGHT; h_idx++) {
|
||||
uc8151d_spi_send_data(old_data, EPD_ROW_LEN);
|
||||
}
|
||||
|
||||
// Fill new data
|
||||
uc8151d_spi_send_cmd(0x13);
|
||||
for (size_t h_idx = 0; h_idx < EPD_HEIGHT; h_idx++) {
|
||||
uc8151d_spi_send_data(buf_ptr, EPD_ROW_LEN);
|
||||
buf_ptr += EPD_ROW_LEN;
|
||||
}
|
||||
|
||||
// Issue refresh
|
||||
uc8151d_spi_send_cmd(0x12);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
uc8151d_wait_busy(0);
|
||||
|
||||
uc8151d_sleep();
|
||||
}
|
||||
|
||||
void uc8151d_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
|
||||
{
|
||||
size_t len = ((area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1)) / 8;
|
||||
|
||||
ESP_LOGD(TAG, "x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", area->x1, area->x2, area->y1, area->y2);
|
||||
ESP_LOGD(TAG, "Writing LVGL fb with len: %u", len);
|
||||
|
||||
uint8_t *buf = (uint8_t *) color_map;
|
||||
uc8151d_full_update(buf);
|
||||
|
||||
lv_disp_flush_ready(drv);
|
||||
ESP_LOGD(TAG, "Ready");
|
||||
}
|
||||
|
||||
void uc8151d_lv_set_fb_cb(struct _disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
uint16_t byte_index = (x >> 3u) + (y * EPD_ROW_LEN);
|
||||
uint8_t bit_index = x & 0x07u;
|
||||
|
||||
if (color.full) {
|
||||
BIT_SET(buf[byte_index], 7 - bit_index);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Clear at x: %u, y: %u", x, y);
|
||||
BIT_CLEAR(buf[byte_index], 7 - bit_index);
|
||||
}
|
||||
}
|
||||
|
||||
void uc8151d_lv_rounder_cb(struct _disp_drv_t *disp_drv, lv_area_t *area)
|
||||
{
|
||||
// Always send full framebuffer if it's not in partial mode
|
||||
area->x1 = 0;
|
||||
area->y1 = 0;
|
||||
area->x2 = EPD_WIDTH - 1;
|
||||
area->y2 = EPD_HEIGHT - 1;
|
||||
}
|
||||
|
||||
void uc8151d_init()
|
||||
{
|
||||
// Initialise event group
|
||||
uc8151d_evts = xEventGroupCreate();
|
||||
if (!uc8151d_evts) {
|
||||
ESP_LOGE(TAG, "Failed when initialising event group!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup output pins, output (PP)
|
||||
gpio_config_t out_io_conf = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = PIN_DC_BIT | PIN_RST_BIT,
|
||||
.pull_down_en = 0,
|
||||
.pull_up_en = 0,
|
||||
};
|
||||
ESP_ERROR_CHECK(gpio_config(&out_io_conf));
|
||||
|
||||
// Setup input pin, pull-up, input
|
||||
gpio_config_t in_io_conf = {
|
||||
.intr_type = GPIO_INTR_POSEDGE,
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pin_bit_mask = PIN_BUSY_BIT,
|
||||
.pull_down_en = 0,
|
||||
.pull_up_en = 1,
|
||||
};
|
||||
ESP_ERROR_CHECK(gpio_config(&in_io_conf));
|
||||
gpio_install_isr_service(0);
|
||||
gpio_isr_handler_add(PIN_BUSY, uc8151d_busy_intr, (void *) PIN_BUSY);
|
||||
|
||||
ESP_LOGI(TAG, "IO init finished");
|
||||
uc8151d_panel_init();
|
||||
ESP_LOGI(TAG, "Panel initialised");
|
||||
}
|
39
lvgl_tft/uc8151d.h
Normal file
39
lvgl_tft/uc8151d.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
@file uc8151d.h
|
||||
@brief GoodDisplay GDEW0154M09 e-paper display w/ FitiPower JD79653A
|
||||
@version 1.0
|
||||
@date 2020-08-28
|
||||
@author Jackson Ming Hu <huming2207@gmail.com>
|
||||
|
||||
|
||||
@section LICENSE
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Jackson Ming Hu
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LVGL_DEMO_UC8151D_H
|
||||
#define LVGL_DEMO_UC8151D_H
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
void uc8151d_init();
|
||||
void uc8151d_lv_set_fb_cb(struct _disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t color, lv_opa_t opa);
|
||||
|
||||
void uc8151d_lv_rounder_cb(struct _disp_drv_t *disp_drv, lv_area_t *area);
|
||||
void uc8151d_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map);
|
||||
|
||||
#endif //LVGL_DEMO_UC8151D_H
|
34
lvgl_touch/CMakeLists.txt
Normal file
34
lvgl_touch/CMakeLists.txt
Normal file
|
@ -0,0 +1,34 @@
|
|||
if(ESP_PLATFORM)
|
||||
|
||||
set(SOURCES "touch_driver.c")
|
||||
|
||||
# Include only the source file of the selected
|
||||
# display controller.
|
||||
if(CONFIG_LV_TOUCH_CONTROLLER_XPT2046)
|
||||
list(APPEND SOURCES "xpt2046.c")
|
||||
elseif(CONFIG_LV_TOUCH_CONTROLLER_FT6X06)
|
||||
list(APPEND SOURCES "ft6x36.c")
|
||||
elseif(CONFIG_LV_TOUCH_CONTROLLER_STMPE610)
|
||||
list(APPEND SOURCES "stmpe610")
|
||||
elseif(CONFIG_LV_TOUCH_CONTROLLER_ADCRAW)
|
||||
list(APPEND SOURCES "adcraw.c")
|
||||
elseif(CONFIG_LV_TOUCH_CONTROLLER_FT81X)
|
||||
list(APPEND SOURCES "FT81x.c")
|
||||
elseif(CONFIG_LV_TOUCH_CONTROLLER_RA8875)
|
||||
list(APPEND SOURCES "ra8875_touch.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI)
|
||||
list(APPEND SOURCES "tp_spi.c")
|
||||
elseif(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_I2C)
|
||||
list(APPEND SOURCES "tp_i2c.c")
|
||||
endif()
|
||||
|
||||
# Print the included source files
|
||||
message("SOURCES contents: " "${SOURCES}")
|
||||
|
||||
idf_component_register(SRCS ${SOURCES}
|
||||
INCLUDE_DIRS .
|
||||
REQUIRES lvgl)
|
||||
|
||||
endif()
|
85
lvgl_touch/FT81x.c
Normal file
85
lvgl_touch/FT81x.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* @file FT81x.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "FT81x.h"
|
||||
|
||||
#include "../lvgl_tft/EVE.h"
|
||||
#include "../lvgl_tft/EVE_commands.h"
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
/**
|
||||
* Get the current position and state of the touchpad
|
||||
* @param data store the read data here
|
||||
* @return false: because no more data to be read
|
||||
*/
|
||||
bool FT81x_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
|
||||
{
|
||||
static int16_t last_x = 0;
|
||||
static int16_t last_y = 0;
|
||||
bool touched = true;
|
||||
|
||||
uint32_t XY = EVE_memRead32(REG_TOUCH_SCREEN_XY);
|
||||
uint16_t Y = XY & 0xffff;
|
||||
uint16_t X = XY >> 16;
|
||||
|
||||
// is it not touched (or invalid because of calibration range)
|
||||
if(X == 0x8000 || Y == 0x8000 || X > LV_HOR_RES_MAX || Y > LV_VER_RES_MAX)
|
||||
{
|
||||
touched = false;
|
||||
X = last_x;
|
||||
Y = last_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_x = X;
|
||||
last_y = Y;
|
||||
}
|
||||
|
||||
data->point.x = X;
|
||||
data->point.y = Y;
|
||||
data->state = (touched == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
46
lvgl_touch/FT81x.h
Normal file
46
lvgl_touch/FT81x.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* @file STMPE610.h
|
||||
*/
|
||||
|
||||
#ifndef FT81X_TOUCH__H
|
||||
#define FT81X_TOUCH__H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
;
|
||||
bool FT81x_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* FT81X_TOUCH__H */
|
458
lvgl_touch/Kconfig
Normal file
458
lvgl_touch/Kconfig
Normal file
|
@ -0,0 +1,458 @@
|
|||
menu "LVGL Touch controller"
|
||||
|
||||
config LV_TOUCH_CONTROLLER
|
||||
int
|
||||
default 0 if LV_TOUCH_CONTROLLER_NONE
|
||||
default 1 if LV_TOUCH_CONTROLLER_XPT2046
|
||||
default 2 if LV_TOUCH_CONTROLLER_FT6X06
|
||||
default 3 if LV_TOUCH_CONTROLLER_STMPE610
|
||||
default 4 if LV_TOUCH_CONTROLLER_ADCRAW
|
||||
default 5 if LV_TOUCH_CONTROLLER_FT81X
|
||||
default 6 if LV_TOUCH_CONTROLLER_RA8875
|
||||
|
||||
choice
|
||||
prompt "Select a touch panel controller model."
|
||||
default LV_TOUCH_CONTROLLER_NONE
|
||||
help
|
||||
Select the controller for your touch panel.
|
||||
|
||||
config LV_TOUCH_CONTROLLER_NONE
|
||||
bool "None"
|
||||
config LV_TOUCH_CONTROLLER_XPT2046
|
||||
select LV_TOUCH_DRIVER_PROTOCOL_SPI
|
||||
bool "XPT2046"
|
||||
config LV_TOUCH_CONTROLLER_FT6X06
|
||||
select LV_TOUCH_DRIVER_PROTOCOL_I2C
|
||||
bool "FT6X06"
|
||||
config LV_TOUCH_CONTROLLER_STMPE610
|
||||
select LV_TOUCH_DRIVER_PROTOCOL_SPI
|
||||
bool "STMPE610"
|
||||
config LV_TOUCH_CONTROLLER_ADCRAW
|
||||
select LV_TOUCH_DRIVER_ADC
|
||||
bool "ADCRAW"
|
||||
config LV_TOUCH_CONTROLLER_FT81X
|
||||
select LV_TOUCH_DRIVER_PROTOCOL_SPI
|
||||
bool "FT81X"
|
||||
config LV_TOUCH_CONTROLLER_RA8875
|
||||
select LV_TOUCH_DRIVER_DISPLAY
|
||||
bool "RA8875"
|
||||
endchoice
|
||||
|
||||
config LV_TOUCH_DRIVER_PROTOCOL_SPI
|
||||
bool
|
||||
help
|
||||
Touch controller protocol SPI
|
||||
|
||||
config LV_TOUCH_DRIVER_PROTOCOL_I2C
|
||||
bool
|
||||
help
|
||||
Touch controller protocol I2C
|
||||
|
||||
config LV_TOUCH_DRIVER_ADC
|
||||
bool
|
||||
help
|
||||
Touch controller via ADC
|
||||
|
||||
config LV_TOUCH_DRIVER_DISPLAY
|
||||
bool
|
||||
help
|
||||
Touch controller uses same interface/device as display
|
||||
(Note: Display must be initialized before touch)
|
||||
|
||||
choice
|
||||
prompt "Touch I2C port"
|
||||
depends on LV_TOUCH_DRIVER_PROTOCOL_I2C
|
||||
|
||||
default LV_TOUCH_I2C_PORT_0
|
||||
help
|
||||
Select the I2C port used by the touch controller.
|
||||
|
||||
config LV_TOUCH_I2C_PORT_0
|
||||
bool "I2C PORT 0"
|
||||
config LV_TOUCH_I2C_PORT_1
|
||||
bool "I2C PORT 1"
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Touch Controller SPI Bus."
|
||||
depends on LV_TOUCH_DRIVER_PROTOCOL_SPI
|
||||
|
||||
default LV_TOUCH_CONTROLLER_SPI_VSPI if !IDF_TARGET_ESP32S2
|
||||
default LV_TOUCH_CONTROLLER_SPI_FSPI if IDF_TARGET_ESP32S2
|
||||
help
|
||||
Select the SPI Bus the TFT Display is attached to.
|
||||
|
||||
config LV_TOUCH_CONTROLLER_SPI_HSPI
|
||||
bool "HSPI"
|
||||
config LV_TOUCH_CONTROLLER_SPI_VSPI
|
||||
bool "VSPI" if !IDF_TARGET_ESP32S2
|
||||
config LV_TOUCH_CONTROLLER_SPI_FSPI
|
||||
bool "FSPI" if IDF_TARGET_ESP32S2
|
||||
endchoice
|
||||
|
||||
menu "Touchpanel (XPT2046) Pin Assignments"
|
||||
depends on LV_TOUCH_CONTROLLER_XPT2046
|
||||
|
||||
config LV_TOUCH_SPI_MISO
|
||||
int
|
||||
prompt "GPIO for MISO (Master In Slave Out)"
|
||||
range 0 39
|
||||
default 35 if LV_PREDEFINED_PINS_38V1
|
||||
default 19
|
||||
|
||||
help
|
||||
Configure the touchpanel MISO pin here.
|
||||
|
||||
config LV_TOUCH_SPI_MOSI
|
||||
int
|
||||
prompt "GPIO for MOSI (Master Out Slave In)"
|
||||
range 0 39
|
||||
default 32 if LV_PREDEFINED_PINS_38V1
|
||||
default 23
|
||||
|
||||
help
|
||||
Configure the touchpanel MOSI pin here.
|
||||
|
||||
config LV_TOUCH_SPI_CLK
|
||||
int "GPIO for CLK (SCK / Serial Clock)"
|
||||
range 0 39
|
||||
default 26 if LV_PREDEFINED_PINS_38V1
|
||||
default 18
|
||||
help
|
||||
Configure the touchpanel CLK pin here.
|
||||
|
||||
config LV_TOUCH_SPI_CS
|
||||
int "GPIO for CS (Slave Select)"
|
||||
range 0 39
|
||||
default 33 if LV_PREDEFINED_PINS_38V1
|
||||
default 5
|
||||
help
|
||||
Configure the touchpanel CS pin here.
|
||||
|
||||
config LV_TOUCH_PIN_IRQ
|
||||
int "GPIO for IRQ (Interrupt Request)"
|
||||
range 0 39
|
||||
default 27 if LV_PREDEFINED_PINS_38V4
|
||||
default 25
|
||||
help
|
||||
Configure the touchpanel CS pin here.
|
||||
endmenu
|
||||
|
||||
menu "Touchpanel Configuration (XPT2046)"
|
||||
depends on LV_TOUCH_CONTROLLER_XPT2046
|
||||
|
||||
config LV_TOUCH_X_MIN
|
||||
int
|
||||
prompt "Minimum X coordinate value."
|
||||
default 0 if LV_PREDEFINED_PINS_38V4
|
||||
default 200
|
||||
|
||||
config LV_TOUCH_Y_MIN
|
||||
int
|
||||
prompt "Minimum Y coordinate value."
|
||||
default 0 if LV_PREDEFINED_PINS_38V4
|
||||
default 120
|
||||
|
||||
config LV_TOUCH_X_MAX
|
||||
int
|
||||
prompt "Maximum X coordinate value."
|
||||
default 4095 if LV_PREDEFINED_PINS_38V4
|
||||
default 1900
|
||||
|
||||
config LV_TOUCH_Y_MAX
|
||||
int
|
||||
prompt "Maximum Y coordinate value."
|
||||
default 4095 if LV_PREDEFINED_PINS_38V4
|
||||
default 1900
|
||||
|
||||
config LV_TOUCH_XY_SWAP
|
||||
bool
|
||||
prompt "Swap XY."
|
||||
default y
|
||||
|
||||
config LV_TOUCH_INVERT_X
|
||||
bool
|
||||
prompt "Invert X coordinate value."
|
||||
default y
|
||||
|
||||
config LV_TOUCH_INVERT_Y
|
||||
bool
|
||||
prompt "Invert Y coordinate value."
|
||||
default y
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Touchpanel (FT6X06) Pin Assignments"
|
||||
depends on LV_TOUCH_CONTROLLER_FT6X06
|
||||
|
||||
config LV_TOUCH_I2C_SDA
|
||||
int
|
||||
prompt "GPIO for SDA (I2C)"
|
||||
range 0 39
|
||||
default 21
|
||||
help
|
||||
Configure the I2C touchpanel SDA pin here.
|
||||
|
||||
config LV_TOUCH_I2C_SCL
|
||||
int "GPIO for clock signal SCL (I2C)"
|
||||
range 0 39
|
||||
default 22
|
||||
help
|
||||
Configure the I2C touchpanel SCL pin here.
|
||||
endmenu
|
||||
|
||||
menu "Touchpanel Configuration (FT6X06)"
|
||||
depends on LV_TOUCH_CONTROLLER_FT6X06
|
||||
|
||||
config LV_FT6X36_SWAPXY
|
||||
bool
|
||||
prompt "Swap X with Y coordinate."
|
||||
default y
|
||||
|
||||
config LV_FT6X36_INVERT_X
|
||||
bool
|
||||
prompt "Invert X coordinate value."
|
||||
default n
|
||||
|
||||
config LV_FT6X36_INVERT_Y
|
||||
bool
|
||||
prompt "Invert Y coordinate value."
|
||||
default y
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Touchpanel (STMPE610) Pin Assignments"
|
||||
depends on LV_TOUCH_CONTROLLER_STMPE610
|
||||
|
||||
config LV_TOUCH_SPI_MISO
|
||||
int
|
||||
prompt "GPIO for MISO (Master In Slave Out)"
|
||||
range 0 39
|
||||
default 35 if LV_PREDEFINED_PINS_38V1
|
||||
default 19 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING
|
||||
default 19
|
||||
|
||||
help
|
||||
Configure the touchpanel MISO pin here.
|
||||
|
||||
config LV_TOUCH_SPI_MOSI
|
||||
int
|
||||
prompt "GPIO for MOSI (Master Out Slave In)"
|
||||
range 0 39
|
||||
default 32 if LV_PREDEFINED_PINS_38V1
|
||||
default 18 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING
|
||||
default 23
|
||||
|
||||
help
|
||||
Configure the touchpanel MOSI pin here.
|
||||
|
||||
config LV_TOUCH_SPI_CLK
|
||||
int "GPIO for CLK (SCK / Serial Clock)"
|
||||
range 0 39
|
||||
default 26 if LV_PREDEFINED_PINS_38V1
|
||||
default 5 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING
|
||||
default 18
|
||||
help
|
||||
Configure the touchpanel CLK pin here.
|
||||
|
||||
config LV_TOUCH_SPI_CS
|
||||
int "GPIO for CS (Slave Select)"
|
||||
range 0 39
|
||||
default 33 if LV_PREDEFINED_PINS_38V1
|
||||
default 32 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING
|
||||
default 5
|
||||
help
|
||||
Configure the touchpanel CS pin here.
|
||||
endmenu
|
||||
|
||||
menu "Touchpanel Configuration (STMPE610)"
|
||||
depends on LV_TOUCH_CONTROLLER_STMPE610
|
||||
|
||||
config LV_TOUCH_X_MIN
|
||||
int
|
||||
prompt "Minimum X coordinate value."
|
||||
default 160
|
||||
|
||||
config LV_TOUCH_Y_MIN
|
||||
int
|
||||
prompt "Minimum Y coordinate value."
|
||||
default 230
|
||||
|
||||
config LV_TOUCH_X_MAX
|
||||
int
|
||||
prompt "Maximum X coordinate value."
|
||||
default 3800
|
||||
|
||||
config LV_TOUCH_Y_MAX
|
||||
int
|
||||
prompt "Maximum Y coordinate value."
|
||||
default 3800
|
||||
|
||||
config LV_TOUCH_XY_SWAP
|
||||
bool
|
||||
prompt "Swap XY."
|
||||
default n
|
||||
|
||||
config LV_TOUCH_INVERT_X
|
||||
bool
|
||||
prompt "Invert X coordinate value."
|
||||
default y
|
||||
|
||||
config LV_TOUCH_INVERT_Y
|
||||
bool
|
||||
prompt "Invert Y coordinate value."
|
||||
default y
|
||||
endmenu
|
||||
|
||||
menu "Touchpanel (ADCRAW) Pin Assignments"
|
||||
depends on LV_TOUCH_CONTROLLER_ADCRAW
|
||||
|
||||
config LV_TOUCHSCREEN_RESISTIVE_PIN_YU
|
||||
int
|
||||
prompt "GPIO Y+"
|
||||
default 26 if CONFIG_LV_PREDEFINED_DISPLAY_WROVER4
|
||||
default 26
|
||||
|
||||
help
|
||||
Configure the touchpanel Y+ pin. Can be a regular GPIO.
|
||||
|
||||
config LV_TOUCHSCREEN_RESISTIVE_PIN_YD
|
||||
int
|
||||
prompt "GPIO/ADC Y-"
|
||||
default 32 if CONFIG_LV_PREDEFINED_DISPLAY_WROVER4
|
||||
default 32
|
||||
|
||||
help
|
||||
Configure the touchpanel Y- pin. Must be ADC input.
|
||||
|
||||
config LV_TOUCHSCREEN_RESISTIVE_PIN_XL
|
||||
int
|
||||
prompt "GPIO X-"
|
||||
default 27 if CONFIG_LV_PREDEFINED_DISPLAY_WROVER4
|
||||
default 27
|
||||
|
||||
help
|
||||
Configure the touchpanel X- pin. Can be a regular GPIO.
|
||||
|
||||
config LV_TOUCHSCREEN_RESISTIVE_PIN_XR
|
||||
int
|
||||
prompt "GPIO/ADC X+"
|
||||
default 33 if CONFIG_LV_PREDEFINED_DISPLAY_WROVER4
|
||||
default 33
|
||||
|
||||
help
|
||||
Configure the touchpanel X- pin. Must be ADC input.
|
||||
endmenu
|
||||
|
||||
menu "Touchpanel Configuration (ADCRAW)"
|
||||
depends on LV_TOUCH_CONTROLLER_ADCRAW
|
||||
|
||||
config LV_TOUCH_X_MIN
|
||||
int
|
||||
prompt "Minimum X coordinate value."
|
||||
default 160
|
||||
|
||||
config LV_TOUCH_Y_MIN
|
||||
int
|
||||
prompt "Minimum Y coordinate value."
|
||||
default 230
|
||||
|
||||
config LV_TOUCH_X_MAX
|
||||
int
|
||||
prompt "Maximum X coordinate value."
|
||||
default 3800
|
||||
|
||||
config LV_TOUCH_Y_MAX
|
||||
int
|
||||
prompt "Maximum Y coordinate value."
|
||||
default 3800
|
||||
|
||||
config LV_TOUCH_XY_SWAP
|
||||
bool
|
||||
prompt "Swap XY."
|
||||
default n
|
||||
|
||||
config LV_TOUCH_INVERT_X
|
||||
bool
|
||||
prompt "Invert X coordinate value."
|
||||
default y
|
||||
|
||||
config LV_TOUCH_INVERT_Y
|
||||
bool
|
||||
prompt "Invert Y coordinate value."
|
||||
default y
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Touchpanel Configuration (RA8875)"
|
||||
depends on LV_TOUCH_CONTROLLER_RA8875
|
||||
|
||||
config LV_TOUCH_X_MIN
|
||||
int
|
||||
prompt "Minimum X coordinate ADC value"
|
||||
range 0 1023
|
||||
default 0
|
||||
|
||||
config LV_TOUCH_Y_MIN
|
||||
int
|
||||
prompt "Minimum Y coordinate ADC value"
|
||||
range 0 1023
|
||||
default 0
|
||||
|
||||
config LV_TOUCH_X_MAX
|
||||
int
|
||||
prompt "Maximum X coordinate ADC value"
|
||||
range 0 1023
|
||||
default 1023
|
||||
|
||||
config LV_TOUCH_Y_MAX
|
||||
int
|
||||
prompt "Maximum Y coordinate ADC value"
|
||||
range 0 1023
|
||||
default 1023
|
||||
|
||||
config LV_TOUCH_XY_SWAP
|
||||
bool
|
||||
prompt "Swap XY"
|
||||
default n
|
||||
|
||||
config LV_TOUCH_INVERT_X
|
||||
bool
|
||||
prompt "Invert X coordinate value"
|
||||
default n
|
||||
|
||||
config LV_TOUCH_INVERT_Y
|
||||
bool
|
||||
prompt "Invert Y coordinate value"
|
||||
default n
|
||||
|
||||
config LV_TOUCH_RA8875_SAMPLE_TIME
|
||||
int
|
||||
prompt "TP Sample Time Adjusting"
|
||||
range 0 7
|
||||
default 0
|
||||
|
||||
config LV_TOUCH_RA8875_ADC_CLOCK
|
||||
int
|
||||
prompt "ADC Clock Setting"
|
||||
range 0 7
|
||||
default 0
|
||||
|
||||
config LV_TOUCH_RA8875_WAKEUP_ENABLE
|
||||
bool
|
||||
prompt "Touch Panel Wakeup Enable"
|
||||
default n
|
||||
|
||||
config LV_TOUCH_RA8875_EXTERNAL_VREF
|
||||
bool
|
||||
prompt "TP ADC Use External Reference Voltage Source"
|
||||
default n
|
||||
|
||||
config LV_TOUCH_RA8875_DEBOUNCE_ENABLE
|
||||
bool
|
||||
prompt "De-bounce Circuit Enable for Touch Panel Interrupt"
|
||||
default y
|
||||
|
||||
endmenu
|
||||
|
||||
endmenu
|
324
lvgl_touch/adcraw.c
Normal file
324
lvgl_touch/adcraw.c
Normal file
|
@ -0,0 +1,324 @@
|
|||
/**
|
||||
* @file ADCRAW.c
|
||||
*/
|
||||
|
||||
#include "adcraw.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#if CONFIG_LV_TOUCH_CONTROLLER_ADCRAW
|
||||
|
||||
#define TAG "ADCRAW"
|
||||
#define CALIBRATIONINSET 1 // range 0 <= CALIBRATIONINSET <= 40
|
||||
#define SAMPLE_CALIBRATION_POINTS 4
|
||||
// use this scale factor to avoid working in floating point numbers
|
||||
#define TOUCHSCREEN_RESISTIVE_CALIBRATION_SCALE_FACTOR 8
|
||||
#define SCALE_FACTOR (1 << TOUCHSCREEN_RESISTIVE_CALIBRATION_SCALE_FACTOR)
|
||||
#define CAL_X_INSET (((GetMaxX() + 1) * (CALIBRATIONINSET >> 1)) / 100)
|
||||
#define CAL_Y_INSET (((GetMaxY() + 1) * (CALIBRATIONINSET >> 1)) / 100)
|
||||
#define NUMSAMPLES 8
|
||||
|
||||
static void ad_touch_handler(void *arg);
|
||||
|
||||
static const esp_timer_create_args_t periodic_timer_args = {
|
||||
.callback = &ad_touch_handler,
|
||||
};
|
||||
static esp_timer_handle_t periodic_timer;
|
||||
|
||||
// Current ADC values for X and Y channels
|
||||
int16_t adcX, adcY = 0;
|
||||
int16_t temp_x, temp_y, temp_z1, temp_z2;
|
||||
|
||||
// coefficient values
|
||||
int _trA, _trB, _trC, _trD;
|
||||
|
||||
int16_t xRawTouch[SAMPLE_CALIBRATION_POINTS];
|
||||
int16_t yRawTouch[SAMPLE_CALIBRATION_POINTS];
|
||||
TOUCH_STATES state;
|
||||
|
||||
const gpio_num_t yu = TOUCHSCREEN_RESISTIVE_PIN_YU;
|
||||
const gpio_num_t xl = TOUCHSCREEN_RESISTIVE_PIN_XL;
|
||||
const gpio_num_t yd = TOUCHSCREEN_RESISTIVE_PIN_YD;
|
||||
const gpio_num_t xr = TOUCHSCREEN_RESISTIVE_PIN_XR;
|
||||
|
||||
static const int gpio_to_adc[] = {
|
||||
GPIO_TO_ADC_ELEMENT(TOUCHSCREEN_RESISTIVE_PIN_YD),
|
||||
GPIO_TO_ADC_ELEMENT(TOUCHSCREEN_RESISTIVE_PIN_XR)
|
||||
};
|
||||
|
||||
static void TouchCalculateCalPoints(void)
|
||||
{
|
||||
int32_t trA, trB, trC, trD; // variables for the coefficients
|
||||
int32_t trAhold, trBhold, trChold, trDhold;
|
||||
int32_t test1, test2; // temp variables (must be signed type)
|
||||
|
||||
int16_t xPoint[SAMPLE_CALIBRATION_POINTS], yPoint[SAMPLE_CALIBRATION_POINTS];
|
||||
|
||||
yPoint[0] = yPoint[1] = CAL_Y_INSET;
|
||||
yPoint[2] = yPoint[3] = (GetMaxY() - CAL_Y_INSET);
|
||||
xPoint[0] = xPoint[3] = CAL_X_INSET;
|
||||
xPoint[1] = xPoint[2] = (GetMaxX() - CAL_X_INSET);
|
||||
|
||||
// calculate points transfer function
|
||||
// based on two simultaneous equations solve for the constants
|
||||
|
||||
// use sample points 1 and 4
|
||||
// Dy1 = aTy1 + b; Dy4 = aTy4 + b
|
||||
// Dx1 = cTx1 + d; Dy4 = aTy4 + b
|
||||
|
||||
test1 = (int32_t)yPoint[0] - (int32_t)yPoint[3];
|
||||
test2 = (int32_t)yRawTouch[0] - (int32_t)yRawTouch[3];
|
||||
|
||||
trA = ((int32_t)((int32_t)test1 * SCALE_FACTOR) / test2);
|
||||
trB = ((int32_t)((int32_t)yPoint[0] * SCALE_FACTOR) - (trA * (int32_t)yRawTouch[0]));
|
||||
|
||||
test1 = (int32_t)xPoint[0] - (int32_t)xPoint[2];
|
||||
test2 = (int32_t)xRawTouch[0] - (int32_t)xRawTouch[2];
|
||||
|
||||
trC = ((int32_t)((int32_t)test1 * SCALE_FACTOR) / test2);
|
||||
trD = ((int32_t)((int32_t)xPoint[0] * SCALE_FACTOR) - (trC * (int32_t)xRawTouch[0]));
|
||||
|
||||
trAhold = trA;
|
||||
trBhold = trB;
|
||||
trChold = trC;
|
||||
trDhold = trD;
|
||||
|
||||
// use sample points 2 and 3
|
||||
// Dy2 = aTy2 + b; Dy3 = aTy3 + b
|
||||
// Dx2 = cTx2 + d; Dy3 = aTy3 + b
|
||||
|
||||
test1 = (int32_t)yPoint[1] - (int32_t)yPoint[2];
|
||||
test2 = (int32_t)yRawTouch[1] - (int32_t)yRawTouch[2];
|
||||
|
||||
trA = ((int32_t)(test1 * SCALE_FACTOR) / test2);
|
||||
trB = ((int32_t)((int32_t)yPoint[1] * SCALE_FACTOR) - (trA * (int32_t)yRawTouch[1]));
|
||||
|
||||
test1 = (int32_t)xPoint[1] - (int32_t)xPoint[3];
|
||||
test2 = (int32_t)xRawTouch[1] - (int32_t)xRawTouch[3];
|
||||
|
||||
trC = ((int32_t)((int32_t)test1 * SCALE_FACTOR) / test2);
|
||||
trD = ((int32_t)((int32_t)xPoint[1] * SCALE_FACTOR) - (trC * (int32_t)xRawTouch[1]));
|
||||
|
||||
// get the average and use it
|
||||
_trA = (trA + trAhold) >> 1;
|
||||
_trB = (trB + trBhold) >> 1;
|
||||
_trC = (trC + trChold) >> 1;
|
||||
_trD = (trD + trDhold) >> 1;
|
||||
}
|
||||
|
||||
void adcraw_init(void)
|
||||
{
|
||||
state = IDLE; // set the state of the state machine to start the sampling
|
||||
|
||||
gpio_set_drive_capability(yu, GPIO_DRIVE_CAP_3);
|
||||
gpio_set_drive_capability(yd, GPIO_DRIVE_CAP_3);
|
||||
gpio_set_drive_capability(xl, GPIO_DRIVE_CAP_3);
|
||||
gpio_set_drive_capability(xr, GPIO_DRIVE_CAP_3);
|
||||
|
||||
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, 5 * 1000)); //5ms (expressed as microseconds)
|
||||
|
||||
/*Load calibration data*/
|
||||
xRawTouch[0] = TOUCHCAL_ULX;
|
||||
yRawTouch[0] = TOUCHCAL_ULY;
|
||||
xRawTouch[1] = TOUCHCAL_URX;
|
||||
yRawTouch[1] = TOUCHCAL_URY;
|
||||
xRawTouch[3] = TOUCHCAL_LLX;
|
||||
yRawTouch[3] = TOUCHCAL_LLY;
|
||||
xRawTouch[2] = TOUCHCAL_LRX;
|
||||
yRawTouch[2] = TOUCHCAL_LRY;
|
||||
|
||||
TouchCalculateCalPoints();
|
||||
}
|
||||
|
||||
static void setup_axis(gpio_num_t plus, gpio_num_t minus, gpio_num_t measure, gpio_num_t ignore)
|
||||
{
|
||||
// Set GPIOs:
|
||||
// - Float "ignore" and "measure"
|
||||
gpio_pad_select_gpio(ignore);
|
||||
gpio_set_direction(ignore, GPIO_MODE_DISABLE);
|
||||
gpio_set_pull_mode(ignore, GPIO_FLOATING);
|
||||
gpio_pad_select_gpio(measure);
|
||||
gpio_set_direction(measure, GPIO_MODE_DISABLE);
|
||||
gpio_set_pull_mode(measure, GPIO_FLOATING);
|
||||
// - Set "plus" to 1, "minus" to 0
|
||||
gpio_config(&(gpio_config_t) {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = (1ULL << plus) | (1ULL << minus)
|
||||
});
|
||||
gpio_set_level(plus, 1);
|
||||
gpio_set_level(minus, 0);
|
||||
}
|
||||
|
||||
static void setup_adc(gpio_num_t measure)
|
||||
{
|
||||
// Init ADC
|
||||
adc1_channel_t channel = gpio_to_adc[measure];
|
||||
adc_gpio_init(ADC_UNIT_1, channel);
|
||||
adc1_config_width(ADC_WIDTH_BIT_10);
|
||||
adc1_config_channel_atten(channel, ADC_ATTEN_DB_11);
|
||||
}
|
||||
|
||||
static void insert_sort(int16_t array[], uint8_t size) {
|
||||
uint8_t j;
|
||||
int16_t save;
|
||||
|
||||
for (int i = 1; i < size; i++) {
|
||||
save = array[i];
|
||||
for (j = i; j >= 1 && save < array[j - 1]; j--)
|
||||
array[j] = array[j - 1];
|
||||
array[j] = save;
|
||||
}
|
||||
}
|
||||
|
||||
static void ad_touch_handler(void *arg)
|
||||
{
|
||||
(void) arg;
|
||||
uint8_t i;
|
||||
int16_t samples[NUMSAMPLES];
|
||||
|
||||
switch (state) {
|
||||
case IDLE:
|
||||
adcX = 0;
|
||||
adcY = 0;
|
||||
|
||||
case SET_X :
|
||||
setup_axis(yd, yu, xr, xl);
|
||||
setup_adc(xr);
|
||||
state = READ_X;
|
||||
break;
|
||||
|
||||
case READ_X:
|
||||
for (i = 0; i < NUMSAMPLES; i++)
|
||||
samples[i] = adc1_get_raw(gpio_to_adc[xr]);
|
||||
insert_sort(samples, NUMSAMPLES);
|
||||
temp_x = samples[NUMSAMPLES / 2];
|
||||
|
||||
case SET_Y :
|
||||
setup_axis(xl, xr, yd, yu);
|
||||
setup_adc(yd);
|
||||
state = READ_Y;
|
||||
break;
|
||||
|
||||
case READ_Y:
|
||||
for (i = 0; i < NUMSAMPLES; i++)
|
||||
samples[i] = adc1_get_raw(gpio_to_adc[yd]);
|
||||
insert_sort(samples, NUMSAMPLES);
|
||||
temp_y = samples[NUMSAMPLES / 2];
|
||||
|
||||
case SET_Z1 :
|
||||
setup_axis(yu, xl, yd, xr);
|
||||
setup_adc(yd);
|
||||
state = READ_Z1;
|
||||
break;
|
||||
|
||||
case READ_Z1:
|
||||
temp_z1 = adc1_get_raw(gpio_to_adc[yd]);
|
||||
|
||||
case SET_Z2 :
|
||||
setup_axis(yu, xl, xr, yd);
|
||||
setup_adc(yd);
|
||||
state = READ_Z2;
|
||||
break;
|
||||
|
||||
case READ_Z2:
|
||||
temp_z2 = adc1_get_raw(gpio_to_adc[xr]);
|
||||
|
||||
if (temp_z1 < TOUCHSCREEN_RESISTIVE_PRESS_THRESHOLD) {
|
||||
#if CONFIG_LV_TOUCH_XY_SWAP
|
||||
adcX = temp_y;
|
||||
adcY = temp_x;
|
||||
#else
|
||||
adcX = temp_x;
|
||||
adcY = temp_y;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
adcX = -1;
|
||||
adcY = -1;
|
||||
}
|
||||
state = SET_X;
|
||||
//printf("x: %d y: %d z: %d\n", adcX, adcY, temp_z1 - temp_z2);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int16_t TouchGetRawX(void)
|
||||
{
|
||||
int16_t x = adcX;
|
||||
|
||||
#if CONFIG_LV_TOUCH_INVERT_X
|
||||
x = 1023 - x;
|
||||
#endif
|
||||
return x;
|
||||
}
|
||||
|
||||
static int16_t TouchGetX(void)
|
||||
{
|
||||
int16_t result = TouchGetRawX();
|
||||
|
||||
if (result > 0) {
|
||||
result = (int16_t)((((int32_t)_trC * result) + _trD) >> TOUCHSCREEN_RESISTIVE_CALIBRATION_SCALE_FACTOR);
|
||||
}
|
||||
printf("x: %d\n", result);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int16_t TouchGetRawY(void)
|
||||
{
|
||||
int16_t y = adcY;
|
||||
|
||||
#if CONFIG_LV_TOUCH_INVERT_Y
|
||||
y = 1023 - y;
|
||||
#endif
|
||||
return y;
|
||||
}
|
||||
|
||||
static int16_t TouchGetY(void)
|
||||
{
|
||||
int16_t result = TouchGetRawY();
|
||||
|
||||
if (result > 0) {
|
||||
result = (int16_t)((((int32_t)_trA * result) + (int32_t)_trB) >> TOUCHSCREEN_RESISTIVE_CALIBRATION_SCALE_FACTOR);
|
||||
}
|
||||
printf("y: %d\n", result);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current position and state of the touchpad
|
||||
* @param data store the read data here
|
||||
* @return false: because no more data to be read
|
||||
*/
|
||||
bool adcraw_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
|
||||
{
|
||||
static int16_t last_x = 0;
|
||||
static int16_t last_y = 0;
|
||||
|
||||
int16_t x, y;
|
||||
|
||||
x = TouchGetX();
|
||||
y = TouchGetY();
|
||||
|
||||
if ((x > 0) && (y > 0)) {
|
||||
data->point.x = x;
|
||||
data->point.y = y;
|
||||
last_x = data->point.x;
|
||||
last_y = data->point.y;
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
}
|
||||
else {
|
||||
data->point.x = last_x;
|
||||
data->point.y = last_y;
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif //CONFIG_LV_TOUCH_CONTROLLER_ADCRAW
|
79
lvgl_touch/adcraw.h
Normal file
79
lvgl_touch/adcraw.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* @file ADCRAW.h
|
||||
*/
|
||||
|
||||
#ifndef ADCRAW_H
|
||||
#define ADCRAW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/adc.h"
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
#define TOUCHSCREEN_RESISTIVE_PIN_YU CONFIG_LV_TOUCHSCREEN_RESSITIVE_PIN_YU // Y+ any gpio
|
||||
#define TOUCHSCREEN_RESISTIVE_PIN_YD CONFIG_LV_TOUCHSCREEN_RESISTIVE_PIN_YD // Y- also ADC
|
||||
#define TOUCHSCREEN_RESISTIVE_PIN_XL CONFIG_LV_TOUCHSCREEN_RESISTIVE_PIN_XL // X- any gpio
|
||||
#define TOUCHSCREEN_RESISTIVE_PIN_XR CONFIG_LV_TOUCHSCREEN_RESISTIVE_PIN_XR // X+ also ADC
|
||||
|
||||
// Default calibration points
|
||||
#define TOUCHCAL_ULX 29 // Upper Left X
|
||||
#define TOUCHCAL_ULY 84 // Upper Left Y
|
||||
#define TOUCHCAL_URX 828 // Upper Right X
|
||||
#define TOUCHCAL_URY 60 // Upper Right Y
|
||||
#define TOUCHCAL_LLX 29 // Lower Left X
|
||||
#define TOUCHCAL_LLY 928 // Lower Left Y
|
||||
#define TOUCHCAL_LRX 828 // Lower Right X
|
||||
#define TOUCHCAL_LRY 928 // Lower Right Y
|
||||
|
||||
#define TOUCHSCREEN_RESISTIVE_PRESS_THRESHOLD 1023
|
||||
|
||||
/*GetMaxX Macro*/
|
||||
#if CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
#define GetMaxX() (CONFIG_LV_DISPLAY_WIDTH - 1)
|
||||
#else
|
||||
#define GetMaxX() (CONFIG_LV_DISPLAY_HEIGHT - 1)
|
||||
#endif
|
||||
|
||||
/*GetMaxY Macro*/
|
||||
#if CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
|
||||
#define GetMaxY() (CONFIG_LV_DISPLAY_HEIGHT - 1)
|
||||
#else
|
||||
#define GetMaxY() (CONFIG_LV_DISPLAY_WIDTH - 1)
|
||||
#endif
|
||||
|
||||
#ifndef CONCAT3
|
||||
#define _CONCAT3(a,b,c) a ## b ## c
|
||||
#define CONCAT3(a,b,c) _CONCAT3(a,b,c)
|
||||
#endif
|
||||
|
||||
#define GPIO_TO_ADC_ELEMENT(x) [x] = CONCAT3(ADC1_GPIO, x, _CHANNEL)
|
||||
|
||||
typedef enum {
|
||||
IDLE,
|
||||
SET_X,
|
||||
SET_Y,
|
||||
SET_Z1,
|
||||
SET_Z2,
|
||||
READ_X,
|
||||
READ_Y,
|
||||
READ_Z1,
|
||||
READ_Z2
|
||||
} TOUCH_STATES;
|
||||
|
||||
void adcraw_init(void);
|
||||
bool adcraw_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* ADCRAW_H */
|
4
lvgl_touch/component.mk
Normal file
4
lvgl_touch/component.mk
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Touch drivers
|
||||
|
||||
COMPONENT_SRCDIRS := .
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
200
lvgl_touch/ft6x36.c
Normal file
200
lvgl_touch/ft6x36.c
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright © 2020 Wolfgang Christl
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the “Software”), to deal in the Software
|
||||
* without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
* to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <driver/i2c.h>
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include <lvgl.h>
|
||||
#else
|
||||
#include <lvgl/lvgl.h>
|
||||
#endif
|
||||
#include "ft6x36.h"
|
||||
#include "tp_i2c.h"
|
||||
|
||||
#define TAG "FT6X36"
|
||||
|
||||
|
||||
ft6x36_status_t ft6x36_status;
|
||||
uint8_t current_dev_addr; // set during init
|
||||
|
||||
esp_err_t ft6x06_i2c_read8(uint8_t slave_addr, uint8_t register_addr, uint8_t *data_buf) {
|
||||
i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
|
||||
|
||||
i2c_master_start(i2c_cmd);
|
||||
i2c_master_write_byte(i2c_cmd, (slave_addr << 1) | I2C_MASTER_WRITE, true);
|
||||
i2c_master_write_byte(i2c_cmd, register_addr, I2C_MASTER_ACK);
|
||||
|
||||
i2c_master_start(i2c_cmd);
|
||||
i2c_master_write_byte(i2c_cmd, (slave_addr << 1) | I2C_MASTER_READ, true);
|
||||
|
||||
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);
|
||||
i2c_cmd_link_delete(i2c_cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the FT6x36 gesture ID. Initialize first!
|
||||
* @param dev_addr: I2C FT6x36 Slave address.
|
||||
* @retval The gesture ID or 0x00 in case of failure
|
||||
*/
|
||||
uint8_t ft6x36_get_gesture_id() {
|
||||
if (!ft6x36_status.inited) {
|
||||
ESP_LOGE(TAG, "Init first!");
|
||||
return 0x00;
|
||||
}
|
||||
uint8_t data_buf;
|
||||
esp_err_t ret;
|
||||
if ((ret = ft6x06_i2c_read8(current_dev_addr, FT6X36_GEST_ID_REG, &data_buf) != ESP_OK))
|
||||
ESP_LOGE(TAG, "Error reading from device: %s", esp_err_to_name(ret));
|
||||
return data_buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize for FT6x36 communication via I2C
|
||||
* @param dev_addr: Device address on communication Bus (I2C slave address of FT6X36).
|
||||
* @retval None
|
||||
*/
|
||||
void ft6x06_init(uint16_t dev_addr) {
|
||||
if (!ft6x36_status.inited) {
|
||||
|
||||
/* I2C master is initialized before calling this function */
|
||||
#if 0
|
||||
esp_err_t code = i2c_master_init();
|
||||
#else
|
||||
esp_err_t code = ESP_OK;
|
||||
#endif
|
||||
|
||||
if (code != ESP_OK) {
|
||||
ft6x36_status.inited = false;
|
||||
ESP_LOGE(TAG, "Error during I2C init %s", esp_err_to_name(code));
|
||||
} else {
|
||||
ft6x36_status.inited = true;
|
||||
current_dev_addr = dev_addr;
|
||||
uint8_t data_buf;
|
||||
esp_err_t ret;
|
||||
ESP_LOGI(TAG, "Found touch panel controller");
|
||||
if ((ret = ft6x06_i2c_read8(dev_addr, FT6X36_PANEL_ID_REG, &data_buf) != ESP_OK))
|
||||
ESP_LOGE(TAG, "Error reading from device: %s",
|
||||
esp_err_to_name(ret)); // Only show error the first time
|
||||
ESP_LOGI(TAG, "\tDevice ID: 0x%02x", data_buf);
|
||||
|
||||
ft6x06_i2c_read8(dev_addr, FT6X36_CHIPSELECT_REG, &data_buf);
|
||||
ESP_LOGI(TAG, "\tChip ID: 0x%02x", data_buf);
|
||||
|
||||
ft6x06_i2c_read8(dev_addr, FT6X36_DEV_MODE_REG, &data_buf);
|
||||
ESP_LOGI(TAG, "\tDevice mode: 0x%02x", data_buf);
|
||||
|
||||
ft6x06_i2c_read8(dev_addr, FT6X36_FIRMWARE_ID_REG, &data_buf);
|
||||
ESP_LOGI(TAG, "\tFirmware ID: 0x%02x", data_buf);
|
||||
|
||||
ft6x06_i2c_read8(dev_addr, FT6X36_RELEASECODE_REG, &data_buf);
|
||||
ESP_LOGI(TAG, "\tRelease code: 0x%02x", data_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the touch screen X and Y positions values. Ignores multi touch
|
||||
* @param drv:
|
||||
* @param data: Store data here
|
||||
* @retval Always false
|
||||
*/
|
||||
bool ft6x36_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
|
||||
uint8_t data_xy[4]; // 2 bytes X | 2 bytes Y
|
||||
uint8_t touch_pnt_cnt; // Number of detected touch points
|
||||
static int16_t last_x = 0; // 12bit pixel value
|
||||
static int16_t last_y = 0; // 12bit pixel value
|
||||
|
||||
ft6x06_i2c_read8(current_dev_addr, FT6X36_TD_STAT_REG, &touch_pnt_cnt);
|
||||
if (touch_pnt_cnt != 1) { // ignore no touch & multi touch
|
||||
data->point.x = last_x;
|
||||
data->point.y = last_y;
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read X value
|
||||
i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
|
||||
|
||||
i2c_master_start(i2c_cmd);
|
||||
i2c_master_write_byte(i2c_cmd, (current_dev_addr << 1) | I2C_MASTER_WRITE, true);
|
||||
i2c_master_write_byte(i2c_cmd, FT6X36_P1_XH_REG, I2C_MASTER_ACK);
|
||||
|
||||
i2c_master_start(i2c_cmd);
|
||||
i2c_master_write_byte(i2c_cmd, (current_dev_addr << 1) | I2C_MASTER_READ, true);
|
||||
|
||||
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);
|
||||
i2c_cmd_link_delete(i2c_cmd);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error getting X coordinates: %s", esp_err_to_name(ret));
|
||||
data->point.x = last_x;
|
||||
data->point.y = last_y;
|
||||
data->state = LV_INDEV_STATE_REL; // no touch detected
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read Y value
|
||||
i2c_cmd = i2c_cmd_link_create();
|
||||
|
||||
i2c_master_start(i2c_cmd);
|
||||
i2c_master_write_byte(i2c_cmd, (current_dev_addr << 1) | I2C_MASTER_WRITE, true);
|
||||
i2c_master_write_byte(i2c_cmd, FT6X36_P1_YH_REG, I2C_MASTER_ACK);
|
||||
|
||||
i2c_master_start(i2c_cmd);
|
||||
i2c_master_write_byte(i2c_cmd, (current_dev_addr << 1) | I2C_MASTER_READ, true);
|
||||
|
||||
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);
|
||||
i2c_cmd_link_delete(i2c_cmd);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error getting Y coordinates: %s", esp_err_to_name(ret));
|
||||
data->point.x = last_x;
|
||||
data->point.y = last_y;
|
||||
data->state = LV_INDEV_STATE_REL; // no touch detected
|
||||
return false;
|
||||
}
|
||||
|
||||
last_x = ((data_xy[0] & FT6X36_MSB_MASK) << 8) | (data_xy[1] & FT6X36_LSB_MASK);
|
||||
last_y = ((data_xy[2] & FT6X36_MSB_MASK) << 8) | (data_xy[3] & FT6X36_LSB_MASK);
|
||||
|
||||
#if CONFIG_LV_FT6X36_SWAPXY
|
||||
int16_t swap_buf = last_x;
|
||||
last_x = last_y;
|
||||
last_y = swap_buf;
|
||||
#endif
|
||||
#if CONFIG_LV_FT6X36_INVERT_X
|
||||
last_x = LV_HOR_RES - last_x;
|
||||
#endif
|
||||
#if CONFIG_LV_FT6X36_INVERT_Y
|
||||
last_y = LV_VER_RES - last_y;
|
||||
#endif
|
||||
data->point.x = last_x;
|
||||
data->point.y = last_y;
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
ESP_LOGV(TAG, "X=%u Y=%u", data->point.x, data->point.y);
|
||||
return false;
|
||||
}
|
162
lvgl_touch/ft6x36.h
Normal file
162
lvgl_touch/ft6x36.h
Normal file
|
@ -0,0 +1,162 @@
|
|||
#ifndef __FT6X06_H
|
||||
/*
|
||||
* Copyright © 2020 Wolfgang Christl
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the “Software”), to deal in the Software
|
||||
* without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
* to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __FT6X06_H
|
||||
|
||||
#include <lvgl/src/lv_hal/lv_hal.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FT6236_I2C_SLAVE_ADDR 0x38
|
||||
|
||||
/* Maximum border values of the touchscreen pad that the chip can handle */
|
||||
#define FT6X36_MAX_WIDTH ((uint16_t)800)
|
||||
#define FT6X36_MAX_HEIGHT ((uint16_t)480)
|
||||
|
||||
/* Max detectable simultaneous touch points */
|
||||
#define FT6X36_MAX_TOUCH_PNTS 2
|
||||
|
||||
/* Register of the current mode */
|
||||
#define FT6X36_DEV_MODE_REG 0x00
|
||||
|
||||
/* Possible modes as of FT6X36_DEV_MODE_REG */
|
||||
#define FT6X36_DEV_MODE_WORKING 0x00
|
||||
#define FT6X36_DEV_MODE_FACTORY 0x04
|
||||
|
||||
#define FT6X36_DEV_MODE_MASK 0x70
|
||||
#define FT6X36_DEV_MODE_SHIFT 4
|
||||
|
||||
/* Gesture ID register */
|
||||
#define FT6X36_GEST_ID_REG 0x01
|
||||
|
||||
/* Possible values returned by FT6X36_GEST_ID_REG */
|
||||
#define FT6X36_GEST_ID_NO_GESTURE 0x00
|
||||
#define FT6X36_GEST_ID_MOVE_UP 0x10
|
||||
#define FT6X36_GEST_ID_MOVE_RIGHT 0x14
|
||||
#define FT6X36_GEST_ID_MOVE_DOWN 0x18
|
||||
#define FT6X36_GEST_ID_MOVE_LEFT 0x1C
|
||||
#define FT6X36_GEST_ID_ZOOM_IN 0x48
|
||||
#define FT6X36_GEST_ID_ZOOM_OUT 0x49
|
||||
|
||||
/* Status register: stores number of active touch points (0, 1, 2) */
|
||||
#define FT6X36_TD_STAT_REG 0x02
|
||||
#define FT6X36_TD_STAT_MASK 0x0F
|
||||
#define FT6X36_TD_STAT_SHIFT 0x00
|
||||
|
||||
/* Touch events */
|
||||
#define FT6X36_TOUCH_EVT_FLAG_PRESS_DOWN 0x00
|
||||
#define FT6X36_TOUCH_EVT_FLAG_LIFT_UP 0x01
|
||||
#define FT6X36_TOUCH_EVT_FLAG_CONTACT 0x02
|
||||
#define FT6X36_TOUCH_EVT_FLAG_NO_EVENT 0x03
|
||||
|
||||
#define FT6X36_TOUCH_EVT_FLAG_SHIFT 6
|
||||
#define FT6X36_TOUCH_EVT_FLAG_MASK (3 << FT6X36_TOUCH_EVT_FLAG_SHIFT)
|
||||
|
||||
#define FT6X36_MSB_MASK 0x0F
|
||||
#define FT6X36_MSB_SHIFT 0
|
||||
#define FT6X36_LSB_MASK 0xFF
|
||||
#define FT6X36_LSB_SHIFT 0
|
||||
|
||||
#define FT6X36_P1_XH_REG 0x03
|
||||
#define FT6X36_P1_XL_REG 0x04
|
||||
#define FT6X36_P1_YH_REG 0x05
|
||||
#define FT6X36_P1_YL_REG 0x06
|
||||
|
||||
#define FT6X36_P1_WEIGHT_REG 0x07 /* Register reporting touch pressure - read only */
|
||||
#define FT6X36_TOUCH_WEIGHT_MASK 0xFF
|
||||
#define FT6X36_TOUCH_WEIGHT_SHIFT 0
|
||||
|
||||
#define FT6X36_P1_MISC_REG 0x08 /* Touch area register */
|
||||
|
||||
#define FT6X36_TOUCH_AREA_MASK (0x04 << 4) /* Values related to FT6X36_Pn_MISC_REG */
|
||||
#define FT6X36_TOUCH_AREA_SHIFT 0x04
|
||||
|
||||
#define FT6X36_P2_XH_REG 0x09
|
||||
#define FT6X36_P2_XL_REG 0x0A
|
||||
#define FT6X36_P2_YH_REG 0x0B
|
||||
#define FT6X36_P2_YL_REG 0x0C
|
||||
#define FT6X36_P2_WEIGHT_REG 0x0D
|
||||
#define FT6X36_P2_MISC_REG 0x0E
|
||||
|
||||
/* Threshold for touch detection */
|
||||
#define FT6X36_TH_GROUP_REG 0x80
|
||||
#define FT6X36_THRESHOLD_MASK 0xFF /* Values FT6X36_TH_GROUP_REG : threshold related */
|
||||
#define FT6X36_THRESHOLD_SHIFT 0
|
||||
|
||||
#define FT6X36_TH_DIFF_REG 0x85 /* Filter function coefficients */
|
||||
|
||||
#define FT6X36_CTRL_REG 0x86 /* Control register */
|
||||
|
||||
#define FT6X36_CTRL_KEEP_ACTIVE_MODE 0x00 /* Will keep the Active mode when there is no touching */
|
||||
#define FT6X36_CTRL_KEEP_AUTO_SWITCH_MONITOR_MODE 0x01 /* Switching from Active mode to Monitor mode automatically when there is no touching */
|
||||
|
||||
#define FT6X36_TIME_ENTER_MONITOR_REG 0x87 /* The time period of switching from Active mode to Monitor mode when there is no touching */
|
||||
|
||||
#define FT6X36_PERIOD_ACTIVE_REG 0x88 /* Report rate in Active mode */
|
||||
#define FT6X36_PERIOD_MONITOR_REG 0x89 /* Report rate in Monitor mode */
|
||||
|
||||
#define FT6X36_RADIAN_VALUE_REG 0x91 /* The value of the minimum allowed angle while Rotating gesture mode */
|
||||
|
||||
#define FT6X36_OFFSET_LEFT_RIGHT_REG 0x92 /* Maximum offset while Moving Left and Moving Right gesture */
|
||||
#define FT6X36_OFFSET_UP_DOWN_REG 0x93 /* Maximum offset while Moving Up and Moving Down gesture */
|
||||
|
||||
#define FT6X36_DISTANCE_LEFT_RIGHT_REG 0x94 /* Minimum distance while Moving Left and Moving Right gesture */
|
||||
#define FT6X36_DISTANCE_UP_DOWN_REG 0x95 /* Minimum distance while Moving Up and Moving Down gesture */
|
||||
|
||||
#define FT6X36_LIB_VER_H_REG 0xA1 /* High 8-bit of LIB Version info */
|
||||
#define FT6X36_LIB_VER_L_REG 0xA2 /* Low 8-bit of LIB Version info */
|
||||
|
||||
#define FT6X36_CHIPSELECT_REG 0xA3 /* 0x36 for ft6236; 0x06 for ft6206 */
|
||||
|
||||
#define FT6X36_POWER_MODE_REG 0xA5
|
||||
#define FT6X36_FIRMWARE_ID_REG 0xA6
|
||||
#define FT6X36_RELEASECODE_REG 0xAF
|
||||
#define FT6X36_PANEL_ID_REG 0xA8
|
||||
#define FT6X36_OPMODE_REG 0xBC
|
||||
|
||||
|
||||
typedef struct {
|
||||
bool inited;
|
||||
} ft6x36_status_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize for FT6x36 communication via I2C
|
||||
* @param dev_addr: Device address on communication Bus (I2C slave address of FT6X36).
|
||||
* @retval None
|
||||
*/
|
||||
void ft6x06_init(uint16_t dev_addr);
|
||||
|
||||
uint8_t ft6x36_get_gesture_id();
|
||||
|
||||
/**
|
||||
* @brief Get the touch screen X and Y positions values. Ignores multi touch
|
||||
* @param drv:
|
||||
* @param data: Store data here
|
||||
* @retval Always false
|
||||
*/
|
||||
bool ft6x36_read(lv_indev_drv_t *drv, lv_indev_data_t *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __FT6X06_H */
|
181
lvgl_touch/ra8875_touch.c
Normal file
181
lvgl_touch/ra8875_touch.c
Normal file
|
@ -0,0 +1,181 @@
|
|||
/**
|
||||
* @file RA8875_TOUCH.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "ra8875_touch.h"
|
||||
|
||||
#include "../lvgl_tft/ra8875.h"
|
||||
|
||||
#ifndef CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875
|
||||
#error "Display controller must be RA8875"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define DEBUG false
|
||||
#define TAG "RA8875-Touch"
|
||||
|
||||
#define DIV_ROUND_UP(n, d) (((n)+(d)-1)/(d))
|
||||
|
||||
#define INTC2_TP_INT (0x04)
|
||||
|
||||
#define TPCR0_ADC_TIMING ((CONFIG_LV_TOUCH_RA8875_SAMPLE_TIME << 4) | CONFIG_LV_TOUCH_RA8875_ADC_CLOCK)
|
||||
#if LVGL_TOUCH_RA8875_WAKEUP_ENABLE
|
||||
#define TPCR0_VAL (0x08 | TPCR0_ADC_TIMING)
|
||||
#else
|
||||
#define TPCR0_VAL (TPCR0_ADC_TIMING)
|
||||
#endif
|
||||
|
||||
#if LVGL_TOUCH_RA8875_EXTERNAL_VREF
|
||||
#if LVGL_TOUCH_RA8875_DEBOUNCE_ENABLE
|
||||
#define TPCR1_VAL (0x24)
|
||||
#else
|
||||
#define TPCR1_VAL (0x20)
|
||||
#endif
|
||||
#else
|
||||
#if LVGL_TOUCH_RA8875_DEBOUNCE_ENABLE
|
||||
#define TPCR1_VAL (0x04)
|
||||
#else
|
||||
#define TPCR1_VAL (0x00)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void ra8875_corr(int * x, int * y);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void ra8875_touch_init(void)
|
||||
{
|
||||
struct {
|
||||
uint8_t cmd; // Register address of command
|
||||
uint8_t data; // Value to write to register
|
||||
} init_cmds[] = {
|
||||
{RA8875_REG_TPCR0, TPCR0_VAL}, // Touch Panel Control Register 0 (TPCR0)
|
||||
{RA8875_REG_TPCR1, TPCR1_VAL}, // Touch Panel Control Register 1 (TPCR1)
|
||||
};
|
||||
#define INIT_CMDS_SIZE (sizeof(init_cmds)/sizeof(init_cmds[0]))
|
||||
|
||||
ESP_LOGI(TAG, "Initializing RA8875 Touch...");
|
||||
|
||||
// Send all the commands
|
||||
for (unsigned int i = 0; i < INIT_CMDS_SIZE; i++) {
|
||||
ra8875_write_cmd(init_cmds[i].cmd, init_cmds[i].data);
|
||||
}
|
||||
ra8875_touch_enable(true);
|
||||
}
|
||||
|
||||
void ra8875_touch_enable(bool enable)
|
||||
{
|
||||
ESP_LOGI(TAG, "%s touch.", enable ? "Enabling" : "Disabling");
|
||||
uint8_t val = enable ? (0x80 | TPCR0_VAL) : (TPCR0_VAL);
|
||||
ra8875_write_cmd(RA8875_REG_TPCR0, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current position and state of the touchscreen
|
||||
* @param data store the read data here
|
||||
* @return false: because no more data to be read
|
||||
*/
|
||||
bool ra8875_touch_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
|
||||
{
|
||||
static int x = 0;
|
||||
static int y = 0;
|
||||
|
||||
int intr = ra8875_read_cmd(RA8875_REG_INTC2); // Interrupt Control Register2 (INTC2)
|
||||
|
||||
data->state = (intr & INTC2_TP_INT) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
|
||||
|
||||
if (data->state == LV_INDEV_STATE_PR) {
|
||||
x = ra8875_read_cmd(RA8875_REG_TPXH); // Touch Panel X High Byte Data Register (TPXH)
|
||||
y = ra8875_read_cmd(RA8875_REG_TPYH); // Touch Panel Y High Byte Data Register (TPYH)
|
||||
int xy = ra8875_read_cmd(RA8875_REG_TPXYL); // Touch Panel X/Y Low Byte Data Register (TPXYL)
|
||||
|
||||
x = (x << 2) | (xy & 0x03);
|
||||
y = (y << 2) | ((xy >> 2) & 0x03);
|
||||
|
||||
#if DEBUG
|
||||
ESP_LOGI(TAG, "Touch Poll Raw: %d,%d", x, y);
|
||||
#endif
|
||||
|
||||
// Convert to display coordinates
|
||||
ra8875_corr(&x, &y);
|
||||
|
||||
// Clear interrupt
|
||||
ra8875_write_cmd(RA8875_REG_INTC2, INTC2_TP_INT); // Interrupt Control Register2 (INTC2)
|
||||
}
|
||||
|
||||
data->point.x = x;
|
||||
data->point.y = y;
|
||||
|
||||
#if DEBUG
|
||||
ESP_LOGI(TAG, "Touch Poll - Event: %d; %d,%d", data->state, data->point.x, data->point.y);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void ra8875_corr(int * x, int * y)
|
||||
{
|
||||
#if RA8875_XY_SWAP != 0
|
||||
int tmp = *x;
|
||||
*x = *y;
|
||||
*y = tmp;
|
||||
#endif
|
||||
|
||||
if ((*x) <= RA8875_X_MIN) {
|
||||
(*x) = 0;
|
||||
} else if ((*x) >= RA8875_X_MAX) {
|
||||
(*x) = LV_HOR_RES-1;
|
||||
} else {
|
||||
(*x) = (((*x) - RA8875_X_MIN) * (LV_HOR_RES-1)) / (RA8875_X_MAX - RA8875_X_MIN);
|
||||
}
|
||||
|
||||
if ((*y) <= RA8875_Y_MIN) {
|
||||
(*y) = 0;
|
||||
} else if ((*y) >= RA8875_Y_MAX) {
|
||||
(*y) = LV_VER_RES-1;
|
||||
} else {
|
||||
(*y) = (((*y) - RA8875_Y_MIN) * (LV_VER_RES-1)) / (RA8875_Y_MAX - RA8875_Y_MIN);
|
||||
}
|
||||
|
||||
#if RA8875_X_INV != 0
|
||||
(*x) = (LV_HOR_RES-1) - (*x);
|
||||
#endif
|
||||
|
||||
#if RA8875_Y_INV != 0
|
||||
(*y) = (LV_VER_RES-1) - (*y);
|
||||
#endif
|
||||
}
|
56
lvgl_touch/ra8875_touch.h
Normal file
56
lvgl_touch/ra8875_touch.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* @file RA8875_TOUCH.h
|
||||
*/
|
||||
|
||||
#ifndef RA8875X_TOUCH__H
|
||||
#define RA8875X_TOUCH__H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define RA8875_X_MIN CONFIG_LV_TOUCH_X_MIN
|
||||
#define RA8875_Y_MIN CONFIG_LV_TOUCH_Y_MIN
|
||||
#define RA8875_X_MAX CONFIG_LV_TOUCH_X_MAX
|
||||
#define RA8875_Y_MAX CONFIG_LV_TOUCH_Y_MAX
|
||||
#define RA8875_X_INV CONFIG_LV_TOUCH_INVERT_X
|
||||
#define RA8875_Y_INV CONFIG_LV_TOUCH_INVERT_Y
|
||||
#define RA8875_XY_SWAP CONFIG_LV_TOUCH_XY_SWAP
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void ra8875_touch_init(void);
|
||||
void ra8875_touch_enable(bool enable);
|
||||
bool ra8875_touch_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* RA8875_TOUCH__H */
|
242
lvgl_touch/stmpe610.c
Normal file
242
lvgl_touch/stmpe610.c
Normal file
|
@ -0,0 +1,242 @@
|
|||
/**
|
||||
* @file STMPE610.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "stmpe610.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "tp_spi.h"
|
||||
#include <stddef.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "STMPE610"
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void write_8bit_reg(uint8_t reg, uint8_t val);
|
||||
static uint16_t read_16bit_reg(uint8_t reg);
|
||||
static uint8_t read_8bit_reg(uint8_t reg);
|
||||
static void read_data(int16_t *x, int16_t *y, uint8_t *z);
|
||||
static bool buffer_empty();
|
||||
static void adjust_data(int16_t * x, int16_t * y);
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the STMPE610
|
||||
*/
|
||||
void stmpe610_init(void)
|
||||
{
|
||||
uint8_t u8;
|
||||
uint16_t u16;
|
||||
|
||||
ESP_LOGI(TAG, "Initialization.");
|
||||
|
||||
// Get the initial SPI configuration
|
||||
//u8 = read_8bit_reg(STMPE_SPI_CFG);
|
||||
//ESP_LOGI(TAG, "SPI_CFG = 0x%x", u8);
|
||||
|
||||
// Attempt a software reset
|
||||
write_8bit_reg(STMPE_SYS_CTRL1, STMPE_SYS_CTRL1_RESET);
|
||||
vTaskDelay(10 / portTICK_RATE_MS);
|
||||
|
||||
// Reset the SPI configuration, making sure auto-increment is set
|
||||
u8 = read_8bit_reg(STMPE_SPI_CFG);
|
||||
write_8bit_reg(STMPE_SPI_CFG, u8 | STMPE_SPI_CFG_AA);
|
||||
u8 = read_8bit_reg(STMPE_SPI_CFG);
|
||||
ESP_LOGI(TAG, "SPI_CFG = 0x%x", u8);
|
||||
|
||||
// Verify SPI communication
|
||||
u16 = read_16bit_reg(STMPE_CHIP_ID);
|
||||
if (u16 != 0x811) {
|
||||
ESP_LOGE(TAG, "Incorrect version: 0x%x", u16);
|
||||
}
|
||||
|
||||
write_8bit_reg(STMPE_SYS_CTRL2, 0x00); // Disable clocks
|
||||
write_8bit_reg(STMPE_TSC_CTRL, 0); // Disable to allow writing
|
||||
|
||||
write_8bit_reg(STMPE_TSC_CTRL,
|
||||
STEMP_TSC_CTRL_TRACK_0 |
|
||||
STMPE_TSC_CTRL_XYZ |
|
||||
STMPE_TSC_CTRL_EN);
|
||||
|
||||
write_8bit_reg(STMPE_TSC_CFG, STMPE_TSC_CFG_4SAMPLE |
|
||||
STMPE_TSC_CFG_DELAY_1MS |
|
||||
STMPE_TSC_CFG_SETTLE_1MS);
|
||||
|
||||
write_8bit_reg(STMPE_TSC_FRACTION_Z, 0x7);
|
||||
write_8bit_reg(STMPE_TSC_I_DRIVE, STMPE_TSC_I_DRIVE_50MA);
|
||||
|
||||
write_8bit_reg(STMPE_SYS_CTRL2, 0x04); // GPIO clock off, TSC clock on, ADC clock on
|
||||
|
||||
write_8bit_reg(STMPE_ADC_CTRL1, STMPE_ADC_CTRL1_12BIT | STMPE_ADC_CTRL1_80CLK);
|
||||
write_8bit_reg(STMPE_ADC_CTRL2, STMPE_ADC_CTRL2_3_25MHZ);
|
||||
|
||||
write_8bit_reg(STMPE_GPIO_ALT_FUNCT, 0x00); // Disable GPIO
|
||||
|
||||
write_8bit_reg(STMPE_FIFO_TH, 1); // Set FIFO threshold
|
||||
write_8bit_reg(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET); // Assert FIFO reset
|
||||
write_8bit_reg(STMPE_FIFO_STA, 0); // Deassert FIFO reset
|
||||
|
||||
write_8bit_reg(STMPE_INT_EN, 0x00); // No interrupts
|
||||
write_8bit_reg(STMPE_INT_STA, 0xFF); // reset all ints
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current position and state of the touchpad
|
||||
* @param data store the read data here
|
||||
* @return false: because no more data to be read
|
||||
*/
|
||||
bool stmpe610_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;
|
||||
int c = 0;
|
||||
int16_t x = 0;
|
||||
int16_t y = 0;
|
||||
uint8_t z;
|
||||
|
||||
if ((read_8bit_reg(STMPE_TSC_CTRL) & STMPE_TSC_TOUCHED) == STMPE_TSC_TOUCHED) {
|
||||
// Making sure that we read all data and return the latest point
|
||||
while (!buffer_empty()) {
|
||||
read_data(&x, &y, &z);
|
||||
c++;
|
||||
}
|
||||
|
||||
if (c > 0) {
|
||||
//ESP_LOGI(TAG, "%d: %d %d %d", c, x, y, z);
|
||||
|
||||
adjust_data(&x, &y);
|
||||
last_x = x;
|
||||
last_y = y;
|
||||
//ESP_LOGI(TAG, " ==> %d %d", x, y);
|
||||
}
|
||||
|
||||
z = read_8bit_reg(STMPE_INT_STA); // Clear interrupts
|
||||
z = read_8bit_reg(STMPE_FIFO_STA);
|
||||
if ((z & STMPE_FIFO_STA_OFLOW) == STMPE_FIFO_STA_OFLOW) {
|
||||
// Clear the FIFO if we discover an overflow
|
||||
write_8bit_reg(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET);
|
||||
write_8bit_reg(STMPE_FIFO_STA, 0); // unreset
|
||||
ESP_LOGE(TAG, "Fifo overflow");
|
||||
}
|
||||
}
|
||||
|
||||
if (c == 0) {
|
||||
x = last_x;
|
||||
y = last_y;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
data->point.x = (int16_t) x;
|
||||
data->point.y = (int16_t) y;
|
||||
data->state = valid == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
static void write_8bit_reg(uint8_t reg, uint8_t val)
|
||||
{
|
||||
uint8_t data_send[2];
|
||||
|
||||
data_send[0] = reg;
|
||||
data_send[1] = val;
|
||||
tp_spi_write_reg(data_send, 2);
|
||||
}
|
||||
|
||||
|
||||
static uint16_t read_16bit_reg(uint8_t reg)
|
||||
{
|
||||
uint8_t data_recv[2];
|
||||
|
||||
tp_spi_read_reg(0x80 | reg, data_recv, 2);
|
||||
|
||||
return data_recv[0] << 8 | data_recv[1];
|
||||
}
|
||||
|
||||
|
||||
static uint8_t read_8bit_reg(uint8_t reg)
|
||||
{
|
||||
uint8_t data_recv;
|
||||
|
||||
tp_spi_read_reg(0x80 | reg, &data_recv, 1);
|
||||
|
||||
return data_recv;
|
||||
}
|
||||
|
||||
|
||||
static void read_data(int16_t *x, int16_t *y, uint8_t *z)
|
||||
{
|
||||
*x = read_16bit_reg(STMPE_TSC_DATA_X);
|
||||
*y = read_16bit_reg(STMPE_TSC_DATA_Y);
|
||||
*z = read_8bit_reg(STMPE_TSC_DATA_Z);
|
||||
}
|
||||
|
||||
|
||||
static bool buffer_empty()
|
||||
{
|
||||
return ((read_8bit_reg(STMPE_FIFO_STA) & STMPE_FIFO_STA_EMPTY) == STMPE_FIFO_STA_EMPTY);
|
||||
}
|
||||
|
||||
|
||||
static void adjust_data(int16_t * x, int16_t * y)
|
||||
{
|
||||
#if STMPE610_XY_SWAP != 0
|
||||
int16_t swap_tmp;
|
||||
swap_tmp = *x;
|
||||
*x = *y;
|
||||
*y = swap_tmp;
|
||||
#endif
|
||||
|
||||
if((*x) > STMPE610_X_MIN)(*x) -= STMPE610_X_MIN;
|
||||
else(*x) = 0;
|
||||
|
||||
if((*y) > STMPE610_Y_MIN)(*y) -= STMPE610_Y_MIN;
|
||||
else(*y) = 0;
|
||||
|
||||
(*x) = (uint32_t)((uint32_t)(*x) * LV_HOR_RES) /
|
||||
(STMPE610_X_MAX - STMPE610_X_MIN);
|
||||
|
||||
(*y) = (uint32_t)((uint32_t)(*y) * LV_VER_RES) /
|
||||
(STMPE610_Y_MAX - STMPE610_Y_MIN);
|
||||
|
||||
#if STMPE610_X_INV != 0
|
||||
(*x) = LV_HOR_RES - (*x);
|
||||
#endif
|
||||
|
||||
#if STMPE610_Y_INV != 0
|
||||
(*y) = LV_VER_RES - (*y);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
185
lvgl_touch/stmpe610.h
Normal file
185
lvgl_touch/stmpe610.h
Normal file
|
@ -0,0 +1,185 @@
|
|||
/**
|
||||
* @file STMPE610.h
|
||||
*/
|
||||
|
||||
#ifndef STMPE610_H
|
||||
#define STMPE610_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/** 16-bit Chip Version **/
|
||||
#define STMPE_CHIP_ID 0x00
|
||||
|
||||
/** Reset Control **/
|
||||
#define STMPE_SYS_CTRL1 0x03
|
||||
#define STMPE_SYS_CTRL1_RESET 0x02
|
||||
|
||||
/** Clock Contrl **/
|
||||
#define STMPE_SYS_CTRL2 0x04
|
||||
|
||||
/** SPI Config **/
|
||||
#define STMPE_SPI_CFG 0x08
|
||||
#define STMPE_SPI_CFG_MODE0 0x00
|
||||
#define STMPE_SPI_CFG_MODE1 0x01
|
||||
#define STMPE_SPI_CFG_MODE2 0x02
|
||||
#define STMPE_SPI_CFG_MODE3 0x03
|
||||
#define STMPE_SPI_CFG_AA 0x04
|
||||
|
||||
/** Touchscreen controller setup **/
|
||||
#define STMPE_TSC_CTRL 0x40
|
||||
#define STMPE_TSC_CTRL_EN 0x01
|
||||
#define STMPE_TSC_CTRL_XYZ 0x00
|
||||
#define STMPE_TSC_CTRL_XY 0x02
|
||||
#define STEMP_TSC_CTRL_TRACK_0 0x00
|
||||
#define STEMP_TSC_CTRL_TRACK_4 0x10
|
||||
#define STEMP_TSC_CTRL_TRACK_8 0x20
|
||||
#define STEMP_TSC_CTRL_TRACK_16 0x30
|
||||
#define STEMP_TSC_CTRL_TRACK_32 0x40
|
||||
#define STEMP_TSC_CTRL_TRACK_64 0x50
|
||||
#define STEMP_TSC_CTRL_TRACK_92 0x60
|
||||
#define STEMP_TSC_CTRL_TRACK_127 0x70
|
||||
#define STMPE_TSC_TOUCHED 0x80
|
||||
|
||||
/** Interrupt control **/
|
||||
#define STMPE_INT_CTRL 0x09
|
||||
#define STMPE_INT_CTRL_POL_HIGH 0x04
|
||||
#define STMPE_INT_CTRL_POL_LOW 0x00
|
||||
#define STMPE_INT_CTRL_EDGE 0x02
|
||||
#define STMPE_INT_CTRL_LEVEL 0x00
|
||||
#define STMPE_INT_CTRL_ENABLE 0x01
|
||||
#define STMPE_INT_CTRL_DISABLE 0x00
|
||||
|
||||
/** Interrupt enable **/
|
||||
#define STMPE_INT_EN 0x0A
|
||||
#define STMPE_INT_EN_TOUCHDET 0x01
|
||||
#define STMPE_INT_EN_FIFOTH 0x02
|
||||
#define STMPE_INT_EN_FIFOOF 0x04
|
||||
#define STMPE_INT_EN_FIFOFULL 0x08
|
||||
#define STMPE_INT_EN_FIFOEMPTY 0x10
|
||||
#define STMPE_INT_EN_ADC 0x40
|
||||
#define STMPE_INT_EN_GPIO 0x80
|
||||
|
||||
/** Interrupt status **/
|
||||
#define STMPE_INT_STA 0x0B
|
||||
#define STMPE_INT_STA_TOUCHDET 0x01
|
||||
|
||||
/** ADC control **/
|
||||
#define STMPE_ADC_CTRL1 0x20
|
||||
#define STMPE_ADC_CTRL1_INT 0x00
|
||||
#define STMPE_ADC_CTRL1_EXT 0x02
|
||||
#define STMPE_ADC_CTRL1_12BIT 0x08
|
||||
#define STMPE_ADC_CTRL1_10BIT 0x00
|
||||
#define STMPE_ADC_CTRL1_36CLK 0x00
|
||||
#define STMPE_ADC_CTRL1_44CLK 0x10
|
||||
#define STMPE_ADC_CTRL1_56CLK 0x20
|
||||
#define STMPE_ADC_CTRL1_64CLK 0x30
|
||||
#define STMPE_ADC_CTRL1_80CLK 0x40
|
||||
#define STMPE_ADC_CTRL1_96CLK 0x50
|
||||
#define STMPE_ADC_CTRL1_124CLK 0x60
|
||||
|
||||
/** ADC control **/
|
||||
#define STMPE_ADC_CTRL2 0x21
|
||||
#define STMPE_ADC_CTRL2_1_625MHZ 0x00
|
||||
#define STMPE_ADC_CTRL2_3_25MHZ 0x01
|
||||
#define STMPE_ADC_CTRL2_6_5MHZ 0x02
|
||||
|
||||
/** Touchscreen controller configuration **/
|
||||
#define STMPE_TSC_CFG 0x41
|
||||
#define STMPE_TSC_CFG_1SAMPLE 0x00
|
||||
#define STMPE_TSC_CFG_2SAMPLE 0x40
|
||||
#define STMPE_TSC_CFG_4SAMPLE 0x80
|
||||
#define STMPE_TSC_CFG_8SAMPLE 0xC0
|
||||
#define STMPE_TSC_CFG_DELAY_10US 0x00
|
||||
#define STMPE_TSC_CFG_DELAY_50US 0x08
|
||||
#define STMPE_TSC_CFG_DELAY_100US 0x10
|
||||
#define STMPE_TSC_CFG_DELAY_500US 0x18
|
||||
#define STMPE_TSC_CFG_DELAY_1MS 0x20
|
||||
#define STMPE_TSC_CFG_DELAY_5MS 0x28
|
||||
#define STMPE_TSC_CFG_DELAY_10MS 0x30
|
||||
#define STMPE_TSC_CFG_DELAY_50MS 0x38
|
||||
#define STMPE_TSC_CFG_SETTLE_10US 0x00
|
||||
#define STMPE_TSC_CFG_SETTLE_100US 0x01
|
||||
#define STMPE_TSC_CFG_SETTLE_500US 0x02
|
||||
#define STMPE_TSC_CFG_SETTLE_1MS 0x03
|
||||
#define STMPE_TSC_CFG_SETTLE_5MS 0x04
|
||||
#define STMPE_TSC_CFG_SETTLE_10MS 0x05
|
||||
#define STMPE_TSC_CFG_SETTLE_50MS 0x06
|
||||
#define STMPE_TSC_CFG_SETTLE_100MS 0x07
|
||||
|
||||
/** FIFO level to generate interrupt **/
|
||||
#define STMPE_FIFO_TH 0x4A
|
||||
|
||||
/** Current filled level of FIFO **/
|
||||
#define STMPE_FIFO_SIZE 0x4C
|
||||
|
||||
/** Current status of FIFO **/
|
||||
#define STMPE_FIFO_STA 0x4B
|
||||
#define STMPE_FIFO_STA_RESET 0x01
|
||||
#define STMPE_FIFO_STA_OFLOW 0x80
|
||||
#define STMPE_FIFO_STA_FULL 0x40
|
||||
#define STMPE_FIFO_STA_EMPTY 0x20
|
||||
#define STMPE_FIFO_STA_THTRIG 0x10
|
||||
|
||||
/** Touchscreen controller drive I **/
|
||||
#define STMPE_TSC_I_DRIVE 0x58
|
||||
#define STMPE_TSC_I_DRIVE_20MA 0x00
|
||||
#define STMPE_TSC_I_DRIVE_50MA 0x01
|
||||
|
||||
/** Data port for TSC data address **/
|
||||
#define STMPE_TSC_DATA_X 0x4D
|
||||
#define STMPE_TSC_DATA_Y 0x4F
|
||||
#define STMPE_TSC_DATA_Z 0x51
|
||||
#define STMPE_TSC_FRACTION_Z 0x56
|
||||
|
||||
/** GPIO **/
|
||||
#define STMPE_GPIO_SET_PIN 0x10
|
||||
#define STMPE_GPIO_CLR_PIN 0x11
|
||||
#define STMPE_GPIO_DIR 0x13
|
||||
#define STMPE_GPIO_ALT_FUNCT 0x17
|
||||
|
||||
|
||||
/** Calibration Constants **/
|
||||
#define STMPE610_X_MIN CONFIG_LV_TOUCH_X_MIN
|
||||
#define STMPE610_Y_MIN CONFIG_LV_TOUCH_Y_MIN
|
||||
#define STMPE610_X_MAX CONFIG_LV_TOUCH_X_MAX
|
||||
#define STMPE610_Y_MAX CONFIG_LV_TOUCH_Y_MAX
|
||||
#define STMPE610_XY_SWAP CONFIG_LV_TOUCH_XY_SWAP
|
||||
#define STMPE610_X_INV CONFIG_LV_TOUCH_INVERT_X
|
||||
#define STMPE610_Y_INV CONFIG_LV_TOUCH_INVERT_Y
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void stmpe610_init(void);
|
||||
bool stmpe610_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* STMPE610_H */
|
47
lvgl_touch/touch_driver.c
Normal file
47
lvgl_touch/touch_driver.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* @file touch_driver.c
|
||||
*/
|
||||
|
||||
#include "touch_driver.h"
|
||||
#include "tp_spi.h"
|
||||
#include "tp_i2c.h"
|
||||
|
||||
|
||||
void touch_driver_init(void)
|
||||
{
|
||||
#if defined (CONFIG_LV_TOUCH_CONTROLLER_XPT2046)
|
||||
xpt2046_init();
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT6X06)
|
||||
ft6x06_init(FT6236_I2C_SLAVE_ADDR);
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_STMPE610)
|
||||
stmpe610_init();
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_ADCRAW)
|
||||
adcraw_init();
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
|
||||
/* nothing to do */
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_RA8875)
|
||||
ra8875_touch_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
#if defined (CONFIG_LV_TOUCH_CONTROLLER_XPT2046)
|
||||
res = xpt2046_read(drv, data);
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT6X06)
|
||||
res = ft6x36_read(drv, data);
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_STMPE610)
|
||||
res = stmpe610_read(drv, data);
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_ADCRAW)
|
||||
res = adcraw_read(drv, data);
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
|
||||
res = FT81x_read(drv, data);
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_RA8875)
|
||||
res = ra8875_touch_read(drv, data);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
52
lvgl_touch/touch_driver.h
Normal file
52
lvgl_touch/touch_driver.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* @file touch_driver.h
|
||||
*/
|
||||
|
||||
#ifndef TOUCH_DRIVER_H
|
||||
#define TOUCH_DRIVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_LV_TOUCH_CONTROLLER_XPT2046)
|
||||
#include "xpt2046.h"
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT6X06)
|
||||
#include "ft6x36.h"
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_STMPE610)
|
||||
#include "stmpe610.h"
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_ADCRAW)
|
||||
#include "adcraw.h"
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
|
||||
#include "FT81x.h"
|
||||
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_RA8875)
|
||||
#include "ra8875_touch.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void touch_driver_init(void);
|
||||
bool touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* TOUCH_DRIVER_H */
|
||||
|
43
lvgl_touch/tp_i2c.c
Normal file
43
lvgl_touch/tp_i2c.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright © 2020 Wolfgang Christl
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the “Software”), to deal in the Software
|
||||
* without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
* to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <driver/i2c.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#define I2C_MASTER_FREQ_HZ 100000 /* 100kHz*/
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /* I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /* I2C master doesn't need buffer */
|
||||
|
||||
/**
|
||||
* @brief ESP32 I2C init as master
|
||||
* @ret ESP32 error code
|
||||
*/
|
||||
esp_err_t i2c_master_init(void) {
|
||||
int i2c_master_port = I2C_NUM_0;
|
||||
i2c_config_t conf;
|
||||
conf.mode = I2C_MODE_MASTER;
|
||||
conf.sda_io_num = CONFIG_LV_TOUCH_I2C_SDA;
|
||||
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
conf.scl_io_num = CONFIG_LV_TOUCH_I2C_SCL;
|
||||
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
|
||||
i2c_param_config(i2c_master_port, &conf);
|
||||
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
|
||||
}
|
36
lvgl_touch/tp_i2c.h
Normal file
36
lvgl_touch/tp_i2c.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright © 2020 Wolfgang Christl
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the “Software”), to deal in the Software
|
||||
* without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
* to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __TS_H
|
||||
#define __TS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
esp_err_t i2c_master_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TS_H */
|
109
lvgl_touch/tp_spi.c
Normal file
109
lvgl_touch/tp_spi.c
Normal file
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* @file tp_spi.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "tp_spi.h"
|
||||
#include "touch_driver.h"
|
||||
#include "esp_system.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "../lvgl_helpers.h"
|
||||
#include "../lvgl_spi_conf.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static spi_device_handle_t spi;
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
void tp_spi_add_device_config(spi_host_device_t host, spi_device_interface_config_t *devcfg)
|
||||
{
|
||||
esp_err_t ret=spi_bus_add_device(host, devcfg, &spi);
|
||||
assert(ret==ESP_OK);
|
||||
}
|
||||
|
||||
void tp_spi_add_device(spi_host_device_t host)
|
||||
{
|
||||
spi_device_interface_config_t devcfg={
|
||||
.clock_speed_hz = SPI_TOUCH_CLOCK_SPEED_HZ,
|
||||
.mode = SPI_TOUCH_SPI_MODE,
|
||||
.spics_io_num=TP_SPI_CS, //CS pin
|
||||
.queue_size=1,
|
||||
.pre_cb=NULL,
|
||||
.post_cb=NULL,
|
||||
.command_bits = 8,
|
||||
.address_bits = 0,
|
||||
.dummy_bits = 0,
|
||||
.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_NO_DUMMY,
|
||||
};
|
||||
|
||||
//Attach the Touch controller to the SPI bus
|
||||
tp_spi_add_device_config(host, &devcfg);
|
||||
}
|
||||
|
||||
void tp_spi_xchg(uint8_t* data_send, uint8_t* data_recv, uint8_t byte_count)
|
||||
{
|
||||
spi_transaction_t t = {
|
||||
.length = byte_count * 8, // SPI transaction length is in bits
|
||||
.tx_buffer = data_send,
|
||||
.rx_buffer = data_recv};
|
||||
|
||||
esp_err_t ret = spi_device_transmit(spi, &t);
|
||||
assert(ret == ESP_OK);
|
||||
}
|
||||
|
||||
void tp_spi_write_reg(uint8_t* data, uint8_t byte_count)
|
||||
{
|
||||
spi_transaction_t t = {
|
||||
.length = byte_count * 8,
|
||||
.tx_buffer = data,
|
||||
.flags = 0
|
||||
};
|
||||
|
||||
esp_err_t ret = spi_device_transmit(spi, &t);
|
||||
assert(ret == ESP_OK);
|
||||
}
|
||||
|
||||
void tp_spi_read_reg(uint8_t reg, uint8_t* data, uint8_t byte_count)
|
||||
{
|
||||
spi_transaction_t t = {
|
||||
.length = (byte_count + sizeof(reg)) * 8,
|
||||
.rxlength = byte_count * 8,
|
||||
.cmd = reg,
|
||||
.rx_buffer = data,
|
||||
.flags = 0
|
||||
};
|
||||
|
||||
// Read - send first byte as command
|
||||
esp_err_t ret = spi_device_transmit(spi, &t);
|
||||
assert(ret == ESP_OK);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
45
lvgl_touch/tp_spi.h
Normal file
45
lvgl_touch/tp_spi.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* @file tp_spi.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TP_SPI_H
|
||||
#define TP_SPI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
#include <driver/spi_master.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void tp_spi_add_device(spi_host_device_t host);
|
||||
void tp_spi_add_device_config(spi_host_device_t host, spi_device_interface_config_t *config);
|
||||
void tp_spi_xchg(uint8_t* data_send, uint8_t* data_recv, uint8_t byte_count);
|
||||
void tp_spi_write_reg(uint8_t* data, uint8_t byte_count);
|
||||
void tp_spi_read_reg(uint8_t reg, uint8_t* data, uint8_t byte_count);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*TP_SPI_H*/
|
180
lvgl_touch/xpt2046.c
Normal file
180
lvgl_touch/xpt2046.c
Normal file
|
@ -0,0 +1,180 @@
|
|||
/**
|
||||
* @file XPT2046.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "xpt2046.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "tp_spi.h"
|
||||
#include <stddef.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TAG "XPT2046"
|
||||
|
||||
#define CMD_X_READ 0b10010000
|
||||
#define CMD_Y_READ 0b11010000
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void xpt2046_corr(int16_t * x, int16_t * y);
|
||||
static void xpt2046_avg(int16_t * x, int16_t * y);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
int16_t avg_buf_x[XPT2046_AVG];
|
||||
int16_t avg_buf_y[XPT2046_AVG];
|
||||
uint8_t avg_last;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the XPT2046
|
||||
*/
|
||||
void xpt2046_init(void)
|
||||
{
|
||||
gpio_config_t irq_config = {
|
||||
.pin_bit_mask = BIT64(XPT2046_IRQ),
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "XPT2046 Initialization");
|
||||
|
||||
esp_err_t ret = gpio_config(&irq_config);
|
||||
assert(ret == ESP_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current position and state of the touchpad
|
||||
* @param data store the read data here
|
||||
* @return false: because no more data to be read
|
||||
*/
|
||||
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;
|
||||
|
||||
int16_t x = 0;
|
||||
int16_t y = 0;
|
||||
|
||||
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];
|
||||
ESP_LOGI(TAG, "P(%d,%d)", x, y);
|
||||
|
||||
/*Normalize Data back to 12-bits*/
|
||||
x = x >> 4;
|
||||
y = y >> 4;
|
||||
ESP_LOGI(TAG, "P_norm(%d,%d)", x, y);
|
||||
|
||||
xpt2046_corr(&x, &y);
|
||||
xpt2046_avg(&x, &y);
|
||||
last_x = x;
|
||||
last_y = y;
|
||||
|
||||
ESP_LOGI(TAG, "x = %d, y = %d", x, y);
|
||||
} else {
|
||||
x = last_x;
|
||||
y = last_y;
|
||||
avg_last = 0;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
data->point.x = x;
|
||||
data->point.y = y;
|
||||
data->state = valid == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
static void xpt2046_corr(int16_t * x, int16_t * y)
|
||||
{
|
||||
#if XPT2046_XY_SWAP != 0
|
||||
int16_t swap_tmp;
|
||||
swap_tmp = *x;
|
||||
*x = *y;
|
||||
*y = swap_tmp;
|
||||
#endif
|
||||
|
||||
if((*x) > XPT2046_X_MIN)(*x) -= XPT2046_X_MIN;
|
||||
else(*x) = 0;
|
||||
|
||||
if((*y) > XPT2046_Y_MIN)(*y) -= XPT2046_Y_MIN;
|
||||
else(*y) = 0;
|
||||
|
||||
(*x) = (uint32_t)((uint32_t)(*x) * LV_HOR_RES) /
|
||||
(XPT2046_X_MAX - XPT2046_X_MIN);
|
||||
|
||||
(*y) = (uint32_t)((uint32_t)(*y) * LV_VER_RES) /
|
||||
(XPT2046_Y_MAX - XPT2046_Y_MIN);
|
||||
|
||||
#if XPT2046_X_INV != 0
|
||||
(*x) = LV_HOR_RES - (*x);
|
||||
#endif
|
||||
|
||||
#if XPT2046_Y_INV != 0
|
||||
(*y) = LV_VER_RES - (*y);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void xpt2046_avg(int16_t * x, int16_t * y)
|
||||
{
|
||||
/*Shift out the oldest data*/
|
||||
uint8_t i;
|
||||
for(i = XPT2046_AVG - 1; i > 0 ; i--) {
|
||||
avg_buf_x[i] = avg_buf_x[i - 1];
|
||||
avg_buf_y[i] = avg_buf_y[i - 1];
|
||||
}
|
||||
|
||||
/*Insert the new point*/
|
||||
avg_buf_x[0] = *x;
|
||||
avg_buf_y[0] = *y;
|
||||
if(avg_last < XPT2046_AVG) avg_last++;
|
||||
|
||||
/*Sum the x and y coordinates*/
|
||||
int32_t x_sum = 0;
|
||||
int32_t y_sum = 0;
|
||||
for(i = 0; i < avg_last ; i++) {
|
||||
x_sum += avg_buf_x[i];
|
||||
y_sum += avg_buf_y[i];
|
||||
}
|
||||
|
||||
/*Normalize the sums*/
|
||||
(*x) = (int32_t)x_sum / avg_last;
|
||||
(*y) = (int32_t)y_sum / avg_last;
|
||||
}
|
57
lvgl_touch/xpt2046.h
Normal file
57
lvgl_touch/xpt2046.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* @file XPT2046.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XPT2046_H
|
||||
#define XPT2046_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define XPT2046_IRQ CONFIG_LV_TOUCH_PIN_IRQ
|
||||
|
||||
#define XPT2046_AVG 4
|
||||
#define XPT2046_X_MIN CONFIG_LV_TOUCH_X_MIN
|
||||
#define XPT2046_Y_MIN CONFIG_LV_TOUCH_Y_MIN
|
||||
#define XPT2046_X_MAX CONFIG_LV_TOUCH_X_MAX
|
||||
#define XPT2046_Y_MAX CONFIG_LV_TOUCH_Y_MAX
|
||||
#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
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void xpt2046_init(void);
|
||||
bool xpt2046_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* XPT2046_H */
|
Loading…
Reference in a new issue