Inter-integrated Circuit (I2C)#

Hardware Interface#

Defined in namespace hal

#include <libhal/i2c.hpp>

class i2c#

Inter-integrated Circuit (I2C) hardware abstract interface.

Also known as Two Wire Interface (TWI) communication protocol. This is a very commonly used protocol for communication with sensors and peripheral devices because it only requires two connections SDA (data signal) and SCL (clock signal). This is possible because the protocol for I2C is addressable.

Subclassed by hal::soft::inert_i2c, hal::soft::minimum_speed_i2c

Public Functions

inline void configure(const settings &p_settings)#

Configure i2c to match the settings supplied.

Parameters:

p_settings – - settings to apply to i2c driver

Throws:

hal::operation_not_supported – - if the settings could not be achieved.

inline void transaction(hal::byte p_address, std::span<const hal::byte> p_data_out, std::span<hal::byte> p_data_in, hal::function_ref<hal::timeout_function> p_timeout)#

perform an i2c transaction with another device on the bus. The type of transaction depends on values of input parameters. This function will block until the entire transfer is finished.

Performing Write, Read and Write-Then-Read transactions depends on which span for data_out and data_in are set to null.

  • For write transactions, pass p_data_in as an empty span std::span<hal::byte>{} and pass a buffer to p_data_out.

  • For read transactions, pass p_data_out as an empty span std::span<const hal::byte>{} and pass a buffer to p_data_in.

  • For write-then-read transactions, pass a buffer for both p_data_in p_data_out.

  • If both p_data_in and p_data_out are empty, simply do nothing and return success.

In the event of arbitration loss, this function will wait for the bus to become free and try again. Arbitration loss means that during the address phase of a transaction 1 or more i2c bus controllers attempted to perform an transaction and one of the i2c bus controllers, that isn’t this one won out.

Parameters:
  • p_address – 7-bit address of the device you want to communicate with. To perform a transaction with a 10-bit address, this parameter must be the address upper byte of the 10-bit address OR’d with 0b1111’0000 (the 10-bit address indicator). The lower byte of the address must be contained in the first byte of the p_data_out span.

  • p_data_out – data to be written to the addressed device. Set to nullptr with length zero in order to skip writing.

  • p_data_in – buffer to store read data from the addressed device. Set to nullptr with length 0 in order to skip reading.

  • p_timeout – callable which notifies the i2c driver that it has run out of time to perform the transaction and must stop and return control to the caller.

Throws:
  • hal::timed_out – from p_timeout if the transaction exceeds its deadline.

  • hal::no_such_device – - indicates that no devices on the bus acknowledge the address in this transaction, which could mean that the device is not connected to the bus, is not powered, not available to respond, broken or many other possible outcomes.

  • hal::resource_unavailable_try_again – - if there is another controller on the bus and it won control of the bus, this transaction is canceled and this exception is thrown.

  • hal::io_error – - indicates that the i2c lines were put into an invalid state during the transaction due to interference, misconfiguration, hardware fault, malfunctioning i2c peripheral or possibly something else. This tends to present a hardware issue and is usually not recoverable.

struct settings#

Generic settings for a standard I2C device.

Public Members

hertz clock_rate = 100.0_kHz#

The serial clock rate in hertz.

Utilities#

Utilities for working with I2C, defined in namespace hal

#include <libhal-util/i2c.hpp>

group I2CUtils

Enums

enum class i2c_operation#

Set of I2C transaction operations.

Values:

enumerator write#

Denotes an i2c write operation.

enumerator read#

Denotes an i2c read operation.

Functions

constexpr auto operator==(const i2c::settings &p_lhs, const i2c::settings &p_rhs)#

Compares two I2C bus states.

Parameters:
  • p_lhs – A I2C bus.

  • p_rhs – A I2C bus.

Returns:

A boolean if they are the same or not.

inline void write(i2c &p_i2c, hal::byte p_address, std::span<const hal::byte> p_data_out, timeout auto p_timeout)#

write data to a target device on the i2c bus

Shorthand for writing i2c.transfer(…) for write only operations

Parameters:
  • p_i2c – - i2c driver

  • p_address – - target address

  • p_data_out – - buffer of bytes to write to the target device

  • p_timeout – - amount of time to execute the transaction

inline void write(i2c &p_i2c, hal::byte p_address, std::span<const hal::byte> p_data_out)#

write data to a target device on the i2c bus

Shorthand for writing i2c.transfer(…) for write only operations, but never times out. Can be used for devices that never perform clock stretching.

Parameters:
  • p_i2c – - i2c driver

  • p_address – - target address

  • p_data_out – - buffer of bytes to write to the target device

