It is currently Mon Oct 15, 2018 9:43 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Fri Oct 19, 2012 1:50 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20656
Location: NE Indiana, USA (NTSC)
I'm thinking of a design for a synthesizer to fit in a CPLD that would work even on an NES.

Each channel would resemble an APU channel, but without hardware envelope, length counter, or sweep. Each channel has an 11-bit divider, an 8-step PWM sequencer, and a volume control.
Code:
7654 3210  $4020/$4024
TT   VVVV
||   ++++- Volume
++-------- Timbre (12.5%, 25%, 37.5%, or 50% duty)

7654 3210  $4022/$4026
PPPPPPPPP
+++++++++- Period (bits 7-0)

7654 3210  $4023/$4024
      PPP
      +++- Period (bits 10-8)

As on the 2A03 APU, the CPU frequency is pre-divided by 2 before being sent to the synthesizer as an 895 kHz clock.

Every time a channel's waveform rises or falls, the sequencer pulls /IRQ low.
When $4011 is read, the channels are summed and put on the data bus, and /IRQ goes high impedance.
So if you have two channels playing notes at about 300 Hz, you get about 1200 IRQs per second: 300 rises and 300 falls for each channel. Each IRQ takes 19 cycles to service:
Code:
  brk $00    ; 7
irq:
  dec $4011  ; 6
  rti        ; 6

Thus the CPU would spend about 1.3 percent of the time servicing IRQs. This would increase with higher frequencies, and it might be best to design the music engine to play lower frequencies on the CPLD and higher on the APU.

A CPLD needs a macrocell for each flip-flop, but it also needs a few spare macrocells for complex combinational logic. I count 64 flip-flops, meaning it might fit in a 72 macrocell CPLD, but it might not.
  • Divider reset values: 11 bits per channel
  • Volume: 4 bits per channel
  • Timbre:2 bits per channel:
  • Divider position: 11 bits per channel
  • Sequencer position: 3 bits per channel
  • Pre-scaler: 1 bit
  • IRQ flag: 1 bit

It'd need 26 pins, some of which might be shared with the mapper on a larger CPLD:
Inputs: R/W, /ROMSEL, A14-A0, M2, D7
Input/output: D6-D0

So would this be feasible?


Top
 Profile  
 
PostPosted: Fri Oct 19, 2012 2:21 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6874
Location: Canada
Why 11 bits and not 12? The APU squares are kinda lacking for bass (something that the VRC6 squares can do nicely with their extra octave, the 5B as well).


Top
 Profile  
 
PostPosted: Fri Oct 19, 2012 3:23 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4093
Any latency of the IRQ would affect the sound produced, and there will always be some latency.
What's the worst case for IRQ latency? Worst case is when the CPU is doing a sprite DMA transfer to the PPU (518 CPU cycles). Otherwise, the worst case is doing a read-modify-write nnnn,X instruction for 7 cycles at the same time as a DMC fetch, so that's about 9 cycles.

Let's say there's a sampling rate of 44100 Hz, and use Samples as the unit for measuring jitter. One frame is 29780.66 CPU cycles, and covers 734 samples of audio. If there was a sprite DMA delaying an interrupt response, it would jitter up to 13 samples, enough for quite an audible artifact. The other 9 cycles jitter is about .2 samples, and probably won't matter at all.

So you'd get crummy sound when running a game with sprites.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Fri Oct 19, 2012 4:16 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20656
Location: NE Indiana, USA (NTSC)
rainwarrior wrote:
Why 11 bits and not 12? The APU squares are kinda lacking for bass

Mostly trying to leave a bit of wiggle room for the compiler to fit it all.

Dwedit wrote:
Any latency of the IRQ would affect the sound produced

True, but audibly?

Dwedit wrote:
at the same time as a DMC fetch

This would not be used together with DMC automatic playback due to conflict on $4011. But you have a point about sprites.


Top
 Profile  
 
PostPosted: Fri Oct 19, 2012 6:32 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10892
Location: Rio de Janeiro - Brazil
The sprite issue is the true deal breaker of this way of generating sound. What good are a couple of extra sound channels when you can't even use the sprites right?


Top
 Profile  
 
PostPosted: Fri Oct 19, 2012 6:49 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20656
Location: NE Indiana, USA (NTSC)
So is there a better alternative to requiring each 72-pin console owner to solder?


Top
 Profile  
 
PostPosted: Fri Oct 19, 2012 7:31 pm 
Offline
User avatar

Joined: Mon Sep 27, 2004 8:33 am
Posts: 3715
Location: Central Texas, USA
PC's solved this in the 1980s:
Image


Top
 Profile  
 
PostPosted: Fri Oct 19, 2012 8:14 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10892
Location: Rio de Janeiro - Brazil
Hahaha! Muffled sounds coming from the cart would be really cool! XD

