mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-09 04:57:06 +03:00
working buttons (LMS only)
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
@@ -28,75 +29,87 @@
|
||||
|
||||
static const char * TAG = "audio_controls";
|
||||
|
||||
typedef struct {
|
||||
void (*volume_up)(void);
|
||||
void (*volume_down)(void);
|
||||
void (*play_toggle)(void);
|
||||
void (*play)(void);
|
||||
void (*pause)(void);
|
||||
void (*stop)(void);
|
||||
} audio_control_t;
|
||||
static actrls_t default_controls, current_controls;
|
||||
|
||||
static audio_control_t default_control, current_control;
|
||||
static void control_handler(void *id, button_event_e event, button_press_e press, bool long_press) {
|
||||
actrls_config_t *key = (actrls_config_t*) id;
|
||||
actrls_action_e action;
|
||||
|
||||
/****************************************************************************************
|
||||
* DOWN button
|
||||
*/
|
||||
static void down(button_event_e event, button_press_e press, bool long_press) {
|
||||
if (press == BUTTON_NORMAL) {
|
||||
if (!long_press) ESP_LOGI(TAG, "volume DOWN %u", event);
|
||||
else ESP_LOGI(TAG, "volume DOWN long %u", event);
|
||||
} else {
|
||||
if (!long_press) ESP_LOGI(TAG, "volume DOWN shifted %u", event);
|
||||
else ESP_LOGI(TAG, "volume DOWN long shifted %u", event);
|
||||
ESP_LOGD(TAG, "control gpio:%u press:%u long:%u event:%u", key->gpio, press, long_press, event);
|
||||
|
||||
switch(press) {
|
||||
case BUTTON_NORMAL:
|
||||
if (long_press) action = key->longpress[event == BUTTON_PRESSED ? 0 : 1];
|
||||
else action = key->normal[event == BUTTON_PRESSED ? 0 : 1];
|
||||
break;
|
||||
case BUTTON_SHIFTED:
|
||||
if (long_press) action = key->longshifted[event == BUTTON_PRESSED ? 0 : 1];
|
||||
else action = key->shifted[event == BUTTON_PRESSED ? 0 : 1];
|
||||
break;
|
||||
default:
|
||||
action = ACTRLS_NONE;
|
||||
break;
|
||||
}
|
||||
//if (event == BUTTON_PRESSED) (*current_control.volume_down)();
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* UP button
|
||||
*/
|
||||
static void up(button_event_e event, button_press_e press, bool long_press) {
|
||||
if (press == BUTTON_NORMAL) {
|
||||
if (!long_press) ESP_LOGI(TAG, "volume UP %u", event);
|
||||
else ESP_LOGI(TAG, "volume UP long %u", event);
|
||||
} else {
|
||||
if (!long_press) ESP_LOGI(TAG, "volume UP shifted %u", event);
|
||||
else ESP_LOGI(TAG, "volume UP long shifted %u", event);
|
||||
if (action != ACTRLS_NONE) {
|
||||
ESP_LOGD(TAG, " calling action %u", action);
|
||||
if (current_controls[action]) (*current_controls[action])();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void up(void *id, button_event_e event, button_press_e press, bool longpress) {
|
||||
if (press == BUTTON_NORMAL) {
|
||||
if (longpress) ESP_LOGI(TAG, "up long %u", event);
|
||||
else ESP_LOGI(TAG, "up %u", event);
|
||||
} else if (press == BUTTON_SHIFTED) {
|
||||
if (longpress) ESP_LOGI(TAG, "up shifted long %u", event);
|
||||
else ESP_LOGI(TAG, "up shifted %u", event);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "don't know what we are doing here %u", event);
|
||||
}
|
||||
}
|
||||
|
||||
void down(void *id, button_event_e event, button_press_e press, bool longpress) {
|
||||
if (press == BUTTON_NORMAL) {
|
||||
if (longpress) ESP_LOGI(TAG, "down long %u", event);
|
||||
else ESP_LOGI(TAG, "down %u", event);
|
||||
} else if (press == BUTTON_SHIFTED) {
|
||||
if (longpress) ESP_LOGI(TAG, "down shifted long %u", event);
|
||||
else ESP_LOGI(TAG, "down shifted %u", event);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "don't know what we are doing here %u", event);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
void actrls_init(int n, actrls_config_t *config) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
button_create(config + i, config[i].gpio, config[i].type, config[i].pull, control_handler, config[i].long_press, config[i].shifter_gpio);
|
||||
}
|
||||
//if (event == BUTTON_PRESSED) (*current_control.volume_up)();
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
void audio_controls_init(void) {
|
||||
/*
|
||||
button_create(18, BUTTON_LOW, true, up, 0, -1);
|
||||
button_create(19, BUTTON_LOW, true, down, 0, -1);
|
||||
button_create(21, BUTTON_LOW, true, play, 0, -1);
|
||||
*/
|
||||
button_create(4, BUTTON_LOW, true, up, 2000, -1);
|
||||
button_create(5, BUTTON_LOW, true, down, 3000, 4);
|
||||
void actrls_set_default(actrls_t controls) {
|
||||
memcpy(default_controls, controls, sizeof(actrls_t));
|
||||
memcpy(current_controls, default_controls, sizeof(actrls_t));
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
void default_audio_control(audio_control_t *control) {
|
||||
default_control = current_control = *control;
|
||||
void actrls_set(actrls_t controls) {
|
||||
memcpy(current_controls, controls, sizeof(actrls_t));
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
void register_audio_control(audio_control_t *control) {
|
||||
current_control = *control;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
void deregister_audio_control(void) {
|
||||
current_control = default_control;
|
||||
void actrls_unset(void) {
|
||||
memcpy(current_controls, default_controls, sizeof(actrls_t));
|
||||
}
|
||||
|
||||
@@ -18,4 +18,25 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
void audio_controls_init(void);
|
||||
#include "buttons.h"
|
||||
|
||||
// BEWARE: this is the index of the array of action below
|
||||
typedef enum { ACTRLS_NONE = -1, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY,
|
||||
ACTRLS_PAUSE, ACTRLS_STOP, ACTRLS_REW, ACTRLS_FWD, ACTRLS_PREV, ACTRLS_NEXT,
|
||||
ACTRLS_MAX
|
||||
} actrls_action_e;
|
||||
typedef void (*actrls_handler)(void);
|
||||
typedef actrls_handler actrls_t[ACTRLS_MAX - ACTRLS_NONE - 1];
|
||||
typedef struct {
|
||||
int gpio;
|
||||
int type;
|
||||
bool pull;
|
||||
int long_press;
|
||||
int shifter_gpio;
|
||||
actrls_action_e normal[2], longpress[2], shifted[2], longshifted[2]; // [0] keypressed, [1] keyreleased
|
||||
} actrls_config_t;
|
||||
|
||||
void actrls_init(int n, actrls_config_t *config);
|
||||
void actrls_set_default(actrls_t controls);
|
||||
void actrls_set(actrls_t controls);
|
||||
void actrls_unset(void);
|
||||
|
||||
@@ -40,6 +40,7 @@ static int n_buttons = 0;
|
||||
#define DEBOUNCE 50
|
||||
|
||||
static struct button_s {
|
||||
void *id;
|
||||
int gpio, index;
|
||||
button_handler handler;
|
||||
struct button_s *shifter;
|
||||
@@ -73,6 +74,7 @@ static void buttons_timer( TimerHandle_t xTimer ) {
|
||||
struct button_s *button = (struct button_s*) pvTimerGetTimerID (xTimer);
|
||||
|
||||
button->level = gpio_get_level(button->gpio);
|
||||
if (button->shifter && button->shifter->type == button->shifter->level) button->shifter->shifting = true;
|
||||
|
||||
if (button->long_press && !button->long_timer && button->level == button->type) {
|
||||
// detect a long press, so hold event generation
|
||||
@@ -97,7 +99,7 @@ static void buttons_task(void* arg) {
|
||||
while (1) {
|
||||
struct button_s button;
|
||||
button_event_e event;
|
||||
button_press_e press = BUTTON_NORMAL;
|
||||
button_press_e press;
|
||||
|
||||
if (!xQueueReceive(button_evt_queue, &button, portMAX_DELAY)) continue;
|
||||
|
||||
@@ -106,10 +108,8 @@ static void buttons_task(void* arg) {
|
||||
ESP_LOGD(TAG, "received event:%u from gpio:%u level:%u (timer %u shifting %u)", event, button.gpio, button.level, button.long_timer, button.shifting);
|
||||
|
||||
// find if shifting is activated
|
||||
if (button.shifter && button.shifter->type == button.shifter->level) {
|
||||
button.shifter->shifting = true;
|
||||
press = BUTTON_SHIFTED;
|
||||
}
|
||||
if (button.shifter && button.shifter->type == button.shifter->level) press = BUTTON_SHIFTED;
|
||||
else press = BUTTON_NORMAL;
|
||||
|
||||
/*
|
||||
long_timer will be set either because we truly have a long press
|
||||
@@ -120,18 +120,18 @@ static void buttons_task(void* arg) {
|
||||
if (event == BUTTON_RELEASED) {
|
||||
// early release of a long-press button, send press/release
|
||||
if (!button.shifting) {
|
||||
(*button.handler)(BUTTON_PRESSED, press, false);
|
||||
(*button.handler)(BUTTON_RELEASED, press, false);
|
||||
(*button.handler)(button.id, BUTTON_PRESSED, press, false);
|
||||
(*button.handler)(button.id, BUTTON_RELEASED, press, false);
|
||||
}
|
||||
// button is a copy, so need to go to real context
|
||||
buttons[button.index].shifting = false;
|
||||
} else if (!button.shifting) {
|
||||
// normal long press and not shifting so don't discard
|
||||
(*button.handler)(BUTTON_PRESSED, press, true);
|
||||
(*button.handler)(button.id, BUTTON_PRESSED, press, true);
|
||||
}
|
||||
} else {
|
||||
// normal press/release of a button or release of a long-press button
|
||||
if (!button.shifting) (*button.handler)(event, press, button.long_press);
|
||||
if (!button.shifting) (*button.handler)(button.id, event, press, button.long_press);
|
||||
// button is a copy, so need to go to real context
|
||||
buttons[button.index].shifting = false;
|
||||
}
|
||||
@@ -141,14 +141,14 @@ static void buttons_task(void* arg) {
|
||||
/****************************************************************************************
|
||||
* dummy button handler
|
||||
*/
|
||||
void dummy_handler(button_event_e event, button_press_e press) {
|
||||
void dummy_handler(void *id, button_event_e event, button_press_e press) {
|
||||
ESP_LOGW(TAG, "should not be here");
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Create buttons
|
||||
*/
|
||||
void button_create(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, button_handler handler, int long_press, int shifter_gpio) {
|
||||
|
||||
if (n_buttons >= MAX_BUTTONS) return;
|
||||
|
||||
@@ -157,13 +157,14 @@ void button_create(int gpio, int type, bool pull, button_handler handler, int lo
|
||||
if (!n_buttons) {
|
||||
button_evt_queue = xQueueCreate(10, sizeof(struct button_s));
|
||||
gpio_install_isr_service(0);
|
||||
xTaskCreate(buttons_task, "buttons_task", 2048, NULL, ESP_TASK_PRIO_MIN + 1, NULL);
|
||||
xTaskCreate(buttons_task, "buttons_task", 8192, NULL, ESP_TASK_PRIO_MIN + 1, NULL);
|
||||
}
|
||||
|
||||
// just in case this structure is allocated later
|
||||
// just in case this structure is allocated in a future release
|
||||
memset(buttons + n_buttons, 0, sizeof(struct button_s));
|
||||
|
||||
// set mandatory parameters
|
||||
buttons[n_buttons].id = id;
|
||||
buttons[n_buttons].gpio = gpio;
|
||||
buttons[n_buttons].handler = handler;
|
||||
buttons[n_buttons].long_press = long_press;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
typedef enum { BUTTON_PRESSED, BUTTON_RELEASED } button_event_e;
|
||||
typedef enum { BUTTON_NORMAL, BUTTON_SHIFTED } button_press_e;
|
||||
typedef void (*button_handler)(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 long_press to 0 for no long-press
|
||||
@@ -32,4 +32,4 @@ set shifter_gpio to -1 for no shift
|
||||
NOTE: shifter buttons *must* be created before shiftee
|
||||
*/
|
||||
|
||||
void button_create(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, button_handler handler, int long_press, int shifter_gpio);
|
||||
Reference in New Issue
Block a user