/*
 ******************************************************************************
 *              
 *     リアルタイム・クロックの処理
 *
 *     $Id: lb_rtc.c,v 1.5 2004/03/02 01:30:26 tong Exp $
 *
 ******************************************************************************
 */

#include <ultra64.h>
#include "lb_rtc.h"
#include "padmgr.h"
#include "m_common_data.h"

/*
 ******************************************************************************
 ******************************************************************************
 *     
 *  リアルタイム・クロック関連の処理
 *
 *  概説 : 
 *         リアルタイム・クロックへの時刻設定, 獲得, 判定を行なう処理。
 *
 *  補足 :
 *         lb_rtc.hの先頭にあるマクロに, 以下の定義を行なわなければならない。
 *
 *         lbRTC_LOC_SERIAL_MSGQ()    : ロックしメッセージキューを得るための
 *                                    処理
 *         lbRTC_UNLOC_SERIAL_MSGQ(p) : メッセージキューを得るためのロックを
 *                                    解除する処理
 *
 *  関数 :
 *         lbRTC_WriteArea()      : バックアップ領域に書き込む
 *         lbRTC_ReadArea()       : バックアップ領域から読み込む
 *         lbRTC_Settime()        : リアルタイム・クロックの時間設定
 *         lbRTC_Gettime()        : リアルタイム・クロックの時間を得る
 *
 *         lbRTC_IsEqualDate()    : 日付の一致を判定
 *         lbRTC_IsEqualTime()    : 時間の一致を判定
 *         lbRTC_IsOverTime()     : 時間越え判定
 *         lbRTC_IsJustAtRTC()    : リアルタイム・クロックの一致判定
 *
 *         lbRTC_GetDaysByMonth() : 月の日数を得る
 *         lbRTC_GetIntervalDays(): 日数差を得る
 *         lbRTC_IntervalTime()   : 時間の差分計算
 *
 *         lbRTC_Add_YY()         : 年数の加算
 *         lbRTC_Add_MM()         : 月数の加算
 *         lbRTC_Add_DD()         : 日数の加算 
 *         lbRTC_Add_hh()         : 時間の加算
 *         lbRTC_Add_mm()         : 分の加算
 *         lbRTC_Add_ss()         : 秒の加算
 *         lbRTC_Add_Date()       : 日付の加算
 *
 *         lbRTC_Sub_YY()         : 年数の減算
 *         lbRTC_Sub_MM()         : 月数の減算
 *         lbRTC_Sub_DD()         : 日数の減算 
 *         lbRTC_Sub_hh()         : 時間の減算
 *         lbRTC_Sub_mm()         : 分の減算
 *         lbRTC_Sub_ss()         : 秒の減算
 *         lbRTC_Sub_Date()       : 日付の減算
 *
 *         lbRTC_Week()           : 曜日を求める
 *
 *         lbRTC_IsOverRTC()      : リアルタイム・クロックの時間越え判定
 *         lbRTC_IsOverWeekRTC()  : リアルタイム・クロックの曜日越え判定
 *
 *         lbRTC_TimeCopy()       : 日付のコピー
 *         lbRTC_IsValidTime()    : 日付のチェック
 *
 ******************************************************************************
 ******************************************************************************
 */
//#define RTC_DEBUG

#ifdef BBPLAYER
u32 bbRTC_delta_minutes = 0;
int bbRTC_delta_sign = 0;

#endif

static int l_lbRTC_isInitial = TRUE;
/*
 ******************************************************************************
 *  機能 :
 *         リアルタイム・クロックの初期化
 *  説明 :
 *         リアルタイム・クロックの処理を初期化する
 *  戻り値 :
 *           == 0 : 正常
 *           != 0 : エラー番号(マニュアルを参照)
 ******************************************************************************
 */
extern int lbRTC_Initial(void)
{
    static int ret;
    
    if (l_lbRTC_isInitial == TRUE) {
#ifdef BBPLAYER

	l_lbRTC_isInitial = FALSE;

	osBbRtcInit();

        mFRm_FlashLoadAllData_malloc();
        bbRTC_delta_minutes = SaveGet(delta.minutes);
        bbRTC_delta_sign = SaveGet(delta.sign);

	ret = 0;
#else
	/* 初期化を行っていない場合 */
	OSMesgQueue  *siMessegeQ = lbRTC_LOC_SERIAL_MSGQ();

	l_lbRTC_isInitial = FALSE;
	ret = (int)osRTCInit(siMessegeQ);
	lbRTC_UNLOC_SERIAL_MSGQ(siMessegeQ);
#endif
#ifdef RTC_DEBUG    
	PRINTF("RTC initial\n");
#endif
    }
#ifdef RTC_DEBUG    
    PRINTF("RTC init return value ? = %x\n", ret);
#endif
    return ret;
}
/*
 ******************************************************************************
 *  機能 :
 *         リアルタイム・クロックの初期化と状態確認
 *  説明 :
 *         リアルタイム・クロックの初期化と状態を確認する。異常があった場合は, 
 *       再度初期化を行いその結果を返す。
 *  戻り値 :
 *         == 0 : 正常
 *         != 0 : エラー番号(マニュアルを参照)
 ******************************************************************************
 */
