From 0c20efd7caa04f9c419b09ff7f79486be5f92871 Mon Sep 17 00:00:00 2001 From: boerge1 Date: Thu, 25 Apr 2024 16:45:06 +0200 Subject: [PATCH] Issue_202: Enhance modifier card SleepTimer to stop only after the track finished --- README.md | 3 +- TonUINO-TNG.ino | 2 +- sd-card/mp3/0938_modifier_sleep_mode.mp3 | Bin 0 -> 13344 bytes src/modifier.cpp | 55 +++++++------ src/modifier.hpp | 32 +++----- src/mp3.hpp | 1 + src/state_machine.cpp | 100 ++++++++++++----------- src/state_machine.hpp | 5 +- src/tonuino.cpp | 4 +- src/tonuino.hpp | 15 ++-- test/src/admin_tests.cpp | 21 ++++- 11 files changed, 126 insertions(+), 112 deletions(-) create mode 100644 sd-card/mp3/0938_modifier_sleep_mode.mp3 diff --git a/README.md b/README.md index f9fbec8..d022f0d 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,8 @@ Die SD Karte (Ordner mp3 und advert) hat sich gegenüber der Version 3.1.6 geän # Change Log -## Version 3.1.7 (14.04.2024) +## Version 3.1.7 (26.04.2024) +- [Issue 202](https://github.com/tonuino/TonUINO-TNG/issues/202): Enhance modifier card SleepTimer to stop only after the track finished - [Issue 197](https://github.com/tonuino/TonUINO-TNG/issues/197): SPECIAL_START_SHORTCUT: pin A6 cannot be read digital on Nano ## Version 3.1.7 (11.04.2024) diff --git a/TonUINO-TNG.ino b/TonUINO-TNG.ino index 385ec31..7b85f85 100644 --- a/TonUINO-TNG.ino +++ b/TonUINO-TNG.ino @@ -35,7 +35,7 @@ void setup() LOG(init_log, s_error, F("TonUINO Version 3.1 - refactored by Boerge1\n")); LOG(init_log, s_error, F("created by Thorsten Voß and licensed under GNU/GPL.")); LOG(init_log, s_error, F("Information and contribution at https://tonuino.de.\n")); - LOG(init_log, s_error, F("V3.1.7 14.04.24\n")); + LOG(init_log, s_error, F("V3.1.7 26.04.24\n")); Tonuino::getTonuino().setup(); } diff --git a/sd-card/mp3/0938_modifier_sleep_mode.mp3 b/sd-card/mp3/0938_modifier_sleep_mode.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..1c489ed91c661e1c491196aebe7712c81e96a96d GIT binary patch literal 13344 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 literal 0 HcmV?d00001 diff --git a/src/modifier.cpp b/src/modifier.cpp index 4175fa3..e69635e 100644 --- a/src/modifier.cpp +++ b/src/modifier.cpp @@ -7,6 +7,9 @@ namespace { +Tonuino &tonuino = Tonuino::getTonuino(); +Mp3 &mp3 = tonuino.getMp3(); + const __FlashStringHelper* str_SleepTimer () { return F("SleepTimer") ; } const __FlashStringHelper* str_FreezeDance () { return F("FreezeDance") ; } const __FlashStringHelper* str_KindergardenMode () { return F("Kita") ; } @@ -16,17 +19,40 @@ const __FlashStringHelper* str_RepeatSingleModifier() { return F("RepeatSingle") void SleepTimer::loop() { if (sleepTimer.isActive() && sleepTimer.isExpired()) { + LOG(modifier_log, s_info, str_SleepTimer(), F(" -> expired")); + if (not stopAfterTrackFinished || stopAfterTrackFinished_active) { + LOG(modifier_log, s_info, str_SleepTimer(), F(" -> SLEEP!")); + if (SM_tonuino::is_in_state()) + SM_tonuino::dispatch(command_e(commandRaw::pause)); + //tonuino.resetActiveModifier(); + } + else { + stopAfterTrackFinished_active = true; + sleepTimer.start(10 * 60000); + } + } +} +bool SleepTimer::handleNext() { + if (stopAfterTrackFinished_active) { LOG(modifier_log, s_info, str_SleepTimer(), F(" -> SLEEP!")); - if (SM_tonuino::is_in_state()) - SM_tonuino::dispatch(command_e(commandRaw::pause)); + mp3.clearFolderQueue(); + stopAfterTrackFinished_active = false; + sleepTimer.stop(); //tonuino.resetActiveModifier(); } + return false; } void SleepTimer::init(uint8_t special /* is minutes*/) { LOG(modifier_log, s_info, str_SleepTimer(), F(" minutes: "), special); + stopAfterTrackFinished_active = false; + if (special > 0x80) { + stopAfterTrackFinished = true; + special -= 0x80; + } else { + stopAfterTrackFinished = false; + } sleepTimer.start(special * 60000); - //playAdvertisement(advertTracks::t_302_sleep); } void FreezeDance::loop() { @@ -88,26 +114,3 @@ bool RepeatSingleModifier::handleNext() { bool RepeatSingleModifier::handlePrevious() { return handleNext(); } - -//bool FeedbackModifier::handleVolumeDown() { -// if (volume > settings.minVolume) { -// playAdvertisement(volume - 1, false); -// } else { -// playAdvertisement(volume, false); -// } -// LOG(modifier_log, s_info, F("FeedbackModifier::handleVolumeDown()!")); -// return false; -//} -//bool FeedbackModifier::handleVolumeUp() { -// if (volume < settings.maxVolume) { -// playAdvertisement(volume + 1, false); -// } else { -// playAdvertisement(volume, false); -// } -// LOG(modifier_log, s_info, F("FeedbackModifier::handleVolumeUp()!")); -// return false; -//} -//bool FeedbackModifier::handleRFID(const folderSettings &/*newCard*/) { -// LOG(modifier_log, s_info, F("FeedbackModifier::handleRFID()")); -// return false; -//} diff --git a/src/modifier.hpp b/src/modifier.hpp index d28faa5..4fcea57 100644 --- a/src/modifier.hpp +++ b/src/modifier.hpp @@ -14,7 +14,7 @@ struct folderSettings; class Modifier { public: - Modifier(Tonuino &tonuino, Mp3 &mp3): tonuino(tonuino), mp3(mp3) {} + Modifier() {} //virtual ~Modifier() {} virtual void loop () {} virtual bool handleNext () { return false; } @@ -26,26 +26,26 @@ class Modifier { virtual void init (uint8_t) {} Modifier& operator=(const Modifier&) = delete; -protected: - Tonuino &tonuino; - Mp3 &mp3; }; class SleepTimer: public Modifier { public: - SleepTimer(Tonuino &tonuino, Mp3 &mp3): Modifier(tonuino, mp3) {} + SleepTimer() {} void loop () final; + bool handleNext () final; pmode_t getActive () final { return pmode_t::sleep_timer; } void init(uint8_t) final; private: Timer sleepTimer{}; + bool stopAfterTrackFinished{}; + bool stopAfterTrackFinished_active{}; }; class FreezeDance: public Modifier { public: - FreezeDance(Tonuino &tonuino, Mp3 &mp3): Modifier(tonuino, mp3) {} + FreezeDance() {} void loop () final; pmode_t getActive () final { return pmode_t::freeze_dance; } @@ -61,7 +61,7 @@ class FreezeDance: public Modifier { class Locked: public Modifier { public: - Locked(Tonuino &tonuino, Mp3 &mp3): Modifier(tonuino, mp3) {} + Locked() {} bool handleButton(command) final { LOG(modifier_log, s_debug, F("Locked::Button -> LOCKED!")) ; return true; } bool handleRFID(const folderSettings&) final { LOG(modifier_log, s_debug, F("Locked::RFID -> LOCKED!")) ; return true; } @@ -71,7 +71,7 @@ class Locked: public Modifier { class ToddlerMode: public Modifier { public: - ToddlerMode(Tonuino &tonuino, Mp3 &mp3): Modifier(tonuino, mp3) {} + ToddlerMode() {} bool handleButton(command) final { LOG(modifier_log, s_debug, F("ToddlerMode::Button -> LOCKED!")); return true; } pmode_t getActive() final { return pmode_t::toddler; } @@ -79,7 +79,7 @@ class ToddlerMode: public Modifier { class KindergardenMode: public Modifier { public: - KindergardenMode(Tonuino &tonuino, Mp3 &mp3): Modifier(tonuino, mp3) {} + KindergardenMode() {} bool handleNext ( ) final; bool handleButton(command cmd ) final; bool handleRFID (const folderSettings &newCard) final; @@ -94,22 +94,10 @@ class KindergardenMode: public Modifier { class RepeatSingleModifier: public Modifier { public: - RepeatSingleModifier(Tonuino &tonuino, Mp3 &mp3): Modifier(tonuino, mp3) {} + RepeatSingleModifier() {} bool handleNext () final; bool handlePrevious() final; pmode_t getActive () final { return pmode_t::repeat_single; } }; -// An modifier can also do somethings in addition to the modified action -// by returning false (not handled) at the end -// This simple FeedbackModifier will tell the volume before changing it and -// give some feedback once a RFID card is detected. -//class FeedbackModifier: public Modifier { -//public: -// FeedbackModifier(Tonuino &tonuino, Mp3 &mp3, const Settings &settings): Modifier(tonuino, mp3, settings) {} -// bool handleVolumeDown() final; -// bool handleVolumeUp () final; -// bool handleRFID (const folderSettings &newCard) final; -//}; - #endif /* SRC_MODIFIER_HPP_ */ diff --git a/src/mp3.hpp b/src/mp3.hpp index 1d87b12..13af8ea 100644 --- a/src/mp3.hpp +++ b/src/mp3.hpp @@ -118,6 +118,7 @@ enum class mp3Tracks: uint16_t { t_935_yes = 935, t_936_batch_cards_intro = 936, t_937_memory_game_cards_intro= 937, + t_938_modifier_sleep_mode = 938, t_940_shortcut_into = 940, t_941_pause = 941, t_942_up = 942, diff --git a/src/state_machine.cpp b/src/state_machine.cpp index 17757a4..2fba385 100644 --- a/src/state_machine.cpp +++ b/src/state_machine.cpp @@ -1578,9 +1578,12 @@ void Admin_ModCard::entry() { VoiceMenu::entry(); - mode = pmode_t::none; - current_subState = start_writeCard; - readyToWrite = false; + current_subState = get_mode; + + folder.mode = pmode_t::none; + folder.folder = 0; + folder.special = 0; + folder.special2 = 0; } void Admin_ModCard::react(command_e const &cmd_e) { @@ -1589,65 +1592,68 @@ void Admin_ModCard::react(command_e const &cmd_e) { } const command cmd = commands.getCommand(cmd_e.cmd_raw, state_for_command::admin); - if (not readyToWrite) + if (current_subState != start_writeCard && current_subState != run_writeCard) VoiceMenu::react(cmd); if (isAbort(cmd)) return; - if (readyToWrite) { - switch (current_subState) { - case start_writeCard: - folder.folder = 0; - folder.special = 0; - folder.special2 = 0; - folder.mode = mode; - if (mode == pmode_t::sleep_timer) - switch (currentValue) { - case 1: - folder.special = 5; - break; - case 2: - folder.special = 15; - break; - case 3: - folder.special = 30; - break; - case 4: - folder.special = 60; - break; - } - SM_writeCard::folder = folder; - SM_writeCard::start(); - current_subState = run_writeCard; - break; - case run_writeCard: - if (handleWriteCard(cmd_e)) - return; - break; - default: - break; - } - return; - } - else if (Commands::isSelect(cmd) && (currentValue != 0)) { - if (mode == pmode_t::none) { - mode = static_cast(currentValue); - if (mode != pmode_t::sleep_timer) { + switch (current_subState) { + case get_mode : + if (Commands::isSelect(cmd) && (currentValue != 0)) { + folder.mode = static_cast(currentValue); + if (folder.mode != pmode_t::sleep_timer) { mp3.clearMp3Queue(); - readyToWrite = true; + current_subState = start_writeCard; } else { numberOfOptions = 4; startMessage = mp3Tracks::t_960_timer_intro; messageOffset = mp3Tracks::t_960_timer_intro; VoiceMenu::entry(); + current_subState = get_sleeptime_timer; } } - else { - mp3.clearMp3Queue(); - readyToWrite = true; + break; + case get_sleeptime_timer: + if (Commands::isSelect(cmd) && (currentValue != 0)) { + switch (currentValue) { + case 1: + folder.special = 5; + break; + case 2: + folder.special = 15; + break; + case 3: + folder.special = 30; + break; + case 4: + folder.special = 60; + break; + } + numberOfOptions = 2; + startMessage = mp3Tracks::t_938_modifier_sleep_mode; + messageOffset = mp3Tracks::t_933_switch_volume_intro; + VoiceMenu::entry(); + current_subState = get_sleeptime_mode; + } + break; + case get_sleeptime_mode : + if (Commands::isSelect(cmd) && (currentValue != 0)) { + if (currentValue == 2) + folder.special += 0x80; + current_subState = start_writeCard; } + break; + case start_writeCard : + SM_writeCard::folder = folder; + SM_writeCard::start(); + current_subState = run_writeCard; + break; + case run_writeCard : + if (handleWriteCard(cmd_e)) + return; + break; } } diff --git a/src/state_machine.hpp b/src/state_machine.hpp index cebb09b..fb39231 100644 --- a/src/state_machine.hpp +++ b/src/state_machine.hpp @@ -336,12 +336,13 @@ class Admin_ModCard: public Amin_BaseWriteCard void react(command_e const &) final; private: enum subState: uint8_t { + get_mode, + get_sleeptime_timer, + get_sleeptime_mode, start_writeCard, run_writeCard, }; - pmode_t mode {}; subState current_subState{}; - bool readyToWrite {}; }; class Admin_ShortCut: public Admin_BaseSetting diff --git a/src/tonuino.cpp b/src/tonuino.cpp index 01e2b2e..6175601 100644 --- a/src/tonuino.cpp +++ b/src/tonuino.cpp @@ -264,14 +264,14 @@ void Tonuino::playTrackNumber () { // Leider kann das Modul selbst keine Queue abspielen, daher müssen wir selbst die Queue verwalten void Tonuino::nextTrack(uint8_t tracks, bool fromOnPlayFinished) { LOG(play_log, s_info, F("nextTrack")); - if (activeModifier->handleNext()) - return; if (fromOnPlayFinished && mp3.isPlayingFolder() && (myFolder.mode == pmode_t::hoerbuch || myFolder.mode == pmode_t::hoerbuch_1)) { const uint8_t trackToSave = (mp3.getCurrentTrack() < numTracksInFolder) ? mp3.getCurrentTrack()+1 : 1; settings.writeFolderSettingToFlash(myFolder.folder, trackToSave); if (myFolder.mode == pmode_t::hoerbuch_1) mp3.clearFolderQueue(); } + if (activeModifier->handleNext()) + return; mp3.playNext(tracks, fromOnPlayFinished); if (not fromOnPlayFinished && mp3.isPlayingFolder() && (myFolder.mode == pmode_t::hoerbuch || myFolder.mode == pmode_t::hoerbuch_1)) { settings.writeFolderSettingToFlash(myFolder.folder, mp3.getCurrentTrack()); diff --git a/src/tonuino.hpp b/src/tonuino.hpp index a4874bd..96ef27d 100644 --- a/src/tonuino.hpp +++ b/src/tonuino.hpp @@ -114,14 +114,13 @@ class Tonuino { friend class Base; - Modifier noneModifier {*this, mp3}; - SleepTimer sleepTimer {*this, mp3}; - FreezeDance freezeDance {*this, mp3}; - Locked locked {*this, mp3}; - ToddlerMode toddlerMode {*this, mp3}; - KindergardenMode kindergardenMode {*this, mp3}; - RepeatSingleModifier repeatSingleModifier{*this, mp3}; - //FeedbackModifier feedbackModifier {*this, mp3}; + Modifier noneModifier {}; + SleepTimer sleepTimer {}; + FreezeDance freezeDance {}; + Locked locked {}; + ToddlerMode toddlerMode {}; + KindergardenMode kindergardenMode {}; + RepeatSingleModifier repeatSingleModifier{}; Modifier* activeModifier {&noneModifier}; diff --git a/test/src/admin_tests.cpp b/test/src/admin_tests.cpp index 5f20bf4..a46066a 100644 --- a/test/src/admin_tests.cpp +++ b/test/src/admin_tests.cpp @@ -686,7 +686,8 @@ TEST_F(admin_test_fixture, Admin_ModCard) { pmode_t::repeat_single, }; uint8_t timer_set = 4; - uint8_t timer_expect = 60; + uint8_t mode_set = 2; + uint8_t special_expect = 60 + 0x80; Print::clear_output(); @@ -718,7 +719,21 @@ TEST_F(admin_test_fixture, Admin_ModCard) { } // button select --> select timer button_for_command(command::select, state_for_command::admin); - } + + // select mode + execute_cycle_for_ms(time_check_play); + EXPECT_TRUE(getMp3().is_playing_mp3()); + EXPECT_EQ(getMp3().df_mp3_track, static_cast(mp3Tracks::t_938_modifier_sleep_mode)); + for (uint8_t t = 1; t <= mode_set; ++t) { + // button up --> play mode + button_for_command(command::next, state_for_command::admin); + execute_cycle_for_ms(time_check_play); + EXPECT_TRUE(getMp3().is_playing_mp3()); + EXPECT_EQ(getMp3().df_mp3_track, static_cast(mp3Tracks::t_933_switch_volume_intro) + t); + } + // button select --> select timer + button_for_command(command::select, state_for_command::admin); +} execute_cycle(); // --> start_writeCard execute_cycle(); // --> run_writeCard @@ -726,7 +741,7 @@ TEST_F(admin_test_fixture, Admin_ModCard) { folderSettings card_expected = { 0, mode , 0, 0 }; if (mode == pmode_t::sleep_timer) - card_expected.special = timer_expect; + card_expected.special = special_expect; EXPECT_EQ(card_expected, card_decode());