Skip to content

Commit

Permalink
Fix: knob loses diff event (BSP-592) (#450)
Browse files Browse the repository at this point in the history
* Fix: knob loses diff event

* fix: knob lost event

* fix: calculate diff in callback

* fix: If the direction is reversed, clear the count

* Update version

---------

Co-authored-by: Vilem Zavodny <[email protected]>
  • Loading branch information
espressif2022 and espzav authored Jan 28, 2025
1 parent d515c54 commit 75464fd
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 30 deletions.
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_driver_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;
}

0 comments on commit 75464fd

Please sign in to comment.