diff --git a/src/app_console/app_console.cpp b/src/app_console/app_console.cpp index 7347f130..4b755c67 100644 --- a/src/app_console/app_console.cpp +++ b/src/app_console/app_console.cpp @@ -471,7 +471,7 @@ int CmdSamd(int argc, char** argv) { } else if (cmd == "msc") { bool current = samd.UsbMassStorage(); std::cout << "toggling to: " << !current << std::endl; - samd.UsbMassStorage(!current); + events::System().Dispatch(system_fsm::SamdUsbMscChanged{.en = !current}); } else if (cmd == "off") { std::cout << "bye !!!" << std::endl; vTaskDelay(pdMS_TO_TICKS(5)); diff --git a/src/drivers/storage.cpp b/src/drivers/storage.cpp index 9cf505f8..b3588130 100644 --- a/src/drivers/storage.cpp +++ b/src/drivers/storage.cpp @@ -118,8 +118,8 @@ SdStorage::~SdStorage() { sdspi_host_remove_device(this->handle_); sdspi_host_deinit(); - gpio_.WriteSync(IGpios::Pin::kSdPowerEnable, 0); gpio_.WriteSync(IGpios::Pin::kSdMuxDisable, 1); + gpio_.WriteSync(IGpios::Pin::kSdPowerEnable, 0); } auto SdStorage::GetFs() -> FATFS* { diff --git a/src/system_fsm/include/system_events.hpp b/src/system_fsm/include/system_events.hpp index 794cf84f..a363887e 100644 --- a/src/system_fsm/include/system_events.hpp +++ b/src/system_fsm/include/system_events.hpp @@ -53,6 +53,10 @@ struct SdDetectChanged : tinyfsm::Event { bool has_sd_card; }; +struct SamdUsbMscChanged : tinyfsm::Event { + bool en; +}; + struct ChargingStatusChanged : tinyfsm::Event {}; struct BatteryStateChanged : tinyfsm::Event { battery::Battery::BatteryState new_state; diff --git a/src/system_fsm/include/system_fsm.hpp b/src/system_fsm/include/system_fsm.hpp index 1e340711..5a0ea599 100644 --- a/src/system_fsm/include/system_fsm.hpp +++ b/src/system_fsm/include/system_fsm.hpp @@ -61,6 +61,7 @@ class SystemState : public tinyfsm::Fsm { virtual void react(const StorageError&) {} virtual void react(const KeyLockChanged&) {} virtual void react(const SdDetectChanged&) {} + virtual void react(const SamdUsbMscChanged&) {} virtual void react(const database::event::UpdateFinished&) {} virtual void react(const audio::PlaybackFinished&) {} virtual void react(const internal::IdleTimeout&) {} @@ -101,6 +102,7 @@ class Running : public SystemState { void react(const SdDetectChanged&) override; void react(const audio::PlaybackFinished&) override; void react(const database::event::UpdateFinished&) override; + void react(const SamdUsbMscChanged&) override; using SystemState::react; diff --git a/src/system_fsm/running.cpp b/src/system_fsm/running.cpp index ec448657..60103086 100644 --- a/src/system_fsm/running.cpp +++ b/src/system_fsm/running.cpp @@ -10,6 +10,7 @@ #include "db_events.hpp" #include "file_gatherer.hpp" #include "freertos/projdefs.h" +#include "gpios.hpp" #include "result.hpp" #include "audio_fsm.hpp" @@ -55,6 +56,11 @@ void Running::react(const database::event::UpdateFinished&) { } void Running::react(const SdDetectChanged& ev) { + if (sServices->samd().UsbMassStorage()) { + // We don't currently control the sd card, so don't mess with it. + return; + } + if (ev.has_sd_card) { if (!sStorage && mountStorage()) { events::Ui().Dispatch(StorageMounted{}); @@ -64,6 +70,42 @@ void Running::react(const SdDetectChanged& ev) { } } +void Running::react(const SamdUsbMscChanged& ev) { + if (ev.en) { + // Stop using the sd card, and power it off. + unmountStorage(); + + // Set up the SD card for usage by the samd21. + auto& gpios = sServices->gpios(); + gpios.WriteSync(drivers::IGpios::Pin::kSdPowerEnable, 1); + gpios.WriteSync(drivers::IGpios::Pin::kSdMuxSwitch, + drivers::IGpios::SD_MUX_SAMD); + gpios.WriteSync(drivers::IGpios::Pin::kSdMuxDisable, 0); + + // Off you go! + sServices->samd().UsbMassStorage(true); + } else { + // Make sure the samd knows that its access is going away, and give it time + // to finish up any remaining work. + sServices->samd().UsbMassStorage(false); + vTaskDelay(pdMS_TO_TICKS(250)); + + auto& gpios = sServices->gpios(); + // No more writing, please! + gpios.WriteSync(drivers::IGpios::Pin::kSdMuxDisable, 1); + vTaskDelay(pdMS_TO_TICKS(100)); + + // Reboot the SD card so that it comes up in a consistent state. + // TODO: can we avoid doing this? + gpios.WriteSync(drivers::IGpios::Pin::kSdPowerEnable, 0); + + // Now it's ready for us. + if (mountStorage()) { + events::Ui().Dispatch(StorageMounted{}); + } + } +} + auto Running::mountStorage() -> bool { ESP_LOGI(kTag, "mounting sd card"); auto storage_res = drivers::SdStorage::Create(sServices->gpios());