2020-01-16 18:06:22 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Primitive, Copy, Clone, PartialEq)]
|
2019-07-06 13:53:36 +01:00
|
|
|
#[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,
|
|
|
|
}
|
|
|
|
|
2020-01-16 18:06:22 +00:00
|
|
|
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
2019-08-02 22:18:59 +01:00
|
|
|
pub struct InterruptController {
|
|
|
|
pub interrupt_master_enable: bool,
|
2019-08-05 07:44:27 +01:00
|
|
|
pub interrupt_enable: IrqBitmask,
|
|
|
|
pub interrupt_flags: IrqBitmask,
|
2019-08-02 22:18:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl InterruptController {
|
|
|
|
pub fn new() -> InterruptController {
|
|
|
|
InterruptController {
|
|
|
|
interrupt_master_enable: false,
|
2019-08-05 07:44:27 +01:00
|
|
|
..Default::default()
|
2019-08-02 22:18:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-05 07:44:27 +01:00
|
|
|
pub fn request_irqs(&mut self, flags: IrqBitmask) {
|
2019-11-11 01:35:16 +00:00
|
|
|
self.interrupt_flags.0 |= flags.0;
|
2019-08-05 07:44:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn irq_pending(&self) -> bool {
|
2019-11-11 01:35:16 +00:00
|
|
|
self.interrupt_master_enable & ((self.interrupt_flags.0 & self.interrupt_enable.0) != 0)
|
2019-08-02 22:18:59 +01:00
|
|
|
}
|
|
|
|
}
|
2019-08-05 07:44:27 +01:00
|
|
|
|
|
|
|
impl IrqBitmask {
|
|
|
|
pub fn add_irq(&mut self, i: Interrupt) {
|
|
|
|
self.0 |= 1 << (i as usize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bitfield! {
|
2020-01-16 18:06:22 +00:00
|
|
|
#[derive(Serialize, Deserialize, Default, Copy, Clone, PartialEq)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub struct IrqBitmask(u16);
|
|
|
|
impl Debug;
|
|
|
|
u16;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub LCD_VBlank, set_LCD_VBlank: 0;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub LCD_HBlank, set_LCD_HBlank: 1;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub LCD_VCounterMatch, set_LCD_VCounterMatch: 2;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub Timer0_Overflow, set_Timer0_Overflow: 3;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub Timer1_Overflow, set_Timer1_Overflow: 4;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub Timer2_Overflow, set_Timer2_Overflow: 5;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub Timer3_Overflow, set_Timer3_Overflow: 6;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub SerialCommunication, set_SerialCommunication: 7;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub DMA0, set_DMA0: 8;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub DMA1, set_DMA1: 9;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub DMA2, set_DMA2: 10;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub DMA3, set_DMA3: 11;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub Keypad, set_Keypad: 12;
|
2019-08-13 19:57:45 +01:00
|
|
|
#[allow(non_snake_case)]
|
2019-08-05 07:44:27 +01:00
|
|
|
pub GamePak, set_GamePak: 13;
|
|
|
|
}
|