Open antevens opened 4 years ago
Ooh nice catch. This was/is a tricky one to figure out.
Long story short: Currently HyperDisplay is not happy working with color definitions that are less than a byte wide. This bug applies to non-text output as well
When we call TOLED.println
in buffered mode:
write
function calls pixel
pixel
detects buffered mode and calls swpixel
swpixel
so it calls the HD defaultswpixel
uses the window standard method to determine a pixel offset (within the windows buffer) given the window coordinates of that pixel (that is left->right and top->bottom)getOffsetColor
function to determine where in the window's buffer to put the color informationmemcpy
copies n bytes from the supplied color information to the window. getOffsetColor
for the SSD1309 the number of bytes copied to window memory is always zero and thus the desired data is not saved. There are more problems, I suspect.
Possible Solutions:
storeColor
' function in HyperDisplay that can operate on sub-byte wide color types and use it in the swpixel function to control access to window buffers rather than just copying bytesI will start prototyping a fix. Thanks for reporting this issue!
That makes sense, I spent a couple of hours looking through the code trying to find the reason but didn't see anything obvious, no wonder :)
As a work-around to speed up text updates I added a flag in my branch to set all pixels in a character area not used by the character to 0x00 at the same time the character pixels are set to avoid having to clear the whole window before updating, it's probably not as good as the buffered update but usable for now.
Thanks for the update and all the hard work, it's appreciated!
Alright, I've got a fix in place. It feels really quite hacky but fortunately it doesn't affect the integrity of HyperDisplay, only the middle layer (SSD1309 driver). Try updating to the latest of all the HyperDisplay libraries (Top and middle layers have changed)
P.s. if it is speed you are after the 'buffered' mode is probably not going to help. When the show
method is called it triggers an update of the entire window (pixel-by-pixel, and without any optimization)
In the non-buffered mode the SSD1309 will only change pixels that are directly called.
However the implementation is not fully optimized - only pixelwise access is implemented and for that to work the memory addressing mode, column address, and page address all need to be updated in addition to the actual data.
Implementing line and rectangle optimizations will help in some cases but I am not sure if there is a guaranteed way to have pixelwise access that is any faster.
Happy new year!
Thanks for the update, I guess I'll stick with re-rendering characters for now, based on the documentation I figured buffered mode would at least only change those pixels that needed updating since the last "show()", I open an issue in the SSD1309 repo with my findings.
Happy New Year and thanks again for addressing this!
I think I've found a couple of minor issues:
#include "HyperDisplay_UG2856KLBAG01.h"
uint8_t windowMemZero[10*128];
//////////////////////////////
// Pinout and Hardware //
//////////////////////////////
#define SERIAL_PORT Serial
#define SPI_PORT SPI
#define CS_PIN 9
#define DC_PIN 10
// END USER SETUP
// Set up Transparent Organic LED Display and SPI communications
UG2856KLBAG01_SPI TOLED;
uint8_t color = 0x01;
uint8_t noColor = 0x00;
// Create Windows
wind_info_t windowZero; // Create some window objects
void setup() {
// Start serial communications
Serial.begin(9600);
// Start TOLED/SPI communications
SPI_PORT.begin();
TOLED.begin(CS_PIN, DC_PIN, SPI_PORT);
TOLED.setWindowDefaults(&windowZero);
TOLED.setWindowColorSequence(&windowZero, (color_t)&color);
TOLED.setWindowMemory(&windowZero, (color_t)windowMemZero, 10*128);
windowZero.xMin = 0;
windowZero.yMin = 0;
windowZero.xMax = 127;
windowZero.yMax = 9;
TOLED.pCurrentWindow = &windowZero;
TOLED.buffer();
TOLED.println("buffered fails");
TOLED.resetTextCursor();
TOLED.show();
delay(3000);
TOLED.windowClear();
Serial.println(F("Transparent Graphical OLED"));
}
void loop() {
Serial.println(F("looping"));
delay(1000);
TOLED.println("print more");
TOLED.resetTextCursor();
TOLED.show();
}
Ahh you are being a much more thorough tester than I have been! (Thanks!)
I was worried that something like this might happen because I've made the getOffsetColor
function run double duty for the SSD1309
Usually it should only have to return a pointer to the next user color type that was N pixels after the base. In this case I've made it so that it also can return literal values (0 and 1) that will indicate to the drawing function to render something directly. This mode is activated when the window data pointer is non-null. So that's probably close to the culprit.
hello there I was wondering if you could send an example of the the getCharInfo and write function I tried using serial print it did not work. I just need example of how to plug in the data in the correct coordinates.
@dani0303
I assume you want to create a custom font - if not then the libraries default font should work out of the box.
To make your own custom font you only need to implement either getCharInfo
or write
. If you make your own write
function then you are completely in control and you will only use getCharInfo
if you personally decide to. If you want to rely on the default write
function in HyperDisplay then you will only need to make your own getCharInfo
.
The best example of getCharInfo
might be the default implementation in the HyperDisplay source code
You can use that as a starting point, as well as the other examples posted here
Honestly - HyperDisplay needs a dedicated solution for font handling and I haven't had any bandwidth to figure it out. This will get you started in the right direction and once you've tried it out maybe you will have ideas on how to make it better.
Subject of the issue
Using buffered output for text fails to render to screen
Your workbench
Arduino 33 BLE Sense On a breadboard, powered from USB SPI interface at 10Mhz
Steps to reproduce
include "HyperDisplay_UG2856KLBAG01.h"
uint8_t windowMemZero[10*128/8]; // not sure if this is the right way to reserve monochrome pixel memory
////////////////////////////// // Pinout and Hardware // //////////////////////////////
define SERIAL_PORT Serial
define SPI_PORT SPI
define CS_PIN 9
define DC_PIN 10
// END USER SETUP
// Set colors for the TOLED display uint8_t color = 0x01; uint8_t noColor = 0x00;
// Set up Transparent Organic LED Display and SPI communications UG2856KLBAG01_SPI TOLED;
// Create Windows wind_info_t windowZero, windowOne, windowTwo; // Create some window objects
void setup() { // Start serial communications Serial.begin(9600);
// Start TOLED/SPI communications SPI_PORT.begin(); TOLED.begin(CS_PIN, DC_PIN, SPI_PORT);
TOLED.setWindowDefaults(&windowZero); TOLED.setWindowDefaults(&windowOne); TOLED.setWindowDefaults(&windowTwo);
TOLED.setWindowColorSequence(&windowZero, (color_t)&color); TOLED.setWindowColorSequence(&windowOne, (color_t)&color); TOLED.setWindowColorSequence(&windowTwo, (color_t)&color);
TOLED.setWindowMemory(&windowZero, (color_t)windowMemZero, 10*128);
windowZero.xMin = 0; windowZero.yMin = 0; windowZero.xMax = 127; windowZero.yMax = 9;
windowOne.xMin = 0; windowOne.yMin = 10; windowOne.xMax = 127; windowOne.yMax = 19;
windowTwo.xMin = 0; windowTwo.yMin = 20; windowTwo.xMax = 127; windowTwo.yMax = 29;
TOLED.pCurrentWindow = &windowZero; TOLED.buffer(); TOLED.println("buffered fails"); TOLED.resetTextCursor(); TOLED.show(&windowZero);
TOLED.pCurrentWindow = &windowOne; TOLED.println("two direct"); TOLED.resetTextCursor();
TOLED.pCurrentWindow = &windowTwo; TOLED.println("three will be cleared"); TOLED.resetTextCursor();
delay(3000); TOLED.windowClear();
Serial.println(F("Transparent Graphical OLED")); }
void loop() { Serial.println(F("looping")); delay(1000); TOLED.show(); TOLED.show(&windowZero); TOLED.pCurrentWindow = &windowZero; TOLED.direct(); TOLED.println("direct works"); TOLED.resetTextCursor(); TOLED.buffer(); TOLED.println("buffered fails"); // but the cursor is still moved ... TOLED.resetTextCursor(); TOLED.show(); delay(1000); }
Expected behaviour
Buffered text should be rendered to screen alternating with direct text
Actual behaviour
Buffered text is never shown