This commit is contained in:
2025-06-14 08:33:02 +03:00
parent 1b872f8b82
commit db0e997aad
2 changed files with 167 additions and 10 deletions

View File

@@ -23,6 +23,33 @@ extern "C"
{ {
#endif #endif
typedef int32_t rotary_encoder_position_t;
// /**
// * @brief Enum representing the direction of rotation.
// */
typedef enum
{
ROTARY_ENCODER_DIRECTION_NOT_SET = 0, ///< Direction not yet known (stationary since reset)
ROTARY_ENCODER_DIRECTION_CLOCKWISE,
ROTARY_ENCODER_DIRECTION_COUNTER_CLOCKWISE,
} rotary_encoder_direction_t;
// // Used internally
// ///@cond INTERNAL
#define TABLE_COLS 4
typedef uint8_t table_row_t[TABLE_COLS];
// ///@endcond
// /**
// * @brief Struct represents the current state of the device in terms of incremental position and direction of last movement
// */
typedef struct
{
rotary_encoder_position_t position; ///< Numerical position since reset. This value increments on clockwise rotation, and decrements on counter-clockewise rotation. Counts full or half steps depending on mode. Set to zero on reset.
rotary_encoder_direction_t direction; ///< Direction of last movement. Set to NOT_SET on reset.
} rotary_encoder_state_t;
typedef struct // Structure for initial initialization of encoder. typedef struct // Structure for initial initialization of encoder.
{ {
uint8_t task_priority; // Task priority for the encoder isr processing. @note It is not recommended to set a value less than 10. uint8_t task_priority; // Task priority for the encoder isr processing. @note It is not recommended to set a value less than 10.
@@ -47,6 +74,9 @@ extern "C"
uint8_t encoder_number; // Encoder unique number. uint8_t encoder_number; // Encoder unique number.
bool is_initialized; // Encoder initialization flag. bool is_initialized; // Encoder initialization flag.
const table_row_t *table; ///< Pointer to active state transition table
uint8_t table_state; ///< Internal state
volatile rotary_encoder_state_t state; ///< Device state
} zh_encoder_handle_t; } zh_encoder_handle_t;
ESP_EVENT_DECLARE_BASE(ZH_ENCODER); ESP_EVENT_DECLARE_BASE(ZH_ENCODER);
@@ -115,9 +145,9 @@ extern "C"
// typedef int32_t rotary_encoder_position_t; // typedef int32_t rotary_encoder_position_t;
// /** // // /**
// * @brief Enum representing the direction of rotation. // // * @brief Enum representing the direction of rotation.
// */ // // */
// typedef enum // typedef enum
// { // {
// ROTARY_ENCODER_DIRECTION_NOT_SET = 0, ///< Direction not yet known (stationary since reset) // ROTARY_ENCODER_DIRECTION_NOT_SET = 0, ///< Direction not yet known (stationary since reset)
@@ -125,15 +155,15 @@ extern "C"
// ROTARY_ENCODER_DIRECTION_COUNTER_CLOCKWISE, // ROTARY_ENCODER_DIRECTION_COUNTER_CLOCKWISE,
// } rotary_encoder_direction_t; // } rotary_encoder_direction_t;
// // Used internally // // // Used internally
// ///@cond INTERNAL // // ///@cond INTERNAL
// #define TABLE_COLS 4 // #define TABLE_COLS 4
// typedef uint8_t table_row_t[TABLE_COLS]; // typedef uint8_t table_row_t[TABLE_COLS];
// ///@endcond // // ///@endcond
// /** // // /**
// * @brief Struct represents the current state of the device in terms of incremental position and direction of last movement // // * @brief Struct represents the current state of the device in terms of incremental position and direction of last movement
// */ // // */
// typedef struct // typedef struct
// { // {
// rotary_encoder_position_t position; ///< Numerical position since reset. This value increments on clockwise rotation, and decrements on counter-clockewise rotation. Counts full or half steps depending on mode. Set to zero on reset. // rotary_encoder_position_t position; ///< Numerical position since reset. This value increments on clockwise rotation, and decrements on counter-clockewise rotation. Counts full or half steps depending on mode. Set to zero on reset.

View File

@@ -104,9 +104,15 @@ esp_err_t zh_encoder_init(const zh_encoder_init_config_t *config, zh_encoder_han
{ {
_zh_encoder_validate_config(config); _zh_encoder_validate_config(config);
_zh_encoder_gpio_init(config); _zh_encoder_gpio_init(config);
handle->a_gpio_number = config->a_gpio_number;
handle->b_gpio_number = config->b_gpio_number;
_zh_encoder_configure_interrupts(config, handle); _zh_encoder_configure_interrupts(config, handle);
_zh_encoder_init_resources(config); _zh_encoder_init_resources(config);
_zh_encoder_create_task(config); _zh_encoder_create_task(config);
handle->table = &_encoder_matrix[0]; // enable_half_step ? &_ttable_half[0] : &_ttable_full[0];
handle->table_state = R_START;
handle->state.position = 0;
handle->state.direction = ROTARY_ENCODER_DIRECTION_NOT_SET;
return ESP_OK; return ESP_OK;
} }
@@ -365,6 +371,8 @@ static esp_err_t _zh_encoder_configure_interrupts(const zh_encoder_init_config_t
ZH_ENCODER_CHECK(err == ESP_OK, err, "Interrupt initialization failed."); ZH_ENCODER_CHECK(err == ESP_OK, err, "Interrupt initialization failed.");
err = gpio_isr_handler_add(config->b_gpio_number, _zh_encoder_isr_handler, handle); err = gpio_isr_handler_add(config->b_gpio_number, _zh_encoder_isr_handler, handle);
ZH_ENCODER_CHECK(err == ESP_OK, err, "Interrupt initialization failed."); ZH_ENCODER_CHECK(err == ESP_OK, err, "Interrupt initialization failed.");
// printf("queue.b_gpio_number %d\n", handle->b_gpio_number);
// printf("queue.q_gpio_number %d\n", handle->a_gpio_number);
return ESP_OK; return ESP_OK;
} }
@@ -397,8 +405,36 @@ static esp_err_t _zh_encoder_create_task(const zh_encoder_init_config_t *config)
static void _zh_encoder_isr_handler(void *arg) static void _zh_encoder_isr_handler(void *arg)
{ {
zh_encoder_handle_t *queue = (zh_encoder_handle_t *)arg;
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR(_queue_handle, arg, &xHigherPriorityTaskWoken); uint8_t pin_state = (gpio_get_level(queue->b_gpio_number) << 1) | gpio_get_level(queue->a_gpio_number);
// printf("pin_state %d\n", pin_state);
queue->table_state = queue->table[queue->table_state & 0xf][pin_state];
uint8_t event = queue->table_state & 0x30;
switch (event)
{
case DIR_CW:
++queue->state.position;
queue->state.direction = ROTARY_ENCODER_DIRECTION_CLOCKWISE;
// printf("event %d\n", event);
// send_event = true;
// printf("state.position %ld\n", queue->state.position);
xQueueSendFromISR(_queue_handle, queue, &xHigherPriorityTaskWoken);
break;
case DIR_CCW:
--queue->state.position;
queue->state.direction = ROTARY_ENCODER_DIRECTION_COUNTER_CLOCKWISE;
// printf("event %d\n", event);
// send_event = true;
// printf("state.position %ld\n", queue.state.position);
xQueueSendFromISR(_queue_handle, queue, &xHigherPriorityTaskWoken);
break;
default:
break;
}
// BaseType_t xHigherPriorityTaskWoken = pdFALSE;
// xQueueSendFromISR(_queue_handle, queue, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken == pdTRUE) if (xHigherPriorityTaskWoken == pdTRUE)
{ {
portYIELD_FROM_ISR(); portYIELD_FROM_ISR();
@@ -407,4 +443,95 @@ static void _zh_encoder_isr_handler(void *arg)
static void _zh_encoder_isr_processing_task(void *pvParameter) static void _zh_encoder_isr_processing_task(void *pvParameter)
{ {
zh_encoder_handle_t queue = {0};
while (xQueueReceive(_queue_handle, &queue, portMAX_DELAY) == pdTRUE)
{
// printf("queue.b_gpio_number %d\n", queue.b_gpio_number);
// printf("queue.q_gpio_number %d\n", queue.a_gpio_number);
// uint8_t pin_state = (gpio_get_level(queue.b_gpio_number) << 1) | gpio_get_level(queue.a_gpio_number);
// // printf("pin_state %d\n", pin_state);
// queue.table_state = queue.table[queue.table_state & 0xf][pin_state];
// uint8_t event = queue.table_state & 0x30;
// switch (event)
// {
// case DIR_CW:
// ++queue.state.position;
// queue.state.direction = ROTARY_ENCODER_DIRECTION_CLOCKWISE;
// printf("event %d\n", event);
// // send_event = true;
// printf("state.position %ld\n", queue.state.position);
// break;
// case DIR_CCW:
// --queue.state.position;
// queue.state.direction = ROTARY_ENCODER_DIRECTION_COUNTER_CLOCKWISE;
// printf("event %d\n", event);
// // send_event = true;
// printf("state.position %ld\n", queue.state.position);
// break;
// default:
// break;
// }
printf("state.position %ld\n", queue.state.position);
}
vTaskDelete(NULL);
// rotary_encoder_info_t *info = (rotary_encoder_info_t *)args;
// uint8_t event = 0;
// if (info != NULL)
// {
// // Get state of input pins.
// uint8_t pin_state = (gpio_get_level(info->pin_b) << 1) | gpio_get_level(info->pin_a);
// // Determine new state from the pins and state table.
// #ifdef ROTARY_ENCODER_DEBUG
// uint8_t old_state = info->table_state;
// #endif
// queue.table_state = queue.table[queue.table_state & 0xf][pin_state];
// // Return emit bits, i.e. the generated event.
// event = queue.table_state & 0x30;
// #ifdef ROTARY_ENCODER_DEBUG
// ESP_EARLY_LOGD(TAG, "BA %d%d, state 0x%02x, new state 0x%02x, event 0x%02x",
// pin_state >> 1, pin_state & 1, old_state, info->table_state, event);
// #endif
// }
// return event;
// uint8_t event = _process(info);
// bool send_event = false;
// switch (event)
// {
// case DIR_CW:
// ++info->state.position;
// info->state.direction = ROTARY_ENCODER_DIRECTION_CLOCKWISE;
// // send_event = true;
// break;
// case DIR_CCW:
// --info->state.position;
// info->state.direction = ROTARY_ENCODER_DIRECTION_COUNTER_CLOCKWISE;
// send_event = true;
// break;
// default:
// break;
// }
// if (send_event && info->queue)
// {
// rotary_encoder_event_t queue_event =
// {
// .state =
// {
// .position = info->state.position,
// .direction = info->state.direction,
// },
// };
// BaseType_t task_woken = pdFALSE;
// xQueueSendFromISR(info->queue, &queue_event, &task_woken);
// if (task_woken)
// {
// portYIELD_FROM_ISR();
// }
// }
} }