unit timer;
{
the break is caused wherein we need to exec the calls 110 times a sec, not 55. RT200 is caused by an overflow in the 
delay unit.the math inside is STILL 16 bits. WE NEVER EVER FIXED THIS. YET, even with FPC.

This is caused by using a counter to count the number of times a loop can be executed in a fixed time, measured by the real-time clock. When Turbo Pascal was developed it ran on machines with CPUs running at 1 to 8 MHz, and no thought was given to the possibility of much higher speeds; but at 200MHz the 16-bit counter overflows. 

pulled from http://www.merlyn.demon.co.uk/pas-wait.htm examples   

I have a workaround.This instead does not require a speed check or looped execution time.That would check the speed of the CPU.
Instead we just yield the unused processor cycles back to the processor.Thank you whoever put this on merlin's page.It is VERY hard to find.

 --Jazz
}

interface

//procedure Sleep(milliseconds: Cardinal);
Function GetClockTics_RDTSC : QWord; Assembler;
Procedure UTime; { return ticks since brought up. (GetOSTicks).This is actually a commond. }
procedure TimerPhase(Hz: LongWord);
procedure InstallTimer;
procedure delay(ms:longint); //Working now.Yields unused time to CPU.
implementation

uses
  x86,video,irq;
// baseunix if you want sleep()

const
  PhasePerSecond = 119;
var
  TimerTicks: LongWord = 0;
  rdb_status1, rdb_status2 : byte;
  rdb_count1, rdb_count2  : word;
  i,j    : word;

Function GetClockTics_RDTSC : QWord; Assembler;

Asm
  rdtsc
End;


Procedure UTime;  

var
  UDays,UHours,UMinutes,USeconds:longword;




  //slightly inaccurate
  begin
    UDays:=(TimerTicks mod 864000);
    UHours:=(TimerTicks mod 36000);
    UMinutes:=(TimerTicks mod 600);
    USeconds:=(TimerTicks mod 110);
    write('There has been: ');
    writelong(UDays);
    write(' days ');
    writelong(UHours);
    write(' hours ');
    writelong(UMinutes);
    write(' minutes ');
    writelong(USeconds);
    write(' seconds ');
    writeln(' since boot ');
    
  end;

procedure TimerPhase(Hz: LongWord);
var
  Divisor: LongInt;

begin
  Divisor:=1193181 div Hz;  //1.19Mhz in 1 sec intervals,[which is about 119 ~110 time a second, not 55 ~ 60, like borland.]
  
  WritePortB($43,$36);
  WritePortB($40,Divisor and $FF);
  WritePortB($40,Divisor shr 8);
end;

procedure TimerHandler(var r: TRegisters);
begin
  Inc(TimerTicks);
 // if TimerTicks mod PhasePerSecond=0 then   WriteStrLn('Tick') ;  One second has passed...
end;

procedure InstallTimer;

begin
  Write('Installing Timer...'#9#9);
  InstallIrqHandler(0,@TimerHandler);
  
  TimerPhase(PhasePerSecond);
  WriteLn('[ OK ]');
end;


procedure Delay(ms:longint);
// actually slows down emulator,so it might be accurate now.
 var
	us:integer;

begin
// gives back resources to cpu until such time

  us:=1000*1000*(ms mod 1000);  //time in Mhz*Milisecond or 'seconds'
  while ms<>us do begin
  
  asm
       push ax ; mov ax,1680h ; int 2fh ; pop ax;  {free cpu}
     
  end;
  
  dec(us,1);
  end;


end;

{this may be more effective. this requires threads and processes from baseunix unit, so we cant use it.
it sleeps the process.


procedure Sleep(milliseconds: Cardinal);

Var
  timeout,timeoutresult : TTimespec;

begin
  timeout.tv_sec:=milliseconds div 1000; //1 sec
  timeout.tv_nsec:=1000*1000*(milliseconds mod 1000);
  fpnanosleep(@timeout,@timeoutresult);
end;
}


begin
end.
