Files
yoradio/yoRadio/src/core/display.cpp
2025-08-29 14:52:33 +03:00

698 lines
22 KiB
C++

#include "Arduino.h"
#include "options.h"
#include "WiFi.h"
#include "time.h"
#include "config.h"
#include "display.h"
#include "player.h"
#include "network.h"
#include "netserver.h"
#include "timekeeper.h"
#include "../pluginsManager/pluginsManager.h"
#include "../displays/dspcore.h"
#include "../displays/widgets/widgets.h"
#include "../displays/widgets/pages.h"
#include "../displays/tools/l10n.h"
Display display;
#ifdef USE_NEXTION
#include "../displays/nextion.h"
Nextion nextion;
#endif
#ifndef CORE_STACK_SIZE
#define CORE_STACK_SIZE 1024*4
#endif
#ifndef DSP_TASK_PRIORITY
#define DSP_TASK_PRIORITY 2
#endif
#ifndef DSP_TASK_CORE_ID
#define DSP_TASK_CORE_ID 0
#endif
#ifndef DSP_TASK_DELAY
#define DSP_TASK_DELAY pdMS_TO_TICKS(10) // cap for 50 fps
#endif
#define DSP_QUEUE_TICKS 0
#ifndef DSQ_SEND_DELAY
//#define DSQ_SEND_DELAY portMAX_DELAY
#define DSQ_SEND_DELAY pdMS_TO_TICKS(200)
#endif
QueueHandle_t displayQueue;
static void loopDspTask(void * pvParameters){
while(true){
#ifndef DUMMYDISPLAY
if(displayQueue==NULL) break;
if(timekeeper.loop0()){
display.loop();
#ifndef NETSERVER_LOOP1
netserver.loop();
#endif
}
#else
timekeeper.loop0();
#ifndef NETSERVER_LOOP1
netserver.loop();
#endif
#endif
vTaskDelay(DSP_TASK_DELAY);
}
vTaskDelete( NULL );
}
void Display::_createDspTask(){
xTaskCreatePinnedToCore(loopDspTask, "DspTask", CORE_STACK_SIZE, NULL, DSP_TASK_PRIORITY, NULL, DSP_TASK_CORE_ID);
}
#ifndef DUMMYDISPLAY
//============================================================================================================================
DspCore dsp;
Page *pages[] = { new Page(), new Page(), new Page(), new Page() };
#if !((DSP_MODEL==DSP_ST7735 && DTYPE==INITR_BLACKTAB) || DSP_MODEL==DSP_ST7789 || DSP_MODEL==DSP_ST7796 || DSP_MODEL==DSP_ILI9488 || DSP_MODEL==DSP_ILI9486 || DSP_MODEL==DSP_ILI9341 || DSP_MODEL==DSP_ILI9225)
#undef BITRATE_FULL
#define BITRATE_FULL false
#endif
void returnPlayer(){
display.putRequest(NEWMODE, PLAYER);
}
Display::~Display() {
delete _pager;
delete _footer;
delete _plwidget;
delete _nums;
delete _clock;
delete _meta;
delete _title1;
delete _title2;
delete _plcurrent;
}
void Display::init() {
Serial.print("##[BOOT]#\tdisplay.init\t");
#ifdef USE_NEXTION
nextion.begin();
#endif
#if LIGHT_SENSOR!=255
analogSetAttenuation(ADC_0db);
#endif
_bootStep = 0;
dsp.initDisplay();
displayQueue=NULL;
displayQueue = xQueueCreate( 5, sizeof( requestParams_t ) );
while(displayQueue==NULL){;}
_createDspTask();
while(!_bootStep==0) { delay(10); }
//_pager.begin();
//_bootScreen();
_pager = new Pager();
_footer = new Page();
_plwidget = new PlayListWidget();
_nums = new NumWidget();
_clock = new ClockWidget();
_meta = new ScrollWidget();
_title1 = new ScrollWidget();
_plcurrent = new ScrollWidget();
Serial.println("done");
}
uint16_t Display::width(){ return dsp.width(); }
uint16_t Display::height(){ return dsp.height(); }
#if TIME_SIZE>19
#if DSP_MODEL==DSP_SSD1322
#define BOOT_PRG_COLOR WHITE
#define BOOT_TXT_COLOR WHITE
#define PINK WHITE
#elif DSP_MODEL==DSP_SSD1327
#define BOOT_PRG_COLOR 0x07
#define BOOT_TXT_COLOR 0x3f
#define PINK 0x02
#else
#define BOOT_PRG_COLOR 0xE68B
#define BOOT_TXT_COLOR 0xFFFF
#define PINK 0xF97F
#endif
#endif
void Display::_bootScreen(){
_boot = new Page();
_boot->addWidget(new ProgressWidget(bootWdtConf, bootPrgConf, BOOT_PRG_COLOR, 0));
_bootstring = (TextWidget*) &_boot->addWidget(new TextWidget(bootstrConf, 50, true, BOOT_TXT_COLOR, 0));
_pager->addPage(_boot);
_pager->setPage(_boot, true);
dsp.drawLogo(bootLogoTop);
_bootStep = 1;
}
void Display::_buildPager(){
_meta->init("*", metaConf, config.theme.meta, config.theme.metabg);
_title1->init("*", title1Conf, config.theme.title1, config.theme.background);
_clock->init(clockConf, 0, 0);
#if DSP_MODEL==DSP_NOKIA5110
_plcurrent->init("*", playlistConf, 0, 1);
#else
_plcurrent->init("*", playlistConf, config.theme.plcurrent, config.theme.plcurrentbg);
#endif
_plwidget->init(_plcurrent);
#if !defined(DSP_LCD)
_plcurrent->moveTo({TFT_FRAMEWDT, (uint16_t)(_plwidget->currentTop()), (int16_t)playlistConf.width});
#endif
#ifndef HIDE_TITLE2
_title2 = new ScrollWidget("*", title2Conf, config.theme.title2, config.theme.background);
#endif
#if !defined(DSP_LCD) && DSP_MODEL!=DSP_NOKIA5110
_plbackground = new FillWidget(playlBGConf, config.theme.plcurrentfill);
#if DSP_INVERT_TITLE || defined(DSP_OLED)
_metabackground = new FillWidget(metaBGConf, config.theme.metafill);
#else
_metabackground = new FillWidget(metaBGConfInv, config.theme.metafill);
#endif
#endif
#if DSP_MODEL==DSP_NOKIA5110
_plbackground = new FillWidget(playlBGConf, 1);
//_metabackground = new FillWidget(metaBGConf, 1);
#endif
#ifndef HIDE_VU
_vuwidget = new VuWidget(vuConf, bandsConf, config.theme.vumax, config.theme.vumin, config.theme.background);
#endif
#ifndef HIDE_VOLBAR
_volbar = new SliderWidget(volbarConf, config.theme.volbarin, config.theme.background, 254, config.theme.volbarout);
#endif
#ifndef HIDE_HEAPBAR
_heapbar = new SliderWidget(heapbarConf, config.theme.buffer, config.theme.background, psramInit()?300000:1600 * config.store.abuff);
#endif
#ifndef HIDE_VOL
_voltxt = new TextWidget(voltxtConf, 10, false, config.theme.vol, config.theme.background);
#endif
#ifndef HIDE_IP
_volip = new TextWidget(iptxtConf, 30, false, config.theme.ip, config.theme.background);
#endif
#ifndef HIDE_RSSI
_rssi = new TextWidget(rssiConf, 20, false, config.theme.rssi, config.theme.background);
#endif
_nums->init(numConf, 10, false, config.theme.digit, config.theme.background);
#ifndef HIDE_WEATHER
_weather = new ScrollWidget("\007", weatherConf, config.theme.weather, config.theme.background);
#endif
if(_volbar) _footer->addWidget( _volbar);
if(_voltxt) _footer->addWidget( _voltxt);
if(_volip) _footer->addWidget( _volip);
if(_rssi) _footer->addWidget( _rssi);
if(_heapbar) _footer->addWidget( _heapbar);
if(_metabackground) pages[PG_PLAYER]->addWidget( _metabackground);
pages[PG_PLAYER]->addWidget(_meta);
pages[PG_PLAYER]->addWidget(_title1);
if(_title2) pages[PG_PLAYER]->addWidget(_title2);
if(_weather) pages[PG_PLAYER]->addWidget(_weather);
#if BITRATE_FULL
_fullbitrate = new BitrateWidget(fullbitrateConf, config.theme.bitrate, config.theme.background);
pages[PG_PLAYER]->addWidget( _fullbitrate);
#else
_bitrate = new TextWidget(bitrateConf, 30, false, config.theme.bitrate, config.theme.background);
pages[PG_PLAYER]->addWidget( _bitrate);
#endif
if(_vuwidget) pages[PG_PLAYER]->addWidget( _vuwidget);
pages[PG_PLAYER]->addWidget(_clock);
pages[PG_SCREENSAVER]->addWidget(_clock);
pages[PG_PLAYER]->addPage(_footer);
if(_metabackground) pages[PG_DIALOG]->addWidget( _metabackground);
pages[PG_DIALOG]->addWidget(_meta);
pages[PG_DIALOG]->addWidget(_nums);
#if !defined(DSP_LCD) && DSP_MODEL!=DSP_NOKIA5110
pages[PG_DIALOG]->addPage(_footer);
#endif
#if !defined(DSP_LCD)
if(_plbackground) {
pages[PG_PLAYLIST]->addWidget( _plbackground);
_plbackground->setHeight(_plwidget->itemHeight());
_plbackground->moveTo({0,(uint16_t)(_plwidget->currentTop()-playlistConf.widget.textsize*2), (int16_t)playlBGConf.width});
}
#endif
pages[PG_PLAYLIST]->addWidget(_plcurrent);
pages[PG_PLAYLIST]->addWidget(_plwidget);
for(const auto& p: pages) _pager->addPage(p);
}
void Display::_apScreen() {
if(_boot) _pager->removePage(_boot);
#ifndef DSP_LCD
_boot = new Page();
#if DSP_MODEL!=DSP_NOKIA5110
#if DSP_INVERT_TITLE || defined(DSP_OLED)
_boot->addWidget(new FillWidget(metaBGConf, config.theme.metafill));
#else
_boot->addWidget(new FillWidget(metaBGConfInv, config.theme.metafill));
#endif
#endif
ScrollWidget *bootTitle = (ScrollWidget*) &_boot->addWidget(new ScrollWidget("*", apTitleConf, config.theme.meta, config.theme.metabg));
bootTitle->setText("ёRadio AP Mode");
TextWidget *apname = (TextWidget*) &_boot->addWidget(new TextWidget(apNameConf, 30, false, config.theme.title1, config.theme.background));
apname->setText(LANG::apNameTxt);
TextWidget *apname2 = (TextWidget*) &_boot->addWidget(new TextWidget(apName2Conf, 30, false, config.theme.clock, config.theme.background));
apname2->setText(apSsid);
TextWidget *appass = (TextWidget*) &_boot->addWidget(new TextWidget(apPassConf, 30, false, config.theme.title1, config.theme.background));
appass->setText(LANG::apPassTxt);
TextWidget *appass2 = (TextWidget*) &_boot->addWidget(new TextWidget(apPass2Conf, 30, false, config.theme.clock, config.theme.background));
appass2->setText(apPassword);
ScrollWidget *bootSett = (ScrollWidget*) &_boot->addWidget(new ScrollWidget("*", apSettConf, config.theme.title2, config.theme.background));
bootSett->setText(config.ipToStr(WiFi.softAPIP()), LANG::apSettFmt);
_pager->addPage(_boot);
_pager->setPage(_boot);
#else
dsp.apScreen();
#endif
}
void Display::_start() {
if(_boot) _pager->removePage(_boot);
#ifdef USE_NEXTION
nextion.wake();
#endif
if (network.status != CONNECTED && network.status != SDREADY) {
_apScreen();
#ifdef USE_NEXTION
nextion.apScreen();
#endif
_bootStep = 2;
return;
}
#ifdef USE_NEXTION
//nextion.putcmd("page player");
nextion.start();
#endif
_buildPager();
_mode = PLAYER;
config.setTitle(LANG::const_PlReady);
if(_heapbar) _heapbar->lock(!config.store.audioinfo);
if(_weather) _weather->lock(!config.store.showweather);
if(_weather && config.store.showweather) _weather->setText(LANG::const_getWeather);
if(_vuwidget) _vuwidget->lock();
if(_rssi) _setRSSI(WiFi.RSSI());
#ifndef HIDE_IP
if(_volip) _volip->setText(config.ipToStr(WiFi.localIP()), iptxtFmt);
#endif
_pager->setPage( pages[PG_PLAYER]);
_volume();
_station();
_time(false);
_bootStep = 2;
pm.on_display_player();
}
void Display::_showDialog(const char *title){
dsp.setScrollId(NULL);
_pager->setPage( pages[PG_DIALOG]);
#ifdef META_MOVE
_meta->moveTo(metaMove);
#endif
_meta->setAlign(WA_CENTER);
_meta->setText(title);
}
void Display::_swichMode(displayMode_e newmode) {
#ifdef USE_NEXTION
//nextion.swichMode(newmode);
nextion.putRequest({NEWMODE, newmode});
#endif
if (newmode == _mode || (network.status != CONNECTED && network.status != SDREADY)) return;
_mode = newmode;
dsp.setScrollId(NULL);
if (newmode == PLAYER) {
if(player.isRunning())
if(clockMove.width<0) _clock->moveBack(); else _clock->moveTo(clockMove);
else
_clock->moveBack();
#ifdef DSP_LCD
dsp.clearDsp();
#endif
numOfNextStation = 0;
#ifdef META_MOVE
_meta->moveBack();
#endif
_meta->setAlign(metaConf.widget.align);
_meta->setText(config.station.name);
_nums->setText("");
config.isScreensaver = false;
_pager->setPage( pages[PG_PLAYER]);
config.setDspOn(config.store.dspon, false);
pm.on_display_player();
}
if (newmode == SCREENSAVER || newmode == SCREENBLANK) {
config.isScreensaver = true;
_pager->setPage( pages[PG_SCREENSAVER]);
if (newmode == SCREENBLANK) {
//dsp.clearClock();
_clock->clear();
config.setDspOn(false, false);
}
}else{
config.screensaverTicks=SCREENSAVERSTARTUPDELAY;
config.screensaverPlayingTicks=SCREENSAVERSTARTUPDELAY;
config.isScreensaver = false;
}
if (newmode == VOL) {
#ifndef HIDE_IP
_showDialog(LANG::const_DlgVolume);
#else
_showDialog(config.ipToStr(WiFi.localIP()));
#endif
_nums->setText(config.store.volume, numtxtFmt);
}
if (newmode == LOST) _showDialog(LANG::const_DlgLost);
if (newmode == UPDATING) _showDialog(LANG::const_DlgUpdate);
if (newmode == SLEEPING) _showDialog("SLEEPING");
if (newmode == SDCHANGE) _showDialog(LANG::const_waitForSD);
if (newmode == INFO || newmode == SETTINGS || newmode == TIMEZONE || newmode == WIFI) _showDialog(LANG::const_DlgNextion);
if (newmode == NUMBERS) _showDialog("");
if (newmode == STATIONS) {
_pager->setPage( pages[PG_PLAYLIST]);
_plcurrent->setText("");
currentPlItem = config.lastStation();
_drawPlaylist();
}
}
void Display::resetQueue(){
if(displayQueue!=NULL) xQueueReset(displayQueue);
}
void Display::_drawPlaylist() {
//dsp.drawPlaylist(currentPlItem);
_plwidget->drawPlaylist(currentPlItem);
timekeeper.waitAndReturnPlayer(30);
}
void Display::_drawNextStationNum(uint16_t num) {
timekeeper.waitAndReturnPlayer(30);
_meta->setText(config.stationByNum(num));
_nums->setText(num, "%d");
}
void Display::putRequest(displayRequestType_e type, int payload){
if(displayQueue==NULL) return;
requestParams_t request;
request.type = type;
request.payload = payload;
xQueueSend(displayQueue, &request, DSQ_SEND_DELAY);
#ifdef USE_NEXTION
nextion.putRequest(request);
#endif
}
void Display::_layoutChange(bool played){
if(config.store.vumeter && _vuwidget){
if(played){
if(_vuwidget) _vuwidget->unlock();
//_clock->moveTo(clockMove);
if(clockMove.width<0) _clock->moveBack(); else _clock->moveTo(clockMove);
if(_weather) _weather->moveTo(weatherMoveVU);
}else{
if(_vuwidget) if(!_vuwidget->locked()) _vuwidget->lock();
_clock->moveBack();
if(_weather) _weather->moveBack();
}
}else{
if(played){
if(clockMove.width<0) _clock->moveBack(); else _clock->moveTo(clockMove);
if(_weather) _weather->moveTo(weatherMove);
//_clock->moveBack();
}else{
if(_weather) _weather->moveBack();
_clock->moveBack();
}
}
}
void Display::loop() {
if(_bootStep==0) {
_pager->begin();
_bootScreen();
return;
}
if(displayQueue==NULL || _locked) return;
_pager->loop();
#ifdef USE_NEXTION
nextion.loop();
#endif
requestParams_t request;
if(xQueueReceive(displayQueue, &request, DSP_QUEUE_TICKS)){
bool pm_result = true;
pm.on_display_queue(request, pm_result);
if(pm_result)
switch (request.type){
case NEWMODE: _swichMode((displayMode_e)request.payload); break;
case CLOSEPLAYLIST: player.sendCommand({PR_PLAY, request.payload});
case CLOCK:
if(_mode==PLAYER || _mode==SCREENSAVER) _time();
/*#ifdef USE_NEXTION
if(_mode==TIMEZONE) nextion.localTime(network.timeinfo);
if(_mode==INFO) nextion.rssi();
#endif*/
break;
case NEWTITLE: _title(); break;
case NEWSTATION: _station(); break;
case NEXTSTATION: _drawNextStationNum(request.payload); break;
case DRAWPLAYLIST: _drawPlaylist(); break;
case DRAWVOL: _volume(); break;
case DBITRATE: {
char buf[20];
snprintf(buf, 20, bitrateFmt, config.station.bitrate);
if(_bitrate) { _bitrate->setText(config.station.bitrate==0?"":buf); }
if(_fullbitrate) {
_fullbitrate->setBitrate(config.station.bitrate);
_fullbitrate->setFormat(config.configFmt);
}
}
break;
case AUDIOINFO: if(_heapbar) { _heapbar->lock(!config.store.audioinfo); _heapbar->setValue(player.inBufferFilled()); } break;
case SHOWVUMETER: {
if(_vuwidget){
_vuwidget->lock(!config.store.vumeter);
_layoutChange(player.isRunning());
}
break;
}
case SHOWWEATHER: {
if(_weather) _weather->lock(!config.store.showweather);
if(!config.store.showweather){
#ifndef HIDE_IP
if(_volip) _volip->setText(config.ipToStr(WiFi.localIP()), iptxtFmt);
#endif
}else{
if(_weather) _weather->setText(LANG::const_getWeather);
}
break;
}
case NEWWEATHER: {
if(_weather && timekeeper.weatherBuf) _weather->setText(timekeeper.weatherBuf);
break;
}
case BOOTSTRING: {
if(_bootstring) _bootstring->setText(config.ssids[request.payload].ssid, LANG::bootstrFmt);
/*#ifdef USE_NEXTION
char buf[50];
snprintf(buf, 50, bootstrFmt, config.ssids[request.payload].ssid);
nextion.bootString(buf);
#endif*/
break;
}
case WAITFORSD: {
if(_bootstring) _bootstring->setText(LANG::const_waitForSD);
break;
}
case SDFILEINDEX: {
if(_mode == SDCHANGE) _nums->setText(request.payload, "%d");
break;
}
case DSPRSSI: if(_rssi){ _setRSSI(request.payload); } if (_heapbar && config.store.audioinfo) _heapbar->setValue(player.isRunning()?player.inBufferFilled():0); break;
case PSTART: _layoutChange(true); break;
case PSTOP: _layoutChange(false); break;
case DSP_START: _start(); break;
case NEWIP: {
#ifndef HIDE_IP
if(_volip) _volip->setText(config.ipToStr(WiFi.localIP()), iptxtFmt);
#endif
break;
}
default: break;
// check if there are more messages waiting in the Q, in this case break the loop() and go
// for another round to evict next message, do not waste time to redraw the screen, etc...
if (uxQueueMessagesWaiting(displayQueue))
return;
}
}
dsp.loop();
/*
#if I2S_DOUT==255
player.computeVUlevel();
#endif
*/
}
void Display::_setRSSI(int rssi) {
if(!_rssi) return;
#if RSSI_DIGIT
_rssi->setText(rssi, rssiFmt);
return;
#endif
char rssiG[3];
int rssi_steps[] = {RSSI_STEPS};
if(rssi >= rssi_steps[0]) strlcpy(rssiG, "\004\006", 3);
if(rssi >= rssi_steps[1] && rssi < rssi_steps[0]) strlcpy(rssiG, "\004\005", 3);
if(rssi >= rssi_steps[2] && rssi < rssi_steps[1]) strlcpy(rssiG, "\004\002", 3);
if(rssi >= rssi_steps[3] && rssi < rssi_steps[2]) strlcpy(rssiG, "\003\002", 3);
if(rssi < rssi_steps[3] || rssi >= 0) strlcpy(rssiG, "\001\002", 3);
_rssi->setText(rssiG);
}
void Display::_station() {
_meta->setAlign(metaConf.widget.align);
_meta->setText(config.station.name);
/*#ifdef USE_NEXTION
nextion.newNameset(config.station.name);
nextion.bitrate(config.station.bitrate);
nextion.bitratePic(ICON_NA);
#endif*/
}
char *split(char *str, const char *delim) {
char *dmp = strstr(str, delim);
if (dmp == NULL) return NULL;
*dmp = '\0';
return dmp + strlen(delim);
}
void Display::_title() {
if (strlen(config.station.title) > 0) {
char tmpbuf[strlen(config.station.title)+1];
strlcpy(tmpbuf, config.station.title, strlen(config.station.title)+1);
char *stitle = split(tmpbuf, " - ");
if(stitle && _title2){
_title1->setText(tmpbuf);
_title2->setText(stitle);
}else{
_title1->setText(config.station.title);
if(_title2) _title2->setText("");
}
/*#ifdef USE_NEXTION
nextion.newTitle(config.station.title);
#endif*/
}else{
_title1->setText("");
if(_title2) _title2->setText("");
}
if (player_on_track_change) player_on_track_change();
pm.on_track_change();
}
void Display::_time(bool redraw) {
#if LIGHT_SENSOR!=255
if(config.store.dspon) {
config.store.brightness = AUTOBACKLIGHT(analogRead(LIGHT_SENSOR));
config.setBrightness();
}
#endif
if(config.isScreensaver && network.timeinfo.tm_sec % 60 == 0){
#if TIME_SIZE<19
uint16_t ft=static_cast<uint16_t>(random(TFT_FRAMEWDT, (dsp.height()-TIME_SIZE*CHARHEIGHT-TFT_FRAMEWDT)));
#else
uint16_t ft=static_cast<uint16_t>(random(TFT_FRAMEWDT+TIME_SIZE, (dsp.height()-_clock->dateSize()-TFT_FRAMEWDT*2)));
#endif
uint16_t lt=static_cast<uint16_t>(random(TFT_FRAMEWDT, (dsp.width()-_clock->clockWidth()-TFT_FRAMEWDT)));
if(clockConf.align==WA_CENTER) lt-=(dsp.width()-_clock->clockWidth())/2;
//_clock->moveTo({clockConf.left, ft, 0});
_clock->moveTo({lt, ft, 0});
}
_clock->draw();
/*#ifdef USE_NEXTION
nextion.printClock(network.timeinfo);
#endif*/
}
void Display::_volume() {
if(_volbar) _volbar->setValue(config.store.volume);
#ifndef HIDE_VOL
if(_voltxt) _voltxt->setText(config.store.volume, voltxtFmt);
#endif
if(_mode==VOL) {
timekeeper.waitAndReturnPlayer(3);
_nums->setText(config.store.volume, numtxtFmt);
}
/*#ifdef USE_NEXTION
nextion.setVol(config.store.volume, _mode == VOL);
#endif*/
}
void Display::flip(){ dsp.flip(); }
void Display::invert(){ dsp.invert(); }
void Display::setContrast(){
#if DSP_MODEL==DSP_NOKIA5110
dsp.setContrast(config.store.contrast);
#endif
}
bool Display::deepsleep(){
#if defined(LCD_I2C) || defined(DSP_OLED) || BRIGHTNESS_PIN!=255
dsp.sleep();
return true;
#endif
return false;
}
void Display::wakeup(){
#if defined(LCD_I2C) || defined(DSP_OLED) || BRIGHTNESS_PIN!=255
dsp.wake();
#endif
}
//============================================================================================================================
#else // !DUMMYDISPLAY
//============================================================================================================================
void Display::init(){
_createDspTask();
#ifdef USE_NEXTION
nextion.begin(true);
#endif
}
void Display::_start(){
#ifdef USE_NEXTION
//nextion.putcmd("page player");
nextion.start();
#endif
config.setTitle(LANG::const_PlReady);
}
void Display::putRequest(displayRequestType_e type, int payload){
if(type==DSP_START) _start();
#ifdef USE_NEXTION
requestParams_t request;
request.type = type;
request.payload = payload;
nextion.putRequest(request);
#else
if(type==NEWMODE) mode((displayMode_e)payload);
#endif
}
//============================================================================================================================
#endif // DUMMYDISPLAY