Skip to content

Commit 9c273ab

Browse files
committed
md: better handle 32X PWM sample/clock rate changes
1 parent 6cc9f5a commit 9c273ab

File tree

2 files changed

+36
-23
lines changed

2 files changed

+36
-23
lines changed

ares/md/m32x/m32x.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ struct M32X {
130130
auto main() -> void;
131131
auto step(u32 clocks) -> void;
132132
auto power(bool reset) -> void;
133+
auto updateFrequency() -> void;
133134

134135
//serialization.cpp
135136
auto serialize(serializer&) -> void;

ares/md/m32x/pwm.cpp

+35-23
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
auto M32X::PWM::load(Node::Object parent) -> void {
22
stream = parent->append<Node::Audio::Stream>("PWM");
33
stream->setChannels(2);
4-
stream->setFrequency(44'100);
4+
n12 clocks = cycle - 1;
5+
updateFrequency();
56
}
67

78
auto M32X::PWM::unload(Node::Object parent) -> void {
@@ -10,36 +11,41 @@ auto M32X::PWM::unload(Node::Object parent) -> void {
1011
}
1112

1213
auto M32X::PWM::main() -> void {
13-
n12 clocks = cycle-1;
14-
if(clocks && (lmode.bit(0)^lmode.bit(1) || rmode.bit(0)^rmode.bit(1))) {
15-
if(lmode == 1) lsample = lfifo.read();
16-
if(lmode == 2) lsample = rfifo.read();
14+
n12 clocks = cycle - 1;
1715

18-
if(rmode == 1) rsample = rfifo.read();
19-
if(rmode == 2) rsample = lfifo.read();
16+
//check if cycle rate has changed and update sample rate accordingly
17+
static n12 previousCycle = cycle;
18+
if (cycle != previousCycle) {
19+
previousCycle = cycle;
20+
updateFrequency();
21+
}
22+
23+
if (clocks && (lmode.bit(0) ^ lmode.bit(1) || rmode.bit(0) ^ rmode.bit(1))) {
24+
if (lmode == 1) lsample = lfifo.read();
25+
if (lmode == 2) lsample = rfifo.read();
26+
27+
if (rmode == 1) rsample = rfifo.read();
28+
if (rmode == 2) rsample = lfifo.read();
2029

21-
lfifoLatch.bit(14) = lfifo.empty();
22-
rfifoLatch.bit(14) = rfifo.empty();
23-
mfifoLatch.bit(14) = lfifoLatch.bit(14) & rfifoLatch.bit(14);
30+
lfifoLatch.bit(14) = lfifo.empty();
31+
rfifoLatch.bit(14) = rfifo.empty();
32+
mfifoLatch.bit(14) = lfifoLatch.bit(14) & rfifoLatch.bit(14);
2433

25-
if(periods++ == n4(timer-1)) {
26-
periods = 0;
27-
m32x.shm.irq.pwm.active = 1;
28-
m32x.shs.irq.pwm.active = 1;
29-
m32x.shm.dmac.dreq[1] = dreqIRQ;
30-
m32x.shs.dmac.dreq[1] = dreqIRQ;
34+
if (periods++ == n4(timer - 1)) {
35+
periods = 0;
36+
m32x.shm.irq.pwm.active = 1;
37+
m32x.shs.irq.pwm.active = 1;
38+
m32x.shm.dmac.dreq[1] = dreqIRQ;
39+
m32x.shs.dmac.dreq[1] = dreqIRQ;
40+
}
3141
}
32-
}
3342

34-
counter += max(1, clocks);
35-
while(counter >= 522) {
36-
counter -= 522;
3743
auto left = cycle > 0 ? lsample / (f32)cycle : 0;
3844
auto right = cycle > 0 ? rsample / (f32)cycle : 0;
39-
stream->frame(left, right);
40-
}
4145

42-
step(clocks);
46+
stream->frame(left, right); // Output the frame without the loop, since the sample rate is adjusted dynamically
47+
48+
step(clocks);
4349
}
4450

4551
auto M32X::PWM::step(u32 clocks) -> void {
@@ -64,4 +70,10 @@ auto M32X::PWM::power(bool reset) -> void {
6470
lfifoLatch = 0x4000; // empty
6571
rfifoLatch = 0x4000; // empty
6672
mfifoLatch = 0x4000; // empty
73+
updateFrequency();
74+
}
75+
76+
auto M32X::PWM::updateFrequency() -> void {
77+
n12 clocks = cycle - 1;
78+
stream->setFrequency((system.frequency() * 6) / (7.0 * (2 * (clocks) - 1)));
6779
}

0 commit comments

Comments
 (0)