2017-01-16 19:22:03 +01:00
|
|
|
/*!\file ci2c.h
|
|
|
|
** \author SMFSW
|
2017-01-22 18:32:00 +01:00
|
|
|
** \version 0.3
|
2017-01-16 19:22:03 +01:00
|
|
|
** \copyright MIT SMFSW (2017)
|
|
|
|
** \brief arduino i2c in plain c declarations
|
|
|
|
**/
|
|
|
|
/****************************************************************/
|
|
|
|
#ifndef __CI2C_H__
|
2017-01-22 18:32:00 +01:00
|
|
|
#define __CI2C_H__ "v0.3"
|
2017-01-16 19:22:03 +01:00
|
|
|
/****************************************************************/
|
|
|
|
|
2017-01-22 18:32:00 +01:00
|
|
|
#if defined(DOXY)
|
|
|
|
// Define gcc __attribute__ as void when Doxygen runs
|
|
|
|
#define __attribute__(a) //!< GCC attribute (ignored by Doxygen)
|
|
|
|
#endif
|
|
|
|
|
2017-01-16 19:22:03 +01:00
|
|
|
#if (ARDUINO >= 100)
|
|
|
|
#include <Arduino.h>
|
|
|
|
#else
|
|
|
|
#include <WProgram.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C"{
|
|
|
|
#endif
|
|
|
|
|
2017-01-22 18:32:00 +01:00
|
|
|
#define DEF_CI2C_NB_RETRIES 3 //!< Default cI2C transaction retries
|
|
|
|
#define DEF_CI2C_TIMEOUT 100 //!< Default cI2C timeout
|
|
|
|
|
|
|
|
|
|
|
|
/*! \enum enI2C_RW
|
|
|
|
* \brief I2C RW bit enumeration
|
|
|
|
* \attribute packed enum
|
|
|
|
*/
|
|
|
|
typedef enum __attribute__((__packed__)) enI2C_RW {
|
|
|
|
I2C_WRITE = 0, //!< I2C rw bit (write)
|
|
|
|
I2C_READ //!< I2C rw bit (read)
|
|
|
|
} I2C_RW;
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
|
2017-01-22 18:32:00 +01:00
|
|
|
/*! \enum enI2C_SPEED
|
|
|
|
* \brief I2C bus speed
|
|
|
|
* \attribute packed enum
|
|
|
|
*/
|
2017-01-16 19:22:03 +01:00
|
|
|
typedef enum __attribute__((__packed__)) enI2C_SPEED {
|
|
|
|
I2C_SLOW = 100, //!< I2C Slow speed (100KHz)
|
|
|
|
I2C_LOW = 400, //!< I2C Low speed (400KHz)
|
|
|
|
I2C_FAST = 1000 //!< I2C Fast mode (1MHz)
|
|
|
|
} I2C_SPEED;
|
|
|
|
|
|
|
|
|
2017-01-22 18:32:00 +01:00
|
|
|
/*! \enum enI2C_STATUS
|
|
|
|
* \brief I2C slave status
|
|
|
|
* \attribute packed enum
|
|
|
|
*/
|
|
|
|
typedef enum __attribute__((__packed__)) enI2C_STATUS {
|
|
|
|
I2C_OK = 0x00, //!< I2C OK
|
|
|
|
I2C_BUSY, //!< I2C Bus busy
|
|
|
|
I2C_NACK //!< I2C Not Acknowledge
|
|
|
|
} I2C_STATUS;
|
|
|
|
|
|
|
|
/*! \enum enI2C_INT_SIZE
|
|
|
|
* \brief I2C slave internal address registers size
|
|
|
|
* \attribute packed enum
|
|
|
|
*/
|
2017-01-16 19:22:03 +01:00
|
|
|
typedef enum __attribute__((__packed__)) enI2C_INT_SIZE {
|
2017-01-22 18:32:00 +01:00
|
|
|
I2C_NO_REG = 0x00, //!< Internal address registers not applicable for slave
|
|
|
|
I2C_8B_REG, //!< Slave internal address registers space is 8bits wide
|
|
|
|
I2C_16B_REG //!< Slave internal address registers space is 16bits wide
|
2017-01-16 19:22:03 +01:00
|
|
|
} I2C_INT_SIZE;
|
|
|
|
|
|
|
|
|
2017-01-22 18:32:00 +01:00
|
|
|
typedef bool (*ci2c_fct_ptr) (const void*, uint16_t, uint8_t*, uint16_t); //!< i2c read/write function pointer typedef
|
2017-01-16 19:22:03 +01:00
|
|
|
|
2017-01-22 18:32:00 +01:00
|
|
|
/*! \struct StructI2CSlave
|
|
|
|
* \brief ci2c slave config and control parameters
|
|
|
|
* \attribute packed struct
|
|
|
|
*/
|
2017-01-16 19:22:03 +01:00
|
|
|
typedef struct __attribute__((__packed__)) StructI2CSlave {
|
2017-01-22 18:32:00 +01:00
|
|
|
/*! \struct cfg
|
|
|
|
* \brief ci2c slave parameters
|
|
|
|
*/
|
2017-01-16 19:22:03 +01:00
|
|
|
struct {
|
|
|
|
uint8_t addr; //!< Slave address
|
|
|
|
I2C_INT_SIZE reg_size; //!< Slave internal registers size
|
|
|
|
ci2c_fct_ptr wr; //!< Slave write function pointer
|
|
|
|
ci2c_fct_ptr rd; //!< Slave read function pointer
|
|
|
|
} cfg;
|
|
|
|
uint16_t reg_addr; //!< Internal current register address
|
|
|
|
I2C_STATUS status; //!< Status of the last communications
|
|
|
|
} I2C_SLAVE;
|
|
|
|
|
|
|
|
|
|
|
|
/***************************/
|
|
|
|
/*** I2C SLAVE FUNCTIONS ***/
|
|
|
|
/***************************/
|
|
|
|
|
|
|
|
/*! \brief Init an I2C slave structure for cMI2C communication
|
2017-01-22 18:32:00 +01:00
|
|
|
* \param [in] slave - pointer to the I2C slave structure to init
|
|
|
|
* \param [in] sl_addr - I2C slave address
|
|
|
|
* \param [in] reg_sz - internal register map size
|
|
|
|
* \return nothing
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
|
|
|
extern void I2C_slave_init(I2C_SLAVE * slave, uint8_t sl_addr, I2C_INT_SIZE reg_sz);
|
|
|
|
|
|
|
|
/*! \brief Redirect slave I2C read/write function (if needed for advanced use)
|
2017-01-22 18:32:00 +01:00
|
|
|
* \param [in] slave - pointer to the I2C slave structure to init
|
|
|
|
* \param [in] func - pointer to read/write function to affect
|
|
|
|
* \param [in] rw - 0 = write function, 1 = read function
|
|
|
|
* \return nothing
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern void I2C_slave_set_rw_func(I2C_SLAVE * slave, ci2c_fct_ptr func, I2C_RW rw);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
/*! \brief Change I2C slave address
|
2017-01-22 18:32:00 +01:00
|
|
|
* \attribute inline
|
|
|
|
* \param [in, out] slave - pointer to the I2C slave structure to init
|
|
|
|
* \param [in] sl_addr - I2C slave address
|
|
|
|
* \return true if new address set (false if address is >7Fh)
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern inline bool __attribute__((__always_inline__)) I2C_slave_set_addr(I2C_SLAVE * slave, uint8_t sl_addr);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
/*! \brief Change I2C registers map size (for access)
|
2017-01-22 18:32:00 +01:00
|
|
|
* \attribute inline
|
|
|
|
* \param [in, out] slave - pointer to the I2C slave structure
|
|
|
|
* \param [in] reg_sz - internal register map size
|
|
|
|
* \return true if new size is correct (false otherwise and set to 16bit by default)
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern inline bool __attribute__((__always_inline__)) I2C_slave_set_reg_size(I2C_SLAVE * slave, I2C_INT_SIZE reg_sz);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
/*! \brief Get I2C slave address
|
2017-01-22 18:32:00 +01:00
|
|
|
* \attribute inline
|
|
|
|
* \param [in] slave - pointer to the I2C slave structure
|
|
|
|
* \return I2C slave address
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern inline uint8_t __attribute__((__always_inline__)) I2C_slave_get_addr(I2C_SLAVE * slave);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
/*! \brief Get I2C register map size (for access)
|
2017-01-22 18:32:00 +01:00
|
|
|
* \attribute inline
|
|
|
|
* \param [in] slave - pointer to the I2C slave structure
|
|
|
|
* \return register map using 16bits if true (1Byte otherwise)
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern inline bool __attribute__((__always_inline__)) I2C_slave_get_reg_size(I2C_SLAVE * slave);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
/*! \brief Get I2C current register address (addr may passed this way in procedures if contigous accesses)
|
2017-01-22 18:32:00 +01:00
|
|
|
* \attribute inline
|
|
|
|
* \param [in] slave - pointer to the I2C slave structure
|
|
|
|
* \return current register map address
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern inline uint16_t __attribute__((__always_inline__)) I2C_slave_get_reg_addr(I2C_SLAVE * slave);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*************************/
|
|
|
|
/*** I2C BUS FUNCTIONS ***/
|
|
|
|
/*************************/
|
|
|
|
|
|
|
|
/*! \brief Enable I2c module on arduino board (including pull-ups,
|
2017-01-22 18:32:00 +01:00
|
|
|
* enabling of ACK, and setting clock frequency)
|
|
|
|
* \param [in] speed - I2C bus speed in KHz
|
|
|
|
* \return nothing
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
|
|
|
extern void I2C_init(uint16_t speed);
|
|
|
|
|
2017-01-22 18:32:00 +01:00
|
|
|
/*! \brief Disable I2c module on arduino board (releasing pull-ups, and TWI control)
|
|
|
|
* \return nothing
|
|
|
|
*/
|
|
|
|
extern void I2C_uninit();
|
|
|
|
|
2017-01-16 19:22:03 +01:00
|
|
|
/*! \brief Change I2C frequency
|
2017-01-22 18:32:00 +01:00
|
|
|
* \param [in] speed - I2C bus speed in KHz
|
|
|
|
* \return true if change is successful (false otherwise)
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
|
|
|
extern bool I2C_set_speed(uint16_t speed);
|
|
|
|
|
|
|
|
/*! \brief Change I2C ack timeout
|
2017-01-22 18:32:00 +01:00
|
|
|
* \param [in] timeout - I2C ack timeout (500 ms max)
|
|
|
|
* \return true if change is successful (false otherwise)
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern bool I2C_set_timeout(uint16_t timeout);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
/*! \brief Change I2C message retries (in case of failure)
|
2017-01-22 18:32:00 +01:00
|
|
|
* \param [in] retries - I2C number of retries (max of 8)
|
|
|
|
* \return true if change is successful (false otherwise)
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern bool I2C_set_retries(uint8_t retries);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
/*! \brief Get I2C busy status
|
2017-01-22 18:32:00 +01:00
|
|
|
* \attribute inline
|
|
|
|
* \return true if busy
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern inline bool __attribute__((__always_inline__)) I2C_is_busy(void);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
/*! \brief This function writes the provided data to the address specified.
|
2017-01-22 18:32:00 +01:00
|
|
|
* \attribute inline
|
|
|
|
* \param [in, out] slave - pointer to the I2C slave structure
|
|
|
|
* \param [in] reg_addr - register address in register map
|
|
|
|
* \param [in] data - pointer to the first byte of a block of data to write
|
|
|
|
* \param [in] bytes - indicates how many bytes of data to write
|
|
|
|
* \return I2C_STATUS status of write attempt
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern inline I2C_STATUS __attribute__((__always_inline__)) I2C_write(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
/*! \brief This inline is a wrapper to I2C_write in case of contigous operations
|
2017-01-22 18:32:00 +01:00
|
|
|
* \attribute inline
|
|
|
|
* \param [in, out] slave - pointer to the I2C slave structure
|
|
|
|
* \param [in] data - pointer to the first byte of a block of data to write
|
|
|
|
* \param [in] bytes - indicates how many bytes of data to write
|
|
|
|
* \return I2C_STATUS status of write attempt
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern inline I2C_STATUS __attribute__((__always_inline__)) I2C_write_next(I2C_SLAVE * slave, uint8_t * data, uint16_t bytes);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*! \brief This function reads data from the address specified and stores this
|
2017-01-22 18:32:00 +01:00
|
|
|
* data in the area provided by the pointer.
|
|
|
|
* \attribute inline
|
|
|
|
* \param [in, out] slave - pointer to the I2C slave structure
|
|
|
|
* \param [in] reg_addr - register address in register map
|
|
|
|
* \param [in, out] data - pointer to the first byte of a block of data to read
|
|
|
|
* \param [in] bytes - indicates how many bytes of data to read
|
|
|
|
* \return I2C_STATUS status of read attempt
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern inline I2C_STATUS __attribute__((__always_inline__)) I2C_read(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
/*! \brief This inline is a wrapper to I2C_read in case of contigous operations
|
2017-01-22 18:32:00 +01:00
|
|
|
* \attribute inline
|
|
|
|
* \param [in, out] slave - pointer to the I2C slave structure
|
|
|
|
* \param [in] data - pointer to the first byte of a block of data to read
|
|
|
|
* \param [in] bytes - indicates how many bytes of data to read
|
|
|
|
* \return I2C_STATUS status of read attempt
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-01-22 18:32:00 +01:00
|
|
|
extern inline I2C_STATUS __attribute__((__always_inline__)) I2C_read_next(I2C_SLAVE * slave, uint8_t * data, uint16_t bytes);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
/***********************************/
|
|
|
|
/*** cI2C LOW LEVEL FUNCTIONS ***/
|
|
|
|
/*** THAT MAY BE USEFUL FOR DVPT ***/
|
|
|
|
/***********************************/
|
|
|
|
/*! \brief I2C bus reset (Release SCL and SDA lines and re-enable module)
|
2017-01-22 18:32:00 +01:00
|
|
|
* \return nothing
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
|
|
|
extern void I2C_reset(void);
|
|
|
|
/*! \brief Send start condition
|
2017-01-22 18:32:00 +01:00
|
|
|
* \return true if start condition acknowledged (false otherwise)
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
|
|
|
extern bool I2C_start(void);
|
|
|
|
/*! \brief Send stop condition
|
2017-01-22 18:32:00 +01:00
|
|
|
* \return true if stop condition acknowledged (false otherwise)
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
|
|
|
extern bool I2C_stop(void);
|
|
|
|
/*! \brief Send byte on bus
|
2017-01-22 18:32:00 +01:00
|
|
|
* \param [in] dat - data to be sent
|
|
|
|
* \return true if data sent acknowledged (false otherwise)
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
|
|
|
extern bool I2C_snd8(uint8_t dat);
|
|
|
|
/*! \brief Receive byte from bus
|
2017-01-22 18:32:00 +01:00
|
|
|
* \param [in] ack - true if wait for ack
|
|
|
|
* \return true if data reception acknowledged (false otherwise)
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
|
|
|
extern uint8_t I2C_rcv8(bool ack);
|
2017-01-22 18:32:00 +01:00
|
|
|
/*! \brief Send I2C address
|
|
|
|
* \param [in] slave - pointer to the I2C slave structure
|
|
|
|
* \param [in] rw - read/write transaction
|
|
|
|
* \return true if I2C chip address sent acknowledged (false otherwise)
|
|
|
|
*/
|
|
|
|
extern bool I2C_sndAddr(I2C_SLAVE * slave, I2C_RW rw);
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|