use serde::{Deserialize, Serialize};
use super::{envelope::Envelope, length_counter::LengthCounter};
use std::fmt::Debug;
#[derive(Clone, Copy, Default, Serialize, Deserialize)]
pub struct PulseRegister {
pub duty: u32,
pub timer: usize,
pub timer_reload: usize,
pub envelope: Envelope,
pub length_counter: LengthCounter,
pub sweep_enabled: bool,
pub sweep_period: usize,
pub sweep_target_period: usize,
pub sweep_divider: usize,
pub sweep_negate: bool,
pub sweep_shift: usize,
pub enabled: bool,
pub sequencer: usize,
}
const DUTY_CYCLES: [[u32; 8]; 4] = [
[0, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 0, 0, 0],
[1, 0, 0, 1, 1, 1, 1, 1],
];
impl PulseRegister {
pub fn muted(&self) -> bool {
!self.enabled
|| self.sweep_target_period > 0x7FF
|| self.length_counter.muted()
|| self.timer_reload < 8
}
pub fn value(&self) -> u32 {
if self.muted() || DUTY_CYCLES[self.duty as usize][self.sequencer] == 0 {
0
} else {
self.envelope.value()
}
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
if !self.enabled {
self.length_counter.load = 0;
}
}
}
impl Debug for PulseRegister {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"on={} timer={:3X} target_period={:X} divider={:X} duty={:X} length=[{:?}] sweep=[on={} shift={:X}]",
self.enabled,
self.timer_reload,
self.sweep_target_period,
self.sweep_divider,
self.duty,
self.length_counter,
self.sweep_enabled,
self.sweep_shift
)
}
}