diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index abf7b5d398f..dee3a375949 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -81,7 +81,7 @@ use crate::{ OutputSignal, Pull, }, - lcd_cam::{cam::private::RxPins, private::calculate_clkm, BitOrder, ByteOrder}, + lcd_cam::{calculate_clkm, BitOrder, ByteOrder}, peripheral::{Peripheral, PeripheralRef}, peripherals::LCD_CAM, }; @@ -604,8 +604,7 @@ impl RxPins for RxSixteenBits { const BUS_WIDTH: usize = 2; } -mod private { - pub trait RxPins { - const BUS_WIDTH: usize; - } +#[doc(hidden)] +pub trait RxPins { + const BUS_WIDTH: usize; } diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index 72ab45dea80..2017f4d07cb 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -75,12 +75,13 @@ use crate::{ OutputSignal, }, lcd_cam::{ - asynch::LCD_DONE_WAKER, - lcd::{i8080::private::TxPins, ClockMode, DelayMode, Phase, Polarity}, - private::{calculate_clkm, Instance}, + calculate_clkm, + lcd::{ClockMode, DelayMode, Phase, Polarity}, BitOrder, ByteOrder, + Instance, Lcd, + LCD_DONE_WAKER, }, peripheral::{Peripheral, PeripheralRef}, peripherals::LCD_CAM, @@ -703,8 +704,7 @@ impl<'d> TxPins for TxSixteenBits<'d> { } } -mod private { - pub trait TxPins { - fn configure(&mut self); - } +#[doc(hidden)] +pub trait TxPins { + fn configure(&mut self); } diff --git a/esp-hal/src/lcd_cam/mod.rs b/esp-hal/src/lcd_cam/mod.rs index 38a29f83b4a..3e095151fe0 100644 --- a/esp-hal/src/lcd_cam/mod.rs +++ b/esp-hal/src/lcd_cam/mod.rs @@ -10,12 +10,18 @@ pub mod lcd; use core::marker::PhantomData; +use embassy_sync::waitqueue::AtomicWaker; + use crate::{ interrupt::InterruptHandler, lcd_cam::{cam::Cam, lcd::Lcd}, + macros::handler, peripheral::Peripheral, - peripherals::LCD_CAM, + peripherals::{Interrupt, LCD_CAM}, system::{self, PeripheralClockControl}, + Async, + Blocking, + Cpu, InterruptConfigurable, }; @@ -27,7 +33,7 @@ pub struct LcdCam<'d, DM: crate::Mode> { pub cam: Cam<'d>, } -impl<'d> LcdCam<'d, crate::Blocking> { +impl<'d> LcdCam<'d, Blocking> { /// Creates a new `LcdCam` instance. pub fn new(lcd_cam: impl Peripheral
+ 'd) -> Self { crate::into_ref!(lcd_cam); @@ -40,56 +46,47 @@ impl<'d> LcdCam<'d, crate::Blocking> { lcd_cam: unsafe { lcd_cam.clone_unchecked() }, _mode: PhantomData, }, - cam: Cam { - lcd_cam: unsafe { lcd_cam.clone_unchecked() }, + cam: Cam { lcd_cam }, + } + } + + /// Reconfigures the peripheral for asynchronous operation. + pub fn into_async(mut self) -> LcdCam<'d, Async> { + self.set_interrupt_handler(interrupt_handler); + LcdCam { + lcd: Lcd { + lcd_cam: self.lcd.lcd_cam, + _mode: PhantomData, }, + cam: self.cam, } } } -impl<'d> crate::private::Sealed for LcdCam<'d, crate::Blocking> {} +impl crate::private::Sealed for LcdCam<'_, Blocking> {} // TODO: This interrupt is shared with the Camera module, we should handle this // in a similar way to the gpio::IO -impl<'d> InterruptConfigurable for LcdCam<'d, crate::Blocking> { +impl InterruptConfigurable for LcdCam<'_, Blocking> { fn set_interrupt_handler(&mut self, handler: InterruptHandler) { unsafe { - crate::interrupt::bind_interrupt( - crate::peripherals::Interrupt::LCD_CAM, - handler.handler(), - ); - crate::interrupt::enable(crate::peripherals::Interrupt::LCD_CAM, handler.priority()) - .unwrap(); + crate::interrupt::bind_interrupt(Interrupt::LCD_CAM, handler.handler()); + crate::interrupt::enable(Interrupt::LCD_CAM, handler.priority()).unwrap(); } } } -impl<'d> LcdCam<'d, crate::Async> { - /// Creates a new `LcdCam` instance for asynchronous operation. - pub fn new_async(lcd_cam: impl Peripheral
+ 'd) -> Self {
- crate::into_ref!(lcd_cam);
-
- PeripheralClockControl::enable(system::Peripheral::LcdCam);
-
- unsafe {
- crate::interrupt::bind_interrupt(
- crate::peripherals::Interrupt::LCD_CAM,
- asynch::interrupt_handler.handler(),
- );
- }
- crate::interrupt::enable(
- crate::peripherals::Interrupt::LCD_CAM,
- asynch::interrupt_handler.priority(),
- )
- .unwrap();
-
- Self {
+impl<'d> LcdCam<'d, Async> {
+ /// Reconfigures the peripheral for blocking operation.
+ pub fn into_blocking(self) -> LcdCam<'d, Blocking> {
+ crate::interrupt::disable(Cpu::ProCpu, Interrupt::LCD_CAM);
+ #[cfg(multi_core)]
+ crate::interrupt::disable(Cpu::AppCpu, Interrupt::LCD_CAM);
+ LcdCam {
lcd: Lcd {
- lcd_cam: unsafe { lcd_cam.clone_unchecked() },
+ lcd_cam: self.lcd.lcd_cam,
_mode: PhantomData,
},
- cam: Cam {
- lcd_cam: unsafe { lcd_cam.clone_unchecked() },
- },
+ cam: self.cam,
}
}
}
@@ -116,205 +113,193 @@ pub enum ByteOrder {
Inverted = 1,
}
-#[doc(hidden)]
-pub mod asynch {
- use embassy_sync::waitqueue::AtomicWaker;
- use procmacros::handler;
-
- use super::private::Instance;
-
- pub(crate) static LCD_DONE_WAKER: AtomicWaker = AtomicWaker::new();
+pub(crate) static LCD_DONE_WAKER: AtomicWaker = AtomicWaker::new();
- #[handler]
- pub(crate) fn interrupt_handler() {
- // TODO: this is a shared interrupt with Camera and here we ignore that!
- if Instance::is_lcd_done_set() {
- Instance::unlisten_lcd_done();
- LCD_DONE_WAKER.wake()
- }
+#[handler]
+fn interrupt_handler() {
+ // TODO: this is a shared interrupt with Camera and here we ignore that!
+ if Instance::is_lcd_done_set() {
+ Instance::unlisten_lcd_done();
+ LCD_DONE_WAKER.wake()
}
}
-mod private {
- use crate::peripherals::LCD_CAM;
-
- pub(crate) struct Instance;
-
- // NOTE: the LCD_CAM interrupt registers are shared between LCD and Camera and
- // this is only implemented for the LCD side, when the Camera is implemented a
- // CriticalSection will be needed to protect these shared registers.
- impl Instance {
- pub(crate) fn listen_lcd_done() {
- let lcd_cam = unsafe { LCD_CAM::steal() };
- lcd_cam
- .lc_dma_int_ena()
- .modify(|_, w| w.lcd_trans_done_int_ena().set_bit());
- }
-
- pub(crate) fn unlisten_lcd_done() {
- let lcd_cam = unsafe { LCD_CAM::steal() };
- lcd_cam
- .lc_dma_int_ena()
- .modify(|_, w| w.lcd_trans_done_int_ena().clear_bit());
- }
+pub(crate) struct Instance;
+
+// NOTE: the LCD_CAM interrupt registers are shared between LCD and Camera and
+// this is only implemented for the LCD side, when the Camera is implemented a
+// CriticalSection will be needed to protect these shared registers.
+impl Instance {
+ pub(crate) fn listen_lcd_done() {
+ let lcd_cam = unsafe { LCD_CAM::steal() };
+ lcd_cam
+ .lc_dma_int_ena()
+ .modify(|_, w| w.lcd_trans_done_int_ena().set_bit());
+ }
- pub(crate) fn is_lcd_done_set() -> bool {
- let lcd_cam = unsafe { LCD_CAM::steal() };
- lcd_cam
- .lc_dma_int_raw()
- .read()
- .lcd_trans_done_int_raw()
- .bit()
- }
+ pub(crate) fn unlisten_lcd_done() {
+ let lcd_cam = unsafe { LCD_CAM::steal() };
+ lcd_cam
+ .lc_dma_int_ena()
+ .modify(|_, w| w.lcd_trans_done_int_ena().clear_bit());
}
- pub struct ClockDivider {
- // Integral LCD clock divider value. (8 bits)
- // Value 0 is treated as 256
- // Value 1 is treated as 2
- // Value N is treated as N
- pub div_num: usize,
-
- // Fractional clock divider numerator value. (6 bits)
- pub div_b: usize,
-
- // Fractional clock divider denominator value. (6 bits)
- pub div_a: usize,
+
+ pub(crate) fn is_lcd_done_set() -> bool {
+ let lcd_cam = unsafe { LCD_CAM::steal() };
+ lcd_cam
+ .lc_dma_int_raw()
+ .read()
+ .lcd_trans_done_int_raw()
+ .bit()
}
+}
+pub(crate) struct ClockDivider {
+ // Integral LCD clock divider value. (8 bits)
+ // Value 0 is treated as 256
+ // Value 1 is treated as 2
+ // Value N is treated as N
+ pub div_num: usize,
+
+ // Fractional clock divider numerator value. (6 bits)
+ pub div_b: usize,
+
+ // Fractional clock divider denominator value. (6 bits)
+ pub div_a: usize,
+}
- pub fn calculate_clkm(
- desired_frequency: usize,
- source_frequencies: &[usize],
- ) -> (usize, ClockDivider) {
- let mut result_freq = 0;
- let mut result = None;
-
- for (i, &source_frequency) in source_frequencies.iter().enumerate() {
- let div = calculate_closest_divider(source_frequency, desired_frequency);
- if let Some(div) = div {
- let freq = calculate_output_frequency(source_frequency, &div);
- if result.is_none() || freq > result_freq {
- result = Some((i, div));
- result_freq = freq;
- }
+pub(crate) fn calculate_clkm(
+ desired_frequency: usize,
+ source_frequencies: &[usize],
+) -> (usize, ClockDivider) {
+ let mut result_freq = 0;
+ let mut result = None;
+
+ for (i, &source_frequency) in source_frequencies.iter().enumerate() {
+ let div = calculate_closest_divider(source_frequency, desired_frequency);
+ if let Some(div) = div {
+ let freq = calculate_output_frequency(source_frequency, &div);
+ if result.is_none() || freq > result_freq {
+ result = Some((i, div));
+ result_freq = freq;
}
}
-
- result.expect("Desired frequency was too low for the dividers to divide to")
}
- fn calculate_output_frequency(source_frequency: usize, divider: &ClockDivider) -> usize {
- let n = match divider.div_num {
- 0 => 256,
- 1 => 2,
- _ => divider.div_num.min(256),
- };
+ result.expect("Desired frequency was too low for the dividers to divide to")
+}
- if divider.div_b != 0 && divider.div_a != 0 {
- // OUTPUT = SOURCE / (N + B/A)
- // OUTPUT = SOURCE / ((NA + B)/A)
- // OUTPUT = (SOURCE * A) / (NA + B)
+fn calculate_output_frequency(source_frequency: usize, divider: &ClockDivider) -> usize {
+ let n = match divider.div_num {
+ 0 => 256,
+ 1 => 2,
+ _ => divider.div_num.min(256),
+ };
- // u64 is required to fit the numbers from this arithmetic.
+ if divider.div_b != 0 && divider.div_a != 0 {
+ // OUTPUT = SOURCE / (N + B/A)
+ // OUTPUT = SOURCE / ((NA + B)/A)
+ // OUTPUT = (SOURCE * A) / (NA + B)
- let source = source_frequency as u64;
- let n = n as u64;
- let a = divider.div_b as u64;
- let b = divider.div_a as u64;
+ // u64 is required to fit the numbers from this arithmetic.
- ((source * a) / (n * a + b)) as _
- } else {
- source_frequency / n
- }
- }
+ let source = source_frequency as u64;
+ let n = n as u64;
+ let a = divider.div_b as u64;
+ let b = divider.div_a as u64;
- fn calculate_closest_divider(
- source_frequency: usize,
- desired_frequency: usize,
- ) -> Option