Compare commits

..

No commits in common. "06c69353156559aa786e8116f2527e8de3ee2d38" and "079e676baf70a943d31317afde47b759ca69ca2d" have entirely different histories.

12 changed files with 94 additions and 98 deletions

View File

@ -75,7 +75,6 @@
#define configUSE_TIME_SLICING 0 #define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0 #define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1 #define configENABLE_BACKWARD_COMPATIBILITY 1
#define configUSE_TASK_NOTIFICATIONS 0
/* Hook function related definitions. */ /* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0 #define configUSE_IDLE_HOOK 0

View File

@ -142,6 +142,9 @@ void DisplayApp::Process(void* instance) {
NRF_LOG_INFO("displayapp task started!"); NRF_LOG_INFO("displayapp task started!");
app->InitHw(); app->InitHw();
// Send a dummy notification to unlock the lvgl display driver for the first iteration
xTaskNotifyGive(xTaskGetCurrentTaskHandle());
while (true) { while (true) {
app->Refresh(); app->Refresh();
} }

View File

@ -38,6 +38,9 @@ void DisplayApp::Process(void* instance) {
auto* app = static_cast<DisplayApp*>(instance); auto* app = static_cast<DisplayApp*>(instance);
NRF_LOG_INFO("displayapp task started!"); NRF_LOG_INFO("displayapp task started!");
// Send a dummy notification to unlock the lvgl display driver for the first iteration
xTaskNotifyGive(xTaskGetCurrentTaskHandle());
app->InitHw(); app->InitHw();
while (true) { while (true) {
app->Refresh(); app->Refresh();
@ -91,6 +94,7 @@ void DisplayApp::DisplayLogo(uint16_t color) {
Pinetime::Tools::RleDecoder rleDecoder(infinitime_nb, sizeof(infinitime_nb), color, colorBlack); Pinetime::Tools::RleDecoder rleDecoder(infinitime_nb, sizeof(infinitime_nb), color, colorBlack);
for (int i = 0; i < displayWidth; i++) { for (int i = 0; i < displayWidth; i++) {
rleDecoder.DecodeNext(displayBuffer, displayWidth * bytesPerPixel); rleDecoder.DecodeNext(displayBuffer, displayWidth * bytesPerPixel);
ulTaskNotifyTake(pdTRUE, 500);
lcd.DrawBuffer(0, i, displayWidth, 1, reinterpret_cast<const uint8_t*>(displayBuffer), displayWidth * bytesPerPixel); lcd.DrawBuffer(0, i, displayWidth, 1, reinterpret_cast<const uint8_t*>(displayBuffer), displayWidth * bytesPerPixel);
} }
} }
@ -99,6 +103,7 @@ void DisplayApp::DisplayOtaProgress(uint8_t percent, uint16_t color) {
const uint8_t barHeight = 20; const uint8_t barHeight = 20;
std::fill(displayBuffer, displayBuffer + (displayWidth * bytesPerPixel), color); std::fill(displayBuffer, displayBuffer + (displayWidth * bytesPerPixel), color);
for (int i = 0; i < barHeight; i++) { 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)); uint16_t barWidth = std::min(static_cast<float>(percent) * 2.4f, static_cast<float>(displayWidth));
lcd.DrawBuffer(0, displayWidth - barHeight + i, barWidth, 1, reinterpret_cast<const uint8_t*>(displayBuffer), barWidth * bytesPerPixel); lcd.DrawBuffer(0, displayWidth - barHeight + i, barWidth, 1, reinterpret_cast<const uint8_t*>(displayBuffer), barWidth * bytesPerPixel);
} }

View File

@ -152,6 +152,10 @@ void LittleVgl::SetFullRefresh(FullRefreshDirections direction) {
void LittleVgl::FlushDisplay(const lv_area_t* area, lv_color_t* color_p) { void LittleVgl::FlushDisplay(const lv_area_t* area, lv_color_t* color_p) {
uint16_t y1, y2, width, height = 0; uint16_t y1, y2, width, height = 0;
ulTaskNotifyTake(pdTRUE, 200);
// Notification is still needed (even if there is a mutex on SPI) because of the DataCommand pin
// which cannot be set/clear during a transfer.
if ((scrollDirection == LittleVgl::FullRefreshDirections::Down) && (area->y2 == visibleNbLines - 1)) { if ((scrollDirection == LittleVgl::FullRefreshDirections::Down) && (area->y2 == visibleNbLines - 1)) {
writeOffset = ((writeOffset + totalNbLines) - visibleNbLines) % totalNbLines; writeOffset = ((writeOffset + totalNbLines) - visibleNbLines) % totalNbLines;
} else if ((scrollDirection == FullRefreshDirections::Up) && (area->y1 == 0)) { } else if ((scrollDirection == FullRefreshDirections::Up) && (area->y1 == 0)) {
@ -215,6 +219,7 @@ void LittleVgl::FlushDisplay(const lv_area_t* area, lv_color_t* color_p) {
if (height > 0) { if (height > 0) {
lcd.DrawBuffer(area->x1, y1, width, height, reinterpret_cast<const uint8_t*>(color_p), width * height * 2); lcd.DrawBuffer(area->x1, y1, width, height, reinterpret_cast<const uint8_t*>(color_p), width * height * 2);
ulTaskNotifyTake(pdTRUE, 100);
} }
uint16_t pixOffset = width * height; uint16_t pixOffset = width * height;

View File

@ -9,8 +9,8 @@ Spi::Spi(SpiMaster& spiMaster, uint8_t pinCsn) : spiMaster {spiMaster}, pinCsn {
nrf_gpio_pin_set(pinCsn); nrf_gpio_pin_set(pinCsn);
} }
bool Spi::Write(const uint8_t* data, size_t size, const std::function<void()>& preTransactionHook) { bool Spi::Write(const uint8_t* data, size_t size, void (*TransactionHook)(bool)) {
return spiMaster.Write(pinCsn, data, size, preTransactionHook); return spiMaster.Write(pinCsn, data, size, TransactionHook);
} }
bool Spi::Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) { bool Spi::Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) {

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <cstddef> #include <cstddef>
#include <functional>
#include "drivers/SpiMaster.h" #include "drivers/SpiMaster.h"
namespace Pinetime { namespace Pinetime {
@ -15,7 +14,7 @@ namespace Pinetime {
Spi& operator=(Spi&&) = delete; Spi& operator=(Spi&&) = delete;
bool Init(); bool Init();
bool Write(const uint8_t* data, size_t size, const std::function<void()>& preTransactionHook); bool Write(const uint8_t* data, size_t size, void (*TransactionHook)(bool));
bool Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize); bool Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize);
bool WriteCmdAndBuffer(const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize); bool WriteCmdAndBuffer(const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize);
void Sleep(); void Sleep();

View File

@ -136,11 +136,20 @@ void SpiMaster::OnEndEvent() {
spiBaseAddress->TASKS_START = 1; spiBaseAddress->TASKS_START = 1;
} else { } else {
nrf_gpio_pin_set(this->pinCsn);
currentBufferAddr = 0;
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(mutex, &xHigherPriorityTaskWoken); if (taskToNotify != nullptr) {
portYIELD_FROM_ISR(xHigherPriorityTaskWoken); vTaskNotifyGiveFromISR(taskToNotify, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
nrf_gpio_pin_set(this->pinCsn);
if (this->TransactionHook != nullptr) {
this->TransactionHook(false);
}
currentBufferAddr = 0;
BaseType_t xHigherPriorityTaskWoken2 = pdFALSE;
xSemaphoreGiveFromISR(mutex, &xHigherPriorityTaskWoken2);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken | xHigherPriorityTaskWoken2);
} }
} }
@ -167,12 +176,14 @@ void SpiMaster::PrepareRx(const uint32_t bufferAddress, const size_t size) {
spiBaseAddress->EVENTS_END = 0; spiBaseAddress->EVENTS_END = 0;
} }
bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size, const std::function<void()>& preTransactionHook) { bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size, void (*TransactionHook)(bool)) {
if (data == nullptr) if (data == nullptr)
return false; return false;
auto ok = xSemaphoreTake(mutex, portMAX_DELAY); auto ok = xSemaphoreTake(mutex, portMAX_DELAY);
ASSERT(ok == true); ASSERT(ok == true);
taskToNotify = xTaskGetCurrentTaskHandle();
this->TransactionHook = TransactionHook;
this->pinCsn = pinCsn; this->pinCsn = pinCsn;
if (size == 1) { if (size == 1) {
@ -181,8 +192,8 @@ bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size, const st
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0); DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
} }
if (preTransactionHook != nullptr) { if (this->TransactionHook != nullptr) {
preTransactionHook(); this->TransactionHook(true);
} }
nrf_gpio_pin_clear(this->pinCsn); nrf_gpio_pin_clear(this->pinCsn);
@ -199,6 +210,9 @@ bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size, const st
while (spiBaseAddress->EVENTS_END == 0) while (spiBaseAddress->EVENTS_END == 0)
; ;
nrf_gpio_pin_set(this->pinCsn); nrf_gpio_pin_set(this->pinCsn);
if (this->TransactionHook != nullptr) {
this->TransactionHook(false);
}
currentBufferAddr = 0; currentBufferAddr = 0;
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0); DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
@ -212,6 +226,8 @@ bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size, const st
bool SpiMaster::Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) { bool SpiMaster::Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) {
xSemaphoreTake(mutex, portMAX_DELAY); xSemaphoreTake(mutex, portMAX_DELAY);
taskToNotify = nullptr;
this->TransactionHook = nullptr;
this->pinCsn = pinCsn; this->pinCsn = pinCsn;
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0); DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
spiBaseAddress->INTENCLR = (1 << 6); spiBaseAddress->INTENCLR = (1 << 6);
@ -259,6 +275,10 @@ void SpiMaster::Wakeup() {
bool SpiMaster::WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize) { bool SpiMaster::WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize) {
xSemaphoreTake(mutex, portMAX_DELAY); xSemaphoreTake(mutex, portMAX_DELAY);
taskToNotify = nullptr;
this->TransactionHook = nullptr;
this->pinCsn = pinCsn; this->pinCsn = pinCsn;
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0); DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
spiBaseAddress->INTENCLR = (1 << 6); spiBaseAddress->INTENCLR = (1 << 6);

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <functional>
#include <FreeRTOS.h> #include <FreeRTOS.h>
#include <semphr.h> #include <semphr.h>
@ -32,7 +31,7 @@ namespace Pinetime {
SpiMaster& operator=(SpiMaster&&) = delete; SpiMaster& operator=(SpiMaster&&) = delete;
bool Init(); bool Init();
bool Write(uint8_t pinCsn, const uint8_t* data, size_t size, const std::function<void()>& preTransactionHook); bool Write(uint8_t pinCsn, const uint8_t* data, size_t size, void (*TransactionHook)(bool));
bool Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize); bool Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize);
bool WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize); bool WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize);
@ -51,12 +50,14 @@ namespace Pinetime {
NRF_SPIM_Type* spiBaseAddress; NRF_SPIM_Type* spiBaseAddress;
uint8_t pinCsn; uint8_t pinCsn;
void (*TransactionHook)(bool);
SpiMaster::SpiModule spi; SpiMaster::SpiModule spi;
SpiMaster::Parameters params; SpiMaster::Parameters params;
volatile uint32_t currentBufferAddr = 0; volatile uint32_t currentBufferAddr = 0;
volatile size_t currentBufferSize = 0; volatile size_t currentBufferSize = 0;
volatile TaskHandle_t taskToNotify;
SemaphoreHandle_t mutex = nullptr; SemaphoreHandle_t mutex = nullptr;
}; };
} }

View File

@ -1,18 +1,19 @@
#include "drivers/St7789.h" #include "drivers/St7789.h"
#include <hal/nrf_gpio.h> #include <hal/nrf_gpio.h>
#include <libraries/delay/nrf_delay.h>
#include <nrfx_log.h> #include <nrfx_log.h>
#include "drivers/Spi.h" #include "drivers/Spi.h"
#include "task.h" #include "drivers/PinMap.h"
using namespace Pinetime::Drivers; using namespace Pinetime::Drivers;
St7789::St7789(Spi& spi, uint8_t pinDataCommand, uint8_t pinReset) : spi {spi}, pinDataCommand {pinDataCommand}, pinReset {pinReset} { St7789::St7789(Spi& spi) : spi {spi} {
} }
void St7789::Init() { void St7789::Init() {
nrf_gpio_cfg_output(pinDataCommand); nrf_gpio_cfg_output(PinMap::LcdDataCommand);
nrf_gpio_cfg_output(pinReset); nrf_gpio_cfg_output(PinMap::LcdReset);
nrf_gpio_pin_set(pinReset); nrf_gpio_pin_set(PinMap::LcdReset);
HardwareReset(); HardwareReset();
SoftwareReset(); SoftwareReset();
SleepOut(); SleepOut();
@ -29,77 +30,47 @@ void St7789::Init() {
DisplayOn(); DisplayOn();
} }
void St7789::EnableDataMode(bool isStart) {
if (isStart) {
nrf_gpio_pin_set(PinMap::LcdDataCommand);
}
}
void St7789::EnableCommandMode(bool isStart) {
if (isStart) {
nrf_gpio_pin_clear(PinMap::LcdDataCommand);
}
}
void St7789::WriteCommand(uint8_t cmd) {
WriteSpi(&cmd, 1, EnableCommandMode);
}
void St7789::WriteData(uint8_t data) { void St7789::WriteData(uint8_t data) {
WriteData(&data, 1); WriteSpi(&data, 1, EnableDataMode);
} }
void St7789::WriteData(const uint8_t* data, size_t size) { void St7789::WriteSpi(const uint8_t* data, size_t size, void (*TransactionHook)(bool)) {
WriteSpi(data, size, [pinDataCommand = pinDataCommand]() { spi.Write(data, size, TransactionHook);
nrf_gpio_pin_set(pinDataCommand);
});
}
void St7789::WriteCommand(uint8_t data) {
WriteCommand(&data, 1);
}
void St7789::WriteCommand(const uint8_t* data, size_t size) {
WriteSpi(data, size, [pinDataCommand = pinDataCommand]() {
nrf_gpio_pin_clear(pinDataCommand);
});
}
void St7789::WriteSpi(const uint8_t* data, size_t size, const std::function<void()>& preTransactionHook) {
spi.Write(data, size, preTransactionHook);
} }
void St7789::SoftwareReset() { void St7789::SoftwareReset() {
EnsureSleepOutPostDelay();
WriteCommand(static_cast<uint8_t>(Commands::SoftwareReset)); WriteCommand(static_cast<uint8_t>(Commands::SoftwareReset));
// If sleep in: must wait 120ms before sleep out can sent (see driver datasheet) nrf_delay_ms(150);
// Unconditionally wait as software reset doesn't need to be performant
sleepIn = true;
lastSleepExit = xTaskGetTickCount();
vTaskDelay(pdMS_TO_TICKS(125));
} }
void St7789::SleepOut() { void St7789::SleepOut() {
if (!sleepIn) {
return;
}
WriteCommand(static_cast<uint8_t>(Commands::SleepOut)); WriteCommand(static_cast<uint8_t>(Commands::SleepOut));
// Wait 5ms for clocks to stabilise
// pdMS rounds down => 6 used here
vTaskDelay(pdMS_TO_TICKS(6));
// Cannot send sleep in or software reset for 120ms
lastSleepExit = xTaskGetTickCount();
sleepIn = false;
}
void St7789::EnsureSleepOutPostDelay() {
TickType_t delta = xTaskGetTickCount() - lastSleepExit;
// Due to timer wraparound, there is a chance of delaying when not necessary
// It is very low (pdMS_TO_TICKS(125)/2^32) and waiting an extra 125ms isn't too bad
if (delta < pdMS_TO_TICKS(125)) {
vTaskDelay(pdMS_TO_TICKS(125) - delta);
}
} }
void St7789::SleepIn() { void St7789::SleepIn() {
if (sleepIn) {
return;
}
EnsureSleepOutPostDelay();
WriteCommand(static_cast<uint8_t>(Commands::SleepIn)); WriteCommand(static_cast<uint8_t>(Commands::SleepIn));
// Wait 5ms for clocks to stabilise
// pdMS rounds down => 6 used here
vTaskDelay(pdMS_TO_TICKS(6));
sleepIn = true;
} }
void St7789::ColMod() { void St7789::ColMod() {
WriteCommand(static_cast<uint8_t>(Commands::ColMod)); WriteCommand(static_cast<uint8_t>(Commands::ColMod));
WriteData(0x55); WriteData(0x55);
nrf_delay_ms(10);
} }
void St7789::MemoryDataAccessControl() { void St7789::MemoryDataAccessControl() {
@ -136,10 +107,12 @@ void St7789::RowAddressSet() {
void St7789::DisplayInversionOn() { void St7789::DisplayInversionOn() {
WriteCommand(static_cast<uint8_t>(Commands::DisplayInversionOn)); WriteCommand(static_cast<uint8_t>(Commands::DisplayInversionOn));
nrf_delay_ms(10);
} }
void St7789::NormalModeOn() { void St7789::NormalModeOn() {
WriteCommand(static_cast<uint8_t>(Commands::NormalModeOn)); WriteCommand(static_cast<uint8_t>(Commands::NormalModeOn));
nrf_delay_ms(10);
} }
void St7789::DisplayOn() { void St7789::DisplayOn() {
@ -158,11 +131,12 @@ void St7789::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
WriteData(y0 & 0xff); WriteData(y0 & 0xff);
WriteData(y1 >> 8); WriteData(y1 >> 8);
WriteData(y1 & 0xff); WriteData(y1 & 0xff);
WriteToRam();
} }
void St7789::WriteToRam(const uint8_t* data, size_t size) { void St7789::WriteToRam() {
WriteCommand(static_cast<uint8_t>(Commands::WriteToRam)); WriteCommand(static_cast<uint8_t>(Commands::WriteToRam));
WriteData(data, size);
} }
void St7789::SetVdv() { void St7789::SetVdv() {
@ -174,6 +148,7 @@ void St7789::SetVdv() {
void St7789::DisplayOff() { void St7789::DisplayOff() {
WriteCommand(static_cast<uint8_t>(Commands::DisplayOff)); WriteCommand(static_cast<uint8_t>(Commands::DisplayOff));
nrf_delay_ms(500);
} }
void St7789::VerticalScrollStartAddress(uint16_t line) { void St7789::VerticalScrollStartAddress(uint16_t line) {
@ -188,28 +163,23 @@ void St7789::Uninit() {
void St7789::DrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t* data, size_t size) { void St7789::DrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t* data, size_t size) {
SetAddrWindow(x, y, x + width - 1, y + height - 1); SetAddrWindow(x, y, x + width - 1, y + height - 1);
WriteToRam(data, size); WriteSpi(data, size, EnableDataMode);
} }
void St7789::HardwareReset() { void St7789::HardwareReset() {
nrf_gpio_pin_clear(pinReset); nrf_gpio_pin_clear(PinMap::LcdReset);
vTaskDelay(pdMS_TO_TICKS(1)); nrf_delay_ms(10);
nrf_gpio_pin_set(pinReset); nrf_gpio_pin_set(PinMap::LcdReset);
// If hardware reset started while sleep out, reset time may be up to 120ms
// Unconditionally wait as hardware reset doesn't need to be performant
sleepIn = true;
lastSleepExit = xTaskGetTickCount();
vTaskDelay(pdMS_TO_TICKS(125));
} }
void St7789::Sleep() { void St7789::Sleep() {
SleepIn(); SleepIn();
nrf_gpio_cfg_default(pinDataCommand); nrf_gpio_cfg_default(PinMap::LcdDataCommand);
NRF_LOG_INFO("[LCD] Sleep"); NRF_LOG_INFO("[LCD] Sleep");
} }
void St7789::Wakeup() { void St7789::Wakeup() {
nrf_gpio_cfg_output(pinDataCommand); nrf_gpio_cfg_output(PinMap::LcdDataCommand);
SleepOut(); SleepOut();
VerticalScrollStartAddress(verticalScrollingStartAddress); VerticalScrollStartAddress(verticalScrollingStartAddress);
DisplayOn(); DisplayOn();

View File

@ -1,9 +1,6 @@
#pragma once #pragma once
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <functional>
#include <FreeRTOS.h>
namespace Pinetime { namespace Pinetime {
namespace Drivers { namespace Drivers {
@ -11,7 +8,7 @@ namespace Pinetime {
class St7789 { class St7789 {
public: public:
explicit St7789(Spi& spi, uint8_t pinDataCommand, uint8_t pinReset); explicit St7789(Spi& spi);
St7789(const St7789&) = delete; St7789(const St7789&) = delete;
St7789& operator=(const St7789&) = delete; St7789& operator=(const St7789&) = delete;
St7789(St7789&&) = delete; St7789(St7789&&) = delete;
@ -29,30 +26,26 @@ namespace Pinetime {
private: private:
Spi& spi; Spi& spi;
uint8_t pinDataCommand;
uint8_t pinReset;
uint8_t verticalScrollingStartAddress = 0; uint8_t verticalScrollingStartAddress = 0;
bool sleepIn;
TickType_t lastSleepExit;
void HardwareReset(); void HardwareReset();
void SoftwareReset(); void SoftwareReset();
void SleepOut(); void SleepOut();
void EnsureSleepOutPostDelay();
void SleepIn(); void SleepIn();
void ColMod(); void ColMod();
void MemoryDataAccessControl(); void MemoryDataAccessControl();
void DisplayInversionOn(); void DisplayInversionOn();
void NormalModeOn(); void NormalModeOn();
void WriteToRam(const uint8_t* data, size_t size); void WriteToRam();
void DisplayOn(); void DisplayOn();
void DisplayOff(); void DisplayOff();
void SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); void SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
void SetVdv(); void SetVdv();
void WriteCommand(uint8_t cmd); void WriteCommand(uint8_t cmd);
void WriteCommand(const uint8_t* data, size_t size); void WriteSpi(const uint8_t* data, size_t size, void (*TransactionHook)(bool));
void WriteSpi(const uint8_t* data, size_t size, const std::function<void()>& preTransactionHook); static void EnableDataMode(bool isStart);
static void EnableCommandMode(bool isStart);
enum class Commands : uint8_t { enum class Commands : uint8_t {
SoftwareReset = 0x01, SoftwareReset = 0x01,
@ -72,7 +65,6 @@ namespace Pinetime {
VdvSet = 0xc4, VdvSet = 0xc4,
}; };
void WriteData(uint8_t data); void WriteData(uint8_t data);
void WriteData(const uint8_t* data, size_t size);
void ColumnAddressSet(); void ColumnAddressSet();
static constexpr uint16_t Width = 240; static constexpr uint16_t Width = 240;

View File

@ -68,7 +68,7 @@ Pinetime::Drivers::SpiMaster spi {Pinetime::Drivers::SpiMaster::SpiModule::SPI0,
Pinetime::PinMap::SpiMiso}}; Pinetime::PinMap::SpiMiso}};
Pinetime::Drivers::Spi lcdSpi {spi, Pinetime::PinMap::SpiLcdCsn}; Pinetime::Drivers::Spi lcdSpi {spi, Pinetime::PinMap::SpiLcdCsn};
Pinetime::Drivers::St7789 lcd {lcdSpi, Pinetime::PinMap::LcdDataCommand, Pinetime::PinMap::LcdReset}; Pinetime::Drivers::St7789 lcd {lcdSpi};
Pinetime::Drivers::Spi flashSpi {spi, Pinetime::PinMap::SpiFlashCsn}; Pinetime::Drivers::Spi flashSpi {spi, Pinetime::PinMap::SpiFlashCsn};
Pinetime::Drivers::SpiNorFlash spiNorFlash {flashSpi}; Pinetime::Drivers::SpiNorFlash spiNorFlash {flashSpi};

View File

@ -45,7 +45,7 @@ Pinetime::Drivers::Spi flashSpi {spi, Pinetime::PinMap::SpiFlashCsn};
Pinetime::Drivers::SpiNorFlash spiNorFlash {flashSpi}; Pinetime::Drivers::SpiNorFlash spiNorFlash {flashSpi};
Pinetime::Drivers::Spi lcdSpi {spi, Pinetime::PinMap::SpiLcdCsn}; Pinetime::Drivers::Spi lcdSpi {spi, Pinetime::PinMap::SpiLcdCsn};
Pinetime::Drivers::St7789 lcd {lcdSpi, Pinetime::PinMap::LcdDataCommand, Pinetime::PinMap::LcdReset}; Pinetime::Drivers::St7789 lcd {lcdSpi};
Pinetime::Controllers::BrightnessController brightnessController; Pinetime::Controllers::BrightnessController brightnessController;
@ -121,6 +121,7 @@ void DisplayLogo() {
Pinetime::Tools::RleDecoder rleDecoder(infinitime_nb, sizeof(infinitime_nb)); Pinetime::Tools::RleDecoder rleDecoder(infinitime_nb, sizeof(infinitime_nb));
for (int i = 0; i < displayWidth; i++) { for (int i = 0; i < displayWidth; i++) {
rleDecoder.DecodeNext(displayBuffer, displayWidth * bytesPerPixel); rleDecoder.DecodeNext(displayBuffer, displayWidth * bytesPerPixel);
ulTaskNotifyTake(pdTRUE, 500);
lcd.DrawBuffer(0, i, displayWidth, 1, reinterpret_cast<const uint8_t*>(displayBuffer), displayWidth * bytesPerPixel); lcd.DrawBuffer(0, i, displayWidth, 1, reinterpret_cast<const uint8_t*>(displayBuffer), displayWidth * bytesPerPixel);
} }
} }
@ -129,6 +130,7 @@ void DisplayProgressBar(uint8_t percent, uint16_t color) {
static constexpr uint8_t barHeight = 20; static constexpr uint8_t barHeight = 20;
std::fill(displayBuffer, displayBuffer + (displayWidth * bytesPerPixel), color); std::fill(displayBuffer, displayBuffer + (displayWidth * bytesPerPixel), color);
for (int i = 0; i < barHeight; i++) { 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)); uint16_t barWidth = std::min(static_cast<float>(percent) * 2.4f, static_cast<float>(displayWidth));
lcd.DrawBuffer(0, displayWidth - barHeight + i, barWidth, 1, reinterpret_cast<const uint8_t*>(displayBuffer), barWidth * bytesPerPixel); lcd.DrawBuffer(0, displayWidth - barHeight + i, barWidth, 1, reinterpret_cast<const uint8_t*>(displayBuffer), barWidth * bytesPerPixel);
} }