/*********************************************************************************************
* File£º	2410rtc.c
* Author:	embest
* Desc£º	rtc operation library
* History:	
*			R.X.Huang, Programming modify, March 12, 2005
*********************************************************************************************/
/*------------------------------------------------------------------------------------------*/
/*                                     include files	                                    */
/*------------------------------------------------------------------------------------------*/
#include "2410lib.h"
#include "rtc_test.h"

/*------------------------------------------------------------------------------------------*/
/*                                     global variables                                     */
/*------------------------------------------------------------------------------------------*/
INT8T *day[8] = {" ","SUN","MON","TUE","WED","THR","FRI","SAT"};
INT32T g_nYear,g_nMonth,g_nDate,g_nWeekday,g_nHour,g_nMin,g_nSec;

volatile INT32T f_nIsRtcInt;
volatile UINT32T f_unTickCount;

/*********************************************************************************************
* name:		rtc_init
* func:		rtc init
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void rtc_init(void)
{
    rRTCCON  = rRTCCON  & ~(0xf)  | 0x1;	// No reset, Merge BCD counters, 1/32768, RTC Control enable
    
    rBCDYEAR = rBCDYEAR & ~(0xff) | TESTYEAR;
    rBCDMON  = rBCDMON  & ~(0x1f) | TESTMONTH;
    rBCDDATE = rBCDDATE & ~(0x3f) | TESTDATE;         
    rBCDDAY  = rBCDDAY  & ~(0x7)  | TESTDAY;// SUN:1 MON:2 TUE:3 WED:4 THU:5 FRI:6 SAT:7
    rBCDHOUR = rBCDHOUR & ~(0x3f) | TESTHOUR;
    rBCDMIN  = rBCDMIN  & ~(0x7f) | TESTMIN;
    rBCDSEC  = rBCDSEC  & ~(0x7f) | TESTSEC;
    
    rRTCCON  = 0x0;							// No reset, Merge BCD counters, 1/32768, RTC Control disable    
}

/*********************************************************************************************
* name:		rtc_display
* func:		display rtc value
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void rtc_display(void)
{
    INT32T nTmp; 
	// INT32T nKey;                  

    uart_printf("\n Display current Date and time: \n");

	rRTCCON = 0x01;	// No reset, Merge BCD counters, 1/32768, RTC Control enable
    uart_printf(" Press any key to exit.\n");
    while(!uart_getkey())
    {    
        while(1)
        {
            if(rBCDYEAR==0x99) 
                g_nYear = 0x1999;
            else 
                g_nYear    = 0x2000 + rBCDYEAR;
            g_nMonth   = rBCDMON;
            g_nWeekday = rBCDDAY;
            g_nDate    = rBCDDATE;
            g_nHour    = rBCDHOUR;
            g_nMin     = rBCDMIN;
            g_nSec     = rBCDSEC;
            
            if(g_nSec!=nTmp)                // Same time is not display
            {
                nTmp = g_nSec;
                break;
           }         
       }
        uart_printf(" %02x:%02x:%02x  %10s,  %02x/%02x/%04x\r",g_nHour,g_nMin,g_nSec,day[g_nWeekday],g_nMonth,g_nDate,g_nYear);
//		uart_printf(" %02x:%02x:%02x  %9s,  %2x/%2x/%4x     rBCDDATE = %x, g_nWeekday= %x\n",g_nHour,g_nMin,g_nSec,day[g_nWeekday],g_nMonthg_nDatee,g_nYear,rBCDDATE,g_nWeekday);        
   }
	rRTCCON = 0x0;	// No reset, Merge BCD counters, 1/32768, RTC Control disable(for power consumption)
    
    uart_printf("\n\n Exit display.\n");
}

/*********************************************************************************************
* name:		rtc_set
* func:		set a new g_nDate & time to rtc
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void rtc_set(void)
{
    uart_printf("\n Please input 0x and Two digit then press Enter, such as 0x99.\n");
    uart_printf(" Year  (0x??): ");
    g_nYear = uart_getintnum();
    
    uart_printf(" Month (0x??): ");
    g_nMonth = uart_getintnum();
    
    uart_printf(" Date  (0x??): ");
    g_nDate = uart_getintnum();
          
    uart_printf("\n 1:Sunday 2:Monday 3:Thesday 4:Wednesday 5:Thursday 6:Friday 7:Saturday\n");
    uart_printf(" Day of week : ");
    g_nWeekday = uart_getintnum();
    
    uart_printf("\n Hour  (0x??): ");
    g_nHour = uart_getintnum();
    
    uart_printf(" Minute(0x??): ");
    g_nMin = uart_getintnum();
    
    uart_printf(" Second(0x??): ");
    g_nSec = uart_getintnum();
    
    rRTCCON  = rRTCCON  & ~(0xf)  | 0x1;// No reset, Merge BCD counters, 1/32768, RTC Control enable
    
    rBCDYEAR = rBCDYEAR & ~(0xff) | g_nYear;
    rBCDMON  = rBCDMON  & ~(0x1f) | g_nMonth;
    rBCDDAY  = rBCDDAY  & ~(0x7)  | g_nWeekday;// SUN:1 MON:2 TUE:3 WED:4 THU:5 FRI:6 SAT:7
    rBCDDATE = rBCDDATE & ~(0x3f) | g_nDate;
    rBCDHOUR = rBCDHOUR & ~(0x3f) | g_nHour;
    rBCDMIN  = rBCDMIN  & ~(0x7f) | g_nMin;
    rBCDSEC  = rBCDSEC  & ~(0x7f) | g_nSec;
    
	rRTCCON  = 0x0;						//  No reset, Merge BCD counters, 1/32768, RTC Control disable    
}

/*********************************************************************************************
* name:		rtc_read
* func:		read data from rtc
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void rtc_read(void)
{
	while(1)
	{
		// read the data from RTC registers
		if(rBCDYEAR == 0x99) 
			g_nYear = 0x1999;
		else 
	    	g_nYear = 0x2000 + rBCDYEAR;
	    	
		g_nMonth   = rBCDMON;
		g_nWeekday = rBCDDAY;
		g_nDate    = rBCDDATE;
		g_nHour    = rBCDHOUR;
		g_nMin     = rBCDMIN;
		g_nSec     = rBCDSEC;
		
		if(g_nSec != 0)
	    	break;
	}	 
}

/*********************************************************************************************
* name:		rtc_round_reset
* func:		test rtc round reset function
* para:		none
* ret:		
* modify:
* comment:		
* 			Round boundary 30, 40 or 50 g_nSec
* 			For example, when the current time is 23:37:47 and the round baundary is selected to 40 g_nSec,
* 			the round reset changes the current time is 23:38:00.
*********************************************************************************************/  
void rtc_round_reset(void)
{
    UINT32T save_GPFCON;

    uart_printf("\n RTC Round Reset Test for S3C2410 \n");
    save_GPFCON = rGPFCON;

    rEXTINT0 = 0x2;					// Falling edge triggered
    rGPFCON  = 0x2;					// EINT0

    pISR_EINT0 = (unsigned int)rtc_int0_int;
    rINTMSK   &= ~(BIT_EINT0);

	// rtc_init();
	rRTCCON = 0x01;					// No reset, Merge BCD counters, 1/32768, RTC Control enable
    uart_printf(" Press any key to exit.\n\n");
    uart_printf(" Press EINT0 nKey to test round reset.\n");
    uart_printf(" *If seconds >=30s, add 1 to minute, else clear second as 0.\n");
    
    while(!uart_getkey())
		uart_printf(" %02x:%02x:%02x\r",rBCDHOUR,rBCDMIN,rBCDSEC);        
	rINTMSK |= BIT_EINT0;
	rRTCCON = 0x0;					// No reset, Merge BCD counters, 1/32768, RTC Control disable
    rGPFCON = save_GPFCON;
}

