feat: added status enumeration
This commit is contained in:
1 parent
d9872c8e94
commit
fb87e98189
6 files changed
+91
-69
No files matched your search
+59
-57
@@ -22,21 +22,21 @@
|
||||
|
||||
Внутренняя структура энкодера (opaque-хэндл, доступен только через API компонента):
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
| ------ | ----- | ---------- |
|
||||
| `s_gpio_status` | `bool` | Текущее состояние кнопки (обновляется только колбэком таймера дребезга) |
|
||||
| `encoder_number` | `uint8_t` | Уникальный номер энкодера, передаётся в событиях |
|
||||
| `s_gpio_number` | `gpio_num_t` | GPIO кнопки (`GPIO_NUM_MAX`, если кнопка отключена) |
|
||||
| `encoder_step` | `float` | Приращение позиции на один фиксатор энкодера |
|
||||
| `encoder_position` | `float` | Текущая позиция энкодера |
|
||||
| `encoder_min_value` | `float` | Минимальное значение позиции |
|
||||
| `encoder_max_value` | `float` | Максимальное значение позиции |
|
||||
| `count_accumulator` | `int32_t` | Остаток импульсов PCNT, не образующий целого шага |
|
||||
| `pcnt_counts_per_step` | `uint8_t` | Количество импульсов PCNT на один шаг |
|
||||
| `pcnt_unit_handle` | `pcnt_unit_handle_t` | Дескриптор единицы PCNT |
|
||||
| `pcnt_channel_a_handle` | `pcnt_channel_handle_t` | Дескриптор канала A (edge A, level B) |
|
||||
| `pcnt_channel_b_handle` | `pcnt_channel_handle_t` | Дескриптор канала B (edge B, level A) |
|
||||
| `button_timer` | `TimerHandle_t` | Одноразовый таймер подавления дребезга кнопки |
|
||||
| Поле | Тип | Описание |
|
||||
| ----------------------- | ----------------------- | ----------------------------------------------------------------------- |
|
||||
| `s_gpio_status` | `bool` | Текущее состояние кнопки (обновляется только колбэком таймера дребезга) |
|
||||
| `encoder_number` | `uint8_t` | Уникальный номер энкодера, передаётся в событиях |
|
||||
| `s_gpio_number` | `gpio_num_t` | GPIO кнопки (`GPIO_NUM_MAX`, если кнопка отключена) |
|
||||
| `encoder_step` | `float` | Приращение позиции на один фиксатор энкодера |
|
||||
| `encoder_position` | `float` | Текущая позиция энкодера |
|
||||
| `encoder_min_value` | `float` | Минимальное значение позиции |
|
||||
| `encoder_max_value` | `float` | Максимальное значение позиции |
|
||||
| `count_accumulator` | `int32_t` | Остаток импульсов PCNT, не образующий целого шага |
|
||||
| `pcnt_counts_per_step` | `uint8_t` | Количество импульсов PCNT на один шаг |
|
||||
| `pcnt_unit_handle` | `pcnt_unit_handle_t` | Дескриптор единицы PCNT |
|
||||
| `pcnt_channel_a_handle` | `pcnt_channel_handle_t` | Дескриптор канала A (edge A, level B) |
|
||||
| `pcnt_channel_b_handle` | `pcnt_channel_handle_t` | Дескриптор канала B (edge B, level A) |
|
||||
| `button_timer` | `TimerHandle_t` | Одноразовый таймер подавления дребезга кнопки |
|
||||
|
||||
Поля, к которым обращаются из прерываний и задачи обработки, защищены критической секцией на спинлоке.
|
||||
|
||||
@@ -44,22 +44,22 @@
|
||||
|
||||
Передаётся из ISR точки наблюдения PCNT в общую задачу обработки:
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|------|-----|----------|
|
||||
| `count` | `int32_t` | Знаковое значение счётчика PCNT, прочитанное перед сбросом |
|
||||
| `handle` | `zh_encoder_handle_t *` | Указатель на хэндл энкодера-источника |
|
||||
| Поле | Тип | Описание |
|
||||
| -------- | ----------------------- | ---------------------------------------------------------- |
|
||||
| `count` | `int32_t` | Знаковое значение счётчика PCNT, прочитанное перед сбросом |
|
||||
| `handle` | `zh_encoder_handle_t *` | Указатель на хэндл энкодера-источника |
|
||||
|
||||
Указатель на хэндл читается без спинлока: это безопасно, так как память хэндла освобождается в `zh_encoder_deinit()` только после удаления общей задачи обработки (при удалении последнего энкодера).
|
||||
|
||||
### Общие (статические) ресурсы
|
||||
|
||||
| Ресурс | Тип | Описание |
|
||||
| -------- | ----- | ---------- |
|
||||
| `zh_encoder` | `TaskHandle_t` | Дескриптор общей задачи обработки, создаётся для первого энкодера |
|
||||
| `_queue_handle` | `QueueHandle_t` | Общая очередь сообщений от ISR PCNT к задаче обработки |
|
||||
| `_spinlock` | `portMUX_TYPE` | Спинлок для защиты общих данных энкодеров |
|
||||
| `_stats` | `zh_encoder_stats_t` | Глобальная статистика ошибок (счётчики и watermark стека) |
|
||||
| `_vector` | `zh_vector_t *` | Вектор `zh_vector` с номерами зарегистрированных энкодеров |
|
||||
| Ресурс | Тип | Описание |
|
||||
| --------------- | -------------------- | ----------------------------------------------------------------- |
|
||||
| `zh_encoder` | `TaskHandle_t` | Дескриптор общей задачи обработки, создаётся для первого энкодера |
|
||||
| `_queue_handle` | `QueueHandle_t` | Общая очередь сообщений от ISR PCNT к задаче обработки |
|
||||
| `_spinlock` | `portMUX_TYPE` | Спинлок для защиты общих данных энкодеров |
|
||||
| `_stats` | `zh_encoder_stats_t` | Глобальная статистика ошибок (счётчики и watermark стека) |
|
||||
| `_vector` | `zh_vector_t *` | Вектор `zh_vector` с номерами зарегистрированных энкодеров |
|
||||
|
||||
Общая задача, очередь и вектор создаются при инициализации **первого** энкодера и удаляются при деинициализации **последнего**. Параметры `task_priority`, `stack_size` и `queue_size` первого энкодера действуют для всей системы.
|
||||
|
||||
@@ -75,37 +75,39 @@
|
||||
|
||||
### Инициализация и освобождение
|
||||
|
||||
| Функция | Описание |
|
||||
| --------- | ---------- |
|
||||
| `zh_encoder_init()` | Создаёт энкодер по конфигурации: проверяет параметры, регистрирует номер в векторе, при необходимости создаёт общую очередь и задачу, инициализирует PCNT и GPIO кнопки. Позиция устанавливается в середину диапазона. Требует, чтобы входной `*handle` был равен `NULL`. |
|
||||
| `zh_encoder_deinit()` | Останавливает PCNT, удаляет каналы и единицу, снимает обработчик GPIO прерываний и таймер кнопки, удаляет номер из вектора. При удалении последнего энкодера удаляет общую задачу, очередь и вектор. Устанавливает входной указатель в `NULL`. |
|
||||
| `zh_encoder_reinit()` | Меняет диапазон (`min`, `max`) и шаг (`step`) без перераспределения ресурсов, сбрасывает позицию в середину нового диапазона и обнуляет счётчик PCNT. |
|
||||
| Функция | Описание |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `zh_encoder_init()` | Создаёт энкодер по конфигурации: проверяет параметры, регистрирует номер в векторе, при необходимости создаёт общую очередь и задачу, инициализирует PCNT и GPIO кнопки. Позиция устанавливается в середину диапазона. Требует, чтобы входной `*handle` был равен `NULL`. |
|
||||
| `zh_encoder_deinit()` | Останавливает PCNT, удаляет каналы и единицу, снимает обработчик GPIO прерываний и таймер кнопки, удаляет номер из вектора. При удалении последнего энкодера удаляет общую задачу, очередь и вектор. Устанавливает входной указатель в `NULL`. |
|
||||
| `zh_encoder_reinit()` | Меняет диапазон (`min`, `max`) и шаг (`step`) без перераспределения ресурсов, сбрасывает позицию в середину нового диапазона и обнуляет счётчик PCNT. |
|
||||
|
||||
### Управление позицией
|
||||
|
||||
| Функция | Описание |
|
||||
|---------|----------|
|
||||
| `zh_encoder_set()` | Устанавливает позицию в заданное значение (в пределах настроенного диапазона), обнуляет аккумулятор и счётчик PCNT. |
|
||||
| `zh_encoder_get()` | Читает текущую позицию энкодера. |
|
||||
| `zh_encoder_reset()` | Сбрасывает позицию в середину диапазона `(min + max) / 2` и обнуляет счётчик PCNT. |
|
||||
| Функция | Описание |
|
||||
| -------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| `zh_encoder_set()` | Устанавливает позицию в заданное значение (в пределах настроенного диапазона), обнуляет аккумулятор и счётчик PCNT. |
|
||||
| `zh_encoder_get()` | Читает текущую позицию энкодера. |
|
||||
| `zh_encoder_reset()` | Сбрасывает позицию в середину диапазона `(min + max) / 2` и обнуляет счётчик PCNT. |
|
||||
|
||||
### Статистика
|
||||
|
||||
| Функция | Описание |
|
||||
|---------|----------|
|
||||
| `zh_encoder_get_stats()` | Возвращает read-only указатель на глобальную структуру статистики `zh_encoder_stats_t`. Указатель действителен до вызова `zh_encoder_reset_stats()`. |
|
||||
| `zh_encoder_reset_stats()` | Обнуляет все счётчики статистики. |
|
||||
| Функция | Описание |
|
||||
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `zh_encoder_get_stats()` | Возвращает read-only указатель на глобальную структуру статистики `zh_encoder_stats_t`. Указатель действителен до вызова `zh_encoder_reset_stats()`. |
|
||||
| `zh_encoder_reset_stats()` | Обнуляет все счётчики статистики. |
|
||||
|
||||
### Типы и события
|
||||
|
||||
| Элемент | Описание |
|
||||
| --------- | ---------- |
|
||||
| `zh_encoder_init_config_t` | Конфигурация инициализации: GPIO, диапазон, шаг, параметры задачи и уникальный номер. Значения по умолчанию задаёт `ZH_ENCODER_INIT_CONFIG_DEFAULT()`. |
|
||||
| `zh_encoder_stats_t` | Статистика: `event_post_error`, `queue_overflow_error`, `min_stack_size`. |
|
||||
| `zh_encoder_event_on_isr_t` | Данные события поворота: позиция, номер энкодера, направление (`true` — увеличение). |
|
||||
| `zh_encoder_button_event_on_isr_t` | Данные события кнопки: номер энкодера, состояние. |
|
||||
| `zh_encoder_event_id_t` | Идентификаторы событий: `ZH_BUTTON_EVENT`, `ZH_ENCODER_EVENT`. |
|
||||
| `ZH_ENCODER` | База событий `esp_event`, в которую компонент постит все сообщения. |
|
||||
| Тип | Конструктор значений | Значения |
|
||||
| ---------------------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `zh_encoder_init_config_t` | `ZH_ENCODER_INIT_CONFIG_DEFAULT()` | Конфигурация инициализации: GPIO, диапазон, шаг, параметры задачи и уникальный номер |
|
||||
| `zh_encoder_stats_t` | — | Статистика: `event_post_error`, `queue_overflow_error`, `min_stack_size` |
|
||||
| `zh_encoder_event_id_t` | — | Идентификаторы событий: `ZH_BUTTON_EVENT`, `ZH_ENCODER_EVENT` |
|
||||
| `zh_encoder_status_t` | — | Направление поворота: `ZH_ENCODER_STATUS_DECREASED`, `ZH_ENCODER_STATUS_INCREASED` |
|
||||
| `zh_encoder_button_status_t` | — | Состояние кнопки: `ZH_ENCODER_BUTTON_STATUS_PRESSED` (уровень 0), `ZH_ENCODER_BUTTON_STATUS_RELEASED` (уровень 1) |
|
||||
| `zh_encoder_event_on_isr_t` | — | Данные события поворота: позиция, номер энкодера, направление (`zh_encoder_status_t`) |
|
||||
| `zh_encoder_button_event_on_isr_t` | — | Данные события кнопки: номер энкодера, состояние (`zh_encoder_button_status_t`) |
|
||||
| `ZH_ENCODER` | `ESP_EVENT_DEFINE_BASE` | База событий `esp_event`, в которую компонент постит все сообщения |
|
||||
|
||||
## Потокобезопасность
|
||||
|
||||
@@ -161,11 +163,11 @@ void zh_encoder_event_handler(void *arg, esp_event_base_t event_base, int32_t ev
|
||||
if (event_id == ZH_ENCODER_EVENT) {
|
||||
zh_encoder_event_on_isr_t *rot = (zh_encoder_event_on_isr_t *)event_data;
|
||||
printf("Encoder %d: position %0.3f (%s)\n", rot->encoder_number,
|
||||
rot->encoder_position, rot->encoder_status ? "up" : "down");
|
||||
rot->encoder_position, rot->encoder_status == ZH_ENCODER_STATUS_INCREASED ? "up" : "down");
|
||||
} else if (event_id == ZH_BUTTON_EVENT) {
|
||||
zh_encoder_button_event_on_isr_t *btn = (zh_encoder_button_event_on_isr_t *)event_data;
|
||||
printf("Encoder %d: button %s\n", btn->encoder_number,
|
||||
btn->button_status ? "released" : "pressed");
|
||||
btn->button_status == ZH_ENCODER_BUTTON_STATUS_RELEASED ? "released" : "pressed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,13 +261,13 @@ esp_log_level_set("zh_encoder", ESP_LOG_ERROR);
|
||||
|
||||
## Ошибки
|
||||
|
||||
| Код | Описание |
|
||||
| ----- | ---------- |
|
||||
| `ESP_OK` | Операция выполнена успешно |
|
||||
| `ESP_ERR_INVALID_ARG` | NULL-аргументы, неверные параметры конфигурации (диапазон, шаг, номер, GPIO), дублирование номера энкодера, позиция вне диапазона |
|
||||
| `ESP_ERR_INVALID_STATE` | Энкодер по входному хэндлу уже инициализирован (`*handle != NULL`) |
|
||||
| `ESP_ERR_NO_MEM` | Не удалось выделить память под хэндл энкодера |
|
||||
| `ESP_FAIL` | Ошибка инициализации GPIO/PCNT, создания задачи, очереди или вектора, сброса счётчика PCNT |
|
||||
| Код | Описание |
|
||||
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `ESP_OK` | Операция выполнена успешно |
|
||||
| `ESP_ERR_INVALID_ARG` | NULL-аргументы, неверные параметры конфигурации (диапазон, шаг, номер, GPIO), дублирование номера энкодера, позиция вне диапазона |
|
||||
| `ESP_ERR_INVALID_STATE` | Энкодер по входному хэндлу уже инициализирован (`*handle != NULL`) |
|
||||
| `ESP_ERR_NO_MEM` | Не удалось выделить память под хэндл энкодера |
|
||||
| `ESP_FAIL` | Ошибка инициализации GPIO/PCNT, создания задачи, очереди или вектора, сброса счётчика PCNT |
|
||||
|
||||
## Ограничения
|
||||
|
||||
|
||||
Reference in new issue
Block a user