@@ -61,6 +61,23 @@ mod app {
6161 use super :: * ;
6262 use systick_monotonic:: * ; // Implements the `Monotonic` trait
6363
64+ pub enum Message {
65+ /// Word from PS/2 port 0
66+ Ps2Data0 ( u16 ) ,
67+ /// Word from PS/2 port 1
68+ Ps2Data1 ( u16 ) ,
69+ /// Message from SPI bus
70+ SpiRequest ( neotron_bmc_protocol:: Request ) ,
71+ /// The power button was given a tap
72+ PowerButtonShortPress ,
73+ /// The power button was held down
74+ PowerButtonLongPress ,
75+ /// The reset button was given a tap
76+ ResetButtonShortPress ,
77+ /// The UART got some data
78+ UartByte ( u8 ) ,
79+ }
80+
6481 #[ shared]
6582 struct Shared {
6683 /// The power LED (D1101)
@@ -112,9 +129,11 @@ mod app {
112129 /// Our register state
113130 #[ lock_free]
114131 register_state : RegisterState ,
115- /// Keyboard words sink
132+ /// Read messages here
116133 #[ lock_free]
117- kb_q_out : Consumer < ' static , u16 , 8 > ,
134+ msg_q_out : Consumer < ' static , Message , 8 > ,
135+ /// Write messages here
136+ msg_q_in : Producer < ' static , Message , 8 > ,
118137 /// SPI Peripheral
119138 spi : neotron_bmc_pico:: spi:: SpiPeripheral < 5 , 64 > ,
120139 /// CS pin
@@ -131,8 +150,6 @@ mod app {
131150 press_button_reset_short : debouncr:: Debouncer < u8 , debouncr:: Repeat2 > ,
132151 /// Keyboard PS/2 decoder
133152 kb_decoder : neotron_bmc_pico:: ps2:: Ps2Decoder ,
134- /// Keyboard words source
135- kb_q_in : Producer < ' static , u16 , 8 > ,
136153 }
137154
138155 #[ monotonic( binds = SysTick , default = true ) ]
@@ -144,7 +161,7 @@ mod app {
144161 ///
145162 /// * Task `led_power_blink` - blinks the LED
146163 /// * Task `button_poll` - checks the power and reset buttons
147- #[ init( local = [ queue: Queue <u16 , 8 > = Queue :: new( ) ] ) ]
164+ #[ init( local = [ queue: Queue <Message , 8 > = Queue :: new( ) ] ) ]
148165 fn init ( ctx : init:: Context ) -> ( Shared , Local , init:: Monotonics ) {
149166 defmt:: info!( "Neotron BMC version {:?} booting" , VERSION ) ;
150167
@@ -285,7 +302,7 @@ mod app {
285302
286303 defmt:: info!( "Init complete!" ) ;
287304
288- let ( kb_q_in , kb_q_out ) = ctx. local . queue . split ( ) ;
305+ let ( msg_q_in , msg_q_out ) = ctx. local . queue . split ( ) ;
289306
290307 let shared_resources = Shared {
291308 serial,
@@ -307,7 +324,8 @@ mod app {
307324 firmware_version :
308325 * b"Neotron BMC v0.3.1\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 " ,
309326 } ,
310- kb_q_out,
327+ msg_q_out,
328+ msg_q_in,
311329 spi,
312330 pin_cs,
313331 } ;
@@ -316,7 +334,6 @@ mod app {
316334 press_button_power_long : debouncr:: debounce_16 ( false ) ,
317335 press_button_reset_short : debouncr:: debounce_2 ( false ) ,
318336 kb_decoder : neotron_bmc_pico:: ps2:: Ps2Decoder :: new ( ) ,
319- kb_q_in,
320337 } ;
321338 let init = init:: Monotonics ( mono) ;
322339 ( shared_resources, local_resources, init)
@@ -325,45 +342,29 @@ mod app {
325342 /// Our idle task.
326343 ///
327344 /// This task is called when there is nothing else to do.
328- #[ idle( shared = [ kb_q_out , spi, register_state] ) ]
345+ #[ idle( shared = [ msg_q_out , msg_q_in , spi, register_state] ) ]
329346 fn idle ( mut ctx : idle:: Context ) -> ! {
330347 defmt:: info!( "Idle is running..." ) ;
331348 loop {
332- if let Some ( word) = ctx. shared . kb_q_out . dequeue ( ) {
333- if let Some ( byte) = neotron_bmc_pico:: ps2:: Ps2Decoder :: check_word ( word) {
334- defmt:: info!( "< KB 0x{:x}" , byte) ;
335- } else {
336- defmt:: warn!( "< Bad KB 0x{:x}" , word) ;
337- }
338- }
339-
340- let mut req = None ;
341- ctx. shared . spi . lock ( |spi| {
342- let mut mark_done = false ;
343- if let Some ( data) = spi. get_received ( ) {
344- use proto:: Receivable ;
345- match proto:: Request :: from_bytes ( data) {
346- Ok ( inner_req) => {
347- mark_done = true ;
348- req = Some ( inner_req) ;
349- }
350- Err ( proto:: Error :: BadLength ) => {
351- // Need more data
352- }
353- Err ( e) => {
354- defmt:: warn!( "Bad Req ({:02x})" , e as u8 ) ;
355- mark_done = true ;
356- }
349+ match ctx. shared . msg_q_out . dequeue ( ) {
350+ Some ( Message :: Ps2Data0 ( word) ) => {
351+ if let Some ( byte) = neotron_bmc_pico:: ps2:: Ps2Decoder :: check_word ( word) {
352+ defmt:: info!( "< KB 0x{:x}" , byte) ;
353+ } else {
354+ defmt:: warn!( "< Bad KB 0x{:x}" , word) ;
357355 }
358356 }
359- if mark_done {
360- // Couldn't do this whilst holding the `data` ref.
361- spi. mark_done ( ) ;
357+ Some ( Message :: Ps2Data1 ( word) ) => {
358+ if let Some ( byte) = neotron_bmc_pico:: ps2:: Ps2Decoder :: check_word ( word) {
359+ defmt:: info!( "< MS 0x{:x}" , byte) ;
360+ } else {
361+ defmt:: warn!( "< Bad MS 0x{:x}" , word) ;
362+ }
362363 }
363- } ) ;
364-
365- match req {
366- Some ( req) => match req. request_type {
364+ Some ( Message :: PowerButtonLongPress ) => { }
365+ Some ( Message :: PowerButtonShortPress ) => { }
366+ Some ( Message :: ResetButtonShortPress ) => { }
367+ Some ( Message :: SpiRequest ( req) ) => match req. request_type {
367368 proto:: RequestType :: Read | proto:: RequestType :: ReadAlt => {
368369 let rsp = match req. register {
369370 0x00 => {
@@ -393,9 +394,53 @@ mod app {
393394 } ) ;
394395 }
395396 } ,
396- None => { }
397+ Some ( Message :: UartByte ( rx_byte) ) => {
398+ defmt:: info!( "UART RX {:?}" , rx_byte) ;
399+ // TODO: Copy byte to software buffer and turn UART RX
400+ // interrupt off if buffer is full
401+ }
402+ None => {
403+ // No messages
404+ }
397405 }
398406
407+ // Look for something in the SPI bytes received buffer:
408+ let mut req = None ;
409+ ctx. shared . spi . lock ( |spi| {
410+ let mut mark_done = false ;
411+ if let Some ( data) = spi. get_received ( ) {
412+ use proto:: Receivable ;
413+ match proto:: Request :: from_bytes ( data) {
414+ Ok ( inner_req) => {
415+ mark_done = true ;
416+ req = Some ( inner_req) ;
417+ }
418+ Err ( proto:: Error :: BadLength ) => {
419+ // Need more data
420+ }
421+ Err ( e) => {
422+ defmt:: warn!( "Bad Req ({:02x})" , e as u8 ) ;
423+ mark_done = true ;
424+ }
425+ }
426+ }
427+ if mark_done {
428+ // Couldn't do this whilst holding the `data` ref.
429+ spi. mark_done ( ) ;
430+ }
431+ } ) ;
432+
433+ // If we got a valid message, queue it so we can look at it next time around
434+ if let Some ( req) = req {
435+ if ctx
436+ . shared
437+ . msg_q_in
438+ . lock ( |q| q. enqueue ( Message :: SpiRequest ( req) ) )
439+ . is_err ( )
440+ {
441+ panic ! ( "Q full!" ) ;
442+ }
443+ }
399444 // TODO: Read ADC for 3.3V and 5.0V rails and check good
400445 }
401446 }
@@ -408,8 +453,8 @@ mod app {
408453 #[ task(
409454 binds = EXTI4_15 ,
410455 priority = 4 ,
411- shared = [ ps2_clk0, ps2_dat0, exti, spi, pin_cs] ,
412- local = [ kb_decoder, kb_q_in ]
456+ shared = [ ps2_clk0, msg_q_in , ps2_dat0, exti, spi, pin_cs] ,
457+ local = [ kb_decoder]
413458 ) ]
414459 fn exti4_15_interrupt ( mut ctx : exti4_15_interrupt:: Context ) {
415460 let pr = ctx. shared . exti . pr . read ( ) ;
@@ -419,7 +464,14 @@ mod app {
419464 // Do we have a complete word?
420465 if let Some ( data) = ctx. local . kb_decoder . add_bit ( data_bit) {
421466 // Don't dump in the ISR - we're busy. Add it to this nice lockless queue instead.
422- ctx. local . kb_q_in . enqueue ( data) . unwrap ( ) ;
467+ if ctx
468+ . shared
469+ . msg_q_in
470+ . lock ( |q| q. enqueue ( Message :: Ps2Data0 ( data) ) )
471+ . is_err ( )
472+ {
473+ panic ! ( "queue full" ) ;
474+ } ;
423475 }
424476 // Clear the pending flag for this pin
425477 ctx. shared . exti . pr . write ( |w| w. pr15 ( ) . set_bit ( ) ) ;
@@ -442,16 +494,17 @@ mod app {
442494 ///
443495 /// It fires whenever there is new data received on USART1. We should flag to the host
444496 /// that data is available.
445- #[ task( binds = USART1 , shared = [ serial] ) ]
446- fn usart1_interrupt ( ctx : usart1_interrupt:: Context ) {
497+ #[ task( binds = USART1 , shared = [ serial, msg_q_in ] ) ]
498+ fn usart1_interrupt ( mut ctx : usart1_interrupt:: Context ) {
447499 // Reading the register clears the RX-Not-Empty-Interrupt flag.
448500 match ctx. shared . serial . read ( ) {
449501 Ok ( b) => {
450- defmt :: info! ( "<< UART {:x}" , b ) ;
451- }
452- Err ( _ ) => {
453- defmt :: warn! ( "<< UART None?" ) ;
502+ let _ = ctx
503+ . shared
504+ . msg_q_in
505+ . lock ( |q| q . enqueue ( Message :: UartByte ( b ) ) ) ;
454506 }
507+ _ => { }
455508 }
456509 }
457510
0 commit comments