Skip to content

Commit 75464fd

Browse files
Fix: knob loses diff event (BSP-592) (#450)
* 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 <98878239+espzav@users.noreply.github.com>
1 parent d515c54 commit 75464fd

File tree

2 files changed

+111
-30
lines changed

2 files changed

+111
-30
lines changed

components/esp_lvgl_port/src/lvgl8/esp_lvgl_port_knob.c

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -19,7 +19,8 @@ typedef struct {
1919
knob_handle_t knob_handle; /* Encoder knob handlers */
2020
button_handle_t btn_handle; /* Encoder button handlers */
2121
lv_indev_drv_t indev_drv; /* LVGL input device driver */
22-
bool btn_enter; /* Encoder button enter state */
22+
bool btn_enter; /* Encoder button enter state */
23+
int32_t diff; /* Encoder diff */
2324
} lvgl_port_encoder_ctx_t;
2425

2526
/*******************************************************************************
@@ -29,6 +30,9 @@ typedef struct {
2930
static void lvgl_port_encoder_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data);
3031
static void lvgl_port_encoder_btn_down_handler(void *arg, void *arg2);
3132
static void lvgl_port_encoder_btn_up_handler(void *arg, void *arg2);
33+
static void lvgl_port_encoder_left_handler(void *arg, void *arg2);
34+
static void lvgl_port_encoder_right_handler(void *arg, void *arg2);
35+
static int32_t lvgl_port_calculate_diff(knob_handle_t knob, knob_event_t event);
3236

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

61+
ESP_ERROR_CHECK(iot_knob_register_cb(encoder_ctx->knob_handle, KNOB_LEFT, lvgl_port_encoder_left_handler, encoder_ctx));
62+
ESP_ERROR_CHECK(iot_knob_register_cb(encoder_ctx->knob_handle, KNOB_RIGHT, lvgl_port_encoder_right_handler, encoder_ctx));
63+
5764
/* Encoder Enter */
5865
if (encoder_cfg->encoder_enter != NULL) {
5966
encoder_ctx->btn_handle = iot_button_create(encoder_cfg->encoder_enter);
@@ -64,6 +71,7 @@ lv_indev_t *lvgl_port_add_encoder(const lvgl_port_encoder_cfg_t *encoder_cfg)
6471
ESP_ERROR_CHECK(iot_button_register_cb(encoder_ctx->btn_handle, BUTTON_PRESS_UP, lvgl_port_encoder_btn_up_handler, encoder_ctx));
6572

6673
encoder_ctx->btn_enter = false;
74+
encoder_ctx->diff = 0;
6775

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

119127
static void lvgl_port_encoder_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
120128
{
121-
static int32_t last_v = 0;
122-
123129
assert(indev_drv);
124130
lvgl_port_encoder_ctx_t *ctx = (lvgl_port_encoder_ctx_t *)indev_drv->user_data;
125131
assert(ctx);
126132

127-
int32_t invd = iot_knob_get_count_value(ctx->knob_handle);
128-
knob_event_t event = iot_knob_get_event(ctx->knob_handle);
129-
130-
if (last_v ^ invd) {
131-
last_v = invd;
132-
data->enc_diff = (KNOB_LEFT == event) ? (-1) : ((KNOB_RIGHT == event) ? (1) : (0));
133-
} else {
134-
data->enc_diff = 0;
135-
}
133+
data->enc_diff = ctx->diff;
136134
data->state = (true == ctx->btn_enter) ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
135+
ctx->diff = 0;
137136
}
138137

139138
static void lvgl_port_encoder_btn_down_handler(void *arg, void *arg2)
@@ -159,3 +158,47 @@ static void lvgl_port_encoder_btn_up_handler(void *arg, void *arg2)
159158
}
160159
}
161160
}
161+
162+
static void lvgl_port_encoder_left_handler(void *arg, void *arg2)
163+
{
164+
lvgl_port_encoder_ctx_t *ctx = (lvgl_port_encoder_ctx_t *) arg2;
165+
knob_handle_t knob = (knob_handle_t)arg;
166+
if (ctx && knob) {
167+
/* LEFT */
168+
if (knob == ctx->knob_handle) {
169+
int32_t diff = lvgl_port_calculate_diff(knob, KNOB_LEFT);
170+
ctx->diff = (ctx->diff > 0) ? diff : ctx->diff + diff;
171+
}
172+
}
173+
}
174+
175+
static void lvgl_port_encoder_right_handler(void *arg, void *arg2)
176+
{
177+
lvgl_port_encoder_ctx_t *ctx = (lvgl_port_encoder_ctx_t *) arg2;
178+
knob_handle_t knob = (knob_handle_t)arg;
179+
if (ctx && knob) {
180+
/* RIGHT */
181+
if (knob == ctx->knob_handle) {
182+
int32_t diff = lvgl_port_calculate_diff(knob, KNOB_RIGHT);
183+
ctx->diff = (ctx->diff < 0) ? diff : ctx->diff + diff;
184+
}
185+
}
186+
}
187+
188+
static int32_t lvgl_port_calculate_diff(knob_handle_t knob, knob_event_t event)
189+
{
190+
static int32_t last_v = 0;
191+
192+
int32_t diff = 0;
193+
int32_t invd = iot_knob_get_count_value(knob);
194+
195+
if (last_v ^ invd) {
196+
197+
diff = (int32_t)((uint32_t)invd - (uint32_t)last_v);
198+
diff += (event == KNOB_RIGHT && invd < last_v) ? CONFIG_KNOB_HIGH_LIMIT :
199+
(event == KNOB_LEFT && invd > last_v) ? CONFIG_KNOB_LOW_LIMIT : 0;
200+
last_v = invd;
201+
}
202+
203+
return diff;
204+
}

