GB/音频/512 Hz 时钟信号

Game Boy 内部存在一个 512 Hz 时钟信号, 用于向序列发生器(Frame Sequence)提供信号输入. 下面将在代码中实现该时钟信号.

struct ChannelSquare {}
struct ChannelWave {}
struct ChannelNoise {}

pub struct Apu {
    reg: Register,
    timer: Timer,
    channel1: ChannelSquare,
    channel2: ChannelSquare,
    channel3: ChannelWave,
    channel4: ChannelNoise,
}

impl Apu {
    pub fn power_up() -> Self {
        Self {
            reg: Register::power_up(Channel::Mixer),
            timer: Timer::power_up(4194304 / 512),
            channel1: ChannelSquare::power_up(),
            channel2: ChannelSquare::power_up(),
            channel3: ChannelWave::power_up(),
            channel4: ChannelNoise::power_up(),
        }
    }

    pub fn next(&mut self, cycles: u32) {
        if !self.reg.get_power() {
            return;
        }

        for _ in 0..self.timer.next(cycles) {
            self.channel1.next(self.timer.period);
            self.channel2.next(self.timer.period);
            self.channel3.next(self.timer.period);
            self.channel4.next(self.timer.period);

            // 512 Hz 时钟信号
            //
            // ... Your Codes
        }
    }
}

结构体 Apu 是音频模块主要对外导出的结构类型, 它需要被嵌入内存管理模块上. 每当 CPU 执行完一条指令, CPU 通知音频模块该指令的执行周期, 这通过 next 函数完成. 由于 CPU 的时钟周期是 4194304, 因此为了获取 512 Hz 的时钟信号, 只需要每当 CPU 执行消耗 4194304/512 周期时产生一个新的信号即可. 在代码中表现来看, 将代码写入 "Your Codes" 代码块即可实现每秒执行指定代码 512 次.