From 120a27e00e717d8d9ba10cd3d9d7abcc280f5734 Mon Sep 17 00:00:00 2001 From: Atreya Bain Date: Fri, 14 Feb 2025 08:51:59 +0000 Subject: [PATCH] Add keycode configuration and cpu throttling --- src/device/device.rs | 21 ++++++++++-- src/device/keyboard.rs | 27 +++++++++++---- src/kb_map.rs | 24 -------------- src/main.rs | 14 +++----- src/sdl_adapters/sdl_keyboard_adapter.rs | 42 +++++++++++++++++++----- 5 files changed, 78 insertions(+), 50 deletions(-) delete mode 100644 src/kb_map.rs diff --git a/src/device/device.rs b/src/device/device.rs index 7080532..3a853e2 100644 --- a/src/device/device.rs +++ b/src/device/device.rs @@ -4,6 +4,8 @@ use crate::device::timer::DeviceTimerManager; use crate::util::EmulatorResult; use rand::random; use std::sync::{Arc, Mutex}; +use std::thread::sleep; +use std::time::Duration; pub struct Device { pub registers: RegisterFile, @@ -52,15 +54,30 @@ impl Device { const FONT_DEFAULT_MEM_LOCATION_END: usize = 0x9F; const ROM_START: usize = 0x200; + // Throttling configuration for cpu + const DO_CHIP_CPU_THROTTLING:bool = true; + const TARGET_CPU_SPEED_INSTRUCTIONS_PER_SECOND: u64 = 800; + const TARGET_CPU_INSTRUCTION_TIME: Duration = Duration::from_millis(1000/Self::TARGET_CPU_SPEED_INSTRUCTIONS_PER_SECOND); + pub fn cycle(&mut self) -> EmulatorResult<()> { - self.device_keyboard.update_keyboard()?; + let time_start = std::time::Instant::now(); + self.device_keyboard.update_keyboard_registers()?; let pc = self.registers.pc as usize; let instr_slice = self.memory.get(pc..pc + 2).expect("Failed to get memory"); self.registers.pc += 2; let instruction = Instruction::decode_instruction(instr_slice); - self.execute_instruction(instruction) + self.execute_instruction(instruction)?; + + let instruction_time = time_start.elapsed(); + let time_left_to_sleep_for_instruction = Self::TARGET_CPU_INSTRUCTION_TIME.checked_sub(instruction_time).unwrap_or(Duration::ZERO); + if Self::DO_CHIP_CPU_THROTTLING { + log::trace!("Instruction took {:?}, left with {:?}",instruction_time,time_left_to_sleep_for_instruction); + sleep(time_left_to_sleep_for_instruction); + } + + Ok(()) } /// convert the 2 indices into one fn get_framebuffer_index(x: usize, y: usize) -> usize { diff --git a/src/device/keyboard.rs b/src/device/keyboard.rs index 45bbc59..562e41b 100644 --- a/src/device/keyboard.rs +++ b/src/device/keyboard.rs @@ -9,11 +9,15 @@ pub struct Keyboard { /// Receives keyboard events from main thread keyboard_event_receiver: std::sync::mpsc::Receiver, } +#[derive(Eq,PartialEq, PartialOrd, Clone, Copy, Debug)] +pub enum Key{ + K0=0,K1,K2,K3,K4,K5,K6,K7,K8,K9,KA,KB,KC,KD,KE,KF +} #[derive(Clone, Debug, Eq, PartialEq)] pub enum KeyboardEvent { - KeyUp(u8), - KeyDown(u8), + KeyUp(Key), + KeyDown(Key), } impl Keyboard { @@ -26,7 +30,7 @@ impl Keyboard { /// Update keyboard based on pending keyboard events. /// If no events are presents, it will return without any action. - pub fn update_keyboard(&mut self) -> EmulatorResult<()> { + pub fn update_keyboard_registers(&mut self) -> EmulatorResult<()> { loop { let keyboard_event_recv_res = self.keyboard_event_receiver.try_recv(); match keyboard_event_recv_res { @@ -52,11 +56,22 @@ impl Keyboard { fn update_keyboard_state(&mut self, keyboard_event: KeyboardEvent) { match keyboard_event { KeyboardEvent::KeyUp(key) => { - self.bitflags &= !((1 << key) as u16); + self.bitflags &= !((1u16 << (key as u16)) as u16); } KeyboardEvent::KeyDown(key) => { - self.bitflags |= 1 << key; + self.bitflags |= 1 << (key as u16); } } } -} \ No newline at end of file +} + +#[cfg(test)] +mod tests { + use super::Key; + + #[test] + fn test_key_assignment(){ + assert_eq!(0,Key::K0 as u16); + assert_eq!(15,Key::KF as u16); + } +} diff --git a/src/kb_map.rs b/src/kb_map.rs deleted file mode 100644 index bddcd0c..0000000 --- a/src/kb_map.rs +++ /dev/null @@ -1,24 +0,0 @@ -use sdl2::keyboard::Keycode; - -/// get index of key pressed. 0..9+A..F provides a u8 -pub fn get_key_index(p0: Keycode) -> Option { - match p0 { - Keycode::Kp0 => Some(0x0), - Keycode::Kp1 => Some(0x1), - Keycode::Kp2 => Some(0x2), - Keycode::Kp3 => Some(0x3), - Keycode::Kp4 => Some(0x4), - Keycode::Kp5 => Some(0x5), - Keycode::Kp6 => Some(0x6), - Keycode::Kp7 => Some(0x7), - Keycode::Kp8 => Some(0x8), - Keycode::Kp9 => Some(0x9), - Keycode::A => Some(0xA), - Keycode::B => Some(0xB), - Keycode::C => Some(0xC), - Keycode::D => Some(0xD), - Keycode::E => Some(0xE), - Keycode::F => Some(0xF), - _ => None - } -} diff --git a/src/main.rs b/src/main.rs index 8f8e60c..939bb9a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,14 +19,12 @@ use crate::args::Porcel8ProgramArgs; use crate::device::Device; use crate::util::EmulatorResult; -use crate::kb_map::get_key_index; use crate::sdl_adapters::sdl_audio_adapter::SdlAudioAdapter; use crate::sdl_adapters::sdl_graphics_adapter::SdlGraphicsAdapter; use crate::sdl_adapters::sdl_keyboard_adapter::SdlKeyboardAdapter; mod args; mod device; -mod kb_map; mod util; mod sdl_adapters; mod rom; @@ -68,15 +66,11 @@ fn main() -> EmulatorResult<()> { device_termination_signal_sender.send(()).expect("Could not send"); break 'running; } - Event::KeyDown { keycode: Some(x), repeat: false, .. } => { - if let Some(key_val) = get_key_index(x) { - sdl_kb_adapter.send_key_down(key_val)?; - } + Event::KeyDown { keycode: Some(keycode), repeat: false, .. } => { + sdl_kb_adapter.process_key_down(keycode)?; } - Event::KeyUp { keycode: Some(x), repeat: false, .. } => { - if let Some(key_val) = get_key_index(x) { - sdl_kb_adapter.send_key_up(key_val)?; - } + Event::KeyUp { keycode: Some(keycode), repeat: false, .. } => { + sdl_kb_adapter.process_key_up(keycode)?; } _ => {} } diff --git a/src/sdl_adapters/sdl_keyboard_adapter.rs b/src/sdl_adapters/sdl_keyboard_adapter.rs index 572f5e0..2b0962a 100644 --- a/src/sdl_adapters/sdl_keyboard_adapter.rs +++ b/src/sdl_adapters/sdl_keyboard_adapter.rs @@ -1,5 +1,5 @@ use std::sync::mpsc::Sender; -use crate::device::keyboard::{Keyboard, KeyboardEvent}; +use crate::device::keyboard::{Key, Keyboard, KeyboardEvent}; use crate::device::keyboard::KeyboardEvent::{KeyDown, KeyUp}; use crate::util::EmulatorResult; @@ -22,15 +22,41 @@ impl SdlKeyboardAdapter { (sdl2_kb_adapter,device_kb) } - pub fn send_key_up(&self, keycode: u8) -> EmulatorResult { - log::trace!("Sending Key up {}",keycode); - self.keyboard_event_sender.send(KeyUp(keycode))?; - Ok(keycode) + pub fn process_key_up(&self, keycode: sdl2::keyboard::Keycode) -> EmulatorResult<()> { + log::debug!("Sending Key up {}",keycode); + if let Some(key) = Self::keycode_to_key(keycode){ + self.keyboard_event_sender.send(KeyUp(key))?; + } + Ok(()) } - pub fn send_key_down(&self, keycode: u8) -> EmulatorResult { + pub fn process_key_down(&self, keycode: sdl2::keyboard::Keycode) -> EmulatorResult<()> { log::trace!("Sending Key down {}",keycode); - self.keyboard_event_sender.send(KeyDown(keycode))?; - Ok(keycode) + if let Some(key) = Self::keycode_to_key(keycode){ + self.keyboard_event_sender.send(KeyDown(key))?; + } + Ok(()) + } + /// Key map configuration + pub fn keycode_to_key(keycode: sdl2::keyboard::Keycode) -> Option{ + match keycode { + sdl2::keyboard::Keycode::X=>Some(Key::K0), + sdl2::keyboard::Keycode::Num1=>Some(Key::K1), + sdl2::keyboard::Keycode::Num2=>Some(Key::K2), + sdl2::keyboard::Keycode::Num3=>Some(Key::K3), + sdl2::keyboard::Keycode::Q=>Some(Key::K4), + sdl2::keyboard::Keycode::W=>Some(Key::K5), + sdl2::keyboard::Keycode::E=>Some(Key::K6), + sdl2::keyboard::Keycode::A=>Some(Key::K7), + sdl2::keyboard::Keycode::S=>Some(Key::K8), + sdl2::keyboard::Keycode::D=>Some(Key::K9), + sdl2::keyboard::Keycode::Z=>Some(Key::KA), + sdl2::keyboard::Keycode::C=>Some(Key::KB), + sdl2::keyboard::Keycode::Num4=>Some(Key::KC), + sdl2::keyboard::Keycode::R=>Some(Key::KD), + sdl2::keyboard::Keycode::F=>Some(Key::KE), + sdl2::keyboard::Keycode::V=>Some(Key::KF), + _=>None + } } }