113 lines
2.1 KiB
Go
113 lines
2.1 KiB
Go
|
package display
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"image"
|
||
|
"image/color"
|
||
|
"log"
|
||
|
"sync"
|
||
|
|
||
|
"golang.org/x/image/font"
|
||
|
"golang.org/x/image/font/inconsolata"
|
||
|
"golang.org/x/image/math/fixed"
|
||
|
"periph.io/x/conn/v3/i2c"
|
||
|
"periph.io/x/conn/v3/i2c/i2creg"
|
||
|
"periph.io/x/devices/v3/ssd1306"
|
||
|
"periph.io/x/host/v3"
|
||
|
)
|
||
|
|
||
|
type displaySsd1306 struct {
|
||
|
mutex sync.Mutex
|
||
|
logger *log.Logger
|
||
|
|
||
|
font font.Face
|
||
|
bus i2c.BusCloser
|
||
|
dev *ssd1306.Dev
|
||
|
img *image.Gray
|
||
|
}
|
||
|
|
||
|
func newSsd1306(logger *log.Logger) (Display, error) {
|
||
|
if _, err := host.Init(); err != nil {
|
||
|
return nil, fmt.Errorf("drivers init: %w(may be i2c is disabled)", err)
|
||
|
}
|
||
|
|
||
|
// Setup device
|
||
|
bus, err := i2creg.Open("")
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("open i2c bus: %w", err)
|
||
|
}
|
||
|
opts := ssd1306.Opts{
|
||
|
W: 128,
|
||
|
H: 32,
|
||
|
Rotated: false,
|
||
|
Sequential: true,
|
||
|
SwapTopBottom: false,
|
||
|
}
|
||
|
dev, err := ssd1306.NewI2C(bus, &opts)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("create i2c: %w", err)
|
||
|
}
|
||
|
|
||
|
// Create image
|
||
|
img := image.NewGray(image.Rect(0, 0, dev.Bounds().Dx(), dev.Bounds().Dy()))
|
||
|
|
||
|
return &displaySsd1306{
|
||
|
logger: logger,
|
||
|
font: inconsolata.Regular8x16,
|
||
|
bus: bus,
|
||
|
dev: dev,
|
||
|
img: img,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (d *displaySsd1306) GetImg() *image.Gray {
|
||
|
d.mutex.Lock()
|
||
|
defer d.mutex.Unlock()
|
||
|
|
||
|
return d.img
|
||
|
}
|
||
|
|
||
|
func (d *displaySsd1306) GetFont() font.Face {
|
||
|
return d.font
|
||
|
}
|
||
|
|
||
|
func (d *displaySsd1306) Clear() error {
|
||
|
d.mutex.Lock()
|
||
|
defer d.mutex.Unlock()
|
||
|
|
||
|
for i := range d.img.Pix {
|
||
|
d.img.Pix[i] = 0
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (d *displaySsd1306) PutText(x, y int, text string) error {
|
||
|
d.mutex.Lock()
|
||
|
defer d.mutex.Unlock()
|
||
|
|
||
|
// Create font drawer
|
||
|
col := color.Gray{255}
|
||
|
point := fixed.Point26_6{X: fixed.I(x), Y: fixed.I(y)}
|
||
|
|
||
|
drawer := &font.Drawer{
|
||
|
Dst: d.img,
|
||
|
Src: image.NewUniform(col),
|
||
|
Face: d.font,
|
||
|
Dot: point,
|
||
|
}
|
||
|
drawer.DrawString(text)
|
||
|
|
||
|
d.dev.Draw(d.img.Bounds(), d.img, image.Point{})
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (d *displaySsd1306) Close() error {
|
||
|
d.mutex.Lock()
|
||
|
defer d.mutex.Unlock()
|
||
|
|
||
|
if err := d.bus.Close(); err != nil {
|
||
|
d.logger.Println("Close i2c bus:", err.Error())
|
||
|
}
|
||
|
return nil
|
||
|
}
|