From 1f961964f0e67c26ffc2ce28846bee77f39f6bed Mon Sep 17 00:00:00 2001 From: Hexa Dust Date: Fri, 18 Jul 2025 20:31:23 +0100 Subject: [PATCH] use B compare match register to trigger interrupt --- src/main.rs | 31 +++++++++++++++++++++++-------- src/timer.rs | 24 ++++++++++++++++++------ 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/main.rs b/src/main.rs index 94b4770..d3154a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,10 +18,9 @@ use keyboard::{Debounce, KeyPress, KeyReadout, Keyboard}; use arduino_hal::{ adc::channel::{ADC6, ADC7}, - clock::Clock, hal::port::{PB3, PB4, PB5, PC1, PC2, PC3, PD2, PD3, PD4, PD7}, port::{mode::Output, Pin}, - Adc, DefaultClock, + Adc, }; use ufmt::derive::uDebug; @@ -41,6 +40,10 @@ pub const DISPLAY_SEGMENT_SIG_MINUS: usize = 0; pub const DISPLAY_SEGMENTS_EXP: usize = 2; pub const DISPLAY_SEGMENT_EXP_MINUS: usize = 6; +// Timing +pub const IO_SEG_REFRESH_FREQ: u32 = 100; // Segment timer freq; from 62 to 15779 for 8bit counter +pub const IO_SEG_ON_DIV: u32 = 10; // How long to hold segment LEDs on as part of time for segment timer + pub const STACK_DEPTH: usize = 7; type Calc = StackCalc; @@ -61,11 +64,22 @@ unsafe fn TIMER0_COMPA() { // ... avr_device::interrupt::free( |cs| match LED.borrow(cs).borrow_mut().deref_mut().as_mut() { - Some(led) => led.toggle(), + // Some(led) => led.toggle(), + Some(led) => led.set_high(), + None => panic!(), + }, + ); +} + +#[avr_device::interrupt(atmega328p)] +unsafe fn TIMER0_COMPB() { + //TODO: Disable display segment and handle keyboard input for current segment + avr_device::interrupt::free( + |cs| match LED.borrow(cs).borrow_mut().deref_mut().as_mut() { + Some(led) => led.set_low(), None => panic!(), }, ); - //..toggle()); } struct IOSelect<'p> { @@ -470,13 +484,14 @@ fn main() -> ! { calculator: CalcluclatorState::EnterSignificant, }; - // TODO: configure timer, enable it to interrupt: dp.TC1.tifr1 - // https://github.com/monoper/rust-atmega328p/blob/main/arduino-nano/key-tmr-input/src/main.rs - timer::segment_timer_init(dp.TC0, (DefaultClock::FREQ / 1024 / 100) as u8); // 16_000_000 / 1024 / 100 => 156 avr_device::interrupt::free(|cs| { LED.borrow(cs).replace(Some(pins.d13.into_output())); }); - + timer::segment_timer_init( + dp.TC0, // Timer0 (8bit) + IO_SEG_REFRESH_FREQ, // run segments at 100Hz + IO_SEG_ON_DIV, // 1/10th of 100Hz, 1ms segment on time + ); unsafe { avr_device::interrupt::enable(); } diff --git a/src/timer.rs b/src/timer.rs index 5dd76b6..9e307f0 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -1,12 +1,24 @@ -use arduino_hal::pac::TC0; +use arduino_hal::{clock::Clock, pac::TC0, DefaultClock}; + +// Raises two interrupts: TIMER0_COMPA every period cycles/1024 +// and TIMER0_COMPB compb_cocunt cycles/1024 after TIMER0_COMPA +pub fn segment_timer_init(tc0: TC0, seg_freq: u32, on_div: u32) { + // 16_000_000 / 1024 / 100 => 156 (100Hz|10ms) + let ocra = DefaultClock::FREQ / 1024 / seg_freq; + let ocrb: u32 = ocra / on_div; -pub fn segment_timer_init(tc0: TC0, counts: u8) { // Use CTC mode: reset counter when matches compare value tc0.tccr0a.write(|w| w.wgm0().ctc()); - // Set the compare value - tc0.ocr0a.write(|w| w.bits(counts)); + // Set the compare value for TOP (reset) + tc0.ocr0a + .write(|w| w.bits(ocra.try_into().expect("timer init seg_freq 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"))); // Slow down the timer (CLK / prescale) tc0.tccr0b.write(|w| w.cs0().prescale_1024()); - // Raise interrupt on reset - tc0.timsk0.write(|w| w.ocie0a().set_bit()); + // Raise interrupt on counter TOP (reset) + // Raise interrupt on B match + tc0.timsk0 + .write(|w| w.ocie0a().set_bit().ocie0b().set_bit()); }