; TIME.COM (8080 version) Version 2.0.
; CP/M program to display and set the real-time clock on Kaypro 4-84.
; Written 04/22/84 by Bob Snider, Columbus Ohio. Greatly expanded 6/30/84.
; Dispaly is MM/DD HH:MM:SS and can be 24-hour format or 12-hour with
; AM/PM. Date is optional, and the ability to set the clock is optional
; for those who want a minimum length module. Customize this assembly
; by setting the options in the "Customization section".
; The clock is just displayed by the command "TIME". The clock is displayed
; and set by anything extra on the command line, ie. "TIME SET". The
; program will prompt for date and time value which must be entered as in the
; display format. Each of the following items can be set independently:
;    Date (month/day)
;    Day of the week
;    Time of day (seconds may be omitted)
; If the 12-hour format is on, AM or PM must always follow the time.
; Any omitted items are not changed in the clock.
; The clock is set at the carriage return. The input line is parsed for
; proper format, but not checked for valid dates or times. If nothing is
; entered the time is unchanged. If an error is detected, the position of
; the error in the string is flagged with a '^' and nothing is set.
; The clock is checked to see if an update has occurred while being read,
; and it is re-read if so, ensuring valid time displays.
; Problems or enhancements should be directed to the Kaypro User's Group on
; CompuServe, page PCS-25.
;
; CONDITIONAL ASSEMBLY CONSTANTS FOR CUSTOMIZATION.
NO      EQU     0               ;VALUE FOR 'NO' IN OPTIONS.
YES     EQU     1               ;VALUE FOR 'YES' IN OPTIONS.
;
; CUSTOMIZATION SECTION. EACH OPTION MUST BE CODED 'YES' OR 'NO'.
;
AMPM    EQU     YES             ;12-HOUR CLOCK FORMAT WITH AM/PM. NO=24 HOUR.
DATE    EQU     YES             ;DATE IS DISPLAYED.
WEEKDAY EQU     YES             ;DAY OF WEEK IS DISPLAYED.
ZEROSUP EQU     YES             ;SUPPRESS LEADING 0'S IN NUMBERS.
SETTIME EQU     YES             ;ALLOW TIME TO BE SET. NO=DISPLAY ONLY.
;
; COMPILE-TIME CONSTANTS.
;
BOOT    EQU     0000H           ;SYSTEM BOOT ADDRESS
BDOS    EQU     0005H           ;BDOS ENTRY POINT
COMTAIL EQU     0080H           ;COMMAND TAIL FROM COMMAND LINE (COUNT+CHARS)
CONOUT  EQU     2               ;CODE FOR CONSOLE OUTPUT REQUEST
RTCA    EQU     20H             ;CLOCK ADDRESS SELECT REG
RTCD    EQU     24H             ;CLOCK DATA REGISTER
RTCS    EQU     22H             ;CLOCK STATUS REGISTER
REGEND  EQU     5+(DATE*3 OR WEEKDAY)  ;ENDING REGISTER COUNT FOR TIME LOOP
CR      EQU     0DH             ;CARRIAGE RETURN CHAR
LF      EQU     0AH             ;LINE FEED CHAR
;
; WE BEGIN.
;
        ORG     0100H           
        JMP     START           ;SKIP ID
        DB      'TIME V2.0 RAS 6/30/84'
START:
; FIRST SAVE CP/M STACK AND SET UP OURS.
        LXI     H,0             ;CLEAR HL
        DAD     SP              ;ADD SP+0 IN HL
        SHLD    SAVESP          ;SAVE SP OF CPM
        LXI     SP,STACK        ;POINT TO MY STACK AREA
