root/platform/ixus310_elph500hs/kbd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. simulate_playback_press
  2. simulate_power_press
  3. is_button_displayed
  4. is_button_active
  5. show_virtual_buttons
  6. chdk_process_touch
  7. draw_test_pixel
  8. virtual_buttons
  9. ts_process_touch
  10. get_usb_bit
  11. kbd_fetch_data
  12. my_kbd_read_keys
  13. wrap_kbd_p1_f
  14. mykbd_task

   1 #include "lolevel.h"
   2 #include "platform.h"
   3 #include "core.h"
   4 #include "conf.h"
   5 #include "kbd_common.h"
   6 #include "touchscreen.h"
   7 #include "levent.h"
   8 #include "gui.h"
   9 #include "gui_draw.h"
  10 #include "gui_osd.h"
  11 #include "font.h"
  12 
  13 // Uncomment this line to enable 'PLAY' and 'OFF' buttons in the CHDK OSD 
  14 // Can be used to switch in/out of playback mode and power off the camera 
  15 // (For 'nekut' whose camera has a broken playback button - http://chdk.setepontos.com/index.php?topic=6634.msg75039#msg75039) 
  16 //#define   TS_PLAY_POWER_HACK  1 
  17 
  18 long kbd_new_state[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
  19 long kbd_prev_state[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
  20 long kbd_mod_state[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
  21 static long touch_panel_state;
  22 
  23 extern void _GetKbdState(long*);
  24 
  25 //void my_blinkk(void) {
  26 //      int i;
  27 ////    while(1) {
  28 //              *((volatile int *) 0xC0220134) = 0x46; // Turn on LED
  29 //              for (i=0; i<0x200000; i++) { asm volatile ( "nop\n" ); }
  30 //
  31 //              *((volatile int *) 0xC0220134) = 0x44; // Turn off LED
  32 //              for (i=0; i<0x200000; i++) { asm volatile ( "nop\n" ); }
  33 //
  34 //              *((volatile int *) 0xC0220134) = 0x46; // Turn on LED
  35 //              for (i=0; i<0x200000; i++) { asm volatile ( "nop\n" ); }
  36 //
  37 //              *((volatile int *) 0xC0220134) = 0x44; // Turn off LED
  38 //              for (i=0; i<0x900000; i++) { asm volatile ( "nop\n" ); }
  39 ////    }
  40 //}
  41 
  42 #define TS_KEY_TOGGLE_RAW   200
  43 #define TS_KEY_TOGGLE_ZEBRA 201
  44 #define TS_KEY_TOGGLE_HISTO 202
  45 #define TS_KEY_TOGGLE_OSD   203
  46 #define TS_KEY_TOGGLE_OVRD  204
  47 #define TS_KEY_TOGGLE_EDGE  205
  48 #define TS_KEY_PLAYBACK     214 
  49 #define TS_KEY_POWER        215 
  50 
  51 #define TS_XL       0
  52 #define TS_XR       422
  53 #define TS_W        58
  54 #define TS_YT       0
  55 #define TS_H        48
  56 #define LB(x,n,s)   TS_XL+x*TS_W, TS_YT+n*TS_H, TS_XL+(x+1)*TS_W-1, TS_YT+n*TS_H+TS_H-1, s
  57 #define RB(x,n,s)   TS_XR-x*TS_W, TS_YT+n*TS_H, TS_XR-(x-1)*TS_W-1, TS_YT+n*TS_H+TS_H-1, s
  58 
  59 extern const char* gui_on_off_enum(int change, int arg);
  60 extern const char* gui_histo_show_enum(int change, int arg);
  61 extern const char* gui_override_disable_enum(int change, int arg);
  62 
  63 #define MODE_VID    0x400
  64 
  65 #if defined(TS_PLAY_POWER_HACK) 
  66 static int playbutton_hack; 
  67 static const char* simulate_playback_press(int change, int arg) 
  68 { 
  69     void levent_set_play(void); 
  70     if (change) levent_set_play(); 
  71     return 0; 
  72 } 
  73  
  74 static const char* simulate_power_press(int change, int arg) 
  75 { 
  76     void camera_shutdown_in_a_second(void); 
  77     if (change) camera_shutdown_in_a_second(); 
  78     return 0; 
  79 } 
  80 #endif
  81 
  82 KeyMap keymap[] = {
  83 
  84 //  { 1, TOUCH_SCREEN       , 0x00000008, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Touch screen panel
  85     { 1, KEY_ZOOM_IN        , 0x00001000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Found @0xff3d144c, levent 0x02
  86     { 1, KEY_ZOOM_OUT       , 0x00008000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Found @0xff3d1454, levent 0x03
  87     { 2, KEY_SHOOT_FULL     , 0x00000a00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Found @0xff3d146c, levent 0x01
  88     { 2, KEY_SHOOT_FULL_ONLY, 0x00000800, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },   // http://chdk.setepontos.com/index.php?topic=1444.msg70223#msg70223
  89     { 2, KEY_SHOOT_HALF     , 0x00000200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Found @0xff3d1464, levent 0x00
  90     { 2, KEY_POWER           ,0x00001000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Found @0xff3d1474, levent 0x600
  91     { 2, KEY_PLAYBACK        ,0x00004000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Found @0xff3d147c, levent 0x601
  92 
  93     { 3, KEY_PRINT          , 0x00000001, LB(0,1,1), 0, "CHDK",  0,    GUI_MODE_NONE,      100, MODE_REC|MODE_PLAY|MODE_VID, 0, 0, 0 }, // virtual touch screen key
  94 
  95     { 3, KEY_MENU                   , 0x00000002, LB(0,2,1), 0, "Menu",  0, GUI_MODE_ALT, 100, MODE_REC|MODE_PLAY|MODE_VID, 0, 0, 0 },
  96         { 3, KEY_SET                , 0x00000004, LB(0,3,1), 0, "Set",   0, GUI_MODE_ALT, 100, MODE_REC|MODE_PLAY|MODE_VID, 0, 0, 0 },
  97 
  98     { 3, TS_KEY_TOGGLE_RAW  , 0x00000100, RB(1,1,1), 1, "RAW",   0, GUI_MODE_ALT, GUI_MODE_ALT, MODE_REC|MODE_PLAY, &conf.save_raw, gui_on_off_enum, &conf.touchscreen_disable_shortcut_controls },
  99     { 3, TS_KEY_TOGGLE_OSD  , 0x00000200, RB(1,2,1), 1, "OSD",   0, GUI_MODE_ALT, GUI_MODE_ALT, MODE_REC|MODE_PLAY, &conf.show_osd, gui_on_off_enum, &conf.touchscreen_disable_shortcut_controls },
 100     { 3, TS_KEY_TOGGLE_OVRD , 0x00000400, RB(1,3,1), 1, "OvrDis",0, GUI_MODE_ALT, GUI_MODE_ALT, MODE_REC|MODE_PLAY, &conf.override_disable, gui_override_disable_enum, &conf.touchscreen_disable_shortcut_controls },
 101     { 3, TS_KEY_TOGGLE_ZEBRA, 0x00000800, RB(2,1,1), 1, "Zebra", 0, GUI_MODE_ALT, GUI_MODE_ALT, MODE_REC|MODE_PLAY, &conf.zebra_draw, gui_on_off_enum, &conf.touchscreen_disable_shortcut_controls },
 102     { 3, TS_KEY_TOGGLE_HISTO, 0x00001000, RB(2,2,1), 1, "Hist",  0, GUI_MODE_ALT, GUI_MODE_ALT, MODE_REC|MODE_PLAY, &conf.show_histo, gui_histo_show_enum, &conf.touchscreen_disable_shortcut_controls },
 103     { 3, TS_KEY_TOGGLE_EDGE , 0x00002000, RB(2,3,1), 1, "Edge",  0, GUI_MODE_ALT, GUI_MODE_ALT, MODE_REC|MODE_PLAY, &conf.edge_overlay_enable, gui_on_off_enum, &conf.touchscreen_disable_shortcut_controls },
 104 
 105 #if defined(TS_PLAY_POWER_HACK) 
 106     { 3, TS_KEY_PLAYBACK    , 0x00400000, LB(1,0,1), 0, "PLAY",  0,    GUI_MODE_ALT,       GUI_MODE_ALT,  MODE_REC|MODE_PLAY, &playbutton_hack, simulate_playback_press, 0 },
 107     { 3, TS_KEY_POWER       , 0x00800000, LB(3,0,1), 0, "OFF",   0,    GUI_MODE_ALT,       GUI_MODE_ALT,  MODE_REC|MODE_PLAY, &playbutton_hack, simulate_power_press, 0 },
 108 #endif
 109 #ifdef OPT_DEBUGGING
 110     { 3, KEY_DISPLAY        , 0x00000008, LB(0,4,1), 0, "Debug", 0,    GUI_MODE_ALT,       GUI_MODE_ALT,  MODE_REC|MODE_PLAY, 0, 0, 0 },
 111 #endif
 112     { 3, KEY_DISPLAY        , 0x00000008, LB(0,4,1), 0, "Back",  0,    GUI_MODE_MENU,      GUI_MODE_MENU, MODE_REC|MODE_PLAY, 0, 0, 0 },
 113     { 3, KEY_DISPLAY        , 0x00000008, LB(0,4,1), 0, "Disp",  0,    GUI_MODE_MENU+1,    100,           MODE_REC|MODE_PLAY|MODE_VID, 0, 0, 0 },
 114     { 3, KEY_UP             , 0x00000010, RB(0,1,2), 0, "\x18",  0,    GUI_MODE_MENU,      100,           MODE_REC|MODE_PLAY|MODE_VID, 0, 0, 0 },
 115     { 3, KEY_LEFT           , 0x00000020, RB(0,2,2), 0, "\x1B",  0,    GUI_MODE_MENU,      100,           MODE_REC|MODE_PLAY|MODE_VID, 0, 0, 0 },
 116     { 3, KEY_RIGHT          , 0x00000040, RB(0,3,2), 0, "\x1A",  0,    GUI_MODE_MENU,      100,           MODE_REC|MODE_PLAY|MODE_VID, 0, 0, 0 },
 117     { 3, KEY_DOWN           , 0x00000080, RB(0,4,2), 0, "\x19",  0,    GUI_MODE_MENU,      100,           MODE_REC|MODE_PLAY|MODE_VID, 0, 0, 0 },
 118 
 119     { 3, KEY_UP                     , 0x00000010, RB(0,0,1), 0, "Man",   "Focus",  GUI_MODE_ALT, GUI_MODE_ALT, MODE_REC, &conf.subj_dist_override_koef, 0, &conf.touchscreen_disable_shortcut_controls },
 120     { 3, KEY_DISPLAY        , 0x00000008, RB(0,1,1), 0, "Max",   "Dist",   GUI_MODE_ALT, GUI_MODE_ALT, MODE_REC, 0, 0, &conf.touchscreen_disable_shortcut_controls },
 121     { 3, KEY_DOWN           , 0x00000080, RB(0,2,1), 0, "Hyper", "Dist",   GUI_MODE_ALT, GUI_MODE_ALT, MODE_REC, 0, 0, &conf.touchscreen_disable_shortcut_controls },
 122         { 3, KEY_LEFT               , 0x00000020, RB(0,3,1), 0, "- Foc.","Factor", GUI_MODE_ALT, GUI_MODE_ALT, MODE_REC, 0, 0, &conf.touchscreen_disable_shortcut_controls },
 123     { 3, KEY_RIGHT                  , 0x00000040, RB(0,4,1), 0, "+ Foc.","Factor", GUI_MODE_ALT, GUI_MODE_ALT, MODE_REC, 0, 0, &conf.touchscreen_disable_shortcut_controls },
 124 
 125         { 0 } 
 126 };
 127 
 128 static int is_button_displayed(int b, int guiMode, int camMode)
 129 {
 130     return (
 131             (keymap[b].grp == 3) && 
 132             (guiMode >= keymap[b].min_gui_mode) && 
 133             (guiMode <= keymap[b].max_gui_mode) && 
 134             (camMode & keymap[b].cam_mode_mask) &&
 135             ((keymap[b].conf_disable == 0) || (*keymap[b].conf_disable == 0))
 136            );
 137 }
 138 
 139 static int is_button_active(int b, int guiMode, int camMode)
 140 {
 141     return (is_button_displayed(b, guiMode, camMode) && keymap[b].canonkey);
 142 }
 143 
 144 int show_virtual_buttons()
 145 {
 146     extern char canon_play_menu_active;
 147     return (canon_menu_active==(int)&canon_menu_active-4) && (canon_shoot_menu_active==0) && (canon_play_menu_active == 0);
 148 }
 149 
 150 // Called from hooked touch panel task (boot.c)
 151 // Return 0 to allow touch event to pass onto firmware, 1 to block event from firmware.
 152 int chdk_process_touch()
 153 {
 154     //ts_check_cnt++;
 155 
 156     // If in canon menu, let the firmware have all the touch events.
 157     if (!show_virtual_buttons()) return 0;
 158 
 159     int camMode = (get_movie_status()==VIDEO_RECORD_IN_PROGRESS) ? MODE_VID : (camera_info.state.mode & MODE_MASK);
 160 
 161     // Touch co-ordinate
 162     unsigned int tx = ((touch_screen_x & 0x7FFF) >> 5) ^ 0x3FF;
 163     unsigned int ty = ((touch_screen_y & 0x7FFF) >> 5) ^ 0x3FF;
 164     // Screen co-ordinate
 165     int sx = ((tx - 40) * 480) / 954;
 166     int sy = ((ty - 60) * 240) / 900;
 167     if (conf.rotate_osd)
 168     {
 169         sx = 480 - sx;
 170         sy = 240 - sy;
 171     }
 172 
 173     // Search for CHDK on screen buttons matching co-ordinate
 174     int i;
 175     for (i=0; keymap[i].hackkey; i++)
 176     {
 177         if ((sx >= keymap[i].x1) && (sx < keymap[i].x2) && (sy >= keymap[i].y1) && (sy < keymap[i].y2) && is_button_active(i,camera_info.state.gui_mode,camMode))
 178         {
 179             touch_panel_state &= ~keymap[i].canonkey;
 180         }
 181     }
 182 
 183     // Check if menu touched
 184     int mk = gui_touch_process(sx, sy);
 185     if (mk != 0)
 186     {
 187         for (i=0; keymap[i].hackkey; i++)
 188         {
 189             if ((keymap[i].hackkey == mk) && is_button_active(i,camera_info.state.gui_mode,camMode))
 190             {
 191                 touch_panel_state &= ~keymap[i].canonkey;
 192             }
 193         }
 194     }
 195 
 196     // If in alt mode (or about to enter alt mode) block event from firmware
 197     return !camera_info.state.gui_mode_none || (((touch_panel_state & 1) == 0) && ((kbd_mod_state[3] & 1) != 0));
 198 }
 199 
 200 int redraw_buttons = 1;
 201 
 202 // Test a pixel value of the CHDK on-screen button to see if it may have been erased
 203 static int draw_test_pixel(coord x, coord y, color c)
 204 {
 205     extern char* bitmap_buffer[];
 206     extern int active_bitmap_buffer;
 207     if (conf.rotate_osd)
 208         return (bitmap_buffer[active_bitmap_buffer][(240-y) * camera_screen.buffer_width + ASPECT_XCORRECTION(480-x) - 1] == c);
 209     else
 210         return (bitmap_buffer[active_bitmap_buffer][y * camera_screen.buffer_width + ASPECT_XCORRECTION(x)] == c);
 211 }
 212 
 213 void virtual_buttons()
 214 {
 215     char buf[30];
 216 
 217     // If shooting or in any Canon menus then don't display any CHDK buttons
 218     if ((camera_info.state.gui_mode_none && camera_info.state.is_shutter_half_press) || !show_virtual_buttons()) return;
 219 
 220     // Check if border of CHDK button is corrupted, force redraw if so
 221     if (!draw_test_pixel(0, 80, (camera_info.state.gui_mode)?COLOR_GREEN:COLOR_WHITE)) redraw_buttons = 1;
 222 
 223     if (redraw_buttons)
 224     {
 225         //ts_redraw_cnt++;
 226 
 227         int i, x1, y1, x2, y2, sc, xo, yo;
 228         int camMode = (get_movie_status()==VIDEO_RECORD_IN_PROGRESS) ? MODE_VID : (camera_info.state.mode & MODE_MASK);
 229 
 230         color c1 = MAKE_COLOR(COLOR_GREY_DK_TRANS, COLOR_WHITE);
 231         color c2 = MAKE_COLOR(COLOR_GREY_DK_TRANS, COLOR_GREEN);
 232 
 233         for (i=0; keymap[i].hackkey; i++)
 234         {
 235             if (is_button_displayed(i, camera_info.state.gui_mode, camMode) && keymap[i].nm)
 236             {
 237                 x1 = keymap[i].x1;
 238                 x2 = keymap[i].x2;
 239                 y1 = keymap[i].y1;
 240                 y2 = keymap[i].y2;
 241                 sc = keymap[i].sc;
 242                 yo = (sc == 1) ? 16 : 8;
 243 
 244                 twoColors cl = c1;
 245                 if (camera_info.state.gui_mode && (keymap[i].hackkey == KEY_PRINT)) cl = c2;
 246                 if (keymap[i].conf_val && *keymap[i].conf_val) cl = c2;
 247 
 248                 draw_rectangle(x1, y1, x2, y2, cl, RECT_BORDER3|DRAW_FILLED|RECT_ROUND_CORNERS);
 249 
 250                 if (keymap[i].conf_val && keymap[i].chg_val)
 251                 {
 252                     yo -= 9;
 253                     strcpy(buf,(char*)keymap[i].chg_val(0,(int)keymap[i].conf_val));
 254                     buf[6] = 0;
 255                     xo = (58 - strlen(buf)*FONT_WIDTH*sc) / 2;
 256                     draw_string(x1+xo, y1+yo+18, buf, cl);
 257                 }
 258                 else if (keymap[i].nm2)
 259                 {
 260                     yo -= 9;
 261                     xo = (58 - strlen(keymap[i].nm2)*FONT_WIDTH*sc) / 2;
 262                     draw_string(x1+xo, y1+yo+18, keymap[i].nm2, cl);
 263                 }
 264                 xo = (58 - strlen(keymap[i].nm)*FONT_WIDTH*sc) / 2;
 265                 draw_string_scaled(x1+xo, y1+yo, keymap[i].nm, cl, sc, sc);
 266             }
 267         }
 268     }
 269 
 270     redraw_buttons = 0;
 271 }
 272 
 273 int ts_process_touch()
 274 {
 275     int rv = 0, i;
 276 
 277     if (touch_panel_state != (long)0xFFFFFFFF)
 278     {
 279         int camMode = (get_movie_status()==VIDEO_RECORD_IN_PROGRESS) ? MODE_VID : (camera_info.state.mode & MODE_MASK);
 280 
 281         //ts_proc_cnt++;
 282 
 283         for (i=0; keymap[i].hackkey; i++)
 284         {
 285             if (is_button_active(i, camera_info.state.gui_mode, camMode))
 286             {
 287                 if (kbd_is_key_clicked(keymap[i].hackkey))
 288                 {
 289                     if (keymap[i].conf_val && keymap[i].chg_val)
 290                     {
 291                         keymap[i].chg_val(1,(int)keymap[i].conf_val);
 292                         rv = keymap[i].redraw & 1;
 293                     }
 294                     if (keymap[i].redraw & 2) redraw_buttons = 1;
 295                 }
 296             }
 297         }
 298     }
 299 
 300     return rv;
 301 }
 302 
 303 //-----------------------------------------------------------------------------
 304 
 305 int get_usb_bit()
 306 {
 307     long usb_physw[3];
 308     usb_physw[USB_IDX] = 0;
 309     _kbd_read_keys_r2(usb_physw);
 310     return(( usb_physw[USB_IDX] & USB_MASK)==USB_MASK) ;
 311 }
 312 
 313 void kbd_fetch_data(long *dst)
 314 {
 315     _GetKbdState(dst);
 316     _kbd_read_keys_r2(dst);
 317 
 318     static int was_active = 0;
 319 
 320     if (touch_screen_active == 2)               // Touch screen activated?
 321     {
 322         was_active = 1;                                     // Record activated, wait until released
 323     }
 324     else if (was_active)
 325     {
 326         kbd_new_state[3] = touch_panel_state;               // Use virtual button state
 327         was_active = 0;
 328     }
 329     else
 330     {
 331         kbd_new_state[3] = touch_panel_state = 0xFFFFFFFF;  // Clear out virtual button state
 332     }
 333 }
 334 
 335 void my_kbd_read_keys()
 336 {
 337     kbd_update_key_state();
 338     kbd_update_physw_bits();
 339 }
 340 
 341 long __attribute__((naked,noinline)) wrap_kbd_p1_f()
 342 {
 343     asm volatile(
 344         "STMFD   SP!, {R1-R7,LR}\n"
 345         "MOV     R5, #0\n"
 346         //"BL      _kbd_read_keys \n"
 347         "BL     my_kbd_read_keys\n"
 348         "B       _kbd_p1_f_cont\n"
 349     );
 350     return 0; // shut up the compiler
 351 }
 352 
 353 // no stack manipulation needed here, since we create the task directly
 354 void __attribute__((naked,noinline))
 355 mykbd_task()
 356 {
 357     while (physw_run){
 358         _SleepTask(physw_sleep_delay);
 359 
 360         if (wrap_kbd_p1_f() == 1){ // autorepeat ?
 361             _kbd_p2_f();
 362         }
 363     }
 364 
 365     _ExitTask();
 366 }

/* [<][>][^][v][top][bottom][index][help] */