From a21f56b2d5c01b90e86453d1e7d38968085b09e0 Mon Sep 17 00:00:00 2001 From: Dave Hylands Date: Sun, 28 Sep 2014 11:21:13 -0700 Subject: [PATCH] Added pyb.elapsed_millis and pyb.elapsed_micros tested using: stmhal: https://github.com/dhylands/upy-examples/blob/master/elapsed.py teensy: https://github.com/dhylands/upy-examples/blob/master/teensy/elapsed.py --- stmhal/modpyb.c | 60 ++++++++++++++++++++++++++++++------------- stmhal/qstrdefsport.h | 2 ++ teensy/modpyb.c | 60 ++++++++++++++++++++++++++++++++++++++++++- teensy/qstrdefsport.h | 3 +++ teensy/teensy_hal.c | 2 +- 5 files changed, 107 insertions(+), 20 deletions(-) diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c index 09a8caf278..7f39098caf 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -188,15 +188,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_sync_obj, pyb_sync); /// \function millis() /// Returns the number of milliseconds since the board was last reset. /// -/// Note that this may return a negative number. This allows you to always -/// do: -/// start = pyb.millis() -/// ...do some operation... -/// elapsed = pyb.millis() - start -/// -/// and as long as the time of your operation is less than 24 days, you'll -/// always get the right answer and not have to worry about whether pyb.millis() -/// wraps around. +/// The result is always a micropython smallint (31-bit signed number), so +/// after 2^30 milliseconds (about 12.4 days) this will start to return +/// negative numbers. STATIC mp_obj_t pyb_millis(void) { // We want to "cast" the 32 bit unsigned into a small-int. This means // copying the MSB down 1 bit (extending the sign down), which is @@ -205,18 +199,29 @@ STATIC mp_obj_t pyb_millis(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_millis_obj, pyb_millis); +/// \function elapsed_millis(start) +/// Returns the number of milliseconds which have elapsed since `start`. +/// +/// This function takes care of counter wrap, and always returns a positive +/// number. This means it can be used to measure periods upto about 12.4 days. +/// +/// Example: +/// start = pyb.millis() +/// while pyb.elapsed_millis(start) < 1000: +/// # Perform some operation +STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) { + uint32_t startMillis = mp_obj_get_int(start); + uint32_t currMillis = HAL_GetTick(); + return MP_OBJ_NEW_SMALL_INT((currMillis - startMillis) & 0x3fffffff); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis); + /// \function micros() /// Returns the number of microseconds since the board was last reset. /// -/// Note that this may return a negative number. This allows you to always -/// do: -/// start = pyb.micros() -/// ...do some operation... -/// elapsed = pyb.micros() - start -/// -/// and as long as the time of your operation is less than 35 minutes, you'll -/// always get the right answer and not have to worry about whether pyb.micros() -/// wraps around. +/// The result is always a micropython smallint (31-bit signed number), so +/// after 2^30 microseconds (about 17.8 minutes) this will start to return +/// negative numbers. STATIC mp_obj_t pyb_micros(void) { // We want to "cast" the 32 bit unsigned into a small-int. This means // copying the MSB down 1 bit (extending the sign down), which is @@ -225,6 +230,23 @@ STATIC mp_obj_t pyb_micros(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_micros_obj, pyb_micros); +/// \function elapsed_micros(start) +/// Returns the number of microseconds which have elapsed since `start`. +/// +/// This function takes care of counter wrap, and always returns a positive +/// number. This means it can be used to measure periods upto about 17.8 minutes. +/// +/// Example: +/// start = pyb.micros() +/// while pyb.elapsed_micros(start) < 1000: +/// # Perform some operation +STATIC mp_obj_t pyb_elapsed_micros(mp_obj_t start) { + uint32_t startMicros = mp_obj_get_int(start); + uint32_t currMicros = sys_tick_get_microseconds(); + return MP_OBJ_NEW_SMALL_INT((currMicros - startMicros) & 0x3fffffff); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros); + /// \function delay(ms) /// Delay for the given number of milliseconds. STATIC mp_obj_t pyb_delay(mp_obj_t ms_in) { @@ -376,7 +398,9 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_USB_VCP), (mp_obj_t)&pyb_usb_vcp_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&pyb_millis_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_millis), (mp_obj_t)&pyb_elapsed_millis_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_micros), (mp_obj_t)&pyb_micros_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_micros), (mp_obj_t)&pyb_elapsed_micros_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&pyb_delay_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_udelay), (mp_obj_t)&pyb_udelay_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&pyb_sync_obj }, diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h index a3a0f0d023..674b8f3f8b 100644 --- a/stmhal/qstrdefsport.h +++ b/stmhal/qstrdefsport.h @@ -68,6 +68,8 @@ Q(/sd) Q(/sd/lib) Q(millis) Q(micros) +Q(elapsed_millis) +Q(elapsed_micros) // for file class Q(seek) diff --git a/teensy/modpyb.c b/teensy/modpyb.c index 696554ee4b..18d3809cf3 100644 --- a/teensy/modpyb.c +++ b/teensy/modpyb.c @@ -157,11 +157,66 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_sync_obj, pyb_sync); /// \function millis() /// Returns the number of milliseconds since the board was last reset. +/// +/// The result is always a micropython smallint (31-bit signed number), so +/// after 2^30 milliseconds (about 12.4 days) this will start to return +/// negative numbers. STATIC mp_obj_t pyb_millis(void) { - return mp_obj_new_int(HAL_GetTick()); + // We want to "cast" the 32 bit unsigned into a small-int. This means + // copying the MSB down 1 bit (extending the sign down), which is + // equivalent to just using the MP_OBJ_NEW_SMALL_INT macro. + return MP_OBJ_NEW_SMALL_INT(HAL_GetTick()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_millis_obj, pyb_millis); +/// \function elapsed_millis(start) +/// Returns the number of milliseconds which have elapsed since `start`. +/// +/// This function takes care of counter wrap, and always returns a positive +/// number. This means it can be used to measure periods upto about 12.4 days. +/// +/// Example: +/// start = pyb.millis() +/// while pyb.elapsed_millis(start) < 1000: +/// # Perform some operation +STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) { + uint32_t startMillis = mp_obj_get_int(start); + uint32_t currMillis = HAL_GetTick(); + return MP_OBJ_NEW_SMALL_INT((currMillis - startMillis) & 0x3fffffff); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis); + +/// \function micros() +/// Returns the number of microseconds since the board was last reset. +/// +/// The result is always a micropython smallint (31-bit signed number), so +/// after 2^30 microseconds (about 17.8 minutes) this will start to return +/// negative numbers. +STATIC mp_obj_t pyb_micros(void) { + // We want to "cast" the 32 bit unsigned into a small-int. This means + // copying the MSB down 1 bit (extending the sign down), which is + // equivalent to just using the MP_OBJ_NEW_SMALL_INT macro. + return MP_OBJ_NEW_SMALL_INT(micros()); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_micros_obj, pyb_micros); + +/// \function elapsed_micros(start) +/// Returns the number of microseconds which have elapsed since `start`. +/// +/// This function takes care of counter wrap, and always returns a positive +/// number. This means it can be used to measure periods upto about 17.8 minutes. +/// +/// Example: +/// start = pyb.micros() +/// while pyb.elapsed_micros(start) < 1000: +/// # Perform some operation +STATIC mp_obj_t pyb_elapsed_micros(mp_obj_t start) { + uint32_t startMicros = mp_obj_get_int(start); + uint32_t currMicros = micros(); + return MP_OBJ_NEW_SMALL_INT((currMicros - startMicros) & 0x3fffffff); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros); + /// \function delay(ms) /// Delay for the given number of milliseconds. STATIC mp_obj_t pyb_delay(mp_obj_t ms_in) { @@ -248,6 +303,9 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_hid), (mp_obj_t)&pyb_hid_send_report_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&pyb_millis_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_millis), (mp_obj_t)&pyb_elapsed_millis_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_micros), (mp_obj_t)&pyb_micros_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_micros), (mp_obj_t)&pyb_elapsed_micros_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&pyb_delay_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_udelay), (mp_obj_t)&pyb_udelay_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&pyb_sync_obj }, diff --git a/teensy/qstrdefsport.h b/teensy/qstrdefsport.h index 202052f6b8..cfcbf7705c 100644 --- a/teensy/qstrdefsport.h +++ b/teensy/qstrdefsport.h @@ -50,6 +50,9 @@ Q(enable_irq) Q(usb_mode) Q(have_cdc) Q(millis) +Q(micros) +Q(elapsed_millis) +Q(elapsed_micros) Q(udelay) Q(UART) diff --git a/teensy/teensy_hal.c b/teensy/teensy_hal.c index b7ac842af8..39f41ad8ad 100644 --- a/teensy/teensy_hal.c +++ b/teensy/teensy_hal.c @@ -8,7 +8,7 @@ #include MICROPY_HAL_H uint32_t HAL_GetTick(void) { - return micros(); + return millis(); } void HAL_Delay(uint32_t Delay) {