⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timer.c

📁 计算时间间隔的程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************\
**  TIMING CODE MODULE (80x86 specific code!)                              **
**=========================================================================**
**  Written by Ethan Rohrer, (c) Nuthing Software, December 4, 1994        **
**                                                                         **
**  Revision History                                                       **
**  ----------------                                                       **
**  Date        Description                                                **
**  ---------   ---------------------------------------------------------  **
**  13 May 94   Initial Release                                            **
**  04 Dec 94   Updated code to conform to current coding standards/style  **
**              Allowed appl. to specify # of timers as param. to TM_Init  **
**              Standardized error handling with function _TM_Error        **
**=========================================================================**
**  This file contains code which makes use of system timer 0.  This timer **
**  normally operates at a frequency of 1.1932MHz, regardless of the speed **
**  of the CPU.  Normally, this timer is operating in mode 3 (square wave  **
**  mode), and it completes a "cycle" in 0.054926 seconds (~1/18.207       **
**  seconds).  The reason I say "normally" is because it is possible to    **
**  change the length of the cycle, which changes the timer's frequency.   **
**  This is NOT what the following code does.                              **
**                                                                         **
**  System timer 0 has its own 16 bit counter.  Here is some simplified    **
**  pseudo-code of what system timer 0 does with its counter when it is    **
**  operating in mode 3, and its frequency has not been tampered with:     **
**                                                                         **
**      counter = 65536                                                    **
**      while (counter != 0)                                               **
**          counter -= 2;                                                  **
**      counter = 65536                                                    **
**      while (counter != 0)                                               **
**          counter -= 2;                                                  **
**                                                                         **
**  You read that right.  The counter is decremented from 65536 to 0       **
**  TWICE.  This is somewhat unfortunate, because we want to read that     **
**  counter to use for our timing operations because it is very accurate.  **
**  The counter is decremented 65536 times in one timer cycle (32768       **
**  times in each while loop above).  So, the time between decrements is:  **
**                                                                         **
**      (0.054926 seconds/cycle) / (65536 decrements/cycle) =              **
**                      0.000000838 seconds/decrement = 838ns/decrement    **
**                                                                         **
**  Since the counter is decremented to 0 twice in each timer cycle, we    **
**  would only be able to time events that take no longer than 0.027463    **
**  seconds (one half of the timer cycle, the duration of one of the       **
**  while loops above).                                                    **
**                                                                         **
**  The solution used by the code in this file is to change the timer's    **
**  operation mode to mode 2.  Here is some simplified pseudo-code of what **
**  system timer 0 does with its counter when it is operating in mode 2,   **
**  and its frequency has not been tampered with:                          **
**                                                                         **
**      counter = 65536                                                    **
**      while (counter != 0)                                               **
**          counter -= 1;                                                  **
**                                                                         **
**  This solves any problems concerning the ambiguity of determining       **
**  which while loop is executing when we read the counter from the timer. **
**  But now, we have a 16 bit value which can only be used to time events  **
**  which take no longer than 0.054926 seconds (duration of one cycle).    **
**                                                                         **
**  The solution used by this code is to make use of another timer:        **
**  the "large timer", which is a 32-bit value at memory location          **
**  0x40:0x6C.  Conveniently, this "large timer" is incremented each time  **
**  system timer 0 completes a cycle (once each 0.054926 seconds).         **
**  The code in this file generates 32-bit values to represent the         **
**  time.  Obviously, we can't pack in the 16 bit counter and the 32 bit   **
**  large timer into the 32 bit time type, so we cut off the high order    **
**  16 bits of the large timer.  The following picture describes how the   **
**  time value is generated using the timers:                              **
**                                                                         **
**    31                                        0 15                   0   **
**    ------------------------------------------- ----------------------   **
**    |         L a r g e   T i m e r           | |  65535 - Counter   |   **
**    ------------------------------------------- ----------------------   **
**                         |                     |                     |   **
**                        \|/                   \|/                   \|/  **
**                         V                     V                     V   **
**                         31                  16 15                   0   **
**                         ---------------------- ----------------------   **
**                         |                 t T I M E                 |   **
**                         ---------------------- ----------------------   **
**                                                                         **
**  (Note that we have to use (65535-Counter) because Counter is being     **
**  decremented by the timer, but time is increasing)                      **
**                                                                         **
**=========================================================================**
**  USING THIS MODULE                                                      **
**      Before calling any other timing routine, you must call TM_Init(n), **
**      where  n  specifies the number of timers your application needs.   **
**      It may be a good idea to call TM_Init() in the initialization      **
**      portion of your application.                                       **
**                                                                         **
**      To begin timing an event, make a call to TM_StartTimer(tid),       **
**      where tid is an integer in the range [0..(n-1)] which specifies    **
**      which of the n timers you are starting.                            **
**                                                                         **
**      To compute the duration of the event, just call                    **
**      TM_ElapsedTime(tid), where tid is the same integer used in the     **
**      call to TM_StartTimer().                                           **
**                                                                         **
**      When you are finished with the timing routines, call TM_Close().   **
**      This should fit in nicely with the cleanup section of your         **
**      application.                                                       **
**                                                                         **
**      If your application NEEDS to handle the time computations itself,  **
**      the function TM_ReadTimer(tid) is also available.  This function   **
**      will return the current time (MOD 1 hour, approximately).  I       **
**      discourage use of this function, but discovered that I need it     **
**      for another module/library...                                      **
**                                                                         **
**      EXAMPLES                                                           **
**          A simple delaying routine:                                     **
**              void delay( tTIME duration )                               **
**              {                                                          **
**                  TM_StartTimer(0);                                      **
**                  while (TM_ElapsedTime(0) < duration)                   **
**                      ;                                                  **
**              }                                                          **
**                                                                         **
**          A fixed frame-rate game:                                       **
**              TM_Init(1);                                                **
**              while (player_not_dead)                                    **
**              {                                                          **
**                  TM_StartTimer(0);                                      **
**                  MoveMonsters();                                        **
**                  MovePlayers();                                         **
**                  UpdateDisplay();                                       **
**                  while (TM_ElapsedTime(0) < frame_duration)             **
**                      ;                                                  **
**              }                                                          **
**              TM_Close();                                                **
\***************************************************************************/

