aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/lcd.rs58
-rw-r--r--examples/stm32u0/Cargo.toml2
-rw-r--r--examples/stm32u0/src/bin/lcd.rs63
3 files changed, 64 insertions, 59 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
diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml
index 9f5227e3f..42d349cda 100644
--- a/examples/stm32u0/Cargo.toml
+++ b/examples/stm32u0/Cargo.toml
@@ -7,7 +7,7 @@ publish = false
7 7
8[dependencies] 8[dependencies]
9# Change stm32u083rc to your chip name, if necessary. 9# Change stm32u083rc to your chip name, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083mc", "memory-x", "unstable-pac", "exti", "chrono"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
diff --git a/examples/stm32u0/src/bin/lcd.rs b/examples/stm32u0/src/bin/lcd.rs
index 5551dd819..f27c4458b 100644
--- a/examples/stm32u0/src/bin/lcd.rs
+++ b/examples/stm32u0/src/bin/lcd.rs
@@ -3,7 +3,10 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::{lcd::{Bias, Config, Duty, Lcd, VoltageSource}, time::Hertz}; 6use embassy_stm32::{
7 lcd::{Bias, Config, Duty, Lcd, LcdPin},
8 time::Hertz,
9};
7use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
8 11
9#[embassy_executor::main] 12#[embassy_executor::main]
@@ -31,41 +34,41 @@ async fn main(_spawner: Spawner) {
31 let mut config = Config::default(); 34 let mut config = Config::default();
32 config.bias = Bias::Third; 35 config.bias = Bias::Third;
33 config.duty = Duty::Quarter; 36 config.duty = Duty::Quarter;
34 config.target_fps = Hertz(60); 37 config.target_fps = Hertz(100);
35 38
36 let mut lcd = Lcd::new( 39 let mut lcd = Lcd::new(
37 p.LCD, 40 p.LCD,
38 config, 41 config,
39 p.PC3, 42 p.PC3,
40 [ 43 [
41 p.PA8.into(), 44 LcdPin::from(p.PA8),
42 p.PA9.into(), 45 LcdPin::from(p.PA9),
43 p.PA10.into(), 46 LcdPin::from(p.PA10),
44 p.PB1.into(), 47 LcdPin::from(p.PB1),
45 p.PB9.into(), 48 LcdPin::from(p.PB9),
46 p.PB11.into(), 49 LcdPin::from(p.PB11),
47 p.PB14.into(), 50 LcdPin::from(p.PB14),
48 p.PB15.into(), 51 LcdPin::from(p.PB15),
49 p.PC4.into(), 52 LcdPin::from(p.PC4),
50 p.PC5.into(), 53 LcdPin::from(p.PC5),
51 p.PC6.into(), 54 LcdPin::from(p.PC6),
52 p.PC8.into(), 55 LcdPin::from(p.PC8),
53 p.PC9.into(), 56 LcdPin::from(p.PC9),
54 p.PC10.into(), 57 LcdPin::from(p.PC10),
55 p.PC11.into(), 58 LcdPin::from(p.PC11),
56 p.PD8.into(), 59 LcdPin::from(p.PD8),
57 p.PD9.into(), 60 LcdPin::from(p.PD9),
58 p.PD12.into(), 61 LcdPin::from(p.PD12),
59 p.PD13.into(), 62 LcdPin::from(p.PD13),
60 p.PD0.into(), 63 LcdPin::from(p.PD0),
61 p.PD1.into(), 64 LcdPin::from(p.PD1),
62 p.PD3.into(), 65 LcdPin::from(p.PD3),
63 p.PD4.into(), 66 LcdPin::from(p.PD4),
64 p.PD5.into(), 67 LcdPin::from(p.PD5),
65 p.PD6.into(), 68 LcdPin::from(p.PD6),
66 p.PE7.into(), 69 LcdPin::from(p.PE7),
67 p.PE8.into(), 70 LcdPin::from(p.PE8),
68 p.PE9.into(), 71 LcdPin::from(p.PE9),
69 ], 72 ],
70 ); 73 );
71 74