Mozzi  alpha 0.01.1t
sound synthesis library for Arduino
 All Classes Functions Typedefs
MozziGuts.cpp
00001 /*
00002  * MozziGuts.cpp
00003  *
00004  * Copyright 2012 Tim Barrass.
00005  *
00006  * This file is part of Mozzi.
00007  *
00008  * Mozzi is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 3 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * Mozzi is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with Mozzi.  If not, see <http://www.gnu.org/licenses/>.
00020  *
00021  */
00022 
00023 
00024 #include "MozziGuts.h"
00025 #include <util/atomic.h>
00026 #include "utils.h"
00027 
00028 
00029 
00030 
00031 
00045 void startMozzi(unsigned int control_rate_hz)
00046 {
00047 
00048                 // audio
00049                 pinMode(AUDIO_CHANNEL_1_PIN, OUTPUT);           // set pin to output for audio
00050                 Timer1.initialize(1000000UL/AUDIO_RATE);                        // set period
00051                 Timer1.pwm(AUDIO_CHANNEL_1_PIN, AUDIO_BIAS);                    // pwm pin, 50% of Mozzi's duty cycle, ie. 0 signal
00052 
00053                 #ifdef MOZZI_AC_OUTPUT
00054                 // alternative audio technique from "toneAC.cpp" by Tim Eckel - teckel@leethost.com
00055                 // Copyright 2013 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html
00056                 // to get louder output form a speaker by using two out of phase pins in push/pull fashion
00057                 //TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(COM1B0); // Inverted/none-inverted mode (AC).
00058                 Timer1.pwm(AUDIO_CHANNEL_1_AC_PIN, AUDIO_BIAS);  // AC pin
00059                 TCCR1A |= _BV(COM1B0); // Invert AC pin output
00060                 #endif
00061 
00062                 // TB 15-2-2013 Replaced this line with the ISR below
00063                 Timer1.attachInterrupt(outputAudio);                                            // call outputAudio() on each interrupt
00064 
00065                 // control
00066                 // Using Timer0 for control disables Arduino's time functions
00067                 // but also saves on the interrupts and blocking action of those functions.
00068                 // May add a config option for Using Timer2 instead if needed.
00069                 // (MozziTimer2 can be re-introduced for that).
00070                 TimerZero::init(1000000/control_rate_hz,updateControl); // set period, attach updateControl()
00071                 TimerZero::start();
00072 
00073 }
00074 
00075 /*
00076 // interrupt service routine
00077 ISR(TIMER1_OVF_vect)
00078 {
00079                 outputAudio();
00080 }
00081 */
00082 
00083 // ring buffer for audio output
00084 #define BUFFER_NUM_CELLS 256
00085 static int output_buffer[BUFFER_NUM_CELLS];
00086 
00087 static volatile unsigned char num_out; // shared by audioHook() (in loop()), and outputAudio() (in audio interrupt), where it is changed // test
00088 
00089 
00100 void audioHook()
00101 {
00102                 static unsigned char num_in = 0;
00103                 unsigned int gap = num_in - num_out; // wraps to a big number if it's negative
00104 
00105                 if(gap < BUFFER_NUM_CELLS) // prevent writing over cells which haven't been output yet
00106                 {
00107                                 output_buffer[num_in++] = updateAudio() + AUDIO_BIAS;
00108                 }
00109 }
00110 
00111 
00112 /* This is the callback routine attached to the Timer1 audio interrupt.
00113 It moves sound data from the output buffer to the Arduino output register,
00114 running at AUDIO_RATE.
00115 */
00116 inline
00117 static void outputAudio()
00118 { // takes 1 us or shorter, digital scope seems to have trouble catching it
00119                 //SET_PIN13_HIGH;
00120                 #ifdef MOZZI_AC_OUTPUT
00121                 AUDIO_CHANNEL_1_OUTPUT_REGISTER =  AUDIO_CHANNEL_1_AC_OUTPUT_REGISTER = output_buffer[num_out++];
00122                 #else
00123                 AUDIO_CHANNEL_1_OUTPUT_REGISTER =  output_buffer[num_out++];
00124                 #endif
00125                 //SET_PIN13_LOW;
00126 }
00127 
00128 // Unmodified TimerOne.cpp has TIMER3_OVF_vect.
00129 // Watch out if you update the library file.
00130 // The symptom will be no sound.
00131 // ISR(TIMER1_OVF_vect)
00132 // {
00133 //              Timer1.isrCallback();
00134 // }