; ******************************************************* ; * * ; * TIME.AZM * ; * * ; * Z80 CP/M Utility for OKI MSM6242 RTC * ; * * ; * John Blalock, July 29, 1985 * ; * * ; ******************************************************* ; MSM6242 EQUATES RTC EQU 0B0H ;BASE ADDRESS OF 6242 CREGD EQU RTC+13 ;CONTROL REGISTER D CREGE EQU RTC+14 ;CONTROL REGISTER E CREGF EQU RTC+15 ;CONTROL REGISTER F HOLD EQU 05H ;HOLD AND IRQ BITS IN CREGD BUSY EQU 02H ;BUSY BIT IN CREGD ADJ30 EQU 0CH ;+/- 30 SEC ADJUST AND IRQ BITS IN CREGD RESET EQU 01H ;RESET BIT IN CREGF MODE12 EQU 00H ;12-HOUR MODE - BIT 2 IN CREGF MODE24 EQU 04H ;24-HOUR MODE - BIT 2 IN CREGF ;CPM EQUATES CPM EQU 0000H ;CP/M WARM BOOT BDOS EQU 0005H ;BDOS ENTRY CONIN EQU 01H ;BDOS CONSOLE INPUT FUNCTION CONOUT EQU 02H ;BDOS CONSOLE OUTPUT FUNCTION PRSTG EQU 09H ;BDOS PRINT STRING ON CONSOLE FUNCTION RBUFF EQU 0AH ;BDOS READ CONSOLE BUFFER FUNCTION CONST EQU 0BH ;BDOS RETURN CONSOLE STATUS FUNCTION CR EQU 0DH ;ASCII CARRIAGE RETURN LF EQU 0AH ;ASCII LINE FEED ORG 0100H START: LD (SPSAVE),SP ;SAVE ENTRY STACK POINTER LD SP,STACK ;INITIALIZE STACK POINTER XOR A ;CLEAR A OUT (CREGE),A ;CLEAR CONTROL REG E OUT (CREGF),A ;CLEAR CONTROL REG F START1: LD DE,TITLE ;CLEAR SCREEN AND PRINT TITLE CALL PRINT LD DE,MENU ;PRINT VERSION AND OPENING MENU CALL PRINT LD C,CONIN ;GET RESPONSE CALL BDOS AND 5FH ;FORCE UPPER CASE CP 'D' ;DISPLAY ? JR Z,DISPLY CP 'A' ;ADJUST ? JP Z,ADJUST CP 'S' ;SET ? JP Z,SET JR START1 DISPLY: CALL CLEAR ;CLEAR SCREEN AND TURN CURSOR OFF LD DE,DSPMSG ;TELL ABOUT CTL-C CALL PRINT DSPLY1: CALL WAKEUP ;GET RTC ACCESS CALL SHOW ;SHOW THE TIME OR A ;ANYTHING TYPED ? JR Z,DSPLY1 ;NO, DISPLAY AGAIN CP 'C'-64 ;CONTROL-C ? JR NZ,DSPLY1 ;NO, DO IT ALL OVER CALL CURTOG ;TURN CURSOR BACK ON CALL CRLF ;SKIP A LINE LD SP,(SPSAVE) ;RESTORE ENTRY STACK POINTER RET ;RETURN TO CP/M ADJUST: CALL CLEAR ;CLEAR SCREEN AND PRINT TITLE LD DE,ADJMSG ;GIVE INFO CALL PRINT ADJ1: CALL WAKEUP ;GET RTC ACCESS CALL SHOW ;SHOW THE TIME OR A ;ANYTHING TYPED ? JR Z,ADJ1 ;NO, DISPLAY AGAIN CP CR ; ? JR NZ,ADJ3 ;NO, SEE IF CTL-C LD A,ADJ30 ;YES, GET +/- 30 SEC ADJUST BIT OUT (CREGD),A ;ADJUST THE TIME LD BC,0 ;LONG DELAY ADJ2: DEC B JR NZ,ADJ2 DEC C JR NZ,ADJ2 JR ADJ1 ;KEEP DISPLAYING ADJ3: CP 'C'-64 ;CONTROL-C ? JR NZ,ADJ1 ;NO, IGNORE CHARACTER CALL CURTOG ;YES,TURN CURSOR BACK ON CALL CRLF ;SKIP A LINE LD SP,(SPSAVE) ;RESTORE ENTRY STACK POINTER RET ;RETURN TO CP/M SET: LD DE,SETMSG ;POINT TO SET MESSAGE CALL PRINT ;PRINT IT LD HL,BUFF ;POINT TO INPUT BUFFER LD A,14 ;"WYYMMDDHHMMSSA"=14 LD (HL),A ;SET BUFFER MAX VALUE EX DE,HL ;PASS BUFFER ADDRESS IN DE LD C,RBUFF ;GET INPUT STRING CALL BDOS LD HL,BUFF+1 ;=> NUMBER OF DIGITS LD A,14 ;SHOULD BE 14 CP (HL) ;IS IT ? JR NZ,SET1 ;NO, ERROR! LD A,(BUFF+15) ;GET MODE & AM/PM FLAG AND 0FH ;REMOVE ASCII BIAS CP 2 ;24-HOUR MODE? JR NZ,SET2 ;NO, MUST BE 12-HOUR MODE LD A,4 ;24-HOUR MODE LD (MODE),A ;SAVE FOR LATER JR SET3 SET1: LD DE,MSG2 ;ERROR MESSAGE CALL PRINT JR SET SET2: LD B,A ;SAVE FLAG IN B LD A,MODE12 ;12-HOUR MODE LD (MODE),A ;SAVE FOR LATER LD A,B OR A ;AM ? JR Z,SET3 ;YES, LEAVE HOURS TENS AS IS LD A,(BUFF+9) ;NO, GET HOUR TENS OR 4 ;SET PM BIT LD (BUFF+9),A ;RESAVE IN BUFFER SET3: LD DE,MSG3 ;READY TO SET ? CALL PRINT LD C,CONIN ;WAIT FOR INPUT CALL BDOS CP 'C'-64 ;ABORT? JP Z,SET ;YES START OVER LD A,(MODE) ;GET MODE OR RESET ;OR IN RESET BIT OUT (CREGF),A ;RESET AND SET MODE EX DE,HL ;SHORT DELAY EX DE,HL LD A,(MODE) ;GET MODE OUT (CREGF),A ;MAKE SURE IT'S SET EX DE,HL ;SHORT DELAY EX DE,HL XOR A ;CLEAR A OUT (CREGF),A ;GET OUT OF RESET CALL WAKEUP ;GET ACCESS TO RTC REGS LD B,13 ;13 REGISTERS TO SET LD C,RTC+12 ;START WITH WEEK REGISTER LD HL,BUFF+2 ;=> POINT TO WEEK DIGIT SET4: LD A,(HL) ;GET DIGIT OUT (C),A ;SET IT INC HL ;POINT TO NEXT DIGIT DEC C ;AND NEXT RTC PORT DEC B ;COUNT THIS ONE JR NZ,SET4 ;LOOP UNTIL ALL 13 ARE DONE XOR A ;CLEAR A OUT (CREGD),A ;CLEAR HOLD BIT JP DISPLY ;SHOW NEW TIME WAKEUP: XOR A ;CLEAR A OUT (CREGD),A ;AND CONTROL REG D LD A,HOLD ;GET HOLD BITS OUT (CREGD),A ;HOLD THE RTC LD C,20 ;BUSY SHOULD GO LOW IN 190 USEC WAKE1: IN A,(CREGD) ;GET CONTROL REG D AND BUSY ;EXTRACT BUSY BIT RET Z ;RETURN IF IT'S AWAKE DEC C ;COUNT THIS TRY JR NZ,WAKE1 ;TRY UNTIL BUSY=0 OR > 190 USEC PASSES JR WAKEUP ;NO RESPONSE, TRY AGAIN - UNDOC 6242 BUG! SHOW: LD HL,BUFF ;POINT TO INPUT BUFFER LD B,13 ;13 REGISTERS TO READ LD C,RTC+12 ;START WITH WEEK REGISTER SHOW1: IN A,(C) ;GET DIGIT LD (HL),A ;SAVE IT INC HL ;POINT TO NEXT DIGIT DEC C ;AND NEXT RTC PORT DEC B ;COUNT THIS ONE JR NZ,SHOW1 ;LOOP UNTIL ALL 13 ARE DONE XOR A ;CLEAR A OUT (CREGD),A ;CLEAR HOLD BIT LD E,CR ;PRINT A CARRIAGE RETURN LD C,CONOUT CALL BDOS LD A,(BUFF) ;GET DAY OF WEEK AND 7 ;MASK OFF EXTRA BITS ADD A,A ;DOUBLE FOR TABLE OFFSET LD E,A ;PUT IN E XOR A ;CLEAR A LD D,A ;AND D LD HL,WKTBL ;BASE OF WEEK TABLE ADD HL,DE ;ADD OFFSET CALL PRHLMS ;PRINT STRING WHOSE ADDRESS HL POINTS TO CALL COMSPC ;PRINT COMMA, SPACE LD A,(BUFF+4) ;GET MONTH UNITS AND 0FH ;MASK OFF EXTRA BITS LD B,A ;SAVE IN B LD A,(BUFF+3) ;GET MONTH TENS AND 1 ;OCT-DEC ? JR Z,SHOW2 ;NO, THEN ADD ZERO LD A,10 ;YES, MUST ADD TEN SHOW2: ADD A,B ;A=MONTH IN BINARY DEC A ;MAKE JAN=0 ADD A,A ;DOUBLE IT FOR TABLE OFFSET LD E,A ;PUT IN E XOR A ;CLEAR A LD D,A ;AND D LD HL,MONTBL ;BASE OF MONTH TABLE ADD HL,DE ;ADD OFFSET CALL PRHLMS ;PRINT STRING WHOSE ADDRESS HL POINTS TO CALL SPACE ;SPACE OVER ONE LD A,(BUFF+5) ;GET TENS OF DAYS AND 3 ;ANY TENS ? JR Z,SHOW3 ;NO, DON'T PRINT CALL PRCHAR ;YES, PRINT SHOW3: LD A,(BUFF+6) ;GET DAYS UNITS CALL PRCHAR ;AND PRINT LD DE,MSG19 ;PRINT ", 19" CALL PRINT LD A,(BUFF+1) ;GET YEARS TENS CALL PRCHAR ;PRINT LD A,(BUFF+2) ;GET YEARS UNITS CALL PRCHAR ;PRINT CALL SPACE ;SPACE OVER TWO PLACES CALL SPACE LD A,(BUFF+7) ;HOURS TENS AND 3 ;MASK OFF AM/PM BIT CALL PRCHAR LD A,(BUFF+8) ;HOURS UNITS CALL PRCHAR CALL COLON ;PRINT A COLON LD A,(BUFF+9) ;MINUTES TENS CALL PRCHAR LD A,(BUFF+10) ;MINUTES UNITS CALL PRCHAR CALL COLON ;PRINT A COLON LD A,(BUFF+11) ;SECONDS TENS CALL PRCHAR LD A,(BUFF+12) ;SECONDS UNITS CALL PRCHAR IN A,(CREGF) ;READ CONTROL REG F AND 4 ;24-HOUR MODE ? JR NZ,SHOW5 ;YES, THEN SKIP AM/PM CALL SPACE ;NO, THEN NEED TO PRINT AM/PM LD E,'a' ;ASSUME AM LD A,(BUFF+7) ;GET HOURS TENS DIGIT AND 4 ;AM OR PM ? JR Z,SHOW4 ;JUMP IF IT'S AM LD E,'p' ;TAKE A "P" IF IT'S PM SHOW4: LD C,CONOUT ;PRINT THE A OR P CALL BDOS LD E,'m' ;NOW PRINT THE M LD C,CONOUT CALL BDOS SHOW5: LD C,CONST ;GET CONSOLE STATUS CALL BDOS OR A ;ANYTHING TYPED ? JR Z,SHOW6 ;NO, RETURN A=0 LD C,CONIN ;YES, GET CHARACTER CALL BDOS SHOW6: PUSH AF ;SAVE FOR RETURN LD DE,SPCMSG ;COVER UP ANY EXTRA CHARACTERS CALL PRINT POP AF ;RETURN CHAR OR 00 IN A RET CLEAR: LD DE,TITLE ;CLEAR THE SCREEN AND PRINT TITLE CALL PRINT CURTOG: LD E,1BH ;ESC LD C,CONOUT CALL BDOS LD E,'.' ;PERIOD LD C,CONOUT JP BDOS PRHLMS: LD A,(HL) ;GET LOW BYTE OF MESSAGE ADDRESS LD E,A ;PASS IN REG E INC HL ;POINT TO HIGH BYTE OF MESSAGE ADDRESS LD A,(HL) ;GET IT LD D,A ;PASS IN REG D JP PRINT ;NOW PRINT IT AND RETURN COLON: LD E,':' ;PRINT A COLON LD C,CONOUT JP BDOS PRCHAR: AND 0FH ;MASK OFF EXTRA BITS OR 30H ;MAKE ASCII LD E,A ;PASS IN REG E LD C,CONOUT JP BDOS COMSPC: LD E,',' ;PRINT A COMMA LD C,CONOUT CALL BDOS SPACE: LD E,' ' ;PRINT A SPACE LD C,CONOUT JP BDOS CRLF: LD DE,CRLFM ;CR/LF MESSAGE PRINT: LD C,PRSTG ;PRINT STRING FUNCTION JP BDOS WKTBL: DW SUNMSG DW MONMSG DW TUEMSG DW WEDMSG DW THUMSG DW FRIMSG DW SATMSG MONTBL: DW JANMSG DW FEBMSG DW MARMSG DW APRMSG DW MAYMSG DW JUNMSG DW JULMSG DW AUGMSG DW SEPMSG DW OCTMSG DW NOVMSG DW DECMSG SUNMSG: DB 'Sunday$' MONMSG: DB 'Monday$' TUEMSG: DB 'Tuesday$' WEDMSG: DB 'Wednesday$' THUMSG: DB 'Thursday$' FRIMSG: DB 'Friday$' SATMSG: DB 'Saturday$' JANMSG: DB 'January$' FEBMSG: DB 'February$' MARMSG: DB 'March$' APRMSG: DB 'April$' MAYMSG: DB 'May$' JUNMSG: DB 'June$' JULMSG: DB 'July$' AUGMSG: DB 'August$' SEPMSG: DB 'September$' OCTMSG: DB 'October$' NOVMSG: DB 'November$' DECMSG: DB 'December$' MSG19: DB ', 19$' SETMSG: DB CR,LF,LF,'Enter setting as "WYYMODDHHMISSA" where',CR,LF,LF DB ' W = day of Week (0=Sunday - 6=Saturday)',CR,LF DB ' YY = last two digits of Year',CR,LF DB ' MO = Month number (01=Jan - 12=Dec)',CR,LF DB ' DD = Day of month (01 - 31)',CR,LF DB ' HH = Hour (01 - 12, or 00-23)',CR,LF DB ' MI = Minute (00 - 59)',CR,LF DB ' SS = Second (00 - 59)',CR,LF DB ' F = Mode and am/pm flag',CR,LF DB ' (0=AM, 1=PM, 2=24-hour mode)',CR,LF,LF DB ' WYYMODDHHMISSF',CR,LF DB 'What setting do you want ? $' MSG2: DB 7,CR,LF,'INVALID ENTRY!',CR,LF,LF,'$' MSG3: DB CR,LF,'Enter Ctl-C to start over, ' DB 'any other key to set the time: $' CRLFM: DB CR,LF,'$' TITLE: DB 1AH,'John Blalock''s OKI MSM6242 Real Time Clock Utility $' MENU: DB ' 7/29/85 Version',CR,LF,LF,LF DB 'Do you want to Set, Display, or Adjust the time? ' DB '(S/D/A) : $' ADJMSG: DB CR,LF,LF,'Enter to adjust time to nearest minute. ' DB 'Enter Ctl-C to exit.',CR,LF,LF,'$' DSPMSG: DB CR,LF,LF,'Enter Ctl-C to exit.',CR,LF,LF,'$' SPCMSG: DB ' $' MODE: DB 1 SPSAVE: DS 2 BUFF: DS 16 STACK EQU $+30 END