diff --git a/README.md b/README.md index 2ec0cc2..f9779a4 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ - [Software dependencies](#dependencies) - [Hardware setup](#hardware-setup) - [Quick start](#quick-start) +- [Detailed start](https://github.com/e2002/yoradio/wiki/How-to-flash) - [Update](#update) - [Update over web-interface](#update-over-web-interface) - [Controls](Controls.md) @@ -63,17 +64,19 @@ https://www.aliexpress.com/item/33009687492.html --- ## Connection tables -| SPI Display | ESP-32 | options.h | +##### SPI Displays +| Display | ESP-32 | myoptions.h | | ------ | ------ | ------ | | GND | GND | - | | VCC | +5v | - | | SCL | 18 | - | | SDA | 23 | - | | CSL | 5* | TFT_CS | -| RSTL | 15* | TFT_RST | +| RST | 15* | TFT_RST | | DCL | 4* | TFT_DC | -| NOKIA5110 | ESP-32 | options.h | +##### Nokia 5110 +| NOKIA5110 | ESP-32 | myoptions.h | | ------ | ------ | ------ | | RST | 15* | TFT_RST | | CE | 5* | TFT_CS | @@ -83,14 +86,16 @@ https://www.aliexpress.com/item/33009687492.html | VCC | +3v3 | - | | GND | GND | - | -| I2C Display | ESP-32 | options.h | +##### I2C Displays +| Display | ESP-32 | myoptions.h | | ------ | ------ | ------ | | GND | GND | - | | VCC | +5v | - | -| SDA | 13* | I2C_SDA | -| SCL | 14* | I2C_SCL | +| SDA | 21* | I2C_SDA | +| SCL | 22* | I2C_SCL | -| LCD 1602 | ESP-32 | options.h | +##### LCD Displays (1602, 2004) +| Display | ESP-32 | myoptions.h | | ------ | ------ | ------ | | GND | GND | - | | VCC | +5v | - | @@ -101,7 +106,8 @@ https://www.aliexpress.com/item/33009687492.html | D6 | any* | LCD_D6 | | D7 | any* | LCD_D7 | -| Touchscreen | ESP-32 | options.h | +##### Touchscreen +| Touchscreen | ESP-32 | myoptions.h | | ------ | ------ | ------ | | GND | GND | - | | VCC | +3.3v | - | @@ -111,7 +117,8 @@ https://www.aliexpress.com/item/33009687492.html | IRQ | N/C | - | | CS | any* | TS_CS | -| I2S DAC | ESP-32 | options.h | +##### I2S DAC +| I2S DAC | ESP-32 | myoptions.h | | ------ | ------ | ------ | | GND | GND | - | | VIN | +5v | - | @@ -119,7 +126,8 @@ https://www.aliexpress.com/item/33009687492.html | BCLK | 26* | I2S_BCLK | | LRC(WSEL) | 25* | I2S_LRC | -| VS1053 | ESP-32 | options.h | +##### VS1053 +| VS1053 | ESP-32 | myoptions.h | | ------ | ------ | ------ | | XDCS | 25* | VS1053_DCS | | XCS | 27* | VS1053_CS | @@ -132,10 +140,19 @@ https://www.aliexpress.com/item/33009687492.html | DGND | GND | - | _\#\# Important! You must choose between I2S DAC and VS1053 by disabling the second module in the settings (see below)_ +##### Nextion Displays +| Display | ESP-32 | myoptions.h | +| ------ | ------ | ------ | +| GND | GND | - | +| VCC | +5v | - | +| TX | 14* | NEXTION_RX | +| RX | 15* | NEXTION_TX | -| Buttons, Encoder, LED, IR, Joystick | ESP-32 | options.h | +##### Controls +| Buttons, Encoder, LED, IR, Joystick | ESP-32 | myoptions.h | | ------ | ------ | ------ | | GND | GND | - | +| 5v | 3v3 | - | | PIN | any* | ENC_BTNx, BTN_xxx, LED_BUILTIN, IR_PIN | _\* Any free pin, configured in myoptions.h_ \ @@ -150,7 +167,9 @@ _\** GPIO 16 and 17 are used by PSRAM on the WROVER modules._ \* _if you need MQTT support_ #### Tool: -[ESP32 Filesystem Uploader](https://randomnerdtutorials.com/install-esp32-filesystem-uploader-arduino-ide/) +[ESP32 Filesystem Uploader](https://randomnerdtutorials.com/install-esp32-filesystem-uploader-arduino-ide/) \ + +**See [wiki](https://github.com/e2002/yoradio/wiki/How-to-flash#preparing) for details** --- ## Hardware setup @@ -206,6 +225,8 @@ _\*this step can be skipped if you add WiFiSSID WiFiPassword pairs to the [yoRad **Localization:** Если Adafruit_GFX ещё не русифицирована, русифицировать её, заменив файл Arduino/libraries/Adafruit_GFX_Library/glcdfont.c файлом [yoRadio/fonts/glcdfont.c](yoRadio/fonts/glcdfont.c) +**See [wiki](https://github.com/e2002/yoradio/wiki/How-to-flash#build--flash) for details** + --- ## Update 1. Backup your settings: \ @@ -291,11 +312,22 @@ download _http://\/data/playlist.csv_ and _http://\/data --- ## Plugins -At the moment, you can display additional information on the display by writing a few additional functions. There is no documentation yet, you will have to deal with the example, which is in file [exsamples/plugins/displayhandlers.ino](exsamples/plugins/displayhandlers.ino).\ +At the moment, you can display additional information on the display by writing a few additional functions. There is no documentation yet, you will have to deal with the examples, which is in directory [exsamples/plugins/](https://github.com/e2002/yoradio/tree/main/exsamples/plugins).\ Work is in progress... --- ## Version history +#### v0.7.330 +**!!! a [full update](#update-over-web-interface) with Sketch data upload is required. After updating please press CTRL+F5 in browser !!!** \ +**Please backup playlist.csv and wifi.csv before updating.** +- added the ability to configure parameters through the [web interface](images/settings.png) +- new parameter BRIGHTNESS_PIN - pin for adjusting the brightness of the display. Details in [exsamples/myoptions.h](exsamples/myoptions.h#L105) +- the weather plugin is integrated into the code, the settings are made through the web interface + +_**PS:** Due to the change in the storage location of settings in the ESP memory, settings such as:_ \ +**smartstart, audioinfo, time zone, IR remote, last volume level, last played station, equalizer** \ +_will have to be configured again through the web interface. Please understand and forgive._ + #### v0.7.017 - fix initialization of some vs1053b green boards - fix VU initialization on vs1053b boards @@ -317,7 +349,7 @@ Work is in progress... #### v0.6.494 - adding VU meter for displays ST7735 160x128, ST7735 128x128, ILI9341 320x240, ST7789 320x240 \ - option ENABLE_VU_METER (see [myoptions.h](exsamples/myoptions.h#L113) for exsample) \ + option ENABLE_VU_METER (see [myoptions.h](exsamples/myoptions.h) for exsample) \ **!!! Important !!!** \ if you enable this feathure on the esp32 wroom, due to lack of memory, you must modify the file Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp \ **replace the line 221** \ @@ -344,8 +376,8 @@ Work is in progress... #### v0.6.355 - added support for ST7789 1.3' 240x240 SPI displays \ - _!!! Important !!! This display requires further development when used in conjunction with the VS1053 module. \ - See this link for details https://www.instructables.com/Adding-CS-Pin-to-13-LCD/_ + _!!! Important !!! This display requires further development when used in conjunction with the VS1053 module._ \ + See this link for details https://www.instructables.com/Adding-CS-Pin-to-13-LCD/ #### v0.6.348 - fixed display bugs in the rssibitrate plugin @@ -368,7 +400,7 @@ Work is in progress... - added support for ILI9225 220x176 SPI displays - added support for I2S internal DAC, option I2S_INTERNAL (see [myoptions.h](exsamples/myoptions.h#L111) for exsample) \ _(this option worked only with esp32 core version==2.0.0)_ -- new option SOFT_AP_REBOOT_DELAY (see [myoptions.h](exsamples/myoptions.h#L112) for exsample) +- new option SOFT_AP_REBOOT_DELAY (see [myoptions.h](exsamples/myoptions.h) for exsample) - fixed MQTT connection when WiFi reconnected - fixed date display for ILI9341 displays - fixed garbage on volume control with displays ILI9341 diff --git a/exsamples/myoptions.h b/exsamples/myoptions.h index 6c7b32c..43aae4e 100644 --- a/exsamples/myoptions.h +++ b/exsamples/myoptions.h @@ -13,6 +13,14 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti /* DSP_MODEL. See description/available values in the options.h file */ /* This option is required. Use DSP_DUMMY if no display is connected */ #define DSP_MODEL DSP_DUMMY +/* + * !!! Important !!! + * if you use colored TFT displays with the esp32 wroom, due to lack of memory, you must modify the file Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp + * replace the line 221 + * xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); + * with + * xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 / 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); +*/ /******************************************/ /* SPI PINS. SCL(SCK, CLK) must be connected to pin 18 @@ -25,9 +33,6 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti /* NEXTION */ //#define NEXTION_RX 255 /* Nextion RX pin */ //#define NEXTION_TX 255 /* Nextion TX pin */ -//#define NEXTION_WEATHER_LAT "55.7512" /* Nextion latitude for display Weather */ -//#define NEXTION_WEATHER_LON "37.6184" /* Nextion longitude for display Weather */ -//#define NEXTION_WEATHER_KEY "" /* Openweathermap API key https://openweathermap.org/appid */ /* I2C PINS */ //#define I2C_SDA 21 /* I2C SDA pin. It is best to connect to pin 21. */ @@ -41,11 +46,12 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti /******************************************/ /* VS1053 PINS. VS1053 SCK must be connected to pin 18 + VS1053 MISO must be connected to pin 19 VS1053 MOSI must be connected to pin 23 */ -//#define VS1053_CS 255 /* Should be set to 255 if the board is not used */ -//#define VS1053_DCS 25 -//#define VS1053_DREQ 26 -//#define VS1053_RST -1 /* Set to -1 if connected to Esp EN pin */ +//#define VS1053_CS 255 /* XCS pin. Should be set to 255 if the board is not used */ +//#define VS1053_DCS 25 /* XDCS pin. */ +//#define VS1053_DREQ 26 /* DREQ pin. */ +//#define VS1053_RST -1 /* XRESET pin. Set to -1 if connected to Esp EN pin */ /******************************************/ /* ENCODER */ @@ -91,41 +97,25 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti DO must be connected to pin 19 IRQ - not connected */ //#define TS_CS 255 /* Touch screen CS pin -//#define TS_ROTATE 1 /* Touch screen rotation. 0 - 0, 1 - 90, 2 - 180, 3 - 270 degrees */ -//#define TS_DBG false /* Generate debug to Serial output */ /******************************************/ /* Other settings. */ //#define DTYPE INITR_BLACKTAB /* ST7735 display submodel */ - /* Could be one of: */ - /* INITR_BLACKTAB 1.8' https://aliexpress.com/item/1005002822797745.html */ - /* (See this note If INITR_BLACKTAB have a noisy line on one side of the screen https://github.com/e2002/yoradio#note-if-initr_blacktab-dsp-have-a-noisy-line-on-one-side-of-the-screen-then-in-adafruit_st7735cpp ) */ - /* INITR_144GREENTAB // 1.44' https://aliexpress.com/item/1005002822797745.html */ - /* INITR_MINI160x80 // 0.96' 160x80 ST7735S https://???? */ - /* INITR_GREENTAB */ - /* INITR_REDTAB */ + /* Could be one of: */ + /* INITR_BLACKTAB 1.8' https://aliexpress.com/item/1005002822797745.html */ + /* (See this note If INITR_BLACKTAB have a noisy line on one side of the screen https://github.com/e2002/yoradio#note-if-initr_blacktab-dsp-have-a-noisy-line-on-one-side-of-the-screen-then-in-adafruit_st7735cpp ) */ + /* INITR_144GREENTAB // 1.44' https://aliexpress.com/item/1005002822797745.html */ + /* INITR_MINI160x80 // 0.96' 160x80 ST7735S https://???? */ + /* INITR_GREENTAB */ + /* INITR_REDTAB */ //#define LED_BUILTIN 2 /* LED Pin */ -//#define TFT_ROTATE 3 /* Display rotation. 0 - 0, 1 - 90, 2 - 180, 3 - 270 degrees */ -//#define TFT_CONTRAST 55 /* Nokia 5110 contrast */ -//#define TFT_INVERT true /* Invert the display colors (usually true) */ -//#define VOL_STEP 1 /* Volume control step */ -//#define VOL_ACCELERATION 200 /* Encoder vol acceleration; 0 or 1 means disabled acceleration */ //#define MUTE_PIN 255 /* MUTE Pin */ //#define MUTE_VAL HIGH /* Write this to MUTE_PIN when player is stopped */ -//#define PL_WITH_NUMBERS /* show the number of station in the playlist */ +//#define BRIGHTNESS_PIN 255 /* Pin for adjusting the brightness of the display (output 0 - 3v3) */ //#define PLAYER_FORCE_MONO false /* mono option on boot - false stereo, true mono */ -//#define SNTP_SERVER "pool.ntp.org", "0.ru.pool.ntp.org" /* custom ntp servers min 1 max 3 comma separated values */ //#define I2S_INTERNAL false /* If true - use esp32 internal DAC */ -//#define SOFT_AP_REBOOT_DELAY 0 /* Delay in milliseconds after which ESP is rebooting if it is in softAP mode (0 - disabled) */ -//#define ENABLE_VU_METER false /* enable? vu meter for some displays */ -/* - * !!! Important !!! - * if you enable this feathure on the esp32 wroom, due to lack of memory, you must modify the file Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp - * replace the line 221 - * xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); - * with - * xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 / 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); -*/ +//#define ROTATE_90 false /* Optional 90 degree rotation for square displays */ + /* VU settings. See the default settings for your display in file yoRadio/display_vu.h */ /************************************************************************************************************************************************************************************/ /* vu left | vu top | band width | band height | band space | num of bands | fade speed | horisontal | Max Bands Color | Min Bands Color */ @@ -136,7 +126,6 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti /* IR control */ //#define IR_PIN 255 //#define IR_TIMEOUT 80 /* see kTimeout description in IRremoteESP8266 exsample https://github.com/crankyoldgit/IRremoteESP8266/blob/master/examples/IRrecvDumpV2/IRrecvDumpV2.ino */ -//#define IR_TLP 40 /* see kTolerancePercentage description in IRremoteESP8266 exsample https://github.com/crankyoldgit/IRremoteESP8266/blob/master/examples/IRrecvDumpV2/IRrecvDumpV2.ino */ /******************************************/ diff --git a/images/settings.png b/images/settings.png new file mode 100644 index 0000000..382ec52 Binary files /dev/null and b/images/settings.png differ diff --git a/yoRadio/config.cpp b/yoRadio/config.cpp index 4d0a6ec..6bf1305 100644 --- a/yoRadio/config.cpp +++ b/yoRadio/config.cpp @@ -11,13 +11,7 @@ void Config::init() { irindex=-1; #endif eepromRead(EEPROM_START, store); - if (store.tz_set != 57) { // update to v0.4.200 - store.tz_set = 57; - store.tzHour = 3; - store.tzMin = 0; - store.timezoneOffset = 0; - } - if (store.config_set != 4256) setDefaults(); + if (store.config_set != 4262) setDefaults(); //if (!SPIFFS.begin(false, "/spiffs", 30)) { if (!SPIFFS.begin(false)) { return; @@ -36,6 +30,10 @@ void Config::init() { memset(ircodes.irVals, 0, sizeof(ircodes.irVals)); } #endif +#if BRIGHTNESS_PIN!=255 + pinMode(BRIGHTNESS_PIN, OUTPUT); + setBrightness(false); +#endif } template int Config::eepromWrite(int ee, const T& value) { @@ -56,7 +54,7 @@ template int Config::eepromRead(int ee, T& value) { } void Config::setDefaults() { - store.config_set = 4256; + store.config_set = 4262; store.volume = 12; store.balance = 0; store.trebble = 0; @@ -67,10 +65,41 @@ void Config::setDefaults() { store.lastSSID = 0; store.audioinfo = false; store.smartstart = 2; - store.tz_set = 57; store.tzHour = 3; store.tzMin = 0; store.timezoneOffset = 0; + + store.vumeter=false; + store.softapdelay=0; + store.flipscreen=false; + store.invertdisplay=false; + store.numplaylist=false; + store.fliptouch=false; + store.dbgtouch=false; + store.dspon=true; + store.brightness=100; + store.contrast=55; + strlcpy(store.sntp1,"0.ru.pool.ntp.org", 35); + strlcpy(store.sntp2,"1.ru.pool.ntp.org", 35); + store.showweather=false; + strlcpy(store.weatherlat,"55.7512", 10); + strlcpy(store.weatherlon,"37.6184", 10); + strlcpy(store.weatherkey,"", 64); + store.volsteps = 1; + store.encacc = 200; + store.irto = 80; + store.irtlp = 35; + store.btnpullup = true; + store.btnlongpress = 200; + store.btnclickticks = 300; + store.btnpressticks = 500; + store.encpullup = false; + store.enchalf = false; + store.enc2pullup = false; + store.enc2half = false; + store.forcemono = false; + store.i2sinternal = false; + store.rotate90 = false; } void Config::setTimezone(int8_t tzh, int8_t tzm) { @@ -247,17 +276,17 @@ void Config::fillPlMenu(char plmenu[][40], int from, byte count, bool removeNum) } while (playlist.available()) { if (parseCSV(playlist.readStringUntil('\n').c_str(), sName, sUrl, sOvol)) { -#ifdef PL_WITH_NUMBERS - if(removeNum){ - strlcpy(plmenu[c], sName, 39); + if(config.store.numplaylist){ + if(removeNum){ + strlcpy(plmenu[c], sName, 39); + }else{ + char buf[BUFLEN+10]; + sprintf(buf, "%d %s", (int)(from+c), sName); + strlcpy(plmenu[c], buf, 39); + } }else{ - char buf[BUFLEN+10]; - sprintf(buf, "%d %s", (int)(from+c), sName); - strlcpy(plmenu[c], buf, 39); + strlcpy(plmenu[c], sName, 39); } -#else - strlcpy(plmenu[c], sName, 39); -#endif c++; } if (c >= count) break; @@ -344,7 +373,7 @@ bool Config::parseWsCommand(const char* line, char* cmd, char* val, byte cSize) strlcpy(cmd, line, tmpe - line + 1); if (strlen(tmpe + 1) == 0) return false; memset(val, 0, cSize); - strlcpy(val, tmpe + 1, tmpe + 1 - line + 1); + strlcpy(val, tmpe + 1, strlen(line) - strlen(cmd) + 1); return true; } @@ -391,3 +420,10 @@ bool Config::initNetwork() { file.close(); return true; } + +void Config::setBrightness(bool dosave){ +#if BRIGHTNESS_PIN!=255 + analogWrite(BRIGHTNESS_PIN, config.store.dspon?map(store.brightness, 0, 100, 0, 255):0); + if(dosave) save(); +#endif +} diff --git a/yoRadio/config.h b/yoRadio/config.h index 57e3f0c..be658a6 100644 --- a/yoRadio/config.h +++ b/yoRadio/config.h @@ -4,8 +4,9 @@ #include "options.h" #define EEPROM_SIZE 768 -#define EEPROM_START 0 -#define EEPROM_START_IR 100 +#define EEPROM_START 500 +#define EEPROM_START_IR 0 +#define EEPROM_START_2 10 #define BUFLEN 140 #define PLAYLIST_PATH "/data/playlist.csv" #define SSIDS_PATH "/data/wifi.csv" @@ -14,7 +15,7 @@ struct config_t { - unsigned int config_set; //must be 4256 + unsigned int config_set; //must be 4262 byte volume; int8_t balance; int8_t trebble; @@ -25,10 +26,41 @@ struct config_t byte lastSSID; bool audioinfo; byte smartstart; - byte tz_set; // must be 57 int8_t tzHour; int8_t tzMin; uint16_t timezoneOffset; + + bool vumeter; + uint8_t softapdelay; + bool flipscreen; + bool invertdisplay; + bool numplaylist; + bool fliptouch; + bool dbgtouch; + bool dspon; + uint8_t brightness; + uint8_t contrast; + char sntp1[35]; + char sntp2[35]; + bool showweather; + char weatherlat[10]; + char weatherlon[10]; + char weatherkey[64]; + uint8_t volsteps; + uint16_t encacc; + uint8_t irto; + uint8_t irtlp; + bool btnpullup; + uint16_t btnlongpress; + uint16_t btnclickticks; + uint16_t btnpressticks; + bool encpullup; + bool enchalf; + bool enc2pullup; + bool enc2half; + bool forcemono; + bool i2sinternal; + bool rotate90; }; #if IR_PIN!=255 @@ -74,7 +106,7 @@ class Config { void init(); byte setVolume(byte val); void saveVolume(); - void setTone(int8_t bass, int8_t middle, int8_t trebble); + void setTone(int8_t bass, int8_t middle, int8_t trebble); void setBalance(int8_t balance); byte setLastStation(byte val); byte setCountStation(byte val); @@ -91,10 +123,12 @@ class Config { void setSmartStart(byte ss); void initPlaylist(); void indexPlaylist(); - void fillPlMenu(char plmenu[][40], int from, byte count, bool removeNum=false); + void fillPlMenu(char plmenu[][40], int from, byte count, bool removeNum = false); void setTimezone(int8_t tzh, int8_t tzm); void setTimezoneOffset(uint16_t tzo); uint16_t getTimezoneOffset(); + void setBrightness(bool dosave=false); + private: template int eepromWrite(int ee, const T& value); template int eepromRead(int ee, T& value); diff --git a/yoRadio/controls.cpp b/yoRadio/controls.cpp index e90f4e7..70f4139 100644 --- a/yoRadio/controls.cpp +++ b/yoRadio/controls.cpp @@ -59,7 +59,6 @@ byte irVolRepeat = 0; const uint16_t kCaptureBufferSize = 1024; const uint8_t kTimeout = IR_TIMEOUT; const uint16_t kMinUnknownSize = 12; -const uint8_t kTolerancePercentage = IR_TLP; //kTolerance; // kTolerance is normally 25% #define LEGACY_TIMING_INFO false IRrecv irrecv(IR_PIN, kCaptureBufferSize, kTimeout, true); @@ -85,13 +84,13 @@ void initControls() { encoder.begin(); encoder.setup(readEncoderISR); encoder.setBoundaries(0, 254, true); - encoder.setAcceleration(VOL_ACCELERATION); + encoder.setAcceleration(config.store.encacc); #endif #if ENC2_BTNL!=255 encoder2.begin(); encoder2.setup(readEncoder2ISR); encoder2.setBoundaries(0, 254, true); - encoder2.setAcceleration(VOL_ACCELERATION); + encoder2.setAcceleration(config.store.encacc); #endif #if ISPUSHBUTTONS @@ -116,7 +115,7 @@ void initControls() { #endif #if TS_CS!=255 ts.begin(); - ts.setRotation(TS_ROTATE); + ts.setRotation(config.store.fliptouch?3:1); #endif #if IR_PIN!=255 pinMode(IR_PIN, INPUT); @@ -124,7 +123,7 @@ void initControls() { #if DECODE_HASH irrecv.setUnknownThreshold(kMinUnknownSize); #endif // DECODE_HASH - irrecv.setTolerance(kTolerancePercentage); + irrecv.setTolerance(config.store.irtlp); irrecv.enableIRIn(); #endif // IR_PIN!=255 } @@ -411,7 +410,7 @@ void touchLoop() { int16_t yDelta = map(abs(touchStation - touchY), 0, display.screenheight, 0, TS_STEPS); display.putRequest({NEWMODE, STATIONS}); if (yDelta>1) { - controlsEvent((touchStation - touchY)>0); + controlsEvent((touchStation - touchY)<0); touchStation = touchY; } } @@ -421,7 +420,7 @@ void touchLoop() { break; } } - if (TS_DBG) { + if (config.store.dbgtouch) { Serial.print(", x = "); Serial.print(p.x); Serial.print(", y = "); @@ -609,3 +608,25 @@ void onBtnDoubleClick(int id) { break; } } +void setIRTolerance(uint8_t tl){ + config.store.irtlp=tl; + config.save(); +#if IR_PIN!=255 + irrecv.setTolerance(config.store.irtlp); +#endif +} +void setEncAcceleration(uint16_t acc){ + config.store.encacc=acc; + config.save(); +#if ENC_BTNL!=255 + encoder.setAcceleration(config.store.encacc); +#endif +#if ENC2_BTNL!=255 + encoder2.setAcceleration(config.store.encacc); +#endif +} +void flipTS(){ +#if TS_CS!=255 + ts.setRotation(config.store.fliptouch?3:1); +#endif +} diff --git a/yoRadio/controls.h b/yoRadio/controls.h index e0afdf0..84a76d1 100644 --- a/yoRadio/controls.h +++ b/yoRadio/controls.h @@ -29,6 +29,10 @@ void onBtnLongPressStart(int id); void onBtnLongPressStop(int id); tsDirection_e tsDirection(uint16_t x, uint16_t y); +void setIRTolerance(uint8_t tl); +void setEncAcceleration(uint16_t acc); +void flipTS(); + extern __attribute__((weak)) void ctrls_on_loop(); #endif diff --git a/yoRadio/data/www/dragpl.js.gz b/yoRadio/data/www/dragpl.js.gz index 9d5b729..55df2e0 100644 Binary files a/yoRadio/data/www/dragpl.js.gz and b/yoRadio/data/www/dragpl.js.gz differ diff --git a/yoRadio/data/www/elogo.png b/yoRadio/data/www/elogo.png index cb92ffd..9d9d42c 100644 Binary files a/yoRadio/data/www/elogo.png and b/yoRadio/data/www/elogo.png differ diff --git a/yoRadio/data/www/elogo100.png b/yoRadio/data/www/elogo100.png deleted file mode 100644 index d1508d5..0000000 Binary files a/yoRadio/data/www/elogo100.png and /dev/null differ diff --git a/yoRadio/data/www/elogo84.png b/yoRadio/data/www/elogo84.png new file mode 100644 index 0000000..ee369bf Binary files /dev/null and b/yoRadio/data/www/elogo84.png differ diff --git a/yoRadio/data/www/index.html b/yoRadio/data/www/index.html index dae5d1e..877969e 100644 --- a/yoRadio/data/www/index.html +++ b/yoRadio/data/www/index.html @@ -6,33 +6,28 @@ - - ёRadio + + ёRadio - Player
- - + diff --git a/yoRadio/display.cpp b/yoRadio/display.cpp index 0e067d2..4c2affa 100644 --- a/yoRadio/display.cpp +++ b/yoRadio/display.cpp @@ -3,7 +3,7 @@ #include "WiFi.h" #include "time.h" #include "display.h" -#if ENABLE_VU_METER +#if VU_READY==1 #include "display_vu.h" #endif #include "player.h" @@ -73,6 +73,13 @@ void ticks() { byte currentScrollId = 0; /* one scroll on one time */ +#if WEATHER_READY==1 +bool weatherRequest = false; +TaskHandle_t weatherUpdateTaskHandle; +Ticker weatherTicker; +char weatherText[254] = { 0 }; +#endif + void Scroll::init(byte ScrollId, const char *sep, byte tsize, byte top, uint16_t dlay, uint16_t fgcolor, uint16_t bgcolor) { textsize = tsize; id = ScrollId; @@ -239,6 +246,15 @@ void Display::init() { #endif plCurrent.init(4, " * ", PLCURRENT_SIZE, yStart, STARTTIME_PL, TFT_BG, TFT_LOGO); plCurrent.lock(); +#if WEATHER_READY==1 + if (DSP_MODEL == DSP_ST7735 || (DSP_MODEL == DSP_SSD1327)) { + weatherScroll.init(5, " * ", 1, TFT_LINEHGHT * 4 + 6, 0, ORANGE, TFT_BG); + }else if(DSP_MODEL == DSP_ILI9225){ + weatherScroll.init(5, " * ", 1, TFT_LINEHGHT * 6 + 5, 0, ORANGE, TFT_BG); + } else { + weatherScroll.init(5, " * ", 2, TFT_LINEHGHT * 9 + 5, 0, ORANGE, TFT_BG); + } +#endif if (dsp_on_init) dsp_on_init(); } @@ -476,6 +492,9 @@ void Display::loop() { switch (mode) { case PLAYER: { drawPlayer(); +#if WEATHER_READY==1 + weatherScroll.loop(); +#endif break; } case INFO: @@ -500,9 +519,15 @@ void Display::loop() { } dsp.loop(); if (dsp_on_loop) dsp_on_loop(&dsp); -#if ENABLE_VU_METER +#if VU_READY==1 drawVU(&dsp); #endif +#if WEATHER_READY==1 + if (weatherRequest) { + weatherRequest = false; + weatherScroll.setText(dsp.utf8Rus(weatherText, true)); + } +#endif } void Display::centerText(const char* text, byte y, uint16_t fg, uint16_t bg) { @@ -635,6 +660,19 @@ void Display::volume() { #endif //netserver.requestOnChange(VOLUME, 0); } + +void Display::flip(){ + dsp.flip(); +} + +void Display::invert(){ + dsp.invert(); +} +#if DSP_MODEL==DSP_NOKIA5110 +void Display::setContrast(){ + dsp.setContrast(config.store.contrast); +} +#endif // DSP_MODEL==DSP_NOKIA5110 /******************************************************************************************************************/ #endif // !DUMMYDISPLAY @@ -662,3 +700,140 @@ void Display::putRequest(requestParams_t request){ } /******************************************************************************************************************/ #endif // DUMMYDISPLAY + +#ifndef DUMMYDISPLAY +#if WEATHER_READY==1 + +bool getForecast() { + WiFiClient client; + const char* host = "api.openweathermap.org"; + + if (!client.connect(host, 80)) { + Serial.println("## OPENWEATHERMAP ###: connection failed"); + return false; + } + char httpget[250] = {0}; + sprintf(httpget, "GET /data/2.5/weather?lat=%s&lon=%s&units=metric&lang=ru&appid=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", config.store.weatherlat, config.store.weatherlon, config.store.weatherkey, host); + client.print(httpget); + unsigned long timeout = millis(); + while (client.available() == 0) { + if (millis() - timeout > 2000UL) { + Serial.println("## OPENWEATHERMAP ###: client available timeout !"); + client.stop(); + return false; + } + } + timeout = millis(); + String line = ""; + if (client.connected()) { + while (client.available()) + { + line = client.readStringUntil('\n'); + if (strstr(line.c_str(), "\"temp\"") != NULL) { + client.stop(); + break; + } + if ((millis() - timeout) > 500) + { + client.stop(); + Serial.println("## OPENWEATHERMAP ###: client read timeout !"); + return false; + } + } + } + if (strstr(line.c_str(), "\"temp\"") == NULL) { + Serial.println("## OPENWEATHERMAP ###: weather not found !"); + return false; + } + char *tmpe; + char *tmps; + const char* cursor = line.c_str(); + char desc[120], temp[20], hum[20], press[20], icon[5]; + + tmps = strstr(cursor, "\"description\":\""); + if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: description not found !"); return false;} + tmps += 15; + tmpe = strstr(tmps, "\",\""); + if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: description not found !"); return false;} + strlcpy(desc, tmps, tmpe - tmps + 1); + cursor = tmpe + 2; + + // "ясно","icon":"01d"}], + tmps = strstr(cursor, "\"icon\":\""); + if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: icon not found !"); return false;} + tmps += 8; + tmpe = strstr(tmps, "\"}"); + if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: icon not found !"); return false;} + strlcpy(icon, tmps, tmpe - tmps + 1); + cursor = tmpe + 2; + + tmps = strstr(cursor, "\"temp\":"); + if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: temp not found !"); return false;} + tmps += 7; + tmpe = strstr(tmps, ",\""); + if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: temp not found !"); return false;} + strlcpy(temp, tmps, tmpe - tmps + 1); + cursor = tmpe + 2; + float tempf = atof(temp); + + tmps = strstr(cursor, "\"pressure\":"); + if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: pressure not found !"); return false;} + tmps += 11; + tmpe = strstr(tmps, ",\""); + if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: pressure not found !"); return false;} + strlcpy(press, tmps, tmpe - tmps + 1); + cursor = tmpe + 2; + int pressi = (float)atoi(press) / 1.333; + + tmps = strstr(cursor, "humidity\":"); + if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: humidity not found !"); return false;} + tmps += 10; + tmpe = strstr(tmps, ",\""); + if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: humidity not found !"); return false;} + strlcpy(hum, tmps, tmpe - tmps + 1); + + Serial.printf("## OPENWEATHERMAP ###: description: %s, temp:%.1f C, pressure:%dmmHg, humidity:%s%%\n", desc, tempf, pressi, hum); + sprintf(weatherText, "%s, %.1f C * давление: %d мм * влажность: %s%%", desc, tempf, pressi, hum); + return true; + +} + +void Display::getWeather( void * pvParameters ) { + delay(200); + if (getForecast()) { + weatherRequest = true; + weatherTicker.detach(); + weatherTicker.attach(WEATHER_REQUEST_INTERVAL, display.updateWeather); + } else { + weatherTicker.detach(); + weatherTicker.attach(WEATHER_REQUEST_INTERVAL_FAULTY, display.updateWeather); + } + vTaskDelete( NULL ); +} +#endif // WEATHER_READY==1 + +void Display::updateWeather(){ +#if WEATHER_READY==1 + if(!config.store.showweather || strlen(config.store.weatherkey)==0) return; + xTaskCreatePinnedToCore( + getWeather, /* Task function. */ + "dspGetWeather1", /* name of task. */ + 1024 * 4, /* Stack size of task */ + NULL, /* parameter of the task */ + 0, /* priority of the task */ + &weatherUpdateTaskHandle, /* Task handle to keep track of created task */ + 0); /* pin task to core CORE_FOR_LOOP_CONTROLS */ +#endif // WEATHER_READY==1 +} + +void Display::showWeather(){ +#if WEATHER_READY==1 + if(strlen(config.store.weatherkey)!=0 && config.store.showweather) display.updateWeather(); + if(!config.store.showweather){ + memset(weatherText, 0, sizeof(weatherText)); + weatherScroll.setText(weatherText); + } +#endif // WEATHER_READY==1 +} +/******************************************************************************************************************/ +#endif // !DUMMYDISPLAY diff --git a/yoRadio/display.h b/yoRadio/display.h index c484607..a5409e1 100644 --- a/yoRadio/display.h +++ b/yoRadio/display.h @@ -38,8 +38,20 @@ #elif DSP_MODEL==DSP_ILI9225 #include "src/displays/displayILI9225.h" #endif +#ifndef VU_READY +#define VU_READY 0 +#endif +#ifndef DSP_FLIPPED +#define DSP_FLIPPED 1 +#endif +#ifndef WEATHER_READY +#define WEATHER_READY 0 +#else +#define WEATHER_REQUEST_INTERVAL 1800 //30min +#define WEATHER_REQUEST_INTERVAL_FAULTY 30 +#endif -enum displayMode_e { PLAYER, VOL, STATIONS, NUMBERS, LOST, UPDATING, INFO, SETTINGS, TIMEZONE, WIFI }; +enum displayMode_e { PLAYER, VOL, STATIONS, NUMBERS, LOST, UPDATING, INFO, SETTINGS, TIMEZONE, WIFI, CLEAR }; enum displayRequestType_e { NEWMODE, CLOCK, NEWTITLE, RETURNTITLE, NEWSTATION, NEXTSTATION, DRAWPLAYLIST, DRAWVOL }; struct requestParams_t @@ -111,6 +123,15 @@ class Display { void bootString(const char* text, byte y); void bootLogo(); void putRequest(requestParams_t request); + void flip(); + void invert(); + static void updateWeather(); + void showWeather(); +#if DSP_MODEL==DSP_NOKIA5110 + void setContrast(); +#else + void setContrast(){}; +#endif // DSP_MODEL==DSP_NOKIA5110 #else void init(); void loop(){}; @@ -122,9 +143,18 @@ class Display { void bootString(const char* text, byte y); void bootLogo(){}; void putRequest(requestParams_t request); + void flip(){}; + void invert(){}; + void setContrast(){}; + static void updateWeather(){}; + void showWeather(){}; #endif #ifndef DUMMYDISPLAY private: +#if WEATHER_READY==1 + Scroll weatherScroll; + static void getWeather( void * pvParameters ); +#endif Ticker timer; Scroll meta, title1, title2; bool clockRequest; diff --git a/yoRadio/display_vu.h b/yoRadio/display_vu.h index db34015..7a076f2 100644 --- a/yoRadio/display_vu.h +++ b/yoRadio/display_vu.h @@ -1,4 +1,3 @@ -#if ENABLE_VU_METER #ifndef display_vu_h #define display_vu_h #include "player.h" @@ -21,23 +20,29 @@ enum : uint16_t VU_PARAMS2; /**********************************************************************************************************************************************************************************/ /* vu left | vu top | band width | band height | band space | num of bands | fade speed | horisontal | Max Bands Color | Min Bands Color */ /**********************************************************************************************************************************************************************************/ + #if DSP_MODEL==DSP_ST7735 && DTYPE==INITR_BLACKTAB /* ST7735 160x128 */ -enum : uint16_t { VU_X = 4, VU_Y = 50, VU_BW = 10, VU_BH = 44, VU_BS = 2, VU_NB = 8, VU_FS = 2, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; +enum : uint16_t { VU_X = 4, VU_Y = 50, VU_BW = 10, VU_BH = 44, VU_BS = 2, VU_NB = 8, VU_FS = 2, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; + #elif DSP_MODEL==DSP_ST7735 && DTYPE==INITR_144GREENTAB /* ST7735 128x128 */ -enum : uint16_t { VU_X = 4, VU_Y = 45, VU_BW = 60, VU_BH = 8, VU_BS = 0, VU_NB = 10, VU_FS = 2, VU_HOR = 1, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = DARK_GRAY }; +enum : uint16_t { VU_X = 4, VU_Y = 97, VU_BW = 60, VU_BH = 8, VU_BS = 0, VU_NB = 10, VU_FS = 2, VU_HOR = 1, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = DARK_GRAY }; #define GREENTAB128 + #elif DSP_MODEL==DSP_ILI9341 /* ILI9341 320x240 */ -enum : uint16_t { VU_X = 4, VU_Y = 100, VU_BW = 20, VU_BH = 86, VU_BS = 4, VU_NB = 10, VU_FS = 5, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; +enum : uint16_t { VU_X = 4, VU_Y = 116, VU_BW = 24, VU_BH = 80, VU_BS = 4, VU_NB = 8, VU_FS = 5, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; + #elif DSP_MODEL==DSP_ST7789 /* ST7789 320x240 */ -enum : uint16_t { VU_X = 4, VU_Y = 100, VU_BW = 20, VU_BH = 86, VU_BS = 4, VU_NB = 10, VU_FS = 3, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; +enum : uint16_t { VU_X = 4, VU_Y = 116, VU_BW = 24, VU_BH = 80, VU_BS = 4, VU_NB = 8, VU_FS = 5, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; + #elif DSP_MODEL==DSP_ST7789_240 /* ST7789 240x240 */ -enum : uint16_t { VU_X = 4, VU_Y = 90, VU_BW = 120, VU_BH = 20, VU_BS = 0, VU_NB = 12, VU_FS = 3, VU_HOR = 1, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; +enum : uint16_t { VU_X = 4, VU_Y = 90, VU_BW = 120, VU_BH = 20, VU_BS = 0, VU_NB = 12, VU_FS = 3, VU_HOR = 1, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; + #elif DSP_MODEL==DSP_ILI9225 /* ILI9225 220x176 */ -enum : uint16_t { VU_X = 4, VU_Y = 74, VU_BW = 13, VU_BH = 60, VU_BS = 2, VU_NB = 10, VU_FS = 3, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; +enum : uint16_t { VU_X = 4, VU_Y = 80, VU_BW = 13, VU_BH = 56, VU_BS = 2, VU_NB = 8, VU_FS = 3, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; + #elif (DSP_MODEL==DSP_ST7735 && DTYPE==INITR_MINI160x80) || (DSP_MODEL==DSP_GC9106) /* ST7735 160x80, GC9106 160x80 */ -enum : uint16_t { VU_X = 1, VU_Y = 30, VU_BW = 12, VU_BH = 36, VU_BS = 4, VU_NB = 8, VU_FS = 2, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; -#else -#error YOUR DISPLAY DOES NOT SUPPORT ENABLE_VU_METER FEATURE YET +enum : uint16_t { VU_X = 1, VU_Y = 30, VU_BW = 12, VU_BH = 36, VU_BS = 4, VU_NB = 8, VU_FS = 2, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; + #endif #endif //VU_PARAMS /**********************************************************************************************************************************************************************************/ @@ -47,6 +52,7 @@ void drawVU(DspCore *dsp); GFXcanvas16 gfxc(VU_BW*2+VU_BS,VU_BH); void drawVU(DspCore *dsp){ + if(!config.store.vumeter) return; if(display.mode!=PLAYER && display.mode!=VOL) return; #ifdef GREENTAB128 if(display.mode==VOL) return; @@ -106,4 +112,3 @@ void drawVU(DspCore *dsp){ } } #endif -#endif diff --git a/yoRadio/netserver.cpp b/yoRadio/netserver.cpp index df9785a..b7074b6 100644 --- a/yoRadio/netserver.cpp +++ b/yoRadio/netserver.cpp @@ -8,12 +8,15 @@ #include "options.h" #include "network.h" #include "mqtt.h" +#include "controls.h" #include #ifndef MIN_MALLOC #define MIN_MALLOC 24112 #endif +#define CORS_DEBUG + NetServer netserver; AsyncWebServer webserver(80); @@ -25,7 +28,6 @@ void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len); void handleHTTPPost(AsyncWebServerRequest * request); -byte ssidCount; bool shouldReboot = false; char* updateError(){ @@ -34,23 +36,40 @@ char* updateError(){ return ret; } +void NetServer::takeMallocDog(){ + int mcb = heap_caps_get_free_size(MALLOC_CAP_8BIT); + int mci = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); + (void)mci; + log_i("[yoradio] webserver.on / - MALLOC_CAP_INTERNAL=%d, MALLOC_CAP_8BIT=%d", mci, mcb); + resumePlay = mcb < MIN_MALLOC; + if (resumePlay) { + player.toggle(); + while (player.isRunning()) { + vTaskDelay(10); + } + vTaskDelay(50); + } +} + +void NetServer::giveMallocDog(){ + if (resumePlay) { + resumePlay = false; + vTaskDelay(100); + player.toggle(); + } +} + bool NetServer::begin() { importRequest = false; irRecordEnable = false; webserver.on("/", HTTP_GET, [](AsyncWebServerRequest * request) { - ssidCount = 0; - int mcb = heap_caps_get_free_size(MALLOC_CAP_8BIT); - int mci = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); - (void)mci; - log_i("[yoradio] webserver.on / - MALLOC_CAP_INTERNAL=%d, MALLOC_CAP_8BIT=%d", mci, mcb); - netserver.resumePlay = mcb < MIN_MALLOC; - if (netserver.resumePlay) { - player.toggle(); - while (player.isRunning()) { - delay(10); - } + netserver.takeMallocDog(); + if (network.status == CONNECTED) { + request->send(SPIFFS, "/www/index.html", String(), false, processor); + }else{ + request->send(SPIFFS, "/www/settings.html", String(), false, processor); } - request->send(SPIFFS, "/www/index.html", String(), false, processor); + netserver.giveMallocDog(); }); webserver.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=31536000"); @@ -59,23 +78,37 @@ bool NetServer::begin() { handleHTTPPost(request); }); webserver.on(PLAYLIST_PATH, HTTP_GET, [](AsyncWebServerRequest * request) { + netserver.takeMallocDog(); request->send(SPIFFS, PLAYLIST_PATH, "application/octet-stream"); + netserver.giveMallocDog(); }); webserver.on(INDEX_PATH, HTTP_GET, [](AsyncWebServerRequest * request) { request->send(SPIFFS, INDEX_PATH, "application/octet-stream"); }); webserver.on(SSIDS_PATH, HTTP_GET, [](AsyncWebServerRequest * request) { + netserver.takeMallocDog(); request->send(SPIFFS, SSIDS_PATH, "application/octet-stream"); + netserver.giveMallocDog(); }); webserver.on("/upload", HTTP_POST, [](AsyncWebServerRequest * request) { //request->send(200); + }, handleUpload); webserver.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){ + netserver.takeMallocDog(); request->send(SPIFFS, "/www/update.html", String(), false, processor); + netserver.giveMallocDog(); + }); + webserver.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request){ + netserver.takeMallocDog(); + request->send(SPIFFS, "/www/settings.html", String(), false, processor); + netserver.giveMallocDog(); }); #if IR_PIN!=255 webserver.on("/ir", HTTP_GET, [](AsyncWebServerRequest *request){ + netserver.takeMallocDog(); request->send(SPIFFS, "/www/ir.html", String(), false, processor); + netserver.giveMallocDog(); }); #endif webserver.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){ @@ -109,6 +142,10 @@ bool NetServer::begin() { } } }); +#ifdef CORS_DEBUG + DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), F("*")); + DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), F("content-type")); +#endif webserver.begin(); websocket.onEvent(onWsEvent); webserver.addHandler(&websocket); @@ -136,7 +173,7 @@ void NetServer::loop() { } if (importRequest) { if (importPlaylist()) { - requestOnChange(PLAYLIST, 0); + //requestOnChange(PLAYLIST, 0); } importRequest = false; } @@ -157,16 +194,355 @@ void NetServer::irValsToWs(){ websocket.textAll(buf); } #endif -void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len) { +void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t clientId) { AwsFrameInfo *info = (AwsFrameInfo*)arg; if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) { data[len] = 0; - char cmd[15], val[15]; - if (config.parseWsCommand((const char*)data, cmd, val, 15)) { + char cmd[65], val[65]; + if (config.parseWsCommand((const char*)data, cmd, val, 65)) { + if (strcmp(cmd, "getmode") == 0) { + requestOnChange(GETMODE,clientId); + return; + } + if (strcmp(cmd, "getindex") == 0) { + requestOnChange(GETINDEX,clientId); + return; + } + if (strcmp(cmd, "getsystem") == 0) { + requestOnChange(GETSYSTEM,clientId); + return; + } + if (strcmp(cmd, "getscreen") == 0) { + requestOnChange(GETSCREEN,clientId); + return; + } + if (strcmp(cmd, "gettimezone") == 0) { + requestOnChange(GETTIMEZONE,clientId); + return; + } + if (strcmp(cmd, "getcontrols") == 0) { + requestOnChange(GETCONTROLS,clientId); + return; + } + if (strcmp(cmd, "getweather") == 0) { + requestOnChange(GETWEATHER,clientId); + return; + } + if (strcmp(cmd, "getactive") == 0) { + requestOnChange(GETACTIVE,clientId); + return; + } + + if (strcmp(cmd, "smartstart") == 0) { + byte valb=atoi(val); + config.store.smartstart=valb==1?1:2; + if(!player.isRunning() && config.store.smartstart==1) config.store.smartstart=0; + config.save(); + return; + } + if (strcmp(cmd, "audioinfo") == 0) { + byte valb=atoi(val); + config.store.audioinfo=valb; + config.save(); + display.putRequest({NEWMODE, CLEAR}); + display.putRequest({NEWMODE, PLAYER}); + return; + } + if (strcmp(cmd, "vumeter") == 0) { + byte valb=atoi(val); + config.store.vumeter=valb; + config.save(); + display.putRequest({NEWMODE, CLEAR}); + display.putRequest({NEWMODE, PLAYER}); + return; + } + if (strcmp(cmd, "softap") == 0) { + byte valb=atoi(val); + config.store.softapdelay=valb; + config.save(); + return; + } + if (strcmp(cmd, "invertdisplay") == 0) { + byte valb=atoi(val); + config.store.invertdisplay=valb; + config.save(); + display.invert(); + return; + } + if (strcmp(cmd, "numplaylist") == 0) { + byte valb=atoi(val); + config.store.numplaylist=valb; + config.save(); + display.putRequest({NEWMODE, CLEAR}); + display.putRequest({NEWMODE, PLAYER}); + return; + } + + if (strcmp(cmd, "fliptouch") == 0) { + byte valb=atoi(val); + config.store.fliptouch=valb==1; + config.save(); + flipTS(); + return; + } + if (strcmp(cmd, "dbgtouch") == 0) { + byte valb=atoi(val); + config.store.dbgtouch=valb==1; + config.save(); + return; + } + if (strcmp(cmd, "flipscreen") == 0) { + byte valb=atoi(val); + config.store.flipscreen=valb; + config.save(); + display.flip(); + display.putRequest({NEWMODE, CLEAR}); + display.putRequest({NEWMODE, PLAYER}); + return; + } + if (strcmp(cmd, "brightness") == 0) { + byte valb=atoi(val); + config.store.brightness=valb; + //display.setContrast(); + config.setBrightness(true); + return; + } + if (strcmp(cmd, "screenon") == 0) { + byte valb=atoi(val); + config.store.dspon=valb==1; + config.setBrightness(true); + return; + } + if (strcmp(cmd, "contrast") == 0) { + byte valb=atoi(val); + config.store.contrast=valb; + config.save(); + display.setContrast(); + return; + } + if (strcmp(cmd, "tzh") == 0) { + int vali=atoi(val); + config.store.tzHour=vali; + return; + } + if (strcmp(cmd, "tzm") == 0) { + int vali=atoi(val); + config.store.tzMin=vali; + return; + } + if (strcmp(cmd, "sntp2") == 0) { + strlcpy(config.store.sntp2,val, 35); + return; + } + if (strcmp(cmd, "sntp1") == 0) { + strlcpy(config.store.sntp1,val, 35); + bool tzdone=false; + if(strlen(config.store.sntp1)>0 && strlen(config.store.sntp2)>0){ + configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2); + tzdone=true; + }else if(strlen(config.store.sntp1)>0){ + configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1); + tzdone=true; + } + if(tzdone){ + network.requestTimeSync(true); + config.save(); + } + return; + } + + if (strcmp(cmd, "volsteps") == 0) { + uint8_t valb=atoi(val); + config.store.volsteps=valb; + config.save(); + return; + } + if (strcmp(cmd, "encacceleration") == 0) { + uint16_t valb=atoi(val); + setEncAcceleration(valb); + config.store.encacc=valb; + config.save(); + return; + } + if (strcmp(cmd, "irtlp") == 0) { + uint8_t valb=atoi(val); + setIRTolerance(valb); + return; + } + if (strcmp(cmd, "showweather") == 0) { + uint8_t valb=atoi(val); + config.store.showweather=valb==1; + config.save(); + display.showWeather(); +#ifdef USE_NEXTION + nextion.startWeather(); +#endif + display.putRequest({NEWMODE, CLEAR}); + display.putRequest({NEWMODE, PLAYER}); + return; + } + if (strcmp(cmd, "lat") == 0) { + strlcpy(config.store.weatherlat,val, 10); + return; + } + if (strcmp(cmd, "lon") == 0) { + strlcpy(config.store.weatherlon,val, 10); + return; + } + if (strcmp(cmd, "key") == 0) { + strlcpy(config.store.weatherkey,val, 64); + config.save(); + display.showWeather(); +#ifdef USE_NEXTION + nextion.startWeather(); +#endif + display.putRequest({NEWMODE, CLEAR}); + display.putRequest({NEWMODE, PLAYER}); + return; + } + + if (strcmp(cmd, "reset") == 0) { + if (strcmp(val, "system") == 0) { + config.store.smartstart=2; + config.store.audioinfo=false; + config.store.vumeter=false; + config.store.softapdelay=0; + config.save(); + display.putRequest({NEWMODE, CLEAR}); + display.putRequest({NEWMODE, PLAYER}); + requestOnChange(GETSYSTEM,clientId); + return; + } + if (strcmp(val, "screen") == 0) { + config.store.flipscreen=false; + display.flip(); + config.store.invertdisplay=false; + display.invert(); + config.store.dspon=true; + config.store.brightness=100; + config.setBrightness(false); + config.store.contrast=55; + display.setContrast(); + config.store.numplaylist=false; + config.save(); + display.putRequest({NEWMODE, CLEAR}); + display.putRequest({NEWMODE, PLAYER}); + requestOnChange(GETSCREEN,clientId); + return; + } + if (strcmp(val, "timezone") == 0) { + config.store.tzHour=3; + config.store.tzMin=0; + strlcpy(config.store.sntp1,"pool.ntp.org", 35); + strlcpy(config.store.sntp2,"0.ru.pool.ntp.org", 35); + config.save(); + configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2); + network.requestTimeSync(true); + requestOnChange(GETTIMEZONE,clientId); + return; + } + if (strcmp(val, "weather") == 0) { + config.store.showweather=0; + strlcpy(config.store.weatherlat,"55.7512", 10); + strlcpy(config.store.weatherlon,"37.6184", 10); + strlcpy(config.store.weatherkey,"", 64); + config.save(); + display.showWeather(); +#ifdef USE_NEXTION + nextion.startWeather(); +#endif + display.putRequest({NEWMODE, CLEAR}); + display.putRequest({NEWMODE, PLAYER}); + requestOnChange(GETWEATHER,clientId); + return; + } + if (strcmp(val, "controls") == 0) { + config.store.volsteps=1; + config.store.fliptouch=false; + config.store.dbgtouch=false; + setEncAcceleration(200); + setIRTolerance(40); + requestOnChange(GETCONTROLS,clientId); + return; + } + } if (strcmp(cmd, "volume") == 0) { byte v = atoi(val); player.setVol(v, false); } + + /* REMOVE FROM POST + * if (request->hasParam("trebble", true)) { + AsyncWebParameter* pt = request->getParam("trebble", true); + AsyncWebParameter* pm = request->getParam("middle", true); + AsyncWebParameter* pb = request->getParam("bass", true); + int t = atoi(pt->value().c_str()); + int m = atoi(pm->value().c_str()); + int b = atoi(pb->value().c_str()); + //setTone(int8_t gainLowPass, int8_t gainBandPass, int8_t gainHighPass) + player.setTone(b, m, t); + config.setTone(b, m, t); + netserver.requestOnChange(EQUALIZER, 0); + request->send(200); + return; + } + if (request->hasParam("ballance", true)) { + AsyncWebParameter* p = request->getParam("ballance", true); + int b = atoi(p->value().c_str()); + player.setBalance(b); + config.setBalance(b); + netserver.requestOnChange(BALANCE, 0); + request->send(200); + return; + } + */ + if (strcmp(cmd, "balance") == 0) { + int8_t valb=atoi(val); + player.setBalance(valb); + config.setBalance(valb); + netserver.requestOnChange(BALANCE, 0); + return; + } + if (strcmp(cmd, "treble") == 0) { + int8_t valb=atoi(val); + player.setTone(config.store.bass, config.store.middle, valb); + config.setTone(config.store.bass, config.store.middle, valb); + netserver.requestOnChange(EQUALIZER, 0); + return; + } + if (strcmp(cmd, "middle") == 0) { + int8_t valb=atoi(val); + player.setTone(config.store.bass, valb, config.store.trebble); + config.setTone(config.store.bass, valb, config.store.trebble); + netserver.requestOnChange(EQUALIZER, 0); + return; + } + if (strcmp(cmd, "bass") == 0) { + int8_t valb=atoi(val); + player.setTone(valb, config.store.middle, config.store.trebble); + config.setTone(valb, config.store.middle, config.store.trebble); + netserver.requestOnChange(EQUALIZER, 0); + return; + } + if (strcmp(cmd, "submitplaylist") == 0) { + if(player.isRunning()){ + player.toggle(); + while (player.isRunning()) { + vTaskDelay(10); + } + vTaskDelay(50); + resumePlay=true; + } + return; + } + if (strcmp(cmd, "submitplaylistdone") == 0) { + if(resumePlay){ + vTaskDelay(100); + player.toggle(); + resumePlay=false; + } + return; + } #if IR_PIN!=255 if (strcmp(cmd, "irbtn") == 0) { config.irindex=atoi(val); @@ -264,7 +640,7 @@ bool NetServer::importPlaylist() { } void NetServer::requestOnChange(requestType_e request, uint8_t clientId) { - char buf[BUFLEN + 50] = { 0 }; + char buf[BUFLEN * 2] = { 0 }; switch (request) { case PLAYLIST: { getPlaylist(clientId); @@ -279,6 +655,90 @@ void NetServer::requestOnChange(requestType_e request, uint8_t clientId) { #endif break; } + case GETACTIVE: { + bool dbgact = false; + String act="\"group_wifi\","; + if (network.status == CONNECTED) { + act+="\"group_system\","; + if(BRIGHTNESS_PIN!=255 || DSP_FLIPPED==1 || DSP_MODEL==DSP_NOKIA5110 || dbgact){ + act+="\"group_display\","; + } +#ifdef USE_NEXTION + act+="\"group_nextion\","; + if (WEATHER_READY==0 || dbgact){ + act+="\"group_weather\","; + } +#endif + if(VU_READY==1 || dbgact){ + act+="\"group_vu\","; + } + if(BRIGHTNESS_PIN!=255 || dbgact){ + act+="\"group_brightness\","; + } + if(DSP_FLIPPED==1 || dbgact){ + act+="\"group_tft\","; + } + if(TS_CS!=255 || dbgact){ + act+="\"group_touch\","; + } + if(DSP_MODEL==DSP_NOKIA5110){ + act+="\"group_nokia\","; + } + if(DSP_MODEL!=DSP_DUMMY || dbgact){ + act+="\"group_timezone\","; + + } + if (WEATHER_READY==1 || dbgact){ + act+="\"group_weather\","; + } + act+="\"group_controls\","; + if(ENC_BTNL!=255 || ENC2_BTNL!=255 || dbgact){ + act+="\"group_encoder\","; + } + if(IR_PIN!=255 || dbgact){ + act+="\"group_ir\","; + } + } + act = act.substring(0, act.length()-1); + sprintf (buf, "{\"act\":[%s]}", act.c_str()); + break; + } + case GETMODE: { + sprintf (buf, "{\"pmode\":\"%s\"}", network.status == CONNECTED?"player":"ap"); + break; + } + case GETINDEX: { + requestOnChange(STATION, clientId); + requestOnChange(TITLE, clientId); + requestOnChange(VOLUME, clientId); + requestOnChange(EQUALIZER, clientId); + requestOnChange(BALANCE, clientId); + requestOnChange(BITRATE, clientId); + requestOnChange(MODE, clientId); + //playlistrequest = clientId; /* Cleanup this */ + return; + break; + } + case GETSYSTEM: { + sprintf (buf, "{\"sst\":%d,\"aif\":%d,\"vu\":%d,\"softr\":%d}", config.store.smartstart!=2, config.store.audioinfo, config.store.vumeter, config.store.softapdelay); + break; + } + case GETSCREEN: { + sprintf (buf, "{\"flip\":%d,\"inv\":%d,\"nump\":%d,\"tsf\":%d,\"tsd\":%d,\"dspon\":%d,\"br\":%d,\"con\":%d}", config.store.flipscreen, config.store.invertdisplay, config.store.numplaylist, config.store.fliptouch, config.store.dbgtouch, config.store.dspon, config.store.brightness, config.store.contrast); + break; + } + case GETTIMEZONE: { + sprintf (buf, "{\"tzh\":%d,\"tzm\":%d,\"sntp1\":\"%s\",\"sntp2\":\"%s\"}", config.store.tzHour, config.store.tzMin, config.store.sntp1, config.store.sntp2); + break; + } + case GETWEATHER: { + sprintf (buf, "{\"wen\":%d,\"wlat\":\"%s\",\"wlon\":\"%s\",\"wkey\":\"%s\"}", config.store.showweather, config.store.weatherlat, config.store.weatherlon, config.store.weatherkey); + break; + } + case GETCONTROLS: { + sprintf (buf, "{\"vols\":%d,\"enca\":%d,\"irtl\":%d}", config.store.volsteps, config.store.encacc, config.store.irtlp); + break; + } case STATION: { sprintf (buf, "{\"nameset\": \"%s\"}", config.station.name); requestOnChange(ITEM, clientId); @@ -343,22 +803,6 @@ String processor(const String& var) { // %Templates% if (var == "VERSION") { return VERSION; } - if (var == "SSID") { - ssidCount++; - return String(config.ssids[ssidCount - 1].ssid); - } - if (var == "PASS") { - return String(config.ssids[ssidCount - 1].password); - } - if (var == "APMODE") { - return network.status == CONNECTED ? "" : " style=\"display: none!important\""; - } - if (var == "NOTAPMODE") { - return network.status == CONNECTED ? " hidden" : ""; - } - if (var == "IRMODE") { - return IR_PIN == 255 ? "" : " ir"; - } return String(); } @@ -381,22 +825,21 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp switch (type) { case WS_EVT_CONNECT: if(config.store.audioinfo) Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str()); - - netserver.requestOnChange(STATION, client->id()); + /*netserver.requestOnChange(STATION, client->id()); netserver.requestOnChange(TITLE, client->id()); netserver.requestOnChange(VOLUME, client->id()); netserver.requestOnChange(EQUALIZER, client->id()); netserver.requestOnChange(BALANCE, client->id()); netserver.requestOnChange(BITRATE, client->id()); netserver.requestOnChange(MODE, client->id()); - netserver.playlistrequest = client->id(); + netserver.playlistrequest = client->id();*/ break; case WS_EVT_DISCONNECT: if(config.store.audioinfo) Serial.printf("WebSocket client #%u disconnected\n", client->id()); break; case WS_EVT_DATA: - netserver.onWsMessage(arg, data, len); + netserver.onWsMessage(arg, data, len, client->id()); break; case WS_EVT_PONG: case WS_EVT_ERROR: diff --git a/yoRadio/netserver.h b/yoRadio/netserver.h index 62a562b..b211db4 100644 --- a/yoRadio/netserver.h +++ b/yoRadio/netserver.h @@ -5,7 +5,7 @@ #include "ESPAsyncWebServer.h" #include "AsyncUDP.h" -enum requestType_e { PLAYLIST, STATION, ITEM, TITLE, VOLUME, NRSSI, BITRATE, MODE, EQUALIZER, BALANCE, PLAYLISTSAVED }; +enum requestType_e { PLAYLIST, STATION, ITEM, TITLE, VOLUME, NRSSI, BITRATE, MODE, EQUALIZER, BALANCE, PLAYLISTSAVED, GETMODE, GETINDEX, GETACTIVE, GETSYSTEM, GETSCREEN, GETTIMEZONE, GETWEATHER, GETCONTROLS }; class NetServer { public: @@ -18,8 +18,10 @@ class NetServer { void loop(); void requestOnChange(requestType_e request, uint8_t clientId); void setRSSI(int val); - void onWsMessage(void *arg, uint8_t *data, size_t len); + void onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t clientId); bool savePlaylist(const char* post); + void takeMallocDog(); + void giveMallocDog(); #if IR_PIN!=255 bool irRecordEnable; void irToWs(const char* protocol, uint64_t irvalue); diff --git a/yoRadio/network.cpp b/yoRadio/network.cpp index bc76cb9..63f11d7 100644 --- a/yoRadio/network.cpp +++ b/yoRadio/network.cpp @@ -62,13 +62,19 @@ void Network::begin() { digitalWrite(LED_BUILTIN, LOW); status = CONNECTED; WiFi.setSleep(false); - configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), SNTP_SERVER); - //getLocalTime(&timeinfo); + //configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), SNTP_SERVER); + if(strlen(config.store.sntp1)>0 && strlen(config.store.sntp2)>0){ + configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2); + }else if(strlen(config.store.sntp1)>0){ + configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1); + } + ////getLocalTime(&timeinfo); stimer.once_ms(200,getFirstTime); ntimer.attach_ms(TSYNC_DELAY, syncTime); #ifdef USE_NEXTION nextion.startWeather(); #endif + display.updateWeather(); if (network_on_connect) network_on_connect(); } @@ -91,7 +97,6 @@ void Network::raiseSoftAP() { WiFi.softAP(apSsid, apPassword); Serial.printf("\n\nRunning in AP mode.\nConnect to AP %s with password %s for settings.\n\n", apSsid, apPassword); status = SOFT_AP; -#if SOFT_AP_REBOOT_DELAY>0 - rtimer.attach_ms(SOFT_AP_REBOOT_DELAY, rebootTime); -#endif + if(config.store.softapdelay>0) + rtimer.attach_ms(config.store.softapdelay*1000*60, rebootTime); } diff --git a/yoRadio/options.h b/yoRadio/options.h index 73848b2..820f196 100644 --- a/yoRadio/options.h +++ b/yoRadio/options.h @@ -1,7 +1,7 @@ #ifndef options_h #define options_h -#define VERSION "0.7.017" +#define VERSION "0.7.330" /******************************************************* DO NOT EDIT THIS FILE. @@ -64,22 +64,13 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti #ifndef NEXTION_TX #define NEXTION_TX 255 #endif -#ifndef NEXTION_WEATHER_LAT - #define NEXTION_WEATHER_LAT "55.7512" -#endif -#ifndef NEXTION_WEATHER_LON - #define NEXTION_WEATHER_LON "37.6184" -#endif -#ifndef NEXTION_WEATHER_KEY - #define NEXTION_WEATHER_KEY "" -#endif /* OLED I2C DISPLAY */ #ifndef I2C_SDA - #define I2C_SDA 13 + #define I2C_SDA 21 #endif #ifndef I2C_SCL - #define I2C_SCL 14 + #define I2C_SCL 22 #endif #ifndef I2C_RST #define I2C_RST -1 @@ -176,12 +167,6 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti #ifndef TS_CS #define TS_CS 255 #endif -#ifndef TS_ROTATE - #define TS_ROTATE 1 -#endif -#ifndef TS_DBG - #define TS_DBG false -#endif /* LCD DISPLAY */ #ifndef LCD_RS @@ -209,49 +194,23 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti #endif /* Other settings. You can overwrite them in the myoptions.h file */ -#ifndef TFT_ROTATE - #define TFT_ROTATE 3 // display rotation. 0 - 0, 1 - 90, 2 - 180, 3 - 270 degrees -#endif -#ifndef TFT_CONTRAST - #define TFT_CONTRAST 55 // Nokia 5110 contrast -#endif -#ifndef TFT_INVERT - #define TFT_INVERT true // invert the display colors (usually true) -#endif -#ifndef VOL_STEP - #define VOL_STEP 1 // Encoder vol step -#endif -#ifndef VOL_ACCELERATION - #define VOL_ACCELERATION 200 // Encoder vol acceleration; 0 or 1 means disabled acceleration -#endif #ifndef MUTE_PIN #define MUTE_PIN 255 // MUTE Pin #endif #ifndef MUTE_VAL #define MUTE_VAL HIGH // Write this to MUTE_PIN when player is stopped #endif +#ifndef BRIGHTNESS_PIN + #define BRIGHTNESS_PIN 255 // BRIGHTNESS Pin +#endif #ifndef PLAYER_FORCE_MONO #define PLAYER_FORCE_MONO false // mono option - false stereo, true mono #endif -#ifndef SNTP_SERVER - #define SNTP_SERVER "pool.ntp.org", "0.ru.pool.ntp.org" // custom ntp servers min 1 max 3 comma separated values -#endif #ifndef I2S_INTERNAL #define I2S_INTERNAL false // If true - use esp32 internal DAC #endif -#ifndef SOFT_AP_REBOOT_DELAY - #define SOFT_AP_REBOOT_DELAY 0 // Delay in ms after which ESP is rebooting if it is in softAP mode (0 - disabled) -#endif -#ifndef ENABLE_VU_METER - #define ENABLE_VU_METER false // enable? vu meter for some displays -/* - * !!! Important !!! - * if you enable this feathure on the esp32 wroom, due to lack of memory, you must modify the file Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp - * replace the line 221 - * xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); - * with - * xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 / 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); -*/ +#ifndef ROTATE_90 + #define ROTATE_90 false // Optional 90 degree rotation for square displays #endif /* *** ST7735 display submodel *** @@ -273,8 +232,5 @@ INITR_REDTAB #ifndef IR_TIMEOUT #define IR_TIMEOUT 80 // kTimeout, see IRremoteESP8266 documentation #endif -#ifndef IR_TLP - #define IR_TLP 40 // kTolerancePercentage, see IRremoteESP8266 documentation -#endif #endif diff --git a/yoRadio/player.cpp b/yoRadio/player.cpp index d9e9640..bd3f649 100644 --- a/yoRadio/player.cpp +++ b/yoRadio/player.cpp @@ -156,14 +156,14 @@ void Player::toggle() { void Player::stepVol(bool up) { if (up) { - if (config.store.volume <= 254 - VOL_STEP) { - setVol(config.store.volume + VOL_STEP, false); + if (config.store.volume <= 254 - config.store.volsteps) { + setVol(config.store.volume + config.store.volsteps, false); }else{ setVol(254, false); } } else { - if (config.store.volume >= VOL_STEP) { - setVol(config.store.volume - VOL_STEP, false); + if (config.store.volume >= config.store.volsteps) { + setVol(config.store.volume - config.store.volsteps, false); }else{ setVol(0, false); } diff --git a/yoRadio/src/ILI9225Fix/TFT_22_ILI9225Fix.cpp b/yoRadio/src/ILI9225Fix/TFT_22_ILI9225Fix.cpp index e5b539e..add322f 100644 --- a/yoRadio/src/ILI9225Fix/TFT_22_ILI9225Fix.cpp +++ b/yoRadio/src/ILI9225Fix/TFT_22_ILI9225Fix.cpp @@ -545,7 +545,7 @@ void TFT_22_ILI9225::clear() { } -void TFT_22_ILI9225::invert(boolean flag) { +void TFT_22_ILI9225::invertDisplay(boolean flag) { startWrite(); _writeCommand16(flag ? ILI9225C_INVON : ILI9225C_INVOFF); //_writeCommand(0x00, flag ? ILI9225C_INVON : ILI9225C_INVOFF); diff --git a/yoRadio/src/ILI9225Fix/TFT_22_ILI9225Fix.h b/yoRadio/src/ILI9225Fix/TFT_22_ILI9225Fix.h index 79b0089..16cfb2d 100644 --- a/yoRadio/src/ILI9225Fix/TFT_22_ILI9225Fix.h +++ b/yoRadio/src/ILI9225Fix/TFT_22_ILI9225Fix.h @@ -186,7 +186,7 @@ class TFT_22_ILI9225 { /// Invert screen /// @param flag true to invert, false for normal screen - void invert(boolean flag); + void invertDisplay(boolean flag); /// Switch backlight on or off /// @param flag true=on, false=off diff --git a/yoRadio/src/audioVS1053/audioVS1053Ex.cpp b/yoRadio/src/audioVS1053/audioVS1053Ex.cpp index 9e1b724..29d92bd 100644 --- a/yoRadio/src/audioVS1053/audioVS1053Ex.cpp +++ b/yoRadio/src/audioVS1053/audioVS1053Ex.cpp @@ -1569,7 +1569,6 @@ void Audio::setDefaults(){ * \n The VU meter takes about 0.2MHz of processing power with 48 kHz samplerate. */ void Audio::setVUmeter() { -// if(!ENABLE_VU_METER) return; uint16_t MP3Status = read_register(SCI_STATUS); if(MP3Status==0) { Serial.println("VS1053 Error: Unable to write SCI_STATUS"); @@ -1593,7 +1592,6 @@ void Audio::setVUmeter() { * \warning This feature is only available with patches that support VU meter. */ void Audio::getVUlevel() { -// if(!ENABLE_VU_METER) return; if(!_vuInitalized) return; int16_t reg = read_register(SCI_AICTRL3); uint8_t rl = map((uint8_t)reg, 85, 92, 0, 255); diff --git a/yoRadio/src/displays/displayDummy.h b/yoRadio/src/displays/displayDummy.h index 9a710fc..47cdd98 100644 --- a/yoRadio/src/displays/displayDummy.h +++ b/yoRadio/src/displays/displayDummy.h @@ -15,6 +15,8 @@ #define SCROLLTIME 60 #endif +#define DSP_FLIPPED 0 + class DspCore { public: DspCore(); diff --git a/yoRadio/src/displays/displayGC9106.cpp b/yoRadio/src/displays/displayGC9106.cpp index ad237b9..08cb734 100644 --- a/yoRadio/src/displays/displayGC9106.cpp +++ b/yoRadio/src/displays/displayGC9106.cpp @@ -12,11 +12,7 @@ #define DEF_SPI_FREQ 24000000 /* set it to 0 for system default */ #endif -#if ENABLE_VU_METER #define CLOCK_DELTA 16 -#else -#define CLOCK_DELTA 0 -#endif #define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY) #define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl) @@ -120,12 +116,9 @@ void DspCore::apScreen() { void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { begin(DEF_SPI_FREQ); cp437(true); - invertDisplay(!TFT_INVERT); + invert(); fillScreen(TFT_BG); - byte tftRotate = TFT_ROTATE; - if(tftRotate>1) tftRotate=3; - if(tftRotate==0) tftRotate=1; - setRotation(tftRotate); + flip(); setTextWrap(false); screenwidth = width(); screenheight = height(); @@ -239,15 +232,16 @@ void DspCore::printClock(struct tm timeinfo, bool dots, bool redraw){ char timeBuf[50] = { 0 }; char tmpBuf[4] = { 0 }; uint16_t ncwidth, ncheight; + uint16_t clockdelta=config.store.vumeter?CLOCK_DELTA:0; strftime(timeBuf, sizeof(timeBuf), "%H %M", &timeinfo); setTextSize(1); setFont(&DS_DIGI28pt7b); if(strstr(oldTimeBuf, timeBuf)==NULL || redraw){ getTextBounds(oldTimeBuf, 0, 0, &x, &y, &wot, &hot); - setCursor((swidth - wot) / 2 - 4 + CLOCK_DELTA, clockY+28+6); + setCursor((swidth - wot) / 2 - 4 + clockdelta, clockY+28+6); setTextColor(TFT_BG); print(oldTimeBuf); - dot = (swidth - wot) / 2 - 4 + CLOCK_DELTA; + dot = (swidth - wot) / 2 - 4 + clockdelta; /* dots */ strlcpy(tmpBuf, oldTimeBuf, 3); getTextBounds(tmpBuf, 0, 0, &x, &y, &ncwidth, &ncheight); @@ -260,8 +254,8 @@ void DspCore::printClock(struct tm timeinfo, bool dots, bool redraw){ setTextSize(1); getTextBounds(timeBuf, 0, 0, &x, &y, &ncwidth, &ncheight); setTextColor(TFT_LOGO); - setCursor((swidth - ncwidth) / 2 - 4 + CLOCK_DELTA, clockY+28+6); - dot = (swidth - ncwidth) / 2 - 4 + CLOCK_DELTA; + setCursor((swidth - ncwidth) / 2 - 4 + clockdelta, clockY+28+6); + dot = (swidth - ncwidth) / 2 - 4 + clockdelta; setTextSize(1); print(timeBuf); /* dots */ @@ -384,5 +378,11 @@ void DspCore::printText(const char* txt) { void DspCore::loop(bool force) { } +void DspCore::flip(){ + setRotation(config.store.flipscreen?1:3); +} +void DspCore::invert(){ + invertDisplay(config.store.invertdisplay); +} #endif diff --git a/yoRadio/src/displays/displayGC9106.h b/yoRadio/src/displays/displayGC9106.h index d159529..3c5f4f3 100644 --- a/yoRadio/src/displays/displayGC9106.h +++ b/yoRadio/src/displays/displayGC9106.h @@ -7,6 +7,8 @@ #include "../Adafruit_GC9106Ex/Adafruit_GC9106Ex.h" #include "fonts/DS_DIGI28pt7b.h" +#define VU_READY 1 + #define TFT_LINEHGHT 10 #define TFT_FRAMEWDT 0 @@ -58,6 +60,8 @@ class DspCore: public Adafruit_GC9106Ex { void loop(bool force=false); virtual void startWrite(void); virtual void endWrite(void); + void flip(); + void invert(); /*virtual void sendCommand(uint8_t commandByte, uint8_t *dataBytes, uint8_t numDataBytes); virtual void sendCommand(uint8_t commandByte, const uint8_t *dataBytes = NULL, diff --git a/yoRadio/src/displays/displayILI9225.cpp b/yoRadio/src/displays/displayILI9225.cpp index 21291de..e5919b9 100644 --- a/yoRadio/src/displays/displayILI9225.cpp +++ b/yoRadio/src/displays/displayILI9225.cpp @@ -190,10 +190,10 @@ void DspCore::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { //hspi.begin(); begin(); - invert(TFT_INVERT); + invert(); setBackgroundColor(TFT_BG); clear(); - setOrientation(TFT_ROTATE); + flip(); setTextSize(1); screenwidth = maxX(); screenheight = maxY(); @@ -449,5 +449,10 @@ void DspCore::drawRGBBitmap(int16_t x, int16_t y, const uint16_t *bitmap, int16_ drawBitmap(x, y, bitmap, w, h); GIVE_MUTEX(); } - +void DspCore::flip(){ + setOrientation(config.store.flipscreen?3:1); +} +void DspCore::invert(){ + invertDisplay(config.store.invertdisplay); +} #endif diff --git a/yoRadio/src/displays/displayILI9225.h b/yoRadio/src/displays/displayILI9225.h index e0e806b..6229e58 100644 --- a/yoRadio/src/displays/displayILI9225.h +++ b/yoRadio/src/displays/displayILI9225.h @@ -5,6 +5,9 @@ #include "../ILI9225Fix/TFT_22_ILI9225Fix.h" #include "fonts/DS_DIGI28pt7b.h" +#define VU_READY 1 +#define WEATHER_READY 1 + #define TFT_LINEHGHT 10 #define TFT_FRAMEWDT 4 #define META_SIZE 2 @@ -73,6 +76,8 @@ class DspCore: public TFT_22_ILI9225 { int16_t width(void) { return (int16_t)maxX(); } int16_t height(void) { return (int16_t)maxY(); } void drawRGBBitmap(int16_t x, int16_t y, const uint16_t *bitmap, int16_t w, int16_t h); + void flip(); + void invert(); private: uint16_t swidth, sheight; uint16_t bgcolor, fgcolor; diff --git a/yoRadio/src/displays/displayILI9341.cpp b/yoRadio/src/displays/displayILI9341.cpp index 0605d1e..fec2192 100644 --- a/yoRadio/src/displays/displayILI9341.cpp +++ b/yoRadio/src/displays/displayILI9341.cpp @@ -113,10 +113,10 @@ void DspCore::apScreen() { void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { begin(); /* SPI_DEFAULT_FREQ 40000000 */ - invertDisplay(TFT_INVERT); + invert(); cp437(true); fillScreen(TFT_BG); - setRotation(TFT_ROTATE); + flip(); setTextWrap(false); setTextSize(1); screenwidth = width(); @@ -385,5 +385,11 @@ void DspCore::printText(const char* txt) { void DspCore::loop(bool force) { } +void DspCore::flip(){ + setRotation(config.store.flipscreen?1:3); +} +void DspCore::invert(){ + invertDisplay(config.store.invertdisplay); +} #endif diff --git a/yoRadio/src/displays/displayILI9341.h b/yoRadio/src/displays/displayILI9341.h index 48f3934..dfa7afc 100644 --- a/yoRadio/src/displays/displayILI9341.h +++ b/yoRadio/src/displays/displayILI9341.h @@ -7,6 +7,9 @@ // https://tchapi.github.io/Adafruit-GFX-Font-Customiser/ #include "fonts/DS_DIGI42pt7b.h" +#define VU_READY 1 +#define WEATHER_READY 1 + #define TFT_LINEHGHT 10 #define TFT_FRAMEWDT 8 #define META_SIZE 3 @@ -58,6 +61,8 @@ class DspCore: public Adafruit_ILI9341 { void loop(bool force=false); virtual void startWrite(void); virtual void endWrite(void); + void flip(); + void invert(); private: uint16_t swidth, sheight; char oldTimeBuf[20]; diff --git a/yoRadio/src/displays/displayLC1602.h b/yoRadio/src/displays/displayLC1602.h index 3d7b872..1252b9c 100644 --- a/yoRadio/src/displays/displayLC1602.h +++ b/yoRadio/src/displays/displayLC1602.h @@ -3,6 +3,8 @@ #include "Arduino.h" +#define DSP_FLIPPED 0 + #if DSP_MODEL==DSP_2004 || DSP_MODEL==DSP_2004I2C #define LCD_2004 #endif @@ -89,6 +91,8 @@ class DspCore: public LiquidCrystal { void ip(const char* str); void drawPlaylist(uint16_t currentItem, char* currentItemText); void loop(bool force=false); + void flip(){}; + void invert(){}; private: uint16_t swidth, sheight, xOffset, yOffset; int16_t nextX; diff --git a/yoRadio/src/displays/displayN5110.cpp b/yoRadio/src/displays/displayN5110.cpp index 6900a2c..6b7837a 100644 --- a/yoRadio/src/displays/displayN5110.cpp +++ b/yoRadio/src/displays/displayN5110.cpp @@ -134,13 +134,11 @@ void DspCore::data(uint8_t c) { void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { begin(); - setContrast(TFT_CONTRAST); + setContrast(config.store.contrast); cp437(true); + invert(); fillScreen(TFT_BG); - byte tftRotate = TFT_ROTATE; - if(tftRotate>2) tftRotate=2; - if(tftRotate==1) tftRotate=0; - setRotation(tftRotate); + flip(); setTextWrap(false); screenwidth = width(); screenheight = height(); @@ -339,5 +337,11 @@ boolean DspCore::checkdelay(int m, unsigned long &tstamp) { return false; } } +void DspCore::flip(){ + setRotation(config.store.flipscreen?2:0); +} +void DspCore::invert(){ + invertDisplay(config.store.invertdisplay); +} #endif diff --git a/yoRadio/src/displays/displayN5110.h b/yoRadio/src/displays/displayN5110.h index 424fc90..b9a4406 100644 --- a/yoRadio/src/displays/displayN5110.h +++ b/yoRadio/src/displays/displayN5110.h @@ -58,6 +58,8 @@ class DspCore: public Adafruit_PCD8544 { void loop(bool force=false); virtual void command(uint8_t c); virtual void data(uint8_t c); + void flip(); + void invert(); private: uint16_t swidth, sheight; unsigned long loopdelay; diff --git a/yoRadio/src/displays/displaySH1106.cpp b/yoRadio/src/displays/displaySH1106.cpp index 81d9847..2088ee0 100644 --- a/yoRadio/src/displays/displaySH1106.cpp +++ b/yoRadio/src/displays/displaySH1106.cpp @@ -142,12 +142,8 @@ void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { } cp437(true); fillScreen(TFT_BG); - byte tftRotate = TFT_ROTATE; -#if DSP_MODEL==DSP_SH1107 - if(tftRotate>=2) tftRotate=3; - if(tftRotate==0) tftRotate=1; -#endif - setRotation(tftRotate); + flip(); + invert(); setTextWrap(false); screenwidth = width(); screenheight = height(); @@ -348,5 +344,16 @@ boolean DspCore::checkdelay(int m, unsigned long &tstamp) { return false; } } - +void DspCore::flip(){ +#if DSP_MODEL==DSP_SH1107 + setRotation(config.store.flipscreen?3:1); +#endif +#if DSP_MODEL==DSP_SH1106 + setRotation(config.store.flipscreen?2:0); +#endif +} + +void DspCore::invert(){ + invertDisplay(config.store.invertdisplay); +} #endif diff --git a/yoRadio/src/displays/displaySH1106.h b/yoRadio/src/displays/displaySH1106.h index 964548e..eeac7de 100644 --- a/yoRadio/src/displays/displaySH1106.h +++ b/yoRadio/src/displays/displaySH1106.h @@ -57,6 +57,8 @@ class DspCore: public Adafruit_SH1107 { void ip(const char* str); void drawPlaylist(uint16_t currentItem, char* currentItemText); void loop(bool force=false); + void flip(); + void invert(); private: uint16_t swidth, sheight; unsigned long loopdelay; diff --git a/yoRadio/src/displays/displaySSD1305.cpp b/yoRadio/src/displays/displaySSD1305.cpp index a7e55e3..01ee651 100644 --- a/yoRadio/src/displays/displaySSD1305.cpp +++ b/yoRadio/src/displays/displaySSD1305.cpp @@ -144,7 +144,8 @@ void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { } cp437(true); fillScreen(TFT_BG); - setRotation(TFT_ROTATE); + flip(); + invert(); setTextWrap(false); screenwidth = width(); screenheight = height(); @@ -332,5 +333,11 @@ boolean DspCore::checkdelay(int m, unsigned long &tstamp) { return false; } } +void DspCore::flip(){ + setRotation(config.store.flipscreen?2:0); +} +void DspCore::invert(){ + invertDisplay(config.store.invertdisplay); +} #endif diff --git a/yoRadio/src/displays/displaySSD1305.h b/yoRadio/src/displays/displaySSD1305.h index 79976d8..ef411a9 100644 --- a/yoRadio/src/displays/displaySSD1305.h +++ b/yoRadio/src/displays/displaySSD1305.h @@ -5,6 +5,8 @@ #include #include +#define WEATHER_READY 0 + #define TFT_LINEHGHT 8 #define TFT_FRAMEWDT 0 @@ -51,6 +53,8 @@ class DspCore: public Adafruit_SSD1305 { void ip(const char* str); void drawPlaylist(uint16_t currentItem, char* currentItemText); void loop(bool force=false); + void flip(); + void invert(); private: uint16_t swidth, sheight; unsigned long loopdelay; diff --git a/yoRadio/src/displays/displaySSD1306.cpp b/yoRadio/src/displays/displaySSD1306.cpp index c1215bc..e662ed1 100644 --- a/yoRadio/src/displays/displaySSD1306.cpp +++ b/yoRadio/src/displays/displaySSD1306.cpp @@ -141,10 +141,8 @@ void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { } cp437(true); fillScreen(TFT_BG); - byte tftRotate = TFT_ROTATE; - if(tftRotate>2) tftRotate=2; - if(tftRotate==1) tftRotate=0; - setRotation(tftRotate); + flip(); + invert(); setTextWrap(false); screenwidth = width(); screenheight = height(); @@ -355,5 +353,11 @@ boolean DspCore::checkdelay(int m, unsigned long &tstamp) { return false; } } +void DspCore::flip(){ + setRotation(config.store.flipscreen?2:0); +} +void DspCore::invert(){ + invertDisplay(config.store.invertdisplay); +} #endif diff --git a/yoRadio/src/displays/displaySSD1306.h b/yoRadio/src/displays/displaySSD1306.h index 226f88b..cbebbb2 100644 --- a/yoRadio/src/displays/displaySSD1306.h +++ b/yoRadio/src/displays/displaySSD1306.h @@ -71,6 +71,8 @@ class DspCore: public Adafruit_SSD1306 { void ip(const char* str); void drawPlaylist(uint16_t currentItem, char* currentItemText); void loop(bool force=false); + void flip(); + void invert(); private: uint16_t swidth, sheight; unsigned long loopdelay; diff --git a/yoRadio/src/displays/displaySSD1327.cpp b/yoRadio/src/displays/displaySSD1327.cpp index 0f8e99e..2d9bfd9 100644 --- a/yoRadio/src/displays/displaySSD1327.cpp +++ b/yoRadio/src/displays/displaySSD1327.cpp @@ -123,7 +123,8 @@ void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { } cp437(true); fillScreen(TFT_BG); - setRotation(TFT_ROTATE); + flip(); + invert(); setTextWrap(false); screenwidth = width(); screenheight = height(); @@ -401,5 +402,15 @@ boolean DspCore::checkdelay(int m, unsigned long &tstamp) { return false; } } +void DspCore::flip(){ + if(ROTATE_90){ + setRotation(config.store.flipscreen?3:1); + }else{ + setRotation(config.store.flipscreen?2:0); + } +} +void DspCore::invert(){ + invertDisplay(config.store.invertdisplay); +} #endif diff --git a/yoRadio/src/displays/displaySSD1327.h b/yoRadio/src/displays/displaySSD1327.h index c242f3d..052315c 100644 --- a/yoRadio/src/displays/displaySSD1327.h +++ b/yoRadio/src/displays/displaySSD1327.h @@ -6,6 +6,8 @@ #include #include "fonts/DS_DIGI28pt7b.h" +#define WEATHER_READY 1 + #define TFT_LINEHGHT 10 #define TFT_FRAMEWDT 4 @@ -13,26 +15,9 @@ #define PLMITEMLENGHT 40 #define PLMITEMHEIGHT 22 #define TITLE_TOP2 TFT_FRAMEWDT + 3 * TFT_LINEHGHT -/* -#ifdef DSP_FPS -#if DSP_FPS!=0 -#define SCROLLDELTA (DSP_FPS>30)?3:(80/DSP_FPS) -#define SCROLLTIME (DSP_FPS>30)?34:(1000/DSP_FPS) -#else -#define SCROLLDELTA 4 -#define SCROLLTIME 83 -#define LOOP_DELAY 83 -#endif -#else -#define SCROLLDELTA 4 -#define SCROLLTIME 83 -#define LOOP_DELAY 40 -#endif -*/ + #if !defined(SCROLLDELTA) || !defined(SCROLLTIME) -/*#define SCROLLDELTA 5 -#define SCROLLTIME 83 -#define LOOP_DELAY 100*/ + #define SCROLLDELTA 2 #define SCROLLTIME 30 #define LOOP_DELAY 33 @@ -70,6 +55,8 @@ class DspCore: public Adafruit_SSD1327 { void ip(const char* str); void drawPlaylist(uint16_t currentItem, char* currentItemText); void loop(bool force=false); + void flip(); + void invert(); private: uint16_t swidth, sheight; int16_t x, y; diff --git a/yoRadio/src/displays/displayST7735.cpp b/yoRadio/src/displays/displayST7735.cpp index faab6f3..c6b752d 100644 --- a/yoRadio/src/displays/displayST7735.cpp +++ b/yoRadio/src/displays/displayST7735.cpp @@ -13,11 +13,9 @@ #include "../../network.h" #ifndef DEF_SPI_FREQ -#define DEF_SPI_FREQ 40000000UL /* set it to 0 for system default */ +#define DEF_SPI_FREQ 26000000UL /* set it to 0 for system default */ #endif -#if ENABLE_VU_METER - #if DTYPE==INITR_BLACKTAB #define CLOCK_DELTA 12 #elif DTYPE==INITR_MINI160x80 @@ -26,10 +24,6 @@ #define CLOCK_DELTA 0 #endif -#else // !ENABLE_VU_METER -#define CLOCK_DELTA 0 -#endif - #define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY) #define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl) @@ -133,9 +127,9 @@ void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { initR(DTYPE); if(DEF_SPI_FREQ > 0) setSPISpeed(DEF_SPI_FREQ); cp437(true); - invertDisplay((DTYPE==INITR_MINI160x80)?TFT_INVERT:!TFT_INVERT); + invert(); fillScreen(TFT_BG); - setRotation(TFT_ROTATE); + flip(); setTextWrap(false); screenwidth = width(); screenheight = height(); @@ -270,15 +264,16 @@ void DspCore::printClock(struct tm timeinfo, bool dots, bool redraw){ char timeBuf[50] = { 0 }; char tmpBuf[4] = { 0 }; uint16_t ncwidth, ncheight; + uint16_t clockdelta=config.store.vumeter?CLOCK_DELTA:0; strftime(timeBuf, sizeof(timeBuf), "%H %M", &timeinfo); setTextSize(1); setFont(&DS_DIGI28pt7b); if(strstr(oldTimeBuf, timeBuf)==NULL || redraw){ getTextBounds(oldTimeBuf, 0, 0, &x, &y, &wot, &hot); - setCursor((swidth - wot) / 2 - 4 + CLOCK_DELTA, clockY+28+6); + setCursor((swidth - wot) / 2 - 4 + clockdelta, clockY+28+6); setTextColor(TFT_BG); print(oldTimeBuf); - dot = (swidth - wot) / 2 - 4 + CLOCK_DELTA; + dot = (swidth - wot) / 2 - 4 + clockdelta; /* dots */ strlcpy(tmpBuf, oldTimeBuf, 3); getTextBounds(tmpBuf, 0, 0, &x, &y, &ncwidth, &ncheight); @@ -291,8 +286,8 @@ void DspCore::printClock(struct tm timeinfo, bool dots, bool redraw){ setTextSize(1); getTextBounds(timeBuf, 0, 0, &x, &y, &ncwidth, &ncheight); setTextColor(TFT_LOGO); - setCursor((swidth - ncwidth) / 2 - 4 + CLOCK_DELTA, clockY+28+6); - dot = (swidth - ncwidth) / 2 - 4 + CLOCK_DELTA; + setCursor((swidth - ncwidth) / 2 - 4 + clockdelta, clockY+28+6); + dot = (swidth - ncwidth) / 2 - 4 + clockdelta; setTextSize(1); print(timeBuf); /* dots */ @@ -406,5 +401,15 @@ void DspCore::printText(const char* txt) { void DspCore::loop(bool force) { } +void DspCore::flip(){ + if(ROTATE_90){ + setRotation(config.store.flipscreen?2:0); + }else{ + setRotation(config.store.flipscreen?3:1); + } +} +void DspCore::invert(){ + invertDisplay((DTYPE==INITR_MINI160x80)?!config.store.invertdisplay:config.store.invertdisplay); +} #endif diff --git a/yoRadio/src/displays/displayST7735.h b/yoRadio/src/displays/displayST7735.h index c17966a..eb141e4 100644 --- a/yoRadio/src/displays/displayST7735.h +++ b/yoRadio/src/displays/displayST7735.h @@ -6,6 +6,9 @@ #include #include "fonts/DS_DIGI28pt7b.h" +#define VU_READY 1 +#define WEATHER_READY 1 + #define TFT_LINEHGHT 10 #if DTYPE==INITR_MINI160x80 #define TFT_FRAMEWDT 0 @@ -69,6 +72,8 @@ class DspCore: public Adafruit_ST7735 { void loop(bool force=false); virtual void startWrite(void); virtual void endWrite(void); + void flip(); + void invert(); private: uint16_t swidth, sheight; char oldTimeBuf[20]; diff --git a/yoRadio/src/displays/displayST7789.cpp b/yoRadio/src/displays/displayST7789.cpp index c5cc37e..12be91b 100644 --- a/yoRadio/src/displays/displayST7789.cpp +++ b/yoRadio/src/displays/displayST7789.cpp @@ -117,10 +117,10 @@ void DspCore::apScreen() { void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { init(240,(DSP_MODEL==DSP_ST7789)?320:240); if(DEF_SPI_FREQ > 0) setSPISpeed(DEF_SPI_FREQ); - invertDisplay(TFT_INVERT); + invert(); cp437(true); fillScreen(TFT_BG); - setRotation(TFT_ROTATE); + flip(); setTextWrap(false); setTextSize(1); screenwidth = width(); @@ -382,5 +382,20 @@ void DspCore::printText(const char* txt) { void DspCore::loop(bool force) { } - +void DspCore::flip(){ +#if DSP_MODEL==DSP_ST7789 + setRotation(config.store.flipscreen?3:1); +#endif +#if DSP_MODEL==DSP_ST7789_240 + if(ROTATE_90){ + setRotation(config.store.flipscreen?3:1); + }else{ + setRotation(config.store.flipscreen?2:0); + } +#endif +} + +void DspCore::invert(){ + invertDisplay(config.store.invertdisplay); +} #endif diff --git a/yoRadio/src/displays/displayST7789.h b/yoRadio/src/displays/displayST7789.h index 1c5b0aa..331600c 100644 --- a/yoRadio/src/displays/displayST7789.h +++ b/yoRadio/src/displays/displayST7789.h @@ -7,6 +7,9 @@ // https://tchapi.github.io/Adafruit-GFX-Font-Customiser/ #include "fonts/DS_DIGI42pt7b.h" +#define VU_READY 1 +#define WEATHER_READY 1 + #define TFT_LINEHGHT 10 #define TFT_FRAMEWDT 8 #define META_SIZE 3 @@ -58,6 +61,8 @@ class DspCore: public Adafruit_ST7789 { void loop(bool force=false); virtual void startWrite(void); virtual void endWrite(void); + void flip(); + void invert(); private: uint16_t swidth, sheight; char oldTimeBuf[20]; diff --git a/yoRadio/src/displays/nextion.cpp b/yoRadio/src/displays/nextion.cpp index f04de3b..5d55817 100644 --- a/yoRadio/src/displays/nextion.cpp +++ b/yoRadio/src/displays/nextion.cpp @@ -320,12 +320,22 @@ void Nextion::loop() { } if (sscanf(rxbuf, "tzhour=%d", &scanDigit) == 1){ config.setTimezone((int8_t)scanDigit, config.store.tzMin); - configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), SNTP_SERVER); + //configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), SNTP_SERVER); + if(strlen(config.store.sntp1)>0 && strlen(config.store.sntp2)>0){ + configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2); + }else if(strlen(config.store.sntp1)>0){ + configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1); + } network.requestTimeSync(true); } if (sscanf(rxbuf, "tzmin=%d", &scanDigit) == 1){ config.setTimezone(config.store.tzHour, (int8_t)scanDigit); - configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), SNTP_SERVER); + //configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), SNTP_SERVER); + if(strlen(config.store.sntp1)>0 && strlen(config.store.sntp2)>0){ + configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2); + }else if(strlen(config.store.sntp1)>0){ + configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1); + } network.requestTimeSync(true); } if (sscanf(rxbuf, "audioinfo=%d", &scanDigit) == 1){ @@ -558,7 +568,7 @@ bool Nextion::getForecast(){ return false; } char httpget[250] = {0}; - sprintf(httpget, "GET /data/2.5/weather?lat=%s&lon=%s&units=metric&lang=ru&appid=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", NEXTION_WEATHER_LAT, NEXTION_WEATHER_LON, NEXTION_WEATHER_KEY, host); + sprintf(httpget, "GET /data/2.5/weather?lat=%s&lon=%s&units=metric&lang=ru&appid=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", config.store.weatherlat, config.store.weatherlon, config.store.weatherkey, host); client.print(httpget); unsigned long timeout = millis(); while (client.available() == 0) { @@ -684,6 +694,10 @@ void Nextion::getWeather(void * pvParameters){ } void Nextion::updateWeather() { + if(strlen(config.store.weatherkey)==0 || !config.store.showweather) { + nextion.weatherVisible(0); + return; + } xTaskCreatePinnedToCore( nextion.getWeather, /* Task function. */ "nextiongetWeather", /* name of task. */ @@ -691,15 +705,11 @@ void Nextion::updateWeather() { NULL, /* parameter of the task */ 0, /* priority of the task */ &nextion.weatherUpdateTaskHandle, /* Task handle to keep track of created task */ - 0); /* pin task to core CORE_FOR_LOOP_CONTROLS */ + 0); /* pin task to core 0 */ } void Nextion::startWeather(){ - if(strlen(NEXTION_WEATHER_KEY)==0) { - Serial.println("## OPENWEATHERMAP ###: ERROR: NEXTION_WEATHER_KEY not configured"); - return; - } - updateWeather(); /* pin task to core CORE_FOR_LOOP_CONTROLS */ + updateWeather(); } /*