From 223bae19234abb37b855e54da064136faaf47f47 Mon Sep 17 00:00:00 2001 From: e2002 Date: Mon, 22 Aug 2022 11:50:48 +0300 Subject: [PATCH] v0.7.402 --- README.md | 11 +++ exsamples/mytheme.h | 47 ++++++++++ exsamples/plugins/deepsleep.ino | 35 ++++--- exsamples/plugins/displayhandlers.ino | 8 +- exsamples/plugins/rssibitrate.ino | 4 +- yoRadio/config.cpp | 57 +++++++++++- yoRadio/config.h | 28 +++++- yoRadio/data/www/script.js.gz | Bin 5112 -> 5125 bytes yoRadio/data/www/settings.html | 6 +- yoRadio/display.cpp | 32 +++++-- yoRadio/display.h | 7 ++ yoRadio/display_vu.h | 42 +++++---- yoRadio/netserver.cpp | 13 ++- yoRadio/netserver.h | 2 +- yoRadio/options.h | 87 +++++++++++++++++- yoRadio/src/ILI9225Fix/TFT_22_ILI9225Fix.cpp | 4 +- yoRadio/src/ILI9225Fix/TFT_22_ILI9225Fix.h | 2 +- yoRadio/src/displays/displayGC9106.cpp | 50 +++++----- yoRadio/src/displays/displayGC9106.h | 7 +- yoRadio/src/displays/displayILI9225.cpp | 91 +++++++++++-------- yoRadio/src/displays/displayILI9225.h | 40 +------- yoRadio/src/displays/displayILI9341.cpp | 87 +++++++++--------- yoRadio/src/displays/displayILI9341.h | 38 +------- yoRadio/src/displays/displayLC1602.cpp | 17 ++++ yoRadio/src/displays/displayLC1602.h | 4 +- yoRadio/src/displays/displayN5110.cpp | 11 +++ yoRadio/src/displays/displayN5110.h | 5 + yoRadio/src/displays/displaySH1106.cpp | 10 ++ yoRadio/src/displays/displaySH1106.h | 4 + yoRadio/src/displays/displaySSD1305.cpp | 6 ++ yoRadio/src/displays/displaySSD1305.h | 2 + yoRadio/src/displays/displaySSD1306.cpp | 11 +++ yoRadio/src/displays/displaySSD1306.h | 5 + yoRadio/src/displays/displaySSD1327.cpp | 24 ++++- yoRadio/src/displays/displaySSD1327.h | 3 + yoRadio/src/displays/displayST7735.cpp | 69 +++++++------- yoRadio/src/displays/displayST7735.h | 36 +------- yoRadio/src/displays/displayST7789.cpp | 81 +++++++++-------- yoRadio/src/displays/displayST7789.h | 38 +------- 39 files changed, 644 insertions(+), 380 deletions(-) create mode 100644 exsamples/mytheme.h diff --git a/README.md b/README.md index 692c30c5..e97908e4 100644 --- a/README.md +++ b/README.md @@ -317,6 +317,17 @@ Work is in progress... --- ## Version history +#### v0.7.402 +**!!! 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 themize color displays. Details in [exsamples/mytheme.h](exsamples/mytheme.h) +- in this connection, examples of plugins displayhandlers.ino and rssibitrate.ino have been updated +- parameter VU_PARAMS2 is deprecated. New parameter - VU_PARAMS3. Details in [yoRadio/display_vu.h](yoRadio/display_vu.h) +- added deepsleep capability for LCD_I2C and OLED displays +- in this connection, a full update with Sketch data upload is required +- in this connection, example of plugi deepsleep.ino (exsamples/plugins/deepsleep.ino) have been updated +- some bug fixes + #### v0.7.355 - updating libraries ESP32-audioI2S and ESP32-vs1053_ext to the latest version - optimization of the web interface during playback diff --git a/exsamples/mytheme.h b/exsamples/mytheme.h new file mode 100644 index 00000000..cdb7fcdd --- /dev/null +++ b/exsamples/mytheme.h @@ -0,0 +1,47 @@ +#ifndef _my_theme_h +#define _my_theme_h + +/* + Theming of color displays + DSP_ST7735, DSP_ST7789, DSP_ILI9341, DSP_GC9106, DSP_ILI9225, DSP_ST7789_240 + *********************************************************************** + * !!! This file must be in the root directory of the sketch !!! * + *********************************************************************** + Uncomment (remove double slash //) from desired line to apply color +*/ +#define ENABLE_THEME +#ifdef ENABLE_THEME + +/*----------------------------------------------------------------------------------------------------------------*/ +/* | COLORS | values (0-255) | */ +/* | color name | R G B | */ +/*----------------------------------------------------------------------------------------------------------------*/ +//#define COLOR_BACKGROUND 255, 255, 0 /* background */ +//#define COLOR_STATION_NAME 91, 118, 255 /* station name */ +//#define COLOR_SNG_TITLE_1 255, 0, 0 /* first title */ +//#define COLOR_SNG_TITLE_2 0, 0, 0 /* second title */ +//#define COLOR_WEATHER 255, 0, 216 /* weather string */ +//#define COLOR_VU_MAX 152, 138, 138 /* max of VU meter */ +//#define COLOR_VU_MIN 250, 130, 130 /* min of VU meter */ +//#define COLOR_CLOCK 60, 224, 33 /* clock color */ +//#define COLOR_SECONDS 0, 255, 255 /* seconds color (DSP_ST7789, DSP_ILI9341, DSP_ILI9225) */ +//#define COLOR_DAY_OF_W 255, 0, 0 /* day of week color (DSP_ST7789, DSP_ILI9341, DSP_ILI9225) */ +//#define COLOR_DATE 0, 0, 255 /* date color (DSP_ST7789, DSP_ILI9341, DSP_ILI9225) */ +//#define COLOR_HEAP 255, 168, 162 /* heap string */ +//#define COLOR_BUFFER 157, 171, 251 /* buffer line */ +//#define COLOR_IP 41, 189, 207 /* ip address */ +//#define COLOR_VOLUME_VALUE 165, 162, 132 /* volume string (DSP_ST7789, DSP_ILI9341, DSP_ILI9225) */ +//#define COLOR_RSSI 255, 148, 156 /* rssi */ +//#define COLOR_VOLBAR_OUT 198, 93, 0 /* volume bar outline */ +//#define COLOR_VOLBAR_IN 189, 189, 189 /* volume bar fill */ +//#define COLOR_DIGITS 100, 100, 255 /* volume / station number */ +//#define COLOR_DIVIDER 0, 255, 0 /* divider color (DSP_ST7789, DSP_ILI9341, DSP_ILI9225) */ +//#define COLOR_PLAYLIST_0 255, 0, 0 /* playlist string 0 */ +//#define COLOR_PLAYLIST_1 0, 255, 0 /* playlist string 1 */ +//#define COLOR_PLAYLIST_2 255, 0, 255 /* playlist string 2 */ +//#define COLOR_PLAYLIST_3 0, 0, 255 /* playlist string 3 */ +//#define COLOR_PLAYLIST_4 0, 255, 255 /* playlist string 4 */ + + +#endif /* #ifdef ENABLE_THEME */ +#endif /* #define _my_theme_h */ diff --git a/exsamples/plugins/deepsleep.ino b/exsamples/plugins/deepsleep.ino index 93c87d1f..8fa788a1 100644 --- a/exsamples/plugins/deepsleep.ino +++ b/exsamples/plugins/deepsleep.ino @@ -1,29 +1,36 @@ -/************************************************************** +/****************************************************************************************************************** Example of esp32 deep sleep when playback is stopped. This file must be in the root directory of the sketch. -**************************************************************/ -#define SLEEP_DELAY 60 // 1 min -#define WAKEUP_PIN_1 GPIO_NUM_12 -#define WAKEUP_LEVEL LOW +*******************************************************************************************************************/ +#define SLEEP_DELAY 60 /* 1 min deep sleep delay */ +#define WAKEUP_PIN ENC_BTNB /* wakeup pin (one of: BTN_XXXX, ENC_BTNB, ENC2_BTNB) */ + /* must be one of: 0,2,4,12,13,14,15,25,26,27,32,33,34,35,36,39 */ +#define WAKEUP_LEVEL LOW /* wakeup level (usually LOW) */ +#if WAKEUP_PIN!=255 Ticker deepSleepTicker; void goToSleep(){ - if(BRIGHTNESS_PIN!=255) analogWrite(BRIGHTNESS_PIN, 0); /* BRIGHTNESS_PIN added in v0.7.330 */ - esp_deep_sleep_start(); + if(BRIGHTNESS_PIN!=255) analogWrite(BRIGHTNESS_PIN, 0); /* BRIGHTNESS_PIN added in v0.7.330 */ + if(display.deepsleep()) { /* if deep sleep is possible */ + esp_deep_sleep_start(); /* go to sleep */ + }else{ /* else */ + deepSleepTicker.detach(); /* detach the timer */ + } } -void yoradio_on_setup(){ - esp_sleep_enable_ext0_wakeup(WAKEUP_PIN_1, WAKEUP_LEVEL); - deepSleepTicker.attach(SLEEP_DELAY, goToSleep); +void yoradio_on_setup(){ /* occurs during loading */ + esp_sleep_enable_ext0_wakeup((gpio_num_t)WAKEUP_PIN, WAKEUP_LEVEL); /* enable wakeup pin */ + deepSleepTicker.attach(SLEEP_DELAY, goToSleep); /* attach to delay */ } -void player_on_start_play(){ - deepSleepTicker.detach(); +void player_on_start_play(){ /* occurs during player is start playing */ + deepSleepTicker.detach(); /* detach the timer */ } -void player_on_stop_play(){ - deepSleepTicker.attach(SLEEP_DELAY, goToSleep); +void player_on_stop_play(){ /* occurs during player is stop playing */ + deepSleepTicker.attach(SLEEP_DELAY, goToSleep); /* attach to delay */ } +#endif /* #if WAKEUP_PIN!=255 */ diff --git a/exsamples/plugins/displayhandlers.ino b/exsamples/plugins/displayhandlers.ino index a7f0f022..9e410b2f 100644 --- a/exsamples/plugins/displayhandlers.ino +++ b/exsamples/plugins/displayhandlers.ino @@ -157,11 +157,11 @@ void dsp_on_start(DspCore *dsp) { ***********************************************/ void dsp_on_init() { if (DSP_MODEL == DSP_ST7735 || (DSP_MODEL == DSP_SSD1327)) { - hello.init(5, " * ", 1, TFT_LINEHGHT * 4 + 6, 0, ORANGE, TFT_BG); + hello.init(5, " * ", 1, TFT_LINEHGHT * 4 + 6, 0, config.theme.weather, config.theme.background); }else if(DSP_MODEL == DSP_ILI9225){ - hello.init(5, " * ", 1, TFT_LINEHGHT * 6 + 5, 0, ORANGE, TFT_BG); + hello.init(5, " * ", 1, TFT_LINEHGHT * 6 + 5, 0, config.theme.weather, config.theme.background); } else { - hello.init(5, " * ", 2, TFT_LINEHGHT * 9 + 5, 0, ORANGE, TFT_BG); + hello.init(5, " * ", 2, TFT_LINEHGHT * 9 + 5, 0, config.theme.weather, config.theme.background); } } @@ -194,7 +194,7 @@ bool dsp_before_clock(DspCore *dsp, bool dots) { if (display.mode == PLAYER) { dsp->setFont(); dsp->setTextSize(1); - display.centerText(dsp->utf8Rus("Hello from plugin!", true), display.screenheight - TFT_FRAMEWDT * 2 - TFT_LINEHGHT * 2 - 2, PINK, TFT_BG); + display.centerText(dsp->utf8Rus("Hello from plugin!", true), display.screenheight - TFT_FRAMEWDT * 2 - TFT_LINEHGHT * 2 - 2, 0xF97F, config.theme.background); } return true; // false, if you need to disable the drawing of the clock } diff --git a/exsamples/plugins/rssibitrate.ino b/exsamples/plugins/rssibitrate.ino index ff907a7b..37b1b2eb 100644 --- a/exsamples/plugins/rssibitrate.ino +++ b/exsamples/plugins/rssibitrate.ino @@ -16,7 +16,7 @@ bool dsp_before_rssi(DspCore *dsp){ sprintf(buf, "RSSI:000dBm"); dsp->setTextSize(1); dsp->getTextBounds(buf, 0, 0, &x1, &y1, &w, &h); - dsp->fillRect(dsp->width() - w - TFT_FRAMEWDT /* left */, vTop /* top */, w /* width */, TFT_LINEHGHT-2 /* height */, TFT_BG /* background color */); + dsp->fillRect(dsp->width() - w - TFT_FRAMEWDT /* left */, vTop /* top */, w /* width */, TFT_LINEHGHT-2 /* height */, config.theme.background /* background color */); sprintf(buf, "%dkBits", config.station.bitrate); dsp->getTextBounds(buf, 0, 0, &x1, &y1, &w, &h); if(cnt<2){ @@ -25,7 +25,7 @@ bool dsp_before_rssi(DspCore *dsp){ } cnt++; if(cnt>3) cnt=0; - dsp->setTextColor(SILVER,TFT_BG); + dsp->setTextColor(config.theme.rssi,config.theme.background); dsp->setCursor(dsp->width() - w - TFT_FRAMEWDT, vTop); dsp->print(buf); /* print bitrate */ return false; /* disable to print RSSI */ diff --git a/yoRadio/config.cpp b/yoRadio/config.cpp index 8f3a90d4..4fae0dd1 100644 --- a/yoRadio/config.cpp +++ b/yoRadio/config.cpp @@ -28,6 +28,7 @@ void Config::init() { if (!SPIFFS.begin(false)) { return; } + loadTheme(); ssidsCount = 0; initPlaylist(); if (store.lastStation == 0 && store.countStation > 0) { @@ -48,6 +49,39 @@ void Config::init() { #endif } +uint16_t Config::color565(uint8_t r, uint8_t g, uint8_t b) +{ + return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); +} + +void Config::loadTheme(){ + theme.background = color565(COLOR_BACKGROUND); + theme.meta = color565(COLOR_STATION_NAME); + theme.title1 = color565(COLOR_SNG_TITLE_1); + theme.title2 = color565(COLOR_SNG_TITLE_2); + theme.digit = color565(COLOR_DIGITS); + theme.div = color565(COLOR_DIVIDER); + theme.weather = color565(COLOR_WEATHER); + theme.vumax = color565(COLOR_VU_MAX); + theme.vumin = color565(COLOR_VU_MIN); + theme.clock = color565(COLOR_CLOCK); + theme.seconds = color565(COLOR_SECONDS); + theme.dow = color565(COLOR_DAY_OF_W); + theme.date = color565(COLOR_DATE); + theme.heap = color565(COLOR_HEAP); + theme.buffer = color565(COLOR_BUFFER); + theme.ip = color565(COLOR_IP); + theme.vol = color565(COLOR_VOLUME_VALUE); + theme.rssi = color565(COLOR_RSSI); + theme.volbarout = color565(COLOR_VOLBAR_OUT); + theme.volbarin = color565(COLOR_VOLBAR_IN); + theme.playlist[0] = color565(COLOR_PLAYLIST_0); + theme.playlist[1] = color565(COLOR_PLAYLIST_1); + theme.playlist[2] = color565(COLOR_PLAYLIST_2); + theme.playlist[3] = color565(COLOR_PLAYLIST_3); + theme.playlist[4] = color565(COLOR_PLAYLIST_4); +} + template int Config::eepromWrite(int ee, const T& value) { const byte* p = (const byte*)(const void*)&value; int i; @@ -435,7 +469,28 @@ bool Config::initNetwork() { void Config::setBrightness(bool dosave){ #if BRIGHTNESS_PIN!=255 - analogWrite(BRIGHTNESS_PIN, config.store.dspon?map(store.brightness, 0, 100, 0, 255):0); + if(!store.dspon && dosave) { + display.wakeup(); + } + //analogWrite(BRIGHTNESS_PIN, config.store.dspon?map(store.brightness, 0, 100, 0, 255):0); + analogWrite(BRIGHTNESS_PIN, map(store.brightness, 0, 100, 0, 255)); + if(!store.dspon) store.dspon = true; if(dosave) save(); #endif } + +void Config::setDspOn(bool dspon){ + store.dspon = dspon; + save(); + if(!dspon){ +#if BRIGHTNESS_PIN!=255 + analogWrite(BRIGHTNESS_PIN, 0); +#endif + display.deepsleep(); + }else{ + display.wakeup(); +#if BRIGHTNESS_PIN!=255 + analogWrite(BRIGHTNESS_PIN, map(store.brightness, 0, 100, 0, 255)); +#endif + } +} diff --git a/yoRadio/config.h b/yoRadio/config.h index 7e0946dc..a073d201 100644 --- a/yoRadio/config.h +++ b/yoRadio/config.h @@ -15,6 +15,29 @@ void DBGVB(const char *format, ...); +struct theme_t { + uint16_t background; + uint16_t meta; + uint16_t title1; + uint16_t title2; + uint16_t digit; + uint16_t div; + uint16_t weather; + uint16_t vumax; + uint16_t vumin; + uint16_t clock; + uint16_t seconds; + uint16_t dow; + uint16_t date; + uint16_t heap; + uint16_t buffer; + uint16_t ip; + uint16_t vol; + uint16_t rssi; + uint16_t volbarout; + uint16_t volbarin; + uint16_t playlist[5]; +}; struct config_t { unsigned int config_set; //must be 4262 @@ -92,6 +115,7 @@ class Config { public: config_t store; station_t station; + theme_t theme; #if IR_PIN!=255 int irindex; uint8_t irchck; @@ -106,6 +130,7 @@ class Config { void saveIR(); #endif void init(); + void loadTheme(); byte setVolume(byte val); void saveVolume(); void setTone(int8_t bass, int8_t middle, int8_t trebble); @@ -130,11 +155,12 @@ class Config { void setTimezoneOffset(uint16_t tzo); uint16_t getTimezoneOffset(); void setBrightness(bool dosave=false); - + void setDspOn(bool dspon); private: template int eepromWrite(int ee, const T& value); template int eepromRead(int ee, T& value); void setDefaults(); + uint16_t color565(uint8_t r, uint8_t g, uint8_t b); }; extern Config config; diff --git a/yoRadio/data/www/script.js.gz b/yoRadio/data/www/script.js.gz index 48eedda9dc81e03ee07578c5034bed3d296adfaf..ba3ea9fc124084ca7dc3631bb07b5e11e6d8c15e 100644 GIT binary patch literal 5125 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 literal 5112 zcmVfEdYI6YPJo|IoHj_U)e+7!WmQ*C`;dHJuc9=}! zq?g{MNhWc=-d&RULXnV!ny-+M6*u+&e!F;(AVpG=o6Pj)@~}l>cd=M3_60y!eoj_t zAre1k#3LJ?gz07+rGYPanv4tP=fUbbkJ5+jP2*xcFGS9hr8^s(Hen3qvpZMN&xXy5 zG`M6!KNc*{gG4~LQ}agfn5AnC5Ulf@CE^#sVg++Y)Az&h=@qm*=Y?Pi%Uvf*{m>ba zG<-A6JA?!g@P47Xa?4Hu4Vu!VNFxSASh~(dehmX7 zA|+|Y65^AR5W*!)_Anlg9f?{F5138ZrUG_9Zi>^%|NrrXc)a}ywDMd2@*1o%~bKD%>Mi9(Te8H!E|!XE8;IV3q;7V2T?Y4WD^ z{tA|auCrt!PDAF+5V+QtWYO--5E>2@SuJ+2V8YBrZL&rs#{Jp!;mLG5J)PmtX}u>_ z1b)Vz_`-KX_%Xn)BAA5O!^d&#i(utWzKn+tPu~~Rh2H~uGm%5%3pf7G^OAKGNi>Z( z0}00OW*^SvD+HR2LGjqpUTnF9RCSM)4;NadSugx8Q0+{j^R6^M%OWLWxuZx{gDJq!>sd6%#*57Jl&K z?96GlIl3)Ni|t0L8nL_W#`~%yW2BS)>}$=Zg-=t98r-tR4k-wbo#;I^IOD{bb4h z;YVxchG_tRuwr45Pa}pOA7B3x0#i|uE`*=af#wOGa!sUn+>3~3dk!2y)%wzG;){;) z@Z^f+BIE_myatDN9ni@-HX5Q~@l6LX_A1hKu+pHS=n`r;U)BM`4nQ@k)Ql@EvNSn- z2Ie_mu0#S>*v!H_Kb(rRBt8g2(+EmddgoF6vFez{&b|O8U4y|MUm;JPA#=71E9OZP zDc*rpBqBShBgt2Lpv|_?W_!qE1JT@`>v@%Kw3*lQ54eLJoN0u}7j^bF@McfcG-;xy z$$qGp?7D#pZ}yPM6*#C4p&X!~NJX%$RC0ViT+LY$_(1@(kV{Wwh~ewQiSb-SrRl?m zeO3%Oi4I|4M7hk+{GjiWlIOTq*&n?r@Rj#KoYC%ajRz-S-r!F^qUA zR^*t>;Pr5*;QRkoyE}Zpqc2!D zEnR8(?yLL`P{|R@sa9hn;ju%Y1`9gHZyPZ%a9$MvTpN6_V_*v&ZRZR?aywou!GUBm zj4Rgjmvir`rW`_*IC9+OMdZT=!B1BXK!_AP4@akhqE(Z3y~%uJTceD-|*TNM~JOYt#~2L-P{c4fDj3?FDv>9$9MOp=OMH#2A4O4)2MeS0-=AL4 z5s{)W4bl~8Y)fp)H%Q5qQsdyJiZ*Ln57!{mgBV9}KT>fHqNZz+t%XOaR?Y1YP7?15 z;dlbrg(qQ9KWklI_)FEXgrb$kDlAkwse&kdN(WdI26wb(XQldQKw81hG^~dk0@b@^ zhY}7>8+eMQ8tu?)FfgR=1s!Gu{7$G9%qei(gHUnXZ!C&N$e2@*!oMDoPisH8981!D zntNnV^{ba}V6NMWJRe6QU$Y7xR+uL84AhwAERFS|$D7UO z7^W~jUgwx&faeLRO)bGRiZ8gSJ9>1ez}~+8I^RRRtIr{yBrnv!GweqV`qh zM7#pcqLl(o7Yi8NGlu1vs!`aD7inf%M4G)y3$^8C`dpdER_g#fb=n44=);-kS(|B< zfh~Ii0%$mDtjOgrJFc}>qo_74U=&8auA&W;Pc`{t7%BW;O-_bDZgMixhGij6$y7be z*$R{-%^`LyVo=bPgM=FDmToO0QQjBJ`zHLUr$0fCKl}>0v>uSYWO4EFgxaQ zH}k01KOE*AzNT-eJOfI(P;�frs^(Q&Ek{UcYusj4uiA3u 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 ak_k_=R34!Ov{)MP=l=p@2jl9ZQUCyD{ncau diff --git a/yoRadio/data/www/settings.html b/yoRadio/data/www/settings.html index b7d8a528..cbc32e12 100644 --- a/yoRadio/data/www/settings.html +++ b/yoRadio/data/www/settings.html @@ -42,14 +42,14 @@

SёTTINGS

Firmware update
-