v1.2: No internal address transmission when reading/writing to next internal address (auto-increment feature of most I2C devices)

This commit is contained in:
SMFSW 2017-11-30 22:40:42 +01:00
parent a44abc72ec
commit acfcfec7aa
6 changed files with 23 additions and 25 deletions

View File

@ -38,7 +38,7 @@ PROJECT_NAME = "Arduino Hardware I2C for AVR MCUs (plain c)"
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = 1.1 PROJECT_NUMBER = 1.2
# Using the PROJECT_BRIEF tag one can provide an optional one line description # 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 # for a project that appears at the top of each page and should give viewer a

View File

@ -15,6 +15,9 @@ Feel free to share your thoughts @ xgarmanboziax@gmail.com about:
------------ ------------
** Actual: ** Actual:
v1.2 30 Nov 2017:
- No internal address transmission when reading/writing to next internal address (make sure not to r/w last 16 address right just after init, otherwise make a dummy of address 0 just before)
v1.1 29 Nov 2017: v1.1 29 Nov 2017:
- Frequency calculation fix (thanks to TonyWilk) - Frequency calculation fix (thanks to TonyWilk)
- Set Frequency higher than Fast Mode (400KHz) will set bus to Fast Mode (frequency is up to 400KHz on AVR) - Set Frequency higher than Fast Mode (400KHz) will set bus to Fast Mode (frequency is up to 400KHz on AVR)

View File

