@@ -52,9 +52,18 @@ pub enum DcPowerState {
5252}
5353
5454/// This is our system state, as accessible via SPI reads and writes.
55- #[ derive( Debug ) ]
55+ #[ derive( Debug , Default ) ]
5656pub struct RegisterState {
57+ /// The version of this firmware
5758 firmware_version : [ u8 ; 32 ] ,
59+ /// Bytes we've read from the keyboard, ready for sending to the host
60+ ps2_kb_bytes : heapless:: Deque < u8 , 16 > ,
61+ /// Used for holding our TX buffer, so we can re-send if required
62+ scratch : [ u8 ; 16 ] ,
63+ /// A copy of the last request, so we can spot duplicates and re-send
64+ /// without re-doing a FIFO read. This happens if our response gets a CRC
65+ /// error.
66+ last_req : Option < proto:: Request > ,
5867}
5968
6069#[ app( device = crate :: pac, peripherals = true , dispatchers = [ USB , USART3_4_5_6 , TIM14 , TIM15 , TIM16 , TIM17 , PVD ] ) ]
@@ -339,8 +348,8 @@ mod app {
339348 #[ idle( shared = [ msg_q_out, msg_q_in, spi] ) ]
340349 fn idle ( mut ctx : idle:: Context ) -> ! {
341350 let mut register_state = RegisterState {
342- firmware_version :
343- * b"Neotron BMC v0.3.1 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 " ,
351+ firmware_version : * b"Neotron BMC v0.4.1-alpha \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 " ,
352+ .. Default :: default ( )
344353 } ;
345354
346355 defmt:: info!( "Idle is running..." ) ;
@@ -349,8 +358,9 @@ mod app {
349358 Some ( Message :: Ps2Data0 ( word) ) => {
350359 if let Some ( byte) = neotron_bmc_pico:: ps2:: Ps2Decoder :: check_word ( word) {
351360 defmt:: info!( "< KB 0x{:x}" , byte) ;
352- // TODO: Copy byte to software buffer and turn PS/2 bus off
353- // if buffer is full
361+ if let Err ( _x) = register_state. ps2_kb_bytes . push_back ( byte) {
362+ defmt:: warn!( "KB overflow!" ) ;
363+ }
354364 } else {
355365 defmt:: warn!( "< Bad KB 0x{:x}" , word) ;
356366 }
@@ -362,25 +372,22 @@ mod app {
362372 defmt:: warn!( "< Bad MS 0x{:x}" , word) ;
363373 }
364374 }
365- Some ( Message :: PowerButtonLongPress ) => { }
366- Some ( Message :: PowerButtonShortPress ) => { }
367- Some ( Message :: ResetButtonShortPress ) => { }
368- Some ( Message :: SpiRequest ( req) ) => match req. request_type {
369- proto:: RequestType :: Read | proto:: RequestType :: ReadAlt => {
370- process_command ( req, & mut register_state, |rsp| {
371- ctx. shared . spi . lock ( |spi| {
372- spi. set_transmit_sendable ( rsp) . unwrap ( ) ;
373- } ) ;
374- } ) ;
375- }
376- _ => {
377- let rsp =
378- proto:: Response :: new_without_data ( proto:: ResponseResult :: BadLength ) ;
375+ Some ( Message :: PowerButtonLongPress ) => {
376+ // TODO: Move button handling out of ISR
377+ }
378+ Some ( Message :: PowerButtonShortPress ) => {
379+ // TODO: Move button handling out of ISR
380+ }
381+ Some ( Message :: ResetButtonShortPress ) => {
382+ // TODO: Move button handling out of ISR
383+ }
384+ Some ( Message :: SpiRequest ( req) ) => {
385+ process_command ( req, & mut register_state, |rsp| {
379386 ctx. shared . spi . lock ( |spi| {
380- spi. set_transmit_sendable ( & rsp) . unwrap ( ) ;
387+ spi. set_transmit_sendable ( rsp) . unwrap ( ) ;
381388 } ) ;
382- }
383- } ,
389+ } ) ;
390+ }
384391 Some ( Message :: UartByte ( rx_byte) ) => {
385392 defmt:: info!( "UART RX {:?}" , rx_byte) ;
386393 // TODO: Copy byte to software buffer and turn UART RX
@@ -625,26 +632,75 @@ fn process_command<F>(req: proto::Request, register_state: &mut RegisterState, r
625632where
626633 F : FnOnce ( & proto:: Response ) ,
627634{
628- let rsp = match Command :: parse ( req. register ) {
629- Some ( Command :: ProtocolVersion ) => {
635+ if register_state. last_req . as_ref ( ) == Some ( & req) {
636+ // A duplicate! Resend what we sent last time (so we don't affect FIFOs with a duplicate read).
637+ let length = req. length_or_data as usize ;
638+ let rsp = proto:: Response :: new_ok_with_data ( & register_state. scratch [ 0 ..length] ) ;
639+ defmt:: warn!( "Retry" ) ;
640+ rsp_handler ( & rsp) ;
641+ return ;
642+ }
643+
644+ // We were not sent what we were sent last time, so forget the previous request.
645+ register_state. last_req = None ;
646+
647+ // What do they want?
648+ let rsp = match ( req. request_type , Command :: parse ( req. register ) ) {
649+ ( proto:: RequestType :: Read , Some ( Command :: ProtocolVersion ) )
650+ | ( proto:: RequestType :: ReadAlt , Some ( Command :: ProtocolVersion ) ) => {
651+ defmt:: debug!( "Reading ProtocolVersion" ) ;
652+ // They want the Protocol Version we support. Give them v0.1.1.
630653 let length = req. length_or_data as usize ;
631- if length != 3 {
632- proto:: Response :: new_without_data ( proto:: ResponseResult :: BadLength )
633- } else {
654+ if length == 3 {
655+ // No need to cache
634656 proto:: Response :: new_ok_with_data ( & [ 0 , 1 , 1 ] )
657+ } else {
658+ proto:: Response :: new_without_data ( proto:: ResponseResult :: BadLength )
635659 }
636660 }
637- Some ( Command :: FirmwareVersion ) => {
661+ ( proto:: RequestType :: Read , Some ( Command :: FirmwareVersion ) )
662+ | ( proto:: RequestType :: ReadAlt , Some ( Command :: FirmwareVersion ) ) => {
663+ defmt:: debug!( "Reading FirmwareVersion" ) ;
664+ // They want the Firmware Version string.
638665 let length = req. length_or_data as usize ;
639- if length > register_state. firmware_version . len ( ) {
640- proto:: Response :: new_without_data ( proto:: ResponseResult :: BadLength )
641- } else {
666+ if length <= register_state. firmware_version . len ( ) {
642667 let bytes = & register_state. firmware_version ;
668+ // No need to cache
643669 proto:: Response :: new_ok_with_data ( & bytes[ 0 ..length] )
670+ } else {
671+ proto:: Response :: new_without_data ( proto:: ResponseResult :: BadLength )
672+ }
673+ }
674+ ( proto:: RequestType :: Read , Some ( Command :: Ps2KbBuffer ) )
675+ | ( proto:: RequestType :: ReadAlt , Some ( Command :: Ps2KbBuffer ) ) => {
676+ defmt:: debug!( "Reading Ps2KbBuffer" ) ;
677+ let length = req. length_or_data as usize ;
678+ if length > 0 && length <= register_state. scratch . len ( ) {
679+ // First byte is the # bytes in the FIFO
680+ register_state. scratch [ 0 ] = register_state. ps2_kb_bytes . len ( ) as u8 ;
681+ // Then as many of those FIFO bytes as fit
682+ for slot in & mut register_state. scratch [ 1 ..] {
683+ if let Some ( x) = register_state. ps2_kb_bytes . pop_front ( ) {
684+ * slot = x;
685+ } else {
686+ * slot = 0 ;
687+ }
688+ }
689+ // OK, cache this one because FIFO reads are damaing.
690+ register_state. last_req = Some ( req) ;
691+ // Send the response
692+ proto:: Response :: new_ok_with_data ( & register_state. scratch [ 0 ..length] )
693+ } else {
694+ // Can't help you - you want a weird number of bytes
695+ proto:: Response :: new_without_data ( proto:: ResponseResult :: BadLength )
644696 }
645697 }
646- _ => proto:: Response :: new_without_data ( proto:: ResponseResult :: BadRegister ) ,
698+ _ => {
699+ // Sorry, that register / request type is not supported
700+ proto:: Response :: new_without_data ( proto:: ResponseResult :: BadRegister )
701+ }
647702 } ;
703+ defmt:: debug!( "Sending {:?}" , rsp) ;
648704 rsp_handler ( & rsp) ;
649705}
650706
0 commit comments