1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-22 23:56:13 +01:00

Refactor Display handler to (hopefully) improve clarity.

This commit is contained in:
Neil McKechnie 2023-02-22 21:06:03 +00:00
parent c2e8557c4c
commit 4eb277f19e
2 changed files with 63 additions and 58 deletions

View File

@ -36,7 +36,7 @@
* not held up significantly. The exception to this is when * not held up significantly. The exception to this is when
* the loop2() function is called with force=true, where * the loop2() function is called with force=true, where
* a screen update is executed to completion. This is normally * a screen update is executed to completion. This is normally
* only done during start-up. * only noMoreRowsToDisplay during start-up.
* The scroll mode is selected by defining SCROLLMODE as 0, 1 or 2 * The scroll mode is selected by defining SCROLLMODE as 0, 1 or 2
* in the config.h. * in the config.h.
* #define SCROLLMODE 0 is scroll continuous (fill screen if poss), * #define SCROLLMODE 0 is scroll continuous (fill screen if poss),
@ -53,9 +53,9 @@ Display::Display(DisplayDevice *deviceDriver) {
// Get device dimensions in characters (e.g. 16x2). // Get device dimensions in characters (e.g. 16x2).
numCharacterColumns = _deviceDriver->getNumCols(); numCharacterColumns = _deviceDriver->getNumCols();
numCharacterRows = _deviceDriver->getNumRows();; numCharacterRows = _deviceDriver->getNumRows();;
for (uint8_t row=0; row<MAX_CHARACTER_ROWS; row++) for (uint8_t row = 0; row < MAX_CHARACTER_ROWS; row++)
rowBuffer[row] = (char *)calloc(1, MAX_CHARACTER_COLS+1); rowBuffer[row][0] = '\0';
topRow = -1; // loop2 will fill from row 0 topRow = ROW_INITIAL; // loop2 will fill from row 0
addDisplay(0); // Add this display as display number 0 addDisplay(0); // Add this display as display number 0
}; };
@ -69,13 +69,13 @@ void Display::_clear() {
_deviceDriver->clearNative(); _deviceDriver->clearNative();
for (uint8_t row = 0; row < MAX_CHARACTER_ROWS; row++) for (uint8_t row = 0; row < MAX_CHARACTER_ROWS; row++)
rowBuffer[row][0] = '\0'; rowBuffer[row][0] = '\0';
topRow = -1; // loop2 will fill from row 0 topRow = ROW_INITIAL; // loop2 will fill from row 0
} }
void Display::_setRow(uint8_t line) { void Display::_setRow(uint8_t line) {
hotRow = line; hotRow = line;
hotCol = 0; hotCol = 0;
rowBuffer[hotRow][hotCol] = 0; // Clear existing text rowBuffer[hotRow][0] = 0; // Clear existing text
} }
size_t Display::_write(uint8_t b) { size_t Display::_write(uint8_t b) {
@ -109,63 +109,57 @@ Display *Display::loop2(bool force) {
return NULL; return NULL;
} else { } else {
// force full screen update from the beginning. // force full screen update from the beginning.
rowFirst = -1; rowFirst = ROW_INITIAL;
rowNext = 0; rowNext = ROW_INITIAL;
bufferPointer = 0; bufferPointer = 0;
done = false; noMoreRowsToDisplay = false;
slot = 0; slot = 0;
} }
do { do {
if (bufferPointer == 0) { if (bufferPointer == 0) {
// Find a line of data to write to the screen. // Find a line of data to write to the screen.
if (rowFirst < 0) rowFirst = rowNext; if (rowFirst == ROW_INITIAL) rowFirst = rowNext;
skipBlankRows(); if (findNextNonBlankRow()) {
if (!done) { // Non-blank line found, so copy it (including terminator)
// Non-blank line found, so copy it. for (uint8_t i = 0; i <= MAX_CHARACTER_COLS; i++)
for (uint8_t i = 0; i < sizeof(buffer); i++)
buffer[i] = rowBuffer[rowNext][i]; buffer[i] = rowBuffer[rowNext][i];
} else } else {
buffer[0] = '\0'; // Empty line // No non-blank lines left, so draw a blank line
buffer[0] = 0;
}
_deviceDriver->setRowNative(slot); // Set position for display _deviceDriver->setRowNative(slot); // Set position for display
charIndex = 0; charIndex = 0;
bufferPointer = &buffer[0]; bufferPointer = &buffer[0];
} else { } else {
// Write next character, or a space to erase current position. // Write next character, or a space to erase current position.
char ch = *bufferPointer; char ch = *bufferPointer;
if (ch) { if (ch) {
_deviceDriver->writeNative(ch); _deviceDriver->writeNative(ch);
bufferPointer++; bufferPointer++;
} else } else {
_deviceDriver->writeNative(' '); _deviceDriver->writeNative(' ');
}
if (++charIndex >= MAX_CHARACTER_COLS) { if (++charIndex >= MAX_CHARACTER_COLS) {
// Screen slot completed, move to next slot on screen // Screen slot completed, move to next slot on screen
slot++;
bufferPointer = 0; bufferPointer = 0;
if (!done) { slot++;
moveToNextRow(); if (slot >= numCharacterRows) {
skipBlankRows(); // Last slot on screen written, reset ready for next screen update.
}
}
if (slot >= numCharacterRows) {
// Last slot finished, reset ready for next screen update.
#if SCROLLMODE==2 #if SCROLLMODE==2
if (!done) { if (!noMoreRowsToDisplay) {
// On next refresh, restart one row on from previous start. // On next refresh, restart one row on from previous start.
rowNext = rowFirst; rowNext = rowFirst;
moveToNextRow(); findNextNonBlankRow();
skipBlankRows(); }
}
#endif #endif
done = false; noMoreRowsToDisplay = false;
slot = 0; slot = 0;
rowFirst = -1; rowFirst = ROW_INITIAL;
lastScrollTime = currentMillis; lastScrollTime = currentMillis;
return NULL; return NULL;
}
} }
} }
} while (force); } while (force);
@ -173,19 +167,30 @@ Display *Display::loop2(bool force) {
return NULL; return NULL;
} }
void Display::moveToNextRow() { bool Display::findNextNonBlankRow() {
rowNext = rowNext + 1; while (!noMoreRowsToDisplay) {
if (rowNext >= MAX_CHARACTER_ROWS) rowNext = 0; if (rowNext == ROW_INITIAL)
rowNext = 0;
else
rowNext = rowNext + 1;
if (rowNext >= MAX_CHARACTER_ROWS) rowNext = ROW_INITIAL;
#if SCROLLMODE == 1 #if SCROLLMODE == 1
// Finished if we've looped back to row 0 // Finished if we've looped back to start
if (rowNext == 0) done = true; if (rowNext == ROW_INITIAL) {
noMoreRowsToDisplay = true;
return false;
}
#else #else
// Finished if we're back to the first one shown // Finished if we're back to the first one shown
if (rowNext == rowFirst) done = true; if (rowNext == rowFirst) {
noMoreRowsToDisplay = true;
return false;
}
#endif #endif
} if (rowBuffer[rowNext][0] != 0) {
// Found non-blank row
void Display::skipBlankRows() { return true;
while (!done && rowBuffer[rowNext][0] == 0) }
moveToNextRow(); }
return false;
} }

