home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
-
- FILE
- pfm1.c - unidirectional velocity measurement using
- Pulse Frequency Modulation with adaptive pulse group size.
-
- 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
- This differs from pfm0.c in that the group size used in velocity
- calculation adapts to the arrival rate of the pulses.
-
- If the pulses arrive too slowly, as determined by MAXPERIOD and
- the sampling time, the group size is halved since we do not want
- the group interval to exceed the sampling time. If the problem
- persists, the group size is reduced again until the lower limit
- of one, in which case velocity is based on the interval between
- consecutive pulses.
-
- However, if the pulses are arriving too rapidly, then the group
- size should be increased as the interval timer cannot accurately
- measure small intervals. The minimum period, MINPERIOD criteria
- to determine if we should increase the group size is based on the
- resolution of the interval timer. In this case, the interval timer
- has a poor resolution and MINPERIOD reflects this.
-
- 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" /* environmemnt */
-
- #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 MINPERIOD 50L /* minimum group period, timer limit */
- #define MAXPERIOD 200L /* max group period, sampling time limit */
-
- #define INPORT 0x3BE /* parallel input port address */
- #define INMASK 0x01 /* mask for pulse bit */
-
- #define MAXINT 0x7FFF /* max value for 16-bit integer */
-
- 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 - get velocity reading, adaptive version
-
- SYNOPSIS
- double pfm_getv()
-
- RETURNS
- displacement per second
-
- REMARKS
- This version differs from that in pfm0.c in that the group size
- is adjusted to keep the period (i.e. the time interval needed to
- collect the number of pulses forming a group) between MINPERIOD
- and MAXPERIOD.
-
- If the group period is less than MINPERIOD, pulses are arriving
- too fast for the resolution of the timer. The group size is
- doubled.
-
- If the group period is greater than MAXPERIOD, pulses are
- arriving too slowly to form a group when a velocity reading is
- required. The group size is halved (with a floor of 1).
-
- LAST UPDATE
- 26 January 1988
- name change and other minor modifications
- ----------------------------------------------------------------------*/
-
- double pfm_getv()
- {
- long time; /* time period - copy of global period */
- int count; /* copy of pcount */
- int istat; /* interrupt status */
-
-
- istat = disable(); /* begin critical section */
-
- if (pflag) /* data available */
- {
- pflag = 0; /* reset immediately */
- time = period;
- count = group;
-
- /*---------------------------------------------------------
- If the period is less than some predefined minimum,
- pulses are arriving too fast. Double the group size.
- ---------------------------------------------------------*/
-
- if (period <= MINPERIOD) /* pulses arriving too fast, */
- group <<= 1; /* double the group size. */
-
- if (group < 0) /* group variable overflow! */
- group = MAXINT; /* set to max integer value */
- }
- else /* not enough pulses for a group since last pfm_getv() */
- {
- /*-------------------------------------------------------------
- Base velocity on the current pulse count instead of the
- group count. This is more accurate than returning the
- previous velocity value. If the current pulse count is
- zero, then the velocity is too low for the resolution
- of this routine; it is effectively zero.
- --------------------------------------------------------------*/
-
- time = ReadITimer(itimer);
- count = pcount;
-
- /*------------------------------------------------------------
- If the elasped time since the start of the current group
- exceeds MAXPERIOD, either the pulses are arriving too
- slowly or the group size is too big, or both. The group
- size is halved.
- ------------------------------------------------------------*/
-
- if (time > MAXPERIOD) /* pulses are arriving too slowly */
- if (group > 1)
- group >>= 1; /* halve group size, floor of 1 */
- }
-
- if (istat) /* exit critical section */
- enable();
-
- return(count * pscale / time);
- }
-
-
-
- /*---------------------------------------------------------------------
- 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) /* verify pulse */
- {
- ++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 */
- }
-
-
-