mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-14 23:47:02 +03:00
Compare commits
33 Commits
I2S-4MFlas
...
misc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c36348e99d | ||
|
|
faa9976d3d | ||
|
|
1dbffe6753 | ||
|
|
8e5dbd2144 | ||
|
|
974ff5fa68 | ||
|
|
4dce4b307b | ||
|
|
4aa54537e5 | ||
|
|
d27a430664 | ||
|
|
0fa41e5ef7 | ||
|
|
2146014f04 | ||
|
|
7d409668c8 | ||
|
|
0ebce7472b | ||
|
|
5f5466fcb0 | ||
|
|
71911914cb | ||
|
|
4f6dcc2cc7 | ||
|
|
f4615462c7 | ||
|
|
6033c7fc14 | ||
|
|
a98b1d00b0 | ||
|
|
1e45348e4a | ||
|
|
96a05d8a6b | ||
|
|
7a9f3e0781 | ||
|
|
3575245324 | ||
|
|
c36d663a7f | ||
|
|
13294ddd0c | ||
|
|
449ef32a4e | ||
|
|
50390dbc61 | ||
|
|
fc5f3f5ac9 | ||
|
|
6f4ed0679e | ||
|
|
511df0b4b8 | ||
|
|
6682ee947e | ||
|
|
813e7ee712 | ||
|
|
6c9537e259 | ||
|
|
ac9ad2eee2 |
59
README.md
59
README.md
@@ -14,6 +14,7 @@ But squeezelite-esp32 is highly extensible and you can add
|
||||
- Buttons and Rotary Encoder and map/combine them to various functions (play, pause, volume, next ...)
|
||||
- IR receiver (no pullup resistor or capacitor needed, just the 38kHz receiver)
|
||||
- Monochrome, GrayScale or Color displays using SPI or I2C (supported drivers are SH1106, SSD1306, SSD1322, SSD1326/7, SSD1351, ST7735, ST7789 and ILI9341).
|
||||
- Ethernet using a Microchip LAN8720 with RMII interface or Davicom DM9051 over SPI.
|
||||
|
||||
Other features include
|
||||
|
||||
@@ -23,7 +24,7 @@ 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 can be found [here]( https://raw.githubusercontent.com/sle118/squeezelite-esp32/master/plugin/repo.xml)
|
||||
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)*
|
||||
@@ -135,18 +136,19 @@ sda=<gpio>,scl=<gpio>[,port=0|1][,speed=<speed>]
|
||||
```
|
||||
<strong>Please note that you can not use the same GPIO or port as the DAC</strong>
|
||||
### SPI
|
||||
The NVS parameter "spi_config" set the spi's gpio used for generic purpose (e.g. display). Leave it blank to disable SPI usage. The DC parameter is needed for displays. Syntax is
|
||||
The esp32 has 4 SPI sub-systems, one is unaccessible so numbering is 0..2 and SPI0 is reserved for Flash/PSRAM. The NVS parameter "spi_config" set the spi's gpio used for generic purpose (e.g. display). Leave it blank to disable SPI usage. The DC parameter is needed for displays. Syntax is
|
||||
```
|
||||
data=<gpio>,clk=<gpio>[,dc=<gpio>][,host=1|2]
|
||||
data|mosi=<gpio>,clk=<gpio>[,dc=<gpio>][,host=1|2][,miso=<gpio>]
|
||||
```
|
||||
Default "host" is 1. The "miso" parameter is only used when SPI bus is to be shared with other peripheral (e.g. ethernet, see below), otherwise it can be omitted. Note that "data" can also be named "mosi".
|
||||
### 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>[,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 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.
|
||||
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 and be aware that this cannot coexit with RMII Ethernet (see ethernet section below). I2C parameters are optional and 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:
|
||||
So far, TAS57xx, TAS5713, AC101, WM8978 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"} ],
|
||||
@@ -243,6 +245,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 +276,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
|
||||
```
|
||||
@@ -366,11 +370,52 @@ 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**
|
||||
### Ethernet (coming soon)
|
||||
Wired ethernet is supported by esp32 with various options but squeezelite is only supporting a Microchip LAN8720 with a RMII interface like [this](https://www.aliexpress.com/item/32858432526.html) or Davicom DM9051 over SPI like [that](https://www.amazon.com/dp/B08JLFWX9Z).
|
||||
|
||||
#### RMII (LAN8720)
|
||||
- RMII PHY wiring is fixed and can not be changed
|
||||
|
||||
| GPIO | RMII Signal | Notes |
|
||||
| ------ | ----------- | ------------ |
|
||||
| GPIO21 | TX_EN | EMAC_TX_EN |
|
||||
| GPIO19 | TX0 | EMAC_TXD0 |
|
||||
| GPIO22 | TX1 | EMAC_TXD1 |
|
||||
| GPIO25 | RX0 | EMAC_RXD0 |
|
||||
| GPIO26 | RX1 | EMAC_RXD1 |
|
||||
| GPIO27 | CRS_DV | EMAC_RX_DRV |
|
||||
|
||||
- SMI (Serial Management Interface) wiring is not fixed and you can change it either in the configuration or using "eth_config" parameter with the following syntax:
|
||||
```
|
||||
model=lan8720,mdc=<gpio>,mdio=<gpio>[,rst=<gpio>]
|
||||
```
|
||||
Connecting a reset pin for the LAN8720 is optional but recommended to avoid that GPIO0 (50MHz input clock) locks the esp32 in download mode at boot time.
|
||||
- Clock
|
||||
|
||||
The APLL of the esp32 is required for the audio codec, so we **need** a LAN8720 that provides a 50MHz clock. That clock **must** be connected to GPIO0, there is no alternative. This means that if your DAC requires an MCLK, then you are out of luck. It is not possible to have both to work together. There might be some workaround using CLK_OUT2 and GPIO3, but I don't have time for this.
|
||||
#### SPI (DM9051)
|
||||
Ethernet over SPI is supported as well and requires less GPIOs but is obvsiously slower. Another benefit is that the SPI bus can be shared with the display, but it's also possible to have a dedicated SPI interface. The esp32 has 4 SPI sub-systems, one is unaccessible so numbering is 0..2 and SPI0 is reserved for Flash/PSRAM. The "eth_config" parameter syntax becomes:
|
||||
```
|
||||
model=dm9051,cs=<gpio>,speed=<clk_in_Hz>,intr=<gpio>[,host=<-1|1|2>][,rst=<gpio>][,mosi=<gpio>,miso=<gpio>,clk=<gpio>]
|
||||
```
|
||||
- To use the system SPI, shared with display (see spi_config) "host" must be set to -1. Any other value will reserve the SPI interface (careful of conflict with spi_config). The default "host" is 2 to avoid conflicting wiht default "spi_config" settings.
|
||||
- When not using system SPI, "mosi" for data out, "miso" for data in and "clk" **must** be set
|
||||
- The esp32 has a special I/O multiplexer for faster speed (up to 80 MHz) but that requires using specific GPIOs, which depends on SPI bus (See [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_master.html) for more details)
|
||||
|
||||
| Pin Name | SPI2 | SPI3 |
|
||||
| -------- | ---- | ---- |
|
||||
| CS0* | 15 | 5 |
|
||||
| SCLK | 14 | 18 |
|
||||
| MISO | 12 | 19 |
|
||||
| MOSI | 13 | 23 |
|
||||
|
||||
** THIS IS NOT AVAILABLE YET, SO MORE TO COME ON HOW TO USE WIRED ETHERNET***
|
||||
### 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
|
||||
```
|
||||
channel=0..7,scale=<scale>,cells=<2|3>,[atten=<0|1|2|3>]
|
||||
channel=0..7,scale=<scale>,cells=<2|3>[,atten=<0|1|2|3>]
|
||||
```
|
||||
NB: Set parameter to empty to disable battery reading. For well-known configuration, this is ignored (except for SqueezeAMP where number of cells is required)
|
||||
# Configuration
|
||||
@@ -476,7 +521,7 @@ If you have already cloned the repository and you are getting compile errors on
|
||||
- per mad & few others, edit configure and change $ac_link to add -c (faking link)
|
||||
- change ac_files to remove ''
|
||||
- add DEPS_CFLAGS and DEPS_LIBS to avoid pkg-config to be required
|
||||
- stack consumption can be very high with some codec variants, so set NONTHREADSAFE_PSEUDOSTACK and GLOBAL_STACK_SIZE=32000 and unset VAR_ARRAYS in config.h
|
||||
- stack consumption can be very high with some codec variants, so set NONTHREADSAFE_PSEUDOSTACK and GLOBAL_STACK_SIZE=48000 and unset VAR_ARRAYS in config.h
|
||||
- libmad has been patched to avoid using a lot of stack and is not provided here. There is an issue with sync detection in 1.15.1b from where the original stack patch was done but since a few fixes have been made wrt sync detection. This 1.15.1b-10 found on debian fixes the issue where mad thinks it has reached sync but has not and so returns a wrong sample rate. It comes at the expense of 8KB (!) of code where a simple check in squeezelite/mad.c that next_frame[0] is 0xff and next_frame[1] & 0xf0 is 0xf0 does the trick ...
|
||||
|
||||
# Footnotes
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
idf_component_register(
|
||||
INCLUDE_DIRS . ./inc inc/alac inc/FLAC inc/helix-aac inc/mad inc/ogg inc/opus inc/opusfile inc/resample16 inc/soxr inc/vorbis
|
||||
INCLUDE_DIRS . ./inc inc/alac inc/FLAC inc/helix-aac inc/mad inc/ogg inc/opus inc/opusfile inc/resample16 inc/soxr inc/vorbis
|
||||
)
|
||||
|
||||
if (DEFINED AAC_DISABLE_SBR)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
idf_component_register( SRC_DIRS .
|
||||
INCLUDE_DIRS .
|
||||
PRIV_REQUIRES tools newlib console esp_common freertos
|
||||
PRIV_REQUIRES tools newlib console esp_common freertos
|
||||
REQUIRES nvs_flash json
|
||||
)
|
||||
|
||||
|
||||
@@ -611,6 +611,7 @@ static int do_i2s_cmd(int argc, char **argv)
|
||||
}
|
||||
if(i2s_args.model_name->count>0 && strlen(i2s_args.model_name->sval[0])>0){
|
||||
strncpy(i2s_dac_pin.model,i2s_args.model_name->sval[0],sizeof(i2s_dac_pin.model));
|
||||
i2s_dac_pin.model[sizeof(i2s_dac_pin.model) - 1] = '\0';
|
||||
}
|
||||
if(!nerrors ){
|
||||
fprintf(f,"Storing i2s parameters.\n");
|
||||
|
||||
@@ -76,6 +76,7 @@ static struct {
|
||||
|
||||
static struct {
|
||||
struct arg_int *data;
|
||||
struct arg_int *miso;
|
||||
struct arg_int *clk;
|
||||
struct arg_int *dc;
|
||||
struct arg_int *host;
|
||||
@@ -453,6 +454,7 @@ static int do_spiconfig_cmd(int argc, char **argv){
|
||||
/* Check "--clk" option */
|
||||
nerrors+=is_output_gpio(spiconfig_args.clk, f, &spi_config.sclk_io_num, true);
|
||||
nerrors+=is_output_gpio(spiconfig_args.data, f, &spi_config.mosi_io_num, true);
|
||||
nerrors+=is_output_gpio(spiconfig_args.miso, f, &spi_config.miso_io_num, true);
|
||||
nerrors+=is_output_gpio(spiconfig_args.dc, f, &dc, true);
|
||||
nerrors+=is_output_gpio(spiconfig_args.host, f, &host, true);
|
||||
|
||||
@@ -1030,7 +1032,8 @@ static void register_spiconfig(void)
|
||||
{
|
||||
spiconfig_args.clear = arg_lit0(NULL, "clear", "Clear configuration");
|
||||
spiconfig_args.clk = arg_int0("k", "clk", "<n>", "Clock GPIO");
|
||||
spiconfig_args.data = arg_int0("d","data", "<n>","Data GPIO");
|
||||
spiconfig_args.data = arg_int0("d","data", "<n>","Data OUT GPIO");
|
||||
spiconfig_args.miso = arg_int0("d","miso", "<n>","Data IN GPIO");
|
||||
spiconfig_args.dc = arg_int0("c","dc", "<n>", "DC GPIO");
|
||||
spiconfig_args.host= arg_int0("h", "host", "1|2", "SPI Host Number");
|
||||
spiconfig_args.end = arg_end(4);
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -117,8 +117,10 @@ static bool wifi_join(const char *ssid, const char *pass, int timeout_ms)
|
||||
initialise_wifi();
|
||||
wifi_config_t wifi_config = { 0 };
|
||||
strncpy((char *) wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
|
||||
wifi_config.sta.ssid[sizeof(wifi_config.sta.ssid) - 1] = '\0';
|
||||
if (pass) {
|
||||
strncpy((char *) wifi_config.sta.password, pass, sizeof(wifi_config.sta.password));
|
||||
wifi_config.sta.password[sizeof(wifi_config.sta.password) - 1] = '\0';
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
|
||||
|
||||
@@ -25,6 +25,11 @@
|
||||
#define CONFIG_AIRPLAY_NAME "ESP32-AirPlay"
|
||||
#endif
|
||||
|
||||
static EXT_RAM_ATTR struct raop_cb_s {
|
||||
raop_cmd_vcb_t cmd;
|
||||
raop_data_cb_t data;
|
||||
} raop_cbs;
|
||||
|
||||
log_level raop_loglevel = lINFO;
|
||||
log_level util_loglevel;
|
||||
|
||||
@@ -88,7 +93,7 @@ const static actrls_t controls = {
|
||||
NULL, NULL, // rew, fwd
|
||||
raop_prev, raop_next, // prev, next
|
||||
NULL, NULL, NULL, NULL, // left, right, up, down
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, // pre1-6
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, // pre1-6
|
||||
raop_volume_down, raop_volume_up, raop_toggle// knob left, knob_right, knob push
|
||||
};
|
||||
|
||||
@@ -150,17 +155,27 @@ void raop_sink_deinit(void) {
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Airplay sink initialization
|
||||
* Airplay sink startup
|
||||
*/
|
||||
void raop_sink_init(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb) {
|
||||
const char *hostname;
|
||||
static bool raop_sink_start(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb) {
|
||||
const char *hostname = NULL;
|
||||
char sink_name[64-6] = CONFIG_AIRPLAY_NAME;
|
||||
tcpip_adapter_ip_info_t ipInfo;
|
||||
tcpip_adapter_ip_info_t ipInfo = { };
|
||||
struct in_addr host;
|
||||
tcpip_adapter_if_t ifs[] = { TCPIP_ADAPTER_IF_ETH, TCPIP_ADAPTER_IF_STA, TCPIP_ADAPTER_IF_AP };
|
||||
|
||||
// get various IP info
|
||||
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo);
|
||||
tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &hostname);
|
||||
for (int i = 0; i < sizeof(ifs) / sizeof(tcpip_adapter_if_t); i++)
|
||||
if (tcpip_adapter_get_ip_info(ifs[i], &ipInfo) == ESP_OK && ipInfo.ip.addr != IPADDR_ANY) {
|
||||
tcpip_adapter_get_hostname(ifs[i], &hostname);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hostname) {
|
||||
LOG_INFO( "no hostname/IP found, can't start AirPlay");
|
||||
return false;
|
||||
}
|
||||
|
||||
host.s_addr = ipInfo.ip.addr;
|
||||
|
||||
// initialize mDNS
|
||||
@@ -168,7 +183,7 @@ void raop_sink_init(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb) {
|
||||
ESP_ERROR_CHECK( mdns_hostname_set(hostname) );
|
||||
|
||||
char * sink_name_buffer= (char *)config_alloc_get(NVS_TYPE_STR,"airplay_name");
|
||||
if(sink_name_buffer != NULL){
|
||||
if (sink_name_buffer != NULL){
|
||||
memset(sink_name, 0x00, sizeof(sink_name));
|
||||
strncpy(sink_name,sink_name_buffer,sizeof(sink_name)-1 );
|
||||
free(sink_name_buffer);
|
||||
@@ -181,6 +196,30 @@ void raop_sink_init(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb) {
|
||||
esp_read_mac(mac, ESP_MAC_WIFI_STA);
|
||||
cmd_handler_chain = cmd_cb;
|
||||
raop = raop_create(host, sink_name, mac, 0, cmd_handler, data_cb);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Airplay sink timer handler
|
||||
*/
|
||||
static void raop_start_handler( TimerHandle_t xTimer ) {
|
||||
if (raop_sink_start(raop_cbs.cmd, raop_cbs.data)) {
|
||||
xTimerDelete(xTimer, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Airplay sink initialization
|
||||
*/
|
||||
void raop_sink_init(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb) {
|
||||
if (!raop_sink_start(cmd_cb, data_cb)) {
|
||||
raop_cbs.cmd = cmd_cb;
|
||||
raop_cbs.data = data_cb;
|
||||
TimerHandle_t timer = xTimerCreate("raopStart", 5000 / portTICK_RATE_MS, pdTRUE, NULL, raop_start_handler);
|
||||
xTimerStart(timer, portMAX_DELAY);
|
||||
LOG_INFO( "Delaying AirPlay start");
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
|
||||
@@ -118,7 +118,7 @@ static void set_i2s_pin(char *config, i2s_pin_config_t *pin_config) {
|
||||
* Get i2s config structure from config string
|
||||
*/
|
||||
const i2s_platform_config_t * config_get_i2s_from_str(char * dac_config ){
|
||||
static i2s_platform_config_t i2s_dac_pin = {
|
||||
static EXT_RAM_ATTR i2s_platform_config_t i2s_dac_pin = {
|
||||
.i2c_addr = -1,
|
||||
.sda= -1,
|
||||
.scl = -1,
|
||||
@@ -142,12 +142,39 @@ const i2s_platform_config_t * config_get_i2s_from_str(char * dac_config ){
|
||||
return &i2s_dac_pin;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Get eth config structure from config string
|
||||
*/
|
||||
const eth_config_t * config_get_eth_from_str(char * eth_config ){
|
||||
static EXT_RAM_ATTR eth_config_t eth_pin = {
|
||||
.rmii = false,
|
||||
.model = "",
|
||||
};
|
||||
char * p=NULL;
|
||||
|
||||
if ((p = strcasestr(eth_config, "model")) != NULL) sscanf(p, "%*[^=]=%15[^,]", eth_pin.model);
|
||||
if ((p = strcasestr(eth_config, "mdc")) != NULL) eth_pin.mdc = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(eth_config, "mdio")) != NULL) eth_pin.mdio = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(eth_config, "rst")) != NULL) eth_pin.rst = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(eth_config, "mosi")) != NULL) eth_pin.mosi = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(eth_config, "miso")) != NULL) eth_pin.miso = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(eth_config, "intr")) != NULL) eth_pin.intr = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(eth_config, "cs")) != NULL) eth_pin.cs = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(eth_config, "speed")) != NULL) eth_pin.speed = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(eth_config, "clk")) != NULL) eth_pin.clk = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(eth_config, "host")) != NULL) eth_pin.host = atoi(strchr(p, '=') + 1);
|
||||
|
||||
if (strcasestr(eth_pin.model, "lan8720")) eth_pin.rmii = true;
|
||||
|
||||
return ð_pin;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Get spdif config structure
|
||||
*/
|
||||
const i2s_platform_config_t * config_spdif_get( ){
|
||||
char * spdif_config = config_spdif_get_string();
|
||||
static i2s_platform_config_t i2s_dac_config;
|
||||
static EXT_RAM_ATTR i2s_platform_config_t i2s_dac_config;
|
||||
memcpy(&i2s_dac_config, config_get_i2s_from_str(spdif_config), sizeof(i2s_dac_config));
|
||||
free(spdif_config);
|
||||
return &i2s_dac_config;
|
||||
@@ -158,12 +185,34 @@ const i2s_platform_config_t * config_spdif_get( ){
|
||||
*/
|
||||
const i2s_platform_config_t * config_dac_get(){
|
||||
char * spdif_config = get_dac_config_string();
|
||||
static i2s_platform_config_t i2s_dac_config;
|
||||
static EXT_RAM_ATTR i2s_platform_config_t i2s_dac_config;
|
||||
memcpy(&i2s_dac_config, config_get_i2s_from_str(spdif_config), sizeof(i2s_dac_config));
|
||||
free(spdif_config);
|
||||
return &i2s_dac_config;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Get ethernet config structure
|
||||
*/
|
||||
const eth_config_t * config_eth_get( ){
|
||||
char * config = config_alloc_get_str("eth_config", CONFIG_ETH_CONFIG, "rst=" STR(CONFIG_ETH_PHY_RST_IO)
|
||||
#if defined(CONFIG_ETH_LAN8720)
|
||||
",model=lan8720"
|
||||
#elif defined(CONFIG_ETH_DM9051)
|
||||
",model=dm9051"
|
||||
#endif
|
||||
",mdc=" STR(CONFIG_ETH_MDC_IO) ",mdio=" STR(CONFIG_ETH_MDIO_IO)
|
||||
",host=" STR(CONFIG_ETH_SPI_HOST) ",cs=" STR(CONFIG_ETH_SPI_CS_IO)
|
||||
",mosi=" STR(CONFIG_ETH_SPI_MOSI_IO) ",miso=" STR(CONFIG_ETH_SPI_MISO_IO)
|
||||
",intr=" STR(CONFIG_ETH_SPI_INTR_IO)
|
||||
",clk=" STR(CONFIG_ETH_SPI_CLK_IO) ",speed=" STR(CONFIG_ETH_SPI_SPEED) );
|
||||
static EXT_RAM_ATTR eth_config_t eth_config;
|
||||
ESP_LOGD(TAG, "Ethernet config string %s", config);
|
||||
memcpy(ð_config, config_get_eth_from_str(config), sizeof(eth_config));
|
||||
free(config);
|
||||
return ð_config;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
@@ -342,7 +391,7 @@ esp_err_t config_spi_set(const spi_bus_config_t * config, int host, int dc){
|
||||
esp_err_t err = ESP_OK;
|
||||
char * config_buffer=calloc(buffer_size,1);
|
||||
if(config_buffer) {
|
||||
snprintf(config_buffer,buffer_size,"data=%u,clk=%u,dc=%u,host=%u",config->mosi_io_num,config->sclk_io_num,dc,host);
|
||||
snprintf(config_buffer,buffer_size,"data=%u,clk=%u,dc=%u,host=%u,miso=%d",config->mosi_io_num,config->sclk_io_num,dc,host,config->miso_io_num);
|
||||
log_send_messaging(MESSAGING_INFO,"Updating SPI configuration to %s",config_buffer);
|
||||
err = config_set_value(NVS_TYPE_STR, "spi_config", config_buffer);
|
||||
if(err!=ESP_OK){
|
||||
@@ -512,7 +561,7 @@ const set_GPIO_struct_t * get_gpio_struct(){
|
||||
*/
|
||||
const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host) {
|
||||
char *nvs_item, *p;
|
||||
static spi_bus_config_t spi = {
|
||||
static EXT_RAM_ATTR spi_bus_config_t spi = {
|
||||
.mosi_io_num = -1,
|
||||
.sclk_io_num = -1,
|
||||
.miso_io_num = -1,
|
||||
@@ -523,6 +572,8 @@ const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host) {
|
||||
nvs_item = config_alloc_get_str("spi_config", CONFIG_SPI_CONFIG, NULL);
|
||||
if (nvs_item) {
|
||||
if ((p = strcasestr(nvs_item, "data")) != NULL) spi.mosi_io_num = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(nvs_item, "mosi")) != NULL) spi.mosi_io_num = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(nvs_item, "miso")) != NULL) spi.miso_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, "dc")) != NULL) spi_system_dc_gpio = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(nvs_item, "host")) != NULL) spi_system_host = atoi(strchr(p, '=') + 1);
|
||||
|
||||
@@ -30,6 +30,16 @@ typedef struct {
|
||||
bool rotate;
|
||||
} display_config_t;
|
||||
|
||||
typedef struct {
|
||||
bool rmii;
|
||||
char model[16];
|
||||
int rst;
|
||||
int mdc, mdio;
|
||||
int host;
|
||||
int cs, mosi, miso, intr, clk;
|
||||
int speed;
|
||||
} eth_config_t;
|
||||
|
||||
typedef struct {
|
||||
i2s_pin_config_t pin;
|
||||
char model[32];
|
||||
@@ -75,6 +85,7 @@ typedef struct {
|
||||
} gpio_entry_t;
|
||||
|
||||
const display_config_t * config_display_get();
|
||||
const eth_config_t * config_eth_get( );
|
||||
esp_err_t config_display_set(const display_config_t * config);
|
||||
esp_err_t config_i2c_set(const i2c_config_t * config, int port);
|
||||
esp_err_t config_i2s_set(const i2s_platform_config_t * config, const char * nvs_name);
|
||||
|
||||
@@ -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,7 +47,15 @@ static EXT_RAM_ATTR struct button_s {
|
||||
TimerHandle_t timer;
|
||||
} buttons[MAX_BUTTONS];
|
||||
|
||||
// can't use EXT_RAM_ATTR for initialized structure
|
||||
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 EXT_RAM_ATTR struct {
|
||||
QueueHandle_t queue;
|
||||
void *client;
|
||||
rotary_encoder_info_t info;
|
||||
@@ -57,7 +63,7 @@ static struct {
|
||||
rotary_handler handler;
|
||||
} rotary;
|
||||
|
||||
static struct {
|
||||
static EXT_RAM_ATTR struct {
|
||||
RingbufHandle_t rb;
|
||||
infrared_handler handler;
|
||||
} infrared;
|
||||
@@ -117,6 +123,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 +274,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 +374,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 +386,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;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
static const char *TAG = "led";
|
||||
|
||||
static struct led_s {
|
||||
static EXT_RAM_ATTR struct led_s {
|
||||
gpio_num_t gpio;
|
||||
bool on;
|
||||
int onstate;
|
||||
@@ -40,7 +40,7 @@ static struct led_s {
|
||||
TimerHandle_t timer;
|
||||
} leds[MAX_LED];
|
||||
|
||||
static struct {
|
||||
static EXT_RAM_ATTR struct {
|
||||
int gpio;
|
||||
int active;
|
||||
int pwm;
|
||||
|
||||
@@ -218,7 +218,6 @@ static void notify(in_addr_t ip, u16_t hport, u16_t cport) {
|
||||
|
||||
// close existing CLI connection and open new one
|
||||
if (cli_sock >= 0) closesocket(cli_sock);
|
||||
cli_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
connect_cli_socket();
|
||||
|
||||
LOG_INFO("notified server %s hport %hu cport %hu", inet_ntoa(ip), hport, cport);
|
||||
|
||||
@@ -244,8 +244,7 @@ static void visu_handler(u8_t *data, int len);
|
||||
static void dmxt_handler(u8_t *data, int len);
|
||||
static void displayer_task(void* arg);
|
||||
|
||||
// PLACEHOLDER
|
||||
void *led_display = 0x1000;
|
||||
void *led_display;
|
||||
|
||||
/* scrolling undocumented information
|
||||
grfs
|
||||
@@ -537,7 +536,8 @@ static void show_display_buffer(char *ddram) {
|
||||
char *line2;
|
||||
|
||||
memset(line1, 0, LINELEN+1);
|
||||
strncpy(line1, ddram, LINELEN);
|
||||
strncpy(line1, ddram, LINELEN+1);
|
||||
line1[LINELEN] = '\0';
|
||||
line2 = &(ddram[LINELEN]);
|
||||
line2[LINELEN] = '\0';
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -76,24 +76,7 @@ static esp_err_t _httpd_server_init(struct httpd_data *hd)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int ctrl_fd = cs_create_ctrl_sock(hd->config.ctrl_port);
|
||||
if (ctrl_fd < 0) {
|
||||
ESP_LOGE(TAG, LOG_FMT("error in creating ctrl socket (%d)"), errno);
|
||||
close(fd);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int msg_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (msg_fd < 0) {
|
||||
ESP_LOGE(TAG, LOG_FMT("error in creating msg socket (%d)"), errno);
|
||||
close(fd);
|
||||
close(ctrl_fd);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
hd->listen_fd = fd;
|
||||
hd->ctrl_fd = ctrl_fd;
|
||||
hd->msg_fd = msg_fd;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -198,14 +181,6 @@ static esp_err_t _httpd_server(struct httpd_data *hd)
|
||||
}
|
||||
|
||||
/* Case0: Do we have a control message? */
|
||||
if (FD_ISSET(hd->ctrl_fd, &read_set)) {
|
||||
ESP_LOGD(TAG, LOG_FMT("processing ctrl message"));
|
||||
_httpd_process_ctrl_msg(hd);
|
||||
if (hd->hd_td.status == THREAD_STOPPING) {
|
||||
ESP_LOGD(TAG, LOG_FMT("stopping thread"));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Case1: Do we have any activity on the current data
|
||||
* sessions? */
|
||||
@@ -259,8 +234,6 @@ static void _httpd_thread(void *arg)
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, LOG_FMT("web server exiting"));
|
||||
close(hd->msg_fd);
|
||||
cs_free_ctrl_sock(hd->ctrl_fd);
|
||||
_httpd_close_all_sessions(hd);
|
||||
close(hd->listen_fd);
|
||||
hd->hd_td.status = THREAD_STOPPED;
|
||||
|
||||
@@ -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();
|
||||
@@ -303,6 +292,7 @@ void wifi_manager_init_wifi(){
|
||||
|
||||
void set_lms_server_details(in_addr_t ip, u16_t hport, u16_t cport){
|
||||
strncpy(lms_server_ip,inet_ntoa(ip),sizeof(lms_server_ip));
|
||||
lms_server_ip[sizeof(lms_server_ip)-1]='\0';
|
||||
ESP_LOGI(TAG,"LMS IP: %s, hport: %d, cport: %d",lms_server_ip, hport, cport);
|
||||
lms_server_port = hport;
|
||||
lms_server_cport = cport;
|
||||
@@ -315,6 +305,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 +1220,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 +1530,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 +1613,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);
|
||||
|
||||
@@ -96,12 +96,70 @@ menu "Squeezelite-ESP32"
|
||||
string
|
||||
default "SPI,driver=ST7789,width=240,height=240,cs=5,back=12,speed=16000000,HFlip,VFlip" if TWATCH2020
|
||||
default ""
|
||||
config ETH_CONFIG
|
||||
string
|
||||
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
|
||||
endmenu
|
||||
|
||||
menu "Ethernet Options"
|
||||
visible if BASIC_I2C_BT && (ETH_USE_ESP32_EMAC || ETH_USE_SPI_ETHERNET)
|
||||
choice
|
||||
prompt "Ethernet Chipset"
|
||||
default ETH_NODRIVER
|
||||
config ETH_NODRIVER
|
||||
bool "Defined in NVS"
|
||||
config ETH_LAN8720
|
||||
bool "Microchip LAN8720 (RMII)"
|
||||
config ETH_DM9051
|
||||
bool "Davicom 9051 (SPI)"
|
||||
endchoice
|
||||
config ETH_PHY_RST_IO
|
||||
int "PHY Reset GPIO number" if !ETH_NODRIVER
|
||||
default -1
|
||||
help
|
||||
Set the GPIO number used to reset PHY chip.
|
||||
Set to -1 to disable PHY chip hardware reset.
|
||||
config ETH_MDC_IO
|
||||
int "SMI MDC GPIO number" if ETH_LAN8720
|
||||
default -1
|
||||
help
|
||||
Set the GPIO number used by SMI MDC.
|
||||
config ETH_MDIO_IO
|
||||
int "SMI MDIO GPIO number" if ETH_LAN8720
|
||||
default -1
|
||||
help
|
||||
Set the GPIO number used by SMI MDIO.
|
||||
config ETH_SPI_HOST
|
||||
int "SPI host number (-1,1 or 2)" if ETH_DM9051
|
||||
default -1
|
||||
help
|
||||
Set to -1 to use system's SPI config (see Various I/O)
|
||||
Set to 2 or 3 to use a dedicated bus
|
||||
config ETH_SPI_INTR_IO
|
||||
int "interrupt" if ETH_DM9051
|
||||
default -1
|
||||
config ETH_SPI_CS_IO
|
||||
int "Chip Select" if ETH_DM9051
|
||||
default -1
|
||||
config ETH_SPI_CLK_IO
|
||||
int "SPI clock" if ETH_SPI_HOST != -1 && ETH_DM9051
|
||||
default -1
|
||||
config ETH_SPI_MOSI_IO
|
||||
int "Data Out" if ETH_SPI_HOST != -1 && ETH_DM9051
|
||||
default -1
|
||||
config ETH_SPI_MISO_IO
|
||||
int "Data In" if ETH_SPI_HOST != -1 && ETH_DM9051
|
||||
default -1
|
||||
config ETH_SPI_SPEED
|
||||
int "SPI speed (Hz)" if ETH_SPI_HOST != -1 && ETH_DM9051
|
||||
default 20000000
|
||||
endmenu
|
||||
|
||||
menu "Audio settings"
|
||||
menu "DAC settings"
|
||||
visible if BASIC_I2C_BT
|
||||
|
||||
@@ -366,6 +366,9 @@ void register_default_nvs(){
|
||||
ESP_LOGD(TAG,"Registering default value for key %s, value %s", "display_config", CONFIG_DISPLAY_CONFIG);
|
||||
config_set_default(NVS_TYPE_STR, "display_config", CONFIG_DISPLAY_CONFIG, 0);
|
||||
|
||||
ESP_LOGD(TAG,"Registering default value for key %s, value %s", "eth_config", CONFIG_ETH_CONFIG);
|
||||
config_set_default(NVS_TYPE_STR, "eth_config", CONFIG_ETH_CONFIG, 0);
|
||||
|
||||
ESP_LOGD(TAG,"Registering default value for key %s, value %s", "i2c_config", CONFIG_I2C_CONFIG);
|
||||
config_set_default(NVS_TYPE_STR, "i2c_config", CONFIG_I2C_CONFIG, 0);
|
||||
|
||||
|
||||
@@ -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