25#include <frequency/frequency>
49#if SOC_HP_I2C_NUM >= 2
52#if SOC_LP_I2C_NUM >= 1
79#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
102 void lock()
const { _mux.lock(); }
105 [[nodiscard]]
bool try_lock() const noexcept {
return _mux.try_lock(); }
114 [[nodiscard]]
enum port port()
const {
return _port; }
117 [[nodiscard]] freq::hertz
frequency()
const {
return _frequency; }
137 template<
typename Rep,
typename Period>
138 [[nodiscard]] std::vector<uint8_t>
scan_devices(
const std::chrono::duration<Rep, Period>&
timeout)
const {
139 return _scan_devices(std::chrono::ceil<std::chrono::milliseconds>(
timeout));
142#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
162 template<
typename Rep,
typename Period>
163 void probe(uint8_t address,
const std::chrono::duration<Rep, Period>&
timeout)
const {
164 unwrap(_probe(address, std::chrono::ceil<std::chrono::milliseconds>(
timeout)));
185 template<
typename Rep,
typename Period>
187 return _probe(address, std::chrono::ceil<std::chrono::milliseconds>(
timeout));
193 [[nodiscard]] std::vector<uint8_t> _scan_devices(std::chrono::milliseconds
timeout)
const;
194 [[nodiscard]]
result<void> _probe(uint8_t address, std::chrono::milliseconds
timeout)
const;
196 mutable std::recursive_mutex _mux;
199 freq::hertz _frequency;
221#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
242 [[nodiscard]]
const std::shared_ptr<master_bus>&
bus()
const {
return _bus; }
248 [[nodiscard]] uint8_t
address()
const {
return _address; }
250#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
267 template<
typename Rep,
typename Period>
269 _bus->probe(_address, std::chrono::ceil<std::chrono::milliseconds>(
timeout));
287 template<
typename Rep,
typename Period>
289 return _bus->try_probe(_address, std::chrono::ceil<std::chrono::milliseconds>(
timeout));
292#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
312 template<
typename Rep,
typename Period>
313 void transmit(
const std::vector<uint8_t> data,
const std::chrono::duration<Rep, Period>&
timeout) {
338 template<
typename Rep,
typename Period>
339 void transmit(
const uint8_t* buf,
size_t size,
const std::chrono::duration<Rep, Period>&
timeout) {
363 template<
typename Rep,
typename Period>
390 template<
typename Rep,
typename Period>
393 return _try_transmit(buf, size, std::chrono::ceil<std::chrono::milliseconds>(
timeout));
396#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
420 template<
typename Rep,
typename Period>
421 [[nodiscard]] std::vector<uint8_t>
receive(
size_t size,
const std::chrono::duration<Rep, Period>&
timeout) {
446 template<
typename Rep,
typename Period>
447 void receive(uint8_t* buf,
size_t size,
const std::chrono::duration<Rep, Period>&
timeout) {
471 template<
typename Rep,
typename Period>
472 void receive(std::vector<uint8_t> buf,
const std::chrono::duration<Rep, Period>&
timeout) {
494 template<
typename Rep,
typename Period>
497 std::vector<uint8_t> buf(size);
522 template<
typename Rep,
typename Period>
525 return _try_receive(buf, size, std::chrono::ceil<std::chrono::milliseconds>(
timeout));
545 template<
typename Rep,
typename Period>
551#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
573 template<
typename Rep,
typename Period>
602 template<
typename Rep,
typename Period>
630 template<
typename Rep,
typename Period>
633 const std::vector<uint8_t> buf,
634 const std::chrono::duration<Rep, Period>&
timeout
662 template<
typename Rep,
typename Period>
667 const std::chrono::duration<Rep, Period>&
timeout
669 return _try_write_register(reg, buf, size, std::chrono::ceil<std::chrono::milliseconds>(
timeout));
672#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
683 void write_register(uint8_t regHigh, uint8_t regLow,
const std::vector<uint8_t> buf) {
698 template<
typename Rep,
typename Period>
702 const std::vector<uint8_t> buf,
703 const std::chrono::duration<Rep, Period>&
timeout
719 void write_register(uint8_t regHigh, uint8_t regLow,
const uint8_t* buf,
size_t size) {
735 template<
typename Rep,
typename Period>
741 const std::chrono::duration<Rep, Period>&
timeout
770 template<
typename Rep,
typename Period>
774 const std::vector<uint8_t> buf,
775 const std::chrono::duration<Rep, Period>&
timeout
805 template<
typename Rep,
typename Period>
811 const std::chrono::duration<Rep, Period>&
timeout
813 return _try_write_register(regHigh, regLow, buf, size, std::chrono::ceil<std::chrono::milliseconds>(
timeout));
816#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
826 void write_registers(std::vector<uint16_t> registers,
const std::vector<uint8_t> buf) {
840 template<
typename Rep,
typename Period>
842 std::vector<uint16_t> registers,
843 const std::vector<uint8_t> buf,
844 const std::chrono::duration<Rep, Period>&
timeout
859 void write_registers(std::vector<uint16_t> registers,
const uint8_t* buf,
size_t size) {
874 template<
typename Rep,
typename Period>
876 std::vector<uint16_t> registers,
879 const std::chrono::duration<Rep, Period>&
timeout
906 template<
typename Rep,
typename Period>
908 std::vector<uint16_t> registers,
909 const std::vector<uint8_t> buf,
910 const std::chrono::duration<Rep, Period>&
timeout
938 template<
typename Rep,
typename Period>
940 std::vector<uint16_t> registers,
943 const std::chrono::duration<Rep, Period>&
timeout
945 return _try_write_registers(registers, buf, size, std::chrono::ceil<std::chrono::milliseconds>(
timeout));
948#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
960 [[nodiscard]] std::vector<uint8_t>
read_register(uint16_t reg,
size_t size) {
976 template<
typename Rep,
typename Period>
977 [[nodiscard]] std::vector<uint8_t>
1003 template<
typename Rep,
typename Period>
1031 template<
typename Rep,
typename Period>
1058 template<
typename Rep,
typename Period>
1061 std::vector<uint8_t> buf(size);
1085 template<
typename Rep,
typename Period>
1114 template<
typename Rep,
typename Period>
1117 return _try_read_register(reg, buf, size, std::chrono::ceil<std::chrono::milliseconds>(
timeout));
1120#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1133 [[nodiscard]] std::vector<uint8_t>
read_register(uint8_t regHigh, uint8_t regLow,
size_t size) {
1150 template<
typename Rep,
typename Period>
1151 [[nodiscard]] std::vector<uint8_t>
1167 void read_register(uint8_t regHigh, uint8_t regLow, uint8_t* buf,
size_t size) {
1183 template<
typename Rep,
typename Period>
1189 const std::chrono::duration<Rep, Period>&
timeout
1218 template<
typename Rep,
typename Period>
1221 std::vector<uint8_t> buf(size);
1248 template<
typename Rep,
typename Period>
1252 std::vector<uint8_t> buf,
1253 const std::chrono::duration<Rep, Period>&
timeout
1283 template<
typename Rep,
typename Period>
1289 const std::chrono::duration<Rep, Period>&
timeout
1291 return _try_read_register(regHigh, regLow, buf, size, std::chrono::ceil<std::chrono::milliseconds>(
timeout));
1297 [[nodiscard]]
result<void> _try_transmit(
const uint8_t* buf,
size_t size, std::chrono::milliseconds
timeout);
1298 [[nodiscard]]
result<void> _try_receive(uint8_t* buf,
size_t size, std::chrono::milliseconds
timeout);
1301 _try_write_register(uint16_t reg,
const uint8_t* buf,
size_t size, std::chrono::milliseconds
timeout);
1307 std::chrono::milliseconds
timeout
1310 std::vector<uint16_t> registers,
1313 std::chrono::milliseconds
timeout
1316 _try_read_register(uint16_t reg, uint8_t* buf,
size_t size, std::chrono::milliseconds
timeout);
1318 _try_read_register(uint8_t regHigh, uint8_t regLow, uint8_t* buf,
size_t size, std::chrono::milliseconds
timeout);
1320 std::shared_ptr<master_bus> _bus;
1342#if SOC_HP_I2C_NUM >= 2
1343 case i2c::port::i2c1:
1346#if SOC_LP_I2C_NUM >= 1
1347 case i2c::port::lp_i2c0:
1351 return "unknown(" + std::to_string(
static_cast<int>(p)) +
")";
1357#include "sdkconfig.h"
1358#ifdef CONFIG_IDFXX_STD_FORMAT
1364struct formatter<
idfxx::i2c::port> {
1365 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
1367 template<
typename FormatContext>
1370 return std::copy(s.begin(), s.end(), ctx.out());
I2C master bus controller with thread-safe device access.
master_bus(enum port port, gpio sda, gpio scl, freq::hertz frequency)
Creates a new I2C master bus.
std::vector< uint8_t > scan_devices() const
Scans for devices on the bus.
enum port port() const
Returns the I2C port.
std::vector< uint8_t > scan_devices(const std::chrono::duration< Rep, Period > &timeout) const
Scans for devices on the bus.
void probe(uint8_t address) const
Probes for a device at the specified address.
master_bus & operator=(master_bus &&)=delete
master_bus & operator=(const master_bus &)=delete
result< void > try_probe(uint8_t address, const std::chrono::duration< Rep, Period > &timeout) const
Probes for a device at the specified address.
i2c_master_bus_handle_t handle() const
Returns the underlying ESP-IDF bus handle.
void probe(uint8_t address, const std::chrono::duration< Rep, Period > &timeout) const
Probes for a device at the specified address.
freq::hertz frequency() const
Returns the bus clock frequency in Hz.
void unlock() const
Releases exclusive access to the bus.
master_bus(const master_bus &)=delete
result< void > try_probe(uint8_t address) const
Probes for a device at the specified address.
bool try_lock() const noexcept
Tries to acquire exclusive access without blocking.
static result< std::unique_ptr< master_bus > > make(enum port port, gpio sda, gpio scl, freq::hertz frequency)
Creates a new I2C master bus.
master_bus(master_bus &&)=delete
void lock() const
Acquires exclusive access to the bus.
I2C device at a specific 7-bit address with register operations.
void transmit(const uint8_t *buf, size_t size)
Transmits data to the device.
result< void > try_probe() const
Probes the device.
result< void > try_write_register(uint8_t regHigh, uint8_t regLow, const std::vector< uint8_t > buf)
Writes data to a register.
result< void > try_read_register(uint16_t reg, uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
result< void > try_read_register(uint8_t regHigh, uint8_t regLow, std::vector< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
result< void > try_write_register(uint16_t reg, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
result< std::vector< uint8_t > > try_receive(size_t size, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
void write_register(uint16_t reg, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
void write_register(uint16_t reg, const uint8_t *buf, size_t size)
Writes data to a register.
void write_registers(std::vector< uint16_t > registers, const uint8_t *buf, size_t size)
Writes data to multiple registers.
std::vector< uint8_t > read_register(uint16_t reg, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
void write_register(uint8_t regHigh, uint8_t regLow, const std::vector< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
void read_register(uint8_t regHigh, uint8_t regLow, uint8_t *buf, size_t size)
Reads data from a register.
void receive(std::vector< uint8_t > buf)
Receives data from the device.
result< std::vector< uint8_t > > try_read_register(uint16_t reg, size_t size)
Reads data from a register.
result< void > try_write_register(uint8_t regHigh, uint8_t regLow, const std::vector< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
result< void > try_write_registers(std::vector< uint16_t > registers, const std::vector< uint8_t > buf)
Writes data to multiple registers.
result< void > try_read_register(uint16_t reg, std::vector< uint8_t > &buf)
Reads data from a register.
result< void > try_read_register(uint8_t regHigh, uint8_t regLow, uint8_t *buf, size_t size)
Reads data from a register.
std::vector< uint8_t > read_register(uint8_t regHigh, uint8_t regLow, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
void transmit(const std::vector< uint8_t > data)
Transmits data to the device.
result< void > try_write_registers(std::vector< uint16_t > registers, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to multiple registers.
result< void > try_transmit(const std::vector< uint8_t > data, const std::chrono::duration< Rep, Period > &timeout)
Transmits data to the device.
void receive(uint8_t *buf, size_t size)
Receives data from the device.
void probe() const
Probes the device.
result< void > try_transmit(const std::vector< uint8_t > data)
Transmits data to the device.
void write_register(uint8_t regHigh, uint8_t regLow, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
void receive(std::vector< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
result< void > try_write_register(uint8_t regHigh, uint8_t regLow, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
void receive(uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
result< void > try_receive(uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
void probe(const std::chrono::duration< Rep, Period > &timeout) const
Probes the device.
result< std::vector< uint8_t > > try_read_register(uint8_t regHigh, uint8_t regLow, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
result< std::vector< uint8_t > > try_receive(size_t size)
Receives data from the device.
master_device(master_device &&)=delete
void read_register(uint16_t reg, std::vector< uint8_t > buf)
Reads data from a register.
void read_register(uint8_t regHigh, uint8_t regLow, uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
result< void > try_write_registers(std::vector< uint16_t > registers, const std::vector< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to multiple registers.
void write_register(uint16_t reg, const std::vector< uint8_t > buf)
Writes data to a register.
master_device(const master_device &)=delete
result< std::vector< uint8_t > > try_read_register(uint8_t regHigh, uint8_t regLow, size_t size)
Reads data from a register.
result< void > try_read_register(uint8_t regHigh, uint8_t regLow, uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
void write_register(uint16_t reg, const std::vector< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
result< void > try_write_registers(std::vector< uint16_t > registers, const uint8_t *buf, size_t size)
Writes data to multiple registers.
void write_registers(std::vector< uint16_t > registers, const std::vector< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to multiple registers.
result< void > try_read_register(uint16_t reg, std::vector< uint8_t > &buf, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
void write_registers(std::vector< uint16_t > registers, const std::vector< uint8_t > buf)
Writes data to multiple registers.
master_device(std::shared_ptr< master_bus > bus, uint8_t address)
Creates a new device on the specified bus.
static result< std::unique_ptr< master_device > > make(std::shared_ptr< master_bus > bus, uint8_t address)
Creates a new device on the specified bus.
result< void > try_receive(std::vector< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
result< std::vector< uint8_t > > try_read_register(uint16_t reg, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
result< void > try_receive(std::vector< uint8_t > buf)
Receives data from the device.
void read_register(uint16_t reg, uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
result< void > try_write_register(uint16_t reg, const std::vector< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
result< void > try_transmit(const uint8_t *buf, size_t size)
Transmits data to the device.
result< void > try_read_register(uint8_t regHigh, uint8_t regLow, std::vector< uint8_t > buf)
Reads data from a register.
uint8_t address() const
Returns the 7-bit device address.
const std::shared_ptr< master_bus > & bus() const
Returns the parent bus.
result< void > try_receive(uint8_t *buf, size_t size)
Receives data from the device.
void write_registers(std::vector< uint16_t > registers, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to multiple registers.
i2c_master_dev_handle_t handle() const
Returns the underlying ESP-IDF device handle.
void transmit(const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Transmits data to the device.
result< void > try_write_register(uint16_t reg, const uint8_t *buf, size_t size)
Writes data to a register.
result< void > try_read_register(uint16_t reg, uint8_t *buf, size_t size)
Reads data from a register.
result< void > try_transmit(const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Transmits data to the device.
std::vector< uint8_t > receive(size_t size)
Receives data from the device.
std::vector< uint8_t > read_register(uint16_t reg, size_t size)
Reads data from a register.
void read_register(uint16_t reg, std::vector< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
std::vector< uint8_t > read_register(uint8_t regHigh, uint8_t regLow, size_t size)
Reads data from a register.
std::vector< uint8_t > receive(size_t size, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
result< void > try_write_register(uint16_t reg, const std::vector< uint8_t > buf)
Writes data to a register.
master_device & operator=(const master_device &)=delete
void write_register(uint8_t regHigh, uint8_t regLow, const uint8_t *buf, size_t size)
Writes data to a register.
result< void > try_probe(const std::chrono::duration< Rep, Period > &timeout) const
Probes the device.
master_device & operator=(master_device &&)=delete
void read_register(uint16_t reg, uint8_t *buf, size_t size)
Reads data from a register.
void transmit(const std::vector< uint8_t > data, const std::chrono::duration< Rep, Period > &timeout)
Transmits data to the device.
result< void > try_write_register(uint8_t regHigh, uint8_t regLow, const uint8_t *buf, size_t size)
Writes data to a register.
void write_register(uint8_t regHigh, uint8_t regLow, const std::vector< uint8_t > buf)
Writes data to a register.
std::string to_string(core_id c)
Returns a string representation of a CPU core identifier.
struct i2c_master_bus_t * i2c_master_bus_handle_t
struct i2c_master_dev_t * i2c_master_dev_handle_t
port
I2C port identifiers.
static constexpr auto DEFAULT_TIMEOUT
Default timeout for I2C operations.
I2C master driver classes.
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
@ timeout
Operation timed out.
std::expected< T, std::error_code > result
result type wrapping a value or error code.