/************************************************************************/
/* Copyright 1990 - 1997 MBARI                                          */
/************************************************************************/
/* $Header: rtc.c,v 1.2 91/09/23 09:38:59 hebo Exp $                    */
/* Summary  : Functions to read time from MK48T08 chip on MVME-162 CPU  */
/*              under vxWorks                                           */
/* Filename : rtc.c                                                     */
/* Author   : Bob Herlien (rah)                                         */
/* Project  : Tiburon ROV                                               */
/* $Revision: 1.2 $                                                     */
/* Created  : 02/28/91                                                  */
/************************************************************************/
/* Modification History:                                                */
/* $Log:        rtc.c,v $
 * Revision 1.2  91/09/23  09:38:59  09:38:59  hebo (Bob Herlien 408-647-3748)
 * Minor bug fixes, added -DMICROTIME
 *
 * Revision 1.1  91/09/06  16:05:35  16:05:35  hebo (Bob Herlien 408-647-3748)
 * Initial revision
 *
 * Revision 1.0  91/08/09  11:10:33  11:10:33  hebo (Bob Herlien 408-647-3748)
 * Initial revision
 *      */
/* 28feb91 rah, created                                                 */
/************************************************************************/
/* The Unix Epoch (day 0) is Jan 1, 1970.  The real-time clock chip     */
/* only gives 2 decimal digits of year.  Also, a Unix time_t value      */
/* (signed long) can only go +/- 68 years from 1970.  Therefore, these  */
/* routines assume that the year is between 1970 and 2070.  Note that   */
/* the leap-year exception for centuries not divisible by 400 is not a  */
/* factor in this period.                                               */
/************************************************************************/

#include <mbariTypes.h>                 /* MBARI standard types             */
#include <vxWorks.h>                    /* VxWorks includes                 */
#include <time.h>                       /* struct tm definition             */
#include <sys/times.h>                  /* struct timeval, timezone defns   */
#include <usrTime.h>                    /* time structure definitions       */
#include "mv162.h"                      /* Hardware defns for MVME-162      */


/* Defines for MK48T08 Real-Time Clock Chip on MVME-162 */

#define RTC(x)          ((unsigned char *)(TOD_CLOCK + x))

#define RTC_CTRL        RTC(0)          /* Control byte of RTC chip         */
#define RTC_SECS        RTC(1)          /* Seconds on RTC chip      */
#define RTC_MINS        RTC(2)          /* Minutes on RTC chip      */
#define RTC_HR          RTC(3)          /* Hours on RTC chip                */
#define RTC_DAY         RTC(4)          /* Day of week (1 - 7) on RTC chip */
#define RTC_DATE        RTC(5)          /* Date (1 - 31) on RTC chip        */
#define RTC_MONTH       RTC(6)          /* Month on RTC chip                */
#define RTC_YR          RTC(7)          /* Year (00 - 99) on RTC chip    */

#define STOP_BIT        0x80            /* "Stop Clock" bit in seconds field*/
#define WRITE_BIT       0x80            /* "Write" bit in control byte      */
#define READ_BIT        0x40            /* "Read" bit in control byte       */


/********************************/
/*      External Functions      */
/********************************/

Extern Int32 julday( Int32 yr, Int32 mo, Int32 day );
Extern Int32 ep_days( Int32 year, Int32 yday );


/************************************************************************/
/* Function    : bcd_to_hex                                             */
/* Purpose     : BCD to hex conversion                                  */
/* Input       : BCD byte                                               */
/* Outputs     : Hex byte                                               */
/************************************************************************/
        Int32
bcd_to_hex( Int32 byte )
{
    return( (10 * (byte>>4)) + (byte & 0xf) );

} /* bcd_to_hex() */


/************************************************************************/
/* Function    : hex_to_bcd                                             */
/* Purpose     : Hex to BCD conversion                                  */
/* Input       : Hex byte                                               */
/* Outputs     : BCD byte                                               */
/************************************************************************/
        Int32
