waveshare213v2: Move initialization to testable functions

pull/41/head
Michael Hanselmann 4 years ago
parent 347b4e237c
commit cbda71a0c8

@ -0,0 +1,75 @@
// Copyright 2021 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package waveshare2in13v2
type controller interface {
sendCommand(byte)
sendData([]byte)
waitUntilIdle()
}
func initDisplayFull(ctrl controller, opts *Opts) {
ctrl.waitUntilIdle()
ctrl.sendCommand(swReset)
ctrl.waitUntilIdle()
ctrl.sendCommand(setAnalogBlockControl)
ctrl.sendData([]byte{0x54})
ctrl.sendCommand(setDigitalBlockControl)
ctrl.sendData([]byte{0x3B})
ctrl.sendCommand(driverOutputControl)
ctrl.sendData([]byte{
byte((opts.Height - 1) % 0xFF),
byte((opts.Height - 1) / 0xFF),
0x00,
})
ctrl.sendCommand(borderWaveformControl)
ctrl.sendData([]byte{0x03})
ctrl.sendCommand(writeVcomRegister)
ctrl.sendData([]byte{0x55})
ctrl.sendCommand(gateDrivingVoltageControl)
ctrl.sendData([]byte{gateDrivingVoltage19V})
ctrl.sendCommand(sourceDrivingVoltageControl)
ctrl.sendData([]byte{sourceDrivingVoltageVSH1_15V, sourceDrivingVoltageVSH2_5V, sourceDrivingVoltageVSL_neg15V})
ctrl.sendCommand(setDummyLinePeriod)
ctrl.sendData([]byte{0x30})
ctrl.sendCommand(setGateTime)
ctrl.sendData([]byte{0x0A})
ctrl.sendCommand(writeLutRegister)
ctrl.sendData(opts.FullUpdate[:70])
}
func initDisplayPartial(ctrl controller, opts *Opts) {
ctrl.sendCommand(writeVcomRegister)
ctrl.sendData([]byte{0x26})
ctrl.waitUntilIdle()
ctrl.sendCommand(writeLutRegister)
ctrl.sendData(opts.PartialUpdate[:70])
// Undocumented command used in vendor example code.
ctrl.sendCommand(0x37)
ctrl.sendData([]byte{0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00})
ctrl.sendCommand(displayUpdateControl2)
ctrl.sendData([]byte{0xC0})
ctrl.sendCommand(masterActivation)
ctrl.waitUntilIdle()
ctrl.sendCommand(borderWaveformControl)
ctrl.sendData([]byte{0x01})
}

@ -0,0 +1,110 @@
// Copyright 2021 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package waveshare2in13v2
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)
type record struct {
cmd byte
data []byte
}
type fakeController []record
func (r *fakeController) sendCommand(cmd byte) {
*r = append(*r, record{
cmd: cmd,
})
}
func (r *fakeController) sendData(data []byte) {
cur := &(*r)[len(*r)-1]
cur.data = append(cur.data, data...)
}
func (*fakeController) waitUntilIdle() {
}
func TestInitDisplayFull(t *testing.T) {
for _, tc := range []struct {
name string
opts Opts
want []record
}{
{
name: "epd2in13v2",
opts: EPD2in13v2,
want: []record{
{cmd: swReset},
{cmd: setAnalogBlockControl, data: []byte{0x54}},
{cmd: setDigitalBlockControl, data: []byte{0x3b}},
{
cmd: driverOutputControl,
data: []byte{250 - 1, 0, 0},
},
{cmd: borderWaveformControl, data: []byte{0x03}},
{cmd: writeVcomRegister, data: []byte{0x55}},
{cmd: gateDrivingVoltageControl, data: []byte{gateDrivingVoltage19V}},
{
cmd: sourceDrivingVoltageControl,
data: []byte{
sourceDrivingVoltageVSH1_15V,
sourceDrivingVoltageVSH2_5V,
sourceDrivingVoltageVSL_neg15V,
},
},
{cmd: setDummyLinePeriod, data: []byte{0x30}},
{cmd: setGateTime, data: []byte{0x0a}},
{cmd: writeLutRegister, data: EPD2in13v2.FullUpdate},
},
},
} {
t.Run(tc.name, func(t *testing.T) {
var got fakeController
initDisplayFull(&got, &tc.opts)
if diff := cmp.Diff([]record(got), tc.want, cmpopts.EquateEmpty(), cmp.AllowUnexported(record{})); diff != "" {
t.Errorf("initDisplayFull() difference (-got +want):\n%s", diff)
}
})
}
}
func TestInitDisplayPartial(t *testing.T) {
for _, tc := range []struct {
name string
opts Opts
want []record
}{
{
name: "epd2in13v2",
opts: EPD2in13v2,
want: []record{
{cmd: writeVcomRegister, data: []byte{0x26}},
{cmd: writeLutRegister, data: EPD2in13v2.PartialUpdate},
{cmd: 0x37, data: []byte{0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00}},
{cmd: displayUpdateControl2, data: []byte{0xc0}},
{cmd: masterActivation},
{cmd: borderWaveformControl, data: []byte{0x01}},
},
},
} {
t.Run(tc.name, func(t *testing.T) {
var got fakeController
initDisplayPartial(&got, &tc.opts)
if diff := cmp.Diff([]record(got), tc.want, cmpopts.EquateEmpty(), cmp.AllowUnexported(record{})); diff != "" {
t.Errorf("initDisplayPartial() difference (-got +want):\n%s", diff)
}
})
}
}

