From ef21ade602116421db2734d23320401ac6669773 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 23 May 2025 12:56:12 +1000 Subject: [PATCH] extmod/machine_pulse: Optimise time_pulse_us for code size. 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 --- extmod/machine_pulse.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/extmod/machine_pulse.c b/extmod/machine_pulse.c index 85dba86d9b..1ec4d5f083 100644 --- a/extmod/machine_pulse.c +++ b/extmod/machine_pulse.c @@ -31,19 +31,34 @@ #if MICROPY_PY_MACHINE_PULSE MP_WEAK mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) { + mp_uint_t nchanges = 2; mp_uint_t start = mp_hal_ticks_us(); - while (mp_hal_pin_read(pin) != pulse_level) { - if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) { - return (mp_uint_t)-2; + for (;;) { + // Sample ticks and pin as close together as possible, and always in the same + // order each time around the loop. This gives the most accurate measurement. + mp_uint_t t = mp_hal_ticks_us(); + int pin_value = mp_hal_pin_read(pin); + + if (pin_value == pulse_level) { + // Pin is at desired value. Flip desired value and see if we are done. + pulse_level = 1 - pulse_level; + if (--nchanges == 0) { + return t - start; + } + start = t; + } else { + // Pin hasn't changed yet, check for timeout. + mp_uint_t dt = t - start; + if (dt >= timeout_us) { + return -nchanges; + } + + // Allow a port to perform background task processing if needed. + #ifdef MICROPY_PY_MACHINE_TIME_PULSE_US_HOOK + MICROPY_PY_MACHINE_TIME_PULSE_US_HOOK(dt); + #endif } } - start = mp_hal_ticks_us(); - while (mp_hal_pin_read(pin) == pulse_level) { - if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) { - return (mp_uint_t)-1; - } - } - return mp_hal_ticks_us() - start; } static mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) {