#[derive(Clone,Copy)]
pub enum TimerMode {
Periodic
}
pub type TimerInterruptHandler = fn(u16) ->bool;
pub trait TimerControl {
fn interrupting(&mut self, period: u16) -> &mut Self;
fn mode(&mut self, mode: TimerMode) -> &mut Self;
fn count_max(&mut self, max: u16) -> &mut Self;
fn start(&mut self, handler: Option<TimerInterruptHandler>);
fn stop(&mut self);
fn get_count(&self) -> u16;
fn reset_count(&mut self);
}
#[cfg(target_arch="avr")]
pub mod base {
use crate::hal::generic::timer::{TimerInterruptHandler, TimerMode, TimerControl};
#[repr(C)]
pub struct AvrTypeBTimerControl {
pub(crate) ctrla: u8,
pub(crate) ctrlb: u8,
pub(crate) reserved: [u8; 2],
pub(crate) evctrl: u8,
pub(crate) intctrl: u8,
pub(crate) intflags: u8,
pub(crate) status: u8,
pub(crate) dbgctrl: u8,
pub(crate) temp: u8,
pub(crate) cnt: u16,
pub(crate) ccmp: u16
}
pub trait AtmelTCB {
fn enable(&mut self);
fn disable(&mut self);
fn enable_interrupt(&mut self);
fn clear_interrupt(&mut self);
fn mask_interrupt(&mut self);
fn set_top(&mut self, top: u16);
fn set_periodic_mode(&mut self);
}
impl AtmelTCB for AvrTypeBTimerControl {
#[inline(always)]
fn enable(&mut self) {
unsafe {
core::ptr::write_volatile(&mut self.ctrla as *mut u8, 0b01000011);
}
}
#[inline(always)]
fn disable(&mut self) {
unsafe {
core::ptr::write_volatile(&mut self.ctrla as *mut u8, 0b00000000);
}
}
#[inline(always)]
fn enable_interrupt(&mut self) {
unsafe {
core::ptr::write_volatile(&mut self.intctrl as *mut u8, 0b00000001);
}
}
#[inline(always)]
fn clear_interrupt(&mut self) {
unsafe {
core::ptr::write_volatile(&mut self.intflags as *mut u8, 0b00000001);
}
}
#[inline(always)]
fn mask_interrupt(&mut self) {
unsafe {
core::ptr::write_volatile(&mut self.intctrl as *mut u8, 0b00000000);
}
}
#[inline(always)]
fn set_top(&mut self, top: u16) {
unsafe {
core::ptr::write_volatile(&mut self.cnt as *mut u16, 0x0000);
core::ptr::write_volatile(&mut self.ccmp as *mut u16, top);
}
}
#[inline(always)]
fn set_periodic_mode(&mut self) {
unsafe {
let ctrlb_reg = &mut self.ctrlb as *mut u8;
let ctrlb = core::ptr::read_volatile(ctrlb_reg);
core::ptr::write_volatile(ctrlb_reg, ctrlb | 0b00010000);
}
}
}
pub struct AtmelTimer<T>
where
T: 'static + AtmelTCB
{
pub(crate) interrupt_handler: Option<TimerInterruptHandler>,
pub(crate) interrupt_period: u16,
pub(crate) tcb: &'static mut T,
pub(crate) count_max: u16,
pub(crate) mode: TimerMode
}
impl<T> TimerControl for AtmelTimer<T>
where
T: AtmelTCB
{
fn interrupting(&mut self, period: u16) -> &mut Self {
unsafe {
core::ptr::write_volatile(&mut self.interrupt_period as *mut u16, period)
}
self
}
fn mode(&mut self, mode: TimerMode) -> &mut Self {
self.mode = mode;
self
}
fn count_max(&mut self, max: u16) -> &mut Self {
self.count_max = max;
self
}
fn start(&mut self, handler: Option<TimerInterruptHandler>) {
self.tcb.disable();
match self.mode {
TimerMode::Periodic => {
self.tcb.set_periodic_mode();
self.tcb.set_top(self.count_max.clone());
}
};
self.tcb.clear_interrupt();
match handler {
None => {
self.tcb.mask_interrupt();
},
Some(handler) => {
self.interrupt_handler = Some(handler);
self.tcb.enable_interrupt();
}
}
self.tcb.enable();
}
fn stop(&mut self) {
self.tcb.disable();
}
fn get_count(&self) -> u16 {
todo!()
}
fn reset_count(&mut self) {
todo!()
}
}
impl<T> AtmelTimer<T>
where
T: AtmelTCB
{
#[inline(always)]
pub(crate) fn call_interrupt(&mut self, ticks: u16) {
match self.interrupt_handler {
Some(handler) => {
match handler(ticks) {
true => {},
false => self.tcb.disable()
}
},
None => {}
}
}
#[inline(always)]
pub(crate) fn interrupt_period(&self) -> u16 {
unsafe {
core::ptr::read_volatile(&self.interrupt_period as *const u16)
}
}
}
#[macro_export]
macro_rules! atmel_tcb {
($tcbref:expr, $isr:ident) => {
use crate::hal::generic::timer::TimerMode;
use crate::hal::generic::timer::base::{ AtmelTimer, AtmelTCB, AvrTypeBTimerControl };
use crate::mut_singleton;
pub type TimerImpl = AtmelTimer<AvrTypeBTimerControl>;
mut_singleton!(
AtmelTimer<AvrTypeBTimerControl>,
INSTANCE,
instance,
AtmelTimer {
interrupt_handler: None,
interrupt_period: 0,
tcb: core::mem::transmute($tcbref),
count_max: 0,
mode: TimerMode::Periodic
});
#[no_mangle]
pub unsafe extern "avr-interrupt" fn $isr() {
static mut COUNT_INTS : u16 = 0;
crate::hal::concurrency::interrupt::isr(||{
let counter = core::ptr::read_volatile(&COUNT_INTS as *const u16);
match &mut INSTANCE {
None => {},
Some(atmeltimer) => {
if counter == 0 {
atmeltimer.call_interrupt(COUNT_INTS.clone());
core::ptr::write_volatile(&mut COUNT_INTS as *mut u16, atmeltimer.interrupt_period())
} else {
core::ptr::write_volatile(&mut COUNT_INTS as *mut u16, counter-1);
}
atmeltimer.tcb.clear_interrupt();
}
}
})
}
}
}
}
#[cfg(not(target_arch="avr"))]
pub mod base {
use crate::hal::generic::timer::{TimerInterruptHandler, TimerMode, TimerControl};
#[repr(C)]
pub struct DummyTypeBTimerControl {
}
pub trait DummyTCB {
fn enable(&mut self);
fn disable(&mut self);
fn enable_interrupt(&mut self);
fn clear_interrupt(&mut self);
fn mask_interrupt(&mut self);
fn set_top(&mut self, top: u16);
fn set_periodic_mode(&mut self);
}
impl DummyTCB for DummyTypeBTimerControl {
fn enable(&mut self) {
println!("*** TCB: Enabled");
}
fn disable(&mut self) {
println!("*** TCB: Disabled");
}
fn enable_interrupt(&mut self) {
println!("*** TCB: Interrupts enabled");
}
fn clear_interrupt(&mut self) {
println!("*** TCB: Interrupts cleared");
}
fn mask_interrupt(&mut self) {
println!("*** TCB: Interrupts masked");
}
fn set_top(&mut self, top: u16) {
println!("*** TCB: Counter top set to {}", top);
}
#[inline(always)]
fn set_periodic_mode(&mut self) {
println!("*** TCB: Set to periodic mode");
}
}
#[allow(dead_code)]
pub struct DummyTimer<T>
where
T: 'static + DummyTCB
{
pub(crate) interrupt_handler: Option<TimerInterruptHandler>,
pub(crate) interrupt_period: u16,
pub(crate) tcb: T,
pub(crate) count_max: u16,
pub(crate) mode: TimerMode
}
impl<T> TimerControl for DummyTimer<T>
where
T: DummyTCB
{
fn interrupting(&mut self, period: u16) -> &mut Self {
println!("*** TCB: Set to interrupt every {} cycles", period);
self
}
fn mode(&mut self, _mode: TimerMode) -> &mut Self {
println!("*** TCB: Set timer mode");
self
}
fn count_max(&mut self, max: u16) -> &mut Self {
println!("*** TCB: Set count_max to {}", max);
self
}
fn start(&mut self, handler: Option<TimerInterruptHandler>) {
println!("*** TCB: Set handler to {:?}", handler);
self.tcb.disable();
match self.mode {
TimerMode::Periodic => {
self.tcb.set_periodic_mode();
self.tcb.set_top(self.count_max.clone());
}
};
self.tcb.clear_interrupt();
match handler {
None => {
self.tcb.mask_interrupt();
},
Some(handler) => {
self.interrupt_handler = Some(handler);
self.tcb.enable_interrupt();
}
}
self.tcb.enable();
}
fn stop(&mut self) {
self.tcb.disable();
}
fn get_count(&self) -> u16 {
todo!()
}
fn reset_count(&mut self) {
todo!()
}
}
impl<T> DummyTimer<T>
where
T: DummyTCB
{
#[allow(dead_code)]
pub(crate) fn call_interrupt(&mut self, ticks: u16) {
match self.interrupt_handler {
Some(handler) => {
match handler(ticks) {
true => {},
false => self.tcb.disable()
}
},
None => {}
}
}
#[allow(dead_code)]
pub(crate) fn interrupt_period(&self) -> u16 {
self.interrupt_period
}
}
#[macro_export]
macro_rules! atmel_tcb {
($tcbref:expr, $isr:ident) => {
use crate::hal::generic::timer::TimerMode;
use crate::hal::generic::timer::base::{ DummyTimer, DummyTypeBTimerControl };
pub type TimerImpl = DummyTimer<DummyTypeBTimerControl>;
static mut INSTANCE: DummyTimer<DummyTypeBTimerControl> = DummyTimer {
interrupt_handler: None,
interrupt_period: 0,
tcb: DummyTypeBTimerControl {},
count_max: 0,
mode: TimerMode::Periodic
};
pub fn instance() -> &'static mut TimerImpl {
unsafe {
&mut INSTANCE
}
}
}
}
}