mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-10 13:37:03 +03:00
initial refactoring
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -13,115 +13,52 @@
|
||||
#include "driver/i2s.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "gpio_exp.h"
|
||||
#define ASSIGN_GPIO(pin, root, name, mandatory) config_set_gpio(&pin, &(root).name, (root).has_##name, #name, mandatory)
|
||||
|
||||
extern const char *i2c_name_type;
|
||||
extern const char *spi_name_type;
|
||||
#define ASSIGN_COND_VAL_1LVL(name, targetval) \
|
||||
((targetval) = (platform && platform->has_##name ? &(platform->name) : NULL))
|
||||
#define ASSIGN_COND_VAL_2LVL(name1, name2, targetval) \
|
||||
((targetval) = (platform && platform->has_##name1 && platform->name1.has_##name2 ? &(platform->name1.name2) : NULL))
|
||||
#define ASSIGN_COND_VAL_3LVL(name1, name2, name3, targetval) \
|
||||
((targetval) = (platform && platform->has_##name1 && platform->name1.has_##name2 && platform->name1.name2.has_##name3 ? &(platform->name1.name2.name3) : NULL))
|
||||
#define ASSIGN_COND_VAL_4LVL(name1, name2, name3, name4, targetval) \
|
||||
((targetval) = (platform && platform->has_##name1 && platform->name1.has_##name2 && platform->name1.name2.has_##name3 && platform->name1.name2.name3.has_##name4 ? &(platform->name1.name2.name3.name4) : NULL))
|
||||
#define ASSIGN_COND_VAL_5LVL(name1, name2, name3, name4, name5, targetval) \
|
||||
((targetval) = (platform && platform->has_##name1 && platform->name1.has_##name2 && platform->name1.name2.has_##name3 && platform->name1.name2.name3.has_##name4 && platform->name1.name2.name3.name4.has_##name5 ? &(platform->name1.name2.name3.name4.name5) : NULL))
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
int address;
|
||||
int RST_pin;
|
||||
bool hflip;
|
||||
bool vflip;
|
||||
const char *drivername;
|
||||
int CS_pin;
|
||||
int speed;
|
||||
int back;
|
||||
int depth;
|
||||
const char *type;
|
||||
bool rotate;
|
||||
bool invert;
|
||||
int colorswap;
|
||||
int mode;
|
||||
} display_config_t;
|
||||
|
||||
typedef struct eth_config_struct {
|
||||
char model[16];
|
||||
bool valid;
|
||||
bool rmii;
|
||||
bool spi;
|
||||
int rst;
|
||||
int mdc, mdio;
|
||||
int host;
|
||||
int cs, mosi, miso, intr, clk;
|
||||
int speed;
|
||||
} eth_config_t;
|
||||
|
||||
typedef struct {
|
||||
i2s_pin_config_t pin;
|
||||
char model[32];
|
||||
int mute_gpio;
|
||||
int mute_level;
|
||||
int i2c_addr;
|
||||
int sda;
|
||||
int scl;
|
||||
} i2s_platform_config_t;
|
||||
#define SYS_NET(target) ASSIGN_COND_VAL_1LVL(net,target)
|
||||
#define SYS_DISPLAY(target) ASSIGN_COND_VAL_2LVL(dev,display,target)
|
||||
#define SYS_DEV_LEDSTRIP(target) ASSIGN_COND_VAL_2LVL(dev,led_strip,target)
|
||||
#define SYS_DEV_ROTARY(target) ASSIGN_COND_VAL_2LVL(dev,rotary,target)
|
||||
#define SYS_DISPLAY_COMMON(target) ASSIGN_COND_VAL_3LVL(dev,display,common,target)
|
||||
#define SYS_DISPLAY_SPI(target) ASSIGN_COND_VAL_3LVL(dev,display,spi,target)
|
||||
#define SYS_DISPLAY_I2C(target) ASSIGN_COND_VAL_3LVL(dev,display,i2c,target)
|
||||
#define SYS_GPIOS(target) ASSIGN_COND_VAL_2LVL(dev,gpios,target)
|
||||
#define SYS_ETH(target) ASSIGN_COND_VAL_2LVL(dev,eth,target)
|
||||
#define SYS_ETH_COMMON(target) ASSIGN_COND_VAL_3LVL(dev,eth,common,target)
|
||||
|
||||
typedef struct {
|
||||
int gpio;
|
||||
int level;
|
||||
bool fixed;
|
||||
} gpio_with_level_t;
|
||||
|
||||
typedef struct {
|
||||
gpio_with_level_t vcc;
|
||||
gpio_with_level_t gnd;
|
||||
gpio_with_level_t amp;
|
||||
gpio_with_level_t ir;
|
||||
gpio_with_level_t jack;
|
||||
gpio_with_level_t green;
|
||||
gpio_with_level_t red;
|
||||
gpio_with_level_t spkfault;
|
||||
gpio_with_level_t power;
|
||||
} set_GPIO_struct_t;
|
||||
#define SYS_I2CBUS(target) ASSIGN_COND_VAL_2LVL(dev,i2c,target)
|
||||
#define SYS_GPIOS_NAME(name,target) ASSIGN_COND_VAL_2LVL(gpios,name,target)
|
||||
#define SYS_SERVICES(target) ASSIGN_COND_VAL_1LVL(services,target)
|
||||
#define SYS_SERVICES_SPOTIFY(target) ASSIGN_COND_VAL_2LVL(services,cspot,target)
|
||||
#define SYS_SERVICES_METADATA(target) ASSIGN_COND_VAL_2LVL(services,metadata,target)
|
||||
#define SYS_SERVICES_AIRPLAY(target) ASSIGN_COND_VAL_2LVL(services,airplay,target)
|
||||
#define SYS_SERVICES_SLEEP(target) ASSIGN_COND_VAL_2LVL(services,sleep,target)
|
||||
#define SYS_SERVICES_EQUALIZER(target) ASSIGN_COND_VAL_2LVL(services,equalizer,target)
|
||||
|
||||
typedef struct {
|
||||
int A;
|
||||
int B;
|
||||
int SW;
|
||||
bool knobonly;
|
||||
bool volume_lock;
|
||||
bool longpress;
|
||||
int timer;
|
||||
} rotary_struct_t;
|
||||
#define SYS_SERVICES_TELNET(target) ASSIGN_COND_VAL_2LVL(services,telnet,target)
|
||||
#define SYS_SERVICES_BTSINK(target) ASSIGN_COND_VAL_2LVL(services,bt_sink,target)
|
||||
#define SYS_SERVICES_SQUEEZELITE(target) ASSIGN_COND_VAL_2LVL(services,squeezelite,target)
|
||||
|
||||
typedef struct {
|
||||
char type[16];
|
||||
int length;
|
||||
int gpio;
|
||||
} ledvu_struct_t;
|
||||
|
||||
typedef struct {
|
||||
bool fixed;
|
||||
char * name;
|
||||
char * group;
|
||||
int gpio;
|
||||
} gpio_entry_t;
|
||||
#define SYS_DEV_BATTERY(target) ASSIGN_COND_VAL_2LVL(dev,battery,target)
|
||||
|
||||
const display_config_t * config_display_get();
|
||||
const eth_config_t * config_eth_get( );
|
||||
void config_eth_init( eth_config_t * target );
|
||||
esp_err_t config_display_set(const display_config_t * config);
|
||||
esp_err_t config_i2c_set(const i2c_config_t * config, int port);
|
||||
esp_err_t config_i2s_set(const i2s_platform_config_t * config, const char * nvs_name);
|
||||
esp_err_t config_spi_set(const spi_bus_config_t * config, int host, int dc);
|
||||
const i2c_config_t * config_i2c_get(int * i2c_port);
|
||||
const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host);
|
||||
const gpio_exp_config_t * config_gpio_exp_get(int index);
|
||||
void parse_set_GPIO(void (*cb)(int gpio, char *value));
|
||||
const i2s_platform_config_t * config_dac_get();
|
||||
const i2s_platform_config_t * config_spdif_get( );
|
||||
const i2s_platform_config_t * config_i2s_get_from_str(char * dac_config );
|
||||
esp_err_t config_spdif_set(const i2s_platform_config_t * config);
|
||||
bool is_spdif_config_locked();
|
||||
esp_err_t free_gpio_entry( gpio_entry_t ** gpio);
|
||||
gpio_entry_t * get_gpio_by_name(char * name,char * group, bool refresh);
|
||||
gpio_entry_t * get_gpio_by_no(int gpionum, bool refresh);
|
||||
|
||||
bool is_dac_config_locked();
|
||||
bool are_statistics_enabled();
|
||||
const rotary_struct_t * config_rotary_get();
|
||||
esp_err_t config_rotary_set(rotary_struct_t * rotary);
|
||||
const ledvu_struct_t * config_ledvu_get();
|
||||
esp_err_t config_ledvu_set(ledvu_struct_t * ledvu);
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "esp_log.h"
|
||||
#include "cJSON.h"
|
||||
#include "buttons.h"
|
||||
#include "platform_config.h"
|
||||
#include "Configurator.h"
|
||||
#include "accessors.h"
|
||||
#include "services.h"
|
||||
#include "audio_controls.h"
|
||||
@@ -118,50 +118,53 @@ static void ir_handler(uint16_t addr, uint16_t cmd) {
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
static void set_ir_gpio(int gpio, char *value) {
|
||||
if (strcasestr(value, "ir")) {
|
||||
if (strcasestr(value, "rc5")) create_infrared(gpio, ir_handler, IR_RC5);
|
||||
else create_infrared(gpio, ir_handler, IR_NEC);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
esp_err_t actrls_init(const char *profile_name) {
|
||||
esp_err_t err = ESP_OK;
|
||||
char *config = config_alloc_get_default(NVS_TYPE_STR, "rotary_config", NULL, 0);
|
||||
|
||||
if (config && *config) {
|
||||
char *p;
|
||||
int A = -1, B = -1, SW = -1, longpress = 0;
|
||||
|
||||
// parse config
|
||||
PARSE_PARAM(config, "A", '=', A);
|
||||
PARSE_PARAM(config, "B", '=', B);
|
||||
PARSE_PARAM(config, "SW", '=', SW);
|
||||
if ((p = strcasestr(config, "knobonly"))) {
|
||||
p = strchr(p, '=');
|
||||
int double_press = p ? atoi(p + 1) : 350;
|
||||
rotary.timer = xTimerCreate("knobTimer", double_press / portTICK_RATE_MS, pdFALSE, NULL, rotary_timer);
|
||||
longpress = 500;
|
||||
ESP_LOGI(TAG, "single knob navigation %d", double_press);
|
||||
} else {
|
||||
if ((p = strcasestr(config, "volume")) != NULL) rotary.volume_lock = true;
|
||||
if ((p = strcasestr(config, "longpress")) != NULL) longpress = 1000;
|
||||
}
|
||||
|
||||
// create rotary (no handling of long press)
|
||||
err = create_rotary(NULL, A, B, SW, longpress, control_rotary_handler) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
// set infrared GPIO if any
|
||||
parse_set_GPIO(set_ir_gpio);
|
||||
esp_err_t actrls_init(const char* profile_name) {
|
||||
esp_err_t err = ESP_OK;
|
||||
sys_Rotary* dev_config = NULL;
|
||||
if (!SYS_DEV_ROTARY(dev_config) ) {
|
||||
ESP_LOGD(TAG, "Rotary not configured");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (!err) return actrls_init_json(profile_name, true);
|
||||
else return err;
|
||||
char* p;
|
||||
int A = -1, B = -1, SW = -1, longpress = 0;
|
||||
A = dev_config->A.pin;
|
||||
B = dev_config->B.pin;
|
||||
SW = dev_config->SW.pin;
|
||||
|
||||
if (dev_config->has_knobonly && dev_config->knobonly.enable) {
|
||||
p = strchr(p, '=');
|
||||
|
||||
int double_press =
|
||||
dev_config->knobonly.delay_ms > 0 ? dev_config->knobonly.delay_ms : 350;
|
||||
rotary.timer =
|
||||
xTimerCreate("knobTimer", double_press / portTICK_RATE_MS, pdFALSE, NULL, rotary_timer);
|
||||
longpress = 500;
|
||||
ESP_LOGI(TAG, "single knob navigation %d", double_press);
|
||||
} else {
|
||||
|
||||
if (dev_config->volume) rotary.volume_lock = true;
|
||||
if (dev_config->longpress) longpress = 1000;
|
||||
}
|
||||
|
||||
// create rotary (no handling of long press)
|
||||
err = create_rotary(NULL, A, B, SW, longpress, control_rotary_handler) ? ESP_OK : ESP_FAIL;
|
||||
|
||||
if (platform->dev.has_ir && platform->dev.ir.gpio.pin >= 0) {
|
||||
|
||||
if (platform->dev.ir.type == sys_InfraredType_IR_NEC) {
|
||||
create_infrared(platform->dev.ir.gpio.pin, ir_handler, IR_RC5);
|
||||
} else {
|
||||
create_infrared(platform->dev.ir.gpio.pin, ir_handler, IR_NEC);
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
return actrls_init_json(profile_name, true);
|
||||
else
|
||||
return err;
|
||||
return err;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
@@ -509,62 +512,64 @@ static void actrls_defaults(actrls_config_t *config) {
|
||||
*/
|
||||
static esp_err_t actrls_init_json(const char *profile_name, bool create) {
|
||||
esp_err_t err = ESP_OK;
|
||||
actrls_config_t *cur_config = NULL;
|
||||
actrls_config_t *config_root = NULL;
|
||||
char *config;
|
||||
const cJSON *button;
|
||||
#pragma message("Add support to button profile names")
|
||||
// actrls_config_t *cur_config = NULL;
|
||||
// actrls_config_t *config_root = NULL;
|
||||
// char *config=NULL;
|
||||
// const cJSON *button;
|
||||
|
||||
if (!profile_name) return ESP_OK;
|
||||
if ((config = config_alloc_get_str(profile_name, NULL, CONFIG_AUDIO_CONTROLS)) == NULL) return ESP_FAIL;
|
||||
if (!*config) goto exit;
|
||||
// if (!profile_name) return ESP_OK;
|
||||
// //if ((config = config_alloc_get_str(profile_name, NULL, CONFIG_AUDIO_CONTROLS)) == NULL) return ESP_FAIL;
|
||||
// // TODO: Add support for the commented code
|
||||
// if (!*config) goto exit;
|
||||
|
||||
ESP_LOGD(TAG,"Parsing JSON structure %s", config);
|
||||
cJSON *buttons = cJSON_Parse(config);
|
||||
if (buttons == NULL) {
|
||||
ESP_LOGE(TAG,"JSON Parsing failed for %s", config);
|
||||
err = ESP_FAIL;
|
||||
} else {
|
||||
ESP_LOGD(TAG,"Json parsing completed");
|
||||
if (cJSON_IsArray(buttons)) {
|
||||
ESP_LOGD(TAG,"configuration is an array as expected");
|
||||
cur_config =config_root= actrls_init_alloc_structure(buttons, profile_name);
|
||||
if(!cur_config) {
|
||||
ESP_LOGE(TAG,"Config buffer was empty. ");
|
||||
cJSON_Delete(buttons);
|
||||
err = ESP_FAIL;
|
||||
goto exit;
|
||||
}
|
||||
ESP_LOGD(TAG,"Processing button definitions. ");
|
||||
cJSON_ArrayForEach(button, buttons){
|
||||
char * str = cJSON_Print(button);
|
||||
ESP_LOGD(TAG,"Processing %s. ", str?str:"");
|
||||
if(str){
|
||||
free(str);
|
||||
}
|
||||
actrls_defaults(cur_config);
|
||||
esp_err_t loc_err = actrls_process_button(button, cur_config);
|
||||
err = (err == ESP_OK) ? loc_err : err;
|
||||
if (loc_err == ESP_OK) {
|
||||
if (create) button_create((void*) cur_config, cur_config->gpio,cur_config->type,
|
||||
cur_config->pull,cur_config->debounce, control_handler,
|
||||
cur_config->long_press, cur_config->shifter_gpio);
|
||||
} else {
|
||||
ESP_LOGE(TAG,"Error parsing button structure. Button will not be registered.");
|
||||
}
|
||||
// ESP_LOGD(TAG,"Parsing JSON structure %s", config);
|
||||
// cJSON *buttons = cJSON_Parse(config);
|
||||
// if (buttons == NULL) {
|
||||
// ESP_LOGE(TAG,"JSON Parsing failed for %s", config);
|
||||
// err = ESP_FAIL;
|
||||
// } else {
|
||||
// ESP_LOGD(TAG,"Json parsing completed");
|
||||
// if (cJSON_IsArray(buttons)) {
|
||||
// ESP_LOGD(TAG,"configuration is an array as expected");
|
||||
// cur_config =config_root= actrls_init_alloc_structure(buttons, profile_name);
|
||||
// if(!cur_config) {
|
||||
// ESP_LOGE(TAG,"Config buffer was empty. ");
|
||||
// cJSON_Delete(buttons);
|
||||
// err = ESP_FAIL;
|
||||
// goto exit;
|
||||
// }
|
||||
// ESP_LOGD(TAG,"Processing button definitions. ");
|
||||
// cJSON_ArrayForEach(button, buttons){
|
||||
// char * str = cJSON_Print(button);
|
||||
// ESP_LOGD(TAG,"Processing %s. ", str?str:"");
|
||||
// if(str){
|
||||
// free(str);
|
||||
// }
|
||||
// actrls_defaults(cur_config);
|
||||
// esp_err_t loc_err = actrls_process_button(button, cur_config);
|
||||
// err = (err == ESP_OK) ? loc_err : err;
|
||||
// if (loc_err == ESP_OK) {
|
||||
// if (create) button_create((void*) cur_config, cur_config->gpio,cur_config->type,
|
||||
// cur_config->pull,cur_config->debounce, control_handler,
|
||||
// cur_config->long_press, cur_config->shifter_gpio);
|
||||
// } else {
|
||||
// ESP_LOGE(TAG,"Error parsing button structure. Button will not be registered.");
|
||||
// }
|
||||
|
||||
cur_config++;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG,"Invalid configuration; array is expected and none received in %s ", config);
|
||||
}
|
||||
cJSON_Delete(buttons);
|
||||
}
|
||||
// Now update the global json_config object. If we are recursively processing menu structures,
|
||||
// the last init that completes will assigh the first json config object found, which will match
|
||||
// the default config from nvs.
|
||||
json_config = config_root;
|
||||
exit:
|
||||
free(config);
|
||||
// cur_config++;
|
||||
// }
|
||||
// } else {
|
||||
// ESP_LOGE(TAG,"Invalid configuration; array is expected and none received in %s ", config);
|
||||
// }
|
||||
// cJSON_Delete(buttons);
|
||||
// }
|
||||
// // Now update the global json_config object. If we are recursively processing menu structures,
|
||||
// // the last init that completes will assigh the first json config object found, which will match
|
||||
// // the default config from nvs.
|
||||
// json_config = config_root;
|
||||
// exit:
|
||||
// free(config);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "esp_log.h"
|
||||
#include "driver/adc.h"
|
||||
#include "battery.h"
|
||||
#include "platform_config.h"
|
||||
#include "Configurator.h"
|
||||
|
||||
/*
|
||||
There is a bug in esp32 which causes a spurious interrupt on gpio 36/39 when
|
||||
@@ -30,16 +30,13 @@
|
||||
static const char *TAG = "battery";
|
||||
|
||||
static struct {
|
||||
int channel;
|
||||
float sum, avg, scale;
|
||||
int count;
|
||||
int cells, attenuation;
|
||||
sys_Battery * battery_config;
|
||||
TimerHandle_t timer;
|
||||
} battery = {
|
||||
.channel = -1,
|
||||
.cells = 2,
|
||||
};
|
||||
|
||||
} battery;
|
||||
#define BATTERY_CHANNEL(b) (b.battery_config?b.battery_config->channel - sys_BatteryChannelEnum_CH0:-1)
|
||||
#define ATTENUATION(b) (b.battery_config?b.battery_config->atten - sys_BatteryAttenEnum_ATT_0:-1)
|
||||
void (*battery_handler_svc)(float value, int cells);
|
||||
|
||||
/****************************************************************************************
|
||||
@@ -54,7 +51,8 @@ float battery_value_svc(void) {
|
||||
*/
|
||||
uint8_t battery_level_svc(void) {
|
||||
// TODO: this is vastly incorrect
|
||||
int level = battery.avg ? (battery.avg - (3.0 * battery.cells)) / ((4.2 - 3.0) * battery.cells) * 100 : 0;
|
||||
if(!battery.battery_config){ return 0; }
|
||||
int level = battery.avg ? (battery.avg - (3.0 * battery.battery_config->cells)) / ((4.2 - 3.0) * battery.battery_config->cells) * 100 : 0;
|
||||
return level < 100 ? level : 100;
|
||||
}
|
||||
|
||||
@@ -62,11 +60,13 @@ uint8_t battery_level_svc(void) {
|
||||
*
|
||||
*/
|
||||
static void battery_callback(TimerHandle_t xTimer) {
|
||||
battery.sum += adc1_get_raw(battery.channel) * battery.scale / 4095.0;
|
||||
if(!battery.battery_config){ return; }
|
||||
|
||||
battery.sum += adc1_get_raw(BATTERY_CHANNEL(battery)) * battery.battery_config->scale / 4095.0;
|
||||
if (++battery.count == 30) {
|
||||
battery.avg = battery.sum / battery.count;
|
||||
battery.sum = battery.count = 0;
|
||||
if (battery_handler_svc) (battery_handler_svc)(battery.avg, battery.cells);
|
||||
if (battery_handler_svc) (battery_handler_svc)(battery.avg, battery.battery_config->cells);
|
||||
ESP_LOGI(TAG, "Voltage %.2fV", battery.avg);
|
||||
}
|
||||
}
|
||||
@@ -75,31 +75,15 @@ static void battery_callback(TimerHandle_t xTimer) {
|
||||
*
|
||||
*/
|
||||
void battery_svc_init(void) {
|
||||
char *nvs_item = config_alloc_get_default(NVS_TYPE_STR, "bat_config", "", 0);
|
||||
|
||||
#ifdef CONFIG_BAT_LOCKED
|
||||
char *p = nvs_item;
|
||||
asprintf(&nvs_item, CONFIG_BAT_CONFIG ",%s", p);
|
||||
free(p);
|
||||
#endif
|
||||
|
||||
if (nvs_item) {
|
||||
PARSE_PARAM(nvs_item, "channel", '=', battery.channel);
|
||||
PARSE_PARAM_FLOAT(nvs_item, "scale", '=', battery.scale);
|
||||
PARSE_PARAM(nvs_item, "atten", '=', battery.attenuation);
|
||||
PARSE_PARAM(nvs_item, "cells", '=', battery.cells);
|
||||
free(nvs_item);
|
||||
}
|
||||
|
||||
if (battery.channel != -1) {
|
||||
if (SYS_DEV_BATTERY(battery.battery_config) && BATTERY_CHANNEL(battery) != -1) {
|
||||
adc1_config_width(ADC_WIDTH_BIT_12);
|
||||
adc1_config_channel_atten(battery.channel, battery.attenuation);
|
||||
adc1_config_channel_atten(BATTERY_CHANNEL(battery), ATTENUATION(battery));
|
||||
|
||||
battery.avg = adc1_get_raw(battery.channel) * battery.scale / 4095.0;
|
||||
battery.avg = adc1_get_raw(BATTERY_CHANNEL(battery)) * battery.scale / 4095.0;
|
||||
battery.timer = xTimerCreate("battery", BATTERY_TIMER / portTICK_RATE_MS, pdTRUE, NULL, battery_callback);
|
||||
xTimerStart(battery.timer, portMAX_DELAY);
|
||||
|
||||
ESP_LOGI(TAG, "Battery measure channel: %u, scale %f, atten %d, cells %u, avg %.2fV", battery.channel, battery.scale, battery.attenuation, battery.cells, battery.avg);
|
||||
ESP_LOGI(TAG, "Battery measure channel: %u, scale %f, atten %d, cells %u, avg %.2fV", BATTERY_CHANNEL(battery), battery.scale, ATTENUATION(battery), battery.battery_config->cells, battery.avg);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "No battery");
|
||||
}
|
||||
|
||||
@@ -6,28 +6,28 @@
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/rmt.h"
|
||||
#include "platform_config.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/timers.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "Configurator.h"
|
||||
#include "accessors.h"
|
||||
#include "globdefs.h"
|
||||
#include "gpio_exp.h"
|
||||
#include "led.h"
|
||||
#include "globdefs.h"
|
||||
#include "accessors.h"
|
||||
#include "services.h"
|
||||
|
||||
#define MAX_LED 8
|
||||
#define BLOCKTIME 10 // up to portMAX_DELAY
|
||||
#define MAX_LED 8
|
||||
#define BLOCKTIME 10 // up to portMAX_DELAY
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||
#define LEDC_SPEED_MODE LEDC_LOW_SPEED_MODE
|
||||
@@ -35,46 +35,53 @@
|
||||
#define LEDC_SPEED_MODE LEDC_HIGH_SPEED_MODE
|
||||
#endif
|
||||
|
||||
static const char *TAG = "led";
|
||||
static const char* TAG = "led";
|
||||
|
||||
#define RMT_CLK (40/2)
|
||||
#define RMT_CLK (40 / 2)
|
||||
|
||||
static int8_t led_rmt_channel = -1;
|
||||
static uint32_t scale24(uint32_t bright, uint8_t);
|
||||
|
||||
static const struct rmt_led_param_s {
|
||||
led_type_t type;
|
||||
sys_LedTypesEnum type;
|
||||
uint8_t bits;
|
||||
// number of ticks in nanoseconds converted in RMT_CLK ticks
|
||||
rmt_item32_t bit_0;
|
||||
rmt_item32_t bit_1;
|
||||
uint32_t green, red;
|
||||
uint32_t (*scale)(uint32_t, uint8_t);
|
||||
} rmt_led_param[] = {
|
||||
{ LED_WS2812, 24, {{{350 / RMT_CLK, 1, 1000 / RMT_CLK, 0}}}, {{{1000 / RMT_CLK, 1, 350 / RMT_CLK, 0}}}, 0xff0000, 0x00ff00, scale24 },
|
||||
{ .type = -1 } };
|
||||
} rmt_led_param[] = {
|
||||
{sys_LedTypesEnum_LED_TYPE_WS2812, 24, {{{350 / RMT_CLK, 1, 1000 / RMT_CLK, 0}}},
|
||||
{{{1000 / RMT_CLK, 1, 350 / RMT_CLK, 0}}}, 0xff0000, 0x00ff00, scale24},
|
||||
{.type = -1}};
|
||||
|
||||
static EXT_RAM_ATTR struct led_s {
|
||||
gpio_num_t gpio;
|
||||
bool on;
|
||||
uint32_t color;
|
||||
int ontime, offtime;
|
||||
int bright;
|
||||
int channel;
|
||||
const struct rmt_led_param_s *rmt;
|
||||
int pushedon, pushedoff;
|
||||
bool pushed;
|
||||
TimerHandle_t timer;
|
||||
gpio_num_t gpio;
|
||||
bool on;
|
||||
uint32_t color;
|
||||
int ontime, offtime;
|
||||
int bright;
|
||||
int channel;
|
||||
const struct rmt_led_param_s* rmt;
|
||||
int pushedon, pushedoff;
|
||||
bool pushed;
|
||||
TimerHandle_t timer;
|
||||
} leds[MAX_LED];
|
||||
|
||||
// can't use EXT_RAM_ATTR for initialized structure
|
||||
static struct led_config_s {
|
||||
int gpio;
|
||||
int color;
|
||||
int bright;
|
||||
led_type_t type;
|
||||
} green = { .gpio = CONFIG_LED_GREEN_GPIO, .color = 0, .bright = -1, .type = LED_GPIO },
|
||||
red = { .gpio = CONFIG_LED_RED_GPIO, .color = 0, .bright = -1, .type = LED_GPIO };
|
||||
int gpio;
|
||||
int color;
|
||||
int bright;
|
||||
sys_LedTypesEnum type;
|
||||
} green = {.gpio = CONFIG_LED_GREEN_GPIO,
|
||||
.color = 0,
|
||||
.bright = -1,
|
||||
.type = sys_LedTypesEnum_LED_TYPE_GPIO},
|
||||
red = {.gpio = CONFIG_LED_RED_GPIO,
|
||||
.color = 0,
|
||||
.bright = -1,
|
||||
.type = sys_LedTypesEnum_LED_TYPE_GPIO};
|
||||
|
||||
static int led_max = 2;
|
||||
|
||||
@@ -91,7 +98,7 @@ static uint32_t scale24(uint32_t color, uint8_t scale) {
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
static void set_level(struct led_s *led, bool on) {
|
||||
static void set_level(struct led_s* led, bool on) {
|
||||
if (led->rmt) {
|
||||
uint32_t data = on ? led->rmt->scale(led->color, led->bright) : 0;
|
||||
uint32_t mask = 1 << (led->rmt->bits - 1);
|
||||
@@ -104,86 +111,89 @@ static void set_level(struct led_s *led, bool on) {
|
||||
rmt_write_items(led->channel, buffer, led->rmt->bits, false);
|
||||
} else if (led->bright < 0 || led->gpio >= GPIO_NUM_MAX) {
|
||||
gpio_set_level_x(led->gpio, on ? led->color : !led->color);
|
||||
} else {
|
||||
ledc_set_duty(LEDC_SPEED_MODE, led->channel, on ? led->bright : (led->color ? 0 : pwm_system.max));
|
||||
ledc_update_duty(LEDC_SPEED_MODE, led->channel);
|
||||
}
|
||||
} else {
|
||||
ledc_set_duty(
|
||||
LEDC_SPEED_MODE, led->channel, on ? led->bright : (led->color ? 0 : pwm_system.max));
|
||||
ledc_update_duty(LEDC_SPEED_MODE, led->channel);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
static void vCallbackFunction( TimerHandle_t xTimer ) {
|
||||
struct led_s *led = (struct led_s*) pvTimerGetTimerID (xTimer);
|
||||
static void vCallbackFunction(TimerHandle_t xTimer) {
|
||||
struct led_s* led = (struct led_s*)pvTimerGetTimerID(xTimer);
|
||||
|
||||
if (!led->timer) return;
|
||||
if (!led->timer) return;
|
||||
|
||||
led->on = !led->on;
|
||||
ESP_EARLY_LOGD(TAG,"led vCallbackFunction setting gpio %d level %d (bright:%d)", led->gpio, led->on, led->bright);
|
||||
set_level(led, led->on);
|
||||
led->on = !led->on;
|
||||
ESP_EARLY_LOGD(TAG, "led vCallbackFunction setting gpio %d level %d (bright:%d)", led->gpio,
|
||||
led->on, led->bright);
|
||||
set_level(led, led->on);
|
||||
|
||||
// was just on for a while
|
||||
if (!led->on && led->offtime == -1) return;
|
||||
// was just on for a while
|
||||
if (!led->on && led->offtime == -1) return;
|
||||
|
||||
// regular blinking
|
||||
xTimerChangePeriod(xTimer, (led->on ? led->ontime : led->offtime) / portTICK_RATE_MS, BLOCKTIME);
|
||||
// regular blinking
|
||||
xTimerChangePeriod(
|
||||
xTimer, (led->on ? led->ontime : led->offtime) / portTICK_RATE_MS, BLOCKTIME);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
bool led_blink_core(int idx, int ontime, int offtime, bool pushed) {
|
||||
if (!leds[idx].gpio || leds[idx].gpio < 0 ) return false;
|
||||
if (!leds[idx].gpio || leds[idx].gpio < 0) return false;
|
||||
|
||||
ESP_LOGD(TAG,"led_blink_core %d on:%d off:%d, pushed:%u", idx, ontime, offtime, pushed);
|
||||
if (leds[idx].timer) {
|
||||
// normal requests waits if a pop is pending
|
||||
if (!pushed && leds[idx].pushed) {
|
||||
leds[idx].pushedon = ontime;
|
||||
leds[idx].pushedoff = offtime;
|
||||
return true;
|
||||
}
|
||||
xTimerStop(leds[idx].timer, BLOCKTIME);
|
||||
}
|
||||
ESP_LOGD(TAG, "led_blink_core %d on:%d off:%d, pushed:%u", idx, ontime, offtime, pushed);
|
||||
if (leds[idx].timer) {
|
||||
// normal requests waits if a pop is pending
|
||||
if (!pushed && leds[idx].pushed) {
|
||||
leds[idx].pushedon = ontime;
|
||||
leds[idx].pushedoff = offtime;
|
||||
return true;
|
||||
}
|
||||
xTimerStop(leds[idx].timer, BLOCKTIME);
|
||||
}
|
||||
|
||||
// save current state if not already pushed
|
||||
if (!leds[idx].pushed) {
|
||||
leds[idx].pushedon = leds[idx].ontime;
|
||||
leds[idx].pushedoff = leds[idx].offtime;
|
||||
leds[idx].pushed = pushed;
|
||||
}
|
||||
// save current state if not already pushed
|
||||
if (!leds[idx].pushed) {
|
||||
leds[idx].pushedon = leds[idx].ontime;
|
||||
leds[idx].pushedoff = leds[idx].offtime;
|
||||
leds[idx].pushed = pushed;
|
||||
}
|
||||
|
||||
// then set new one
|
||||
leds[idx].ontime = ontime;
|
||||
leds[idx].offtime = offtime;
|
||||
// then set new one
|
||||
leds[idx].ontime = ontime;
|
||||
leds[idx].offtime = offtime;
|
||||
|
||||
if (ontime == 0) {
|
||||
ESP_LOGD(TAG,"led %d, setting reverse level", idx);
|
||||
set_level(leds + idx, false);
|
||||
} else if (offtime == 0) {
|
||||
ESP_LOGD(TAG,"led %d, setting level", idx);
|
||||
set_level(leds + idx, true);
|
||||
} else {
|
||||
if (!leds[idx].timer) {
|
||||
ESP_LOGD(TAG,"led %d, Creating timer", idx);
|
||||
leds[idx].timer = xTimerCreate("ledTimer", ontime / portTICK_RATE_MS, pdFALSE, (void *)&leds[idx], vCallbackFunction);
|
||||
}
|
||||
if (ontime == 0) {
|
||||
ESP_LOGD(TAG, "led %d, setting reverse level", idx);
|
||||
set_level(leds + idx, false);
|
||||
} else if (offtime == 0) {
|
||||
ESP_LOGD(TAG, "led %d, setting level", idx);
|
||||
set_level(leds + idx, true);
|
||||
} else {
|
||||
if (!leds[idx].timer) {
|
||||
ESP_LOGD(TAG, "led %d, Creating timer", idx);
|
||||
leds[idx].timer = xTimerCreate("ledTimer", ontime / portTICK_RATE_MS, pdFALSE,
|
||||
(void*)&leds[idx], vCallbackFunction);
|
||||
}
|
||||
leds[idx].on = true;
|
||||
set_level(leds + idx, true);
|
||||
set_level(leds + idx, true);
|
||||
|
||||
ESP_LOGD(TAG,"led %d, Setting gpio %d and starting timer", idx, leds[idx].gpio);
|
||||
if (xTimerStart(leds[idx].timer, BLOCKTIME) == pdFAIL) return false;
|
||||
}
|
||||
ESP_LOGD(TAG, "led %d, Setting gpio %d and starting timer", idx, leds[idx].gpio);
|
||||
if (xTimerStart(leds[idx].timer, BLOCKTIME) == pdFAIL) return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
bool led_brightness(int idx, int bright) {
|
||||
if (bright > 100) bright = 100;
|
||||
if (bright > 100) bright = 100;
|
||||
|
||||
if (leds[idx].rmt) {
|
||||
leds[idx].bright = bright;
|
||||
@@ -195,86 +205,89 @@ bool led_brightness(int idx, int bright) {
|
||||
ledc_update_duty(LEDC_SPEED_MODE, leds[idx].channel);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
bool led_unpush(int idx) {
|
||||
if (!leds[idx].gpio || leds[idx].gpio<0) return false;
|
||||
if (!leds[idx].gpio || leds[idx].gpio < 0) return false;
|
||||
|
||||
led_blink_core(idx, leds[idx].pushedon, leds[idx].pushedoff, true);
|
||||
leds[idx].pushed = false;
|
||||
led_blink_core(idx, leds[idx].pushedon, leds[idx].pushedoff, true);
|
||||
leds[idx].pushed = false;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
int led_allocate(void) {
|
||||
if (led_max < MAX_LED) return led_max++;
|
||||
return -1;
|
||||
if (led_max < MAX_LED) return led_max++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
bool led_config(int idx, gpio_num_t gpio, int color, int bright, led_type_t type) {
|
||||
if (gpio < 0) {
|
||||
ESP_LOGW(TAG,"LED GPIO -1 ignored");
|
||||
return false;
|
||||
}
|
||||
bool led_config(int idx, sys_LED* led_config) {
|
||||
if (!led_config->has_gpio) {
|
||||
return false;
|
||||
}
|
||||
if (led_config->gpio.pin < 0) {
|
||||
ESP_LOGW(TAG, "LED GPIO -1 ignored");
|
||||
return false;
|
||||
}
|
||||
if (idx >= MAX_LED) return false;
|
||||
if (led_config->brightness > 100) led_config->brightness = 100;
|
||||
|
||||
if (idx >= MAX_LED) return false;
|
||||
|
||||
if (bright > 100) bright = 100;
|
||||
|
||||
leds[idx].gpio = gpio;
|
||||
leds[idx].color = color;
|
||||
leds[idx].gpio = led_config->gpio.pin;
|
||||
leds[idx].color = led_config->gpio.level;
|
||||
leds[idx].rmt = NULL;
|
||||
leds[idx].bright = -1;
|
||||
|
||||
if (type != LED_GPIO) {
|
||||
if (led_config->led_type != sys_LedTypesEnum_LED_TYPE_GPIO) {
|
||||
// first make sure we have a known addressable led
|
||||
for (const struct rmt_led_param_s *p = rmt_led_param; !leds[idx].rmt && p->type >= 0; p++) if (p->type == type) leds[idx].rmt = p;
|
||||
for (const struct rmt_led_param_s* p = rmt_led_param; !leds[idx].rmt && p->type >= 0; p++)
|
||||
if (p->type == led_config->led_type) leds[idx].rmt = p;
|
||||
if (!leds[idx].rmt) return false;
|
||||
|
||||
if (led_rmt_channel < 0) led_rmt_channel = RMT_NEXT_TX_CHANNEL();
|
||||
leds[idx].channel = led_rmt_channel;
|
||||
leds[idx].bright = bright > 0 ? bright : 100;
|
||||
leds[idx].bright = led_config->brightness > 0 ? led_config->brightness : 100;
|
||||
|
||||
// set counter clock to 40MHz
|
||||
rmt_config_t config = RMT_DEFAULT_CONFIG_TX(gpio, leds[idx].channel);
|
||||
rmt_config_t config = RMT_DEFAULT_CONFIG_TX(led_config->gpio.pin, leds[idx].channel);
|
||||
config.clk_div = 2;
|
||||
|
||||
rmt_config(&config);
|
||||
rmt_driver_install(config.channel, 0, 0);
|
||||
} else if (bright < 0 || gpio >= GPIO_NUM_MAX) {
|
||||
gpio_pad_select_gpio_x(gpio);
|
||||
gpio_set_direction_x(gpio, GPIO_MODE_OUTPUT);
|
||||
} else if (led_config->brightness < 0 || led_config->gpio.pin >= GPIO_NUM_MAX) {
|
||||
gpio_pad_select_gpio_x(led_config->gpio.pin);
|
||||
gpio_set_direction_x(led_config->gpio.pin, GPIO_MODE_OUTPUT);
|
||||
} else {
|
||||
leds[idx].channel = pwm_system.base_channel++;
|
||||
leds[idx].bright = pwm_system.max * powf(bright / 100.0, 3);
|
||||
if (!color) leds[idx].bright = pwm_system.max - leds[idx].bright;
|
||||
leds[idx].channel = pwm_system.base_channel++;
|
||||
leds[idx].bright = pwm_system.max * powf(led_config->brightness / 100.0, 3);
|
||||
if (!led_config->gpio.level) leds[idx].bright = pwm_system.max - leds[idx].bright;
|
||||
|
||||
ledc_channel_config_t ledc_channel = {
|
||||
.channel = leds[idx].channel,
|
||||
.duty = leds[idx].bright,
|
||||
.gpio_num = gpio,
|
||||
ledc_channel_config_t ledc_channel = {
|
||||
.channel = leds[idx].channel,
|
||||
.duty = leds[idx].bright,
|
||||
.gpio_num = led_config->gpio.pin,
|
||||
.speed_mode = LEDC_SPEED_MODE,
|
||||
.hpoint = 0,
|
||||
.timer_sel = pwm_system.timer,
|
||||
.hpoint = 0,
|
||||
.timer_sel = pwm_system.timer,
|
||||
};
|
||||
|
||||
ledc_channel_config(&ledc_channel);
|
||||
}
|
||||
ledc_channel_config(&ledc_channel);
|
||||
}
|
||||
|
||||
set_level(leds + idx, false);
|
||||
ESP_LOGD(TAG,"Index %d, GPIO %d, color/onstate %d / RMT %d, bright %d%%", idx, gpio, color, type, bright);
|
||||
|
||||
return true;
|
||||
set_level(leds + idx, false);
|
||||
ESP_LOGI(TAG, "Configuring LED %s %d (on:%d rmt:%s %d%% )", idx == LED_GREEN ? "GREEN" : "RED",
|
||||
led_config->gpio.pin, led_config->gpio.level, sys_LedTypesEnum_name(led_config->led_type),
|
||||
led_config->brightness);
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
@@ -283,31 +296,38 @@ bool led_config(int idx, gpio_num_t gpio, int color, int bright, led_type_t type
|
||||
static void led_suspend(void) {
|
||||
led_off(LED_GREEN);
|
||||
led_off(LED_RED);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
void set_led_gpio(int gpio, char *value) {
|
||||
struct led_config_s *config;
|
||||
void set_led_gpio(int gpio, char* value) {
|
||||
struct led_config_s* config;
|
||||
|
||||
if (strcasestr(value, "green")) config = &green;
|
||||
else if (strcasestr(value, "red"))config = &red;
|
||||
else return;
|
||||
if (strcasestr(value, "green"))
|
||||
config = &green;
|
||||
else if (strcasestr(value, "red"))
|
||||
config = &red;
|
||||
else
|
||||
return;
|
||||
|
||||
config->gpio = gpio;
|
||||
char *p = value;
|
||||
char* p = value;
|
||||
while ((p = strchr(p, ':')) != NULL) {
|
||||
p++;
|
||||
if ((strcasestr(p, "ws2812")) != NULL) config->type = LED_WS2812;
|
||||
else config->color = atoi(p);
|
||||
if ((strcasestr(p, "ws2812")) != NULL)
|
||||
config->type = sys_LedTypesEnum_LED_TYPE_WS2812;
|
||||
else
|
||||
config->color = atoi(p);
|
||||
}
|
||||
|
||||
if (config->type != LED_GPIO) {
|
||||
for (const struct rmt_led_param_s *p = rmt_led_param; p->type >= 0; p++) {
|
||||
if (config->type != sys_LedTypesEnum_LED_TYPE_GPIO) {
|
||||
for (const struct rmt_led_param_s* p = rmt_led_param; p->type >= 0; p++) {
|
||||
if (p->type == config->type) {
|
||||
if (config == &green) config->color = p->green;
|
||||
else config->color = p->red;
|
||||
if (config == &green)
|
||||
config->color = p->green;
|
||||
else
|
||||
config->color = p->red;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -315,31 +335,18 @@ void set_led_gpio(int gpio, char *value) {
|
||||
}
|
||||
|
||||
void led_svc_init(void) {
|
||||
#ifdef CONFIG_LED_GREEN_GPIO_LEVEL
|
||||
green.color = CONFIG_LED_GREEN_GPIO_LEVEL;
|
||||
#endif
|
||||
#ifdef CONFIG_LED_RED_GPIO_LEVEL
|
||||
red.color = CONFIG_LED_RED_GPIO_LEVEL;
|
||||
#endif
|
||||
sys_Gpios* gpios = NULL;
|
||||
if (!platform->has_gpios) {
|
||||
return;
|
||||
}
|
||||
gpios = &platform->gpios;
|
||||
if (gpios->has_greenLED) {
|
||||
led_config(LED_GREEN, &gpios->greenLED);
|
||||
}
|
||||
if (gpios->has_redLED) {
|
||||
led_config(LED_RED, &gpios->redLED);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_LED_LOCKED
|
||||
parse_set_GPIO(set_led_gpio);
|
||||
#endif
|
||||
|
||||
char *nvs_item = config_alloc_get(NVS_TYPE_STR, "led_brightness");
|
||||
if (nvs_item) {
|
||||
PARSE_PARAM(nvs_item, "green", '=', green.bright);
|
||||
PARSE_PARAM(nvs_item, "red", '=', red.bright);
|
||||
free(nvs_item);
|
||||
}
|
||||
|
||||
led_config(LED_GREEN, green.gpio, green.color, green.bright, green.type);
|
||||
led_config(LED_RED, red.gpio, red.color, red.bright, red.type);
|
||||
|
||||
// make sure we switch off all leds (useful for gpio expanders)
|
||||
services_sleep_setsuspend(led_suspend);
|
||||
|
||||
ESP_LOGI(TAG,"Configuring LEDs green:%d (on:%d rmt:%d %d%% ), red:%d (on:%d rmt:%d %d%% )",
|
||||
green.gpio, green.color, green.type, green.bright,
|
||||
red.gpio, red.color, red.type, red.bright);
|
||||
}
|
||||
|
||||
@@ -12,17 +12,16 @@
|
||||
#ifndef LED_H
|
||||
#define LED_H
|
||||
#include "driver/gpio.h"
|
||||
#include "Configurator.h"
|
||||
|
||||
enum { LED_GREEN = 0, LED_RED };
|
||||
typedef enum { LED_GPIO = -1, LED_WS2812 } led_type_t;
|
||||
|
||||
#define led_on(idx) led_blink_core(idx, 1, 0, false)
|
||||
#define led_off(idx) led_blink_core(idx, 0, 0, false)
|
||||
#define led_blink(idx, on, off) led_blink_core(idx, on, off, false)
|
||||
#define led_blink_pushed(idx, on, off) led_blink_core(idx, on, off, true)
|
||||
|
||||
// if type is LED_GPIO then color set the GPIO logic value for "on"
|
||||
bool led_config(int idx, gpio_num_t gpio, int color, int bright, led_type_t type);
|
||||
bool led_config(int idx, sys_LED * led_config);
|
||||
bool led_brightness(int idx, int percent);
|
||||
bool led_blink_core(int idx, int ontime, int offtime, bool push);
|
||||
bool led_unpush(int idx);
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_attr.h"
|
||||
#include "config.h"
|
||||
#include "nvs_utilities.h"
|
||||
// #include "nvs_utilities.h"
|
||||
|
||||
#include "platform_esp32.h"
|
||||
#include "messaging.h"
|
||||
#include "tools.h"
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
#include "buttons.h"
|
||||
#include "led.h"
|
||||
#include "globdefs.h"
|
||||
#include "platform_config.h"
|
||||
// #include "Configurator.h"
|
||||
// TODO: Add support for the commented code: search for TODO in the code below")
|
||||
#include "accessors.h"
|
||||
#include "messaging.h"
|
||||
#include "cJSON.h"
|
||||
@@ -41,8 +42,7 @@ bool jack_inserted_svc(void);
|
||||
void (*spkfault_handler_svc)(bool inserted);
|
||||
bool spkfault_svc(void);
|
||||
|
||||
static monitor_gpio_t jack = { CONFIG_JACK_GPIO, 0 };
|
||||
static monitor_gpio_t spkfault = { CONFIG_SPKFAULT_GPIO, 0 };
|
||||
|
||||
static bool monitor_stats;
|
||||
|
||||
/****************************************************************************************
|
||||
@@ -163,8 +163,11 @@ static void jack_handler_default(void *id, button_event_e event, button_press_e
|
||||
*
|
||||
*/
|
||||
bool jack_inserted_svc (void) {
|
||||
if (jack.gpio != -1) return button_is_pressed(jack.gpio, NULL);
|
||||
else return true;
|
||||
sys_GPIO * jack=NULL;
|
||||
if(SYS_GPIOS_NAME(jack,jack)){
|
||||
return button_is_pressed(jack->pin, NULL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
@@ -181,41 +184,13 @@ static void spkfault_handler_default(void *id, button_event_e event, button_pres
|
||||
*
|
||||
*/
|
||||
bool spkfault_svc (void) {
|
||||
return button_is_pressed(spkfault.gpio, NULL);
|
||||
sys_GPIO * spkfault=NULL;
|
||||
if(SYS_GPIOS_NAME(spkfault,spkfault)){
|
||||
return button_is_pressed(spkfault->pin, NULL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
#ifndef CONFIG_JACK_LOCKED
|
||||
static void set_jack_gpio(int gpio, char *value) {
|
||||
if (strcasestr(value, "jack")) {
|
||||
char *p;
|
||||
jack.gpio = gpio;
|
||||
if ((p = strchr(value, ':')) != NULL) jack.active = atoi(p + 1);
|
||||
}
|
||||
else {
|
||||
jack.gpio = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
#ifndef CONFIG_SPKFAULT_LOCKED
|
||||
static void set_spkfault_gpio(int gpio, char *value) {
|
||||
if (strcasestr(value, "spkfault")) {
|
||||
char *p;
|
||||
spkfault.gpio = gpio;
|
||||
if ((p = strchr(value, ':')) != NULL) spkfault.active = atoi(p + 1);
|
||||
}
|
||||
else {
|
||||
spkfault.gpio = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
@@ -233,40 +208,19 @@ static void pseudo_idle(void *arg) {
|
||||
*
|
||||
*/
|
||||
void monitor_svc_init(void) {
|
||||
ESP_LOGI(TAG, "Initializing monitoring");
|
||||
|
||||
#ifdef CONFIG_JACK_GPIO_LEVEL
|
||||
jack.active = CONFIG_JACK_GPIO_LEVEL;
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_JACK_LOCKED
|
||||
parse_set_GPIO(set_jack_gpio);
|
||||
#endif
|
||||
|
||||
// re-use button management for jack handler, it's a GPIO after all
|
||||
if (jack.gpio != -1) {
|
||||
ESP_LOGI(TAG,"Adding jack (%s) detection GPIO %d", jack.active ? "high" : "low", jack.gpio);
|
||||
button_create(NULL, jack.gpio, jack.active ? BUTTON_HIGH : BUTTON_LOW, false, 250, jack_handler_default, 0, -1);
|
||||
ESP_LOGI(TAG, "Initializing monitoring");
|
||||
sys_Services * services = NULL;
|
||||
sys_GPIO * gpio=NULL;
|
||||
if(SYS_GPIOS_NAME(jack,gpio) && gpio->pin>=0){
|
||||
ESP_LOGI(TAG,"Adding jack (%s) detection GPIO %d", gpio->level ? "high" : "low", gpio->pin);
|
||||
button_create(NULL, gpio->pin, gpio->level ? BUTTON_HIGH : BUTTON_LOW, false, 250, jack_handler_default, 0, -1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPKFAULT_GPIO_LEVEL
|
||||
spkfault.active = CONFIG_SPKFAULT_GPIO_LEVEL;
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SPKFAULT_LOCKED
|
||||
parse_set_GPIO(set_spkfault_gpio);
|
||||
#endif
|
||||
|
||||
// re-use button management for speaker fault handler, it's a GPIO after all
|
||||
if (spkfault.gpio != -1) {
|
||||
ESP_LOGI(TAG,"Adding speaker fault (%s) detection GPIO %d", spkfault.active ? "high" : "low", spkfault.gpio);
|
||||
button_create(NULL, spkfault.gpio, spkfault.active ? BUTTON_HIGH : BUTTON_LOW, false, 0, spkfault_handler_default, 0, -1);
|
||||
if(SYS_GPIOS_NAME(spkfault,gpio) && gpio->pin>=0){
|
||||
ESP_LOGI(TAG,"Adding speaker fault (%s) detection GPIO %d", gpio->level ? "high" : "low", gpio->pin);
|
||||
button_create(NULL, gpio->pin, gpio->level ? BUTTON_HIGH : BUTTON_LOW, false, 0, spkfault_handler_default, 0, -1);
|
||||
}
|
||||
|
||||
// do we want stats
|
||||
char *p = config_alloc_get_default(NVS_TYPE_STR, "stats", "n", 0);
|
||||
monitor_stats = p && (*p == '1' || *p == 'Y' || *p == 'y');
|
||||
FREE_AND_NULL(p);
|
||||
monitor_stats = SYS_SERVICES(services) && services->statistics;
|
||||
|
||||
ESP_LOGI(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu) dma:%zu (min:%zu)",
|
||||
heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
|
||||
@@ -281,18 +235,4 @@ void monitor_svc_init(void) {
|
||||
static EXT_RAM_ATTR StackType_t xStack[PSEUDO_IDLE_STACK_SIZE] __attribute__ ((aligned (4)));
|
||||
xTaskCreateStatic( (TaskFunction_t) pseudo_idle, "pseudo_idle", PSEUDO_IDLE_STACK_SIZE,
|
||||
NULL, ESP_TASK_PRIO_MIN, xStack, xTaskBuffer );
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
monitor_gpio_t * get_spkfault_gpio(){
|
||||
return &spkfault ;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
monitor_gpio_t * get_jack_insertion_gpio(){
|
||||
return &jack;
|
||||
}
|
||||
@@ -9,11 +9,6 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
typedef struct {
|
||||
int gpio;
|
||||
int active;
|
||||
} monitor_gpio_t;
|
||||
|
||||
extern void (*pseudo_idle_svc)(uint32_t now);
|
||||
|
||||
extern void (*jack_handler_svc)(bool inserted);
|
||||
@@ -25,7 +20,3 @@ extern bool spkfault_svc(void);
|
||||
extern void (*battery_handler_svc)(float value, int cells);
|
||||
extern float battery_value_svc(void);
|
||||
extern uint16_t battery_level_svc(void);
|
||||
|
||||
extern monitor_gpio_t * get_spkfault_gpio();
|
||||
extern monitor_gpio_t * get_jack_insertion_gpio();
|
||||
|
||||
|
||||
@@ -12,11 +12,10 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/rmt.h"
|
||||
#include "platform_config.h"
|
||||
#include "Configurator.h"
|
||||
#include "gpio_exp.h"
|
||||
#include "battery.h"
|
||||
#include "led.h"
|
||||
@@ -43,7 +42,7 @@ pwm_system_t pwm_system = {
|
||||
.base_channel = LEDC_CHANNEL_0,
|
||||
.max = (1 << LEDC_TIMER_13_BIT),
|
||||
};
|
||||
|
||||
static sys_SleepService * sleep_config;
|
||||
static EXT_RAM_ATTR struct {
|
||||
uint64_t wake_gpio, wake_level;
|
||||
uint64_t rtc_gpio, rtc_level;
|
||||
@@ -58,46 +57,23 @@ static EXT_RAM_ATTR struct {
|
||||
|
||||
static const char *TAG = "services";
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
void set_chip_power_gpio(int gpio, char *value) {
|
||||
bool parsed = true;
|
||||
|
||||
// we only parse on-chip GPIOs
|
||||
if (gpio >= GPIO_NUM_MAX) return;
|
||||
|
||||
if (!strcasecmp(value, "vcc") ) {
|
||||
gpio_pad_select_gpio(gpio);
|
||||
gpio_set_direction(gpio, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(gpio, 1);
|
||||
} else if (!strcasecmp(value, "gnd")) {
|
||||
gpio_pad_select_gpio(gpio);
|
||||
gpio_set_direction(gpio, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(gpio, 0);
|
||||
} else parsed = false;
|
||||
|
||||
if (parsed) ESP_LOGI(TAG, "set GPIO %u to %s", gpio, value);
|
||||
void set_gpio_level(sys_GPIO*gpio,const char * name, gpio_mode_t mode){
|
||||
gpio_pad_select_gpio(gpio->pin);
|
||||
gpio_set_direction(gpio->pin, mode);
|
||||
gpio_set_level(gpio->pin, gpio->level);
|
||||
ESP_LOGI(TAG, "set GPIO %u to %s, level %d", gpio->pin,name, gpio->level);
|
||||
}
|
||||
void set_chip_power_gpio(sys_Gpios*gpios) {
|
||||
|
||||
if(gpios->has_power){
|
||||
gpios->power.level = 1;
|
||||
set_gpio_level(&gpios->power,"vcc", GPIO_MODE_OUTPUT);
|
||||
}
|
||||
if(gpios->has_GND){
|
||||
gpios->GND.level = 0;
|
||||
set_gpio_level(&gpios->GND,"gnd", GPIO_MODE_OUTPUT);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
void set_exp_power_gpio(int gpio, char *value) {
|
||||
bool parsed = true;
|
||||
|
||||
// we only parse on-chip GPIOs
|
||||
if (gpio < GPIO_NUM_MAX) return;
|
||||
|
||||
if (!strcasecmp(value, "vcc") ) {
|
||||
gpio_exp_set_direction(gpio, GPIO_MODE_OUTPUT, NULL);
|
||||
gpio_exp_set_level(gpio, 1, true, NULL);
|
||||
} else if (!strcasecmp(value, "gnd")) {
|
||||
gpio_exp_set_direction(gpio, GPIO_MODE_OUTPUT, NULL);
|
||||
gpio_exp_set_level(gpio, 0, true, NULL);
|
||||
} else parsed = false;
|
||||
|
||||
if (parsed) ESP_LOGI(TAG, "set expanded GPIO %u to %s", gpio, value);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
@@ -175,76 +151,54 @@ static void sleep_battery(float level, int cells) {
|
||||
*
|
||||
*/
|
||||
void services_sleep_init(void) {
|
||||
char *config = config_alloc_get(NVS_TYPE_STR, "sleep_config");
|
||||
char *p;
|
||||
|
||||
ESP_LOGD(TAG,"Initializing sleep services");
|
||||
if(!SYS_SERVICES_SLEEP(sleep_config)){
|
||||
ESP_LOGD(TAG,"No sleep service configured") ;
|
||||
}
|
||||
// get the wake criteria
|
||||
if ((p = strcasestr(config, "wake"))) {
|
||||
char list[32] = "", item[8];
|
||||
sscanf(p, "%*[^=]=%31[^,]", list);
|
||||
p = list - 1;
|
||||
while (p++ && sscanf(p, "%7[^|]", item)) {
|
||||
int level = 0, gpio = atoi(item);
|
||||
if (!rtc_gpio_is_valid_gpio(gpio)) {
|
||||
ESP_LOGE(TAG, "invalid wake GPIO %d (not in RTC domain)", gpio);
|
||||
} else {
|
||||
sleep_context.wake_gpio |= 1LL << gpio;
|
||||
}
|
||||
if (sscanf(item, "%*[^:]:%d", &level)) sleep_context.wake_level |= level << gpio;
|
||||
p = strchr(p, '|');
|
||||
}
|
||||
|
||||
// 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) {
|
||||
ESP_LOGI(TAG, "Sleep wake-up gpio bitmap 0x%llx (active 0x%llx)", sleep_context.wake_gpio, sleep_context.wake_level);
|
||||
for(int i=0;i<sleep_config->wake_count;i++){
|
||||
if (!rtc_gpio_is_valid_gpio(sleep_config->wake[i].pin)) {
|
||||
ESP_LOGE(TAG, "invalid wake GPIO %d (not in RTC domain)", sleep_config->wake[i].pin);
|
||||
} else {
|
||||
sleep_context.wake_gpio |= 1LL << sleep_config->wake[i].pin;
|
||||
sleep_context.wake_gpio |= 1LL << sleep_config->wake[i].pin;
|
||||
sleep_context.wake_level |= sleep_config->wake[i].level << sleep_config->wake[i].pin;
|
||||
}
|
||||
}
|
||||
// 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) {
|
||||
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);
|
||||
sleep_context.battery_level = sleep_config->batt;
|
||||
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
|
||||
if ((p = strcasestr(config, "rtc"))) {
|
||||
char list[32] = "", item[8];
|
||||
sscanf(p, "%*[^=]=%31[^,]", list);
|
||||
p = list - 1;
|
||||
while (p++ && sscanf(p, "%7[^|]", item)) {
|
||||
int level = 0, gpio = atoi(item);
|
||||
if (!rtc_gpio_is_valid_gpio(gpio)) {
|
||||
ESP_LOGE(TAG, "invalid rtc GPIO %d", gpio);
|
||||
} else {
|
||||
sleep_context.rtc_gpio |= 1LL << gpio;
|
||||
}
|
||||
if (sscanf(item, "%*[^:]:%d", &level)) sleep_context.rtc_level |= level << gpio;
|
||||
p = strchr(p, '|');
|
||||
}
|
||||
|
||||
// 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) {
|
||||
ESP_LOGI(TAG, "RTC forced gpio bitmap 0x%llx (active 0x%llx)", sleep_context.rtc_gpio, sleep_context.rtc_level);
|
||||
for(int i = 0;i<sleep_config->rtc_count;i++){
|
||||
if (!rtc_gpio_is_valid_gpio(sleep_config->rtc[i].pin)) {
|
||||
ESP_LOGE(TAG, "invalid rtc GPIO %d", sleep_config->rtc[i].pin);
|
||||
} else {
|
||||
sleep_context.rtc_gpio |= 1LL << sleep_config->rtc[i].pin;
|
||||
sleep_context.rtc_level |= sleep_config->rtc[i].level << sleep_config->rtc[i].pin;
|
||||
}
|
||||
}
|
||||
// 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) {
|
||||
ESP_LOGI(TAG, "RTC forced gpio bitmap 0x%llx (active 0x%llx)", sleep_context.rtc_gpio, sleep_context.rtc_level);
|
||||
}
|
||||
|
||||
// get the GPIOs that activate sleep (we could check that we have a valid wake)
|
||||
if ((p = strcasestr(config, "sleep"))) {
|
||||
int gpio, level = 0;
|
||||
char sleep[8] = "";
|
||||
sscanf(p, "%*[^=]=%7[^,]", sleep);
|
||||
gpio = atoi(sleep);
|
||||
if ((p = strchr(sleep, ':')) != NULL) level = atoi(p + 1);
|
||||
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);
|
||||
if(sleep_config->has_sleep && sleep_config->sleep.pin >=0 ){
|
||||
ESP_LOGI(TAG, "Sleep activation gpio %d (active %d)", sleep_config->sleep.pin, sleep_config->sleep.level);
|
||||
button_create(NULL, sleep_config->sleep.pin, sleep_config->sleep.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;
|
||||
|
||||
sleep_context.delay = sleep_config->delay*60*1000;
|
||||
|
||||
// now check why we woke-up
|
||||
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
||||
@@ -259,8 +213,11 @@ void services_sleep_init(void) {
|
||||
// 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);
|
||||
if(sleep_config->spurious>0){
|
||||
sleep_context.spurious = sleep_config->spurious;
|
||||
}
|
||||
sleep_context.spurious *= 60*1000;
|
||||
|
||||
ESP_LOGI(TAG, "spurious wake-up detection during %d sec", sleep_context.spurious / 1000);
|
||||
}
|
||||
}
|
||||
@@ -353,7 +310,7 @@ void services_sleep_setsleeper(uint32_t (*sleeper)(void)) {
|
||||
void services_init(void) {
|
||||
messaging_service_init();
|
||||
gpio_install_isr_service(0);
|
||||
|
||||
// todo: untangle i2c stuff
|
||||
#ifdef CONFIG_I2C_LOCKED
|
||||
if (i2c_system_port == 0) {
|
||||
i2c_system_port = 1;
|
||||
@@ -362,7 +319,7 @@ void services_init(void) {
|
||||
#endif
|
||||
|
||||
// set potential power GPIO on chip first in case expanders are power using these
|
||||
parse_set_GPIO(set_chip_power_gpio);
|
||||
set_chip_power_gpio(&platform->gpios);
|
||||
|
||||
// shared I2C bus
|
||||
const i2c_config_t * i2c_config = config_i2c_get(&i2c_system_port);
|
||||
@@ -394,11 +351,43 @@ void services_init(void) {
|
||||
}
|
||||
|
||||
// create GPIO expanders
|
||||
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);
|
||||
|
||||
// now set potential power GPIO on expander
|
||||
parse_set_GPIO(set_exp_power_gpio);
|
||||
gpio_exp_config_t gpio_exp_config;
|
||||
if(platform->has_dev && platform->dev.gpio_exp_count>0){
|
||||
for(int count = 0;count<platform->dev.gpio_exp_count;count++){
|
||||
sys_GPIOExp * exp = &platform->dev.gpio_exp[count];
|
||||
gpio_exp_config.base = exp->base;
|
||||
gpio_exp_config.count = exp->count;
|
||||
gpio_exp_config.phy.addr = exp->addr;
|
||||
if(exp->has_intr){
|
||||
gpio_exp_config.intr = exp->intr.pin;
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG,"Expander doesn't have intr pin");
|
||||
}
|
||||
if(exp->which_ExpType == sys_GPIOExp_spi_tag){
|
||||
gpio_exp_config.phy.cs_pin= exp->ExpType.spi.cs.pin;
|
||||
gpio_exp_config.phy.host = exp->ExpType.spi.host == sys_HostEnum_UNSPECIFIED_HOST ?sys_HostEnum_Host0:exp->ExpType.spi.host -1;
|
||||
gpio_exp_config.phy.speed = exp->ExpType.spi.speed>0?exp->ExpType.spi.speed:0;
|
||||
}
|
||||
else {
|
||||
gpio_exp_config.phy.port = exp->ExpType.i2c.port == sys_PortEnum_UNSPECIFIED_SYSTPORT?sys_PortEnum_SYSTEM:exp->ExpType.i2c.port -1;
|
||||
}
|
||||
strncpy(gpio_exp_config.model,sys_GPIOExpModelEnum_name(exp->model),sizeof(gpio_exp_config.model)-1);
|
||||
gpio_exp_create(&gpio_exp_config);
|
||||
}
|
||||
}
|
||||
if(platform->has_gpios ){
|
||||
// if(platform->gpios.has_GND){
|
||||
// platform->gpios.GND.level = 0;
|
||||
// set_gpio_level(&platform->gpios.GND,"GND", GPIO_MODE_OUTPUT);
|
||||
// }
|
||||
// if(platform->gpios.has_Vcc){
|
||||
// platform->gpios.Vcc.level = 1;
|
||||
// set_gpio_level(&platform->gpios.Vcc,"VCC", GPIO_MODE_OUTPUT);
|
||||
// }
|
||||
set_chip_power_gpio(&platform->gpios);
|
||||
}
|
||||
|
||||
|
||||
// system-wide PWM timer configuration
|
||||
ledc_timer_config_t pwm_timer = {
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Configurator.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum { SLEEP_ONTIMER, SLEEP_ONKEY, SLEEP_ONGPIO, SLEEP_ONIR, SLEEP_ONBATTERY } sleep_cause_e;
|
||||
@@ -15,3 +17,4 @@ void services_sleep_activate(sleep_cause_e cause);
|
||||
void services_sleep_setsuspend(void (*hook)(void));
|
||||
void services_sleep_setsleeper(uint32_t (*sleeper)(void));
|
||||
void services_sleep_init(void);
|
||||
void set_gpio_level(sys_GPIO*gpio,const char * name, gpio_mode_t mode);
|
||||
|
||||
Reference in New Issue
Block a user