;************************************************************************ ; ; Version 2.3 Fixed buffer pointer to year to properly ; increment and update YEAR latch at new year. ; ; Included .Z80 pseudo-op for Microsoft M80 ; assembler. ; ; Chan Webb -- October 20, 1987 ; ;************************************************************************ ; ; Version 2.1 Fixed days table to include Tuesday and indexing ; offset into days table. ; ; Richard Jacobson June 30, 1987 ; ;************************************************************************ ; ; Version 2.0 Fixed stack set-up error, moved stack and string ; buffers to DSEG at end, print "1987" rather than ; "'87", broke out console output stuff to subroutines ; and formatted as ZCPR33 type 3 COMfile. Will still ; work on non-Z33/BGii systems if linked at 100H (use ; ZT0100.COM, ZT8000.COM is linked at 8000H and is for ; for ZCPR33 or BGii - 1.13 or later - only). ; ; Bruce Morgen @11:01:11 June 25, 1987 ; ;************************************************************************ ;* * ;* Written by Fred Maxwell and released into the * ;* public domain in January of 1987. Do whatever * ;* you want with it, but please give credit where * ;* credit is due. * ;* * ;* ZTIME.MAC - This program reads the time from the Kenmore * ;* Computer Technologies Ztime-I calendar/clock for * ;* Z80 based systems. It is assumed that the clock * ;* is addressed to I/O address E0h. If not, edit * ;* this source file and change BASE to the address * ;* that you have your clock addressed to. There * ;* has been no attempt to optimize this program * ;* due to its inherently small size and fast speed. * ;* It was written with legibility in mind. To * ;* compile this program, use Z80ASM or Z80ASMP(+) * ;* from SLR systems. This is THE BEST Z80 assembler * ;* available and it's from a company that is still * ;* actively supporting CP/M users. Let's support * ;* them by buying their products. * ;* * ;* This program will print the date out as * ;* shown below: * ;* * ;* Sunday January 18, '87 07:43:26 * ;* * ;* * * * * * * * * SPECIAL FEATURE * * * * * * * * * ;* * ;* This program will keep the year correct as long * ;* as it is run at least once every 5 months. It * ;* does this by storing the year in a latch in the * ;* 58167 clock chip. It also stores the month in * ;* another latch. When the time is read, the * ;* current month is compared to the month stored * ;* in the latch. If the current month number is * ;* lower than the month number in the latch, the * ;* year is incremented by one and stored back in * ;* the latch. * ;* * ;************************************************************************ .Z80 BASE EQU 0E0H ; This is the base address of the 58167. SEC EQU BASE+02H ; Second counter. MIN EQU BASE+03H ; Minute counter. HOUR EQU BASE+04H ; Hour counter. DAY EQU BASE+05H ; Day of week counter. DATE EQU BASE+06H ; Date of month counter. MONTH EQU BASE+07H ; Month counter. YEAR EQU BASE+09H ; 11s latch where we store year. PRVMON EQU BASE+0FH ; Month on last clock access. BDOS EQU 00005H ; Address of BDOS entry point. ZTIME: JP START DB 'Z3ENV',3 DW 00 DW ZTIME DAYS: ; 7 Days x 12 bytes per day (84 bytes). DB 'Sunday $ ' DB 'Monday $ ' DB 'Tuesday $ ' DB 'Wednesday $' DB 'Thursday $ ' DB 'Friday $ ' DB 'Saturday $ ' MONTHS: ; 12 months x 11 bytes per month (132 bytes). DB 'January $ ' DB 'February $ ' DB 'March $ ' DB 'April $ ' DB 'May $ ' DB 'June $ ' DB 'July $ ' DB 'August $ ' DB 'September $' DB 'October $ ' DB 'November $ ' DB 'December $ ' SEPARATER: DB ', 19$' ; Between day of month and year. SPACES: DB ' - $' ; Between date and time. CRLF: DB 0DH,0AH,'$' ; Carriage Return, Linefeed. START: LD (STACK),SP LD SP,STACK ; Use internal stack. CALL CRLFST LD HL,BUFFER ; ----> Date buffer (7 bytes) CALL RDCLOK ; Get date & time into buffer in packed BCD. DAY_PRINT: LD A,(HL) ; Get day number into INC HL ; Point to month PUSH HL DEC A ; 0 = Sunday, 1 = Monday, ..., 6 = Saturday. LD B,A ; = day x 1 ADD A,A ; X 2 ADD A,A ; X 4 ADD A,B ; X 5 ADD A,A ; X 10 ADD A,B ; X 11 ADD A,B ; X 12 LD E,A ; = Day x 12 = offset into day name table. LD D,0 ; = Offset LD HL,DAYS ; points to table of days. ADD HL,DE ; points to name of day. EX DE,HL ; points to name of day. CALL BPSTR MONTH_PRINT: POP HL ; Get pointer to month. XOR A ; Zero accumulator. LD B,A ; Zero register . RLD ; Get tens digit. JR Z,BINARY ; It's less than 10 if digit is 0 LD B,10 ; Add this to low nibble to make binary. BINARY: RLD ; Get ones digit into . ADD A,B ; Add tens digit. INC HL ; Point to date. PUSH HL ; Save pointer LD B,A ; Save Packed BCD month number. DEC A ; 0 = Jan., 1 = Feb, ..., 11 = Dec. LD B,A ; = month x 1 ADD A,A ; X 2 ADD A,A ; X 4 ADD A,B ; X 5 ADD A,A ; X 10 ADD A,B ; X 11 LD E,A ; = Day x 11 = offset into month table. LD D,0 ; = Offset LD HL,MONTHS ; points to table of months. ADD HL,DE ; points to name of month. EX DE,HL ; points to name of month. CALL BPSTR DATE_PRINT: POP HL ; Get pointer to date (packed BCD). LD A,(HL) ; Get packed BCD into . INC HL ; Point to year. PUSH HL ; Save pointer. CALL BCD_PRINT ; Print 2 digits of date. LD DE,SEPARATER ; Print ', 19'. CALL BPSTR YEAR_PRINT: POP HL ; Get pointer to year (packed BCD). LD A,(HL) ; Get packed BCD into . INC HL ; Point to hour. PUSH HL ; Save pointer. CALL BCD_PRINT ; Print 2 digits of year. LD DE,SPACES ; Print " " (3 spaces). CALL BPSTR HOUR_PRINT: POP HL ; Get pointer to hour (packed BCD). LD A,(HL) ; Get packed BCD into . INC HL ; Point to minutes PUSH HL ; Save pointer. CALL BCD_PRINT ; Print 2 digits of date. LD E,':' ; Print ":" (colon). CALL BPCHAR MIN_PRINT: POP HL ; Get pointer to minutes (packed BCD). LD A,(HL) ; Get packed BCD into . INC HL ; Point to seconds. PUSH HL ; Save pointer. CALL BCD_PRINT ; Print 2 digits of minutes. LD E,'.' ; Print ":" (colon). CALL BPCHAR SEC_PRINT: POP HL ; Get pointer to seconds (packed BCD). LD A,(HL) ; Get packed BCD into . CALL BCD_PRINT ; Print 2 digits of seconds. LD DE,CRLF ; Print CR,LF CALL BPSTR LD SP,(STACK) ; Restore it. RET ; All done. ;************************************************************************ ;* * ;* BCD_PRINT - this subroutine prints the two digit packed * ;* BCD number in to the console. * ;* * ;* ON ENTRY: contains packed BCD number. * ;* * ;* ON EXIT: All registers to be considered trashed. * ;* * ;************************************************************************ BCD_PRINT: PUSH AF ; Save packed BCD number SRL A ; Get tens digit in low nibble... SRL A ; And high nibble zeroed. SRL A SRL A ADD A,030H ; Make it ASCII. LD E,A CALL BPCHAR POP AF ; Get packed BCD back in . AND 0FH ; Strip tens digit. ADD A,030H ; Make ASCII. LD E,A JP BPCHAR ; RET ; All done. ;************************************************************************ ;* * ;* RDCLOK - This routine reads the day (1-7), year (00-99), * ;* month (1-12), date (1-31), hours (0-23), minutes * ;* (0-59), and seconds (0-59). These values are * ;* returned as packed BCD in a buffer pointed to * ;* by in the format: * ;* * ;* BYTE CONTENTS * ;* ---- -------- * ;* 1 Day * ;* 2 Month * ;* 3 Date * ;* 4 Year * ;* 5 Hours * ;* 6 Minutes * ;* 7 Seconds * ;* * ;* NOTE: Since the year is stored in a static location in * ;* the clock, it is incremented whenever the current * ;* month is less than the previous month (also stored * ;* in a static location in the clock). * ;* * ;* ON ENTRY: points to buffer. * ;* * ;* ON EXIT : points to buffer. * ;* * ;* NOTE: The seconds are read at the beginning and end of the * ;* clock read. They must be the same to guarantee * ;* that the clock hasn't changed during the read. The * ;* status bit which indicates roll-over is basically * ;* worthless, since the clock can roll over between * ;* reading minutes and hours without ever setting the * ;* bit. This can lead to times like 11:00:00 when it * ;* really just turned to 12 o'clock. * ;* * ;************************************************************************ RDCLOK: PUSH HL ; Save address of buffer. IN A,(SEC) ; Read seconds first and verify LD E,A ; That they don't change. LD C,DAY ; Get the day first. INI ; Read it and store in buffer. LD C,MONTH ; Now read the month into buffer. INI LD C,DATE ; Read date into buffer. INI LD C,YEAR ; Point to the year. INI ; Read it into the buffer. LD C,HOUR ; Now, read the hour. INI LD C,MIN ; Read minutes into buffer. INI IN A,(SEC) ; And finally, read seconds. CP E ; Did clock change during read? JR Z,AOK ; We're OK if seconds match. POP HL ; Restore buffer address. JR RDCLOK ; Try again. AOK: LD (HL),A ; Store seconds in buffer. ; Now, adjust the year if current month is less than month at last ; clock read. POP HL ; HL=start buffer address. PUSH HL INC HL ; Point to month storage. IN A,(PRVMON) ; Month at last clock read. LD B,A ; = Previous Month LD A,(HL) ; = Current Month OUT (PRVMON),A ; Update previous month storage. CP B ; Is Current < Previous? JR NC,DONE ; If not, we're done. INC HL INC HL ; Point back to year storage. LD A,(HL) ; = Year. ADD A,1 ; Year <-- Year + 1 DAA ; Adjust for packed BCD. LD (HL),A ; Store Year. OUT (YEAR),A ; In chip, too. DONE: POP HL ; Restore pointer to buffer. RET ; All done. BPCHAR: LD C,2 JR BDJP CRLFST: LD DE,CRLF BPSTR: LD C,9 BDJP: JP BDOS DSEG BUFFER: DS 7 ; Storage for date and time in packed BCD. DS 30 ; 15 level stack. STACK: DS 2 END