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