Inputstatus nur bei Änderung senden
Wie manfred hatte auch ich ein Problem damit, dass ein anliegendes Input-Signal permanent übermittelt wird. Das ist nun anders, der Input-Status wird nur noch bei Änderungen übermittelt. Im Unterschied zu seiner Lösung erfolgt bei mir aber auch keine periodische Wiederholung, solange diese nicht explizit angefordert wird.
Togglen von Eingängen (Bit 7)
Wenn das Bit 7 aktiviert ist (0x40), dann werden die Bits 1 bis 6 als "Toggle"-Befehl gedeutet. Beispiel: 0b01010001 bedeutet, dass der Status von Relais 1 und 5 geändert wird. Die Anderen bleiben wie sie sind. 0b01111111 wechselt den Status aller Relais, 0b01000000 bleibt ohne jeden Effekt.
Abfrage des Portstatus (Bit 8 )
Manchmal ist es sinnvoll erfragen zu können wie die Relais aktuell geschaltet sind. Und da der Input-Status nun nicht mehr permanent gesendet wird, möchte man diesen nun womöglich auch explizit abfragen können. Deshalb dient Bit 8 (0x80) nun dazu, im Anschluss an den aktuellen Befehl den Status von Input- und Output-Ports zurückzugeben.
Um den Status zu erfragen ohne ihn zu ändern kann man das Status-Bit 8 mit dem Toggle-Bit 7 kombinieren und 0b11000000 (= 0xC0) senden. Dies bedeutet: "Toggle nichts, und gib mir anschließend den Status der Ports zurück".
Damit das lesende Programm Input- und Output-Ports voneinander unterscheiden kann ist beim Output-Port das Bit 8 aktiviert. Sind zum Beispiel die Relais 2, 3 und 5 aktiviert, und am Optokoppler 4 liegt ein Signal an, so sähe die Antwort auf ein 0xC0 so aus:
>>> 0b11000000 (Status erfragen)
<<< 0b10010110 (Bit 8 = 1: Status der Relais)
<<< 0b00001000 (Bit 8 = 0: Status der Eingänge)
Initialisierung zum Schutz vor Hardwareerkennung
Wie bereits von Lucky001 berichtet habe auch ich das Problem, dass die Relais beim ersten Einstecken zufällige Umschaltungen vornehmen. Vermutlich liegt es an der Hardwareerkennung des Betriebssystem, die das angeschlossene Gerät zu identifizieren versucht.
Der angehängte Patch löst das Problem, in dem er initial eine Sequenz von 16 aufeinanderfolgenden 0xC0-Bytes erwartet, bevor Eingaben akzeptiert werden. Der Vorteil dieser Variante ist, dass sie in keinem Fall eine Änderung der Relais verursacht, auch wenn die Relaiskarte bereits initialisiert sein sollte. Im schlimmstem Fall werden halt nur 2*16 Bytes für die angefragten Port-Stati gesendet.
@Ulrich: Vielen, vielen Dank für dieses geniale Projekt
![Smile :-)](./images/smilies/icon_smile.gif)
Update 11.10.2010:
Den initFrames-Zähler nun jedesmal zurücksetzen, wenn die usbDeviceAdr == 0 ist. Dies deutet nämlich darauf hin, dass die Platine zwischenzeitlich vom PC getrennt war oder dieser neu gestartet wurde. Auch dann muss der Hardware-Erkennungsversuch des Betriebssystems geblockt werden. Hierfür war es notwendig, die Variable "usbDeviceAdr" aus der usbdrv/usbdrv.c als "extern" zu deklarieren. Um den Code von usbdrv nicht zu modifizieren erfolgt dies in der usbconfig.h, die von beiden C-Dateien inkludiert wird.
Bei der Gelegenheit auch gleich USB_CFG_IS_SELF_POWERED auf 1 gesetzt, da wir die Spannungsversorgung der USB-Schnittstelle nicht benötigen und dies dem Controller auch mitteilen sollten
![Smile :-)](./images/smilies/icon_smile.gif)