Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Tca955x device family #2374

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/devices/Tca955x/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Tca955x - I/O Expander device family

## Summary

The TCA955X device family provides 8/16-bit, general purpose I/O expansion for I2C. The devices can be configured with polariy invertion and interrupts.

## Device Family

The family contains the TCA9554 (8-bit) and the TCA9555 (16-bit) device. Both devices are compatible with 400kHz Bus speed.

- **TCA9554**: [datasheet](https://www.ti.com/lit/ds/symlink/tca9554.pdf)
- **TCA9555**: [datasheet](https://www.ti.com/lit/ds/symlink/tca9555.pdf)

## Interrupt support

The `Tca955x` has one interrupt pin. The corresponding pins need to be connected to a master GPIO controller for this feature to work. You can use a GPIO controller around the MCP device to handle everything for you:
```csharp
// Gpio controller from parent device (eg. Raspberry Pi)
_gpioController = new GpioController();
_i2c = I2cDevice.Create(new I2cConnectionSettings(1, 0x20));
// The "Interrupt" line of the TCA9554 is connected to GPIO input 11 of the Raspi
_device = new Tca9554(_i2c, 11, _gpioController, false);
GpioController theDeviceController = new GpioController(_device);
theDeviceController.OpenPin(1, PinMode.Input);
theDeviceController.RegisterCallbackForPinValueChangedEvent(1, PinEventTypes.Rising, Callback);
```

## Binding Notes
Ellerbach marked this conversation as resolved.
Show resolved Hide resolved

The bindings includes an `Tca955x` abstract class and derived for 8-bit `Tca9554` and 16-bit `Tca9555`.
32 changes: 32 additions & 0 deletions src/devices/Tca955x/Register.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Iot.Device.Tca955x
{
/// <summary>
/// Register for the base class and the 8-Bit device
/// </summary>
public enum Register
{
/// <summary>
/// Register Adress for the Inputs P0 - P7
/// Only Read Allowed on this Register
/// </summary>
InputPort = 0x00,

/// <summary>
/// Register Adress for the Outputs P0 - P7
/// </summary>
OutputPort = 0x01,

/// <summary>
/// Register Adress for the Polarity Inversion P0 - P7
/// </summary>
PolarityInversionPort = 0x02,

/// <summary>
/// Register Adress for the Configuration P0 - P7
/// </summary>
ConfigurationPort = 0x03,
}
}
62 changes: 62 additions & 0 deletions src/devices/Tca955x/Tca9554.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Device.Gpio;
using System.Device.I2c;

namespace Iot.Device.Tca955x
{
/// <summary>
/// Class for the Tca9554 8-Bit I/O Exander
/// </summary>
public class Tca9554 : Tca955x
{
/// <summary>
/// Constructor for the Tca9554 I2C I/O Expander.
/// </summary>
/// <param name="device">The I2C device used for communication</param>
/// <param name="interrupt">The input pin number that is connected to the interrupt.</param>
/// <param name="gpioController">The controller for the reset and interrupt pins. If not specified, the default controller will be used.</param>
/// <param name="shouldDispose">True to dispose the Gpio Controller.</param>
public Tca9554(I2cDevice device, int interrupt = -1, GpioController? gpioController = null, bool shouldDispose = true)
: base(device, interrupt, gpioController, shouldDispose)
{
}

/// <inheritdoc/>
protected override int PinCount => 8;

/// <inheritdoc/>
protected override byte GetByteRegister(int pinNumber, ushort value)
{
return (byte)(value & 0xFF);
}

/// <inheritdoc/>
protected override int GetBitNumber(int pinNumber)
{
return pinNumber;
}

/// <inheritdoc/>
protected override byte GetRegisterIndex(int pinNumber, Register registerType)
{
// No conversion for 8-Bit devices
return (byte)registerType;
}

/// <summary>
/// Write a byte to the given Register.
/// </summary>
/// <param name="register">The given Register.</param>
/// <param name="value">The value to write.</param>
public void WriteByte(Register register, byte value) => InternalWriteByte((byte)register, value);

/// <summary>
/// Read a byte from the given Register.
/// </summary>
/// <param name="register">The given Register.</param>
/// <returns>The readed byte from the Register.</returns>
public byte ReadByte(Register register) => InternalReadByte((byte)register);
}
}
98 changes: 98 additions & 0 deletions src/devices/Tca955x/Tca9555.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// 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.Gpio;
using System.Device.I2c;

namespace Iot.Device.Tca955x
{
/// <summary>
/// Class for the Tca9555 16-Bit I/O Exander
/// </summary>
public class Tca9555 : Tca955x
{
/// <summary>
/// Constructor for the Tca9555 I2C I/O Expander.
/// </summary>
/// <param name="device">The I2C Device the device is connected to. Expect an I2C Adress between 0x20 and 0x27</param>
/// <param name="interrupt">The input pin number that is connected to the interrupt.</param>
/// <param name="gpioController">The controller for the reset and interrupt pins. If not specified, the default controller will be used.</param>
/// <param name="shouldDispose">True to dispose the Gpio Controller.</param>
public Tca9555(I2cDevice device, int interrupt = -1, GpioController? gpioController = null, bool shouldDispose = true)
: base(device, interrupt, gpioController, shouldDispose)
{
}

/// <inheritdoc/>
protected override int PinCount => 16;

/// <inheritdoc/>
protected override byte GetByteRegister(int pinNumber, ushort value)
{
if (pinNumber >= 0 &&
pinNumber <= 7)
{
return (byte)(value & 0xFF);
}
else if (pinNumber >= 8 &&
pinNumber <= 15)
{
return (byte)((value >> 8) & 0xFF);
}

return 0;
}

/// <inheritdoc/>
protected override int GetBitNumber(int pinNumber)
{
if (pinNumber >= 0 &&
pinNumber <= 7)
{
return pinNumber;
}
else if (pinNumber >= 8 &&
pinNumber <= 15)
{
return pinNumber - 8;
}

return 0;
}

/// <inheritdoc/>
protected override byte GetRegisterIndex(int pinNumber, Register registerType)
{
byte register = (byte)registerType;
register += (byte)registerType;

if (pinNumber >= 0 &&
pinNumber <= 7)
{
return register;
}
else if (pinNumber >= 8 &&
pinNumber <= 15)
{
return ++register;
}

throw new ArgumentOutOfRangeException(nameof(pinNumber));
}

/// <summary>
/// Write a byte to the given Register.
/// </summary>
/// <param name="register">The given Register.</param>
/// <param name="value">The value to write.</param>
public void WriteByte(Tca9555Register register, byte value) => InternalWriteByte((byte)register, value);

/// <summary>
/// Read a byte from the given Register.
/// </summary>
/// <param name="register">The given Register.</param>
/// <returns>The readed byte from the Register.</returns>
public byte ReadByte(Tca9555Register register) => InternalReadByte((byte)register);
}
}
53 changes: 53 additions & 0 deletions src/devices/Tca955x/Tca9555Register.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Iot.Device.Tca955x
{
/// <summary>
/// Register for the 16 Bit Device
/// </summary>
public enum Tca9555Register
{
/// <summary>
/// Register Adress for the Inputs P00 - P07
/// Only Read Allowed on this Register
/// </summary>
InputPort0 = 0x00,

/// <summary>
/// Register Adress for the Inputs P10 - P17
/// Only Read Allowed on this Register
/// </summary>
InputPort1 = 0x01,

/// <summary>
/// Register Adress for the Outputs P00 - P07
/// </summary>
OutputPort0 = 0x02,

/// <summary>
/// Register Adress for the Outputs P10 - P17
/// </summary>
OutputPort1 = 0x03,

/// <summary>
/// Register Adress for the Polarity Inversion P00 - P07
/// </summary>
PolarityInversionPort0 = 0x04,

/// <summary>
/// Register Adress for the Polarity Inversion P10 - P17
/// </summary>
PolarityInversionPort1 = 0x05,

/// <summary>
/// Register Adress for the Configuration P00 - P07
/// </summary>
ConfigurationPort0 = 0x06,

/// <summary>
/// Register Adress for the Configuration P10 - P17
/// </summary>
ConfigurationPort1 = 0x06,
}
}
Loading