Thanks for your kind words.
On Aug 26, 11:45 pm, "
telbo...@googlemail.com"
<
telbo...@googlemail.com> wrote:
> And at that point my brain melted. Any chance anyone can explain
> what's going on in audioOn() ?
Sure. There is a lot to understand here though. First, you'll need the
data sheet for the processor in the Arduino. I'm assuming you're using
a 328 Arduino, so here's the current data sheet.
http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf
Read chapter 17. You should recognise some of the names, particularly
when you get to 17.11.
_BV() is a bit vector. _BV(0) is bit 0, so has value '1' (00000001 in
binary). _BV(1) = 2 = 00000010 bin, _BV(2) = 4 = 00000100 bin etc. _BV
(n) has a '1' in the n-th bit.
So taking those lines one at a time:
TCCR2A = _BV(COM2B1) | _BV(WGM20);
This sets up the TCCR2A register. The '|' is a logic OR, so the value
being loaded into it has a '1' in the COM2B1 and WGM20 position, '0'
elsewhere. Therefore, it sets Timer/Counter 2 Control Register A to
the following:
WGM22/21/20 = 0/0/1: PWM, Phase Correct mode (WGM2 will be zeroed in
the line below)
COM2A1/COM2A0 = 0/0 : Normal port operation, OC2A disconnected.
COM2B1/COM2B0 = 1/0 : Clear OC2B on Compare Match when up-counting.
Set OC2B on Compare Match when down-counting.
TCCR2B = _BV(CS20);
Set Timer/Counter 2 Control Register B to the following:
FOC2A/2B: Not set.
WGM22 = 0: Sets PWM mode - see above.
CS22/21/20 = 0/0/1: Set timer clock source to clkT2S which is 16MHz on
most Arduinos. (See Arduino board schematic and data sheet chapter 8)
TIMSK2 = _BV(TOIE2);
Enable interrupt on Timer/Counter2 Overflow. (See Chapter 11 and the
AVR-GCC manual).
So what this does is get Timer2 to count 16 million times per second.
It counts up 0 to 255, then down 255 to 0. (Atmel calls this 'Phase
Correct PWM'). When OCR2B (Auduino calls this 'PWM_VALUE') is more
than the count, the OC2B is high. Otherwise it is low. The OC2B is
connected to pin 5 of the microprocessor, which maps to Arduino pin 3.
(Check data sheet section 1, and the Arduino board schematic).
Therefore, it sets up pin 3 to be a PWM, like analogWrite() - but with
two additional features.
1) An interrupt occurs every cycle. That calls the synthesis maths
routine in the background.
2) The PWM runs much faster than it normally would. The Arduino PWMs
normally run at about 500 or 1000Hz, but Auduino runs them at 31250Hz.
It needs to run them this fast to generate audio waveforms. The PWM
process generates a buzz, but at 31kHz that buzz is past the hearing
range of the human ear (which works up to about 17kHz).
Now if you want to generate a second output, you'll need to do the
following.
1) Because everything is tied to Timer2, by far the easiest solution
is to use the second comparator output for that timer, OC2A. That pin
outputs to Arduino digital pin 11, so now you know why it's labelled
'PWM' on the PCB. You'll need to configure that pin as an output, like
pin 3.
2) Now you need to adjust the setting of TCCR2A to enable PWM mode on
OC2A.
3) You need to adjust the interrupt routine to both OCR2A and OCR2B
are updated with new values every sample.
I know - your head has probably exploded at that point! But persist.
There is a lot to understand, but once you do, you will understand a
lot more how Arduino works internally, and you will have many extra
tools in your programming tool chest. Generating music, speech, TV
signals, data protocols and more are all possible once you've mastered
the data sheet.
Good luck!
Peter