![]() |
Mozzi
alpha 0.01.1s
sound synthesis library for Arduino
|
00001 /* 00002 MozziTimer2.cpp - Using timer 2 (or 4 on ATmega32U4) with a configurable interrupt rate. 00003 00004 Copyright 2012 Tim Barrass 00005 00006 This file is part of Mozzi. 00007 00008 Combines the hardware compatibility of Flexitimer2/MsTimer2 with the 00009 precision and efficiency of TimerTwo library (unknown, from https://bitbucket.org/johnmccombs, 4/2/2012), 00010 with other tweaks. 00011 00012 FlexiTimer2 00013 Wim Leers <work@wimleers.com> 00014 00015 Based on MsTimer2 00016 Javier Valencia <javiervalencia80@gmail.com> 00017 00018 History: 00019 31/Jan/2013 (TB) - added " || defined(__AVR_ATmega644P__)" 00020 wherever __AVR_ATmega328P__ is included in a list 00021 25/Aug/2012 (TB) - Replaced scheme for setting up timers with 00022 one based on TimerTwo library. 00023 Kept precompiler directives selecting processor models. 00024 16/Dec/2011 - Added Teensy/Teensy++ support (bperrybap) 00025 note: teensy uses timer4 instead of timer2 00026 25/April/10 - Based on MsTimer2 V0.5 (from 29/May/09) 00027 00028 This library is free software; you can redistribute it and/or 00029 modify it under the terms of the GNU Lesser General Public 00030 License as published by the Free Software Foundation; either 00031 version 2.1 of the License, or (at your option) any later version. 00032 00033 This library is distributed in the hope that it will be useful, 00034 but WITHOUT ANY WARRANTY; without even the implied warranty of 00035 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00036 Lesser General Public License for more details. 00037 00038 You should have received a copy of the GNU Lesser General Public 00039 License along with this library; if not, write to the Free Software 00040 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00041 */ 00042 00043 #include <MozziTimer2.h> 00044 #include <stdlib.h> 00045 00046 00047 bool MozziTimer2::start_; 00048 void (*MozziTimer2::f_)(); 00049 unsigned MozziTimer2::period_; 00050 00051 unsigned char MozziTimer2::set(unsigned int usec, void (*f)(), bool start) 00052 { 00053 f_ = f; 00054 start_ = start; 00055 00056 // assume F_CPU is a multiple of 1000000 00057 // number of clock ticks to delay usec microseconds 00058 unsigned long ticks = usec * (F_CPU/1000000); 00059 00060 unsigned char num_prescale_factors; 00061 00062 #if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_ATmega644P__) 00063 00064 // table by prescale = 2^n where n is the table index 00065 num_prescale_factors = 11; 00066 unsigned char * preScale; 00067 preScale = (unsigned char*) calloc (num_prescale_factors, sizeof(unsigned char)); 00068 preScale[0] = (1 << CS20); 00069 preScale[1] = 0; 00070 preScale[2] = 0; 00071 preScale[3] = (1 << CS21); 00072 preScale[4] = 0; 00073 preScale[5] = (1 << CS21) | (1 << CS20); 00074 preScale[6] = (1 << CS22); 00075 preScale[7] = (1 << CS22) | (1 << CS20); 00076 preScale[8] = (1 << CS22) | (1 << CS21); 00077 preScale[9] = 0; 00078 preScale[10] = (1 << CS22) | (1 << CS21) | (1 << CS20); 00079 00080 // determine prescale factor and TOP/OCR2A value 00081 // use minimum prescale factor 00082 unsigned char ps, i; 00083 for (i = 0; i < num_prescale_factors; i++) 00084 { 00085 ps = preScale[i]; 00086 if (ps && (ticks >> i) <= 256) 00087 break; 00088 } 00089 00090 //return error if usec is too large 00091 if (i == num_prescale_factors) 00092 { 00093 free (preScale); 00094 return false; 00095 } 00096 00097 free (preScale); 00098 00099 period_ = ((long)(ticks >> i) * (1 << i))/ (F_CPU /1000000); 00100 00101 // disable timer 2 interrupts 00102 TIMSK2 = 0; 00103 00104 // use system clock (clkI/O). 00105 ASSR &= ~(1 << AS2); 00106 /* real 00107 // Clear Timer on Compare Match (CTC) mode 00108 TCCR2A = (1 << WGM21); 00109 */ 00110 // test 00111 //TCCR2B = _BV(WGM23); // set mode as phase and frequency correct pwm, stop the timer 00112 //TCCR2A = 0; // clear control register A 00113 // TCCR2A = _BV(COM2B1) | _BV(WGM20) | _BV(WGM22);// | _BV(COM2A1); // fast pwm, Clear OC2B on Compare Match when up-counting. Set OC2B on Compare Match when down-counting. TOP = OCRA. PWM pin cleared on 00114 // TCCR2B = ps; 00115 // ken sherriff 00116 TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20); 00117 TCCR2B = _BV(WGM22) | _BV(CS22); 00118 // end test 00119 /* 00120 // only need prescale bits in TCCR2B 00121 TCCR2B = ps; 00122 */ 00123 00124 00125 00126 // set TOP so timer period is (ticks >> i) 00127 OCR2A = (ticks >> i) - 1; 00128 00129 return true; 00130 00131 #elif defined (__AVR_ATmega8__) // same table as above, but shorter names and TCCR2 is different 00132 00133 // table by prescale = 2^n where n is the table index 00134 num_prescale_factors = 11; 00135 unsigned char * preScale; 00136 preScale = (unsigned char*) calloc (num_prescale_factors, sizeof(unsigned char)); 00137 preScale[0] = (1 << CS20); 00138 preScale[1] = 0; 00139 preScale[2] = 0; 00140 preScale[3] = (1 << CS21); 00141 preScale[4] = 0; 00142 preScale[5] = (1 << CS21) | (1 << CS20); 00143 preScale[6] = (1 << CS22); 00144 preScale[7] = (1 << CS22) | (1 << CS20); 00145 preScale[8] = (1 << CS22) | (1 << CS21); 00146 preScale[9] = 0; 00147 preScale[10] = (1 << CS22) | (1 << CS21) | (1 << CS20); 00148 00149 // determine prescale factor and TOP/OCR2 value 00150 // use minimum prescale factor 00151 unsigned char ps, i; 00152 for (i = 0; i < num_prescale_factors; i++) 00153 { 00154 ps = preScale[i]; 00155 if (ps && (ticks >> i) <= 256) 00156 break; 00157 } 00158 00159 //return error if usec is too large 00160 if (i == num_prescale_factors) 00161 { 00162 free (preScale); 00163 return false; 00164 } 00165 00166 free (preScale); 00167 00168 period_ = ((long)(ticks >> i) * (1 << i))/ (F_CPU /1000000); 00169 00170 // disable timer 2 interrupts 00171 TIMSK = 0; 00172 00173 // use system clock (clkI/O). 00174 ASSR &= ~(1 << AS2); 00175 00176 // Clear Timer on Compare Match (CTC) mode and set prescale bits 00177 TCCR2 = (1 << WGM21) | ps; 00178 00179 // set TOP so timer period is (ticks >> i) 00180 OCR2 = (ticks >> i) - 1; 00181 00182 return true; 00183 00184 #elif defined (__AVR_ATmega128__) // like 328 timer 0, with short names 00185 00186 // table by prescale = 2^n where n is the table index 00187 num_prescale_factors = 11; 00188 unsigned char * preScale; 00189 preScale = (unsigned char*) calloc (num_prescale_factors, sizeof(unsigned char)); 00190 preScale[0] = (1 << CS00); 00191 preScale[1] = 0; 00192 preScale[2] = 0; 00193 preScale[3] = (1 << CS01); 00194 preScale[4] = 0; 00195 preScale[5] = 0; 00196 preScale[6] = (1 << CS01) | (1 << CS00); 00197 preScale[7] = 0; 00198 preScale[8] = (1 << CS02); 00199 preScale[9] = 0; 00200 preScale[10] = (1 << CS02) | (1 << CS00); 00201 00202 // determine prescale factor and TOP/OCR2 value 00203 // use minimum prescale factor 00204 unsigned char ps, i; 00205 for (i = 0; i < num_prescale_factors; i++) 00206 { 00207 ps = preScale[i]; 00208 if (ps && (ticks >> i) <= 256) 00209 break; 00210 } 00211 00212 //return error if usec is too large 00213 if (i == num_prescale_factors) 00214 { 00215 free (preScale); 00216 return false; 00217 } 00218 00219 free (preScale); 00220 00221 period_ = ((long)(ticks >> i) * (1 << i))/ (F_CPU /1000000); 00222 00223 // disable timer 2 interrupts 00224 TIMSK = 0; 00225 00226 // use system clock (clkI/O). 00227 ASSR &= ~(1 << AS0); 00228 00229 // Clear Timer on Compare Match (CTC) mode and set prescale bits 00230 TCCR2 = (1 << WGM21) | ps; 00231 00232 // set TOP so timer period is (ticks >> i) 00233 OCR2 = (ticks >> i) - 1; 00234 00235 return true; 00236 00237 #elif defined (__AVR_ATmega32U4__) 00238 00239 TCCR4B = 0; 00240 TCCR4A = 0; 00241 TCCR4C = 0; 00242 TCCR4D = 0; 00243 TCCR4E = 0; 00244 00245 // table by prescale = 2^n where n is the table index 00246 num_prescale_factors = 15; 00247 unsigned char * preScale; 00248 preScale = (unsigned char*) calloc (num_prescale_factors, sizeof(unsigned char)); 00249 preScale[0] = (1 << CS40); 00250 preScale[1] = (1 << CS41); 00251 preScale[2] = (1 << CS40) | (1 << CS41); 00252 preScale[3] = (1 << CS42); 00253 preScale[4] = (1 << CS40) | (1 << CS42); 00254 preScale[5] = (1 << CS41) | (1 << CS42); 00255 preScale[6] = (1 << CS40) | (1 << CS41) | (1 << CS42); 00256 preScale[7] = (1 << CS43); 00257 preScale[8] = (1 << CS40) | (1 << CS43); 00258 preScale[9] = (1 << CS41) | (1 << CS43); 00259 preScale[10] = (1 << CS40) | (1 << CS41) | (1 << CS43); 00260 preScale[11] = (1 << CS42) | (1 << CS43); 00261 preScale[12] = (1 << CS40) | (1 << CS42) | (1 << CS43); 00262 preScale[13] = (1 << CS41) | (1 << CS42) | (1 << CS43); 00263 preScale[14] = (1 << CS40) | (1 << CS41) | (1 << CS42) | (1 << CS43); 00264 00265 // determine prescale factor and TOP/OCR4C value 00266 // use minimum prescale factor 00267 unsigned char ps, i; 00268 for (i = 0; i < num_prescale_factors; i++) 00269 { 00270 ps = preScale[i]; 00271 if (ps && (ticks >> i) <= 256) 00272 break; 00273 } 00274 00275 //return error if usec is too large 00276 if (i == num_prescale_factors) 00277 { 00278 free (preScale); 00279 return false; 00280 } 00281 00282 free (preScale); 00283 00284 period_ = ((long)(ticks >> i) * (1 << i))/ (F_CPU /1000000); 00285 00286 // disable timer 4 interrupts 00287 TIMSK4 = 0; 00288 00289 // set prescale bits in TCCR4B (not sure if/why PSR4 is needed, doc says it resets the prescaler) 00290 TCCR4B = ps | (1<<PSR4); 00291 00292 // set TOP so timer period is (ticks >> i) 00293 OCR4A = (ticks >> i) - 1; 00294 00295 return true; 00296 00297 #else 00298 #error Unsupported CPU type 00299 #endif 00300 00301 } 00302 00303 00304 00305 void MozziTimer2::start() 00306 { 00307 #if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_ATmega644P__) 00308 00309 TIMSK2 |= (1 << OCIE2A); 00310 00311 #elif defined (__AVR_ATmega8__) || (__AVR_ATmega128__) 00312 00313 TIMSK |= (1 << OCIE2); 00314 00315 #elif defined (__AVR_ATmega32U4__) 00316 00317 TIMSK4 |= (1 << OCIE4A); 00318 00319 #endif 00320 } 00321 00322 00323 00324 void MozziTimer2::stop() 00325 { 00326 #if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_ATmega644P__) 00327 00328 TIMSK2 &= ~(1 << OCIE2A); 00329 00330 #elif defined (__AVR_ATmega8__) || (__AVR_ATmega128__) 00331 00332 TIMSK &= ~(1<<OCIE2); 00333 00334 #elif defined (__AVR_ATmega32U4__) 00335 00336 TIMSK4 = 0; 00337 00338 #endif 00339 } 00340 00341 00342 #if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_ATmega644P__) 00343 00344 // interrupt service routine that wraps a user defined function supplied by attachInterrupt 00345 ISR(TIMER2_OVF_vect, ISR_NOBLOCK) 00346 { 00347 (*MozziTimer2::f_)(); 00348 } 00349 00350 /* 00351 ISR(TIMER2_COMPA_vect, ISR_NOBLOCK) // ISR_NOBLOCK so it can be interrupted by Timer 1 (audio) 00352 { 00353 // disable timer 2 interrupts 00354 TIMSK2 = 0; 00355 // call user function 00356 (*MozziTimer2::f_)(); 00357 // in case f_ enabled interrupts 00358 cli(); 00359 // clear counter if start_ is true 00360 if (MozziTimer2::start_) 00361 { 00362 // start counter 00363 TCNT2 = 0; 00364 // clear possible pending interrupt 00365 TIFR2 |= (1 << OCF2A); 00366 } 00367 // enable timer 2 COMPA interrupt 00368 TIMSK2 |= (1 << OCIE2A); 00369 } 00370 00371 */ 00372 #elif defined (__AVR_ATmega8__) || (__AVR_ATmega128__) 00373 00374 ISR(TIMER2_COMP_vect, ISR_NOBLOCK) 00375 { 00376 // disable timer 2 interrupts 00377 TIMSK = 0; 00378 // call user function 00379 (*MozziTimer2::f_)(); 00380 // in case f_ enabled interrupts 00381 cli(); 00382 // clear counter if start_ is true 00383 if (MozziTimer2::start_) 00384 { 00385 // start counter 00386 TCNT2 = 0; 00387 // clear possible pending interrupt 00388 TIFR |= (1 << OCF2); 00389 } 00390 // enable timer 2 COMPA interrupt 00391 TIMSK |= (1 << OCIE2); 00392 } 00393 00394 00395 #elif defined (__AVR_ATmega32U4__) 00396 00397 ISR(TIMER4_COMPA_vect, ISR_NOBLOCK) // this all needs checking 00398 { 00399 // disable timer 4 interrupts 00400 TIMSK4 = 0; 00401 // call user function 00402 (*MozziTimer2::f_)(); 00403 // in case f_ enabled interrupts 00404 cli(); 00405 // clear counter if start_ is true 00406 if (MozziTimer2::start_) 00407 { 00408 // start counter 00409 TCNT4 = 0; 00410 // clear possible pending interrupt 00411 TIFR4 |= (1 << OCF4A); 00412 } 00413 // enable timer 4 COMPA interrupt 00414 TIMSK4 |= (1 << OCIE4A); 00415 } 00416 00417 #endif 00418 00419