1
0
mirror of https://github.com/SMFSW/cI2C synced 2024-11-04 17:58:50 +01:00

Compare commits

...

23 Commits
v1.1 ... master

Author SHA1 Message Date
SMFSW
d31cca271e Updated to travis-ci.com status 2018-12-12 20:54:31 +01:00
SMFSW
e94f51f762 Removed deprecated sudo from .travis.yml 2018-12-11 19:53:01 +01:00
SMFSW
dbe9dc0a61 typo in ReleaseNotes.md 2018-06-17 18:23:58 +02:00
SMFSW
e6d3d2a8ae v1.3: Delay between retries set to 1ms 2018-05-27 15:57:06 +02:00
SMFSW
b9babcdde0 Added dedicated Doxyfile for Travis CI and updated .travis.yml to use graphviz 2018-05-04 17:43:37 +02:00
SMFSW
b079e7997d Doxyfile updated for Travis CI 2018-05-04 12:30:50 +02:00
SMFSW
3277748c49 Updated Doxyfile & .travis.yml 2018-05-04 02:23:19 +02:00
SMFSW
de152ccc5f Updated .travis.yml 2018-05-04 01:46:31 +02:00
SMFSW
fa20634862 Updated .travis.yml 2018-05-04 01:29:09 +02:00
SMFSW
4ce72eeb34 Upadated Doxyfile and .travis.yml for documentation generation 2018-05-04 00:34:44 +02:00
SMFSW
669f2c787b Updated README.md 2018-05-04 00:16:21 +02:00
SMFSW
7122bfd2de Updated README.md 2018-05-03 21:24:01 +02:00
SMFSW
66ceef30b4 Updated README.md 2018-05-03 21:15:08 +02:00
SMFSW
7a2af3d743 README.md updated 2018-05-03 20:57:08 +02:00
SMFSW
668e2ebcf5 Release Notes.md renamed to ReleaseNotes.md 2018-05-03 20:06:58 +02:00
SMFSW
93e2ffcccc Release Notes.md renamed to ReleaseNotes.md 2018-05-03 20:05:10 +02:00
SMFSW
dc8c19cb7a v1.3: Updated README.md 2018-05-03 19:33:34 +02:00
SMFSW
ee3b56f52e v1.3: updated README.md for Travis 2018-05-03 19:22:12 +02:00
SMFSW
a3ed48b1f1 v1.3: Release Notes is now markdown 2018-05-03 19:14:57 +02:00
SMFSW
0e091c3f95 updated .travis.yml 2018-05-03 19:02:27 +02:00
SMFSW
4fcef282b6 v1.3: Added Travis CI support and removed doxygen version anchors in sources 2018-05-03 18:42:08 +02:00
SMFSW
63be41402d Doxyfile 2018-03-15 01:38:58 +01:00
SMFSW
acfcfec7aa v1.2: No internal address transmission when reading/writing to next internal address (auto-increment feature of most I2C devices) 2017-11-30 22:40:42 +01:00
10 changed files with 2567 additions and 80 deletions

4
.gitignore vendored Normal file → Executable file
View File

@ -27,3 +27,7 @@
*.exe *.exe
*.out *.out
*.app *.app
#Doxygen
doxygen_sqlite3.db
html

29
.travis.yml Executable file
View File

