]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/libs4c/kbd/kbd_base.c
Included ARM LPC21xx related code from uLan project. The snapshot date is 2008-07-05
[lincan.git] / embedded / libs4c / kbd / kbd_base.c
1 #include "kbd.h"
2
3 extern scan2key_t *kbd_scan2key_tab;
4 extern scan2mod_t *kbd_scan2mod_tab;
5
6 /* State of keyboard matrix and key press reporting */
7
8 unsigned char key_down_arr[KBD_SCAN_CNT];
9 unsigned char key_chng_arr[KBD_SCAN_CNT];
10 unsigned char key_hit;
11
12 kbd_keymod_t key_mod;
13
14 int key_last_changed;
15
16 /* Internal state for repeat processing */
17
18 short key_use_timer;
19 short key_state;
20 kbd_interval_t key_time;
21
22 #define KEY_STATE_IDLE     0
23 #define KEY_STATE_PUSH     1
24 #define KEY_STATE_RELEASE  2
25 #define KEY_STATE_REPEAT   4
26 #define KEY_STATE_NOISE    8
27 #define KEY_STATE_BUSY     (KEY_STATE_PUSH|KEY_STATE_RELEASE)
28
29
30 /**
31  * kbd_scan - Scan keyboard matrix and report requests for state change
32  *
33  * Scans keyboard matrix connected row by row by calling function
34  * mx1_kbd_onerow(). Number of scanned output lines is defined
35  * by %KBD_SCAN_CNT. Checks read keyboard state against @key_down_arr
36  * and updates @key_change_arr array. The @key_down_arr state is 
37  * left unchanged. It is changed later by kbd_down() function.
38  * Returns 0, if no keyboard activity is found. Returns 1
39  * if at least one key is pressed. Returns 2 or 3 in case
40  * of detected change.
41  */
42 int 
43 kbd_scan()
44 {
45         int i, ret=0;
46         unsigned char mask, val, chng;
47         for(i=0,mask=1;i<KBD_SCAN_CNT;i++,mask<<=1) {
48                 val=kbd_onerow(mask);
49                 chng=val^key_down_arr[i];
50                 key_chng_arr[i]=chng;
51                 if(val) ret|=1;
52                 if(chng) ret|=2;
53         }
54         /* mx1_kbd_onerow(~0); */
55         return ret;
56 }
57
58
59 /**
60  * kbd_scan2mod - Propagate keyboard matrix changes between modifiers
61  * @scan_code:          Scan code of last detected key change
62  *
63  * Functions check keyboard matrix state in @key_down_arr.
64  * It updates @key_mod according to @key_down_arr and 
65  * modifiers transformations table @kbd_scan2mwmod_tab.
66  */
67 void 
68 kbd_scan2mod(int scan_code)
69 {
70         unsigned char val, chng;
71         int s;
72         scan2mod_t *mt=kbd_scan2mod_tab;
73
74         for(;(s=mt->scan);mt++) {
75                 chng=(s==scan_code);
76                 s--;
77                 val=key_down_arr[s/KBD_RET_CNT]&(1<<(s%KBD_RET_CNT));
78                 if(val) {
79                         key_mod|=mt->set_mod;
80                         if(chng){
81                                 key_mod^=mt->xor_mod;
82                         }
83                 } else {
84                         key_mod&=~mt->set_mod;
85                 }
86         }
87 }
88
89 /**
90  * kbd_down - Detects changed key scancode and applies changes to matrix state
91  *
92  * Functions check @key_chng_arr and process changes.
93  * It updates its internal state @key_state, does
94  * noise cancellation and repeat timing, then updates 
95  * @key_down_arr, stores detected scancode to @key_last_changed
96  * and calls modifiers processing kbd_scan2mod().
97  * Return value is zero if no change is detected. 
98  * In other case evaluated scancode is returned.
99  * Variable @key_hit signals by value 1 pressed key, by value
100  * 2 key release.
101  */
102 int 
103 kbd_down()
104 {
105         int i, j=0;
106         unsigned char val;
107         
108         if(!(key_state&KEY_STATE_BUSY)){
109                 for(i=0;i<KBD_SCAN_CNT;i++) {
110                         if(!(val=key_chng_arr[i])) continue;
111                         for(j=0;!(val&1);j++) val>>=1;
112                         key_last_changed=i*KBD_RET_CNT+j+1;
113                         if(key_down_arr[i]&(1<<j)){
114                                 key_time=KEY_TIMER+KEY_PUSH_T;
115                                 key_state=KEY_STATE_RELEASE;
116                         }else{
117                                 key_time=KEY_TIMER+KEY_RELEASE_T;
118                                 key_state=KEY_STATE_PUSH;
119                         }
120                         break;
121                 }
122                 if(key_state==KEY_STATE_IDLE)
123                         return 0;
124         } else {
125                 if(!key_last_changed){
126                         key_state=KEY_STATE_IDLE;
127                         return 0;
128                 }
129                 i=(key_last_changed-1)/KBD_RET_CNT;
130                 j=(key_last_changed-1)%KBD_RET_CNT;
131                 if(!(key_chng_arr[i]&(1<<j))){
132                         /* Noise detected */
133                         if(!(key_state&KEY_STATE_NOISE)){
134                                 key_time=KEY_TIMER+KEY_RELEASE_T;
135                                 key_state|=KEY_STATE_NOISE;
136                         }
137                 }
138         }
139
140         if(!key_use_timer){
141                 if(KEY_TIMER) key_use_timer=1;
142                 if(key_state&KEY_STATE_REPEAT) return 0;
143         }else{
144                 if((long)(KEY_TIMER-key_time)<0) return 0;
145         }
146         
147         if(key_state==KEY_STATE_PUSH) {
148                 key_down_arr[i]|=1<<j;
149                 kbd_scan2mod(key_last_changed);
150                 key_state=KEY_STATE_REPEAT;
151                 key_time=KEY_TIMER+KEY_REPFIRST_T;
152                 key_hit=1;
153                 return key_last_changed;
154         } else if(key_state==KEY_STATE_REPEAT) {
155                 key_time=KEY_TIMER+KEY_REPNEXT_T;
156                 key_hit=1;
157                 return key_last_changed;
158         } else if(key_state==KEY_STATE_RELEASE) {
159                 key_down_arr[i]&=~(1<<j);
160                 kbd_scan2mod(key_last_changed);
161                 key_state=KEY_STATE_IDLE;
162                 key_hit=2;
163                 return key_last_changed;
164         } 
165         key_state=KEY_STATE_IDLE;
166         return 0;
167 }
168
169 /**
170  * kbd_scan2key - Converts scancode to kbd_key_t keyboard values
171  * @scan:       Detected scancode
172  *
173  * Computes kbd_key_t value for detected scancode.
174  * Uses @kbd_scan2key_tab transformation table
175  * and @key_mod modifiers information.
176  */
177 kbd_key_t kbd_scan2key(int scan)
178 {
179         if((key_mod&KBDMOD_SGM_SC)&&kbd_scan2key_tab[scan].sc)
180                 return kbd_scan2key_tab[scan].sc;
181         return kbd_scan2key_tab[scan].bc;
182 }
183