From eb7a1b3ac9cbacb74afb7fcd1d40c51a18c90060 Mon Sep 17 00:00:00 2001 From: JF Date: Wed, 22 Jan 2020 21:08:53 +0100 Subject: [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/drivers/SpiMaster.cpp | 100 +++++++++++++++++++++++++++++++--------------- src/drivers/SpiMaster.h | 13 +++--- src/drivers/St7789.cpp | 9 +++-- src/drivers/St7789.h | 4 +- 4 files changed, 82 insertions(+), 44 deletions(-) (limited to 'src/drivers') 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; - - bufferSize -= currentSize; - bufferAddr += currentSize; + if(repeat > 0) + NRF_SPIM0->SHORTS = (1<<17); - NRF_SPIM0->RXD.PTR = (uint32_t) 0; - NRF_SPIM0->RXD.MAXCNT = 0; - NRF_SPIM0->RXD.LIST = 0; + auto currentSize = std::min((size_t)255, bufferSize); + NRF_SPIM0->TXD.PTR = bufferAddr; + NRF_SPIM0->TXD.MAXCNT = currentSize; + NRF_SPIM0->TXD.LIST = 0; - if(size != 1) { - NRF_SPIM0->EVENTS_END = 0; - } + currentBufferSize -= currentSize; + currentBufferAddr += currentSize; - NRF_SPIM0->TASKS_START = 1; + 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; - 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, -- cgit v1.2.3