Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: knob loses diff event (BSP-592) #450

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/esp_lvgl_port/idf_component.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: "2.4.3"
version: "2.4.4"
description: ESP LVGL port
url: https://github.com/espressif/esp-bsp/tree/master/components/esp_lvgl_port
dependencies:
Expand Down
69 changes: 56 additions & 13 deletions components/esp_lvgl_port/src/lvgl8/esp_lvgl_port_knob.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -19,7 +19,8 @@ typedef struct {
knob_handle_t knob_handle; /* Encoder knob handlers */
button_handle_t btn_handle; /* Encoder button handlers */
lv_indev_drv_t indev_drv; /* LVGL input device driver */
bool btn_enter; /* Encoder button enter state */
bool btn_enter; /* Encoder button enter state */
int32_t diff; /* Encoder diff */
} lvgl_port_encoder_ctx_t;

/*******************************************************************************
Expand All @@ -29,6 +30,9 @@ typedef struct {
static void lvgl_port_encoder_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data);
static void lvgl_port_encoder_btn_down_handler(void *arg, void *arg2);
static void lvgl_port_encoder_btn_up_handler(void *arg, void *arg2);
static void lvgl_port_encoder_left_handler(void *arg, void *arg2);
static void lvgl_port_encoder_right_handler(void *arg, void *arg2);
static int32_t lvgl_port_calculate_diff(knob_handle_t knob, knob_event_t event);

/*******************************************************************************
* Public API functions
Expand All @@ -54,6 +58,9 @@ lv_indev_t *lvgl_port_add_encoder(const lvgl_port_encoder_cfg_t *encoder_cfg)
ESP_GOTO_ON_FALSE(encoder_ctx->knob_handle, ESP_ERR_NO_MEM, err, TAG, "Not enough memory for knob create!");
}

ESP_ERROR_CHECK(iot_knob_register_cb(encoder_ctx->knob_handle, KNOB_LEFT, lvgl_port_encoder_left_handler, encoder_ctx));
ESP_ERROR_CHECK(iot_knob_register_cb(encoder_ctx->knob_handle, KNOB_RIGHT, lvgl_port_encoder_right_handler, encoder_ctx));

/* Encoder Enter */
if (encoder_cfg->encoder_enter != NULL) {
encoder_ctx->btn_handle = iot_button_create(encoder_cfg->encoder_enter);
Expand All @@ -64,6 +71,7 @@ lv_indev_t *lvgl_port_add_encoder(const lvgl_port_encoder_cfg_t *encoder_cfg)
ESP_ERROR_CHECK(iot_button_register_cb(encoder_ctx->btn_handle, BUTTON_PRESS_UP, lvgl_port_encoder_btn_up_handler, encoder_ctx));

encoder_ctx->btn_enter = false;
encoder_ctx->diff = 0;

/* Register a encoder input device */
lv_indev_drv_init(&encoder_ctx->indev_drv);
Expand Down Expand Up @@ -118,22 +126,13 @@ esp_err_t lvgl_port_remove_encoder(lv_indev_t *encoder)

static void lvgl_port_encoder_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
{
static int32_t last_v = 0;

assert(indev_drv);
lvgl_port_encoder_ctx_t *ctx = (lvgl_port_encoder_ctx_t *)indev_drv->user_data;
assert(ctx);

int32_t invd = iot_knob_get_count_value(ctx->knob_handle);
knob_event_t event = iot_knob_get_event(ctx->knob_handle);

if (last_v ^ invd) {
last_v = invd;
data->enc_diff = (KNOB_LEFT == event) ? (-1) : ((KNOB_RIGHT == event) ? (1) : (0));
} else {
data->enc_diff = 0;
}
data->enc_diff = ctx->diff;
data->state = (true == ctx->btn_enter) ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
ctx->diff = 0;
}

static void lvgl_port_encoder_btn_down_handler(void *arg, void *arg2)
Expand All @@ -159,3 +158,47 @@ static void lvgl_port_encoder_btn_up_handler(void *arg, void *arg2)
}
}
}

