Files
H2201_Audio_Mixer/ESP32/main/H2201_buttons.c
Martijn Scheepers baf4dd4c9a bluetooth recoonect
2022-05-06 15:41:29 +02:00

204 lines
6.2 KiB
C

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "driver/pcnt.h"
#include "esp_log.h"
#include "H2201_buttons.h"
#include "H2201_i2c.h"
static const char *TAG = "H2201_buttons";
static QueueHandle_t H2201_button_event_queue = NULL;
static QueueHandle_t H2201_encoder_volume_queue = NULL;
static uint32_t encoder_pcnt_unit = 0;
static void IRAM_ATTR gpio_isr_handler(void *arg)
{
uint32_t gpio_num = (uint32_t)arg;
xQueueSendFromISR(H2201_button_event_queue, &gpio_num, NULL);
}
static void H2201_button_task(void *arg)
{
uint32_t io_num;
uint32_t encoder_val;
for (;;)
{
if (xQueueReceive(H2201_button_event_queue, &io_num, 10 / portTICK_PERIOD_MS))
{
int level = gpio_get_level(io_num);
// printf("GPIO[%d] intr, val: %d\n", io_num, level);
if (level == 0)
{
H2201_i2c_beep();
}
}
if (xQueueReceive(H2201_encoder_volume_queue, &encoder_val, 10 / portTICK_PERIOD_MS))
{
// printf("Encoder value: %zu\n", encoder_val);
if (encoder_val == 1)
{
H2201_i2c_mastervolume_up();
}
else
{
H2201_i2c_mastervolume_down();
}
}
// printf("1=%d ", H2201_dipswitch_read(1));
// printf("2=%d ", H2201_dipswitch_read(2));
// printf("3=%d ", H2201_dipswitch_read(3));
// printf("4=%d ", H2201_dipswitch_read(4));
// printf("5=%d ", H2201_dipswitch_read(5));
// printf("6=%d ", H2201_dipswitch_read(6));
// printf("7=%d ", H2201_dipswitch_read(7));
// printf("8=%d\n", H2201_dipswitch_read(8));
}
}
//******************* shiftregsiter ********************************
void H2201_shiftregister_init(void)
{
gpio_set_direction(SHIFT_CLOCK, GPIO_MODE_OUTPUT);
gpio_set_direction(SHIFT_LATCH, GPIO_MODE_OUTPUT);
gpio_set_direction(SHIFT_DATA, GPIO_MODE_INPUT);
}
void H2201_shiftregister_read(bool dipswitch[9])
{
// clock inputs in registers
gpio_set_level(SHIFT_LATCH, 1);
gpio_set_level(SHIFT_CLOCK, 1);
gpio_set_level(SHIFT_CLOCK, 0);
gpio_set_level(SHIFT_LATCH, 0);
// get de bits
for (size_t i = 8; i > 0; --i)
{
gpio_set_level(SHIFT_CLOCK, 1);
dipswitch[i] = gpio_get_level(SHIFT_DATA);
gpio_set_level(SHIFT_CLOCK, 0);
}
}
bool H2201_dipswitch_read(int sw)
{
if (sw < 0 || sw > 8)
{
return false;
}
bool dipswitch[9];
H2201_shiftregister_read(dipswitch);
return dipswitch[sw];
}
//******************* buttons ********************************
void H2201_buttons_init(void)
{
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_NEGEDGE;
io_conf.pin_bit_mask = ((1ULL << BUTTON_1) | (1ULL << BUTTON_2) | (1ULL << BUTTON_3) | (1ULL << BUTTON_4));
io_conf.mode = GPIO_MODE_INPUT;
gpio_config(&io_conf);
// Please do not use the interrupt of GPIO36 and GPIO39 when using ADC or Wi-Fi with sleep mode enabled.
// Please refer to the comments of `adc1_get_raw`.
// Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
// As a workaround, call adc_power_acquire() in the app. This will result in higher power consumption (by ~1mA),
// but will remove the glitches on GPIO36 and GPIO39.
adc_power_acquire();
H2201_button_event_queue = xQueueCreate(20, sizeof(uint32_t));
xTaskCreate(H2201_button_task, "H2201_button_task", 4096, NULL, 10, NULL);
gpio_install_isr_service(ESP_INTR_FLAG_EDGE);
gpio_isr_handler_add(BUTTON_1, gpio_isr_handler, (void *)BUTTON_1);
gpio_isr_handler_add(BUTTON_2, gpio_isr_handler, (void *)BUTTON_2);
gpio_isr_handler_add(BUTTON_3, gpio_isr_handler, (void *)BUTTON_3);
gpio_isr_handler_add(BUTTON_4, gpio_isr_handler, (void *)BUTTON_4);
}
//******************* encoder ********************************
static void IRAM_ATTR H2201_encoder_pcnt_overflow_handler(void *arg)
{
uint32_t status;
pcnt_get_event_status(encoder_pcnt_unit, &status);
if (status & PCNT_EVT_H_LIM)
{
uint32_t val = 1;
xQueueSendFromISR(H2201_encoder_volume_queue, &val, NULL);
}
else if (status & PCNT_EVT_L_LIM)
{
uint32_t val = 0;
xQueueSendFromISR(H2201_encoder_volume_queue, &val, NULL);
}
}
void H2201_encoder_init(void)
{
H2201_encoder_volume_queue = xQueueCreate(10, sizeof(uint32_t));
// Configure channel 0
pcnt_config_t dev_config = {
.pulse_gpio_num = ROTARY_A_GPIO,
.ctrl_gpio_num = ROTARY_B_GPIO,
.channel = PCNT_CHANNEL_0,
.unit = encoder_pcnt_unit,
.pos_mode = PCNT_COUNT_DEC,
.neg_mode = PCNT_COUNT_INC,
.lctrl_mode = PCNT_MODE_REVERSE,
.hctrl_mode = PCNT_MODE_KEEP,
// .counter_h_lim = ROTARY_HIGH_LIMIT,
// .counter_l_lim = ROTARY_LOW_LIMIT,
.counter_h_lim = (1),
.counter_l_lim = (-1),
};
if (pcnt_unit_config(&dev_config) != ESP_OK)
{
ESP_LOGE(TAG, "config pcnt channel 0 failed");
}
// register interrupt handler
if (pcnt_isr_service_install(0) != ESP_OK)
{
ESP_LOGE(TAG, "install isr service failed");
}
pcnt_isr_handler_add(dev_config.unit, H2201_encoder_pcnt_overflow_handler, &dev_config.unit);
// pcnt_event_enable(dev_config.unit, PCNT_EVT_ZERO);
pcnt_event_enable(dev_config.unit, PCNT_EVT_H_LIM);
pcnt_event_enable(dev_config.unit, PCNT_EVT_L_LIM);
/* Configure and enable the input filter */
if (pcnt_set_filter_value(dev_config.unit, ROTARY_GLITCH_US * 80) != ESP_OK)
{
ESP_LOGE(TAG, "set glitch filter failed");
}
if (ROTARY_GLITCH_US)
{
pcnt_filter_enable(dev_config.unit);
}
else
{
pcnt_filter_disable(dev_config.unit);
}
// PCNT pause and reset value
pcnt_counter_pause(dev_config.unit);
pcnt_counter_clear(dev_config.unit);
// start encoder
if (pcnt_counter_resume(dev_config.unit) != ESP_OK)
{
ESP_LOGE(TAG, "counter start failed");
}
}