audio refactoring done + T-WATCH2020 support

This commit is contained in:
Philippe G
2020-08-02 21:36:36 -07:00
parent 78563b20f3
commit 340a1bd19e
16 changed files with 297 additions and 105 deletions

View File

@@ -31,6 +31,8 @@ CONFIG_SPDIF_BCK_IO=27
CONFIG_SPDIF_WS_IO=26 CONFIG_SPDIF_WS_IO=26
CONFIG_SPDIF_DO_IO=-1 CONFIG_SPDIF_DO_IO=-1
CONFIG_DAC_CONFIG="model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32" CONFIG_DAC_CONFIG="model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32"
CONFIG_MUTE_GPIO=-1
CONFIG_MUTE_GPIO_LEVEL=-1
CONFIG_IDF_TARGET_ESP32=y CONFIG_IDF_TARGET_ESP32=y
CONFIG_IDF_TARGET="esp32" CONFIG_IDF_TARGET="esp32"

View File

@@ -33,6 +33,8 @@ CONFIG_SDIF_NUM=0
CONFIG_SPDIF_BCK_IO=33 CONFIG_SPDIF_BCK_IO=33
CONFIG_SPDIF_WS_IO=25 CONFIG_SPDIF_WS_IO=25
CONFIG_SPDIF_DO_IO=-1 CONFIG_SPDIF_DO_IO=-1
CONFIG_MUTE_GPIO=-1
CONFIG_MUTE_GPIO_LEVEL=-1
CONFIG_IDF_TARGET_ESP32=y CONFIG_IDF_TARGET_ESP32=y
CONFIG_IDF_TARGET="esp32" CONFIG_IDF_TARGET="esp32"

View File

@@ -31,9 +31,10 @@ CONFIG_BAT_SCALE="20.24"
CONFIG_I2S_NUM=0 CONFIG_I2S_NUM=0
CONFIG_SDIF_NUM=0 CONFIG_SDIF_NUM=0
CONFIG_SPDIF_CONFIG="bck=33,ws=25,do=15" CONFIG_SPDIF_CONFIG="bck=33,ws=25,do=15"
CONFIG_DAC_CONFIG="model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14" CONFIG_DAC_CONFIG="model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14:0"
CONFIG_IDF_TARGET_ESP32=y CONFIG_IDF_TARGET_ESP32=y
CONFIG_IDF_TARGET="esp32" CONFIG_IDF_TARGET="esp32"
CONFIG_MUTE_GPIO_LEVEL=-1
# #
# SDK tool configuration # SDK tool configuration

View File

@@ -32,6 +32,7 @@ CONFIG_I2S_NUM=0
CONFIG_SDIF_NUM=0 CONFIG_SDIF_NUM=0
CONFIG_SPDIF_CONFIG="bck=33,ws=25,do=15" CONFIG_SPDIF_CONFIG="bck=33,ws=25,do=15"
CONFIG_DAC_CONFIG="model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14" CONFIG_DAC_CONFIG="model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14"
CONFIG_MUTE_GPIO_LEVEL=-1
CONFIG_IDF_TARGET_ESP32=y CONFIG_IDF_TARGET_ESP32=y
CONFIG_IDF_TARGET="esp32" CONFIG_IDF_TARGET="esp32"

View File

@@ -611,9 +611,21 @@ void config_delete_key(const char *key){
} }
config_unlock(); config_unlock();
} }
void * config_alloc_get(nvs_type_t nvs_type, const char *key) { void * config_alloc_get(nvs_type_t nvs_type, const char *key) {
return config_alloc_get_default(nvs_type, key, NULL, 0); return config_alloc_get_default(nvs_type, key, NULL, 0);
} }
void * config_alloc_get_str(const char *key, char *lead, char *fallback) {
if (lead && *lead) return strdup(lead);
char *value = config_alloc_get_default(NVS_TYPE_STR, key, NULL, 0);
if ((!value || !*value) && fallback) {
if (value) free(value);
value = strdup(fallback);
}
return value;
}
void * config_alloc_get_default(nvs_type_t nvs_type, const char *key, void * default_value, size_t blob_size) { void * config_alloc_get_default(nvs_type_t nvs_type, const char *key, void * default_value, size_t blob_size) {
void * value = NULL; void * value = NULL;

View File

@@ -34,6 +34,7 @@ void * config_alloc_get_default(nvs_type_t type, const char *key, void * default
void config_delete_key(const char *key); void config_delete_key(const char *key);
void config_set_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size); void config_set_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size);
void * config_alloc_get(nvs_type_t nvs_type, const char *key) ; void * config_alloc_get(nvs_type_t nvs_type, const char *key) ;
void * config_alloc_get_str(const char *key, char *lead, char *fallback);
bool wait_for_commit(); bool wait_for_commit();
char * config_alloc_get_json(bool bFormatted); char * config_alloc_get_json(bool bFormatted);
esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value); esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value);