static void lvgl_port_encoder_left_handler(void *arg, void *arg2)
{
lvgl_port_encoder_ctx_t *ctx = (lvgl_port_encoder_ctx_t *) arg2;
knob_handle_t knob = (knob_handle_t)arg;
if (ctx && knob) {
/* LEFT */
if (knob == ctx->knob_handle) {
int32_t diff = lvgl_port_calculate_diff(knob, KNOB_LEFT);
ctx->diff = (ctx->diff > 0) ? diff : ctx->diff + diff;
}
}
}

static void lvgl_port_encoder_right_handler(void *arg, void *arg2)
{
lvgl_port_encoder_ctx_t *ctx = (lvgl_port_encoder_ctx_t *) arg2;
knob_handle_t knob = (knob_handle_t)arg;
if (ctx && knob) {
/* RIGHT */
if (knob == ctx->knob_handle) {
int32_t diff = lvgl_port_calculate_diff(knob, KNOB_RIGHT);
ctx->diff = (ctx->diff < 0) ? diff : ctx->diff + diff;
}
}
}

static int32_t lvgl_port_calculate_diff(knob_handle_t knob, knob_event_t event)
{
static int32_t last_v = 0;

int32_t diff = 0;
int32_t invd = iot_knob_get_count_value(knob);

if (last_v ^ invd) {

diff = (int32_t)((uint32_t)invd - (uint32_t)last_v);
diff += (event == KNOB_RIGHT && invd < last_v) ? CONFIG_KNOB_HIGH_LIMIT :
(event == KNOB_LEFT && invd > last_v) ? CONFIG_KNOB_LOW_LIMIT : 0;
last_v = invd;
}

return diff;
}
72 changes: 55 additions & 17 deletions components/esp_lvgl_port/src/lvgl9/esp_lvgl_port_knob.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -20,6 +20,7 @@ typedef struct {
button_handle_t btn_handle; /* Encoder button handlers */
lv_indev_t *indev; /* LVGL input device driver */
bool btn_enter; /* Encoder button enter state */
int32_t diff; /* Encoder diff */
} lvgl_port_encoder_ctx_t;

/*******************************************************************************
Expand All @@ -29,7 +30,9 @@ typedef struct {
static void lvgl_port_encoder_read(lv_indev_t *indev_drv, lv_indev_data_t *data);
static void lvgl_port_encoder_btn_down_handler(void *arg, void *arg2);
static void lvgl_port_encoder_btn_up_handler(void *arg, void *arg2);
static void lvgl_port_encoder_knob_handler(void *arg, void *arg2);
static void lvgl_port_encoder_left_handler(void *arg, void *arg2);
static void lvgl_port_encoder_right_handler(void *arg, void *arg2);
static int32_t lvgl_port_calculate_diff(knob_handle_t knob, knob_event_t event);

/*******************************************************************************
* Public API functions
Expand All @@ -54,8 +57,8 @@ lv_indev_t *lvgl_port_add_encoder(const lvgl_port_encoder_cfg_t *encoder_cfg)
encoder_ctx->knob_handle = iot_knob_create(encoder_cfg->encoder_a_b);
ESP_GOTO_ON_FALSE(encoder_ctx->knob_handle, ESP_ERR_NO_MEM, err, TAG, "Not enough memory for knob create!");

ESP_ERROR_CHECK(iot_knob_register_cb(encoder_ctx->knob_handle, KNOB_LEFT, lvgl_port_encoder_knob_handler, encoder_ctx));
ESP_ERROR_CHECK(iot_knob_register_cb(encoder_ctx->knob_handle, KNOB_RIGHT, lvgl_port_encoder_knob_handler, encoder_ctx));
ESP_ERROR_CHECK(iot_knob_register_cb(encoder_ctx->knob_handle, KNOB_LEFT, lvgl_port_encoder_left_handler, encoder_ctx));
ESP_ERROR_CHECK(iot_knob_register_cb(encoder_ctx->knob_handle, KNOB_RIGHT, lvgl_port_encoder_right_handler, encoder_ctx));
}

/* Encoder Enter */
Expand All @@ -68,6 +71,7 @@ lv_indev_t *lvgl_port_add_encoder(const lvgl_port_encoder_cfg_t *encoder_cfg)
ESP_ERROR_CHECK(iot_button_register_cb(encoder_ctx->btn_handle, BUTTON_PRESS_UP, lvgl_port_encoder_btn_up_handler, encoder_ctx));

