It is currently Fri Dec 15, 2017 1:31 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Tue Dec 20, 2016 7:51 pm 
Offline

Joined: Sun Feb 07, 2016 6:16 pm
Posts: 301
(This is pretty much a follow up of the conversation in Mesen's main thread, but I figured this might be better off as a thread of its own at this point)

So I've been taking another look at Mesen's square channel code, and looking at the "apu_mixer/square" test's code..

And there's something that I just can't make sense of.
In the test, square 2's duty cycle is set to 50%.
The code writes to $4007 to reset square 2's sequencer and sets the timer to 111 (i.e clock every 224 cpu cycles)
Then, it loops and writes 127 to $4011, 160 times in a row (each 896 cycles apart), before finally writing 123 on the 161th write.

The sequence looks like this, right after the $4007 write that causes the sequencer to reset to 0 (thus outputting 0 for the next 4 square cycles)
Code:
DMC Value:         127 #1          127 #2          127 #3  ... (156 more writes) ...    127 #160        123             127            [...]
Square Output:     0   0   0   0   1   1   1   1   0      ...                   ...     1   1   1   1   0   0   0   0   1   1   1   1  [...]

So odd writes (1, 3, #161) match with a "0" for the duty cycle and even writes (#2, #4, #160) match with a "1".
This means that the 161th write (value = 123) falls on a falling edge for the duty cycle (1 -> 0), which makes BOTH channels drop at the same time.
Considering the test is attempting to cancel both channels by applying the opposite change, that doesn't make sense. I would expect the exact opposite.

What am I not understanding?

Current problems I had with my code vs the wiki:
1- Writes to $4003/7 were resetting the sequencer AND the timer (instead of just the sequencer).
2- The sequencer was counting upwards instead of downwards.
(It looks like both of these might be "fixes" I took from puNES' code while attempting to make the apu_mixer tests work, but they both contradict the wiki)

After fixing these to match the wiki, I get a perfect match up (cycle-wise) between the square duty changes and the DMC writes, but the value of the square channel is always opposite of what it would need to be for it to cancel out the DMC's output.
At this point, if I invert the duty cycle so that the sequence after a $4007 write is 11110000 instead of 00001111, everything falls into place and the sound output is (to my ears) even closer to the apu_mixer/square recording than my older code.

Picture below is the (what I assume to be) NES recording that was bundled with the tests, Mesen's 0.5.3 output (bottom), and Mesen's current output if I fix both bugs, and invert the duty cycle like I said (middle).
Clearly the middle one is the closest to the recording - so what am I not getting?


Attachments:
ApuMixerSquare.png
ApuMixerSquare.png [ 10.69 KiB | Viewed 981 times ]
Top
 Profile  
 
PostPosted: Tue Dec 20, 2016 7:57 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19346
Location: NE Indiana, USA (NTSC)
Inverting the duty is on the right track. Because the waveform position counter is a down counter, it counts in the order 07654321, producing the waveform 01111000.


Top
 Profile  
 
PostPosted: Tue Dec 20, 2016 8:04 pm 
Offline

Joined: Sun Feb 07, 2016 6:16 pm
Posts: 301
Yes, it counts 07654321, but that produces 00001111 (according to the wiki), which is what I used in the sequence above (repeated 161 times).
But then that doesn't produce noise cancellation, it doubles up the sound's volume instead. (DMC goes 127 -> 123 when square goes 1 -> 0, and then 123 -> 127 happens when square does 0 -> 1)

To get the square channel to produce the opposite of the DMC channel, I need to count backwards (07654321) and invert the duty cycle values (0<->1) so that it becomes 11110000.


Top
 Profile  
 
PostPosted: Wed Dec 21, 2016 5:38 am 
Offline
User avatar

Joined: Sun Sep 19, 2004 10:59 pm
Posts: 1393
Sour wrote:
Yes, it counts 07654321, but that produces 00001111 (according to the wiki)

The wiki is wrong, then - the hardware definitely outputs 01111000 for that duty cycle, and I'm pretty sure it's been confirmed against visual2a03 (it effectively outputs D2 of the counter).

_________________
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.


Top
 Profile  
 
PostPosted: Wed Dec 21, 2016 6:32 am 
Offline

Joined: Sun Feb 07, 2016 6:16 pm
Posts: 301
Ah, now I see my mistake. Thanks for clearing this up! I always looked at the wiki's data thinking it was the internal representation of the duty cycle from indexes 0 to 7. But it does actually says that this is the actual sequence that is output, so it's actually listed as 07654321.

So I wasn't counting backwards as I originally thought.
That still leaves a 1 duty cycle gap though. Does writing to 4003/7 change the output instantly because it resets the sequencer? Or is that delayed until the next time the timer expires? I.e, when you write does it reset to index 0 and then goes to index 7 on the next time the timer is up?


Top
 Profile  
 
PostPosted: Wed Dec 21, 2016 3:19 pm 
Offline

Joined: Sun Feb 07, 2016 6:16 pm
Posts: 301
I took a look at Nintendulator's code, and it implies any write to $4000-4007 can instantly alter the channel's output - I'm not sure if this is actually written anywhere on the wiki though.

So the write to $4007 instantly resets the sequencer, and ends up setting the volume to 0.
The sequence is then 0 (on $4007 write) 1 (on next timer) 1 1 1 0 0 0 (like the wiki), with the first DMC write occurring at the same time as the first "1", this matches up perfectly with the DMC channel's output. The end result is an almost silent tone, all while keeping in line with everything that's written in the wiki.

Problem solved, I think. Thanks for the help!


Top
 Profile  
 
PostPosted: Wed Dec 21, 2016 5:48 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 10:59 pm
Posts: 1393
Sour wrote:
I took a look at Nintendulator's code, and it implies any write to $4000-4007 can instantly alter the channel's output - I'm not sure if this is actually written anywhere on the wiki though.

It's only for $4003 and $4007, and the APU Pulse page states that "The sequencer is restarted at the first value of the current sequence."

_________________
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.


Top
 Profile  
 
PostPosted: Wed Dec 21, 2016 9:22 pm 
Offline

Joined: Sun Feb 07, 2016 6:16 pm
Posts: 301
Quietust wrote:
the APU Pulse page states that "The sequencer is restarted at the first value of the current sequence."
Yea, but I always had interpreted that as "the next time the timer expires and the duty cycle moves to the next step, it'll have been reset to the start of the sequence instead".
Now that I know the actual behavior, and thinking about it from a hardware point of view (which is something I know relatively little about), it does make more sense that it would be applied immediately, though.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group