Mozzi  alpha 0.01.1f
sound synthesis library for Arduino
 All Classes Functions
FlexiTimer2.cpp
00001 /*
00002   FlexiTimer2.h - Using timer2 with a configurable resolution
00003   Wim Leers <work@wimleers.com>
00004  
00005   Based on MsTimer2
00006   Javier Valencia <javiervalencia80@gmail.com>
00007  
00008   History:
00009     16/Dec/2011 - Added Teensy/Teensy++ support (bperrybap)
00010                                    note: teensy uses timer4 instead of timer2
00011     25/April/10 - Based on MsTimer2 V0.5 (from 29/May/09)
00012  
00013   This library is free software; you can redistribute it and/or
00014   modify it under the terms of the GNU Lesser General Public
00015   License as published by the Free Software Foundation; either
00016   version 2.1 of the License, or (at your option) any later version.
00017  
00018   This library is distributed in the hope that it will be useful,
00019   but WITHOUT ANY WARRANTY; without even the implied warranty of
00020   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00021   Lesser General Public License for more details.
00022  
00023   You should have received a copy of the GNU Lesser General Public
00024   License along with this library; if not, write to the Free Software
00025   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00026 */
00027 
00028 #include <FlexiTimer2.h>
00029 
00030 unsigned long FlexiTimer2::time_units;
00031 void (*FlexiTimer2::func)();
00032 volatile unsigned long FlexiTimer2::count;
00033 volatile char FlexiTimer2::overflowing;
00034 volatile unsigned int FlexiTimer2::tcnt2;
00035 
00036 void FlexiTimer2::set(unsigned long ms, void (*f)())
00037 {
00038                 FlexiTimer2::set(ms, 0.001, f);
00039 }
00040 
00041 
00047 void FlexiTimer2::set(unsigned long units, double resolution, void (*f)())
00048 {
00049                 float prescaler = 0.0;
00050 
00051                 if (units == 0)
00052                                 time_units = 1;
00053                 else
00054                                 time_units = units;
00055 
00056                 func = f;
00057 
00058 #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__)
00059 
00060                 TIMSK2 &= ~(1<<TOIE2);
00061                 TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
00062                 TCCR2B &= ~(1<<WGM22);
00063                 ASSR &= ~(1<<AS2);
00064                 TIMSK2 &= ~(1<<OCIE2A);
00065 
00066                 if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL))
00067                 {               // prescaler set to 64
00068                                 TCCR2B |= (1<<CS22);
00069                                 TCCR2B &= ~((1<<CS21) | (1<<CS20));
00070                                 prescaler = 64.0;
00071                 }
00072                 else if (F_CPU < 1000000UL)
00073                 {               // prescaler set to 8
00074                                 TCCR2B |= (1<<CS21);
00075                                 TCCR2B &= ~((1<<CS22) | (1<<CS20));
00076                                 prescaler = 8.0;
00077                 }
00078                 else
00079                 { // F_CPU > 16Mhz, prescaler set to 128
00080                                 TCCR2B |= ((1<<CS22) | (1<<CS20));
00081                                 TCCR2B &= ~(1<<CS21);
00082                                 prescaler = 128.0;
00083                 }
00084 #elif defined (__AVR_ATmega8__)
00085                 TIMSK &= ~(1<<TOIE2);
00086                 TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
00087                 TIMSK &= ~(1<<OCIE2);
00088                 ASSR &= ~(1<<AS2);
00089 
00090                 if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL))
00091                 {               // prescaler set to 64
00092                                 TCCR2 |= (1<<CS22);
00093                                 TCCR2 &= ~((1<<CS21) | (1<<CS20));
00094                                 prescaler = 64.0;
00095                 }
00096                 else if (F_CPU < 1000000UL)
00097                 {               // prescaler set to 8
00098                                 TCCR2 |= (1<<CS21);
00099                                 TCCR2 &= ~((1<<CS22) | (1<<CS20));
00100                                 prescaler = 8.0;
00101                 }
00102                 else
00103                 { // F_CPU > 16Mhz, prescaler set to 128
00104                                 TCCR2 |= ((1<<CS22) && (1<<CS20));
00105                                 TCCR2 &= ~(1<<CS21);
00106                                 prescaler = 128.0;
00107                 }
00108 #elif defined (__AVR_ATmega128__)
00109                 TIMSK &= ~(1<<TOIE2);
00110                 TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
00111                 TIMSK &= ~(1<<OCIE2);
00112 
00113                 if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL))
00114                 {               // prescaler set to 64
00115                                 TCCR2 |= ((1<<CS21) | (1<<CS20));
00116                                 TCCR2 &= ~(1<<CS22);
00117                                 prescaler = 64.0;
00118                 }
00119                 else if (F_CPU < 1000000UL)
00120                 {               // prescaler set to 8
00121                                 TCCR2 |= (1<<CS21);
00122                                 TCCR2 &= ~((1<<CS22) | (1<<CS20));
00123                                 prescaler = 8.0;
00124                 }
00125                 else
00126                 { // F_CPU > 16Mhz, prescaler set to 256
00127                                 TCCR2 |= (1<<CS22);
00128                                 TCCR2 &= ~((1<<CS21) | (1<<CS20));
00129                                 prescaler = 256.0;
00130                 }
00131 #elif defined (__AVR_ATmega32U4__)
00132                 TCCR4B = 0;
00133                 TCCR4A = 0;
00134                 TCCR4C = 0;
00135                 TCCR4D = 0;
00136                 TCCR4E = 0;
00137                 if (F_CPU >= 16000000L)
00138                 {
00139                                 TCCR4B = (1<<CS43) | (1<<PSR4);
00140                                 prescaler = 128.0;
00141                 }
00142                 else if (F_CPU >= 8000000L)
00143                 {
00144                                 TCCR4B = (1<<CS42) | (1<<CS41) | (1<<CS40) | (1<<PSR4);
00145                                 prescaler = 64.0;
00146                 }
00147                 else if (F_CPU >= 4000000L)
00148                 {
00149                                 TCCR4B = (1<<CS42) | (1<<CS41) | (1<<PSR4);
00150                                 prescaler = 32.0;
00151                 }
00152                 else if (F_CPU >= 2000000L)
00153                 {
00154                                 TCCR4B = (1<<CS42) | (1<<CS40) | (1<<PSR4);
00155                                 prescaler = 16.0;
00156                 }
00157                 else if (F_CPU >= 1000000L)
00158                 {
00159                                 TCCR4B = (1<<CS42) | (1<<PSR4);
00160                                 prescaler = 8.0;
00161                 }
00162                 else if (F_CPU >= 500000L)
00163                 {
00164                                 TCCR4B = (1<<CS41) | (1<<CS40) | (1<<PSR4);
00165                                 prescaler = 4.0;
00166                 }
00167                 else
00168                 {
00169                                 TCCR4B = (1<<CS41) | (1<<PSR4);
00170                                 prescaler = 2.0;
00171                 }
00172                 tcnt2 = (int)((float)F_CPU * resolution / prescaler) - 1;
00173                 OCR4C = tcnt2;
00174                 return;
00175 #else
00176 #error Unsupported CPU type
00177 #endif
00178 
00179                 tcnt2 = 256 - (int)((float)F_CPU * resolution / prescaler);
00180 }
00181 
00182 void FlexiTimer2::start()
00183 {
00184                 count = 0;
00185                 overflowing = 0;
00186 #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__)
00187 
00188                 TCNT2 = tcnt2;
00189                 TIMSK2 |= (1<<TOIE2);
00190 #elif defined (__AVR_ATmega128__)
00191 
00192                 TCNT2 = tcnt2;
00193                 TIMSK |= (1<<TOIE2);
00194 #elif defined (__AVR_ATmega8__)
00195 
00196                 TCNT2 = tcnt2;
00197                 TIMSK |= (1<<TOIE2);
00198 #elif defined (__AVR_ATmega32U4__)
00199 
00200                 TIFR4 = (1<<TOV4);
00201                 TCNT4 = 0;
00202                 TIMSK4 = (1<<TOIE4);
00203 #endif
00204 }
00205 
00206 void FlexiTimer2::stop()
00207 {
00208 #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__)
00209                 TIMSK2 &= ~(1<<TOIE2);
00210 #elif defined (__AVR_ATmega128__)
00211 
00212                 TIMSK &= ~(1<<TOIE2);
00213 #elif defined (__AVR_ATmega8__)
00214 
00215                 TIMSK &= ~(1<<TOIE2);
00216 #elif defined (__AVR_ATmega32U4__)
00217 
00218                 TIMSK4 = 0;
00219 #endif
00220 }
00221 
00222 void FlexiTimer2::_overflow()
00223 {
00224                 count += 1;
00225 
00226                 if (count >= time_units && !overflowing)
00227                 {
00228                                 overflowing = 1;
00229                                 count = 0;//count - time_units; // subtract time_uints to catch missed overflows
00230                                 // set to 0 if you don't want this.
00231                                 (*func)();
00232                                 overflowing = 0;
00233                 }
00234 }
00235 #if defined (__AVR_ATmega32U4__)
00236 ISR(TIMER4_OVF_vect)
00237 {
00238 #else
00239                 ISR(TIMER2_OVF_vect)
00240                 {
00241 #endif
00242 #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__)
00243                                 TCNT2 = FlexiTimer2::tcnt2;
00244 #elif defined (__AVR_ATmega128__)
00245 
00246                                 TCNT2 = FlexiTimer2::tcnt2;
00247 #elif defined (__AVR_ATmega8__)
00248 
00249                                 TCNT2 = FlexiTimer2::tcnt2;
00250 #elif defined (__AVR_ATmega32U4__)
00251                                 // not necessary on 32u4's high speed timer4
00252 #endif
00253 
00254                                 FlexiTimer2::_overflow();
00255                 }
00256