{ Donated by Warren Smith, Feb 1982 } Module Clock; { This is a collection of routines to access } { an OKI MSM5832 clock chip. } Const { Ports used by the clock } Clk_Cmd_Port = $5A; Clk_Data_Port = $5B; Zero = 0; Dig_Mask = $0F; Rd_Bit = $10; Wr_Bit = $20; Hold_Bit = $40; Min_Time_Index = 0; Max_Time_Index = 5; Day_of_Week = 6; Min_Date_Index = 7; Max_Date_Index = 12; Type Time_Array = array [Min_Time_Index .. Max_Time_Index] of byte; Date_Array = array [Min_Date_Index .. Max_Date_Index] of byte; { These external routines are only used by the last procedure and may } { be erased if that routine is unused. } External Procedure GotoXY (X, Y : integer); External Procedure Read_Cursor (Var X, Y : integer); Function Combine (Byte1, Byte2 : byte) : integer; begin { Combine } Combine := Byte1 * 10 + Byte2 end; { Combine } Procedure DisComb (Value : integer; Var Byte1, Byte2 : byte); begin { DisComb } Byte1 := (Value DIV 10) MOD 10; Byte2 := Value MOD 10 end; { DisComb } Function Rd_Clock (Digit : byte) : byte; begin { Rd_Clock } Out [Clk_Cmd_Port] := Digit ! Rd_Bit; Rd_Clock := Inp [Clk_Data_Port]; Out [Clk_Cmd_Port] := Zero end; { Rd_Clock } Procedure Wrt_Clock (Digit, Value : byte); begin { Wrt_Clock } Digit := Digit & Dig_Mask; Out [Clk_Cmd_Port] := Hold_Bit; Out [Clk_Cmd_Port] := Digit ! Hold_Bit; Out [Clk_Data_Port] := Value; Out [Clk_Cmd_Port] := Digit ! Hold_Bit ! Wr_Bit; Out [Clk_Cmd_Port] := Digit ! Hold_Bit; Out [Clk_Cmd_Port] := Zero end; { Wrt_Clock } Procedure Get_Time (Var Seconds, Minutes, Hours : Integer); Var I, Hours10 : integer; Time : Time_Array; begin { Get_Time } For I := Min_Time_Index to Max_Time_Index do Time [I] := Rd_Clock (I); Hours10 := Min_Time_Index + 5; { Mask out 12/24 format and AM/PM bit } Time [Hours10] := Time [Hours10] & 3; I := Min_Time_Index; Seconds := Combine (Time[I+1], Time[I]); I := I + 2; Minutes := Combine (Time[I+1], Time[I]); I := I + 2; Hours := Combine (Time[I+1], Time[I]) end; { Get_Time } Procedure Set_Time (Seconds, Minutes, Hours : integer); Const Mode_24 = 8; { 24 hour mode bit } Var I, Hours10 : integer; Time : Time_Array; begin { Set_Time } Hours10 := Min_Time_Index + 5; I := Min_Time_Index; DisComb (Seconds, Time[I+1], Time[I]); I := I + 2; DisComb (Minutes, Time[I+1], Time[I]); I := I + 2; DisComb (Hours, Time[I+1], Time[I]); Time [Hours10] := Time [Hours10] ! Mode_24;{set 24 hour mode in hours 10's} For I := Min_Time_Index to Max_Time_Index do Wrt_Clock ( I, Time [I]) end; { Set_Time } Procedure Get_Date (Var Day, Month, Year : integer); Var I, Days10 : integer; Date : Date_Array; begin { Get_Date } For I := Min_Date_Index to Max_Date_Index do Date [I] := Rd_Clock (I); Days10 := Max_Date_Index - 4; Date [Days10] := Date [Days10] & 3; { mask out leap year bit } I := Min_Date_Index; Day := Combine (Date[I+1], Date[I]); I := I + 2; Month := Combine (Date[I+1], Date[I]); I := I + 2; Year := Combine (Date[I+1], Date[I]) end; { Get_Date } Procedure Set_Date (Day, Month, Year : integer); Const Leap_Bit = 8; Var I, Days10 : integer; Date : Date_Array; begin { Set_Date } Days10 := Max_Date_Index - 4; I := Min_Date_Index; DisComb (Day, Date[I+1], Date[I]); I := I + 2; DisComb (Month, Date[I+1], Date[I]); I := I + 2; DisComb (Year, Date[I+1], Date[I]); if (Month <= 2) AND ((Year Mod 4) = 0) then Date[Days10] := Date[Days10] ! Leap_Bit; { set leap bit in Days 10's} For I := Min_Date_Index to Max_Date_Index do Wrt_Clock (I, Date[I]) end; { Set_Date } Procedure Get_Day (Var Day : integer); begin { Get_Day } Day := Rd_Clock (Day_of_Week) end; { Get_Day } Procedure Set_Day (New_Day : integer); begin { Set_Day } { make sure it is in valid range } If (New_Day >= 0) and (New_Day <= 6) then Wrt_Clock (Day_of_Week, New_Day) end; { Set_Day } Procedure Wrt_AM_PM (Var Outfile : Text; Seconds, Minutes, Hours : integer); Var AP : array [ 1 .. 2 ] of char; begin { Wrt_AM_PM } If Hours > 12 then begin Hours := Hours - 12; AP := 'pm' end else If Hours = 12 then AP := 'pm' else AP := 'am'; Write (Outfile, (Hours MOD 100):2, ':', ((Minutes DIV 10) MOD 10):1, (Minutes MOD 10):1, ':', ((Seconds DIV 10) MOD 10):1, (Seconds MOD 10):1, ' ',AP) end; { Wrt_AM_PM } Procedure Wrt_Time (Var Outfile : Text; Seconds, Minutes, Hours : integer); begin { Wrt_Time } Write (Outfile, ((Hours DIV 10) MOD 10):1, (Hours MOD 10):1, ':', ((Minutes DIV 10) MOD 10):1, (Minutes MOD 10):1, ':', ((Seconds DIV 10) MOD 10):1, (Seconds MOD 10):1) end; { Wrt_Time } Procedure Wrt_Date (Var Outfile : Text; Day, Month, Year : integer); Var Mon : array [ 1 .. 3 ] of char; begin { Wrt_Date } Case Month of 1 : Mon := 'Jan'; 2 : Mon := 'Feb'; 3 : Mon := 'Mar'; 4 : Mon := 'Apr'; 5 : Mon := 'May'; 6 : Mon := 'Jun'; 7 : Mon := 'Jul'; 8 : Mon := 'Aug'; 9 : Mon := 'Sep'; 10 : Mon := 'Oct'; 11 : Mon := 'Nov'; 12 : Mon := 'Dec'; else Mon := 'OOP' end; Write (Outfile, Mon, ' ', Day:1, ',', ' 19', (Year MOD 100):2) end; { Wrt_Date } Procedure Wrt_Day (Var OutFile : Text; Day : integer); Var New_Day : array [ 1 .. 3 ] of char; begin { Wrt_Day } Case Day of 0 : New_Day := 'Sun'; 1 : New_Day := 'Mon'; 2 : New_Day := 'Tue'; 3 : New_Day := 'Wed'; 4 : New_Day := 'Thu'; 5 : New_Day := 'Fri'; 6 : New_Day := 'Sat'; else New_Day := 'DAY' end; Write (OutFile, New_Day) end; { Wrt_Day } Procedure Time_Block (X, Y : integer); Var Seconds, Minutes, Hours, Day_of_Week, Day, Month, Year : integer; Old_X, Old_Y : integer; begin { Time_Block } Read_Cursor (Old_X, Old_Y); Get_Time (Seconds, Minutes, Hours); Get_Date (Day, Month, Year); Get_Day (Day_of_Week); GotoXY (X, Y); Wrt_Day (OutPut, Day_of_Week); GotoXY (X, Y + 1); Wrt_Date (OutPut, Day, Month, Year); GotoXY (X, Y + 2); Wrt_AM_PM (OutPut, Seconds, Minutes, Hours); GotoXY (Old_X, Old_Y) end; { Time_Block } Modend. .