; Program in 8080 assembly language to read real-time-clock located ; at ports 30h through 33h in Morrow MD 2/3 rev. 2 main board ; Mike Allen 8/16/86 ; CLS EQU 'Z'-40H ;^Z TO CLEAR SCREEN CONBUF EQU 80H PA EQU 30H ;REAL-TIME-CLOCK PORT A PB EQU 31H ;REAL-TIME-CLOCK PORT B PC EQU 32H ;REAL-TIME-CLOCK PORT C CNTRL EQU 33H ;REAL-TIME-CLOCK CONTROL PORT BDOS EQU 5 ;BDOS CALL VECTOR WBOOT EQU 0 ;BDOS WARM BOOT CODE CONOUT EQU 2 ;BDOS CONSOLE CHARACTER OUT CODE PRTSTR EQU 9 ;BDOS CONSOLE STRING OUT CODE RCONBF: EQU 0AH ;BDOS READ CONSOLE BUFFER CODE CONSTAT EQU 0BH ;BDOS CONSOLE STATUS CODE ORG 100H MVI E,CLS ;CLEAR THE SCREEN MVI C,CONOUT CALL BDOS MVI A,090H ;SET UP 8255 OUT CNTRL MVI A,020H ;PUT MSM5832 IN READ MODE OUT PC LOOP: LXI D,RTC ;START OF REAL-TIME-CLOCK BUFFER MVI A,0 ;FIRST MSM5832 ADDRESS LOOP1: MOV B,A ;SAVE CURRENT ADDRESS OUT PB ;SEND ADDRESS TO MSM5832 NOP ;WAIT A WHILE NOP NOP NOP IN PA ;GET DATA FROM MSM5832 ANI 0FH ;MASK OFF 4 MSB STAX D ;SAVE IT IN BUFFER INX D ;INCREMENT BUFFER POINTER MOV A,B ;GET LATEST ADDRESS INR A ;INCREMENT IT CPI 13 ;GOT ALL THE DATA? JNZ LOOP1 ;NOPE, SO REPEAT IT MVI A,0H ;DONE - TURN OFF THE MSM5832 READ OUT PC LDA RTC+5 ;CHECK FOR 24HR, AM OR PM MVI B,0 CPI 8 ;CHECK FOR 24HR JP SETFLG ;YEP, FINISH IT INR B CPI 4 ;CHECK FOR PM JM SETFLG ;NOPE, IS AM INR B ;YEP, IT IS PM SETFLG: ANI 3 ;STRIP OFF 24HR AND PM BITS STA RTC+5 ;SAVE IT MOV A,B ;GET FLAG STA FLAG ;SAVE IT YRIN: LXI D,YRMSG ;PRINT THE YEAR PROMPT CALL MSGOUT LDA RTC+12 ;AND PRESENT VALUE CALL PRTNUM LDA RTC+11 CALL PRTNUM CALL FINLN ;FINISH THE PROMPT LINE LDA RTC+12 ;MAKE YEARS A BCD NUMBER RLC RLC RLC RLC ANI 0F0H MOV B,A LDA RTC+11 ORA B CALL RDNUM ;GET THE NEW VALUE INR A ;CHECK ERROR FLAG ORA A JZ YRIN DCR A PUSH PSW ;SAVE RETURN VALUE RRC RRC RRC RRC ANI 0FH ;GET 10S OF YEARS STA RTC+12 ;SAVE IT POP PSW ;RECOVER VALUE ANI 0FH ;GET 1S OF YEARS STA RTC+11 ;SAVE THEM TOO. LYIN: LXI D,LYMSG ;SEND LEAP YEAR PROMPT CALL MSGOUT LDA RTC+8 RRC RRC ANI 0FH STA LYFLAG ;SAVE CURRENT VALUE CALL PRTNUM ;SHOW CURRENT VALUE CALL FINLN ;FINISH PROMPT LDA LYFLAG ;GET PRESENT VALUE FOR DEFAULT CALL RDNUM ;GET NEW VALUE INR A ;CHECK FOR ERROR JZ LYIN DCR A CPI 0 ;CANNOT BE LESS THAN ZERO JM LYIN CPI 2 ;NOR GREATER THAN 1 JP LYIN RLC RLC ANI 4 ;PUT IN PROPER BIT LOCATION STA LYFLAG ;SAVE IT FOR LATER MOIN: LXI D,MOMSG ;SEND OUT MONTH PROMPT CALL MSGOUT LDA RTC+10 ;SHOW PRESENT VALUE CALL PNZNUM LDA RTC+9 CALL PRTNUM CALL FINLN ;FINISH THE PROMPT LDA RTC+10 ;MAKE BCD VALUE OF MONTHS FOR DEFAULT RLC RLC RLC RLC ANI 0F0H MOV B,A LDA RTC+9 ORA B CALL RDNUM ;GET NEW VALUE INR A ;CHECK FOR ERROR JZ MOIN DCR A CPI 1 ;CANNOT BE LESS THAN 1 JM MOIN CPI 13H ;OR MORE THAN 12 JP MOIN PUSH PSW RRC RRC RRC RRC ANI 0FH STA RTC+10 ;SAVE 10S OF MONTHS POP PSW AIN 0FH STA RTC+9 ;SAVE 1S OF MONTHS DAYIN: LXI D,DAYMSG ;SEND DAY PROMPT CALL MSGOUT LDA RTC+8 ;SEND CURRENT VALUE ANI 3 CALL PNZNUM LDA RTC+7 CALL PRTNUM CALL FINLN ;FINISH PROMPT LDA RTC+8 ;MAKE BCD DAYS FOR PROMPT RLC RLC RLC RLC ANI 30H MOV B,A LDA RTC+7 ORA B CALL RDNUM ;GET NEW NUMBER INR A ;CHECK FOR ERROR JZ DAYIN DCR A CPI 1 ;NOT LESS THAN 1 JM DAYIN CPI 32H ;NO MORE THAN 31 JP DAYIN PUSH PSW ;SAVE WORD RRC RRC RRC RRC ANI 3 ;MAKE DAYS X10 MOV B,A LDA LYFLAG ;GET LEAP YEAR ORA B ;OR IN 10S OF DAYS STA RTC+8 ;SAVE WHOLE THING POP PSW ;RECOVER WORD ANI 0FH ;GET 1S OF DAYS STA RTC+7 ;SAVE 1S OF DAYS DOWIN: LXI D,DOWMSG ;SEND DAY-OF-WEEK PROMPT CALL MSGOUT LDA RTC+6 ;SHOW CURRENT VALUE CALL PRTNUM CALL FINLN ;FINISH PROPMT LDA RTC+6 ;GET FOR DEFAULT CALL RDNUM ;GET NEW VALUE INR A ;CHECK FOR ERROR JZ DOWIN DCR A CPI 0 ;NOT LESDS THAN ZER0 JM DOWIN CPI 7 ;OR GREATER THAN 6 JP DOWIN STA RTC+6 ;SAVE DAY OF WEEK CTIN: LXI D,CTMSG ;SEND CIVIL TIME PROMPT CALL MSGOUT LDA FLAG ;SHOW PRESENT VALUE CALL PRTNUM CALL FINLN ;FINISH PROMPT LDA FLAG ;GET OLD VALUE FOR DEFAULT CALL RDNUM ;GET NEW VALUE INR A ;CHECK FOR ERROR JZ CTIN DCR A CPI 0 ;NOT LESS THAN ZERO JM CTIN CPI 3 ;NOR GREATER THAN 2 JP CTIN STA FLAG ORA A JZ HRIN ;IF 24 HR TIME, NO NEED TO ADJUST HRS LDA RTC+5 ;GET HRS X10 ADD A ;X2 MOV B,A ;SAVE X2 FOR LATER ADD A ;X4 ADD A ;X8 ADD B ;X10 MOV B,A ;SAVE IT LDA RTC+4 ;GET HRS X1 ADD B ;TOTAL HRS IN BINARY! JNZ HICHCK ;WELL, IT'S NOT ZERO MVI A,1 STA RTC+5 MVI A,2 STA RTC+4 ;ZERO HOURS IS 12 HRS IN CIVILIAN TIME JMP HRIN HICHCK: CPI 13 ;13 O'CLOCK IS A NONO IN CIVILIAN TIME JM HRIN SUI 12 ;MAKE IT LEGAL MVI B,0 ;INITIALIZE 10S COUNTER DVLOOP: INR B SUI 10 JP DVLOOP DCR B ADI 10 STA RTC+4 ;A HAS 1S OF HOURS MOV A,B STA RTC+5 ;B HAS 10S OF HOURS HRIN: LXI D,HRMSG ;SEND HR PROMPT CALL MSGOUT LDA RTC+5 ;SHOW CURRENT VALUE CALL PNZNUM LDA RTC+4 CALL PRTNUM CALL FINLN ;FINISH PROMPT LDA RTC+5 ;SAVE HOURS FOR DEFAULT RLC RLC RLC RLC ANI 0F0H MOV B,A LDA RTC+4 ORA B CALL RDNUM ;GET NEW VALUE CPI 0 ;LESS THAN ZERO IS ALWAYS BAD JM HRIN CPI 24H ;24 OR MORE IS ALWAYS BAD JP HRIN PUSH PSW ;SAVE ENTERED VALUE LDA FLAG ;CHECK FOR 24HR TIME ORA A JZ HROUT POP PSW ;12 HR TIME, CHECK AGAIN CPI 1 ;NOTHING LESS THAN 1 JM HRIN CPI 13H ;NOR MORE THAN 12 JP HRIN PUSH PSW HROUT: POP PSW ;GET WORD BACK MOV B,A ;SAVE IT ANI 0FH STA RTC+4 ;SAVE HRS X1 MOV A,B RRC RRC RRC RRC ANI 3 ;GET HRS X10 PUSH PSW ;SAVE IT FOR LATER MVI A,2 ;START FLAG AT 24HR MOV B,A LDA FLAG ;CHECK FOR 24 HR ORA A JZ NEWFLG DCR B ;FLAG AT PM CPI 2 ;CHECK FOR PM JZ NEWFLG DCR B ;MUST BE AM NEWFLG: MOV A,B ;PUT FLAG BITS IN PROPER LOCATION RLC RLC ANI 0CH MOV B,A POP PSW ;RECOVER HRS X10 ORA B ;PUT IN THE FLAG BITS STA RTC+5 ;SAVE HRS X10 AND FLAGS MININ: LXI D,MINMSG ;SEND OUT MINUTES PROMPT CALL MSGOUT LDA RTC+3 ;AND CURRENT VALUE CALL PNZNUM LDA RTC+2 CALL PRTNUM CALL FINLN ;FINISH THE PROMPT LDA RTC+3 ;MADE BCD MINUTES FOR DEFAULT RLC RLC RLC RLC ANI 0F0H MOV B,A LDA RTC+2 ORA B CALL RDNUM ;GET NEW VALUE INR A JZ MININ ;ERROR? DCR A CPI 0 JM MININ ;NOT LESS THAN 0 CPI 60H JP MININ ;NOR MORE THAN 59 PUSH PSW ;SAVE NEW VALUE RRC RRC RRC RRC ANI 0FH ;GET MIN X10 STA RTC+3 ;SAVE IT POP PSW ANI 0FH ;GEN MIN X1 STA RTC+2 ;SAVE IT TOO LXI D,GOPRMT CALL MSGOUT GOLOOP: MVI C,CONSTAT CALL BDOS ORA A JZ GOLOOP MVI A,080H ;SET UP 8255 OUT CNTRL MVI A,010H ;TURN ON HOLD OUT PC MVI A,50 ;WAIT A LONG TIME WLOOP: DCR A JNZ WLOOP LXI D,RTC ;START OF REAL-TIME-CLOCK BUFFER MVI A,0 ;FIRST MSM5832 ADDRESS OLOOP1: MOV B,A ;SAVE CURRENT ADDRESS OUT PB ;SEND ADDRESS TO MSM5832 NOP ;WAIT A WHILE NOP NOP NOP LDAX D ;GET DATA FROM BUFFER ANI 0FH ;MASK OFF 4 MSB OUT PA ;SEND DATA TO MSM5832 MVI A,50H ;STROBE THE WRITE LINE OUT PC MVI A,10H OUT PC INX D ;INCREMENT BUFFER POINTER MOV A,B ;GET LATEST ADDRESS INR A ;INCREMENT IT CPI 13 ;SENT ALL THE DATA? JNZ OLOOP1 ;NOPE, SO REPEAT IT MVI A,0H ;DONE - TURN OFF THE MSM5832 READ OUT PC MVI A,90H ;RESTORE THE 8255 OUT CNTRL MVI C,WBOOT ;WARM BOOT CALL BDOS PNZNUM: ORA A RZ ;DON'T PRINT A '0' PRTNUM: ADI '0' ;MAKE NUMER ASCII MOV E,A ;GET READY TO PRINT MVI C,CONOUT JMP BDOS ;LET BDOS SUPPLY THE 'RET' FINLN: LXI D,ENDMSG MSGOUT: MVI C,PRTSTR JMP BDOS RDNUM: STA BCDNUM ;SAVE DEFAULT MVI A,80 STA CONBUF LXI D,CONBUF ;READ THE CONSOLE BUFFER MVI C,RCONBF CALL BDOS LDA CONBUF+1 ;CHECK STRING LENGTH ORA A JNZ BIGCHK ;SOMETHING THERE, SEE IF TOO LONG LDA BCDNUM ;NOTHING THERE, RETURN DEFAULT JMP INDONE BIGCHK: CPI 3 ;NO MORE THAN 2 CHARACTERS ALLOWED JP INERR LDA CONBUF+2 ;GET THE 1ST CHARACTER CPI '0' ;LESS THAN '0' IS AN ERROR JM INERR CPI '9'+1 ;GREATER THAN '9' IS AN ERROR JP INERR SUI 30H ;REAL ASCII NUMBER, MAKE INTO INTEGER STA NEWIN ;SAVE IT FOR LATER LDA CONBUF+1 ;IS THERE A SECOND CHARACTER? CPI 2 JZ TWOIN ;GO GET IT LDA NEWIN ;ONLY ONE CHARACTER - RETURN IT JMP INDONE TWOIN: LDA CONBUF+3 ;GET THE 2ND CHARACTER CPI '0' ;LESS THAN '0' IS AN ERROR JM INERR CPI '9'+1 ;GREATER THAN '9' IS AN ERROR JP INERR SUI 30H ;REAL ASCII NUMBER, MAKE INTO INTEGER MOV B,A ;SAVE IT LDA NEWIN RLC RLC RLC RLC ;PUT IN TOP 4 BITS ANI 0F0H ;MAKE SURE BOTTOM IS CLEAR ORA B ;BRING BACK ONES DIGIT JMP INDONE ;DONE INERR: MVI A,0FFH ;ERROR FLAG INDONE: PUSH PSW LXI D,LF CALL MSGOUT POP PSW RET YRMSG: DB 'Year? <$' LYMSG: DB 'Leap Year? [1=yes] <$' MOMSG: DB 'Month? <$' DAYMSG: DB 'Day? <$' DOWMSG: DB 'Day of the week? [0=Sunday, 6=Saturday] <$' CTMSG: DB '24 hr[0], AM[1] or PM[2]? <$' HRMSG: DB 'Hours? <$' MINMSG: DB 'Minutes? <$' GOPRMT: DB 'Press RETURN to start clock on the minute$' ENDMSG: DB '> $' CRLF: DB 0DH LF: DB 0AH,'$' BCDNUM: DS 1 NEWIN: DS 1 FLAG: DS 1 LYFLAG: DS 1 RTC: DS 13 END