Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions internal/legacy/pinconfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package legacy

import (
"errors"

"tinygo.org/x/drivers/internal/pin"
)

// The pingconfig group of files serve to abstract away
// pin configuration calls on the machine.Pin type.
// It was observed this way of developing drivers was
// non-portable and unusable on "big" Go projects so
// future projects should NOT configure pins in driver code.
// Users must configure pins before passing them as arguments
// to drivers.

// ConfigurePinOut is a legacy function used to configure pins as outputs.
//
// Deprecated: Do not configure pins in drivers.
// This is a legacy feature and should only be used by drivers that
// previously configured pins in initialization to avoid breaking users.
func ConfigurePinOut(po pin.Output) {
configurePinOut(po)
}

// ConfigurePinInput is a legacy function used to configure pins as inputs.
//
// Deprecated: Do not configure pins in drivers.
// This is a legacy feature and should only be used by drivers that
// previously configured pins in initialization to avoid breaking users.
func ConfigurePinInputPulldown(pi pin.Input) {
configurePinInputPulldown(pi)
}

// ConfigurePinInput is a legacy function used to configure pins as inputs.
//
// Deprecated: Do not configure pins in drivers.
// This is a legacy feature and should only be used by drivers that
// previously configured pins in initialization to avoid breaking users.
func ConfigurePinInput(pi pin.Input) {
configurePinInput(pi)
}

// ConfigurePinInput is a legacy function used to configure pins as inputs.
//
// Deprecated: Do not configure pins in drivers.
// This is a legacy feature and should only be used by drivers that
// previously configured pins in initialization to avoid breaking users.
func ConfigurePinInputPullup(pi pin.Input) {
configurePinInputPullup(pi)
}

// PinIsNoPin returns true if the argument is a machine.Pin type and is the machine.NoPin predeclared type.
//
// Deprecated: Drivers do not require pin knowledge from now on.
func PinIsNoPin(pin any) bool {
return pinIsNoPin(pin)
}

var (
ErrConfigBeforeInstantiated = errors.New("device must be instantiated with New before calling Configure method")
)
15 changes: 15 additions & 0 deletions internal/legacy/pinconfig_go.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//go:build !tinygo

package legacy

import "tinygo.org/x/drivers/internal/pin"

// This file compiles for non-tinygo builds
// for use with "big" or "upstream" Go where
// there is no machine package.

func configurePinOut(p pin.Output) {}
func configurePinInput(p pin.Input) {}
func configurePinInputPulldown(p pin.Input) {}
func configurePinInputPullup(p pin.Input) {}
func pinIsNoPin(a any) bool { return false }
10 changes: 10 additions & 0 deletions internal/legacy/pinconfig_nopulls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//go:build baremetal && fe310

package legacy

import "machine"

const (
pulldown = machine.PinInput
pullup = machine.PinInput
)
13 changes: 13 additions & 0 deletions internal/legacy/pinconfig_pulls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//go:build baremetal && !fe310

package legacy

import "machine"

// If you are getting a build error here you then we missed adding
// your CPU build tag to the list of CPUs that do not have pulldown/pullups.
// Add it above and in pinhal_nopulls! You should also add a smoketest for it :)
const (
pulldown = machine.PinInputPulldown
pullup = machine.PinInputPullup
)
37 changes: 37 additions & 0 deletions internal/legacy/pinconfig_tinygo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//go:build baremetal

package legacy

import (
"machine"

"tinygo.org/x/drivers/internal/pin"
)

func configurePinOut(po pin.Output) {
configurePin(po, machine.PinOutput)
}

func configurePinInputPulldown(pi pin.Input) {
configurePin(pi, pulldown) // some chips do not have pull down, in which case pulldown==machine.PinInput.
}

func configurePinInput(pi pin.Input) {
configurePin(pi, machine.PinInput)
}

func configurePinInputPullup(pi pin.Input) {
configurePin(pi, pullup) // some chips do not have pull up, in which case pullup==machine.PinInput.
}

func pinIsNoPin(a any) bool {
p, ok := a.(machine.Pin)
return ok && p == machine.NoPin
}

func configurePin(p any, mode machine.PinMode) {
machinePin, ok := p.(machine.Pin)
if ok {
machinePin.Configure(machine.PinConfig{Mode: mode})
}
}
72 changes: 72 additions & 0 deletions internal/pin/internalpin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// package pin implements a TinyGo Pin HAL.
// It serves to eliminate machine.Pin from driver constructors
// so that drivers can be used in "big" Go projects where
// there is no machine package.
// This file contains both function and interface-style Pin HAL definitions.
package pin

