PI4IOE5V I/O Expander
The Pi4ioe5v I/O expander component allows the user to configure inputs, outputs, polarity inversion, and internal pulls via I2C.
API Reference
Header File
Classes
-
class Pi4ioe5v : public espp::BasePeripheral<uint8_t, true>
PI4IOE5V I2C GPIO Expander family driver.
Provides APIs to configure direction, set/clear/read GPIOs, invert input polarity, and enable/configure pulls for PI4IOE5Vxxxx devices. Derives from
espp::BasePeripheral<uint8_t, true>
(8-bit register addresses, addressed device).The register layout used here matches common PI4IOE5V variants with two 8-bit ports (total 16 GPIOs). If your variant differs (e.g., pull register addresses), adjust the
Reg
map accordingly.Example
This component is typically bound to anespp::I2c i2c({ .port = I2C_NUM_1, .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, }); // Configure PI4IOE5V: single 8-bit port as outputs espp::Pi4ioe5v exp({ .device_address = espp::Pi4ioe5v::DEFAULT_ADDRESS, .direction_mask = 0x00, // all outputs .output_state = 0xFF, // initial state .probe = std::bind(&espp::I2c::probe_device, &i2c, std::placeholders::_1), .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), .read_register = std::bind(&espp::I2c::read_at_register, &i2c, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), .write_then_read = std::bind(&espp::I2c::write_read, &i2c, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), .log_level = espp::Logger::Verbosity::WARN, }); std::error_code ec; exp.initialize(ec); if (ec) { fmt::print("PI4IOE5V init failed: {}\n", ec.message()); return; } auto task_fn = [&](std::mutex &m, std::condition_variable &cv) { static uint8_t value = 0xAA; value ^= 0xFF; // toggle pattern exp.write_outputs(value, ec); if (!ec) { uint8_t inputs = exp.read_inputs(ec); if (!ec) { fmt::print("OUT=0x{:02X} IN=0x{:02X}\n", value, inputs); } } { std::unique_lock<std::mutex> lk(m); cv.wait_for(lk, 500ms); } return false; }; espp::Task task({.callback = task_fn, .task_config = {.name = "PI4IOE5V Task", .stack_size_bytes = 4 * 1024}, .log_level = espp::Logger::Verbosity::WARN}); task.start();
espp::I2c
instance using std::bind for the IO hooks. See the README for a short example.Public Types
-
enum class Reg : uint8_t
Register map (typical 8-GPIO variant: single 8-bit port)
Values:
-
enumerator INPUT
Input values (read-only)
-
enumerator OUTPUT
Output latch (read/write)
-
enumerator POLARITY_INV
Input polarity invert (1=invert)
-
enumerator DIRECTION
Direction (1=input, 0=output)
-
enumerator PULL_ENABLE
Pull enable (1=enabled) [variant-specific].
-
enumerator PULL_SELECT
Pull select (1=pull-up, 0=pull-down) [variant-specific].
-
enumerator INPUT
-
typedef std::function<bool(uint8_t)> probe_fn
Function to probe the peripheral
- Param address:
The address to probe
- Return:
True if the peripheral is found at the given address
Public Functions
-
inline explicit Pi4ioe5v(const Config &cfg)
Construct the PI4IOE5V expander.
- Parameters:
cfg – Driver configuration, including IO hooks and initial state.
-
inline bool initialize(std::error_code &ec)
Initialize the expander with the provided configuration.
- Parameters:
ec – Error code set on failure
- Returns:
true on success, false on error
-
inline void set_direction(uint8_t mask_inputs, std::error_code &ec)
Set pin directions for the 8-bit port (1=input, 0=output)
- Parameters:
mask_inputs – Bit mask of inputs (bits 0..7)
ec – Error code set on failure
-
inline void write_outputs(uint8_t value, std::error_code &ec)
Write the output latch for the 8-bit port
- Parameters:
value – Latch values (bits 0..7)
ec – Error code set on failure
-
inline uint8_t read_inputs(std::error_code &ec)
Read current input pin states for the 8-bit port
- Parameters:
ec – Error code set on failure
- Returns:
Bit mask of inputs (bits 0..7)
-
inline void set_polarity_invert(uint8_t mask, std::error_code &ec)
Configure input polarity inversion (1=invert)
- Parameters:
mask – Bit mask to invert (bits 0..7)
ec – Error code set on failure
-
inline void configure_pull(uint8_t enable_mask, uint8_t up_select_mask, std::error_code &ec)
Configure internal pull resistors
- Parameters:
enable_mask – Pull enable mask (1=enable)
up_select_mask – Pull select mask (1=up, 0=down)
ec – Error code set on failure
-
inline bool probe(std::error_code &ec)
Probe the peripheral
Note
This function is thread safe
Note
If the probe function is not set, this function will return false and set the error code to operation_not_supported
Note
This function is only available if UseAddress is true
- Parameters:
ec – The error code to set if there is an error
- Returns:
True if the peripheral is found
-
inline void set_address(uint8_t address)
Set the address of the peripheral
Note
This function is thread safe
Note
This function is only available if UseAddress is true
- Parameters:
address – The address of the peripheral
-
inline void set_probe(const probe_fn &probe)
Set the probe function
Note
This function is thread safe
Note
This should rarely be used, as the probe function is usually set in the constructor. If you need to change the probe function, consider using the set_config function instead.
Note
This function is only available if UseAddress is true
- Parameters:
probe – The probe function
-
inline void set_write(const write_fn &write)
Set the write function
Note
This function is thread safe
Note
This should rarely be used, as the write function is usually set in the constructor. If you need to change the write function, consider using the set_config function instead.
- Parameters:
write – The write function
-
inline void set_read(const read_fn &read)
Set the read function
Note
This function is thread safe
Note
This should rarely be used, as the read function is usually set in the constructor. If you need to change the read function, consider using the set_config function instead.
- Parameters:
read – The read function
-
inline void set_read_register(const read_register_fn &read_register)
Set the read register function
Note
This function is thread safe
Note
This should rarely be used, as the read register function is usually set in the constructor. If you need to change the read register function, consider using the set_config function instead.
- Parameters:
read_register – The read register function
-
inline void set_write_then_read(const write_then_read_fn &write_then_read)
Set the write then read function
Note
This function is thread safe
Note
This should rarely be used, as the write then read function is usually set in the constructor. If you need to change the write then
- Parameters:
write_then_read – The write then read function
-
inline void set_separate_write_then_read_delay(const std::chrono::milliseconds &delay)
Set the delay between the write and read operations in write_then_read
Note
This function is thread safe
Note
This should rarely be used, as the delay is usually set in the constructor. If you need to change the delay, consider using the set_config function instead.
Note
This delay is only used if the write_then_read function is not set to a custom function and the write and read functions are separate functions.
- Parameters:
delay – The delay between the write and read operations in write_then_read
-
inline void set_config(const Config &config)
Set the configuration for the peripheral
Note
This function is thread safe
Note
The configuration should normally be set in the constructor, but this function can be used to change the configuration after the peripheral has been created - for instance if the peripheral could be found on different communications buses.
- Parameters:
config – The configuration for the peripheral
-
inline void set_config(Config &&config)
Set the configuration for the peripheral
Note
This function is thread safe
Note
The configuration should normally be set in the constructor, but this function can be used to change the configuration after the peripheral has been created - for instance if the peripheral could be found on different communications buses.
- Parameters:
config – The configuration for the peripheral
-
inline const std::string &get_name() const
Get the name of the component
Note
This is the tag of the logger
- Returns:
A const reference to the name of the component
-
inline void set_log_tag(const std::string_view &tag)
Set the tag for the logger
- Parameters:
tag – The tag to use for the logger
-
inline espp::Logger::Verbosity get_log_level() const
Get the log level for the logger
See also
See also
- Returns:
The verbosity level of the logger
-
inline void set_log_level(espp::Logger::Verbosity level)
Set the log level for the logger
See also
See also
- Parameters:
level – The verbosity level to use for the logger
-
inline void set_log_verbosity(espp::Logger::Verbosity level)
Set the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls set_log_level
- Parameters:
level – The verbosity level to use for the logger
-
inline espp::Logger::Verbosity get_log_verbosity() const
Get the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls get_log_level
- Returns:
The verbosity level of the logger
-
inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)
Set the rate limit for the logger
See also
Note
Only calls to the logger that have _rate_limit suffix will be rate limited
- Parameters:
rate_limit – The rate limit to use for the logger
Public Static Attributes
-
static constexpr uint8_t DEFAULT_ADDRESS = 0x40
Default I2C address when address pins are tied low (variant dependent)
-
struct Config
Configuration structure for the PI4IOE5V driver.
Public Members
-
uint8_t device_address = DEFAULT_ADDRESS
I2C device address
-
uint8_t direction_mask = 0xFF
Optional initial configuration for single 8-bit port (1=input, 0=output)
-
uint8_t output_state = 0x00
Initial output latch state.
-
uint8_t polarity_invert = 0x00
Input invert mask (1=invert)
-
uint8_t pull_enable = 0x00
Pull enable mask (1=enable)
-
uint8_t pull_up_select = 0x00
Pull select mask (1=up, 0=down)
-
BasePeripheral::probe_fn probe = {nullptr}
Optional bus probe.
-
BasePeripheral::write_fn write = {nullptr}
Write function.
-
BasePeripheral::read_register_fn read_register = {nullptr}
Read register function.
-
BasePeripheral::write_then_read_fn write_then_read = {nullptr}
Write-then-read function.
-
bool auto_init = true
Initialize in ctor.
-
uint8_t device_address = DEFAULT_ADDRESS
-
enum class Reg : uint8_t