;grip.asm - camcorder active handgrip code LIST P = PIC16C55, n = 66 INCLUDE PIC55 equ 1FFH ; Define Reset Vector Same equ 1 same equ 1 TRIS_READ_LANC equ 011h ;A0, 4 in - 1, 2, 3 out TRIS_WRITE_LANC equ 010h ;A4 in - 0,1,2,3 out TRIS_READ_SWITCHES equ 0ffh ; all inputs INPUT equ 0 ;bit to use for reading LANC - used 2x OUTPUT equ 0 ;bit to use for writing LANC - used 2x MENU_MODE_LED equ 1 ;set when in menu mode - used 2x SEND_COMM_LED equ 2 ;set when sending commands - used 4x SHIFT_LED equ 3 ;set when shift key is pressed - used 3x BIT_TIME equ .31 ;for 4 MHz - used 2x ; on my SONY CCD-TR6, values from 33 to 28 worked - mid range ; is 30 or 31 ORG 0ch ;start of GP registers counter RES 1 counter2 RES 1 bit_counter RES 1 bits_to_send RES 1 byte_to_write RES 1 command_byte_1 RES 1 command_byte_2 RES 1 byte_number RES 1 command_pass RES 1 menu_mode RES 1 ; switch vars: ; values 0 = open (pin is pulled high) ; 1 = was open, now closed (falling edge) ; 2 = was closed, still closed (held down) ; 4 = was closed, now open (button released) ; ; can value test - if 0 do nothing. ; if != 0, decide.... ; if 4, then clear to 0 (for now...) hat_up RES 1 ; hat UP zoom tele HAT_UP equ 0 ; bit number in PORTB hat_down RES 1 ; hat DOWN zoom wide HAT_DOWN equ 1 ; bit number in PORTB hat_left RES 1 ; hat LEFT focus far HAT_LEFT equ 2 ; bit number in PORTB hat_right RES 1 ; hat RIGHT focus near HAT_RIGHT equ 3 ; bit number in PORTB button_left RES 1 ; left red button start/stop BUTTON_LEFT equ 4 ; bit number in PORTB button_right RES 1 ; right red button BUTTON_RIGHT equ 5 ; bit number in PORTB trigger RES 1 ; trigger TRIGGER equ 6 ; bit number in PORTB shift RES 1 ; lower red button shift SHIFT equ 7 ; bit number in PORTB ORG 0 top call init goto happy_dance ; ends with 'goto main' main call wait_for_interframe ;do all switch reading in the ; 6 ms (4 left after this routine) ; between frames .... this is ; lots of time... each machine cycle is ; 1 us - so we have ~4000 to use... goto scan_switches ;ends with 'goto main' ;---------------------------------------------------------------------- ; subroutine call table....since 'call' target must be in first 256 bytes ; but goto can go anywhere wait_for_interframe ; retlw 0 ;for debugging goto wait_for_interframe_real send_command_5 goto send_command_5 scan_switches goto scan_switches_real init goto init_real ;----------------------------------------------- ; command functions - these do not need the _return label since they ; execute a goto send_command_5_real at their end ; ; this kludge code is needed since older PICs (like the one I'm using) ; can only call & return from the first 256 bytes (I think its 256) zoom_tele_fast goto zoom_tele_fast_real zoom_tele_slow goto zoom_tele_slow_real zoom_wide_fast goto zoom_wide_fast_real zoom_wide_slow goto zoom_wide_slow_real focus_close goto focus_close_real focus_far goto focus_far_real start_stop goto start_stop_real toggle_display goto toggle_display_real toggle_backlight goto toggle_backlight_real capture goto capture_real snap_still goto snap_still_real fader goto fader_real menu_toggle goto menu_toggle_real menu_select goto menu_select_real menu_up goto menu_up_real menu_down goto menu_down_real ;---------------------------------------------------------------------- ;wait_for_interframe routine ; when called will eat time waiting for a roughly 2 ms idle time on ; LANC - reads INPUT bit of PORTA ; uses counter counter2 wait_for_interframe_real sync_up movlw 3 movwf counter2 ; counter2 = 3 clrf counter ; counter = 0 sync_loop btfss PORTA, INPUT ;if lanc = 1, skip jump goto sync_up ; any lanc = 0 resets counters ; lanc == 1 to get here incfsz counter, 1 ; inc low byte of counter goto sync_loop ; skip jump if counter overflows to 0 decfsz counter2, 1 ; decrement counter2 goto sync_loop ; skip jump if --counter2 == 0 sync_ed retlw 0 ;return to caller ;-------------------------------------------------------------------- ; send_command_5 sends command in command_byte_1 and command_byte_2 ; the required 5 times. send_command_5_real bsf PORTA, SEND_COMM_LED ;turn on the 'sending command' LED ; movlw 1 ;for debugging... ; movwf command_pass ;debugging ; goto sc_done ;debugging movlw 5 movwf command_pass sc5_1 call wait_for_interframe ;------------------------------------------------------------------ ; send_command ; waits until bit INPUT of PORTA goes low, then delays ; 1 bit time minus a few cycles, then sends the byte in ; command_byte_1, then waits for INPUT to go low again, then ; sends byte in command_byte_2 ; uses: ; bit_counter, bits_to_send, byte_to_write, byte_number send_command movlw 2 movwf byte_number ;initialize outer loop counter movf command_byte_1, 0 movwf byte_to_write ;put command byte into byte_to_write sc_wait_for_LANC_start movlw TRIS_READ_LANC ; A0 = input, A1 = output tris PORTA sc_wfLs_1 btfsc PORTA, INPUT ;waiting for input port to drop - goto sc_wfLs_1 ;is start bit from camcorder movlw BIT_TIME - 1 ; @ 4 MHz movwf bit_counter sc_wfLs_2 ;each loop = 1.5 us @ 8MHz decfsz bit_counter, 1 goto sc_wfLs_2 sc_write_byte movlw 8 movwf bits_to_send movlw TRIS_WRITE_LANC ; A0 = input, A1 = output tris PORTA sc_write_bit movlw BIT_TIME ;34 loops @ 3 clocks @ 1us each @ 4mhz movwf bit_counter btfsc byte_to_write, 0 ;test bit 0 goto sc_wb_set_1 ;skipped if bit 0 = 0 bsf PORTA, OUTPUT ;clear output bit to 0 goto sc_wb_1 sc_wb_set_1 bcf PORTA, OUTPUT ;set output bit to 1 - sc_wb_1 decfsz bit_counter, 1 goto sc_wb_1 rrf byte_to_write, same decfsz bits_to_send, same goto sc_write_bit movlw TRIS_READ_LANC ; A0 = input, A1 = output tris PORTA decfsz byte_number, same goto sc_byte_2 goto sc_done sc_byte_2 movf command_byte_2, 0 movwf byte_to_write goto sc_wait_for_LANC_start sc_done decfsz command_pass, same goto sc5_1 bcf PORTA, SEND_COMM_LED ;turn off the sending comand LED retlw 0 ;---------------------------- ; zoom_wide_slow - fill command bytes with zoom out command - ; jump to send_command_5 zoom_wide_slow_real movlw 028h movwf command_byte_1 movlw 012h movwf command_byte_2 goto send_command_5_real ;---------------------------- ; zoom_wide_fast - fill command bytes with zoom out command - ; jump to send_command_5 zoom_wide_fast_real movlw 028h movwf command_byte_1 movlw 01ah movwf command_byte_2 goto send_command_5_real ;---------------------------- ; zoom_tele_slow - fill command bytes with zoom in command - ; jump to send_command_5 zoom_tele_slow_real movlw 028h movwf command_byte_1 movlw 002h movwf command_byte_2 goto send_command_5_real ;---------------------------- ; zoom_tele_fast - fill command bytes with zoom in command - ; jump to send_command_5 zoom_tele_fast_real movlw 028h movwf command_byte_1 movlw 00ah movwf command_byte_2 goto send_command_5_real ;---------------------------- ; focus_close - fill command bytes with focus closer command - ; jump to send_command_5 focus_close_real movlw 028h movwf command_byte_1 movlw 047h movwf command_byte_2 goto send_command_5_real ;---------------------------- ; focus_far - fill command bytes with focus farther command - ; jump to send_command_5 focus_far_real movlw 028h movwf command_byte_1 movlw 045h movwf command_byte_2 goto send_command_5_real ;---------------------------- ; start_stop - fill command bytes with start_stop in command - ; jump to send_command_5 start_stop_real movlw 018h movwf command_byte_1 movlw 033h movwf command_byte_2 goto send_command_5_real ;---------------------------- toggle_display_real movlw 018h movwf command_byte_1 movlw 0b4h movwf command_byte_2 goto send_command_5_real ;---------------------------- toggle_backlight_real movlw 028h movwf command_byte_1 movlw 051h movwf command_byte_2 goto send_command_5_real ;---------------------------- capture_real movlw 018h movwf command_byte_1 movlw 039h movwf command_byte_2 goto send_command_5_real ;---------------------------- snap_still_real movlw 018h movwf command_byte_1 movlw 02bh movwf command_byte_2 goto send_command_5_real ;---------------------------- fader_real movlw 028h movwf command_byte_1 movlw 025h movwf command_byte_2 goto send_command_5_real ;---------------------------- menu_toggle_real btfss menu_mode, 0 ;are we in menu mode now? goto turn_menu_mode_on ;not now bcf menu_mode, 0 bcf PORTA, MENU_MODE_LED goto send_menu_command turn_menu_mode_on bsf menu_mode, 0 bsf PORTA, MENU_MODE_LED send_menu_command movlw 018h movwf command_byte_1 movlw 09ah movwf command_byte_2 goto send_command_5_real ;---------------------------- menu_select_real movlw 018h movwf command_byte_1 movlw 0a2h movwf command_byte_2 goto send_command_5_real ;---------------------------- menu_up_real movlw 018h movwf command_byte_1 movlw 084h movwf command_byte_2 goto send_command_5_real ;---------------------------- menu_down_real movlw 018h movwf command_byte_1 movlw 086h movwf command_byte_2 goto send_command_5_real ;---------------------------- wakeup_command movlw 018h movwf command_byte_1 movlw 05eh movwf command_byte_2 goto send_command_5_real ;----------------------------------------------------------------------- init_real movlw TRIS_READ_LANC ; A0 = input, A2 = output, A1,3,4,5 input tris PORTA clrf PORTA ; clear output bits to 0 movlw TRIS_READ_SWITCHES tris PORTB movlw 0 ;all bits PORTC outputs tris PORTC clrf PORTC ;set to 0 clrwdt movlw 7 ;tmr0 prescale to 1:256 option clrf counter clrf counter2 clrf bit_counter clrf bits_to_send clrf byte_to_write clrf command_byte_1 clrf command_byte_2 clrf byte_number clrf command_pass clrf menu_mode clrf hat_up clrf hat_down clrf hat_left clrf hat_right clrf button_left clrf button_right clrf trigger clrf shift ;check_for_trigger - if pressed - send power-on command... btfsc PORTB, TRIGGER retlw 0 ;key not pressed goto wakeup_command ;---------------------------------------------------------------- scan_switches_real ; switch var values: 0 = not pressed ; 1 = was open, now pressed BIT 0 ; 2 = was pressed, still pressed BIT 1 ; 4 = was pressed, now clear BIT 2 t0 btfsc PORTB, HAT_UP goto t0_0 ;key not pressed t0_1 ;is pressed now btfsc hat_up, 1 ; was key previously pressed? goto t1 ;yes - no need for processing - goto next clrf hat_up bsf hat_up, 0 ; set hat_up to 1 goto t1 t0_0 ;is not pressed now btfss hat_up, 1 ;was pressed? goto t1 clrf hat_up bsf hat_up, 2 ;set hat_up to 4 - was pressed, now clear ;================================== t1 btfsc PORTB, HAT_DOWN goto t1_0 ;key not pressed t1_1 ;is pressed now btfsc hat_down, 1 ; was key previously pressed? goto t2 ;yes - no need for processing - goto next clrf hat_down bsf hat_down, 0 ; set hat_down to 1 goto t2 t1_0 ;is not pressed now btfss hat_down, 1 ;was pressed? goto t2 clrf hat_down bsf hat_down, 2 ;set hat_down to 4 - was pressed, now clear ;================================== t2 btfsc PORTB, HAT_LEFT goto t2_0 ;key not pressed t2_1 ;is pressed now btfsc hat_left, 1 ; was key previously pressed? goto t3 ;yes - no need for processing - goto next clrf hat_left bsf hat_left, 0 ; set hat_left to 1 goto t3 t2_0 ;is not pressed now btfss hat_left, 1 ;was pressed? goto t3 clrf hat_left bsf hat_left, 2 ;set hat_left to 4 - was pressed, now clear ;================================== t3 btfsc PORTB, HAT_RIGHT goto t3_0 ;key not pressed t3_1 ;is pressed now btfsc hat_right , 1 ; was key previously pressed? goto t4 ;yes - no need for processing - goto next clrf hat_right bsf hat_right, 0 ; set hat_ to 1 goto t4 t3_0 ;is not pressed now btfss hat_right, 1 ;was pressed? goto t4 clrf hat_right bsf hat_right, 2 ;set hat_right to 4 - was pressed, now clear ;================================== t4 btfsc PORTB, BUTTON_LEFT goto t4_0 ;key not pressed t4_1 ;is pressed now btfsc button_left , 1 ; was key previously pressed? goto t5 ;yes - no need for processing - goto next clrf button_left bsf button_left, 0 ; set button_left to 1 goto t5 t4_0 ;is not pressed now btfss button_left, 1 ;was pressed? goto t5 clrf button_left bsf button_left, 2 ;set button_left to 4 - was pressed, now clear ;================================== t5 btfsc PORTB, BUTTON_RIGHT goto t5_0 ;key not pressed t5_1 ;is pressed now btfsc button_right, 1 ; was key previously pressed? goto t6 ;yes - no need for processing - goto next clrf button_right bsf button_right, 0 ; set button_right to 1 goto t6 t5_0 ;is not pressed now btfss button_right, 1 ;was pressed? goto t6 clrf button_right bsf button_right, 2 ;set button_right to 4 - was pressed, now clear ;================================== t6 btfsc PORTB, TRIGGER goto t6_0 ;key not pressed t6_1 ;is pressed now btfsc trigger, 1 ; was key previously pressed? goto t7 ;yes - no need for processing - goto next clrf trigger bsf trigger, 0 ; set trigger to 1 goto t7 t6_0 ;is not pressed now btfss trigger, 1 ;was pressed? goto t7 clrf trigger bsf trigger, 2 ;set trigger to 4 - was pressed, now clear ;================================== ;shift is different - only need to know if it is down or up t7 btfsc PORTB, SHIFT goto t7_0 ;key not pressed bsf shift, 0 ; set shift to 1 bsf PORTA, SHIFT_LED ; turn on "shift" LED goto t8 t7_0 ;is not pressed now clrf shift bcf PORTA, SHIFT_LED ;turn off shift LED ;================================== t8 ;time to digest what we have... right now, will only do single command ; per press, so we only need to find key vars that are value 1 ; also should clear any that are set to 4 (may not need the rising edge, but ; am capturing it for now.... ; also, will only look for single buttons for now... (other than shift) ;+++++++++++++++++ p1 btfss hat_up, 0 goto p2 ;hat_up not pressed btfsc menu_mode, 0 ;are we in menu_mode? goto p1menu btfsc shift, 0 ;if shift pressed? goto p1shift call zoom_tele_slow p1exit clrf hat_up goto main p1shift call zoom_tele_fast goto p1exit p1menu call menu_up goto p1exit ;+++++++++++++++++ p2 btfss hat_down, 0 goto p3 ;hat_up not pressed btfsc menu_mode, 0 ;are we in menu_mode? goto p2menu btfsc shift, 0 ;if shift pressed? goto p2shift call zoom_wide_slow p2exit clrf hat_down goto main p2shift call zoom_wide_fast goto p2exit p2menu call menu_down goto p2exit ;+++++++++++++++++ p3 btfss hat_left, 0 goto p4 call focus_close clrf hat_left goto main ;+++++++++++++++++ p4 btfss hat_right, 0 goto p5 btfsc menu_mode, 0 ;are we in menu_mode? goto p4menu call focus_far p4exit clrf hat_right goto main p4menu call menu_select goto p4exit ;+++++++++++++++++ p5 btfss button_left, 2 goto p5a clrf button_left goto p6 p5a btfss button_left, 0 goto p6 btfsc shift, 0 ;if shift pressed? goto p5shift ; no - don't do s/s call fader p5out movlw 2 movwf button_left goto main p5shift call toggle_backlight goto p5out ;+++++++++++++++++ p6 btfss button_right, 2 goto p6a clrf button_right goto p7 p6a btfss button_right, 0 goto p7 btfsc shift, 0 ;if shift pressed? goto p6shift ; no - don't do s/s call toggle_display p6out movlw 2 movwf button_right goto main p6shift call start_stop goto p6out ;+++++++++++++++++ p7 btfss trigger, 2 ;was trigger pressed, but now clear? goto p7a clrf trigger ; in now released, clear and continue goto main p7a btfss trigger, 0 goto main btfsc shift, 0 ;if shift pressed? goto p7shift ; no - do unshifted_trigger call capture p7out movlw 2 movwf trigger goto main p7shift ; call snap_still ;rev 1 was this - but snap_still will run ; during record, then end record... bad... call menu_toggle goto p7out ;=================================================================== ;happy_dance ; let user know we're alive by winking shift and send command LEDS ; about 2HZ - return on any keypress ; happy_dance ;turn on send command to start bsf PORTA, SEND_COMM_LED ;turn on the 'sending command' LED movf PORTB, 0 ;get switches movwf bit_counter ;save it movlw .20 ;20 half-seconds (roughly) ;each TMR0 loop is 66ms x 7 ~ 460ms movwf counter ;run for 10 seconds or until button is pressed hd_inner movlw 7 movwf counter2 tw0 movf PORTB, 0 ;get switches in W subwf bit_counter, 0 ;sub - result in W btfss STATUS,2 ;if != 0 , switch pressed goto happy_exit movf TMR0, 0 ;get timer btfss STATUS,2 goto tw0 ;wait for tmr0 to = 0 tw1 movf PORTB, 0 ;get switches in W subwf bit_counter, 0 ;sub - result in W btfss STATUS,2 ;if != 0 , switch pressed goto happy_exit movf TMR0, 0 ;get timer btfsc STATUS,2 goto tw1 ;wait for tmr0 to != 0 decfsz counter2, same goto tw0 ;toggle LEDS movlw 0ch ;flip bits 2 & 3 xorwf PORTA, same decfsz counter, same goto hd_inner happy_exit bcf PORTA, SHIFT_LED bcf PORTA, SEND_COMM_LED clrf counter clrf counter2 clrf bit_counter goto main MESSAGE_LEN equ .42 ORG 1ff - MESSAGE_LEN - 4 de "Ed's LANC Grip controller rev 2 (c) 1999" ;-------------------------------------------------------------------- ORG PIC55 goto top END