Compare commits

..

10 commits

Author SHA1 Message Date
Andreas Mieke 341b522b7b fix(lcd-backlight): Update to ESP IDF v5 2023-12-30 05:15:27 +01:00
Andreas Mieke 8592cb9d29 Add Schmitt SPI display driver 2023-12-30 03:47:03 +01:00
arktrin 26fe6e7703 clarify the 52/53 px offset oddity 2021-12-23 14:54:28 -06:00
arktrin c4cd524487 add offset for 240x135 displays based on ST7789 2021-12-23 14:54:28 -06:00
arktrin 8d1fbcf5c4 replace hardcoded SPI DMA parameter 2021-12-21 16:57:51 -06:00
arktrin 8cbbc299e9 fix SPI names for touch
with ESP32-C3 specific auto-dma proper selection
2021-12-21 16:57:51 -06:00
Tomas Rezucha 762bb35265
Merge pull request #152 from lvgl/revert-151-fix/spi-names
Revert "fix spi names"
2021-12-17 19:18:36 +01:00
Tomas Rezucha d44b7e808a
Revert "fix spi names" 2021-12-17 19:18:05 +01:00
Tomas Rezucha 02d351f898
Merge pull request #151 from lvgl/fix/spi-names
fix spi names
2021-12-16 15:46:10 +01:00
Tomas Rezucha 22ba4161b5 fix spi names 2021-12-16 15:45:23 +01:00
59 changed files with 1413 additions and 2040 deletions

View file

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

5
.gitignore vendored
View file

@ -59,7 +59,4 @@ build
# Kconfig files
sdkconfig
sdkconfig.old
# pre-commit configuration file
.pre-commit-config.yaml
sdkconfig.old

3
.gitmodules vendored
View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,161 +0,0 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "display_port.h"
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "disp_spi.h"
#include "lvgl_i2c/i2c_manager.h"
#include <stdbool.h>
#include <assert.h>
/* NOTE: Needed by the I2C Manager */
#define OLED_I2C_PORT (CONFIG_LV_I2C_DISPLAY_PORT)
/* FIXME: Be able to get display driver I2C address from Kconfig */
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306)
#define OLED_I2C_ADDRESS 0x3C
#else
#define OLED_I2C_ADDRESS 0x00
#endif
// Control byte
#define OLED_CONTROL_BYTE_CMD_SINGLE 0x80
#define OLED_CONTROL_BYTE_CMD_STREAM 0x00
#define OLED_CONTROL_BYTE_DATA_STREAM 0x40
#define LV_DISPLAY_DC_CMD_MODE 0
#define LV_DISPLAY_DC_DATA_MODE 1
/* Helper functions to get display communication interface kind, this can be
* implemented as users see fit, we're using the symbols created by Kconfig
* because is what we have available.
* Other ways to implement it is using the user_data poiter in lv_disp_drv_t */
static inline bool display_interface_is_spi(lv_disp_drv_t * drv);
static inline bool display_interface_is_i2c(lv_disp_drv_t * drv);
void display_port_delay(lv_disp_drv_t *drv, uint32_t delay_ms)
{
(void) drv;
vTaskDelay(pdMS_TO_TICKS(delay_ms));
}
void display_port_backlight(lv_disp_drv_t *drv, uint8_t state)
{
(void) drv;
#ifdef CONFIG_LV_DISP_PIN_BCKL
gpio_set_level(CONFIG_LV_DISP_PIN_BCKL, state);
#endif
}
void display_port_gpio_dc(lv_disp_drv_t *drv, uint8_t state)
{
(void) drv;
#ifdef CONFIG_LV_DISPLAY_USE_DC
gpio_set_level(CONFIG_LV_DISP_PIN_DC, state);
#endif
}
void display_port_gpio_rst(lv_disp_drv_t *drv, uint8_t state)
{
(void) drv;
#ifdef CONFIG_LV_DISP_USE_RST
gpio_set_level(CONFIG_LV_DISP_PIN_RST, state);
#endif
}
bool display_port_gpio_is_busy(lv_disp_drv_t *drv)
{
(void) drv;
bool device_busy = false;
#ifdef CONFIG_LV_DISP_PIN_BUSY
/* FIXME Assuming the busy signal in logic 1 means the device is busy */
if (gpio_get_level(CONFIG_LV_DISP_PIN_BUSY) == 1) {
device_busy = true;
}
#endif
return device_busy;
}
void display_interface_send_cmd(lv_disp_drv_t *drv, uint32_t cmd, cmd_width_t cmd_width, void *args, size_t args_len)
{
(void) drv;
if (display_interface_is_spi(drv)) {
disp_wait_for_pending_transactions();
display_port_gpio_dc(drv, LV_DISPLAY_DC_CMD_MODE);
if (CMD_WIDTH_8BITS == cmd_width) {
uint8_t cmd_8bits = (uint8_t) cmd & 0xFFU;
disp_spi_send_data(&cmd_8bits, 1);
}
else if (CMD_WIDTH_16BITS == cmd_width) {
/* Send 16bits cmd */
}
else {
/* Invalid cmd size */
assert(0);
}
if (args != CMD_WITHOUT_ARGS) {
display_port_gpio_dc(drv, LV_DISPLAY_DC_DATA_MODE);
disp_spi_send_data(args, args_len);
}
}
if (display_interface_is_i2c(drv)) {
uint8_t *data = (uint8_t *) args;
lvgl_i2c_write(OLED_I2C_PORT, OLED_I2C_ADDRESS, cmd, data, args_len);
}
}
void display_interface_send_data(lv_disp_drv_t *drv, void *data, size_t len)
{
(void) drv;
if (display_interface_is_spi(drv)) {
disp_wait_for_pending_transactions();
display_port_gpio_dc(drv, LV_DISPLAY_DC_DATA_MODE);
disp_spi_send_colors(data, len);
/* lv_disp_flush_ready is called in the SPI xfer done callback */
}
if (display_interface_is_i2c(drv)) {
lvgl_i2c_write(OLED_I2C_PORT, OLED_I2C_ADDRESS, OLED_CONTROL_BYTE_DATA_STREAM, data, len);
}
}
static inline bool display_interface_is_spi(lv_disp_drv_t * drv)
{
(void) drv;
bool retval = false;
#if defined (CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI)
retval = true;
#endif
return retval;
}
static inline bool display_interface_is_i2c(lv_disp_drv_t * drv)
{
(void) drv;
bool retval = false;
#if defined (CONFIG_LV_TFT_DISPLAY_PROTOCOL_I2C)
retval = true;
#endif
return retval;
}

View file

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

View file

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

View file

