📄 realtimeclock.c
字号:
//**********************************************************************
//
// Filename: realtimeclock.c
//
// Description:
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Use of this source code is subject to the terms of the Cirrus end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to
// use this source code. For a copy of the EULA, please see the
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2005, All Rights Reserved
//
//**********************************************************************
#include <windows.h>
#include <nkintr.h>
#include <hwdefs.h>
DWORD dwReschedIncrement;
#ifdef REAL_RTC
extern BOOL InitializeISL1208(LPSYSTEMTIME ptime);
//extern BOOL ISL1208GetRealTime( LPSYSTEMTIME ptime );
extern BOOL ISL1208SetRealTime(LPSYSTEMTIME ptime);
BOOL g_bRTCWithBattery=TRUE;
BOOL g_bRealRTCInitialized=FALSE;
unsigned __int64 RealTimeBias = 0; // Number of 100-nanosecond intervals since
// January 1, 1601.
typedef volatile struct _rtcif_tag
{
DWORD dr; // data register
DWORD mr; // match register
union {
DWORD stat; // interrupt status (read only)
DWORD eoi; // interrupt clear (write only)
};
DWORD lr; // load register
DWORD cr; // control register
} RTCIF, *PRTCIF;
BOOL isleap(int year)
{
BOOL leap=FALSE;
if ((year % 4) == 0)
{
leap = TRUE;
if ((year % 100) == 0) {
leap = (year%400) ? 0 : 1;
}
}
return leap;
}
short DayOfThisMonth( short year, short month )
{
if(month<=7)
{
if( month%2) return 31;
else if( month !=2) return 30;
else if( isleap( year ) ) return 29;
else return 28;
}
else
{
if( month%2) return 30;
else return 31;
}
}
DWORD GetDaysFrom1601( LPSYSTEMTIME pTime )
{
DWORD year;
DWORD leapYear=0;
DWORD day;
WORD i;
UCHAR cMonth=pTime->wMonth-1;
year= pTime->wYear;
year-=1601;
leapYear = year/4;
leapYear-= year/100;
leapYear+= year/400;
day= year*365 + leapYear;
for( i=1; i< pTime->wMonth; i++ )
{
day+=DayOfThisMonth( (short)(pTime->wYear) , (short)i );
}
day+=pTime->wDay -1;
return day;
}
__int64 MySystemTimeToFileTime( LPSYSTEMTIME pTime )
{
DWORD day;
DWORD nsDay= 864000000;// 000; //8640,0000,0000
__int64 time;
day=GetDaysFrom1601( pTime);
day*=1000;
time= (__int64)day * nsDay;
nsDay= (( 60*pTime->wHour + pTime->wMinute ) *60 +pTime->wSecond ) ;
time+= (__int64)nsDay*10000000;
return time;
}
BOOL OEMGetRealTime(LPSYSTEMTIME lpst)
{
unsigned __int64 realTime;
FILETIME ft;
BOOL bRet;
//
// Implement the realtime clock.
//
PRTCIF pRTC = (PRTCIF) RTC_BASE;
DWORD dwRTCDR = pRTC->dr;
if( g_bRTCWithBattery ){
if( !g_bRealRTCInitialized ){
SYSTEMTIME time;
time.wYear=2006;
time.wMonth=7;
time.wDay=7;
time.wHour=12;
time.wMinute=1;
time.wSecond=1;
time.wDayOfWeek=5;
time.wMilliseconds=0;
if( InitializeISL1208( &time ) )
g_bRealRTCInitialized=TRUE;
else
g_bRTCWithBattery=FALSE;
*(__int64*)(&ft)= MySystemTimeToFileTime(&time);
realTime = (unsigned __int64) dwRTCDR; // data in seconds
realTime *= 1000; // convert to ms
realTime *= 10000; // convert to 100ns
// get the desired "real" time
RealTimeBias = (unsigned __int64) ft.dwHighDateTime << 32;
RealTimeBias += ft.dwLowDateTime;
// compensate for the clock time
RealTimeBias -= realTime;
}
}
//
// read the clock registers
//
realTime = (unsigned __int64) dwRTCDR; // data in seconds
realTime *= 1000; // convert to ms
realTime *= 10000; // convert to 100ns
realTime += RealTimeBias; // convert to "real" time
//
// load time/data structure
//
ft.dwLowDateTime = (DWORD)realTime;
ft.dwHighDateTime = (DWORD)(realTime >> 32);
bRet=KFileTimeToSystemTime( &ft, lpst );
RETAILMSG(0,(TEXT("Time %d/%d/%d %d:%d:%d --%d(%d)\r\n")
,lpst->wYear
,lpst->wMonth
,lpst->wDay
,lpst->wHour
,lpst->wMinute
,lpst->wSecond
,lpst->wDayOfWeek
,bRet
));
return bRet;
}
BOOL OEMSetRealTime(LPSYSTEMTIME lpst)
{
unsigned __int64 realTime;
FILETIME ft;
//
// Impliment battery backed real time clock.
//
//
PRTCIF pRTC = (PRTCIF) RTC_BASE;
DWORD dwRTCDR = pRTC->dr;
if( !ISL1208SetRealTime( lpst ) )
g_bRTCWithBattery=FALSE;
*(__int64*)(&ft)= MySystemTimeToFileTime(lpst);
// if (bRet = KSystemTimeToFileTime(lpst, &ft))
{
// read the clock registers
realTime = (unsigned __int64) dwRTCDR; // data in seconds
realTime *= 1000; // convert to ms
realTime *= 10000; // convert to 100ns
// get the desired "real" time
RealTimeBias = (unsigned __int64) ft.dwHighDateTime << 32;
RealTimeBias += ft.dwLowDateTime;
// compensate for the clock time
RealTimeBias -= realTime;
}
return TRUE;
}
BOOL OEMSetAlarmTime(LPSYSTEMTIME lpst)
{
FILETIME ft;
BOOL bRet = FALSE;
ULARGE_INTEGER alarmTime, currentTime, deltaTime;
PRTCIF pRTC = (PRTCIF) RTC_BASE;
DWORD dwRTCDR = pRTC->dr;
// get the desired alarm time
if (bRet = KSystemTimeToFileTime(lpst, &ft)) {
alarmTime.LowPart = ft.dwLowDateTime;
alarmTime.HighPart = ft.dwHighDateTime;
alarmTime.QuadPart -= RealTimeBias;
// get the current time
currentTime.QuadPart = (unsigned __int64) dwRTCDR; // data in seconds
currentTime.QuadPart *= 1000; // convert to ms
currentTime.QuadPart *= 10000; // convert to 100ns
// make sure the alarm occurs in the future
if(alarmTime.QuadPart < currentTime.QuadPart) {
DEBUGMSG(FALSE, (_T("OEMSetAlarmTime: alarm 0x%08x:%08x occurs before 0x%08x:%08x\r\n"),
alarmTime.HighPart, alarmTime.LowPart, currentTime.HighPart, currentTime.LowPart));
} else {
// round up to the nearest number of seconds
deltaTime.QuadPart = alarmTime.QuadPart - currentTime.QuadPart;
deltaTime.QuadPart += 9999999; // msecs, usecs, 100ns
deltaTime.QuadPart /= 10000000; // convert to seconds
// do we have enough resolution in our timer to handle the request?
if(deltaTime.HighPart != 0) {
DEBUGMSG(FALSE, (_T("OEMSetAlarmTime: alarm 0x%08x:%08x delta with 0x%08x:%08x (0x%08x:%08x) is too large\r\n"),
alarmTime.HighPart, alarmTime.LowPart, currentTime.HighPart, currentTime.LowPart, deltaTime.HighPart, deltaTime.LowPart));
} else {
// clear interrupts, write the comparator, and enable interrupts
pRTC->eoi = 0; // any value clears pending interrupts
pRTC->mr = dwRTCDR + deltaTime.LowPart;
pRTC->cr = 1; // enable match interrupt
OEMInterruptEnable(SYSINTR_RTC_ALARM, NULL, 0);
bRet = TRUE;
}
}
}
// return TRUE if alarm set, FALSE otherwise
return bRet;
}
#else //REAL_RTC
extern volatile LARGE_INTEGER CurTicks;
// The following control the debug output of the alarm & set functions
#define DEBUG_ALARM 0
#define DEBUG_SET 0
static volatile BOOL gfInitRTC = TRUE;
static FILETIME gftLastFileTime;
static LARGE_INTEGER gliLastCurTicks; // in ms
//
// The following are located in hal\interrupt.c
// They are used to control the alarm setting.
//
extern volatile BOOL gfRTCAlarm; // Is the RTC alarm enabled?
extern volatile LARGE_INTEGER gliRTCAlarmTicks; // Date & time of the alarm.
//
// Multipling by 161111 and then right shifting by 13 is the same as 10000000 / TIMER_508KHZ_FREQ
//
// This gives you the number of 100 nano second chunks...(nano chunks)
//
//#define TICKS_TO_NANO_CHUNKS( time ) (time) *= 161111; (time) = ((time) >> 13)
//#define TICKS_TO_NANO_CHUNKS( time ) (time)*=10*17/100;
#define TICKS_TO_NANO_CHUNKS( time ) (time)*=1302; (time)=(time)>>7
//#define TICKS_TO_NANO_CHUNKS( time ) (time)*=10*11; (time)=(time)>>6
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -