Better buttons and LEDs API
diff --git a/src/buttons.rs b/src/buttons.rs
index 9bcc2f0..5787f83 100644
--- a/src/buttons.rs
+++ b/src/buttons.rs
@@ -1,5 +1,6 @@
use crate::callback::CallbackSubscription;
-use crate::callback::SubscribableCallback;
+use crate::callback::Consumer;
+use crate::result::OtherError;
use crate::result::TockResult;
use crate::syscalls;
use core::marker::PhantomData;
@@ -18,50 +19,92 @@
}
#[non_exhaustive]
-pub struct ButtonDriver;
+pub struct ButtonsDriverFactory;
-impl ButtonDriver {
- pub fn with_callback<CB>(self, callback: CB) -> WithCallback<CB> {
- WithCallback { callback }
- }
-}
-
-pub struct WithCallback<CB> {
- callback: CB,
-}
-
-impl<CB: FnMut(usize, ButtonState)> SubscribableCallback for WithCallback<CB> {
- fn call_rust(&mut self, button_num: usize, state: usize, _: usize) {
- (self.callback)(button_num, state.into());
- }
-}
-
-impl<CB: FnMut(usize, ButtonState)> WithCallback<CB> {
- pub fn init(&mut self) -> TockResult<Buttons> {
- let buttons = Buttons {
- count: syscalls::command(DRIVER_NUMBER, command_nr::COUNT, 0, 0)?,
- subscription: syscalls::subscribe_cb(
- DRIVER_NUMBER,
- subscribe_nr::SUBSCRIBE_CALLBACK,
- self,
- )?,
+impl ButtonsDriverFactory {
+ pub fn init_driver(&mut self) -> TockResult<ButtonsDriver> {
+ let buttons_driver = ButtonsDriver {
+ num_buttons: syscalls::command(DRIVER_NUMBER, command_nr::COUNT, 0, 0)?,
+ lifetime: PhantomData,
};
- Ok(buttons)
+ Ok(buttons_driver)
+ }
+}
+
+pub struct ButtonsDriver<'a> {
+ num_buttons: usize,
+ lifetime: PhantomData<&'a ()>,
+}
+
+impl<'a> ButtonsDriver<'a> {
+ pub fn num_buttons(&self) -> usize {
+ self.num_buttons
+ }
+
+ pub fn get(&self, button_num: usize) -> Option<Button> {
+ if button_num < self.num_buttons {
+ Some(Button {
+ button_num,
+ lifetime: PhantomData,
+ })
+ } else {
+ None
+ }
+ }
+
+ pub fn buttons(&self) -> Buttons {
+ Buttons {
+ num_buttons: self.num_buttons,
+ curr_button: 0,
+ lifetime: PhantomData,
+ }
+ }
+
+ pub fn subscribe<CB: Fn(usize, ButtonState)>(
+ &self,
+ callback: &'a mut CB,
+ ) -> TockResult<CallbackSubscription> {
+ syscalls::subscribe::<ButtonsEventConsumer, _>(
+ DRIVER_NUMBER,
+ subscribe_nr::SUBSCRIBE_CALLBACK,
+ callback,
+ )
+ .map_err(Into::into)
+ }
+}
+
+struct ButtonsEventConsumer;
+
+impl<CB: Fn(usize, ButtonState)> Consumer<CB> for ButtonsEventConsumer {
+ fn consume(callback: &mut CB, button_num: usize, button_state: usize, _: usize) {
+ let button_state = match button_state {
+ 0 => ButtonState::Released,
+ 1 => ButtonState::Pressed,
+ _ => return,
+ };
+ callback(button_num, button_state);
}
}
pub struct Buttons<'a> {
- count: usize,
- #[allow(dead_code)] // Used in drop
- subscription: CallbackSubscription<'a>,
+ num_buttons: usize,
+ curr_button: usize,
+ lifetime: PhantomData<&'a ()>,
}
-impl<'a> Buttons<'a> {
- pub fn iter_mut(&mut self) -> ButtonIter {
- ButtonIter {
- curr_button: 0,
- button_count: self.count,
- _lifetime: Default::default(),
+impl<'a> Iterator for Buttons<'a> {
+ type Item = Button<'a>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.curr_button < self.num_buttons {
+ let item = Button {
+ button_num: self.curr_button,
+ lifetime: PhantomData,
+ };
+ self.curr_button += 1;
+ Some(item)
+ } else {
+ None
}
}
}
@@ -72,65 +115,45 @@
Released,
}
-impl From<usize> for ButtonState {
- fn from(state: usize) -> ButtonState {
- match state {
- 0 => ButtonState::Released,
- 1 => ButtonState::Pressed,
- _ => unreachable!(),
+impl From<ButtonState> for bool {
+ fn from(button_state: ButtonState) -> Self {
+ match button_state {
+ ButtonState::Released => false,
+ ButtonState::Pressed => true,
}
}
}
-impl<'a, 'b> IntoIterator for &'b mut Buttons<'a> {
- type Item = ButtonHandle<'b>;
- type IntoIter = ButtonIter<'b>;
-
- fn into_iter(self) -> Self::IntoIter {
- self.iter_mut()
- }
-}
-
-pub struct ButtonIter<'a> {
- curr_button: usize,
- button_count: usize,
- _lifetime: PhantomData<&'a ()>,
-}
-
-impl<'a> Iterator for ButtonIter<'a> {
- type Item = ButtonHandle<'a>;
-
- fn next(&mut self) -> Option<Self::Item> {
- if self.curr_button < self.button_count {
- let item = ButtonHandle {
- button_num: self.curr_button,
- _lifetime: Default::default(),
- };
- self.curr_button += 1;
- Some(item)
- } else {
- None
- }
- }
-}
-
-pub struct ButtonHandle<'a> {
+pub struct Button<'a> {
button_num: usize,
- _lifetime: PhantomData<&'a ()>,
+ lifetime: PhantomData<&'a ()>,
}
-impl<'a> ButtonHandle<'a> {
- pub fn enable(&mut self) -> TockResult<Button> {
+impl<'a> Button<'a> {
+ pub fn button_num(&self) -> usize {
+ self.button_num
+ }
+
+ pub fn read(&self) -> TockResult<ButtonState> {
+ let button_state = syscalls::command(DRIVER_NUMBER, command_nr::READ, self.button_num, 0)?;
+ match button_state {
+ 0 => Ok(ButtonState::Released),
+ 1 => Ok(ButtonState::Pressed),
+ _ => Err(OtherError::ButtonsDriverInvalidState.into()),
+ }
+ }
+
+ pub fn enable_interrupt(&self) -> TockResult<()> {
syscalls::command(
DRIVER_NUMBER,
command_nr::ENABLE_INTERRUPT,
self.button_num,
0,
)?;
- Ok(Button { handle: self })
+ Ok(())
}
- pub fn disable(&mut self) -> TockResult<()> {
+ pub fn disable_interrupt(&self) -> TockResult<()> {
syscalls::command(
DRIVER_NUMBER,
command_nr::DISABLE_INTERRUPT,
@@ -140,15 +163,3 @@
Ok(())
}
}
-
-pub struct Button<'a> {
- handle: &'a ButtonHandle<'a>,
-}
-
-impl<'a> Button<'a> {
- pub fn read(&self) -> TockResult<ButtonState> {
- syscalls::command(DRIVER_NUMBER, command_nr::READ, self.handle.button_num, 0)
- .map(ButtonState::from)
- .map_err(Into::into)
- }
-}