// OutputFunc is hardware abstraction for a pin which outputs a
// digital signal (high or low level).
//
// // Code conversion demo: from machine.Pin to pin.OutputFunc
// led := machine.LED
// led.Configure(machine.PinConfig{Mode: machine.Output})
// var pin pin.OutputFunc = led.Set // Going from a machine.Pin to a pin.OutputFunc
//
// This is an alternative to [Output] which is an interface type.
type OutputFunc func(level bool)

// High sets the underlying pin's level to high. This is equivalent to calling PinOutput(true).
func (setPin OutputFunc) High() {
setPin(true)
}

// Low sets the underlying pin's level to low. This is equivalent to calling PinOutput(false).
func (setPin OutputFunc) Low() {
setPin(false)
}

// InputFunc is hardware abstraction for a pin which receives a
// digital signal and reads it (high or low level).
//
// // Code conversion demo: from machine.Pin to pin.InputFunc
// input := machine.LED
// input.Configure(machine.PinConfig{Mode: machine.PinInputPulldown}) // or use machine.PinInputPullup or machine.Input
// var pin pin.InputFunc = input.Get // Going from a machine.Pin to a pin.InputFunc
//
// This is an alternative to [Input] which is an interface type.
type InputFunc func() (level bool)

// // Below is an example on how to define a input/output pin HAL for a
// // pin that must switch between input and output mode:
//
// var pinIsOutput bool
// var po PinOutputFunc = func(b bool) {
// if !pinIsOutput {
// pin.Configure(outputMode)
// pinIsOutput = true
// }
// pin.Set(b)
// }
//
// var pi PinInputFunc = func() bool {
// if pinIsOutput {
// pin.Configure(inputMode)
// pinIsOutput = false
// }
// return pin.Get()
// }

// Output interface represents a pin hardware abstraction layer for a pin that can output a digital signal.
//
// This is an alternative to [OutputFunc] abstraction which is a function type.
type Output interface {
Set(level bool)
}

// Input interface represents a pin hardware abstraction layer for a pin that can read a digital signal.
//
// This is an alternative to [InputFunc] abstraction which is a function type.
type Input interface {
Get() (level bool)
}
40 changes: 23 additions & 17 deletions uc8151/uc8151.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ package uc8151 // import "tinygo.org/x/drivers/uc8151"
import (
"errors"
"image/color"
"machine"
"time"

"tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
"tinygo.org/x/drivers/internal/pin"
"tinygo.org/x/drivers/pixel"
)

Expand All @@ -31,10 +32,10 @@ type Config struct {

type Device struct {
bus drivers.SPI
cs machine.Pin
dc machine.Pin
rst machine.Pin
busy machine.Pin
cs pin.OutputFunc
dc pin.OutputFunc
rst pin.OutputFunc
isBusy pin.InputFunc
width int16
height int16
buffer []uint8
Expand All @@ -49,17 +50,22 @@ type Device struct {
type Speed uint8

// New returns a new uc8151 driver. Pass in a fully configured SPI bus.
func New(bus drivers.SPI, csPin, dcPin, rstPin, busyPin machine.Pin) Device {
csPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
rstPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
busyPin.Configure(machine.PinConfig{Mode: machine.PinInput})
// Pins passed in must be configured beforehand.
func New(bus drivers.SPI, csPin, dcPin, rstPin pin.Output, busyPin pin.Input) Device {
// For backwards compatibility.
// This driver used to configure pins,
// so leave in to not break users.
// May be removed in future so try not to depend on it!
legacy.ConfigurePinOut(csPin)
legacy.ConfigurePinOut(dcPin)
legacy.ConfigurePinOut(rstPin)
legacy.ConfigurePinInput(busyPin)
return Device{
bus: bus,
cs: csPin,
dc: dcPin,
rst: rstPin,
busy: busyPin,
bus: bus,
cs: csPin.Set,
dc: dcPin.Set,
rst: rstPin.Set,
isBusy: busyPin.Get,
}
}

Expand Down Expand Up @@ -313,14 +319,14 @@ func (d *Device) ClearDisplay() {

// WaitUntilIdle waits until the display is ready
func (d *Device) WaitUntilIdle() {
for !d.busy.Get() {
for !d.isBusy() {
time.Sleep(10 * time.Millisecond)
}
}

// IsBusy returns the busy status of the display
func (d *Device) IsBusy() bool {
return d.busy.Get()
return d.isBusy()
}

// ClearBuffer sets the buffer to 0xFF (white)
Expand Down