use crate::common::{Clock, Reset, ResetKind};
use serde::{Deserialize, Serialize};
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[must_use]
pub struct Envelope {
pub start: bool,
pub constant_volume: bool,
pub volume: u8,
pub divider: u8,
pub counter: u8,
pub loops: bool,
}
impl Envelope {
pub const fn new() -> Self {
Self {
start: false,
constant_volume: false,
volume: 0,
divider: 0,
counter: 0,
loops: false,
}
}
#[inline]
#[must_use]
pub const fn volume(&self) -> u8 {
if self.constant_volume {
self.volume
} else {
self.counter
}
}
#[inline]
pub const fn restart(&mut self) {
self.start = true;
}
#[inline]
pub const fn write_ctrl(&mut self, val: u8) {
self.loops = (val & 0x20) == 0x20; self.constant_volume = (val & 0x10) == 0x10; self.volume = val & 0x0F; }
}
impl Clock for Envelope {
fn clock(&mut self) {
if self.start {
self.start = false;
self.counter = 15;
self.divider = self.volume;
} else if self.divider > 0 {
self.divider -= 1;
} else {
self.divider = self.volume;
if self.counter > 0 {
self.counter -= 1;
} else if self.loops {
self.counter = 15;
}
}
}
}
impl Reset for Envelope {
fn reset(&mut self, _kind: ResetKind) {
self.start = false;
self.constant_volume = false;
self.volume = 0;
self.divider = 0;
self.counter = 0;
}
}