Skip to content

Commit ed5396f

Browse files
committed
IO: Add an OLED display example
1 parent 5a61832 commit ed5396f

2 files changed

Lines changed: 136 additions & 0 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import processing.io.*;
2+
3+
// 0.96" 128x64 OLED display ("SKU 346540")
4+
SSD1306 oled;
5+
6+
void setup() {
7+
size(128, 64);
8+
9+
// the display can be set to one of these two addresses: 0x3c (default) or 0x3d
10+
// (they might be listed as 0x7a and 0x7b on the circuit board)
11+
oled = new SSD1306(I2C.list()[0], 0x3c);
12+
}
13+
14+
void draw() {
15+
line(0, 0, 127, 63);
16+
line(0, 63, 127, 0);
17+
oled.sendImage(get());
18+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import processing.io.I2C;
2+
3+
// SSD1306 is a small, inexpensive 128x64 pixels monochrome OLED display
4+
// available online as "0.96" 128x64 OLED display", SKU 346540
5+
// or from Adafruit
6+
// datasheet: https://www.adafruit.com/datasheets/SSD1306.pdf
7+
8+
class SSD1306 extends I2C {
9+
int address;
10+
11+
// there can be more than one device connected to the bus
12+
// as long as they have different addresses
13+
SSD1306(String dev, int address) {
14+
super(dev);
15+
this.address = address;
16+
init();
17+
}
18+
19+
protected void init() {
20+
writeCommand(0xae); // turn display off
21+
writeCommand(0xa8, 0x3f); // set multiplex ratio to the highest setting
22+
writeCommand(0x8d, 0x14); // enable charge pump
23+
writeCommand(0x20, 0x00); // set memory addressing mode to horizontal
24+
writeCommand(0xd5, 0x80); // set display clock divide ratio & oscillator frequency to default
25+
writeCommand(0xd3, 0x00); // no display offset
26+
writeCommand(0x40 | 0x00); // set default display start line
27+
28+
// use the following two lines to flip the display
29+
writeCommand(0xa0 | 0x01); // set segment re-map
30+
writeCommand(0xc8); // set COM output scan direction
31+
32+
writeCommand(0xda, 0x12); // set COM pins hardware configuration
33+
writeCommand(0xd9, 0xf1); // set pre-charge period to 241x DCLK
34+
writeCommand(0xdB, 0x40); // set VCOMH deselect level
35+
writeCommand(0xa4); // display RAM content (not all-on)
36+
writeCommand(0xa6); // set normal (not-inverted) display
37+
38+
// set this since we don't have access to the OLED's reset pins (?)
39+
writeCommand(0x21, 0, 127); // set column address
40+
writeCommand(0x22, 0, 7); // set page address
41+
42+
writeCommand(0x81, 0xcf); // set contrast
43+
writeCommand(0x2e); // deactivate scroll
44+
writeCommand(0xaf); // turn display on
45+
}
46+
47+
void invert(boolean inverted) {
48+
if (inverted) {
49+
writeCommand(0xa7);
50+
} else {
51+
writeCommand(0xa6);
52+
}
53+
}
54+
55+
void sendImage(PImage img) {
56+
sendImage(img, 0, 0);
57+
}
58+
59+
void sendImage(PImage img, int startX, int startY) {
60+
byte[] frame = new byte[1024];
61+
img.loadPixels();
62+
for (int y=startY; y < height && y-startY < 64; y++) {
63+
for (int x=startX; x < width && x-startX < 128; x++) {
64+
if (brightness(img.pixels[y*img.width+x]) < 128) {
65+
// this isn't the normal (scanline) mapping, but 8 pixels below each other at a time
66+
// white pixels have their bit turned on
67+
frame[x + (y/8)*128] |= (1 << (y % 8));
68+
}
69+
}
70+
}
71+
sendFramebuffer(frame);
72+
}
73+
74+
void sendFramebuffer(byte[] buf) {
75+
if (buf.length != 1024) {
76+
System.err.println("The framebuffer should be 1024 bytes long, with one bit per pixel");
77+
throw new IllegalArgumentException("Unexpected buffer size");
78+
}
79+
80+
writeCommand(0x00 | 0x0); // set start address
81+
writeCommand(0x10 | 0x0); // set higher column start address
82+
writeCommand(0x40 | 0x0); // set start line
83+
84+
// send the frame buffer as 16 byte long packets
85+
for (int i=0; i < buf.length/16; i++) {
86+
super.beginTransmission(address);
87+
super.write(0x40); // indicates data write
88+
for (int j=0; j < 16; j++) {
89+
super.write(buf[i*16+j]);
90+
}
91+
super.endTransmission();
92+
}
93+
}
94+
95+
protected void writeCommand(int arg1) {
96+
super.beginTransmission(address);
97+
super.write(0x00); // indicates command write
98+
super.write(arg1);
99+
super.endTransmission();
100+
}
101+
102+
protected void writeCommand(int arg1, int arg2) {
103+
super.beginTransmission(address);
104+
super.write(0x00);
105+
super.write(arg1);
106+
super.write(arg2);
107+
super.endTransmission();
108+
}
109+
110+
protected void writeCommand(int arg1, int arg2, int arg3) {
111+
super.beginTransmission(address);
112+
super.write(0x00);
113+
super.write(arg1);
114+
super.write(arg2);
115+
super.write(arg3);
116+
super.endTransmission();
117+
}
118+
}

0 commit comments

Comments
 (0)