;
; READ THE CLOCK TIME IN ONE BURST.
; 
READTIME:
        MVI     A,0CFH          ;INITIAL STATUS SETUP BYTE
        OUT     RTCS            ;SET PIO FOR MODE 3 IN/OUTPUT
        MVI     A,0E0H          ;LOW 5 BITS OUTPUT, TOP 3 INPUT
        OUT     RTCS            ;SET PIO IN/OUT BITS
        MVI     A,03H           ;DISABLE INTERRUPTS
        OUT     RTCS            ;DO IT
        MVI     A,14H           ;STATUS REG ADDR
        OUT     RTCA            ;SELECT IT
        IN      RTCD            ;RESET STATUS BIT
DOREAD:
        LXI     H,VALUE         ;POINT TO TIME SAVE AREA
        MVI     B,2             ;START WITH SECONDS
BURST:
        MOV     A,B             ;A IS REGISTER WE WANT TO READ
        CPI     REGEND          ;GOTTEN ALL WE WANT?
        JNC     CHECK           ;YES, DONE GETTING TIME
        OUT     RTCA            ;SELECT THAT REGISTER OF CLOCK
        IN      RTCD            ;READ THE CLOCK DATA
        MOV     M,A             ;SAVE IN CORE
        INX     H               ;NEXT MEMORY LOCATION
        INR     B               ;NEXT REG ADDR
        JMP     BURST           ;GO GET MORE DATA
CHECK:
; SEE IF THE CLOCK ROLLED OVER DURING THE READS.
        MVI     A,14H           ;STATUS REG ADDR
        OUT     RTCA            ;SELECT IT
        IN      RTCD            ;GET STATUS
        ORA     A               ;WAS CLOCK ROLL?
        JNZ     DOREAD          ;YES, GO READ AGAIN
;
; FORMAT THE DATE AND TIME AND SEND TO CONSOLE.
;
GOTIT:
    IF DATE                     ;INCLUDE ONLY IF DATE DISPLAY OPTION
        LXI     H,MONTH         ;POINT TO MONTH VALUE
        CALL    HEXOUTL         ;PRINT IT (MAYBE ZERO SUPPRESSED)
        MVI     A,'/'           ;SEPARATOR
        CALL    CHAROUT         ;SEND A CHAR
        DCX     H               ;POINT TO DAY OF MONTH
        CALL    HEXOUTL         ;PRINT IT (ALSO ZERO-SUP)
        CALL    BLANK           ;PRINT A BLANK
    ENDIF ;(DATE)
    IF WEEKDAY                  ;INCLUDE IF DAY OF WEEK OPTION
        DCX     H               ;POINT TO DAY OF WEEK
        MOV     L,M             ;GET VALUE
        DCR     L               ;ADJUST FOR 0-6
        MVI     H,0             ;CLEAR TOP
        LXI     D,DAYTAB        ;GET ADDRESS OF TABLE
        XCHG                    ;FLIP HL,DE
        DAD     D               ;TABLE+3*(HL)=NAME TO USE
        DAD     D
        DAD     D
        MVI     B,3             ;3 CHARS TO SHOW
WKOUT:  MOV     A,M             ;GET ONE
        CALL    CHAROUT         ;SEND IT
        INX     H               ;NEXT
        DCR     B               ;COUNT IT
        JNZ     WKOUT           ;LOOP
        CALL    BLANK           ;PUT SPACER
    ENDIF ;(WEEKDAY)
        LXI     H,HOURS         ;POINT TO HOURS
    IF AMPM                     ;INCLUDE ONLY IF 12 HOUR AM/PM DISPLAY OPT.
        MOV     A,M             ;GET HOURS
        MVI     B,'A'           ;ASSUME AM
        CPI     12H             ;IS AFTERNOON?
        JC      NOPMADJ         ;NO, NO MORE ADJUSTMENTS
        MVI     B,'P'           ;YES, IS PM
        JZ      NOPMADJ         ;IF STILL IN HOUR 12, NO NUMBERIC ADJUST
        SBI     12H             ;SUBTRACT 12 HOURS
        DAA                     ;DECIMAL ADJUST
