/*
    TMClock.c, Copyright (c) by Silvio Dragone & David Reist,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public Licence.
 
    A full copy of the GNU GPL is provided in the file COPYING found in the 
    development root of Topsy.
*/

#include "TMHal.h"
#include "IOHal.h"
#include "IODevice.h"
#include "TMScheduler.h"
#include "Support.h"
#include "TMClock.h"
#include "cpu.h"


/*
 * This function initializes the clock on the board.
 */
Error setClockValue( ClockId cId,
                     int period,
                     ClockMode cMode)
{
  unsigned long int TimerNo = 0, TimerEnable = 0;

  if (cMode == RATEGENERATOR)
  {
    switch (cId)
    {
    case CLOCK0:
      TimerNo = (unsigned long int)SA_TIMER_1_LOAD;
      TimerEnable = (unsigned long int)SA_TIMER_1_CONTROL;
      break;
    case CLOCK1:
      TimerNo = (unsigned long int)SA_TIMER_2_LOAD;
      TimerEnable = (unsigned long int)SA_TIMER_2_CONTROL;
      break;
    case CLOCK2:
      TimerNo = (unsigned long int)SA_TIMER_3_LOAD;
      TimerEnable = (unsigned long int)SA_TIMER_3_CONTROL;
      break;
    case CLOCK3:
      TimerNo = (unsigned long int)SA_TIMER_4_LOAD;
      TimerEnable = (unsigned long int)SA_TIMER_4_CONTROL;
      break;
    default:
      return TM_FAILED;
    }
    //-CJ		printf("setting clock value: TimerNo %#lx TimerEnable %#lx\n",
    //-CJ				TimerNo, TimerEnable);
    setClockValue_asm( TimerNo, period, TimerEnable );
  }
  else
  {
    PANIC("Only RATEGENERATOR-Mode is supported!");
  }

  return TM_OK;
}

/* When a clock interrupt is generated, the clock must be stoped. So a
 * reset is performed.
 * If not done, the interrupt is generated at once again and again ...
 */
void tmResetClockInterrupt(ClockId cId)
{
  unsigned long int TimerNo, TimerDisable;

  ioConsolePutString("\ntmResetClockInterrupt reached");

  switch (cId)
  {
  case CLOCK0:
    TimerNo = (unsigned long int)SA_TIMER_1_CLEAR;
    TimerDisable = (unsigned long int)SA_TIMER_1_CONTROL;
    break;
  case CLOCK1:
    TimerNo = (unsigned long int)SA_TIMER_2_CLEAR;
    TimerDisable = (unsigned long int)SA_TIMER_2_CONTROL;
    break;
  case CLOCK2:
    TimerNo = (unsigned long int)SA_TIMER_3_CLEAR;
    TimerDisable = (unsigned long int)SA_TIMER_3_CONTROL;
    break;
  case CLOCK3:
    TimerNo = (unsigned long int)SA_TIMER_4_CLEAR;
    TimerDisable = (unsigned long int)SA_TIMER_4_CONTROL;
    break;
  default:
    return;
  }
  resetClock_asm( TimerNo, TimerDisable );
}

/* We would calculate the seconds since January 1st 1998, 00:00, UTC,
 * and return or set them, but not implemented yet.
 */
unsigned long tmRTClockGetSeconds()
{
  return 0;
}

void tmRTClockSetSeconds(unsigned long seconds, unsigned long microSeconds)
{
  return;
}