static int lbRTC_IsOki(lbRTC_time_c *i_Time)
{
    int  ret = lbRTC_Initial();

    if (!ret) {
#ifdef BBPLAYER
        u8 year;
	osBbRtcGet( &year, 
                    &(i_Time->month), 
		    &(i_Time->day), 
		    &(i_Time->week), 
		    &(i_Time->hour), 
		    &(i_Time->min), 
		    &(i_Time->sec) );
        i_Time->year = year + 2000;
        
        if (bbRTC_delta_sign==lbRTC_OVER_TIME) {
            lbRTC_Add_mm(i_Time, bbRTC_delta_minutes);
        } else if (bbRTC_delta_sign==lbRTC_LESS_TIME) {
            lbRTC_Sub_mm(i_Time, bbRTC_delta_minutes);
        }

        i_Time->year = (i_Time->year>lbRTC_MAX_YEAR || i_Time->year<lbRTC_MIN_YEAR) ? lbRTC_MIN_YEAR : i_Time->year;
        i_Time->month = (i_Time->month>lbRTC_MAX_MONTH || i_Time->month<lbRTC_MIN_MONTH) ? lbRTC_MIN_MONTH : i_Time->month;
        i_Time->day = (i_Time->day>lbRTC_MAX_DAY || i_Time->day<lbRTC_MIN_DAY) ? lbRTC_MIN_DAY : i_Time->day;
        i_Time->hour = (i_Time->hour>lbRTC_MAX_HOUR || i_Time->hour<lbRTC_MIN_HOUR) ? lbRTC_MIN_HOUR : i_Time->hour;
        i_Time->min = (i_Time->min>lbRTC_MAX_MINUTE || i_Time->min<lbRTC_MIN_MINUTE) ? lbRTC_MIN_MINUTE : i_Time->min;
        i_Time->sec = (i_Time->sec>lbRTC_MAX_SECOND || i_Time->sec<lbRTC_MIN_SECOND) ? lbRTC_MIN_SECOND : i_Time->sec;
        i_Time->week = lbRTC_Week(i_Time->year, i_Time->month, i_Time->day);

	return 0;
#else
	/* 現在のＲＴＣが正常に初期化されていた場合,
	   ＲＴＣ読み込を行い状態を確認する */
	OSMesgQueue   *siMessegeQ = lbRTC_LOC_SERIAL_MSGQ();
	
	ret = (int)osRTCGetTime(siMessegeQ, i_Time);
	lbRTC_UNLOC_SERIAL_MSGQ(siMessegeQ);
	if (!ret) {
	    return ret;
	}	
#endif
    }            
    /* ＲＴＣが異常だった場合,
       ＲＴＣに再度初期化を行うための設定を行う */
    l_lbRTC_isInitial = TRUE;
    return ret;
}        	
/*
 ******************************************************************************
 *  機能 :
 *         リアルタイム・クロックの状態確認
 *  説明 :
 *         リアルタイム・クロックの状態を確認する。異常があった場合は, 再度
 *       初期化を行いその結果を返す。
 *         lbRTC_Sampling()を行い, １秒以上経過後にこの処理を通すことによって
 *        , ＲＴＣが時間の更新を行えているか再確認できる。
 *         処理を通す間隔が１秒経過していない場合もエラーを返すので注意が必要。
 *  戻り値 :
 *         == 0 : 正常
 *         != 0 : エラー番号(マニュアルを参照)
 ******************************************************************************
 */
static int l_lbRTC_IsSampled = FALSE;
static lbRTC_time_c  l_lbRTC_Time;

extern int lbRTC_IsAbnormal(void)
{
    lbRTC_time_c  time;
    int           ret = lbRTC_IsOki(&time);
    
    if (ret == 0) {
	/* ＲＴＣが正常状態の場合 */
	if (l_lbRTC_IsSampled == TRUE) {
	    /* ＲＴＣの時間更新確認値を新しくサンプルしていた場合 */
	    int  sec1, sec2;
	    
	    sec1 = time.sec + time.min * lbRTC_SECCONDS;
	    sec2 = l_lbRTC_Time.sec + l_lbRTC_Time.min * lbRTC_SECCONDS;
	    if (sec1 != sec2) {
		/* サンプルタイムと今のタイムが不一致の場合,
		   正常に動作 */
#ifdef RTC_DEBUG    
		PRINTF("RTC Normal = %x\n", ret);
#endif
		return ret;
	    }
	}
#ifdef RTC_DEBUG    
	PRINTF("RTC Abnormal = -1\n");
#endif
#ifndef DEBUG
	l_lbRTC_IsSampled = FALSE;
	l_lbRTC_isInitial = TRUE;
	return -1;
#endif
    }
    else {
	/* ＲＴＣが異常の場合 */
#ifdef RTC_DEBUG    
	PRINTF("RTC Abnormal = %x\n", ret);
#endif
    }
    return ret;
}
/*
 ******************************************************************************
 *  機能 :
 *         リアルタイム・クロックの状態確認のためのサンプリング
 *  説明 :
 *         ＲＴＣが時間の更新を行えているか確認するためのサンプリングを行う。
 *         この処理を通して１秒以上経過後にlbRTC_IsAbnormal()を通すことによっ
 *       て, ＲＴＣが時間の更新を行えているか再確認できる。処理を通す間隔が１
 *       秒経過していない場合もエラーを返すので注意が必要。
 *  戻り値 :
 *         == 0 : 正常
 *         != 0 : エラー番号(マニュアルを参照)
 ******************************************************************************
 */
extern void lbRTC_Sampling(void)
{
    lbRTC_time_c  time;
    
    if ((lbRTC_IsOki(&time) == 0) && (l_lbRTC_IsSampled == FALSE)) {
	/* ＲＴＣの時間更新確認値を新しくサンプルする場合 */
	l_lbRTC_Time.sec = time.sec;
	l_lbRTC_Time.min = time.min;
#ifdef RTC_DEBUG    
	PRINTF("RTC Sampling : %d sec\n", l_lbRTC_Time.sec);
#endif
	l_lbRTC_IsSampled = TRUE;
    }
}
/*
 ******************************************************************************
 *  機能 :
 *         バックアップ領域に書き込む
 *  説明 :
 *         ＲＴＣが持つ８バイトのバックアップ領域に書き込む。
 *  入力 :
 *         *Buffer : ８バイトの書き込みデータの先頭ポインター
 ******************************************************************************
 */
extern void lbRTC_WriteArea(u8 *Buffer)
{
    if (lbRTC_Initial() == 0) {
	/* RTCが正常な場合 */
	OSMesgQueue *siMessegeQ = lbRTC_LOC_SERIAL_MSGQ();

	osRTCWriteData(siMessegeQ, Buffer);
	lbRTC_UNLOC_SERIAL_MSGQ(siMessegeQ);
    }
}

/*
 ******************************************************************************
 *  機能 :
 *         バックアップ領域から読み込む
 *  説明 :
 *         ＲＴＣが持つ８バイトのバックアップ領域から内容を読み込む。
 *  入力 :
 *         *Buffer : ８バイトの読み込み領域の先頭ポインター
 ******************************************************************************
 */
extern void lbRTC_ReadArea(u8 *Buffer)
{
    if (lbRTC_Initial() == 0) {
	/* RTCが正常な場合 */
	OSMesgQueue *siMessegeQ = lbRTC_LOC_SERIAL_MSGQ();

	osRTCReadData(siMessegeQ, Buffer);
	lbRTC_UNLOC_SERIAL_MSGQ(siMessegeQ);
    }
}

/*
 ******************************************************************************
 *  機能 :
 *         リアルタイム・クロックの時間設定
 *  説明 :
 *         リアルタイム・クロックに指定の時間を設定する
 *  入力 :
 *         *Time : 設定時間のポインター
 ******************************************************************************
 */
