CPLD square wave synthesizer

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderator: Moderators

tepples
Posts: 22603
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

CPLD square wave synthesizer

Post by tepples »

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: Select all

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: Select all

  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?
User avatar
rainwarrior
Posts: 8719
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: CPLD square wave synthesizer

Post by rainwarrior »

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).
User avatar
Dwedit
Posts: 4833
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: CPLD square wave synthesizer

Post by Dwedit »

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!
tepples
Posts: 22603
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: CPLD square wave synthesizer

Post by tepples »

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.
User avatar
tokumaru
Posts: 12385
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: CPLD square wave synthesizer

Post by tokumaru »

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?
tepples
Posts: 22603
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: CPLD square wave synthesizer

Post by tepples »

So is there a better alternative to requiring each 72-pin console owner to solder?
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: CPLD square wave synthesizer

Post by blargg »

PC's solved this in the 1980s:
Image
User avatar
tokumaru
Posts: 12385
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: CPLD square wave synthesizer

Post by tokumaru »

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!
User avatar
Dwedit
Posts: 4833
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: CPLD square wave synthesizer

Post by Dwedit »

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!
Bananmos
Posts: 552
Joined: Wed Mar 09, 2005 9:08 am
Contact:

Re: CPLD square wave synthesizer

Post by Bananmos »

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?...
User avatar
Dwedit
Posts: 4833
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: CPLD square wave synthesizer

Post by Dwedit »

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 574 times
Last edited by Dwedit on Sat Oct 20, 2012 8:38 pm, edited 1 time in total.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Bananmos
Posts: 552
Joined: Wed Mar 09, 2005 9:08 am
Contact:

Re: CPLD square wave synthesizer

Post by Bananmos »

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...
tepples
Posts: 22603
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: CPLD square wave synthesizer

Post by tepples »

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?
User avatar
Dwedit
Posts: 4833
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: CPLD square wave synthesizer

Post by Dwedit »

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!
tepples
Posts: 22603
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: CPLD square wave synthesizer

Post by tepples »

I think RAMBO-1 (#64) does that. Its counterpart to MMC3's scanline counter can count either PA12 rises (like MMC3) or M2/4.
Post Reply