View File

@@ -56,12 +56,7 @@ GDS_DetectFunc *drivers[] = { SH1106_Detect, SSD1306_Detect, SSD132x_Detect, SSD
*/ */
void display_init(char *welcome) { void display_init(char *welcome) {
bool init = false; bool init = false;
char *config = config_alloc_get(NVS_TYPE_STR, "display_config"); char *config = config_alloc_get_str("display_config", CONFIG_DISPLAY_CONFIG, "N/A");
if (!config) {
ESP_LOGI(TAG, "no display");
return;
}
int width = -1, height = -1, backlight_pin = -1; int width = -1, height = -1, backlight_pin = -1;
char *p, *drivername = strstr(config, "driver"); char *p, *drivername = strstr(config, "driver");

View File

@@ -75,7 +75,7 @@ const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host) {
.quadhd_io_num = -1 .quadhd_io_num = -1
}; };
nvs_item = config_alloc_get(NVS_TYPE_STR, "spi_config"); nvs_item = config_alloc_get_str("spi_config", CONFIG_SPI_CONFIG, NULL);
if (nvs_item) { if (nvs_item) {
if ((p = strcasestr(nvs_item, "data")) != NULL) spi.mosi_io_num = atoi(strchr(p, '=') + 1); if ((p = strcasestr(nvs_item, "data")) != NULL) spi.mosi_io_num = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(nvs_item, "clk")) != NULL) spi.sclk_io_num = atoi(strchr(p, '=') + 1); if ((p = strcasestr(nvs_item, "clk")) != NULL) spi.sclk_io_num = atoi(strchr(p, '=') + 1);

View File

@@ -231,7 +231,7 @@ void led_svc_init(void) {
#ifndef CONFIG_LED_LOCKED #ifndef CONFIG_LED_LOCKED
parse_set_GPIO(set_led_gpio); parse_set_GPIO(set_led_gpio);
#endif #endif
ESP_LOGI(TAG,"Configuring LEDs green:%d (active:%d %d%%), red:%d (active:%d %d%%)", green.gpio, green.active, green.pwm, red.gpio, red.active, red.pwm); ESP_LOGI(TAG,"Configuring LEDs green:%d (active:%d %d%%), red:%d (active:%d %d%%)", green.gpio, green.active, green.pwm, green.gpio, green.active, green.pwm );
char *nvs_item = config_alloc_get(NVS_TYPE_STR, "led_brightness"), *p; char *nvs_item = config_alloc_get(NVS_TYPE_STR, "led_brightness"), *p;
if (nvs_item) { if (nvs_item) {

View File

@@ -52,7 +52,7 @@ static bool init(char *config, int i2c_port_num);
static void deinit(void); static void deinit(void);
static void speaker(bool active); static void speaker(bool active);
static void headset(bool active); static void headset(bool active);
static void volume(unsigned left, unsigned right); static bool volume(unsigned left, unsigned right);
static void power(adac_power_e mode); static void power(adac_power_e mode);
const struct adac_s dac_ac101 = { "AC101", init, deinit, power, speaker, headset, volume }; const struct adac_s dac_ac101 = { "AC101", init, deinit, power, speaker, headset, volume };
@@ -164,8 +164,9 @@ static void deinit(void) {
/**************************************************************************************** /****************************************************************************************
* change volume * change volume
*/ */
static void volume(unsigned left, unsigned right) { static bool volume(unsigned left, unsigned right) {
// nothing at that point, volume is handled by backend // nothing at that point, volume is handled by backend
return false;
} }
/**************************************************************************************** /****************************************************************************************

View File

@@ -21,7 +21,7 @@ struct adac_s {
void (*power)(adac_power_e mode); void (*power)(adac_power_e mode);
void (*speaker)(bool active); void (*speaker)(bool active);
void (*headset)(bool active); void (*headset)(bool active);
void (*volume)(unsigned left, unsigned right); bool (*volume)(unsigned left, unsigned right);
}; };
extern const struct adac_s dac_tas57xx; extern const struct adac_s dac_tas57xx;

View File

@@ -12,22 +12,163 @@
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/task.h> #include <freertos/task.h>
#include <driver/i2s.h> #include <driver/i2s.h>
#include "driver/i2c.h"
#include "esp_log.h" #include "esp_log.h"
#include "cJSON.h"
#include "config.h" #include "config.h"
#include "adac.h" #include "adac.h"
static const char TAG[] = "DAC external"; static const char TAG[] = "DAC external";
static void deinit(void) { }
static void speaker(bool active) { }
static void headset(bool active) { }
static bool volume(unsigned left, unsigned right) { return false; }
static void power(adac_power_e mode);
static bool init(char *config, int i2c_port_num); static bool init(char *config, int i2c_port_num);
static void deinit(void) { };
static void speaker(bool active) { }; static bool i2c_json_execute(char *set);
static void headset(bool active) { } ; static esp_err_t i2c_write_reg(uint8_t reg, uint8_t val);
static void volume(unsigned left, unsigned right) { }; static uint8_t i2c_read_reg(uint8_t reg);
static void power(adac_power_e mode) { };
const struct adac_s dac_external = { "i2s", init, deinit, power, speaker, headset, volume }; const struct adac_s dac_external = { "i2s", init, deinit, power, speaker, headset, volume };
static int i2c_port, i2c_addr;
static cJSON *i2c_json;
/****************************************************************************************
* init
*/
static bool init(char *config, int i2c_port_num) { static bool init(char *config, int i2c_port_num) {
char *p;
i2c_port = i2c_port_num;
// configure i2c
i2c_config_t i2c_config = {
.mode = I2C_MODE_MASTER,
.sda_io_num = -1,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_io_num = -1,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 250000,
};
if ((p = strcasestr(config, "i2c")) != NULL) i2c_addr = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(config, "sda")) != NULL) i2c_config.sda_io_num = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(config, "scl")) != NULL) i2c_config.scl_io_num = atoi(strchr(p, '=') + 1);
p = config_alloc_get_str("dac_controlset", CONFIG_DAC_CONTROLSET, NULL);
i2c_json = cJSON_Parse(p);
if (!i2c_addr || !i2c_json || i2c_config.sda_io_num == -1 || i2c_config.scl_io_num == -1) {
if (p) free(p);
ESP_LOGW(TAG, "No i2c controlset found");
return true;
}
ESP_LOGI(TAG, "DAC uses I2C @%d with sda:%d, scl:%d", i2c_addr, i2c_config.sda_io_num, i2c_config.scl_io_num);
// we have an I2C configured
i2c_param_config(i2c_port, &i2c_config);
i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false);
if (!i2c_json_execute("init")) {
ESP_LOGE(TAG, "could not intialize DAC");
return false;
}
return true; return true;
} }
/****************************************************************************************
* power
*/
static void power(adac_power_e mode) {
if (mode == ADAC_STANDBY || mode == ADAC_OFF) i2c_json_execute("poweroff");
else i2c_json_execute("poweron");
}
/****************************************************************************************
*
*/
bool i2c_json_execute(char *set) {
cJSON *json_set = cJSON_GetObjectItemCaseSensitive(i2c_json, set);
cJSON *item;
if (!json_set) return true;
cJSON_ArrayForEach(item, json_set)
{
cJSON *reg = cJSON_GetObjectItemCaseSensitive(item, "reg");
cJSON *val = cJSON_GetObjectItemCaseSensitive(item, "val");
cJSON *mode = cJSON_GetObjectItemCaseSensitive(item, "mode");
if (!reg || !val) continue;
if (!mode) {
i2c_write_reg(reg->valueint, val->valueint);
} else if (!strcasecmp(mode->valuestring, "or")) {
uint8_t data = i2c_read_reg(reg->valueint);
data |= (uint8_t) val->valueint;
i2c_write_reg(reg->valueint, data);
} else if (!strcasecmp(mode->valuestring, "and")) {
uint8_t data = i2c_read_reg(reg->valueint);
data &= (uint8_t) val->valueint;
i2c_write_reg(reg->valueint, data);
}
}
return true;
}
/****************************************************************************************
*
*/
static esp_err_t i2c_write_reg(uint8_t reg, uint8_t val) {
esp_err_t ret;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, i2c_addr | I2C_MASTER_WRITE, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, val, I2C_MASTER_NACK);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGW(TAG, "I2C write failed");
}
return ret;
}
/****************************************************************************************
*
*/
static uint8_t i2c_read_reg(uint8_t reg) {
esp_err_t ret;
uint8_t data = 0;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, i2c_addr | I2C_MASTER_WRITE, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, i2c_addr | I2C_MASTER_READ, I2C_MASTER_NACK);
i2c_master_read_byte(cmd, &data, I2C_MASTER_NACK);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGW(TAG, "I2C read failed");
}
return data;
}

