3 Commits

Author SHA1 Message Date
72fbd49641 Merge commit 'be29ff31f7ef00bcb59bf2bd1ee2e87ccef20584' into wip 2025-12-25 11:17:09 +03:00
b614e67b6f wip: 2025-12-25 11:14:04 +03:00
4368ac9845 wip: 2025-12-24 19:54:21 +03:00
5 changed files with 74 additions and 3126 deletions

View File

@@ -4,10 +4,6 @@
1. [ESP32 ESP-IDF v5.5.1](https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32/index.html) 1. [ESP32 ESP-IDF v5.5.1](https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32/index.html)
## SAST Tools
[PVS-Studio](https://pvs-studio.com/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) - static analyzer for C, C++, C#, and Java code.
## Features ## Features
1. Support some encoders on one device. 1. Support some encoders on one device.
@@ -15,11 +11,6 @@
## Attention ## Attention
1. If the button is not used, specify any free GPIO in the initial configuration. 1. If the button is not used, specify any free GPIO in the initial configuration.
2. For correct operation, please enable the following settings in the menuconfig:
```text
GPIO_CTRL_FUNC_IN_IRAM
```
## Using ## Using
@@ -56,18 +47,18 @@ void app_main(void)
esp_log_level_set("zh_encoder", ESP_LOG_ERROR); esp_log_level_set("zh_encoder", ESP_LOG_ERROR);
esp_event_loop_create_default(); esp_event_loop_create_default();
esp_event_handler_instance_register(ZH_ENCODER, ESP_EVENT_ANY_ID, &zh_encoder_event_handler, NULL, NULL); esp_event_handler_instance_register(ZH_ENCODER, ESP_EVENT_ANY_ID, &zh_encoder_event_handler, NULL, NULL);
zh_encoder_init_config_t config = ZH_ENCODER_INIT_CONFIG_DEFAULT(); zh_encoder_init_config_t encoder_init_config = ZH_ENCODER_INIT_CONFIG_DEFAULT();
config.task_priority = 5; encoder_init_config.task_priority = 5;
config.stack_size = configMINIMAL_STACK_SIZE; encoder_init_config.stack_size = configMINIMAL_STACK_SIZE;
config.queue_size = 5; encoder_init_config.queue_size = 5;
config.a_gpio_number = GPIO_NUM_27; encoder_init_config.a_gpio_number = GPIO_NUM_27;
config.b_gpio_number = GPIO_NUM_26; encoder_init_config.b_gpio_number = GPIO_NUM_26;
config.s_gpio_number = GPIO_NUM_17; encoder_init_config.s_gpio_number = GPIO_NUM_17;
config.encoder_min_value = 0; encoder_init_config.encoder_min_value = 0;
config.encoder_max_value = 100; encoder_init_config.encoder_max_value = 100;
config.encoder_step = 0.1; encoder_init_config.encoder_step = 0.1;
config.encoder_number = ENCODER_NUMBER; encoder_init_config.encoder_number = ENCODER_NUMBER;
zh_encoder_init(&config, &encoder_handle); zh_encoder_init(&encoder_init_config, &encoder_handle);
zh_encoder_get(&encoder_handle, &encoder_position); zh_encoder_get(&encoder_handle, &encoder_position);
printf("Encoder position %0.2f.\n", encoder_position); printf("Encoder position %0.2f.\n", encoder_position);
for (;;) for (;;)

File diff suppressed because it is too large Load Diff

View File

@@ -39,34 +39,34 @@ extern "C"
*/ */
typedef struct typedef struct
{ {
double encoder_step; /*!< Encoder step. @note Must be greater than 0. */ uint8_t task_priority; /*!< Task priority for the encoder isr processing. @note Minimum value is 1. */
double encoder_min_value; /*!< Encoder min value. @note Must be less than encoder_max_value. */ uint16_t stack_size; /*!< Stack size for task for the encoder isr processing processing. @note The minimum size is configMINIMAL_STACK_SIZE. */
double encoder_max_value; /*!< Encoder max value. @note Must be greater than encoder_min_value. */ uint8_t queue_size; /*!< Queue size for task for the encoder processing. @note Minimum value is 1. */
uint8_t task_priority; /*!< Task priority for the encoder isr processing. @note Minimum value is 1. */ uint8_t a_gpio_number; /*!< Encoder A GPIO number. */
uint8_t queue_size; /*!< Queue size for task for the encoder processing. @note Minimum value is 1. */ uint8_t b_gpio_number; /*!< Encoder B GPIO number. */
uint8_t a_gpio_number; /*!< Encoder A GPIO number. */ uint8_t s_gpio_number; /*!< Encoder button GPIO number. */
uint8_t b_gpio_number; /*!< Encoder B GPIO number. */ int32_t encoder_min_value; /*!< Encoder min value. @note Must be less than encoder_max_value. */
uint8_t s_gpio_number; /*!< Encoder button GPIO number. */ int32_t encoder_max_value; /*!< Encoder max value. @note Must be greater than encoder_min_value. */
uint8_t encoder_number; /*!< Unique encoder number. @note Must be greater than 0. */ double encoder_step; /*!< Encoder step. @note Must be greater than 0. */
uint16_t stack_size; /*!< Stack size for task for the encoder isr processing processing. @note The minimum size is configMINIMAL_STACK_SIZE. */ uint8_t encoder_number; /*!< Unique encoder number. */
} zh_encoder_init_config_t; } zh_encoder_init_config_t;
/** /**
* @brief Encoder handle. * @brief Encoder handle.
*/ */
typedef struct // -V802 typedef struct
{ {
double encoder_step; /*!< Encoder step. */ uint8_t a_gpio_number; /*!< Encoder A GPIO number. */
double encoder_position; /*!< Encoder position. */ uint8_t b_gpio_number; /*!< Encoder B GPIO number. */
double encoder_min_value; /*!< Encoder min value. */ uint8_t s_gpio_number; /*!< Encoder button GPIO number. */
double encoder_max_value; /*!< Encoder max value. */ int32_t encoder_min_value; /*!< Encoder min value. */
uint8_t a_gpio_number; /*!< Encoder A GPIO number. */ int32_t encoder_max_value; /*!< Encoder max value. */
uint8_t b_gpio_number; /*!< Encoder B GPIO number. */ double encoder_step; /*!< Encoder step. */
uint8_t s_gpio_number; /*!< Encoder button GPIO number. */ double encoder_position; /*!< Encoder position. */
uint8_t encoder_number; /*!< Encoder unique number. */ bool button_status; /*!< Encoder button status. */
uint8_t encoder_state; /*!< Encoder internal state. */ uint8_t encoder_number; /*!< Encoder unique number. */
bool button_status; /*!< Encoder button status. */ uint8_t encoder_state; /*!< Encoder internal state. */
bool is_initialized; /*!< Encoder initialization flag. */ bool is_initialized; /*!< Encoder initialization flag. */
} zh_encoder_handle_t; } zh_encoder_handle_t;
/** /**
@@ -88,8 +88,8 @@ extern "C"
*/ */
typedef struct typedef struct
{ {
double encoder_position; /*!< Encoder current position. */
uint8_t encoder_number; /*!< Encoder unique number. */ uint8_t encoder_number; /*!< Encoder unique number. */
double encoder_position; /*!< Encoder current position. */
bool button_status; /*!< Encoder button status. */ bool button_status; /*!< Encoder button status. */
} zh_encoder_event_on_isr_t; } zh_encoder_event_on_isr_t;
@@ -116,20 +116,6 @@ extern "C"
*/ */
esp_err_t zh_encoder_deinit(zh_encoder_handle_t *handle); esp_err_t zh_encoder_deinit(zh_encoder_handle_t *handle);
/**
* @brief Reinitialize encoder (change min, max and step values).
*
* @note The encoder will be set to the position (encoder_min_value + encoder_max_value)/2.
*
* @param[in, out] handle Pointer to unique encoder handle.
* @param[in] min Encoder min value. @note Must be less than encoder_max_value.
* @param[in] max Encoder max value. @note Must be greater than encoder_min_value.
* @param[in] step Encoder step. @note Must be greater than 0.
*
* @return ESP_OK if success or an error code otherwise.
*/
esp_err_t zh_encoder_reinit(zh_encoder_handle_t *handle, double min, double max, double step);
/** /**
* @brief Set encoder position. * @brief Set encoder position.
* *

View File

@@ -1 +1 @@
1.5.0 1.3.0

View File

@@ -29,13 +29,11 @@ static const uint8_t _encoder_matrix[7][4] = {
TaskHandle_t zh_encoder = NULL; TaskHandle_t zh_encoder = NULL;
static QueueHandle_t _queue_handle = NULL; static QueueHandle_t _queue_handle = NULL;
static portMUX_TYPE _spinlock = portMUX_INITIALIZER_UNLOCKED;
static volatile uint64_t _prev_us = 0; static volatile uint64_t _prev_us = 0;
static uint8_t _encoder_counter = 0; static uint8_t _encoder_counter = 0;
static bool _is_prev_gpio_isr_handler = false; static bool _is_prev_gpio_isr_handler = false;
static zh_encoder_stats_t _stats = {0}; static zh_encoder_stats_t _stats = {0};
static uint8_t _encoder_number_matrix[10] = {0};
static esp_err_t _zh_encoder_validate_config(const zh_encoder_init_config_t *config); static esp_err_t _zh_encoder_validate_config(const zh_encoder_init_config_t *config);
static esp_err_t _zh_encoder_gpio_init(const zh_encoder_init_config_t *config, zh_encoder_handle_t *handle); static esp_err_t _zh_encoder_gpio_init(const zh_encoder_init_config_t *config, zh_encoder_handle_t *handle);
@@ -46,7 +44,7 @@ static void _zh_encoder_isr_processing_task(void *pvParameter);
ESP_EVENT_DEFINE_BASE(ZH_ENCODER); ESP_EVENT_DEFINE_BASE(ZH_ENCODER);
esp_err_t zh_encoder_init(const zh_encoder_init_config_t *config, zh_encoder_handle_t *handle) // -V2008 esp_err_t zh_encoder_init(const zh_encoder_init_config_t *config, zh_encoder_handle_t *handle)
{ {
ZH_LOGI("Encoder initialization started."); ZH_LOGI("Encoder initialization started.");
ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder initialization failed. Invalid argument."); ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder initialization failed. Invalid argument.");
@@ -57,29 +55,40 @@ esp_err_t zh_encoder_init(const zh_encoder_init_config_t *config, zh_encoder_han
err = _zh_encoder_resources_init(config); err = _zh_encoder_resources_init(config);
if (_is_prev_gpio_isr_handler == true) if (_is_prev_gpio_isr_handler == true)
{ {
ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number); if (config->s_gpio_number != GPIO_NUM_MAX)
gpio_isr_handler_remove((gpio_num_t)config->s_gpio_number); gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number); {
gpio_reset_pin((gpio_num_t)config->s_gpio_number), "Encoder initialization failed. Resources initialization failed."); ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->s_gpio_number);
gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number); gpio_reset_pin((gpio_num_t)config->s_gpio_number), "Encoder initialization failed. Resources initialization failed.");
}
else
{
ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number); gpio_reset_pin((gpio_num_t)config->a_gpio_number);
gpio_reset_pin((gpio_num_t)config->b_gpio_number), "Encoder initialization failed. Resources initialization failed.");
}
} }
else else
{ {
ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number); if (config->s_gpio_number != GPIO_NUM_MAX)
gpio_isr_handler_remove((gpio_num_t)config->s_gpio_number); gpio_uninstall_isr_service(); gpio_reset_pin((gpio_num_t)config->a_gpio_number); {
gpio_reset_pin((gpio_num_t)config->b_gpio_number); gpio_reset_pin((gpio_num_t)config->s_gpio_number), "Encoder initialization failed. Resources initialization failed."); ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->s_gpio_number);
gpio_uninstall_isr_service(); gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number); gpio_reset_pin((gpio_num_t)config->s_gpio_number), "Encoder initialization failed. Resources initialization failed.");
}
else
{
ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number); gpio_uninstall_isr_service();
gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number), "Encoder initialization failed. Resources initialization failed.");
}
} }
err = _zh_encoder_task_init(config); err = _zh_encoder_task_init(config);
if (_is_prev_gpio_isr_handler == true) if (_is_prev_gpio_isr_handler == true)
{ {
ZH_ERROR_CHECK(err == ESP_OK, err, vQueueDelete(_queue_handle); _queue_handle = NULL; gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); ZH_ERROR_CHECK(err == ESP_OK, err, vQueueDelete(_queue_handle); _queue_handle = NULL; gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number);
gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number); gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number), gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number), "Encoder initialization failed. Processing task initialization failed.");
"Encoder initialization failed. Processing task initialization failed.");
} }
else else
{ {
ZH_ERROR_CHECK(err == ESP_OK, err, vQueueDelete(_queue_handle); _queue_handle = NULL; gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); ZH_ERROR_CHECK(err == ESP_OK, err, vQueueDelete(_queue_handle); _queue_handle = NULL; gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number);
gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->s_gpio_number); gpio_uninstall_isr_service(); gpio_uninstall_isr_service(); gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number), "Encoder initialization failed. Processing task initialization failed.");
gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number); gpio_reset_pin((gpio_num_t)config->s_gpio_number),
"Encoder initialization failed. Processing task initialization failed.");
} }
handle->a_gpio_number = config->a_gpio_number; handle->a_gpio_number = config->a_gpio_number;
handle->b_gpio_number = config->b_gpio_number; handle->b_gpio_number = config->b_gpio_number;
@@ -92,14 +101,6 @@ esp_err_t zh_encoder_init(const zh_encoder_init_config_t *config, zh_encoder_han
handle->encoder_position = (handle->encoder_min_value + handle->encoder_max_value) / 2; handle->encoder_position = (handle->encoder_min_value + handle->encoder_max_value) / 2;
handle->is_initialized = true; handle->is_initialized = true;
++_encoder_counter; ++_encoder_counter;
for (uint8_t i = 0; i < sizeof(_encoder_number_matrix); ++i)
{
if (_encoder_number_matrix[i] == 0)
{
_encoder_number_matrix[i] = handle->encoder_number;
break;
}
}
ZH_LOGI("Encoder initialization completed successfully."); ZH_LOGI("Encoder initialization completed successfully.");
return ESP_OK; return ESP_OK;
} }
@@ -126,44 +127,17 @@ esp_err_t zh_encoder_deinit(zh_encoder_handle_t *handle)
} }
handle->is_initialized = false; handle->is_initialized = false;
--_encoder_counter; --_encoder_counter;
for (uint8_t i = 0; i < sizeof(_encoder_number_matrix); ++i)
{
if (_encoder_number_matrix[i] == handle->encoder_number)
{
_encoder_number_matrix[i] = 0;
break;
}
}
ZH_LOGI("Encoder deinitialization completed successfully."); ZH_LOGI("Encoder deinitialization completed successfully.");
return ESP_OK; return ESP_OK;
} }
esp_err_t zh_encoder_reinit(zh_encoder_handle_t *handle, double min, double max, double step) // -V2008
{
ZH_LOGI("Encoder reinitialization started.");
ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder reinitialization failed. Invalid argument.");
ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Encoder reinitialization failed. Encoder not initialized.");
ZH_ERROR_CHECK(max > min, ESP_ERR_INVALID_ARG, NULL, "Encoder reinitialization failed. Invalid encoder min/max value.");
ZH_ERROR_CHECK(step > 0, ESP_ERR_INVALID_ARG, NULL, "Encoder reinitialization failed. Invalid encoder step.");
taskENTER_CRITICAL(&_spinlock);
handle->encoder_min_value = min;
handle->encoder_max_value = max;
handle->encoder_step = step;
handle->encoder_position = (handle->encoder_min_value + handle->encoder_max_value) / 2;
taskEXIT_CRITICAL(&_spinlock);
ZH_LOGI("Encoder reinitialization completed successfully.");
return ESP_OK;
}
esp_err_t zh_encoder_set(zh_encoder_handle_t *handle, double position) esp_err_t zh_encoder_set(zh_encoder_handle_t *handle, double position)
{ {
ZH_LOGI("Encoder set position started."); ZH_LOGI("Encoder set position started.");
ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder set position failed. Invalid argument."); ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder set position failed. Invalid argument.");
ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Encoder set position failed. Encoder not initialized."); ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Encoder set position failed. Encoder not initialized.");
ZH_ERROR_CHECK(position <= handle->encoder_max_value && position >= handle->encoder_min_value, ESP_ERR_INVALID_ARG, NULL, "Encoder set position failed. Invalid argument."); ZH_ERROR_CHECK(position <= handle->encoder_max_value && position >= handle->encoder_min_value, ESP_ERR_INVALID_ARG, NULL, "Encoder set position failed. Invalid argument.");
taskENTER_CRITICAL(&_spinlock);
handle->encoder_position = position; handle->encoder_position = position;
taskEXIT_CRITICAL(&_spinlock);
ZH_LOGI("Encoder set position completed successfully."); ZH_LOGI("Encoder set position completed successfully.");
return ESP_OK; return ESP_OK;
} }
@@ -183,9 +157,7 @@ esp_err_t zh_encoder_reset(zh_encoder_handle_t *handle)
ZH_LOGI("Encoder reset started."); ZH_LOGI("Encoder reset started.");
ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder reset failed. Invalid argument."); ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder reset failed. Invalid argument.");
ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Encoder reset failed. Encoder not initialized."); ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Encoder reset failed. Encoder not initialized.");
taskENTER_CRITICAL(&_spinlock);
handle->encoder_position = (handle->encoder_min_value + handle->encoder_max_value) / 2; handle->encoder_position = (handle->encoder_min_value + handle->encoder_max_value) / 2;
taskEXIT_CRITICAL(&_spinlock);
ZH_LOGI("Encoder reset completed successfully."); ZH_LOGI("Encoder reset completed successfully.");
return ESP_OK; return ESP_OK;
} }
@@ -204,22 +176,17 @@ void zh_encoder_reset_stats(void)
ZH_LOGI("Error statistic reset successfully."); ZH_LOGI("Error statistic reset successfully.");
} }
static esp_err_t _zh_encoder_validate_config(const zh_encoder_init_config_t *config) // -V2008 static esp_err_t _zh_encoder_validate_config(const zh_encoder_init_config_t *config)
{ {
ZH_ERROR_CHECK(config != NULL, ESP_ERR_INVALID_ARG, NULL, "Invalid configuration."); ZH_ERROR_CHECK(config != NULL, ESP_ERR_INVALID_ARG, NULL, "Invalid configuration.");
ZH_ERROR_CHECK(config->task_priority >= 1 && config->stack_size >= configMINIMAL_STACK_SIZE, ESP_ERR_INVALID_ARG, NULL, "Invalid task settings."); ZH_ERROR_CHECK(config->task_priority >= 1 && config->stack_size >= configMINIMAL_STACK_SIZE, ESP_ERR_INVALID_ARG, NULL, "Invalid task settings.");
ZH_ERROR_CHECK(config->queue_size >= 1, ESP_ERR_INVALID_ARG, NULL, "Invalid queue size."); ZH_ERROR_CHECK(config->queue_size >= 1, ESP_ERR_INVALID_ARG, NULL, "Invalid queue size.");
ZH_ERROR_CHECK(config->encoder_max_value > config->encoder_min_value, ESP_ERR_INVALID_ARG, NULL, "Invalid encoder min/max value."); ZH_ERROR_CHECK(config->encoder_max_value > config->encoder_min_value, ESP_ERR_INVALID_ARG, NULL, "Invalid encoder min/max value.");
ZH_ERROR_CHECK(config->encoder_step > 0, ESP_ERR_INVALID_ARG, NULL, "Invalid encoder step."); ZH_ERROR_CHECK(config->encoder_step > 0, ESP_ERR_INVALID_ARG, NULL, "Invalid encoder step.");
ZH_ERROR_CHECK(config->encoder_number > 0, ESP_ERR_INVALID_ARG, NULL, "Invalid encoder number.");
for (uint8_t i = 0; i < sizeof(_encoder_number_matrix); ++i)
{
ZH_ERROR_CHECK(config->encoder_number != _encoder_number_matrix[i], ESP_ERR_INVALID_ARG, NULL, "Encoder number already present.");
}
return ESP_OK; return ESP_OK;
} }
static esp_err_t _zh_encoder_gpio_init(const zh_encoder_init_config_t *config, zh_encoder_handle_t *handle) // -V2008 static esp_err_t _zh_encoder_gpio_init(const zh_encoder_init_config_t *config, zh_encoder_handle_t *handle)
{ {
ZH_ERROR_CHECK(config->a_gpio_number < GPIO_NUM_MAX && config->b_gpio_number < GPIO_NUM_MAX && config->s_gpio_number < GPIO_NUM_MAX, ESP_ERR_INVALID_ARG, NULL, "Invalid GPIO number.") ZH_ERROR_CHECK(config->a_gpio_number < GPIO_NUM_MAX && config->b_gpio_number < GPIO_NUM_MAX && config->s_gpio_number < GPIO_NUM_MAX, ESP_ERR_INVALID_ARG, NULL, "Invalid GPIO number.")
ZH_ERROR_CHECK(config->a_gpio_number != config->b_gpio_number, ESP_ERR_INVALID_ARG, NULL, "Encoder A and B GPIO is same.") ZH_ERROR_CHECK(config->a_gpio_number != config->b_gpio_number, ESP_ERR_INVALID_ARG, NULL, "Encoder A and B GPIO is same.")
@@ -234,47 +201,33 @@ static esp_err_t _zh_encoder_gpio_init(const zh_encoder_init_config_t *config, z
if (_encoder_counter == 0) if (_encoder_counter == 0)
{ {
err = gpio_install_isr_service(ESP_INTR_FLAG_LOWMED); err = gpio_install_isr_service(ESP_INTR_FLAG_LOWMED);
ZH_ERROR_CHECK(err == ESP_OK || err == ESP_ERR_INVALID_STATE, err, gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number); ZH_ERROR_CHECK(err == ESP_OK || err == ESP_ERR_INVALID_STATE, err, gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number), "Failed install isr service.");
gpio_reset_pin((gpio_num_t)config->s_gpio_number), "Failed install isr service.");
if (err == ESP_ERR_INVALID_STATE) if (err == ESP_ERR_INVALID_STATE)
{ {
_is_prev_gpio_isr_handler = true; _is_prev_gpio_isr_handler = true;
} }
} }
err = gpio_isr_handler_add((gpio_num_t)config->a_gpio_number, _zh_encoder_isr_handler, handle); err = gpio_isr_handler_add(config->a_gpio_number, _zh_encoder_isr_handler, handle);
ZH_ERROR_CHECK(err == ESP_OK, err, gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number), "Interrupt initialization failed.");
err = gpio_isr_handler_add(config->b_gpio_number, _zh_encoder_isr_handler, handle);
if (_is_prev_gpio_isr_handler == true) if (_is_prev_gpio_isr_handler == true)
{ {
ZH_ERROR_CHECK(err == ESP_OK, err, gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number); ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number), "Interrupt initialization failed.");
gpio_reset_pin((gpio_num_t)config->s_gpio_number), "Interrupt initialization failed.");
} }
else else
{ {
ZH_ERROR_CHECK(err == ESP_OK, err, gpio_uninstall_isr_service(); gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number); ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_uninstall_isr_service(); gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number), "Interrupt initialization failed.");
gpio_reset_pin((gpio_num_t)config->s_gpio_number), "Interrupt initialization failed.");
} }
err = gpio_isr_handler_add((gpio_num_t)config->b_gpio_number, _zh_encoder_isr_handler, handle); err = gpio_isr_handler_add(config->s_gpio_number, _zh_encoder_isr_handler, handle);
if (_is_prev_gpio_isr_handler == true)
{
ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->a_gpio_number);
gpio_reset_pin((gpio_num_t)config->b_gpio_number); gpio_reset_pin((gpio_num_t)config->s_gpio_number), "Interrupt initialization failed.");
}
else
{
ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_uninstall_isr_service(); gpio_reset_pin((gpio_num_t)config->a_gpio_number);
gpio_reset_pin((gpio_num_t)config->b_gpio_number); gpio_reset_pin((gpio_num_t)config->s_gpio_number), "Interrupt initialization failed.");
}
err = gpio_isr_handler_add((gpio_num_t)config->s_gpio_number, _zh_encoder_isr_handler, handle);
if (_is_prev_gpio_isr_handler == true) if (_is_prev_gpio_isr_handler == true)
{ {
ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number); ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number);
gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number); gpio_reset_pin((gpio_num_t)config->s_gpio_number), gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number), "Interrupt initialization failed.");
"Interrupt initialization failed.");
} }
else else
{ {
ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number); ZH_ERROR_CHECK(err == ESP_OK, err, gpio_isr_handler_remove((gpio_num_t)config->a_gpio_number); gpio_isr_handler_remove((gpio_num_t)config->b_gpio_number); gpio_uninstall_isr_service();
gpio_uninstall_isr_service(); gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number); gpio_reset_pin((gpio_num_t)config->a_gpio_number); gpio_reset_pin((gpio_num_t)config->b_gpio_number), "Interrupt initialization failed.");
gpio_reset_pin((gpio_num_t)config->s_gpio_number), "Interrupt initialization failed.");
} }
return ESP_OK; return ESP_OK;
} }
@@ -315,8 +268,7 @@ static void IRAM_ATTR _zh_encoder_isr_handler(void *arg)
} }
} }
_prev_us = _current_us; _prev_us = _current_us;
encoder_handle->encoder_state = _encoder_matrix[encoder_handle->encoder_state & 0x0F] encoder_handle->encoder_state = _encoder_matrix[encoder_handle->encoder_state & 0x0F][(gpio_get_level((gpio_num_t)encoder_handle->b_gpio_number) << 1) | gpio_get_level((gpio_num_t)encoder_handle->a_gpio_number)];
[(gpio_get_level((gpio_num_t)encoder_handle->b_gpio_number) << 1) | gpio_get_level((gpio_num_t)encoder_handle->a_gpio_number)];
switch (encoder_handle->encoder_state & 0x30) switch (encoder_handle->encoder_state & 0x30)
{ {
case ZH_ENCODER_DIRECTION_CW: case ZH_ENCODER_DIRECTION_CW: