troubleshooting sweep and envelope units, hopefully
This commit is contained in:
parent
686d45f8d3
commit
f936258310
|
@ -23,6 +23,8 @@ pub struct Square {
|
||||||
|
|
||||||
timer: u16,
|
timer: u16,
|
||||||
timer_period: u16,
|
timer_period: u16,
|
||||||
|
|
||||||
|
target_period: u16,
|
||||||
sweep_divider: u16, // Period, P
|
sweep_divider: u16, // Period, P
|
||||||
sweep_counter: u16,
|
sweep_counter: u16,
|
||||||
shift_count: u8,
|
shift_count: u8,
|
||||||
|
@ -50,6 +52,8 @@ impl Square {
|
||||||
|
|
||||||
timer: 0,
|
timer: 0,
|
||||||
timer_period: 0,
|
timer_period: 0,
|
||||||
|
|
||||||
|
target_period: 0,
|
||||||
sweep_divider: 0,
|
sweep_divider: 0,
|
||||||
sweep_counter: 0,
|
sweep_counter: 0,
|
||||||
shift_count: 0,
|
shift_count: 0,
|
||||||
|
@ -76,10 +80,12 @@ impl Square {
|
||||||
// Update volume for this channel
|
// Update volume for this channel
|
||||||
// The mixer receives the current envelope volume except when
|
// The mixer receives the current envelope volume except when
|
||||||
self.sample = if self.duty_cycle[self.duty_counter] == 0 // the sequencer output is zero, or
|
self.sample = if self.duty_cycle[self.duty_counter] == 0 // the sequencer output is zero, or
|
||||||
|| self.sweep_divider > 0x7FF // overflow from the sweep unit's adder is silencing the channel,
|
|| self.target_period > 0x7FF // overflow from the sweep unit's adder is silencing the channel,
|
||||||
|| self.length_counter == 0 // the length counter is zero, or
|
|| self.length_counter == 0 // the length counter is zero, or
|
||||||
|| self.timer < 8 { // the timer has a value less than eight.
|
|| self.timer_period < 8 { // the timer has a value less than eight.
|
||||||
0
|
0
|
||||||
|
} else if self.constant_volume_flag {
|
||||||
|
self.envelope
|
||||||
} else {
|
} else {
|
||||||
self.decay_counter
|
self.decay_counter
|
||||||
};
|
};
|
||||||
|
@ -96,12 +102,6 @@ impl Square {
|
||||||
self.envelope_divider = self.envelope; // and the divider's period is immediately reloaded
|
self.envelope_divider = self.envelope; // and the divider's period is immediately reloaded
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clock_length_counter(&mut self) {
|
|
||||||
if !(self.length_counter == 0 || self.length_counter_halt) {
|
|
||||||
self.length_counter -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clock_envelope_divider(&mut self) {
|
fn clock_envelope_divider(&mut self) {
|
||||||
// When the divider is clocked while at 0, it is loaded with V and clocks the decay level counter.
|
// When the divider is clocked while at 0, it is loaded with V and clocks the decay level counter.
|
||||||
|
@ -119,23 +119,18 @@ impl Square {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clock_sweep(&mut self) {
|
pub fn clock_length_counter(&mut self) {
|
||||||
// The sweep unit continuously calculates each channel's target period in this way:
|
if !(self.length_counter == 0 || self.length_counter_halt) {
|
||||||
// A barrel shifter shifts the channel's 11-bit raw timer period right by the shift count, producing the change amount.
|
self.length_counter -= 1;
|
||||||
let change = self.timer_period >> self.shift_count;
|
|
||||||
// If the negate flag is true, the change amount is made negative.
|
|
||||||
// The target period is the sum of the current period and the change amount.
|
|
||||||
if self.sweep_negate {
|
|
||||||
self.sweep_divider = self.timer_period - change;
|
|
||||||
if self.second_channel {
|
|
||||||
self.sweep_divider -= 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.sweep_divider = self.timer_period + change;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clock_sweep(&mut self) {
|
||||||
|
// When the frame counter sends a half-frame clock (at 120 or 96 Hz), two things happen.
|
||||||
// If the divider's counter is zero, the sweep is enabled, and the sweep unit is not muting the channel: The pulse's period is adjusted.
|
// If the divider's counter is zero, the sweep is enabled, and the sweep unit is not muting the channel: The pulse's period is adjusted.
|
||||||
if self.sweep_counter == 0 && self.sweep_enabled && !(self.timer < 8 || self.sweep_divider > 0x7FF) {
|
if self.sweep_counter == 0 && self.sweep_enabled && !(self.timer_period < 8 || self.target_period > 0x7FF) {
|
||||||
self.timer_period = self.sweep_divider;
|
self.timer_period = self.target_period;
|
||||||
|
println!("timer period adjusted to {}", self.timer_period);
|
||||||
}
|
}
|
||||||
// If the divider's counter is zero or the reload flag is true: The counter is set to P and the reload flag is cleared. Otherwise, the counter is decremented.
|
// If the divider's counter is zero or the reload flag is true: The counter is set to P and the reload flag is cleared. Otherwise, the counter is decremented.
|
||||||
if self.sweep_counter == 0 || self.sweep_reload {
|
if self.sweep_counter == 0 || self.sweep_reload {
|
||||||
|
@ -144,6 +139,24 @@ impl Square {
|
||||||
} else {
|
} else {
|
||||||
self.sweep_counter -= 1;
|
self.sweep_counter -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The sweep unit continuously calculates each channel's target period in this way:
|
||||||
|
// A barrel shifter shifts the channel's 11-bit raw timer period right by the shift count, producing the change amount.
|
||||||
|
let change = self.timer_period >> self.shift_count;
|
||||||
|
// If the negate flag is true, the change amount is made negative.
|
||||||
|
// The target period is the sum of the current period and the change amount.
|
||||||
|
if self.sweep_negate {
|
||||||
|
self.target_period = self.timer_period - change;
|
||||||
|
// The two pulse channels have their adders' carry inputs wired differently,
|
||||||
|
// which produces different results when each channel's change amount is made negative:
|
||||||
|
// Pulse 1 adds the ones' complement (−c − 1). Making 20 negative produces a change amount of −21.
|
||||||
|
// Pulse 2 adds the two's complement (−c). Making 20 negative produces a change amount of −20.
|
||||||
|
if !self.second_channel {
|
||||||
|
self.target_period -= 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.target_period = self.timer_period + change;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// $4000/$4004
|
// $4000/$4004
|
||||||
|
@ -186,6 +199,5 @@ impl Square {
|
||||||
// The sequencer is immediately restarted at the first value of the current sequence. The envelope is also restarted. The period divider is not reset.
|
// The sequencer is immediately restarted at the first value of the current sequence. The envelope is also restarted. The period divider is not reset.
|
||||||
self.duty_counter = 0;
|
self.duty_counter = 0;
|
||||||
self.start = true;
|
self.start = true;
|
||||||
self.duty_counter = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue