Make idle state more robust + check playback state
This commit is contained in:
@@ -144,6 +144,8 @@ void Playback::exit() {
|
||||
// to drain.
|
||||
vTaskDelay(pdMS_TO_TICKS(250));
|
||||
sOutput->SetInUse(false);
|
||||
|
||||
events::System().Dispatch(PlaybackFinished{});
|
||||
}
|
||||
|
||||
void Playback::react(const QueueUpdate& ev) {
|
||||
|
||||
@@ -25,6 +25,8 @@ struct PlaybackUpdate : tinyfsm::Event {
|
||||
uint32_t seconds_total;
|
||||
};
|
||||
|
||||
struct PlaybackFinished : tinyfsm::Event {};
|
||||
|
||||
struct QueueUpdate : tinyfsm::Event {
|
||||
bool current_changed;
|
||||
};
|
||||
|
||||
+12
-2
@@ -49,12 +49,17 @@ void Idle::exit() {
|
||||
}
|
||||
|
||||
void Idle::react(const KeyLockChanged& ev) {
|
||||
if (!ev.falling) {
|
||||
if (ev.falling) {
|
||||
transit<Running>();
|
||||
}
|
||||
}
|
||||
|
||||
void Idle::react(const internal::IdleTimeout& ev) {
|
||||
if (!IdleCondition()) {
|
||||
// Defensively ensure that we didn't miss an idle-ending event.
|
||||
transit<Running>();
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(kTag, "system shutting down");
|
||||
|
||||
// FIXME: It would be neater to just free a bunch of our pointers, deinit the
|
||||
@@ -79,7 +84,12 @@ void Idle::react(const internal::IdleTimeout& ev) {
|
||||
|
||||
sGpios->Flush();
|
||||
|
||||
sSamd->PowerDown();
|
||||
// Retry shutting down in case of a transient failure with the SAMD. e.g. i2c
|
||||
// timeouts. This guards against a buggy SAMD firmware preventing idle.
|
||||
for (;;) {
|
||||
sSamd->PowerDown();
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace states
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "app_console.hpp"
|
||||
#include "audio_events.hpp"
|
||||
#include "battery.hpp"
|
||||
#include "bluetooth.hpp"
|
||||
#include "database.hpp"
|
||||
@@ -54,9 +55,12 @@ class SystemState : public tinyfsm::Fsm<SystemState> {
|
||||
virtual void react(const StorageMounted&) {}
|
||||
virtual void react(const StorageError&) {}
|
||||
virtual void react(const KeyLockChanged&) {}
|
||||
virtual void react(const audio::PlaybackFinished&) {}
|
||||
virtual void react(const internal::IdleTimeout&) {}
|
||||
|
||||
protected:
|
||||
auto IdleCondition() -> bool;
|
||||
|
||||
static std::shared_ptr<drivers::Gpios> sGpios;
|
||||
static std::shared_ptr<drivers::Samd> sSamd;
|
||||
static std::shared_ptr<drivers::NvsStorage> sNvs;
|
||||
@@ -101,6 +105,8 @@ class Running : public SystemState {
|
||||
|
||||
void react(const KeyLockChanged&) override;
|
||||
void react(const StorageError&) override;
|
||||
void react(const audio::PlaybackFinished&) override;
|
||||
|
||||
using SystemState::react;
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "app_console.hpp"
|
||||
#include "audio_events.hpp"
|
||||
#include "file_gatherer.hpp"
|
||||
#include "freertos/projdefs.h"
|
||||
#include "result.hpp"
|
||||
@@ -68,7 +69,13 @@ void Running::exit() {
|
||||
}
|
||||
|
||||
void Running::react(const KeyLockChanged& ev) {
|
||||
if (!ev.falling && audio::AudioState::is_in_state<audio::states::Standby>()) {
|
||||
if (IdleCondition()) {
|
||||
transit<Idle>();
|
||||
}
|
||||
}
|
||||
|
||||
void Running::react(const audio::PlaybackFinished& ev) {
|
||||
if (IdleCondition()) {
|
||||
transit<Idle>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +105,11 @@ void SystemState::react(const internal::BatteryTimerFired&) {
|
||||
}
|
||||
}
|
||||
|
||||
auto SystemState::IdleCondition() -> bool {
|
||||
return !sGpios->Get(drivers::IGpios::Pin::kKeyLock) &&
|
||||
audio::AudioState::is_in_state<audio::states::Standby>();
|
||||
}
|
||||
|
||||
} // namespace system_fsm
|
||||
|
||||
FSM_INITIAL_STATE(system_fsm::SystemState, system_fsm::states::Booting)
|
||||
|
||||
Reference in New Issue
Block a user