mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 10:38:41 +00:00
ce5e443084
Also add an example for using multiple devices.
211 lines
6.1 KiB
Go
211 lines
6.1 KiB
Go
package mcp23017
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
qt "github.com/frankban/quicktest"
|
|
)
|
|
|
|
func TestGetPins(t *testing.T) {
|
|
c := qt.New(t)
|
|
bus := newBus(c)
|
|
fdev := bus.addDevice(0x20)
|
|
fdev.Registers[rGPIO] = 0b10101100
|
|
fdev.Registers[rGPIO|portB] = 0b01010011
|
|
dev, err := NewI2C(bus, 0x20)
|
|
c.Assert(err, qt.IsNil)
|
|
pins, err := dev.GetPins()
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(pins, qt.Equals, Pins(0b01010011_10101100))
|
|
}
|
|
|
|
func TestSetPins(t *testing.T) {
|
|
c := qt.New(t)
|
|
bus := newBus(c)
|
|
fdev := bus.addDevice(0x20)
|
|
fdev.Registers[rGPIO] = 0b00001111
|
|
fdev.Registers[rGPIO|portB] = 0b11110000
|
|
dev, err := NewI2C(bus, 0x20)
|
|
c.Assert(err, qt.IsNil)
|
|
pins, err := dev.GetPins()
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(pins, qt.Equals, Pins(0b11110000_00001111))
|
|
|
|
err = dev.SetPins(0b01100000_00110000, 0b10101010_01010101)
|
|
c.Assert(err, qt.IsNil)
|
|
pins, err = dev.GetPins()
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(pins, qt.Equals, Pins(0b01110000_0001_1010))
|
|
|
|
// The logic uses the cached value of the pins rather than
|
|
// reading it from the registers each time.
|
|
fdev.Registers[rGPIO] = 0
|
|
fdev.Registers[rGPIO|portB] = 0
|
|
|
|
err = dev.SetPins(0b01000000_00110000, 0b01100000_00000000)
|
|
c.Assert(err, qt.IsNil)
|
|
pins, err = dev.GetPins()
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(pins, qt.Equals, Pins(0b01010000_00011010))
|
|
}
|
|
|
|
func TestTogglePins(t *testing.T) {
|
|
c := qt.New(t)
|
|
bus := newBus(c)
|
|
fdev := bus.addDevice(0x20)
|
|
fdev.Registers[rGPIO] = 0b00001111
|
|
fdev.Registers[rGPIO|portB] = 0b11110000
|
|
dev, err := NewI2C(bus, 0x20)
|
|
c.Assert(err, qt.IsNil)
|
|
pins, err := dev.GetPins()
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(pins, qt.Equals, Pins(0b11110000_00001111))
|
|
|
|
err = dev.TogglePins(0b10101010_01010101)
|
|
c.Assert(err, qt.IsNil)
|
|
pins, err = dev.GetPins()
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(pins, qt.Equals, Pins(0b01011010_01011010))
|
|
}
|
|
|
|
func TestSetGetModes(t *testing.T) {
|
|
c := qt.New(t)
|
|
bus := newBus(c)
|
|
fdev := bus.addDevice(0x20)
|
|
dev, err := NewI2C(bus, 0x20)
|
|
c.Assert(err, qt.IsNil)
|
|
// Calling SetModes with less items in than there are
|
|
// pins should use the last item for all the unspecified ones.
|
|
err = dev.SetModes([]PinMode{Input | Invert, Output})
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(fdev.Registers[rIODIR], qt.Equals, uint8(0b00000001))
|
|
c.Assert(fdev.Registers[rIOPOL], qt.Equals, uint8(0b00000001))
|
|
c.Assert(fdev.Registers[rGPPU], qt.Equals, uint8(0))
|
|
|
|
modes := make([]PinMode, 17)
|
|
err = dev.GetModes(modes)
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(modes[0], qt.Equals, Input|Invert)
|
|
for i, m := range modes[1:16] {
|
|
c.Assert(m, qt.Equals, Output, qt.Commentf("index %d", i))
|
|
}
|
|
c.Assert(modes[16], qt.Equals, PinMode(0))
|
|
|
|
// Using an empty slice should reset all the modes to the initial state.
|
|
err = dev.SetModes(nil)
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(fdev.Registers[rIODIR], qt.Equals, uint8(0b11111111))
|
|
c.Assert(fdev.Registers[rIOPOL], qt.Equals, uint8(0))
|
|
c.Assert(fdev.Registers[rGPPU], qt.Equals, uint8(0))
|
|
}
|
|
|
|
func TestPinSetGet(t *testing.T) {
|
|
c := qt.New(t)
|
|
bus := newBus(c)
|
|
fdev := bus.addDevice(0x20)
|
|
dev, err := NewI2C(bus, 0x20)
|
|
c.Assert(err, qt.IsNil)
|
|
pin := dev.Pin(1)
|
|
v, err := pin.Get()
|
|
c.Assert(err, qt.Equals, nil)
|
|
c.Assert(v, qt.Equals, false)
|
|
err = pin.Set(true)
|
|
c.Assert(err, qt.Equals, nil)
|
|
c.Assert(fdev.Registers[rGPIO], qt.Equals, uint8(0b10))
|
|
v, err = pin.Get()
|
|
c.Assert(err, qt.Equals, nil)
|
|
c.Assert(v, qt.Equals, true)
|
|
err = pin.Set(false)
|
|
c.Assert(err, qt.Equals, nil)
|
|
c.Assert(fdev.Registers[rGPIO], qt.Equals, uint8(0))
|
|
err = pin.High()
|
|
c.Assert(err, qt.Equals, nil)
|
|
c.Assert(fdev.Registers[rGPIO], qt.Equals, uint8(0b10))
|
|
err = pin.Low()
|
|
c.Assert(err, qt.Equals, nil)
|
|
c.Assert(fdev.Registers[rGPIO], qt.Equals, uint8(0))
|
|
}
|
|
|
|
func TestPinToggle(t *testing.T) {
|
|
c := qt.New(t)
|
|
bus := newBus(c)
|
|
fdev := bus.addDevice(0x20)
|
|
dev, err := NewI2C(bus, 0x20)
|
|
c.Assert(err, qt.IsNil)
|
|
pin := dev.Pin(1)
|
|
v, err := pin.Get()
|
|
c.Assert(err, qt.Equals, nil)
|
|
c.Assert(v, qt.Equals, false)
|
|
err = pin.Toggle()
|
|
c.Assert(err, qt.Equals, nil)
|
|
c.Assert(fdev.Registers[rGPIO], qt.Equals, uint8(0b10))
|
|
err = pin.Toggle()
|
|
c.Assert(err, qt.Equals, nil)
|
|
c.Assert(fdev.Registers[rGPIO], qt.Equals, uint8(0))
|
|
}
|
|
|
|
func TestPinMode(t *testing.T) {
|
|
c := qt.New(t)
|
|
bus := newBus(c)
|
|
fdev := bus.addDevice(0x20)
|
|
dev, err := NewI2C(bus, 0x20)
|
|
c.Assert(err, qt.IsNil)
|
|
pin := dev.Pin(1)
|
|
mode, err := pin.GetMode()
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(mode, qt.Equals, PinMode(0))
|
|
c.Assert(mode&Direction, qt.Equals, Input)
|
|
|
|
err = pin.SetMode(Input | Pullup | Invert)
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(fdev.Registers[rIODIR], qt.Equals, uint8(0b11111111))
|
|
c.Assert(fdev.Registers[rIOPOL], qt.Equals, uint8(0b10))
|
|
c.Assert(fdev.Registers[rGPPU], qt.Equals, uint8(0b10))
|
|
|
|
mode, err = pin.GetMode()
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(mode, qt.Equals, Input|Pullup|Invert)
|
|
|
|
// Set another pin to output.
|
|
err = dev.Pin(2).SetMode(Output)
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(fdev.Registers[rIODIR], qt.Equals, uint8(0b11111011))
|
|
c.Assert(fdev.Registers[rIOPOL], qt.Equals, uint8(0b10))
|
|
c.Assert(fdev.Registers[rGPPU], qt.Equals, uint8(0b10))
|
|
|
|
// Check that changing a pin in port B works too.
|
|
err = dev.Pin(8).SetMode(Output)
|
|
c.Assert(err, qt.IsNil)
|
|
c.Assert(fdev.Registers[rIODIR], qt.Equals, uint8(0b11111011))
|
|
c.Assert(fdev.Registers[rIODIR|portB], qt.Equals, uint8(0b11111110))
|
|
c.Assert(fdev.Registers[rIOPOL], qt.Equals, uint8(0b10))
|
|
c.Assert(fdev.Registers[rIOPOL|portB], qt.Equals, uint8(0))
|
|
c.Assert(fdev.Registers[rGPPU], qt.Equals, uint8(0b10))
|
|
c.Assert(fdev.Registers[rGPPU|portB], qt.Equals, uint8(0))
|
|
}
|
|
|
|
func TestPins(t *testing.T) {
|
|
c := qt.New(t)
|
|
var p Pins
|
|
p.Set(1, true)
|
|
c.Assert(p, qt.Equals, Pins(0b10))
|
|
c.Assert(p.Get(1), qt.Equals, true)
|
|
c.Assert(p.Get(0), qt.Equals, false)
|
|
c.Assert(p.Get(16), qt.Equals, false)
|
|
p.High(2)
|
|
c.Assert(p, qt.Equals, Pins(0b110))
|
|
p.Low(1)
|
|
c.Assert(p, qt.Equals, Pins(0b100))
|
|
}
|
|
|
|
func TestInitWithError(t *testing.T) {
|
|
c := qt.New(t)
|
|
bus := newBus(c)
|
|
fdev := bus.addDevice(0x20)
|
|
fdev.Err = fmt.Errorf("some error")
|
|
dev, err := NewI2C(bus, 0x20)
|
|
c.Assert(err, qt.ErrorMatches, `cannot initialize mcp23017 device at 0x20: some error`)
|
|
c.Assert(dev, qt.IsNil)
|
|
}
|