1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-25 21:41:23 +01:00
CommandStation-EX/SSD1306/SSD1306Ascii.cpp
Neil McKechnie 4685d2b24a Speed up OLED writes
Add new flushDisplay() to end any in-progress I2C transaction.  Previously, an redundant command was sent that ended the in-progress transaction but also sent another complete, but unnecessary, transaction.
2021-02-19 10:49:43 +00:00

139 lines
4.7 KiB
C++

/* Arduino SSD1306Ascii Library
* Copyright (C) 2015 by William Greiman
*
* This file is part of the Arduino SSD1306Ascii Library
*
* This Library is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the Arduino SSD1306Ascii Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "SSD1306Ascii.h"
//------------------------------------------------------------------------------
void SSD1306Ascii::clear() {
clear(0, displayWidth() - 1, 0 , displayRows() - 1);
}
//------------------------------------------------------------------------------
void SSD1306Ascii::clear(uint8_t c0, uint8_t c1, uint8_t r0, uint8_t r1) {
// Ensure only rows on display will be cleared.
if (r1 >= displayRows()) r1 = displayRows() - 1;
for (uint8_t r = r0; r <= r1; r++) {
setCursor(c0, r);
for (uint8_t c = c0; c <= c1; c++) {
// Ensure clear() writes zero. result is (m_invertMask^m_invertMask).
ssd1306WriteRamBuf(m_invertMask);
}
}
setCursor(c0, r0);
}
//------------------------------------------------------------------------------
void SSD1306Ascii::init(const DevType* dev) {
m_col = 0;
m_row = 0;
#ifdef __AVR__
const uint8_t* table = (const uint8_t*)pgm_read_word(&dev->initcmds);
#else // __AVR__
const uint8_t* table = dev->initcmds;
#endif // __AVR
uint8_t size = readFontByte(&dev->initSize);
m_displayWidth = readFontByte(&dev->lcdWidth);
m_displayHeight = readFontByte(&dev->lcdHeight);
m_colOffset = readFontByte(&dev->colOffset);
for (uint8_t i = 0; i < size; i++) {
ssd1306WriteCmd(readFontByte(table + i));
}
clear();
}
//------------------------------------------------------------------------------
void SSD1306Ascii::setCol(uint8_t col) {
if (col < m_displayWidth) {
m_col = col;
col += m_colOffset;
ssd1306WriteCmd(SSD1306_SETLOWCOLUMN | (col & 0XF));
ssd1306WriteCmd(SSD1306_SETHIGHCOLUMN | (col >> 4));
}
}
//------------------------------------------------------------------------------
void SSD1306Ascii::setContrast(uint8_t value) {
ssd1306WriteCmd(SSD1306_SETCONTRAST);
ssd1306WriteCmd(value);
}
//------------------------------------------------------------------------------
void SSD1306Ascii::setCursor(uint8_t col, uint8_t row) {
setCol(col);
setRow(row);
}
//------------------------------------------------------------------------------
void SSD1306Ascii::setFont(const uint8_t* font) {
m_font = font;
m_letterSpacing = 1;
m_fontFirstChar = readFontByte(m_font + FONT_FIRST_CHAR);
m_fontCharCount = readFontByte(m_font + FONT_CHAR_COUNT);
m_fontHeight = readFontByte(m_font + FONT_HEIGHT);
m_fontWidth = readFontByte(m_font + FONT_WIDTH);
}
//------------------------------------------------------------------------------
void SSD1306Ascii::setRow(uint8_t row) {
if (row < displayRows()) {
m_row = row;
ssd1306WriteCmd(SSD1306_SETSTARTPAGE | m_row);
}
}
//------------------------------------------------------------------------------
void SSD1306Ascii::ssd1306WriteRam(uint8_t c) {
if (m_col < m_displayWidth) {
writeDisplay(c^m_invertMask, SSD1306_MODE_RAM);
m_col++;
}
}
//------------------------------------------------------------------------------
void SSD1306Ascii::ssd1306WriteRamBuf(uint8_t c) {
if (m_col < m_displayWidth) {
writeDisplay(c^m_invertMask, SSD1306_MODE_RAM_BUF);
m_col++;
}
}
//------------------------------------------------------------------------------
size_t SSD1306Ascii::write(uint8_t ch) {
if (!m_font) {
return 0;
}
uint8_t w = readFontByte(m_font + FONT_WIDTH);
uint8_t h = readFontByte(m_font + FONT_HEIGHT);
uint8_t nr = (h + 7)/8;
uint8_t first = readFontByte(m_font + FONT_FIRST_CHAR);
uint8_t count = readFontByte(m_font + FONT_CHAR_COUNT);
const uint8_t* base = m_font + FONT_WIDTH_TABLE;
if (ch < first || ch >= (first + count)) return 0;
ch -= first;
uint8_t s = letterSpacing();
// Fixed width font.
base += nr*w*ch;
uint8_t scol = m_col;
for (uint8_t r = 0; r < nr; r++) {
if (r) {
setCursor(scol, m_row + 1);
}
for (uint8_t c = 0; c < w; c++) {
uint8_t b = readFontByte(base + c + r*w);
ssd1306WriteRamBuf(b);
}
for (uint8_t i = 0; i < s; i++) {
ssd1306WriteRamBuf(0);
}
}
flushDisplay();
return 1;
}