16 bit audio/waveform gen. on a duemilanove?

Since the duemilanove has at least 16 free pins, could you do 16 (or 16 +1 polarity) bit audio with a resistor ladder+NOT gate setup or something? Way I figure, if you use 16 bit audio (15 voltage+1 polarity) at 50khz sample rate, you get 320 total clock cycles per sample and 20 clock cycles per bit you need to toggle. That's plenty, right? (Especially if you wanted to write it in ASM or AVR-C (the second one you can do right in the arduino IDE)). To send audio over serial, let's say we want 50000*16Bd or 800kBd. Just to give us some spare room, let's aim for 1MBd. In the past when I've used low-level bitbanging from serial data, I used a very fast technique like this: (Note, this is for either an attiny45 or 2313, not an ATMega)

char x;
char y;
UBRRL=0; //(1MBd@16mhz, max possible is 2MBd)
UCSRB=(1<<RXEN)|(1<<TXEN);
UCSRC=(1<<UCSZ1)|(1<<UCSZ0);
//I'm skipping all of the pin input/output declarations
while(1){
     while(!(UCSRA&(1<<RXC)));
     x=UDR;
     while(!(UCSRA&(1<<RXC)));
     y=UDR;
     PORTB=x;
     PORTC=y;//you would actually have to use part of PORTD too
}

Anyway, I haven't studied the number of clock cycles each operation requires, but I think there is still plenty of headroom left in the 320 instruction limit to add more complex stuff (ie independent tone generation). Note that if this would work, the 50khz audio would actually be faster than the standard 44100khz sample rate. I think many devices use 24 bit audio, but for a non-dedicated micro I think 16 bit is impressive.

Would this work at all for complex audio/waveform generation or am I missing something?
Will

Not sure what this 15+1 bit audio format is you are talking about; you seem to be under the impression that you need a sign bit to tell it to go positive or negative? This isn't needed.

All you need to do is output your sample on the resistor ladder, then apply a negative DC voltage of half the amplitude of the output waveform to shift the ground level "up" (or bias the signal down, whichever way you want to look at it) so that the waveform is centered properly again...

I don't think 16 bit audio is outside the Arduino's capabilities, but then I haven't looked at it closely, either. Nor am I a guru in audio, either. So I can't answer your questions there...

:slight_smile:

That's true, cr0sh, but I'm not sure how to apply a -2.5 voltage, and either way I end up with the same resolution (32768 voltage levels above and below the x axis) and I feel like subtracting voltage seems a little bit iffy in terms of accuracy.
Thanks for the advice! ;D

Or you get a serial input D/A chip like this one
http://datasheets.maxim-ic.com/en/ds/MAX9850.pdf
or something similar from analog devices

Could be a lot easier to manipulate data into it than than trying to write out 16-bit parallel data with a uC that doesn't even have a complete 8-bit port when you want to receive serial data also.

just for giggles you can write asm in the arduino IDE with the appropriate tags

Don't overlook the fact that if you want 16 bit accuracy, the analogue part of your circuit needs to be accurate to 16 bits too, which means an error of no more than +/-0.5 in 65536 which is 0.0008%. So your resistors (particularly around the MSB) would need to have a tolerance of 0.0008% or better. Good luck with finding those :slight_smile: You may be able to get accuracy of 10 or 11 bits from 0.1% resistors and careful selection.

Another source of error is the noise on the output pins of the 328. For 16 bit accuracy the MSB needs to have less than 0.0008% of noise. I reckon there's at least 1% noise on the pin though, that would restrict you to 7 or 8 bit accuracy. You could try to use buffers, but then you'd need the buffer to be good to 0.0008%.

@crossroads
Yeah, this would just be for fun. Obviously it would be impractical to use arduino for this anyway.

@osgeld
Really? How do you do this? I think it would be cool to introduce yourself to ASM through the arduino IDE...

@stimmer
Haha, I knew there was a reason no one was doing this! Oh well, I guess 5 or 6 bit audio makes more sense anyway as then you actually have some free pins to use.