// Copyright (C)2018-2023, Philip Munts dba Munts Technologies. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. namespace IO.Devices.PCA9534 { /// /// Encapsulates PCA9534 (and similar) I2C GPIO Expanders. /// public class Device { private readonly IO.Interfaces.I2C.Device dev; private byte config; private byte latch; private byte[] cmd = { 0, 0 }; // I2C command buffer private byte[] resp = { 0 }; // I2C response buffer /// /// The number of available GPIO pins per chip. /// public const int MAX_PINS = 8; /// /// Input Port Register address. /// public const byte InputPortReg = 0; /// /// Output Port Register address. /// public const byte OutputPortReg = 1; /// /// Input Port Polarity Register address. /// public const byte InputPolarityReg = 2; /// /// Configuration Register address. /// public const byte ConfigurationReg = 3; /// /// Configure all pins as inputs. /// public const byte AllInputs = 0xFF; /// /// Configure all pins as outputs. /// public const byte AllOutputs = 0x00; /// /// Configure all inputs as normal polarity. /// public const byte AllNormal = 0x00; /// /// Turn all outputs off. /// public const byte AllOff = 0x00; /// /// Constructor for a PCA9534 (or similar) GPIO Expander. /// /// I2C bus controller. /// I2C slave address. /// GPIO pin configuration. /// Initial output states. public Device(IO.Interfaces.I2C.Bus bus, int addr, byte config = AllInputs, byte states = AllOff) { this.dev = new IO.Interfaces.I2C.Device(bus, addr); this.Write(ConfigurationReg, config); this.Write(InputPolarityReg, AllNormal); this.Write(OutputPortReg, states); } /// /// Read from the specified PCA9534 device register. /// /// Register address. /// Register contents. public byte Read(byte addr) { if (addr > ConfigurationReg) throw new System.Exception("Invalid register address"); this.cmd[0] = addr; this.dev.Transaction(this.cmd, 1, this.resp, 1); return this.resp[0]; } /// /// Write to the specified PCA9534 device register. /// /// Register address. /// Data to written. public void Write(byte addr, byte data) { if (addr > ConfigurationReg) throw new System.Exception("Invalid register address"); if (addr == InputPortReg) throw new System.Exception("Cannot write to input port register"); this.cmd[0] = addr; this.cmd[1] = data; this.dev.Write(cmd, 2); if (addr == ConfigurationReg) this.config = data; else if (addr == OutputPortReg) this.latch = data; } /// /// Return actual state of the GPIO pins. /// /// Pin states (MSB = GPIO7). public byte Read() { return this.Read(InputPortReg); } /// /// Write all GPIO pins. /// /// Data to write to pins (MSB = GPIO7). public void Write(byte data) { this.Write(OutputPortReg, data); } /// /// This read-only property returns the last value written to the /// configuration register. /// public byte Config { get { return this.config; } } /// /// This read-only property returns the last value written to the /// output port register. /// public byte Latch { get { return this.latch; } } } }