home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
sysutl
/
dtkclk11.arc
/
WRITE.C
< prev
Wrap
Text File
|
1989-07-07
|
5KB
|
188 lines
/*
* Routines to write to the DTK clock/calendar board.
* (C) Copyright 1989 Richard B. Wales. All Rights Reserved.
*/
#include "clkdefs.h"
/*
* WRITE_CLOCK
* Writes a date/time stamp to the clock board.
* An approximation (to within +/- 5 seconds) of the "seconds" value
* is represented by offsetting the "day of the week" written to the
* clock. This offset can be retrieved later by comparing the real
* day of the week corresponding to the clock date with the day of
* the week claimed by the clock board.
*/
struct clockval *
write_clock (struct clockval *cv)
{ unsigned char clkdata[13];
int n, wkday;
/* Make sure there is an input parameter. */
if (cv == NULL_CLOCK) return NULL_CLOCK;
/*
* Do some simple sanity checking on the input.
*/
if (cv->cv_month == 0 || cv->cv_day == 0 || cv->cv_hour >= 24
|| cv->cv_minute >= 60 || cv->cv_second >= 60)
return NULL_CLOCK;
/*
* The century must be correct for the
* range of years from 1980 through 2079.
*/
if (cv->cv_century != ((cv->cv_year >= 80) ? 19 : 20))
return NULL_CLOCK;
/*
* Verify the month number and the number of days in the month.
* Since 2000 is a leap year, the test for Feburary can assume
* that any year divisible by 4 is a leap year.
*/
switch (cv->cv_month)
{
case 1: case 3: case 5: case 7:
case 8: case 10: case 12:
if (cv->cv_day > 31) return NULL_CLOCK;
break;
case 2:
if (cv->cv_day > ((cv->cv_year & 0x3) ? 28 : 29))
return NULL_CLOCK;
break;
case 4: case 6: case 9: case 11:
if (cv->cv_day > 30) return NULL_CLOCK;
break;
default:
return NULL_CLOCK;
}
/*
* Add five seconds to the time before writing it to the clock,
* so that the "tens of seconds" kludge with the day of the week
* (see below) will result in a value that is within five seconds
* either way of the actual time.
*/
advance_time (cv, 5);
/*
* Compute the day of the week.
*/
wkday = day_of_the_week (cv);
/*
* The 5832 chip contains a major design misfeature, in that the
* "seconds" information is always reset to zero when a new time
* is written to the clock, regardless of the actual "seconds"
* value being written. In order to get around this problem to
* some degree, this program modifies the "day of the week" on
* the clock by adding a "tens of seconds" quantity to the day
* of the week before storing it in the clock. This offset can
* be reconstructed later, when the clock value is read back, by
* comparing the clock's idea of the day of the week with the
* true day of the week.
*/
wkday += cv->cv_second / 10;
wkday %= 7;
cv->cv_second = 0;
/*
* Copy the input to the character array
* which will be used to set the clock.
*/
clkdata[0] = 0; /* seconds -- always zero */
clkdata[1] = 0; /* seconds -- always zero */
clkdata[2] = cv->cv_minute % 10;
clkdata[3] = cv->cv_minute / 10;
clkdata[4] = cv->cv_hour % 10;
clkdata[5] = cv->cv_hour / 10;
clkdata[6] = wkday;
clkdata[7] = cv->cv_day % 10;
clkdata[8] = cv->cv_day / 10;
clkdata[9] = cv->cv_month % 10;
clkdata[10] = cv->cv_month / 10;
clkdata[11] = cv->cv_year % 10;
clkdata[12] = cv->cv_year / 10;
for (n = 0; n < 13; n++)
if (clkdata[n] > 9) return NULL_CLOCK;
/*
* Set the extra bit which indicates 24-hour mode.
*/
clkdata[5] |= 0x08;
/*
* Determine whether the next February will have 29 days.
* This flag is set starting in March of the previous year;
* the 5832 clock chip automatically turns the flag off
* after February 29 has passed.
*/
if (((cv->cv_year & 0x3) == 0 && cv->cv_month <= 2) ||
((cv->cv_year & 0x3) == 3 && cv->cv_month >= 3))
clkdata[8] |= 0x40;
/*
* Prepare to write data to the clock.
*/
outportb (PPICTRL, PPI_WRITE); /* ready to write to PPI */
outportb (CLKCTRL, 0); /* clear clock control bits */
/*
* Verify that the clock is actually there by writing an arbitrary
* value to the PPI's port B, and then trying to read it back.
* This test really only verifies that something resembling a PPI
* is active in the I/O port address space used by the DTK clock.
*/
outportb (CLKADDR, 0x55);
if (inportb (CLKADDR) != 0x55) return NULL_CLOCK;
/*
* Write the new clock value.
*/
READY_TO_WRITE;
for (n = 0; n < 13; n++) WRITE_CLOCK (n);
DONE_WRITING;
/*
* Indicate success by returning the input parameter value.
*/
return cv;
}
/*
* TIME_TO_CLOCK
* Converts DOS "date" and "time" structures into a unified
* date/time stamp structure used in the rest of the program.
*/
void
time_to_clock (struct date *da, struct time *ti,
struct clockval **cv)
{ static struct clockval cval;
/*
* Perform sanity checks on the input parameters.
*/
if (cv != NULL_CLOCK_P) *cv = NULL_CLOCK;
if (da == NULL_DATE || ti == NULL_TIME || cv == NULL_CLOCK_P)
return;
/*
* Transform the date and time into the clock structure.
*/
cval.cv_century = da->da_year / 100;
cval.cv_year = da->da_year % 100;
cval.cv_month = da->da_mon;
cval.cv_day = da->da_day;
cval.cv_hour = ti->ti_hour;
cval.cv_minute = ti->ti_min;
cval.cv_second = ti->ti_sec;
/*
* That's all.
*/
*cv = &cval;
}