?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{FILE START}

library

?curdirlinks? - Rev 6

?prevdifflink? - Blame - ?getfile?

/*! \file pulse.c \brief Pulse/frequency generation function library. */
//*****************************************************************************
//
// File Name    : 'pulse.c'
// Title                : Pulse/frequency generation function library
// Author               : Pascal Stang - Copyright (C) 2000-2002
// Created              : 2002-08-19
// Revised              : 2003-05-29
// Version              : 0.7
// Target MCU   : Atmel AVR Series
// Editor Tabs  : 4
//
// This code is distributed under the GNU Public License
//              which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#include "global.h"
#include "timer.h"
#include "pulse.h"

// Global variables
// pulse generation registers
volatile static unsigned char  PulseT1AMode;
volatile static unsigned short PulseT1ACount;
volatile static unsigned short PulseT1APeriodTics;
volatile static unsigned char  PulseT1BMode;
volatile static unsigned short PulseT1BCount;
volatile static unsigned short PulseT1BPeriodTics;

// pulse mode bit definitions
// PULSE_MODE_COUNTED
//              if true, the requested number of pulses are output, then output is turned off
//              if false, pulses are output continuously
#define PULSE_MODE_CONTINUOUS   0x00
#define PULSE_MODE_COUNTED              0x01

// functions

void pulseInit(void)
{
        // initialize timer1 for pulse operation
        pulseT1Init();
}

void pulseT1Init(void)
{
        // try to make sure that timer1 is in "normal" mode
        // most importantly, turn off PWM mode
        timer1PWMOff();

        // set some reasonable initial values
        // in case the user forgets to
        PulseT1AMode = 0;
        PulseT1BMode = 0;
        PulseT1ACount = 0;
        PulseT1BCount = 0;
        PulseT1APeriodTics = 0x8000;
        PulseT1BPeriodTics = 0x8000;

        // attach the pulse service routines to
        // the timer 1 output compare A and B interrupts
        timerAttach(TIMER1OUTCOMPAREA_INT,pulseT1AService);
        timerAttach(TIMER1OUTCOMPAREB_INT,pulseT1BService);
}

void pulseT1Off(void)
{
        // turns pulse outputs off immediately
        
        // set pulse counters to zero (finished)
        PulseT1ACount = 0;
        PulseT1BCount = 0;
        // disconnect OutputCompare action from OC1A pin
        cbi(TCCR1A,COM1A1);
        cbi(TCCR1A,COM1A0);
        // disconnect OutputCompare action from OC1B pin
        cbi(TCCR1A,COM1B1);
        cbi(TCCR1A,COM1B0);
        // detach the pulse service routines
        timerDetach(TIMER1OUTCOMPAREA_INT);
        timerDetach(TIMER1OUTCOMPAREB_INT);
}

void pulseT1ASetFreq(u16 freqHz)
{
        // set the frequency of the pulse output
        // we need to find the requested period/2 (in timer tics)
        // from the frequency (in hertz)

        // calculate how many tics in period/2
        // this is the (timer tic rate)/(2*requested freq)
        PulseT1APeriodTics = ((u32)F_CPU/((u32)timer1GetPrescaler()*2*freqHz));
}

void pulseT1BSetFreq(u16 freqHz)
{
        // set the frequency of the pulse output
        // we need to find the requested period/2 (in timer tics)
        // from the frequency (in hertz)

        // calculate how many tics in period/2
        // this is the (timer tic rate)/(2*requested freq)
        PulseT1BPeriodTics = ((u32)F_CPU/((u32)timer1GetPrescaler()*2*freqHz));
}

void pulseT1ARun(u16 nPulses)
{
        // set the number of pulses we want and the mode
        if(nPulses)
        {
                // if the nPulses is non-zero, use "counted" mode
                PulseT1AMode |= PULSE_MODE_COUNTED;
                PulseT1ACount = nPulses<<1;
        }
        else
        {
                // if nPulses is zero, run forever
                PulseT1AMode &= ~PULSE_MODE_COUNTED;
                PulseT1ACount = 1<<1;
        }
        // set OutputCompare action to toggle OC1A pin
        cbi(TCCR1A,COM1A1);
        sbi(TCCR1A,COM1A0);

        // now the "enabling" stuff

        // set the output compare one pulse cycle ahead of current timer position 
        // to make sure we don't have to wait until the timer overflows and comes
        // back to the current value
        // set future output compare time to TCNT1 + PulseT1APeriodTics
        //outw(OCR1A, inw(TCNT1) + PulseT1APeriodTics);
        OCR1A += PulseT1APeriodTics;

        // enable OutputCompare interrupt
        sbi(TIMSK, OCIE1A);
}

