1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-24 21:21:24 +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* LCDDisplay::loop2(bool force) {
if ((!force) && (millis() - lastScrollTime)< LCD_SCROLL_TIME) return NULL;
lastScrollTime=millis();
clearNative();
int rowFirst=nextFilledRow();
if (rowFirst<0)return NULL; // No filled rows
setRowNative(0);
writeNative(rowBuffer[rowFirst]);
for (int slot=1;slot<lcdRows;slot++) {
int rowNext=nextFilledRow();
if (rowNext==rowFirst){
// we have wrapped around and not filled the screen
topRow=-1; // start again at first row next time.
LCDDisplay *LCDDisplay::loop2(bool force)
{
static int rowFirst = -1;
static int rowNext = 0;
static int charIndex = 0;
static char buffer[MAX_LCD_COLS+1];
static char *bptr = 0;
static bool done = false;
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) {
done = true;
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;
}
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
}
} while (force);
return NULL;
}

View File

@ -49,13 +49,15 @@ class LCDDisplay : public Print {
void clearNative();
void displayNative();
void setRowNative(byte line);
void writeNative(char * b);
void writeNative(char b);
unsigned long lastScrollTime=0;
int hotRow=0;
int hotCol=0;
int topRow=0;
int lcdRows;
int lcdCols;
int slot=0;
void renderRow(byte row);
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::setRowNative(byte row) { (void)row;}
void LCDDisplay::clearNative() {}
void LCDDisplay::writeNative(char * b){ (void)b;} //
void LCDDisplay::writeNative(char b){ (void)b;} //
void LCDDisplay::displayNative(){}

View File

@ -32,14 +32,21 @@ SSD1306AsciiWire LCDDriver;
Wire.begin();
for (byte address=0x3c; address<=0x3d; address++) {
Wire.beginTransmission(address);
byte error = Wire.endTransmission();
byte error = Wire.endTransmission(true);
if (!error) {
// Device found
DIAG(F("\nOLED display found at 0x%x"), address);
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;
LCDDriver.setFont(System5x7); // Normal 1:1 pixel scale
LCDDriver.setFont(System5x7); // Normal 1:1 pixel scale, 8 bits high
clear();
return;
}
@ -47,7 +54,7 @@ SSD1306AsciiWire LCDDriver;
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();}
@ -55,10 +62,12 @@ SSD1306AsciiWire LCDDriver;
// Positions text write to start of row 1..n and clears previous text
int y=row;
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() { }

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)
// 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
// #define OLED_DRIVER 128,32