AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi QueryPerformanceCounter - Probleme, Zeitversatz
Thema durchsuchen
Ansicht
Themen-Optionen

QueryPerformanceCounter - Probleme, Zeitversatz

Ein Thema von TERWI · begonnen am 17. Jul 2011 · letzter Beitrag vom 18. Jul 2011
Antwort Antwort
Seite 2 von 2     12   
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
378 Beiträge
 
Delphi 11 Alexandria
 
#11

AW: QueryPerformanceCounter - Probleme, Zeitversatz

  Alt 18. Jul 2011, 11:42
@himitsu

A) Die in PC's verfügbaren IR's sind alle vom Typ IRDA und für Datenverbindungen z.B. zu einem PDA o.ä.
Für 'normale FB's mit 35-36KHz Modulation nicht zu verwenden.

B) Über die Sache mit den Threads denke ich nach - leider im Büro keine Chance

@hathor

Ob eine Hardwarelösung so viel besser ist ?
Zum einen kostet sie extra um zum anderen muss der PC auch wieder irgendwo 'zuhören', wenn der kleine Bruder spricht.
Ich lasse mir auch nur nen Event vom COM-Port auf DSR geben und lese max 80mS (via erst dann gestartetem Timer) Daten, die da kommen (können).
Da gibt es keine Dauer-Loop mit Sleeps oder sonstigen Schwachfug.


Ich hab mein FB-Tool mal wieder ausgebuddelt, weil ich genau an einem solchen HTPC wieder weiterarbeiten muss (!).
Hatte mir damals mal nen Topfield TF 7700 PVR gegönnt und dachte, mit dem passenden Image (AAC MME) ist das sicher besser als mein WinDoof-Gebastel (in einem jedoch sehr schicken Gehäuse).

Falsch gedacht ! Mit dem Pinguin komme ich nicht klar und das, was ich haben will, geht mit dem Topf (zunächst) nicht.
Also alles noch mal neu überarbeitet und diesmal richtig.

Als DVB-App verwende ich neben DVBDream übrigens meine eigene Kreation. Geht gut.
Zum OnlineTV-Zeitung lesen nehme ich den TV-Browser und zum Filme gucken wurde VLC adaptiert/implementiert.
Das alles kann ich über eine einzige (egal welche) FB aus dem Sofa steuern.

Nur wenn es da schon mit der Auswertung der FB hapert .... aber auch das bekomme ich (mit eurer Hilfe =!) sicher hin.