NOPMADJ:
        CPI     00H             ;IS MIDNIGHT HOUR?
        JNZ     NOMIDAM         ;NO
        MVI     A,12H           ;YES, SET 12 AM
NOMIDAM:
        MOV     M,A             ;RESET HOURS
        MOV     A,B             ;GET AM/PM FLAG
        STA     AMPMFLAG        ;SAVE IT FOR LATER
    ENDIF ;(AMPM)
        CALL    HEXOUTL         ;PRINT HOURS (MAYBE ZERO SUPPRESSED)
        CALL    COLON           ;PUT OUT A ":" FOLLOWED BY MINUTES
        CALL    COLON           ;':' AND SECONDS
    IF AMPM                     ;IF AM/PM DISPLAY OPTION
        CALL    BLANK           ;PRINT A BLANK
        LDA     AMPMFLAG        ;GET A OR P
        CALL    CHAROUT         ;PRINT IT
        MVI     A,'M'           ;GET AN M
        CALL    CHAROUT         ;PRINT IT
    ENDIF ;(AMPM)
        CALL    CRLF            ;PUT OUT CR LF
;
; SEE IF CLOCK SET REQUESTED BY ANYTHING IN THE COMMAND TAIL.
; PROMPT FOR THE DATE AND TIME TO SET THE CLOCK IF REQUESTED.
;
    IF SETTIME                  ;INCLUDE ONLY IF TIME SET OPTION
        LDA     COMTAIL         ;GET THE COUNT
        CPI     2               ;IS AT LEAST 2 CHARS?
        JC      DONE            ;NO, RETURN NOW
; SET THE TIME REQUESTED.
DOSET:
        LXI     H,VALUE         ;POINT TO DATE/TIME VALUE AREA
        MVI     B,6             ;COUNT TO CLEAR
CLEAR:  MVI     M,0FFH          ;SET NO VALUE
        INX     H               ;NEXT
        DCR     B               ;COUNT
        JNZ     CLEAR           ;LOOP FOR ALL
        LXI     D,PROMPT        ;POINT TO PROMPT MESSAGE
        MVI     C,09H           ;PRINT STRING FUNCTION
        CALL    BDOS            ;PUT TEXT ON SCREEN.
        MVI     A,30            ;GET BUFFER LENGTH
        STA     INMAX           ;SET LENGTH
        LXI     D,INMAX         ;POINT TO START OF BUFFER PARMS
        MVI     C,0AH           ;READ BUFFER FUNCTION
        CALL    BDOS            ;READ CONSOLE INPUT
        CALL    CRLF            ;FEED A LINE
        LXI     H,INLEN         ;POINT TO INPUT BUFFER LENGTH
        MOV     A,M             ;GET RETURNED LENGTH
        ORA     A               ;WAS IT ZERO?
        JZ      NOTSET          ;YES, NOTHING TO SET
        MOV     E,A             ;SAVE COUNT
        MVI     D,0             ;CLEAR D
        INX     H               ;POINT TO 1ST CHAR
        DAD     D               ;POINT BEYOND LAST CHAR
        MVI     M,' '           ;SET A SCAN DELIMITER
        INX     H               ;POINT ONE MORE
        MVI     M,0             ;SET FINAL PARSE DELIMITER
        LXI     H,INBUF         ;POINT TO FIRST CHAR
    ENDIF ;(SETTIME ALONE)
    IF SETTIME AND DATE         ;INCLUDE IF DATE OPTION IS ON
        SHLD    WKPTR           ;SAVE SCAN POINTER
        CALL    NUMBER          ;DECODE A NUMBER AND DELIMITER
        JC      NODATE          ;INVALID NUM, NO DATE THERE
        CPI     '/'             ;WAS DELIM A SLASH?
        JZ      OKDATE          ;YES, WE HAVE A DATE
        LHLD    WKPTR           ;NO, RESTORE SCAN TO START
        JMP     NODATE          ;CONTINUE NEXT ITEM
