Carve out backlight control to separate component

This commit is contained in:
Tomas Rezucha 2021-08-03 08:59:59 +02:00
parent 678779c848
commit fa042b0ecd
6 changed files with 227 additions and 108 deletions

View file

@ -3,8 +3,7 @@ if(ESP_PLATFORM)
file(GLOB SOURCES *.c) file(GLOB SOURCES *.c)
set(LVGL_INCLUDE_DIRS . lvgl_tft) set(LVGL_INCLUDE_DIRS . lvgl_tft)
list(APPEND SOURCES "lvgl_tft/disp_driver.c") list(APPEND SOURCES "lvgl_tft/disp_driver.c")
list(APPEND SOURCES "lvgl_tft/esp_lcd_backlight.c")
#@todo add SimleInclude macro here
# Include only the source file of the selected # Include only the source file of the selected
# display controller. # display controller.
@ -79,11 +78,6 @@ if(CONFIG_LV_TOUCH_CONTROLLER)
endif() endif()
endif() endif()
# Add backlight control to compilation only if it is selected in menuconfig
if(CONFIG_LV_ENABLE_BACKLIGHT_CONTROL)
list(APPEND SOURCES "lvgl_tft/esp_lcd_backlight.c")
endif()
if(CONFIG_LV_I2C) if(CONFIG_LV_I2C)
list(APPEND SOURCES "lvgl_i2c/i2c_manager.c") list(APPEND SOURCES "lvgl_i2c/i2c_manager.c")
endif() endif()

View file

