home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
sysutl
/
dtkclk11.arc
/
READ.C
< prev
next >
Wrap
Text File
|
1989-06-15
|
5KB
|
169 lines
/*
* Routines to read the DTK clock/calendar board.
* (C) Copyright 1989 Richard B. Wales. All Rights Reserved.
*/
#include "clkdefs.h"
/*
* READ_CLOCK
* Reads the date/time from the clock board.
* An additional "tens of seconds" offset is derived from the "day
* of the week" value on the clock board (by comparing this value
* with the true day of the week), and is added into the returned
* value.
*/
struct clockval *
read_clock (void)
{ unsigned char clkdata[13];
unsigned char save_seconds;
int n, tries, wkday;
static struct clockval cval;
/*
* Prepare to read data from the clock.
*/
outportb (PPICTRL, PPI_READ); /* ready to read from 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;
/*
* Read the clock value, starting with the seconds.
* After reading the entire clock, read the seconds digit again;
* if it has changed from the initial reading,
* read the entire clock value again.
*/
tries = 4;
READY_TO_READ;
do
{ for (n = 0; n < 13; n++) READ_CLOCK (n);
save_seconds = clkdata[0]; READ_CLOCK (0);
} while (--tries > 0 && clkdata[0] != save_seconds);
DONE_READING;
if (clkdata[0] != save_seconds) return NULL_CLOCK;
/*
* Check for 12- or 24-hour mode.
* If the clock value is in 12-hour mode,
* transform to 24-hour mode before proceeding further.
*/
switch (clkdata[5] & 0xc)
{ case 0x0: /* 12-hour AM */
if (clkdata[5] == 1 && clkdata[4] == 2)
clkdata[5] = 0, clkdata[4] = 0;
break;
case 0x4: /* 12-hour PM */
clkdata[5] &= 0x3;
if (clkdata[5] != 1 || clkdata[4] != 2)
{ clkdata[5] += 1, clkdata[4] += 2;
if (clkdata[4] >= 10)
clkdata[4] -= 10, clkdata[5] += 1;
}
break;
default: /* 24-hour */
clkdata[5] &= 0x3;
}
/*
* The 4-bit of the "tens of days" digit is used as a leap-year
* indicator (current or coming February will have 29 days).
* This information is not important while reading the clock.
*/
clkdata[8] &= 0x3;
/*
* Copy the clock data into the output structure (BCD format).
* Note that the "century" information is not included in the
* clock output, and must be generated by the program on the
* assumption that the year is in the range 1980 through 2079.
*/
cval.cv_second = clkdata[1] * 10 + clkdata[0];
cval.cv_minute = clkdata[3] * 10 + clkdata[2];
cval.cv_hour = clkdata[5] * 10 + clkdata[4];
cval.cv_day = clkdata[8] * 10 + clkdata[7];
cval.cv_month = clkdata[10] * 10 + clkdata[9];
cval.cv_year = clkdata[12] * 10 + clkdata[11];
cval.cv_century = ((clkdata[12] >= 8) ? 19 : 20);
/*
* Perform a few simple sanity checks on the result.
*/
if (cval.cv_month == 0 || cval.cv_month > 12
|| cval.cv_day == 0 || cval.cv_day > 31
|| cval.cv_hour >= 24
|| cval.cv_minute >= 60
|| cval.cv_second >= 60)
return NULL_CLOCK;
/*
* Since a major design misfeature of the 5832 chip causes the
* "seconds" to be reset to zero whenever a new time is written
* to the clock, the "day of the week" on the clock encodes an
* additional multiple of ten seconds to be added to the clock
* value. Extract this quantity by comparing the clock data
* with the true day of the week, then adjust the time accordingly.
*/
wkday = clkdata[6] - day_of_the_week (&cval);
while (wkday < 0) wkday += 7;
while (wkday >= 7) wkday -= 7;
advance_time (&cval, 10 * wkday);
/*
* Return the clock value to the calling routine.
*/
return &cval;
}
/*
* CLOCK_TO_TIME
* Converts the unified date/time structure used by the bulk of
* the program into the separate "date" and "time" structures
* used by DOS.
*/
void
clock_to_time (struct clockval *cv,
struct date **da,
struct time **ti)
{ static struct date date;
static struct time time;
/*
* Perform sanity checking on the input parameters.
*/
if (da != NULL_DATE_P) *da = NULL_DATE;
if (ti != NULL_TIME_P) *ti = NULL_TIME;
if (cv == NULL_CLOCK || da == NULL_DATE_P || ti == NULL_TIME_P)
return;
/*
* Set up the date structure.
*/
date.da_year = cv->cv_century * 100 + cv->cv_year;
date.da_mon = cv->cv_month;
date.da_day = cv->cv_day;
/*
* Set up the time structure.
*/
time.ti_hour = cv->cv_hour;
time.ti_min = cv->cv_minute;
time.ti_sec = cv->cv_second;
time.ti_hund = 0;
/*
* Set the returned values.
*/
*da = &date;
*ti = &time;
}