@ -6,8 +6,6 @@
#ifndef LVGL_SPI_CONF_H
#define LVGL_SPI_CONF_H
#include <sdkconfig.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -20,32 +18,25 @@ extern "C" {
* DEFINES
*********************/
// DISPLAY PINS
/* Mandatory pins are MOSI and CLK */
#define DISP_SPI_MOSI CONFIG_LV_DISP_SPI_MOSI
#define DISP_SPI_CLK CONFIG_LV_DISP_SPI_CLK
/* Optional pins */
#if defined (CONFIG_LV_DISPLAY_USE_SPI_MISO)
#define DISP_SPI_MISO CONFIG_LV_DISP_SPI_MISO
#define DISP_SPI_INPUT_DELAY_NS CONFIG_LV_DISP_SPI_INPUT_DELAY_NS
#define DISP_SPI_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 (0U)
#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
@ -59,38 +50,24 @@ extern "C" {
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) && \
defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
#define SHARED_SPI_BUS
#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
#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
#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_PROTOCOL_SPI)
/* Display controller SPI host configuration */
#if defined (CONFIG_LV_TFT_DISPLAY_SPI2_HOST)
#define TFT_SPI_HOST SPI2_HOST
#elif defined (CONFIG_LV_TFT_DISPLAY_SPI3_HOST)
#define TFT_SPI_HOST SPI3_HOST
#else
#error SPI host not defined
#endif
#endif
/* Touch controller SPI host configuration */
#if defined (CONFIG_LV_TOUCH_CONTROLLER_SPI2_HOST)
#define TOUCH_SPI_HOST SPI2_HOST
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_SPI3_HOST)
#define TOUCH_SPI_HOST SPI3_HOST
#endif
#if defined (CONFIG_LV_TFT_DISPLAY_SPI_HALF_DUPLEX)
@ -107,30 +84,61 @@ extern "C" {
#define DISP_SPI_TRANS_MODE_SIO
#endif
/* Detect usage of shared SPI bus between display and indev controllers
*
* If the user sets the same MOSI and CLK pins for both display and indev
* controllers then we can assume the user is using the same SPI bus
* If so verify the user specified the same SPI bus for both */
#if !defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
#if defined (CONFIG_LV_TOUCH_CONTROLLER_SPI2_HOST)
#define TOUCH_SPI_HOST SPI2_HOST
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_SPI3_HOST)
#define TOUCH_SPI_HOST SPI3_HOST
#endif
#if defined (CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI) && \
(CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI == 1) && \
defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI) && \
(TP_SPI_MOSI == DISP_SPI_MOSI) && (TP_SPI_CLK == DISP_SPI_CLK)
/* 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 (SPIx_HOST) for both display and touch driver
#else
#endif
#define SHARED_SPI_BUS
#endif
#endif
#endif
/**********************
* TYPEDEFS
**********************/
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_SCHMITT)
#define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 4)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488)
#define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 3)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C)
#define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 2)
#else
#define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 2)
#endif
#if defined (CONFIG_LV_TFT_USE_CUSTOM_SPI_CLK_DIVIDER)
#define SPI_TFT_CLOCK_SPEED_HZ ((80 * 1000 * 1000) / CONFIG_LV_TFT_CUSTOM_SPI_CLK_DIVIDER)
#else
@ -151,30 +159,31 @@ extern "C" {
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341)
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
#elif defined(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C)
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
#define SPI_TFT_CLOCK_SPEED_HZ (40 * 1000 * 1000)
#elif defined(CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
#define SPI_TFT_CLOCK_SPEED_HZ (32*1000*1000)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544)
#define SPI_TFT_CLOCK_SPEED_HZ (4*1000*1000)
#else
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
#define SPI_TFT_CLOCK_SPEED_HZ (5*1000*1000) // Set to 40 later
#endif
#endif
#endif /* CONFIG_LV_TFT_USE_CUSTOM_SPI_CLK_DIVIDER */
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789)
#define SPI_TFT_SPI_MODE (2U)
#define SPI_TFT_SPI_MODE (2)
#else
#define SPI_TFT_SPI_MODE (0U)
#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 (1U)
#define SPI_TOUCH_SPI_MODE (1)
#else
#define SPI_TOUCH_CLOCK_SPEED_HZ (2*1000*1000)
#define SPI_TOUCH_SPI_MODE (0U)
#define SPI_TOUCH_SPI_MODE (0)
#endif
/**********************

View file

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

View file

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

View file

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

View file

@ -178,6 +178,10 @@ menu "LVGL TFT Display controller"
bool
help
PCD8544 display controller (Nokia 3110/5110)
config LV_TFT_DISPLAY_CONTROLLER_SCHMITT
bool
help
Schmitt's display controller
# Display controller communication protocol
#
# This symbols define the communication protocol used by the
@ -226,15 +230,15 @@ menu "LVGL TFT Display controller"
config LV_TFT_DISPLAY_X_OFFSET
depends on LV_TFT_DISPLAY_OFFSETS
int "X offset"
default 40 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_LANDSCAPE || DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
default 53 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_PORTRAIT || DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
default 40 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
default 53 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
default 0
config LV_TFT_DISPLAY_Y_OFFSET
depends on LV_TFT_DISPLAY_OFFSETS
int "Y offset"
default 53 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_LANDSCAPE || DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
default 40 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_PORTRAIT || DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
default 53 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
default 40 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
default 0
@ -349,6 +353,10 @@ menu "LVGL TFT Display controller"
select LV_TFT_DISPLAY_CONTROLLER_PCD8544
select LV_TFT_DISPLAY_PROTOCOL_SPI
select LV_TFT_DISPLAY_MONOCHROME
config LV_TFT_DISPLAY_USER_CONTROLLER_SCHMITT
bool "SCHMITT"
select LV_TFT_DISPLAY_CONTROLLER_SCHMITT
select LV_TFT_DISPLAY_PROTOCOL_SPI
endchoice
config CUSTOM_DISPLAY_BUFFER_SIZE
@ -469,15 +477,14 @@ menu "LVGL TFT Display controller"
choice
prompt "TFT SPI Bus." if LV_TFT_DISPLAY_PROTOCOL_SPI
default LV_TFT_DISPLAY_SPI2_HOST if LV_PREDEFINED_DISPLAY_TTGO
default LV_TFT_DISPLAY_SPI3_HOST if !LV_PREDEFINED_DISPLAY_TTGO
default LV_TFT_DISPLAY_SPI2_HOST
help
Select the SPI Bus the TFT Display is attached to.
config LV_TFT_DISPLAY_SPI2_HOST
bool "SPI2_HOST"
config LV_TFT_DISPLAY_SPI3_HOST
bool "SPI3_HOST" if !IDF_TARGET_ESP32C3
help
Select the SPI Bus the TFT Display is attached to.
bool "SPI3_HOST"
endchoice
choice
@ -907,13 +914,6 @@ menu "LVGL TFT Display controller"
help
Configure the display Reset pin here.
config LV_DISP_USE_BUSY
bool "Use a GPIO for busy signal" if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D
default y if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D
default n
help
Use a GPIO for busy signal available in e-ink display controllers.
config LV_DISP_PIN_BUSY
int "GPIO for Busy" if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D
default 35 if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D

View file

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

View file

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

View file

@ -1,95 +0,0 @@
#ifndef DISPLAY_PORT_H_
#define DISPLAY_PORT_H_
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#include <stdint.h>
#include <stdbool.h>
#define CMD_WITHOUT_ARGS NULL
enum {
CMD_WIDTH_8BITS,
CMD_WIDTH_16BITS,
CMD_WIDTH_INVALID,
};
typedef uint8_t cmd_width_t;
/**
* Busy wait delay port
*
* @param drv Pointer to driver See @ref lv_disp_drv_t
* @param delay_ms Delay duration in milliseconds
*/
void display_port_delay(lv_disp_drv_t *drv, uint32_t delay_ms);
/**
* Backlight control port
*
* @param drv Pointer to driver See @ref lv_disp_drv_t
* @param state State of the backlight signal
*/
void display_port_backlight(lv_disp_drv_t *drv, uint8_t state);
/**
* DC signal control port
*
* @param drv Pointer to driver See @ref lv_disp_drv_t
* @param state State of the DC signal, 1 for logic high, 0 for logic low
*/
void display_port_gpio_dc(lv_disp_drv_t *drv, uint8_t state);
/**
* Hardware reset control port
*
* @param drv Pointer to driver See @ref lv_disp_drv_t
* @param state State of the reset signal, 1 for logic high, 0 for logic low
*/
void display_port_gpio_rst(lv_disp_drv_t *drv, uint8_t state);
/**
* Display is busy port
*
* @param drv Pointer to driver See @ref lv_disp_drv_t
*
* @retval Returns false when display is not busy, true otherwise.
*/
bool display_port_gpio_is_busy(lv_disp_drv_t *drv);
/**
* Send cmd to display
*
* @param drv Pointer to driver
* @param cmd Command to send
* @param cmd_width Width of the command (in bits) to be sent, see @ref cmd_width_t
* @param args Pointer to arguments, use CMD_WITHOUT_ARGS to send command without arguments
* @param args_len Arguments length (in bytes) to be sent
*/
void display_interface_send_cmd(lv_disp_drv_t *drv, uint32_t cmd, cmd_width_t cmd_width, void *args, size_t args_len);
/**
* Send (image) data to display
*
* User must call lv_disp_flush after the image is sent
*
* @param drv Pointer to driver
* @param data Pointer to data to be sent
* @param len Data length (in bytes) to be sent
*/
void display_interface_send_data(lv_disp_drv_t *drv, void *data, size_t len);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View file

@ -8,10 +8,12 @@
*********************/
#include "esp_lcd_backlight.h"
#include "driver/ledc.h"
#include "driver/gpio.h"
#include "rom/gpio.h"
#include "esp_log.h"
#include "soc/ledc_periph.h" // to invert LEDC output on IDF version < v4.3
#define SIG_GPIO_OUT_IDX 128
typedef struct {
bool pwm_control; // true: LEDC is used, false: GPIO is used
int index; // Either GPIO or LEDC channel
@ -49,7 +51,7 @@ disp_backlight_h disp_backlight_new(const disp_backlight_config_t *config)
};
const ledc_timer_config_t LCD_backlight_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.bit_num = LEDC_TIMER_10_BIT,
.duty_resolution = LEDC_TIMER_10_BIT,
.timer_num = config->timer_idx,
.freq_hz = 5000,
.clk_cfg = LEDC_AUTO_CLK};

