tetanes_core/mapper/
vrc_irq.rs1use crate::{
6 common::{Clock, Reset, ResetKind},
7 cpu::{Cpu, Irq},
8};
9use serde::{Deserialize, Serialize};
10
11#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize)]
12#[must_use]
13pub struct VrcIrq {
14 pub reload: u8,
15 pub counter: u8,
16 pub prescalar_counter: i16,
17 pub enabled: bool,
18 pub enabled_after_ack: bool,
19 pub cycle_mode: bool,
20}
21
22impl VrcIrq {
23 pub const fn write_reload(&mut self, val: u8) {
24 self.reload = val;
25 }
26
27 pub fn write_control(&mut self, val: u8) {
28 self.enabled_after_ack = val & 0x01 == 0x01;
29 self.enabled = val & 0x02 == 0x02;
30 self.cycle_mode = val & 0x04 == 0x04;
31
32 if self.enabled {
33 self.counter = self.reload;
34 self.prescalar_counter = 341;
35 }
36
37 Cpu::clear_irq(Irq::MAPPER);
38 }
39
40 pub fn acknowledge(&mut self) {
41 self.enabled = self.enabled_after_ack;
42 Cpu::clear_irq(Irq::MAPPER);
43 }
44}
45
46impl Clock for VrcIrq {
47 fn clock(&mut self) -> u64 {
48 if self.enabled {
49 self.prescalar_counter -= 3;
50 if self.cycle_mode || self.prescalar_counter <= 0 {
51 if self.counter == 0xFF {
52 self.counter = self.reload;
53 Cpu::set_irq(Irq::MAPPER);
54 } else {
55 self.counter += 1;
56 }
57 self.prescalar_counter += 341;
58 }
59 1
60 } else {
61 0
62 }
63 }
64}
65
66impl Reset for VrcIrq {
67 fn reset(&mut self, _kind: ResetKind) {
68 self.reload = 0;
69 self.counter = 0;
70 self.prescalar_counter = 0;
71 self.enabled = false;
72 self.enabled_after_ack = false;
73 self.cycle_mode = false;
74 }
75}