From d3adb8cd563ca1fa8f070106c0fdf1b780ab3cbd Mon Sep 17 00:00:00 2001 From: Ivan Li Date: Sun, 5 Mar 2023 21:47:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20IO=20=E6=89=A9?= =?UTF-8?q?=E5=B1=95=E8=8A=AF=E7=89=87=20PCA9555=20=E4=B8=8E=20EC11=20?= =?UTF-8?q?=E7=BC=96=E7=A0=81=E5=99=A8=E7=9A=84=E9=9B=86=E6=88=90=E3=80=82?= =?UTF-8?q?=20issue=20#3.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/Kconfig.projbuild | 60 +++++----- main/embedded_display.c | 4 +- main/main.c | 1 - main/pca9555.c | 3 +- main/ui_input.c | 260 ++++++++++++++++++---------------------- 5 files changed, 151 insertions(+), 177 deletions(-) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 4498b5e..ca4fa7e 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -65,43 +65,43 @@ menu "MQTT Configuration" endmenu menu "Encoder Configuration" - config ENCODER_0_CLK_PIN - int "encoder 0 clock GPIO" - range 0 32 + config ENCODER_0_CLK_PORT_IO + int "encoder 0 clock IO" + range 0 7 + default 1 + help + Encoder 0 clock io on PCA9555 port 1 + config ENCODER_0_DT_PORT_IO + int "encoder 0 data IO" + range 0 7 default 2 - help - Encoder 0 clock pin - config ENCODER_0_DT_PIN - int "encoder 0 data GPIO" - range 0 32 - default 3 help Encoder 0 clock data - config ENCODER_0_SW_PIN - int "encoder 0 switch GPIO" - range 0 32 + config ENCODER_0_SW_PORT_IO + int "encoder 0 switch IO" + range 0 7 + default 0 + help + Encoder 0 switch io on PCA9555 port 1 + + config ENCODER_1_CLK_PORT_IO + int "encoder 1 clock IO" + range 0 7 default 4 help - Encoder 0 switch pin - - config ENCODER_1_CLK_PIN - int "encoder 1 clock GPIO" - range 0 32 + Encoder 1 clock io on PCA9555 port 1 + config ENCODER_1_DT_PORT_IO + int "encoder 1 data IO" + range 0 7 default 5 - help - Encoder 1 clock pin - config ENCODER_1_DT_PIN - int "encoder 1 data GPIO" - range 0 32 - default 6 help Encoder 1 clock data - config ENCODER_1_SW_PIN - int "encoder 1 switch GPIO" - range 0 32 - default 7 + config ENCODER_1_SW_PORT_IO + int "encoder 1 switch IO" + range 0 7 + default 3 help - Encoder 1 switch pin + Encoder 1 switch io on PCA9555 port 1 endmenu @@ -109,13 +109,13 @@ menu "I2C Configuration" config I2C_SCL int "I2C SCL GPIO" range 0 32 - default 8 + default 5 help I2C SCL GPIO config I2C_SDA int "I2C SDA GPIO" range 0 32 - default 10 + default 4 help I2C SDA GPIO config I2C_NUM diff --git a/main/embedded_display.c b/main/embedded_display.c index 0bc2ad7..ae343b4 100644 --- a/main/embedded_display.c +++ b/main/embedded_display.c @@ -57,7 +57,9 @@ void display_set_pos(uint8_t x, uint8_t y) { } void display_print8_str(uint8_t x, uint8_t y, char str[]) { - if (!is_embedded_display_online) return; + if (!is_embedded_display_online) { + return; + } uint8_t c; for (uint8_t ch, ci = 0; ch = str[ci], ch != '\0'; ci++, x += 8) { c = ch - 0x20; diff --git a/main/main.c b/main/main.c index 714ff14..3a06fb1 100644 --- a/main/main.c +++ b/main/main.c @@ -26,7 +26,6 @@ void app_main(void) { ambient_light_auto_fetch(); auto_fetch_temperature(); pca9555_init(); - pca9555_auto_fetch(); ui_input_init(); xTaskCreate(mqtt_publish_ui_input, "mqtt_publish_ui_input", 2048, NULL, 10, NULL); diff --git a/main/pca9555.c b/main/pca9555.c index a881f53..6d2ae71 100644 --- a/main/pca9555.c +++ b/main/pca9555.c @@ -1,3 +1,4 @@ +#pragma once #include #include @@ -107,5 +108,5 @@ void pca9555_init() { } ESP_LOGI(PCA_9555_TAG, "Initializing PCA9555"); esp_log_level_set(PCA_9555_TAG, ESP_LOG_DEBUG); - pca9555_write_config(PCA95555_CMD_CONFIGURATION_PORT_1, 0x01); + pca9555_write_config(PCA95555_CMD_CONFIGURATION_PORT_1, 0xff); } diff --git a/main/ui_input.c b/main/ui_input.c index 06bb0c8..8bafa95 100644 --- a/main/ui_input.c +++ b/main/ui_input.c @@ -11,66 +11,50 @@ #include "freertos/queue.h" #include "freertos/task.h" #include "light.c" +#include "pca9555.c" -#define GPIO_OUTPUT_IO_0 5 -#define GPIO_OUTPUT_IO_1 6 -#define GPIO_OUTPUT_PIN_SEL \ - ((1ULL << GPIO_OUTPUT_IO_0) | (1ULL << GPIO_OUTPUT_IO_1)) -#define ENCODER_0_CLK_PIN CONFIG_ENCODER_0_CLK_PIN -#define ENCODER_0_DT_PIN CONFIG_ENCODER_0_DT_PIN -#define ENCODER_0_SW_PIN CONFIG_ENCODER_0_SW_PIN -#define ENCODER_0_CLK_PIN_MASK 1ULL << ENCODER_0_CLK_PIN -#define ENCODER_0_DT_PIN_MASK 1ULL << ENCODER_0_DT_PIN -#define ENCODER_0_SW_PIN_MASK 1ULL << ENCODER_0_SW_PIN -#define ENCODER_1_CLK_PIN CONFIG_ENCODER_1_CLK_PIN -#define ENCODER_1_DT_PIN CONFIG_ENCODER_1_DT_PIN -#define ENCODER_1_SW_PIN CONFIG_ENCODER_1_SW_PIN -#define ENCODER_1_CLK_PIN_MASK 1ULL << ENCODER_1_CLK_PIN -#define ENCODER_1_DT_PIN_MASK 1ULL << ENCODER_1_DT_PIN -#define ENCODER_1_SW_PIN_MASK 1ULL << ENCODER_1_SW_PIN +#define ENCODER_0_CLK_PORT_IO CONFIG_ENCODER_0_CLK_PORT_IO +#define ENCODER_0_DT_PORT_IO CONFIG_ENCODER_0_DT_PORT_IO +#define ENCODER_0_SW_PORT_IO CONFIG_ENCODER_0_SW_PORT_IO +#define ENCODER_1_CLK_PORT_IO CONFIG_ENCODER_1_CLK_PORT_IO +#define ENCODER_1_DT_PORT_IO CONFIG_ENCODER_1_DT_PORT_IO +#define ENCODER_1_SW_PORT_IO CONFIG_ENCODER_1_SW_PORT_IO +#define ENCODER_INT_GPIO GPIO_NUM_3 #define ESP_INTR_FLAG_DEFAULT 0 -#define NOT_ROTATING -1 -#define CLOCKWISE 1 -#define COUNTER_CLOCKWISE 0 +#define RISING_EDGE_NOT_ROTATING 0b00000000 +#define RISING_EDGE_CLOCKWISE 0b10000000 +#define RISING_EDGE_COUNTER_CLOCKWISE 0b11000000 +#define RISING_EDGE_ROTATING_MASK 0b11000000 + +#define FALLING_EDGE_NOT_ROTATING 0b00000000 +#define FALLING_EDGE_CLOCKWISE 0b00100000 +#define FALLING_EDGE_COUNTER_CLOCKWISE 0b00110000 +#define FALLING_EDGE_ROTATING_MASK 0b00110000 static const char *UI_INPUT_TAG = "UiInput"; static xQueueHandle ui_input_event = NULL; static xQueueHandle ui_input_raw_event = NULL; -static int8_t rising_edge_rotation_direction = NOT_ROTATING; -static int8_t falling_edge_rotation_direction = NOT_ROTATING; +typedef struct encoder_state { + e_ui_input_raw_key_t key; + uint8_t bits; // rising_edge_rotation_direction, + // falling_edge_rotation_direction, dt, clk, sw + uint8_t value; // dt, clk, sw +} encoder_state_t; -uint8_t input_key; +static encoder_state_t encoder_0_state = {.key = ui_input_raw_key_encoder_0, + .bits = 0}; +static encoder_state_t encoder_1_state = {.key = ui_input_raw_key_encoder_1, + .bits = 0}; + +uint8_t level_byte; +int8_t delta = 0; +char changing_str[12] = "NC"; static void IRAM_ATTR gpio_isr_handler(void *arg) { - input_key = (e_ui_input_raw_key_t)arg; - - switch (input_key) { - case ui_input_raw_key_encoder_0: { - s_ui_input_raw_t event = { - .key = input_key, - .value = (gpio_get_level(ENCODER_0_SW_PIN) << 2) | - (gpio_get_level(ENCODER_0_CLK_PIN) << 1) | - (gpio_get_level(ENCODER_0_DT_PIN)), - }; - xQueueSendFromISR(ui_input_raw_event, &event, NULL); - break; - } - case ui_input_raw_key_encoder_1: { - s_ui_input_raw_t event = { - .key = input_key, - .value = (gpio_get_level(ENCODER_1_SW_PIN) << 2) | - (gpio_get_level(ENCODER_1_CLK_PIN) << 1) | - (gpio_get_level(ENCODER_1_DT_PIN)), - }; - xQueueSendFromISR(ui_input_raw_event, &event, NULL); - break; - } - default: - return; - } + xQueueSendFromISR(ui_input_raw_event, NULL, NULL); } static void ui_input_update_embedded_display(void *arg) { @@ -111,91 +95,90 @@ static void ui_input_update_embedded_display(void *arg) { } } -static void ui_input_raw_handler(void *arg) { - s_ui_input_raw_t input; - uint8_t clk_level; - uint8_t dt_level; - uint8_t sw_level; - int8_t delta = 0; - char changing_str[12] = "NC"; - for (;;) { - if (xQueueReceive(ui_input_raw_event, &input, portMAX_DELAY)) { - sw_level = input.value >> 2 & 1; - clk_level = input.value >> 1 & 1; - dt_level = input.value & 1; - if (clk_level) { - rising_edge_rotation_direction = dt_level == 0; - if (falling_edge_rotation_direction == rising_edge_rotation_direction) { - if (rising_edge_rotation_direction) { - delta = 1; - } else { - delta = -1; - } - falling_edge_rotation_direction = NOT_ROTATING; - } else { - delta = 0; - if (falling_edge_rotation_direction != NOT_ROTATING) { - rising_edge_rotation_direction = NOT_ROTATING; - } - } +static void encoder_value_change(encoder_state_t *state) { + if ((state->value >> 1 & 1) == (state->bits >> 1 & 1)) { + return; + } + + state->bits = (state->bits & 0b11111000) | (state->value & 0b111); + if (state->value >> 1 & 1) { + state->bits = (state->bits & (~RISING_EDGE_ROTATING_MASK)) | 0x80 | + ~(state->value >> 2 & 1) << 6; + if (((state->bits & FALLING_EDGE_ROTATING_MASK) >> 4) == + ((state->bits & RISING_EDGE_ROTATING_MASK) >> 6)) { + if ((state->bits & RISING_EDGE_ROTATING_MASK) == RISING_EDGE_CLOCKWISE) { + delta = -1; } else { - falling_edge_rotation_direction = dt_level; - if (rising_edge_rotation_direction == falling_edge_rotation_direction) { - if (falling_edge_rotation_direction) { - delta = 1; - } else { - delta = -1; - } - rising_edge_rotation_direction = NOT_ROTATING; - - } else { - delta = 0; - if (rising_edge_rotation_direction != NOT_ROTATING) { - falling_edge_rotation_direction = NOT_ROTATING; - } - } + delta = 1; } - - if (delta == 0) { - continue; + state->bits = (state->bits & (~FALLING_EDGE_ROTATING_MASK)) | + FALLING_EDGE_NOT_ROTATING; + } else { + delta = 0; + if ((state->bits & FALLING_EDGE_ROTATING_MASK) != + FALLING_EDGE_NOT_ROTATING) { + state->bits = (state->bits & (~FALLING_EDGE_ROTATING_MASK)) | + FALLING_EDGE_NOT_ROTATING; } - - // display_fill_rect(0, 6, 128, 8, 0); - - // switch (input.key) { - // case ui_input_raw_key_encoder_0: - // sprintf(changing_str, "E0 %d: %u%u%u%u%u", delta, - // (input.value >> 4) & 1, (input.value >> 3) & 1, - // (input.value >> 2) & 1, (input.value >> 1) & 1, - // (input.value) & 1); - // break; - // case ui_input_raw_key_encoder_1: - // sprintf(changing_str, "E1 %d: %u%u%u%u%u", delta, - // (input.value >> 4) & 1, (input.value >> 3) & 1, - // (input.value >> 2) & 1, (input.value >> 1) & 1, - // (input.value) & 1); - // break; - // default: - // strcpy(changing_str, "NC"); - // break; - // } - // display_print8_str(8, 6, changing_str); - s_ui_input_t event = {.value = delta}; - if (input.key == ui_input_raw_key_encoder_0) { - if (sw_level) { - event.key = ui_input_key_computer_volume; - } else { - event.key = ui_input_key_display_0_brightness; - } - } else if (input.key == ui_input_raw_key_encoder_1) { - if (sw_level) { - event.key = ui_input_key_display_ambient_lighting_level; - led_strip_set_brightness(display_ambient_lighting_level + delta); - } else { - event.key = ui_input_key_display_1_brightness; - } + } + } else { + state->bits = (state->bits & (~FALLING_EDGE_ROTATING_MASK)) | 0x20 | + (state->value >> 2 & 1) << 4; + if (((state->bits & FALLING_EDGE_ROTATING_MASK) >> 4) == + ((state->bits & RISING_EDGE_ROTATING_MASK) >> 6)) { + if ((state->bits & FALLING_EDGE_ROTATING_MASK) == + FALLING_EDGE_CLOCKWISE) { + delta = -1; + } else { + delta = 1; } - xQueueSendFromISR(ui_input_event, &event, NULL); + state->bits = (state->bits & (~RISING_EDGE_ROTATING_MASK)) | + RISING_EDGE_NOT_ROTATING; + + } else { + delta = 0; + if ((state->bits & RISING_EDGE_ROTATING_MASK) != + RISING_EDGE_NOT_ROTATING) { + state->bits = (state->bits & (~RISING_EDGE_ROTATING_MASK)) | + RISING_EDGE_NOT_ROTATING; + } + } + } + + if (delta == 0) { + return; + } + + s_ui_input_t event = {.value = delta}; + if (state->key == ui_input_raw_key_encoder_0) { + if (state->value & 1) { + event.key = ui_input_key_computer_volume; + } else { + event.key = ui_input_key_display_0_brightness; + } + } else if (state->key == ui_input_raw_key_encoder_1) { + if (state->value & 1) { + event.key = ui_input_key_display_ambient_lighting_level; + led_strip_set_brightness(display_ambient_lighting_level + delta); + } else { + event.key = ui_input_key_display_1_brightness; + } + } + xQueueSend(ui_input_event, &event, NULL); +} + +static void ui_input_raw_handler(void *arg) { + for (;;) { + if (xQueueReceive(ui_input_raw_event, NULL, portMAX_DELAY)) { + pca9555_read_one_input(PCA95555_CMD_INPUT_PORT_1, &level_byte); + + ESP_LOGI(UI_INPUT_TAG, "ui_input_raw_handler: %d%d%d %d%d%d", + level_byte & 1, level_byte >> 1 & 1, level_byte >> 2 & 1, + level_byte >> 3 & 1, level_byte >> 4 & 1, level_byte >> 5 & 1); + encoder_0_state.value = level_byte & 0x7; + encoder_value_change(&encoder_0_state); + encoder_1_state.value = level_byte >> 3 & 0x7; + encoder_value_change(&encoder_1_state); } } } @@ -208,29 +191,18 @@ void ui_input_init(void) { io_conf.pull_up_en = 1; io_conf.pull_down_en = 0; // interrupt of rising edge - io_conf.intr_type = GPIO_INTR_ANYEDGE; - io_conf.pin_bit_mask = ENCODER_0_CLK_PIN_MASK | ENCODER_1_CLK_PIN_MASK; - gpio_config(&io_conf); - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.pin_bit_mask = ENCODER_0_DT_PIN_MASK | ENCODER_1_DT_PIN_MASK; - gpio_config(&io_conf); - io_conf.pull_up_en = 1; - io_conf.pull_down_en = 0; - io_conf.pin_bit_mask = ENCODER_0_SW_PIN_MASK | ENCODER_1_SW_PIN_MASK; + io_conf.intr_type = GPIO_INTR_NEGEDGE; + io_conf.pin_bit_mask = 1ULL << ENCODER_INT_GPIO; gpio_config(&io_conf); // start encoder task ui_input_event = xQueueCreate(10, sizeof(s_ui_input_t)); - ui_input_raw_event = xQueueCreate(10, sizeof(s_ui_input_raw_t)); + ui_input_raw_event = xQueueCreate(10, 0); // install gpio isr service gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); // hook isr handler for specific gpio pin - gpio_isr_handler_add(ENCODER_0_CLK_PIN, gpio_isr_handler, - (void *)ui_input_raw_key_encoder_0); - // hook isr handler for specific gpio pin - gpio_isr_handler_add(ENCODER_1_CLK_PIN, gpio_isr_handler, - (void *)ui_input_raw_key_encoder_1); + gpio_isr_handler_add(ENCODER_INT_GPIO, gpio_isr_handler, NULL); xTaskCreate(ui_input_update_embedded_display, "ui_input_event", 2048, NULL, 10, NULL);