From 1573a8c4cde1cd9528b422b2dcc598e37ffe94a7 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Thu, 2 May 2024 19:12:26 +1000 Subject: WIP merge cyclically dependent components into one big component --- src/tangara/system_fsm/booting.cpp | 140 +++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 src/tangara/system_fsm/booting.cpp (limited to 'src/tangara/system_fsm/booting.cpp') 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 + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include "collation.hpp" +#include "haptics.hpp" +#include "spiffs.hpp" +#include "system_fsm.hpp" + +#include +#include + +#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::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::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()); + + ESP_LOGI(kTag, "installing remaining drivers"); + drivers::spiffs_mount(); + sServices->samd(std::unique_ptr(drivers::Samd::Create())); + sServices->touchwheel( + std::unique_ptr{drivers::TouchWheel::Create()}); + sServices->haptics(std::make_unique( + sServices->nvs().HapticMotorIsErm() + ? std::variant( + drivers::ErmMotor()) + : drivers::LraMotor())); + + auto adc = drivers::AdcBattery::Create(); + sServices->battery(std::make_unique( + sServices->samd(), std::unique_ptr(adc))); + + sServices->track_queue( + std::make_unique(sServices->bg_worker())); + sServices->tag_parser(std::make_unique()); + sServices->collator(locale::CreateCollator()); + + ESP_LOGI(kTag, "init bluetooth"); + sServices->bluetooth(std::make_unique( + 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(); + } else { + transit(); + } +} + +} // namespace states +} // namespace system_fsm -- cgit v1.2.3