mirror of
https://github.com/kaesaecracker/servicepoint-simulator.git
synced 2025-01-18 02:20:14 +01:00
move command execution code to own file
This commit is contained in:
parent
9f5d256963
commit
69502ac3fb
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…
Reference in a new issue