aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/hrtim
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-07-28 17:16:46 -0500
committerxoviat <[email protected]>2023-07-28 17:16:46 -0500
commite495d606ec62ccfd72eaf9fc868455da217e2d5c (patch)
treed967e3ec3dad2ef895502bd42dc63f917c4a0faa /embassy-stm32/src/hrtim
parent28136579e98ea4d9745867d7c1ffff0ad826b504 (diff)
stm32/hrtim: extract traits
Diffstat (limited to 'embassy-stm32/src/hrtim')
-rw-r--r--embassy-stm32/src/hrtim/mod.rs6
-rw-r--r--embassy-stm32/src/hrtim/traits.rs196
2 files changed, 200 insertions, 2 deletions
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs
index 7e3a8f144..ddf8cc2a8 100644
--- a/embassy-stm32/src/hrtim/mod.rs
+++ b/embassy-stm32/src/hrtim/mod.rs
@@ -1,3 +1,5 @@
1mod traits;
2
1use core::marker::PhantomData; 3use core::marker::PhantomData;
2 4
3use embassy_hal_common::{into_ref, PeripheralRef}; 5use embassy_hal_common::{into_ref, PeripheralRef};
@@ -5,7 +7,7 @@ use embassy_hal_common::{into_ref, PeripheralRef};
5#[allow(unused_imports)] 7#[allow(unused_imports)]
6use crate::gpio::sealed::{AFType, Pin}; 8use crate::gpio::sealed::{AFType, Pin};
7use crate::gpio::AnyPin; 9use crate::gpio::AnyPin;
8use crate::pwm::HighResolutionCaptureCompare16bitInstance; 10use crate::hrtim::traits::HighResolutionCaptureCompare16bitInstance;
9use crate::time::Hertz; 11use crate::time::Hertz;
10use crate::Peripheral; 12use crate::Peripheral;
11 13
@@ -41,7 +43,7 @@ pub struct ChE<T: HighResolutionCaptureCompare16bitInstance> {
41} 43}
42 44
43mod sealed { 45mod sealed {
44 use crate::pwm::HighResolutionCaptureCompare16bitInstance; 46 use super::HighResolutionCaptureCompare16bitInstance;
45 47
46 pub trait AdvancedChannel<T: HighResolutionCaptureCompare16bitInstance> { 48 pub trait AdvancedChannel<T: HighResolutionCaptureCompare16bitInstance> {
47 fn raw() -> usize; 49 fn raw() -> usize;
diff --git a/embassy-stm32/src/hrtim/traits.rs b/embassy-stm32/src/hrtim/traits.rs
new file mode 100644
index 000000000..16193a450
--- /dev/null
+++ b/embassy-stm32/src/hrtim/traits.rs
@@ -0,0 +1,196 @@
1use crate::time::Hertz;
2
3#[derive(Clone, Copy)]
4pub(crate) enum HighResolutionControlPrescaler {
5 Div1,
6 Div2,
7 Div4,
8 Div8,
9 Div16,
10 Div32,
11 Div64,
12 Div128,
13}
14
15impl From<HighResolutionControlPrescaler> for u32 {
16 fn from(val: HighResolutionControlPrescaler) -> Self {
17 match val {
18 HighResolutionControlPrescaler::Div1 => 1,
19 HighResolutionControlPrescaler::Div2 => 2,
20 HighResolutionControlPrescaler::Div4 => 4,
21 HighResolutionControlPrescaler::Div8 => 8,
22 HighResolutionControlPrescaler::Div16 => 16,
23 HighResolutionControlPrescaler::Div32 => 32,
24 HighResolutionControlPrescaler::Div64 => 64,
25 HighResolutionControlPrescaler::Div128 => 128,
26 }
27 }
28}
29
30impl From<HighResolutionControlPrescaler> for u8 {
31 fn from(val: HighResolutionControlPrescaler) -> Self {
32 match val {
33 HighResolutionControlPrescaler::Div1 => 0b000,
34 HighResolutionControlPrescaler::Div2 => 0b001,
35 HighResolutionControlPrescaler::Div4 => 0b010,
36 HighResolutionControlPrescaler::Div8 => 0b011,
37 HighResolutionControlPrescaler::Div16 => 0b100,
38 HighResolutionControlPrescaler::Div32 => 0b101,
39 HighResolutionControlPrescaler::Div64 => 0b110,
40 HighResolutionControlPrescaler::Div128 => 0b111,
41 }
42 }
43}
44
45impl From<u8> for HighResolutionControlPrescaler {
46 fn from(val: u8) -> Self {
47 match val {
48 0b000 => HighResolutionControlPrescaler::Div1,
49 0b001 => HighResolutionControlPrescaler::Div2,
50 0b010 => HighResolutionControlPrescaler::Div4,
51 0b011 => HighResolutionControlPrescaler::Div8,
52 0b100 => HighResolutionControlPrescaler::Div16,
53 0b101 => HighResolutionControlPrescaler::Div32,
54 0b110 => HighResolutionControlPrescaler::Div64,
55 0b111 => HighResolutionControlPrescaler::Div128,
56 _ => unreachable!(),
57 }
58 }
59}
60
61impl HighResolutionControlPrescaler {
62 pub fn compute_min_high_res(val: u32) -> Self {
63 *[
64 HighResolutionControlPrescaler::Div1,
65 HighResolutionControlPrescaler::Div2,
66 HighResolutionControlPrescaler::Div4,
67 HighResolutionControlPrescaler::Div8,
68 HighResolutionControlPrescaler::Div16,
69 HighResolutionControlPrescaler::Div32,
70 HighResolutionControlPrescaler::Div64,
71 HighResolutionControlPrescaler::Div128,
72 ]
73 .iter()
74 .skip_while(|psc| <HighResolutionControlPrescaler as Into<u32>>::into(**psc) <= val)
75 .next()
76 .unwrap()
77 }
78
79 pub fn compute_min_low_res(val: u32) -> Self {
80 *[
81 HighResolutionControlPrescaler::Div32,
82 HighResolutionControlPrescaler::Div64,
83 HighResolutionControlPrescaler::Div128,
84 ]
85 .iter()
86 .skip_while(|psc| <HighResolutionControlPrescaler as Into<u32>>::into(**psc) <= val)
87 .next()
88 .unwrap()
89 }
90}
91
92pub(crate) mod sealed {
93 use super::*;
94
95 pub trait HighResolutionCaptureCompare16bitInstance: crate::timer::sealed::HighResolutionControlInstance {
96 fn set_master_frequency(frequency: Hertz);
97
98 fn set_channel_frequency(channnel: usize, frequency: Hertz);
99
100 /// Set the dead time as a proportion of max_duty
101 fn set_channel_dead_time(channnel: usize, dead_time: u16);
102
103 // fn enable_outputs(enable: bool);
104 //
105 // fn enable_channel(&mut self, channel: usize, enable: bool);
106 }
107}
108
109pub trait HighResolutionCaptureCompare16bitInstance:
110 sealed::HighResolutionCaptureCompare16bitInstance + 'static
111{
112}
113
114foreach_interrupt! {
115 ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => {
116 impl sealed::HighResolutionCaptureCompare16bitInstance for crate::peripherals::$inst {
117 fn set_master_frequency(frequency: Hertz) {
118 use crate::rcc::sealed::RccPeripheral;
119 use crate::timer::sealed::HighResolutionControlInstance;
120
121 let f = frequency.0;
122 let timer_f = Self::frequency().0;
123 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
124 let psc = if Self::regs().isr().read().dllrdy() {
125 HighResolutionControlPrescaler::compute_min_high_res(psc_min)
126 } else {
127 HighResolutionControlPrescaler::compute_min_low_res(psc_min)
128 };
129
130 let psc_val: u32 = psc.into();
131 let timer_f = 32 * (timer_f / psc_val);
132 let per: u16 = (timer_f / f) as u16;
133
134 let regs = Self::regs();
135
136 regs.mcr().modify(|w| w.set_ckpsc(psc.into()));
137 regs.mper().modify(|w| w.set_mper(per));
138 }
139
140 fn set_channel_frequency(channel: usize, frequency: Hertz) {
141 use crate::rcc::sealed::RccPeripheral;
142 use crate::timer::sealed::HighResolutionControlInstance;
143
144 let f = frequency.0;
145 let timer_f = Self::frequency().0;
146 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
147 let psc = if Self::regs().isr().read().dllrdy() {
148 HighResolutionControlPrescaler::compute_min_high_res(psc_min)
149 } else {
150 HighResolutionControlPrescaler::compute_min_low_res(psc_min)
151 };
152
153 let psc_val: u32 = psc.into();
154 let timer_f = 32 * (timer_f / psc_val);
155 let per: u16 = (timer_f / f) as u16;
156
157 let regs = Self::regs();
158
159 regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into()));
160 regs.tim(channel).per().modify(|w| w.set_per(per));
161 }
162
163 fn set_channel_dead_time(channel: usize, dead_time: u16) {
164 use crate::timer::sealed::HighResolutionControlInstance;
165
166 let regs = Self::regs();
167
168 let channel_psc: HighResolutionControlPrescaler = regs.tim(channel).cr().read().ckpsc().into();
169 let psc_val: u32 = channel_psc.into();
170
171
172 // The dead-time base clock runs 4 times slower than the hrtim base clock
173 // u9::MAX = 511
174 let psc_min = (psc_val * dead_time as u32) / (4 * 511);
175 let psc = if Self::regs().isr().read().dllrdy() {
176 HighResolutionControlPrescaler::compute_min_high_res(psc_min)
177 } else {
178 HighResolutionControlPrescaler::compute_min_low_res(psc_min)
179 };
180
181 let dt_psc_val: u32 = psc.into();
182 let dt_val = (dt_psc_val * dead_time as u32) / (4 * psc_val);
183
184 regs.tim(channel).dt().modify(|w| {
185 w.set_dtprsc(psc.into());
186 w.set_dtf(dt_val as u16);
187 w.set_dtr(dt_val as u16);
188 });
189 }
190 }
191
192 impl HighResolutionCaptureCompare16bitInstance for crate::peripherals::$inst {
193
194 }
195 };
196}