DigitalIO driver with dynamic channel count

This commit is contained in:
Emanuele Trabattoni
2025-07-12 13:45:00 +02:00
parent 1955b8cb39
commit ef7b9506b6
8 changed files with 335 additions and 38 deletions

124
src/digitalIO.cpp Normal file
View File

@@ -0,0 +1,124 @@
#include <digitalIO.h>
digitalIO::digitalIO(drivers::I2C &i2c, drivers::MODBUS &bus, std::vector<uint8_t> remotes) : m_localOuts(drivers::TCA9554PWR(i2c, TCA9554_ADDRESS)), m_remoteAddrs(remotes)
{
for (uint8_t i(DI1); i < DI_MAX; i++)
{
pinMode(i, INPUT_PULLUP); // set all local pins as digitalInput
}
for (auto a : remotes)
{
m_remotes.emplace_back(remoteIO(a, bus));
}
}
digitalIO::~digitalIO()
{
}
void digitalIO::digitalIOWrite(const uint8_t ch, const bool value)
{
if (ch < 0 || ch > getOutNum())
{
LOG_ERROR("Invalid digitalIOWrite channel number", ch);
}
if (ch < drivers::TCA9554PWR::DO_MAX) // write to i2c device for local outputs
{
digitalWriteLocal(ch, value);
}
else
{
digitalWriteRemote(ch - drivers::TCA9554PWR::DO_MAX, value);
}
}
const bool digitalIO::digitalIORead(const uint8_t ch)
{
if (ch < 0 || ch > getInNum())
{
LOG_ERROR("Invalid digitalIORead channel number", ch);
}
if (ch < (DI_MAX - DI1)) // read from local inputs not as gpio numbers
{
return digitalReadLocal(ch);
}
else
{
return digitalReadRemote(ch - (DI_MAX - DI1));
}
}
void digitalIO::reset()
{
// set all local and remote outputs to 0
m_localOuts.setPort(0x00);
for (auto r: m_remotes)
r.resetAll(false);
}
const uint8_t digitalIO::getOutNum()
{
return drivers::TCA9554PWR::DO_MAX + m_remotes.size() * remoteIO::CH_MAX;
}
const uint8_t digitalIO::getInNum()
{
return DI_MAX + m_remotes.size() * remoteIO::CH_MAX;
}
void digitalIO::digitalWriteLocal(const uint8_t ch, const bool value)
{
uint8_t retries(0);
while (retries++ < maxRetries)
{
if (m_localOuts.setOut(ch, value))
{
LOG_DEBUG("digitalWriteLocal channel", ch, " status", value ? "True" : "False");
break;
}
LOG_ERROR("Failed digitalWriteLocal channel ", ch, " status", value ? "True" : "False");
}
}
void digitalIO::digitalWriteRemote(const uint8_t ch, const bool value)
{
uint8_t retries(0);
const uint8_t selectedRemote(floor(ch / 8.0f));
const uint8_t selectedChannel(ch % remoteIO::CH_MAX);
while (retries++ < maxRetries)
{
if (m_remotes[selectedRemote].setOut((remoteIO::channel_t)selectedChannel, value))
{
LOG_DEBUG("digitalWriteRemote remote", selectedRemote, " channel ", selectedChannel, " status", value ? "True" : "False");
break;
}
LOG_ERROR("Failed digitalWriteRemote remote", selectedRemote, " channel ", selectedChannel, " status", value ? "True" : "False");
}
}
const bool digitalIO::digitalReadLocal(const uint8_t ch)
{
bool value = !digitalRead(ch + DI1); // base pin number in enum, inverted input
LOG_DEBUG("digitalReadLocal pin", (ch + DI1), " status", value ? "True" : "False");
return value;
}
const bool digitalIO::digitalReadRemote(const uint8_t ch)
{
uint8_t retries(0);
const uint8_t selectedRemote(floor(ch / 8.0f));
const uint8_t selectedChannel(ch % remoteIO::CH_MAX);
bool value;
while (retries++ < maxRetries)
{
if (m_remotes[selectedRemote].getIn((remoteIO::channel_t)selectedChannel, value))
{
LOG_DEBUG("digitalReadRemote remote", selectedRemote, " channel ", selectedChannel, " status", value ? "True" : "False");
return value;
}
LOG_ERROR("Failed digitalReadRemote remote", selectedRemote, " channel ", selectedChannel, " status", value ? "True" : "False");
}
return false;
}