/*******************************************************************************
 * (c) Copyright 2015 Microsemi Corporation.  All rights reserved.
 *
 *
 *
 * SVN $Revision: $
 * SVN $Date: $
 */

#include <api_oam_sdk/metroam_hal/inc/mr_hal.h>
#include <time.h>
#include <stdio.h>

#include "osal.h"
#include "rtc.h"

#include "egl_assert.h"
#include "egl_log.h"

//VR uncommented declarations
static uint16_t		log_handle	= 0;			// handle used to log messages for this module
static osMutex_t	rtcLock		= NULL;			// Mutex to protect access to the RTC

void rtcGetTime(rtcRaw_t *rtcTime)
{
#ifdef FREERTOS
	osMutexTake(rtcLock,0);	// Make this function thread safe

	// The registers should always be read in this order as HW latches the
	// Upper (seconds) register when the lower (nanoSec) register is read
	// This guarantees atomic read of the full 64-bit time value
	mrHalRegRead(RTC_VAL_LOWER_REG_ADDR,&rtcTime->nanoSec);
	mrHalRegRead(RTC_VAL_UPPER_REG_ADDR,&rtcTime->seconds);
	osMutexGive(rtcLock);
#else
	//  little pointer abuse but data types are essentially the same
	clock_gettime(CLOCK_REALTIME,(struct timespec*)rtcTime);
#endif
}

char* rtcGetTimeStr(void)
{
	rtcRaw_t 	rtcTime;
	struct tm 	*currtime;
	static char	tStr[40];

	// Get the current RTC time
	rtcGetTime(&rtcTime);
	// Convert it to local time
	currtime = localtime((time_t *)&rtcTime.seconds);

	sprintf(tStr,"%d-%02d-%02dT%02d:%02d:%02d.%u",currtime->tm_year+1900,currtime->tm_mon+1,currtime->tm_mday,
				currtime->tm_hour,currtime->tm_min,currtime->tm_sec,(rtcTime.nanoSec/1000));
	return tStr;
}

void rtcSetTime(rtcRaw_t rtcTime)
{
#if FREERTOS
	osMutexTake(rtcLock,0);	// Make this function thread safe
#endif
	// The registers should always be written in this order as HW holds the
	// lower (nanoSec) register value until the Upper (seconds) register is
	// written and both are written together
	// This guarantees atomic write of the full 64-bit time value
	mrHalRegWrite(RTC_VAL_LOWER_REG_ADDR,rtcTime.nanoSec);
	mrHalRegWrite(RTC_VAL_UPPER_REG_ADDR,rtcTime.seconds);
#if FREERTOS
	osMutexGive(rtcLock);

	//DO_LOG_NOTICE(log_handle,"The system time is set to %s",ctime((long*)&rtcTime.seconds));
#else
	fprintf(stderr,"The HW RTC time is set to %s",ctime((long*)&rtcTime.seconds));
#endif
}

void rtcInit(void)
{
#ifdef FREERTOS
	rtcRaw_t newTime;

	log_init();

	// Get a log handle if we don't already have one
	if (log_handle == 0)
	{
		log_handle = log_register("RTC");
	}
	// Set the default logging level to debug for this module
	log_setLevelNotice(log_handle);

	// Create a mutex to protect access to the clock time
	if (rtcLock == NULL)
	{
		rtcLock  = osMutexCreate();
	}
	ASSERT_NOT_NULL(rtcLock);

	struct tm startTime;
	startTime.tm_sec 	= 0;    // Seconds
	startTime.tm_min	= 0;    // Minutes
	startTime.tm_hour	= 12;   // Hours
	startTime.tm_mday	= 16;	// Day of Month
	startTime.tm_mon	= 6;	// Month
	startTime.tm_year	= 115;	// Year

	newTime.seconds = mktime(&startTime),0;
	newTime.nanoSec = 0;
	rtcSetTime(newTime);
#else
	rtcRaw_t rtcTime;

	// Get the system clock time
	clock_gettime(CLOCK_REALTIME,(struct timespec*)&rtcTime);
	// Apply the system time to the HW RTC
	rtcSetTime(rtcTime);
#endif
}