Geändert von TERWI (18. Jul 2011 um 11:45 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
378 Beiträge
 
Delphi 11 Alexandria
 
#12

AW: QueryPerformanceCounter - Probleme, Zeitversatz

  Alt 18. Jul 2011, 19:07
Da ich wirklich nicht der Held in Sachen Threads bin, brauche ich eure (kleine) Unterstützung.
Zum Verständnis, wie es in meinen FB-Tool 'abgeht', hier mal die relevanten Codeschnipsel, wie im Normalfall bei erkannter und angelernter FB:
Delphi-Quellcode:
// -----------------------------------------------------------------------------
procedure TIR2KB_frm_RCINTERFACE.FormCreate(Sender: TObject);
begin
  ...
  RCTimer.Enabled := false; // disable Timer
  RCTimer.Interval := 80; // set to 80 mS / fit for almost IR-RCCodes
  ...
  SetProcessCPUKernel(GetProcessID, 1); // use always 1st CPU (safe ?)
  if QueryPerformanceFrequency(qpcfreq) Then
  begin
    ... // do not start COM if error occurs here !
  end;
  ...
end;

// -----------------------------------------------------------------------------
procedure TIR2KB_frm_RCINTERFACE.StartCOM;
begin
  RCTimer.Enabled := false; // stop timer for safety / on restart
  Data.RCInterface := 2;
  ComPort.Open;
  ComPort.SetRTS(True);
  ComPort.SetDTR(True);
  // QueryPerformanceCounter(TSqpc1); // remain TqpcStamp divider
  TSqpc1 := 0; // defined settingfor 1st compare
end;

// -----------------------------------------------------------------------------
procedure TIR2KB_frm_RCINTERFACE.ComPortDSRChange(Sender: TObject; OnOff: Boolean);
begin
  QueryPerformanceCounter(TSqpc2); // get new TqpcStamp
  Tqpc := ((TSqpc2 - TSqpc1) * 1000000) div qpcfreq; // calc Tqpc in µS !
  TSqpc1 := TSqpc2; // set last TqpcStamp
  if (Tqpc > 12500) then // > 12.5 mS ? > must be a new Code-Sequence!
  begin
    fillchar(TCP, sizeof(TTCP),0); // clear TP - new frame started
    RCTimer.Enabled := false; // stop timer for safety
    RCTimer.Enabled := true; // start timer again
    exit; // !!! wait for next valid pulse
  end; // TCP.Len = 0 !
  if (TCP.Len < TCPmaxlen) then // space in TP to write ?
  begin
    TCP.HL[TCP.Len] := OnOff; // Pulse-type
    TCP.Pulse[TCP.Len] := Tqpc; // Pulse-duration
    TCP.Time := TCP.Time + Tqpc; // Command-duration (incremented)
    inc(TCP.Len); // number of pulses
  end;
end;

// -----------------------------------------------------------------------------
procedure TIR2KB_frm_RCINTERFACE.RCTimerTimer(Sender: TObject);
begin
  case Data.RCInterface of
   1: begin // USB
        ....
        CheckRCData;
      end;
   2: begin // COM
        RCTimer.Enabled := false; // stop timer for safety / on restart
        CheckRCData;
      end;
   3: begin // HID
        ....
        CheckRCData;
      end;
  end;
end;
'FormCreate' arbeitet neben den o.a. Dingen logo noch ne Latte anderer Initialisierungen ab. Normaler INI-Kram...
So bald der gewünschte Kern definiert gesetzt ist (Abfrage auf Erfolg fehlt noch), wird hier nur einmal der erforderliche Divisor gelesen.
Sollte lt. MS nur einmal passieren - hier sicherlich der richtige Platz !?

'StartCOM' wird im weiteren Verlauf des Programms automatisch ausgeführt, wenn so weit COM mit dem korrekten Port und QPC verfügbar ist.
Der erstmaligen Aufruf von QPC ist hier eigentlich unwichtig, daher ausmarkiert und der Wert der 'Startzeit' auf 0 gesetzt.

'ComPortDSRChange' ist eine Event-Routine, die (nur) bei Signalwechsel (H > L oder L > H) am DSR-Pin vom COM-Port aufgerufen wird.
Erst hier lese ich den QPC als Stopp-Wert und ermittle die vergangene Zeit seit letztem Event - oder Start.
[INTERMEZZO]
Eben hier fiel auf, das sich 'gelegentlich' und nicht konkret wiederholbar halt eben die berechnete Zeit (weit) in's negative verschiebt und auch kurz danach ebenso (und weiter) in's positive.
Irgendwann nach ca. 10-20 bis 30-40 mS passt das dann interessanterweise wieder.
Für ne Mittelwertbildung von Ping-Zeiten kann man das vielleicht ignorieren - aber in diesem Fall fehlen bei den Adressen und Daten einer FB-Taste halt ein paar elementare wichtige Bits zur Tastenerkennung ....

[/INTERMEZZO]
Startwert wird = Stoppwert gesetzt für den nächsten Event.
Wenn > als 12.5mS, dann handelt es sich garantiert (99,99999%) um den 1. Event seit Start oder eine neue Folge von Impulsen der FB (auch wenn man eine Taste gedrückt hält). Ist das der Fall, lösche ich mein 'Daten-Array', stoppe den Timer pro forma und starte in wieder.
Nix Repeat, While, Wait, Sleep oder in der Art. Hier wird keiner Prozessorzeit verballert.
Wichtig:
Dieser Timer läuft 80 mS (das passt für die Laufzeit eines Daten-/Adress-Frames für alle möglichen gängigen IR-FBs) und gibt mir ein definiertes Ende auf das sonst endlose Warten eines beendeten Frames.
Ich mache das deswegen hier so, weil es unterschiedliche FB-Protokolle mit unterschiedlichen Pulse-/Pause-Zeiten und unterschiedlichen Datenlängen gibt. Muss universell sein - man kann nicht (schon) für für jeden Typ ne extra Abfrage machen, bläht nur auf und wird unübersichtlich.
Danach 'raus aus dem Haus'.

Handelt es sich um einen (vermeintlich) gültigen Impulsabstand, merke ich mir entsprechende Daten zur späteren Auswertung.
Danach warten auf den nächsten Event - oder halt bis der Timer nach 80 mS abgelaufen ist.

'RCTimerTimer' benötige ich eigentlich nur für COM - USB und HID 'funktionieren anders, deshalb lasse ich hier erst mal weg ....
Der Timer schaltet sich bei Aufruf selber ab, bis er wieder durch den ersten 'Neu-Impuls' in 'ComPortDSRChange' gestartet wird.
Dazwischen vergehen mindestens 20 mS - mit dem 'Erkennen' eines neuen, kompletten Daten-/Adress-Frames also min. 100 mS.
Das reicht erfahrungsgemäß nach ausgiebigen Tests hier, um eine Auswertung durchzuführen und Daten entsprechend an die Applikation(en) zu senden. Ich hatte bisher keine Timing-Probs damit. Mit ca. 20 und auch mehr verschiedenen FBs.

'CheckRCData' (hier nicht gelistet) validiert die Daten vorgegebener FB's/Programme und gibt sie bei Gültigkeit je nach Einstellung über eine flexibel einzubindende Callback-Rotuine an ein korrespondierendes Programm / System weiter:
- als ein KeyBoard-Event oder Maus-Simulation (an gewählte App / Fenster)
- via API des Programms direkt dahin
- oder .... was sonst noch so geht. Ausbaufähig ?!

Funktioniert wirklich recht genial.
Auf meinem WinDoof-HTPC (AMD X2 5400) kann ich damit die DVB-App 'DVBDream', VLC und auch die Online-TV-Zeitung TV-Browser recht gut vom Sofa mit einer IMON-FB (die hat ein Mausrad) recht prima bedienen. Noch gibt es hier & da ein paar Macken - aber da arbeite ich ja (wieder) dran .....


Problem ist bei der Lösung, dass ich wie o.g. absolut kein Held in Sachen Threads bin.
Und da dieses Proggie sowohl als Stand-Alone-App läuft (zum Anlernen, einstellen, zuweisen), sowie auch als DLL in einer Anwendung, ist eine generelle Kernzuweisung für die gesamte App sicher nicht der schlaueste Weg ...
Im SA-Betrieb stört die generelle Zuweisung auf einen Kern absolut nicht, aber z.B. als DLL mit DVBDream und meinem kleinen (naja, auch wachsenden) DVB-Proggie geht das von der reduzierten Performance her gar nicht.
Mit VLC + TV-Browser hab ich das mangels Zeit noch nicht getestet.

Wie löst man das mit dem Zugriff betreff QPC auf nur einen Kern am schlauesten ?

-

Geändert von TERWI (18. Jul 2011 um 20:11 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:37 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz