home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
sysutl
/
dtkclk11.arc
/
DTKCLOCK.DOC
< prev
next >
Wrap
Text File
|
1989-07-10
|
13KB
|
258 lines
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.