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

@@ -1,3 +1,4 @@
#include "Arduino.h"
#include "controls.h"
#include "options.h"
#include "config.h"
@@ -34,7 +35,7 @@ OneButton btnright(BTN_RIGHT, true, BTN_INTERNALPULLUP);
#include <IRtext.h>
#include <IRutils.h>
byte irVolRepeat=0;
byte irVolRepeat = 0;
const uint16_t kCaptureBufferSize = 1024;
const uint8_t kTimeout = IR_TIMEOUT;
const uint16_t kMinUnknownSize = 12;
@@ -71,6 +72,7 @@ void initControls() {
btnright.attachDoubleClick(onRightDoubleClick);
#endif
#if IR_PIN!=255
pinMode(IR_PIN, INPUT);
assert(irutils::lowLevelSanityCheck() == 0);
#if DECODE_HASH
irrecv.setUnknownThreshold(kMinUnknownSize);
@@ -112,9 +114,30 @@ void encoderLoop() {
#endif
#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() {
if (irrecv.decode(&irResults)) {
if(IR_DEBUG) {
if (IR_DEBUG) {
Serial.print(resultToHumanReadableBasic(&irResults));
return;
}
@@ -133,6 +156,13 @@ void irLoop() {
}
switch (irResults.value) {
case IR_CODE_PLAY: {
irBlink();
if (display.mode == NUMBERS) {
display.swichMode(PLAYER);
player.play(display.numOfNextStation);
display.numOfNextStation = 0;
break;
}
onEncClick();
break;
}
@@ -155,15 +185,64 @@ void irLoop() {
break;
}
case IR_CODE_HASH: {
if (display.mode == NUMBERS) {
display.swichMode(PLAYER);
display.numOfNextStation = 0;
break;
}
display.swichMode(display.mode == PLAYER ? STATIONS : PLAYER);
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
void onEncClick() {
if (display.mode == NUMBERS) {
display.numOfNextStation = 0;
display.swichMode(PLAYER);
}
if (display.mode == PLAYER) {
player.toggle();
}
@@ -183,6 +262,10 @@ void onEncLPStart() {
}
void controlsEvent(bool toRight) {
if (display.mode == NUMBERS) {
display.numOfNextStation = 0;
display.swichMode(PLAYER);
}
if (display.mode != STATIONS) {
display.swichMode(VOL);
player.stepVol(toRight);

View File

@@ -9,7 +9,8 @@ void onEncDoubleClick();
void onEncLPStart();
void encoderLoop();
void irLoop();
void irNum(byte num);
void irBlink();
void controlsEvent(bool toRight);
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 id="settings"%NOTAPMODE%>
<h2>WiFi Settings</h2>
<form autocomplete="off">
<ul id="credentialwrap">
<li class="credentialitem">
<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"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 class="credentialitem">
<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"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 class="credentialitem">
<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"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 class="credentialitem">
<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"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 class="credentialitem">
<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"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>
</ul>
</form>
<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="save_button" onclick="submitWiFi()">Save</div>
</div>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -28,6 +28,7 @@ class DisplayDummy {
void printClock(const char* timestr);
void displayHeapForDebug();
void drawVolumeBar(bool withNumber);
void drawNextStationNum(uint16_t num);
char* utf8Rus(const char* str, bool uppercase);
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);

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) {
setTextSize(1);
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 displayHeapForDebug();
void drawVolumeBar(bool withNumber);
void drawNextStationNum(uint16_t num);
char* utf8Rus(const char* str, bool uppercase);
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);

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) {
setTextSize(2);
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 displayHeapForDebug();
void drawVolumeBar(bool withNumber);
void drawNextStationNum(uint16_t num);
char* utf8Rus(const char* str, bool uppercase);
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);

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) {
setTextSize(2);
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 displayHeapForDebug();
void drawVolumeBar(bool withNumber);
void drawNextStationNum(uint16_t num);
char* utf8Rus(const char* str, bool uppercase);
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);

View File

@@ -260,7 +260,7 @@ void Telnet::on_input(const char* str, byte clientId) {
printf(clientId, "> ");
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 (sb < 1) sb = 1;
if (sb >= config.store.countStation) sb = config.store.countStation;

View File

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