aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/lcd.rs
diff options
context:
space:
mode:
authorDion Dokter <[email protected]>2025-11-20 14:16:43 +0100
committerDion Dokter <[email protected]>2025-11-20 14:16:43 +0100
commitd111eceb4ba0094d34f58a4695bb3d43d188e591 (patch)
tree75f9824731af674208d357c01e4208804cec3ec6 /embassy-stm32/src/lcd.rs
parent4f2c36e447455e8d33607d586859d3d075cabf1d (diff)
Update LCD to modern embassy
Diffstat (limited to 'embassy-stm32/src/lcd.rs')
-rw-r--r--embassy-stm32/src/lcd.rs58
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
2use core::marker::PhantomData; 2use core::marker::PhantomData;
3 3
4use embassy_hal_internal::{into_ref, PeripheralRef}; 4use embassy_hal_internal::{Peri, PeripheralType};
5 5
6use crate::gpio::{AFType, AnyPin, SealedPin}; 6use crate::gpio::{AfType, AnyPin, SealedPin};
7use crate::peripherals;
7use crate::rcc::{self, RccPeripheral}; 8use crate::rcc::{self, RccPeripheral};
8use crate::time::Hertz; 9use crate::time::Hertz;
9use 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> {
123impl<'d, T: Instance> Lcd<'d, T> { 123impl<'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
266impl<'d, T: Instance> Drop for Lcd<'d, T> { 268impl<'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
272pub struct LcdPin<'d, T: Instance> { 276pub 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
278impl<'d, T: Instance, Pin: Peripheral<P: SegComPin<T>> + 'd> From<Pin> for LcdPin<'d, T> { 282impl<'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
284impl<'d, T: Instance> LcdPin<'d, T> { 288impl<'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
298trait SealedInstance: crate::rcc::SealedRccPeripheral { 300trait SealedInstance: crate::rcc::SealedRccPeripheral + PeripheralType {
299 fn regs() -> crate::pac::lcd::Lcd; 301 fn regs() -> crate::pac::lcd::Lcd;
300} 302}
301 303