mcp23017: implement pin toggling

Also add an example for using multiple devices.
This commit is contained in:
Roger Peppe
2020-08-24 11:55:00 +01:00
committed by Ron Evans
parent edf9ba92be
commit ce5e443084
6 changed files with 146 additions and 0 deletions
+19
View File
@@ -154,6 +154,15 @@ func (d *Device) SetPins(pins, mask Pins) error {
return nil
}
// TogglePins inverts the values on all pins for
// which mask is high.
func (d *Device) TogglePins(mask Pins) error {
if mask == 0 {
return nil
}
return d.SetPins(^d.pins, mask)
}
// Pin returns a Pin representing the given pin number (from 0 to 15).
// Pin numbers from 0 to 7 represent port A pins 0 to 7.
// Pin numbers from 8 to 15 represent port B pins 0 to 7.
@@ -295,6 +304,11 @@ func (p Pin) Low() error {
return p.Set(false)
}
// Toggle inverts the value output on the pin.
func (p Pin) Toggle() error {
return p.dev.TogglePins(p.mask)
}
// Get returns the current value of the given pin.
func (p Pin) Get() (bool, error) {
// TODO this reads 2 registers when we could read just one.
@@ -357,6 +371,11 @@ func (p *Pins) Low(pin int) {
*p &^= pinMask(pin)
}
// Toggle inverts the value of the given pin.
func (p *Pins) Toggle(pin int) {
*p ^= pinMask(pin)
}
func pinMask(pin int) Pins {
return 1 << pin
}
+37
View File
@@ -50,6 +50,25 @@ func TestSetPins(t *testing.T) {
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)
@@ -108,6 +127,24 @@ func TestPinSetGet(t *testing.T) {
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)
+21
View File
@@ -117,6 +117,22 @@ func (devs Devices) SetPins(pins, mask PinSlice) error {
return nil
}
// TogglePins inverts the values on all pins for
// which mask is high.
func (devs Devices) TogglePins(mask PinSlice) error {
defaultMask := mask.extra()
for i, dev := range devs {
devMask := defaultMask
if i < len(mask) {
devMask = mask[i]
}
if err := dev.TogglePins(devMask); err != nil {
return err
}
}
return nil
}
// PinSlice represents an arbitrary nunber of pins, each element corresponding
// to the pins for one device. The value of the highest numbered pin in the
// slice is extended to all other pins beyond the end of the slice.
@@ -154,6 +170,11 @@ func (pins PinSlice) Low(pin int) {
pins[pin/PinCount].Low(pin % PinCount)
}
// Toggle inverts the value of the given pin.
func (pins PinSlice) Toggle(pin int) {
pins[pin/PinCount].Toggle(pin % PinCount)
}
// Ensure checks that pins has enough space to store
// at least length pins. If it does, it returns pins unchanged.
// Otherwise, it returns pins with elements appended as needed,
+22
View File
@@ -102,6 +102,26 @@ func TestDevicesSetPinsMask(t *testing.T) {
c.Assert(pins, qt.DeepEquals, PinSlice{0b01010011_10101101, 0b01010010_10101100})
}
func TestDevicesTogglePins(t *testing.T) {
c := qt.New(t)
bus := newBus(c)
bus.addDevice(0x20)
bus.addDevice(0x21)
devs, err := NewI2CDevices(bus, 0x20, 0x21)
c.Assert(err, qt.IsNil)
mask := make(PinSlice, 2)
mask.High(0)
mask.High(16)
err = devs.TogglePins(mask)
c.Assert(err, qt.IsNil)
pins := make(PinSlice, 2)
err = devs.GetPins(pins)
c.Assert(err, qt.IsNil)
c.Assert(pins, qt.DeepEquals, PinSlice{0b00000000_00000001, 0b00000000_00000001})
}
func TestDevicesSetGetModes(t *testing.T) {
c := qt.New(t)
bus := newBus(c)
@@ -163,4 +183,6 @@ func TestPinSlice(t *testing.T) {
c.Assert(pins.Get(16), qt.Equals, false)
pins.High(16)
c.Assert(pins.Get(16), qt.Equals, true)
pins.Toggle(16)
c.Assert(pins.Get(16), qt.Equals, false)
}