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 #include "debug_led.h"
  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     {
 222         if (camera_info.cam_remote_sync_status_led == -1)
 223             debug_led(state);
 224         else
 225             *(int*)camera_info.cam_remote_sync_status_led=state ? 0x46 : 0x44;
 226     }
 227 }
 228 
 229 /*---------------------------------------------------------------------------------------------------------
 230 
 231     usb_remote_key()
 232 
 233     - called from the kbd_process() keyboard handler or usb_HPtimer_good()
 234     - monitors USB power state and stores in global variable remote_state
 235     - captures the time of 0->1 and 1->0 transitions and buffers them
 236     - stores most recent power on pulse width in global variable usb_power
 237     - stores most recent pulse count in global variable usb_count
 238   ---------------------------------------------------------------------------------------------------------*/
 239 
 240 void usb_buffer_insert(int value)
 241 {
 242     if ( ++usb_buffer_in > &usb_buffer[USB_BUFFER_SIZE-1] ) usb_buffer_in = usb_buffer ;    
 243     if ( usb_buffer_in == usb_buffer_out )
 244     {
 245         if ( ++usb_buffer_out > &usb_buffer[USB_BUFFER_SIZE-1] ) usb_buffer_out = usb_buffer ;
 246     }
 247     *usb_buffer_in = value ;
 248 }
 249  
 250 void usb_remote_key( void )
 251 {
 252     static int pulse_count=0 ;
 253 
 254     usb_state = get_remote_state() ;
 255 
 256     if(conf.remote_enable)
 257     {
 258         if (usb_state)
 259         {                                                                   // USB power is ON
 260             if (remote_mark_count<30000) remote_mark_count++ ;              // track how long the USB power is ON
 261             if (remote_space_count != 0)                                    // is this the 0 -> 1 transistion?
 262             {                                                               //
 263                 usb_buffer_insert(remote_space_count);                      // insert space length into buffer
 264                 remote_space_count = 0 ;                                    // reset the counter
 265             }
 266         }
 267         else
 268         {                                                                   // USB power if OFF
 269             if(remote_space_count>-30000) remote_space_count-- ;            // track how long the USB power is OFF (note space counts are negative)
 270             if (remote_mark_count != 0)                                     // is this the 1 -> 0 transistion?
 271             {                                                               //
 272                 pulse_count++ ;                                             // count pulses transistions
 273                 usb_power = remote_mark_count;                              // transfer most recent pulse length to variable read by scripts
 274                 usb_buffer_insert(remote_mark_count);                       // insert pulse length into buffer
 275                 remote_mark_count = 0;                                      // reset the counter
 276                 camera_info.state.kbd_last_clicked = 0xFF;                  // flag the remote key as the last one pressed (for scripts)
 277                 camera_info.state.kbd_last_clicked_time = get_tick_count(); // store key release time too
 278             }                                                               //
 279             if ((remote_space_count < -50) && (pulse_count > 0))            // pulse counting done if no activity for 50 timer periods
 280             {
 281                 usb_count = pulse_count ;
 282                 logic_module_usb_count = pulse_count ;
 283                 pulse_count = 0 ;
 284             }
 285         }
 286     }
 287 }
 288 
 289 
 290 /*---------------------------------------------------------------------------------------------------------
 291 
 292      High Precision USB Remote Timer Callback routines.
 293 
 294   ---------------------------------------------------------------------------------------------------------*/
 295 int usb_HPtimer_error_count;
 296 
 297 int usb_HPtimer_good(int time, int interval) 
 298 {
 299     usb_HPtimer_handle=0;
 300     start_usb_HPtimer(interval) ;
 301     usb_remote_key() ;
 302     return 0;
 303 }
 304  
 305 int usb_HPtimer_bad(int time, int interval) 
 306 {
 307     usb_HPtimer_error_count++;
 308     return (usb_HPtimer_good(time, interval));
 309 }
 310 
 311 /*---------------------------------------------------------------------------------------------------------
 312 
 313      clear_usb_power()
 314 
 315   ---------------------------------------------------------------------------------------------------------*/
 316 
 317 void clear_usb_power()
 318 {
 319     usb_power = 0 ;
 320     usb_count = 0 ;
 321     logic_module_usb_count = 0;
 322     usb_buffer_out = usb_buffer_in = usb_buffer ;
 323 }
 324 
 325 /*---------------------------------------------------------------------------------------------------------
 326 
 327      get_usb_power()
 328 
 329   ---------------------------------------------------------------------------------------------------------*/
 330 
 331 
 332 int get_usb_power(int mode)
 333 {
 334     int x = 0;
 335 
 336     switch( mode)
 337     {
 338         case SINGLE_PULSE :
 339             x = usb_power;
 340             usb_power = 0;
 341             break ;
 342         case USB_STATE :
 343             x=usb_state;
 344             break ;
 345         case BUFFERED_PULSE :
 346             if ( usb_buffer_out != usb_buffer_in )
 347             {
 348                 if ( ++usb_buffer_out > &usb_buffer[USB_BUFFER_SIZE-1] ) usb_buffer_out = usb_buffer ;
 349                 x = *usb_buffer_out ;
 350             }
 351             break ;
 352         case PULSE_COUNT :
 353             x = usb_count;
 354             usb_count = 0;
 355             break ;
 356         case LM_PULSE_COUNT :
 357             x = logic_module_usb_count;
 358             logic_module_usb_count = 0;
 359             break ;
 360         case HPTIMER_ERROR_COUNT :
 361             x = usb_HPtimer_error_count;
 362             usb_HPtimer_error_count = 0;
 363             break ;
 364     }
 365     return x;
 366 }
 367 
 368 
 369 /*===================================================================================================
 370 
 371    main USB remote processing routine - called every 10 mSec fronm kbd.c
 372 
 373   ===================================================================================================*/
 374 
 375 extern void (*usb_driver[])( ) ;
 376 extern void (*usb_module_play[])( ) ;
 377 extern void (*usb_module_shoot[])( ) ;
 378 extern void (*usb_module_video[])( ) ;
 379 
 380 static int rmt_state = RMT_DISABLED ;
 381 
 382 void set_usb_remote_state()
 383 {
 384     if (conf.remote_enable)
 385     {
 386         rmt_state = RMT_ENABLED ;
 387         switch_type = conf.remote_switch_type ;
 388         control_module = conf.remote_control_mode ;
 389     }
 390     else
 391     {
 392         rmt_state = RMT_DISABLED ;
 393         usb_remote_active = 0 ;
 394     }
 395     virtual_remote_state = driver_state = logic_module_state = REMOTE_RESET ;
 396 }
 397 
 398 int handle_usb_remote()
 399 {
 400     if (conf.remote_enable)
 401     {
 402         if (camera_info.state.mode_play)
 403             camera_mode = CAMERA_MODE_PLAYBACK ;
 404         else
 405             camera_mode = camera_info.state.mode_video ? CAMERA_MODE_VIDEO : CAMERA_MODE_SHOOTING ;
 406 
 407         (*usb_driver[switch_type])(get_usb_power(USB_STATE));           // jump to driver state machine
 408 
 409         switch( camera_mode )
 410         {
 411             case CAMERA_MODE_PLAYBACK :
 412                 (*usb_module_play[switch_type])();                      // jump to control module state machine
 413                 break ;
 414             case CAMERA_MODE_SHOOTING :
 415                 (*usb_module_shoot[control_module])();                  // jump to control module state machine
 416                 break ;
 417             case CAMERA_MODE_VIDEO :
 418                 (*usb_module_video[control_module])();                  // jump to control module state machine
 419                 break ;
 420             default :
 421                 conf.remote_enable = 0 ;
 422                 break ;
 423         }
 424 
 425         usb_remote_active = ((logic_module_state  > 1) || (driver_state  > 1) || (virtual_remote_state  > 1) ) ? 1 : 0 ;
 426 
 427         #ifdef USB_REMOTE_RECORD
 428             debug_add_rec();
 429         #endif
 430 
 431         #ifdef USB_REMOTE_DEBUGGING
 432             extern int sync_counter ;
 433             extern long physw_status[3] ;
 434             extern int usb_buffer[] ;
 435             extern int * usb_buffer_in ;
 436             extern int * usb_buffer_out ;
 437             extern const char* gui_USB_switch_types[] ;
 438             extern const char* gui_USB_control_modes[];
 439             extern EXPO_BRACKETING_VALUES bracketing;
 440             char buf[64] ;
 441             static int debug_print = 0 ;
 442             static int startup_delay = 0 ;
 443             int i, buff_pos,  *buff_ptr ;
 444 
 445             if ( startup_delay < 100 ) startup_delay++ ;                // need to give things time to settle before using draw_string()
 446             else
 447             {
 448                 if ( debug_print++ > 10000 ) debug_print = 0 ;
 449 
 450                 if ((debug_print%2) == 0)
 451                 {
 452                     switch( virtual_remote_state )
 453                     {
 454                         case  REMOTE_RESET :
 455                             sprintf(buf,"RESET      ") ;
 456                             break;
 457                         case  REMOTE_RELEASE :
 458                             sprintf(buf,"RELEASED  ") ;
 459                             break;
 460                         case  REMOTE_HALF_PRESS :
 461                             sprintf(buf,"HALF PRESS    ") ;
 462                             break;
 463                         case  REMOTE_FULL_PRESS :
 464                             sprintf(buf,"FULL PRESS    ") ;
 465                             break;
 466                         default :
 467                             sprintf(buf,"ERROR    ") ;
 468                             break;
 469                     }
 470                     draw_string(2,FONT_HEIGHT,buf,MAKE_COLOR(COLOR_YELLOW,COLOR_RED));
 471                 }
 472                 else
 473                 {
 474                     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));
 475                     draw_string(2,FONT_HEIGHT*3,buf,MAKE_COLOR(COLOR_BLACK,COLOR_YELLOW));
 476                 }
 477 
 478                 if (((debug_print+25)%100) ==0 )
 479                 {
 480                     sprintf(buf,"switch=%d logic=%d sync=%s mode=%d  ", switch_type, control_module, conf.synch_enable?"yes":"no", camera_mode) ;
 481                     draw_string(2,FONT_HEIGHT*2,buf,MAKE_COLOR(COLOR_YELLOW,COLOR_BLACK));
 482                     sprintf(buf,"sync count=%d, pulse count=%d width=%d  b=%d  ", sync_counter, usb_count, usb_power,   bracketing.shoot_counter);
 483                     draw_string(2,FONT_HEIGHT*4,buf,MAKE_COLOR(COLOR_BLACK,COLOR_YELLOW));
 484                     sprintf(buf,"physw=%d err=%d %d %d  ", physw_status[0]&0x03, debug_errors[0],  debug_errors[1],  debug_errors[2] );
 485                     draw_string(2,FONT_HEIGHT*5,buf,MAKE_COLOR(COLOR_BLACK,COLOR_YELLOW));
 486                 }
 487 
 488                 if (((debug_print+75)%100) == 0 )
 489                 {
 490                     buff_ptr = usb_buffer_in ;
 491                     buff_pos = 0 ;
 492 
 493                     for ( i=0 ; i<16 ; i++ )
 494                     {
 495                         sprintf(&buf[buff_pos],"%d ", *buff_ptr) ;
 496                         buff_pos = strlen(buf) ;
 497                         if ( buff_pos > 45 )
 498                         {
 499                             buf[45] = 0 ;
 500                             i=17 ;
 501                         }
 502                         if ( buff_ptr-- == usb_buffer )  buff_ptr = &usb_buffer[15] ;
 503                     }
 504                     draw_string(2,FONT_HEIGHT*6,buf,MAKE_COLOR(COLOR_BLACK,COLOR_YELLOW));
 505                 }
 506             }
 507         #endif
 508     }
 509 
 510     return usb_remote_active ;
 511 }

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