📄 pmic_rtc.cpp
字号:
//------------------------------------------------------------------------------
//
// Copyright (C) 2005, Motorola Inc. All Rights Reserved
//
//------------------------------------------------------------------------------
//
// File: pmic_rtc.cpp
//
// This file contains the PMIC rtc SDK interface that is used by applications
// and other drivers to access registers of the MC13783 RTC.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include "mxarm11_macros.h"
#include "pmic_ioctl.h"
#include "regs.h"
#include "regs_regulator.h"
#include "pmic_rtc.h"
#include "pmic_basic_types.h"
#include "pmic_lla.h"
//-----------------------------------------------------------------------------
// External Functions
//-----------------------------------------------------------------------------
// External Variables
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
// Global Variables
extern HANDLE hPMI;
#ifdef DEBUG
// Debug zone bit positions
#define ZONEID_ERROR 0
#define ZONEID_WARN 1
#define ZONEID_INIT 2
#define ZONEID_FUNC 3
#define ZONEID_INFO 4
// Debug zone masks
#define ZONEMASK_ERROR (1 << ZONEID_ERROR)
#define ZONEMASK_WARN (1 << ZONEID_WARN)
#define ZONEMASK_INIT (1 << ZONEID_INIT)
#define ZONEMASK_FUNC (1 << ZONEID_FUNC)
#define ZONEMASK_INFO (1 << ZONEID_INFO)
// Debug zone args to DEBUGMSG
#define ZONE_ERROR DEBUGZONE(ZONEID_ERROR)
#define ZONE_WARN DEBUGZONE(ZONEID_WARN)
#define ZONE_INIT DEBUGZONE(ZONEID_INIT)
#define ZONE_FUNC DEBUGZONE(ZONEID_FUNC)
#define ZONE_INFO DEBUGZONE(ZONEID_INFO)
extern DBGPARAM dpCurSettings;
// Named event for interrupt registration
static TCHAR *gEventNamePri = TEXT("EVENT_RTC");
static TCHAR *gRTCEventName;
#endif // DEBUG
//------------------------------------------------------------------------------
// Global Variables
//These macro define some default information of RTC
#define ORIGINYEAR 1980 // the begin year
#define MAXYEAR (ORIGINYEAR + 100) // the maxium year
#define JAN1WEEK 2 // Jan 1 1980 is a Tuesday
#define GetDayOfWeek(X) (((X-1)+JAN1WEEK)%7)
#define TYPE_TIME 0
#define TYPE_ALRM 1
static const UINT8 monthtable[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static const UINT8 monthtable_leap[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static HANDLE hIntrEventtodaPmic;
static HANDLE hPmicTODalarmThread;
//static BOOL bTODalarmTerminate;
static BOOL PmicTodAlarmThreadProc(LPVOID lpParam);
SYSTEMTIME default_time = {2003,1,3,1,0,0,0,0}; //Jan 1, 2003, Wednesday
//-----------------------------------------------------------------------------
// Local Variables
//-----------------------------------------------------------------------------
// Local Functions
static int IsLeapYear(int Year)
{
int Leap;
Leap = 0;
if ((Year % 4) == 0) {
Leap = 1;
if ((Year % 100) == 0) {
Leap = (Year%400) ? 0 : 1;
}
}
return (Leap);
}
// Calculate the total number of days in lpTime, since Jan 1, ORIGINYEAR
int CalculateDays(SYSTEMTIME* lpTime)
{
UINT8 *month_tab;
int days, year, month;
int i;
days = lpTime->wDay;
month = lpTime->wMonth;
year = lpTime->wYear;
// Calculate number of days spent so far from beginning of this year
month_tab = (UINT8 *)(IsLeapYear(year) ? monthtable_leap : monthtable);
for (i = 0; i < month - 1; i++)
{
days += month_tab[i];
}
// calculate the number of days in the previous years
for (i = ORIGINYEAR; i < year; i++)
{
days += (IsLeapYear(i) ? 366 : 365);
}
return days;
}
// Calculate the number of seconds in lpTime since the beginning of the day
int CalculateSeconds(SYSTEMTIME* lpTime)
{
return (lpTime->wHour * 60 * 60 + lpTime->wMinute * 60
+ lpTime->wSecond);
}
// split total days since Jan 1, ORIGINYEAR into year, month and day
PMIC_STATUS ConvertDays(int days, SYSTEMTIME* lpTime)
{
int dayofweek, month, year;
UINT8 *month_tab;
//Calculate current day of the week
dayofweek = GetDayOfWeek(days);
year = ORIGINYEAR;
while (days > 365)
{
if (IsLeapYear(year))
{
if (days > 366)
{
days -= 366;
year += 1;
}
}
else
{
days -= 365;
year += 1;
}
}
// Determine whether it is a leap year
month_tab = (UINT8 *)((IsLeapYear(year))? monthtable_leap : monthtable);
for (month=0; month<12; month++)
{
if (days <= month_tab[month])
break;
days -= month_tab[month];
}
month += 1;
lpTime->wDay = days;
lpTime->wDayOfWeek = dayofweek;
lpTime->wMonth = month;
lpTime->wYear = year;
return PMIC_SUCCESS;
}
// convert time of day in seconds to hour, minute and seconds
PMIC_STATUS ConvertSeconds(int seconds, SYSTEMTIME* lpTime)
{
int minutes = 0, hours = 0;
if(seconds < 86400)
{
if (seconds >= 60)
{
minutes = (int) seconds / 60;
seconds -= (minutes * 60);
if (minutes >= 60)
{
hours = (int) minutes / 60;
minutes -= (hours * 60);
}
}
}
else
{
ERRORMSG(TRUE, (_T("TOD in sec is wrong(seconds > 86399) %d"), seconds));
return PMIC_ERROR;
}
lpTime->wHour = hours;
lpTime->wMinute = minutes;
lpTime->wSecond = seconds;
return PMIC_SUCCESS;
}
// set the given time & day into the register pair indicated by type
PMIC_STATUS SetTime(int type, SYSTEMTIME* lpTime)
{
PMIC_PARAM_LLA_WRITE_REG param;
int days, seconds;
// calculate time of day in seconds
seconds = CalculateSeconds(lpTime);
if(seconds > 86399)
return PMIC_ERROR;
//Set Reg TimeOftheDay TOD -> Hours, Min , Sec : a 17 bit time of day (TOD)
param.addr = (type == TYPE_TIME) ? MC13783_RTC_TM_ADDR : MC13783_RTC_ALM_ADDR;
param.data = seconds;
param.mask = 0xFFFFFFFF;
if(!DeviceIoControl(hPMI, PMIC_IOCTL_LLA_WRITE_REG, ¶m,
sizeof(param), NULL, 0, NULL, NULL))
return PMIC_ERROR;
// Calculate days.
days = CalculateDays(lpTime);
//Set Reg Day -> years, months , days :the 15 bit DAY counter
param.addr = (type == TYPE_TIME) ? MC13783_RTC_DAY_ADDR : MC13783_RTC_DAY_ALM_ADDR;
param.data = days;
if(!DeviceIoControl(hPMI, PMIC_IOCTL_LLA_WRITE_REG, ¶m,
sizeof(param), NULL, 0, NULL, NULL))
return PMIC_ERROR;
return PMIC_SUCCESS;
}
// get the time and day from the register pair indicated by type
PMIC_STATUS GetTime(int type, SYSTEMTIME* lpTime)
{
UINT32 seconds, days;
UINT32 addr;
addr = (type == TYPE_TIME) ? MC13783_RTC_TM_ADDR : MC13783_RTC_ALM_ADDR;
if (!DeviceIoControl(hPMI, PMIC_IOCTL_LLA_READ_REG, &addr, sizeof(addr),
&seconds, sizeof(seconds), NULL, NULL))
return PMIC_ERROR;
addr = (type == TYPE_TIME) ? MC13783_RTC_DAY_ADDR : MC13783_RTC_DAY_ALM_ADDR;
if (!DeviceIoControl(hPMI, PMIC_IOCTL_LLA_READ_REG, &addr, sizeof(addr),
&days, sizeof(days), NULL, NULL))
return PMIC_ERROR;
//convert seconds to hours , minutes and seconds of the day
if (ConvertSeconds(seconds, lpTime) != PMIC_SUCCESS)
return PMIC_ERROR;
// convert days to year, month and day
if (ConvertDays(days, lpTime) != PMIC_SUCCESS)
return PMIC_ERROR;
return PMIC_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: pmicRTCSetSystemTime
//
// This function sets the current system time and date.
//
// Parameters:
// Pointer to a SYSTEMTIME structure that contains the current system date and time.
//
// Returns:
// PMIC_STATUS.
//
//------------------------------------------------------------------------------
PMIC_STATUS pmicRTCSetSystemTime(SYSTEMTIME* lpSystemTime)
{
return SetTime(TYPE_TIME, lpSystemTime);
}
//------------------------------------------------------------------------------
//
// Function: pmicRTCGetSystemTime
//
// This function retrieves the current system time and date.
//
// Parameters:
// lpSystemTime
// Pointer to a SYSTEMTIME structure to receive the current system date
// Returns:
// PMIC_STATUS.
//
//------------------------------------------------------------------------------
PMIC_STATUS pmicRTCGetSystemTime(SYSTEMTIME* lpSystemTime)
{
return GetTime(TYPE_TIME, lpSystemTime);
}
//------------------------------------------------------------------------------
//
// Function: pmicRTCSetAlarmTime
//
// This function sets the alarm time and date
//
// Parameters:
// lpAlarmTime
// Pointer to a SYSTEMTIME structure that contains thealarm date and time.
//
// Returns:
// PMIC_STATUS.
//
//------------------------------------------------------------------------------
PMIC_STATUS pmicRTCSetAlarmTime(SYSTEMTIME* lpAlarmTime)
{
return SetTime(TYPE_ALRM, lpAlarmTime);
}
//------------------------------------------------------------------------------
//
// Function: pmicRTCGetAlarmTime
//
// This function retrieves the alarm time and date
//
// Parameters:
// llpAlarmTime
// Pointer to a SYSTEMTIME structure to receive the alarm date and time.
//
// Returns:
// PMIC_STATUS.
//
//------------------------------------------------------------------------------
PMIC_STATUS pmicRTCGetAlarmTime(SYSTEMTIME* lpAlarmTime)
{
return GetTime(TYPE_ALRM, lpAlarmTime);
}
//------------------------------------------------------------------------------
//
// Function: pmicRTCRegisterAlarmCallback
//
// This function registers alarm callback function.
//
// Parameters:
// alarmCB
// Alarm callback function.
//
// Returns:
// PMIC_STATUS.
//
//------------------------------------------------------------------------------
PMIC_STATUS pmicRTCRegisterAlarmCallback(RTC_ALARM_CB alarmCB)
{
PMIC_STATUS status=PMIC_ERROR;
// create event for PMIC interrupt signaling
// pEventAttributes = NULL (must be NULL)
// bManualReset = FALSE => resets automatically to nonsignaled
// state after waiting thread released
// bInitialState = FALSE => initial state is non-signaled
// lpName = EVENT_RTC_PRI => object created with a name
hIntrEventtodaPmic = CreateEvent(NULL, FALSE, FALSE, TEXT("EVENT_RTC_PRI"));
// check if CreateEvent failed
if (hIntrEventtodaPmic == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("%s(): CreateEvent failed!\r\n"),
__WFUNCTION__));
return status;
}
// Register for PMIC ADC done interrupts.
if (PmicInterruptRegister(PMIC_MC13783_INT_TODAI, TEXT("EVENT_RTC_PRI"))
!= PMIC_SUCCESS)
{
ERRORMSG(1, (_T("Pmic TODAlarm RtcInterruptRegister failed\r\n")));
return status;
}
// Make sure RTC interrupt is unmasked
if (PmicInterruptEnable(PMIC_MC13783_INT_TODAI) != PMIC_SUCCESS)
{
ERRORMSG(TRUE, (_T("PmicRTCInit: PmicInterruptEnable failed\r\n")));
goto cleanUp;
}
bTODalarmTerminate = FALSE;
hPmicTODalarmThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)PmicTodAlarmThreadProc,
(LPVOID)alarmCB, 0, NULL);
if (!hPmicTODalarmThread)
{
DEBUGMSG(ZONE_ERROR,(TEXT("PmicIsrThreadStart: CreateThread failed\r\n")));
PmicInterruptDeregister(PMIC_MC13783_INT_TODAI);
goto cleanUp;
}
status = PMIC_SUCCESS;
cleanUp:
if (status != PMIC_SUCCESS)PmicInterruptDeregister(PMIC_MC13783_INT_TODAI);
return status;
}
//------------------------------------------------------------------------------
//
// Function: pmicRTCCancelAlarm
//
// This function cancels the alarm time and date setting.
//
// Parameters:
// None
//
// Returns:
// PMIC_STATUS.
//
//------------------------------------------------------------------------------
PMIC_STATUS pmicRTCCancelAlarm()
{
PmicInterruptDeregister(PMIC_MC13783_INT_TODAI);
bTODalarmTerminate = TRUE;
CloseHandle(hPmicTODalarmThread);
return PMIC_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: PmicIsrThreadProc
//
// ISR Thread Process that launches IST loop.
//
// Parameters:
// None.
//
// Returns:
// TRUE if success, FALSE if failure.
//
//------------------------------------------------------------------------------
static BOOL
PmicTodAlarmThreadProc(LPVOID lpParam)
{
RTC_ALARM_CB p = (RTC_ALARM_CB) lpParam;
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
while(!bTODalarmTerminate)
{
if (WaitForSingleObject(hIntrEventtodaPmic, INFINITE) == WAIT_OBJECT_0)
p();
}
ExitThread(TRUE);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -