|
@@ -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;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
}
|