extern void lbRTC_SetTime(lbRTC_time_c *Time)
{
    if ((ZCommonGet(time.rtc_use) == ON) &&
	(ZCommonGet(time.rtc_crash) == OFF)) {
#ifdef BBPLAYER
        u8 year;
        lbRTC_time_c bb_time;

	osBbRtcGet( &year, 
                    &(bb_time.month), 
		    &(bb_time.day), 
		    &(bb_time.week), 
		    &(bb_time.hour), 
		    &(bb_time.min), 
		    &(bb_time.sec) );
        bb_time.year = year + 2000;
        bb_time.week --;

	Time->week = lbRTC_Week(Time->year, Time->month, Time->day);

        bbRTC_delta_sign = lbRTC_IsOverTime(&bb_time, Time);
        if (bbRTC_delta_sign==lbRTC_LESS_TIME) {
            bbRTC_delta_minutes = lbRTC_IntervalTime (&bb_time, Time);
        } else if (bbRTC_delta_sign==lbRTC_OVER_TIME) {
            bbRTC_delta_minutes = lbRTC_IntervalTime (Time, &bb_time);
        } 
#else
	/* RTCが利用可能な場合 */
	OSMesgQueue *siMessegeQ;
	    
	Time->week = lbRTC_Week(Time->year, Time->month, Time->day);
	siMessegeQ = lbRTC_LOC_SERIAL_MSGQ();
	osRTCSetTime(siMessegeQ, Time);
	lbRTC_UNLOC_SERIAL_MSGQ(siMessegeQ);
#endif
	    
#if DEBUG
	PRINTF("*** リアルタイム・クロックの時間設定 ***\n");
	PRINTF("Time->year=%d \n", Time->year);
	PRINTF("Time->month=%d \n", Time->month);
	PRINTF("Time->day=%d \n", Time->day);
	PRINTF("Time->week=%d \n", Time->week);
#endif	/* DEBUG */
    }
    else {
	lbRTC_TimeCopy(ZCommonGetP(time.rtcTime), Time);
    }
}

#if 0 // 2000/7/26 otsuki
extern void	lbRTC_SetTime(
    lbRTC_time_c	*Time
    )
{
    /* ＲＴＣを使う ? */
    if (ZCommonGet(time.rtc_use) == ON) {
	/* 現在の時間を得る */
	lbRTC_Settime(Time);
    }
    else {
	lbRTC_TimeCopy(ZCommonGetP(time.rtcTime), Time);
    }
}
#endif	/* DEBUG */

/*
 ******************************************************************************
 *  機能 :
 *         リアルタイム・クロックの時間を得る
 *  説明 :
 *         リアルタイム・クロックから時間を得る
 *  入力 :
 *         *Time : 読み込み時間を格納する領域のポインター
 ******************************************************************************
 */
extern void lbRTC_GetTime(lbRTC_time_c *Time)
{
    if ((ZCommonGet(time.rtc_use) == ON) &&
	(ZCommonGet(time.rtc_crash) == OFF)) {
#ifdef BBPLAYER
        u8 year;
	osBbRtcGet( &year, 
                    &(Time->month), 
		    &(Time->day), 
		    &(Time->week), 
		    &(Time->hour), 
		    &(Time->min), 
		    &(Time->sec) );
	Time->year = year + 2000;

        if (bbRTC_delta_sign==lbRTC_OVER_TIME) {
            lbRTC_Add_mm(Time, bbRTC_delta_minutes);
        } else if (bbRTC_delta_sign==lbRTC_LESS_TIME) {
            lbRTC_Sub_mm(Time, bbRTC_delta_minutes);
        }

        Time->year = (Time->year>lbRTC_MAX_YEAR || Time->year<lbRTC_MIN_YEAR) ? lbRTC_MIN_YEAR : Time->year;
        Time->month = (Time->month>lbRTC_MAX_MONTH || Time->month<lbRTC_MIN_MONTH) ? lbRTC_MIN_MONTH : Time->month;
        Time->day = (Time->day>lbRTC_MAX_DAY || Time->day<lbRTC_MIN_DAY) ? lbRTC_MIN_DAY : Time->day;
        Time->hour = (Time->hour>lbRTC_MAX_HOUR || Time->hour<lbRTC_MIN_HOUR) ? lbRTC_MIN_HOUR : Time->hour;
        Time->min = (Time->min>lbRTC_MAX_MINUTE || Time->min<lbRTC_MIN_MINUTE) ? lbRTC_MIN_MINUTE : Time->min;
        Time->sec = (Time->sec>lbRTC_MAX_SECOND || Time->sec<lbRTC_MIN_SECOND) ? lbRTC_MIN_SECOND : Time->sec;
        Time->week = lbRTC_Week(Time->year, Time->month, Time->day);
#else
	/* RTCが利用可能な場合 */
	OSMesgQueue *siMessegeQ = lbRTC_LOC_SERIAL_MSGQ();
	    
	osRTCGetTime(siMessegeQ, Time);
	lbRTC_UNLOC_SERIAL_MSGQ(siMessegeQ);
#endif
#if 0 /* def DEBUG */
	PRINTF("*** リアルタイム・クロックの取得時間 ***\n");
	PRINTF("Time->year=%d \n", Time->year);
	PRINTF("Time->month=%d \n", Time->month);
	PRINTF("Time->day=%d \n", Time->day);
	PRINTF("Time->week=%d \n", Time->week);
#endif	/* DEBUG */

    }
    else {
	lbRTC_TimeCopy(Time, ZCommonGetP(time.rtcTime));
    }
}

#if 0 // 2000/7/26 otsuki
extern void	lbRTC_GetTime(
    lbRTC_time_c	*Time
    )
{
    /* ＲＴＣを使う ? */
    if (ZCommonGet(time.rtc_use) == ON) {
	/* 現在の時間を得る */
	lbRTC_Gettime(Time);
    }
    else {
	lbRTC_TimeCopy(Time, ZCommonGetP(time.rtcTime));
    }
}
#endif	/* DEBUG */

/*
 ******************************************************************************
 *  機能 :
 *         月の日数を得る
 *  説明 :
 *         指定の西暦と月から, その月の日数を返す。
 *  入力 :
 *         Year  : 西暦
 *         Month : 日数を得たい月
 *  出力 :
 *         lbRTC_GetDaysByMonth() : 日数
 ******************************************************************************
 */
extern lbRTC_DD_t lbRTC_GetDaysByMonth(lbRTC_YY_t Year, lbRTC_MM_t Month)
{
    static const lbRTC_DD_t  days_month[lbRTC_MODE][lbRTC_MONTH_NUM + 1] =
    {
	{0, 31,28,31,30,31,30,31,31,30,31,30,31},            /* 通常年 */
	{0, 31,29,31,30,31,30,31,31,30,31,30,31}             /* 閏年 */
    };
    int  YYmode = lbRTC_IS_LEAP_YEAR(Year) == TRUE ? 1 : 0;

    return days_month[YYmode][(int)Month];
}

/*
 ******************************************************************************
 *  機能 :
 *         日付の判定
 *  説明 :
 *         二つの日付を比較判定する。
 *  入力 :
 *         *i_dYear  : 日付Ａの年
 *         *i_dMonth : 日付Ａの月
 *         *i_dDay   : 日付Ａの日
 *         *i_sYear  : 日付Ｂの年
 *         *i_sMonth : 日付Ｂの月
 *         *i_sDay   : 日付Ｂの日
 *  出力 :
 *         lbRTC_IsEqualDate() == -1 : Ａ日付が小さい場合（Ａ＜Ｂ）
 *         lbRTC_IsEqualDate() == 0  : ＡとＢが同じ日付の場合（Ａ＝Ｂ）
 *         lbRTC_IsEqualDate() == 1  : Ａ日付が大きい場合（Ａ＞Ｂ）
 ******************************************************************************
 */
