Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

pulse.c

Go to the documentation of this file.
00001 /*! \file pulse.c \brief Pulse/frequency generation function library. */
00002 //*****************************************************************************
00003 //
00004 // File Name    : 'pulse.c'
00005 // Title        : Pulse/frequency generation function library
00006 // Author       : Pascal Stang - Copyright (C) 2000-2002
00007 // Created      : 2002-08-19
00008 // Revised      : 2003-05-29
00009 // Version      : 0.7
00010 // Target MCU   : Atmel AVR Series
00011 // Editor Tabs  : 4
00012 //
00013 // This code is distributed under the GNU Public License
00014 //      which can be found at http://www.gnu.org/licenses/gpl.txt
00015 //
00016 //*****************************************************************************
00017 
00018 #include <avr/io.h>
00019 #include <avr/interrupt.h>
00020 #include <avr/pgmspace.h>
00021 
00022 #include "global.h"
00023 #include "timer.h"
00024 #include "pulse.h"
00025 
00026 // Global variables
00027 // pulse generation registers
00028 volatile static unsigned char  PulseT1AMode;
00029 volatile static unsigned short PulseT1ACount;
00030 volatile static unsigned short PulseT1APeriodTics;
00031 volatile static unsigned char  PulseT1BMode;
00032 volatile static unsigned short PulseT1BCount;
00033 volatile static unsigned short PulseT1BPeriodTics;
00034 
00035 // pulse mode bit definitions
00036 // PULSE_MODE_COUNTED
00037 //      if true, the requested number of pulses are output, then output is turned off
00038 //      if false, pulses are output continuously
00039 #define PULSE_MODE_CONTINUOUS   0x00
00040 #define PULSE_MODE_COUNTED      0x01
00041 
00042 // functions
00043 
00044 void pulseInit(void)
00045 {
00046     // initialize timer1 for pulse operation
00047     pulseT1Init();
00048 }
00049 
00050 void pulseT1Init(void)
00051 {
00052     // try to make sure that timer1 is in "normal" mode
00053     // most importantly, turn off PWM mode
00054     timer1PWMOff();
00055 
00056     // set some reasonable initial values
00057     // in case the user forgets to
00058     PulseT1AMode = 0;
00059     PulseT1BMode = 0;
00060     PulseT1ACount = 0;
00061     PulseT1BCount = 0;
00062     PulseT1APeriodTics = 0x8000;
00063     PulseT1BPeriodTics = 0x8000;
00064 
00065     // attach the pulse service routines to
00066     // the timer 1 output compare A and B interrupts
00067     timerAttach(TIMER1OUTCOMPAREA_INT,pulseT1AService);
00068     timerAttach(TIMER1OUTCOMPAREB_INT,pulseT1BService);
00069 }
00070 
00071 void pulseT1Off(void)
00072 {
00073     // turns pulse outputs off immediately
00074     
00075     // set pulse counters to zero (finished)
00076     PulseT1ACount = 0;
00077     PulseT1BCount = 0;
00078     // disconnect OutputCompare action from OC1A pin
00079     cbi(TCCR1A,COM1A1);
00080     cbi(TCCR1A,COM1A0);
00081     // disconnect OutputCompare action from OC1B pin
00082     cbi(TCCR1A,COM1B1);
00083     cbi(TCCR1A,COM1B0);
00084     // detach the pulse service routines
00085     timerDetach(TIMER1OUTCOMPAREA_INT);
00086     timerDetach(TIMER1OUTCOMPAREB_INT);
00087 }
00088 
00089 void pulseT1ASetFreq(u16 freqHz)
00090 {
00091     // set the frequency of the pulse output
00092     // we need to find the requested period/2 (in timer tics)
00093     // from the frequency (in hertz)
00094 
00095     // calculate how many tics in period/2
00096     // this is the (timer tic rate)/(2*requested freq)
00097     PulseT1APeriodTics = ((u32)F_CPU/((u32)timer1GetPrescaler()*2*freqHz));
00098 }
00099 
00100 void pulseT1BSetFreq(u16 freqHz)
00101 {
00102     // set the frequency of the pulse output
00103     // we need to find the requested period/2 (in timer tics)
00104     // from the frequency (in hertz)
00105 
00106     // calculate how many tics in period/2
00107     // this is the (timer tic rate)/(2*requested freq)
00108     PulseT1BPeriodTics = ((u32)F_CPU/((u32)timer1GetPrescaler()*2*freqHz));
00109 }
00110 
00111 void pulseT1ARun(u16 nPulses)
00112 {
00113     // set the number of pulses we want and the mode
00114     if(nPulses)
00115     {
00116         // if the nPulses is non-zero, use "counted" mode
00117         PulseT1AMode |= PULSE_MODE_COUNTED;
00118         PulseT1ACount = nPulses<<1;
00119     }
00120     else
00121     {
00122         // if nPulses is zero, run forever
00123         PulseT1AMode &= ~PULSE_MODE_COUNTED;
00124         PulseT1ACount = 1<<1;
00125     }
00126     // set OutputCompare action to toggle OC1A pin
00127     cbi(TCCR1A,COM1A1);
00128     sbi(TCCR1A,COM1A0);
00129 
00130     // now the "enabling" stuff
00131 
00132     // set the output compare one pulse cycle ahead of current timer position 
00133     // to make sure we don't have to wait until the timer overflows and comes
00134     // back to the current value
00135     // set future output compare time to TCNT1 + PulseT1APeriodTics
00136     //outw(OCR1A, inw(TCNT1) + PulseT1APeriodTics);
00137     OCR1A += PulseT1APeriodTics;
00138 
00139     // enable OutputCompare interrupt
00140     sbi(TIMSK, OCIE1A);
00141 }
00142 
00143 void pulseT1BRun(u16 nPulses)
00144 {
00145     // set the number of pulses we want and the mode
00146     if(nPulses)
00147     {
00148         // if the nPulses is non-zero, use "counted" mode
00149         PulseT1BMode |= PULSE_MODE_COUNTED;
00150         PulseT1BCount = nPulses<<1;
00151     }
00152     else
00153     {
00154         // if nPulses is zero, run forever
00155         PulseT1BMode &= ~PULSE_MODE_COUNTED;
00156         PulseT1BCount = 1<<1;
00157     }
00158     // set OutputCompare action to toggle OC1B pin
00159     // (note: with all the A's and B's flying around, TCCR1A is not a bug)
00160     cbi(TCCR1A,COM1B1);
00161     sbi(TCCR1A,COM1B0);
00162 
00163     // now the "enabling" stuff
00164 
00165     // set the output compare one pulse cycle ahead of current timer position 
00166     // to make sure we don't have to wait until the timer overflows and comes
00167     // back to the current value
00168     // set future output compare time to TCNT1 + PulseT1APeriodTics
00169     //outw(OCR1B, inw(TCNT1) + PulseT1BPeriodTics);
00170     OCR1B += PulseT1BPeriodTics;
00171 
00172     // enable OutputCompare interrupt
00173     sbi(TIMSK, OCIE1B);
00174 }
00175 
00176 void pulseT1AStop(void)
00177 {
00178     // stop output regardless of remaining pulses or mode
00179     // go to "counted" mode
00180     PulseT1AMode |= PULSE_MODE_COUNTED;
00181     // set pulses to zero
00182     PulseT1ACount = 0;
00183 }
00184 
00185 void pulseT1BStop(void)
00186 {
00187     // stop output regardless of remaining pulses or mode
00188     // go to "counted" mode
00189     PulseT1BMode |= PULSE_MODE_COUNTED;
00190     // set pulses to zero
00191     PulseT1BCount = 0;
00192 }
00193 
00194 u16 pulseT1ARemaining(void)
00195 {
00196     // return the number of pulses remaining for channel A
00197     // add 1 to make sure we round up, >>1 equivalent to /2
00198     return (PulseT1ACount+1)>>1;
00199 }
00200 
00201 u16 pulseT1BRemaining(void)
00202 {
00203     // return the number of pulses remaining for channel A
00204     // add 1 to make sure we round up, >>1 equivalent to /2
00205     return (PulseT1BCount+1)>>1;
00206 }
00207 
00208 void pulseT1AService(void)
00209 {
00210     // check if TimerPulseACount is non-zero
00211     //      (i.e. pulses are still requested)
00212     if(PulseT1ACount)
00213     {
00214         //u16 OCValue;
00215         // read in current value of output compare register OCR1A
00216         //OCValue =  inp(OCR1AL);       // read low byte of OCR1A
00217         //OCValue += inp(OCR1AH)<<8;    // read high byte of OCR1A
00218         // increment OCR1A value by PulseT1APeriodTics
00219         //OCValue += PulseT1APeriodTics;
00220         // set future output compare time to this new value
00221         //outp((OCValue>>8),        OCR1AH);    // write high byte
00222         //outp((OCValue & 0x00FF),OCR1AL);  // write low byte
00223 
00224         // the following line should be identical in operation
00225         // to the lines above, but for the moment, I'm not convinced
00226         // this method is bug-free.  At least it's simpler!
00227         //outw(OCR1A, inw(OCR1A) + PulseT1APeriodTics);
00228         // change again
00229         OCR1A += PulseT1APeriodTics;
00230                         
00231         // decrement the number of pulses executed
00232         if(PulseT1AMode & PULSE_MODE_COUNTED)
00233             PulseT1ACount--;
00234     }
00235     else
00236     {
00237         // pulse count has reached zero
00238         // disable the output compare's action on OC1A pin
00239         cbi(TCCR1A,COM1A1);
00240         cbi(TCCR1A,COM1A0);
00241         // and disable the output compare's interrupt to stop pulsing
00242         cbi(TIMSK, OCIE1A);
00243     }
00244 }
00245 
00246 void pulseT1BService(void)
00247 {
00248     // check if TimerPulseACount is non-zero
00249     //      (i.e. pulses are still requested)
00250     if(PulseT1BCount)
00251     {
00252         //u16 OCValue;
00253         // read in current value of output compare register OCR1B
00254         //OCValue =  inp(OCR1BL);       // read low byte of OCR1B
00255         //OCValue += inp(OCR1BH)<<8;    // read high byte of OCR1B
00256         // increment OCR1B value by PulseT1BPeriodTics
00257         //OCValue += PulseT1BPeriodTics; 
00258         // set future output compare time to this new value
00259         //outp((OCValue>>8),        OCR1BH);    // write high byte
00260         //outp((OCValue & 0x00FF),OCR1BL);  // write low byte
00261 
00262         // the following line should be identical in operation
00263         // to the lines above, but for the moment, I'm not convinced
00264         // this method is bug-free.  At least it's simpler!
00265         //outw(OCR1B, inw(OCR1B) + PulseT1BPeriodTics);
00266         // change again
00267         OCR1B += PulseT1BPeriodTics;
00268 
00269         
00270         // decrement the number of pulses executed
00271         if(PulseT1BMode & PULSE_MODE_COUNTED)
00272             PulseT1BCount--;
00273     }
00274     else
00275     {
00276         // pulse count has reached zero
00277         // disable the output compare's action on OC1B pin
00278         cbi(TCCR1A,COM1B1);
00279         cbi(TCCR1A,COM1B0);
00280         // and disable the output compare's interrupt to stop pulsing
00281         cbi(TIMSK, OCIE1B);
00282     }
00283 }

Generated on Sun Oct 29 03:41:07 2006 for Procyon AVRlib by  doxygen 1.4.2