Skip to content

Commit dd6f498

Browse files
authored
ssd1306: Add support for SH1106 and SH1107 (#104)
* Add support for SH1106 Chip * Add support for SH1107 Chip * Expand example w/ Geometric drawing examples. * Cleanup code to use constants.
1 parent 9a7f7ac commit dd6f498

File tree

5 files changed

+277
-84
lines changed

5 files changed

+277
-84
lines changed

ssd1306/doc.go

+18-6
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@
22
// Use of this source code is governed under the Apache License, Version 2.0
33
// that can be found in the LICENSE file.
44

5-
// Package ssd1306 controls a 128x64 monochrome OLED display via a SSD1306
6-
// controller.
5+
// Package ssd1306 controls a monochrome OLED display via a SSD1306, SH1106,
6+
// or SH1107 controller. The driver automatically detects the variant and
7+
// adjusts accordingly.
78
//
89
// The driver does differential updates: it only sends modified pixels for the
910
// smallest rectangle, to economize bus bandwidth. This is especially important
1011
// when using I²C as the bus default speed (often 100kHz) is slow enough to
1112
// saturate the bus at less than 10 frames per second.
1213
//
13-
// The SSD1306 is a write-only device. It can be driven on either I²C or SPI
14-
// with 4 wires. Changing between protocol is likely done through resistor
15-
// soldering, for boards that support both.
14+
// The device can be driven on either I²C or SPI with 4 wires. Changing
15+
// between protocol is likely done through resistor soldering, for boards that
16+
// support both.
1617
//
1718
// Some boards expose a RES / Reset pin. If present, it must be normally be
1819
// High. When set to Low (Ground), it enables the reset circuitry. It can be
@@ -25,11 +26,22 @@
2526
// # Datasheets
2627
//
2728
// Product page:
29+
//
30+
// # SSD1306
31+
//
2832
// http://www.solomon-systech.com/en/product/display-ic/oled-driver-controller/ssd1306/
2933
//
3034
// https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf
3135
//
3236
// "DM-OLED096-624": https://drive.google.com/file/d/0B5lkVYnewKTGaEVENlYwbDkxSGM/view
3337
//
34-
// "ssd1306": https://drive.google.com/file/d/0B5lkVYnewKTGYzhyWWp0clBMR1E/view
38+
// # SH1106
39+
//
40+
// https://cdn.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf
41+
//
42+
// # SH1107
43+
//
44+
// https://www.adafruit.com/product/5297
45+
//
46+
// https://www.displayfuture.com/Display/datasheet/controller/SH1107.pdf
3547
package ssd1306

ssd1306/example_test.go

+64-13
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@
55
package ssd1306_test
66

77
import (
8+
"flag"
9+
"fmt"
810
"image"
11+
"image/color"
12+
"image/draw"
913
"log"
14+
"math"
15+
"time"
1016

1117
"periph.io/x/conn/v3/i2c/i2creg"
1218
"periph.io/x/devices/v3/ssd1306"
@@ -19,35 +25,80 @@ func Example() {
1925
if _, err := host.Init(); err != nil {
2026
log.Fatal(err)
2127
}
22-
28+
var width = flag.Int("width", 128, "Display Width")
29+
var height = flag.Int("height", 64, "Display Height")
30+
flag.Parse()
2331
// Use i2creg I²C bus registry to find the first available I²C bus.
2432
b, err := i2creg.Open("")
2533
if err != nil {
2634
log.Fatal(err)
2735
}
2836
defer b.Close()
29-
30-
dev, err := ssd1306.NewI2C(b, &ssd1306.DefaultOpts)
37+
opts := ssd1306.DefaultOpts
38+
opts.W = *width
39+
opts.H = *height
40+
if opts.H == 32 {
41+
opts.Sequential = true
42+
}
43+
dev, err := ssd1306.NewI2C(b, &opts)
3144
if err != nil {
32-
log.Fatalf("failed to initialize ssd1306: %v", err)
45+
log.Fatalf("failed to initialize display: %s", err.Error())
3346
}
47+
fmt.Printf("device=%s\n", dev.String())
3448

35-
// Draw on it.
3649
img := image1bit.NewVerticalLSB(dev.Bounds())
3750
// Note: this code is commented out so periph does not depend on:
3851
// "golang.org/x/image/font"
3952
// "golang.org/x/image/font/basicfont"
4053
// "golang.org/x/image/math/fixed"
4154
//
42-
// f := basicfont.Face7x13
43-
// drawer := font.Drawer{
44-
// Dst: img,
45-
// Src: &image.Uniform{image1bit.On},
46-
// Face: f,
47-
// Dot: fixed.P(0, img.Bounds().Dy()-1-f.Descent),
48-
// }
49-
// drawer.DrawString("Hello from periph!")
55+
// Draw on it.
56+
/*
57+
f := basicfont.Face7x13
58+
drawer := font.Drawer{
59+
Dst: img,
60+
Src: &image.Uniform{image1bit.On},
61+
62+
Face: f,
63+
Dot: fixed.P(0, img.Bounds().Dy()-1-f.Descent),
64+
}
65+
drawer.DrawString("Hello from periph!")
66+
_ = dev.Draw(dev.Bounds(), img, image.Point{})
67+
time.Sleep(5 * time.Second)
68+
*/
69+
70+
white := color.RGBA{255, 255, 255, 255}
71+
black := color.RGBA{0, 0, 0, 255}
72+
colors := []color.RGBA{white, black}
73+
74+
rectNum := 0
75+
// Draw some nested rectangles
76+
for w, h := opts.W, opts.H; w > 0 && h > 0; w, h = w-4, h-4 {
77+
rect := image.Rect(0, 0, w, h)
78+
draw.Draw(img, rect.Add(image.Point{X: rectNum * 2, Y: rectNum * 2}), &image.Uniform{colors[rectNum%2]}, image.Point{}, draw.Src)
79+
rectNum += 1
80+
}
81+
5082
if err := dev.Draw(dev.Bounds(), img, image.Point{}); err != nil {
5183
log.Fatal(err)
5284
}
85+
time.Sleep(5 * time.Second)
86+
87+
// Draw a Sine Wave
88+
_ = dev.Invert(true)
89+
img = image1bit.NewVerticalLSB(dev.Bounds())
90+
img.DrawHLine(0, opts.W, opts.H>>1-1, image1bit.On)
91+
img.DrawVLine(0, opts.H, opts.W>>1-1, image1bit.On)
92+
angle := float64(0)
93+
angleStep := float64((4 * math.Pi) / float64(opts.W))
94+
scale := float64((opts.H >> 1) - 4)
95+
for step := opts.W - 1; step >= 0; step -= 1 {
96+
y := int(float64(math.Sin(angle)*scale)) + opts.H>>1
97+
img.SetBit(step, y, image1bit.On)
98+
angle += angleStep
99+
}
100+
_ = dev.Draw(dev.Bounds(), img, image.Point{})
101+
time.Sleep(10 * time.Second)
102+
103+
_ = dev.Halt()
53104
}

ssd1306/image1bit/image1bit.go

+14
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,20 @@ func (i *VerticalLSB) SetBit(x, y int, b Bit) {
143143
}
144144
}
145145

146+
// Draw a horizontal line from start to end at ypos
147+
func (i *VerticalLSB) DrawHLine(start, end, ypos int, b Bit) {
148+
for x := start; x < end; x++ {
149+
i.SetBit(x, ypos, b)
150+
}
151+
}
152+
153+
// Draw a vertical line from start to end at xpos
154+
func (i *VerticalLSB) DrawVLine(start, end, xpos int, b Bit) {
155+
for y := start; y < end; y++ {
156+
i.SetBit(xpos, y, b)
157+
}
158+
}
159+
146160
/*
147161
// SubImage returns an image representing the portion of the image p visible
148162
// through r. The returned value shares pixels with the original image.

0 commit comments

Comments
 (0)