Nein nein nein... keine neue Tasten Entprellung...
Es geht um folgendes ...
man hat ein Uc und ein paar tasten angeschlossen und nun moechte man
heraus finden ist taste xy gedruckt oder nicht. Oder wurde diese gerade
erst gedruckt oder gerade erst losgelassen. Oder ... Man haelt diese
schon seit laengerem gedruckt..
Alles bekannte Anforderungen an kleine uC Steuerungen mit ein paar
tasten.
Also habe ich in die tasten gehauen und raus gekommen sind diese
Routinen, die genau diese Anforderungen erfüllen.
Das ganze ist so programmiert, das man bis zu 32 oder 64 (bei long long)
tasten solchen Status anfragen kann.
Der Status, die eine Tasten haben kann sind :
RELEASE wenn alles losgelassen ist
RELEASED wenn die Taste seit letzte abfrage Losgelassen wurde
PRESS wenn die Taste gedruckt ist
PRESSED wenn die Taste gedruckt wurde
PRESS_LONG wenn die Taste seit laengerem (Definition von laenge siehe
source code) gedruckt wurde
Der Status kann mehrere tasten Zustaende haben (PRESSED|PRESS) oder
(PRESS|PRESS_LONG) :D und folgt der negativen logik. (low active).
Viel Spass und hoffe Euch hilft es genau so,
wie es mir geholfen hat :)
Roman
roman65536 schrieb:
> Nein nein nein... keine neue Tasten Entprellung...
Hast recht, das Entprellen, also das Wichtigste, macht sie gerade nicht.
Warum?
> man hat ein Uc und ein paar tasten angeschlossen und nun moechte man> heraus finden ist taste xy gedruckt oder nicht. Oder wurde diese gerade> erst gedruckt oder gerade erst losgelassen. Oder ... Man haelt diese> schon seit laengerem gedruckt..
Jau, dat gibbed allet schon längst, schau Dir mal meine Entprellfunktion
für 8 Tasten an.
Die hat sogar ne Repeatfunktion und merkt sich den Druck, auch wenn
schon wieder losgelassen wurde.
Sie benötigt auch deutlich weniger Code, SRAM und CPU-Zeit.
> RELEASED wenn die Taste seit letzte abfrage Losgelassen wurde
...
> PRESSED wenn die Taste gedruckt wurde> PRESS_LONG wenn die Taste seit laengerem (Definition von laenge siehe> source code) gedruckt wurde
Deine Abfrage switches_status() liest doch nur den Status und setzt
nichts zurück. Also wie sollen dann genau nur einmal die Flags gesetzt
sein?
In meiner Routine erfolgt das Abtasten und das Auswerten dagegen völlig
unabhängig. Das Main kann die Ereignisflags auswerten und rücksetzen,
wann es Zeit hat und ist nicht an einen festen Zyklus gebunden.
Peter
Hmm..
Das mag ja sein Peter, das deine schneller, kleiner und und und ist...
Nur was soll man mit einer AVR Assembler routine auf einem Coldfire oder
ARM ??
oder ... wie werte ich zb. tasten aus, die von einem key/display
controller kommen so wie sie zb. in den video recordern verbaut sind ??
Da kommen die tasten bytes fix entprellt. Und wo es auch mehr als nur 8
tasten sein koennen ?? oder auswerten von hmm.. sagen wir mal
touchscreen ?? ist der stift auf der Flaeche oder nicht..
Die eigentlich Arbeit erledigt die switches_update() routine..
der alte wert wird verglichen mit den aktuellen. Per Xor oder "^" in C.
so alla D flip flop danach input und output xor'en und schon hat man
deltas.
der Rest ist nur noch logisches ORen oder ANDen..
"..merkt sich den Druck, auch wenn
schon wieder losgelassen wurde." Weiss nicht was du meinst.
roman
roman65536 schrieb:
> Nur was soll man mit einer AVR Assembler routine auf einem Coldfire oder> ARM ??
Hä?
Das ist doch C.
Beitrag "Universelle Tastenabfrage"
Und ein ARM ist bestimmt auch nicht unglücklich, wenn er weniger
CPU-Zeit benötigt.
Je nach Portbreite ist dann die Routine natürlich für minimal 16 oder 32
Inputs.
Das Vertical Counter Prinzip bearbeitet immer alle 8/16/32Bits parallel
und nicht in einer Loop.
> "..merkt sich den Druck, auch wenn> schon wieder losgelassen wurde." Weiss nicht was du meinst.
Der Timerinterrupt läuft immer, z.B. alle 10ms und tastet ab.
Die Mainloop ist z.B. für eine Sekunde mit was anderem beschäftigt. Dann
ruft sie get_key_press() auf und bekommt das Ereignis. Die Taste kann
derweil schon 0,5s losgelassen worden sein.
Der Trick ist, daß erst get_key_press() das Flag liest und löscht. Jeder
Tastendruck bewirkt dadurch auch nur genau ein Ereignis. Egal, wann und
wie oft get_key_press() aufgerufen wird.
Peter
Da muß ich Peter zustimmen: die Bulletproof-Geschichte läuft problemlos
auch auf einem STM32 (Cortex-M3) und auf einem ARM9 (unter WinCE6) -
reines C, ohne Spezialitäten, man muß nur die aktuelle Belegung der
Tasteneingänge abfragen...
Ahoi, Martin
Martin Schneider schrieb:
> Da muß ich Peter zustimmen: die Bulletproof-Geschichte läuft problemlos> auch auf einem STM32 (Cortex-M3) und auf einem ARM9 (unter WinCE6)
Ebenfalls auf einem TMS320F2812.
Schaut..
Mir hat diese version geholfen. Peter's "C" version kenne ich nicht,
resp. nicht gefunden in dem Uc.net code Sammlung (nur die asm avr
version), Peter nehme es nicht persoenlich, es ist manchmal schwer hier
etwas zu finden. Mir hat meine version geholfen den sie ist universal
und auch fuer Linux Solaris anwendbar resp. direkt PS/2 codes, Curses
oder Xwin. Wie schon jemand geschrieben hat.. nicht jede kann bei allen
moeglichen Applikationen Interrupts verwenden (damit ich nicht sagen
will, dass pooling besser ist).
Ich moechte doch niemanden schlecht oder besser machen oder
Programmierer Ego ankratzen. Ich verwende ja auch Peters code Fragmente
:) wollte lediglich etwas an die Gemeinschaft zurueckgeben. Sollte meine
version jemanden helfen, take it. wenn nicht.. niemand ist gezwungen es
runter zu laden.
lg roman
Wenn ich Deinen Code richtig verstehe, funktioniert er nur dann, wenn
switches_update() und switches_status() immer genau im Wechsel
aufgerufen werden. Erfolgt das zu langsam, können Ereignisse verloren
gehen.
Deshalb war es mir wichtig, das Abtasten und das Auswerten voneinander
zu entkoppeln.
Es nervt nämlich tierisch bei vielen kommerziellen Geräten, wenn
Tastendrücke verloren gehen.
Peter
Peter,
Ja das ist so..
Bei meiner Applikation wollte ich eigentlich auf das PRESSED losgehen..
dh. mich interessierte eigentlich nicht ob die Taste gedruckt ist (zu
dem zeitpunkt). Es sollte ein Taste gedrueck werden (was ein Status
PRESSED|PRESS zurueck gibt) um in ein Menue zu gelangen. Danach muss die
Taste wieder losgelassen werden und wieder gedruckt werden um weiter im
Menue etwas zu selektierien etc.
Bei mir laufft das ganze ohne Interrupts, den es je ein grosse loop. die
delta Erkennung koennte ich verbessern resp. aus dem loop rausnehmen,
jedoch die 5 verschiedene status muss ich per loop tun.
roman
roman65536 schrieb:
> Peter,>>> Ja das ist so..> Bei meiner Applikation wollte ich eigentlich auf das PRESSED losgehen..> dh. mich interessierte eigentlich nicht ob die Taste gedruckt ist (zu> dem zeitpunkt). Es sollte ein Taste gedrueck werden (was ein Status> PRESSED|PRESS zurueck gibt) um in ein Menue zu gelangen. Danach muss die> Taste wieder losgelassen werden und wieder gedruckt werden um weiter im> Menue etwas zu selektierien etc.
Genau für den Fall sind die PeDa Routinen besser geeignet.
Deine Funktionen könnte ich mir bei einem Joystick vorstellen, obwohl
ich mir nicht sicher bin, ob da nicht direkte Pin Abfrage einfacher
wäre.
> Bei mir laufft das ganze ohne Interrupts, den es je ein grosse loop. die> delta Erkennung koennte ich verbessern resp. aus dem loop rausnehmen,> jedoch die 5 verschiedene status muss ich per loop tun.
Man kann deine Funktionen auch aus einem Interrupt heraus aufrufen. So
ist das ja auch wieder nicht. Genauso wie man die PeDa Routinen aus der
ISR isolieren, in eine Funktion packen und aus der Hauptschleife heraus
aufrufen könnte.
Aber die fehlende Entprellung wäre für die meisten hier ein
KO-Kriterium.
Die PeDa Routinen haben den Charme, dass
* sie kurz sind
* so gut wie keine Rechenzeit verbrauchen
* irgendein regelmässiger Interrupt, den man mitbenutzen kann in
praktisch jedem Programm rumlungert
* sobald die ISR aktiv ist, sich keine Gedanken mehr um verlorene
Tastendrücke machen braucht. Selbst wenn das Programm kurzfristig
etwas mehr zu tun hat, gehen selbst kurze Tastendrücke nicht verloren.
* sie auch mit den grindigsten Tasten, deren Kontakte ausgeleiert sind,
klar kommen.
* sie schnell in ein Projekt übernommen, eingebaut und angepasst werden
können.
Es ist schwer, diese Funktionalität zu toppen. Egal in welcher Richtung.
In Punkte Codeverbrauch, Resourcenverbrauch, Komfort (sowohl für den
Anwender als auch für den Programmierer) sind sie so ziemlich das
Optimium dessen, was man kriegen kann.
Tja Karl..
Genau um das ging es auch bei mir ja .. eine Art Joystick,
mit dem ich dann nur noch feststellen wollte ging es rauf/runter oder
ins menue rein. Und dabei habe ich nur berücksichtigt, das ich die
gleichen routinen auch fuer das auswerten von einem PT6311 benutzen
koennte oder etwas anderes.
Da ich leider zu dem Zeitpunkt nichts von der C version wusste und in
der AVR Code samlung nur die ASM version fand, haute ich selber in die
tasten.
Es geht doch gar nicht um zu top'en. waere zb. die C version auch dort,
wuerde ich es meine wahrscheinlich nie programieren.
Zu dem waere es wirklich keine Sache den code zu ergänzen das nix
verloren geht. Ob das allerdings Sinn macht, ist eine andere Sache...
den PRESSED|RELEASED zusammen... na ja.
Meine End user (4,7 jh) kommen mit der Version auf alle Faelle ziemlich
klar, ob jetzt die tasten status per int. oder per polling gesetzt wird,
ist Ihnen egal, Hauptsache passiert was..
Und mir hat es geholfen.
Irgendwie, kommt es mir vor als nur "privilegierte" leute hier code rein
stellen koennen... ich zwinge doch niemanden...
BTW: Peter du hast mich auf eine idee gebracht wie ich den loop los
werden kann. hmmm... cool...
Da hier schon einige den Code kennen und davon begeistert sind, mag der
Eindruck entstehen, daß nun alle auf Dich eindreschen. Das ist aber
bestimmt nicht so gemeint.
Letztendlich wichtig ist, daß eine Lösung zuverlässig arbeitet.
Und schön ist dann, wenn sie mit möglichst wenig Seiteneffekten und
Ressourcen in andere Projekte einfügbar ist.
Meine Projekte sind wohl etwas kleiner als Deine, daher kein extra
Tastenkontroller und das Entprellen muß mit drin sein.
Peter
roman65536 schrieb:
> Genau um das ging es auch bei mir ja .. eine Art Joystick,> mit dem ich dann nur noch feststellen wollte ging es rauf/runter oder> ins menue rein.
OK.
Das ist dann im Eröffnungsposting nicht so recht reübergekommen.
> Irgendwie, kommt es mir vor als nur "privilegierte" leute hier code rein> stellen koennen... ich zwinge doch niemanden...
Sorry, wenn dieser Eindruck entsteht.
Das wir sicherlich nicht so gemeint.
Das Thema Tastenentprellunf und Auswertung (diesmal mit echten
Digi-Tastern) ist eines, welches oft genug um restlichen Forum
auftaucht. Und oft sehen wir dort völlig untaugliche Entprellfunktionen,
die der Frager nur deswegen eingebaut hat, weil er sie 'irgendwo'
gefunden hat.
Ich denke, es ist auch in der Codesammlung wichtig abzugrenzen, wo ein
Code eingebaut werden kann und wo nicht. Wo er Sinn macht und wo nicht.
Wo es bessere Lösungen gibt und wo nicht.
> BTW: Peter du hast mich auf eine idee gebracht wie ich den loop los> werden kann. hmmm... cool...
Dann hat es sich schon ausgezahlt :-)
Vielleicht liegt es auch an meinem wording...
Ich wollte nicht dass ein Eindruck von Entprellung entsteht. Das thema
ist ja zur genuege behandelt.
Es geht hier um eine High level Auswertung (oder zu minderst higher
level :).
dh. Von einem Kontroller ala VFD Kontroller kriegt man eine byte
sequence mit Tasten bits, die entweder high oder low sind. Den
Kontroller muss man periodisch auslesen um an diese key byte sequence zu
gelangen. Jedoch..
So wie der VFD Kontroller arbeitet, sind die tasten schon entprellt und
ready to use.
Darum auch das Wort "Auswertung" und kein bulletprooved oder Entprellung
etc...
Meine Routinen stellen dann fest, ob die key's high/low sind oder seit
dem letztem Durchlauf resp. abfrage Gedruckt worden sind oder wieder
Losgelassen, oder ist eine taste laenger gedruckt.
roman