osal_rs/traits/timer.rs
1/***************************************************************************
2 *
3 * osal-rs
4 * Copyright (C) 2023/2026 Antonio Salsi <passy.linux@zresa.it>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 ***************************************************************************/
19
20//! Software timer trait for delayed and periodic callbacks.
21//!
22//! Timers execute callback functions in the context of a timer service task,
23//! enabling delayed operations and periodic tasks without dedicated threads.
24
25use core::any::Any;
26
27use alloc::{boxed::Box, sync::Arc};
28
29use crate::os::types::TickType;
30use crate::utils::{OsalRsBool, Result};
31
32/// Type-erased parameter for timer callbacks.
33///
34/// Allows passing arbitrary data to timer callback functions.
35pub type TimerParam = Arc<dyn Any + Send + Sync>;
36
37/// Timer callback function pointer type.
38///
39/// Callbacks receive the timer handle and optional parameter,
40/// and can return an updated parameter value.
41pub type TimerFnPtr = dyn Fn(Box<dyn Timer>, Option<TimerParam>) -> Result<TimerParam> + Send + Sync + 'static;
42
43/// Software timer for delayed and periodic callbacks.
44///
45/// Timers run callbacks in the timer service task context, not ISR context.
46/// They can be one-shot or auto-reloading (periodic).
47///
48/// # Examples
49///
50/// ## One-shot Timer
51///
52/// ```ignore
53/// use osal_rs::os::{Timer, TimerFn};
54/// use core::time::Duration;
55///
56/// let timer = Timer::new(
57/// "one_shot",
58/// Duration::from_secs(5),
59/// false, // One-shot
60/// None,
61/// |_timer, _param| {
62/// println!("Timer expired!");
63/// Ok(None)
64/// }
65/// ).unwrap();
66///
67/// timer.start(0);
68/// ```
69///
70/// ## Periodic Timer
71///
72/// ```ignore
73/// let periodic = Timer::new(
74/// "periodic",
75/// Duration::from_millis(100),
76/// true, // Auto-reload
77/// None,
78/// |_timer, _param| {
79/// println!("Tick!");
80/// Ok(None)
81/// }
82/// ).unwrap();
83///
84/// periodic.start(0);
85/// // Runs every 100ms until stopped
86/// ```
87pub trait Timer {
88 /// Starts or restarts the timer.
89 ///
90 /// If the timer is already running, it is reset to its full period.
91 ///
92 /// # Parameters
93 ///
94 /// * `ticks_to_wait` - Max ticks to wait if command queue is full
95 ///
96 /// # Returns
97 ///
98 /// * `True` - Command sent successfully
99 /// * `False` - Failed to send command
100 ///
101 /// # Examples
102 ///
103 /// ```ignore
104 /// timer.start(100); // Start with 100 tick timeout
105 /// ```
106 fn start(&self, ticks_to_wait: TickType) -> OsalRsBool;
107
108 /// Stops the timer.
109 ///
110 /// The timer will not expire until started again.
111 ///
112 /// # Parameters
113 ///
114 /// * `ticks_to_wait` - Max ticks to wait if command queue is full
115 ///
116 /// # Returns
117 ///
118 /// * `True` - Command sent successfully
119 /// * `False` - Failed to send command
120 ///
121 /// # Examples
122 ///
123 /// ```ignore
124 /// timer.stop(100);
125 /// ```
126 fn stop(&self, ticks_to_wait: TickType) -> OsalRsBool;
127
128 /// Resets the timer to its full period.
129 ///
130 /// If the timer is running, it restarts from the beginning.
131 /// If stopped, it starts the timer.
132 ///
133 /// # Parameters
134 ///
135 /// * `ticks_to_wait` - Max ticks to wait if command queue is full
136 ///
137 /// # Returns
138 ///
139 /// * `True` - Command sent successfully
140 /// * `False` - Failed to send command
141 ///
142 /// # Examples
143 ///
144 /// ```ignore
145 /// timer.reset(100); // Restart timer
146 /// ```
147 fn reset(&self, ticks_to_wait: TickType) -> OsalRsBool;
148
149 /// Changes the timer period.
150 ///
151 /// The new period takes effect immediately if the timer is running.
152 ///
153 /// # Parameters
154 ///
155 /// * `new_period_in_ticks` - New timer period in ticks
156 /// * `new_period_ticks` - Max ticks to wait if command queue is full
157 ///
158 /// # Returns
159 ///
160 /// * `True` - Command sent successfully
161 /// * `False` - Failed to send command
162 ///
163 /// # Examples
164 ///
165 /// ```ignore
166 /// // Change period to 500 ticks
167 /// timer.change_period(500, 100);
168 /// ```
169 fn change_period(&self, new_period_in_ticks: TickType, new_period_ticks: TickType) -> OsalRsBool;
170
171 /// Deletes the timer and frees its resources.
172 ///
173 /// The timer must be stopped before deletion.
174 ///
175 /// # Parameters
176 ///
177 /// * `ticks_to_wait` - Max ticks to wait if command queue is full
178 ///
179 /// # Returns
180 ///
181 /// * `True` - Command sent successfully
182 /// * `False` - Failed to send command
183 ///
184 /// # Examples
185 ///
186 /// ```ignore
187 /// let mut timer = Timer::new(...).unwrap();
188 /// timer.stop(100);
189 /// timer.delete(100);
190 /// ```
191 fn delete(&mut self, ticks_to_wait: TickType) -> OsalRsBool;
192}