void pulseT1BRun(u16 nPulses)
{
        // set the number of pulses we want and the mode
        if(nPulses)
        {
                // if the nPulses is non-zero, use "counted" mode
                PulseT1BMode |= PULSE_MODE_COUNTED;
                PulseT1BCount = nPulses<<1;
        }
        else
        {
                // if nPulses is zero, run forever
                PulseT1BMode &= ~PULSE_MODE_COUNTED;
                PulseT1BCount = 1<<1;
        }
        // set OutputCompare action to toggle OC1B pin
        // (note: with all the A's and B's flying around, TCCR1A is not a bug)
        cbi(TCCR1A,COM1B1);
        sbi(TCCR1A,COM1B0);

        // now the "enabling" stuff

        // set the output compare one pulse cycle ahead of current timer position 
        // to make sure we don't have to wait until the timer overflows and comes
        // back to the current value
        // set future output compare time to TCNT1 + PulseT1APeriodTics
        //outw(OCR1B, inw(TCNT1) + PulseT1BPeriodTics);
        OCR1B += PulseT1BPeriodTics;

        // enable OutputCompare interrupt
        sbi(TIMSK, OCIE1B);
}

void pulseT1AStop(void)
{
        // stop output regardless of remaining pulses or mode
        // go to "counted" mode
        PulseT1AMode |= PULSE_MODE_COUNTED;
        // set pulses to zero
        PulseT1ACount = 0;
}

void pulseT1BStop(void)
{
        // stop output regardless of remaining pulses or mode
        // go to "counted" mode
        PulseT1BMode |= PULSE_MODE_COUNTED;
        // set pulses to zero
        PulseT1BCount = 0;
}

u16 pulseT1ARemaining(void)
{
        // return the number of pulses remaining for channel A
        // add 1 to make sure we round up, >>1 equivalent to /2
        return (PulseT1ACount+1)>>1;
}

u16 pulseT1BRemaining(void)
{
        // return the number of pulses remaining for channel A
        // add 1 to make sure we round up, >>1 equivalent to /2
        return (PulseT1BCount+1)>>1;
}

void pulseT1AService(void)
{
        // check if TimerPulseACount is non-zero
        //              (i.e. pulses are still requested)
        if(PulseT1ACount)
        {
                //u16 OCValue;
                // read in current value of output compare register OCR1A
                //OCValue =  inp(OCR1AL);               // read low byte of OCR1A
                //OCValue += inp(OCR1AH)<<8;    // read high byte of OCR1A
                // increment OCR1A value by PulseT1APeriodTics
                //OCValue += PulseT1APeriodTics;
                // set future output compare time to this new value
                //outp((OCValue>>8),            OCR1AH);        // write high byte
                //outp((OCValue & 0x00FF),OCR1AL);      // write low byte

                // the following line should be identical in operation
                // to the lines above, but for the moment, I'm not convinced
                // this method is bug-free.  At least it's simpler!
                //outw(OCR1A, inw(OCR1A) + PulseT1APeriodTics);
                // change again
                OCR1A += PulseT1APeriodTics;
                                                
                // decrement the number of pulses executed
                if(PulseT1AMode & PULSE_MODE_COUNTED)
                        PulseT1ACount--;
        }
        else
        {
                // pulse count has reached zero
                // disable the output compare's action on OC1A pin
                cbi(TCCR1A,COM1A1);
                cbi(TCCR1A,COM1A0);
                // and disable the output compare's interrupt to stop pulsing
                cbi(TIMSK, OCIE1A);
        }
}

void pulseT1BService(void)
{
        // check if TimerPulseACount is non-zero
        //              (i.e. pulses are still requested)
        if(PulseT1BCount)
        {
                //u16 OCValue;
                // read in current value of output compare register OCR1B
                //OCValue =  inp(OCR1BL);               // read low byte of OCR1B
                //OCValue += inp(OCR1BH)<<8;    // read high byte of OCR1B
                // increment OCR1B value by PulseT1BPeriodTics
                //OCValue += PulseT1BPeriodTics; 
                // set future output compare time to this new value
                //outp((OCValue>>8),            OCR1BH);        // write high byte
                //outp((OCValue & 0x00FF),OCR1BL);      // write low byte

                // the following line should be identical in operation
                // to the lines above, but for the moment, I'm not convinced
                // this method is bug-free.  At least it's simpler!
                //outw(OCR1B, inw(OCR1B) + PulseT1BPeriodTics);
                // change again
                OCR1B += PulseT1BPeriodTics;

                
                // decrement the number of pulses executed
                if(PulseT1BMode & PULSE_MODE_COUNTED)
                        PulseT1BCount--;
        }
        else
        {
                // pulse count has reached zero
                // disable the output compare's action on OC1B pin
                cbi(TCCR1A,COM1B1);
                cbi(TCCR1A,COM1B0);
                // and disable the output compare's interrupt to stop pulsing
                cbi(TIMSK, OCIE1B);
        }
}
{FILE END}
{FOOTER START}

Powered by WebSVN v2.8.3