From cf5ad2f280c9c515a8597c5a948b65a5bf65aa1a Mon Sep 17 00:00:00 2001 From: Daniel Esteban Date: Tue, 23 Jan 2024 00:28:22 +0100 Subject: [PATCH 1/2] Initial support for PCA9548A 8-channel I2C-bus --- examples/pca9548a/main.go | 67 ++++++++++++++++++++++++++++++ pca9548a/pca9685a.go | 87 +++++++++++++++++++++++++++++++++++++++ pca9548a/registers.go | 5 +++ smoketest.sh | 1 + 4 files changed, 160 insertions(+) create mode 100644 examples/pca9548a/main.go create mode 100644 pca9548a/pca9685a.go create mode 100644 pca9548a/registers.go diff --git a/examples/pca9548a/main.go b/examples/pca9548a/main.go new file mode 100644 index 000000000..f39eec456 --- /dev/null +++ b/examples/pca9548a/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "machine" + "time" + "tinygo.org/x/drivers/bme280" + "tinygo.org/x/drivers/pca9548a" +) + +func main() { + time.Sleep(5 * time.Second) + err := machine.I2C0.Configure(machine.I2CConfig{}) + if err != nil { + panic(err.Error()) + } + mux := pca9548a.New(machine.I2C0, pca9548a.Address) + if !mux.IsConnected() { + println("NO DEVICE DETECTED") + return + } + + port := mux.GetPortState() + println("GET PORT", port) + mux.DisablePort() + mux.SetPort(0) + port = mux.GetPortState() + println("GET PORT", port) + mux.SetPort(1) + port = mux.GetPortState() + println("GET PORT", port) + + tmpSensors := make([]bme280.Device, 2) + + for i := uint8(0); i < 2; i++ { + mux.SetPort(i) + time.Sleep(10 * time.Millisecond) + tmpSensors[i] = bme280.New(machine.I2C0) + tmpSensors[i].Configure() + + connected := tmpSensors[i].Connected() + if !connected { + println("\nBME280 Sensor not detected\n", i) + } else { + println("\nBME280 Sensor detected\n", i) + } + } + time.Sleep(10000 * time.Millisecond) + + for { + for i := uint8(0); i < 2; i++ { + mux.SetPort(i) + t, err := tmpSensors[i].ReadTemperature() + if err != nil { + println(i, "Error reading temperature") + } + println(i, "temperature", t) + + p, err := tmpSensors[i].ReadPressure() + if err != nil { + println("Error reading pressure") + } + println(i, "pressure", p) + + } + time.Sleep(40 * time.Millisecond) + } +} diff --git a/pca9548a/pca9685a.go b/pca9548a/pca9685a.go new file mode 100644 index 000000000..709b226da --- /dev/null +++ b/pca9548a/pca9685a.go @@ -0,0 +1,87 @@ +// Package pca9548a provides a driver for the PCA9548A 8-channel I2C-bus. +// +// Datasheet: +// https://www.nxp.com/docs/en/data-sheet/PCA9548A.pdf +package pca9548a // import "tinygo.org/x/drivers/pca9548a" + +import ( + "tinygo.org/x/drivers" +) + +// Device is a handle to the PCA9548A device given an address +type Device struct { + addr uint8 + bus drivers.I2C + buf [4]byte +} + +// New creates a new instance of a PCA9548A device. It performs +// no IO on the i2c bus. +func New(bus drivers.I2C, addr uint8) Device { + return Device{ + bus: bus, + addr: addr, + } +} + +// Connected returns whether a PCA9548A has been found. +// It does a "who am I" request and checks the response. +func (d *Device) IsConnected() bool { + d.SetPortState(0xA5) + response := d.GetPortState() + d.SetPortState(0x00) + return response == 0xA5 +} + +// SetPort enables the given port to send data. +func (d *Device) SetPort(portNumber byte) { + portValue := uint8(0) + if portNumber <= 7 { + portValue = 1 << portNumber + } + d.bus.Tx(uint16(d.addr), []byte{portValue}, nil) +} + +// GetPort gets the first port enabled. +func (d *Device) GetPort() byte { + portBits := d.GetPortState() + for i := uint8(0); i < 8; i++ { + if (portBits & (1 << i)) != 0x00 { + return i + } + } + return 99 +} + +// SetPortState set the states of all the ports at the same time, this could cause some issues if +// you enable two (or more) ports with the same devices at the same time. +func (d *Device) SetPortState(portBits byte) { + d.bus.Tx(uint16(d.addr), []byte{portBits}, nil) +} + +// GetPortState get the state of all the ports. +func (d *Device) GetPortState() byte { + portBits := make([]byte, 1) + d.bus.Tx(uint16(d.addr), nil, portBits) + return portBits[0] +} + +// EnablePort enables the given port without modifying any other, this could cause some issues if +// you enable two (or more) ports with the same devices at the same time. +func (d *Device) EnablePort(portNumber byte) { + if portNumber > 7 { + portNumber = 7 + } + + settings := d.GetPortState() + settings |= 1 << portNumber + + d.SetPortState(settings) +} + +// DisablePort disables the given port without modifying any other. +func (d *Device) DisablePort() byte { + portBits := make([]byte, 1) + d.bus.Tx(uint16(d.addr), nil, portBits) + return portBits[0] +} diff --git a/pca9548a/registers.go b/pca9548a/registers.go new file mode 100644 index 000000000..770cd7a51 --- /dev/null +++ b/pca9548a/registers.go @@ -0,0 +1,5 @@ +package pca9548a + +const ( + Address = 0x70 +) diff --git a/smoketest.sh b/smoketest.sh index e0a9203c4..ffbe2a386 100755 --- a/smoketest.sh +++ b/smoketest.sh @@ -135,3 +135,4 @@ tinygo build -size short -o ./build/test.hex -target=pico ./examples/ndir/main_n tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ndir/main_ndir.go tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ndir/main_ndir.go tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/mpu9150/main.go +tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/pca9548a/main.go From 25450cf8669b894ad5d9251b74e19e02a378b5fc Mon Sep 17 00:00:00 2001 From: Daniel Esteban Date: Wed, 24 Jan 2024 09:32:48 +0100 Subject: [PATCH 2/2] added InvalidPort const --- pca9548a/pca9685a.go | 2 +- pca9548a/registers.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pca9548a/pca9685a.go b/pca9548a/pca9685a.go index 709b226da..088e1b640 100644 --- a/pca9548a/pca9685a.go +++ b/pca9548a/pca9685a.go @@ -50,7 +50,7 @@ func (d *Device) GetPort() byte { return i } } - return 99 + return InvalidPort } // SetPortState set the states of all the ports at the same time, this could cause some issues if diff --git a/pca9548a/registers.go b/pca9548a/registers.go index 770cd7a51..91c1799dd 100644 --- a/pca9548a/registers.go +++ b/pca9548a/registers.go @@ -1,5 +1,6 @@ package pca9548a const ( - Address = 0x70 + Address = 0x70 + InvalidPort = 0xff )