cv | links | quotes | ascii | tgtimes | gopher | mail

Solomon Systech SSD1306 OLED Screen



Small 128x32 OLED screen, the one I have is from AZ-Delivery but most if not all use the same base controller: SSD1306.

The display is controlled by a parallel interface, on top of which is connected internally an SPI and an I²C multiplexer, so that 8 bits written one after the other via an SPI or I²C packet get written in parallel to the internal display controler.

Mapping of the parallel port to I²C

The display controller already does the job of mapping the parallel port through I²C packets. The parallel pins are:

R/W: Switch between read and write mode. There is no way to set manually this pin through I²C. Instead, the read or write I²C command will sets this pin high or low as appropriate.

D0-D7: Data ports that receives the content of the I²C packets.

D/C: Switch between data and control read/write. Data for sending the pixel data, one pixel per bit (no color support on this one).

Other pins are not reachable or needed. Because there are 9 pins that need to be reached in total, there is the following encoding format to span the 9 bits over two packets:

[ 0b11000000, 0xDD ] x N
[ 0b10000000, 0xCC ] x N
0b01000000, [ 0xDD ] x N
0b00000000, [ 0xCC ] x N

For instance one write with a sequence of 1data 1control 4data

0b11000000, 0xDD, 0b10000000, 0xCC, 0b01000000, 0xDD, 0xDD, 0xDD, 0xDD

Getting the device to work under 5V

The device requires 12v of input. It will succeed to respond to I²C commands, but will fail to turn the screen on under 5V. To work around that, the SSD1306 controller offers a mode where it charges external accumulators as long as power is not in use, to release it all at once it needs to.

This is described on the last page of the datasheet, with the 0x3D, 0x14 control packet.

Only after this was set, the display can be turned on with a 0xAF control packet.

Filling the screen

The screen is composd of groups of 8 pixels named "Segment", filled by incoming data bytes where every bit maps to one pixel.

The segment correspond to vertical lines of 8 pixel.

Once a segment is filled the controller automatically switch to the next segment, therefore filling the screen segment per segment.

The order that segments are being walked through by the controller can be configured by control packets. The order I found the most convenient was the following.

 ────── NCols ──────
 000 008 010 ...│3F0│    │
  | / | / |  ...│ | │Seg │
 007 00F 017 ...│3FF│    │
  ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘─┘    │
 400 408 410 ... 7F0     │NRows
  | / | / |  ...  |      │
 407 40F 417 ... 7FF     │
 ... ... ... ... ...    ...

NCols: is the number of pixel wide, here 128

NRows: the number of pixel high, here 64.