mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2026-01-28 13:20:49 +03:00
Start of 5.X work
This commit is contained in:
@@ -5,44 +5,46 @@
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/timers.h"
|
||||
#include <stdio.h>
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include "Config.h"
|
||||
#include "accessors.h"
|
||||
#include "battery.h"
|
||||
#include "buttons.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/rmt.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/rmt.h"
|
||||
#include "Configurator.h"
|
||||
#include "gpio_exp.h"
|
||||
#include "battery.h"
|
||||
#include "led.h"
|
||||
#include "monitor.h"
|
||||
#include "globdefs.h"
|
||||
#include "accessors.h"
|
||||
#include "gpio_exp.h"
|
||||
#include "led.h"
|
||||
#include "messaging.h"
|
||||
#include "buttons.h"
|
||||
#include "monitor.h"
|
||||
#include "services.h"
|
||||
#include "tools.h"
|
||||
|
||||
extern void battery_svc_init(void);
|
||||
extern void monitor_svc_init(void);
|
||||
extern void led_svc_init(void);
|
||||
|
||||
int i2c_system_port = I2C_SYSTEM_PORT;
|
||||
int i2c_system_speed = 400000;
|
||||
int spi_system_host = SPI_SYSTEM_HOST;
|
||||
int spi_system_dc_gpio = -1;
|
||||
int rmt_system_base_tx_channel = RMT_CHANNEL_0;
|
||||
int rmt_system_base_rx_channel = RMT_CHANNEL_MAX-1;
|
||||
int rmt_system_base_rx_channel = RMT_CHANNEL_MAX - 1;
|
||||
|
||||
pwm_system_t pwm_system = {
|
||||
.timer = LEDC_TIMER_0,
|
||||
.base_channel = LEDC_CHANNEL_0,
|
||||
.max = (1 << LEDC_TIMER_13_BIT),
|
||||
.timer = LEDC_TIMER_0,
|
||||
.base_channel = LEDC_CHANNEL_0,
|
||||
.max = (1 << LEDC_TIMER_13_BIT),
|
||||
};
|
||||
static sys_SleepService * sleep_config;
|
||||
static sys_sleep_config* sleep_config;
|
||||
static EXT_RAM_ATTR uint8_t gpio_exp_count = 0;
|
||||
static EXT_RAM_ATTR bool spi_configured = false;
|
||||
static EXT_RAM_ATTR bool i2c_configured = false;
|
||||
static EXT_RAM_ATTR struct {
|
||||
uint64_t wake_gpio, wake_level;
|
||||
uint64_t rtc_gpio, rtc_level;
|
||||
@@ -55,31 +57,93 @@ static EXT_RAM_ATTR struct {
|
||||
uint32_t (*sleeper[10])(void);
|
||||
} sleep_context;
|
||||
|
||||
static const char *TAG = "services";
|
||||
static const char* TAG = "services";
|
||||
|
||||
void set_gpio_level(sys_GPIO*gpio,const char * name, gpio_mode_t mode){
|
||||
bool are_GPIOExp_equal(const sys_exp_config* exp1, const sys_exp_config* exp2) {
|
||||
if (exp1 == NULL || exp2 == NULL) {
|
||||
return false; // Safeguard against NULL pointers
|
||||
}
|
||||
|
||||
// Check if model, address, and base are the same
|
||||
if (exp1->model != exp2->model || exp1->addr != exp2->addr || exp1->base != exp2->base) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if intr structure (pin and level) are the same
|
||||
if (exp1->intr != exp2->intr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sys_dev_config_callback(pb_istream_t* istream, pb_ostream_t* ostream, const pb_field_iter_t* field) {
|
||||
ESP_LOGV(TAG, "Decoding/Encoding Devices, tag: %d", field->tag);
|
||||
sys_exp_config** pExp = (sys_exp_config**)field->pData;
|
||||
sys_exp_config* exp = NULL;
|
||||
|
||||
if (istream != NULL && field->tag == sys_dev_config_gpio_exp_tag) {
|
||||
ESP_LOGD(TAG, "Decoding GPIO Expander #%d", gpio_exp_count + 1);
|
||||
sys_exp_config entry = sys_exp_config_init_default;
|
||||
if (!pb_decode(istream, &sys_exp_config_msg, &entry)) {
|
||||
return false;
|
||||
}
|
||||
if (entry.model == sys_exp_models_UNSPECIFIED_EXP) {
|
||||
ESP_LOGD(TAG, "Skipping GPIO Expander model %s", sys_exp_models_name(entry.model));
|
||||
return true;
|
||||
}
|
||||
// Don't add the expander if it was already decoded. This could
|
||||
// happen if both the configuration and the platform configuration
|
||||
// contain the definition.
|
||||
for (int i = 0; i < gpio_exp_count; i++) {
|
||||
if (are_GPIOExp_equal(&(*pExp)[i], &entry)) {
|
||||
ESP_LOGW(TAG, "GPIO Expander entry already exists, skipping addition.");
|
||||
return true; // Skip adding as it already exists
|
||||
}
|
||||
}
|
||||
|
||||
gpio_exp_count++;
|
||||
|
||||
*pExp = heap_caps_realloc(*pExp, sizeof(sys_exp_config) * gpio_exp_count, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
|
||||
// Assert after realloc to ensure memory allocation was successful
|
||||
assert(*pExp != NULL);
|
||||
exp = (*pExp) + gpio_exp_count - 1; // Simplified pointer arithmetic
|
||||
memcpy(exp, &entry, sizeof(entry));
|
||||
ESP_LOGD(TAG, "GPIO Expander #%d model %s", gpio_exp_count, sys_exp_models_name(entry.model));
|
||||
|
||||
} else if (ostream != NULL && field->tag == sys_dev_config_gpio_exp_tag) {
|
||||
ESP_LOGV(TAG, "Encoding %d GPIO Expanders", gpio_exp_count);
|
||||
|
||||
for (int i = 0; i < gpio_exp_count; i++) {
|
||||
if (!pb_encode_tag_for_field(ostream, field)) {
|
||||
return false;
|
||||
}
|
||||
if (!pb_encode_submessage(ostream, &sys_exp_config_msg, &(*pExp)[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ESP_LOGV(TAG, "GPIO Expander encoding completed");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void set_gpio_level(sys_gpio_config* gpio, const char* name, gpio_mode_t mode) {
|
||||
ESP_LOGI(TAG, "set GPIO %u to %s, level %d", gpio->pin, name, gpio->level);
|
||||
if (gpio->pin < 0) {
|
||||
ESP_LOGW(TAG, "Invalid gpio %d for %s", gpio->pin, name);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
gpio_set_level(gpio->pin, gpio->level);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -96,7 +160,7 @@ static void sleep_timer(uint32_t now) {
|
||||
if (!first) first = now;
|
||||
|
||||
// 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;
|
||||
|
||||
// time to evaluate if we had spurious wake-up
|
||||
@@ -151,12 +215,13 @@ static void sleep_battery(float level, int cells) {
|
||||
*
|
||||
*/
|
||||
void services_sleep_init(void) {
|
||||
ESP_LOGD(TAG,"Initializing sleep services");
|
||||
if(!SYS_SERVICES_SLEEP(sleep_config)){
|
||||
ESP_LOGD(TAG,"No sleep service configured") ;
|
||||
ESP_LOGD(TAG, "Initializing sleep services");
|
||||
if (!sys_services_config_SLEEP(sleep_config)) {
|
||||
ESP_LOGD(TAG, "No sleep service configured");
|
||||
return;
|
||||
}
|
||||
// get the wake criteria
|
||||
for(int i=0;i<sleep_config->wake_count;i++){
|
||||
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 {
|
||||
@@ -165,7 +230,8 @@ void services_sleep_init(void) {
|
||||
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
|
||||
// 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);
|
||||
}
|
||||
@@ -177,7 +243,7 @@ void services_sleep_init(void) {
|
||||
battery_handler_svc = sleep_battery;
|
||||
ESP_LOGI(TAG, "Sleep on battery level of %.2f", sleep_context.battery_level);
|
||||
}
|
||||
for(int i = 0;i<sleep_config->rtc_count;i++){
|
||||
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 {
|
||||
@@ -185,20 +251,21 @@ void services_sleep_init(void) {
|
||||
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
|
||||
// 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(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);
|
||||
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
|
||||
|
||||
sleep_context.delay = sleep_config->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();
|
||||
@@ -207,17 +274,19 @@ void services_sleep_init(void) {
|
||||
|
||||
// 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();
|
||||
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;
|
||||
if(sleep_config->spurious>0){
|
||||
if (sleep_config->spurious > 0) {
|
||||
sleep_context.spurious = sleep_config->spurious;
|
||||
}
|
||||
sleep_context.spurious *= 60*1000;
|
||||
|
||||
sleep_context.spurious *= 60 * 1000;
|
||||
|
||||
ESP_LOGI(TAG, "spurious wake-up detection during %d sec", sleep_context.spurious / 1000);
|
||||
}
|
||||
}
|
||||
@@ -226,7 +295,7 @@ void services_sleep_init(void) {
|
||||
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));
|
||||
if (sleep_context.delay) ESP_LOGI(TAG, "inactivity timer of %d minute(s)", sleep_context.delay / (60 * 1000));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +304,8 @@ void services_sleep_init(void) {
|
||||
*/
|
||||
void services_sleep_activate(sleep_cause_e cause) {
|
||||
// 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
|
||||
esp_sleep_config_gpio_isolate();
|
||||
@@ -249,9 +319,11 @@ void services_sleep_activate(sleep_cause_e cause) {
|
||||
|
||||
// do we need to maintain a pull-up or down of that GPIO
|
||||
if ((1LL << i) & sleep_context.rtc_gpio) {
|
||||
if ((sleep_context.rtc_level >> i) & 0x01) rtc_gpio_pullup_en(i);
|
||||
else rtc_gpio_pulldown_en(i);
|
||||
// or is this not wake-up GPIO, just isolate it
|
||||
if ((sleep_context.rtc_level >> i) & 0x01)
|
||||
rtc_gpio_pullup_en(i);
|
||||
else
|
||||
rtc_gpio_pulldown_en(i);
|
||||
// or is this not wake-up GPIO, just isolate it
|
||||
} else if (!((1LL << i) & sleep_context.wake_gpio)) {
|
||||
rtc_gpio_isolate(i);
|
||||
}
|
||||
@@ -261,10 +333,11 @@ void services_sleep_activate(sleep_cause_e cause) {
|
||||
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);
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3) && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
|
||||
if (!sleep_context.wake_level) esp_sleep_enable_ext1_wakeup(sleep_context.wake_gpio, ESP_EXT1_WAKEUP_ANY_LOW);
|
||||
if (!sleep_context.wake_level)
|
||||
esp_sleep_enable_ext1_wakeup(sleep_context.wake_gpio, ESP_EXT1_WAKEUP_ANY_LOW);
|
||||
else
|
||||
#endif
|
||||
esp_sleep_enable_ext1_wakeup(sleep_context.wake_gpio, ESP_EXT1_WAKEUP_ANY_HIGH);
|
||||
esp_sleep_enable_ext1_wakeup(sleep_context.wake_gpio, ESP_EXT1_WAKEUP_ANY_HIGH);
|
||||
} else if (sleep_context.wake_gpio) {
|
||||
int gpio = __builtin_ctzll(sleep_context.wake_gpio);
|
||||
int level = (sleep_context.wake_level >> gpio) & 0x01;
|
||||
@@ -274,136 +347,186 @@ void services_sleep_activate(sleep_cause_e cause) {
|
||||
ESP_LOGW(TAG, "going to sleep cause %d, no wake-up option", 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
|
||||
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();
|
||||
// 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);
|
||||
else
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
static void register_method(void **store, size_t size, void *method) {
|
||||
for (int i = 0; i < size; i++, *store++) if (!*store) {
|
||||
*store = method;
|
||||
return;
|
||||
}
|
||||
static void register_method(void** store, size_t size, void* method) {
|
||||
for (int i = 0; i < size; i++, *store++)
|
||||
if (!*store) {
|
||||
*store = method;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
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)) {
|
||||
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_ports_init(void) {
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
ESP_LOGI(TAG, "Initializing ports");
|
||||
gpio_install_isr_service(0);
|
||||
ESP_LOGD(TAG, "Checking i2c port usage");
|
||||
if (platform->dev.dac.has_i2c && platform->dev.has_i2c && platform->dev.dac.i2c.port != sys_i2c_port_UNSPECIFIED &&
|
||||
platform->dev.dac.i2c.port == platform->dev.i2c.port) {
|
||||
ESP_LOGE(TAG, "Port %s is used for internal DAC use. Switching to ", sys_i2c_port_name(platform->dev.dac.i2c.port));
|
||||
platform->dev.i2c.port = platform->dev.i2c.port == sys_i2c_port_PORT0 ? sys_i2c_port_PORT1 : sys_i2c_port_PORT0;
|
||||
config_raise_changed(false);
|
||||
}
|
||||
|
||||
// shared I2C bus
|
||||
ESP_LOGD(TAG, "Configuring I2C");
|
||||
const i2c_config_t* i2c_config = config_i2c_get(&platform->dev.i2c);
|
||||
ESP_LOGD(TAG, "Stored I2C configuration [sda:%d scl:%d port:%s speed:%u]", i2c_config->sda_io_num, i2c_config->scl_io_num,
|
||||
sys_i2c_port_name(platform->dev.i2c.port), i2c_config->master.clk_speed);
|
||||
if (i2c_config->sda_io_num != -1 && i2c_config->scl_io_num != -1) {
|
||||
ESP_LOGI(TAG, "Configuring I2C sda:%d scl:%d port:%s speed:%u", i2c_config->sda_io_num, i2c_config->scl_io_num,
|
||||
sys_i2c_port_name(platform->dev.i2c.port), i2c_config->master.clk_speed);
|
||||
i2c_param_config(platform->dev.i2c.port - sys_i2c_port_PORT0, i2c_config);
|
||||
if ((err = i2c_driver_install(platform->dev.i2c.port - sys_i2c_port_PORT0, i2c_config->mode, 0, 0, 0)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error setting up i2c: %s", esp_err_to_name(err));
|
||||
} else {
|
||||
i2c_configured = true;
|
||||
}
|
||||
} else {
|
||||
if (platform->dev.has_display && platform->dev.display.has_common && platform->dev.display.which_dispType == sys_display_config_i2c_tag) {
|
||||
ESP_LOGE(TAG, "I2C configuration missing for display %s", sys_display_drivers_name(platform->dev.display.common.driver));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Shared I2C not configured");
|
||||
}
|
||||
}
|
||||
|
||||
const spi_bus_config_t* spi_config = config_spi_get((spi_host_device_t*)&spi_system_host);
|
||||
ESP_LOGD(TAG, "Stored SPI configuration[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) {
|
||||
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 ((err = spi_bus_initialize(spi_system_host, spi_config, SPI_DMA_CH_AUTO)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error setting up SPI bus: %s", esp_err_to_name(err));
|
||||
} else {
|
||||
spi_configured = true;
|
||||
}
|
||||
if (spi_system_dc_gpio != -1) {
|
||||
gpio_reset_pin(spi_system_dc_gpio);
|
||||
gpio_set_direction(spi_system_dc_gpio, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(spi_system_dc_gpio, 0);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "No DC GPIO set, SPI display will not work");
|
||||
}
|
||||
} else {
|
||||
spi_system_host = -1;
|
||||
if (platform->dev.has_display && platform->dev.display.has_common &&
|
||||
platform->dev.display.common.driver != sys_display_drivers_UNSPECIFIED &&
|
||||
platform->dev.display.which_dispType == sys_display_config_spi_tag) {
|
||||
ESP_LOGE(TAG, "SPI bus configuration missing for display %s", sys_display_drivers_name(platform->dev.display.common.driver));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "SPI bus not configured");
|
||||
}
|
||||
}
|
||||
}
|
||||
void services_gpio_init(void) {
|
||||
ESP_LOGI(TAG, "Initializing GPIOs");
|
||||
// set potential power GPIO on chip first in case expanders are power using these
|
||||
sys_gpio_config* gpio = NULL;
|
||||
if (SYS_GPIOS_NAME(power, gpio) && gpio->pin >= 0) {
|
||||
ESP_LOGD(TAG, "Handling power gpio");
|
||||
gpio->level = sys_gpio_lvl_HIGH;
|
||||
set_gpio_level(gpio, "power", GPIO_MODE_OUTPUT);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "No power GPIO defined");
|
||||
}
|
||||
|
||||
if (SYS_GPIOS_NAME(GND, gpio) && gpio->pin >= 0) {
|
||||
ESP_LOGD(TAG, "Handling GND gpio");
|
||||
gpio->level = sys_gpio_lvl_LOW;
|
||||
set_gpio_level(gpio, "GND", GPIO_MODE_OUTPUT);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "No GND gpio defined");
|
||||
}
|
||||
|
||||
// create GPIO expanders
|
||||
gpio_exp_config_t gpio_exp_config;
|
||||
if (platform->has_dev && gpio_exp_count > 0 && platform->dev.gpio_exp[0].model != sys_exp_models_UNSPECIFIED_EXP) {
|
||||
ESP_LOGI(TAG, "Initializing %d GPIO Expander(s)", gpio_exp_count);
|
||||
for (int count = 0; count < gpio_exp_count; count++) {
|
||||
sys_exp_config* exp = &platform->dev.gpio_exp[count];
|
||||
if (exp->model == sys_exp_models_UNSPECIFIED_EXP) {
|
||||
ESP_LOGD(TAG, "Skipping unknown model");
|
||||
continue;
|
||||
}
|
||||
gpio_exp_config.phy.ena_pin = -1;
|
||||
gpio_exp_config.base = exp->base;
|
||||
gpio_exp_config.count = exp->count;
|
||||
gpio_exp_config.phy.addr = exp->addr;
|
||||
gpio_exp_config.intr = exp->intr;
|
||||
if (exp->has_ena && exp->ena.pin >= 0) {
|
||||
gpio_exp_config.phy.ena_pin = exp->ena.pin;
|
||||
gpio_exp_config.phy.ena_lvl = exp->ena.level;
|
||||
}
|
||||
if (exp->which_ExpType == sys_exp_config_spi_tag) {
|
||||
if (!spi_configured) {
|
||||
ESP_LOGE(TAG, "SPI bus not configured for GPIO Expander index %d (%s)", count, sys_exp_models_name(exp->model));
|
||||
continue;
|
||||
}
|
||||
gpio_exp_config.phy.cs_pin = exp->ExpType.spi.cs;
|
||||
gpio_exp_config.phy.host =
|
||||
(!platform->dev.has_spi || (platform->dev.has_spi && platform->dev.spi.host == sys_dev_common_hosts_NONE) ? sys_dev_common_hosts_Host0 : platform->dev.spi.host) - sys_dev_common_hosts_Host0;
|
||||
gpio_exp_config.phy.speed = exp->ExpType.spi.speed > 0 ? exp->ExpType.spi.speed : 0;
|
||||
} else {
|
||||
if (!i2c_configured) {
|
||||
ESP_LOGE(TAG, "I2C bus not configured for GPIO Expander index %d (%s)", count, sys_exp_models_name(exp->model));
|
||||
continue;
|
||||
}
|
||||
gpio_exp_config.phy.port =
|
||||
((!platform->dev.has_i2c || (platform->dev.has_i2c && platform->dev.i2c.port == sys_i2c_port_UNSPECIFIED) )? sys_dev_common_ports_SYSTEM : platform->dev.i2c.port) - sys_dev_common_ports_SYSTEM ;
|
||||
}
|
||||
strncpy(gpio_exp_config.model, sys_exp_models_name(exp->model), sizeof(gpio_exp_config.model) - 1);
|
||||
gpio_exp_create(&gpio_exp_config);
|
||||
}
|
||||
} else if (gpio_exp_count > 0) {
|
||||
ESP_LOGW(TAG, "GPIO Expander count %d but none is valid", gpio_exp_count);
|
||||
}
|
||||
}
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
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;
|
||||
ESP_LOGE(TAG, "Port 0 is reserved for internal DAC use");
|
||||
}
|
||||
#endif
|
||||
ESP_LOGI(TAG, "Initializing services");
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
// set potential power GPIO on chip first in case expanders are power using these
|
||||
set_chip_power_gpio(&platform->gpios);
|
||||
|
||||
// shared I2C bus
|
||||
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);
|
||||
|
||||
if (i2c_config->sda_io_num != -1 && i2c_config->scl_io_num != -1) {
|
||||
i2c_param_config(i2c_system_port, i2c_config);
|
||||
i2c_driver_install(i2c_system_port, i2c_config->mode, 0, 0, 0 );
|
||||
} else {
|
||||
i2c_system_port = -1;
|
||||
ESP_LOGW(TAG, "no I2C configured");
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (spi_config->mosi_io_num != -1 && spi_config->sclk_io_num != -1) {
|
||||
spi_bus_initialize( spi_system_host, spi_config, SPI_DMA_CH_AUTO );
|
||||
if (spi_system_dc_gpio != -1) {
|
||||
gpio_reset_pin(spi_system_dc_gpio);
|
||||
gpio_set_direction( spi_system_dc_gpio, GPIO_MODE_OUTPUT );
|
||||
gpio_set_level( spi_system_dc_gpio, 0 );
|
||||
} else {
|
||||
ESP_LOGW(TAG, "No DC GPIO set, SPI display will not work");
|
||||
}
|
||||
} else {
|
||||
spi_system_host = -1;
|
||||
ESP_LOGW(TAG, "no SPI configured");
|
||||
}
|
||||
|
||||
// create GPIO expanders
|
||||
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 = {
|
||||
.duty_resolution = LEDC_TIMER_13_BIT,
|
||||
.freq_hz = 5000,
|
||||
// system-wide PWM timer configuration
|
||||
ledc_timer_config_t pwm_timer = {
|
||||
.duty_resolution = LEDC_TIMER_13_BIT,
|
||||
.freq_hz = 5000,
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
#else
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||
#endif
|
||||
.timer_num = pwm_system.timer,
|
||||
};
|
||||
.timer_num = pwm_system.timer,
|
||||
};
|
||||
|
||||
ledc_timer_config(&pwm_timer);
|
||||
|
||||
led_svc_init();
|
||||
battery_svc_init();
|
||||
monitor_svc_init();
|
||||
ledc_timer_config(&pwm_timer);
|
||||
led_svc_init();
|
||||
battery_svc_init();
|
||||
monitor_svc_init();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user