|
|
|
@@ -17,6 +17,7 @@
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
#include "driver/gpio.h"
|
|
|
|
|
#include "driver/ledc.h"
|
|
|
|
|
#include "driver/spi_master.h"
|
|
|
|
|
#include "esp_attr.h"
|
|
|
|
|
#include "esp_check.h"
|
|
|
|
@@ -58,6 +59,12 @@
|
|
|
|
|
#define LCD_DIRECT_LAST_FRAME_EXTRA_HOLD_MS 200U
|
|
|
|
|
#define LCD_DIRECT_BASIC_FACE_FRAME_HOLD_MS 100U
|
|
|
|
|
#define LCD_DIRECT_BASIC_FACE_LAST_FRAME_HOLD_MS 100U
|
|
|
|
|
#define LCD_DIRECT_BACKLIGHT_PWM_FREQUENCY_HZ 20000U
|
|
|
|
|
#define LCD_DIRECT_BACKLIGHT_PWM_DUTY_RESOLUTION LEDC_TIMER_10_BIT
|
|
|
|
|
#define LCD_DIRECT_BACKLIGHT_PWM_DUTY_MAX ((1U << 10U) - 1U)
|
|
|
|
|
#define LCD_DIRECT_BACKLIGHT_PWM_TIMER LEDC_TIMER_0
|
|
|
|
|
#define LCD_DIRECT_BACKLIGHT_PWM_CHANNEL LEDC_CHANNEL_0
|
|
|
|
|
#define LCD_DIRECT_BACKLIGHT_LOCK_TIMEOUT_MS 100U
|
|
|
|
|
|
|
|
|
|
#define LCD_CMD_MADCTL 0x36
|
|
|
|
|
#define LCD_CMD_RAMCTRL 0xB0
|
|
|
|
@@ -133,6 +140,7 @@ static const lcd_direct_init_cmd_t s_st7789_init_cmds[] = {
|
|
|
|
|
static esp_lcd_panel_io_handle_t s_panel_io;
|
|
|
|
|
static esp_lcd_panel_handle_t s_panel;
|
|
|
|
|
static SemaphoreHandle_t s_lock;
|
|
|
|
|
static SemaphoreHandle_t s_backlight_lock;
|
|
|
|
|
static SemaphoreHandle_t s_completion_sem;
|
|
|
|
|
static SemaphoreHandle_t s_preheat_done_sem;
|
|
|
|
|
static SemaphoreHandle_t s_transfer_done_sem;
|
|
|
|
@@ -465,10 +473,49 @@ static esp_err_t lcd_direct_get_png_image(const char *path,
|
|
|
|
|
return ESP_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t lcd_direct_backlight_duty(uint8_t brightness_percent)
|
|
|
|
|
{
|
|
|
|
|
uint32_t duty = ((uint32_t)brightness_percent * LCD_DIRECT_BACKLIGHT_PWM_DUTY_MAX + 50U) / 100U;
|
|
|
|
|
#if !CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH
|
|
|
|
|
duty = LCD_DIRECT_BACKLIGHT_PWM_DUTY_MAX - duty;
|
|
|
|
|
#endif
|
|
|
|
|
return duty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static esp_err_t lcd_direct_backlight_init(void)
|
|
|
|
|
{
|
|
|
|
|
const ledc_timer_config_t timer_config = {
|
|
|
|
|
.speed_mode = LEDC_LOW_SPEED_MODE,
|
|
|
|
|
.duty_resolution = LCD_DIRECT_BACKLIGHT_PWM_DUTY_RESOLUTION,
|
|
|
|
|
.timer_num = LCD_DIRECT_BACKLIGHT_PWM_TIMER,
|
|
|
|
|
.freq_hz = LCD_DIRECT_BACKLIGHT_PWM_FREQUENCY_HZ,
|
|
|
|
|
.clk_cfg = LEDC_AUTO_CLK,
|
|
|
|
|
};
|
|
|
|
|
ESP_RETURN_ON_ERROR(ledc_timer_config(&timer_config), TAG, "backlight PWM timer config failed");
|
|
|
|
|
|
|
|
|
|
const ledc_channel_config_t channel_config = {
|
|
|
|
|
.gpio_num = CONFIG_TQ_SCREEN_BACKLIGHT_GPIO,
|
|
|
|
|
.speed_mode = LEDC_LOW_SPEED_MODE,
|
|
|
|
|
.channel = LCD_DIRECT_BACKLIGHT_PWM_CHANNEL,
|
|
|
|
|
.intr_type = LEDC_INTR_DISABLE,
|
|
|
|
|
.timer_sel = LCD_DIRECT_BACKLIGHT_PWM_TIMER,
|
|
|
|
|
.duty = lcd_direct_backlight_duty(CONFIG_TQ_SCREEN_BACKLIGHT_BRIGHTNESS_PERCENT),
|
|
|
|
|
.hpoint = 0,
|
|
|
|
|
};
|
|
|
|
|
ESP_RETURN_ON_ERROR(ledc_channel_config(&channel_config), TAG, "backlight PWM channel config failed");
|
|
|
|
|
|
|
|
|
|
ESP_LOGI(TAG,
|
|
|
|
|
"Backlight PWM initialized gpio=%d frequency=%uHz brightness=%d%% active_high=%d",
|
|
|
|
|
CONFIG_TQ_SCREEN_BACKLIGHT_GPIO,
|
|
|
|
|
(unsigned)LCD_DIRECT_BACKLIGHT_PWM_FREQUENCY_HZ,
|
|
|
|
|
CONFIG_TQ_SCREEN_BACKLIGHT_BRIGHTNESS_PERCENT,
|
|
|
|
|
CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH ? 1 : 0);
|
|
|
|
|
return ESP_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static esp_err_t lcd_direct_gpio_init(void)
|
|
|
|
|
{
|
|
|
|
|
uint64_t pin_mask = (1ULL << CONFIG_TQ_SCREEN_BACKLIGHT_GPIO) |
|
|
|
|
|
(1ULL << CONFIG_TQ_SCREEN_DC_GPIO);
|
|
|
|
|
uint64_t pin_mask = (1ULL << CONFIG_TQ_SCREEN_DC_GPIO);
|
|
|
|
|
if (CONFIG_TQ_SCREEN_RESET_PIN >= 0) {
|
|
|
|
|
pin_mask |= (1ULL << CONFIG_TQ_SCREEN_RESET_PIN);
|
|
|
|
|
}
|
|
|
|
@@ -482,13 +529,11 @@ static esp_err_t lcd_direct_gpio_init(void)
|
|
|
|
|
};
|
|
|
|
|
ESP_RETURN_ON_ERROR(gpio_config(&gpio_config_data), TAG, "gpio config failed");
|
|
|
|
|
|
|
|
|
|
gpio_set_level(CONFIG_TQ_SCREEN_BACKLIGHT_GPIO,
|
|
|
|
|
CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH ? 1 : 0);
|
|
|
|
|
gpio_set_level(CONFIG_TQ_SCREEN_DC_GPIO, 0);
|
|
|
|
|
if (CONFIG_TQ_SCREEN_RESET_PIN >= 0) {
|
|
|
|
|
gpio_set_level(CONFIG_TQ_SCREEN_RESET_PIN, 1);
|
|
|
|
|
}
|
|
|
|
|
return ESP_OK;
|
|
|
|
|
return lcd_direct_backlight_init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static esp_err_t lcd_direct_panel_init(void)
|
|
|
|
@@ -1301,6 +1346,11 @@ esp_err_t lcd_direct_init_device(void)
|
|
|
|
|
|
|
|
|
|
s_lock = xSemaphoreCreateMutex();
|
|
|
|
|
ESP_RETURN_ON_FALSE(s_lock != NULL, ESP_ERR_NO_MEM, TAG, "lock create failed");
|
|
|
|
|
s_backlight_lock = xSemaphoreCreateMutex();
|
|
|
|
|
ESP_RETURN_ON_FALSE(s_backlight_lock != NULL,
|
|
|
|
|
ESP_ERR_NO_MEM,
|
|
|
|
|
TAG,
|
|
|
|
|
"backlight lock create failed");
|
|
|
|
|
s_completion_sem = xSemaphoreCreateBinary();
|
|
|
|
|
ESP_RETURN_ON_FALSE(s_completion_sem != NULL, ESP_ERR_NO_MEM, TAG, "completion sem create failed");
|
|
|
|
|
s_preheat_done_sem = xSemaphoreCreateBinary();
|
|
|
|
@@ -1331,6 +1381,38 @@ esp_err_t lcd_direct_init_device(void)
|
|
|
|
|
return ESP_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
esp_err_t lcd_direct_set_backlight_brightness(uint8_t brightness_percent)
|
|
|
|
|
{
|
|
|
|
|
ESP_RETURN_ON_FALSE(brightness_percent <= 100U,
|
|
|
|
|
ESP_ERR_INVALID_ARG,
|
|
|
|
|
TAG,
|
|
|
|
|
"backlight brightness must be between 0 and 100 percent");
|
|
|
|
|
ESP_RETURN_ON_FALSE(s_initialized && s_backlight_lock != NULL,
|
|
|
|
|
ESP_ERR_INVALID_STATE,
|
|
|
|
|
TAG,
|
|
|
|
|
"LCD backlight is not initialized");
|
|
|
|
|
ESP_RETURN_ON_FALSE(xSemaphoreTake(s_backlight_lock,
|
|
|
|
|
pdMS_TO_TICKS(LCD_DIRECT_BACKLIGHT_LOCK_TIMEOUT_MS)) == pdTRUE,
|
|
|
|
|
ESP_ERR_TIMEOUT,
|
|
|
|
|
TAG,
|
|
|
|
|
"backlight lock timed out");
|
|
|
|
|
|
|
|
|
|
esp_err_t err = ledc_set_duty(LEDC_LOW_SPEED_MODE,
|
|
|
|
|
LCD_DIRECT_BACKLIGHT_PWM_CHANNEL,
|
|
|
|
|
lcd_direct_backlight_duty(brightness_percent));
|
|
|
|
|
if (err == ESP_OK) {
|
|
|
|
|
err = ledc_update_duty(LEDC_LOW_SPEED_MODE, LCD_DIRECT_BACKLIGHT_PWM_CHANNEL);
|
|
|
|
|
}
|
|
|
|
|
xSemaphoreGive(s_backlight_lock);
|
|
|
|
|
|
|
|
|
|
if (err == ESP_OK) {
|
|
|
|
|
ESP_LOGI(TAG, "Backlight brightness set to %u%%", (unsigned)brightness_percent);
|
|
|
|
|
} else {
|
|
|
|
|
ESP_LOGE(TAG, "Backlight brightness update failed: %s", esp_err_to_name(err));
|
|
|
|
|
}
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lcd_direct_start_render_loop(void)
|
|
|
|
|
{
|
|
|
|
|
if (!s_initialized) {
|
|
|
|
|