Replace Safe functions with legacy.PinOutput

This commit is contained in:
Yurii Soldak
2025-09-21 10:04:20 +02:00
parent c6d83b783f
commit 453ff96a66
16 changed files with 112 additions and 108 deletions
+2 -1
View File
@@ -4,6 +4,7 @@ import (
"time" "time"
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
// DeviceSPI is the SPI interface to a BMI160 accelerometer/gyroscope. There is // DeviceSPI is the SPI interface to a BMI160 accelerometer/gyroscope. There is
@@ -23,7 +24,7 @@ type DeviceSPI struct {
// using this device. // using this device.
func NewSPI(csb drivers.PinOutput, spi drivers.SPI) *DeviceSPI { func NewSPI(csb drivers.PinOutput, spi drivers.SPI) *DeviceSPI {
return &DeviceSPI{ return &DeviceSPI{
CSB: drivers.SafePinOutput(csb), // chip select CSB: legacy.PinOutput(csb), // chip select
Bus: spi, Bus: spi,
} }
} }
+1 -1
View File
@@ -17,7 +17,7 @@ type Device struct {
// New returns a new buzzer driver given which pin to use // New returns a new buzzer driver given which pin to use
func New(pin drivers.PinOutput) Device { func New(pin drivers.PinOutput) Device {
return Device{ return Device{
set: drivers.SafePinOutput(pin).Set, set: pin.Set,
High: false, High: false,
BPM: 96.0, BPM: 96.0,
} }
+2 -4
View File
@@ -45,9 +45,7 @@ type device struct {
func (t *device) ReadMeasurements() error { func (t *device) ReadMeasurements() error {
// initial waiting // initial waiting
state := powerUp(t.pin) state := powerUp(t.pin)
defer func() { defer t.pin.Set(state)
t.pin.Set(state)
}()
err := t.read() err := t.read()
if err == nil { if err == nil {
t.initialized = true t.initialized = true
@@ -213,7 +211,7 @@ func waitForDataTransmission(p drivers.PinInput) error {
func NewDummyDevice(pin drivers.Pin, deviceType DeviceType) DummyDevice { func NewDummyDevice(pin drivers.Pin, deviceType DeviceType) DummyDevice {
pin.Set(true) pin.Set(true)
return &device{ return &device{
pin: drivers.SafePin(pin), pin: pin,
measurements: deviceType, measurements: deviceType,
initialized: false, initialized: false,
temperature: 0, temperature: 0,
+2 -2
View File
@@ -129,7 +129,7 @@ func New(pin drivers.Pin, deviceType DeviceType) Device {
pin.Set(true) pin.Set(true)
return &managedDevice{ return &managedDevice{
t: device{ t: device{
pin: drivers.SafePin(pin), pin: pin,
measurements: deviceType, measurements: deviceType,
initialized: false, initialized: false,
}, },
@@ -146,7 +146,7 @@ func NewWithPolicy(pin drivers.Pin, deviceType DeviceType, updatePolicy UpdatePo
pin.Set(true) pin.Set(true)
result := &managedDevice{ result := &managedDevice{
t: device{ t: device{
pin: drivers.SafePin(pin), pin: pin,
measurements: deviceType, measurements: deviceType,
initialized: false, initialized: false,
}, },
+5 -1
View File
@@ -1,14 +1,18 @@
//go:build baremetal && tinygo
package main package main
import ( import (
"fmt" "fmt"
"machine" "machine"
"time" "time"
"tinygo.org/x/drivers/dht" "tinygo.org/x/drivers/dht"
"tinygo.org/x/drivers/tinygo"
) )
func main() { func main() {
pin := machine.D6 pin := tinygo.New(machine.D6)
dhtSensor := dht.New(pin, dht.DHT11) dhtSensor := dht.New(pin, dht.DHT11)
for { for {
temp, hum, err := dhtSensor.Measurements() temp, hum, err := dhtSensor.Measurements()
+4 -1
View File
@@ -5,10 +5,13 @@ import (
"time" "time"
"tinygo.org/x/drivers/hcsr04" "tinygo.org/x/drivers/hcsr04"
"tinygo.org/x/drivers/tinygo"
) )
func main() { func main() {
sensor := hcsr04.New(machine.D10, machine.D9) trigger := tinygo.New(machine.D10) // automatically configures pin as output
echo := tinygo.New(machine.D9) // automatically configures pin as input
sensor := hcsr04.New(trigger, echo)
sensor.Configure() sensor.Configure()
println("Ultrasonic starts") println("Ultrasonic starts")
+11 -10
View File
@@ -5,20 +5,22 @@
package hcsr04 package hcsr04
import ( import (
"machine"
"time" "time"
"tinygo.org/x/drivers"
) )
const TIMEOUT = 23324 // max sensing distance (4m) const TIMEOUT = 23324 // max sensing distance (4m)
// Device holds the pins // Device holds the pins
type Device struct { type Device struct {
trigger machine.Pin trigger drivers.PinOutput
echo machine.Pin echo drivers.PinInput
} }
// New returns a new ultrasonic driver given 2 pins // New returns a new ultrasonic driver given 2 pins.
func New(trigger, echo machine.Pin) Device { // Pins must be configured as output (trigger) and input (echo).
func New(trigger drivers.PinOutput, echo drivers.PinInput) Device {
return Device{ return Device{
trigger: trigger, trigger: trigger,
echo: echo, echo: echo,
@@ -27,8 +29,7 @@ func New(trigger, echo machine.Pin) Device {
// Configure configures the pins of the Device // Configure configures the pins of the Device
func (d *Device) Configure() { func (d *Device) Configure() {
d.trigger.Configure(machine.PinConfig{Mode: machine.PinOutput}) // no-op, left for API compatibility
d.echo.Configure(machine.PinConfig{Mode: machine.PinInput})
} }
// ReadDistance returns the distance of the object in mm // ReadDistance returns the distance of the object in mm
@@ -45,11 +46,11 @@ func (d *Device) ReadDistance() int32 {
// ReadPulse returns the time of the pulse (roundtrip) in microseconds // ReadPulse returns the time of the pulse (roundtrip) in microseconds
func (d *Device) ReadPulse() int32 { func (d *Device) ReadPulse() int32 {
t := time.Now() t := time.Now()
d.trigger.Low() d.trigger.Set(false)
time.Sleep(2 * time.Microsecond) time.Sleep(2 * time.Microsecond)
d.trigger.High() d.trigger.Set(true)
time.Sleep(10 * time.Microsecond) time.Sleep(10 * time.Microsecond)
d.trigger.Low() d.trigger.Set(false)
i := uint8(0) i := uint8(0)
for { for {
if d.echo.Get() { if d.echo.Get() {
+9
View File
@@ -0,0 +1,9 @@
//go:build !(baremetal && tinygo)
package legacy
import "tinygo.org/x/drivers"
func PinOutput(pin drivers.PinOutput) drivers.PinOutput {
return pin
}
+16
View File
@@ -0,0 +1,16 @@
//go:build baremetal && tinygo
package legacy
import (
"machine"
"tinygo.org/x/drivers"
)
func PinOutput(pin drivers.PinOutput) drivers.PinOutput {
if p, ok := pin.(machine.Pin); ok {
p.Configure(machine.PinConfig{Mode: machine.PinOutput})
}
return pin
}
+10 -6
View File
@@ -4,13 +4,17 @@ package drivers
// allowing the use of different hardware or libraries without changing driver code. // allowing the use of different hardware or libraries without changing driver code.
// //
// Note, pin mode functionality is not part of the Pin interface. // Note, pin mode functionality is not part of the Pin interface.
// Implementations must ensure correct pin mode is set when Get or Set methods are called. // Client code is responsible for configuring pin modes correctly.
// This can be done either before passing the pin to a driver constructor
// or by ensuring correct pin mode is set when Get or Set methods are called.
// See rpio package for an example of a pin implementation that does this.
// //
// Drivers must use SafePin(), SafePinInput() and SafePinOutput() wrappers in constructors. // Drivers that used to configure output pin mode in their constructors can use
// The client code can pass either machine.Pin or a custom implementation of the Pin interface. // legacy.PinOutput() wrapper to keep the same behavior for machine.Pin.
// Wrappers for TinyGo's machine.Pin are provided in pin_tinygo.go. // See internal/legacy/pinlegacy_tinygo.go and internal/legacy/pinlegacy_generic.go for details.
// It's custom implementation's responsibility to configure the pin modes correctly as //
// Wrappers in pin_generic.go are no-ops. // All new drivers are encouraged to not configure pin modes in their constructors and
// do not depend on either machine package or legacy wrappers.
// PinInput is an interface for reading the state of a pin. // PinInput is an interface for reading the state of a pin.
type PinInput interface { type PinInput interface {
-18
View File
@@ -1,18 +0,0 @@
//go:build !tinygo
// Generic no-op implementations of SafePin, SafePinInput and SafePinOutput.
// It's custom implementation's responsibility to configure the pin modes correctly when needed.
package drivers
func SafePinInput(pin PinInput) PinInput {
return pin
}
func SafePinOutput(pin PinOutput) PinOutput {
return pin
}
func SafePin(pin Pin) Pin {
return pin
}
-57
View File
@@ -1,57 +0,0 @@
//go:build tinygo
// Implementation of the Pin interface for tinygo (baremetal), depends on "machine" package.
// SafePin, SafePinInput and SafePinOutput wrappers must be used in constructors of drivers.
package drivers
import (
"machine"
)
// MachinePin wraps machine.Pin to ensure correct pin mode is set when Get or Set methods are called.
type MachinePin struct {
pin machine.Pin
mode machine.PinMode
modeSet bool
}
func (p *MachinePin) Get() bool {
if !p.modeSet || p.mode != machine.PinInput {
p.pin.Configure(machine.PinConfig{Mode: machine.PinInput})
p.mode = machine.PinInput
}
return p.pin.Get()
}
func (p *MachinePin) Set(high bool) {
if !p.modeSet || p.mode != machine.PinOutput {
p.pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
p.mode = machine.PinOutput
}
p.pin.Set(high)
}
// Wrappers for Pin, PinInput and PinOutput interfaces that convert machine.Pin to safe MachinePin.
func SafePinInput(pin PinInput) PinInput {
if p, ok := pin.(machine.Pin); ok {
return &MachinePin{pin: p}
}
return pin
}
func SafePinOutput(pin PinOutput) PinOutput {
if p, ok := pin.(machine.Pin); ok {
return &MachinePin{pin: p}
}
return pin
}
func SafePin(pin Pin) Pin {
if p, ok := pin.(machine.Pin); ok {
return &MachinePin{pin: p}
}
return pin
}
+2
View File
@@ -1,4 +1,6 @@
// Implementation of the Pin interface for the Raspberry Pi GPIO pins. // Implementation of the Pin interface for the Raspberry Pi GPIO pins.
// Depends on the go-rpio library.
// Configures pin modes automatically when Get or Set methods are called.
package rpio // import "tinygo.org/x/drivers/rpio" package rpio // import "tinygo.org/x/drivers/rpio"
+4 -3
View File
@@ -4,6 +4,7 @@ import (
"time" "time"
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
type SPIBus struct { type SPIBus struct {
@@ -19,9 +20,9 @@ func NewSPI(bus drivers.SPI, dcPin, resetPin, csPin drivers.PinOutput) *Device {
return &Device{ return &Device{
bus: &SPIBus{ bus: &SPIBus{
wire: bus, wire: bus,
dcPin: drivers.SafePinOutput(dcPin), dcPin: legacy.PinOutput(dcPin),
resetPin: drivers.SafePinOutput(resetPin), resetPin: legacy.PinOutput(resetPin),
csPin: drivers.SafePinOutput(csPin), csPin: legacy.PinOutput(csPin),
}, },
} }
} }
+5 -4
View File
@@ -10,6 +10,7 @@ import (
"errors" "errors"
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
"tinygo.org/x/drivers/pixel" "tinygo.org/x/drivers/pixel"
) )
@@ -73,10 +74,10 @@ func New(bus drivers.SPI, resetPin, dcPin, csPin, blPin drivers.PinOutput) Devic
func NewOf[T Color](bus drivers.SPI, resetPin, dcPin, csPin, blPin drivers.PinOutput) DeviceOf[T] { func NewOf[T Color](bus drivers.SPI, resetPin, dcPin, csPin, blPin drivers.PinOutput) DeviceOf[T] {
return DeviceOf[T]{ return DeviceOf[T]{
bus: bus, bus: bus,
dcPin: drivers.SafePinOutput(dcPin), dcPin: legacy.PinOutput(dcPin),
resetPin: drivers.SafePinOutput(resetPin), resetPin: legacy.PinOutput(resetPin),
csPin: drivers.SafePinOutput(csPin), csPin: legacy.PinOutput(csPin),
blPin: drivers.SafePinOutput(blPin), blPin: legacy.PinOutput(blPin),
} }
} }
+39
View File
@@ -0,0 +1,39 @@
//go:build baremetal && tinygo
package tinygo // import "tinygo.org/x/drivers/tinygo"
import "machine"
// tinygo.Pin wraps machine.Pin to ensure correct pin mode is set when Get or Set methods are called.
type Pin struct {
pin machine.Pin
mode machine.PinMode
modeSet bool
inputMode machine.PinMode
}
func New(pin machine.Pin) *Pin {
return &Pin{pin: pin, inputMode: machine.PinInput}
}
func NewWithInputMode(pin machine.Pin, inputMode machine.PinMode) *Pin {
return &Pin{pin: pin, inputMode: inputMode}
}
func (p *Pin) Get() bool {
if !p.modeSet || p.mode != p.inputMode {
p.pin.Configure(machine.PinConfig{Mode: p.inputMode})
p.mode = machine.PinInput
}
return p.pin.Get()
}
func (p *Pin) Set(high bool) {
if !p.modeSet || p.mode != machine.PinOutput {
p.pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
p.mode = machine.PinOutput
}
p.pin.Set(high)
}