dashboard/
led_mod.rs

1//! Module for the LED lights
2//!
3//! Responsible for handling the WS2812B LED lights on the dashboard.
4//!
5//! WS2812B Datasheet: [https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf](https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf)
6
7// use defmt::info;
8use defmt::trace;
9use embassy_stm32::Peri;
10use embassy_stm32::peripherals::{DMA2_CH1, TIM2};
11use embassy_stm32::timer::simple_pwm::SimplePwm;
12use embassy_time::Timer;
13use rgb_led_pwm_dma_maker::{LedDataComposition, LedDmaBuffer, RGB, calc_dma_buffer_length};
14
15use crate::can_mod::RELAY_STATE;
16use crate::eco_can::RelayState;
17
18// There are 5 LED's on the board
19const LED_COUNT: usize = 5;
20
21/// Updates the LED lights on the dashboard
22#[embassy_executor::task]
23pub async fn led_task(mut led_in: SimplePwm<'static, TIM2>, mut led_dma: Peri<'static, DMA2_CH1>) {
24    // RESET_LENGTH = reset_period / data_transfer_time = 50us / 1.25us = 40
25    const RESET_LENGTH: usize = 40;
26    // Calculate the dma buffer's length at compile time
27    // Uses RGB888 formatting
28    const DMA_BUFFER_LEN: usize = calc_dma_buffer_length(8 * 3, LED_COUNT, RESET_LENGTH);
29    // t1h = T1H / data_transfer_time * max_duty_cycle = 0.8us / 1.25us * 200 =
30    let t1h: u16 = 128;
31    // t1h = T0H / data_transfer_time * max_duty_cycle = 0.4us / 1.25us * 200 =
32    let t0h: u16 = 64;
33
34    let mut led_array: [RGB; LED_COUNT] = [
35        RGB::new(3, 0, 0),
36        RGB::new(0, 3, 0),
37        RGB::new(0, 0, 3),
38        RGB::new(0, 3, 3),
39        RGB::new(3, 3, 0),
40    ];
41    let mut dma_buffer = LedDmaBuffer::<DMA_BUFFER_LEN>::new(t1h, t0h, LedDataComposition::GRB);
42
43    loop {
44        let relay_state = RELAY_STATE.lock().await;
45
46        // Inialized display screen if switching relay state
47        match *relay_state {
48            RelayState::RELAY_STRTP => led_startup(&mut led_array),
49            RelayState::RELAY_CHRGE => led_charging(&mut led_array),
50            RelayState::RELAY_STBY => led_standby(&mut led_array),
51            RelayState::RELAY_RUN => led_running(&mut led_array),
52        }
53        let _ = dma_buffer.set_dma_buffer(&led_array, None);
54        // Output pwm waveform to set LEDs
55        led_in
56            .waveform::<embassy_stm32::timer::Ch1>(led_dma.reborrow(), dma_buffer.get_dma_buffer())
57            .await;
58        trace!("LED Health check");
59        Timer::after_millis(600).await;
60    }
61}
62
63fn led_startup(led_array: &mut [RGB; LED_COUNT]) {
64    *led_array = [
65        RGB::new(3, 0, 0),
66        RGB::new(0, 3, 0),
67        RGB::new(0, 0, 3),
68        RGB::new(0, 3, 3),
69        RGB::new(3, 3, 0),
70    ];
71}
72fn led_charging(led_array: &mut [RGB; LED_COUNT]) {
73    *led_array = [
74        RGB::new(0, 3, 0),
75        RGB::new(0, 3, 0),
76        RGB::new(0, 3, 0),
77        RGB::new(0, 3, 0),
78        RGB::new(0, 3, 0),
79    ];
80}
81fn led_standby(led_array: &mut [RGB; LED_COUNT]) {
82    *led_array = [
83        RGB::new(3, 0, 0),
84        RGB::new(0, 3, 0),
85        RGB::new(0, 0, 3),
86        RGB::new(0, 3, 3),
87        RGB::new(3, 3, 0),
88    ];
89}
90fn led_running(led_array: &mut [RGB; LED_COUNT]) {
91    led_array.rotate_left(1);
92}