mirror of
https://github.com/SMFSW/cI2C
synced 2024-11-11 13:18:51 +01:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d31cca271e | ||
|
e94f51f762 | ||
|
dbe9dc0a61 | ||
|
e6d3d2a8ae | ||
|
b9babcdde0 | ||
|
b079e7997d | ||
|
3277748c49 | ||
|
de152ccc5f | ||
|
fa20634862 | ||
|
4ce72eeb34 | ||
|
669f2c787b | ||
|
7122bfd2de | ||
|
66ceef30b4 | ||
|
7a2af3d743 | ||
|
668e2ebcf5 | ||
|
93e2ffcccc | ||
|
dc8c19cb7a | ||
|
ee3b56f52e | ||
|
a3ed48b1f1 | ||
|
0e091c3f95 | ||
|
4fcef282b6 | ||
|
63be41402d | ||
|
acfcfec7aa | ||
|
a44abc72ec | ||
|
ed7030cffc |
4
.gitignore
vendored
Normal file → Executable file
4
.gitignore
vendored
Normal file → Executable file
@ -27,3 +27,7 @@
|
|||||||
*.exe
|
*.exe
|
||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
|
|
||||||
|
#Doxygen
|
||||||
|
doxygen_sqlite3.db
|
||||||
|
html
|
29
.travis.yml
Executable file
29
.travis.yml
Executable 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)
|
12
Doxyfile
12
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
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 0.6
|
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
2446
Doxyfile.auto
Executable file
File diff suppressed because it is too large
Load Diff
95
README.md
95
README.md
@ -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
|
|
||||||
|
@ -1,20 +1,37 @@
|
|||||||
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:
|
||||||
|
- 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)
|
||||||
|
- I2C_set_xxx now returns values applied, not bool
|
||||||
|
|
||||||
|
v1.0 21 Nov 2017:
|
||||||
|
- Added const qualifier for function parameters
|
||||||
|
- Return from comm functions if bytes to R/W set to 0
|
||||||
|
|
||||||
v0.6 12 Jul 2017:
|
v0.6 12 Jul 2017:
|
||||||
- compliance with Arduino v1.5+ IDE source located in src subfolder
|
- compliance with Arduino v1.5+ IDE source located in src subfolder
|
||||||
|
|
@ -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 Jan 31 2017
|
latest mod Nov 30 2017
|
||||||
by SMFSW
|
by SMFSW
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -24,8 +24,8 @@ void setup() {
|
|||||||
Serial.begin(115200); // start serial for output
|
Serial.begin(115200); // start serial for output
|
||||||
I2C_init(I2C_FM); // init with Fast Mode (400KHz)
|
I2C_init(I2C_FM); // init with Fast Mode (400KHz)
|
||||||
I2C_slave_init(&FRAM, 0x50, I2C_16B_REG);
|
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, (ci2c_fct_ptr) I2C_wr_advanced, I2C_WRITE);
|
||||||
I2C_slave_set_rw_func(&FRAM, I2C_rd_advanced, I2C_READ);
|
I2C_slave_set_rw_func(&FRAM, (ci2c_fct_ptr) I2C_rd_advanced, I2C_READ);
|
||||||
|
|
||||||
I2C_get_chip_id(&FRAM, &str[0]);
|
I2C_get_chip_id(&FRAM, &str[0]);
|
||||||
|
|
||||||
@ -62,14 +62,16 @@ void loop() {
|
|||||||
* \param [in] bytes - indicates how many bytes of data to write
|
* \param [in] bytes - indicates how many bytes of data to write
|
||||||
* \return Boolean indicating success/fail of write attempt
|
* \return Boolean indicating success/fail of write attempt
|
||||||
*/
|
*/
|
||||||
bool I2C_wr_advanced(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes)
|
bool I2C_wr_advanced(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes)
|
||||||
{
|
{
|
||||||
slave->reg_addr = reg_addr;
|
if (bytes == 0) { return false; }
|
||||||
|
|
||||||
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; }
|
||||||
@ -96,14 +98,14 @@ bool I2C_wr_advanced(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint1
|
|||||||
* \param [in] bytes - indicates how many bytes of data to read
|
* \param [in] bytes - indicates how many bytes of data to read
|
||||||
* \return Boolean indicating success/fail of read attempt
|
* \return Boolean indicating success/fail of read attempt
|
||||||
*/
|
*/
|
||||||
bool I2C_rd_advanced(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes)
|
bool I2C_rd_advanced(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes)
|
||||||
{
|
{
|
||||||
slave->reg_addr = reg_addr;
|
if (bytes == 0) { return false; }
|
||||||
|
|
||||||
if (bytes == 0) { bytes = 1; }
|
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
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
name=cI2C
|
name=cI2C
|
||||||
version=0.6
|
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)
|
||||||
|
363
src/ci2c.c
363
src/ci2c.c
@ -1,18 +1,13 @@
|
|||||||
/*!\file ci2c.c
|
/*!\file ci2c.c
|
||||||
** \author SMFSW
|
** \author SMFSW
|
||||||
** \version 0.6
|
** \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
|
||||||
@ -35,13 +30,13 @@
|
|||||||
#define clrRegBit(r, b) r &= (uint8_t) (~(1 << b)) //!< clear bit \b b in register \b r
|
#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 invRegBit(r, b) r ^= (1 << b) //!< invert bit \b b in register \b r
|
||||||
|
|
||||||
/*! \struct i2c
|
/*!\struct i2c
|
||||||
* \brief static ci2c bus config and control parameters
|
** \brief static ci2c bus config and control parameters
|
||||||
*/
|
**/
|
||||||
static struct {
|
static struct {
|
||||||
/*! \struct cfg
|
/*!\struct cfg
|
||||||
* \brief ci2c bus parameters
|
** \brief ci2c bus parameters
|
||||||
*/
|
**/
|
||||||
struct {
|
struct {
|
||||||
I2C_SPEED speed; //!< i2c bus speed
|
I2C_SPEED speed; //!< i2c bus speed
|
||||||
uint8_t retries; //!< i2c message retries when fail
|
uint8_t retries; //!< i2c message retries when fail
|
||||||
@ -53,80 +48,78 @@ static struct {
|
|||||||
|
|
||||||
|
|
||||||
// Needed prototypes
|
// Needed prototypes
|
||||||
static bool I2C_wr(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes);
|
static bool I2C_wr(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes);
|
||||||
static bool I2C_rd(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes);
|
static bool I2C_rd(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes);
|
||||||
|
|
||||||
|
|
||||||
/*! \brief Init an I2C slave structure for cMI2C communication
|
/*!\brief Init an I2C slave structure for cMI2C communication
|
||||||
* \param [in] slave - pointer to the I2C slave structure to init
|
** \param [in] slave - pointer to the I2C slave structure to init
|
||||||
* \param [in] sl_addr - I2C slave address
|
** \param [in] sl_addr - I2C slave address
|
||||||
* \param [in] reg_sz - internal register map size
|
** \param [in] reg_sz - internal register map size
|
||||||
* \return nothing
|
** \return nothing
|
||||||
*/
|
**/
|
||||||
void I2C_slave_init(I2C_SLAVE * slave, uint8_t sl_addr, I2C_INT_SIZE reg_sz)
|
void I2C_slave_init(I2C_SLAVE * slave, const uint8_t sl_addr, const I2C_INT_SIZE reg_sz)
|
||||||
{
|
{
|
||||||
(void) I2C_slave_set_addr(slave, sl_addr);
|
(void) I2C_slave_set_addr(slave, sl_addr);
|
||||||
(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Redirect slave I2C read/write function (if needed for advanced use)
|
/*!\brief Redirect slave I2C read/write function (if needed for advanced use)
|
||||||
* \param [in] slave - pointer to the I2C slave structure to init
|
** \param [in] slave - pointer to the I2C slave structure to init
|
||||||
* \param [in] func - pointer to read/write function to affect
|
** \param [in] func - pointer to read/write function to affect
|
||||||
* \param [in] rw - 0 = write function, 1 = read function
|
** \param [in] rw - 0 = write function, 1 = read function
|
||||||
* \return nothing
|
** \return nothing
|
||||||
*/
|
**/
|
||||||
void I2C_slave_set_rw_func(I2C_SLAVE * slave, ci2c_fct_ptr func, I2C_RW rw)
|
void I2C_slave_set_rw_func(I2C_SLAVE * slave, const ci2c_fct_ptr func, const I2C_RW rw)
|
||||||
{
|
{
|
||||||
ci2c_fct_ptr * pfc = (ci2c_fct_ptr*) (rw ? &slave->cfg.rd : &slave->cfg.wr);
|
ci2c_fct_ptr * pfc = (ci2c_fct_ptr*) (rw ? &slave->cfg.rd : &slave->cfg.wr);
|
||||||
*pfc = func;
|
*pfc = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Change I2C slave address
|
/*!\brief Change I2C slave address
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure to init
|
** \param [in, out] slave - pointer to the I2C slave structure to init
|
||||||
* \param [in] sl_addr - I2C slave address
|
** \param [in] sl_addr - I2C slave address
|
||||||
* \return true if new address set (false if address is >7Fh)
|
** \return true if new address set (false if address is >7Fh)
|
||||||
*/
|
**/
|
||||||
bool I2C_slave_set_addr(I2C_SLAVE * slave, uint8_t sl_addr)
|
bool I2C_slave_set_addr(I2C_SLAVE * slave, const uint8_t sl_addr)
|
||||||
{
|
{
|
||||||
if (sl_addr > 0x7F) { return false; }
|
if (sl_addr > 0x7F) { return false; }
|
||||||
slave->cfg.addr = sl_addr;
|
slave->cfg.addr = sl_addr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Change I2C registers map size (for access)
|
/*!\brief Change I2C registers map size (for access)
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure
|
** \param [in, out] slave - pointer to the I2C slave structure
|
||||||
* \param [in] reg_sz - internal register map size
|
** \param [in] reg_sz - internal register map size
|
||||||
* \return true if new size is correct (false otherwise and set to 16bit by default)
|
** \return true if new size is correct (false otherwise and set to 16bit by default)
|
||||||
*/
|
**/
|
||||||
bool I2C_slave_set_reg_size(I2C_SLAVE * slave, I2C_INT_SIZE reg_sz)
|
bool I2C_slave_set_reg_size(I2C_SLAVE * slave, const I2C_INT_SIZE reg_sz)
|
||||||
{
|
{
|
||||||
slave->cfg.reg_size = reg_sz > I2C_16B_REG ? I2C_16B_REG : reg_sz;
|
slave->cfg.reg_size = reg_sz > I2C_16B_REG ? I2C_16B_REG : reg_sz;
|
||||||
return !(reg_sz > I2C_16B_REG);
|
return !(reg_sz > I2C_16B_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Set I2C current register address
|
/*!\brief Set I2C current register address
|
||||||
* \attribute inline
|
** \attribute inline
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure
|
** \param [in, out] slave - pointer to the I2C slave structure
|
||||||
* \param [in] reg_addr - register address
|
** \param [in] reg_addr - register address
|
||||||
* \return nothing
|
** \return nothing
|
||||||
*/
|
**/
|
||||||
static inline void __attribute__((__always_inline__)) I2C_slave_set_reg_addr(I2C_SLAVE * slave, uint16_t reg_addr)
|
static inline void __attribute__((__always_inline__)) I2C_slave_set_reg_addr(I2C_SLAVE * slave, const uint16_t reg_addr) {
|
||||||
{
|
slave->reg_addr = reg_addr; }
|
||||||
slave->reg_addr = reg_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! \brief Enable I2c module on arduino board (including pull-ups,
|
/*!\brief Enable I2c module on arduino board (including pull-ups,
|
||||||
* enabling of ACK, and setting clock frequency)
|
* enabling of ACK, and setting clock frequency)
|
||||||
* \param [in] speed - I2C bus speed in KHz
|
** \param [in] speed - I2C bus speed in KHz
|
||||||
* \return nothing
|
** \return nothing
|
||||||
*/
|
**/
|
||||||
void I2C_init(uint16_t speed)
|
void I2C_init(const uint16_t speed)
|
||||||
{
|
{
|
||||||
// Set SDA and SCL to ports with pull-ups
|
// Set SDA and SCL to ports with pull-ups
|
||||||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__)
|
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__)
|
||||||
@ -140,9 +133,9 @@ void I2C_init(uint16_t speed)
|
|||||||
(void) I2C_set_speed(speed);
|
(void) I2C_set_speed(speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Disable I2c module on arduino board (releasing pull-ups, and TWI control)
|
/*!\brief Disable I2c module on arduino board (releasing pull-ups, and TWI control)
|
||||||
* \return nothing
|
** \return nothing
|
||||||
*/
|
**/
|
||||||
void I2C_uninit()
|
void I2C_uninit()
|
||||||
{
|
{
|
||||||
// Release SDA and SCL ports pull-ups
|
// Release SDA and SCL ports pull-ups
|
||||||
@ -158,9 +151,9 @@ void I2C_uninit()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \brief I2C bus reset (Release SCL and SDA lines and re-enable module)
|
/*!\brief I2C bus reset (Release SCL and SDA lines and re-enable module)
|
||||||
* \return nothing
|
** \return nothing
|
||||||
*/
|
**/
|
||||||
void I2C_reset(void)
|
void I2C_reset(void)
|
||||||
{
|
{
|
||||||
TWCR = 0;
|
TWCR = 0;
|
||||||
@ -168,72 +161,70 @@ void I2C_reset(void)
|
|||||||
setRegBit(TWCR, TWEN);
|
setRegBit(TWCR, TWEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Change I2C frequency
|
/*!\brief Change I2C frequency
|
||||||
* \param [in] speed - I2C speed in kHz (max 1MHz)
|
** \param [in] speed - I2C speed in KHz (max 400KHz on avr)
|
||||||
* \return true if change is successful (false otherwise)
|
** \return Configured bus speed
|
||||||
*/
|
**/
|
||||||
bool I2C_set_speed(uint16_t speed)
|
uint16_t I2C_set_speed(const uint16_t speed)
|
||||||
{
|
{
|
||||||
i2c.cfg.speed = (I2C_SPEED) ((speed == 0) ? (uint16_t) I2C_STD : ((speed > (uint16_t) I2C_HS) ? (uint16_t) I2C_STD : speed));
|
i2c.cfg.speed = (I2C_SPEED) ((speed == 0) ? (uint16_t) I2C_STD : ((speed > (uint16_t) I2C_FM) ? (uint16_t) I2C_FM : speed));
|
||||||
|
|
||||||
clrRegBit(TWCR, TWEN); // Ensure i2c module is disabled
|
clrRegBit(TWCR, TWEN); // Ensure i2c module is disabled
|
||||||
|
|
||||||
// Set prescaler and clock frequency
|
// Set prescaler and clock frequency
|
||||||
clrRegBit(TWSR, TWPS0);
|
clrRegBit(TWSR, TWPS0);
|
||||||
clrRegBit(TWSR, TWPS1);
|
clrRegBit(TWSR, TWPS1);
|
||||||
TWBR = ((F_CPU / (i2c.cfg.speed * 1000)) - 16) / 2;
|
TWBR = (((F_CPU / 1000) / i2c.cfg.speed) - 16) / 2;
|
||||||
|
|
||||||
I2C_reset(); // re-enable module
|
I2C_reset(); // re-enable module
|
||||||
|
|
||||||
return (i2c.cfg.speed == speed);
|
return i2c.cfg.speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Change I2C ack timeout
|
/*!\brief Change I2C ack timeout
|
||||||
* \param [in] timeout - I2C ack timeout (500 ms max)
|
** \param [in] timeout - I2C ack timeout (500 ms max)
|
||||||
* \return true if change is successful (false otherwise)
|
** \return Configured timeout
|
||||||
*/
|
**/
|
||||||
bool I2C_set_timeout(uint16_t timeout)
|
uint16_t I2C_set_timeout(const uint16_t timeout)
|
||||||
{
|
{
|
||||||
static const uint16_t max_timeout = 500;
|
static const uint16_t max_timeout = 500;
|
||||||
i2c.cfg.timeout = (timeout > max_timeout) ? max_timeout : timeout;
|
i2c.cfg.timeout = (timeout > max_timeout) ? max_timeout : timeout;
|
||||||
return (i2c.cfg.timeout == timeout);
|
return i2c.cfg.timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Change I2C message retries (in case of failure)
|
/*!\brief Change I2C message retries (in case of failure)
|
||||||
* \param [in] retries - I2C number of retries (max of 8)
|
** \param [in] retries - I2C number of retries (max of 8)
|
||||||
* \return true if change is successful (false otherwise)
|
** \return Configured number of retries
|
||||||
*/
|
**/
|
||||||
bool I2C_set_retries(uint8_t retries)
|
uint8_t I2C_set_retries(const uint8_t retries)
|
||||||
{
|
{
|
||||||
static const uint16_t max_retries = 8;
|
static const uint16_t max_retries = 8;
|
||||||
i2c.cfg.retries = (retries > max_retries) ? max_retries : retries;
|
i2c.cfg.retries = (retries > max_retries) ? max_retries : retries;
|
||||||
return (i2c.cfg.retries == retries);
|
return i2c.cfg.retries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Get I2C busy status
|
/*!\brief Get I2C busy status
|
||||||
* \return true if busy
|
** \return true if busy
|
||||||
*/
|
**/
|
||||||
bool I2C_is_busy(void)
|
bool I2C_is_busy(void) {
|
||||||
{
|
return i2c.busy; }
|
||||||
return i2c.busy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! \brief This function reads or writes the provided data to/from the address specified.
|
/*!\brief This function reads or writes the provided data to/from the address specified.
|
||||||
* If anything in the write process is not successful, then it will be repeated
|
* If anything in the write process is not successful, then it will be repeated
|
||||||
* up till 3 more times (default). If still not successful, returns NACK
|
* up till 3 more times (default). If still not successful, returns NACK
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure to init
|
** \param [in, out] slave - pointer to the I2C slave structure to init
|
||||||
* \param [in] reg_addr - register address in register map
|
** \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] data - pointer to the first byte of a block of data to write
|
||||||
* \param [in] bytes - indicates how many bytes of data to write
|
** \param [in] bytes - indicates how many bytes of data to write
|
||||||
* \param [in] rw - 0 = write, 1 = read operation
|
** \param [in] rw - 0 = write, 1 = read operation
|
||||||
* \return I2C_STATUS status of write attempt
|
** \return I2C_STATUS status of write attempt
|
||||||
*/
|
**/
|
||||||
static I2C_STATUS I2C_comm(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes, I2C_RW rw)
|
static I2C_STATUS I2C_comm(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes, const I2C_RW rw)
|
||||||
{
|
{
|
||||||
uint8_t retry = i2c.cfg.retries;
|
uint8_t retry = i2c.cfg.retries;
|
||||||
bool ack = false;
|
bool ack = false;
|
||||||
ci2c_fct_ptr fc = (ci2c_fct_ptr) (rw ? slave->cfg.rd : slave->cfg.wr);
|
ci2c_fct_ptr fc = (ci2c_fct_ptr) (rw ? slave->cfg.rd : slave->cfg.wr);
|
||||||
|
|
||||||
if (I2C_is_busy()) { return slave->status = I2C_BUSY; }
|
if (I2C_is_busy()) { return slave->status = I2C_BUSY; }
|
||||||
i2c.busy = true;
|
i2c.busy = true;
|
||||||
@ -241,7 +232,7 @@ static I2C_STATUS I2C_comm(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data,
|
|||||||
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--;
|
||||||
}
|
}
|
||||||
@ -250,53 +241,45 @@ static I2C_STATUS I2C_comm(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data,
|
|||||||
return slave->status = ack ? I2C_OK : I2C_NACK;
|
return slave->status = ack ? I2C_OK : I2C_NACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief This function writes the provided data to the address specified.
|
/*!\brief This function writes the provided data to the address specified.
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure
|
** \param [in, out] slave - pointer to the I2C slave structure
|
||||||
* \param [in] reg_addr - register address in register map
|
** \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] data - pointer to the first byte of a block of data to write
|
||||||
* \param [in] bytes - indicates how many bytes of data to write
|
** \param [in] bytes - indicates how many bytes of data to write
|
||||||
* \return I2C_STATUS status of write attempt
|
** \return I2C_STATUS status of write attempt
|
||||||
*/
|
**/
|
||||||
I2C_STATUS I2C_write(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes)
|
I2C_STATUS I2C_write(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes) {
|
||||||
{
|
return I2C_comm(slave, reg_addr, data, bytes, I2C_WRITE); }
|
||||||
return I2C_comm(slave, reg_addr, data, bytes, I2C_WRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \brief This function reads data from the address specified and stores this
|
/*!\brief This function reads data from the address specified and stores this
|
||||||
* data in the area provided by the pointer.
|
* data in the area provided by the pointer.
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure
|
** \param [in, out] slave - pointer to the I2C slave structure
|
||||||
* \param [in] reg_addr - register address in register map
|
** \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, 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
|
** \param [in] bytes - indicates how many bytes of data to read
|
||||||
* \return I2C_STATUS status of read attempt
|
** \return I2C_STATUS status of read attempt
|
||||||
*/
|
**/
|
||||||
I2C_STATUS I2C_read(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes)
|
I2C_STATUS I2C_read(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes) {
|
||||||
{
|
return I2C_comm(slave, reg_addr, data, bytes, I2C_READ); }
|
||||||
return I2C_comm(slave, reg_addr, data, bytes, I2C_READ);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! \brief Start i2c_timeout timer
|
/*!\brief Start i2c_timeout timer
|
||||||
* \attribute inline
|
** \attribute inline
|
||||||
* \return nothing
|
** \return nothing
|
||||||
*/
|
**/
|
||||||
static inline void __attribute__((__always_inline__)) I2C_start_timeout(void)
|
static inline void __attribute__((__always_inline__)) I2C_start_timeout(void) {
|
||||||
{
|
i2c.start_wait = (uint16_t) millis(); }
|
||||||
i2c.start_wait = (uint16_t) millis();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \brief Test i2c_timeout
|
/*!\brief Test i2c_timeout
|
||||||
* \attribute inline
|
** \attribute inline
|
||||||
* \return true if i2c_timeout occured (false otherwise)
|
** \return true if i2c_timeout occured (false otherwise)
|
||||||
*/
|
**/
|
||||||
static inline uint8_t __attribute__((__always_inline__)) I2C_timeout(void)
|
static inline uint8_t __attribute__((__always_inline__)) I2C_timeout(void) {
|
||||||
{
|
return (((uint16_t) millis() - i2c.start_wait) >= i2c.cfg.timeout); }
|
||||||
return (((uint16_t) millis() - i2c.start_wait) >= i2c.cfg.timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \brief Send start condition
|
/*!\brief Send start condition
|
||||||
* \return true if start condition acknowledged (false otherwise)
|
** \return true if start condition acknowledged (false otherwise)
|
||||||
*/
|
**/
|
||||||
bool I2C_start(void)
|
bool I2C_start(void)
|
||||||
{
|
{
|
||||||
I2C_start_timeout();
|
I2C_start_timeout();
|
||||||
@ -312,9 +295,9 @@ bool I2C_start(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send stop condition
|
/*!\brief Send stop condition
|
||||||
* \return true if stop condition acknowledged (false otherwise)
|
** \return true if stop condition acknowledged (false otherwise)
|
||||||
*/
|
**/
|
||||||
bool I2C_stop(void)
|
bool I2C_stop(void)
|
||||||
{
|
{
|
||||||
I2C_start_timeout();
|
I2C_start_timeout();
|
||||||
@ -327,11 +310,11 @@ bool I2C_stop(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send byte on bus
|
/*!\brief Send byte on bus
|
||||||
* \param [in] dat - data to be sent
|
** \param [in] dat - data to be sent
|
||||||
* \return true if data sent acknowledged (false otherwise)
|
** \return true if data sent acknowledged (false otherwise)
|
||||||
*/
|
**/
|
||||||
bool I2C_wr8(uint8_t dat)
|
bool I2C_wr8(const uint8_t dat)
|
||||||
{
|
{
|
||||||
TWDR = dat;
|
TWDR = dat;
|
||||||
|
|
||||||
@ -350,11 +333,11 @@ bool I2C_wr8(uint8_t dat)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Receive byte from bus
|
/*!\brief Receive byte from bus
|
||||||
* \param [in] ack - true if wait for ack
|
** \param [in] ack - true if wait for ack
|
||||||
* \return true if data reception acknowledged (false otherwise)
|
** \return true if data reception acknowledged (false otherwise)
|
||||||
*/
|
**/
|
||||||
uint8_t I2C_rd8(bool ack)
|
uint8_t I2C_rd8(const bool ack)
|
||||||
{
|
{
|
||||||
I2C_start_timeout();
|
I2C_start_timeout();
|
||||||
|
|
||||||
@ -369,12 +352,12 @@ uint8_t I2C_rd8(bool ack)
|
|||||||
return ((((TWI_STATUS == MR_DATA_NACK) && (!ack)) || ((TWI_STATUS == MR_DATA_ACK) && (ack))) ? true : false);
|
return ((((TWI_STATUS == MR_DATA_NACK) && (!ack)) || ((TWI_STATUS == MR_DATA_ACK) && (ack))) ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send I2C address
|
/*!\brief Send I2C address
|
||||||
* \param [in] slave - pointer to the I2C slave structure
|
** \param [in] slave - pointer to the I2C slave structure
|
||||||
* \param [in] rw - read/write transaction
|
** \param [in] rw - read/write transaction
|
||||||
* \return true if I2C chip address sent acknowledged (false otherwise)
|
** \return true if I2C chip address sent acknowledged (false otherwise)
|
||||||
*/
|
**/
|
||||||
bool I2C_sndAddr(I2C_SLAVE * slave, I2C_RW rw)
|
bool I2C_sndAddr(I2C_SLAVE * slave, const I2C_RW rw)
|
||||||
{
|
{
|
||||||
TWDR = (slave->cfg.addr << 1) | rw;
|
TWDR = (slave->cfg.addr << 1) | rw;
|
||||||
|
|
||||||
@ -394,21 +377,23 @@ bool I2C_sndAddr(I2C_SLAVE * slave, I2C_RW rw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \brief This procedure calls appropriate functions to perform a proper send transaction on I2C bus.
|
/*!\brief This procedure calls appropriate functions to perform a proper send transaction on I2C bus.
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure
|
** \param [in, out] slave - pointer to the I2C slave structure
|
||||||
* \param [in] reg_addr - register address in register map
|
** \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] data - pointer to the first byte of a block of data to write
|
||||||
* \param [in] bytes - indicates how many bytes of data to write
|
** \param [in] bytes - indicates how many bytes of data to write
|
||||||
* \return Boolean indicating success/fail of write attempt
|
** \return Boolean indicating success/fail of write attempt
|
||||||
*/
|
**/
|
||||||
static bool I2C_wr(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes)
|
static bool I2C_wr(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes)
|
||||||
{
|
{
|
||||||
(void) I2C_slave_set_reg_addr(slave, reg_addr);
|
if (bytes == 0) { return false; }
|
||||||
|
|
||||||
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; }
|
||||||
@ -428,21 +413,21 @@ static bool I2C_wr(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \brief This procedure calls appropriate functions to perform a proper receive transaction on I2C bus.
|
/*!\brief This procedure calls appropriate functions to perform a proper receive transaction on I2C bus.
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure
|
** \param [in, out] slave - pointer to the I2C slave structure
|
||||||
* \param [in] reg_addr - register address in register map
|
** \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, 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
|
** \param [in] bytes - indicates how many bytes of data to read
|
||||||
* \return Boolean indicating success/fail of read attempt
|
** \return Boolean indicating success/fail of read attempt
|
||||||
*/
|
**/
|
||||||
static bool I2C_rd(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes)
|
static bool I2C_rd(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes)
|
||||||
{
|
{
|
||||||
(void) I2C_slave_set_reg_addr(slave, reg_addr);
|
if (bytes == 0) { return false; }
|
||||||
|
|
||||||
if (bytes == 0) { bytes = 1; }
|
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
|
||||||
|
355
src/ci2c.h
355
src/ci2c.h
@ -1,8 +1,8 @@
|
|||||||
/*!\file ci2c.h
|
/*!\file ci2c.h
|
||||||
** \author SMFSW
|
** \author SMFSW
|
||||||
** \version 0.6
|
** \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__
|
||||||
@ -25,49 +25,49 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"{
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEF_CI2C_NB_RETRIES 3 //!< Default cI2C transaction retries
|
#define DEF_CI2C_NB_RETRIES 3 //!< Default cI2C transaction retries
|
||||||
#define DEF_CI2C_TIMEOUT 100 //!< Default cI2C timeout
|
#define DEF_CI2C_TIMEOUT 100 //!< Default cI2C timeout
|
||||||
|
|
||||||
|
|
||||||
/*! \enum enI2C_RW
|
/*!\enum enI2C_RW
|
||||||
* \brief I2C RW bit enumeration
|
** \brief I2C RW bit enumeration
|
||||||
* \attribute packed enum
|
** \attribute packed enum
|
||||||
*/
|
**/
|
||||||
typedef enum __attribute__((__packed__)) enI2C_RW {
|
typedef enum __attribute__((__packed__)) enI2C_RW {
|
||||||
I2C_WRITE = 0, //!< I2C rw bit (write)
|
I2C_WRITE = 0, //!< I2C rw bit (write)
|
||||||
I2C_READ //!< I2C rw bit (read)
|
I2C_READ //!< I2C rw bit (read)
|
||||||
} I2C_RW;
|
} I2C_RW;
|
||||||
|
|
||||||
|
|
||||||
/*! \enum enI2C_SPEED
|
/*!\enum enI2C_SPEED
|
||||||
* \brief I2C bus speed
|
** \brief I2C bus speed
|
||||||
* \attribute packed enum
|
** \attribute packed enum
|
||||||
*/
|
**/
|
||||||
typedef enum __attribute__((__packed__)) enI2C_SPEED {
|
typedef enum __attribute__((__packed__)) enI2C_SPEED {
|
||||||
I2C_STD = 100, //!< I2C Standard (100KHz)
|
I2C_STD = 100, //!< I2C Standard (100KHz)
|
||||||
I2C_FM = 400, //!< I2C Fast Mode (400KHz)
|
I2C_FM = 400, //!< I2C Fast Mode (400KHz)
|
||||||
I2C_FMP = 1000, //!< I2C Fast mode + (1MHz)
|
I2C_FMP = 1000, //!< I2C Fast mode + (1MHz): will set speed to Fast Mode (up to 400KHz on avr)
|
||||||
I2C_HS = 3400 //!< I2C High Speed (3.4MHz)
|
I2C_HS = 3400 //!< I2C High Speed (3.4MHz): will set speed to Fast Mode (up to 400KHz on avr)
|
||||||
} I2C_SPEED;
|
} I2C_SPEED;
|
||||||
|
|
||||||
|
|
||||||
/*! \enum enI2C_STATUS
|
/*!\enum enI2C_STATUS
|
||||||
* \brief I2C slave status
|
** \brief I2C slave status
|
||||||
* \attribute packed enum
|
** \attribute packed enum
|
||||||
*/
|
**/
|
||||||
typedef enum __attribute__((__packed__)) enI2C_STATUS {
|
typedef enum __attribute__((__packed__)) enI2C_STATUS {
|
||||||
I2C_OK = 0x00, //!< I2C OK
|
I2C_OK = 0x00, //!< I2C OK
|
||||||
I2C_BUSY, //!< I2C Bus busy
|
I2C_BUSY, //!< I2C Bus busy
|
||||||
I2C_NACK //!< I2C Not Acknowledge
|
I2C_NACK //!< I2C Not Acknowledge
|
||||||
} I2C_STATUS;
|
} I2C_STATUS;
|
||||||
|
|
||||||
/*! \enum enI2C_INT_SIZE
|
/*!\enum enI2C_INT_SIZE
|
||||||
* \brief I2C slave internal address registers size
|
** \brief I2C slave internal address registers size
|
||||||
* \attribute packed enum
|
** \attribute packed enum
|
||||||
*/
|
**/
|
||||||
typedef enum __attribute__((__packed__)) enI2C_INT_SIZE {
|
typedef enum __attribute__((__packed__)) enI2C_INT_SIZE {
|
||||||
I2C_NO_REG = 0x00, //!< Internal address registers not applicable for slave
|
I2C_NO_REG = 0x00, //!< Internal address registers not applicable for slave
|
||||||
I2C_8B_REG, //!< Slave internal address registers space is 8bits wide
|
I2C_8B_REG, //!< Slave internal address registers space is 8bits wide
|
||||||
@ -75,16 +75,17 @@ typedef enum __attribute__((__packed__)) enI2C_INT_SIZE {
|
|||||||
} I2C_INT_SIZE;
|
} I2C_INT_SIZE;
|
||||||
|
|
||||||
|
|
||||||
typedef bool (*ci2c_fct_ptr) (const void*, uint16_t, uint8_t*, uint16_t); //!< i2c read/write function pointer typedef
|
typedef bool (*ci2c_fct_ptr) (void*, const uint16_t, uint8_t*, const uint16_t); //!< i2c read/write function pointer typedef
|
||||||
|
|
||||||
/*! \struct StructI2CSlave
|
|
||||||
* \brief ci2c slave config and control parameters
|
/*!\struct StructI2CSlave
|
||||||
* \attribute packed struct
|
** \brief ci2c slave config and control parameters
|
||||||
*/
|
** \attribute packed struct
|
||||||
|
**/
|
||||||
typedef struct __attribute__((__packed__)) StructI2CSlave {
|
typedef struct __attribute__((__packed__)) StructI2CSlave {
|
||||||
/*! \struct cfg
|
/*!\struct cfg
|
||||||
* \brief ci2c slave parameters
|
** \brief ci2c slave parameters
|
||||||
*/
|
**/
|
||||||
struct {
|
struct {
|
||||||
uint8_t addr; //!< Slave address
|
uint8_t addr; //!< Slave address
|
||||||
I2C_INT_SIZE reg_size; //!< Slave internal registers size
|
I2C_INT_SIZE reg_size; //!< Slave internal registers size
|
||||||
@ -100,183 +101,177 @@ typedef struct __attribute__((__packed__)) StructI2CSlave {
|
|||||||
/*** I2C SLAVE FUNCTIONS ***/
|
/*** I2C SLAVE FUNCTIONS ***/
|
||||||
/***************************/
|
/***************************/
|
||||||
|
|
||||||
/*! \brief Init an I2C slave structure for cMI2C communication
|
/*!\brief Init an I2C slave structure for cMI2C communication
|
||||||
* \param [in] slave - pointer to the I2C slave structure to init
|
** \param [in] slave - pointer to the I2C slave structure to init
|
||||||
* \param [in] sl_addr - I2C slave address
|
** \param [in] sl_addr - I2C slave address
|
||||||
* \param [in] reg_sz - internal register map size
|
** \param [in] reg_sz - internal register map size
|
||||||
* \return nothing
|
** \return nothing
|
||||||
*/
|
**/
|
||||||
extern void I2C_slave_init(I2C_SLAVE * slave, uint8_t sl_addr, I2C_INT_SIZE reg_sz);
|
void I2C_slave_init(I2C_SLAVE * slave, const uint8_t sl_addr, const I2C_INT_SIZE reg_sz);
|
||||||
|
|
||||||
/*! \brief Redirect slave I2C read/write function (if needed for advanced use)
|
/*!\brief Redirect slave I2C read/write function (if needed for advanced use)
|
||||||
* \param [in] slave - pointer to the I2C slave structure to init
|
** \param [in] slave - pointer to the I2C slave structure to init
|
||||||
* \param [in] func - pointer to read/write function to affect
|
** \param [in] func - pointer to read/write function to affect
|
||||||
* \param [in] rw - 0 = write function, 1 = read function
|
** \param [in] rw - 0 = write function, 1 = read function
|
||||||
* \return nothing
|
** \return nothing
|
||||||
*/
|
**/
|
||||||
extern void I2C_slave_set_rw_func(I2C_SLAVE * slave, ci2c_fct_ptr func, I2C_RW rw);
|
void I2C_slave_set_rw_func(I2C_SLAVE * slave, const ci2c_fct_ptr func, const I2C_RW rw);
|
||||||
|
|
||||||
/*! \brief Change I2C slave address
|
/*!\brief Change I2C slave address
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure to init
|
** \param [in, out] slave - pointer to the I2C slave structure to init
|
||||||
* \param [in] sl_addr - I2C slave address
|
** \param [in] sl_addr - I2C slave address
|
||||||
* \return true if new address set (false if address is >7Fh)
|
** \return true if new address set (false if address is >7Fh)
|
||||||
*/
|
**/
|
||||||
extern bool I2C_slave_set_addr(I2C_SLAVE * slave, uint8_t sl_addr);
|
bool I2C_slave_set_addr(I2C_SLAVE * slave, const uint8_t sl_addr);
|
||||||
|
|
||||||
/*! \brief Change I2C registers map size (for access)
|
/*!\brief Change I2C registers map size (for access)
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure
|
** \param [in, out] slave - pointer to the I2C slave structure
|
||||||
* \param [in] reg_sz - internal register map size
|
** \param [in] reg_sz - internal register map size
|
||||||
* \return true if new size is correct (false otherwise and set to 16bit by default)
|
** \return true if new size is correct (false otherwise and set to 16bit by default)
|
||||||
*/
|
**/
|
||||||
extern bool I2C_slave_set_reg_size(I2C_SLAVE * slave, I2C_INT_SIZE reg_sz);
|
bool I2C_slave_set_reg_size(I2C_SLAVE * slave, const I2C_INT_SIZE reg_sz);
|
||||||
|
|
||||||
/*! \brief Get I2C slave address
|
/*!\brief Get I2C slave address
|
||||||
* \attribute inline
|
** \attribute inline
|
||||||
* \param [in] slave - pointer to the I2C slave structure
|
** \param [in] slave - pointer to the I2C slave structure
|
||||||
* \return I2C slave address
|
** \return I2C slave address
|
||||||
*/
|
**/
|
||||||
inline uint8_t __attribute__((__always_inline__)) I2C_slave_get_addr(I2C_SLAVE * slave)
|
inline uint8_t __attribute__((__always_inline__)) I2C_slave_get_addr(const I2C_SLAVE * slave) {
|
||||||
{
|
return slave->cfg.addr; }
|
||||||
return slave->cfg.addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \brief Get I2C register map size (for access)
|
/*!\brief Get I2C register map size (for access)
|
||||||
* \attribute inline
|
** \attribute inline
|
||||||
* \param [in] slave - pointer to the I2C slave structure
|
** \param [in] slave - pointer to the I2C slave structure
|
||||||
* \return register map using 16bits if true (1Byte otherwise)
|
** \return register map using 16bits if true (1Byte otherwise)
|
||||||
*/
|
**/
|
||||||
inline bool __attribute__((__always_inline__)) I2C_slave_get_reg_size(I2C_SLAVE * slave)
|
inline bool __attribute__((__always_inline__)) I2C_slave_get_reg_size(const I2C_SLAVE * slave) {
|
||||||
{
|
return slave->cfg.reg_size; }
|
||||||
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(const I2C_SLAVE * slave) {
|
||||||
|
return slave->reg_addr; }
|
||||||
|
|
||||||
/*! \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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************/
|
/*************************/
|
||||||
/*** I2C BUS FUNCTIONS ***/
|
/*** I2C BUS FUNCTIONS ***/
|
||||||
/*************************/
|
/*************************/
|
||||||
|
|
||||||
/*! \brief Enable I2c module on arduino board (including pull-ups,
|
/*!\brief Enable I2c module on arduino board (including pull-ups,
|
||||||
* enabling of ACK, and setting clock frequency)
|
* enabling of ACK, and setting clock frequency)
|
||||||
* \param [in] speed - I2C bus speed in KHz
|
** \param [in] speed - I2C bus speed in KHz
|
||||||
* \return nothing
|
** \return nothing
|
||||||
*/
|
**/
|
||||||
extern void I2C_init(uint16_t speed);
|
void I2C_init(const uint16_t speed);
|
||||||
|
|
||||||
/*! \brief Disable I2c module on arduino board (releasing pull-ups, and TWI control)
|
/*!\brief Disable I2c module on arduino board (releasing pull-ups, and TWI control)
|
||||||
* \return nothing
|
** \return nothing
|
||||||
*/
|
**/
|
||||||
extern void I2C_uninit();
|
void I2C_uninit();
|
||||||
|
|
||||||
/*! \brief Change I2C frequency
|
/*!\brief Change I2C frequency
|
||||||
* \param [in] speed - I2C bus speed in KHz
|
** \param [in] speed - I2C bus speed in KHz (max 400KHz on AVR)
|
||||||
* \return true if change is successful (false otherwise)
|
** \return Configured bus speed
|
||||||
*/
|
**/
|
||||||
extern bool I2C_set_speed(uint16_t speed);
|
uint16_t I2C_set_speed(const uint16_t speed);
|
||||||
|
|
||||||
/*! \brief Change I2C ack timeout
|
/*!\brief Change I2C ack timeout
|
||||||
* \param [in] timeout - I2C ack timeout (500 ms max)
|
** \param [in] timeout - I2C ack timeout (500 ms max)
|
||||||
* \return true if change is successful (false otherwise)
|
** \return Configured timeout
|
||||||
*/
|
**/
|
||||||
extern bool I2C_set_timeout(uint16_t timeout);
|
uint16_t I2C_set_timeout(const uint16_t timeout);
|
||||||
|
|
||||||
/*! \brief Change I2C message retries (in case of failure)
|
/*!\brief Change I2C message retries (in case of failure)
|
||||||
* \param [in] retries - I2C number of retries (max of 8)
|
** \param [in] retries - I2C number of retries (max of 8)
|
||||||
* \return true if change is successful (false otherwise)
|
** \return Configured number of retries
|
||||||
*/
|
**/
|
||||||
extern bool I2C_set_retries(uint8_t retries);
|
uint8_t I2C_set_retries(const uint8_t retries);
|
||||||
|
|
||||||
/*! \brief Get I2C busy status
|
/*!\brief Get I2C busy status
|
||||||
* \return true if busy
|
** \return true if busy
|
||||||
*/
|
**/
|
||||||
extern bool I2C_is_busy(void);
|
bool I2C_is_busy(void);
|
||||||
|
|
||||||
/*! \brief This function writes the provided data to the address specified.
|
/*!\brief This function writes the provided data to the address specified.
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure
|
** \param [in, out] slave - pointer to the I2C slave structure
|
||||||
* \param [in] reg_addr - register address in register map
|
** \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] data - pointer to the first byte of a block of data to write
|
||||||
* \param [in] bytes - indicates how many bytes of data to write
|
** \param [in] bytes - indicates how many bytes of data to write
|
||||||
* \return I2C_STATUS status of write attempt
|
** \return I2C_STATUS status of write attempt
|
||||||
*/
|
**/
|
||||||
extern I2C_STATUS I2C_write(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes);
|
I2C_STATUS I2C_write(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes);
|
||||||
|
|
||||||
/*! \brief This inline is a wrapper to I2C_write in case of contigous operations
|
/*!\brief This inline is a wrapper to I2C_write in case of contigous operations
|
||||||
* \attribute inline
|
** \attribute inline
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure
|
** \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] data - pointer to the first byte of a block of data to write
|
||||||
* \param [in] bytes - indicates how many bytes of data to write
|
** \param [in] bytes - indicates how many bytes of data to write
|
||||||
* \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, uint16_t bytes)
|
inline I2C_STATUS __attribute__((__always_inline__)) I2C_write_next(I2C_SLAVE * slave, uint8_t * data, const uint16_t bytes) {
|
||||||
{
|
return I2C_write(slave, slave->reg_addr, data, 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
|
/*!\brief This function reads data from the address specified and stores this
|
||||||
* data in the area provided by the pointer.
|
* data in the area provided by the pointer.
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure
|
** \param [in, out] slave - pointer to the I2C slave structure
|
||||||
* \param [in] reg_addr - register address in register map
|
** \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, 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
|
** \param [in] bytes - indicates how many bytes of data to read
|
||||||
* \return I2C_STATUS status of read attempt
|
** \return I2C_STATUS status of read attempt
|
||||||
*/
|
**/
|
||||||
extern I2C_STATUS I2C_read(I2C_SLAVE * slave, uint16_t reg_addr, uint8_t * data, uint16_t bytes);
|
I2C_STATUS I2C_read(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes);
|
||||||
|
|
||||||
/*! \brief This inline is a wrapper to I2C_read in case of contigous operations
|
/*!\brief This inline is a wrapper to I2C_read in case of contigous operations
|
||||||
* \attribute inline
|
** \attribute inline
|
||||||
* \param [in, out] slave - pointer to the I2C slave structure
|
** \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] data - pointer to the first byte of a block of data to read
|
||||||
* \param [in] bytes - indicates how many bytes of data to read
|
** \param [in] bytes - indicates how many bytes of data to read
|
||||||
* \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, uint16_t bytes)
|
inline I2C_STATUS __attribute__((__always_inline__)) I2C_read_next(I2C_SLAVE * slave, uint8_t * data, const uint16_t bytes) {
|
||||||
{
|
return I2C_read(slave, slave->reg_addr, data, 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************/
|
/***********************************/
|
||||||
/*** cI2C LOW LEVEL FUNCTIONS ***/
|
/*** cI2C LOW LEVEL FUNCTIONS ***/
|
||||||
/*** THAT MAY BE USEFUL FOR DVPT ***/
|
/*** THAT MAY BE USEFUL FOR DVPT ***/
|
||||||
/***********************************/
|
/***********************************/
|
||||||
/*! \brief I2C bus reset (Release SCL and SDA lines and re-enable module)
|
/*!\brief I2C bus reset (Release SCL and SDA lines and re-enable module)
|
||||||
* \return nothing
|
** \return nothing
|
||||||
*/
|
**/
|
||||||
extern void I2C_reset(void);
|
void I2C_reset(void);
|
||||||
/*! \brief Send start condition
|
|
||||||
* \return true if start condition acknowledged (false otherwise)
|
/*!\brief Send start condition
|
||||||
*/
|
** \return true if start condition acknowledged (false otherwise)
|
||||||
extern bool I2C_start(void);
|
**/
|
||||||
/*! \brief Send stop condition
|
bool I2C_start(void);
|
||||||
* \return true if stop condition acknowledged (false otherwise)
|
|
||||||
*/
|
/*!\brief Send stop condition
|
||||||
extern bool I2C_stop(void);
|
** \return true if stop condition acknowledged (false otherwise)
|
||||||
/*! \brief Send byte on bus
|
**/
|
||||||
* \param [in] dat - data to be sent
|
bool I2C_stop(void);
|
||||||
* \return true if data sent acknowledged (false otherwise)
|
|
||||||
*/
|
/*!\brief Send byte on bus
|
||||||
extern bool I2C_wr8(uint8_t dat);
|
** \param [in] dat - data to be sent
|
||||||
/*! \brief Receive byte from bus
|
** \return true if data sent acknowledged (false otherwise)
|
||||||
* \param [in] ack - true if wait for ack
|
**/
|
||||||
* \return true if data reception acknowledged (false otherwise)
|
bool I2C_wr8(const uint8_t dat);
|
||||||
*/
|
|
||||||
extern uint8_t I2C_rd8(bool ack);
|
/*!\brief Receive byte from bus
|
||||||
/*! \brief Send I2C address
|
** \param [in] ack - true if wait for ack
|
||||||
* \param [in] slave - pointer to the I2C slave structure
|
** \return true if data reception acknowledged (false otherwise)
|
||||||
* \param [in] rw - read/write transaction
|
**/
|
||||||
* \return true if I2C chip address sent acknowledged (false otherwise)
|
uint8_t I2C_rd8(const bool ack);
|
||||||
*/
|
|
||||||
extern bool I2C_sndAddr(I2C_SLAVE * slave, I2C_RW rw);
|
/*!\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)
|
||||||
|
**/
|
||||||
|
bool I2C_sndAddr(I2C_SLAVE * slave, const I2C_RW rw);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
Loading…
Reference in New Issue
Block a user