Skip to content

Commit 2d3c360

Browse files
authored
Merge pull request #44 from YushiOMOTE/refactor-apu
Refactor apu
2 parents 7c60de6 + bb92cfb commit 2d3c360

File tree

12 files changed

+648
-337
lines changed

12 files changed

+648
-337
lines changed

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ lazy_static = { version = "1.2", features = ["spin_no_std"] }
1616
log = "0.4"
1717
hashbrown = "0.14"
1818
spin = "0.9"
19+
bitfield-struct = "0.8.0"
1920

2021
[dev-dependencies]
2122
env_logger = "0.11"

core/src/apu/mixer.rs

Lines changed: 68 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,52 @@ use super::{
66
};
77
use crate::hardware::Stream;
88
use alloc::sync::Arc;
9+
use bitfield_struct::bitfield;
910
use core::sync::atomic::{AtomicBool, AtomicUsize};
1011
use spin::Mutex;
1112

1213
pub struct Mixer {
1314
power: bool,
14-
ctrl: u8,
15-
so1_volume: usize,
16-
so2_volume: usize,
17-
so_mask: usize,
18-
enable: bool,
15+
nr50: Nr50,
16+
nr51: Nr51,
1917
stream: MixerStream,
2018
}
2119

20+
#[bitfield(u8)]
21+
struct Nr50 {
22+
#[bits(3)]
23+
right_volume: usize,
24+
vin_right_enable: bool,
25+
#[bits(3)]
26+
left_volume: usize,
27+
vin_left_enable: bool,
28+
}
29+
30+
#[bitfield(u8)]
31+
struct Nr51 {
32+
ch1_right: bool,
33+
ch2_right: bool,
34+
ch3_right: bool,
35+
ch4_right: bool,
36+
ch1_left: bool,
37+
ch2_left: bool,
38+
ch3_left: bool,
39+
ch4_left: bool,
40+
}
41+
2242
impl Mixer {
2343
pub fn new() -> Self {
2444
Self {
2545
power: false,
26-
ctrl: 0,
27-
so1_volume: 0,
28-
so2_volume: 0,
29-
so_mask: 0,
30-
enable: false,
46+
nr50: Nr50::default(),
47+
nr51: Nr51::default(),
3148
stream: MixerStream::new(),
3249
}
3350
}
3451

3552
/// Read NR50 register (0xff24)
3653
pub fn read_ctrl(&self) -> u8 {
37-
self.ctrl
54+
self.nr50.into_bits()
3855
}
3956

4057
/// Write NR50 register (0xff24)
@@ -43,15 +60,14 @@ impl Mixer {
4360
return;
4461
}
4562

46-
self.ctrl = value;
47-
self.so1_volume = (value as usize & 0x70) >> 4;
48-
self.so2_volume = value as usize & 0x07;
63+
self.nr50 = Nr50::from_bits(value);
64+
4965
self.update_stream();
5066
}
5167

5268
/// Read NR51 register (0xff25)
5369
pub fn read_so_mask(&self) -> u8 {
54-
self.so_mask as u8
70+
self.nr51.into_bits()
5571
}
5672

5773
/// Write NR51 register (0xff25)
@@ -60,7 +76,8 @@ impl Mixer {
6076
return;
6177
}
6278

63-
self.so_mask = value as usize;
79+
self.nr51 = Nr51::from_bits(value);
80+
6481
self.update_stream();
6582
}
6683

@@ -82,54 +99,68 @@ impl Mixer {
8299
self.stream.clone()
83100
}
84101