View File

@@ -93,7 +93,10 @@ static size_t dma_buf_frames;
static pthread_t thread; static pthread_t thread;
static TaskHandle_t stats_task; static TaskHandle_t stats_task;
static bool stats; static bool stats;
static int amp_gpio = -1; static struct {
int gpio, active;
} amp_control = { -1, 1 },
mute_control = { CONFIG_MUTE_GPIO, CONFIG_MUTE_GPIO_LEVEL };
DECLARE_ALL_MIN_MAX; DECLARE_ALL_MIN_MAX;
@@ -129,14 +132,17 @@ static void jack_handler(bool inserted) {
* amp GPIO * amp GPIO
*/ */
static void set_amp_gpio(int gpio, char *value) { static void set_amp_gpio(int gpio, char *value) {
char *p;
if (!strcasecmp(value, "amp")) { if (!strcasecmp(value, "amp")) {
amp_gpio = gpio; amp_control.gpio = gpio;
if ((p = strchr(value, ':')) != NULL) amp_control.active = atoi(p + 1);
gpio_pad_select_gpio(amp_gpio); gpio_pad_select_gpio(amp_control.gpio);
gpio_set_direction(amp_gpio, GPIO_MODE_OUTPUT); gpio_set_direction(amp_control.gpio, GPIO_MODE_OUTPUT);
gpio_set_level(amp_gpio, 0); gpio_set_level(amp_control.gpio, !amp_control.active);
LOG_INFO("setting amplifier GPIO %d", amp_gpio); LOG_INFO("setting amplifier GPIO %d (active:%d)", amp_control.gpio, amp_control.active);
} }
} }
@@ -145,7 +151,7 @@ static void set_amp_gpio(int gpio, char *value) {
*/ */
void output_init_i2s(log_level level, char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle) { void output_init_i2s(log_level level, char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle) {
loglevel = level; loglevel = level;
char *p, *dac_config, *spdif_config; char *p;
esp_err_t res; esp_err_t res;
p = config_alloc_get_default(NVS_TYPE_STR, "jack_mutes_amp", "n", 0); p = config_alloc_get_default(NVS_TYPE_STR, "jack_mutes_amp", "n", 0);
@@ -186,12 +192,9 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
i2s_pin_config_t i2s_pin_config = { .bck_io_num = -1, .ws_io_num = -1, .data_out_num = -1, .data_in_num = -1 }; i2s_pin_config_t i2s_pin_config = { .bck_io_num = -1, .ws_io_num = -1, .data_out_num = -1, .data_in_num = -1 };
// get SPDIF configuration from NVS or compile // get SPDIF configuration from NVS or compile
#ifdef CONFIG_SPDIF_CONFIG char *spdif_config = config_alloc_get_str("spdif_config", CONFIG_SPDIF_CONFIG, "bck=" STR(CONFIG_SPDIF_BCK_IO)
spdif_config = strdup(CONFIG_SPDIF_CONFIG); ",ws=" STR(CONFIG_SPDIF_WS_IO) ",do=" STR(CONFIG_SPDIF_DO_IO));
#else
spdif_config = config_alloc_get(NVS_TYPE_STR, "spdif_config");
if (!spdif_config) spdif_config = strdup("bck=" STR(CONFIG_SPDIF_BCK_IO) ",ws=" STR(CONFIG_SPDIF_WS_IO) ",do=" STR(CONFIG_SPDIF_DO_IO));
#endif
if ((p = strcasestr(spdif_config, "do")) != NULL) i2s_pin_config.data_out_num = atoi(strchr(p, '=') + 1); if ((p = strcasestr(spdif_config, "do")) != NULL) i2s_pin_config.data_out_num = atoi(strchr(p, '=') + 1);
// common I2S initialization // common I2S initialization
@@ -237,12 +240,10 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
gpio_set_level(i2s_pin_config.data_out_num, 0); gpio_set_level(i2s_pin_config.data_out_num, 0);
} }
#ifdef CONFIG_DAC_CONFIG char *dac_config = config_alloc_get_str("dac_config", CONFIG_DAC_CONFIG, "model=i2s,bck=" STR(CONFIG_I2S_BCK_IO)
dac_config = strdup(CONFIG_DAC_CONFIG); ",ws=" STR(CONFIG_I2S_WS_IO) ",do=" STR(CONFIG_I2S_DO_IO)
#else ",sda=" STR(CONFIG_I2C_SDA) ",scl=" STR(CONFIG_I2C_SCL)
dac_config = config_alloc_get(NVS_TYPE_STR, "dac_config"); ",mute" STR(CONFIG_MUTE_GPIO));
if (!dac_config) dac_config = strdup("model=i2s,bck=" STR(CONFIG_I2S_BCK_IO) ",ws=" STR(CONFIG_I2S_WS_IO) ",do=" STR(CONFIG_I2S_DO_IO) ",sda=" STR(CONFIG_I2C_SDA) ",scl=" STR(CONFIG_I2C_SCL));
#endif
char model[32] = "i2s"; char model[32] = "i2s";
if ((p = strcasestr(dac_config, "model")) != NULL) sscanf(p, "%*[^=]=%31[^,]", model); if ((p = strcasestr(dac_config, "model")) != NULL) sscanf(p, "%*[^=]=%31[^,]", model);
@@ -252,6 +253,13 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
if ((p = strcasestr(dac_config, "bck")) != NULL) i2s_pin_config.bck_io_num = atoi(strchr(p, '=') + 1); if ((p = strcasestr(dac_config, "bck")) != NULL) i2s_pin_config.bck_io_num = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(dac_config, "ws")) != NULL) i2s_pin_config.ws_io_num = atoi(strchr(p, '=') + 1); if ((p = strcasestr(dac_config, "ws")) != NULL) i2s_pin_config.ws_io_num = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(dac_config, "do")) != NULL) i2s_pin_config.data_out_num = atoi(strchr(p, '=') + 1); if ((p = strcasestr(dac_config, "do")) != NULL) i2s_pin_config.data_out_num = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(dac_config, "mute")) != NULL) {
char mute[8];
sscanf(p, "%*[^=]=%7[^,]", mute);
mute_control.gpio = atoi(mute);
if ((p = strchr(mute, ':')) != NULL) mute_control.active = atoi(p + 1);
}
free(dac_config); free(dac_config);
i2s_config.sample_rate = output.current_sample_rate; i2s_config.sample_rate = output.current_sample_rate;
@@ -264,8 +272,14 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
res |= i2s_driver_install(CONFIG_I2S_NUM, &i2s_config, 0, NULL); res |= i2s_driver_install(CONFIG_I2S_NUM, &i2s_config, 0, NULL);
res |= i2s_set_pin(CONFIG_I2S_NUM, &i2s_pin_config); res |= i2s_set_pin(CONFIG_I2S_NUM, &i2s_pin_config);
LOG_INFO("%s DAC using I2S bck:%d, ws:%d, do:%d", model, i2s_pin_config.bck_io_num, if (res == ESP_OK && mute_control.gpio >= 0) {
i2s_pin_config.ws_io_num, i2s_pin_config.data_out_num); gpio_pad_select_gpio(mute_control.gpio);
gpio_set_direction(mute_control.gpio, GPIO_MODE_OUTPUT);
gpio_set_level(mute_control.gpio, mute_control.active);
}
LOG_INFO("%s DAC using I2S bck:%d, ws:%d, do:%d, mute:%d:%d (res:%d)", model, i2s_pin_config.bck_io_num, i2s_pin_config.ws_io_num,
i2s_pin_config.data_out_num, mute_control.gpio, mute_control.active, res);
} }
free(spdif_config); free(spdif_config);
@@ -340,8 +354,8 @@ void output_close_i2s(void) {
* change volume * change volume
*/ */
bool output_volume_i2s(unsigned left, unsigned right) { bool output_volume_i2s(unsigned left, unsigned right) {
adac->volume(left, right); if (mute_control.gpio >= 0) gpio_set_level(mute_control.gpio, (left | right) ? !mute_control.active : mute_control.active);
return false; return adac->volume(left, right);
} }
/**************************************************************************************** /****************************************************************************************
@@ -422,8 +436,8 @@ static void *output_thread_i2s(void *arg) {
LOG_INFO("Output state is %d", output.state); LOG_INFO("Output state is %d", output.state);
if (output.state == OUTPUT_OFF) { if (output.state == OUTPUT_OFF) {
led_blink(LED_GREEN, 100, 2500); led_blink(LED_GREEN, 100, 2500);
if (amp_gpio != -1) gpio_set_level(amp_gpio, 0); if (amp_control.gpio != -1) gpio_set_level(amp_control.gpio, !amp_control.active);
LOG_INFO("switching off amp GPIO %d", amp_gpio); LOG_INFO("switching off amp GPIO %d", amp_control.gpio);
} else if (output.state == OUTPUT_STOPPED) { } else if (output.state == OUTPUT_STOPPED) {
adac->speaker(false); adac->speaker(false);
led_blink(LED_GREEN, 200, 1000); led_blink(LED_GREEN, 200, 1000);
@@ -486,7 +500,7 @@ static void *output_thread_i2s(void *arg) {
i2s_zero_dma_buffer(CONFIG_I2S_NUM); i2s_zero_dma_buffer(CONFIG_I2S_NUM);
i2s_start(CONFIG_I2S_NUM); i2s_start(CONFIG_I2S_NUM);
adac->power(ADAC_ON); adac->power(ADAC_ON);
if (amp_gpio != -1) gpio_set_level(amp_gpio, 1); if (amp_control.gpio != -1) gpio_set_level(amp_control.gpio, amp_control.active);
} }
// this does not work well as set_sample_rates resets the fifos (and it's too early) // this does not work well as set_sample_rates resets the fifos (and it's too early)

View File

@@ -27,7 +27,7 @@ static bool init(char *config, int i2c_port_num);
static void deinit(void); static void deinit(void);
static void speaker(bool active); static void speaker(bool active);
static void headset(bool active); static void headset(bool active);
static void volume(unsigned left, unsigned right); static bool volume(unsigned left, unsigned right);
static void power(adac_power_e mode); static void power(adac_power_e mode);
const struct adac_s dac_tas57xx = { "TAS57xx", init, deinit, power, speaker, headset, volume }; const struct adac_s dac_tas57xx = { "TAS57xx", init, deinit, power, speaker, headset, volume };
@@ -61,7 +61,6 @@ static const struct tas57xx_cmd_s tas57xx_cmd[] = {
static uint8_t tas57_addr; static uint8_t tas57_addr;
static int i2c_port; static int i2c_port;
static int mute_gpio = -1;
static void dac_cmd(dac_cmd_e cmd, ...); static void dac_cmd(dac_cmd_e cmd, ...);
static int tas57_detect(void); static int tas57_detect(void);
@@ -85,7 +84,6 @@ static bool init(char *config, int i2c_port_num) {
if ((p = strcasestr(config, "sda")) != NULL) i2c_config.sda_io_num = atoi(strchr(p, '=') + 1); if ((p = strcasestr(config, "sda")) != NULL) i2c_config.sda_io_num = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(config, "scl")) != NULL) i2c_config.scl_io_num = atoi(strchr(p, '=') + 1); if ((p = strcasestr(config, "scl")) != NULL) i2c_config.scl_io_num = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(config, "mute")) != NULL) mute_gpio = atoi(strchr(p, '=') + 1);
i2c_param_config(i2c_port, &i2c_config); i2c_param_config(i2c_port, &i2c_config);
i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false); i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false);
@@ -113,20 +111,14 @@ static bool init(char *config, int i2c_port_num) {
esp_err_t res = i2c_master_cmd_begin(i2c_port, i2c_cmd, 500 / portTICK_RATE_MS); esp_err_t res = i2c_master_cmd_begin(i2c_port, i2c_cmd, 500 / portTICK_RATE_MS);
i2c_cmd_link_delete(i2c_cmd); i2c_cmd_link_delete(i2c_cmd);
ESP_LOGI(TAG, "TAS57xx uses I2C sda:%d, scl:%d and mute: %d", i2c_config.sda_io_num, i2c_config.scl_io_num, mute_gpio); ESP_LOGI(TAG, "TAS57xx uses I2C sda:%d, scl:%d", i2c_config.sda_io_num, i2c_config.scl_io_num);
if (res == ESP_OK) { if (res != ESP_OK) {
if (mute_gpio >= 0) {
// init volume & mute
gpio_pad_select_gpio(mute_gpio);
gpio_set_direction(mute_gpio, GPIO_MODE_OUTPUT);
gpio_set_level(mute_gpio, 0);
}
return true;
} else {
ESP_LOGE(TAG, "could not intialize TAS57xx %d", res); ESP_LOGE(TAG, "could not intialize TAS57xx %d", res);
return false; return false;
} }
return true;
} }
/**************************************************************************************** /****************************************************************************************
@@ -139,10 +131,7 @@ static void deinit(void) {
/**************************************************************************************** /****************************************************************************************
* change volume * change volume
*/ */
static void volume(unsigned left, unsigned right) { static bool volume(unsigned left, unsigned right) { return false; }
ESP_LOGI(TAG, "TAS57xx volume (L:%u R:%u)", left, right);
if (mute_gpio >= 0) gpio_set_level(mute_gpio, left || right);
}
/**************************************************************************************** /****************************************************************************************
* power * power
@@ -175,8 +164,7 @@ static void speaker(bool active) {
/**************************************************************************************** /****************************************************************************************
* headset * headset
*/ */
static void headset(bool active) { static void headset(bool active) { }
}
/**************************************************************************************** /****************************************************************************************
* DAC specific commands * DAC specific commands

View File

@@ -21,6 +21,7 @@ menu "Squeezelite-ESP32"
help help
Set logging level info|debug|sdebug Set logging level info|debug|sdebug
endmenu endmenu
config JACK_LOCKED config JACK_LOCKED
bool bool
config BAT_LOCKED config BAT_LOCKED
@@ -33,16 +34,38 @@ menu "Squeezelite-ESP32"
bool bool
config SPKFAULT_LOCKED config SPKFAULT_LOCKED
bool bool
config MUTE_GPIO_LEVEL
int
default 0
# AGGREGATES - begin
# these parameters are "aggregates" that take precedence. The must have a default value
config DAC_CONFIG config DAC_CONFIG
string string
default "model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14" if SQUEEZEAMP default "model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14:0" if SQUEEZEAMP
default "model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32" if A1S default "model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32" if A1S
default "model=I2S,bck=26,ws=25,do=33,i2c=106,sda=21,scl=22" if TWATCH2020
default ""
config SPDIF_CONFIG config SPDIF_CONFIG
string string
default "bck=33,ws=25,do=15" if SQUEEZEAMP default "bck=33,ws=25,do=15" if SQUEEZEAMP
menu "Audio Output" default ""
config SPI_CONFIG
string
default "dc=27,data=19,clk=18" if TWATCH2020
default ""
config DISPLAY_CONFIG
string
default "SPI,driver=ST7789,width=240,height=240,cs=5,back=12,speed=16000000,HFlip,VFlip" if TWATCH2020
default ""
config DAC_CONTROLSET
string
default "{ \"init\": [ {\"reg\":41, \"val\":128}, {\"reg\":18, \"val\":255} ], \"poweron\": [ {\"reg\":18, \"val\":64, \"mode\":\"or\"} ], \"poweroff\": [ {\"reg\":18, \"val\":191, \"mode\":\"and\"} ] }" if TWATCH2020
default ""
# AGGREGATES - end
choice OUTPUT_TYPE choice OUTPUT_TYPE
prompt "Output Type" prompt "Main system"
default BASIC_I2C_BT default BASIC_I2C_BT
help help
Type of hardware platform Type of hardware platform
@@ -56,10 +79,14 @@ menu "Squeezelite-ESP32"
config A1S config A1S
bool "ESP32-A1S module" bool "ESP32-A1S module"
select I2C_LOCKED select I2C_LOCKED
config TWATCH2020
bool "T-WATCH2020 by LilyGo"
select I2C_LOCKED
config BASIC_I2C_BT config BASIC_I2C_BT
bool "Generic I2S & Bluetooth" bool "Generic I2S & Bluetooth"
endchoice endchoice
menu "Audio settings"
menu "DAC settings" menu "DAC settings"
visible if BASIC_I2C_BT visible if BASIC_I2C_BT
menu "I2S settings" menu "I2S settings"
@@ -106,6 +133,10 @@ menu "Squeezelite-ESP32"
default -1 default -1
help help
GPIO used to mute DAC (not used mostly, leave it to -1). GPIO used to mute DAC (not used mostly, leave it to -1).
config MUTE_GPIO_LEVEL
int "Mute GPIO active level"
depends on MUTE_GPIO != -1
default 1
endmenu endmenu
menu "SPDIF settings" menu "SPDIF settings"
@@ -199,16 +230,17 @@ menu "Squeezelite-ESP32"
endmenu endmenu
menu "Display Screen" menu "Display Screen"
depends on !TWATCH2020
config DISPLAY_CONFIG config DISPLAY_CONFIG
string "Screen configuraton" string "Screen configuraton"
default ""
help help
Set parameters for display screen, leave empty for no screen Set parameters for display screen, leave empty for no screen
I2C,width=<pixels>,height=<pixels>[address=<i2c_address>][,HFlip][,VFlip] I2C,driver=<model>,width=<pixels>,height=<pixels>[address=<i2c_address>][,HFlip][,VFlip][,rotate]
SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,HFlip][,VFlip] SPI,driver=<model>,width=<pixels>,height=<pixels>,cs=<gpio>[,HFlip][,VFlip][,rotate]
endmenu endmenu
menu "Various I/O" menu "Various I/O"
visible if !TWATCH2020
config I2C_CONFIG config I2C_CONFIG
string "I2C system configuration" string "I2C system configuration"
default "" default ""
@@ -217,7 +249,6 @@ menu "Squeezelite-ESP32"
sda=<gpio>,scl=<gpio>[,speed=<num>][,port=<0|1>] sda=<gpio>,scl=<gpio>[,speed=<num>][,port=<0|1>]
config SPI_CONFIG config SPI_CONFIG
string "SPI system configuration" string "SPI system configuration"
default ""
help help
Set parameters of shared SPI interface Set parameters of shared SPI interface
data=<gpio>,clk=<gpio>[,d/c=<num>][,host=<0|1|2>] data=<gpio>,clk=<gpio>[,d/c=<num>][,host=<0|1|2>]
@@ -226,7 +257,7 @@ menu "Squeezelite-ESP32"
default "" default ""
help help
Set parameters of shared GPIO with special values. Set parameters of shared GPIO with special values.
<gpio_1>=Vcc|GND|amp|jack[:0|1][,<gpio_n>=Vcc|GND|amp|jack[:0|1]] <gpio_1>=Vcc|GND|amp[:0|1]|jack[:0|1][,<gpio_n>=Vcc|GND|amp[:0|1]|jack[:0|1]]
'amp' => GPIO that is set when playback starts 'amp' => GPIO that is set when playback starts
'jack' => GPIO used for audio jack detection 'jack' => GPIO used for audio jack detection
'green', 'red' => GPIO for status LED 'green', 'red' => GPIO for status LED
@@ -236,39 +267,39 @@ menu "Squeezelite-ESP32"
default "" default ""
help help
Set GPIO for rotary encoder (quadrature phase). See README on SqueezeESP32 project's GitHub for more details Set GPIO for rotary encoder (quadrature phase). See README on SqueezeESP32 project's GitHub for more details
A=<gpio>,B=<gpio>[,SW=gpio>[,volume][,longpress]] A=<gpio>,B=<gpio>[,SW=gpio>[[,knobonly[=<ms>]|[,volume][,longpress]]
endmenu endmenu
menu "LED configuration" menu "LED configuration"
visible if !SQUEEZEAMP visible if !SQUEEZEAMP && !TWATCH2020
config LED_GREEN_GPIO config LED_GREEN_GPIO
int "Green led GPIO" int "Green led GPIO"
default -1 if !SQUEEZEAMP
default 12 if SQUEEZEAMP default 12 if SQUEEZEAMP
default -1
help help
Set to -1 for no LED Set to -1 for no LED
config LED_GREEN_GPIO_LEVEL config LED_GREEN_GPIO_LEVEL
int "Green led ON level" int "Green led ON level"
depends on LED_GREEN_GPIO != -1 depends on LED_GREEN_GPIO != -1
default 0 if SQUEEZEAMP default 0 if SQUEEZEAMP
default 1 if !SQUEEZEAMP default 1
config LED_RED_GPIO config LED_RED_GPIO
int "Red led GPIO" int "Red led GPIO"
default -1 if !SQUEEZEAMP
default 13 if SQUEEZEAMP default 13 if SQUEEZEAMP
default -1
help help
Set to -1 for no LED Set to -1 for no LED
config LED_RED_GPIO_LEVEL config LED_RED_GPIO_LEVEL
int "Red led ON level" int "Red led ON level"
depends on LED_RED_GPIO != -1 depends on LED_RED_GPIO != -1
default 0 if SQUEEZEAMP default 0 if SQUEEZEAMP
default 1 if !SQUEEZEAMP default 1
endmenu endmenu
menu "Audio JACK" menu "Audio JACK"
visible if !SQUEEZEAMP visible if !SQUEEZEAMP && !TWATCH2020
config JACK_GPIO config JACK_GPIO
int "Jack insertion GPIO" int "Jack insertion GPIO"
default -1 if !SQUEEZEAMP
default 34 if SQUEEZEAMP default 34 if SQUEEZEAMP
default -1
help help
GPIO to detect speaker jack insertion. Set to -1 for no detection. GPIO to detect speaker jack insertion. Set to -1 for no detection.
config JACK_GPIO_LEVEL config JACK_GPIO_LEVEL
@@ -277,11 +308,11 @@ menu "Squeezelite-ESP32"
default 0 default 0
endmenu endmenu
menu "Speaker Fault" menu "Speaker Fault"
visible if !SQUEEZEAMP visible if !SQUEEZEAMP && !TWATCH2020
config SPKFAULT_GPIO config SPKFAULT_GPIO
int "Speaker fault GPIO" int "Speaker fault GPIO"
default -1 if !SQUEEZEAMP
default 2 if SQUEEZEAMP default 2 if SQUEEZEAMP
default -1
help help
GPIO to detect speaker fault condition. Set to -1 for no detection. GPIO to detect speaker fault condition. Set to -1 for no detection.
config SPKFAULT_GPIO_LEVEL config SPKFAULT_GPIO_LEVEL
@@ -290,18 +321,18 @@ menu "Squeezelite-ESP32"
default 0 default 0
endmenu endmenu
menu "Battery measure" menu "Battery measure"
visible if !SQUEEZEAMP visible if !SQUEEZEAMP && !TWATCH2020
config BAT_CHANNEL config BAT_CHANNEL
int "Set channel (0..7)" int "Set channel (0..7)"
default -1 if !SQUEEZEAMP
default 7 if SQUEEZEAMP default 7 if SQUEEZEAMP
default -1
help help
Read a value every 10s on ADC1 on set Channel Read a value every 10s on ADC1 on set Channel
config BAT_SCALE config BAT_SCALE
string "Set scaling factor" string "Set scaling factor"
depends on BAT_CHANNEL != -1 depends on BAT_CHANNEL != -1
default "" if !SQUEEZEAMP
default "20.24" if SQUEEZEAMP default "20.24" if SQUEEZEAMP
default ""
help help
Set the scaling factor for this 12 bits ADC Set the scaling factor for this 12 bits ADC
endmenu endmenu

View File

@@ -330,6 +330,9 @@ void register_default_nvs(){
ESP_LOGD(TAG,"Registering default value for key %s", "dac_config"); ESP_LOGD(TAG,"Registering default value for key %s", "dac_config");
config_set_default(NVS_TYPE_STR, "dac_config", "", 0); config_set_default(NVS_TYPE_STR, "dac_config", "", 0);
ESP_LOGD(TAG,"Registering default value for key %s", "dac_controlset");
config_set_default(NVS_TYPE_STR, "dac_controlset", "", 0);
ESP_LOGD(TAG,"Registering default value for key %s", "bat_config"); ESP_LOGD(TAG,"Registering default value for key %s", "bat_config");
config_set_default(NVS_TYPE_STR, "bat_config", "", 0); config_set_default(NVS_TYPE_STR, "bat_config", "", 0);