1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
use crate::mmio; use bit_field::BitField; const BANK_0_MODE: u8 = 0x00; const BANK_0_DATA: u8 = 0x01; const BANK_0_INTR_EN: u8 = 0x02; const BANK_0_INTR_MODE: u8 = 0x03; const BANK_0_INTR_TRIG: u8 = 0x04; const BANK_0_INTR_ACK: u8 = 0x05; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum PinMode { Input, Output, } #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum IntrMode { RisingEdge, FallingEdge, } #[repr(transparent)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub struct IoPin(pub u32); impl IoPin { pub fn get_mode(&self) -> PinMode { assert!(self.0 < 32); let is_input = unsafe { mmio::read(BANK_0_MODE) }.get_bit(self.0 as _); if is_input { PinMode::Input } else { PinMode::Output } } pub fn set_mode(&self, mode: PinMode) { assert!(self.0 < 32); let mut bank = unsafe { mmio::read(BANK_0_MODE) }; bank.set_bit(self.0 as _, match mode { PinMode::Input => true, PinMode::Output => false, }); unsafe { mmio::write(BANK_0_MODE, bank); } } pub fn read(&self) -> bool { assert!(self.0 < 32); unsafe { mmio::read(BANK_0_DATA) }.get_bit(self.0 as _) } pub fn write(&self, value: bool) { assert!(self.0 < 32); let mut bank = unsafe { mmio::read(BANK_0_DATA) }; bank.set_bit(self.0 as _, value); unsafe { mmio::write(BANK_0_DATA, bank); } } pub fn enable_interrupt(&self, mode: IntrMode) { let mut bank = unsafe { mmio::read(BANK_0_INTR_MODE) }; let mode_bit = match mode { IntrMode::RisingEdge => false, IntrMode::FallingEdge => true, }; bank.set_bit(self.0 as _, mode_bit); unsafe { mmio::write(BANK_0_INTR_MODE, bank); } let mut bank = unsafe { mmio::read(BANK_0_INTR_EN) }; bank.set_bit(self.0 as _, true); unsafe { mmio::write(BANK_0_INTR_EN, bank); } } pub fn disable_interrupt(&self) { let mut bank = unsafe { mmio::read(BANK_0_INTR_EN) }; bank.set_bit(self.0 as _, false); unsafe { mmio::write(BANK_0_INTR_EN, bank); } } pub fn ack_interrupt(&self) { unsafe { mmio::write(BANK_0_INTR_ACK, (1 << self.0)); } } } pub fn first_interrupt_pin() -> Option<IoPin> { let bank = unsafe { mmio::read(BANK_0_INTR_TRIG) }; for i in 0..32u32 { if bank.get_bit(i as usize) { return Some(IoPin(i)); } } None }