typedef union {
    int  yymmdd;
    struct {
	lbRTC_YY_t year; 
	lbRTC_MM_t month;
	lbRTC_DD_t day;
    } part;
} lbRTC_date_c;

extern int lbRTC_IsEqualDate(lbRTC_YY_t i_dYear, 
			     lbRTC_MM_t i_dMonth,
			     lbRTC_DD_t i_dDay,  
			     lbRTC_YY_t i_sYear, 
			     lbRTC_MM_t i_sMonth,
			     lbRTC_DD_t i_sDay)
{
    lbRTC_date_c  dDate;
    lbRTC_date_c  sDate;
    int           result;

    dDate.part.year  = i_dYear;
    dDate.part.month = i_dMonth;
    dDate.part.day   = i_dDay;
    sDate.part.year  = i_sYear;
    sDate.part.month = i_sMonth;
    sDate.part.day   = i_sDay;

    result = dDate.yymmdd - sDate.yymmdd;
    if (result == 0) {
	/* ＡとＢが同じ日付の場合 */
	return 0;
    }
    if (result < 0) {
	/* Ｂ日付が未来の場合 */
	return -1;
    }
    /* Ａ日付が未来の場合 */
    return 1;
}

/*
 ******************************************************************************
 *  機能 :
 *         時間の一致を判定
 *  説明 :
 *         二つの時間が判定モードのレベルで完全に一致しているか比較判定する。
 *  入力 :
 *         *dTime : 時間Ａのポインター
 *         *sTime : 時間Ｂのポインター
 *         Mode   : 判定モード
 *
 *                 lbRTC_JUST_YY : '年'で判定
 *                 lbRTC_JUST_MM : '月'で判定
 *                 lbRTC_JUST_DD : '日'で判定
 *                 lbRTC_JUST_WW : '曜日'で判定
 *                 lbRTC_JUST_hh : '時'で判定
 *                 lbRTC_JUST_mm : '分'で判定
 *                 lbRTC_JUST_ss : '秒'で判定
 *                 lbRTC_JUST    : 全てで判定
 *                 
 *                 ・組み合わせての判定の場合は, '|'を使って設定する。
 *
 *                   (例)  '時''分'で判定する場合
 *                         lbRTC_JUST_hh | lbRTC_JUST_mm
 *  出力 :
 *         lbRTC_IsEqualTime() == TRUE  : 時間が一致した
 *         lbRTC_IsEqualTime() == FALSE : 時間が一致しなかった
 ******************************************************************************
 */
extern int lbRTC_IsEqualTime(const lbRTC_time_c *dTime,
			     const lbRTC_time_c *sTime,
			     int          Mode)
{
    int  just = 0;
    
    /* 選択した判定モードの日付,時間の判定 */
    if (Mode & lbRTC_JUST_ss) {
	/* '秒'を判定 */
	if(dTime->sec == sTime->sec) {
	    just |= lbRTC_JUST_ss;
	}
    }
    if (Mode & lbRTC_JUST_mm) {
	/* '分'を判定 */
	if(dTime->min == sTime->min) {
	    just |= lbRTC_JUST_mm;
	}
    }
    if (Mode & lbRTC_JUST_hh) {
	/* '時'を判定 */
	if(dTime->hour == sTime->hour) {
	    just |= lbRTC_JUST_hh;
	}
    }
    if (Mode & lbRTC_JUST_WW) {
	/* '曜'を判定 */
	if(dTime->week == sTime->week) {
	    just |= lbRTC_JUST_WW;
	}
    }
    if (Mode & lbRTC_JUST_DD) {
	/* '日'を判定 */
	if(dTime->day == sTime->day) {
	    just |= lbRTC_JUST_DD;
	}
    }
    if (Mode & lbRTC_JUST_MM) {
	/* '月'を判定 */
	if(dTime->month == sTime->month) {
	    just |= lbRTC_JUST_MM;
	}
    }
    if (Mode & lbRTC_JUST_YY) {
	/* '年'を判定 */
	if(dTime->year == sTime->year) {
	    just |= lbRTC_JUST_YY;
	}
    }

    /* 選択した判定モードの日付,時間が一致したか判定 */
#if 0
    if ((just & Mode) == Mode) {
	return TRUE;             /* 一致 */
    }
    return FALSE;                /* 不一致 */
#else
    return ((just & Mode) == Mode);
#endif
}

/*
 ******************************************************************************
 *  機能 :
 *         時間越え判定
 *  説明 :
 *         時間Ｂが時間Ａを越えているか判定する
 *  入力 :
 *         *dTime : 時間Ａのポインター
 *         *sTime : 時間Ｂのポインター
 *  出力 :
 *         lbRTC_IsOverTime() == lbRTC_LESS_TIME : 越えていない
 *         lbRTC_IsOverTime() == lbRTC_OVER_TIME : 一致しているか越えている
 ******************************************************************************
 */
extern int lbRTC_IsOverTime(const lbRTC_time_c *dTime, const lbRTC_time_c *sTime)
{
    if (sTime->year < dTime->year) {
	/* '年'に達していない場合  */
	return lbRTC_LESS_TIME;
    }
    if (sTime->year == dTime->year) {
	if (sTime->month >= dTime->month) {
	    if (sTime->month == dTime->month) {
		if (sTime->day >= dTime->day) {
		    if (sTime->day == dTime->day) {
			if (sTime->hour >= dTime->hour) {
			    if (sTime->hour == dTime->hour) {
				if (sTime->min >= dTime->min) {
				    if (sTime->min == dTime->min) {
					if (sTime->sec < dTime->sec) {
					    /* '秒'に達していない場合 */
					    return lbRTC_LESS_TIME;
					}
				    }
				}
				else {
				    /* '分'に達していない場合  */
				    return lbRTC_LESS_TIME;
				}
			    }
			}
			else {
			    /* '時'に達していない場合  */
			    return lbRTC_LESS_TIME;
			}
		    }
		}
		else {
		    /* '日'に達していない場合  */
		    return lbRTC_LESS_TIME;
		}
	    }
	}
	else {
	    /* '月'に達していない場合  */
	    return lbRTC_LESS_TIME;
	}
    }
    /* 時間(dTimeの時間)に達した場合 */
    return lbRTC_OVER_TIME;
}

