; File: READ_RTC.A51 Date: 07/14/92 ; ; /* (c) Copyright BLUE EARTH RESEARCH, MANKATO, MN 1992. */ ; /* All rights reserved. */ ; $ ERRORPRINT DEBUG XREF TITLE(RTC PROGRAM SUBROUTINES) $ PL(60) PW(93) DATE(07-14-92) ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; RTC PROGRAMS: SET, READ, AND FORMAT THE OUTPUT TO ASCII ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; The following program contains subroutines for setting and ; reading the Real Time Clock (RTC). ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; Reading the Clock: ; The RTC's time registers are read, and the data is stored in ; external memory beginning at address 4200H. The next part of ; the routine puts all of the date and time data into an ASCII ; character string. This was originally written to display the ; data on an LCD, so the actual character string is preceded by ; two bytes which were used to position the cursor on the LCD ; display module. ; The character string must be initialized once by the ; following BASIC statement : CALL 7DD9H ; After that, the clock data can be read and displayed at ; any time by the following BASIC statement : CALL 7D00H ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; Setting the Clock: ; The routine to set the clock assumes that the registers used ; to read the clock contain the values that are to be used to ; set the clock. Once the appropriate data has been stored in ; memory (beginning at address 4200H), the clock can be set by ; executing the following BASIC statement: CALL 7D4BH $ EJECT XSEG AT 4200H SEC1: DS 1 SEC10: DS 1 MIN1: DS 1 MIN10: DS 1 HOUR1: DS 1 HOUR10: DS 1 DAY1: DS 1 DAY10: DS 1 MON1: DS 1 MON10: DS 1 YEAR1: DS 1 YEAR10: DS 1 XSEG AT 4210H POS1: DS 2 ; CURSOR POSITION MON: DS 2 DS 1 DAY: DS 2 DS 1 YEAR: DS 2 DS 1 ; END OF STRING POS2: DS 2 ; CURSOR POSITION HOUR: DS 2 DS 1 MIN: DS 2 DS 1 SEC: DS 2 DS 1 ; END OF STRING TOTAL EQU 12 ; NUMBER OF CLOCK REGISTERS CLOCK EQU 0FE00H PROGRAM_MEMORY BIT 38.4 DSEG AT 18H BYTE_COUNT: DS 1 BYTE_HOLD: DS 1 POINTER: DS 1 POINTER1: DS 1 $ EJECT CSEG AT 07D00H ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; READ THE RTC ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ READ_RTC: MOV POINTER,#0 ACALL HOLD ; OK TO READ LOOP1: MOV DPTR,#CLOCK ; POINT TO REGISTER MOV A,#10H MOV B,POINTER MUL AB MOV DPL,A MOVX A,@DPTR ; GET BYTE ANL A,#0FH ; MASK UNUSED BITS MOV BYTE_HOLD,A ; STORE IT MOV DPTR,#SEC1 ; GET BYTE STORE LOCATION MOV DPL,POINTER MOV A,BYTE_HOLD MOVX @DPTR,A ; WRITE BYTE TO MEMORY INC POINTER ; INCREMENT POINTER MOV A,POINTER CJNE A,#TOTAL,LOOP1 ; WRITE TO MORE REGISTERS ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ RESET HOLD BIT ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ MOV DPTR, #0FED0H ; SET REGISTER D MOV A, #0010B MOVX @DPTR, A ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ MASK AM/PM ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ MOV DPTR,#HOUR10 ; POINT TO AM/PM BIT MOVX A,@DPTR ; GET IT ANL A,#0011B ; MASK OFF AM/PM BIT MOVX @DPTR,A ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ SJMP ASCII_FORMAT ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; HOLD, BUSY ALGORITHM ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; WAIT FOR BUSY TO GO LOW RETRY: MOVX A, @DPTR ANL A, #0FEH MOVX @DPTR, A MOV BYTE_COUNT,#95 DJNZ BYTE_COUNT, $ ; HOLD, BUSY ROUTINE HOLD: MOV DPTR, #0FED0H MOVX A, @DPTR ORL A, #1 BUSY: MOVX @DPTR, A MOVX A, @DPTR ANL A, #02 JNZ RETRY RET $ EJECT ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; SET THE RTC ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ SET_RTC: MOV DPTR,#0FEF0H ; SET REGISTER F MOV A,#0111B ; SELECT 24 HOUR MODE MOVX @DPTR,A MOV DPTR,#0FEE0H ; SET REGISTER E MOV A,#1101B ; NO INTERRUPTS MOVX @DPTR,A MOV POINTER,#0 ACALL HOLD ; OK TO WRITE LOOP: MOV DPTR,#SEC1 ; GET BYTE TO WRITE MOV DPL,POINTER MOVX A,@DPTR MOV BYTE_HOLD,A ; STORE BYTE MOV DPTR,#CLOCK ; POINT TO REGISTER MOV A,#10H MOV B,POINTER MUL AB MOV DPL,A MOV A,BYTE_HOLD MOVX @DPTR, A ; WRITE BYTE INC POINTER ; INCREMENT POINTER MOV A,POINTER CJNE A,#TOTAL,LOOP ; WRITE TO MORE REGISTERS ; SET REGISTER D MOV DPTR, #0FED0H MOV A, #0010B MOVX @DPTR, A ; SET REGISTER F MOV DPTR, #0FEF0H MOV A, #0100B MOVX @DPTR, A RET ; BACK TO BASIC $ EJECT ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; FORMAT THE RTC OUTPUT TO ASCII CHARACTERS ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ PROCESS: ACALL LOOP2 LOOP2: MOV DPL,POINTER MOVX A,@DPTR ; GET THE BYTE ADD A,#30H ; MAKE IT ASCII MOV DPL,POINTER1 MOVX @DPTR,A ; SAVE IT INC POINTER ; BUMP TO OTHER HALF OF NUMBER DEC POINTER1 RET ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ASCII_FORMAT: MOV DPH,#HIGH(SEC1) ; POINT TO BOTH LOCATIONS MOV BYTE_COUNT,#3 ; LOAD NUMBER OF BYTES MOV POINTER,#LOW(SEC1) ; POINT TO RAW NUMBERS MOV POINTER1,#LOW(SEC+1) ; POINT TO FINISHED DATA LOOP3: ACALL PROCESS DEC POINTER1 ; BUMP PAST DELIMITER DJNZ BYTE_COUNT,LOOP3 MOV POINTER,#LOW(YEAR1) ; POINT TO RAW NUMBERS MOV POINTER1,#LOW(YEAR+1) ; POINT TO FINISHED DATA ACALL PROCESS MOV BYTE_COUNT,#2 ; LOAD NUMBER OF BYTES MOV POINTER,#LOW(DAY1) ; POINT TO RAW NUMBERS MOV POINTER1,#LOW(DAY+1) ; POINT TO FINISHED DATA LOOP5: ACALL PROCESS DEC POINTER1 ; BUMP PAST DELIMITER DJNZ BYTE_COUNT,LOOP5 $ EJECT ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; OUTPUT ASCII CHARACTERS ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; OUTPUT A STRING OF CHARACTERS FROM PROGRAM MEMORY. CHARACTER ; STRING IS TERMINATED BY A '"' (22H) IN PROGRAM MEMORY. ; SET BIT 52 (38.4) IN ORDER TO SPECIFY PROGRAM MEMORY. ; BASIC OPBYTE IS 5 FOR STRING OUTPUT (R3:R1 POINT TO IT) ; NOTE: ; The output routines also output the cursor position bytes. ; To output the data and/or time only, replace the program ; labels POS1 and POS2 with MON and HOUR, respectively. ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ OUTPUTTIME: SETB PROGRAM_MEMORY MOV R3,#HIGH(POS2) ; POINT TO CHARACTER STRING MOV R1,#LOW(POS2) MOV A,#5 LCALL 30H OUTPUTDATE: SETB PROGRAM_MEMORY MOV R3,#HIGH(POS1) ; POINT TO CHARACTER STRING MOV R1,#LOW(POS1) MOV A,#5 LJMP 30H $ EJECT ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; INITIALIZE THE ASCII OUTPUT FORMAT ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; FORMAT OUTPUT SO IT APPEARS AS 'nXX/YY/ZZ"' ; WHERE n IS THE CURSOR POSITIONING BYTE ; XX IS THE MONTH ; YY IS THE DATE ; ZZ IS THE YEAR MOV DPTR,#POS1 ; STORE DATE STRING CONSTANTS MOV A,#1BH MOVX @DPTR,A MOV DPTR,#MON+2 MOV A,#'/' MOVX @DPTR,A MOV DPTR,#DAY+2 MOVX @DPTR,A MOV DPTR,#YEAR+2 MOV A,#'"' MOVX @DPTR,A ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; FORMAT OUTPUT SO IT APPEARS AS 'nXX:YY:ZZ"' ; WHERE n IS THE CURSOR POSITIONING BYTE ; XX IS THE HOURS ; YY IS THE MINUTES ; ZZ IS THE SECONDS INC DPTR ; STORE TIME STRING CONSTANTS MOV A,#1BH MOVX @DPTR,A MOV DPTR,#HOUR+2 MOV A,#':' MOVX @DPTR,A MOV DPTR,#MIN+2 MOVX @DPTR,A MOV DPTR,#SEC+2 MOV A,#'"' MOVX @DPTR,A RET ; END OF PROGRAM END ; Following is the HEX file derived from the assembled source ; file. This can be used for directly loading the program via ; MONITOR-51 and almost any terminal program. :107D0000751A00B13E90FE007410851AF0A4F58239 :107D1000E0540FF519904200851A82E519F0051A12 :107D2000E51AB40CE090FED07402F0904205E054E5 :107D300003F08064E054FEF075185FD518FD90FEE6 :107D4000D0E04401F0E0540270EA2290FEF07407A3 :107D5000F090FEE0740DF0751A00B13E904200857F :107D60001A82E0F51990FE007410851AF0A4F582CD :107D7000E519F0051AE51AB40CE290FED07402F091 :107D800090FEF07404F022B189851A82E0243085D7 :107D90001B82F0051A151B22758342751803751A8C :107DA00000751B24B187151BD518F9751A0A751BA8 :107DB00019B187751802751A06751B16B187151B40 :107DC000D518F9D2347B42791B7405120030D234B5 :107DD0007B4279107405020030904210741BF090C1 :107DE0004214742FF0904217F090421A7422F0A3BC :107DF000741BF090421F743AF0904222F09042259A :047E00007422F022D6 :00000001FF