OKDATE: MOV     A,C             ;GET DECODED VALUE
        STA     MONTH           ;SET MONTH
        INX     H               ;NEXT CHAR
        CALL    NUMBER          ;TRY FOR DAY
        JC      ERROR
        CPI     ' '             ;WAS DELIM A BLANK?
        JNZ     ERROR           ;NO, BAD
        MOV     A,C             ;GET NUM
        STA     DAY             ;SET DAY OF MONTH
        INX     H               ;NEXT CHAR
    ENDIF ;(SETTIME AND DATE)
NODATE:
    IF SETTIME AND WEEKDAY      ;INCLUDE WITH DAY OF WEEK OPTION
        LXI     D,DAYTAB        ;POINT TO TABLE
        MVI     C,1             ;INIT VALUE
        SHLD    WKPTR           ;SAVE START POINTER
LOOKUP: LHLD    WKPTR           ;GET START ADDR
        MVI     B,3             ;LENGTH
LOOKUPLOOP:
        LDAX    D               ;GET TABLE CHAR
        CPI     0               ;END OF TABLE?
        JZ      NOWEEKDAY       ;YES, NOT FOUND, NOT ERROR YET
        XRA     M               ;BASIC COMPARE
        ANI     0DFH            ;ELIMINATE CASE DIFFERENCE
        JZ      LOOKMATCH       ;MATCHES IF ZERO
ADJUST: INX     D               ;NO MATCH, BUMP TABLE PTR
        DCR     B               ;FOR REST OF LENGTH
        JNZ     ADJUST          ;LOOP
        INR     C               ;BUMP VALUE
        JMP     LOOKUP          ;TRY NEXT
LOOKMATCH:
        INX     D               ;NEXT IN TABLE
        INX     H               ;NEXT IN INPUT
        DCR     B               ;COUNT
        JNZ     LOOKUPLOOP      ;TRY NEXT CHAR
; GOOD WEEK DAY NAME FOUND.
        MOV     A,C             ;GET DECODED VALUE
        STA     DAYOFWEEK       ;SAVE
        MOV     A,M             ;GET NEXT CHAR
        CPI     ' '             ;IS GOOD DELIM?
        JNZ     ERROR           ;NO, CRUSH IT
        INX     H               ;POINT TO NEXT CHAR
    ENDIF ;(WEEKDAY)
NOWEEKDAY:
    IF SETTIME                  ;INCLUDE IF SET TIME OPTION
        CALL    NUMBER          ;GET NEXT NUMBER
        JC      NOTIME          ;NO TIME THERE
        CPI     ':'             ;WAS DELIM ':'?
        JNZ     ERROR           ;NO, BAD INPUT
        MOV     A,C             ;GET VALUE
        STA     HOURS           ;SAVE
        INX     H               ;NEXT
        CALL    NUMBER          ;TRY FOR MINUTES
        JC      ERROR
        MOV     A,C
        STA     MINUTES         ;SAVE MINUTES
        MOV     A,M             ;GET DELIM AGAIN
        CPI     ':'             ;CHECK DELIM
        JNZ     NOSECS          ;ALLOW SECONDS TO BE OMITTED
        INX     H               ;NEXT
        CALL    NUMBER          ;TRY FOR SECONDS
        JC      ERROR           ;BAD
        MOV     A,C
        STA     SECONDS         ;SAVE SECONDS
