mirror of https://github.com/periph/devices
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.
111 lines
2.9 KiB
Go
111 lines
2.9 KiB
Go
// Copyright 2022 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.
|
|
|
|
// Package tca95xx provides an interface to the Texas Instruments TCA95 series
|
|
// of 8-bit I²C extenders.
|
|
//
|
|
// The following variants are supported:
|
|
//
|
|
// - PCA9536 - address: 0x41
|
|
// - TCA6408A - addresses: 0x20, 0x21
|
|
// - TCA6416 - addresses: 0x20, 0x21
|
|
// - TCA6416A - addresses: 0x20, 0x21
|
|
// - TCA9534 - addresses: 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
|
|
// - TCA9534A - addresses: 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
|
|
// - TCA9535 - addresses: 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
|
|
// - TCA9537 - address: 0x49
|
|
// - TCA9538 - address: 0x70, 0x71, 0x72, 0x73
|
|
// - TCA9539 - address: 0x74, 0x75, 0x76, 0x77
|
|
// - TCA9554 - addresses: 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
|
|
// - TCA9555 - addresses: 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
|
|
//
|
|
// Both gpio.Pin and conn.Conn interfaces are supported.
|
|
package tca95xx
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"periph.io/x/conn/v3"
|
|
"periph.io/x/conn/v3/gpio/gpioreg"
|
|
"periph.io/x/conn/v3/i2c"
|
|
)
|
|
|
|
// Dev is a TCA95xx series I²C extender with two ways to interact with the pins
|
|
// on the extender chip - as per pin gpio.Pin, or as per port conn.Conn
|
|
// connections.
|
|
type Dev struct {
|
|
Pins [][]Pin // Pins is a double array structured as: [port][pin].
|
|
Conns []conn.Conn // Conns uses the same [port] array structure.
|
|
}
|
|
|
|
// New returns a device object that communicates over I²C to the TCA95xx device
|
|
// family of I/O extenders.
|
|
func New(bus i2c.Bus, variant Variant, addr uint16) (*Dev, error) {
|
|
v, found := variants[variant]
|
|
if !found {
|
|
return nil, fmt.Errorf("%s: Unsupported variant", string(variant))
|
|
}
|
|
if v.isAddrInvalid(addr) {
|
|
return nil, fmt.Errorf("tca95xx: address not supported by device type %s", string(variant))
|
|
}
|
|
|
|
i2c := i2c.Dev{
|
|
Bus: bus,
|
|
Addr: addr,
|
|
}
|
|
|
|
devicename := string(variant) + "_" + strconv.FormatInt(int64(addr), 16)
|
|
ports := v.getPorts(&i2c, devicename)
|
|
|
|
// Map the register maps and ports into gpio.Pins.
|
|
pins := make([][]Pin, len(ports))
|
|
pinsLeft := v.pins
|
|
for i := range ports {
|
|
// pre-cache iodir
|
|
_, err := ports[i].iodir.readValue(false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if pinsLeft > 8 {
|
|
pins[i] = ports[i].pins(8)
|
|
pinsLeft -= 8
|
|
} else {
|
|
pins[i] = ports[i].pins(pinsLeft)
|
|
pinsLeft = 0
|
|
}
|
|
for j := range pins[i] {
|
|
pin := pins[i][j]
|
|
// Ignore registration failure.
|
|
_ = gpioreg.Register(pin)
|
|
}
|
|
}
|
|
|
|
// Convert to an array of Conn interfaces.
|
|
var conns []conn.Conn
|
|
for i := range ports {
|
|
conns = append(conns, ports[i])
|
|
}
|
|
|
|
d := Dev{
|
|
Pins: pins,
|
|
Conns: conns,
|
|
}
|
|
|
|
return &d, nil
|
|
}
|
|
|
|
// Close removes any registration to the device.
|
|
func (d *Dev) Close() error {
|
|
for _, port := range d.Pins {
|
|
for _, pin := range port {
|
|
err := gpioreg.Unregister(pin.Name())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|