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

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