diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp index 82cefc43..f1917a77 100644 --- a/src/drivers/St7789.cpp +++ b/src/drivers/St7789.cpp @@ -1,7 +1,4 @@ #include "drivers/St7789.h" -#include -#include -#include "drivers/Spi.h" using namespace Pinetime::Drivers; @@ -53,22 +50,52 @@ void St7789::WriteSpi(const uint8_t* data, size_t size, const std::function(Commands::SoftwareReset)); - vTaskDelay(pdMS_TO_TICKS(150)); + // If sleep in: must wait 120ms before sleep out can sent (see driver datasheet) + // Unconditionally wait as software reset doesn't need to be performant + sleepIn = true; + lastSleepExit = xTaskGetTickCount(); + vTaskDelay(pdMS_TO_TICKS(125)); } void St7789::SleepOut() { + if (!sleepIn) { + return; + } WriteCommand(static_cast(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() { + if (sleepIn) { + return; + } + EnsureSleepOutPostDelay(); WriteCommand(static_cast(Commands::SleepIn)); + // Wait 5ms for clocks to stabilise + // pdMS rounds down => 6 used here + vTaskDelay(pdMS_TO_TICKS(6)); + sleepIn = true; } void St7789::ColMod() { WriteCommand(static_cast(Commands::ColMod)); WriteData(0x55); - vTaskDelay(pdMS_TO_TICKS(10)); } void St7789::MemoryDataAccessControl() { @@ -105,12 +132,10 @@ void St7789::RowAddressSet() { void St7789::DisplayInversionOn() { WriteCommand(static_cast(Commands::DisplayInversionOn)); - vTaskDelay(pdMS_TO_TICKS(10)); } void St7789::NormalModeOn() { WriteCommand(static_cast(Commands::NormalModeOn)); - vTaskDelay(pdMS_TO_TICKS(10)); } void St7789::DisplayOn() { @@ -145,7 +170,6 @@ void St7789::SetVdv() { void St7789::DisplayOff() { WriteCommand(static_cast(Commands::DisplayOff)); - vTaskDelay(pdMS_TO_TICKS(500)); } void St7789::VerticalScrollStartAddress(uint16_t line) { @@ -165,8 +189,13 @@ void St7789::DrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, void St7789::HardwareReset() { nrf_gpio_pin_clear(pinReset); - vTaskDelay(pdMS_TO_TICKS(10)); + vTaskDelay(pdMS_TO_TICKS(1)); nrf_gpio_pin_set(pinReset); + // 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() { diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h index 715bd1bd..fcb6f944 100644 --- a/src/drivers/St7789.h +++ b/src/drivers/St7789.h @@ -3,6 +3,10 @@ #include #include +#include +#include +#include "drivers/Spi.h" + namespace Pinetime { namespace Drivers { class Spi; @@ -30,10 +34,13 @@ namespace Pinetime { uint8_t pinDataCommand; uint8_t pinReset; uint8_t verticalScrollingStartAddress = 0; + bool sleepIn; + TickType_t lastSleepExit; void HardwareReset(); void SoftwareReset(); void SleepOut(); + void EnsureSleepOutPostDelay(); void SleepIn(); void ColMod(); void MemoryDataAccessControl();