Skip to content

Commit 6ae0c4a

Browse files
Suggestion to make function HAL internal and Interface HAL public
1 parent 457e1e5 commit 6ae0c4a

File tree

9 files changed

+148
-152
lines changed

9 files changed

+148
-152
lines changed

dht/thermometer.go

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
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"
16+
"tinygo.org/x/drivers/internal/legacy"
17+
"tinygo.org/x/drivers/internal/pin"
1518
)
1619

1720
// DummyDevice provides a basic interface for DHT devices.
@@ -30,7 +33,8 @@ type DummyDevice interface {
3033
// Since taking measurements from the sensor is time consuming procedure and blocks interrupts,
3134
// user can avoid any hidden calls to the sensor.
3235
type device struct {
33-
pin machine.Pin
36+
set pin.OutputFn
37+
get pin.InputFn
3438

3539
measurements DeviceType
3640
initialized bool
@@ -43,8 +47,8 @@ type device struct {
4347
// According to documentation pin should be always, but the t *device restores pin to the state before call.
4448
func (t *device) ReadMeasurements() error {
4549
// initial waiting
46-
state := powerUp(t.pin)
47-
defer t.pin.Set(state)
50+
state := powerUp(t.set, t.get)
51+
defer t.set(state)
4852
err := t.read()
4953
if err == nil {
5054
t.initialized = true
@@ -93,14 +97,11 @@ func (t *device) HumidityFloat() (float32, error) {
9397
// Perform initialization of the communication protocol.
9498
// Device lowers the voltage on pin for startingLow=20ms and starts listening for response
9599
// Section 5.2 in [1]
96-
func initiateCommunication(p machine.Pin) {
97-
// Send low signal to the device
98-
p.Configure(machine.PinConfig{Mode: machine.PinOutput})
99-
p.Low()
100+
func initiateCommunication(set pin.OutputFn) {
101+
set.Low()
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+
set.High()
104105
}
105106

106107
// Measurements returns both measurements: temperature and humidity as they sent by the device.
@@ -131,14 +132,14 @@ func (t *device) read() error {
131132
signals := signalsData[:]
132133

133134
// Start communication protocol with sensor
134-
initiateCommunication(t.pin)
135+
initiateCommunication(t.set)
135136
// Wait for sensor's response and abort if sensor does not reply
136-
err := waitForDataTransmission(t.pin)
137+
err := waitForDataTransmission(t.get)
137138
if err != nil {
138139
return err
139140
}
140141
// count low and high cycles for sensor's reply
141-
receiveSignals(t.pin, signals)
142+
receiveSignals(t.get, signals)
142143

143144
// process received signals and store the result in the buffer. Abort if data transmission was interrupted and not
144145
// all 40 bits were received
@@ -158,13 +159,13 @@ 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(get pin.InputFn, result []counter) {
162163
i := uint8(0)
163164
mask := interrupt.Disable()
164165
defer interrupt.Restore(mask)
165166
for ; i < 40; i++ {
166-
result[i*2] = expectChange(pin, false)
167-
result[i*2+1] = expectChange(pin, true)
167+
result[i*2] = expectChange(get, false)
168+
result[i*2+1] = expectChange(get, true)
168169
}
169170
}
170171

@@ -189,33 +190,59 @@ 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(get pin.InputFn) error {
193194
// wait for thermometer to pull down
194-
if expectChange(p, true) == timeout {
195+
if expectChange(get, true) == timeout {
195196
return NoSignalError
196197
}
197198
//wait for thermometer to pull up
198-
if expectChange(p, false) == timeout {
199+
if expectChange(get, false) == timeout {
199200
return NoSignalError
200201
}
201202
// wait for thermometer to pull down and start sending the data
202-
if expectChange(p, true) == timeout {
203+
if expectChange(get, true) == timeout {
203204
return NoSignalError
204205
}
205206
return nil
206207
}
207208

208-
// Constructor function for a DummyDevice implementation.
209-
// This device provides full control to the user.
210-
// It does not do any hidden measurements calls and does not check
211-
// for 2 seconds delay between measurements.
212-
func NewDummyDevice(pin machine.Pin, deviceType DeviceType) DummyDevice {
213-
pin.High()
209+
func newDevice(pin drivers.Pin, deviceType DeviceType) *device {
210+
pin.Set(true)
211+
// Pins are configured to maintain backward compatibility,
212+
// When writing new drivers we assume that pins are configured in user code
213+
// so the device initialization could be simplified like this:
214+
// return &device{
215+
// set: pin.Set,
216+
// get: pin.Get,
217+
// ...
218+
// }
219+
isOutput := true
214220
return &device{
215-
pin: pin,
221+
set: func(level bool) {
222+
if !isOutput {
223+
legacy.ConfigurePinOut(pin)
224+
isOutput = true
225+
}
226+
pin.Set(level)
227+
},
228+
get: func() bool {
229+
if isOutput {
230+
legacy.ConfigurePinInput(pin)
231+
isOutput = false
232+
}
233+
return pin.Get()
234+
},
216235
measurements: deviceType,
217236
initialized: false,
218237
temperature: 0,
219238
humidity: 0,
220239
}
221240
}
241+
242+
// Constructor function for a DummyDevice implementation.
243+
// This device provides full control to the user.
244+
// It does not do any hidden measurements calls and does not check
245+
// for 2 seconds delay between measurements.
246+
func NewDummyDevice(pin drivers.Pin, deviceType DeviceType) DummyDevice {
247+
return newDevice(pin, deviceType)
248+
}

dht/timesafethermometer.go

Lines changed: 8 additions & 15 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,14 +125,10 @@ 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{
130-
t: device{
131-
pin: pin,
132-
measurements: deviceType,
133-
initialized: false,
134-
},
131+
t: *newDevice(pin, deviceType),
135132
lastUpdate: time.Time{},
136133
policy: UpdatePolicy{
137134
UpdateTime: time.Second * 2,
@@ -141,14 +138,10 @@ func New(pin machine.Pin, deviceType DeviceType) Device {
141138
}
142139

143140
// Constructor of the Device implementation with given UpdatePolicy
144-
func NewWithPolicy(pin machine.Pin, deviceType DeviceType, updatePolicy UpdatePolicy) Device {
145-
pin.High()
141+
func NewWithPolicy(pin drivers.Pin, deviceType DeviceType, updatePolicy UpdatePolicy) Device {
142+
pin.Set(true)
146143
result := &managedDevice{
147-
t: device{
148-
pin: pin,
149-
measurements: deviceType,
150-
initialized: false,
151-
},
144+
t: *newDevice(pin, deviceType),
152145
lastUpdate: time.Time{},
153146
}
154147
result.Configure(updatePolicy)

dht/util.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,24 @@
33
package dht // import "tinygo.org/x/drivers/dht"
44

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

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

20-
func expectChange(p machine.Pin, oldState bool) counter {
21+
func expectChange(get pin.InputFn, oldState bool) counter {
2122
cnt := counter(0)
22-
for ; p.Get() == oldState && cnt != timeout; cnt++ {
23+
for ; get() == oldState && cnt != timeout; cnt++ {
2324
}
2425
return cnt
2526
}

internal/legacy/pinconfig.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package legacy
33
import (
44
"errors"
55

6-
"tinygo.org/x/drivers/internal/pin"
6+
"tinygo.org/x/drivers"
77
)
88

99
// The pingconfig group of files serve to abstract away
@@ -19,7 +19,7 @@ import (
1919
// Deprecated: Do not configure pins in drivers.
2020
// This is a legacy feature and should only be used by drivers that
2121
// previously configured pins in initialization to avoid breaking users.
22-
func ConfigurePinOut(po pin.Output) {
22+
func ConfigurePinOut(po drivers.OutputPin) {
2323
configurePinOut(po)
2424
}
2525

@@ -28,7 +28,7 @@ func ConfigurePinOut(po pin.Output) {
2828
// Deprecated: Do not configure pins in drivers.
2929
// This is a legacy feature and should only be used by drivers that
3030
// previously configured pins in initialization to avoid breaking users.
31-
func ConfigurePinInputPulldown(pi pin.Input) {
31+
func ConfigurePinInputPulldown(pi drivers.InputPin) {
3232
configurePinInputPulldown(pi)
3333
}
3434

@@ -37,7 +37,7 @@ func ConfigurePinInputPulldown(pi pin.Input) {
3737
// Deprecated: Do not configure pins in drivers.
3838
// This is a legacy feature and should only be used by drivers that
3939
// previously configured pins in initialization to avoid breaking users.
40-
func ConfigurePinInput(pi pin.Input) {
40+
func ConfigurePinInput(pi drivers.InputPin) {
4141
configurePinInput(pi)
4242
}
4343

@@ -46,7 +46,7 @@ func ConfigurePinInput(pi pin.Input) {
4646
// Deprecated: Do not configure pins in drivers.
4747
// This is a legacy feature and should only be used by drivers that
4848
// previously configured pins in initialization to avoid breaking users.
49-
func ConfigurePinInputPullup(pi pin.Input) {
49+
func ConfigurePinInputPullup(pi drivers.InputPin) {
5050
configurePinInputPullup(pi)
5151
}
5252

internal/legacy/pinconfig_tinygo.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,22 @@ package legacy
55
import (
66
"machine"
77

8-
"tinygo.org/x/drivers/internal/pin"
8+
"tinygo.org/x/drivers"
99
)
1010

11-
func configurePinOut(po pin.Output) {
11+
func configurePinOut(po drivers.OutputPin) {
1212
configurePin(po, machine.PinOutput)
1313
}
1414

15-
func configurePinInputPulldown(pi pin.Input) {
15+
func configurePinInputPulldown(pi drivers.InputPin) {
1616
configurePin(pi, pulldown) // some chips do not have pull down, in which case pulldown==machine.PinInput.
1717
}
1818

19-
func configurePinInput(pi pin.Input) {
19+
func configurePinInput(pi drivers.InputPin) {
2020
configurePin(pi, machine.PinInput)
2121
}
2222

23-
func configurePinInputPullup(pi pin.Input) {
23+
func configurePinInputPullup(pi drivers.InputPin) {
2424
configurePin(pi, pullup) // some chips do not have pull up, in which case pullup==machine.PinInput.
2525
}
2626

internal/pin/internalpin.go

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,17 @@
11
package pin
22

3-
import "tinygo.org/x/drivers"
3+
// OutputFn is a function that sets the underlying pin's level.
4+
type OutputFn func(level bool)
45

5-
// This file contains interface-style Pin HAL definition.
6-
// It serves to eliminate machine.Pin from driver constructors
7-
// so that drivers can be used in "big" Go projects where
8-
// there is no machine package.
9-
10-
// Here to aid relevant documentation links of [drivers.PinOutput] and [drivers.PinInput].
11-
var _ drivers.PinOutput
12-
13-
// Output represents a pin hardware abstraction layer for a pin that can output a digital signal.
14-
//
15-
// This is an alternative to [drivers.PinOutput] abstraction which is a function type and has
16-
// not been standardized as of yet as a standard HAL in the drivers package,
17-
// [discussion ongoing here].
18-
//
19-
// [discussion ongoing here]: https://github.com/orgs/tinygo-org/discussions/5043
20-
type Output interface {
21-
Set(level bool)
6+
// High sets the underlying pin's level to high. This is equivalent to calling PinOutput(true).
7+
func (setPin OutputFn) High() {
8+
setPin(true)
229
}
2310

24-
// Input represents a pin hardware abstraction layer.
25-
// See [Output] for more information on why this type exists separate to drivers.
26-
type Input interface {
27-
Get() (level bool)
11+
// Low sets the underlying pin's level to low. This is equivalent to calling PinOutput(false).
12+
func (setPin OutputFn) Low() {
13+
setPin(false)
2814
}
15+
16+
// InputFn is a function that reads the underlying pin's level.
17+
type InputFn func() (level bool)

0 commit comments

Comments
 (0)