From 1fff7f634f5f4cd0195c4191a80b125a2f7c2e68 Mon Sep 17 00:00:00 2001 From: Paul van Tilburg Date: Sun, 17 Mar 2019 14:19:52 +0100 Subject: [PATCH] Add documentation; tiny code refactoring --- src/led_ring.rs | 60 +++++++++++++++++++++++++++++++++++++++++++------ src/main.rs | 16 ++++++++++++- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/led_ring.rs b/src/led_ring.rs index a587032..038d81f 100644 --- a/src/led_ring.rs +++ b/src/led_ring.rs @@ -1,15 +1,25 @@ +//! Module for manipulating the LED ring. + use hal::gpio::{Output, PushPull}; use hal::prelude::*; +/// Type alias for a generic LED output. pub type Led = hal::gpio::gpiod::PD>; +/// The cycle direction of the LED ring +/// +/// The direction can be interpreted as such when the mini-USB port of the board is being held +/// down. #[derive(Debug, Eq, PartialEq)] pub enum Direction { + /// Cycle clockwise. Clockwise, + /// Cycle counter-clockwise. CounterClockwise, } impl Direction { + /// Returns the flipped/reversed direction. fn flip(&self) -> Direction { match self { Direction::Clockwise => Direction::CounterClockwise, @@ -18,24 +28,38 @@ impl Direction { } } +/// The mode the LED ring is in. #[derive(Debug, Eq, PartialEq)] pub enum Mode { + /// All LEDs are off. Off, + /// The LEDs are cycling (two on at any time) following some direction. Cycle, + /// The LEDs follow the accelerometer (shows which side of the board is pointing down). Accelerometer, } +/// The LED ring. +/// +/// The ring on this board is comprised of four LEDs. This struct provides methods +/// for animating them. pub struct LedRing { - pub direction: Direction, - pub mode: Mode, - pub index: usize, - pub leds: [crate::Led; 4], + /// The current cycle direction. + direction: Direction, + /// The current mode. + mode: Mode, + /// The index of the current LED being lit. + index: usize, + /// The LED outputs being used to comprise the LED ring. + leds: [crate::Led; 4], } impl LedRing { + /// The number of cycles between LED ring updates (used by tasks). pub const PERIOD: u32 = 8_000_000; - pub fn from(leds: [crate::Led; 4]) -> LedRing { + /// Sets up the LED ring using using four LED GPIO outputs. + pub fn from(leds: [Led; 4]) -> LedRing { LedRing { direction: Direction::Clockwise, mode: Mode::Cycle, @@ -44,30 +68,43 @@ impl LedRing { } } + /// Enables cycle mode. pub fn enable_cycle(&mut self) { self.mode = Mode::Cycle; } + /// Enables accelerometer mode. pub fn enable_accel(&mut self) { self.mode = Mode::Accelerometer; } + /// Disables either cycle or accelerometer mode. pub fn disable(&mut self) { self.mode = Mode::Off; } + /// Returns whether the LED ring is in cycle mode. pub fn is_mode_cycle(&self) -> bool { self.mode == Mode::Cycle } + /// Returns whether the LED ring is in acceleromter mode. pub fn is_mode_accel(&self) -> bool { self.mode == Mode::Accelerometer } + /// Reverses the cycle direction. + /// + /// This will have no immediately visible effect if the LED ring is not in cycle mode + /// but it will be used when the cycle mode is enabled again. pub fn reverse(&mut self) { self.direction = self.direction.flip(); } + /// Advances the cycling one step. + /// + /// This will have have directly visible effect regardless of the mode the + /// LED ring is in and override what is shown at that moment. pub fn advance(&mut self) { let num_leds = self.leds.len(); @@ -80,21 +117,30 @@ impl LedRing { }; } + /// Turns all LEDs on. + /// + /// This is done immediately, regardless of the current mode. pub fn all_on(&mut self) { for led in self.leds.iter_mut() { led.set_high(); } } + /// Turns all LEDs off. + /// + /// This is done immediately, regardless of the current mode. pub fn all_off(&mut self) { for led in self.leds.iter_mut() { led.set_low(); } } + /// Turns on specific LEDs based on the direction array. + /// + /// When looking with the mini-USB port of the board held down (south), the directions of + /// the array can be interpreted as: `[east, south, west, north]`. pub fn set_directions(&mut self, directions: [bool; 4]) { - for setting in self.leds.iter_mut().zip(directions.iter()) { - let (led, on_off) = setting; + for (led, on_off) in self.leds.iter_mut().zip(directions.iter()) { if *on_off { led.set_high(); } else { diff --git a/src/main.rs b/src/main.rs index 7a3a64c..f2df6f2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,8 @@ +//! STM32F4DISCOVERY demo application +//! +//! This demo application sports a serial command-interface for controlling what the LED +//! ring does: cycle clock-wise, counter clock-wise, or follow the accelerometer. + #![deny(unsafe_code)] #![deny(warnings)] #![no_main] @@ -40,9 +45,11 @@ const APP: () = { static mut accel: Accelerometer = (); static mut accel_cs: AccelerometerCs = (); + /// Initializes the application by setting up the LED ring, user button, serial + /// interface and accelerometer. #[init(spawn = [accel_leds, cycle_leds])] fn init() -> init::LateResources { - // Set up the LED ring and spawn the LEDs switch task. + // Set up the LED ring and spawn the task corresponding to the mode. let gpiod = device.GPIOD.split(); let leds = [ gpiod.pd12.into_push_pull_output().downgrade(), @@ -110,6 +117,7 @@ const APP: () = { } } + /// Task that advances the LED ring one step and schedules the next trigger (if enabled). #[task(schedule = [cycle_leds], resources = [led_ring])] fn cycle_leds() { resources.led_ring.lock(|led_ring| { @@ -122,6 +130,8 @@ const APP: () = { }); } + /// Task that performs an accelerometers measurement and adjusts the LED ring accordingly + /// and schedules the next trigger (if enabled). #[task(schedule = [accel_leds], resources = [accel, accel_cs, led_ring, serial_tx])] fn accel_leds() { resources.accel_cs.set_low(); @@ -149,6 +159,8 @@ const APP: () = { }) } + /// Interrupt handler that writes that the button is pressed to the serial interface + /// and reverses the LED ring cycle direction. #[interrupt(binds = EXTI0, resources = [button, exti, led_ring, serial_tx])] fn button_pressed() { resources.led_ring.lock(|led_ring| led_ring.reverse()); @@ -161,6 +173,8 @@ const APP: () = { resources.button.clear_interrupt_pending_bit(resources.exti); } + /// Interrupt handler that reads data from the serial connection and handles commands + /// once an appropriate command is in the buffer. #[interrupt( binds = USART2, priority = 2,