home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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;
- }