home *** CD-ROM | disk | FTP | other *** search
- PROGRAMS TO HANDLE "DTK" CLOCK/CALENDAR BOARD
- (based on the OKI 5832 clock/calendar chip)
-
- Version 1.10
-
- Richard B. Wales
- July 1989
- Internet mail: wales@CS.UCLA.EDU
- CompuServe: 70521,301
-
-
- (C) Copyright 1989 Richard B. Wales. All Rights Reserved.
- These programs, SAVECLK and READCLK, may be freely copied and distributed
- for commercial or non-commercial use, provided:
-
- (1) the source code is included in any distribution;
- (2) all copyright notices are retained intact; and
- (3) no charge (other than a reasonable copying or communications
- charge) is assessed.
-
- I believe these programs are bug-free. However, I disclaim any and all
- liability for any damages, including incidental or consequential damages,
- which might result from your use of these programs.
-
-
- WHY I WROTE THESE PROGRAMS
-
- My original home computer (a Taiwanese "turbo" XT clone) had a built-in
- clock/calendar on the motherboard. When I upgraded to a 286-based
- motherboard, I lost this feature and had to go buy an outboard clock.
- Since I already had all the serial and parallel ports I needed, I didn't
- want to waste money on an "everything-but-the-kitchen-sink" multifunction
- card. I ended up buying a clock/calendar card by DTK (a Taiwanese com-
- pany specializing in various kinds of PC accessories, most of which come
- with documentation that doesn't identify the company at all).
-
- Two programs came with my new DTK clock card: SETTIME (to set the time
- in both the system and the clock card), and AUTOTIME (to read the time
- from the clock card and set the system time accordingly). I quickly grew
- to dislike these programs. Not only were their user interfaces horrid
- (e.g., SETTIME required you to input the new time in the form HH-MM-SS,
- with minus signs instead of colons; and AUTOTIME cleared the screen even
- if the output was redirected to NUL), but these programs exited via the
- ancient DOS "Int 27" (TSR) call -- leaving the program permanently resi-
- dent in memory for no good reason at all. A further botherance was that,
- no matter what I input for the "seconds" portion of the time, SETTIME
- would always end up resetting the seconds to zero.
-
- Resolving to improve on the DTK software, I studied them via a disassembler
- (to figure out how to interface with the clock card). Additionally, I
- called the manufacturer of the clock/calendar chip (Oki Semiconductor)
- and got a complimentary copy of their IC data book and application notes
- for the "5832" chip which DTK used.
-
- The two programs offered here (SAVECLK and READCLK) are the result of this
- study. As it turned out, the resetting of the "seconds" portion of the
- time to zero is a misfeature of the 5832 chip itself -- not the SETTIME
- program. However, I was able to fashion a kludge that permits the time to
- be stored to within +/- 5 seconds of the actual value.
-
-
- USER INTERFACE TO THE "SAVECLK" AND "READCLK" PROGRAMS
-
- SAVECLK does not contain its own routine to query the user for the date
- and time. Rather, it uses whatever date/time has already been set in the
- system (e.g., via the DOS commands DATE and TIME). After changing the
- system date/time (via DATE and TIME, or any other desired program), simply
- type "SAVECLK" to store the new information in the clock card.
-
- READCLK reads the clock card value and sets the system date/time accordingly.
- You may wish to insert the command "READCLK" into your AUTOEXEC.BAT file.
-
- Due to a hardware design flaw, the DTK card is "frozen" on power-up, and
- remains frozen until you do a READCLK. In order to get around this bug,
- READCLK may be called with a single numeric argument (in the range 1 to 119),
- giving a value in seconds which should be added to the clock. On my system,
- for example, I have the command "READCLK 33" near the start of my AUTOEXEC.BAT
- file -- since it takes about 33 seconds to get to the READCLK command from a
- power-up. This "freezing" also takes place if you hit the "reset" button, but
- it does not happen if you reboot via CTRL-ALT-DEL. However, READCLK checks to
- see whether you are doing a "warm" reboot (by looking at the byte at location
- 0040:0072), and it will skip the resetting of the clock board in such cases.
-
- SAVECLK and READCLK each generates three lines of output. If you wish, you
- may redirect this output to a file, or to NUL.
-
-
- THE DTK CLOCK/CALENDAR CARD
-
- The DTK clock/calendar card consists basically of a 5832 clock chip (with
- a backup battery) and an 8255 programmable peripheral interface (PPI) chip.
- The card responds to the four I/O ports 020Ch through 020Fh, as follows:
-
- 020Ch: clock data port (PPI port A; 4 low-order bits only)
- 020Dh: clock address port (PPI port B; 4 low-order bits only)
- 020Eh: clock control lines (PPI port C; 4 high-order bits only)
- 020Fh: PPI control lines (all 8 bits)
-
- Note that the assignment of the three PPI ports to the various parts of the
- clock chip was more or less arbitrary on DTK's part -- as was the choice of
- the particular block of four consecutive I/O ports.
-
- A detailed description of the 8255 PPI is beyond the scope of these notes.
- However, it may be noted that only three values for the PPI control port
- (020Fh) are useful in this application:
-
- 90h: read from port A (data);
- write to ports B (address) and C (control)
- 80h: write to ports A (data), B (address), and C (control)
- 00h: disable PPI (no access to clock)
-
- The clock control lines are connected to port 020Eh of the PPI as follows:
-
- 80h: select (enable access to) clock
- 40h: "hold" (freeze) clock value for reading
- (also used when writing a new value to clock)
- 20h: enable reading clock's current value
- 10h: enable writing new value to clock
-
- As with the assignment of PPI ports, the assignment of these control lines
- to these particular bits of PPI port C was more or less arbitrary on DTK's
- part.
-
- The data items on the clock chip are addressed as follows; this assignment
- is built into the 5832 chip:
-
- 0Ch: tens digit of year
- 0Bh: units digit of year
- 0Ah: tens digit of month
- 09h: units digit of month
- 08h: tens digit of day (see notes below)
- 07h: units digit of day
- 06h: day of the week
- 05h: tens digit of hour (see notes below)
- 04h: units digit of hour
- 03h: tens digit of minute
- 02h: units digit of minute
- 01h: tens digit of second
- 00h: units digit of second
-
- The "tens digit of hour" data item also contains 12/24-hour and AM/PM info
- in the high-order bits: 08h = 24-hour clock; 04h = 12-hour clock, PM;
- 00h = 12-hour clock, AM. (Only the 24-hour format is used by SAVECLK and
- READCLK.)
-
- The "tens digit of day" data item also contains a high-order bit (04h) if
- the next February will have 29 days instead of 28. This bit may be set at
- any time starting with March 1 of the preceding year; it will remain set
- until February 29 has passed, and is automatically reset on March 1.
-
- The 5832 chip does not store the "century" part of the year. The SAVECLK
- and READCLK programs assume that the year is between 1980 and 2079 -- a
- hopefully safe assumption. :-)
-
- Reading the clock is fairly simple. After setting up some preliminary
- values in the various I/O ports, the program outputs an address to the
- "clock address" port, then reads a value from the "clock data" port. Note
- that the 5832 chip requires up to 6 uS after the address has been specified
- before the data is guaranteed to be readable; this time is expended via a
- wait loop in the program.
-
- While it is possible to "hold" the clock while reading it, an approach that
- works just as well (and which is used in these programs) is to simply read
- the clock starting at the low-order end (i.e., seconds first) -- and then to
- re-read the seconds digit. If the seconds digit has not changed during the
- course of reading, then all is well; otherwise, the clock is read over again.
-
- Writing to the clock requires the use of the "hold" signal, followed by a
- delay of at least 150 uS. Then, each digit is written in turn, followed by
- a "write" signal lasting at least 1 uS. A misfeature of the 5832 causes the
- seconds data to be cleared to zero instead of being set to the value being
- written; this is compensated for to some extent in the SAVECLK and READCLK
- programs by fiddling with the "day of the week" value, as described below.
-
- Only the low-order four bits of each data byte read from or written to the
- clock are significant. When reading from the clock, the four high-order bits
- of each byte are 1's and need to be masked out; when writing, the four high-
- order bits of each byte are simply ignored by the clock.
-
-
- HANDLING OF SECONDS ON THE 5832 CLOCK CHIP
-
- The 5832 chip includes a "seconds" value in its output. However, whenever
- a new value is written to the clock, the "seconds" are -- for reasons known
- only to the designers of the chip -- reset to zero.
-
- After quite a bit of thought, I managed to fabricate an obscure scheme for
- storing a bit more precision in the time value stored in the clock by my
- SAVECLK program. The 5832 chip includes a "day of the week" value, which
- can be set arbitrarily by the software (and which is incremented each day
- by the chip). The 5832 makes no effort to validate the day of the week.
- By storing a bogus "day of the week" value in the chip -- and comparing the
- chip's information (as read later by READCLK) with the true day of the week
- corresponding to the date -- I managed to store a constant multiple of 10
- seconds as a fixed offset to be added to the clock output.
-
- What I do is this: When setting the time in SAVECLK, I use a perpetual cal-
- endar algorithm (courtesy of Martin Gardner) to figure out the true day of
- the week corresponding to the date. I then add to this the number of seconds
- (divided by ten, with the remainder thrown away) in the time. Thus, for
- instance, if the true day of the week is Monday, and the current time to be
- stored in the clock card ends with 10 seconds, I add one to the day and store
- "Tuesday" as the day of the week on the card. For 20 seconds, I would change
- the day from Monday to Wednesday; and so on.
-
- Also, before doing any of the above, I add 5 seconds to the date/time I intend
- to store in the clock card. This means that I leave the day of the week alone
- from 55 through 4 seconds; add one day from 5 through 14 seconds; two days for
- 15-24 seconds; and so on. By doing this, I effectively set the clock card to
- within +/- 5 seconds of the correct time.
-
- When I read the time back in READCLK, I compute the true day of the week for
- the date off of the card, and compare it with the day of the week I read from
- the card. I then multiply the difference (modulo 7, of course) by 10 seconds
- and add that value to the date/time from the clock card.
-
- The clock card uses the seven values 0-6 to represent the day of the week.
- Since the 5832 chip doesn't attempt to validate the day of the week in any
- way, the correspondence between days and numeric values is arbitrary. I chose
- to use the DOS convention (0 = Sunday), for clarity if nothing else.
-
- Note that I couldn't simply store the "tens of seconds" data as a raw figure
- in the "day of the week" slot of the clock -- since this figure gets incre-
- mented every day, and when reading the clock back later on I have no way of
- knowing how many days have elapsed since I last set the time. The only way to
- store this extra data was to make it into an offset relative to the correct
- day of the week.
-
-
- COMPILING THE SOURCE
-
- These programs were compiled with Borland Turbo C 1.5, using the "tiny"
- memory model, and converted to .COM files via EXE2BIN.
-
- I have include .PRJ files for both SAVECLK and READCLK, for compilation under
- Turbo C's integrated environment. Note that the linker will give a warning
- about there not being a "stack" segment; this is an inevitable consequence of
- using the "tiny" memory model, and you may safely ignore the warning.
-
- I have also included the TCCONFIG.TC file I used for these programs. If you
- compile the source yourself, be sure to go into the "Directories" item in the
- "Options" menu and change the various Turbo C directories from the ones I use
- (I installed my Turbo C stuff in C:\MISC\TC15) to the ones you use.
-
-
- KNOWN PROBLEMS
-
- If the clock has not been set at all (e.g., you just replaced the lithium
- battery), READCLK will set your system time to a strange value and will not
- realize anything is wrong.
-
- If you do a CTRL-ALT-DEL reboot, followed later on by a "reset button" reboot
- (without powering the system off), READCLK will think the second reboot was a
- "warm" reboot, and it will not reset the clock board forward by the number of
- seconds given in the argument. I suppose I could fix this by having READCLK
- change the value in 0040:0072 from 34H (the "warm boot" flag) to something
- else, but I didn't want to interfere with anything else in the system that
- might care about this value.