home *** CD-ROM | disk | FTP | other *** search
- include mmclock.mac
- title MM58167A time routines -- Copyright 1990 Wales
-
- ; ======================================================================
- ;
- ; Time routines for the MM58167A clock/calendar.
- ; (C) Copyright 1990 Richard B. Wales. All Rights Reserved.
- ;
- ; Global variables:
- ;
- ; bcd2bin
- ; A translation table which maps BCD values into binary.
- ;
- ; bin2bcd
- ; A translation table which maps binary values into BCD.
- ;
- ; Global routines:
- ;
- ; GetTime
- ; Reads the real-time clock.
- ;
- ; SetTime
- ; Sets the real-time clock.
-
- ; ======================================================================
- ;
- ; Global symbols.
-
- public GetTime, SetTime, bcd2bin, bin2bcd
-
- ; ======================================================================
- ;
- ; XLAT table for converting BCD to binary.
- ; NOTE: This table is only long enough for valid input values.
-
- bcd2bin:
- TENS=0
- rept 10
- UNITS=0
- rept 10
- db (10*TENS) + UNITS
- UNITS=UNITS+1
- endm
- if TENS LT 9
- db 6 dup (255)
- endif
- TENS=TENS+1
- endm
-
- ; ======================================================================
- ;
- ; XLAT table for converting binary to BCD.
- ; NOTE: This table is only long enough for valid input values.
-
- bin2bcd:
- TENS=0
- rept 10
- UNITS=0
- rept 10
- db (16*TENS) + UNITS
- UNITS=UNITS+1
- endm
- TENS=TENS+1
- endm
-
- ; ======================================================================
- ;
- ; GetTime
- ;
- ; Read the time-of-day info from the clock.
- ;
- ; Arguments:
- ;
- ; DX Should be set to the initial I/O port address
- ; for the clock.
- ;
- ; Returned values:
- ;
- ; CH Hours (0-23).
- ; CL Minutes (0-59).
- ; DH Seconds (0-59).
- ; DL Hundredths of a second (0-99).
-
- GetTime proc near
-
- ; Set up the loop count.
- mov cx, MAX_RETRIES
-
- ; We'll skip the milliseconds position in the counter.
- inc dx
-
- read_again:
- ; Read the counter info from the clock. Finish up by re-reading
- ; the 1/100 second info and comparing it with the value originally
- ; read from this position. The 1/100 second position must be read
- ; first, and must therefore be read via a byte-sized IN, since
- ; some AT-clones don't read the ports in IBM-compatible (lower
- ; port first) order.
- mov bp, cx ; save loop counter
- INBR bl ; 1/100 seconds (save in BL)
- inc dx
- INBR bh ; seconds (save in BH)
- inc dx
- INWR cx ; hours/minutes (save in CX)
- dec dx
- dec dx ; back to start of counter
- INBR al ; re-read 1/100 second
- cmp al, bl ; compare with saved value
- jne short read_ticked ; if changed, try again
- mov dx, bx ; move seconds to right place
-
- ; Convert everything from BCD to straight binary.
- INIT_DS
- mov bx, offset bcd2bin
- XLATCK cx, cx, 23, 59, bad_read ; hours/minutes
- XLATCK dx, dx, 59, 99, bad_read ; seconds
- ret
-
- read_ticked:
- ; The counter rolled over while we were reading it. Try again.
- mov cx, bp ; restore loop counter
- loop short read_again
-
- bad_read:
- ; In case of failure, return "midnight".
- xor cx, cx
- xor dx, dx
- ret
-
- GetTime endp
-
- ; ======================================================================
- ;
- ; SetTime
- ;
- ; Write the time-of-day info to the clock.
- ;
- ; Arguments:
- ;
- ; CH Hours (0-23).
- ; CL Minutes (0-59).
- ; DH Seconds (0-59).
- ; DL Hundredths of a second (0-99).
- ; BP Should be set to the initial I/O port address
- ; for the clock.
- ;
- ; Returned values:
- ;
- ; None.
-
- SetTime proc near
-
- ; Validate the input and convert from BCD to binary.
- INIT_DS
- mov bx, offset bin2bcd
- CKXLAT cx, si, 23, 59, bad_write
- CKXLAT dx, di, 59, 99, bad_write
-
- ; Write the counter info to the clock. Finish up by re-reading
- ; the first counter byte (1/100 second) and making sure it has
- ; not changed.
- mov dx, bp ; I/O port
- mov cx, MAX_RETRIES ; loop count
- write_again:
- xor ax, ax ; 1/1000 second (always zero)
- OUTBR al
- inc dx
- OUTWR di ; seconds and 1/100 second (DI)
- inc dx
- inc dx
- OUTWR si ; hours and minutes (SI)
- dec dx
- dec dx ; back to 1/100 second position
- mov ax, di
- INBR al ; re-read 1/100 second
- dec dx ; back to 1/1000 second position
- cmp ax, di ; 1/100 sec should be unchanged;
- jnz short write_ticked ; if not, try again
- ret
-
- write_ticked:
- ; The counter rolled over while we were writing. Try again.
- loop short write_again
-
- bad_write:
- ret
-
- SetTime endp
-
- code ends
-
- end