tetanes_core/apu/
triangle.rs1use crate::{
6 apu::{
7 Channel,
8 length_counter::LengthCounter,
9 timer::{Timer, TimerCycle},
10 },
11 common::{Clock, Reset, ResetKind, Sample},
12};
13use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
19#[must_use]
20pub struct Triangle {
21 pub timer: Timer,
22 pub sequence: u8,
23 pub length: LengthCounter,
24 pub linear: LinearCounter,
25 pub force_silent: bool,
26}
27
28impl Default for Triangle {
29 fn default() -> Self {
30 Self::new()
31 }
32}
33
34impl Triangle {
35 const SEQUENCE: [u8; 32] = [
36 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
37 12, 13, 14, 15,
38 ];
39
40 pub const fn new() -> Self {
41 Self {
42 timer: Timer::new(0),
43 sequence: 0,
44 length: LengthCounter::new(Channel::Triangle),
45 linear: LinearCounter::new(),
46 force_silent: false,
47 }
48 }
49
50 #[must_use]
51 pub const fn silent(&self) -> bool {
52 self.force_silent
53 }
54
55 pub const fn set_silent(&mut self, silent: bool) {
56 self.force_silent = silent;
57 }
58
59 pub fn clock_quarter_frame(&mut self) {
60 self.linear.clock();
61 }
62
63 pub fn clock_half_frame(&mut self) {
64 self.clock_quarter_frame();
65 self.length.clock();
66 }
67
68 pub const fn write_linear_counter(&mut self, val: u8) {
70 self.linear.control = (val & 0x80) == 0x80; self.linear.write(val & 0x7F); self.length.write_ctrl(self.linear.control); }
74
75 pub fn write_timer_lo(&mut self, val: u8) {
77 self.timer.period = (self.timer.period & 0xFF00) | u64::from(val); }
79
80 pub fn write_timer_hi(&mut self, val: u8) {
82 self.length.write(val >> 3);
83 self.timer.period = (self.timer.period & 0x00FF) | (u64::from(val & 0x07) << 8); self.linear.reload = true;
85 }
86
87 pub const fn set_enabled(&mut self, enabled: bool) {
88 self.length.set_enabled(enabled);
89 }
90}
91
92impl Sample for Triangle {
93 fn output(&self) -> f32 {
94 if self.silent() {
95 0.0
96 } else if self.timer.period < 2 {
97 7.5
100 } else {
101 f32::from(Self::SEQUENCE[self.sequence as usize])
102 }
103 }
104}
105
106impl TimerCycle for Triangle {
107 fn cycle(&self) -> u64 {
108 self.timer.cycle
109 }
110}
111
112impl Clock for Triangle {
113 fn clock(&mut self) -> u64 {
118 if self.timer.clock() > 0 && self.length.counter > 0 && self.linear.counter > 0 {
119 self.sequence = (self.sequence + 1) & 0x1F;
120 1
121 } else {
122 0
123 }
124 }
125}
126
127impl Reset for Triangle {
128 fn reset(&mut self, kind: ResetKind) {
129 self.length.reset(kind);
130 self.linear.reset(kind);
131 self.sequence = 0;
132 }
133}
134
135#[derive(Default, Debug, Clone, Serialize, Deserialize)]
139#[must_use]
140pub struct LinearCounter {
141 pub reload: bool,
142 pub control: bool,
143 pub counter_reload: u8,
144 pub counter: u8,
145}
146
147impl LinearCounter {
148 pub const fn new() -> Self {
149 Self {
150 reload: false,
151 control: false,
152 counter_reload: 0u8,
153 counter: 0u8,
154 }
155 }
156
157 pub const fn write(&mut self, val: u8) {
158 self.counter_reload = val;
159 }
160}
161
162impl Clock for LinearCounter {
163 fn clock(&mut self) -> u64 {
164 let mut clock = 0;
165 if self.reload {
166 self.counter = self.counter_reload;
167 clock = 1;
168 } else if self.counter > 0 {
169 self.counter -= 1;
170 }
171 if !self.control {
172 self.reload = false;
173 }
174 clock
175 }
176}
177
178impl Reset for LinearCounter {
179 fn reset(&mut self, _kind: ResetKind) {
180 self.counter = 0;
181 self.counter_reload = 0;
182 self.reload = false;
183 self.control = false;
184 }
185}