mirror of
https://github.com/SMFSW/cI2C
synced 2024-11-25 03:04:21 +01:00
v0.5: speed enum names change
This commit is contained in:
parent
b50281b841
commit
52b3885bfc
6
Doxyfile
6
Doxyfile
@ -32,19 +32,19 @@ DOXYFILE_ENCODING = UTF-8
|
||||
# title of most generated pages and in a few other places.
|
||||
# The default value is: My Project.
|
||||
|
||||
PROJECT_NAME = "Arduino Hardware I2C for AVR (plain c)"
|
||||
PROJECT_NAME = "Arduino Hardware I2C for AVR MCUs (plain c)"
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 0.3
|
||||
PROJECT_NUMBER = 0.5
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
# quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
PROJECT_BRIEF = "Arduino Hardware I2C for AVR (plain c) documentation"
|
||||
PROJECT_BRIEF = "Arduino Hardware I2C for AVR MCUs (plain c) documentation"
|
||||
|
||||
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
||||
# in the documentation. The maximum height of the logo should not exceed 55
|
||||
|
50
README.md
50
README.md
@ -1,6 +1,20 @@
|
||||
# cI2C
|
||||
Arduino Hardware I2C for AVR (plain c)
|
||||
Hardware I2C library for AVR µcontrollers (lib intended for I2C protocols development in c, for easier ports to other µcontrollers)
|
||||
|
||||
Hardware I2C library for AVR MCUs (lib intended for I2C protocols development in c, for easier ports to other MCUs)
|
||||
|
||||
## Library choice:
|
||||
* cI2C library implements I2C bus for AVR tagets (Uno, Nano, Mega...)
|
||||
* you may prefer this one when:
|
||||
* working on AVR targets
|
||||
* interrupts are not needed
|
||||
* WireWrapper implements I2C bus for every platform that includes Wire library
|
||||
* you would have to use this one when:
|
||||
* working on non-AVR targets
|
||||
* portability is needed (using Wire library)
|
||||
|
||||
No refactoring is required when switching between **cI2C** & **WireWrapper** libs;
|
||||
Both libs share same Typedefs, Functions & Parameters.
|
||||
|
||||
## Notes:
|
||||
* cI2C is written in plain c (intentionally)
|
||||
@ -8,11 +22,38 @@ Hardware I2C library for AVR
|
||||
* cI2C is designed to act as bus Master (Slave mode will be considered in future releases)
|
||||
* cI2C is set to work on AVR targets only
|
||||
* for other targets, you may use **WireWrapper** instead (will be using Wire)
|
||||
* **cI2C** & **WireWrapper** libs declare same structures & functions as seen from the outside
|
||||
(switch between libs without changing anyhting but the include)
|
||||
|
||||
## Usage:
|
||||
refer to Doxygen generated documentation & example sketches
|
||||
This library is intended to be able to work with multiple slaves connected on the same I2C bus.
|
||||
Thus, the I2C bus and Slaves are defined separately.
|
||||
|
||||
* On one hand, I2C bus has to be initialised with appropriate speed:
|
||||
* use I2C_init(speed): speed can be choosen from I2C_SPEED enum for convenience, or passing an integer as parameter
|
||||
* On the other hand, Slave(s) have to be defined and initialised too:
|
||||
* use I2C_SLAVE typedef to declare slaves structs
|
||||
* use I2C_slave_init(pSlave, addr, regsize)
|
||||
* **pSlave** is a pointer to the slave struct to initialise
|
||||
* **addr** is the slave I2C address (don't shift addr, lib takes care of that)
|
||||
* **regsize** is the width of internal slave registers (to be choosen from I2C_INT_SIZE)
|
||||
* in case you need to use custom R/W procedures for a particular slave:
|
||||
* use I2C_slave_set_rw_func(pSlave, pFunc, rw)
|
||||
* **pSlave** is a pointer to the slave declaration to initialise
|
||||
* **pFunc** is a pointer to the Read or Write bypass function
|
||||
* **rw** can be choosen from I2C_RW enum (wr=0, rd=1)
|
||||
|
||||
After all inits are done, the lib can basically be used this way:
|
||||
* I2C_read(pSlave, regaddr, pData, bytes)
|
||||
* **pSlave** is a pointer to the slave struct to read from
|
||||
* **regaddr** is the start address to read from
|
||||
* **pData** is a pointer to the place where datas read will be stored
|
||||
* **bytes** number of bytes to read from slave
|
||||
* returns true if read is ok, false otherwise
|
||||
* I2C_write(pSlave, regaddr, pData, bytes)
|
||||
* **pSlave** is a pointer to the slave struct to write to
|
||||
* **regaddr** is the start address to write to
|
||||
* **pData** is a pointer to the block of datas to write to slave
|
||||
* **bytes** number of bytes to write to slave
|
||||
* returns true if write is ok, false otherwise
|
||||
|
||||
## Examples included:
|
||||
following examples should work with any I2C EEPROM/FRAM with address 0x50
|
||||
@ -24,7 +65,6 @@ following examples should work with any I2C EEPROM/FRAM with address 0x50
|
||||
Doxygen doc can be generated for the library using doxyfile
|
||||
|
||||
## Links:
|
||||
|
||||
Feel free to share your thoughts @ xgarmanboziax@gmail.com about:
|
||||
* issues encountered
|
||||
* optimisations
|
||||
|
@ -1,6 +1,12 @@
|
||||
Arduino Hardware I2C for AVR (plain c)
|
||||
2017-2017 SMFSW
|
||||
|
||||
- cI2C is set to work on AVR targets only
|
||||
-> for other targets, you may use WireWrapper instead (will be using Wire)
|
||||
-> cI2C & WireWrapper libs declare same structures & functions as seen from the outside
|
||||
(switch between libs without changing anyhting but the include)
|
||||
|
||||
|
||||
Feel free to share your thoughts @ xgarmanboziax@gmail.com about:
|
||||
- issues encountered
|
||||
- optimisations
|
||||
@ -9,6 +15,16 @@ Feel free to share your thoughts @ xgarmanboziax@gmail.com about:
|
||||
------------
|
||||
|
||||
** Actual:
|
||||
v0.5 31 Jan 2017:
|
||||
- refactored I2C_SPEED enum names for coherence with I2C specifications
|
||||
- High Speed mode added in I2C_SPEED enum
|
||||
|
||||
v0.4 23 Jan 2017:
|
||||
- less inlines (less warnings)
|
||||
- inlines put into header (compatibility with WireWrapper)
|
||||
- other common code between cI2C and WireWrapper changes
|
||||
- README.md updated to tell about WireWrapper library
|
||||
|
||||
v0.3 22 Jan 2017:
|
||||
- used function pointer in function parameters for convenience
|
||||
- fixed read bug for devices without register address
|
||||
|
99
ci2c.c
99
ci2c.c
@ -1,6 +1,6 @@
|
||||
/*!\file ci2c.c
|
||||
** \author SMFSW
|
||||
** \version 0.3
|
||||
** \version 0.5
|
||||
** \copyright MIT SMFSW (2017)
|
||||
** \brief arduino master i2c in plain c code
|
||||
**/
|
||||
@ -35,9 +35,6 @@
|
||||
#define clrRegBit(r, b) r &= (uint8_t) (~(1 << b)) //!< clear bit \b b in register \b r
|
||||
#define invRegBit(r, b) r ^= (1 << b) //!< invert bit \b b in register \b r
|
||||
|
||||
#define binEval(exp) ((exp) ? true : false) //!< boolean evaluation of expression \b exp
|
||||
#define nbinEval(exp) (!binEval(exp)) //!< complemented boolean evaluation of expression \b exp
|
||||
|
||||
/*! \struct i2c
|
||||
* \brief static ci2c bus config and control parameters
|
||||
*/
|
||||
@ -52,7 +49,7 @@ static struct {
|
||||
} cfg;
|
||||
uint16_t start_wait; //!< time start waiting for acknowledge
|
||||
bool busy; //!< true if already busy (in case of interrupts implementation)
|
||||
} i2c = { {0, DEF_CI2C_NB_RETRIES, DEF_CI2C_TIMEOUT }, 0, false };
|
||||
} i2c = { { (I2C_SPEED) 0, DEF_CI2C_NB_RETRIES, DEF_CI2C_TIMEOUT }, 0, false };
|
||||
|
||||
|
||||
// Needed prototypes
|
||||
@ -70,8 +67,8 @@ void I2C_slave_init(I2C_SLAVE * slave, uint8_t sl_addr, I2C_INT_SIZE reg_sz)
|
||||
{
|
||||
(void) I2C_slave_set_addr(slave, sl_addr);
|
||||
(void) I2C_slave_set_reg_size(slave, reg_sz);
|
||||
I2C_slave_set_rw_func(slave, I2C_wr, I2C_WRITE);
|
||||
I2C_slave_set_rw_func(slave, I2C_rd, I2C_READ);
|
||||
I2C_slave_set_rw_func(slave, (ci2c_fct_ptr) I2C_wr, I2C_WRITE);
|
||||
I2C_slave_set_rw_func(slave, (ci2c_fct_ptr) I2C_rd, I2C_READ);
|
||||
slave->reg_addr = 0;
|
||||
slave->status = I2C_OK;
|
||||
}
|
||||
@ -89,12 +86,11 @@ void I2C_slave_set_rw_func(I2C_SLAVE * slave, ci2c_fct_ptr func, I2C_RW rw)
|
||||
}
|
||||
|
||||
/*! \brief Change I2C slave address
|
||||
* \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)
|
||||
*/
|
||||
inline bool __attribute__((__always_inline__)) I2C_slave_set_addr(I2C_SLAVE * slave, uint8_t sl_addr)
|
||||
bool I2C_slave_set_addr(I2C_SLAVE * slave, uint8_t sl_addr)
|
||||
{
|
||||
if (sl_addr > 0x7F) { return false; }
|
||||
slave->cfg.addr = sl_addr;
|
||||
@ -102,12 +98,11 @@ inline bool __attribute__((__always_inline__)) I2C_slave_set_addr(I2C_SLAVE * sl
|
||||
}
|
||||
|
||||
/*! \brief Change I2C registers map size (for access)
|
||||
* \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)
|
||||
*/
|
||||
inline bool __attribute__((__always_inline__)) I2C_slave_set_reg_size(I2C_SLAVE * slave, I2C_INT_SIZE reg_sz)
|
||||
bool I2C_slave_set_reg_size(I2C_SLAVE * slave, I2C_INT_SIZE reg_sz)
|
||||
{
|
||||
slave->cfg.reg_size = reg_sz > I2C_16B_REG ? I2C_16B_REG : reg_sz;
|
||||
return !(reg_sz > I2C_16B_REG);
|
||||
@ -124,35 +119,6 @@ static inline void __attribute__((__always_inline__)) I2C_slave_set_reg_addr(I2C
|
||||
slave->reg_addr = reg_addr;
|
||||
}
|
||||
|
||||
/*! \brief Get I2C slave address
|
||||
* \attribute inline
|
||||
* \param [in] slave - pointer to the I2C slave structure
|
||||
* \return I2C slave address
|
||||
*/
|
||||
inline uint8_t __attribute__((__always_inline__)) I2C_slave_get_addr(I2C_SLAVE * slave)
|
||||
{
|
||||
return slave->cfg.addr;
|
||||
}
|
||||
|
||||
/*! \brief Get I2C register map size (for access)
|
||||
* \attribute inline
|
||||
* \param [in] slave - pointer to the I2C slave structure
|
||||
* \return register map using 16bits if true (1Byte otherwise)
|
||||
*/
|
||||
inline bool __attribute__((__always_inline__)) I2C_slave_get_reg_size(I2C_SLAVE * slave)
|
||||
{
|
||||
return slave->cfg.reg_size;
|
||||
}
|
||||
|
||||
/*! \brief Get I2C current register address (addr may passed this way in procedures if contigous accesses)
|
||||
* \attribute inline
|
||||
* \param [in] slave - pointer to the I2C slave structure
|
||||
* \return current register map address
|
||||
*/
|
||||
inline uint16_t __attribute__((__always_inline__)) I2C_slave_get_reg_addr(I2C_SLAVE * slave)
|
||||
{
|
||||
return slave->reg_addr;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Enable I2c module on arduino board (including pull-ups,
|
||||
@ -208,7 +174,7 @@ void I2C_reset(void)
|
||||
*/
|
||||
bool I2C_set_speed(uint16_t speed)
|
||||
{
|
||||
i2c.cfg.speed = (I2C_SPEED) ((speed == 0) ? I2C_SLOW : ((speed > I2C_FAST) ? I2C_SLOW : speed));
|
||||
i2c.cfg.speed = (I2C_SPEED) ((speed == 0) ? (uint16_t) I2C_STD : ((speed > (uint16_t) I2C_HS) ? (uint16_t) I2C_STD : speed));
|
||||
|
||||
clrRegBit(TWCR, TWEN); // Ensure i2c module is disabled
|
||||
|
||||
@ -245,10 +211,9 @@ bool I2C_set_retries(uint8_t retries)
|
||||
}
|
||||
|
||||
/*! \brief Get I2C busy status
|
||||
* \attribute inline
|
||||
* \return true if busy
|
||||
*/
|
||||
inline bool __attribute__((__always_inline__)) I2C_is_busy(void)
|
||||
bool I2C_is_busy(void)
|
||||
{
|
||||
return i2c.busy;
|
||||
}
|
||||
@ -286,58 +251,30 @@ static I2C_STATUS I2C_comm(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data,
|
||||
}
|
||||
|
||||
/*! \brief This function writes the provided data to the address specified.
|
||||
* \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
|
||||
*/
|
||||
inline I2C_STATUS __attribute__((__always_inline__)) I2C_write(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes)
|
||||
I2C_STATUS I2C_write(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes)
|
||||
{
|
||||
return I2C_comm(slave, reg_addr, data, bytes, I2C_WRITE);
|
||||
}
|
||||
|
||||
/*! \brief This inline is a wrapper to I2C_write in case of contigous operations
|
||||
* \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
|
||||
*/
|
||||
inline I2C_STATUS __attribute__((__always_inline__)) I2C_write_next(I2C_SLAVE * slave, uint8_t * data, uint16_t bytes)
|
||||
{
|
||||
// TODO: implement read next so that it doesn't have to send start register address again
|
||||
return I2C_write(slave, slave->reg_addr, data, bytes);
|
||||
}
|
||||
|
||||
/*! \brief This function reads data from the address specified and stores this
|
||||
* 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
|
||||
*/
|
||||
inline I2C_STATUS __attribute__((__always_inline__)) I2C_read(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes)
|
||||
I2C_STATUS I2C_read(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes)
|
||||
{
|
||||
return I2C_comm(slave, reg_addr, data, bytes, I2C_READ);
|
||||
}
|
||||
|
||||
/*! \brief This inline is a wrapper to I2C_read in case of contigous operations
|
||||
* \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
|
||||
*/
|
||||
inline I2C_STATUS __attribute__((__always_inline__)) I2C_read_next(I2C_SLAVE * slave, uint8_t * data, uint16_t bytes)
|
||||
{
|
||||
// TODO: implement read next so that it doesn't have to send start register address again
|
||||
return I2C_read(slave, slave->reg_addr, data, bytes);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Start i2c_timeout timer
|
||||
* \attribute inline
|
||||
@ -394,7 +331,7 @@ bool I2C_stop(void)
|
||||
* \param [in] dat - data to be sent
|
||||
* \return true if data sent acknowledged (false otherwise)
|
||||
*/
|
||||
bool I2C_snd8(uint8_t dat)
|
||||
bool I2C_wr8(uint8_t dat)
|
||||
{
|
||||
TWDR = dat;
|
||||
|
||||
@ -417,7 +354,7 @@ bool I2C_snd8(uint8_t dat)
|
||||
* \param [in] ack - true if wait for ack
|
||||
* \return true if data reception acknowledged (false otherwise)
|
||||
*/
|
||||
uint8_t I2C_rcv8(bool ack)
|
||||
uint8_t I2C_rd8(bool ack)
|
||||
{
|
||||
I2C_start_timeout();
|
||||
|
||||
@ -474,14 +411,14 @@ static bool I2C_wr(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_
|
||||
{
|
||||
if (slave->cfg.reg_size >= I2C_16B_REG) // if size >2, 16bit address is used
|
||||
{
|
||||
if (I2C_snd8((uint8_t) (reg_addr >> 8)) == false) { return false; }
|
||||
if (I2C_wr8((uint8_t) (reg_addr >> 8)) == false) { return false; }
|
||||
}
|
||||
if (I2C_snd8((uint8_t) reg_addr) == false) { return false; }
|
||||
if (I2C_wr8((uint8_t) reg_addr) == false) { return false; }
|
||||
}
|
||||
|
||||
for (uint16_t cnt = 0; cnt < bytes; cnt++)
|
||||
{
|
||||
if (I2C_snd8(*(data++)) == false) { return false; }
|
||||
if (I2C_wr8(*data++) == false) { return false; }
|
||||
slave->reg_addr++;
|
||||
}
|
||||
|
||||
@ -510,16 +447,16 @@ static bool I2C_rd(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_
|
||||
if (I2C_sndAddr(slave, I2C_WRITE) == false) { return false; }
|
||||
if (slave->cfg.reg_size >= I2C_16B_REG) // if size >2, 16bit address is used
|
||||
{
|
||||
if (I2C_snd8((uint8_t) (reg_addr >> 8)) == false) { return false; }
|
||||
if (I2C_wr8((uint8_t) (reg_addr >> 8)) == false) { return false; }
|
||||
}
|
||||
if (I2C_snd8((uint8_t) reg_addr) == false) { return false; }
|
||||
if (I2C_wr8((uint8_t) reg_addr) == false) { return false; }
|
||||
}
|
||||
if (I2C_start() == false) { return false; }
|
||||
if (I2C_sndAddr(slave, I2C_READ) == false) { return false; }
|
||||
|
||||
for (uint16_t cnt = 0; cnt < bytes; cnt++)
|
||||
{
|
||||
if (I2C_rcv8((cnt == (bytes - 1)) ? false : true) == false) { return false; }
|
||||
if (I2C_rd8((cnt == (bytes - 1)) ? false : true) == false) { return false; }
|
||||
*data++ = TWDR;
|
||||
slave->reg_addr++;
|
||||
}
|
||||
|
59
ci2c.h
59
ci2c.h
@ -1,12 +1,12 @@
|
||||
/*!\file ci2c.h
|
||||
** \author SMFSW
|
||||
** \version 0.3
|
||||
** \version 0.5
|
||||
** \copyright MIT SMFSW (2017)
|
||||
** \brief arduino i2c in plain c declarations
|
||||
**/
|
||||
/****************************************************************/
|
||||
#ifndef __CI2C_H__
|
||||
#define __CI2C_H__ "v0.3"
|
||||
#define __CI2C_H__ "v0.5"
|
||||
/****************************************************************/
|
||||
|
||||
#if defined(DOXY)
|
||||
@ -47,9 +47,10 @@ typedef enum __attribute__((__packed__)) enI2C_RW {
|
||||
* \attribute packed enum
|
||||
*/
|
||||
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_STD = 100, //!< I2C Standard (100KHz)
|
||||
I2C_FM = 400, //!< I2C Fast Mode (400KHz)
|
||||
I2C_FMP = 1000, //!< I2C Fast mode + (1MHz)
|
||||
I2C_HS = 3400 //!< I2C High Speed (3.4MHz)
|
||||
} I2C_SPEED;
|
||||
|
||||
|
||||
@ -116,42 +117,48 @@ extern void I2C_slave_init(I2C_SLAVE * slave, uint8_t sl_addr, I2C_INT_SIZE reg_
|
||||
extern void I2C_slave_set_rw_func(I2C_SLAVE * slave, ci2c_fct_ptr func, I2C_RW rw);
|
||||
|
||||
/*! \brief Change I2C slave address
|
||||
* \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)
|
||||
*/
|
||||
extern inline bool __attribute__((__always_inline__)) I2C_slave_set_addr(I2C_SLAVE * slave, uint8_t sl_addr);
|
||||
extern bool I2C_slave_set_addr(I2C_SLAVE * slave, uint8_t sl_addr);
|
||||
|
||||
/*! \brief Change I2C registers map size (for access)
|
||||
* \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)
|
||||
*/
|
||||
extern inline bool __attribute__((__always_inline__)) I2C_slave_set_reg_size(I2C_SLAVE * slave, I2C_INT_SIZE reg_sz);
|
||||
extern bool I2C_slave_set_reg_size(I2C_SLAVE * slave, I2C_INT_SIZE reg_sz);
|
||||
|
||||
/*! \brief Get I2C slave address
|
||||
* \attribute inline
|
||||
* \param [in] slave - pointer to the I2C slave structure
|
||||
* \return I2C slave address
|
||||
*/
|
||||
extern inline uint8_t __attribute__((__always_inline__)) I2C_slave_get_addr(I2C_SLAVE * slave);
|
||||
inline uint8_t __attribute__((__always_inline__)) I2C_slave_get_addr(I2C_SLAVE * slave)
|
||||
{
|
||||
return slave->cfg.addr;
|
||||
}
|
||||
|
||||
/*! \brief Get I2C register map size (for access)
|
||||
* \attribute inline
|
||||
* \param [in] slave - pointer to the I2C slave structure
|
||||
* \return register map using 16bits if true (1Byte otherwise)
|
||||
*/
|
||||
extern inline bool __attribute__((__always_inline__)) I2C_slave_get_reg_size(I2C_SLAVE * slave);
|
||||
inline bool __attribute__((__always_inline__)) I2C_slave_get_reg_size(I2C_SLAVE * slave)
|
||||
{
|
||||
return slave->cfg.reg_size;
|
||||
}
|
||||
|
||||
/*! \brief Get I2C current register address (addr may passed this way in procedures if contigous accesses)
|
||||
* \attribute inline
|
||||
* \param [in] slave - pointer to the I2C slave structure
|
||||
* \return current register map address
|
||||
*/
|
||||
extern inline uint16_t __attribute__((__always_inline__)) I2C_slave_get_reg_addr(I2C_SLAVE * slave);
|
||||
|
||||
inline uint16_t __attribute__((__always_inline__)) I2C_slave_get_reg_addr(I2C_SLAVE * slave)
|
||||
{
|
||||
return slave->reg_addr;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
/*** I2C BUS FUNCTIONS ***/
|
||||
@ -188,20 +195,18 @@ extern bool I2C_set_timeout(uint16_t timeout);
|
||||
extern bool I2C_set_retries(uint8_t retries);
|
||||
|
||||
/*! \brief Get I2C busy status
|
||||
* \attribute inline
|
||||
* \return true if busy
|
||||
*/
|
||||
extern inline bool __attribute__((__always_inline__)) I2C_is_busy(void);
|
||||
extern bool I2C_is_busy(void);
|
||||
|
||||
/*! \brief This function writes the provided data to the address specified.
|
||||
* \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
|
||||
*/
|
||||
extern inline I2C_STATUS __attribute__((__always_inline__)) I2C_write(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes);
|
||||
extern I2C_STATUS I2C_write(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes);
|
||||
|
||||
/*! \brief This inline is a wrapper to I2C_write in case of contigous operations
|
||||
* \attribute inline
|
||||
@ -210,19 +215,21 @@ extern inline I2C_STATUS __attribute__((__always_inline__)) I2C_write(I2C_SLAVE
|
||||
* \param [in] bytes - indicates how many bytes of data to write
|
||||
* \return I2C_STATUS status of write attempt
|
||||
*/
|
||||
extern inline I2C_STATUS __attribute__((__always_inline__)) I2C_write_next(I2C_SLAVE * slave, uint8_t * data, uint16_t bytes);
|
||||
|
||||
inline I2C_STATUS __attribute__((__always_inline__)) I2C_write_next(I2C_SLAVE * slave, uint8_t * data, uint16_t bytes)
|
||||
{
|
||||
// TODO: implement read next so that it doesn't have to send start register address again
|
||||
return I2C_write(slave, slave->reg_addr, data, bytes);
|
||||
}
|
||||
|
||||
/*! \brief This function reads data from the address specified and stores this
|
||||
* 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
|
||||
*/
|
||||
extern inline I2C_STATUS __attribute__((__always_inline__)) I2C_read(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes);
|
||||
extern I2C_STATUS I2C_read(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes);
|
||||
|
||||
/*! \brief This inline is a wrapper to I2C_read in case of contigous operations
|
||||
* \attribute inline
|
||||
@ -231,7 +238,11 @@ extern inline I2C_STATUS __attribute__((__always_inline__)) I2C_read(I2C_SLAVE *
|
||||
* \param [in] bytes - indicates how many bytes of data to read
|
||||
* \return I2C_STATUS status of read attempt
|
||||
*/
|
||||
extern inline I2C_STATUS __attribute__((__always_inline__)) I2C_read_next(I2C_SLAVE * slave, uint8_t * data, uint16_t bytes);
|
||||
inline I2C_STATUS __attribute__((__always_inline__)) I2C_read_next(I2C_SLAVE * slave, uint8_t * data, uint16_t bytes)
|
||||
{
|
||||
// TODO: implement read next so that it doesn't have to send start register address again
|
||||
return I2C_read(slave, slave->reg_addr, data, bytes);
|
||||
}
|
||||
|
||||
|
||||
/***********************************/
|
||||
@ -254,12 +265,12 @@ extern bool I2C_stop(void);
|
||||
* \param [in] dat - data to be sent
|
||||
* \return true if data sent acknowledged (false otherwise)
|
||||
*/
|
||||
extern bool I2C_snd8(uint8_t dat);
|
||||
extern bool I2C_wr8(uint8_t dat);
|
||||
/*! \brief Receive byte from bus
|
||||
* \param [in] ack - true if wait for ack
|
||||
* \return true if data reception acknowledged (false otherwise)
|
||||
*/
|
||||
extern uint8_t I2C_rcv8(bool ack);
|
||||
extern uint8_t I2C_rd8(bool ack);
|
||||
/*! \brief Send I2C address
|
||||
* \param [in] slave - pointer to the I2C slave structure
|
||||
* \param [in] rw - read/write transaction
|
||||
|
@ -7,7 +7,7 @@
|
||||
This example code is in the public domain.
|
||||
|
||||
created Jan 12 2017
|
||||
latest mod Jan 22 2017
|
||||
latest mod Jan 31 2017
|
||||
by SMFSW
|
||||
*/
|
||||
|
||||
@ -22,7 +22,7 @@ void setup() {
|
||||
memset(&str, blank, sizeof(str));
|
||||
|
||||
Serial.begin(115200); // start serial for output
|
||||
I2C_init(I2C_LOW); // init with low speed (400KHz)
|
||||
I2C_init(I2C_FM); // init with Fast Mode (400KHz)
|
||||
I2C_slave_init(&FRAM, 0x50, I2C_16B_REG);
|
||||
I2C_slave_set_rw_func(&FRAM, I2C_wr_advanced, I2C_WRITE);
|
||||
I2C_slave_set_rw_func(&FRAM, I2C_rd_advanced, I2C_READ);
|
||||
@ -72,14 +72,14 @@ bool I2C_wr_advanced(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint1
|
||||
{
|
||||
if (slave->cfg.reg_size >= I2C_16B_REG) // if size >2, 16bit address is used
|
||||
{
|
||||
if (I2C_snd8((uint8_t) (reg_addr >> 8)) == false) { return false; }
|
||||
if (I2C_wr8((uint8_t) (reg_addr >> 8)) == false) { return false; }
|
||||
}
|
||||
if (I2C_snd8((uint8_t) reg_addr) == false) { return false; }
|
||||
if (I2C_wr8((uint8_t) reg_addr) == false) { return false; }
|
||||
}
|
||||
|
||||
for (uint16_t cnt = 0; cnt < bytes; cnt++)
|
||||
{
|
||||
if (I2C_snd8(*(data++)) == false) { return false; }
|
||||
if (I2C_wr8(*(data++)) == false) { return false; }
|
||||
slave->reg_addr++;
|
||||
}
|
||||
|
||||
@ -108,16 +108,16 @@ bool I2C_rd_advanced(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint1
|
||||
if (I2C_sndAddr(slave, I2C_WRITE) == false) { return false; }
|
||||
if (slave->cfg.reg_size >= I2C_16B_REG) // if size >2, 16bit address is used
|
||||
{
|
||||
if (I2C_snd8((uint8_t) (reg_addr >> 8)) == false) { return false; }
|
||||
if (I2C_wr8((uint8_t) (reg_addr >> 8)) == false) { return false; }
|
||||
}
|
||||
if (I2C_snd8((uint8_t) reg_addr) == false) { return false; }
|
||||
if (I2C_wr8((uint8_t) reg_addr) == false) { return false; }
|
||||
}
|
||||
if (I2C_start() == false) { return false; }
|
||||
if (I2C_sndAddr(slave, I2C_READ) == false) { return false; }
|
||||
|
||||
for (uint16_t cnt = 0; cnt < bytes; cnt++)
|
||||
{
|
||||
if (I2C_rcv8((cnt == (bytes - 1)) ? false : true) == false) { return false; }
|
||||
if (I2C_rd8((cnt == (bytes - 1)) ? false : true) == false) { return false; }
|
||||
*data++ = TWDR;
|
||||
slave->reg_addr++;
|
||||
}
|
||||
@ -142,13 +142,13 @@ bool I2C_get_chip_id(I2C_SLAVE * slave, uint8_t * data)
|
||||
|
||||
if (I2C_start() == false) { return false; }
|
||||
if (I2C_sndAddr(&FRAM_ID, I2C_WRITE) == false) { return false; }
|
||||
if (I2C_snd8(slave->cfg.addr << 1) == false) { return false; }
|
||||
if (I2C_wr8(slave->cfg.addr << 1) == false) { return false; }
|
||||
if (I2C_start() == false) { return false; }
|
||||
if (I2C_sndAddr(&FRAM_ID, I2C_READ) == false) { return false; }
|
||||
|
||||
for (uint16_t cnt = 0; cnt < bytes; cnt++)
|
||||
{
|
||||
if (I2C_rcv8((cnt == (bytes - 1)) ? false : true) == false) { return false; }
|
||||
if (I2C_rd8((cnt == (bytes - 1)) ? false : true) == false) { return false; }
|
||||
*data++ = TWDR;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
This example code is in the public domain.
|
||||
|
||||
created Jan 12 2017
|
||||
latest mod Jan 22 2017
|
||||
latest mod Jan 31 2017
|
||||
by SMFSW
|
||||
*/
|
||||
|
||||
@ -17,7 +17,7 @@ I2C_SLAVE FRAM; // slave declaration
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200); // start serial for output
|
||||
I2C_init(I2C_LOW); // init with low speed (400KHz)
|
||||
I2C_init(I2C_FM); // init with Fast Mode (400KHz)
|
||||
I2C_slave_init(&FRAM, 0x50, I2C_16B_REG);
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
This example code is in the public domain.
|
||||
|
||||
created Jan 12 2017
|
||||
latest mod Jan 22 2017
|
||||
latest mod Jan 31 2017
|
||||
by SMFSW
|
||||
*/
|
||||
|
||||
@ -18,7 +18,7 @@ I2C_SLAVE FRAM; // slave declaration
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200); // start serial for output
|
||||
I2C_init(I2C_LOW); // init with low speed (400KHz)
|
||||
I2C_init(I2C_FM); // init with Fast Mode (400KHz)
|
||||
I2C_slave_init(&FRAM, 0x50, I2C_16B_REG);
|
||||
}
|
||||
|
||||
|
@ -44,9 +44,10 @@ I2C_WRITE LITERAL1
|
||||
I2C_OK LITERAL1
|
||||
I2C_BUSY LITERAL1
|
||||
I2C_NACK LITERAL1
|
||||
I2C_LOW LITERAL1
|
||||
I2C_SLOW LITERAL1
|
||||
I2C_FAST LITERAL1
|
||||
I2C_STD LITERAL1
|
||||
I2C_FM LITERAL1
|
||||
I2C_FMP LITERAL1
|
||||
I2C_HS LITERAL1
|
||||
I2C_NO_REG LITERAL1
|
||||
I2C_8B_REG LITERAL1
|
||||
I2C_16B_REG LITERAL1
|
||||
|
@ -1,10 +1,10 @@
|
||||
name=cI2C
|
||||
version=0.3
|
||||
version=0.5
|
||||
author=SMFSW
|
||||
maintainer=SMFSW
|
||||
sentence=Arduino Hardware I2C for AVR (in plain c)
|
||||
paragraph=Hardware I2C library for AVR µcontrollers (lib intended for I2C protocols development in c, for easier ports to other µcontrollers)
|
||||
paragraph=Hardware I2C library for AVR MCUs (lib intended for I2C protocols development in c, for easier ports to other MCUs)
|
||||
category=Communication
|
||||
url=http://playground.arduino.cc/code/CI2C
|
||||
url=https://github.com/SMFSW/cI2C
|
||||
architectures=avr
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user