View file

@ -18,12 +18,15 @@
#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
@ -49,7 +52,7 @@ typedef struct {
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);
static void hx8357_reset(void);
/**********************
* INITIALIZATION ARRAYS
@ -156,31 +159,44 @@ static uint8_t displayType = HX8357D;
void hx8357_init(void)
{
hx8357_reset();
//Initialize non-SPI GPIOs
gpio_pad_select_gpio(HX8357_DC);
gpio_set_direction(HX8357_DC, GPIO_MODE_OUTPUT);
LV_LOG_INFO("Initialization.");
#if HX8357_USE_RST
gpio_pad_select_gpio(HX8357_RST);
gpio_set_direction(HX8357_RST, GPIO_MODE_OUTPUT);
//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)
}
}
//Reset the display
gpio_set_level(HX8357_RST, 0);
vTaskDelay(10 / portTICK_RATE_MS);
gpio_set_level(HX8357_RST, 1);
vTaskDelay(120 / portTICK_RATE_MS);
#endif
hx8357_set_rotation(1);
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_COLORS
hx8357_send_cmd(HX8357_INVON);
@ -273,13 +289,3 @@ static void hx8357_send_color(void * data, uint16_t length)
gpio_set_level(HX8357_DC, 1); /*Data mode*/
disp_spi_send_colors(data, length);
}
static void hx8357_reset(void)
{
#if HX8357_USE_RST
gpio_set_level(HX8357_RST, 0);
vTaskDelay(10 / portTICK_RATE_MS);
gpio_set_level(HX8357_RST, 1);
vTaskDelay(120 / portTICK_RATE_MS);
#endif
}

View file

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

View file

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

View file

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

View file

@ -7,24 +7,22 @@
* INCLUDES
*********************/
#include "ili9341.h"
#include "disp_spi.h"
#include "display_port.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
/*********************
* DEFINES
*********************/
#define END_OF_CMD_MARKER 0xFFU
#define MEMORY_ACCESS_CONTROL_REG 0x36U
#define SOFTWARE_RESET_REG 0x01U
#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];
@ -34,13 +32,12 @@ typedef struct {
/**********************
* STATIC PROTOTYPES
**********************/
static void ili9341_set_orientation(lv_disp_drv_t * drv, uint8_t orientation);
static void ili9341_set_orientation(uint8_t orientation);
static void ili9341_send_cmd(lv_disp_drv_t * drv, uint8_t cmd);
static void ili9341_send_data(lv_disp_drv_t * drv, void * data, uint16_t length);
static void ili9341_send_color(lv_disp_drv_t * drv, void * data, uint16_t length);
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 void ili9341_reset(lv_disp_drv_t * drv);
/**********************
* STATIC VARIABLES
**********************/
@ -53,172 +50,162 @@ static void ili9341_reset(lv_disp_drv_t * drv);
* GLOBAL FUNCTIONS
**********************/
void ili9341_init(lv_disp_drv_t * drv)
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},
/* Power control */
{0xC0, {0x26}, 1},
/* Power control */
{0xC1, {0x11}, 1},
/* VCOM control */
{0xC5, {0x35, 0x3E}, 2},
/* VCOM control */
{0xC7, {0xBE}, 1},
/* Memory Access Control */
{0x36, {0x28}, 1},
/* Pixel Format Set */
{0x3A, {0x55}, 1},
{0xB1, {0x00, 0x1B}, 2},
{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}, END_OF_CMD_MARKER},
};
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},
};
ili9341_reset(drv);
//Initialize non-SPI GPIOs
gpio_pad_select_gpio(ILI9341_DC);
gpio_set_direction(ILI9341_DC, GPIO_MODE_OUTPUT);
//Send all the commands
uint16_t cmd = 0;
while (ili_init_cmds[cmd].databytes != END_OF_CMD_MARKER) {
ili9341_send_cmd(drv, ili_init_cmds[cmd].cmd);
ili9341_send_data(drv, ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes & 0x1F);
if (ili_init_cmds[cmd].databytes & 0x80) {
display_port_delay(drv, 100);
}
#if ILI9341_USE_RST
gpio_pad_select_gpio(ILI9341_RST);
gpio_set_direction(ILI9341_RST, GPIO_MODE_OUTPUT);
cmd++;
}
//Reset the display
gpio_set_level(ILI9341_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ILI9341_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
ili9341_set_orientation(drv, ILI9341_INITIAL_ORIENTATION);
ESP_LOGI(TAG, "Initialization.");
#if ILI9341_INVERT_COLORS == 1U
ili9341_send_cmd(drv, 0x21);
//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_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION);
#if ILI9341_INVERT_COLORS == 1
ili9341_send_cmd(0x21);
#else
ili9341_send_cmd(drv, 0x20);
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] = {0};
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
uint8_t data[4];
/*Column addresses*/
data[0] = (area->x1 >> 8) & 0xFF;
data[1] = area->x1 & 0xFF;
data[2] = (area->x2 >> 8) & 0xFF;
data[3] = area->x2 & 0xFF;
/*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);
ili9341_send_cmd(drv, 0x2A);
ili9341_send_data(drv, 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);
/* Page addresses */
data[0] = (area->y1 >> 8) & 0xFF;
data[1] = area->y1 & 0xFF;
data[2] = (area->y2 >> 8) & 0xFF;
data[3] = area->y2 & 0xFF;
ili9341_send_cmd(drv, 0x2B);
ili9341_send_data(drv, data, 4);
/* Memory write */
ili9341_send_cmd(drv, 0x2C);
ili9341_send_color(drv, (void*)color_map, size * 2);
/*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_sleep_in(lv_disp_drv_t * drv)
void ili9341_sleep_in()
{
uint8_t data[] = {0x08};
ili9341_send_cmd(drv, 0x10);
ili9341_send_data(drv, data, 1);
uint8_t data[] = {0x08};
ili9341_send_cmd(0x10);
ili9341_send_data(&data, 1);
}
void ili9341_sleep_out(lv_disp_drv_t * drv)
void ili9341_sleep_out()
{
uint8_t data[] = {0x08};
ili9341_send_cmd(drv, 0x11);
ili9341_send_data(drv, data, 1);
uint8_t data[] = {0x08};
ili9341_send_cmd(0x11);
ili9341_send_data(&data, 1);
}
/**********************
* STATIC FUNCTIONS
**********************/
static inline void set_cmd_mode(lv_disp_drv_t * drv)
{
display_port_gpio_dc(drv, 0);
}
static inline void set_data_mode(lv_disp_drv_t * drv)
{
display_port_gpio_dc(drv, 1);
}
static void ili9341_send_cmd(lv_disp_drv_t * drv, uint8_t cmd)
static void ili9341_send_cmd(uint8_t cmd)
{
disp_wait_for_pending_transactions();
set_cmd_mode(drv);
gpio_set_level(ILI9341_DC, 0); /*Command mode*/
disp_spi_send_data(&cmd, 1);
}
static void ili9341_send_data(lv_disp_drv_t *drv, void * data, uint16_t length)
static void ili9341_send_data(void * data, uint16_t length)
{
disp_wait_for_pending_transactions();
set_data_mode(drv);
gpio_set_level(ILI9341_DC, 1); /*Data mode*/
disp_spi_send_data(data, length);
}
static void ili9341_send_color(lv_disp_drv_t *drv, void * data, uint16_t length)
static void ili9341_send_color(void * data, uint16_t length)
{
disp_wait_for_pending_transactions();
set_data_mode(drv);
gpio_set_level(ILI9341_DC, 1); /*Data mode*/
disp_spi_send_colors(data, length);
}
static void ili9341_set_orientation(lv_disp_drv_t *drv, uint8_t orientation)
static void ili9341_set_orientation(uint8_t orientation)
{
assert(orientation < 4);
// 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
const uint8_t data[] = {0x68, 0x68, 0x08, 0x08};
uint8_t data[] = {0x68, 0x68, 0x08, 0x08};
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_M5CORE2)
const uint8_t data[] = {0x08, 0x88, 0x28, 0xE8};
uint8_t data[] = {0x08, 0x88, 0x28, 0xE8};
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_WROVER4)
const uint8_t data[] = {0x6C, 0xEC, 0xCC, 0x4C};
#else
const uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
uint8_t data[] = {0x6C, 0xEC, 0xCC, 0x4C};
#elif defined (CONFIG_LV_PREDEFINED_DISPLAY_NONE)
uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
#endif
ili9341_send_cmd(drv, MEMORY_ACCESS_CONTROL_REG);
ili9341_send_data(drv, (void *) &data[orientation], 1);
}
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]);
/* Reset the display, if we don't have a reset pin we use software reset */
static void ili9341_reset(lv_disp_drv_t *drv)
{
#if defined(ILI9341_USE_RST)
display_port_gpio_rst(drv, 0);
display_port_delay(drv, 100);
display_port_gpio_rst(drv, 1);
display_port_delay(drv, 100);
#else
ili9341_send_cmd(drv, SOFTWARE_RESET_REG);
display_port_delay(drv, 5);
#endif
ili9341_send_cmd(0x36);
ili9341_send_data((void *) &data[orientation], 1);
}

