diff --git a/components/encoder/Kconfig b/components/encoder/Kconfig index d1990a0b..739c855e 100644 --- a/components/encoder/Kconfig +++ b/components/encoder/Kconfig @@ -25,4 +25,15 @@ menu "Rotary encoders" int "Long press timeout, us" default 500000 + config RE_ACCELERATION_MIN_CUTOFF + int "Minimum Acceleration cutoff time (ms)" + default 200 + help + At this time in milliseconds between rotary ticks we want to be at the minimum acceleration + + config RE_ACCELERATION_MAX_CUTOFF + int "Maximum Acceleration cutoff time (ms)" + default 4 + help + At this time in milliseconds between rotary ticks we want to be at the maximum acceleration endmenu diff --git a/components/encoder/encoder.c b/components/encoder/encoder.c index 4be63aa4..ad173387 100644 --- a/components/encoder/encoder.c +++ b/components/encoder/encoder.c @@ -128,13 +128,33 @@ inline static void read_encoder(rotary_encoder_t *re) re->store = (re->store << 4) | re->code; - if (re->store == 0xe817) inc = 1; - if (re->store == 0xd42b) inc = -1; + if ((re->store == 0xe817)||(re->store == 0x17e8)) inc = 1; + if ((re->store == 0xd42b)||(re->store == 0x2bd4)) inc = -1; if (inc) { - ev.type = RE_ET_CHANGED; ev.diff = inc; + if (re->acceleration.coeff > 1) + { + int64_t nowMicros = esp_timer_get_time(); + // at 200 ms, we want to have minimum acceleration + uint32_t accelerationMinCutoffMillis = CONFIG_RE_ACCELERATION_MIN_CUTOFF; + // at 4 ms, we want to have maximum acceleration + uint32_t accelerationMaxCutoffMillis = CONFIG_RE_ACCELERATION_MAX_CUTOFF; + uint32_t millisAfterLastMotion = (nowMicros - re->acceleration.last_time) / 1000u; + re->acceleration.last_time = nowMicros; + + if (millisAfterLastMotion < accelerationMinCutoffMillis) + { + if (millisAfterLastMotion < accelerationMaxCutoffMillis) + { + millisAfterLastMotion = accelerationMaxCutoffMillis; // limit to maximum acceleration + } + ev.diff = inc * ((int32_t)(re->acceleration.coeff / millisAfterLastMotion) == 0 ? 1 : (int32_t)(re->acceleration.coeff / millisAfterLastMotion)); + } + } + + ev.type = RE_ET_CHANGED; xQueueSendToBack(_queue, &ev, 0); } } @@ -252,3 +272,18 @@ esp_err_t rotary_encoder_remove(rotary_encoder_t *re) xSemaphoreGive(mutex); return ESP_ERR_NOT_FOUND; } + +esp_err_t rotary_encoder_enable_acceleration(rotary_encoder_t *re, uint16_t coeff) +{ + CHECK_ARG(re); + re->acceleration.coeff = coeff; + re->acceleration.last_time = esp_timer_get_time(); + return ESP_OK; +} + +esp_err_t rotary_encoder_disable_acceleration(rotary_encoder_t *re) +{ + CHECK_ARG(re); + re->acceleration.coeff = 0; + return ESP_OK; +} diff --git a/components/encoder/encoder.h b/components/encoder/encoder.h index 1268e983..a7d21259 100644 --- a/components/encoder/encoder.h +++ b/components/encoder/encoder.h @@ -57,6 +57,11 @@ typedef enum { RE_BTN_LONG_PRESSED = 2 //!< Button currently long pressed } rotary_encoder_btn_state_t; +//Rotary encoder acceleration variables +typedef struct { + int64_t last_time; + uint16_t coeff; +} rotary_encoder_acceleration_t; /** * Rotary encoder descriptor */ @@ -68,6 +73,7 @@ typedef struct size_t index; uint64_t btn_pressed_time_us; rotary_encoder_btn_state_t btn_state; + rotary_encoder_acceleration_t acceleration; } rotary_encoder_t; /** @@ -115,6 +121,23 @@ esp_err_t rotary_encoder_add(rotary_encoder_t *re); */ esp_err_t rotary_encoder_remove(rotary_encoder_t *re); +/** + * @brief Enable acceleration on the rotary encoder + * + * @param re Encoder descriptor + * @param coeff Acceleration coefficient. Higher value means faster acceleration + * @return esp_err_t + */ +esp_err_t rotary_encoder_enable_acceleration(rotary_encoder_t *re, uint16_t coeff); + +/** + * @brief Disable acceleration on the rotary encoder + * + * @param re Encoder descriptor + * @return `ESP_OK` on success + */ +esp_err_t rotary_encoder_disable_acceleration(rotary_encoder_t *re); + #ifdef __cplusplus } #endif diff --git a/examples/encoder/default/main/main.c b/examples/encoder/default/main/main.c index db200f20..141ae8c6 100644 --- a/examples/encoder/default/main/main.c +++ b/examples/encoder/default/main/main.c @@ -61,9 +61,13 @@ void test(void *arg) break; case RE_ET_BTN_CLICKED: ESP_LOGI(TAG, "Button clicked"); + rotary_encoder_enable_acceleration(&re, 100); + ESP_LOGI(TAG, "Acceleration enabled"); break; case RE_ET_BTN_LONG_PRESSED: ESP_LOGI(TAG, "Looooong pressed button"); + rotary_encoder_disable_acceleration(&re); + ESP_LOGI(TAG, "Acceleration disabled"); break; case RE_ET_CHANGED: val += e.diff;