Skip to content

Commit c6d83b7

Browse files
committed
Pin HAL to break dependency of drivers from TinyGo's machine package
1 parent 3fa0811 commit c6d83b7

File tree

15 files changed

+328
-88
lines changed

15 files changed

+328
-88
lines changed

bmi160/bmi160.go

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package bmi160
22

33
import (
4-
"machine"
54
"time"
65

76
"tinygo.org/x/drivers"
@@ -11,7 +10,7 @@ import (
1110
// also an I2C interface, but it is not yet supported.
1211
type DeviceSPI struct {
1312
// Chip select pin
14-
CSB machine.Pin
13+
CSB drivers.PinOutput
1514

1615
buf [7]byte
1716

@@ -22,9 +21,9 @@ type DeviceSPI struct {
2221
// NewSPI returns a new device driver. The pin and SPI interface are not
2322
// touched, provide a fully configured SPI object and call Configure to start
2423
// using this device.
25-
func NewSPI(csb machine.Pin, spi drivers.SPI) *DeviceSPI {
24+
func NewSPI(csb drivers.PinOutput, spi drivers.SPI) *DeviceSPI {
2625
return &DeviceSPI{
27-
CSB: csb, // chip select
26+
CSB: drivers.SafePinOutput(csb), // chip select
2827
Bus: spi,
2928
}
3029
}
@@ -33,8 +32,7 @@ func NewSPI(csb machine.Pin, spi drivers.SPI) *DeviceSPI {
3332
// configures the BMI160, but it does not configure the SPI interface (it is
3433
// assumed to be up and running).
3534
func (d *DeviceSPI) Configure() error {
36-
d.CSB.Configure(machine.PinConfig{Mode: machine.PinOutput})
37-
d.CSB.High()
35+
d.CSB.Set(true)
3836

3937
// The datasheet recommends doing a register read from address 0x7F to get
4038
// SPI communication going:
@@ -86,9 +84,9 @@ func (d *DeviceSPI) ReadTemperature() (temperature int32, err error) {
8684
data[0] = 0x80 | reg_TEMPERATURE_0
8785
data[1] = 0
8886
data[2] = 0
89-
d.CSB.Low()
87+
d.CSB.Set(false)
9088
err = d.Bus.Tx(data, data)
91-
d.CSB.High()
89+
d.CSB.Set(true)
9290
if err != nil {
9391
return
9492
}
@@ -123,9 +121,9 @@ func (d *DeviceSPI) ReadAcceleration() (x int32, y int32, z int32, err error) {
123121
for i := 1; i < len(data); i++ {
124122
data[i] = 0
125123
}
126-
d.CSB.Low()
124+
d.CSB.Set(false)
127125
err = d.Bus.Tx(data, data)
128-
d.CSB.High()
126+
d.CSB.Set(true)
129127
if err != nil {
130128
return
131129
}
@@ -153,9 +151,9 @@ func (d *DeviceSPI) ReadRotation() (x int32, y int32, z int32, err error) {
153151
for i := 1; i < len(data); i++ {
154152
data[i] = 0
155153
}
156-
d.CSB.Low()
154+
d.CSB.Set(false)
157155
err = d.Bus.Tx(data, data)
158-
d.CSB.High()
156+
d.CSB.Set(true)
159157
if err != nil {
160158
return
161159
}
@@ -201,9 +199,9 @@ func (d *DeviceSPI) readRegister(address uint8) uint8 {
201199
data := d.buf[:2]
202200
data[0] = 0x80 | address
203201
data[1] = 0
204-
d.CSB.Low()
202+
d.CSB.Set(false)
205203
d.Bus.Tx(data, data)
206-
d.CSB.High()
204+
d.CSB.Set(true)
207205
return data[1]
208206
}
209207

@@ -217,7 +215,7 @@ func (d *DeviceSPI) writeRegister(address, data uint8) {
217215
buf[0] = address
218216
buf[1] = data
219217

220-
d.CSB.Low()
218+
d.CSB.Set(false)
221219
d.Bus.Tx(buf, buf)
222-
d.CSB.High()
220+
d.CSB.Set(true)
223221
}

buzzer/buzzer.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,37 @@
22
package buzzer // import "tinygo.org/x/drivers/buzzer"
33

44
import (
5-
"machine"
6-
75
"time"
6+
7+
"tinygo.org/x/drivers"
88
)
99

1010
// Device wraps a GPIO connection to a buzzer.
1111
type Device struct {
12-
pin machine.Pin
12+
set drivers.PinSet
1313
High bool
1414
BPM float64
1515
}
1616

1717
// New returns a new buzzer driver given which pin to use
18-
func New(pin machine.Pin) Device {
18+
func New(pin drivers.PinOutput) Device {
1919
return Device{
20-
pin: pin,
20+
set: drivers.SafePinOutput(pin).Set,
2121
High: false,
2222
BPM: 96.0,
2323
}
2424
}
2525

2626
// On sets the buzzer to a high state.
2727
func (l *Device) On() (err error) {
28-
l.pin.Set(true)
28+
l.set(true)
2929
l.High = true
3030
return
3131
}
3232

3333
// Off sets the buzzer to a low state.
3434
func (l *Device) Off() (err error) {
35-
l.pin.Set(false)
35+
l.set(false)
3636
l.High = false
3737
return
3838
}

dht/thermometer.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
package dht // import "tinygo.org/x/drivers/dht"
1010

1111
import (
12-
"machine"
1312
"runtime/interrupt"
1413
"time"
14+
15+
"tinygo.org/x/drivers"
1516
)
1617

1718
// DummyDevice provides a basic interface for DHT devices.
@@ -30,7 +31,7 @@ type DummyDevice interface {
3031
// Since taking measurements from the sensor is time consuming procedure and blocks interrupts,
3132
// user can avoid any hidden calls to the sensor.
3233
type device struct {
33-
pin machine.Pin
34+
pin drivers.Pin
3435

3536
measurements DeviceType
3637
initialized bool
@@ -44,7 +45,9 @@ type device struct {
4445
func (t *device) ReadMeasurements() error {
4546
// initial waiting
4647
state := powerUp(t.pin)
47-
defer t.pin.Set(state)
48+
defer func() {
49+
t.pin.Set(state)
50+
}()
4851
err := t.read()
4952
if err == nil {
5053
t.initialized = true
@@ -93,14 +96,12 @@ func (t *device) HumidityFloat() (float32, error) {
9396
// Perform initialization of the communication protocol.
9497
// Device lowers the voltage on pin for startingLow=20ms and starts listening for response
9598
// Section 5.2 in [1]
96-
func initiateCommunication(p machine.Pin) {
99+
func initiateCommunication(p drivers.Pin) {
97100
// Send low signal to the device
98-
p.Configure(machine.PinConfig{Mode: machine.PinOutput})
99-
p.Low()
101+
p.Set(false)
100102
time.Sleep(startingLow)
101103
// Set pin to high and wait for reply
102-
p.High()
103-
p.Configure(machine.PinConfig{Mode: machine.PinInput})
104+
p.Set(true)
104105
}
105106

106107
// Measurements returns both measurements: temperature and humidity as they sent by the device.
@@ -158,7 +159,7 @@ func (t *device) read() error {
158159

159160
// receiveSignals counts number of low and high cycles. The execution is time critical, so the function disables
160161
// interrupts
161-
func receiveSignals(pin machine.Pin, result []counter) {
162+
func receiveSignals(pin drivers.PinInput, result []counter) {
162163
i := uint8(0)
163164
mask := interrupt.Disable()
164165
defer interrupt.Restore(mask)
@@ -189,7 +190,7 @@ func (t *device) extractData(signals []counter, buf []uint8) error {
189190
// waitForDataTransmission waits for reply from the sensor.
190191
// If no reply received, returns NoSignalError.
191192
// For more details, see section 5.2 in [1]
192-
func waitForDataTransmission(p machine.Pin) error {
193+
func waitForDataTransmission(p drivers.PinInput) error {
193194
// wait for thermometer to pull down
194195
if expectChange(p, true) == timeout {
195196
return NoSignalError
@@ -209,10 +210,10 @@ func waitForDataTransmission(p machine.Pin) error {
209210
// This device provides full control to the user.
210211
// It does not do any hidden measurements calls and does not check
211212
// for 2 seconds delay between measurements.
212-
func NewDummyDevice(pin machine.Pin, deviceType DeviceType) DummyDevice {
213-
pin.High()
213+
func NewDummyDevice(pin drivers.Pin, deviceType DeviceType) DummyDevice {
214+
pin.Set(true)
214215
return &device{
215-
pin: pin,
216+
pin: drivers.SafePin(pin),
216217
measurements: deviceType,
217218
initialized: false,
218219
temperature: 0,

dht/timesafethermometer.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
package dht // import "tinygo.org/x/drivers/dht"
1010

1111
import (
12-
"machine"
1312
"time"
13+
14+
"tinygo.org/x/drivers"
1415
)
1516

1617
// Device interface provides main functionality of the DHTXX sensors.
@@ -124,11 +125,11 @@ func (m *managedDevice) Configure(policy UpdatePolicy) {
124125

125126
// Constructor of the Device implementation.
126127
// This implementation updates data every 2 seconds during data access.
127-
func New(pin machine.Pin, deviceType DeviceType) Device {
128-
pin.High()
128+
func New(pin drivers.Pin, deviceType DeviceType) Device {
129+
pin.Set(true)
129130
return &managedDevice{
130131
t: device{
131-
pin: pin,
132+
pin: drivers.SafePin(pin),
132133
measurements: deviceType,
133134
initialized: false,
134135
},
@@ -141,11 +142,11 @@ func New(pin machine.Pin, deviceType DeviceType) Device {
141142
}
142143

143144
// Constructor of the Device implementation with given UpdatePolicy
144-
func NewWithPolicy(pin machine.Pin, deviceType DeviceType, updatePolicy UpdatePolicy) Device {
145-
pin.High()
145+
func NewWithPolicy(pin drivers.Pin, deviceType DeviceType, updatePolicy UpdatePolicy) Device {
146+
pin.Set(true)
146147
result := &managedDevice{
147148
t: device{
148-
pin: pin,
149+
pin: drivers.SafePin(pin),
149150
measurements: deviceType,
150151
initialized: false,
151152
},

dht/util.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,22 @@
33
package dht // import "tinygo.org/x/drivers/dht"
44

55
import (
6-
"machine"
76
"time"
7+
8+
"tinygo.org/x/drivers"
89
)
910

1011
// Check if the pin is disabled
11-
func powerUp(p machine.Pin) bool {
12+
func powerUp(p drivers.Pin) bool {
1213
state := p.Get()
1314
if !state {
14-
p.High()
15+
p.Set(true)
1516
time.Sleep(startTimeout)
1617
}
1718
return state
1819
}
1920

20-
func expectChange(p machine.Pin, oldState bool) counter {
21+
func expectChange(p drivers.PinInput, oldState bool) counter {
2122
cnt := counter(0)
2223
for ; p.Get() == oldState && cnt != timeout; cnt++ {
2324
}

examples/rpio/main.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package main
2+
3+
// Example program for the ST7735 display (Waveshare 1.44" LCD HAT) using the rpio driver on a Raspberry Pi.
4+
5+
import (
6+
"fmt"
7+
"image/color"
8+
"time"
9+
10+
go_rpio "github.com/stianeikeland/go-rpio/v4"
11+
"tinygo.org/x/drivers/rpio"
12+
"tinygo.org/x/drivers/st7735"
13+
)
14+
15+
var (
16+
black = color.RGBA{0, 0, 0, 255}
17+
colors = [...]color.RGBA{
18+
{255, 0, 0, 255}, // red
19+
{0, 255, 0, 255}, // green
20+
{0, 0, 255, 255}, // blue
21+
{255, 255, 0, 255}, // yellow
22+
}
23+
)
24+
25+
func main() {
26+
if err := go_rpio.Open(); err != nil {
27+
fmt.Println("Error opening GPIO:", err)
28+
return
29+
}
30+
defer go_rpio.Close()
31+
32+
// Initialize SPI and pins
33+
spi := rpio.NewSPI()
34+
resetPin := rpio.NewPin(27)
35+
dcPin := rpio.NewPin(25)
36+
csPin := rpio.NewPin(8)
37+
blPin := rpio.NewPin(24)
38+
39+
// Initialize display
40+
device := st7735.New(spi, resetPin, dcPin, csPin, blPin)
41+
device.Configure(st7735.Config{
42+
Width: 128,
43+
Height: 128,
44+
Model: st7735.GREENTAB,
45+
RowOffset: 3,
46+
ColumnOffset: 2,
47+
})
48+
device.InvertColors(false)
49+
device.EnableBacklight(true)
50+
device.IsBGR(true) // no effect w/o rotation!
51+
device.SetRotation(st7735.NO_ROTATION)
52+
53+
width, height := device.Size()
54+
55+
// Clear display
56+
device.FillScreen(black)
57+
58+
// Draw rectangles in a loop, clockwise rotation of colors
59+
pos := 0
60+
for {
61+
device.FillRectangle(0, 0, width/2, height/2, colors[(pos+0)%len(colors)]) // top left
62+
device.FillRectangle(0, height/2, width/2, height/2, colors[(pos+1)%len(colors)]) // bottom left
63+
device.FillRectangle(width/2, height/2, width/2, height/2, colors[(pos+2)%len(colors)]) // bottom right
64+
device.FillRectangle(width/2, 0, width/2, height/2, colors[(pos+3)%len(colors)]) // top right
65+
pos++
66+
time.Sleep(1 * time.Second)
67+
}
68+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
1313
github.com/orsinium-labs/tinymath v1.1.0
1414
github.com/soypat/natiu-mqtt v0.5.1
15+
github.com/stianeikeland/go-rpio/v4 v4.6.0
1516
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d
1617
golang.org/x/net v0.33.0
1718
tinygo.org/x/tinyfont v0.3.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ github.com/orsinium-labs/tinymath v1.1.0 h1:KomdsyLHB7vE3f1nRAJF2dyf1m/gnM2HxfTe
1717
github.com/orsinium-labs/tinymath v1.1.0/go.mod h1:WPXX6ei3KSXG7JfA03a+ekCYaY9SWN4I+JRl2p6ck+A=
1818
github.com/soypat/natiu-mqtt v0.5.1 h1:rwaDmlvjzD2+3MCOjMZc4QEkDkNwDzbct2TJbpz+TPc=
1919
github.com/soypat/natiu-mqtt v0.5.1/go.mod h1:xEta+cwop9izVCW7xOx2W+ct9PRMqr0gNVkvBPnQTc4=
20+
github.com/stianeikeland/go-rpio/v4 v4.6.0 h1:eAJgtw3jTtvn/CqwbC82ntcS+dtzUTgo5qlZKe677EY=
21+
github.com/stianeikeland/go-rpio/v4 v4.6.0/go.mod h1:A3GvHxC1Om5zaId+HqB3HKqx4K/AqeckxB7qRjxMK7o=
2022
github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
2123
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d h1:0olWaB5pg3+oychR51GUVCEsGkeCU/2JxjBgIo4f3M0=
2224
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=

0 commit comments

Comments
 (0)