edgebadge/
buttons.rs

1use super::hal;
2
3use cortex_m::asm::delay as cycle_delay;
4use gpio::{Floating, Input, Output, PushPull};
5use hal::gpio::{self, *};
6use hal::prelude::*;
7
8#[derive(Debug, PartialEq)]
9pub enum Keys {
10    SelectDown,
11    SelectUp,
12    StartDown,
13    StartUp,
14    BDown,
15    BUp,
16    ADown,
17    AUp,
18
19    UpUp,
20    UpDown,
21    DownUp,
22    DownDown,
23    LeftUp,
24    LeftDown,
25    RightUp,
26    RightDown,
27}
28
29pub struct ButtonIter {
30    pub pressed: u8,
31    pub released: u8,
32    pub bit_index: u8,
33}
34
35//should be impossible for released and pressed, but gives released preference
36fn mask_to_event(mask: u8, released: u8, pressed: u8) -> Option<Keys> {
37    let pressed_bool = mask & pressed == mask;
38    let released_bool = mask & released == mask;
39
40    match mask {
41        0x80 => {
42            if released_bool {
43                Some(Keys::BUp)
44            } else if pressed_bool {
45                Some(Keys::BDown)
46            } else {
47                None
48            }
49        }
50        0x40 => {
51            if released_bool {
52                Some(Keys::AUp)
53            } else if pressed_bool {
54                Some(Keys::ADown)
55            } else {
56                None
57            }
58        }
59        0x20 => {
60            if released_bool {
61                Some(Keys::StartUp)
62            } else if pressed_bool {
63                Some(Keys::StartDown)
64            } else {
65                None
66            }
67        }
68        0x10 => {
69            if released_bool {
70                Some(Keys::SelectUp)
71            } else if pressed_bool {
72                Some(Keys::SelectDown)
73            } else {
74                None
75            }
76        }
77
78        0x08 => {
79            if released_bool {
80                Some(Keys::RightUp)
81            } else if pressed_bool {
82                Some(Keys::RightDown)
83            } else {
84                None
85            }
86        }
87        0x04 => {
88            if released_bool {
89                Some(Keys::DownUp)
90            } else if pressed_bool {
91                Some(Keys::DownDown)
92            } else {
93                None
94            }
95        }
96        0x02 => {
97            if released_bool {
98                Some(Keys::UpUp)
99            } else if pressed_bool {
100                Some(Keys::UpDown)
101            } else {
102                None
103            }
104        }
105        0x01 => {
106            if released_bool {
107                Some(Keys::LeftUp)
108            } else if pressed_bool {
109                Some(Keys::LeftDown)
110            } else {
111                None
112            }
113        }
114        _ => None,
115    }
116}
117
118impl Iterator for ButtonIter {
119    type Item = Keys;
120
121    fn next(&mut self) -> Option<Keys> {
122        //really want a while post increment but doesnt exist
123        if self.bit_index >= 8 {
124            return None;
125        }
126
127        //funky do while
128        while {
129            let mask = 0x01 << self.bit_index;
130            self.bit_index += 1;
131
132            let event = mask_to_event(mask, self.released, self.pressed);
133            if event.is_some() {
134                return event;
135            }
136
137            self.bit_index < 8
138        } {}
139
140        None
141    }
142}
143
144/// Button pins
145pub struct ButtonReader {
146    /// Button Latch
147    pub latch: Pb0<Output<PushPull>>,
148    /// Button Out
149    pub data_in: Pb30<Input<Floating>>,
150    /// Button Clock
151    pub clock: Pb31<Output<PushPull>>,
152    pub last: u8,
153}
154
155//120mhz, 1 cycle = 0.000000008333333 = 8.333333ns
156//https://www.onsemi.com/pub/Collateral/MC74HC165A-D.PDF
157//3v <=125c
158//tsu min setup time 55ns = 7 cycles
159//th min hold time 5ns = 1 cycles
160//tw min pulse width 36ns = 5 cycles
161//trec min recovery time 55ns, how long before you should attempt to read
162// again?
163impl ButtonReader {
164    // 48*8.333ns total blocking read
165    /// Returns a ButtonIter of button changes as Keys enums
166    pub fn events(&mut self) -> ButtonIter {
167        self.latch.set_low().ok();
168        cycle_delay(7); //tsu?
169        self.latch.set_high().ok();
170        cycle_delay(1); //th?
171
172        let mut current: u8 = 0;
173
174        for _i in 0..8 {
175            current <<= 1;
176
177            self.clock.set_low().ok();
178            cycle_delay(5); //tw
179
180            if self.data_in.is_high().unwrap() {
181                current |= 1;
182            }
183            self.clock.set_high().ok();
184        }
185
186        let iter = ButtonIter {
187            pressed: (self.last ^ current) & current,
188            released: (self.last ^ current) & self.last,
189            bit_index: 0,
190        };
191
192        self.last = current;
193
194        iter
195    }
196}