ASTERISK option added
[opentx.git] / radio / src / keys.cpp
blob9f9052d727d1fa20047ce0ad9db2b7ee67f7ecbb
1 /*
2 * Copyright (C) OpenTX
4 * Based on code named
5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #include "opentx.h"
23 #define KEY_LONG_DELAY 32 // long key press minimum duration (x10ms), must be less than KEY_REPEAT_DELAY
24 #define KEY_REPEAT_DELAY 40 // press longer than this enables repeat (but does not fire it yet)
25 #define KEY_REPEAT_TRIGGER 48 // repeat trigger, used in combination with m_state to produce decreasing times between repeat events
26 #define KEY_REPEAT_PAUSE_DELAY 64
28 #ifdef SIMU
29 #define FILTERBITS 1 // defines how many bits are used for debounce
30 #else
31 #define FILTERBITS 4 // defines how many bits are used for debounce
32 #endif
34 #define KSTATE_OFF 0
35 #define KSTATE_RPTDELAY 95
36 #define KSTATE_START 97
37 #define KSTATE_PAUSE 98
38 #define KSTATE_KILLED 99
41 event_t s_evt;
42 struct InactivityData inactivity = {0};
43 Key keys[NUM_KEYS];
45 event_t getEvent(bool trim)
47 event_t evt = s_evt;
48 int8_t k = EVT_KEY_MASK(s_evt) - TRM_BASE;
49 bool trim_evt = (k>=0 && k<TRM_LAST-TRM_BASE+1);
51 if (trim == trim_evt) {
52 s_evt = 0;
53 return evt;
55 else {
56 return 0;
60 void Key::input(bool val)
62 // store new value in the bits that hold the key state history (used for debounce)
63 uint8_t t_vals = m_vals ;
64 t_vals <<= 1 ;
65 if (val) t_vals |= 1;
66 m_vals = t_vals ;
68 m_cnt++;
70 if (m_state && m_vals == 0) {
71 // key is released
72 if (m_state != KSTATE_KILLED) {
73 // TRACE("key %d BREAK", key());
74 putEvent(EVT_KEY_BREAK(key()));
76 m_state = KSTATE_OFF;
77 m_cnt = 0;
78 return;
81 switch (m_state) {
82 case KSTATE_OFF:
83 if (m_vals == ((1<<FILTERBITS)-1)) {
84 m_state = KSTATE_START;
85 m_cnt = 0;
87 break;
89 case KSTATE_START:
90 // TRACE("key %d FIRST", key());
91 putEvent(EVT_KEY_FIRST(key()));
92 inactivity.counter = 0;
93 m_state = KSTATE_RPTDELAY;
94 m_cnt = 0;
95 break;
97 case KSTATE_RPTDELAY: // gruvin: delay state before first key repeat
98 if (m_cnt == KEY_LONG_DELAY) {
99 // generate long key press
100 // TRACE("key %d LONG", key());
101 putEvent(EVT_KEY_LONG(key()));
103 if (m_cnt == KEY_REPEAT_DELAY) {
104 m_state = 16;
105 m_cnt = 0;
107 break;
109 case 16:
110 case 8:
111 case 4:
112 case 2:
113 if (m_cnt >= KEY_REPEAT_TRIGGER) { //3 6 12 24 48 pulses in every 480ms
114 m_state >>= 1;
115 m_cnt = 0;
117 // no break
118 case 1:
119 if ((m_cnt & (m_state-1)) == 0) {
120 // this produces repeat events that at first repeat slowly and then increase in speed
121 // TRACE("key %d REPEAT", key());
122 if (!IS_SHIFT_KEY(key()))
123 putEvent(EVT_KEY_REPT(key()));
125 break;
127 case KSTATE_PAUSE: //pause repeat events
128 if (m_cnt >= KEY_REPEAT_PAUSE_DELAY) {
129 m_state = 8;
130 m_cnt = 0;
132 break;
134 case KSTATE_KILLED: //killed
135 break;
139 void Key::pauseEvents()
141 m_state = KSTATE_PAUSE;
142 m_cnt = 0;
145 void Key::killEvents()
147 // TRACE("key %d killed", key());
148 m_state = KSTATE_KILLED;
152 uint8_t Key::key() const
154 return (this - keys);
157 // Introduce a slight delay in the key repeat sequence
158 void pauseEvents(event_t event)
160 event = EVT_KEY_MASK(event);
161 if (event < (int)DIM(keys)) keys[event].pauseEvents();
164 // Disables any further event generation (BREAK and REPEAT) for this key, until the key is released
165 void killEvents(event_t event)
167 event = EVT_KEY_MASK(event);
168 if (event < (int)DIM(keys)) {
169 keys[event].killEvents();
173 void killAllEvents()
175 for (uint8_t key = 0; key < DIM(keys); key++) {
176 keys[key].killEvents();
180 bool waitKeysReleased()
182 #if defined(PCBSKY9X)
183 RTOS_WAIT_MS(200); // 200ms
184 #endif
186 // loop until all keys are up
187 #if !defined(BOOT)
188 tmr10ms_t start = get_tmr10ms();
189 #endif
191 while (keyDown()) {
192 WDG_RESET();
194 #if !defined(BOOT)
195 if ((get_tmr10ms() - start) >= 300) { // wait no more than 3 seconds
196 //timeout expired, at least one key stuck
197 return false;
199 #endif
202 memclear(keys, sizeof(keys));
203 putEvent(0);
204 return true;