tepples wrote:
So is there a better alternative to requiring each 72-pin console owner to solder?

I guess this is the most straight forward solution so far... But people who are stuck with RF still won't be able to use it.

If you really want a transparent, non-weird solution that will work for everyone without severely crippling the software, I guess you'll have to make your mapper a bit more complex and implement a DMA feature that can be used instead of the one in the CPU. If you can make it more general so that it can also be used with $2007, even better!


Top
 Profile  
 
PostPosted: Fri Oct 19, 2012 9:19 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4093
I believe it's actually possible to get around the sprite problem with software.
You can anticipate when the IRQs will fire, and know whether to update sprites immediately, or wait until after the interrupt.

There are about 29780.66 cycles in a frame. You tell the timer what the period should be in units of clock cycles.
Calculate the number of cycles until the next interrupt after the next vblank. Something like period - (29780.66 - oldTimerValue) % period. If your result is less than 518, wait until after the interrupt happens before you upload sprites, otherwise upload sprites immediately.

Example: your audio frequency is 261.625Hz, so you need an interrupt twice as often. The period is 3420 cycles. You start at 0.
Interrupt will happen ~8.7 times before vblank happens. ~.3 periods are remaining, which is 1000 cycles until the next interrupt. You have more than 518 cycles left, so you can safely upload sprite data without messing the audio up.

Once you exceed 1727.58Hz as your audio frequency, you will always be interrupted during a sprite DMA, but you can still try to lessen the effects by getting the minimum amount of jitter.

You need to adjust for different regions, like PAL or Dendy, and need to keep track of what value the timer is expected to be at. Also, if you reset the timer's phase, you can reset your counter to zero as well.

So your code ends up looking like this:
VBLANK:
possibly update timer period, so you know you did it first thing during the frame.
check if we want to update sprites before the interrupt
If we do, update sprites
otherwise, update sprites the next time the IRQ is handled.
After completing all the vblank code, do the math and figure out when the next interrupt will happen for the next frame.

And you can probably test this stuff out on any existing emulator by using Mapper #73. You need a longer interrupt handler of course.

edit: This is designed for a single channel.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Sat Oct 20, 2012 5:22 am 
Offline

Joined: Wed Mar 09, 2005 9:08 am
Posts: 418
Quote:
True, but audibly?


That's a good question indeed... I find we often worry about things that while sounding like a showstopper in theory may have little practical consequence. But the only way to know is to try. So how about implementing this propsed wave generator in software first, and inserting those delays in your stream to hear how it will sound?...


Top
 Profile  
 
PostPosted: Sat Oct 20, 2012 1:36 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4093
Here's an example of what it might sound like without correcting for timing issues.
Little demo program that plays Twinkle Twinkle Little Star with Konami VRC3 IRQs.
Compatibility: Works on Nintendulator, Bizhawk, and PuNES. Fails on FCEUX, Nestopia, Bizhawk, and possibly everything else.

One of the programs does no Sprite DMA at all.
The other program blindly does Sprite DMA every frame without trying to work around the timing issues.


Attachments:
twinkle.zip [3.23 KiB]
Downloaded 178 times

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Last edited by Dwedit on Sat Oct 20, 2012 8:38 pm, edited 1 time in total.
Top
 Profile  
 
PostPosted: Sat Oct 20, 2012 1:49 pm 
Offline

Joined: Wed Mar 09, 2005 9:08 am
Posts: 418
That was quick :)

Unfortunately, both programs sound like crap in Nintendulator on my slowish Netbook, and my Powerpak won't run it, so can't comment on how it sounds :( would love to hear a recording from real hardware...


Top
 Profile  
 
PostPosted: Sat Oct 20, 2012 2:04 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20656
Location: NE Indiana, USA (NTSC)
Image
VRC3 is blue (not yet implemented on PowerPak). Could you modify it to work on something green?

Here's another way to simulate it:
  1. Load a wave file of a chiptune recording in 735-sample blocks.
  2. Set the first 13 samples of each block equal to the first sample. Or to simulate "trying to work around the timing issues", set the first 13 samples equal to the seventh sample.
  3. Write the modified wave file.
Should I write a Python program that does this?


Top
 Profile  
 
PostPosted: Sat Oct 20, 2012 2:07 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4093
I picked VRC3 because it was the only mapper that automatically reloaded the IRQ counter to the latch value after the counter completes. It acts just like the timers on the GBA. None of the other mappers do that.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Sat Oct 20, 2012 2:12 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20656
Location: NE Indiana, USA (NTSC)
I think RAMBO-1 (#64) does that. Its counterpart to MMC3's scanline counter can count either PA12 rises (like MMC3) or M2/4.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 5 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