home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / NUTUG11.ZIP / DATETIME.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1987-11-21  |  13.4 KB  |  432 lines

  1. Unit DateTime;
  2.              {NORTHWESTERN UNIVERSITY TURBO USERS GROUP UTILITIES}
  3.  
  4.                             (** FILE DATETIME.PAS **)
  5.  
  6.  
  7.           {This is a set of routines for (1) Getting and Setting the
  8.           DOS system time and date. (2) Event timing.               }
  9.  
  10.           {/These routines provide a good illustration of the use of
  11.           DOS function calls.                                      /}
  12.  
  13. Interface
  14.  
  15. Uses      Dos,
  16.           Crt,
  17.           BASECON;
  18.                  {The InBCD function in this file is required by
  19.                  three of the following routines.               }
  20.  
  21.  
  22.  
  23. PROCEDURE GetDosDate (VAR M, DofM, Y, DofW : integer);
  24.          {Gets date with MS-DOS call.                                       }
  25.  
  26. PROCEDURE GetDosTime (VAR Hour, Min, Sec, CSec : integer);
  27.          {Gets the time with MS-DOS interrupt call.}
  28.  
  29. FUNCTION SetDosDate (Month, Day, Year : integer) : Boolean;
  30.          {Sets the DOS date according to the input: Year (1980 - 2099)
  31.          Month (1 - 12) and Day (1 - 31). Returns false if any of the
  32.          inputs are out of range.                                    }
  33.  
  34. FUNCTION SetDosTime (Hour24, Min, Sec : integer) : Boolean;
  35.          {Uses DOS interrupt to set time according to input: Hour24
  36.          (0 - 23), Min (0 - 59) and Sec (0 - 59). }
  37.  
  38. PROCEDURE ASTDateTime (VAR H, M, S, mS, Y, Mo, D : Integer);
  39.          (***************************************************************)
  40.          (* This procedure will read the time off of an AST Memory board*)
  41.          (* (and probably all of its clones) equipped with a National   *)
  42.          (* Semiconductor MM58167A Real time clock.                     *)
  43.          (***************************************************************)
  44.  
  45. FUNCTION DOSTimer : real;
  46.          {Returns time since midnight in milliseconds. The average
  47.          resolution is 54 milliseconds.                          }
  48.  
  49. FUNCTION JTimer : real;
  50.          {This function returns the time in milliseconds since midnight
  51.          for systems having TallTree J-RAM 2 board. The resolution is
  52.          1 millisecond.}
  53.  
  54. FUNCTION ASTTimer : real;
  55.          {For systems having AST clock/calendar board or compatable.
  56.          Returns the time since midnight in milliseconds with a
  57.          resolution of one millisecond.}
  58.  
  59. PROCEDURE DateTimeDemo;
  60.  
  61. Implementation
  62.  
  63. TYPE
  64.  
  65.   RegType  = Registers;
  66.  
  67. PROCEDURE GetDosDate (VAR M, DofM, Y, DofW : integer);
  68.  
  69.          {Gets date with MS-DOS call.                                       }
  70.  
  71. VAR
  72.  
  73.   Reg : RegType;
  74.  
  75. Begin
  76.  
  77.   Reg.AH := $2A;                       {Function call $2A returns the date. }
  78.   MsDos (Reg);
  79.  
  80.   with Reg do
  81.     begin
  82.       Y    := CX;
  83.       M    := DH;
  84.       DofM := DL;
  85.       DofW := AL;                      {Undocumented. See GetDosTime.       }
  86.     end {with}                         {Sun = 0, Sat = 6.                   }
  87.  
  88. End; {GetDosDate (VAR M, DofM, Y, DofW : integer}
  89.  
  90.  
  91. PROCEDURE GetDosTime (VAR Hour, Min, Sec, CSec : integer);
  92.  
  93.          {Gets the time with MS-DOS interrupt call. NOTE: The DOS V2
  94.          Technical Manual incorrectly states that the Day of Week is
  95.          returned by function $2C. In fact, it is returned by the date
  96.          function $2A (as is logical).
  97.  
  98.          The clock is only updated 18.2 times per second so there is
  99.          uncertainty of +/- 2.5/100 sec in the value returned in CSec.}
  100.  
  101. VAR
  102.  
  103.   Reg : RegType;
  104.  
  105. Begin
  106.  
  107.   Reg.AH := $2C;                       {Function call $2C returns time.     }
  108.   MsDos (Reg);
  109.  
  110.   with Reg do
  111.     begin
  112.       Hour   := CH;
  113.       Min    := CL;
  114.       Sec    := DH;
  115.       CSec   := DL;                     {Sec/100.                           }
  116.     end {with}
  117.  
  118. End; {GetDosTime (VAR Hour, Min, Sec, CSec : integer)}
  119.  
  120.  
  121. FUNCTION SetDosDate (Month, Day, Year : integer) : Boolean;
  122.  
  123.          {Sets the DOS date according to the input: Year (1980 - 2099)
  124.          Month (1 - 12) and Day (1 - 31). Returns false if any of the
  125.          inputs are out of range.                                    }
  126.  
  127. VAR
  128.  
  129.   Reg : RegType;
  130.  
  131. Begin
  132.  
  133.   with Reg do
  134.     begin
  135.       AH := $2B;                       {Set Date function.                  }
  136.       CX := Year;
  137.       DH := Month;
  138.       DL := Day;
  139.     end; {with}
  140.  
  141.   MsDos (Reg);
  142.  
  143.   SetDosDate := Reg.Al = 0;            {AL is the error return.             }
  144.  
  145.          {/Note: This is more economical than an: if . . then . . else
  146.           construction.                                                    /}
  147.  
  148. End; {SetDosDate (Month, Day, Year : integer) : Boolean}
  149.  
  150.  
  151. FUNCTION SetDosTime (Hour24, Min, Sec : integer) : Boolean;
  152.  
  153.          {Uses DOS interrupt to set time according to input: Hour24
  154.          (0 - 23), Min (0 - 59) and Sec (0 - 59). See comment for set-
  155.          ting 1/100 sec if this is required.
  156.  
  157.          Function returns false if any of the inputs are out range.   }
  158.  
  159. VAR
  160.  
  161.   Reg : RegType;
  162.  
  163. Begin
  164.  
  165.   with Reg do
  166.     begin
  167.       AH := $2D;                       {Set Time function.                  }
  168.       CH := Hour24;
  169.       CL := Min;
  170.       DH := Sec mod 60;                {*}
  171.       DL := 0;                         {Use for setting 1/100 sec.          }
  172.     end; {with}
  173.  
  174.          {*Sec mod 60 to avoid error in case 'Sec' undefined.}
  175.  
  176.   MsDos (Reg);
  177.   SetDosTime := Reg.AL = 0;             {AL is the error return.             }
  178.  
  179. End; {SetDosTime (Hour24, Min, Sec : integer) : Boolean}
  180.  
  181.  
  182.  
  183.  
  184. PROCEDURE ASTDateTime (VAR H, M, S, mS, Y, Mo, D : Integer);
  185.  
  186.          (***************************************************************
  187.          This procedure will read the time off of an AST Memory board
  188.          (and probably all of its clones) equipped with a National
  189.          Semiconductor MM58167A Real time clock. Although the National
  190.          Semiconductor clock uses the I/O adresses $2C0 to $2DF, AST
  191.          has put a "latch" in front of the clock so that all of the
  192.          functions can be used while only using 8 bytes of I/O space.
  193.          Thus, the procedure for extracting the time is different than
  194.          that for the J-Ram timer (see JTimer in these utilities).
  195.          Execution speed is sacrificed for I/O space. The function takes
  196.          3 ms to execute (using a Zenith 151 with a V-20 running at 4.77
  197.          MHz. See the clock-board's manual for more details.
  198.                                                    6-13-86 SEL
  199.           ************************************************************)
  200.  
  201. Var ccs:integer;
  202.  
  203. Function ReadPortAST (PortNum:integer):integer;
  204. begin
  205.   port[$2C0]:=PortNum;
  206.   ReadPortAST:=Port[$2C1];
  207. end;
  208.  
  209.  
  210. Begin                     (*ASTTime*)
  211.                           (*First read the ports as quickly as possible*)
  212.   ms :=ReadPortAST(0);    (*actually, this is 1/10000 of a second*)
  213.   ccs :=ReadPortAST(1);
  214.   s  :=ReadPortAST(2);
  215.   m  :=ReadPortAST(3);
  216.   h  :=ReadPortAST(4);
  217.   D  :=ReadPortAST(6);
  218.   Mo :=ReadPortAST(7);
  219.   Y  :=(ReadPortAST(10));
  220.                            (*Now convert from BCD*)
  221.   ms:=InBCD(ccs)*10 + InBCD(ms shr 4);
  222.   s :=InBCD(s);
  223.   m :=InBCD(m);
  224.   h :=InBCD(h);
  225.   D :=InBCD(D);
  226.   Mo:=InBCD(Mo);
  227.   Y :=InBCD(Y);
  228.  
  229. End; {ASTDateTime}
  230.  
  231.  
  232.  
  233.            {/The following three functions return the time since
  234.            midnight in milliseconds and are intended for timing
  235.            purposes. DOSTimer will work on any IBM PC compatable
  236.            system but has a resolution of only 54 milliseconds. The
  237.            remaining two use clock/calendar boards and have a reso-
  238.            lution of one millisecond. For critical applications
  239.            the time should be determined for executing the function
  240.            and this should be subtracted from the observed time.
  241.  
  242.            By using the calendar functions the timing range can be
  243.            extended. But watch out for the following: (1) Overflow
  244.            of the mantissa. (2) It has been reported that a correction
  245.            of several seconds is made to the DOS clock at midnight.
  246.            (3) The DOS clock on most sytems drift by a minute or
  247.            more a day.                                           /}
  248.  
  249.  
  250. FUNCTION DOSTimer : real;
  251.  
  252.          {Returns time since midnight in milliseconds. The average
  253.          resolution is 54 milliseconds.                          }
  254.  
  255.  
  256. VAR
  257.  
  258.   Reg : RegType;
  259.  
  260. Begin
  261.  
  262.   Reg.AH := $2C;                       {Function call $2C returns time.     }
  263.   MsDos (Reg);
  264.  
  265.   with Reg do
  266.     begin
  267.       DOSTimer :=
  268.         3.6E6 * CH +                   {Hours.                              }
  269.         6.0E4 * CL +                   {Mins.                               }
  270.         1.0E3 * DH +                   {Secs.                               }
  271.         1.0E1 * Dl;                    {Secs / 100.                         }
  272.     end {with}
  273.  
  274. End; {DOSTimer : real}
  275.  
  276.  
  277. FUNCTION JTimer : real;
  278.  
  279.  
  280.          {This function returns the time in milliseconds since midnight
  281.          for systems having TallTree J-RAM 2 board. The resolution is
  282.          1 millisecond.
  283.  
  284.          The ports for the clock on the J-RAM board are assigned as follows;
  285.  
  286.            $2C0*  : (Integer)  millisec X 10;
  287.            $2C2*  : (Byte)     sec;
  288.            $2C3*  : (Byte)     min;
  289.            $2C4*  : (Byte)     hr;
  290.            $2C6*  : (Byte)     day;
  291.            $2C9   : (Byte)     month;
  292.            $2CA   : (Byte)     year - 1980;
  293.  
  294.          *NOTE: Values returned by these ports are in BCD.           }
  295.  
  296.          {/Data transfer between external devices and the 8088 is by
  297.          the use of 'Ports'. Turbo has two pre-defined arrays, Port
  298.          and PortW, for passing byte and integer data respectively.
  299.          The index of the array defines the port number.            /}
  300.  
  301. VAR
  302.  
  303.   Ms, S, M, H : integer;
  304.  
  305. Begin
  306.  
  307.   Ms := PortW[$2C0];                   {Poll the ports as rapidly as        }
  308.   S  := Port[$2C2];                    {possible in order to minimize the   }
  309.   M  := Port[$2C3];                    {probability that a port will be     }
  310.   H  := Port[$2C4];                    {incremented during polling.         }
  311.  
  312.   Ms := Ms shr 4;                      {A BCD divide by ten.                }
  313.  
  314.   JTimer := 3.6E6 * InBCD (H) +        {Hours.                              }
  315.             6.0E4 * InBCD (M) +        {Minutes.                            }
  316.             1.0E3 * InBCD (S) +        {Seconds.                            }
  317.             InBCD (Ms);
  318.  
  319. End; {JTimer : real}
  320.  
  321.  
  322. FUNCTION ASTTimer : real;
  323.  
  324.          {For systems having AST clock/calendar board or compatable.
  325.          Returns the time since midnight in milliseconds with a
  326.          resolution of one millisecond.
  327.  
  328.          The coding is based on Scott Lindsey's ASTDateTime routine. }
  329.  
  330. VAR
  331.  
  332.   MSec, CSec, Sec, Min, Hr : integer;
  333.  
  334.  
  335. Begin
  336.  
  337.   Port [$2C0] := 0;
  338.   MSec        := Port [$2C1];          {Actually 1/10000 sec.               }
  339.   Port [$2C0] := 1;
  340.   CSec        := Port [$2C1];
  341.   Port [$2C0] := 2;
  342.   Sec         := Port [$2C1];
  343.   Port [$2C0] := 3;
  344.   Min         := Port [$2C1];
  345.   Port [$2C0] := 4;
  346.   Hr          := Port [$2C1];
  347.  
  348.   MSec := MSec shr 4;                  {BCD convert to millisec.            }
  349.  
  350.   ASTTimer := 3.6E6 * InBCD (Hr)   +   {Hours.                              }
  351.               6.0E4 * InBCD (Min)  +   {Minutes.                            }
  352.               1.0E3 * InBCD (Sec)  +   {Seconds.                            }
  353.               1.0E1 * InBCD (CSec) +   {Centisec.                           }
  354.                       InBCD (MSec);
  355.  
  356. End; {ASTTimer : real}
  357.  
  358.  
  359. PROCEDURE DateTimeDemo;
  360.  
  361. TYPE
  362.  
  363.   String10 = string[10];
  364.  
  365. Procedure ErrorMsg (Word : String10);
  366.  
  367. begin
  368.  
  369.   GoToXY (5, 22); ClrEol;
  370.   if Word <> '' then
  371.     write (Word + ' not in allowed range. Please re-enter.');
  372.  
  373. end; {ErrorMsg (Word : String10}
  374.  
  375. VAR
  376.  
  377.  Y, M, D, K, Hr, Min, Sec : integer;
  378.  OK                    : Boolean;
  379.  ch                    : char;
  380.  
  381. Begin
  382.  
  383.   repeat
  384.     ClrScr;
  385.     ch := ' ';                         {Initialize.                         }
  386.     GoToXY (31, 5); write ('DOS Date-Time Demo');
  387.     GoToXY (31, 6); write ('------------------');
  388.     repeat
  389.       GoToXY (1, 9); ClrEol;
  390.       write ('Enter date to set - Month (1 - 12): ':50);
  391.       read (M); writeln; ClrEol;
  392.       write ('Day (1 - 31): ':50);
  393.       read (D); writeln; ClrEol;
  394.       write ('Year (4 digits): ':50);
  395.       read (Y);
  396.       OK := SetDosDate (M, D, Y);
  397.       if not OK then
  398.         ErrorMsg ('Date');
  399.     until OK;
  400.     ErrorMsg ('');                     {Clear.                              }
  401.     writeln; writeln;
  402.     repeat
  403.       GoToXY (1, 14); ClrEol;
  404.       write ('Enter time to set - Hr (0 - 23): ':50);
  405.       read (Hr); writeln; ClrEol;
  406.       write ('Min (0 - 59): ':50);
  407.       read (Min); writeln; ClrEol;
  408.       write ('Sec (0 - 59): ':50);
  409.       read (Sec);
  410.       OK := SetDosTime (Hr, Min, Sec);
  411.       if not OK then
  412.         ErrorMsg ('Time');
  413.     until OK;
  414.  
  415.     ErrorMsg ('');                     {Clear.                              }
  416.     GoToXY (1, 19);
  417.     GetDosDate (M, D, Y, K);
  418.     GetDosTime (Hr, Min, Sec, K);
  419.     writeln ('     The date has been entered as: ', M, '-', D, '-', Y - 1900);
  420.     writeln;
  421.     writeln ('     The time has been entered as: ', Hr, ':', Min, ':', Sec);
  422.  
  423.     GoToXY (6, 24); write ('Press any key to repeat or Q to quit. ');
  424.     Ch := readkey;
  425.   until UpCase (ch) = 'Q';
  426.  
  427. End; {DateTimeDemo}
  428.  
  429. BEGIN (* Unit DateTime *)
  430.  
  431. END.
  432.