timer refactoring
This commit is contained in:
61
src/timer.rs
61
src/timer.rs
@@ -1,22 +1,46 @@
|
||||
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;
|
||||
|
||||
// How much time in μs to reserve for post LED off operation (keyboard read)
|
||||
const BUFFER_US: u32 = 250;
|
||||
const BUFFER_TICKS: u32 = us_to_ticks(BUFFER_US);
|
||||
|
||||
const fn us_to_ticks(us: u32) -> u32 {
|
||||
TIMER_FREQ * us / 1_000_000
|
||||
}
|
||||
|
||||
// Sets up timer to rise two interrupts:
|
||||
// 1. TIMER0_COMPA - every segment_rate_us μs
|
||||
// 2. TIMER0_COMPB - segment_on_us μs after TIMER0_COMPA
|
||||
pub fn segment_timer_init(tc0: TC0, segment_rate_us: u32, segment_on_us: u32) {
|
||||
// 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 = DefaultClock::FREQ / 64 * segment_rate_us / 1_000_000;
|
||||
let ocrb = DefaultClock::FREQ / 64 * segment_on_us / 1_000_000;
|
||||
assert!(ocra > ocrb);
|
||||
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"
|
||||
);
|
||||
|
||||
// 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 seg_freq out of rage")));
|
||||
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 on_div out of rage")));
|
||||
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)
|
||||
@@ -24,3 +48,20 @@ pub fn segment_timer_init(tc0: TC0, segment_rate_us: u32, segment_on_us: u32) {
|
||||
tc0.timsk0
|
||||
.write(|w| w.ocie0a().set_bit().ocie0b().set_bit());
|
||||
}
|
||||
|
||||
// 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"),
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user