diff --git a/CMakeLists.txt b/CMakeLists.txt index 063decbe..21c63797 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(pinetime VERSION 0.2.0 LANGUAGES C CXX ASM) +project(pinetime VERSION 0.2.99 LANGUAGES C CXX ASM) set(NRF_TARGET "nrf52") diff --git a/src/Components/Gfx/Gfx.cpp b/src/Components/Gfx/Gfx.cpp index 9e680687..6c19518a 100644 --- a/src/Components/Gfx/Gfx.cpp +++ b/src/Components/Gfx/Gfx.cpp @@ -11,11 +11,21 @@ void Gfx::Init() { } void Gfx::ClearScreen() { - lcd.FillRectangle(0, 0, width, height, 0x0000); + SetBackgroundColor(0x0000); + lcd.BeginDrawBuffer(0, 0, width, height); + for(int i = 0; i < height; i++) { + lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2); + } + lcd.EndDrawBuffer(); } void Gfx::FillRectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint16_t color) { - lcd.FillRectangle(x, y, width, height, color); + SetBackgroundColor(color); + lcd.BeginDrawBuffer(0, 0, width, height); + for(int i = 0; i < height; i++) { + lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2); + } + lcd.EndDrawBuffer(); } void Gfx::DrawString(uint8_t x, uint8_t y, uint16_t color, const char *text, const FONT_INFO *p_font, bool wrap) { @@ -70,15 +80,15 @@ void Gfx::DrawChar(const FONT_INFO *font, uint8_t c, uint8_t *x, uint8_t y, uint for (uint16_t i = 0; i < font->height; i++) { for (uint16_t j = 0; j < bytes_in_line; j++) { for (uint8_t k = 0; k < 8; k++) { - if ((1 << (7 - k)) & - font->data[font->charInfo[char_idx].offset + i * bytes_in_line + j]) { - lcd.NextDrawBuffer(reinterpret_cast(&color), 2); + if ((1 << (7 - k)) & font->data[font->charInfo[char_idx].offset + i * bytes_in_line + j]) { + buffer[(j*8)+k] = color; } else { - lcd.NextDrawBuffer(reinterpret_cast(&bg), 2); + buffer[(j*8)+k] = bg; } } } + lcd.NextDrawBuffer(reinterpret_cast(&buffer), bytes_in_line*8*2); } lcd.EndDrawBuffer(); *x += font->charInfo[char_idx].widthBits + font->spacePixels; @@ -96,4 +106,10 @@ void Gfx::Wakeup() { lcd.Wakeup(); } +void Gfx::SetBackgroundColor(uint16_t color) { + for(int i = 0; i < width; i++) { + buffer[i] = color; + } +} + diff --git a/src/Components/Gfx/Gfx.h b/src/Components/Gfx/Gfx.h index 9bd07fee..d8728701 100644 --- a/src/Components/Gfx/Gfx.h +++ b/src/Components/Gfx/Gfx.h @@ -21,10 +21,14 @@ namespace Pinetime { void Wakeup(); private: + static constexpr uint8_t width = 240; + static constexpr uint8_t height = 240; + + uint16_t buffer[width]; // 1 line buffer Drivers::St7789& lcd; - const uint8_t width = 240; - const uint8_t height = 240; + void pixel_draw(uint8_t x, uint8_t y, uint16_t color); + void SetBackgroundColor(uint16_t color); }; } } diff --git a/src/DisplayApp/DisplayApp.cpp b/src/DisplayApp/DisplayApp.cpp index 3b7007af..29c75fa8 100644 --- a/src/DisplayApp/DisplayApp.cpp +++ b/src/DisplayApp/DisplayApp.cpp @@ -31,8 +31,8 @@ DisplayApp::DisplayApp(Controllers::Battery &batteryController, batteryController{batteryController}, bleController{bleController}, dateTimeController{dateTimeController}, - clockScreen{*(gfx.get())}/*, - messageScreen{*(gfx.get())}*/ { + clockScreen{*(gfx.get())}, + messageScreen{*(gfx.get())} { msgQueue = xQueueCreate(queueSize, itemSize); currentScreen = &clockScreen; } @@ -121,16 +121,20 @@ void DisplayApp::Refresh() { void DisplayApp::RunningState() { clockScreen.SetCurrentDateTime(dateTimeController.CurrentDateTime()); +// if(currentScreen != nullptr) { +// currentScreen->Refresh(false); +// } + if(currentScreen != nullptr) { - currentScreen->Refresh(false); + currentScreen->Refresh(true); } -// if(screenState) { -// currentScreen = &clockScreen; -// } else { -// currentScreen = &messageScreen; -// } -// screenState = !screenState; + if(screenState) { + currentScreen = &clockScreen; + } else { + currentScreen = &messageScreen; + } + screenState = !screenState; } @@ -153,7 +157,7 @@ void DisplayApp::OnTouchEvent() { auto info = touchPanel.GetTouchInfo(); if(info.isTouch) { - lcd->FillRectangle(info.x-10, info.y-10, 20,20, pointColor); + gfx->FillRectangle(info.x-10, info.y-10, 20,20, pointColor); pointColor+=10; } } diff --git a/src/DisplayApp/DisplayApp.h b/src/DisplayApp/DisplayApp.h index 5fb8f6f8..eabfe099 100644 --- a/src/DisplayApp/DisplayApp.h +++ b/src/DisplayApp/DisplayApp.h @@ -57,8 +57,8 @@ namespace Pinetime { Screens::Clock clockScreen; Screens::Screen* currentScreen = nullptr; -// Screens::Message messageScreen; -// bool screenState = false; + Screens::Message messageScreen; + bool screenState = false; static constexpr uint8_t pinSpiSck = 2; static constexpr uint8_t pinSpiMosi = 3; static constexpr uint8_t pinSpiMiso = 4; diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index 42d3d77b..e8130c76 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -1,6 +1,7 @@ #include +#include #include "SpiMaster.h" - +#include using namespace Pinetime::Drivers; SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters ¶ms) : @@ -9,22 +10,24 @@ SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters bool SpiMaster::Init() { /* Configure GPIO pins used for pselsck, pselmosi, pselmiso and pselss for SPI0 */ + nrf_gpio_pin_set(params.pinSCK); nrf_gpio_cfg_output(params.pinSCK); + nrf_gpio_pin_clear(params.pinMOSI); nrf_gpio_cfg_output(params.pinMOSI); nrf_gpio_cfg_input(params.pinMISO, NRF_GPIO_PIN_NOPULL); nrf_gpio_cfg_output(params.pinCSN); pinCsn = params.pinCSN; switch(spi) { - case SpiModule::SPI0: spiBaseAddress = NRF_SPI0; break; - case SpiModule::SPI1: spiBaseAddress = NRF_SPI1; break; + case SpiModule::SPI0: spiBaseAddress = NRF_SPIM0; break; + case SpiModule::SPI1: spiBaseAddress = NRF_SPIM1; break; default: return false; } /* Configure pins, frequency and mode */ - spiBaseAddress->PSELSCK = params.pinSCK; - spiBaseAddress->PSELMOSI = params.pinMOSI; - spiBaseAddress->PSELMISO = params.pinMISO; + NRF_SPIM0->PSELSCK = params.pinSCK; + NRF_SPIM0->PSELMOSI = params.pinMOSI; + NRF_SPIM0->PSELMISO = params.pinMISO; nrf_gpio_pin_set(pinCsn); /* disable Set slave select (inactive high) */ uint32_t frequency; @@ -32,7 +35,7 @@ bool SpiMaster::Init() { case Frequencies::Freq8Mhz: frequency = 0x80000000; break; default: return false; } - spiBaseAddress->FREQUENCY = frequency; + NRF_SPIM0->FREQUENCY = frequency; uint32_t regConfig = 0; switch(params.bitOrder) { @@ -48,14 +51,21 @@ bool SpiMaster::Init() { default: return false; } - spiBaseAddress->CONFIG = regConfig; - spiBaseAddress->EVENTS_READY = 0; - spiBaseAddress->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos); + setup_workaround_for_ftpan_58(NRF_SPIM0, 0, 0); + + NRF_SPIM0->CONFIG = regConfig; + NRF_SPIM0->EVENTS_ENDRX = 0; + NRF_SPIM0->EVENTS_ENDTX = 0; + NRF_SPIM0->EVENTS_END = 0; + NRF_SPI0->EVENTS_READY = 0; + NRF_SPI0->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos); + NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); return true; } -bool SpiMaster::Write(const uint8_t *data, size_t size) { +bool SpiMaster::WriteFast(const uint8_t *data, size_t size) { + auto spi = reinterpret_cast(spiBaseAddress); volatile uint32_t dummyread; if(data == nullptr) return false; @@ -63,27 +73,27 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) { /* enable slave (slave select active low) */ nrf_gpio_pin_clear(pinCsn); - spiBaseAddress->EVENTS_READY = 0; + NRF_SPI0->EVENTS_READY = 0; - spiBaseAddress->TXD = (uint32_t)*data++; + NRF_SPI0->TXD = (uint32_t)*data++; while(--size) { - spiBaseAddress->TXD = (uint32_t)*data++; + NRF_SPI0->TXD = (uint32_t)*data++; /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */ - while (spiBaseAddress->EVENTS_READY == 0); + while (NRF_SPI0->EVENTS_READY == 0); /* clear the event to be ready to receive next messages */ - spiBaseAddress->EVENTS_READY = 0; + NRF_SPI0->EVENTS_READY = 0; - dummyread = spiBaseAddress->RXD; + dummyread = NRF_SPI0->RXD; } /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */ - while (spiBaseAddress->EVENTS_READY == 0); + while (NRF_SPI0->EVENTS_READY == 0); - dummyread = spiBaseAddress->RXD; + dummyread = NRF_SPI0->RXD; /* disable slave (slave select active low) */ nrf_gpio_pin_set(pinCsn); @@ -91,9 +101,68 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) { return true; } +void SpiMaster::setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel) { + // Create an event when SCK toggles. + NRF_GPIOTE->CONFIG[gpiote_channel] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | + (spim->PSEL.SCK << GPIOTE_CONFIG_PSEL_Pos) | + (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos); + + // Stop the spim instance when SCK toggles. + NRF_PPI->CH[ppi_channel].EEP = (uint32_t) &NRF_GPIOTE->EVENTS_IN[gpiote_channel]; + NRF_PPI->CH[ppi_channel].TEP = (uint32_t) &spim->TASKS_STOP; + NRF_PPI->CHENSET = 1U << ppi_channel; +} + +bool SpiMaster::Write(const uint8_t *data, size_t size) { + if(data == nullptr) return false; + + if(size == 1) { + setup_workaround_for_ftpan_58(NRF_SPIM0, 0,0); + } else { + NRF_GPIOTE->CONFIG[0] = 0; + NRF_PPI->CH[0].EEP = 0; + NRF_PPI->CH[0].TEP = 0; + NRF_PPI->CHENSET = 0; + } + + nrf_gpio_pin_clear(pinCsn); + auto spim = reinterpret_cast(spiBaseAddress); + + while(size > 0) { + auto currentSize = std::min((size_t)255, size); + size -= currentSize; + NRF_SPIM0->TXD.PTR = (uint32_t) data; + NRF_SPIM0->TXD.MAXCNT = currentSize; + NRF_SPIM0->TXD.LIST = 0; + + NRF_SPIM0->RXD.PTR = (uint32_t) 0; + NRF_SPIM0->RXD.MAXCNT = 0; + NRF_SPIM0->RXD.LIST = 0; + + NRF_SPIM0->EVENTS_END = 0; + + NRF_SPIM0->TASKS_START = 1; + + + while (NRF_SPIM0->EVENTS_END == 0); + } + + nrf_gpio_pin_set(pinCsn); + + return true; +} + +bool SpiMaster::GetStatusEnd() { + return (bool)*(volatile uint32_t *)((uint8_t *)spiBaseAddress + (uint32_t)NRF_SPIM_EVENT_END); +} + +bool SpiMaster::GetStatusStarted() { + return (bool)*(volatile uint32_t *)((uint8_t *)spiBaseAddress + (uint32_t)NRF_SPIM_EVENT_STARTED); +} + void SpiMaster::Sleep() { - while(NRF_SPI0->ENABLE != 0) { - NRF_SPI0->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos); + while(NRF_SPIM0->ENABLE != 0) { + NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos); } nrf_gpio_cfg_default(params.pinSCK); nrf_gpio_cfg_default(params.pinMOSI); diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index 073501a8..5376ac8e 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -24,12 +24,17 @@ namespace Pinetime { SpiMaster(const SpiModule spi, const Parameters& params); bool Init(); bool Write(const uint8_t* data, size_t size); + bool WriteFast(const uint8_t* data, size_t size); + void setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel); void Sleep(); void Wakeup(); + bool GetStatusEnd(); + bool GetStatusStarted(); + private: - NRF_SPI_Type * spiBaseAddress; + NRF_SPIM_Type * spiBaseAddress; uint8_t pinCsn; SpiMaster::SpiModule spi; diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp index ac813064..f47c2f58 100644 --- a/src/drivers/St7789.cpp +++ b/src/drivers/St7789.cpp @@ -38,7 +38,7 @@ void St7789::WriteData(uint8_t data) { void St7789::WriteSpi(const uint8_t* data, size_t size) { - spi.Write(data, size); + spi.Write(data, size); } void St7789::SoftwareReset() { @@ -95,20 +95,6 @@ void St7789::DisplayOn() { WriteCommand(static_cast(Commands::DisplayOn)); } -void St7789::FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color) { - BeginDrawBuffer(x, y, width, height); - - uint32_t c = color + (color << 16); - uint8_t w = width/2; - - for(y=height+ST7789_ROW_OFFSET; y>ST7789_ROW_OFFSET; y--) { - for(x=w; x>0; x--) { - NextDrawBuffer(reinterpret_cast(&c), 4); - } - } - EndDrawBuffer(); -} - void St7789::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { WriteCommand(static_cast(Commands::ColumnAddressSet)); WriteData(x0 >> 8); @@ -160,7 +146,7 @@ void St7789::EndDrawBuffer() { } void St7789::NextDrawBuffer(const uint8_t *data, size_t size) { - spi.Write(data, size); + WriteSpi(data, size); } void St7789::HardwareReset() { diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h index a32a96f9..8e4690b0 100644 --- a/src/drivers/St7789.h +++ b/src/drivers/St7789.h @@ -10,7 +10,6 @@ namespace Pinetime { void Init(); void Uninit(); void DrawPixel(uint16_t x, uint16_t y, uint32_t color); - void FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color); void BeginDrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height); void NextDrawBuffer(const uint8_t* data, size_t size);