mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-31 04:57:47 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 453ff96a66 | |||
| c6d83b783f |
+15
-16
@@ -1,17 +1,17 @@
|
||||
package bmi160
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
"tinygo.org/x/drivers/internal/legacy"
|
||||
)
|
||||
|
||||
// DeviceSPI is the SPI interface to a BMI160 accelerometer/gyroscope. There is
|
||||
// also an I2C interface, but it is not yet supported.
|
||||
type DeviceSPI struct {
|
||||
// Chip select pin
|
||||
CSB machine.Pin
|
||||
CSB drivers.PinOutput
|
||||
|
||||
buf [7]byte
|
||||
|
||||
@@ -22,9 +22,9 @@ type DeviceSPI struct {
|
||||
// NewSPI returns a new device driver. The pin and SPI interface are not
|
||||
// touched, provide a fully configured SPI object and call Configure to start
|
||||
// using this device.
|
||||
func NewSPI(csb machine.Pin, spi drivers.SPI) *DeviceSPI {
|
||||
func NewSPI(csb drivers.PinOutput, spi drivers.SPI) *DeviceSPI {
|
||||
return &DeviceSPI{
|
||||
CSB: csb, // chip select
|
||||
CSB: legacy.PinOutput(csb), // chip select
|
||||
Bus: spi,
|
||||
}
|
||||
}
|
||||
@@ -33,8 +33,7 @@ func NewSPI(csb machine.Pin, spi drivers.SPI) *DeviceSPI {
|
||||
// configures the BMI160, but it does not configure the SPI interface (it is
|
||||
// assumed to be up and running).
|
||||
func (d *DeviceSPI) Configure() error {
|
||||
d.CSB.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
d.CSB.High()
|
||||
d.CSB.Set(true)
|
||||
|
||||
// The datasheet recommends doing a register read from address 0x7F to get
|
||||
// SPI communication going:
|
||||
@@ -86,9 +85,9 @@ func (d *DeviceSPI) ReadTemperature() (temperature int32, err error) {
|
||||
data[0] = 0x80 | reg_TEMPERATURE_0
|
||||
data[1] = 0
|
||||
data[2] = 0
|
||||
d.CSB.Low()
|
||||
d.CSB.Set(false)
|
||||
err = d.Bus.Tx(data, data)
|
||||
d.CSB.High()
|
||||
d.CSB.Set(true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -123,9 +122,9 @@ func (d *DeviceSPI) ReadAcceleration() (x int32, y int32, z int32, err error) {
|
||||
for i := 1; i < len(data); i++ {
|
||||
data[i] = 0
|
||||
}
|
||||
d.CSB.Low()
|
||||
d.CSB.Set(false)
|
||||
err = d.Bus.Tx(data, data)
|
||||
d.CSB.High()
|
||||
d.CSB.Set(true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -153,9 +152,9 @@ func (d *DeviceSPI) ReadRotation() (x int32, y int32, z int32, err error) {
|
||||
for i := 1; i < len(data); i++ {
|
||||
data[i] = 0
|
||||
}
|
||||
d.CSB.Low()
|
||||
d.CSB.Set(false)
|
||||
err = d.Bus.Tx(data, data)
|
||||
d.CSB.High()
|
||||
d.CSB.Set(true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -201,9 +200,9 @@ func (d *DeviceSPI) readRegister(address uint8) uint8 {
|
||||
data := d.buf[:2]
|
||||
data[0] = 0x80 | address
|
||||
data[1] = 0
|
||||
d.CSB.Low()
|
||||
d.CSB.Set(false)
|
||||
d.Bus.Tx(data, data)
|
||||
d.CSB.High()
|
||||
d.CSB.Set(true)
|
||||
return data[1]
|
||||
}
|
||||
|
||||
@@ -217,7 +216,7 @@ func (d *DeviceSPI) writeRegister(address, data uint8) {
|
||||
buf[0] = address
|
||||
buf[1] = data
|
||||
|
||||
d.CSB.Low()
|
||||
d.CSB.Set(false)
|
||||
d.Bus.Tx(buf, buf)
|
||||
d.CSB.High()
|
||||
d.CSB.Set(true)
|
||||
}
|
||||
|
||||
+7
-7
@@ -2,22 +2,22 @@
|
||||
package buzzer // import "tinygo.org/x/drivers/buzzer"
|
||||
|
||||
import (
|
||||
"machine"
|
||||
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// Device wraps a GPIO connection to a buzzer.
|
||||
type Device struct {
|
||||
pin machine.Pin
|
||||
set drivers.PinSet
|
||||
High bool
|
||||
BPM float64
|
||||
}
|
||||
|
||||
// New returns a new buzzer driver given which pin to use
|
||||
func New(pin machine.Pin) Device {
|
||||
func New(pin drivers.PinOutput) Device {
|
||||
return Device{
|
||||
pin: pin,
|
||||
set: pin.Set,
|
||||
High: false,
|
||||
BPM: 96.0,
|
||||
}
|
||||
@@ -25,14 +25,14 @@ func New(pin machine.Pin) Device {
|
||||
|
||||
// On sets the buzzer to a high state.
|
||||
func (l *Device) On() (err error) {
|
||||
l.pin.Set(true)
|
||||
l.set(true)
|
||||
l.High = true
|
||||
return
|
||||
}
|
||||
|
||||
// Off sets the buzzer to a low state.
|
||||
func (l *Device) Off() (err error) {
|
||||
l.pin.Set(false)
|
||||
l.set(false)
|
||||
l.High = false
|
||||
return
|
||||
}
|
||||
|
||||
+10
-11
@@ -9,9 +9,10 @@
|
||||
package dht // import "tinygo.org/x/drivers/dht"
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"runtime/interrupt"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// DummyDevice provides a basic interface for DHT devices.
|
||||
@@ -30,7 +31,7 @@ type DummyDevice interface {
|
||||
// Since taking measurements from the sensor is time consuming procedure and blocks interrupts,
|
||||
// user can avoid any hidden calls to the sensor.
|
||||
type device struct {
|
||||
pin machine.Pin
|
||||
pin drivers.Pin
|
||||
|
||||
measurements DeviceType
|
||||
initialized bool
|
||||
@@ -93,14 +94,12 @@ func (t *device) HumidityFloat() (float32, error) {
|
||||
// Perform initialization of the communication protocol.
|
||||
// Device lowers the voltage on pin for startingLow=20ms and starts listening for response
|
||||
// Section 5.2 in [1]
|
||||
func initiateCommunication(p machine.Pin) {
|
||||
func initiateCommunication(p drivers.Pin) {
|
||||
// Send low signal to the device
|
||||
p.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
p.Low()
|
||||
p.Set(false)
|
||||
time.Sleep(startingLow)
|
||||
// Set pin to high and wait for reply
|
||||
p.High()
|
||||
p.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||
p.Set(true)
|
||||
}
|
||||
|
||||
// Measurements returns both measurements: temperature and humidity as they sent by the device.
|
||||
@@ -158,7 +157,7 @@ func (t *device) read() error {
|
||||
|
||||
// receiveSignals counts number of low and high cycles. The execution is time critical, so the function disables
|
||||
// interrupts
|
||||
func receiveSignals(pin machine.Pin, result []counter) {
|
||||
func receiveSignals(pin drivers.PinInput, result []counter) {
|
||||
i := uint8(0)
|
||||
mask := interrupt.Disable()
|
||||
defer interrupt.Restore(mask)
|
||||
@@ -189,7 +188,7 @@ func (t *device) extractData(signals []counter, buf []uint8) error {
|
||||
// waitForDataTransmission waits for reply from the sensor.
|
||||
// If no reply received, returns NoSignalError.
|
||||
// For more details, see section 5.2 in [1]
|
||||
func waitForDataTransmission(p machine.Pin) error {
|
||||
func waitForDataTransmission(p drivers.PinInput) error {
|
||||
// wait for thermometer to pull down
|
||||
if expectChange(p, true) == timeout {
|
||||
return NoSignalError
|
||||
@@ -209,8 +208,8 @@ func waitForDataTransmission(p machine.Pin) error {
|
||||
// This device provides full control to the user.
|
||||
// It does not do any hidden measurements calls and does not check
|
||||
// for 2 seconds delay between measurements.
|
||||
func NewDummyDevice(pin machine.Pin, deviceType DeviceType) DummyDevice {
|
||||
pin.High()
|
||||
func NewDummyDevice(pin drivers.Pin, deviceType DeviceType) DummyDevice {
|
||||
pin.Set(true)
|
||||
return &device{
|
||||
pin: pin,
|
||||
measurements: deviceType,
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
package dht // import "tinygo.org/x/drivers/dht"
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// Device interface provides main functionality of the DHTXX sensors.
|
||||
@@ -124,8 +125,8 @@ func (m *managedDevice) Configure(policy UpdatePolicy) {
|
||||
|
||||
// Constructor of the Device implementation.
|
||||
// This implementation updates data every 2 seconds during data access.
|
||||
func New(pin machine.Pin, deviceType DeviceType) Device {
|
||||
pin.High()
|
||||
func New(pin drivers.Pin, deviceType DeviceType) Device {
|
||||
pin.Set(true)
|
||||
return &managedDevice{
|
||||
t: device{
|
||||
pin: pin,
|
||||
@@ -141,8 +142,8 @@ func New(pin machine.Pin, deviceType DeviceType) Device {
|
||||
}
|
||||
|
||||
// Constructor of the Device implementation with given UpdatePolicy
|
||||
func NewWithPolicy(pin machine.Pin, deviceType DeviceType, updatePolicy UpdatePolicy) Device {
|
||||
pin.High()
|
||||
func NewWithPolicy(pin drivers.Pin, deviceType DeviceType, updatePolicy UpdatePolicy) Device {
|
||||
pin.Set(true)
|
||||
result := &managedDevice{
|
||||
t: device{
|
||||
pin: pin,
|
||||
|
||||
+5
-4
@@ -3,21 +3,22 @@
|
||||
package dht // import "tinygo.org/x/drivers/dht"
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// Check if the pin is disabled
|
||||
func powerUp(p machine.Pin) bool {
|
||||
func powerUp(p drivers.Pin) bool {
|
||||
state := p.Get()
|
||||
if !state {
|
||||
p.High()
|
||||
p.Set(true)
|
||||
time.Sleep(startTimeout)
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
||||
func expectChange(p machine.Pin, oldState bool) counter {
|
||||
func expectChange(p drivers.PinInput, oldState bool) counter {
|
||||
cnt := counter(0)
|
||||
for ; p.Get() == oldState && cnt != timeout; cnt++ {
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
//go:build baremetal && tinygo
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/dht"
|
||||
"tinygo.org/x/drivers/tinygo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pin := machine.D6
|
||||
pin := tinygo.New(machine.D6)
|
||||
dhtSensor := dht.New(pin, dht.DHT11)
|
||||
for {
|
||||
temp, hum, err := dhtSensor.Measurements()
|
||||
|
||||
@@ -5,10 +5,13 @@ import (
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/hcsr04"
|
||||
"tinygo.org/x/drivers/tinygo"
|
||||
)
|
||||
|
||||
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()
|
||||
|
||||
println("Ultrasonic starts")
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package main
|
||||
|
||||
// Example program for the ST7735 display (Waveshare 1.44" LCD HAT) using the rpio driver on a Raspberry Pi.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"time"
|
||||
|
||||
go_rpio "github.com/stianeikeland/go-rpio/v4"
|
||||
"tinygo.org/x/drivers/rpio"
|
||||
"tinygo.org/x/drivers/st7735"
|
||||
)
|
||||
|
||||
var (
|
||||
black = color.RGBA{0, 0, 0, 255}
|
||||
colors = [...]color.RGBA{
|
||||
{255, 0, 0, 255}, // red
|
||||
{0, 255, 0, 255}, // green
|
||||
{0, 0, 255, 255}, // blue
|
||||
{255, 255, 0, 255}, // yellow
|
||||
}
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := go_rpio.Open(); err != nil {
|
||||
fmt.Println("Error opening GPIO:", err)
|
||||
return
|
||||
}
|
||||
defer go_rpio.Close()
|
||||
|
||||
// Initialize SPI and pins
|
||||
spi := rpio.NewSPI()
|
||||
resetPin := rpio.NewPin(27)
|
||||
dcPin := rpio.NewPin(25)
|
||||
csPin := rpio.NewPin(8)
|
||||
blPin := rpio.NewPin(24)
|
||||
|
||||
// Initialize display
|
||||
device := st7735.New(spi, resetPin, dcPin, csPin, blPin)
|
||||
device.Configure(st7735.Config{
|
||||
Width: 128,
|
||||
Height: 128,
|
||||
Model: st7735.GREENTAB,
|
||||
RowOffset: 3,
|
||||
ColumnOffset: 2,
|
||||
})
|
||||
device.InvertColors(false)
|
||||
device.EnableBacklight(true)
|
||||
device.IsBGR(true) // no effect w/o rotation!
|
||||
device.SetRotation(st7735.NO_ROTATION)
|
||||
|
||||
width, height := device.Size()
|
||||
|
||||
// Clear display
|
||||
device.FillScreen(black)
|
||||
|
||||
// Draw rectangles in a loop, clockwise rotation of colors
|
||||
pos := 0
|
||||
for {
|
||||
device.FillRectangle(0, 0, width/2, height/2, colors[(pos+0)%len(colors)]) // top left
|
||||
device.FillRectangle(0, height/2, width/2, height/2, colors[(pos+1)%len(colors)]) // bottom left
|
||||
device.FillRectangle(width/2, height/2, width/2, height/2, colors[(pos+2)%len(colors)]) // bottom right
|
||||
device.FillRectangle(width/2, 0, width/2, height/2, colors[(pos+3)%len(colors)]) // top right
|
||||
pos++
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ require (
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/orsinium-labs/tinymath v1.1.0
|
||||
github.com/soypat/natiu-mqtt v0.5.1
|
||||
github.com/stianeikeland/go-rpio/v4 v4.6.0
|
||||
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d
|
||||
golang.org/x/net v0.33.0
|
||||
tinygo.org/x/tinyfont v0.3.0
|
||||
|
||||
@@ -17,6 +17,8 @@ github.com/orsinium-labs/tinymath v1.1.0 h1:KomdsyLHB7vE3f1nRAJF2dyf1m/gnM2HxfTe
|
||||
github.com/orsinium-labs/tinymath v1.1.0/go.mod h1:WPXX6ei3KSXG7JfA03a+ekCYaY9SWN4I+JRl2p6ck+A=
|
||||
github.com/soypat/natiu-mqtt v0.5.1 h1:rwaDmlvjzD2+3MCOjMZc4QEkDkNwDzbct2TJbpz+TPc=
|
||||
github.com/soypat/natiu-mqtt v0.5.1/go.mod h1:xEta+cwop9izVCW7xOx2W+ct9PRMqr0gNVkvBPnQTc4=
|
||||
github.com/stianeikeland/go-rpio/v4 v4.6.0 h1:eAJgtw3jTtvn/CqwbC82ntcS+dtzUTgo5qlZKe677EY=
|
||||
github.com/stianeikeland/go-rpio/v4 v4.6.0/go.mod h1:A3GvHxC1Om5zaId+HqB3HKqx4K/AqeckxB7qRjxMK7o=
|
||||
github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d h1:0olWaB5pg3+oychR51GUVCEsGkeCU/2JxjBgIo4f3M0=
|
||||
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||
|
||||
+11
-10
@@ -5,20 +5,22 @@
|
||||
package hcsr04
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
const TIMEOUT = 23324 // max sensing distance (4m)
|
||||
|
||||
// Device holds the pins
|
||||
type Device struct {
|
||||
trigger machine.Pin
|
||||
echo machine.Pin
|
||||
trigger drivers.PinOutput
|
||||
echo drivers.PinInput
|
||||
}
|
||||
|
||||
// New returns a new ultrasonic driver given 2 pins
|
||||
func New(trigger, echo machine.Pin) Device {
|
||||
// New returns a new ultrasonic driver given 2 pins.
|
||||
// Pins must be configured as output (trigger) and input (echo).
|
||||
func New(trigger drivers.PinOutput, echo drivers.PinInput) Device {
|
||||
return Device{
|
||||
trigger: trigger,
|
||||
echo: echo,
|
||||
@@ -27,8 +29,7 @@ func New(trigger, echo machine.Pin) Device {
|
||||
|
||||
// Configure configures the pins of the Device
|
||||
func (d *Device) Configure() {
|
||||
d.trigger.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
d.echo.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||
// no-op, left for API compatibility
|
||||
}
|
||||
|
||||
// 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
|
||||
func (d *Device) ReadPulse() int32 {
|
||||
t := time.Now()
|
||||
d.trigger.Low()
|
||||
d.trigger.Set(false)
|
||||
time.Sleep(2 * time.Microsecond)
|
||||
d.trigger.High()
|
||||
d.trigger.Set(true)
|
||||
time.Sleep(10 * time.Microsecond)
|
||||
d.trigger.Low()
|
||||
d.trigger.Set(false)
|
||||
i := uint8(0)
|
||||
for {
|
||||
if d.echo.Get() {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
//go:build !(baremetal && tinygo)
|
||||
|
||||
package legacy
|
||||
|
||||
import "tinygo.org/x/drivers"
|
||||
|
||||
func PinOutput(pin drivers.PinOutput) drivers.PinOutput {
|
||||
return pin
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package drivers
|
||||
|
||||
// Pin types abstract the underlying implementation of a pin,
|
||||
// allowing the use of different hardware or libraries without changing driver code.
|
||||
//
|
||||
// Note, pin mode functionality is not part of the Pin interface.
|
||||
// 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 that used to configure output pin mode in their constructors can use
|
||||
// legacy.PinOutput() wrapper to keep the same behavior for machine.Pin.
|
||||
// See internal/legacy/pinlegacy_tinygo.go and internal/legacy/pinlegacy_generic.go for details.
|
||||
//
|
||||
// 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.
|
||||
type PinInput interface {
|
||||
Get() bool
|
||||
}
|
||||
|
||||
// PinOutput is an interface for setting the state of a pin.
|
||||
type PinOutput interface {
|
||||
Set(bool)
|
||||
}
|
||||
|
||||
// Pin is an interface for a pin that can be both input and output.
|
||||
type Pin interface {
|
||||
PinInput
|
||||
PinOutput
|
||||
}
|
||||
|
||||
// PinGet is a function type for getting the state of a pin
|
||||
// Shall be used in high-performance drivers to avoid interface call overhead.
|
||||
type PinGet func() bool
|
||||
|
||||
// PinSet is a function type for setting the state of a pin.
|
||||
// Shall be used in high-performance drivers to avoid interface call overhead.
|
||||
type PinSet func(bool)
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// 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"
|
||||
|
||||
import go_rpio "github.com/stianeikeland/go-rpio/v4"
|
||||
|
||||
type Pin struct {
|
||||
modeSet bool
|
||||
Mode go_rpio.Mode
|
||||
Pin go_rpio.Pin
|
||||
}
|
||||
|
||||
func NewPin(pinNumber int) *Pin {
|
||||
return &Pin{Pin: go_rpio.Pin(pinNumber)}
|
||||
}
|
||||
|
||||
func (p *Pin) Get() bool {
|
||||
if !p.modeSet || p.Mode != go_rpio.Input {
|
||||
p.Pin.Input()
|
||||
p.Mode = go_rpio.Input
|
||||
}
|
||||
return p.Pin.Read() == go_rpio.High
|
||||
}
|
||||
|
||||
func (p *Pin) Set(high bool) {
|
||||
if !p.modeSet || p.Mode != go_rpio.Output {
|
||||
p.Pin.Output()
|
||||
p.Mode = go_rpio.Output
|
||||
}
|
||||
state := go_rpio.Low
|
||||
if high {
|
||||
state = go_rpio.High
|
||||
}
|
||||
p.Pin.Write(state)
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package rpio // import "tinygo.org/x/drivers/rpio"
|
||||
|
||||
import go_rpio "github.com/stianeikeland/go-rpio/v4"
|
||||
|
||||
type SPI struct {
|
||||
}
|
||||
|
||||
func NewSPI() (s *SPI) {
|
||||
if err := go_rpio.SpiBegin(go_rpio.Spi0); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
go_rpio.SpiSpeed(25_000_000) // 25 MHz
|
||||
go_rpio.SpiChipSelect(0)
|
||||
return &SPI{}
|
||||
}
|
||||
|
||||
func (s *SPI) Tx(w, r []byte) error {
|
||||
data := make([]byte, len(w))
|
||||
copy(data, w)
|
||||
go_rpio.SpiExchange(data)
|
||||
copy(r, data)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SPI) Transfer(b byte) (byte, error) {
|
||||
w := []byte{b}
|
||||
r := make([]byte, len(w))
|
||||
err := s.Tx(w, r)
|
||||
return r[0], err
|
||||
}
|
||||
+17
-20
@@ -1,46 +1,43 @@
|
||||
package ssd1306
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
"tinygo.org/x/drivers/internal/legacy"
|
||||
)
|
||||
|
||||
type SPIBus struct {
|
||||
wire drivers.SPI
|
||||
dcPin machine.Pin
|
||||
resetPin machine.Pin
|
||||
csPin machine.Pin
|
||||
dcPin drivers.PinOutput
|
||||
resetPin drivers.PinOutput
|
||||
csPin drivers.PinOutput
|
||||
buffer []byte // buffer to avoid heap allocations
|
||||
}
|
||||
|
||||
// NewSPI creates a new SSD1306 connection. The SPI wire must already be configured.
|
||||
func NewSPI(bus drivers.SPI, dcPin, resetPin, csPin machine.Pin) *Device {
|
||||
dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
resetPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
csPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
func NewSPI(bus drivers.SPI, dcPin, resetPin, csPin drivers.PinOutput) *Device {
|
||||
return &Device{
|
||||
bus: &SPIBus{
|
||||
wire: bus,
|
||||
dcPin: dcPin,
|
||||
resetPin: resetPin,
|
||||
csPin: csPin,
|
||||
dcPin: legacy.PinOutput(dcPin),
|
||||
resetPin: legacy.PinOutput(resetPin),
|
||||
csPin: legacy.PinOutput(csPin),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// configure pins with the SPI bus and allocate the buffer
|
||||
func (b *SPIBus) configure(address uint16, size int16) []byte {
|
||||
b.csPin.Low()
|
||||
b.dcPin.Low()
|
||||
b.resetPin.Low()
|
||||
b.csPin.Set(false)
|
||||
b.dcPin.Set(false)
|
||||
b.resetPin.Set(false)
|
||||
|
||||
b.resetPin.High()
|
||||
b.resetPin.Set(true)
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
b.resetPin.Low()
|
||||
b.resetPin.Set(false)
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
b.resetPin.High()
|
||||
b.resetPin.Set(true)
|
||||
|
||||
b.buffer = make([]byte, size+1) // +1 for a command
|
||||
return b.buffer[1:] // return the image buffer
|
||||
@@ -59,10 +56,10 @@ func (b *SPIBus) flush() error {
|
||||
|
||||
// tx sends data to the display
|
||||
func (b *SPIBus) tx(data []byte, isCommand bool) error {
|
||||
b.csPin.High()
|
||||
b.csPin.Set(true)
|
||||
b.dcPin.Set(!isCommand)
|
||||
b.csPin.Low()
|
||||
b.csPin.Set(false)
|
||||
err := b.wire.Tx(data, nil)
|
||||
b.csPin.High()
|
||||
b.csPin.Set(true)
|
||||
return err
|
||||
}
|
||||
|
||||
+17
-21
@@ -5,12 +5,12 @@ package st7735 // import "tinygo.org/x/drivers/st7735"
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"errors"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
"tinygo.org/x/drivers/internal/legacy"
|
||||
"tinygo.org/x/drivers/pixel"
|
||||
)
|
||||
|
||||
@@ -39,10 +39,10 @@ type Device = DeviceOf[pixel.RGB565BE]
|
||||
// formats.
|
||||
type DeviceOf[T Color] struct {
|
||||
bus drivers.SPI
|
||||
dcPin machine.Pin
|
||||
resetPin machine.Pin
|
||||
csPin machine.Pin
|
||||
blPin machine.Pin
|
||||
dcPin drivers.PinOutput
|
||||
resetPin drivers.PinOutput
|
||||
csPin drivers.PinOutput
|
||||
blPin drivers.PinOutput
|
||||
width int16
|
||||
height int16
|
||||
columnOffset int16
|
||||
@@ -65,23 +65,19 @@ type Config struct {
|
||||
}
|
||||
|
||||
// New creates a new ST7735 connection. The SPI wire must already be configured.
|
||||
func New(bus drivers.SPI, resetPin, dcPin, csPin, blPin machine.Pin) Device {
|
||||
func New(bus drivers.SPI, resetPin, dcPin, csPin, blPin drivers.PinOutput) Device {
|
||||
return NewOf[pixel.RGB565BE](bus, resetPin, dcPin, csPin, blPin)
|
||||
}
|
||||
|
||||
// NewOf creates a new ST7735 connection with a particular pixel format. The SPI
|
||||
// wire must already be configured.
|
||||
func NewOf[T Color](bus drivers.SPI, resetPin, dcPin, csPin, blPin machine.Pin) DeviceOf[T] {
|
||||
dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
resetPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
csPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
blPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
func NewOf[T Color](bus drivers.SPI, resetPin, dcPin, csPin, blPin drivers.PinOutput) DeviceOf[T] {
|
||||
return DeviceOf[T]{
|
||||
bus: bus,
|
||||
dcPin: dcPin,
|
||||
resetPin: resetPin,
|
||||
csPin: csPin,
|
||||
blPin: blPin,
|
||||
dcPin: legacy.PinOutput(dcPin),
|
||||
resetPin: legacy.PinOutput(resetPin),
|
||||
csPin: legacy.PinOutput(csPin),
|
||||
blPin: legacy.PinOutput(blPin),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,11 +110,11 @@ func (d *DeviceOf[T]) Configure(cfg Config) {
|
||||
d.batchData = pixel.NewImage[T](int(d.batchLength), 1)
|
||||
|
||||
// reset the device
|
||||
d.resetPin.High()
|
||||
d.resetPin.Set(true)
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
d.resetPin.Low()
|
||||
d.resetPin.Set(false)
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
d.resetPin.High()
|
||||
d.resetPin.Set(true)
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
|
||||
// Common initialization
|
||||
@@ -226,7 +222,7 @@ func (d *DeviceOf[T]) Configure(cfg Config) {
|
||||
|
||||
d.SetRotation(d.rotation)
|
||||
|
||||
d.blPin.High()
|
||||
d.blPin.Set(true)
|
||||
}
|
||||
|
||||
// Display does nothing, there's no buffer as it might be too big for some boards
|
||||
@@ -438,9 +434,9 @@ func (d *DeviceOf[T]) Size() (w, h int16) {
|
||||
// EnableBacklight enables or disables the backlight
|
||||
func (d *DeviceOf[T]) EnableBacklight(enable bool) {
|
||||
if enable {
|
||||
d.blPin.High()
|
||||
d.blPin.Set(true)
|
||||
} else {
|
||||
d.blPin.Low()
|
||||
d.blPin.Set(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user