summaryrefslogtreecommitdiff
path: root/src/tangara/system_fsm
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-05-03 16:40:39 +1000
committerjacqueline <me@jacqueline.id.au>2024-05-03 16:40:39 +1000
commit344a46d0664eb75d232eacea91a4957a25e071f6 (patch)
treee6ee54d9c8060af3d3bb94ec4b79e9d505b270e5 /src/tangara/system_fsm
parent3ceb8025ee4330c177101ed30ec17dfb0002f41e (diff)
downloadtangara-fw-344a46d0664eb75d232eacea91a4957a25e071f6.tar.gz
Respond to sd card mounts and unmounts within lua
Includes no longer blocking the main menu on an sd card being inserted!!
Diffstat (limited to 'src/tangara/system_fsm')
-rw-r--r--src/tangara/system_fsm/running.cpp60
-rw-r--r--src/tangara/system_fsm/system_events.hpp10
-rw-r--r--src/tangara/system_fsm/system_fsm.hpp8
3 files changed, 50 insertions, 28 deletions
diff --git a/src/tangara/system_fsm/running.cpp b/src/tangara/system_fsm/running.cpp
index 82edd018..ac36ec64 100644
--- a/src/tangara/system_fsm/running.cpp
+++ b/src/tangara/system_fsm/running.cpp
@@ -10,6 +10,7 @@
#include "database/db_events.hpp"
#include "database/file_gatherer.hpp"
#include "drivers/gpios.hpp"
+#include "drivers/spi.hpp"
#include "ff.h"
#include "freertos/portmacro.h"
#include "freertos/projdefs.h"
@@ -42,11 +43,7 @@ void Running::entry() {
sUnmountTimer = xTimerCreate("unmount_timeout", kTicksBeforeUnmount, false,
NULL, timer_callback);
}
- // Only mount our storage immediately if we know it's not currently in use
- // by the SAMD.
- if (!sServices->samd().UsbMassStorage()) {
- mountStorage();
- }
+ mountStorage();
}
void Running::exit() {
@@ -80,10 +77,28 @@ void Running::react(const SdDetectChanged& ev) {
if (ev.has_sd_card && !sStorage) {
mountStorage();
}
+
// Don't automatically unmount, since this event seems to occasionally happen
// supriously. FIXME: Why?
- // (It doesn't matter too much; by the time we get this event the SD card has
- // already been disconnected electrically.)
+ // Instead, check whether or not the card has actually gone away.
+ if (sStorage) {
+ FRESULT res;
+ FF_DIR dir;
+ {
+ auto lock = drivers::acquire_spi();
+ res = f_opendir(&dir, "/");
+ }
+
+ if (res != FR_OK) {
+ ESP_LOGW(kTag, "sd card ejected unsafely!");
+ unmountStorage();
+ }
+
+ {
+ auto lock = drivers::acquire_spi();
+ f_closedir(&dir);
+ }
+ }
}
void Running::react(const SamdUsbMscChanged& ev) {
@@ -134,25 +149,37 @@ auto Running::checkIdle() -> void {
}
}
-auto Running::mountStorage() -> bool {
+auto Running::updateSdState(drivers::SdState state) -> void {
+ sServices->sd(state);
+ events::Ui().Dispatch(SdStateChanged{});
+ events::Audio().Dispatch(SdStateChanged{});
+ events::System().Dispatch(SdStateChanged{});
+}
+
+auto Running::mountStorage() -> void {
+ // Only mount our storage if we know it's not currently in use by the SAMD.
+ if (sServices->samd().UsbMassStorage()) {
+ updateSdState(drivers::SdState::kNotMounted);
+ return;
+ }
+
ESP_LOGI(kTag, "mounting sd card");
auto storage_res = drivers::SdStorage::Create(sServices->gpios());
if (storage_res.has_error()) {
ESP_LOGW(kTag, "failed to mount!");
switch (storage_res.error()) {
case drivers::SdStorage::FAILED_TO_MOUNT:
- sServices->sd(drivers::SdState::kNotFormatted);
+ updateSdState(drivers::SdState::kNotFormatted);
break;
case drivers::SdStorage::FAILED_TO_READ:
default:
- sServices->sd(drivers::SdState::kNotPresent);
+ updateSdState(drivers::SdState::kNotPresent);
break;
}
- return false;
+ return;
}
sStorage.reset(storage_res.value());
- sServices->sd(drivers::SdState::kMounted);
ESP_LOGI(kTag, "opening database");
sFileGatherer = new database::FileGathererImpl();
@@ -161,16 +188,14 @@ auto Running::mountStorage() -> bool {
sServices->collator(), sServices->bg_worker());
if (database_res.has_error()) {
unmountStorage();
- return false;
+ return;
}
sServices->database(
std::unique_ptr<database::Database>{database_res.value()});
ESP_LOGI(kTag, "storage loaded okay");
- events::Ui().Dispatch(StorageMounted{});
- events::Audio().Dispatch(StorageMounted{});
- events::System().Dispatch(StorageMounted{});
+ updateSdState(drivers::SdState::kMounted);
// Tell the database to refresh so that we pick up any changes from the newly
// mounted card.
@@ -183,14 +208,13 @@ auto Running::mountStorage() -> bool {
db->updateIndexes();
});
}
-
- return true;
}
auto Running::unmountStorage() -> void {
ESP_LOGW(kTag, "unmounting storage");
sServices->database({});
sStorage.reset();
+ updateSdState(drivers::SdState::kNotMounted);
}
} // namespace states
diff --git a/src/tangara/system_fsm/system_events.hpp b/src/tangara/system_fsm/system_events.hpp
index c174a1da..3452e58e 100644
--- a/src/tangara/system_fsm/system_events.hpp
+++ b/src/tangara/system_fsm/system_events.hpp
@@ -9,11 +9,12 @@
#include <memory>
#include "battery/battery.hpp"
-#include "drivers/bluetooth_types.hpp"
#include "database/database.hpp"
-#include "ff.h"
+#include "drivers/bluetooth_types.hpp"
#include "drivers/haptics.hpp"
#include "drivers/samd.hpp"
+#include "drivers/storage.hpp"
+#include "ff.h"
#include "system_fsm/service_locator.hpp"
#include "tinyfsm.hpp"
@@ -38,10 +39,7 @@ struct FatalError : tinyfsm::Event {};
struct OnIdle : tinyfsm::Event {};
-/*
- * Sent by SysState when the system storage has been successfully mounted.
- */
-struct StorageMounted : tinyfsm::Event {};
+struct SdStateChanged : tinyfsm::Event {};
struct StorageError : tinyfsm::Event {
FRESULT error;
diff --git a/src/tangara/system_fsm/system_fsm.hpp b/src/tangara/system_fsm/system_fsm.hpp
index d69141dd..5c4157cd 100644
--- a/src/tangara/system_fsm/system_fsm.hpp
+++ b/src/tangara/system_fsm/system_fsm.hpp
@@ -15,19 +15,19 @@
#include "audio/audio_events.hpp"
#include "audio/track_queue.hpp"
#include "battery/battery.hpp"
-#include "drivers/bluetooth.hpp"
#include "database/database.hpp"
#include "database/db_events.hpp"
#include "database/tag_parser.hpp"
+#include "drivers/bluetooth.hpp"
#include "drivers/display.hpp"
#include "drivers/gpios.hpp"
#include "drivers/nvs.hpp"
#include "drivers/samd.hpp"
#include "drivers/storage.hpp"
+#include "drivers/touchwheel.hpp"
#include "system_fsm/service_locator.hpp"
#include "system_fsm/system_events.hpp"
#include "tinyfsm.hpp"
-#include "drivers/touchwheel.hpp"
namespace system_fsm {
@@ -55,7 +55,6 @@ class SystemState : public tinyfsm::Fsm<SystemState> {
virtual void react(const DisplayReady&) {}
virtual void react(const BootComplete&) {}
- virtual void react(const StorageMounted&) {}
virtual void react(const StorageError&) {}
virtual void react(const KeyLockChanged&) {}
virtual void react(const SdDetectChanged&) {}
@@ -110,7 +109,8 @@ class Running : public SystemState {
private:
auto checkIdle() -> void;
- auto mountStorage() -> bool;
+ auto updateSdState(drivers::SdState) -> void;
+ auto mountStorage() -> void;
auto unmountStorage() -> void;
bool storage_mounted_;