mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-06 19:47:02 +03:00
add GPIO to drive external amplifier
This commit is contained in:
@@ -77,6 +77,7 @@ sure that using rate_delay would fix that
|
|||||||
RESET_MIN_MAX(buffering);
|
RESET_MIN_MAX(buffering);
|
||||||
|
|
||||||
#define STATS_PERIOD_MS 5000
|
#define STATS_PERIOD_MS 5000
|
||||||
|
#define STAT_STACK_SIZE (3*1024)
|
||||||
|
|
||||||
extern struct outputstate output;
|
extern struct outputstate output;
|
||||||
extern struct buffer *streambuf;
|
extern struct buffer *streambuf;
|
||||||
@@ -92,18 +93,21 @@ static bool jack_mutes_amp;
|
|||||||
static bool running, isI2SStarted;
|
static bool running, isI2SStarted;
|
||||||
static i2s_config_t i2s_config;
|
static i2s_config_t i2s_config;
|
||||||
static int bytes_per_frame;
|
static int bytes_per_frame;
|
||||||
static thread_type thread, stats_thread;
|
|
||||||
static u8_t *obuf;
|
static u8_t *obuf;
|
||||||
static frames_t oframes;
|
static frames_t oframes;
|
||||||
static bool spdif;
|
static bool spdif;
|
||||||
static size_t dma_buf_frames;
|
static size_t dma_buf_frames;
|
||||||
|
static pthread_t thread;
|
||||||
|
static TaskHandle_t stats_task;
|
||||||
|
static bool stats;
|
||||||
|
static int amp_gpio = -1;
|
||||||
|
|
||||||
DECLARE_ALL_MIN_MAX;
|
DECLARE_ALL_MIN_MAX;
|
||||||
|
|
||||||
static int _i2s_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
|
static int _i2s_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
|
||||||
s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr);
|
s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr);
|
||||||
static void *output_thread_i2s();
|
static void *output_thread_i2s(void *arg);
|
||||||
static void *output_thread_i2s_stats();
|
static void *output_thread_i2s_stats(void *arg);
|
||||||
static void spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, size_t *count);
|
static void spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, size_t *count);
|
||||||
static void (*jack_handler_chain)(bool inserted);
|
static void (*jack_handler_chain)(bool inserted);
|
||||||
|
|
||||||
@@ -254,6 +258,16 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
|
|||||||
if (jack_mutes_amp && jack_inserted_svc()) adac->speaker(false);
|
if (jack_mutes_amp && jack_inserted_svc()) adac->speaker(false);
|
||||||
else adac->speaker(true);
|
else adac->speaker(true);
|
||||||
|
|
||||||
|
p = config_alloc_get_default(NVS_TYPE_STR, "amp_GPIO", NULL, 0);
|
||||||
|
if (p) {
|
||||||
|
amp_gpio = atoi(p);
|
||||||
|
gpio_pad_select_gpio(amp_gpio);
|
||||||
|
gpio_set_direction(amp_gpio, GPIO_MODE_OUTPUT);
|
||||||
|
gpio_set_level(amp_gpio, 0);
|
||||||
|
LOG_INFO("setting amplifier GPIO %d", amp_gpio);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
esp_pthread_cfg_t cfg = esp_pthread_get_default_config();
|
esp_pthread_cfg_t cfg = esp_pthread_get_default_config();
|
||||||
|
|
||||||
cfg.thread_name= "output_i2s";
|
cfg.thread_name= "output_i2s";
|
||||||
@@ -263,11 +277,17 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
|
|||||||
esp_pthread_set_cfg(&cfg);
|
esp_pthread_set_cfg(&cfg);
|
||||||
pthread_create(&thread, NULL, output_thread_i2s, NULL);
|
pthread_create(&thread, NULL, output_thread_i2s, NULL);
|
||||||
|
|
||||||
cfg.thread_name= "output_i2s_sts";
|
// do we want stats
|
||||||
cfg.prio = CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT - 1;
|
p = config_alloc_get_default(NVS_TYPE_STR, "stats", "n", 0);
|
||||||
cfg.stack_size = 2048;
|
stats = p && (*p == '1' || *p == 'Y' || *p == 'y');
|
||||||
esp_pthread_set_cfg(&cfg);
|
free(p);
|
||||||
pthread_create(&stats_thread, NULL, output_thread_i2s_stats, NULL);
|
|
||||||
|
// memory still used but at least task is not created
|
||||||
|
if (stats) {
|
||||||
|
static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4)));
|
||||||
|
static EXT_RAM_ATTR StackType_t xStack[STAT_STACK_SIZE] __attribute__ ((aligned (4)));
|
||||||
|
stats_task = xTaskCreateStatic( (TaskFunction_t) output_thread_i2s_stats, "output_i2s_sts", STAT_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 1, xStack, &xTaskBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -279,7 +299,7 @@ void output_close_i2s(void) {
|
|||||||
running = false;
|
running = false;
|
||||||
UNLOCK;
|
UNLOCK;
|
||||||
pthread_join(thread, NULL);
|
pthread_join(thread, NULL);
|
||||||
pthread_join(stats_thread, NULL);
|
if (stats) vTaskDelete(stats_task);
|
||||||
|
|
||||||
i2s_driver_uninstall(CONFIG_I2S_NUM);
|
i2s_driver_uninstall(CONFIG_I2S_NUM);
|
||||||
free(obuf);
|
free(obuf);
|
||||||
@@ -345,7 +365,7 @@ static int _i2s_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32
|
|||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
* Main output thread
|
* Main output thread
|
||||||
*/
|
*/
|
||||||
static void *output_thread_i2s() {
|
static void *output_thread_i2s(void *arg) {
|
||||||
size_t count = 0, bytes;
|
size_t count = 0, bytes;
|
||||||
frames_t iframes = FRAME_BLOCK;
|
frames_t iframes = FRAME_BLOCK;
|
||||||
uint32_t timer_start = 0;
|
uint32_t timer_start = 0;
|
||||||
@@ -369,8 +389,11 @@ static void *output_thread_i2s() {
|
|||||||
// manage led display & analogue
|
// manage led display & analogue
|
||||||
if (state != output.state) {
|
if (state != output.state) {
|
||||||
LOG_INFO("Output state is %d", output.state);
|
LOG_INFO("Output state is %d", output.state);
|
||||||
if (output.state == OUTPUT_OFF) led_blink(LED_GREEN, 100, 2500);
|
if (output.state == OUTPUT_OFF) {
|
||||||
else if (output.state == OUTPUT_STOPPED) {
|
led_blink(LED_GREEN, 100, 2500);
|
||||||
|
if (amp_gpio != -1) gpio_set_level(amp_gpio, 0);
|
||||||
|
LOG_INFO("switching off amp GPIO %d", amp_gpio);
|
||||||
|
} else if (output.state == OUTPUT_STOPPED) {
|
||||||
adac->speaker(false);
|
adac->speaker(false);
|
||||||
led_blink(LED_GREEN, 200, 1000);
|
led_blink(LED_GREEN, 200, 1000);
|
||||||
} else if (output.state == OUTPUT_RUNNING) {
|
} else if (output.state == OUTPUT_RUNNING) {
|
||||||
@@ -432,6 +455,7 @@ static void *output_thread_i2s() {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
||||||
@@ -476,13 +500,12 @@ static void *output_thread_i2s() {
|
|||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
* Stats output thread
|
* Stats output thread
|
||||||
*/
|
*/
|
||||||
static void *output_thread_i2s_stats() {
|
static void *output_thread_i2s_stats(void *arg) {
|
||||||
//return;
|
while (1) {
|
||||||
while (running) {
|
// no need to lock
|
||||||
LOCK;
|
|
||||||
output_state state = output.state;
|
output_state state = output.state;
|
||||||
UNLOCK;
|
|
||||||
if(state>OUTPUT_STOPPED){
|
if(stats && state>OUTPUT_STOPPED){
|
||||||
LOG_INFO( "Output State: %d, current sample rate: %d, bytes per frame: %d",state,output.current_sample_rate, bytes_per_frame);
|
LOG_INFO( "Output State: %d, current sample rate: %d, bytes per frame: %d",state,output.current_sample_rate, bytes_per_frame);
|
||||||
LOG_INFO( LINE_MIN_MAX_FORMAT_HEAD1);
|
LOG_INFO( LINE_MIN_MAX_FORMAT_HEAD1);
|
||||||
LOG_INFO( LINE_MIN_MAX_FORMAT_HEAD2);
|
LOG_INFO( LINE_MIN_MAX_FORMAT_HEAD2);
|
||||||
@@ -502,7 +525,7 @@ static void *output_thread_i2s_stats() {
|
|||||||
LOG_INFO(" ----------+----------+-----------+-----------+");
|
LOG_INFO(" ----------+----------+-----------+-----------+");
|
||||||
RESET_ALL_MIN_MAX;
|
RESET_ALL_MIN_MAX;
|
||||||
}
|
}
|
||||||
usleep(STATS_PERIOD_MS *1000);
|
vTaskDelay( pdMS_TO_TICKS( STATS_PERIOD_MS ) );
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -321,6 +321,12 @@ void register_default_nvs(){
|
|||||||
|
|
||||||
ESP_LOGD(TAG,"Registering default value for key %s", "telnet_block");
|
ESP_LOGD(TAG,"Registering default value for key %s", "telnet_block");
|
||||||
config_set_default(NVS_TYPE_STR, "telnet_block", "500", 0);
|
config_set_default(NVS_TYPE_STR, "telnet_block", "500", 0);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG,"Registering default value for key %s", "stats");
|
||||||
|
config_set_default(NVS_TYPE_STR, "stats", "n", 0);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG,"Registering default value for key %s", "amp_GPIO");
|
||||||
|
config_set_default(NVS_TYPE_STR, "amp_GPIO", "", 0);
|
||||||
|
|
||||||
ESP_LOGD(TAG,"Done setting default values in nvs.");
|
ESP_LOGD(TAG,"Done setting default values in nvs.");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user