@@ -151,59 +151,63 @@ pub enum KeyState { #[default] Up, Down }
151151
152152/// Keypad scanner loop.
153153///
154- /// Pass this its initial `config` plus a handoff channel through which it can
154+ /// Pass this its initial `config` plus a watch channel through which it can
155155/// receive updated configs. It'll scan the provided GPIO port (pins 0-7) and
156156/// emit events through `out_queue`.
157157pub async fn task (
158- mut config : Config ,
159- mut config_update : lilos_handoff:: Popper < ' _ , Config > ,
158+ mut config_update : lilos_watch:: Receiver < ' _ , Config > ,
160159 gpio : device:: gpio:: Gpio ,
161160 mut out_queue : spsc:: Pusher < ' _ , KeyEvent > ,
162161) -> Infallible {
163162 configure_pins ( gpio) ;
164163
164+ // Make a copy of the config so we can be specific about changes.
165+ let mut config = config_update. copy_current ( ) ;
166+
165167 let debouncers = DEBOUNCERS . take ( ) ;
166168 let mut scan_gate = PeriodicGate :: from ( SCAN_INTERVAL ) ;
167169 loop {
168170 scan_gate. next_time ( ) . await ;
169171
170172 // Process any config update before starting the scan.
171- if let Some ( new_config) = config_update. try_pop ( ) {
172- // Handle any "killed" drive lines. This occurs when the
173- // `driven_lines` bit was 1 in the old config, and is becoming 0.
174- // When a drive line is killed we need to reset the state of its
175- // debouncers so they don't do anything.
176- for ( line, debounce_row) in debouncers. iter_mut ( ) . enumerate ( ) {
177- let line_mask = 1 << line;
178- let in_use_before = config. driven_lines & line_mask != 0 ;
179- let still_in_use = new_config. driven_lines & line_mask != 0 ;
180- if in_use_before && !still_in_use {
181- for debouncer in debounce_row {
182- * debouncer = Default :: default ( ) ;
173+ if config_update. is_changed ( ) {
174+ config_update. glimpse_and_update ( |new_config| {
175+ // Handle any "killed" drive lines. This occurs when the
176+ // `driven_lines` bit was 1 in the old config, and is becoming 0.
177+ // When a drive line is killed we need to reset the state of its
178+ // debouncers so they don't do anything.
179+ for ( line, debounce_row) in debouncers. iter_mut ( ) . enumerate ( ) {
180+ let line_mask = 1 << line;
181+ let in_use_before = config. driven_lines & line_mask != 0 ;
182+ let still_in_use = new_config. driven_lines & line_mask != 0 ;
183+ if in_use_before && !still_in_use {
184+ for debouncer in debounce_row {
185+ * debouncer = Default :: default ( ) ;
186+ }
183187 }
184188 }
185- }
186- // Handle any "killed" keys. This occurs when the key's bit in the
187- // `ghost_mask` was not set before, but has become set. As in the
188- // killed line case, we need to reset its debouncer state.
189- //
190- // This is written using a range and indexing because, believe it or
191- // not, enumerate generates much larger code -- at least as of
192- // 1.75.0. This is because we're at opt-level="z", which makes dumb
193- // decisions like "not inlining the enumerate iterator for slices."
194- # [ allow ( clippy :: needless_range_loop ) ]
195- for line in 0 ..8 {
196- for col in 0 .. 8 {
197- let col_mask = 1 << col ;
198- let real_before = config . ghost_mask [ line] & col_mask = = 0 ;
199- let still_real = new_config . ghost_mask [ line ] & col_mask != 0 ;
200- if real_before && !still_real {
201- debouncers [ line ] [ col ] = Default :: default ( ) ;
189+ // Handle any "killed" keys. This occurs when the key's bit in the
190+ // `ghost_mask` was not set before, but has become set. As in the
191+ // killed line case, we need to reset its debouncer state.
192+ //
193+ // This is written using a range and indexing because, believe it or
194+ // not, enumerate generates much larger code -- at least as of
195+ // 1.75.0. This is because we're at opt-level="z", which makes dumb
196+ // decisions like "not inlining the enumerate iterator for slices."
197+ # [ allow ( clippy :: needless_range_loop ) ]
198+ for line in 0 .. 8 {
199+ for col in 0 ..8 {
200+ let col_mask = 1 << col ;
201+ let real_before = config . ghost_mask [ line ] & col_mask == 0 ;
202+ let still_real = new_config . ghost_mask [ line] & col_mask ! = 0 ;
203+ if real_before && !still_real {
204+ debouncers [ line ] [ col ] = Default :: default ( ) ;
205+ }
202206 }
203207 }
204- }
205- // Apply the config.
206- config = new_config ;
208+ // Apply the config.
209+ config = * new_config ;
210+ } ) ;
207211 }
208212 // Config doesn't get modified anywhere else in this loop -- see:
209213 let config = & config;
0 commit comments