diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 34c780ce..fea80ce7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -422,6 +422,8 @@ list(APPEND FACTORY_SOURCE_FILES systemtask/SystemTask.cpp drivers/TwiMaster.cpp components/gfx/Gfx.cpp + displayapp/icons/infinitime/infinitime-nb.c + components/rle/RleDecoder.cpp ) diff --git a/src/components/rle/RleDecoder.cpp b/src/components/rle/RleDecoder.cpp index 62abd615..19a90fda 100644 --- a/src/components/rle/RleDecoder.cpp +++ b/src/components/rle/RleDecoder.cpp @@ -6,6 +6,12 @@ RleDecoder::RleDecoder(const uint8_t *buffer, size_t size) : buffer{buffer}, siz } +RleDecoder::RleDecoder(const uint8_t *buffer, size_t size, uint16_t foregroundColor, uint16_t backgroundColor) : RleDecoder{buffer, size} { + this->foregroundColor = foregroundColor; + this->backgroundColor = backgroundColor; +} + + void RleDecoder::DecodeNext(uint8_t *output, size_t maxBytes) { for (;encodedBufferIndex #include #include +#include +#include "displayapp/icons/infinitime/infinitime-nb.c" using namespace Pinetime::Applications; @@ -11,7 +13,7 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver Controllers::DateTime &dateTimeController, Drivers::WatchdogView &watchdog, System::SystemTask &systemTask, Pinetime::Controllers::NotificationManager& notificationManager) : - lcd{lcd} { + lcd{lcd}, bleController{bleController} { msgQueue = xQueueCreate(queueSize, itemSize); } @@ -24,41 +26,76 @@ void DisplayApp::Start() { void DisplayApp::Process(void *instance) { auto *app = static_cast(instance); NRF_LOG_INFO("displayapp task started!"); - app->InitHw(); // Send a dummy notification to unlock the lvgl display driver for the first iteration xTaskNotifyGive(xTaskGetCurrentTaskHandle()); + app->InitHw(); while (1) { app->Refresh(); } } void DisplayApp::InitHw() { - + DisplayLogo(colorWhite); } void DisplayApp::Refresh() { - static bool hello = false; - - - if(hello) { - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - lcd.DrawPixel(j, i, 0xF000); - } - } - } - else { - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - lcd.DrawPixel(j, i, 0x0); - } + Display::Messages msg; + if (xQueueReceive(msgQueue, &msg, 200)) { + switch (msg) { + case Display::Messages::UpdateBleConnection: + if (bleController.IsConnected()) + DisplayLogo(colorBlue); + else + DisplayLogo(colorWhite); + break; + case Display::Messages::BleFirmwareUpdateStarted: + DisplayLogo(colorGreen); + break; + default: + break; } } - hello = !hello; - vTaskDelay(200); + if (bleController.IsFirmwareUpdating()) { + uint8_t percent = (static_cast(bleController.FirmwareUpdateCurrentBytes()) / + static_cast(bleController.FirmwareUpdateTotalBytes())) * 100.0f; + switch (bleController.State()) { + case Controllers::Ble::FirmwareUpdateStates::Running: + DisplayOtaProgress(percent, colorWhite); + break; + case Controllers::Ble::FirmwareUpdateStates::Validated: + DisplayOtaProgress(100, colorGreenSwapped); + break; + case Controllers::Ble::FirmwareUpdateStates::Error: + DisplayOtaProgress(100, colorRedSwapped); + break; + default: + break; + } + } +} + +void DisplayApp::DisplayLogo(uint16_t color) { + Pinetime::Tools::RleDecoder rleDecoder(infinitime_nb, sizeof(infinitime_nb), color, colorBlack); + for(int i = 0; i < displayWidth; i++) { + rleDecoder.DecodeNext(displayBuffer, displayWidth * bytesPerPixel); + ulTaskNotifyTake(pdTRUE, 500); + lcd.BeginDrawBuffer(0, i, displayWidth, 1); + lcd.NextDrawBuffer(reinterpret_cast(displayBuffer), displayWidth * bytesPerPixel); + } +} + +void DisplayApp::DisplayOtaProgress(uint8_t percent, uint16_t color) { + const uint8_t barHeight = 20; + std::fill(displayBuffer, displayBuffer+(displayWidth * bytesPerPixel), color); + for(int i = 0; i < barHeight; i++) { + ulTaskNotifyTake(pdTRUE, 500); + uint16_t barWidth = std::min(static_cast(percent) * 2.4f, static_cast(displayWidth)); + lcd.BeginDrawBuffer(0, displayWidth - barHeight + i, barWidth, 1); + lcd.NextDrawBuffer(reinterpret_cast(displayBuffer), barWidth * bytesPerPixel); + } } void DisplayApp::PushMessage(Display::Messages msg) { diff --git a/src/displayapp/DisplayAppFactory.h b/src/displayapp/DisplayAppFactory.h index a923ae2d..d1703cfb 100644 --- a/src/displayapp/DisplayAppFactory.h +++ b/src/displayapp/DisplayAppFactory.h @@ -40,12 +40,28 @@ namespace Pinetime { private: TaskHandle_t taskHandle; static void Process(void* instance); + void DisplayLogo(uint16_t color); + void DisplayOtaProgress(uint8_t percent, uint16_t color); void InitHw(); void Refresh(); Pinetime::Drivers::St7789& lcd; + Controllers::Ble &bleController; + static constexpr uint8_t queueSize = 10; static constexpr uint8_t itemSize = 1; QueueHandle_t msgQueue; + static constexpr uint8_t displayWidth = 240; + static constexpr uint8_t displayHeight = 240; + static constexpr uint8_t bytesPerPixel = 2; + + static constexpr uint16_t colorWhite = 0xFFFF; + static constexpr uint16_t colorGreen = 0x07E0; + static constexpr uint16_t colorGreenSwapped = 0xE007; + static constexpr uint16_t colorBlue = 0x0000ff; + static constexpr uint16_t colorRed = 0xff00; + static constexpr uint16_t colorRedSwapped = 0x00ff; + static constexpr uint16_t colorBlack = 0x0000; + uint8_t displayBuffer[displayWidth * bytesPerPixel]; }; diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index efa22a6f..e9836511 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -143,6 +143,7 @@ void SystemTask::Work() { ReloadIdleTimer(); isBleDiscoveryTimerRunning = true; bleDiscoveryTimer = 5; + displayApp->PushMessage(Pinetime::Applications::Display::Messages::UpdateBleConnection); break; case Messages::BleFirmwareUpdateStarted: doNotGoToSleep = true;