abstracting i2c_t3 to reuse code

Status
Not open for further replies.

linuxgeek

Well-known member
I have a bunch of code to setup an i2c sensor, etc. And each sensor could be on a different bus, and possibly different addresses.
So I want to reuse my code, and be able to change the code easily to handle different setups.

Here's my first basic attempt just to test the concept (it compiles), and just wanted to ask if this makes sense? Or if there is anything I should keep in mind. I know this is getting very tied into i2c_t3, but it seems the easiest way for me to do this.

Code:
#include <i2c_t3.h>

void setup() {
  // put your setup code here, to run once:
  setupWire(&Wire, I2C_PINS_18_19);
  setupWire(&Wire1, I2C_PINS_22_23);
}

void setupWire(i2c_t3 *WireTmp, i2c_pins setupPins) {
  WireTmp->begin(I2C_MASTER, 0x00, setupPins, I2C_PULLUP_EXT, I2C_RATE_100);
}

void loop() {
  // put your main code here, to run repeatedly:

}
 
you did all that for just 2 initialization lines normally from i2c_t3? i would think your making it more complicated this way
 
No, there's a lot more code. This was just a simple one-line to test the redirection.
I've got much more code for doing the configuration, etc. And making 4 copies of every function that I develop to essentially do the same thing is kind of a nightmare to maintain.
 
That might work fine. Not sure how much as it depends on how you expand it.

When I was first doing some testing of different things for the K66 beta, I wanted to test out the different I2C busses, so I hacked up a version of the Adafruit_SSD1306 library where I could pass in which buss each device was on, it is in the fork/branch: https://github.com/KurtE/Adafruit_SSD1306/tree/I2C_T3

In this code, I passed in which Buss to use by reference versus pointer. With this I was able to generate a test case with multiple of these devices defined. Could only test one at a time as I have 1 display...

Side Notes:
When I started making a potential version of Wire library that supported multiple devices, I did the same thing except I used the class name TwoWire, which in my version of Wire, I defined as the base class name. Also trying to decide in my version of Wire to keep as base class and each Wire object as subclass or to do like the Wire library for the Arduino Due which defines to instances of the TwoWire object, where the differences are passed in the constructor and/or some methods have to figure out which buss they are on... However in either case I wanted TwoWire as the class name as I have found a few libraries out there that have done something similar to support the Arduino Due, so those libraries should work with my wire...
 
I like your approach. I think I'm gonna stick to the simple C language conventions (pointers) cause I don't want to think about C++ to minimize the # of hiccups for me. But I can likely switch this over to your implementation easily afterwards.
 
My preferred method is to use the following:

Code:
i2c_t3(port).begin(I2C_MASTER, 0, pins, pullups, clock);

Where port is a uint8_t defining which bus number the I2C is working with (i.e. instead of Wire, Wire1, etc it's 0, 1, 2, ...), pins is of type i2c_pins, pullups is of type i2c_pullup, and clock is a uint32_t. if you want to get fancy, you can define an I2C configuration structure like:

Code:
struct i2cConfig {
    uint8_t port;       // I2C bus number
    i2c_pins pins;      // I2C pins
    i2c_pullup pullups;	// I2C pullups
    uint32_t clock;     // I2C clock frequency
};

And then call that structure for each sensor, like:

Code:
i2cConfig IMU;
IMU.port = 0;
IMU.pins = I2C_PINS_18_19;
IMU.pullups = I2C_PULLUP_EXT;
IMU.clock = 400000;

Then your calls to i2c_t3 would be like:

Code:
i2c_t3(IMU.port).begin(I2C_MASTER, 0, IMU.pins, IMU.pullups, IMU.clock);
 
Yes I think this is a good idea. I think I'll put this struct inside the struct for all the other sensor config.
I want to get it so that in one place at the top of my sketch I do all my sensor setup and everything else automagically does what I want. This way I can experiment more freely.
 
what ive done is setup a function that loads all 3 i2c busses and have setup call it, the rest is plug&play, i find it cleaner
 
Oh, glad I re-read this cause now I realize more of what brtaylor was saying. I had no idea that you could call i2c_t3 directly by passing the port. That's exactly what I needed, as I was looking for a way to avoid having to code "Wire", "Wire1", etc. That simplifies things a lot.

Code:
i2c_t3(port).begin(I2C_MASTER, 0, pins, pullups, clock);

Thank you!
 
Status
Not open for further replies.
Back
Top