www.mikrocontroller.net

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


Autor: Karsten K. (karsten42)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
evtl. direkt if( key_state & shift_key_mask ) benutzen?

Autor: Gerhard (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach dir eine zusätzliche Funktion
uint8_t is_key_press( uint8_t key_mask )
{
  cli();                                          // read and clear atomic !
  key_mask &= key_state;
  sei();
  return key_mask;
}

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.

Autor: Karsten K. (karsten42)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karsten K. (karsten42)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
volatile uint8_t key_state;                                // debounced and inverted key state:
                                                  // bit = 1: key pressed
volatile uint8_t key_press;                                // key press detect
 
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)

Autor: Karsten K. (karsten42)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karsten K. (karsten42)
Datum:

Bewertung
0 lesenswert
nicht 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:
#define SHIFT_KEYS  (1<<KEY_LEVL)              // Shift Keys
#define SECOND_KEYS  (1<<KEY_FRQ | 1 << KEY_MODE)// Second function Keys

volatile uint8_t key_shift;

//...Code in ISR()
key_press |= key_state & i;        // 0->1: key press detect

if(key_state & SHIFT_KEYS)  {      // if key in SHIFT_KEYS ?

   if(key_state & SECOND_KEYS)  {  // Second key just pressed now?

      key_shift |= key_state & i;  // write keys to shift buffer
      key_press ^= key_shift;      //clear keys from key_press
   }
}


// Abfrage Funktion
uint8_t
get_key_shift( char key_mask )  {

  cli();
  key_mask &= key_shift;          // read key(s)
  key_shift ^= key_mask;          // clear key(s)
  sei();
  return key_mask;
}

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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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:
  if( get_key_press( 1<<KEY_1_2 ){
    if( key_state & 1<<KEY_SHIFT ){
      do_1();
    }else{
      do_2();
    }
  }


Peter

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
>
> uint8_t is_key_press( uint8_t key_mask )
> {
>   cli();                                          // read and clear
> atomic !
>   key_mask &= key_state;
>   sei();
>   return key_mask;
> }
> 
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...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Läubi .. schrieb:
> Karl heinz Buchegger schrieb:
>>
>> uint8_t is_key_press( uint8_t key_mask )
>> {
>>   cli();                                          // read and clear
>> atomic !
>>   key_mask &= key_state;
>>   sei();
>>   return key_mask;
>> }
>> 
> Mal eine Verständnisfrage: Wozu hier ein cli?

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.