home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / timer / mschrt3 / watch.c < prev   
Encoding:
C/C++ Source or Header  |  1990-07-24  |  20.9 KB  |  498 lines

  1. /*---------------------------------------------------------------------------
  2.  |  Program WATCH                                                           |
  3.  |                                                                          |
  4.  |  This program creates a stopwatch on the display with "Taylor" split     |
  5.  |  capability.                                                             |
  6.  |                                                                          |
  7.  |  This program uses two timers to keep track of total and lap times.      |
  8.  |  This method can result in a least significant digit "jitter" of .01 sec |
  9.  |  on the lap timer.  A better, but more complex method is to use a single |
  10.  |  timer to keep track of both.  The dual timer method makes for better    |
  11.  |  demo code and was chosen for that reason only.                          |
  12.  |                                                                          |
  13.  |  NOTE: Compile with stack checking disabled.                             |
  14.  |                                                                          |
  15.  |  (c)1989 Ryle Design, P.O. Box 22, Mt. Pleasant, Michigan 48804          |
  16.  |                                                                          |
  17.  |  V3.00  Microsoft C Shareware Evaluation Version                         |
  18.  ---------------------------------------------------------------------------*/
  19.  
  20. #include <stdio.h>
  21. #include <conio.h>
  22. #include <dos.h>
  23.  
  24. #include "pchrt.h"
  25.  
  26. #ifndef TRUE
  27.     #define TRUE    1
  28.     #define FALSE   0
  29. #endif
  30.  
  31. #define TIMEROFF    0
  32. #define TIMERON     1
  33. #define LAPSTOP     0
  34. #define LAPRUN      1
  35. #define F1          59
  36. #define F2          60
  37. #define KEYPORT     0x60
  38.  
  39. #define MSMINS      60000000L;
  40. #define MSSECS      1000000L;
  41. #define MSHUNDS     10000L;
  42.  
  43. char            tstring[9] = {"00:00.00"};
  44. char            lstring[9] = {"00:00.00"};
  45.  
  46. int             tstate = TIMEROFF;
  47. int             lstate = LAPSTOP;
  48. int             laps;
  49. unsigned long   ltime = 0;
  50. unsigned long   ttime = 0;
  51.  
  52. pchrt_type      dtime[2];
  53.  
  54. void (interrupt far *old_keybd_int)(void);
  55. void interrupt far new_keybd_int(void);
  56.  
  57. #define inportb     inp
  58. #define getvect     _dos_getvect
  59. #define setvect     _dos_setvect
  60.  
  61.  
  62. void gotoxy(char x, char y)
  63. /*--------------------------------------------------------------------------
  64.  |  This function moves the video cursor to a location on the display using|
  65.  |  BIOS interrupt 10h.  Video page 0 is assumed.  No range checking is    |
  66.  |  implemented.                                                           |
  67.  |                                                                         |
  68.  |  Globals referenced: none                                               |
  69.  |                                                                         |
  70.  |  Arguments: (char) x - X column position (1-80)                         |
  71.  |             (char) y - Y row position (1-25)                            |
  72.  |                                                                         |
  73.  |  Returns  : void                                                        |
  74.  --------------------------------------------------------------------------*/
  75. {
  76.     union REGS regs;
  77.  
  78.     regs.h.ah = 0x02;                       /* set cursor function request */
  79.     regs.h.bh = 0;                          /* assume video page 0 */
  80.     regs.h.dl = (x - 1);                    /* apply column offset */
  81.     regs.h.dh = (y - 1);                    /* apply row offset    */
  82.  
  83.     int86(0x10,®s,®s);                /* call BIOS video services */
  84.  
  85. } /* gotoxy */
  86.  
  87.  
  88. void clrscr(void)
  89. /*--------------------------------------------------------------------------
  90.  |  This function clears the video display using BIOS interrupt 10h.  The  |
  91.  |  text display is blanked and the cursor is set to (1,1).                |
  92.  |  A 25 line display and video page 0 is assumed.  The display attribute  |
  93.  |  is assumed to be 0x07 (light grey on black)                            |
  94.  |                                                                         |
  95.  |  Globals referenced: none                                               |
  96.  |                                                                         |
  97.  |  Arguments: void                                                        |
  98.  |                                                                         |
  99.  |  Returns  : void                                                        |
  100.  --------------------------------------------------------------------------*/
  101. {
  102.     union REGS regs;
  103.  
  104.     regs.h.ah = 0x06;                       /* init/scroll function request */
  105.     regs.h.al = 0;                          /* blank window                 */
  106.     regs.h.bh = 0x07;                       /* background attribute         */
  107.     regs.h.ch = 0;                          /* window starts at 0,0         */
  108.     regs.h.cl = 0;
  109.     regs.h.dh = 24;                         /* goes to 79,24                */
  110.     regs.h.dl = 79;
  111.  
  112.     int86(0x10,®s,®s);                /* call BIOS video services     */
  113.  
  114.     gotoxy(1,1);                            /* home cursor                  */
  115.  
  116. } /* clrscr */
  117.  
  118.  
  119. int hide_cursor(void)
  120. /*--------------------------------------------------------------------------
  121.  |  This function disables the cursor.                                     |
  122.  |                                                                         |
  123.  |  Globals referenced: none                                               |
  124.  |                                                                         |
  125.  |  Arguments : void                                                       |
  126.  |                                                                         |
  127.  |  Returns   : (int) cursor shape for later restoration                   |
  128.  --------------------------------------------------------------------------*/
  129. {
  130.     union REGS  regs;
  131.     int         cursortype;
  132.  
  133.     regs.h.ah = 15;                                         /* get current video page */
  134.     int86(0x10,®s,®s);
  135.  
  136.     regs.h.ah = 3;                                          /* request cursor shape */
  137.     int86(0x10,®s,®s);                                /* regs.bh has video page from last int86() call */
  138.  
  139.     cursortype = regs.h.cl + ( (int) regs.h.ch << 8);       /* store cursor start & stop rasters */
  140.  
  141.     regs.h.ah = 1;                                          /* set cursor shape */
  142.     regs.h.ch = 32;                                         /* set bit 5 - turns cursor off */
  143.     int86(0x10,®s,®s);                                /* and disable cursor */
  144.  
  145.     return(cursortype);
  146.  
  147. } /* hide_cursor */
  148.  
  149.  
  150.  
  151. void set_cursor(int cursortype)
  152. /*---------------------------------------------------------------------------
  153.  |  This function sets the cursor to a new shape.                           |
  154.  |                                                                          |
  155.  |  Globals referenced: none                                                |
  156.  |                                                                          |
  157.  |  Arguments : (int) cursortype - high 8 bits is start raster              |
  158.  |                                 low 8 bits is stop raster                |
  159.  |  Returns   : void                                                        |
  160.  ---------------------------------------------------------------------------*/
  161. {
  162.     union REGS  regs;
  163.  
  164.     regs.h.ah = 1;                                          /* set cursor shape */
  165.     regs.h.ch = (cursortype & 0xFF00) >> 8;                 /* cursor start raster */
  166.     regs.h.cl = (cursortype & 0x00FF);                      /* cursor stop raster */
  167.     int86(0x10,®s,®s);                                /* call BIOS interupt 10h */
  168.  
  169. } /* set_cursor */
  170.  
  171.  
  172.  
  173. void restore_old_keybd_int(void)
  174. /*---------------------------------------------------------------------------
  175.  |  This function restores the original keyboard interrupt and must be      |
  176.  |  called prior to program completion.                                     |
  177.  |                                                                          |
  178.  |  Globals referenced: old_keybd_int                                       |
  179.  |                                                                          |
  180.  |  Arguments: void                                                         |
  181.  |                                                                          |
  182.  |  Returns  : void                                                         |
  183.  ---------------------------------------------------------------------------*/
  184. {
  185.     setvect(9,old_keybd_int);                       /* restore old ISR vector */
  186.  
  187. } /* restore_old_keybd_int */
  188.  
  189.  
  190.  
  191. void install_new_keybd_int(void)
  192. /*---------------------------------------------------------------------------
  193.  |  This function saves the original keyboard interrupt vector and installs |
  194.  |  the address of our user written interrupt handler in the ISR vector     |
  195.  |  table.                                                                  |
  196.  |                                                                          |
  197.  |  Globals referenced: old_keybd_int                                       |
  198.  |                      new_keybd_int                                       |
  199.  |                                                                          |
  200.  |  Arguments: void                                                         |
  201.  |                                                                          |
  202.  |  Returns  : void                                                         |
  203.  ---------------------------------------------------------------------------*/
  204. {
  205.     old_keybd_int = getvect(9);                     /* save old ISR vector    */
  206.     setvect(9,new_keybd_int);                       /* install new ISR vector */
  207.  
  208. } /* install_new_keybd_int */
  209.  
  210.  
  211.  
  212. void interrupt far new_keybd_int(void)
  213. /*---------------------------------------------------------------------------
  214.  |  This function is our new interrupt service routine for interrupt 9h.    |
  215.  |  The following occurs:                                                   |
  216.  |      1. The keyboard hardware port is read to see what key was pressed.  |
  217.  |      2. If F1 or F2 were pressed, the watch state is checked and         |
  218.  |         appropriate action is taken.                                     |
  219.  |      3. The old keyboard interrupt is called.                            |
  220.  |                                                                          |
  221.  |  Since this function is invoked by a hardware interrupt, it functions    |
  222.  |  asynchronously to the main program execution and provides extremely     |
  223.  |  high timing accuracy.                                                   |
  224.  |                                                                          |
  225.  |  Globals referenced: tstate                                              |
  226.  |                      lstate                                              |
  227.  |                      ltime                                               |
  228.  |                      ttime                                               |
  229.  |                      laps                                                |
  230.  |                      old_keybd_int                                       |
  231.  |                                                                          |
  232.  |  Arguments: void                                                         |
  233.  |                                                                          |
  234.  |  Returns  : void                                                         |
  235.  ---------------------------------------------------------------------------*/
  236. {
  237.     char unsigned   scan_code;
  238.     unsigned long   hits;
  239.  
  240.     scan_code = inportb(KEYPORT);                   /* read keyboard */
  241.     if (scan_code == F1)                            /* check for F1 key */
  242.     {
  243.         if (tstate == TIMEROFF)                     /* if the watch is off ... */
  244.         {
  245.             t_entry(0);                             /* start main timer */
  246.             t_entry(1);                             /* start lap timer  */
  247.             tstate = TIMERON;                       /* set state flags  */
  248.             lstate = LAPRUN;
  249.         }
  250.         else                                        /* the watch was on ... */
  251.         {
  252.             t_exit(0);                              /* stop main timer */
  253.             t_exit(1);                              /* stop lap timer  */
  254.             tstate = TIMEROFF;                      /* set flags       */
  255.             lstate = LAPSTOP;
  256.         }
  257.     }
  258.     else if (scan_code == F2)                       /* check for F2 key */
  259.     {
  260.         if (tstate == TIMEROFF)                     /* if watch was off */
  261.         {
  262.             t_reset(0);                             /* master reset     */
  263.             t_reset(1);
  264.             ttime = 0;
  265.             ltime = 0;
  266.             laps = 0;
  267.         }
  268.         else                                        /* if watch was running */
  269.         {
  270.             if (lstate == LAPRUN)                   /* end of lap if lap was running */
  271.             {
  272.                 t_exit(1);
  273.                 t_ask_timer(1,&hits,<ime);
  274.                 t_reset(1);
  275.                 t_entry(1);
  276.                 lstate = LAPSTOP;
  277.                 laps++;
  278.             }
  279.             else                                        /* current lap continues if lap was off */
  280.             {
  281.                 lstate = LAPRUN;
  282.             }
  283.         }
  284.     }
  285.  
  286.     (*old_keybd_int)();                             /* call the old keyboard ISR */
  287.  
  288. } /* new_keybd_int */
  289.  
  290.  
  291. void make_time_string(unsigned long tval, char *tstring)
  292. /*---------------------------------------------------------------------------
  293.  |  This function converts a quantity of microseconds into a displayable    |
  294.  |  string in the form MM:SS.HH .                                           |
  295.  |                                                                          |
  296.  |  Globals referenced: none                                                |
  297.  |                                                                          |
  298.  |  Arguments: (unsigned long) tval - time in microseconds to convert       |
  299.  |             (char *) tstring[] - string to receive time conversion       |
  300.  |                                                                          |
  301.  |  Returns  : void                                                         |
  302.  ---------------------------------------------------------------------------*/
  303. {
  304.     int     mins, secs, hunds;
  305.  
  306.     mins = tval / MSMINS;
  307.     tval -= (long) mins * MSMINS;
  308.  
  309.     secs = tval / MSSECS;
  310.     tval -= (long) secs * MSSECS;
  311.  
  312.     hunds = tval / MSHUNDS;
  313.  
  314.     sprintf(tstring,"%.2d:%.2d.%.2d",mins,secs,hunds);
  315.  
  316. } /* make_time_string */
  317.  
  318.  
  319.  
  320. void draw_watch(void)
  321. /*---------------------------------------------------------------------------
  322.  |  This function draws the stopwatch on the display.                       |
  323.  |                                                                          |
  324.  |  Globals referenced: none                                                |
  325.  |                                                                          |
  326.  |  Arguments: void                                                         |
  327.  |                                                                          |
  328.  |  Returns  : void                                                         |
  329.  ---------------------------------------------------------------------------*/
  330. {
  331.     int     indx;
  332.  
  333.     gotoxy(33,9);   putch(218);                     /* draw the corners */
  334.     gotoxy(46,9);   putch(191);
  335.     gotoxy(33,15);  putch(192);
  336.     gotoxy(46,15);  putch(217);
  337.  
  338.     for (indx=34; indx<46; indx++)                  /* draw horizontal lines */
  339.     {
  340.         gotoxy(indx,9);   putch(196);
  341.         gotoxy(indx,15);  putch(196);
  342.         gotoxy(indx,12);  putch(196);
  343.     }
  344.  
  345.     for(indx=10; indx<15; indx++)                   /* draw vertical lines */
  346.     {
  347.         gotoxy(33,indx);  putch(179);
  348.         gotoxy(46,indx);  putch(179);
  349.     }
  350.  
  351.     gotoxy(33,12); putch(195);                      /* draw vert/horiz intersections */
  352.     gotoxy(46,12); putch(180);
  353.  
  354.     gotoxy(35,10); printf("Total Time");
  355.     gotoxy(37,13); printf("Lap 00");
  356.  
  357. } /* draw_watch */
  358.  
  359.  
  360.  
  361. void show_total_time(unsigned long ttime)
  362. /*---------------------------------------------------------------------------
  363.  |  This function displays the total time accumulated by the watch in the   |
  364.  |  appropriate area of the watch face.                                     |
  365.  |                                                                          |
  366.  |  Globals referenced: none                                                |
  367.  |                                                                          |
  368.  |  Arguments: (unsigned long) ttime - time to display                      |
  369.  |                                                                          |
  370.  |  Returns  : void                                                         |
  371.  ---------------------------------------------------------------------------*/
  372. {
  373.     char    tstring[9];
  374.  
  375.     make_time_string(ttime,tstring);    /* convert microseconds to MM:SS.HH */
  376.  
  377.     gotoxy(36,11);
  378.     printf("%s",tstring);
  379.  
  380. } /* show_total_time */
  381.  
  382.  
  383.  
  384. void show_lap_time(unsigned long ltime)
  385. /*---------------------------------------------------------------------------
  386.  |  This function displays the current lap time accumulated by the watch in |
  387.  |  the appropriate area of the watch face.                                 |
  388.  |                                                                          |
  389.  |  Globals referenced: none                                                |
  390.  |                                                                          |
  391.  |  Arguments: (unsigned long) ltime - time to display                      |
  392.  |                                                                          |
  393.  |  Returns  : void                                                         |
  394.  ---------------------------------------------------------------------------*/
  395. {
  396.     char    tstring[9];
  397.  
  398.     make_time_string(ltime,tstring);    /* convert microseconds to MM:SS.HH */
  399.     
  400.     gotoxy(36,14);
  401.     printf("%s",tstring);
  402.  
  403. } /* show_lap_time */
  404.  
  405.  
  406.  
  407. void show_lap(int lap)
  408. /*---------------------------------------------------------------------------
  409.  |  This function displays the current lap the watch is timing in the       |
  410.  |  appropriate area of the watch face.                                     |
  411.  |                                                                          |
  412.  |  Globals referenced: none                                                |
  413.  |                                                                          |
  414.  |  Arguments: (int) lap - lap to display                                   |
  415.  |                                                                          |
  416.  |  Returns: void                                                           |
  417.  ---------------------------------------------------------------------------*/
  418. {
  419.     if (lap == 100) lap = 0;            /* roll over after 99 laps */
  420.  
  421.     gotoxy(41,13);
  422.     printf("%2.2d",lap);
  423.  
  424. } /* show_lap */
  425.  
  426.  
  427. void main(void)
  428. {
  429.     int             atom, cursor;
  430.     unsigned long   hits;
  431.  
  432.     t_start();
  433.  
  434.     /* first set up the display */
  435.  
  436.     clrscr();
  437.     cursor = hide_cursor();
  438.  
  439.     gotoxy(25,6); printf("MSCHRT V3 Demonstration Series");
  440.     gotoxy(35,7); printf("StopWatch");
  441.  
  442.     draw_watch();
  443.  
  444.     gotoxy(14,17); printf("F1 Starts/Stops Watch          F2 Lap Splits/Resets Watch");
  445.     gotoxy(35,19); printf("<ESC> quits");
  446.  
  447.     show_total_time(ttime);
  448.     show_lap_time(ltime);
  449.     show_lap(laps);
  450.  
  451.     install_new_keybd_int();
  452.  
  453.     /* watch display update loop */
  454.     
  455.     do
  456.     {
  457.         if (tstate == TIMEROFF)
  458.         {
  459.             t_ask_timer(0,&hits,&ttime);
  460.             t_ask_timer(1,&hits,<ime);
  461.             show_total_time(ttime);
  462.             show_lap_time(ltime);
  463.             show_lap(laps);
  464.         }
  465.         else
  466.         {
  467.             t_get(&dtime[0]);
  468.             ttime = t_diff(&(tdata->tstart),&dtime[0]) + tdata->elapsed;
  469.             show_total_time(ttime);
  470.             if (lstate == LAPRUN)
  471.             {
  472.                 t_get(&dtime[1]);
  473.                 ltime = t_diff(&((tdata+1)->tstart),&dtime[1]) + (tdata+1)->elapsed;
  474.                 show_lap_time(ltime);
  475.             }
  476.             else
  477.             {
  478.                 show_lap_time(ltime);
  479.                 show_lap(laps);
  480.             }
  481.         }
  482.  
  483.         if (kbhit()) atom = getch();
  484.     }
  485.     while (atom != 27);
  486.  
  487.     /* if user presses <ESC>, we fall through to here.  Clean up and exit */
  488.  
  489.     restore_old_keybd_int();
  490.  
  491.     t_stop();
  492.  
  493.     set_cursor(cursor);
  494.     gotoxy(1,24);
  495.     printf("StopWatch complete.");
  496.  
  497. } /* main */
  498.