use avr_oxide::hal::generic::cpu::private::{PermitIdleToken, PermitStandbyToken};
use avr_oxide::hal::generic::cpu::{ClockControl, ConfigurationChange, Cpu, SleepControl};
use avr_oxide::{mut_singleton, v_read, v_write};
use avr_oxide::hal::atmega328p::{ADDR_CLKPR, ADDR_CPU};
#[repr(C)]
pub struct Atmega328PControlRegisters {
pub(crate) sp: u16,
pub(crate) sreg: u8
}
#[repr(C)]
pub struct Atmega328PClockPrescaleRegister {
pub(crate) clkpr: u8
}
pub struct NullSleepController;
impl Cpu for Atmega328PControlRegisters {
unsafe fn write_protected(&mut self, change: ConfigurationChange, register: &mut u8, value: u8) {
*register = value;
}
fn read_sp(&self) -> u16 {
unsafe {
v_read!(u16,self.sp) & 0b0000_0111_1111_1111
}
}
unsafe fn write_sp(&mut self, sp: u16) {
v_write!(u16,self.sp,sp)
}
fn read_sreg(&self) -> u8 {
unsafe {
v_read!(u8,self.sreg)
}
}
unsafe fn write_sreg(&mut self, sreg: u8) {
v_write!(u8,self.sreg,sreg)
}
fn interrupts_enabled(&self) -> bool {
(self.read_sreg() & 0b1000_0000) > 0
}
}
#[inline(always)]
pub fn instance() -> &'static mut Atmega328PControlRegisters {
unsafe {
core::mem::transmute(ADDR_CPU)
}
}
pub fn clock() -> &'static mut Atmega328PClockPrescaleRegister {
unsafe {
core::mem::transmute(ADDR_CLKPR)
}
}
impl ClockControl for Atmega328PClockPrescaleRegister {
unsafe fn clk_per_prescaler(&mut self, scaler: u8) {
extern "C" {
fn ccp_clkper_write(ioaddr: *mut u8, value: u8);
}
let clkps_val = match scaler {
1 => 0x00,
2 => 0x01,
4 => 0x02,
8 => 0x03,
16 => 0x04,
32 => 0x05,
64 => 0x06,
128 => 0x07,
_ => panic!()
};
ccp_clkper_write(&mut self.clkpr as *mut u8, clkps_val);
}
}
#[macro_export]
macro_rules! cpu {
() => {
avr_oxide::hal::atmega328p::cpu::instance()
}
}
impl SleepControl for NullSleepController {
unsafe fn reset(&mut self) {
}
fn inhibit_standby(&mut self) -> PermitStandbyToken {
PermitStandbyToken
}
fn permit_standby(&mut self, token: PermitStandbyToken) {
}
fn standby_permitted(&self) -> bool {
false
}
fn inhibit_idle(&mut self) -> PermitIdleToken {
PermitIdleToken
}
fn permit_idle(&mut self, token: PermitIdleToken) {
}
fn idle_permitted(&self) -> bool {
false
}
}
mut_singleton!(
NullSleepController,
SLEEPCTRLINSTANCE,
sleepctrl,
NullSleepController {
});
#[macro_export]
macro_rules! sleepctrl {
() => {
avr_oxide::hal::atmega328p::cpu::sleepctrl()
}
}