Add gpio to drivers singleton
diff --git a/src/electronics/shift_register.rs b/src/electronics/shift_register.rs
index f170225..10eac0d 100644
--- a/src/electronics/shift_register.rs
+++ b/src/electronics/shift_register.rs
@@ -1,18 +1,18 @@
use crate::gpio::GpioPinWrite;
use crate::result::TockResult;
-pub struct ShiftRegister {
- data_pin: GpioPinWrite,
- clock_pin: GpioPinWrite,
- latch_pin: GpioPinWrite,
+pub struct ShiftRegister<'a> {
+ data_pin: GpioPinWrite<'a>,
+ clock_pin: GpioPinWrite<'a>,
+ latch_pin: GpioPinWrite<'a>,
}
-impl ShiftRegister {
+impl<'a> ShiftRegister<'a> {
pub fn new(
- data_pin: GpioPinWrite,
- clock_pin: GpioPinWrite,
- latch_pin: GpioPinWrite,
- ) -> ShiftRegister {
+ data_pin: GpioPinWrite<'a>,
+ clock_pin: GpioPinWrite<'a>,
+ latch_pin: GpioPinWrite<'a>,
+ ) -> ShiftRegister<'a> {
ShiftRegister {
data_pin,
clock_pin,
@@ -20,14 +20,14 @@
}
}
- pub fn write_bits(&self, values: &[bool]) -> TockResult<()> {
+ pub fn write_bits(&mut self, values: &[bool]) -> TockResult<()> {
for i in values {
self.push_bit(*i)?;
}
self.display()
}
- fn push_bit(&self, value: bool) -> TockResult<()> {
+ fn push_bit(&mut self, value: bool) -> TockResult<()> {
if value {
self.data_pin.set_high()
} else {
@@ -37,7 +37,7 @@
self.clock_pin.set_low()
}
- fn display(&self) -> TockResult<()> {
+ fn display(&mut self) -> TockResult<()> {
self.latch_pin.set_high()?;
self.latch_pin.set_low()
}
diff --git a/src/gpio.rs b/src/gpio.rs
index d416632..e8e0373 100644
--- a/src/gpio.rs
+++ b/src/gpio.rs
@@ -1,9 +1,12 @@
+use crate::result::OtherError;
+use crate::result::TockError;
use crate::result::TockResult;
use crate::syscalls;
+use core::marker::PhantomData;
const DRIVER_NUMBER: usize = 0x00004;
-mod gpio_commands {
- pub const SUBSCRIBE_CALLBACK: usize = 0;
+mod command_nr {
+ pub const NUMBER_PINS: usize = 0;
pub const ENABLE_OUTPUT: usize = 1;
pub const SET_HIGH: usize = 2;
pub const SET_LOW: usize = 3;
@@ -15,6 +18,65 @@
pub const DISABLE: usize = 9;
}
+mod subscribe_nr {
+ pub const SUBSCRIBE_CALLBACK: usize = 0;
+}
+
+pub struct GpioDriver {
+ pub(crate) _unconstructible: (),
+}
+
+impl GpioDriver {
+ pub fn all_pins<'a>(&'a mut self) -> TockResult<GpioIter<'a>> {
+ let number = self.number_of_pins()?;
+ Ok(GpioIter {
+ curr_gpio: 0,
+ gpio_count: number,
+ phantom: PhantomData,
+ })
+ }
+
+ pub fn pin<'a>(&'a mut self, pin: usize) -> TockResult<GpioPinUnitialized<'a>> {
+ let number = self.number_of_pins()?;
+ if pin < number {
+ Ok(GpioPinUnitialized {
+ number: pin,
+ phantom: PhantomData,
+ })
+ } else {
+ Err(TockError::Other(OtherError::NotEnoughGpioPins))
+ }
+ }
+
+ fn number_of_pins(&self) -> TockResult<usize> {
+ syscalls::command(DRIVER_NUMBER, command_nr::NUMBER_PINS, 0, 0).map_err(Into::into)
+ }
+}
+
+#[derive(Copy, Clone)]
+pub struct GpioIter<'a> {
+ curr_gpio: usize,
+ gpio_count: usize,
+ phantom: PhantomData<&'a mut ()>,
+}
+
+impl<'a> Iterator for GpioIter<'a> {
+ type Item = GpioPinUnitialized<'a>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.curr_gpio < self.gpio_count {
+ let item = GpioPinUnitialized {
+ number: self.curr_gpio,
+ phantom: PhantomData,
+ };
+ self.curr_gpio += 1;
+ Some(item)
+ } else {
+ None
+ }
+ }
+}
+
pub enum InputMode {
PullUp,
PullDown,
@@ -47,27 +109,34 @@
}
}
-pub struct GpioPinUnitialized {
+pub struct GpioPinUnitialized<'a> {
number: usize,
+ phantom: PhantomData<&'a mut ()>,
}
-pub struct GpioPinWrite {
+pub struct GpioPinWrite<'a> {
number: usize,
+ phantom: PhantomData<&'a mut ()>,
}
-pub struct GpioPinRead {
+pub struct GpioPinRead<'a> {
number: usize,
+ phantom: PhantomData<&'a mut ()>,
}
-impl GpioPinUnitialized {
- pub fn new(number: usize) -> GpioPinUnitialized {
- GpioPinUnitialized { number }
+impl<'a> GpioPinUnitialized<'a> {
+ pub fn new(number: usize) -> GpioPinUnitialized<'a> {
+ GpioPinUnitialized {
+ number,
+ phantom: PhantomData,
+ }
}
- pub fn open_for_write(self) -> TockResult<GpioPinWrite> {
- syscalls::command(DRIVER_NUMBER, gpio_commands::ENABLE_OUTPUT, self.number, 0)?;
+ pub fn open_for_write(self) -> TockResult<GpioPinWrite<'a>> {
+ syscalls::command(DRIVER_NUMBER, command_nr::ENABLE_OUTPUT, self.number, 0)?;
Ok(GpioPinWrite {
number: self.number,
+ phantom: PhantomData,
})
}
@@ -75,85 +144,81 @@
self,
callback: Option<(extern "C" fn(usize, usize, usize, usize), IrqMode)>,
input_mode: InputMode,
- ) -> TockResult<GpioPinRead> {
+ ) -> TockResult<GpioPinRead<'a>> {
let (callback, irq_mode) = callback.unwrap_or((noop_callback, IrqMode::EitherEdge));
self.enable_input(input_mode)
.and_then(|pin| pin.subscribe_callback(callback))
- .and_then(|pin| pin.enable_callback(irq_mode))
+ .and_then(move |pin| pin.enable_callback(irq_mode))
}
fn subscribe_callback(
self,
callback: extern "C" fn(usize, usize, usize, usize),
- ) -> TockResult<GpioPinUnitialized> {
+ ) -> TockResult<GpioPinUnitialized<'a>> {
syscalls::subscribe_fn(
DRIVER_NUMBER,
- gpio_commands::SUBSCRIBE_CALLBACK,
+ subscribe_nr::SUBSCRIBE_CALLBACK,
callback,
self.number,
)?;
Ok(self)
}
- fn enable_input(self, mode: InputMode) -> TockResult<GpioPinUnitialized> {
+ fn enable_input(self, mode: InputMode) -> TockResult<GpioPinUnitialized<'a>> {
syscalls::command(
DRIVER_NUMBER,
- gpio_commands::ENABLE_INPUT,
+ command_nr::ENABLE_INPUT,
self.number,
mode.to_num(),
)?;
Ok(self)
}
- fn enable_callback(self, irq_mode: IrqMode) -> TockResult<GpioPinRead> {
+ fn enable_callback(self, irq_mode: IrqMode) -> TockResult<GpioPinRead<'a>> {
syscalls::command(
DRIVER_NUMBER,
- gpio_commands::ENABLE_INTERRUPT,
+ command_nr::ENABLE_INTERRUPT,
self.number,
irq_mode.to_num(),
)?;
Ok(GpioPinRead {
number: self.number,
+ phantom: PhantomData,
})
}
}
-impl GpioPinWrite {
- pub fn set_low(&self) -> TockResult<()> {
- syscalls::command(DRIVER_NUMBER, gpio_commands::SET_LOW, self.number, 0)?;
+impl<'a> GpioPinWrite<'a> {
+ pub fn set_low(&mut self) -> TockResult<()> {
+ syscalls::command(DRIVER_NUMBER, command_nr::SET_LOW, self.number, 0)?;
Ok(())
}
- pub fn set_high(&self) -> TockResult<()> {
- syscalls::command(DRIVER_NUMBER, gpio_commands::SET_HIGH, self.number, 0)?;
+ pub fn set_high(&mut self) -> TockResult<()> {
+ syscalls::command(DRIVER_NUMBER, command_nr::SET_HIGH, self.number, 0)?;
Ok(())
}
- pub fn toggle(&self) -> TockResult<()> {
- syscalls::command(DRIVER_NUMBER, gpio_commands::TOGGLE, self.number, 0)?;
+ pub fn toggle(&mut self) -> TockResult<()> {
+ syscalls::command(DRIVER_NUMBER, command_nr::TOGGLE, self.number, 0)?;
Ok(())
}
}
-impl GpioPinRead {
- pub fn read(&self) -> bool {
- syscalls::command(DRIVER_NUMBER, gpio_commands::READ, self.number, 0).ok() == Some(1)
+impl<'a> GpioPinRead<'a> {
+ pub fn read(&'a self) -> bool {
+ syscalls::command(DRIVER_NUMBER, command_nr::READ, self.number, 0).ok() == Some(1)
}
}
-impl Drop for GpioPinWrite {
+impl<'a> Drop for GpioPinWrite<'a> {
fn drop(&mut self) {
- let _ = syscalls::command(DRIVER_NUMBER, gpio_commands::DISABLE, self.number, 0);
+ let _ = syscalls::command(DRIVER_NUMBER, command_nr::DISABLE, self.number, 0);
}
}
-impl Drop for GpioPinRead {
+impl<'a> Drop for GpioPinRead<'a> {
fn drop(&mut self) {
- let _ = syscalls::command(
- DRIVER_NUMBER,
- gpio_commands::DISABLE_INTERRUPT,
- self.number,
- 0,
- );
- let _ = syscalls::command(DRIVER_NUMBER, gpio_commands::DISABLE, self.number, 0);
+ let _ = syscalls::command(DRIVER_NUMBER, command_nr::DISABLE_INTERRUPT, self.number, 0);
+ let _ = syscalls::command(DRIVER_NUMBER, command_nr::DISABLE, self.number, 0);
}
}
diff --git a/src/hardware.rs b/src/hardware.rs
index 6e8b84d..bd9a87d 100644
--- a/src/hardware.rs
+++ b/src/hardware.rs
@@ -1,4 +1,5 @@
use crate::console::ConsoleDriver;
+use crate::gpio::GpioDriver;
use crate::led::LedDriver;
use crate::result::OtherError;
use crate::result::TockError;
@@ -11,6 +12,7 @@
pub console_driver: ConsoleDriver,
pub led_driver: LedDriver,
pub timer_context: DriverContext,
+ pub gpio_driver: GpioDriver,
}
/// Retrieve Hardware struct. Returns Hardware only once.
@@ -42,6 +44,9 @@
timer_context: DriverContext {
active_timer: Cell::new(None),
},
+ gpio_driver: GpioDriver {
+ _unconstructible: (),
+ },
};
static mut HARDWARE_SINGLETON: Option<Hardware> = Some(HARDWARE);
diff --git a/src/led.rs b/src/led.rs
index ded7d01..ae2a2d4 100644
--- a/src/led.rs
+++ b/src/led.rs
@@ -81,7 +81,7 @@
pub struct LedIter<'a> {
curr_led: usize,
led_count: usize,
- phantom: PhantomData<&'a ()>,
+ phantom: PhantomData<&'a mut ()>,
}
impl<'a> Iterator for LedIter<'a> {
diff --git a/src/result.rs b/src/result.rs
index 4eaec21..f3929ca 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -70,6 +70,7 @@
TimerDriverDurationOutOfRange,
TimerDriverErroneousClockFrequency,
DriverAlreadyTaken,
+ NotEnoughGpioPins,
}
impl From<OtherError> for TockError {