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"), ) }); } }