source: trunk/platform/ixus870_sd880/kbd.c @ 1344

Revision 1344, 11.6 KB checked in by philmoz, 20 months ago (diff)

Implement the full shutter press without releasing half-press logic:
http://chdk.setepontos.com/index.php?topic=1444.0

  • 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];
15static long kbd_prev_state[3];
16static long kbd_mod_state[3];
17
18static long last_kbd_key = 0;
19static long alt_mode_key_mask = 0x00000800; // key_print
20static int usb_power=0;
21static int remote_key, remote_count;
22static int shoot_counter=0;
23extern void _platformsub_kbd_fetch_data(long*);
24
25#define DELAY_TIMEOUT 10000
26
27// each mask should be the xor of all key values in the corresponding group
28#define KEYS_MASK0 (0x00000000)
29#define KEYS_MASK1 (0x00000000)
30#define KEYS_MASK2 (0x00000FFF)
31
32#define NEW_SS (0x2000)
33
34// from sub_FF846198 (via aSdProtect (just above it))
35// LDR  R1, =dword_FFAD6F20     R1 = 0xFFAD6F20 = a
36// MOV  R3, #1                  R3 = 1
37// LDRB R2, [R1,#0x114]         R2 = a[0x114] = 0x51
38// LDRB R1, [R1,#0x114]         R1 = a[0x114] = 0x51
39// MOV  R2, R2,LSR#5            R2 = 0x51 >> 5 = 2 = SD_READONLY_REG
40// LDR  R0, [R0,R2,LSL#2]       R0 = R0[2] = b[2]
41// AND  R1, R1, #0x1F           R1 = 0x51 & 0x1F = 0x11
42// AND  R0, R0, R3,LSL R1       R0 = b[2] & (1 << 0x11)
43// MOV  R0, R0,LSR R1           R0 = (b[2] & (1 << 0x11)) >> 0x11
44// AND  R0, R0, #1              R0 = ((b[2] & (1 << 0x11)) >> 0x11) & 0x1
45// BX   LR                      return
46#define SD_READONLY_FLAG (0x20000)  // 1 << 0x11
47#define SD_READONLY_REG 2
48
49#define USB_MASK (0x40000)
50#define USB_REG 2               // idx in physw_status
51
52
53#ifndef MALLOCD_STACK
54static char kbd_stack[NEW_SS];
55#endif
56
57
58static KeyMap keymap[] = {
59        /* tiny bug: key order matters. see kbd_get_pressed_key()
60         * for example
61         * KEY_SHOOT_FULL and KEY_SHOOT_HALF overlap and the first has precedence
62         */
63
64        // (note: key is in group i if it changes a bit in physw_status[i])
65        // group, CHDK key      , mask
66        { 2, KEY_SHOOT_FULL     , 0x00000003 },
67    { 2, KEY_SHOOT_FULL_ONLY, 0x00000002 },
68        { 2, KEY_SHOOT_HALF     , 0x00000001 },
69
70        { 2, KEY_UP             , 0x00000080 },
71        { 2, KEY_DOWN           , 0x00000040 },
72        { 2, KEY_LEFT           , 0x00000010 },
73        { 2, KEY_RIGHT          , 0x00000020 },
74        { 2, KEY_SET            , 0x00000100 },
75        { 2, KEY_ZOOM_IN        , 0x00000004 },
76        { 2, KEY_ZOOM_OUT       , 0x00000008 },
77        { 2, KEY_MENU           , 0x00000400 },
78        { 2, KEY_DISPLAY        , 0x00000200 },
79        { 2, KEY_PRINT          , 0x00000800 },
80        { 0, 0, 0 }
81};
82
83
84long __attribute__((naked)) wrap_kbd_p1_f() ;
85
86void wait_until_remote_button_is_released(void)
87{
88
89long x[3];
90int count1;
91int count2;
92int tick,tick2,tick3;
93int nSW;
94int prev_usb_power,cur_usb_power;
95 // ------ add by Masuji SUTO (start) --------------
96    static int nMode;
97 // ------ add by Masuji SUTO (end)   --------------
98
99asm volatile ("STMFD SP!, {R0-R11,LR}\n"); // store R0-R11 and LR in stack
100debug_led(1);
101tick = get_tick_count();
102tick2 = tick;
103static long usb_physw[3];
104if (conf.synch_enable && conf.ricoh_ca1_mode && conf.remote_enable && (!shooting_get_drive_mode()|| ((shooting_get_drive_mode()==2) && state_shooting_progress != SHOOTING_PROGRESS_PROCESSING)))  // synch mode enable so wait for USB to disconnect
105  {
106// ------ add by Masuji SUTO (start) --------------
107        nMode=0;
108        usb_physw[USB_REG] = 0;                                             // makes sure USB bit is cleared.
109        _kbd_read_keys_r2(usb_physw);
110        if((usb_physw[USB_REG] & USB_MASK)==USB_MASK) nMode=1;
111// ------ add by Masuji SUTO (end)   --------------
112     if(conf.ricoh_ca1_mode && conf.remote_enable)
113     {
114        if(shooting_get_drive_mode()==1 && state_shooting_progress == SHOOTING_PROGRESS_PROCESSING){                    //continuous-shooting mode
115                if(conf.bracket_type>2){
116                        if(shoot_counter<2) shutter_int=3;
117                        shoot_counter--;
118                        }
119                else{
120                        prev_usb_power=0;
121                        nSW = 0;
122                        do
123                                {     
124                                usb_physw[USB_REG] = 0;                                             // makes sure USB bit is cleared.
125                                _kbd_read_keys_r2(usb_physw);
126                                cur_usb_power = (usb_physw[USB_REG] & USB_MASK)==USB_MASK;
127                                if(cur_usb_power){
128                                        if(!prev_usb_power){
129                                                tick2 = get_tick_count();
130                                                prev_usb_power=cur_usb_power;
131                                                }
132                                        else{
133                                                if((int)get_tick_count()-tick2>1000) {debug_led(0);}
134                                                }
135                                        }
136                                else{
137                                        if(prev_usb_power){
138                                                tick3 = (int)get_tick_count()-tick2;
139                                                if(nSW==10) {
140                                                        if(tick3>50) shutter_int=1;
141                                                        nSW=20;
142                                                        }
143                                                if(nSW==0 && tick3>0) {
144                                                        if(tick3<50) {
145                                                        nSW=10;
146                                                        }
147                                                else{
148                                                        if(tick3>1000) shutter_int=1;
149                                                                nSW=20;
150                                                        }
151                                                }
152                                                prev_usb_power=cur_usb_power;
153                                                }
154                                        }
155                                if((int)get_tick_count()-tick >= DELAY_TIMEOUT) {nSW=20;shutter_int=2;}
156                                }
157                         while(nSW<20);
158                         }
159                }               //continuous-shooting mode
160                else{           // normal mode
161                        shoot_counter=0;
162                        if(conf.bracket_type>2){
163                                shoot_counter=(conf.bracket_type-2)*2;
164                                }
165        do
166           {
167         //  _platformsub_kbd_fetch_data(x);
168           usb_physw[USB_REG] = 0;
169          _kbd_read_keys_r2(usb_physw);           
170           }
171
172// ------ modif by Masuji SUTO (start) --------------
173    while(((((usb_physw[USB_REG] & USB_MASK)!=USB_MASK) && (nMode==0)) || (((usb_physw[USB_REG] & USB_MASK)==USB_MASK) && (nMode==1))) && ((int)get_tick_count()-tick < DELAY_TIMEOUT));
174// ------ modif by Masuji SUTO (end)   --------------
175        }
176       } // ricoh ca-1 mode
177
178else
179
180       {
181         do
182          {
183         //  _platformsub_kbd_fetch_data(x);
184           usb_physw[USB_REG] = 0;
185          _kbd_read_keys_r2(usb_physw);           
186           }
187        while((usb_physw[USB_REG]&USB_MASK) &&  ((int)get_tick_count()-tick < DELAY_TIMEOUT));
188
189        }
190
191  } // synch enable
192
193
194if (conf.synch_delay_enable && conf.synch_delay_value>0)       // if delay is switched on and greater than 0
195  {
196    for (count1=0;count1<conf.synch_delay_value+(conf.synch_delay_coarse_value*1000);count1++) // wait delay_value * 0.1ms
197    {
198      for (count2=0;count2<1400;count2++)            // delay approx. 0.1ms
199        {
200        }
201     }
202  }
203
204debug_led(0);
205
206asm volatile ("LDMFD SP!, {R0-R11,LR}\n"); // restore R0-R11 and LR from stack
207}
208
209
210
211
212static void __attribute__((noinline)) mykbd_task_proceed()
213{
214  int i;
215        while (physw_run){
216                _SleepTask(10);
217               
218                if (wrap_kbd_p1_f() == 1){ // autorepeat ?
219                        _kbd_p2_f();
220                }
221        }
222}
223
224void __attribute__((naked,noinline)) mykbd_task()
225{
226    /* WARNING
227     * Stack pointer manipulation performed here!
228     * This means (but not limited to):
229     *  function arguments destroyed;
230     *  function CAN NOT return properly;
231     *  MUST NOT call or use stack variables before stack
232     *  is setup properly;
233     *
234     */
235
236        register int i;
237        register long *newstack;
238
239#ifndef MALLOCD_STACK
240        newstack = (void*)kbd_stack;
241#else
242        newstack = malloc(NEW_SS);
243#endif
244
245        for (i=0;i<NEW_SS/4;i++)
246                newstack[i]=0xdededede;
247
248        asm volatile (
249                "MOV    SP, %0"
250                :: "r"(((char*)newstack)+NEW_SS)
251                : "memory"
252        );
253
254        mykbd_task_proceed();
255
256        /* function can be modified to restore SP here...
257         */
258
259        _ExitTask();
260}
261
262
263long __attribute__((naked,noinline)) wrap_kbd_p1_f()
264{
265        // first three lines from kbd_p1_f plus a jump to the fourth
266        asm volatile(
267                "STMFD   SP!, {R1-R5,LR}\n"
268                "MOV     R4, #0\n"
269                "BL      my_kbd_read_keys\n"
270                "B       _kbd_p1_f_cont\n"
271        );
272        return 0; // shut up the compiler
273}
274
275volatile int jogdial_stopped=0;
276
277void my_kbd_read_keys()
278{
279        kbd_prev_state[0] = kbd_new_state[0];
280        kbd_prev_state[1] = kbd_new_state[1];
281        kbd_prev_state[2] = kbd_new_state[2];
282       
283        _platformsub_kbd_fetch_data(kbd_new_state);
284
285        if (kbd_process() == 0){
286                // leave it alone...
287          physw_status[0] = kbd_new_state[0];
288          physw_status[1] = kbd_new_state[1];
289          physw_status[2] = kbd_new_state[2];
290          physw_status[2] |= alt_mode_key_mask;
291          jogdial_stopped=0;
292
293        } else {
294                // override keys
295        physw_status[0] = (kbd_new_state[0] & (~KEYS_MASK0)) |
296                          (kbd_mod_state[0] & KEYS_MASK0);
297
298        physw_status[1] = (kbd_new_state[1] & (~KEYS_MASK1)) |
299                          (kbd_mod_state[1] & KEYS_MASK1);
300
301        physw_status[2] = (kbd_new_state[2] & (~KEYS_MASK2)) |
302                          (kbd_mod_state[2] & KEYS_MASK2);
303
304        if ((jogdial_stopped==0) && !state_kbd_script_run){ jogdial_stopped=1; get_jogdial_direction(); }
305        else if (jogdial_stopped && state_kbd_script_run) jogdial_stopped=0;
306
307        }
308       
309        _kbd_read_keys_r2(physw_status);
310
311        remote_key = (physw_status[USB_REG] & USB_MASK)==USB_MASK;
312                if (remote_key)
313                        remote_count += 1;
314                else if (remote_count) {
315                        usb_power = remote_count;
316                        remote_count = 0;
317                }
318        if (conf.remote_enable) {
319#if USB_REG == SD_READONLY_REG
320                physw_status[USB_REG] = physw_status[USB_REG] & ~(SD_READONLY_FLAG | USB_MASK);
321#else
322                physw_status[USB_REG] = physw_status[USB_REG] & ~USB_MASK;
323                physw_status[SD_READONLY_REG] = physw_status[SD_READONLY_REG] & ~SD_READONLY_FLAG;
324#endif
325        } else {
326                physw_status[SD_READONLY_REG] = physw_status[SD_READONLY_REG] & ~SD_READONLY_FLAG;
327        }
328
329}
330
331
332
333/****************/
334
335void kbd_set_alt_mode_key_mask(long key)
336{
337        int i;
338        for (i=0; keymap[i].hackkey; ++i) {
339                if (keymap[i].hackkey == key) {
340                        alt_mode_key_mask = keymap[i].canonkey;
341                        return;
342                }
343        }
344}
345
346
347void kbd_key_press(long key)
348{
349        int i;
350        for (i=0;keymap[i].hackkey;i++){
351                if (keymap[i].hackkey == key){
352                        kbd_mod_state[keymap[i].grp] &= ~keymap[i].canonkey;
353                        return;
354                }
355        }
356}
357
358void kbd_key_release(long key)
359{
360        int i;
361        for (i=0;keymap[i].hackkey;i++){
362                if (keymap[i].hackkey == key){
363                        kbd_mod_state[keymap[i].grp] |= keymap[i].canonkey;
364                        return;
365                }
366        }
367}
368
369void kbd_key_release_all()
370{
371        kbd_mod_state[0] |= KEYS_MASK0;
372        kbd_mod_state[1] |= KEYS_MASK1;
373        kbd_mod_state[2] |= KEYS_MASK2;
374}
375
376long kbd_is_key_pressed(long key)
377{
378        int i;
379        for (i=0;keymap[i].hackkey;i++){
380                if (keymap[i].hackkey == key){
381                        return ((kbd_new_state[keymap[i].grp] & keymap[i].canonkey) == 0) ? 1:0;
382                }
383        }
384        return 0;
385}
386
387long kbd_is_key_clicked(long key)
388{
389        int i;
390        for (i=0;keymap[i].hackkey;i++){
391                if (keymap[i].hackkey == key){
392                        return ((kbd_prev_state[keymap[i].grp] & keymap[i].canonkey) != 0) &&
393                               ((kbd_new_state[keymap[i].grp] & keymap[i].canonkey) == 0);
394                }
395        }
396        return 0;
397}
398
399long kbd_get_pressed_key()
400{
401        int i;
402        for (i=0;keymap[i].hackkey;i++){
403                if ((kbd_new_state[keymap[i].grp] & keymap[i].canonkey) == 0){
404                        return keymap[i].hackkey;
405                }
406        }
407        return 0;
408}
409
410long kbd_get_clicked_key()
411{
412        int i;
413        for (i=0;keymap[i].hackkey;i++){
414                if (((kbd_prev_state[keymap[i].grp] & keymap[i].canonkey) != 0) &&
415                    ((kbd_new_state[keymap[i].grp] & keymap[i].canonkey) == 0)) {
416                        return keymap[i].hackkey;
417                }
418        }
419        return 0;
420}
421
422
423void kbd_reset_autoclicked_key() {
424        last_kbd_key = 0;
425}
426
427long kbd_get_autoclicked_key() {
428        static long last_kbd_time = 0, press_count = 0;
429        register long key, t;
430       
431        key=kbd_get_clicked_key();
432        if (key) {
433                last_kbd_key = key;
434                press_count = 0;
435                last_kbd_time = get_tick_count();
436                return key;
437        } else {
438                if (last_kbd_key && kbd_is_key_pressed(last_kbd_key)) {
439                        t = get_tick_count();
440                        if (t-last_kbd_time>((press_count)?175:500)) {
441                                ++press_count;
442                                last_kbd_time = t;
443                                return last_kbd_key;
444                        } else {
445                                return 0;
446                        }
447                } else {
448                        last_kbd_key = 0;
449                        return 0;
450                }
451        }
452}
453
454
455int get_usb_power(int edge)
456{
457        int x;
458
459        if (edge) return remote_key;
460        x = usb_power;
461        usb_power = 0;
462        return x;
463}
464
465long kbd_use_zoom_as_mf() {
466 return 0;
467}
468
469static int new_jogdial=0, old_jogdial=0;
470
471int Get_JogDial(void){
472 // address from sub above aJogdail (sub_FF84B8D8)
473 return (*(int*)0xC0240104)>>16;
474}
475
476long get_jogdial_direction(void) {
477 // XXX this seems to have a overflow bug: old=MIN_INT, new = old-1 = MAX_INT  ->  old-1 < old < new = old - 1
478 // not likely to happen though (very long runs with a bias for tuning one direction; bias is probably to the right due to menus)
479 old_jogdial=new_jogdial;
480 new_jogdial=Get_JogDial();
481 if (old_jogdial<new_jogdial) return JOGDIAL_RIGHT;
482 else if (old_jogdial>new_jogdial) return JOGDIAL_LEFT;
483 else return 0;
484}
Note: See TracBrowser for help on using the repository browser.