掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
キーボードイベントのリアルタイム性を上げるには? (ID:36502)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
USBキーボードのレポートレートは標準で125Hzつまり 0.008000秒(8ミリ秒)以上の精度は出ませんね… 正直もう少し高いと思ってました。最初に書いた経験則の1/100秒は意外と妥当だったんですね。 私が上で算出した値はあくまで理論値ですが、そのレポートレートまで同期させた時のゆらぎです。(押しっぱなし一定間隔の為) そのブレが0.000063秒だったということですね。 ですので、完全に一定間隔でない場合、Kennyさんの最後の計測結果の1桁目はUSBキーボードの精度未満の話なので、切り捨てるのが妥当だと思います。 どーしても気になるというのであれば、ソフトウエア側の精度をめいいっぱい考慮したタイマーをこしらえてみたのでこれを使ってみてください。 USBレポートレートの精度を大幅に超えてるはずです。 USB 125Hzを使っている時点で全くの無価値ですが。USBはもっと周波数を上げることが可能です。 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); private { Private 宣言 } fStartClock : UInt64; fStopClock : Uint64; fCPUClock : UInt64; fCounting : Boolean; public { Public 宣言 } procedure ShowResult(); end; var Form1: TForm1; implementation {$R *.dfm} //CPUクロック数取得 function GetCPUClock():UInt64; var Lo, Hi: DWORD; begin asm PUSH edx PUSH eax // RDTSC Delphi5では使えないらしい // http://rakasaka.fc2web.com/delphi/cpuclock.html //DW $310F //私は未確認なので保証しません。 rdtsc MOV Lo, eax MOV Hi, edx POP eax POP edx end; Result := Hi; Result := (Result shl 32) or Lo; end; //1秒当たりのCPU周Clock数取得 //1秒の取得にはWindowsAPIを使用するしかない function GetCPUClockFrequency(): UInt64; var aStartClock : UInt64; aAPIFreq : Int64; aAPIClockStart : Int64; aAPIClockStop : Int64; aAPIClockNow : Int64; begin QueryPerformanceFrequency(aAPIFreq); aStartClock := GetCPUClock(); QueryPerformanceCounter(aAPIClockStart); aAPIClockStop := aAPIClockStart + aAPIFreq; repeat QueryPerformanceCounter(aAPIClockNow); until aAPIClockStop <= aAPIClockNow; Result := GetCPUClock()-aStartClock; end; procedure TForm1.FormCreate(Sender: TObject); begin //最初の2回は時間がかかるらしい //http://www.02.246.ne.jp/~torutk/cxx/clock/cpucounter.html GetCPUClock(); GetCPUClock(); fCPUClock := GetCPUClockFrequency(); fCounting := False; end; procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if fCounting = False then fStartClock := GetCPUClock() else begin fStopClock := GetCPUClock(); ShowResult; end; fCounting := not fCounting; end; procedure TForm1.ShowResult(); var str:string; aTime:Extended; begin aTime := (fStopClock - fStartClock)/fCPUClock; str := FloatToStr(aTime) + ' sec'; Canvas.TextOut(0,0,str); Beep; end; end. さらにソフトウエア側の精度を上げるにはVCLとの決別が必要かと。
←解決時は質問者本人がここをチェックしてください。
更新する
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.