/*
 ******************************************************************************
 *  機能 :
 *         リアルタイム・クロックの一致判定
 *  説明 :
 *         リアルタイム・クロックが, 判定モードのレベルで指定時間に完全に一致し
 *       たか判定する。
 *  入力 :
 *         *Time : 一致時間のポインター
 *         Mode  : 判定モード
 *
 *                 lbRTC_JUST_YY : '年'で判定
 *                 lbRTC_JUST_MM : '月'で判定
 *                 lbRTC_JUST_DD : '日'で判定
 *                 lbRTC_JUST_WW : '曜日'で判定
 *                 lbRTC_JUST_hh : '時'で判定
 *                 lbRTC_JUST_mm : '分'で判定
 *                 lbRTC_JUST_ss : '秒'で判定
 *                 lbRTC_JUST    : 全てで判定
 *                 
 *                 ・組み合わせての判定の場合は, '|'を使って設定する。
 *
 *                   (例)  '時''分'で判定する場合
 *                         lbRTC_JUST_hh | lbRTC_JUST_mm
 *  出力 :
 *         lbRTC_IsJustAtRTC() == TRUE  : 一致
 *         lbRTC_IsJustAtRTC() == FALSE : 不一致
 ******************************************************************************
 */
extern int lbRTC_IsJustAtRTC(const lbRTC_time_c *Time, int Mode)
{
    lbRTC_time_c  currentTime;
    
    /* 現在の時間を得る */
    lbRTC_GetTime(&currentTime);

    /* 選択した判定モードの日付,時間の判定 */
#if 0
    if (lbRTC_IsEqualTime(&currentTime, Time, Mode) == TRUE) {
	/* 一致した場合 */
	return TRUE;
    }
    /* 不一致の場合 */
    return FALSE;
#else
    return lbRTC_IsEqualTime(&currentTime, Time, Mode);
#endif
}

/*
 ******************************************************************************
 *  機能 :
 *         リアルタイム・クロックの時間越え判定
 *  説明 :
 *         リアルタイム・クロックが指定時間を経過したか判定する。
 *  入力 :
 *         *Time : 経過判定時間のポインター
 *  出力 :
 *         lbRTC_IsOverRTC() == TRUE  : 指定時間を経過
 *         lbRTC_IsOverRTC() == FALSE : 指定時間を未経過
 ******************************************************************************
 */
extern int lbRTC_IsOverRTC(const lbRTC_time_c *Time)
{
    lbRTC_time_c  currentTime;

    /* 現在の時間を得る */
    lbRTC_GetTime(&currentTime);

#if 0
    if (lbRTC_IsOverTime(Time, &currentTime) == lbRTC_OVER_TIME) {
	/* 時間を経過した場合 */
	return TRUE;
    }
    /* 時間になっていない場合 */
    return FALSE;
#else  /* 01/01/29 20:43 hayakawa  */
    return (lbRTC_IsOverTime(Time, &currentTime) == lbRTC_OVER_TIME);
#endif
}

/*
 ******************************************************************************
 *  機能 :
 *         リアルタイム・クロックの曜日越え判定
 *  説明 :
 *         リアルタイム・クロックが判定開始時間から判定曜日を経過したか判定す
 *       る。
 *  入力 :
 *         *StartTime : 判定開始時間のポインター
 *         AlarmWeek  : 判定曜日
 *  出力 :
 *         lbRTC_IsOverWeekRTC() == TRUE  : 指定曜日を経過
 *         lbRTC_IsOverWeekRTC() == FALSE : 指定曜日を未経過
 ******************************************************************************
 */
extern int lbRTC_IsOverWeekRTC(const lbRTC_time_c *StartTime, lbRTC_WW_t AlarmWeek)
{
    int           days = (int)(AlarmWeek - StartTime->week);
    lbRTC_time_c  alarmTime = *StartTime;

    if (days < 1) {
	days += lbRTC_WEEK;
    }
    /* アラーム日付を求める */
    alarmTime.hour = 0;
    alarmTime.min = 0;
    alarmTime.sec = 0;
    lbRTC_Add_DD(&alarmTime, days);       
    /* 現在の時間がアラーム日付を経過したかチェックする */
    return lbRTC_IsOverRTC(&alarmTime);   
}

/*
 ******************************************************************************
 *  機能 :
 *         時間の差分計算
 *  説明 :
 *         時間Ａと時間Ｂの差を求める。
 *  制限 :
 *         最大差分時間は, lbRTC_MAX_INTERVAL_TIME_e。
 *  入力 :
 *         *a_time : 時間Ａ
 *         *b_time : 時間Ｂ
 *  出力 :
 *         lbRTC_IntervalTime() != 0 : 差分時間(分単位)
 *         lbRTC_IntervalTime() == 0 : 差がないか (時間Ａ < 時間Ｂ) の場合。
 ******************************************************************************
 */
extern unsigned int lbRTC_IntervalTime(const lbRTC_time_c *a_time,
				       const lbRTC_time_c *b_time)
{
    /*
     *   osRTCGetIntervalTime()は, ソフトにより演算なので RTC が停止していても
     * 問題ない。
     */
#if 0
    return (unsigned int)osRTCGetIntervalTime(b_time, a_time);
#else /* osRTCGetIntervalTimeの引数がconstになってないのでクッション変数をかます */
    {
        lbRTC_time_c a_time1 = *a_time;
        lbRTC_time_c b_time1 = *b_time;

        return (unsigned int)osRTCGetIntervalTime(&b_time1, &a_time1);
    }
#endif
}
/*
 ******************************************************************************
 *  機能 :
 *         日数差を得る
 *  説明 :
 *         時間Ａから時間Ｂまでの日数差を求める。
 *         （時間Ａ ≦ 時間Ｂ であること）
 *  入力 :
 *         *i_TimeA : 時間Ａ
 *         *i_TimeB : 時間Ｂ
 *  出力 :
 *         lbRTC_GetIntervalDays() : 時間Ａと時間Ｂの日数差
 ******************************************************************************
 */
