diff options
| author | jacqueline <me@jacqueline.id.au> | 2024-05-02 19:12:26 +1000 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2024-05-02 19:12:26 +1000 |
| commit | 1573a8c4cde1cd9528b422b2dcc598e37ffe94a7 (patch) | |
| tree | d162822b8fd7054f81bace0c7a65ab4d5e6f93ef /src/tangara/system_fsm/booting.cpp | |
| parent | a231fd1c8afedbeb14b0bc77d76bad61db986059 (diff) | |
| download | tangara-fw-1573a8c4cde1cd9528b422b2dcc598e37ffe94a7.tar.gz | |
WIP merge cyclically dependent components into one big component
Diffstat (limited to 'src/tangara/system_fsm/booting.cpp')
| -rw-r--r-- | src/tangara/system_fsm/booting.cpp | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/tangara/system_fsm/booting.cpp b/src/tangara/system_fsm/booting.cpp new file mode 100644 index 00000000..44700cc4 --- /dev/null +++ b/src/tangara/system_fsm/booting.cpp @@ -0,0 +1,140 @@ +/* + * Copyright 2023 jacqueline <me@jacqueline.id.au> + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include "collation.hpp" +#include "haptics.hpp" +#include "spiffs.hpp" +#include "system_fsm.hpp" + +#include <stdint.h> +#include <memory> + +#include "assert.h" +#include "esp_err.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +#include "freertos/projdefs.h" +#include "freertos/timers.h" + +#include "adc.hpp" +#include "audio_fsm.hpp" +#include "battery.hpp" +#include "bluetooth.hpp" +#include "bluetooth_types.hpp" +#include "display_init.hpp" +#include "event_queue.hpp" +#include "gpios.hpp" +#include "i2c.hpp" +#include "nvs.hpp" +#include "samd.hpp" +#include "service_locator.hpp" +#include "spi.hpp" +#include "system_events.hpp" +#include "tag_parser.hpp" +#include "tasks.hpp" +#include "touchwheel.hpp" +#include "track_queue.hpp" +#include "ui_fsm.hpp" + +namespace system_fsm { +namespace states { + +[[maybe_unused]] static const char kTag[] = "BOOT"; + +static auto bt_event_cb(drivers::bluetooth::Event ev) -> void { + events::Ui().Dispatch(BluetoothEvent{.event = ev}); + events::Audio().Dispatch(BluetoothEvent{.event = ev}); +} + +static const TickType_t kInterruptCheckPeriod = pdMS_TO_TICKS(100); + +auto Booting::entry() -> void { + ESP_LOGI(kTag, "beginning tangara boot"); + sServices.reset(new ServiceLocator()); + + ESP_LOGI(kTag, "installing early drivers"); + // NVS is needed first because it contains information about what specific + // hardware configuration we're running on. + sServices->nvs( + std::unique_ptr<drivers::NvsStorage>(drivers::NvsStorage::OpenSync())); + + // HACK: tell the unit that it has an ERM motor (we will likely default to + // LRAs in future, but all the current units in the field use ERMs.) + sServices->nvs().HapticMotorIsErm(true); + + // HACK: fix up the switch polarity on newer dev units + // sServices->nvs().LockPolarity(false); + + // I2C and SPI are both always needed. We can't even power down or show an + // error without these. + ESP_ERROR_CHECK(drivers::init_spi()); + sServices->gpios(std::unique_ptr<drivers::Gpios>( + drivers::Gpios::Create(sServices->nvs().LockPolarity()))); + + ESP_LOGI(kTag, "starting ui"); + if (!ui::UiState::InitBootSplash(sServices->gpios(), sServices->nvs())) { + events::System().Dispatch(FatalError{}); + return; + } + + ESP_LOGI(kTag, "starting bg worker"); + sServices->bg_worker(std::make_unique<tasks::WorkerPool>()); + + ESP_LOGI(kTag, "installing remaining drivers"); + drivers::spiffs_mount(); + sServices->samd(std::unique_ptr<drivers::Samd>(drivers::Samd::Create())); + sServices->touchwheel( + std::unique_ptr<drivers::TouchWheel>{drivers::TouchWheel::Create()}); + sServices->haptics(std::make_unique<drivers::Haptics>( + sServices->nvs().HapticMotorIsErm() + ? std::variant<drivers::ErmMotor, drivers::LraMotor>( + drivers::ErmMotor()) + : drivers::LraMotor())); + + auto adc = drivers::AdcBattery::Create(); + sServices->battery(std::make_unique<battery::Battery>( + sServices->samd(), std::unique_ptr<drivers::AdcBattery>(adc))); + + sServices->track_queue( + std::make_unique<audio::TrackQueue>(sServices->bg_worker())); + sServices->tag_parser(std::make_unique<database::TagParserImpl>()); + sServices->collator(locale::CreateCollator()); + + ESP_LOGI(kTag, "init bluetooth"); + sServices->bluetooth(std::make_unique<drivers::Bluetooth>( + sServices->nvs(), sServices->bg_worker())); + sServices->bluetooth().SetEventHandler(bt_event_cb); + + BootComplete ev{.services = sServices}; + events::Audio().Dispatch(ev); + events::Ui().Dispatch(ev); + events::System().Dispatch(ev); +} + +auto Booting::exit() -> void { + // TODO(jacqueline): Gate this on something. Debug flag? Flashing mode? + sAppConsole = new console::AppConsole(); + sAppConsole->sServices = sServices; + sAppConsole->Launch(); + + TimerHandle_t timer = xTimerCreate("INTERRUPTS", kInterruptCheckPeriod, true, + NULL, check_interrupts_cb); + xTimerStart(timer, portMAX_DELAY); +} + +auto Booting::react(const BootComplete& ev) -> void { + ESP_LOGI(kTag, "bootup completely successfully"); + + if (sServices->gpios().IsLocked()) { + transit<Idle>(); + } else { + transit<Running>(); + } +} + +} // namespace states +} // namespace system_fsm |
