From c399199bfccb5298fe4b0cf566d8e69729596ba4 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Tue, 30 Jan 2024 09:55:31 +1100 Subject: [PATCH] Improve handling of sd card changes during runtime - mount if an sd card is inserted - unmount if it's removed --- src/drivers/storage.cpp | 2 +- src/system_fsm/include/system_events.hpp | 3 + src/system_fsm/include/system_fsm.hpp | 13 +++- src/system_fsm/running.cpp | 76 ++++++++++++------------ src/system_fsm/system_fsm.cpp | 7 +++ 5 files changed, 62 insertions(+), 39 deletions(-) diff --git a/src/drivers/storage.cpp b/src/drivers/storage.cpp index cb1407a6..9cf505f8 100644 --- a/src/drivers/storage.cpp +++ b/src/drivers/storage.cpp @@ -118,7 +118,7 @@ SdStorage::~SdStorage() { sdspi_host_remove_device(this->handle_); sdspi_host_deinit(); - gpio_.WriteSync(IGpios::Pin::kSdPowerEnable, 1); + gpio_.WriteSync(IGpios::Pin::kSdPowerEnable, 0); gpio_.WriteSync(IGpios::Pin::kSdMuxDisable, 1); } diff --git a/src/system_fsm/include/system_events.hpp b/src/system_fsm/include/system_events.hpp index 54e0aa9c..794cf84f 100644 --- a/src/system_fsm/include/system_events.hpp +++ b/src/system_fsm/include/system_events.hpp @@ -49,6 +49,9 @@ struct KeyLockChanged : tinyfsm::Event { struct HasPhonesChanged : tinyfsm::Event { bool has_headphones; }; +struct SdDetectChanged : tinyfsm::Event { + bool has_sd_card; +}; struct ChargingStatusChanged : tinyfsm::Event {}; struct BatteryStateChanged : tinyfsm::Event { diff --git a/src/system_fsm/include/system_fsm.hpp b/src/system_fsm/include/system_fsm.hpp index cb733639..2db1cddc 100644 --- a/src/system_fsm/include/system_fsm.hpp +++ b/src/system_fsm/include/system_fsm.hpp @@ -59,6 +59,7 @@ class SystemState : public tinyfsm::Fsm { virtual void react(const StorageMounted&) {} virtual void react(const StorageError&) {} virtual void react(const KeyLockChanged&) {} + virtual void react(const SdDetectChanged&) {} virtual void react(const audio::PlaybackFinished&) {} virtual void react(const internal::IdleTimeout&) {} @@ -95,12 +96,22 @@ class Running : public SystemState { void exit() override; void react(const KeyLockChanged&) override; - void react(const StorageError&) override; + void react(const SdDetectChanged&) override; void react(const audio::PlaybackFinished&) override; using SystemState::react; + + private: + auto mountStorage() -> bool; + auto unmountStorage() -> void; + + bool storage_mounted_; }; +/** + * State for when the screen is off, controls locked, and music paused. Prelude + * to shutting off power completely. + */ class Idle : public SystemState { public: void entry() override; diff --git a/src/system_fsm/running.cpp b/src/system_fsm/running.cpp index 9c556e0a..9e10f9ec 100644 --- a/src/system_fsm/running.cpp +++ b/src/system_fsm/running.cpp @@ -25,13 +25,40 @@ namespace states { static database::IFileGatherer* sFileGatherer; -/* - * Ensure the storage and database are both available. If either of these fails - * to open, then we assume it's an issue with the underlying SD card. - */ void Running::entry() { + if (mountStorage()) { + events::Ui().Dispatch(StorageMounted{}); + } +} + +void Running::exit() { + unmountStorage(); +} + +void Running::react(const KeyLockChanged& ev) { + if (IdleCondition()) { + transit(); + } +} + +void Running::react(const audio::PlaybackFinished& ev) { + if (IdleCondition()) { + transit(); + } +} + +void Running::react(const SdDetectChanged& ev) { + if (ev.has_sd_card) { + if (!sStorage && mountStorage()) { + events::Ui().Dispatch(StorageMounted{}); + } + } else { + unmountStorage(); + } +} + +auto Running::mountStorage() -> bool { ESP_LOGI(kTag, "mounting sd card"); - vTaskDelay(pdMS_TO_TICKS(250)); auto storage_res = drivers::SdStorage::Create(sServices->gpios()); if (storage_res.has_error()) { ESP_LOGW(kTag, "failed to mount!"); @@ -44,12 +71,9 @@ void Running::entry() { sServices->sd(drivers::SdState::kNotPresent); break; } - - events::System().Dispatch(StorageError{}); - events::Audio().Dispatch(StorageError{}); - events::Ui().Dispatch(StorageError{}); - return; + return false; } + sStorage.reset(storage_res.value()); sServices->sd(drivers::SdState::kMounted); @@ -59,43 +83,21 @@ void Running::entry() { database::Database::Open(*sFileGatherer, sServices->tag_parser(), sServices->collator(), sServices->bg_worker()); if (database_res.has_error()) { - ESP_LOGW(kTag, "failed to open!"); - events::System().Dispatch(StorageError{}); - events::Audio().Dispatch(StorageError{}); - events::Ui().Dispatch(StorageError{}); - return; + unmountStorage(); + return false; } + sServices->database( std::unique_ptr{database_res.value()}); ESP_LOGI(kTag, "storage loaded okay"); - StorageMounted ev{}; - events::System().Dispatch(ev); - events::Audio().Dispatch(ev); - events::Ui().Dispatch(ev); + return true; } -void Running::exit() { +auto Running::unmountStorage() -> void { sServices->database({}); sStorage.reset(); } -void Running::react(const KeyLockChanged& ev) { - if (IdleCondition()) { - transit(); - } -} - -void Running::react(const audio::PlaybackFinished& ev) { - if (IdleCondition()) { - transit(); - } -} - -void Running::react(const StorageError& ev) { - ESP_LOGW(kTag, "error loading storage"); - // TODO. -} - } // namespace states } // namespace system_fsm diff --git a/src/system_fsm/system_fsm.cpp b/src/system_fsm/system_fsm.cpp index 17f09576..df750e80 100644 --- a/src/system_fsm/system_fsm.cpp +++ b/src/system_fsm/system_fsm.cpp @@ -48,11 +48,13 @@ void SystemState::react(const internal::GpioInterrupt&) { auto& gpios = sServices->gpios(); bool prev_key_lock = gpios.IsLocked(); bool prev_has_headphones = !gpios.Get(drivers::Gpios::Pin::kPhoneDetect); + bool prev_has_sd = gpios.Get(drivers::Gpios::Pin::kSdCardDetect); gpios.Read(); bool key_lock = gpios.IsLocked(); bool has_headphones = !gpios.Get(drivers::Gpios::Pin::kPhoneDetect); + bool has_sd = gpios.Get(drivers::Gpios::Pin::kSdCardDetect); if (key_lock != prev_key_lock) { KeyLockChanged ev{.locking = key_lock}; @@ -64,6 +66,11 @@ void SystemState::react(const internal::GpioInterrupt&) { HasPhonesChanged ev{.has_headphones = has_headphones}; events::Audio().Dispatch(ev); } + if (has_sd != prev_has_sd) { + SdDetectChanged ev{.has_sd_card = !has_sd}; + events::System().Dispatch(ev); + events::Ui().Dispatch(ev); + } } void SystemState::react(const internal::SamdInterrupt&) {