mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-24 08:28:29 +03:00
Compare commits
32 Commits
I2S-4MFlas
...
SqueezeAmp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c36d663a7f | ||
|
|
13294ddd0c | ||
|
|
449ef32a4e | ||
|
|
50390dbc61 | ||
|
|
fc5f3f5ac9 | ||
|
|
6f4ed0679e | ||
|
|
511df0b4b8 | ||
|
|
6682ee947e | ||
|
|
813e7ee712 | ||
|
|
6c9537e259 | ||
|
|
ac9ad2eee2 | ||
|
|
f38840bbe0 | ||
|
|
fd56f649ab | ||
|
|
c4bd320afe | ||
|
|
5e8978d1af | ||
|
|
6e082a5654 | ||
|
|
5af3250aea | ||
|
|
527187b2f8 | ||
|
|
102d2f6af5 | ||
|
|
4edd429b0a | ||
|
|
35099d1131 | ||
|
|
ce9c3952e8 | ||
|
|
4ee6352185 | ||
|
|
3a720a1e7d | ||
|
|
987fa5d18c | ||
|
|
23c936ec93 | ||
|
|
d4f10a761e | ||
|
|
d68d163538 | ||
|
|
94580c6771 | ||
|
|
2717277c6e | ||
|
|
b6d537a207 | ||
|
|
cf047c8098 |
2
.github/workflows/CrossBuild.yml
vendored
2
.github/workflows/CrossBuild.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
strategy:
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
node: [I2S-4MFlash, SqueezeAmp, ESP32-A1S]
|
||||
node: [I2S-4MFlash, SqueezeAmp]
|
||||
depth: [16, 32]
|
||||
steps:
|
||||
- name: Set target name
|
||||
|
||||
54
README.md
54
README.md
@@ -23,23 +23,25 @@ Other features include
|
||||
- Full web interface for further configuration/management
|
||||
- Firmware over-the-air update
|
||||
|
||||
To control the equalizer or use the display on LMS, a new player model is required and this is provided through a plugin that is part of LMS' 3rd party repositories
|
||||
|
||||
## Performances
|
||||
*(opinions presented here so I = @philippe44)*
|
||||
The main build of squeezelite-esp32 is a 16 bits internal core with all calculations in 32 bits or float precision. This is a design choice I've made to preserve CPU performances (it is already stretching a lot the esp32 chipset) and optimize memory usage as we only have 4MB of usable RAM. Some might correctly comment that the WROVER module have 8MB of RAM, but the processor is only able to address 4MB and the remaining 4MB must be paginated by smaller blocks and I don't have patience to that.
|
||||
|
||||
Now, when I did the porting of squeezelite to esp32, I've also made the core 16 or 32 bits compatible at compile-time. So far, it works in 32 bits but less tests have been done. You can chose to compile it in 32 bits mode. I'm not very interested above 16 bits samples because it does not bring anything (I have an engineering background in theory of information).
|
||||
|
||||
| Capability |16 bits|32 bits| comment |
|
||||
|----------------------------|-------|-------|-------------------------------------------------------------------|
|
||||
| max sampling rate | 192k | 96k | 192k is very challenging, especially when combined with display |
|
||||
| max bit depth | 16 | 24 | 24 bits are truncated in 16 bits mode |
|
||||
| spdif |16 bits|20 bits| |
|
||||
| mp3, aac, opus, ogg/vorbis | 48k | 48k | |
|
||||
| alac, flac, ogg/flac | 96k | 96k | |
|
||||
| pcm, wav, aif | 192k | 96k | |
|
||||
| equalizer | Y | N | 48kHz max (after resampling) - equalization skipped on 96k tracks |
|
||||
| resampling | Y | N | |
|
||||
| cross-fade | 10s | <5s | depends on buffer size and sampling rate |
|
||||
| Capability |16 bits|32 bits| comment |
|
||||
|----------------------------|-------|-------|--------------------------------------------------------------------|
|
||||
| max sampling rate | 192k | 96k | 192k is very challenging, especially when combined with display |
|
||||
| max bit depth | 16 | 24 | 24 bits are truncated in 16 bits mode |
|
||||
| spdif |16 bits|20 bits| |
|
||||
| mp3, aac, opus, ogg/vorbis | 48k | 48k | |
|
||||
| alac, flac, ogg/flac | 96k | 96k | |
|
||||
| pcm, wav, aif | 192k | 96k | |
|
||||
| equalizer | Y | N | 48kHz max (after resampling) - equalization skipped on >48k tracks |
|
||||
| resampling | Y | N | |
|
||||
| cross-fade | 10s | <5s | depends on buffer size and sampling rate |
|
||||
|
||||
The esp32 must run at 240 MHz, with Quad-SPI I/O at 80 MHz and a clock of 40 Mhz. Still, it's a lot to run, especially knowing that it has a serial Flash and PSRAM, so kudos to Espressif for their chipset optimization. Now, to have all the decoding, resampling, equalizing, gain, display, spectrum/vu is a very (very) delicate equilibrium between use of internal /external RAM, tasks priorities and buffer handling. It is not perfect and the more you push the system to the limit, the higher the risk that some files would not play (see below). In general, the display will always have the lowest priority and you'll notice slowdown in scrolling and VU/Spectrum refresh rates. Now, even display thread has some critical section and impacts the capabilities. For example, a 16 bits-depth color display with low SPI speed might prevent 24/96 flac to work but still work with pcm 24/96
|
||||
|
||||
@@ -68,7 +70,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.
|
||||
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)
|
||||
|
||||
The board shown above has the following IO set
|
||||
- amplifier: GPIO21
|
||||
@@ -85,11 +87,15 @@ The board shown above has the following IO set
|
||||
|
||||
So a possible config would be
|
||||
- set_GPIO: 21=amp,22=green:0,39=jack:0
|
||||
- dac_config: model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32
|
||||
- a button mapping:
|
||||
```
|
||||
[{"gpio":5,"normal":{"pressed":"ACTRLS_TOGGLE"}},{"gpio":18,"pull":true,"shifter_gpio":5,"normal":{"pressed":"ACTRLS_VOLUP"}, "shifted":{"pressed":"ACTRLS_NEXT"}}, {"gpio":23,"pull":true,"shifter_gpio":5,"normal":{"pressed":"ACTRLS_VOLDOWN"},"shifted":{"pressed":"ACTRLS_PREV"}}]
|
||||
```
|
||||
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=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
|
||||
|
||||
@@ -136,11 +142,11 @@ data=<gpio>,clk=<gpio>[,dc=<gpio>][,host=1|2]
|
||||
### DAC/I2S
|
||||
The NVS parameter "dac_config" set the gpio used for i2s communication with your DAC. You can define the defaults at compile time but nvs parameter takes precedence except for SqueezeAMP and A1S where these are forced at runtime. Syntax is
|
||||
```
|
||||
bck=<gpio>,ws=<gpio>,do=<gpio>[,mute=<gpio>[:0|1][,model=TAS57xx|TAS5713|AC101|I2S][,sda=<gpio>,scl=gpio[,i2c=<addr>]]
|
||||
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. 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.
|
||||
|
||||
The parameter "dac_controlset" allows definition of simple commands to be sent over i2c for init, power on and off using a JSON syntax:
|
||||
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:
|
||||
```
|
||||
{ init: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ],
|
||||
poweron: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ],
|
||||
@@ -148,7 +154,7 @@ The parameter "dac_controlset" allows definition of simple commands to be sent o
|
||||
```
|
||||
This is standard JSON notation, so if you are not familiar with it, Google is your best friend. Be aware that the '...' means you can have as many entries as you want, it's not part of the syntax. Every section is optional, but it does not make sense to set i2c in the 'dac_config' parameter and not setting anything here. The parameter 'mode' allows to *or* the register with the value or to *and* it. Don't set 'mode' if you simply want to write. **Note that all values must be decimal**. You can use a validator like [this](https://jsonlint.com) to verify your syntax
|
||||
|
||||
NB: For well-known configuration, this is ignored
|
||||
NB: For specific builds (all except I2S), all this is ignored. For know codecs, the built-in sequences can be overwritten using dac_controlset
|
||||
|
||||
<strong>Please note that you can not use the same GPIO or port as the I2C</strong>
|
||||
### SPDIF
|
||||
@@ -197,7 +203,7 @@ SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,back=<gpio>][,reset=<gpio>][,speed
|
||||
- ST7789 is a 240x320 65k (262k not enabled) color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/2inch-lcd-module.htm). It also exist with 240x240 displays. See **rotate** for use in portrait mode
|
||||
- ILI9341 is another 240x320 65k (262k capable) color SPI. I've not used it much, the driver it has been provided by one external contributor to the project
|
||||
|
||||
To use the display on LMS, add repository https://raw.githubusercontent.com/sle118/squeezelite-esp32/master/plugin/repo.xml. You will then be able to tweak how the vu-meter and spectrum analyzer are displayed, as well as size of artwork. You can also install the excellent plugin "Music Information Screen" which is super useful to tweak the layout.
|
||||
You can tweak how the vu-meter and spectrum analyzer are displayed, as well as size of artwork through a dedicated menu in player's settings (don't forget to add the plugin).
|
||||
|
||||
The NVS parameter "metadata_config" sets how metadata is displayed for AirPlay and Bluetooth. Syntax is
|
||||
```
|
||||
@@ -237,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
|
||||
```
|
||||
@@ -267,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
|
||||
```
|
||||
@@ -301,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
|
||||
@@ -359,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
|
||||
```
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -89,7 +89,12 @@ static bool init(char *config, int i2c_port, i2s_config_t *i2s_config) {
|
||||
adac_write_word(AC101_ADDR, I2S_SR_CTRL, BIN(0111,0000,0000,0000)); // 44.1kHz
|
||||
|
||||
// analogue config
|
||||
#if BYTES_PER_FRAME == 8
|
||||
adac_write_word(AC101_ADDR, I2S1LCK_CTRL, BIN(1000,1000,0111,0000)); // Slave, BCLK=I2S/8,LRCK=32,24bits,I2Smode, Stereo
|
||||
i2s_config->bits_per_sample = 24;
|
||||
#else
|
||||
adac_write_word(AC101_ADDR, I2S1LCK_CTRL, BIN(1000,1000,0101,0000)); // Slave, BCLK=I2S/8,LRCK=32,16bits,I2Smode, Stereo
|
||||
#endif
|
||||
adac_write_word(AC101_ADDR, I2S1_SDOUT_CTRL, BIN(1100,0000,0000,0000)); // I2S1ADC (R&L)
|
||||
adac_write_word(AC101_ADDR, I2S1_SDIN_CTRL, BIN(1100,0000,0000,0000)); // IS21DAC (R&L)
|
||||
adac_write_word(AC101_ADDR, I2S1_MXR_SRC, BIN(0010,0010,0000,0000)); // ADCL, ADCR
|
||||
|
||||
@@ -26,8 +26,16 @@ static int i2c_port = -1;
|
||||
int adac_init(char *config, int i2c_port_num) {
|
||||
char *p;
|
||||
int i2c_addr = 0;
|
||||
i2c_port = i2c_port_num;
|
||||
|
||||
// some crappy codecs require MCLK to work
|
||||
if ((p = strcasestr(config, "mck")) != NULL) {
|
||||
ESP_LOGI(TAG, "Configuring MCLK on GPIO0");
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
|
||||
REG_WRITE(PIN_CTRL, 0xFFFFFFF0);
|
||||
}
|
||||
|
||||
i2c_port = i2c_port_num;
|
||||
|
||||
// configure i2c
|
||||
i2c_config_t i2c_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
|
||||
@@ -166,6 +166,26 @@ const actrls_t LMS_controls = {
|
||||
lms_knob_left, lms_knob_right, lms_knob_push,
|
||||
};
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
static void connect_cli_socket(void) {
|
||||
struct sockaddr_in addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = server_ip,
|
||||
.sin_port = htons(server_cport),
|
||||
};
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
|
||||
cli_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (connect(cli_sock, (struct sockaddr *) &addr, addrlen) < 0) {
|
||||
LOG_ERROR("unable to connect to server %s:%hu with cli", inet_ntoa(server_ip), server_cport);
|
||||
closesocket(cli_sock);
|
||||
cli_sock = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
@@ -175,8 +195,12 @@ static void cli_send_cmd(char *cmd) {
|
||||
|
||||
len = sprintf(packet, "%02x:%02x:%02x:%02x:%02x:%02x %s\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], cmd);
|
||||
LOG_DEBUG("sending command %s at %s:%hu", packet, inet_ntoa(server_ip), server_cport);
|
||||
|
||||
|
||||
if (cli_sock < 0) connect_cli_socket();
|
||||
|
||||
if (send(cli_sock, packet, len, MSG_DONTWAIT) < 0) {
|
||||
closesocket(cli_sock);
|
||||
cli_sock = -1;
|
||||
LOG_WARN("cannot send CLI %s", packet);
|
||||
}
|
||||
|
||||
@@ -188,26 +212,14 @@ static void cli_send_cmd(char *cmd) {
|
||||
* Notification when server changes
|
||||
*/
|
||||
static void notify(in_addr_t ip, u16_t hport, u16_t cport) {
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
|
||||
server_ip = ip;
|
||||
server_hport = hport;
|
||||
server_cport = cport;
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = server_ip;
|
||||
addr.sin_port = htons(server_cport);
|
||||
|
||||
// close existing CLI connection and open new one
|
||||
if (cli_sock >= 0) closesocket(cli_sock);
|
||||
cli_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (connect(cli_sock, (struct sockaddr *) &addr, addrlen) < 0) {
|
||||
LOG_ERROR("unable to connect to server %s:%hu with cli", inet_ntoa(server_ip), server_cport);
|
||||
closesocket(cli_sock);
|
||||
cli_sock = -1;
|
||||
}
|
||||
connect_cli_socket();
|
||||
|
||||
LOG_INFO("notified server %s hport %hu cport %hu", inet_ntoa(ip), hport, cport);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
31
components/squeezelite/external/dac_external.c
vendored
31
components/squeezelite/external/dac_external.c
vendored
@@ -32,6 +32,21 @@ const struct adac_s dac_external = { "i2s", init, adac_deinit, power, speaker, h
|
||||
static cJSON *i2c_json;
|
||||
static int i2c_addr;
|
||||
|
||||
static struct {
|
||||
char *model;
|
||||
bool mclk;
|
||||
char *controlset;
|
||||
} codecs[] = {
|
||||
{ "es8388", true,
|
||||
"{\"init\":[ \
|
||||
{\"reg\":8,\"val\":0}, {\"reg\":2,\"val\":243}, {\"reg\":43,\"val\":128}, {\"reg\":0,\"val\":5}, \
|
||||
{\"reg\":1,\"val\":64}, {\"reg\":4,\"val\":60}, {\"reg\":23,\"val\":24}, {\"reg\":24,\"val\":2}, \
|
||||
{\"reg\":26,\"val\":0}, {\"reg\":27,\"val\":0}, {\"reg\":25,\"val\":50}, {\"reg\":38,\"val\":0}, \
|
||||
{\"reg\":39,\"val\":184}, {\"reg\":42,\"val\":184}, {\"reg\":46,\"val\":30}, {\"reg\":47,\"val\":30}, \
|
||||
{\"reg\":48,\"val\":30}, {\"reg\":49,\"val\":30}, {\"reg\":2,\"val\":170}]}" },
|
||||
{ NULL, false, NULL }
|
||||
};
|
||||
|
||||
/****************************************************************************************
|
||||
* init
|
||||
*/
|
||||
@@ -44,10 +59,22 @@ static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config) {
|
||||
ESP_LOGI(TAG, "DAC on I2C @%d", i2c_addr);
|
||||
|
||||
p = config_alloc_get_str("dac_controlset", CONFIG_DAC_CONTROLSET, NULL);
|
||||
|
||||
if ((!p || !*p) && (p = strcasestr(config, "model")) != NULL) {
|
||||
char model[32] = "";
|
||||
int i;
|
||||
sscanf(p, "%*[^=]=%31[^,]", model);
|
||||
for (i = 0; *model && ((p = codecs[i].controlset) != NULL) && strcasecmp(codecs[i].model, model); i++);
|
||||
if (p && codecs[i].mclk) {
|
||||
ESP_LOGI(TAG, "Configuring MCLK on GPIO0");
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
|
||||
REG_WRITE(PIN_CTRL, 0xFFFFFFF0);
|
||||
}
|
||||
}
|
||||
|
||||
i2c_json = cJSON_Parse(p);
|
||||
|
||||
if (!i2c_json) {
|
||||
if (p) free(p);
|
||||
ESP_LOGW(TAG, "no i2c controlset found");
|
||||
return true;
|
||||
}
|
||||
@@ -56,7 +83,7 @@ static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config) {
|
||||
ESP_LOGE(TAG, "could not intialize DAC");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -43,6 +43,11 @@ static const struct tas57xx_cmd_s tas57xx_init_sequence[] = {
|
||||
{ 0x25, 0x08 }, // ignore SCK halt
|
||||
{ 0x08, 0x10 }, // Mute control enable (from TAS5780)
|
||||
{ 0x54, 0x02 }, // Mute output control (from TAS5780)
|
||||
#if BYTES_PER_FRAME == 8
|
||||
{ 0x28, 0x03 }, // I2S length 32 bits
|
||||
#else
|
||||
{ 0x28, 0x00 }, // I2S length 16 bits
|
||||
#endif
|
||||
{ 0x02, 0x00 }, // restart
|
||||
{ 0xff, 0xff } // end of table
|
||||
};
|
||||
|
||||
@@ -62,7 +62,7 @@ static bool init(char *config, int i2c_port, i2s_config_t *i2s_config) {
|
||||
i2c_write_shadow(49, 102);
|
||||
|
||||
// Configure system clk to GPIO0 for DAC MCLK input
|
||||
ESP_LOGI(TAG, "Configuring MCLK on pin:%d", 0);
|
||||
ESP_LOGI(TAG, "Configuring MCLK on GPIO0");
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
|
||||
REG_WRITE(PIN_CTRL, 0xFFFFFFF0);
|
||||
|
||||
|
||||
@@ -1085,15 +1085,15 @@ window.setURL = function(button) {
|
||||
|
||||
function rssiToIcon(rssi) {
|
||||
if (rssi >= -55) {
|
||||
return `#signal-wifi-fill`;
|
||||
return `signal-wifi-fill`;
|
||||
} else if (rssi >= -60) {
|
||||
return `#signal-wifi-3-fill`;
|
||||
return `signal-wifi-3-fill`;
|
||||
} else if (rssi >= -65) {
|
||||
return `#signal-wifi-2-fill`;
|
||||
return `signal-wifi-2-fill`;
|
||||
} else if (rssi >= -70) {
|
||||
return `#signal-wifi-1-fill`;
|
||||
return `signal-wifi-1-fill`;
|
||||
} else {
|
||||
return `#signal-wifi-line`;
|
||||
return `signal-wifi-line`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/favicon-32x32.png BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/index.html.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/js/index.df6830.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/js/node-modules.df6830.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/js/runtime.df6830.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/js/index.0e064e.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/js/node-modules.0e064e.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/js/runtime.0e064e.bundle.js.gz BINARY)
|
||||
|
||||
@@ -4,31 +4,31 @@ extern const uint8_t _favicon_32x32_png_start[] asm("_binary_favicon_32x32_png_s
|
||||
extern const uint8_t _favicon_32x32_png_end[] asm("_binary_favicon_32x32_png_end");
|
||||
extern const uint8_t _index_html_gz_start[] asm("_binary_index_html_gz_start");
|
||||
extern const uint8_t _index_html_gz_end[] asm("_binary_index_html_gz_end");
|
||||
extern const uint8_t _index_df6830_bundle_js_gz_start[] asm("_binary_index_df6830_bundle_js_gz_start");
|
||||
extern const uint8_t _index_df6830_bundle_js_gz_end[] asm("_binary_index_df6830_bundle_js_gz_end");
|
||||
extern const uint8_t _node_modules_df6830_bundle_js_gz_start[] asm("_binary_node_modules_df6830_bundle_js_gz_start");
|
||||
extern const uint8_t _node_modules_df6830_bundle_js_gz_end[] asm("_binary_node_modules_df6830_bundle_js_gz_end");
|
||||
extern const uint8_t _runtime_df6830_bundle_js_gz_start[] asm("_binary_runtime_df6830_bundle_js_gz_start");
|
||||
extern const uint8_t _runtime_df6830_bundle_js_gz_end[] asm("_binary_runtime_df6830_bundle_js_gz_end");
|
||||
extern const uint8_t _index_0e064e_bundle_js_gz_start[] asm("_binary_index_0e064e_bundle_js_gz_start");
|
||||
extern const uint8_t _index_0e064e_bundle_js_gz_end[] asm("_binary_index_0e064e_bundle_js_gz_end");
|
||||
extern const uint8_t _node_modules_0e064e_bundle_js_gz_start[] asm("_binary_node_modules_0e064e_bundle_js_gz_start");
|
||||
extern const uint8_t _node_modules_0e064e_bundle_js_gz_end[] asm("_binary_node_modules_0e064e_bundle_js_gz_end");
|
||||
extern const uint8_t _runtime_0e064e_bundle_js_gz_start[] asm("_binary_runtime_0e064e_bundle_js_gz_start");
|
||||
extern const uint8_t _runtime_0e064e_bundle_js_gz_end[] asm("_binary_runtime_0e064e_bundle_js_gz_end");
|
||||
const char * resource_lookups[] = {
|
||||
"/favicon-32x32.png",
|
||||
"/index.html.gz",
|
||||
"/js/index.df6830.bundle.js.gz",
|
||||
"/js/node-modules.df6830.bundle.js.gz",
|
||||
"/js/runtime.df6830.bundle.js.gz",
|
||||
"/js/index.0e064e.bundle.js.gz",
|
||||
"/js/node-modules.0e064e.bundle.js.gz",
|
||||
"/js/runtime.0e064e.bundle.js.gz",
|
||||
""
|
||||
};
|
||||
const uint8_t * resource_map_start[] = {
|
||||
_favicon_32x32_png_start,
|
||||
_index_html_gz_start,
|
||||
_index_df6830_bundle_js_gz_start,
|
||||
_node_modules_df6830_bundle_js_gz_start,
|
||||
_runtime_df6830_bundle_js_gz_start
|
||||
_index_0e064e_bundle_js_gz_start,
|
||||
_node_modules_0e064e_bundle_js_gz_start,
|
||||
_runtime_0e064e_bundle_js_gz_start
|
||||
};
|
||||
const uint8_t * resource_map_end[] = {
|
||||
_favicon_32x32_png_end,
|
||||
_index_html_gz_end,
|
||||
_index_df6830_bundle_js_gz_end,
|
||||
_node_modules_df6830_bundle_js_gz_end,
|
||||
_runtime_df6830_bundle_js_gz_end
|
||||
_index_0e064e_bundle_js_gz_end,
|
||||
_node_modules_0e064e_bundle_js_gz_end,
|
||||
_runtime_0e064e_bundle_js_gz_end
|
||||
};
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
/***********************************
|
||||
webpack_headers
|
||||
Hash: df683065b9a62ef5a0ce
|
||||
Hash: 0e064eadc7c8b7881633
|
||||
Version: webpack 4.46.0
|
||||
Time: 2739ms
|
||||
Built at: 26.04.2021 07:00:49
|
||||
Time: 9582ms
|
||||
Built at: 2021-07-09 11 h 14 min 41 s
|
||||
Asset Size Chunks Chunk Names
|
||||
./js/index.df6830.bundle.js 232 KiB 0 [emitted] [immutable] index
|
||||
./js/index.df6830.bundle.js.br 32.5 KiB [emitted]
|
||||
./js/index.df6830.bundle.js.gz 41.9 KiB [emitted]
|
||||
./js/node-modules.df6830.bundle.js 266 KiB 1 [emitted] [immutable] [big] node-modules
|
||||
./js/node-modules.df6830.bundle.js.br 76.3 KiB [emitted]
|
||||
./js/node-modules.df6830.bundle.js.gz 88.7 KiB [emitted]
|
||||
./js/runtime.df6830.bundle.js 1.46 KiB 2 [emitted] [immutable] runtime
|
||||
./js/runtime.df6830.bundle.js.br 644 bytes [emitted]
|
||||
./js/runtime.df6830.bundle.js.gz 722 bytes [emitted]
|
||||
./js/index.0e064e.bundle.js 232 KiB 0 [emitted] [immutable] index
|
||||
./js/index.0e064e.bundle.js.br 32.7 KiB [emitted]
|
||||
./js/index.0e064e.bundle.js.gz 42 KiB [emitted]
|
||||
./js/node-modules.0e064e.bundle.js 266 KiB 1 [emitted] [immutable] [big] node-modules
|
||||
./js/node-modules.0e064e.bundle.js.br 76.3 KiB [emitted]
|
||||
./js/node-modules.0e064e.bundle.js.gz 88.7 KiB [emitted]
|
||||
./js/runtime.0e064e.bundle.js 1.46 KiB 2 [emitted] [immutable] runtime
|
||||
./js/runtime.0e064e.bundle.js.br 644 bytes [emitted]
|
||||
./js/runtime.0e064e.bundle.js.gz 722 bytes [emitted]
|
||||
favicon-32x32.png 634 bytes [emitted]
|
||||
index.html 21.7 KiB [emitted]
|
||||
index.html.br 4.74 KiB [emitted]
|
||||
index.html.gz 5.75 KiB [emitted]
|
||||
sprite.svg 4.4 KiB [emitted]
|
||||
sprite.svg.br 898 bytes [emitted]
|
||||
Entrypoint index [big] = ./js/runtime.df6830.bundle.js ./js/node-modules.df6830.bundle.js ./js/index.df6830.bundle.js
|
||||
Entrypoint index [big] = ./js/runtime.0e064e.bundle.js ./js/node-modules.0e064e.bundle.js ./js/index.0e064e.bundle.js
|
||||
[6] ./node_modules/bootstrap/dist/js/bootstrap-exposed.js 437 bytes {1} [built]
|
||||
[11] ./src/sass/main.scss 1.55 KiB {0} [built]
|
||||
[16] ./node_modules/remixicon/icons/Device/signal-wifi-fill.svg 323 bytes {1} [built]
|
||||
[17] ./node_modules/remixicon/icons/Device/signal-wifi-3-fill.svg 327 bytes {1} [built]
|
||||
[18] ./node_modules/remixicon/icons/Device/signal-wifi-2-fill.svg 327 bytes {1} [built]
|
||||
[19] ./node_modules/remixicon/icons/Device/signal-wifi-1-fill.svg 327 bytes {1} [built]
|
||||
[20] ./node_modules/remixicon/icons/Device/signal-wifi-line.svg 323 bytes {1} [built]
|
||||
[21] ./node_modules/remixicon/icons/Device/battery-line.svg 315 bytes {1} [built]
|
||||
[22] ./node_modules/remixicon/icons/Device/battery-low-line.svg 323 bytes {1} [built]
|
||||
[23] ./node_modules/remixicon/icons/Device/battery-fill.svg 315 bytes {1} [built]
|
||||
[24] ./node_modules/remixicon/icons/Media/headphone-fill.svg 318 bytes {1} [built]
|
||||
[25] ./node_modules/remixicon/icons/Device/device-recover-fill.svg 329 bytes {1} [built]
|
||||
[26] ./node_modules/remixicon/icons/Device/bluetooth-fill.svg 319 bytes {1} [built]
|
||||
[27] ./node_modules/remixicon/icons/Device/bluetooth-connect-fill.svg 335 bytes {1} [built]
|
||||
[38] ./src/index.ts + 1 modules 62.5 KiB {0} [built]
|
||||
[16] ./node_modules/remixicon/icons/Device/signal-wifi-fill.svg 340 bytes {1} [built]
|
||||
[17] ./node_modules/remixicon/icons/Device/signal-wifi-3-fill.svg 344 bytes {1} [built]
|
||||
[18] ./node_modules/remixicon/icons/Device/signal-wifi-2-fill.svg 344 bytes {1} [built]
|
||||
[19] ./node_modules/remixicon/icons/Device/signal-wifi-1-fill.svg 344 bytes {1} [built]
|
||||
[20] ./node_modules/remixicon/icons/Device/signal-wifi-line.svg 340 bytes {1} [built]
|
||||
[21] ./node_modules/remixicon/icons/Device/battery-line.svg 332 bytes {1} [built]
|
||||
[22] ./node_modules/remixicon/icons/Device/battery-low-line.svg 340 bytes {1} [built]
|
||||
[23] ./node_modules/remixicon/icons/Device/battery-fill.svg 332 bytes {1} [built]
|
||||
[24] ./node_modules/remixicon/icons/Media/headphone-fill.svg 335 bytes {1} [built]
|
||||
[25] ./node_modules/remixicon/icons/Device/device-recover-fill.svg 346 bytes {1} [built]
|
||||
[26] ./node_modules/remixicon/icons/Device/bluetooth-fill.svg 336 bytes {1} [built]
|
||||
[27] ./node_modules/remixicon/icons/Device/bluetooth-connect-fill.svg 352 bytes {1} [built]
|
||||
[38] ./src/index.ts + 1 modules 62.6 KiB {0} [built]
|
||||
| ./src/index.ts 1.4 KiB [built]
|
||||
| ./src/js/custom.js 61 KiB [built]
|
||||
+ 24 hidden modules
|
||||
@@ -43,14 +43,14 @@ Entrypoint index [big] = ./js/runtime.df6830.bundle.js ./js/node-modules.df6830.
|
||||
WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
|
||||
This can impact web performance.
|
||||
Assets:
|
||||
./js/node-modules.df6830.bundle.js (266 KiB)
|
||||
./js/node-modules.0e064e.bundle.js (266 KiB)
|
||||
|
||||
WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
|
||||
Entrypoints:
|
||||
index (499 KiB)
|
||||
./js/runtime.df6830.bundle.js
|
||||
./js/node-modules.df6830.bundle.js
|
||||
./js/index.df6830.bundle.js
|
||||
./js/runtime.0e064e.bundle.js
|
||||
./js/node-modules.0e064e.bundle.js
|
||||
./js/index.0e064e.bundle.js
|
||||
|
||||
|
||||
WARNING in webpack performance recommendations:
|
||||
@@ -58,9 +58,9 @@ You can limit the size of your bundles by using import() or require.ensure to la
|
||||
For more info visit https://webpack.js.org/guides/code-splitting/
|
||||
Child html-webpack-plugin for "index.html":
|
||||
Asset Size Chunks Chunk Names
|
||||
index.html 559 KiB 0
|
||||
index.html 560 KiB 0
|
||||
Entrypoint undefined = index.html
|
||||
[0] ./node_modules/html-webpack-plugin/lib/loader.js!./src/index.ejs 22.9 KiB {0} [built]
|
||||
[0] ./node_modules/html-webpack-plugin/lib/loader.js!./src/index.ejs 23.9 KiB {0} [built]
|
||||
[1] ./node_modules/lodash/lodash.js 531 KiB {0} [built]
|
||||
[2] (webpack)/buildin/global.js 472 bytes {0} [built]
|
||||
[3] (webpack)/buildin/module.js 497 bytes {0} [built]
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
components/wifi-manager/webapp/webpack/dist/js/index.0e064e.bundle.js.br
vendored
Normal file
BIN
components/wifi-manager/webapp/webpack/dist/js/index.0e064e.bundle.js.br
vendored
Normal file
Binary file not shown.
BIN
components/wifi-manager/webapp/webpack/dist/js/index.0e064e.bundle.js.gz
vendored
Normal file
BIN
components/wifi-manager/webapp/webpack/dist/js/index.0e064e.bundle.js.gz
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -367,8 +367,7 @@ module.exports = merge(common, {
|
||||
filename: 'test',
|
||||
minify: false,
|
||||
excludeChunks: ['index'],
|
||||
}),
|
||||
new SpriteLoaderPlugin({plainSprite: true})
|
||||
})
|
||||
|
||||
],
|
||||
});
|
||||
|
||||
@@ -84,7 +84,6 @@ SemaphoreHandle_t wifi_manager_json_mutex = NULL;
|
||||
SemaphoreHandle_t wifi_manager_sta_ip_mutex = NULL;
|
||||
char *wifi_manager_sta_ip = NULL;
|
||||
#define STA_IP_LEN sizeof(char) * IP4ADDR_STRLEN_MAX
|
||||
bool bHasConnected=false;
|
||||
uint16_t ap_num = MAX_AP_NUM;
|
||||
wifi_ap_record_t *accessp_records=NULL;
|
||||
cJSON * accessp_cjson=NULL;
|
||||
@@ -108,6 +107,9 @@ static const char TAG[] = "wifi_manager";
|
||||
/* @brief task handle for the main wifi_manager task */
|
||||
static TaskHandle_t task_wifi_manager = NULL;
|
||||
|
||||
#define STA_POLLING_MIN (15*1000)
|
||||
#define STA_POLLING_MAX (10*60*1000)
|
||||
|
||||
/**
|
||||
* The actual WiFi settings in use
|
||||
*/
|
||||
@@ -266,7 +268,6 @@ void wifi_manager_init_wifi(){
|
||||
/* event handler and event group for the wifi driver */
|
||||
ESP_LOGD(TAG, "Initializing wifi. Creating event group");
|
||||
wifi_manager_event_group = xEventGroupCreate();
|
||||
bHasConnected=false;
|
||||
// Now Initialize the Wifi Stack
|
||||
ESP_LOGD(TAG, "Initializing wifi. Initializing tcp_ip adapter");
|
||||
tcpip_adapter_init();
|
||||
@@ -283,18 +284,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();
|
||||
@@ -315,6 +304,9 @@ static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport) {
|
||||
wifi_manager_update_status();
|
||||
}
|
||||
|
||||
static void polling_STA(void* timer_id) {
|
||||
wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_AUTO_RECONNECT);
|
||||
}
|
||||
|
||||
void wifi_manager_start(){
|
||||
|
||||
@@ -1227,6 +1219,11 @@ void wifi_manager( void * pvParameters ){
|
||||
EventBits_t uxBits;
|
||||
uint8_t retries = 0;
|
||||
esp_err_t err=ESP_OK;
|
||||
TimerHandle_t STA_timer;
|
||||
uint32_t STA_duration = STA_POLLING_MIN;
|
||||
|
||||
/* create timer for background STA connection */
|
||||
STA_timer = xTimerCreate("background STA", pdMS_TO_TICKS(STA_duration), pdFALSE, NULL, polling_STA);
|
||||
|
||||
/* start http server */
|
||||
http_server_start();
|
||||
@@ -1532,23 +1529,38 @@ void wifi_manager( void * pvParameters ){
|
||||
|
||||
if(retries < WIFI_MANAGER_MAX_RETRY){
|
||||
ESP_LOGD(TAG, "Issuing ORDER_CONNECT_STA to retry connection.");
|
||||
if(!bHasConnected) retries++;
|
||||
retries++;
|
||||
wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_AUTO_RECONNECT);
|
||||
}
|
||||
else{
|
||||
/* In this scenario the connection was lost beyond repair: kick start the AP! */
|
||||
retries = 0;
|
||||
wifi_mode_t mode;
|
||||
ESP_LOGW(TAG, "All connect retry attempts failed.");
|
||||
|
||||
|
||||
/* put us in softAP mode first */
|
||||
esp_wifi_get_mode(&mode);
|
||||
/* if it was a restore attempt connection, we clear the bit */
|
||||
xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_RESTORE_STA_BIT);
|
||||
|
||||
ESP_LOGD(TAG, "Issuing ORDER_START_AP to trigger AP start.");
|
||||
/* start SoftAP */
|
||||
wifi_manager_send_message(ORDER_START_AP, NULL);
|
||||
|
||||
if(WIFI_MODE_APSTA != mode){
|
||||
/* call directly config_ap because we don't want to scan so the message has no benefit */
|
||||
ESP_LOGD(TAG, "Starting AP directly.");
|
||||
wifi_manager_config_ap();
|
||||
STA_duration = STA_POLLING_MIN;
|
||||
/* manual callback if needed */
|
||||
if(cb_ptr_arr[ORDER_START_AP]) (*cb_ptr_arr[ORDER_START_AP])(NULL);
|
||||
}
|
||||
else if(STA_duration < STA_POLLING_MAX) {
|
||||
STA_duration *= 1.25;
|
||||
}
|
||||
|
||||
xTimerChangePeriod(STA_timer, pdMS_TO_TICKS(STA_duration), portMAX_DELAY);
|
||||
xTimerStart(STA_timer, portMAX_DELAY);
|
||||
ESP_LOGD(TAG, "STA search slow polling of %d", STA_duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* callback */
|
||||
if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
|
||||
}
|
||||
@@ -1600,7 +1612,9 @@ void wifi_manager( void * pvParameters ){
|
||||
/* bring down DNS hijack */
|
||||
ESP_LOGD(TAG, "Stopping dns server.");
|
||||
dns_server_stop();
|
||||
bHasConnected=true;
|
||||
|
||||
/* stop AP mode */
|
||||
esp_wifi_set_mode(WIFI_MODE_STA);
|
||||
|
||||
/* callback */
|
||||
if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
|
||||
|
||||
@@ -49,49 +49,39 @@ menu "Squeezelite-ESP32"
|
||||
select I2C_LOCKED
|
||||
select LED_LOCKED
|
||||
select SPKFAULT_LOCKED
|
||||
config A1S
|
||||
bool "ESP32-A1S module"
|
||||
select I2C_LOCKED
|
||||
config DAC32
|
||||
bool "DAC32 module"
|
||||
config BASIC_I2C_BT
|
||||
bool "Generic I2S & Bluetooth"
|
||||
config TWATCH2020
|
||||
bool "T-WATCH2020 by LilyGo"
|
||||
select I2C_LOCKED
|
||||
config BASIC_I2C_BT
|
||||
bool "Generic I2S & Bluetooth"
|
||||
endchoice
|
||||
config RELEASE_API
|
||||
string "Software update URL"
|
||||
default "https://api.github.com/repos/sle118/squeezelite-esp32/releases" if !DAC32
|
||||
default "https://yourdomain/api/releases" if DAC32
|
||||
default "https://api.github.com/repos/sle118/squeezelite-esp32/releases"
|
||||
help
|
||||
Set the URL of the API that the front-end UI will use to fetch software updates
|
||||
config SQUEEZELITE_ESP32_RELEASE_URL
|
||||
string "Release URL"
|
||||
default "https://github.com/sle118/squeezelite-esp32/releases" if !DAC32
|
||||
default "https://yourdomain/releases" if DAC32
|
||||
default "https://github.com/sle118/squeezelite-esp32/releases"
|
||||
help
|
||||
Set the URL where users can see a list of releases
|
||||
# you can't change default values once they are set so changing "Target" will not reset
|
||||
# project name if they are visible config - they have to be silent strings
|
||||
config PROJECT_NAME
|
||||
string "Project Name"
|
||||
default "Squeezelite-A1S" if A1S
|
||||
string
|
||||
default "SqueezeAMP" if SQUEEZEAMP
|
||||
default "DAC32" if DAC32
|
||||
default "Squeezelite-TWATCH" if TWATCH2020
|
||||
default "Squeezelite-ESP32" if !A1S && !SQUEEZEAMP && !DAC32 && !TWATCH2020
|
||||
default "Squeezelite-ESP32"
|
||||
config FW_PLATFORM_NAME
|
||||
string "Hardware Platform Name"
|
||||
string
|
||||
default "SqueezeAmp" if SQUEEZEAMP
|
||||
default "DAC32" if DAC32
|
||||
default "ESP32-A1S" if A1S
|
||||
default "TWATCH" if TWATCH2020
|
||||
default "I2S-4MFlash" if !A1S && !SQUEEZEAMP && !DAC32 && !TWATCH2020
|
||||
default "ESP32"
|
||||
# AGGREGATES - begin
|
||||
# these parameters are "aggregates" that take precedence. They must have a default value
|
||||
config DAC_CONFIG
|
||||
string
|
||||
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=I2S,bck=26,ws=25,do=33,i2c=53,sda=21,scl=22" if TWATCH2020
|
||||
default ""
|
||||
config SPDIF_CONFIG
|
||||
@@ -138,7 +128,7 @@ menu "Squeezelite-ESP32"
|
||||
I2S data output gpio pin to use.
|
||||
config I2S_DI_IO
|
||||
int "I2S Data Input GPIO number. "
|
||||
default -1 if !A1S
|
||||
default -1
|
||||
help
|
||||
I2S data input gpio pin to use (not used mostly, leave it to -1).
|
||||
endmenu
|
||||
@@ -188,16 +178,7 @@ menu "Squeezelite-ESP32"
|
||||
help
|
||||
I2S data output IO use to simulate SPDIF
|
||||
endmenu
|
||||
|
||||
menu "SPDIF settings"
|
||||
visible if A1S
|
||||
config SPDIF_DO_IO
|
||||
int "SPDIF Data I/O GPIO number"
|
||||
default -1
|
||||
help
|
||||
I2S data output IO use to simulate SPDIF
|
||||
endmenu
|
||||
|
||||
|
||||
menu "A2DP settings"
|
||||
config A2DP_SINK_NAME
|
||||
string "Name of Bluetooth A2DP device"
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user