Skip to content

Commit

Permalink
Merge pull request #56 from YushiOMOTE/channel-4-tests
Browse files Browse the repository at this point in the history
Channel 4 tests
  • Loading branch information
YushiOMOTE authored Jul 31, 2024
2 parents 05f6400 + 4e2c91d commit 6d6c95b
Show file tree
Hide file tree
Showing 8 changed files with 845 additions and 43 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ Test status of [Same Suite](https://github.com/YushiOMOTE/SameSuite/tree/430ab7f
* [x] `apu/div_write_trigger_10.gb`
* [x] `apu/div_write_trigger_volume.gb`
* [x] `apu/div_write_trigger_volume_10.gb`
* [x] `apu/div_trigger_volume_10.gb`
* [x] `apu/channel_4/channel_4_lfsr.gb`
* [x] `apu/channel_4/channel_4_lfsr15.gb`
* [x] `apu/channel_4/channel_4_lfsr_7_15.gb`
* [x] `apu/channel_4/channel_4_lfsr_15_7.gb`

## Projects

Expand Down
81 changes: 54 additions & 27 deletions core/src/apu/noise.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use super::{dac::Dac, envelope::Envelope, frame_sequencer::Frame, length_counter::LengthCounter};
use crate::clock::{ClockDivider, Timer};
use crate::{
clock::{ClockDivider, Timer},
cpu::CPU_FREQ_HZ,
};

use bitfield_struct::bitfield;

const NOISE_FREQ_HZ: usize = 262_144;
// LFSR runs at CPU rate.
const NOISE_FREQ_HZ: usize = CPU_FREQ_HZ;

#[derive(Debug, Clone)]
pub struct Noise {
Expand Down Expand Up @@ -122,6 +126,7 @@ impl Noise {
}

self.nr43 = Nr43::from_bits(value);
self.lfsr.set_mode(self.nr43.step());
}

/// Read NR44 register (0xff23)
Expand All @@ -141,7 +146,7 @@ impl Noise {
.update(self.nr44.trigger(), self.nr44.enable_length());

if self.nr44.trigger() {
self.reload_timer();
self.reload_initial_timer(self.nr43.step());
self.lfsr.trigger(self.nr43.step());
self.envelope
.update(self.nr42.init(), self.nr42.count(), self.nr42.increase());
Expand All @@ -159,27 +164,37 @@ impl Noise {
for _ in 0..times {
self.update();
}

self.write_amp();
}

fn update(&mut self) {
if !self.is_active() {
return;
}
if !self.timer.tick() {
return;
}

self.reload_timer();

self.lfsr.update();
}

self.dac.write(if self.lfsr.high() {
fn write_amp(&mut self) {
self.dac.write(if self.is_active() && self.lfsr.high() {
self.envelope.amp()
} else {
0
});
}

fn reload_initial_timer(&mut self, short: bool) {
self.timer.reset();

// TODO: Understand the initial delay more.
self.timer.set_interval(
self.timer_interval() + if short { 0 } else { 7 * self.timer_interval() } + 3,
);
}

fn reload_timer(&mut self) {
self.timer.reset();
self.timer.set_interval(self.timer_interval());
Expand All @@ -189,11 +204,19 @@ impl Noise {
let divider = self.nr43.div_freq();
let shift = self.nr43.shift_freq();

if divider == 0 {
(5 << shift) / 10
} else {
divider << shift
}
// Divisor code Divisor
// -----------------------
// 0 8
// 1 16
// 2 32
// 3 48
// 4 64
// 5 80
// 6 96
// 7 112
let base = if divider == 0 { 8 } else { divider * 16 };

base << shift
}

pub fn is_active(&self) -> bool {
Expand All @@ -204,6 +227,9 @@ impl Noise {
self.power = true;

self.length_counter.power_on();

self.reload_timer();
self.divider.reset();
}

pub fn power_off(&mut self) {
Expand All @@ -216,8 +242,6 @@ impl Noise {

self.length_counter.power_off();

self.lfsr.reset();

self.dac.power_off();
}

Expand All @@ -239,35 +263,38 @@ struct Lfsr {
impl Lfsr {
fn new() -> Self {
Self {
value: 0,
value: 0xff,
short: false,
}
}

fn reset(&mut self) {
self.value = 0;
self.short = false;
}

fn high(&self) -> bool {
// Inverted bit 1
self.value & 1 == 0
}

fn trigger(&mut self, short: bool) {
self.value = 0;
self.short = short;
self.value = 0xff;
}

fn set_mode(&mut self, short: bool) {
self.short = short;
}

fn update(&mut self) {
// NXOR bit 0 and 1.
let bit = !((self.value & 0x01) ^ ((self.value & 0x02) >> 1)) & 1;
// Xor bit 0 and 1.
let bit = (self.value & 1) ^ ((self.value & 2) >> 1) & 1;

// Shift right.
self.value >>= 1;

// Put the bit at bit 14 (i.e. 15 bits shift register)
self.value = (self.value & !0x4000) | (bit << 14);

// Put XOR-ed result in bit 15 (and bit 7 in short mode)
if self.short {
self.value = ((self.value >> 1) & 0x7f7f) | (bit << 7) | (bit << 15);
} else {
self.value = ((self.value >> 1) & 0x7fff) | (bit << 15);
// Put the bit at bit 6 (i.e. 7 bits shift register)
self.value = (self.value & !0x0040) | (bit << 6);
}
}
}
Loading

0 comments on commit 6d6c95b

Please sign in to comment.