This repository has been archived on 2024-06-01. You can view files and clone it, but cannot push or open issues or pull requests.
rustboyadvance-ng/core/src/interrupt.rs
Michel Heily a3546cbe07 Run cargo-fmt
Former-commit-id: b0a8fe8948fe8affe3377acf0c72af8d78717789
Former-commit-id: fee6919ea7cf16c5bf6e1bd21b993770cc08998f
2020-10-17 06:36:02 -07:00

115 lines
3.1 KiB
Rust

use std::cell::Cell;
use std::rc::Rc;
use serde::{Deserialize, Serialize};
pub trait InterruptConnect {
// Connect a SharedInterruptFlags to this interrupt source
fn connect_irq(&mut self, interrupt_flags: SharedInterruptFlags);
}
#[derive(Serialize, Deserialize, Debug, Primitive, Copy, Clone, PartialEq)]
#[allow(non_camel_case_types)]
pub enum Interrupt {
LCD_VBlank = 0,
LCD_HBlank = 1,
LCD_VCounterMatch = 2,
Timer0_Overflow = 3,
Timer1_Overflow = 4,
Timer2_Overflow = 5,
Timer3_Overflow = 6,
SerialCommunication = 7,
DMA0 = 8,
DMA1 = 9,
DMA2 = 10,
DMA3 = 11,
Keypad = 12,
GamePak = 13,
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct InterruptController {
pub interrupt_master_enable: bool,
pub interrupt_enable: IrqBitmask,
pub interrupt_flags: SharedInterruptFlags,
}
impl InterruptController {
pub fn new(interrupt_flags: SharedInterruptFlags) -> InterruptController {
InterruptController {
interrupt_flags,
interrupt_master_enable: false,
..Default::default()
}
}
#[inline]
pub fn irq_pending(&self) -> bool {
self.interrupt_master_enable
& ((self.interrupt_flags.get().value() & self.interrupt_enable.0) != 0)
}
#[inline]
pub fn clear(&mut self, value: u16) {
let _if = self.interrupt_flags.get();
let new_if = _if.0 & !value;
self.interrupt_flags.set(IrqBitmask(new_if));
}
}
impl InterruptConnect for InterruptController {
fn connect_irq(&mut self, interrupt_flags: SharedInterruptFlags) {
self.interrupt_flags = interrupt_flags;
}
}
#[inline]
pub fn signal_irq(interrupt_flags: &SharedInterruptFlags, i: Interrupt) {
let _if = interrupt_flags.get();
let new_if = _if.0 | 1 << (i as usize);
interrupt_flags.set(IrqBitmask(new_if));
}
impl IrqBitmask {
pub fn value(&self) -> u16 {
self.0
}
}
bitfield! {
#[derive(Serialize, Deserialize, Default, Copy, Clone, PartialEq)]
pub struct IrqBitmask(u16);
impl Debug;
u16;
#[allow(non_snake_case)]
pub LCD_VBlank, set_LCD_VBlank: 0;
#[allow(non_snake_case)]
pub LCD_HBlank, set_LCD_HBlank: 1;
#[allow(non_snake_case)]
pub LCD_VCounterMatch, set_LCD_VCounterMatch: 2;
#[allow(non_snake_case)]
pub Timer0_Overflow, set_Timer0_Overflow: 3;
#[allow(non_snake_case)]
pub Timer1_Overflow, set_Timer1_Overflow: 4;
#[allow(non_snake_case)]
pub Timer2_Overflow, set_Timer2_Overflow: 5;
#[allow(non_snake_case)]
pub Timer3_Overflow, set_Timer3_Overflow: 6;
#[allow(non_snake_case)]
pub SerialCommunication, set_SerialCommunication: 7;
#[allow(non_snake_case)]
pub DMA0, set_DMA0: 8;
#[allow(non_snake_case)]
pub DMA1, set_DMA1: 9;
#[allow(non_snake_case)]
pub DMA2, set_DMA2: 10;
#[allow(non_snake_case)]
pub DMA3, set_DMA3: 11;
#[allow(non_snake_case)]
pub Keypad, set_Keypad: 12;
#[allow(non_snake_case)]
pub GamePak, set_GamePak: 13;
}
pub type SharedInterruptFlags = Rc<Cell<IrqBitmask>>;