; ; CP/M Time-of-day Program ; ; v1.08 12/22/82 WGW Changed name of program to TIME.COM ; v1.07 11/12/82 WGW Correct values for get/settime ; v1.06 11/10/82 WGW Changed help message to fit on EC8800 ; v1.05 9/20/82 WGW Get number of days via gettime ; v1.04 7/01/82 WGW Correct noon time (12 PM) ; v1.03 6/07/82 WGW Correct get character routine ; v1.02 5/27/82 WGW Check validity of time, regular/military time ; v1.01 5/21/82 WGW Set time of day ; v1.00 5/20/82 WGW Read time of day (original version) ; version equ 1 revision equ 8 month equ 12 day equ 22 year equ 82 cpm equ 0 bdos equ 5 fcb1 equ 5ch ; location of first fcb parsed by ccp fcb2 equ 6ch ; location of second fcb filename equ 1 ; offset into fcb fileextension equ filename+8 ; offset into fcb parameter1a equ fcb1+filename parameter1b equ fcb1+fileextension parameter2a equ fcb2+filename parameter2b equ fcb2+fileextension tpa equ 100h beep equ 7 cr equ 13 lf equ 10 endmsg equ '$' regulartime equ 0 militarytime equ 0ffh uppercase equ 5fh displaychar equ ' ' ; character indicating display tod repeatchar equ 'P' ; character indicating repeat mode militarychar equ 'M' ; character indicating military tod maxhours equ 24h ; 24 hours morning equ maxhours/2 noon equ 12h midnight equ 0 maxminutes equ 60h ; 60 minutes readconsole equ 1 ; bdos function calls getconsole equ 6 printstring equ 9 consolestatus equ 11 settime equ 104 readtime equ 105 readclock equ 155 org tpa jmp start signon: db cr,lf db 'Time-of-day Program WGW V' db (version/10)+'0' db (version mod 10)+'0' db '.' db (revision/10)+'0' db (revision mod 10)+'0' db ' ' db (month/10)+'0' db (month mod 10)+'0' db '/' db (day/10)+'0' db (day mod 10)+'0' db '/' db (year/10)+'0' db (year mod 10)+'0' db endmsg displaytype: db regulartime ; default display type ; ; --- Main part of program ----------- ; start: lxi sp,stack ; use internal stack call main ; perform main program lxi d,crlfmsg call print1 jmp cpm ; exit main: lda parameter1a ; a := first char of first parameter call isdigit ; see if a digit is entered jz settod ; see if the time is to be set cpi militarychar ; check for military time jnz checkdisplaytype mvi a,militarytime ; set display type to military time sta displaytype lda parameter2a ; a := first char of second parameter checkdisplaytype: cpi displaychar ; check for print one time display jz printtime cpi repeatchar ; check for repeat time display jz repeatprinttime lxi d,signon ; otherwise print signon call print lxi d,helpmsg ; and print format message print: call print1 ; print string printcrlf: lxi d,crlfmsg ; begin a new line print1: mvi c,printstring jmp bdos helpmsg: db 'The following display the time-of-day:',cr,lf db cr,lf db 'TIME Prints normal time',cr,lf db 'TIME M Prints military time',cr,lf db cr,lf db 'The following display the time-of-day',cr,lf db ' until a key is pressed:',cr,lf db cr,lf db 'TIME P Prints normal time',cr,lf db 'TIME M P Prints military time',cr,lf db cr,lf db 'The following set the time-of-day:',cr,lf db cr,lf db 'TIME hh.mm Set military time',cr,lf db 'TIME hh.mm AM Set normal time (morning)',cr,lf db 'TIME hh.mm PM Set normal time (evening)',cr,lf db ' when a key is pressed.',cr,lf db endmsg printtime: ; print time-of-day lxi d,timeismsg ; print 'time is' call print1 lxi d,tod ; read the tod clock mvi c,readclock call bdos call converttime lxi d,timemsg ; print the time call print1 call ismilitary ; see if military time display cnz printampm lxi d,crmsg ; print trailing cr jmp print1 printampm: call getampm ; get right letter mov a,l ; a := am/pm character sta ampm ; update message lxi d,ampmmsg ; print am/pm message jmp print1 getampm: mvi l,'P' ; l := possible result lda todhours ; a := hours cpi morning ; see if it is the morning rnc ; exit if in the evening mvi l,'A' ret converttime: lda todhours ; convert to ascii and display call converthourscheck ; check the hours call makeascii shld msghours lda todminutes call makeascii shld msgminutes lda todseconds call makeascii shld msgseconds ret converthourscheck: mov b,a ; b := hours (BCD) call ismilitary ; see if it is military time mov a,b ; a := hours (BCD) rz ; exit if military time ora a ; check for midnight mvi a,12h ; return 12 if midnight rz ; exit if midnight mov a,b ; a := hours (BCD) cpi morning+1 ; check if evening rc ; exit if in morning adi 88h ; subtract 12 hours daa ; make BCD ret ismilitary: lda displaytype ; a := displaytype cpi militarytime ; return zero if military time ret repeatprinttime: ; print tod until character entered call printtime mvi c,consolestatus ; get console status call bdos ora a jz repeatprinttime ; loop until done if no character typed getchr: mvi c,consolestatus ; get console status call bdos ora a jz getchr ; wait until character entered mvi e,0ffh ; e := get character mvi c,getconsole ; get the character jmp bdos ; and exit settod: ; set time-of-day lxi d,tod ; get time-of-day to set days mvi c,readtime call bdos lhld parameter1a ; get hours xchg ; de := parameter call makebcdblank ; convert to bcd, possible leading ' ' cpi 0ffh ; check for entry errors jz seterror call checkhours ; check for range error jnc seterror ; jump if greater or equal to limit sta todhours lhld parameter1b ; get minutes xchg ; de := parameter call makebcd ; convert to bcd cpi 0ffh ; check for entry errors jz seterror cpi maxminutes ; check for range error jnc seterror ; jump if greater or equal to limit sta todminutes lxi d,startmsg ; print waiting to set time message call print1 call getchr ; get a character call printcrlf lxi d,tod ; set time-of-day mvi c,settime call bdos jmp printtime ; print the time just set checkhours: mov b,a ; b := hours (BCD) lda parameter2a ; a := first char of second parameter cpi 'P' ; see if it is PM jz checkhourspm cpi 'A' ; see if it is AM jz checkhoursam cpi ' ' ; see if it is military time (default) jz checkhoursmilitary ora a ; no carry indicates an error ret checkhoursmilitary: mov a,b ; a := hours (BCD) cpi maxhours ; check max hours ret checkhourspm: mov a,b ; a := hours (BCD) ora a ; see if it is zero rz ; return with no carry if zero adi morning ; convert to PM hours daa ; make BCD cpi maxhours ; check max hours rnz ; return in not midnight mvi a,noon ; return a := 12h if noon stc ; set carry to indicate it is ok ret checkhoursam: mov a,b ; a := hours (BCD) ora a ; see if it is zero rz ; return with no carry if zero cpi morning ; check max hours rnc ; exit if ok (1 to 11 am) cpi 12h ; see if it is 12 am rnc ; exit if not 12 am (error) sub a ; a := 0 (12 midnight) stc ; set carry to indicate it is ok ret startmsg: db cr,lf db 'Enter any key to set time of day',endmsg seterrormsg: db 'Invalid time-of-day format',endmsg seterror: lxi d,seterrormsg ; print error message call error lxi d,helpmemsg ; print how-to-get-help message jmp print helpmemsg: db cr,lf db 'Enter the following to get more information:',cr,lf db cr,lf db 'TIME ?',endmsg error: push d ; save error message index lxi d,errorprefix ; print error prefix call print1 pop d call print1 ; print error message lxi d,errorsuffix ; print error suffix jmp print errorprefix: db cr,lf db '*** ',endmsg errorsuffix: db ' ***',beep,endmsg isdigit: ; returns zero if A is an ascii digit mov c,a ; c := character push b ; save it call isdigit1 ; check digit pop b ; restore character, return zero flag mov a,c ret isdigit1: cpi '0' ; is is less than a '0' jc returnff cpi '9'+1 jnc returnff ; is it greater than a '9' return0: sub a ; a := 0, zero = true ret returnff: mvi a,0ffh ; a := 0ffh, zero = false ora a ret makebcdblank: ; a := bcd value of de (ls, ms), ls can = ' ' mov a,d ; a := ls ascii digit cpi ' ' ; see if it is a blank jnz makebcd ; convert if already a digit mov d,e ; shift right one digit mvi e,'0' ; set in a leading zero makebcd: ; a := bcd value of de (ls, ms) mov a,e ; a := ms ascii digit call isdigit ; see if it is a digit rnz ; exit if it is not mov a,e ; restore ms ascii digit ral ; shift into upper nibble ral ral ral ani 0f0h ; a (ms nibble) := bcd part of ms ascii digit mov e,a ; save it mov a,d ; a := ls ascii digit call isdigit ; see if this is a digit too rnz mov a,d ; restore ls ascii digit ani 0fh ; a (ls nibble) := bcd part of ls ascii digit ora e ; a := result ret makeascii: push psw call makedigit mov h,a ; h := ls digit (remember, msb stored last) pop psw rrc rrc rrc rrc ; a (ls nibble) := ms nibble call makedigit mov l,a ; hl := two ascii digits ret makedigit: ani 0fh ; a := ls nibble adi '0' ; convert to a digit ret tod: dw 0 todhours: db 0 todminutes: db 0 todseconds: db 0 timeismsg: db 'The time is ',endmsg timemsg: ; displays time msghours: db '00.' msgminutes: db '00.' msgseconds: db '00',endmsg ampmmsg: db ' ' ampm: db ' M',endmsg crmsg: db cr,endmsg crlfmsg: db cr,lf,endmsg ds 256 ; internal stack stack: end