diff --git a/I2CManager.cpp b/I2CManager.cpp
index 676f2ce..27e85f1 100644
--- a/I2CManager.cpp
+++ b/I2CManager.cpp
@@ -17,6 +17,8 @@
* along with CommandStation. If not, see .
*/
+#include
+#include
#include "I2CManager.h"
// If not already initialised, initialise I2C (wire).
@@ -48,10 +50,80 @@ void I2CManagerClass::forceClock(uint32_t speed) {
// Check if specified I2C address is responding.
// Returns 0 if OK, or error code.
-uint8_t I2CManagerClass::exists(uint8_t address) {
+uint8_t I2CManagerClass::checkAddress(uint8_t address) {
begin();
Wire.beginTransmission(address);
return Wire.endTransmission();
}
+bool I2CManagerClass::exists(uint8_t address) {
+ return checkAddress(address)==0;
+}
+
+// Write a complete transmission to I2C using a supplied buffer of data
+uint8_t I2CManagerClass::write(uint8_t address, const uint8_t buffer[], uint8_t size) {
+ Wire.beginTransmission(address);
+ Wire.write(buffer, size);
+ return Wire.endTransmission();
+}
+
+// Write a complete transmission to I2C using a supplied buffer of data in Flash
+uint8_t I2CManagerClass::write_P(uint8_t address, const uint8_t buffer[], uint8_t size) {
+ uint8_t ramBuffer[size];
+ memcpy_P(ramBuffer, buffer, size);
+ return write(address, ramBuffer, size);
+}
+
+
+// Write a complete transmission to I2C using a list of data
+uint8_t I2CManagerClass::write(uint8_t address, int nBytes, ...) {
+ uint8_t buffer[nBytes];
+ va_list args;
+ va_start(args, nBytes);
+ for (uint8_t i=0; i 0) {
+ Wire.beginTransmission(address);
+ Wire.write(writeBuffer, writeSize);
+ Wire.endTransmission(false); // Don't free bus yet
+ }
+ Wire.requestFrom(address, readSize);
+ uint8_t nBytes = 0;
+ while (Wire.available() && nBytes < readSize)
+ readBuffer[nBytes++] = Wire.read();
+ return nBytes;
+}
+
+// Overload of read() to allow command to be specified as a series of bytes.
+uint8_t I2CManagerClass::read(uint8_t address, uint8_t readBuffer[], uint8_t readSize,
+ uint8_t writeSize, ...) {
+ va_list args;
+ // Copy the series of bytes into an array.
+ va_start(args, writeSize);
+ uint8_t writeBuffer[writeSize];
+ for (uint8_t i=0; i
+#include "FSH.h"
/*
* Helper class to manage access to the I2C 'Wire' subsystem.
@@ -48,12 +48,27 @@ public:
// Force clock speed
void forceClock(uint32_t speed);
// Check if specified I2C address is responding.
- uint8_t exists(uint8_t address);
+ uint8_t checkAddress(uint8_t address);
+ bool exists(uint8_t address);
+ // Write a complete transmission to I2C from an array in RAM
+ uint8_t write(uint8_t address, const uint8_t buffer[], uint8_t size);
+ // Write a complete transmission to I2C from an array in Flash
+ uint8_t write_P(uint8_t address, const uint8_t buffer[], uint8_t size);
+ // Write a transmission to I2C from a list of bytes.
+ uint8_t write(uint8_t address, int nBytes, ...);
+ // Write a command from an array in RAM and read response
+ uint8_t read(uint8_t address, uint8_t writeBuffer[], uint8_t writeSize,
+ uint8_t readBuffer[], uint8_t readSize);
+ // Write a command from an arbitrary list of bytes and read response
+ uint8_t read(uint8_t address, uint8_t readBuffer[], uint8_t readSize,
+ uint8_t writeSize, ...);
+ // Write a null command and read the response.
+ uint8_t read(uint8_t address, uint8_t readBuffer[], uint8_t readSize);
private:
bool _beginCompleted = false;
bool _clockSpeedFixed = false;
- uint32_t _clockSpeed = 1000000L; // 1MHz max on Arduino.
+ uint32_t _clockSpeed = 400000L; // 400kHz max on Arduino.
};
extern I2CManagerClass I2CManager;
diff --git a/LCD_OLED.h b/LCD_OLED.h
index afd79fd..a849a20 100644
--- a/LCD_OLED.h
+++ b/LCD_OLED.h
@@ -24,7 +24,6 @@
#include "I2CManager.h"
#include "SSD1306Ascii.h"
-#include "Wire.h"
SSD1306AsciiWire LCDDriver;
// DEVICE SPECIFIC LCDDisplay Implementation for OLED
@@ -34,10 +33,9 @@ LCDDisplay::LCDDisplay() {
I2CManager.begin();
I2CManager.setClock(400000L); // Set max supported I2C speed
for (byte address = 0x3c; address <= 0x3d; address++) {
- byte error = I2CManager.exists(address);
- if (!error) {
+ if (I2CManager.exists(address)) {
// Device found
- DIAG(F("OLED display found at 0x%x"), address);
+ DIAG(F("\nOLED display found at 0x%x"), address);
interfake(OLED_DRIVER, 0);
const DevType *devType;
if (lcdCols == 132)
@@ -65,7 +63,7 @@ void LCDDisplay::interfake(int p1, int p2, int p3) {
void LCDDisplay::clearNative() { LCDDriver.clear(); }
void LCDDisplay::setRowNative(byte row) {
- // Positions text write to start of row 1..n and clears previous text
+ // Positions text write to start of row 1..n
int y = row;
LCDDriver.setCursor(0, y);
}
diff --git a/LiquidCrystal_I2C.cpp b/LiquidCrystal_I2C.cpp
index 751892a..90aac56 100644
--- a/LiquidCrystal_I2C.cpp
+++ b/LiquidCrystal_I2C.cpp
@@ -15,32 +15,13 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with CommandStation. If not, see .
+ * along with CommandStation-EX. If not, see .
*/
+#include
#include "LiquidCrystal_I2C.h"
#include "I2CManager.h"
-#include
-#if defined(ARDUINO) && ARDUINO >= 100
-
-#include "Arduino.h"
-
-#define printIIC(args) Wire.write(args)
-inline size_t LiquidCrystal_I2C::write(uint8_t value) {
- send(value, Rs);
- return 1;
-}
-
-#else
-#include "WProgram.h"
-
-#define printIIC(args) Wire.send(args)
-inline void LiquidCrystal_I2C::write(uint8_t value) { send(value, Rs); }
-
-#endif
-#include "Wire.h"
-
// When the display powers up, it is configured as follows:
//
// 1. Display clear
@@ -72,7 +53,7 @@ void LiquidCrystal_I2C::init() { init_priv(); }
void LiquidCrystal_I2C::init_priv() {
I2CManager.begin();
- I2CManager.setClock(100000L); // PCF8574 is limited to 100kHz.
+ I2CManager.setClock(100000L); // PCF8574 is spec'd to 100kHz.
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
begin(_cols, _rows);
@@ -85,10 +66,9 @@ void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines) {
_numlines = lines;
(void)cols; // Suppress compiler warning.
- // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
// according to datasheet, we need at least 40ms after power rises above 2.7V
// before sending commands. Arduino can turn on way befer 4.5V so we'll allow
- // 100 milliseconds after pulling both RS and R/W and backlight pin low
+ // 100 milliseconds after pulling both RS and R/W and backlight pin low
expanderWrite(
_backlightval); // reset expander and turn backlight off (Bit 8 =1)
delay(100);
@@ -167,23 +147,11 @@ void LiquidCrystal_I2C::backlight(void) {
expanderWrite(0);
}
-void LiquidCrystal_I2C::setBacklight(uint8_t new_val) {
- if (new_val) {
- backlight(); // turn backlight on
- } else {
- noBacklight(); // turn backlight off
- }
-}
-
-void LiquidCrystal_I2C::printstr(const char c[]) {
- // This function is not identical to the function used for "real" I2C displays
- // it's here so the user sketch doesn't have to be changed
- print(c);
-}
-
/*********** mid level commands, for sending data/cmds */
-inline void LiquidCrystal_I2C::command(uint8_t value) { send(value, 0); }
+inline void LiquidCrystal_I2C::command(uint8_t value) {
+ send(value, 0);
+}
/************ low level data pushing commands **********/
@@ -209,37 +177,37 @@ inline void LiquidCrystal_I2C::command(uint8_t value) { send(value, 0); }
* transmission and start another one is a stop bit, a start bit, 8 address bits,
* an ack, 8 data bits and another ack; this is at least 20 bits, i.e. >50us
* at 400kHz and >200us at 100kHz. Therefore, we don't need additional delay.
+ *
+ * Similarly, the Enable must be set/reset for at least 450ns. This is
+ * well within the I2C clock cycle time of 2.5us at 400kHz. Data is clocked in
+ * to the HD44780 on the trailing edge of the Enable pin, so we set the Enable
+ * as we present the data, then in the next byte we reset Enable without changing
+ * the data.
*/
-// write either command or data (8 bits) to the HD44780 as
-// a single I2C transmission.
+// write either command or data (8 bits) to the HD44780 LCD controller as
+// a single I2C transmission.
void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) {
- uint8_t highnib = value & 0xf0;
- uint8_t lownib = (value << 4) & 0xf0;
+ mode |= _backlightval;
+ uint8_t highnib = (value & 0xf0) | mode;
+ uint8_t lownib = ((value << 4) & 0xf0) | mode;
// Send both nibbles
- Wire.beginTransmission(_Addr);
- write4bits(highnib | mode, true);
- write4bits(lownib | mode, true);
- Wire.endTransmission();
+ byte buffer[] = {(byte)(highnib|En), highnib, (byte)(lownib|En), lownib};
+ I2CManager.write(_Addr, buffer, sizeof(buffer));
}
-// write 4 bits to the HD44780 interface. If inTransmission is false
-// then the nibble will be sent in its own I2C transmission.
-void LiquidCrystal_I2C::write4bits(uint8_t value, bool inTransmission) {
- int _data = (int)value | _backlightval;
- if (!inTransmission) Wire.beginTransmission(_Addr);
+// write 4 bits to the HD44780 LCD controller.
+void LiquidCrystal_I2C::write4bits(uint8_t value) {
+ uint8_t _data = value | _backlightval;
// Enable must be set/reset for at least 450ns. This is well within the
// I2C clock cycle time of 2.5us at 400kHz. Data is clocked in to the
// HD44780 on the trailing edge of the Enable pin.
- printIIC(_data | En);
- printIIC(_data);
- if (!inTransmission) Wire.endTransmission();
+ byte buffer[] = {(byte)(_data|En), _data};
+ I2CManager.write(_Addr, buffer, sizeof(buffer));
}
-// write a byte to the PCF8574 I2C interface
+// write a byte to the PCF8574 I2C interface. We don't need to set
+// the enable pin for this.
void LiquidCrystal_I2C::expanderWrite(uint8_t value) {
- int _data = (int)value | _backlightval;
- Wire.beginTransmission(_Addr);
- printIIC(_data);
- Wire.endTransmission();
+ I2CManager.write(_Addr, 1, value | _backlightval);
}
\ No newline at end of file
diff --git a/LiquidCrystal_I2C.h b/LiquidCrystal_I2C.h
index 2d6919e..9316385 100644
--- a/LiquidCrystal_I2C.h
+++ b/LiquidCrystal_I2C.h
@@ -21,9 +21,7 @@
#ifndef LiquidCrystal_I2C_h
#define LiquidCrystal_I2C_h
-#include
-#include "Print.h"
-#include
+#include
// commands
#define LCD_CLEARDISPLAY 0x01
@@ -82,25 +80,15 @@ public:
void backlight();
void setCursor(uint8_t, uint8_t);
-#if defined(ARDUINO) && ARDUINO >= 100
virtual size_t write(uint8_t);
-#else
- virtual void write(uint8_t);
-#endif
void command(uint8_t);
void init();
- void oled_init();
-
-////compatibility API function aliases
-void setBacklight(uint8_t new_val); // alias for backlight() and nobacklight()
-void printstr(const char[]);
private:
void init_priv();
void send(uint8_t, uint8_t);
- void write4bits(uint8_t, bool inTransmission=false);
+ void write4bits(uint8_t);
void expanderWrite(uint8_t);
- void pulseEnable(uint8_t);
uint8_t _Addr;
uint8_t _displayfunction;
uint8_t _displaycontrol;
diff --git a/PWMServoDriver.cpp b/PWMServoDriver.cpp
index 7db69d8..55d9ef5 100644
--- a/PWMServoDriver.cpp
+++ b/PWMServoDriver.cpp
@@ -23,7 +23,6 @@
* BSD license, all text above must be included in any redistribution
*/
#include
-#include
#include "PWMServoDriver.h"
#include "DIAG.h"
#include "I2CManager.h"
@@ -60,7 +59,7 @@ bool PWMServoDriver::setup(int board) {
uint8_t i2caddr=PCA9685_I2C_ADDRESS + board;
// Test if device is available
- byte error = I2CManager.exists(i2caddr);
+ byte error = I2CManager.checkAddress(i2caddr);
if (error) {
DIAG(F("I2C Servo device 0x%x Not Found %d"),i2caddr, error);
failFlags|=1<> 8);
- byte error=Wire.endTransmission();
+ uint8_t buffer[] = {(uint8_t)(PCA9685_FIRST_SERVO + 4 * pin), // 4 registers per pin
+ 0, 0, (uint8_t)(value & 0xff), (uint8_t)(value >> 8)};
+ if (value == 4095) buffer[2] = 0x10; // Full on
+ byte error=I2CManager.write(PCA9685_I2C_ADDRESS + board, buffer, sizeof(buffer));
if (error!=0) DIAG(F("SetServo error %d"),error);
}
}
void PWMServoDriver::writeRegister(uint8_t i2caddr,uint8_t hardwareRegister, uint8_t d) {
- Wire.beginTransmission(i2caddr);
- Wire.write(hardwareRegister);
- Wire.write(d);
- Wire.endTransmission();
+ I2CManager.write(i2caddr, 2, hardwareRegister, d);
}
diff --git a/SSD1306Ascii.cpp b/SSD1306Ascii.cpp
index 85e406a..feb0f0d 100644
--- a/SSD1306Ascii.cpp
+++ b/SSD1306Ascii.cpp
@@ -16,27 +16,38 @@
* .
*/
#include "SSD1306Ascii.h"
+#include "I2CManager.h"
+#include "FSH.h"
+
+
+// Maximum number of bytes we can send per transmission is 32.
+const uint8_t FLASH SSD1306AsciiWire::blankPixels[32] =
+ {0x40, // First byte specifies data mode
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//==============================================================================
-// SSD1306Ascii Method Definitions
-
+// SSD1306AsciiWire Method Definitions
//------------------------------------------------------------------------------
-void SSD1306Ascii::clear() {
+void SSD1306AsciiWire::clear() {
clear(0, displayWidth() - 1, 0, displayRows() - 1);
}
//------------------------------------------------------------------------------
-void SSD1306Ascii::clear(uint8_t c0, uint8_t c1, uint8_t r0, uint8_t r1) {
+void SSD1306AsciiWire::clear(uint8_t columnStart, uint8_t columnEnd,
+ uint8_t rowStart, uint8_t rowEnd) {
+ const int maxBytes = sizeof(blankPixels); // max number of bytes sendable over Wire
// 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++) ssd1306WriteRamBuf(0);
+ if (rowEnd >= displayRows()) rowEnd = displayRows() - 1;
+ for (uint8_t r = rowStart; r <= rowEnd; r++) {
+ setCursor(columnStart, r); // Position at start of row to be erased
+ for (uint8_t c = columnStart; c <= columnEnd; c += maxBytes-1) {
+ uint8_t len = min((uint8_t)(columnEnd-c+1), maxBytes-1) + 1;
+ I2CManager.write_P(m_i2cAddr, blankPixels, len); // Write up to 31 blank columns
+ }
}
- setCursor(c0, r0);
}
//------------------------------------------------------------------------------
-void SSD1306Ascii::init(const DevType* dev) {
+void SSD1306AsciiWire::begin(const DevType* dev, uint8_t i2cAddr) {
+ m_i2cAddr = i2cAddr;
m_col = 0;
m_row = 0;
#ifdef __AVR__
@@ -48,125 +59,50 @@ void SSD1306Ascii::init(const DevType* dev) {
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();
+ I2CManager.write_P(m_i2cAddr, table, size);
}
//------------------------------------------------------------------------------
-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 SSD1306AsciiWire::setContrast(uint8_t value) {
+ I2CManager.write(m_i2cAddr, 2,
+ 0x00, // Set to command mode
+ SSD1306_SETCONTRAST, value);
+}
+//------------------------------------------------------------------------------
+void SSD1306AsciiWire::setCursor(uint8_t col, uint8_t row) {
+ if (row < displayRows() && col < m_displayWidth) {
+ m_row = row;
+ m_col = col + m_colOffset;
+ I2CManager.write(m_i2cAddr, 4,
+ 0x00, // Set to command mode
+ SSD1306_SETLOWCOLUMN | (col & 0XF),
+ SSD1306_SETHIGHCOLUMN | (col >> 4),
+ SSD1306_SETSTARTPAGE | m_row);
}
}
//------------------------------------------------------------------------------
-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) {
+void SSD1306AsciiWire::setFont(const uint8_t* font) {
m_font = font;
m_fontFirstChar = readFontByte(m_font + FONT_FIRST_CHAR);
m_fontCharCount = readFontByte(m_font + FONT_CHAR_COUNT);
}
//------------------------------------------------------------------------------
-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, SSD1306_MODE_RAM);
- m_col++;
- }
-}
-//------------------------------------------------------------------------------
-void SSD1306Ascii::ssd1306WriteRamBuf(uint8_t c) {
- if (m_col < m_displayWidth) {
- writeDisplay(c, SSD1306_MODE_RAM_BUF);
- m_col++;
- }
-}
-//------------------------------------------------------------------------------
-size_t SSD1306Ascii::write(uint8_t ch) {
- if (!m_font) {
- return 0;
- }
+size_t SSD1306AsciiWire::write(uint8_t ch) {
const uint8_t* base = m_font + FONT_WIDTH_TABLE;
if (ch < m_fontFirstChar || ch >= (m_fontFirstChar + m_fontCharCount))
return 0;
ch -= m_fontFirstChar;
base += fontWidth * ch;
- for (uint8_t c = 0; c < fontWidth; c++) {
- uint8_t b = readFontByte(base + c);
- ssd1306WriteRamBuf(b);
- }
- for (uint8_t i = 0; i < letterSpacing; i++) {
- ssd1306WriteRamBuf(0);
- }
- flushDisplay();
+ uint8_t buffer[1+fontWidth+letterSpacing];
+ buffer[0] = 0x40; // set SSD1306 controller to data mode
+ uint8_t bufferPos = 1;
+ // Copy character pixel columns
+ for (uint8_t i = 0; i < fontWidth; i++)
+ buffer[bufferPos++] = readFontByte(base++);
+ // Add blank pixels between letters
+ for (uint8_t i = 0; i < letterSpacing; i++)
+ buffer[bufferPos++] = 0;
+ // Write the data to I2C display
+ I2CManager.write(m_i2cAddr, buffer, bufferPos);
return 1;
}
-
-//=============================================================================
-// SSD1306AsciiWire method definitions
-
-#define m_oledWire Wire
-
-void SSD1306AsciiWire::begin(const DevType* dev, uint8_t i2cAddr) {
-#if OPTIMIZE_I2C
- m_nData = 0;
-#endif // OPTIMIZE_I2C
- m_i2cAddr = i2cAddr;
- init(dev);
-}
-
-//------------------------------------------------------------------------------
-void SSD1306AsciiWire::writeDisplay(uint8_t b, uint8_t mode) {
-#if OPTIMIZE_I2C
- if (m_nData > 16 || (m_nData && mode == SSD1306_MODE_CMD)) {
- m_oledWire.endTransmission();
- m_nData = 0;
- }
- if (m_nData == 0) {
- m_oledWire.beginTransmission(m_i2cAddr);
- m_oledWire.write(mode == SSD1306_MODE_CMD ? 0X00 : 0X40);
- }
- m_oledWire.write(b);
- if (mode == SSD1306_MODE_RAM_BUF) {
- m_nData++;
- } else {
- m_oledWire.endTransmission();
- m_nData = 0;
- }
-#else // OPTIMIZE_I2C
- m_oledWire.beginTransmission(m_i2cAddr);
- m_oledWire.write(mode == SSD1306_MODE_CMD ? 0X00 : 0X40);
- m_oledWire.write(b);
- m_oledWire.endTransmission();
-#endif // OPTIMIZE_I2C
-}
-
-//------------------------------------------------------------------------------
-void SSD1306AsciiWire::flushDisplay() {
-#if OPTIMIZE_I2C
- if (m_nData) {
- m_oledWire.endTransmission();
- m_nData = 0;
- }
-#endif // OPTIMIZE_I2C
-}
-//------------------------------------------------------------------------------
diff --git a/SSD1306Ascii.h b/SSD1306Ascii.h
index 2b4961f..e06b4cf 100644
--- a/SSD1306Ascii.h
+++ b/SSD1306Ascii.h
@@ -12,127 +12,41 @@
* 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
+ * along with this software. If not, see
* .
*/
-/**
- * @file SSD1306AsciiWire.h
- * @brief Class for I2C displays using Wire.
- */
-#ifndef SSD1306AsciiWire_h
-#define SSD1306AsciiWire_h
-#include
+#ifndef SSD1306Ascii_h
+#define SSD1306Ascii_h
#include "Arduino.h"
-#include "LCDDisplay.h"
#include "SSD1306font.h"
#include "SSD1306init.h"
-//------------------------------------------------------------------------------
-/** SSD1306Ascii version basis */
-#define SDD1306_ASCII_VERSION 1.3.0
-//------------------------------------------------------------------------------
-// Configuration options.
-
-/** Use larger faster I2C code. */
-#define OPTIMIZE_I2C 1
-
-//------------------------------------------------------------------------------
-// Values for writeDisplay() mode parameter.
-/** Write to Command register. */
-#define SSD1306_MODE_CMD 0
-/** Write one byte to display RAM. */
-#define SSD1306_MODE_RAM 1
-/** Write to display RAM with possible buffering. */
-#define SSD1306_MODE_RAM_BUF 2
-//------------------------------------------------------------------------------
-
-/**
- * @class SSD1306Ascii
- * @brief SSD1306 base class
- */
-class SSD1306Ascii : public Print {
+class SSD1306AsciiWire : public Print {
public:
using Print::write;
- SSD1306Ascii() {}
- /**
- * @brief Clear the display and set the cursor to (0, 0).
- */
+ SSD1306AsciiWire() {}
+ // Initialize the display controller.
+ void begin(const DevType* dev, uint8_t i2cAddr);
+ // Clear the display and set the cursor to (0, 0).
void clear();
- /**
- * @brief Clear a region of the display.
- *
- * @param[in] c0 Starting column.
- * @param[in] c1 Ending column.
- * @param[in] r0 Starting row;
- * @param[in] r1 Ending row;
- * @note The final cursor position will be (c0, r0).
- */
+ // Clear a region of the display.
void clear(uint8_t c0, uint8_t c1, uint8_t r0, uint8_t r1);
- /**
- * @brief Clear a field of n fieldWidth() characters.
- *
- * @param[in] col Field start column.
- *
- * @param[in] row Field start row.
- *
- * @param[in] n Number of characters in the field.
- *
- */
- void clearField(uint8_t col, uint8_t row, uint8_t n);
- /**
- * @brief Clear the display to the end of the current line.
- * @note The number of rows cleared will be determined by the height
- * of the current font.
- * @note The cursor will be returned to the original position.
- */
- void clearToEOL();
- /**
- * @return The current column in pixels.
- */
+ // The current column in pixels.
inline uint8_t col() const { return m_col; }
- /**
- * @return The display hight in pixels.
- */
+ // The display hight in pixels.
inline uint8_t displayHeight() const { return m_displayHeight; }
- /**
- * @brief Set display to normal or 180 degree remap mode.
- *
- * @param[in] mode true for normal mode, false for remap mode.
- *
- * @note Adafruit and many ebay displays use remap mode.
- * Use normal mode to rotate these displays 180 degrees.
- */
- void displayRemap(bool mode);
- /**
- * @return The display height in rows with eight pixels to a row.
- */
+ // The display height in rows with eight pixels to a row.
inline uint8_t displayRows() const { return m_displayHeight / 8; }
- /**
- * @return The display width in pixels.
- */
+ // The display width in pixels.
inline uint8_t displayWidth() const { return m_displayWidth; }
- /**
- * @brief Set the cursor position to (0, 0).
- */
+ // Set the cursor position to (0, 0).
inline void home() { setCursor(0, 0); }
- /**
- * @brief Initialize the display controller.
- *
- * @param[in] dev A display initialization structure.
- */
+ // Initialize the display controller.
void init(const DevType* dev);
- /**
- * @return the current row number with eight pixels to a row.
- */
+ // the current row number with eight pixels to a row.
inline uint8_t row() const { return m_row; }
- /**
- * @brief Set the current column number.
- *
- * @param[in] col The desired column number in pixels.
- */
- void setCol(uint8_t col);
/**
* @brief Set the display contrast.
*
@@ -152,34 +66,6 @@ class SSD1306Ascii : public Print {
* @param[in] font Pointer to a font table.
*/
void setFont(const uint8_t* font);
- /**
- * @brief Set the current row number.
- *
- * @param[in] row the row number in eight pixel rows.
- */
- void setRow(uint8_t row);
- /**
- * @brief Write a command byte to the display controller.
- *
- * @param[in] c The command byte.
- * @note The byte will immediately be sent to the controller.
- */
- inline void ssd1306WriteCmd(uint8_t c) { writeDisplay(c, SSD1306_MODE_CMD); }
- /**
- * @brief Write a byte to RAM in the display controller.
- *
- * @param[in] c The data byte.
- * @note The byte will immediately be sent to the controller.
- */
- void ssd1306WriteRam(uint8_t c);
- /**
- * @brief Write a byte to RAM in the display controller.
- *
- * @param[in] c The data byte.
- * @note The byte may be buffered until a call to ssd1306WriteCmd
- * or ssd1306WriteRam or flushDisplay.
- */
- void ssd1306WriteRamBuf(uint8_t c);
/**
* @brief Display a character.
*
@@ -188,47 +74,24 @@ class SSD1306Ascii : public Print {
*/
size_t write(uint8_t c);
- protected:
- virtual void writeDisplay(uint8_t b, uint8_t mode) = 0;
- virtual void flushDisplay() = 0;
+ private:
uint8_t m_col; // Cursor column.
uint8_t m_row; // Cursor RAM row.
uint8_t m_displayWidth; // Display width.
uint8_t m_displayHeight; // Display height.
uint8_t m_colOffset; // Column offset RAM to SEG.
- const uint8_t* m_font = nullptr; // Current font.
+ const uint8_t* m_font = NULL; // Current font.
// Only fixed size 5x7 fonts in a 6x8 cell are supported.
- const int fontWidth = 5;
- const int fontHeight = 7;
+ const uint8_t fontWidth = 5;
+ const uint8_t fontHeight = 7;
const uint8_t letterSpacing = 1;
uint8_t m_fontFirstChar;
uint8_t m_fontCharCount;
-};
-/**
- * @class SSD1306AsciiWire
- * @brief Class for I2C displays using Wire.
- */
-class SSD1306AsciiWire : public SSD1306Ascii {
- public:
- /**
- * @brief Initialize the display controller.
- *
- * @param[in] dev A device initialization structure.
- * @param[in] i2cAddr The I2C address of the display controller.
- */
- void begin(const DevType* dev, uint8_t i2cAddr);
-
- protected:
- void writeDisplay(uint8_t b, uint8_t mode);
- void flushDisplay();
-
- protected:
uint8_t m_i2cAddr;
-#if OPTIMIZE_I2C
- uint8_t m_nData;
-#endif // OPTIMIZE_I2C
+
+ static const uint8_t blankPixels[];
};
-#endif // SSD1306AsciiWire_h
+#endif // SSD1306Ascii_h
diff --git a/SSD1306init.h b/SSD1306init.h
index fb99deb..b861b81 100644
--- a/SSD1306init.h
+++ b/SSD1306init.h
@@ -118,6 +118,7 @@ struct DevType {
/** Initialization commands for a 128x32 SSD1306 oled display. */
static const uint8_t MEM_TYPE Adafruit128x32init[] = {
// Init sequence for Adafruit 128x32 OLED module
+ 0x00, // Set to command mode
SSD1306_DISPLAYOFF,
SSD1306_SETDISPLAYCLOCKDIV, 0x80, // the suggested ratio 0x80
SSD1306_SETMULTIPLEX, 0x1F, // ratio 32
@@ -148,6 +149,7 @@ static const DevType MEM_TYPE Adafruit128x32 = {
/** Initialization commands for a 128x64 SSD1306 oled display. */
static const uint8_t MEM_TYPE Adafruit128x64init[] = {
// Init sequence for Adafruit 128x64 OLED module
+ 0x00, // Set to command mode
SSD1306_DISPLAYOFF,
SSD1306_SETDISPLAYCLOCKDIV, 0x80, // the suggested ratio 0x80
SSD1306_SETMULTIPLEX, 0x3F, // ratio 64
@@ -177,6 +179,7 @@ static const DevType MEM_TYPE Adafruit128x64 = {
// This section is based on https://github.com/stanleyhuangyc/MultiLCD
/** Initialization commands for a 128x64 SH1106 oled display. */
static const uint8_t MEM_TYPE SH1106_128x64init[] = {
+ 0x00, // Set to command mode
SSD1306_DISPLAYOFF,
SSD1306_SETSTARTPAGE | 0X0, // set page address
SSD1306_SETCONTRAST, 0x80, // 128