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

encoder.c

Go to the documentation of this file.
00001 /*! \file encoder.c \brief Quadrature Encoder reader/driver. */
00002 //*****************************************************************************
00003 //
00004 // File Name    : 'encoder.c'
00005 // Title        : Quadrature Encoder reader/driver
00006 // Author       : Pascal Stang - Copyright (C) 2003-2004
00007 // Created      : 2003.01.26
00008 // Revised      : 2004.06.25
00009 // Version      : 0.3
00010 // Target MCU   : Atmel AVR Series
00011 // Editor Tabs  : 4
00012 //
00013 // NOTE: This code is currently below version 1.0, and therefore is considered
00014 // to be lacking in some functionality or documentation, or may not be fully
00015 // tested.  Nonetheless, you can expect most functions to work.
00016 //
00017 // This code is distributed under the GNU Public License
00018 //      which can be found at http://www.gnu.org/licenses/gpl.txt
00019 //
00020 //*****************************************************************************
00021 
00022 #ifndef WIN32
00023     #include <avr/io.h>
00024     #include <avr/signal.h>
00025     #include <avr/interrupt.h>
00026 #endif
00027 
00028 #include "global.h"
00029 #include "encoder.h"
00030 
00031 // Program ROM constants
00032 
00033 // Global variables
00034 volatile EncoderStateType EncoderState[NUM_ENCODERS];
00035 
00036 // Functions
00037 
00038 // encoderInit() initializes hardware and encoder position readings
00039 //      Run this init routine once before using any other encoder functions.
00040 void encoderInit(void)
00041 {
00042     u08 i;
00043 
00044     // initialize/clear encoder data
00045     for(i=0; i<NUM_ENCODERS; i++)
00046     {
00047         EncoderState[i].position = 0;
00048         //EncoderState[i].velocity = 0;     // NOT CURRENTLY USED
00049     }
00050 
00051     // configure direction and interrupt I/O pins:
00052     // - for input
00053     // - apply pullup resistors
00054     // - any-edge interrupt triggering
00055     // - enable interrupt
00056 
00057     #ifdef ENC0_SIGNAL
00058         // set interrupt pins to input and apply pullup resistor
00059         cbi(ENC0_PHASEA_DDR, ENC0_PHASEA_PIN);
00060         sbi(ENC0_PHASEA_PORT, ENC0_PHASEA_PIN);
00061         // set encoder direction pin for input and apply pullup resistor
00062         cbi(ENC0_PHASEB_DDR, ENC0_PHASEB_PIN);
00063         sbi(ENC0_PHASEB_PORT, ENC0_PHASEB_PIN);
00064         // configure interrupts for any-edge triggering
00065         sbi(ENC0_ICR, ENC0_ISCX0);
00066         cbi(ENC0_ICR, ENC0_ISCX1);
00067         // enable interrupts
00068         sbi(IMSK, ENC0_INT);    // ISMK is auto-defined in encoder.h
00069     #endif
00070     #ifdef ENC1_SIGNAL
00071         // set interrupt pins to input and apply pullup resistor
00072         cbi(ENC1_PHASEA_DDR, ENC1_PHASEA_PIN);
00073         sbi(ENC1_PHASEA_PORT, ENC1_PHASEA_PIN);
00074         // set encoder direction pin for input and apply pullup resistor
00075         cbi(ENC1_PHASEB_DDR, ENC1_PHASEB_PIN);
00076         sbi(ENC1_PHASEB_PORT, ENC1_PHASEB_PIN);
00077         // configure interrupts for any-edge triggering
00078         sbi(ENC1_ICR, ENC1_ISCX0);
00079         cbi(ENC1_ICR, ENC1_ISCX1);
00080         // enable interrupts
00081         sbi(IMSK, ENC1_INT);    // ISMK is auto-defined in encoder.h
00082     #endif
00083     #ifdef ENC2_SIGNAL
00084         // set interrupt pins to input and apply pullup resistor
00085         cbi(ENC2_PHASEA_DDR, ENC2_PHASEA_PIN);
00086         sbi(ENC2_PHASEA_PORT, ENC2_PHASEA_PIN);
00087         // set encoder direction pin for input and apply pullup resistor
00088         cbi(ENC2_PHASEB_DDR, ENC2_PHASEB_PIN);
00089         sbi(ENC2_PHASEB_PORT, ENC2_PHASEB_PIN);
00090         // configure interrupts for any-edge triggering
00091         sbi(ENC2_ICR, ENC2_ISCX0);
00092         cbi(ENC2_ICR, ENC2_ISCX1);
00093         // enable interrupts
00094         sbi(IMSK, ENC2_INT);    // ISMK is auto-defined in encoder.h
00095     #endif
00096     #ifdef ENC3_SIGNAL
00097         // set interrupt pins to input and apply pullup resistor
00098         cbi(ENC3_PHASEA_DDR, ENC3_PHASEA_PIN);
00099         sbi(ENC3_PHASEA_PORT, ENC3_PHASEA_PIN);
00100         // set encoder direction pin for input and apply pullup resistor
00101         cbi(ENC3_PHASEB_DDR, ENC3_PHASEB_PIN);
00102         sbi(ENC3_PHASEB_PORT, ENC3_PHASEB_PIN);
00103         // configure interrupts for any-edge triggering
00104         sbi(ENC3_ICR, ENC3_ISCX0);
00105         cbi(ENC3_ICR, ENC3_ISCX1);
00106         // enable interrupts
00107         sbi(IMSK, ENC3_INT);    // ISMK is auto-defined in encoder.h
00108     #endif
00109     
00110     // enable global interrupts
00111     sei();
00112 }
00113 
00114 // encoderOff() disables hardware and stops encoder position updates
00115 void encoderOff(void)
00116 {
00117     // disable encoder interrupts
00118     #ifdef ENC0_SIGNAL
00119         // disable interrupts
00120         sbi(IMSK, INT0);    // ISMK is auto-defined in encoder.h
00121     #endif
00122     #ifdef ENC1_SIGNAL
00123         // disable interrupts
00124         sbi(IMSK, INT1);    // ISMK is auto-defined in encoder.h
00125     #endif
00126     #ifdef ENC2_SIGNAL
00127         // disable interrupts
00128         sbi(IMSK, INT2);    // ISMK is auto-defined in encoder.h
00129     #endif
00130     #ifdef ENC3_SIGNAL
00131         // disable interrupts
00132         sbi(IMSK, INT3);    // ISMK is auto-defined in encoder.h
00133     #endif
00134 }
00135 
00136 // encoderGetPosition() reads the current position of the encoder 
00137 s32 encoderGetPosition(u08 encoderNum)
00138 {
00139     // sanity check
00140     if(encoderNum < NUM_ENCODERS)
00141         return EncoderState[encoderNum].position;
00142     else
00143         return 0;
00144 }
00145 
00146 // encoderSetPosition() sets the current position of the encoder
00147 void encoderSetPosition(u08 encoderNum, s32 position)
00148 {
00149     // sanity check
00150     if(encoderNum < NUM_ENCODERS)
00151         EncoderState[encoderNum].position = position;
00152     // else do nothing
00153 }
00154 
00155 #ifdef ENC0_SIGNAL
00156 //! Encoder 0 interrupt handler
00157 SIGNAL(ENC0_SIGNAL)
00158 {
00159     // encoder has generated a pulse
00160     // check the relative phase of the input channels
00161     // and update position accordingly
00162     if( ((inb(ENC0_PHASEA_PORTIN) & (1<<ENC0_PHASEA_PIN)) == 0) ^
00163         ((inb(ENC0_PHASEB_PORTIN) & (1<<ENC0_PHASEB_PIN)) == 0) )
00164     {
00165         EncoderState[0].position++;
00166     }
00167     else
00168     {
00169         EncoderState[0].position--;
00170     }
00171 }
00172 #endif
00173 
00174 #ifdef ENC1_SIGNAL
00175 //! Encoder 1 interrupt handler
00176 SIGNAL(ENC1_SIGNAL)
00177 {
00178     // encoder has generated a pulse
00179     // check the relative phase of the input channels
00180     // and update position accordingly
00181     if( ((inb(ENC1_PHASEA_PORTIN) & (1<<ENC1_PHASEA_PIN)) == 0) ^
00182         ((inb(ENC1_PHASEB_PORTIN) & (1<<ENC1_PHASEB_PIN)) == 0) )
00183     {
00184         EncoderState[1].position++;
00185     }
00186     else
00187     {
00188         EncoderState[1].position--;
00189     }
00190 }
00191 #endif
00192 
00193 #ifdef ENC2_SIGNAL
00194 //! Encoder 2 interrupt handler
00195 SIGNAL(ENC2_SIGNAL)
00196 {
00197     // encoder has generated a pulse
00198     // check the relative phase of the input channels
00199     // and update position accordingly
00200     if( ((inb(ENC2_PHASEA_PORTIN) & (1<<ENC2_PHASEA_PIN)) == 0) ^
00201         ((inb(ENC2_PHASEB_PORTIN) & (1<<ENC2_PHASEB_PIN)) == 0) )
00202     {
00203         EncoderState[2].position++;
00204     }
00205     else
00206     {
00207         EncoderState[2].position--;
00208     }
00209 }
00210 #endif
00211 
00212 #ifdef ENC3_SIGNAL
00213 //! Encoder 3 interrupt handler
00214 SIGNAL(ENC3_SIGNAL)
00215 {
00216     // encoder has generated a pulse
00217     // check the relative phase of the input channels
00218     // and update position accordingly
00219     if( ((inb(ENC3_PHASEA_PORTIN) & (1<<ENC3_PHASEA_PIN)) == 0) ^
00220         ((inb(ENC3_PHASEB_PORTIN) & (1<<ENC3_PHASEB_PIN)) == 0) )
00221     {
00222         EncoderState[3].position++;
00223     }
00224     else
00225     {
00226         EncoderState[3].position--;
00227     }
00228 }
00229 #endif

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