corstone300-hal 0.1.0

Hardware abstraction layer Crate for the Arm(R) Corstone(TM)-300 Reference System
Documentation
// Copyright 2022 Arm Limited and/or its affiliates <open-source-office@arm.com>
//
// SPDX-License-Identifier: MIT

use crate::pac;

pub struct Led<const ID: usize>;
impl<const ID: usize> embedded_hal::digital::v2::OutputPin for Led<ID> {
    type Error = core::convert::Infallible;

    fn set_low(&mut self) -> Result<(), Self::Error> {
        unsafe {
            let mask = 1 << ID;
            let fpgaio = &*pac::FPGAIO::ptr();
            fpgaio.led.modify(|r, w| w.bits(r.bits() & !mask));
        }
        Ok(())
    }

    fn set_high(&mut self) -> Result<(), Self::Error> {
        unsafe {
            let mask = 1 << ID;
            let fpgaio = &*pac::FPGAIO::ptr();
            fpgaio.led.modify(|r, w| w.bits(r.bits() | mask));
        }
        Ok(())
    }
}
impl<const ID: usize> embedded_hal::digital::v2::StatefulOutputPin for Led<ID> {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        unsafe {
            let mask = 1 << ID;
            let fpgaio = &*pac::FPGAIO::ptr();
            Ok(fpgaio.led.read().bits() & mask == mask)
        }
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        unsafe {
            let mask = 1 << ID;
            let fpgaio = &*pac::FPGAIO::ptr();
            Ok(fpgaio.led.read().bits() & mask == 0)
        }
    }
}
impl<const ID: usize> embedded_hal::digital::v2::toggleable::Default for Led<ID> {}

pub struct Button<const _ID: usize>;
impl<const ID: usize> embedded_hal::digital::v2::InputPin for Button<ID> {
    type Error = core::convert::Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        unsafe {
            let mask = 1 << ID;
            let fpgaio = &*pac::FPGAIO::ptr();
            Ok(fpgaio.button.read().bits() & mask == mask)
        }
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        unsafe {
            let mask = 1 << ID;
            let fpgaio = &*pac::FPGAIO::ptr();
            Ok(fpgaio.button.read().bits() & mask == 0)
        }
    }
}
pub struct Switch<const _ID: usize>;
impl<const ID: usize> embedded_hal::digital::v2::InputPin for Switch<ID> {
    type Error = core::convert::Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        unsafe {
            let mask = 1 << ID;
            let fpgaio = &*pac::FPGAIO::ptr();
            Ok(fpgaio.switches.read().bits() & mask == mask)
        }
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        unsafe {
            let mask = 1 << ID;
            let fpgaio = &*pac::FPGAIO::ptr();
            Ok(fpgaio.switches.read().bits() & mask == 0)
        }
    }
}
pub struct Clocks;
impl Clocks {
    pub fn clk1hz(&self) -> u32 {
        unsafe {
            let fpgaio = &*pac::FPGAIO::ptr();
            fpgaio.clk1hz.read().bits()
        }
    }
    pub fn clk100hz(&self) -> u32 {
        unsafe {
            let fpgaio = &*pac::FPGAIO::ptr();
            fpgaio.clk100hz.read().bits()
        }
    }
    pub fn counter(&mut self) -> &pac::fpgaio::COUNTER {
        unsafe {
            let fpgaio = &*pac::FPGAIO::ptr();
            &fpgaio.counter
        }
    }
    pub fn prescaler(&mut self) -> &pac::fpgaio::PRESCALER {
        unsafe {
            let fpgaio = &*pac::FPGAIO::ptr();
            &fpgaio.prescaler
        }
    }
    pub fn pscntr(&mut self) -> &pac::fpgaio::PSCNTR {
        unsafe {
            let fpgaio = &*pac::FPGAIO::ptr();
            &fpgaio.pscntr
        }
    }
}

pub struct Parts {
    pub ul0: Led<0>,
    pub ul1: Led<1>,
    pub ul2: Led<2>,
    pub ul3: Led<3>,
    pub ul4: Led<4>,
    pub ul5: Led<5>,
    pub ul6: Led<6>,
    pub ul7: Led<7>,
    pub pb1led: Led<8>,
    pub pb2led: Led<9>,
    pub button0: Button<0>,
    pub button1: Button<1>,
    pub switch0: Switch<0>,
    pub switch1: Switch<1>,
    pub switch2: Switch<2>,
    pub switch3: Switch<3>,
    pub switch4: Switch<4>,
    pub switch5: Switch<5>,
    pub switch6: Switch<6>,
    pub switch7: Switch<7>,
    pub clocks: Clocks,
}

pub trait FPGAIOExt {
    fn split(self) -> Parts;
}

macro_rules! impl_ext {
    ($p:path) => {
        impl FPGAIOExt for $p {
            fn split(self) -> Parts {
                Parts {
                    ul0: Led,
                    ul1: Led,
                    ul2: Led,
                    ul3: Led,
                    ul4: Led,
                    ul5: Led,
                    ul6: Led,
                    ul7: Led,
                    pb1led: Led,
                    pb2led: Led,
                    button0: Button,
                    button1: Button,
                    switch0: Switch,
                    switch1: Switch,
                    switch2: Switch,
                    switch3: Switch,
                    switch4: Switch,
                    switch5: Switch,
                    switch6: Switch,
                    switch7: Switch,
                    clocks: Clocks,
                }
            }
        }
    };
}

impl_ext!(super::pac::FPGAIO);
impl_ext!(super::pac::FPGAIO_SECURE);