mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-08 12:37:01 +03:00
add (some) spurious IR detection capability
This commit is contained in:
@@ -22,6 +22,8 @@ static const char* TAG = "IR";
|
|||||||
#define IR_TOOLS_FLAGS_PROTO_EXT (1 << 0) /*!< Enable Extended IR protocol */
|
#define IR_TOOLS_FLAGS_PROTO_EXT (1 << 0) /*!< Enable Extended IR protocol */
|
||||||
#define IR_TOOLS_FLAGS_INVERSE (1 << 1) /*!< Inverse the IR signal, i.e. take high level as low, and vice versa */
|
#define IR_TOOLS_FLAGS_INVERSE (1 << 1) /*!< Inverse the IR signal, i.e. take high level as low, and vice versa */
|
||||||
|
|
||||||
|
static int8_t ir_gpio = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief IR device type
|
* @brief IR device type
|
||||||
*
|
*
|
||||||
@@ -478,6 +480,12 @@ bool infrared_receive(RingbufHandle_t rb, infrared_handler handler) {
|
|||||||
return decoded;
|
return decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int8_t infrared_gpio(void) {
|
||||||
|
return ir_gpio;
|
||||||
|
};
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
@@ -491,6 +499,7 @@ void infrared_init(RingbufHandle_t *rb, int gpio, infrared_mode_t mode) {
|
|||||||
ir_parser_config.flags |= IR_TOOLS_FLAGS_PROTO_EXT; // Using extended IR protocols (both NEC and RC5 have extended version)
|
ir_parser_config.flags |= IR_TOOLS_FLAGS_PROTO_EXT; // Using extended IR protocols (both NEC and RC5 have extended version)
|
||||||
|
|
||||||
ir_parser = (mode == IR_NEC) ? ir_parser_rmt_new_nec(&ir_parser_config) : ir_parser_rmt_new_rc5(&ir_parser_config);
|
ir_parser = (mode == IR_NEC) ? ir_parser_rmt_new_nec(&ir_parser_config) : ir_parser_rmt_new_rc5(&ir_parser_config);
|
||||||
|
ir_gpio = gpio;
|
||||||
|
|
||||||
// get RMT RX ringbuffer
|
// get RMT RX ringbuffer
|
||||||
rmt_get_ringbuf_handle(rmt_channel, rb);
|
rmt_get_ringbuf_handle(rmt_channel, rb);
|
||||||
|
|||||||
@@ -17,4 +17,5 @@ typedef void (*infrared_handler)(uint16_t addr, uint16_t cmd);
|
|||||||
|
|
||||||
bool infrared_receive(RingbufHandle_t rb, infrared_handler handler);
|
bool infrared_receive(RingbufHandle_t rb, infrared_handler handler);
|
||||||
void infrared_init(RingbufHandle_t *rb, int gpio, infrared_mode_t mode);
|
void infrared_init(RingbufHandle_t *rb, int gpio, infrared_mode_t mode);
|
||||||
|
int8_t infrared_gpio(void);
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ pwm_system_t pwm_system = {
|
|||||||
static EXT_RAM_ATTR struct {
|
static EXT_RAM_ATTR struct {
|
||||||
uint64_t wake_gpio, wake_level;
|
uint64_t wake_gpio, wake_level;
|
||||||
uint64_t rtc_gpio, rtc_level;
|
uint64_t rtc_gpio, rtc_level;
|
||||||
uint32_t delay;
|
uint32_t delay, spurious;
|
||||||
float battery_level;
|
float battery_level;
|
||||||
int battery_count;
|
int battery_count;
|
||||||
void (*idle_chain)(uint32_t now);
|
void (*idle_chain)(uint32_t now);
|
||||||
@@ -110,22 +110,49 @@ static void sleep_gpio_handler(void *id, button_event_e event, button_press_e mo
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void sleep_timer(uint32_t now) {
|
static void sleep_timer(uint32_t now) {
|
||||||
static uint32_t last;
|
static EXT_RAM_ATTR uint32_t last, first;
|
||||||
|
|
||||||
// first chain the calls to psudo_idle function
|
// first chain the calls to pseudo_idle function
|
||||||
if (sleep_context.idle_chain) sleep_context.idle_chain(now);
|
if (sleep_context.idle_chain) sleep_context.idle_chain(now);
|
||||||
|
|
||||||
|
// we need boot time for spurious timeout calculation
|
||||||
|
if (!first) first = now;
|
||||||
|
|
||||||
// only query callbacks every 30s if we have at least one sleeper
|
// only query callbacks every 30s if we have at least one sleeper
|
||||||
if (!*sleep_context.sleeper || now < last + 30*1000) return;
|
if (!*sleep_context.sleeper || now < last + 30*1000) return;
|
||||||
last = now;
|
last = now;
|
||||||
|
|
||||||
// call all sleep hooks that might want to do something
|
// time to evaluate if we had spurious wake-up
|
||||||
for (uint32_t (**sleeper)(void) = sleep_context.sleeper; *sleeper; sleeper++) {
|
if (sleep_context.spurious && now > sleep_context.spurious + first) {
|
||||||
if ((*sleeper)() < sleep_context.delay) return;
|
bool spurious = true;
|
||||||
|
|
||||||
|
// see if at least one sleeper has been awake since we started
|
||||||
|
for (uint32_t (**sleeper)(void) = sleep_context.sleeper; *sleeper && spurious; sleeper++) {
|
||||||
|
spurious &= (*sleeper)() >= now - first;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no activity since we woke-up, this was a spurious one
|
||||||
|
if (spurious) {
|
||||||
|
ESP_LOGI(TAG, "spurious wake of %d sec, going back to sleep", (now - first) / 1000);
|
||||||
|
services_sleep_activate(SLEEP_ONTIMER);
|
||||||
|
}
|
||||||
|
|
||||||
|
// resume normal work but we might have no "regular" inactivity delay
|
||||||
|
sleep_context.spurious = 0;
|
||||||
|
if (!sleep_context.delay) *sleep_context.sleeper = NULL;
|
||||||
|
ESP_LOGI(TAG, "wake-up was not spurious after %d sec", (now - first) / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we are here, we are ready to sleep;
|
// we might be here because we are waiting for spurious
|
||||||
services_sleep_activate(SLEEP_ONTIMER);
|
if (sleep_context.delay) {
|
||||||
|
// call all sleepers to know how long for how long they have been inactive
|
||||||
|
for (uint32_t (**sleeper)(void) = sleep_context.sleeper; sleep_context.delay && *sleeper; sleeper++) {
|
||||||
|
if ((*sleeper)() < sleep_context.delay) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we are here, we are ready to sleep;
|
||||||
|
services_sleep_activate(SLEEP_ONTIMER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
@@ -150,23 +177,6 @@ static void sleep_init(void) {
|
|||||||
char *config = config_alloc_get(NVS_TYPE_STR, "sleep_config");
|
char *config = config_alloc_get(NVS_TYPE_STR, "sleep_config");
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
// do we want delay sleep
|
|
||||||
PARSE_PARAM(config, "delay", '=', sleep_context.delay);
|
|
||||||
sleep_context.delay *= 60*1000;
|
|
||||||
if (sleep_context.delay) {
|
|
||||||
sleep_context.idle_chain = pseudo_idle_svc;
|
|
||||||
pseudo_idle_svc = sleep_timer;
|
|
||||||
ESP_LOGI(TAG, "Sleep inactivity of %d minute(s)", sleep_context.delay / (60*1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
// do we want battery safety
|
|
||||||
PARSE_PARAM_FLOAT(config, "batt", '=', sleep_context.battery_level);
|
|
||||||
if (sleep_context.battery_level != 0.0) {
|
|
||||||
sleep_context.battery_chain = battery_handler_svc;
|
|
||||||
battery_handler_svc = sleep_battery;
|
|
||||||
ESP_LOGI(TAG, "Sleep on battery level of %.2f", sleep_context.battery_level);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the wake criteria
|
// get the wake criteria
|
||||||
if ((p = strcasestr(config, "wake"))) {
|
if ((p = strcasestr(config, "wake"))) {
|
||||||
char list[32] = "", item[8];
|
char list[32] = "", item[8];
|
||||||
@@ -189,6 +199,15 @@ static void sleep_init(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do we want battery safety
|
||||||
|
PARSE_PARAM_FLOAT(config, "batt", '=', sleep_context.battery_level);
|
||||||
|
if (sleep_context.battery_level != 0.0) {
|
||||||
|
sleep_context.battery_chain = battery_handler_svc;
|
||||||
|
battery_handler_svc = sleep_battery;
|
||||||
|
ESP_LOGI(TAG, "Sleep on battery level of %.2f", sleep_context.battery_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// get the rtc-pull criteria
|
// get the rtc-pull criteria
|
||||||
if ((p = strcasestr(config, "rtc"))) {
|
if ((p = strcasestr(config, "rtc"))) {
|
||||||
char list[32] = "", item[8];
|
char list[32] = "", item[8];
|
||||||
@@ -211,7 +230,7 @@ static void sleep_init(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// then get the gpio that activate sleep (we could check that we have a valid wake)
|
// get the GPIOs that activate sleep (we could check that we have a valid wake)
|
||||||
if ((p = strcasestr(config, "sleep"))) {
|
if ((p = strcasestr(config, "sleep"))) {
|
||||||
int gpio, level = 0;
|
int gpio, level = 0;
|
||||||
char sleep[8] = "";
|
char sleep[8] = "";
|
||||||
@@ -221,6 +240,36 @@ static void sleep_init(void) {
|
|||||||
ESP_LOGI(TAG, "Sleep activation gpio %d (active %d)", gpio, level);
|
ESP_LOGI(TAG, "Sleep activation gpio %d (active %d)", gpio, level);
|
||||||
button_create(NULL, gpio, level ? BUTTON_HIGH : BUTTON_LOW, true, 0, sleep_gpio_handler, 0, -1);
|
button_create(NULL, gpio, level ? BUTTON_HIGH : BUTTON_LOW, true, 0, sleep_gpio_handler, 0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do we want delay sleep
|
||||||
|
PARSE_PARAM(config, "delay", '=', sleep_context.delay);
|
||||||
|
sleep_context.delay *= 60*1000;
|
||||||
|
|
||||||
|
// now check why we woke-up
|
||||||
|
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
||||||
|
if (cause == ESP_SLEEP_WAKEUP_EXT0 || cause == ESP_SLEEP_WAKEUP_EXT1) {
|
||||||
|
ESP_LOGI(TAG, "waking-up from deep sleep with cause %d", cause);
|
||||||
|
|
||||||
|
// find the type of wake-up
|
||||||
|
uint64_t wake_gpio;
|
||||||
|
if (cause == ESP_SLEEP_WAKEUP_EXT0) wake_gpio = sleep_context.wake_gpio;
|
||||||
|
else wake_gpio = esp_sleep_get_ext1_wakeup_status();
|
||||||
|
|
||||||
|
// we might be woken up by infrared in which case we want a short sleep
|
||||||
|
if (infrared_gpio() >= 0 && ((1LL << infrared_gpio()) & wake_gpio)) {
|
||||||
|
sleep_context.spurious = 1;
|
||||||
|
PARSE_PARAM(config, "spurious", '=', sleep_context.spurious);
|
||||||
|
sleep_context.spurious *= 60*1000;
|
||||||
|
ESP_LOGI(TAG, "spurious wake-up detection during %d sec", sleep_context.spurious / 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have inactivity timer (user-set or because of IR wake) then active counters
|
||||||
|
if (sleep_context.delay || sleep_context.spurious) {
|
||||||
|
sleep_context.idle_chain = pseudo_idle_svc;
|
||||||
|
pseudo_idle_svc = sleep_timer;
|
||||||
|
if (sleep_context.delay) ESP_LOGI(TAG, "inactivity timer of %d minute(s)", sleep_context.delay / (60*1000));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
|
|||||||
Reference in New Issue
Block a user