55 lines
1.8 KiB
Rust
55 lines
1.8 KiB
Rust
use arduino_hal::{clock::Clock, pac::TC0, DefaultClock};
|
|
|
|
// Prescaler set for the timer (see tccr0b)
|
|
const TIMER_PRESCALE: u32 = 64;
|
|
// Timer clock tick rate per second
|
|
const TIMER_FREQ: u32 = DefaultClock::FREQ / TIMER_PRESCALE;
|
|
|
|
const fn us_to_ticks(us: u32) -> u32 {
|
|
TIMER_FREQ * us / 1_000_000
|
|
}
|
|
|
|
// Timer 0 (8bit)
|
|
pub struct SegmentTimer(TC0);
|
|
|
|
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);
|
|
|
|
// 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 ocrb = us_to_ticks(segment_on_us);
|
|
// 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"),
|
|
)
|
|
});
|
|
}
|
|
}
|