mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-09 04:57:06 +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);
|
||||||
|
|
||||||
|
|||||||
@@ -37,35 +37,35 @@ int spi_system_host = SPI_SYSTEM_HOST;
|
|||||||
int spi_system_dc_gpio = -1;
|
int spi_system_dc_gpio = -1;
|
||||||
int rmt_system_base_channel = RMT_CHANNEL_0;
|
int rmt_system_base_channel = RMT_CHANNEL_0;
|
||||||
|
|
||||||
pwm_system_t pwm_system = {
|
pwm_system_t pwm_system = {
|
||||||
.timer = LEDC_TIMER_0,
|
.timer = LEDC_TIMER_0,
|
||||||
.base_channel = LEDC_CHANNEL_0,
|
.base_channel = LEDC_CHANNEL_0,
|
||||||
.max = (1 << LEDC_TIMER_13_BIT),
|
.max = (1 << LEDC_TIMER_13_BIT),
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
||||||
void (*battery_chain)(float level, int cells);
|
void (*battery_chain)(float level, int cells);
|
||||||
void (*suspend[10])(void);
|
void (*suspend[10])(void);
|
||||||
uint32_t (*sleeper[10])(void);
|
uint32_t (*sleeper[10])(void);
|
||||||
} sleep_context;
|
} sleep_context;
|
||||||
|
|
||||||
static const char *TAG = "services";
|
static const char *TAG = "services";
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void set_chip_power_gpio(int gpio, char *value) {
|
void set_chip_power_gpio(int gpio, char *value) {
|
||||||
bool parsed = true;
|
bool parsed = true;
|
||||||
|
|
||||||
// we only parse on-chip GPIOs
|
// we only parse on-chip GPIOs
|
||||||
if (gpio >= GPIO_NUM_MAX) return;
|
if (gpio >= GPIO_NUM_MAX) return;
|
||||||
|
|
||||||
if (!strcasecmp(value, "vcc") ) {
|
if (!strcasecmp(value, "vcc") ) {
|
||||||
gpio_pad_select_gpio(gpio);
|
gpio_pad_select_gpio(gpio);
|
||||||
gpio_set_direction(gpio, GPIO_MODE_OUTPUT);
|
gpio_set_direction(gpio, GPIO_MODE_OUTPUT);
|
||||||
@@ -75,19 +75,19 @@ void set_chip_power_gpio(int gpio, char *value) {
|
|||||||
gpio_set_direction(gpio, GPIO_MODE_OUTPUT);
|
gpio_set_direction(gpio, GPIO_MODE_OUTPUT);
|
||||||
gpio_set_level(gpio, 0);
|
gpio_set_level(gpio, 0);
|
||||||
} else parsed = false;
|
} else parsed = false;
|
||||||
|
|
||||||
if (parsed) ESP_LOGI(TAG, "set GPIO %u to %s", gpio, value);
|
if (parsed) ESP_LOGI(TAG, "set GPIO %u to %s", gpio, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void set_exp_power_gpio(int gpio, char *value) {
|
void set_exp_power_gpio(int gpio, char *value) {
|
||||||
bool parsed = true;
|
bool parsed = true;
|
||||||
|
|
||||||
// we only parse on-chip GPIOs
|
// we only parse on-chip GPIOs
|
||||||
if (gpio < GPIO_NUM_MAX) return;
|
if (gpio < GPIO_NUM_MAX) return;
|
||||||
|
|
||||||
if (!strcasecmp(value, "vcc") ) {
|
if (!strcasecmp(value, "vcc") ) {
|
||||||
gpio_exp_set_direction(gpio, GPIO_MODE_OUTPUT, NULL);
|
gpio_exp_set_direction(gpio, GPIO_MODE_OUTPUT, NULL);
|
||||||
gpio_exp_set_level(gpio, 1, true, NULL);
|
gpio_exp_set_level(gpio, 1, true, NULL);
|
||||||
@@ -95,78 +95,88 @@ void set_exp_power_gpio(int gpio, char *value) {
|
|||||||
gpio_exp_set_direction(gpio, GPIO_MODE_OUTPUT, NULL);
|
gpio_exp_set_direction(gpio, GPIO_MODE_OUTPUT, NULL);
|
||||||
gpio_exp_set_level(gpio, 0, true, NULL);
|
gpio_exp_set_level(gpio, 0, true, NULL);
|
||||||
} else parsed = false;
|
} else parsed = false;
|
||||||
|
|
||||||
if (parsed) ESP_LOGI(TAG, "set expanded GPIO %u to %s", gpio, value);
|
if (parsed) ESP_LOGI(TAG, "set expanded GPIO %u to %s", gpio, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void sleep_gpio_handler(void *id, button_event_e event, button_press_e mode, bool long_press) {
|
static void sleep_gpio_handler(void *id, button_event_e event, button_press_e mode, bool long_press) {
|
||||||
if (event == BUTTON_PRESSED) services_sleep_activate(SLEEP_ONGPIO);
|
if (event == BUTTON_PRESSED) services_sleep_activate(SLEEP_ONGPIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void sleep_battery(float level, int cells) {
|
static void sleep_battery(float level, int cells) {
|
||||||
// chain if any
|
// chain if any
|
||||||
if (sleep_context.battery_chain) sleep_context.battery_chain(level, cells);
|
if (sleep_context.battery_chain) sleep_context.battery_chain(level, cells);
|
||||||
|
|
||||||
// then assess if we have to stop because of low batt
|
// then assess if we have to stop because of low batt
|
||||||
if (level < sleep_context.battery_level) {
|
if (level < sleep_context.battery_level) {
|
||||||
if (sleep_context.battery_count++ == 2) services_sleep_activate(SLEEP_ONBATTERY);
|
if (sleep_context.battery_count++ == 2) services_sleep_activate(SLEEP_ONBATTERY);
|
||||||
} else {
|
} else {
|
||||||
sleep_context.battery_count = 0;
|
sleep_context.battery_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void sleep_init(void) {
|
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];
|
||||||
@@ -182,13 +192,22 @@ static void sleep_init(void) {
|
|||||||
if (sscanf(item, "%*[^:]:%d", &level)) sleep_context.wake_level |= level << gpio;
|
if (sscanf(item, "%*[^:]:%d", &level)) sleep_context.wake_level |= level << gpio;
|
||||||
p = strchr(p, '|');
|
p = strchr(p, '|');
|
||||||
}
|
}
|
||||||
|
|
||||||
// when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can be done
|
// when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can be done
|
||||||
if (sleep_context.wake_gpio) {
|
if (sleep_context.wake_gpio) {
|
||||||
ESP_LOGI(TAG, "Sleep wake-up gpio bitmap 0x%llx (active 0x%llx)", sleep_context.wake_gpio, sleep_context.wake_level);
|
ESP_LOGI(TAG, "Sleep wake-up gpio bitmap 0x%llx (active 0x%llx)", sleep_context.wake_gpio, sleep_context.wake_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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];
|
||||||
@@ -204,42 +223,72 @@ static void sleep_init(void) {
|
|||||||
if (sscanf(item, "%*[^:]:%d", &level)) sleep_context.rtc_level |= level << gpio;
|
if (sscanf(item, "%*[^:]:%d", &level)) sleep_context.rtc_level |= level << gpio;
|
||||||
p = strchr(p, '|');
|
p = strchr(p, '|');
|
||||||
}
|
}
|
||||||
|
|
||||||
// when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can be done
|
// when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can be done
|
||||||
if (sleep_context.rtc_gpio) {
|
if (sleep_context.rtc_gpio) {
|
||||||
ESP_LOGI(TAG, "RTC forced gpio bitmap 0x%llx (active 0x%llx)", sleep_context.rtc_gpio, sleep_context.rtc_level);
|
ESP_LOGI(TAG, "RTC forced gpio bitmap 0x%llx (active 0x%llx)", sleep_context.rtc_gpio, sleep_context.rtc_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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] = "";
|
||||||
sscanf(p, "%*[^=]=%7[^,]", sleep);
|
sscanf(p, "%*[^=]=%7[^,]", sleep);
|
||||||
gpio = atoi(sleep);
|
gpio = atoi(sleep);
|
||||||
if ((p = strchr(sleep, ':')) != NULL) level = atoi(p + 1);
|
if ((p = strchr(sleep, ':')) != NULL) level = atoi(p + 1);
|
||||||
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void services_sleep_activate(sleep_cause_e cause) {
|
void services_sleep_activate(sleep_cause_e cause) {
|
||||||
// call all sleep hooks that might want to do something
|
// call all sleep hooks that might want to do something
|
||||||
for (void (**suspend)(void) = sleep_context.suspend; *suspend; suspend++) (*suspend)();
|
for (void (**suspend)(void) = sleep_context.suspend; *suspend; suspend++) (*suspend)();
|
||||||
|
|
||||||
// isolate all possible GPIOs, except the wake-up and RTC-maintaines ones
|
// isolate all possible GPIOs, except the wake-up and RTC-maintaines ones
|
||||||
esp_sleep_config_gpio_isolate();
|
esp_sleep_config_gpio_isolate();
|
||||||
|
|
||||||
// keep RTC domain up if we need to maintain pull-up/down of some GPIO from RTC
|
// keep RTC domain up if we need to maintain pull-up/down of some GPIO from RTC
|
||||||
if (sleep_context.rtc_gpio) esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
if (sleep_context.rtc_gpio) esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||||
|
|
||||||
for (int i = 0; i < GPIO_NUM_MAX; i++) {
|
for (int i = 0; i < GPIO_NUM_MAX; i++) {
|
||||||
// must be a RTC GPIO
|
// must be a RTC GPIO
|
||||||
if (!rtc_gpio_is_valid_gpio(i)) continue;
|
if (!rtc_gpio_is_valid_gpio(i)) continue;
|
||||||
|
|
||||||
// do we need to maintain a pull-up or down of that GPIO
|
// do we need to maintain a pull-up or down of that GPIO
|
||||||
if ((1LL << i) & sleep_context.rtc_gpio) {
|
if ((1LL << i) & sleep_context.rtc_gpio) {
|
||||||
if ((sleep_context.rtc_level >> i) & 0x01) rtc_gpio_pullup_en(i);
|
if ((sleep_context.rtc_level >> i) & 0x01) rtc_gpio_pullup_en(i);
|
||||||
@@ -249,7 +298,7 @@ void services_sleep_activate(sleep_cause_e cause) {
|
|||||||
rtc_gpio_isolate(i);
|
rtc_gpio_isolate(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// is there just one GPIO
|
// is there just one GPIO
|
||||||
if (sleep_context.wake_gpio & (sleep_context.wake_gpio - 1)) {
|
if (sleep_context.wake_gpio & (sleep_context.wake_gpio - 1)) {
|
||||||
ESP_LOGI(TAG, "going to sleep cause %d, wake-up on multiple GPIO, any '1' wakes up 0x%llx", cause, sleep_context.wake_gpio);
|
ESP_LOGI(TAG, "going to sleep cause %d, wake-up on multiple GPIO, any '1' wakes up 0x%llx", cause, sleep_context.wake_gpio);
|
||||||
@@ -268,13 +317,13 @@ void services_sleep_activate(sleep_cause_e cause) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we need to use a timer in case the same button is used for sleep and wake-up and it's "pressed" vs "released" selected
|
// we need to use a timer in case the same button is used for sleep and wake-up and it's "pressed" vs "released" selected
|
||||||
if (cause == SLEEP_ONKEY) xTimerStart(xTimerCreate("sleepTimer", pdMS_TO_TICKS(1000), pdFALSE, NULL, (void (*)(void*)) esp_deep_sleep_start), 0);
|
if (cause == SLEEP_ONKEY) xTimerStart(xTimerCreate("sleepTimer", pdMS_TO_TICKS(1000), pdFALSE, NULL, (void (*)(void*)) esp_deep_sleep_start), 0);
|
||||||
else esp_deep_sleep_start();
|
else esp_deep_sleep_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void register_method(void **store, size_t size, void *method) {
|
static void register_method(void **store, size_t size, void *method) {
|
||||||
for (int i = 0; i < size; i++, *store++) if (!*store) {
|
for (int i = 0; i < size; i++, *store++) if (!*store) {
|
||||||
@@ -284,26 +333,26 @@ static void register_method(void **store, size_t size, void *method) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void services_sleep_setsuspend(void (*hook)(void)) {
|
void services_sleep_setsuspend(void (*hook)(void)) {
|
||||||
register_method((void**) sleep_context.suspend, sizeof(sleep_context.suspend)/sizeof(*sleep_context.suspend), (void*) hook);
|
register_method((void**) sleep_context.suspend, sizeof(sleep_context.suspend)/sizeof(*sleep_context.suspend), (void*) hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void services_sleep_setsleeper(uint32_t (*sleeper)(void)) {
|
void services_sleep_setsleeper(uint32_t (*sleeper)(void)) {
|
||||||
register_method((void**) sleep_context.sleeper, sizeof(sleep_context.sleeper)/sizeof(*sleep_context.sleeper), (void*) sleeper);
|
register_method((void**) sleep_context.sleeper, sizeof(sleep_context.sleeper)/sizeof(*sleep_context.sleeper), (void*) sleeper);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void services_init(void) {
|
void services_init(void) {
|
||||||
messaging_service_init();
|
messaging_service_init();
|
||||||
gpio_install_isr_service(0);
|
gpio_install_isr_service(0);
|
||||||
|
|
||||||
#ifdef CONFIG_I2C_LOCKED
|
#ifdef CONFIG_I2C_LOCKED
|
||||||
if (i2c_system_port == 0) {
|
if (i2c_system_port == 0) {
|
||||||
i2c_system_port = 1;
|
i2c_system_port = 1;
|
||||||
@@ -314,7 +363,7 @@ void services_init(void) {
|
|||||||
// set potential power GPIO on chip first in case expanders are power using these
|
// set potential power GPIO on chip first in case expanders are power using these
|
||||||
parse_set_GPIO(set_chip_power_gpio);
|
parse_set_GPIO(set_chip_power_gpio);
|
||||||
|
|
||||||
// shared I2C bus
|
// shared I2C bus
|
||||||
const i2c_config_t * i2c_config = config_i2c_get(&i2c_system_port);
|
const i2c_config_t * i2c_config = config_i2c_get(&i2c_system_port);
|
||||||
ESP_LOGI(TAG,"Configuring I2C sda:%d scl:%d port:%u speed:%u", i2c_config->sda_io_num, i2c_config->scl_io_num, i2c_system_port, i2c_config->master.clk_speed);
|
ESP_LOGI(TAG,"Configuring I2C sda:%d scl:%d port:%u speed:%u", i2c_config->sda_io_num, i2c_config->scl_io_num, i2c_system_port, i2c_config->master.clk_speed);
|
||||||
|
|
||||||
@@ -324,11 +373,11 @@ void services_init(void) {
|
|||||||
} else {
|
} else {
|
||||||
i2c_system_port = -1;
|
i2c_system_port = -1;
|
||||||
ESP_LOGW(TAG, "no I2C configured");
|
ESP_LOGW(TAG, "no I2C configured");
|
||||||
}
|
}
|
||||||
|
|
||||||
const spi_bus_config_t * spi_config = config_spi_get((spi_host_device_t*) &spi_system_host);
|
const spi_bus_config_t * spi_config = config_spi_get((spi_host_device_t*) &spi_system_host);
|
||||||
ESP_LOGI(TAG,"Configuring SPI mosi:%d miso:%d clk:%d host:%u dc:%d", spi_config->mosi_io_num, spi_config->miso_io_num, spi_config->sclk_io_num, spi_system_host, spi_system_dc_gpio);
|
ESP_LOGI(TAG,"Configuring SPI mosi:%d miso:%d clk:%d host:%u dc:%d", spi_config->mosi_io_num, spi_config->miso_io_num, spi_config->sclk_io_num, spi_system_host, spi_system_dc_gpio);
|
||||||
|
|
||||||
if (spi_config->mosi_io_num != -1 && spi_config->sclk_io_num != -1) {
|
if (spi_config->mosi_io_num != -1 && spi_config->sclk_io_num != -1) {
|
||||||
spi_bus_initialize( spi_system_host, spi_config, 1 );
|
spi_bus_initialize( spi_system_host, spi_config, 1 );
|
||||||
if (spi_system_dc_gpio != -1) {
|
if (spi_system_dc_gpio != -1) {
|
||||||
@@ -337,35 +386,35 @@ void services_init(void) {
|
|||||||
gpio_set_level( spi_system_dc_gpio, 0 );
|
gpio_set_level( spi_system_dc_gpio, 0 );
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW(TAG, "No DC GPIO set, SPI display will not work");
|
ESP_LOGW(TAG, "No DC GPIO set, SPI display will not work");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
spi_system_host = -1;
|
spi_system_host = -1;
|
||||||
ESP_LOGW(TAG, "no SPI configured");
|
ESP_LOGW(TAG, "no SPI configured");
|
||||||
}
|
}
|
||||||
|
|
||||||
// create GPIO expanders
|
// create GPIO expanders
|
||||||
const gpio_exp_config_t* gpio_exp_config;
|
const gpio_exp_config_t* gpio_exp_config;
|
||||||
for (int count = 0; (gpio_exp_config = config_gpio_exp_get(count)); count++) gpio_exp_create(gpio_exp_config);
|
for (int count = 0; (gpio_exp_config = config_gpio_exp_get(count)); count++) gpio_exp_create(gpio_exp_config);
|
||||||
|
|
||||||
// now set potential power GPIO on expander
|
// now set potential power GPIO on expander
|
||||||
parse_set_GPIO(set_exp_power_gpio);
|
parse_set_GPIO(set_exp_power_gpio);
|
||||||
|
|
||||||
// system-wide PWM timer configuration
|
// system-wide PWM timer configuration
|
||||||
ledc_timer_config_t pwm_timer = {
|
ledc_timer_config_t pwm_timer = {
|
||||||
.duty_resolution = LEDC_TIMER_13_BIT,
|
.duty_resolution = LEDC_TIMER_13_BIT,
|
||||||
.freq_hz = 5000,
|
.freq_hz = 5000,
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||||
#else
|
#else
|
||||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||||
#endif
|
#endif
|
||||||
.timer_num = pwm_system.timer,
|
.timer_num = pwm_system.timer,
|
||||||
};
|
};
|
||||||
|
|
||||||
ledc_timer_config(&pwm_timer);
|
ledc_timer_config(&pwm_timer);
|
||||||
|
|
||||||
led_svc_init();
|
led_svc_init();
|
||||||
battery_svc_init();
|
battery_svc_init();
|
||||||
monitor_svc_init();
|
monitor_svc_init();
|
||||||
sleep_init();
|
sleep_init();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user