/*********************************************************************************************
* name:		rtc_alarm_test
* func:		test rtc alarm
* para:		none
* ret:		f_nIsRtcInt = 0 : rtc not work
*	        f_nIsRtcInt = 1 : rtc work fine
* modify:
* comment:		
*********************************************************************************************/  
int rtc_alarm_test(void)  
{
    // INT32T g_nHour=0xff0000,g_nMin=0xff00,g_nSec=0xff;
    uart_printf(" RTC Alarm Test for S3C2410 \n");

    // rtc_init();
    rRTCCON  = 0x01;				// No reset, Merge BCD counters, 1/32768, RTC Control enable
    rALMYEAR = rBCDYEAR ;
    rALMMON  = rBCDMON;
    rALMDATE = rBCDDATE  ;
    rALMHOUR = rBCDHOUR ;
    rALMMIN  = rBCDMIN  ;
    rALMSEC  = rBCDSEC + 2; 
    f_nIsRtcInt = 0;
    pISR_RTC = (unsigned int)rtc_int;
    rRTCALM  = 0x7f;				// Global,g_nYear,g_nMonth,Day,g_nHour,Minute,Second alarm enable
    rRTCCON  = 0x0;					// No reset, Merge BCD counters, 1/32768, RTC Control disable
    rINTMSK &= ~(BIT_RTC);

	uart_printf(" %02x:%02x:%02x\n",rBCDHOUR,rBCDMIN,rBCDSEC);        
    // while(f_nIsRtcInt==0);
    delay(21000);					// delay 2.1s
	uart_printf(" %02x:%02x:%02x\n",rBCDHOUR,rBCDMIN,rBCDSEC);        

    rINTMSK |= BIT_RTC;
    rRTCCON  = 0x0;					// No reset, Merge BCD counters, 1/32768, RTC Control disable    
    return f_nIsRtcInt;
}

