////////////////////////////////////////////////////////////////////////////////
// Clock.cpp -- this file is part of the Emulator Developers Kit
// available at http://ourworld.compuserve.com/homepages/pc64/develop.htm

RegisterPersistentClass(Clock);


////////////////////////////////////////////////////////////////////////////////
// destructor prevents calling StopCounter() in TimerRoot

Clock::~Clock() {
  Timer* p = &TimerRoot;
  do {
    p->pPrevTimer = NULL;
    p = p->pNextTimer;
  } while (p != &TimerRoot);
}


////////////////////////////////////////////////////////////////////////////////
// should never come here
// this task is performed by the VIC in the current implementation

__declspec(naked) void Clock::OnClock() { __asm {
  int 3
}}


////////////////////////////////////////////////////////////////////////////////
// initialisation

void Clock::DoInit() {

  // initialize base class
  Chip::DoInit();

  // set function to call each clock
  SetOnClock((pfn)OnClock);

  // initialize the timer root
  TimerRoot.Init("TimerRoot", this);
  TimerRoot.SetClock(*this);
  TimerRoot.pNextTimer = &TimerRoot;
  TimerRoot.pPrevTimer = &TimerRoot;

  // set the overflow timer
  Overflow.Init("Overflow", this);
  Overflow.SetClock(*this);
  Overflow.SetOnFire((pfn)OnOverflow);
  Overflow.StartCounter(iOverflow);

  // when there are no active user timers and the overflow timer is
  // removed and executed, the list would be empty which may not happen
  AvoidEmptyList.Init("AvoidEmptyList", this);
  AvoidEmptyList.SetClock(*this);
  AvoidEmptyList.StartCounter(iOverflow + 1);
}


////////////////////////////////////////////////////////////////////////////////
// count the overflows because system clocks are only 32 bits wide

void Clock::OnOverflow() {

  // count overflows
  rOverflow += iOverflow;
  Overflow.StartCounter(iOverflow);

  // set the dummy timer so that the list doesn't get empty
  AvoidEmptyList.StartCounter(iOverflow + 1);
}


////////////////////////////////////////////////////////////////////////////////
// change clock frequency

global void Clock::SetFrequency(int iNewFrequency) {

  // check parameters and conditions
  assert(iNewFrequency > 0);

  // set the new frequency
  iFrequency = iNewFrequency;
}
