Add keycode configuration and cpu throttling

This commit is contained in:
2025-02-14 08:51:59 +00:00
parent 462a447489
commit 120a27e00e
5 changed files with 78 additions and 50 deletions

View File

@@ -4,6 +4,8 @@ use crate::device::timer::DeviceTimerManager;
use crate::util::EmulatorResult; use crate::util::EmulatorResult;
use rand::random; use rand::random;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread::sleep;
use std::time::Duration;
pub struct Device { pub struct Device {
pub registers: RegisterFile, pub registers: RegisterFile,
@@ -52,15 +54,30 @@ impl Device {
const FONT_DEFAULT_MEM_LOCATION_END: usize = 0x9F; const FONT_DEFAULT_MEM_LOCATION_END: usize = 0x9F;
const ROM_START: usize = 0x200; 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<()> { 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 pc = self.registers.pc as usize;
let instr_slice = self.memory.get(pc..pc + 2).expect("Failed to get memory"); let instr_slice = self.memory.get(pc..pc + 2).expect("Failed to get memory");
self.registers.pc += 2; self.registers.pc += 2;
let instruction = Instruction::decode_instruction(instr_slice); 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 /// convert the 2 indices into one
fn get_framebuffer_index(x: usize, y: usize) -> usize { fn get_framebuffer_index(x: usize, y: usize) -> usize {

View File

@@ -9,11 +9,15 @@ pub struct Keyboard {
/// Receives keyboard events from main thread /// Receives keyboard events from main thread
keyboard_event_receiver: std::sync::mpsc::Receiver<KeyboardEvent>, keyboard_event_receiver: std::sync::mpsc::Receiver<KeyboardEvent>,
} }
#[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)] #[derive(Clone, Debug, Eq, PartialEq)]
pub enum KeyboardEvent { pub enum KeyboardEvent {
KeyUp(u8), KeyUp(Key),
KeyDown(u8), KeyDown(Key),
} }
impl Keyboard { impl Keyboard {
@@ -26,7 +30,7 @@ impl Keyboard {
/// Update keyboard based on pending keyboard events. /// Update keyboard based on pending keyboard events.
/// If no events are presents, it will return without any action. /// 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 { loop {
let keyboard_event_recv_res = self.keyboard_event_receiver.try_recv(); let keyboard_event_recv_res = self.keyboard_event_receiver.try_recv();
match keyboard_event_recv_res { match keyboard_event_recv_res {
@@ -52,11 +56,22 @@ impl Keyboard {
fn update_keyboard_state(&mut self, keyboard_event: KeyboardEvent) { fn update_keyboard_state(&mut self, keyboard_event: KeyboardEvent) {
match keyboard_event { match keyboard_event {
KeyboardEvent::KeyUp(key) => { KeyboardEvent::KeyUp(key) => {
self.bitflags &= !((1 << key) as u16); self.bitflags &= !((1u16 << (key as u16)) as u16);
} }
KeyboardEvent::KeyDown(key) => { KeyboardEvent::KeyDown(key) => {
self.bitflags |= 1 << key; self.bitflags |= 1 << (key as u16);
} }
} }
} }
} }
#[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);
}
}

View File

@@ -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<u8> {
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
}
}

View File

@@ -19,14 +19,12 @@ use crate::args::Porcel8ProgramArgs;
use crate::device::Device; use crate::device::Device;
use crate::util::EmulatorResult; use crate::util::EmulatorResult;
use crate::kb_map::get_key_index;
use crate::sdl_adapters::sdl_audio_adapter::SdlAudioAdapter; use crate::sdl_adapters::sdl_audio_adapter::SdlAudioAdapter;
use crate::sdl_adapters::sdl_graphics_adapter::SdlGraphicsAdapter; use crate::sdl_adapters::sdl_graphics_adapter::SdlGraphicsAdapter;
use crate::sdl_adapters::sdl_keyboard_adapter::SdlKeyboardAdapter; use crate::sdl_adapters::sdl_keyboard_adapter::SdlKeyboardAdapter;
mod args; mod args;
mod device; mod device;
mod kb_map;
mod util; mod util;
mod sdl_adapters; mod sdl_adapters;
mod rom; mod rom;
@@ -68,15 +66,11 @@ fn main() -> EmulatorResult<()> {
device_termination_signal_sender.send(()).expect("Could not send"); device_termination_signal_sender.send(()).expect("Could not send");
break 'running; break 'running;
} }
Event::KeyDown { keycode: Some(x), repeat: false, .. } => { Event::KeyDown { keycode: Some(keycode), repeat: false, .. } => {
if let Some(key_val) = get_key_index(x) { sdl_kb_adapter.process_key_down(keycode)?;
sdl_kb_adapter.send_key_down(key_val)?;
}
} }
Event::KeyUp { keycode: Some(x), repeat: false, .. } => { Event::KeyUp { keycode: Some(keycode), repeat: false, .. } => {
if let Some(key_val) = get_key_index(x) { sdl_kb_adapter.process_key_up(keycode)?;
sdl_kb_adapter.send_key_up(key_val)?;
}
} }
_ => {} _ => {}
} }

View File

@@ -1,5 +1,5 @@
use std::sync::mpsc::Sender; 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::device::keyboard::KeyboardEvent::{KeyDown, KeyUp};
use crate::util::EmulatorResult; use crate::util::EmulatorResult;
@@ -22,15 +22,41 @@ impl SdlKeyboardAdapter {
(sdl2_kb_adapter,device_kb) (sdl2_kb_adapter,device_kb)
} }
pub fn send_key_up(&self, keycode: u8) -> EmulatorResult<u8> { pub fn process_key_up(&self, keycode: sdl2::keyboard::Keycode) -> EmulatorResult<()> {
log::trace!("Sending Key up {}",keycode); log::debug!("Sending Key up {}",keycode);
self.keyboard_event_sender.send(KeyUp(keycode))?; if let Some(key) = Self::keycode_to_key(keycode){
Ok(keycode) self.keyboard_event_sender.send(KeyUp(key))?;
}
Ok(())
} }
pub fn send_key_down(&self, keycode: u8) -> EmulatorResult<u8> { pub fn process_key_down(&self, keycode: sdl2::keyboard::Keycode) -> EmulatorResult<()> {
log::trace!("Sending Key down {}",keycode); log::trace!("Sending Key down {}",keycode);
self.keyboard_event_sender.send(KeyDown(keycode))?; if let Some(key) = Self::keycode_to_key(keycode){
Ok(keycode) self.keyboard_event_sender.send(KeyDown(key))?;
}
Ok(())
}
/// Key map configuration
pub fn keycode_to_key(keycode: sdl2::keyboard::Keycode) -> Option<Key>{
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
}
} }
} }