control segment brightness; test pattern

This commit is contained in:
2025-07-26 15:14:08 +01:00
parent 6517cfd72b
commit f816a09554
3 changed files with 81 additions and 66 deletions

View File

@@ -13,55 +13,51 @@ const fn us_to_ticks(us: u32) -> u32 {
TIMER_FREQ * us / 1_000_000
}
// Sets up timer to rise two interrupts:
// 1. TIMER0_COMPA - segment_switch_us - time in μs to switch to next segment
// 2. TIMER0_COMPB - segment_on_us - time in μs to keep segment LEDs on
pub fn segment_timer_init(tc0: TC0, segment_switch_us: u32, segment_on_us: u32) {
// 16_000_000 / 64 * 1000 / 1_000_000 => 250
let ocra = us_to_ticks(segment_switch_us);
let ocrb = us_to_ticks(segment_on_us);
assert!(
ocra > ocrb + BUFFER_TICKS,
"segment_on_us cannot be longer than segment_switch_us - buffer"
);
// Timer 0 (8bit)
pub struct SegmentTimer(TC0);
// Use CTC mode: reset counter when matches compare value
tc0.tccr0a.write(|w| w.wgm0().ctc());
// Set the compare value for TOP (reset)
tc0.ocr0a.write(|w| {
w.bits(
ocra.try_into()
.expect("timer init segment_switch_us out of rage"),
)
});
// Set the compare value for B match
tc0.ocr0b.write(|w| {
w.bits(
ocrb.try_into()
.expect("timer init segment_on_us out of rage"),
)
});
// Slow down the timer (CLK / prescale)
tc0.tccr0b.write(|w| w.cs0().prescale_64());
// Raise interrupt on TOP (reset)
// Raise interrupt on B match
tc0.timsk0
.write(|w| w.ocie0a().set_bit().ocie0b().set_bit());
}
impl SegmentTimer {
// Sets up timer to rise interrupts:
// 1. TIMER0_COMPA - segment_switch_us - time in μs to switch to next segment
// 2. TIMER0_COMPB - set by set_segment_on_time to keep segment LEDs on
pub fn init(tc0: TC0, segment_switch_us: u32) -> SegmentTimer {
// 16_000_000 / 64 * 1000 / 1_000_000 => 250
let ocra = us_to_ticks(segment_switch_us);
// Set for how long the segment LEDs should be on in μs
pub fn set_segment_on_time(tc0: TC0, segment_on_us: u32) {
let ocra = tc0.ocr0a.read().bits();
let ocrb = us_to_ticks(segment_on_us);
assert!(
ocra as u32 > ocrb + BUFFER_TICKS,
"segment_on_us cannot be longer than segment_switch_us - buffer"
);
// Set the compare value for B match
tc0.ocr0b.write(|w| {
w.bits(
ocrb.try_into()
.expect("timer init segment_on_us out of rage"),
)
});
// Use CTC mode: reset counter when matches compare value
tc0.tccr0a.write(|w| w.wgm0().ctc());
// Set the compare value for TOP (reset)
tc0.ocr0a.write(|w| {
w.bits(
ocra.try_into()
.expect("timer init segment_switch_us out of rage"),
)
});
// Slow down the timer (CLK / prescale)
tc0.tccr0b.write(|w| w.cs0().prescale_64());
// Raise interrupt on TOP (reset)
// Raise interrupt on B match
tc0.timsk0
.write(|w| w.ocie0a().set_bit().ocie0b().set_bit());
SegmentTimer(tc0)
}
// Set for how long the segment LEDs should be on in μs
// Controls TIMER0_COMPB interrupt time after TIMER0_COMPA
pub fn segment_on_time(&mut self, segment_on_us: u32) {
let ocra = self.0.ocr0a.read().bits();
let ocrb = us_to_ticks(segment_on_us);
assert!(
ocra as u32 > ocrb + BUFFER_TICKS,
"segment_on_us cannot be longer than segment_switch_us - buffer"
);
// Set the compare value for B match
self.0.ocr0b.write(|w| {
w.bits(
ocrb.try_into()
.expect("timer init segment_on_us out of rage"),
)
});
}
}