Propeller DUTY D/A issue
BradC
Posts: 2,601
This has been driving me absolutely mental for weeks now and I've finally tracked it down.
If you still have vaguely youthful hearing and a good pair of headphones, run this code on a demoboard.
You would think that as frqa never changes, you should never see a change in the output level. As the demoboard D/A output is coupled by a couple of 1uF caps to the headphone amp what you *should* get is absolute silence + what I would have thought was perhaps a very small hiss (it is being modulated after all).
What you actually get is a crystal clear tone.
Try values from $8003_0000 to $8008_0000 and see how the tone changes.
This also works on the negative side of analogue 0 here and means that as you reproduce a small analogue signal that crosses 0, you get a massive amount of harmonic content injected on top of your signal that manifests itself as noise.
If you use both counters it gets far worse as they appear to interact with one another.
Uncomment the counter b lines above to double the volume of the noise, even though counter b is set to $8000_0000, which in a solo counter creates no noise at all.
Have I done something completely wrong here?
I can't be the first to notice this, so I figure I'm doing something dumb.
I've been chasing this for weeks now on my proto-board, so I thought it might be something my hardware was doing, but I can reproduce it clear as a bell on a stock demo board, so maybe it's not my hardware after all.
Now the reason this has been driving me nuts is my D/A cog runs both counters as independent D/A units. I accept a signed input, scale it and add $8000_0000 to it to give me a nicely biased analogue signal. As my input signals disappear towards zero they get this noise superimposed on them which comes out has horrid harmonic distortion.
Is there a better way to achieve what I'm trying to do? (2 separate 16 bit D/A outputs)
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
lt's not particularly silly, is it?
If you still have vaguely youthful hearing and a good pair of headphones, run this code on a demoboard.
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 PUB Go dira := 1<<10 + 1<<11 ctra := %00110 << 26 + 10 frqa := $8003_0000 ' ctrb := %00110 << 26 + 11 ' frqb := $8000_0000 repeat
You would think that as frqa never changes, you should never see a change in the output level. As the demoboard D/A output is coupled by a couple of 1uF caps to the headphone amp what you *should* get is absolute silence + what I would have thought was perhaps a very small hiss (it is being modulated after all).
What you actually get is a crystal clear tone.
Try values from $8003_0000 to $8008_0000 and see how the tone changes.
This also works on the negative side of analogue 0 here and means that as you reproduce a small analogue signal that crosses 0, you get a massive amount of harmonic content injected on top of your signal that manifests itself as noise.
If you use both counters it gets far worse as they appear to interact with one another.
Uncomment the counter b lines above to double the volume of the noise, even though counter b is set to $8000_0000, which in a solo counter creates no noise at all.
Have I done something completely wrong here?
I can't be the first to notice this, so I figure I'm doing something dumb.
I've been chasing this for weeks now on my proto-board, so I thought it might be something my hardware was doing, but I can reproduce it clear as a bell on a stock demo board, so maybe it's not my hardware after all.
Now the reason this has been driving me nuts is my D/A cog runs both counters as independent D/A units. I accept a signed input, scale it and add $8000_0000 to it to give me a nicely biased analogue signal. As my input signals disappear towards zero they get this noise superimposed on them which comes out has horrid harmonic distortion.
Is there a better way to achieve what I'm trying to do? (2 separate 16 bit D/A outputs)
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
lt's not particularly silly, is it?
Comments
Two potential solutions spring to mind. Reset your zero signal value to some other value less prone to harmonic generation, say 2/5th i.e. $6666_6666 or some prime number. Alternatively an anti-aliasing noise signal could be added to the lower FRQx or PHSx bits. Something as simple as XORing CNT with the lower 16-17bits of FRQx might work. Using an actual random number generator is likely to work better. Here is a List of RNGs from Wikipedia, and a bloody fast RNG I just coded in ASM myself. (Look in the external link provided by wikipedia, it's got a simpler version of the RNG on the top of page 4)
My two bits,
Lawson
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Lunch cures all problems! have you had lunch?
I'll just order some external DAC's..
Makes me wonder about the amount of distortion people are getting when they use the duty D/A for playing WAV files..
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
lt's not particularly silly, is it?
Crazy ideas R'us
Lawson
*edit* I think 16-bits precision at audio frequencies is beyond the capabilities of DUTY mode counters at 80Mhz. To get 16-bits of precision the output low pass filter needs to average at least 2^16 clock cycles of output. I.e. the cut off frequency of the output filter would have to be 1.22Khz or lower. (12 to 13-bit precision looks much more reasonable)
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Lunch cures all problems! have you had lunch?
Post Edited (Lawson) : 9/19/2009 4:47:25 PM GMT
(Sorry I can't just test this, I don't have a demo board...I'm currently doing a quick protoboard solder-up to hear this for myself.)
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
lonesock
Piranha are people too.
High frequency distortion?
Brad, is this the same project as the noisy A/D performance? There I think you concluded that it would take an external A/D, right? Now an external D/A too.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
Thanks Tracy, that is precisely the problem and I now see there is really no practical resolution to it.
Yeah it is unfortunately.
I'm seeing how minimal I can get for a guitar effects processor. I had hoped I'd be able to get as minimal as a propeller, eeprom and quad op-amp as for what I'm doing I could get away with fairly low resolution if it was clean, but I appear to need an external A/D and D/A to get anything vaguely clean and linear. It's only an extra 2 8 pin chips + a voltage reference, but it's still an extra $6 in parts and board realestate. If I'm adding a pair of converters I may as well add a high speed/resolution codec instead (which I was hoping to avoid).
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
lt's not particularly silly, is it?
I've heard some really clean-sounding audio from the Demo Board, so I'm betting your issues can be resolved without resorting to an external D/A. You need to make sure that "analog zero" is $8000_0000. If your digital input signal varies from that for some reason, it's easy enough to program a low-pass filter to compute a moving average. Each new frqa would then become:
····frqa := $8000_0000 + instantaneous_signal - moving_average
-Phil
Edit: Said phsa, meant frqa.
Post Edited (Phil Pilgrim (PhiPi)) : 9/20/2009 8:05:54 AM GMT
My analogue zero is $8000_0000. I use a very long average low pass filter to be sure of that (and I spit the actual values out to the TV to verify what I'm hearing on the converter). As the audio crosses around $800[noparse][[/noparse]12345]_0000 and the other side of the zero it incurs harmonic distortion.
I even fed it a synthesized sine wave at 0.5HZ, and still got audible noise around the zero cross.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
lt's not particularly silly, is it?
Can you post some simple example code that runs on the Demo Board to illustrate this phenomenon with real audio?
-Phil
Difficult to set the cut off frequency high enough when you have low frequency components that go down below 110HZ and slowly drop in amplitude to analogue zero. You tend to spend quite a bit of time in that nasty portion of the waveform.
Here's some code that generates a nice clean(ish) sine wave at about 130HZ. It slowly steps the volume down by effectively right shifting the sine values (ie left shifting them less) prior to bias adjustment and remains relatively clean until it gets down to the lower volume levels, where the DAC noise becomes quite clearly audible.
Not the greatest test in the world, but clearly demonstrates the noise I'm on about (unless of course I've bolloxed the code and it's generating some weird interference at low volume levels). Short of digitising some low frequency guitar waveforms and putting a huge DAT block in this is the best I can probably manage.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
lt's not particularly silly, is it?
Here's your code, which I've modified to dither the amplitude just slightly in order to eliminate the pattern noise you're hearing. The amount of dithering is set by the variable ditheramt. It it's set too high, the white noise it produces will be all too apparent.
-Phil
Post Edited (Phil Pilgrim (PhiPi)) : 9/24/2009 7:52:17 PM GMT