Guest User

Untitled

a guest
Mar 10th, 2020
194
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <DFMiniMp3.h>
  2. #include <EEPROM.h>
  3. #include <JC_Button.h>
  4. #include <MFRC522.h>
  5. #include <SPI.h>
  6. #include <SoftwareSerial.h>
  7. #include <avr/sleep.h>
  8.  
  9. /*
  10. _____ _____ _____ _____ _____
  11. |_ _|___ ___| | | | | | |
  12. | | | . | | | |- -| | | | | |
  13. |_| |___|_|_|_____|_____|_|___|_____|
  14. TonUINO Version 2.1
  15.  
  16. created by Thorsten Voß and licensed under GNU/GPL.
  17. Information and contribution at https://tonuino.de.
  18. */
  19.  
  20. // Entferne die // in der unteren Zeile, um die Unterstützung von fünf Knöpfen zu aktivieren
  21. //#define FIVEBUTTONS
  22.  
  23. static const uint32_t cardCookie = 322417479;
  24.  
  25. // DFPlayer Mini
  26. SoftwareSerial mySoftwareSerial(2, 3); // RX, TX
  27. uint16_t numTracksInFolder;
  28. uint16_t currentTrack;
  29. uint16_t firstTrack;
  30. uint8_t queue[255];
  31. uint8_t volume;
  32.  
  33. struct folderSettings {
  34. uint8_t folder;
  35. uint8_t mode;
  36. uint8_t special;
  37. uint8_t special2;
  38. };
  39.  
  40. // Dieses Objekt speichert NFC-Tag Daten
  41. struct nfcTagObject {
  42. uint32_t cookie;
  43. uint8_t version;
  44. folderSettings nfcFolderSettings;
  45. // uint8_t folder;
  46. // uint8_t mode;
  47. // uint8_t special;
  48. // uint8_t special2;
  49. };
  50.  
  51. // Admin-Einstellungen im EEPROM gespeichert
  52. struct adminSettings {
  53. uint32_t cookie;
  54. byte version;
  55. uint8_t maxVolume;
  56. uint8_t minVolume;
  57. uint8_t initVolume;
  58. uint8_t eq;
  59. bool locked;
  60. long standbyTimer;
  61. bool invertVolumeButtons;
  62. folderSettings shortCuts[4];
  63. uint8_t adminMenuLocked;
  64. uint8_t adminMenuPin[4];
  65. };
  66.  
  67. adminSettings mySettings;
  68. nfcTagObject myCard;
  69. folderSettings *myFolder;
  70. unsigned long sleepAtMillis = 0;
  71. static uint16_t _lastTrackFinished;
  72.  
  73. static void nextTrack(uint16_t track);
  74. uint8_t voiceMenu(int numberOfOptions, int startMessage, int messageOffset,
  75. bool preview = false, int previewFromFolder = 0, int defaultValue = 0, bool exitWithLongPress = false);
  76. bool isPlaying();
  77. bool checkTwo ( uint8_t a[], uint8_t b[] );
  78. void writeCard(nfcTagObject nfcTag);
  79. void dump_byte_array(byte * buffer, byte bufferSize);
  80. void adminMenu(bool fromCard = false);
  81. bool knownCard = false;
  82.  
  83. // Eine Benachrichtigungsklasse implementieren,
  84. // seine Mitgliedsmethoden werden aufgerufen
  85. //
  86. class Mp3Notify {
  87. public:
  88. static void OnError(uint16_t errorCode) {
  89. // see DfMp3_Error for code meaning
  90. Serial.println();
  91. Serial.print("Com Error ");
  92. Serial.println(errorCode);
  93. }
  94. static void PrintlnSourceAction(DfMp3_PlaySources source, const char* action) {
  95. if (source & DfMp3_PlaySources_Sd) Serial.print("SD Karte ");
  96. if (source & DfMp3_PlaySources_Usb) Serial.print("USB ");
  97. if (source & DfMp3_PlaySources_Flash) Serial.print("Flash ");
  98. Serial.println(action);
  99. }
  100. static void OnPlayFinished(DfMp3_PlaySources source, uint16_t track) {
  101. // Serial.print("Track beendet");
  102. // Serial.println(track);
  103. // delay(100);
  104. nextTrack(track);
  105. }
  106. static void OnPlaySourceOnline(DfMp3_PlaySources source) {
  107. PrintlnSourceAction(source, "online");
  108. }
  109. static void OnPlaySourceInserted(DfMp3_PlaySources source) {
  110. PrintlnSourceAction(source, "bereit");
  111. }
  112. static void OnPlaySourceRemoved(DfMp3_PlaySources source) {
  113. PrintlnSourceAction(source, "entfernt");
  114. }
  115. };
  116.  
  117. static DFMiniMp3<SoftwareSerial, Mp3Notify> mp3(mySoftwareSerial);
  118.  
  119. void shuffleQueue() {
  120. // Queue für die Zufallswiedergabe erstellen
  121. for (uint8_t x = 0; x < numTracksInFolder - firstTrack + 1; x++)
  122. queue[x] = x + firstTrack;
  123. // Rest mit 0 auffüllen
  124. for (uint8_t x = numTracksInFolder - firstTrack + 1; x < 255; x++)
  125. queue[x] = 0;
  126. // Queue mischen
  127. for (uint8_t i = 0; i < numTracksInFolder - firstTrack + 1; i++)
  128. {
  129. uint8_t j = random (0, numTracksInFolder - firstTrack + 1);
  130. uint8_t t = queue[i];
  131. queue[i] = queue[j];
  132. queue[j] = t;
  133. }
  134. /* Serial.println(F("Queue :"));
  135. for (uint8_t x = 0; x < numTracksInFolder - firstTrack + 1 ; x++)
  136. Serial.println(queue[x]);
  137. */
  138. }
  139.  
  140. void writeSettingsToFlash() {
  141. Serial.println(F("=== writeSettingsToFlash()"));
  142. int address = sizeof(myFolder->folder) * 100;
  143. EEPROM.put(address, mySettings);
  144. }
  145.  
  146. void resetSettings() {
  147. Serial.println(F("=== resetSettings()"));
  148. mySettings.cookie = cardCookie;
  149. mySettings.version = 2;
  150. mySettings.maxVolume = 25;
  151. mySettings.minVolume = 5;
  152. mySettings.initVolume = 15;
  153. mySettings.eq = 1;
  154. mySettings.locked = false;
  155. mySettings.standbyTimer = 0;
  156. mySettings.invertVolumeButtons = true;
  157. mySettings.shortCuts[0].folder = 0;
  158. mySettings.shortCuts[1].folder = 0;
  159. mySettings.shortCuts[2].folder = 0;
  160. mySettings.shortCuts[3].folder = 0;
  161. mySettings.adminMenuLocked = 0;
  162. mySettings.adminMenuPin[0] = 1;
  163. mySettings.adminMenuPin[1] = 1;
  164. mySettings.adminMenuPin[2] = 1;
  165. mySettings.adminMenuPin[3] = 1;
  166.  
  167. writeSettingsToFlash();
  168. }
  169.  
  170. void migrateSettings(int oldVersion) {
  171. if (oldVersion == 1) {
  172. Serial.println(F("=== resetSettings()"));
  173. Serial.println(F("1 -> 2"));
  174. mySettings.version = 2;
  175. mySettings.adminMenuLocked = 0;
  176. mySettings.adminMenuPin[0] = 1;
  177. mySettings.adminMenuPin[1] = 1;
  178. mySettings.adminMenuPin[2] = 1;
  179. mySettings.adminMenuPin[3] = 1;
  180. writeSettingsToFlash();
  181. }
  182. }
  183.  
  184. void loadSettingsFromFlash() {
  185. Serial.println(F("=== loadSettingsFromFlash()"));
  186. int address = sizeof(myFolder->folder) * 100;
  187. EEPROM.get(address, mySettings);
  188. if (mySettings.cookie != cardCookie)
  189. resetSettings();
  190. migrateSettings(mySettings.version);
  191.  
  192. Serial.print(F("Version: "));
  193. Serial.println(mySettings.version);
  194.  
  195. Serial.print(F("Maximal Volume: "));
  196. Serial.println(mySettings.maxVolume);
  197.  
  198. Serial.print(F("Minimal Volume: "));
  199. Serial.println(mySettings.minVolume);
  200.  
  201. Serial.print(F("Initial Volume: "));
  202. Serial.println(mySettings.initVolume);
  203.  
  204. Serial.print(F("EQ: "));
  205. Serial.println(mySettings.eq);
  206.  
  207. Serial.print(F("Locked: "));
  208. Serial.println(mySettings.locked);
  209.  
  210. Serial.print(F("Sleep Timer: "));
  211. Serial.println(mySettings.standbyTimer);
  212.  
  213. Serial.print(F("Inverted Volume Buttons: "));
  214. Serial.println(mySettings.invertVolumeButtons);
  215.  
  216. Serial.print(F("Admin Menu locked: "));
  217. Serial.println(mySettings.adminMenuLocked);
  218.  
  219. Serial.print(F("Admin Menu Pin: "));
  220. Serial.print(mySettings.adminMenuPin[0]);
  221. Serial.print(mySettings.adminMenuPin[1]);
  222. Serial.print(mySettings.adminMenuPin[2]);
  223. Serial.println(mySettings.adminMenuPin[3]);
  224. }
  225.  
  226. class Modifier {
  227. public:
  228. virtual void loop() {}
  229. virtual bool handlePause() {
  230. return false;
  231. }
  232. virtual bool handleNext() {
  233. return false;
  234. }
  235. virtual bool handlePrevious() {
  236. return false;
  237. }
  238. virtual bool handleNextButton() {
  239. return false;
  240. }
  241. virtual bool handlePreviousButton() {
  242. return false;
  243. }
  244. virtual bool handleVolumeUp() {
  245. return false;
  246. }
  247. virtual bool handleVolumeDown() {
  248. return false;
  249. }
  250. virtual bool handleRFID(nfcTagObject *newCard) {
  251. return false;
  252. }
  253. virtual uint8_t getActive() {
  254. return 0;
  255. }
  256. Modifier() {
  257.  
  258. }
  259. };
  260.  
  261. Modifier *activeModifier = NULL;
  262.  
  263. class SleepTimer: public Modifier {
  264. private:
  265. unsigned long sleepAtMillis = 0;
  266.  
  267. public:
  268. void loop() {
  269. if (this->sleepAtMillis != 0 && millis() > this->sleepAtMillis) {
  270. Serial.println(F("=== SleepTimer::loop() -> SLEEP!"));
  271. mp3.pause();
  272. setstandbyTimer();
  273. activeModifier = NULL;
  274. delete this;
  275. }
  276. }
  277.  
  278. SleepTimer(uint8_t minutes) {
  279. Serial.println(F("=== SleepTimer()"));
  280. Serial.println(minutes);
  281. this->sleepAtMillis = millis() + minutes * 60000;
  282. // if (isPlaying())
  283. // mp3.playAdvertisement(302);
  284. // delay(500);
  285. }
  286. uint8_t getActive() {
  287. Serial.println(F("== SleepTimer::getActive()"));
  288. return 1;
  289. }
  290. };
  291.  
  292. class FreezeDance: public Modifier {
  293. private:
  294. unsigned long nextStopAtMillis = 0;
  295. const uint8_t minSecondsBetweenStops = 5;
  296. const uint8_t maxSecondsBetweenStops = 30;
  297.  
  298. void setNextStopAtMillis() {
  299. uint16_t seconds = random(this->minSecondsBetweenStops, this->maxSecondsBetweenStops + 1);
  300. Serial.println(F("=== FreezeDance::setNextStopAtMillis()"));
  301. Serial.println(seconds);
  302. this->nextStopAtMillis = millis() + seconds * 1000;
  303. }
  304.  
  305. public:
  306. void loop() {
  307. if (this->nextStopAtMillis != 0 && millis() > this->nextStopAtMillis) {
  308. Serial.println(F("== FreezeDance::loop() -> FREEZE!"));
  309. if (isPlaying()) {
  310. mp3.playAdvertisement(301);
  311. delay(500);
  312. }
  313. setNextStopAtMillis();
  314. }
  315. }
  316. FreezeDance(void) {
  317. Serial.println(F("=== FreezeDance()"));
  318. if (isPlaying()) {
  319. delay(1000);
  320. mp3.playAdvertisement(300);
  321. delay(500);
  322. }
  323. setNextStopAtMillis();
  324. }
  325. uint8_t getActive() {
  326. Serial.println(F("== FreezeDance::getActive()"));
  327. return 2;
  328. }
  329. };
  330.  
  331. class Locked: public Modifier {
  332. public:
  333. virtual bool handlePause() {
  334. Serial.println(F("== Locked::handlePause() -> LOCKED!"));
  335. return true;
  336. }
  337. virtual bool handleNextButton() {
  338. Serial.println(F("== Locked::handleNextButton() -> LOCKED!"));
  339. return true;
  340. }
  341. virtual bool handlePreviousButton() {
  342. Serial.println(F("== Locked::handlePreviousButton() -> LOCKED!"));
  343. return true;
  344. }
  345. virtual bool handleVolumeUp() {
  346. Serial.println(F("== Locked::handleVolumeUp() -> LOCKED!"));
  347. return true;
  348. }
  349. virtual bool handleVolumeDown() {
  350. Serial.println(F("== Locked::handleVolumeDown() -> LOCKED!"));
  351. return true;
  352. }
  353. virtual bool handleRFID(nfcTagObject *newCard) {
  354. Serial.println(F("== Locked::handleRFID() -> LOCKED!"));
  355. return true;
  356. }
  357. Locked(void) {
  358. Serial.println(F("=== Locked()"));
  359. // if (isPlaying())
  360. // mp3.playAdvertisement(303);
  361. }
  362. uint8_t getActive() {
  363. return 3;
  364. }
  365. };
  366.  
  367. class ToddlerMode: public Modifier {
  368. public:
  369. virtual bool handlePause() {
  370. Serial.println(F("== ToddlerMode::handlePause() -> LOCKED!"));
  371. return true;
  372. }
  373. virtual bool handleNextButton() {
  374. Serial.println(F("== ToddlerMode::handleNextButton() -> LOCKED!"));
  375. return true;
  376. }
  377. virtual bool handlePreviousButton() {
  378. Serial.println(F("== ToddlerMode::handlePreviousButton() -> LOCKED!"));
  379. return true;
  380. }
  381. virtual bool handleVolumeUp() {
  382. Serial.println(F("== ToddlerMode::handleVolumeUp() -> LOCKED!"));
  383. return true;
  384. }
  385. virtual bool handleVolumeDown() {
  386. Serial.println(F("== ToddlerMode::handleVolumeDown() -> LOCKED!"));
  387. return true;
  388. }
  389. ToddlerMode(void) {
  390. Serial.println(F("=== ToddlerMode()"));
  391. // if (isPlaying())
  392. // mp3.playAdvertisement(304);
  393. }
  394. uint8_t getActive() {
  395. Serial.println(F("== ToddlerMode::getActive()"));
  396. return 4;
  397. }
  398. };
  399.  
  400. class KindergardenMode: public Modifier {
  401. private:
  402. nfcTagObject nextCard;
  403. bool cardQueued = false;
  404.  
  405. public:
  406. virtual bool handleNext() {
  407. Serial.println(F("== KindergardenMode::handleNext() -> NEXT"));
  408. //if (this->nextCard.cookie == cardCookie && this->nextCard.nfcFolderSettings.folder != 0 && this->nextCard.nfcFolderSettings.mode != 0) {
  409. //myFolder = &this->nextCard.nfcFolderSettings;
  410. if (this->cardQueued == true) {
  411. this->cardQueued = false;
  412.  
  413. myCard = nextCard;
  414. myFolder = &myCard.nfcFolderSettings;
  415. Serial.println(myFolder->folder);
  416. Serial.println(myFolder->mode);
  417. playFolder();
  418. return true;
  419. }
  420. return false;
  421. }
  422. // virtual bool handlePause() {
  423. // Serial.println(F("== KindergardenMode::handlePause() -> LOCKED!"));
  424. // return true;
  425. // }
  426. virtual bool handleNextButton() {
  427. Serial.println(F("== KindergardenMode::handleNextButton() -> LOCKED!"));
  428. return true;
  429. }
  430. virtual bool handlePreviousButton() {
  431. Serial.println(F("== KindergardenMode::handlePreviousButton() -> LOCKED!"));
  432. return true;
  433. }
  434. virtual bool handleRFID(nfcTagObject * newCard) { // lot of work to do!
  435. Serial.println(F("== KindergardenMode::handleRFID() -> queued!"));
  436. this->nextCard = *newCard;
  437. this->cardQueued = true;
  438. if (!isPlaying()) {
  439. handleNext();
  440. }
  441. return true;
  442. }
  443. KindergardenMode() {
  444. Serial.println(F("=== KindergardenMode()"));
  445. // if (isPlaying())
  446. // mp3.playAdvertisement(305);
  447. // delay(500);
  448. }
  449. uint8_t getActive() {
  450. Serial.println(F("== KindergardenMode::getActive()"));
  451. return 5;
  452. }
  453. };
  454.  
  455. class RepeatSingleModifier: public Modifier {
  456. public:
  457. virtual bool handleNext() {
  458. Serial.println(F("== RepeatSingleModifier::handleNext() -> REPEAT CURRENT TRACK"));
  459. delay(50);
  460. if (isPlaying()) return true;
  461. mp3.playFolderTrack(myFolder->folder, currentTrack);
  462. _lastTrackFinished = 0;
  463. return true;
  464. }
  465. RepeatSingleModifier() {
  466. Serial.println(F("=== RepeatSingleModifier()"));
  467. }
  468. uint8_t getActive() {
  469. Serial.println(F("== RepeatSingleModifier::getActive()"));
  470. return 6;
  471. }
  472. };
  473.  
  474. // Ein Modifikator kann auch etwas zusätzlich zur modifizierten Aktion tun
  475. // durch Rückgabe von Falsch (nicht behandelt) am Ende
  476. // Dieser einfache FeedbackModifier teilt die Lautstärke vor der Änderung mit und
  477. // eine Rückmeldung, sobald eine RFID-Karte erkannt wird.
  478. class FeedbackModifier: public Modifier {
  479. public:
  480. virtual bool handleVolumeDown() {
  481. if (volume > mySettings.minVolume) {
  482. mp3.playAdvertisement(volume - 1);
  483. }
  484. else {
  485. mp3.playAdvertisement(volume);
  486. }
  487. delay(500);
  488. Serial.println(F("== FeedbackModifier::handleVolumeDown()!"));
  489. return false;
  490. }
  491. virtual bool handleVolumeUp() {
  492. if (volume < mySettings.maxVolume) {
  493. mp3.playAdvertisement(volume + 1);
  494. }
  495. else {
  496. mp3.playAdvertisement(volume);
  497. }
  498. delay(500);
  499. Serial.println(F("== FeedbackModifier::handleVolumeUp()!"));
  500. return false;
  501. }
  502. virtual bool handleRFID(nfcTagObject *newCard) {
  503. Serial.println(F("== FeedbackModifier::handleRFID()"));
  504. return false;
  505. }
  506. };
  507.  
  508. // Leider kann das Modul selbst keine Queue abspielen, daher müssen wir selbst die Queue verwalten
  509. static void nextTrack(uint16_t track) {
  510. Serial.println(track);
  511. if (activeModifier != NULL)
  512. if (activeModifier->handleNext() == true)
  513. return;
  514.  
  515. if (track == _lastTrackFinished) {
  516. return;
  517. }
  518. _lastTrackFinished = track;
  519.  
  520. if (knownCard == false)
  521. // Wenn eine neue Karte angelernt wird soll das Ende eines Tracks nicht
  522. // verarbeitet werden
  523. return;
  524.  
  525. Serial.println(F("=== nextTrack()"));
  526.  
  527. if (myFolder->mode == 1 || myFolder->mode == 7) {
  528. Serial.println(F("Hörspielmodus ist aktiv -> keinen neuen Track spielen"));
  529. setstandbyTimer();
  530. // mp3.sleep(); // Je nach Modul kommt es nicht mehr zurück aus dem Sleep!
  531. }
  532. if (myFolder->mode == 2 || myFolder->mode == 8) {
  533. if (currentTrack != numTracksInFolder) {
  534. currentTrack = currentTrack + 1;
  535. mp3.playFolderTrack(myFolder->folder, currentTrack);
  536. Serial.print(F("Albummodus ist aktiv -> nächster Track: "));
  537. Serial.print(currentTrack);
  538. } else
  539. // mp3.sleep(); // Je nach Modul kommt es nicht mehr zurück aus dem Sleep!
  540. setstandbyTimer();
  541. { }
  542. }
  543. if (myFolder->mode == 3 || myFolder->mode == 9) {
  544. if (currentTrack != numTracksInFolder - firstTrack + 1) {
  545. Serial.print(F("Party -> weiter in der Queue "));
  546. currentTrack++;
  547. } else {
  548. Serial.println(F("Ende der Queue -> beginne von vorne"));
  549. currentTrack = 1;
  550. //// Wenn am Ende der Queue neu gemischt werden soll bitte die Zeilen wieder aktivieren
  551. // Serial.println(F("Ende der Queue -> mische neu"));
  552. // shuffleQueue();
  553. }
  554. Serial.println(queue[currentTrack - 1]);
  555. mp3.playFolderTrack(myFolder->folder, queue[currentTrack - 1]);
  556. }
  557.  
  558. if (myFolder->mode == 4) {
  559. Serial.println(F("Einzel Modus aktiv -> Strom sparen"));
  560. // mp3.sleep(); // Je nach Modul kommt es nicht mehr zurück aus dem Sleep!
  561. setstandbyTimer();
  562. }
  563. if (myFolder->mode == 5) {
  564. if (currentTrack != numTracksInFolder) {
  565. currentTrack = currentTrack + 1;
  566. Serial.print(F("Hörbuch Modus ist aktiv -> nächster Track und "
  567. "Fortschritt speichern"));
  568. Serial.println(currentTrack);
  569. mp3.playFolderTrack(myFolder->folder, currentTrack);
  570. // Fortschritt im EEPROM abspeichern
  571. EEPROM.update(myFolder->folder, currentTrack);
  572. } else {
  573. // mp3.sleep(); // Je nach Modul kommt es nicht mehr zurück aus dem Sleep!
  574. // Fortschritt zurück setzen
  575. EEPROM.update(myFolder->folder, 1);
  576. setstandbyTimer();
  577. }
  578. }
  579. delay(500);
  580. }
  581.  
  582. static void previousTrack() {
  583. Serial.println(F("=== previousTrack()"));
  584. /* if (myCard.mode == 1 || myCard.mode == 7) {
  585. Serial.println(F("Hörspielmodus ist aktiv -> Track von vorne spielen"));
  586. mp3.playFolderTrack(myCard.folder, currentTrack);
  587. }*/
  588. if (myFolder->mode == 2 || myFolder->mode == 8) {
  589. Serial.println(F("Albummodus ist aktiv -> vorheriger Track"));
  590. if (currentTrack != firstTrack) {
  591. currentTrack = currentTrack - 1;
  592. }
  593. mp3.playFolderTrack(myFolder->folder, currentTrack);
  594. }
  595. if (myFolder->mode == 3 || myFolder->mode == 9) {
  596. if (currentTrack != 1) {
  597. Serial.print(F("Party Modus ist aktiv -> zurück in der Qeueue "));
  598. currentTrack--;
  599. }
  600. else
  601. {
  602. Serial.print(F("Anfang der Queue -> springe ans Ende "));
  603. currentTrack = numTracksInFolder;
  604. }
  605. Serial.println(queue[currentTrack - 1]);
  606. mp3.playFolderTrack(myFolder->folder, queue[currentTrack - 1]);
  607. }
  608. if (myFolder->mode == 4) {
  609. Serial.println(F("Einzel Modus aktiv -> Track von vorne spielen"));
  610. mp3.playFolderTrack(myFolder->folder, currentTrack);
  611. }
  612. if (myFolder->mode == 5) {
  613. Serial.println(F("Hörbuch Modus ist aktiv -> vorheriger Track und "
  614. "Fortschritt speichern"));
  615. if (currentTrack != 1) {
  616. currentTrack = currentTrack - 1;
  617. }
  618. mp3.playFolderTrack(myFolder->folder, currentTrack);
  619. // Fortschritt im EEPROM abspeichern
  620. EEPROM.update(myFolder->folder, currentTrack);
  621. }
  622. delay(1000);
  623. }
  624.  
  625. // MFRC522
  626. #define RST_PIN 9 // Konfigurierbar, siehe typisches Pin-Layout oben
  627. #define SS_PIN 10 // Konfigurierbar, siehe typisches Pin-Layout oben
  628. MFRC522 mfrc522(SS_PIN, RST_PIN); // Erstelle MFRC522
  629. MFRC522::MIFARE_Key key;
  630. bool successRead;
  631. byte sector = 1;
  632. byte blockAddr = 4;
  633. byte trailerBlock = 7;
  634. MFRC522::StatusCode status;
  635.  
  636. #define buttonPause A0
  637. #define buttonUp A1
  638. #define buttonDown A2
  639. #define busyPin 4
  640. #define shutdownPin 7
  641. #define openAnalogPin A7
  642.  
  643. #ifdef FIVEBUTTONS
  644. #define buttonFourPin A3
  645. #define buttonFivePin A4
  646. #endif
  647.  
  648. #define LONG_PRESS 1000
  649.  
  650. Button pauseButton(buttonPause);
  651. Button upButton(buttonUp);
  652. Button downButton(buttonDown);
  653. #ifdef FIVEBUTTONS
  654. Button buttonFour(buttonFourPin);
  655. Button buttonFive(buttonFivePin);
  656. #endif
  657. bool ignorePauseButton = false;
  658. bool ignoreUpButton = false;
  659. bool ignoreDownButton = false;
  660. #ifdef FIVEBUTTONS
  661. bool ignoreButtonFour = false;
  662. bool ignoreButtonFive = false;
  663. #endif
  664.  
  665. /// Funktionen für den Standby Timer (z.B. über Pololu-Switch oder Mosfet)
  666.  
  667. void setstandbyTimer() {
  668. Serial.println(F("=== setstandbyTimer()"));
  669. if (mySettings.standbyTimer != 0)
  670. sleepAtMillis = millis() + (mySettings.standbyTimer * 60 * 1000);
  671. else
  672. sleepAtMillis = 0;
  673. Serial.println(sleepAtMillis);
  674. }
  675.  
  676. void disablestandbyTimer() {
  677. Serial.println(F("=== disablestandby()"));
  678. sleepAtMillis = 0;
  679. }
  680.  
  681. void checkStandbyAtMillis() {
  682. if (sleepAtMillis != 0 && millis() > sleepAtMillis) {
  683. Serial.println(F("=== power off!"));
  684. // In den Schlafmodus übergehen
  685. digitalWrite(shutdownPin, HIGH);
  686. delay(500);
  687.  
  688. // http://discourse.voss.earth/t/intenso-s10000-powerbank-automatische-abschaltung-software-only/805
  689. // Abschaltung auf 27mA (Powerbank schaltet sich nach 30-60s ab)
  690. mfrc522.PCD_AntennaOff();
  691. mfrc522.PCD_SoftPowerDown();
  692. mp3.sleep();
  693.  
  694. set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  695. cli(); // Unterbrechungen sperren
  696. sleep_mode();
  697. }
  698. }
  699.  
  700. bool isPlaying() {
  701. return !digitalRead(busyPin);
  702. }
  703.  
  704. void waitForTrackToFinish() {
  705. long currentTime = millis();
  706. #define TIMEOUT 1000
  707. do {
  708. mp3.loop();
  709. } while (!isPlaying() && millis() < currentTime + TIMEOUT);
  710. delay(1000);
  711. do {
  712. mp3.loop();
  713. } while (isPlaying());
  714. }
  715.  
  716. void setup() {
  717.  
  718. Serial.begin(115200); // Es gibt ein paar Debug Ausgaben über die serielle Schnittstelle
  719.  
  720. // Wert für randomSeed() erzeugen durch das mehrfache Sammeln von rauschenden LSBs eines offenen Analogeingangs
  721. uint32_t ADC_LSB;
  722. uint32_t ADCSeed;
  723. for (uint8_t i = 0; i < 128; i++) {
  724. ADC_LSB = analogRead(openAnalogPin) & 0x1;
  725. ADCSeed ^= ADC_LSB << (i % 32);
  726. }
  727. randomSeed(ADCSeed); // Zufallsgenerator initialisieren
  728.  
  729. // Dieser Hinweis darf nicht entfernt werden
  730. Serial.println(F("\n _____ _____ _____ _____ _____"));
  731. Serial.println(F("|_ _|___ ___| | | | | | |"));
  732. Serial.println(F(" | | | . | | | |- -| | | | | |"));
  733. Serial.println(F(" |_| |___|_|_|_____|_____|_|___|_____|\n"));
  734. Serial.println(F("TonUINO Version 2.1"));
  735. Serial.println(F("created by Thorsten Voß and licensed under GNU/GPL."));
  736. Serial.println(F("Information and contribution at https://tonuino.de.\n"));
  737.  
  738. // Busy Pin
  739. pinMode(busyPin, INPUT);
  740.  
  741. // Einstellungen aus EEPROM laden
  742. loadSettingsFromFlash();
  743.  
  744. // Aktiviere Standby-Timer
  745. setstandbyTimer();
  746.  
  747. // DFPlayer Mini initialisieren
  748. mp3.begin();
  749. // Zwei Sekunden warten bis der DFPlayer Mini initialisiert ist
  750. delay(2000);
  751. volume = mySettings.initVolume;
  752. mp3.setVolume(volume);
  753. mp3.setEq(mySettings.eq - 1);
  754. // Fix für das Problem mit dem Timeout (ist jetzt in Upstream daher nicht mehr nötig!)
  755. //mySoftwareSerial.setTimeout(10000);
  756.  
  757. // NFC Leser initialisieren
  758. SPI.begin(); // Init SPI bus
  759. mfrc522.PCD_Init(); // Init MFRC522
  760. mfrc522
  761. .PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader
  762. for (byte i = 0; i < 6; i++) {
  763. key.keyByte[i] = 0xFF;
  764. }
  765.  
  766. pinMode(buttonPause, INPUT_PULLUP);
  767. pinMode(buttonUp, INPUT_PULLUP);
  768. pinMode(buttonDown, INPUT_PULLUP);
  769. #ifdef FIVEBUTTONS
  770. pinMode(buttonFourPin, INPUT_PULLUP);
  771. pinMode(buttonFivePin, INPUT_PULLUP);
  772. #endif
  773. pinMode(shutdownPin, OUTPUT);
  774. digitalWrite(shutdownPin, LOW);
  775.  
  776.  
  777. // Reset --- Alle drei Knöpfe beim Starten gedrückt halten -> alle Einstellungen werden gelöscht!
  778. if (digitalRead(buttonPause) == LOW && digitalRead(buttonUp) == LOW &&
  779. digitalRead(buttonDown) == LOW) {
  780. Serial.println(F("Reset -> EEPROM wird gelöscht"));
  781. for (int i = 0; i < EEPROM.length(); i++) {
  782. EEPROM.update(i, 0);
  783. }
  784. loadSettingsFromFlash();
  785. }
  786.  
  787.  
  788. // Startverknüpfung "beim Start" - z.B. Willkommens-Sound
  789. playShortCut(3);
  790. }
  791.  
  792. void readButtons() {
  793. pauseButton.read();
  794. upButton.read();
  795. downButton.read();
  796. #ifdef FIVEBUTTONS
  797. buttonFour.read();
  798. buttonFive.read();
  799. #endif
  800. }
  801.  
  802. void volumeUpButton() {
  803. if (activeModifier != NULL)
  804. if (activeModifier->handleVolumeUp() == true)
  805. return;
  806.  
  807. Serial.println(F("=== volumeUp()"));
  808. if (volume < mySettings.maxVolume) {
  809. mp3.increaseVolume();
  810. volume++;
  811. }
  812. Serial.println(volume);
  813. }
  814.  
  815. void volumeDownButton() {
  816. if (activeModifier != NULL)
  817. if (activeModifier->handleVolumeDown() == true)
  818. return;
  819.  
  820. Serial.println(F("=== volumeDown()"));
  821. if (volume > mySettings.minVolume) {
  822. mp3.decreaseVolume();
  823. volume--;
  824. }
  825. Serial.println(volume);
  826. }
  827.  
  828. void nextButton() {
  829. if (activeModifier != NULL)
  830. if (activeModifier->handleNextButton() == true)
  831. return;
  832.  
  833. nextTrack(random(65536));
  834. delay(1000);
  835. }
  836.  
  837. void previousButton() {
  838. if (activeModifier != NULL)
  839. if (activeModifier->handlePreviousButton() == true)
  840. return;
  841.  
  842. previousTrack();
  843. delay(1000);
  844. }
  845.  
  846. void playFolder() {
  847. Serial.println(F("== playFolder()")) ;
  848. disablestandbyTimer();
  849. knownCard = true;
  850. _lastTrackFinished = 0;
  851. numTracksInFolder = mp3.getFolderTrackCount(myFolder->folder);
  852. firstTrack = 1;
  853. Serial.print(numTracksInFolder);
  854. Serial.print(F(" Dateien in Ordner "));
  855. Serial.println(myFolder->folder);
  856.  
  857. // Hörspielmodus: eine zufällige Datei aus dem Ordner
  858. if (myFolder->mode == 1) {
  859. Serial.println(F("Hörspielmodus -> zufälligen Track wiedergeben"));
  860. currentTrack = random(1, numTracksInFolder + 1);
  861. Serial.println(currentTrack);
  862. mp3.playFolderTrack(myFolder->folder, currentTrack);
  863. }
  864. // Album Modus: kompletten Ordner spielen
  865. if (myFolder->mode == 2) {
  866. Serial.println(F("Album Modus -> kompletten Ordner wiedergeben"));
  867. currentTrack = 1;
  868. mp3.playFolderTrack(myFolder->folder, currentTrack);
  869. }
  870. // Party Modus: Ordner in zufälliger Reihenfolge
  871. if (myFolder->mode == 3) {
  872. Serial.println(
  873. F("Party Modus -> Ordner in zufälliger Reihenfolge wiedergeben"));
  874. shuffleQueue();
  875. currentTrack = 1;
  876. mp3.playFolderTrack(myFolder->folder, queue[currentTrack - 1]);
  877. }
  878. // Einzel Modus: eine Datei aus dem Ordner abspielen
  879. if (myFolder->mode == 4) {
  880. Serial.println(
  881. F("Einzel Modus -> eine Datei aus dem Odrdner abspielen"));
  882. currentTrack = myFolder->special;
  883. mp3.playFolderTrack(myFolder->folder, currentTrack);
  884. }
  885. // Hörbuch Modus: kompletten Ordner spielen und Fortschritt merken
  886. if (myFolder->mode == 5) {
  887. Serial.println(F("Hörbuch Modus -> kompletten Ordner spielen und "
  888. "Fortschritt merken"));
  889. currentTrack = EEPROM.read(myFolder->folder);
  890. if (currentTrack == 0 || currentTrack > numTracksInFolder) {
  891. currentTrack = 1;
  892. }
  893. mp3.playFolderTrack(myFolder->folder, currentTrack);
  894. }
  895. // Spezialmodus Von-Bin: Hörspiel: eine zufällige Datei aus dem Ordner
  896. if (myFolder->mode == 7) {
  897. Serial.println(F("Spezialmodus Von-Bin: Hörspiel -> zufälligen Track wiedergeben"));
  898. Serial.print(myFolder->special);
  899. Serial.print(F(" bis "));
  900. Serial.println(myFolder->special2);
  901. numTracksInFolder = myFolder->special2;
  902. currentTrack = random(myFolder->special, numTracksInFolder + 1);
  903. Serial.println(currentTrack);
  904. mp3.playFolderTrack(myFolder->folder, currentTrack);
  905. }
  906.  
  907. // Spezialmodus Von-Bis: Album: alle Dateien zwischen Start und Ende spielen
  908. if (myFolder->mode == 8) {
  909. Serial.println(F("Spezialmodus Von-Bis: Album: alle Dateien zwischen Start- und Enddatei spielen"));
  910. Serial.print(myFolder->special);
  911. Serial.print(F(" bis "));
  912. Serial.println(myFolder->special2);
  913. numTracksInFolder = myFolder->special2;
  914. currentTrack = myFolder->special;
  915. mp3.playFolderTrack(myFolder->folder, currentTrack);
  916. }
  917.  
  918. // Spezialmodus Von-Bis: Party Ordner in zufälliger Reihenfolge
  919. if (myFolder->mode == 9) {
  920. Serial.println(
  921. F("Spezialmodus Von-Bis: Party -> Ordner in zufälliger Reihenfolge wiedergeben"));
  922. firstTrack = myFolder->special;
  923. numTracksInFolder = myFolder->special2;
  924. shuffleQueue();
  925. currentTrack = 1;
  926. mp3.playFolderTrack(myFolder->folder, queue[currentTrack - 1]);
  927. }
  928. }
  929.  
  930. void playShortCut(uint8_t shortCut) {
  931. Serial.println(F("=== playShortCut()"));
  932. Serial.println(shortCut);
  933. if (mySettings.shortCuts[shortCut].folder != 0) {
  934. myFolder = &mySettings.shortCuts[shortCut];
  935. playFolder();
  936. disablestandbyTimer();
  937. delay(1000);
  938. }
  939. else
  940. Serial.println(F("Shortcut not configured!"));
  941. }
  942.  
  943. static bool hasCard = false;
  944.  
  945. static byte lastCardUid[4];
  946. static byte retries;
  947. static bool lastCardWasUL;
  948.  
  949.  
  950. const byte PCS_NO_CHANGE = 0; // Keine Änderung seit dem letzten pollCard()-Aufruf festgestellt
  951. const byte PCS_NEW_CARD = 1; // Karte mit neuer UID erkannt (Hatte vorher keine Karte oder andere Karte)
  952. const byte PCS_CARD_GONE = 2; // Karte ist nicht mehr erreichbar
  953. const byte PCS_CARD_IS_BACK = 3; // Karte war weg und ist jetzt wieder da
  954.  
  955.  
  956. byte pollCard()
  957. {
  958. const byte maxRetries = 2;
  959.  
  960. if (!hasCard)
  961. {
  962. if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial() && readCard(&myCard))
  963. {
  964. bool bSameUID = !memcmp(lastCardUid, mfrc522.uid.uidByte, 4);
  965. Serial.print(F("IsSameAsLastUID="));
  966. Serial.println(bSameUID);
  967. // store info about current card
  968. memcpy(lastCardUid, mfrc522.uid.uidByte, 4);
  969. lastCardWasUL = mfrc522.PICC_GetType(mfrc522.uid.sak) == MFRC522::PICC_TYPE_MIFARE_UL;
  970.  
  971. retries = maxRetries;
  972. hasCard = true;
  973. return bSameUID ? PCS_CARD_IS_BACK : PCS_NEW_CARD;
  974. }
  975. return PCS_NO_CHANGE;
  976. }
  977. else // hasCard
  978. {
  979. // Einen Dummy-Lesebefehl ausführen, nur um zu sehen, ob die Karte in Reichweite ist
  980. byte buffer[18];
  981. byte size = sizeof(buffer);
  982.  
  983. if (mfrc522.MIFARE_Read(lastCardWasUL ? 8 : blockAddr, buffer, &size) != MFRC522::STATUS_OK)
  984. {
  985. if (retries > 0)
  986. {
  987. retries--;
  988. }
  989. else
  990. {
  991. Serial.println(F("card gone"));
  992. mfrc522.PICC_HaltA();
  993. mfrc522.PCD_StopCrypto1();
  994. hasCard = false;
  995. return PCS_CARD_GONE;
  996. }
  997. }
  998. else
  999. {
  1000. retries = maxRetries;
  1001. }
  1002. }
  1003. return PCS_NO_CHANGE;
  1004. }
  1005.  
  1006. void handleCardReader()
  1007. {
  1008. // Frage Karte nur alle 100ms
  1009. static uint8_t lastCardPoll = 0;
  1010. uint8_t now = millis();
  1011.  
  1012. if (static_cast<uint8_t>(now - lastCardPoll) > 100)
  1013. {
  1014. lastCardPoll = now;
  1015. switch (pollCard())
  1016. {
  1017. case PCS_NEW_CARD:
  1018. onNewCard();
  1019. break;
  1020.  
  1021. case PCS_CARD_GONE:
  1022. mp3.pause();
  1023. setstandbyTimer();
  1024. break;
  1025.  
  1026. case PCS_CARD_IS_BACK:
  1027. mp3.start();
  1028. disablestandbyTimer();
  1029. break;
  1030. }
  1031. }
  1032. }
  1033.  
  1034. void loop() {
  1035. do {
  1036. checkStandbyAtMillis();
  1037. mp3.loop();
  1038.  
  1039. // Modifier : WIP!
  1040. if (activeModifier != NULL) {
  1041. activeModifier->loop();
  1042. }
  1043.  
  1044. // Buttons werden nun über JS_Button gehandelt, dadurch kann jede Taste doppelt belegt werden
  1045. readButtons();
  1046.  
  1047. // Admin-Menü
  1048. if ((pauseButton.pressedFor(LONG_PRESS) || upButton.pressedFor(LONG_PRESS) || downButton.pressedFor(LONG_PRESS)) && pauseButton.isPressed() && upButton.isPressed() && downButton.isPressed()) {
  1049. mp3.pause();
  1050. do {
  1051. readButtons();
  1052. } while (pauseButton.isPressed() || upButton.isPressed() || downButton.isPressed());
  1053. readButtons();
  1054. adminMenu();
  1055. break;
  1056. }
  1057.  
  1058. if (pauseButton.wasReleased()) {
  1059. if (activeModifier != NULL)
  1060. if (activeModifier->handlePause() == true)
  1061. return;
  1062. if (ignorePauseButton == false)
  1063. if (isPlaying()) {
  1064. mp3.pause();
  1065. setstandbyTimer();
  1066. }
  1067. else if (knownCard) {
  1068. mp3.start();
  1069. disablestandbyTimer();
  1070. }
  1071. ignorePauseButton = false;
  1072. } else if (pauseButton.pressedFor(LONG_PRESS) &&
  1073. ignorePauseButton == false) {
  1074. if (activeModifier != NULL)
  1075. if (activeModifier->handlePause() == true)
  1076. return;
  1077. if (isPlaying()) {
  1078. uint8_t advertTrack;
  1079. if (myFolder->mode == 3 || myFolder->mode == 9) {
  1080. advertTrack = (queue[currentTrack - 1]);
  1081. }
  1082. else {
  1083. advertTrack = currentTrack;
  1084. }
  1085. // Spezialmodus Von-Bis für Album und Party gibt die Dateinummer relativ zur Startposition wieder
  1086. if (myFolder->mode == 8 || myFolder->mode == 9) {
  1087. advertTrack = advertTrack - myFolder->special + 1;
  1088. }
  1089. mp3.playAdvertisement(advertTrack);
  1090. }
  1091. else {
  1092. playShortCut(0);
  1093. }
  1094. ignorePauseButton = true;
  1095. }
  1096.  
  1097. if (upButton.pressedFor(LONG_PRESS)) {
  1098. #ifndef FIVEBUTTONS
  1099. if (isPlaying()) {
  1100. if (!mySettings.invertVolumeButtons) {
  1101. volumeUpButton();
  1102. }
  1103. else {
  1104. nextButton();
  1105. }
  1106. }
  1107. else {
  1108. playShortCut(1);
  1109. }
  1110. ignoreUpButton = true;
  1111. #endif
  1112. } else if (upButton.wasReleased()) {
  1113. if (!ignoreUpButton)
  1114. if (!mySettings.invertVolumeButtons) {
  1115. nextButton();
  1116. }
  1117. else {
  1118. volumeUpButton();
  1119. }
  1120. ignoreUpButton = false;
  1121. }
  1122.  
  1123. if (downButton.pressedFor(LONG_PRESS)) {
  1124. #ifndef FIVEBUTTONS
  1125. if (isPlaying()) {
  1126. if (!mySettings.invertVolumeButtons) {
  1127. volumeDownButton();
  1128. }
  1129. else {
  1130. previousButton();
  1131. }
  1132. }
  1133. else {
  1134. playShortCut(2);
  1135. }
  1136. ignoreDownButton = true;
  1137. #endif
  1138. } else if (downButton.wasReleased()) {
  1139. if (!ignoreDownButton) {
  1140. if (!mySettings.invertVolumeButtons) {
  1141. previousButton();
  1142. }
  1143. else {
  1144. volumeDownButton();
  1145. }
  1146. }
  1147. ignoreDownButton = false;
  1148. }
  1149. #ifdef FIVEBUTTONS
  1150. if (buttonFour.wasReleased()) {
  1151. if (isPlaying()) {
  1152. if (!mySettings.invertVolumeButtons) {
  1153. volumeUpButton();
  1154. }
  1155. else {
  1156. nextButton();
  1157. }
  1158. }
  1159. else {
  1160. playShortCut(1);
  1161. }
  1162. }
  1163. if (buttonFive.wasReleased()) {
  1164. if (isPlaying()) {
  1165. if (!mySettings.invertVolumeButtons) {
  1166. volumeDownButton();
  1167. }
  1168. else {
  1169. previousButton();
  1170. }
  1171. }
  1172. else {
  1173. playShortCut(2);
  1174. }
  1175. }
  1176. #endif
  1177. // Ende der Buttons
  1178.  
  1179. handleCardReader();
  1180. }
  1181.  
  1182. void onNewCard()
  1183. {
  1184. // RFID Karte wurde aufgelegt
  1185. randomSeed(millis() + random(1000));
  1186. if (myCard.cookie == 322417479 && myFolder->folder != 0 && myFolder->mode != 0) {
  1187. playFolder();
  1188. }
  1189. else {
  1190. // Neue Karte konfigurieren
  1191. knownCard = false;
  1192. setupCard();
  1193. }
  1194. }
  1195.  
  1196. void adminMenu(bool fromCard = false) {
  1197. disablestandbyTimer();
  1198. mp3.pause();
  1199. Serial.println(F("=== adminMenu()"));
  1200. knownCard = false;
  1201. if (fromCard == false) {
  1202. // Das Admin-Menü wurde gesperrt - Es kann weiterhin über die Admin-Karte abgerufen werden.
  1203. if (mySettings.adminMenuLocked == 1) {
  1204. return;
  1205. }
  1206. // Pin Prüfung
  1207. else if (mySettings.adminMenuLocked == 2) {
  1208. uint8_t pin[4];
  1209. mp3.playMp3FolderTrack(991);
  1210. if (askCode(pin) == true) {
  1211. if (checkTwo(pin, mySettings.adminMenuPin) == false) {
  1212. return;
  1213. }
  1214. } else {
  1215. return;
  1216. }
  1217. }
  1218. // Übereinstimmung prüfen
  1219. else if (mySettings.adminMenuLocked == 3) {
  1220. uint8_t a = random(10, 20);
  1221. uint8_t b = random(1, 10);
  1222. uint8_t c;
  1223. mp3.playMp3FolderTrack(992);
  1224. waitForTrackToFinish();
  1225. mp3.playMp3FolderTrack(a);
  1226.  
  1227. if (random(1, 3) == 2) {
  1228. // a + b
  1229. c = a + b;
  1230. waitForTrackToFinish();
  1231. mp3.playMp3FolderTrack(993);
  1232. } else {
  1233. // a - b
  1234. b = random(1, a);
  1235. c = a - b;
  1236. waitForTrackToFinish();
  1237. mp3.playMp3FolderTrack(994);
  1238. }
  1239. waitForTrackToFinish();
  1240. mp3.playMp3FolderTrack(b);
  1241. Serial.println(c);
  1242. uint8_t temp = voiceMenu(255, 0, 0, false);
  1243. if (temp != c) {
  1244. return;
  1245. }
  1246. }
  1247. }
  1248. int subMenu = voiceMenu(12, 900, 900, false, false, 0, true);
  1249. if (subMenu == 0)
  1250. return;
  1251. if (subMenu == 1) {
  1252. resetCard();
  1253. mfrc522.PICC_HaltA();
  1254. mfrc522.PCD_StopCrypto1();
  1255. }
  1256. else if (subMenu == 2) {
  1257. // Maximale Lautstärke
  1258. mySettings.maxVolume = voiceMenu(30 - mySettings.minVolume, 930, mySettings.minVolume, false, false, mySettings.maxVolume - mySettings.minVolume) + mySettings.minVolume;
  1259. }
  1260. else if (subMenu == 3) {
  1261. // Minimale Lautstärke
  1262. mySettings.minVolume = voiceMenu(mySettings.maxVolume - 1, 931, 0, false, false, mySettings.minVolume);
  1263. }
  1264. else if (subMenu == 4) {
  1265. // Initial Volume
  1266. mySettings.initVolume = voiceMenu(mySettings.maxVolume - mySettings.minVolume + 1, 932, mySettings.minVolume - 1, false, false, mySettings.initVolume - mySettings.minVolume + 1) + mySettings.minVolume - 1;
  1267. }
  1268. else if (subMenu == 5) {
  1269. // Equalizer
  1270. mySettings.eq = voiceMenu(6, 920, 920, false, false, mySettings.eq);
  1271. mp3.setEq(mySettings.eq - 1);
  1272. }
  1273. else if (subMenu == 6) {
  1274. // Erstelle Modifier Karte
  1275. nfcTagObject tempCard;
  1276. tempCard.cookie = cardCookie;
  1277. tempCard.version = 1;
  1278. tempCard.nfcFolderSettings.folder = 0;
  1279. tempCard.nfcFolderSettings.special = 0;
  1280. tempCard.nfcFolderSettings.special2 = 0;
  1281. tempCard.nfcFolderSettings.mode = voiceMenu(6, 970, 970, false, false, 0, true);
  1282.  
  1283. if (tempCard.nfcFolderSettings.mode != 0) {
  1284. if (tempCard.nfcFolderSettings.mode == 1) {
  1285. switch (voiceMenu(4, 960, 960)) {
  1286. case 1: tempCard.nfcFolderSettings.special = 5; break;
  1287. case 2: tempCard.nfcFolderSettings.special = 15; break;
  1288. case 3: tempCard.nfcFolderSettings.special = 30; break;
  1289. case 4: tempCard.nfcFolderSettings.special = 60; break;
  1290. }
  1291. }
  1292. mp3.playMp3FolderTrack(800);
  1293. do {
  1294. readButtons();
  1295. if (upButton.wasReleased() || downButton.wasReleased()) {
  1296. Serial.println(F("Abgebrochen!"));
  1297. mp3.playMp3FolderTrack(802);
  1298. return;
  1299. }
  1300. } while (!mfrc522.PICC_IsNewCardPresent());
  1301.  
  1302. // RFID Karte wurde aufgelegt
  1303. if (mfrc522.PICC_ReadCardSerial()) {
  1304. Serial.println(F("schreibe Karte..."));
  1305. writeCard(tempCard);
  1306. delay(100);
  1307. mfrc522.PICC_HaltA();
  1308. mfrc522.PCD_StopCrypto1();
  1309. waitForTrackToFinish();
  1310. }
  1311. }
  1312. }
  1313. else if (subMenu == 7) {
  1314. uint8_t shortcut = voiceMenu(4, 940, 940);
  1315. setupFolder(&mySettings.shortCuts[shortcut - 1]);
  1316. mp3.playMp3FolderTrack(400);
  1317. }
  1318. else if (subMenu == 8) {
  1319. switch (voiceMenu(5, 960, 960)) {
  1320. case 1: mySettings.standbyTimer = 5; break;
  1321. case 2: mySettings.standbyTimer = 15; break;
  1322. case 3: mySettings.standbyTimer = 30; break;
  1323. case 4: mySettings.standbyTimer = 60; break;
  1324. case 5: mySettings.standbyTimer = 0; break;
  1325. }
  1326. }
  1327. else if (subMenu == 9) {
  1328. // Erstelle Karten für Ordner
  1329. // Ordner abfragen
  1330. nfcTagObject tempCard;
  1331. tempCard.cookie = cardCookie;
  1332. tempCard.version = 1;
  1333. tempCard.nfcFolderSettings.mode = 4;
  1334. tempCard.nfcFolderSettings.folder = voiceMenu(99, 301, 0, true);
  1335. uint8_t special = voiceMenu(mp3.getFolderTrackCount(tempCard.nfcFolderSettings.folder), 321, 0,
  1336. true, tempCard.nfcFolderSettings.folder);
  1337. uint8_t special2 = voiceMenu(mp3.getFolderTrackCount(tempCard.nfcFolderSettings.folder), 322, 0,
  1338. true, tempCard.nfcFolderSettings.folder, special);
  1339.  
  1340. mp3.playMp3FolderTrack(936);
  1341. waitForTrackToFinish();
  1342. for (uint8_t x = special; x <= special2; x++) {
  1343. mp3.playMp3FolderTrack(x);
  1344. tempCard.nfcFolderSettings.special = x;
  1345. Serial.print(x);
  1346. Serial.println(F(" Karte auflegen"));
  1347. do {
  1348. readButtons();
  1349. if (upButton.wasReleased() || downButton.wasReleased()) {
  1350. Serial.println(F("Abgebrochen!"));
  1351. mp3.playMp3FolderTrack(802);
  1352. return;
  1353. }
  1354. } while (!mfrc522.PICC_IsNewCardPresent());
  1355.  
  1356. // RFID Karte wurde aufgelegt
  1357. if (mfrc522.PICC_ReadCardSerial()) {
  1358. Serial.println(F("schreibe Karte..."));
  1359. writeCard(tempCard);
  1360. delay(100);
  1361. mfrc522.PICC_HaltA();
  1362. mfrc522.PCD_StopCrypto1();
  1363. waitForTrackToFinish();
  1364. }
  1365. }
  1366. }
  1367. else if (subMenu == 10) {
  1368. // Umkehrfunktionen für Auf-/Ab-Tasten
  1369. int temp = voiceMenu(2, 933, 933, false);
  1370. if (temp == 2) {
  1371. mySettings.invertVolumeButtons = true;
  1372. }
  1373. else {
  1374. mySettings.invertVolumeButtons = false;
  1375. }
  1376. }
  1377. else if (subMenu == 11) {
  1378. Serial.println(F("Reset -> EEPROM wird gelöscht"));
  1379. for (int i = 0; i < EEPROM.length(); i++) {
  1380. EEPROM.update(i, 0);
  1381. }
  1382. resetSettings();
  1383. mp3.playMp3FolderTrack(999);
  1384. }
  1385. // Admin-Menü sperren
  1386. else if (subMenu == 12) {
  1387. int temp = voiceMenu(4, 980, 980, false);
  1388. if (temp == 1) {
  1389. mySettings.adminMenuLocked = 0;
  1390. }
  1391. else if (temp == 2) {
  1392. mySettings.adminMenuLocked = 1;
  1393. }
  1394. else if (temp == 3) {
  1395. int8_t pin[4];
  1396. mp3.playMp3FolderTrack(991);
  1397. if (askCode(pin)) {
  1398. memcpy(mySettings.adminMenuPin, pin, 4);
  1399. mySettings.adminMenuLocked = 2;
  1400. }
  1401. }
  1402. else if (temp == 4) {
  1403. mySettings.adminMenuLocked = 3;
  1404. }
  1405.  
  1406. }
  1407. writeSettingsToFlash();
  1408. setstandbyTimer();
  1409. }
  1410.  
  1411. bool askCode(uint8_t *code) {
  1412. uint8_t x = 0;
  1413. while (x < 4) {
  1414. readButtons();
  1415. if (pauseButton.pressedFor(LONG_PRESS))
  1416. break;
  1417. if (pauseButton.wasReleased())
  1418. code[x++] = 1;
  1419. if (upButton.wasReleased())
  1420. code[x++] = 2;
  1421. if (downButton.wasReleased())
  1422. code[x++] = 3;
  1423. }
  1424. return true;
  1425. }
  1426.  
  1427. uint8_t voiceMenu(int numberOfOptions, int startMessage, int messageOffset,
  1428. bool preview = false, int previewFromFolder = 0, int defaultValue = 0, bool exitWithLongPress = false) {
  1429. uint8_t returnValue = defaultValue;
  1430. if (startMessage != 0)
  1431. mp3.playMp3FolderTrack(startMessage);
  1432. Serial.print(F("=== voiceMenu() ("));
  1433. Serial.print(numberOfOptions);
  1434. Serial.println(F(" Options)"));
  1435. do {
  1436. if (Serial.available() > 0) {
  1437. int optionSerial = Serial.parseInt();
  1438. if (optionSerial != 0 && optionSerial <= numberOfOptions)
  1439. return optionSerial;
  1440. }
  1441. readButtons();
  1442. mp3.loop();
  1443. if (pauseButton.pressedFor(LONG_PRESS)) {
  1444. mp3.playMp3FolderTrack(802);
  1445. ignorePauseButton = true;
  1446. return defaultValue;
  1447. }
  1448. if (pauseButton.wasReleased()) {
  1449. if (returnValue != 0) {
  1450. Serial.print(F("=== "));
  1451. Serial.print(returnValue);
  1452. Serial.println(F(" ==="));
  1453. return returnValue;
  1454. }
  1455. delay(1000);
  1456. }
  1457.  
  1458. if (upButton.pressedFor(LONG_PRESS)) {
  1459. returnValue = min(returnValue + 10, numberOfOptions);
  1460. Serial.println(returnValue);
  1461. //mp3.pause();
  1462. mp3.playMp3FolderTrack(messageOffset + returnValue);
  1463. waitForTrackToFinish();
  1464. /*if (preview) {
  1465. if (previewFromFolder == 0)
  1466. mp3.playFolderTrack(returnValue, 1);
  1467. else
  1468. mp3.playFolderTrack(previewFromFolder, returnValue);
  1469. }*/
  1470. ignoreUpButton = true;
  1471. } else if (upButton.wasReleased()) {
  1472. if (!ignoreUpButton) {
  1473. returnValue = min(returnValue + 1, numberOfOptions);
  1474. Serial.println(returnValue);
  1475. //mp3.pause();
  1476. mp3.playMp3FolderTrack(messageOffset + returnValue);
  1477. if (preview) {
  1478. waitForTrackToFinish();
  1479. if (previewFromFolder == 0) {
  1480. mp3.playFolderTrack(returnValue, 1);
  1481. } else {
  1482. mp3.playFolderTrack(previewFromFolder, returnValue);
  1483. }
  1484. delay(1000);
  1485. }
  1486. } else {
  1487. ignoreUpButton = false;
  1488. }
  1489. }
  1490.  
  1491. if (downButton.pressedFor(LONG_PRESS)) {
  1492. returnValue = max(returnValue - 10, 1);
  1493. Serial.println(returnValue);
  1494. //mp3.pause();
  1495. mp3.playMp3FolderTrack(messageOffset + returnValue);
  1496. waitForTrackToFinish();
  1497. /*if (preview) {
  1498. if (previewFromFolder == 0)
  1499. mp3.playFolderTrack(returnValue, 1);
  1500. else
  1501. mp3.playFolderTrack(previewFromFolder, returnValue);
  1502. }*/
  1503. ignoreDownButton = true;
  1504. } else if (downButton.wasReleased()) {
  1505. if (!ignoreDownButton) {
  1506. returnValue = max(returnValue - 1, 1);
  1507. Serial.println(returnValue);
  1508. //mp3.pause();
  1509. mp3.playMp3FolderTrack(messageOffset + returnValue);
  1510. if (preview) {
  1511. waitForTrackToFinish();
  1512. if (previewFromFolder == 0) {
  1513. mp3.playFolderTrack(returnValue, 1);
  1514. }
  1515. else {
  1516. mp3.playFolderTrack(previewFromFolder, returnValue);
  1517. }
  1518. delay(1000);
  1519. }
  1520. } else {
  1521. ignoreDownButton = false;
  1522. }
  1523. }
  1524. } while (true);
  1525. }
  1526.  
  1527. void resetCard() {
  1528. mp3.playMp3FolderTrack(800);
  1529. do {
  1530. pauseButton.read();
  1531. upButton.read();
  1532. downButton.read();
  1533.  
  1534. if (upButton.wasReleased() || downButton.wasReleased()) {
  1535. Serial.print(F("Abgebrochen!"));
  1536. mp3.playMp3FolderTrack(802);
  1537. return;
  1538. }
  1539. } while (!mfrc522.PICC_IsNewCardPresent());
  1540.  
  1541. if (!mfrc522.PICC_ReadCardSerial())
  1542. return;
  1543.  
  1544. Serial.print(F("Karte wird neu konfiguriert!"));
  1545. setupCard();
  1546. }
  1547.  
  1548. bool setupFolder(folderSettings * theFolder) {
  1549. // Ordner abfragen
  1550. theFolder->folder = voiceMenu(99, 301, 0, true, 0, 0, true);
  1551. if (theFolder->folder == 0) return false;
  1552.  
  1553. // Wiedergabemodus abfragen
  1554. theFolder->mode = voiceMenu(9, 310, 310, false, 0, 0, true);
  1555. if (theFolder->mode == 0) return false;
  1556.  
  1557. // // Hörbuchmodus -> Fortschritt im EEPROM auf 1 setzen
  1558. // EEPROM.update(theFolder->folder, 1);
  1559.  
  1560. // Einzelmodus -> Datei abfragen
  1561. if (theFolder->mode == 4)
  1562. theFolder->special = voiceMenu(mp3.getFolderTrackCount(theFolder->folder), 320, 0,
  1563. true, theFolder->folder);
  1564. // Admin Funktionen
  1565. if (theFolder->mode == 6) {
  1566. //theFolder->special = voiceMenu(3, 320, 320);
  1567. theFolder->folder = 0;
  1568. theFolder->mode = 255;
  1569. }
  1570. // Spezialmodus Von-Bis
  1571. if (theFolder->mode == 7 || theFolder->mode == 8 || theFolder->mode == 9) {
  1572. theFolder->special = voiceMenu(mp3.getFolderTrackCount(theFolder->folder), 321, 0,
  1573. true, theFolder->folder);
  1574. theFolder->special2 = voiceMenu(mp3.getFolderTrackCount(theFolder->folder), 322, 0,
  1575. true, theFolder->folder, theFolder->special);
  1576. }
  1577. return true;
  1578. }
  1579.  
  1580. void setupCard() {
  1581. mp3.pause();
  1582. Serial.println(F("=== setupCard()"));
  1583. nfcTagObject newCard;
  1584. if (setupFolder(&newCard.nfcFolderSettings) == true)
  1585. {
  1586. // Karte ist konfiguriert und wird gespeichert
  1587. mp3.pause();
  1588. do {
  1589. } while (isPlaying());
  1590. writeCard(newCard);
  1591. }
  1592. delay(1000);
  1593. }
  1594. bool readCard(nfcTagObject * nfcTag) {
  1595. nfcTagObject tempCard;
  1596. // Es werden einige Details des PICC angezeigt (Dies ist: die Tag/Karte)
  1597. Serial.print(F("Card UID:"));
  1598. dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
  1599. Serial.println();
  1600. Serial.print(F("PICC type: "));
  1601. MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
  1602. Serial.println(mfrc522.PICC_GetTypeName(piccType));
  1603.  
  1604. byte buffer[18];
  1605. byte size = sizeof(buffer);
  1606.  
  1607. // Authentifiziere mit Key A
  1608. if ((piccType == MFRC522::PICC_TYPE_MIFARE_MINI ) ||
  1609. (piccType == MFRC522::PICC_TYPE_MIFARE_1K ) ||
  1610. (piccType == MFRC522::PICC_TYPE_MIFARE_4K ) )
  1611. {
  1612. Serial.println(F("Authenticating Classic using key A..."));
  1613. status = mfrc522.PCD_Authenticate(
  1614. MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  1615. }
  1616. else if (piccType == MFRC522::PICC_TYPE_MIFARE_UL )
  1617. {
  1618. byte pACK[] = {0, 0}; //16 Bit ACK Passwort von der tempCard zurückgegeben
  1619.  
  1620. // Authentifiziere mit Key A
  1621. Serial.println(F("Authenticating MIFARE UL..."));
  1622. status = mfrc522.PCD_NTAG216_AUTH(key.keyByte, pACK);
  1623. }
  1624.  
  1625. if (status != MFRC522::STATUS_OK) {
  1626. Serial.print(F("PCD_Authenticate() failed: "));
  1627. Serial.println(mfrc522.GetStatusCodeName(status));
  1628. return false;
  1629. }
  1630.  
  1631. // Gesamten Sektor zeigen, wie er derzeit ist
  1632. // Serial.println(F("Current data in sector:"));
  1633. // mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
  1634. // Serial.println();
  1635.  
  1636. // Read data from the block
  1637. if ((piccType == MFRC522::PICC_TYPE_MIFARE_MINI ) ||
  1638. (piccType == MFRC522::PICC_TYPE_MIFARE_1K ) ||
  1639. (piccType == MFRC522::PICC_TYPE_MIFARE_4K ) )
  1640. {
  1641. Serial.print(F("Reading data from block "));
  1642. Serial.print(blockAddr);
  1643. Serial.println(F(" ..."));
  1644. status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(blockAddr, buffer, &size);
  1645. if (status != MFRC522::STATUS_OK) {
  1646. Serial.print(F("MIFARE_Read() failed: "));
  1647. Serial.println(mfrc522.GetStatusCodeName(status));
  1648. return false;
  1649. }
  1650. }
  1651. else if (piccType == MFRC522::PICC_TYPE_MIFARE_UL )
  1652. {
  1653. byte buffer2[18];
  1654. byte size2 = sizeof(buffer2);
  1655.  
  1656. status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(8, buffer2, &size2);
  1657. if (status != MFRC522::STATUS_OK) {
  1658. Serial.print(F("MIFARE_Read_1() failed: "));
  1659. Serial.println(mfrc522.GetStatusCodeName(status));
  1660. return false;
  1661. }
  1662. memcpy(buffer, buffer2, 4);
  1663.  
  1664. status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(9, buffer2, &size2);
  1665. if (status != MFRC522::STATUS_OK) {
  1666. Serial.print(F("MIFARE_Read_2() failed: "));
  1667. Serial.println(mfrc522.GetStatusCodeName(status));
  1668. return false;
  1669. }
  1670. memcpy(buffer + 4, buffer2, 4);
  1671.  
  1672. status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(10, buffer2, &size2);
  1673. if (status != MFRC522::STATUS_OK) {
  1674. Serial.print(F("MIFARE_Read_3() failed: "));
  1675. Serial.println(mfrc522.GetStatusCodeName(status));
  1676. return false;
  1677. }
  1678. memcpy(buffer + 8, buffer2, 4);
  1679.  
  1680. status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(11, buffer2, &size2);
  1681. if (status != MFRC522::STATUS_OK) {
  1682. Serial.print(F("MIFARE_Read_4() failed: "));
  1683. Serial.println(mfrc522.GetStatusCodeName(status));
  1684. return false;
  1685. }
  1686. memcpy(buffer + 12, buffer2, 4);
  1687. }
  1688.  
  1689. Serial.print(F("Data on Card "));
  1690. Serial.println(F(":"));
  1691. dump_byte_array(buffer, 16);
  1692. Serial.println();
  1693. Serial.println();
  1694.  
  1695. uint32_t tempCookie;
  1696. tempCookie = (uint32_t)buffer[0] << 24;
  1697. tempCookie += (uint32_t)buffer[1] << 16;
  1698. tempCookie += (uint32_t)buffer[2] << 8;
  1699. tempCookie += (uint32_t)buffer[3];
  1700.  
  1701. tempCard.cookie = tempCookie;
  1702. tempCard.version = buffer[4];
  1703. tempCard.nfcFolderSettings.folder = buffer[5];
  1704. tempCard.nfcFolderSettings.mode = buffer[6];
  1705. tempCard.nfcFolderSettings.special = buffer[7];
  1706. tempCard.nfcFolderSettings.special2 = buffer[8];
  1707.  
  1708. if (tempCard.cookie == cardCookie) {
  1709.  
  1710. if (activeModifier != NULL && tempCard.nfcFolderSettings.folder != 0) {
  1711. if (activeModifier->handleRFID(&tempCard) == true) {
  1712. return false;
  1713. }
  1714. }
  1715.  
  1716. if (tempCard.nfcFolderSettings.folder == 0) {
  1717. if (activeModifier != NULL) {
  1718. if (activeModifier->getActive() == tempCard.nfcFolderSettings.mode) {
  1719. activeModifier = NULL;
  1720. Serial.println(F("modifier removed"));
  1721. if (isPlaying()) {
  1722. mp3.playAdvertisement(261);
  1723. }
  1724. else {
  1725. mp3.start();
  1726. delay(100);
  1727. mp3.playAdvertisement(261);
  1728. delay(100);
  1729. mp3.pause();
  1730. }
  1731. delay(2000);
  1732. return false;
  1733. }
  1734. }
  1735. if (tempCard.nfcFolderSettings.mode != 0 && tempCard.nfcFolderSettings.mode != 255) {
  1736. if (isPlaying()) {
  1737. mp3.playAdvertisement(260);
  1738. }
  1739. else {
  1740. mp3.start();
  1741. delay(100);
  1742. mp3.playAdvertisement(260);
  1743. delay(100);
  1744. mp3.pause();
  1745. }
  1746. }
  1747. switch (tempCard.nfcFolderSettings.mode ) {
  1748. case 0:
  1749. case 255:
  1750. mfrc522.PICC_HaltA(); mfrc522.PCD_StopCrypto1(); adminMenu(true); break;
  1751. case 1: activeModifier = new SleepTimer(tempCard.nfcFolderSettings.special); break;
  1752. case 2: activeModifier = new FreezeDance(); break;
  1753. case 3: activeModifier = new Locked(); break;
  1754. case 4: activeModifier = new ToddlerMode(); break;
  1755. case 5: activeModifier = new KindergardenMode(); break;
  1756. case 6: activeModifier = new RepeatSingleModifier(); break;
  1757.  
  1758. }
  1759. delay(2000);
  1760. return false;
  1761. }
  1762. else {
  1763. memcpy(nfcTag, &tempCard, sizeof(nfcTagObject));
  1764. Serial.println( nfcTag->nfcFolderSettings.folder);
  1765. myFolder = &nfcTag->nfcFolderSettings;
  1766. Serial.println( myFolder->folder);
  1767. }
  1768. return true;
  1769. }
  1770. else {
  1771. memcpy(nfcTag, &tempCard, sizeof(nfcTagObject));
  1772. return true;
  1773. }
  1774. }
  1775.  
  1776.  
  1777. void writeCard(nfcTagObject nfcTag) {
  1778. MFRC522::PICC_Type mifareType;
  1779. byte buffer[16] = {0x13, 0x37, 0xb3, 0x47, // 0x1337 0xb347 Magischer Cookie zu
  1780. // Identifiziere unsere NFC-Tags
  1781. 0x02, // Version 1
  1782. nfcTag.nfcFolderSettings.folder, // Der vom Benutzer ausgewählte Ordner
  1783. nfcTag.nfcFolderSettings.mode, // Der vom Benutzer gewählte Wiedergabemodus
  1784. nfcTag.nfcFolderSettings.special, // Titel oder Funktion für Adminkarten
  1785. nfcTag.nfcFolderSettings.special2,
  1786. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  1787. };
  1788.  
  1789. byte size = sizeof(buffer);
  1790.  
  1791. mifareType = mfrc522.PICC_GetType(mfrc522.uid.sak);
  1792.  
  1793. // Authentifiziere mit Key B
  1794. // Mit der Karte authentifizieren und kartenspezifische Parameter einstellen
  1795. if ((mifareType == MFRC522::PICC_TYPE_MIFARE_MINI ) ||
  1796. (mifareType == MFRC522::PICC_TYPE_MIFARE_1K ) ||
  1797. (mifareType == MFRC522::PICC_TYPE_MIFARE_4K ) )
  1798. {
  1799. Serial.println(F("Authenticating again using key A..."));
  1800. status = mfrc522.PCD_Authenticate(
  1801. MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  1802. }
  1803. else if (mifareType == MFRC522::PICC_TYPE_MIFARE_UL )
  1804. {
  1805. byte pACK[] = {0, 0}; //16 Bit ACK Passwort vom NFC-Tag zurückgegeben
  1806.  
  1807. // Authentifiziere mit Key A
  1808. Serial.println(F("Authenticating UL..."));
  1809. status = mfrc522.PCD_NTAG216_AUTH(key.keyByte, pACK);
  1810. }
  1811.  
  1812. if (status != MFRC522::STATUS_OK) {
  1813. Serial.print(F("PCD_Authenticate() failed: "));
  1814. Serial.println(mfrc522.GetStatusCodeName(status));
  1815. mp3.playMp3FolderTrack(401);
  1816. return;
  1817. }
  1818.  
  1819. // Schreibe Daten in den Block
  1820. Serial.print(F("Writing data into block "));
  1821. Serial.print(blockAddr);
  1822. Serial.println(F(" ..."));
  1823. dump_byte_array(buffer, 16);
  1824. Serial.println();
  1825.  
  1826. if ((mifareType == MFRC522::PICC_TYPE_MIFARE_MINI ) ||
  1827. (mifareType == MFRC522::PICC_TYPE_MIFARE_1K ) ||
  1828. (mifareType == MFRC522::PICC_TYPE_MIFARE_4K ) )
  1829. {
  1830. status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(blockAddr, buffer, 16);
  1831. }
  1832. else if (mifareType == MFRC522::PICC_TYPE_MIFARE_UL )
  1833. {
  1834. byte buffer2[16];
  1835. byte size2 = sizeof(buffer2);
  1836.  
  1837. memset(buffer2, 0, size2);
  1838. memcpy(buffer2, buffer, 4);
  1839. status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(8, buffer2, 16);
  1840.  
  1841. memset(buffer2, 0, size2);
  1842. memcpy(buffer2, buffer + 4, 4);
  1843. status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(9, buffer2, 16);
  1844.  
  1845. memset(buffer2, 0, size2);
  1846. memcpy(buffer2, buffer + 8, 4);
  1847. status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(10, buffer2, 16);
  1848.  
  1849. memset(buffer2, 0, size2);
  1850. memcpy(buffer2, buffer + 12, 4);
  1851. status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(11, buffer2, 16);
  1852. }
  1853.  
  1854. if (status != MFRC522::STATUS_OK) {
  1855. Serial.print(F("MIFARE_Write() failed: "));
  1856. Serial.println(mfrc522.GetStatusCodeName(status));
  1857. mp3.playMp3FolderTrack(401);
  1858. }
  1859. else
  1860. mp3.playMp3FolderTrack(400);
  1861. Serial.println();
  1862. delay(2000);
  1863. }
  1864.  
  1865.  
  1866.  
  1867. /**
  1868. Hilfsroutine, um ein Byte-Array als Hex-Werte nach Serial zu dumpen.
  1869. */
  1870. void dump_byte_array(byte * buffer, byte bufferSize) {
  1871. for (byte i = 0; i < bufferSize; i++) {
  1872. Serial.print(buffer[i] < 0x10 ? " 0" : " ");
  1873. Serial.print(buffer[i], HEX);
  1874. }
  1875. }
  1876.  
  1877. ///////////////////////////////////////// Prüfe Bytes ///////////////////////////////////
  1878. bool checkTwo ( uint8_t a[], uint8_t b[] ) {
  1879. for ( uint8_t k = 0; k < 4; k++ ) { // Wiederhole 4 Mal
  1880. if ( a[k] != b[k] ) { // Wenn a != b dann falsch. Denn: Wenn einer scheitert, dann scheitern alle
  1881. return false;
  1882. }
  1883. }
  1884. return true;
  1885. }
RAW Paste Data