You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

323 lines
9.4 KiB

;:::::::::::::::::::::::::::::::::::::::***************************
; Time-handling Routines ** Machine-Dependant **
; D-X Designs Pty Ltd, P112 ***************************
;
; This module incorporates provisions for an interrupt-driven clock, or
; the Dallas DS-1202 Real Time Clock for obtaining Time and Date Info.
;
; 1.0 - 18 Jul 96 - Initial Release. HFB
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; This code module should handle all Time-related segments, to include
; Interrupt handlers for Real Time update, motor timeouts, user down-
; counter and any necessary time format conversion routines.
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; TIMER
; This routine keeps the Real Time Clock, Diskette Time Out
; counter, and General-Purpose down-counters. An interrupt is
; generated every 50 mS by the Z-182 Programmable Interrupt Timer
; and used to update parameters. Every other interrupt (100 mS
; intervals) is used to update the 100 mS counters and Time string
; if using Interrupt-driven Time and Date.
; Enter: No parameters needed (Interrupt)
; Exit : None
; Uses : None. All registers preserved. Decrements MTM, User and BIOS
; general-purpose counter bytes every 100 mS.
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
CSEG
; Come here every 50 milliseconds from Programmable Reload Timer 0
TIMER: DI ; Don't Interrupt from here
LD (TIMSTK),SP ; Save entry Stack Pointer
LD SP,TIMSTK ; ..set up Local Interrupt Stack
PUSH HL
PUSH AF ; Save the registers
IN0 A,(TCR)
IN0 A,(TMDR0L)
IN0 A,(TMDR0H) ; Clear the interrupt
LD HL,FLAG50 ; Point to 50 mS Flag
LD A,(HL) ; fetch
XOR 01H ; and toggle LSB
LD (HL),A ; Re-save
JR NZ,TDONE ; ..exit if Odd 50 mS Tick
LD HL,DCNTR ; Adjust User GP Down-Counter
DEC (HL)
LD HL,MTM ; Adjust Bios GP Down-Counter
DEC (HL)
INC HL ; Point to Motor On-timer (MOTIM)
LD A,(HL)
OR A ; Already Timed Out?
JR Z,TIMER0 ; ..jump if So
DEC (HL) ; Else count down
CALL Z,MOTOFF ; turning Motors Off if timed out
TIMER0:
; Adjust the Interrupt-driven Real Clock (if no Real Time Clock exists).
; This "Clock" maintains Date and Time in a DateStamper(C) compatible
; string per ZSDOS specifications.
IF CLOCK AND [NOT DS1202]
LD HL,TENTHS ; 100ms counter
INC (HL) ; Bump Tenths-of-Seconds
LD A,(HL) ; get the value
SUB 10 ; Subtract limit value (in decimal times 2)
JR NZ,TDONE ; jump to exit if no rollover
LD (HL),A ; Else save a zero
DEC HL ; back down time string
LD A,(HL) ; Get Seconds
INC A ; bump
DAA ; in BCD
LD (HL),A ; and save
SUB 60H ; Subtract limit value
JR NZ,TDONE ; ..jump to exit if no rollover
LD (HL),A ; Else save a zero
DEC HL ; back down time string
LD A,(HL) ; Get Minutes
INC A ; bump
DAA ; in BCD
LD (HL),A ; and save
SUB 60H ; Subtract limit value
JR NZ,TDONE ; ..jump to exit if no rollover
LD (HL),A ; Else save a zero
DEC HL ; back down time string
LD A,(HL) ; Get Hours
INC A ; bump
DAA ; in BCD
LD (HL),A ; and save
SUB 24H ; Subtract limit value
JR NZ,TDONE ; ..jump to exit if no rollover
LD (HL),A ; Else save a zero
DEC HL ; back down time string
LD A,(HL) ; Get Day
INC A ; bump
DAA ; in BCD
LD (HL),A ; and save
PUSH DE ; Save regs
PUSH AF
EX DE,HL
LD HL,DPM-1 ; Point to days per month table indexed base 1
DEC DE ; back up to Months byte
LD A,(DE)
INC DE ; move ptr back
CP 10 ; >Sept?
JR C,TIMER1 ; ..jump if Not
SUB 6 ; Else convert BCD to binary
TIMER1: CALL ADDAHL ; Offset into table based on Month
POP AF ; Get current day count
CP (HL) ; Time for new month?
EX DE,HL ; (put regs back)
POP DE
JR C,TDONE ; ..exit here if not time
LD (HL),1 ; Else start out on first of month
DEC HL ; back down to month
LD A,(HL) ; Get month
INC A ; Bump
DAA ; in BCD
LD (HL),A ; and save
SUB 13H ; Time for new year?
JR C,TDONE ; ..exit if not
LD (HL),1 ; Else start at month 1 (Jan)
DEC HL ; back up to Years byte
LD A,(HL) ; Get Year
INC A ; bump
DAA ; in BCD
LD (HL),A ; and save
SUB 99H ; Time for next century?
JR NZ,TDONE ; ..exit if not
LD (HL),A ; Else save 0 year
ENDIF ;Clock & Not DS1202
TDONE: POP AF
POP HL ; Restore registers
LD SP,(TIMSTK) ; and Stack Pointer
; EI ; allow Ints again
RET
IF CLOCK AND [NOT DS1202] ; Table of Days-per-Month
DPM: DEFB 31H+1, 28H+1, 31H+1 ; January, February, March
DEFB 30H+1, 31H+1, 30H+1 ; April, May, June
DEFB 31H+1, 31H+1, 30H+1 ; July, August, September
DEFB 31H+1, 30H+1, 31H+1 ; October, November, December
ENDIF ;Clock & Not Ds1202
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; TIME - Set or Return the time string as defined for ZSDOS. If Reading,
; The Six digit BCD ZSDOS Clock string is copied to the location
; addressed by Register pair DE. As an enhancement, the tenths-of-seconds
; value is returned in Reg D. If Setting the Clock, the RTC clock string
; will be set from the 6 bytes addressed by DE.
;
; ENTER: C - 0 to Read the Clock, Non-0 (1 recommended) to Set the Clock
; DE = Pointer to receive 6-byte Time/Date on Read, Source for Set
;
; EXIT : E = Original contents of Target Seconds field
; D = Tenths of Seconds field
; HL = Pointer to Target Seconds field
; A = 1 for success, 0 if Unable to Set or Read
; BC = Address of User General-Purpose Down-Counter
;
; NOTE: The Wall Clock string is arranged as BCD digits with Tenths-
; of-Seconds byte appended. The entire string is:
;
; YR MO DA HH MM SS TT
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
IF CLOCK AND DS1202
IF SIMHCLK
SIMHPORT EQU 0FEH
READCLOCK EQU 7
WRITECLOCK EQU 8
PARBLOCKSIZE EQU 6
TIME:
EX DE,HL ; GET DE TO HL
LD A,C
OR A
JR NZ,WRCLK
;
GETTIM: LD A,READCLOCK
OUT (SIMHPORT),A
LD BC,256*(PARBLOCKSIZE-1)+SIMHPORT ; B := 5, C := 0FEH
INIR
LD E,(HL) ; Save original seconds in E
INI ; READ SECONDS
DEC HL
LD A,1 ; Set OK status return
LD BC,DCNTR ; Get Address of User Down-Counter
RET
;
WRCLK: LD A,WRITECLOCK
OUT (SIMHPORT),A
LD A,L
OUT (SIMHPORT),A
LD A,H
OUT (SIMHPORT),A
LD A,1
LD BC,DCNTR ; Get Address of User Down-Counter
RET
ENDIF ; SIMHCLK
IF HBCLK
TIME:
LD A,C
OR A
JR NZ,WRCLK
;
RDCLK:
PUSH DE ; Save the final destination
LD HL,TIMBUF ; Point HL to temp buf
LD B,20H ; HBIOS function to read RTC
CALL HBX_INVOKE ; Do it
LD HL,TIMBUF ; Setup HL as source
POP DE ; And recover final destination
LD BC,5 ; Copy first 5 bytes
LDIR ; Do it
LD A,(DE) ; Now get the original seconds value to A
INC BC ; Setup to copy last byte, BC := 1
LDIR ; Do it
EX DE,HL ; Set HL to seconds dest for return
DEC HL ; Decrement to point back at seconds value
LD D,0 ; Tenths is always zero
LD E,A ; Get original seconds value
LD BC,DCNTR ; BC must point to countdown timer on return
LD A,1 ; Signal success
RET
;
WRCLK:
EX DE,HL ; Make incoming DE the copy source in HL
LD DE,TIMBUF ; We are copying to time buffer
LD BC,6 ; For 6 bytes
LDIR ; Do it, time buffer now ready
LD HL,TIMBUF ; Point to time buffer
LD B,21H ; Set clock function
CALL HBX_INVOKE ; Do it via HBIOS
LD BC,DCNTR ; BC must point to countdown timer on return
LD A,1 ; Signal success
RET
ENDIF ; HBCLK
ENDIF ;Clock & Ds1202
JP ISTRUE ; Handle fall thru if no clock driver
IF HBCLK
TIMBUF DEFS 6
ENDIF
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
IF CLOCK AND [NOT DS1202] ; Not Dallas, make Intrpt Code
TIME: LD A,C ; Get Clock Operation Flag
LD BC,5 ; and set up for ZSDOS Read/Write
LD HL,YEAR ; Pointing to Clock String
OR A ; Is it a Read?
JR Z,TIMES ; ..jump it so
EX DE,HL ; Else swap pointers for write
TIMES: DI ; disable Interrupts
LDIR ; and move 5 bytes of 6 bytes (.1 Sec = 7)
LD C,(HL) ; Get the Seconds byte
INC HL ; bump to 1/10th Seconds
LD H,(HL) ; and Get
; EI ; Re-enable Interrupts
EX DE,HL ; Swap pointers
LD E,(HL) ; Preserve original Sec field contents in E
LD (HL),C ; and store the Seconds byte (.1 Sec in D)
LD BC,DCNTR ; Get Address of User Down-Counter
LD A,01 ; Set Ok exit value of 1
RET
ENDIF ;Clock & Not Ds1202
IF NOT CLOCK ; If No Clock..
XOR A ; Set Error Return
RET ; and exit
ELSE
DSEG
; Real Time Clock Buffer
IF NOT DS1202 ; Don't need this if D-X Designs P112
YEAR: DEFS 1 ; Year - packed BCD
DEFS 1 ; Month - packed BCD
DEFS 1 ; Day - packed BCD
DEFS 1 ; Hour - packed BCD
DEFS 1 ; Minute - packed BCD
DEFS 1 ; Seconds - packed BCD
TENTHS: DEFS 1 ; Tenths of Seconds - Binary (Int, else..)
ENDIF
ENDIF ;Clock
;.....
; Save some space in the Common RAM Area for a local stack
DSEG
DCNTR: DEFS 1 ; User 100 mS General-Purpose Down-Counter
FLAG50: DEFS 1 ; Flag for dividing 50mS to 100mS ticks
DEFS 12 ; We use 6 levels of stack (worst case)
TIMSTK: DEFS 2 ; Store the entry Stack pointer here
CSEG ; End up by restoring CSEG
;=========================== END of TIM-DX ==================================