home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 15 / 15.iso / s / s300 / 1.ddi / CHAP3 / PFM0.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-05-02  |  7.2 KB  |  245 lines

  1. /***********************************************************************
  2.  
  3. FILE
  4.     pfm0.c  -  simple unidirectional velocity measurement using
  5.                Pulse Frequency Modulation
  6.  
  7. ENTRY ROUTINES
  8.     pfm_getv   -  read velocity value
  9.     pfm_group  -  set pulse group size
  10.  
  11. PRIVATE ROUTINE
  12.     pulse      -  pulse interrupt service routine
  13.  
  14. INITIALIZATION ROUTINE
  15.     pfm_init  -  initialize this module
  16.  
  17. REMARKS
  18.     Velocity is calculated from the time interval it takes for a certain
  19.     number of pulses to be detected.  If the pulse rate is such that not
  20.     enough pulses have arrived to form a group when a velocity reading is
  21.     desired, then the velocity is calculated from the current pulse count
  22.     instead of the group count.
  23.  
  24.     This module requires the use of an interval timer to time the group
  25.     interval.  Interval timers are implemented in software in the time.c
  26.     module and are clocked off the single countdown timer available in the
  27.     IBM PC.  The function ReadITimer() returns the interval value in
  28.     milliseconds and the procedure SetITimer() resets the interval to 0.
  29.  
  30.     This module uses the xignal package and time.c to set up parallel
  31.     port interrupts and pulse timing.  Thus, it must be linked with
  32.     time.obj and xignal.lib
  33.  
  34. LAST UPDATE
  35.     26 January 1988
  36.         change names and eliminate getgroup()
  37.  
  38.     Copyright(c) 1985-1988  D.M. Auslander and C.H. Tham
  39.  
  40. ***********************************************************************/
  41.  
  42. /***********************************************************************
  43.                             I M P O R T S
  44. ***********************************************************************/
  45.  
  46. #include "envir.h"          /* environment */
  47.  
  48. #include "inout.h"          /* in() and out() mapping */
  49. #include "time.h"           /* timer module declarations */
  50. #include "xignal.h"         /* xignal package declarations */
  51.  
  52.  
  53. /***********************************************************************
  54.                         P R I V A T E    D A T A
  55. ***********************************************************************/
  56.  
  57. #define INPORT  0x3BE       /* parallel input port address */
  58. #define INMASK  0x01        /* mask for pulse bit */
  59.  
  60. static double pscale;           /* pulses per unit displacement */
  61. static int itimer;              /* interval timer number */
  62. static int pflag = 0;           /* a group has arrived */
  63. static long period = 0L;        /* time period for last group */
  64. static int pcount = 0;          /* pulse count */
  65. static int group = 1;           /* number of pulses per group */
  66.  
  67.  
  68. /***********************************************************************
  69.                     E N T R Y    R O U T I N E S
  70. ***********************************************************************/
  71.  
  72. /*----------------------------------------------------------------------
  73. FUNCTION
  74.     PFM_GETV  -  return velocity reading
  75.  
  76. SYNOPSIS
  77.     double pfm_getv()
  78.  
  79. RETURNS
  80.     displacement per second
  81.  
  82. REMARKS
  83.     If there are insufficient pulses to make up a group, the velocity
  84.     is based on the current pulse count instead of the group number.
  85.  
  86.     Note that pflag (and pcount) is accessed with interrupts disabled.
  87.  
  88.     pscale is a conversion factor to give velocity in revs/sec or 
  89.     whatever unit is convenient.
  90.  
  91. LAST UPDATE
  92.     26 January 1988
  93. ----------------------------------------------------------------------*/
  94.     
  95. double pfm_getv()
  96. {
  97.     double v;           /* temporary velocity value */
  98.     long time;          /* time period - copy of global period */
  99.     int count;          /* copy of pcount */
  100.     int istat;          /* interrupt status */
  101.  
  102.  
  103.     istat = disable();                      /* begin critical section */
  104.  
  105.     if (pflag)                              /* whole group collected */
  106.     {
  107.         pflag = 0;                          /* reset immediately */
  108.         time = period;
  109.  
  110.         if (istat)                          /* exit critical section */
  111.             enable();
  112.  
  113.         v = (group * pscale) / time;        /* calculate velocity */
  114.     }
  115.     else    /* not enough pulses for a group since last pfm_getv() */
  116.     {
  117.         count = pcount;
  118.         time = ReadITimer(itimer);
  119.  
  120.         if (istat)                          /* exit critical section */
  121.             enable();
  122.  
  123.         /* base velocity on current pulse count instead of group */
  124.  
  125.         v = (count * pscale) / time;
  126.     }
  127.  
  128.     return(v);
  129. }
  130.  
  131.  
  132.  
  133. /*---------------------------------------------------------------------
  134. ROUTINES
  135.     PFM_GROUP  -  set pulse group size
  136.  
  137. SYNOPSIS
  138.     void pfm_group(size)
  139.     int size;
  140.  
  141. PARAMETER
  142.     size  -  number of pulses in a group
  143.  
  144. LAST UPDATE
  145.     26 January 1988
  146.         name change
  147. ----------------------------------------------------------------------*/
  148.  
  149. void pfm_group(size)
  150. int size;
  151. {
  152.     int istat;      /* interrupt status */
  153.     
  154.     
  155.     istat = disable();
  156.     
  157.     group = size;
  158.  
  159.     if (istat)
  160.         enable();
  161. }
  162.  
  163.  
  164.  
  165. /***********************************************************************
  166.                   P R I V A T E    R O U T I N E
  167. ***********************************************************************/
  168.  
  169. /*----------------------------------------------------------------------
  170. PROCEDURE
  171.     PULSE  -  pulse interrupt service routine
  172.  
  173. SYNOPSIS
  174.     static void pulse()  -  called by lower level interrupt service routine
  175.  
  176. REMARKS
  177.     If pulse count enough for a group, reset interval timer and record
  178.     the time interval for the group.
  179.  
  180. LAST UPDATE
  181.     8 April 1985
  182. ----------------------------------------------------------------------*/
  183.     
  184. static void pulse()
  185. {
  186.  
  187.     if (in(INPORT) & INMASK)    /* a pulse is detected */
  188.     {
  189.         ++pcount;
  190.  
  191.         if (pcount >= group)                /* enough for a group */
  192.         {
  193.             period = ReadITimer(itimer);    /* record group period */
  194.  
  195.             SetITimer(itimer);              /* reset interval timer */
  196.             pcount = 0;                     /* reset pulse count */
  197.             pflag = 1;                      /* indicate data available */
  198.         }
  199.     }
  200.  
  201. }
  202.  
  203.  
  204. /***********************************************************************
  205.             I N I T I A L I Z A T I O N    R O U T I N E S
  206. ***********************************************************************/
  207.  
  208. /*----------------------------------------------------------------------
  209. PROCEDURE
  210.     PFM_INIT  -  initialize
  211.  
  212. SYNOPSIS
  213.     void pfm_init(scale)
  214.     double scale;
  215.  
  216. PARAMETERS
  217.     scale  -  pulse scaling factor: displacement per pulse
  218.  
  219. REMARKS
  220.     The scale is multiplied by 1000 because the interval timer
  221.     readings are in milliseconds.
  222.  
  223. LAST UPDATE
  224.     28 January 1988
  225.         allocate interval timer here instead of externally
  226. ----------------------------------------------------------------------*/
  227.  
  228. void pfm_init(scale)
  229. double scale;
  230. {
  231.  
  232.     pscale = scale * 1000.0;
  233.  
  234.     itimer = NewITimer();   /* allocate an interval timer */
  235.  
  236.     group = 100;            /* default to 100 pulses in a group */
  237.  
  238.     SetITimer(itimer);      /* initialize interval timer */
  239.  
  240.     xignal(XIGPRN, pulse);  /* set pulse() as parallel port isr */
  241.  
  242.     out(INPORT, 0x14);      /* enable parallel port interrupts */
  243. }
  244.  
  245.