hex_to_bcd( Int32 byte )
{
    return( ((byte / 10) << 4) + (byte % 10) );

} /* hex_to_bcd() */


/************************************************************************/
/* function    : rtc_on                                                 */
/* purpose     : Make sure rtc chip is running                          */
/* inputs      : None                                                   */
/* outputs     : None                                                   */
/************************************************************************/
        Void
rtc_on( Void )
{
    if ( *RTC_SECS & STOP_BIT )         /* Clock stopped?               */
        *RTC_SECS &= ~STOP_BIT;         /* Start it                     */

} /* rtc_on() */


/************************************************************************/
/* Function    : sysRtcRead                                             */
/* Purpose     : Read the RTC chip, put the results in struct tm *tp    */
/* Inputs      : Pointer to struct tm to put current time into          */
/* Outputs     : Time in time_t format                                  */
/************************************************************************/
        time_t
sysRtcRead( struct tm *tp )
{
    time_t      rtn;
    struct tm   temp_tm;

    rtc_on();                           /* Make sure RTC is running     */

    if ( tp == (struct tm *)NULL )      /* If no tm, use temp one       */
        tp = &temp_tm;

    *RTC_CTRL |= READ_BIT;              /* Stop updating clock          */
    tp->tm_sec = bcd_to_hex(*RTC_SECS & 0x7f);
    tp->tm_min = bcd_to_hex(*RTC_MINS & 0x7f);
    tp->tm_hour = bcd_to_hex(*RTC_HR & 0x3f);
    tp->tm_mday = bcd_to_hex(*RTC_DATE & 0x3f);
    tp->tm_mon = bcd_to_hex(*RTC_MONTH & 0x1f) - 1;
    tp->tm_year = bcd_to_hex(*RTC_YR);
    if ( tp->tm_year < YEAR0 )          /* RTC_YR 00 is actual year 2000*/
        tp->tm_year += 100;
    tp->tm_wday = (*RTC_DAY & 7) - 1;
    *RTC_CTRL &= ~(WRITE_BIT | READ_BIT); /* Restart clock updating     */
    tp->tm_yday = julday( (tp->tm_year % 100), tp->tm_mon, tp->tm_mday ) - 1;
    tp->tm_isdst = 0;

    rtn = ep_days(tp->tm_year - YEAR0, tp->tm_yday) * SECS_PER_DAY;
    rtn += (tp->tm_hour * 3600L) + (tp->tm_min * 60) + tp->tm_sec;
    return( rtn );

} /* sysRtcRead() */


/************************************************************************/
/* Function    : sysRtcWrite                                            */
/* Purpose     : Write the RTC chip from the values of struct tm *tp    */
/* Inputs      : Pointer to struct tm that contains current time        */
/* Outputs     : None                                                   */
/************************************************************************/
        Void
sysRtcWrite( const struct tm *tp )
{
    rtc_on();                           /* Make sure RTC is running     */
    *RTC_CTRL |= WRITE_BIT;             /* Stop the clock               */

    *RTC_SECS = (char)(hex_to_bcd(tp->tm_sec) & 0x7f);
    *RTC_MINS = (char)(hex_to_bcd(tp->tm_min) & 0x7f);
    *RTC_HR   = (char)(hex_to_bcd(tp->tm_hour) & 0x3f);
    *RTC_DAY  = (char)((tp->tm_wday + 1) & 7);
    *RTC_DATE = (char)(hex_to_bcd(tp->tm_mday) & 0x3f);
    *RTC_MONTH = (char)(hex_to_bcd(tp->tm_mon + 1) & 0x1f);
    *RTC_YR   = (char)hex_to_bcd(tp->tm_year % 100);

    *RTC_CTRL &= ~(WRITE_BIT | READ_BIT); /* Restart clock              */

} /* sysRtcWrite() */
