@@ -16,7 +16,7 @@ use core::convert::TryFrom;
1616use heapless:: spsc:: { Consumer , Producer , Queue } ;
1717use rtic:: app;
1818use stm32f0xx_hal:: {
19- gpio:: gpioa:: { PA10 , PA11 , PA12 , PA15 , PA2 , PA3 , PA4 , PA9 } ,
19+ gpio:: gpioa:: { PA10 , PA11 , PA12 , PA15 , PA2 , PA3 , PA4 , PA8 , PA9 } ,
2020 gpio:: gpiob:: { PB0 , PB1 , PB3 , PB4 , PB5 } ,
2121 gpio:: gpiof:: { PF0 , PF1 } ,
2222 gpio:: { Alternate , Floating , Input , Output , PullDown , PullUp , PushPull , AF1 } ,
@@ -165,6 +165,8 @@ mod app {
165165 press_button_reset_short : debouncr:: Debouncer < u8 , debouncr:: Repeat2 > ,
166166 /// Run-time Clock Control (required for resetting peripheral blocks)
167167 rcc : Option < rcc:: Rcc > ,
168+ /// IRQ pin
169+ pin_irq : PA8 < Output < PushPull > > ,
168170 }
169171
170172 #[ monotonic( binds = SysTick , default = true ) ]
@@ -230,6 +232,7 @@ mod app {
230232 pin_sck,
231233 pin_cipo,
232234 pin_copi,
235+ mut pin_irq,
233236 ) = cortex_m:: interrupt:: free ( |cs| {
234237 (
235238 // uart_tx,
@@ -273,11 +276,21 @@ mod app {
273276 } ,
274277 // pin_copi,
275278 gpioa. pa7 . into_alternate_af0 ( cs) ,
279+ // pin_irq
280+ gpioa. pa8 . into_push_pull_output ( cs) ,
276281 )
277282 } ) ;
278283
284+ // Put host in reset
279285 pin_sys_reset. set_low ( ) . unwrap ( ) ;
286+ // Turn the PSU off
280287 pin_dc_on. set_low ( ) . unwrap ( ) ;
288+ // IRQ is active low; we have no need for service.
289+ pin_irq. set_high ( ) . unwrap ( ) ;
290+ // Power LED is off
291+ led_power. set_low ( ) . unwrap ( ) ;
292+ // Buzzer is off
293+ _buzzer_pwm. set_low ( ) . unwrap ( ) ;
281294
282295 defmt:: info!( "Creating UART..." ) ;
283296
@@ -293,9 +306,6 @@ mod app {
293306 & mut rcc,
294307 ) ;
295308
296- led_power. set_low ( ) . unwrap ( ) ;
297- _buzzer_pwm. set_low ( ) . unwrap ( ) ;
298-
299309 // Set EXTI15 to use PORT A (PA15) - button input
300310 dp. SYSCFG . exticr4 . modify ( |_r, w| w. exti15 ( ) . pa15 ( ) ) ;
301311
@@ -348,6 +358,7 @@ mod app {
348358 press_button_power_long : debouncr:: debounce_16 ( false ) ,
349359 press_button_reset_short : debouncr:: debounce_2 ( false ) ,
350360 rcc : Some ( rcc) ,
361+ pin_irq,
351362 } ;
352363 let init = init:: Monotonics ( mono) ;
353364 ( shared_resources, local_resources, init)
@@ -356,7 +367,7 @@ mod app {
356367 /// Our idle task.
357368 ///
358369 /// This task is called when there is nothing else to do.
359- #[ idle( shared = [ msg_q_out, msg_q_in, spi, state_dc_power_enabled, pin_dc_on, pin_sys_reset] , local = [ rcc] ) ]
370+ #[ idle( shared = [ msg_q_out, msg_q_in, spi, state_dc_power_enabled, pin_dc_on, pin_sys_reset] , local = [ rcc, pin_irq ] ) ]
360371 fn idle ( mut ctx : idle:: Context ) -> ! {
361372 // TODO: Get this from the VERSION static variable or from PKG_VERSION
362373 let mut register_state = RegisterState {
@@ -366,7 +377,25 @@ mod app {
366377 // Take this out of the `local` object to avoid sharing issues.
367378 let mut rcc = ctx. local . rcc . take ( ) . unwrap ( ) ;
368379 defmt:: info!( "Idle is running..." ) ;
380+ let mut irq_masked = true ;
381+ let mut is_high = false ;
369382 loop {
383+ if !irq_masked && !register_state. ps2_kb_bytes . is_empty ( ) {
384+ // We need service
385+ ctx. local . pin_irq . set_low ( ) . unwrap ( ) ;
386+ if is_high {
387+ defmt:: trace!( "irq set" ) ;
388+ is_high = false ;
389+ }
390+ } else {
391+ // We do not need service
392+ ctx. local . pin_irq . set_high ( ) . unwrap ( ) ;
393+ if !is_high {
394+ defmt:: trace!( "irq clear" ) ;
395+ is_high = true ;
396+ }
397+ }
398+
370399 match ctx. shared . msg_q_out . dequeue ( ) {
371400 Some ( Message :: Ps2Data0 ( word) ) => {
372401 if let Some ( byte) = neotron_bmc_pico:: ps2:: Ps2Decoder :: check_word ( word) {
@@ -392,11 +421,13 @@ mod app {
392421 . state_dc_power_enabled
393422 . lock ( |r| * r = DcPowerState :: Off ) ;
394423 // Stop any SPI stuff that's currently going on (the host is about to be powered off)
395- ctx. shared . spi . lock ( |s| s. stop ( ) ) ;
424+ ctx. shared . spi . lock ( |s| s. reset ( & mut rcc ) ) ;
396425 // Put the host into reset
397426 ctx. shared . pin_sys_reset . lock ( |pin| pin. set_low ( ) . unwrap ( ) ) ;
398427 // Shut off the 5V power
399428 ctx. shared . pin_dc_on . set_low ( ) . unwrap ( ) ;
429+ // Mask the IRQ to avoid back-powering the host
430+ irq_masked = true ;
400431 // Start LED blinking again
401432 led_power_blink:: spawn ( ) . unwrap ( ) ;
402433 }
@@ -418,6 +449,8 @@ mod app {
418449 // TODO: Take system out of reset when 3.3V and 5.0V are good
419450 // Returns an error if it's already scheduled (but we don't care)
420451 let _ = exit_reset:: spawn_after ( RESET_DURATION_MS . millis ( ) ) ;
452+ // Set 5 - unmask the IRQ
453+ irq_masked = false ;
421454 }
422455 }
423456 Some ( Message :: PowerButtonRelease ) => {
@@ -436,8 +469,11 @@ mod app {
436469 // Is the board powered on? Don't do a reset if it's powered off.
437470 if ctx. shared . state_dc_power_enabled . lock ( |r| * r) == DcPowerState :: On {
438471 defmt:: info!( "Reset!" ) ;
439- ctx . shared . pin_sys_reset . lock ( |pin| pin . set_low ( ) . unwrap ( ) ) ;
472+ // Step 1 - Stop any SPI stuff that's currently going on (the host is about to be reset)
440473 ctx. shared . spi . lock ( |s| s. reset ( & mut rcc) ) ;
474+ // Step 2 - Hold reset line (active) low
475+ ctx. shared . pin_sys_reset . lock ( |pin| pin. set_low ( ) . unwrap ( ) ) ;
476+ // Step 3 - Take it out of reset in a short while
441477 // Returns an error if it's already scheduled (but we don't care)
442478 let _ = exit_reset:: spawn_after ( RESET_DURATION_MS . millis ( ) ) ;
443479 }
@@ -466,7 +502,7 @@ mod app {
466502 use proto:: Receivable ;
467503 match proto:: Request :: from_bytes_with_crc ( data, crc) {
468504 Ok ( inner_req) => {
469- defmt:: debug !( "Got packet" ) ;
505+ defmt:: trace !( "Got packet" ) ;
470506 req = Some ( inner_req) ;
471507 }
472508 Err ( proto:: Error :: BadLength ) => {
@@ -708,7 +744,7 @@ where
708744 // A duplicate! Resend what we sent last time (so we don't affect FIFOs with a duplicate read).
709745 let length = req. length_or_data as usize ;
710746 let rsp = proto:: Response :: new_ok_with_data ( & register_state. scratch [ 0 ..length] ) ;
711- defmt:: warn !( "Retry " ) ;
747+ defmt:: debug !( "Detected a retry " ) ;
712748 rsp_handler ( & rsp) ;
713749 return ;
714750 }
@@ -776,11 +812,4 @@ where
776812 // defmt::debug!("Sent {:?}", rsp);
777813}
778814
779- // TODO: Pins we haven't used yet
780- // SPI pins
781- // spi_clk: gpioa.pa5.into_alternate_af0(cs),
782- // spi_cipo: gpioa.pa6.into_alternate_af0(cs),
783- // spi_copi: gpioa.pa7.into_alternate_af0(cs),
784- // I²C pins
785- // i2c_scl: gpiob.pb6.into_alternate_af4(cs),
786- // i2c_sda: gpiob.pb7.into_alternate_af4(cs),
815+ // End of file
0 commit comments