@ -910,51 +910,6 @@ menu "LVGL TFT Display controller"
help help
Configure the display Busy pin here. Configure the display Busy pin here.
config LV_ENABLE_BACKLIGHT_CONTROL
bool "Enable control of the display backlight by using an GPIO." if \
( LV_PREDEFINED_DISPLAY_NONE && ! ( LV_TFT_DISPLAY_CONTROLLER_SH1107 || LV_TFT_DISPLAY_CONTROLLER_SSD1306 ) ) \
|| LV_PREDEFINED_DISPLAY_RPI_MPI3501
default y if LV_PREDEFINED_DISPLAY_M5STACK
default n if LV_PREDEFINED_DISPLAY_M5CORE2
default y if LV_PREDEFINED_DISPLAY_WROVER4
default y if LV_PREDEFINED_DISPLAY_ERTFT0356
default y if LV_PREDEFINED_DISPLAY_TTGO
default y if LV_PREDEFINED_DISPLAY_TTGO_CAMERA_PLUS
default y if LV_PREDEFINED_DISPLAY_WT32_SC01
help
Enable controlling the display backlight using an GPIO
config LV_BACKLIGHT_ACTIVE_LVL
bool "Is backlight turn on with a HIGH (1) logic level?"
depends on LV_ENABLE_BACKLIGHT_CONTROL
default y if LV_PREDEFINED_DISPLAY_M5STACK
default y if LV_PREDEFINED_DISPLAY_ERTFT0356
default y if LV_PREDEFINED_DISPLAY_TTGO
default y if LV_PREDEFINED_DISPLAY_TTGO_CAMERA_PLUS
default y if LV_PREDEFINED_DISPLAY_WT32_SC01
help
Some backlights are turned on with a high signal, others held low.
If enabled, a value of 1 will be sent to the display to enable the backlight,
otherwise a 0 will be expected to enable it.
config LV_DISP_PIN_BCKL
int "GPIO for Backlight Control"
depends on LV_ENABLE_BACKLIGHT_CONTROL
default 23 if LV_PREDEFINED_PINS_38V1
default 26 if LV_PREDEFINED_PINS_38V4
default 32 if LV_PREDEFINED_DISPLAY_M5STACK
default 5 if LV_PREDEFINED_DISPLAY_WROVER4
default 2 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING
default 27 if LV_PREDEFINED_DISPLAY_ERTFT0356
default 0 if LV_PREDEFINED_PINS_TKOALA
default 4 if LV_PREDEFINED_DISPLAY_TTGO
default 2 if LV_PREDEFINED_DISPLAY_TTGO_CAMERA_PLUS
default 23 if LV_PREDEFINED_DISPLAY_WT32_SC01
default 27
help
Configure the display BCLK (LED) pin here.
endmenu endmenu
choice choice
@ -965,19 +920,86 @@ menu "LVGL TFT Display controller"
config LV_I2C_DISPLAY_PORT_0 config LV_I2C_DISPLAY_PORT_0
bool bool
prompt "I2C port 0" prompt "I2C port 0"
help help
I2C is shared peripheral managed by I2C Manager. In order to configure I2C Manager (pinout, etc.) see menu I2C is shared peripheral managed by I2C Manager. In order to configure I2C Manager (pinout, etc.) see menu
Component config->I2C Port Settings. Component config->I2C Port Settings.
config LV_I2C_DISPLAY_PORT_1 config LV_I2C_DISPLAY_PORT_1
bool bool
prompt "I2C port 1" prompt "I2C port 1"
help help
I2C is shared peripheral managed by I2C Manager. In order to configure I2C Manager (pinout, etc.) see menu I2C is shared peripheral managed by I2C Manager. In order to configure I2C Manager (pinout, etc.) see menu
Component config->I2C Port Settings. Component config->I2C Port Settings.
endchoice endchoice
choice
prompt "Backlight Control" if \
(! ( LV_TFT_DISPLAY_CONTROLLER_SH1107 || LV_TFT_DISPLAY_CONTROLLER_SSD1306 ) )
default LV_DISP_BACKLIGHT_SWITCH if LV_PREDEFINED_DISPLAY_M5STACK
default LV_DISP_BACKLIGHT_OFF if LV_PREDEFINED_DISPLAY_M5CORE2
default LV_DISP_BACKLIGHT_SWITCH if LV_PREDEFINED_DISPLAY_WROVER4
default LV_DISP_BACKLIGHT_SWITCH if LV_PREDEFINED_DISPLAY_ERTFT0356
default LV_DISP_BACKLIGHT_SWITCH if LV_PREDEFINED_DISPLAY_TTGO
default LV_DISP_BACKLIGHT_SWITCH if LV_PREDEFINED_DISPLAY_TTGO_CAMERA_PLUS
default LV_DISP_BACKLIGHT_SWITCH if LV_PREDEFINED_DISPLAY_WT32_SC01
default LV_DISP_BACKLIGHT_OFF
config LV_DISP_BACKLIGHT_OFF
bool
prompt "Not Used"
help
Display backlight is not controlled by this driver, must be hardwired in hardware.
config LV_DISP_BACKLIGHT_SWITCH
bool
prompt "Switch control"
help
Display backlight can be switched on or off.
config LV_DISP_BACKLIGHT_PWM
bool
prompt "PWM control"
help
Display backlight is controlled by pulse-width modulation, allowing brightness settings.
endchoice
config LV_BACKLIGHT_ACTIVE_LVL
bool "Is backlight turn on with a HIGH (1) logic level?" if \
( LV_PREDEFINED_DISPLAY_NONE && ! ( LV_TFT_DISPLAY_CONTROLLER_SH1107 || LV_TFT_DISPLAY_CONTROLLER_SSD1306 ) ) \
|| LV_PREDEFINED_DISPLAY_RPI_MPI3501
depends on !LV_DISP_BACKLIGHT_OFF
default y if LV_PREDEFINED_DISPLAY_M5STACK
default y if LV_PREDEFINED_DISPLAY_ERTFT0356
default y if LV_PREDEFINED_DISPLAY_TTGO
default y if LV_PREDEFINED_DISPLAY_TTGO_CAMERA_PLUS
default y if LV_PREDEFINED_DISPLAY_WT32_SC01
help
Some backlights are turned on with a high signal, others held low.
If enabled, a value of 1 will be sent to the display to enable the backlight,
otherwise a 0 will be expected to enable it.
config LV_DISP_PIN_BCKL
int "GPIO for Backlight Control" if \
( LV_PREDEFINED_DISPLAY_NONE && ! ( LV_TFT_DISPLAY_CONTROLLER_SH1107 || LV_TFT_DISPLAY_CONTROLLER_SSD1306 ) ) \
|| LV_PREDEFINED_DISPLAY_RPI_MPI3501
depends on !LV_DISP_BACKLIGHT_OFF
default 23 if LV_PREDEFINED_PINS_38V1
default 26 if LV_PREDEFINED_PINS_38V4
default 32 if LV_PREDEFINED_DISPLAY_M5STACK
default 5 if LV_PREDEFINED_DISPLAY_WROVER4
default 2 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING
default 27 if LV_PREDEFINED_DISPLAY_ERTFT0356
default 0 if LV_PREDEFINED_PINS_TKOALA
default 4 if LV_PREDEFINED_DISPLAY_TTGO
default 2 if LV_PREDEFINED_DISPLAY_TTGO_CAMERA_PLUS
default 23 if LV_PREDEFINED_DISPLAY_WT32_SC01
default 27
help
Configure the display BCLK (LED) pin here.
config LV_I2C config LV_I2C
bool bool
default y if LV_I2C_DISPLAY default y if LV_I2C_DISPLAY

