/***************************************************************************/
/*  Author           : P.H. Seerden                                        */
/*  Description      : Driver for the PCF2129A RTC hardware interface on   */
/*                     the MicroCore48 rev A board.                        */
/*                                                                         */
/*                  (C) Copyright 2012 NXP Semiconductors                  */
/*                                                                         */
/***************************************************************************/

#include <LPC11Uxx.h>                              // LPC11Uxx definitions
#include "ssp0.h"
#include "command.h"
#include "uart.h"

static SSP_MSG msg;                                // PCF2129A RTC SSP message
static WORD    wrBuf[8];                           // PCF2129A RTC write buffer
static WORD    rdBuf[8];                           // PCF2129A RTC read buffer

union {
    BYTE buf[7];
    struct {
    BYTE   seconds;                                // slave address to sent/receive message
    BYTE   minutes;                                // number of bytes in message buffer
    BYTE   hours;                                  // pointer to I2C message buffer
    BYTE   day;                                    // address of next I2C message in chain
    BYTE   weekday;                                // address of next I2C message in chain
    BYTE   month;                                  // address of next I2C message in chain
    BYTE   year;                                   // address of next I2C message in chain
    }rtd;
} x;

void RTC_ST(void)                                  // Set Time, format: "ST <hours> <minutes> <cr>
{
  LONG h,m= 0xFF;

    h = GetArgument();                             // get hours from command line
    m = GetArgument();                             // get minutes from command line
    if (h > 0x23 || m > 0x59)
        PrintString("err: invalid time\n");
    else
    {
        msg.ssel  = 0x12;                          // use Port P1.2 for SSP driver
        msg.rxbuf = rdBuf;
        msg.txbuf = wrBuf;
        msg.len   = 4;
        wrBuf[0]  = 0x23;                          // address of seconds to write
        wrBuf[1]  = 0;                             // seconds to 0
        wrBuf[2]  = m;                             // minutes
        wrBuf[3]  = h;                             // hours

        SSP0_Transfer(&msg);                       // start SSP0 message transfer
    }
}

void RTC_SD(void)                                  // Set Date, format: "SD <day> <month> <year> <cr>
{
  LONG d,m,y;

    d = GetArgument();                             // get hours from command line
    m = GetArgument();                             // get minutes from command line
    y = GetArgument();
    if (d == 0 || d > 0x31 || m == 0 || m > 0x12 || y > 0x99)
        PrintString("err: invalid date\n");
    else
    {
        msg.ssel  = 0x12;                          // use Port P1.2 for SSP driver
        msg.rxbuf = rdBuf;
        msg.txbuf = wrBuf;
        msg.len   = 5;
        wrBuf[0]  = 0x26;                          // address of days register to write
        wrBuf[1]  = d;                             // day
        wrBuf[2]  = 0;                             // week day
        wrBuf[3]  = m;                             // month
        wrBuf[4]  = y;                             // year

        SSP0_Transfer(&msg);                       // start SSP0 message transfer
    }
}

void RTC_SC(void)                                  // Set CLKOUT, format: "ST <val> <cr>
{
  LONG val;

    val = GetArgument();
    if (val > 6)
        PrintString("err: CLKOUT frequency selection\n");
    else
    {
        msg.ssel  = 0x12;                          // use Port P1.2 for SSP driver
        msg.rxbuf = rdBuf;
        msg.txbuf = wrBuf;
        msg.len   = 2;
        wrBuf[0]  = 0x2F;                          // address of CLKOUT control register
        wrBuf[1]  = val;                           // value

        SSP0_Transfer(&msg);                       // start SSP0 message transfer
    }
}

void RTC_RT(void)                                  // Read Time, format: "RT <cr>
{
    while (ua_inchar() != 0x1B)                    // exit with <Esc>
    {
        msg.ssel  = 0x12;                          // use Port P1.2 for SSP driver
        msg.rxbuf = rdBuf;
        msg.txbuf = wrBuf;
        msg.len   = 4;
        wrBuf[0]  = 0xA3;                          // read PCF2129A time registers

        SSP0_Transfer(&msg);                       // start SSP0 message transfer

        PrintByte(rdBuf[3]);                       // hours
        PrintString (":");
        PrintByte(rdBuf[2]);                       // minutes
        PrintString (":");
        PrintByte(rdBuf[1]);                       // seconds
        ua_outchar('\r');
    }
    PrintString ("\n\n");
}

void RTC_RD(void)                                  // Read Date and Time, format: "RD <cr>
{
    msg.ssel  = 0x12;                              // use Port P1.2 for SSP driver
    msg.rxbuf = rdBuf;
    msg.txbuf = wrBuf;
    msg.len   = 8;
    wrBuf[0]  = 0xA3;                              // read PCF2129A time and date registers

    SSP0_Transfer(&msg);                           // start SSP0 message transfer

    PrintByte(rdBuf[3]);                           // hours
    PrintString (":");
    PrintByte(rdBuf[2]);                           // minutes
    PrintString (":");
    PrintByte(rdBuf[1]);                           // seconds
    PrintString ("  ");

    PrintByte(rdBuf[4]);                           // day
    PrintString ("-");
    PrintByte(rdBuf[6]);                           // month
    PrintString ("-20");
    PrintByte(rdBuf[7]);                           // year
    PrintString ("\n");
}

void RTC_Init(void)
{
    LPC_GPIO->DIR[1] = (1<<2);                     // P1.2 = RTC SSEL
    LPC_GPIO->SET[1] = (1<<2);                     // P1.2 high

    SSP0_Init();                                   // initialize SSP bus
}
