rich keyboard
This commit is contained in:
13
README.md
13
README.md
@@ -28,7 +28,11 @@ syntaxe supplémentaire supportée:
|
||||
- depuis le sous dossier simu
|
||||
`cargo run --release fichierentre`
|
||||
|
||||
Pour rajouter le support de multiplication/division: rajouter --features=div_mul
|
||||
## Features
|
||||
rajouter --features=[liste séparé par des virgules]
|
||||
- div_mul: Support des instruction de multiplication / division
|
||||
- rgba: Écran au format RGBA plutot que 0BGR
|
||||
- rich_keyboard: rajoute trois champs de mmio pour le clavier. Voir MMIO
|
||||
|
||||
### instruction spéciale:
|
||||
halt (jump 0) met le programme en pause, mais on peut se reveiller par des interuptions
|
||||
@@ -45,6 +49,13 @@ Passage au format RGBA (a pour alpha) avec la feature rgba
|
||||
- 0x01200010 : Position verticale de la souris (en pixels, -1 si hors de l'écran) (lecture seule)
|
||||
- 0x01201000 : Activation des Interupts de MMIO. Remis a zero par `dint`. Attention, Écrire ici sans activer les interruptions va bloquer les intéruptions et l'affichage (écriture seule)
|
||||
|
||||
|
||||
Si la feature rich_keyboard est active, tout en lecture seule:
|
||||
- 0x01200000 - 12 : Clavier : Representation ascii multichar de la touche pressé, modifié par Alt, Ctrl ... (eg ascii(a), ascii(A), ascii(^)<<8 | ascii(a))
|
||||
- 0x01200000 - 8 : Clavier Representation ascii multichar non modifié (eg ascii(a), ascii(\)<<8 | ascii(r))
|
||||
- 0x01200000 - 4: Clavier (press | repeat << 1) press: 1 si appuis, 0 si relache. repeat: 1 si l'appuis vient d'une répétition due a l'OS
|
||||
- 0x01200000 : Clavier (scancode, comme précédement) (lecture seule)
|
||||
|
||||
## Interuptions:
|
||||
Si les interruptions sont activées (avec eint), qu'il y a une raison de faire une interruption,
|
||||
et qu'on n'est pas déjà dans une routine d'interruption de priorité >=,
|
||||
|
||||
@@ -11,3 +11,5 @@ winit_input_helper = "0.17.0"
|
||||
|
||||
[features]
|
||||
div_mul = []
|
||||
rgba = []
|
||||
rich_keyboard = []
|
||||
|
||||
@@ -10,7 +10,7 @@ use std::{
|
||||
};
|
||||
|
||||
pub(crate) struct SharedState {
|
||||
pub(crate) keyboard: AtomicU32,
|
||||
pub(crate) keyboard: [AtomicU32; 4],
|
||||
pub(crate) screen_buf: [AtomicU32; 480 * 640],
|
||||
pub(crate) external_interupts: AtomicU32,
|
||||
pub(crate) external_enabled_interupts: AtomicU32,
|
||||
@@ -18,7 +18,7 @@ pub(crate) struct SharedState {
|
||||
}
|
||||
|
||||
pub(crate) static SHARED: SharedState = SharedState {
|
||||
keyboard: AtomicU32::new(0),
|
||||
keyboard: [const { AtomicU32::new(0) }; 4],
|
||||
screen_buf: [const { AtomicU32::new(0) }; 480 * 640],
|
||||
external_interupts: AtomicU32::new(0),
|
||||
external_enabled_interupts: AtomicU32::new(0),
|
||||
@@ -432,9 +432,17 @@ impl Computer {
|
||||
let buf_addr = (addr - 0x0100_0000) / 4;
|
||||
(&SHARED.screen_buf[buf_addr])
|
||||
.load(std::sync::atomic::Ordering::Relaxed)
|
||||
} else if 0x0120_0000 <= addr && addr <= 0x0120_0010 {
|
||||
match addr - 0x0120_0000 {
|
||||
0 => SHARED.keyboard.load(std::sync::atomic::Ordering::Relaxed),
|
||||
} else {
|
||||
match addr as isize - 0x0120_0000 {
|
||||
#[cfg(feature = "rich_keyboard")]
|
||||
-12 => {
|
||||
SHARED.keyboard[0].load(std::sync::atomic::Ordering::Relaxed)
|
||||
}
|
||||
#[cfg(feature = "rich_keyboard")]
|
||||
-8 => SHARED.keyboard[1].load(std::sync::atomic::Ordering::Relaxed),
|
||||
#[cfg(feature = "rich_keyboard")]
|
||||
-4 => SHARED.keyboard[2].load(std::sync::atomic::Ordering::Relaxed),
|
||||
0 => SHARED.keyboard[3].load(std::sync::atomic::Ordering::Relaxed),
|
||||
4 => time::Instant::now()
|
||||
.duration_since(self.creation)
|
||||
.as_millis() as u32,
|
||||
@@ -442,11 +450,11 @@ impl Computer {
|
||||
12 => SHARED.mouse[1].load(std::sync::atomic::Ordering::Relaxed),
|
||||
16 => SHARED.mouse[2].load(std::sync::atomic::Ordering::Relaxed),
|
||||
//guaranted by the inequality and is multiple of 4
|
||||
_ => unsafe { unreachable_unchecked() },
|
||||
_ => {
|
||||
self.serve_interupt(InteruptKind::IllegalOpcode, [next_opcode]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.serve_interupt(InteruptKind::IllegalOpcode, [next_opcode]);
|
||||
return;
|
||||
};
|
||||
}
|
||||
Instruction::Push(op2) => {
|
||||
@@ -506,7 +514,7 @@ impl Computer {
|
||||
match kind {
|
||||
InteruptKind::MMIO => {
|
||||
(&SHARED.external_interupts)
|
||||
.store(0, std::sync::atomic::Ordering::Relaxed);
|
||||
.store(0, std::sync::atomic::Ordering::Release);
|
||||
atomic_wait::wake_all(&SHARED.external_interupts);
|
||||
//no need to check prev because MMIO is the lowest priority
|
||||
self.interupts = InteruptState::Enabled
|
||||
|
||||
@@ -11,7 +11,7 @@ use std::hint::unlikely;
|
||||
use std::process::exit;
|
||||
use std::sync::{
|
||||
Arc,
|
||||
atomic::Ordering::{Relaxed, Release},
|
||||
atomic::Ordering::{Acquire, Relaxed, Release},
|
||||
};
|
||||
use std::thread::scope;
|
||||
use std::time::{Duration, Instant};
|
||||
@@ -21,6 +21,7 @@ use winit::application::ApplicationHandler;
|
||||
use winit::dpi::LogicalSize;
|
||||
use winit::event::WindowEvent;
|
||||
use winit::event_loop::EventLoop;
|
||||
use winit::platform::modifier_supplement::KeyEventExtModifierSupplement;
|
||||
use winit::platform::scancode::PhysicalKeyExtScancode;
|
||||
use winit::window::Window;
|
||||
// use winit_input_helper::WinitInputHelper;
|
||||
@@ -31,11 +32,11 @@ mod cpu;
|
||||
use cpu::SHARED;
|
||||
|
||||
fn wait_int() {
|
||||
let mut v = (&SHARED.external_interupts).load(Relaxed);
|
||||
let mut v = (&SHARED.external_interupts).load(Acquire);
|
||||
while unlikely(v != 0) {
|
||||
println!("wating for interupt clear {v}");
|
||||
atomic_wait::wait(&SHARED.external_interupts, v);
|
||||
v = (&SHARED.external_interupts).load(std::sync::atomic::Ordering::Relaxed);
|
||||
v = (&SHARED.external_interupts).load(Acquire);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +77,9 @@ impl<'a> ApplicationHandler for App<'a> {
|
||||
) {
|
||||
// Draw the current frame
|
||||
match event {
|
||||
WindowEvent::KeyboardInput { event, .. } => {
|
||||
WindowEvent::KeyboardInput {
|
||||
event: key_event, ..
|
||||
} => {
|
||||
let enabled = (&SHARED.external_enabled_interupts).load(Relaxed)
|
||||
& Into::<u32>::into(MMIOInterupt::Keyboard)
|
||||
!= 0;
|
||||
@@ -84,18 +87,31 @@ impl<'a> ApplicationHandler for App<'a> {
|
||||
if enabled {
|
||||
wait_int();
|
||||
}
|
||||
match event.state {
|
||||
winit::event::ElementState::Pressed => {
|
||||
if let Some(val) = event.physical_key.to_scancode() {
|
||||
cpu::SHARED
|
||||
.keyboard
|
||||
.store(val + 8, std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
winit::event::ElementState::Released => SHARED
|
||||
.keyboard
|
||||
.store(0, std::sync::atomic::Ordering::Relaxed),
|
||||
#[cfg(feature = "rich_keyboard")]
|
||||
{
|
||||
let txt = key_event
|
||||
.logical_key
|
||||
.to_text()
|
||||
.unwrap_or("")
|
||||
.as_bytes()
|
||||
.into_iter()
|
||||
.fold(0, |a, e| a << 8 | (*e as u32));
|
||||
SHARED.keyboard[0].store(txt, Relaxed);
|
||||
let txt = key_event
|
||||
.key_without_modifiers()
|
||||
.to_text()
|
||||
.unwrap_or("")
|
||||
.as_bytes()
|
||||
.into_iter()
|
||||
.fold(0, |a, e| a << 8 | (*e as u32));
|
||||
SHARED.keyboard[1].store(txt, Relaxed);
|
||||
SHARED.keyboard[2].store(
|
||||
key_event.state.is_pressed() as u32 | ((key_event.repeat as u32) << 1),
|
||||
Relaxed,
|
||||
);
|
||||
}
|
||||
SHARED.keyboard[3]
|
||||
.store(key_event.physical_key.to_scancode().unwrap_or(0), Relaxed);
|
||||
if enabled {
|
||||
(&SHARED.external_interupts).store(MMIOInterupt::Keyboard.into(), Release);
|
||||
atomic_wait::wake_all(&SHARED.external_interupts);
|
||||
@@ -105,7 +121,9 @@ impl<'a> ApplicationHandler for App<'a> {
|
||||
let enabled = (&SHARED.external_enabled_interupts).load(Relaxed)
|
||||
& Into::<u32>::into(MMIOInterupt::MouseMove)
|
||||
!= 0;
|
||||
if enabled {wait_int();}
|
||||
if enabled {
|
||||
wait_int();
|
||||
}
|
||||
match self
|
||||
.pixels
|
||||
.as_ref()
|
||||
@@ -113,10 +131,8 @@ impl<'a> ApplicationHandler for App<'a> {
|
||||
.window_pos_to_pixel((position.x as f32, position.y as f32))
|
||||
{
|
||||
Ok((x, y)) => {
|
||||
(&cpu::SHARED.mouse[1])
|
||||
.store(x as u32, Relaxed);
|
||||
(&cpu::SHARED.mouse[2])
|
||||
.store(y as u32, Relaxed);
|
||||
(&cpu::SHARED.mouse[1]).store(x as u32, Relaxed);
|
||||
(&cpu::SHARED.mouse[2]).store(y as u32, Relaxed);
|
||||
}
|
||||
Err(_) => {
|
||||
(&SHARED.mouse[1]).store(u32::MAX, Relaxed);
|
||||
@@ -137,7 +153,9 @@ impl<'a> ApplicationHandler for App<'a> {
|
||||
let enabled = (&SHARED.external_enabled_interupts).load(Relaxed)
|
||||
& Into::<u32>::into(MMIOInterupt::MouseClick)
|
||||
!= 0;
|
||||
if enabled {wait_int();}
|
||||
if enabled {
|
||||
wait_int();
|
||||
}
|
||||
let but = 1
|
||||
<< match button {
|
||||
winit::event::MouseButton::Left => 0,
|
||||
@@ -177,8 +195,16 @@ impl<'a> ApplicationHandler for App<'a> {
|
||||
|
||||
let screen = pix.frame_mut();
|
||||
for (addr, ubgr) in cpu::SHARED.screen_buf.iter().enumerate() {
|
||||
let ubgr = ubgr.load(std::sync::atomic::Ordering::Relaxed);
|
||||
let rgba = [ubgr as u8, (ubgr >> 8) as u8, (ubgr >> 16) as u8, 0xff];
|
||||
let raw = ubgr.load(std::sync::atomic::Ordering::Relaxed);
|
||||
#[cfg(not(feature = "rgba"))]
|
||||
let rgba = [raw as u8, (raw >> 8) as u8, (raw >> 16) as u8, 0xff];
|
||||
#[cfg(feature = "rgba")]
|
||||
let rgba = [
|
||||
(raw >> 24) as u8,
|
||||
(raw >> 16) as u8,
|
||||
(raw >> 8) as u8,
|
||||
raw as u8,
|
||||
];
|
||||
for i in 0..4 {
|
||||
screen[addr * 4 + i] = rgba[i];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user