View File

@ -40,6 +40,7 @@ public:
static const int MAX_CHARACTER_ROWS = 8; static const int MAX_CHARACTER_ROWS = 8;
static const int MAX_CHARACTER_COLS = MAX_MSG_SIZE; static const int MAX_CHARACTER_COLS = MAX_MSG_SIZE;
static const long DISPLAY_SCROLL_TIME = 3000; // 3 seconds static const long DISPLAY_SCROLL_TIME = 3000; // 3 seconds
static const uint8_t ROW_INITIAL = 255;
private: private:
DisplayDevice *_deviceDriver; DisplayDevice *_deviceDriver;
@ -47,18 +48,18 @@ private:
unsigned long lastScrollTime = 0; unsigned long lastScrollTime = 0;
uint8_t hotRow = 0; uint8_t hotRow = 0;
uint8_t hotCol = 0; uint8_t hotCol = 0;
int8_t topRow = 0; uint8_t topRow = 0;
uint8_t slot = 0; uint8_t slot = 0;
int8_t rowFirst = -1; uint8_t rowFirst = ROW_INITIAL;
int8_t rowNext = 0; uint8_t rowNext = ROW_INITIAL;
uint8_t charIndex = 0; uint8_t charIndex = 0;
char buffer[MAX_CHARACTER_COLS + 1]; char buffer[MAX_CHARACTER_COLS + 1];
char* bufferPointer = 0; char* bufferPointer = 0;
bool done = false; bool noMoreRowsToDisplay = false;
uint16_t numCharacterRows; uint16_t numCharacterRows;
uint16_t numCharacterColumns = MAX_CHARACTER_COLS; uint16_t numCharacterColumns = MAX_CHARACTER_COLS;
char *rowBuffer[MAX_CHARACTER_ROWS]; char rowBuffer[MAX_CHARACTER_ROWS][MAX_CHARACTER_COLS+1];
public: public:
void begin() override; void begin() override;
@ -68,8 +69,7 @@ public:
void _refresh() override; void _refresh() override;
void _displayLoop() override; void _displayLoop() override;
Display *loop2(bool force); Display *loop2(bool force);
void moveToNextRow(); bool findNextNonBlankRow();
void skipBlankRows();
}; };