From eb7a1b3ac9cbacb74afb7fcd1d40c51a18c90060 Mon Sep 17 00:00:00 2001 From: JF Date: Wed, 22 Jan 2020 21:08:53 +0100 Subject: [PATCH] [WIP] Max SPI speed reached (119ms for a full refresh. Theo max : 240*240*16 = 115.2ms) using IRQ and DMA. Code needs some cleaning before integration. --- src/Components/Gfx/Gfx.cpp | 4 +- src/DisplayApp/DisplayApp.cpp | 22 ++++++++ src/drivers/SpiMaster.cpp | 100 +++++++++++++++++++++++----------- src/drivers/SpiMaster.h | 13 +++-- src/drivers/St7789.cpp | 9 +-- src/drivers/St7789.h | 4 +- src/main.cpp | 7 ++- src/sdk_config.h | 6 +- 8 files changed, 114 insertions(+), 51 deletions(-) diff --git a/src/Components/Gfx/Gfx.cpp b/src/Components/Gfx/Gfx.cpp index 6c19518a..94106513 100644 --- a/src/Components/Gfx/Gfx.cpp +++ b/src/Components/Gfx/Gfx.cpp @@ -22,9 +22,7 @@ void Gfx::ClearScreen() { void Gfx::FillRectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint16_t color) { SetBackgroundColor(color); lcd.BeginDrawBuffer(0, 0, width, height); - for(int i = 0; i < height; i++) { - lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2); - } + lcd.NextDrawBuffer(reinterpret_cast(buffer), width * 2, 240); lcd.EndDrawBuffer(); } diff --git a/src/DisplayApp/DisplayApp.cpp b/src/DisplayApp/DisplayApp.cpp index 29c75fa8..c1561cc2 100644 --- a/src/DisplayApp/DisplayApp.cpp +++ b/src/DisplayApp/DisplayApp.cpp @@ -65,7 +65,28 @@ void DisplayApp::InitHw() { touchPanel.Init(); } +uint32_t acc = 0; +uint32_t count = 0; +bool toggle = true; void DisplayApp::Refresh() { + + uint32_t before = nrf_rtc_counter_get(portNRF_RTC_REG); + if(toggle) { + gfx->FillRectangle(0,0,240,240,0x0000); + } else { + gfx->FillRectangle(0,0,240,240,0xffff); + } + uint32_t after = nrf_rtc_counter_get(portNRF_RTC_REG); + + acc += (after - before); + if((count % 10) == 0) { + NRF_LOG_INFO("DRAW : %d ms", (uint32_t)(acc/10)); + acc = 0; + } + count++; + toggle = !toggle; + +#if 0 TickType_t queueTimeout; switch (state) { case States::Idle: @@ -116,6 +137,7 @@ void DisplayApp::Refresh() { break; } } +#endif } void DisplayApp::RunningState() { diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index f7e64db6..7c6186a6 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -62,6 +62,7 @@ bool SpiMaster::Init() { NRF_SPIM0->INTENSET = ((unsigned)1 << (unsigned)6); NRF_SPIM0->INTENSET = ((unsigned)1 << (unsigned)1); + NRF_SPIM0->INTENSET = ((unsigned)1 << (unsigned)19); NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); @@ -83,34 +84,61 @@ void SpiMaster::setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_ NRF_PPI->CHENSET = 1U << ppi_channel; } - - -void SpiMaster::irq() { +void SpiMaster::irqStarted() { if(busy) { - if(bufferSize > 0) { - auto currentSize = std::min((size_t)255, bufferSize); + auto s = currentBufferSize; + if(s > 0) { + auto currentSize = std::min((size_t)255, s); - NRF_SPIM0->TXD.PTR = (uint32_t) bufferAddr; + NRF_SPIM0->TXD.PTR = (uint32_t) currentBufferAddr; NRF_SPIM0->TXD.MAXCNT = currentSize; NRF_SPIM0->TXD.LIST = 0; - bufferAddr += currentSize; - bufferSize -= currentSize; + currentBufferAddr += currentSize; + currentBufferSize -= currentSize; NRF_SPIM0->RXD.PTR = (uint32_t) 0; NRF_SPIM0->RXD.MAXCNT = 0; NRF_SPIM0->RXD.LIST = 0; - NRF_SPIM0->TASKS_START = 1; + + if(repeat == 0) + NRF_SPIM0->SHORTS = 0; return; }else { + if(repeat > 0) { + repeat = repeat -1; + + currentBufferAddr = bufferAddr; + currentBufferSize = bufferSize; + s = currentBufferSize; + auto currentSize = std::min((size_t)255, s); + NRF_SPIM0->TXD.PTR = (uint32_t) currentBufferAddr; + NRF_SPIM0->TXD.MAXCNT = currentSize; + NRF_SPIM0->TXD.LIST = 0; + + currentBufferAddr += currentSize; + currentBufferSize -= currentSize; + + NRF_SPIM0->RXD.PTR = (uint32_t) 0; + NRF_SPIM0->RXD.MAXCNT = 0; + NRF_SPIM0->RXD.LIST = 0; + } + } + } +} + +void SpiMaster::irqEnd() { + if(busy) { + if(repeat == 0 && currentBufferSize == 0) { nrf_gpio_pin_set(pinCsn); busy = false; } } } -bool SpiMaster::Write(const uint8_t *data, size_t size) { + +bool SpiMaster::Write(const uint8_t *data, size_t size, size_t r) { if(data == nullptr) return false; while(busy) { @@ -121,7 +149,7 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) { setup_workaround_for_ftpan_58(NRF_SPIM0, 0,0); NRF_SPIM0->INTENCLR = (1<<6); NRF_SPIM0->INTENCLR = (1<<1); - + NRF_SPIM0->INTENCLR = (1<<19); } else { NRF_GPIOTE->CONFIG[0] = 0; NRF_PPI->CH[0].EEP = 0; @@ -129,38 +157,38 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) { NRF_PPI->CHENSET = 0; NRF_SPIM0->INTENSET = (1<<6); NRF_SPIM0->INTENSET = (1<<1); + NRF_SPIM0->INTENSET = (1<<19); } nrf_gpio_pin_clear(pinCsn); - bufferAddr = (uint32_t)data; - bufferSize = size; + currentBufferAddr = bufferAddr = (uint32_t)data; + currentBufferSize = bufferSize = size; + repeat = r; busy = true; -// while(size > 0) { - auto currentSize = std::min((size_t)255, bufferSize); - NRF_SPIM0->TXD.PTR = (uint32_t) data; - NRF_SPIM0->TXD.MAXCNT = currentSize; - NRF_SPIM0->TXD.LIST = 0; + if(repeat > 0) + NRF_SPIM0->SHORTS = (1<<17); - bufferSize -= currentSize; - bufferAddr += currentSize; + auto currentSize = std::min((size_t)255, bufferSize); + NRF_SPIM0->TXD.PTR = bufferAddr; + 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; + currentBufferSize -= currentSize; + currentBufferAddr += currentSize; - if(size != 1) { - NRF_SPIM0->EVENTS_END = 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; - NRF_SPIM0->TASKS_START = 1; - - if(size == 1) { - while (NRF_SPIM0->EVENTS_END == 0); - busy = false; - nrf_gpio_pin_set(pinCsn); - } + if(size == 1) { + while (NRF_SPIM0->EVENTS_END == 0); + busy = false; + nrf_gpio_pin_set(pinCsn); + } return true; @@ -187,3 +215,9 @@ void SpiMaster::Sleep() { void SpiMaster::Wakeup() { Init(); } + +void SpiMaster::Wait() { + while(busy) { + asm("nop"); + } +} diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index dff63e94..ee03186c 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -23,9 +23,9 @@ namespace Pinetime { SpiMaster(const SpiModule spi, const Parameters& params); bool Init(); - bool Write(const uint8_t* data, size_t size); - bool WriteRepeat(const uint8_t *data, size_t size, int repeat); + bool Write(const uint8_t* data, size_t size, size_t r = 0); void setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel); + void Wait(); void Sleep(); void Wakeup(); @@ -33,7 +33,8 @@ namespace Pinetime { bool GetStatusEnd(); bool GetStatusStarted(); - void irq(); + void irqEnd(); + void irqStarted(); private: NRF_SPIM_Type * spiBaseAddress; @@ -42,11 +43,13 @@ namespace Pinetime { SpiMaster::SpiModule spi; SpiMaster::Parameters params; - std::atomic busy {false}; + volatile bool busy = false; uint32_t bufferAddr = 0; - + volatile uint32_t currentBufferAddr = 0; size_t bufferSize = 0; + volatile size_t currentBufferSize = 0; + volatile uint32_t repeat = 0; }; } } diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp index f47c2f58..6b663132 100644 --- a/src/drivers/St7789.cpp +++ b/src/drivers/St7789.cpp @@ -37,8 +37,8 @@ void St7789::WriteData(uint8_t data) { } -void St7789::WriteSpi(const uint8_t* data, size_t size) { - spi.Write(data, size); +void St7789::WriteSpi(const uint8_t* data, size_t size, size_t repeat) { + spi.Write(data, size, repeat); } void St7789::SoftwareReset() { @@ -143,10 +143,11 @@ void St7789::BeginDrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t he } void St7789::EndDrawBuffer() { + spi.Wait(); } -void St7789::NextDrawBuffer(const uint8_t *data, size_t size) { - WriteSpi(data, size); +void St7789::NextDrawBuffer(const uint8_t *data, size_t size, size_t repeat) { + WriteSpi(data, size, repeat); } void St7789::HardwareReset() { diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h index 8e4690b0..eef051b7 100644 --- a/src/drivers/St7789.h +++ b/src/drivers/St7789.h @@ -12,7 +12,7 @@ namespace Pinetime { void DrawPixel(uint16_t x, uint16_t y, uint32_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); + void NextDrawBuffer(const uint8_t* data, size_t size, size_t repeat = 0); void EndDrawBuffer(); void DisplayOn(); @@ -40,7 +40,7 @@ namespace Pinetime { void SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); void WriteCommand(uint8_t cmd); - void WriteSpi(const uint8_t* data, size_t size); + void WriteSpi(const uint8_t* data, size_t size, size_t repeat = 0); enum class Commands : uint8_t { SoftwareReset = 0x01, diff --git a/src/main.cpp b/src/main.cpp index 14be5ca2..284113c1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -162,7 +162,12 @@ extern Pinetime::Drivers::SpiMaster* spiInstance; void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) { if(((NRF_SPIM0->INTENSET & (1<<6)) != 0) && NRF_SPIM0->EVENTS_END == 1) { NRF_SPIM0->EVENTS_END = 0; - spiInstance->irq(); + spiInstance->irqEnd(); + } + + if(((NRF_SPIM0->INTENSET & (1<<19)) != 0) && NRF_SPIM0->EVENTS_STARTED == 1) { + NRF_SPIM0->EVENTS_STARTED = 0; + spiInstance->irqStarted(); } diff --git a/src/sdk_config.h b/src/sdk_config.h index 21363202..e74751ef 100644 --- a/src/sdk_config.h +++ b/src/sdk_config.h @@ -8452,15 +8452,15 @@ // NRF_LOG_ENABLED - nrf_log - Logger //========================================================== #ifndef NRF_LOG_ENABLED -#define NRF_LOG_ENABLED 0 +#define NRF_LOG_ENABLED 1 #endif #ifndef NRF_LOG_BACKEND_RTT_ENABLED -#define NRF_LOG_BACKEND_RTT_ENABLED 0 +#define NRF_LOG_BACKEND_RTT_ENABLED 1 #endif #ifndef NRF_LOG_BACKEND_SERIAL_USES_RTT -#define NRF_LOG_BACKEND_SERIAL_USES_RTT 0 +#define NRF_LOG_BACKEND_SERIAL_USES_RTT 1 #endif // Log message pool - Configuration of log message pool