NOSECS: MOV     A,M             ;GET DELIM AGAIN
        CPI     ' '             ;VALID FINAL DELIM?
        JNZ     ERROR           ;NO, GARBAGE
        INX     H               ;NEXT CHAR
    ENDIF ;(SETTIME)
    IF SETTIME AND AMPM         ;INCLUDE DECODING FOR 12-HOUR FORMAT OPTION
        MOV     A,M             ;GET NEXT CHAR
        ANI     0DFH            ;MAKE UPPER CASE
        CPI     'A'             ;IS A?
        JZ      AOK             ;YES
        CPI     'P'             ;IS P?
        JNZ     ERROR           ;NO, ERROR
        LDA     HOURS           ;FOR PM, GET HOURS BACK
        CPI     12H             ;WAS IT NOON HOUR?
        JZ      APOK            ;YES, NO ADJUST
        ADI     12H             ;+12 HOURS FOR PM
        DAA                     ;DECIMAL ADJUST
        STA     HOURS           ;UPDATE VALUE
        JMP     APOK            ;CONTINUE
AOK:    LDA     HOURS           ;GET HOURS
        CPI     12H             ;WAS MIDNIGHT HOUR?
        JNZ     APOK            ;NO, NO ADJUST
        MVI     A,00H           ;YES, SET TO 00 HOURS
        STA     HOURS           ;UPDATE HOURS
APOK:   INX     H               ;POINT TO 'M'
        MOV     A,M             ;GET IT
        ANI     0DFH            ;UPPER CASE
        CPI     'M'             ;IS IT REALLY?
        JNZ     ERROR           ;AW, SHUCKS
        INX     H               ;LAST CHECK
        MOV     A,M             ;GET DELIM
        CPI     ' '             ;VALID?
        JNZ     ERROR           ;NO
        INX     H               ;NEXT
    ENDIF ;(SETTIME AND AMPM)
NOTIME:
    IF SETTIME                  ;NOW FOR ALL SETS
        MOV     A,M             ;LOOK AT LAST DELIM
        ORA     A               ;WAS END OF STRING?
        JNZ     ERROR           ;FOOEY
; NOW LOAD THE TIME VALUES INTO THE CLOCK DEVICE.
        LDA     SECONDS         ;FIRST CHECK FOR SECONDS GIVEN
        CPI     0FFH            ;WAS OMITTED?
        JZ      NOGO            ;YES, NO GO COMMAND
        MVI     A,15H           ;GET ADDRESS FOR 'GO' COMMAND
        OUT     RTCA            ;RESET SECONDS AND BELOW
        MVI     A,00H           ;JUST CLEAR REG
        OUT     RTCD            ;CAUSE LOW REGS TO CLEAR
NOGO:   MVI     B,2             ;START AT SECONDS REGISTER
        LXI     H,SECONDS       ;POINT TO SAVED SECONDS VALUE
OUTSET:
        MOV     A,B             ;GET REG ADDR
        CPI     REGEND          ;DONE ALL WE WANT?
        JNC     SETOK           ;YES, SET IS DONE
        OUT     RTCA            ;SELECT THAT REG
        MOV     A,M             ;GET SAVED VALUE
        CPI     0FFH            ;IS IT 'NO CHANGE'?
        JZ      SKIPIT          ;YES, SKIP THIS ONE
        OUT     RTCD            ;SET THE REGISTER
SKIPIT: INX     H               ;POINT TO NEXT VALUE
        INR     B               ;NEXT REG ADDR
        JMP     OUTSET          ;LOOP FOR ALL REGS
SETOK:
        LXI     D,OKMSG         ;POINT TO TIME SET OK
ECHOEXIT:
        MVI     C,09H           ;PRINT STRING FUNCTION
        CALL    BDOS            ;PUT TEXT ON SCREEN.
        MVI     A,0             ;GET A ZERO
        STA     COMTAIL         ;CLEAR COMMAND TAIL LENGTH
        JMP     READTIME        ;DISPLAY NEW TIME AND EXIT
ERROR:
        PUSH    H               ;SAVE ADDR OF ERROR
        MVI     B,30            ;SET UP TO CLEAR 30 CHARS
        LXI     H,INBUF         ;POINT TO BUFFER
