MHVLib
20111011
An efficiency oriented runtime library for AVR microcontrollers
|
00001 /* 00002 * Copyright (c) 2011, Make, Hack, Void Inc 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * * Redistributions of source code must retain the above copyright 00008 * notice, this list of conditions and the following disclaimer. 00009 * * Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * * Neither the name of the Make, Hack, Void nor the 00013 * names of its contributors may be used to endorse or promote products 00014 * derived from this software without specific prior written permission. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00017 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00018 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 * DISCLAIMED. IN NO EVENT SHALL MAKE, HACK, VOID BE LIABLE FOR ANY 00020 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00021 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00022 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00023 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00025 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 00029 #include <MHV_Timer16.h> 00030 #include <avr/interrupt.h> 00031 #include <util/atomic.h> 00032 00033 #ifdef MHV_TIMER16_1 00034 00035 /* Create a new timer 00036 * param: time the time in microseconds 00037 */ 00038 MHV_Timer16::MHV_Timer16(volatile uint8_t *controlRegA, volatile uint8_t *controlRegB, volatile uint8_t *controlRegC, 00039 volatile uint16_t *outputCompare1, volatile uint16_t *outputCompare2, volatile uint16_t *outputCompare3, 00040 volatile uint16_t *counter, volatile uint8_t *interrupt, volatile uint16_t *inputCapture1) { 00041 _controlRegA = controlRegA; 00042 _controlRegB = controlRegB; 00043 _controlRegC = controlRegC; 00044 _outputCompare1 = outputCompare1; 00045 _outputCompare2 = outputCompare2; 00046 _outputCompare3 = outputCompare3; 00047 _counter = counter; 00048 _interrupt = interrupt; 00049 _inputCapture1 = inputCapture1; 00050 _counterSize = 16; 00051 _mode = MHV_TIMER_REPETITIVE; 00052 _type = MHV_TIMER_TYPE_5_PRESCALERS; 00053 00054 _haveTime3 = false; 00055 _triggerData3 = NULL; 00056 _triggerFunction3 = NULL; 00057 00058 } 00059 00060 uint16_t MHV_Timer16::current(void) { 00061 uint16_t ret; 00062 00063 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00064 ret = *_counter; 00065 } 00066 return ret; 00067 } 00068 00069 /* Set the generation mode 00070 * param mode the mode to run the timer in 00071 */ 00072 void MHV_Timer16::setGenerationMode(void) { 00073 switch (_mode) { 00074 case MHV_TIMER_ONE_SHOT: 00075 case MHV_TIMER_REPETITIVE: 00076 *_controlRegA = (*_controlRegA & 0xfc); 00077 *_controlRegB = (*_controlRegB & 0xe7) | _BV(WGM12); 00078 break; 00079 case MHV_TIMER_16_PWM_PHASE_CORRECT: 00080 *_controlRegA = (*_controlRegA & 0xfc); 00081 *_controlRegB = (*_controlRegB & 0xe7) | _BV(WGM13); 00082 break; 00083 case MHV_TIMER_16_PWM_FAST: 00084 *_controlRegA = (*_controlRegA & 0xfc) | _BV(WGM11); 00085 *_controlRegB = (*_controlRegB & 0xe7) | _BV(WGM13) | _BV(WGM12); 00086 break; 00087 case MHV_TIMER_16_PWM_PHASE_FREQ_CORRECT: // Always use ICR for top 00088 *_controlRegA = (*_controlRegA & 0xfc); 00089 *_controlRegB = (*_controlRegB & 0xe7) | _BV(WGM13); 00090 break; 00091 default: 00092 break; 00093 } 00094 } 00095 00096 /* Get the number of timer cycles available 00097 */ 00098 uint16_t MHV_Timer16::getTop(void) { 00099 switch (_mode) { 00100 case MHV_TIMER_ONE_SHOT: 00101 case MHV_TIMER_REPETITIVE: 00102 return *_outputCompare1; 00103 case MHV_TIMER_16_PWM_PHASE_CORRECT: 00104 case MHV_TIMER_16_PWM_FAST: 00105 case MHV_TIMER_16_PWM_PHASE_FREQ_CORRECT: 00106 return *_inputCapture1; 00107 default: 00108 return 0; 00109 } 00110 } 00111 00112 /* Set the number of timer cycles available 00113 */ 00114 void MHV_Timer16::setTop(uint16_t value) { 00115 switch (_mode) { 00116 case MHV_TIMER_ONE_SHOT: 00117 case MHV_TIMER_REPETITIVE: 00118 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00119 *_outputCompare1 = value; 00120 } 00121 break; 00122 case MHV_TIMER_16_PWM_PHASE_CORRECT: 00123 case MHV_TIMER_16_PWM_FAST: 00124 case MHV_TIMER_16_PWM_PHASE_FREQ_CORRECT: 00125 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00126 *_inputCapture1 = value; 00127 } 00128 default: 00129 break; 00130 } 00131 } 00132 00133 void MHV_Timer16::setOutput(uint8_t channel, uint16_t value) { 00134 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00135 switch (channel) { 00136 case 1: 00137 *_outputCompare1 = value; 00138 break; 00139 case 2: 00140 *_outputCompare2 = value; 00141 break; 00142 case 3: 00143 *_outputCompare3 = value; 00144 break; 00145 } 00146 } 00147 } 00148 00149 00150 void MHV_Timer16::setOutput1(uint16_t value) { 00151 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00152 *_outputCompare1 = value; 00153 } 00154 } 00155 00156 void MHV_Timer16::setOutput2(uint16_t value) { 00157 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00158 *_outputCompare2 = value; 00159 } 00160 } 00161 00162 void MHV_Timer16::setOutput3(uint16_t value) { 00163 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00164 *_outputCompare3 = value; 00165 } 00166 } 00167 00168 uint16_t MHV_Timer16::getOutput(uint8_t channel) { 00169 uint16_t ret = 0; 00170 00171 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00172 switch (channel) { 00173 case 1: 00174 ret = *_outputCompare1; 00175 break; 00176 case 2: 00177 ret = *_outputCompare2; 00178 break; 00179 case 3: 00180 ret = *_outputCompare3; 00181 break; 00182 } 00183 } 00184 00185 return ret; 00186 } 00187 00188 uint16_t MHV_Timer16::getOutput1(void) { 00189 uint16_t ret; 00190 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00191 ret = *_outputCompare1; 00192 } 00193 return ret; 00194 } 00195 00196 uint16_t MHV_Timer16::getOutput2(void) { 00197 uint16_t ret; 00198 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00199 ret = *_outputCompare2; 00200 } 00201 return ret; 00202 } 00203 00204 uint16_t MHV_Timer16::getOutput3(void) { 00205 uint16_t ret; 00206 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00207 ret = *_outputCompare3; 00208 } 00209 return ret; 00210 } 00211 00212 void MHV_Timer16::connectOutput(uint8_t channel, MHV_TIMER_CONNECT_TYPE type) { 00213 switch (channel) { 00214 case 1: 00215 *_controlRegA = (*_controlRegA & 0x3F) | (type << 6); 00216 break; 00217 case 2: 00218 *_controlRegA = (*_controlRegA & 0xCF) | (type << 4); 00219 break; 00220 case 3: 00221 *_controlRegA = (*_controlRegA & 0xF3) | (type << 2); 00222 break; 00223 } 00224 } 00225 00226 void MHV_Timer16::connectOutput1(MHV_TIMER_CONNECT_TYPE type) { 00227 *_controlRegA = (*_controlRegA & 0x3F) | (type << 6); 00228 } 00229 00230 void MHV_Timer16::connectOutput2(MHV_TIMER_CONNECT_TYPE type) { 00231 *_controlRegA = (*_controlRegA & 0xCF) | (type << 4); 00232 } 00233 00234 void MHV_Timer16::connectOutput3(MHV_TIMER_CONNECT_TYPE type) { 00235 *_controlRegA = (*_controlRegA & 0xF3) | (type << 2); 00236 } 00237 00238 void MHV_Timer16::disable(void) { 00239 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00240 _setPrescaler(MHV_TIMER_PRESCALER_DISABLED); 00241 *_interrupt &= ~_BV(OCIE1A); 00242 00243 if (_haveTime2) { 00244 *_interrupt &= ~_BV(OCIE1B); 00245 } 00246 00247 #ifdef OCIE1C 00248 if (_haveTime3) { 00249 *_interrupt &= ~_BV(OCIE1C); 00250 } 00251 #endif 00252 } 00253 } 00254 00255 void MHV_Timer16::enable(void) { 00256 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00257 *_counter = 0; 00258 _setPrescaler(_prescaler); 00259 setGenerationMode(); 00260 if (_triggerFunction1) { 00261 *_interrupt |= _BV(OCIE1A); 00262 } 00263 if (*_outputCompare2 && _triggerFunction2) { 00264 *_interrupt |= _BV(OCIE1B); 00265 _haveTime2 = true; 00266 } else { 00267 _haveTime2 = false; 00268 } 00269 00270 #ifdef OCIE1C 00271 if (*_outputCompare3 && _triggerFunction3) { 00272 *_interrupt |= _BV(OCIE1C); 00273 _haveTime3 = true; 00274 } else { 00275 _haveTime3 = false; 00276 } 00277 #endif 00278 } 00279 } 00280 00281 void MHV_Timer16::setPeriods(MHV_TIMER_PRESCALER prescaler, uint16_t time1, uint16_t time2, uint16_t time3) { 00282 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00283 _prescaler = prescaler; 00284 _setPrescaler(prescaler); 00285 00286 *_counter = 0; 00287 *_outputCompare1 = time1; 00288 *_outputCompare2 = time2; 00289 *_outputCompare3 = time3; 00290 } 00291 } 00292 00293 /* Times are in microseconds 00294 */ 00295 void MHV_Timer16::setPeriods(uint32_t usec1, uint32_t usec2, uint32_t usec3) { 00296 MHV_TIMER_PRESCALER prescaler; 00297 uint16_t factor = 0; 00298 uint32_t maxTime; 00299 00300 usec1 *= F_CPU / (1000000 * 2); // time is now in clocks 00301 usec2 *= F_CPU / (1000000 * 2); // time is now in clocks 00302 usec3 *= F_CPU / (1000000 * 2); // time is now in clocks 00303 00304 if (usec1 > usec2) { 00305 maxTime = usec1; 00306 } else { 00307 maxTime = usec2; 00308 } 00309 if (usec3 > maxTime) { 00310 maxTime = usec3; 00311 } 00312 00313 calculatePrescaler(maxTime, &prescaler, &factor); 00314 if (usec1) { 00315 calculateTop(&usec1, factor); 00316 } 00317 if (usec2) { 00318 calculateTop(&usec2, factor); 00319 } 00320 if (usec3) { 00321 calculateTop(&usec3, factor); 00322 } 00323 setPeriods(prescaler, usec1, usec2, usec3); 00324 } 00325 00326 void MHV_Timer16::setTriggers(void (*triggerFunction1)(void *triggerData), void *triggerData1, 00327 void (*triggerFunction2)(void *triggerData), void *triggerData2, 00328 void (*triggerFunction3)(void *triggerData), void *triggerData3) { 00329 _triggerFunction1 = triggerFunction1; 00330 _triggerData1 = triggerData1; 00331 _triggerFunction2 = triggerFunction2; 00332 _triggerData2 = triggerData2; 00333 _triggerFunction3 = triggerFunction3; 00334 _triggerData3 = triggerData3; 00335 } 00336 00337 00338 void MHV_Timer16::trigger3() { 00339 if (_triggerFunction3) { 00340 _triggerFunction3(_triggerData3); 00341 } 00342 } 00343 00344 #endif // MHV_TIMER16_1