This commit is contained in:
e2002
2022-03-02 17:07:29 +03:00
parent 37c4f79d94
commit 3933938305
22 changed files with 212 additions and 24 deletions

View File

@@ -198,13 +198,20 @@ download _http://\<yoradioip\>/data/playlist.csv_ and _http://\<yoradioip\>/data
--- ---
## Version history ## Version history
#### v0.4.315
- added support for digital buttons for the IR control \
(num keys - enter number of station, ok - play, hash - cancel)
- added buttons for exporting settings from the web interface
- added MUTE_PIN to be able to control the audio output
- fixed js/html bugs (a [full update](#update) is required)
#### v0.4.298 #### v0.4.298
- fixed playlist scrollbar in Chrome - fixed playlist scrollbar in Chrome (required [full update](#update))
#### v0.4.297 #### v0.4.297
- fix _"Could not decode a text frame as UTF-8"_ websocket error _//Thanks for [Verholazila](https://4pda.to/forum/index.php?s=&showtopic=1010378&view=findpost&p=113551446)_ - fix _"Could not decode a text frame as UTF-8"_ websocket error _//Thanks for [Verholazila](https://4pda.to/forum/index.php?s=&showtopic=1010378&view=findpost&p=113551446)_
- fix display of non-latin characters in the web interface - fix display of non-latin characters in the web interface
- fix css in Chrome - fix css in Chrome (a [full update](#update) is required)
#### v0.4.293 #### v0.4.293
- IR repeat fix - IR repeat fix

View File

@@ -1,3 +1,4 @@
#include "Arduino.h"
#include "controls.h" #include "controls.h"
#include "options.h" #include "options.h"
#include "config.h" #include "config.h"
@@ -34,7 +35,7 @@ OneButton btnright(BTN_RIGHT, true, BTN_INTERNALPULLUP);
#include <IRtext.h> #include <IRtext.h>
#include <IRutils.h> #include <IRutils.h>
byte irVolRepeat=0; byte irVolRepeat = 0;
const uint16_t kCaptureBufferSize = 1024; const uint16_t kCaptureBufferSize = 1024;
const uint8_t kTimeout = IR_TIMEOUT; const uint8_t kTimeout = IR_TIMEOUT;
const uint16_t kMinUnknownSize = 12; const uint16_t kMinUnknownSize = 12;
@@ -71,6 +72,7 @@ void initControls() {
btnright.attachDoubleClick(onRightDoubleClick); btnright.attachDoubleClick(onRightDoubleClick);
#endif #endif
#if IR_PIN!=255 #if IR_PIN!=255
pinMode(IR_PIN, INPUT);
assert(irutils::lowLevelSanityCheck() == 0); assert(irutils::lowLevelSanityCheck() == 0);
#if DECODE_HASH #if DECODE_HASH
irrecv.setUnknownThreshold(kMinUnknownSize); irrecv.setUnknownThreshold(kMinUnknownSize);
@@ -112,9 +114,30 @@ void encoderLoop() {
#endif #endif
#if IR_PIN!=255 #if IR_PIN!=255
void irBlink() {
if (player.mode == STOPPED) {
for(byte i=0; i<7; i++) {
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
delay(100);
}
}
}
void irNum(byte num) {
uint16_t s;
if (display.numOfNextStation == 0 && num == 0) return;
if (display.mode == PLAYER) display.swichMode(NUMBERS);
if (display.numOfNextStation > UINT16_MAX / 10) return;
s = display.numOfNextStation * 10 + num;
if (s > config.store.countStation) return;
display.numOfNextStation = s;
display.drawNextStationNum(s);
}
void irLoop() { void irLoop() {
if (irrecv.decode(&irResults)) { if (irrecv.decode(&irResults)) {
if(IR_DEBUG) { if (IR_DEBUG) {
Serial.print(resultToHumanReadableBasic(&irResults)); Serial.print(resultToHumanReadableBasic(&irResults));
return; return;
} }
@@ -133,6 +156,13 @@ void irLoop() {
} }
switch (irResults.value) { switch (irResults.value) {
case IR_CODE_PLAY: { case IR_CODE_PLAY: {
irBlink();
if (display.mode == NUMBERS) {
display.swichMode(PLAYER);
player.play(display.numOfNextStation);
display.numOfNextStation = 0;
break;
}
onEncClick(); onEncClick();
break; break;
} }
@@ -155,15 +185,64 @@ void irLoop() {
break; break;
} }
case IR_CODE_HASH: { case IR_CODE_HASH: {
if (display.mode == NUMBERS) {
display.swichMode(PLAYER);
display.numOfNextStation = 0;
break;
}
display.swichMode(display.mode == PLAYER ? STATIONS : PLAYER); display.swichMode(display.mode == PLAYER ? STATIONS : PLAYER);
break; break;
} }
case IR_CODE_NUM0: {
irNum(0);
break;
}
case IR_CODE_NUM1: {
irNum(1);
break;
}
case IR_CODE_NUM2: {
irNum(2);
break;
}
case IR_CODE_NUM3: {
irNum(3);
break;
}
case IR_CODE_NUM4: {
irNum(4);
break;
}
case IR_CODE_NUM5: {
irNum(5);
break;
}
case IR_CODE_NUM6: {
irNum(6);
break;
}
case IR_CODE_NUM7: {
irNum(7);
break;
}
case IR_CODE_NUM8: {
irNum(8);
break;
}
case IR_CODE_NUM9: {
irNum(9);
break;
}
} }
} }
} }
#endif #endif
void onEncClick() { void onEncClick() {
if (display.mode == NUMBERS) {
display.numOfNextStation = 0;
display.swichMode(PLAYER);
}
if (display.mode == PLAYER) { if (display.mode == PLAYER) {
player.toggle(); player.toggle();
} }
@@ -183,6 +262,10 @@ void onEncLPStart() {
} }
void controlsEvent(bool toRight) { void controlsEvent(bool toRight) {
if (display.mode == NUMBERS) {
display.numOfNextStation = 0;
display.swichMode(PLAYER);
}
if (display.mode != STATIONS) { if (display.mode != STATIONS) {
display.swichMode(VOL); display.swichMode(VOL);
player.stepVol(toRight); player.stepVol(toRight);

View File

@@ -9,7 +9,8 @@ void onEncDoubleClick();
void onEncLPStart(); void onEncLPStart();
void encoderLoop(); void encoderLoop();
void irLoop(); void irLoop();
void irNum(byte num);
void irBlink();
void controlsEvent(bool toRight); void controlsEvent(bool toRight);
void onLeftClick(); void onLeftClick();

2
yoRadio/data/data/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

View File

@@ -0,0 +1 @@
1
1 1
1 1

View File

@@ -67,34 +67,37 @@
</div><!--player--> </div><!--player-->
<div id="settings"%NOTAPMODE%> <div id="settings"%NOTAPMODE%>
<h2>WiFi Settings</h2> <h2>WiFi Settings</h2>
<form autocomplete="off">
<ul id="credentialwrap"> <ul id="credentialwrap">
<li class="credentialitem"> <li class="credentialitem">
<span>1.</span> <span>1.</span>
<div class="textinput"><label for="ssid0">SSID</label><input name="ssid" id="ssid0" type="text" value="%SSID%" maxlength="20"/ ></div> <div class="textinput"><label for="ssid0">SSID</label><input name="ssid" id="ssid0" type="text" value="%SSID%" maxlength="20"/ ></div>
<div class="textinput"><label for"pass0">Password</label><input name="pass" id="pass0" type="password" value="%PASS%" maxlength="40" /></div> <div class="textinput"><label for"pass0">Password</label><input name="pass" id="pass0" type="text" data-pass="%PASS%" placeholder="**********" value="" maxlength="40" autocomplete="off" readonly="readonly" onfocus="this.removeAttribute('readonly');" /></div>
</li> </li>
<li class="credentialitem"> <li class="credentialitem">
<span>2.</span> <span>2.</span>
<div class="textinput"><label for="ssid1">SSID</label><input name="ssid" id="ssid1" type="text" value="%SSID%" maxlength="20" /></div> <div class="textinput"><label for="ssid1">SSID</label><input name="ssid" id="ssid1" type="text" value="%SSID%" maxlength="20" /></div>
<div class="textinput"><label for"pass1">Password</label><input name="pass" id="pass1" type="password" value="%PASS%" maxlength="40" /></div> <div class="textinput"><label for"pass1">Password</label><input name="pass" id="pass1" type="text" data-pass="%PASS%" placeholder="**********" value="" maxlength="40" autocomplete="off" readonly="readonly" onfocus="this.removeAttribute('readonly');" /></div>
</li> </li>
<li class="credentialitem"> <li class="credentialitem">
<span>3.</span> <span>3.</span>
<div class="textinput"><label for="ssid2">SSID</label><input name="ssid" id="ssid2" type="text" value="%SSID%" maxlength="20" /></div> <div class="textinput"><label for="ssid2">SSID</label><input name="ssid" id="ssid2" type="text" value="%SSID%" maxlength="20" /></div>
<div class="textinput"><label for"pass2">Password</label><input name="pass" id="pass2" type="password" value="%PASS%" maxlength="40" /></div> <div class="textinput"><label for"pass2">Password</label><input name="pass" id="pass2" type="text" data-pass="%PASS%" placeholder="**********" value="" maxlength="40" autocomplete="off" readonly="readonly" onfocus="this.removeAttribute('readonly');" /></div>
</li> </li>
<li class="credentialitem"> <li class="credentialitem">
<span>4.</span> <span>4.</span>
<div class="textinput"><label for="ssid3">SSID</label><input name="ssid" id="ssid3" type="text" value="%SSID%" maxlength="20" /></div> <div class="textinput"><label for="ssid3">SSID</label><input name="ssid" id="ssid3" type="text" value="%SSID%" maxlength="20" /></div>
<div class="textinput"><label for"pass3">Password</label><input name="pass" id="pass3" type="password" value="%PASS%" maxlength="40" /></div> <div class="textinput"><label for"pass3">Password</label><input name="pass" id="pass3" type="text" data-pass="%PASS%" placeholder="**********" value="" maxlength="40" autocomplete="off" readonly="readonly" onfocus="this.removeAttribute('readonly');" /></div>
</li> </li>
<li class="credentialitem"> <li class="credentialitem">
<span>5.</span> <span>5.</span>
<div class="textinput"><label for="ssid4">SSID</label><input name="ssid" id="ssid4" type="text" value="%SSID%" maxlength="20" /></div> <div class="textinput"><label for="ssid4">SSID</label><input name="ssid" id="ssid4" type="text" value="%SSID%" maxlength="20" /></div>
<div class="textinput"><label for"pass4">Password</label><input name="pass" id="pass4" type="password" value="%PASS%" maxlength="40" /></div> <div class="textinput"><label for"pass4">Password</label><input name="pass" id="pass4" type="text" data-pass="%PASS%" placeholder="**********" value="" maxlength="40" autocomplete="off" readonly="readonly" onfocus="this.removeAttribute('readonly');" /></div>
</li> </li>
</ul> </ul>
</form>
<div class="formbuttons"> <div class="formbuttons">
<div class="button" id="wifiexport_button" onclick="doWifiExport()"%APMODE%>Export</div>
<div class="button" id="cancel_button" onclick="doCancel()"%APMODE%>Cancel</div> <div class="button" id="cancel_button" onclick="doCancel()"%APMODE%>Cancel</div>
<div class="button" id="save_button" onclick="submitWiFi()">Save</div> <div class="button" id="save_button" onclick="submitWiFi()">Save</div>
</div> </div>

View File

@@ -1,9 +1,12 @@
var gateway = `ws://${window.location.hostname}/ws`; var gateway = `ws://${window.location.hostname}/ws`;
var websocket; var websocket;
var currentItem = 0; var currentItem = 0;
var wserrcnt = 0;
var wstimeout;
window.addEventListener('load', onLoad); window.addEventListener('load', onLoad);
function initWebSocket() { function initWebSocket() {
clearTimeout(wstimeout);
console.log('Trying to open a WebSocket connection...'); console.log('Trying to open a WebSocket connection...');
websocket = new WebSocket(gateway); websocket = new WebSocket(gateway);
websocket.onopen = onOpen; websocket.onopen = onOpen;
@@ -12,13 +15,14 @@ function initWebSocket() {
} }
function onOpen(event) { function onOpen(event) {
console.log('Connection opened'); console.log('Connection opened');
wserrcnt=0;
} }
function onClose(event) { function onClose(event) {
console.log('Connection closed'); //console.log('Connection closed');
wserrcnt++;
document.getElementById('playbutton').setAttribute("class", "stopped"); document.getElementById('playbutton').setAttribute("class", "stopped");
setTimeout(initWebSocket, 2000); wstimeout=setTimeout(initWebSocket, wserrcnt<10?2000:120000);
} }
function onMessage(event) { function onMessage(event) {
var data = JSON.parse(event.data); var data = JSON.parse(event.data);
if(data.nameset) document.getElementById('nameset').innerHTML = data.nameset; if(data.nameset) document.getElementById('nameset').innerHTML = data.nameset;
@@ -138,7 +142,6 @@ function setVolRangeValue(el, val=null){
var value = (el.value-el.min)/(el.max-el.min)*100; var value = (el.value-el.min)/(el.max-el.min)*100;
el.style.background = 'linear-gradient(to right, #bfa73e 0%, #bfa73e ' + value + '%, #272727 ' + value + '%, #272727 100%)'; el.style.background = 'linear-gradient(to right, #bfa73e 0%, #bfa73e ' + value + '%, #272727 ' + value + '%, #272727 100%)';
} }
function onRangeVolChange(value) { function onRangeVolChange(value) {
xhr = new XMLHttpRequest(); xhr = new XMLHttpRequest();
xhr.open("POST","/",true); xhr.open("POST","/",true);
@@ -162,10 +165,12 @@ function onRangeBalChange(el){
} }
function showSettings(){ function showSettings(){
document.getElementById('pleditorwrap').hidden=true; document.getElementById('pleditorwrap').hidden=true;
document.getElementById('equalizerbg').hidden=true;
document.getElementById('settings').hidden=false; document.getElementById('settings').hidden=false;
} }
function showEditor(){ function showEditor(){
document.getElementById('settings').hidden=true; document.getElementById('settings').hidden=true;
document.getElementById('equalizerbg').hidden=true;
initPLEditor(); initPLEditor();
document.getElementById('pleditorwrap').hidden=false; document.getElementById('pleditorwrap').hidden=false;
} }
@@ -176,6 +181,10 @@ function doCancel() {
function doExport() { function doExport() {
window.open("/data/playlist.csv"); window.open("/data/playlist.csv");
} }
function doWifiExport() {
document.getElementById('settings').hidden=true;
window.open("/data/wifi.csv");
}
function doUpload(finput) { function doUpload(finput) {
var formData = new FormData(); var formData = new FormData();
formData.append("plfile", finput.files[0]); formData.append("plfile", finput.files[0]);
@@ -231,7 +240,8 @@ function submitWiFi(){
for (var i = 0; i <= items.length - 1; i++) { for (var i = 0; i <= items.length - 1; i++) {
inputs=items[i].getElementsByTagName("input"); inputs=items[i].getElementsByTagName("input");
if(inputs[0].value == "") continue; if(inputs[0].value == "") continue;
output+=inputs[0].value+"\t"+inputs[1].value+"\n"; let ps=inputs[1].value==""?inputs[1].getAttribute('data-pass'):inputs[1].value;
output+=inputs[0].value+"\t"+ps+"\n";
} }
if(output!=""){ // Well, let's say, quack. if(output!=""){ // Well, let's say, quack.
xhr = new XMLHttpRequest(); xhr = new XMLHttpRequest();

View File

@@ -204,6 +204,9 @@ void Display::swichMode(displayMode_e newmode) {
if (newmode == VOL) { if (newmode == VOL) {
dsp.frameTitle("VOLUME"); dsp.frameTitle("VOLUME");
} }
if (newmode == NUMBERS) {
dsp.frameTitle("STATION");
}
if (newmode == STATIONS) { if (newmode == STATIONS) {
currentPlItem = config.store.lastStation; currentPlItem = config.store.lastStation;
plCurrent.reset(); plCurrent.reset();
@@ -235,6 +238,10 @@ void Display::drawPlaylist() {
plCurrent.setText(dsp.utf8Rus(buf, true)); plCurrent.setText(dsp.utf8Rus(buf, true));
} }
void Display::drawNextStationNum(uint16_t num) {
dsp.drawNextStationNum(num);
}
void Display::loop() { void Display::loop() {
switch (mode) { switch (mode) {
case PLAYER: { case PLAYER: {
@@ -245,6 +252,9 @@ void Display::loop() {
drawVolume(); drawVolume();
break; break;
} }
case NUMBERS: {
break;
}
case STATIONS: { case STATIONS: {
plCurrent.loop(); plCurrent.loop();
break; break;

View File

@@ -5,7 +5,7 @@
#include <Ticker.h> #include <Ticker.h>
#include "config.h" #include "config.h"
enum displayMode_e { PLAYER, VOL, STATIONS }; enum displayMode_e { PLAYER, VOL, STATIONS, NUMBERS };
class Scroll { class Scroll {
public: public:
@@ -42,6 +42,7 @@ class Display {
uint16_t screenwidth, screenheight; uint16_t screenwidth, screenheight;
displayMode_e mode; displayMode_e mode;
uint16_t currentPlItem; uint16_t currentPlItem;
uint16_t numOfNextStation;
public: public:
Display() {}; Display() {};
void init(); void init();
@@ -58,6 +59,7 @@ class Display {
void ip(); void ip();
void swichMode(displayMode_e newmode); void swichMode(displayMode_e newmode);
void drawPlaylist(); void drawPlaylist();
void drawNextStationNum(uint16_t num);
private: private:
Ticker timer; Ticker timer;
Scroll meta, title1, title2, plCurrent; Scroll meta, title1, title2, plCurrent;

View File

@@ -1,7 +1,7 @@
#ifndef options_h #ifndef options_h
#define options_h #define options_h
#define VERSION "0.4.298" #define VERSION "0.4.315"
#if __has_include("myoptions.h") #if __has_include("myoptions.h")
#include "myoptions.h" // <- write your variable values here #include "myoptions.h" // <- write your variable values here
@@ -115,6 +115,13 @@
#define VOL_STEP 1 // Encoder vol step #define VOL_STEP 1 // Encoder vol step
#endif #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
/* /*
*** ST7735 display submodel *** *** ST7735 display submodel ***
INITR_BLACKTAB // 1.8' https://aliexpress.ru/item/1005002822797745.html INITR_BLACKTAB // 1.8' https://aliexpress.ru/item/1005002822797745.html

View File

@@ -28,6 +28,7 @@ Player::Player() {}
void Player::init() { void Player::init() {
if(MUTE_PIN!=255) pinMode(MUTE_PIN, OUTPUT);
#if I2S_DOUT!=255 #if I2S_DOUT!=255
setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
#else #else
@@ -55,7 +56,8 @@ void Player::loop() {
Audio::loop(); Audio::loop();
} else { } else {
if (isRunning()) { if (isRunning()) {
digitalWrite(LED_BUILTIN, LOW); //digitalWrite(LED_BUILTIN, LOW);
setOutputPins(false);
display.title("[stopped]"); display.title("[stopped]");
stopSong(); stopSong();
stopInfo(); stopInfo();
@@ -84,9 +86,15 @@ void Player::zeroRequest() {
request.doSave = false; request.doSave = false;
} }
void Player::play(byte stationId) { void Player::setOutputPins(bool isPlaying) {
digitalWrite(LED_BUILTIN, isPlaying);
if(MUTE_PIN!=255) digitalWrite(MUTE_PIN, isPlaying?!MUTE_VAL:MUTE_VAL);
}
void Player::play(uint16_t stationId) {
stopSong(); stopSong();
digitalWrite(LED_BUILTIN, LOW); //digitalWrite(LED_BUILTIN, LOW);
setOutputPins(false);
display.title("[connecting]"); display.title("[connecting]");
telnet.printf("##CLI.META#: %s\n", config.station.title); telnet.printf("##CLI.META#: %s\n", config.station.title);
config.loadStation(stationId); config.loadStation(stationId);
@@ -97,7 +105,8 @@ void Player::play(byte stationId) {
mode = PLAYING; mode = PLAYING;
config.setSmartStart(1); config.setSmartStart(1);
netserver.requestOnChange(MODE, 0); netserver.requestOnChange(MODE, 0);
digitalWrite(LED_BUILTIN, HIGH); //digitalWrite(LED_BUILTIN, HIGH);
setOutputPins(true);
requesToStart = true; requesToStart = true;
}else{ }else{
Serial.println("Some Unknown Bug..."); Serial.println("Some Unknown Bug...");

View File

@@ -27,7 +27,7 @@ class Player: public Audio {
void init(); void init();
void loop(); void loop();
void zeroRequest(); void zeroRequest();
void play(byte stationId); void play(uint16_t stationId);
void prev(); void prev();
void next(); void next();
void toggle(); void toggle();
@@ -35,6 +35,7 @@ class Player: public Audio {
void setVol(byte volume, bool inside); void setVol(byte volume, bool inside);
byte volToI2S(byte volume); byte volToI2S(byte volume);
void stopInfo(); void stopInfo();
void setOutputPins(bool isPlaying);
}; };
extern Player player; extern Player player;

View File

@@ -137,6 +137,10 @@ void DisplayDummy::drawVolumeBar(bool withNumber) {
} }
void DisplayDummy::drawNextStationNum(uint16_t num) {
}
void DisplayDummy::frameTitle(const char* str) { void DisplayDummy::frameTitle(const char* str) {
} }

View File

@@ -28,6 +28,7 @@ class DisplayDummy {
void printClock(const char* timestr); void printClock(const char* timestr);
void displayHeapForDebug(); void displayHeapForDebug();
void drawVolumeBar(bool withNumber); void drawVolumeBar(bool withNumber);
void drawNextStationNum(uint16_t num);
char* utf8Rus(const char* str, bool uppercase); char* utf8Rus(const char* str, bool uppercase);
void drawScrollFrame(uint16_t texttop, uint16_t textheight, uint16_t bg); void drawScrollFrame(uint16_t texttop, uint16_t textheight, uint16_t bg);
void getScrolBbounds(const char* text, const char* separator, byte textsize, uint16_t &tWidth, uint16_t &tHeight, uint16_t &sWidth); void getScrolBbounds(const char* text, const char* separator, byte textsize, uint16_t &tWidth, uint16_t &tHeight, uint16_t &sWidth);

View File

@@ -250,6 +250,21 @@ void DisplayN5110::drawVolumeBar(bool withNumber) {
} }
} }
void DisplayN5110::drawNextStationNum(uint16_t num) {
setTextSize(1);
setTextColor(TFT_FG);
char numstr[7];
uint16_t wv, hv;
int16_t x1, y1;
sprintf(numstr, "%d", num);
setFont(&DS_DIGI15pt7b);
getTextBounds(numstr, 0, 0, &x1, &y1, &wv, &hv);
fillRect(TFT_FRAMEWDT, 24-10, swidth - TFT_FRAMEWDT / 2, hv + 3, TFT_BG);
setCursor((swidth - wv) / 2, 24+8);
print(numstr);
setFont();
}
void DisplayN5110::frameTitle(const char* str) { void DisplayN5110::frameTitle(const char* str) {
setTextSize(1); setTextSize(1);
centerText(str, TFT_FRAMEWDT, TFT_LOGO, TFT_BG); centerText(str, TFT_FRAMEWDT, TFT_LOGO, TFT_BG);

View File

@@ -33,6 +33,7 @@ class DisplayN5110: public Adafruit_PCD8544 {
void printClock(const char* timestr); void printClock(const char* timestr);
void displayHeapForDebug(); void displayHeapForDebug();
void drawVolumeBar(bool withNumber); void drawVolumeBar(bool withNumber);
void drawNextStationNum(uint16_t num);
char* utf8Rus(const char* str, bool uppercase); char* utf8Rus(const char* str, bool uppercase);
void drawScrollFrame(uint16_t texttop, uint16_t textheight, uint16_t bg); void drawScrollFrame(uint16_t texttop, uint16_t textheight, uint16_t bg);
void getScrolBbounds(const char* text, const char* separator, byte textsize, uint16_t &tWidth, uint16_t &tHeight, uint16_t &sWidth); void getScrolBbounds(const char* text, const char* separator, byte textsize, uint16_t &tWidth, uint16_t &tHeight, uint16_t &sWidth);

View File

@@ -245,6 +245,19 @@ void DisplaySSD1306::drawVolumeBar(bool withNumber) {
} }
} }
void DisplaySSD1306::drawNextStationNum(uint16_t num) {
setTextSize(2);
setTextColor(TFT_FG);
char numstr[7];
uint16_t wv, hv;
int16_t x1, y1;
sprintf(numstr, "%d", num);
getTextBounds(numstr, 0, 0, &x1, &y1, &wv, &hv);
fillRect(TFT_FRAMEWDT, 24, swidth - TFT_FRAMEWDT / 2, hv + 3, TFT_BG);
setCursor((swidth - wv) / 2, 24);
print(numstr);
}
void DisplaySSD1306::frameTitle(const char* str) { void DisplaySSD1306::frameTitle(const char* str) {
setTextSize(2); setTextSize(2);
centerText(str, TFT_FRAMEWDT, TFT_LOGO, TFT_BG); centerText(str, TFT_FRAMEWDT, TFT_LOGO, TFT_BG);

View File

@@ -30,6 +30,7 @@ class DisplaySSD1306: public Adafruit_SSD1306 {
void printClock(const char* timestr); void printClock(const char* timestr);
void displayHeapForDebug(); void displayHeapForDebug();
void drawVolumeBar(bool withNumber); void drawVolumeBar(bool withNumber);
void drawNextStationNum(uint16_t num);
char* utf8Rus(const char* str, bool uppercase); char* utf8Rus(const char* str, bool uppercase);
void drawScrollFrame(uint16_t texttop, uint16_t textheight, uint16_t bg); void drawScrollFrame(uint16_t texttop, uint16_t textheight, uint16_t bg);
void getScrolBbounds(const char* text, const char* separator, byte textsize, uint16_t &tWidth, uint16_t &tHeight, uint16_t &sWidth); void getScrolBbounds(const char* text, const char* separator, byte textsize, uint16_t &tWidth, uint16_t &tHeight, uint16_t &sWidth);

View File

@@ -275,6 +275,21 @@ void DisplayST7735::drawVolumeBar(bool withNumber) {
} }
} }
void DisplayST7735::drawNextStationNum(uint16_t num) {
setTextSize(1);
setTextColor(TFT_FG);
setFont(&DS_DIGI28pt7b);
char numstr[7];
uint16_t wv, hv;
int16_t x1, y1;
sprintf(numstr, "%d", num);
getTextBounds(numstr, 0, 0, &x1, &y1, &wv, &hv);
fillRect(TFT_FRAMEWDT, 48, swidth - TFT_FRAMEWDT / 2, hv + 3, TFT_BG);
setCursor((swidth - wv) / 2, 48 + hv);
print(numstr);
setFont();
}
void DisplayST7735::frameTitle(const char* str) { void DisplayST7735::frameTitle(const char* str) {
setTextSize(2); setTextSize(2);
centerText(str, TFT_FRAMEWDT, TFT_LOGO, TFT_BG); centerText(str, TFT_FRAMEWDT, TFT_LOGO, TFT_BG);

View File

@@ -31,6 +31,7 @@ class DisplayST7735: public Adafruit_ST7735 {
void printClock(const char* timestr); void printClock(const char* timestr);
void displayHeapForDebug(); void displayHeapForDebug();
void drawVolumeBar(bool withNumber); void drawVolumeBar(bool withNumber);
void drawNextStationNum(uint16_t num);
char* utf8Rus(const char* str, bool uppercase); char* utf8Rus(const char* str, bool uppercase);
void drawScrollFrame(uint16_t texttop, uint16_t textheight, uint16_t bg); void drawScrollFrame(uint16_t texttop, uint16_t textheight, uint16_t bg);
void getScrolBbounds(const char* text, const char* separator, byte textsize, uint16_t &tWidth, uint16_t &tHeight, uint16_t &sWidth); void getScrolBbounds(const char* text, const char* separator, byte textsize, uint16_t &tWidth, uint16_t &tHeight, uint16_t &sWidth);

View File

@@ -260,7 +260,7 @@ void Telnet::on_input(const char* str, byte clientId) {
printf(clientId, "> "); printf(clientId, "> ");
return; return;
} }
uint8_t sb; uint16_t sb;
if (sscanf(str, "play(%d)", &sb) == 1 || sscanf(str, "cli.play(\"%d\")", &sb) == 1 || sscanf(str, "play %d", &sb) == 1 ) { if (sscanf(str, "play(%d)", &sb) == 1 || sscanf(str, "cli.play(\"%d\")", &sb) == 1 || sscanf(str, "play %d", &sb) == 1 ) {
if (sb < 1) sb = 1; if (sb < 1) sb = 1;
if (sb >= config.store.countStation) sb = config.store.countStation; if (sb >= config.store.countStation) sb = config.store.countStation;

View File

@@ -13,10 +13,11 @@
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW); //digitalWrite(LED_BUILTIN, LOW);
config.init(); config.init();
display.init(); display.init();
player.init(); player.init();
player.setOutputPins(false);
network.begin(); network.begin();
if (network.status != CONNECTED) { if (network.status != CONNECTED) {
netserver.begin(); netserver.begin();