diff --git a/src/devices/Device-Index.md b/src/devices/Device-Index.md
index 0219676212..3210c03601 100755
--- a/src/devices/Device-Index.md
+++ b/src/devices/Device-Index.md
@@ -113,6 +113,7 @@
* [STUSB4500 - Autonomous USB-C PD controller for Power Sinks / UFP](StUsb4500/README.md)
* [System.Device.Model - attributes for device bindings](System.Device.Model/README.md)
* [TCS3472x Sensors](Tcs3472x/README.md)
+* [TCA954X Multiplexer](Tca954x/README.md)
* [TLC1543 - 10-bit ADC with 11 input channels](Tlc1543/README.md)
* [TM1637 - Segment Display](Tm1637/README.md)
* [TSL256x - Illuminance sensor](Tsl256x/README.md)
diff --git a/src/devices/Pca95x4/README.md b/src/devices/Pca95x4/README.md
index 976f3b6283..3d67b2a485 100644
--- a/src/devices/Pca95x4/README.md
+++ b/src/devices/Pca95x4/README.md
@@ -1,6 +1,6 @@
# Pca95x4 - I2C GPIO Expander
-The PCA95x4 provides 8 bits of General Purpose parallel Input/Output (GPIO) expansion for I2C-bus applications.
+The PCA95x4 provides 8 bits of General Purpose parallel Input/Output (GPIO) expansion for I2C-bus applications. Not to be confused with the PCA954x, which is a group of I2C bus multiplexers.
## Documentation
diff --git a/src/devices/README.md b/src/devices/README.md
index ad9ad556ff..a4097de8e3 100755
--- a/src/devices/README.md
+++ b/src/devices/README.md
@@ -211,6 +211,7 @@ Our vision: the majority of .NET bindings are written completely in .NET languag
* [Mcp23xxx - I/O Expander device family](Mcp23xxx/README.md)
* [NXP/TI PCx857x](Pcx857x/README.md)
* [Pca95x4 - I2C GPIO Expander](Pca95x4/README.md)
+* [TCA9548A - TCA9548A Low-Voltage 8-Channel I2C Switch with Reset](Tca954x/README.md)
### CAN BUS libraries/modules
diff --git a/src/devices/Tca954x/MultiplexerChannel.cs b/src/devices/Tca954x/MultiplexerChannel.cs
new file mode 100644
index 0000000000..adf2c2c36e
--- /dev/null
+++ b/src/devices/Tca954x/MultiplexerChannel.cs
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+namespace Iot.Device.Tca954x
+{
+ ///
+ /// Available channels
+ ///
+ [Flags]
+ public enum MultiplexerChannel : byte
+ {
+ ///
+ /// No channel is selected
+ ///
+ None = 0,
+
+ ///
+ /// Channel 0 Byte (2^0 = 1)
+ ///
+ Channel0 = 0x01,
+
+ ///
+ /// Channel 1 Byte (2^1 = 2)
+ ///
+ Channel1 = 0x02,
+
+ ///
+ /// Channel 2 Byte (2^2 = 4)
+ ///
+ Channel2 = 0x04,
+
+ ///
+ /// Channel 3 Byte (2^3 = 8)
+ ///
+ Channel3 = 0x08,
+
+ ///
+ /// Channel 4 Byte (2^4 = 16)
+ ///
+ Channel4 = 0x10,
+
+ ///
+ /// Channel 5 Byte (2^5 = 32)
+ ///
+ Channel5 = 0x20,
+
+ ///
+ /// Channel 6 Byte (2^6 = 64)
+ ///
+ Channel6 = 0x40,
+
+ ///
+ /// Channel 7 Byte (2^7 = 128)
+ ///
+ Channel7 = 0x80
+ }
+
+}
diff --git a/src/devices/Tca954x/PossibleMuxAddress.png b/src/devices/Tca954x/PossibleMuxAddress.png
new file mode 100644
index 0000000000..b1c9027d46
Binary files /dev/null and b/src/devices/Tca954x/PossibleMuxAddress.png differ
diff --git a/src/devices/Tca954x/README.md b/src/devices/Tca954x/README.md
new file mode 100644
index 0000000000..2c3201d4fd
--- /dev/null
+++ b/src/devices/Tca954x/README.md
@@ -0,0 +1,115 @@
+# TCA954X - TCA954X Low-Voltage Multi-Channel I2C Switch with Reset
+
+The TCA954X/PCA954X group of devices is a set of I2C switches. Several types are available, with 2, 4 or 8 channels, and different voltage specifications. The first letter is sometimes also "P". Not to be confused with PCA95x4, which is a set of GPIO expanders.
+
+The TCA9548A device has eight bidirectional translating switches that can be controlled through the I2C bus. The SCL/SDA upstream pair fans out to eight downstream pairs, or channels.
+
+All operations for basic usage has been developed. If needed, RESET operation can also be implemented.
+
+## Documentation
+
+![TCA9548A](./TCA9548A.jpg)
+
+TCA9548A [datasheet](https://www.ti.com/lit/ds/symlink/tca9548a.pdf)
+
+You will find this device as ["Adafruit TCA9548A 1-to-8 I2C Multiplexer Breakout"](https://learn.adafruit.com/adafruit-tca9548a-1-to-8-i2c-multiplexer-breakout)
+
+A list of [different variants](https://www.ti.com/interface/i2c/switches-and-multiplexers/products.html?keyMatch=TCA9548) is available on the Texas Instruments Website.
+
+## Usage
+
+Create a ```Tca9548A``` class and pass the I2C device. The default I2C address is provided in the class.
+
+```csharp
+ Console.WriteLine("Hello TCA9548A!");
+ var bus = I2cBus.Create(1);
+ Tca9548A tca9548a = new Tca9548A(bus.CreateDevice(Tca9548A.DefaultI2cAddress), bus);
+
+ // Get all connected I2C interfaces
+ foreach (var channelBuses in tca9548a)
+ {
+ var deviceAddress = ((Tca9548AChannelBus)channelBuses).PerformBusScan();
+ foreach (var device in deviceAddress)
+ {
+ if (device == Bno055Sensor.DefaultI2cAddress || device == Bno055Sensor.SecondI2cAddress)
+ {
+ Bno055Sensor bno055Sensor = new Bno055Sensor(channelBuses.CreateDevice(device));
+ Console.WriteLine($"Id: {bno055Sensor.Info.ChipId}, AccId: {bno055Sensor.Info.AcceleratorId}, GyroId: {bno055Sensor.Info.GyroscopeId}, MagId: {bno055Sensor.Info.MagnetometerId}");
+ Console.WriteLine($"Firmware version: {bno055Sensor.Info.FirmwareVersion}, Bootloader: {bno055Sensor.Info.BootloaderVersion}");
+ Console.WriteLine($"Temperature source: {bno055Sensor.TemperatureSource}, Operation mode: {bno055Sensor.OperationMode}, Units: {bno055Sensor.Units}");
+ Console.WriteLine($"Powermode: {bno055Sensor.PowerMode}");
+ var calibrationStatus = bno055Sensor.GetCalibrationStatus();
+ Console.WriteLine($"Calibration Status : {calibrationStatus}");
+ var magneto = bno055Sensor.Magnetometer;
+ Console.WriteLine($"Magnetometer X: {magneto.X} Y: {magneto.Y} Z: {magneto.Z}");
+ var gyro = bno055Sensor.Gyroscope;
+ Console.WriteLine($"Gyroscope X: {gyro.X} Y: {gyro.Y} Z: {gyro.Z}");
+ var accele = bno055Sensor.Accelerometer;
+ Console.WriteLine($"Acceleration X: {accele.X} Y: {accele.Y} Z: {accele.Z}");
+ var orien = bno055Sensor.Orientation;
+ Console.WriteLine($"Orientation Heading: {orien.X} Roll: {orien.Y} Pitch: {orien.Z}");
+ var line = bno055Sensor.LinearAcceleration;
+ Console.WriteLine($"Linear acceleration X: {line.X} Y: {line.Y} Z: {line.Z}");
+ var gravity = bno055Sensor.Gravity;
+ Console.WriteLine($"Gravity X: {gravity.X} Y: {gravity.Y} Z: {gravity.Z}");
+ var qua = bno055Sensor.Quaternion;
+ Console.WriteLine($"Quaternion X: {qua.X} Y: {qua.Y} Z: {qua.Z} W: {qua.W}");
+ var temp = bno055Sensor.Temperature.DegreesCelsius;
+ Console.WriteLine($"Temperature: {temp} °C");
+ }
+ else if (device == Bmp180.DefaultI2cAddress)
+ {
+ using Bmp180 i2cBmp280 = new(channelBuses.CreateDevice(device));
+ // set samplings
+ i2cBmp280.SetSampling(Sampling.Standard);
+ // read values
+ Temperature tempValue = i2cBmp280.ReadTemperature();
+ Console.WriteLine($"Temperature: {tempValue.DegreesCelsius:0.#}\u00B0C");
+ Pressure preValue = i2cBmp280.ReadPressure();
+ Console.WriteLine($"Pressure: {preValue.Hectopascals:0.##}hPa");
+
+ // Note that if you already have the pressure value and the temperature, you could also calculate altitude by
+ // calling WeatherHelper.CalculateAltitude(preValue, Pressure.MeanSeaLevel, tempValue) which would be more performant.
+ Length altValue = i2cBmp280.ReadAltitude(WeatherHelper.MeanSeaLevel);
+
+ Console.WriteLine($"Altitude: {altValue:0.##}m");
+ Thread.Sleep(1000);
+
+ // set higher sampling
+ i2cBmp280.SetSampling(Sampling.UltraLowPower);
+
+ // read values
+ tempValue = i2cBmp280.ReadTemperature();
+ Console.WriteLine($"Temperature: {tempValue.DegreesCelsius:0.#}\u00B0C");
+ preValue = i2cBmp280.ReadPressure();
+ Console.WriteLine($"Pressure: {preValue.Hectopascals:0.##}hPa");
+
+ // Note that if you already have the pressure value and the temperature, you could also calculate altitude by
+ // calling WeatherHelper.CalculateAltitude(preValue, Pressure.MeanSeaLevel, tempValue) which would be more performant.
+ altValue = i2cBmp280.ReadAltitude(WeatherHelper.MeanSeaLevel);
+ Console.WriteLine($"Altitude: {altValue:0.##}m");
+ }
+
+ Thread.Sleep(1000);
+ }
+
+ }
+```
+
+### Sample wiring
+
+**Important** to understand:
+If you are getting lower data rate from sensor connected via Multiplexer on Raspberry Pi, you need to adjust the bus speed.
+
+This example uses the I2C bus 1 with GPIO 2 and 3 on raspberry pi and gathers data from to BNO055 sensors and 4 BMP180 sensors over TCA9548A Mux
+
+![Wiring sample](TCA9548A_Connections.png)
+
+## Possible TCA9548A Addresses
+
+![Possible Addresses](PossibleMuxAddress.png)
+
+## TCA9546A - Low Voltage 4-Channel I2C
+
+TCA9546A [datasheet](https://www.ti.com/lit/ds/symlink/tca9546a.pdf)
+You can use the same class to control the 4-Channel Multiplexer also.
diff --git a/src/devices/Tca954x/TCA9548A.jpg b/src/devices/Tca954x/TCA9548A.jpg
new file mode 100644
index 0000000000..32759d61c0
Binary files /dev/null and b/src/devices/Tca954x/TCA9548A.jpg differ
diff --git a/src/devices/Tca954x/TCA9548A_Connections.png b/src/devices/Tca954x/TCA9548A_Connections.png
new file mode 100644
index 0000000000..cdafee02fa
Binary files /dev/null and b/src/devices/Tca954x/TCA9548A_Connections.png differ
diff --git a/src/devices/Tca954x/TCA9548A_usage.fzz b/src/devices/Tca954x/TCA9548A_usage.fzz
new file mode 100644
index 0000000000..fbf73630d4
Binary files /dev/null and b/src/devices/Tca954x/TCA9548A_usage.fzz differ
diff --git a/src/devices/Tca954x/Tca9548A.cs b/src/devices/Tca954x/Tca9548A.cs
new file mode 100644
index 0000000000..af48149575
--- /dev/null
+++ b/src/devices/Tca954x/Tca9548A.cs
@@ -0,0 +1,197 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Device.I2c;
+using System.Device.Model;
+using System.IO;
+
+namespace Iot.Device.Tca954x
+{
+ ///
+ /// Tca9548A - 8-Channel I2C Switch/Multiplexer
+ ///
+ [Interface("Tca9548A - 8-Channel I2C Switch/Multiplexer")]
+ public class Tca9548A : IList, IDisposable
+ {
+ private readonly bool _shouldDispose;
+ private readonly List _channelBuses = new List();
+ private MultiplexerChannel? _activeChannels;
+
+ ///
+ /// The default I2C Address, page 15 of the main documentation
+ /// https://www.ti.com/lit/ds/symlink/tca9548a.pdf
+ ///
+ public const byte DefaultI2cAddress = 0x70;
+
+ ///
+ /// Array of all possible Multiplexer Channels
+ ///
+ private static readonly MultiplexerChannel[] DeviceChannels = new MultiplexerChannel[]
+ {
+ MultiplexerChannel.Channel0, MultiplexerChannel.Channel1, MultiplexerChannel.Channel2, MultiplexerChannel.Channel3, MultiplexerChannel.Channel4,
+ MultiplexerChannel.Channel5, MultiplexerChannel.Channel6, MultiplexerChannel.Channel7
+ };
+
+ private I2cDevice _i2CDevice;
+
+ ///
+ /// Creates a Multiplexer Instance
+ ///
+ /// The I2C Device of the Mux itself
+ /// The bus the mux is connected to
+ /// true to dispose the I2C device at dispose
+ /// Exception thrown if I2C device is null
+ public Tca9548A(I2cDevice i2cDevice, I2cBus mainBus, bool shouldDispose = true)
+ {
+ _i2CDevice = i2cDevice ?? throw new ArgumentNullException(nameof(i2cDevice));
+ _shouldDispose = shouldDispose;
+ _activeChannels = null; // We don't know the state of the multiplexer
+ foreach (var channel in DeviceChannels)
+ {
+ _channelBuses.Add(new Tca9548AChannelBus(this, mainBus, channel));
+ }
+ }
+
+ ///
+ /// Gets Channel busses of the multiplexer
+ ///
+ /// channel number
+ ///
+ public I2cBus this[int index] => _channelBuses[index];
+
+ ///
+ /// Select a group of multiplexer channels.
+ ///
+ /// The channels to select
+ ///
+ /// In most cases, a single channel will be selected at a time, but it is possible to write to several channels at once. Reading
+ /// from multiple channels at once will result in undefined behavior.
+ ///
+ public void SelectChannel(MultiplexerChannel multiplexChannels)
+ {
+ if (TryGetSelectedChannel(out var channel) && channel != multiplexChannels)
+ {
+ _i2CDevice.WriteByte(Convert.ToByte(multiplexChannels));
+ _activeChannels = multiplexChannels;
+ }
+ }
+
+ ///
+ /// Try getting the selected channel on Multiplexer
+ ///
+ /// selected Multiplexer Channel
+ /// true if able to retrieve selected channel
+ public bool TryGetSelectedChannel(out MultiplexerChannel selectedChannel)
+ {
+ try
+ {
+ if (_activeChannels.HasValue)
+ {
+ selectedChannel = _activeChannels.Value;
+ return true;
+ }
+
+ var channel = _i2CDevice.ReadByte();
+ if (Enum.IsDefined(typeof(MultiplexerChannel), channel))
+ {
+ selectedChannel = (MultiplexerChannel)channel;
+ return true;
+ }
+ else
+ {
+ selectedChannel = MultiplexerChannel.Channel0;
+ return false;
+ }
+ }
+ catch (Exception)
+ {
+ selectedChannel = MultiplexerChannel.Channel0;
+ return false;
+ }
+ }
+
+ ///
+ public void Dispose()
+ {
+ if (_shouldDispose)
+ {
+ _i2CDevice?.Dispose();
+ }
+
+ _i2CDevice = null!;
+ }
+
+ ///
+ public int Count => _channelBuses.Count;
+
+ ///
+ public bool IsReadOnly => true;
+
+ I2cBus IList.this[int index] { get => _channelBuses[index]; set => _channelBuses[index] = (Tca9548AChannelBus)value; }
+
+ ///
+ public int IndexOf(I2cBus item)
+ {
+ return _channelBuses.IndexOf((Tca9548AChannelBus)item);
+ }
+
+ ///
+ public void Insert(int index, I2cBus item)
+ {
+ _channelBuses.Insert(index, (Tca9548AChannelBus)item);
+ }
+
+ ///
+ public void RemoveAt(int index)
+ {
+ _channelBuses.RemoveAt(index);
+ }
+
+ ///
+ public void Add(I2cBus item)
+ {
+ _channelBuses.Add((Tca9548AChannelBus)item);
+ }
+
+ ///
+ public void Clear()
+ {
+ _channelBuses.Clear();
+ }
+
+ ///
+ public bool Contains(I2cBus item)
+ {
+ return _channelBuses.Contains((Tca9548AChannelBus)item);
+ }
+
+ ///
+ public void CopyTo(I2cBus[] array, int arrayIndex)
+ {
+ _channelBuses.CopyTo((Tca9548AChannelBus[])array, arrayIndex);
+
+ }
+
+ ///
+ public bool Remove(I2cBus item)
+ {
+ return _channelBuses.Remove((Tca9548AChannelBus)item);
+ }
+
+ ///
+ public IEnumerator GetEnumerator()
+ {
+ return _channelBuses.GetEnumerator();
+ }
+
+ ///
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+
+}
diff --git a/src/devices/Tca954x/Tca9548AChannelBus.cs b/src/devices/Tca954x/Tca9548AChannelBus.cs
new file mode 100644
index 0000000000..3c360d28f9
--- /dev/null
+++ b/src/devices/Tca954x/Tca9548AChannelBus.cs
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Device.I2c;
+using Iot.Device.Board;
+
+namespace Iot.Device.Tca954x
+{
+ ///
+ /// I2C BUs of TCA9548A channel
+ ///
+ public class Tca9548AChannelBus : I2cBus
+ {
+ private readonly I2cBus _channelBus;
+ private readonly Tca9548A _tca9548A;
+ private readonly MultiplexerChannel _tcaChannel;
+
+ ///
+ /// Creates new I2C bus Instance for multiplexer channel
+ ///
+ /// TCA9548A multiplexer
+ /// Main Bus
+ /// Selected Channel on Multiplexer
+ internal Tca9548AChannelBus(Tca9548A tca9548A, I2cBus mainBus, MultiplexerChannel channels)
+ {
+ _tca9548A = tca9548A;
+ _tcaChannel = channels;
+ _channelBus = mainBus;
+ }
+
+ private void SelectDeviceChannel() => _tca9548A.SelectChannel(_tcaChannel);
+
+ ///
+ /// Creates I2C device
+ ///
+ /// Device address related with the device to create.
+ /// I2cDevice instance.
+ public override I2cDevice CreateDevice(int deviceAddress)
+ {
+ SelectDeviceChannel();
+ return new Tca9548AI2cDevice(_tca9548A, _tcaChannel, _channelBus.CreateDevice(deviceAddress));
+ }
+
+ ///
+ /// Returns all the connected device on selected channel
+ ///
+ /// The list of used addresses
+ public List PerformBusScan()
+ {
+ SelectDeviceChannel();
+ return _channelBus.PerformBusScan();
+ }
+
+ ///
+ /// Removes I2C device.
+ ///
+ /// Device address to remove.m
+ public override void RemoveDevice(int deviceAddress)
+ {
+ SelectDeviceChannel();
+ _channelBus.RemoveDevice(deviceAddress);
+ }
+
+ }
+}
diff --git a/src/devices/Tca954x/Tca9548ADevice.cs b/src/devices/Tca954x/Tca9548ADevice.cs
new file mode 100644
index 0000000000..48b336a9b5
--- /dev/null
+++ b/src/devices/Tca954x/Tca9548ADevice.cs
@@ -0,0 +1,105 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Device.I2c;
+
+namespace Iot.Device.Tca954x
+{
+ internal class Tca9548AI2cDevice : I2cDevice
+ {
+ private readonly I2cDevice _channelDevice;
+ private readonly Tca9548A _tca9548A;
+ private readonly MultiplexerChannel _tcaChannel;
+
+ ///
+ /// The connection settings of a device on an I2C bus.
+ ///
+ public override I2cConnectionSettings ConnectionSettings => _channelDevice.ConnectionSettings;
+
+ ///
+ /// Initializes a new instance of the class on the of TCA mux that will use the specified settings to communicate with the I2C device.
+ ///
+ /// Instance on TCA9548A device
+ /// Channel on which device is
+ /// I2C device (from the parent bus)
+ internal Tca9548AI2cDevice(Tca9548A tca9548A, MultiplexerChannel tcaChannel, I2cDevice device)
+ {
+ _tca9548A = tca9548A;
+ _tcaChannel = tcaChannel;
+ _channelDevice = device;
+ }
+
+ private void SelectDeviceChannel() => _tca9548A.SelectChannel(_tcaChannel);
+
+ ///
+ /// Reads data from the I2C device.
+ ///
+ ///
+ /// The buffer to read the data from the I2C device.
+ /// The length of the buffer determines how much data to read from the I2C device.
+ ///
+ public override void Read(Span buffer)
+ {
+ SelectDeviceChannel();
+ _channelDevice.Read(buffer);
+ }
+
+ ///
+ /// Reads a byte from the I2C device.
+ ///
+ /// A byte read from the I2C device.
+ public override byte ReadByte()
+ {
+ SelectDeviceChannel();
+ return _channelDevice.ReadByte();
+ }
+
+ ///
+ /// Writes data to the I2C device.
+ ///
+ ///
+ /// The buffer that contains the data to be written to the I2C device.
+ /// The data should not include the I2C device address.
+ ///
+ public override void Write(ReadOnlySpan buffer)
+ {
+ SelectDeviceChannel();
+ _channelDevice.Write(buffer);
+ }
+
+ ///
+ /// Writes a byte to the I2C device.
+ ///
+ /// The byte to be written to the I2C device.
+ public override void WriteByte(byte value)
+ {
+ SelectDeviceChannel();
+ _channelDevice.WriteByte(value);
+ }
+
+ ///
+ /// Performs an atomic operation to write data to and then read data from the I2C bus on which the device is connected,
+ /// and sends a restart condition between the write and read operations.
+ ///
+ ///
+ /// The buffer that contains the data to be written to the I2C device.
+ /// The data should not include the I2C device address.
+ ///
+ /// The buffer to read the data from the I2C device.
+ /// The length of the buffer determines how much data to read from the I2C device.
+ ///
+ public override void WriteRead(ReadOnlySpan writeBuffer, Span readBuffer)
+ {
+ SelectDeviceChannel();
+ _channelDevice.WriteRead(writeBuffer, readBuffer);
+ }
+
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ _channelDevice.Dispose();
+ base.Dispose(disposing);
+ }
+ }
+}
diff --git a/src/devices/Tca954x/Tca9548a.sln b/src/devices/Tca954x/Tca9548a.sln
new file mode 100644
index 0000000000..288dbb942b
--- /dev/null
+++ b/src/devices/Tca954x/Tca9548a.sln
@@ -0,0 +1,51 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.3.32519.111
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tca954x", "Tca954x.csproj", "{28EDCECC-F951-4004-8213-FAF1ACD3DFD2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tca9548a.sample", "samples\Tca9548a.sample.csproj", "{A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Debug|x64.Build.0 = Debug|Any CPU
+ {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Debug|x86.Build.0 = Debug|Any CPU
+ {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Release|x64.ActiveCfg = Release|Any CPU
+ {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Release|x64.Build.0 = Release|Any CPU
+ {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Release|x86.ActiveCfg = Release|Any CPU
+ {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Release|x86.Build.0 = Release|Any CPU
+ {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Debug|x64.Build.0 = Debug|Any CPU
+ {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Debug|x86.Build.0 = Debug|Any CPU
+ {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Release|x64.ActiveCfg = Release|Any CPU
+ {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Release|x64.Build.0 = Release|Any CPU
+ {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Release|x86.ActiveCfg = Release|Any CPU
+ {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {7B84C9EE-D5AF-4ABC-ACEE-2F126D8738EA}
+ EndGlobalSection
+EndGlobal
diff --git a/src/devices/Tca954x/Tca954x.csproj b/src/devices/Tca954x/Tca954x.csproj
new file mode 100644
index 0000000000..fed1b33c01
--- /dev/null
+++ b/src/devices/Tca954x/Tca954x.csproj
@@ -0,0 +1,12 @@
+
+
+
+ $(DefaultBindingTfms)
+ false
+
+
+
+
+
+
+
diff --git a/src/devices/Tca954x/category.txt b/src/devices/Tca954x/category.txt
new file mode 100644
index 0000000000..120d076e1c
--- /dev/null
+++ b/src/devices/Tca954x/category.txt
@@ -0,0 +1 @@
+Multiplexer
\ No newline at end of file
diff --git a/src/devices/Tca954x/samples/Program.cs b/src/devices/Tca954x/samples/Program.cs
new file mode 100644
index 0000000000..407413b4ec
--- /dev/null
+++ b/src/devices/Tca954x/samples/Program.cs
@@ -0,0 +1,101 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Threading;
+using System.Device.I2c;
+using Iot.Device.Tca954x;
+using Iot.Device.Bno055;
+using Iot.Device.Bmp180;
+using UnitsNet;
+using Iot.Device.Common;
+using Iot.Device.Board;
+
+namespace Tca9548a.Sample
+{
+ ///
+ /// Sample Test Class
+ ///
+ public static class Program
+ {
+ ///
+ /// Program Entry Point
+ ///
+ public static void Main()
+ {
+ Console.WriteLine("Hello TCA9548A!");
+ var bus = I2cBus.Create(1);
+ Tca9548A tca9548a = new Tca9548A(bus.CreateDevice(Tca9548A.DefaultI2cAddress), bus);
+
+ // Get all connected I2C interfaces
+ foreach (var channelBuses in tca9548a)
+ {
+ var deviceAddress = ((Tca9548AChannelBus)channelBuses).PerformBusScan();
+ foreach (var device in deviceAddress)
+ {
+ if (device == Bno055Sensor.DefaultI2cAddress || device == Bno055Sensor.SecondI2cAddress)
+ {
+ Bno055Sensor bno055Sensor = new Bno055Sensor(channelBuses.CreateDevice(device));
+ Console.WriteLine($"Id: {bno055Sensor.Info.ChipId}, AccId: {bno055Sensor.Info.AcceleratorId}, GyroId: {bno055Sensor.Info.GyroscopeId}, MagId: {bno055Sensor.Info.MagnetometerId}");
+ Console.WriteLine($"Firmware version: {bno055Sensor.Info.FirmwareVersion}, Bootloader: {bno055Sensor.Info.BootloaderVersion}");
+ Console.WriteLine($"Temperature source: {bno055Sensor.TemperatureSource}, Operation mode: {bno055Sensor.OperationMode}, Units: {bno055Sensor.Units}");
+ Console.WriteLine($"Powermode: {bno055Sensor.PowerMode}");
+ var calibrationStatus = bno055Sensor.GetCalibrationStatus();
+ Console.WriteLine($"Calibration Status : {calibrationStatus}");
+ var magneto = bno055Sensor.Magnetometer;
+ Console.WriteLine($"Magnetometer X: {magneto.X} Y: {magneto.Y} Z: {magneto.Z}");
+ var gyro = bno055Sensor.Gyroscope;
+ Console.WriteLine($"Gyroscope X: {gyro.X} Y: {gyro.Y} Z: {gyro.Z}");
+ var accele = bno055Sensor.Accelerometer;
+ Console.WriteLine($"Acceleration X: {accele.X} Y: {accele.Y} Z: {accele.Z}");
+ var orien = bno055Sensor.Orientation;
+ Console.WriteLine($"Orientation Heading: {orien.X} Roll: {orien.Y} Pitch: {orien.Z}");
+ var line = bno055Sensor.LinearAcceleration;
+ Console.WriteLine($"Linear acceleration X: {line.X} Y: {line.Y} Z: {line.Z}");
+ var gravity = bno055Sensor.Gravity;
+ Console.WriteLine($"Gravity X: {gravity.X} Y: {gravity.Y} Z: {gravity.Z}");
+ var qua = bno055Sensor.Quaternion;
+ Console.WriteLine($"Quaternion X: {qua.X} Y: {qua.Y} Z: {qua.Z} W: {qua.W}");
+ var temp = bno055Sensor.Temperature.DegreesCelsius;
+ Console.WriteLine($"Temperature: {temp} °C");
+ }
+ else if (device == Bmp180.DefaultI2cAddress)
+ {
+ using Bmp180 i2cBmp280 = new(channelBuses.CreateDevice(device));
+ // set samplings
+ i2cBmp280.SetSampling(Sampling.Standard);
+ // read values
+ Temperature tempValue = i2cBmp280.ReadTemperature();
+ Console.WriteLine($"Temperature: {tempValue.DegreesCelsius:0.#}\u00B0C");
+ Pressure preValue = i2cBmp280.ReadPressure();
+ Console.WriteLine($"Pressure: {preValue.Hectopascals:0.##}hPa");
+
+ // Note that if you already have the pressure value and the temperature, you could also calculate altitude by
+ // calling WeatherHelper.CalculateAltitude(preValue, Pressure.MeanSeaLevel, tempValue) which would be more performant.
+ Length altValue = i2cBmp280.ReadAltitude(WeatherHelper.MeanSeaLevel);
+
+ Console.WriteLine($"Altitude: {altValue:0.##}m");
+ Thread.Sleep(1000);
+
+ // set higher sampling
+ i2cBmp280.SetSampling(Sampling.UltraLowPower);
+
+ // read values
+ tempValue = i2cBmp280.ReadTemperature();
+ Console.WriteLine($"Temperature: {tempValue.DegreesCelsius:0.#}\u00B0C");
+ preValue = i2cBmp280.ReadPressure();
+ Console.WriteLine($"Pressure: {preValue.Hectopascals:0.##}hPa");
+
+ // Note that if you already have the pressure value and the temperature, you could also calculate altitude by
+ // calling WeatherHelper.CalculateAltitude(preValue, Pressure.MeanSeaLevel, tempValue) which would be more performant.
+ altValue = i2cBmp280.ReadAltitude(WeatherHelper.MeanSeaLevel);
+ Console.WriteLine($"Altitude: {altValue:0.##}m");
+ }
+
+ Thread.Sleep(1000);
+ }
+
+ }
+ }
+ }
+}
diff --git a/src/devices/Tca954x/samples/Tca9548a.sample.csproj b/src/devices/Tca954x/samples/Tca9548a.sample.csproj
new file mode 100644
index 0000000000..e39417d491
--- /dev/null
+++ b/src/devices/Tca954x/samples/Tca9548a.sample.csproj
@@ -0,0 +1,12 @@
+
+
+
+ Exe
+ $(DefaultSampleTfms)
+
+
+
+
+
+
+