Skip to content

Commit

Permalink
machine: Add time_hardware_pulse_us function.
Browse files Browse the repository at this point in the history
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 the different *pulse_level*,
then waits the equal to *pulse_level* and then counts pulse duration.

Signed-off-by: IhorNehrutsa <[email protected]>
  • Loading branch information
IhorNehrutsa committed Nov 5, 2024
1 parent 594670e commit 457bad9
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 0 deletions.
23 changes: 23 additions & 0 deletions docs/library/machine.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 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
Expand Down
38 changes: 38 additions & 0 deletions extmod/machine_pulse.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions extmod/modmachine.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions extmod/modmachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 457bad9

Please sign in to comment.