home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Homebrewer's Handbook / vr.iso / vr386 / timer.c < prev    next >
C/C++ Source or Header  |  1996-03-19  |  6KB  |  207 lines

  1. /* Timer routines for REND386; written by Dave Stampe, July 1992 */
  2.  
  3. /* Completely rewritten 19/12/93, to use JOYTIMER.ASM and new, more
  4.    robust control interface, and millisecond timing           */
  5.  
  6. /*
  7.  This code is part of the VR-386 project, created by Dave Stampe.
  8.  VR-386 is a desendent of REND386, created by Dave Stampe and
  9.  Bernie Roehl.  Almost all the code has been rewritten by Dave
  10.  Stampre for VR-386.
  11.  
  12.  Copyright (c) 1994 by Dave Stampe:
  13.  May be freely used to write software for release into the public domain
  14.  or for educational use; all commercial endeavours MUST contact Dave Stampe
  15.  (dstampe@psych.toronto.edu) for permission to incorporate any part of
  16.  this software or source code into their products!  Usually there is no
  17.  charge for under 50-100 items for low-cost or shareware products, and terms
  18.  are reasonable.  Any royalties are used for development, so equipment is
  19.  often acceptable payment.
  20.  
  21.  ATTRIBUTION:  If you use any part of this source code or the libraries
  22.  in your projects, you must give attribution to VR-386 and Dave Stampe,
  23.  and any other authors in your documentation, source code, and at startup
  24.  of your program.  Let's keep the freeware ball rolling!
  25.  
  26.  DEVELOPMENT: VR-386 is a effort to develop the process started by
  27.  REND386, improving programmer access by rewriting the code and supplying
  28.  a standard API.  If you write improvements, add new functions rather
  29.  than rewriting current functions.  This will make it possible to
  30.  include you improved code in the next API release.  YOU can help advance
  31.  VR-386.  Comments on the API are welcome.
  32.  
  33.  CONTACT: dstampe@psych.toronto.edu
  34. */
  35.  
  36.  
  37. #include <dos.h>
  38. #include <bios.h>
  39. #include <stdio.h>
  40. #include <conio.h>
  41. #include <stdlib.h>
  42. #include <signal.h>
  43.  
  44. #include "pcdevice.h"
  45. #include "devpriv.h"
  46.  
  47. /******************* TIMER INTERRUPT STUFF ****************/
  48. #define SYNC_INTERVAL 5
  49.  
  50. int get_ticks_per_second(void)
  51. {
  52.  return 1000;  // always in msec now, so this is not too useful
  53. }
  54.  
  55. void tdelay(long d)     // delay in msec: current_time() always in msec now
  56. {
  57.  long dl = current_time() + d;
  58.  
  59.  while(current_time()<=dl);
  60. }
  61.  
  62. static long last_render_duration = 200;
  63. static long render_start_time = 0;
  64.  
  65.     // call before rendering begins
  66. void register_render_start()
  67. {
  68.  render_start_time = current_time();
  69. }
  70.  
  71.     // call after rendering ends
  72. void register_render_end()
  73. {
  74.  last_render_duration = current_time() - render_start_time;
  75.  if (last_render_duration < 2) last_render_duration = 2;
  76. }
  77.  
  78.     // returns time of last render in milliseconds
  79. long last_render_time()
  80. {
  81.  return last_render_duration;
  82. }
  83.  
  84.  
  85.  
  86. /************* INTERRUPT SETUP?RESET **************/
  87.  
  88. #define TIMER_VECT 8        /* timer chip int. vector */
  89. #define KBRD_VECT  9        /* keyboard intercept     */
  90.  
  91. // this is the most portable (PM or DOS) method to chain with
  92. #define UNUSED_TVECTOR 0x78    /* for timer chain        */
  93. #define UNUSED_KVECTOR 0x79    /* for keyboard chain     */
  94.  
  95.  
  96. void (__interrupt __far *old_kbrd_hook) () = NULL; //DOS keyboard interrupt handler
  97.  
  98. void (__interrupt __far *old_timer_hook)() = NULL; //DOS 18.2 Hz interrupt handler
  99.  
  100.  
  101. static void _reset_timer()   /* RESET PC TO NORMAL */
  102. {
  103.   _disable();
  104.  
  105.   if(old_timer_hook)
  106.       setvect(TIMER_VECT, old_timer_hook); /* reset vector */
  107.   old_timer_hook = NULL;
  108.  
  109.   if(old_kbrd_hook)
  110.       setvect(KBRD_VECT, old_kbrd_hook);   /* reset vector */
  111.   old_kbrd_hook = NULL;
  112.  
  113.   write_timer(0);
  114.   _enable();
  115.  
  116.   signal(SIGINT, SIG_DFL);
  117.   signal(SIGABRT, SIG_DFL);
  118.   signal(SIGFPE, SIG_DFL);
  119. }
  120.  
  121.  
  122. static void _init_timer(int speed) /* SET UP FAST TIMER */
  123. {
  124.   atexit(_reset_timer); /* set traps for error, ctrl c, */
  125.   signal(SIGABRT, _reset_timer);
  126.   signal(SIGFPE, _reset_timer);
  127.   signal(SIGINT, _reset_timer);
  128.  
  129.   write_timer(speed);
  130.   counts_per_tick = speed;
  131.   timer_tick_count = 0;
  132.   ticks_per_second = 1190000L/speed;
  133.   frame_resync_interval = SYNC_INTERVAL;
  134.  
  135.       /* setup int's if required(first run) */
  136.   if (old_timer_hook==NULL)
  137.     {
  138.       _disable();
  139.       old_timer_hook = getvect(TIMER_VECT); /* setup ISR vectors */
  140.       setvect(UNUSED_TVECTOR, old_timer_hook);
  141.       setvect(TIMER_VECT, timer_isr);
  142.       _enable();
  143.     }
  144. }
  145.  
  146. int keymon_on = 0;
  147.  
  148. int init_key_monitor()
  149. {
  150.   if (old_kbrd_hook==NULL)
  151.     {
  152.       _disable();
  153.       old_kbrd_hook = getvect(KBRD_VECT); /* setup ISR vectors */
  154.       setvect(UNUSED_KVECTOR,old_kbrd_hook);
  155.       setvect(KBRD_VECT, kbrd_isr);
  156.       _enable();
  157.       keymon_on++;
  158.       return 1;
  159.     }
  160.  return 0;
  161. }
  162.  
  163.  
  164. /************** SETUP EXTERNALLY *************/
  165.  
  166. static unsigned timer_rate = 6000;  // default time goal for POWERGLOVE
  167. static unsigned frame_setup = 0;    // can't set timer if frame lock
  168.  
  169. int init_timer(unsigned speed, void (*timer_hook)())
  170. {
  171.  if(timer_hook)
  172.    timer_interrupt_hook = timer_hook;       // timer tick interrupt handler
  173.  if(frame_setup) return counts_per_tick;  // can't set if frame locked!
  174.  if(speed) timer_rate = speed;
  175.  
  176.  _init_timer(timer_rate);
  177.  return counts_per_tick;
  178. }
  179.  
  180.  
  181. #define ADVANCE 100             /* time (microseconds) of advance   */
  182.                 /* in vert. interrupt.  Will act as */
  183.                 /* "vertical hold" adjustment       */
  184.  
  185.  
  186. int init_frame_lock(unsigned speed, void (*frame_hook)())
  187. {
  188.   unsigned i_rate;
  189.   unsigned tpf;
  190.  
  191.   frame_interrupt_hook = frame_hook;    // frame-end interrupt handler
  192.   if(speed) timer_rate = speed;        // suggested speed
  193.   frame_setup++;            // lock time base
  194.  
  195.   i_rate = find_vsync_count() - ADVANCE; /* use a multiple of video rate   */
  196.   tpf = i_rate/timer_rate;          /* about 2x for 72 fps, 3x for 60 */
  197.   if (tpf < 2) tpf = 2;             /* need at leas twice for switch */
  198.   if (tpf > 10) tpf = 10;          /* come on now...           */
  199.   i_rate /= tpf;
  200.   timer_frame_interval = tpf;
  201.  
  202.   _init_timer(i_rate);
  203.   return counts_per_tick;
  204. }
  205.  
  206.  
  207.