diff options
Diffstat (limited to 'pw_i2c/public')
-rw-r--r-- | pw_i2c/public/pw_i2c/device.h | 8 | ||||
-rw-r--r-- | pw_i2c/public/pw_i2c/initiator.h | 8 | ||||
-rw-r--r-- | pw_i2c/public/pw_i2c/register_device.h | 291 |
3 files changed, 183 insertions, 124 deletions
diff --git a/pw_i2c/public/pw_i2c/device.h b/pw_i2c/public/pw_i2c/device.h index 4a76ba57a..3085053fb 100644 --- a/pw_i2c/public/pw_i2c/device.h +++ b/pw_i2c/public/pw_i2c/device.h @@ -49,7 +49,7 @@ class Device { // START + I2C Address + WRITE(0) + TX_BUFFER_BYTES + STOP // START + I2C Address + READ(1) + RX_BUFFER_BYTES + STOP // - // The timeout defines the minimum duration one may block waiting for both + // The timeout defines the maximum duration one may block waiting for both // exclusive bus access and the completion of the I2C transaction. // // Preconditions: @@ -87,7 +87,7 @@ class Device { // Write bytes. The signal on the bus should appear as follows: // START + I2C Address + WRITE(0) + TX_BUFFER_BYTES + STOP // - // The timeout defines the minimum duration one may block waiting for both + // The timeout defines the maximum duration one may block waiting for both // exclusive bus access and the completion of the I2C transaction. // // Preconditions: @@ -117,7 +117,7 @@ class Device { // Read bytes. The signal on the bus should appear as follows: // START + I2C Address + READ(1) + RX_BUFFER_BYTES + STOP // - // The timeout defines the minimum duration one may block waiting for both + // The timeout defines the maximum duration one may block waiting for both // exclusive bus access and the completion of the I2C transaction. // // Preconditions: @@ -146,7 +146,7 @@ class Device { // Probes the device for an I2C ACK after only writing the address. // This is done by attempting to read a single byte from the specified device. // - // The timeout defines the minimum duration one may block waiting for both + // The timeout defines the maximum duration one may block waiting for both // exclusive bus access and the completion of the I2C transaction. // // Preconditions: diff --git a/pw_i2c/public/pw_i2c/initiator.h b/pw_i2c/public/pw_i2c/initiator.h index 7d9d6ddde..edf5fa0cf 100644 --- a/pw_i2c/public/pw_i2c/initiator.h +++ b/pw_i2c/public/pw_i2c/initiator.h @@ -61,7 +61,7 @@ class Initiator { // START + I2C Address + WRITE(0) + TX_BUFFER_BYTES + STOP // START + I2C Address + READ(1) + RX_BUFFER_BYTES + STOP // - // The timeout defines the minimum duration one may block waiting for both + // The timeout defines the maximum duration one may block waiting for both // exclusive bus access and the completion of the I2C transaction. // // Preconditions: @@ -99,7 +99,7 @@ class Initiator { // Write bytes. The signal on the bus should appear as follows: // START + I2C Address + WRITE(0) + TX_BUFFER_BYTES + STOP // - // The timeout defines the minimum duration one may block waiting for both + // The timeout defines the maximum duration one may block waiting for both // exclusive bus access and the completion of the I2C transaction. // // Preconditions: @@ -133,7 +133,7 @@ class Initiator { // Read bytes. The signal on the bus should appear as follows: // START + I2C Address + READ(1) + RX_BUFFER_BYTES + STOP // - // The timeout defines the minimum duration one may block waiting for both + // The timeout defines the maximum duration one may block waiting for both // exclusive bus access and the completion of the I2C transaction. // // Preconditions: @@ -166,7 +166,7 @@ class Initiator { // Probes the device for an I2C ACK after only writing the address. // This is done by attempting to read a single byte from the specified device. // - // The timeout defines the minimum duration one may block waiting for both + // The timeout defines the maximum duration one may block waiting for both // exclusive bus access and the completion of the I2C transaction. // // Preconditions: diff --git a/pw_i2c/public/pw_i2c/register_device.h b/pw_i2c/public/pw_i2c/register_device.h index b71683c83..0582c4a1a 100644 --- a/pw_i2c/public/pw_i2c/register_device.h +++ b/pw_i2c/public/pw_i2c/register_device.h @@ -32,38 +32,28 @@ enum class RegisterAddressSize { k4Bytes = 4, }; -// RegisterDevice is used to write/read registers, chunks of data -// or just an array of bytes over a bus to a device. -// -// DISCLAIMER: -// It is important to note that bulk write/read may not be supported for every -// device and that it's up to the user to know the capabilities of their device. -// Users should also be aware of the register and address size and use the -// appropriate methods for their device. -// -// - WriteRegisters* -// Write to a set of registers starting at a specific address/offset. -// Endianness will be applied to data that's read or written. -// -// - WriteRegister* -// Write data to a register where the max register size is 4 bytes. -// Endianness will be applied to data that's read or written. -// -// - ReadRegisters* -// Read a set of registers starting at a specific address/offset. -// Endianness will be applied to data that's read or written. -// -// - ReadRegister* -// Read data to a register where the max register size is 4 bytes. -// Endianness will be applied to data that's read or written. +/// The common interface for I2C register devices. Contains methods to help +/// read and write the device's registers. +/// +/// @warning This interface assumes that you know how to consult your device's +/// datasheet to determine correct address sizes, data sizes, endianness, etc. class RegisterDevice : public Device { public: - // Args: - // initiator: I2C initiator for the bus the device is on. - // address: I2C device address. - // register_address_order: Endianness of the register address. - // data_order: Endianness of the data. - // register_address_size: Size of the register address. + /// This constructor specifies the endianness of the register address and + /// data separately. If your register address and data have the same + /// endianness and you'd like to specify them both with a single argument, + /// see the other `pw::i2c::RegisterDevice` constructor. + /// + /// @param[in] initiator A `pw::i2c::Initiator` instance for the bus that the + /// device is on. + /// + /// @param[in] address The address of the I2C device. + /// + /// @param[in] register_address_order The endianness of the register address. + /// + /// @param[in] data_order The endianness of the data. + /// + /// @param[in] register_address_size The size of the register address. constexpr RegisterDevice(Initiator& initiator, Address address, endian register_address_order, @@ -74,11 +64,20 @@ class RegisterDevice : public Device { data_order_(data_order), register_address_size_(register_address_size) {} - // Args: - // initiator: I2C initiator for the bus the device is on. - // address: I2C device address. - // order: Endianness of the register address and data. - // register_address_size: Size of the register address. + /// This constructor specifies the endianness of the register address and + /// data with a single argument. If your register address and data have + /// different endianness, use the other `pw::i2c::RegisterDevice` + /// constructor. + /// + /// @param[in] initiator A `pw::i2c::Initiator` instance for the bus that the + /// device is on. + /// + /// @param[in] address The address of the I2C device. + /// + /// @param[in] order The endianness of both the register address and register + /// data. + /// + /// @param[in] register_address_size The size of the register address. constexpr RegisterDevice(Initiator& initiator, Address address, endian order, @@ -88,148 +87,208 @@ class RegisterDevice : public Device { data_order_(order), register_address_size_(register_address_size) {} - // Writes data to multiple contiguous registers starting at specific register. - // WriteRegisters has byte addressable capabilities and it is up to the user - // to determine the appropriate size based on the features of the device. The - // amount of data to write is the size of the span. Endianness is taken into - // account if register_data_size is 2 bytes or 4 bytes. Both address and - // data will use the same endianness provided by the constructor. - // - // It is important to note that bulk write may not be supported for every - // device and that it's up to the user to know the capabilities of their - // device. Args: - // register_address: Register address to send. - // register_data: Data to write. - // buffer: Since we need a buffer to construct the write data that consists - // of the register address and the register data, the buffer should - // be big enough such that the two can be concatenated. - // timeout: timeout that's used for both lock and transaction. - // Returns: - // Ok: Successful. - // DeadlineExceeded: Unable to acquire exclusive Initiator access and - // complete the I2C transaction in time. - // FailedPrecondition: Interface is not initialized and/or enabled. - // Internal: Building data for the write buffer has an issue. - // InvalidArgument: Device_address is larger than the 10 bit address space. - // OutOfRange: if buffer size is too small for data and register_address. - // Unavailable: if NACK and device did not respond in time. + /// Writes data to multiple contiguous registers starting at a specific + /// register. This method is byte-addressable. + /// + /// `register_address` and `register_data` use the endianness that was + /// provided when this `pw::i2c::RegisterDevice` instance was constructed. + /// + /// @pre This method assumes that you've verified that your device supports + /// bulk writes and that `register_data` is a correct size for your device. + /// + /// @param[in] register_address The register address to begin writing at. + /// + /// @param[in] register_data The data to write. Endianness is taken into + /// account if the data is 2 or 4 bytes. + /// + /// @param[in] buffer A buffer for constructing the write data. The size of + /// this buffer must be at least as large as the size of `register_address` + /// plus the size of `register_data`. + /// + /// @param[in] timeout The maximum duration to block waiting for both + /// exclusive bus access and the completion of the I2C transaction. + /// + /// @returns A `pw::Status` object with one of the following statuses: + /// * @pw_status{OK} - The bulk write was successful. + /// * @pw_status{DEADLINE_EXCEEDED} - Unable to acquire exclusive bus access + /// and complete the transaction in time. + /// * @pw_status{FAILED_PRECONDITION} - The interface is not initialized or + /// enabled. + /// * @pw_status{INTERNAL} - An issue occurred while building + /// `register_data`. + /// * @pw_status{INVALID_ARGUMENT} - `register_address` is larger than the + /// 10-bit address space. + /// * @pw_status{OUT_OF_RANGE} - The size of `buffer` is less than the size + /// of `register_address` plus the size of `register_data`. + /// * @pw_status{UNAVAILABLE} - The device took too long to respond to the + /// NACK. Status WriteRegisters(uint32_t register_address, ConstByteSpan register_data, ByteSpan buffer, chrono::SystemClock::duration timeout); + /// Variant of `pw::i2c::RegisterDevice::WriteRegisters()` that requires + /// `register_data` to be exactly 8 bits. Status WriteRegisters8(uint32_t register_address, span<const uint8_t> register_data, ByteSpan buffer, chrono::SystemClock::duration timeout); + /// Variant of `pw::i2c::RegisterDevice::WriteRegisters()` that requires + /// `register_data` to be exactly 16 bits. Status WriteRegisters16(uint32_t register_address, span<const uint16_t> register_data, ByteSpan buffer, chrono::SystemClock::duration timeout); + /// Variant of `pw::i2c::RegisterDevice::WriteRegisters()` that requires + /// `register_data` to be exactly 32 bits. Status WriteRegisters32(uint32_t register_address, span<const uint32_t> register_data, ByteSpan buffer, chrono::SystemClock::duration timeout); - // Reads data chunk starting at specific offset or register. - // ReadRegisters has byte addressable capabilities and it is up to the user - // to determine the appropriate size based on the features of the device. The - // amount of data to read is the size of the span. Endianness is taken into - // account for the *16 and *32 bit methods. Both address and data will use - // the same endianness provided by the constructor. - // - // It is important to note that bulk read may not be supported for every - // device and that it's up to the user to know the capabilities of their - // device. Args: - // register_address: Register address to send. - // return_data: Area to read data to. - // timeout: Timeout that's used for both lock and transaction. - // Returns: - // Ok: Successful. - // DeadlineExceeded: Unable to acquire exclusive Initiator access and - // complete the I2C transaction in time. - // FailedPrecondition: Interface is not initialized and/or enabled. - // Internal: Building data for the write buffer has an issue. - // InvalidArgument: Device_address is larger than the 10 bit address space. - // Unavailable: if NACK and device did not respond in time. + /// Reads data from multiple contiguous registers starting from a specific + /// offset or register. This method is byte-addressable. + /// + /// `register_address` and `return_data` use the endianness that was + /// provided when this `pw::i2c::RegisterDevice` instance was constructed. + /// + /// @pre This method assumes that you've verified that your device supports + /// bulk reads and that `return_data` is a correct size for your device. + /// + /// @param[in] register_address The register address to begin reading at. + /// + /// @param[out] return_data The area to read the data into. The amount of + /// data that will be read is equal to the size of this span. Endianness is + /// taken into account if this span is 2 or 4 bytes. + /// + /// @param[in] timeout The maximum duration to block waiting for both + /// exclusive bus access and the completion of the I2C transaction. + /// + /// @returns A `pw::Status` object with one of the following statuses: + /// * @pw_status{OK} - The bulk read was successful. + /// * @pw_status{DEADLINE_EXCEEDED} - Unable to acquire exclusive bus access + /// and complete the transaction in time. + /// * @pw_status{FAILED_PRECONDITION} - The interface is not initialized or + /// enabled. + /// * @pw_status{INTERNAL} - An issue occurred while building `return_data`. + /// * @pw_status{INVALID_ARGUMENT} - `register_address` is larger than the + /// 10-bit address space. + /// * @pw_status{UNAVAILABLE} - The device took too long to respond to the + /// NACK. Status ReadRegisters(uint32_t register_address, ByteSpan return_data, chrono::SystemClock::duration timeout); + /// Variant of `pw::i2c::RegisterDevice::ReadRegisters()` that requires + /// `return_data` to be exactly 8 bits. Status ReadRegisters8(uint32_t register_address, span<uint8_t> return_data, chrono::SystemClock::duration timeout); + /// Variant of `pw::i2c::RegisterDevice::ReadRegisters()` that requires + /// `return_data` to be exactly 16 bits. Status ReadRegisters16(uint32_t register_address, span<uint16_t> return_data, chrono::SystemClock::duration timeout); + /// Variant of `pw::i2c::RegisterDevice::ReadRegisters()` that requires + /// `return_data` to be exactly 32 bits. Status ReadRegisters32(uint32_t register_address, span<uint32_t> return_data, chrono::SystemClock::duration timeout); - // Writes the register address first before data. - // User should be careful which WriteRegister* API is used and should use - // the one that matches their register data size if not byte addressable. - // - // Both address and data will use the same endianness provided by the - // constructor. - // Args: - // register_address: Register address to send. - // register_data: Data to write. - // timeout: Timeout that's used for both lock and transaction. - // Returns: - // Ok: Successful. - // DeadlineExceeded: Unable to acquire exclusive Initiator access and - // complete the I2C transaction in time. - // FailedPrecondition: Interface is not initialized and/or enabled. - // Internal: Building data for the write buffer has an issue. - // InvalidArgument: Device_address is larger than the 10 bit address space. - // Unavailable: if NACK and device did not respond in time. + /// Sends a register address to write to and then writes to that address. + /// + /// `register_address` and `register_data` use the endianness that was + /// provided when this `pw::i2c::RegisterDevice` instance was constructed. + /// + /// @pre This method assumes that you've verified that `register_data` is a + /// correct size for your device. + /// + /// @param[in] register_address The register address to write to. + /// + /// @param[in] register_data The data that should be written at the address. + /// The maximum allowed size is 4 bytes. + /// + /// @param[in] timeout The maximum duration to block waiting for both + /// exclusive bus access and the completion of the I2C transaction. + /// + /// @returns A `pw::Status` object with one of the following statuses: + /// * @pw_status{OK} - The write was successful. + /// * @pw_status{DEADLINE_EXCEEDED} - Unable to acquire exclusive bus access + /// and complete the transaction in time. + /// * @pw_status{FAILED_PRECONDITION} - The interface is not initialized or + /// enabled. + /// * @pw_status{INTERNAL} - An issue occurred while writing the data. + /// * @pw_status{INVALID_ARGUMENT} - `register_address` is larger than the + /// 10-bit address space. + /// * @pw_status{UNAVAILABLE} - The device took too long to respond to the + /// NACK. Status WriteRegister(uint32_t register_address, std::byte register_data, chrono::SystemClock::duration timeout); + /// Variant of `pw::i2c::RegisterDevice::WriteRegister()` that writes exactly + /// 8 bits. Status WriteRegister8(uint32_t register_address, uint8_t register_data, chrono::SystemClock::duration timeout); + /// Variant of `pw::i2c::RegisterDevince::WriteRegister()` that writes exactly + /// 16 bits. Status WriteRegister16(uint32_t register_address, uint16_t register_data, chrono::SystemClock::duration timeout); + /// Variant of `pw::i2c::RegisterDevice::WriteRegister()` that writes exactly + /// 32 bits. Status WriteRegister32(uint32_t register_address, uint32_t register_data, chrono::SystemClock::duration timeout); - // Reads data from the device after sending the register address first. - // User should be careful which ReadRegister* API is used and should use - // the one that matches their register data size if not byte addressable. - // - // Both address and data will use the same endianness provided by the - // constructor. - // Args: - // register_address: Register address to send. - // timeout: Timeout that's used for both lock and transaction. - // Returns: - // Ok: Successful. - // DeadlineExceeded: Unable to acquire exclusive Initiator access and - // complete the I2C transaction in time. - // FailedPrecondition: Interface is not initialized and/or enabled. - // Internal: Building data for the write buffer has an issue. - // InvalidArgument: Device_address is larger than the 10 bit address space. - // Unavailable: if NACK and device did not respond in time. + /// Sends a register address to read from and then reads from that address. + /// + /// `register_address` and the return data use the endianness that was + /// provided when this `pw::i2c::RegisterDevice` instance was constructed. + /// + /// @pre This method assumes that you've verified that the return data size + /// is a correct size for your device. + /// + /// @param[in] register_address The register address to read. + /// + /// @param[in] timeout The maximum duration to block waiting for both + /// exclusive bus access and the completion of the I2C transaction. + /// + /// @returns On success, a `pw::Result` object with a value representing the + /// register data and a status of @pw_status{OK}. On error, a `pw::Result` + /// object with no value and one of the following statuses: + /// * @pw_status{DEADLINE_EXCEEDED} - Unable to acquire exclusive bus access + /// and complete the transaction in time. + /// * @pw_status{FAILED_PRECONDITION} - The interface is not initialized or + /// enabled. + /// * @pw_status{INTERNAL} - An issue occurred while building the return + /// data. + /// * @pw_status{INVALID_ARGUMENT} - `register_address` is larger than the + /// 10-bit address space. + /// * @pw_status{UNAVAILABLE} - The device took too long to respond to the + /// NACK. Result<std::byte> ReadRegister(uint32_t register_address, chrono::SystemClock::duration timeout); + /// Variant of `pw::i2c::RegisterDevice::ReadRegister()` that returns exactly + /// 8 bits. Result<uint8_t> ReadRegister8(uint32_t register_address, chrono::SystemClock::duration timeout); + /// Variant of `pw::i2c::RegisterDevice::ReadRegister()` that returns exactly + /// 16 bits. Result<uint16_t> ReadRegister16(uint32_t register_address, chrono::SystemClock::duration timeout); + /// Variant of `pw::i2c::RegisterDevice::ReadRegister()` that returns exactly + /// 32 bits. Result<uint32_t> ReadRegister32(uint32_t register_address, chrono::SystemClock::duration timeout); |