From fa1704106c44ef4846e7acf3b105f61f179371de Mon Sep 17 00:00:00 2001 From: Yurii Soldak Date: Sun, 9 Nov 2025 22:16:13 +0100 Subject: [PATCH 1/3] ssd1xxx: break dependency from machine package --- internal/pin/internalpin.go | 13 +++++++++++ ssd1289/pinbus.go | 31 +++++++++---------------- ssd1289/ssd1289.go | 45 +++++++++++++++++++------------------ ssd1306/ssd1306_spi.go | 26 ++++++++++++--------- ssd1331/ssd1331.go | 25 ++++++++++++--------- ssd1351/ssd1351.go | 37 +++++++++++++++--------------- 6 files changed, 95 insertions(+), 82 deletions(-) diff --git a/internal/pin/internalpin.go b/internal/pin/internalpin.go index 6879f3480..c65b377cf 100644 --- a/internal/pin/internalpin.go +++ b/internal/pin/internalpin.go @@ -70,3 +70,16 @@ type Output interface { type Input interface { Get() (level bool) } + +// OutputStruct implements optional convenience methods +type OutputStruct struct { + Output +} + +func (p OutputStruct) High() { + p.Set(true) +} + +func (p OutputStruct) Low() { + p.Set(false) +} diff --git a/ssd1289/pinbus.go b/ssd1289/pinbus.go index aacdf79aa..7dde7b675 100644 --- a/ssd1289/pinbus.go +++ b/ssd1289/pinbus.go @@ -1,15 +1,19 @@ package ssd1289 -import "machine" +import ( + "tinygo.org/x/drivers/internal/legacy" + "tinygo.org/x/drivers/internal/pin" +) type pinBus struct { - pins [16]machine.Pin + pins [16]pin.Output } -func NewPinBus(pins [16]machine.Pin) pinBus { +func NewPinBus(pins [16]pin.Output) pinBus { + // configure GPIO pins (on baremetal targets only, for backwards compatibility) for i := 0; i < 16; i++ { - pins[i].Configure(machine.PinConfig{Mode: machine.PinOutput}) + legacy.ConfigurePinOut(pins[i]) } return pinBus{ @@ -18,20 +22,7 @@ func NewPinBus(pins [16]machine.Pin) pinBus { } func (b pinBus) Set(data uint16) { - b.pins[15].Set((data & (1 << 15)) != 0) - b.pins[14].Set((data & (1 << 14)) != 0) - b.pins[13].Set((data & (1 << 13)) != 0) - b.pins[12].Set((data & (1 << 12)) != 0) - b.pins[11].Set((data & (1 << 11)) != 0) - b.pins[10].Set((data & (1 << 10)) != 0) - b.pins[9].Set((data & (1 << 9)) != 0) - b.pins[8].Set((data & (1 << 8)) != 0) - b.pins[7].Set((data & (1 << 7)) != 0) - b.pins[6].Set((data & (1 << 6)) != 0) - b.pins[5].Set((data & (1 << 5)) != 0) - b.pins[4].Set((data & (1 << 4)) != 0) - b.pins[3].Set((data & (1 << 3)) != 0) - b.pins[2].Set((data & (1 << 2)) != 0) - b.pins[1].Set((data & (1 << 1)) != 0) - b.pins[0].Set((data & (1 << 0)) != 0) + for i := 15; i >= 0; i-- { + b.pins[i].Set((data & (1 << i)) != 0) + } } diff --git a/ssd1289/ssd1289.go b/ssd1289/ssd1289.go index f5cc22a0e..848d9d39f 100644 --- a/ssd1289/ssd1289.go +++ b/ssd1289/ssd1289.go @@ -5,8 +5,10 @@ package ssd1289 import ( "image/color" - "machine" "time" + + "tinygo.org/x/drivers/internal/legacy" + "tinygo.org/x/drivers/internal/pin" ) type Bus interface { @@ -14,35 +16,24 @@ type Bus interface { } type Device struct { - rs machine.Pin - wr machine.Pin - cs machine.Pin - rst machine.Pin + rs pin.OutputStruct + wr pin.OutputStruct + cs pin.OutputStruct + rst pin.OutputStruct bus Bus } const width = int16(240) const height = int16(320) -func New(rs machine.Pin, wr machine.Pin, cs machine.Pin, rst machine.Pin, bus Bus) Device { - d := Device{ - rs: rs, - wr: wr, - cs: cs, - rst: rst, +func New(rs, wr, cs, rst pin.Output, bus Bus) *Device { + return &Device{ + rs: pin.OutputStruct{Output: rs}, + wr: pin.OutputStruct{Output: wr}, + cs: pin.OutputStruct{Output: cs}, + rst: pin.OutputStruct{Output: rst}, bus: bus, } - - rs.Configure(machine.PinConfig{Mode: machine.PinOutput}) - wr.Configure(machine.PinConfig{Mode: machine.PinOutput}) - cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) - rst.Configure(machine.PinConfig{Mode: machine.PinOutput}) - - cs.High() - rst.High() - wr.High() - - return d } func (d *Device) lcdWriteCom(cmd Command) { @@ -71,6 +62,16 @@ func (d *Device) lcdWriteBusInt(data uint16) { } func (d *Device) Configure() { + + // configure GPIO pins (only on baremetal targets) + legacy.ConfigurePinOut(d.rs) + legacy.ConfigurePinOut(d.wr) + legacy.ConfigurePinOut(d.cs) + legacy.ConfigurePinOut(d.rst) + + d.cs.High() + d.wr.High() + d.rst.High() time.Sleep(time.Millisecond * 5) d.rst.Low() diff --git a/ssd1306/ssd1306_spi.go b/ssd1306/ssd1306_spi.go index d96299de5..1b50c8bc5 100644 --- a/ssd1306/ssd1306_spi.go +++ b/ssd1306/ssd1306_spi.go @@ -1,37 +1,41 @@ package ssd1306 import ( - "machine" "time" "tinygo.org/x/drivers" + "tinygo.org/x/drivers/internal/legacy" + "tinygo.org/x/drivers/internal/pin" ) type SPIBus struct { wire drivers.SPI - dcPin machine.Pin - resetPin machine.Pin - csPin machine.Pin + dcPin pin.OutputStruct + resetPin pin.OutputStruct + csPin pin.OutputStruct buffer []byte // buffer to avoid heap allocations } // NewSPI creates a new SSD1306 connection. The SPI wire must already be configured. -func NewSPI(bus drivers.SPI, dcPin, resetPin, csPin machine.Pin) *Device { - dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) - resetPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) - csPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) +func NewSPI(bus drivers.SPI, dcPin, resetPin, csPin pin.Output) *Device { return &Device{ bus: &SPIBus{ wire: bus, - dcPin: dcPin, - resetPin: resetPin, - csPin: csPin, + dcPin: pin.OutputStruct{Output: dcPin}, + resetPin: pin.OutputStruct{Output: resetPin}, + csPin: pin.OutputStruct{Output: csPin}, }, } } // configure pins with the SPI bus and allocate the buffer func (b *SPIBus) configure(address uint16, size int16) []byte { + + // configure GPIO pins (on baremetal targets only, for backwards compatibility) + legacy.ConfigurePinOut(b.dcPin) + legacy.ConfigurePinOut(b.resetPin) + legacy.ConfigurePinOut(b.csPin) + b.csPin.Low() b.dcPin.Low() b.resetPin.Low() diff --git a/ssd1331/ssd1331.go b/ssd1331/ssd1331.go index 0717c48e1..9657d3524 100644 --- a/ssd1331/ssd1331.go +++ b/ssd1331/ssd1331.go @@ -5,12 +5,13 @@ package ssd1331 // import "tinygo.org/x/drivers/ssd1331" import ( "image/color" - "machine" "errors" "time" "tinygo.org/x/drivers" + "tinygo.org/x/drivers/internal/legacy" + "tinygo.org/x/drivers/internal/pin" ) type Model uint8 @@ -19,9 +20,9 @@ type Rotation uint8 // Device wraps an SPI connection. type Device struct { bus drivers.SPI - dcPin machine.Pin - resetPin machine.Pin - csPin machine.Pin + dcPin pin.OutputStruct + resetPin pin.OutputStruct + csPin pin.OutputStruct width int16 height int16 batchLength int16 @@ -36,15 +37,12 @@ type Config struct { } // New creates a new SSD1331 connection. The SPI wire must already be configured. -func New(bus drivers.SPI, resetPin, dcPin, csPin machine.Pin) Device { - dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) - resetPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) - csPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) +func New(bus drivers.SPI, resetPin, dcPin, csPin pin.Output) Device { return Device{ bus: bus, - dcPin: dcPin, - resetPin: resetPin, - csPin: csPin, + dcPin: pin.OutputStruct{Output: dcPin}, + resetPin: pin.OutputStruct{Output: resetPin}, + csPin: pin.OutputStruct{Output: csPin}, } } @@ -68,6 +66,11 @@ func (d *Device) Configure(cfg Config) { d.batchLength += d.batchLength & 1 d.batchData = make([]uint8, d.batchLength*2) + // configure GPIO pins (on baremetal targets only, for backwards compatibility) + legacy.ConfigurePinOut(d.dcPin) + legacy.ConfigurePinOut(d.resetPin) + legacy.ConfigurePinOut(d.csPin) + // reset the device d.resetPin.High() time.Sleep(100 * time.Millisecond) diff --git a/ssd1351/ssd1351.go b/ssd1351/ssd1351.go index 3561dd6ca..57ca71fbd 100644 --- a/ssd1351/ssd1351.go +++ b/ssd1351/ssd1351.go @@ -6,10 +6,11 @@ package ssd1351 // import "tinygo.org/x/drivers/ssd1351" import ( "errors" "image/color" - "machine" "time" "tinygo.org/x/drivers" + "tinygo.org/x/drivers/internal/legacy" + "tinygo.org/x/drivers/internal/pin" ) var ( @@ -20,11 +21,11 @@ var ( // Device wraps an SPI connection. type Device struct { bus drivers.SPI - dcPin machine.Pin - resetPin machine.Pin - csPin machine.Pin - enPin machine.Pin - rwPin machine.Pin + dcPin pin.OutputStruct + resetPin pin.OutputStruct + csPin pin.OutputStruct + enPin pin.OutputStruct + rwPin pin.OutputStruct width int16 height int16 rowOffset int16 @@ -41,14 +42,14 @@ type Config struct { } // New creates a new SSD1351 connection. The SPI wire must already be configured. -func New(bus drivers.SPI, resetPin, dcPin, csPin, enPin, rwPin machine.Pin) Device { +func New(bus drivers.SPI, resetPin, dcPin, csPin, enPin, rwPin pin.Output) Device { return Device{ bus: bus, - dcPin: dcPin, - resetPin: resetPin, - csPin: csPin, - enPin: enPin, - rwPin: rwPin, + dcPin: pin.OutputStruct{Output: dcPin}, + resetPin: pin.OutputStruct{Output: resetPin}, + csPin: pin.OutputStruct{Output: csPin}, + enPin: pin.OutputStruct{Output: enPin}, + rwPin: pin.OutputStruct{Output: rwPin}, } } @@ -72,12 +73,12 @@ func (d *Device) Configure(cfg Config) { d.bufferLength = d.height } - // configure GPIO pins - d.dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) - d.resetPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) - d.csPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) - d.enPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) - d.rwPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) + // configure GPIO pins (on baremetal targets only, for backwards compatibility) + legacy.ConfigurePinOut(d.dcPin) + legacy.ConfigurePinOut(d.resetPin) + legacy.ConfigurePinOut(d.csPin) + legacy.ConfigurePinOut(d.enPin) + legacy.ConfigurePinOut(d.rwPin) // reset the device d.resetPin.High() From d3712321f1c93285fa8b200c91c1318da825289c Mon Sep 17 00:00:00 2001 From: Yurii Soldak Date: Sun, 9 Nov 2025 22:46:05 +0100 Subject: [PATCH 2/3] fix ssd1289 example --- examples/ssd1289/main.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/ssd1289/main.go b/examples/ssd1289/main.go index c68f328df..96a21764e 100644 --- a/examples/ssd1289/main.go +++ b/examples/ssd1289/main.go @@ -5,6 +5,7 @@ import ( "machine" "math/rand" + "tinygo.org/x/drivers/internal/pin" "tinygo.org/x/drivers/ssd1289" ) @@ -16,7 +17,7 @@ func main() { //consider creating a more efficient bus implementation that uses //your microcontrollers built in "ports" //see rp2040bus.go for an example for the rapsberry pi pico - bus := ssd1289.NewPinBus([16]machine.Pin{ + bus := ssd1289.NewPinBus([16]pin.Output{ machine.GP4, //DB0 machine.GP5, //DB1 machine.GP6, //DB2 From a7b77c04220a488c6e0b8e69ac93002ef067de0d Mon Sep 17 00:00:00 2001 From: Yurii Soldak Date: Tue, 11 Nov 2025 11:54:14 +0100 Subject: [PATCH 3/3] simplify --- internal/pin/internalpin.go | 13 ---------- ssd1289/ssd1289.go | 40 ++++++++++++++++--------------- ssd1306/ssd1306_spi.go | 24 +++++++++---------- ssd1331/ssd1331.go | 23 +++++++++--------- ssd1351/ssd1351.go | 48 ++++++++++++++++++++----------------- 5 files changed, 69 insertions(+), 79 deletions(-) diff --git a/internal/pin/internalpin.go b/internal/pin/internalpin.go index c65b377cf..6879f3480 100644 --- a/internal/pin/internalpin.go +++ b/internal/pin/internalpin.go @@ -70,16 +70,3 @@ type Output interface { type Input interface { Get() (level bool) } - -// OutputStruct implements optional convenience methods -type OutputStruct struct { - Output -} - -func (p OutputStruct) High() { - p.Set(true) -} - -func (p OutputStruct) Low() { - p.Set(false) -} diff --git a/ssd1289/ssd1289.go b/ssd1289/ssd1289.go index 848d9d39f..8b1e55f60 100644 --- a/ssd1289/ssd1289.go +++ b/ssd1289/ssd1289.go @@ -16,10 +16,10 @@ type Bus interface { } type Device struct { - rs pin.OutputStruct - wr pin.OutputStruct - cs pin.OutputStruct - rst pin.OutputStruct + rs pin.OutputFunc + wr pin.OutputFunc + cs pin.OutputFunc + rst pin.OutputFunc bus Bus } @@ -27,13 +27,25 @@ const width = int16(240) const height = int16(320) func New(rs, wr, cs, rst pin.Output, bus Bus) *Device { - return &Device{ - rs: pin.OutputStruct{Output: rs}, - wr: pin.OutputStruct{Output: wr}, - cs: pin.OutputStruct{Output: cs}, - rst: pin.OutputStruct{Output: rst}, + d := &Device{ + rs: rs.Set, + wr: wr.Set, + cs: cs.Set, + rst: rst.Set, bus: bus, } + + // configure GPIO pins (only on baremetal targets, for backwards compatibility) + legacy.ConfigurePinOut(rs) + legacy.ConfigurePinOut(wr) + legacy.ConfigurePinOut(cs) + legacy.ConfigurePinOut(rst) + + d.cs.High() + d.rst.High() + d.wr.High() + + return d } func (d *Device) lcdWriteCom(cmd Command) { @@ -62,16 +74,6 @@ func (d *Device) lcdWriteBusInt(data uint16) { } func (d *Device) Configure() { - - // configure GPIO pins (only on baremetal targets) - legacy.ConfigurePinOut(d.rs) - legacy.ConfigurePinOut(d.wr) - legacy.ConfigurePinOut(d.cs) - legacy.ConfigurePinOut(d.rst) - - d.cs.High() - d.wr.High() - d.rst.High() time.Sleep(time.Millisecond * 5) d.rst.Low() diff --git a/ssd1306/ssd1306_spi.go b/ssd1306/ssd1306_spi.go index 1b50c8bc5..938abce53 100644 --- a/ssd1306/ssd1306_spi.go +++ b/ssd1306/ssd1306_spi.go @@ -10,32 +10,30 @@ import ( type SPIBus struct { wire drivers.SPI - dcPin pin.OutputStruct - resetPin pin.OutputStruct - csPin pin.OutputStruct + dcPin pin.OutputFunc + resetPin pin.OutputFunc + csPin pin.OutputFunc buffer []byte // buffer to avoid heap allocations } // NewSPI creates a new SSD1306 connection. The SPI wire must already be configured. func NewSPI(bus drivers.SPI, dcPin, resetPin, csPin pin.Output) *Device { + // configure GPIO pins (on baremetal targets only, for backwards compatibility) + legacy.ConfigurePinOut(dcPin) + legacy.ConfigurePinOut(resetPin) + legacy.ConfigurePinOut(csPin) return &Device{ bus: &SPIBus{ wire: bus, - dcPin: pin.OutputStruct{Output: dcPin}, - resetPin: pin.OutputStruct{Output: resetPin}, - csPin: pin.OutputStruct{Output: csPin}, + dcPin: dcPin.Set, + resetPin: resetPin.Set, + csPin: csPin.Set, }, } } // configure pins with the SPI bus and allocate the buffer func (b *SPIBus) configure(address uint16, size int16) []byte { - - // configure GPIO pins (on baremetal targets only, for backwards compatibility) - legacy.ConfigurePinOut(b.dcPin) - legacy.ConfigurePinOut(b.resetPin) - legacy.ConfigurePinOut(b.csPin) - b.csPin.Low() b.dcPin.Low() b.resetPin.Low() @@ -64,7 +62,7 @@ func (b *SPIBus) flush() error { // tx sends data to the display func (b *SPIBus) tx(data []byte, isCommand bool) error { b.csPin.High() - b.dcPin.Set(!isCommand) + b.dcPin(!isCommand) b.csPin.Low() err := b.wire.Tx(data, nil) b.csPin.High() diff --git a/ssd1331/ssd1331.go b/ssd1331/ssd1331.go index 9657d3524..426850fcd 100644 --- a/ssd1331/ssd1331.go +++ b/ssd1331/ssd1331.go @@ -20,9 +20,9 @@ type Rotation uint8 // Device wraps an SPI connection. type Device struct { bus drivers.SPI - dcPin pin.OutputStruct - resetPin pin.OutputStruct - csPin pin.OutputStruct + dcPin pin.OutputFunc + resetPin pin.OutputFunc + csPin pin.OutputFunc width int16 height int16 batchLength int16 @@ -38,11 +38,15 @@ type Config struct { // New creates a new SSD1331 connection. The SPI wire must already be configured. func New(bus drivers.SPI, resetPin, dcPin, csPin pin.Output) Device { + // configure GPIO pins (on baremetal targets only, for backwards compatibility) + legacy.ConfigurePinOut(dcPin) + legacy.ConfigurePinOut(resetPin) + legacy.ConfigurePinOut(csPin) return Device{ bus: bus, - dcPin: pin.OutputStruct{Output: dcPin}, - resetPin: pin.OutputStruct{Output: resetPin}, - csPin: pin.OutputStruct{Output: csPin}, + dcPin: dcPin.Set, + resetPin: resetPin.Set, + csPin: csPin.Set, } } @@ -66,11 +70,6 @@ func (d *Device) Configure(cfg Config) { d.batchLength += d.batchLength & 1 d.batchData = make([]uint8, d.batchLength*2) - // configure GPIO pins (on baremetal targets only, for backwards compatibility) - legacy.ConfigurePinOut(d.dcPin) - legacy.ConfigurePinOut(d.resetPin) - legacy.ConfigurePinOut(d.csPin) - // reset the device d.resetPin.High() time.Sleep(100 * time.Millisecond) @@ -254,7 +253,7 @@ func (d *Device) Data(data uint8) { // Tx sends data to the display func (d *Device) Tx(data []byte, isCommand bool) { - d.dcPin.Set(!isCommand) + d.dcPin(!isCommand) d.bus.Tx(data, nil) } diff --git a/ssd1351/ssd1351.go b/ssd1351/ssd1351.go index 57ca71fbd..dd737f13f 100644 --- a/ssd1351/ssd1351.go +++ b/ssd1351/ssd1351.go @@ -20,17 +20,18 @@ var ( // Device wraps an SPI connection. type Device struct { - bus drivers.SPI - dcPin pin.OutputStruct - resetPin pin.OutputStruct - csPin pin.OutputStruct - enPin pin.OutputStruct - rwPin pin.OutputStruct - width int16 - height int16 - rowOffset int16 - columnOffset int16 - bufferLength int16 + bus drivers.SPI + dcPin pin.OutputFunc + resetPin pin.OutputFunc + csPin pin.OutputFunc + enPin pin.OutputFunc + rwPin pin.OutputFunc + width int16 + height int16 + rowOffset int16 + columnOffset int16 + bufferLength int16 + configurePins func() } // Config is the configuration for the display @@ -45,11 +46,18 @@ type Config struct { func New(bus drivers.SPI, resetPin, dcPin, csPin, enPin, rwPin pin.Output) Device { return Device{ bus: bus, - dcPin: pin.OutputStruct{Output: dcPin}, - resetPin: pin.OutputStruct{Output: resetPin}, - csPin: pin.OutputStruct{Output: csPin}, - enPin: pin.OutputStruct{Output: enPin}, - rwPin: pin.OutputStruct{Output: rwPin}, + dcPin: dcPin.Set, + resetPin: resetPin.Set, + csPin: csPin.Set, + enPin: enPin.Set, + rwPin: rwPin.Set, + configurePins: func() { + legacy.ConfigurePinOut(dcPin) + legacy.ConfigurePinOut(resetPin) + legacy.ConfigurePinOut(csPin) + legacy.ConfigurePinOut(enPin) + legacy.ConfigurePinOut(rwPin) + }, } } @@ -74,11 +82,7 @@ func (d *Device) Configure(cfg Config) { } // configure GPIO pins (on baremetal targets only, for backwards compatibility) - legacy.ConfigurePinOut(d.dcPin) - legacy.ConfigurePinOut(d.resetPin) - legacy.ConfigurePinOut(d.csPin) - legacy.ConfigurePinOut(d.enPin) - legacy.ConfigurePinOut(d.rwPin) + d.configurePins() // reset the device d.resetPin.High() @@ -279,7 +283,7 @@ func (d *Device) Data(data uint8) { // Tx sends data to the display func (d *Device) Tx(data []byte, isCommand bool) { - d.dcPin.Set(!isCommand) + d.dcPin(!isCommand) d.csPin.Low() d.bus.Tx(data, nil) d.csPin.High()