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

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