From 7a9b45dbdb459e3d62b068e54879042fab12230a Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Tue, 5 Nov 2024 10:56:41 +0200 Subject: [PATCH] machine: Add time_hardware_pulse_us function. The difference from `time_pulse_us` is that if the pin is initially equal to *pulse_level* then `time_pulse_us` counts the pulse duration immediately, but `time_hardware_pulse_us` first waits for the different *pulse_level*, then waits the equal to *pulse_level* and then counts pulse duration. Signed-off-by: IhorNehrutsa --- docs/library/machine.rst | 23 +++++++++++++++++++++++ extmod/machine_pulse.c | 38 ++++++++++++++++++++++++++++++++++++++ extmod/modmachine.c | 1 + extmod/modmachine.h | 1 + 4 files changed, 63 insertions(+) diff --git a/docs/library/machine.rst b/docs/library/machine.rst index 7d2eb26a7ea34..b360fd5322e11 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -198,6 +198,29 @@ Miscellaneous functions above. The timeout is the same for both cases and given by *timeout_us* (which is in microseconds). +.. function:: time_hardware_pulse_us(pin, pulse_level, timeout_us=1000000, /) + + Time a pulse on the given *pin*, and return the duration of the pulse in + microseconds. The *pulse_level* argument should be 0 to time a low pulse + or 1 to time a high pulse. + + If the pin is initially equal to *pulse_level* then first waits until + the pin input becomes different from *pulse_level* (***). + Then the function waits until the pin input becomes equal to *pulse_level* (**), + then the function counts the duration that the pin is equal to *pulse_level* (*). + + The function returns -3 if there was timeout waiting for condition marked (***) above. + The function will return -2 if there was timeout waiting for condition marked + (**) above, and -1 if there was timeout during the main measurement, marked (*) + above. The timeout is the same for all cases and given by *timeout_us* (which + is in microseconds). + + The difference from `time_pulse_us` is that if the pin is initially equal to *pulse_level* + then `time_pulse_us` counts the pulse duration immediately, + but `time_hardware_pulse_us` first waits for the different *pulse_level*, + then waits the equal to *pulse_level* and then counts pulse duration. + A little bit longer, but higher accuracy. + .. function:: bitstream(pin, encoding, timing, data, /) Transmits *data* by bit-banging the specified *pin*. The *encoding* argument diff --git a/extmod/machine_pulse.c b/extmod/machine_pulse.c index 85dba86d9b5ad..8515a5ad2937d 100644 --- a/extmod/machine_pulse.c +++ b/extmod/machine_pulse.c @@ -62,4 +62,42 @@ static mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj, 2, 3, machine_time_pulse_us_); +MP_WEAK mp_uint_t machine_time_hardware_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) { + 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)-3; + } + } + 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; + } + } + return mp_hal_ticks_us() - start; +} + +static mp_obj_t machine_time_hardware_pulse_us_(size_t n_args, const mp_obj_t *args) { + mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(args[0]); + int level = 0; + if (mp_obj_is_true(args[1])) { + level = 1; + } + mp_uint_t timeout_us = 1000000; + if (n_args > 2) { + timeout_us = mp_obj_get_int(args[2]); + } + mp_uint_t us = machine_time_hardware_pulse_us(pin, level, timeout_us); + // May return -1 or -2 or -3 in case of timeout + return mp_obj_new_int(us); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_hardware_pulse_us_obj, 2, 3, machine_time_hardware_pulse_us_); + #endif diff --git a/extmod/modmachine.c b/extmod/modmachine.c index 5906835949861..5441f378d2dcf 100644 --- a/extmod/modmachine.c +++ b/extmod/modmachine.c @@ -188,6 +188,7 @@ static const mp_rom_map_elem_t machine_module_globals_table[] = { #endif #if MICROPY_PY_MACHINE_PULSE { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, + { MP_ROM_QSTR(MP_QSTR_time_hardware_pulse_us), MP_ROM_PTR(&machine_time_hardware_pulse_us_obj) }, #endif // Classes for PinBase and Signal. diff --git a/extmod/modmachine.h b/extmod/modmachine.h index 7c16ed302ee2f..41aab2aaddcec 100644 --- a/extmod/modmachine.h +++ b/extmod/modmachine.h @@ -255,6 +255,7 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bitstream_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj); +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_hardware_pulse_us_obj); #if MICROPY_PY_MACHINE_I2C int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);