#include <t_services.h>
#include <cqnxparm.h>
#include "kernel_id.h"
#include "touch.h"
#include <string.h>

#define	CCR_CLKEN	(1<<0)
#define	CCR_CTCRST	(1<<1)
#define	CCR_CLKSRC	(1<<4)

#define	CIIR_IMSEC	(1<<0)
#define	CIIR_IMDOM	(1<<3)

const char *week_days[] = {
  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
};

void rtc_init(void)
{
    /* Disable RTC, Reset Counter, Select 32K Xtal */
    RTC_CCR = CCR_CTCRST | CCR_CLKSRC;
#ifdef NO_BACKUP
    RTC_SEC = RTC_MIN = RTC_HOUR = RTC_DOW = 0;
    RTC_DOM = RTC_DOY = RTC_MONTH = 1;
    RTC_YEAR = 2009;
#endif

    /* Generate Interrupt every second */
    RTC_CIIR = CIIR_IMSEC;
    RTC_CISS = 0x80 | 0x07;
    RTC_AMR = 0;

    RTC_CCR &= ~CCR_CTCRST;
    RTC_CCR |= CCR_CLKEN;
    ena_int(INTNO_RTC);
}

#define	ILR_RTCCIF	(1<<0)
#define	ILR_RTSSF	(1<<2)
static UB subsec;
static UB newdate;

/* RTC Interrupt handler */
void rtc_handler(void)
{
    int ilr;

    ilr = RTC_ILR;
    if (RTC_ILR & ILR_RTCCIF) {
        ipsnd_dtq(DTQ_EVENT, (VP_INT) (TICK_MARK | EV_TICK));
        if (newdate ||                          /* date command issued */
            (RTC_CTIME0 & 0x1f3f3f) == 0) {	/* HH:MM:SS = 00:00:00 */
            ipsnd_dtq(DTQ_EVENT, (VP_INT) (TICK_MARK | EV_MTICK));
            newdate = 0;
        }
    }
    if (RTC_ILR & ILR_RTSSF) {
        if (++subsec == 8) {	/* 500ms */
            subsec = 0;
            if ((RTC_ILR & ILR_RTCCIF) == 0) {
                ipsnd_dtq(DTQ_EVENT, (VP_INT) (TICK_MARK | EV_HTICK));
            }
        }
    }
    RTC_ILR = ILR_RTSSF | ILR_RTCCIF;
}

void date_usage()
{
    cons_printf("Usage: date MMDDhhmm [0-6]\n");
}

void date_command(int argc, char **argv)
{
    char *cp;
    int val, len, dow;

    if (argc > 1) {
        cp = argv[1];
        len = strlen(cp);
        if (len < 8) {
            date_usage();
            return;
        }
        if (argc > 2) {
            dow = atoi(argv[2]);
            if (dow < 0 || dow > 6) {
                date_usage();
                return;
            }
            RTC_DOW = dow;
        }
        if (len == 8) {	/* MMDDhhmm */
            val = atoi(cp);
            RTC_MONTH = val / 1000000;
            val %= 1000000;
            RTC_DOM = val / 10000;
            val %= 10000;
            RTC_HOUR = val / 100;
            RTC_MIN = val % 100;
            RTC_SEC = 0;
            newdate = 1;
        }
    }
    cons_printf("%d/%02d/%02d %s %02d:%02d:%02d\n",
        (RTC_CTIME1 >> 16) & 0x7ff,(RTC_CTIME1 >> 8) & 0x0f, RTC_CTIME1 & 0x1f,
        week_days[RTC_DOW],
        (RTC_CTIME0 >> 16) & 0x1f, (RTC_CTIME0 >> 8) & 0x3f, RTC_CTIME0 & 0x3f);
}
