source: trunk/platform/a495/kbd.c @ 1605

Revision 1605, 6.4 KB checked in by philmoz, 16 months ago (diff)

Merged revision(s) 1604 from branches/release-1_0:
Fix for inverted key logic and initialisation for A495 (thx srsa_4c).
Also applied to A490 which has the same key logic.
http://chdk.setepontos.com/index.php?topic=650.msg80363#msg80363

  • Property svn:eol-style set to native
Line 
1#include "lolevel.h"
2#include "platform.h"
3#include "core.h"
4#include "conf.h"
5#include "keyboard.h"
6
7typedef struct {
8    short grp;
9    short hackkey;
10    long canonkey;
11} KeyMap;
12
13
14static long kbd_new_state[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
15static long kbd_prev_state[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
16static long kbd_mod_state[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
17
18static long last_kbd_key = 0;
19
20extern void _platformsub_kbd_fetch_data(long*);
21
22#define KEYS_MASK0 (0x00020000)
23#define KEYS_MASK1 (0x00000000)
24#define KEYS_MASK2 (0x017001f4)
25#define KEYS_INV2 (0x01700000)
26/*
27the 4 button states residing in the upper half of physw_status[2] seem to be inverted
28to handle these correctly, their value needs to be inverted:
29- when reading from physw_status[2] to the state variables
30- when writing to physw_status[2] from the state variables
31KEYS_INV2 should be used for that
32SD_READONLY_FLAG and USB_MASK are not affected by this
33
34when idle, physw_status[2] looks like: "000001000000000xxxxx000111110100"
35                         KEYS_MASK2 is "00000001011100000000000111110100"
36*/
37
38#define SD_READONLY_FLAG (0x40000)
39#define USB_MASK (0x80000)
40#define USB_IDX 2
41
42extern void usb_remote_key( int ) ;
43int get_usb_bit()
44{
45        long usb_physw[3];
46        usb_physw[USB_IDX] = 0;
47        _kbd_read_keys_r2(usb_physw);
48        return(( usb_physw[USB_IDX] & USB_MASK)==USB_MASK) ;
49}
50
51static KeyMap keymap[] = {
52    /* tiny bug: key order matters. see kbd_get_pressed_key()
53    * for example
54    */
55
56    //{ 0, KEY_DISPLAY  , 0x00020000 }, // Playback
57    { 0, KEY_PRINT      , 0x00020000 }, // Playback
58
59    { 2, KEY_SHOOT_FULL , 0x00000030 }, // 0x00000010 (KEY_SHOOT_HALF) + 0x00000020 (KEY_SHOOT_FULL_ONLY)
60    { 2, KEY_SHOOT_FULL_ONLY, 0x00000020 },
61    { 2, KEY_SHOOT_HALF , 0x00000010 },
62   
63    { 2, KEY_UP         , 0x00100000 },
64    { 2, KEY_DOWN       , 0x00200000 },
65    { 2, KEY_LEFT       , 0x00400000 },
66    { 2, KEY_RIGHT      , 0x00000004 },
67    { 2, KEY_SET        , 0x00000100 },
68    { 2, KEY_ZOOM_IN    , 0x00000080 },
69    { 2, KEY_ZOOM_OUT   , 0x00000040 },
70    { 2, KEY_MENU       , 0x01000000 },
71    { 0, 0, 0 }
72};
73
74
75long __attribute__((naked)) wrap_kbd_p1_f() ;
76
77
78static void __attribute__((noinline)) mykbd_task_proceed()
79{
80        /* Initialize our own kbd_new_state[] array with the
81           current physical status. (inspired by the S90 port)
82           */
83        kbd_new_state[0] = physw_status[0];
84        kbd_new_state[1] = physw_status[1];
85        kbd_new_state[2] = physw_status[2] ^ KEYS_INV2;
86        while (physw_run){
87                _SleepTask(10);
88               
89                if (wrap_kbd_p1_f() == 1){ // autorepeat ?
90                        _kbd_p2_f();
91                }
92        }
93}
94
95void __attribute__((naked,noinline)) mykbd_task()
96{
97        mykbd_task_proceed();
98        _ExitTask();
99}
100
101
102long __attribute__((naked,noinline)) wrap_kbd_p1_f()
103{
104        asm volatile(
105                        "STMFD   SP!, {R1-R5,LR}\n"
106                        "MOV     R4, #0\n"
107                        //"BL      _kbd_read_keys\n"       // replaces kbd_fetch_data()
108                        "BL      my_kbd_read_keys\n"     // +
109                        "B       _kbd_p1_f_cont\n"       // continue
110        );
111       
112        return 0; // shut up the compiler
113}
114
115
116void my_kbd_read_keys()
117{
118        // If script are running, replace PRINT button with DISPLAY
119        if (state_kbd_script_run) {
120                int i;
121                for (i=0; keymap[i].hackkey; i++) {
122                        if (keymap[i].hackkey == KEY_PRINT) {
123                                keymap[i].hackkey = KEY_DISPLAY;
124                                break;
125                        }
126                }
127        } else {
128                int i;
129                for (i=0; keymap[i].hackkey; i++) {
130                        if (keymap[i].hackkey == KEY_DISPLAY) {
131                                keymap[i].hackkey = KEY_PRINT;
132                                break;
133                        }
134                }
135        }
136       
137        kbd_prev_state[0] = kbd_new_state[0];
138        //kbd_prev_state[1] = kbd_new_state[1];
139        kbd_prev_state[2] = kbd_new_state[2];
140       
141        asm volatile(
142        "BL      _kbd_read_keys\n"
143        );
144       
145        //_platformsub_kbd_fetch_data(kbd_new_state);
146        kbd_new_state[0] = physw_status[0];
147        kbd_new_state[1] = physw_status[1];
148        kbd_new_state[2] = physw_status[2] ^ KEYS_INV2;
149       
150        if (kbd_process() == 0){
151                // leave it alone...
152        } else {
153        // override keys
154        physw_status[0] = (kbd_new_state[0] | KEYS_MASK0) & (~KEYS_MASK0 | kbd_mod_state[0]);
155        //physw_status[1] = (kbd_new_state[1] | KEYS_MASK1) & (~KEYS_MASK1 | kbd_mod_state[1]);
156        physw_status[2] = ((kbd_new_state[2] | KEYS_MASK2) & (~KEYS_MASK2 | kbd_mod_state[2])) ^ KEYS_INV2;
157        }
158       
159        //_kbd_read_keys_r2(physw_status);
160
161        usb_remote_key(physw_status[USB_IDX]) ;
162       
163        if (conf.remote_enable) {
164                physw_status[USB_IDX] = physw_status[USB_IDX] & ~(SD_READONLY_FLAG | USB_MASK);
165        } else {
166                physw_status[USB_IDX] = physw_status[USB_IDX] & ~SD_READONLY_FLAG;
167        }
168}
169
170
171
172
173/****************/
174
175void kbd_key_press(long key)
176{
177        int i;
178        for (i=0;keymap[i].hackkey;i++){
179                if (keymap[i].hackkey == key){
180                        kbd_mod_state[keymap[i].grp] &= ~keymap[i].canonkey;
181                        return;
182                }
183        }
184}
185
186void kbd_key_release(long key)
187{
188        int i;
189        for (i=0;keymap[i].hackkey;i++){
190                if (keymap[i].hackkey == key){
191                        kbd_mod_state[keymap[i].grp] |= keymap[i].canonkey;
192                        return;
193                }
194        }
195}
196
197void kbd_key_release_all()
198{
199        kbd_mod_state[0] |= KEYS_MASK0;
200        kbd_mod_state[1] |= KEYS_MASK1;
201        kbd_mod_state[2] |= KEYS_MASK2;
202}
203
204long kbd_is_key_pressed(long key)
205{
206        int i;
207        for (i=0;keymap[i].hackkey;i++){
208                if (keymap[i].hackkey == key){
209                        return ((kbd_new_state[keymap[i].grp] & keymap[i].canonkey) == 0) ? 1:0;
210                }
211        }
212        return 0;
213}
214
215long kbd_is_key_clicked(long key)
216{
217        int i;
218        for (i=0;keymap[i].hackkey;i++){
219                if (keymap[i].hackkey == key){
220                        return ((kbd_prev_state[keymap[i].grp] & keymap[i].canonkey) != 0) &&
221                                   ((kbd_new_state[keymap[i].grp] & keymap[i].canonkey) == 0);
222                }
223        }
224        return 0;
225}
226
227long kbd_get_pressed_key()
228{
229        int i;
230        for (i=0;keymap[i].hackkey;i++){
231                if (kbd_is_key_pressed(keymap[i].hackkey)) {
232                        return keymap[i].hackkey;
233                }
234        }
235        return 0;
236}
237
238long kbd_get_clicked_key()
239{
240        int i;
241        for (i=0;keymap[i].hackkey;i++){
242                if (((kbd_prev_state[keymap[i].grp] & keymap[i].canonkey) != 0) &&
243                        ((kbd_new_state[keymap[i].grp] & keymap[i].canonkey) == 0)) {
244                        return keymap[i].hackkey;
245                }
246        }
247        return 0;
248}
249
250
251void kbd_reset_autoclicked_key() {
252        last_kbd_key = 0;
253}
254
255long kbd_get_autoclicked_key() {
256        static long last_kbd_time = 0, press_count = 0;
257        register long key, t;
258       
259        key=kbd_get_clicked_key();
260        if (key) {
261                last_kbd_key = key;
262                press_count = 0;
263                last_kbd_time = get_tick_count();
264                return key;
265        } else {
266                if (last_kbd_key && kbd_is_key_pressed(last_kbd_key)) {
267                        t = get_tick_count();
268                        if (t-last_kbd_time>((press_count)?175:500)) {
269                                ++press_count;
270                                last_kbd_time = t;
271                                return last_kbd_key;
272                        } else {
273                                return 0;
274                        }
275                } else {
276                        last_kbd_key = 0;
277                        return 0;
278                }
279        }
280}
281
282
283long kbd_use_zoom_as_mf() {
284        return 0;
285}
Note: See TracBrowser for help on using the repository browser.