aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/lcd.rs
diff options
context:
space:
mode:
authorDion Dokter <[email protected]>2025-11-22 15:25:54 +0100
committerDion Dokter <[email protected]>2025-11-22 15:25:54 +0100
commitf686ce9ebb19081e12eae203e92273f8ecb6eaf2 (patch)
tree1a139c7265d29388c621409b081d8aed0ebc7735 /embassy-stm32/src/lcd.rs
parent2649ba2a49fad0c04e3323d17373707f2eb03097 (diff)
Impl blink
Diffstat (limited to 'embassy-stm32/src/lcd.rs')
-rw-r--r--embassy-stm32/src/lcd.rs73
1 files changed, 71 insertions, 2 deletions
diff --git a/embassy-stm32/src/lcd.rs b/embassy-stm32/src/lcd.rs
index 348865fbd..ea29f1398 100644
--- a/embassy-stm32/src/lcd.rs
+++ b/embassy-stm32/src/lcd.rs
@@ -152,6 +152,7 @@ pub enum Drive {
152pub struct Lcd<'d, T: Instance> { 152pub struct Lcd<'d, T: Instance> {
153 _peri: PhantomData<&'d mut T>, 153 _peri: PhantomData<&'d mut T>,
154 duty: Duty, 154 duty: Duty,
155 ck_div: u32,
155} 156}
156 157
157impl<'d, T: Instance> Lcd<'d, T> { 158impl<'d, T: Instance> Lcd<'d, T> {
@@ -227,9 +228,11 @@ impl<'d, T: Instance> Lcd<'d, T> {
227 } 228 }
228 } 229 }
229 230
231 let ck_div = lcd_clk.0 / ((1 << ps) * (div + 16));
232
230 trace!( 233 trace!(
231 "lcd_clk: {}, fps: {}, ps: {}, div: {}", 234 "lcd_clk: {}, fps: {}, ps: {}, div: {}, ck_div: {}",
232 lcd_clk, best_fps_match, ps, div 235 lcd_clk, best_fps_match, ps, div, ck_div
233 ); 236 );
234 237
235 if best_fps_match == u32::MAX || ps > 0xF { 238 if best_fps_match == u32::MAX || ps > 0xF {
@@ -271,6 +274,7 @@ impl<'d, T: Instance> Lcd<'d, T> {
271 Self { 274 Self {
272 _peri: PhantomData, 275 _peri: PhantomData,
273 duty: config.duty, 276 duty: config.duty,
277 ck_div,
274 } 278 }
275 } 279 }
276 280
@@ -371,6 +375,42 @@ impl<'d, T: Instance> Lcd<'d, T> {
371 pub fn num_com_pins(&self) -> u8 { 375 pub fn num_com_pins(&self) -> u8 {
372 self.duty.num_com_pins() 376 self.duty.num_com_pins()
373 } 377 }
378
379 /// Set the blink behavior on some pixels.
380 ///
381 /// The blink frequency is an approximation. It's divided from the clock selected by the FPS.
382 /// Play with the FPS value if you want the blink frequency to be more accurate.
383 ///
384 /// If a blink frequency cannot be attained, this function will panic.
385 pub fn set_blink(&mut self, selector: BlinkSelector, freq: BlinkFreq) {
386 // Freq * 100 to be able to do integer math
387 let scaled_blink_freq = match freq {
388 BlinkFreq::Hz0_25 => 25,
389 BlinkFreq::Hz0_5 => 50,
390 BlinkFreq::Hz1 => 100,
391 BlinkFreq::Hz2 => 200,
392 BlinkFreq::Hz4 => 400,
393 };
394
395 let desired_divider = self.ck_div * 100 / scaled_blink_freq;
396 let target_divider = desired_divider.next_power_of_two();
397 let power_divisions = target_divider.trailing_zeros();
398
399 trace!(
400 "Setting LCD blink frequency -> desired_divider: {}, target_divider: {}",
401 desired_divider, target_divider
402 );
403
404 assert!(
405 (8..=1024).contains(&target_divider),
406 "LCD blink frequency cannot be attained"
407 );
408
409 T::regs().fcr().modify(|reg| {
410 reg.set_blinkf((power_divisions - 3) as u8);
411 reg.set_blink(selector as u8);
412 })
413 }
374} 414}
375 415
376impl<'d, T: Instance> Drop for Lcd<'d, T> { 416impl<'d, T: Instance> Drop for Lcd<'d, T> {
@@ -381,6 +421,35 @@ impl<'d, T: Instance> Drop for Lcd<'d, T> {
381 } 421 }
382} 422}
383 423
424/// Blink frequency
425#[derive(Debug, Clone, Copy, PartialEq, Eq)]
426pub enum BlinkFreq {
427 /// 0.25 hz
428 Hz0_25,
429 /// 0.5 hz
430 Hz0_5,
431 /// 1 hz
432 Hz1,
433 /// 2 hz
434 Hz2,
435 /// 4 hz
436 Hz4,
437}
438
439/// Blink pixel selector
440#[derive(Debug, Clone, Copy, PartialEq, Eq)]
441#[repr(u8)]
442pub enum BlinkSelector {
443 /// No pixels blink
444 None = 0b00,
445 /// The SEG0, COM0 pixel blinks if the pixel is set
446 Seg0Com0 = 0b01,
447 /// The SEG0 pixel of all COMs blinks if the pixel is set
448 Seg0ComAll = 0b10,
449 /// All pixels blink if the pixel is set
450 All = 0b11,
451}
452
384/// A type-erased pin that can be configured as an LCD pin. 453/// A type-erased pin that can be configured as an LCD pin.
385/// This is used for passing pins to the new function in the array. 454/// This is used for passing pins to the new function in the array.
386pub struct LcdPin<'d, T: Instance> { 455pub struct LcdPin<'d, T: Instance> {