Browse Source

Cleanup and add comments

Kevin Lee 2 years ago
parent
commit
f27ca7a5d8
2 changed files with 144 additions and 304 deletions
  1. 54 99
      Nixie_Firmware_Rust/src/main.rs
  2. 90 205
      Nixie_Firmware_Rust/src/nixie.rs

+ 54 - 99
Nixie_Firmware_Rust/src/main.rs

@@ -24,7 +24,7 @@ use stm32l4xx_hal::{
     prelude::*,
     rcc,
     stm32::Interrupt,
-    timer::Timer,
+    timer::{Timer, Event},
 };
 
 mod ds3231;
@@ -37,37 +37,12 @@ use nixie::*;
 static RTC_INT: Mutex<RefCell<Option<PB5<Input<Floating>>>>> = Mutex::new(RefCell::new(None));
 static FAULT_INT: Mutex<RefCell<Option<PA3<Input<PullUp>>>>> = Mutex::new(RefCell::new(None));
 static FAULT_LED: Mutex<RefCell<Option<PC15<Output<PushPull>>>>> = Mutex::new(RefCell::new(None));
-static I2C: Mutex<
-    RefCell<
-        Option<
-            I2c<
-                I2C1,
-                (
-                    PA9<Alternate<AF4, Output<OpenDrain>>>,
-                    PA10<Alternate<AF4, Output<OpenDrain>>>,
-                ),
-            >,
-        >,
-    >,
-> = Mutex::new(RefCell::new(None));
+static I2C: Mutex<RefCell<Option<
+            I2c<I2C1, (PA9<Alternate<AF4, Output<OpenDrain>>>,PA10<Alternate<AF4,Output<OpenDrain>>>,),>,
+        >,>,> = Mutex::new(RefCell::new(None));
 static FPS_TIMER: Mutex<RefCell<Option<Timer<TIM2>>>> = Mutex::new(RefCell::new(None));
 static CYCLE_TIMER: Mutex<RefCell<Option<Timer<TIM7>>>> = Mutex::new(RefCell::new(None));
 
-// unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
-//     core::slice::from_raw_parts(
-//         (p as *const T) as *const u8,
-//         core::mem::size_of::<T>(),
-//     )
-// }
-
-// pub fn concat<T: Copy + Default, const A: usize, const B: usize>(a: &[T; A], b: &[T; B]) -> [T; A+B] {
-//     let mut whole: [T; A+B] = [Default::default(); A+B];
-//     let (one, two) = whole.split_at_mut(A);
-//     one.copy_from_slice(a);
-//     two.copy_from_slice(b);
-//     whole
-// }
-
 #[cfg(not(test))]
 #[entry]
 fn main() -> ! {
@@ -100,10 +75,7 @@ fn main() -> ! {
     let mut gpioc = dp.GPIOC.split(&mut rcc.ahb2);
 
     // Configure high voltage PSU enable pin on PA2
-    let mut hv_enable =
-        gpioa
-            .pa2
-            .into_push_pull_output_with_state(&mut gpioa.moder, &mut gpioa.otyper, State::Low);
+    let mut hv_enable = gpioa.pa2.into_push_pull_output_with_state(&mut gpioa.moder, &mut gpioa.otyper, State::Low);
 
     // Configure serial port
     // let tx = gpiob.pb6.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
@@ -117,11 +89,7 @@ fn main() -> ! {
     // );
 
     // Configure fault LED output on PC15
-    let fault_led = gpioc.pc15.into_push_pull_output_with_state(
-        &mut gpioc.moder,
-        &mut gpioc.otyper,
-        State::Low,
-    );
+    let fault_led = gpioc.pc15.into_push_pull_output_with_state(&mut gpioc.moder, &mut gpioc.otyper, State::Low);
 
     // Store fault LED in static singleton so that interrupt has access to it
     free(|cs| {
@@ -129,9 +97,7 @@ fn main() -> ! {
     });
 
     // Configure fault input interrupt on PA3
-    let mut fault_int = gpioa
-        .pa3
-        .into_pull_up_input(&mut gpioa.moder, &mut gpioa.pupdr);
+    let mut fault_int = gpioa.pa3.into_pull_up_input(&mut gpioa.moder, &mut gpioa.pupdr);
     fault_int.make_interrupt_source(&mut dp.SYSCFG, &mut rcc.apb2);
     fault_int.enable_interrupt(&mut dp.EXTI);
     fault_int.trigger_on_edge(&mut dp.EXTI, Edge::FALLING);
@@ -151,16 +117,15 @@ fn main() -> ! {
         panic!();
     }
 
-    // Configure I2C SCL
-    let scl = gpioa
-        .pa9
-        .into_open_drain_output(&mut gpioa.moder, &mut gpioa.otyper);
+    // Enable RNG peripheral
+    let rng = dp.RNG.enable(&mut rcc.ahb2, clocks);
+
+    // Configure I2C SCL pin
+    let scl = gpioa.pa9.into_open_drain_output(&mut gpioa.moder, &mut gpioa.otyper);
     let scl = scl.into_af4(&mut gpioa.moder, &mut gpioa.afrh);
 
-    // Configure I2C SDA
-    let sda = gpioa
-        .pa10
-        .into_open_drain_output(&mut gpioa.moder, &mut gpioa.otyper);
+    // Configure I2C SDA pin
+    let sda = gpioa.pa10.into_open_drain_output(&mut gpioa.moder, &mut gpioa.otyper);
     let sda = sda.into_af4(&mut gpioa.moder, &mut gpioa.afrh);
 
     // Initialize I2C (configured for 1Mhz, but actually runs at 600kHz)
@@ -173,15 +138,13 @@ fn main() -> ! {
     ds3231::init(DS3231_ADDR, &mut i2c);
 
     // Configure input interrupt pin from DS3231 on PB5
-    // Interrupt is pulled high, with open drain on DS3231 to pull low
-    let mut rtc_int = gpiob
-        .pb5
-        .into_floating_input(&mut gpiob.moder, &mut gpiob.pupdr);
+    // Interrupt is pulled high, with open drain on DS3231 
+    let mut rtc_int = gpiob.pb5.into_floating_input(&mut gpiob.moder, &mut gpiob.pupdr);
     rtc_int.make_interrupt_source(&mut dp.SYSCFG, &mut rcc.apb2);
     rtc_int.enable_interrupt(&mut dp.EXTI);
     rtc_int.trigger_on_edge(&mut dp.EXTI, Edge::FALLING);
 
-    // Configure NVIC mask to enable interrupt source
+    // Configure NVIC mask to enable interrupt from DS3231
     unsafe { NVIC::unmask(Interrupt::EXTI9_5); }
 
     // Store RTC interrupt in static singleton so that interrupt has access to it
@@ -190,39 +153,22 @@ fn main() -> ! {
     });
 
     // Configure DAC AMP enable pin for AD8591 on PB1
-    let mut _dac_enable = gpiob.pb1.into_push_pull_output_with_state(
-        &mut gpiob.moder,
-        &mut gpiob.otyper,
-        State::High,
-    );
+    let mut _dac_enable = gpiob.pb1.into_push_pull_output_with_state(&mut gpiob.moder, &mut gpiob.otyper, State::High);
 
     // Configure DAC VIN for AD8591 on PA5
     // Note that this pin should actually be configured as analog output (for DAC)
     // but stm32l4xx_hal doesn't have support for the DAC as of now. We also currently
     // set the output to only the highest possible voltage, so the same functionality
     // can be achieved by configuring the pin as a digital output set to high.
-    let mut _dac_output = gpioa.pa5.into_push_pull_output_with_state(
-        &mut gpioa.moder,
-        &mut gpioa.otyper,
-        State::High,
-    );
+    let mut _dac_output = gpioa.pa5.into_push_pull_output_with_state(&mut gpioa.moder, &mut gpioa.otyper, State::High);
 
     // Configure PWM enable pin (active low) for PCA9685 on PA7
-    let mut pwm_enable = gpioa.pa7.into_push_pull_output_with_state(
-        &mut gpioa.moder,
-        &mut gpioa.otyper,
-        State::High,
-    );
+    let mut pwm_enable = gpioa.pa7.into_push_pull_output_with_state(&mut gpioa.moder, &mut gpioa.otyper, State::High);
 
     // Initialize the PCA9685 display refresh timer
-    let fps_timer = Timer::tim2(
-        dp.TIM2,
-        nixie::DISPLAY_REFRESH_FPS.hz(),
-        clocks,
-        &mut rcc.apb1r1,
-    );
-
-    // Configure NVIC mask to enable interrupt for TIM2
+    let fps_timer = Timer::tim2(dp.TIM2, nixie::DISPLAY_REFRESH_FPS.hz(), clocks, &mut rcc.apb1r1);
+
+    // Configure NVIC mask to enable interrupt for the display refresh timer
     unsafe { NVIC::unmask(Interrupt::TIM2) };
 
     // Save display refresh timer in static singleton so that interrupt has access to it
@@ -230,6 +176,17 @@ fn main() -> ! {
         FPS_TIMER.borrow(cs).replace(Some(fps_timer));
     });
 
+    // Initiaize display cycle timer
+    let cycle_timer = Timer::tim7(dp.TIM7, (1000 / nixie::CYCLE_FADE_DURATION_MS).hz(), clocks, &mut rcc.apb1r1);
+
+    // Configure NVIC mask to enable interrupt for display cycle timer
+    unsafe { NVIC::unmask(Interrupt::TIM7) };
+
+    // Save display cycle timer in static singleton so that interrupt has access to it
+    free(|cs| {
+        CYCLE_TIMER.borrow(cs).replace(Some(cycle_timer));
+    });
+
     // Small delay to ensure that PCA9685 is fully powered on before writing to it
     delay_timer.delay_us(10_u32);
 
@@ -244,41 +201,26 @@ fn main() -> ! {
         I2C.borrow(cs).replace(Some(i2c));
     });
 
-    let cycle_timer = Timer::tim7(
-        dp.TIM7,
-        (1000 / nixie::CYCLE_FADE_DURATION_MS).hz(),
-        clocks,
-        &mut rcc.apb1r1,
-    );
-
-    unsafe { NVIC::unmask(Interrupt::TIM7) };
-
-    // Save display refresh timer in static singleton so that interrupt has access to it
-    free(|cs| {
-        CYCLE_TIMER.borrow(cs).replace(Some(cycle_timer));
-    });
-
-    let rng = dp.RNG.enable(&mut rcc.ahb2, clocks);
-
     // Enable the high voltage power supply last
     hv_enable.set_high().unwrap();
 
+    // Cycle through all tubes on powerup
     nixie::cycle_start(0);
     nixie::cycle_start(1);
     nixie::cycle_start(2);
     nixie::cycle_start(3);
 
     loop {
-        // let rng_delay = nixie::CYCLE_REFRESH_INTERVAL + (rng.get_random_data() % nixie::CYCLE_REFRESH_VARIANCE);
-        let rng_delay = nixie::CYCLE_REFRESH_INTERVAL;
-
-        delay_timer.delay_ms(rng_delay * 1000);
+        // Delay before cycling digits to prevent cathode poisoning
+        delay_timer.delay_ms(CYCLE_REFRESH_INTERVAL * 1000);
 
+        // Choose a random tube to cycle
         let tube = (rng.get_random_data() % 4) as usize;
         nixie::cycle_start(tube);
     }
 }
 
+// Helper function to set onboard LED state
 fn set_fault_led(state: State) {
     free(|cs| {
         let mut led_ref = FAULT_LED.borrow(cs).borrow_mut();
@@ -291,6 +233,7 @@ fn set_fault_led(state: State) {
     });
 }
 
+// Interrupt handler for 1HZ signal from offchip RTC (DS3231)
 #[interrupt]
 fn EXTI9_5() {
     free(|cs| {
@@ -307,6 +250,7 @@ fn EXTI9_5() {
     });
 }
 
+// Interrupt handler for fault interrupt from USB monitor (TUSB322)
 #[interrupt]
 fn EXTI3() {
     free(|cs| {
@@ -320,6 +264,7 @@ fn EXTI3() {
     });
 }
 
+// Interrupt handler for internal timer that drives display refresh rate
 #[interrupt]
 fn TIM2() {
     free(|cs| {
@@ -330,14 +275,24 @@ fn TIM2() {
     });
 }
 
+// Interrupt handler for internal timer that drives individual digits within a cycle sequence
 #[interrupt]
 fn TIM7() {
-    nixie::cycle_interrupt();
+    free(|cs| {
+        let mut cycle_timer_ref = CYCLE_TIMER.borrow(cs).borrow_mut();
+        if let Some(ref mut cycle_timer) = cycle_timer_ref.deref_mut() {
+            if nixie::cycle_interrupt() {
+                cycle_timer.unlisten(Event::TimeOut);
+            } else {
+                cycle_timer.clear_interrupt(Event::TimeOut);
+            }
+        }
+    });
 }
 
+// Custom panic handler
 #[panic_handler]
 #[cfg(not(test))]
-/// Custom panic handler
 fn panic(_info: &PanicInfo) -> ! {
     set_fault_led(State::High);
     loop {

+ 90 - 205
Nixie_Firmware_Rust/src/nixie.rs

@@ -66,178 +66,58 @@ static TUBE_MAPPING: PwmOutputMap = {
         driver: [
             PwmDriver {
                 digit: [
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 8,
-                    }, // Tube 0 Digit 0
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 9,
-                    }, // Tube 0 Digit 1
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 10,
-                    }, // Tube 0 Digit 2
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 12,
-                    }, // Tube 0 Digit 3
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 15,
-                    }, // Tube 0 Digit 4
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 14,
-                    }, // Tube 0 Digit 5
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 11,
-                    }, // Tube 0 Digit 6
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 0,
-                    }, // Tube 0 Digit 7
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 1,
-                    }, // Tube 0 Digit 8
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 13,
-                    }, // Tube 0 Digit 9
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 8, }, // Tube 0 Digit 0
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 9, }, // Tube 0 Digit 1
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 10, }, // Tube 0 Digit 2
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 12, }, // Tube 0 Digit 3
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 15, }, // Tube 0 Digit 4
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 14, }, // Tube 0 Digit 5
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 11, }, // Tube 0 Digit 6
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 0, }, // Tube 0 Digit 7
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 1, }, // Tube 0 Digit 8
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 13, }, // Tube 0 Digit 9
                 ],
             },
             PwmDriver {
                 digit: [
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 5,
-                    }, // Tube 1 Digit 0
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 6,
-                    }, // Tube 1 Digit 1
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 7,
-                    }, // Tube 1 Digit 2
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 2,
-                    }, // Tube 1 Digit 3
-                    DigitToPin {
-                        address: PCA9685_ADDR_2,
-                        pin: 4,
-                    }, // Tube 1 Digit 4
-                    DigitToPin {
-                        address: PCA9685_ADDR_2,
-                        pin: 1,
-                    }, // Tube 1 Digit 5
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 4,
-                    }, // Tube 1 Digit 6
-                    DigitToPin {
-                        address: PCA9685_ADDR_2,
-                        pin: 2,
-                    }, // Tube 1 Digit 7
-                    DigitToPin {
-                        address: PCA9685_ADDR_2,
-                        pin: 3,
-                    }, // Tube 1 Digit 8
-                    DigitToPin {
-                        address: PCA9685_ADDR_1,
-                        pin: 3,
-                    }, // Tube 1 Digit 9
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 5, }, // Tube 1 Digit 0
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 6, }, // Tube 1 Digit 1
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 7, }, // Tube 1 Digit 2
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 2, }, // Tube 1 Digit 3
+                    DigitToPin { address: PCA9685_ADDR_2, pin: 4, }, // Tube 1 Digit 4
+                    DigitToPin { address: PCA9685_ADDR_2, pin: 1, }, // Tube 1 Digit 5
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 4, }, // Tube 1 Digit 6
+                    DigitToPin { address: PCA9685_ADDR_2, pin: 2, }, // Tube 1 Digit 7
+                    DigitToPin { address: PCA9685_ADDR_2, pin: 3, }, // Tube 1 Digit 8
+                    DigitToPin { address: PCA9685_ADDR_1, pin: 3, }, // Tube 1 Digit 9
                 ],
             },
             PwmDriver {
                 digit: [
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 8,
-                    }, // Tube 2 Digit 0
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 9,
-                    }, // Tube 2 Digit 1
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 10,
-                    }, // Tube 2 Digit 2
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 12,
-                    }, // Tube 2 Digit 3
-                    DigitToPin {
-                        address: PCA9685_ADDR_2,
-                        pin: 12,
-                    }, // Tube 2 Digit 4
-                    DigitToPin {
-                        address: PCA9685_ADDR_2,
-                        pin: 13,
-                    }, // Tube 2 Digit 5
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 11,
-                    }, // Tube 2 Digit 6
-                    DigitToPin {
-                        address: PCA9685_ADDR_2,
-                        pin: 14,
-                    }, // Tube 2 Digit 7
-                    DigitToPin {
-                        address: PCA9685_ADDR_2,
-                        pin: 11,
-                    }, // Tube 2 Digit 8
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 13,
-                    }, // Tube 2 Digit 9
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 8, }, // Tube 2 Digit 0
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 9, }, // Tube 2 Digit 1
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 10, }, // Tube 2 Digit 2
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 12, }, // Tube 2 Digit 3
+                    DigitToPin { address: PCA9685_ADDR_2, pin: 12, }, // Tube 2 Digit 4
+                    DigitToPin { address: PCA9685_ADDR_2, pin: 13, }, // Tube 2 Digit 5
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 11, }, // Tube 2 Digit 6
+                    DigitToPin { address: PCA9685_ADDR_2, pin: 14, }, // Tube 2 Digit 7
+                    DigitToPin { address: PCA9685_ADDR_2, pin: 11, }, // Tube 2 Digit 8
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 13, }, // Tube 2 Digit 9
                 ],
             },
             PwmDriver {
                 digit: [
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 5,
-                    }, // Tube 3 Digit 0
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 6,
-                    }, // Tube 3 Digit 1
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 7,
-                    }, // Tube 3 Digit 2
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 2,
-                    }, // Tube 3 Digit 3
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 14,
-                    }, // Tube 3 Digit 4
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 15,
-                    }, // Tube 3 Digit 5
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 4,
-                    }, // Tube 3 Digit 6
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 1,
-                    }, // Tube 3 Digit 7
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 0,
-                    }, // Tube 3 Digit 8
-                    DigitToPin {
-                        address: PCA9685_ADDR_3,
-                        pin: 3,
-                    }, // Tube 3 Digit 9
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 5, }, // Tube 3 Digit 0
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 6, }, // Tube 3 Digit 1
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 7, }, // Tube 3 Digit 2
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 2, }, // Tube 3 Digit 3
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 14, }, // Tube 3 Digit 4
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 15, }, // Tube 3 Digit 5
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 4, }, // Tube 3 Digit 6
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 1, }, // Tube 3 Digit 7
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 0, }, // Tube 3 Digit 8
+                    DigitToPin { address: PCA9685_ADDR_3, pin: 3, }, // Tube 3 Digit 9
                 ],
             },
         ],