@ -0,0 +1,29 @@
language: c
addons:
apt:
packages:
- graphviz
# Blacklist
branches:
except:
- gh-pages
env:
global:
- PRETTYNAME="cI2C: Arduino Hardware I2C for AVR (in plain c)"
- GH_REPO_NAME: cI2C
- GH_REPO_REF: github.com/SMFSW/cI2C.git
- DOXYFILE: $TRAVIS_BUILD_DIR/Doxyfile.auto
before_install:
- source <(curl -SLs https://raw.githubusercontent.com/SMFSW/travis-ci-arduino/master/install.sh)
script:
- build_avr_platforms
# Generate and deploy documentation
after_success:
- source <(curl -SLs https://raw.githubusercontent.com/SMFSW/travis-ci-arduino/master/library_check.sh)
- source <(curl -SLs https://raw.githubusercontent.com/SMFSW/travis-ci-arduino/master/doxy_gen_and_deploy.sh)

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.3
# 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
@ -244,7 +244,7 @@ TCL_SUBST =
# members will be omitted, etc. # members will be omitted, etc.
# The default value is: NO. # The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_FOR_C = YES
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored # Python sources only. Doxygen will then generate output that is more tailored
@ -748,7 +748,7 @@ WARN_IF_DOC_ERROR = YES
# parameter documentation, but not about the absence of documentation. # parameter documentation, but not about the absence of documentation.
# The default value is: NO. # The default value is: NO.
WARN_NO_PARAMDOC = NO WARN_NO_PARAMDOC = YES
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered. # a warning is encountered.
@ -770,7 +770,7 @@ WARN_FORMAT = "$file:$line: $text"
# messages should be written. If left blank the output is written to standard # messages should be written. If left blank the output is written to standard
# error (stderr). # error (stderr).
WARN_LOGFILE = WARN_LOGFILE = workdir/doxy.log
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Configuration options related to the input files # Configuration options related to the input files
@ -935,7 +935,7 @@ FILTER_SOURCE_PATTERNS =
# (index.html). This can be useful if you have a project on for instance GitHub # (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output. # and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE = USE_MDFILE_AS_MAINPAGE = README.md
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Configuration options related to source browsing # Configuration options related to source browsing
@ -1729,7 +1729,7 @@ LATEX_EXTRA_FILES =
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = NO PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate # If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES, to get a # the PDF file directly from the LaTeX files. Set this option to YES, to get a

2446
Doxyfile.auto Executable file

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,12 @@
# cI2C # cI2C [![Build Status](https://travis-ci.com/SMFSW/cI2C.svg?branch=master)](https://travis-ci.com/SMFSW/cI2C)
Arduino Hardware I2C for AVR (plain c) Arduino Hardware I2C for AVR (plain c)
Hardware I2C library for AVR MCUs (lib intended for I2C protocols development in c, for easier ports to other MCUs) Hardware I2C library for AVR MCUs (lib intended for I2C protocols development in c, for easier ports to other MCUs)
## Library choice: ## Library choice
* cI2C library implements I2C bus for AVR tagets (Uno, Nano, Mega...)
* cI2C library implements I2C bus for AVR targets (Uno, Nano, Mega...)
* you may prefer this one when: * you may prefer this one when:
* working on AVR targets * working on AVR targets
* interrupts are not needed * interrupts are not needed
@ -16,64 +18,69 @@ Hardware I2C library for AVR MCUs (lib intended for I2C protocols development in
No refactoring is required when switching between **cI2C** & **WireWrapper** libs; No refactoring is required when switching between **cI2C** & **WireWrapper** libs;
Both libs share same Typedefs, Functions & Parameters. Both libs share same Typedefs, Functions & Parameters.
## Notes: ## Notes
* cI2C is written in plain c (intentionally) * cI2C is written in plain c (intentionally)
* cI2C does not use any interrupt (yet, but soon will have to) * cI2C does not use any interrupt (yet, but soon will have to)
* cI2C is designed to act as bus Master (Slave mode will be considered in future releases) * 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 * cI2C is set to work on AVR targets only
* for other targets, you may use **WireWrapper** instead (will be using Wire) * for other targets, you may use **WireWrapper** instead (will be using Wire)
## Usage: ## Usage
This library is intended to be able to work with multiple slaves connected on the same I2C bus. 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. Thus, the I2C bus and Slaves are defined separately.
* On one hand, I2C bus has to be initialised with appropriate speed: * On one hand, I2C bus has to be initialized with appropriate speed:
* use I2C_init(speed): speed can be choosen from I2C_SPEED enum for convenience, or passing an integer as parameter * use `I2C_init(speed)`: speed can be chosen 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: * On the other hand, Slave(s) have to be defined and initialized too:
* use I2C_SLAVE typedef to declare slaves structs * use `I2C_SLAVE` typedef to declare slaves structs
* use I2C_slave_init(pSlave, addr, regsize) * use `I2C_slave_init(pSlave, addr, regsize)`
* **pSlave** is a pointer to the slave struct to initialise * `pSlave`: pointer to the slave struct to initialize
* **addr** is the slave I2C address (don't shift addr, lib takes care of that) * `addr`: 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) * `regsize`: width of internal slave registers (to be chosen from `I2C_INT_SIZE`)
* in case you need to use custom R/W procedures for a particular slave: * in case you need to use custom R/W procedures for a particular slave:
* use I2C_slave_set_rw_func(pSlave, pFunc, rw) * use `I2C_slave_set_rw_func(pSlave, pFunc, rw)`
* **pSlave** is a pointer to the slave declaration to initialise * `pSlave`: pointer to the slave declaration to initialize
* **pFunc** is a pointer to the Read or Write bypass function * `pFunc`: pointer to the Read or Write bypass function
* **rw** can be choosen from I2C_RW enum (wr=0, rd=1) * `rw`: can be chosen from `I2C_RW` enum (wr=0, rd=1)
After all inits are done, the lib can basically be used this way: After all inits are done, the lib can basically be used this way:
* I2C_read(pSlave, regaddr, pData, bytes) * `I2C_read(pSlave, regaddr, pData, bytes)`
* **pSlave** is a pointer to the slave struct to read from * `pSlave`: pointer to the slave struct to read from
* **regaddr** is the start address to read from * `regaddr`: start address to read from
* **pData** is a pointer to the place where datas read will be stored * `pData`: pointer to the place where datas read will be stored
* **bytes** number of bytes to read from slave * `bytes`: number of bytes to read from slave
* returns true if read is ok, false otherwise * returns `true` if read is ok, `false` otherwise
* I2C_write(pSlave, regaddr, pData, bytes) * `I2C_write(pSlave, regaddr, pData, bytes)`
* **pSlave** is a pointer to the slave struct to write to * `pSlave`: pointer to the slave struct to write to
* **regaddr** is the start address to write to * `regaddr`: start address to write to
* **pData** is a pointer to the block of datas to write to slave * `pData`: pointer to the block of datas to write to slave
* **bytes** number of bytes to write to slave * `bytes`: number of bytes to write to slave
* returns true if write is ok, false otherwise * returns `true` if write is ok, `false` otherwise
## Examples included
## Examples included:
following examples should work with any I2C EEPROM/FRAM with address 0x50 following examples should work with any I2C EEPROM/FRAM with address 0x50
(yet function to get Chip ID are device dependant (and will probably only work on FUJITSU devices)) (yet function to get Chip ID are device dependent (and will probably only work on FUJITSU devices))
* ci2c_master_write.ino: Write some bytes to FRAM and compare them with what's read afterwards * [ci2c_master_write.ino](examples/ci2c_master_write/ci2c_master_write.ino): Write some bytes to FRAM and compare them with what's read afterwards
* ci2c_master_read.ino: Read some bytes in FRAM * [ci2c_master_read.ino](examples/ci2c_master_read/ci2c_master_read.ino): Read some bytes in FRAM
* ci2c_advanced.ino: Redirecting slave write & read functions (to custom functions following typedef) * [ci2c_advanced.ino](examples/ci2c_advanced/ci2c_advanced.ino): Redirecting slave write & read functions (to custom functions following typedef)
Doxygen doc can be generated for the library using doxyfile ## Documentation
## Links: Doxygen doc can be generated using "Doxyfile".
Feel free to share your thoughts @ xgarmanboziax@gmail.com about:
* issues encountered See [generated documentation](https://smfsw.github.io/cI2C/)
* optimisations
* improvements & new functionalities ## Release Notes
See [release notes](ReleaseNotes.md)
## See also
**cI2C** **cI2C**
- https://github.com/SMFSW/cI2C * [cI2C github](https://github.com/SMFSW/cI2C) - C implementation of this library
- https://bitbucket.org/SMFSW/ci2c
**WireWrapper** **WireWrapper**
- https://github.com/SMFSW/WireWrapper * [WireWrapper github](https://github.com/SMFSW/WireWrapper) - Cpp implementation using Wire Wrapper
- https://bitbucket.org/SMFSW/wirewrapper

View File

@ -1,20 +1,28 @@
Arduino Hardware I2C for AVR (plain c) Arduino Hardware I2C for AVR (plain c)
2017-2017 SMFSW 2017-2018 SMFSW
- cI2C is set to work on AVR targets only - cI2C is set to work on AVR targets only
-> for other targets, you may use WireWrapper instead (will be using Wire) -> for other targets, you may use WireWrapper instead (will be using Wire)
-> cI2C & WireWrapper libs declare same structures & functions as seen from the outside -> cI2C & WireWrapper libs declare same structures & functions as seen from the outside
(switch between libs without changing anyhting but the include) (switch between libs without changing anything but the include)
Feel free to share your thoughts @ xgarmanboziax@gmail.com about: Feel free to share your thoughts @ xgarmanboziax@gmail.com about:
- issues encountered - issues encountered
- optimisations - optimizations
- improvements & new functionalities - improvements & new functionalities
------------ ------------
** Actual: ** Actual:
v1.3 13 May 2018:
- Delay between retries is now 1ms
- Adding support for unit tests and doxygen documentation generation with Travis CI
- Updated README.md
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.3
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,13 @@
/*!\file ci2c.c /*!\file ci2c.c
** \author SMFSW ** \author SMFSW
** \version 1.1 ** \copyright MIT SMFSW (2017-2018)
** \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 +64,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;
} }
@ -237,7 +232,7 @@ static I2C_STATUS I2C_comm(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t *
ack = fc(slave, reg_addr, data, bytes); ack = fc(slave, reg_addr, data, bytes);
while ((!ack) && (retry != 0)) // If com not successful, retry some more times while ((!ack) && (retry != 0)) // If com not successful, retry some more times
{ {
delay(5); delay(1);
ack = fc(slave, reg_addr, data, bytes); ack = fc(slave, reg_addr, data, bytes);
retry--; retry--;
} }
@ -393,12 +388,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 +424,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,8 @@
/*!\file ci2c.h /*!\file ci2c.h
** \author SMFSW ** \author SMFSW
** \version 1.1 ** \copyright MIT SMFSW (2017-2018)
** \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 +212,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 +232,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); }