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 /// Creates a new software timer.
89 ///
90 /// # Parameters
91 ///
92 /// * `name` - Timer name for debugging
93 /// * `timer_period_in_ticks` - Timer period in ticks
94 /// * `auto_reload` - `true` for periodic, `false` for one-shot
95 /// * `param` - Optional parameter passed to callback
96 /// * `callback` - Function called when timer expires
97 ///
98 /// # Returns
99 ///
100 /// * `Ok(Self)` - Successfully created timer
101 /// * `Err(Error)` - Creation failed
102 ///
103 /// # Examples
104 ///
105 /// ```ignore
106 /// use osal_rs::os::{Timer, TimerFn};
107 ///
108 /// let timer = Timer::new(
109 /// "my_timer",
110 /// 1000,
111 /// false,
112 /// None,
113 /// |_timer, _param| Ok(None)
114 /// ).unwrap();
115 /// ```
116 fn new<F>(name: &str, timer_period_in_ticks: TickType, auto_reload: bool, param: Option<TimerParam>, callback: F) -> Result<Self>
117 where
118 Self: Sized,
119 F: Fn(Box<dyn Timer>, Option<TimerParam>) -> Result<TimerParam> + Send + Sync + Clone + 'static;
120
121 /// Starts or restarts the timer.
122 ///
123 /// If the timer is already running, it is reset to its full period.
124 ///
125 /// # Parameters
126 ///
127 /// * `ticks_to_wait` - Max ticks to wait if command queue is full
128 ///
129 /// # Returns
130 ///
131 /// * `True` - Command sent successfully
132 /// * `False` - Failed to send command
133 ///
134 /// # Examples
135 ///
136 /// ```ignore
137 /// timer.start(100); // Start with 100 tick timeout
138 /// ```
139 fn start(&self, ticks_to_wait: TickType) -> OsalRsBool;
140
141 /// Stops the timer.
142 ///
143 /// The timer will not expire until started again.
144 ///
145 /// # Parameters
146 ///
147 /// * `ticks_to_wait` - Max ticks to wait if command queue is full
148 ///
149 /// # Returns
150 ///
151 /// * `True` - Command sent successfully
152 /// * `False` - Failed to send command
153 ///
154 /// # Examples
155 ///
156 /// ```ignore
157 /// timer.stop(100);
158 /// ```
159 fn stop(&self, ticks_to_wait: TickType) -> OsalRsBool;
160
161 /// Resets the timer to its full period.
162 ///
163 /// If the timer is running, it restarts from the beginning.
164 /// If stopped, it starts the timer.
165 ///
166 /// # Parameters
167 ///
168 /// * `ticks_to_wait` - Max ticks to wait if command queue is full
169 ///
170 /// # Returns
171 ///
172 /// * `True` - Command sent successfully
173 /// * `False` - Failed to send command
174 ///
175 /// # Examples
176 ///
177 /// ```ignore
178 /// timer.reset(100); // Restart timer
179 /// ```
180 fn reset(&self, ticks_to_wait: TickType) -> OsalRsBool;
181
182 /// Changes the timer period.
183 ///
184 /// The new period takes effect immediately if the timer is running.
185 ///
186 /// # Parameters
187 ///
188 /// * `new_period_in_ticks` - New timer period in ticks
189 /// * `new_period_ticks` - Max ticks to wait if command queue is full
190 ///
191 /// # Returns
192 ///
193 /// * `True` - Command sent successfully
194 /// * `False` - Failed to send command
195 ///
196 /// # Examples
197 ///
198 /// ```ignore
199 /// // Change period to 500 ticks
200 /// timer.change_period(500, 100);
201 /// ```
202 fn change_period(&self, new_period_in_ticks: TickType, new_period_ticks: TickType) -> OsalRsBool;
203
204 /// Deletes the timer and frees its resources.
205 ///
206 /// The timer must be stopped before deletion.
207 ///
208 /// # Parameters
209 ///
210 /// * `ticks_to_wait` - Max ticks to wait if command queue is full
211 ///
212 /// # Returns
213 ///
214 /// * `True` - Command sent successfully
215 /// * `False` - Failed to send command
216 ///
217 /// # Examples
218 ///
219 /// ```ignore
220 /// let mut timer = Timer::new(...).unwrap();
221 /// timer.stop(100);
222 /// timer.delete(100);
223 /// ```
224 fn delete(&mut self, ticks_to_wait: TickType) -> OsalRsBool;
225}