You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
devices/pcf857x/pcf857x_test.go

217 lines
5.0 KiB
Go

// Copyright 2025 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
//
// This test assumes you have a PCF8575 and that the data pins are jumpered
//
// 0 => 8
// 1 => 9
// ...
// 7 => 15
package pcf857x
import (
"errors"
"strings"
"testing"
"periph.io/x/conn/v3/gpio"
"periph.io/x/conn/v3/gpio/gpioreg"
"periph.io/x/conn/v3/i2c/i2ctest"
)
func getDev(recordingName string, t *testing.T) (*Dev, error) {
// Create a new I2C IO extender
bus := i2ctest.Playback{Ops: recordingData[recordingName]}
extender, err := New(&bus, DefaultAddress, PCF8575)
if err != nil {
t.Error(err)
}
return extender, err
}
// Test basic dev and pin functions.
func TestBasic(t *testing.T) {
dev, err := getDev(t.Name(), t)
if err != nil {
return
}
t.Logf("dev=%#v", dev)
pin := dev.Pins[1]
t.Logf("pin=%#v", pin)
s := dev.String()
if len(s) == 0 {
t.Error("String() failure")
} //
if len(dev.Pins) != 16 {
t.Errorf("expected 16 GPIO pins. Found %d", len(dev.Pins))
}
e := pin.PWM(10, 10)
if !errors.Is(e, ErrNotImplmented) {
t.Errorf("PWM() expected ErrNotImplemented. Received %#v", e)
}
if pin.Halt() != nil {
t.Error("expected nil on pin.Halt()")
}
if pin.Name() != pin.String() {
t.Error("pin.Name()!=pin.String()")
}
if !strings.HasPrefix(pin.Name(), dev.String()) {
t.Errorf("Expected pin.Name()=%s to start with dev.String()=%s", pin.Name(), dev.String())
}
err = dev.Halt()
if err != nil {
t.Error(err)
}
}
// Test that the pins are registered in gpioreg as expected.
func TestGPIOReg(t *testing.T) {
dev, err := getDev(t.Name(), t)
if err != nil {
return
}
for ix := range dev.width {
p := dev.Pins[ix]
if p.Number() != ix {
t.Errorf("pin.Number() does not match ordinal position %d! Found %d", ix, p.Number())
}
pReg := gpioreg.ByName(p.Name())
if pReg == nil {
t.Errorf("pin %s not found in gpioreg", p.Name())
}
}
}
// This test goes through the pins from 0-7, and writes to them and then reads
// the value on pin+8 and verifies it's correct. Then, it reverses direction and
// writes to pin[8] and reads from pin[0].
func TestPinsSequentially(t *testing.T) {
dev, err := getDev(t.Name(), t)
if err != nil {
return
}
limit := dev.width >> 1
for ixOuter := range limit {
// Iterate over the lower 8 pins
for ixInner := range limit {
// Sequentially, set each pin to High if it's not the value of ix
p := dev.Pins[ixInner]
pRead := dev.Pins[ixInner+limit]
for direction := range 2 {
writeLevel := gpio.Level(ixInner != ixOuter)
err = p.Out(writeLevel)
if err != nil {
t.Error(err)
}
readVal := pRead.Read()
if readVal != writeLevel {
t.Errorf("wrote %t to pin[%d]. Expected same on pin[%d], found %t",
writeLevel,
p.Number(),
pRead.Number(),
readVal)
}
if direction == 0 {
// swap the direction so we're now going pin[8] => pin[0] and stay in
// the loop to repeat the test.
x := pRead
pRead = p
p = x
}
}
}
}
}
// This tests the group functionality.
func TestGroup(t *testing.T) {
dev, err := getDev(t.Name(), t)
if err != nil {
return
}
defer func() { _ = dev.Halt() }()
set1 := make([]int, dev.width>>1)
set2 := make([]int, dev.width>>1)
for ix := range len(set1) {
set1[ix] = ix
set2[ix] = ix + len(set1)
}
gr1, err := dev.Group(set1...)
if err != nil {
return
}
gr2, err := dev.Group(set2...)
if err != nil {
return
}
// Test the basic group functionality. Note that for group1, pinOffset==pin.Number, but
// for group2, pinOffset!=pin.Number
grTest := gr1
for range 2 {
for pinNumber, pin := range grTest.Pins() {
x := grTest.ByNumber(pin.Number())
if x == nil {
t.Errorf("group.ByNumber() returned nil for pin %d", pin.Number())
}
x = grTest.ByOffset(pinNumber)
if x == nil {
t.Errorf("group.ByOffset returned nil for pin number %d", pinNumber)
} else {
if x.Number() != pin.Number() {
t.Errorf("group.ByOffset() didn't return the expected pin. Expected %d, found %d", pin.Number(), x.Number())
}
}
x = grTest.ByName(pin.Name())
if x == nil || x.Name() != pin.Name() {
t.Error("group.ByName() didn't find a pin or returned the wrong pin!")
}
}
grTest = gr2
}
if len(gr1.String()) == 0 {
t.Error("group.String() didn't return a value")
}
// Test the read/write functionality.
limit := (1 << len(set1))
var read gpio.GPIOValue
for groupNumber := range 2 {
for val := range limit {
err = gr1.Out(gpio.GPIOValue(val), 0)
if err != nil {
t.Error(err)
}
read, err = gr2.Read(0)
if err != nil {
t.Error(err)
}
if read != gpio.GPIOValue(val) {
t.Errorf("Error writing/reading groups. Wrote %d on write group %s, read %d on read group%s", val, gr1, read, gr2)
}
}
if groupNumber == 0 {
x := gr1
gr1 = gr2
gr2 = x
}
}
err = gr1.Halt()
if err != nil {
t.Error(err)
}
err = gr2.Halt()
if err != nil {
t.Error(err)
}
}