FLAGLOOP:
        MVI     M,' '           ;CLEAR A CHAR
        INX     H               ;NEXT
        DCR     B               ;COUNT
        JNZ     FLAGLOOP        ;LOOP
        POP     H               ;GET ERROR ADDR BACK
        MVI     M,'^'           ;PUT A POINTER TO ERROR
        INX     H               ;NEXT
        MVI     M,'$'           ;PUT ENDING STRING
        LXI     D,INBUF         ;POINT TO ERROR FLAG LINE
        MVI     C,09H           ;PRINT STRING FUNCTION
        CALL    BDOS            ;DISPLAY FLAG LINE
        LXI     D,ERRMSG        ;POINT TO ERROR MESSAGE
        MVI     C,09H           ;PRINT STRING
        CALL    BDOS            ;DISPLAY ERROR MSG
        JMP     READTIME        ;RE-TRY INPUT
; NOTHING ENTERED IN RESPONSE TO PROMPT. SAY NOT SETTING AND DONE.
NOTSET:
        LXI     D,NOSETMSG      ;POINT TO MSG
        JMP     ECHOEXIT        ;EXIT WITH TIME DISPLAY
;
; ROUTINE TO DECODE A NUMBER UP TO 2 DIGITS AND A DELIMITER.
; INPUT IS HL POINTING TO NEXT IN BUFFER. 0 BYTE IS END OF STRING.
; NUMBER VALUE (IN BCD) IS RETURNED IN C. DELIMITER IS IN A.
; ANY ERROR DETECTED IN NUMBER CAUSES CARRY FLAG SET AND HL RESTORED.
;
NUMBER:
        MVI     B,2             ;INIT MAX DIGIT COUNTER
        MVI     C,0             ;CLEAR ANSWER WORK AREA
        SHLD    WKPTR           ;SAVE STARTING SCAN
GETDIG:
        MOV     A,M             ;GET CHAR FROM BUFFER
        CPI     '0'             ;IS >= '0'?
        JC      NONDIGIT        ;NO, NOT A DIGIT
        CPI     '9'+1           ;IS <= '9'?
        JNC     NONDIGIT        ;NO, NOT A DIGIT
        ANI     0FH             ;ISOLATE DIGIT VALUE
        MOV     D,A             ;SAVE IT
        MOV     A,C             ;GET PREVIOUS VALUE
        RLC ! RLC ! RLC ! RLC   ;SHIFT TO HIGH NYBBLE
        ORA     D               ;ADD IN NEW DIGIT
        MOV     C,A             ;SAVE NEW VALUE
        INX     H               ;POINT TO NEXT CHAR
        DCR     B               ;COUNT DIGIT
        JNZ     GETDIG          ;TRY FOR ANOTHER IF LENGTH LEFT
NONDIGIT:
        MOV     A,B             ;LOOK AT COUNT
        CPI     2               ;WERE THERE ANY DIGITS?
        JZ      BADNUM          ;NO, ERROR
        MOV     A,M             ;GET DELIMITER BACK
        ORA     A               ;TURN OFF CARRY
        RET                     ;RETURN GOOD
BADNUM:
        LHLD    WKPTR           ;RESTORE SCAN PTR
        STC                     ;SET WE HAD AN ERROR
        RET                     ;RETURN ERROR
; TIME SET MESSAGES.
PROMPT:
        DB      'Enter values in above format. Omitted values are unchanged.'
        DB      CR,LF,'$'
OKMSG   DB      'Set OK.',CR,LF,'$'
ERRMSG  DB      CR,LF,'Invalid format.',CR,LF,'$'
NOSETMSG:
        DB      'Nothing set.',CR,LF,'$'
;
    ENDIF ;(SETTIME)
;
; DONE. RESTORE PREVIOUS STACK AND RETURN TO CP/M.
;
DONE:
        LHLD    SAVESP          ;GET SAVED SP
        SPHL                    ;SP=HL, RESTORE PREV SP
        RET                     ;RETURN TO CP/M
