home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_02_01 / 2n01033a < prev    next >
Text File  |  1990-12-04  |  7KB  |  270 lines

  1.  
  2. /* METER.C   A display and digital filter example
  3.  *      By Frank Bosso of Product Designs, Danbury CT.
  4.  *      last edit: 20-Oct.-90
  5. */
  6. #include <stdio.h>  /* call for the standard defines */
  7. #include <graph.h> /* There are graphic statements here */
  8. #include <stdlib.h>
  9. /* 
  10.  * A little formality
  11. */
  12. char cpyrit[]="METER Copyright (c) 1990 Product Designs";
  13. /*
  14. * Declare the program constants
  15. */
  16. #define BLACK_COLOR  0        /* 0 = EGA black */
  17. #define BACK_COLOR  1         /* 1 = EGA blue */
  18. #define FORG_COLOR  16        /* 16 = EGA white */
  19. #define  FULL_SCALE  100      /* The standard full scale*/
  20. #define  DISPLAY_SCALE  100   /* meter display width */
  21. #define  STEP_SIZE 25         /*the square wave amplitude*/
  22. #define  STEP_TIME 150         /* the square wave timing */
  23. #define WN_MAX 32 /*The highest allowable ratio of Fs/Wn*/
  24. #define FOREVER for (;;)       /* A long loop construct */
  25. /*
  26.  * A structure to contain the control variables
  27.  * for a metering display
  28. */
  29. typedef struct {
  30.   int oldvalue;
  31.   int     x1;             /* first order variable */
  32.   int     x2;             /* second order variable */
  33.   int     l;              /*      left posx */
  34.   int     b;             /*      bottom posy */
  35.   int     r;             /*      right posx */
  36.   int     t;             /*      top posy */
  37.   int     w2; /* (F/W)^2 = position filter constant */
  38.   int     aw; /* a*F/W = velocity filter constant */
  39.   } METER;
  40. /*
  41.  * Some instances of a meter
  42. */
  43. METER   M0 = {0};
  44. METER   M1 = {0};
  45. METER   M2 = {0};
  46.  
  47. METER   M3 = {0};
  48. METER   M4 = {0};
  49. METER   M5 = {0};
  50. /*
  51.  * Prototype the display functions
  52. */
  53. void create_all_meter(int wn);
  54. void create_meter(METER *(p),int posx,int posy,
  55.                   int warg,int aarg);
  56. void show_meter(METER *(p), int value);
  57. int filter_meter(METER *(p), int value);
  58. int fetch(int arg);
  59. /*
  60.  * Now for the mainline
  61. */
  62. main()
  63. {
  64. int  i, j, o, tmp;   /* create some working variables */
  65. int  step;
  66. int  wn;
  67.  
  68. _setvideomode(_HRES16COLOR);    /* Select EGA mode */
  69.  
  70. wn = 2; /* The initial frequency ratio */
  71.  
  72. create_all_meter(wn);           /* Paint the meter panel */
  73.  
  74. i=25;
  75.  
  76. /*
  77.  * stroke the meter displays through their
  78.  * full range
  79. */
  80. FOREVER {
  81.     j = fetch(i);
  82.  
  83.     show_meter( &M0,j);
  84.     show_meter( &M1,j);
  85.     show_meter( &M2,j);
  86.  
  87.     show_meter( &M3,j);
  88.     show_meter( &M4,j);
  89.     show_meter( &M5,j);
  90.  
  91.     if( kbhit() ){ /* Take action if the user requests */
  92.       getch(); /* Clear the keyboard buffer */
  93.       wn+=wn; /*Change the natural frequency of the panel*/
  94.       if ( wn < WN_MAX) {
  95.         create_all_meter(wn); /*Paint a new meter screen*/
  96.         }
  97.       else
  98.         break;
  99.       }
  100.     }
  101. /*
  102.  * shutting down now
  103.  * attempt to restore the tube to normal
  104. */
  105. _setvideomode(_DEFAULTMODE);
  106. }
  107. /*
  108. * procedure to return a test value
  109. * this procedure accepts an integer argument which forms
  110. * the basis for the return value.
  111. * the argument has a random number in the 0 to 10 count
  112. *     range
  113. * an additional 'step' is added to the signal to form
  114. *     a square wave.
  115. * the size and period of the square wave are controlled
  116. * by a pair of #defines
  117. */
  118. int fetch( int arg)
  119. {
  120. static int step;
  121. int j;
  122.  
  123. /*
  124.  * simulate a real noisy signal
  125. */
  126. j = arg;
  127. j += rand()/6540;
  128. /*
  129.  * Now add a step function to the signal to show
  130.  * long term dynamics
  131. */
  132. if( step++ >= STEP_TIME) {
  133.   j += STEP_SIZE;
  134.   if( step++ >= STEP_TIME*2)
  135.     step = 0;
  136.   }
  137. return( j );
  138. }
  139. /*
  140.  * execute a second order filter algorithm
  141.  * Note that these four LOC represent
  142.  * the reason for this program!
  143. */
  144. int filter_meter(METER *(p), int value)
  145. {
  146. int out;
  147.  
  148. out = p->x1/ p->w2;
  149. p->x2 = value+ p->x2- p->x2/ p->aw- out;
  150. p->x1 = p->x1+ p->x2;
  151.  
  152. return(out);
  153. }
  154. /*
  155. * Display a point on the meter.
  156.  *              Apply the filtering
  157.  *    Scale the result to the physical full scale
  158.  *    Clip the number to physical limits
  159.  *              Blank out the old point
  160.  *              Paint the new line
  161.  *
  162.  *              The display range is from 0 to 100.
  163.  *      This range is normalized for the physical scale
  164. */
  165. void show_meter(METER *(p), int value)
  166. {
  167. int     v;
  168.  
  169. /*
  170.  * First perform the smoothing operation
  171. */
  172. v = filter_meter(p, value);
  173. /*
  174.  * now apply the full scale multiplier
  175. */
  176. v = (v*DISPLAY_SCALE/FULL_SCALE)+p->l;  
  177. /*
  178.  * Perform a limiting function here to
  179.  * keep the pointer inside the metering area
  180. */
  181. if ( v < p->l )
  182.     v = p->l;
  183. if ( v > p->r )
  184.     v = p->r;
  185. /*
  186.  * rub out the current pointer
  187. */
  188. _setcolor(BACK_COLOR);
  189. _pie(_GBORDER, p->l,p->b, p->r,p->t,
  190.      p->oldvalue,p->t, p->oldvalue,p->t);
  191. /*
  192.  * Now paint the new pointer
  193. */
  194. _setcolor(FORG_COLOR);
  195. _pie(_GBORDER, p->l,p->b, p->r,p->t, v,p->t, v,p->t);
  196. p->oldvalue=v;  /* remember this for contracting out later*/
  197. }
  198. /*
  199.  * procedure to Create a panel of meters
  200. */
  201. void create_all_meter(int wn)
  202. {
  203. _setcolor(BLACK_COLOR);
  204. _clearscreen(_GCLEARSCREEN);    /* blank the whole screen */
  205. /* Create the reference meter */
  206. create_meter(&M0, 100,  50, 1,  1);
  207. create_meter(&M1, 300,  50, wn, 2);
  208. create_meter(&M2, 500,  50, wn, 4);
  209.  
  210. create_meter(&M3, 100, 125, wn, 8);
  211. create_meter(&M4, 300, 125, wn, 32);
  212. create_meter(&M5, 500, 125, wn, 64);
  213.  
  214. _settextposition(22, 30);
  215. printf("OUT = X1/%2u", wn*wn);
  216. _settextposition(23, 30);
  217. printf("X2 = IN + X2 - X2/Q*%2u - OUT", wn);
  218. _settextposition(24, 30);
  219. printf("X1 = X1 + X2");
  220. _settextposition(25, 10);
  221. printf("Type a space");
  222. }
  223. /*
  224.  * procedure to create one meter
  225.  * Initialize the meter location variables
  226.  *  and paint the meter display
  227.  *      p points to a METER structure instance
  228.  * posx is the meter X axis position argument
  229.  * posy is the meter Y axis position argument
  230.  * warg = Fs/Wn sampling frequency to natural
  231.  *      frequency ratio
  232.  * aarg = Q*(Fs/Wn) = damping factor control =1/2*Q
  233. */
  234. void create_meter(METER *(p), int posx, int posy,
  235.                   int warg, int qarg )
  236. {
  237. /*
  238.  * First fill in the meter array data
  239. */
  240. p->l= posx-DISPLAY_SCALE/2;
  241. p->b =posy+30;
  242. p->r =posx+DISPLAY_SCALE/2;
  243. p->t =posy-30;
  244. p->oldvalue=p->l;
  245. p->w2 = warg*warg;
  246. p->aw = (warg*qarg)/8;
  247. if (p->aw == 0) p->aw++;  /* Force a stable filter algo */
  248. p->x1 = 0;
  249. p->x2 = 0;
  250.  
  251. _setcolor(BACK_COLOR);  /* setup the background color */
  252. /*
  253.  * now paint the meter outline
  254. */
  255. _pie(_GFILLINTERIOR,p->l,p->b,p->r,p->t,p->r,p->t,p->l,p->t);
  256. /*
  257.  * Identify the filter parameters
  258. */
  259. _settextposition(p->b/8-2, 0+p->l/8);
  260. printf("F/W    =%2u Q =%4.2f", warg, (double) qarg/8);
  261.  
  262. _settextposition(1+p->b/8-2, 0+p->l/8);
  263. printf("(F/W)^2=%2u Q*F/W=%2u", p->w2, p->aw);
  264. /*
  265.  *       Paint the zero pointer
  266. */
  267. show_meter( p,0);
  268. }
  269.  
  270.