use super::{channel::Channel, duty_cycle::DutyCycle, panning::Panning};
#[cfg_attr(not(target_family = "wasm"), derive(PartialEq, Eq, Debug))]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
#[derive(Clone, Copy)]
pub struct ToneFlags {
channel: Channel,
#[cfg_attr(feature = "serde", serde(default))]
duty_cycle: DutyCycle,
#[cfg_attr(feature = "serde", serde(default))]
panning: Panning,
}
impl ToneFlags {
pub const fn builder() -> ToneFlagsBuilder {
ToneFlagsBuilder::new()
}
pub const fn new() -> Self {
Self {
channel: Channel::Pulse1,
duty_cycle: DutyCycle::C12_5,
panning: Panning::Center,
}
}
}
impl Default for ToneFlags {
fn default() -> Self {
Self::new()
}
}
pub struct ToneFlagsBuilder {
flags: ToneFlags,
}
impl ToneFlagsBuilder {
pub const fn new() -> Self {
Self {
flags: ToneFlags::new(),
}
}
pub const fn with_channel(mut self, channel: Channel) -> Self {
self.flags.channel = channel;
self
}
pub const fn with_duty_cycle(mut self, duty_cycle: DutyCycle) -> Self {
self.flags.duty_cycle = duty_cycle;
self
}
pub const fn with_panning(mut self, panning: Panning) -> Self {
self.flags.panning = panning;
self
}
pub const fn build(self) -> ToneFlags {
self.flags
}
}
impl Default for ToneFlagsBuilder {
fn default() -> Self {
Self::new()
}
}
impl From<ToneFlags> for u16 {
fn from(value: ToneFlags) -> Self {
value.channel as u16 | ((value.duty_cycle as u16) << 2) | ((value.panning as u16) << 4)
}
}
impl From<u16> for ToneFlags {
fn from(value: u16) -> Self {
let channel = Channel::from((value & 0b11) as u8);
let duty_cycle = DutyCycle::from(((value >> 2) & 0b1100) as u8);
let panning = Panning::from(((value >> 4) & 0b110000) as u8);
Self {
channel,
duty_cycle,
panning,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn flags_to_u16() {
assert_eq!(
u16::from(ToneFlags {
channel: Channel::Pulse1,
duty_cycle: DutyCycle::C12_5,
panning: Panning::Center
}),
0
);
assert_eq!(
u16::from(ToneFlags {
channel: Channel::Pulse2,
duty_cycle: DutyCycle::C75,
panning: Panning::Right
}),
0x231
);
}
#[test]
fn flags_from_u16() {
assert_eq!(
ToneFlags::from(0),
ToneFlags {
channel: Channel::Pulse1,
duty_cycle: DutyCycle::C12_5,
panning: Panning::Center
}
);
assert_eq!(
ToneFlags::from(0x231),
ToneFlags {
channel: Channel::Pulse2,
duty_cycle: DutyCycle::C75,
panning: Panning::Right
}
);
}
}