diff --git a/Tonuino.ino b/Tonuino.ino index c6b19f57..1589b583 100644 --- a/Tonuino.ino +++ b/Tonuino.ino @@ -18,7 +18,10 @@ */ // uncomment the below line to enable five button support -//#define FIVEBUTTONS +#define FIVEBUTTONS + +// uncomment the below line to enable a power led (by default at pin D5) +#define POWERLED static const uint32_t cardCookie = 322417479; @@ -70,7 +73,7 @@ folderSettings *myFolder; unsigned long sleepAtMillis = 0; static uint16_t _lastTrackFinished; -static void nextTrack(uint16_t track); +static void nextTrack(); uint8_t voiceMenu(int numberOfOptions, int startMessage, int messageOffset, bool preview = false, int previewFromFolder = 0, int defaultValue = 0, bool exitWithLongPress = false); bool isPlaying(); @@ -98,11 +101,17 @@ class Mp3Notify { Serial.println(action); } static void OnPlayFinished(DfMp3_PlaySources source, uint16_t track) { - // Serial.print("Track beendet"); - // Serial.println(track); - // delay(100); - nextTrack(track); + Serial.println(track); + //delay(100); + if (track == _lastTrackFinished) { + Serial.println(F("Ignoring duplicate OnPlayFinished event")); + return; + } + _lastTrackFinished = track; + + nextTrack(); } + static void OnPlaySourceOnline(DfMp3_PlaySources source) { PrintlnSourceAction(source, "online"); } @@ -114,6 +123,38 @@ class Mp3Notify { } }; +enum Mode { + // Hörspielmodus: eine zufällige Datei aus dem Ordner + RADIO_PLAY = 1, + // Album Modus: kompletten Ordner spielen + ALBUM = 2, + // Party Modus: Ordner in zufälliger Reihenfolge + PARTY = 3, + // Einzel Modus: eine Datei aus dem Ordner abspielen + SINGLE = 4, + // Hörbuch Modus: kompletten Ordner spielen und Fortschritt merken + AUDIOBOOK = 5, + // Admin Funktionen + ADMIN_LEGACY = 6, + // Spezialmodus Von-Bis: Hörspiel: eine zufällige Datei aus dem Ordner + SPECIAL_RADIO_PLAY = 7, + // Spezialmodus Von-Bis: Album: alle Dateien zwischen Start und Ende spielen + SPECIAL_ALBUM = 8, + // Spezialmodus Von-Bis: Party Ordner in zufälliger Reihenfolge + SPECIAL_PARTY = 9 +}; + +enum Modifiers { + SLEEP_TIMER = 1, + FREEZE_DANCE = 2, + LOCKED = 3, + TODDLER_MODE = 4, + KINDERGARDEN_MODE = 5, + REPEAT_SINGLE = 6, + SINGLE_TRACK = 7, + ADMIN = 255 +}; + static DFMiniMp3 mp3(mySoftwareSerial); void shuffleQueue() { @@ -277,28 +318,31 @@ class SleepTimer: public Modifier { SleepTimer(uint8_t minutes) { Serial.println(F("=== SleepTimer()")); - Serial.println(minutes); + Serial.print(minutes); + Serial.println(F(" minutes")); this->sleepAtMillis = millis() + minutes * 60000; // if (isPlaying()) // mp3.playAdvertisement(302); // delay(500); } + uint8_t getActive() { Serial.println(F("== SleepTimer::getActive()")); - return 1; + return SLEEP_TIMER; } }; class FreezeDance: public Modifier { private: unsigned long nextStopAtMillis = 0; - const uint8_t minSecondsBetweenStops = 5; - const uint8_t maxSecondsBetweenStops = 30; + const uint8_t minSecondsBetweenStops = 20; + const uint8_t maxSecondsBetweenStops = 45; void setNextStopAtMillis() { uint16_t seconds = random(this->minSecondsBetweenStops, this->maxSecondsBetweenStops + 1); Serial.println(F("=== FreezeDance::setNextStopAtMillis()")); - Serial.println(seconds); + Serial.print(seconds); + Serial.println(F(" seconds until next stop")); this->nextStopAtMillis = millis() + seconds * 1000; } @@ -313,6 +357,7 @@ class FreezeDance: public Modifier { setNextStopAtMillis(); } } + FreezeDance(void) { Serial.println(F("=== FreezeDance()")); if (isPlaying()) { @@ -322,9 +367,10 @@ class FreezeDance: public Modifier { } setNextStopAtMillis(); } + uint8_t getActive() { Serial.println(F("== FreezeDance::getActive()")); - return 2; + return FREEZE_DANCE; } }; @@ -360,7 +406,8 @@ class Locked: public Modifier { // mp3.playAdvertisement(303); } uint8_t getActive() { - return 3; + Serial.println(F("== Locked::getActive()")); + return LOCKED; } }; @@ -393,7 +440,7 @@ class ToddlerMode: public Modifier { } uint8_t getActive() { Serial.println(F("== ToddlerMode::getActive()")); - return 4; + return TODDLER_MODE; } }; @@ -412,25 +459,31 @@ class KindergardenMode: public Modifier { myCard = nextCard; myFolder = &myCard.nfcFolderSettings; + Serial.print(F("Folder ")); Serial.println(myFolder->folder); + Serial.print(F("Mode ")); Serial.println(myFolder->mode); playFolder(); return true; } return false; } + // virtual bool handlePause() { // Serial.println(F("== KindergardenMode::handlePause() -> LOCKED!")); // return true; // } + virtual bool handleNextButton() { Serial.println(F("== KindergardenMode::handleNextButton() -> LOCKED!")); return true; } + virtual bool handlePreviousButton() { Serial.println(F("== KindergardenMode::handlePreviousButton() -> LOCKED!")); return true; } + virtual bool handleRFID(nfcTagObject * newCard) { // lot of work to do! Serial.println(F("== KindergardenMode::handleRFID() -> queued!")); this->nextCard = *newCard; @@ -440,15 +493,17 @@ class KindergardenMode: public Modifier { } return true; } + KindergardenMode() { Serial.println(F("=== KindergardenMode()")); // if (isPlaying()) // mp3.playAdvertisement(305); // delay(500); } + uint8_t getActive() { Serial.println(F("== KindergardenMode::getActive()")); - return 5; + return KINDERGARDEN_MODE; } }; @@ -462,12 +517,46 @@ class RepeatSingleModifier: public Modifier { _lastTrackFinished = 0; return true; } + RepeatSingleModifier() { Serial.println(F("=== RepeatSingleModifier()")); } + uint8_t getActive() { Serial.println(F("== RepeatSingleModifier::getActive()")); - return 6; + return REPEAT_SINGLE; + } +}; + +//only play the current track and then stop playing, regardless the mode that is configured originally +class SingleTrackModifier : public Modifier { + public: + virtual void loop() {} + virtual bool handleNext() { + Serial.println(F("== SingleTrackModifier::handleNext() -> Stop playing")); + setstandbyTimer(); + activeModifier = NULL; + delete this; + return true; + } + + SingleTrackModifier() { + Serial.println(F("=== SingleTrackModifier()")); + } + + virtual bool handleNextButton() { + Serial.println(F("== SingleTrackModifier::handleNextButton() -> LOCKED!")); + return true; + } + + virtual bool handlePreviousButton() { + Serial.println(F("== SingleTrackModifier::handlePreviousButton() -> LOCKED!")); + return true; + } + + virtual uint8_t getActive() { + Serial.println(F("== SingleTrackModifier::getActive()")); + return SINGLE_TRACK; } }; @@ -488,6 +577,7 @@ class FeedbackModifier: public Modifier { Serial.println(F("== FeedbackModifier::handleVolumeDown()!")); return false; } + virtual bool handleVolumeUp() { if (volume < mySettings.maxVolume) { mp3.playAdvertisement(volume + 1); @@ -499,6 +589,7 @@ class FeedbackModifier: public Modifier { Serial.println(F("== FeedbackModifier::handleVolumeUp()!")); return false; } + virtual bool handleRFID(nfcTagObject *newCard) { Serial.println(F("== FeedbackModifier::handleRFID()")); return false; @@ -506,119 +597,122 @@ class FeedbackModifier: public Modifier { }; // Leider kann das Modul selbst keine Queue abspielen, daher müssen wir selbst die Queue verwalten -static void nextTrack(uint16_t track) { - Serial.println(track); +static void nextTrack() { + Serial.println(F("=== nextTrack()")); + if (activeModifier != NULL) if (activeModifier->handleNext() == true) return; - if (track == _lastTrackFinished) { - return; - } - _lastTrackFinished = track; - if (knownCard == false) // Wenn eine neue Karte angelernt wird soll das Ende eines Tracks nicht // verarbeitet werden return; - Serial.println(F("=== nextTrack()")); - - if (myFolder->mode == 1 || myFolder->mode == 7) { - Serial.println(F("Hörspielmodus ist aktiv -> keinen neuen Track spielen")); - setstandbyTimer(); - // mp3.sleep(); // Je nach Modul kommt es nicht mehr zurück aus dem Sleep! - } - if (myFolder->mode == 2 || myFolder->mode == 8) { - if (currentTrack != numTracksInFolder) { - currentTrack = currentTrack + 1; - mp3.playFolderTrack(myFolder->folder, currentTrack); - Serial.print(F("Albummodus ist aktiv -> nächster Track: ")); - Serial.print(currentTrack); - } else - // mp3.sleep(); // Je nach Modul kommt es nicht mehr zurück aus dem Sleep! - setstandbyTimer(); - { } - } - if (myFolder->mode == 3 || myFolder->mode == 9) { - if (currentTrack != numTracksInFolder - firstTrack + 1) { - Serial.print(F("Party -> weiter in der Queue ")); - currentTrack++; - } else { - Serial.println(F("Ende der Queue -> beginne von vorne")); - currentTrack = 1; - //// Wenn am Ende der Queue neu gemischt werden soll bitte die Zeilen wieder aktivieren - // Serial.println(F("Ende der Queue -> mische neu")); - // shuffleQueue(); - } - Serial.println(queue[currentTrack - 1]); - mp3.playFolderTrack(myFolder->folder, queue[currentTrack - 1]); + uint16_t nextTrack = 65535; + switch (myFolder->mode) { + case RADIO_PLAY: + case SPECIAL_RADIO_PLAY: + Serial.print(F("Hörspielmodus ist aktiv -> ")); + break; + case ALBUM: + case SPECIAL_ALBUM: + Serial.print(F("Albummodus ist aktiv -> ")); + if (currentTrack != numTracksInFolder) { + currentTrack = currentTrack + 1; + nextTrack = currentTrack; + } + break; + case PARTY: + case SPECIAL_PARTY: + Serial.print(F("Partymodus ist aktiv -> ")); + if (currentTrack != numTracksInFolder - firstTrack + 1) { + currentTrack++; + } else { + Serial.print(F("Ende der Queue, beginne von vorne -> ")); + currentTrack = 1; + //// Wenn am Ende der Queue neu gemischt werden soll bitte die Zeilen wieder aktivieren + // Serial.println(F("Ende der Queue -> mische neu")); + // shuffleQueue(); + } + nextTrack = queue[currentTrack - 1]; + break; + case SINGLE: + Serial.println(F("Einzel Modus aktiv, Strom sparen -> ")); + break; + case AUDIOBOOK: + Serial.println(F("Hörbuch Modus ist aktiv, Fortschritt wird gespeichert -> ")); + if (currentTrack != numTracksInFolder) { + currentTrack = currentTrack + 1; + // Fortschritt im EEPROM abspeichern + EEPROM.update(myFolder->folder, currentTrack); + nextTrack = currentTrack; + } else { + // Fortschritt zurück setzen + EEPROM.update(myFolder->folder, 1); + } + break; } - if (myFolder->mode == 4) { - Serial.println(F("Einzel Modus aktiv -> Strom sparen")); - // mp3.sleep(); // Je nach Modul kommt es nicht mehr zurück aus dem Sleep! + if (nextTrack != 65535) { + Serial.print(F("nächster track ist: ")); + Serial.println(nextTrack); + mp3.playFolderTrack(myFolder->folder, nextTrack); + } else { + Serial.println(F("keinen neuen Track spielen")); setstandbyTimer(); } - if (myFolder->mode == 5) { - if (currentTrack != numTracksInFolder) { - currentTrack = currentTrack + 1; - Serial.print(F("Hörbuch Modus ist aktiv -> nächster Track und " - "Fortschritt speichern")); - Serial.println(currentTrack); - mp3.playFolderTrack(myFolder->folder, currentTrack); - // Fortschritt im EEPROM abspeichern - EEPROM.update(myFolder->folder, currentTrack); - } else { - // mp3.sleep(); // Je nach Modul kommt es nicht mehr zurück aus dem Sleep! - // Fortschritt zurück setzen - EEPROM.update(myFolder->folder, 1); - setstandbyTimer(); - } - } + delay(500); } static void previousTrack() { Serial.println(F("=== previousTrack()")); - /* if (myCard.mode == 1 || myCard.mode == 7) { + + switch (myFolder->mode) { + /*case RADIO_PLAY: + case SPECIAL_RADIO_PLAY: Serial.println(F("Hörspielmodus ist aktiv -> Track von vorne spielen")); - mp3.playFolderTrack(myCard.folder, currentTrack); - }*/ - if (myFolder->mode == 2 || myFolder->mode == 8) { - Serial.println(F("Albummodus ist aktiv -> vorheriger Track")); - if (currentTrack != firstTrack) { - currentTrack = currentTrack - 1; - } - mp3.playFolderTrack(myFolder->folder, currentTrack); - } - if (myFolder->mode == 3 || myFolder->mode == 9) { - if (currentTrack != 1) { - Serial.print(F("Party Modus ist aktiv -> zurück in der Qeueue ")); - currentTrack--; - } - else - { - Serial.print(F("Anfang der Queue -> springe ans Ende ")); - currentTrack = numTracksInFolder; - } - Serial.println(queue[currentTrack - 1]); - mp3.playFolderTrack(myFolder->folder, queue[currentTrack - 1]); - } - if (myFolder->mode == 4) { - Serial.println(F("Einzel Modus aktiv -> Track von vorne spielen")); - mp3.playFolderTrack(myFolder->folder, currentTrack); - } - if (myFolder->mode == 5) { - Serial.println(F("Hörbuch Modus ist aktiv -> vorheriger Track und " - "Fortschritt speichern")); - if (currentTrack != 1) { - currentTrack = currentTrack - 1; - } - mp3.playFolderTrack(myFolder->folder, currentTrack); - // Fortschritt im EEPROM abspeichern - EEPROM.update(myFolder->folder, currentTrack); + mp3.playFolderTrack(myFolder.folder, currentTrack); + break;*/ + case ALBUM: + case SPECIAL_ALBUM: + Serial.println(F("Albummodus ist aktiv -> vorheriger Track")); + if (currentTrack != firstTrack) { + currentTrack = currentTrack - 1; + } + mp3.playFolderTrack(myFolder->folder, currentTrack); + break; + case PARTY: + case SPECIAL_PARTY: + if (currentTrack != 1) { + Serial.println(F("Party Modus ist aktiv -> zurück in der Qeueue ")); + currentTrack--; + } else { + Serial.println(F("Anfang der Queue -> springe ans Ende ")); + currentTrack = numTracksInFolder; + } + Serial.print(F("Previous track from queue is ")); + Serial.println(queue[currentTrack - 1]); + mp3.playFolderTrack(myFolder->folder, queue[currentTrack - 1]); + break; + case SINGLE: + Serial.println(F("Einzel Modus aktiv -> Track von vorne spielen")); + mp3.playFolderTrack(myFolder->folder, currentTrack); + break; + case AUDIOBOOK: + Serial.println(F("Hörbuch Modus ist aktiv -> vorheriger Track und Fortschritt speichern")); + if (currentTrack != 1) { + currentTrack = currentTrack - 1; + } + Serial.print(F("Previous track is ")); + Serial.println(currentTrack); + mp3.playFolderTrack(myFolder->folder, currentTrack); + // Fortschritt im EEPROM abspeichern + EEPROM.update(myFolder->folder, currentTrack); + break; } + delay(1000); } @@ -642,7 +736,11 @@ MFRC522::StatusCode status; #ifdef FIVEBUTTONS #define buttonFourPin A3 -#define buttonFivePin A4 +#define buttonFivePin A5 +#endif + +#ifdef POWERLED +#define powerLedPin 5 #endif #define LONG_PRESS 1000 @@ -670,7 +768,9 @@ void setstandbyTimer() { sleepAtMillis = millis() + (mySettings.standbyTimer * 60 * 1000); else sleepAtMillis = 0; - Serial.println(sleepAtMillis); + Serial.print(F("Standby timer set to ")); + Serial.print(sleepAtMillis); + Serial.println(F(" millis")); } void disablestandbyTimer() { @@ -681,6 +781,9 @@ void disablestandbyTimer() { void checkStandbyAtMillis() { if (sleepAtMillis != 0 && millis() > sleepAtMillis) { Serial.println(F("=== power off!")); +#ifdef POWERLED + digitalWrite(powerLedPin, LOW); +#endif // enter sleep state digitalWrite(shutdownPin, HIGH); delay(500); @@ -689,7 +792,6 @@ void checkStandbyAtMillis() { // powerdown to 27mA (powerbank switches off after 30-60s) mfrc522.PCD_AntennaOff(); mfrc522.PCD_SoftPowerDown(); - mp3.sleep(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); cli(); // Disable interrupts @@ -714,6 +816,10 @@ void waitForTrackToFinish() { } void setup() { +#ifdef POWERLED + pinMode(powerLedPin, OUTPUT); + digitalWrite(powerLedPin, HIGH); +#endif Serial.begin(115200); // Es gibt ein paar Debug Ausgaben über die serielle Schnittstelle @@ -750,7 +856,7 @@ void setup() { delay(2000); volume = mySettings.initVolume; mp3.setVolume(volume); - mp3.setEq(mySettings.eq - 1); + mp3.setEq(DfMp3_Eq(mySettings.eq - 1)); // Fix für das Problem mit dem Timeout (ist jetzt in Upstream daher nicht mehr nötig!) //mySoftwareSerial.setTimeout(10000); @@ -809,6 +915,7 @@ void volumeUpButton() { mp3.increaseVolume(); volume++; } + Serial.print(F("Volume ")); Serial.println(volume); } @@ -822,6 +929,7 @@ void volumeDownButton() { mp3.decreaseVolume(); volume--; } + Serial.print(F("Volume ")); Serial.println(volume); } @@ -830,7 +938,7 @@ void nextButton() { if (activeModifier->handleNextButton() == true) return; - nextTrack(random(65536)); + nextTrack(); delay(1000); } @@ -854,81 +962,82 @@ void playFolder() { Serial.print(F(" Dateien in Ordner ")); Serial.println(myFolder->folder); - // Hörspielmodus: eine zufällige Datei aus dem Ordner - if (myFolder->mode == 1) { - Serial.println(F("Hörspielmodus -> zufälligen Track wiedergeben")); - currentTrack = random(1, numTracksInFolder + 1); - Serial.println(currentTrack); - mp3.playFolderTrack(myFolder->folder, currentTrack); - } - // Album Modus: kompletten Ordner spielen - if (myFolder->mode == 2) { - Serial.println(F("Album Modus -> kompletten Ordner wiedergeben")); - currentTrack = 1; - mp3.playFolderTrack(myFolder->folder, currentTrack); - } - // Party Modus: Ordner in zufälliger Reihenfolge - if (myFolder->mode == 3) { - Serial.println( - F("Party Modus -> Ordner in zufälliger Reihenfolge wiedergeben")); - shuffleQueue(); - currentTrack = 1; - mp3.playFolderTrack(myFolder->folder, queue[currentTrack - 1]); - } - // Einzel Modus: eine Datei aus dem Ordner abspielen - if (myFolder->mode == 4) { - Serial.println( - F("Einzel Modus -> eine Datei aus dem Odrdner abspielen")); - currentTrack = myFolder->special; - mp3.playFolderTrack(myFolder->folder, currentTrack); - } - // Hörbuch Modus: kompletten Ordner spielen und Fortschritt merken - if (myFolder->mode == 5) { - Serial.println(F("Hörbuch Modus -> kompletten Ordner spielen und " - "Fortschritt merken")); - currentTrack = EEPROM.read(myFolder->folder); - if (currentTrack == 0 || currentTrack > numTracksInFolder) { + switch (myFolder->mode) { + case RADIO_PLAY: + // Hörspielmodus: eine zufällige Datei aus dem Ordner + Serial.println(F("Hörspielmodus -> zufälligen Track wiedergeben")); + currentTrack = random(1, numTracksInFolder + 1); + Serial.print(F("Playing track ")); + Serial.println(currentTrack); + mp3.playFolderTrack(myFolder->folder, currentTrack); + break; + case ALBUM: + // Album Modus: kompletten Ordner spielen + Serial.println(F("Album Modus -> kompletten Ordner wiedergeben")); currentTrack = 1; - } - mp3.playFolderTrack(myFolder->folder, currentTrack); - } - // Spezialmodus Von-Bin: Hörspiel: eine zufällige Datei aus dem Ordner - if (myFolder->mode == 7) { - Serial.println(F("Spezialmodus Von-Bin: Hörspiel -> zufälligen Track wiedergeben")); - Serial.print(myFolder->special); - Serial.print(F(" bis ")); - Serial.println(myFolder->special2); - numTracksInFolder = myFolder->special2; - currentTrack = random(myFolder->special, numTracksInFolder + 1); - Serial.println(currentTrack); - mp3.playFolderTrack(myFolder->folder, currentTrack); - } - - // Spezialmodus Von-Bis: Album: alle Dateien zwischen Start und Ende spielen - if (myFolder->mode == 8) { - Serial.println(F("Spezialmodus Von-Bis: Album: alle Dateien zwischen Start- und Enddatei spielen")); - Serial.print(myFolder->special); - Serial.print(F(" bis ")); - Serial.println(myFolder->special2); - numTracksInFolder = myFolder->special2; - currentTrack = myFolder->special; - mp3.playFolderTrack(myFolder->folder, currentTrack); - } - - // Spezialmodus Von-Bis: Party Ordner in zufälliger Reihenfolge - if (myFolder->mode == 9) { - Serial.println( - F("Spezialmodus Von-Bis: Party -> Ordner in zufälliger Reihenfolge wiedergeben")); - firstTrack = myFolder->special; - numTracksInFolder = myFolder->special2; - shuffleQueue(); - currentTrack = 1; - mp3.playFolderTrack(myFolder->folder, queue[currentTrack - 1]); + mp3.playFolderTrack(myFolder->folder, currentTrack); + break; + case PARTY: + // Party Modus: Ordner in zufälliger Reihenfolge + Serial.println(F("Party Modus -> Ordner in zufälliger Reihenfolge wiedergeben")); + shuffleQueue(); + currentTrack = 1; + mp3.playFolderTrack(myFolder->folder, queue[currentTrack - 1]); + break; + case SINGLE: + // Einzel Modus: eine Datei aus dem Ordner abspielen + Serial.println(F("Einzel Modus -> eine Datei aus dem Odrdner abspielen")); + currentTrack = myFolder->special; + mp3.playFolderTrack(myFolder->folder, currentTrack); + break; + case AUDIOBOOK: + // Hörbuch Modus: kompletten Ordner spielen und Fortschritt merken + Serial.println(F("Hörbuch Modus -> kompletten Ordner spielen und Fortschritt merken")); + currentTrack = EEPROM.read(myFolder->folder); + if (currentTrack == 0 || currentTrack > numTracksInFolder) { + currentTrack = 1; + } + Serial.print(F("Playing track ")); + Serial.println(currentTrack); + mp3.playFolderTrack(myFolder->folder, currentTrack); + break; + case SPECIAL_RADIO_PLAY: + // Spezialmodus Von-Bis: Hörspiel: eine zufällige Datei aus dem Ordner + Serial.println(F("Spezialmodus Von-Bis: Hörspiel -> zufälligen Track wiedergeben")); + Serial.print(myFolder->special); + Serial.print(F(" bis ")); + Serial.println(myFolder->special2); + numTracksInFolder = myFolder->special2; + currentTrack = random(myFolder->special, numTracksInFolder + 1); + Serial.print(F("Playing track ")); + Serial.println(currentTrack); + mp3.playFolderTrack(myFolder->folder, currentTrack); + break; + case SPECIAL_ALBUM: + // Spezialmodus Von-Bis: Album: alle Dateien zwischen Start und Ende spielen + Serial.println(F("Spezialmodus Von-Bis: Album: alle Dateien zwischen Start- und Enddatei spielen")); + Serial.print(myFolder->special); + Serial.print(F(" bis ")); + Serial.println(myFolder->special2); + numTracksInFolder = myFolder->special2; + currentTrack = myFolder->special; + mp3.playFolderTrack(myFolder->folder, currentTrack); + break; + case SPECIAL_PARTY: + // Spezialmodus Von-Bis: Party Ordner in zufälliger Reihenfolge + Serial.println(F("Spezialmodus Von-Bis: Party -> Ordner in zufälliger Reihenfolge wiedergeben")); + firstTrack = myFolder->special; + numTracksInFolder = myFolder->special2; + shuffleQueue(); + currentTrack = 1; + mp3.playFolderTrack(myFolder->folder, queue[currentTrack - 1]); + break; } } void playShortCut(uint8_t shortCut) { Serial.println(F("=== playShortCut()")); + Serial.print(F("Selected shortcut ")); Serial.println(shortCut); if (mySettings.shortCuts[shortCut].folder != 0) { myFolder = &mySettings.shortCuts[shortCut]; @@ -965,6 +1074,22 @@ void loop() { break; } +#ifdef FIVEBUTTONS + // continue with last card + if (!isPlaying() && buttonFour.pressedFor(LONG_PRESS) && buttonFive.pressedFor(LONG_PRESS)) { + do { + readButtons(); + } while (buttonFour.isPressed() || buttonFive.isPressed()); + readButtons(); + if (loadLastCard(&myCard) == true) { + if (myCard.cookie == cardCookie && myCard.nfcFolderSettings.folder != 0 && myCard.nfcFolderSettings.mode != 0) { + playFolder(); + } + } + break; + } +#endif + if (pauseButton.wasReleased()) { if (activeModifier != NULL) if (activeModifier->handlePause() == true) @@ -986,14 +1111,14 @@ void loop() { return; if (isPlaying()) { uint8_t advertTrack; - if (myFolder->mode == 3 || myFolder->mode == 9) { + if (myFolder->mode == PARTY || myFolder->mode == SPECIAL_PARTY) { advertTrack = (queue[currentTrack - 1]); } else { advertTrack = currentTrack; } // Spezialmodus Von-Bis für Album und Party gibt die Dateinummer relativ zur Startposition wieder - if (myFolder->mode == 8 || myFolder->mode == 9) { + if (myFolder->mode == SPECIAL_ALBUM || myFolder->mode == SPECIAL_PARTY) { advertTrack = advertTrack - myFolder->special + 1; } mp3.playAdvertisement(advertTrack); @@ -1109,7 +1234,31 @@ void loop() { mfrc522.PCD_StopCrypto1(); } -void adminMenu(bool fromCard = false) { +bool loadLastCard(nfcTagObject * nfcTag) { + Serial.println(F("Loading last folder card from EEPROM")); + nfcTagObject tempCard; + + int address = sizeof(folderSettings::folder) * 100 + sizeof(adminSettings); + EEPROM.get(address, tempCard); + + // only care about folder cards + if (tempCard.nfcFolderSettings.folder != 0) { + if (activeModifier != NULL && activeModifier->handleRFID(&tempCard)) { + return false; + } + + memcpy(nfcTag, &tempCard, sizeof(nfcTagObject)); + myFolder = &nfcTag->nfcFolderSettings; + Serial.print(F("Loaded last card with folder ")); + Serial.println(myFolder->folder); + + return true; + } + + return false; +} + +void adminMenu(bool fromCard) { disablestandbyTimer(); mp3.pause(); Serial.println(F("=== adminMenu()")); @@ -1154,6 +1303,7 @@ void adminMenu(bool fromCard = false) { } waitForTrackToFinish(); mp3.playMp3FolderTrack(b); + Serial.print(F("C is ")); Serial.println(c); uint8_t temp = voiceMenu(255, 0, 0, false); if (temp != c) { @@ -1184,7 +1334,7 @@ void adminMenu(bool fromCard = false) { else if (subMenu == 5) { // EQ mySettings.eq = voiceMenu(6, 920, 920, false, false, mySettings.eq); - mp3.setEq(mySettings.eq - 1); + mp3.setEq(DfMp3_Eq(mySettings.eq - 1)); } else if (subMenu == 6) { // create modifier card @@ -1194,10 +1344,10 @@ void adminMenu(bool fromCard = false) { tempCard.nfcFolderSettings.folder = 0; tempCard.nfcFolderSettings.special = 0; tempCard.nfcFolderSettings.special2 = 0; - tempCard.nfcFolderSettings.mode = voiceMenu(6, 970, 970, false, false, 0, true); + tempCard.nfcFolderSettings.mode = voiceMenu(7, 970, 970, false, false, 0, true); if (tempCard.nfcFolderSettings.mode != 0) { - if (tempCard.nfcFolderSettings.mode == 1) { + if (tempCard.nfcFolderSettings.mode == SLEEP_TIMER) { switch (voiceMenu(4, 960, 960)) { case 1: tempCard.nfcFolderSettings.special = 5; break; case 2: tempCard.nfcFolderSettings.special = 15; break; @@ -1246,7 +1396,7 @@ void adminMenu(bool fromCard = false) { nfcTagObject tempCard; tempCard.cookie = cardCookie; tempCard.version = 1; - tempCard.nfcFolderSettings.mode = 4; + tempCard.nfcFolderSettings.mode = SINGLE; tempCard.nfcFolderSettings.folder = voiceMenu(99, 301, 0, true); uint8_t special = voiceMenu(mp3.getFolderTrackCount(tempCard.nfcFolderSettings.folder), 321, 0, true, tempCard.nfcFolderSettings.folder); @@ -1308,7 +1458,7 @@ void adminMenu(bool fromCard = false) { mySettings.adminMenuLocked = 1; } else if (temp == 3) { - int8_t pin[4]; + uint8_t pin[4]; mp3.playMp3FolderTrack(991); if (askCode(pin)) { memcpy(mySettings.adminMenuPin, pin, 4); @@ -1341,7 +1491,7 @@ bool askCode(uint8_t *code) { } uint8_t voiceMenu(int numberOfOptions, int startMessage, int messageOffset, - bool preview = false, int previewFromFolder = 0, int defaultValue = 0, bool exitWithLongPress = false) { + bool preview, int previewFromFolder, int defaultValue, bool exitWithLongPress) { uint8_t returnValue = defaultValue; if (startMessage != 0) mp3.playMp3FolderTrack(startMessage); @@ -1363,9 +1513,8 @@ uint8_t voiceMenu(int numberOfOptions, int startMessage, int messageOffset, } if (pauseButton.wasReleased()) { if (returnValue != 0) { - Serial.print(F("=== ")); - Serial.print(returnValue); - Serial.println(F(" ===")); + Serial.print(F("Selected option ")); + Serial.println(returnValue); return returnValue; } delay(1000); @@ -1373,6 +1522,7 @@ uint8_t voiceMenu(int numberOfOptions, int startMessage, int messageOffset, if (upButton.pressedFor(LONG_PRESS)) { returnValue = min(returnValue + 10, numberOfOptions); + Serial.print(F("Current option ")); Serial.println(returnValue); //mp3.pause(); mp3.playMp3FolderTrack(messageOffset + returnValue); @@ -1387,6 +1537,7 @@ uint8_t voiceMenu(int numberOfOptions, int startMessage, int messageOffset, } else if (upButton.wasReleased()) { if (!ignoreUpButton) { returnValue = min(returnValue + 1, numberOfOptions); + Serial.print(F("Current option ")); Serial.println(returnValue); //mp3.pause(); mp3.playMp3FolderTrack(messageOffset + returnValue); @@ -1406,6 +1557,7 @@ uint8_t voiceMenu(int numberOfOptions, int startMessage, int messageOffset, if (downButton.pressedFor(LONG_PRESS)) { returnValue = max(returnValue - 10, 1); + Serial.print(F("Current option ")); Serial.println(returnValue); //mp3.pause(); mp3.playMp3FolderTrack(messageOffset + returnValue); @@ -1420,6 +1572,7 @@ uint8_t voiceMenu(int numberOfOptions, int startMessage, int messageOffset, } else if (downButton.wasReleased()) { if (!ignoreDownButton) { returnValue = max(returnValue - 1, 1); + Serial.print(F("Current option ")); Serial.println(returnValue); //mp3.pause(); mp3.playMp3FolderTrack(messageOffset + returnValue); @@ -1474,17 +1627,17 @@ bool setupFolder(folderSettings * theFolder) { // EEPROM.update(theFolder->folder, 1); // Einzelmodus -> Datei abfragen - if (theFolder->mode == 4) + if (theFolder->mode == SINGLE) theFolder->special = voiceMenu(mp3.getFolderTrackCount(theFolder->folder), 320, 0, true, theFolder->folder); // Admin Funktionen - if (theFolder->mode == 6) { + if (theFolder->mode == ADMIN_LEGACY) { //theFolder->special = voiceMenu(3, 320, 320); theFolder->folder = 0; - theFolder->mode = 255; + theFolder->mode = ADMIN; } // Spezialmodus Von-Bis - if (theFolder->mode == 7 || theFolder->mode == 8 || theFolder->mode == 9) { + if (theFolder->mode == SPECIAL_RADIO_PLAY || theFolder->mode == SPECIAL_ALBUM || theFolder->mode == SPECIAL_PARTY) { theFolder->special = voiceMenu(mp3.getFolderTrackCount(theFolder->folder), 321, 0, true, theFolder->folder); theFolder->special2 = voiceMenu(mp3.getFolderTrackCount(theFolder->folder), 322, 0, @@ -1602,11 +1755,9 @@ bool readCard(nfcTagObject * nfcTag) { memcpy(buffer + 12, buffer2, 4); } - Serial.print(F("Data on Card ")); - Serial.println(F(":")); + Serial.println(F("Data on Card:")); dump_byte_array(buffer, 16); Serial.println(); - Serial.println(); uint32_t tempCookie; tempCookie = (uint32_t)buffer[0] << 24; @@ -1648,7 +1799,7 @@ bool readCard(nfcTagObject * nfcTag) { return false; } } - if (tempCard.nfcFolderSettings.mode != 0 && tempCard.nfcFolderSettings.mode != 255) { + if (tempCard.nfcFolderSettings.mode != 0 && tempCard.nfcFolderSettings.mode != ADMIN) { if (isPlaying()) { mp3.playAdvertisement(260); } @@ -1662,24 +1813,43 @@ bool readCard(nfcTagObject * nfcTag) { } switch (tempCard.nfcFolderSettings.mode ) { case 0: - case 255: - mfrc522.PICC_HaltA(); mfrc522.PCD_StopCrypto1(); adminMenu(true); break; - case 1: activeModifier = new SleepTimer(tempCard.nfcFolderSettings.special); break; - case 2: activeModifier = new FreezeDance(); break; - case 3: activeModifier = new Locked(); break; - case 4: activeModifier = new ToddlerMode(); break; - case 5: activeModifier = new KindergardenMode(); break; - case 6: activeModifier = new RepeatSingleModifier(); break; - + case ADMIN: + mfrc522.PICC_HaltA(); + mfrc522.PCD_StopCrypto1(); + adminMenu(true); + break; + case SLEEP_TIMER: + activeModifier = new SleepTimer(tempCard.nfcFolderSettings.special); + break; + case FREEZE_DANCE: + activeModifier = new FreezeDance(); + break; + case LOCKED: + activeModifier = new Locked(); + break; + case TODDLER_MODE: + activeModifier = new ToddlerMode(); + break; + case KINDERGARDEN_MODE: + activeModifier = new KindergardenMode(); + break; + case REPEAT_SINGLE: + activeModifier = new RepeatSingleModifier(); + break; + case SINGLE_TRACK: + activeModifier = new SingleTrackModifier(); + break; } delay(2000); return false; } else { memcpy(nfcTag, &tempCard, sizeof(nfcTagObject)); - Serial.println( nfcTag->nfcFolderSettings.folder); myFolder = &nfcTag->nfcFolderSettings; + Serial.print(F("Folder ")); Serial.println( myFolder->folder); + int address = sizeof(folderSettings::folder) * 100 + sizeof(adminSettings); + EEPROM.put(address, tempCard); } return true; } @@ -1774,7 +1944,6 @@ void writeCard(nfcTagObject nfcTag) { } else mp3.playMp3FolderTrack(400); - Serial.println(); delay(2000); } diff --git a/audio_messages_de.txt b/audio_messages_de.txt index 05cea662..d0f0a863 100644 --- a/audio_messages_de.txt +++ b/audio_messages_de.txt @@ -73,6 +73,7 @@ mp3/0973_modifier_Locked.mp3|TonUINO Sperren mp3/0974_modifier_Toddler.mp3|Krabbler-Modus - Alle Tasten vom TonUINO werden für die ganz Kleinen gesperrt. Karten funktionieren weiterhin. mp3/0975_modifier_KinderGarden.mp3|KiTa-Modus - Damit es keinen Streit mehr gibt werden neue Karten nicht sofort gespielt sondern erst nachdem das aktuelle Lied vorbei ist. Die Vor- und Zurücktasten sind gesperrt. mp3/0976_modifier_repeat1.mp3|Titel wiederholen - den aktuellen Titel endlos wiederholen. +mp3/0977_modifier_single_track.mp3|Einzelmodus - Der aktuelle Titel wird wiedergegeben, danach endet die Wiedergabe. mp3/0980_admin_lock_intro.mp3|Wähle bitte aus ob und wie das Adminmenü geschützt werden soll. mp3/0981_admin_lock_disabled.mp3|Kein Schutz - das Adminmenü kann jederzeit durch drücken von allen drei Tasten aktiviert werden. mp3/0982_admin_lock_card.mp3|Nur Adminkarte - das Adminmenü kann nur mit einer Adminkarte geöffnet werden. Eine neue Adminkarte kann jederzeit angelernt werden.