Hallo zusammen!
Ich sitze hier grad vor einem Problem und komme nicht mehr weiter.
Es geht um Folgendes:
Ich habe mir einen Adapter für meine im Auto vorhandene
Lenkradfernbedienung gebaut. Die LFB-Tasten sind eine Widerstandsleiter,
also geradezu prädestiniert für die berühmte PeDa
Matrix-Entprellroutine.
Leider funktioniert diese ja nur genau ein Mal, also bei einem
Tastendruck ist die Prüfung auf "Taste gedrückt" nur beim ersten Mal
wahr.
Ich hätte aber gern, so wie bei der "normalen" PeDa-Entprellung, die
Möglichkeit einen langen Tastendruck mit automatischer Wiederholung zu
realisieren.
Also habe ich die Matrix-Entprellung erst mal ein wenig für mich
umgebaut, meine Tasten sind ja nicht in einer Matrix.
Das Array mit den Schwellwerten bekommt eben eine andere Füllung,
gleichzeitig habe ich die Einträge auf 16bit-Typen umgestellt.
Im Debugger hat das schon mal ganz gut ausgesehen, bis auf die Tatsache
mit der fehlenden Wiederholmöglichkeit.
Darum habe ich versucht, diese Funktionen nachzurüsten.
Also die zusätzliche Variable und die #defines im Header, sowie die
Funktion get_key_rpt in meinen Code eingefügt, und die Interrupt-Routine
erweitert.
Original Matrix-Interrupt:
1 | static u16 ct0, ct1;
|
2 | u16 i;
|
3 |
|
4 | i = key_state ^ key_no( ADCH ); // key changed ?
|
5 | ct0 = ~( ct0 & i ); // reset or count ct0
|
6 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1
|
7 | i &= ct0 & ct1; // count until roll over ?
|
8 | key_state ^= i; // then toggle debounced state
|
9 | key_press |= key_state & i; // 0->1: key press detect
|
Original Tasten-Interrupt:
1 | static uint8_t ct0 = 0xFF, ct1 = 0xFF, rpt;
|
2 | uint8_t i;
|
3 |
|
4 | i = key_state ^ ~KEY_PIN; // key changed ?
|
5 | ct0 = ~( ct0 & i ); // reset or count ct0
|
6 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1
|
7 | i &= ct0 & ct1; // count until roll over ?
|
8 | key_state ^= i; // then toggle debounced state
|
9 | key_press |= key_state & i; // 0->1: key press detect
|
10 |
|
11 | if( (key_state & REPEAT_MASK) == 0 ) // check repeat function
|
12 | rpt = REPEAT_START; // start delay
|
13 | if( --rpt == 0 ){
|
14 | rpt = REPEAT_NEXT; // repeat delay
|
15 | key_rpt |= key_state & REPEAT_MASK;
|
16 | }
|
Bei mir wurde daraus:
1 | uint16_t val;
|
2 | val = ADC;
|
3 |
|
4 | static uint16_t ct0;
|
5 | static uint16_t ct1;
|
6 | static uint16_t rpt;
|
7 | uint16_t i;
|
8 |
|
9 | // key press detection
|
10 | i = key_state ^ key_no(val); // key changed ?
|
11 | ct0 = ~( ct0 & i ); // reset or count ct0
|
12 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1
|
13 | i &= ct0 & ct1; // count until roll over ?
|
14 | key_state ^= i; // then toggle debounced state
|
15 | key_press |= key_state & i; // 0->1: key press detect
|
16 |
|
17 | // key repeat detection
|
18 | if((key_state & REPEAT_MASK) == key_state) // check repeat function
|
19 | rpt = REPEAT_START; // start delay
|
20 | if( --rpt == 0 )
|
21 | {
|
22 | rpt = REPEAT_NEXT; // repeat delay
|
23 | key_rpt |= key_state & REPEAT_MASK;
|
24 | }
|
Im PeDa Tasten-Interrupt werden der Eingangs-Port invertiert wird, hat
natürlich die Wiederholungs-Behandlung
if( (key_state & REPEAT_MASK) == 0 )
nicht funktioniert, und ich habe es in
if((key_state & REPEAT_MASK) == key_state)
geändert.
Jetzt hab ich aber das Problem, dass in jedem Interrupt der Variablen
rpt wieder REPEAT_START zugewiesen wird, also der Countdown funktioniert
nicht.
Bei mir hats immer noch über 30° in der Wohnung, ich glaub mein Hirn ist
etwas weichgekocht im Moment... ;)
Könnt ihr mal bitte darüberschauen, ob ihr meinen Fehler findet?
Für Lösungsvorschläge wäre ich sehr dankbar!
MfG Stefan