File tca9534.h¶
Go to the documentation of this file
Source Code¶
#pragma once
#ifndef DSY_TCA9534_H
#define DSY_TCA9534_H
#include "per/gpio.h"
#include "per/i2c.h"
namespace daisy
{
enum class Tca9534Register : uint8_t
{
INPUT = 0x00,
OUTPUT = 0x01,
POLARITY = 0x02,
CONFIG = 0x03,
};
enum class Tca9534Mode : uint8_t
{
INPUT,
OUTPUT,
};
class Tca9534
{
public:
struct Config
{
I2CHandle::Config i2c_config;
uint8_t i2c_address;
void Defaults()
{
i2c_config.periph = I2CHandle::Config::Peripheral::I2C_1;
i2c_config.speed = I2CHandle::Config::Speed::I2C_400KHZ;
i2c_config.mode = I2CHandle::Config::Mode::I2C_MASTER;
i2c_config.pin_config.scl = Pin(PORTB, 8);
i2c_config.pin_config.sda = Pin(PORTB, 9);
// TCA9534 default (A2/A1/A0 = 000). Do not left-shift: libDaisy
// Read/WriteDataAtAddress expect the 7-bit address.
i2c_address = 0x20;
}
};
Tca9534()
: i2c_(nullptr),
address_(0x20),
output_state_(0x00),
config_(0xFF),
last_ok_(false),
owns_i2c_(false)
{
}
void Init()
{
Config cfg;
cfg.Defaults();
Init(cfg);
}
void Init(const Config& config)
{
address_ = config.i2c_address;
owns_i2c_ = true;
owned_i2c_.Init(config.i2c_config);
i2c_ = &owned_i2c_;
// Datasheet power-on: all pins inputs (0xFF), outputs low.
config_ = 0xFF;
output_state_ = 0x00;
WriteReg(Tca9534Register::CONFIG, config_);
WriteReg(Tca9534Register::OUTPUT, output_state_);
}
void Init(I2CHandle& i2c, uint8_t address = 0x20)
{
i2c_ = &i2c;
address_ = address;
owns_i2c_ = false;
config_ = 0xFF;
output_state_ = 0x00;
}
bool SetConfig(uint8_t config)
{
config_ = config;
return WriteReg(Tca9534Register::CONFIG, config_);
}
bool SetOutputState(uint8_t output)
{
output_state_ = output;
return WriteReg(Tca9534Register::OUTPUT, output_state_);
}
bool PinMode(uint8_t pin, Tca9534Mode mode)
{
if(pin > 7)
return false;
if(mode == Tca9534Mode::INPUT)
config_ |= static_cast<uint8_t>(1u << pin);
else
config_ &= static_cast<uint8_t>(~(1u << pin));
return WriteReg(Tca9534Register::CONFIG, config_);
}
bool WritePin(uint8_t pin, bool high)
{
if(pin > 7)
return false;
if(high)
output_state_ |= static_cast<uint8_t>(1u << pin);
else
output_state_ &= static_cast<uint8_t>(~(1u << pin));
return WriteReg(Tca9534Register::OUTPUT, output_state_);
}
bool ReadInput(uint8_t& value)
{
last_ok_ = ReadReg(Tca9534Register::INPUT, value);
return last_ok_;
}
bool ReadPin(uint8_t pin, bool& high)
{
uint8_t value = 0;
if(!ReadInput(value) || pin > 7)
return false;
high = (value & static_cast<uint8_t>(1u << pin)) != 0;
return true;
}
bool LastTransferOk() const { return last_ok_; }
bool LastReadOk() const { return last_ok_; }
uint8_t OutputState() const { return output_state_; }
uint8_t ConfigRegister() const { return config_; }
uint8_t Address() const { return address_; }
private:
bool WriteReg(Tca9534Register reg, uint8_t value)
{
if(i2c_ == nullptr)
{
last_ok_ = false;
return false;
}
last_ok_ = i2c_->WriteDataAtAddress(
address_, static_cast<uint8_t>(reg), 1, &value, 1, 10)
== I2CHandle::Result::OK;
return last_ok_;
}
bool ReadReg(Tca9534Register reg, uint8_t& value)
{
if(i2c_ == nullptr)
{
last_ok_ = false;
return false;
}
last_ok_ = i2c_->ReadDataAtAddress(
address_, static_cast<uint8_t>(reg), 1, &value, 1, 10)
== I2CHandle::Result::OK;
return last_ok_;
}
I2CHandle* i2c_;
I2CHandle owned_i2c_;
uint8_t address_;
uint8_t output_state_;
uint8_t config_;
bool last_ok_;
bool owns_i2c_;
};
} // namespace daisy
#endif // DSY_TCA9534_H