Class pn532::esp32::i2c::command

Class Documentation

class command

Class that wraps an I2C ESP32’s command.

ESP32’s I2C driver does not allow direct control of the bus; it rather packs all the operations into a prebuild command (represented by a i2c_cmd_handle_t) which is single use. This class is a wrapper for it. Since there is a resource associated to this command, this class has move-only semantics. The command can be invoked via command::operator()(), but once that method is called, it’s unusable and any attempt to further use it or append read/write operation will fail.

using namespace std::chrono_literals;
constexpr std::uint8_t slave_addr = 0x26;

// Implement a command that reads 1 byte status and 4 bytes data
std::uint8_t slave_status = 0x00;
mlab::bin_data slave_payload{mlab::prealloc(4)};

pn532::i2c::command cmd;
cmd.write(slave_addr, true);
cmd.read(slave_status, I2C_MASTER_ACK);
cmd.read(slave_payload.view(), I2C_MASTER_LAST_NACK); // Send a final NACK
cmd.stop();

if (const auto result = cmd(I2C_NUM_0, 100ms); result) {
    std::printf("Successfully trasmitted via I2C.\n");
    // Parse the 4 bytes into an unsigned integer
    std::uint32_t payload_data = 0;
    mlab::bin_stream s{slave_payload};
    s >> mlab::msb32 >> payload_data;
    std::printf("Slave status: %d payload: %u\n", status,  payload_data);
} else {
    std::printf("I2C command failed with status: %s\n", pn532::i2c::to_string(result.error()));
}

Public Functions

command()

Constructs a new, empty, I2C command (via i2c_cmd_link_create).

~command()

Releases all associated resources via i2c_cmd_link_delete.

command(command const&) = delete
command(command&&) noexcept = default
command &operator=(command const&) = delete
command &operator=(command&&) noexcept = default
void write(std::uint8_t b, bool enable_ack_check)

Append a new write operation to the command, writing a unique byte.

Parameters:
  • b – Byte to write.

  • enable_ack_check – If true, the driver will check for a corresponding ACK from the slave. If that is not received, the command as a whole will fail with a error status.

void write(mlab::range<const uint8_t*> data, bool enable_ack_check)

Append a new write operation to the command, writing a sequence of bytes.

Parameters:
  • data – A range of bytes to write. The caller is responsible for keeping this memory in scope and valid until this command object is destroyed. This is passed directly down to the driver, so beware: it is not documented what happens if you pass an empty range.

  • enable_ack_check – If true, the driver will check for a corresponding ACK from the slave. If that is not received, the command as a whole will fail with a error status.

void read(mlab::range<uint8_t*> buffer, i2c_ack_type_t ack)

Append a new read operation to the command, reading a sequence of bytes.

Parameters:
  • buffer – A preallocated buffer of bytes to fill. The caller is responsible for preallocating this memory to exactly the length of the read operation, and keep it in scope and valid until this command object is destroyed. This is passed directly down to the driver, so beware: it is not documented what happens if you pass an empty range.

  • ack – The type of ACK to send. See i2c_types.h for further documentation.

void read(std::uint8_t &b, i2c_ack_type_t ack)

Append a new read operation to the command, reading a single byte.

Parameters:
  • b – A non-constant reference to the byte to fill. The caller is responsible of making sure that the reference is in scope until when this command object is destroyed.

  • ack – The type of ACK to send. See i2c_types.h for further documentation.

void stop()

Append a stop to the command.

Note

A stop is a specific I2C command, so in principle after a stop you can further append write and read operations.

mlab::result<error> operator()(i2c_port_t port, std::chrono::milliseconds timeout)

Executes the buffered command as is it, and invalidates this instance.

Parameters:
  • port – The I2C port on which to run the command.

  • timeout – The maximum time the driver is allowed to take to execute before it fails with a error::timeout

Returns:

A result which is either mlab::result_success, or carries one of the possible error statuses.