From 97f34506217605e41b01f14b3a8c8c8bfd5efa7b Mon Sep 17 00:00:00 2001 From: Neil McKechnie Date: Wed, 24 Nov 2021 12:53:03 +0000 Subject: [PATCH] Simplify OLED driver initialisation. Simplify the initialisation in the SSD1306Ascii driver, by removing some of the complex structures that were inherited from the library on which it is based. This should also allow it to compile on the ESP32 platform. --- SSD1306Ascii.cpp | 170 ++++++++++++++++++++--------------------------- SSD1306Ascii.h | 25 +------ 2 files changed, 72 insertions(+), 123 deletions(-) diff --git a/SSD1306Ascii.cpp b/SSD1306Ascii.cpp index 17fd5a2..2fc23c2 100644 --- a/SSD1306Ascii.cpp +++ b/SSD1306Ascii.cpp @@ -89,28 +89,93 @@ const uint8_t FLASH SSD1306AsciiWire::blankPixels[30] = {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}; + +//============================================================================== +// this section is based on https://github.com/adafruit/Adafruit_SSD1306 + +/** Initialization commands for a 128x32 or 128x64 SSD1306 oled display. */ +const uint8_t FLASH SSD1306AsciiWire::Adafruit128xXXinit[] = { + // Init sequence for Adafruit 128x32/64 OLED module + 0x00, // Set to command mode + SSD1306_DISPLAYOFF, + SSD1306_SETDISPLAYCLOCKDIV, 0x80, // the suggested ratio 0x80 + SSD1306_SETMULTIPLEX, 0x3F, // ratio 64 (initially) + SSD1306_SETDISPLAYOFFSET, 0x0, // no offset + SSD1306_SETSTARTLINE | 0x0, // line #0 + SSD1306_CHARGEPUMP, 0x14, // internal vcc + SSD1306_MEMORYMODE, 0x02, // page mode + SSD1306_SEGREMAP | 0x1, // column 127 mapped to SEG0 + SSD1306_COMSCANDEC, // column scan direction reversed + SSD1306_SETCOMPINS, 0X12, // set COM pins + SSD1306_SETCONTRAST, 0x7F, // contrast level 127 + SSD1306_SETPRECHARGE, 0xF1, // pre-charge period (1, 15) + SSD1306_SETVCOMDETECT, 0x40, // vcomh regulator level + SSD1306_DISPLAYALLON_RESUME, + SSD1306_NORMALDISPLAY, + SSD1306_DISPLAYON +}; + +//------------------------------------------------------------------------------ +// This section is based on https://github.com/stanleyhuangyc/MultiLCD + +/** Initialization commands for a 128x64 SH1106 oled display. */ +const uint8_t FLASH SSD1306AsciiWire::SH1106_132x64init[] = { + 0x00, // Set to command mode + SSD1306_DISPLAYOFF, + SSD1306_SETDISPLAYCLOCKDIV, 0X80, // set osc division + SSD1306_SETMULTIPLEX, 0x3F, // ratio 64 + SSD1306_SETDISPLAYOFFSET, 0X00, // set display offset + SSD1306_SETSTARTPAGE | 0X0, // set page address + SSD1306_SETSTARTLINE | 0x0, // set start line + SH1106_SET_PUMP_MODE, SH1106_PUMP_ON, // set charge pump enable + SSD1306_SEGREMAP | 0X1, // set segment remap + SSD1306_COMSCANDEC, // Com scan direction + SSD1306_SETCOMPINS, 0X12, // set COM pins + SSD1306_SETCONTRAST, 0x80, // 128 + SSD1306_SETPRECHARGE, 0X1F, // set pre-charge period + SSD1306_SETVCOMDETECT, 0x40, // set vcomh + SH1106_SET_PUMP_VOLTAGE | 0X2, // 8.0 volts + SSD1306_NORMALDISPLAY, // normal / reverse + SSD1306_DISPLAYON +}; + //============================================================================== // SSD1306AsciiWire Method Definitions //------------------------------------------------------------------------------ // Constructor SSD1306AsciiWire::SSD1306AsciiWire(int width, int height) { + m_displayWidth = width; + m_displayHeight = height; // Set size in characters in base class lcdRows = height / 8; lcdCols = width / 6; + m_col = 0; + m_row = 0; + m_colOffset = 0; I2CManager.begin(); I2CManager.setClock(400000L); // Set max supported I2C speed for (byte address = 0x3c; address <= 0x3d; address++) { if (I2CManager.exists(address)) { + m_i2cAddr = address; + if (m_displayWidth==132 && m_displayHeight==64) { + // SH1106 display. This uses 128x64 centered within a 132x64 OLED. + m_colOffset = 2; + I2CManager.write_P(address, SH1106_132x64init, sizeof(SH1106_132x64init)); + } else if (m_displayWidth==128 && (m_displayHeight==64 || m_displayHeight==32)) { + // SSD1306 128x64 or 128x32 + I2CManager.write_P(address, Adafruit128xXXinit, sizeof(Adafruit128xXXinit)); + if (m_displayHeight == 32) + I2CManager.write(address, 5, 0, // Set command mode + SSD1306_SETMULTIPLEX, 0x1F, // ratio 32 + SSD1306_SETCOMPINS, 0x02); // sequential COM pins, disable remap + } else { + DIAG(F("OLED configuration option not recognised")); + return; + } // Device found DIAG(F("%dx%d OLED display configured on I2C:x%x"), width, height, address); - if (width == 132) - begin(&SH1106_132x64, address); - else if (height == 32) - begin(&Adafruit128x32, address); - else - begin(&Adafruit128x64, address); // Set singleton address lcdDisplay = this; clear(); @@ -132,23 +197,6 @@ void SSD1306AsciiWire::clearNative() { } } -// Initialise device -void SSD1306AsciiWire::begin(const DevType* dev, uint8_t i2cAddr) { - m_i2cAddr = i2cAddr; - m_col = 0; - m_row = 0; - const uint8_t* table = (const uint8_t*)GETFLASHW(&dev->initcmds); - uint8_t size = GETFLASH(&dev->initSize); - m_displayWidth = GETFLASH(&dev->lcdWidth); - m_displayHeight = GETFLASH(&dev->lcdHeight); - m_colOffset = GETFLASH(&dev->colOffset); - I2CManager.write_P(m_i2cAddr, table, size); - if (m_displayHeight == 32) - I2CManager.write(m_i2cAddr, 5, 0, // Set command mode - SSD1306_SETMULTIPLEX, 0x1F, // ratio 32 - SSD1306_SETCOMPINS, 0x02); // sequential COM pins, disable remap -} - //------------------------------------------------------------------------------ // Set cursor position (by text line) @@ -209,82 +257,6 @@ size_t SSD1306AsciiWire::writeNative(uint8_t ch) { return 1; } -//============================================================================== -// this section is based on https://github.com/adafruit/Adafruit_SSD1306 - -/** Initialization commands for a 128x32 or 128x64 SSD1306 oled display. */ -const uint8_t FLASH SSD1306AsciiWire::Adafruit128xXXinit[] = { - // Init sequence for Adafruit 128x32/64 OLED module - 0x00, // Set to command mode - SSD1306_DISPLAYOFF, - SSD1306_SETDISPLAYCLOCKDIV, 0x80, // the suggested ratio 0x80 - SSD1306_SETMULTIPLEX, 0x3F, // ratio 64 (initially) - SSD1306_SETDISPLAYOFFSET, 0x0, // no offset - SSD1306_SETSTARTLINE | 0x0, // line #0 - SSD1306_CHARGEPUMP, 0x14, // internal vcc - SSD1306_MEMORYMODE, 0x02, // page mode - SSD1306_SEGREMAP | 0x1, // column 127 mapped to SEG0 - SSD1306_COMSCANDEC, // column scan direction reversed - SSD1306_SETCOMPINS, 0X12, // set COM pins - SSD1306_SETCONTRAST, 0x7F, // contrast level 127 - SSD1306_SETPRECHARGE, 0xF1, // pre-charge period (1, 15) - SSD1306_SETVCOMDETECT, 0x40, // vcomh regulator level - SSD1306_DISPLAYALLON_RESUME, - SSD1306_NORMALDISPLAY, - SSD1306_DISPLAYON -}; - -/** Initialize a 128x32 SSD1306 oled display. */ -const DevType FLASH SSD1306AsciiWire::Adafruit128x32 = { - Adafruit128xXXinit, - sizeof(Adafruit128xXXinit), - 128, - 32, - 0 -}; - -/** Initialize a 128x64 oled display. */ -const DevType FLASH SSD1306AsciiWire::Adafruit128x64 = { - Adafruit128xXXinit, - sizeof(Adafruit128xXXinit), - 128, - 64, - 0 -}; -//------------------------------------------------------------------------------ -// This section is based on https://github.com/stanleyhuangyc/MultiLCD - -/** Initialization commands for a 128x64 SH1106 oled display. */ -const uint8_t FLASH SSD1306AsciiWire::SH1106_132x64init[] = { - 0x00, // Set to command mode - SSD1306_DISPLAYOFF, - SSD1306_SETDISPLAYCLOCKDIV, 0X80, // set osc division - SSD1306_SETMULTIPLEX, 0x3F, // ratio 64 - SSD1306_SETDISPLAYOFFSET, 0X00, // set display offset - SSD1306_SETSTARTPAGE | 0X0, // set page address - SSD1306_SETSTARTLINE | 0x0, // set start line - SH1106_SET_PUMP_MODE, SH1106_PUMP_ON, // set charge pump enable - SSD1306_SEGREMAP | 0X1, // set segment remap - SSD1306_COMSCANDEC, // Com scan direction - SSD1306_SETCOMPINS, 0X12, // set COM pins - SSD1306_SETCONTRAST, 0x80, // 128 - SSD1306_SETPRECHARGE, 0X1F, // set pre-charge period - SSD1306_SETVCOMDETECT, 0x40, // set vcomh - SH1106_SET_PUMP_VOLTAGE | 0X2, // 8.0 volts - SSD1306_NORMALDISPLAY, // normal / reverse - SSD1306_DISPLAYON -}; - -/** Initialize a 132x64 oled SH1106 display. */ -const DevType FLASH SSD1306AsciiWire::SH1106_132x64 = { - SH1106_132x64init, - sizeof(SH1106_132x64init), - 128, - 64, - 2 // SH1106 is a 132x64 controller but most OLEDs are only attached - // to columns 2-129. -}; - //------------------------------------------------------------------------------ diff --git a/SSD1306Ascii.h b/SSD1306Ascii.h index 90a7e7e..312a62f 100644 --- a/SSD1306Ascii.h +++ b/SSD1306Ascii.h @@ -32,21 +32,6 @@ //#define NOLOWERCASE //------------------------------------------------------------------------------ -// Device initialization structure. - -struct DevType { - /* Pointer to initialization command bytes. */ - const uint8_t* initcmds; - /* Number of initialization bytes */ - const uint8_t initSize; - /* Width of the display in pixels */ - const uint8_t lcdWidth; - /** Height of the display in pixels. */ - const uint8_t lcdHeight; - /* Column offset RAM to display. Used to pick start column of SH1106. */ - const uint8_t colOffset; -}; - // Constructor class SSD1306AsciiWire : public LCDDisplay { public: @@ -55,25 +40,17 @@ class SSD1306AsciiWire : public LCDDisplay { SSD1306AsciiWire(int width, int height); // Initialize the display controller. - void begin(const DevType* dev, uint8_t i2cAddr); + void begin(uint8_t i2cAddr); // Clear the display and set the cursor to (0, 0). void clearNative() override; // Set cursor to start of specified text line void setRowNative(byte line) override; - - // Initialize the display controller. - void init(const DevType* dev); // Write one character to OLED size_t writeNative(uint8_t c) override; - // Display characteristics / initialisation - static const DevType FLASH Adafruit128x32; - static const DevType FLASH Adafruit128x64; - static const DevType FLASH SH1106_132x64; - bool isBusy() override { return requestBlock.isBusy(); } private: