/** ###################################################################
**     THIS COMPONENT MODULE IS GENERATED BY THE TOOL. DO NOT MODIFY IT.
**     Filename    : TmDt1.c
**     Project     : ProcessorExpert
**     Processor   : MC56F84789VLL
**     Component   : TimeDate
**     Version     : Component 02.108, Driver 02.05, CPU db: 3.50.001
**     Compiler    : Metrowerks DSP C Compiler
**     Date/Time   : 2012-07-05, 13:52, # CodeGen: 7
**     Abstract    :
**         This component "TimeDate" implements real time and date.
**         The component requires a periodic interrupt generator: timer
**         compare or reload register or timer-overflow interrupt
**         (of free running counter). User can select precision of
**         selected timer.
**         The component supports also alarm with event OnAlarm.
**     Settings    :
**         Timer name                  : TMRA0 (16-bit)
**
**         Counter                     : TMRA_0_CNTR [E145]
**         Mode register               : TMRA_0_CTRL [E146]
**         Run register                : TMRA_0_CTRL [E146]
**         Prescaler                   : TMRA_0_CTRL [E146]
**         Compare register            : TMRA_0_COMP1 [E140]
**         Flip-flop register          : TMRA_0_SCTRL [E147]
**
**         Interrupt name              : INT_TMRA_0
**         Interrupt enable reg.       : TMRA_0_SCTRL [E147]
**         Priority                    : 1
**         User handling procedure     : TmDt1_OnAlarm
**         This event is called whenever the current time is equal
**         to alarm time
**
**         High speed mode
**             Prescaler               : divide-by-32
**             Clock                   : 3125000 Hz
**           Resolution of timer
**             Xtal ticks              : 160000
**             microseconds            : 20000
**             milliseconds            : 20
**             seconds (real)          : 0.02
**             Hz                      : 50
**
**         Initialization:
**              Timer                  : Enabled
**
**              Time                   : 11:59:55
**              Date                   : 1/1/2008
**     Contents    :
**         SetTime  - byte TmDt1_SetTime(byte Hour, byte Min, byte Sec, byte Sec100);
**         SetDate  - byte TmDt1_SetDate(word Year, byte Month, byte Day);
**         GetDate  - byte TmDt1_GetDate(DATEREC *Date);
**         SetAlarm - byte TmDt1_SetAlarm(byte Hour, byte Min, byte Sec, byte Sec100);
**
**     Copyright : 1997 - 2012 Freescale Semiconductor, Inc. All Rights Reserved.
**     
**     http      : www.freescale.com
**     mail      : support@freescale.com
** ###################################################################*/

/* MODULE TmDt1. */

#include "Events.h"
#include "TmDt1.h"

static bool EnUser;                    /* Enable/Disable device by user */
static byte CntDay;                    /* Day counter */
static byte CntMonth;                  /* Month counter */
static word CntYear;                   /* Year Counter */
static dword TotalHthH;                /* Software tick counter (1 tick = 10ms) */
static dword AlarmHth;                 /* Alarm time (compared with software tick counter) */
static bool AlarmFlg;                  /* Alarm flag */

/* Table of month length (in days) */
static const byte ULY[12] = {31U,28U,31U,30U,31U,30U,31U,31U,30U,31U,30U,31U}; /* Un-leap-year */
static const byte  LY[12] = {31U,29U,31U,30U,31U,30U,31U,31U,30U,31U,30U,31U}; /* Leap-year */
/* Number of days from beggin of the year */
static const word MONTH_DAYS[13] = {0U,31U,59U,90U,120U,151U,181U,212U,243U,273U,304U,334U}; /* Un-leap-year */

/* Internal method prototypes */
static void HWEnDi(void);
static void SetCV(word Val);
static void SetPV(byte Val);

/*
** ===================================================================
**     Method      :  SetCV (component TimeDate)
**
**     Description :
**         Sets compare or preload register value. The method is called 
**         automatically as a part of several internal methods.
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void SetCV(word Val)
{
  EnterCritical();                     /* Disable global interrupts */
  setReg(TMRA_0_CMPLD1,Val);           /* Store given value to the compare preload 1 register */
  setReg(TMRA_0_CMPLD2,Val);           /* Store given value to the compare preload 2 register */
  ExitCritical();                      /* Enable global interrupts */
}

/*
** ===================================================================
**     Method      :  SetPV (component TimeDate)
**
**     Description :
**         Sets prescaler value. The method is called automatically as a 
**         part of several internal methods.
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void SetPV(byte Val)
{
  setRegBitGroup(TMRA_0_CTRL,PCS,Val); /* Store given value to the prescaler */
  setReg(TMRA_0_CNTR,0);               /* Reset counter */
}

/*
** ===================================================================
**     Method      :  HWEnDi (component TimeDate)
**
**     Description :
**         Enables or disables the peripheral(s) associated with the bean.
**         The method is called automatically as a part of the Enable and 
**         Disable methods and several internal methods.
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void HWEnDi(void)
{
  if (EnUser) {                        /* Enable device? */
    setReg(TMRA_0_COMP1,getReg(TMRA_0_CMPLD1)); /* Refresh compare 1 register */
    setReg(TMRA_0_COMP2,getReg(TMRA_0_CMPLD2)); /* Refresh compare 2 register */
    setRegBitGroup(TMRA_0_CTRL,CM,0x01); /* Run counter */
  }
  else {                               /* Disable device? */
    setRegBitGroup(TMRA_0_CTRL,CM,0x00); /* Stop counter */
    setReg(TMRA_0_CNTR,0);             /* Reset counter */
  }
}

/*
** ===================================================================
**     Method      :  TmDt1_SetTime (component TimeDate)
**
**     Description :
**         This method sets a new actual time.
**     Parameters  :
**         NAME            - DESCRIPTION
**         Hour            - Hours (0 - 23)
**         Min             - Minutes (0 - 59)
**         Sec             - Seconds (0 - 59)
**         Sec100          - Hundredths of seconds (0 - 99)
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
**                           ERR_SPEED - This device does not work in
**                           the active speed mode
**                           ERR_RANGE - Parameter out of range
** ===================================================================
*/
byte TmDt1_SetTime(byte Hour,byte Min,byte Sec,byte Sec100)
{
  bool TmrRun;                         /* Temporary flag enable/disable */

  if ((Sec100 > 0x63U) || (Sec > 0x3BU) || (Min > 0x3BU) || (Hour > 0x17U)) { /* Test correctnes of given time */
    return ERR_RANGE;                  /* If not correct then error */
  }
  TmrRun = EnUser;                     /* Store actual device state */
  if (EnUser) {                        /* Is the device enabled by user? */
    EnUser = FALSE;                    /* If yes then set the flag "device disabled" */
    HWEnDi();                          /* Enable/disable device according to status flags */
  }
  TotalHthH = (0x00057E40UL * (dword)Hour) + (0x1770U * (dword)Min) + (0x64U * (dword)Sec) + (dword)Sec100; /* Load given time re-calculated to 10ms ticks into software tick counter */
  AlarmFlg = (bool)((TotalHthH < AlarmHth) ? FALSE : TRUE); /* Set up alarm flag */
  if (TmrRun) {                        /* Was the device disabled? */
    EnUser = TRUE;                     /* If yes set flag "device enabled" */
    HWEnDi();                          /* Enable/disable device according to status flags */
  }
  return ERR_OK;                       /* OK */
}

/*
** ===================================================================
**     Method      :  TmDt1_SetDate (component TimeDate)
**
**     Description :
**         This method sets a new actual date. See limitations at the
**         page <General Info>.
**     Parameters  :
**         NAME            - DESCRIPTION
**         Year            - Years (16-bit unsigned integer)
**         Month           - Months (8-bit unsigned integer)
**         Day             - Days (8-bit unsigned integer)
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
**                           ERR_SPEED - This device does not work in
**                           the active speed mode
**                           ERR_RANGE - Parameter out of range
** ===================================================================
*/
byte TmDt1_SetDate(word Year,byte Month,byte Day)
{
  const byte *ptr;                     /* Pointer to ULY/LY table */

  if ((Year < 0x07CEU) || (Year > 0x0833U) || (Month > 0x0CU) || (Month == 0x00U) || (Day > 0x1FU) || (Day == 0x00U)) { /* Test correctness of given parameters */
    return ERR_RANGE;                  /* If not correct then error */
  }
  if (Year & 0x03U) {                  /* Is given year un-leap-one? */
    ptr = ULY;                         /* Set pointer to un-leap-year day table */
  }
  else {                               /* Is given year leap-one? */
    ptr = LY;                          /* Set pointer to leap-year day table */
  }
  if (ptr[Month - 1U] < Day) {         /* Does the obtained number of days exceed number of days in the appropriate month & year? */
    return ERR_RANGE;                  /* If yes (incorrect date inserted) then error */
  }
  EnterCritical();                     /* Disable global interrupts */
  CntDay = Day;                        /* Set day counter to the given value */
  CntMonth = Month;                    /* Set month counter to the given value */
  CntYear = Year;                      /* Set year counter to the given value */
  ExitCritical();                      /* Enable global interrupts */
  return ERR_OK;                       /* OK */
}

/*
** ===================================================================
**     Method      :  TmDt1_GetDate (component TimeDate)
**
**     Description :
**         This method returns current date.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * Date            - Pointer to the structure DATEREC. It
**                           contains actual year, month, and day
**                           description.
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
**                           ERR_SPEED - This device does not work in
**                           the active speed mode
** ===================================================================
*/
byte TmDt1_GetDate(DATEREC *Date)
{
  EnterCritical();                     /* Disable global interrupts */
  Date->Year = CntYear;                /* Year */
  Date->Month = CntMonth;              /* Month */
  Date->Day = CntDay;                  /* Day */
  ExitCritical();                      /* Enable global interrupts */
  return ERR_OK;                       /* OK */
}

/*
** ===================================================================
**     Method      :  TmDt1_SetAlarm (component TimeDate)
**
**     Description :
**         This method sets a new time of alarm. (only time, not date -
**         alarm event <OnAlarm> is called every 24 hours). Setting any
**         parameter out of its range disables alarm.
**     Parameters  :
**         NAME            - DESCRIPTION
**         Hour            - Hours (0 - 23)
**         Min             - Minutes (0 - 59)
**         Sec             - Seconds (0 - 59)
**         Sec100          - Hundredths of seconds (0 - 99)
**     Returns     :
**         ---             - Error code, possible codes: 
**                           - ERR_OK - OK 
**                           - ERR_SPEED - This device does not work in
**                           the active speed mode
** ===================================================================
*/
byte TmDt1_SetAlarm(byte Hour,byte Min,byte Sec,byte Sec100)
{
  register dword Hundredth;            /* Temporary variable */

  if ((Sec100 > 0x63U) || (Sec > 0x3BU) || (Min > 0x3BU) || (Hour > 0x17U)) { /* Test correctness of the given time */
    AlarmHth = ULONG_MAX;              /* If no correct then it means switch off the alarm */
    return ERR_OK;                     /* OK */
  }
  Hundredth = (0x00057E40UL * (dword)Hour) + (0x1770U * (dword)Min) + (0x64U * (dword)Sec) + (dword)Sec100; /* Load given time re-calculated to 10ms ticks into temporary variable */
  EnterCritical();                     /* Disable global interrupts */
  AlarmFlg = (bool)((TotalHthH < Hundredth) ? FALSE : TRUE); /* Set up alarm flag */
  AlarmHth = Hundredth;                /* Copy content of temporary variable into Alarm time variable */
  ExitCritical();                      /* Enable global interrupts */
  return ERR_OK;                       /* OK */
}

/*
** ===================================================================
**     Method      :  TmDt1_Init (component TimeDate)
**
**     Description :
**         Initializes the associated peripheral(s) and the beans 
**         internal variables. The method is called automatically as a 
**         part of the application initialization code.
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
void TmDt1_Init(void)
{
  /* TMRA_0_CTRL: CM=0,PCS=0,SCS=0,ONCE=0,LENGTH=1,DIR=0,COINIT=0,OUTMODE=4 */
  setReg(TMRA_0_CTRL,0x24);            /* Stop timer, use alternating compare registers */
  /* TMRA_0_SCTRL: TCF=0,TCFIE=1,TOF=0,TOFIE=0,IEF=0,IEFIE=0,IPS=0,INPUT=0,CAPTURE_MODE=0,MSTR=0,EEOF=0,VAL=0,FORCE=0,OPS=0,OEN=0 */
  setReg(TMRA_0_SCTRL,0x4000);         /* Enable compare interrupt */
  setReg(TMRA_0_CNTR,0x00);            /* Reset counter register */
  setReg(TMRA_0_LOAD,0x00);            /* Reset load register */
  setReg(TMRA_0_COMP1,0xF423);         /* Set up compare 1 register */
  setReg(TMRA_0_COMP2,0xF423);         /* Set up compare 2 register */
  /* TMRA_0_CSCTRL: DBG_EN=0,FAULT=0,ALT_LOAD=0,ROC=0,TCI=0,UP=0,??=0,TCF2EN=0,TCF1EN=0,TCF2=0,TCF1=0,CL2=1,CL1=2 */
  setReg(TMRA_0_CSCTRL,0x06);          /* Compare load control */
  EnUser = TRUE;                       /* Enable device */
  SetCV((word)0xF423);                 /* Store appropriate value to the compare register according to the selected high speed CPU mode */
  SetPV((byte)0x0D);                   /* Set prescaler register according to the selected high speed CPU mode */
  HWEnDi();                            /* Enable/disable device according to status flags */
  AlarmHth = ULONG_MAX;                /* Disable alarm */
  AlarmFlg = FALSE;                    /* Reset alarm flag */
  (void)TmDt1_SetDate((word)2008,(byte)1,(byte)1); /* Initial date */
  (void)TmDt1_SetTime((byte)11,(byte)59,(byte)55,(byte)0); /* Initialize time */
}

/*
** ===================================================================
**     Method      :  TmDt1_Interrupt (component TimeDate)
**
**     Description :
**         The method services the interrupt of the selected peripheral(s)
**         and eventually invokes the beans event(s).
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
#pragma interrupt alignsp saveall
void TmDt1_Interrupt(void)
{
  bool UserEvent = FALSE;              /* Temporary variable */
  register const byte *ptr;            /* Pointer to ULY/LY table */

  clrRegBit(TMRA_0_SCTRL,TCF);         /* Reset interrupt request flag */
  TotalHthH += 0x02UL;                 /* Software timer counter increment by timer period (10 ms) */
  if (!AlarmFlg) {                     /* Has the alarm already been on? */
    if (TotalHthH >= AlarmHth) {       /* Is the condition for alarm invocation satisfied? */
      UserEvent = TRUE;                /* Set user event invocation flag */
      AlarmFlg = TRUE;                 /* Set alarm flag - alarm has been invocated */
    }
  }
  if (TotalHthH >= 0x0083D600UL) {     /* Does the counter reach 24 hours? */
    TotalHthH -= 0x0083D600UL;         /* If yes then reset it by subtracting exactly 24 hours */
    AlarmFlg = FALSE;                  /* Reset alarm flag - alarm has not occured during these 24 hours yet */
    CntDay++;                          /* Increment day counter */
    if (CntYear & 0x03U) {             /* Is this year un-leap-one? */
      ptr = ULY;                       /* Set pointer to un-leap-year day table */
    }
    else {                             /* Is this year leap-one? */
      ptr = LY;                        /* Set pointer to leap-year day table */
    }
    ptr--;                             /* Decrement the pointer */
    if (CntDay > ptr[CntMonth]) {      /* Day counter overflow? */
      CntDay = 1U;                     /* Set day counter on 1 */
      CntMonth++;                      /* Increment month counter */
      if (CntMonth > 0x0CU) {          /* Month counter overflow? */
        CntMonth = 1U;                 /* Set month counter on 1 */
        CntYear++;                     /* Increment year counter */
      }
    }
  }
  if (UserEvent) {                     /* Is the condition for user event invocation satisfied? */
    TmDt1_OnAlarm();                   /* Invoke user event */
  }
}

/* END TmDt1. */

/*
** ###################################################################
**
**     This file was created by Processor Expert 5.3 [05.01]
**     for the Freescale 56800 series of microcontrollers.
**
** ###################################################################
*/
