avr-simulator 0.6.3

Oxidized interface for simavr
Documentation
use super::*;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct Port {
    port: u8,
    ddr: u8,
}

impl Port {
    fn get(avr: &mut Avr, port: char) -> Self {
        let mut state = ffi::avr_ioport_state_t {
            _bitfield_align_1: Default::default(),
            _bitfield_1: Default::default(),
            __bindgen_padding_0: Default::default(),
        };

        // Safety: `IoCtl::IoPortGetState` requires parameter of type
        // `avr_ioport_state_t`, which is the case here
        let status =
            unsafe { avr.ioctl(IoCtl::IoPortGetState { port }, &mut state) };

        if status == -1 {
            panic!("Current AVR doesn't have port P{}", port);
        }

        Port {
            port: state.port() as u8,
            ddr: state.ddr() as u8,
        }
    }
}

pub struct Pin;

impl Pin {
    pub fn set(avr: &Avr, port: char, pin: u8, high: bool) {
        let irq = avr
            .try_io_getirq(IoCtl::IoPortGetIrq { port }, pin as u32)
            .unwrap_or_else(|| {
                panic!("Current AVR doesn't have pin P{}{}", port, pin)
            });

        // Safety: `IoPortGetIrq` can be raised with a zero or one
        unsafe {
            ffi::avr_raise_irq(irq.as_ptr(), if high { 1 } else { 0 });
        }
    }

    pub fn get(avr: &mut Avr, port: char, pin: u8) -> bool {
        Port::get(avr, port).port & (1 << pin) > 0
    }

    pub fn get_mode(avr: &mut Avr, port: char, pin: u8) -> PinMode {
        if Port::get(avr, port).ddr & (1 << pin) == 0 {
            PinMode::Input
        } else {
            PinMode::Output
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub enum PinMode {
    Input,
    Output,
}

impl PinMode {
    pub fn is_input(&self) -> bool {
        *self == Self::Input
    }

    pub fn is_output(&self) -> bool {
        *self == Self::Output
    }
}