components/esp_lvgl_port/src/lvgl9/esp_lvgl_port_knob.c

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -20,6 +20,7 @@ typedef struct {
2020
button_handle_t btn_handle; /* Encoder button handlers */
2121
lv_indev_t *indev; /* LVGL input device driver */
2222
bool btn_enter; /* Encoder button enter state */
23+
int32_t diff; /* Encoder diff */
2324
} lvgl_port_encoder_ctx_t;
2425

2526
/*******************************************************************************
@@ -29,7 +30,9 @@ typedef struct {
2930
static void lvgl_port_encoder_read(lv_indev_t *indev_drv, lv_indev_data_t *data);
3031
static void lvgl_port_encoder_btn_down_handler(void *arg, void *arg2);
3132
static void lvgl_port_encoder_btn_up_handler(void *arg, void *arg2);
32-
static void lvgl_port_encoder_knob_handler(void *arg, void *arg2);
33+
static void lvgl_port_encoder_left_handler(void *arg, void *arg2);
34+
static void lvgl_port_encoder_right_handler(void *arg, void *arg2);
35+
static int32_t lvgl_port_calculate_diff(knob_handle_t knob, knob_event_t event);
3336

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

57-
ESP_ERROR_CHECK(iot_knob_register_cb(encoder_ctx->knob_handle, KNOB_LEFT, lvgl_port_encoder_knob_handler, encoder_ctx));
58-
ESP_ERROR_CHECK(iot_knob_register_cb(encoder_ctx->knob_handle, KNOB_RIGHT, lvgl_port_encoder_knob_handler, encoder_ctx));
60+
ESP_ERROR_CHECK(iot_knob_register_cb(encoder_ctx->knob_handle, KNOB_LEFT, lvgl_port_encoder_left_handler, encoder_ctx));
61+
ESP_ERROR_CHECK(iot_knob_register_cb(encoder_ctx->knob_handle, KNOB_RIGHT, lvgl_port_encoder_right_handler, encoder_ctx));
5962
}
6063

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

7073
encoder_ctx->btn_enter = false;
74+
encoder_ctx->diff = 0;
7175

7276
lvgl_port_lock(0);
7377
/* Register a encoder input device */
@@ -130,21 +134,13 @@ esp_err_t lvgl_port_remove_encoder(lv_indev_t *encoder)
130134

