This part has a page of its own, with a note on using it and a circuit to try: the part page.
SSD1306 OLED display
The 128x64 OLED module every hobby kit has, over I2C. Aliases: 0.96 inch OLED, I2C OLED display.
Two wires and power. The part is an I2C slave decoded straight off the pin edges, a command interpreter, and 1 KB of display RAM. There is no I2C peripheral on the Uno or the ESP32-C3 in Mokxi, so the bus is bit-banged, and the module's own 4k7 pull-ups (modeled here too) are what bring the lines back up.
Pins
| Pin | What it does |
|---|---|
VCC |
Supply. |
GND |
Ground. |
SCL |
Open-drain clock. |
SDA |
Open-drain data. |
Properties
address: the I2C address, 0x3C by default (the alternate 0x3D also works).
What the model gets right
The part models the command set the common libraries actually send (display on and off, addressing mode, column and page windows, inverse, entire-display-on, contrast, segment remap and COM scan direction) in all three addressing modes, so a driver written against a real panel works here unchanged. A 128x64 monochrome frame is 1024 bytes; on an Uno, sending all of it over the bit-banged bus takes a third of a second, which is why the firmware library sends only the 8-column blocks of each page that actually changed.
What it does not model
It never stretches the clock. A real SSD1306 can hold SCL low to make the master
wait; this one acknowledges every byte immediately and always. A driver that relies on
clock stretching works here and might not on the bench, and, the other way around, a
master that ignores stretching passes here and would corrupt a real panel.
The bus has no errors in it. The slave acknowledges its own address and every byte sent to it, and answers nothing else at all: there is no read transfer, no NACK, no arbitration, no bus timeout and no way to make it fail. Nothing checks the clock rate either, so a bit-banged bus at any speed works.
The charge pump is modeled. A module has one supply pin and the 7.5 V the panel
needs comes from a pump inside the chip, which powers up off. 0x8D 0x14 starts it and
0x8D 0x10 stops it, and the glass is lit only when the display is on and the pump
is running, so a driver that sends 0xAF and forgets 0x8D gets the same dark panel
here that it gets on the bench, which is one of the two commonest reasons a real
SSD1306 stays black.
Several other commands are taken and thrown away. The multiplex
ratio, the display offset, the display clock divide, pre-charge, COM pin configuration,
VCOMH deselect and the start line are all accepted and stored and change nothing on the
glass. Hardware scrolling
(0x26–0x2F) is accepted and ignored, so a scrolling banner stands still.
Contrast (0x81) reaches the canvas as one of sixteen brightness steps rather than as
the real panel's 256, and there is no refresh rate, no pixel persistence and no burn-in.
Reads from the panel are not modeled at all.
Code
The Adafruit tutorial compiles as it stands on every board but the ATtiny85:
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display(128, 64, &Wire, -1);
void setup() {
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) for (;;);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Hello, world!");
display.drawRect(0, 20, 40, 20, SSD1306_WHITE);
display.display();
}
Both headers are Mokxi's own, on mokxi_ssd1306.h, so a frame costs what that
driver's does: only the blocks that changed go over the bus. What is there:
clearDisplay, display, drawPixel, lines, rectangles, rounded rectangles,
circles and triangles outlined and filled, one-bit bitmaps, setTextSize,
setTextColor, setCursor, print and println, setRotation,
invertDisplay and dim. What differs from upstream:
- The font is Mokxi's own 5x7, in the same 6x8 cell, with capitals, digits and
punctuation. Lower case prints as capitals, and
setFontis not there. begin()leaves the panel blank where upstream draws its logo.- A
128, 32sketch draws in the top half of this 128x64 part. Thessd1306x32is the 0.91 inch strip such a sketch is written for, and the 1.3 inch module is an SH1106, which needs its own library. - Only the I2C constructors. The SPI ones name a module Mokxi does not have.
- On an Uno the frame is 1 KB of the 2 KB of RAM, the same cost as upstream. The ATtiny85 has 512 bytes, so the header stops with a message there.
Common mistakes
Wiring 0xA0/0xC0 instead of 0xA1/0xC8 (or trusting the power-on default) and
getting a mirrored picture. A real 128x64 module needs those two commands to draw
upright, and every library sends them for exactly that reason.
See it in action
OLED pong, OLED dice and Binary clock all drive an SSD1306. Open them at /templates, and read the parts games are made of for the fuller story of the bus and the driver.