diff --git a/Controls.md b/Controls.md
new file mode 100644
index 0000000..47b678b
--- /dev/null
+++ b/Controls.md
@@ -0,0 +1,68 @@
+## Controls
+
+
+
+---
+- [Buttons](#buttons)
+- [Encoders](#encoders)
+- [IR receiver](#ir-receiver)
+- [Joystick](#joystic)
+- [Back to Readme](Readme.md)
+
+---
+### Buttons
+Up to 5 buttons can be connected to the device. Three buttons are enough to control it.
+
+Button actions:
+- BTN_LEFT\
+ click: volume down\
+ dblclick: previous station\
+ longpress: quick volume down
+- BTN_CENTER\
+ click: start/stop playing\
+ dblclick: toggle between PLAYER/PLAYLIST mode\
+ longpress: toggle between PLAYER/PLAYLIST mode
+- BTN_RIGHT\
+ click: volume up\
+ dblclick: next station\
+ longpress: quick volume up
+- BTN_UP\
+ click: without display - next station, with display - move up\
+ dblclick: doing nothing\
+ longpress: with display - quick move up
+- BTN_DOWN\
+ click: without display - prev station, with display - move down\
+ dblclick: doing nothing\
+ longpress: with display - quick move down
+
+---
+### Encoders
+You can connect one or two encoders to replace/complete the buttons. One encoder (without buttons) is enough to control the device.
+
+- ENCODER1\
+ rotate left: (ENC_BTNL) in PLAYER mode - volume down, in PLAYLIST mode - move up\
+ rotate right: (ENC_BTNR) in PLAYER mode - volume up, in PLAYLIST mode - move down\
+ click, dblclick, longpress: (ENC_BTNB) same as BTN_CENTER
+- ENCODER2\
+ rotate left: (ENC2_BTNL) if not pressed - switch to PLAYLIST mode and move up, if pressed - volume down\
+ rotate right: (ENC2_BTNR) if not pressed - switch to PLAYLIST mode and move down, if pressed - volume up\
+ click, dblclick: (ENC2_BTNB) same as BTN_CENTER
+
+---
+### IR receiver
+- IR_CODE_PLAY: start/stop playing
+- IR_CODE_PREV: previous station
+- IR_CODE_NEXT: next station
+- IR_CODE_VOLUP: volume up, longpress - quick volume up
+- IR_CODE_VOLDN: volume down, longpress - quick volume down
+- IR_CODE_HASH: toggle between PLAYER/PLAYLIST mode
+- IR_CODE_NUM0-NUM9:\
+ Start entering the station number. To finish input and start playback, press the play button. To cancel, press hash.
+
+---
+### Joystick
+You can use a joystick [like this](https://aliexpress.com/item/4000681560472.html) instead of connecting five buttons
+
+
+
+---
diff --git a/Images.md b/Images.md
index ff8b99a..89d7843 100644
--- a/Images.md
+++ b/Images.md
@@ -25,4 +25,8 @@
\
\
\
-
+\
+\
+\
+\
+
diff --git a/README.md b/README.md
index a003605..f0b1f88 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,7 @@
- [Hardware setup](#hardware-setup)
- [Quick start](#quick-start)
- [Update](#update)
+- [Controls](Controls.md)
- [MQTT](#mqtt)
- [Home Assistant](#home-assistant)
- [More features](#more-features)
@@ -230,7 +231,7 @@ download _http://\/data/playlist.csv_ and _http://\/data
**Commands**: \
**prev** - prev station \
**next** - next station \
- **toggle** - start/stop playing \
+ **toggle** - start/stop playing \
**stop** - stop playing \
**start, play** - start playing \
**boot, reboot** - reboot \
@@ -243,6 +244,13 @@ download _http://\/data/playlist.csv_ and _http://\/data
---
## Version history
+#### v0.5.033
+- added two buttons BTN_UP, BTN_DOWN
+- added the pins for the second encoder ENC2_BTNL, ENC2_BTNB, ENC2_BTNR
+- fixed display of playlist with SSD1306 configuration
+- improvements in the displays work
+- bugs fixes, some improvements
+
#### v0.5.020
- added support for SSD1306 128x32 I2C displays
diff --git a/exsamples/myoptions.h b/exsamples/myoptions.h
index 60d4876..cedba12 100644
--- a/exsamples/myoptions.h
+++ b/exsamples/myoptions.h
@@ -49,6 +49,14 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
//#define ENC_HALFQUARD true /* Experiment with it */
/******************************************/
+/* ENCODER2 */
+//#define ENC2_BTNL 255 /* Left rotation */
+//#define ENC2_BTNB 255 /* Encoder button */
+//#define ENC2_BTNR 255 /* Right rotation */
+//#define ENC2_INTERNALPULLUP true /* Enable the weak pull up resistors */
+//#define ENC2_HALFQUARD true /* Experiment with it */
+/******************************************/
+
/* BUTTONS */
//#define BTN_LEFT 255 /* VolDown, Prev */
//#define BTN_CENTER 255 /* Play, Stop, Show playlist */
diff --git a/images/controls.jpg b/images/controls.jpg
new file mode 100644
index 0000000..f154a74
Binary files /dev/null and b/images/controls.jpg differ
diff --git a/images/img13.jpg b/images/img13.jpg
index 1bac5ab..d4923a2 100644
Binary files a/images/img13.jpg and b/images/img13.jpg differ
diff --git a/images/img14.jpg b/images/img14.jpg
new file mode 100644
index 0000000..fa042d2
Binary files /dev/null and b/images/img14.jpg differ
diff --git a/images/joystick.jpg b/images/joystick.jpg
new file mode 100644
index 0000000..45e3e70
Binary files /dev/null and b/images/joystick.jpg differ
diff --git a/yoRadio/controls.cpp b/yoRadio/controls.cpp
index 41b8ea9..40650f4 100644
--- a/yoRadio/controls.cpp
+++ b/yoRadio/controls.cpp
@@ -6,19 +6,25 @@
#include "display.h"
long encOldPosition = 0;
+long enc2OldPosition = 0;
int lpId = -1;
-#define ISPUSHBUTTONS BTN_LEFT!=255 || BTN_LEFT!=255 || BTN_RIGHT!=255 || ENC_BTNB!=255
+#define ISPUSHBUTTONS BTN_LEFT!=255 || BTN_CENTER!=255 || BTN_RIGHT!=255 || ENC_BTNB!=255 || BTN_UP!=255 || BTN_DOWN!=255 || ENC2_BTNB!=255
#if ISPUSHBUTTONS
#include "OneButton.h"
-OneButton button[] {{BTN_LEFT, true, BTN_INTERNALPULLUP}, {BTN_CENTER, true, BTN_INTERNALPULLUP}, {BTN_RIGHT, true, BTN_INTERNALPULLUP}, {ENC_BTNB, true, ENC_INTERNALPULLUP}};
+OneButton button[] {{BTN_LEFT, true, BTN_INTERNALPULLUP}, {BTN_CENTER, true, BTN_INTERNALPULLUP}, {BTN_RIGHT, true, BTN_INTERNALPULLUP}, {ENC_BTNB, true, ENC_INTERNALPULLUP}, {BTN_UP, true, BTN_INTERNALPULLUP}, {BTN_DOWN, true, BTN_INTERNALPULLUP}, {ENC2_BTNB, true, ENC2_INTERNALPULLUP}};
constexpr uint8_t nrOfButtons = sizeof(button) / sizeof(button[0]);
#endif
-#if ENC_BTNL!=255 && ENC_BTNR!=255
+#if (ENC_BTNL!=255 && ENC_BTNR!=255) || (ENC2_BTNL!=255 && ENC2_BTNR!=255)
#include
+#if (ENC_BTNL!=255 && ENC_BTNR!=255)
ESP32Encoder encoder;
#endif
+#if (ENC2_BTNL!=255 && ENC2_BTNR!=255)
+ESP32Encoder encoder2;
+#endif
+#endif
#if IR_PIN!=255
#include
@@ -41,17 +47,25 @@ decode_results irResults;
void initControls() {
#if ENC_BTNL!=255
- ESP32Encoder::useInternalWeakPullResistors = ENC_INTERNALPULLUP ? UP : DOWN;
+ encoder.useInternalWeakPullResistors = ENC_INTERNALPULLUP ? UP : DOWN;
if (ENC_HALFQUARD) {
encoder.attachHalfQuad(ENC_BTNL, ENC_BTNR);
} else {
encoder.attachFullQuad(ENC_BTNL, ENC_BTNR);
}
#endif
+#if ENC2_BTNL!=255
+ encoder2.useInternalWeakPullResistors = ENC2_INTERNALPULLUP ? UP : DOWN;
+ if (ENC2_HALFQUARD) {
+ encoder2.attachHalfQuad(ENC2_BTNL, ENC2_BTNR);
+ } else {
+ encoder2.attachFullQuad(ENC2_BTNL, ENC2_BTNR);
+ }
+#endif
#if ISPUSHBUTTONS
for (int i = 0; i < nrOfButtons; i++)
{
- if ((i == 0 && BTN_LEFT == 255) || (i == 1 && BTN_CENTER == 255) || (i == 2 && BTN_RIGHT == 255) || (i == 3 && ENC_BTNB == 255)) continue;
+ if ((i == 0 && BTN_LEFT == 255) || (i == 1 && BTN_CENTER == 255) || (i == 2 && BTN_RIGHT == 255) || (i == 3 && ENC_BTNB == 255) || (i == 4 && BTN_UP == 255) || (i == 5 && BTN_DOWN == 255) || (i == 6 && ENC2_BTNB == 255)) continue;
button[i].attachClick([](void* p) {
onBtnClick((int)p);
}, (void*)i);
@@ -84,14 +98,20 @@ void loopControls() {
#if ENC_BTNL!=255
encoderLoop();
#endif
+#if ENC2_BTNL!=255
+ encoder2Loop();
+#endif
#if ISPUSHBUTTONS
for (unsigned i = 0; i < nrOfButtons; i++)
{
- if ((i == 0 && BTN_LEFT == 255) || (i == 1 && BTN_CENTER == 255) || (i == 2 && BTN_RIGHT == 255) || (i == 3 && ENC_BTNB == 255)) continue;
+ if ((i == 0 && BTN_LEFT == 255) || (i == 1 && BTN_CENTER == 255) || (i == 2 && BTN_RIGHT == 255) || (i == 3 && ENC_BTNB == 255) || (i == 4 && BTN_UP == 255) || (i == 5 && BTN_DOWN == 255) || (i == 6 && ENC2_BTNB == 255)) continue;
button[i].tick();
if (lpId >= 0) {
+ if(DSP_MODEL==DSP_DUMMY && (lpId==4 || lpId==5)) continue;
onBtnDuringLongPress(lpId);
+ yield();
}
+ yield();
}
#endif
#if IR_PIN!=255
@@ -111,6 +131,22 @@ void encoderLoop() {
}
#endif
+#if ENC2_BTNL!=255
+void encoder2Loop() {
+ long encNewPosition = encoder2.getCount() / 2;
+ if (encNewPosition != 0 && encNewPosition != enc2OldPosition) {
+ enc2OldPosition = encNewPosition;
+ encoder2.setCount(0);
+ uint8_t bp = 2;
+ if(ENC2_BTNB!=255){
+ bp = digitalRead(ENC2_BTNB);
+ }
+ if(bp==HIGH && display.mode!=STATIONS) display.swichMode(STATIONS);
+ controlsEvent(encNewPosition > 0);
+ }
+}
+#endif
+
#if IR_PIN!=255
void irBlink() {
if (player.mode == STOPPED) {
@@ -183,6 +219,7 @@ void irLoop() {
}
case IR_CODE_HASH: {
if (display.mode == NUMBERS) {
+ display.returnTile();
display.swichMode(PLAYER);
display.numOfNextStation = 0;
break;
@@ -236,14 +273,16 @@ void irLoop() {
#endif // if IR_PIN!=255
void onBtnLongPressStart(int id) {
- switch (id) {
- case 0:
- case 2: {
+ switch ((controlEvt_e)id) {
+ case EVT_BTNLEFT:
+ case EVT_BTNRIGHT:
+ case EVT_BTNUP:
+ case EVT_BTNDOWN:{
lpId = id;
break;
}
- case 1:
- case 3: {
+ case EVT_BTNCENTER:
+ case EVT_ENCBTNB: {
display.swichMode(display.mode == PLAYER ? STATIONS : PLAYER);
break;
}
@@ -251,9 +290,11 @@ void onBtnLongPressStart(int id) {
}
void onBtnLongPressStop(int id) {
- switch (id) {
- case 0:
- case 2: {
+ switch ((controlEvt_e)id) {
+ case EVT_BTNLEFT:
+ case EVT_BTNRIGHT:
+ case EVT_BTNUP:
+ case EVT_BTNDOWN:{
lpId = -1;
break;
}
@@ -272,15 +313,25 @@ boolean checklpdelay(int m, unsigned long &tstamp) {
void onBtnDuringLongPress(int id) {
if (checklpdelay(BTN_LONGPRESS_LOOP_DELAY, lpdelay)) {
- switch (id) {
- case 0: {
+ switch ((controlEvt_e)id) {
+ case EVT_BTNLEFT: {
controlsEvent(false);
break;
}
- case 2: {
+ case EVT_BTNRIGHT: {
controlsEvent(true);
break;
}
+ case EVT_BTNUP:
+ case EVT_BTNDOWN: {
+ if (display.mode == PLAYER) {
+ display.swichMode(STATIONS);
+ }
+ if (display.mode == STATIONS) {
+ controlsEvent(id==EVT_BTNDOWN);
+ }
+ break;
+ }
}
}
}
@@ -305,13 +356,14 @@ void controlsEvent(bool toRight) {
}
void onBtnClick(int id) {
- switch (id) {
- case 0: {
+ switch ((controlEvt_e)id) {
+ case EVT_BTNLEFT: {
controlsEvent(false);
break;
}
- case 1:
- case 3: {
+ case EVT_BTNCENTER:
+ case EVT_ENCBTNB:
+ case EVT_ENC2BTNB: {
if (display.mode == NUMBERS) {
display.numOfNextStation = 0;
display.swichMode(PLAYER);
@@ -325,26 +377,45 @@ void onBtnClick(int id) {
}
break;
}
- case 2: {
+ case EVT_BTNRIGHT: {
controlsEvent(true);
break;
}
+ case EVT_BTNUP:
+ case EVT_BTNDOWN: {
+ if(DSP_MODEL==DSP_DUMMY){
+ if(id==EVT_BTNUP){
+ player.next();
+ }else{
+ player.prev();
+ }
+ }else{
+ if (display.mode == PLAYER) {
+ display.swichMode(STATIONS);
+ }
+ if (display.mode == STATIONS) {
+ controlsEvent(id==EVT_BTNDOWN);
+ }
+ }
+ break;
+ }
}
}
void onBtnDoubleClick(int id) {
- switch (id) {
- case 0: {
+ switch ((controlEvt_e)id) {
+ case EVT_BTNLEFT: {
if (display.mode != PLAYER) return;
player.prev();
break;
}
- case 1:
- case 3: {
+ case EVT_BTNCENTER:
+ case EVT_ENCBTNB:
+ case EVT_ENC2BTNB: {
display.swichMode(display.mode == PLAYER ? STATIONS : PLAYER);
break;
}
- case 2: {
+ case EVT_BTNRIGHT: {
if (display.mode != PLAYER) return;
player.next();
break;
diff --git a/yoRadio/controls.h b/yoRadio/controls.h
index 0d15e67..7963c3f 100644
--- a/yoRadio/controls.h
+++ b/yoRadio/controls.h
@@ -1,11 +1,14 @@
#ifndef controls_h
#define controls_h
+enum controlEvt_e { EVT_BTNLEFT, EVT_BTNCENTER, EVT_BTNRIGHT, EVT_ENCBTNB, EVT_BTNUP, EVT_BTNDOWN, EVT_ENC2BTNB };
+
boolean checklpdelay(int m, unsigned long &tstamp);
void initControls();
void loopControls();
void encoderLoop();
+void encoder2Loop();
void irLoop();
void irNum(byte num);
void irBlink();
diff --git a/yoRadio/display.cpp b/yoRadio/display.cpp
index 30f87c7..5201ffe 100644
--- a/yoRadio/display.cpp
+++ b/yoRadio/display.cpp
@@ -260,7 +260,9 @@ void Display::swichMode(displayMode_e newmode) {
volume();
#endif
} else {
- meta.lock();
+ if (newmode != NUMBERS) {
+ meta.lock();
+ }
title1.lock();
if (TITLE_SIZE2 != 0) title2.lock();
#ifdef CLOCK_SPACE
@@ -271,7 +273,8 @@ void Display::swichMode(displayMode_e newmode) {
dsp.frameTitle("VOLUME");
}
if (newmode == NUMBERS) {
- dsp.frameTitle("STATION");
+ //dsp.frameTitle("STATION");
+ meta.reset();
}
if (newmode == STATIONS) {
currentPlItem = config.store.lastStation;
@@ -305,6 +308,11 @@ void Display::drawPlaylist() {
}
void Display::drawNextStationNum(uint16_t num) {
+ char plMenu[1][40];
+ char currentItemText[40] = {0};
+ config.fillPlMenu(plMenu, num, 1);
+ strlcpy(currentItemText, plMenu[0], 39);
+ meta.setText(dsp.utf8Rus(currentItemText, true));
dsp.drawNextStationNum(num);
}
@@ -319,6 +327,7 @@ void Display::loop() {
break;
}
case NUMBERS: {
+ meta.loop();
break;
}
case STATIONS: {
@@ -354,6 +363,12 @@ void Display::station() {
netserver.requestOnChange(STATION, 0);
}
+void Display::returnTile(){
+ meta.setText(dsp.utf8Rus(config.station.name, true));
+ meta.reset();
+ dsp.loop();
+}
+
void Display::title(const char *str) {
const char *title = str;
char ttl[BUFLEN / 2] = { 0 };
diff --git a/yoRadio/display.h b/yoRadio/display.h
index 67e3580..ab3970d 100644
--- a/yoRadio/display.h
+++ b/yoRadio/display.h
@@ -55,6 +55,7 @@ class Display {
void bootLogo();
void station();
void title(const char *str);
+ void returnTile();
void time(bool redraw = false);
void volume();
void ip();
diff --git a/yoRadio/options.h b/yoRadio/options.h
index 8aa5ec4..4ad7a46 100644
--- a/yoRadio/options.h
+++ b/yoRadio/options.h
@@ -1,7 +1,7 @@
#ifndef options_h
#define options_h
-#define VERSION "0.5.020"
+#define VERSION "0.5.035"
/*******************************************************
DO NOT EDIT THIS FILE.
@@ -96,6 +96,22 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#define ENC_HALFQUARD true
#endif
+#ifndef ENC2_BTNL
+ #define ENC2_BTNL 255
+#endif
+#ifndef ENC2_BTNB
+ #define ENC2_BTNB 255
+#endif
+#ifndef ENC2_BTNR
+ #define ENC2_BTNR 255
+#endif
+#ifndef ENC2_INTERNALPULLUP
+ #define ENC2_INTERNALPULLUP true
+#endif
+#ifndef ENC2_HALFQUARD
+ #define ENC2_HALFQUARD true
+#endif
+
/* BUTTONS */
#ifndef BTN_LEFT
#define BTN_LEFT 255
@@ -106,6 +122,12 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#ifndef BTN_RIGHT
#define BTN_RIGHT 255
#endif
+#ifndef BTN_UP
+ #define BTN_UP 255
+#endif
+#ifndef BTN_DOWN
+ #define BTN_DOWN 255
+#endif
#ifndef BTN_INTERNALPULLUP
#define BTN_INTERNALPULLUP true
#endif
diff --git a/yoRadio/src/LiquidCrystalI2C/LiquidCrystalI2CEx.cpp b/yoRadio/src/LiquidCrystalI2C/LiquidCrystalI2CEx.cpp
index 6a5a091..1699b2c 100644
--- a/yoRadio/src/LiquidCrystalI2C/LiquidCrystalI2CEx.cpp
+++ b/yoRadio/src/LiquidCrystalI2C/LiquidCrystalI2CEx.cpp
@@ -64,7 +64,7 @@ void LiquidCrystal_I2C::init_priv()
if((_sda_pin==255 && _scl_pin==255) || (_sda_pin==21 && _scl_pin==22)){
Wire.begin();
}else{
- Wire.begin(_sda_pin, _scl_pin, (uint32_t)100000);
+ Wire.begin((int)_sda_pin, (int)_scl_pin, (uint32_t)100000);
}
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
begin(_cols, _rows);
diff --git a/yoRadio/src/displays/displayLC1602.cpp b/yoRadio/src/displays/displayLC1602.cpp
index ad72d2b..1b3856d 100644
--- a/yoRadio/src/displays/displayLC1602.cpp
+++ b/yoRadio/src/displays/displayLC1602.cpp
@@ -64,7 +64,7 @@ void DisplayLC1602::getScrolBbounds(const char* text, const char* separator, byt
}
void DisplayLC1602::clearScroll(uint16_t texttop, uint16_t textheight, uint16_t bg) {
- for(uint16_t x=0; x