feat(input): implement KEYCNT keypad interrupt control
Add a dependency-free keypad state machine in gba-core, map KEYCNT, latch IF bit 12, and wake HALT through the existing interrupt gates. Sample complete CPU/DMA control writes once so transient byte values cannot create false requests. Document the mGBA-style polling policy and its unverified hardware retrigger limits. Cover every button-state/selection pair, register masks, repeated requests, byte/word writes, failed-store isolation, DMA priority, ARM/Thumb IRQ return, BIOS IntrWait, and retained BIOS reset state. Follow the restructured workspace and modular documentation. Validated on Darwin arm64: workspace and core/demo tests pass in debug and release, with Clippy, rustdoc, ten native window smoke tests, and terminal demos passing.
This commit is contained in:
parent
7d396fea35
commit
597b02881b
14 changed files with 710 additions and 21 deletions
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
display::{DisplayPosition, CYCLES_PER_LINE, HBLANK_START, VISIBLE_LINES},
|
||||
dma::{DmaError, DMA_BASE, DMA_END},
|
||||
input::Buttons,
|
||||
io::{Io, HALTCNT, POSTFLG},
|
||||
io::{Io, HALTCNT, KEYINPUT, POSTFLG},
|
||||
timing::{bus_cycles, AccessKind, AccessWidth, DataTiming, StepTiming},
|
||||
video::{self, sprites::pipeline, Framebuffer, VideoError},
|
||||
};
|
||||
|
|
@ -325,7 +325,8 @@ impl Memory {
|
|||
}
|
||||
|
||||
/// Replace the current pressed-button state. This does not advance time.
|
||||
/// KEYCNT and keypad interrupts are not implemented yet.
|
||||
/// Sample KEYCNT and latch a matching keypad IRQ immediately, without cycles.
|
||||
/// This can wake HALT; CPU IRQ delivery occurs on a later Machine::step.
|
||||
pub fn set_buttons(&mut self, buttons: Buttons) {
|
||||
self.io.set_buttons(buttons);
|
||||
}
|
||||
|
|
@ -424,6 +425,10 @@ impl Memory {
|
|||
},
|
||||
);
|
||||
if address >> 24 == 0x04 {
|
||||
if address & !3 == KEYINPUT {
|
||||
self.io.write_keypad(address, &bytes);
|
||||
return Ok(());
|
||||
}
|
||||
for (offset, byte) in bytes.into_iter().enumerate() {
|
||||
let byte_address = address + offset as u32;
|
||||
if matches!(byte_address, POSTFLG | HALTCNT) && !self.can_write_power_control() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue