home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
-
- FILE
- quad1.c - quadrature position and velocity measurement routines
-
- ENTRY ROUTINE
- quad_getp - get position
-
- PRIVATE ROUTINE
- pulse - parallel port interrupt service routine
-
- INITIALIZATION ROUTINE
- quad_init - initialize this module
-
- REMARKS
- This module extends quad0.c by measuring velocity as well as
- position using quadrature signals.
-
- For simplicity, this module assumes that quad_getv() will be
- called at fixed intervals corresponding to the sampling period.
- The velocity is then calculated by counting pulses over a sample
- interval. Unless the velocity is very slow, calculating velocity
- at every quadrature state transistion may incur too much overhead.
-
- Note also that the pulse count variables are integers instead of
- long integers. On an IBM-PC, ints are faster and access can be
- assume to be atomic with most compilers. However, there is a
- greater chance of overflow. Whether to use ints or longs depends
- on the requirements of your application (and how paranoid you
- are obout overflows).
-
- You may want to use an interval timer instead of assuming a
- fixed sampling interval. See pfm0.c and time.c for an example
- of how a software interval timer in time.c may be used.
-
- This module requires the xignal package to set up the parallel
- port interrupt handler.
-
- LAST UPDATE
- 27 January 1988
-
- Copyright(c) 1985-1988 D.M. Auslander and C.H. Tham
-
- ***********************************************************************/
-
- /***********************************************************************
- I M P O R T S
- ***********************************************************************/
-
- #include "envir.h"
-
- #include "inout.h"
- #include "xignal.h"
-
-
- /***********************************************************************
- F O R W A R D D E C L A R A T I O N S
- ***********************************************************************/
-
- #ifdef ANSI
-
- void incp(void);
- void decp(void);
-
- #else
-
- void incp();
- void decp();
-
- #endif
-
- /***********************************************************************
- P R I V A T E D A T A
- ***********************************************************************/
-
- #define PHASEMASK 0x03 /* mask for bits 0 and 1 on parallel port */
-
- #define STATE00 0x00 /* quadrature states */
- #define STATE01 0x01
- #define STATE10 0x02
- #define STATE11 0x03
-
- #define INPORT 0x3BE /* parallel input port address */
-
- #define FORWARD 1 /* forward direction flag value */
- #define REVERSE 0 /* reverse direction flag value */
-
- static int oldstate; /* previous state of quadrature input */
- static int curstate; /* current quadrature state */
- static int pcount; /* current pulse count */
- static int rcount; /* reference count, for computing velocity */
- static int error; /* error flag, initialized to false */
- static int revflag; /* direction reversal flag */
- static int direction; /* direction flag */
- static double pscale; /* displacement per count */
- static double tsamp; /* sampling period */
-
-
- /***********************************************************************
- E N T R Y R O U T I N E S
- ***********************************************************************/
-
- /*----------------------------------------------------------------------
- FUNCTION
- QUAD_GETP - read position value (same as in quad0.c)
-
- SYNOPSIS
- double quad_getp()
-
- RETURNS
- incremental position in inches
-
- LAST UPDATE
- 26 January 1988
- change to double return type
- ----------------------------------------------------------------------*/
-
- double quad_getp()
- {
- int istat; /* interrupt status */
- int count; /* copy of pcount */
-
-
- if (error)
- {
- printf("quadrature state transistion error\n");
-
- error = 0; /* reset error flag */
- }
-
- istat = disable(); /* begin critical section */
-
- count = pcount;
-
- if (istat) /* exit critical section */
- enable();
-
- return(count * pscale);
- }
-
-
-
- /*----------------------------------------------------------------------
- FUNCTION
- QUAD_GETV - derive velocity from quadrature pulses
-
- SYNOPSIS
- double quad_getv()
-
- RETURNS
- velocity in rev/sec
-
- REMARKS
- For simplicity, we assume getv() is called at intervals of tsamp
- seconds. However, you may wish to use an interval timer instead
- of making this assumption.
-
- The velocity is derived from the diffrence between the current
- pulse count and the pulse count when this routine is last called
- in the previous sampling instance. If there is a change in
- direction between the current and last call (as indicated by the
- revflag), velocity is derived using the pulse count when the direction
- reversal takes place (rcount) instead of the count when this routine
- is last called (lcount). This gives a reasonable estimate of the
- actual velocity.
-
- If you are using an interval timer instead of assuming fixed
- sampling time, substitute calls to read and reset the interval
- timer instead of using tsamp.
-
- LAST UPDATE
- 27 January 1988
- use rcount when direction changes.
- ----------------------------------------------------------------------*/
-
- double quad_getv()
- {
- static int last_count = 0; /* pcount at last call */
- int cur_count; /* current value of pcount */
- int rev_count; /* copy of rcount */
- int istat; /* interrupt status */
- double velocity; /* computed velocity */
-
-
- if (error)
- {
- printf("quadrature state transistion error\n");
-
- error = 0; /* reset error flag */
- }
-
- /*------------------------------------------------------------
- Copies of pcount and rcount are made with interrupts
- disabled to prevent their being asynchronously changed by
- pulse() during velocity computation. This precaution
- may be omitted to reduce overheads if the resultant error
- in velocity is not significant. Real time programming
- is full of such trade-offs.
- ------------------------------------------------------------*/
-
- istat = disable();
-
- cur_count = pcount;
- rev_count = rcount;
-
- if (revflag) /* a direction reversal has taken place */
- {
- revflag = 0;
-
- if (istat) /* interrupts enabled after clearing revflag */
- enable();
-
- velocity = (cur_count - rev_count) * pscale / tsamp;
- }
- else
- {
- if (istat)
- enable();
-
- velocity = (cur_count - last_count) * pscale / tsamp;
- }
-
- last_count = cur_count;
-
- return(velocity);
- }
-
-
-
- /***********************************************************************
- P R I V A T E R O U T I N E S
- ***********************************************************************/
-
- /*---------------------------------------------------------------------
- PROCEDURE
- PULSE - quadrature pulse input interrupt service routine
-
- SYNOPSIS
- static void pulse(), called by parallel port interrupt service routine
-
- REMARKS
- Basically the same as that in quad0.c, except that it calls
- procedures decp() and incp() to update the pulse count and
- set revflag if there is a change in direction.
-
- LAST UPDATE
- 26 January 1988
- use new void type
- ----------------------------------------------------------------------*/
-
- static void pulse()
- {
-
- oldstate = curstate; /* update state variables */
-
- curstate = in(INPORT) & PHASEMASK; /* read quadrature signal */
-
- switch (oldstate)
- {
- case STATE00:
-
- if (curstate == STATE01)
- decp();
- else if (curstate == STATE10)
- incp();
- else
- error = 1;
-
- break;
-
- case STATE01:
-
- if (curstate == STATE11)
- decp();
- else if (curstate == STATE00)
- incp();
- else
- error = 1;
-
- break;
-
- case STATE11:
-
- if (curstate == STATE10)
- decp();
- else if (curstate == STATE01)
- incp();
- else
- error = 1;
-
- break;
-
- case STATE10:
-
- if (curstate == STATE00)
- decp();
- else if (curstate == STATE11)
- incp();
- else
- error = 1;
- }
-
- }
-
-
-
- /*---------------------------------------------------------------------
- PROCEDURE
- INCP - increment pulse count
-
- SYNOPSIS
- static void incp()
-
- REMARKS
- Updates direction indicator and mark current pulse count
-
- LAST UPDATE
- 27 January 1988
- mark current pcount instead of using flag
- ----------------------------------------------------------------------*/
-
- static void incp()
- {
-
- ++pcount; /* increment pulse count */
-
- if (direction == REVERSE) /* direction reversal is indicated */
- {
- direction = FORWARD;
- rcount = pcount;
- revflag = 1;
- }
-
- }
-
-
-
- /*---------------------------------------------------------------------
- PROCEDURE
- DECP - decrement pulse count
-
- SYNOPSIS
- static void decp()
-
- REMARKS
- Updates direction indicator and mark current pulse count
-
- LAST UPDATE
- 27 January 1988
- mark current pcount instead of using flag
- ----------------------------------------------------------------------*/
-
- static void decp()
- {
-
- --pcount; /* decrement pulse count */
-
- if (direction == FORWARD) /* direction reversal is indicated */
- {
- direction = REVERSE;
- rcount = pcount;
- revflag = 1;
- }
-
- }
-
-
- /***********************************************************************
- I N I T I A L I Z A T I O N R O U T I N E S
- ***********************************************************************/
-
- /*---------------------------------------------------------------------
- PROCEDURE
- QUAD_INIT - initialize
-
- SYNOPSIS
- void quad_init(scale, period)
- double scale, period;
-
- PARAMETERS
- scale - displacement per quadrature count
- period - sampling period
-
- LAST UPDATE
- 26 January 1988
- calling routine specifies scaling factor
- ----------------------------------------------------------------------*/
-
- void quad_init(scale, period)
- double scale, period;
- {
-
- pscale = scale;
- tsamp = period;
-
- pcount = 0;
- rcount = 0;
- error = 0;
- revflag = 0;
- direction = FORWARD; /* arbitrary choice */
-
- curstate = oldstate = in(INPORT) & PHASEMASK;
-
- xignal(XIGPRN, pulse); /* install pulse() as service routine */
-
- }
-
-