extern int lbRTC_GetIntervalDays(const lbRTC_time_c *i_TimeA, const lbRTC_time_c *i_TimeB)
{
  static const int total_days[2][lbRTC_MONTH_NUM + 1] =
  {
      {0,31,59,90,120,151,181,212,243,273,304,334,365},
      {0,31,60,91,121,152,182,213,244,274,305,335,366}
  };
  
  int  four_years = (i_TimeB->year - i_TimeA->year) / 4;   /* 差を４年単位に*/
  int  surplus_years = (i_TimeB->year - i_TimeA->year) % 4;/* 上の余りを作成 */
  int  i_TimeA_leap = ((i_TimeA->year % 4)==0);          /* 開始年が閏年か？ */
  int  i_TimeB_leap = ((i_TimeB->year % 4)==0);          /* 終了年が閏年か？ */
  int  add_leap = (((4 - (i_TimeA->year % 4)) % 4)
		   < surplus_years);                     /* 余りの年の閏年 */
  int  days;

  if(i_TimeA->year > i_TimeB->year) {
      return(0);
  }
  else {
      if(i_TimeA->year == i_TimeB->year) {
	  if(i_TimeA->month > i_TimeB->month) {
	      return(0);
	  }
	  else {
	      if(i_TimeA->month == i_TimeB->month) {
		  if(i_TimeA->day > i_TimeB->day) {
		      return(0);
		  }
		  else {
		      if(i_TimeA->day == i_TimeB->day) {
			  if(i_TimeA->hour > i_TimeB->hour) {
			      return(0);
			  }
			  else {
			      if(i_TimeA->hour == i_TimeB->hour) {
				  if(i_TimeA->min > i_TimeB->min) {
				      return(0);
				  }
			      }
			  }
		      }
		  }
	      }
	  }
      }
  }
  
  /* 日数差の計算
   * ４年＝３６５＊３＋３６６＝１４６１
   * これに余った年数＊３６５を加え、最後に閏年が余りに存在すれば１日加算する。
   */
  days = four_years * 1461 + surplus_years * 365 + add_leap;
  /* ＋最後の年の１月１日からの日にち */
  days += (i_TimeB->day - 1);              /* ＋その月の日数 */
  days += total_days[i_TimeB_leap]
                    [i_TimeB->month - 1];  /* ＋前の月までの合計日数 */
  /* −最初の年の１月１日からの日にち */
  days -= (i_TimeA->day - 1);             /* −その月の日数 */
  days -= total_days[i_TimeA_leap]
                    [i_TimeA->month - 1]; /* −前の月までの合計日数 */

  return days;
}

/*
 ******************************************************************************
 *  機能 :
 *         年数の加算
 *  説明 :
 *         指定日付に年数を加算する。
 *  制限 :
 *         計算結果が保証されるのは 2099年まで。
 *  入力 :
 *         *dTime : 加算される日付のポインター
 *         Year   : 加算する年数
 *  出力 :
 *         *dTime : 加算された日付のポインター
 ******************************************************************************
 */
extern void lbRTC_Add_YY(lbRTC_time_c *dTime, int Year)
{
    dTime->year += (lbRTC_YY_t)Year;
}

/*
 ******************************************************************************
 *  機能 :
 *         月数の加算
 *  説明 :
 *         指定日付に月数を加算する。
 *  入力 :
 *         *dTime : 加算される日付のポインター
 *         Month  : 加算する月数
 *  出力 :
 *         *dTime : 加算された日付のポインター
 ******************************************************************************
 */
extern void lbRTC_Add_MM(lbRTC_time_c *dTime, int Month)
{
    int  c_month = (int)dTime->month;

    c_month += Month;
    if (c_month > lbRTC_DECEMBER) {
	lbRTC_Add_YY(dTime, c_month / lbRTC_MONTH_NUM);
	c_month %= lbRTC_MONTH_NUM;
    }
    dTime->month = (lbRTC_MM_t)c_month;
}

/*
 ******************************************************************************
 *  機能 :
 *         日数の加算
 *  説明 :
 *         指定日付に日数を加算する。
 *  制限 :
 *         加算日数の最大値は lbRTC_MAX_ADD_DATE_e 日。それ以上の日数の場合は。
 *       結果が保証されない。
 *  入力 :
 *         *dTime : 加算される日付のポインター
 *         Day    : 加算する日数
 *  出力 :
 *         *dTime : 加算された日付のポインター
 ******************************************************************************
 */
#define	lbRTC_IS_LEAP_YEAR(x)	((((x) % 4) == 0) ? TRUE : FALSE)

/*
extern void lbRTC_Add_DD(lbRTC_time_c *dTime, int Days)
{
    int  MMdays = (int)lbRTC_GetDaysByMonth(dTime->year,
					    (lbRTC_MM_t)(dTime->month));
    int  c_day = (int)dTime->day;

    c_day += Days;

    if (c_day > MMdays) {
	c_day -= MMdays;
	lbRTC_Add_MM(dTime, 1);
    }
    dTime->day = (lbRTC_DD_t)c_day;
}
*/

extern int lbRTC_Add_DD(lbRTC_time_c *dTime, int Days)
{
    int ret = 0;
    int MMdays = (int)lbRTC_GetDaysByMonth(dTime->year,
					    (lbRTC_MM_t)(dTime->month));
    int c_day = (int)dTime->day;
    int MMdays_2 = 0;

    c_day += Days;

    if (c_day > MMdays) {
	c_day -= MMdays;
	lbRTC_Add_MM(dTime, 1);
        MMdays_2 = (int)lbRTC_GetDaysByMonth(dTime->year,
                                             (lbRTC_MM_t)(dTime->month));
        if (c_day > MMdays_2) {
            ret = c_day - MMdays_2;
            c_day = MMdays_2;
        }
    }
    dTime->day = (lbRTC_DD_t)c_day;

    return ret;
}

/*
 ******************************************************************************
 *  機能 :
 *         時間の加算
 *  説明 :
 *         指定日付に時間を加算する。
 *  入力 :
 *         *dTime : 加算される日付のポインター
 *         Hour   : 加算する時間
 *  出力 :
 *         *dTime : 加算された日付のポインター
 ******************************************************************************
 */

/*
extern void lbRTC_Add_hh(lbRTC_time_c *dTime, int Hour)
{
    int  c_hour = (int)dTime->hour;

    c_hour += Hour;
    if (c_hour >= lbRTC_HOURS) {
	lbRTC_Add_DD(dTime, c_hour / lbRTC_HOURS);
	c_hour %= lbRTC_HOURS;
    }
    dTime->hour = (lbRTC_hh_t)c_hour;
}
*/

extern void lbRTC_Add_hh(lbRTC_time_c *dTime, int Hour)
{
    int days = 0;
    int  c_hour = (int)dTime->hour;

    c_hour += Hour;
    if (c_hour >= lbRTC_HOURS) {
        days = lbRTC_Add_DD(dTime, c_hour / lbRTC_HOURS);
        while (days!=0) 
            days = lbRTC_Add_DD(dTime, days);
	
	c_hour %= lbRTC_HOURS;
    }
    dTime->hour = (lbRTC_hh_t)c_hour;
}

/*
 ******************************************************************************
 *  機能 :
 *         分の加算
 *  説明 :
 *         指定日付に分数を加算する。
 *  入力 :
 *         *dTime : 加算される日付のポインター
 *         Minute : 加算する分数
 *  出力 :
 *         *dTime : 加算された日付のポインター
 ******************************************************************************
 */
extern void lbRTC_Add_mm(lbRTC_time_c *dTime, int Minute)
{
    int  c_minute = (int)dTime->min;

    c_minute += Minute;
    if (c_minute >= lbRTC_MINUTES) {
	lbRTC_Add_hh(dTime, c_minute / lbRTC_MINUTES);
	c_minute %= lbRTC_MINUTES;
    }
    dTime->min = (lbRTC_mm_t)c_minute;
}