View file

@ -4,8 +4,10 @@
#include "disp_driver.h" #include "disp_driver.h"
#include "disp_spi.h" #include "disp_spi.h"
#include "esp_lcd_backlight.h"
#include "sdkconfig.h"
void disp_driver_init(void) void *disp_driver_init(void)
{ {
#if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341 #if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341
ili9341_init(); ili9341_init();
@ -42,6 +44,34 @@ void disp_driver_init(void)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
ili9163c_init(); ili9163c_init();
#endif #endif
// We still use menuconfig for these settings
// It will be set up during runtime in the future
#ifndef CONFIG_LV_DISP_BACKLIGHT_OFF
const disp_backlight_config_t bckl_config = {
.gpio_num = CONFIG_LV_DISP_PIN_BCKL,
#if defined CONFIG_LV_DISP_BACKLIGHT_PWM
.pwm_control = true,
#else
.pwm_control = false,
#endif
#if defined CONFIG_LV_BACKLIGHT_ACTIVE_LVL
.output_invert = false, // Backlight on high
#else
.output_invert = true, // Backlight on low
#endif
.timer_idx = 0,
.channel_idx = 0 // @todo this prevents us from having two PWM controlled displays
};
const disp_backlight_config_t *bckl_config_p = &bckl_config;
#else
const disp_backlight_config_t *bckl_config_p = NULL;
#endif
disp_backlight_h bckl_handle = disp_backlight_new(bckl_config_p);
disp_backlight_set(bckl_handle, 100);
return bckl_handle;
} }
void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map) void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)

View file

@ -67,7 +67,7 @@ extern "C" {
**********************/ **********************/
/* Initialize display */ /* Initialize display */
void disp_driver_init(void); void *disp_driver_init(void);
/* Display flush callback */ /* Display flush callback */
void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);

View file

