2021-01-19 04:54:38 +00:00
|
|
|
use crate::instruction::Cycles;
|
2021-03-16 02:16:11 +00:00
|
|
|
use bitfield::bitfield;
|
2021-01-03 08:05:46 +00:00
|
|
|
#[derive(Debug, Clone, Copy, Default)]
|
|
|
|
pub struct Sound {
|
2021-01-18 00:58:57 +00:00
|
|
|
pub control: SoundControl,
|
2021-01-17 23:33:12 +00:00
|
|
|
pub ch1: Channel1,
|
2021-01-18 00:58:57 +00:00
|
|
|
}
|
|
|
|
|
2021-01-19 04:54:38 +00:00
|
|
|
impl Sound {
|
|
|
|
pub fn step(&mut self, _cycles: Cycles) {
|
|
|
|
//
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-18 00:58:57 +00:00
|
|
|
#[derive(Debug, Clone, Copy, Default)]
|
|
|
|
pub struct SoundControl {
|
|
|
|
pub channel: ChannelControl,
|
2021-03-16 02:16:11 +00:00
|
|
|
pub output: SoundOutput,
|
2021-01-18 00:58:57 +00:00
|
|
|
pub status: SoundStatus,
|
2021-01-03 08:05:46 +00:00
|
|
|
}
|
|
|
|
|
2021-03-16 02:16:11 +00:00
|
|
|
// TODO: What to do about the separation of freq bits
|
|
|
|
// across multiple registers?
|
|
|
|
bitfield! {
|
|
|
|
pub struct FrequencyHigh(u8);
|
|
|
|
impl Debug;
|
|
|
|
_, initial: 7;
|
|
|
|
from into FrequencyType, get_freq_type, set_freq_type: 6;
|
|
|
|
_, set_freq_high_bits: 2, 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Copy for FrequencyHigh {}
|
|
|
|
impl Clone for FrequencyHigh {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for FrequencyHigh {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u8> for FrequencyHigh {
|
|
|
|
fn from(byte: u8) -> Self {
|
|
|
|
Self(byte)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<FrequencyHigh> for u8 {
|
|
|
|
fn from(duty: FrequencyHigh) -> Self {
|
|
|
|
duty.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bitfield! {
|
|
|
|
pub struct FrequencyLow(u8);
|
|
|
|
impl Debug;
|
|
|
|
pub _, set_freq_bits: 7, 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Copy for FrequencyLow {}
|
|
|
|
impl Clone for FrequencyLow {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for FrequencyLow {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u8> for FrequencyLow {
|
|
|
|
fn from(byte: u8) -> Self {
|
|
|
|
Self(byte)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_11bit_freq(low: &FrequencyLow, high: FrequencyHigh) -> u16 {
|
|
|
|
let high_bits = high.0 & 0b111;
|
|
|
|
|
|
|
|
(low.0 as u16) << 8 | ((high_bits as u16) << 4)
|
2021-01-19 06:30:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
enum FrequencyType {
|
2021-01-19 07:36:44 +00:00
|
|
|
Counter = 0,
|
2021-03-16 00:19:40 +00:00
|
|
|
Consecutive = 1,
|
2021-01-19 06:30:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u8> for FrequencyType {
|
|
|
|
fn from(byte: u8) -> Self {
|
|
|
|
match byte {
|
|
|
|
0b00 => Self::Counter,
|
2021-03-16 00:19:40 +00:00
|
|
|
0b01 => Self::Consecutive,
|
|
|
|
_ => unreachable!("{} is not a valid number for FrequencyType"),
|
2021-01-19 06:30:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for FrequencyType {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::Counter
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-16 02:16:11 +00:00
|
|
|
bitfield! {
|
|
|
|
pub struct SoundStatus(u8);
|
|
|
|
impl Debug;
|
|
|
|
all_enabled, set_all_enabled: 7;
|
|
|
|
sound_4, _: 3;
|
|
|
|
sound_3, _: 2;
|
|
|
|
sound_2, _: 1;
|
|
|
|
sound_1, _: 0;
|
|
|
|
}
|
2021-01-19 06:30:10 +00:00
|
|
|
|
2021-03-16 02:16:11 +00:00
|
|
|
impl Copy for SoundStatus {}
|
|
|
|
impl Clone for SoundStatus {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
*self
|
2021-01-19 06:30:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-16 02:16:11 +00:00
|
|
|
impl Default for SoundStatus {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(0)
|
|
|
|
}
|
2021-01-03 08:05:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u8> for SoundStatus {
|
|
|
|
fn from(byte: u8) -> Self {
|
2021-03-16 02:16:11 +00:00
|
|
|
Self(byte)
|
2021-01-03 08:05:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<SoundStatus> for u8 {
|
2021-03-16 02:16:11 +00:00
|
|
|
fn from(duty: SoundStatus) -> Self {
|
|
|
|
duty.0
|
2021-01-03 08:05:46 +00:00
|
|
|
}
|
|
|
|
}
|
2021-01-17 23:33:12 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, Default)]
|
|
|
|
pub struct Channel1 {
|
|
|
|
pub sound_duty: SoundDuty,
|
|
|
|
pub vol_envelope: VolumeEnvelope,
|
2021-03-16 02:16:11 +00:00
|
|
|
pub freq_hi: FrequencyHigh,
|
|
|
|
pub freq_lo: FrequencyLow,
|
2021-01-17 23:33:12 +00:00
|
|
|
}
|
|
|
|
|
2021-03-16 02:16:11 +00:00
|
|
|
bitfield! {
|
|
|
|
pub struct VolumeEnvelope(u8);
|
|
|
|
impl Debug;
|
|
|
|
init_vol, set_init_vol: 7, 4;
|
|
|
|
from into EnvelopeDirection, direction, set_direction: 3;
|
|
|
|
sweep_count, set_sweep_count: 2, 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Copy for VolumeEnvelope {}
|
|
|
|
impl Clone for VolumeEnvelope {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for VolumeEnvelope {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(0)
|
|
|
|
}
|
2021-01-17 23:33:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u8> for VolumeEnvelope {
|
|
|
|
fn from(byte: u8) -> Self {
|
2021-03-16 02:16:11 +00:00
|
|
|
Self(byte)
|
2021-01-17 23:33:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<VolumeEnvelope> for u8 {
|
2021-03-16 02:16:11 +00:00
|
|
|
fn from(duty: VolumeEnvelope) -> Self {
|
|
|
|
duty.0
|
2021-01-17 23:33:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
enum EnvelopeDirection {
|
2021-01-19 07:36:44 +00:00
|
|
|
Decrease = 0,
|
|
|
|
Increase = 1,
|
2021-01-17 23:33:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u8> for EnvelopeDirection {
|
|
|
|
fn from(byte: u8) -> Self {
|
|
|
|
match byte {
|
|
|
|
0b00 => Self::Decrease,
|
|
|
|
0b01 => Self::Increase,
|
2021-01-19 07:36:44 +00:00
|
|
|
_ => unreachable!(
|
|
|
|
"{:#04X} is not a possible value for EnvelopeDirection",
|
|
|
|
byte
|
|
|
|
),
|
2021-01-17 23:33:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for EnvelopeDirection {
|
|
|
|
fn default() -> Self {
|
2021-01-19 07:36:44 +00:00
|
|
|
Self::Decrease
|
2021-01-17 23:33:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-16 02:16:11 +00:00
|
|
|
bitfield! {
|
|
|
|
pub struct SoundDuty(u8);
|
|
|
|
impl Debug;
|
|
|
|
from into WavePattern, wave_pattern, set_wave_pattern: 7, 6;
|
|
|
|
_, set_sound_length: 5, 0; // TODO: Getter only used if bit 6 in NR14 is set
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Copy for SoundDuty {}
|
|
|
|
impl Clone for SoundDuty {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for SoundDuty {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(0)
|
|
|
|
}
|
2021-01-17 23:33:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u8> for SoundDuty {
|
|
|
|
fn from(byte: u8) -> Self {
|
2021-03-16 02:16:11 +00:00
|
|
|
Self(byte)
|
2021-01-17 23:33:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<SoundDuty> for u8 {
|
|
|
|
fn from(duty: SoundDuty) -> Self {
|
2021-03-16 02:16:11 +00:00
|
|
|
duty.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<WavePattern> for u8 {
|
|
|
|
fn from(pattern: WavePattern) -> Self {
|
|
|
|
use WavePattern::*;
|
|
|
|
|
|
|
|
match pattern {
|
|
|
|
OneEighth => 0b00,
|
|
|
|
OneQuarter => 0b01,
|
|
|
|
OneHalf => 0b10,
|
|
|
|
ThreeQuarters => 0b11,
|
|
|
|
}
|
2021-01-17 23:33:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
2021-03-16 02:16:11 +00:00
|
|
|
pub enum WavePattern {
|
2021-01-19 07:36:44 +00:00
|
|
|
OneEighth = 0, // 12.5% ( _-------_-------_------- )
|
|
|
|
OneQuarter = 1, // 25% ( __------__------__------ )
|
|
|
|
OneHalf = 2, // 50% ( ____----____----____---- ) (normal)
|
|
|
|
ThreeQuarters = 3, // 75% ( ______--______--______-- )
|
2021-01-17 23:33:12 +00:00
|
|
|
}
|
|
|
|
|
2021-03-16 02:16:11 +00:00
|
|
|
impl Default for WavePattern {
|
2021-01-17 23:33:12 +00:00
|
|
|
fn default() -> Self {
|
|
|
|
Self::OneEighth // Rationale: OneEighth is 0x00
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-16 02:16:11 +00:00
|
|
|
impl From<u8> for WavePattern {
|
2021-01-17 23:33:12 +00:00
|
|
|
fn from(byte: u8) -> Self {
|
|
|
|
match byte {
|
|
|
|
0b00 => Self::OneEighth,
|
|
|
|
0b01 => Self::OneQuarter,
|
|
|
|
0b10 => Self::OneHalf,
|
|
|
|
0b11 => Self::ThreeQuarters,
|
|
|
|
_ => unreachable!("{:#04X} is not a valid value for a Sound Wave", byte),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-16 02:16:11 +00:00
|
|
|
bitfield! {
|
|
|
|
pub struct SoundOutput(u8);
|
|
|
|
impl Debug;
|
|
|
|
snd4_so2, set_snd4_so2: 7;
|
|
|
|
snd3_so2, set_snd3_so2: 6;
|
|
|
|
snd2_so2, set_snd2_so2: 5;
|
|
|
|
snd1_so2, set_snd1_so2: 4;
|
|
|
|
snd4_so1, set_snd4_so1: 3;
|
|
|
|
snd3_so1, set_snd3_so1: 2;
|
|
|
|
snd2_so1, set_snd2_so1: 1;
|
|
|
|
snd1_so1, set_snd1_so1: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Copy for SoundOutput {}
|
|
|
|
impl Clone for SoundOutput {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for SoundOutput {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u8> for SoundOutput {
|
2021-01-17 23:33:12 +00:00
|
|
|
fn from(byte: u8) -> Self {
|
2021-03-16 02:16:11 +00:00
|
|
|
Self(byte)
|
2021-01-17 23:33:12 +00:00
|
|
|
}
|
|
|
|
}
|
2021-01-18 00:58:57 +00:00
|
|
|
|
2021-03-16 02:16:11 +00:00
|
|
|
impl From<SoundOutput> for u8 {
|
|
|
|
fn from(duty: SoundOutput) -> Self {
|
|
|
|
duty.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bitfield! {
|
|
|
|
pub struct ChannelControl(u8);
|
|
|
|
impl Debug;
|
|
|
|
vin_so2, set_vin_so2: 7;
|
|
|
|
so2_level, set_so2_level: 6, 4;
|
|
|
|
vin_so1, set_vin_so1: 3;
|
|
|
|
so1_level, set_so1_level: 2, 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Copy for ChannelControl {}
|
|
|
|
impl Clone for ChannelControl {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for ChannelControl {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(0)
|
|
|
|
}
|
2021-01-18 00:58:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u8> for ChannelControl {
|
|
|
|
fn from(byte: u8) -> Self {
|
2021-03-16 02:16:11 +00:00
|
|
|
Self(byte)
|
2021-01-18 00:58:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ChannelControl> for u8 {
|
2021-03-16 02:16:11 +00:00
|
|
|
fn from(duty: ChannelControl) -> Self {
|
|
|
|
duty.0
|
2021-01-18 00:58:57 +00:00
|
|
|
}
|
|
|
|
}
|