@ -12,11 +12,6 @@ import (
"periph.io/x/devices/v3/ssd1306/image1bit"
)
type controller interface {
sendCommand(byte)
sendData([]byte)
}
// setMemoryArea configures the target drawing area (horizontal is in bytes,
// vertical in pixels).
func setMemoryArea(ctrl controller, area image.Rectangle) {

@ -14,24 +14,6 @@ import (
"periph.io/x/devices/v3/ssd1306/image1bit"
)
type record struct {
cmd byte
data []byte
}
type fakeController []record
func (r *fakeController) sendCommand(cmd byte) {
*r = append(*r, record{
cmd: cmd,
})
}
func (r *fakeController) sendData(data []byte) {
cur := &(*r)[len(*r)-1]
cur.data = append(cur.data, data...)
}
func TestDrawSpec(t *testing.T) {
for _, tc := range []struct {
name string

@ -154,89 +154,6 @@ func NewHat(p spi.Port, opts *Opts) (*Dev, error) {
return New(p, dc, cs, rst, busy, opts)
}
func (d *Dev) initFull() error {
eh := errorHandler{d: *d}
// Software Reset
eh.waitUntilIdle()
eh.sendCommand(swReset)
eh.waitUntilIdle()
// Set analog block control
eh.sendCommand(setAnalogBlockControl)
eh.sendData([]byte{0x54})
// Set digital block control
eh.sendCommand(setDigitalBlockControl)
eh.sendData([]byte{0x3B})
// Driver output control
eh.sendCommand(driverOutputControl)
eh.sendData([]byte{
byte((d.opts.Height - 1) % 0xFF),
byte((d.opts.Height - 1) / 0xFF),
0x00,
})
// Border Waveform
eh.sendCommand(borderWaveformControl)
eh.sendData([]byte{0x03})
// VCOM Voltage
eh.sendCommand(writeVcomRegister)
eh.sendData([]byte{0x55})
eh.sendCommand(gateDrivingVoltageControl)
eh.sendData([]byte{gateDrivingVoltage19V})
eh.sendCommand(sourceDrivingVoltageControl)
eh.sendData([]byte{sourceDrivingVoltageVSH1_15V, sourceDrivingVoltageVSH2_5V, sourceDrivingVoltageVSL_neg15V})
// Dummy Line
eh.sendCommand(setDummyLinePeriod)
eh.sendData([]byte{0x30})
// Gate Time
eh.sendCommand(setGateTime)
eh.sendData([]byte{0x0A})
eh.sendCommand(writeLutRegister)
eh.sendData(d.opts.FullUpdate[:70])
eh.waitUntilIdle()
return eh.err
}
func (d *Dev) initPartial() error {
eh := errorHandler{d: *d}
// VCOM Voltage
eh.sendCommand(writeVcomRegister)
eh.sendData([]byte{0x26})
eh.waitUntilIdle()
eh.sendCommand(writeLutRegister)
eh.sendData(d.opts.PartialUpdate[:70])
eh.sendCommand(0x37)
eh.sendData([]byte{0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00})
eh.sendCommand(displayUpdateControl2)
eh.sendData([]byte{0xC0})
eh.sendCommand(masterActivation)
eh.waitUntilIdle()
// Border Waveform
eh.sendCommand(borderWaveformControl)
eh.sendData([]byte{0x01})
return eh.err
}
// Init will initialize the display with the partial-update or full-update mode.
func (d *Dev) Init(partialUpdate PartialUpdate) error {
// Hardware Reset
@ -244,11 +161,15 @@ func (d *Dev) Init(partialUpdate PartialUpdate) error {
return err
}
eh := errorHandler{d: *d}
if partialUpdate {
return d.initPartial()
initDisplayPartial(&eh, d.opts)
} else {
initDisplayFull(&eh, d.opts)
}
return d.initFull()
return eh.err
}
// Clear clears the display.

Loading…
Cancel
Save