Using the High Speed or regular fast PWM modes of various AVR MCU's to make
sounds and tones using DDS (Direct Digital Synthesis).
On ATtiny26: (WIP!)
The attiny26 code takes a MIDI note number (0-127, 7-bit) from a read of the first 7 bits of PORTA in parallel, then outputs that particular note using a PWM channel and DDS for Sine Wave generation ( through a Low-Pass filter ). This may expand to use OC1A and OC1B to have two channels, and you select one or the other using the 8th bit of PORTA. I may add (if there is space, and spare ISR cycles) the ability to select from Square, Triange, Saw, or Sine waves for the output by using a 2-bit (0-3) control on 2 of the pins on PORTB.
* Make code to run on an ATtiny85 that has control over I2C/TWI or SPI if possible, and maybe 2 channels.
It's been quite a while since I messed with this project. But the last time I did, I connected the AVR's PWM output through the Low-Pass Filter and in series with a capacitor to a 8ohm Speaker. My code took a 7-bit MIDI note code from the pins on PORTA and then was supposed to play that note from it's output. In testing in comparison with a musical tone generator on my computer, the note entered, when coming out of the AVR was always a note higher in pitch. I'm still not sure why that is, but I just did a simple fix in the code to play one note under the entered MIDI code, so the actual tone output is correct. So now my basic goal for the project has been fulfilled, but I have some Ideas to maybe extend it, such as double channels and different wave output selections for square, sawtooth, and triangle waves.
Just tested the output signal through a simple low-pass filter, then fed into my Heathkit IO-12 oscilloscope. Showing a pretty nice sine wave so far. I'm not exactly sure if it is the correct frequency, but at least it's a sine wave.
UPDATE: It should be 261.626Hz, and the there ~3.5 periods on the display, which is refreshing at around 80Hz if the knobs are correct. (261.626Hz)/(3.5) = 74.75Hz; So this is pretty close, and I am betting that the oscilloscope is the inaccurate one here, as it is very old, the knobs are loose, and it probably hasn't been calibrated for a long time, if at all. (Also I dug it out of my school's E-Waste)
My old (but only one I own) oscilloscope:
The STK500 with the ATtiny26 in my crazy ribbon-cable based 20SOIC to 20DIP breakout, with signal from OCIA is fed into a Low-pass filter consisting of a 1k resistor and 100nF cap, which then goes to the oscilloscope.
I finally got to cleaning up and compiling the test code I wrote for the ATtiny26! This test code should be producing the "Middle C" note, with output from OC1A on PB1. The output seems to be correct when fed into my Stellaris Launchpad Logic analyser and OLS. It shows the PWM changing based on the table values. I have not listened to the audio yet ( people may be awakened! ), or added a low pass filter for the Sine Wave generation, so those will have to wait.