root/core/usb_remote.c

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

DEFINITIONS

This source file includes following definitions.
  1. debug_error
  2. debug_error
  3. debug_dump_rec
  4. debug_add_rec
  5. kbd_synch_delay
  6. kbd_calibrate_synch_delay
  7. usb_remote_status_led
  8. usb_buffer_insert
  9. usb_remote_key
  10. usb_HPtimer_good
  11. usb_HPtimer_bad
  12. clear_usb_power
  13. get_usb_power
  14. set_usb_remote_state
  15. handle_usb_remote

   1 /*===================================================================================================
   2     usb_remote.c
   3 
   4         -   called every 10 mSec from kbd.c
   5         -   when enabled via CHDK menu, monitors the state of USB power and takes action on a change
   6         -   consists of :
   7                 -   a user selectable driver module that watches the USB power state
   8                     and sets the state of a "virtual" remote switch
   9                 -   a user selectable control module that translates the state of the
  10                     "virtual" remote switch to KEY_PRESS actions
  11                 -   [FUTURE] extends the script command get_usb_power() to return the current state of
  12                     the "virtual" remote switch, allowing scripts to easily work with all switch types
  13                 -   [FUTURE]  supplies a framework for adding support to read PWM devices (e.g. gentles) and
  14                     to perform control actions based on those signals (at some point somebody might even use
  15                     this to build a Arduino-type remote control keypad
  16   ===================================================================================================*/
  17 
  18 #include "camera_info.h"
  19 #include "stdlib.h"
  20 #include "clock.h"
  21 #include "modes.h"
  22 #include "shooting.h"
  23 #include "conf.h"
  24 #include "action_stack.h"
  25 #include "gui_draw.h"
  26 #include "usb_remote.h"
  27 
  28 
  29 /*===================================================================================================
  30     Variables
  31   ===================================================================================================*/
  32 int usb_sync_wait_flag=0 ;
  33 int usb_remote_active=0 ;
  34 int bracketing_timeout = 0 ;
  35 int usb_power=0;
  36 static int usb_count=0;
  37 static int logic_module_usb_count = 0 ;
  38 int remote_mark_count, remote_space_count;
  39 
  40 #define USB_BUFFER_SIZE 16
  41 static int usb_buffer[USB_BUFFER_SIZE] ;
  42 static int * usb_buffer_in = usb_buffer ;
  43 static int * usb_buffer_out = usb_buffer ;
  44 
  45 
  46 enum SWITCH_TYPE            switch_type = SW_NONE ;
  47 enum CONTROL_MODULE         control_module = RMT_NONE ;
  48 enum VIRTUAL_REMOTE_STATE   virtual_remote_state = REMOTE_RESET ;
  49 enum DRIVER_STATE           driver_state = SW_RESET;
  50 enum LOGIC_MODULE_STATE     logic_module_state = LM_RESET;
  51 enum USB_POWER_STATE        usb_state = USB_POWER_OFF ;
  52 enum CAMERA_MODE            camera_mode = CAMERA_MODE_PLAYBACK ;
  53 
  54 /*===================================================================================================
  55     Debug and error handling
  56   ===================================================================================================*/
  57 
  58 
  59  #ifdef USB_REMOTE_DEBUGGING
  60 
  61 #define NUMBER_OF_ERRORS 21
  62 
  63 int debug_errors[NUMBER_OF_ERRORS] ;
  64 
  65 void debug_error(int err_num)
  66 {
  67     if ( (err_num > 0) && (err_num <= NUMBER_OF_ERRORS ))
  68     {
  69         --err_num ;
  70         if ( ++debug_errors[err_num] > 999 ) debug_errors[err_num]=0 ;
  71     }
  72 }
  73 
  74 #else
  75 
  76 void debug_error(int err_num)
  77 {
  78 }
  79 
  80 #endif
  81 
  82 #ifdef USB_REMOTE_RECORD
  83 
  84 struct debug_rec_remote_state {
  85     long tick;
  86     char usb;
  87     char driver_state;
  88     char virtual_remote_state;
  89     char usb_count;
  90     char logic_module_state;
  91     char usb_sync_wait;
  92     char usb_remote_active;
  93 };
  94 
  95 #define DEBUG_MAX_REC 8192
  96 
  97 
  98 struct debug_rec_remote_state *debug_rec_buf = NULL;
  99 
 100 static int debug_num_rec = 0;
 101 static int debug_num_rec_file = 0;
 102 
 103 static void debug_dump_rec()
 104 {
 105     char fn[12];
 106     int fd;
 107     sprintf(fn, "A/RC%05d.DAT", debug_num_rec_file);
 108     debug_num_rec_file++;
 109 
 110     fd = open(fn, O_WRONLY|O_CREAT, 0777);
 111     if (fd>=0)
 112     {
 113         write(fd, debug_rec_buf, sizeof(struct debug_rec_remote_state) * debug_num_rec);
 114         close(fd);
 115     }
 116     debug_num_rec = 0;
 117 }
 118 
 119 static void debug_add_rec()
 120 {
 121     static int last_active = 0;
 122     if (debug_num_rec >= DEBUG_MAX_REC) return;
 123     if (!debug_rec_buf) debug_rec_buf = umalloc(sizeof(struct debug_rec_remote_state) * DEBUG_MAX_REC);
 124     if (!debug_rec_buf) return;
 125 
 126     debug_rec_buf[debug_num_rec].tick = get_tick_count();
 127     debug_rec_buf[debug_num_rec].usb = usb_state;
 128 
 129     debug_rec_buf[debug_num_rec].driver_state = driver_state;
 130     debug_rec_buf[debug_num_rec].virtual_remote_state = virtual_remote_state;
 131     debug_rec_buf[debug_num_rec].usb_count = usb_count;
 132     debug_rec_buf[debug_num_rec].logic_module_state = logic_module_state;
 133     debug_rec_buf[debug_num_rec].usb_sync_wait = usb_sync_wait_flag;
 134     debug_rec_buf[debug_num_rec].usb_remote_active = usb_remote_active;
 135 
 136     debug_num_rec++;
 137     if ((debug_num_rec >= DEBUG_MAX_REC) ||
 138         (last_active && !usb_remote_active)) debug_dump_rec();
 139 
 140     last_active = usb_remote_active;
 141 }
 142 
 143 #endif
 144 
 145 
 146 /*---------------------------------------------------------------------------------------------------------
 147 
 148     kbd_synch_delay :
 149         support the sync delay option of USB remote
 150 
 151     Adds a fixed hard coded loop delay before releasing the shooting process in sync mode
 152 
 153   ---------------------------------------------------------------------------------------------------------*/
 154 
 155 static int synch_delay_tick = 2800;                                     // default calibration value - not tuned for any camera
 156 
 157 
 158 void kbd_synch_delay(int delay_value)
 159 {
 160     int count1;
 161 
 162     for (count1=0;count1<delay_value;count1++)                          //wait delay_value * 0.1ms
 163     {
 164         asm volatile (
 165         "mov r1, #0\n"
 166         ".loop: \n\t"
 167         "add r1, r1, #1\n\t"
 168         "cmp r1, %0\n\t"
 169         "blt .loop"
 170         :
 171         : "r" (synch_delay_tick)
 172         : "r1" );
 173 
 174     }
 175 }
 176 
 177 
 178 #define CALIBRATE_SYNCH_DELAY 1
 179 #undef CALIBRATE_SYNCH_DELAY                                            // Note : comment this out during testing to calibrate a camera's sync delay
 180 
 181 #ifdef CALIBRATE_SYNCH_DELAY
 182 
 183 #define KBD_CALIBRATE_TIME 100
 184 
 185 static int synch_delay_calib = 0;
 186 
 187 void kbd_calibrate_synch_delay()
 188 {
 189     if (synch_delay_calib) return;
 190     int t0 = get_tick_count();
 191     kbd_synch_delay(10 * KBD_CALIBRATE_TIME);
 192     int t = get_tick_count() - t0;
 193 
 194     synch_delay_tick = synch_delay_tick * KBD_CALIBRATE_TIME / t;
 195 
 196     if (synch_delay_tick < 100) synch_delay_tick = 2800;                /*something went wrong */
 197     if (synch_delay_tick > 100000) synch_delay_tick = 2800;
 198 
 199     int fd;
 200     char buf[64];
 201     sprintf(buf, "%d %d ", synch_delay_tick, t);
 202     fd = open("A/CALIB.TXT", O_WRONLY|O_CREAT, 0777);
 203     if (fd>=0) {
 204       write(fd, buf, strlen(buf));
 205       close(fd);
 206       }
 207     synch_delay_calib = 1;
 208 }
 209 #endif
 210 
 211 /*---------------------------------------------------------------------------------------------------------
 212 
 213     usb_remote_status_led :
 214         Turn on a camera LED while the camera is waiting for a USB 1->0 transistion to terminate sync wait mode
 215 
 216   ---------------------------------------------------------------------------------------------------------*/
 217 
 218 void usb_remote_status_led(int state)
 219 {
 220     if (camera_info.cam_remote_sync_status_led)
 221         *(int*)camera_info.cam_remote_sync_status_led=state ? 0x46 : 0x44;
 222 }
 223 
 224 /*---------------------------------------------------------------------------------------------------------
 225 
 226     usb_remote_key()
 227 
 228     - called from the kbd_process() keyboard handler or usb_HPtimer_good()
 229     - monitors USB power state and stores in global variable remote_state
 230     - captures the time of 0->1 and 1->0 transitions and buffers them
 231     - stores most recent power on pulse width in global variable usb_power
 232     - stores most recent pulse count in global variable usb_count
 233   ---------------------------------------------------------------------------------------------------------*/
 234 
 235 void usb_buffer_insert(int value)
 236 {
 237     if ( ++usb_buffer_in > &usb_buffer[USB_BUFFER_SIZE-1] ) usb_buffer_in = usb_buffer ;    
 238     if ( usb_buffer_in == usb_buffer_out )
 239     {
 240         if ( ++usb_buffer_out > &usb_buffer[USB_BUFFER_SIZE-1] ) usb_buffer_out = usb_buffer ;
 241     }
 242     *usb_buffer_in = value ;
 243 }
 244  
 245 void usb_remote_key( void )
 246 {
 247     static int pulse_count=0 ;
 248 
 249     usb_state = get_remote_state() ;
 250 
 251     if(conf.remote_enable)
 252     {
 253         if (usb_state)
 254         {                                                                   // USB power is ON
 255             if (remote_mark_count<30000) remote_mark_count++ ;              // track how long the USB power is ON
 256             if (remote_space_count != 0)                                    // is this the 0 -> 1 transistion?
 257             {                                                               //
 258                 usb_buffer_insert(remote_space_count);                      // insert space length into buffer
 259                 remote_space_count = 0 ;                                    // reset the counter
 260             }
 261         }
 262         else
 263         {                                                                   // USB power if OFF
 264             if(remote_space_count>-30000) remote_space_count-- ;            // track how long the USB power is OFF (note space counts are negative)
 265             if (remote_mark_count != 0)                                     // is this the 1 -> 0 transistion?
 266             {                                                               //
 267                 pulse_count++ ;                                             // count pulses transistions
 268                 usb_power = remote_mark_count;                              // transfer most recent pulse length to variable read by scripts
 269                 usb_buffer_insert(remote_mark_count);                       // insert pulse length into buffer
 270                 remote_mark_count = 0;                                      // reset the counter
 271                 camera_info.state.kbd_last_clicked = 0xFF;                  // flag the remote key as the last one pressed (for scripts)
 272                 camera_info.state.kbd_last_clicked_time = get_tick_count(); // store key release time too
 273             }                                                               //
 274             if ((remote_space_count < -50) && (pulse_count > 0))            // pulse counting done if no activity for 50 timer periods
 275             {
 276                 usb_count = pulse_count ;
 277                 logic_module_usb_count = pulse_count ;
 278                 pulse_count = 0 ;
 279             }
 280         }
 281     }
 282 }
 283 
 284 
 285 /*---------------------------------------------------------------------------------------------------------
 286 
 287      High Precision USB Remote Timer Callback routines.
 288 
 289   ---------------------------------------------------------------------------------------------------------*/
 290 int usb_HPtimer_error_count;
 291 
 292 int usb_HPtimer_good(int time, int interval) 
 293 {
 294     usb_HPtimer_handle=0;
 295     start_usb_HPtimer(interval) ;
 296     usb_remote_key() ;
 297     return 0;
 298 }
 299  
 300 int usb_HPtimer_bad(int time, int interval) 
 301 {
 302     usb_HPtimer_error_count++;
 303     return (usb_HPtimer_good(time, interval));
 304 }
 305 
 306 /*---------------------------------------------------------------------------------------------------------
 307 
 308      clear_usb_power()
 309 
 310   ---------------------------------------------------------------------------------------------------------*/
 311 
 312 void clear_usb_power()
 313 {
 314     usb_power = 0 ;
 315     usb_count = 0 ;
 316     logic_module_usb_count = 0;
 317     usb_buffer_out = usb_buffer_in = usb_buffer ;
 318 }
 319 
 320 /*---------------------------------------------------------------------------------------------------------
 321 
 322      get_usb_power()
 323 
 324   ---------------------------------------------------------------------------------------------------------*/
 325 
 326 
 327 int get_usb_power(int mode)
 328 {
 329     int x = 0;
 330 
 331     switch( mode)
 332     {
 333         case SINGLE_PULSE :
 334             x = usb_power;
 335             usb_power = 0;
 336             break ;
 337         case USB_STATE :
 338             x=usb_state;
 339             break ;
 340         case BUFFERED_PULSE :
 341             if ( usb_buffer_out != usb_buffer_in )
 342             {
 343                 if ( ++usb_buffer_out > &usb_buffer[USB_BUFFER_SIZE-1] ) usb_buffer_out = usb_buffer ;
 344                 x = *usb_buffer_out ;
 345             }
 346             break ;
 347         case PULSE_COUNT :
 348             x = usb_count;
 349             usb_count = 0;
 350             break ;
 351         case LM_PULSE_COUNT :
 352             x = logic_module_usb_count;
 353             logic_module_usb_count = 0;
 354             break ;
 355         case HPTIMER_ERROR_COUNT :
 356             x = usb_HPtimer_error_count;
 357             usb_HPtimer_error_count = 0;
 358             break ;
 359     }
 360     return x;
 361 }
 362 
 363 
 364 /*===================================================================================================
 365 
 366    main USB remote processing routine - called every 10 mSec fronm kbd.c
 367 
 368   ===================================================================================================*/
 369 
 370 extern void (*usb_driver[])( ) ;
 371 extern void (*usb_module_play[])( ) ;
 372 extern void (*usb_module_shoot[])( ) ;
 373 extern void (*usb_module_video[])( ) ;
 374 
 375 static int rmt_state = RMT_DISABLED ;
 376 
 377 void set_usb_remote_state()
 378 {
 379     if (conf.remote_enable)
 380     {
 381         rmt_state = RMT_ENABLED ;
 382         switch_type = conf.remote_switch_type ;
 383         control_module = conf.remote_control_mode ;
 384     }
 385     else
 386     {
 387         rmt_state = RMT_DISABLED ;
 388         usb_remote_active = 0 ;
 389     }
 390     virtual_remote_state = driver_state = logic_module_state = REMOTE_RESET ;
 391 }
 392 
 393 int handle_usb_remote()
 394 {
 395     if (conf.remote_enable)
 396     {
 397         if (camera_info.state.mode_play)
 398             camera_mode = CAMERA_MODE_PLAYBACK ;
 399         else
 400             camera_mode = camera_info.state.mode_video ? CAMERA_MODE_VIDEO : CAMERA_MODE_SHOOTING ;
 401 
 402         (*usb_driver[switch_type])(get_usb_power(USB_STATE));           // jump to driver state machine
 403 
 404         switch( camera_mode )
 405         {
 406             case CAMERA_MODE_PLAYBACK :
 407                 (*usb_module_play[switch_type])();                      // jump to control module state machine
 408                 break ;
 409             case CAMERA_MODE_SHOOTING :
 410                 (*usb_module_shoot[control_module])();                  // jump to control module state machine
 411                 break ;
 412             case CAMERA_MODE_VIDEO :
 413                 (*usb_module_video[control_module])();                  // jump to control module state machine
 414                 break ;
 415             default :
 416                 conf.remote_enable = 0 ;
 417                 break ;
 418         }
 419 
 420         usb_remote_active = ((logic_module_state  > 1) || (driver_state  > 1) || (virtual_remote_state  > 1) ) ? 1 : 0 ;
 421 
 422         #ifdef USB_REMOTE_RECORD
 423             debug_add_rec();
 424         #endif
 425 
 426         #ifdef USB_REMOTE_DEBUGGING
 427             extern int sync_counter ;
 428             extern long physw_status[3] ;
 429             extern int usb_buffer[] ;
 430             extern int * usb_buffer_in ;
 431             extern int * usb_buffer_out ;
 432             extern const char* gui_USB_switch_types[] ;
 433             extern const char* gui_USB_control_modes[];
 434             extern EXPO_BRACKETING_VALUES bracketing;
 435             char buf[64] ;
 436             static int debug_print = 0 ;
 437             static int startup_delay = 0 ;
 438             int i, buff_pos,  *buff_ptr ;
 439 
 440             if ( startup_delay < 100 ) startup_delay++ ;                // need to give things time to settle before using draw_string()
 441             else
 442             {
 443                 if ( debug_print++ > 10000 ) debug_print = 0 ;
 444 
 445                 if ((debug_print%2) == 0)
 446                 {
 447                     switch( virtual_remote_state )
 448                     {
 449                         case  REMOTE_RESET :
 450                             sprintf(buf,"RESET      ") ;
 451                             break;
 452                         case  REMOTE_RELEASE :
 453                             sprintf(buf,"RELEASED  ") ;
 454                             break;
 455                         case  REMOTE_HALF_PRESS :
 456                             sprintf(buf,"HALF PRESS    ") ;
 457                             break;
 458                         case  REMOTE_FULL_PRESS :
 459                             sprintf(buf,"FULL PRESS    ") ;
 460                             break;
 461                         default :
 462                             sprintf(buf,"ERROR    ") ;
 463                             break;
 464                     }
 465                     draw_string(2,FONT_HEIGHT,buf,MAKE_COLOR(COLOR_YELLOW,COLOR_RED));
 466                 }
 467                 else
 468                 {
 469                     sprintf(buf,"RMT=%d drv=%d lgc=%d  sync=%d  tmo=%d  ", usb_remote_active, driver_state, logic_module_state, usb_sync_wait_flag, (bracketing_timeout?bracketing_timeout-get_tick_count():0));
 470                     draw_string(2,FONT_HEIGHT*3,buf,MAKE_COLOR(COLOR_BLACK,COLOR_YELLOW));
 471                 }
 472 
 473                 if (((debug_print+25)%100) ==0 )
 474                 {
 475                     sprintf(buf,"switch=%d logic=%d sync=%s mode=%d  ", switch_type, control_module, conf.synch_enable?"yes":"no", camera_mode) ;
 476                     draw_string(2,FONT_HEIGHT*2,buf,MAKE_COLOR(COLOR_YELLOW,COLOR_BLACK));
 477                     sprintf(buf,"sync count=%d, pulse count=%d width=%d  b=%d  ", sync_counter, usb_count, usb_power,   bracketing.shoot_counter);
 478                     draw_string(2,FONT_HEIGHT*4,buf,MAKE_COLOR(COLOR_BLACK,COLOR_YELLOW));
 479                     sprintf(buf,"physw=%d err=%d %d %d  ", physw_status[0]&0x03, debug_errors[0],  debug_errors[1],  debug_errors[2] );
 480                     draw_string(2,FONT_HEIGHT*5,buf,MAKE_COLOR(COLOR_BLACK,COLOR_YELLOW));
 481                 }
 482 
 483                 if (((debug_print+75)%100) == 0 )
 484                 {
 485                     buff_ptr = usb_buffer_in ;
 486                     buff_pos = 0 ;
 487 
 488                     for ( i=0 ; i<16 ; i++ )
 489                     {
 490                         sprintf(&buf[buff_pos],"%d ", *buff_ptr) ;
 491                         buff_pos = strlen(buf) ;
 492                         if ( buff_pos > 45 )
 493                         {
 494                             buf[45] = 0 ;
 495                             i=17 ;
 496                         }
 497                         if ( buff_ptr-- == usb_buffer )  buff_ptr = &usb_buffer[15] ;
 498                     }
 499                     draw_string(2,FONT_HEIGHT*6,buf,MAKE_COLOR(COLOR_BLACK,COLOR_YELLOW));
 500                 }
 501             }
 502         #endif
 503     }
 504 
 505     return usb_remote_active ;
 506 }

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