From acfcfec7aa95dde2b0173eaadc9fa8576db7f320 Mon Sep 17 00:00:00 2001 From: SMFSW Date: Thu, 30 Nov 2017 22:40:42 +0100 Subject: [PATCH] v1.2: No internal address transmission when reading/writing to next internal address (auto-increment feature of most I2C devices) --- Doxyfile | 2 +- Release Notes.txt | 3 +++ examples/ci2c_advanced/ci2c_advanced.ino | 14 +++++++------- library.properties | 2 +- src/ci2c.c | 22 +++++++++------------- src/ci2c.h | 5 ++--- 6 files changed, 23 insertions(+), 25 deletions(-) diff --git a/Doxyfile b/Doxyfile index 86df2ac..258dccf 100755 --- a/Doxyfile +++ b/Doxyfile @@ -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 # 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 # for a project that appears at the top of each page and should give viewer a diff --git a/Release Notes.txt b/Release Notes.txt index 37763a8..e88ae2b 100755 --- a/Release Notes.txt +++ b/Release Notes.txt @@ -15,6 +15,9 @@ Feel free to share your thoughts @ xgarmanboziax@gmail.com about: ------------ ** 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: - 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) diff --git a/examples/ci2c_advanced/ci2c_advanced.ino b/examples/ci2c_advanced/ci2c_advanced.ino index 99ec91d..51fd128 100755 --- a/examples/ci2c_advanced/ci2c_advanced.ino +++ b/examples/ci2c_advanced/ci2c_advanced.ino @@ -7,7 +7,7 @@ This example code is in the public domain. created Jan 12 2017 - latest mod Nov 21 2017 + latest mod Nov 30 2017 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; } - slave->reg_addr = reg_addr; - if (I2C_start() == 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 (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; } - slave->reg_addr = reg_addr; - - if (slave->cfg.reg_size) + if ((slave->cfg.reg_size) && (reg_addr != slave->reg_addr)) // Don't send address if reading next { + slave->reg_addr = reg_addr; + if (I2C_start() == 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 diff --git a/library.properties b/library.properties index 03a46be..5c540bc 100755 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=cI2C -version=1.1 +version=1.2 author=SMFSW maintainer=SMFSW sentence=Arduino Hardware I2C for AVR (in plain c) diff --git a/src/ci2c.c b/src/ci2c.c index 9293724..c7fc536 100755 --- a/src/ci2c.c +++ b/src/ci2c.c @@ -1,18 +1,14 @@ /*!\file ci2c.c ** \author SMFSW -** \version 1.1 +** \version 1.2 ** \copyright MIT SMFSW (2017) ** \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: 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" #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); 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->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; } @@ -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; } - (void) I2C_slave_set_reg_addr(slave, reg_addr); - if (I2C_start() == 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 (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; } - (void) I2C_slave_set_reg_addr(slave, reg_addr); - - if (slave->cfg.reg_size) // If start register has to be sent first + if ((slave->cfg.reg_size) && (reg_addr != slave->reg_addr)) // Don't send address if reading next { + (void) I2C_slave_set_reg_addr(slave, reg_addr); + if (I2C_start() == 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 diff --git a/src/ci2c.h b/src/ci2c.h index b3196dd..59e674b 100755 --- a/src/ci2c.h +++ b/src/ci2c.h @@ -1,8 +1,9 @@ /*!\file ci2c.h ** \author SMFSW -** \version 1.1 +** \version 1.2 ** \copyright MIT SMFSW (2017) ** \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__ @@ -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 **/ 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); } /*!\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 **/ 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); }