Skip to content

Commit 19c420b

Browse files
authored
Merge pull request #764 from pieterdepiet/LinuxI2CDev
Support for Linux /dev/i2c-%u
2 parents 605a740 + b388531 commit 19c420b

7 files changed

Lines changed: 5674 additions & 0 deletions

File tree

LinuxI2CDev/I2Cdev/I2Cdev.cpp

Lines changed: 391 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,391 @@
1+
// I2Cdev library collection - Main I2C device class
2+
// Abstracts bit and byte I2C R/W functions into a convenient class
3+
// 2013-06-05 by Jeff Rowberg <jeff@rowberg.net>
4+
//
5+
// Changelog:
6+
// 2021-09-28 - allow custom Wire object as transaction function argument
7+
// 2020-01-20 - hardija : complete support for Teensy 3.x
8+
// 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1
9+
// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications
10+
// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan)
11+
// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire
12+
// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation
13+
// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums)
14+
// 2011-10-03 - added automatic Arduino version detection for ease of use
15+
// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications
16+
// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x)
17+
// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default
18+
// 2011-08-02 - added support for 16-bit registers
19+
// - fixed incorrect Doxygen comments on some methods
20+
// - added timeout value for read operations (thanks mem @ Arduino forums)
21+
// 2011-07-30 - changed read/write function structures to return success or byte counts
22+
// - made all methods static for multi-device memory savings
23+
// 2011-07-28 - initial release
24+
25+
/* ============================================
26+
I2Cdev device library code is placed under the MIT license
27+
Copyright (c) 2013 Jeff Rowberg
28+
29+
Permission is hereby granted, free of charge, to any person obtaining a copy
30+
of this software and associated documentation files (the "Software"), to deal
31+
in the Software without restriction, including without limitation the rights
32+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33+
copies of the Software, and to permit persons to whom the Software is
34+
furnished to do so, subject to the following conditions:
35+
36+
The above copyright notice and this permission notice shall be included in
37+
all copies or substantial portions of the Software.
38+
39+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45+
THE SOFTWARE.
46+
===============================================
47+
*/
48+
49+
#include "I2Cdev.h"
50+
51+
#include <fcntl.h>
52+
#include <unistd.h>
53+
#include <errno.h>
54+
#include <string.h>
55+
#include <stdio.h>
56+
#include <sys/ioctl.h>
57+
#include <linux/i2c-dev.h>
58+
59+
static const char* i2cDev = NULL;
60+
/** Default constructor.
61+
*/
62+
I2Cdev::I2Cdev() {
63+
}
64+
65+
void I2Cdev::initialize(const char* devPath) {
66+
i2cDev = devPath;
67+
}
68+
/** Read a single bit from an 8-bit device register.
69+
* @param devAddr I2C slave device address
70+
* @param regAddr Register regAddr to read from
71+
* @param bitNum Bit position to read (0-7)
72+
* @param data Container for single bit value
73+
* @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
74+
* @return Status of read operation (true = success)
75+
*/
76+
int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout) {
77+
uint8_t b;
78+
uint8_t count = readByte(devAddr, regAddr, &b, timeout);
79+
*data = b & (1 << bitNum);
80+
return count;
81+
}
82+
83+
/** Read a single bit from a 16-bit device register.
84+
* @param devAddr I2C slave device address
85+
* @param regAddr Register regAddr to read from
86+
* @param bitNum Bit position to read (0-15)
87+
* @param data Container for single bit value
88+
* @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
89+
* @return Status of read operation (true = success)
90+
*/
91+
int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout) {
92+
uint16_t b;
93+
uint8_t count = readWord(devAddr, regAddr, &b, timeout);
94+
*data = b & (1 << bitNum);
95+
return count;
96+
}
97+
98+
/** Read multiple bits from an 8-bit device register.
99+
* @param devAddr I2C slave device address
100+
* @param regAddr Register regAddr to read from
101+
* @param bitStart First bit position to read (0-7)
102+
* @param length Number of bits to read (not more than 8)
103+
* @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05)
104+
* @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
105+
* @return Status of read operation (true = success)
106+
*/
107+
int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout) {
108+
// 01101001 read byte
109+
// 76543210 bit numbers
110+
// xxx args: bitStart=4, length=3
111+
// 010 masked
112+
// -> 010 shifted
113+
uint8_t count, b;
114+
if ((count = readByte(devAddr, regAddr, &b, timeout)) != 0) {
115+
uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
116+
b &= mask;
117+
b >>= (bitStart - length + 1);
118+
*data = b;
119+
}
120+
return count;
121+
}
122+
123+
/** Read multiple bits from a 16-bit device register.
124+
* @param devAddr I2C slave device address
125+
* @param regAddr Register regAddr to read from
126+
* @param bitStart First bit position to read (0-15)
127+
* @param length Number of bits to read (not more than 16)
128+
* @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05)
129+
* @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
130+
* @return Status of read operation (1 = success, 0 = failure, -1 = timeout)
131+
*/
132+
int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout) {
133+
// 1101011001101001 read byte
134+
// fedcba9876543210 bit numbers
135+
// xxx args: bitStart=12, length=3
136+
// 010 masked
137+
// -> 010 shifted
138+
uint8_t count;
139+
uint16_t w;
140+
if ((count = readWord(devAddr, regAddr, &w, timeout)) != 0) {
141+
uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1);
142+
w &= mask;
143+
w >>= (bitStart - length + 1);
144+
*data = w;
145+
}
146+
return count;
147+
}
148+
149+
/** Read single byte from an 8-bit device register.
150+
* @param devAddr I2C slave device address
151+
* @param regAddr Register regAddr to read from
152+
* @param data Container for byte value read from device
153+
* @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
154+
* @return Status of read operation (true = success)
155+
*/
156+
int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout) {
157+
return readBytes(devAddr, regAddr, 1, data, timeout);
158+
}
159+
160+
/** Read single word from a 16-bit device register.
161+
* @param devAddr I2C slave device address
162+
* @param regAddr Register regAddr to read from
163+
* @param data Container for word value read from device
164+
* @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
165+
* @return Status of read operation (true = success)
166+
*/
167+
int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout) {
168+
return readWords(devAddr, regAddr, 1, data, timeout);
169+
}
170+
171+
/** Read multiple bytes from an 8-bit device register.
172+
* @param devAddr I2C slave device address
173+
* @param regAddr First register regAddr to read from
174+
* @param length Number of bytes to read
175+
* @param data Buffer to store read data in
176+
* @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
177+
* @return Number of bytes read (-1 indicates failure)
178+
*/
179+
int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout) {
180+
int fd = open(i2cDev, O_RDWR);
181+
if (fd < 0) {
182+
fprintf(stderr, "Failed to open i2c device %s: %s\n", i2cDev, strerror(errno));
183+
return -1;
184+
}
185+
if (ioctl(fd, I2C_SLAVE, (unsigned long) devAddr) < 0) {
186+
fprintf(stderr, "Failed to set i2c address to %u: %s\n", devAddr, strerror(errno));
187+
close(fd);
188+
return -1;
189+
}
190+
if (timeout != 0 && ioctl(fd, I2C_TIMEOUT, (unsigned long) timeout / 100) < 0) {
191+
fprintf(stderr, "Failed to set i2c timeout: %s\n", strerror(errno));
192+
}
193+
if (write(fd, &regAddr, 1) != 1) {
194+
fprintf(stderr, "Failed to write reg: %s\n", strerror(errno));
195+
}
196+
if (read(fd, data, length) != length) {
197+
fprintf(stderr, "Failed to read reg: %s\n", strerror(errno));
198+
close(fd);
199+
return -1;
200+
}
201+
close(fd);
202+
return length;
203+
}
204+
205+
/** Read multiple words from a 16-bit device register.
206+
* @param devAddr I2C slave device address
207+
* @param regAddr First register regAddr to read from
208+
* @param length Number of words to read
209+
* @param data Buffer to store read data in
210+
* @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
211+
* @return Number of words read (-1 indicates failure)
212+
*/
213+
int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout) {
214+
uint8_t buff[length * 2];
215+
216+
if (readBytes(devAddr, regAddr, length * 2, buff, timeout) > 0)
217+
{
218+
for (int i = 0; i < length; i++)
219+
{
220+
data[i] = (buff[i * 2] << 8) | buff[i * 2 + 1];
221+
}
222+
return length;
223+
}
224+
225+
return -1;
226+
}
227+
228+
/** write a single bit in an 8-bit device register.
229+
* @param devAddr I2C slave device address
230+
* @param regAddr Register regAddr to write to
231+
* @param bitNum Bit position to write (0-7)
232+
* @param value New bit value to write
233+
* @return Status of operation (true = success)
234+
*/
235+
bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) {
236+
uint8_t b;
237+
readByte(devAddr, regAddr, &b, I2Cdev::readTimeout);
238+
b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
239+
return writeByte(devAddr, regAddr, b);
240+
}
241+
242+
/** write a single bit in a 16-bit device register.
243+
* @param devAddr I2C slave device address
244+
* @param regAddr Register regAddr to write to
245+
* @param bitNum Bit position to write (0-15)
246+
* @param value New bit value to write
247+
* @return Status of operation (true = success)
248+
*/
249+
bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) {
250+
uint16_t w;
251+
readWord(devAddr, regAddr, &w, I2Cdev::readTimeout);
252+
w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum));
253+
return writeWord(devAddr, regAddr, w);
254+
}
255+
256+
/** Write multiple bits in an 8-bit device register.
257+
* @param devAddr I2C slave device address
258+
* @param regAddr Register regAddr to write to
259+
* @param bitStart First bit position to write (0-7)
260+
* @param length Number of bits to write (not more than 8)
261+
* @param data Right-aligned value to write
262+
* @return Status of operation (true = success)
263+
*/
264+
bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) {
265+
// 010 value to write
266+
// 76543210 bit numbers
267+
// xxx args: bitStart=4, length=3
268+
// 00011100 mask byte
269+
// 10101111 original value (sample)
270+
// 10100011 original & ~mask
271+
// 10101011 masked | value
272+
uint8_t b;
273+
if (readByte(devAddr, regAddr, &b, I2Cdev::readTimeout) != 0) {
274+
uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
275+
data <<= (bitStart - length + 1); // shift data into correct position
276+
data &= mask; // zero all non-important bits in data
277+
b &= ~(mask); // zero all important bits in existing byte
278+
b |= data; // combine data with existing byte
279+
return writeByte(devAddr, regAddr, b);
280+
} else {
281+
return false;
282+
}
283+
}
284+
285+
/** Write multiple bits in a 16-bit device register.
286+
* @param devAddr I2C slave device address
287+
* @param regAddr Register regAddr to write to
288+
* @param bitStart First bit position to write (0-15)
289+
* @param length Number of bits to write (not more than 16)
290+
* @param data Right-aligned value to write
291+
* @return Status of operation (true = success)
292+
*/
293+
bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) {
294+
// 010 value to write
295+
// fedcba9876543210 bit numbers
296+
// xxx args: bitStart=12, length=3
297+
// 0001110000000000 mask word
298+
// 1010111110010110 original value (sample)
299+
// 1010001110010110 original & ~mask
300+
// 1010101110010110 masked | value
301+
uint16_t w;
302+
if (readWord(devAddr, regAddr, &w, I2Cdev::readTimeout) != 0) {
303+
uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1);
304+
data <<= (bitStart - length + 1); // shift data into correct position
305+
data &= mask; // zero all non-important bits in data
306+
w &= ~(mask); // zero all important bits in existing word
307+
w |= data; // combine data with existing word
308+
return writeWord(devAddr, regAddr, w);
309+
} else {
310+
return false;
311+
}
312+
}
313+
314+
/** Write single byte to an 8-bit device register.
315+
* @param devAddr I2C slave device address
316+
* @param regAddr Register address to write to
317+
* @param data New byte value to write
318+
* @return Status of operation (true = success)
319+
*/
320+
bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) {
321+
return writeBytes(devAddr, regAddr, 1, &data);
322+
}
323+
324+
/** Write single word to a 16-bit device register.
325+
* @param devAddr I2C slave device address
326+
* @param regAddr Register address to write to
327+
* @param data New word value to write
328+
* @return Status of operation (true = success)
329+
*/
330+
bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) {
331+
return writeWords(devAddr, regAddr, 1, &data);
332+
}
333+
334+
/** Write multiple bytes to an 8-bit device register.
335+
* @param devAddr I2C slave device address
336+
* @param regAddr First register address to write to
337+
* @param length Number of bytes to write
338+
* @param data Buffer to copy new data from
339+
* @return Status of operation (true = success)
340+
*/
341+
bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) {
342+
int fd = open(i2cDev, O_RDWR);
343+
if (fd < 0) {
344+
fprintf(stderr, "Failed to open i2c device %s: %s\n", i2cDev, strerror(errno));
345+
return -1;
346+
}
347+
if (ioctl(fd, I2C_SLAVE, (unsigned long) devAddr) < 0) {
348+
fprintf(stderr, "Failed to set i2c address to %u: %s\n", devAddr, strerror(errno));
349+
close(fd);
350+
return -1;
351+
}
352+
uint16_t buff_length = length + 1;
353+
uint8_t buff[buff_length];
354+
buff[0] = regAddr;
355+
356+
memcpy(&buff[1], data, length);
357+
358+
if (write(fd, buff, buff_length) != buff_length)
359+
{
360+
fprintf(stderr, "Failed to write reg: %s\n", strerror(errno));
361+
close(fd);
362+
return false;
363+
}
364+
close(fd);
365+
return true;
366+
}
367+
368+
/** Write multiple words to a 16-bit device register.
369+
* @param devAddr I2C slave device address
370+
* @param regAddr First register address to write to
371+
* @param length Number of words to write
372+
* @param data Buffer to copy new data from
373+
* @return Status of operation (true = success)
374+
*/
375+
bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) {
376+
uint8_t buff[length * 2];
377+
378+
for (int i = 0; i < length; i++)
379+
{
380+
buff[2 * i] = (uint8_t)(data[i] >> 8); //MSByte
381+
buff[1 + 2 * i] = (uint8_t)(data[i] >> 0); //LSByte
382+
}
383+
384+
return writeBytes(devAddr, regAddr, length * 2, buff);
385+
}
386+
387+
/** Default timeout value for read operations.
388+
* Set this to 0 to disable timeout detection.
389+
*/
390+
uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT;
391+

0 commit comments

Comments
 (0)