Show the time in several formats.

The program below reads the time from the hardware clock (mostly a DS 1287 or compatible chip) and shows it on screen. The format is either text, or numeric. In the latter case, only the numbers from the clock registers are put on screen.

The program is simple and easy. Just sit behind iut after you printed and see how far you come.

I won't spoil the source with comments and remarks. So if you want the source, just cut and paste it from the screen.

MODULE Datum;

(*      Show the date and time of the system clocks.
        One option is to use the DOS software clock and the other uses the RTC chip.
        A future version should be able to set the RTC.
        CopyLeft 2000, Jan Verhoeven. This is GNU GPL software
        *)

FROM    SYSTEM      IMPORT  ASSEMBLER;
FROM    System      IMPORT  Terminate, GetArg;
FROM    Strings     IMPORT  Assign, CompareStr;
FROM    Xchar       IMPORT  UpperString;
FROM    InOut       IMPORT  Write, WriteCard, WriteLn, WriteString, WriteLine, WriteHex;
FROM    Keyboard    IMPORT  GetKey, KeyPressed;


CONST   Tab      = 09X;

TYPE    RegisterMode = (BCD, Binary);
        HourMode     = (AMPM, Digital);

VAR     Second, Minute, Hour,
        Day, DoW, Month, Year,
        Century, RegB,
        Count                   : CARDINAL;

        Option                  : ARRAY [0..20] OF CHAR;
        DataMode                : RegisterMode;
        TimeFormat              : HourMode;


PROCEDURE ReadRTC (Register : CARDINAL) : CARDINAL;

(*      Read one byte from specified register from RTC      *)

VAR     Result : CARDINAL;

BEGIN
    ASM
        MOV   AL, Register
        OUT   70H, AL
        IN    AL, 71H
        MOV   AH, 00
        MOV   Result, AX
    END;
    RETURN Result
END ReadRTC;


PROCEDURE WriteRTC (Register, Value : CARDINAL);

(*      Write Value to specified Register of RTC            *)

BEGIN
    ASM
        MOV   AL, Register
        OUT   70H, AL
        MOV   AL, Value
        OUT   71H, AL
    END;
END WriteRTC;


PROCEDURE SetRtc;               (*      Write current date and time to the RTC chip         *)

VAR     OldRegB,                (*  Register B value        *)
        Value   : CARDINAL;     (*  Temporary value         *)

BEGIN
    OldRegB := ReadRTC (11);
    Value := OldRegB;           INC (Value, 128);

    WriteRTC (11, Value  );     (*  Disable clock actions   *)
    WriteRTC ( 0, Second );
    WriteRTC ( 2, Minute );
    WriteRTC ( 4, Hour   );
    WriteRTC ( 6, DoW    );
    WriteRTC ( 7, Day    );
    WriteRTC ( 8, Month  );
    WriteRTC ( 9, Year   );
    WriteRTC (50, Century);
    WriteRTC (11, OldRegB);     (*  Re-Enable clock actions *)
END SetRtc;


PROCEDURE Convert (Value  : CARDINAL; Mode  : RegisterMode; Format  : HourMode) : CARDINAL;

BEGIN
    IF Format = AMPM THEN
        IF 7 IN BITSET (Value) THEN  DEC (Value, 116)  END
    END;
    IF Mode = BCD THEN
        RETURN  (Value MOD 16) + 10 * (Value DIV 16)
    ELSE
        RETURN  Value
    END
END Convert;


PROCEDURE GetRtc;

(*      Read the current date and time from the RTC chip    *)

BEGIN
    RegB := ReadRTC (11);
    IF 1 IN BITSET (RegB) THEN          (*  Check 24/12 bit *)
        TimeFormat := Digital
    ELSE
        TimeFormat := AMPM
    END;
    IF 2 IN BITSET (RegB) THEN          (*  Check DM bit    *)
        DataMode := Binary
    ELSE
        DataMode := BCD
    END;

    Second  := Convert (ReadRTC  (0), DataMode, TimeFormat);
    Minute  := Convert (ReadRTC  (2), DataMode, TimeFormat);
    Hour    := Convert (ReadRTC  (4), DataMode, TimeFormat);
    DoW     := Convert (ReadRTC  (6), DataMode, TimeFormat);
    Day     := Convert (ReadRTC  (7), DataMode, TimeFormat);
    Month   := Convert (ReadRTC  (8), DataMode, TimeFormat);
    Year    := Convert (ReadRTC  (9), DataMode, TimeFormat);
    Century := Convert (ReadRTC (50), DataMode, TimeFormat);

    WriteCard (Second, 8);      WriteCard (Minute, 8);
    WriteCard (Hour,   8);      WriteCard (DoW,    8);
    WriteCard (Day,    8);      WriteCard (Month,  8);
    WriteCard (Year,   8);      WriteCard (Century,8);      WriteLn;

    IF Century = 19 THEN
        INC (Year, 1900);
    ELSE
        INC (Year, 2000);
    END;
END GetRtc;


(* PROCEDURE GetDos (VAR Month, Day, DoW, Year, Hour, Minute, Second : CARDINAL);   *)

PROCEDURE GetDosData;

(*      Read date and time from DOS clock.  *)

