Compare commits

...

14 Commits

Author SHA1 Message Date
Philippe G
50390dbc61 Fix i2s mode for 32 bits & SPDIF - release 2021-09-24 18:19:50 -07:00
Philippe G
fc5f3f5ac9 remove extra UNLOCK_S in opus - release 2021-09-18 09:30:03 -07:00
Philippe G
6f4ed0679e fix 32 bits sample size L/R swap - release
issue is in esp-idf
2021-09-11 21:40:10 -07:00
Philippe G
511df0b4b8 release 2021-08-19 19:13:35 -07:00
Philippe G
6682ee947e Merge branch 'master-cmake' of https://github.com/sle118/squeezelite-esp32 into master-cmake 2021-08-19 19:12:09 -07:00
Philippe G
813e7ee712 use polling for gpio 36 & 39 - release 2021-08-19 19:11:39 -07:00
philippe44
6c9537e259 Update README.md 2021-08-19 19:10:39 -07:00
Philippe G
ac9ad2eee2 send ANIC when grfe's transitiion is not 'c' - release 2021-08-14 11:39:24 -07:00
Philippe G
f38840bbe0 release 2021-08-09 18:02:57 -07:00
Philippe G
fd56f649ab Merge branch 'master-cmake' of https://github.com/sle118/squeezelite-esp32 into master-cmake 2021-08-09 18:01:53 -07:00
Philippe G
c4bd320afe close memory stream before returning on parsing error - release 2021-08-09 18:01:48 -07:00
philippe44
5e8978d1af Update README.md 2021-08-06 09:34:52 -07:00
philippe44
6e082a5654 Update README.md 2021-08-04 13:28:15 -07:00
philippe44
5af3250aea Update README.md 2021-08-04 13:27:21 -07:00
12 changed files with 80 additions and 51 deletions

View File