@ -8,51 +8,95 @@
*********************/ *********************/
#include "esp_lcd_backlight.h" #include "esp_lcd_backlight.h"
#include "driver/ledc.h" #include "driver/ledc.h"
#include "driver/gpio.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_rom_gpio.h" // for output signal inversion
static const char *TAG = "disp_brightness"; typedef struct {
bool pwm_control; // true: LEDC is used, false: GPIO is used
int index; // Either GPIO or LEDC channel
} disp_backlight_t;
void disp_brightness_control_enable(void) static const char *TAG = "disp_backlight";
disp_backlight_h disp_backlight_new(const disp_backlight_config_t *config)
{ {
/* if (config == NULL)
Configure LED (Backlight) pin as PWM for Brightness control. return NULL;
*/ disp_backlight_t *bckl_dev = calloc(1, sizeof(disp_backlight_t));
ledc_channel_config_t LCD_backlight_channel = { if (bckl_dev == NULL){
.gpio_num = DISP_PIN_BCKL, ESP_LOGW(TAG, "Could not create new LCD backlight instance");
.speed_mode = LEDC_LOW_SPEED_MODE, return NULL;
.channel = LEDC_CHANNEL_0, }
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER_0,
.duty = 0,
.hpoint = 0,
.flags.output_invert = 0
};
ledc_timer_config_t LCD_backlight_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.bit_num = LEDC_TIMER_10_BIT,
.timer_num = LEDC_TIMER_0,
.freq_hz = 5000,
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK( ledc_timer_config(&LCD_backlight_timer) ); if (config->pwm_control){
ESP_ERROR_CHECK( ledc_channel_config(&LCD_backlight_channel) ); // Configure LED (Backlight) pin as PWM for Brightness control.
bckl_dev->pwm_control = true;
bckl_dev->index = config->channel_idx;
const ledc_channel_config_t LCD_backlight_channel = {
.gpio_num = config->gpio_num,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = config->channel_idx,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = config->timer_idx,
.duty = 0,
.hpoint = 0,
.flags.output_invert = config->output_invert //@todo added only in recent IDF versions
};
const ledc_timer_config_t LCD_backlight_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.bit_num = LEDC_TIMER_10_BIT,
.timer_num = config->timer_idx,
.freq_hz = 5000,
.clk_cfg = LEDC_AUTO_CLK};
ESP_ERROR_CHECK(ledc_timer_config(&LCD_backlight_timer));
ESP_ERROR_CHECK(ledc_channel_config(&LCD_backlight_channel));
}
else
{
// Configure GPIO for output
bckl_dev->index = config->gpio_num;
gpio_pad_select_gpio(config->gpio_num);
ESP_ERROR_CHECK(gpio_set_direction(config->gpio_num, GPIO_MODE_OUTPUT));
esp_rom_gpio_connect_out_signal(config->gpio_num, SIG_GPIO_OUT_IDX, config->output_invert, false);
}
return (disp_backlight_h)bckl_dev;
} }
void disp_set_brightness(uint16_t brightness) void disp_backlight_set(disp_backlight_h bckl, int brightness_percent)
{ {
/* // Check input paramters
Set brightness. if (bckl == NULL)
0 -> Display off return;
100 -> Full brightness if (brightness_percent > 100)
NOTE: brightness value must be between 0 - 100 brightness_percent = 100;
*/ if (brightness_percent < 0)
if(brightness > 100) brightness_percent = 0;
{
ESP_LOGE(TAG, "Brightness value must be between 0 - 100"); disp_backlight_t *bckl_dev = (disp_backlight_t *) bckl;
return; ESP_LOGI(TAG, "Setting LCD backlight: %d%%", brightness_percent);
}
ESP_ERROR_CHECK( ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, brightness*10) ); if (bckl_dev->pwm_control) {
ESP_ERROR_CHECK( ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0) ); uint32_t duty_cycle = (1023 * brightness_percent) / 100; // LEDC resolution set to 10bits, thus: 100% = 1023
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, bckl_dev->index, duty_cycle));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, bckl_dev->index));
} else {
ESP_ERROR_CHECK(gpio_set_level(bckl_dev->index, brightness_percent));
}
}
void disp_backlight_delete(disp_backlight_h bckl)
{
if (bckl == NULL)
return;
disp_backlight_t *bckl_dev = (disp_backlight_t *) bckl;
if (bckl_dev->pwm_control) {
ledc_stop(LEDC_LOW_SPEED_MODE, bckl_dev->index, 0);
} else {
gpio_reset_pin(bckl_dev->index);
}
free (bckl);
} }

View file

@ -9,29 +9,58 @@
* INCLUDES * INCLUDES
*********************/ *********************/
#include <stdbool.h> #include <stdbool.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#ifdef __cplusplus
/********************* extern "C" { /* extern "C" */
* DEFINES
*********************/
#if CONFIG_LV_ENABLE_BACKLIGHT_CONTROL
#define DISP_PIN_BCKL CONFIG_LV_DISP_PIN_BCKL
#endif #endif
/********************** /**********************
* GLOBAL PROTOTYPES * GLOBAL PROTOTYPES
**********************/ **********************/
void disp_brightness_control_enable(void);
void disp_set_brightness(uint16_t brightness);
/**
* @brief Display backlight controller handle
*
*/
typedef void * disp_backlight_h;
/**
* @brief Configuration structure of backlight controller
*
*/
typedef struct {
bool pwm_control;
bool output_invert;
int gpio_num; // see gpio_num_t
// Relevant only for PWM controlled backlight
// Ignored for switch (ON/OFF) backlight control
int timer_idx; // ledc_timer_t
int channel_idx; // ledc_channel_t
} disp_backlight_config_t;
/**
* @brief Create new backlight controller
*
* @param[in] config Configuration structure of backlight controller
* @return Display backlight controller handle
*/
disp_backlight_h disp_backlight_new(const disp_backlight_config_t *config);
/**
* @brief Set backlight
*
* Brightness parameter can be 0-100 for PWM controlled backlight.
* GPIO controlled backlight (ON/OFF) is turned off witch value 0 and turned on with any positive value.
*
* @param bckl Backlight controller handle
* @param[in] brightness_percent Brightness in [%]
*/
void disp_backlight_set(disp_backlight_h bckl, int brightness_percent);
void disp_backlight_delete(disp_backlight_h bckl);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif
#endif /*ESP_LCD_BACKLIGHT_H*/ #endif /*ESP_LCD_BACKLIGHT_H*/