diff --git a/.vscode/settings.json b/.vscode/settings.json index 1bef50e..915bf19 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,7 +7,7 @@ "idf.openOcdConfigs": [ "board/esp32c3-builtin.cfg" ], - "idf.port": "/dev/cu.usbmodem149201", + "idf.port": "/dev/cu.usbmodem14A01", "idf.pythonBinPath": "/Users/ivan/.espressif/python_env/idf4.4_py3.8_env/bin/python", "idf.toolsPath": "/Users/ivan/.espressif", "idf.gitPath": "/usr/bin/git", @@ -46,6 +46,7 @@ "esp_event.h": "c", "string.h": "c", "i2c.h": "c", - "esp_log.h": "c" + "esp_log.h": "c", + "queue.h": "c" } } diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 6d157e0..646c31b 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,2 +1,2 @@ -idf_component_register(SRCS "ambient_light.c" "temperature.c" "embedded_display.c" "ui.c" "mqtt.c" "main.c" "wifi.c" "light.c" "mqtt.c" +idf_component_register(SRCS "ui_input.c" "asr_pro.c" "ambient_light.c" "temperature.c" "embedded_display.c" "mqtt.c" "main.c" "wifi.c" "light.c" "mqtt.c" INCLUDE_DIRS ".") \ No newline at end of file diff --git a/main/ambient_light.c b/main/ambient_light.c index 59da1d8..6e710cf 100644 --- a/main/ambient_light.c +++ b/main/ambient_light.c @@ -164,20 +164,20 @@ void ambient_light_fetch(void* arg) { als_ch0_raw); } // als ch1 - error = apds_9930_read_word( - APDS_9930_CMD_AUTO_INCREMENT | APDS_9930_REG_Ch1DATAL, - &(als_ch1_buffer[1]), &(als_ch1_buffer[0])); - if (error != ESP_OK) { - ESP_LOGW(AMBIENT_LIGHT_TAG, "read failed. %x", error); - } else { - als_ch1_raw = als_ch1_buffer[0] << 8 | als_ch1_buffer[1]; - sprintf(als_ch1_str, "Ch1: % 5d ", als_ch1_raw); - display_print8_str(8, 6, als_ch1_str); - ESP_LOGD(AMBIENT_LIGHT_TAG, "ALS Ch1: %d, %x", als_ch1_raw, - als_ch1_raw); - } + // error = apds_9930_read_word( + // APDS_9930_CMD_AUTO_INCREMENT | APDS_9930_REG_Ch1DATAL, + // &(als_ch1_buffer[1]), &(als_ch1_buffer[0])); + // if (error != ESP_OK) { + // ESP_LOGW(AMBIENT_LIGHT_TAG, "read failed. %x", error); + // } else { + // als_ch1_raw = als_ch1_buffer[0] << 8 | als_ch1_buffer[1]; + // sprintf(als_ch1_str, "Ch1: % 5d ", als_ch1_raw); + // display_print8_str(8, 6, als_ch1_str); + // ESP_LOGD(AMBIENT_LIGHT_TAG, "ALS Ch1: %d, %x", als_ch1_raw, + // als_ch1_raw); + // } - vTaskDelay(pdMS_TO_TICKS(100)); + vTaskDelay(pdMS_TO_TICKS(1000)); } display_fill_rect(0, 2, 128, 8, 0x00); } @@ -187,7 +187,7 @@ void ambient_light_auto_fetch() { } void ambient_light_init() { - // esp_log_level_set(AMBIENT_LIGHT_TAG, ESP_LOG_DEBUG); + esp_log_level_set(AMBIENT_LIGHT_TAG, ESP_LOG_ERROR); ESP_ERROR_CHECK(apds_9930_write(APDS_9930_CMD_REPEATED | APDS_9930_REG_ATIME, APDS_9930_ATIME_VALUE)); ESP_ERROR_CHECK(apds_9930_write(APDS_9930_CMD_REPEATED | APDS_9930_REG_PTIME, diff --git a/main/asr_pro.c b/main/asr_pro.c new file mode 100644 index 0000000..011dc0a --- /dev/null +++ b/main/asr_pro.c @@ -0,0 +1,87 @@ +#include "driver/gpio.h" +#include "driver/uart.h" +#include "esp_log.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "light.c" +#include "string.h" + +static const int RX_BUF_SIZE = 1024; + +#define TXD_PIN (GPIO_NUM_12) +#define RXD_PIN (GPIO_NUM_13) + +int sendData(const char *logName, const char *data) { + const int len = strlen(data); + const int txBytes = uart_write_bytes(UART_NUM_1, data, len); + ESP_LOGI(logName, "Wrote %d bytes", txBytes); + return txBytes; +} + +static void tx_task(void *arg) { + static const char *TX_TASK_TAG = "TX_TASK"; + esp_log_level_set(TX_TASK_TAG, ESP_LOG_INFO); + while (1) { + sendData(TX_TASK_TAG, "Hello world"); + vTaskDelay(2000 / portTICK_PERIOD_MS); + } +} + +static void rx_task(void *arg) { + static const char *RX_TASK_TAG = "RX_TASK"; + esp_log_level_set(RX_TASK_TAG, ESP_LOG_INFO); + uint8_t *data = (uint8_t *)malloc(RX_BUF_SIZE + 1); + uint8_t tx_buff[4] = {0}; + while (1) { + const int rxBytes = uart_read_bytes(UART_NUM_1, data, RX_BUF_SIZE, + 100 / portTICK_PERIOD_MS); + if (rxBytes > 0) { + data[rxBytes] = 0; + ESP_LOGI(RX_TASK_TAG, "Read %d bytes: '%s'", rxBytes, data); + ESP_LOG_BUFFER_HEXDUMP(RX_TASK_TAG, data, rxBytes, ESP_LOG_INFO); + + if (data[0] == 0x11 && rxBytes >= 2) { + if (data[1] <= 6) { + light_mode = data[1]; + } + tx_buff[0] = data[0]; + tx_buff[1] = light_mode; + uart_write_bytes(UART_NUM_1, tx_buff, 2); + } else if (data[0] == 0x12 && rxBytes >= 2) { + tx_buff[0] = 0x12; + tx_buff[1] = data[1]; + led_strip_set_brightness(data[1]); + uart_write_bytes(UART_NUM_1, tx_buff, 2); + } else if (data[0] == 0x13 && rxBytes >= 2) { + tx_buff[0] = 0x12; + tx_buff[1] = display_ambient_lighting_level + (int8_t)data[1]; + led_strip_set_brightness(tx_buff[1]); + uart_write_bytes(UART_NUM_1, tx_buff, 2); + } + } + } + free(data); +} + +void asr_pro_init() { + const uart_config_t uart_config = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .source_clk = UART_SCLK_APB, + }; + // We won't use a buffer for sending data. + uart_driver_install(UART_NUM_1, RX_BUF_SIZE * 2, 0, 0, NULL, 0); + uart_param_config(UART_NUM_1, &uart_config); + uart_set_pin(UART_NUM_1, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, + UART_PIN_NO_CHANGE); + + xTaskCreate(rx_task, "uart_rx_task", 1024 * 2, NULL, configMAX_PRIORITIES, + NULL); + // xTaskCreate(tx_task, "uart_tx_task", 1024 * 2, NULL, configMAX_PRIORITIES - + // 1, + // NULL); +} \ No newline at end of file diff --git a/main/embedded_display.c b/main/embedded_display.c index c8f739c..eb9f698 100644 --- a/main/embedded_display.c +++ b/main/embedded_display.c @@ -101,4 +101,4 @@ void init_display() { display_fill(0x00); display_set_pos(0, 0); -} \ No newline at end of file +} diff --git a/main/light.c b/main/light.c index fbf548b..5c65a06 100644 --- a/main/light.c +++ b/main/light.c @@ -6,6 +6,7 @@ software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +#pragma once #include "driver/rmt.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" @@ -27,10 +28,18 @@ typedef enum light_mode_e { light_mode_mqtt_connected = 3, light_mode_desktop_online = 4, light_mode_desktop_sending_colors = 5, + light_mode_off = 6, } light_mode_t; led_strip_t *light_led_strip; light_mode_t light_mode; +float display_ambient_light_brightness = 1; +uint8_t display_ambient_lighting_level = 255; + +void led_strip_set_brightness(uint8_t level) { + display_ambient_lighting_level = level; + display_ambient_light_brightness = (float)level / 255.0; +} /** * @brief Simple helper function, converting HSV color space to RGB color @@ -178,7 +187,11 @@ void light_for_idle() { for (uint16_t j = 0, hue = offset; j < STRIP_LED_NUMBER; j++, hue += step_length) { // Build RGB values - led_strip_hsv2rgb(hue, 100, 50, &red, &green, &blue); + led_strip_hsv2rgb(hue, 50, 100, &red, &green, &blue); + + red = red * display_ambient_light_brightness; + green = green * display_ambient_light_brightness; + blue = blue * display_ambient_light_brightness; // Write RGB values to strip driver ESP_ERROR_CHECK( light_led_strip->set_pixel(light_led_strip, j, red, green, blue)); @@ -246,8 +259,12 @@ void light_play_colors(uint16_t len, uint8_t *buffer) { for (uint16_t led_index = 0, buffer_cursor = 0; led_index < STRIP_LED_NUMBER && buffer_cursor < len; led_index++, buffer_cursor += 3) { - uint8_t r = buffer[buffer_cursor], g = buffer[buffer_cursor + 1], - b = buffer[buffer_cursor + 2]; + uint8_t r = (uint8_t)((float)buffer[buffer_cursor] * + display_ambient_light_brightness), + g = (uint8_t)((float)buffer[buffer_cursor + 1] * + display_ambient_light_brightness), + b = (uint8_t)((float)buffer[buffer_cursor + 2] * + display_ambient_light_brightness); ESP_ERROR_CHECK( light_led_strip->set_pixel(light_led_strip, led_index, r, g, b)); } diff --git a/main/main.c b/main/main.c index ba6850c..60bad3e 100644 --- a/main/main.c +++ b/main/main.c @@ -1,4 +1,5 @@ #include "ambient_light.c" +#include "asr_pro.c" #include "driver/i2c.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" @@ -6,6 +7,7 @@ #include "light.c" #include "mqtt.c" #include "sdkconfig.h" +#include "ui_input.c" #include "wifi.c" #define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ @@ -49,9 +51,10 @@ void app_main(void) { ambient_light_init(); ambient_light_auto_fetch(); auto_fetch_temperature(); - init_ui(); - xTaskCreate(publish_ui_input, "ui_input_event", 2048, NULL, 10, NULL); + ui_input_init(); + xTaskCreate(mqtt_publish_ui_input, "ui_input_event", 2048, NULL, 10, NULL); vTaskDelay(pdMS_TO_TICKS(10)); + asr_pro_init(); light_play(light_mode_connection_wifi); if (connect_wifi()) { light_play(light_mode_idle); diff --git a/main/mqtt.c b/main/mqtt.c index 48a1387..62958b7 100644 --- a/main/mqtt.c +++ b/main/mqtt.c @@ -13,7 +13,7 @@ #include "freertos/semphr.h" #include "freertos/task.h" #include "mqtt_client.h" -#include "ui.c" +#include "ui_input.c" #define MQTT_BROKER_URL CONFIG_MQTT_BROKER_URL #define NUMBER_OF_LEDS CONFIG_NUMBER_OF_LEDS @@ -193,21 +193,21 @@ static bool waiting_and_get_colors() { } } -static void publish_ui_input(void *arg) { +static void mqtt_publish_ui_input(void *arg) { s_ui_input_t input; for (;;) { if (xQueueReceive(ui_input_event, &input, portMAX_DELAY)) { switch (input.key) { - case UI_INPUT_DISPLAY_0_BRIGHTNESS: - case UI_INPUT_DISPLAY_1_BRIGHTNESS: { + case ui_input_key_display_0_brightness: + case ui_input_key_display_1_brightness: { cJSON *publish_json_root, *brightness; publish_json_root = cJSON_CreateObject(); cJSON_AddNumberToObject( publish_json_root, "display_index", - UI_INPUT_DISPLAY_0_BRIGHTNESS == input.key ? 0 : 1); + ui_input_key_display_0_brightness == input.key ? 0 : 1); cJSON_AddItemToObject(publish_json_root, "brightness", brightness = cJSON_CreateObject()); - cJSON_AddNumberToObject(brightness, "Absolute", input.value); + cJSON_AddNumberToObject(brightness, "Relative", input.value); char *publish_str = cJSON_Print(publish_json_root); cJSON_Delete(publish_json_root); esp_mqtt_client_publish(client, MQTT_KEY_DISPLAY_BRIGHTNESS_INPUT, diff --git a/main/temperature.c b/main/temperature.c index f2ed1e1..22b764c 100644 --- a/main/temperature.c +++ b/main/temperature.c @@ -64,7 +64,7 @@ void fetch_temperature(void* arg) { } display_print8_str(8, 0, temperature_str); } - vTaskDelay(pdMS_TO_TICKS(500)); + vTaskDelay(pdMS_TO_TICKS(2000)); } display_fill_rect(0, 0, 128, 2, 0x00); } diff --git a/main/ui.c b/main/ui.c deleted file mode 100644 index 7c1ebfd..0000000 --- a/main/ui.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "driver/gpio.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/task.h" - -#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_CLK_PIN_MASK 1ULL << ENCODER_0_CLK_PIN -#define ENCODER_0_DT_PIN_MASK 1ULL << ENCODER_0_DT_PIN -#define ENCODER_1_CLK_PIN CONFIG_ENCODER_1_CLK_PIN -#define ENCODER_1_DT_PIN CONFIG_ENCODER_1_DT_PIN -#define ENCODER_1_CLK_PIN_MASK 1ULL << ENCODER_1_CLK_PIN -#define ENCODER_1_DT_PIN_MASK 1ULL << ENCODER_1_DT_PIN -#define ESP_INTR_FLAG_DEFAULT 0 - -#define NOT_ROTATING -1 -#define CLOCKWISE 1 -#define COUNTER_CLOCKWISE 0 - -#define UI_INPUT_DISPLAY_0_BRIGHTNESS 1 -#define UI_INPUT_DISPLAY_1_BRIGHTNESS 2 - -typedef struct s_ui_input { - uint8_t key; - uint16_t value; -} s_ui_input_t; - -static xQueueHandle ui_input_event = NULL; - -static int8_t rising_edge_rotation_direction = NOT_ROTATING; -static int8_t falling_edge_rotation_direction = NOT_ROTATING; -static uint8_t display_0_brightness = 20; -static uint8_t display_1_brightness = 20; - -static s_ui_input_t current_ui_input = {}; - -uint8_t input_key; -uint8_t clk_pin = ENCODER_0_CLK_PIN; -uint8_t dt_level; -uint8_t dt_pin = ENCODER_0_DT_PIN; -uint8_t* value = &display_0_brightness; - -static void IRAM_ATTR gpio_isr_handler(void* arg) { - uint8_t input_key = (uint8_t)arg; - - switch (input_key) { - case UI_INPUT_DISPLAY_0_BRIGHTNESS: - clk_pin = ENCODER_0_CLK_PIN; - dt_pin = ENCODER_0_DT_PIN; - value = &display_0_brightness; - break; - case UI_INPUT_DISPLAY_1_BRIGHTNESS: - clk_pin = ENCODER_1_CLK_PIN; - dt_pin = ENCODER_1_DT_PIN; - value = &display_1_brightness; - break; - default: - break; - } - dt_level = gpio_get_level(dt_pin); - if (gpio_get_level(clk_pin)) { - rising_edge_rotation_direction = dt_level == 0; - if (falling_edge_rotation_direction == rising_edge_rotation_direction) { - if (rising_edge_rotation_direction) { - gpio_set_level(GPIO_OUTPUT_IO_0, 1); - gpio_set_level(GPIO_OUTPUT_IO_1, 0); - *value += 1; - } else { - gpio_set_level(GPIO_OUTPUT_IO_0, 0); - gpio_set_level(GPIO_OUTPUT_IO_1, 1); - *value -= 1; - } - falling_edge_rotation_direction = NOT_ROTATING; - - current_ui_input.key = input_key; - current_ui_input.value = *value; - xQueueSendFromISR(ui_input_event, ¤t_ui_input, NULL); - } else { - if (falling_edge_rotation_direction != NOT_ROTATING) { - rising_edge_rotation_direction = NOT_ROTATING; - } - } - } else { - falling_edge_rotation_direction = dt_level; - // printf("F %d\t", falling_edge_rotation_direction); - if (rising_edge_rotation_direction == falling_edge_rotation_direction) { - if (falling_edge_rotation_direction) { - gpio_set_level(GPIO_OUTPUT_IO_0, 1); - gpio_set_level(GPIO_OUTPUT_IO_1, 0); - *value += 1; - } else { - gpio_set_level(GPIO_OUTPUT_IO_0, 0); - gpio_set_level(GPIO_OUTPUT_IO_1, 1); - *value -= 1; - } - rising_edge_rotation_direction = NOT_ROTATING; - - current_ui_input.key = input_key; - current_ui_input.value = *value; - xQueueSendFromISR(ui_input_event, ¤t_ui_input, NULL); - - } else { - if (rising_edge_rotation_direction != NOT_ROTATING) { - falling_edge_rotation_direction = NOT_ROTATING; - } - } - } -} - -void init_ui(void) { - // zero-initialize the config structure. - gpio_config_t io_conf = {}; - // disable interrupt - io_conf.intr_type = GPIO_INTR_DISABLE; - // set as output mode - io_conf.mode = GPIO_MODE_OUTPUT; - // bit mask of the pins that you want to set,e.g.GPIO18/19 - io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; - // disable pull-down mode - io_conf.pull_down_en = 0; - // disable pull-up mode - io_conf.pull_up_en = 0; - // configure GPIO with the given settings - gpio_config(&io_conf); - - io_conf.mode = GPIO_MODE_INPUT; - 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); - - // start encoder task - ui_input_event = xQueueCreate(10, sizeof(s_ui_input_t)); - - // 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_DISPLAY_0_BRIGHTNESS); - // hook isr handler for specific gpio pin - gpio_isr_handler_add(ENCODER_1_CLK_PIN, gpio_isr_handler, - (void*)UI_INPUT_DISPLAY_1_BRIGHTNESS); -} diff --git a/main/ui_input.c b/main/ui_input.c new file mode 100644 index 0000000..49e6caa --- /dev/null +++ b/main/ui_input.c @@ -0,0 +1,278 @@ +#pragma once + +#include +#include +#include + +#include "driver/gpio.h" +#include "embedded_display.c" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "light.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 ESP_INTR_FLAG_DEFAULT 0 + +#define NOT_ROTATING -1 +#define CLOCKWISE 1 +#define COUNTER_CLOCKWISE 0 + +static const char *UI_INPUT_TAG = "UiInput"; + +typedef enum e_ui_input_key { + ui_input_key_display_0_brightness = 0, + ui_input_key_display_1_brightness = 1, + ui_input_key_computer_volume = 2, + ui_input_key_display_ambient_lighting_level = 3, + ui_input_key_display_ambient_lighting_mode = 4, + ui_input_key_display_0_mode = 5, + ui_input_key_display_1_mode = 6, +} e_ui_input_key_t; + +typedef struct s_ui_input { + e_ui_input_key_t key; + int16_t value; +} s_ui_input_t; + +typedef enum e_ui_input_raw_key { + ui_input_raw_key_encoder_0 = 0, + ui_input_raw_key_encoder_1 = 1, +} e_ui_input_raw_key_t; + +typedef struct s_ui_input_raw { + e_ui_input_raw_key_t key; + uint8_t value; +} s_ui_input_raw_t; + +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; +static uint8_t display_0_brightness = 20; +static uint8_t display_1_brightness = 20; +static uint8_t computer_volume = 30; + +static s_ui_input_t current_ui_input = {}; + +uint8_t input_key; + +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; + } +} + +static void ui_input_update_embedded_display(void *arg) { + s_ui_input_t input; + char changing_str[12] = "NC"; + for (;;) { + if (xQueueReceive(ui_input_event, &input, portMAX_DELAY)) { + switch (input.key) { + case ui_input_key_display_0_brightness: + sprintf(changing_str, "Dis0: % 3d", input.value); + break; + case ui_input_key_display_1_brightness: + sprintf(changing_str, "Dis1: % 3d", input.value); + break; + case ui_input_key_computer_volume: + sprintf(changing_str, "CVol: % 3d", input.value); + break; + case ui_input_key_display_ambient_lighting_level: + sprintf(changing_str, "ALLv: % 3d", display_ambient_lighting_level); + break; + case ui_input_key_display_ambient_lighting_mode: + sprintf(changing_str, "ALMd: % 3d", input.value); + break; + case ui_input_key_display_0_mode: + sprintf(changing_str, "Dis0M: % 2d", input.value); + break; + case ui_input_key_display_1_mode: + sprintf(changing_str, "Dis1M: % 2d", input.value); + break; + + default: + strcpy(changing_str, "NC"); + break; + } + display_fill_rect(0, 6, 128, 8, 0); + display_print8_str(8, 6, changing_str); + } + } +} + +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; + } + } + } 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; + } + } + } + + if (delta == 0) { + continue; + } + + // 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; + } + } + xQueueSendFromISR(ui_input_event, &event, NULL); + } + } +} + +void ui_input_init(void) { + // zero-initialize the config structure. + gpio_config_t io_conf = {}; + // disable interrupt + io_conf.intr_type = GPIO_INTR_DISABLE; + // set as output mode + io_conf.mode = GPIO_MODE_OUTPUT; + // bit mask of the pins that you want to set,e.g.GPIO18/19 + io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; + // disable pull-down mode + io_conf.pull_down_en = 0; + // disable pull-up mode + io_conf.pull_up_en = 0; + // configure GPIO with the given settings + gpio_config(&io_conf); + + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pull_up_en = 1; + // 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; + 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)); + + // 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); + + xTaskCreate(ui_input_update_embedded_display, "ui_input_event", 2048, NULL, + 10, NULL); + xTaskCreate(ui_input_raw_handler, "ui_input_event", 2048, NULL, 10, NULL); +}