1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-25 13:41:23 +01:00

Enhance OLED/LCD speed

Write one character or position command per loop entry so as not to hold up the loop.  Add support for SH1106 OLED as 132x64 size option.
This commit is contained in:
Neil McKechnie 2021-02-18 16:00:00 +00:00
parent 01c3e7487f
commit ec1d674da7
5 changed files with 91 additions and 37 deletions

View File

@ -44,36 +44,78 @@ size_t LCDDisplay::write(uint8_t b) {
lcdDisplay->loop2(false); lcdDisplay->loop2(false);
} }
LCDDisplay* LCDDisplay::loop2(bool force) { LCDDisplay *LCDDisplay::loop2(bool force)
if ((!force) && (millis() - lastScrollTime)< LCD_SCROLL_TIME) return NULL; {
lastScrollTime=millis(); static int rowFirst = -1;
clearNative(); static int rowNext = 0;
int rowFirst=nextFilledRow(); static int charIndex = 0;
if (rowFirst<0)return NULL; // No filled rows static char buffer[MAX_LCD_COLS+1];
setRowNative(0); static char *bptr = 0;
writeNative(rowBuffer[rowFirst]); static bool done = false;
for (int slot=1;slot<lcdRows;slot++) {
int rowNext=nextFilledRow(); unsigned long currentMillis = millis();
if ((!force) && (currentMillis - lastScrollTime) < LCD_SCROLL_TIME)
return NULL;
do {
if (bptr == 0) {
// No pending write, so go and look for one.
if (!done) {
if (rowFirst < 0) rowFirst = rowNext;
// Skip blank rows
while (rowBuffer[rowNext][0] == 0) {
rowNext = (rowNext + 1) % MAX_LCD_ROWS;
if (rowNext == rowFirst) { if (rowNext == rowFirst) {
// we have wrapped around and not filled the screen done = true;
topRow=-1; // start again at first row next time.
break; break;
} }
setRowNative(slot);
writeNative(rowBuffer[rowNext]);
} }
displayNative(); }
if (!done) {
// Non-blank line found, so copy it.
strncpy(buffer, rowBuffer[rowNext], MAX_LCD_COLS);
} else
buffer[0] = '\0'; // Empty line
setRowNative(slot); // Set position for display
charIndex = 0;
bptr = &buffer[0];
} else {
// Write one character, which will be a space if the string is exhausted.
char ch = *bptr;
if (ch) {
writeNative(ch);
bptr++;
} else
writeNative(' ');
if (++charIndex >= MAX_LCD_COLS) {
// Screen slot completed, move to next one
slot++;
bptr = 0;
if (!done) {
rowNext = (rowNext + 1) % MAX_LCD_ROWS;
if (rowNext == rowFirst) done = true;
}
}
if (slot >= lcdRows) {
// Last slot done, reset ready for next update.
slot = 0;
done = false;
rowFirst = -1;
lastScrollTime = currentMillis;
return NULL;
}
}
} while (force);
return NULL; return NULL;
} }
int LCDDisplay::nextFilledRow() {
for (int rx=1;rx<=MAX_LCD_ROWS;rx++) {
topRow++;
topRow %= MAX_LCD_ROWS;
if (rowBuffer[topRow][0]) return topRow;
}
return -1; // No slots filled
}

View File

@ -49,13 +49,15 @@ class LCDDisplay : public Print {
void clearNative(); void clearNative();
void displayNative(); void displayNative();
void setRowNative(byte line); void setRowNative(byte line);
void writeNative(char * b); void writeNative(char b);
unsigned long lastScrollTime=0; unsigned long lastScrollTime=0;
int hotRow=0; int hotRow=0;
int hotCol=0; int hotCol=0;
int topRow=0; int topRow=0;
int lcdRows; int lcdRows;
int lcdCols;
int slot=0;
void renderRow(byte row); void renderRow(byte row);
char rowBuffer[MAX_LCD_ROWS][MAX_LCD_COLS+1]; char rowBuffer[MAX_LCD_ROWS][MAX_LCD_COLS+1];
}; };

