Main Page   Compound List   File List   Compound Members   File Members  

pulse.c

Go to the documentation of this file.
00001 
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              : 2002-08-19
00009 // Version              : 1.1
00010 // Target MCU   : Atmel AVR Series
00011 // Editor Tabs  : 3
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 <io.h>
00020         #include <sig-avr.h>
00021         #include <interrupt.h>
00022         #include <progmem.h>
00023 #endif
00024 
00025 #include "global.h"
00026 #include "timer.h"
00027 #include "pulse.h"
00028 
00029 // Global variables
00030 extern short __attribute__ ((progmem)) TimerPrescaleFactor[];
00031 // pulse generation registers
00032 volatile static unsigned char  PulseT1AMode;
00033 volatile static unsigned short PulseT1ACount;
00034 volatile static unsigned short PulseT1APeriodTics;
00035 volatile static unsigned char  PulseT1BMode;
00036 volatile static unsigned short PulseT1BCount;
00037 volatile static unsigned short PulseT1BPeriodTics;
00038 
00039 // pulse mode bit definitions
00040 // PULSE_MODE_COUNTED
00041 //              if true, the requested number of pulses are output, then output is turned off
00042 //              if false, pulses are output continuously
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         // get the current prescaler setting
00099         u16 prescaleDiv = 1<<(PRG_RDB(TimerPrescaleFactor+(inp(TCCR1B) & TIMER_PRESCALE_MASK)));
00100         // calculate how many tics in period/2
00101         // this is the (timer tic rate)/(2*requested freq)
00102         PulseT1APeriodTics = ((u32)F_CPU/((u32)prescaleDiv*2*freqHz));
00103 }
00104 
00105 void pulseT1BSetFreq(u16 freqHz)
00106 {
00107         // set the frequency of the pulse output
00108         // we need to find the requested period/2 (in timer tics)
00109         // from the frequency (in hertz)
00110 
00111         // get the current prescaler setting
00112         u16 prescaleDiv = 1<<(PRG_RDB(TimerPrescaleFactor+(inp(TCCR1B) & TIMER_PRESCALE_MASK)));
00113         // calculate how many tics in period/2
00114         // this is the (timer tic rate)/(2*requested freq)
00115         PulseT1BPeriodTics = ((u32)F_CPU/((u32)prescaleDiv*2*freqHz));
00116 }
00117 
00118 void pulseT1ARun(u16 nPulses)
00119 {
00120         // set the output compare one cycle ahead to make sure we
00121         // don't have to wait until the timer overflows and comes
00122         // back to the current value
00123         u16 OCValue;
00124         // read in current value of output compare register OCR1A
00125         OCValue =  inp(OCR1AL);         // read low byte of OCR1A
00126         OCValue += inp(OCR1AH)<<8;      // read high byte of OCR1A
00127         // increment OCR1A value by PulseT1APeriodTics
00128         OCValue += PulseT1APeriodTics; 
00129         // set future output compare time to this new value
00130         outp((OCValue>>8),              OCR1AH);        // write high byte
00131         outp((OCValue & 0x00FF),OCR1AL);        // write low byte
00132 
00133         // now the "enabling" stuff
00134         // set the number of pulses we want
00135         if(nPulses)
00136         {
00137                 // if the nPulses is non-zero, use "counted" mode
00138                 PulseT1AMode |= PULSE_MODE_COUNTED;
00139                 PulseT1ACount = nPulses<<1;
00140         }
00141         else
00142         {
00143                 // if nPulses is zero, run forever
00144                 PulseT1AMode &= ~PULSE_MODE_COUNTED;
00145                 PulseT1ACount = 1<<1;
00146         }
00147         // set OutputCompare action to toggle OC1A pin
00148         cbi(TCCR1A,COM1A1);
00149         sbi(TCCR1A,COM1A0);
00150         // enable OutputCompare interrupt
00151         sbi(TIMSK, OCIE1A);
00152 }
00153 
00154 void pulseT1BRun(u16 nPulses)
00155 {
00156         // set the output compare one cycle ahead to make sure we
00157         // don't have to wait until the timer overflows and comes
00158         // back to the current value
00159         u16 OCValue;
00160         // read in current value of output compare register OCR1B
00161         OCValue =  inp(OCR1BL);         // read low byte of OCR1B
00162         OCValue += inp(OCR1BH)<<8;      // read high byte of OCR1B
00163         // increment OCR1B value by PulseT1BPeriodTics
00164         OCValue += PulseT1BPeriodTics; 
00165         // set future output compare time to this new value
00166         outp((OCValue>>8),              OCR1BH);        // write high byte
00167         outp((OCValue & 0x00FF),OCR1BL);        // write low byte
00168 
00169         // now the "enabling" stuff
00170         // set the number of pulses we want
00171         if(nPulses)
00172         {
00173                 // if the nPulses is non-zero, use "counted" mode
00174                 PulseT1BMode |= PULSE_MODE_COUNTED;
00175                 PulseT1BCount = nPulses<<1;
00176         }
00177         else
00178         {
00179                 // if nPulses is zero, run forever
00180                 PulseT1BMode &= ~PULSE_MODE_COUNTED;
00181                 PulseT1BCount = 1<<1;
00182         }
00183         // set OutputCompare action to toggle OC1B pin
00184         // (note: with all the A's and B's flying around, TCCR1A is not a bug)
00185         cbi(TCCR1A,COM1B1);
00186         sbi(TCCR1A,COM1B0);
00187 
00188         // enable OutputCompare interrupt
00189         sbi(TIMSK, OCIE1B);
00190 }
00191 
00192 u16 pulseT1ARemaining(void)
00193 {
00194         // return the number of pulses remaining for channel A
00195         // add 1 to make sure we round up, >>1 equivalent to /2
00196         return (PulseT1ACount+1)>>1;
00197 }
00198 
00199 u16 pulseT1BRemaining(void)
00200 {
00201         // return the number of pulses remaining for channel A
00202         // add 1 to make sure we round up, >>1 equivalent to /2
00203         return (PulseT1BCount+1)>>1;
00204 }
00205 
00206 void pulseT1AService(void)
00207 {
00208         u16 OCValue;
00209         
00210         // check if TimerPulseACount is non-zero
00211         //              (i.e. pulses are still requested)
00212         if(PulseT1ACount)
00213         {
00214                 // read in current value of output compare register OCR1A
00215                 OCValue =  inp(OCR1AL);         // read low byte of OCR1A
00216                 OCValue += inp(OCR1AH)<<8;      // read high byte of OCR1A
00217                 // increment OCR1A value by PulseT1APeriodTics
00218                 OCValue += PulseT1APeriodTics; 
00219                 // set future output compare time to this new value
00220                 outp((OCValue>>8),              OCR1AH);        // write high byte
00221                 outp((OCValue & 0x00FF),OCR1AL);        // write low byte
00222                 // decrement the number of pulses executed
00223                 if(PulseT1AMode & PULSE_MODE_COUNTED)
00224                         PulseT1ACount--;
00225         }
00226         else
00227         {
00228                 // pulse count has reached zero
00229                 // disable the output compare's action on OC1A pin
00230                 cbi(TCCR1A,COM1A1);
00231                 cbi(TCCR1A,COM1A0);
00232                 // and disable the output compare's interrupt to stop pulsing
00233                 cbi(TIMSK, OCIE1A);
00234         }
00235 }
00236 
00237 void pulseT1BService(void)
00238 {
00239         u16 OCValue;
00240         
00241         // check if TimerPulseACount is non-zero
00242         //              (i.e. pulses are still requested)
00243         if(PulseT1BCount)
00244         {
00245                 // read in current value of output compare register OCR1B
00246                 OCValue =  inp(OCR1BL);         // read low byte of OCR1B
00247                 OCValue += inp(OCR1BH)<<8;      // read high byte of OCR1B
00248                 // increment OCR1B value by PulseT1BPeriodTics
00249                 OCValue += PulseT1BPeriodTics; 
00250                 // set future output compare time to this new value
00251                 outp((OCValue>>8),              OCR1BH);        // write high byte
00252                 outp((OCValue & 0x00FF),OCR1BL);        // write low byte
00253                 // decrement the number of pulses executed
00254                 if(PulseT1BMode & PULSE_MODE_COUNTED)
00255                         PulseT1BCount--;
00256         }
00257         else
00258         {
00259                 // pulse count has reached zero
00260                 // disable the output compare's action on OC1B pin
00261                 cbi(TCCR1A,COM1B1);
00262                 cbi(TCCR1A,COM1B0);
00263                 // and disable the output compare's interrupt to stop pulsing
00264                 cbi(TIMSK, OCIE1B);
00265         }
00266 }

Generated at Fri Oct 25 15:36:38 2002 for avrlib by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001