diff --git a/README.md b/README.md index 4656321..b29a50f 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,9 @@ https://aliexpress.com/item/32965676064.html - or **Nokia5110** 84x48 SPI https://aliexpress.com/item/1005001621837569.htmlz ##### Controls -Three tact buttons or Encoder or all together +- Three tact buttons https://www.aliexpress.com/item/32907144687.html +- Encoder https://www.aliexpress.com/item/32873198060.html +- IR Control https://www.aliexpress.com/item/32562721229.html --- ## Connection tables @@ -85,10 +87,10 @@ Three tact buttons or Encoder or all together _\#\# Important! You must choose between I2S DAC and VS1053 by disabling the second module in the settings (see below)_ -| Buttons, Encoder | ESP-32 | options.h | +| Buttons, Encoder, LED, IR | ESP-32 | options.h | | ------ | ------ | ------ | | GND | GND | - | -| PIN | * | ENC_BTNx, BTN_xxx | +| PIN | * | ENC_BTNx, BTN_xxx, LED_BUILTIN, IR_PIN | _\* Any free pin, configured in options.h_ \ _\** GPIOs 34-39 don't have software pullup/down functions. For encoder/buttons use an external pullup resistor, 10 kOhm works here_ @@ -96,7 +98,7 @@ _\** GPIOs 34-39 don't have software pullup/down functions. For encoder/buttons --- ## Dependencies #### Libraries: -Adafruit_GFX, Adafruit_ST7735\*, Adafruit_SSD1306\*, Adafruit_PCD8544\*, (\* depending on display model), ESP32Encoder, OneButton, [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer), [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) +Adafruit_GFX, Adafruit_ST7735\*, Adafruit_SSD1306\*, Adafruit_PCD8544\*, (\* depending on display model), ESP32Encoder, OneButton, IRremoteESP8266, [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer), [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) #### Tool: [ESP32 Filesystem Uploader](https://randomnerdtutorials.com/install-esp32-filesystem-uploader-arduino-ide/) @@ -184,6 +186,13 @@ _\*this step can be skipped if you add WiFiSSID WiFiPassword pairs to the [yoRad --- ## Version history +#### v0.4.292 +- added support for IR control +- new options in options.h (ENC_INTERNALPULLUP, ENC_HALFQUARD, BTN_INTERNALPULLUP, VOL_STEP) _//Thanks for [Buska1968](https://4pda.to/forum/index.php?s=&showtopic=1010378&view=findpost&p=113385448)_ +- сompilation error for module SSD1306 with arduino-esp32 version newest than 2.0.0 +- fix compiler warnings in options.h +- fix some compiler warnings + #### v0.4.260 - added control of balance and equalizer for VS1053 - **TFT_ROTATE** and st7735 **DTYPE** moved to myoptions.h diff --git a/yoRadio/config.cpp b/yoRadio/config.cpp index 8fed721..82e35aa 100644 --- a/yoRadio/config.cpp +++ b/yoRadio/config.cpp @@ -331,6 +331,7 @@ bool Config::saveWifi(const char* post) { file.print(post); file.close(); ESP.restart(); + return true; } } @@ -350,4 +351,5 @@ bool Config::initNetwork() { } } file.close(); + return true; } diff --git a/yoRadio/controls.cpp b/yoRadio/controls.cpp index c9912e2..4788c9a 100644 --- a/yoRadio/controls.cpp +++ b/yoRadio/controls.cpp @@ -4,29 +4,55 @@ #include "player.h" #include "display.h" -#include -#include "OneButton.h" - long encOldPosition = 0; +#if BTN_LEFT!=255 || BTN_LEFT!=255 || BTN_RIGHT!=255 || ENC_BTNL!=255 +#include "OneButton.h" +#endif + #if ENC_BTNL!=255 +#include ESP32Encoder encoder; OneButton encbutton(ENC_BTNB, true); #endif + #if BTN_LEFT!=255 -OneButton btnleft(BTN_LEFT, true); +OneButton btnleft(BTN_LEFT, true, BTN_INTERNALPULLUP); #endif #if BTN_CENTER!=255 -OneButton btncenter(BTN_CENTER, true); +OneButton btncenter(BTN_CENTER, true, BTN_INTERNALPULLUP); #endif #if BTN_RIGHT!=255 -OneButton btnright(BTN_RIGHT, true); +OneButton btnright(BTN_RIGHT, true, BTN_INTERNALPULLUP); +#endif + +#if IR_PIN!=255 +#include +#include +#include +#include +#include +#include + +byte irVolRepeat=0; +const uint16_t kCaptureBufferSize = 1024; +const uint8_t kTimeout = IR_TIMEOUT; +const uint16_t kMinUnknownSize = 12; +const uint8_t kTolerancePercentage = IR_TLP; //kTolerance; // kTolerance is normally 25% +#define LEGACY_TIMING_INFO false + +IRrecv irrecv(IR_PIN, kCaptureBufferSize, kTimeout, true); +decode_results irResults; #endif void initControls() { #if ENC_BTNL!=255 - ESP32Encoder::useInternalWeakPullResistors = UP; - encoder.attachHalfQuad(ENC_BTNL, ENC_BTNR); + ESP32Encoder::useInternalWeakPullResistors = ENC_INTERNALPULLUP ? UP : DOWN; + if (ENC_HALFQUARD) { + encoder.attachHalfQuad(ENC_BTNL, ENC_BTNR); + } else { + encoder.attachFullQuad(ENC_BTNL, ENC_BTNR); + } encbutton.attachClick(onEncClick); encbutton.attachDoubleClick(onEncDoubleClick); encbutton.attachLongPressStart(onEncLPStart); @@ -44,6 +70,14 @@ void initControls() { btnright.attachClick(onRightClick); btnright.attachDoubleClick(onRightDoubleClick); #endif +#if IR_PIN!=255 + assert(irutils::lowLevelSanityCheck() == 0); +#if DECODE_HASH + irrecv.setUnknownThreshold(kMinUnknownSize); +#endif // DECODE_HASH + irrecv.setTolerance(kTolerancePercentage); + irrecv.enableIRIn(); +#endif // IR_PIN!=255 } void loopControls() { @@ -59,6 +93,9 @@ void loopControls() { #endif #if BTN_RIGHT!=255 btnright.tick(); +#endif +#if IR_PIN!=255 + irLoop(); #endif yield(); } @@ -74,6 +111,58 @@ void encoderLoop() { } #endif +#if IR_PIN!=255 +void irLoop() { + if (irrecv.decode(&irResults)) { + if(IR_DEBUG) { + Serial.print(resultToHumanReadableBasic(&irResults)); + return; + } + if (!irResults.repeat && irResults.command!=0) { + irVolRepeat = 0; + } + switch (irVolRepeat) { + case 1: { + controlsEvent(display.mode == STATIONS ? false : true); + break; + } + case 2: { + controlsEvent(display.mode == STATIONS ? true : false); + break; + } + } + switch (irResults.value) { + case IR_CODE_PLAY: { + onEncClick(); + break; + } + case IR_CODE_PREV: { + player.prev(); + break; + } + case IR_CODE_NEXT: { + player.next(); + break; + } + case IR_CODE_VOLUP: { + controlsEvent(display.mode == STATIONS ? false : true); + irVolRepeat = 1; + break; + } + case IR_CODE_VOLDN: { + controlsEvent(display.mode == STATIONS ? true : false); + irVolRepeat = 2; + break; + } + case IR_CODE_HASH: { + display.swichMode(display.mode == PLAYER ? STATIONS : PLAYER); + break; + } + } + } +} +#endif + void onEncClick() { if (display.mode == PLAYER) { player.toggle(); diff --git a/yoRadio/controls.h b/yoRadio/controls.h index ca3bb29..3955528 100644 --- a/yoRadio/controls.h +++ b/yoRadio/controls.h @@ -1,12 +1,14 @@ #ifndef controls_h #define controls_h + void initControls(); void loopControls(); void onEncClick(); void onEncDoubleClick(); void onEncLPStart(); void encoderLoop(); +void irLoop(); void controlsEvent(bool toRight); diff --git a/yoRadio/data/data/wifi.csv b/yoRadio/data/data/wifi.csv deleted file mode 100644 index e69de29..0000000 diff --git a/yoRadio/display.cpp b/yoRadio/display.cpp index a5817b0..ed12b2c 100644 --- a/yoRadio/display.cpp +++ b/yoRadio/display.cpp @@ -38,7 +38,7 @@ void ticks() { #define SCROLLTIME 83 #endif -void Scroll::init(char *sep, byte tsize, byte top, uint16_t dlay, uint16_t fgcolor, uint16_t bgcolor) { +void Scroll::init(const char *sep, byte tsize, byte top, uint16_t dlay, uint16_t fgcolor, uint16_t bgcolor) { textsize = tsize; texttop = top; fg = fgcolor; diff --git a/yoRadio/display.h b/yoRadio/display.h index 7838f6c..e86538f 100644 --- a/yoRadio/display.h +++ b/yoRadio/display.h @@ -10,7 +10,7 @@ enum displayMode_e { PLAYER, VOL, STATIONS }; class Scroll { public: Scroll() { }; - void init(char *sep, byte tsize, byte top, uint16_t dlay, uint16_t fgcolor, uint16_t bgcolor); + void init(const char *sep, byte tsize, byte top, uint16_t dlay, uint16_t fgcolor, uint16_t bgcolor); void setText(const char *txt); void loop(); void reset(); diff --git a/yoRadio/netserver.cpp b/yoRadio/netserver.cpp index d5a4097..1c5391d 100644 --- a/yoRadio/netserver.cpp +++ b/yoRadio/netserver.cpp @@ -53,6 +53,7 @@ bool NetServer::begin() { packet.println(WiFi.localIP()); }); } + return true; } void NetServer::loop() { @@ -122,6 +123,7 @@ bool NetServer::savePlaylist(const char* post) { file.print(post); file.close(); netserver.requestOnChange(PLAYLISTSAVED, 0); + return true; } } diff --git a/yoRadio/options.h b/yoRadio/options.h index 1cb769c..a77a0df 100644 --- a/yoRadio/options.h +++ b/yoRadio/options.h @@ -1,7 +1,11 @@ #ifndef options_h #define options_h -#define VERSION "0.4.260" +#define VERSION "0.4.292" + +#if __has_include("myoptions.h") +#include "myoptions.h" // <- write your variable values here +#endif /* DISPLAY MODEL * 0 - DUMMY @@ -9,59 +13,107 @@ * 2 - SSD1306 * 3 - NOKIA5110 */ -#define DSP_MODEL 1 +#ifndef DSP_MODEL + #define DSP_MODEL 1 +#endif /* * The connection tables are located here https://github.com/e2002/yoradio#connection-tables */ -/* - * TFT DISPLAY - */ -#define TFT_CS 5 -#define TFT_RST 15 // Or set to -1 and connect to Esp EN pin -//#define TFT_RST -1 // we use the seesaw for resetting to save a pin -#define TFT_DC 4 -/* - * OLED I2C DISPLAY - */ -#define I2C_SDA 13 -#define I2C_SCL 14 -#define I2C_RST -1 -/* - * VS1053 - */ -#define VS1053_CS 255 // 27 -#define VS1053_DCS 25 -#define VS1053_DREQ 26 -#define VS1053_RST -1 // set to -1 if connected to Esp EN pin -/* - * I2S DAC - */ -#define I2S_DOUT 27 // DIN connection -#define I2S_BCLK 26 // BCLK Bit clock -#define I2S_LRC 25 // WSEL Left Right Clock -/* - * ENCODER - */ -#define ENC_BTNL 255 -#define ENC_BTNB 255 -#define ENC_BTNR 255 -/* - * BUTTONS - */ -#define BTN_LEFT 255 -#define BTN_CENTER 255 -#define BTN_RIGHT 255 -/* - * ESP DEVBOARD - */ -#define LED_BUILTIN 2 +/* TFT DISPLAY */ +#ifndef TFT_CS + #define TFT_CS 5 +#endif +#ifndef TFT_RST + #define TFT_RST 15 // Or set to -1 and connect to Esp EN pin +#endif +#ifndef TFT_DC + #define TFT_DC 4 +#endif -/* - * Other settings. You can overwrite them in the myoptions.h file - */ -#define TFT_ROTATE 3 // display rotation. 0 - 0, 1 - 90, 2 - 180, 3 - 270 degrees +/* OLED I2C DISPLAY */ +#ifndef I2C_SDA + #define I2C_SDA 13 +#endif +#ifndef I2C_SCL + #define I2C_SCL 14 +#endif +#ifndef I2C_RST + #define I2C_RST -1 +#endif + +/* VS1053 */ +#ifndef VS1053_CS + #define VS1053_CS 255 // 27 +#endif +#ifndef VS1053_DCS + #define VS1053_DCS 25 +#endif +#ifndef VS1053_DREQ + #define VS1053_DREQ 26 +#endif +#ifndef VS1053_RST + #define VS1053_RST -1 // set to -1 if connected to Esp EN pin +#endif + +/* I2S DAC */ +#ifndef I2S_DOUT + #define I2S_DOUT 27 // DIN connection +#endif +#ifndef I2S_BCLK + #define I2S_BCLK 26 // BCLK Bit clock +#endif +#ifndef I2S_LRC + #define I2S_LRC 25 // WSEL Left Right Clock +#endif + +/* ENCODER */ +#ifndef ENC_BTNL + #define ENC_BTNL 255 +#endif +#ifndef ENC_BTNB + #define ENC_BTNB 255 +#endif +#ifndef ENC_BTNR + #define ENC_BTNR 255 +#endif +#ifndef ENC_INTERNALPULLUP // Thanks for Buska1968. See this topic: https://4pda.to/forum/index.php?s=&showtopic=1010378&view=findpost&p=113385448 + #define ENC_INTERNALPULLUP true +#endif +#ifndef ENC_HALFQUARD + #define ENC_HALFQUARD true +#endif + +/* BUTTONS */ +#ifndef BTN_LEFT + #define BTN_LEFT 255 +#endif +#ifndef BTN_CENTER + #define BTN_CENTER 255 +#endif +#ifndef BTN_RIGHT + #define BTN_RIGHT 255 +#endif +#ifndef BTN_INTERNALPULLUP + #define BTN_INTERNALPULLUP true +#endif + +/* ESP DEVBOARD */ +#ifndef LED_BUILTIN + #define LED_BUILTIN 2 +#endif + +/* Other settings. You can overwrite them in the myoptions.h file */ +#ifndef TFT_ROTATE + #define TFT_ROTATE 3 // display rotation. 0 - 0, 1 - 90, 2 - 180, 3 - 270 degrees +#endif +#ifndef TFT_CONTRAST + #define TFT_CONTRAST 55 // Nokia 5110 contrast +#endif +#ifndef VOL_STEP + #define VOL_STEP 1 // Encoder vol step +#endif /* *** ST7735 display submodel *** @@ -71,10 +123,74 @@ INITR_144GREENTAB // 1.44' https://aliexpress.ru/item/1005002822797745.html INITR_GREENTAB INITR_REDTAB */ -#define DTYPE INITR_BLACKTAB - -#if __has_include("myoptions.h") -#include "myoptions.h" +#ifndef DTYPE + #define DTYPE INITR_BLACKTAB #endif +/* IR */ +#ifndef IR_PIN + #define IR_PIN 255 +#endif +#ifndef IR_DEBUG + #define IR_DEBUG 0 // 1 - for capture ir codes from serial +#endif +#ifndef IR_TIMEOUT + #define IR_TIMEOUT 80 // kTimeout, see IRremoteESP8266 documentation +#endif +#ifndef IR_TLP + #define IR_TLP 40 // kTolerancePercentage, see IRremoteESP8266 documentation +#endif +#ifndef IR_CODE_PLAY + #define IR_CODE_PLAY 0xFF02FD +#endif +#ifndef IR_CODE_PREV + #define IR_CODE_PREV 0xFF22DD +#endif +#ifndef IR_CODE_NEXT + #define IR_CODE_NEXT 0xFFC23D +#endif +#ifndef IR_CODE_VOLUP + #define IR_CODE_VOLUP 0xFF629D +#endif +#ifndef IR_CODE_VOLDN + #define IR_CODE_VOLDN 0xFFA857 +#endif +#ifndef IR_CODE_NUM0 + #define IR_CODE_NUM0 0xFF4AB5 +#endif +#ifndef IR_CODE_NUM1 + #define IR_CODE_NUM1 0xFF6897 +#endif +#ifndef IR_CODE_NUM2 + #define IR_CODE_NUM2 0xFF9867 +#endif +#ifndef IR_CODE_NUM3 + #define IR_CODE_NUM3 0xFFB04F +#endif +#ifndef IR_CODE_NUM4 + #define IR_CODE_NUM4 0xFF30CF +#endif +#ifndef IR_CODE_NUM5 + #define IR_CODE_NUM5 0xFF18E7 +#endif +#ifndef IR_CODE_NUM6 + #define IR_CODE_NUM6 0xFF7A85 +#endif +#ifndef IR_CODE_NUM7 + #define IR_CODE_NUM7 0xFF10EF +#endif +#ifndef IR_CODE_NUM8 + #define IR_CODE_NUM8 0xFF38C7 +#endif +#ifndef IR_CODE_NUM9 + #define IR_CODE_NUM9 0xFF5AA5 +#endif +#ifndef IR_CODE_HASH + #define IR_CODE_HASH 0xFF52AD // Toggle playlist mode +#endif +#ifndef IR_CODE_AST + #define IR_CODE_AST 0xFF42BD +#endif + + #endif diff --git a/yoRadio/player.cpp b/yoRadio/player.cpp index 3af6ac6..b6f7eac 100644 --- a/yoRadio/player.cpp +++ b/yoRadio/player.cpp @@ -51,7 +51,6 @@ void Player::stopInfo() { } void Player::loop() { - //Serial.println(mode == PLAYING?"mode == PLAYING":"mode == STOPPED"); if (mode == PLAYING) { Audio::loop(); } else { @@ -129,12 +128,16 @@ void Player::toggle() { void Player::stepVol(bool up) { if (up) { - if (config.store.volume < 254) { - setVol(config.store.volume + 1, false); + if (config.store.volume <= 254 - VOL_STEP) { + setVol(config.store.volume + VOL_STEP, false); + }else{ + setVol(254, false); } } else { - if (config.store.volume > 0) { - setVol(config.store.volume - 1, false); + if (config.store.volume >= VOL_STEP) { + setVol(config.store.volume - VOL_STEP, false); + }else{ + setVol(0, false); } } } diff --git a/yoRadio/src/audioI2S/Audio.cpp b/yoRadio/src/audioI2S/Audio.cpp index 3a2394e..962b59a 100644 --- a/yoRadio/src/audioI2S/Audio.cpp +++ b/yoRadio/src/audioI2S/Audio.cpp @@ -4246,7 +4246,7 @@ void Audio::setBalance(int8_t bal){ // bal -16...16 } //--------------------------------------------------------------------------------------------------------------------- void Audio::setVolume(uint8_t vol) { // vol 22 steps, 0...21 - if(vol > 256) vol = 256; + if(vol > 255) vol = 255; //volume = map(eeprom_config.volume, 0, 21, 0, 255); //m_vol = map(vol, 0, 254, 0, 64); m_vol = vol; diff --git a/yoRadio/src/audioVS1053/audioVS1053Ex.cpp b/yoRadio/src/audioVS1053/audioVS1053Ex.cpp index f8a21b1..6ddfd60 100644 --- a/yoRadio/src/audioVS1053/audioVS1053Ex.cpp +++ b/yoRadio/src/audioVS1053/audioVS1053Ex.cpp @@ -376,7 +376,7 @@ void Audio::setVolume(uint8_t vol){ write_register(SCI_VOL, value); } //--------------------------------------------------------------------------------------------------------------------- -void Audio::setTone(uint8_t *rtone){ // Set bass/treble (4 nibbles) +void Audio::setTone(int8_t *rtone){ // Set bass/treble (4 nibbles) // Set tone characteristics. See documentation for the 4 nibbles. uint16_t value=0; // Value to send to SCI_BASS @@ -400,7 +400,7 @@ void Audio::setTone(int8_t gainLowPass, int8_t gainBandPass, int8_t gainHighPass if(gainLowPass>15) gainLowPass=15; if(gainBandPass<0) gainBandPass=0; if(gainBandPass>13) gainBandPass=13; - uint8_t rtone[] = {map(gainHighPass, -16, 16, -8, 7), 2+gainBandPass, gainLowPass, 15-gainBandPass}; + int8_t rtone[] = {(int8_t)map(gainHighPass, -16, 16, -8, 7), (int8_t)(2+gainBandPass), gainLowPass, (int8_t)(15-gainBandPass)}; setTone(rtone); } void Audio::setBalance(int8_t bal){ diff --git a/yoRadio/src/audioVS1053/audioVS1053Ex.h b/yoRadio/src/audioVS1053/audioVS1053Ex.h index 2957e7f..ccbcacb 100644 --- a/yoRadio/src/audioVS1053/audioVS1053Ex.h +++ b/yoRadio/src/audioVS1053/audioVS1053Ex.h @@ -248,7 +248,7 @@ public: void begin() ; // Begin operation. Sets pins correctly and prepares SPI bus. void stop_mp3client(); void setVolume(uint8_t vol); // Set the player volume.Level from 0-21, higher is louder. - void setTone(uint8_t* rtone); // Set the player baas/treble, 4 nibbles for treble gain/freq and bass gain/freq + void setTone(int8_t* rtone); // Set the player baas/treble, 4 nibbles for treble gain/freq and bass gain/freq uint8_t getVolume(); // Get the current volume setting, higher is louder. void printDetails(const char* str); // Print configuration details to serial output. const char* printVersion(); // Print ID and version of vs1053 chip diff --git a/yoRadio/src/displays/displayN5110.h b/yoRadio/src/displays/displayN5110.h index 6b5b5f8..7e34c7d 100644 --- a/yoRadio/src/displays/displayN5110.h +++ b/yoRadio/src/displays/displayN5110.h @@ -10,7 +10,6 @@ #define TFT_LINEHGHT 8 #define TFT_FRAMEWDT 0 -#define TFT_CONTRAST 55 #define PLMITEMS 7 #define PLMITEMLENGHT 40 diff --git a/yoRadio/src/displays/displaySSD1306.cpp b/yoRadio/src/displays/displaySSD1306.cpp index 25af264..76488d5 100644 --- a/yoRadio/src/displays/displaySSD1306.cpp +++ b/yoRadio/src/displays/displaySSD1306.cpp @@ -123,7 +123,7 @@ void DisplaySSD1306::apScreen() { } void DisplaySSD1306::initD(uint16_t &screenwidth, uint16_t &screenheight) { - I2CSSD1306.begin(I2C_SDA, I2C_SCL, 400000); + I2CSSD1306.begin(I2C_SDA, I2C_SCL, (uint32_t)400000); if (!begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1306 allocation failed")); for (;;); // Don't proceed, loop forever