View File

@ -22,6 +22,6 @@
void LCDDisplay::interfake(int p1, int p2, int p3) {(void)p1; (void)p2; (void)p3;} void LCDDisplay::interfake(int p1, int p2, int p3) {(void)p1; (void)p2; (void)p3;}
void LCDDisplay::setRowNative(byte row) { (void)row;} void LCDDisplay::setRowNative(byte row) { (void)row;}
void LCDDisplay::clearNative() {} void LCDDisplay::clearNative() {}
void LCDDisplay::writeNative(char * b){ (void)b;} // void LCDDisplay::writeNative(char b){ (void)b;} //
void LCDDisplay::displayNative(){} void LCDDisplay::displayNative(){}

View File

@ -32,14 +32,21 @@ SSD1306AsciiWire LCDDriver;
Wire.begin(); Wire.begin();
for (byte address=0x3c; address<=0x3d; address++) { for (byte address=0x3c; address<=0x3d; address++) {
Wire.beginTransmission(address); Wire.beginTransmission(address);
byte error = Wire.endTransmission(); byte error = Wire.endTransmission(true);
if (!error) { if (!error) {
// Device found // Device found
DIAG(F("\nOLED display found at 0x%x"), address); DIAG(F("\nOLED display found at 0x%x"), address);
interfake(OLED_DRIVER,0); interfake(OLED_DRIVER,0);
LCDDriver.begin(lcdRows==32 ? &Adafruit128x32 : &Adafruit128x64, address); const DevType *devType;
if (lcdCols == 132)
devType = &SH1106_128x64; // Actually 132x64 but treated as 128x64
else if (lcdCols == 128 && lcdRows == 8)
devType = &Adafruit128x64;
else
devType = &Adafruit128x32;
LCDDriver.begin(devType, address);
lcdDisplay=this; lcdDisplay=this;
LCDDriver.setFont(System5x7); // Normal 1:1 pixel scale LCDDriver.setFont(System5x7); // Normal 1:1 pixel scale, 8 bits high
clear(); clear();
return; return;
} }
@ -47,7 +54,7 @@ SSD1306AsciiWire LCDDriver;
DIAG(F("\nOLED display not found\n")); DIAG(F("\nOLED display not found\n"));
} }
void LCDDisplay::interfake(int p1, int p2, int p3) {(void)p1; lcdRows=p2/8; (void)p3;} void LCDDisplay::interfake(int p1, int p2, int p3) {lcdCols=p1; lcdRows=p2/8; (void)p3;}
void LCDDisplay::clearNative() {LCDDriver.clear();} void LCDDisplay::clearNative() {LCDDriver.clear();}
@ -55,10 +62,12 @@ SSD1306AsciiWire LCDDriver;
// Positions text write to start of row 1..n and clears previous text // Positions text write to start of row 1..n and clears previous text
int y=row; int y=row;
LCDDriver.setCursor(0, y); LCDDriver.setCursor(0, y);
LCDDriver.clearToEOL(); //LCDDriver.clearToEOL();
} }
void LCDDisplay::writeNative(char * b){ LCDDriver.write(b); } void LCDDisplay::writeNative(char b) {
LCDDriver.write(b);
}
void LCDDisplay::displayNative() { } void LCDDisplay::displayNative() { }

View File

@ -102,6 +102,7 @@ The configuration file for DCC-EX Command Station
//OR define OLED_DRIVER width,height in pixels (address auto detected) //OR define OLED_DRIVER width,height in pixels (address auto detected)
// 128x32 or 128x64 I2C SSD1306-based devices are supported. // 128x32 or 128x64 I2C SSD1306-based devices are supported.
// Also 132x64 I2C SH1106 devices.
// This will not work on a UNO due to memory constraints // This will not work on a UNO due to memory constraints
// #define OLED_DRIVER 128,32 // #define OLED_DRIVER 128,32