@@ -42,14 +42,14 @@ mod rgb;
4242
4343use crate :: hal:: { self , pac:: interrupt, pio:: PIOExt } ;
4444use core:: {
45- cell:: { RefCell , UnsafeCell } ,
45+ cell:: UnsafeCell ,
4646 ptr:: addr_of_mut,
4747 sync:: atomic:: { AtomicBool , AtomicU16 , AtomicU32 , Ordering } ,
4848} ;
4949use defmt:: { debug, trace} ;
5050use neotron_common_bios:: video:: { Attr , GlyphAttr , TextBackgroundColour , TextForegroundColour } ;
5151
52- use portable_atomic :: AtomicUsize ;
52+ use core :: sync :: atomic :: { AtomicU8 , AtomicUsize } ;
5353pub use rgb:: { RGBColour , RGBPair } ;
5454
5555// -----------------------------------------------------------------------------
@@ -71,22 +71,23 @@ pub struct ModeInfo {
7171/// Holds a video mode and a pointer, but as an atomic value suitable for use in
7272/// a `static`.
7373pub struct VideoMode {
74- inner : critical_section:: Mutex < RefCell < ModeInfo > > ,
74+ raw_mode : AtomicU8 ,
75+ raw_ptr : AtomicUsize ,
7576}
7677
7778unsafe impl Sync for VideoMode { }
7879
7980impl VideoMode {
8081 /// Construct a new [`NewModeWrapper`] with the given mode.
8182 const fn new ( ) -> VideoMode {
83+ let mode = neotron_common_bios:: video:: Mode :: new (
84+ neotron_common_bios:: video:: Timing :: T640x480 ,
85+ neotron_common_bios:: video:: Format :: Text8x16 ,
86+ ) ;
87+ let ptr = 0 ;
8288 VideoMode {
83- inner : critical_section:: Mutex :: new ( RefCell :: new ( ModeInfo {
84- mode : neotron_common_bios:: video:: Mode :: new (
85- neotron_common_bios:: video:: Timing :: T640x480 ,
86- neotron_common_bios:: video:: Format :: Text8x16 ,
87- ) ,
88- ptr : core:: ptr:: null_mut ( ) ,
89- } ) ) ,
89+ raw_mode : AtomicU8 :: new ( mode. as_u8 ( ) ) ,
90+ raw_ptr : AtomicUsize :: new ( ptr) ,
9091 }
9192 }
9293
@@ -95,17 +96,19 @@ impl VideoMode {
9596 if modeinfo. ptr . is_null ( ) {
9697 modeinfo. ptr = GLYPH_ATTR_ARRAY . as_ptr ( ) as * mut u32 ;
9798 }
98- critical_section :: with ( |cs| {
99- self . inner . replace ( cs , modeinfo ) ;
100- } )
99+ self . raw_mode
100+ . store ( modeinfo . mode . as_u8 ( ) , Ordering :: Relaxed ) ;
101+ self . raw_ptr . store ( modeinfo . ptr as usize , Ordering :: Relaxed ) ;
101102 }
102103
103104 /// Get the current video mode.
104105 pub fn get_mode ( & self ) -> ModeInfo {
105- let mut modeinfo = critical_section:: with ( |cs| {
106- let info = self . inner . borrow_ref ( cs) ;
107- * info
108- } ) ;
106+ let raw_mode = self . raw_mode . load ( Ordering :: Relaxed ) ;
107+ let raw_ptr = self . raw_ptr . load ( Ordering :: Relaxed ) ;
108+ let mut modeinfo = ModeInfo {
109+ mode : unsafe { neotron_common_bios:: video:: Mode :: from_u8 ( raw_mode) } ,
110+ ptr : raw_ptr as * mut u32 ,
111+ } ;
109112 if modeinfo. ptr . is_null ( ) {
110113 modeinfo. ptr = GLYPH_ATTR_ARRAY . as_ptr ( ) as * mut u32 ;
111114 }
@@ -176,10 +179,19 @@ impl RenderEngine {
176179 self . frame_count += 1 ;
177180
178181 // Update video mode only on first line of video
179- let modeinfo = VIDEO_MODE . get_mode ( ) ;
180- self . current_video_ptr = modeinfo. ptr ;
181- self . current_video_mode = modeinfo. mode ;
182+ loop {
183+ let modeinfo = VIDEO_MODE . get_mode ( ) ;
184+ self . current_video_ptr = modeinfo. ptr ;
185+ self . current_video_mode = modeinfo. mode ;
186+ let modeinfo2 = VIDEO_MODE . get_mode ( ) ;
187+ // make sure we get these two as a pair and they can't update one without the other
188+ if modeinfo. mode == modeinfo2. mode {
189+ break ;
190+ }
191+ }
192+ // Tell the ISR to now generate our newly chosen timing
182193 CURRENT_TIMING_MODE . store ( self . current_video_mode . timing ( ) as usize , Ordering :: Relaxed ) ;
194+ // set up our text console to be the right size
183195 self . num_text_cols = self . current_video_mode . text_width ( ) . unwrap_or ( 0 ) as usize ;
184196 self . num_text_rows = self . current_video_mode . text_height ( ) . unwrap_or ( 0 ) as usize ;
185197 }
0 commit comments