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

Generated on Tue Sep 20 03:11:43 2005 for Procyon AVRlib by  doxygen 1.4.2