diff options
| author | Dion Dokter <[email protected]> | 2025-11-20 14:16:43 +0100 |
|---|---|---|
| committer | Dion Dokter <[email protected]> | 2025-11-20 14:16:43 +0100 |
| commit | d111eceb4ba0094d34f58a4695bb3d43d188e591 (patch) | |
| tree | 75f9824731af674208d357c01e4208804cec3ec6 /embassy-stm32/src/lcd.rs | |
| parent | 4f2c36e447455e8d33607d586859d3d075cabf1d (diff) | |
Update LCD to modern embassy
Diffstat (limited to 'embassy-stm32/src/lcd.rs')
| -rw-r--r-- | embassy-stm32/src/lcd.rs | 58 |
1 files changed, 30 insertions, 28 deletions
diff --git a/embassy-stm32/src/lcd.rs b/embassy-stm32/src/lcd.rs index 15d3e8fbc..7c1877a38 100644 --- a/embassy-stm32/src/lcd.rs +++ b/embassy-stm32/src/lcd.rs | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | //! LCD | 1 | //! LCD |
| 2 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 3 | 3 | ||
| 4 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 4 | use embassy_hal_internal::{Peri, PeripheralType}; |
| 5 | 5 | ||
| 6 | use crate::gpio::{AFType, AnyPin, SealedPin}; | 6 | use crate::gpio::{AfType, AnyPin, SealedPin}; |
| 7 | use crate::peripherals; | ||
| 7 | use crate::rcc::{self, RccPeripheral}; | 8 | use crate::rcc::{self, RccPeripheral}; |
| 8 | use crate::time::Hertz; | 9 | use crate::time::Hertz; |
| 9 | use crate::{peripherals, Peripheral}; | ||
| 10 | 10 | ||
| 11 | #[non_exhaustive] | 11 | #[non_exhaustive] |
| 12 | #[derive(Debug, Clone, Copy)] | 12 | #[derive(Debug, Clone, Copy)] |
| @@ -123,21 +123,24 @@ pub struct Lcd<'d, T: Instance> { | |||
| 123 | impl<'d, T: Instance> Lcd<'d, T> { | 123 | impl<'d, T: Instance> Lcd<'d, T> { |
| 124 | /// Initialize the lcd driver | 124 | /// Initialize the lcd driver |
| 125 | pub fn new<const N: usize>( | 125 | pub fn new<const N: usize>( |
| 126 | _peri: impl Peripheral<P = T> + 'd, | 126 | _peripheral: Peri<'d, T>, |
| 127 | config: Config, | 127 | config: Config, |
| 128 | vlcd_pin: impl Peripheral<P = impl VlcdPin<T>> + 'd, | 128 | vlcd_pin: Peri<'_, impl VlcdPin<T>>, |
| 129 | pins: [LcdPin<'d, T>; N], | 129 | pins: [LcdPin<'d, T>; N], |
| 130 | ) -> Self { | 130 | ) -> Self { |
| 131 | rcc::enable_and_reset::<T>(); | 131 | rcc::enable_and_reset::<T>(); |
| 132 | 132 | ||
| 133 | into_ref!(vlcd_pin); | 133 | vlcd_pin.set_as_af( |
| 134 | vlcd_pin.set_as_af(vlcd_pin.af_num(), AFType::OutputPushPull); | 134 | vlcd_pin.af_num(), |
| 135 | vlcd_pin.set_speed(crate::gpio::Speed::VeryHigh); | 135 | AfType::output(crate::gpio::OutputType::PushPull, crate::gpio::Speed::VeryHigh), |
| 136 | ); | ||
| 136 | 137 | ||
| 137 | // Set the pins | 138 | // Set the pins |
| 138 | for pin in pins { | 139 | for pin in pins { |
| 139 | pin.pin.set_as_af(pin.af_num, AFType::OutputPushPull); | 140 | pin.pin.set_as_af( |
| 140 | pin.pin.set_speed(crate::gpio::Speed::VeryHigh); | 141 | pin.af_num, |
| 142 | AfType::output(crate::gpio::OutputType::PushPull, crate::gpio::Speed::VeryHigh), | ||
| 143 | ); | ||
| 141 | } | 144 | } |
| 142 | 145 | ||
| 143 | // Initialize the display ram to 0 | 146 | // Initialize the display ram to 0 |
| @@ -147,7 +150,7 @@ impl<'d, T: Instance> Lcd<'d, T> { | |||
| 147 | } | 150 | } |
| 148 | 151 | ||
| 149 | // Calculate the clock dividers | 152 | // Calculate the clock dividers |
| 150 | let Some(lcd_clk) = (unsafe { rcc::get_freqs().rtc }) else { | 153 | let Some(lcd_clk) = (unsafe { rcc::get_freqs().rtc.to_hertz() }) else { |
| 151 | panic!("The LCD driver needs the RTC/LCD clock to be running"); | 154 | panic!("The LCD driver needs the RTC/LCD clock to be running"); |
| 152 | }; | 155 | }; |
| 153 | let duty_divider = match config.duty { | 156 | let duty_divider = match config.duty { |
| @@ -183,10 +186,7 @@ impl<'d, T: Instance> Lcd<'d, T> { | |||
| 183 | 186 | ||
| 184 | trace!( | 187 | trace!( |
| 185 | "lcd_clk: {}, fps: {}, ps: {}, div: {}", | 188 | "lcd_clk: {}, fps: {}, ps: {}, div: {}", |
| 186 | lcd_clk, | 189 | lcd_clk, best_fps_match, ps, div |
| 187 | best_fps_match, | ||
| 188 | ps, | ||
| 189 | div | ||
| 190 | ); | 190 | ); |
| 191 | 191 | ||
| 192 | if best_fps_match == u32::MAX || ps > 0xF { | 192 | if best_fps_match == u32::MAX || ps > 0xF { |
| @@ -228,7 +228,7 @@ impl<'d, T: Instance> Lcd<'d, T> { | |||
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | /// Change the contrast by changing the voltage being used. | 230 | /// Change the contrast by changing the voltage being used. |
| 231 | /// | 231 | /// |
| 232 | /// This from low at 0 to high at 7. | 232 | /// This from low at 0 to high at 7. |
| 233 | pub fn set_contrast_control(&mut self, value: u8) { | 233 | pub fn set_contrast_control(&mut self, value: u8) { |
| 234 | T::regs().fcr().modify(|w| w.set_cc(value)); | 234 | T::regs().fcr().modify(|w| w.set_cc(value)); |
| @@ -236,17 +236,19 @@ impl<'d, T: Instance> Lcd<'d, T> { | |||
| 236 | 236 | ||
| 237 | /// Change the contrast by introducing a deadtime to the signals | 237 | /// Change the contrast by introducing a deadtime to the signals |
| 238 | /// where the voltages are held at 0V. | 238 | /// where the voltages are held at 0V. |
| 239 | /// | 239 | /// |
| 240 | /// This from no dead time at 0 to high dead time at 7. | 240 | /// This from no dead time at 0 to high dead time at 7. |
| 241 | pub fn set_dead_time(&mut self, value: u8) { | 241 | pub fn set_dead_time(&mut self, value: u8) { |
| 242 | T::regs().fcr().modify(|w: &mut stm32_metapac::lcd::regs::Fcr| w.set_dead(value)); | 242 | T::regs() |
| 243 | .fcr() | ||
| 244 | .modify(|w: &mut stm32_metapac::lcd::regs::Fcr| w.set_dead(value)); | ||
| 243 | } | 245 | } |
| 244 | 246 | ||
| 245 | /// Write frame data to the peripheral. | 247 | /// Write frame data to the peripheral. |
| 246 | /// | 248 | /// |
| 247 | /// What each bit means depends on the exact microcontroller you use, | 249 | /// What each bit means depends on the exact microcontroller you use, |
| 248 | /// which pins are connected to your LCD and also the LCD layout itself. | 250 | /// which pins are connected to your LCD and also the LCD layout itself. |
| 249 | /// | 251 | /// |
| 250 | /// This function blocks until the last update display request has been processed. | 252 | /// This function blocks until the last update display request has been processed. |
| 251 | pub fn write_frame(&mut self, data: &[u32; 16]) { | 253 | pub fn write_frame(&mut self, data: &[u32; 16]) { |
| 252 | while T::regs().sr().read().udr() {} | 254 | while T::regs().sr().read().udr() {} |
| @@ -265,37 +267,37 @@ impl<'d, T: Instance> Lcd<'d, T> { | |||
| 265 | 267 | ||
| 266 | impl<'d, T: Instance> Drop for Lcd<'d, T> { | 268 | impl<'d, T: Instance> Drop for Lcd<'d, T> { |
| 267 | fn drop(&mut self) { | 269 | fn drop(&mut self) { |
| 270 | // Disable the lcd | ||
| 271 | T::regs().cr().modify(|w| w.set_lcden(false)); | ||
| 268 | rcc::disable::<T>(); | 272 | rcc::disable::<T>(); |
| 269 | } | 273 | } |
| 270 | } | 274 | } |
| 271 | 275 | ||
| 272 | pub struct LcdPin<'d, T: Instance> { | 276 | pub struct LcdPin<'d, T: Instance> { |
| 273 | pin: PeripheralRef<'d, AnyPin>, | 277 | pin: Peri<'d, AnyPin>, |
| 274 | af_num: u8, | 278 | af_num: u8, |
| 275 | _phantom: PhantomData<T>, | 279 | _phantom: PhantomData<T>, |
| 276 | } | 280 | } |
| 277 | 281 | ||
| 278 | impl<'d, T: Instance, Pin: Peripheral<P: SegComPin<T>> + 'd> From<Pin> for LcdPin<'d, T> { | 282 | impl<'d, T: Instance, Pin: SegComPin<T>> From<Peri<'d, Pin>> for LcdPin<'d, T> { |
| 279 | fn from(value: Pin) -> Self { | 283 | fn from(value: Peri<'d, Pin>) -> Self { |
| 280 | Self::new(value) | 284 | Self::new(value) |
| 281 | } | 285 | } |
| 282 | } | 286 | } |
| 283 | 287 | ||
| 284 | impl<'d, T: Instance> LcdPin<'d, T> { | 288 | impl<'d, T: Instance> LcdPin<'d, T> { |
| 285 | pub fn new(pin: impl Peripheral<P = impl SegComPin<T>> + 'd) -> Self { | 289 | pub fn new(pin: Peri<'d, impl SegComPin<T>>) -> Self { |
| 286 | into_ref!(pin); | ||
| 287 | |||
| 288 | let af = pin.af_num(); | 290 | let af = pin.af_num(); |
| 289 | 291 | ||
| 290 | Self { | 292 | Self { |
| 291 | pin: pin.map_into(), | 293 | pin: pin.into(), |
| 292 | af_num: af, | 294 | af_num: af, |
| 293 | _phantom: PhantomData, | 295 | _phantom: PhantomData, |
| 294 | } | 296 | } |
| 295 | } | 297 | } |
| 296 | } | 298 | } |
| 297 | 299 | ||
| 298 | trait SealedInstance: crate::rcc::SealedRccPeripheral { | 300 | trait SealedInstance: crate::rcc::SealedRccPeripheral + PeripheralType { |
| 299 | fn regs() -> crate::pac::lcd::Lcd; | 301 | fn regs() -> crate::pac::lcd::Lcd; |
| 300 | } | 302 | } |
| 301 | 303 | ||
