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 #include <avr/io.h>
00023 #include <avr/interrupt.h>
00024 
00025 #include "global.h"
00026 #include "encoder.h"
00027 
00028 // Program ROM constants
00029 
00030 // Global variables
00031 volatile EncoderStateType EncoderState[NUM_ENCODERS];
00032 
00033 // Functions
00034 
00035 // encoderInit() initializes hardware and encoder position readings
00036 //      Run this init routine once before using any other encoder functions.
00037 void encoderInit(void)
00038 {
00039     u08 i;
00040 
00041     // initialize/clear encoder data
00042     for(i=0; i<NUM_ENCODERS; i++)
00043     {
00044         EncoderState[i].position = 0;
00045         //EncoderState[i].velocity = 0;     // NOT CURRENTLY USED
00046     }
00047 
00048     // configure direction and interrupt I/O pins:
00049     // - for input
00050     // - apply pullup resistors
00051     // - any-edge interrupt triggering
00052     // - enable interrupt
00053 
00054     #ifdef ENC0_SIGNAL
00055         // set interrupt pins to input and apply pullup resistor
00056         cbi(ENC0_PHASEA_DDR, ENC0_PHASEA_PIN);
00057         sbi(ENC0_PHASEA_PORT, ENC0_PHASEA_PIN);
00058         // set encoder direction pin for input and apply pullup resistor
00059         cbi(ENC0_PHASEB_DDR, ENC0_PHASEB_PIN);
00060         sbi(ENC0_PHASEB_PORT, ENC0_PHASEB_PIN);
00061         // configure interrupts for any-edge triggering
00062         sbi(ENC0_ICR, ENC0_ISCX0);
00063         cbi(ENC0_ICR, ENC0_ISCX1);
00064         // enable interrupts
00065         sbi(IMSK, ENC0_INT);    // ISMK is auto-defined in encoder.h
00066     #endif
00067     #ifdef ENC1_SIGNAL
00068         // set interrupt pins to input and apply pullup resistor
00069         cbi(ENC1_PHASEA_DDR, ENC1_PHASEA_PIN);
00070         sbi(ENC1_PHASEA_PORT, ENC1_PHASEA_PIN);
00071         // set encoder direction pin for input and apply pullup resistor
00072         cbi(ENC1_PHASEB_DDR, ENC1_PHASEB_PIN);
00073         sbi(ENC1_PHASEB_PORT, ENC1_PHASEB_PIN);
00074         // configure interrupts for any-edge triggering
00075         sbi(ENC1_ICR, ENC1_ISCX0);
00076         cbi(ENC1_ICR, ENC1_ISCX1);
00077         // enable interrupts
00078         sbi(IMSK, ENC1_INT);    // ISMK is auto-defined in encoder.h
00079     #endif
00080     #ifdef ENC2_SIGNAL
00081         // set interrupt pins to input and apply pullup resistor
00082         cbi(ENC2_PHASEA_DDR, ENC2_PHASEA_PIN);
00083         sbi(ENC2_PHASEA_PORT, ENC2_PHASEA_PIN);
00084         // set encoder direction pin for input and apply pullup resistor
00085         cbi(ENC2_PHASEB_DDR, ENC2_PHASEB_PIN);
00086         sbi(ENC2_PHASEB_PORT, ENC2_PHASEB_PIN);
00087         // configure interrupts for any-edge triggering
00088         sbi(ENC2_ICR, ENC2_ISCX0);
00089         cbi(ENC2_ICR, ENC2_ISCX1);
00090         // enable interrupts
00091         sbi(IMSK, ENC2_INT);    // ISMK is auto-defined in encoder.h
00092     #endif
00093     #ifdef ENC3_SIGNAL
00094         // set interrupt pins to input and apply pullup resistor
00095         cbi(ENC3_PHASEA_DDR, ENC3_PHASEA_PIN);
00096         sbi(ENC3_PHASEA_PORT, ENC3_PHASEA_PIN);
00097         // set encoder direction pin for input and apply pullup resistor
00098         cbi(ENC3_PHASEB_DDR, ENC3_PHASEB_PIN);
00099         sbi(ENC3_PHASEB_PORT, ENC3_PHASEB_PIN);
00100         // configure interrupts for any-edge triggering
00101         sbi(ENC3_ICR, ENC3_ISCX0);
00102         cbi(ENC3_ICR, ENC3_ISCX1);
00103         // enable interrupts
00104         sbi(IMSK, ENC3_INT);    // ISMK is auto-defined in encoder.h
00105     #endif
00106     
00107     // enable global interrupts
00108     sei();
00109 }
00110 
00111 // encoderOff() disables hardware and stops encoder position updates
00112 void encoderOff(void)
00113 {
00114     // disable encoder interrupts
00115     #ifdef ENC0_SIGNAL
00116         // disable interrupts
00117         sbi(IMSK, INT0);    // ISMK is auto-defined in encoder.h
00118     #endif
00119     #ifdef ENC1_SIGNAL
00120         // disable interrupts
00121         sbi(IMSK, INT1);    // ISMK is auto-defined in encoder.h
00122     #endif
00123     #ifdef ENC2_SIGNAL
00124         // disable interrupts
00125         sbi(IMSK, INT2);    // ISMK is auto-defined in encoder.h
00126     #endif
00127     #ifdef ENC3_SIGNAL
00128         // disable interrupts
00129         sbi(IMSK, INT3);    // ISMK is auto-defined in encoder.h
00130     #endif
00131 }
00132 
00133 // encoderGetPosition() reads the current position of the encoder 
00134 s32 encoderGetPosition(u08 encoderNum)
00135 {
00136     // sanity check
00137     if(encoderNum < NUM_ENCODERS)
00138         return EncoderState[encoderNum].position;
00139     else
00140         return 0;
00141 }
00142 
00143 // encoderSetPosition() sets the current position of the encoder
00144 void encoderSetPosition(u08 encoderNum, s32 position)
00145 {
00146     // sanity check
00147     if(encoderNum < NUM_ENCODERS)
00148         EncoderState[encoderNum].position = position;
00149     // else do nothing
00150 }
00151 
00152 #ifdef ENC0_SIGNAL
00153 //! Encoder 0 interrupt handler
00154 SIGNAL(ENC0_SIGNAL)
00155 {
00156     // encoder has generated a pulse
00157     // check the relative phase of the input channels
00158     // and update position accordingly
00159     if( ((inb(ENC0_PHASEA_PORTIN) & (1<<ENC0_PHASEA_PIN)) == 0) ^
00160         ((inb(ENC0_PHASEB_PORTIN) & (1<<ENC0_PHASEB_PIN)) == 0) )
00161     {
00162         EncoderState[0].position++;
00163     }
00164     else
00165     {
00166         EncoderState[0].position--;
00167     }
00168 }
00169 #endif
00170 
00171 #ifdef ENC1_SIGNAL
00172 //! Encoder 1 interrupt handler
00173 SIGNAL(ENC1_SIGNAL)
00174 {
00175     // encoder has generated a pulse
00176     // check the relative phase of the input channels
00177     // and update position accordingly
00178     if( ((inb(ENC1_PHASEA_PORTIN) & (1<<ENC1_PHASEA_PIN)) == 0) ^
00179         ((inb(ENC1_PHASEB_PORTIN) & (1<<ENC1_PHASEB_PIN)) == 0) )
00180     {
00181         EncoderState[1].position++;
00182     }
00183     else
00184     {
00185         EncoderState[1].position--;
00186     }
00187 }
00188 #endif
00189 
00190 #ifdef ENC2_SIGNAL
00191 //! Encoder 2 interrupt handler
00192 SIGNAL(ENC2_SIGNAL)
00193 {
00194     // encoder has generated a pulse
00195     // check the relative phase of the input channels
00196     // and update position accordingly
00197     if( ((inb(ENC2_PHASEA_PORTIN) & (1<<ENC2_PHASEA_PIN)) == 0) ^
00198         ((inb(ENC2_PHASEB_PORTIN) & (1<<ENC2_PHASEB_PIN)) == 0) )
00199     {
00200         EncoderState[2].position++;
00201     }
00202     else
00203     {
00204         EncoderState[2].position--;
00205     }
00206 }
00207 #endif
00208 
00209 #ifdef ENC3_SIGNAL
00210 //! Encoder 3 interrupt handler
00211 SIGNAL(ENC3_SIGNAL)
00212 {
00213     // encoder has generated a pulse
00214     // check the relative phase of the input channels
00215     // and update position accordingly
00216     if( ((inb(ENC3_PHASEA_PORTIN) & (1<<ENC3_PHASEA_PIN)) == 0) ^
00217         ((inb(ENC3_PHASEB_PORTIN) & (1<<ENC3_PHASEB_PIN)) == 0) )
00218     {
00219         EncoderState[3].position++;
00220     }
00221     else
00222     {
00223         EncoderState[3].position--;
00224     }
00225 }
00226 #endif

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