From 658aa8d25d3c87d74118bcf72722424eb1372d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorsten=20Vo=C3=9F?= Date: Mon, 25 Feb 2019 23:08:41 +0100 Subject: [PATCH] =?UTF-8?q?Reset=20function=20moved=20to=20admin=20menu=20?= =?UTF-8?q?//=20Resetfunktion=20ins=20Adminmen=C3=BC=20verschoben?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SD-Karte-Google-Stimme/mp3/0911_reset.mp3 | Bin 0 -> 6478 bytes SD-Karte-Normale-Stimme/mp3/0911_reset.mp3 | Bin 0 -> 28002 bytes Tonuino.ino | 1922 ++++++++++---------- soundfiles.txt | 1 + 4 files changed, 966 insertions(+), 957 deletions(-) create mode 100644 SD-Karte-Google-Stimme/mp3/0911_reset.mp3 create mode 100644 SD-Karte-Normale-Stimme/mp3/0911_reset.mp3 diff --git a/SD-Karte-Google-Stimme/mp3/0911_reset.mp3 b/SD-Karte-Google-Stimme/mp3/0911_reset.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..cdbbc0da6e2c9d82395e13245f61d765560faf0c GIT binary patch literal 6478 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 a+$iLKKZw!gM*bi4x0e5(9{yjwq5lAUeX2D8 literal 0 HcmV?d00001 diff --git a/SD-Karte-Normale-Stimme/mp3/0911_reset.mp3 b/SD-Karte-Normale-Stimme/mp3/0911_reset.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..4253d99e365bd032a48b96a6b347e645ab51d18f GIT binary patch literal 28002 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 literal 0 HcmV?d00001 diff --git a/Tonuino.ino b/Tonuino.ino index c4c9598..d01dce1 100644 --- a/Tonuino.ino +++ b/Tonuino.ino @@ -31,35 +31,35 @@ uint8_t queue[255]; uint8_t volume; struct folderSettings { - uint8_t folder; - uint8_t mode; - uint8_t special; - uint8_t special2; + uint8_t folder; + uint8_t mode; + uint8_t special; + uint8_t special2; }; // this object stores nfc tag data struct nfcTagObject { - uint32_t cookie; - uint8_t version; - folderSettings nfcFolderSettings; - // uint8_t folder; - // uint8_t mode; - // uint8_t special; - // uint8_t special2; + uint32_t cookie; + uint8_t version; + folderSettings nfcFolderSettings; + // uint8_t folder; + // uint8_t mode; + // uint8_t special; + // uint8_t special2; }; // admin settings stored in eeprom struct adminSettings { - uint32_t cookie; - byte version; - uint8_t maxVolume; - uint8_t minVolume; - uint8_t initVolume; - uint8_t eq; - bool locked; - long standbyTimer; - bool invertVolumeButtons; - folderSettings shortCuts[4]; + uint32_t cookie; + byte version; + uint8_t maxVolume; + uint8_t minVolume; + uint8_t initVolume; + uint8_t eq; + bool locked; + long standbyTimer; + bool invertVolumeButtons; + folderSettings shortCuts[4]; }; adminSettings mySettings; @@ -69,7 +69,7 @@ unsigned long sleepAtMillis = 0; static void nextTrack(uint16_t track); uint8_t voiceMenu(int numberOfOptions, int startMessage, int messageOffset, - bool preview = false, int previewFromFolder = 0, int defaultValue = 0, bool exitWithLongPress = false); + bool preview = false, int previewFromFolder = 0, int defaultValue = 0, bool exitWithLongPress = false); bool isPlaying(); bool knownCard = false; @@ -77,75 +77,75 @@ bool knownCard = false; // its member methods will get called // class Mp3Notify { - public: - static void OnError(uint16_t errorCode) { - // see DfMp3_Error for code meaning - Serial.println(); - Serial.print("Com Error "); - Serial.println(errorCode); - } - static void OnPlayFinished(uint16_t track) { - // Serial.print("Track beendet"); - // Serial.println(track); - // delay(100); - nextTrack(track); - } - static void OnCardOnline(uint16_t code) { - Serial.println(F("SD Karte online ")); - } - static void OnCardInserted(uint16_t code) { - Serial.println(F("SD Karte bereit ")); - } - static void OnCardRemoved(uint16_t code) { - Serial.println(F("SD Karte entfernt ")); - } + public: + static void OnError(uint16_t errorCode) { + // see DfMp3_Error for code meaning + Serial.println(); + Serial.print("Com Error "); + Serial.println(errorCode); + } + static void OnPlayFinished(uint16_t track) { + // Serial.print("Track beendet"); + // Serial.println(track); + // delay(100); + nextTrack(track); + } + static void OnCardOnline(uint16_t code) { + Serial.println(F("SD Karte online ")); + } + static void OnCardInserted(uint16_t code) { + Serial.println(F("SD Karte bereit ")); + } + static void OnCardRemoved(uint16_t code) { + Serial.println(F("SD Karte entfernt ")); + } }; static DFMiniMp3 mp3(mySoftwareSerial); void shuffleQueue() { - // Queue für die Zufallswiedergabe erstellen - for (uint8_t x = 0; x < numTracksInFolder - firstTrack + 1; x++) - queue[x] = x + firstTrack; - // Rest mit 0 auffüllen - for (uint8_t x = numTracksInFolder - firstTrack + 1; x < 255; x++) - queue[x] = 0; - // Queue mischen - for (uint8_t i = 0; i < numTracksInFolder - firstTrack + 1; i++) - { - uint8_t j = random (0, numTracksInFolder - firstTrack + 1); - uint8_t t = queue[i]; - queue[i] = queue[j]; - queue[j] = t; - } - Serial.println(F("Queue :")); - for (uint8_t x = 0; x < numTracksInFolder - firstTrack + 1 ; x++) - Serial.println(queue[x]); + // Queue für die Zufallswiedergabe erstellen + for (uint8_t x = 0; x < numTracksInFolder - firstTrack + 1; x++) + queue[x] = x + firstTrack; + // Rest mit 0 auffüllen + for (uint8_t x = numTracksInFolder - firstTrack + 1; x < 255; x++) + queue[x] = 0; + // Queue mischen + for (uint8_t i = 0; i < numTracksInFolder - firstTrack + 1; i++) + { + uint8_t j = random (0, numTracksInFolder - firstTrack + 1); + uint8_t t = queue[i]; + queue[i] = queue[j]; + queue[j] = t; + } + Serial.println(F("Queue :")); + for (uint8_t x = 0; x < numTracksInFolder - firstTrack + 1 ; x++) + Serial.println(queue[x]); } void writeSettingsToFlash() { - Serial.println(F("=== writeSettingsToFlash()")); - int address = sizeof(myFolder->folder) * 100; - EEPROM.put(address, mySettings); + Serial.println(F("=== writeSettingsToFlash()")); + int address = sizeof(myFolder->folder) * 100; + EEPROM.put(address, mySettings); } void resetSettings() { - Serial.println(F("=== resetSettings()")); - mySettings.cookie = cardCookie; - mySettings.version = 1; - mySettings.maxVolume = 25; - mySettings.minVolume = 5; - mySettings.initVolume = 15; - mySettings.eq = 1; - mySettings.locked = false; - mySettings.standbyTimer = 0; - mySettings.invertVolumeButtons = true; - mySettings.shortCuts[0].folder = 0; - mySettings.shortCuts[1].folder = 0; - mySettings.shortCuts[2].folder = 0; - mySettings.shortCuts[3].folder = 0; - writeSettingsToFlash(); + Serial.println(F("=== resetSettings()")); + mySettings.cookie = cardCookie; + mySettings.version = 1; + mySettings.maxVolume = 25; + mySettings.minVolume = 5; + mySettings.initVolume = 15; + mySettings.eq = 1; + mySettings.locked = false; + mySettings.standbyTimer = 0; + mySettings.invertVolumeButtons = true; + mySettings.shortCuts[0].folder = 0; + mySettings.shortCuts[1].folder = 0; + mySettings.shortCuts[2].folder = 0; + mySettings.shortCuts[3].folder = 0; + writeSettingsToFlash(); } void migradeSettings(int oldVersion) { @@ -153,148 +153,148 @@ void migradeSettings(int oldVersion) { } void loadSettingsFromFlash() { - Serial.println(F("=== loadSettingsFromFlash()")); - int address = sizeof(myFolder->folder) * 100; - EEPROM.get(address, mySettings); - if (mySettings.cookie != cardCookie) - resetSettings(); - migradeSettings(mySettings.version); + Serial.println(F("=== loadSettingsFromFlash()")); + int address = sizeof(myFolder->folder) * 100; + EEPROM.get(address, mySettings); + if (mySettings.cookie != cardCookie) + resetSettings(); + migradeSettings(mySettings.version); - Serial.print(F("Version: ")); - Serial.println(mySettings.version); + Serial.print(F("Version: ")); + Serial.println(mySettings.version); - Serial.print(F("Maximal Volume: ")); - Serial.println(mySettings.maxVolume); + Serial.print(F("Maximal Volume: ")); + Serial.println(mySettings.maxVolume); - Serial.print(F("Minimal Volume: ")); - Serial.println(mySettings.minVolume); + Serial.print(F("Minimal Volume: ")); + Serial.println(mySettings.minVolume); - Serial.print(F("Initial Volume: ")); - Serial.println(mySettings.initVolume); + Serial.print(F("Initial Volume: ")); + Serial.println(mySettings.initVolume); - Serial.print(F("EQ: ")); - Serial.println(mySettings.eq); + Serial.print(F("EQ: ")); + Serial.println(mySettings.eq); - Serial.print(F("Locked: ")); - Serial.println(mySettings.locked); + Serial.print(F("Locked: ")); + Serial.println(mySettings.locked); - Serial.print(F("Sleep Timer: ")); - Serial.println(mySettings.standbyTimer); + Serial.print(F("Sleep Timer: ")); + Serial.println(mySettings.standbyTimer); - Serial.print(F("Inverted Volume Buttons: ")); - Serial.println(mySettings.invertVolumeButtons); + Serial.print(F("Inverted Volume Buttons: ")); + Serial.println(mySettings.invertVolumeButtons); } // Leider kann das Modul selbst keine Queue abspielen, daher müssen wir selbst die Queue verwalten static uint16_t _lastTrackFinished; static void nextTrack(uint16_t track) { - if (track == _lastTrackFinished) { - return; - } - Serial.println(F("=== nextTrack()")); - _lastTrackFinished = track; + if (track == _lastTrackFinished) { + return; + } + Serial.println(F("=== nextTrack()")); + _lastTrackFinished = track; - if (knownCard == false) - // Wenn eine neue Karte angelernt wird soll das Ende eines Tracks nicht - // verarbeitet werden - return; + if (knownCard == false) + // Wenn eine neue Karte angelernt wird soll das Ende eines Tracks nicht + // verarbeitet werden + return; - 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]); - } + 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]); + } - 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! - 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); + 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! + 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) { - 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); - } - delay(1000); + Serial.println(F("=== previousTrack()")); + /* if (myCard.mode == 1 || myCard.mode == 7) { + 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); + } + delay(1000); } // MFRC522 @@ -339,893 +339,901 @@ bool ignoreButtonFive = false; /// Funktionen für den Standby Timer (z.B. über Pololu-Switch oder Mosfet) void setstandbyTimer() { - Serial.println(F("=== setstandbyTimer()")); - if (mySettings.standbyTimer != 0) - sleepAtMillis = millis() + (mySettings.standbyTimer * 60 * 1000); - else - sleepAtMillis = 0; - Serial.println(sleepAtMillis); + Serial.println(F("=== setstandbyTimer()")); + if (mySettings.standbyTimer != 0) + sleepAtMillis = millis() + (mySettings.standbyTimer * 60 * 1000); + else + sleepAtMillis = 0; + Serial.println(sleepAtMillis); } void disablestandbyTimer() { - Serial.println(F("=== disablestandby()")); - sleepAtMillis = 0; + Serial.println(F("=== disablestandby()")); + sleepAtMillis = 0; } void checkStandbyAtMillis() { - if (sleepAtMillis != 0 && millis() > sleepAtMillis) { - Serial.println(F("=== power off!")); - // enter sleep state - digitalWrite(shutdownPin, HIGH); - delay(500); + if (sleepAtMillis != 0 && millis() > sleepAtMillis) { + Serial.println(F("=== power off!")); + // enter sleep state + digitalWrite(shutdownPin, HIGH); + delay(500); - // http://discourse.voss.earth/t/intenso-s10000-powerbank-automatische-abschaltung-software-only/805 - // powerdown to 27mA (powerbank switches off after 30-60s) - mfrc522.PCD_AntennaOff(); - mfrc522.PCD_SoftPowerDown(); - mp3.sleep(); + // http://discourse.voss.earth/t/intenso-s10000-powerbank-automatische-abschaltung-software-only/805 + // 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 - sleep_mode(); - } + set_sleep_mode(SLEEP_MODE_PWR_DOWN); + cli(); // Disable interrupts + sleep_mode(); + } } bool isPlaying() { - return !digitalRead(busyPin); + return !digitalRead(busyPin); } void waitForTrackToFinish() { - long currentTime = millis(); + long currentTime = millis(); #define TIMEOUT 1000 - do { - mp3.loop(); - } while (!isPlaying() && millis() < currentTime + TIMEOUT); - delay(1000); - do { - mp3.loop(); - } while (isPlaying()); + do { + mp3.loop(); + } while (!isPlaying() && millis() < currentTime + TIMEOUT); + delay(1000); + do { + mp3.loop(); + } while (isPlaying()); } void setup() { - Serial.begin(115200); // Es gibt ein paar Debug Ausgaben über die serielle Schnittstelle - randomSeed(analogRead(A7)); // Zufallsgenerator initialisieren + Serial.begin(115200); // Es gibt ein paar Debug Ausgaben über die serielle Schnittstelle + randomSeed(analogRead(A7)); // Zufallsgenerator initialisieren - // Dieser Hinweis darf nicht entfernt werden - Serial.println(F("\n _____ _____ _____ _____ _____")); - Serial.println(F("|_ _|___ ___| | | | | | |")); - Serial.println(F(" | | | . | | | |- -| | | | | |")); - Serial.println(F(" |_| |___|_|_|_____|_____|_|___|_____|\n")); - Serial.println(F("TonUINO Version 2.1")); - Serial.println(F("created by Thorsten Voß and licensed under GNU/GPL.")); - Serial.println(F("Information and contribution at https://tonuino.de.\n")); + // Dieser Hinweis darf nicht entfernt werden + Serial.println(F("\n _____ _____ _____ _____ _____")); + Serial.println(F("|_ _|___ ___| | | | | | |")); + Serial.println(F(" | | | . | | | |- -| | | | | |")); + Serial.println(F(" |_| |___|_|_|_____|_____|_|___|_____|\n")); + Serial.println(F("TonUINO Version 2.1")); + Serial.println(F("created by Thorsten Voß and licensed under GNU/GPL.")); + Serial.println(F("Information and contribution at https://tonuino.de.\n")); - // Busy Pin - pinMode(busyPin, INPUT); + // Busy Pin + pinMode(busyPin, INPUT); - // load Settings from EEPROM - loadSettingsFromFlash(); + // load Settings from EEPROM + loadSettingsFromFlash(); - // activate standby timer - setstandbyTimer(); + // activate standby timer + setstandbyTimer(); - // DFPlayer Mini initialisieren - mp3.begin(); - // Zwei Sekunden warten bis der DFPlayer Mini initialisiert ist - delay(2000); - volume = mySettings.initVolume; - mp3.setVolume(volume); - mp3.setEq(mySettings.eq - 1); - // Fix für das Problem mit dem Timeout (ist jetzt in Upstream daher nicht mehr nötig!) - //mySoftwareSerial.setTimeout(10000); + // DFPlayer Mini initialisieren + mp3.begin(); + // Zwei Sekunden warten bis der DFPlayer Mini initialisiert ist + delay(2000); + volume = mySettings.initVolume; + mp3.setVolume(volume); + mp3.setEq(mySettings.eq - 1); + // Fix für das Problem mit dem Timeout (ist jetzt in Upstream daher nicht mehr nötig!) + //mySoftwareSerial.setTimeout(10000); - // NFC Leser initialisieren - SPI.begin(); // Init SPI bus - mfrc522.PCD_Init(); // Init MFRC522 - mfrc522 - .PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader - for (byte i = 0; i < 6; i++) { - key.keyByte[i] = 0xFF; - } + // NFC Leser initialisieren + SPI.begin(); // Init SPI bus + mfrc522.PCD_Init(); // Init MFRC522 + mfrc522 + .PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader + for (byte i = 0; i < 6; i++) { + key.keyByte[i] = 0xFF; + } - pinMode(buttonPause, INPUT_PULLUP); - pinMode(buttonUp, INPUT_PULLUP); - pinMode(buttonDown, INPUT_PULLUP); + pinMode(buttonPause, INPUT_PULLUP); + pinMode(buttonUp, INPUT_PULLUP); + pinMode(buttonDown, INPUT_PULLUP); #ifdef FIVEBUTTONS - pinMode(buttonFourPin, INPUT_PULLUP); - pinMode(buttonFivePin, INPUT_PULLUP); + pinMode(buttonFourPin, INPUT_PULLUP); + pinMode(buttonFivePin, INPUT_PULLUP); #endif - pinMode(shutdownPin, OUTPUT); - digitalWrite(shutdownPin, LOW); + pinMode(shutdownPin, OUTPUT); + digitalWrite(shutdownPin, LOW); - /* // RESET --- ALLE DREI KNÖPFE BEIM STARTEN GEDRÜCKT HALTEN -> alle EINSTELLUNGEN werden gelöscht - if (digitalRead(buttonPause) == LOW && digitalRead(buttonUp) == LOW && - digitalRead(buttonDown) == LOW) { - Serial.println(F("Reset -> EEPROM wird gelöscht")); - for (int i = 0; i < EEPROM.length(); i++) { - EEPROM.update(i, 0); - } - } - */ - // Start Shortcut "at Startup" - e.g. Welcome Sound - playShortCut(3); + /* // RESET --- ALLE DREI KNÖPFE BEIM STARTEN GEDRÜCKT HALTEN -> alle EINSTELLUNGEN werden gelöscht + if (digitalRead(buttonPause) == LOW && digitalRead(buttonUp) == LOW && + digitalRead(buttonDown) == LOW) { + Serial.println(F("Reset -> EEPROM wird gelöscht")); + for (int i = 0; i < EEPROM.length(); i++) { + EEPROM.update(i, 0); + } + } + */ + // Start Shortcut "at Startup" - e.g. Welcome Sound + playShortCut(3); } void readButtons() { - pauseButton.read(); - upButton.read(); - downButton.read(); + pauseButton.read(); + upButton.read(); + downButton.read(); #ifdef FIVEBUTTONS - buttonFour.read(); - buttonFive.read(); + buttonFour.read(); + buttonFive.read(); #endif } void volumeUpButton() { - Serial.println(F("=== volumeUp()")); - if (volume < mySettings.maxVolume) { - mp3.increaseVolume(); - volume++; - } - Serial.println(volume); + Serial.println(F("=== volumeUp()")); + if (volume < mySettings.maxVolume) { + mp3.increaseVolume(); + volume++; + } + Serial.println(volume); } void volumeDownButton() { - Serial.println(F("=== volumeDown()")); - if (volume > mySettings.minVolume) { - mp3.decreaseVolume(); - volume--; - } - Serial.println(volume); + Serial.println(F("=== volumeDown()")); + if (volume > mySettings.minVolume) { + mp3.decreaseVolume(); + volume--; + } + Serial.println(volume); } void nextButton() { - nextTrack(random(65536)); - delay(1000); + nextTrack(random(65536)); + delay(1000); } void previousButton() { - previousTrack(); - delay(1000); + previousTrack(); + delay(1000); } void playFolder() { - disablestandbyTimer(); - randomSeed(millis() + random(1000)); - knownCard = true; - _lastTrackFinished = 0; - numTracksInFolder = mp3.getFolderTrackCount(myFolder->folder); - firstTrack = 1; - Serial.print(numTracksInFolder); - Serial.print(F(" Dateien in Ordner ")); - Serial.println(myFolder->folder); + disablestandbyTimer(); + randomSeed(millis() + random(1000)); + knownCard = true; + _lastTrackFinished = 0; + numTracksInFolder = mp3.getFolderTrackCount(myFolder->folder); + firstTrack = 1; + Serial.print(numTracksInFolder); + 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) { - 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); - } + // 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) { + 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: 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]); - } + // 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]); + } } void playShortCut(uint8_t shortCut) { - Serial.println(F("=== playShortCut()")); - Serial.println(shortCut); - if (mySettings.shortCuts[shortCut].folder != 0) { - myFolder = &mySettings.shortCuts[shortCut]; - playFolder(); - disablestandbyTimer(); - delay(1000); - } - else - Serial.println(F("Shortcut not configured!")); + Serial.println(F("=== playShortCut()")); + Serial.println(shortCut); + if (mySettings.shortCuts[shortCut].folder != 0) { + myFolder = &mySettings.shortCuts[shortCut]; + playFolder(); + disablestandbyTimer(); + delay(1000); + } + else + Serial.println(F("Shortcut not configured!")); } void loop() { - do { - checkStandbyAtMillis(); - mp3.loop(); - // Buttons werden nun über JS_Button gehandelt, dadurch kann jede Taste - // doppelt belegt werden - readButtons(); + do { + checkStandbyAtMillis(); + mp3.loop(); + // Buttons werden nun über JS_Button gehandelt, dadurch kann jede Taste + // doppelt belegt werden + readButtons(); - // admin menu - if ((pauseButton.pressedFor(LONG_PRESS) || upButton.pressedFor(LONG_PRESS) || downButton.pressedFor(LONG_PRESS)) && pauseButton.isPressed() && upButton.isPressed() && downButton.isPressed()) { - mp3.pause(); - do { - readButtons(); - } while (pauseButton.isPressed() || upButton.isPressed() || downButton.isPressed()); - readButtons(); - adminMenu(); - break; - } + // admin menu + if ((pauseButton.pressedFor(LONG_PRESS) || upButton.pressedFor(LONG_PRESS) || downButton.pressedFor(LONG_PRESS)) && pauseButton.isPressed() && upButton.isPressed() && downButton.isPressed()) { + mp3.pause(); + do { + readButtons(); + } while (pauseButton.isPressed() || upButton.isPressed() || downButton.isPressed()); + readButtons(); + adminMenu(); + break; + } - if (pauseButton.wasReleased()) { - if (ignorePauseButton == false) - if (isPlaying()) { - mp3.pause(); - setstandbyTimer(); - } - else if (knownCard) { - mp3.start(); - disablestandbyTimer(); - } - ignorePauseButton = false; - } else if (pauseButton.pressedFor(LONG_PRESS) && - ignorePauseButton == false) { - if (isPlaying()) { - uint8_t advertTrack; - if (myFolder->mode == 3 || myFolder->mode == 9) { - 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) { - advertTrack = advertTrack - myFolder->special + 1; - } - mp3.playAdvertisement(advertTrack); - } - else { - playShortCut(0); - } - ignorePauseButton = true; - } + if (pauseButton.wasReleased()) { + if (ignorePauseButton == false) + if (isPlaying()) { + mp3.pause(); + setstandbyTimer(); + } + else if (knownCard) { + mp3.start(); + disablestandbyTimer(); + } + ignorePauseButton = false; + } else if (pauseButton.pressedFor(LONG_PRESS) && + ignorePauseButton == false) { + if (isPlaying()) { + uint8_t advertTrack; + if (myFolder->mode == 3 || myFolder->mode == 9) { + 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) { + advertTrack = advertTrack - myFolder->special + 1; + } + mp3.playAdvertisement(advertTrack); + } + else { + playShortCut(0); + } + ignorePauseButton = true; + } - if (upButton.pressedFor(LONG_PRESS)) { + if (upButton.pressedFor(LONG_PRESS)) { #ifndef FIVEBUTTONS - if (isPlaying()) { - if (!mySettings.invertVolumeButtons) { - volumeUpButton(); - } - else { - nextButton(); - } - } - else { - playShortCut(1); - } - ignoreUpButton = true; + if (isPlaying()) { + if (!mySettings.invertVolumeButtons) { + volumeUpButton(); + } + else { + nextButton(); + } + } + else { + playShortCut(1); + } + ignoreUpButton = true; #endif - } else if (upButton.wasReleased()) { - if (!ignoreUpButton) - if (!mySettings.invertVolumeButtons) { - nextButton(); - } - else { - volumeUpButton(); - } - ignoreUpButton = false; - } + } else if (upButton.wasReleased()) { + if (!ignoreUpButton) + if (!mySettings.invertVolumeButtons) { + nextButton(); + } + else { + volumeUpButton(); + } + ignoreUpButton = false; + } - if (downButton.pressedFor(LONG_PRESS)) { + if (downButton.pressedFor(LONG_PRESS)) { #ifndef FIVEBUTTONS - if (isPlaying()) { - if (!mySettings.invertVolumeButtons) { - volumeDownButton(); - } - else { - previousButton(); - } - } - else { - playShortCut(2); - } - ignoreDownButton = true; + if (isPlaying()) { + if (!mySettings.invertVolumeButtons) { + volumeDownButton(); + } + else { + previousButton(); + } + } + else { + playShortCut(2); + } + ignoreDownButton = true; #endif - } else if (downButton.wasReleased()) { - if (!ignoreDownButton) { - if (!mySettings.invertVolumeButtons) { - previousButton(); - } - else { - volumeDownButton(); - } - } - ignoreDownButton = false; - } + } else if (downButton.wasReleased()) { + if (!ignoreDownButton) { + if (!mySettings.invertVolumeButtons) { + previousButton(); + } + else { + volumeDownButton(); + } + } + ignoreDownButton = false; + } #ifdef FIVEBUTTONS - if (buttonFour.wasReleased()) { - if (isPlaying()) { - if (!mySettings.invertVolumeButtons) { - volumeUpButton(); - } - else { - nextButton(); - } - } - else { - playShortCut(1); - } - } - if (buttonFive.wasReleased()) { - if (isPlaying()) { - if (!mySettings.invertVolumeButtons) { - volumeDownButton(); - } - else { - previousButton(); - } - } - else { - playShortCut(2); - } - } + if (buttonFour.wasReleased()) { + if (isPlaying()) { + if (!mySettings.invertVolumeButtons) { + volumeUpButton(); + } + else { + nextButton(); + } + } + else { + playShortCut(1); + } + } + if (buttonFive.wasReleased()) { + if (isPlaying()) { + if (!mySettings.invertVolumeButtons) { + volumeDownButton(); + } + else { + previousButton(); + } + } + else { + playShortCut(2); + } + } #endif - // Ende der Buttons - } while (!mfrc522.PICC_IsNewCardPresent()); + // Ende der Buttons + } while (!mfrc522.PICC_IsNewCardPresent()); - // RFID Karte wurde aufgelegt + // RFID Karte wurde aufgelegt - if (!mfrc522.PICC_ReadCardSerial()) - return; + if (!mfrc522.PICC_ReadCardSerial()) + return; - if (readCard(&myCard) == true) { - // make random a little bit more "random" - randomSeed(millis() + random(1000)); - if (myCard.cookie == cardCookie && myFolder->folder != 0 && myFolder->mode != 0) { - playFolder(); - } + if (readCard(&myCard) == true) { + // make random a little bit more "random" + randomSeed(millis() + random(1000)); + if (myCard.cookie == cardCookie && myFolder->folder != 0 && myFolder->mode != 0) { + playFolder(); + } - // Neue Karte konfigurieren - else { - knownCard = false; - setupCard(); - } - } - mfrc522.PICC_HaltA(); - mfrc522.PCD_StopCrypto1(); + // Neue Karte konfigurieren + else { + knownCard = false; + setupCard(); + } + } + mfrc522.PICC_HaltA(); + mfrc522.PCD_StopCrypto1(); } void adminMenu() { - disablestandbyTimer(); - mp3.pause(); - Serial.println(F("=== adminMenu()")); - knownCard = false; + disablestandbyTimer(); + mp3.pause(); + Serial.println(F("=== adminMenu()")); + knownCard = false; - int subMenu = voiceMenu(10, 900, 900, false, false, 0, true); - if (subMenu == 0) - return; - if (subMenu == 1) { - resetCard(); - mfrc522.PICC_HaltA(); - mfrc522.PCD_StopCrypto1(); - } - else if (subMenu == 2) { - // Maximum Volume - mySettings.maxVolume = voiceMenu(30, 930, 0, false, false, mySettings.maxVolume); - } - else if (subMenu == 3) { - // Minimum Volume - mySettings.minVolume = voiceMenu(30, 931, 0, false, false, mySettings.minVolume); - } - else if (subMenu == 4) { - // Initial Volume - mySettings.initVolume = voiceMenu(30, 932, 0, false, false, mySettings.initVolume); - } - else if (subMenu == 5) { - // EQ - mySettings.eq = voiceMenu(6, 920, 920, false, false, mySettings.eq); - mp3.setEq(mySettings.eq - 1); - } - else if (subMenu == 6) { - // create master card - } - else if (subMenu == 7) { - uint8_t shortcut = voiceMenu(4, 940, 940); - setupFolder(&mySettings.shortCuts[shortcut - 1]); - mp3.playMp3FolderTrack(400); - } - else if (subMenu == 8) { - switch (voiceMenu(5, 960, 960)) { - case 1: mySettings.standbyTimer = 5; break; - case 2: mySettings.standbyTimer = 15; break; - case 3: mySettings.standbyTimer = 30; break; - case 4: mySettings.standbyTimer = 60; break; - case 5: mySettings.standbyTimer = 0; break; - } - } - else if (subMenu == 9) { - // Create Cards for Folder - // Ordner abfragen - nfcTagObject tempCard; - tempCard.cookie = cardCookie; - tempCard.version = 1; - tempCard.nfcFolderSettings.mode = 4; - tempCard.nfcFolderSettings.folder = voiceMenu(99, 301, 0, true); - uint8_t special = voiceMenu(mp3.getFolderTrackCount(tempCard.nfcFolderSettings.folder), 321, 0, - true, tempCard.nfcFolderSettings.folder); - uint8_t special2 = voiceMenu(mp3.getFolderTrackCount(tempCard.nfcFolderSettings.folder), 322, 0, - true, tempCard.nfcFolderSettings.folder, special); + int subMenu = voiceMenu(11, 900, 900, false, false, 0, true); + if (subMenu == 0) + return; + if (subMenu == 1) { + resetCard(); + mfrc522.PICC_HaltA(); + mfrc522.PCD_StopCrypto1(); + } + else if (subMenu == 2) { + // Maximum Volume + mySettings.maxVolume = voiceMenu(30, 930, 0, false, false, mySettings.maxVolume); + } + else if (subMenu == 3) { + // Minimum Volume + mySettings.minVolume = voiceMenu(30, 931, 0, false, false, mySettings.minVolume); + } + else if (subMenu == 4) { + // Initial Volume + mySettings.initVolume = voiceMenu(30, 932, 0, false, false, mySettings.initVolume); + } + else if (subMenu == 5) { + // EQ + mySettings.eq = voiceMenu(6, 920, 920, false, false, mySettings.eq); + mp3.setEq(mySettings.eq - 1); + } + else if (subMenu == 6) { + // create master card + } + else if (subMenu == 7) { + uint8_t shortcut = voiceMenu(4, 940, 940); + setupFolder(&mySettings.shortCuts[shortcut - 1]); + mp3.playMp3FolderTrack(400); + } + else if (subMenu == 8) { + switch (voiceMenu(5, 960, 960)) { + case 1: mySettings.standbyTimer = 5; break; + case 2: mySettings.standbyTimer = 15; break; + case 3: mySettings.standbyTimer = 30; break; + case 4: mySettings.standbyTimer = 60; break; + case 5: mySettings.standbyTimer = 0; break; + } + } + else if (subMenu == 9) { + // Create Cards for Folder + // Ordner abfragen + nfcTagObject tempCard; + tempCard.cookie = cardCookie; + tempCard.version = 1; + tempCard.nfcFolderSettings.mode = 4; + tempCard.nfcFolderSettings.folder = voiceMenu(99, 301, 0, true); + uint8_t special = voiceMenu(mp3.getFolderTrackCount(tempCard.nfcFolderSettings.folder), 321, 0, + true, tempCard.nfcFolderSettings.folder); + uint8_t special2 = voiceMenu(mp3.getFolderTrackCount(tempCard.nfcFolderSettings.folder), 322, 0, + true, tempCard.nfcFolderSettings.folder, special); - mp3.playMp3FolderTrack(936); - waitForTrackToFinish(); - for (uint8_t x = special; x <= special2; x++) { - mp3.playMp3FolderTrack(x); - tempCard.nfcFolderSettings.special = x; - Serial.print(x); - Serial.println(F(" Karte auflegen")); - do { - readButtons(); - if (upButton.wasReleased() || downButton.wasReleased()) { - Serial.println(F("Abgebrochen!")); - mp3.playMp3FolderTrack(802); - return; - } - } while (!mfrc522.PICC_IsNewCardPresent()); + mp3.playMp3FolderTrack(936); + waitForTrackToFinish(); + for (uint8_t x = special; x <= special2; x++) { + mp3.playMp3FolderTrack(x); + tempCard.nfcFolderSettings.special = x; + Serial.print(x); + Serial.println(F(" Karte auflegen")); + do { + readButtons(); + if (upButton.wasReleased() || downButton.wasReleased()) { + Serial.println(F("Abgebrochen!")); + mp3.playMp3FolderTrack(802); + return; + } + } while (!mfrc522.PICC_IsNewCardPresent()); - // RFID Karte wurde aufgelegt - if (!mfrc522.PICC_ReadCardSerial()) - return; - Serial.println(F("schreibe Karte...")); - writeCard(tempCard); - delay(100); - mfrc522.PICC_HaltA(); - mfrc522.PCD_StopCrypto1(); - waitForTrackToFinish(); - } - } - else if (subMenu == 10) { - // Invert Functions for Up/Down Buttons - int temp = voiceMenu(2, 933, 933, false); - if (temp == 2) { - mySettings.invertVolumeButtons = true; - } - else { - mySettings.invertVolumeButtons = false; - } - } - writeSettingsToFlash(); - setstandbyTimer(); + // RFID Karte wurde aufgelegt + if (!mfrc522.PICC_ReadCardSerial()) + return; + Serial.println(F("schreibe Karte...")); + writeCard(tempCard); + delay(100); + mfrc522.PICC_HaltA(); + mfrc522.PCD_StopCrypto1(); + waitForTrackToFinish(); + } + } + else if (subMenu == 10) { + // Invert Functions for Up/Down Buttons + int temp = voiceMenu(2, 933, 933, false); + if (temp == 2) { + mySettings.invertVolumeButtons = true; + } + else { + mySettings.invertVolumeButtons = false; + } + } + else if (subMenu == 11) { + Serial.println(F("Reset -> EEPROM wird gelöscht")); + for (int i = 0; i < EEPROM.length(); i++) { + EEPROM.update(i, 0); + } + resetSettings(); + mp3.playMp3FolderTrack(999); + } + writeSettingsToFlash(); + setstandbyTimer(); } bool askCode(uint8_t *code) { - uint8_t x = 0; - while (x < 3) { - readButtons(); - if (pauseButton.pressedFor(LONG_PRESS)) - break; - if (pauseButton.wasReleased()) - code[x++] = 1; - if (upButton.wasReleased()) - code[x++] = 2; - if (downButton.wasReleased()) - code[x++] = 3; - } - return true; + uint8_t x = 0; + while (x < 3) { + readButtons(); + if (pauseButton.pressedFor(LONG_PRESS)) + break; + if (pauseButton.wasReleased()) + code[x++] = 1; + if (upButton.wasReleased()) + code[x++] = 2; + if (downButton.wasReleased()) + code[x++] = 3; + } + return true; } uint8_t voiceMenu(int numberOfOptions, int startMessage, int messageOffset, - bool preview = false, int previewFromFolder = 0, int defaultValue = 0, bool exitWithLongPress = false) { - uint8_t returnValue = defaultValue; - if (startMessage != 0) - mp3.playMp3FolderTrack(startMessage); - Serial.print(F("=== voiceMenu() (")); - Serial.print(numberOfOptions); - Serial.println(F(" Options)")); - do { - if (Serial.available() > 0) { - int optionSerial = Serial.parseInt(); - if (optionSerial != 0 && optionSerial <= numberOfOptions) - return optionSerial; - } - readButtons(); - mp3.loop(); - if (pauseButton.pressedFor(LONG_PRESS)) { - mp3.playMp3FolderTrack(802); - ignorePauseButton = true; - return 0; - } - if (pauseButton.wasReleased()) { - if (returnValue != 0) { - Serial.print(F("=== ")); - Serial.print(returnValue); - Serial.println(F(" ===")); - return returnValue; - } - delay(1000); - } + bool preview = false, int previewFromFolder = 0, int defaultValue = 0, bool exitWithLongPress = false) { + uint8_t returnValue = defaultValue; + if (startMessage != 0) + mp3.playMp3FolderTrack(startMessage); + Serial.print(F("=== voiceMenu() (")); + Serial.print(numberOfOptions); + Serial.println(F(" Options)")); + do { + if (Serial.available() > 0) { + int optionSerial = Serial.parseInt(); + if (optionSerial != 0 && optionSerial <= numberOfOptions) + return optionSerial; + } + readButtons(); + mp3.loop(); + if (pauseButton.pressedFor(LONG_PRESS)) { + mp3.playMp3FolderTrack(802); + ignorePauseButton = true; + return 0; + } + if (pauseButton.wasReleased()) { + if (returnValue != 0) { + Serial.print(F("=== ")); + Serial.print(returnValue); + Serial.println(F(" ===")); + return returnValue; + } + delay(1000); + } - if (upButton.pressedFor(LONG_PRESS)) { - returnValue = min(returnValue + 10, numberOfOptions); - Serial.println(returnValue); - //mp3.pause(); - mp3.playMp3FolderTrack(messageOffset + returnValue); - waitForTrackToFinish(); - /*if (preview) { - if (previewFromFolder == 0) - mp3.playFolderTrack(returnValue, 1); - else - mp3.playFolderTrack(previewFromFolder, returnValue); - }*/ - ignoreUpButton = true; - } else if (upButton.wasReleased()) { - if (!ignoreUpButton) { - returnValue = min(returnValue + 1, numberOfOptions); - Serial.println(returnValue); - //mp3.pause(); - mp3.playMp3FolderTrack(messageOffset + returnValue); - if (preview) { - waitForTrackToFinish(); - if (previewFromFolder == 0) { - mp3.playFolderTrack(returnValue, 1); - } else { - mp3.playFolderTrack(previewFromFolder, returnValue); - } - delay(1000); - } - } else { - ignoreUpButton = false; - } - } + if (upButton.pressedFor(LONG_PRESS)) { + returnValue = min(returnValue + 10, numberOfOptions); + Serial.println(returnValue); + //mp3.pause(); + mp3.playMp3FolderTrack(messageOffset + returnValue); + waitForTrackToFinish(); + /*if (preview) { + if (previewFromFolder == 0) + mp3.playFolderTrack(returnValue, 1); + else + mp3.playFolderTrack(previewFromFolder, returnValue); + }*/ + ignoreUpButton = true; + } else if (upButton.wasReleased()) { + if (!ignoreUpButton) { + returnValue = min(returnValue + 1, numberOfOptions); + Serial.println(returnValue); + //mp3.pause(); + mp3.playMp3FolderTrack(messageOffset + returnValue); + if (preview) { + waitForTrackToFinish(); + if (previewFromFolder == 0) { + mp3.playFolderTrack(returnValue, 1); + } else { + mp3.playFolderTrack(previewFromFolder, returnValue); + } + delay(1000); + } + } else { + ignoreUpButton = false; + } + } - if (downButton.pressedFor(LONG_PRESS)) { - returnValue = max(returnValue - 10, 1); - Serial.println(returnValue); - //mp3.pause(); - mp3.playMp3FolderTrack(messageOffset + returnValue); - waitForTrackToFinish(); - /*if (preview) { - if (previewFromFolder == 0) - mp3.playFolderTrack(returnValue, 1); - else - mp3.playFolderTrack(previewFromFolder, returnValue); - }*/ - ignoreDownButton = true; - } else if (downButton.wasReleased()) { - if (!ignoreDownButton) { - returnValue = max(returnValue - 1, 1); - Serial.println(returnValue); - //mp3.pause(); - mp3.playMp3FolderTrack(messageOffset + returnValue); - if (preview) { - waitForTrackToFinish(); - if (previewFromFolder == 0) { - mp3.playFolderTrack(returnValue, 1); - } - else { - mp3.playFolderTrack(previewFromFolder, returnValue); - } - delay(1000); - } - } else { - ignoreDownButton = false; - } - } - } while (true); + if (downButton.pressedFor(LONG_PRESS)) { + returnValue = max(returnValue - 10, 1); + Serial.println(returnValue); + //mp3.pause(); + mp3.playMp3FolderTrack(messageOffset + returnValue); + waitForTrackToFinish(); + /*if (preview) { + if (previewFromFolder == 0) + mp3.playFolderTrack(returnValue, 1); + else + mp3.playFolderTrack(previewFromFolder, returnValue); + }*/ + ignoreDownButton = true; + } else if (downButton.wasReleased()) { + if (!ignoreDownButton) { + returnValue = max(returnValue - 1, 1); + Serial.println(returnValue); + //mp3.pause(); + mp3.playMp3FolderTrack(messageOffset + returnValue); + if (preview) { + waitForTrackToFinish(); + if (previewFromFolder == 0) { + mp3.playFolderTrack(returnValue, 1); + } + else { + mp3.playFolderTrack(previewFromFolder, returnValue); + } + delay(1000); + } + } else { + ignoreDownButton = false; + } + } + } while (true); } void resetCard() { - mp3.playMp3FolderTrack(800); - do { - pauseButton.read(); - upButton.read(); - downButton.read(); + mp3.playMp3FolderTrack(800); + do { + pauseButton.read(); + upButton.read(); + downButton.read(); - if (upButton.wasReleased() || downButton.wasReleased()) { - Serial.print(F("Abgebrochen!")); - mp3.playMp3FolderTrack(802); - return; - } - } while (!mfrc522.PICC_IsNewCardPresent()); + if (upButton.wasReleased() || downButton.wasReleased()) { + Serial.print(F("Abgebrochen!")); + mp3.playMp3FolderTrack(802); + return; + } + } while (!mfrc522.PICC_IsNewCardPresent()); - if (!mfrc522.PICC_ReadCardSerial()) - return; + if (!mfrc522.PICC_ReadCardSerial()) + return; - Serial.print(F("Karte wird neu konfiguriert!")); - setupCard(); + Serial.print(F("Karte wird neu konfiguriert!")); + setupCard(); } void setupFolder(folderSettings * theFolder) { - // Ordner abfragen - theFolder->folder = voiceMenu(99, 301, 0, true); + // Ordner abfragen + theFolder->folder = voiceMenu(99, 301, 0, true); - // Wiedergabemodus abfragen - theFolder->mode = voiceMenu(9, 310, 310); + // Wiedergabemodus abfragen + theFolder->mode = voiceMenu(9, 310, 310); - // // Hörbuchmodus -> Fortschritt im EEPROM auf 1 setzen - // EEPROM.update(theFolder->folder, 1); + // // Hörbuchmodus -> Fortschritt im EEPROM auf 1 setzen + // EEPROM.update(theFolder->folder, 1); - // Einzelmodus -> Datei abfragen - if (theFolder->mode == 4) - theFolder->special = voiceMenu(mp3.getFolderTrackCount(theFolder->folder), 320, 0, - true, theFolder->folder); - // Admin Funktionen - if (theFolder->mode == 6) - theFolder->special = voiceMenu(3, 320, 320); + // Einzelmodus -> Datei abfragen + if (theFolder->mode == 4) + theFolder->special = voiceMenu(mp3.getFolderTrackCount(theFolder->folder), 320, 0, + true, theFolder->folder); + // Admin Funktionen + if (theFolder->mode == 6) + theFolder->special = voiceMenu(3, 320, 320); - // Spezialmodus Von-Bis - if (theFolder->mode == 7 || theFolder->mode == 8 || theFolder->mode == 9) { - theFolder->special = voiceMenu(mp3.getFolderTrackCount(theFolder->folder), 321, 0, - true, theFolder->folder); - theFolder->special2 = voiceMenu(mp3.getFolderTrackCount(theFolder->folder), 322, 0, - true, theFolder->folder, theFolder->special); - } + // Spezialmodus Von-Bis + if (theFolder->mode == 7 || theFolder->mode == 8 || theFolder->mode == 9) { + theFolder->special = voiceMenu(mp3.getFolderTrackCount(theFolder->folder), 321, 0, + true, theFolder->folder); + theFolder->special2 = voiceMenu(mp3.getFolderTrackCount(theFolder->folder), 322, 0, + true, theFolder->folder, theFolder->special); + } } void setupCard() { - mp3.pause(); - Serial.println(F("=== setupCard()")); - setupFolder(&myCard.nfcFolderSettings); - // Karte ist konfiguriert -> speichern - mp3.pause(); - do { - } while (isPlaying()); - writeCard(myCard); + mp3.pause(); + Serial.println(F("=== setupCard()")); + setupFolder(&myCard.nfcFolderSettings); + // Karte ist konfiguriert -> speichern + mp3.pause(); + do { + } while (isPlaying()); + writeCard(myCard); } bool readCard(nfcTagObject * nfcTag) { - // Show some details of the PICC (that is: the tag/card) - Serial.print(F("Card UID:")); - dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size); - Serial.println(); - Serial.print(F("PICC type: ")); - MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); - Serial.println(mfrc522.PICC_GetTypeName(piccType)); + // Show some details of the PICC (that is: the tag/card) + Serial.print(F("Card UID:")); + dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size); + Serial.println(); + Serial.print(F("PICC type: ")); + MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); + Serial.println(mfrc522.PICC_GetTypeName(piccType)); - byte buffer[18]; - byte size = sizeof(buffer); + byte buffer[18]; + byte size = sizeof(buffer); - // Authenticate using key A - if ((piccType == MFRC522::PICC_TYPE_MIFARE_MINI ) || - (piccType == MFRC522::PICC_TYPE_MIFARE_1K ) || - (piccType == MFRC522::PICC_TYPE_MIFARE_4K ) ) - { - Serial.println(F("Authenticating Classic using key A...")); - status = mfrc522.PCD_Authenticate( - MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid)); - } - else if (piccType == MFRC522::PICC_TYPE_MIFARE_UL ) - { - byte pACK[] = {0, 0}; //16 bit PassWord ACK returned by the NFCtag + // Authenticate using key A + if ((piccType == MFRC522::PICC_TYPE_MIFARE_MINI ) || + (piccType == MFRC522::PICC_TYPE_MIFARE_1K ) || + (piccType == MFRC522::PICC_TYPE_MIFARE_4K ) ) + { + Serial.println(F("Authenticating Classic using key A...")); + status = mfrc522.PCD_Authenticate( + MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid)); + } + else if (piccType == MFRC522::PICC_TYPE_MIFARE_UL ) + { + byte pACK[] = {0, 0}; //16 bit PassWord ACK returned by the NFCtag - // Authenticate using key A - Serial.println(F("Authenticating MIFARE UL...")); - status = mfrc522.PCD_NTAG216_AUTH(key.keyByte, pACK); - } + // Authenticate using key A + Serial.println(F("Authenticating MIFARE UL...")); + status = mfrc522.PCD_NTAG216_AUTH(key.keyByte, pACK); + } - if (status != MFRC522::STATUS_OK) { - Serial.print(F("PCD_Authenticate() failed: ")); - Serial.println(mfrc522.GetStatusCodeName(status)); - return false; - } + if (status != MFRC522::STATUS_OK) { + Serial.print(F("PCD_Authenticate() failed: ")); + Serial.println(mfrc522.GetStatusCodeName(status)); + return false; + } - // Show the whole sector as it currently is - // Serial.println(F("Current data in sector:")); - // mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector); - // Serial.println(); + // Show the whole sector as it currently is + // Serial.println(F("Current data in sector:")); + // mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector); + // Serial.println(); - // Read data from the block - if ((piccType == MFRC522::PICC_TYPE_MIFARE_MINI ) || - (piccType == MFRC522::PICC_TYPE_MIFARE_1K ) || - (piccType == MFRC522::PICC_TYPE_MIFARE_4K ) ) - { - Serial.print(F("Reading data from block ")); - Serial.print(blockAddr); - Serial.println(F(" ...")); - status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(blockAddr, buffer, &size); - if (status != MFRC522::STATUS_OK) { - Serial.print(F("MIFARE_Read() failed: ")); - Serial.println(mfrc522.GetStatusCodeName(status)); - return false; - } - } - else if (piccType == MFRC522::PICC_TYPE_MIFARE_UL ) - { - byte buffer2[18]; - byte size2 = sizeof(buffer2); + // Read data from the block + if ((piccType == MFRC522::PICC_TYPE_MIFARE_MINI ) || + (piccType == MFRC522::PICC_TYPE_MIFARE_1K ) || + (piccType == MFRC522::PICC_TYPE_MIFARE_4K ) ) + { + Serial.print(F("Reading data from block ")); + Serial.print(blockAddr); + Serial.println(F(" ...")); + status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(blockAddr, buffer, &size); + if (status != MFRC522::STATUS_OK) { + Serial.print(F("MIFARE_Read() failed: ")); + Serial.println(mfrc522.GetStatusCodeName(status)); + return false; + } + } + else if (piccType == MFRC522::PICC_TYPE_MIFARE_UL ) + { + byte buffer2[18]; + byte size2 = sizeof(buffer2); - status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(8, buffer2, &size2); - if (status != MFRC522::STATUS_OK) { - Serial.print(F("MIFARE_Read_1() failed: ")); - Serial.println(mfrc522.GetStatusCodeName(status)); - return false; - } - memcpy(buffer, buffer2, 4); + status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(8, buffer2, &size2); + if (status != MFRC522::STATUS_OK) { + Serial.print(F("MIFARE_Read_1() failed: ")); + Serial.println(mfrc522.GetStatusCodeName(status)); + return false; + } + memcpy(buffer, buffer2, 4); - status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(9, buffer2, &size2); - if (status != MFRC522::STATUS_OK) { - Serial.print(F("MIFARE_Read_2() failed: ")); - Serial.println(mfrc522.GetStatusCodeName(status)); - return false; - } - memcpy(buffer + 4, buffer2, 4); + status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(9, buffer2, &size2); + if (status != MFRC522::STATUS_OK) { + Serial.print(F("MIFARE_Read_2() failed: ")); + Serial.println(mfrc522.GetStatusCodeName(status)); + return false; + } + memcpy(buffer + 4, buffer2, 4); - status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(10, buffer2, &size2); - if (status != MFRC522::STATUS_OK) { - Serial.print(F("MIFARE_Read_3() failed: ")); - Serial.println(mfrc522.GetStatusCodeName(status)); - return false; - } - memcpy(buffer + 8, buffer2, 4); + status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(10, buffer2, &size2); + if (status != MFRC522::STATUS_OK) { + Serial.print(F("MIFARE_Read_3() failed: ")); + Serial.println(mfrc522.GetStatusCodeName(status)); + return false; + } + memcpy(buffer + 8, buffer2, 4); - status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(11, buffer2, &size2); - if (status != MFRC522::STATUS_OK) { - Serial.print(F("MIFARE_Read_4() failed: ")); - Serial.println(mfrc522.GetStatusCodeName(status)); - return false; - } - memcpy(buffer + 12, buffer2, 4); - } + status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(11, buffer2, &size2); + if (status != MFRC522::STATUS_OK) { + Serial.print(F("MIFARE_Read_4() failed: ")); + Serial.println(mfrc522.GetStatusCodeName(status)); + return false; + } + memcpy(buffer + 12, buffer2, 4); + } - Serial.print(F("Data on Card ")); - Serial.println(F(":")); - dump_byte_array(buffer, 16); - Serial.println(); - Serial.println(); + Serial.print(F("Data on Card ")); + Serial.println(F(":")); + dump_byte_array(buffer, 16); + Serial.println(); + Serial.println(); - uint32_t tempCookie; - tempCookie = (uint32_t)buffer[0] << 24; - tempCookie += (uint32_t)buffer[1] << 16; - tempCookie += (uint32_t)buffer[2] << 8; - tempCookie += (uint32_t)buffer[3]; + uint32_t tempCookie; + tempCookie = (uint32_t)buffer[0] << 24; + tempCookie += (uint32_t)buffer[1] << 16; + tempCookie += (uint32_t)buffer[2] << 8; + tempCookie += (uint32_t)buffer[3]; - nfcTag->cookie = tempCookie; - nfcTag->version = buffer[4]; - nfcTag->nfcFolderSettings.folder = buffer[5]; - nfcTag->nfcFolderSettings.mode = buffer[6]; - nfcTag->nfcFolderSettings.special = buffer[7]; - nfcTag->nfcFolderSettings.special2 = buffer[8]; + nfcTag->cookie = tempCookie; + nfcTag->version = buffer[4]; + nfcTag->nfcFolderSettings.folder = buffer[5]; + nfcTag->nfcFolderSettings.mode = buffer[6]; + nfcTag->nfcFolderSettings.special = buffer[7]; + nfcTag->nfcFolderSettings.special2 = buffer[8]; - myFolder = &nfcTag->nfcFolderSettings; + myFolder = &nfcTag->nfcFolderSettings; - return true; + return true; } void writeCard(nfcTagObject nfcTag) { - MFRC522::PICC_Type mifareType; - byte buffer[16] = {0x13, 0x37, 0xb3, 0x47, // 0x1337 0xb347 magic cookie to - // identify our nfc tags - 0x02, // version 1 - nfcTag.nfcFolderSettings.folder, // the folder picked by the user - nfcTag.nfcFolderSettings.mode, // the playback mode picked by the user - nfcTag.nfcFolderSettings.special, // track or function for admin cards - nfcTag.nfcFolderSettings.special2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; + MFRC522::PICC_Type mifareType; + byte buffer[16] = {0x13, 0x37, 0xb3, 0x47, // 0x1337 0xb347 magic cookie to + // identify our nfc tags + 0x02, // version 1 + nfcTag.nfcFolderSettings.folder, // the folder picked by the user + nfcTag.nfcFolderSettings.mode, // the playback mode picked by the user + nfcTag.nfcFolderSettings.special, // track or function for admin cards + nfcTag.nfcFolderSettings.special2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; - byte size = sizeof(buffer); + byte size = sizeof(buffer); - mifareType = mfrc522.PICC_GetType(mfrc522.uid.sak); + mifareType = mfrc522.PICC_GetType(mfrc522.uid.sak); - // Authenticate using key B - //authentificate with the card and set card specific parameters - if ((mifareType == MFRC522::PICC_TYPE_MIFARE_MINI ) || - (mifareType == MFRC522::PICC_TYPE_MIFARE_1K ) || - (mifareType == MFRC522::PICC_TYPE_MIFARE_4K ) ) - { - Serial.println(F("Authenticating again using key B...")); - status = mfrc522.PCD_Authenticate( - MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid)); - } - else if (mifareType == MFRC522::PICC_TYPE_MIFARE_UL ) - { - byte pACK[] = {0, 0}; //16 bit PassWord ACK returned by the NFCtag + // Authenticate using key B + //authentificate with the card and set card specific parameters + if ((mifareType == MFRC522::PICC_TYPE_MIFARE_MINI ) || + (mifareType == MFRC522::PICC_TYPE_MIFARE_1K ) || + (mifareType == MFRC522::PICC_TYPE_MIFARE_4K ) ) + { + Serial.println(F("Authenticating again using key B...")); + status = mfrc522.PCD_Authenticate( + MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid)); + } + else if (mifareType == MFRC522::PICC_TYPE_MIFARE_UL ) + { + byte pACK[] = {0, 0}; //16 bit PassWord ACK returned by the NFCtag - // Authenticate using key A - Serial.println(F("Authenticating UL...")); - status = mfrc522.PCD_NTAG216_AUTH(key.keyByte, pACK); - } + // Authenticate using key A + Serial.println(F("Authenticating UL...")); + status = mfrc522.PCD_NTAG216_AUTH(key.keyByte, pACK); + } - if (status != MFRC522::STATUS_OK) { - Serial.print(F("PCD_Authenticate() failed: ")); - Serial.println(mfrc522.GetStatusCodeName(status)); - mp3.playMp3FolderTrack(401); - return; - } + if (status != MFRC522::STATUS_OK) { + Serial.print(F("PCD_Authenticate() failed: ")); + Serial.println(mfrc522.GetStatusCodeName(status)); + mp3.playMp3FolderTrack(401); + return; + } - // Write data to the block - Serial.print(F("Writing data into block ")); - Serial.print(blockAddr); - Serial.println(F(" ...")); - dump_byte_array(buffer, 16); - Serial.println(); + // Write data to the block + Serial.print(F("Writing data into block ")); + Serial.print(blockAddr); + Serial.println(F(" ...")); + dump_byte_array(buffer, 16); + Serial.println(); - if ((mifareType == MFRC522::PICC_TYPE_MIFARE_MINI ) || - (mifareType == MFRC522::PICC_TYPE_MIFARE_1K ) || - (mifareType == MFRC522::PICC_TYPE_MIFARE_4K ) ) - { - status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(blockAddr, buffer, 16); - } - else if (mifareType == MFRC522::PICC_TYPE_MIFARE_UL ) - { - byte buffer2[16]; - byte size2 = sizeof(buffer2); + if ((mifareType == MFRC522::PICC_TYPE_MIFARE_MINI ) || + (mifareType == MFRC522::PICC_TYPE_MIFARE_1K ) || + (mifareType == MFRC522::PICC_TYPE_MIFARE_4K ) ) + { + status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(blockAddr, buffer, 16); + } + else if (mifareType == MFRC522::PICC_TYPE_MIFARE_UL ) + { + byte buffer2[16]; + byte size2 = sizeof(buffer2); - memset(buffer2, 0, size2); - memcpy(buffer2, buffer, 4); - status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(8, buffer2, 16); + memset(buffer2, 0, size2); + memcpy(buffer2, buffer, 4); + status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(8, buffer2, 16); - memset(buffer2, 0, size2); - memcpy(buffer2, buffer + 4, 4); - status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(9, buffer2, 16); + memset(buffer2, 0, size2); + memcpy(buffer2, buffer + 4, 4); + status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(9, buffer2, 16); - memset(buffer2, 0, size2); - memcpy(buffer2, buffer + 8, 4); - status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(10, buffer2, 16); + memset(buffer2, 0, size2); + memcpy(buffer2, buffer + 8, 4); + status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(10, buffer2, 16); - memset(buffer2, 0, size2); - memcpy(buffer2, buffer + 12, 4); - status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(11, buffer2, 16); - } + memset(buffer2, 0, size2); + memcpy(buffer2, buffer + 12, 4); + status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(11, buffer2, 16); + } - if (status != MFRC522::STATUS_OK) { - Serial.print(F("MIFARE_Write() failed: ")); - Serial.println(mfrc522.GetStatusCodeName(status)); - mp3.playMp3FolderTrack(401); - } - else - mp3.playMp3FolderTrack(400); - Serial.println(); - delay(100); + if (status != MFRC522::STATUS_OK) { + Serial.print(F("MIFARE_Write() failed: ")); + Serial.println(mfrc522.GetStatusCodeName(status)); + mp3.playMp3FolderTrack(401); + } + else + mp3.playMp3FolderTrack(400); + Serial.println(); + delay(100); } @@ -1234,8 +1242,8 @@ void writeCard(nfcTagObject nfcTag) { Helper routine to dump a byte array as hex values to Serial. */ void dump_byte_array(byte * buffer, byte bufferSize) { - for (byte i = 0; i < bufferSize; i++) { - Serial.print(buffer[i] < 0x10 ? " 0" : " "); - Serial.print(buffer[i], HEX); - } + for (byte i = 0; i < bufferSize; i++) { + Serial.print(buffer[i] < 0x10 ? " 0" : " "); + Serial.print(buffer[i], HEX); + } } diff --git a/soundfiles.txt b/soundfiles.txt index c9818ce..e49047d 100644 --- a/soundfiles.txt +++ b/soundfiles.txt @@ -30,6 +30,7 @@ mp3/0907_shortcut.mp3|Tasten mit einem Shortcut konfigurieren. Ein Shortcut wird mp3/0908_standbytimer.mp3|Den Timer konfigurieren. mp3/0909_batch_cards.mp3|Einzelkarten für einen Ordner erstellen. mp3/0910_switch_volume.mp3|Funktion der Lautstärketasten umdrehen. +mp3/0911_reset.mp3|Alle Einstellungen löschen. mp3/0920_eq_intro.mp3|Bitte wähle eine Einstellung für den EQ mit den Lautstärketasten aus und bestätige sie mit der Pausetaste. mp3/0921_normal.mp3|Normal mp3/0922_pop.mp3|Pop