source: trunk/platform/sx220hs/kbd.c @ 1790

Revision 1790, 10.0 KB checked in by philmoz, 15 months ago (diff)

Fix for SX220 movie record crash from funnel.
http://chdk.setepontos.com/index.php?topic=650.msg83729#msg83729

  • Property svn:eol-style set to native
Line 
1#include "lolevel.h"
2#include "platform.h"
3#include "core.h"
4#include "keyboard.h"
5#include "conf.h"
6
7typedef struct {
8    short grp;
9    short hackkey;
10    long canonkey;
11} KeyMap;
12
13long kbd_new_state[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
14static long kbd_prev_state[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
15static long kbd_mod_state[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
16
17static KeyMap keymap[];
18static long last_kbd_key = 0;
19static int alt_mode_led=0;
20extern void _GetKbdState(long*);
21
22// override key and feather bits to avoid feather osd messing up chdk display in ALT mode
23#define KEYS_MASK0 (0x000FFC0F)     // sx220 physw_status[0]
24#define KEYS_MASK1 (0x00200000)
25#define KEYS_MASK2 (0x00002182)         // sx220 physw_status[2]
26
27#define NEW_SS (0x2000)
28#define SD_READONLY_FLAG (0x20000)
29#define SD_READONLY_IDX     2         
30#define USB_IDX             2
31
32#define USB_MASK (0x4000000)
33#define USB_IDX  2
34
35extern void usb_remote_key( int ) ;
36int get_usb_bit()
37{
38        long usb_physw[3];
39        usb_physw[USB_IDX] = 0;
40        _kbd_read_keys_r2(usb_physw);
41        return(( usb_physw[USB_IDX] & USB_MASK)==USB_MASK) ;
42}
43
44#ifndef MALLOCD_STACK
45static char kbd_stack[NEW_SS];
46#endif
47
48static KeyMap keymap[] = {
49
50    /* tiny bug: key order matters. see kbd_get_pressed_key()
51    * for example*/
52
53    { 0, KEY_ZOOM_OUT        , 0x00000001 },
54    { 0, KEY_ZOOM_OUT1       , 0x00000001 },
55    { 0, KEY_ZOOM_OUT        , 0x00000002 },
56    { 0, KEY_ZOOM_OUT3       , 0x00000002 },
57    { 0, KEY_ZOOM_OUT        , 0x00000003 },
58    { 0, KEY_ZOOM_OUT2       , 0x00000003 },
59    { 0, KEY_ZOOM_IN         , 0x00000004 },
60    { 0, KEY_ZOOM_IN1        , 0x00000004 },
61    { 0, KEY_ZOOM_IN         , 0x00000008 },
62    { 0, KEY_ZOOM_IN3        , 0x00000008 },
63    { 0, KEY_ZOOM_IN         , 0x0000000C },
64    { 0, KEY_ZOOM_IN2        , 0x0000000C },
65    { 0, KEY_DISPLAY         , 0x00000800 },
66    { 0, KEY_UP              , 0x00001000 },
67    { 0, KEY_RIGHT           , 0x00006000 },
68    { 0, KEY_SET             , 0x00010000 },
69    { 0, KEY_DOWN            , 0x00020000 },
70    { 0, KEY_MENU            , 0x00040000 },
71    { 0, KEY_VIDEO           , 0x00080000 },
72 //   { 0, KEY_RIGHT_SOFT      , 0x00002000 },  //soft keys commented out but still counted in the keymasks, seems to disable them like we want.
73 //   { 0, KEY_UP_SOFT         , 0x00000400 },  //if enabled can cause unintentional button presses in alt menu when rotating the jogdial really fast.
74 //   { 0, KEY_DOWN_SOFT       , 0x00008000 },
75
76    { 1, KEY_PRINT           , 0x00200000 }, // playback = alt button
77    { 1, KEY_PLAYBACK        , 0x00200000 },
78
79 //   { 2, KEY_LEFT_SOFT       , 0x00000080 },
80    { 2, KEY_LEFT            , 0x00000100 },
81    { 2, KEY_SHOOT_FULL      , 0x00002002 },
82    { 2, KEY_SHOOT_FULL_ONLY , 0x00000002 },
83    { 2, KEY_SHOOT_HALF      , 0x00002000 },
84
85    { 0, 0, 0 }
86};
87
88// NOP
89void kbd_set_alt_mode_key_mask(long key)
90{
91}
92
93void my_blinkk(void) {
94        int i;
95        while(1) {
96                *((volatile int *) 0xC0220130) = 0x46; // Turn on LED
97                for (i=0; i<0x200000; i++) { asm volatile ( "nop\n" ); }
98
99                *((volatile int *) 0xC0220130) = 0x44; // Turn off LED
100                for (i=0; i<0x200000; i++) { asm volatile ( "nop\n" ); }
101
102                *((volatile int *) 0xC0220130) = 0x46; // Turn on LED
103                for (i=0; i<0x200000; i++) { asm volatile ( "nop\n" ); }
104
105                *((volatile int *) 0xC0220130) = 0x44; // Turn off LED
106                for (i=0; i<0x900000; i++) { asm volatile ( "nop\n" ); }
107        }
108}
109
110// Set to 1 to disable jogdial events from being processed in firmware
111volatile int jogdial_stopped=0;
112
113long __attribute__((naked)) wrap_kbd_p1_f();
114
115static void __attribute__((noinline)) mykbd_task_proceed() {
116    while (physw_run) {
117        _SleepTask(*((int*)(0x1c40+0x8)));//10); @FF0244F4
118               
119                if (wrap_kbd_p1_f() == 1) {   // autorepeat ?
120                _kbd_p2_f();
121        }
122    }
123}
124
125// no stack manipulation needed here, since we create the task directly
126void __attribute__((naked,noinline)) mykbd_task() {
127
128        mykbd_task_proceed();
129
130// function can be modified to restore SP here...
131
132        _ExitTask();
133}
134
135//
136long __attribute__((naked,noinline)) wrap_kbd_p1_f() {
137    asm volatile(
138                "STMFD   SP!, {R1-R7,LR}\n"       //SX220 modified
139                "MOV     R5, #0\n"                                     
140            //    "BL      _kbd_read_keys\n"       // replaces kbd_fetch_data()
141                "BL      my_kbd_read_keys\n"     // +
142                "B       _kbd_p1_f_cont\n"       // continue
143    );
144       
145        return 0;   // shut up the compiler
146}
147
148// copied from g12 and sx30, thx to philmoz
149// Pointer to stack location where jogdial task records previous and current
150// jogdial positions
151extern short* jog_position;
152
153void jogdial_control(int n)
154{
155    if (jogdial_stopped && !n)
156    {
157        // If re-enabling jogdial set the task code current & previous positions to the actual
158        // dial positions so that the change won't get processed by the firmware
159        jog_position[0] = jog_position[2] = (*(short*)0xC0240106);  // Rear dial
160    }
161    jogdial_stopped = n;
162}
163
164// like SX30 and g12
165void my_kbd_read_keys() {
166       
167    kbd_prev_state[0] = kbd_new_state[0];
168        kbd_prev_state[1] = kbd_new_state[1];
169    kbd_prev_state[2] = kbd_new_state[2];
170
171        _GetKbdState(kbd_new_state);
172        _kbd_read_keys_r2(kbd_new_state);
173       
174
175    if (kbd_process() == 0) {
176        // we read keyboard state with _kbd_read_keys()
177                  physw_status[0] = kbd_new_state[0];
178                  physw_status[1] = kbd_new_state[1];
179          physw_status[2] = kbd_new_state[2];
180                 jogdial_control(0);
181    } else {
182        // override keys
183        physw_status[0] = (kbd_new_state[0] | KEYS_MASK0) & (~KEYS_MASK0 | kbd_mod_state[0]);
184                physw_status[1] = (kbd_new_state[1] | KEYS_MASK1) & (~KEYS_MASK1 | kbd_mod_state[1]);
185        physw_status[2] = (kbd_new_state[2] | KEYS_MASK2) & (~KEYS_MASK2 | kbd_mod_state[2]);
186       
187                if ((jogdial_stopped==0) && !state_kbd_script_run) {
188            jogdial_control(1);
189            get_jogdial_direction();
190        }
191        else if (jogdial_stopped && state_kbd_script_run)
192            jogdial_control(0);
193    }
194
195        usb_remote_key(physw_status[USB_IDX]) ;
196
197        if (conf.remote_enable) {
198                physw_status[USB_IDX] = physw_status[USB_IDX] & ~(SD_READONLY_FLAG | USB_MASK);
199        } else {
200                physw_status[USB_IDX] = physw_status[USB_IDX] & ~SD_READONLY_FLAG;
201        }
202
203}
204
205void kbd_key_press(long key) {
206    int i;
207    for (i=0;keymap[i].hackkey;i++){
208        if (keymap[i].hackkey == key){
209            kbd_mod_state[keymap[i].grp] &= ~keymap[i].canonkey;
210            return;
211        }
212    }
213}
214
215void kbd_key_release(long key) {
216    int i;
217    for (i=0;keymap[i].hackkey;i++) {
218        if (keymap[i].hackkey == key){
219            kbd_mod_state[keymap[i].grp] |= keymap[i].canonkey;
220            return;
221        }
222    }
223}
224
225void kbd_key_release_all() {
226       
227        kbd_mod_state[0] |= KEYS_MASK0;
228    kbd_mod_state[1] |= KEYS_MASK1;
229    kbd_mod_state[2] |= KEYS_MASK2;
230
231}
232
233long kbd_is_key_pressed(long key) {
234    int i;
235    for (i=0;keymap[i].hackkey;i++) {
236        if (keymap[i].hackkey == key) {
237            return ((kbd_new_state[keymap[i].grp] & keymap[i].canonkey) == 0) ? 1:0;
238        }
239    }
240    return 0;
241}
242
243long kbd_is_key_clicked(long key) {
244    int i;
245    for (i=0;keymap[i].hackkey;i++) {
246        if (keymap[i].hackkey == key){
247            return ((kbd_prev_state[keymap[i].grp] & keymap[i].canonkey) != 0) &&
248                ((kbd_new_state[keymap[i].grp] & keymap[i].canonkey) == 0);
249        }
250    }
251    return 0;
252}
253
254long kbd_get_pressed_key() {
255    int i;
256    for (i=0;keymap[i].hackkey;i++) {
257        if ((kbd_new_state[keymap[i].grp] & keymap[i].canonkey) == 0) {
258            return keymap[i].hackkey;
259        }
260    }
261       
262    return 0;
263}
264
265long kbd_get_clicked_key() {
266    int i;
267    for (i=0;keymap[i].hackkey;i++) {
268        if (((kbd_prev_state[keymap[i].grp] & keymap[i].canonkey) != 0) && ((kbd_new_state[keymap[i].grp] & keymap[i].canonkey) == 0)) {
269            return keymap[i].hackkey;
270        }
271    }
272    return 0;
273}
274
275void kbd_reset_autoclicked_key() {
276    last_kbd_key = 0;
277}
278
279long kbd_get_autoclicked_key() {
280    static long last_kbd_time = 0, press_count = 0;
281    register long key, t;
282
283    key=kbd_get_clicked_key();
284    if (key) {
285        last_kbd_key = key;
286        press_count = 0;
287        last_kbd_time = get_tick_count();
288        return key;
289    } else {
290        if (last_kbd_key && kbd_is_key_pressed(last_kbd_key)) {
291            t = get_tick_count();
292            if (t-last_kbd_time>((press_count)?175:500)) {
293                ++press_count;
294                last_kbd_time = t;
295                return last_kbd_key;
296            } else {
297                return 0;
298            }
299        } else {
300            last_kbd_key = 0;
301            return 0;
302        }
303    }
304}
305
306
307#ifdef CAM_USE_ZOOM_FOR_MF
308    long kbd_use_zoom_as_mf() {
309
310        static long v;
311        static long zoom_key_pressed = 0;
312
313        if (kbd_is_key_pressed(KEY_ZOOM_IN) && (mode_get()&MODE_MASK) == MODE_REC) {
314            get_property_case(PROPCASE_FOCUS_MODE, &v, 4);
315            if (v) {
316                kbd_key_release_all();
317                kbd_key_press(KEY_RIGHT);
318                zoom_key_pressed = KEY_ZOOM_IN;
319                return 1;
320            }
321        } else {
322            if (zoom_key_pressed==KEY_ZOOM_IN) {
323                kbd_key_release(KEY_RIGHT);
324                zoom_key_pressed = 0;
325                return 1;
326            }
327        }
328        if (kbd_is_key_pressed(KEY_ZOOM_OUT) && (mode_get()&MODE_MASK) == MODE_REC) {
329            get_property_case(PROPCASE_FOCUS_MODE, &v, 4);
330            if (v) {
331                kbd_key_release_all();
332                kbd_key_press(KEY_LEFT);
333                zoom_key_pressed = KEY_ZOOM_OUT;
334                return 1;
335            }
336        } else {
337            if (zoom_key_pressed==KEY_ZOOM_OUT) {
338                kbd_key_release(KEY_LEFT);
339                zoom_key_pressed = 0;
340                return 1;
341            }
342        }
343        return 0;
344    }
345#endif
346
347int Get_JogDial(void) {
348    return (*(int*)0xC0240104)>>16;     // 0xC0240000 + 0x104
349}
350
351static int new_jogdial=0, old_jogdial=0;
352
353long get_jogdial_direction(void) {
354    old_jogdial=new_jogdial;
355    new_jogdial=Get_JogDial();
356
357    if (old_jogdial<new_jogdial) {
358        return JOGDIAL_RIGHT;
359    } else if (old_jogdial>new_jogdial) {
360        return JOGDIAL_LEFT;
361    } else {
362        return 0;
363    }
364}
Note: See TracBrowser for help on using the repository browser.