summaryrefslogtreecommitdiff
path: root/extmod/machine_pulse.c
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2025-05-23 12:56:12 +1000
committerDamien George <damien@micropython.org>2025-06-13 16:27:35 +1000
commitef21ade602116421db2734d23320401ac6669773 (patch)
tree1080c53bacad4a58a9bb8a857c72d02f857a31ef /extmod/machine_pulse.c
parent5676b45cbb8644f7b04e2a0495c760d905007983 (diff)
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 <damien@micropython.org>
Diffstat (limited to 'extmod/machine_pulse.c')
-rw-r--r--extmod/machine_pulse.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/extmod/machine_pulse.c b/extmod/machine_pulse.c
index 85dba86d9..1ec4d5f08 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;
- }
- }
- 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;
+ 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
}
}
- return mp_hal_ticks_us() - start;
}
static mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) {