From 8c7047549f8b2e2af5ae87c374f4a05cfa6e4e16 Mon Sep 17 00:00:00 2001 From: AndrewCapon Date: Sun, 28 Apr 2024 09:06:00 +0100 Subject: [PATCH 1/7] Add SSD1307Driver --- src/dev/oled_ssd130x.h | 169 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) diff --git a/src/dev/oled_ssd130x.h b/src/dev/oled_ssd130x.h index ee2b354f8..19182f27f 100644 --- a/src/dev/oled_ssd130x.h +++ b/src/dev/oled_ssd130x.h @@ -457,6 +457,175 @@ using SSD130xI2c64x32Driver = daisy::SSD130xDriver<64, 32, SSD130xI2CTransport>; using SSD130x4WireSoftSpi128x64Driver = daisy::SSD130xDriver<128, 64, SSD130x4WireSoftSpiTransport>; + +/** + * A driver implementation for the SSD1307 + */ +template +class SSD1307Driver +{ + public: + struct Config + { + typename Transport::Config transport_config; + }; + + void Init(Config config) + { + transport_.Init(config.transport_config); + + // Init routine... + uint8_t uDispayOffset; + uint8_t uMultiplex; + switch(height) + { + case 64: + uDispayOffset = 0x60; + uMultiplex = 0x7F; + break; + + case 80: + uDispayOffset = 0x68; + uMultiplex = 0x4F; + break; + + case 128: + default: + uDispayOffset = 0x00; + uMultiplex = 0x7F; + break; + } + + // Display Off + transport_.SendCommand(0xaE); + + // Memory Mode + transport_.SendCommand(0x20); + + // Normal Display + transport_.SendCommand(0xA6); + + // Multiplex Ratio + transport_.SendCommand(0xA8); + transport_.SendCommand(uMultiplex); + + // All On Resume + transport_.SendCommand(0xA4); + + // Display Offset + transport_.SendCommand(0xD3); + transport_.SendCommand(uDispayOffset); + + // Display Clock Divide Ratio + transport_.SendCommand(0xD5); + transport_.SendCommand(0x80); + + // Pre Charge + transport_.SendCommand(0xD9); + transport_.SendCommand(0x22); + + // Com Pins + transport_.SendCommand(0xDA); + transport_.SendCommand(0x12); + + // VCOM Detect + transport_.SendCommand(0xDB); + transport_.SendCommand(0x35); + + // Contrast Control + transport_.SendCommand(0x81); + transport_.SendCommand(0x80); + + // Display On + transport_.SendCommand(0xAF); + + }; + + size_t Width() const { return width; }; + size_t Height() const { return height; }; + + void DrawPixel(uint_fast8_t x, uint_fast8_t y, bool on) + { + if(x >= width || y >= height) + return; + if(on) + buffer_[x + (y / 8) * width] |= (1 << (y % 8)); + else + buffer_[x + (y / 8) * width] &= ~(1 << (y % 8)); + } + + void Fill(bool on) + { + for(size_t i = 0; i < sizeof(buffer_); i++) + { + buffer_[i] = on ? 0xff : 0x00; + } + }; + + /** + * Update the display + */ + void Update() + { + uint8_t i; + uint8_t high_column_addr; + switch(height) + { + case 32: high_column_addr = 0x12; break; + + default: high_column_addr = 0x10; break; + } + for(i = 0; i < (height / 8); i++) + { + transport_.SendCommand(0xB0 + i); + transport_.SendCommand(0x00); + transport_.SendCommand(high_column_addr); + transport_.SendData(&buffer_[width * i], width); + } + }; + + private: + Transport transport_; + uint8_t buffer_[width * height / 8]; +}; + +/** + * A driver for the SSD1307 128x64 OLED displays connected via 4 wire SPI + */ +using SSD13074WireSpi128x64Driver + = daisy::SSD1307Driver<128, 64, SSD130x4WireSpiTransport>; + +/** + * A driver for the SSD1307 128x80 OLED displays connected via 4 wire SPI + */ +using SSD13074WireSpi128x80Driver + = daisy::SSD1307Driver<128, 80, SSD130x4WireSpiTransport>; + +/** + * A driver for the SSD1307 128x128 OLED displays connected via 4 wire SPI + */ +using SSD13074WireSpi128x128Driver + = daisy::SSD1307Driver<128, 128, SSD130x4WireSpiTransport>; + +/** + * A driver for the SSD1307 128x64 OLED displays connected via I2C + */ +using SSD1307I2c128x64Driver + = daisy::SSD130xDriver<128, 64, SSD130xI2CTransport>; + +/** + * A driver for the SSD1307 128x80 OLED displays connected via I2C + */ +using SSD1307I2c128x80Driver + = daisy::SSD1307Driver<128, 80, SSD130xI2CTransport>; + +/** + * A driver for the SSD1307 128x128 OLED displays connected via I2C + */ +using SSD1307I2c128x128Driver + = daisy::SSD130xDriver<128, 128, SSD130xI2CTransport>; + + }; // namespace daisy From a353229a5d61fe1610b334143def67b2731ff1f3 Mon Sep 17 00:00:00 2001 From: AndrewCapon Date: Sun, 28 Apr 2024 10:54:24 +0100 Subject: [PATCH 2/7] fix lint madness --- src/dev/oled_ssd130x.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dev/oled_ssd130x.h b/src/dev/oled_ssd130x.h index 19182f27f..dcfe25fcc 100644 --- a/src/dev/oled_ssd130x.h +++ b/src/dev/oled_ssd130x.h @@ -481,19 +481,19 @@ class SSD1307Driver { case 64: uDispayOffset = 0x60; - uMultiplex = 0x7F; - break; + uMultiplex = 0x7F; + break; case 80: uDispayOffset = 0x68; - uMultiplex = 0x4F; - break; + uMultiplex = 0x4F; + break; case 128: default: uDispayOffset = 0x00; - uMultiplex = 0x7F; - break; + uMultiplex = 0x7F; + break; } // Display Off From 65231b9560a9b49c552e2415ba7564a46717c613 Mon Sep 17 00:00:00 2001 From: AndrewCapon Date: Sun, 28 Apr 2024 10:56:36 +0100 Subject: [PATCH 3/7] fix even more lint madness --- src/dev/oled_ssd130x.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/dev/oled_ssd130x.h b/src/dev/oled_ssd130x.h index dcfe25fcc..cba017784 100644 --- a/src/dev/oled_ssd130x.h +++ b/src/dev/oled_ssd130x.h @@ -498,7 +498,7 @@ class SSD1307Driver // Display Off transport_.SendCommand(0xaE); - + // Memory Mode transport_.SendCommand(0x20); @@ -535,10 +535,9 @@ class SSD1307Driver // Contrast Control transport_.SendCommand(0x81); transport_.SendCommand(0x80); - + // Display On transport_.SendCommand(0xAF); - }; size_t Width() const { return width; }; From 765f4837c93c53f946403698ebe2b28fc7ab1711 Mon Sep 17 00:00:00 2001 From: AndrewCapon Date: Sun, 28 Apr 2024 11:02:21 +0100 Subject: [PATCH 4/7] fix even more lint madness --- src/dev/oled_ssd130x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dev/oled_ssd130x.h b/src/dev/oled_ssd130x.h index cba017784..7492897c3 100644 --- a/src/dev/oled_ssd130x.h +++ b/src/dev/oled_ssd130x.h @@ -498,7 +498,7 @@ class SSD1307Driver // Display Off transport_.SendCommand(0xaE); - + // Memory Mode transport_.SendCommand(0x20); From e11cb3157d4329e82007088f65c251f42e28ef0a Mon Sep 17 00:00:00 2001 From: AndrewCapon Date: Mon, 29 Apr 2024 12:35:06 +0100 Subject: [PATCH 5/7] Add DMA chained transfer data for SSD1307 --- src/dev/oled_ssd130x.h | 112 ++++++++++++++++++++++++++++++++---- src/hid/disp/display.h | 5 ++ src/hid/disp/oled_display.h | 2 + 3 files changed, 108 insertions(+), 11 deletions(-) diff --git a/src/dev/oled_ssd130x.h b/src/dev/oled_ssd130x.h index 7492897c3..e1a7bd7d1 100644 --- a/src/dev/oled_ssd130x.h +++ b/src/dev/oled_ssd130x.h @@ -6,6 +6,7 @@ #include "per/spi.h" #include "per/gpio.h" #include "sys/system.h" +#include "stm32h7xx_hal.h" namespace daisy { @@ -78,6 +79,7 @@ class SSD130x4WireSpiTransport dsy_gpio_pin dc; /**< & */ dsy_gpio_pin reset; /**< & */ } pin_config; + bool useDma; void Defaults() { // SPI peripheral config @@ -98,6 +100,8 @@ class SSD130x4WireSpiTransport // SSD130x control pin config pin_config.dc = {DSY_GPIOB, 4}; pin_config.reset = {DSY_GPIOB, 15}; + // Using DMA off by default + useDma = false; } }; void Init(const Config& config) @@ -119,18 +123,32 @@ class SSD130x4WireSpiTransport dsy_gpio_write(&pin_reset_, 1); System::Delay(10); }; + void SendCommand(uint8_t cmd) { dsy_gpio_write(&pin_dc_, 0); spi_.BlockingTransmit(&cmd, 1); }; + void SendCommands(uint8_t* buff, size_t size) + { + dsy_gpio_write(&pin_dc_, 0); + spi_.BlockingTransmit(buff, size); + }; + void SendData(uint8_t* buff, size_t size) { dsy_gpio_write(&pin_dc_, 1); spi_.BlockingTransmit(buff, size); }; + void SendDataDma(uint8_t* buff, size_t size, SpiHandle::EndCallbackFunctionPtr end_callback, void* context) + { + SCB_CleanInvalidateDCache_by_Addr(buff, size); + dsy_gpio_write(&pin_dc_, 1); + spi_.DmaTransmit(buff, size, NULL, end_callback, context); + }; + private: SpiHandle spi_; dsy_gpio pin_reset_; @@ -389,6 +407,14 @@ class SSD130xDriver } }; + /** + * Has update finished + */ + bool UpdateFinished() + { + return true; + } + protected: Transport transport_; uint8_t buffer_[width * height / 8]; @@ -474,6 +500,8 @@ class SSD1307Driver { transport_.Init(config.transport_config); + useDma_ = config.transport_config.useDma; + // Init routine... uint8_t uDispayOffset; uint8_t uMultiplex; @@ -566,26 +594,88 @@ class SSD1307Driver */ void Update() { - uint8_t i; - uint8_t high_column_addr; - switch(height) + if(useDma_) { - case 32: high_column_addr = 0x12; break; - - default: high_column_addr = 0x10; break; + transferPagesCount_ = (height / 8); + if(transferPagesCount_) + { + updateing_ = true; + TransferPageDma(0); + } } - for(i = 0; i < (height / 8); i++) + else { - transport_.SendCommand(0xB0 + i); - transport_.SendCommand(0x00); - transport_.SendCommand(high_column_addr); - transport_.SendData(&buffer_[width * i], width); + uint8_t i; + uint8_t high_column_addr; + switch(height) + { + case 32: high_column_addr = 0x12; break; + + default: high_column_addr = 0x10; break; + } + for(i = 0; i < (height / 8); i++) + { + transport_.SendCommand(0xB0 + i); + transport_.SendCommand(0x00); + transport_.SendCommand(high_column_addr); + transport_.SendData(&buffer_[width * i], width); + } + updateing_ = false; } }; + /** + * Has update finished + */ + bool UpdateFinished() + { + return !updateing_; + } + private: Transport transport_; uint8_t buffer_[width * height / 8]; + bool updateing_; + uint8_t transferPagesCount_; + uint8_t transferingPage_; + bool useDma_; + + void TransferPageDma(uint8_t page) + { + transferingPage_ = page; + + uint8_t high_column_addr; + switch(height) + { + case 32: high_column_addr = 0x12; break; + + default: high_column_addr = 0x10; break; + } + uint8_t commands[] = { static_cast(0xB0 + transferingPage_), 0x00, high_column_addr }; + transport_.SendCommands(commands, 3); + // transport_.SendCommand(0xB0 + transferingPage_); + // transport_.SendCommand(0x00); + // transport_.SendCommand(high_column_addr); + transport_.SendDataDma(&buffer_[width * transferingPage_], width, SpiPageCompleteCallback, this); +// transport_.SendDataDma(&buffer_[width * 16], width, SpiPageCompleteCallback, this); + } + + void PageTransfered(void) + { + if(transferingPage_ < transferPagesCount_-1) + { + TransferPageDma(transferingPage_+1); + } + else + updateing_ = false; + } + + static void SpiPageCompleteCallback(void* context, daisy::SpiHandle::Result result) + { + dsy_gpio_write(pUpdatePin, true); + static_cast(context)->PageTransfered(); + dsy_gpio_write(pUpdatePin, false); + } }; /** diff --git a/src/hid/disp/display.h b/src/hid/disp/display.h index 0ef3cdba8..85324e3e4 100644 --- a/src/hid/disp/display.h +++ b/src/hid/disp/display.h @@ -180,6 +180,11 @@ class OneBitGraphicsDisplay */ virtual void Update() = 0; + /** + Returns true if the Update has finished, used for chained DMA transfers + */ + virtual bool UpdateFinished() = 0; + protected: uint16_t currentX_; uint16_t currentY_; diff --git a/src/hid/disp/oled_display.h b/src/hid/disp/oled_display.h index 6b2cd035e..560435515 100644 --- a/src/hid/disp/oled_display.h +++ b/src/hid/disp/oled_display.h @@ -50,6 +50,8 @@ class OledDisplay : public OneBitGraphicsDisplayImpl> */ void Update() override { driver_.Update(); } + bool UpdateFinished() override { return driver_.UpdateFinished(); } + private: DisplayDriver driver_; From 729729edb1f07ccf0b8634d3e069ce3ee8266a5e Mon Sep 17 00:00:00 2001 From: AndrewCapon Date: Mon, 29 Apr 2024 13:01:29 +0100 Subject: [PATCH 6/7] Make code more unreadable with clang-format --- src/dev/oled_ssd130x.h | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/dev/oled_ssd130x.h b/src/dev/oled_ssd130x.h index e1a7bd7d1..96b4075fe 100644 --- a/src/dev/oled_ssd130x.h +++ b/src/dev/oled_ssd130x.h @@ -123,7 +123,7 @@ class SSD130x4WireSpiTransport dsy_gpio_write(&pin_reset_, 1); System::Delay(10); }; - + void SendCommand(uint8_t cmd) { dsy_gpio_write(&pin_dc_, 0); @@ -142,7 +142,10 @@ class SSD130x4WireSpiTransport spi_.BlockingTransmit(buff, size); }; - void SendDataDma(uint8_t* buff, size_t size, SpiHandle::EndCallbackFunctionPtr end_callback, void* context) + void SendDataDma(uint8_t* buff, + size_t size, + SpiHandle::EndCallbackFunctionPtr end_callback, + void* context) { SCB_CleanInvalidateDCache_by_Addr(buff, size); dsy_gpio_write(&pin_dc_, 1); @@ -410,10 +413,7 @@ class SSD130xDriver /** * Has update finished */ - bool UpdateFinished() - { - return true; - } + bool UpdateFinished() { return true; } protected: Transport transport_; @@ -627,10 +627,7 @@ class SSD1307Driver /** * Has update finished */ - bool UpdateFinished() - { - return !updateing_; - } + bool UpdateFinished() { return !updateing_; } private: Transport transport_; @@ -651,26 +648,32 @@ class SSD1307Driver default: high_column_addr = 0x10; break; } - uint8_t commands[] = { static_cast(0xB0 + transferingPage_), 0x00, high_column_addr }; + uint8_t commands[] = {static_cast(0xB0 + transferingPage_), + 0x00, + high_column_addr}; transport_.SendCommands(commands, 3); // transport_.SendCommand(0xB0 + transferingPage_); // transport_.SendCommand(0x00); // transport_.SendCommand(high_column_addr); - transport_.SendDataDma(&buffer_[width * transferingPage_], width, SpiPageCompleteCallback, this); -// transport_.SendDataDma(&buffer_[width * 16], width, SpiPageCompleteCallback, this); + transport_.SendDataDma(&buffer_[width * transferingPage_], + width, + SpiPageCompleteCallback, + this); + // transport_.SendDataDma(&buffer_[width * 16], width, SpiPageCompleteCallback, this); } void PageTransfered(void) { - if(transferingPage_ < transferPagesCount_-1) + if(transferingPage_ < transferPagesCount_ - 1) { - TransferPageDma(transferingPage_+1); + TransferPageDma(transferingPage_ + 1); } else updateing_ = false; } - - static void SpiPageCompleteCallback(void* context, daisy::SpiHandle::Result result) + + static void SpiPageCompleteCallback(void* context, + daisy::SpiHandle::Result result) { dsy_gpio_write(pUpdatePin, true); static_cast(context)->PageTransfered(); From 8a602c948d570b0ed52055291252dac61e18b1bd Mon Sep 17 00:00:00 2001 From: AndrewCapon Date: Mon, 29 Apr 2024 15:43:15 +0100 Subject: [PATCH 7/7] Remove timing code. --- src/dev/oled_ssd130x.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/dev/oled_ssd130x.h b/src/dev/oled_ssd130x.h index 96b4075fe..8f77c3b9f 100644 --- a/src/dev/oled_ssd130x.h +++ b/src/dev/oled_ssd130x.h @@ -675,9 +675,7 @@ class SSD1307Driver static void SpiPageCompleteCallback(void* context, daisy::SpiHandle::Result result) { - dsy_gpio_write(pUpdatePin, true); static_cast(context)->PageTransfered(); - dsy_gpio_write(pUpdatePin, false); } };