/*********************************************************************************************
* name:		rtc_tick_test
* func:		test rtc tick
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void rtc_tick_test(void)
{
    uart_printf("\n RTC Tick interrupt(1 g_nSec) test for S3C2410 \n");
    uart_printf(" Press any key to exit.\n"); 
        
    pISR_TICK = (unsigned)rtc_tick;
    f_unTickCount  = 1;
    rINTMSK  &= ~(BIT_TICK); 
    rRTCCON   = 0x0;            // No reset[3], Merge BCD counters[2], BCD clock select XTAL[1], RTC Control disable[0]
    rTICNT    = (1<<7) + 127;   // Tick time interrupt enable, Tick time count value 127
                                // Period = (n + 1) / 128 second    n:Tick time count value(1~127)
    uart_getch();
    uart_printf("\n");
    rINTMSK  |= BIT_TICK;
    rRTCCON   = 0x0;            // No reset[3], Merge BCD counters[2], BCD clock select XTAL[1], RTC Control disable[0]
}

/*********************************************************************************************
* name:		rtc_check
* func:		check rtc working or not
* para:		none
* ret:		cRtcAlarm = 0:
*			cRtcAlarm = 1: ok
* modify:
* comment:		
*********************************************************************************************/
char rtc_check(void)
{
	INT8T cRtcAlarm = 0;
	INT8T cYn = 0x59;
   
	// check RTC
	while((cYn == 0x0d)|(cYn == 0x59)|(cYn == 0x79)|(cRtcAlarm == 0))
	{
		uart_printf(" RTC Check(Y/N)? ");
       
		// get data from keybroad
		cYn = uart_getch();
		uart_printf("%c\n",cYn);
		if((cYn == 0x0d)|(cYn == 0x59)|(cYn == 0x79))
			cRtcAlarm = rtc_alarm_test();// test rtc alarm
		else break;
		if (cRtcAlarm) break;
	}
	return cRtcAlarm;   
}

/*********************************************************************************************
* name:		rtc_test
* func:		rtc test main function
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void rtc_test(void)
{
	INT32T	nKey;
	
	//  user interface
	uart_printf("\n RTC Test Example\n"); 
	 
	//  check if rtc work normally
	if(!rtc_check())
		uart_printf("! Please check RTC, maybe it's Wrong. \n");
	else
	{
		uart_printf(" 0. RTC Time Setting    1. Only RTC Display\n");
		uart_printf(" Please Selet : ");
		nKey = uart_getintnum();
		
	    if(!nKey)
	    {
			rtc_init(); 
	    	rtc_set();				// set a new g_nDate and time
	    }
	}
	
	rtc_display();					// display current time
	
	// rtc_tick_test();
	// rtc_round_reset();

	uart_printf(" end.\n");
}

/*********************************************************************************************
* name:		rtc_int0_int
* func:		EINT0 interrupt handler
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void   __irq rtc_int0_int(void)
{
	ClearPending(BIT_EINT0);

	rRTCRST = (1<<3) | 3;			// Round second reset enable, over than 30 g_nSec
}

/*********************************************************************************************
* name:		rtc_int
* func:		rtc interrupt handler
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void  __irq  rtc_int(void)
{
	ClearPending(BIT_RTC);   

    uart_printf(" RTC Alarm Interrupt O.K.\n");
    f_nIsRtcInt = 1;  
}

/*********************************************************************************************
* name:		rtc_tick
* func:		rtc tick
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void  __irq  rtc_tick(void)
{
	ClearPending(BIT_TICK);   

	uart_printf(" %03d seconds\r",f_unTickCount++);
}
