move command execution code to own file
This commit is contained in:
		
							parent
							
								
									9f5d256963
								
							
						
					
					
						commit
						69502ac3fb
					
				
					 3 changed files with 194 additions and 184 deletions
				
			
		
							
								
								
									
										178
									
								
								src/execute_command.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								src/execute_command.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,178 @@ | |||
| use std::sync::{RwLock, RwLockWriteGuard}; | ||||
| 
 | ||||
| use log::{debug, error, info, warn}; | ||||
| use servicepoint2::{ | ||||
|     ByteGrid, Command, Origin, PIXEL_COUNT, PIXEL_WIDTH, PixelGrid, TILE_SIZE, | ||||
| }; | ||||
| 
 | ||||
| use crate::font::BitmapFont; | ||||
| 
 | ||||
| pub(crate) fn execute_command( | ||||
|     command: Command, | ||||
|     font: &BitmapFont, | ||||
|     display_ref: &RwLock<PixelGrid>, | ||||
|     luma_ref: &RwLock<ByteGrid>, | ||||
| ) -> bool { | ||||
|     debug!("received {command:?}"); | ||||
|     match command { | ||||
|         Command::Clear => { | ||||
|             info!("clearing display"); | ||||
|             display_ref.write().unwrap().fill(false); | ||||
|         } | ||||
|         Command::HardReset => { | ||||
|             warn!("display shutting down"); | ||||
|             return false; | ||||
|         } | ||||
|         Command::BitmapLinearWin(Origin(x, y), pixels) => { | ||||
|             let mut display = display_ref.write().unwrap(); | ||||
|             print_pixel_grid(x as usize, y as usize, &pixels, &mut display); | ||||
|         } | ||||
|         Command::Cp437Data(origin, grid) => { | ||||
|             let mut display = display_ref.write().unwrap(); | ||||
|             print_cp437_data(origin, &grid, font, &mut display); | ||||
|         } | ||||
|         #[allow(deprecated)] | ||||
|         Command::BitmapLegacy => { | ||||
|             warn!("ignoring deprecated command {:?}", command); | ||||
|         } | ||||
|         // TODO: how to deduplicate this code in a rusty way?
 | ||||
|         Command::BitmapLinear(offset, vec, _) => { | ||||
|             if !check_bitmap_valid(offset, vec.len()) { | ||||
|                 return true; | ||||
|             } | ||||
|             let mut display = display_ref.write().unwrap(); | ||||
|             for bitmap_index in 0..vec.len() { | ||||
|                 let (x, y) = | ||||
|                     get_coordinates_for_index(offset as usize, bitmap_index); | ||||
|                 display.set(x, y, vec.get(bitmap_index)); | ||||
|             } | ||||
|         } | ||||
|         Command::BitmapLinearAnd(offset, vec, _) => { | ||||
|             if !check_bitmap_valid(offset, vec.len()) { | ||||
|                 return true; | ||||
|             } | ||||
|             let mut display = display_ref.write().unwrap(); | ||||
|             for bitmap_index in 0..vec.len() { | ||||
|                 let (x, y) = | ||||
|                     get_coordinates_for_index(offset as usize, bitmap_index); | ||||
|                 let old_value = display.get(x, y); | ||||
|                 display.set(x, y, old_value && vec.get(bitmap_index)); | ||||
|             } | ||||
|         } | ||||
|         Command::BitmapLinearOr(offset, vec, _) => { | ||||
|             if !check_bitmap_valid(offset, vec.len()) { | ||||
|                 return true; | ||||
|             } | ||||
|             let mut display = display_ref.write().unwrap(); | ||||
|             for bitmap_index in 0..vec.len() { | ||||
|                 let (x, y) = | ||||
|                     get_coordinates_for_index(offset as usize, bitmap_index); | ||||
|                 let old_value = display.get(x, y); | ||||
|                 display.set(x, y, old_value || vec.get(bitmap_index)); | ||||
|             } | ||||
|         } | ||||
|         Command::BitmapLinearXor(offset, vec, _) => { | ||||
|             if !check_bitmap_valid(offset, vec.len()) { | ||||
|                 return true; | ||||
|             } | ||||
|             let mut display = display_ref.write().unwrap(); | ||||
|             for bitmap_index in 0..vec.len() { | ||||
|                 let (x, y) = | ||||
|                     get_coordinates_for_index(offset as usize, bitmap_index); | ||||
|                 let old_value = display.get(x, y); | ||||
|                 display.set(x, y, old_value ^ vec.get(bitmap_index)); | ||||
|             } | ||||
|         } | ||||
|         Command::CharBrightness(origin, grid) => { | ||||
|             let Origin(offset_x, offset_y) = origin; | ||||
|             let offset_x = offset_x as usize; | ||||
|             let offset_y = offset_y as usize; | ||||
| 
 | ||||
|             let mut luma = luma_ref.write().unwrap(); | ||||
|             for inner_y in 0..grid.height { | ||||
|                 for inner_x in 0..grid.width { | ||||
|                     let brightness = grid.get(inner_x, inner_y); | ||||
|                     luma.set( | ||||
|                         offset_x + inner_x, | ||||
|                         offset_y + inner_y, | ||||
|                         brightness, | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         Command::Brightness(brightness) => { | ||||
|             luma_ref.write().unwrap().fill(brightness); | ||||
|         } | ||||
|         Command::FadeOut => { | ||||
|             error!("command not implemented: {command:?}") | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     true | ||||
| } | ||||
| 
 | ||||
| fn check_bitmap_valid(offset: u16, payload_len: usize) -> bool { | ||||
|     if offset as usize + payload_len > PIXEL_COUNT { | ||||
|         error!( | ||||
|             "bitmap with offset {offset} is too big ({} bytes)", | ||||
|             payload_len | ||||
|         ); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     true | ||||
| } | ||||
| 
 | ||||
| fn print_cp437_data( | ||||
|     origin: Origin, | ||||
|     grid: &ByteGrid, | ||||
|     font: &BitmapFont, | ||||
|     display: &mut RwLockWriteGuard<PixelGrid>, | ||||
| ) { | ||||
|     let Origin(x, y) = origin; | ||||
|     let x = x as usize; | ||||
|     let y = y as usize; | ||||
| 
 | ||||
|     for char_y in 0usize..grid.height { | ||||
|         for char_x in 0usize..grid.width { | ||||
|             let char_code = grid.get(char_x, char_y); | ||||
| 
 | ||||
|             let tile_x = char_x + x; | ||||
|             let tile_y = char_y + y; | ||||
| 
 | ||||
|             let bitmap = font.get_bitmap(char_code); | ||||
|             print_pixel_grid( | ||||
|                 tile_x * TILE_SIZE as usize, | ||||
|                 tile_y * TILE_SIZE as usize, | ||||
|                 bitmap, | ||||
|                 display, | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn print_pixel_grid( | ||||
|     offset_x: usize, | ||||
|     offset_y: usize, | ||||
|     pixels: &PixelGrid, | ||||
|     display: &mut RwLockWriteGuard<PixelGrid>, | ||||
| ) { | ||||
|     debug!( | ||||
|         "printing {}x{} grid at {offset_x} {offset_y}", | ||||
|         pixels.width, pixels.height | ||||
|     ); | ||||
|     for inner_y in 0..pixels.height { | ||||
|         for inner_x in 0..pixels.width { | ||||
|             let is_set = pixels.get(inner_x, inner_y); | ||||
|             display.set(offset_x + inner_x, offset_y + inner_y, is_set); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn get_coordinates_for_index(offset: usize, index: usize) -> (usize, usize) { | ||||
|     let pixel_index = offset + index; | ||||
|     ( | ||||
|         pixel_index % PIXEL_WIDTH as usize, | ||||
|         pixel_index / PIXEL_WIDTH as usize, | ||||
|     ) | ||||
| } | ||||
|  | @ -50,7 +50,7 @@ impl BitmapFont { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return BitmapFont { bitmaps }; | ||||
|         BitmapFont { bitmaps } | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_bitmap(&self, char_code: u8) -> &PixelGrid { | ||||
|  |  | |||
							
								
								
									
										198
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										198
									
								
								src/main.rs
									
										
									
									
									
								
							|  | @ -2,20 +2,22 @@ | |||
| 
 | ||||
| use std::io::ErrorKind; | ||||
| use std::net::UdpSocket; | ||||
| use std::sync::{mpsc, RwLock, RwLockWriteGuard}; | ||||
| use std::sync::{mpsc, RwLock}; | ||||
| use std::time::Duration; | ||||
| 
 | ||||
| use clap::Parser; | ||||
| use log::{debug, error, info, warn}; | ||||
| use log::{info, warn}; | ||||
| use servicepoint2::{ | ||||
|     ByteGrid, Command, Origin, Packet, PIXEL_COUNT, PIXEL_HEIGHT, PIXEL_WIDTH, | ||||
|     PixelGrid, TILE_HEIGHT, TILE_SIZE, TILE_WIDTH, | ||||
|     ByteGrid, Command, PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid, TILE_HEIGHT, | ||||
|     TILE_WIDTH, | ||||
| }; | ||||
| use winit::event_loop::{ControlFlow, EventLoop}; | ||||
| 
 | ||||
| use crate::execute_command::execute_command; | ||||
| use crate::font::BitmapFont; | ||||
| use crate::gui::{App, AppEvents}; | ||||
| 
 | ||||
| mod execute_command; | ||||
| mod font; | ||||
| mod gui; | ||||
| 
 | ||||
|  | @ -86,7 +88,15 @@ fn main() { | |||
|                 let vec = buf[..amount].to_vec(); | ||||
|                 let package = servicepoint2::Packet::from(vec); | ||||
| 
 | ||||
|                 if !handle_package(package, &font, display_ref, luma_ref) { | ||||
|                 let command = match Command::try_from(package) { | ||||
|                     Err(err) => { | ||||
|                         warn!("could not read command for packet: {:?}", err); | ||||
|                         continue; | ||||
|                     } | ||||
|                     Ok(val) => val, | ||||
|                 }; | ||||
| 
 | ||||
|                 if !execute_command(command, &font, display_ref, luma_ref) { | ||||
|                     // hard reset
 | ||||
|                     event_proxy | ||||
|                         .send_event(AppEvents::UdpThreadClosed) | ||||
|  | @ -107,181 +117,3 @@ fn main() { | |||
|         udp_thread.join().expect("could not join udp thread"); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| fn handle_package( | ||||
|     received: Packet, | ||||
|     font: &BitmapFont, | ||||
|     display_ref: &RwLock<PixelGrid>, | ||||
|     luma_ref: &RwLock<ByteGrid>, | ||||
| ) -> bool { | ||||
|     let command = match Command::try_from(received) { | ||||
|         Err(err) => { | ||||
|             warn!("could not read command for packet: {:?}", err); | ||||
|             return true; | ||||
|         } | ||||
|         Ok(val) => val, | ||||
|     }; | ||||
| 
 | ||||
|     debug!("received {command:?}"); | ||||
|     match command { | ||||
|         Command::Clear => { | ||||
|             info!("clearing display"); | ||||
|             display_ref.write().unwrap().fill(false); | ||||
|         } | ||||
|         Command::HardReset => { | ||||
|             warn!("display shutting down"); | ||||
|             return false; | ||||
|         } | ||||
|         Command::BitmapLinearWin(Origin(x, y), pixels) => { | ||||
|             let mut display = display_ref.write().unwrap(); | ||||
|             print_pixel_grid(x as usize, y as usize, &pixels, &mut display); | ||||
|         } | ||||
|         Command::Cp437Data(origin, grid) => { | ||||
|             let mut display = display_ref.write().unwrap(); | ||||
|             print_cp437_data(origin, &grid, font, &mut display); | ||||
|         } | ||||
|         #[allow(deprecated)] | ||||
|         Command::BitmapLegacy => { | ||||
|             warn!("ignoring deprecated command {:?}", command); | ||||
|         } | ||||
|         // TODO: how to deduplicate this code in a rusty way?
 | ||||
|         Command::BitmapLinear(offset, vec, _) => { | ||||
|             if !check_bitmap_valid(offset, vec.len()) { | ||||
|                 return true; | ||||
|             } | ||||
|             let mut display = display_ref.write().unwrap(); | ||||
|             for bitmap_index in 0..vec.len() { | ||||
|                 let (x, y) = | ||||
|                     get_coordinates_for_index(offset as usize, bitmap_index); | ||||
|                 display.set(x, y, vec.get(bitmap_index)); | ||||
|             } | ||||
|         } | ||||
|         Command::BitmapLinearAnd(offset, vec, _) => { | ||||
|             if !check_bitmap_valid(offset, vec.len()) { | ||||
|                 return true; | ||||
|             } | ||||
|             let mut display = display_ref.write().unwrap(); | ||||
|             for bitmap_index in 0..vec.len() { | ||||
|                 let (x, y) = | ||||
|                     get_coordinates_for_index(offset as usize, bitmap_index); | ||||
|                 let old_value = display.get(x, y); | ||||
|                 display.set(x, y, old_value && vec.get(bitmap_index)); | ||||
|             } | ||||
|         } | ||||
|         Command::BitmapLinearOr(offset, vec, _) => { | ||||
|             if !check_bitmap_valid(offset, vec.len()) { | ||||
|                 return true; | ||||
|             } | ||||
|             let mut display = display_ref.write().unwrap(); | ||||
|             for bitmap_index in 0..vec.len() { | ||||
|                 let (x, y) = | ||||
|                     get_coordinates_for_index(offset as usize, bitmap_index); | ||||
|                 let old_value = display.get(x, y); | ||||
|                 display.set(x, y, old_value || vec.get(bitmap_index)); | ||||
|             } | ||||
|         } | ||||
|         Command::BitmapLinearXor(offset, vec, _) => { | ||||
|             if !check_bitmap_valid(offset, vec.len()) { | ||||
|                 return true; | ||||
|             } | ||||
|             let mut display = display_ref.write().unwrap(); | ||||
|             for bitmap_index in 0..vec.len() { | ||||
|                 let (x, y) = | ||||
|                     get_coordinates_for_index(offset as usize, bitmap_index); | ||||
|                 let old_value = display.get(x, y); | ||||
|                 display.set(x, y, old_value ^ vec.get(bitmap_index)); | ||||
|             } | ||||
|         } | ||||
|         Command::CharBrightness(origin, grid) => { | ||||
|             let Origin(offset_x, offset_y) = origin; | ||||
|             let offset_x = offset_x as usize; | ||||
|             let offset_y = offset_y as usize; | ||||
| 
 | ||||
|             let mut luma = luma_ref.write().unwrap(); | ||||
|             for inner_y in 0..grid.height { | ||||
|                 for inner_x in 0..grid.width { | ||||
|                     let brightness = grid.get(inner_x, inner_y); | ||||
|                     luma.set( | ||||
|                         offset_x + inner_x, | ||||
|                         offset_y + inner_y, | ||||
|                         brightness, | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         Command::Brightness(brightness) => { | ||||
|             luma_ref.write().unwrap().fill(brightness); | ||||
|         } | ||||
|         Command::FadeOut => { | ||||
|             error!("command not implemented: {command:?}") | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     true | ||||
| } | ||||
| 
 | ||||
| fn check_bitmap_valid(offset: u16, payload_len: usize) -> bool { | ||||
|     if offset as usize + payload_len > PIXEL_COUNT { | ||||
|         error!( | ||||
|             "bitmap with offset {offset} is too big ({} bytes)", | ||||
|             payload_len | ||||
|         ); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     true | ||||
| } | ||||
| 
 | ||||
| fn print_cp437_data( | ||||
|     origin: Origin, | ||||
|     grid: &ByteGrid, | ||||
|     font: &BitmapFont, | ||||
|     display: &mut RwLockWriteGuard<PixelGrid>, | ||||
| ) { | ||||
|     let Origin(x, y) = origin; | ||||
|     let x = x as usize; | ||||
|     let y = y as usize; | ||||
| 
 | ||||
|     for char_y in 0usize..grid.height { | ||||
|         for char_x in 0usize..grid.width { | ||||
|             let char_code = grid.get(char_x, char_y); | ||||
| 
 | ||||
|             let tile_x = char_x + x; | ||||
|             let tile_y = char_y + y; | ||||
| 
 | ||||
|             let bitmap = font.get_bitmap(char_code); | ||||
|             print_pixel_grid( | ||||
|                 tile_x * TILE_SIZE as usize, | ||||
|                 tile_y * TILE_SIZE as usize, | ||||
|                 bitmap, | ||||
|                 display, | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn print_pixel_grid( | ||||
|     offset_x: usize, | ||||
|     offset_y: usize, | ||||
|     pixels: &PixelGrid, | ||||
|     display: &mut RwLockWriteGuard<PixelGrid>, | ||||
| ) { | ||||
|     debug!( | ||||
|         "printing {}x{} grid at {offset_x} {offset_y}", | ||||
|         pixels.width, pixels.height | ||||
|     ); | ||||
|     for inner_y in 0..pixels.height { | ||||
|         for inner_x in 0..pixels.width { | ||||
|             let is_set = pixels.get(inner_x, inner_y); | ||||
|             display.set(offset_x + inner_x, offset_y + inner_y, is_set); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn get_coordinates_for_index(offset: usize, index: usize) -> (usize, usize) { | ||||
|     let pixel_index = offset + index; | ||||
|     ( | ||||
|         pixel_index % PIXEL_WIDTH as usize, | ||||
|         pixel_index / PIXEL_WIDTH as usize, | ||||
|     ) | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vinzenz Schroeter
						Vinzenz Schroeter