/* * 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: 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()); 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); if (sServices->nvs().OutputMode() == drivers::NvsStorage::Output::kBluetooth) { ESP_LOGI(kTag, "enabling bluetooth"); sServices->bluetooth().Enable(); } 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