![]() |
Mozzi
alpha 0.01.1t
sound synthesis library for Arduino
|
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 // }