@@ -55,7 +55,7 @@ pub enum DcPowerState {
5555/// * Stop Bit
5656#[ derive( Debug ) ]
5757pub struct Ps2Decoder {
58- bit_count : u8 ,
58+ bit_mask : u16 ,
5959 collector : u16 ,
6060}
6161
@@ -71,22 +71,22 @@ mod app {
7171 use fugit:: ExtU32 ;
7272
7373 #[ shared]
74- struct Resources {
74+ struct Shared {
7575 /// The power LED (D1101)
7676 #[ lock_free]
7777 led_power : PB0 < Output < PushPull > > ,
7878 /// The status LED (D1102)
7979 #[ lock_free]
80- led_status : PB1 < Output < PushPull > > ,
80+ _led_status : PB1 < Output < PushPull > > ,
8181 /// The FTDI UART header (J105)
8282 #[ lock_free]
8383 serial : serial:: Serial < pac:: USART1 , PA9 < Alternate < AF1 > > , PA10 < Alternate < AF1 > > > ,
8484 /// The Clear-To-Send line on the FTDI UART header (which the serial object can't handle)
8585 #[ lock_free]
86- pin_uart_cts : PA11 < Alternate < AF1 > > ,
86+ _pin_uart_cts : PA11 < Alternate < AF1 > > ,
8787 /// The Ready-To-Receive line on the FTDI UART header (which the serial object can't handle)
8888 #[ lock_free]
89- pin_uart_rts : PA12 < Alternate < AF1 > > ,
89+ _pin_uart_rts : PA12 < Alternate < AF1 > > ,
9090 /// The power button
9191 #[ lock_free]
9292 button_power : PF0 < Input < PullUp > > ,
@@ -108,25 +108,25 @@ mod app {
108108 ps2_clk0 : PA15 < Input < Floating > > ,
109109 /// Clock pin for PS/2 Mouse port
110110 #[ lock_free]
111- ps2_clk1 : PB3 < Input < Floating > > ,
111+ _ps2_clk1 : PB3 < Input < Floating > > ,
112112 /// Data pin for PS/2 Keyboard port
113113 #[ lock_free]
114114 ps2_dat0 : PB4 < Input < Floating > > ,
115115 /// Data pin for PS/2 Mouse port
116116 #[ lock_free]
117- ps2_dat1 : PB5 < Input < Floating > > ,
117+ _ps2_dat1 : PB5 < Input < Floating > > ,
118118 /// The external interrupt peripheral
119119 #[ lock_free]
120120 exti : pac:: EXTI ,
121121 /// Our register state
122122 #[ lock_free]
123- register_state : RegisterState ,
123+ _register_state : RegisterState ,
124124 /// Keyboard bytes sink
125125 #[ lock_free]
126- kb_c : Consumer < ' static , u16 , 8 > ,
126+ kb_q_out : Consumer < ' static , u16 , 8 > ,
127127 /// Keyboard bytes source
128128 #[ lock_free]
129- kb_p : Producer < ' static , u16 , 8 > ,
129+ kb_q_in : Producer < ' static , u16 , 8 > ,
130130 }
131131
132132 #[ local]
@@ -135,10 +135,10 @@ mod app {
135135 press_button_power_short : debouncr:: Debouncer < u8 , debouncr:: Repeat2 > ,
136136 /// Tracks power button state for long presses. 75ms x 16 = 1200ms is a long press
137137 press_button_power_long : debouncr:: Debouncer < u16 , debouncr:: Repeat16 > ,
138+ /// Tracks reset button state for long presses. 75ms x 16 = 1200ms is a long press
139+ press_button_reset_long : debouncr:: Debouncer < u16 , debouncr:: Repeat16 > ,
138140 /// Keyboard PS/2 decoder
139141 kb_decoder : Ps2Decoder ,
140- /// Mouse PS/2 decoder
141- ms_decoder : Ps2Decoder ,
142142 }
143143
144144 #[ monotonic( binds = TIM2 , default = true ) ]
@@ -151,7 +151,7 @@ mod app {
151151 /// * Task `led_power_blink` - blinks the LED
152152 /// * Task `button_poll` - checks the power and reset buttons
153153 #[ init( local = [ queue: Queue <u16 , 8 > = Queue :: new( ) ] ) ]
154- fn init ( ctx : init:: Context ) -> ( Resources , Local , init:: Monotonics ) {
154+ fn init ( ctx : init:: Context ) -> ( Shared , Local , init:: Monotonics ) {
155155 defmt:: info!( "Neotron BMC version {:?} booting" , VERSION ) ;
156156
157157 let dp: pac:: Peripherals = ctx. device ;
@@ -172,21 +172,29 @@ mod app {
172172 let gpioa = dp. GPIOA . split ( & mut rcc) ;
173173 let gpiob = dp. GPIOB . split ( & mut rcc) ;
174174 let gpiof = dp. GPIOF . split ( & mut rcc) ;
175+ // We have to have the closure return a tuple of all our configured
176+ // pins because by taking fields from `gpioa`, `gpiob`, etc, we leave
177+ // them as partial structures. This prevents us from having a call to
178+ // `disable_interrupts` for each pin. We can't simply do the `let foo
179+ // = ` inside the closure either, as the pins would be dropped when
180+ // the closure ended. So, we have this slightly awkward syntax
181+ // instead. Do ensure the pins and the variables line-up correctly;
182+ // order is important!
175183 let (
176184 uart_tx,
177185 uart_rx,
178- pin_uart_cts ,
179- pin_uart_rts ,
186+ _pin_uart_cts ,
187+ _pin_uart_rts ,
180188 mut led_power,
181- mut led_status ,
189+ mut _led_status ,
182190 button_power,
183191 button_reset,
184192 mut pin_dc_on,
185193 mut pin_sys_reset,
186194 ps2_clk0,
187- ps2_clk1 ,
195+ _ps2_clk1 ,
188196 ps2_dat0,
189- ps2_dat1 ,
197+ _ps2_dat1 ,
190198 ) = disable_interrupts ( |cs| {
191199 (
192200 gpioa. pa9 . into_alternate_af1 ( cs) ,
@@ -216,12 +224,8 @@ mod app {
216224
217225 serial. listen ( serial:: Event :: Rxne ) ;
218226
219- led_power_blink:: spawn ( ) . unwrap ( ) ;
220-
221- button_poll:: spawn ( ) . unwrap ( ) ;
222-
223227 led_power. set_low ( ) . unwrap ( ) ;
224- led_status . set_low ( ) . unwrap ( ) ;
228+ _led_status . set_low ( ) . unwrap ( ) ;
225229
226230 // Set EXTI15 to use PORT A (PA15)
227231 dp. SYSCFG . exticr4 . write ( |w| w. exti15 ( ) . pa15 ( ) ) ;
@@ -231,52 +235,55 @@ mod app {
231235 dp. EXTI . emr . modify ( |_r, w| w. mr15 ( ) . set_bit ( ) ) ;
232236 dp. EXTI . ftsr . modify ( |_r, w| w. tr15 ( ) . set_bit ( ) ) ;
233237
238+ // Spawn the tasks that run all the time
239+ led_power_blink:: spawn ( ) . unwrap ( ) ;
240+ button_poll:: spawn ( ) . unwrap ( ) ;
241+
234242 defmt:: info!( "Init complete!" ) ;
235243
236- let ( kb_p, kb_c) = ctx. local . queue . split ( ) ;
237-
238- (
239- Resources {
240- serial,
241- pin_uart_cts,
242- pin_uart_rts,
243- led_power,
244- led_status,
245- button_power,
246- button_reset,
247- state_dc_power_enabled : DcPowerState :: Off ,
248- pin_dc_on,
249- pin_sys_reset,
250- ps2_clk0,
251- ps2_clk1,
252- ps2_dat0,
253- ps2_dat1,
254- exti : dp. EXTI ,
255- register_state : RegisterState {
256- firmware_version : "Neotron BMC v0.0.0" ,
257- } ,
258- kb_p,
259- kb_c,
260- } ,
261- Local {
262- press_button_power_short : debouncr:: debounce_2 ( false ) ,
263- press_button_power_long : debouncr:: debounce_16 ( false ) ,
264- kb_decoder : Ps2Decoder :: new ( ) ,
265- ms_decoder : Ps2Decoder :: new ( ) ,
244+ let ( kb_q_in, kb_q_out) = ctx. local . queue . split ( ) ;
245+
246+ let shared_resources = Shared {
247+ serial,
248+ _pin_uart_cts,
249+ _pin_uart_rts,
250+ led_power,
251+ _led_status,
252+ button_power,
253+ button_reset,
254+ state_dc_power_enabled : DcPowerState :: Off ,
255+ pin_dc_on,
256+ pin_sys_reset,
257+ ps2_clk0,
258+ _ps2_clk1,
259+ ps2_dat0,
260+ _ps2_dat1,
261+ exti : dp. EXTI ,
262+ _register_state : RegisterState {
263+ firmware_version : concat ! ( "Neotron BMC " , env!( "CARGO_PKG_VERSION" ) ) ,
266264 } ,
267- init:: Monotonics ( mono) ,
268- )
265+ kb_q_in,
266+ kb_q_out,
267+ } ;
268+ let local_resources = Local {
269+ press_button_power_short : debouncr:: debounce_2 ( false ) ,
270+ press_button_power_long : debouncr:: debounce_16 ( false ) ,
271+ press_button_reset_long : debouncr:: debounce_16 ( false ) ,
272+ kb_decoder : Ps2Decoder :: new ( ) ,
273+ } ;
274+ let init = init:: Monotonics ( mono) ;
275+ ( shared_resources, local_resources, init)
269276 }
270277
271278 /// Our idle task.
272279 ///
273280 /// This task is called when there is nothing else to do. We
274281 /// do a little logging, then put the CPU to sleep waiting for an interrupt.
275- #[ idle( shared = [ kb_c ] ) ]
282+ #[ idle( shared = [ kb_q_out ] ) ]
276283 fn idle ( ctx : idle:: Context ) -> ! {
277284 defmt:: info!( "Idle is running..." ) ;
278285 loop {
279- if let Some ( word) = ctx. shared . kb_c . dequeue ( ) {
286+ if let Some ( word) = ctx. shared . kb_q_out . dequeue ( ) {
280287 if let Some ( byte) = Ps2Decoder :: check_word ( word) {
281288 defmt:: info!( "< KB {:x}" , byte) ;
282289 } else {
@@ -294,15 +301,15 @@ mod app {
294301 #[ task(
295302 binds = EXTI4_15 ,
296303 priority = 4 ,
297- shared = [ ps2_clk0, ps2_dat0, exti, kb_p ] ,
304+ shared = [ ps2_clk0, ps2_dat0, exti, kb_q_in ] ,
298305 local = [ kb_decoder]
299306 ) ]
300307 fn exti4_15_interrupt ( ctx : exti4_15_interrupt:: Context ) {
301308 let data_bit = ctx. shared . ps2_dat0 . is_high ( ) . unwrap ( ) ;
302309 // Do we have a complete word (and if so, is the parity OK)?
303310 if let Some ( data) = ctx. local . kb_decoder . add_bit ( data_bit) {
304311 // Don't dump in the ISR - we're busy. Add it to this nice lockless queue instead.
305- ctx. shared . kb_p . enqueue ( data) . unwrap ( ) ;
312+ ctx. shared . kb_q_in . enqueue ( data) . unwrap ( ) ;
306313 }
307314 // Clear the pending flag
308315 ctx. shared . exti . pr . write ( |w| w. pr15 ( ) . set_bit ( ) ) ;
@@ -348,21 +355,27 @@ mod app {
348355 /// We poll them rather than setting up an interrupt as we need to debounce them, which involves waiting a short period and checking them again. Given that we have to do that, we might as well not bother with the interrupt.
349356 #[ task(
350357 shared = [
351- led_power, button_power, state_dc_power_enabled ,
352- pin_sys_reset, pin_dc_on
358+ led_power, button_power, button_reset ,
359+ state_dc_power_enabled , pin_sys_reset, pin_dc_on
353360 ] ,
354- local = [ press_button_power_short, press_button_power_long ]
361+ local = [ press_button_power_short, press_button_power_long, press_button_reset_long ]
355362 ) ]
356363 fn button_poll ( ctx : button_poll:: Context ) {
357- // Poll button
358- let pressed: bool = ctx. shared . button_power . is_low ( ) . unwrap ( ) ;
364+ // Poll buttons
365+ let pwr_pressed: bool = ctx. shared . button_power . is_low ( ) . unwrap ( ) ;
366+ let rst_pressed: bool = ctx. shared . button_reset . is_low ( ) . unwrap ( ) ;
359367
360368 // Update state
361- let short_edge = ctx. local . press_button_power_short . update ( pressed) ;
362- let long_edge = ctx. local . press_button_power_long . update ( pressed) ;
369+ let pwr_short_edge = ctx. local . press_button_power_short . update ( pwr_pressed) ;
370+ let pwr_long_edge = ctx. local . press_button_power_long . update ( pwr_pressed) ;
371+ let rst_long_edge = ctx. local . press_button_reset_long . update ( rst_pressed) ;
363372
364373 // Dispatch event
365- match ( long_edge, short_edge, * ctx. shared . state_dc_power_enabled ) {
374+ match (
375+ pwr_long_edge,
376+ pwr_short_edge,
377+ * ctx. shared . state_dc_power_enabled ,
378+ ) {
366379 ( None , Some ( debouncr:: Edge :: Rising ) , DcPowerState :: Off ) => {
367380 defmt:: info!( "Power button pressed whilst off." ) ;
368381 // Button pressed - power on system
@@ -392,11 +405,17 @@ mod app {
392405 }
393406 _ => {
394407 // Do nothing
395- // TODO: Put system in reset here
396- // TODO: Disable DC PSU here
397408 }
398409 }
399410
411+ if let Some ( debouncr:: Edge :: Falling ) = rst_long_edge {
412+ defmt:: info!( "Reset!" ) ;
413+ ctx. shared . pin_sys_reset . set_low ( ) . unwrap ( ) ;
414+ // TODO: This pulse will be very short. We should spawn a task to
415+ // take it out of reset after about 100ms.
416+ ctx. shared . pin_sys_reset . set_high ( ) . unwrap ( ) ;
417+ }
418+
400419 // Re-schedule the timer interrupt
401420 button_poll:: spawn_after ( DEBOUNCE_POLL_INTERVAL_MS . millis ( ) ) . unwrap ( ) ;
402421 }
@@ -405,22 +424,22 @@ mod app {
405424impl Ps2Decoder {
406425 fn new ( ) -> Ps2Decoder {
407426 Ps2Decoder {
408- bit_count : 0 ,
427+ bit_mask : 1 ,
409428 collector : 0 ,
410429 }
411430 }
412431
413432 fn reset ( & mut self ) {
414- self . bit_count = 0 ;
433+ self . bit_mask = 0 ;
415434 self . collector = 0 ;
416435 }
417436
418437 fn add_bit ( & mut self , bit : bool ) -> Option < u16 > {
419438 if bit {
420- self . collector |= 1 << self . bit_count ;
439+ self . collector |= self . bit_mask ;
421440 }
422- self . bit_count + = 1 ;
423- if self . bit_count == 11 {
441+ self . bit_mask << = 1 ;
442+ if self . bit_mask == 0b100000000000 {
424443 let result = self . collector ;
425444 self . reset ( ) ;
426445 Some ( result)
0 commit comments