diff --git a/src/drivers/display.cpp b/src/drivers/display.cpp index 026e1346..c16fc148 100644 --- a/src/drivers/display.cpp +++ b/src/drivers/display.cpp @@ -39,9 +39,6 @@ [[maybe_unused]] static const char* kTag = "DISPLAY"; -// TODO(jacqueline): Encode width and height variations in the init data. -static const uint8_t kDisplayHeight = 128; -static const uint8_t kDisplayWidth = 160; static const uint8_t kTransactionQueueSize = 2; static const gpio_num_t kDisplayDr = GPIO_NUM_33; @@ -51,9 +48,11 @@ static const gpio_num_t kDisplayCs = GPIO_NUM_22; /* * The size of each of our two display buffers. This is fundamentally a balance * between performance and memory usage. LVGL docs recommend a buffer 1/10th the - * size of the screen is the best tradeoff + * size of the screen is the best tradeoff. + 8 + * The 160x128 is the nominal size of our standard faceplate's display. */ -static const int kDisplayBufferSize = kDisplayWidth * kDisplayHeight / 10; +static const int kDisplayBufferSize = 160 * 128 / 10; DMA_ATTR static lv_color_t kDisplayBuffer[kDisplayBufferSize]; namespace drivers { @@ -154,10 +153,8 @@ auto Display::Create(IGpios& expander, lv_disp_drv_init(&display->driver_); display->driver_.draw_buf = &display->buffers_; - display->driver_.hor_res = kDisplayWidth; - display->driver_.ver_res = kDisplayHeight; - // display->driver_.sw_rotate = 1; - // display->driver_.rotated = LV_DISP_ROT_270; + display->driver_.hor_res = init_data.width; + display->driver_.ver_res = init_data.height; display->driver_.sw_rotate = 0; display->driver_.rotated = LV_DISP_ROT_NONE; display->driver_.antialiasing = 0; diff --git a/src/drivers/display_init.cpp b/src/drivers/display_init.cpp index 833ea6a4..a69826fa 100644 --- a/src/drivers/display_init.cpp +++ b/src/drivers/display_init.cpp @@ -101,6 +101,8 @@ static const uint8_t kST7735RCommonFooter[]{ // clang-format on const InitialisationData kST7735R = { + .width = 160, + .height = 128, .num_sequences = 3, .sequences = {kST7735RCommonHeader, kST7735RCommonGreen, kST7735RCommonFooter}}; diff --git a/src/drivers/include/display_init.hpp b/src/drivers/include/display_init.hpp index f6c28b54..9bf5b3f5 100644 --- a/src/drivers/include/display_init.hpp +++ b/src/drivers/include/display_init.hpp @@ -6,6 +6,7 @@ #pragma once +#include #include namespace drivers { @@ -14,6 +15,8 @@ namespace displays { extern const uint8_t kDelayBit; struct InitialisationData { + uint16_t width; + uint16_t height; uint8_t num_sequences; const uint8_t* sequences[4]; }; diff --git a/src/drivers/include/nvs.hpp b/src/drivers/include/nvs.hpp index 5bd825e5..f288f8e2 100644 --- a/src/drivers/include/nvs.hpp +++ b/src/drivers/include/nvs.hpp @@ -71,6 +71,11 @@ class NvsStorage { auto LockPolarity() -> bool; auto LockPolarity(bool) -> void; + auto DisplaySize() + -> std::pair, std::optional>; + auto DisplaySize(std::pair, std::optional>) + -> void; + auto PreferredBluetoothDevice() -> std::optional; auto PreferredBluetoothDevice(std::optional) -> void; @@ -120,6 +125,9 @@ class NvsStorage { nvs_handle_t handle_; Setting lock_polarity_; + Setting display_cols_; + Setting display_rows_; + Setting brightness_; Setting sensitivity_; Setting amp_max_vol_; diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp index 875059be..28cb542c 100644 --- a/src/drivers/nvs.cpp +++ b/src/drivers/nvs.cpp @@ -37,6 +37,8 @@ static constexpr char kKeyAmpLeftBias[] = "hp_bias"; static constexpr char kKeyPrimaryInput[] = "in_pri"; static constexpr char kKeyScrollSensitivity[] = "scroll"; static constexpr char kKeyLockPolarity[] = "lockpol"; +static constexpr char kKeyDisplayCols[] = "dispcols"; +static constexpr char kKeyDisplayRows[] = "disprows"; static auto nvs_get_string(nvs_handle_t nvs, const char* key) -> std::optional { @@ -161,6 +163,8 @@ auto NvsStorage::OpenSync() -> NvsStorage* { NvsStorage::NvsStorage(nvs_handle_t handle) : handle_(handle), lock_polarity_(kKeyLockPolarity), + display_cols_(kKeyDisplayCols), + display_rows_(kKeyDisplayRows), brightness_(kKeyBrightness), sensitivity_(kKeyScrollSensitivity), amp_max_vol_(kKeyAmpMaxVolume), @@ -180,6 +184,8 @@ NvsStorage::~NvsStorage() { auto NvsStorage::Read() -> void { std::lock_guard lock{mutex_}; lock_polarity_.read(handle_); + display_cols_.read(handle_); + display_rows_.read(handle_); brightness_.read(handle_); sensitivity_.read(handle_); amp_max_vol_.read(handle_); @@ -194,6 +200,8 @@ auto NvsStorage::Read() -> void { auto NvsStorage::Write() -> bool { std::lock_guard lock{mutex_}; lock_polarity_.write(handle_); + display_cols_.write(handle_); + display_rows_.write(handle_); brightness_.write(handle_); sensitivity_.write(handle_); amp_max_vol_.write(handle_); @@ -231,6 +239,19 @@ auto NvsStorage::LockPolarity(bool p) -> void { lock_polarity_.set(p); } +auto NvsStorage::DisplaySize() + -> std::pair, std::optional> { + std::lock_guard lock{mutex_}; + return std::make_pair(display_cols_.get(), display_rows_.get()); +} + +auto NvsStorage::DisplaySize( + std::pair, std::optional> size) -> void { + std::lock_guard lock{mutex_}; + display_cols_.set(std::move(size.first)); + display_rows_.set(std::move(size.second)); +} + auto NvsStorage::PreferredBluetoothDevice() -> std::optional { std::lock_guard lock{mutex_}; diff --git a/src/system_fsm/booting.cpp b/src/system_fsm/booting.cpp index 41f46df2..14fed92e 100644 --- a/src/system_fsm/booting.cpp +++ b/src/system_fsm/booting.cpp @@ -62,8 +62,12 @@ auto Booting::entry() -> void { ESP_ERROR_CHECK(drivers::init_spi()); sServices->gpios(std::unique_ptr(drivers::Gpios::Create())); + // NVS is needed early so that we can correctly initialise the display. + sServices->nvs( + std::unique_ptr(drivers::NvsStorage::OpenSync())); + ESP_LOGI(kTag, "starting ui"); - if (!ui::UiState::InitBootSplash(sServices->gpios())) { + if (!ui::UiState::InitBootSplash(sServices->gpios(), sServices->nvs())) { events::System().Dispatch(FatalError{}); return; } @@ -74,8 +78,6 @@ auto Booting::entry() -> void { ESP_LOGI(kTag, "installing remaining drivers"); drivers::spiffs_mount(); sServices->samd(std::unique_ptr(drivers::Samd::Create())); - sServices->nvs( - std::unique_ptr(drivers::NvsStorage::OpenSync())); sServices->touchwheel( std::unique_ptr{drivers::TouchWheel::Create()}); sServices->haptics(std::make_unique()); diff --git a/src/ui/include/ui_fsm.hpp b/src/ui/include/ui_fsm.hpp index 07937559..579cc2bb 100644 --- a/src/ui/include/ui_fsm.hpp +++ b/src/ui/include/ui_fsm.hpp @@ -36,7 +36,7 @@ namespace ui { class UiState : public tinyfsm::Fsm { public: - static auto InitBootSplash(drivers::IGpios&) -> bool; + static auto InitBootSplash(drivers::IGpios&, drivers::NvsStorage&) -> bool; virtual ~UiState() {} diff --git a/src/ui/ui_fsm.cpp b/src/ui/ui_fsm.cpp index 1a9f01b4..0ed012a0 100644 --- a/src/ui/ui_fsm.cpp +++ b/src/ui/ui_fsm.cpp @@ -12,6 +12,7 @@ #include "bluetooth_types.hpp" #include "db_events.hpp" +#include "display_init.hpp" #include "freertos/portmacro.h" #include "freertos/projdefs.h" #include "lua.h" @@ -284,10 +285,21 @@ lua::Property UiState::sLockSwitch{false}; lua::Property UiState::sDatabaseUpdating{false}; -auto UiState::InitBootSplash(drivers::IGpios& gpios) -> bool { +auto UiState::InitBootSplash(drivers::IGpios& gpios, drivers::NvsStorage& nvs) + -> bool { // Init LVGL first, since the display driver registers itself with LVGL. lv_init(); - sDisplay.reset(drivers::Display::Create(gpios, drivers::displays::kST7735R)); + + drivers::displays::InitialisationData init_data = drivers::displays::kST7735R; + + // HACK: correct the display size for our prototypes. + // nvs.DisplaySize({161, 130}); + + auto actual_size = nvs.DisplaySize(); + init_data.width = actual_size.first.value_or(init_data.width); + init_data.height = actual_size.second.value_or(init_data.height); + + sDisplay.reset(drivers::Display::Create(gpios, init_data)); if (sDisplay == nullptr) { return false; }