jamesbowman / i2cdriver

I2CDriver open source tools
https://i2cdriver.com/
BSD 3-Clause "New" or "Revised" License
187 stars 57 forks source link

No register write command #49

Open lukehutch opened 4 years ago

lukehutch commented 4 years ago

The I2C Mini has a register read command, 'r':

Reads an I2C device register data. This command executes the following I2C operations:

  • START, select address dev for writing
  • write a single byte addr
  • START, select address dev for reading
  • read count bytes item STOP

However, it appears there is no corresponding register write command. This seems like a big omission, since many I2C devices that have register values that may be read are controlled by writing to registers.

I realize a similar sequence to the above could be constructed for writing to a register, however it would be great if a command 'w' could be provided so that this boilerplate could be avoided.

Also, there are no commands for 2-byte register devices in the I2C Mini's firmware. See the different I2C addressing modes and how they are handled on the Devantech USB-ISS device here: https://www.robot-electronics.co.uk/htm/usb_iss_i2c_tech.htm

jamesbowman commented 4 years ago

Right, here's the regwr method that does an explicit start-write-stop:

https://github.com/jamesbowman/i2cdriver/blob/master/python/i2cdriver.py#L305-L329

The I2CDriver's protocol is meant as a 1:1 mapping with the traffic on the I2C bus. So all the "higher-level" protocol handling happens on the host (*). From my understanding of the USB-ISS, it takes a different approach, where the USB-ISS also knows about register protocols for many I2C devices. (It also offers I2C_DIRECT commands, very much like the I2CDriver). My preference is for systems where the protocol is explicit -- I've had some difficult experiences with schemes that "wrap" protocols up.

Because of the amazing variety in manufacturers' interpretations of I2C, it's very difficult to cover everything. For example some devices need a STOP before the second START in a read register transaction. For example:

https://github.com/jamesbowman/i2cdriver/blob/master/python/samples/qwiic-keypad.py

I don't see how the USB-ISS handles this case. And some I2C capacitive touch panels use 16-bit addresses, but little endian, while the USB-ISS looks like it only supports big-endian.

My point isn't to criticize the USB-ISS, but that building higher-level protocols into the hardware will inevitably be incomplete. You'll always need the low-level protocol. So why not only do that?

(Oof, sorry this is a bit long. Anyway, it's always interesting to see how others do it. Thanks!)

(*) The exception is the 'r' command, of course, which does several operations. The motivation is to avoid USB turnaround times for this very frequent case. But it's a point solution for devices with 8-bit registers that support this RESTART-style addressing.

lukehutch commented 4 years ago

Makes sense. Well I'd be happy if at least a 'w' command was included for symmetry with the 'r' command, for the common 1-byte register case, where a given number of bytes needs to be written.