diff --git a/OLEDDisplay.cpp b/OLEDDisplay.cpp index 445d41b7e0f06480924e299273ca9eba368e7ad1..0c96567cac8a7b421eb8dca742ce3492ea0f55a0 100644 --- a/OLEDDisplay.cpp +++ b/OLEDDisplay.cpp @@ -506,6 +506,111 @@ void OLEDDisplay::clear(void) { memset(buffer, 0, DISPLAY_BUFFER_SIZE); } +void OLEDDisplay::drawLogBuffer(uint16_t xMove, uint16_t yMove) { + uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS); + // Always align left + setTextAlignment(TEXT_ALIGN_LEFT); + + // State values + uint16_t length = 0; + uint16_t line = 0; + uint16_t lastPos = 0; + + for (uint16_t i=0;i<this->logBufferFilled;i++){ + // Everytime we have a \n print + if (this->logBuffer[i] == 10) { + length++; + // Draw string on line `line` from lastPos to length + // Passing 0 as the lenght because we are in TEXT_ALIGN_LEFT + drawStringInternal(xMove, yMove + (line++) * lineHeight, &this->logBuffer[lastPos], length, 0); + // Remember last pos + lastPos = i; + // Reset length + length = 0; + } else { + // Count chars until next linebreak + length++; + } + } + // Draw the remaining string + if (length > 0) { + drawStringInternal(xMove, yMove + line * lineHeight, &this->logBuffer[lastPos], length, 0); + } +} + +bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars){ + if (logBuffer != NULL) free(logBuffer); + uint16_t size = lines * chars; + if (size > 0) { + this->logBufferLine = 0; // Lines printed + this->logBufferMaxLines = lines; // Lines max printable + this->logBufferSize = size; // Total number of characters the buffer can hold + this->logBuffer = (char *) malloc(size * sizeof(uint8_t)); + if(!this->logBuffer) { + DEBUG_OLEDDISPLAY("[OLEDDISPLAY][setLogBuffer] Not enough memory to create log buffer\n"); + return false; + } + } + return true; +} + +size_t OLEDDisplay::write(uint8_t c) { + if (this->logBufferSize > 0) { + // Don't waste space on \r\n line endings, dropping \r + if (c == 13) return 1; + + bool maxLineNotReached = this->logBufferLine < this->logBufferMaxLines; + bool bufferNotFull = this->logBufferFilled < this->logBufferSize; + + // Can we write to the buffer? + if (bufferNotFull && maxLineNotReached) { + this->logBuffer[logBufferFilled] = utf8ascii(c); + this->logBufferFilled++; + // Keep track of lines written + if (c == 10) this->logBufferLine++; + } else { + // Max line number is reached + if (!maxLineNotReached) this->logBufferLine--; + + // Find the end of the first line + uint16_t firstLineEnd = 0; + for (uint16_t i=0;i<this->logBufferFilled;i++) { + if (this->logBuffer[i] == 10){ + // Include last char too + firstLineEnd = i + 1; + break; + } + } + // If there was a line ending + if (firstLineEnd > 0) { + // Calculate the new logBufferFilled value + this->logBufferFilled = logBufferFilled - firstLineEnd; + // Now we move the lines infront of the buffer + memcpy(this->logBuffer, &this->logBuffer[firstLineEnd], logBufferFilled); + } else { + // Let's reuse the buffer if it was full + if (!bufferNotFull) { + this->logBufferFilled = 0; + }// else { + // Nothing to do here + //} + } + write(c); + } + } + // We are always writing all uint8_t to the buffer + return 1; +} + +size_t OLEDDisplay::write(const char* str) { + if (str == NULL) return 0; + size_t length = strlen(str); + for (size_t i = 0; i < length; i++) { + write(str[i]); + } + return length; +} + // Private functions void OLEDDisplay::sendInitCommands(void) { sendCommand(DISPLAYOFF); diff --git a/OLEDDisplay.h b/OLEDDisplay.h index 364723c3bc9dbcaab9cfc897ace3b7c57bc28892..7c1dcf2c145f95257d21a51ad6b08417f0452022 100644 --- a/OLEDDisplay.h +++ b/OLEDDisplay.h @@ -108,7 +108,7 @@ enum OLEDDISPLAY_TEXT_ALIGNMENT { }; -class OLEDDisplay { +class OLEDDisplay : public Print { public: // Initialize the display bool init(); @@ -209,6 +209,20 @@ class OLEDDisplay { // Clear the local pixel buffer void clear(void); + // Log buffer implementation + + // This will define the lines and characters you can + // print to the screen. When you exeed the buffer size (lines * chars) + // the output may be truncated due to the size constraint. + bool setLogBuffer(uint16_t lines, uint16_t chars); + + // Draw the log buffer at position (x, y) + void drawLogBuffer(uint16_t x, uint16_t y); + + // Implementent needed function to be compatible with Print class + size_t write(uint8_t c); + size_t write(const char* s); + uint8_t *buffer; #ifdef OLEDDISPLAY_DOUBLE_BUFFER @@ -216,10 +230,18 @@ class OLEDDisplay { #endif protected: + OLEDDISPLAY_TEXT_ALIGNMENT textAlignment = TEXT_ALIGN_LEFT; OLEDDISPLAY_COLOR color = WHITE; - const char *fontData = ArialMT_Plain_10; + const char *fontData = ArialMT_Plain_10; + + // State values for logBuffer + uint16_t logBufferSize = 0; + uint16_t logBufferFilled = 0; + uint16_t logBufferLine = 0; + uint16_t logBufferMaxLines = 0; + char *logBuffer = NULL; // Send a command to the display (low level function) virtual void sendCommand(uint8_t com);