View file

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

View file

@ -8,13 +8,16 @@
#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
@ -35,7 +38,6 @@ 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 void ili9481_reset(void);
/**********************
* STATIC VARIABLES
@ -71,9 +73,26 @@ void ili9481_init(void)
{0, {0}, 0xff},
};
ili9481_reset();
//Initialize non-SPI GPIOs
gpio_pad_select_gpio(ILI9481_DC);
gpio_set_direction(ILI9481_DC, GPIO_MODE_OUTPUT);
LV_LOG_INFO("Initialization.");
#if ILI9481_USE_RST
gpio_pad_select_gpio(ILI9481_RST);
gpio_set_direction(ILI9481_RST, GPIO_MODE_OUTPUT);
//Reset the display
gpio_set_level(ILI9481_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ILI9481_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
ESP_LOGI(TAG, "ILI9481 initialization.");
// Exit sleep
ili9481_send_cmd(0x01); /* Software reset */
vTaskDelay(100 / portTICK_RATE_MS);
//Send all the commands
uint16_t cmd = 0;
@ -92,16 +111,13 @@ void ili9481_init(void)
// Flush function based on mvturnho repo
void ili9481_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
{
/* 3 is number of bytes in lv_color_t */
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area) * 3;
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) {
LV_LOG_WARN("Could not allocate enough DMA memory!");
}
if (mybuf == NULL) ESP_LOGW(TAG, "Could not allocate enough DMA memory!");
} while (mybuf == NULL);
uint32_t LD = 0;
@ -144,9 +160,7 @@ void ili9481_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * col
/*Memory write*/
ili9481_send_cmd(ILI9481_CMD_MEMORY_WRITE);
ili9481_send_color((void *) mybuf, size);
/* FIXME: Can we free the memory even when it's being transferred? */
ili9481_send_color((void *) mybuf, size * 3);
heap_caps_free(mybuf);
}
@ -178,29 +192,13 @@ static void ili9481_send_color(void * data, uint16_t length)
static void ili9481_set_orientation(uint8_t orientation)
{
#if (LV_USE_LOG == 1)
const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
};
LV_LOG_INFO("Display orientation: %s", orientation_str[orientation]);
#endif
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);
}
static void ili9481_reset(void)
{
#if ILI9481_USE_RST
gpio_set_level(ILI9481_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ILI9481_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#else
// Exit sleep, software reset
ili9481_send_cmd(0x01);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
}

View file

@ -9,12 +9,14 @@
#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
@ -35,7 +37,7 @@ 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 void ili9486_reset(void);
/**********************
* STATIC VARIABLES
**********************/
@ -50,62 +52,77 @@ static void ili9486_reset(void);
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},
};
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},
};
ili9486_reset();
//Initialize non-SPI GPIOs
gpio_pad_select_gpio(ILI9486_DC);
gpio_set_direction(ILI9486_DC, GPIO_MODE_OUTPUT);
LV_LOG_INFO("ILI9486 Initialization.");
#if ILI9486_USE_RST
gpio_pad_select_gpio(ILI9486_RST);
gpio_set_direction(ILI9486_RST, GPIO_MODE_OUTPUT);
//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++;
}
//Reset the display
gpio_set_level(ILI9486_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ILI9486_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
ESP_LOGI(TAG, "ILI9486 Initialization.");
//Send all the commands
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_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};
/* 2 is the number of bytes in color depth */
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area) * 2;
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);
/*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);
/*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);
ili9486_send_color((void*) color_map, size);
/*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);
}
/**********************
@ -113,30 +130,30 @@ void ili9486_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * col
**********************/
static void ili9486_send_cmd(uint8_t cmd)
{
uint8_t to16bit[] = {
0x00, 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);
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;
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;
}
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));
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)
@ -148,29 +165,20 @@ static void ili9486_send_color(void * data, uint16_t length)
static void ili9486_set_orientation(uint8_t orientation)
{
assert(orientation < 4);
// ESP_ASSERT(orientation < 4);
const uint8_t data[] = {0x48, 0x88, 0x28, 0xE8};
#if (LV_USE_LOG == 1)
const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
};
LV_LOG_INFO("Display orientation: %s", orientation_str[orientation]);
LV_LOG_INFO("0x36 command value: 0x%02X", data[orientation]);
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);
}
static void ili9486_reset(void)
{
#if ILI9486_USE_RST
gpio_set_level(ILI9486_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ILI9486_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
}

View file

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

View file

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

View file

@ -29,39 +29,23 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
#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)))
#if defined CONFIG_LV_DISP_PIN_RST
#define PIN_RST CONFIG_LV_DISP_PIN_RST
#define PIN_RST_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_RST)))
#endif
#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)
#if defined (LV_HOR_RES_MAX)
#define EPD_WIDTH LV_HOR_RES_MAX
#else
/* ToDo Remove magic number */
#define EPD_WIDTH 256u
#endif
#if defined (LV_VER_RES_MAX)
#define EPD_HEIGHT LV_VER_RES_MAX
#else
/* ToDo Remove magic number */
#define EPD_HEIGHT 128u
#endif
#define EPD_ROW_LEN (EPD_HEIGHT / 8u)
/* ToDo Remove semicolon */
#define EPD_PARTIAL_CNT 5;
#define BIT_SET(a, b) ((a) |= (1U << (b)))
@ -139,9 +123,10 @@ static const uint8_t lut_bb1[] = {
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)
#else
#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
@ -191,9 +176,16 @@ static void jd79653a_spi_send_data(uint8_t *data, size_t len)
disp_spi_send_data(data, len);
}
static void jd79653a_spi_send_fb(uint8_t *data, size_t len)
{
disp_wait_for_pending_transactions();
gpio_set_level(PIN_DC, 1); // DC = 1 for data
disp_spi_send_colors(data, len);
}
static void jd79653a_spi_send_seq(const jd79653a_seq_t *seq, size_t len)
{
LV_LOG_INFO("Writing cmd/data sequence, count %u", 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++) {
@ -215,21 +207,21 @@ static esp_err_t jd79653a_wait_busy(uint32_t timeout_ms)
return ((bits & EVT_BUSY) != 0) ? ESP_OK : ESP_ERR_TIMEOUT;
}
static void jd79653a_power_on(void)
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(void)
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(void)
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));
@ -247,9 +239,9 @@ static void jd79653a_load_partial_lut(void)
jd79653a_spi_send_data((uint8_t *)lut_bb1, sizeof(lut_bb1));
}
static void jd79653a_partial_in(void)
static void jd79653a_partial_in()
{
LV_LOG_INFO("Partial in!");
ESP_LOGD(TAG, "Partial in!");
// Panel setting: accept LUT from registers instead of OTP
#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
@ -257,8 +249,7 @@ static void jd79653a_partial_in(void)
#elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
uint8_t pst_use_reg_lut[] = { 0xff, 0x0e };
#else
assert(false); // Unsupported orientation configured. Crash if we get here, but allow compilation for CI
uint8_t pst_use_reg_lut[] = { 0,0 };
#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));
@ -275,9 +266,9 @@ static void jd79653a_partial_in(void)
jd79653a_spi_send_cmd(0x91);
}
static void jd79653a_partial_out(void)
static void jd79653a_partial_out()
{
LV_LOG_INFO("Partial out!");
ESP_LOGD(TAG, "Partial out!");
// Panel setting: use LUT from OTP
#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
@ -285,8 +276,7 @@ static void jd79653a_partial_out(void)
#elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
uint8_t pst_use_otp_lut[] = { 0xdf, 0x0e };
#else
assert(false); // Unsupported orientation configured. Crash if we get here, but allow compilation for CI
uint8_t pst_use_otp_lut[] = { 0,0 };
#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));
@ -304,10 +294,10 @@ static void jd79653a_update_partial(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t
{
jd79653a_power_on();
jd79653a_partial_in();
LV_LOG_INFO("x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", x1, x2, y1, y2);
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;
LV_LOG_INFO("Writing PARTIAL LVGL fb with len: %u", len);
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 };
@ -323,18 +313,16 @@ static void jd79653a_update_partial(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t
len -= EPD_ROW_LEN;
}
LV_LOG_INFO("Partial wait start");
ESP_LOGD(TAG, "Partial wait start");
jd79653a_spi_send_cmd(0x12);
jd79653a_wait_busy(0);
LV_LOG_INFO("Partial updated");
ESP_LOGD(TAG, "Partial updated");
jd79653a_partial_out();
jd79653a_power_off();
}
static void jd79653a_reset(void);
void jd79653a_fb_set_full_color(uint8_t color)
{
jd79653a_power_on();
@ -365,7 +353,7 @@ void jd79653a_fb_set_full_color(uint8_t color)
void jd79653a_fb_full_update(uint8_t *data, size_t len)
{
jd79653a_power_on();
LV_LOG_INFO("Performing full update, len: %u", len);
ESP_LOGD(TAG, "Performing full update, len: %u", len);
uint8_t *data_ptr = data;
@ -384,7 +372,7 @@ void jd79653a_fb_full_update(uint8_t *data, size_t len)
len -= EPD_ROW_LEN;
}
LV_LOG_INFO("Rest len: %u", len);
ESP_LOGD(TAG, "Rest len: %u", len);
jd79653a_spi_send_cmd(0x12); // Issue refresh command
vTaskDelay(pdMS_TO_TICKS(100));
@ -393,7 +381,7 @@ void jd79653a_fb_full_update(uint8_t *data, size_t len)
jd79653a_power_off();
}
void jd79653a_lv_set_fb_cb(lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
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);
@ -406,7 +394,7 @@ void jd79653a_lv_set_fb_cb(lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf
}
}
void jd79653a_lv_rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area)
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;
@ -417,16 +405,15 @@ void jd79653a_lv_rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area)
void jd79653a_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
{
#if LV_USE_LOG
size_t len = ((area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1)) / 8;
LV_LOG_INFO("x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", area->x1, area->x2, area->y1, area->y2);
LV_LOG_INFO("Writing LVGL fb with len: %u, partial counter: %u", len, partial_counter);
#endif
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) {
LV_LOG_INFO("Refreshing in FULL");
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 {
@ -437,7 +424,7 @@ void jd79653a_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t
lv_disp_flush_ready(drv);
}
void jd79653a_deep_sleep(void)
void jd79653a_deep_sleep()
{
jd79653a_spi_send_seq(power_off_seq, EPD_SEQ_LEN(power_off_seq));
jd79653a_wait_busy(1000);
@ -447,15 +434,25 @@ void jd79653a_deep_sleep(void)
jd79653a_spi_send_data(&check_code, sizeof(check_code));
}
void jd79653a_init(void)
void jd79653a_init()
{
// Initialise event group
jd79653a_evts = xEventGroupCreate();
if (!jd79653a_evts) {
LV_LOG_ERROR("Failed when initialising event group!");
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,
@ -468,25 +465,18 @@ void jd79653a_init(void)
gpio_install_isr_service(0);
gpio_isr_handler_add(PIN_BUSY, jd79653a_busy_intr, (void *) PIN_BUSY);
jd79653a_reset();
// 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));
LV_LOG_INFO("Panel init sequence sent");
ESP_LOGI(TAG, "Panel init sequence sent");
// Check BUSY status here
jd79653a_wait_busy(0);
LV_LOG_INFO("Panel is up!");
}
static void jd79653a_reset(void)
{
#if defined CONFIG_LV_DISP_PIN_RST
gpio_set_level(PIN_RST, 0);
// At least 10ms, leave 15ms for now just in case...
vTaskDelay(pdMS_TO_TICKS(15));
gpio_set_level(PIN_RST, 1);
vTaskDelay(pdMS_TO_TICKS(120));
#endif
ESP_LOGI(TAG, "Panel is up!");
}

View file

@ -17,12 +17,12 @@ extern "C"
#include "lvgl/lvgl.h"
#endif
void jd79653a_init(void);
void jd79653a_deep_sleep(void);
void jd79653a_init();
void jd79653a_deep_sleep();
void jd79653a_lv_set_fb_cb(lv_disp_drv_t * disp_drv, uint8_t* buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
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(lv_disp_drv_t * disp_drv, lv_area_t *area);
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);

View file

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

View file

@ -26,6 +26,10 @@ extern "C" {
* DEFINES
*********************/
#define PCD8544_DC CONFIG_LV_DISP_PIN_DC
#define PCD8544_RST CONFIG_LV_DISP_PIN_RST
#define PCD8544_BCKL CONFIG_LV_DISP_PIN_BCKL
/**********************
* TYPEDEFS
**********************/
@ -34,12 +38,12 @@ extern "C" {
* GLOBAL PROTOTYPES
**********************/
void pcd8544_init(lv_disp_drv_t *drv);
void pcd8544_init(void);
void pcd8544_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
void pcd8544_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area);
void pcd8544_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa);
void pcd8544_set_contrast(lv_disp_drv_t *drv, uint8_t contrast);
void pcd8544_set_contrast(uint8_t contrast);
/**********************
* MACROS

View file

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

27
lvgl_tft/schmitt.c Normal file
View file

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

20
lvgl_tft/schmitt.h Normal file
View file

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

View file

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

View file

@ -39,8 +39,8 @@ extern "C" {
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(lv_disp_drv_t * disp_drv, lv_area_t *area);
void sh1107_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
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);

View file

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

View file

@ -9,6 +9,7 @@
#include "st7735s.h"
#include "disp_spi.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@ -19,6 +20,7 @@
/*********************
* DEFINES
*********************/
#define TAG "ST7735S"
#define AXP192_I2C_ADDRESS 0x34
/**********************
@ -39,14 +41,10 @@ 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 st7735s_reset(void);
#ifdef CONFIG_LV_M5STICKC_HANDLE_AXP192
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();
#endif
/**********************
* STATIC VARIABLES
@ -99,9 +97,22 @@ void st7735s_init(void)
{0, {0}, 0xff}
};
st7735s_reset();
//Initialize non-SPI GPIOs
gpio_pad_select_gpio(ST7735S_DC);
gpio_set_direction(ST7735S_DC, GPIO_MODE_OUTPUT);
LV_LOG_INFO("ST7735S initialization.");
#if ST7735S_USE_RST
gpio_pad_select_gpio(ST7735S_RST);
gpio_set_direction(ST7735S_RST, GPIO_MODE_OUTPUT);
//Reset the display
gpio_set_level(ST7735S_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ST7735S_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
ESP_LOGI(TAG, "ST7735S initialization.");
//Send all the commands
uint16_t cmd = 0;
@ -125,29 +136,29 @@ void st7735s_init(void)
void st7735s_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
{
uint8_t data[4] = {0};
uint8_t data[4];
/*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);
/*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);
/*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);
/*Memory write*/
st7735s_send_cmd(0x2C);
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area) * 2;
st7735s_send_color((void*)color_map, size);
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()
@ -193,7 +204,11 @@ static void st7735s_send_color(void * data, uint16_t length)
static void st7735s_set_orientation(uint8_t orientation)
{
assert(orientation < 4);
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
@ -202,58 +217,41 @@ static void st7735s_set_orientation(uint8_t orientation)
*/
uint8_t data[] = {0xC8, 0xC8, 0xA8, 0xA8};
#if (LV_USE_LOG == 1)
const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
};
LV_LOG_INFO("Display orientation: %s", orientation_str[orientation]);
LV_LOG_INFO("0x36 command value: 0x%02X", data[orientation]);
#endif
ESP_LOGD(TAG, "0x36 command value: 0x%02X", data[orientation]);
st7735s_send_cmd(ST7735_MADCTL);
st7735s_send_data((void *) &data[orientation], 1);
}
static void st7735s_reset(void)
{
#if ST7735S_USE_RST
gpio_set_level(ST7735S_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ST7735S_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#endif
}
#ifdef CONFIG_LV_M5STICKC_HANDLE_AXP192
static void axp192_write_byte(uint8_t addr, uint8_t data)
{
err = lvgl_i2c_write(CONFIG_LV_I2C_DISPLAY_PORT, AXP192_I2C_ADDRESS, addr, &data, 1);
if (ret != ESP_OK) {
LV_LOG_ERROR("AXP192 send failed. code: 0x%.2X", ret);
static void axp192_write_byte(uint8_t addr, uint8_t data)
{
err = lvgl_i2c_write(CONFIG_LV_I2C_DISPLAY_PORT, AXP192_I2C_ADDRESS, addr, &data, 1);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "AXP192 send failed. code: 0x%.2X", ret);
}
}
}
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
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();
LV_LOG_INFO("AXP192 initialized, power enabled for LDO2 and LDO3");
}
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_in()
{
axp192_write_byte(0x12, 0x4b);
}
static void axp192_sleep_out()
{
axp192_write_byte(0x12, 0x4d);
}
static void axp192_sleep_out()
{
axp192_write_byte(0x12, 0x4d);
}
#endif

