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:
parent
01c3e7487f
commit
ec1d674da7
@ -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();
|
|
||||||
if (rowNext==rowFirst){
|
|
||||||
// we have wrapped around and not filled the screen
|
|
||||||
topRow=-1; // start again at first row next time.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
setRowNative(slot);
|
|
||||||
writeNative(rowBuffer[rowNext]);
|
|
||||||
}
|
|
||||||
displayNative();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int LCDDisplay::nextFilledRow() {
|
unsigned long currentMillis = millis();
|
||||||
for (int rx=1;rx<=MAX_LCD_ROWS;rx++) {
|
|
||||||
topRow++;
|
if ((!force) && (currentMillis - lastScrollTime) < LCD_SCROLL_TIME)
|
||||||
topRow %= MAX_LCD_ROWS;
|
return NULL;
|
||||||
if (rowBuffer[topRow][0]) return topRow;
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return -1; // No slots filled
|
} while (force);
|
||||||
}
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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];
|
||||||
};
|
};
|
||||||
|
@ -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(){}
|
||||||
|
|
||||||
|
21
LCD_OLED.h
21
LCD_OLED.h
@ -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() { }
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user