gba/
interrupts.rs

1use crate::macros::{pub_const_fn_new_zeroed, u16_bool_field, u16_enum_field};
2
3/// A function you want called during an interrupt.
4pub type IrqFn = unsafe extern "C" fn(IrqBits);
5
6#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
7#[repr(transparent)]
8pub struct IrqBits(u16);
9impl IrqBits {
10  pub_const_fn_new_zeroed!();
11  u16_bool_field!(0, vblank, with_vblank);
12  u16_bool_field!(1, hblank, with_hblank);
13  u16_bool_field!(2, vcounter, with_vcounter);
14  u16_bool_field!(3, timer0, with_timer0);
15  u16_bool_field!(4, timer1, with_timer1);
16  u16_bool_field!(5, timer2, with_timer2);
17  u16_bool_field!(6, timer3, with_timer3);
18  u16_bool_field!(7, serial, with_serial);
19  u16_bool_field!(8, dma0, with_dma0);
20  u16_bool_field!(9, dma1, with_dma1);
21  u16_bool_field!(10, dma2, with_dma2);
22  u16_bool_field!(11, dma3, with_dma3);
23  u16_bool_field!(12, keypad, with_keypad);
24  u16_bool_field!(13, gamepak, with_gamepak);
25
26  pub const VBLANK: Self = Self::new().with_vblank(true);
27  pub const HBLANK: Self = Self::new().with_hblank(true);
28  pub const VCOUNTER: Self = Self::new().with_vcounter(true);
29  pub const TIMER0: Self = Self::new().with_timer0(true);
30  pub const TIMER1: Self = Self::new().with_timer1(true);
31  pub const TIMER2: Self = Self::new().with_timer2(true);
32  pub const TIMER3: Self = Self::new().with_timer3(true);
33  pub const SERIAL: Self = Self::new().with_serial(true);
34  pub const DMA0: Self = Self::new().with_dma0(true);
35  pub const DMA1: Self = Self::new().with_dma1(true);
36  pub const DMA2: Self = Self::new().with_dma2(true);
37  pub const DMA3: Self = Self::new().with_dma3(true);
38  pub const KEYPAD: Self = Self::new().with_keypad(true);
39  pub const GAMEPAK: Self = Self::new().with_gamepak(true);
40
41  #[inline]
42  #[must_use]
43  pub const fn to_u16(self) -> u16 {
44    self.0
45  }
46}
47
48#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
49#[repr(transparent)]
50pub struct WaitstateControl(pub u16);
51impl WaitstateControl {
52  pub_const_fn_new_zeroed!();
53  u16_enum_field!(0 - 1: SramFirstAccess, sram, with_sram);
54  u16_enum_field!(
55    2 - 3:
56    Waitstate0FirstAccess,
57    ws0_first_access,
58    with_ws0_first_access
59  );
60  // true = 2, false = 1
61  u16_bool_field!(4, ws0_second_access, with_ws0_second_access);
62  u16_enum_field!(
63    5 - 6:
64    Waitstate1FirstAccess,
65    ws1_first_access,
66    with_ws1_first_access
67  );
68  // true = 4, false = 1
69  u16_bool_field!(7, ws1_second_access, with_ws1_second_access);
70  u16_enum_field!(
71    8 - 9:
72    Waitstate2FirstAccess,
73    ws2_first_access,
74    with_ws2_first_access
75  );
76  // true = 8, false = 1
77  u16_bool_field!(10, ws2_second_access, with_ws2_second_access);
78  u16_enum_field!(
79    11 - 12:
80    PhiTerminalOutput,
81    phi_terminal_output,
82    with_phi_terminal_output
83  );
84  u16_bool_field!(14, game_pak_prefetch_buffer, with_game_pak_prefetch_buffer);
85  u16_bool_field!(15, game_pak_is_cgb, with_game_pak_is_cgb);
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq)]
89#[repr(u16)]
90pub enum SramFirstAccess {
91  Cycles4 = 0,
92  Cycles3 = 1,
93  Cycles2 = 2,
94  Cycles8 = 3,
95}
96#[derive(Debug, Clone, Copy, PartialEq, Eq)]
97#[repr(u16)]
98pub enum Waitstate0FirstAccess {
99  Cycles4 = 0 << 2,
100  Cycles3 = 1 << 2,
101  Cycles2 = 2 << 2,
102  Cycles8 = 3 << 2,
103}
104#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105#[repr(u16)]
106pub enum Waitstate1FirstAccess {
107  Cycles4 = 0 << 5,
108  Cycles3 = 1 << 5,
109  Cycles2 = 2 << 5,
110  Cycles8 = 3 << 5,
111}
112#[derive(Debug, Clone, Copy, PartialEq, Eq)]
113#[repr(u16)]
114pub enum Waitstate2FirstAccess {
115  Cycles4 = 0 << 8,
116  Cycles3 = 1 << 8,
117  Cycles2 = 2 << 8,
118  Cycles8 = 3 << 8,
119}
120#[derive(Debug, Clone, Copy, PartialEq, Eq)]
121#[repr(u16)]
122pub enum PhiTerminalOutput {
123  Disabled = 0 << 11,
124  Freq4MHz = 1 << 11,
125  Freq8MHz = 2 << 11,
126  Freq16MHz = 3 << 11,
127}
128
129// TODO: might want to support bit ops. But it's not super important right now
130// since they can't be implented as const traits yet anyway.