1pub mod cam;
9pub mod lcd;
10
11use core::marker::PhantomData;
12
13use crate::{
14 Async,
15 Blocking,
16 asynch::AtomicWaker,
17 handler,
18 interrupt::InterruptHandler,
19 lcd_cam::{cam::Cam, lcd::Lcd},
20 peripherals::{Interrupt, LCD_CAM},
21 system::{Cpu, GenericPeripheralGuard},
22};
23
24pub struct LcdCam<'d, Dm: crate::DriverMode> {
26 pub lcd: Lcd<'d, Dm>,
28 pub cam: Cam<'d>,
30}
31
32impl<'d> LcdCam<'d, Blocking> {
33 pub fn new(lcd_cam: LCD_CAM<'d>) -> Self {
35 let lcd_guard = GenericPeripheralGuard::new();
36 let cam_guard = GenericPeripheralGuard::new();
37
38 Self {
39 lcd: Lcd {
40 lcd_cam: unsafe { lcd_cam.clone_unchecked() },
41 _mode: PhantomData,
42 _guard: lcd_guard,
43 },
44 cam: Cam {
45 lcd_cam,
46 _guard: cam_guard,
47 },
48 }
49 }
50
51 pub fn into_async(mut self) -> LcdCam<'d, Async> {
53 self.set_interrupt_handler(interrupt_handler);
54 LcdCam {
55 lcd: Lcd {
56 lcd_cam: self.lcd.lcd_cam,
57 _mode: PhantomData,
58 _guard: self.lcd._guard,
59 },
60 cam: self.cam,
61 }
62 }
63
64 #[instability::unstable]
69 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
70 for core in crate::system::Cpu::other() {
71 crate::interrupt::disable(core, Interrupt::LCD_CAM);
72 }
73 crate::interrupt::bind_handler(Interrupt::LCD_CAM, handler);
74 }
75}
76
77impl crate::private::Sealed for LcdCam<'_, Blocking> {}
78#[instability::unstable]
81impl crate::interrupt::InterruptConfigurable for LcdCam<'_, Blocking> {
82 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
83 self.set_interrupt_handler(handler);
84 }
85}
86
87impl<'d> LcdCam<'d, Async> {
88 pub fn into_blocking(self) -> LcdCam<'d, Blocking> {
90 crate::interrupt::disable(Cpu::current(), Interrupt::LCD_CAM);
91 LcdCam {
92 lcd: Lcd {
93 lcd_cam: self.lcd.lcd_cam,
94 _mode: PhantomData,
95 _guard: self.lcd._guard,
96 },
97 cam: self.cam,
98 }
99 }
100}
101
102#[derive(Debug, Clone, Copy, PartialEq, Default)]
104#[cfg_attr(feature = "defmt", derive(defmt::Format))]
105pub enum BitOrder {
106 #[default]
108 Native = 0,
109 Inverted = 1,
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Default)]
115#[cfg_attr(feature = "defmt", derive(defmt::Format))]
116pub enum ByteOrder {
117 #[default]
119 Native = 0,
120 Inverted = 1,
122}
123
124pub(crate) static LCD_DONE_WAKER: AtomicWaker = AtomicWaker::new();
125
126#[handler]
127fn interrupt_handler() {
128 if Instance::is_lcd_done_set() {
130 Instance::unlisten_lcd_done();
131 LCD_DONE_WAKER.wake()
132 }
133}
134
135pub(crate) struct Instance;
136
137impl Instance {
141 fn enable_listenlcd_done(en: bool) {
142 LCD_CAM::regs()
143 .lc_dma_int_ena()
144 .modify(|_, w| w.lcd_trans_done_int_ena().bit(en));
145 }
146
147 pub(crate) fn listen_lcd_done() {
148 Self::enable_listenlcd_done(true);
149 }
150
151 pub(crate) fn unlisten_lcd_done() {
152 Self::enable_listenlcd_done(false);
153 }
154
155 pub(crate) fn is_lcd_done_set() -> bool {
156 LCD_CAM::regs()
157 .lc_dma_int_raw()
158 .read()
159 .lcd_trans_done_int_raw()
160 .bit()
161 }
162}
163pub(crate) struct ClockDivider {
164 pub div_num: usize,
169
170 pub div_b: usize,
172
173 pub div_a: usize,
175}
176
177#[derive(Debug, Clone, Copy, PartialEq)]
179#[cfg_attr(feature = "defmt", derive(defmt::Format))]
180pub enum ClockError {
181 FrequencyTooLow,
183}
184
185pub(crate) fn calculate_clkm(
186 desired_frequency: usize,
187 source_frequencies: &[usize],
188) -> Result<(usize, ClockDivider), ClockError> {
189 let mut result_freq = 0;
190 let mut result = None;
191
192 for (i, &source_frequency) in source_frequencies.iter().enumerate() {
193 let div = calculate_closest_divider(source_frequency, desired_frequency);
194 if let Some(div) = div {
195 let freq = calculate_output_frequency(source_frequency, &div);
196 if result.is_none() || freq > result_freq {
197 result = Some((i, div));
198 result_freq = freq;
199 }
200 }
201 }
202
203 result.ok_or(ClockError::FrequencyTooLow)
204}
205
206fn calculate_output_frequency(source_frequency: usize, divider: &ClockDivider) -> usize {
207 let n = match divider.div_num {
208 0 => 256,
209 1 => 2,
210 _ => divider.div_num.min(256),
211 };
212
213 if divider.div_b != 0 && divider.div_a != 0 {
214 let source = source_frequency as u64;
221 let n = n as u64;
222 let a = divider.div_b as u64;
223 let b = divider.div_a as u64;
224
225 ((source * a) / (n * a + b)) as _
226 } else {
227 source_frequency / n
228 }
229}
230
231fn calculate_closest_divider(
232 source_frequency: usize,
233 desired_frequency: usize,
234) -> Option<ClockDivider> {
235 let div_num = source_frequency / desired_frequency;
236 if div_num < 2 {
237 return Some(ClockDivider {
240 div_num: 1,
241 div_b: 0,
242 div_a: 0,
243 });
244 }
245 if div_num > 256 {
246 return None;
248 }
249
250 let div_num = if div_num == 256 { 0 } else { div_num };
251
252 let div_fraction = {
253 let div_remainder = source_frequency % desired_frequency;
254 let gcd = hcf(div_remainder, desired_frequency);
255 Fraction {
256 numerator: div_remainder / gcd,
257 denominator: desired_frequency / gcd,
258 }
259 };
260
261 let divider = if div_fraction.numerator == 0 {
262 ClockDivider {
263 div_num,
264 div_b: 0,
265 div_a: 0,
266 }
267 } else {
268 let target = div_fraction;
269 let closest = farey_sequence(63).find(|curr| {
270 let new_curr_num = curr.numerator * target.denominator;
273 let new_target_num = target.numerator * curr.denominator;
274 new_curr_num >= new_target_num
275 });
276
277 let closest = unwrap!(closest, "The fraction must be between 0 and 1");
278
279 ClockDivider {
280 div_num,
281 div_b: closest.numerator,
282 div_a: closest.denominator,
283 }
284 };
285 Some(divider)
286}
287
288const fn hcf(a: usize, b: usize) -> usize {
290 if b != 0 { hcf(b, a % b) } else { a }
291}
292
293struct Fraction {
294 pub numerator: usize,
295 pub denominator: usize,
296}
297
298fn farey_sequence(denominator: usize) -> impl Iterator<Item = Fraction> {
300 let mut a = 0;
301 let mut b = 1;
302 let mut c = 1;
303 let mut d = denominator;
304 core::iter::from_fn(move || {
305 if a > denominator {
306 return None;
307 }
308 let next = Fraction {
309 numerator: a,
310 denominator: b,
311 };
312 let k = (denominator + b) / d;
313 (a, b, c, d) = (c, d, k * c - a, k * d - b);
314 Some(next)
315 })
316}