BEGIN
    ASM
        MOV   AH, 2AH
        INT   21H
        MOV   Month, DH
        MOV   Day, DL
        MOV   DoW, AL
        MOV   Year, CX

        MOV   AH, 2CH
        INT   21H
        MOV   Hour, CH
        MOV   Minute, CL
        MOV   Second, DH
    END;
END GetDosData;


PROCEDURE SetDosData (Month, Day, DoW, Year, Hour, Minute, Second : CARDINAL);

(*      Set date and time with DOS clock.   *)

BEGIN
    ASM
        MOV   DH, Month
        MOV   DL, Day
        MOV   CX, Year
        MOV   AH, 2BH
        INT   21H

        MOV   CH, Hour
        MOV   CL, Minute
        MOV   DH, Second
        MOV   AH, 2DH
        INT   21H
    END;
END SetDosData;


PROCEDURE UpperCase (VAR String     : ARRAY OF CHAR);

(*      Convert string to uppercase characters only         *)

VAR     n       : CARDINAL;

BEGIN
    FOR n := 0 TO HIGH (String) DO
        String [n] := CAP (String [n]);
    END
END UpperCase;


PROCEDURE UserMessage (Code : CARDINAL);

BEGIN
    CASE Code OF
        1 : WriteLine ("Invalid number in day of week register.");
            |
        2 : WriteLine ("Invalid month specified. Please call a mechanic.");
            |
        3 : WriteLine ("Empty command line entered. Assuming help is needed.");
            WriteLn;
            |
        4 : WriteLine ("Please use the following format:");
            WriteLn; Write (Tab);
            WriteLine ("DATUM {= <date/time}, {DOS}, {RTC}, {SET <date/time>}, {SHOW}, {HELP}");
            WriteLn;
            WriteLine ("Separate each argument with a space please.");
            WriteLine ("Use it in any sensible combination, even such as DATUM DOS = RTC.");
            |
        5 : WriteLn;
            WriteLine ("Thank you for using this program. It is published under the rules of the");
            WriteLine ("GNU GPL, of which you should have received a copy with this program.");
            WriteLine ("If you need more information, please issue a DATUM SHOW command.");
            |
        6 : WriteLn;
            WriteLine ("Howdy y'all! This program was made by:"); WriteLn; Write (Tab);
            WriteLine ("Jan Verhoeven, NL-5012 GH 272, E-mail: fruttenboel@gmail.com");
            WriteLn;
            WriteLine ("This is FREE software, as described in the GNU GPL documents. Please study");
            WriteLine ("the GNU GPL documents for more details.");
            WriteLine ("The copyrights of the sourcecode remain with me, but you are permitted to make");
            WriteLine ("modifications to it, as long as the rules of the GNU GPL remain intact, also");
            WriteLine ("for the modified programs."); WriteLn;
            WriteLine ("In case you like this program, please send a postcard to the above address.");
    END;
END UserMessage;


PROCEDURE ShowWeekday (Weekday : CARDINAL);

BEGIN
    CASE Weekday OF
        0 : WriteString ("Sunday");     |
        1 : WriteString ("Monday");      |
        2 : WriteString ("Tuesday");    |
        3 : WriteString ("Wednesday");   |
        4 : WriteString ("Thursday");   |
        5 : WriteString ("Friday");      |
        6 : WriteString ("Saturday");
    ELSE
        UserMessage (1);
        Terminate (1);
    END;
END ShowWeekday;


PROCEDURE ShowMonth (Month : CARDINAL);

BEGIN
    CASE Month OF
        1 : WriteString ("January");    |
        2 : WriteString ("February");   |
        3 : WriteString ("March");      |
        4 : WriteString ("April");      |
        5 : WriteString ("May");        |
        6 : WriteString ("June");       |
        7 : WriteString ("July");       |
        8 : WriteString ("August");     |
        9 : WriteString ("September");  |
       10 : WriteString ("October");    |
       11 : WriteString ("November");   |
       12 : WriteString ("December");
    ELSE
        UserMessage (2);
        Terminate (2);
    END;
END ShowMonth;


PROCEDURE ShowData;

BEGIN
    WriteString ("Today is ");  ShowWeekday (DoW);
    WriteCard (Day, 3);         Write (" ");
    ShowMonth (Month);
    WriteCard (Year, 5);        WriteString (" and the time is now ");
    WriteCard (Hour, 2);        Write (":");
    WriteCard (Minute, 2);      Write (":");
    WriteCard (Second, 2);      Write (".");
    WriteLn;
END ShowData;


BEGIN
    GetArg (Option, Count);
    IF Count = 0 THEN
        UserMessage (3);
        UserMessage (4);
        Terminate (3);          (* Show correct syntax  *)
    END;
    LOOP
        UpperCase (Option);
        IF Count = 0 THEN
            EXIT;
        END;
        IF CompareStr (Option, 'SHOW') = 0 THEN
            UserMessage (6);
        END;
        IF CompareStr (Option, 'HELP') = 0 THEN
            UserMessage (4);
        END;
        IF CompareStr (Option, 'RTC') = 0 THEN
            GetRtc;
            ShowData;
        END;
        IF CompareStr (Option, 'DOS') = 0 THEN
            GetDosData;
            ShowData;
        END;
        GetArg (Option, Count);
    END;
    UserMessage (5);
END Datum.
   

Page created June 2002 and