#pragma once #include #include #include #include #include "esphome/core/helpers.h" namespace esphome::i2c { /// @brief Error codes returned by I2CBus and I2CDevice methods enum ErrorCode { NO_ERROR = 0, ///< No error found during execution of method ERROR_OK = 0, ///< No error found during execution of method ERROR_INVALID_ARGUMENT = 1, ///< method called invalid argument(s) ERROR_NOT_ACKNOWLEDGED = 2, ///< I2C bus acknowledgment not received ERROR_TIMEOUT = 3, ///< timeout while waiting to receive bytes ERROR_NOT_INITIALIZED = 4, ///< call method to a not initialized bus ERROR_TOO_LARGE = 5, ///< requested a transfer larger than buffers can hold ERROR_UNKNOWN = 6, ///< miscellaneous I2C error during execution ERROR_CRC = 7, ///< bytes received with a CRC error }; /// @brief This Class provides the methods to read and write bytes from an I2CBus. /// @note The I2CBus virtual class follows a *Factory design pattern* that provides all the interfaces methods required /// by clients while deferring the actual implementation of these methods to a subclasses. I2C-bus specification and /// user manual can be found here https://www.nxp.com/docs/en/user-guide/UM10204.pdf and an interesting I²C Application /// note https://www.nxp.com/docs/en/application-note/AN10216.pdf class I2CBus { public: virtual ~I2CBus() = default; /// @brief This virtual method writes bytes to an I2CBus from an array, /// then reads bytes into an array of ReadBuffer. /// @param address address of the I²C device on the i2c bus /// @param write_buffer pointer to data /// @param write_count number of bytes to write /// @param read_buffer pointer to an array to receive data /// @param read_count number of bytes to read /// transmission. False will send a restart, keeping the connection active. /// @return an i2c::ErrorCode /// @details This is a pure virtual method that must be implemented in the subclass. virtual ErrorCode write_readv(uint8_t address, const uint8_t *write_buffer, size_t write_count, uint8_t *read_buffer, size_t read_count) = 0; // Legacy functions for compatibility ErrorCode read(uint8_t address, uint8_t *buffer, size_t len) { return this->write_readv(address, nullptr, 0, buffer, len); } ErrorCode write(uint8_t address, const uint8_t *buffer, size_t len, bool stop = true) { return this->write_readv(address, buffer, len, nullptr, 0); } protected: /// @brief Scans the I2C bus for devices. Devices presence is kept in an array of std::pair /// that contains the address and the corresponding bool presence flag. void i2c_scan_(); std::vector> scan_results_; ///< array containing scan results bool scan_{false}; ///< Should we scan ? Can be set in the yaml }; class InternalI2CBus : public I2CBus { public: /// @brief Returns the I2C port number. /// @return the port number of the internal I2C bus virtual int get_port() const = 0; }; } // namespace esphome::i2c