;============================================== ; ; Nikon D70 infra-red remote shutter control ; using the PIC12F675 ; ; (C) 2005 Jan Wagner ; ;============================================== ; Code info: ; ; Compiles with Microchip's free MPLAB IDE, www.microchip.com ; ; Uses the PIC12F675 (PIC12F629 should work too) list p=12f675 include "P12F675.INC" radix dec ; config: ; !MCLR pin off, no code-protect, watchdog off ; internal 4MHz clock with no output (for debug: _INTRC_OSC_CLKOUT, ; scope 1MHz signal on pin 3) ; power-up timer (72ms) on (important for power ; switch debounce!) ; brownout detect on (for additional power switch debounce, but, you ; might also disable this to conserve power) __CONFIG _MCLRE_OFF & _INTRC_OSC_NOCLKOUT & _CP_OFF & _CPD_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON ;------------- ISR VECTORS org 0x000 ; startup goto main org 0x004 ; interrupt service retfie ;------------- VARS : variables into file register bank cblock 0x20 ; (bank 0 0x20-0x5f are free for use) pulsecntr ; 0x20 counter for main pulses (pulselen = 25us * pulsecounter) waitcntr ; 0x21 counter for pauses (pauselen = 25us * waitcntr * pulsecntr) waittmp ; 0x22 temporary storage for waitcntr maincntr ; 0x23 how many times the sequence has been sent endc LED_BIT equ 2 ; IR LED placed on pin 5 (GP2) ;------------- FUNCTIONS ; ; Function doLedToggling ; ; IR LED toggler, toggle once at 40kHz i.e. with 25us period ; ; Input: W contains counter (>0) with the number of toggles ; to perform ; Return: nothing ; Time: W*25us + 2us ; doLedToggling movwf pulsecntr ; store argument W into pulsecounter doLedToggLoop ; ON for 13us bsf GPIO,LED_BIT ; 1/13us GPx high to enable IR LED nop ; 2/13us just use NOPs instead of complicated loop, nop ; might even be a bit less powerhungry nop nop ; 5/13us nop nop nop nop nop ; 10/13us nop nop nop ; 13/13us ; OFF for 12us total bcf GPIO,LED_BIT ; 1/12us GPx low to disable IR LED nop ; 2/12us nop nop nop ; 5/12us nop nop nop nop ; 9/12us decfsz pulsecntr,F ; 10/12us (or +2us on exit) goto doLedToggLoop ; 11&12/12us (+2us) return ; (+2us) ; ; Function do25usPauses ; ; Do a longer pause, duration is approximately in multiples of 25us ; ; Input: W contains outer counter ('pulsecounter'), >0 ; waitcntr contains inner counter, >0 ; ; Return: nothing ; Time: (25us*waitcntr + 3us)*W + 4us ; do25usPauses movwf pulsecntr ; store argument W into pulsecounter movf waitcntr,W ; load waitcntr argument to W movwf waittmp ; place waitcntr into actual temp counter do25outer do25inner ; delay for 25us nop nop nop nop nop ; 5us nop nop nop nop nop ; 10us nop nop nop nop nop ; 15us nop nop nop nop nop ; 20us nop nop ; 22us decfsz waittmp,F ; +1us (+2us on end) goto do25inner ; +2us movwf waittmp ; put back waitcntr into actual counter ; (also +1us on end so condition check always takes 3us) decfsz pulsecntr,F goto do25outer return ;------------- MAIN main clrwdt ; init GPIO pins (PIC12F675 - disable analog inputs) bcf STATUS,RP0 ; bank 0 (GPIO) clrf GPIO ; init GPIO state to 0 movlw 07h ; GP<0:2> to digital IO movwf CMCON ; comparator off bsf STATUS,RP0 ; bank 1 (ANSEL,TRISIO) clrf ANSEL ; digital IO only, no analog clrf TRISIO ; all pins as output ; read the oscillator calibration data (datasheet, example 9-1) ; (part of last mem localtion 0x3FF, is for example 0x34B4) bsf STATUS, RP0 ; bank 1 (OSCCAL) call 3FFh ; get cal value movwf OSCCAL ; calibrate ; initialize for entire sequence bcf STATUS,RP0 ; bank 0 (GPIO) initOneFullSeq movlw 2 ; send same sequence twice movwf maincntr performSequences decfsz maincntr,W ; if maincntr==1, do a longer pause goto doOneSeq ; skip pause, send directly ; long pause of 63000us between first and second time sending ; (25us*waitcntr + 3us)*W + 4us : (25*15+3)*167+4=63130us movlw 15 movwf waitcntr movlw 167 call do25usPauses ; send the sequence ; ON 2250us = 90 * 25us doOneSeq movlw 90 call doLedToggling ; Off 27600us-(ON call 3us + w/f 3us + OFF call 2us)=27592us ; (25us*waitcntr + 3us)*W + 4us : (25*15+3)*73+4=27598 movlw 15 movwf waitcntr movlw 73 call do25usPauses ; ON 650us = 26 * 25us movlw 26 call doLedToggling ; Off 1375us-(3us+3us+2us)=1367us : (25*18+3)*3+4=1363 movlw 18 movwf waitcntr movlw 3 call do25usPauses ; ON 575us = 21 * 25us movlw 21 call doLedToggling ; Off 3350us-(3us+3us+2us)=3342us : (25*2+3)*63+4=3343 movlw 2 movwf waitcntr movlw 63 call do25usPauses ; ON 650us = 26 * 25us movlw 26 call doLedToggling decfsz maincntr,F goto performSequences ; to completely stop: sleep ; or, to run in continuos shooting mode, do ; first a quite long pause... ;movlw 20 ;movwf waitcntr ;movlw 167 ;call do25usPauses ; ...and then restart ;goto initOneFullSeq end |