85-
pub fn enable(&mut self, enable: bool) {
86-
self.enable = enable;
87-
self.update_stream();
88-
}
89-
90102
// Update streams based on register settings
91103
fn update_stream(&mut self) {
92-
self.stream.enable.set(self.enable);
104+
self.stream.enable.set(self.power);
93105

94-
if self.enable {
106+
if self.power {
95107
for (i, tone) in self.stream.tones.iter().enumerate() {
96-
tone.volume.set(self.get_volume(i as u8))
108+
tone.volume.set(self.get_tone_volume(i))
97109
}
98-
self.stream.wave.volume.set(self.get_volume(2));
99-
self.stream.noise.volume.set(self.get_volume(3));
110+
self.stream.wave.volume.set(self.get_wave_volume());
111+
self.stream.noise.volume.set(self.get_noise_volume());
100112
}
101113
}
102114

103-
fn get_volume(&self, id: u8) -> usize {
104-
let mask = 1 << id;
105-
let v1 = if self.so_mask & mask != 0 {
106-
self.so1_volume
115+
fn get_tone_volume(&self, tone: usize) -> usize {
116+
if tone == 0 {
117+
self.get_volume(self.nr51.ch1_right(), self.nr51.ch1_left())
118+
} else {
119+
self.get_volume(self.nr51.ch2_right(), self.nr51.ch2_left())
120+
}
121+
}
122+
123+
fn get_wave_volume(&self) -> usize {
124+
self.get_volume(self.nr51.ch3_right(), self.nr51.ch3_left())
125+
}
126+
127+
fn get_noise_volume(&self) -> usize {
128+
self.get_volume(self.nr51.ch4_right(), self.nr51.ch4_left())
129+
}
130+
131+
fn get_volume(&self, right_enable: bool, left_enable: bool) -> usize {
132+
let right = if right_enable {
133+
self.nr50.right_volume()
107134
} else {
108135
0
109136
};
110-
let v2 = if self.so_mask & (mask << 4) != 0 {
111-
self.so2_volume
137+
138+
let left = if left_enable {
139+
self.nr50.left_volume()
112140
} else {
113141
0
114142
};
115-
v1 + v2
143+
144+
right + left
116145
}
117146

118147
pub fn power_on(&mut self) {
119148
self.power = true;
149+
self.update_stream();
120150
}
121151

122152
pub fn power_off(&mut self) {
123153
self.power = false;
124-
self.ctrl = 0;
125-
self.so1_volume = 0;
126-
self.so2_volume = 0;
127-
self.so_mask = 0;
154+
155+
self.nr50 = Nr50::default();
156+
self.nr51 = Nr51::default();
157+
128158
for tone in &mut self.stream.tones {
129159
tone.clear();
130160
}
131161
self.stream.wave.clear();
132162
self.stream.noise.clear();
163+
self.update_stream();
133164
}
134165
}
135166

core/src/apu/mod.rs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use crate::hardware::HardwareHandle;
66

77
use self::{mixer::Mixer, noise::Noise, tone::Tone, wave::Wave};
88

9+
use bitfield_struct::bitfield;
10+
911
mod clock_divider;
1012
mod frame_sequencer;
1113
mod length_counter;
@@ -23,7 +25,18 @@ pub struct Apu {
2325
wave: Wave,
2426
noise: Noise,
2527
mixer: Mixer,
26-
enable: bool,
28+
nr52: Nr52,
29+
}
30+
31+
#[bitfield(u8)]
32+
struct Nr52 {
33+
ch1_on: bool,
34+
ch2_on: bool,
35+
ch3_on: bool,
36+
ch4_on: bool,
37+
#[bits(3)]
38+
_unused: u8,
39+
power_on: bool,
2740
}
2841

2942
impl Apu {
@@ -39,7 +52,7 @@ impl Apu {
3952
wave: Wave::new(),
4053
noise: Noise::new(),
4154
mixer,
42-
enable: false,
55+
nr52: Nr52::default(),
4356
}
4457
}
4558

@@ -226,40 +239,33 @@ impl Apu {
226239

227240
/// Read NR52 register (0xff26)
228241
pub fn read_enable(&self) -> u8 {
229-
let mut v = 0x70;
230-
v |= if self.enable { 0x80 } else { 0x00 };
231-
v |= if self.tones[0].is_active() {
232-
0x01
233-
} else {
234-
0x00
235-
};
236-
v |= if self.tones[1].is_active() {
237-
0x02
238-
} else {
239-
0x00
240-
};
241-
v |= if self.wave.is_active() { 0x04 } else { 0x00 };
242-
v |= if self.noise.is_active() { 0x08 } else { 0x00 };
243-
v
242+
self.nr52
243+
.with_ch1_on(self.tones[0].is_active())
244+
.with_ch2_on(self.tones[1].is_active())
245+
.with_ch3_on(self.wave.is_active())
246+
.with_ch4_on(self.noise.is_active())
247+
.into_bits()
248+
| 0x70
244249
}
245250

246251
/// Write NR52 register (0xff26)
247252
pub fn write_enable(&mut self, value: u8) {
248-
debug!("Write NR52: {:02x}", value);
253+
let before = self.nr52.power_on();
249254

250-
let enable = value & 0x80 != 0;
255+
self.nr52 = Nr52::from_bits(value);
251256

252-
self.mixer.enable(enable);
257+
let after = self.nr52.power_on();
253258

254-
if !self.enable && enable {
259+
if !before && after {
255260
info!("Sound master enabled");
256261
for tone in &mut self.tones {
257262
tone.power_on();
258263
}
264+
259265
self.wave.power_on();
260266
self.noise.power_on();
261267
self.mixer.power_on();
262-
} else if self.enable && !enable {
268+
} else if before && !after {
263269
info!("Sound master disabled");
264270

265271
for tone in &mut self.tones {
@@ -269,8 +275,6 @@ impl Apu {
269275
self.noise.power_off();
270276
self.mixer.power_off();
271277
}
272-
273-
self.enable = enable;
274278
}
275279

276280
pub fn step(&mut self, cycles: usize) {

0 commit comments

Comments
 (0)