131135
static void lvgl_port_encoder_read(lv_indev_t *indev_drv, lv_indev_data_t *data)
132136
{
133-
static int32_t last_v = 0;
134137
assert(indev_drv);
135138
lvgl_port_encoder_ctx_t *ctx = (lvgl_port_encoder_ctx_t *)lv_indev_get_driver_data(indev_drv);
136139
assert(ctx);
137140

138-
int32_t invd = iot_knob_get_count_value(ctx->knob_handle);
139-
knob_event_t event = iot_knob_get_event(ctx->knob_handle);
140-
141-
if (last_v ^ invd) {
142-
last_v = invd;
143-
data->enc_diff = (KNOB_LEFT == event) ? (-1) : ((KNOB_RIGHT == event) ? (1) : (0));
144-
} else {
145-
data->enc_diff = 0;
146-
}
141+
data->enc_diff = ctx->diff;
147142
data->state = (true == ctx->btn_enter) ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
143+
ctx->diff = 0;
148144
}
149145

150146
static void lvgl_port_encoder_btn_down_handler(void *arg, void *arg2)
@@ -177,9 +173,51 @@ static void lvgl_port_encoder_btn_up_handler(void *arg, void *arg2)
177173
lvgl_port_task_wake(LVGL_PORT_EVENT_TOUCH, ctx->indev);
178174
}
179175

180-
static void lvgl_port_encoder_knob_handler(void *arg, void *arg2)
176+
static void lvgl_port_encoder_left_handler(void *arg, void *arg2)
181177
{
182178
lvgl_port_encoder_ctx_t *ctx = (lvgl_port_encoder_ctx_t *) arg2;
183-
/* Wake LVGL task, if needed */
184-
lvgl_port_task_wake(LVGL_PORT_EVENT_TOUCH, ctx->indev);
179+
knob_handle_t knob = (knob_handle_t)arg;
180+
if (ctx && knob) {
181+
/* LEFT */
182+
if (knob == ctx->knob_handle) {
183+
int32_t diff = lvgl_port_calculate_diff(knob, KNOB_LEFT);
184+
ctx->diff = (ctx->diff > 0) ? diff : ctx->diff + diff;
185+
}
186+
/* Wake LVGL task, if needed */
187+
lvgl_port_task_wake(LVGL_PORT_EVENT_TOUCH, ctx->indev);
188+
}
189+
}
190+
191+
static void lvgl_port_encoder_right_handler(void *arg, void *arg2)
192+
{
193+
lvgl_port_encoder_ctx_t *ctx = (lvgl_port_encoder_ctx_t *) arg2;
194+
knob_handle_t knob = (knob_handle_t)arg;
195+
if (ctx && knob) {
196+
/* RIGHT */
197+
if (knob == ctx->knob_handle) {
198+
int32_t diff = lvgl_port_calculate_diff(knob, KNOB_RIGHT);
199+
ctx->diff = (ctx->diff < 0) ? diff : ctx->diff + diff;
200+
}
201+
/* Wake LVGL task, if needed */
202+
lvgl_port_task_wake(LVGL_PORT_EVENT_TOUCH, ctx->indev);
203+
}
204+
}
205+
206+
207+
static int32_t lvgl_port_calculate_diff(knob_handle_t knob, knob_event_t event)
208+
{
209+
static int32_t last_v = 0;
210+
211+
int32_t diff = 0;
212+
int32_t invd = iot_knob_get_count_value(knob);
213+
214+
if (last_v ^ invd) {
215+
216+
diff = (int32_t)((uint32_t)invd - (uint32_t)last_v);
217+
diff += (event == KNOB_RIGHT && invd < last_v) ? CONFIG_KNOB_HIGH_LIMIT :
218+
(event == KNOB_LEFT && invd > last_v) ? CONFIG_KNOB_LOW_LIMIT : 0;
219+
last_v = invd;
220+
}
221+
222+
return diff;
185223
}

0 commit comments

Comments
 (0)