1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
//! Low-level timer driver.
mod prescaler;
use embassy_hal_internal::Peri;
#[cfg(any(lptim_v2a, lptim_v2b))]
use super::channel::Channel;
#[cfg(any(lptim_v2a, lptim_v2b))]
mod channel_direction;
#[cfg(any(lptim_v2a, lptim_v2b))]
pub use channel_direction::ChannelDirection;
use prescaler::Prescaler;
use super::Instance;
use crate::rcc;
use crate::time::Hertz;
/// Low-level timer driver.
pub struct Timer<'d, T: Instance> {
_tim: Peri<'d, T>,
}
impl<'d, T: Instance> Timer<'d, T> {
/// Create a new timer driver.
pub fn new(tim: Peri<'d, T>) -> Self {
rcc::enable_and_reset::<T>();
Self { _tim: tim }
}
/// Enable the timer.
pub fn enable(&self) {
T::regs().cr().modify(|w| w.set_enable(true));
}
/// Disable the timer.
pub fn disable(&self) {
T::regs().cr().modify(|w| w.set_enable(false));
}
/// Start the timer in single pulse mode.
pub fn single_mode_start(&self) {
T::regs().cr().modify(|w| w.set_sngstrt(true));
}
/// Start the timer in continuous mode.
pub fn continuous_mode_start(&self) {
T::regs().cr().modify(|w| w.set_cntstrt(true));
}
/// Set the frequency of how many times per second the timer counts up to the max value or down to 0.
pub fn set_frequency(&self, frequency: Hertz) {
let f = frequency.0;
assert!(f > 0);
let pclk_f = T::frequency().0;
let pclk_ticks_per_timer_period = pclk_f / f;
let psc = Prescaler::from_ticks(pclk_ticks_per_timer_period);
let arr = psc.scale_down(pclk_ticks_per_timer_period);
T::regs().cfgr().modify(|r| r.set_presc((&psc).into()));
T::regs().arr().modify(|r| r.set_arr(arr.into()));
}
/// Get the timer frequency.
pub fn get_frequency(&self) -> Hertz {
let pclk_f = T::frequency();
let arr = T::regs().arr().read().arr();
let psc = Prescaler::from(T::regs().cfgr().read().presc());
pclk_f / psc.scale_up(arr)
}
/// Get the clock frequency of the timer (before prescaler is applied).
pub fn get_clock_frequency(&self) -> Hertz {
T::frequency()
}
/// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
pub fn get_max_compare_value(&self) -> u16 {
T::regs().arr().read().arr()
}
}
#[cfg(any(lptim_v2a, lptim_v2b))]
impl<'d, T: Instance> Timer<'d, T> {
/// Enable/disable a channel.
pub fn enable_channel(&self, channel: Channel, enable: bool) {
T::regs().ccmr(0).modify(|w| {
w.set_cce(channel.index(), enable);
});
}
/// Get enable/disable state of a channel
pub fn get_channel_enable_state(&self, channel: Channel) -> bool {
T::regs().ccmr(0).read().cce(channel.index())
}
/// Set compare value for a channel.
pub fn set_compare_value(&self, channel: Channel, value: u16) {
T::regs().ccr(channel.index()).modify(|w| w.set_ccr(value));
}
/// Get compare value for a channel.
pub fn get_compare_value(&self, channel: Channel) -> u16 {
T::regs().ccr(channel.index()).read().ccr()
}
/// Set channel direction.
#[cfg(any(lptim_v2a, lptim_v2b))]
pub fn set_channel_direction(&self, channel: Channel, direction: ChannelDirection) {
T::regs()
.ccmr(0)
.modify(|w| w.set_ccsel(channel.index(), direction.into()));
}
/// Enable the timer interrupt.
pub fn enable_interrupt(&self) {
T::regs().dier().modify(|w| w.set_arrmie(true));
}
/// Disable the timer interrupt.
pub fn disable_interrupt(&self) {
T::regs().dier().modify(|w| w.set_arrmie(false));
}
/// Check if the timer interrupt is enabled.
pub fn is_interrupt_enabled(&self) -> bool {
T::regs().dier().read().arrmie()
}
/// Check if the timer interrupt is pending.
pub fn is_interrupt_pending(&self) -> bool {
T::regs().isr().read().arrm()
}
/// Clear the timer interrupt.
pub fn clear_interrupt(&self) {
T::regs().icr().write(|w| w.set_arrmcf(true));
}
}
#[cfg(not(any(lptim_v2a, lptim_v2b)))]
impl<'d, T: Instance> Timer<'d, T> {
/// Set compare value for a channel.
pub fn set_compare_value(&self, value: u16) {
T::regs().cmp().modify(|w| w.set_cmp(value));
}
/// Get compare value for a channel.
pub fn get_compare_value(&self) -> u16 {
T::regs().cmp().read().cmp()
}
/// Enable the timer interrupt.
pub fn enable_interrupt(&self) {
T::regs().ier().modify(|w| w.set_arrmie(true));
}
/// Disable the timer interrupt.
pub fn disable_interrupt(&self) {
T::regs().ier().modify(|w| w.set_arrmie(false));
}
/// Check if the timer interrupt is enabled.
pub fn is_interrupt_enabled(&self) -> bool {
T::regs().ier().read().arrmie()
}
/// Check if the timer interrupt is pending.
pub fn is_interrupt_pending(&self) -> bool {
T::regs().isr().read().arrm()
}
/// Clear the timer interrupt.
pub fn clear_interrupt(&self) {
T::regs().icr().write(|w| w.set_arrmcf(true));
}
}
|