;
; SUBROUTINE TO PUT A CHARACTER TO CONSOLE. CHAR IN A. SAVES HL.
;
CHAROUT:
        PUSH    H               ;SAVE NEEDED REG
        PUSH    B
        MVI     C,CONOUT        ;SET BDOS REQUEST CODE
        MOV     E,A             ;PUT CHAR IN E
        CALL    BDOS            ;SYSTEM CALL
        POP     B       
        POP     H               ;RESTORE
        RET                     ;DONE
; ROUTINE ENTRY TO PUT A BLANK ON THE SCREEN.
BLANK:
        MVI     A,' '           ;GET A SPACE
        JMP     CHAROUT         ;CONTINUE IN CHAROUT SUBROUTINE
; ROUTINE ENTRY TO PUT CR AND LF ON THE SCREEN.
CRLF:
        MVI     A,0DH           ;CARRIAGE RETURN
        CALL    CHAROUT
        MVI     A,0AH           ;LINE FEED
        JMP     CHAROUT
;
; SUBROUTINE TO OUTPUT BYTE AS TWO HEX ASCII DIGITS ON CONSOLE.
; INPUT AT (HL).
;
HEXOUTL:                        ;LEADING DIGIT OUTPUT ROUTINE
    IF ZEROSUP                  ;IF LEADING ZERO SUPPRESSION OPTION
        MOV     A,M             ;GET BYTE
        ANI     0F0H            ;ISOLATE HIGH NYBBLE
        JZ      HEXLOW          ;IF ZERO, DONT PRINT IT
    ENDIF ;(ZEROSUP)
HEXOUT:
        MOV     A,M             ;GET BYTE
        RRC                     ;MOVE TO LOW NYBBLE
        RRC
        RRC
        RRC
        ANI     0FH             ;ISOLATE LOW NYBBLE
        ORI     30H             ;MAKE ASCII DIGIT
        CALL    CHAROUT         ;PRINT IT
HEXLOW: MOV     A,M             ;GET BYTE AGAIN
        ANI     0FH             ;ISOLATE LOW NYBBLE
        ORI     30H             ;ASCII AGAIN
        CALL    CHAROUT         ;PRINT 2ND
        RET                     ;DONE
; ROUTINE ENTRY TO PUT OUT A COLON FOLLOWED BY NEXT VALUE FROM TIME.
COLON:  MVI     A,':'           ;GET A COLON
        CALL    CHAROUT         ;PUT IT OUT IN CHAROUT
        DCX     H               ;POINT TO NEXT VALUE TO GO
        JMP     HEXOUT          ;PRINT IT AND RETURN
;
; CONSTANTS.
;
    IF WEEKDAY                  ;FOR DAY OF WEEK OPTION
DAYTAB:
        DB      'SUNMONTUEWEDTHUFRISAT',0  ;DAY OF WEEK TABLE
    ENDIF
;
; WORK AREA.
;
WKPTR   DS      2               ;INPUT SCAN POINTER SAVE AREA
AMPMFLAG DS     1               ;'A' OR 'M' FOR AM/PM OPTION
SAVESP  DS      2               ;SAVE AREA FOR CP/M STACK POINTER
VALUE   EQU     $               ;SAVED TIME VALUE WORK AREA
SECONDS DS      1               ;SECONDS
MINUTES DS      1               ;MINUTES
HOURS   DS      1               ;HOURS
DAYOFWEEK DS    1               ;DAY OF WEEK
DAY     DS      1               ;DAY
MONTH   DS      1               ;MONTH IS LAST THING
        DS      32              ;16-POSITION STACK
STACK:  EQU     $               ;STACK POINTER STARTS HERE
INMAX   DS      1               ;MAXIMUM INPUT SIZE PUT HERE
INLEN   DS      1               ;RETURNED INPUT CHAR COUNT
INBUF   DS      32              ;INPUT BUFFER + ENDING DELIMS
;
        END
