blob: aac5cb2241ad41400c89549b47405680aa7f4307 [file] [log] [blame]
Woyten30fc95b2019-01-10 21:09:46 +01001use crate::callback::CallbackSubscription;
Woyten70c09f92019-12-01 15:17:32 +01002use crate::callback::Consumer;
3use crate::result::OtherError;
Woytene22bc2b2020-01-17 14:12:47 +01004use crate::result::OutOfRangeError;
Woyten30fc95b2019-01-10 21:09:46 +01005use crate::result::TockResult;
Woyten30fc95b2019-01-10 21:09:46 +01006use crate::syscalls;
Woyten6cf210a2019-11-15 21:18:35 +01007use core::marker::PhantomData;
Woyten7037cf72018-01-05 12:49:17 +01008
Woyten9567d792018-02-04 00:11:39 +01009const DRIVER_NUMBER: usize = 0x00003;
Woyten7037cf72018-01-05 12:49:17 +010010
11mod command_nr {
Woyten9567d792018-02-04 00:11:39 +010012 pub const COUNT: usize = 0;
13 pub const ENABLE_INTERRUPT: usize = 1;
14 pub const DISABLE_INTERRUPT: usize = 2;
15 pub const READ: usize = 3;
Woytena59a7e22018-01-11 22:48:31 +010016}
17
18mod subscribe_nr {
Woyten9567d792018-02-04 00:11:39 +010019 pub const SUBSCRIBE_CALLBACK: usize = 0;
20}
21
torfmaster97c5e722020-01-02 21:30:16 +010022#[non_exhaustive]
Woyten70c09f92019-12-01 15:17:32 +010023pub struct ButtonsDriverFactory;
torfmasterd721a442019-12-27 17:42:42 +010024
Woyten70c09f92019-12-01 15:17:32 +010025impl ButtonsDriverFactory {
26 pub fn init_driver(&mut self) -> TockResult<ButtonsDriver> {
27 let buttons_driver = ButtonsDriver {
28 num_buttons: syscalls::command(DRIVER_NUMBER, command_nr::COUNT, 0, 0)?,
29 lifetime: PhantomData,
Woyten22bc2542019-11-15 23:18:40 +010030 };
Woyten70c09f92019-12-01 15:17:32 +010031 Ok(buttons_driver)
32 }
33}
34
35pub struct ButtonsDriver<'a> {
36 num_buttons: usize,
37 lifetime: PhantomData<&'a ()>,
38}
39
40impl<'a> ButtonsDriver<'a> {
41 pub fn num_buttons(&self) -> usize {
42 self.num_buttons
43 }
44
Woytene22bc2b2020-01-17 14:12:47 +010045 /// Returns the button at 0-based index `button_num`
46 pub fn get(&self, button_num: usize) -> Result<Button, OutOfRangeError> {
Woyten70c09f92019-12-01 15:17:32 +010047 if button_num < self.num_buttons {
Woytene22bc2b2020-01-17 14:12:47 +010048 Ok(Button {
Woyten70c09f92019-12-01 15:17:32 +010049 button_num,
50 lifetime: PhantomData,
51 })
52 } else {
Woytene22bc2b2020-01-17 14:12:47 +010053 Err(OutOfRangeError)
Woyten70c09f92019-12-01 15:17:32 +010054 }
55 }
56
57 pub fn buttons(&self) -> Buttons {
58 Buttons {
59 num_buttons: self.num_buttons,
60 curr_button: 0,
61 lifetime: PhantomData,
62 }
63 }
64
65 pub fn subscribe<CB: Fn(usize, ButtonState)>(
66 &self,
67 callback: &'a mut CB,
68 ) -> TockResult<CallbackSubscription> {
69 syscalls::subscribe::<ButtonsEventConsumer, _>(
70 DRIVER_NUMBER,
71 subscribe_nr::SUBSCRIBE_CALLBACK,
72 callback,
73 )
74 .map_err(Into::into)
75 }
76}
77
78struct ButtonsEventConsumer;
79
80impl<CB: Fn(usize, ButtonState)> Consumer<CB> for ButtonsEventConsumer {
81 fn consume(callback: &mut CB, button_num: usize, button_state: usize, _: usize) {
82 let button_state = match button_state {
83 0 => ButtonState::Released,
84 1 => ButtonState::Pressed,
85 _ => return,
86 };
87 callback(button_num, button_state);
Woyten9567d792018-02-04 00:11:39 +010088 }
Woyten7037cf72018-01-05 12:49:17 +010089}
90
Woyten0833a042018-04-03 19:29:34 +020091pub struct Buttons<'a> {
Woyten70c09f92019-12-01 15:17:32 +010092 num_buttons: usize,
93 curr_button: usize,
94 lifetime: PhantomData<&'a ()>,
Philipp Vollmer617c0802018-01-07 12:09:31 +010095}
96
Woyten70c09f92019-12-01 15:17:32 +010097impl<'a> Iterator for Buttons<'a> {
98 type Item = Button<'a>;
99
100 fn next(&mut self) -> Option<Self::Item> {
101 if self.curr_button < self.num_buttons {
102 let item = Button {
103 button_num: self.curr_button,
104 lifetime: PhantomData,
105 };
106 self.curr_button += 1;
107 Some(item)
108 } else {
109 None
Woytend81a0c62018-01-19 21:44:38 +0100110 }
111 }
Woytena59a7e22018-01-11 22:48:31 +0100112}
Philipp Vollmer617c0802018-01-07 12:09:31 +0100113
Woytenee5de052019-11-12 14:15:22 +0100114#[derive(Copy, Clone, Debug, Eq, PartialEq)]
Woytena59a7e22018-01-11 22:48:31 +0100115pub enum ButtonState {
116 Pressed,
117 Released,
118}
119
Woyten70c09f92019-12-01 15:17:32 +0100120impl From<ButtonState> for bool {
121 fn from(button_state: ButtonState) -> Self {
122 match button_state {
123 ButtonState::Released => false,
124 ButtonState::Pressed => true,
Woytena59a7e22018-01-11 22:48:31 +0100125 }
126 }
127}
128
Woyten70c09f92019-12-01 15:17:32 +0100129pub struct Button<'a> {
Woytena59a7e22018-01-11 22:48:31 +0100130 button_num: usize,
Woyten70c09f92019-12-01 15:17:32 +0100131 lifetime: PhantomData<&'a ()>,
Woytena59a7e22018-01-11 22:48:31 +0100132}
133
Woyten70c09f92019-12-01 15:17:32 +0100134impl<'a> Button<'a> {
135 pub fn button_num(&self) -> usize {
136 self.button_num
137 }
138
139 pub fn read(&self) -> TockResult<ButtonState> {
140 let button_state = syscalls::command(DRIVER_NUMBER, command_nr::READ, self.button_num, 0)?;
141 match button_state {
142 0 => Ok(ButtonState::Released),
143 1 => Ok(ButtonState::Pressed),
144 _ => Err(OtherError::ButtonsDriverInvalidState.into()),
145 }
146 }
147
148 pub fn enable_interrupt(&self) -> TockResult<()> {
Woyten22bc2542019-11-15 23:18:40 +0100149 syscalls::command(
Woyten4f5bc412019-11-21 23:36:58 +0100150 DRIVER_NUMBER,
151 command_nr::ENABLE_INTERRUPT,
152 self.button_num,
153 0,
Woyten22bc2542019-11-15 23:18:40 +0100154 )?;
Woyten70c09f92019-12-01 15:17:32 +0100155 Ok(())
Woytena59a7e22018-01-11 22:48:31 +0100156 }
157
Woyten70c09f92019-12-01 15:17:32 +0100158 pub fn disable_interrupt(&self) -> TockResult<()> {
Woyten22bc2542019-11-15 23:18:40 +0100159 syscalls::command(
Woyten4f5bc412019-11-21 23:36:58 +0100160 DRIVER_NUMBER,
161 command_nr::DISABLE_INTERRUPT,
162 self.button_num,
163 0,
Woyten22bc2542019-11-15 23:18:40 +0100164 )?;
165 Ok(())
Woytena59a7e22018-01-11 22:48:31 +0100166 }
167}