Skip to content

Optimise machine.time_pulse_us implementation for code size, and switch esp8266 port to use it #17346

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

Conversation

dpgeorge
Copy link
Member

Summary

The esp8266 has a custom implementation of machine.time_pulse_us(), which is needed so it can feed the WDT during long waits for a pin change. It doesn't need to have a separate implementation, instead we can use the common one with an optional hook for a port to do work during the busy wait loops.

This PR:

  1. Reworks the common implementation of machine.time_pulse_us() to be more like the esp8266 version. That cuts down code size a little, and improves accuracy a little.
  2. Switches esp8266 to use this common implementation.

Also, motivation comes from #16160: this PR should make that PR much simpler (and lower cost) to implement.

Testing

Tested with a range of square waves from 125Hz to 4kHz on:

  • PYBD_SF2: this has a very accurate measurement and accuracy is unchanged with this PR
  • RPI_PICO2_W: same as PYBD_SF2, very accurate and unchanged with this PR
  • ESP8266: for the frequencies it can handle (up to about 1kHz) this PR is slightly more accurate than before: for example a pulse that is 1000us long, it would measure between 998 and 1000us with an average of 999us. Now it measures between 999us and 1001us with an average of 1000us.

Also tested the timeout argument, a value of 5000000 still takes 5s and doesn't lead to a WDT timeout on esp8266.

Trade-offs and Alternatives

This is an optimisation. There is no change in the API. As tested above, the accuracy is at least the same if not better due to better sampling of ticks and pin at the same point in the code.

Copy link

github-actions bot commented May 23, 2025

Code size report:

   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:   +32 +0.004% standard
      stm32:   -16 -0.004% PYBV10
     mimxrt:   -16 -0.004% TEENSY40
        rp2:    -8 -0.001% RPI_PICO_W
       samd:   -24 -0.009% ADAFRUIT_ITSYBITSY_M4_EXPRESS
  qemu rv32:    +0 +0.000% VIRT_RV32

@dpgeorge
Copy link
Member Author

It's really hard to pass CI these days 😅

@dpgeorge dpgeorge force-pushed the extmod-machine-time-pulse-optimise branch from e6464be to 04226d0 Compare May 23, 2025 03:37
Copy link

codecov bot commented May 23, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.54%. Comparing base (5676b45) to head (398da22).
Report is 2 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #17346   +/-   ##
=======================================
  Coverage   98.54%   98.54%           
=======================================
  Files         169      169           
  Lines       21941    21946    +5     
=======================================
+ Hits        21621    21626    +5     
  Misses        320      320           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dpgeorge dpgeorge force-pushed the extmod-machine-time-pulse-optimise branch from 04226d0 to c21708b Compare May 23, 2025 04:39
@dpgeorge
Copy link
Member Author

@robert-hh regarding your comment that I think you deleted: it should be possible to allow nchanges to be any value, but the initial pulse_value would need to be twiddled like: pulse_value ^= nchanges & 1. Ie if there are an odd number of changes, toggle the initial value.

@robert-hh
Copy link
Contributor

Yes, I delete it because at second though it was wrong. The nchanges counter can not underrun.
Tests with a SAMD21 also returned improved accuracy. A 1000µs pulse showed most values being either 999 or 1002, and an average over 100 samples of 1000 +/- 0.15.

@projectgus projectgus self-requested a review May 29, 2025 03:46
Copy link
Contributor

@projectgus projectgus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice cleanup!

dpgeorge added 2 commits June 13, 2025 16:27
This implementation is based on the esp8266 custom implementation, and
further optimised for size and accuracy.

Testing on PYBD_SF2 and RPI_PICO2_W shows that it is at least as good as
the original implementation in performance.

Signed-off-by: Damien George <damien@micropython.org>
Testing shows that for frequencies which the esp8266 can handle -- up to
about 1kHz -- `machine.time_pulse_us()` now gives more accurate results.

Prior to this commit it would measure on average about 1us lower, but now
the average is much closer to the true value.  For example a pulse that is
1000us long, it would measure between 998 and 1000us.  Now it measures
between 999us and 1001us.

Signed-off-by: Damien George <damien@micropython.org>
@dpgeorge dpgeorge force-pushed the extmod-machine-time-pulse-optimise branch from c21708b to 398da22 Compare June 13, 2025 06:30
@dpgeorge dpgeorge merged commit 398da22 into micropython:master Jun 13, 2025
63 of 64 checks passed
@dpgeorge dpgeorge deleted the extmod-machine-time-pulse-optimise branch June 13, 2025 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extmod Relates to extmod/ directory in source port-esp8266
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants