Add keycode configuration and cpu throttling
This commit is contained in:
@@ -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 {
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
14
src/main.rs
14
src/main.rs
@@ -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)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user