@ -7,7 +7,7 @@
This example code is in the public domain. This example code is in the public domain.
created Jan 12 2017 created Jan 12 2017
latest mod Nov 21 2017 latest mod Nov 30 2017
by SMFSW by SMFSW
*/ */
@ -66,12 +66,12 @@ bool I2C_wr_advanced(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data,
{ {
if (bytes == 0) { return false; } if (bytes == 0) { return false; }
slave->reg_addr = reg_addr;
if (I2C_start() == false) { return false; } if (I2C_start() == false) { return false; }
if (I2C_sndAddr(slave, I2C_WRITE) == false) { return false; } if (I2C_sndAddr(slave, I2C_WRITE) == false) { return false; }
if (slave->cfg.reg_size) if ((slave->cfg.reg_size) && (reg_addr != slave->reg_addr)) // Don't send address if writing next
{ {
slave->reg_addr = reg_addr;
if (slave->cfg.reg_size >= I2C_16B_REG) // if size >2, 16bit address is used if (slave->cfg.reg_size >= I2C_16B_REG) // if size >2, 16bit address is used
{ {
if (I2C_wr8((uint8_t) (reg_addr >> 8)) == false) { return false; } if (I2C_wr8((uint8_t) (reg_addr >> 8)) == false) { return false; }
@ -102,10 +102,10 @@ bool I2C_rd_advanced(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data,
{ {
if (bytes == 0) { return false; } if (bytes == 0) { return false; }
slave->reg_addr = reg_addr; if ((slave->cfg.reg_size) && (reg_addr != slave->reg_addr)) // Don't send address if reading next
if (slave->cfg.reg_size)
{ {
slave->reg_addr = reg_addr;
if (I2C_start() == false) { return false; } if (I2C_start() == false) { return false; }
if (I2C_sndAddr(slave, I2C_WRITE) == false) { return false; } 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 (slave->cfg.reg_size >= I2C_16B_REG) // if size >2, 16bit address is used

View File

@ -1,5 +1,5 @@
name=cI2C name=cI2C
version=1.1 version=1.2
author=SMFSW <xgarmanboziax@gmail.com> author=SMFSW <xgarmanboziax@gmail.com>
maintainer=SMFSW <xgarmanboziax@gmail.com> maintainer=SMFSW <xgarmanboziax@gmail.com>
sentence=Arduino Hardware I2C for AVR (in plain c) sentence=Arduino Hardware I2C for AVR (in plain c)

View File

@ -1,18 +1,14 @@
/*!\file ci2c.c /*!\file ci2c.c
** \author SMFSW ** \author SMFSW
** \version 1.1 ** \version 1.2
** \copyright MIT SMFSW (2017) ** \copyright MIT SMFSW (2017)
** \brief arduino master i2c in plain c code ** \brief arduino master i2c in plain c code
** \warning Don't access (r/w) last 16b internal address byte alone right after init, this would lead to hazardous result (in such case, make a dummy read of addr 0 before)
**/ **/
// TODO: add interrupt vector / callback for it operations (if not too messy) // TODO: add interrupt vector / callback for it operations (if not too messy)
// TODO: consider interrupts at least for RX when slave (and TX when master) // TODO: consider interrupts at least for RX when slave (and TX when master)
// TODO: change contigous r/w operations so it doesn't send internal address again
// TODO: split functions & headers
#include "ci2c.h" #include "ci2c.h"
#define START 0x08 #define START 0x08
@ -69,7 +65,7 @@ void I2C_slave_init(I2C_SLAVE * slave, const uint8_t sl_addr, const I2C_INT_SIZE
(void) I2C_slave_set_reg_size(slave, reg_sz); (void) I2C_slave_set_reg_size(slave, reg_sz);
I2C_slave_set_rw_func(slave, (ci2c_fct_ptr) I2C_wr, I2C_WRITE); 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); I2C_slave_set_rw_func(slave, (ci2c_fct_ptr) I2C_rd, I2C_READ);
slave->reg_addr = 0; slave->reg_addr = (uint16_t) -1; // To be sure to send address on first access (warning: unless last 16b byte address is accessed alone)
slave->status = I2C_OK; slave->status = I2C_OK;
} }
@ -393,12 +389,12 @@ static bool I2C_wr(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, c
{ {
if (bytes == 0) { return false; } if (bytes == 0) { return false; }
(void) I2C_slave_set_reg_addr(slave, reg_addr);
if (I2C_start() == false) { return false; } if (I2C_start() == false) { return false; }
if (I2C_sndAddr(slave, I2C_WRITE) == false) { return false; } if (I2C_sndAddr(slave, I2C_WRITE) == false) { return false; }
if (slave->cfg.reg_size) if ((slave->cfg.reg_size) && (reg_addr != slave->reg_addr)) // Don't send address if writing next
{ {
(void) I2C_slave_set_reg_addr(slave, reg_addr);
if (slave->cfg.reg_size >= I2C_16B_REG) // if size >2, 16bit address is used if (slave->cfg.reg_size >= I2C_16B_REG) // if size >2, 16bit address is used
{ {
if (I2C_wr8((uint8_t) (reg_addr >> 8)) == false) { return false; } if (I2C_wr8((uint8_t) (reg_addr >> 8)) == false) { return false; }
@ -429,10 +425,10 @@ static bool I2C_rd(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, c
{ {
if (bytes == 0) { return false; } if (bytes == 0) { return false; }
(void) I2C_slave_set_reg_addr(slave, reg_addr); if ((slave->cfg.reg_size) && (reg_addr != slave->reg_addr)) // Don't send address if reading next
if (slave->cfg.reg_size) // If start register has to be sent first
{ {
(void) I2C_slave_set_reg_addr(slave, reg_addr);
if (I2C_start() == false) { return false; } if (I2C_start() == false) { return false; }
if (I2C_sndAddr(slave, I2C_WRITE) == false) { return false; } 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 (slave->cfg.reg_size >= I2C_16B_REG) // if size >2, 16bit address is used

View File

@ -1,8 +1,9 @@
/*!\file ci2c.h /*!\file ci2c.h
** \author SMFSW ** \author SMFSW
** \version 1.1 ** \version 1.2
** \copyright MIT SMFSW (2017) ** \copyright MIT SMFSW (2017)
** \brief arduino i2c in plain c declarations ** \brief arduino i2c in plain c declarations
** \warning Don't access (r/w) last 16b internal address byte alone right after init, this would lead to hazardous result (in such case, make a dummy read of addr 0 before)
**/ **/
/****************************************************************/ /****************************************************************/
#ifndef __CI2C_H__ #ifndef __CI2C_H__
@ -212,7 +213,6 @@ I2C_STATUS I2C_write(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data,
** \return I2C_STATUS status of write attempt ** \return I2C_STATUS status of write attempt
**/ **/
inline I2C_STATUS __attribute__((__always_inline__)) I2C_write_next(I2C_SLAVE * slave, uint8_t * data, const uint16_t bytes) { inline I2C_STATUS __attribute__((__always_inline__)) I2C_write_next(I2C_SLAVE * slave, uint8_t * data, const 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); } return I2C_write(slave, slave->reg_addr, data, bytes); }
/*!\brief This function reads data from the address specified and stores this /*!\brief This function reads data from the address specified and stores this
@ -233,7 +233,6 @@ I2C_STATUS I2C_read(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data,
** \return I2C_STATUS status of read attempt ** \return I2C_STATUS status of read attempt
**/ **/
inline I2C_STATUS __attribute__((__always_inline__)) I2C_read_next(I2C_SLAVE * slave, uint8_t * data, const uint16_t bytes) { inline I2C_STATUS __attribute__((__always_inline__)) I2C_read_next(I2C_SLAVE * slave, uint8_t * data, const 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); } return I2C_read(slave, slave->reg_addr, data, bytes); }