encoder_ctx->btn_enter = false;
encoder_ctx->diff = 0;

lvgl_port_lock(0);
/* Register a encoder input device */
Expand Down Expand Up @@ -130,21 +134,13 @@ esp_err_t lvgl_port_remove_encoder(lv_indev_t *encoder)

static void lvgl_port_encoder_read(lv_indev_t *indev_drv, lv_indev_data_t *data)
{
static int32_t last_v = 0;
assert(indev_drv);
lvgl_port_encoder_ctx_t *ctx = (lvgl_port_encoder_ctx_t *)lv_indev_get_user_data(indev_drv);
assert(ctx);

int32_t invd = iot_knob_get_count_value(ctx->knob_handle);
knob_event_t event = iot_knob_get_event(ctx->knob_handle);

if (last_v ^ invd) {
last_v = invd;
data->enc_diff = (KNOB_LEFT == event) ? (-1) : ((KNOB_RIGHT == event) ? (1) : (0));
} else {
data->enc_diff = 0;
}
data->enc_diff = ctx->diff;
data->state = (true == ctx->btn_enter) ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
ctx->diff = 0;
}

static void lvgl_port_encoder_btn_down_handler(void *arg, void *arg2)
Expand Down Expand Up @@ -177,9 +173,51 @@ static void lvgl_port_encoder_btn_up_handler(void *arg, void *arg2)
lvgl_port_task_wake(LVGL_PORT_EVENT_TOUCH, ctx->indev);
}

static void lvgl_port_encoder_knob_handler(void *arg, void *arg2)
static void lvgl_port_encoder_left_handler(void *arg, void *arg2)
{
lvgl_port_encoder_ctx_t *ctx = (lvgl_port_encoder_ctx_t *) arg2;
/* Wake LVGL task, if needed */
lvgl_port_task_wake(LVGL_PORT_EVENT_TOUCH, ctx->indev);
knob_handle_t knob = (knob_handle_t)arg;
if (ctx && knob) {
/* LEFT */
if (knob == ctx->knob_handle) {
int32_t diff = lvgl_port_calculate_diff(knob, KNOB_LEFT);
ctx->diff = (ctx->diff > 0) ? diff : ctx->diff + diff;
}
/* Wake LVGL task, if needed */
lvgl_port_task_wake(LVGL_PORT_EVENT_TOUCH, ctx->indev);
}
}

static void lvgl_port_encoder_right_handler(void *arg, void *arg2)
{
lvgl_port_encoder_ctx_t *ctx = (lvgl_port_encoder_ctx_t *) arg2;
knob_handle_t knob = (knob_handle_t)arg;
if (ctx && knob) {
/* RIGHT */
if (knob == ctx->knob_handle) {
int32_t diff = lvgl_port_calculate_diff(knob, KNOB_RIGHT);
ctx->diff = (ctx->diff < 0) ? diff : ctx->diff + diff;
}
/* Wake LVGL task, if needed */
lvgl_port_task_wake(LVGL_PORT_EVENT_TOUCH, ctx->indev);
}
}


static int32_t lvgl_port_calculate_diff(knob_handle_t knob, knob_event_t event)
{
static int32_t last_v = 0;

int32_t diff = 0;
int32_t invd = iot_knob_get_count_value(knob);

if (last_v ^ invd) {

diff = (int32_t)((uint32_t)invd - (uint32_t)last_v);
diff += (event == KNOB_RIGHT && invd < last_v) ? CONFIG_KNOB_HIGH_LIMIT :
(event == KNOB_LEFT && invd > last_v) ? CONFIG_KNOB_LOW_LIMIT : 0;
last_v = invd;
}

return diff;
}
Loading