From adb15962c672b0914e4f8da6790cee39ff9cb9b2 Mon Sep 17 00:00:00 2001 From: Emanuele Trabattoni Date: Sun, 22 Jun 2025 12:23:38 +0200 Subject: [PATCH] I2C Digitalout driver --- lib/GPIO/WS_TCA9554PWR.cpp | 173 ++++++++++++++++--------------------- lib/GPIO/WS_TCA9554PWR.h | 74 ++++++++-------- 2 files changed, 113 insertions(+), 134 deletions(-) diff --git a/lib/GPIO/WS_TCA9554PWR.cpp b/lib/GPIO/WS_TCA9554PWR.cpp index 4e2f154..ffbfc22 100644 --- a/lib/GPIO/WS_TCA9554PWR.cpp +++ b/lib/GPIO/WS_TCA9554PWR.cpp @@ -1,107 +1,80 @@ #include "WS_TCA9554PWR.h" -/***************************************************** Operation register REG ****************************************************/ -uint8_t Read_REG(uint8_t REG) // Read the value of the TCA9554PWR register REG +namespace drivers { - Wire.beginTransmission(TCA9554_ADDRESS); - Wire.write(REG); - uint8_t result = Wire.endTransmission(); - if (result != 0) { - printf("Data Transfer Failure !!!\r\n"); - } - Wire.requestFrom(TCA9554_ADDRESS, 1); - uint8_t bitsStatus = Wire.read(); - return bitsStatus; -} -uint8_t Write_REG(uint8_t REG,uint8_t Data) // Write Data to the REG register of the TCA9554PWR -{ - Wire.beginTransmission(TCA9554_ADDRESS); - Wire.write(REG); - Wire.write(Data); - uint8_t result = Wire.endTransmission(); - if (result != 0) { - printf("Data write failure!!!\r\n"); - return -1; - } - return 0; -} -/********************************************************** Set EXIO mode **********************************************************/ -void Mode_EXIO(uint8_t Pin,uint8_t State) // Set the mode of the TCA9554PWR Pin. The default is Output mode (output mode or input mode). State: 0= Output mode 1= input mode -{ - uint8_t bitsStatus = Read_REG(TCA9554_CONFIG_REG); - uint8_t Data = (0x01 << (Pin-1)) | bitsStatus; - uint8_t result = Write_REG(TCA9554_CONFIG_REG,Data); - if (result != 0) { - printf("I/O Configuration Failure !!!\r\n"); - } -} -void Mode_EXIOS(uint8_t PinState) // Set the mode of the 7 pins from the TCA9554PWR with PinState -{ - uint8_t result = Write_REG(TCA9554_CONFIG_REG,PinState); - if (result != 0) { - printf("I/O Configuration Failure !!!\r\n"); - } -} -/********************************************************** Read EXIO status **********************************************************/ -uint8_t Read_EXIO(uint8_t Pin) // Read the level of the TCA9554PWR Pin -{ - uint8_t inputBits = Read_REG(TCA9554_INPUT_REG); - uint8_t bitStatus = (inputBits >> (Pin-1)) & 0x01; - return bitStatus; -} -uint8_t Read_EXIOS(uint8_t REG = TCA9554_INPUT_REG) // Read the level of all pins of TCA9554PWR, the default read input level state, want to get the current IO output state, pass the parameter TCA9554_OUTPUT_REG, such as Read_EXIOS(TCA9554_OUTPUT_REG); -{ - uint8_t inputBits = Read_REG(REG); - return inputBits; -} -/********************************************************** Set the EXIO output status **********************************************************/ -bool Set_EXIO(uint8_t Pin,uint8_t State) // Sets the level state of the Pin without affecting the other pins -{ - uint8_t Data; - if(State < 2 && Pin < 9 && Pin > 0){ - uint8_t bitsStatus = Read_EXIOS(TCA9554_OUTPUT_REG); - if(State == 1) - Data = (0x01 << (Pin-1)) | bitsStatus; - else if(State == 0) - Data = (~(0x01 << (Pin-1))) & bitsStatus; - uint8_t result = Write_REG(TCA9554_OUTPUT_REG,Data); - if (result != 0) { - printf("Failed to set GPIO!!!\r\n"); - return 0; - } - return 1; - } - else + TCA9554PWR::TCA9554PWR(I2C &i2c, const uint8_t address) : m_i2c(i2c), m_address(address) { - printf("Parameter error, please enter the correct parameter!\r\n"); - return 0; + writeRegister(TCA9554_OUTPUT_REG, Low); // set all pins to Low state + writeRegister(TCA9554_CONFIG_REG, TCA9554_OUT_MODE); // set all pins as output (relay mode for this board) } -} -bool Set_EXIOS(uint8_t PinState) // Set 7 pins to the PinState state such as :PinState=0x23, 0010 0011 state (the highest bit is not used) -{ - uint8_t result = Write_REG(TCA9554_OUTPUT_REG,PinState); - if (result != 0) { - printf("Failed to set GPIO!!!\r\n"); - return 0; - } - return 1; -} -/********************************************************** Flip EXIO state **********************************************************/ -bool Set_Toggle(uint8_t Pin) // Flip the level of the TCA9554PWR Pin -{ - uint8_t bitsStatus = Read_EXIO(Pin); - uint8_t result = Set_EXIO(Pin,(bool)!bitsStatus); - if (!result) { - printf("Failed to Toggle GPIO!!!\r\n"); - return 0; - } - return 1; -} -/********************************************************* TCA9554PWR Initializes the device ***********************************************************/ -void TCA9554PWR_Init(uint8_t PinMode, uint8_t PinState) // Set the seven pins to PinState state, for example :PinState=0x23, 0010 0011 State (Output mode or input mode) 0= Output mode 1= Input mode. The default value is output mode -{ - Set_EXIOS(PinState); - Mode_EXIOS(PinMode); -} + const bool TCA9554PWR::writeRegister(const uint8_t reg, const uint8_t val) + { + if (m_i2c.Write(m_address, reg, {val})) + return true; + log_e("Unable to write register: reg[%d], val[%d] ", reg, val); + return false; + } + + const bool TCA9554PWR::readRegister(const uint8_t reg, uint8_t &val) + { + std::vector data; + if (m_i2c.Read(m_address, reg, 1, data)) + { + val = data.back(); + return true; + } + log_e("Unable to read register: reg[%d]"); + return false; + } + + const bool TCA9554PWR::setOut(const uint8_t ch, const bool state) + { + uint8_t currState(0); + uint8_t newState(0); + + if (ch < EXIO_PIN1 || ch > EXIO_PIN8) + { + log_e("Invalid write to output channel: [%d]", ch); + return false; + } + if (!readPort(currState)) + return false; + if (state) + newState = (High << ch) | currState; + else + newState = (~(High << ch)) & currState; + return setPort(newState); + } + + const bool TCA9554PWR::setPort(const uint8_t state) + { + if (writeRegister(TCA9554_OUTPUT_REG, state)) + return true; + log_e("Unable to write IO port: state[%02x]", state); + return false; + } + + const bool TCA9554PWR::readOut(const uint8_t ch) + { + uint8_t currState(0); + if (ch < EXIO_PIN1 || ch > EXIO_PIN8) + { + log_e("Invalid read to output channel: [%d]", ch); + return false; + } + if (!readPort(currState)) + return false; + return (currState && (High >> ch)); + } + + const bool TCA9554PWR::readPort(uint8_t &state) + { + if (readRegister(TCA9554_INPUT_REG, state)) + return true; + log_e("Unable to read IO port: state[%02x]", state); + return false; + } + +} diff --git a/lib/GPIO/WS_TCA9554PWR.h b/lib/GPIO/WS_TCA9554PWR.h index b8dfb6a..1e311b7 100644 --- a/lib/GPIO/WS_TCA9554PWR.h +++ b/lib/GPIO/WS_TCA9554PWR.h @@ -1,41 +1,47 @@ #pragma once - -#include #include "I2C_Driver.h" -/****************************************************** The macro defines the TCA9554PWR information ******************************************************/ +/****************************************************** The macro defines the TCA9554PWR information ******************************************************/ -#define TCA9554_ADDRESS 0x20 // TCA9554PWR I2C address -#define TCA9554_INPUT_REG 0x00 // Input register,input level -#define TCA9554_OUTPUT_REG 0x01 // Output register, high and low level output -#define TCA9554_Polarity_REG 0x02 // The Polarity Inversion register (register 2) allows polarity inversion of pins defined as inputs by the Configuration register. -#define TCA9554_CONFIG_REG 0x03 // Configuration register, mode configuration +#define TCA9554_ADDRESS 0x20 // TCA9554PWR I2C address +#define TCA9554_INPUT_REG 0x00 // Input register, input level +#define TCA9554_OUTPUT_REG 0x01 // Output register, high and low level output +#define TCA9554_POLARITY_REG 0x02 // The Polarity Inversion register (register 2) allows polarity inversion of pins defined as inputs by the Configuration register. +#define TCA9554_CONFIG_REG 0x03 // Configuration register, mode configuration +#define TCA9554_OUT_MODE 0x00 // Configuration register value, output mode +#define TCA9554_IN_MODE 0xff // Configuration register value, input mode -#define Low 0 -#define High 1 -#define EXIO_PIN1 1 -#define EXIO_PIN2 2 -#define EXIO_PIN3 3 -#define EXIO_PIN4 4 -#define EXIO_PIN5 5 -#define EXIO_PIN6 6 -#define EXIO_PIN7 7 -#define EXIO_PIN8 8 +#define Low 0x00 +#define High 0x01 -/***************************************************** Operation register REG ****************************************************/ -uint8_t Read_REG(uint8_t REG); // Read the value of the TCA9554PWR register REG -uint8_t Write_REG(uint8_t REG,uint8_t Data); // Write Data to the REG register of the TCA9554PWR -/********************************************************** Set EXIO mode **********************************************************/ -void Mode_EXIO(uint8_t Pin,uint8_t State); // Set the mode of the TCA9554PWR Pin. The default is Output mode (output mode or input mode). State: 0= Output mode 1= input mode -void Mode_EXIOS(uint8_t PinState); // Set the mode of the 7 pins from the TCA9554PWR with PinState -/********************************************************** Read EXIO status **********************************************************/ -uint8_t Read_EXIO(uint8_t Pin); // Read the level of the TCA9554PWR Pin -uint8_t Read_EXIOS(uint8_t REG); // Read the level of all pins of TCA9554PWR, the default read input level state, want to get the current IO output state, pass the parameter TCA9554_OUTPUT_REG, such as Read_EXIOS(TCA9554_OUTPUT_REG); -/********************************************************** Set the EXIO output status **********************************************************/ -bool Set_EXIO(uint8_t Pin,uint8_t State); // Sets the level state of the Pin without affecting the other pins -bool Set_EXIOS(uint8_t PinState); // Set 7 pins to the PinState state such as :PinState=0x23, 0010 0011 state (the highest bit is not used) -/********************************************************** Flip EXIO state **********************************************************/ -bool Set_Toggle(uint8_t Pin); // Flip the level of the TCA9554PWR Pin -/********************************************************* TCA9554PWR Initializes the device ***********************************************************/ -void TCA9554PWR_Init(uint8_t PinMode = 0x00, uint8_t PinState = 0x00); // Set the seven pins to PinState state, for example :PinState=0x23, 0010 0011 State (the highest bit is not used) (Output mode or input mode) 0= Output mode 1= Input mode. The default value is output mode +#define EXIO_PIN1 0 +#define EXIO_PIN2 1 +#define EXIO_PIN3 2 +#define EXIO_PIN4 3 +#define EXIO_PIN5 4 +#define EXIO_PIN6 5 +#define EXIO_PIN7 6 +#define EXIO_PIN8 7 + +namespace drivers +{ + class TCA9554PWR + { + I2C &m_i2c; + uint8_t m_address; + + private: + const bool writeRegister(const uint8_t reg, const uint8_t val); + const bool readRegister(const uint8_t reg, uint8_t &val); + + public: + TCA9554PWR(I2C &i2c, const uint8_t address); + + const bool setOut(const uint8_t channel, const bool state); + const bool setPort(const uint8_t state); + + const bool readOut(const uint8_t channel); + const bool readPort(uint8_t &state); + }; +} \ No newline at end of file