inline void read(i2c &p_i2c, hal::byte p_address, std::span<hal::byte> p_data_in, timeout auto p_timeout)#

read bytes from target device on i2c bus

Shorthand for writing i2c.transfer(…) for read only operations

Parameters:
  • p_i2c – - i2c driver

  • p_address – - target address

  • p_data_in – - buffer to read bytes into from target device

  • p_timeout – - amount of time to execute the transaction

inline void read(i2c &p_i2c, hal::byte p_address, std::span<hal::byte> p_data_in)#

read bytes from target device on i2c bus

Shorthand for writing i2c.transfer(…) for read only operations, but never times out. Can be used for devices that never perform clock stretching.

Parameters:
  • p_i2c – - i2c driver

  • p_address – - target address

  • p_data_in – - buffer to read bytes into from target device

template<size_t bytes_to_read>
std::array<hal::byte, bytes_to_read> read(i2c &p_i2c, hal::byte p_address, timeout auto p_timeout)#

return array of read bytes from target device on i2c bus

Eliminates the need to create a buffer and pass it into the read function.

Template Parameters:

bytes_to_read – - number of bytes to read

Parameters:
  • p_i2c – - i2c driver

  • p_address – - target address

  • p_timeout – - amount of time to execute the transaction

Returns:

std::array<hal::byte, bytes_to_read> - array of bytes from target device

template<size_t bytes_to_read>
std::array<hal::byte, bytes_to_read> read(i2c &p_i2c, hal::byte p_address)#

return array of read bytes from target device on i2c bus

Eliminates the need to create a buffer and pass it into the read function. This operation will never time out and should only be used with devices that never perform clock stretching.

Template Parameters:

bytes_to_read – - number of bytes to read

Parameters:
  • p_i2c – - i2c driver

  • p_address – - target address

Returns:

std::array<hal::byte, bytes_to_read> - array of bytes from target device.

inline void write_then_read(i2c &p_i2c, hal::byte p_address, std::span<const hal::byte> p_data_out, std::span<hal::byte> p_data_in, timeout auto p_timeout = hal::never_timeout())#

write and then read bytes from target device on i2c bus

This API simply calls transaction. This API is here for consistency across the other other communication protocols such as SPI and serial.

Parameters:
  • p_i2c – - i2c driver

  • p_address – - target address

  • p_data_out – - buffer of bytes to write to the target device

  • p_data_in – - buffer to read bytes into from target device

  • p_timeout – - amount of time to execute the transaction

template<size_t bytes_to_read>
std::array<hal::byte, bytes_to_read> write_then_read(i2c &p_i2c, hal::byte p_address, std::span<const hal::byte> p_data_out, timeout auto p_timeout)#

write and then return an array of read bytes from target device on i2c bus

Eliminates the need to create a buffer and pass it into the read function.

Template Parameters:

bytes_to_read – - number of bytes to read after write

Parameters:
  • p_i2c – - i2c driver

  • p_address – - target address

  • p_data_out – - buffer of bytes to write to the target device

  • p_timeout – - amount of time to execute the transaction

Returns:

std::array<hal::byte, bytes_to_read> - array of bytes from target device.

template<size_t bytes_to_read>
std::array<hal::byte, bytes_to_read> write_then_read(i2c &p_i2c, hal::byte p_address, std::span<const hal::byte> p_data_out)#

write and then return an array of read bytes from target device on i2c bus

Eliminates the need to create a buffer and pass it into the read function.

Template Parameters:

bytes_to_read – - number of bytes to read after write

Parameters:
  • p_i2c – - i2c driver

  • p_address – - target address

  • p_data_out – - buffer of bytes to write to the target device

Returns:

std::array<hal::byte, bytes_to_read> -

inline bool probe(i2c &p_i2c, hal::byte p_address)#

probe the i2c bus to see if a device exists

NOTE: that this utilizes the fact that i2c drivers throw std::errc::no_such_device_or_address when a transaction is performed and the device’s address is used on the bus and the device does not respond with an acknowledge.

Parameters:
  • p_i2c – - i2c driver for the i2c bus that the device may exist on

  • p_address – - device to check

Returns:

true - if the device appears on the bus

Returns:

false - if the devices does not appear on the i2c bus

inline hal::byte to_8_bit_address(hal::byte p_address, i2c_operation p_operation) noexcept#

Convert 7-bit i2c address to an 8-bit address.

Parameters:
  • p_address – 7-bit i2c address

  • p_operation – write or read operation

Returns:

hal::byte - 8-bit i2c address