M EQU Byte Ptr 0[BX] ;**************************************************** ; * ; TEST ROUTINES FOR THE SYSTEM SUPPORT 1 * ; REAL TIME CLOCK * ; * ;**************************************************** ;this program assumes that the System Support 1 is addressed ;to the block of ports at 50H, to change to a different address, ;change BASE in equates. BASE EQU 50H ;BASE PORT ADDRESS CLKCMD EQU BASE+10 ;CLOCK COMMAND PORT CLKDATA EQU BASE+11 ;CLOCK DATA PORT BDOS EQU 0005H ;BDOS CALL ADDRESS READ EQU 10H ;READ BIT PATTERN WRITE EQU 20H ;WRITE BIT PATTERN (+HOLD) HOLD EQU 40H ;HOLD BIT PATTERN CSEG ; ORG 100H ;this is the main loop that prints the sign-on message, decides ;what command has been entered and executes that particular routine. ; MOV SP,(Offset STACK) ;SET THE STACK POINTER START: MOV DX,(Offset SIGNON) ;PRINT SIGNON MESSAGE CALL PMSG ;PRINT IT CALL GETCHAR ;GET COMMAND CHARACTER CMP AL,'X' ;IF X JNZ L_1 MOV CL,0 ;THEN RESTART SYSTEM MOV DL,0 INT 224 L_1: CMP AL,'S' ;IF S JZ SETTIME ;THEN SET TIME CMP AL,'P' ;IF P JNZ L_2 JMP PTIME ;THEN PRINT THE TIME L_2: CMP AL,'C' ;IF C JNZ L_3 JMP FOREVER ;THEN PRINT TIME FOREVER L_3: MOV DX,(Offset ERROR) ;NONE OF THE ABOVE CALL PMSG ;PRINT ERROR MESSAGE JMPS START ;AND TRY AGAIN ;this routine sets up HL to point to a table to receive the digits ;to be written to the clock. DE contains the pointer to the table ;of address values that correspond to the desired digit. The table ;is organized in the proper order for reading and writing. The ;routine gets the digits from the console and puts them into memory ;and then writes them to the clock. SETTIME:CALL GETTIME ;GET THE DATE AND TIME DATA MOV BX,(Offset DTABLE) ;H GETS DIGIT TABLE ADDRESS MOV DX,(Offset ATABLE) ;D GETS ADDRESS TABLE MOV CH,13 ;NUMBER OF DIGITS TO WRITE +1 MOV AL,HOLD ;SET HOLD BIT OUT CLKCMD,AL ;AND WRITE IT OUT SET1: DEC CH ;DECREMENT DIGIT COUNT JNZ HERE ;SKIP THIS NEXT BIT IF NOT DONE MOV AL,0 ;CLEAR A OUT CLKCMD,AL ;CLEAR HOLD BIT MOV DX,(Offset TIMEIS) ;SHOW THAT THE TIME IS NOW: CALL PMSG ;WHATEVER CALL CLKPRNT ;PRINT THE STUFF JMPS START ;WE'RE DONE HERE: MOV AL,M ;GET THE DIGIT INTO A MOV CL,AL ;AND PUT IT IN C MOV SI,DX ;GET THE COMMAND IN A MOV AL,[SI] CALL WRTDGT ;WRITE THE DIGIT LAHF ;NEXT INC BX SAHF LAHF ;AND NEXT INC DX SAHF JMPS SET1 ;AND CONTINUE ;this is the routine that gets the digits from the console and ;stores them into memory at the address pointed to by HL. GETTIME:MOV DX,(Offset ASKTIME) ;PROMPT TIME INPUT CALL PMSG MOV BX,(Offset DTABLE) ;ADDRESS TO PUT DIGITS GET1: CALL GETNUMB ;GET DIGIT CMP AL,0DH ;IS IT A CR? JZ GETDATE ;YES, GET THE DATE AND AL,0FH ;CONVERT TO BCD MOV M,AL ;OTHERWISE, PUT THE DIGIT IN MEMORY INC BX ;INCREMENT THE TABLE ADDRESS JMPS GET1 ;GET THE NEXT DIGIT GETDATE:MOV DX,(Offset ASKDATE) CALL PMSG GET2: CALL GETNUMB CMP AL,0DH ;IS IT A CR? JNZ L_4 RET ;YES, RETURN L_4: AND AL,0FH ;CONVERT TO BCD MOV M,AL ;PUT DIGIT IN MEMORY INC BX JMPS GET2 ;this routine gets a character from the console, and checks the ;input for either a carriage return or a valid digit between 0-9 ;will not return until a CR or valid digit is typed. GETNUMB:CALL GETCHAR ;GET A CHARACTER CMP AL,0DH ;IS IT A CR? JNZ L_5 RET L_5: CMP AL,'0' JB GETNUMB CMP AL,'9'+1 JNB GETNUMB RET ;this routine writes the digit to the clock, and checks to ;see if it's the hours or days 10 digit and sets the 24 hour ;and leap year bits accordingly. This routine is called with ;digit address in A and the digit to be written in C. WRTDGT: ;SAVE THE COMMAND PUSH AX ADD AL,HOLD ;ADD IN THE HOLD BIT OUT CLKCMD,AL ;AND OUTPUT IT CMP AL,5+HOLD ;WAS IT THE HOURS 10 DIGIT? JNZ WRT1 ;NO MOV AL,CL ;OTHERWISE GET THE DIGIT ADD AL,08H ;AND SET 24 HOUR MODE JMPS WRT3 WRT1: CMP AL,8+HOLD ;WAS IT THE DAYS 10 DIGIT JNZ WRT2 ;NO MOV AL,CL ;OTHERWISE GET THE DIGIT AND AL,03H ;AND SET NON-LEAP YEAR MODE JMPS WRT3 WRT2: MOV AL,CL ;PUT THE DIGIT IN A WRT3: OUT CLKDATA,AL ;AND OUTPUT IT POP AX ;GET THE COMMAND BACK ADD AL,WRITE+HOLD ;ADD IN THE WRITE AND HOLD BITS OUT CLKCMD,AL ;SEND IT OUT SUB AL,WRITE ;CLEAR THE WRITE BIT OUT CLKCMD,AL ;AND SEND IT RET ;NOW WE'RE DONE ;this routine reads a digit from the clock and masks the leap year ;and AM/PM/24 hour mode bits. This routine is called with the digit ;address in A and returns with the digit value in A RDDGT: ADD AL,READ ;ADD IN THE READ BIT OUT CLKCMD,AL ;AND OUTPUT IT CMP AL,05H+READ ;WAS IT THE HOURS 10 DIGIT IN AL,CLKDATA ; GET THE DIGIT JZ L_6 RET ;IF IT WASN'T, WE'RE DONE L_6: SUB AL,08H ;IF IT WAS, THEN KILL 24 HOUR BIT RET ;AND THEN RETURN ;this routine prints the current time and date once and returns ;(complete with colons and slashes) CLKPRNT:MOV BX,(Offset ATABLE) ;GET THE TABLE ADDRESS IN HL CALL PRINTWO ;PRINT THE FIRST TWO DIGITS MOV AL,':' CALL PCHAR CALL PRINTWO ;PRINT THE NEXT TWO DIGITS MOV AL,':' CALL PCHAR CALL PRINTWO ;PRINT THE NEXT TWO DIGITS MOV AL,' ' CALL PCHAR ;PRINT TWO SPACES MOV AL,' ' CALL PCHAR CALL PRINTWO ;PRINT TWO MORE DIGITS MOV AL,'/' ;PRINT A SLASH CALL PCHAR CALL PRINTWO MOV AL,'/' CALL PCHAR CALL PRINTWO ;PRINT THE LAST TWO DIGITS RET ;WE'RE DONE ;this routine prints two digits from the clock. It is called with ;the digit address of the first digit in HL. Exits with HL pointing ;to the address of the next two digits. PRINTWO:MOV AL,M ;GET THE ADDRESS FROM TABLE CALL RDDGT ;READ THE DIGIT ADD AL,30H ;CONVERT TO ASCII CALL PCHAR ;AND PRINT IT INC BX ;INCREMENT THE POINTER MOV AL,M ;GET THE NEXT ADDRESS CALL RDDGT ADD AL,30H CALL PCHAR INC BX RET ;this routine prints the time once and jumps back to the main loop PTIME: MOV DX,(Offset TIMEIS) ;PRINT "THE TIME IS -" CALL PMSG CALL CLKPRNT ;AND PRINT THE TIME AND DATE JMP START ;AND RESTART ;this routine prints the time forever (unless a CNTL C is typed) ;it continually reads the seconds 1 digit and waits for it to ;change before printing the time. FOREVER:MOV AL,0AH ;LINE FEED CALL PCHAR ;SEND IT FOR1: MOV AL,0DH ;CARRIAGE RETURN CALL PCHAR ;SEND IT CALL CLKPRNT ;PRINT THE TIME MOV AL,0 ;ADDRESS OF SECONDS DIGIT CALL RDDGT ;READ THE SECONDS DIGIT MOV CH,AL ;SAVE IT IN B FOR2: MOV AL,0 CALL RDDGT ;READ IT AGAIN CMP AL,CH ;COMPARE IT TO THE ONE WE JUST READ JZ FOR2 ;LOOP IF IT'S THE SAME JMPS FOR1 ;OTHERWISE PRINT IT AGAIN ;CP/M CALLS AND UTILITIES ;this routine gets a character from the console, converts it to ;uppercase, strips off the parity and checks for CNTL C GETCHAR:PUSH BX ;SAVE HL MOV CL,01 ;CHARACTER IN FUNCTION INT 224 POP BX CMP AL,'a' ;RANGE CHECK FOR UPPER CASE JB SKIP ;CONVERSION CMP AL,'z'+1 ; JNB SKIP AND AL,5FH ;CONVERT TO UPPER CASE SKIP: AND AL,7FH ;AND STRIP PARITY CMP AL,03H ;IS IT A CNTL C? JNZ L_7 MOV CL,0 ;YES, RESTART SYSTEM MOV DL,0 INT 224 L_7: RET ;OTHERWISE WE'RE DONE ;this routine prints a character on the console and checks ;to see if any characters were entered while printing. PCHAR: PUSH DX ;SAVE D REGISTER MOV DL,AL ;CHARACTER TO PRINT IN E MOV CL,02H ;CHARACTER OUT FUNCTION PUSH BX ;SAVE HL INT 224 MOV CL,0BH ;CONSOLE STATUS CHECK INT 224 ;SEE IF A CHARACTER WAS TYPED POP BX POP DX OR AL,AL ;SET THE FLAGS JZ L_8 CALL GETCHAR ;IF A CHARACTER WAS TYPED, GO GET IT L_8: RET ;OR RETURN ;this routine prints the string pointed to by DE until a $ is ;encountered. Should be called with DE pointing to start of string. PMSG: PUSH BX MOV CL,09H ;PSTRING FUNCTION INT 224 POP BX RET ;L_9 EQU $ DSEG ORG 100H ;MESSAGES SIGNON DB 0DH,0AH,0DH,0AH,'TIME AND DATE TEST ROUTINES FOR ' DB 'SYSTEM SUPPORT 1',0DH,0AH,0DH,0AH DB 'PLEASE TYPE ONE OF THE FOLLOWING COMMANDS:',0DH,0AH DB 'S - SET THE TIME AND DATE',0DH,0AH DB 'P - PRINT THE TIME AND DATE ONCE',0DH,0AH DB 'C - CONTINUOUSLY PRINT THE TIME AND DATE',0DH,0AH DB 'X - EXIT TO OPERATING SYSTEM',0DH,0AH DB 0DH,0AH,'COMMAND: $' ERROR DB 0DH,0AH,'THAT WAS NOT ONE OF THE ABOVE COMMANDS' DB 0DH,0AH,'PLEASE TRY AGAIN $' ASKTIME DB 0DH,0AH,'WHAT IS THE TIME? (24 HOUR FORMAT - HH:MM:SS) $' ASKDATE DB 0DH,0AH,'WHAT IS THE DATE? (MM/DD/YY) $' TIMEIS DB 0DH,0AH,'THE TIME AND DATE ARE: $' ;DIGIT ADDRESS TABLE ;this table contains the "address" values that are sent in the ;command byte in the following order: Hours 10, Hours 1, Min 10, ;Min 1, Sec 10, Sec 1, Month 10, Month 1, Days 10, Days 1, Years 10 ;Years 1. ATABLE DB 5,4,3,2,1,0,0AH,9,8,7,0CH,0BH ;this is the area which gets the digits as they are entered from the ;console. DTABLE RS 12 ;this is the area for the stack ; RS 32 ;FOR 16 LEVEL STACK ; STACK RS 0