home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
-
- FILE
- pfm0.c - simple unidirectional velocity measurement using
- Pulse Frequency Modulation
-
- ENTRY ROUTINES
- pfm_getv - read velocity value
- pfm_group - set pulse group size
-
- PRIVATE ROUTINE
- pulse - pulse interrupt service routine
-
- INITIALIZATION ROUTINE
- pfm_init - initialize this module
-
- REMARKS
- Velocity is calculated from the time interval it takes for a certain
- number of pulses to be detected. If the pulse rate is such that not
- enough pulses have arrived to form a group when a velocity reading is
- desired, then the velocity is calculated from the current pulse count
- instead of the group count.
-
- This module requires the use of an interval timer to time the group
- interval. Interval timers are implemented in software in the time.c
- module and are clocked off the single countdown timer available in the
- IBM PC. The function ReadITimer() returns the interval value in
- milliseconds and the procedure SetITimer() resets the interval to 0.
-
- This module uses the xignal package and time.c to set up parallel
- port interrupts and pulse timing. Thus, it must be linked with
- time.obj and xignal.lib
-
- LAST UPDATE
- 26 January 1988
- change names and eliminate getgroup()
-
- Copyright(c) 1985-1988 D.M. Auslander and C.H. Tham
-
- ***********************************************************************/
-
- /***********************************************************************
- I M P O R T S
- ***********************************************************************/
-
- #include "envir.h" /* environment */
-
- #include "inout.h" /* in() and out() mapping */
- #include "time.h" /* timer module declarations */
- #include "xignal.h" /* xignal package declarations */
-
-
- /***********************************************************************
- P R I V A T E D A T A
- ***********************************************************************/
-
- #define INPORT 0x3BE /* parallel input port address */
- #define INMASK 0x01 /* mask for pulse bit */
-
- static double pscale; /* pulses per unit displacement */
- static int itimer; /* interval timer number */
- static int pflag = 0; /* a group has arrived */
- static long period = 0L; /* time period for last group */
- static int pcount = 0; /* pulse count */
- static int group = 1; /* number of pulses per group */
-
-
- /***********************************************************************
- E N T R Y R O U T I N E S
- ***********************************************************************/
-
- /*----------------------------------------------------------------------
- FUNCTION
- PFM_GETV - return velocity reading
-
- SYNOPSIS
- double pfm_getv()
-
- RETURNS
- displacement per second
-
- REMARKS
- If there are insufficient pulses to make up a group, the velocity
- is based on the current pulse count instead of the group number.
-
- Note that pflag (and pcount) is accessed with interrupts disabled.
-
- pscale is a conversion factor to give velocity in revs/sec or
- whatever unit is convenient.
-
- LAST UPDATE
- 26 January 1988
- ----------------------------------------------------------------------*/
-
- double pfm_getv()
- {
- double v; /* temporary velocity value */
- long time; /* time period - copy of global period */
- int count; /* copy of pcount */
- int istat; /* interrupt status */
-
-
- istat = disable(); /* begin critical section */
-
- if (pflag) /* whole group collected */
- {
- pflag = 0; /* reset immediately */
- time = period;
-
- if (istat) /* exit critical section */
- enable();
-
- v = (group * pscale) / time; /* calculate velocity */
- }
- else /* not enough pulses for a group since last pfm_getv() */
- {
- count = pcount;
- time = ReadITimer(itimer);
-
- if (istat) /* exit critical section */
- enable();
-
- /* base velocity on current pulse count instead of group */
-
- v = (count * pscale) / time;
- }
-
- return(v);
- }
-
-
-
- /*---------------------------------------------------------------------
- ROUTINES
- PFM_GROUP - set pulse group size
-
- SYNOPSIS
- void pfm_group(size)
- int size;
-
- PARAMETER
- size - number of pulses in a group
-
- LAST UPDATE
- 26 January 1988
- name change
- ----------------------------------------------------------------------*/
-
- void pfm_group(size)
- int size;
- {
- int istat; /* interrupt status */
-
-
- istat = disable();
-
- group = size;
-
- if (istat)
- enable();
- }
-
-
-
- /***********************************************************************
- P R I V A T E R O U T I N E
- ***********************************************************************/
-
- /*----------------------------------------------------------------------
- PROCEDURE
- PULSE - pulse interrupt service routine
-
- SYNOPSIS
- static void pulse() - called by lower level interrupt service routine
-
- REMARKS
- If pulse count enough for a group, reset interval timer and record
- the time interval for the group.
-
- LAST UPDATE
- 8 April 1985
- ----------------------------------------------------------------------*/
-
- static void pulse()
- {
-
- if (in(INPORT) & INMASK) /* a pulse is detected */
- {
- ++pcount;
-
- if (pcount >= group) /* enough for a group */
- {
- period = ReadITimer(itimer); /* record group period */
-
- SetITimer(itimer); /* reset interval timer */
- pcount = 0; /* reset pulse count */
- pflag = 1; /* indicate data available */
- }
- }
-
- }
-
-
- /***********************************************************************
- I N I T I A L I Z A T I O N R O U T I N E S
- ***********************************************************************/
-
- /*----------------------------------------------------------------------
- PROCEDURE
- PFM_INIT - initialize
-
- SYNOPSIS
- void pfm_init(scale)
- double scale;
-
- PARAMETERS
- scale - pulse scaling factor: displacement per pulse
-
- REMARKS
- The scale is multiplied by 1000 because the interval timer
- readings are in milliseconds.
-
- LAST UPDATE
- 28 January 1988
- allocate interval timer here instead of externally
- ----------------------------------------------------------------------*/
-
- void pfm_init(scale)
- double scale;
- {
-
- pscale = scale * 1000.0;
-
- itimer = NewITimer(); /* allocate an interval timer */
-
- group = 100; /* default to 100 pulses in a group */
-
- SetITimer(itimer); /* initialize interval timer */
-
- xignal(XIGPRN, pulse); /* set pulse() as parallel port isr */
-
- out(INPORT, 0x14); /* enable parallel port interrupts */
- }
-
-