diff --git a/README.md b/README.md index d6de8eb..aa2a49f 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ # ESPuino - rfid-based musiccontroller based on ESP32 with I2S-DAC-support ## NEWS -* EN: I've set up a primarily German-speaking community with much documentation. Also an international corner for non-German-speakers is available at https://forum.espuino.de. Github-Login can be used there but it's not necessary. +* EN: I've set up a primarily German-speaking community with much documentation. Also an international corner for non-German-speakers is available at https://forum.espuino.de. Github-Login can be used there but it's not mandatory. * DE: Ich habe ein primär deutschsprachiges Forum aufgesetzt, welches ich mit reichlich Doku versehen habe. Würde mich freuen, euch dort zu sehen: https://forum.espuino.de. Ihr könnt euch dort mit eurem Github-Login einloggen, jedoch auch "normal" anmelden. Dokumenation findet ihr insbesondere hier: https://forum.espuino.de/c/dokumentation/anleitungen/10 ## Build status ![build workflow](https://github.com/biologist79/ESPuino/actions/workflows/build.yml/badge.svg) ## Changelog -Moved to [another location](changelog.md). Only last three events are kept: -* 05.03.2021: Added support for remote control via infrared. Make sure to enable `IR_CONTROL_ENABLE` to use this feature and don't forget to assign corresponding rc-commands of *your* remote control to actions. +Last three events: * 19.03.2021: Added support for port-expander PCA9555. Can be used for everything, that is "button-like": buttons, headphone-detect, PN5180.IRQ. * 28.03.2021: Added support for fileseek. With commands `CMD_SEEK_FORWARDS` and `CMD_SEEK_BACKWARDS` it's possible to jump a number of seconds defined in `jumpOffset`. +* 30.03.2021: Added support for stereo/mono via `PLAY_MONO_SPEAKER`. If active, mono is used while headphones remain stereo (if `HEADPHONE_ADJUST_ENABLE` is active). ## Known bugs * Some webstreams don't run. Guess it's a combination of saturated connection-pool and lack of heap-memory. Works probably better if ESP32-WROVER (e.g. Lolin D32 pro) is used, as this chip has PSRAM. Advice: Don't enable modules (e.g. MQTT) if you don't need them as this could save memory (and trouble). * English translation/version for webgui is currently pretty outdated. This will be fixed soon when i18n-support will be integrated. diff --git a/changelog.md b/changelog.md index 4366ae2..b5aeeb7 100644 --- a/changelog.md +++ b/changelog.md @@ -33,4 +33,5 @@ * 26.02.2021: Shutdown via webgui is now available. * 05.03.2021: Added support for remote control via infrared. Make sure to enable `IR_CONTROL_ENABLE` to use this feature and don't forget to assign corresponding rc-commands of *your* remote control to actions. * 19.03.2021: Added support for port-expander PCA9555. Can be used for everything, that is "button-like": buttons, headphone-detect, PN5180.IRQ. -* 28.03.2021: Added support for fileseek. With commands `CMD_SEEK_FORWARDS` and `CMD_SEEK_BACKWARDS` it's possible to jump a number of seconds defined in `jumpOffset`. \ No newline at end of file +* 28.03.2021: Added support for fileseek. With commands `CMD_SEEK_FORWARDS` and `CMD_SEEK_BACKWARDS` it's possible to jump a number of seconds defined in `jumpOffset`. +* 30.03.2021: Added support for stereo/mono via `PLAY_MONO_SPEAKER`. If active, mono is used while headphones remain stereo (if `HEADPHONE_ADJUST_ENABLE` is active). \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index f3a3bac..a6e3d81 100644 --- a/platformio.ini +++ b/platformio.ini @@ -60,7 +60,7 @@ lib_deps = ${common.lib_deps_builtin} ${common.lib_deps_external} https://github.com/miguelbalboa/rfid.git - https://github.com/tueddy/PN5180-Library.git + https://github.com/tueddy/PN5180-Library.git#0c200f5 extra_scripts = ${env:common.extra_scripts} upload_port = /dev/cu.SLAB_USBtoUART monitor_port = /dev/cu.SLAB_USBtoUART @@ -79,7 +79,7 @@ lib_deps = ${common.lib_deps_builtin} ${common.lib_deps_external} https://github.com/miguelbalboa/rfid.git - https://github.com/tueddy/PN5180-Library.git + https://github.com/tueddy/PN5180-Library.git#0c200f5 extra_scripts = ${env:common.extra_scripts} upload_port = /dev/cu.wchusbserial1410 monitor_port = /dev/cu.wchusbserial1410 @@ -97,7 +97,7 @@ lib_deps = ${common.lib_deps_builtin} ${common.lib_deps_external} https://github.com/miguelbalboa/rfid.git - https://github.com/tueddy/PN5180-Library.git + https://github.com/tueddy/PN5180-Library.git#0c200f5 extra_scripts = ${env:common.extra_scripts} upload_port = /dev/cu.wchusbserial1410 monitor_port = /dev/cu.wchusbserial1410 @@ -120,7 +120,7 @@ lib_deps = ${common.lib_deps_builtin} ${common.lib_deps_external} https://github.com/miguelbalboa/rfid.git - https://github.com/tueddy/PN5180-Library.git + https://github.com/tueddy/PN5180-Library.git#0c200f5 extra_scripts = ${env:common.extra_scripts} upload_port = /dev/cu.SLAB_USBtoUART monitor_port = /dev/cu.SLAB_USBtoUART @@ -138,7 +138,7 @@ lib_deps = ${common.lib_deps_builtin} ${common.lib_deps_external} https://github.com/miguelbalboa/rfid.git - https://github.com/tueddy/PN5180-Library.git + https://github.com/tueddy/PN5180-Library.git#0c200f5 extra_scripts = ${env:common.extra_scripts} upload_port = /dev/cu.SLAB_USBtoUART monitor_port = /dev/cu.SLAB_USBtoUART @@ -156,7 +156,7 @@ lib_deps = ${common.lib_deps_builtin} ${common.lib_deps_external} https://github.com/miguelbalboa/rfid.git - https://github.com/tueddy/PN5180-Library.git + https://github.com/tueddy/PN5180-Library.git#0c200f5 extra_scripts = ${env:common.extra_scripts} upload_port = /dev/cu.SLAB_USBtoUART monitor_port = /dev/cu.SLAB_USBtoUART diff --git a/src/logmessages.h b/src/logmessages.h index ad34f95..f21c671 100644 --- a/src/logmessages.h +++ b/src/logmessages.h @@ -123,7 +123,7 @@ static const char restoredMaxLoudnessForSpeakerFromNvs[] PROGMEM = "Maximale Lau static const char restoredMaxLoudnessForHeadphoneFromNvs[] PROGMEM = "Maximale Lautstärke für Kopfhörer wurde aus NVS geladen"; static const char wroteMaxLoudnessForSpeakerToNvs[] PROGMEM = "Maximale Lautstärke für Lautsprecher wurde ins NVS geschrieben."; static const char wroteMaxLoudnessForHeadphoneToNvs[] PROGMEM = "Maximale Lautstärke für Kopfhörer wurde ins NVS geschrieben."; -static const char maxVolumeSet[] PROGMEM = "Maximale Lautstärke wurde gesetzt auf "; +static const char maxVolumeSet[] PROGMEM = "Maximale Lautstärke wurde gesetzt auf"; static const char wroteMqttFlagToNvs[] PROGMEM = "MQTT-Flag wurde ins NVS geschrieben."; static const char restoredMqttActiveFromNvs[] PROGMEM = "MQTT-Flag (aktiviert) wurde aus NVS geladen"; static const char restoredMqttDeactiveFromNvs[] PROGMEM = "MQTT-Flag (deaktiviert) wurde aus NVS geladen"; @@ -176,4 +176,6 @@ static const char staticIPConfigFailed[] PROGMEM = "Statische IP-Konfiguration f static const char wakeUpRfidNoIso14443[] PROGMEM = "ESP32 wurde vom Kartenleser aus dem Deepsleep aufgeweckt. Allerdings wurde keine ISO-14443-Karte gefunden. Gehe zurück in den Deepsleep..."; static const char lowPowerCardSuccess[] PROGMEM = "Kartenerkennung via 'low power' erfolgreich durchgeführt"; static const char rememberLastVolume[] PROGMEM = "Lautstärke vor dem letzten Shutdown wird wiederhergestellt. Dies überschreibt die Einstellung der initialen Lautstärke aus der GUI."; -static const char unableToStartFtpServer[] PROGMEM = "Der FTP-Server konnte nicht gestartet werden. Entweder weil er ist bereits gestartet oder kein WLAN verfügbar ist."; \ No newline at end of file +static const char unableToStartFtpServer[] PROGMEM = "Der FTP-Server konnte nicht gestartet werden. Entweder weil er ist bereits gestartet oder kein WLAN verfügbar ist."; +static const char newPlayModeStereo[] PROGMEM = "Neuer Modus: stereo"; +static const char newPlayModeMono[] PROGMEM = "Neuer Modus: mono"; \ No newline at end of file diff --git a/src/logmessages_EN.h b/src/logmessages_EN.h index 24b59c6..265ef64 100644 --- a/src/logmessages_EN.h +++ b/src/logmessages_EN.h @@ -123,7 +123,7 @@ static const char restoredMaxLoudnessForSpeakerFromNvs[] PROGMEM = "Restored max static const char restoredMaxLoudnessForHeadphoneFromNvs[] PROGMEM = "Restored maximum volume for headphone from NVS"; static const char wroteMaxLoudnessForSpeakerToNvs[] PROGMEM = "Wrote maximum volume for speaker to NVS."; static const char wroteMaxLoudnessForHeadphoneToNvs[] PROGMEM = "Wrote maximum volume for headphone to NVS."; -static const char maxVolumeSet[] PROGMEM = "Maximum volume set to "; +static const char maxVolumeSet[] PROGMEM = "Maximum volume set to"; static const char wroteMqttFlagToNvs[] PROGMEM = "Stored MQTT-flag to NVS."; static const char restoredMqttActiveFromNvs[] PROGMEM = "Restored MQTT-flag (enabled) from NVS"; static const char restoredMqttDeactiveFromNvs[] PROGMEM = "Restored MQTT-flag (disabled) from NVS"; @@ -175,4 +175,6 @@ static const char staticIPConfigFailed[] PROGMEM = "Static IP-configuration fail static const char wakeUpRfidNoIso14443[] PROGMEM = "Wakeup caused by low power card-detection. RF-field changed but no ISO-14443 card on reader was found. So I'll return back to sleep now..."; static const char lowPowerCardSuccess[] PROGMEM = "Switch to low power card-detection: success"; static const char rememberLastVolume[] PROGMEM = "Restored volume used before last shutdown. This overwrites the initial volume configured via webgui."; -static const char unableToStartFtpServer[] PROGMEM = "FTP-server cannot be started. This is because FTP-service is already active of because WiFi is unavailable."; \ No newline at end of file +static const char unableToStartFtpServer[] PROGMEM = "FTP-server cannot be started. This is because FTP-service is already active of because WiFi is unavailable."; +static const char newPlayModeStereo[] PROGMEM = "New mode: stereo"; +static const char newPlayModeMono[] PROGMEM = "New mode: mono"; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 55c5591..6bc17c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -132,6 +132,8 @@ typedef struct { // Bit field bool playlistFinished: 1; // If whole playlist is finished uint8_t playUntilTrackNumber: 6; // Number of tracks to play after which uC goes to sleep uint8_t seekmode: 2; // If seekmode is active and if yes: forward or backwards? + bool newPlayMono: 1; // true if mono; false if stereo (helper) + bool currentPlayMono: 1; // true if mono; false if stereo } playProps; playProps playProperties; @@ -1428,6 +1430,10 @@ void playAudio(void *parameter) { static Audio audio; audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); audio.setVolume(initVolume); + audio.forceMono(playProperties.currentPlayMono); + if (playProperties.currentPlayMono) { + audio.setTone(3,0,0); + } uint8_t currentVolume; @@ -1812,6 +1818,19 @@ void playAudio(void *parameter) { playProperties.seekmode = SEEK_NORMAL; } + // Handle if mono/stereo should be changed (e.g. if plugging headphones) + if (playProperties.newPlayMono != playProperties.currentPlayMono) { + playProperties.currentPlayMono = playProperties.newPlayMono; + audio.forceMono(playProperties.currentPlayMono); + if (playProperties.currentPlayMono) { + loggerNl(serialDebug, newPlayModeMono, LOGLEVEL_NOTICE); + audio.setTone(3,0,0); + } else { + loggerNl(serialDebug, newPlayModeStereo, LOGLEVEL_NOTICE); + audio.setTone(0,0,0); + } + } + // Calculate relative position in file (for neopixel) for SD-card-mode #ifdef NEOPIXEL_ENABLE if (!playProperties.playlistFinished && playProperties.playMode != WEBSTREAM) { @@ -2069,7 +2088,7 @@ void showLed(void *parameter) { } if (gotoSleep) { // If deepsleep is planned, turn off LEDs first in order to avoid LEDs still glowing when ESP32 is in deepsleep if (!turnedOffLeds) { - FastLED.clear(); + FastLED.clear(true); turnedOffLeds = true; } @@ -3857,8 +3876,14 @@ void setupVolume(void) { #else if (digitalReadFromAll(HP_DETECT)) { maxVolume = maxVolumeSpeaker; // 1 if headphone is not connected + #ifdef PLAY_MONO_SPEAKER + playProperties.newPlayMono = true; + #else + playProperties.newPlayMono = false; + #endif } else { maxVolume = maxVolumeHeadphone; // 0 if headphone is connected (put to GND) + playProperties.newPlayMono = false; // always stereo for headphones! } snprintf(logBuf, serialLoglength, "%s: %u", (char *) FPSTR(maxVolumeSet), maxVolume); loggerNl(serialDebug, logBuf, LOGLEVEL_INFO); @@ -3874,10 +3899,16 @@ void setupVolume(void) { if (headphoneLastDetectionState != currentHeadPhoneDetectionState && (millis() - headphoneLastDetectionTimestamp >= headphoneLastDetectionDebounce)) { if (currentHeadPhoneDetectionState) { maxVolume = maxVolumeSpeaker; + #ifdef PLAY_MONO_SPEAKER + playProperties.newPlayMono = true; + #else + playProperties.newPlayMono = false; + #endif } else { maxVolume = maxVolumeHeadphone; + playProperties.newPlayMono = false; // Always stereo for headphones if (currentVolume > maxVolume) { - volumeToQueueSender(maxVolume, true); // Lower volume for headphone if headphone's maxvolume is exceeded by volume set in speaker-mode + volumeToQueueSender(maxVolume, true); // Lower volume for headphone if headphone's maxvolume is exceeded by volume set in speaker-mode } } headphoneLastDetectionState = currentHeadPhoneDetectionState; @@ -4657,6 +4688,13 @@ void setup() { playProperties.trackFinished = NULL; playProperties.playlistFinished = true; playProperties.seekmode = SEEK_NORMAL; + #ifdef PLAY_MONO_SPEAKER + playProperties.newPlayMono = true; + playProperties.currentPlayMono = true; + #else + playProperties.newPlayMono = false; + playProperties.currentPlayMono = false; + #endif // Examples for serialized RFID-actions that are stored in NVS // #### diff --git a/src/settings.h b/src/settings.h index 72c4950..92a44be 100644 --- a/src/settings.h +++ b/src/settings.h @@ -31,7 +31,8 @@ //#define NEOPIXEL_REVERSE_ROTATION // Some Neopixels are adressed/soldered counter-clockwise. This can be configured here. #define LANGUAGE 1 // 1 = deutsch; 2 = english //#define STATIC_IP_ENABLE // Enables static IP-configuration (change static ip-section accordingly) - //#define HEADPHONE_ADJUST_ENABLE // Used to adjust (lower) volume for optional headphone-pcb (refer maxVolumeSpeaker / maxVolumeHeadphone) + //#define HEADPHONE_ADJUST_ENABLE // Used to adjust (lower) volume for optional headphone-pcb (refer maxVolumeSpeaker / maxVolumeHeadphone) and to enable stereo (if PLAY_MONO_SPEAKER is set) + #define PLAY_MONO_SPEAKER // If only one speaker is used enabling mono should make sense. Please note: headphones is always stereo (if HEADPHONE_ADJUST_ENABLE is active) #define SHUTDOWN_IF_SD_BOOT_FAILS // Will put ESP to deepsleep if boot fails due to SD. Really recommend this if there's in battery-mode no other way to restart ESP! Interval adjustable via deepsleepTimeAfterBootFails. #define MEASURE_BATTERY_VOLTAGE // Enables battery-measurement via GPIO (ADC) and voltage-divider //#define PLAY_LAST_RFID_AFTER_REBOOT // When restarting ESPuino, the last RFID that was active before, is recalled and played