/*
* Copyright (c) 2015-2019, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*!****************************************************************************
* @file I2C.h
* @brief Inter-Integrated Circuit (I2C) Driver
*
* @anchor ti_drivers_I2C_Overview
* # Overview
*
* The I2C driver is designed to operate as an I2C master and will not
* function as an I2C slave. Multi-master arbitration is not supported;
* therefore, this driver assumes it is the only I2C master on the bus.
* This I2C driver's API set provides the ability to transmit and receive
* data over an I2C bus between the I2C master and I2C slave(s). The
* application is responsible for manipulating and interpreting the data.
*
*
*
* @anchor ti_drivers_I2C_Usage
* # Usage
*
* This section provides a basic @ref ti_drivers_I2C_Synopsis
* "usage summary" and a set of @ref ti_drivers_I2C_Examples "examples"
* in the form of commented code fragments. Detailed descriptions of the
* I2C APIs and their effect are provided in subsequent sections.
*
* @anchor ti_drivers_I2C_Synopsis
* ## Synopsis #
* @anchor ti_drivers_I2C_Synopsis_Code
* @code
* // Import I2C Driver definitions
* #include
*
* // Define name for an index of an I2C bus
* #define SENSORS 0
*
* // Define the slave address of device on the SENSORS bus
* #define OPT_ADDR 0x47
*
* // One-time init of I2C driver
* I2C_init();
*
* // initialize optional I2C bus parameters
* I2C_Params params;
* I2C_Params_init(¶ms);
* params.bitRate = I2C_400kHz;
*
* // Open I2C bus for usage
* I2C_Handle i2cHandle = I2C_open(SENSORS, ¶ms);
*
* // Initialize slave address of transaction
* I2C_Transaction transaction = {0};
* transaction.slaveAddress = OPT_ADDR;
*
* // Read from I2C slave device
* transaction.readBuf = data;
* transaction.readCount = sizeof(data);
* transaction.writeCount = 0;
* I2C_transfer(i2cHandle, &transaction);
*
* // Write to I2C slave device
* transaction.writeBuf = command;
* transaction.writeCount = sizeof(command);
* transaction.readCount = 0;
* I2C_transfer(i2cHandle, &transaction);
*
* // Close I2C
* I2C_close(i2cHandle);
* @endcode
*
* @anchor ti_drivers_I2C_Examples
* ## Examples
*
* @li @ref ti_drivers_I2C_Example_open "Getting an I2C bus handle"
* @li @ref ti_drivers_I2C_Example_write3bytes "Sending 3 bytes"
* @li @ref ti_drivers_I2C_Example_read5bytes "Reading 5 bytes"
* @li @ref ti_drivers_I2C_Example_writeread "Writing then reading in a single transaction"
* @li @ref ti_drivers_I2C_Example_callback "Using Callback mode"
*
* @anchor ti_drivers_I2C_Example_open
* ## Opening the I2C Driver
*
* After calling I2C_init(), the application can open an I2C instance by
* calling I2C_open().The following code example opens an I2C instance with
* default parameters by passing @p NULL for the #I2C_Params argument.
*
* @code
* I2C_Handle i2cHandle;
*
* i2cHandle = I2C_open(0, NULL);
*
* if (i2cHandle == NULL) {
* // Error opening I2C
* while (1) {}
* }
* @endcode
*
* @anchor ti_drivers_I2C_Example_write3bytes
* ## Sending three bytes of data.
*
* @code
* I2C_Transaction i2cTransaction = {0};
* uint8_t writeBuffer[3];
*
* writeBuffer[0] = 0xAB;
* writeBuffer[1] = 0xCD;
* writeBuffer[2] = 0xEF;
*
* i2cTransaction.slaveAddress = 0x50;
* i2cTransaction.writeBuf = writeBuffer;
* i2cTransaction.writeCount = 3;
* i2cTransaction.readBuf = NULL;
* i2cTransaction.readCount = 0;
*
* status = I2C_transfer(i2cHandle, &i2cTransaction);
*
* if (status == false) {
* // Unsuccessful I2C transfer
* }
* @endcode
*
* @anchor ti_drivers_I2C_Example_read5bytes
* ## Reading five bytes of data.
*
* @code
* I2C_Transaction i2cTransaction = {0};
* uint8_t readBuffer[5];
*
* i2cTransaction.slaveAddress = 0x50;
* i2cTransaction.writeBuf = NULL;
* i2cTransaction.writeCount = 0;
* i2cTransaction.readBuf = readBuffer;
* i2cTransaction.readCount = 5;
*
* status = I2C_transfer(i2cHandle, &i2cTransaction);
*
* if (status == false) {
* // Unsuccessful I2C transfer
* }
* @endcode
*
* @anchor ti_drivers_I2C_Example_writeread
* ## Writing two bytes and reading four bytes in a single transaction.
*
* @code
* I2C_Transaction i2cTransaction = {0};
* uint8_t readBuffer[4];
* uint8_t writeBuffer[2];
*
* writeBuffer[0] = 0xAB;
* writeBuffer[1] = 0xCD;
*
* i2cTransaction.slaveAddress = 0x50;
* i2cTransaction.writeBuf = writeBuffer;
* i2cTransaction.writeCount = 2;
* i2cTransaction.readBuf = readBuffer;
* i2cTransaction.readCount = 4;
*
* status = I2C_transfer(i2cHandle, &i2cTransaction);
*
* if (status == false) {
* // Unsuccessful I2C transfer
* }
* @endcode
*
* @anchor ti_drivers_I2C_Example_callback
* ## Using callback mode
* This final example shows usage of #I2C_MODE_CALLBACK, with queuing
* of multiple transactions. Because multiple transactions are simultaneously
* queued, separate #I2C_Transaction structures must be used. Each
* #I2C_Transaction will contain a custom application argument of a
* semaphore handle. The #I2C_Transaction.arg will point to the semaphore
* handle. When the callback function is called, the #I2C_Transaction.arg is
* checked for @p NULL. If this value is not @p NULL, then it can be assumed
* the @p arg is pointing to a valid semaphore handle. The semaphore handle
* is then used to call @p sem_post(). Hypothetically, this can be used to
* signal transaction completion to the task(s) that queued the
* transaction(s).
*
* @code
* void callbackFxn(I2C_Handle handle, I2C_Transaction *msg, bool status)
* {
*
* if (status == false) {
* //transaction failed
* }
*
* // Check for a semaphore handle
* if (msg->arg != NULL) {
*
* // Perform a semaphore post
* sem_post((sem_t *) (msg->arg));
* }
* }
* @endcode
*
* Snippets of the thread code that initiates the transactions are shown below.
* Note the use of multiple #I2C_Transaction structures. The handle of the
* semaphore to be posted is specified via @p i2cTransaction2.arg.
* I2C_transfer() is called three times to initiate each transaction.
* Since callback mode is used, these functions return immediately. After
* the transactions have been queued, other work can be done. Eventually,
* @p sem_wait() is called causing the thread to block until the transaction
* completes. When the transaction completes, the application's callback
* function, @p callbackFxn will be called. Once #I2C_CallbackFxn posts the
* semaphore, the thread will be unblocked and can resume execution.
*
* @code
* void thread(arg0, arg1)
* {
*
* I2C_Transaction i2cTransaction0 = {0};
* I2C_Transaction i2cTransaction1 = {0};
* I2C_Transaction i2cTransaction2 = {0};
*
* // ...
*
* i2cTransaction0.arg = NULL;
* i2cTransaction1.arg = NULL;
* i2cTransaction2.arg = semaphoreHandle;
*
* // ...
*
* I2C_transfer(i2c, &i2cTransaction0);
* I2C_transfer(i2c, &i2cTransaction1);
* I2C_transfer(i2c, &i2cTransaction2);
*
* // ...
*
* sem_wait(semaphoreHandle);
* }
* @endcode
*
*
* @anchor ti_drivers_I2C_Configuration
* # Configuration
*
* Refer to the @ref driver_configuration "Driver's Configuration" section
* for driver configuration information.
*
******************************************************************************
*/
#ifndef ti_drivers_I2C__include
#define ti_drivers_I2C__include
/*! @cond */
#include
#include
#include
/*! @endcond */
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup I2C_CONTROL I2C_control command and status codes
* These I2C macros are reservations for I2C.h
* @{
*/
/*! @cond */
/*!
* @private
* Common I2C_control command code reservation offset.
* I2C driver implementations should offset command codes with
* #I2C_CMD_RESERVED growing positively
*
* Example implementation specific command codes:
* @code
* #define I2CXYZ_CMD_COMMAND0 I2C_CMD_RESERVED + 0
* #define I2CXYZ_CMD_COMMAND1 I2C_CMD_RESERVED + 1
* @endcode
*/
#define I2C_CMD_RESERVED (32)
/*!
* @private
* Common I2C_control status code reservation offset.
* I2C driver implementations should offset status codes with
* #I2C_STATUS_RESERVED growing negatively.
*
* Example implementation specific status codes:
* @code
* #define I2CXYZ_STATUS_ERROR0 I2C_STATUS_RESERVED - 0
* #define I2CXYZ_STATUS_ERROR1 I2C_STATUS_RESERVED - 1
* #define I2CXYZ_STATUS_ERROR2 I2C_STATUS_RESERVED - 2
* @endcode
*/
#define I2C_STATUS_RESERVED (-32)
/*! @endcond */
/**
* @defgroup I2C_STATUS Status Codes
* I2C_STATUS_* macros are general status codes returned by I2C_control()
* @{
* @ingroup I2C_CONTROL
*/
/*!
* @brief Successful status code returned by I2C_control().
*
* I2C_control() returns #I2C_STATUS_SUCCESS if the control code was executed
* successfully.
*/
#define I2C_STATUS_SUCCESS (0)
/*!
* @brief Generic error status code returned by I2C_control().
*
* I2C_control() returns #I2C_STATUS_ERROR if the control code was not executed
* successfully.
*/
#define I2C_STATUS_ERROR (-1)
/*!
* @brief An error status code returned by I2C_control() for undefined
* command codes.
*
* I2C_control() returns #I2C_STATUS_UNDEFINEDCMD if the control code is not
* recognized by the driver implementation.
*/
#define I2C_STATUS_UNDEFINEDCMD (-2)
/** @}*/
/**
* @defgroup I2C_CMD Command Codes
* I2C_CMD_* macros are general command codes for I2C_control(). Not all I2C
* driver implementations support these command codes.
* @{
* @ingroup I2C_CONTROL
*/
/* Add I2C_CMD_ here */
/** @} end I2C commands */
/** @} end I2C_CONTROL group */
/*!
* @brief A handle that is returned from an I2C_open() call.
*/
typedef struct I2C_Config_ *I2C_Handle;
/*!
* @brief Defines a transaction to be used with I2C_transfer()
*
* @sa I2C_transfer()
*/
typedef struct {
/*!
* Pointer to a buffer of at least #I2C_Transaction.writeCount bytes.
* If #I2C_Transaction.writeCount is 0, this pointer is not used.
*/
void *writeBuf;
/*!
* Number of bytes to write to the I2C slave device. A value of 0
* indicates no data will be written to the slave device and only a read
* will occur. If this value
* is not 0, the driver will always perform the write transfer first.
* The data written to the I2C bus is preceded by the
* #I2C_Transaction.slaveAddress with the write bit set. If
* @p writeCount bytes are successfully sent and
* acknowledged, the transfer will complete or perform a read--depending
* on #I2C_Transaction.readCount.
*
* @note Both #I2C_Transaction.writeCount and #I2C_Transaction.readCount
* can not be 0.
*/
size_t writeCount;
/*!
* Pointer to a buffer of at least #I2C_Transaction.readCount bytes.
* If #I2C_Transaction.readCount is 0, this pointer is not used.
*/
void *readBuf;
/*!
* Number of bytes to read from the I2C slave device. A value of 0
* indicates no data will be read and only a write will occur. If
* #I2C_Transaction.writeCount is not 0, this driver will perform the
* write first, followed by the read. The data read from the bus is
* preceded by the #I2C_Transaction.slaveAddress with the read bit set.
* After @p readCount bytes are successfully read, the transfer will
* complete.
*
* @note Both #I2C_Transaction.writeCount and #I2C_Transaction.readCount
* can not be 0.
*/
size_t readCount;
/*!
* I2C slave address used for the transaction. The slave address is
* the first byte transmitted during an I2C transfer. The read/write bit
* is automatically set based upon the #I2C_Transaction.writeCount and
* #I2C_Transaction.readCount.
*/
uint_least8_t slaveAddress;
/*!
* Pointer to a custom argument to be passed to the #I2C_CallbackFxn
* function via the #I2C_Transaction structure.
*
* @note The #I2C_CallbackFxn function is only called when operating in
* #I2C_MODE_CALLBACK.
*
* @sa #I2C_MODE_CALLBACK
* @sa #I2C_CallbackFxn
*/
void *arg;
/*!
* @private This is reserved for use by the driver and must never be
* modified by the application.
*/
void *nextPtr;
} I2C_Transaction;
/*!
* @brief Return behavior of I2C_Transfer() specified in the #I2C_Params.
*
* This enumeration defines the return behaviors for a call to I2C_transfer().
*
* @sa #I2C_Params
*/
typedef enum {
/*!
* In #I2C_MODE_BLOCKING, calls to I2C_transfer() block until the
* #I2C_Transaction completes. Other threads calling I2C_transfer()
* while a transaction is in progress are also placed into a blocked
* state. If multiple threads are blocked, the thread with the highest
* priority will be unblocked first. This implies that arbitration
* will not be executed in chronological order.
*
* @note When using #I2C_MODE_BLOCKING, I2C_transfer() must be called
* from a thread context.
*/
I2C_MODE_BLOCKING,
/*!
* In #I2C_MODE_CALLBACK, calls to I2C_transfer() return immediately. The
* application's callback function, #I2C_Params.transferCallbackFxn, is
* called when the transaction is complete. Sequential calls to
* I2C_transfer() will place #I2C_Transaction structures into an
* internal queue. Queued transactions are automatically started after the
* previous transaction has completed. This queuing occurs regardless of
* any error state from previous transactions. The transactions are
* always executed in chronological order. The
* #I2C_Params.transferCallbackFxn function will be called asynchronously
* as each transaction is completed.
*/
I2C_MODE_CALLBACK
} I2C_TransferMode;
/*!
* @brief The definition of a callback function.
*
* When operating in #I2C_MODE_CALLBACK, the callback function is called
* when an I2C_transfer() completes. The application is responsible for
* declaring an #I2C_CallbackFxn function and providing a pointer
* in #I2C_Params.transferCallbackFxn.
*
* @warning The callback function is called from an interrupt context.
*
* @param[out] handle #I2C_Handle used with the initial call to
* I2C_transfer()
*
* @param[out] transaction Pointer to the #I2C_Transaction structure used
* with the initial call to I2C_transfer(). This structure also contains the
* custom argument specified by @p transaction.arg.
*
* @param[out] transferStatus Boolean indicating if the I2C transaction
* was successful. If @p true, the transaction was successful. If @p false,
* the transaction failed.
*/
typedef void (*I2C_CallbackFxn)(I2C_Handle handle, I2C_Transaction *transaction,
bool transferStatus);
/*!
* @brief Bit rate for an I2C driver instance specified in the #I2C_Params.
*
* This enumeration defines the bit rates used with an I2C_transfer().
*
* @note You must check that the device specific implementation supports the
* desired #I2C_BitRate.
*/
typedef enum {
I2C_100kHz = 0, /*!< I2C Standard-mode. Up to 100 kbit/s. */
I2C_400kHz = 1, /*!< I2C Fast-mode. Up to 400 kbit/s. */
I2C_1000kHz = 2, /*!< I2C Fast-mode Plus. Up to 1Mbit/s. */
I2C_3330kHz = 3, /*!< I2C High-speed mode. Up to 3.4Mbit/s. */
I2C_3400kHz = 3, /*!< I2C High-speed mode. Up to 3.4Mbit/s. */
} I2C_BitRate;
/*!
* @brief I2C parameters used with I2C_open().
*
* I2C_Params_init() must be called prior to setting fields in
* this structure.
*
* @sa I2C_Params_init()
*/
typedef struct {
/*! #I2C_TransferMode for all I2C transfers. */
I2C_TransferMode transferMode;
/*!
* Pointer to a #I2C_CallbackFxn to be invoked after a
* I2C_transfer() completes when operating in #I2C_MODE_CALLBACK.
*/
I2C_CallbackFxn transferCallbackFxn;
/*!
* A #I2C_BitRate specifying the frequency at which the I2C peripheral
* will transmit data during a I2C_transfer().
*/
I2C_BitRate bitRate;
/*! Pointer to a device specific extension of the #I2C_Params */
void *custom;
} I2C_Params;
/*!
* @private
* @brief A function pointer to a driver-specific implementation of
* I2C_cancel().
*/
typedef void (*I2C_CancelFxn) (I2C_Handle handle);
/*!
* @private
* @brief A function pointer to a driver-specific implementation of
* I2C_close().
*/
typedef void (*I2C_CloseFxn) (I2C_Handle handle);
/*!
* @private
* @brief A function pointer to a driver-specific implementation of
* I2C_control().
*/
typedef int_fast16_t (*I2C_ControlFxn) (I2C_Handle handle, uint_fast16_t cmd,
void *controlArg);
/*!
* @private
* @brief A function pointer to a driver-specific implementation of
* I2C_init().
*/
typedef void (*I2C_InitFxn) (I2C_Handle handle);
/*!
* @private
* @brief A function pointer to a driver-specific implementation of
* I2C_open().
*/
typedef I2C_Handle (*I2C_OpenFxn) (I2C_Handle handle, I2C_Params *params);
/*!
* @private
* @brief A function pointer to a driver-specific implementation of
* I2C_transfer().
*/
typedef bool (*I2C_TransferFxn) (I2C_Handle handle,
I2C_Transaction *transaction);
/*!
* @brief The definition of an I2C function table that contains the
* required set of functions to control a specific I2C driver
* implementation.
*/
typedef struct I2C_FxnTable_ {
I2C_CancelFxn cancelFxn;
I2C_CloseFxn closeFxn;
I2C_ControlFxn controlFxn;
I2C_InitFxn initFxn;
I2C_OpenFxn openFxn;
I2C_TransferFxn transferFxn;
} I2C_FxnTable;
/*!
* @brief I2C driver's custom @ref driver_configuration "configuration"
* structure.
*
* @sa I2C_init()
* @sa I2C_open()
*/
typedef struct I2C_Config_ {
/*! Pointer to a @ref driver_function_table "function pointer table"
* with driver-specific implementations of I2C APIs */
I2C_FxnTable const *fxnTablePtr;
/*! Pointer to a driver specific @ref driver_objects "data object". */
void *object;
/*! Pointer to a driver specific @ref driver_hardware_attributes
* "hardware attributes structure". */
void const *hwAttrs;
} I2C_Config;
/*!
* @brief Cancels all I2C transfers
*
* This function will cancel asynchronous I2C_transfer() operations, and is
* applicable only for #I2C_MODE_CALLBACK mode. The in progress transfer, as
* well as any queued transfers, will be canceled. The individual callback
* functions for each transfer will be called in chronological order. The
* callback functions are called in the same context as the I2C_cancel().
*
* @pre I2C_Transfer() has been called.
*
* @param[in] handle An #I2C_Handle returned from I2C_open()
*
* @note Different I2C slave devices will behave differently when an
* in-progress transfer fails and needs to be canceled. The slave
* may need to be reset, or there may be other slave-specific
* steps that can be used to successfully resume communication.
*
* @sa I2C_transfer()
* @sa #I2C_MODE_CALLBACK
*/
extern void I2C_cancel(I2C_Handle handle);
/*!
* @brief Function to close an I2C driver instance
*
* @pre I2C_open() has been called.
*
* @param[in] handle An #I2C_Handle returned from I2C_open()
*/
extern void I2C_close(I2C_Handle handle);
/*!
* @brief Function performs implementation specific features on a
* driver instance.
*
* @pre I2C_open() has to be called first.
*
* @param[in] handle An #I2C_Handle returned from I2C_open()
*
* @param[in] cmd A command value defined by the device specific
* implementation
*
* @param[in] controlArg An optional R/W (read/write) argument that is
* accompanied with @p cmd
*
* @return Implementation specific return codes. Negative values indicate
* unsuccessful operations.
*
* @retval #I2C_STATUS_SUCCESS The call was successful.
* @retval #I2C_STATUS_UNDEFINEDCMD The @p cmd value is not supported by
* the device specific implementation.
*/
extern int_fast16_t I2C_control(I2C_Handle handle, uint_fast16_t cmd,
void *controlArg);
/*!
* @brief Function to initialize the I2C driver.
*
* This function must also be called before any otherI2C driver APIs.
*/
extern void I2C_init(void);
/*!
* @brief Open an I2C driver instance.
*
* @pre I2C_init() has been called.
*
* @param[in] index Index in the @p I2C_Config[] array.
*
* @param[in] params Pointer to an initialized #I2C_Params structure.
* If NULL, the default #I2C_Params values are used.
*
* @return An #I2C_Handle on success, or @p NULL on an error.
*
* @sa I2C_init()
* @sa I2C_close()
*/
extern I2C_Handle I2C_open(uint_least8_t index, I2C_Params *params);
/*!
* @brief Initialize an #I2C_Params structure to its default values.
*
* @param[in] params A pointer to #I2C_Params structure for
* initialization.
*
* Defaults values are:
* @arg #I2C_Params.transferMode = #I2C_MODE_BLOCKING
* @arg #I2C_Params.transferCallbackFxn = @p NULL
* @arg #I2C_Params.bitRate = #I2C_100kHz
* @arg #I2C_Params.custom = @p NULL
*/
extern void I2C_Params_init(I2C_Params *params);
/*!
* @brief Perform an I2C transaction with an I2C slave peripheral.
*
* This function will perform an I2C transfer, as specified by an
* #I2C_Transaction structure.
*
* @note When using #I2C_MODE_BLOCKING, this must be called from a thread
* context.
*
* @param[in] handle An #I2C_Handle returned from I2C_open()
*
* @param[in] transaction A pointer to an #I2C_Transaction. The application
* is responsible for allocating and initializing an #I2C_Transaction
* structure prior to passing it to I2C_Transfer(). This
* structure must persist in memory unmodified until the transfer is complete.
*
* @note #I2C_Transaction structures cannot be re-used until the previous
* transaction has completed.
*
* @return In #I2C_MODE_BLOCKING: @p true for a successful transfer; @p false
* for an error (for example, an I2C bus fault (NACK)).
*
* @return In #I2C_MODE_CALLBACK: always @p true. The #I2C_CallbackFxn @p bool
* argument will be @p true to indicate success, and @p false to
* indicate an error.
*
* @pre I2C_open() has been called.
*
* @sa I2C_open()
* @sa I2C_Transaction
*/
extern bool I2C_transfer(I2C_Handle handle, I2C_Transaction *transaction);
#ifdef __cplusplus
}
#endif
#endif /* ti_drivers_I2C__include */