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