avr-oxide 0.0.5

An extremely simple Rusty operating system for AVR microcontrollers
/* masterclock.rs
 *
 * Developed by Tim Walls <tim.walls@snowgoons.com>
 * Copyright (c) All Rights Reserved, Tim Walls
 */

// Imports ===================================================================
use crate::hal::generic::timer::TimerControl;
use crate::hal::generic::timer::TimerMode::Periodic;
use crate::event::{EventSink, OxideEvent};

use crate::deviceconsts::clock::{ MASTER_CLOCK_PRESCALER, MASTER_CLOCK_HZ, MASTER_TICK_FREQ_HZ };
use static_assertions::const_assert;
use core::marker::PhantomData;

// Declarations ==============================================================
pub struct MasterClock<T,S>
where
  T: 'static + TimerControl,
  S: EventSink
{
  timer: &'static mut T,
  phantom: PhantomData<S>
}


// Code ======================================================================


impl<T, S> MasterClock<T, S>
where
  T: TimerControl,
  S: EventSink
{


  pub fn using_timer<const FREQ_HZ: u16>(timer: &'static mut T) -> Self {
    const CYCLES_PER_TICK: u16       = (MASTER_CLOCK_HZ as u32/(2u32 * MASTER_CLOCK_PRESCALER as u32 * MASTER_TICK_FREQ_HZ as u32)) as u16; // We use CLK_PER/2 in timer config, hence the 2* term
    const_assert!(CYCLES_PER_TICK > 10); // Sanity check really

    debug_assert!(FREQ_HZ < MASTER_TICK_FREQ_HZ);
    debug_assert!(FREQ_HZ > 0);

    Self {
      timer: timer.mode(Periodic).count_max(CYCLES_PER_TICK).interrupting((MASTER_TICK_FREQ_HZ/FREQ_HZ) as u16),
      phantom: PhantomData::default()
    }
  }

  pub fn run(&mut self) {
    self.timer.start(Some(|ticks:u16| {
      S::event(OxideEvent::MasterClockEvent(ticks));
      true
    }));
  }
}


// Tests =====================================================================