Pin HAL to break dependency of drivers from TinyGo's machine package #793
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This change proposes an approach to break dependency of the drivers from machine package.
See also #749 and #753
This approach uses build tags to ensure machine pins configured as outputs in drivers that used to do so and no-op in general pin case. Configuring machine pins as outputs transparently is important to not to break existing client code.
The wrapper does a type check and executes only on
machine.Pin
, passing any custom implementation through.PinOutput
interface is kept minimal, it hasSet(bool)
method only, dropping convenience methodsHigh()
andLow()
. This expected to simplify custom implementations but requires many, yet trivial, changes in drivers -- a fair tradeoff.All new drivers strongly advised not to use this legacy workaround and let pin modes be controlled by client code, either automatically by implementing checks in
Get()
andSet()
methods or once before calling a driver constructor.See updated DHT driver example for automatic pin mode handling.
A proof-of-concept non-TinyGo pin implementation is provided in
rpio
package to control pins on Raspberry Pi.See also example of controlling Waveshare 1.44inch LCD HAT (ST7735 driver) on RPi in
examples/rpio
.This also demonstrates automatic pin mode handling in
Get()
andSet()
functions.Several drivers were updated to use
drivers.Pin[Output]
, for demonstration.Set()
function to avoid performance penalty associated with interface lookups.legacy.PinOutput()
wrapper to maintain old behavior.drivers.Pin
interface that calls bothGet()
andSet()
on a pin -- in this one we have to stop configuring for inputs and outputs and let client code to maintain pin modes, as we can't know in drivers code which of input modes shall be set:PinInput
,PinInputPullup
orPinInputPulldown
. See note in the bottom of this PR description.legacy.PinOutput
and implementlegacy.PinInput
.Please note, none of examples for mentioned drivers, except "DHT" and "HCSR04", were changed, this demonstrates backwards compatibility and the ability to pass
machine.Pin
in changed drivers as before, maintaining functionality.DHT and HCSR04 examples use new helper type
tinygo.Pin
that handles pin modes automatically. It's up to client code to use this implementation or make their own.Note on automatic input mode setting.
At first (see the first commit in this PR), I've tried to implement fully automatic pin mode handling for
machine.Pin
, the only requirement was drivers have to usedrivers.SafePinOutput()
, etc functions. There is a major problem: we can't know for sure which input mode must be set automatically onGet()
operation. Rather than guessing, I propose we let the client code control that. Thankfully, there are not many drivers that use a flavor ofPinInput
mode. And, in the drivers that do, they shall stop doing that, since, as discussed, there is no way to know which mode is correct in every case.