diff --git a/include/os_timer_sig.h b/include/os_timer_sig.h index 99d5461..7fcd479 100644 --- a/include/os_timer_sig.h +++ b/include/os_timer_sig.h @@ -26,8 +26,10 @@ typedef struct os_timer_sig_periodic_static_obj_t void* stub2; os_signal_num_e stub3; os_delta_ticks_t stub4; - bool stub5; + TickType_t stub5; bool stub6; + bool stub7; + bool stub8; } os_timer_sig_periodic_static_obj_t; typedef struct os_timer_sig_periodic_static_t @@ -42,8 +44,9 @@ typedef struct os_timer_sig_one_shot_static_obj_t void* stub2; os_signal_num_e stub3; os_delta_ticks_t stub4; - bool stub5; + TickType_t stub5; bool stub6; + bool stub7; } os_timer_sig_one_shot_static_obj_t; typedef struct os_timer_sig_one_shot_static_t @@ -170,6 +173,24 @@ os_timer_sig_periodic_start(os_timer_sig_periodic_t* const p_obj); void os_timer_sig_one_shot_start(os_timer_sig_one_shot_t* const p_obj); +/** + * @brief Set the new period for the timer (but do not start or restart it). + * + * @param p_obj Pointer to the os_timer_sig_periodic_t object instance. + * @param delay_ticks Period for the timer, specified in system ticks. + */ +void +os_timer_sig_periodic_set_period(os_timer_sig_periodic_t* const p_obj, const os_delta_ticks_t delay_ticks); + +/** + * @brief Set the new period for the timer (but do not start or restart it). + * + * @param p_obj Pointer to the os_timer_sig_periodic_t object instance. + * @param delay_ticks Period for the timer, specified in system ticks. + */ +void +os_timer_sig_one_shot_set_period(os_timer_sig_one_shot_t* const p_obj, const os_delta_ticks_t delay_ticks); + /** * @brief Restarts the periodic timer which sends the specified signal. * @@ -212,26 +233,68 @@ os_timer_sig_one_shot_restart_with_period( const bool flag_reset_active_timer); /** - * @brief Stop and restart the periodic timer which sends the specified signal from the current moment. + * @brief Updates the timestamp associated with a one-shot signal timer when the timer was triggered. + * + * This function is used to update the timestamp value associated with a one-shot signal timer + * when the timer was triggered. It takes a pointer to the `os_timer_sig_one_shot_t` object and + * updates the `timestamp` field with the specified system tick counter. + * + * @param p_obj Pointer to the `os_timer_sig_one_shot_t` object. + * @param timestamp The timestamp value to update. + */ +void +os_timer_sig_one_shot_update_timestamp_when_timer_was_triggered( + os_timer_sig_one_shot_t* const p_obj, + const TickType_t timestamp); + +/** + * @brief Updates the timestamp associated with a periodic signal timer when the timer was triggered. + * + * This function is used to update the timestamp value associated with a periodic signal timer + * when the timer was triggered. It takes a pointer to the `os_timer_sig_periodic_t` object and + * updates the `timestamp` field with the specified system tick counter. + * + * @param p_obj Pointer to the `os_timer_sig_periodic_t` object. + * @param timestamp The timestamp value to update. + */ +void +os_timer_sig_periodic_update_timestamp_when_timer_was_triggered( + os_timer_sig_periodic_t* const p_obj, + const TickType_t timestamp); + +/** + * @brief Stop and restart the periodic timer which sends the specified signal. * * If the timer wasn't initially active, it will initiate it. - * For already active timers, the function stops it and restarts from the current moment. + * This function will restart the timer from the last time it was triggered (or from the current moment). + * For already active timers, the function stops it and then calculates the next trigger time. + * If the time since the last activation exceeds the configured period, the timer will be triggered immediately + * and the signal will be sent and a timer with the specified period will be activated. + * If the time elapsed since the last actuation is less than the configured period, the timer will be configured + * for the remaining time, and after it is triggered, it will be reconfigured for the specified period. * * @param p_obj Pointer to the os_timer_sig_periodic_t object instance. + * @param flag_restart_from_current_moment If true, then restart the timer from the current moment. */ void -os_timer_sig_periodic_relaunch(os_timer_sig_periodic_t* const p_obj); +os_timer_sig_periodic_relaunch(os_timer_sig_periodic_t* const p_obj, bool flag_restart_from_current_moment); /** - * @brief Stop and restart the one-shot timer which sends the specified signal from the current moment. + * @brief Stop and restart the one-shot timer which sends the specified signal. * * If the timer wasn't initially active, it will initiate it. - * For already active timers, the function stops it and restarts from the current moment. + * This function will restart the timer from the last time it was triggered (or from the current moment). + * For already active timers, the function stops it and then calculates the next trigger time. + * If the time since the last activation exceeds the configured period, the timer will be triggered immediately + * and the signal will be sent, but the one-shot timer will not be activated. + * If the time elapsed since the last actuation is less than the configured period, the timer will be configured + * for the remaining time, and after it is triggered. * * @param p_obj Pointer to the os_timer_sig_one_shot_t object instance. + * @param flag_restart_from_current_moment If true, then restart the timer from the current moment. */ void -os_timer_sig_one_shot_relaunch(os_timer_sig_one_shot_t* const p_obj); +os_timer_sig_one_shot_relaunch(os_timer_sig_one_shot_t* const p_obj, const bool flag_restart_from_current_moment); /** * @brief Stop the periodic timer which sends the specified signal. diff --git a/src/os_timer_sig.c b/src/os_timer_sig.c index 3612d95..cbc7b30 100644 --- a/src/os_timer_sig.c +++ b/src/os_timer_sig.c @@ -19,8 +19,10 @@ struct os_timer_sig_periodic_t os_signal_t* p_signal; os_signal_num_e sig_num; os_delta_ticks_t period_ticks; + TickType_t last_tick_when_timer_was_triggered; bool is_static; volatile bool is_active; + bool flag_need_to_restart; }; _Static_assert( @@ -33,6 +35,7 @@ struct os_timer_sig_one_shot_t os_signal_t* p_signal; os_signal_num_e sig_num; os_delta_ticks_t period_ticks; + TickType_t last_tick_when_timer_was_triggered; bool is_static; volatile bool is_active; }; @@ -48,7 +51,13 @@ os_timer_sig_cb_periodic(ATTR_UNUSED os_timer_periodic_t* p_timer, void* p_arg) { return; } - os_timer_sig_periodic_t* p_obj = p_arg; + os_timer_sig_periodic_t* p_obj = p_arg; + p_obj->last_tick_when_timer_was_triggered = xTaskGetTickCount(); + if (p_obj->flag_need_to_restart) + { + p_obj->is_active = os_timer_periodic_restart(p_obj->p_timer, p_obj->period_ticks); + p_obj->flag_need_to_restart = false; + } if (p_obj->is_active) { os_signal_send(p_obj->p_signal, p_obj->sig_num); @@ -62,7 +71,8 @@ os_timer_sig_cb_one_shot(ATTR_UNUSED os_timer_one_shot_t* p_timer, void* p_arg) { return; } - os_timer_sig_one_shot_t* p_obj = p_arg; + os_timer_sig_one_shot_t* p_obj = p_arg; + p_obj->last_tick_when_timer_was_triggered = xTaskGetTickCount(); if (p_obj->is_active) { p_obj->is_active = false; @@ -83,12 +93,14 @@ os_timer_sig_periodic_create( { return NULL; } - p_obj->p_signal = p_signal; - p_obj->sig_num = sig_num; - p_obj->period_ticks = period_ticks; - p_obj->is_static = false; - p_obj->is_active = false; - p_obj->p_timer = os_timer_periodic_create(p_timer_name, period_ticks, &os_timer_sig_cb_periodic, p_obj); + p_obj->p_signal = p_signal; + p_obj->sig_num = sig_num; + p_obj->period_ticks = period_ticks; + p_obj->last_tick_when_timer_was_triggered = xTaskGetTickCount() - period_ticks; + p_obj->is_static = false; + p_obj->is_active = false; + p_obj->flag_need_to_restart = false; + p_obj->p_timer = os_timer_periodic_create(p_timer_name, period_ticks, &os_timer_sig_cb_periodic, p_obj); if (NULL == p_obj->p_timer) { os_timer_sig_periodic_delete(&p_obj); @@ -110,11 +122,13 @@ os_timer_sig_periodic_create_static( { os_timer_sig_periodic_t* const p_obj = (os_timer_sig_periodic_t*)&p_timer_sig_mem->obj_mem; - p_obj->p_signal = p_signal; - p_obj->sig_num = sig_num; - p_obj->period_ticks = period_ticks; - p_obj->is_static = true; - p_obj->is_active = false; + p_obj->p_signal = p_signal; + p_obj->sig_num = sig_num; + p_obj->period_ticks = period_ticks; + p_obj->last_tick_when_timer_was_triggered = xTaskGetTickCount() - period_ticks; + p_obj->is_static = true; + p_obj->is_active = false; + p_obj->flag_need_to_restart = false; p_obj->p_timer = os_timer_periodic_create_static( &p_timer_sig_mem->os_timer_mem, @@ -138,12 +152,13 @@ os_timer_sig_one_shot_create( { return NULL; } - p_obj->p_signal = p_signal; - p_obj->sig_num = sig_num; - p_obj->period_ticks = period_ticks; - p_obj->is_static = false; - p_obj->is_active = false; - p_obj->p_timer = os_timer_one_shot_create(p_timer_name, period_ticks, &os_timer_sig_cb_one_shot, p_obj); + p_obj->p_signal = p_signal; + p_obj->sig_num = sig_num; + p_obj->period_ticks = period_ticks; + p_obj->last_tick_when_timer_was_triggered = xTaskGetTickCount() - period_ticks; + p_obj->is_static = false; + p_obj->is_active = false; + p_obj->p_timer = os_timer_one_shot_create(p_timer_name, period_ticks, &os_timer_sig_cb_one_shot, p_obj); if (NULL == p_obj->p_timer) { os_timer_sig_one_shot_delete(&p_obj); @@ -165,11 +180,12 @@ os_timer_sig_one_shot_create_static( { os_timer_sig_one_shot_t* const p_obj = (os_timer_sig_one_shot_t*)&p_timer_sig_mem->obj_mem; - p_obj->p_signal = p_signal; - p_obj->sig_num = sig_num; - p_obj->period_ticks = period_ticks; - p_obj->is_static = true; - p_obj->is_active = false; + p_obj->p_signal = p_signal; + p_obj->sig_num = sig_num; + p_obj->period_ticks = period_ticks; + p_obj->last_tick_when_timer_was_triggered = xTaskGetTickCount() - period_ticks; + p_obj->is_static = true; + p_obj->is_active = false; p_obj->p_timer = os_timer_one_shot_create_static( &p_timer_sig_mem->os_timer_mem, @@ -260,6 +276,26 @@ os_timer_sig_one_shot_start(os_timer_sig_one_shot_t* const p_obj) os_timer_one_shot_start(p_obj->p_timer); } +void +os_timer_sig_periodic_set_period(os_timer_sig_periodic_t* const p_obj, const os_delta_ticks_t delay_ticks) +{ + if (NULL == p_obj) + { + return; + } + p_obj->period_ticks = delay_ticks; +} + +void +os_timer_sig_one_shot_set_period(os_timer_sig_one_shot_t* const p_obj, const os_delta_ticks_t delay_ticks) +{ + if (NULL == p_obj) + { + return; + } + p_obj->period_ticks = delay_ticks; +} + void os_timer_sig_periodic_restart_with_period( os_timer_sig_periodic_t* const p_obj, @@ -299,7 +335,23 @@ os_timer_sig_one_shot_restart_with_period( } void -os_timer_sig_periodic_relaunch(os_timer_sig_periodic_t* const p_obj) +os_timer_sig_one_shot_update_timestamp_when_timer_was_triggered( + os_timer_sig_one_shot_t* const p_obj, + const TickType_t timestamp) +{ + p_obj->last_tick_when_timer_was_triggered = timestamp; +} + +void +os_timer_sig_periodic_update_timestamp_when_timer_was_triggered( + os_timer_sig_periodic_t* const p_obj, + const TickType_t timestamp) +{ + p_obj->last_tick_when_timer_was_triggered = timestamp; +} + +void +os_timer_sig_periodic_relaunch(os_timer_sig_periodic_t* const p_obj, bool flag_restart_from_current_moment) { if (NULL == p_obj) { @@ -307,11 +359,42 @@ os_timer_sig_periodic_relaunch(os_timer_sig_periodic_t* const p_obj) } p_obj->is_active = false; os_timer_periodic_stop(p_obj->p_timer); - p_obj->is_active = os_timer_periodic_restart(p_obj->p_timer, p_obj->period_ticks); + + int32_t delta_ticks = (int32_t)p_obj->period_ticks; + const TickType_t cur_tick = xTaskGetTickCount(); + if (flag_restart_from_current_moment) + { + os_timer_sig_periodic_update_timestamp_when_timer_was_triggered(p_obj, cur_tick); + } + else + { + const os_delta_ticks_t elapsed_ticks = cur_tick - p_obj->last_tick_when_timer_was_triggered; + + delta_ticks = (int32_t)(p_obj->period_ticks - elapsed_ticks); + } + if (delta_ticks > 0) + { + if (delta_ticks == (int32_t)p_obj->period_ticks) + { + p_obj->flag_need_to_restart = false; + p_obj->is_active = os_timer_periodic_restart(p_obj->p_timer, p_obj->period_ticks); + } + else + { + p_obj->flag_need_to_restart = true; + p_obj->is_active = os_timer_periodic_restart(p_obj->p_timer, delta_ticks); + } + } + else + { + p_obj->flag_need_to_restart = false; + p_obj->is_active = os_timer_periodic_restart(p_obj->p_timer, p_obj->period_ticks); + os_timer_periodic_simulate(p_obj->p_timer); + } } void -os_timer_sig_one_shot_relaunch(os_timer_sig_one_shot_t* const p_obj) +os_timer_sig_one_shot_relaunch(os_timer_sig_one_shot_t* const p_obj, const bool flag_restart_from_current_moment) { if (NULL == p_obj) { @@ -319,7 +402,35 @@ os_timer_sig_one_shot_relaunch(os_timer_sig_one_shot_t* const p_obj) } p_obj->is_active = false; os_timer_one_shot_stop(p_obj->p_timer); - p_obj->is_active = os_timer_one_shot_restart(p_obj->p_timer, p_obj->period_ticks); + + int32_t delta_ticks = (int32_t)p_obj->period_ticks; + const TickType_t cur_tick = xTaskGetTickCount(); + if (flag_restart_from_current_moment) + { + os_timer_sig_one_shot_update_timestamp_when_timer_was_triggered(p_obj, cur_tick); + } + else + { + const os_delta_ticks_t elapsed_ticks = cur_tick - p_obj->last_tick_when_timer_was_triggered; + + delta_ticks = (int32_t)(p_obj->period_ticks - elapsed_ticks); + } + if (delta_ticks > 0) + { + if (delta_ticks == (int32_t)p_obj->period_ticks) + { + p_obj->is_active = os_timer_one_shot_restart(p_obj->p_timer, p_obj->period_ticks); + } + else + { + p_obj->is_active = os_timer_one_shot_restart(p_obj->p_timer, delta_ticks); + } + } + else + { + p_obj->is_active = true; + os_timer_one_shot_simulate(p_obj->p_timer); + } } void