1use crate::gpio::gpioa::{PTB6, PTB7};
5use crate::pac::OSC;
6use core::marker::PhantomData;
7
8pub enum Error {
10 InvalidValue,
12
13 NoPin,
15}
16
17pub struct DontCare;
23
24pub struct Stopped;
26
27pub struct Running;
29
30pub struct Unstoppable;
32
33pub struct Osc<Status, OscType, Range, Gain, ExtalPinState, XtalPinState> {
37 _status: PhantomData<Status>,
38 _osc_type: PhantomData<OscType>,
39 _range: PhantomData<Range>,
40 _gain: PhantomData<Gain>,
41 extal_pin: Option<PTB7<ExtalPinState>>,
42 xtal_pin: Option<PTB6<XtalPinState>>,
43}
44
45pub trait OSCExt {
47 type Osc;
49
50 fn split(self) -> Self::Osc;
52}
53
54impl OSCExt for OSC {
55 type Osc = Osc<Stopped, ExtClock, LowRange, VariableGain, DontCare, DontCare>;
56 fn split(self) -> Osc<Stopped, ExtClock, LowRange, VariableGain, DontCare, DontCare> {
57 Osc {
58 _status: PhantomData,
59 _osc_type: PhantomData, _range: PhantomData, _gain: PhantomData, extal_pin: None,
63 xtal_pin: None,
64 }
65 }
66}
67
68pub struct ExtClock;
70
71pub struct ExtOsc;
73
74pub struct LowRange;
76
77pub struct HighRange;
79
80pub struct VariableGain;
82
83pub struct HighGain;
85
86impl<OscType, Range, Gain, ExtalPinState, XtalPinState>
87 Osc<Stopped, OscType, Range, Gain, ExtalPinState, XtalPinState>
88{
89 pub fn into_running(
91 self,
92 extal_pin: PTB7<ExtalPinState>,
93 ) -> Osc<Running, OscType, Range, Gain, ExtalPinState, XtalPinState> {
94 let osc = unsafe { &(*OSC::ptr()) };
95
96 osc.cr.modify(|_, w| w.oscen().set_bit());
98
99 while osc.cr.read().oscinit().is_0() {
101 cortex_m::asm::nop();
102 }
103
104 Osc {
105 _status: PhantomData,
106 _osc_type: PhantomData,
107 _range: PhantomData,
108 _gain: PhantomData,
109 extal_pin: Some(extal_pin),
110 xtal_pin: self.xtal_pin,
111 }
112 }
113
114 pub fn release_extal_pin(
119 self,
120 ) -> (
121 Result<PTB7<ExtalPinState>, Error>,
122 Osc<Stopped, OscType, Range, Gain, DontCare, XtalPinState>,
123 ) {
124 (
125 self.extal_pin.ok_or(Error::NoPin),
126 Osc {
127 _status: PhantomData,
128 _osc_type: PhantomData,
129 _range: PhantomData,
130 _gain: PhantomData,
131 extal_pin: None,
132 xtal_pin: self.xtal_pin,
133 },
134 )
135 }
136}
137
138impl<OscType, Range, Gain, ExtalPinState, XtalPinState>
139 Osc<Running, OscType, Range, Gain, ExtalPinState, XtalPinState>
140{
141 pub fn into_unstoppable(
144 self,
145 ) -> Osc<Unstoppable, OscType, Range, Gain, ExtalPinState, XtalPinState> {
146 unsafe {
147 (*OSC::ptr()).cr.modify(|_, w| w.oscsten().set_bit());
148 }
149 Osc {
150 _status: PhantomData,
151 _osc_type: PhantomData,
152 _range: PhantomData,
153 _gain: PhantomData,
154 extal_pin: self.extal_pin,
155 xtal_pin: self.xtal_pin,
156 }
157 }
158
159 pub fn into_stopped(self) -> Osc<Stopped, OscType, Range, Gain, ExtalPinState, XtalPinState> {
164 let osc = unsafe { &(*OSC::ptr()) };
165 osc.cr.modify(|_, w| w.oscen().clear_bit());
166 Osc {
167 _status: PhantomData,
168 _osc_type: PhantomData,
169 _range: PhantomData,
170 _gain: PhantomData,
171 extal_pin: self.extal_pin,
172 xtal_pin: self.xtal_pin,
173 }
174 }
175}
176
177impl<OscType, Range, Gain, ExtalPinState, XtalPinState>
178 Osc<Unstoppable, OscType, Range, Gain, ExtalPinState, XtalPinState>
179{
180 pub fn into_running(self) -> Osc<Running, OscType, Range, Gain, ExtalPinState, XtalPinState> {
183 unsafe {
184 (*OSC::ptr()).cr.modify(|_, w| w.oscsten().clear_bit());
185 }
186 Osc {
187 _status: PhantomData,
188 _osc_type: PhantomData,
189 _range: PhantomData,
190 _gain: PhantomData,
191 extal_pin: self.extal_pin,
192 xtal_pin: self.xtal_pin,
193 }
194 }
195
196 pub fn into_stopped(self) -> Osc<Stopped, OscType, Range, Gain, ExtalPinState, XtalPinState> {
201 let osc = unsafe { &(*OSC::ptr()) };
202 osc.cr.modify(|_, w| w.oscen().clear_bit());
203 Osc {
204 _status: PhantomData,
205 _osc_type: PhantomData,
206 _range: PhantomData,
207 _gain: PhantomData,
208 extal_pin: self.extal_pin,
209 xtal_pin: self.xtal_pin,
210 }
211 }
212}
213
214impl<Status, Range, Gain, ExtalPinState, XtalPinState>
215 Osc<Status, ExtOsc, Range, Gain, ExtalPinState, XtalPinState>
216{
217 pub fn into_ext_clock(self) -> Osc<Status, ExtClock, Range, Gain, ExtalPinState, XtalPinState> {
221 unsafe {
222 (*OSC::ptr()).cr.modify(|_, w| w.oscos()._0());
223 }
224 Osc {
225 _status: PhantomData,
226 _osc_type: PhantomData,
227 _range: PhantomData,
228 _gain: PhantomData,
229 extal_pin: self.extal_pin,
230 xtal_pin: self.xtal_pin,
231 }
232 }
233}
234
235impl<Status, Range, Gain, ExtalPinState, XtalPinState>
236 Osc<Status, ExtClock, Range, Gain, ExtalPinState, XtalPinState>
237{
238 pub fn into_ext_osc(self) -> Osc<Status, ExtOsc, Range, Gain, ExtalPinState, XtalPinState> {
242 unsafe { (*OSC::ptr()).cr.modify(|_, w| w.oscos()._1()) }
243 Osc {
244 _status: PhantomData,
245 _osc_type: PhantomData,
246 _range: PhantomData,
247 _gain: PhantomData,
248 extal_pin: self.extal_pin,
249 xtal_pin: self.xtal_pin,
250 }
251 }
252
253 pub fn release_xtal_pin(
260 self,
261 ) -> (
262 Result<PTB6<XtalPinState>, Error>,
263 Osc<Status, ExtClock, Range, Gain, ExtalPinState, DontCare>,
264 ) {
265 (
266 self.xtal_pin.ok_or(Error::NoPin),
267 Osc {
268 _status: PhantomData,
269 _osc_type: PhantomData,
270 _range: PhantomData,
271 _gain: PhantomData,
272 extal_pin: self.extal_pin,
273 xtal_pin: None,
274 },
275 )
276 }
277}
278
279impl<OscType, Gain, ExtalPinState, XtalPinState>
281 Osc<Stopped, OscType, LowRange, Gain, ExtalPinState, XtalPinState>
282{
283 pub fn into_high_range(
287 self,
288 ) -> Osc<Stopped, OscType, HighRange, Gain, ExtalPinState, XtalPinState> {
289 unsafe {
290 (*OSC::ptr()).cr.modify(|_, w| w.range().set_bit());
291 }
292 Osc {
293 _status: PhantomData,
294 _osc_type: PhantomData,
295 _range: PhantomData,
296 _gain: PhantomData,
297 extal_pin: self.extal_pin,
298 xtal_pin: self.xtal_pin,
299 }
300 }
301}
302
303impl<OscType, Gain, ExtalPinState, XtalPinState>
305 Osc<Stopped, OscType, HighRange, Gain, ExtalPinState, XtalPinState>
306{
307 pub fn into_low_range(
311 self,
312 ) -> Osc<Stopped, OscType, HighRange, Gain, ExtalPinState, XtalPinState> {
313 unsafe {
314 (*OSC::ptr()).cr.modify(|_, w| w.range().clear_bit());
315 }
316 Osc {
317 _status: PhantomData,
318 _osc_type: PhantomData,
319 _range: PhantomData,
320 _gain: PhantomData,
321 extal_pin: self.extal_pin,
322 xtal_pin: self.xtal_pin,
323 }
324 }
325}
326
327impl<Status, OscType, Range, ExtalPinState, XtalPinState>
330 Osc<Status, OscType, Range, HighGain, ExtalPinState, XtalPinState>
331{
332 pub fn into_variable_gain(
337 self,
338 ) -> Osc<Status, OscType, Range, VariableGain, ExtalPinState, XtalPinState> {
339 unsafe {
340 (*OSC::ptr()).cr.modify(|_, w| w.hgo().clear_bit());
341 };
342 Osc {
343 _status: PhantomData,
344 _osc_type: PhantomData,
345 _range: PhantomData,
346 _gain: PhantomData,
347 extal_pin: self.extal_pin,
348 xtal_pin: self.xtal_pin,
349 }
350 }
351}
352
353impl<Status, OscType, Range, ExtalPinState, XtalPinState>
354 Osc<Status, OscType, Range, HighGain, ExtalPinState, XtalPinState>
355{
356 pub fn into_high_gain(
361 self,
362 ) -> Osc<Status, OscType, Range, HighGain, ExtalPinState, XtalPinState> {
363 unsafe {
364 (*OSC::ptr()).cr.modify(|_, w| w.hgo().set_bit());
365 };
366 Osc {
367 _status: PhantomData,
368 _osc_type: PhantomData,
369 _range: PhantomData,
370 _gain: PhantomData,
371 extal_pin: self.extal_pin,
372 xtal_pin: self.xtal_pin,
373 }
374 }
375}