pasko-zh / brzo_i2c

Brzo I2C is a fast I2C Implementation written in Assembly for the esp8266
GNU General Public License v3.0
244 stars 47 forks source link

Treating the library like a virtual I2C hub device #16

Open MikeFair opened 7 years ago

MikeFair commented 7 years ago

The work on adding a "clock_stretch" and making different devices work at different speeds on the bus gave me lots of ideas; but namely it grounded something I'd been thinking about for a while now; that it should be possible to encode all the configuration required for an I2C Request in a single numeric identifier that can be "reused" and "passed around".

An application would feed in the details into a function and get back a single 32-bit or 64-bit identfier that represented that "request" as a "request_id". Then one mechanism to trigger a request is just to ask for it by request_id. These ids (with certain "fill in the blank" bits masked out) could be sent over a network or other communication lines to have other devices execute them at your request and send back the results. [This is like what slave I2C devices in some chips do, or what an I2C aggregator/hub is doing.]

So I started wondering about using an I2C bus library that acted like a "virtual i2c hub".

I'd register requests, set up precanned fetches/puts, and then interact with it much the same I would an actual device. I'd call a couple "update" functions at the start of "loop()" and a "commitChanges()" at the end; and the library would get the state/values from the preconfigured devices, I'd manipulate/read them inside loop(), and the library would push back the changes.

We could call commitChanges(), or update(), as often as required.

For example:

"Device Id" + "Item Id" == 64-bit "Request Id"

void setup() {
    I2CBus i2c_bus1(sda, scl);
    uint64_t req_id = i2c_get_request_id(
            device_address, bus_speed, clock_stretch
            , register_address, data_length, is_read, start_repeat, ... 
    );
    i2c_bus1.execRequest(req_id, &data[6]);
    i2c_bus1.setSlaveRequest(slave_id, req_id, (uint8_t*)&the_device_struct);  // Populate data into the_device_struct
}

void loop() {
    i2c_bus1.updateSlaves();

    if (the_device_struct.data_available) {
        Serial.println("Got Value: " + String(the_device_struct.important_value));
    }

    the_device_struct.config_setting = get_new_setting();

    i2c_bus1.commitChanges();
}