more refactoring

- jack & led moved to services
- output_i2s subscribes to jack detection
- add user-defined debounce timer to buttons
This commit is contained in:
philippe44
2020-01-08 19:09:53 -08:00
parent 1409e1ccbe
commit daef63fdea
10 changed files with 96 additions and 50 deletions

View File

@@ -88,7 +88,7 @@ void down(void *id, button_event_e event, button_press_e press, bool longpress)
*/ */
void actrls_init(int n, const actrls_config_t *config) { void actrls_init(int n, const actrls_config_t *config) {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
button_create((void*) (config + i), config[i].gpio, config[i].type, config[i].pull, control_handler, config[i].long_press, config[i].shifter_gpio); button_create((void*) (config + i), config[i].gpio, config[i].type, config[i].pull, config[i].debounce, control_handler, config[i].long_press, config[i].shifter_gpio);
} }
} }

View File

@@ -32,6 +32,7 @@ typedef struct {
int gpio; int gpio;
int type; int type;
bool pull; bool pull;
int debounce;
int long_press; int long_press;
int shifter_gpio; int shifter_gpio;
actrls_action_e normal[2], longpress[2], shifted[2], longshifted[2]; // [0] keypressed, [1] keyreleased actrls_action_e normal[2], longpress[2], shifted[2], longshifted[2]; // [0] keypressed, [1] keyreleased

View File

@@ -43,6 +43,7 @@ static int n_buttons = 0;
static EXT_RAM_ATTR struct button_s { static EXT_RAM_ATTR struct button_s {
void *id; void *id;
int gpio, index; int gpio, index;
int debounce;
button_handler handler; button_handler handler;
struct button_s *shifter; struct button_s *shifter;
int long_press; int long_press;
@@ -63,7 +64,7 @@ static void IRAM_ATTR gpio_isr_handler(void* arg)
struct button_s *button = (struct button_s*) arg; struct button_s *button = (struct button_s*) arg;
BaseType_t woken = pdFALSE; BaseType_t woken = pdFALSE;
if (xTimerGetPeriod(button->timer) > DEBOUNCE / portTICK_RATE_MS) xTimerChangePeriodFromISR(button->timer, DEBOUNCE / portTICK_RATE_MS, &woken); // does that restart the timer? if (xTimerGetPeriod(button->timer) > button->debounce / portTICK_RATE_MS) xTimerChangePeriodFromISR(button->timer, button->debounce / portTICK_RATE_MS, &woken); // does that restart the timer?
else xTimerResetFromISR(button->timer, &woken); else xTimerResetFromISR(button->timer, &woken);
// ESP_EARLY_LOGI(TAG, "INT gpio %u level %u", button->gpio, button->level); // ESP_EARLY_LOGI(TAG, "INT gpio %u level %u", button->gpio, button->level);
} }
@@ -149,7 +150,7 @@ void dummy_handler(void *id, button_event_e event, button_press_e press) {
/**************************************************************************************** /****************************************************************************************
* Create buttons * Create buttons
*/ */
void button_create(void *id, int gpio, int type, bool pull, button_handler handler, int long_press, int shifter_gpio) { void button_create(void *id, int gpio, int type, bool pull, int debounce, button_handler handler, int long_press, int shifter_gpio) {
static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4))); static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4)));
static EXT_RAM_ATTR StackType_t xStack[BUTTON_STACK_SIZE] __attribute__ ((aligned (4))); static EXT_RAM_ATTR StackType_t xStack[BUTTON_STACK_SIZE] __attribute__ ((aligned (4)));
@@ -159,7 +160,6 @@ void button_create(void *id, int gpio, int type, bool pull, button_handler handl
if (!n_buttons) { if (!n_buttons) {
button_evt_queue = xQueueCreate(10, sizeof(struct button_s)); button_evt_queue = xQueueCreate(10, sizeof(struct button_s));
gpio_install_isr_service(0);
xTaskCreateStatic( (TaskFunction_t) buttons_task, "buttons_thread", BUTTON_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 1, xStack, &xTaskBuffer); xTaskCreateStatic( (TaskFunction_t) buttons_task, "buttons_thread", BUTTON_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 1, xStack, &xTaskBuffer);
} }
@@ -169,11 +169,12 @@ void button_create(void *id, int gpio, int type, bool pull, button_handler handl
// set mandatory parameters // set mandatory parameters
buttons[n_buttons].id = id; buttons[n_buttons].id = id;
buttons[n_buttons].gpio = gpio; buttons[n_buttons].gpio = gpio;
buttons[n_buttons].debounce = debounce ? debounce: DEBOUNCE;
buttons[n_buttons].handler = handler; buttons[n_buttons].handler = handler;
buttons[n_buttons].long_press = long_press; buttons[n_buttons].long_press = long_press;
buttons[n_buttons].level = -1; buttons[n_buttons].level = -1;
buttons[n_buttons].type = type; buttons[n_buttons].type = type;
buttons[n_buttons].timer = xTimerCreate("buttonTimer", DEBOUNCE / portTICK_RATE_MS, pdFALSE, (void *) &buttons[n_buttons], buttons_timer); buttons[n_buttons].timer = xTimerCreate("buttonTimer", buttons[n_buttons].debounce / portTICK_RATE_MS, pdFALSE, (void *) &buttons[n_buttons], buttons_timer);
// little trick to find ourselves from queued copy // little trick to find ourselves from queued copy
buttons[n_buttons].index = n_buttons; buttons[n_buttons].index = n_buttons;

View File

@@ -27,9 +27,10 @@ typedef enum { BUTTON_NORMAL, BUTTON_SHIFTED } button_press_e;
typedef void (*button_handler)(void *id, button_event_e event, button_press_e mode, bool long_press); typedef void (*button_handler)(void *id, button_event_e event, button_press_e mode, bool long_press);
/* /*
set debounce to 0 for default (50ms)
set long_press to 0 for no long-press set long_press to 0 for no long-press
set shifter_gpio to -1 for no shift set shifter_gpio to -1 for no shift
NOTE: shifter buttons *must* be created before shiftee NOTE: shifter buttons *must* be created before shiftee
*/ */
void button_create(void *id, int gpio, int type, bool pull, button_handler handler, int long_press, int shifter_gpio); void button_create(void *id, int gpio, int type, bool pull, int debounce, button_handler handler, int long_press, int shifter_gpio);

View File

@@ -15,12 +15,17 @@
#include "esp_system.h" #include "esp_system.h"
#include "esp_log.h" #include "esp_log.h"
#include "monitor.h" #include "monitor.h"
#include "driver/gpio.h"
#include "buttons.h"
#define JACK_GPIO 34
#define MONITOR_TIMER (10*1000) #define MONITOR_TIMER (10*1000)
static const char TAG[] = "monitor"; static const char TAG[] = "monitor";
static TimerHandle_t monitor_timer; static TimerHandle_t monitor_timer;
void (*jack_handler_svc)(bool inserted);
bool jack_inserted_svc(void);
/**************************************************************************************** /****************************************************************************************
* *
@@ -33,12 +38,39 @@ static void monitor_callback(TimerHandle_t xTimer) {
heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM)); heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM));
} }
/****************************************************************************************
*
*/
static void jack_handler_default(void *id, button_event_e event, button_press_e mode, bool long_press) {
ESP_LOGD(TAG, "Jack %s", event == BUTTON_PRESSED ? "inserted" : "removed");
if (jack_handler_svc) (*jack_handler_svc)(event == BUTTON_PRESSED);
}
/****************************************************************************************
*
*/
bool jack_inserted_svc (void) {
#ifdef JACK_GPIO
return !gpio_get_level(JACK_GPIO);
#else
return false;
#endif
}
/**************************************************************************************** /****************************************************************************************
* *
*/ */
void monitor_svc_init(void) { void monitor_svc_init(void) {
ESP_LOGI(TAG, "Initializing monitoring"); ESP_LOGI(TAG, "Initializing monitoring");
#ifdef JACK_GPIO
gpio_pad_select_gpio(JACK_GPIO);
gpio_set_direction(JACK_GPIO, GPIO_MODE_INPUT);
// re-use button management for jack handler, it's a GPIO after all
button_create(NULL, JACK_GPIO, BUTTON_LOW, false, 250, jack_handler_default, 0, -1);
#endif
monitor_timer = xTimerCreate("monitor", MONITOR_TIMER / portTICK_RATE_MS, pdTRUE, NULL, monitor_callback); monitor_timer = xTimerCreate("monitor", MONITOR_TIMER / portTICK_RATE_MS, pdTRUE, NULL, monitor_callback);
xTimerStart(monitor_timer, portMAX_DELAY); xTimerStart(monitor_timer, portMAX_DELAY);
} }

View File

@@ -20,3 +20,6 @@
#pragma once #pragma once
extern void (*jack_handler_svc)(bool inserted);
extern bool jack_inserted_svc(void);

View File

@@ -7,6 +7,8 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include "esp_log.h"
#include "driver/gpio.h"
#include "battery.h" #include "battery.h"
#include "led.h" #include "led.h"
#include "monitor.h" #include "monitor.h"
@@ -17,11 +19,24 @@ extern void led_svc_init(void);
static const char TAG[] = "services"; static const char TAG[] = "services";
#ifdef CONFIG_SQUEEZEAMP
#define LED_GREEN_GPIO 12
#define LED_RED_GPIO 13
#endif
/**************************************************************************************** /****************************************************************************************
* *
*/ */
void services_init(void) { void services_init(void) {
gpio_install_isr_service(0);
ESP_LOGD(TAG,"Configuring LEDs");
led_svc_init();
#ifdef CONFIG_SQUEEZEAMP
led_config(LED_GREEN, LED_GREEN_GPIO, 0);
led_config(LED_RED, LED_RED_GPIO, 0);
#endif
battery_svc_init(); battery_svc_init();
monitor_svc_init(); monitor_svc_init();
led_svc_init();
} }

View File

@@ -49,6 +49,7 @@ sure that using rate_delay would fix that
#include <signal.h> #include <signal.h>
#include "time.h" #include "time.h"
#include "led.h" #include "led.h"
#include "monitor.h"
#define LOCK mutex_lock(outputbuf->mutex) #define LOCK mutex_lock(outputbuf->mutex)
#define UNLOCK mutex_unlock(outputbuf->mutex) #define UNLOCK mutex_unlock(outputbuf->mutex)
@@ -121,7 +122,6 @@ static u8_t *obuf;
static frames_t oframes; static frames_t oframes;
static bool spdif; static bool spdif;
static size_t dma_buf_frames; static size_t dma_buf_frames;
static int jack_status = -1; // 0 = inserted
DECLARE_ALL_MIN_MAX; DECLARE_ALL_MIN_MAX;
@@ -132,6 +132,7 @@ static void *output_thread_i2s_stats();
static void dac_cmd(dac_cmd_e cmd, ...); static void dac_cmd(dac_cmd_e cmd, ...);
static int tas57_detect(void); static int tas57_detect(void);
static void spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, size_t *count); static void spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, size_t *count);
static void (*jack_handler_chain)(bool inserted);
#ifdef CONFIG_SQUEEZEAMP #ifdef CONFIG_SQUEEZEAMP
@@ -201,6 +202,19 @@ static u8_t tas57_addr;
#endif #endif
/****************************************************************************************
* jack insertion handler
*/
static void jack_handler(bool inserted) {
// jack detection bounces a bit but that seems fine
if (jack_mutes_amp) {
LOG_INFO("switching amplifier %s", inserted ? "ON" : "OFF");
if (inserted) dac_cmd(DAC_ANALOGUE_OFF);
else dac_cmd(DAC_ANALOGUE_ON);
}
if (jack_handler_chain) (jack_handler_chain)(inserted);
}
/**************************************************************************************** /****************************************************************************************
* Initialize the DAC output * Initialize the DAC output
*/ */
@@ -209,8 +223,6 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
#ifdef TAS57xx #ifdef TAS57xx
LOG_INFO("Initializing TAS57xx "); LOG_INFO("Initializing TAS57xx ");
gpio_pad_select_gpio(JACK_GPIO);
gpio_set_direction(JACK_GPIO, GPIO_MODE_INPUT);
adc1_config_width(ADC_WIDTH_BIT_12); adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_7, ADC_ATTEN_DB_0); adc1_config_channel_atten(ADC1_CHANNEL_7, ADC_ATTEN_DB_0);
@@ -335,6 +347,12 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
dac_cmd(DAC_STANDBY); dac_cmd(DAC_STANDBY);
jack_handler_chain = jack_handler_svc;
jack_handler_svc = jack_handler;
if (jack_mutes_amp && jack_inserted_svc()) dac_cmd(DAC_ANALOGUE_OFF);
else dac_cmd(DAC_ANALOGUE_ON);
esp_pthread_cfg_t cfg = esp_pthread_get_default_config(); esp_pthread_cfg_t cfg = esp_pthread_get_default_config();
cfg.thread_name= "output_i2s"; cfg.thread_name= "output_i2s";
@@ -451,19 +469,10 @@ static void *output_thread_i2s() {
while (running) { while (running) {
TIME_MEASUREMENT_START(timer_start); TIME_MEASUREMENT_START(timer_start);
#ifdef TAS57xx
// handle jack insertion as a polling function (to avoid to have to do de-bouncing)
if (gpio_get_level(JACK_GPIO) != jack_status) {
jack_status = gpio_get_level(JACK_GPIO);
if (jack_mutes_amp) {
dac_cmd(jack_status ? DAC_ANALOGUE_ON : DAC_ANALOGUE_OFF);
LOG_INFO("Changing jack status %d", jack_status);
}
}
#endif
LOCK; LOCK;
// manage led display // manage led display & analogue
if (state != output.state) { if (state != output.state) {
LOG_INFO("Output state is %d", output.state); LOG_INFO("Output state is %d", output.state);
if (output.state == OUTPUT_OFF) led_blink(LED_GREEN, 100, 2500); if (output.state == OUTPUT_OFF) led_blink(LED_GREEN, 100, 2500);
@@ -474,7 +483,7 @@ static void *output_thread_i2s() {
led_blink(LED_GREEN, 200, 1000); led_blink(LED_GREEN, 200, 1000);
} else if (output.state == OUTPUT_RUNNING) { } else if (output.state == OUTPUT_RUNNING) {
#ifdef TAS57xx #ifdef TAS57xx
if (!jack_mutes_amp || (jack_mutes_amp && jack_status)) dac_cmd(DAC_ANALOGUE_ON); if (!jack_mutes_amp || !jack_inserted_svc()) dac_cmd(DAC_ANALOGUE_ON);
#endif #endif
led_on(LED_GREEN); led_on(LED_GREEN);
} }

View File

@@ -62,6 +62,7 @@ Contains the freeRTOS task and all necessary support
#include "cJSON.h" #include "cJSON.h"
#include "nvs_utilities.h" #include "nvs_utilities.h"
#include "cmd_system.h" #include "cmd_system.h"
#include "monitor.h"
#ifndef RECOVERY_APPLICATION #ifndef RECOVERY_APPLICATION
#define RECOVERY_APPLICATION 0 #define RECOVERY_APPLICATION 0
@@ -70,12 +71,7 @@ Contains the freeRTOS task and all necessary support
#ifndef SQUEEZELITE_ESP32_RELEASE_URL #ifndef SQUEEZELITE_ESP32_RELEASE_URL
#define SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases" #define SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases"
#endif #endif
#ifdef CONFIG_SQUEEZEAMP
#define JACK_GPIO 34
#define JACK_LEVEL !gpio_get_level(JACK_GPIO)?"1":"0"
#else
#define JACK_LEVEL "N/A"
#endif
#define STR_OR_BLANK(p) p==NULL?"":p #define STR_OR_BLANK(p) p==NULL?"":p
#define FREE_AND_NULL(p) if(p!=NULL){ free(p); p=NULL;} #define FREE_AND_NULL(p) if(p!=NULL){ free(p); p=NULL;}
/* objects used to manipulate the main queue of events */ /* objects used to manipulate the main queue of events */
@@ -455,7 +451,7 @@ cJSON * wifi_manager_get_basic_info(cJSON **old){
cJSON_AddNumberToObject(root,"recovery", RECOVERY_APPLICATION ); cJSON_AddNumberToObject(root,"recovery", RECOVERY_APPLICATION );
cJSON_AddItemToObject(root, "ota_dsc", cJSON_CreateString(ota_get_status())); cJSON_AddItemToObject(root, "ota_dsc", cJSON_CreateString(ota_get_status()));
cJSON_AddNumberToObject(root,"ota_pct", ota_get_pct_complete() ); cJSON_AddNumberToObject(root,"ota_pct", ota_get_pct_complete() );
cJSON_AddItemToObject(root, "Jack", cJSON_CreateString(JACK_LEVEL)); cJSON_AddItemToObject(root, "Jack", cJSON_CreateString(jack_inserted_svc() ? "1" : "0"));
cJSON_AddNumberToObject(root,"Voltage", adc1_get_raw(ADC1_CHANNEL_7) / 4095. * (10+174)/10. * 1.1); cJSON_AddNumberToObject(root,"Voltage", adc1_get_raw(ADC1_CHANNEL_7) / 4095. * (10+174)/10. * 1.1);
cJSON_AddNumberToObject(root,"disconnect_count", num_disconnect ); cJSON_AddNumberToObject(root,"disconnect_count", num_disconnect );
cJSON_AddNumberToObject(root,"avg_conn_time", num_disconnect>0?(total_connected_time/num_disconnect):0 ); cJSON_AddNumberToObject(root,"avg_conn_time", num_disconnect>0?(total_connected_time/num_disconnect):0 );

View File

@@ -65,13 +65,6 @@ static const char TAG[] = "esp_app_main";
#define DEFAULT_HOST_NAME "squeezelite" #define DEFAULT_HOST_NAME "squeezelite"
char * fwurl = NULL; char * fwurl = NULL;
#ifdef CONFIG_SQUEEZEAMP
#define LED_GREEN_GPIO 12
#define LED_RED_GPIO 13
#else
#define LED_GREEN_GPIO -1
#define LED_RED_GPIO -1
#endif
static bool bWifiConnected=false; static bool bWifiConnected=false;
extern const uint8_t server_cert_pem_start[] asm("_binary_github_pem_start"); extern const uint8_t server_cert_pem_start[] asm("_binary_github_pem_start");
extern const uint8_t server_cert_pem_end[] asm("_binary_github_pem_end"); extern const uint8_t server_cert_pem_end[] asm("_binary_github_pem_end");
@@ -80,15 +73,15 @@ extern void services_init(void);
static const actrls_config_t board_1[] = { static const actrls_config_t board_1[] = {
// normal long shifted long shifted // normal long shifted long shifted
{ 4, BUTTON_LOW, true, 1000, -1, {ACTRLS_VOLUP, ACTRLS_NONE}, {ACTRLS_PREV, ACTRLS_NONE}, {ACTRLS_NONE, ACTRLS_NONE}, {ACTRLS_NONE, ACTRLS_NONE} }, { 4, BUTTON_LOW, true, 0, 1000, -1, {ACTRLS_VOLUP, ACTRLS_NONE}, {ACTRLS_PREV, ACTRLS_NONE}, {ACTRLS_NONE, ACTRLS_NONE}, {ACTRLS_NONE, ACTRLS_NONE} },
{ 5, BUTTON_LOW, true, 1000, 4, {ACTRLS_VOLDOWN, ACTRLS_NONE}, {ACTRLS_NEXT, ACTRLS_NONE}, {ACTRLS_TOGGLE, ACTRLS_NONE}, {BCTRLS_DOWN, ACTRLS_NONE} }, { 5, BUTTON_LOW, true, 0, 1000, 4, {ACTRLS_VOLDOWN, ACTRLS_NONE}, {ACTRLS_NEXT, ACTRLS_NONE}, {ACTRLS_TOGGLE, ACTRLS_NONE}, {BCTRLS_DOWN, ACTRLS_NONE} },
}; };
static const actrls_config_t board_2[] = { static const actrls_config_t board_2[] = {
// normal long shifted long shifted // normal long shifted long shifted
{ 21, BUTTON_LOW, true, 1000, -1, {ACTRLS_TOGGLE, ACTRLS_NONE}, {ACTRLS_STOP, ACTRLS_NONE}, {ACTRLS_NONE, ACTRLS_NONE}, {ACTRLS_NONE, ACTRLS_NONE} }, { 21, BUTTON_LOW, true, 0, 1000, -1, {ACTRLS_TOGGLE, ACTRLS_NONE}, {ACTRLS_STOP, ACTRLS_NONE}, {ACTRLS_NONE, ACTRLS_NONE}, {ACTRLS_NONE, ACTRLS_NONE} },
{ 18, BUTTON_LOW, true, 1000, 21, {ACTRLS_VOLUP, ACTRLS_NONE}, {ACTRLS_NONE, ACTRLS_NONE}, {ACTRLS_NEXT, ACTRLS_NONE}, {ACTRLS_FWD, ACTRLS_PLAY} }, { 18, BUTTON_LOW, true, 0, 1000, 21, {ACTRLS_VOLUP, ACTRLS_NONE}, {ACTRLS_NONE, ACTRLS_NONE}, {ACTRLS_NEXT, ACTRLS_NONE}, {ACTRLS_FWD, ACTRLS_PLAY} },
{ 19, BUTTON_LOW, true, 1000, 21, {ACTRLS_VOLDOWN, ACTRLS_NONE}, {ACTRLS_NONE, ACTRLS_NONE}, {ACTRLS_PREV, ACTRLS_NONE}, {ACTRLS_REW, ACTRLS_PLAY} }, { 19, BUTTON_LOW, true, 0, 1000, 21, {ACTRLS_VOLDOWN, ACTRLS_NONE}, {ACTRLS_NONE, ACTRLS_NONE}, {ACTRLS_PREV, ACTRLS_NONE}, {ACTRLS_REW, ACTRLS_PLAY} },
}; };
static const struct { static const struct {
@@ -372,6 +365,9 @@ void app_main()
ESP_LOGI(TAG,"Setting up config subsystem."); ESP_LOGI(TAG,"Setting up config subsystem.");
config_init(); config_init();
ESP_LOGD(TAG,"Configuring services");
services_init();
ESP_LOGI(TAG,"Registering default values"); ESP_LOGI(TAG,"Registering default values");
register_default_nvs(); register_default_nvs();
@@ -383,7 +379,6 @@ void app_main()
ESP_LOGD(TAG,"Getting firmware OTA URL (if any)"); ESP_LOGD(TAG,"Getting firmware OTA URL (if any)");
fwurl = process_ota_url(); fwurl = process_ota_url();
ESP_LOGD(TAG,"Getting value for WM bypass, nvs 'bypass_wm'"); ESP_LOGD(TAG,"Getting value for WM bypass, nvs 'bypass_wm'");
char * bypass_wm = config_alloc_get_default(NVS_TYPE_STR, "bypass_wm", "0", 0); char * bypass_wm = config_alloc_get_default(NVS_TYPE_STR, "bypass_wm", "0", 0);
if(bypass_wm==NULL) if(bypass_wm==NULL)
@@ -395,13 +390,6 @@ void app_main()
bypass_wifi_manager=(strcmp(bypass_wm,"1")==0 ||strcasecmp(bypass_wm,"y")==0); bypass_wifi_manager=(strcmp(bypass_wm,"1")==0 ||strcasecmp(bypass_wm,"y")==0);
} }
services_init();
ESP_LOGD(TAG,"Configuring Green led");
led_config(LED_GREEN, LED_GREEN_GPIO, 0);
ESP_LOGD(TAG,"Configuring Red led");
led_config(LED_RED, LED_RED_GPIO, 0);
char *board_index = config_alloc_get_default(NVS_TYPE_STR, "board_index", NULL, 0); char *board_index = config_alloc_get_default(NVS_TYPE_STR, "board_index", NULL, 0);
if (board_index) { if (board_index) {
ESP_LOGD(TAG,"Initializing audio control buttons index %u", atoi(board_index)); ESP_LOGD(TAG,"Initializing audio control buttons index %u", atoi(board_index));