View file

@ -4,15 +4,21 @@
* 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 "display_port.h"
#include "driver/gpio.h"
/*********************
* DEFINES
*********************/
#define TAG "st7789"
/**********************
* TYPEDEFS
**********************/
@ -27,18 +33,13 @@ typedef struct {
/**********************
* STATIC PROTOTYPES
**********************/
static void st7789_set_orientation(lv_disp_drv_t *drv, uint8_t orientation);
static void st7789_send_cmd(lv_disp_drv_t * drv, uint8_t cmd);
static void st7789_send_data(lv_disp_drv_t * drv, void *data, uint16_t length);
static void st7789_send_color(lv_disp_drv_t * drv, void *data, uint16_t length);
static void st7789_reset(lv_disp_drv_t * drv);
static void st7789_set_orientation(uint8_t orientation);
static void st7789_send_color(void *data, size_t length);
static void setup_initial_offsets(void);
/**********************
* STATIC VARIABLES
**********************/
static uint16_t user_x_offset = 0u;
static uint16_t user_y_offset = 0u;
/**********************
* MACROS
@ -47,10 +48,8 @@ static uint16_t user_y_offset = 0u;
/**********************
* GLOBAL FUNCTIONS
**********************/
void st7789_init(lv_disp_drv_t *drv)
void st7789_init(void)
{
setup_initial_offsets();
lcd_init_cmd_t st7789_init_cmds[] = {
{0xCF, {0x00, 0x83, 0X30}, 3},
{0xED, {0x64, 0x03, 0X12, 0X81}, 4},
@ -86,21 +85,39 @@ void st7789_init(lv_disp_drv_t *drv)
{0, {0}, 0xff},
};
st7789_reset(drv);
//Initialize non-SPI GPIOs
gpio_pad_select_gpio(ST7789_DC);
gpio_set_direction(ST7789_DC, GPIO_MODE_OUTPUT);
#if !defined(ST7789_SOFT_RST)
gpio_pad_select_gpio(ST7789_RST);
gpio_set_direction(ST7789_RST, GPIO_MODE_OUTPUT);
#endif
//Reset the display
#if !defined(ST7789_SOFT_RST)
gpio_set_level(ST7789_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ST7789_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
#else
st7789_send_cmd(ST7789_SWRESET);
#endif
printf("ST7789 initialization.\n");
//Send all the commands
uint16_t cmd = 0;
while (st7789_init_cmds[cmd].databytes!=0xff) {
st7789_send_cmd(drv, st7789_init_cmds[cmd].cmd);
st7789_send_data(drv, st7789_init_cmds[cmd].data, st7789_init_cmds[cmd].databytes&0x1F);
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) {
display_port_delay(drv, 100);
vTaskDelay(100 / portTICK_RATE_MS);
}
cmd++;
}
/* FIXME We're setting up the initial orientation in the cmd array */
st7789_set_orientation(drv, ST7789_INITIAL_ORIENTATION);
st7789_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION);
}
/* The ST7789 display controller can drive up to 320*240 displays, when using a 240*240 or 240*135
@ -114,94 +131,98 @@ void st7789_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * colo
uint16_t offsetx2 = area->x2;
uint16_t offsety1 = area->y1;
uint16_t offsety2 = area->y2;
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
offsetx1 += st7789_x_offset();
offsetx2 += st7789_x_offset();
offsety1 += st7789_y_offset();
offsety2 += st7789_y_offset();
#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
#elif (LV_HOR_RES_MAX == 240) && (LV_VER_RES_MAX == 135)
#if (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT) || \
(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
offsetx1 += 40;
offsetx2 += 40;
offsety1 += 53;
offsety2 += 53;
#endif
#elif (LV_HOR_RES_MAX == 135) && (LV_VER_RES_MAX == 240)
#if (CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE) || \
(CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
offsetx1 += 52;
offsetx2 += 52;
offsety1 += 40;
offsety2 += 40;
#endif
#endif
/*Column addresses*/
st7789_send_cmd(drv, ST7789_CASET);
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(drv, data, 4);
st7789_send_data(data, 4);
/*Page addresses*/
st7789_send_cmd(drv, ST7789_RASET);
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(drv, data, 4);
st7789_send_data(data, 4);
/*Memory write*/
st7789_send_cmd(drv, ST7789_RAMWR);
st7789_send_color(drv, (void*) color_map, size * 2);
}
st7789_send_cmd(ST7789_RAMWR);
void st7789_set_x_offset(const uint16_t offset)
{
user_x_offset = offset;
}
size_t size = (size_t)lv_area_get_width(area) * (size_t)lv_area_get_height(area);
void st7789_set_y_offset(const uint16_t offset)
{
user_y_offset = offset;
}
st7789_send_color((void*)color_map, size * 2);
uint16_t st7789_x_offset(void)
{
return user_x_offset;
}
uint16_t st7789_y_offset(void)
{
return user_y_offset;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void st7789_send_cmd(lv_disp_drv_t *drv, uint8_t cmd)
void st7789_send_cmd(uint8_t cmd)
{
disp_wait_for_pending_transactions();
display_port_gpio_dc(drv, 0);
gpio_set_level(ST7789_DC, 0);
disp_spi_send_data(&cmd, 1);
}
static void st7789_send_data(lv_disp_drv_t *drv, void * data, uint16_t length)
void st7789_send_data(void * data, uint16_t length)
{
disp_wait_for_pending_transactions();
display_port_gpio_dc(drv, 1);
gpio_set_level(ST7789_DC, 1);
disp_spi_send_data(data, length);
}
static void st7789_send_color(lv_disp_drv_t *drv, void * data, uint16_t length)
static void st7789_send_color(void * data, size_t length)
{
disp_wait_for_pending_transactions();
display_port_gpio_dc(drv, 1);
gpio_set_level(ST7789_DC, 1);
disp_spi_send_colors(data, length);
}
/* Reset the display, if we don't have a reset pin we use software reset */
static void st7789_reset(lv_disp_drv_t *drv)
static void st7789_set_orientation(uint8_t orientation)
{
#if !defined(ST7789_SOFT_RST)
display_port_gpio_rst(drv, 0);
display_port_delay(drv, 100);
display_port_gpio_rst(drv, 1);
display_port_delay(drv, 100);
#else
st7789_send_cmd(drv, ST7789_SWRESET);
display_port_delay(drv, 5);
#endif
}
// ESP_ASSERT(orientation < 4);
const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"
};
ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]);
static void st7789_set_orientation(lv_disp_drv_t *drv, uint8_t orientation)
{
uint8_t data[] =
{
#if CONFIG_LV_PREDEFINED_DISPLAY_TTGO
@ -211,42 +232,8 @@ static void st7789_set_orientation(lv_disp_drv_t *drv, uint8_t orientation)
#endif
};
st7789_send_cmd(drv, ST7789_MADCTL);
st7789_send_data(drv, (void *) &data[orientation], 1);
}
ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]);
static void setup_initial_offsets(void)
{
#if (CONFIG_LV_TFT_DISPLAY_OFFSETS)
st7789_set_x_offset(CONFIG_LV_TFT_DISPLAY_X_OFFSET);
st7789_set_y_offset(CONFIG_LV_TFT_DISPLAY_Y_OFFSET);
#elif (LV_HOR_RES_MAX == 240) && (LV_VER_RES_MAX == 240)
#if (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
st7789_set_x_offset(80);
st7789_set_y_offset(0);
#elif (CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
st7789_set_x_offset(0);
st7789_set_y_offset(80);
#endif
#elif (LV_HOR_RES_MAX == 240) && (LV_VER_RES_MAX == 135)
#if (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT) || \
(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
st7789_set_x_offset(40);
st7789_set_y_offset(53);
#endif
#elif (LV_HOR_RES_MAX == 135) && (LV_VER_RES_MAX == 240)
#if (CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE) || \
(CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
st7789_set_x_offset(52);
st7789_set_y_offset(40);
#endif
#endif
}
/* Display update callback, we could update the orientation in here
* NOTE Available only for LVGL v8 */
void st7789_update_cb(lv_disp_drv_t *drv)
{
(void) drv;
st7789_send_cmd(ST7789_MADCTL);
st7789_send_data((void *) &data[orientation], 1);
}

View file

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

View file

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

View file

@ -29,37 +29,23 @@
#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)))
#if defined CONFIG_LV_DISP_PIN_RST
#define PIN_RST CONFIG_LV_DISP_PIN_RST
#define PIN_RST_BIT ((1ULL << (uint8_t)(CONFIG_LV_DISP_PIN_RST)))
#endif
#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)
#if defined (LV_HOR_RES_MAX)
#define EPD_WIDTH LV_HOR_RES_MAX
#else
/* ToDo Fix, 256 is just a magic number */
#define EPD_WIDTH 256u
#endif
#if defined (LV_VER_RES_MAX)
#define EPD_HEIGHT LV_VER_RES_MAX
#else
/* ToDo Fix, 128 is just a magic number */
#define EPD_HEIGHT 128u
#endif
#define EPD_ROW_LEN (EPD_HEIGHT / 8u)
#define BIT_SET(a, b) ((a) |= (1U << (b)))
@ -107,6 +93,26 @@ static void uc8151d_spi_send_data_byte(uint8_t 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));
@ -118,7 +124,7 @@ static esp_err_t uc8151d_wait_busy(uint32_t timeout_ms)
return ((bits & EVT_BUSY) != 0) ? ESP_OK : ESP_ERR_TIMEOUT;
}
static void uc8151d_sleep(void)
static void uc8151d_sleep()
{
// Set VCOM to 0xf7
uc8151d_spi_send_cmd(0x50);
@ -133,13 +139,14 @@ static void uc8151d_sleep(void)
uc8151d_spi_send_data_byte(0xa5);
}
static void uc8151d_reset(void);
static void uc8151d_panel_init(void)
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++) {
uc8151d_reset();
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
@ -189,20 +196,19 @@ static void uc8151d_full_update(uint8_t *buf)
void uc8151d_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
{
#if LV_USE_LOG
size_t len = ((area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1)) / 8;
LV_LOG_INFO("x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", area->x1, area->x2, area->y1, area->y2);
LV_LOG_INFO("Writing LVGL fb with len: %u", len);
#endif
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);
LV_LOG_INFO("Ready");
ESP_LOGD(TAG, "Ready");
}
void uc8151d_lv_set_fb_cb(lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
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);
@ -211,12 +217,12 @@ void uc8151d_lv_set_fb_cb(lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_
if (color.full) {
BIT_SET(buf[byte_index], 7 - bit_index);
} else {
LV_LOG_INFO("Clear at x: %u, y: %u", x, y);
ESP_LOGD(TAG, "Clear at x: %u, y: %u", x, y);
BIT_CLEAR(buf[byte_index], 7 - bit_index);
}
}
void uc8151d_lv_rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area)
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;
@ -225,15 +231,25 @@ void uc8151d_lv_rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area)
area->y2 = EPD_HEIGHT - 1;
}
void uc8151d_init(void)
void uc8151d_init()
{
// Initialise event group
uc8151d_evts = xEventGroupCreate();
if (!uc8151d_evts) {
LV_LOG_ERROR("Failed when initialising event group!");
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,
@ -246,18 +262,7 @@ void uc8151d_init(void)
gpio_install_isr_service(0);
gpio_isr_handler_add(PIN_BUSY, uc8151d_busy_intr, (void *) PIN_BUSY);
LV_LOG_INFO("IO init finished");
ESP_LOGI(TAG, "IO init finished");
uc8151d_panel_init();
LV_LOG_INFO("Panel initialised");
}
static void uc8151d_reset(void)
{
#if defined CONFIG_LV_DISP_USE_RST
gpio_set_level(PIN_RST, 0);
// At least 10ms, leave 20ms for now just in case...
vTaskDelay(pdMS_TO_TICKS(20));
gpio_set_level(PIN_RST, 1);
vTaskDelay(pdMS_TO_TICKS(10));
#endif
ESP_LOGI(TAG, "Panel initialised");
}

View file

@ -29,11 +29,11 @@
#include <lvgl.h>
void uc8151d_init(void);
void uc8151d_lv_set_fb_cb(lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
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(lv_disp_drv_t *disp_drv, lv_area_t *area);
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

View file

@ -12,6 +12,7 @@
#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
@ -136,21 +137,21 @@ void adcraw_init(void)
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);
// 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)

View file

@ -1,162 +1,160 @@
/*
* 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.
*/
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include <lvgl.h>
#else
#include <lvgl/lvgl.h>
#endif
#include "ft6x36.h"
#include "lvgl_i2c/i2c_manager.h"
#define TAG "FT6X36"
#define FT6X36_TOUCH_QUEUE_ELEMENTS 1
static ft6x36_status_t ft6x36_status;
/* Set during initialization */
static uint8_t current_dev_addr;
/* -1 coordinates to designate it was never touched */
static ft6x36_touch_t touch_inputs = { -1, -1, LV_INDEV_STATE_REL };
#if CONFIG_LV_FT6X36_COORDINATES_QUEUE
QueueHandle_t ft6x36_touch_queue_handle;
#endif
static esp_err_t ft6x06_i2c_read8(uint8_t slave_addr, uint8_t register_addr, uint8_t *data_buf) {
return lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, slave_addr, register_addr, data_buf, 1);
}
/**
* @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) {
LV_LOG_ERROR("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))
LV_LOG_ERROR("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) {
ft6x36_status.inited = true;
current_dev_addr = dev_addr;
uint8_t data_buf;
esp_err_t ret;
LV_LOG_INFO("Found touch panel controller");
if ((ret = ft6x06_i2c_read8(dev_addr, FT6X36_PANEL_ID_REG, &data_buf) != ESP_OK))
LV_LOG_ERROR("Error reading from device: %s",
esp_err_to_name(ret)); // Only show error the first time
LV_LOG_INFO("\tDevice ID: 0x%02x", data_buf);
ft6x06_i2c_read8(dev_addr, FT6X36_CHIPSELECT_REG, &data_buf);
LV_LOG_INFO("\tChip ID: 0x%02x", data_buf);
ft6x06_i2c_read8(dev_addr, FT6X36_DEV_MODE_REG, &data_buf);
LV_LOG_INFO("\tDevice mode: 0x%02x", data_buf);
ft6x06_i2c_read8(dev_addr, FT6X36_FIRMWARE_ID_REG, &data_buf);
LV_LOG_INFO("\tFirmware ID: 0x%02x", data_buf);
ft6x06_i2c_read8(dev_addr, FT6X36_RELEASECODE_REG, &data_buf);
LV_LOG_INFO("\tRelease code: 0x%02x", data_buf);
#if CONFIG_LV_FT6X36_COORDINATES_QUEUE
ft6x36_touch_queue_handle = xQueueCreate( FT6X36_TOUCH_QUEUE_ELEMENTS, sizeof( ft6x36_touch_t ) );
if( ft6x36_touch_queue_handle == NULL )
{
LV_LOG_ERROR("\tError creating touch input FreeRTOS queue" );
return;
}
xQueueSend( ft6x36_touch_queue_handle, &touch_inputs, 0 );
#endif
}
/**
* @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) {
if (!ft6x36_status.inited) {
LV_LOG_ERROR("Init first!");
return 0x00;
}
uint8_t data_buf[5]; // 1 byte status, 2 bytes X, 2 bytes Y
esp_err_t ret = lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, current_dev_addr, FT6X36_TD_STAT_REG, &data_buf[0], 5);
if (ret != ESP_OK) {
LV_LOG_ERROR("Error talking to touch IC: %s", esp_err_to_name(ret));
}
uint8_t touch_pnt_cnt = data_buf[0]; // Number of detected touch points
if (ret != ESP_OK || touch_pnt_cnt != 1) { // ignore no touch & multi touch
if ( touch_inputs.current_state != LV_INDEV_STATE_REL)
{
touch_inputs.current_state = LV_INDEV_STATE_REL;
#if CONFIG_LV_FT6X36_COORDINATES_QUEUE
xQueueOverwrite( ft6x36_touch_queue_handle, &touch_inputs );
#endif
}
data->point.x = touch_inputs.last_x;
data->point.y = touch_inputs.last_y;
data->state = touch_inputs.current_state;
return false;
}
touch_inputs.current_state = LV_INDEV_STATE_PR;
touch_inputs.last_x = ((data_buf[1] & FT6X36_MSB_MASK) << 8) | (data_buf[2] & FT6X36_LSB_MASK);
touch_inputs.last_y = ((data_buf[3] & FT6X36_MSB_MASK) << 8) | (data_buf[4] & FT6X36_LSB_MASK);
#if CONFIG_LV_FT6X36_SWAPXY
int16_t swap_buf = touch_inputs.last_x;
touch_inputs.last_x = touch_inputs.last_y;
touch_inputs.last_y = swap_buf;
#endif
#if CONFIG_LV_FT6X36_INVERT_X
touch_inputs.last_x = LV_HOR_RES - touch_inputs.last_x;
#endif
#if CONFIG_LV_FT6X36_INVERT_Y
touch_inputs.last_y = LV_VER_RES - touch_inputs.last_y;
#endif
data->point.x = touch_inputs.last_x;
data->point.y = touch_inputs.last_y;
data->state = touch_inputs.current_state;
LV_LOG_INFO("X=%u Y=%u", data->point.x, data->point.y);
#if CONFIG_LV_FT6X36_COORDINATES_QUEUE
xQueueOverwrite( ft6x36_touch_queue_handle, &touch_inputs );
#endif
return false;
}
/*
* 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>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include <lvgl.h>
#else
#include <lvgl/lvgl.h>
#endif
#include "ft6x36.h"
#include "lvgl_i2c/i2c_manager.h"
#define TAG "FT6X36"
#define FT6X36_TOUCH_QUEUE_ELEMENTS 1
static ft6x36_status_t ft6x36_status;
static uint8_t current_dev_addr; // set during init
static ft6x36_touch_t touch_inputs = { -1, -1, LV_INDEV_STATE_REL }; // -1 coordinates to designate it was never touched
#if CONFIG_LV_FT6X36_COORDINATES_QUEUE
QueueHandle_t ft6x36_touch_queue_handle;
#endif
static esp_err_t ft6x06_i2c_read8(uint8_t slave_addr, uint8_t register_addr, uint8_t *data_buf) {
return lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, slave_addr, register_addr, data_buf, 1);
}
/**
* @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) {
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);
#if CONFIG_LV_FT6X36_COORDINATES_QUEUE
ft6x36_touch_queue_handle = xQueueCreate( FT6X36_TOUCH_QUEUE_ELEMENTS, sizeof( ft6x36_touch_t ) );
if( ft6x36_touch_queue_handle == NULL )
{
ESP_LOGE( TAG, "\tError creating touch input FreeRTOS queue" );
return;
}
xQueueSend( ft6x36_touch_queue_handle, &touch_inputs, 0 );
#endif
}
/**
* @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) {
if (!ft6x36_status.inited) {
ESP_LOGE(TAG, "Init first!");
return 0x00;
}
uint8_t data_buf[5]; // 1 byte status, 2 bytes X, 2 bytes Y
esp_err_t ret = lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, current_dev_addr, FT6X36_TD_STAT_REG, &data_buf[0], 5);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Error talking to touch IC: %s", esp_err_to_name(ret));
}
uint8_t touch_pnt_cnt = data_buf[0]; // Number of detected touch points
if (ret != ESP_OK || touch_pnt_cnt != 1) { // ignore no touch & multi touch
if ( touch_inputs.current_state != LV_INDEV_STATE_REL)
{
touch_inputs.current_state = LV_INDEV_STATE_REL;
#if CONFIG_LV_FT6X36_COORDINATES_QUEUE
xQueueOverwrite( ft6x36_touch_queue_handle, &touch_inputs );
#endif
}
data->point.x = touch_inputs.last_x;
data->point.y = touch_inputs.last_y;
data->state = touch_inputs.current_state;
return false;
}
touch_inputs.current_state = LV_INDEV_STATE_PR;
touch_inputs.last_x = ((data_buf[1] & FT6X36_MSB_MASK) << 8) | (data_buf[2] & FT6X36_LSB_MASK);
touch_inputs.last_y = ((data_buf[3] & FT6X36_MSB_MASK) << 8) | (data_buf[4] & FT6X36_LSB_MASK);
#if CONFIG_LV_FT6X36_SWAPXY
int16_t swap_buf = touch_inputs.last_x;
touch_inputs.last_x = touch_inputs.last_y;
touch_inputs.last_y = swap_buf;
#endif
#if CONFIG_LV_FT6X36_INVERT_X
touch_inputs.last_x = LV_HOR_RES - touch_inputs.last_x;
#endif
#if CONFIG_LV_FT6X36_INVERT_Y
touch_inputs.last_y = LV_VER_RES - touch_inputs.last_y;
#endif
data->point.x = touch_inputs.last_x;
data->point.y = touch_inputs.last_y;
data->state = touch_inputs.current_state;
ESP_LOGD(TAG, "X=%u Y=%u", data->point.x, data->point.y);
#if CONFIG_LV_FT6X36_COORDINATES_QUEUE
xQueueOverwrite( ft6x36_touch_queue_handle, &touch_inputs );
#endif
return false;
}

View file

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

View file

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

View file

@ -7,6 +7,7 @@
*********************/
#include "stmpe610.h"
#include "esp_system.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
@ -16,6 +17,8 @@
/*********************
* DEFINES
*********************/
#define TAG "STMPE610"
/**********************
* TYPEDEFS
@ -52,11 +55,11 @@ void stmpe610_init(void)
uint8_t u8;
uint16_t u16;
LV_LOG_INFO("Initialization.");
ESP_LOGI(TAG, "Initialization.");
// Get the initial SPI configuration
//u8 = read_8bit_reg(STMPE_SPI_CFG);
//LV_LOG_INFO("SPI_CFG = 0x%x", u8);
//ESP_LOGI(TAG, "SPI_CFG = 0x%x", u8);
// Attempt a software reset
write_8bit_reg(STMPE_SYS_CTRL1, STMPE_SYS_CTRL1_RESET);
@ -66,12 +69,12 @@ void stmpe610_init(void)
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);
LV_LOG_INFO("SPI_CFG = 0x%x", u8);
ESP_LOGI(TAG, "SPI_CFG = 0x%x", u8);
// Verify SPI communication
u16 = read_16bit_reg(STMPE_CHIP_ID);
if (u16 != 0x811) {
LV_LOG_ERROR("Incorrect version: 0x%x", u16);
ESP_LOGE(TAG, "Incorrect version: 0x%x", u16);
}
write_8bit_reg(STMPE_SYS_CTRL2, 0x00); // Disable clocks
@ -127,12 +130,12 @@ bool stmpe610_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
}
if (c > 0) {
//LV_LOG_INFO("%d: %d %d %d", c, x, y, z);
//ESP_LOGI(TAG, "%d: %d %d %d", c, x, y, z);
adjust_data(&x, &y);
last_x = x;
last_y = y;
//LV_LOG_INFO(" ==> %d %d", x, y);
//ESP_LOGI(TAG, " ==> %d %d", x, y);
}
z = read_8bit_reg(STMPE_INT_STA); // Clear interrupts
@ -141,7 +144,7 @@ bool stmpe610_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
// 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
LV_LOG_ERROR("Fifo overflow");
ESP_LOGE(TAG, "Fifo overflow");
}
}

View file

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