1use crate::prelude::v1::*;
2use crate::base::*;
3use crate::shim::*;
4use crate::units::*;
5
6unsafe impl Send for Timer {}
7unsafe impl Sync for Timer {}
8
9pub struct Timer {
15 handle: FreeRtosTimerHandle,
16 detached: bool
17}
18
19pub struct TimerBuilder<D: DurationTicks> {
21 name: String,
22 period: D,
23 auto_reload: bool
24}
25
26impl<D: DurationTicks> TimerBuilder<D> {
27 pub fn set_name(&mut self, name: &str) -> &mut Self {
29 self.name = name.into();
30 self
31 }
32
33 pub fn set_period(&mut self, period: D) -> &mut Self {
35 self.period = period;
36 self
37 }
38
39 pub fn set_auto_reload(&mut self, auto_reload: bool) -> &mut Self {
41 self.auto_reload = auto_reload;
42 self
43 }
44
45 pub fn create<F>(&self, callback: F) -> Result<Timer, FreeRtosError>
49 where F: Fn(Timer) -> (),
50 F: Send + 'static
51 {
52 Timer::spawn(self.name.as_str(), self.period.to_ticks(), self.auto_reload, callback)
53 }
54}
55
56
57
58impl Timer {
59 pub fn new<D: DurationTicks>(period: D) -> TimerBuilder<D> {
61 TimerBuilder {
62 name: "timer".into(),
63 period: period,
64 auto_reload: true
65 }
66 }
67
68 unsafe fn spawn_inner<'a>(name: &str,
69 period_ticks: FreeRtosTickType,
70 auto_reload: bool,
71 callback: Box<dyn Fn(Timer) + Send + 'a>,)
72 -> Result<Timer, FreeRtosError> {
73 let f = Box::new(callback);
74 let param_ptr = &*f as *const _ as *mut _;
75
76 let (success, timer_handle) = {
77 let name = name.as_bytes();
78 let name_len = name.len();
79 let mut _timer_handle = mem::zeroed::<CVoid>();
80
81 let ret = freertos_rs_timer_create(name.as_ptr(),
82 name_len as u8,
83 period_ticks,
84 if auto_reload { 1 } else { 0 },
85 param_ptr,
86 timer_callback);
87
88 ((ret as usize) != 0, ret)
89 };
90
91 if success {
92 mem::forget(f);
93 } else {
94 return Err(FreeRtosError::OutOfMemory);
95 }
96
97 extern "C" fn timer_callback(handle: FreeRtosTimerHandle) -> () {
98 unsafe {
99 {
100 let timer = Timer {
101 handle: handle,
102 detached: true
103 };
104 if let Ok(callback_ptr) = timer.get_id() {
105 let b = Box::from_raw(callback_ptr as *mut Box<dyn Fn(Timer)>);
106 b(timer);
107 Box::into_raw(b);
108 }
109 }
110 }
111 }
112
113 Ok(Timer {
114 handle: timer_handle as *const _,
115 detached: false
116 })
117 }
118
119
120 fn spawn<F>(name: &str,
121 period_tick: FreeRtosTickType,
122 auto_reload: bool,
123 callback: F)
124 -> Result<Timer, FreeRtosError>
125 where F: Fn(Timer) -> (),
126 F: Send + 'static
127 {
128 unsafe {
129 Timer::spawn_inner(name, period_tick, auto_reload, Box::new(callback))
130 }
131 }
132
133 pub fn start<D: DurationTicks>(&self, block_time: D) -> Result<(), FreeRtosError> {
135 unsafe {
136 if freertos_rs_timer_start(self.handle, block_time.to_ticks()) == 0 {
137 Ok(())
138 } else {
139 Err(FreeRtosError::Timeout)
140 }
141 }
142 }
143
144 pub fn stop<D: DurationTicks>(&self, block_time: D) -> Result<(), FreeRtosError> {
146 unsafe {
147 if freertos_rs_timer_stop(self.handle, block_time.to_ticks()) == 0 {
148 Ok(())
149 } else {
150 Err(FreeRtosError::Timeout)
151 }
152 }
153 }
154
155 pub fn change_period<D: DurationTicks>(&self, block_time: D, new_period: D) -> Result<(), FreeRtosError> {
157 unsafe {
158 if freertos_rs_timer_change_period(self.handle, block_time.to_ticks(), new_period.to_ticks()) == 0 {
159 Ok(())
160 } else {
161 Err(FreeRtosError::Timeout)
162 }
163 }
164 }
165
166 pub unsafe fn detach(mut self) {
171 self.detached = true;
172 }
173
174 fn get_id(&self) -> Result<FreeRtosVoidPtr, FreeRtosError> {
175 unsafe {
176 Ok(freertos_rs_timer_get_id(self.handle))
177 }
178 }
179}
180
181
182impl Drop for Timer {
183 #[allow(unused_must_use)]
184 fn drop(&mut self) {
185 if self.detached == true { return; }
186
187 unsafe {
188 if let Ok(callback_ptr) = self.get_id() {
189 Box::from_raw(callback_ptr as *mut Box<dyn Fn(Timer)>);
191 }
192
193 freertos_rs_timer_delete(self.handle, Duration::ms(1000).to_ticks());
195 }
196 }
197}