#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include "timer.h"

/*-------------------------------- MACROS ---------------------------------*/

/* macro to return the current value of the large timer */

#define  TM_LARGE_TIMER   (*((unsigned long far *)MK_FP(0x40, 0x6C)))

/*--------------------------- GLOBAL VARIABLES ----------------------------*/

/* starting times for all of the timers this code will support */

tTIME  *gpTM_start_time = NULL;

unsigned int gTM_max_timers = 0;

/* flag to let us know if it is ok to run the timing routines */
/*     (1 = NOT safe, 0 = safe)                               */

unsigned char  gTM_module_not_initialized = 1;

/*------------------------- Error Message Strings -------------------------*/

#define TM_ERR_STR_GENERAL                                                 \
	"General (unspecified) error."
#define TM_ERR_STR_UNINITIALIZED                                           \
	"Timing routines not yet initialized.\n"                           \
	"(TM_Init() has not been called)"
#define TM_ERR_STR_BAD_TIMER_ID                                            \
	"Application specified an invalid timer ID."
#define TM_ERR_STR_ALLOC                                                   \
	"Unable to allocate dynamic memory."
#define TM_ERR_STR_ZERO_TIMERS                                             \
	"Application requested 0 timers.\n"                                \
	"(must request 1 or more timers to use this module)"

/*------------------------- Error Message Indices -------------------------*/
/* (Make sure these indices are accurate according to gpTM_error_text[]     */
/* declared below !!)                                                      */

#define TM_ERR_GENERAL           0
#define TM_ERR_UNINITIALIZED     1
#define TM_ERR_BAD_TIMER_ID      2
#define TM_ERR_ALLOC             3
#define TM_ERR_ZERO_TIMERS       4

/*------------------------- Error Message Strings -------------------------*/
/* (Make sure the positions of the error messages in this array are        */
/* accurately represented by the error messages indices listed above !!)   */

char *gpTM_error_text[] =
{
    TM_ERR_STR_GENERAL,
    TM_ERR_STR_UNINITIALIZED,
    TM_ERR_STR_BAD_TIMER_ID,
    TM_ERR_STR_ALLOC,
    TM_ERR_STR_ZERO_TIMERS
};

/***************************************************************************\
**  void _TM_Error( )                                                      **
*****************************************************************************
**  ARGUMENTS                                                              **
**      const char *pCalling_function_name                                 **
**          (I) name of the calling function                               **
**      int error_number                                                   **
**          (I) integer identifier of the error that occurred              **
**      const char *pCustom_message                                        **
**          (I) additional message text to be displayed                    **
**-------------------------------------------------------------------------**
**  RETURNS                                                                **
**      void                                                               **
**-------------------------------------------------------------------------**
**  EXAMPLE USAGE (NOT INTENDED FOR EXTERNAL USE)                          **
**      if ( gTM_module_not_initialized )                                  **
**      {                                                                  **
**          _TM_Error ( pFunction_name, TM_ERR_UNINITIALIZED, NULL ); <-<< **
**          return;                                                        **
**      }                                                                  **
**-------------------------------------------------------------------------**
**  DETECTABLE ERROR CONDITIONS                                            **
**      None                                                               **
**-------------------------------------------------------------------------**
**  DESCRIPTION                                                            **
**      This function will generate a message which will be sent to stderr **
**      to inform the user of an error.  This message will include the     **
**      name of the function the error occurred in (if supplied), a canned **
**      error string for the error indicated, and a custom string (if      **
**      supplied) which may provide more details about th error.           **
**-------------------------------------------------------------------------**
**  LIMITATIONS                                                            **
**      The message text must not exceed 1024 bytes in size, which can     **
**      store over 12 80-character lines of text.                          **
\***************************************************************************/

void _TM_Error ( pCalling_function_name, error_number, pCustom_message )
    const char  *pCalling_function_name;
    int          error_number;
    const char  *pCustom_message;
{
    char error_message[1024];          /* buffer for message text */

    /*---------------------------------------------------------------------*\
    **  Insert the "ERROR IN MODULE "TIMER"" header string into our        **
    **  message.                                                           **
    \*---------------------------------------------------------------------*/

    sprintf ( error_message, 
	      "\n******** ERROR IN MODULE \"TIMER\" *********\n" );

    /*---------------------------------------------------------------------*\

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -