summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorJF <jf@codingfield.com>2020-01-26 13:37:10 +0100
committerJF <jf@codingfield.com>2020-01-26 13:37:10 +0100
commit5fa4f5abe0b752bb2d990378e02d6424a1d1b661 (patch)
treebc2e731c488573d678aec1d388a00f754b24fb02 /src/drivers
parenteb7a1b3ac9cbacb74afb7fcd1d40c51a18c90060 (diff)
Better integration of SPI with DMA and IRQ. Using only 'End' IRQ. Perf could be improved by using 'Started' IRQ to prepare the next buffer while the current one is beeing sent.
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/BufferProvider.h11
-rw-r--r--src/drivers/SpiMaster.cpp101
-rw-r--r--src/drivers/SpiMaster.h21
-rw-r--r--src/drivers/St7789.cpp14
-rw-r--r--src/drivers/St7789.h11
5 files changed, 64 insertions, 94 deletions
diff --git a/src/drivers/BufferProvider.h b/src/drivers/BufferProvider.h
new file mode 100644
index 00000000..50fa253e
--- /dev/null
+++ b/src/drivers/BufferProvider.h
@@ -0,0 +1,11 @@
+#pragma once
+#include <cstddef>
+
+namespace Pinetime {
+ namespace Drivers {
+ class BufferProvider {
+ public:
+ virtual bool GetNextBuffer(uint8_t** buffer, size_t& size) = 0;
+ };
+ }
+} \ No newline at end of file
diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp
index 7c6186a6..84243a96 100644
--- a/src/drivers/SpiMaster.cpp
+++ b/src/drivers/SpiMaster.cpp
@@ -4,10 +4,9 @@
#include <algorithm>
using namespace Pinetime::Drivers;
-SpiMaster* spiInstance;
SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters &params) :
spi{spi}, params{params} {
- spiInstance = this;
+
}
bool SpiMaster::Init() {
@@ -84,12 +83,33 @@ void SpiMaster::setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_
NRF_PPI->CHENSET = 1U << ppi_channel;
}
-void SpiMaster::irqStarted() {
- if(busy) {
- auto s = currentBufferSize;
- if(s > 0) {
- auto currentSize = std::min((size_t)255, s);
+void SpiMaster::OnEndEvent(BufferProvider& provider) {
+ if(!busy) return;
+
+ auto s = currentBufferSize;
+ if(s > 0) {
+ 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;
+
+ NRF_SPIM0->TASKS_START = 1;
+ } else {
+ uint8_t* buffer = nullptr;
+ size_t size = 0;
+ if(provider.GetNextBuffer(&buffer, size)) {
+ currentBufferAddr = (uint32_t) buffer;
+ currentBufferSize = size;
+ auto 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;
@@ -101,44 +121,19 @@ void SpiMaster::irqStarted() {
NRF_SPIM0->RXD.MAXCNT = 0;
NRF_SPIM0->RXD.LIST = 0;
- 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);
+ NRF_SPIM0->TASKS_START = 1;
+ } else {
busy = false;
+ nrf_gpio_pin_set(pinCsn);
}
}
}
+void SpiMaster::OnStartedEvent(BufferProvider& provider) {
+ if(!busy) return;
+}
-bool SpiMaster::Write(const uint8_t *data, size_t size, size_t r) {
+bool SpiMaster::Write(const uint8_t *data, size_t size) {
if(data == nullptr) return false;
while(busy) {
@@ -162,16 +157,12 @@ bool SpiMaster::Write(const uint8_t *data, size_t size, size_t r) {
nrf_gpio_pin_clear(pinCsn);
- currentBufferAddr = bufferAddr = (uint32_t)data;
- currentBufferSize = bufferSize = size;
- repeat = r;
+ currentBufferAddr = (uint32_t)data;
+ currentBufferSize = size;
busy = true;
- if(repeat > 0)
- NRF_SPIM0->SHORTS = (1<<17);
-
- auto currentSize = std::min((size_t)255, bufferSize);
- NRF_SPIM0->TXD.PTR = bufferAddr;
+ auto currentSize = std::min((size_t)255, (size_t)currentBufferSize);
+ NRF_SPIM0->TXD.PTR = currentBufferAddr;
NRF_SPIM0->TXD.MAXCNT = currentSize;
NRF_SPIM0->TXD.LIST = 0;
@@ -187,21 +178,11 @@ bool SpiMaster::Write(const uint8_t *data, size_t size, size_t r) {
if(size == 1) {
while (NRF_SPIM0->EVENTS_END == 0);
busy = false;
- 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_SPIM0->ENABLE != 0) {
NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos);
@@ -216,8 +197,4 @@ void SpiMaster::Wakeup() {
Init();
}
-void SpiMaster::Wait() {
- while(busy) {
- asm("nop");
- }
-}
+
diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h
index ee03186c..7dac747a 100644
--- a/src/drivers/SpiMaster.h
+++ b/src/drivers/SpiMaster.h
@@ -3,6 +3,8 @@
#include <cstddef>
#include <array>
#include <atomic>
+
+#include "BufferProvider.h"
namespace Pinetime {
namespace Drivers {
class SpiMaster {
@@ -23,20 +25,17 @@ namespace Pinetime {
SpiMaster(const SpiModule spi, const Parameters& params);
bool Init();
- 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();
+ bool Write(const uint8_t* data, size_t size);
+
+ void OnStartedEvent(BufferProvider& provider);
+ void OnEndEvent(BufferProvider& provider);
void Sleep();
void Wakeup();
- bool GetStatusEnd();
- bool GetStatusStarted();
-
- void irqEnd();
- void irqStarted();
-
private:
+ void setup_workaround_for_ftpan_58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel);
+
NRF_SPIM_Type * spiBaseAddress;
uint8_t pinCsn;
@@ -44,12 +43,8 @@ namespace Pinetime {
SpiMaster::Parameters params;
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 6b663132..39595dc9 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, size_t repeat) {
- spi.Write(data, size, repeat);
+void St7789::WriteSpi(const uint8_t* data, size_t size) {
+ spi.Write(data, size);
}
void St7789::SoftwareReset() {
@@ -142,12 +142,8 @@ void St7789::BeginDrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t he
nrf_gpio_pin_set(pinDataCommand);
}
-void St7789::EndDrawBuffer() {
- spi.Wait();
-}
-
-void St7789::NextDrawBuffer(const uint8_t *data, size_t size, size_t repeat) {
- WriteSpi(data, size, repeat);
+void St7789::NextDrawBuffer(const uint8_t *data, size_t size) {
+ WriteSpi(data, size);
}
void St7789::HardwareReset() {
@@ -178,5 +174,3 @@ void St7789::Wakeup() {
NormalModeOn();
DisplayOn();
}
-
-
diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h
index eef051b7..9ecf9f27 100644
--- a/src/drivers/St7789.h
+++ b/src/drivers/St7789.h
@@ -12,16 +12,13 @@ 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, size_t repeat = 0);
- void EndDrawBuffer();
+ void NextDrawBuffer(const uint8_t* data, size_t size);
void DisplayOn();
void DisplayOff();
void Sleep();
void Wakeup();
-
-
private:
SpiMaster& spi;
uint8_t pinDataCommand;
@@ -35,12 +32,9 @@ namespace Pinetime {
void DisplayInversionOn();
void NormalModeOn();
void WriteToRam();
-
-
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, size_t repeat = 0);
+ void WriteSpi(const uint8_t* data, size_t size);
enum class Commands : uint8_t {
SoftwareReset = 0x01,
@@ -62,7 +56,6 @@ namespace Pinetime {
static constexpr uint16_t Width = 240;
static constexpr uint16_t Height = 240;
void RowAddressSet();
-
};
}
}