//! Project: CMtec CMDR joystick 24 //! Date: 2023-08-01 //! Author: Christoffer Martinsson //! Email: cm@cmtec.se //! License: Please refer to LICENSE in root directory use rp2040_hal::{ gpio::{Function, FunctionConfig, Pin, PinId, ValidPinMode}, pio::{PIOExt, StateMachineIndex, UninitStateMachine, PIO}, }; use smart_leds::{SmartLedsWrite, RGB8}; use ws2812_pio::Ws2812Direct; /// Status LED modes /// /// * OFF = Syatem offline /// * NORMAL = All system Ok /// * ACTIVITY = System activity /// * OTHER = Other activity /// * WARNING = Warning /// * ERROR = Error /// * BOOTLOADER = Bootloader active #[allow(dead_code)] #[derive(PartialEq, Eq, Copy, Clone)] pub enum StatusMode { Off = 0, Normal = 1, Activity = 2, Other = 3, Warning = 4, Error = 5, Bootloader = 6, } #[warn(dead_code)] /// Status LED driver /// This driver uses the PIO state machine to drive a WS2812 LED /// /// # Example /// /// ``` /// let mut status_led = Ws2812StatusLed::new( /// pins.neopixel.into_mode(), /// &mut pio, /// sm0, /// clocks.peripheral_clock.freq(), /// ); /// ``` pub struct Ws2812StatusLed where I: PinId, P: PIOExt + FunctionConfig, Function

: ValidPinMode, SM: StateMachineIndex, { ws2812_direct: Ws2812Direct, state: bool, mode: StatusMode, } impl Ws2812StatusLed where I: PinId, P: PIOExt + FunctionConfig, Function

: ValidPinMode, SM: StateMachineIndex, { /// Creates a new instance of this driver. /// /// # Arguments /// /// * `pin` - PIO pin /// * `pio` - PIO instance /// * `sm` - PIO state machine /// * `clock_freq` - PIO clock frequency pub fn new( pin: Pin>, pio: &mut PIO

, sm: UninitStateMachine<(P, SM)>, clock_freq: fugit::HertzU32, ) -> Self { // prepare the PIO program let ws2812_direct = Ws2812Direct::new(pin, pio, sm, clock_freq); let state = false; let mode = StatusMode::Off; Self { ws2812_direct, state, mode, } } /// Get current status mode pub fn get_mode(&self) -> StatusMode { self.mode } /// Update status LED /// Depending on the mode, the LED will be set to a different colour /// /// * OFF = off /// * NORMAL = green /// * ACTIVITY = blue /// * OTHER = orange /// * WARNING = red (flashing) /// * ERROR = red /// * BOOTLOADER = purple /// /// Make sure to call this function regularly to keep the LED flashing pub fn update(&mut self, mode: StatusMode) { let colors: [RGB8; 7] = [ (0, 0, 0).into(), // Off (10, 7, 0).into(), // Green (10, 4, 10).into(), // Blue (5, 10, 0).into(), // Orange (2, 20, 0).into(), // Red (2, 20, 0).into(), // Red (0, 10, 10).into(), // Purple ]; self.mode = mode; if mode == StatusMode::Warning && !self.state { self.ws2812_direct .write([colors[mode as usize]].iter().copied()) .unwrap(); self.state = true; } else if mode == StatusMode::Warning || mode == StatusMode::Off { self.ws2812_direct .write([colors[0]].iter().copied()) .unwrap(); self.state = false; } else { self.ws2812_direct .write([colors[mode as usize]].iter().copied()) .unwrap(); self.state = true; } } }