Compare commits

...

6 Commits

Author SHA1 Message Date
Philippe G
9588ae9f39 amp gpio control with jack - release 2021-11-20 11:08:48 -08:00
philippe44
c0c37bd98a Update CrossBuild.yml 2021-11-18 23:07:58 -08:00
philippe44
d5a8e3a4a2 Update CrossBuild.yml 2021-11-18 23:06:16 -08:00
Philippe G
d4b0bc4edb SPIRAM cannot be used for initialized data - release 2021-11-18 18:37:18 -08:00
Philippe G
635d382d71 fully remove ctrl_fd (was uninitialized in server loop) - release 2021-11-18 12:22:48 -08:00
philippe44
5d09d4f853 Update README.md 2021-11-17 10:59:44 -08:00
7 changed files with 44 additions and 53 deletions

View File

@@ -1,6 +1,5 @@
# This is a basic workflow to help you get started with Actions
name: Cross-Build
on:
push:
branches-ignore: [ master ]

View File

@@ -71,7 +71,7 @@ NB: You can use the pre-build binaries SqueezeAMP4MBFlash which has all the hard
- spdif_config: bck=33,ws=25,do=15
### ESP32-A1S
Works with [ESP32-A1S](https://docs.ai-thinker.com/esp32-a1s) module that includes audio codec and headset output. You still need to use a demo board like [this](https://www.aliexpress.com/item/4001060963585.html) or an external amplifier if you want direct speaker connection. Note that there is a version with AC101 codec and another one with ES8388 (see below)
Works with [ESP32-A1S](https://docs.ai-thinker.com/esp32-a1s) module that includes audio codec and headset output. You still need to use a demo board like [this](https://www.aliexpress.com/item/4001060963585.html) or an external amplifier if you want direct speaker connection. Note that there is a version with AC101 codec and another one with ES8388 with probably two variants - these boards are a mess (see below)
The board shown above has the following IO set
- amplifier: GPIO21
@@ -95,8 +95,10 @@ So a possible config would be
for AC101
- dac_config: model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32
for ES8388
for ES8388 (it seems that there are variants with same version number - a total mess)
- dac_config: model=ES8388,bck=5,ws=25,do=26,sda=18,scl=23,i2c=16
or
- dac_config: model=ES8388,bck=27,ws=25,do=26,sda=33,scl=32,i2c=16
### T-WATCH2020 by LilyGo
This is a fun [smartwatch](http://www.lilygo.cn/prod_view.aspx?TypeId=50036&Id=1290&FId=t3:50036:3) based on ESP32. It has a 240x240 ST7789 screen and onboard audio. Not very useful to listen to anything but it works. This is an example of a device that requires an I2C set of commands for its dac (see below). There is a build-option if you decide to rebuild everything by yourself, otherwise the I2S default option works with the following parameters

View File

@@ -40,7 +40,8 @@ static EXT_RAM_ATTR struct led_s {
TimerHandle_t timer;
} leds[MAX_LED];
static EXT_RAM_ATTR struct {
// can't use EXT_RAM_ATTR for initialized structure
static struct {
int gpio;
int active;
int pwm;

View File

@@ -145,7 +145,7 @@ static void monitor_callback(TimerHandle_t xTimer) {
*
*/
static void jack_handler_default(void *id, button_event_e event, button_press_e mode, bool long_press) {
ESP_LOGD(TAG, "Jack %s", event == BUTTON_PRESSED ? "inserted" : "removed");
ESP_LOGI(TAG, "Jack %s", event == BUTTON_PRESSED ? "inserted" : "removed");
if (jack_handler_svc) (*jack_handler_svc)(event == BUTTON_PRESSED);
}

View File

@@ -20,8 +20,8 @@
static const char TAG[] = "DAC external";
static void speaker(bool active) { }
static void headset(bool active) { }
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, i2s_config_t *i2s_config);
@@ -95,6 +95,22 @@ static void power(adac_power_e mode) {
else i2c_json_execute("poweron");
}
/****************************************************************************************
* speaker
*/
static void speaker(bool active) {
if (active) i2c_json_execute("speakeron");
else i2c_json_execute("speakeroff");
}
/****************************************************************************************
* headset
*/
static void headset(bool active) {
if (active) i2c_json_execute("headseton");
else i2c_json_execute("headsetoff");
}
/****************************************************************************************
*
*/

View File

@@ -129,8 +129,13 @@ static bool handler(u8_t *data, int len){
jack_mutes_amp = pkt->config == 0;
config_set_value(NVS_TYPE_STR, "jack_mutes_amp", jack_mutes_amp ? "y" : "n");
if (jack_mutes_amp && jack_inserted_svc()) adac->speaker(false);
else adac->speaker(true);
if (jack_mutes_amp && jack_inserted_svc()) {
adac->speaker(false);
if (amp_control.gpio != -1) gpio_set_level(amp_control.gpio, !amp_control.active);
} else {
adac->speaker(true);
if (amp_control.gpio != -1) gpio_set_level(amp_control.gpio, amp_control.active);
}
}
LOG_INFO("got AUDO %02x", pkt->config);
@@ -151,13 +156,12 @@ static void jack_handler(bool inserted) {
// jack detection bounces a bit but that seems fine
if (jack_mutes_amp) {
LOG_INFO("switching amplifier %s", inserted ? "OFF" : "ON");
if (inserted) adac->speaker(false);
else adac->speaker(true);
adac->speaker(!inserted);
if (amp_control.gpio != -1) gpio_set_level(amp_control.gpio, inserted ? !amp_control.active : amp_control.active);
}
// activate headset
if (inserted) adac->headset(true);
else adac->headset(false);
adac->headset(inserted);
// and chain if any
if (jack_handler_chain) (jack_handler_chain)(inserted);
@@ -343,12 +347,13 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
jack_handler_chain = jack_handler_svc;
jack_handler_svc = jack_handler;
parse_set_GPIO(set_amp_gpio);
if (jack_mutes_amp && jack_inserted_svc()) adac->speaker(false);
else adac->speaker(true);
adac->headset(jack_inserted_svc());
parse_set_GPIO(set_amp_gpio);
// create task as a FreeRTOS task but uses stack in internal RAM
{
@@ -455,7 +460,10 @@ static void output_thread_i2s(void *arg) {
adac->speaker(false);
led_blink(LED_GREEN, 200, 1000);
} else if (output.state == OUTPUT_RUNNING) {
if (!jack_mutes_amp || !jack_inserted_svc()) adac->speaker(true);
if (!jack_mutes_amp || !jack_inserted_svc()) {
if (amp_control.gpio != -1) gpio_set_level(amp_control.gpio, amp_control.active);
adac->speaker(true);
}
led_on(LED_GREEN);
}
}
@@ -513,7 +521,6 @@ static void output_thread_i2s(void *arg) {
i2s_zero_dma_buffer(CONFIG_I2S_NUM);
i2s_start(CONFIG_I2S_NUM);
adac->power(ADAC_ON);
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)

View File

@@ -80,35 +80,6 @@ static esp_err_t _httpd_server_init(struct httpd_data *hd)
return ESP_OK;
}
static void _httpd_process_ctrl_msg(struct httpd_data *hd)
{
struct httpd_ctrl_data msg;
int ret = recv(hd->ctrl_fd, &msg, sizeof(msg), 0);
if (ret <= 0) {
ESP_LOGW(TAG, LOG_FMT("error in recv (%d)"), errno);
return;
}
if (ret != sizeof(msg)) {
ESP_LOGW(TAG, LOG_FMT("incomplete msg"));
return;
}
switch (msg.hc_msg) {
case HTTPD_CTRL_WORK:
if (msg.hc_work) {
ESP_LOGD(TAG, LOG_FMT("work"));
(*msg.hc_work)(msg.hc_work_arg);
}
break;
case HTTPD_CTRL_SHUTDOWN:
ESP_LOGD(TAG, LOG_FMT("shutdown"));
hd->hd_td.status = THREAD_STOPPING;
break;
default:
break;
}
}
static esp_err_t _httpd_accept_conn(struct httpd_data *hd, int listen_fd)
{
/* If no space is available for new session, close the least recently used one */
@@ -164,13 +135,10 @@ static esp_err_t _httpd_server(struct httpd_data *hd)
* older connections will be closed) */
FD_SET(hd->listen_fd, &read_set);
}
FD_SET(hd->ctrl_fd, &read_set);
int tmp_max_fd;
httpd_sess_set_descriptors(hd, &read_set, &tmp_max_fd);
int maxfd = MAX(hd->listen_fd, tmp_max_fd);
tmp_max_fd = maxfd;
maxfd = MAX(hd->ctrl_fd, tmp_max_fd);
int maxfd;
httpd_sess_set_descriptors(hd, &read_set, &maxfd);
maxfd = MAX(hd->listen_fd, maxfd);
ESP_LOGD(TAG, LOG_FMT("doing select maxfd+1 = %d"), maxfd + 1);
int active_cnt = select(maxfd + 1, &read_set, NULL, NULL, NULL);
@@ -180,8 +148,6 @@ static esp_err_t _httpd_server(struct httpd_data *hd)
return ESP_OK;
}
/* Case0: Do we have a control message? */
/* Case1: Do we have any activity on the current data
* sessions? */
int fd = -1;