/*
 ******************************************************************************
 *  機能 :
 *         秒の加算
 *  説明 :
 *         指定日付に秒を加算する。
 *  入力 :
 *         *dTime  : 加算される日付のポインター
 *         Seccond : 加算する秒数
 *  出力 :
 *         *dTime : 加算された日付のポインター
 ******************************************************************************
 */
extern void lbRTC_Add_ss(lbRTC_time_c *dTime, int Seccond)
{
    int  c_seccond = (int)dTime->sec;

    c_seccond += (int)Seccond;
    if (c_seccond >= lbRTC_SECCONDS) {
	lbRTC_Add_mm(dTime, c_seccond / lbRTC_SECCONDS);
	c_seccond %= lbRTC_SECCONDS;
    }
    dTime->sec = (lbRTC_mm_t)c_seccond;
}

/*
 ******************************************************************************
 *  機能 :
 *         日付の加算
 *  説明 :
 *         指定日付 *dTime に指定の日付 *sTime を加算する。
 *  入力 :
 *         *dTime : 加算される日付のポインター
 *         *sTime : 加算する日付のポインター
 *  出力 :
 *         *dTime : 加算された日付のポインター
 ******************************************************************************
 */
extern void lbRTC_Add_Date(lbRTC_time_c *dTime, const lbRTC_time_c *sTime)
{
    lbRTC_Add_ss(dTime, (int)sTime->sec);
    lbRTC_Add_mm(dTime, (int)sTime->min);
    lbRTC_Add_hh(dTime, (int)sTime->hour);
    lbRTC_Add_DD(dTime, (int)sTime->day);
    lbRTC_Add_MM(dTime, (int)sTime->month);
    lbRTC_Add_YY(dTime, (int)sTime->year);
}

/*
 ******************************************************************************
 *  機能 :
 *         年数の減算
 *  説明 :
 *         指定日付に年数を減算する。
 *  制限 :
 *         計算結果が保証されるのは 2099年まで。
 *  入力 :
 *         *dTime : 減算される日付のポインター
 *         Year   : 減算する年数
 *  出力 :
 *         *dTime : 減算された日付のポインター
 ******************************************************************************
 */
extern void lbRTC_Sub_YY(lbRTC_time_c *dTime, int Year)
{
    dTime->year -= (lbRTC_YY_t)Year;
}

/*
 ******************************************************************************
 *  機能 :
 *         月数の減算
 *  説明 :
 *         指定日付に月数を減算する。
 *  入力 :
 *         *dTime : 減算される日付のポインター
 *         Month  : 減算する月数
 *  出力 :
 *         *dTime : 減算された日付のポインター
 ******************************************************************************
 */
extern void lbRTC_Sub_MM(lbRTC_time_c *dTime, int Month)
{
    int  t_month;

    t_month = (int)dTime->month - Month;
    if (t_month < lbRTC_JANUARY) {
	int  t_sub_month = t_month;
	int  t_sub_year;

	if (t_month == 0) {
	    t_month = lbRTC_DECEMBER;
	    t_sub_year = 1;
	}
	else {
	    t_sub_month = ABS(t_month);
	    t_sub_year = t_sub_month / lbRTC_MONTH_NUM + 1;
	    t_month = lbRTC_MONTH_NUM - (t_sub_month % lbRTC_MONTH_NUM);
	}
	lbRTC_Sub_YY(dTime, t_sub_year);
    }
    dTime->month = (lbRTC_MM_t)t_month;
}

/*
 ******************************************************************************
 *  機能 :
 *         日数の減算
 *  説明 :
 *         指定日付に日数を減算する。
 *  制限 :
 *         減算日数の最大値は lbRTC_MAX_SUB_DATE_e 日。それ以上の日数の場合は。
 *       結果が保証されない。
 *  入力 :
 *         *dTime : 減算される日付のポインター
 *         Day    : 減算する日数
 *  出力 :
 *         *dTime : 減算された日付のポインター
 ******************************************************************************
 */
extern void lbRTC_Sub_DD(lbRTC_time_c *dTime, int Days)
{
    int  day = (int)dTime->day;
    int  MMdays;
#if 0
    int  MMdays = (int)lbRTC_GetDaysByMonth(dTime->year,
					    (lbRTC_MM_t)(dTime->month - 1));
#endif

    if( dTime->month == JANUARY ){
	MMdays = (int)lbRTC_GetDaysByMonth(dTime->year,
					   (lbRTC_MM_t)(DECEMBER));
    } else {
	MMdays = (int)lbRTC_GetDaysByMonth(dTime->year,
					   (lbRTC_MM_t)(dTime->month - 1));
    }
    day -= Days;
    if (day <= 0) {
	if (day == 0) {
	    day = MMdays;
	}
	else {
	    day += MMdays;
	}
	lbRTC_Sub_MM(dTime, 1);
    }
    dTime->day = (lbRTC_DD_t)day;
}

/*
 ******************************************************************************
 *  機能 :
 *         時間の減算
 *  説明 :
 *         指定日付に時間を減算する。
 *  入力 :
 *         *dTime : 減算される日付のポインター
 *         Hour   : 減算する時間(0〜23)
 *  出力 :
 *         *dTime : 減算された日付のポインター
 ******************************************************************************
 */
extern void lbRTC_Sub_hh(lbRTC_time_c *dTime, int Hour)
{
    int  t_hour = (int)dTime->hour;

    t_hour -= Hour;
    if (t_hour < 0) {
	int  t_sub_hour = t_hour;
	int  t_sub_days;

	t_sub_hour = ABS(t_hour);
	t_sub_days = t_sub_hour / lbRTC_HOURS + 1;
	t_hour = lbRTC_HOURS - (t_sub_hour % lbRTC_HOURS);
	if (t_hour == lbRTC_HOURS) {
	    t_hour = 0;
	    t_sub_days--;
	}
	lbRTC_Sub_DD(dTime, t_sub_days);
    }
    dTime->hour = (lbRTC_hh_t)t_hour;
}

/*
 ******************************************************************************
 *  機能 :
 *         分の減算
 *  説明 :
 *         指定日付に分数を減算する。
 *  入力 :
 *         *dTime : 減算される日付のポインター
 *         Minute : 減算する分数
 *  出力 :
 *         *dTime : 減算された日付のポインター
 ******************************************************************************
 */
