Skip to content

I2C Speedup #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 25, 2021
Merged

I2C Speedup #20

merged 4 commits into from
Jan 25, 2021

Conversation

caternuson
Copy link
Collaborator

This PR should significantly speed up the I2C transaction and greatly improve the performance of this library. The code change is trivial, but there is a lot of history behind it.

First off, this library was originally written as a simple port of existing Arduino libraries. The huge delays included in the I2C transaction came from there. Some attempts were made to reduce or remove these. Using a repeated start was also attempted. These efforts had mixed success. It could be made to work fast on one platform, but then break on another. Obviously there was some subtle timing requirement that was not being satisfied. But with no real information (no datasheet) to go on, the exact nature of this remained unknown. So the existing delays were simply left in place.

Some recent PR's (#17 and #18) have brought this issue back into the light. Various work arounds were discussed as a way to speed up the library - all assuming the huge delays were still necessary. See those PR threads for more info. Progress was made, but then at some point the idea of removing the delays was again attempted and seemed to work. As before, this worked on some platforms, but not others. This motivated the investigation to snoop actual Wiimote-to-Nunchuk traffic to finally have some idea of what the "requirements" are. The results are documented here:
#2 (comment)

Based on those findings, it seems the critical timing requirement is an O(200us) delay between the write and read transactions. On some slower boards, this can happen naturally without any explicit delay between the two lines of code. But on faster boards, the delay would be <200us and the Nunchuk would NACK on the read. Adding an explicit delay fixed this for all boards. However, the ability to actually generate a 200us delay in Python is a mixed bag. Some hosts can do that, others can not. For those that can not, the attempt results in essentially zero delay. Therefore, this PR uses a conservative default of 2000us which seems to work on all platforms. The value is available as a parameter to allow fine tuning if desired and possible.

Other misc:

  • The read buffer has been increased to 8 bytes to match the Wiimote behavior, even though the last two bytes appear to be meaningless. Maybe 3rd party Nunchuks expect that behavior in some weird way?
  • The _I2C_INIT_DELAY is being left in place for now. Can it be reduced? Unknown. Can investigate for a future PR.
  • The current API is also unchanged for now. Also something for a future PR - maybe provide something that returns all values from the single I2C transaction? Like in a named tuple or something?

Tested on:

  • MO : Trinket M0 and QT Py
  • M4 : Itsy M4
  • Blinka: MCP2221 on linux and RPI4

@ladyada
Copy link
Member

ladyada commented Jan 24, 2021

didnt' test but lgtm

@jfurcean
Copy link
Contributor

I tested this successfully on the following boards:

  • MO : Trinket M0 and QT Py
  • M4 : Feather M4

There were i2c read issues on ESP32-S2 boards (FeatherS2 & MagTag). I think this is related to board specific issues and not related to this library.

@caternuson
Copy link
Collaborator Author

Cool. Thanks!

@caternuson caternuson merged commit b653d73 into adafruit:master Jan 25, 2021
adafruit-adabot added a commit to adafruit/Adafruit_CircuitPython_Bundle that referenced this pull request Jan 26, 2021
Updating https://github.com/adafruit/Adafruit_CircuitPython_Nunchuk to 0.3.0 from 0.2.3:
  > Merge pull request adafruit/Adafruit_CircuitPython_Nunchuk#20 from caternuson/i2c_speedup
  > Merge pull request adafruit/Adafruit_CircuitPython_Nunchuk#14 from caternuson/iss13

Updating https://github.com/adafruit/Adafruit_CircuitPython_SI7021 to v3.3.0 from 3.2.3:
  > Merge pull request adafruit/Adafruit_CircuitPython_SI7021#21 from imgrant/serial_number

Updating https://github.com/adafruit/Adafruit_CircuitPython_PIOASM to 0.1.1 from 0.1.0:
  > Merge pull request adafruit/Adafruit_CircuitPython_PIOASM#2 from ryang14/patch-1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants