Solved

High resolution timer to Delphi 7

Posted on 2011-02-16
9
1,533 Views
Last Modified: 2013-11-22
Want a high resolution timer without wait and lot of CPU load...
GetTickCount and Sleep have only resolution doen to ms integer level....
My problem is as follow...
Need to set the delay, calculated by delay := 6000/Speed...
eg. delay := 6000/307 (= 19,54)  and delay := 6000/300 ( =20).
Any speed changes is not available between 300-307 because of rounded sepeed unit (integer).
Is there possibility to go down to microseconds level and change calculatimg form to eg. SpeedUnit := 60000/Speed, eg. 60000/304 (=1973 µs = 19.7 ms)?
How to do?
0
Comment
Question by:ejla51
9 Comments
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 34905879
0
 
LVL 32

Assisted Solution

by:ewangoya
ewangoya earned 200 total points
ID: 34908175

Have you considered what will happen when you are doing this kind of delay. At first glance seems to me your program will be locking up everytime you do this. Even if you were to use a thread, it will take lots of CPU time

think about this

procedure MyDelay(const AMicroSecs: Integer);
var
  Ellapsed: Integer;
  Start, Stop: Int64;
begin
  QueryPerformanceCounter(Start);
  while Ellapsed < AMicroSeconds do
  begin
     QueryPerformanceCounter(Stop);
     Ellapsed := Stop - Start;
     //since you cant call Sleep or ProcessMessages here because of your high resolution requirement
     //everything else has to stop and wait for this function to complete
  end;
end;

Exactly why is precision up to a millisecond not enough?
0
 

Author Comment

by:ejla51
ID: 34910377
Thanks,
yes I know that about CPU load and have to look for any "lightweight" alternative.
My app send Morse Code telegraphy and timing is quite important (if we want exact right speed).
One length unit has been calculated as 6000/speed (chars/min) .
Due to integer division, unit result will be rounded. What happend here... Light increasing or decreasing of speed have not any effect to really speed because rounded unit would not been changed. A little speed error can be accepted, but there is one, more serious problem....
The fault of the transmit... a  "hiccup" due to heavy CPU load (Sleep, TTimer, interrupts?). These may be noticeable especially on slow computers...
I know that some have managed to overcome those problems, but I do not know how ...
Have noticed that some have used separate applications to sending morse code... I guess there has used DDE channel to send variables and parameters to this client.

Has had some strange ideas to use serial port for this.
- Set custom baud rate referred to speed and send morse character pattern as binary number ... maybe a bit far-fetched idea?
0
 
LVL 2

Accepted Solution

by:
Roza earned 300 total points
ID: 35098589
Following code is being used in latest version of VHFCtest4Win program.

procedure TCustomKeyer.WaitFor(Time: int64);
var CurrentTime: Int64;
    PreWaitStop: Int64;
    Counter: integer;
begin
  PrewaitStop:=Time-FSleepAccuracy;
  Counter:=0;
  QueryPerformanceCounter(CurrentTime);
  while PreWaitStop>CurrentTime do
  begin
    Sleep(1);
    Inc(counter);
    QueryPerformanceCounter(CurrentTime);
  end;

  while Time>CurrentTime do
  begin
    QueryPerformanceCounter(CurrentTime);
  end;
end;


function GetSleepAccuracy:integer;
const TestLength=500;
var counter: integer;
    PerformanceFrequency, CurrentTime: Int64;
    Times: array[0..TestLength] of Int64;
    Time, MaxTime: Int64;
begin
  QueryPerformanceFrequency(PerformanceFrequency);
  QueryPerformanceCounter(CurrentTime);
  Times[0]:=CurrentTime;
  for Counter:=1 to TestLength do
  begin
    sleep(1);
    QueryPerformanceCounter(CurrentTime);
    Times[Counter]:=CurrentTime;
  end;

  MaxTime:=0;

  for Counter:=1 to TestLength do
  begin
    Time:=(Times[Counter]-Times[Counter-1]);
    MaxTime:=Max(MaxTime,Time);
  end;
  Result:=Round(MaxTime*1.5);
end;

After many years of experiments, keying is accurate and I am affraid to correct line of code in keyer unit HI

73 Peter, S52AA
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 

Author Comment

by:ejla51
ID: 35100449
Hi Peter and thank you for the nice tip!

In the quick test I  can't  do it working... propably due to my Keying threads syncronization...
WaitrFor does not  "wait"  anything but passed in zero time...
My CW component  have abt. 1500 rows  so its a little too long to show here.

Have you used separatly Thread  for  keying?

73 Erkki, SM5NBE / SA5N
0
 
LVL 2

Expert Comment

by:Roza
ID: 35107141
Hi Erkki

I use seperate thread with Time priority set to tpTimeCritical;

Usage example:

  private
    { Private declarations }
    procedure WaitFor(Time: int64);
  public
    { Public declarations }
    FSleepAccuracy: Integer;
  end;


procedure TForm1.Button1Click(Sender: TObject);
var CurrentTime,
    StopTime,
    PerformanceFrequency: Int64;
    DelayInMSec: integer;
begin
  QueryPerformanceFrequency(PerformanceFrequency);
  DelayInMSec:=3000;
  Label1.Caption:='Start';
  Label1.Update;
  QueryPerformanceCounter(CurrentTime);

  StopTime:=CurrentTime+Round(DelayInMSec/1000*PerformanceFrequency);
  WaitFor(StopTime);
  Label1.Caption:='Stop';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FSleepAccuracy:=GetSleepAccuracy;
end;

Process of keying is following:

I operate with performancecounter which measures my time.
Ex: KeyOn function first waits for NextEventTime, then sets key and adds Dot/Dash length to NextEventTime.
KeyOff function then waits for NextEventTime and adds necessary pause to NextEventTime.

With this approach all calculation is done at begining of wait time and no unwanted delay is added to keying process because of calculating something.

If Windows switches context away from my thread, the worst thing is that happens during busy waiting of WaitFor function. But when thread continues and time is overrun it imediately turns key on/off or whatewer it should do next and reducing overrun time to minimum.
0
 

Author Comment

by:ejla51
ID: 35146459
ok... thanks.
I have been very busy and haven't had time to work with this project...
I'll accept your tip.
Because ewancoya had same principe to use QueryPerformanceCounter, I have to split points.
If there is some more questions I sent private mail to you Peter.
Regards,
Erkki
   
0
 

Author Comment

by:ejla51
ID: 35184830
Peter,
have looked little more your code...

Is there structure error in WaitFor...??!!

I debugged procedure and found that PreWaitStop would newer be higher than the CurrentTime?
I added a row before While loop :

 Time := Time * 10000; // My original Time is in milliseconds
 Counter:=0;
 QueryPerformanceCounter(CurrentTime);
 PreWaitStop := CurrentTime + (Time - FSleepAccuracy); // Have got FSleepAccuracy value to 10600 with GetSleepAccuracy

  while PreWaitStop > CurrentTime do
  begin
   ...
 
Regards,
Erkki

procedure TCustomKeyer.WaitFor(Time: int64);
var CurrentTime: Int64;
    PreWaitStop: Int64;
    Counter: integer;
begin
  PrewaitStop:=Time-FSleepAccuracy;
  Counter:=0;
  QueryPerformanceCounter(CurrentTime);
  while PreWaitStop>CurrentTime do
  begin
    Sleep(1);
    Inc(counter);
    QueryPerformanceCounter(CurrentTime);
  end;

  while Time>CurrentTime do
  begin
    QueryPerformanceCounter(CurrentTime);
  end;
end;

Open in new window

0
 

Author Comment

by:ejla51
ID: 35188003
Sri Peter,
well, I see ...  Your Time parameter allready include CurrentTime + Delay.
I had only Delay as Time parameter.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now