diff options
author | Jean-François Milants <jf@codingfield.com> | 2021-01-26 20:31:45 +0100 |
---|---|---|
committer | Jean-François Milants <jf@codingfield.com> | 2021-01-26 20:31:45 +0100 |
commit | 25f35c7d0e27af4308b8c263fde6661dbe29c2cc (patch) | |
tree | 145df6c4f8ab6be34771ee3d8caceb0dbb792d23 /src/displayapp/DisplayAppRecovery.cpp | |
parent | 80838d1e42e83b50188d6237d16c81cfa27781a6 (diff) |
Generate pinetime-recovery : a light version of InfiniTime design to be used as a recovery firmware : it only provides basic UI and BLE connectivity for OTA.
This new FW is build on the same codebasse than the actual InfiniTime. Only the display task is different (this allows to remove lvgl from the recovery fw, which is very heavy).
CMake builds and docker have been modified accordingly.
Note than the fw is converted into an image and then into a DFU in the cmake build (previously, it was only done in the
Diffstat (limited to 'src/displayapp/DisplayAppRecovery.cpp')
-rw-r--r-- | src/displayapp/DisplayAppRecovery.cpp | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp new file mode 100644 index 00000000..cccb72d3 --- /dev/null +++ b/src/displayapp/DisplayAppRecovery.cpp @@ -0,0 +1,110 @@ +#include "DisplayAppRecovery.h" +#include "DisplayAppRecovery.h" +#include <FreeRTOS.h> +#include <task.h> +#include <libraries/log/nrf_log.h> +#include <components/rle/RleDecoder.h> +#include "displayapp/icons/infinitime/infinitime-nb.c" + +using namespace Pinetime::Applications; + +DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Drivers::Cst816S &touchPanel, + Controllers::Battery &batteryController, Controllers::Ble &bleController, + Controllers::DateTime &dateTimeController, Drivers::WatchdogView &watchdog, + System::SystemTask &systemTask, + Pinetime::Controllers::NotificationManager& notificationManager, + Pinetime::Controllers::HeartRateController& heartRateController): + lcd{lcd}, bleController{bleController} { + msgQueue = xQueueCreate(queueSize, itemSize); + +} + +void DisplayApp::Start() { + if (pdPASS != xTaskCreate(DisplayApp::Process, "displayapp", 512, this, 0, &taskHandle)) + APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); +} + +void DisplayApp::Process(void *instance) { + auto *app = static_cast<DisplayApp *>(instance); + NRF_LOG_INFO("displayapp task started!"); + + // 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() { + 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; + } + } + + if (bleController.IsFirmwareUpdating()) { + uint8_t percent = (static_cast<float>(bleController.FirmwareUpdateCurrentBytes()) / + static_cast<float>(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<const uint8_t *>(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<float>(percent) * 2.4f, static_cast<float>(displayWidth)); + lcd.BeginDrawBuffer(0, displayWidth - barHeight + i, barWidth, 1); + lcd.NextDrawBuffer(reinterpret_cast<const uint8_t *>(displayBuffer), barWidth * bytesPerPixel); + } +} + +void DisplayApp::PushMessage(Display::Messages msg) { + BaseType_t xHigherPriorityTaskWoken; + xHigherPriorityTaskWoken = pdFALSE; + xQueueSendFromISR(msgQueue, &msg, &xHigherPriorityTaskWoken); + if (xHigherPriorityTaskWoken) { + /* Actual macro used here is port specific. */ + // TODO : should I do something here? + } +}
\ No newline at end of file |