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

class Clock : public Chip {

  Clock* pPrevClock;
  Clock* pNextClock;
  int iBresenham;
  int iFrequency;
  int iHighestFrequency;

  // making the root the sentinel of a circular list avoids NULL pointer checks
  // in SetCounter()/ClearCounter()
  Timer TimerRoot;

  // as the time is only 32 bits wide, a dummy timer has to count overflows
  enum { iOverflow = INT_MAX / 2 + 1 };
  Timer Overflow;
  void OnOverflow();
  real rOverflow;

  // there must be always at least one timer in the list
  Timer AvoidEmptyList;

  // gets called at each clock (not implemented yet because VIC will do this)
  void OnClock();

  // Timer::SetClock must store address of Clock::TimerRoot
  friend Timer;

protected:

  // initialisation
  virtual void DoInit();

public:

  // constructor
  global Clock() {
    pPrevChip = this;
    pNextChip = this;
    pPrevClock = NULL;
    pNextClock = NULL;
    iBresenham = 0;
    iFrequency = 0;
    iHighestFrequency = 0;
    rOverflow = 0;
  }

  // destructor
  global virtual ~Clock();

  // set and get clock frequency
  global void SetFrequency(int iNewFrequency);
  inline int GetFrequency() {
    return iFrequency;
  }

  // convert between clocks and seconds
  inline int ClocksFromSeconds(real rSeconds) {
    return (int)(rSeconds * (real)iFrequency);
  }
  inline real SecondsFromClocks(int iClocks) {
    return iClocks / (real)iFrequency;
  }

  // return the number of clocks since the emulation has started
  inline int GetClocks() {
    return TimerRoot.iClocks + TimerRoot.pNextTimer->iClocks;
  }
  inline real GetClocksReal() {
    return (GetClocks() & (iOverflow - 1)) + rOverflow;
  }


inline void Fire() { TimerRoot.Fire(); } // for void ExecEvent(). TODO: remove
};
