jdigen1 / arduino-tvout

Automatically exported from code.google.com/p/arduino-tvout
0 stars 0 forks source link

Audio output defect: SND_PIN sometimes left HIGH after tone() or notone() #42

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Connect oscilloscope, multimeter, LED, or other indicator to PIN 11.
2. Load any sketch that uses TVout library and includes audio via the tone() 
functions.
3. Sketch should generate multiple tones with intervals of silence in between.

What is the expected output? What do you see instead?
Use of tone(frequency,duration) or notone() should, at the completion of the 
tone, leave PIN 11 in a logic LOW state when complete, but it 
non-deterministicly leaves it in a logic HIGH state 50% of the time.

What version of the product are you using? On what operating system?
Beta1 on Ubuntu 10.04LTS 32bit.

Please provide any additional information below.
The problem arises from the use of TIMER2.  The mode used is CTC with 
TOP=OCR2A, and with a Compare Output A Mode of 01 (toggle).  The comment in 
line #869 of TVout.cpp states '//set COM2A1 to 0', but this is incorrect.

The code for notone(), as well as the code section within vsync_line() in 
video_gen.cpp responsible for stopping a tone started with 
tone(frequency,duration), correctly set TCCR2B to 0, which sets the clock 
select to none, stopping the timer.  They also correctly set the pin state to 
logic LOW with PORTB &= ~(_BV(SND_PIN)).  However, since the Compare Output A 
Mode is unaffected by either of these, PIN 11 remains connected to the Output 
Compare Unit in toggle mode, so the state of the pin cannot be predicted.

A fix is to add the line TCCR2A = 0 to both functions (line #876 in TVout.cpp 
and line #173 in video_gen.cpp), which returns the Compare Output A Mode to 
normal and reconnects PIN 11 to PORTB.  Since tone() sets TCCR2A every time it 
is called(), there should be no side effects to this fix.  This has been tested 
and works as expected.

Why does this matter?  It doesn't, provided the audio circuit driven by tone() 
is correctly designed.  However a speaker directly connected to PIN 11 might 
face (the pin's maximum source current of) 40mA for extended periods.  While 
this will amount to only 13mW, it isn't going to help battery life any.  An 
even more poorly designed audio circuit (say, a MOSFET gated by PIN 11, driving 
a speaker load) could cause serious problems.  Even a simple capacitor put in 
series with the speaker load would fix the problem in both cases, but so would 
2 lines of code.

Original issue reported on code.google.com by joeymorin on 1 Apr 2012 at 7:13