more drivers are now cross platform

This commit is contained in:
soypat
2025-07-02 22:03:58 -03:00
committed by deadprogram
parent 7d3404f060
commit cd37668592
20 changed files with 481 additions and 325 deletions
+4
View File
@@ -2,6 +2,7 @@ package apa102
import ( import (
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
// bbSPI is a dumb bit-bang implementation of SPI protocol that is hardcoded // bbSPI is a dumb bit-bang implementation of SPI protocol that is hardcoded
@@ -18,6 +19,9 @@ type bbSPI struct {
// Configure sets up the SCK and SDO pins as outputs and sets them low // Configure sets up the SCK and SDO pins as outputs and sets them low
func (s *bbSPI) Configure() { func (s *bbSPI) Configure() {
if s.config == nil {
panic(legacy.ErrConfigBeforeInstantiated)
}
s.config() s.config()
s.SCK(false) s.SCK(false)
s.SDO(false) s.SDO(false)
+24 -20
View File
@@ -11,12 +11,12 @@ import (
// also an I2C interface, but it is not yet supported. // also an I2C interface, but it is not yet supported.
type DeviceSPI struct { type DeviceSPI struct {
// Chip select pin // Chip select pin
CSB drivers.PinOutput csb drivers.PinOutput
buf [7]byte buf [7]byte
// SPI bus (requires chip select to be usable). // SPI bus (requires chip select to be usable).
Bus drivers.SPI bus drivers.SPI
config func() config func()
} }
@@ -25,8 +25,8 @@ type DeviceSPI struct {
// using this device. // using this device.
func NewSPI(csb legacy.PinOutput, spi drivers.SPI) *DeviceSPI { func NewSPI(csb legacy.PinOutput, spi drivers.SPI) *DeviceSPI {
return &DeviceSPI{ return &DeviceSPI{
CSB: csb.Set, // chip select csb: csb.Set, // chip select
Bus: spi, bus: spi,
config: func() { config: func() {
legacy.ConfigurePinOut(csb) legacy.ConfigurePinOut(csb)
}, },
@@ -37,7 +37,11 @@ func NewSPI(csb legacy.PinOutput, spi drivers.SPI) *DeviceSPI {
// configures the BMI160, but it does not configure the SPI interface (it is // configures the BMI160, but it does not configure the SPI interface (it is
// assumed to be up and running). // assumed to be up and running).
func (d *DeviceSPI) Configure() error { func (d *DeviceSPI) Configure() error {
d.CSB(true) if d.config == nil {
return legacy.ErrConfigBeforeInstantiated
}
d.config()
d.csb(true)
// The datasheet recommends doing a register read from address 0x7F to get // The datasheet recommends doing a register read from address 0x7F to get
// SPI communication going: // SPI communication going:
@@ -89,9 +93,9 @@ func (d *DeviceSPI) ReadTemperature() (temperature int32, err error) {
data[0] = 0x80 | reg_TEMPERATURE_0 data[0] = 0x80 | reg_TEMPERATURE_0
data[1] = 0 data[1] = 0
data[2] = 0 data[2] = 0
d.CSB(false) d.csb(false)
err = d.Bus.Tx(data, data) err = d.bus.Tx(data, data)
d.CSB(true) d.csb(true)
if err != nil { if err != nil {
return return
} }
@@ -126,9 +130,9 @@ func (d *DeviceSPI) ReadAcceleration() (x int32, y int32, z int32, err error) {
for i := 1; i < len(data); i++ { for i := 1; i < len(data); i++ {
data[i] = 0 data[i] = 0
} }
d.CSB(false) d.csb(false)
err = d.Bus.Tx(data, data) err = d.bus.Tx(data, data)
d.CSB(true) d.csb(true)
if err != nil { if err != nil {
return return
} }
@@ -156,9 +160,9 @@ func (d *DeviceSPI) ReadRotation() (x int32, y int32, z int32, err error) {
for i := 1; i < len(data); i++ { for i := 1; i < len(data); i++ {
data[i] = 0 data[i] = 0
} }
d.CSB(false) d.csb(false)
err = d.Bus.Tx(data, data) err = d.bus.Tx(data, data)
d.CSB(true) d.csb(true)
if err != nil { if err != nil {
return return
} }
@@ -204,9 +208,9 @@ func (d *DeviceSPI) readRegister(address uint8) uint8 {
data := d.buf[:2] data := d.buf[:2]
data[0] = 0x80 | address data[0] = 0x80 | address
data[1] = 0 data[1] = 0
d.CSB(false) d.csb(false)
d.Bus.Tx(data, data) d.bus.Tx(data, data)
d.CSB(true) d.csb(true)
return data[1] return data[1]
} }
@@ -220,7 +224,7 @@ func (d *DeviceSPI) writeRegister(address, data uint8) {
buf[0] = address buf[0] = address
buf[1] = data buf[1] = data
d.CSB(false) d.csb(false)
d.Bus.Tx(buf, buf) d.bus.Tx(buf, buf)
d.CSB(true) d.csb(true)
} }
+55 -116
View File
@@ -1,10 +1,12 @@
//go:build baremetal
// Package easystepper provides a simple driver to rotate a 4-wire stepper motor. // Package easystepper provides a simple driver to rotate a 4-wire stepper motor.
package easystepper // import "tinygo.org/x/drivers/easystepper" package easystepper // import "tinygo.org/x/drivers/easystepper"
import ( import (
"errors"
"machine"
"time" "time"
"tinygo.org/x/drivers"
) )
// StepMode determines the coil sequence used to perform a single step // StepMode determines the coil sequence used to perform a single step
@@ -30,28 +32,10 @@ func (sm StepMode) stepCount() uint {
} }
} }
// DeviceConfig contains the configuration data for a single easystepper driver
type DeviceConfig struct {
// Pin1 ... Pin4 determines the pins to configure and use for the device
Pin1, Pin2, Pin3, Pin4 machine.Pin
// StepCount is the number of steps required to perform a full revolution of the stepper motor
StepCount uint
// RPM determines the speed of the stepper motor in 'Revolutions per Minute'
RPM uint
// Mode determines the coil sequence used to perform a single step
Mode StepMode
}
// DualDeviceConfig contains the configuration data for a dual easystepper driver
type DualDeviceConfig struct {
DeviceConfig
// Pin5 ... Pin8 determines the pins to configure and use for the second device
Pin5, Pin6, Pin7, Pin8 machine.Pin
}
// Device holds the pins and the delay between steps // Device holds the pins and the delay between steps
type Device struct { type Device struct {
pins [4]machine.Pin pins [4]drivers.PinOutput
config func()
stepDelay time.Duration stepDelay time.Duration
stepNumber uint8 stepNumber uint8
stepMode StepMode stepMode StepMode
@@ -62,51 +46,6 @@ type DualDevice struct {
devices [2]*Device devices [2]*Device
} }
// New returns a new single easystepper driver given a DeviceConfig
func New(config DeviceConfig) (*Device, error) {
if config.StepCount == 0 || config.RPM == 0 {
return nil, errors.New("config.StepCount and config.RPM must be > 0")
}
return &Device{
pins: [4]machine.Pin{config.Pin1, config.Pin2, config.Pin3, config.Pin4},
stepDelay: time.Second * 60 / time.Duration((config.StepCount * config.RPM)),
stepMode: config.Mode,
}, nil
}
// Configure configures the pins of the Device
func (d *Device) Configure() {
for _, pin := range d.pins {
pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
}
}
// NewDual returns a new dual easystepper driver given 8 pins, number of steps and rpm
func NewDual(config DualDeviceConfig) (*DualDevice, error) {
// Create the first device
dev1, err := New(config.DeviceConfig)
if err != nil {
return nil, err
}
// Create the second device
config.DeviceConfig.Pin1 = config.Pin5
config.DeviceConfig.Pin2 = config.Pin6
config.DeviceConfig.Pin3 = config.Pin7
config.DeviceConfig.Pin4 = config.Pin8
dev2, err := New(config.DeviceConfig)
if err != nil {
return nil, err
}
// Return composite dual device
return &DualDevice{devices: [2]*Device{dev1, dev2}}, nil
}
// Configure configures the pins of the DualDevice
func (d *DualDevice) Configure() {
d.devices[0].Configure()
d.devices[1].Configure()
}
// Move rotates the motor the number of given steps // Move rotates the motor the number of given steps
// (negative steps will rotate it the opposite direction) // (negative steps will rotate it the opposite direction)
func (d *Device) Move(steps int32) { func (d *Device) Move(steps int32) {
@@ -126,7 +65,7 @@ func (d *Device) Move(steps int32) {
// Off turns off all motor pins // Off turns off all motor pins
func (d *Device) Off() { func (d *Device) Off() {
for _, pin := range d.pins { for _, pin := range d.pins {
pin.Low() pin(false)
} }
} }
@@ -187,28 +126,28 @@ func (d *Device) stepMotor(step uint8) {
func (d *Device) stepMotor4(step uint8) { func (d *Device) stepMotor4(step uint8) {
switch step { switch step {
case 0: case 0:
d.pins[0].High() d.pins[0](true)
d.pins[1].Low() d.pins[1](false)
d.pins[2].High() d.pins[2](true)
d.pins[3].Low() d.pins[3](false)
break break
case 1: case 1:
d.pins[0].Low() d.pins[0](false)
d.pins[1].High() d.pins[1](true)
d.pins[2].High() d.pins[2](true)
d.pins[3].Low() d.pins[3](false)
break break
case 2: case 2:
d.pins[0].Low() d.pins[0](false)
d.pins[1].High() d.pins[1](true)
d.pins[2].Low() d.pins[2](false)
d.pins[3].High() d.pins[3](true)
break break
case 3: case 3:
d.pins[0].High() d.pins[0](true)
d.pins[1].Low() d.pins[1](false)
d.pins[2].Low() d.pins[2](false)
d.pins[3].High() d.pins[3](true)
break break
} }
d.stepNumber = step d.stepNumber = step
@@ -218,45 +157,45 @@ func (d *Device) stepMotor4(step uint8) {
func (d *Device) stepMotor8(step uint8) { func (d *Device) stepMotor8(step uint8) {
switch step { switch step {
case 0: case 0:
d.pins[0].High() d.pins[0](true)
d.pins[2].Low() d.pins[2](false)
d.pins[1].Low() d.pins[1](false)
d.pins[3].Low() d.pins[3](false)
case 1: case 1:
d.pins[0].High() d.pins[0](true)
d.pins[2].High() d.pins[2](true)
d.pins[1].Low() d.pins[1](false)
d.pins[3].Low() d.pins[3](false)
case 2: case 2:
d.pins[0].Low() d.pins[0](false)
d.pins[2].High() d.pins[2](true)
d.pins[1].Low() d.pins[1](false)
d.pins[3].Low() d.pins[3](false)
case 3: case 3:
d.pins[0].Low() d.pins[0](false)
d.pins[2].High() d.pins[2](true)
d.pins[1].High() d.pins[1](true)
d.pins[3].Low() d.pins[3](false)
case 4: case 4:
d.pins[0].Low() d.pins[0](false)
d.pins[2].Low() d.pins[2](false)
d.pins[1].High() d.pins[1](true)
d.pins[3].Low() d.pins[3](false)
case 5: case 5:
d.pins[0].Low() d.pins[0](false)
d.pins[2].Low() d.pins[2](false)
d.pins[1].High() d.pins[1](true)
d.pins[3].High() d.pins[3](true)
case 6: case 6:
d.pins[0].Low() d.pins[0](false)
d.pins[2].Low() d.pins[2](false)
d.pins[1].Low() d.pins[1](false)
d.pins[3].High() d.pins[3](true)
case 7: case 7:
d.pins[0].High() d.pins[0](true)
d.pins[2].Low() d.pins[2](false)
d.pins[1].Low() d.pins[1](false)
d.pins[3].High() d.pins[3](true)
} }
d.stepNumber = step d.stepNumber = step
} }
+83
View File
@@ -0,0 +1,83 @@
//go:build baremetal
package easystepper
import (
"errors"
"machine"
"time"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
)
// New returns a new single easystepper driver given a DeviceConfig
func New(config DeviceConfig) (*Device, error) {
if config.StepCount == 0 || config.RPM == 0 {
return nil, errors.New("config.StepCount and config.RPM must be > 0")
}
return &Device{
pins: [4]drivers.PinOutput{config.Pin1.Set, config.Pin2.Set, config.Pin3.Set, config.Pin4.Set},
stepDelay: time.Second * 60 / time.Duration((config.StepCount * config.RPM)),
stepMode: config.Mode,
config: func() {
legacy.ConfigurePinOut(config.Pin1)
legacy.ConfigurePinOut(config.Pin2)
legacy.ConfigurePinOut(config.Pin3)
legacy.ConfigurePinOut(config.Pin4)
},
}, nil
}
// Configure configures the pins of the Device
func (d *Device) Configure() {
if d.config == nil {
panic(legacy.ErrConfigBeforeInstantiated)
}
d.config()
}
// Configure configures the pins of the DualDevice
func (d *DualDevice) Configure() {
d.devices[0].Configure()
d.devices[1].Configure()
}
// NewDual returns a new dual easystepper driver given 8 pins, number of steps and rpm
func NewDual(config DualDeviceConfig) (*DualDevice, error) {
// Create the first device
dev1, err := New(config.DeviceConfig)
if err != nil {
return nil, err
}
// Create the second device
config.DeviceConfig.Pin1 = config.Pin5
config.DeviceConfig.Pin2 = config.Pin6
config.DeviceConfig.Pin3 = config.Pin7
config.DeviceConfig.Pin4 = config.Pin8
dev2, err := New(config.DeviceConfig)
if err != nil {
return nil, err
}
// Return composite dual device
return &DualDevice{devices: [2]*Device{dev1, dev2}}, nil
}
// DeviceConfig contains the configuration data for a single easystepper driver
type DeviceConfig struct {
// Pin1 ... Pin4 determines the pins to configure and use for the device
Pin1, Pin2, Pin3, Pin4 machine.Pin
// StepCount is the number of steps required to perform a full revolution of the stepper motor
StepCount uint
// RPM determines the speed of the stepper motor in 'Revolutions per Minute'
RPM uint
// Mode determines the coil sequence used to perform a single step
Mode StepMode
}
// DualDeviceConfig contains the configuration data for a dual easystepper driver
type DualDeviceConfig struct {
DeviceConfig
// Pin5 ... Pin8 determines the pins to configure and use for the second device
Pin5, Pin6, Pin7, Pin8 machine.Pin
}
+26
View File
@@ -0,0 +1,26 @@
package easystepper
import (
"errors"
"time"
"tinygo.org/x/drivers"
)
func NewCrossPlatform(stepcount, rpm uint, mode StepMode, pins [4]drivers.PinOutput) (*Device, error) {
if stepcount == 0 || rpm == 0 {
return nil, errors.New("zero rpm and/or stepcount")
}
for i := range pins {
if pins[i] == nil {
return nil, errors.New("nil pin")
}
}
d := &Device{
pins: pins,
stepDelay: time.Second * 60 / time.Duration((stepcount * rpm)),
stepMode: mode,
config: func() {},
}
return d, nil
}
+9 -6
View File
@@ -5,8 +5,6 @@
package ft6336 package ft6336
import ( import (
"machine"
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy" "tinygo.org/x/drivers/internal/legacy"
"tinygo.org/x/drivers/touch" "tinygo.org/x/drivers/touch"
@@ -17,16 +15,18 @@ type Device struct {
bus drivers.I2C bus drivers.I2C
buf []byte buf []byte
Address uint8 Address uint8
intPin machine.Pin config func()
} }
// New returns FT6336 device for the provided I2C bus using default address. // New returns FT6336 device for the provided I2C bus using default address.
func New(i2c drivers.I2C, intPin machine.Pin) *Device { func New(i2c drivers.I2C, intPin legacy.PinInput) *Device {
return &Device{ return &Device{
bus: i2c, bus: i2c,
buf: make([]byte, 11), buf: make([]byte, 11),
Address: Address, Address: Address,
intPin: intPin, config: func() {
legacy.ConfigurePinInputPulldown(intPin)
},
} }
} }
@@ -36,8 +36,11 @@ type Config struct {
// Configure the FT6336 device. // Configure the FT6336 device.
func (d *Device) Configure(config Config) error { func (d *Device) Configure(config Config) error {
if d.config == nil {
return legacy.ErrConfigBeforeInstantiated
}
d.write1Byte(0xA4, 0x00) d.write1Byte(0xA4, 0x00)
d.intPin.Configure(machine.PinConfig{Mode: machine.PinInputPulldown}) d.config()
return nil return nil
} }
+25 -25
View File
@@ -5,12 +5,12 @@ package gc9a01 // import "tinygo.org/x/drivers/gc9a01"
import ( import (
"image/color" "image/color"
"machine"
"time" "time"
"errors" "errors"
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
// Rotation controls the rotation used by the display. // Rotation controls the rotation used by the display.
@@ -22,10 +22,10 @@ type FrameRate uint8
// Device wraps an SPI connection. // Device wraps an SPI connection.
type Device struct { type Device struct {
bus drivers.SPI bus drivers.SPI
dcPin machine.Pin dcPin drivers.PinOutput
resetPin machine.Pin resetPin drivers.PinOutput
csPin machine.Pin csPin drivers.PinOutput
blPin machine.Pin blPin drivers.PinOutput
width int16 width int16
height int16 height int16
columnOffsetCfg int16 columnOffsetCfg int16
@@ -52,27 +52,27 @@ type Config struct {
} }
// New creates a new ST7789 connection. The SPI wire must already be configured. // New creates a new ST7789 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 legacy.PinOutput) Device {
resetPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) legacy.ConfigurePinOut(resetPin)
dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) legacy.ConfigurePinOut(dcPin)
csPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) legacy.ConfigurePinOut(csPin)
blPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) legacy.ConfigurePinOut(blPin)
return Device{ return Device{
bus: bus, bus: bus,
resetPin: resetPin, resetPin: resetPin.Set,
dcPin: dcPin, dcPin: dcPin.Set,
csPin: csPin, csPin: csPin.Set,
blPin: blPin, blPin: blPin.Set,
} }
} }
// Reset the Device // Reset the Device
func (d *Device) Reset() { func (d *Device) Reset() {
d.resetPin.High() d.resetPin(true)
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
d.resetPin.Low() d.resetPin(false)
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
d.resetPin.High() d.resetPin(true)
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
@@ -226,20 +226,20 @@ func (d *Device) Data(data uint8) {
// Tx sends data to the display // Tx sends data to the display
func (d *Device) Tx(data []byte, isCommand bool) { func (d *Device) Tx(data []byte, isCommand bool) {
d.dcPin.Set(!isCommand) d.dcPin(!isCommand)
d.bus.Tx(data, nil) d.bus.Tx(data, nil)
} }
// Rx reads data from the display // Rx reads data from the display
func (d *Device) Rx(command uint8, data []byte) { func (d *Device) Rx(command uint8, data []byte) {
d.dcPin.Low() d.dcPin(false)
d.csPin.Low() d.csPin(false)
d.bus.Transfer(command) d.bus.Transfer(command)
d.dcPin.High() d.dcPin(true)
for i := range data { for i := range data {
data[i], _ = d.bus.Transfer(0xFF) data[i], _ = d.bus.Transfer(0xFF)
} }
d.csPin.High() d.csPin(true)
} }
// Size returns the current size of the display. // Size returns the current size of the display.
@@ -250,9 +250,9 @@ func (d *Device) Size() (w, h int16) {
// EnableBacklight enables or disables the backlight // EnableBacklight enables or disables the backlight
func (d *Device) EnableBacklight(enable bool) { func (d *Device) EnableBacklight(enable bool) {
if enable { if enable {
d.blPin.High() d.blPin(true)
} else { } else {
d.blPin.Low() d.blPin(false)
} }
} }
@@ -563,5 +563,5 @@ func (d *Device) Configure(cfg Config) {
d.Command(DISPON) d.Command(DISPON)
time.Sleep(20 * time.Millisecond) time.Sleep(20 * time.Millisecond)
d.blPin.High() d.blPin(true)
} }
+22 -13
View File
@@ -5,30 +5,39 @@
package hcsr04 package hcsr04
import ( import (
"machine"
"time" "time"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
const TIMEOUT = 23324 // max sensing distance (4m) const TIMEOUT = 23324 // max sensing distance (4m)
// Device holds the pins // Device holds the pins
type Device struct { type Device struct {
trigger machine.Pin trigger drivers.PinOutput
echo machine.Pin echo drivers.PinInput
config func()
} }
// New returns a new ultrasonic driver given 2 pins // New returns a new ultrasonic driver given 2 pins
func New(trigger, echo machine.Pin) Device { func New(trigger legacy.PinOutput, echo legacy.PinInput) Device {
return Device{ return Device{
trigger: trigger, trigger: trigger.Set,
echo: echo, echo: echo.Get,
config: func() {
legacy.ConfigurePinOut(trigger)
legacy.ConfigurePinInput(echo)
},
} }
} }
// Configure configures the pins of the Device // Configure configures the pins of the Device
func (d *Device) Configure() { func (d *Device) Configure() {
d.trigger.Configure(machine.PinConfig{Mode: machine.PinOutput}) if d.config == nil {
d.echo.Configure(machine.PinConfig{Mode: machine.PinInput}) panic(legacy.ErrConfigBeforeInstantiated)
}
d.config()
} }
// ReadDistance returns the distance of the object in mm // ReadDistance returns the distance of the object in mm
@@ -45,14 +54,14 @@ func (d *Device) ReadDistance() int32 {
// ReadPulse returns the time of the pulse (roundtrip) in microseconds // ReadPulse returns the time of the pulse (roundtrip) in microseconds
func (d *Device) ReadPulse() int32 { func (d *Device) ReadPulse() int32 {
t := time.Now() t := time.Now()
d.trigger.Low() d.trigger(false)
time.Sleep(2 * time.Microsecond) time.Sleep(2 * time.Microsecond)
d.trigger.High() d.trigger(true)
time.Sleep(10 * time.Microsecond) time.Sleep(10 * time.Microsecond)
d.trigger.Low() d.trigger(false)
i := uint8(0) i := uint8(0)
for { for {
if d.echo.Get() { if d.echo() {
t = time.Now() t = time.Now()
break break
} }
@@ -66,7 +75,7 @@ func (d *Device) ReadPulse() int32 {
} }
i = 0 i = 0
for { for {
if !d.echo.Get() { if !d.echo() {
return int32(time.Since(t).Microseconds()) return int32(time.Since(t).Microseconds())
} }
i++ i++
+41 -2
View File
@@ -1,5 +1,7 @@
package legacy package legacy
import "errors"
// PinOutput represents a pin hardware abstraction layer for a pin that can output a digital signal. // PinOutput represents a pin hardware abstraction layer for a pin that can output a digital signal.
// This is an alternative to drivers.PinOutput abstraction which is a function type. Pros and cons // This is an alternative to drivers.PinOutput abstraction which is a function type. Pros and cons
// of both approaches have been discussed in the [relevant issue]. PinOutput should only be used // of both approaches have been discussed in the [relevant issue]. PinOutput should only be used
@@ -19,11 +21,48 @@ type PinOutput interface {
Set(level bool) Set(level bool)
} }
// PinInput represents a pin hardware abstraction layer. See [PinOutput] for
// more information on why this is "legacy".
type PinInput interface {
Get() (level bool)
}
// ConfigurePinOut is a legacy function used to configure pins as outputs. // ConfigurePinOut is a legacy function used to configure pins as outputs.
// //
// Deprecated: Do not configure pins in drivers. // Deprecated: Do not configure pins in drivers.
// This is a legacy feature and should only be used by drivers that // This is a legacy feature and should only be used by drivers that
// previously configured pins in initialization to avoid breaking users. // previously configured pins in initialization to avoid breaking users.
func ConfigurePinOut(p PinOutput) { func ConfigurePinOut(po PinOutput) {
configurePinOut(p) 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 PinInput) {
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 PinInput) {
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 PinInput) {
configurePinInputPullup(pi)
}
var (
ErrConfigBeforeInstantiated = errors.New("device must be instantiated with New before calling Configure method")
)
+17 -1
View File
@@ -5,8 +5,24 @@ package legacy
import "machine" import "machine"
func configurePinOut(p PinOutput) { func configurePinOut(p PinOutput) {
configurePin(p, machine.PinInputPulldown)
}
func configurePinInputPulldown(p PinInput) {
configurePin(p, machine.PinInputPulldown)
}
func configurePinInput(p PinInput) {
configurePin(p, machine.PinInput)
}
func configurePinInputPullup(p PinInput) {
configurePin(p, machine.PinInputPullup)
}
func configurePin(p any, mode machine.PinMode) {
machinePin, ok := p.(machine.Pin) machinePin, ok := p.(machine.Pin)
if ok { if ok {
machinePin.Configure(machine.PinConfig{Mode: machine.PinOutput}) machinePin.Configure(machine.PinConfig{Mode: mode})
} }
} }
+4 -1
View File
@@ -2,4 +2,7 @@
package legacy package legacy
func configurePinOut(p PinOutput) {} func configurePinOut(p PinOutput) {}
func configurePinInput(p PinInput) {}
func configurePinInputPulldown(p PinInput) {}
func configurePinInputPullup(p PinInput) {}
+6 -6
View File
@@ -3,9 +3,9 @@ package max6675
import ( import (
"errors" "errors"
"machine"
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
// ErrThermocoupleOpen is returned when the thermocouple input is open. // ErrThermocoupleOpen is returned when the thermocouple input is open.
@@ -14,16 +14,16 @@ var ErrThermocoupleOpen = errors.New("thermocouple input open")
type Device struct { type Device struct {
bus drivers.SPI bus drivers.SPI
cs machine.Pin cs drivers.PinOutput
} }
// Create a new Device to read from a MAX6675 thermocouple. // Create a new Device to read from a MAX6675 thermocouple.
// Pins must be configured before use. Frequency for SPI // Pins must be configured before use. Frequency for SPI
// should be 4.3MHz maximum. // should be 4.3MHz maximum.
func NewDevice(bus drivers.SPI, cs machine.Pin) *Device { func NewDevice(bus drivers.SPI, cs legacy.PinOutput) *Device {
return &Device{ return &Device{
bus: bus, bus: bus,
cs: cs, cs: cs.Set,
} }
} }
@@ -34,11 +34,11 @@ func (d *Device) Read() (float32, error) {
value uint16 value uint16
) )
d.cs.Low() d.cs(false)
if err := d.bus.Tx([]byte{0, 0}, read); err != nil { if err := d.bus.Tx([]byte{0, 0}, read); err != nil {
return 0, err return 0, err
} }
d.cs.High() d.cs(true)
// datasheet: Bit D2 is normally low and goes high if the thermocouple input is open. // datasheet: Bit D2 is normally low and goes high if the thermocouple input is open.
if read[1]&0x04 == 0x04 { if read[1]&0x04 == 0x04 {
+15 -11
View File
@@ -3,31 +3,35 @@
package max72xx package max72xx
import ( import (
"machine"
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
type Device struct { type Device struct {
bus drivers.SPI bus drivers.SPI
cs machine.Pin cs drivers.PinOutput
config func()
} }
// NewDriver creates a new max7219 connection. The SPI wire must already be configured // NewDriver creates a new max7219 connection. The SPI wire must already be configured
// The SPI frequency must not be higher than 10MHz. // The SPI frequency must not be higher than 10MHz.
// parameter cs: the datasheet also refers to this pin as "load" pin. // parameter cs: the datasheet also refers to this pin as "load" pin.
func NewDevice(bus drivers.SPI, cs machine.Pin) *Device { func NewDevice(bus drivers.SPI, cs legacy.PinOutput) *Device {
return &Device{ return &Device{
bus: bus, bus: bus,
cs: cs, cs: cs.Set,
config: func() {
legacy.ConfigurePinOut(cs)
},
} }
} }
// Configure setups the pins. // Configure setups the pins.
func (driver *Device) Configure() { func (driver *Device) Configure() {
outPutConfig := machine.PinConfig{Mode: machine.PinOutput} if driver.config == nil {
panic(legacy.ErrConfigBeforeInstantiated)
driver.cs.Configure(outPutConfig) }
driver.config()
} }
// SetScanLimit sets the scan limit. Maximum is 8. // SetScanLimit sets the scan limit. Maximum is 8.
@@ -89,8 +93,8 @@ func (driver *Device) writeByte(data byte) {
// WriteCommand write data to a given register. // WriteCommand write data to a given register.
func (driver *Device) WriteCommand(register, data byte) { func (driver *Device) WriteCommand(register, data byte) {
driver.cs.Low() driver.cs(false)
driver.writeByte(register) driver.writeByte(register)
driver.writeByte(data) driver.writeByte(data)
driver.cs.High() driver.cs(true)
} }
+29 -22
View File
@@ -8,18 +8,19 @@ package mcp2515 // import "tinygo.org/x/drivers/mcp2515"
import ( import (
"errors" "errors"
"fmt" "fmt"
"machine"
"time" "time"
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
// Device wraps MCP2515 SPI CAN Module. // Device wraps MCP2515 SPI CAN Module.
type Device struct { type Device struct {
spi SPI spi SPI
cs machine.Pin cs drivers.PinOutput
msg *CANMsg msg *CANMsg
mcpMode byte mcpMode byte
config func()
} }
// CANMsg stores CAN message fields. // CANMsg stores CAN message fields.
@@ -36,15 +37,18 @@ const (
) )
// New returns a new MCP2515 driver. Pass in a fully configured SPI bus. // New returns a new MCP2515 driver. Pass in a fully configured SPI bus.
func New(b drivers.SPI, csPin machine.Pin) *Device { func New(b drivers.SPI, csPin legacy.PinOutput) *Device {
d := &Device{ d := &Device{
spi: SPI{ spi: SPI{
bus: b, bus: b,
tx: make([]byte, 0, bufferSize), tx: make([]byte, 0, bufferSize),
rx: make([]byte, 0, bufferSize), rx: make([]byte, 0, bufferSize),
}, },
cs: csPin, cs: csPin.Set,
msg: &CANMsg{}, msg: &CANMsg{},
config: func() {
legacy.ConfigurePinOut(csPin)
},
} }
return d return d
@@ -52,7 +56,10 @@ func New(b drivers.SPI, csPin machine.Pin) *Device {
// Configure sets up the device for communication. // Configure sets up the device for communication.
func (d *Device) Configure() { func (d *Device) Configure() {
d.cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) if d.config == nil {
panic(legacy.ErrConfigBeforeInstantiated)
}
d.config()
} }
const beginTimeoutValue int = 10 const beginTimeoutValue int = 10
@@ -159,9 +166,9 @@ func (d *Device) init(speed, clock byte) error {
// Reset resets mcp2515. // Reset resets mcp2515.
func (d *Device) Reset() error { func (d *Device) Reset() error {
d.cs.Low() d.cs(false)
_, err := d.spi.readWrite(mcpReset) _, err := d.spi.readWrite(mcpReset)
d.cs.High() d.cs(true)
// time.Sleep(time.Microsecond * 4) // time.Sleep(time.Microsecond * 4)
if err != nil { if err != nil {
return err return err
@@ -449,8 +456,8 @@ func (d *Device) readMsg() error {
func (d *Device) readRxBuffer(loadAddr uint8) error { func (d *Device) readRxBuffer(loadAddr uint8) error {
msg := d.msg msg := d.msg
d.cs.Low() d.cs(false)
defer d.cs.High() defer d.cs(true)
_, err := d.spi.readWrite(loadAddr) _, err := d.spi.readWrite(loadAddr)
if err != nil { if err != nil {
return err return err
@@ -517,8 +524,8 @@ func (d *Device) getNextFreeTxBuf() (uint8, uint8, error) {
} }
func (d *Device) writeCANMsg(bufNum uint8, canid uint32, ext, rtrBit, dlc uint8, data []byte) error { func (d *Device) writeCANMsg(bufNum uint8, canid uint32, ext, rtrBit, dlc uint8, data []byte) error {
d.cs.Low() d.cs(false)
defer d.cs.High() defer d.cs(true)
_, err := d.spi.readWrite(txSidhToLoad(bufNum)) _, err := d.spi.readWrite(txSidhToLoad(bufNum))
if err != nil { if err != nil {
return err return err
@@ -537,7 +544,7 @@ func (d *Device) writeCANMsg(bufNum uint8, canid uint32, ext, rtrBit, dlc uint8,
} }
// Since cs.Low and cs.High are executed in d.startTransmission, // Since cs.Low and cs.High are executed in d.startTransmission,
// it is necessary to set cs.High once to separate the instruction of mcp2515. // it is necessary to set cs.High once to separate the instruction of mcp2515.
d.cs.High() d.cs(true)
err = d.startTransmission(bufNum) err = d.startTransmission(bufNum)
if err != nil { if err != nil {
@@ -605,9 +612,9 @@ func (s *SPI) setTxBufData(canid uint32, ext, rtrBit, dlc uint8, data []byte) er
} }
func (d *Device) startTransmission(bufNum uint8) error { func (d *Device) startTransmission(bufNum uint8) error {
d.cs.Low() d.cs(false)
_, err := d.spi.readWrite(txSidhToRTS(bufNum)) _, err := d.spi.readWrite(txSidhToRTS(bufNum))
d.cs.High() d.cs(true)
if err != nil { if err != nil {
return err return err
} }
@@ -701,8 +708,8 @@ func txSidhToLoad(i uint8) uint8 {
} }
func (d *Device) setRegister(addr, value byte) error { func (d *Device) setRegister(addr, value byte) error {
d.cs.Low() d.cs(false)
defer d.cs.High() defer d.cs(true)
_, err := d.spi.readWrite(mcpWrite) _, err := d.spi.readWrite(mcpWrite)
if err != nil { if err != nil {
return err return err
@@ -721,8 +728,8 @@ func (d *Device) setRegister(addr, value byte) error {
} }
func (d *Device) readRegister(addr byte) (byte, error) { func (d *Device) readRegister(addr byte) (byte, error) {
d.cs.Low() d.cs(false)
defer d.cs.High() defer d.cs(true)
_, err := d.spi.readWrite(mcpRead) _, err := d.spi.readWrite(mcpRead)
if err != nil { if err != nil {
return 0, err return 0, err
@@ -740,8 +747,8 @@ func (d *Device) readRegister(addr byte) (byte, error) {
} }
func (d *Device) modifyRegister(addr, mask, data byte) error { func (d *Device) modifyRegister(addr, mask, data byte) error {
d.cs.Low() d.cs(false)
defer d.cs.High() defer d.cs(true)
_, err := d.spi.readWrite(mcpBitMod) _, err := d.spi.readWrite(mcpBitMod)
if err != nil { if err != nil {
return err return err
@@ -783,8 +790,8 @@ func (d *Device) requestNewMode(newMode byte) error {
} }
func (d *Device) readStatus() (byte, error) { func (d *Device) readStatus() (byte, error) {
d.cs.Low() d.cs(false)
defer d.cs.High() defer d.cs(true)
_, err := d.spi.readWrite(mcpReadStatus) _, err := d.spi.readWrite(mcpReadStatus)
if err != nil { if err != nil {
return 0, err return 0, err
+14 -14
View File
@@ -6,18 +6,18 @@ package pcd8544 // import "tinygo.org/x/drivers/pcd8544"
import ( import (
"errors" "errors"
"image/color" "image/color"
"machine"
"time" "time"
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
// Device wraps an SPI connection. // Device wraps an SPI connection.
type Device struct { type Device struct {
bus drivers.SPI bus drivers.SPI
dcPin machine.Pin dcPin drivers.PinOutput
rstPin machine.Pin rstPin drivers.PinOutput
scePin machine.Pin scePin drivers.PinOutput
buffer []byte buffer []byte
width int16 width int16
height int16 height int16
@@ -30,12 +30,12 @@ type Config struct {
} }
// New creates a new PCD8544 connection. The SPI bus must already be configured. // New creates a new PCD8544 connection. The SPI bus must already be configured.
func New(bus drivers.SPI, dcPin, rstPin, scePin machine.Pin) *Device { func New(bus drivers.SPI, dcPin, rstPin, scePin legacy.PinOutput) *Device {
return &Device{ return &Device{
bus: bus, bus: bus,
dcPin: dcPin, dcPin: dcPin.Set,
rstPin: rstPin, rstPin: rstPin.Set,
scePin: scePin, scePin: scePin.Set,
} }
} }
@@ -54,9 +54,9 @@ func (d *Device) Configure(cfg Config) {
d.bufferSize = d.width * d.height / 8 d.bufferSize = d.width * d.height / 8
d.buffer = make([]byte, d.bufferSize) d.buffer = make([]byte, d.bufferSize)
d.rstPin.Low() d.rstPin(false)
time.Sleep(100 * time.Nanosecond) time.Sleep(100 * time.Nanosecond)
d.rstPin.High() d.rstPin(true)
d.SendCommand(FUNCTIONSET | EXTENDEDINSTRUCTION) // H = 1 d.SendCommand(FUNCTIONSET | EXTENDEDINSTRUCTION) // H = 1
d.SendCommand(SETVOP | 0x3f) // 0x3f : Vop6 = 0, Vop5 to Vop0 = 1 d.SendCommand(SETVOP | 0x3f) // 0x3f : Vop6 = 0, Vop5 to Vop0 = 1
d.SendCommand(SETTEMP | 0x03) // Experimentally determined d.SendCommand(SETTEMP | 0x03) // Experimentally determined
@@ -91,13 +91,13 @@ func (d *Device) Display() error {
// sendDataCommand sends image data or a command to the screen // sendDataCommand sends image data or a command to the screen
func (d *Device) sendDataCommand(isCommand bool, data uint8) { func (d *Device) sendDataCommand(isCommand bool, data uint8) {
if isCommand { if isCommand {
d.dcPin.Low() d.dcPin(false)
} else { } else {
d.dcPin.High() d.dcPin(true)
} }
d.scePin.Low() d.scePin(false)
d.bus.Transfer(data) d.bus.Transfer(data)
d.scePin.High() d.scePin(true)
} }
// SetPixel enables or disables a pixel in the buffer // SetPixel enables or disables a pixel in the buffer
+24 -17
View File
@@ -2,7 +2,8 @@
package shiftregister package shiftregister
import ( import (
"machine" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
type NumberBit int8 type NumberBit int8
@@ -16,9 +17,10 @@ const (
// Device holds pin number // Device holds pin number
type Device struct { type Device struct {
latch, clock, out machine.Pin // IC wiring latch, clock, out drivers.PinOutput // IC wiring
bits NumberBit // Pin number config func()
mask uint32 // keep all pins state bits NumberBit // Pin number
mask uint32 // keep all pins state
} }
// ShiftPin is the implementation of the ShiftPin interface. // ShiftPin is the implementation of the ShiftPin interface.
@@ -29,35 +31,40 @@ type ShiftPin struct {
} }
// New returns a new shift output register device // New returns a new shift output register device
func New(Bits NumberBit, Latch, Clock, Out machine.Pin) *Device { func New(Bits NumberBit, Latch, Clock, Out legacy.PinOutput) *Device {
return &Device{ return &Device{
latch: Latch, latch: Latch.Set,
clock: Clock, clock: Clock.Set,
out: Out, out: Out.Set,
bits: Bits, bits: Bits,
config: func() {
legacy.ConfigurePinOut(Latch)
legacy.ConfigurePinOut(Clock)
legacy.ConfigurePinOut(Out)
},
} }
} }
// Configure set hardware configuration // Configure set hardware configuration
func (d *Device) Configure() { func (d *Device) Configure() {
d.latch.Configure(machine.PinConfig{Mode: machine.PinOutput}) if d.config == nil {
d.clock.Configure(machine.PinConfig{Mode: machine.PinOutput}) panic(legacy.ErrConfigBeforeInstantiated)
d.out.Configure(machine.PinConfig{Mode: machine.PinOutput}) }
d.latch.High() d.latch(true)
} }
// WriteMask applies mask's bits to register's outputs pin // WriteMask applies mask's bits to register's outputs pin
// mask's MSB set Q1, LSB set Q8 (for 8 bits mask) // mask's MSB set Q1, LSB set Q8 (for 8 bits mask)
func (d *Device) WriteMask(mask uint32) { func (d *Device) WriteMask(mask uint32) {
d.mask = mask // Keep the mask for individual addressing d.mask = mask // Keep the mask for individual addressing
d.latch.Low() d.latch(false)
for i := 0; i < int(d.bits); i++ { for i := 0; i < int(d.bits); i++ {
d.clock.Low() d.clock(false)
d.out.Set(mask&1 != 0) d.out(mask&1 != 0)
mask = mask >> 1 mask = mask >> 1
d.clock.High() d.clock(true)
} }
d.latch.High() d.latch(true)
} }
// GetShiftPin return an individually addressable pin // GetShiftPin return an individually addressable pin
+2
View File
@@ -1,3 +1,5 @@
//go:build baremetal
package ssd1289 package ssd1289
import "machine" import "machine"
+34 -32
View File
@@ -7,6 +7,9 @@ import (
"image/color" "image/color"
"machine" "machine"
"time" "time"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
type Bus interface { type Bus interface {
@@ -14,10 +17,10 @@ type Bus interface {
} }
type Device struct { type Device struct {
rs machine.Pin rs drivers.PinOutput
wr machine.Pin wr drivers.PinOutput
cs machine.Pin cs drivers.PinOutput
rst machine.Pin rst drivers.PinOutput
bus Bus bus Bus
} }
@@ -26,32 +29,31 @@ const height = int16(320)
func New(rs machine.Pin, wr machine.Pin, cs machine.Pin, rst machine.Pin, bus Bus) Device { func New(rs machine.Pin, wr machine.Pin, cs machine.Pin, rst machine.Pin, bus Bus) Device {
d := Device{ d := Device{
rs: rs, rs: rs.Set,
wr: wr, wr: wr.Set,
cs: cs, cs: cs.Set,
rst: rst, rst: rst.Set,
bus: bus, bus: bus,
} }
legacy.ConfigurePinOut(rs)
legacy.ConfigurePinOut(wr)
legacy.ConfigurePinOut(cs)
legacy.ConfigurePinOut(rst)
rs.Configure(machine.PinConfig{Mode: machine.PinOutput}) cs.Set(true)
wr.Configure(machine.PinConfig{Mode: machine.PinOutput}) rst.Set(true)
cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) wr.Set(true)
rst.Configure(machine.PinConfig{Mode: machine.PinOutput})
cs.High()
rst.High()
wr.High()
return d return d
} }
func (d *Device) lcdWriteCom(cmd Command) { func (d *Device) lcdWriteCom(cmd Command) {
d.rs.Low() d.rs(false)
d.lcdWriteBusInt(uint16(cmd)) d.lcdWriteBusInt(uint16(cmd))
} }
func (d *Device) lcdWriteDataInt(data uint16) { func (d *Device) lcdWriteDataInt(data uint16) {
d.rs.High() d.rs(true)
d.lcdWriteBusInt(data) d.lcdWriteBusInt(data)
} }
@@ -61,8 +63,8 @@ func (d *Device) lcdWriteComData(cmd Command, data uint16) {
} }
func (d *Device) tx() { func (d *Device) tx() {
d.wr.Low() d.wr(false)
d.wr.High() d.wr(true)
} }
func (d *Device) lcdWriteBusInt(data uint16) { func (d *Device) lcdWriteBusInt(data uint16) {
@@ -71,13 +73,13 @@ func (d *Device) lcdWriteBusInt(data uint16) {
} }
func (d *Device) Configure() { func (d *Device) Configure() {
d.rst.High() d.rst(true)
time.Sleep(time.Millisecond * 5) time.Sleep(time.Millisecond * 5)
d.rst.Low() d.rst(false)
time.Sleep(time.Millisecond * 15) time.Sleep(time.Millisecond * 15)
d.rst.High() d.rst(true)
time.Sleep(time.Millisecond * 15) time.Sleep(time.Millisecond * 15)
d.cs.Low() d.cs(false)
//Power supply setting //Power supply setting
d.lcdWriteComData(POWERCONTROL1, 0xA8A4) d.lcdWriteComData(POWERCONTROL1, 0xA8A4)
@@ -137,7 +139,7 @@ func (d *Device) Configure() {
//MUX 319 --> Number of lines in display //MUX 319 --> Number of lines in display
d.lcdWriteComData(DRIVEROUTPUTCONTROL, 0x233F) d.lcdWriteComData(DRIVEROUTPUTCONTROL, 0x233F)
d.cs.High() d.cs(true)
} }
@@ -167,25 +169,25 @@ func (d *Device) SetPixel(x, y int16, c color.RGBA) {
encoded := encodeColor(c) encoded := encodeColor(c)
d.cs.Low() d.cs(false)
d.setXY(uint16(x), uint16(y), uint16(x), uint16(y)) d.setXY(uint16(x), uint16(y), uint16(x), uint16(y))
d.rs.High() d.rs(true)
d.lcdWriteBusInt(encoded) d.lcdWriteBusInt(encoded)
d.cs.High() d.cs(true)
} }
func (d *Device) FillRect(x, y, w, h int16, c color.RGBA) { func (d *Device) FillRect(x, y, w, h int16, c color.RGBA) {
encoded := encodeColor(c) encoded := encodeColor(c)
d.cs.Low() d.cs(false)
d.setXY(uint16(x), uint16(y), uint16(x+(w-1)), uint16(y+(h-1))) d.setXY(uint16(x), uint16(y), uint16(x+(w-1)), uint16(y+(h-1)))
d.rs.High() d.rs(true)
d.bus.Set(encoded) d.bus.Set(encoded)
for i := int64(0); i < int64(w)*int64(h); i++ { for i := int64(0); i < int64(w)*int64(h); i++ {
d.tx() d.tx()
} }
d.cs.High() d.cs(true)
d.rs.Low() d.rs(false)
} }
+14 -13
View File
@@ -11,6 +11,7 @@ import (
"time" "time"
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
type Model uint8 type Model uint8
@@ -19,9 +20,9 @@ type Rotation uint8
// Device wraps an SPI connection. // Device wraps an SPI connection.
type Device struct { type Device struct {
bus drivers.SPI bus drivers.SPI
dcPin machine.Pin dcPin drivers.PinOutput
resetPin machine.Pin resetPin drivers.PinOutput
csPin machine.Pin csPin drivers.PinOutput
width int16 width int16
height int16 height int16
batchLength int16 batchLength int16
@@ -37,14 +38,14 @@ type Config struct {
// New creates a new SSD1331 connection. The SPI wire must already be configured. // New creates a new SSD1331 connection. The SPI wire must already be configured.
func New(bus drivers.SPI, resetPin, dcPin, csPin machine.Pin) Device { func New(bus drivers.SPI, resetPin, dcPin, csPin machine.Pin) Device {
dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) legacy.ConfigurePinOut(dcPin)
resetPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) legacy.ConfigurePinOut(resetPin)
csPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) legacy.ConfigurePinOut(csPin)
return Device{ return Device{
bus: bus, bus: bus,
dcPin: dcPin, dcPin: dcPin.Set,
resetPin: resetPin, resetPin: resetPin.Set,
csPin: csPin, csPin: csPin.Set,
} }
} }
@@ -69,11 +70,11 @@ func (d *Device) Configure(cfg Config) {
d.batchData = make([]uint8, d.batchLength*2) d.batchData = make([]uint8, d.batchLength*2)
// reset the device // reset the device
d.resetPin.High() d.resetPin(true)
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
d.resetPin.Low() d.resetPin(false)
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
d.resetPin.High() d.resetPin(true)
time.Sleep(200 * time.Millisecond) time.Sleep(200 * time.Millisecond)
// Initialization // Initialization
@@ -251,7 +252,7 @@ func (d *Device) Data(data uint8) {
// Tx sends data to the display // Tx sends data to the display
func (d *Device) Tx(data []byte, isCommand bool) { func (d *Device) Tx(data []byte, isCommand bool) {
d.dcPin.Set(!isCommand) d.dcPin(!isCommand)
d.bus.Tx(data, nil) d.bus.Tx(data, nil)
} }
+33 -26
View File
@@ -6,10 +6,10 @@ package ssd1351 // import "tinygo.org/x/drivers/ssd1351"
import ( import (
"errors" "errors"
"image/color" "image/color"
"machine"
"time" "time"
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
) )
var ( var (
@@ -20,11 +20,12 @@ var (
// Device wraps an SPI connection. // Device wraps an SPI connection.
type Device struct { type Device struct {
bus drivers.SPI bus drivers.SPI
dcPin machine.Pin dcPin drivers.PinOutput
resetPin machine.Pin resetPin drivers.PinOutput
csPin machine.Pin csPin drivers.PinOutput
enPin machine.Pin enPin drivers.PinOutput
rwPin machine.Pin rwPin drivers.PinOutput
config func()
width int16 width int16
height int16 height int16
rowOffset int16 rowOffset int16
@@ -41,19 +42,29 @@ type Config struct {
} }
// New creates a new SSD1351 connection. The SPI wire must already be configured. // New creates a new SSD1351 connection. The SPI wire must already be configured.
func New(bus drivers.SPI, resetPin, dcPin, csPin, enPin, rwPin machine.Pin) Device { func New(bus drivers.SPI, resetPin, dcPin, csPin, enPin, rwPin legacy.PinOutput) Device {
return Device{ return Device{
bus: bus, bus: bus,
dcPin: dcPin, dcPin: dcPin.Set,
resetPin: resetPin, resetPin: resetPin.Set,
csPin: csPin, csPin: csPin.Set,
enPin: enPin, enPin: enPin.Set,
rwPin: rwPin, rwPin: rwPin.Set,
config: func() {
legacy.ConfigurePinOut(dcPin)
legacy.ConfigurePinOut(resetPin)
legacy.ConfigurePinOut(csPin)
legacy.ConfigurePinOut(enPin)
legacy.ConfigurePinOut(rwPin)
},
} }
} }
// Configure initializes the display with default configuration // Configure initializes the display with default configuration
func (d *Device) Configure(cfg Config) { func (d *Device) Configure(cfg Config) {
if d.config == nil {
panic(legacy.ErrConfigBeforeInstantiated)
}
if cfg.Width == 0 { if cfg.Width == 0 {
cfg.Width = 128 cfg.Width = 128
} }
@@ -73,23 +84,19 @@ func (d *Device) Configure(cfg Config) {
} }
// configure GPIO pins // configure GPIO pins
d.dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) d.config()
d.resetPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
d.csPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
d.enPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
d.rwPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
// reset the device // reset the device
d.resetPin.High() d.resetPin(true)
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
d.resetPin.Low() d.resetPin(false)
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
d.resetPin.High() d.resetPin(true)
time.Sleep(200 * time.Millisecond) time.Sleep(200 * time.Millisecond)
d.rwPin.Low() d.rwPin(false)
d.dcPin.Low() d.dcPin(false)
d.enPin.High() d.enPin(true)
// Initialization // Initialization
d.Command(SET_COMMAND_LOCK) d.Command(SET_COMMAND_LOCK)
@@ -278,10 +285,10 @@ func (d *Device) Data(data uint8) {
// Tx sends data to the display // Tx sends data to the display
func (d *Device) Tx(data []byte, isCommand bool) { func (d *Device) Tx(data []byte, isCommand bool) {
d.dcPin.Set(!isCommand) d.dcPin(!isCommand)
d.csPin.Low() d.csPin(false)
d.bus.Tx(data, nil) d.bus.Tx(data, nil)
d.csPin.High() d.csPin(true)
} }
// Size returns the current size of the display // Size returns the current size of the display