home *** CD-ROM | disk | FTP | other *** search
- /* DClockChip.c *************************************************************
- *
- * DClockChip ---- Real time clock support routines for DClock.
- *
- * Author -------- Olaf 'Olsen' Barthel, MXM
- * Brabeckstrasse 35
- * D-3000 Hannover 71
- *
- * Federal Republic of Germany
- *
- * This program truly is in the PUBLIC DOMAIN. Written on a cold
- * and damp September evening, hoping the next morning would be
- * better.
- *
- * Compiled using Aztec C 5.0a, CygnusEd Professional 2 & ARexx.
- *
- ***************************************************************************/
-
- /* Various definitions needed by the datestamp
- * conversion routine.
- */
-
- #define MINS_PER_HOUR 60
- #define SECS_PER_MIN 60
- #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
- #define SECS_PER_DAY (SECS_PER_HOUR * 24)
- #define TICS_PER_SEC 50
-
- #define FEB 1
- #define DAYS_PER_YEAR 365
- #define YEARS_PER_LEAP 4
- #define START_YEAR 1978
- #define FIRST_LEAP_YEAR 1980
- #define LEAP_ADJUST (FIRST_LEAP_YEAR - START_YEAR)
- #define LEAP_FEB_DAYS 29
- #define NORM_FEB_DAYS 28
-
- /* Alias names for clock chip registers. */
-
- #define Clock_Second1 (clock . Second1 & 0xF)
- #define Clock_Second10 (clock . Second10 & 0xF)
- #define Clock_Minute1 (clock . Minute1 & 0xF)
- #define Clock_Minute10 (clock . Minute10 & 0xF)
- #define Clock_Hour1 (clock . Hour1 & 0xF)
- #define Clock_Hour10 (clock . Hour10 & 0xF)
- #define Clock_Day1 (clock . Day1 & 0xF)
- #define Clock_Day10 (clock . Day10 & 0xF)
- #define Clock_Month1 (clock . Month1 & 0xF)
- #define Clock_Month10 (clock . Month10 & 0xF)
- #define Clock_Year1 (clock . Year1 & 0xF)
- #define Clock_Year10 (clock . Year10 & 0xF)
-
- /* The builtin clock chip (OKI MSM624SRS) consists of
- * sixteen registers of which each contains four bits
- * of relevant information. The following structure
- * tries to come as close to the register map as
- * possible, even though bitfields would have been
- * the better approach. Unfortunately Aztec 'C' 5.0a
- * forces bitfields to be long word aligned rather than
- * word aligned which causes a whole lot of confusion.
- */
-
- struct ClockChip
- {
- UWORD pad0;
- volatile UWORD Second1;
- UWORD pad1;
- volatile UWORD Second10;
- UWORD pad2;
- volatile UWORD Minute1;
- UWORD pad3;
- volatile UWORD Minute10;
- UWORD pad4;
- volatile UWORD Hour1;
- UWORD pad5;
- volatile UWORD Hour10;
- UWORD pad6;
- volatile UWORD Day1;
- UWORD pad7;
- volatile UWORD Day10;
- UWORD pad8;
- volatile UWORD Month1;
- UWORD pad9;
- volatile UWORD Month10;
- UWORD pad10;
- volatile UWORD Year1;
- UWORD pad11;
- volatile UWORD Year10;
- ULONG pad12;
- UWORD pad13;
- volatile UWORD Adjust;
- };
-
- /* Easy way to access the builtin clock chip. */
-
- #define clock (*((struct ClockChip *)0xdc0000))
-
- /* DateToTimeVal(struct DateTag *Date,struct timeval *TimeVal):
- *
- * Converts the contents of a DateTag into a timeval
- * as used by timer.device.
- */
-
- VOID
- DateToTimeVal(struct DateTag *Date,struct timeval *TimeVal)
- {
- LONG DaysElapsed,YearsElapsed,LeapYears;
- SHORT i;
-
- /* Number of days in each month. */
-
- static UBYTE Months[12] =
- {
- 31,28,31,30,
- 31,30,31,31,
- 30,31,30,31
- };
-
- /* Is this a leap year? */
-
- if(Date -> Year % YEARS_PER_LEAP)
- Months[FEB] = NORM_FEB_DAYS;
- else
- Months[FEB] = LEAP_FEB_DAYS;
-
- /* Calculate elapsed time. */
-
- YearsElapsed = Date -> Year - START_YEAR;
- LeapYears = (YearsElapsed + LEAP_ADJUST - 1) / YEARS_PER_LEAP;
- DaysElapsed = (YearsElapsed * DAYS_PER_YEAR) + LeapYears;
-
- /* Add the days already passed in this year. */
-
- for(i = 0; i < Date -> Month - 1 ; i++)
- DaysElapsed += Months[i];
-
- /* Add the days in the current month. */
-
- DaysElapsed += Date -> Day - 1;
-
- /* Calculate number of seconds. */
-
- TimeVal -> tv_secs = DaysElapsed * SECS_PER_DAY + (Date -> Hour * MINS_PER_HOUR + Date -> Minute) * SECS_PER_MIN + Date -> Second;
- TimeVal -> tv_micro = 0;
- }
-
- /* ReadClock():
- *
- * Read the system clock and set the system time
- * accordingly.
- */
-
- BYTE
- ReadClock()
- {
- struct MsgPort *TimePort;
- struct timerequest *TimeRequest;
- struct DateTag Date;
- UBYTE LastTick;
- BYTE Success = FALSE;
-
- /* Check the second timer. */
-
- LastTick = Clock_Second1;
-
- /* Wait two seconds. */
-
- Delay(TICS_PER_SEC * 2);
-
- /* If the value has changed, we have a
- * clock chip installed.
- */
-
- if(LastTick != Clock_Second1)
- {
- if(TimePort = CreatePort(NULL,0))
- {
- if(TimeRequest = (struct timerequest *)CreateExtIO(TimePort,sizeof(struct timerequest)))
- {
- if(!OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0))
- {
- TimeRequest -> tr_node . io_Command = TR_SETSYSTIME;
-
- Forbid();
-
- /* Stop the clock. */
-
- clock . Adjust |= 1;
-
- /* Wait for it to calm down. */
-
- while(clock . Adjust & 2);
-
- /* Convert the clock entries into a DateTag. */
-
- Date . Year = (Clock_Year10 < 7 ? 10 + Clock_Year10 : Clock_Year10) * 10 + Clock_Year1 + 1900;
- Date . Month = Clock_Month10 * 10 + Clock_Month1;
- Date . Day = Clock_Day10 * 10 + Clock_Day1;
-
- Date . Hour = Clock_Hour10 * 10 + Clock_Hour1;
- Date . Minute = Clock_Minute10 * 10 + Clock_Minute1;
- Date . Second = Clock_Second10 * 10 + Clock_Second1;
-
- /* Restart the clock. */
-
- clock . Adjust &= ~1;
-
- DateToTimeVal(&Date,&TimeRequest -> tr_time);
-
- /* Set the system time. */
-
- DoIO(TimeRequest);
-
- Permit();
-
- Success = TRUE;
-
- CloseDevice(TimeRequest);
- }
-
- DeleteExtIO(TimeRequest);
- }
-
- DeletePort(TimePort);
- }
- }
-
- return(Success);
- }
-