extern void lbRTC_Sub_mm(lbRTC_time_c *dTime, int Minute)
{
    int  t_minute = (int)dTime->min;

    t_minute -= Minute;
    if (t_minute < 0) {
	int  t_sub_minute = t_minute;
	int  t_sub_hours;

	t_sub_minute = ABS(t_minute);
	t_sub_hours = t_sub_minute / lbRTC_MINUTES + 1;
	t_minute = lbRTC_MINUTES - (t_sub_minute % lbRTC_MINUTES);
	if (t_minute == lbRTC_MINUTES) {
	    t_minute = 0;
	    t_sub_hours--;
	}
	lbRTC_Sub_hh(dTime, t_sub_hours);
    }
    dTime->min = (lbRTC_mm_t)t_minute;
}

/*
 ******************************************************************************
 *  機能 :
 *         秒の減算
 *  説明 :
 *         指定日付に秒を減算する。
 *  入力 :
 *         *dTime  : 減算される日付のポインター
 *         Seccond : 減算する秒数
 *  出力 :
 *         *dTime : 減算された日付のポインター
 ******************************************************************************
 */
extern void lbRTC_Sub_ss(lbRTC_time_c *dTime, int Second)
{
    int  t_second = (int)dTime->sec;

    t_second -= Second;
    if (t_second < 0) {
	int  t_sub_second = t_second;
	int  t_sub_minutes;

	t_sub_second = ABS(t_second);
	t_sub_minutes = t_sub_second / lbRTC_SECCONDS + 1;
	t_second = lbRTC_SECCONDS - (t_sub_second % lbRTC_SECCONDS);
	if (t_second == lbRTC_SECCONDS) {
	    t_second = 0;
	    t_sub_minutes--;
	}
	lbRTC_Sub_mm(dTime, t_sub_minutes);
    }
    dTime->sec = (lbRTC_ss_t)t_second;
}

/*
 ******************************************************************************
 *  機能 :
 *         日付の減算
 *  説明 :
 *         指定日付 *dTime に指定の日付 *sTime を減算する。
 *  入力 :
 *         *dTime : 減算される日付のポインター
 *         *sTime : 減算する日付のポインター
 *  出力 :
 *         *dTime : 減算された日付のポインター
 ******************************************************************************
 */
extern void lbRTC_Sub_Date(lbRTC_time_c *dTime, const lbRTC_time_c *sTime)
{
    lbRTC_Sub_ss(dTime, (int)sTime->sec);
    lbRTC_Sub_mm(dTime, (int)sTime->min);
    lbRTC_Sub_hh(dTime, (int)sTime->hour);
    lbRTC_Sub_DD(dTime, (int)sTime->day);
    lbRTC_Sub_MM(dTime, (int)sTime->month);
    lbRTC_Sub_YY(dTime, (int)sTime->year);
}

/*
 ******************************************************************************
 *  機能 :
 *         曜日を求める
 *  説明 :
 *         指定日付の曜日を求める。
 *  入力 :
 *         i_Year  : 年
 *         i_Month : 月
 *         i_Day   : 日
 *  出力 :
 *         lbRTC_Week() : 曜日
 ******************************************************************************
 */
extern lbRTC_WW_t lbRTC_Week(lbRTC_YY_t i_Year,
			     lbRTC_MM_t i_Month,
			     lbRTC_DD_t i_Day)
{
    static const lbRTC_time_c  a_time = {0,0,0, 1,0,1, 1901};
    lbRTC_time_c  b_time = {0,0,0, 0,0,0, 0000};
    
    b_time.year = i_Year;
    b_time.month = i_Month;
    b_time.day = i_Day;
    
    return (lbRTC_WW_t)((lbRTC_GetIntervalDays(&a_time, &b_time) + 2)
			% lbRTC_WEEK);
}

/*
 ******************************************************************************
 *  機能 :
 *         日付のコピー
 *  説明 :
 *         日付をコピーする。
 *  入力 :
 *         *dTime : 日付のコピー先のポインター
 *         *sTime : 日付のコピー元のポインター
 ******************************************************************************
 */
extern void lbRTC_TimeCopy(lbRTC_time_c *dTime, const lbRTC_time_c *sTime)
{
#if 0                           /* 12&loop */
    short  *des = (short *)dTime;
    const short  *src = (const short *)sTime;
    int    sz = sizeof(lbRTC_time_c) / sizeof(short);
    
    while(sz-- > 0) {
	*des++ = *src++;
    }
#else  /* 8+2 */
    *dTime = *sTime;
#endif
}

/*
 ******************************************************************************
 *  機能 :
 *         日付のチェック
 *  説明 :
 *         入力日付が正当な値かチェックする。
 *  制限 :
 *         1999年〜2099年内での日付を確認する。
 *  入力 :
 *         lbRTC_IsValidTime() == TRUE  : 正当な日付
 *         lbRTC_IsValidTime() == FALSE : 不当な日付
 ******************************************************************************
 */
extern int lbRTC_IsValidTime(const lbRTC_time_c *Time)
{
    static const unsigned char  day_tbl[]={
	00,
	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    int  ret;
    
    if ((Time->year < 1901) || (Time->year > 2099) ||
	(Time->month == 0) || (Time->month > 12) ||
	(Time->day == 0) ||
	(Time->hour > 23) || (Time->min > 59) || (Time->sec > 59)) {
	ret = FALSE;
    } else {
	if ((Time->day == 29) && (Time->month == 2)) {
	    ret = lbRTC_IS_LEAP_YEAR(Time->year);
	} else if (Time->day > day_tbl[Time->month]) {
	    ret = FALSE;
	} else {
	    ret = TRUE;
	}
    }
    
    return ret;

}

#if 0 /* テストプログラム */
/*
 ******************************************************************************
 *  時間の表示
 ******************************************************************************
 */
void lbRTC_PrintTime(void)
{
    lbRTC_time_c  time;
    
    lbRTC_Gettime(&time);
    PRINTF("year=%d \n", time.year);
    PRINTF("month=%d \n", time.month);
    PRINTF("day=%d \n", time.day);
    PRINTF("week=%d \n", time.week);
    PRINTF("hour=%d \n", time.hour);
    PRINTF("min=%d \n", time.min);
    PRINTF("sec=%d \n", time.sec);
}
/*
 ******************************************************************************
 *   時間越えのテスト
 ******************************************************************************
 */
void lbRTC_TestOfOverTime(void)
{
    static lbRTC_time_c  timer = {43,3,15,12,2,10,1999};
    static int  fg = 0;
    lbRTC_time_c  time;
    
    if ((lbRTC_IsOverRTC(&timer) == TRUE) && (fg == 0)) {
	lbRTC_Gettime(&time);
	PRINTF("## 時間だよ！！\n");
	PRINTF("year=%d \n", time.year);
	PRINTF("month=%d \n", time.month);
	PRINTF("day=%d \n", time.day);
	    PRINTF("week=%d \n", time.week);
	    PRINTF("hour=%d \n", time.hour);
	    PRINTF("min=%d \n", time.min);
	    PRINTF("sec=%d \n", time.sec);
	    fg = 1;
    }
}
#endif
