diff --git a/main/esp32_rgb_rotary_encoder.c b/main/esp32_rgb_rotary_encoder.c index b64cf9a..a499ea9 100644 --- a/main/esp32_rgb_rotary_encoder.c +++ b/main/esp32_rgb_rotary_encoder.c @@ -1,5 +1,6 @@ #include +#include "driver/gpio.h" #include "esp_err.h" #include "freertos/FreeRTOS.h" #include "freertos/portmacro.h" @@ -9,6 +10,7 @@ #include "esp_log.h" #include "driver/pulse_cnt.h" #include "driver/ledc.h" +#include "hal/gpio_types.h" #include "hal/ledc_types.h" #include "hal/pcnt_types.h" @@ -26,8 +28,63 @@ pcnt_unit_handle_t pcnt_unit; static QueueHandle_t pcnt_queue = NULL; +/* Button Settings */ +static QueueHandle_t control_event_queue = NULL; +portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; +static const uint16_t DEBOUNCE_TIMEOUT = 20; /* Polling period lenght for debounce */ +static uint64_t debounce_time = 0; /* system time of last intterupt */ +static uint8_t btn_state = 1; /* state of gpio last recorded */ + static const char *TAG = "RE Demo"; /* logging tag */ +static void IRAM_ATTR gpio_isr_handler(void *arg) { + uint32_t gpio_num = (uint32_t)arg; + portENTER_CRITICAL_ISR(&mux); + debounce_time = xTaskGetTickCount(); /* set time of interrupt */ + btn_state = gpio_get_level(GPIO_BTN_PIN); /* set state */ + portEXIT_CRITICAL_ISR(&mux); + xQueueSendFromISR(control_event_queue, &gpio_num, NULL); +} + +static void control_event_handler(void *arg) { + uint8_t last_btn_state; + uint64_t last_debounce_time; + ESP_LOGI(TAG, "Starting Control Event Handler"); + while (1) { + /* save these so we can make comparisons */ + portENTER_CRITICAL_ISR(&mux); + last_btn_state = btn_state; + last_debounce_time = debounce_time; + portEXIT_CRITICAL_ISR(&mux); + uint8_t current_state = gpio_get_level(GPIO_BTN_PIN); + uint32_t gpio_num = GPIO_BTN_PIN; + if (xQueueReceive(control_event_queue, &gpio_num, portMAX_DELAY)) { + /* Check if interrupt triggered stays the same for long enough */ + if ((current_state == last_btn_state) && + (xTaskGetTickCount() - last_debounce_time > DEBOUNCE_TIMEOUT)) { + ESP_LOGI(TAG, "Switch pushed!"); + } + } + } +} + +/* Initialize encoder switch */ +static void btn_init(void) { + ESP_LOGI(TAG, "Initializing Encoder Switch"); + + /* Setup gpio control event queue */ + control_event_queue = xQueueCreate(10, sizeof(uint32_t)); + /* install gpio isr hservice */ + gpio_install_isr_service(0); + /* Setup Encoder button */ + gpio_reset_pin(GPIO_BTN_PIN); + gpio_pullup_dis(GPIO_BTN_PIN); + gpio_pulldown_en(GPIO_BTN_PIN); + gpio_set_direction(GPIO_BTN_PIN, GPIO_MODE_INPUT); + gpio_set_intr_type(GPIO_BTN_PIN, GPIO_INTR_POSEDGE); + /* Hook in handler for button */ + gpio_isr_handler_add(GPIO_BTN_PIN, gpio_isr_handler, (void *)GPIO_BTN_PIN); +} /* Initialize LEDC for RGB LEDS in encoder */ static void ledc_init(void) { @@ -153,7 +210,13 @@ void app_main(void){ /* Initialize pulse counter */ pcnt_init(); + /* Initialize led driver */ ledc_init(); + /* Initialize gpio switch */ + btn_init(); + + /* Start task to handle control events */ + xTaskCreate(control_event_handler, "control event handler", 2048, NULL, 10, NULL); /* ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 4095)); */ /* ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0)); */