@@ -298,12 +178,7 @@ impl Tube {
         }
     }
 
-    fn fade_in_out_digit(
-        &mut self,
-        digit: Option<u32>,
-        fade_duration: u32,
-        cycle_cmd: bool,
-    ) {
+    fn fade_in_out_digit(&mut self, digit: Option<u32>, fade_duration: u32, cycle_cmd: bool) {
         // If the tube is in the middle of a cycle sequence and a call comes
         // in to update the tube digit (for time), override the last value of
         // the cycle sequence with the new digit.
@@ -357,7 +232,10 @@ impl Clock {
         }
     }
 
+    // Sets a new time to be displayed
     pub fn rtc_tick(&mut self, second: u32, minute: u32, hour: u32) {
+
+        // Update digit for each tube if value has changed
         match self.hour {
             Some(prev_hour) if prev_hour / 10 == hour / 10 => {
                 if hour / 10 == 0 {
@@ -399,6 +277,7 @@ impl Clock {
             minute % 10
         );
 
+        // Set fade direction for dot
         self.dot.state = match second % 2 {
             0 => State::Incrementing,
             1 => State::Decrementing,
@@ -409,9 +288,11 @@ impl Clock {
         #[cfg(test)]
         println!("RTC tick: dot state is {:?}", self.dot.state);
 
+        // Store the last set value for the next update
         self.hour = Some(hour);
         self.minute = Some(minute);
 
+        // Start the display refresh timer to update the display
         #[cfg(not(test))]
         free(|cs| {
             let mut timer_ref = super::FPS_TIMER.borrow(cs).borrow_mut();
@@ -421,6 +302,8 @@ impl Clock {
         });
     }
 
+    // Updates the display with values due to fade in/out
+    // Returns true if values have changed
     pub fn fps_tick(&mut self) -> bool {
         let mut pending_refresh: bool = false;
 
@@ -435,7 +318,7 @@ impl Clock {
                         digit.updated = true;
                         pending_refresh = true;
                     }
-                },
+                }
                 State::Decrementing => {
                     if digit.value <= min {
                         digit.value = min;
@@ -445,19 +328,18 @@ impl Clock {
                         digit.updated = true;
                         pending_refresh = true;
                     }
-                },
+                }
                 State::Idle => {
                     digit.fade_duration = None;
-                },
+                }
             };
         };
 
         #[cfg(not(test))]
         self.tubes.iter_mut().for_each(|tube| {
             tube.digits.iter_mut().for_each(|digit| {
-
                 if let Some(fade_duration) = digit.fade_duration {
-                    let ticks = fade_duration  * 1000 / (1000 / DISPLAY_REFRESH_FPS * 1000);
+                    let ticks = fade_duration * 1000 / (1000 / DISPLAY_REFRESH_FPS * 1000);
                     let steps = ((DIGIT_MAX_BRIGHTNESS - DIGIT_MIN_BRIGHTNESS) + ticks - 1) / ticks;
                     update_fn(digit, DIGIT_MIN_BRIGHTNESS, DIGIT_MAX_BRIGHTNESS, steps);
                 }
@@ -467,9 +349,8 @@ impl Clock {
         #[cfg(test)]
         for (t, tube) in self.tubes.iter_mut().enumerate() {
             for (d, digit) in tube.digits.iter_mut().enumerate() {
-
                 if let Some(fade_duration) = digit.fade_duration {
-                    let ticks = fade_duration  * 1000 / (1000 / DISPLAY_REFRESH_FPS * 1000);
+                    let ticks = fade_duration * 1000 / (1000 / DISPLAY_REFRESH_FPS * 1000);
                     let steps = ((DIGIT_MAX_BRIGHTNESS - DIGIT_MIN_BRIGHTNESS) + ticks - 1) / ticks;
                     update_fn(digit, DIGIT_MIN_BRIGHTNESS, DIGIT_MAX_BRIGHTNESS, steps);
                 }
@@ -483,9 +364,9 @@ impl Clock {
             }
         }
 
-        // Handle dot
+        // Update dot values
         if let Some(fade_duration) = self.dot.fade_duration {
-            let ticks = fade_duration  * 1000 / (1000 / DISPLAY_REFRESH_FPS * 1000);
+            let ticks = fade_duration * 1000 / (1000 / DISPLAY_REFRESH_FPS * 1000);
             let steps = ((DOT_MAX_BRIGHTNESS - DOT_MIN_BRIGHTNESS) + ticks - 1) / ticks;
             update_fn(&mut self.dot, DOT_MIN_BRIGHTNESS, DOT_MAX_BRIGHTNESS, steps);
         }
@@ -495,6 +376,7 @@ impl Clock {
             println!("Refresh tick: updated dot to value {}", self.dot.value);
         }
 
+        // Compute actual PWM values if display values have changed
         if pending_refresh {
             self.distribute_pwm();
         }
@@ -502,12 +384,13 @@ impl Clock {
         pending_refresh
     }
 
+    // Updates the digit displayed during a cycle sequence
+    // Returns true if the cycle sequence has completed
     pub fn cycle_tick(&mut self) -> bool {
         let mut cycle_ended = true;
 
         self.tubes.iter_mut().for_each(|tube| {
             if let Some(cycle) = tube.cycle.as_mut() {
-
                 #[cfg(test)]
                 println!("Cycle tick: iteration {}", cycle.iteration);
 
@@ -537,6 +420,7 @@ impl Clock {
         cycle_ended
     }
 
+    // Writes updated PWM values to each PCA9685 
     pub fn write_i2c<T>(&mut self, i2c: &mut T)
     where
         T: _embedded_hal_blocking_i2c_WriteRead
@@ -652,20 +536,19 @@ impl Clock {
     }
 }
 
+// Periodically called to update the display with a new time
 pub fn rtc_interrupt<T>(i2c: &mut T)
 where
     T: _embedded_hal_blocking_i2c_WriteRead
         + _embedded_hal_blocking_i2c_Read
         + _embedded_hal_blocking_i2c_Write,
 {
+    // Read new time from DS3231
     let (second, minute, hour) = ds3231::get_time(DS3231_ADDR, i2c);
     let (weekday, day, month, _, _) = ds3231::get_date(DS3231_ADDR, i2c);
 
-    let hour = if ds3231::in_dst(weekday, day, month, hour) {
-        (hour + 1) % 12
-    } else {
-        hour % 12
-    };
+    // Calculate new values and account for DST
+    let hour = if ds3231::in_dst(weekday, day, month, hour) { (hour + 1) % 12 } else { hour % 12 };
     let hour = if hour == 0 { 12 } else { hour };
 
     free(|cs| {
@@ -675,8 +558,7 @@ where
     });
 }
 
-// This function is called by an interrupt that is triggered every
-// DISPLAY_REFRESH_FPS to update the display with a new brightness value.
+// Periodically called to trigger a display refresh
 pub fn fps_interrupt<T>(i2c: &mut T)
 where
     T: _embedded_hal_blocking_i2c_WriteRead
@@ -686,7 +568,11 @@ where
     free(|cs| {
         let mut clock_ref = CLOCK.borrow(cs).borrow_mut();
         let clock = clock_ref.deref_mut();
+
+        // Compute updates for non-static digits
         let updated = clock.fps_tick();
+
+        // Write new values if values have changed, otherwise disable the refresh timer
         if updated {
             clock.write_i2c(i2c);
             free(|cs| {
@@ -706,29 +592,18 @@ where
     });
 }
 
-// This function is called by an interrupt that is triggered every
-// DIGIT_CYCLE_FADE_DURATION_HZ to update the digit being refreshed.
-pub fn cycle_interrupt() {
+// Periodically called during a cycle sequence to increment through digits
+// Returns true if the cycle sequence has completed
+pub fn cycle_interrupt() -> bool {
     free(|cs| {
         let mut clock_ref = CLOCK.borrow(cs).borrow_mut();
         let clock = clock_ref.deref_mut();
 
-        let cycle_ended = clock.cycle_tick();
-        free(|cs| {
-            let mut cycle_timer_ref = super::CYCLE_TIMER.borrow(cs).borrow_mut();
-            if let Some(ref mut cycle_timer) = cycle_timer_ref.deref_mut() {
-                if cycle_ended {
-                    cycle_timer.unlisten(Event::TimeOut);
-                } else {
-                    cycle_timer.clear_interrupt(Event::TimeOut);
-                }
-            }
-        });
-    });
+        clock.cycle_tick()
+    })
 }
 
-// This function is called to start cycling through all digits for a
-// tube to prevent damage to the nixie tube due to cathode poisoning.
+// Start cycling sequence for the given tube to prevent long term damage from cathode poisoning
 pub fn cycle_start(tube: usize) {
     free(|cs| {
         let mut clock_ref = CLOCK.borrow(cs).borrow_mut();
@@ -742,7 +617,7 @@ pub fn cycle_start(tube: usize) {
         });
     });
 
-    // Start the timer to cycle through all digits
+    // Start the timer to cycle through individual digits
     free(|cs| {
         let mut cycle_timer_ref = super::CYCLE_TIMER.borrow(cs).borrow_mut();
         if let Some(ref mut cycle_timer) = cycle_timer_ref.deref_mut() {
@@ -760,14 +635,18 @@ mod test {
     fn pwm_calc_test() {
         let mut clock: Clock = Clock::default();
 
+        // Initialize clock to arbitrary time
         clock.rtc_tick(10, 23, 12);
 
-        for tick in 0..1005 {
+        // Iterate and print output values for each display refresh tick
+        for tick in 0..1000 {
             println!("\nRefresh tick: {}", tick);
             if !clock.fps_tick() {
                 println!("Refresh halted");
                 break;
             }
+
+            // Reset the updated field for each digit
             clock.tubes.iter_mut().for_each(|tube| {
                 tube.digits.iter_mut().for_each(|digit| {
                     digit.updated = false;
@@ -781,6 +660,10 @@ mod test {
     fn cycle_test() {
         let mut clock: Clock = Clock::default();
 
+        // Initialize clock to arbitrary time
+        clock.rtc_tick(10, 23, 12);
+
+        // Simulate a cycle refresh sequence on tube 0
         clock.tubes[0].cycle = Some(CycleSettings {
             last_digit: clock.tubes[0].last_digit,
             next_digit: 0,
@@ -788,8 +671,7 @@ mod test {
             last_fade_duration: DIGIT_FADE_DURATION_MS,
         });
 
-        clock.rtc_tick(10, 23, 12);
-
+        // Iterate and print debug values for each cycle
         for cycle in 0..1000 {
             println!("\nCycle tick: {}", cycle);
             if clock.cycle_tick() {
@@ -797,12 +679,15 @@ mod test {
                 break;
             }
 
-            for tick in 0..1005 {
+            // Iterate and print output values for each display refresh tick
+            for tick in 0..1000 {
                 println!("\nRefresh tick: {}", tick);
                 if !clock.fps_tick() {
                     println!("Refresh halted");
                     break;
                 }
+
+                // Reset the updated field for each digit
                 clock.tubes.iter_mut().for_each(|tube| {
                     tube.digits.iter_mut().for_each(|digit| {
                         digit.updated = false;