@@ -95,7 +95,7 @@ for AC101
- dac_config: model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32
for ES8388
- dac_config model=ES8388,bck=5,ws=26,do=25,sda=18,scl=23,i2c=16
- dac_config: model=ES8388,bck=5,ws=25,do=26,sda=18,scl=23,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
@@ -144,7 +144,7 @@ The NVS parameter "dac_config" set the gpio used for i2s communication with your
```
bck=<gpio>,ws=<gpio>,do=<gpio>[,mck][,mute=<gpio>[:0|1][,model=TAS57xx|TAS5713|AC101|I2S][,sda=<gpio>,scl=gpio[,i2c=<addr>]]
```
if "model" is not set or is not recognized, then default "I2S" is used. The option "mck" is used for some codecs that require a master clock (although they should not). Only GPIO can be used as MCLK. I2C parameters are optional an only needed if your dac requires an I2C control (See 'dac_controlset' below). Note that "i2c" parameters are decimal, hex notation is not allowed.
if "model" is not set or is not recognized, then default "I2S" is used. The option "mck" is used for some codecs that require a master clock (although they should not). Only GPIO0 can be used as MCLK. I2C parameters are optional an only needed if your dac requires an I2C control (See 'dac_controlset' below). Note that "i2c" parameters are decimal, hex notation is not allowed.
So far, TAS75xx, TAS5714, AC101 and ES8388 are recognized models where the proper init sequence/volume/power controls are sent. For other codecs that might require an I2C commands, please use the parameter "dac_controlset" that allows definition of simple commands to be sent over i2c for init, power on and off using a JSON syntax:
```
@@ -243,6 +243,7 @@ Syntax is:
<gpio>=Vcc|GND|amp[:1|0]|ir|jack[:0|1]|green[:0|1]|red[:0|1]|spkfault[:0|1][,<repeated sequence for next GPIO>]
```
You can define the defaults for jack, spkfault leds at compile time but nvs parameter takes precedence except for well-known configurations where these are forced at runtime.
**Note that gpio 36 and 39 are input only and cannot use interrupt. When set to jack or speaker fault, a 100ms polling checks their value but that's expensive**
### LED
See §**set_GPIO** for how to set the green and red LEDs. In addition, their brightness can be controlled using the "led_brigthness" parameter. The syntax is
```
@@ -273,6 +274,7 @@ The SW gpio is optional, you can re-affect it to a pure button if you prefer but
See also the "IMPORTANT NOTE" on the "Buttons" section and remember that when 'lms_ctrls_raw' (see below) is activated, none of these knobonly,volume,longpress options apply, raw button codes (not actions) are simply sent to LMS
**Note that gpio 36 and 39 are input only and cannot use interrupt, so they cannot be set to A or B. When using them for SW, a 100ms polling is used which is expensive**
### Buttons
Buttons are described using a JSON string with the following syntax
```
@@ -307,10 +309,11 @@ Where (all parameters are optionals except gpio)
Where \<action\> is either the name of another configuration to load (remap) or one amongst
```
ACTRLS_NONE, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY,
ACTRLS_NONE, ACTRLS_POWER, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY,
ACTRLS_PAUSE, ACTRLS_STOP, ACTRLS_REW, ACTRLS_FWD, ACTRLS_PREV, ACTRLS_NEXT,
BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT,
KNOB_LEFT, KNOB_RIGHT, KNOB_PUSH
BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT,
BCTRLS_PS1, BCTRLS_PS2, BCTRLS_PS3, BCTRLS_PS4, BCTRLS_PS5, BCTRLS_PS6,
KNOB_LEFT, KNOB_RIGHT, KNOB_PUSH,
```
One you've created such a string, use it to fill a new NVS parameter with any name below 16(?) characters. You can have as many of these configs as you can. Then set the config parameter "actrls_config" with the name of your default config
@@ -365,7 +368,8 @@ The benefit of the "raw" mode is that you can build a player which is as close a
**Be aware that when using non "raw" mode, the CLI (Command Line Interface) of LMS is used and *must* be available without password**
There is no good or bad option, it's your choice. Use the NVS parameter "lms_ctrls_raw" to change that option
**Note that gpio 36 and 39 are input only and cannot use interrupt. When using them for a button, a 100ms polling is started which is expensive. Long press is also likely to not work very well**
### Battery / ADC
The NVS parameter "bat_config" sets the ADC1 channel used to measure battery/DC voltage. The "atten" value attenuates the input voltage to the ADC input (the read value maintains a 0-1V rage) where: 0=no attenuation(0..800mV), 1=2.5dB attenuation(0..1.1V), 2=6dB attenuation(0..1.35V), 3=11dB attenuation(0..2.6V). Scale is a float ratio applied to every sample of the 12 bits ADC. A measure is taken every 10s and an average is made every 5 minutes (not a sliding window). Syntax is
```

View File

@@ -306,6 +306,7 @@ static int do_bt_source_cmd(int argc, char **argv){
}
if(nerrors >0){
arg_print_errors(f,bt_source_args.end,desc_bt_source);
fclose(f);
return 1;
}
@@ -416,6 +417,7 @@ static int do_audio_cmd(int argc, char **argv){
}
if(nerrors >0){
arg_print_errors(f,audio_args.end,desc_audio);
fclose(f);
return 1;
}
@@ -479,6 +481,7 @@ static int do_spdif_cmd(int argc, char **argv){
}
if(nerrors >0){
arg_print_errors(f,spdif_args.end,desc_dac);
fclose(f);
return 1;
}
nerrors+=is_output_gpio(spdif_args.clock, f, &i2s_dac_pin.pin.bck_io_num, true);
@@ -517,6 +520,7 @@ static int do_rotary_cmd(int argc, char **argv){
}
if(nerrors >0){
arg_print_errors(f,rotary_args.end,desc_rotary);
fclose(f);
return 1;
}
nerrors+=is_gpio(rotary_args.A, f, &rotary.A, true,false);
@@ -584,6 +588,7 @@ static int do_i2s_cmd(int argc, char **argv)
}
if(nerrors >0){
arg_print_errors(f,i2s_args.end,desc_dac);
fclose(f);
return 1;
}
nerrors+=is_output_gpio(i2s_args.clock, f, &i2s_dac_pin.pin.bck_io_num, true);
@@ -805,6 +810,7 @@ cJSON * squeezelite_cb(){
argv = (char **) calloc(22, sizeof(char *));
if (argv == NULL) {
FREE_AND_NULL(nvs_config);
fclose(f);
return values;
}
size_t argc = esp_console_split_argv(nvs_config, argv,22);

View File

@@ -324,6 +324,7 @@ static int do_i2c_set_display(int argc, char **argv)
}
if(nerrors>0){
arg_print_errors(f,i2cdisp_args.end,desc_display);
fclose(f);
return 1;
}
/* Check "--type" option */
@@ -446,6 +447,7 @@ static int do_spiconfig_cmd(int argc, char **argv){
}
if(nerrors>0){
arg_print_errors(f,spiconfig_args.end,desc_spiconfig);
fclose(f);
return 1;
}
/* Check "--clk" option */
@@ -520,6 +522,7 @@ static int do_i2cconfig_cmd(int argc, char **argv)
}
if(nerrors>0){
arg_print_errors(f,i2cconfig_args.end,desc_i2c);
fclose(f);
return 1;
}
/* Check "--port" option */

View File

@@ -40,7 +40,6 @@
#endif
static struct {
struct arg_str *scanmode;
//disable_ps struct arg_lit *disable_power_save;
struct arg_end *end;
} wifi_parms_arg;
static struct {
@@ -610,7 +609,6 @@ static int do_configure_wifi(int argc, char **argv){
cmd_send_messaging(argv[0],MESSAGING_ERROR,"Unable to open memory stream.");
return 1;
}
// disable_ps nerrors += enable_disable(f,"disable_ps",wifi_parms_arg.disable_power_save);
if(wifi_parms_arg.scanmode->count>0){
if(strcasecmp(wifi_parms_arg.scanmode->sval[0],"Comprehensive") == 0){
@@ -690,11 +688,7 @@ static int do_set_services(int argc, char **argv)
cJSON * configure_wifi_cb(){
cJSON * values = cJSON_CreateObject();
char * p=NULL;
// disable_ps
// if ((p = config_alloc_get(NVS_TYPE_STR, "disable_ps")) != NULL) {
// cJSON_AddBoolToObject(values,"disable_power_save",strcmp(p,"1") == 0 || strcasecmp(p,"y") == 0);
// FREE_AND_NULL(p);
// }
if ((p = config_alloc_get(NVS_TYPE_STR, "wifi_smode")) != NULL) {
cJSON_AddStringToObject(values,"scanmode",strcasecmp(p,"a") == 0 ?"Comprehensive":"Fast");
FREE_AND_NULL(p);
@@ -757,7 +751,6 @@ static void register_set_services(){
static void register_set_wifi_parms(){
wifi_parms_arg.scanmode = arg_str0(NULL, "scanmode", "Fast|Comprehensive","Sets the WiFi Scan Mode. Use Comprehensive where more than one AP has the same name on different channels. This will ensure that the AP with the strongest signal is chosen.");
//disable_ps wifi_parms_arg.disable_power_save = arg_lit0(NULL, "disable_power_save", "Disable Power Saving. This may help if the wifi connection is unstable.");
wifi_parms_arg.end=arg_end(2);
const esp_console_cmd_t cmd = {
.command = CFG_TYPE_SYST("wifi"),

View File

@@ -25,8 +25,6 @@
#include "rotary_encoder.h"
#include "globdefs.h"
bool gpio36_39_used;
static const char * TAG = "buttons";
static int n_buttons = 0;
@@ -49,6 +47,13 @@ static EXT_RAM_ATTR struct button_s {
TimerHandle_t timer;
} buttons[MAX_BUTTONS];
static struct {
int gpio, level;
struct button_s *button;
} polled_gpio[] = { {36, -1, NULL}, {39, -1, NULL}, {-1, -1, NULL} };
static TimerHandle_t polled_timer;
static struct {
QueueHandle_t queue;
void *client;
@@ -117,6 +122,22 @@ static void buttons_timer( TimerHandle_t xTimer ) {
}
}
/****************************************************************************************
* Buttons polling timer
*/
static void buttons_polling( TimerHandle_t xTimer ) {
for (int i = 0; polled_gpio[i].gpio != -1; i++) {
if (!polled_gpio[i].button) continue;
int level = gpio_get_level(polled_gpio[i].gpio);
if (level != polled_gpio[i].level) {
polled_gpio[i].level = level;
buttons_timer(polled_gpio[i].button->timer);
}
}
}
/****************************************************************************************
* Tasks that calls the appropriate functions when buttons are pressed
*/
@@ -252,14 +273,29 @@ void button_create(void *client, int gpio, int type, bool pull, int debounce, bu
}
}
// nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated
if (gpio == 36 || gpio == 39) gpio36_39_used = true;
// and initialize level ...
buttons[n_buttons].level = gpio_get_level(gpio);
gpio_isr_handler_add(gpio, gpio_isr_handler, (void*) &buttons[n_buttons]);
gpio_intr_enable(gpio);
// nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated
for (int i = 0; polled_gpio[i].gpio != -1; i++) if (polled_gpio[i].gpio == gpio) {
if (!polled_timer) {
polled_timer = xTimerCreate("buttonsPolling", 100 / portTICK_RATE_MS, pdTRUE, polled_gpio, buttons_polling);
xTimerStart(polled_timer, portMAX_DELAY);
}
polled_gpio[i].button = buttons + n_buttons;
polled_gpio[i].level = gpio_get_level(gpio);
ESP_LOGW(TAG, "creating polled gpio %u, level %u", gpio, polled_gpio[i].level);
gpio = -1;
break;
}
// only create timers and ISR is this is not a polled gpio
if (gpio != -1) {
gpio_isr_handler_add(gpio, gpio_isr_handler, (void*) &buttons[n_buttons]);
gpio_intr_enable(gpio);
}
n_buttons++;
}
@@ -337,7 +373,8 @@ static void rotary_button_handler(void *id, button_event_e event, button_press_e
* Create rotary encoder
*/
bool create_rotary(void *id, int A, int B, int SW, int long_press, rotary_handler handler) {
if (A == -1 || B == -1) {
// nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated
if (A == -1 || B == -1 || A == 36 || A == 39 || B == 36 || B == 39) {
ESP_LOGI(TAG, "Cannot create rotary %d %d", A, B);
return false;
}
@@ -348,9 +385,6 @@ bool create_rotary(void *id, int A, int B, int SW, int long_press, rotary_handle
rotary.client = id;
rotary.handler = handler;
// nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated
if (A == 36 || A == 39 || B == 36 || B == 39 || SW == 36 || SW == 39) gpio36_39_used = true;
// Initialise the rotary encoder device with the GPIOs for A and B signals
rotary_encoder_init(&rotary.info, A, B);

View File

@@ -17,7 +17,6 @@ extern int i2c_system_port;
extern int i2c_system_speed;
extern int spi_system_host;
extern int spi_system_dc_gpio;
extern bool gpio36_39_used;
typedef struct {
int timer, base_channel, max;
} pwm_system_t;

View File

@@ -928,8 +928,8 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
if (i2s_config->mode & I2S_MODE_TX) {
// PATCH
I2S[i2s_num]->conf.tx_msb_right = 1;
I2S[i2s_num]->conf.tx_right_first = 0;
I2S[i2s_num]->conf.tx_msb_right = i2s_config->bits_per_sample == 32 ? 0 : 1;
I2S[i2s_num]->conf.tx_right_first = ~I2S[i2s_num]->conf.tx_msb_right;
I2S[i2s_num]->conf.tx_slave_mod = 0; // Master
I2S[i2s_num]->fifo_conf.tx_fifo_mod_force_en = 1;
@@ -940,8 +940,7 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
}
if (i2s_config->mode & I2S_MODE_RX) {
// PATCH
I2S[i2s_num]->conf.rx_msb_right = 1;
I2S[i2s_num]->conf.rx_msb_right = 1;
I2S[i2s_num]->conf.rx_right_first = 0;
I2S[i2s_num]->conf.rx_slave_mod = 0; // Master
I2S[i2s_num]->fifo_conf.rx_fifo_mod_force_en = 1;

View File

@@ -657,7 +657,14 @@ void draw_VU(struct GDS_Device * display, const uint8_t *data, int level, int x,
* Process graphic display data
*/
static void grfe_handler( u8_t *data, int len) {
struct grfe_packet *pkt = (struct grfe_packet*) data;
// we don't support transition, simply claim we're done
if (pkt->transition != 'c') {
LOG_INFO("Transition %c requested with offset %hu, param %d", pkt->transition, pkt->offset, pkt->param);
sendANIC(ANIM_TRANSITION);
}
xSemaphoreTake(displayer.mutex, portMAX_DELAY);
scroller.active = false;

View File

@@ -229,7 +229,6 @@ static decode_state opus_decompress(void) {
if (stream.state <= DISCONNECT) {
LOG_INFO("partial decode");
UNLOCK_O_direct;
UNLOCK_S;
return DECODE_COMPLETE;
} else {
LOG_INFO("no frame decoded");

View File

@@ -238,10 +238,7 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
set_i2s_pin(spdif_config, &i2s_spdif_pin);
set_i2s_pin(dac_config, &i2s_dac_pin);
/* BEWARE: i2s. must be patched to set tx_msb_right/rx_msb_right to 1
* or SPDIF will not work. These settings are not accessible from
* userland and I don't know why
*/
/* BEWARE: i2s.c must be patched otherwise L/R are swapped in 32 bits mode */
// common I2S initialization
i2s_config.mode = I2S_MODE_MASTER | I2S_MODE_TX;

View File

@@ -283,18 +283,6 @@ void wifi_manager_init_wifi(){
ESP_LOGD(TAG, "Initializing wifi. Setting WiFi mode to WIFI_MODE_NULL");
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_NULL) );
ESP_LOGD(TAG, "Initializing wifi. Starting wifi");
// char * disable_ps = config_alloc_get_default(NVS_TYPE_STR, "disable_ps", "n", 0);
// if (gpio36_39_used || (disable_ps && strcasecmp(disable_ps,"y")==0)) {
// if(gpio36_39_used){
// ESP_LOGW(TAG, "GPIO 36 or 39 are in use, need to disable WiFi PowerSave!");
// }
// else {
// ESP_LOGW(TAG, "wifi powersave config is disabled. Disabling WiFi PowerSave!");
// }
// esp_wifi_set_ps(WIFI_PS_NONE);
// }
// FREE_AND_NULL(disable_ps);
ESP_ERROR_CHECK( esp_wifi_start() );
taskYIELD();

View File

@@ -107,8 +107,8 @@ PLUGIN_SQUEEZEESP32_ARTWORK_Y
EN Y
PLUGIN_SQUEEZEESP32_EQUALIZER
DE Parametrischer Equalizer
EN Parametric equalizer
DE Grafischer Equalizer
EN Graphic equalizer
PLUGIN_SQUEEZEESP32_EQUALIZER_SAVE
DE Bitte speichern Sie die Equalizer Einstellungen, falls das Gerät diese dauerhaft verwenden soll. Ansonsten werden sie beim nächsten Start zurückgesetzt.