Forum: Mikrocontroller und Digitale Elektronik Shift-Taste mit PeDa-Lösung


von Karsten K. (karsten42)


Lesenswert?

Moin Moin,

ist mir etwas peinlich aber ich finde nirgends im Forum die Beschriebung 
wie ich mit den PeDa-Funktionen eine Shift + TasteX zum laufen kriege. 
Im Thread
50941 hat Herr Danneegger zwar darauf hingewiesen das er es schon 
beschrieben hat wie es gehen soll; ich hab´s jedoch nirgend gefunden :-(

Ich hab´s mit get_key_long() für die Shift Taste und get_key_short() für 
die TasteX probiert. Das geht aber nur eingeschränkt, denn wenn TasteX 
vorher mal gedrückt wurde und dann die Shift taste lang OHNE TasteX 
gedrückt zu haben:
Example:
if(get_key_long(...) {
   if(het_key_short(...) {
   // juchuuu Shift taset + TasteX
   }
}

Mag mir jemand den Link zum entsprechdenden Thread nennen oder einen 
Tipp geben wie ich das mit der Shift-taste lösen kann??

Daaaanke
Karsten

von Gerhard (Gast)


Lesenswert?

evtl. direkt if( key_state & shift_key_mask ) benutzen?

von Gerhard (Gast)


Lesenswert?

Vollständige Links werden von der Forensoftware umgebaut: 
Beitrag "Einfaches Problem bei Tastendruckerkennung - bitte um Hilfe"

von Karl H. (kbuchegg)


Lesenswert?

Mach dir eine zusätzliche Funktion
1
uint8_t is_key_press( uint8_t key_mask )
2
{
3
  cli();                                          // read and clear atomic !
4
  key_mask &= key_state;
5
  sei();
6
  return key_mask;
7
}

Die Funktion hat die Aufgabe festzustellen, ob eine Taste jetzt gerade 
in diesem Moment gedrückt ist oder nicht. Diese Funktion kannst du dann 
benutzen um nach der Erkennung eines Tastendrucks festzustellen, ob 
jetzt gerade im Moment die SHIFT-Taste betätigt ist oder nicht.

Perfekt ist es nicht, denn zum Zeitpunkt an dem get_key_press eine 
gedrückte Taste meldet, kann ja theoretisch die Taste schon wieder 
losgelassen worden sein.

von Karsten K. (karsten42)


Lesenswert?

Moin Moin,

Vielen dank für die Tipps!

Die Problematik mit get_key_press() ist die gleiche die ich auch schon 
habe :-(  Wenn die "erste" taste losgelassen wird, ist die Erkennung der 
zweiten noch aktiv auch wenn diese minuten später gedrückt wird.
Die normale "Shit-Tasten" kombination ist ja nur gültig wenn beide 
Tasten gleichzeitig gedrückt sind. Die Erkennung einer zweiten Taste 
darf also nur so lange laufen bis eine Zweite (passende) gedrückt wurde 
oder die Erste losgelassen. In etwa so:
if(shift-taste) {
  while(shift gedrückt){
    if(ziel-taste) {
      //mach was draus
      break;
    }
  }
}

Eine Idee??

Gruß
Karsten

von Karl H. (kbuchegg)


Lesenswert?

Karsten Kankowski schrieb:

> Die Problematik mit get_key_press() ist die gleiche die ich auch schon
> habe :-(  Wenn die "erste" taste losgelassen wird, ist die Erkennung der
> zweiten noch aktiv auch wenn diese minuten später gedrückt wird.

Genau

> Die normale "Shit-Tasten" kombination ist ja nur gültig wenn beide
> Tasten gleichzeitig gedrückt sind.

Das müsste man aber ins Herz der ganzen Tastenauswertung reintragen.

> Die Erkennung einer zweiten Taste
> darf also nur so lange laufen bis eine Zweite (passende) gedrückt wurde
> oder die Erste losgelassen. In etwa so:

Das bringt dich im Grunde alles nicht weiter.
Wenn überhaupt, dann müsste man in der ISR erweitern, so dass in der ISR 
nachdem eine Taste als gedrückt anerkannt wurde, gleichzeitig auch noch 
der Zustand einer Shift-Taste mit ausgewertet wird.
Nur dann würde es 100% sicher werden.

Daher sind IMHO solche Shift-Sachen mit der jetzigen Komfortlösung keine 
so gute Idee.

von Karsten K. (karsten42)


Lesenswert?

Moin Karl,

Ja, ich habe die 2-Tastenfrage ( wozu ich die Shift-funktion mitzähle ) 
hier im Forum schon ausgiebig gelesen.
Meine Hoffung war eben jene Aussage von Peter, dass er eine Shift-Tasten 
Lösung schon mal beschrieben habe.

Die ISR erweitern wollte ich eigentlich nicht; denn letztlich wollte ich 
mich um andere Dinge kümmern und die geniale Tastenabfrage "nur" nutzen 
und mich darauf verlassen können.

Ich werde mal probieren ob ich das schaffe; Peter ist da viel genialer 
und ich werde mir sicher einen "abbrechen" :-)

Danke für deine schnelle Hilfe!

Karsten

von Karl H. (kbuchegg)


Lesenswert?

Karsten Kankowski schrieb:

> Ich werde mal probieren ob ich das schaffe; Peter ist da viel genialer
> und ich werde mir sicher einen "abbrechen" :-)

Das Problem ist, dass du mit diesen 3 Variablen
1
volatile uint8_t key_state;                                // debounced and inverted key state:
2
                                                  // bit = 1: key pressed
3
volatile uint8_t key_press;                                // key press detect
4
 
5
volatile uint8_t key_rpt;                                  // key long press and repeat

die Information, ob zum Zeitpunkt des Anerkennens des Tastendrucks eine 
Shift-Taste gedrückt war oder nicht, nicht festhalten kannst.

Du kannst maximal die Auswertung so machen, dass zum Zeitpunkt des 
Auswertens des Tastendrucks per get_key_press noch eine Shift-Taste 
gedrückt sein kann. Wenn die Auswertung kurz nach den Tastendruck 
passiert, ist das kein Problem. Muss der Tastendruck aber 5 Sekunden 
oder länger auf seine Auswertung warten, wird das ein Problem.

Was du tun könntest: Die Shift Taste bewirkt im Programm eine 
Modusumschaltung, die zb durch eine LED angezeigt wird (toggelt den 
Zustand) und dadurch wird der nächste Tastendruck anders ausgewertet. 
Das ist zwar nicht ganz dasselbe wie eine Shift-Taste, kommt der Sache 
aber noch am nächsten. Taschenrechner benutzen zb sowas um eine 2.te 
Funktionsebene auf die Tasten zu mappen. (Bei TI-Rechnern: die "2nd" 
Taste)

von Karsten K. (karsten42)


Lesenswert?

Moin Karl,

Ich muss darüber nachdenken ( soll sowieso ganz gut sein :-) )

Ein 2nd Mode ist eine Option. Es ist dann eine Reihenfolge von Tasten zu 
drücken die in den entsprechenden Mode führt. Ergonomisch nicht toll und 
auch nicht Sicher gegen zufällige Wahl der Reihenfolge. Eine Zeitvorgabe 
in der die Reihenfolge gedrückt werden kann wäre dann zumindest 
notwendig.

Hummm, echt schade um die geniale Tastenabfrage. Es kommt eben in der 
Praxis häufiger vor, dass man mit "shift+X" oder "Zwei-Tasten lange 
drücken" in einen speziellen mode schalten möchte. Es geht eben darum 
diesen mode möglichst nicht zufällig zu erreichen ( daher die beiden 
Finger/Hand ).

Beste grüße
Karsten

von Karsten K. (karsten42)


Lesenswert?

Moin Moin

Ich habe jetzt etwas nachdenken können. Wie gesagt: Sicher nicht so 
elegant wie Peter aber es funktioniert.
Ich habe die ISR etwas erweitert um eine ( oder mehrere ) Shift Tasten 
abzufragen. Ist eine Shift-Taste gerade gedrückt und eine weitere Taste 
ebenfalls ( irgend wann später mal ), so wird ein shift buffer 
beschrieben.
Dieser lässt sich dann "wie gewohnt" mit einer kleinen Funktion 
auslesen. Die normalen Funktionen der Tasten bleiben weiterhin erhalten.

Es muss folgendes zum vorhandenen Code hinzugefügt werden:
1
#define SHIFT_KEYS  (1<<KEY_LEVL)              // Shift Keys
2
#define SECOND_KEYS  (1<<KEY_FRQ | 1 << KEY_MODE)// Second function Keys
3
4
volatile uint8_t key_shift;
5
6
//...Code in ISR()
7
key_press |= key_state & i;        // 0->1: key press detect
8
9
if(key_state & SHIFT_KEYS)  {      // if key in SHIFT_KEYS ?
10
11
   if(key_state & SECOND_KEYS)  {  // Second key just pressed now?
12
13
      key_shift |= key_state & i;  // write keys to shift buffer
14
      key_press ^= key_shift;      //clear keys from key_press
15
   }
16
}
17
18
19
// Abfrage Funktion
20
uint8_t
21
get_key_shift( char key_mask )  {
22
23
  cli();
24
  key_mask &= key_shift;          // read key(s)
25
  key_shift ^= key_mask;          // clear key(s)
26
  sei();
27
  return key_mask;
28
}

In SHIFT_KEYS werden dann alle shift keys ODER verknüpft angegeben. In 
SECOND_KEYS dann diejenigen Tasten für die eine Shift Funktion gelten 
soll. Dabei dürfen dann die Shift Tasten nicht gleichzeitig auch 2nd 
Funktions Tasten sein.

Beste Grüße
Karsten

von Peter D. (peda)


Lesenswert?

Naja, in der Regel möchte man bei Benutzung einer Shifttaste auch ein 
Feedback, d.h. die Auswertung sollte zeitnah (<1s) erfolgen.

Und dann wertet man sie einfach im Main aus:
1
  if( get_key_press( 1<<KEY_1_2 ){
2
    if( key_state & 1<<KEY_SHIFT ){
3
      do_1();
4
    }else{
5
      do_2();
6
    }
7
  }


Peter

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
>
1
> uint8_t is_key_press( uint8_t key_mask )
2
> {
3
>   cli();                                          // read and clear
4
> atomic !
5
>   key_mask &= key_state;
6
>   sei();
7
>   return key_mask;
8
> }
9
>
Mal eine Verständnisfrage: Wozu hier ein cli? Ein uint8 wird ja immer in 
"einem mal" ausgewertet, und auch key_state sollte auch nur einmal 
gelesen werden, key_mask ist sowieso lokal...

von Karl H. (kbuchegg)


Lesenswert?

Läubi .. schrieb:
> Karl heinz Buchegger schrieb:
>>
1
>> uint8_t is_key_press( uint8_t key_mask )
2
>> {
3
>>   cli();                                          // read and clear
4
>> atomic !
5
>>   key_mask &= key_state;
6
>>   sei();
7
>>   return key_mask;
8
>> }
9
>>
> Mal eine Verständnisfrage: Wozu hier ein cli?

Weil ich den Code einfach kopiert habe :-)
(Asche auf mein Haupt)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.