home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD2.img
/
d3xx
/
d388
/
dclock
/
dclockchip.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-22
|
5KB
|
230 lines
/* 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);
}