#include "drivers/St7789.h" #include #include #include #include "drivers/Spi.h" using namespace Pinetime::Drivers; St7789::St7789(Spi& spi, uint8_t pinDataCommand) : spi {spi}, pinDataCommand {pinDataCommand} { } void St7789::Init() { nrf_gpio_cfg_output(pinDataCommand); nrf_gpio_cfg_output(26); nrf_gpio_pin_set(26); HardwareReset(); SoftwareReset(); SleepOut(); ColMod(); MemoryDataAccessControl(); ColumnAddressSet(); RowAddressSet(); // P8B Mirrored version does not need display inversion. #ifndef DRIVER_DISPLAY_MIRROR DisplayInversionOn(); #endif NormalModeOn(); SetVdv(); DisplayOn(); } void St7789::WriteCommand(uint8_t cmd) { nrf_gpio_pin_clear(pinDataCommand); WriteSpi(&cmd, 1); } void St7789::WriteData(uint8_t data) { nrf_gpio_pin_set(pinDataCommand); WriteSpi(&data, 1); } void St7789::WriteSpi(const uint8_t* data, size_t size) { spi.Write(data, size); } void St7789::SoftwareReset() { WriteCommand(static_cast(Commands::SoftwareReset)); nrf_delay_ms(150); } void St7789::SleepOut() { WriteCommand(static_cast(Commands::SleepOut)); } void St7789::SleepIn() { WriteCommand(static_cast(Commands::SleepIn)); } void St7789::ColMod() { WriteCommand(static_cast(Commands::ColMod)); WriteData(0x55); nrf_delay_ms(10); } void St7789::MemoryDataAccessControl() { WriteCommand(static_cast(Commands::MemoryDataAccessControl)); #ifdef DRIVER_DISPLAY_MIRROR // [7] = MY = Page Address Order, 0 = Top to bottom, 1 = Bottom to top // [6] = MX = Column Address Order, 0 = Left to right, 1 = Right to left // [5] = MV = Page/Column Order, 0 = Normal mode, 1 = Reverse mode // [4] = ML = Line Address Order, 0 = LCD refresh from top to bottom, 1 = Bottom to top // [3] = RGB = RGB/BGR Order, 0 = RGB, 1 = BGR // [2] = MH = Display Data Latch Order, 0 = LCD refresh from left to right, 1 = Right to left // [0 .. 1] = Unused WriteData(0b01000000); #else WriteData(0x00); #endif } void St7789::ColumnAddressSet() { WriteCommand(static_cast(Commands::ColumnAddressSet)); WriteData(0x00); WriteData(0x00); WriteData(Width >> 8u); WriteData(Width & 0xffu); } void St7789::RowAddressSet() { WriteCommand(static_cast(Commands::RowAddressSet)); WriteData(0x00); WriteData(0x00); WriteData(320u >> 8u); WriteData(320u & 0xffu); } void St7789::DisplayInversionOn() { WriteCommand(static_cast(Commands::DisplayInversionOn)); nrf_delay_ms(10); } void St7789::NormalModeOn() { WriteCommand(static_cast(Commands::NormalModeOn)); nrf_delay_ms(10); } void St7789::DisplayOn() { WriteCommand(static_cast(Commands::DisplayOn)); } void St7789::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { WriteCommand(static_cast(Commands::ColumnAddressSet)); WriteData(x0 >> 8); WriteData(x0 & 0xff); WriteData(x1 >> 8); WriteData(x1 & 0xff); WriteCommand(static_cast(Commands::RowAddressSet)); WriteData(y0 >> 8); WriteData(y0 & 0xff); WriteData(y1 >> 8); WriteData(y1 & 0xff); WriteToRam(); } void St7789::WriteToRam() { WriteCommand(static_cast(Commands::WriteToRam)); } void St7789::SetVdv() { // By default there is a large step from pixel brightness zero to one. // After experimenting with VCOMS, VRH and VDV, this was found to produce good results. WriteCommand(static_cast(Commands::VdvSet)); WriteData(0x10); } void St7789::DisplayOff() { WriteCommand(static_cast(Commands::DisplayOff)); nrf_delay_ms(500); } void St7789::VerticalScrollDefinition(uint16_t topFixedLines, uint16_t scrollLines, uint16_t bottomFixedLines) { WriteCommand(static_cast(Commands::VerticalScrollDefinition)); WriteData(topFixedLines >> 8u); WriteData(topFixedLines & 0x00ffu); WriteData(scrollLines >> 8u); WriteData(scrollLines & 0x00ffu); WriteData(bottomFixedLines >> 8u); WriteData(bottomFixedLines & 0x00ffu); } void St7789::VerticalScrollStartAddress(uint16_t line) { verticalScrollingStartAddress = line; WriteCommand(static_cast(Commands::VerticalScrollStartAddress)); WriteData(line >> 8u); WriteData(line & 0x00ffu); } void St7789::Uninit() { } void St7789::DrawPixel(uint16_t x, uint16_t y, uint32_t color) { if (x >= Width || y >= Height) { return; } SetAddrWindow(x, y, x + 1, y + 1); nrf_gpio_pin_set(pinDataCommand); WriteSpi(reinterpret_cast(&color), 2); } 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); nrf_gpio_pin_set(pinDataCommand); WriteSpi(data, size); } void St7789::HardwareReset() { nrf_gpio_pin_clear(26); nrf_delay_ms(10); nrf_gpio_pin_set(26); } void St7789::Sleep() { SleepIn(); nrf_gpio_cfg_default(pinDataCommand); nrf_gpio_cfg_default(26); NRF_LOG_INFO("[LCD] Sleep"); } void St7789::Wakeup() { nrf_gpio_cfg_output(pinDataCommand); SleepOut(); VerticalScrollStartAddress(verticalScrollingStartAddress); DisplayOn(); NRF_LOG_INFO("[LCD] Wakeup") }