From 7eb9f3f10d27be67bfd215cadc2daff01caf99d2 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 6 Nov 2022 22:10:09 +1100 Subject: [PATCH 1/2] Only send on display change --- source/Core/Drivers/OLED.cpp | 4 ++-- source/Core/Drivers/OLED.hpp | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/source/Core/Drivers/OLED.cpp b/source/Core/Drivers/OLED.cpp index 6ca691db07..54574248fc 100644 --- a/source/Core/Drivers/OLED.cpp +++ b/source/Core/Drivers/OLED.cpp @@ -25,7 +25,7 @@ bool OLED::initDone = false; uint8_t OLED::displayOffset; uint8_t OLED::screenBuffer[16 + (OLED_WIDTH * 2) + 10]; // The data buffer uint8_t OLED::secondFrameBuffer[OLED_WIDTH * 2]; - +uint32_t OLED::displayChecksum; /*Setup params for the OLED screen*/ /*http://www.displayfuture.com/Display/datasheet/controller/SSD1307.pdf*/ /*All commands are prefixed with 0x80*/ @@ -222,7 +222,7 @@ void OLED::maskScrollIndicatorOnOLED() { // it from the screen buffer which is updated by `OLED::setRotation`. uint8_t rightmostColumn = screenBuffer[7]; uint8_t maskCommands[] = { - // Set column address: + // Set column address: // A[6:0] - Column start address = rightmost column // B[6:0] - Column end address = rightmost column 0x80, diff --git a/source/Core/Drivers/OLED.hpp b/source/Core/Drivers/OLED.hpp index f088f91a23..b6b6743a95 100644 --- a/source/Core/Drivers/OLED.hpp +++ b/source/Core/Drivers/OLED.hpp @@ -47,11 +47,19 @@ class OLED { static void initialize(); // Startup the I2C coms (brings screen out of reset etc) static bool isInitDone(); - // Draw the buffer out to the LCD using the DMA Channel + // Draw the buffer out to the LCD if any content has changed. static void refresh() { - I2C_CLASS::Transmit(DEVICEADDR_OLED, screenBuffer, FRAMEBUFFER_START + (OLED_WIDTH * 2)); - // DMA tx time is ~ 20mS Ensure after calling this you delay for at least 25ms - // or we need to goto double buffering + uint32_t hash = 0; + const int len = FRAMEBUFFER_START + (OLED_WIDTH * 2); + for (int i = 0; i < len; i++) { + hash += (i * screenBuffer[i]); + } + if (hash != displayChecksum) { + displayChecksum = hash; + I2C_CLASS::Transmit(DEVICEADDR_OLED, screenBuffer, len); + // DMA tx time is ~ 20mS Ensure after calling this you delay for at least 25ms + // or we need to goto double buffering + } } static void setDisplayState(DisplayState state) { @@ -112,6 +120,7 @@ class OLED { static DisplayState displayState; static int16_t cursor_x, cursor_y; static uint8_t displayOffset; + static uint32_t displayChecksum; static uint8_t screenBuffer[16 + (OLED_WIDTH * 2) + 10]; // The data buffer static uint8_t secondFrameBuffer[OLED_WIDTH * 2]; }; From 80e7ab3161112d1841b19f8aded3cca21eb5021b Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 6 Nov 2022 22:51:59 +1100 Subject: [PATCH 2/2] Force delay after display state change So that we backoff if OLED is busy Update OLED.hpp --- source/Core/Drivers/OLED.hpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/Core/Drivers/OLED.hpp b/source/Core/Drivers/OLED.hpp index b6b6743a95..9912c5df70 100644 --- a/source/Core/Drivers/OLED.hpp +++ b/source/Core/Drivers/OLED.hpp @@ -10,10 +10,12 @@ #ifndef OLED_HPP_ #define OLED_HPP_ #include "Font.h" +#include "cmsis_os.h" #include "configuration.h" #include #include #include + #ifdef __cplusplus extern "C" { #endif @@ -63,8 +65,13 @@ class OLED { } static void setDisplayState(DisplayState state) { - displayState = state; - screenBuffer[1] = (state == ON) ? 0xAF : 0xAE; + if (state != displayState) { + displayState = state; + screenBuffer[1] = (state == ON) ? 0xAF : 0xAE; + // Dump the screen state change out _now_ + I2C_CLASS::Transmit(DEVICEADDR_OLED, screenBuffer, FRAMEBUFFER_START - 1); + osDelay(TICKS_10MS); + } } static void setRotation(bool leftHanded); // Set the rotation for the screen