diff --git a/src/io/mod.rs b/src/io/mod.rs deleted file mode 100644 index 5d359f0..0000000 --- a/src/io/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod port; - -pub const PORT_B: port::Port = port::Port::new(); -pub const PORT_C: port::Port = port::Port::new(); -pub const PORT_D: port::Port = port::Port::new(); diff --git a/src/io/port.rs b/src/io/port.rs deleted file mode 100644 index 73c8ee0..0000000 --- a/src/io/port.rs +++ /dev/null @@ -1,183 +0,0 @@ -use core::prelude::v1::*; -use core::ptr::{read_volatile, write_volatile}; -use core::marker::PhantomData; - -use Bit; - -pub trait Information { - const DDR: *mut u8; - const IO: *mut u8; - const PIN: *mut u8; -} - -#[derive(Copy, Clone)] -pub struct B; - -impl Information for B { - const DDR: *mut u8 = ::DDRB; - const IO: *mut u8 = ::PORTB; - const PIN: *mut u8 = ::PINB; -} - -#[derive(Copy, Clone)] -pub struct C; - -impl Information for C { - const DDR: *mut u8 = ::DDRC; - const IO: *mut u8 = ::PORTC; - const PIN: *mut u8 = ::PINC; -} - -#[derive(Copy, Clone)] -pub struct D; - -impl Information for D { - const DDR: *mut u8 = ::DDRD; - const IO: *mut u8 = ::PORTD; - const PIN: *mut u8 = ::PIND; -} - -#[derive(Copy, Clone)] -enum Direction { - Output, - Input, -} - -const BITS_IN_BYTE: usize = 8; - -pub struct Configuration { - _port: PhantomData

, - direction: [Option; BITS_IN_BYTE], - pullup: [Option; BITS_IN_BYTE], -} - -impl

Configuration

- where - P: Information -{ - #[inline] - pub fn new() -> Configuration

{ - Configuration { - _port: PhantomData, - direction: Default::default(), - pullup: Default::default(), - } - } - - #[inline] - pub fn set_all_as_output(&mut self) -> &mut Self { - self.direction = [Some(Direction::Output); 8]; - self - } - - #[inline] - pub fn set_all_as_input(&mut self) -> &mut Self { - self.direction = [Some(Direction::Input); 8]; - self - } - - #[inline] - pub fn set_as_output(&mut self, bit: Bit) -> &mut Self { - self.direction[bit as usize] = Some(Direction::Output); - self - } - - #[inline] - pub fn set_as_input(&mut self, bit: Bit) -> &mut Self { - self.direction[bit as usize] = Some(Direction::Input); - self - } - - #[inline] - pub fn enable_pullup(&mut self, bit: Bit) -> &mut Self { - self.pullup[bit as usize] = Some(true); - self - } - - #[inline] - pub fn disable_pullup(&mut self, bit: Bit) -> &mut Self { - self.pullup[bit as usize] = Some(false); - self - } - - #[inline] - pub fn configure(&self) { - // FIXME: Both of these loops are wasteful if we are - // setting all 8 bits, when we could set the entire IO - // register at once. Is there a way we can track that? - - // We use `zip` instead of `enumerate` to guarantee it's a constant - - for (&p, i) in self.direction.iter().zip(0..BITS_IN_BYTE) { - if let Some(enabled) = p { - if let Direction::Output = enabled { - unsafe { asm!("sbi $0 $1" : : "n"(P::DDR), "n"(i)) } - } else { - unsafe { asm!("cbi $0 $1; A" : : "n"(P::DDR), "n"(i)) } - } - } - } - - for (&p, i) in self.pullup.iter().zip(0..BITS_IN_BYTE) { - if let Some(enabled) = p { - if enabled { - unsafe { asm!("sbi $0 $1" : : "n"(P::IO), "n"(i)) } - } else { - unsafe { asm!("cbi $0 $1; B" : : "n"(P::IO), "n"(i)) } - } - } - } - } -} - -#[derive(Copy, Clone)] -pub struct Data { - _port: PhantomData

, -} - -impl

Data

- where - P: Information -{ - #[inline] - pub fn new() -> Data

{ Data { _port: PhantomData } } - - #[inline] - pub fn get(&self) -> u8 { - unsafe { read_volatile(P::PIN) } - } - - #[inline] - pub fn set(&self, value: u8) { - unsafe { write_volatile(P::IO, value) }; - } - - #[inline] - pub fn bit_is_set(&self, bit: Bit) -> bool { - bit.is_set(self.get()) - } - - #[inline] - pub fn set_bit(&self, bit: Bit) { - unsafe { asm!("sbi $0 $1" : : "n"(P::IO), "n"(bit as u8)) } - } - - #[inline] - pub fn clear_bit(&self, bit: Bit) { - unsafe { asm!("cbi $0 $1; C" : : "n"(P::IO), "n"(bit as u8)) } - } - - #[inline] - pub fn toggle_bit(&self, bit: Bit) { - unsafe { asm!("sbi $0 $1" : : "n"(P::PIN), "n"(bit as u8)) } - } -} - -#[derive(Copy, Clone)] -pub struct Port

(PhantomData

); - -impl Port

{ - pub(crate) const fn new() -> Port

{ Port(PhantomData) } - pub fn configuration(&self) -> Configuration

{ Configuration::new() } - pub fn data(&self) -> Data

{ Data::new() } -} diff --git a/src/lib.rs b/src/lib.rs index b4e5948..08a1c3f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,43 +8,10 @@ extern crate core; -// Look like we have a standard library -#[allow(unused_imports)] -use core::{option, iter, fmt, ops, clone, marker}; - pub mod prelude; pub mod timer0; pub mod timer1; pub mod serial; -pub mod io; - -#[derive(Copy, Clone)] -pub enum Bit { - Bit0 = 0, - Bit1 = 1, - Bit2 = 2, - Bit3 = 3, - Bit4 = 4, - Bit5 = 5, - Bit6 = 6, - Bit7 = 7, -} - -impl Bit { - fn as_mask(&self) -> u8 { 1 << *self as u8 } - - pub fn is_set(&self, value: u8) -> bool { - (value & self.as_mask()) != 0 - } - - pub fn set(&self, value: u8) -> u8 { - value | self.as_mask() - } - - pub fn unset(&self, value: u8) -> u8 { - value & !self.as_mask() - } -} macro_rules! bit { (-, $pos:expr) => {}; diff --git a/src/prelude.rs b/src/prelude.rs index 8592448..8895d93 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,8 +1,6 @@ use core::prelude::v1::*; use core::marker::PhantomData; -pub use io::{PORT_B, PORT_C, PORT_D}; - pub struct DisableInterrupts(PhantomData<()>); impl DisableInterrupts {