@@ -183,6 +183,7 @@ pub struct Oled128x128<'a> {
183183 powerdown : bool ,
184184 power_port : IoxPort ,
185185 power_pin : u8 ,
186+ clk_div : u8 ,
186187}
187188
188189impl < ' a > Oled128x128 < ' a > {
@@ -267,9 +268,19 @@ impl<'a> Oled128x128<'a> {
267268 power_port,
268269 power_pin,
269270 powerdown : false ,
271+ clk_div : ( ( perclk_freq / 2 ) / 2_000_000 ) as u8 ,
270272 }
271273 }
272274
275+ // used to recover a wedged SPI interface
276+ pub fn reinit_spi ( & mut self ) {
277+ self . spim . send_cmd_list ( & [ crate :: udma:: SpimCmd :: Config (
278+ SpimClkPol :: LeadingEdgeRise ,
279+ SpimClkPha :: CaptureOnLeading ,
280+ self . clk_div ,
281+ ) ] ) ;
282+ }
283+
273284 /// This should only be called to initialize the panic handler with its own
274285 /// copy of hardware registers.
275286 ///
@@ -300,8 +311,9 @@ impl<'a> Oled128x128<'a> {
300311 Option < CommandSet > ,
301312 ) ,
302313 bool ,
314+ u8 ,
303315 ) {
304- ( self . spim . into_raw_parts ( ) , self . powerdown )
316+ ( self . spim . into_raw_parts ( ) , self . powerdown , self . clk_div )
305317 }
306318
307319 /// Creates a clone of the display handle. This is only safe if the handles are used in a
@@ -331,6 +343,7 @@ impl<'a> Oled128x128<'a> {
331343 Option < CommandSet > ,
332344 ) ,
333345 bool ,
346+ u8 ,
334347 ) ,
335348 iox : & ' a T ,
336349 ) -> Self
@@ -354,6 +367,7 @@ impl<'a> Oled128x128<'a> {
354367 command_set,
355368 ) ,
356369 powerdown,
370+ clk_div,
357371 ) = display_parts;
358372 // compile them into a new object
359373 let mut spim = unsafe {
@@ -398,6 +412,7 @@ impl<'a> Oled128x128<'a> {
398412 powerdown,
399413 power_pin,
400414 power_port,
415+ clk_div,
401416 }
402417 }
403418
@@ -407,7 +422,7 @@ impl<'a> Oled128x128<'a> {
407422
408423 pub fn screen_size ( & self ) -> Point { Point :: new ( WIDTH , LINES ) }
409424
410- pub fn redraw ( & mut self ) { self . draw ( ) ; }
425+ pub fn redraw ( & mut self ) -> Result < ( ) , xous :: Error > { self . draw ( ) }
411426
412427 pub fn blit_screen ( & mut self , bmp : & [ u32 ] ) { self . buffer . copy_from_slice ( bmp) ; }
413428
@@ -417,21 +432,21 @@ impl<'a> Oled128x128<'a> {
417432
418433 pub fn stash ( & mut self ) { self . stash . copy_from_slice ( & self . buffer ) ; }
419434
420- pub fn pop ( & mut self ) {
435+ pub fn pop ( & mut self ) -> Result < ( ) , xous :: Error > {
421436 self . buffer . copy_from_slice ( & self . stash ) ;
422- self . redraw ( ) ;
437+ self . redraw ( )
423438 }
424439
425440 fn set_data ( & self ) { self . iox . set_gpio_pin_value ( self . cd_port , self . cd_pin , IoxValue :: High ) ; }
426441
427442 fn set_command ( & self ) { self . iox . set_gpio_pin_value ( self . cd_port , self . cd_pin , IoxValue :: Low ) ; }
428443
429- pub fn send_command < ' b , U > ( & ' b mut self , cmd : U )
444+ pub fn send_command < ' b , U > ( & ' b mut self , cmd : U ) -> Result < ( ) , xous :: Error >
430445 where
431446 U : IntoIterator < Item = u8 > + ' b ,
432447 {
433448 if self . powerdown {
434- return ;
449+ return Ok ( ( ) ) ;
435450 }
436451 self . set_command ( ) ;
437452 let total_buf_len = self . buffer . len ( ) * size_of :: < u32 > ( ) ;
@@ -451,16 +466,12 @@ impl<'a> Oled128x128<'a> {
451466 . txrx_data_async_from_parts :: < u8 > ( total_buf_len, len, true , false )
452467 . expect ( "Couldn't initiate oled command" ) ;
453468 }
454- self . spim . txrx_await ( false ) . unwrap_or_else ( |_e| {
455- #[ cfg( feature = "std" ) ]
456- log:: error!( "txrx err {:?}" , _e) ;
457- & [ ]
458- } ) ;
469+ self . spim . txrx_await ( false ) . map ( |_| ( ) )
459470 }
460471
461- pub fn init ( & mut self ) {
472+ pub fn init ( & mut self ) -> Result < ( ) , xous :: Error > {
462473 if self . powerdown {
463- return ;
474+ return Ok ( ( ) ) ;
464475 }
465476 use Command :: * ;
466477 let init_sequence = [
@@ -483,17 +494,18 @@ impl<'a> Oled128x128<'a> {
483494
484495 for command in init_sequence {
485496 let bytes = command. encode ( ) ;
486- self . send_command ( bytes) ;
497+ self . send_command ( bytes) ? ;
487498 }
488499 // clear the frame buffer
489500 self . buffer_mut ( ) . fill ( 0xFFFF_FFFF ) ;
490- self . draw ( ) ;
501+ self . draw ( ) ? ;
491502
492503 let display_on = [ DisplayOnOff ( DisplayState :: On ) ] ;
493504 for command in display_on {
494505 let bytes = command. encode ( ) ;
495- self . send_command ( bytes) ;
506+ self . send_command ( bytes) ? ;
496507 }
508+ Ok ( ( ) )
497509 }
498510
499511 pub fn powerdown ( & mut self ) {
@@ -516,9 +528,9 @@ impl<'a> Oled128x128<'a> {
516528 self . powerdown = false ;
517529 }
518530
519- pub fn brightness ( & mut self , level : u8 ) {
531+ pub fn brightness ( & mut self , level : u8 ) -> Result < ( ) , xous :: Error > {
520532 let bytes = Command :: SetContrastControl ( level) . encode ( ) ;
521- self . send_command ( bytes) ;
533+ self . send_command ( bytes)
522534 }
523535
524536 #[ cfg( feature = "std" ) ]
@@ -574,10 +586,10 @@ impl<'a> Oled128x128<'a> {
574586
575587impl < ' a > FrameBuffer for Oled128x128 < ' a > {
576588 /// Copies the SRAM buffer to IFRAM and then transfers that over SPI
577- fn draw ( & mut self ) {
589+ fn draw ( & mut self ) -> Result < ( ) , xous :: Error > {
578590 self . hw_buf . copy_from_slice ( & self . buffer ) ;
579591 if self . powerdown {
580- return ;
592+ return Ok ( ( ) ) ;
581593 }
582594 let chunk_size = 16 ;
583595 let chunks = self . buffer ( ) . len ( ) * size_of :: < u32 > ( ) / chunk_size;
@@ -588,8 +600,8 @@ impl<'a> FrameBuffer for Oled128x128<'a> {
588600 // the transaction is done before the data is done transmitting, and we have to
589601 // toggle set_data() only after the physical transaction is done, not after the
590602 // the last UDMA action has been queued.
591- self . send_command ( Command :: SetPageAddress ( 0 ) . encode ( ) ) ;
592- self . send_command ( Command :: SetColumnAddress ( page as u8 ) . encode ( ) ) ;
603+ self . send_command ( Command :: SetPageAddress ( 0 ) . encode ( ) ) ? ;
604+ self . send_command ( Command :: SetColumnAddress ( page as u8 ) . encode ( ) ) ? ;
593605 // wait for commands to finish before toggling set_data
594606 // self.spim.tx_data_await(false);
595607 // crate::println!("Send page {}, offset {:x}", page, page * chunk_size);
@@ -600,12 +612,9 @@ impl<'a> FrameBuffer for Oled128x128<'a> {
600612 . txrx_data_async_from_parts :: < u8 > ( page * chunk_size, chunk_size, true , false )
601613 . expect ( "Couldn't initiate oled data transfer" ) ;
602614 }
603- self . spim . txrx_await ( false ) . unwrap_or_else ( |_e| {
604- #[ cfg( feature = "std" ) ]
605- log:: error!( "txrx err {:?}" , _e) ;
606- & [ ]
607- } ) ;
615+ self . spim . txrx_await ( false ) ?;
608616 }
617+ Ok ( ( ) )
609618 }
610619
611620 fn clear ( & mut self ) { self . buffer_mut ( ) . fill ( 0xFFFF_FFFF ) ; }
0 commit comments