Browse Source

Preliminary working clock

Kevin Lee 2 years ago
parent
commit
bac69faeef

+ 15 - 15
Nixie_Firmware_Rust/src/ds3231.rs

@@ -107,25 +107,25 @@ register_structs! {
 }
 
 pub enum Weekday {
-    Sunday = 0,
-    Monday = 1,
-    Tuesday = 2,
-    Wednesday = 3,
-    Thursday = 4,
-    Friday = 5,
-    Saturday = 6,
+    Sunday = 1,
+    Monday = 2,
+    Tuesday = 3,
+    Wednesday = 4,
+    Thursday = 5,
+    Friday = 6,
+    Saturday = 7,
 }
 
 impl From<u8> for Weekday {
     fn from(value: u8) -> Self {
         match value {
-            0 => Weekday::Sunday,
-            1 => Weekday::Monday,
-            2 => Weekday::Tuesday,
-            3 => Weekday::Wednesday,
-            4 => Weekday::Thursday,
-            5 => Weekday::Friday,
-            6 => Weekday::Saturday,
+            1 => Weekday::Sunday,
+            2 => Weekday::Monday,
+            3 => Weekday::Tuesday,
+            4 => Weekday::Wednesday,
+            5 => Weekday::Thursday,
+            6 => Weekday::Friday,
+            7 => Weekday::Saturday,
             _ => panic!(),
         }
     }
@@ -288,7 +288,7 @@ fn decimal_to_bcd(value: u32) -> u8 {
 }
 
 pub fn in_dst(weekday: Weekday, day: u32, month: u32, hour_24: u32) -> bool {
-    let prev_sunday: i32 = day as i32 - weekday as i32;
+    let prev_sunday: i32 = day as i32 - weekday as i32 + 1;
     match month {
         0..=2 | 12.. => false,
         4..=10 => true,

+ 35 - 12
Nixie_Firmware_Rust/src/main.rs

@@ -9,13 +9,13 @@
 #[cfg(not(test))]
 use core::panic::PanicInfo;
 
-use core::{borrow::Borrow, cell::RefCell, ops::DerefMut};
-use cortex_m::{asm, interrupt::free, interrupt::Mutex, peripheral::NVIC};
+use core::{cell::RefCell, ops::DerefMut};
+use cortex_m::{interrupt::free, interrupt::Mutex, peripheral::NVIC};
 use cortex_m_rt::entry;
 // use cortex_m_semihosting::hprintln;
 use stm32l4xx_hal::{
     delay::Delay,
-    device::I2C1,
+    device::{I2C1, TIM2},
     gpio::{
         Alternate, Edge, Floating, Input, OpenDrain, Output, PullUp, PushPull, AF4, PA3, PB5, PC15,
     },
@@ -25,6 +25,7 @@ use stm32l4xx_hal::{
     prelude::*,
     rcc,
     stm32::Interrupt,
+    timer::Timer,
 };
 
 mod ds3231;
@@ -50,6 +51,7 @@ static I2C: Mutex<
         >,
     >,
 > = Mutex::new(RefCell::new(None));
+static REFRESH_TIMER: Mutex<RefCell<Option<Timer<TIM2>>>> = Mutex::new(RefCell::new(None));
 
 // unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
 //     core::slice::from_raw_parts(
@@ -92,8 +94,8 @@ fn main() -> ! {
         .pclk2(64.mhz())
         .freeze(&mut flash.acr, &mut pwr);
 
-    // Configure abstract timer that operates off systick timer
-    let mut timer = Delay::new(cp.SYST, clocks);
+    // Configure delay timer that operates off systick timer
+    let mut delay_timer = Delay::new(cp.SYST, clocks);
 
     // Split GPIO peripheral into independent pins and registers
     let mut gpioa = dp.GPIOA.split(&mut rcc.ahb2);
@@ -206,8 +208,24 @@ fn main() -> ! {
         State::High,
     );
 
+    // Initialize the PCA9685 display refresh timer
+    let refresh_timer = Timer::tim2(
+        dp.TIM2,
+        nixie::REFRESH_RATE_HZ.hz(),
+        clocks,
+        &mut rcc.apb1r1,
+    );
+
+    // Configure NVIC mask to enable interrupt for TIM2
+    unsafe { NVIC::unmask(Interrupt::TIM2) };
+
+    // Save display refresh timer in static singleton so that interrupt has access to it
+    free(|cs| {
+        REFRESH_TIMER.borrow(cs).replace(Some(refresh_timer));
+    });
+
     // Small delay to ensure that PCA9685 is fully powered on before writing to it
-    timer.delay_us(10_u32);
+    delay_timer.delay_us(10_u32);
 
     // Initialize PCA9685 (PWM driver)
     pca9685::init(PCA9685_ALL_CALL, &mut i2c);
@@ -215,8 +233,6 @@ fn main() -> ! {
     // Enable PWM output after PCA9685 has been initialized
     pwm_enable.set_low().unwrap();
 
-    pca9685::set_digit(PCA9685_ADDR_1, &mut i2c, 0, 0, 4096);
-
     // Store I2C peripheral in global static variable as it is used in interrupt
     free(|cs| {
         I2C.borrow(cs).replace(Some(i2c));
@@ -248,11 +264,8 @@ fn EXTI9_5() {
         if let Some(ref mut rtc_int) = rtc_int_ref.deref_mut() {
             if let Some(ref mut i2c) = i2c_int_ref.deref_mut() {
                 if rtc_int.check_interrupt() {
-                    rtc_int.clear_interrupt_pending_bit();
                     nixie::rtc_tick(i2c);
-                    // set_fault_led(State::High);
-                    // asm::delay(8_000_000);
-                    // set_fault_led(State::Low);
+                    rtc_int.clear_interrupt_pending_bit();
                 }
             }
         }
@@ -273,6 +286,16 @@ fn EXTI3() {
     });
 }
 
+#[interrupt]
+fn TIM2() {
+    free(|cs| {
+        let mut i2c_int_ref = I2C.borrow(cs).borrow_mut();
+        if let Some(ref mut i2c) = i2c_int_ref.deref_mut() {
+            nixie::refresh_tick(i2c);
+        }
+    });
+}
+
 #[panic_handler]
 #[cfg(not(test))]
 /// Custom panic handler

+ 218 - 166
Nixie_Firmware_Rust/src/nixie.rs

@@ -1,8 +1,12 @@
+use core::ops::DerefMut;
+
+use cortex_m::interrupt::free;
 use stm32l4xx_hal::{
     prelude::{
         _embedded_hal_blocking_i2c_Read, _embedded_hal_blocking_i2c_Write,
         _embedded_hal_blocking_i2c_WriteRead,
     },
+    timer::Event,
 };
 
 use crate::{ds3231, pca9685};
@@ -25,7 +29,7 @@ const MAP_ADDR: usize = 0;
 const MAP_PIN: usize = 1;
 
 const DIGIT_FADE_DURATION_US: u32 = 1_000_000;
-const REFRESH_RATE_US: u32 = 1000;
+pub const REFRESH_RATE_HZ: u32 = 1000;
 
 const DIGIT_RNG_FADE_DURATION_US: u32 = 200_000;
 const DIGIT_RNG_FADE_ITERATIONS: usize = 20;
@@ -323,81 +327,22 @@ pub fn fade_in_out_digit(tube: usize, digit: Option<usize>, fade_duration: u32,
         if (!CLOCK.tubes[tube].refresh_active && !refresh_cmd) || refresh_cmd {
             // Fade out all digits
             for digit in 0..NUM_DIGITS {
-                CLOCK.tubes[tube].digits[digit].current_state = DigitState::Decrementing;
+                if CLOCK.tubes[tube].digits[digit].value != DIGIT_MIN_BRIGHTNESS {
+                    CLOCK.tubes[tube].digits[digit].current_state = DigitState::Decrementing;
+                }
             }
 
             // Fade in the specified digit
             if let Some(digit) = digit {
-                CLOCK.tubes[tube].digits[digit].current_state = DigitState::Incrementing;
+                if CLOCK.tubes[tube].digits[digit].value != DIGIT_MAX_BRIGHTNESS {
+                    CLOCK.tubes[tube].digits[digit].current_state = DigitState::Incrementing;
+                }
             }
 
             CLOCK.tubes[tube].last_active_digit = digit;
             CLOCK.fade_duration = fade_duration;
         }
     }
-
-    // TODO! trigger refresh timer
-}
-
-pub fn refresh_frame() {
-    let mut pending_refresh: bool = false;
-    unsafe {
-        let ticks = CLOCK.fade_duration / REFRESH_RATE_US;
-        let steps = ((DIGIT_MAX_BRIGHTNESS - DIGIT_MIN_BRIGHTNESS) + ticks - 1) / ticks;
-        CLOCK.tubes.iter_mut().for_each(|tube| {
-            tube.digits.iter_mut().for_each(|digit| {
-                match digit.current_state {
-                    DigitState::Incrementing => {
-                        digit.value = digit.value.saturating_add(steps);
-                        if digit.value >= DIGIT_MAX_BRIGHTNESS {
-                            digit.value = DIGIT_MAX_BRIGHTNESS;
-                            digit.current_state = DigitState::Idle;
-                        }
-                        digit.updated = true;
-                        pending_refresh = true;
-                    }
-                    DigitState::Decrementing => {
-                        digit.value = digit.value.saturating_sub(steps);
-                        if digit.value <= DIGIT_MIN_BRIGHTNESS {
-                            digit.value = DIGIT_MIN_BRIGHTNESS;
-                            digit.current_state = DigitState::Idle;
-                        }
-                        digit.updated = true;
-                        pending_refresh = true;
-                    }
-                    DigitState::Idle => (),
-                };
-            });
-        });
-
-        // Handle dot
-        let steps = ((DOT_MAX_BRIGHTNESS - DOT_MIN_BRIGHTNESS) + ticks - 1) / ticks;
-        match CLOCK.dot.current_state {
-            DigitState::Incrementing => {
-                CLOCK.dot.value = CLOCK.dot.value.saturating_add(steps);
-                if CLOCK.dot.value >= DIGIT_MAX_BRIGHTNESS {
-                    CLOCK.dot.value = DIGIT_MAX_BRIGHTNESS;
-                    CLOCK.dot.current_state = DigitState::Idle;
-                }
-                CLOCK.dot.updated = true;
-                pending_refresh = true;
-            }
-            DigitState::Decrementing => {
-                CLOCK.dot.value = CLOCK.dot.value.saturating_sub(steps);
-                if CLOCK.dot.value >= DIGIT_MIN_BRIGHTNESS {
-                    CLOCK.dot.value = DIGIT_MIN_BRIGHTNESS;
-                    CLOCK.dot.current_state = DigitState::Idle;
-                }
-                CLOCK.dot.updated = true;
-                pending_refresh = true;
-            }
-            DigitState::Idle => (),
-        }
-    }
-
-    if pending_refresh {
-        // TODO! trigger refresh timer
-    }
 }
 
 pub fn rtc_tick<T>(i2c: &mut T)
@@ -463,6 +408,13 @@ where
         PREV_HOUR = hour;
 
         STARTUP = false;
+
+        free(|cs| {
+            let mut timer_ref = super::REFRESH_TIMER.borrow(cs).borrow_mut();
+            if let Some(ref mut timer) = timer_ref.deref_mut() {
+                timer.listen(Event::TimeOut);
+            }
+        })
     }
 }
 
@@ -472,33 +424,123 @@ where
         + _embedded_hal_blocking_i2c_Read
         + _embedded_hal_blocking_i2c_Write,
 {
-    compute_pwm_offset();
-
+    let mut pending_refresh: bool = false;
     unsafe {
-        for (t, tube) in CLOCK.tubes.iter().enumerate() {
-            for (d, digit) in tube.digits.iter().filter(|d| d.updated).enumerate() {
+        let ticks = CLOCK.fade_duration / REFRESH_RATE_HZ;
+        let steps = ((DIGIT_MAX_BRIGHTNESS - DIGIT_MIN_BRIGHTNESS) + ticks - 1) / ticks;
+
+        CLOCK.tubes.iter_mut().for_each(|tube| {
+            tube.digits.iter_mut().for_each(|digit| {
+                match digit.current_state {
+                    DigitState::Incrementing => {
+                        if digit.value >= DIGIT_MAX_BRIGHTNESS {
+                            digit.value = DIGIT_MAX_BRIGHTNESS;
+                            digit.current_state = DigitState::Idle;
+                        } else {
+                            digit.value = digit
+                                .value
+                                .saturating_add(steps)
+                                .clamp(DIGIT_MIN_BRIGHTNESS, DIGIT_MAX_BRIGHTNESS);
+                            digit.updated = true;
+                            pending_refresh = true;
+                        }
+                    }
+                    DigitState::Decrementing => {
+                        if digit.value <= DIGIT_MIN_BRIGHTNESS {
+                            digit.value = DIGIT_MIN_BRIGHTNESS;
+                            digit.current_state = DigitState::Idle;
+                        } else {
+                            digit.value = digit
+                                .value
+                                .saturating_sub(steps)
+                                .clamp(DIGIT_MIN_BRIGHTNESS, DIGIT_MAX_BRIGHTNESS);
+                            digit.updated = true;
+                            pending_refresh = true;
+                        }
+                    }
+                    DigitState::Idle => (),
+                };
+            });
+        });
+
+        // Handle dot
+        let steps = ((DOT_MAX_BRIGHTNESS - DOT_MIN_BRIGHTNESS) + ticks - 1) / ticks;
+        match CLOCK.dot.current_state {
+            DigitState::Incrementing => {
+                CLOCK.dot.value = CLOCK
+                    .dot
+                    .value
+                    .saturating_add(steps)
+                    .clamp(DOT_MIN_BRIGHTNESS, DOT_MAX_BRIGHTNESS);
+                if CLOCK.dot.value >= DOT_MAX_BRIGHTNESS {
+                    CLOCK.dot.value = DOT_MAX_BRIGHTNESS;
+                    CLOCK.dot.current_state = DigitState::Idle;
+                }
+                CLOCK.dot.updated = true;
+                pending_refresh = true;
+            }
+            DigitState::Decrementing => {
+                CLOCK.dot.value = CLOCK
+                    .dot
+                    .value
+                    .saturating_sub(steps)
+                    .clamp(DOT_MIN_BRIGHTNESS, DOT_MAX_BRIGHTNESS);
+                if CLOCK.dot.value <= DOT_MIN_BRIGHTNESS {
+                    CLOCK.dot.value = DOT_MIN_BRIGHTNESS;
+                    CLOCK.dot.current_state = DigitState::Idle;
+                }
+                CLOCK.dot.updated = true;
+                pending_refresh = true;
+            }
+            DigitState::Idle => (),
+        }
+    }
+
+    if !pending_refresh {
+        free(|cs| {
+            let mut timer_ref = super::REFRESH_TIMER.borrow(cs).borrow_mut();
+            if let Some(ref mut timer) = timer_ref.deref_mut() {
+                timer.unlisten(Event::TimeOut);
+            }
+        })
+    } else {
+        compute_pwm_offset();
+
+        unsafe {
+            for (t, tube) in CLOCK.tubes.iter().enumerate() {
+                for (d, digit) in tube.digits.iter().enumerate() {
+                    if digit.updated {
+                        pca9685::set_digit(
+                            TUBE_MAPPING.driver[t].digit[d].address,
+                            i2c,
+                            TUBE_MAPPING.driver[t].digit[d].pin,
+                            digit.pwm_start,
+                            digit.pwm_end,
+                        );
+                    }
+                }
+            }
+            if CLOCK.dot.updated {
                 pca9685::set_digit(
-                    TUBE_MAPPING.driver[t].digit[d].address,
+                    TUBE_MAPPING.dot_address,
                     i2c,
-                    TUBE_MAPPING.driver[t].digit[d].pin,
-                    digit.pwm_start,
-                    digit.pwm_end,
+                    TUBE_MAPPING.dot_pin,
+                    CLOCK.dot.pwm_start,
+                    CLOCK.dot.pwm_end,
                 );
             }
         }
-        if CLOCK.dot.updated {
-            pca9685::set_digit(
-                TUBE_MAPPING.dot_address,
-                i2c,
-                TUBE_MAPPING.dot_pin,
-                CLOCK.dot.pwm_start,
-                CLOCK.dot.pwm_end,
-            );
-        }
+
+        free(|cs| {
+            let mut timer_ref = super::REFRESH_TIMER.borrow(cs).borrow_mut();
+            if let Some(ref mut timer) = timer_ref.deref_mut() {
+                timer.clear_interrupt(Event::TimeOut);
+            }
+        })
     }
 }
 
-pub fn rng_tick<T>(i2c: &mut T)
+pub fn rng_tick<T>(_i2c: &mut T)
 where
     T: _embedded_hal_blocking_i2c_WriteRead
         + _embedded_hal_blocking_i2c_Read
@@ -509,91 +551,101 @@ where
 // In the event that there are multiple PWM outputs at less than 100% duty cycle,
 // stagger the start time of each PWM to reduce the switch on surge current.
 fn compute_pwm_offset() {
-    let mut active_digits: u32 = 0;
-    let mut total_on_time: u32 = 0;
-    let mut last_pwm_end: u32 = 0;
+    // let mut active_digits: u32 = 0;
+    // let mut total_on_time: u32 = 0;
+    // let mut last_pwm_end: u32 = 0;
 
-    // Determine the number of active outputs as well as the total on-time across all outputs.
-    // Ignore outputs that are off (min) or fully on (max) as they have no surge impact.
     unsafe {
-        CLOCK.tubes.iter().for_each(|tube| {
-            tube.digits.iter().for_each(|digit| {
-                if digit.value != DIGIT_MAX_BRIGHTNESS && digit.value != DIGIT_MIN_BRIGHTNESS {
-                    active_digits = active_digits + 1;
-                    total_on_time = total_on_time + digit.value;
-                }
+        CLOCK.tubes.iter_mut().for_each(|tube| {
+            tube.digits.iter_mut().for_each(|digit| {
+                digit.pwm_start = 0;
+                digit.pwm_end = digit.value;
             });
         });
-        if CLOCK.dot.value != DIGIT_MAX_BRIGHTNESS && CLOCK.dot.value != DIGIT_MIN_BRIGHTNESS {
-            active_digits = active_digits + 1;
-            total_on_time = total_on_time + CLOCK.dot.value;
-        }
-
-        // If the total on-time across all outputs is less than one PWM period, stagger each
-        // output such that the rise of one pulse begins at the end of the previous pulse.
-        if total_on_time <= DIGIT_MAX_BRIGHTNESS {
-            CLOCK.tubes.iter_mut().for_each(|tube| {
-                tube.digits.iter_mut().for_each(|digit| {
-                    if digit.value == DIGIT_MIN_BRIGHTNESS {
-                        digit.pwm_start = 0;
-                        digit.pwm_end = 0;
-                    } else if digit.value == DIGIT_MAX_BRIGHTNESS {
-                        digit.pwm_start = 0;
-                        digit.pwm_end = DIGIT_MAX_BRIGHTNESS;
-                    } else {
-                        digit.pwm_start = last_pwm_end;
-                        digit.pwm_end = last_pwm_end + digit.value;
-                        last_pwm_end = digit.pwm_end;
-                        digit.updated = true;
-                    }
-                });
-            });
-
-            if CLOCK.dot.value == DIGIT_MIN_BRIGHTNESS {
-                CLOCK.dot.pwm_start = 0;
-                CLOCK.dot.pwm_end = 0;
-            } else if CLOCK.dot.value == DIGIT_MAX_BRIGHTNESS {
-                CLOCK.dot.pwm_start = 0;
-                CLOCK.dot.pwm_end = DIGIT_MAX_BRIGHTNESS;
-            } else {
-                CLOCK.dot.pwm_start = last_pwm_end;
-                CLOCK.dot.pwm_end = last_pwm_end + CLOCK.dot.value;
-                CLOCK.dot.updated = true;
-            }
-        } else {
-            // Compute the amount of overlap between all outputs
-            // int overlap = (totalOnTime - PCA9685_Max_Brightness) / (validOutputs - 1);
-            let overlap = (total_on_time - DIGIT_MAX_BRIGHTNESS) / (active_digits - 1);
-
-            // Compute the staggered output period for each output
-            CLOCK.tubes.iter_mut().for_each(|tube| {
-                tube.digits.iter_mut().for_each(|digit| {
-                    if digit.value == DIGIT_MIN_BRIGHTNESS {
-                        digit.pwm_start = 0;
-                        digit.pwm_end = 0;
-                    } else if digit.value == DIGIT_MAX_BRIGHTNESS {
-                        digit.pwm_start = 0;
-                        digit.pwm_end = DIGIT_MAX_BRIGHTNESS;
-                    } else {
-                        digit.pwm_start = last_pwm_end.saturating_sub(overlap);
-                        digit.pwm_end = digit.pwm_start + digit.value;
-                        last_pwm_end = digit.pwm_end;
-                        digit.updated = true;
-                    }
-                });
-            });
-
-            if CLOCK.dot.value == DIGIT_MIN_BRIGHTNESS {
-                CLOCK.dot.pwm_start = 0;
-                CLOCK.dot.pwm_end = 0;
-            } else if CLOCK.dot.value == DIGIT_MAX_BRIGHTNESS {
-                CLOCK.dot.pwm_start = 0;
-                CLOCK.dot.pwm_end = DIGIT_MAX_BRIGHTNESS;
-            } else {
-                CLOCK.dot.pwm_start = last_pwm_end.saturating_sub(overlap);
-                CLOCK.dot.pwm_end = CLOCK.dot.pwm_start + CLOCK.dot.value;
-                CLOCK.dot.updated = true;
-            }
-        }
+        CLOCK.dot.pwm_start = 0;
+        CLOCK.dot.pwm_end = CLOCK.dot.value;
     }
+
+    // Determine the number of active outputs as well as the total on-time across all outputs.
+    // Ignore outputs that are off (min) or fully on (max) as they have no surge impact.
+    // unsafe {
+    //     CLOCK.tubes.iter().for_each(|tube| {
+    //         tube.digits.iter().for_each(|digit| {
+    //             if digit.value != DIGIT_MAX_BRIGHTNESS && digit.value != DIGIT_MIN_BRIGHTNESS {
+    //                 active_digits = active_digits + 1;
+    //                 total_on_time = total_on_time + digit.value;
+    //             }
+    //         });
+    //     });
+    //     if CLOCK.dot.value != DIGIT_MAX_BRIGHTNESS && CLOCK.dot.value != DIGIT_MIN_BRIGHTNESS {
+    //         active_digits = active_digits + 1;
+    //         total_on_time = total_on_time + CLOCK.dot.value;
+    //     }
+
+    //     // If the total on-time across all outputs is less than one PWM period, stagger each
+    //     // output such that the rise of one pulse begins at the end of the previous pulse.
+    //     if total_on_time <= DIGIT_MAX_BRIGHTNESS {
+    //         CLOCK.tubes.iter_mut().for_each(|tube| {
+    //             tube.digits.iter_mut().for_each(|digit| {
+    //                 if digit.value == DIGIT_MIN_BRIGHTNESS {
+    //                     digit.pwm_start = 0;
+    //                     digit.pwm_end = 0;
+    //                 } else if digit.value == DIGIT_MAX_BRIGHTNESS {
+    //                     digit.pwm_start = 0;
+    //                     digit.pwm_end = DIGIT_MAX_BRIGHTNESS;
+    //                 } else {
+    //                     digit.pwm_start = last_pwm_end;
+    //                     digit.pwm_end = last_pwm_end + digit.value;
+    //                     last_pwm_end = digit.pwm_end;
+    //                     digit.updated = true;
+    //                 }
+    //             });
+    //         });
+
+    //         if CLOCK.dot.value == DIGIT_MIN_BRIGHTNESS {
+    //             CLOCK.dot.pwm_start = 0;
+    //             CLOCK.dot.pwm_end = 0;
+    //         } else if CLOCK.dot.value == DIGIT_MAX_BRIGHTNESS {
+    //             CLOCK.dot.pwm_start = 0;
+    //             CLOCK.dot.pwm_end = DIGIT_MAX_BRIGHTNESS;
+    //         } else {
+    //             CLOCK.dot.pwm_start = last_pwm_end;
+    //             CLOCK.dot.pwm_end = last_pwm_end + CLOCK.dot.value;
+    //             CLOCK.dot.updated = true;
+    //         }
+    //     } else {
+    //         // Compute the amount of overlap between all outputs
+    //         let overlap = (total_on_time - DIGIT_MAX_BRIGHTNESS) / (active_digits - 1);
+
+    //         // Compute the staggered output period for each output
+    //         CLOCK.tubes.iter_mut().for_each(|tube| {
+    //             tube.digits.iter_mut().for_each(|digit| {
+    //                 if digit.value == DIGIT_MIN_BRIGHTNESS {
+    //                     digit.pwm_start = 0;
+    //                     digit.pwm_end = 0;
+    //                 } else if digit.value == DIGIT_MAX_BRIGHTNESS {
+    //                     digit.pwm_start = 0;
+    //                     digit.pwm_end = DIGIT_MAX_BRIGHTNESS;
+    //                 } else {
+    //                     digit.pwm_start = last_pwm_end.saturating_sub(overlap);
+    //                     digit.pwm_end = digit.pwm_start + digit.value;
+    //                     last_pwm_end = digit.pwm_end;
+    //                     digit.updated = true;
+    //                 }
+    //             });
+    //         });
+
+    //         if CLOCK.dot.value == DIGIT_MIN_BRIGHTNESS {
+    //             CLOCK.dot.pwm_start = 0;
+    //             CLOCK.dot.pwm_end = 0;
+    //         } else if CLOCK.dot.value == DIGIT_MAX_BRIGHTNESS {
+    //             CLOCK.dot.pwm_start = 0;
+    //             CLOCK.dot.pwm_end = DIGIT_MAX_BRIGHTNESS;
+    //         } else {
+    //             CLOCK.dot.pwm_start = last_pwm_end.saturating_sub(overlap);
+    //             CLOCK.dot.pwm_end = CLOCK.dot.pwm_start + CLOCK.dot.value;
+    //             CLOCK.dot.updated = true;
+    //         }
+    //     }
+    // }
 }

+ 10 - 1
Nixie_Firmware_Rust/src/pca9685.rs

@@ -103,6 +103,15 @@ pub fn init(address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
         Err(_) => panic!(),
     }
 
+    // Zero 
+    let mut buffer: [u8; 65] = [0; 65];
+    buffer[0] = offset_of!(Pca9685Registers => led).get_byte_offset() as u8;
+
+    match i2c.write(address, &buffer) {
+        Ok(_) => (),
+        Err(_) => panic!(),
+    }
+
     // Re-enable outputs
     mode1_reg.modify(MODE_1::SLEEP::CLEAR);
 
@@ -127,7 +136,7 @@ pub fn set_digit(
     let led_reg: InMemoryRegister<u32, LED_CTRL::Register> = InMemoryRegister::new(0);
 
     led_reg.modify(LED_CTRL::On.val(pwm_start));
-    led_reg.modify(LED_CTRL::On.val(pwm_end));
+    led_reg.modify(LED_CTRL::Off.val(pwm_end));
 
     if pwm_end == 0 {
         led_reg.modify(LED_CTRL::Off_Full::SET)