; ; ; Code for the 12F675 PIC based Servo Controlled Camera Switch. ; SCCS: @(#) ssw.asm 1.6@(#) processor 12F675 radix dec errorlevel -302 ; ; This module is configurable for a number of different combinations of ; facilities. ; ; It is *your* responsibility to ensure that the configuration parameters set ; in the code below match your components and features required. ; ; The options are: ; ; FIXED - selects fixed (ie. non configurable mode) ; set FIXED to 0 for the configurable mode ; set FIXED to 1 for the non-configurable mode ; *NOTE* when you set FIXED to 1 you also need ; to ensure the fixed mode parameters below are ; set correctly ; ; SERVOOUT - selects the output to be via a servo. ; set SERVOOUT to 0 for an open-collector output ; drive that is suitable for Aiptek/Jazz etc. ; set SERVOOUT to 1 for servo pulse output ; ; LEDOUT - selects whether there is an output LED or not ; set LEDOUT to 0 to disable the LED drive ; set LEDOUT to 1 to enable the LED drive ; FIXED equ 0 SERVOOUT equ 1 LEDOUT equ 1 ; ; If fixed (ie. non-configurable) mode is selected then ; these are the parameters that will apply. ; These are correct for the Jazz camera with non-servo ; output. (ie. FIXED == 1, SERVOOUT == 0) if FIXED fix_servoidle equ 1500 ; Servo idle position fix_servofocus equ 1500 ; Servo focus position fix_servoshutter equ 1500 ; Servo shutter position fix_timefocus equ 0 ; Time for focuusing fix_timeshutter equ 2 ; Time for the shutter fix_timepost equ 10 ; Time post shutter fix_timekalive equ 55 ; Camera keep-alive time fix_inputidle equ 1500 ; Input position for idle fix_inputshutter equ 1800 ; Input position for shutter fix_inputpoweroff equ 1800 ; Input position for power off fix_timepoweroff equ 10 ; Time to power off endif ; ; In configurable mode these defaults are loaded into ; the PIC's EEDATA area during programming so that ; the PIC starts with 'sensible' values. if !FIXED ini_servoidle equ 1500 ; Servo idle position ini_servofocus equ 1500 ; Servo focus position ini_servoshutter equ 1750 ; Servo shutter position ini_timefocus equ 0 ; Time for focuusing ini_timeshutter equ 5 ; Time for the shutter ini_timepost equ 10 ; Time post shutter ini_timekalive equ 55 ; Camera keep-alive time ini_inputidle equ 1500 ; Input position for idle ini_inputshutter equ 1800 ; Input position for shutter ini_inputpoweroff equ 1200 ; Input position for power off ini_timepoweroff equ 10 ; Time to power off endif ; ; Assumes: ; Bandgap as calibrated at factory ; CPD disabled ; CP disabled ; BODEN enabled ; MCLR disabled ; PWRTE enabled ; WDT (Watchdog) enabled ; OSC internal RC (no clockout) ; ; The basic circuit for the switch is as follows, this is *not* ; the complete circuit and the associated Web documentation should ; be consulted for the full circuit diagram. ; ; ; power ----------------------- ; | | ; ----------------- ; | + (1) (8) - | ; | PIC12F675 | ; | | ; rx | (3) GP4 |-<- ; >--XXXX-------| GP1 (6) | | (active low rx pulse) ; 4k7 | (5) GP2 |->- ; | | ; | | ; | (2) GP5 | ----------> LED ;Switch >----| GP3 (4) | ; | (7) GP0 | ----------> Servo Out ; ----------------- ; ; ; Features of this software are as follows: ; ; Watchdog timer ensure the software is running, this is used to ensure ; that the software always gets back to the main sensing code. If ; it doesn't the chip is reset. ; ; Timer 0 is used to measure the elapsed time. ; ; This timer runs at 1Mhz with a 1:2 prescaler and is used to ; run a 2kHz timer channel. ; ; Timer 1 is used to measure the input pulse width. Pulse width should be ; 1.5msec nominal at central position +/- 0.5msec depending on the ; control direction. ; ; At 4Mhz clock timer 1 will run at 0.001msec count rate. This gives ; count values for 1.5msec that are well within 16-bit resolution. ; ; Timer 1 is also used to measure the output pulse width for servo ; control. ; #include __CONFIG(_BODEN_ON & _MCLRE_OFF & _PWRTE_ON & _WDT_ON & _INTRC_OSC_NOCLKOUT) ; Main parameters autopulse equ 5 ; Required number 'same value' to program autofuzz equ 3 ; +/- autofuzz is the same value framems equ 25 ; servo control frame rate debounce equ 10 ; Jumper debounce time in 20msec increments lostime equ 20 ; LOS time in 'framems' increments ncfgitems equ 11 ; The number of configuration items stickAat equ 1500-125 ; Position A is < this stickBat equ 1500+125 ; Position B is > this ; GPIO register bits and other constants inrxraw equ 1 ; Active high servo input signal outrxinv equ 2 ; Active low receiver output (inverted inrxraw) inrxbit equ 4 ; Active low rx input always on GP4 videoswitch equ 3 ; Video mode command switch on GP3 outservo equ 0 ; Servo drive for shutter operation outled equ 5 ; LED drive for flashing signals ; Timer 0 operates at 2kHz rate for timing purposes T0rate equ 2000 ; 2000 interrupts per second T0cnt equ ((1000000+T0rate/2) / T0rate + 1)/2 ; EEPROM Data offsets cblock 0 eep_sidle:3 ; Servo Idle Position and check digit eep_sfocus:3 ; Servo Focus Position and check digit eep_sshutter:3 ; Servo Shutter Position and check digit eep_tfocus:2 ; Focus time eep_tshutter:2 ; Shutter time eep_tpost:2 ; Post shutter tim eep_tkalive:2 ; Keep alive time eep_iidle:3 ; Input Idle Position eep_ishutter:3 ; Input Shutter Position eep_ipoweroff:3 ; Input Power off Position eep_tpoweroff:2 ; Power off time endc ; Initialise the EEDATA if we are a configurable version if !FIXED eedata16 macro eep, val org 2100h+eep de low val de high val de (low val) ^ (high val) endm eedata8 macro eep, val org 2100h+eep de val de ~val endm eedata16 eep_sidle, ini_servoidle eedata16 eep_sfocus, ini_servofocus eedata16 eep_sshutter, ini_servoshutter eedata8 eep_tfocus, ini_timefocus eedata8 eep_tshutter, ini_timeshutter eedata8 eep_tpost, ini_timepost eedata8 eep_tkalive, ini_timekalive eedata16 eep_iidle, ini_inputidle eedata16 eep_ishutter, ini_inputshutter eedata16 eep_ipoweroff, ini_inputpoweroff eedata8 eep_tpoweroff, ini_timepoweroff endif ; RAM Definitions cblock 20h w_save ; Int save: !! Both banks used !! sts_save ; int_p1sec ; Used for 0.1sec timing by interrupts int_1sec ; Used for 1sec timing by interrupt ; ---- These are the working copies of ; the EEPROM data. In addition enough ; bits are maintained for the status ; on the configuration variables. cfg_faultyA ; Faulty config items cfg_faultyB cfg_servoidleL ; Servo idle position cfg_servoidleH cfg_servofocusL ; Servo focus position cfg_servofocusH cfg_servoshutterL ; Servo shutter position cfg_servoshutterH cfg_timefocus ; Time for focuusing cfg_timeshutter ; Time for the shutter cfg_timepost ; Time post shutter cfg_timekalive ; Camera keep-alive time cfg_inputidleL ; Input position for idle cfg_inputidleH cfg_inputshutterL ; Input position for shutter cfg_inputshutterH cfg_inputpoweroffL ; Input position for power off cfg_inputpoweroffH cfg_timepoweroff ; Time to power off ; ---- Status information istatus ; Input signal status information (is_*) rxstatus ; Radio Control input status gpioout ; Current GPIO output values trigger_icnt ; Trigger operation counter... (0.1sec) kalive_icnt ; Keep alive counter (1sec) endc ; Possible istatus bits is_programmode equ 0 ; Program mode selected on power up is_idlelt equ 1 ; Idle is when input LT cfg_inputidle:16 is_powerofflt equ 2 ; Poweroff is when input LT cfg_inputpoweroff:16 is_nokeepalive equ 3 ; Keepalive has been turned off is_wnoshutter equ 4 ; Wait for the no shutter state is_videoon equ 5 ; We think the camera is running in video is_doubleka equ 6 ; Double keep-alive for video mode ; Possible rxstatus bits rx_timeout equ 0 ; Frame timeout in RX signal rx_rshutter equ 1 ; Signal is in shutter position now rx_rpoweroff equ 2 ; Signal is in poweroff position now rx_flos equ 3 ; Signal is filtered in LOS rx_fshutter equ 4 ; Signal is filtered in shutter posn rx_fpoweroff equ 5 ; Signal is filtered in power off posn ; ; Reset vector org 0000h goto start ; ; Interupt vector ; ; The interrupt routine. Monitors the passage of time... org 0004h ; Save the state (see page 64 of PIC12F675 data) movwf w_save ; Save W register swapf STATUS,W ; Save status (don't touch flags) banksel sts_save ; Back to bank 0 movwf sts_save ; Clear the timer interrupt, and reload counter. Use addition ; to preserve interrupt rate even if interrupts are off for a while movlw -T0cnt addwf TMR0,F bcf INTCON, T0IF ; Now perform the processing of the interrupt ; - Timer for LED flashing decf flash_icnt,F ; LED flash timer ; - Timer for receiver frame rate and LOS decfsz rxfrmtL,F ; frame monitor timer goto srvtmr1 decf rxfrmtH,F srvtmr1 ; - Timers based on 0.1sec increments decfsz int_p1sec,F goto exitint ; Not a 0.1 sec boundary yet movlw T0rate / 10 movwf int_p1sec ; Reinitialise for 10 Hz rate ; - - The shutter drive counter (in 0.1sec) movfw trigger_icnt btfss STATUS,Z decf trigger_icnt,F ; - Timers based on 1sec increments decfsz int_1sec,F goto exitint ; Not a 1 sec boundary yet movlw 10 movwf int_1sec ; Reinitialise for 1Hz rate ; - - The power off counter (in seconds) movfw powerofficnt btfss STATUS,Z decf powerofficnt,F ; - - Keep alive counter (in seconds) movfw kalive_icnt btfss STATUS,Z decf kalive_icnt,F ; All done, restore status exitint swapf sts_save,w movwf STATUS swapf w_save,f swapf w_save,w retfie ; Record the information we need, we want this to appear in ic_prog on an ; 8 word boundary so that it is clearly visible ; The source version information, and the circuit type while ($ & 7) != 0 dt " " endw dt "ssw.asm" ; Source information while ($ & 7) != 0 dt " " endw dt "V1.6" ; Source information while ($ & 7) != 0 dt " " endw ; -------------------------- Main code ---------------------- ; ; Chip reset, or similar, operation. start ; Calibrate the internal oscilator banksel OSCCAL call 3FFh movwf OSCCAL banksel GPIO ; Default to output driven low when enabled clrf GPIO ; Configure the analog input bits, and the comparator that ; is used as an inverter, so that the control signal can control TMR1 ; Note: don't configure WPU on inrxbit as this will cause unreliable ; input pulse detection due to the 4k7 resistor between COUT and the ; !T1G input. banksel ANSEL movlw 00110000b | (1<= 2.303 msec signal pulse is faulty subwf TMR1H,W btfsc STATUS,C goto toolong btfss GPIO,inrxbit goto whileon ; Stop timer so we can convert things clrf T1CON ; Now the pulse has ended and we are ready to consider the outcome of this... ; First drop pulses that are too small to be valid, these must be an error... movlw 3 subwf TMR1H,W btfss STATUS,C goto apulselp ; < 0.768msec return ; A pulse > 2.560msec is present, wait for it to end and ignore it toolong call checktime btfsc rxstatus,rx_timeout return btfss GPIO,inrxbit goto toolong goto apulselp ; Watch for timeout, this routine is called about once every 12 cycles, ; and checks the frame counter timeout decremented in the ISR. ; The watchdog is cleared so that if the PIC doesn't get back to ; processing the next receiver pulse in 18msec the chip resets... ; checktime clrwdt ; track software is working... btfsc rxfrmtH,7 bsf rxstatus,rx_timeout ; Flag end of time return ; ; --------------- Supply fixed parameters -------------------- if FIXED recall movlw low fix_servoidle movwf cfg_servoidleL movlw high fix_servoidle movwf cfg_servoidleH movlw low fix_servofocus movwf cfg_servofocusL movlw high fix_servofocus movwf cfg_servofocusH movlw low fix_servoshutter movwf cfg_servoshutterL movlw high fix_servoshutter movwf cfg_servoshutterH movlw fix_timefocus movwf cfg_timefocus movlw fix_timeshutter movwf cfg_timeshutter movlw fix_timepost movwf cfg_timepost movlw fix_timekalive movwf cfg_timekalive movlw low fix_inputidle movwf cfg_inputidleL movlw high fix_inputidle movwf cfg_inputidleH movlw low fix_inputshutter movwf cfg_inputshutterL movlw high fix_inputshutter movwf cfg_inputshutterH movlw low fix_inputpoweroff movwf cfg_inputpoweroffL movlw high fix_inputpoweroff movwf cfg_inputpoweroffH movlw fix_timepoweroff movwf cfg_timepoweroff return endif ; ; --------------- Manage the operation of the EEPROM ------------- ; if !FIXED cblock eep_rom ; ROM address endc markflt macro id if id <= 8 bsf cfg_faultyA, id-1 else bsf cfg_faultyB, id-9 endif endm read_16bit macro id, rom, ram movlw ram movwf FSR movlw rom call read_ees16 btfss STATUS,Z markflt id endm read_8bit macro id, rom, ram movlw ram movwf FSR movlw rom call read_ee8 btfss STATUS,Z markflt id endm write_16bit macro id, rom, ram movlw ram movwf FSR movlw rom call write_ee16 endm write_8bit macro id, rom, ram movlw ram movwf FSR movlw rom call write_ee8 endm ; Recall all the EEPROM data and perform the data integrity ; checks on what is in the EEPROM recall ; Parameter 1: Servo Idle Position read_16bit 1, eep_sidle, cfg_servoidleL ; Parameter 2: Servo Focus Position read_16bit 2, eep_sfocus, cfg_servofocusL ; Parameter 3: Servo Shutter Position read_16bit 3, eep_sshutter, cfg_servoshutterL ; Parameter 4: Focus time read_8bit 4, eep_tfocus, cfg_timefocus ; Parameter 5: Shutter time read_8bit 5, eep_tshutter, cfg_timeshutter ; Parameter 6: Post shutter time read_8bit 6, eep_tpost, cfg_timepost ; Parameter 7: Keep-alive read_8bit 7, eep_tkalive, cfg_timekalive ; Parameter 8: Input position for idle read_16bit 8, eep_iidle, cfg_inputidleL ; Parameter 9: Input position for shutter read_16bit 9, eep_ishutter, cfg_inputshutterL ; Parameter 10: Input for power off read_16bit 10,eep_ipoweroff, cfg_inputpoweroffL ; Parameter 11: Time for power off read_8bit 11,eep_tpoweroff, cfg_timepoweroff return ; Read an 8-bit time value... ; FSR is the address to put it into ; W is the eeprom offset ; returns Z on OK, NZ on fail read_ee8 movwf eep_rom call read_eep movwf INDF incf eep_rom,W call read_eep xorwf INDF,W xorlw 0FFh btfsc STATUS,Z return clrf INDF ; Supply a default of zero bcf STATUS,Z ; force NZ status return ; Read a 16-bit servo position... ; FSR is the address to put it into ; W is the eeprom offset ; returns Z on OK, NZ on fail read_ees16 movwf eep_rom call read_eep movwf INDF incf FSR,F incf eep_rom,F movfw eep_rom call read_eep movwf INDF incf eep_rom,W call read_eep xorwf INDF,W decf FSR,F xorwf INDF,W btfsc STATUS,Z return movlw low 1500 ; Supply a default parameter movwf INDF incf FSR,F ; Note: leaves status NZ for return movlw high 1500 movwf INDF return ; Read the location in the W register into the W register read_eep banksel EEADR movwf EEADR bsf EECON1,RD movfw EEDATA banksel w_save return ; ; Write a 16 bit value with checksum to the storage ; FSR is the data address ; W is the EEPROM address write_ee16 movwf eep_rom call write_eepa movfw INDF call write_eepd incf eep_rom,F incf FSR,F movfw eep_rom call write_eepa movfw INDF call write_eepd incf eep_rom,W call write_eepa movfw INDF decf FSR,F xorwf INDF,W goto write_eepd write_ee8 movwf eep_rom call write_eepa movfw INDF call write_eepd incf eep_rom,W call write_eepa comf INDF,W goto write_eepd ; Select the EEPROM address we are going to write to ; W is the address write_eepa banksel EEADR bsf EECON1,WREN movwf EEADR banksel w_save return ; Write the contents of W to the EEPROM, ; Z status -> written OK write_eepd bcf INTCON,GIE banksel EEDATA movwf EEDATA movlw 55h movwf EECON2 movlw 0AAh movwf EECON2 bsf EECON1,WR banksel PIR1 eepwlp clrwdt btfss PIR1,EEIF goto eepwlp bcf PIR1,EEIF banksel EEDATA movfw EEDATA bcf EECON1,WREN bsf EECON1,RD xorwf EEDATA,W banksel w_save bsf INTCON,GIE return endif ; ; -------- Output servo drive ------------ ; cblock servoL ; Desired servo position in usec servoH endc if SERVOOUT ; Pulse the output servo pin high for the currently selected servo ; position. This uses timer 1 in manual count mode to perform the ; best timing we can with timer 0 in use for interrupts. ; Interrupts are disabled for at most 128 usec. ; Note that the output pulse will be a small number of usec greater ; than the select input value. However, this doesn't matter because it ; can be adjusted out via the adjustment stuff anyway. driveservo bcf INTCON,GIE ; Disable interrupts while we start timer ; Enable Timer 1 for counting clrf T1CON ; Ensure the timer is not counting comf servoL,W ; Initialise the register with -servo position movwf TMR1L ; no need to add 1 +/1 1usec can be adjusted comf servoH,W movwf TMR1H ; Turn on the servo output movfw gpioout iorlw 1< 3 mod 4 TCY ; 1 -> 2 mod 4 TCY ; 2 -> 1 mod 4 TCY ; 3 -> 0 mod 4 TCY movfw TMR1L andlw 03h ; find out where we are in the cycle mod 4 Tcy btfsc STATUS,Z goto ds_w3 ; 0 -> 3 TCY addlw -1 btfsc STATUS,Z goto ds_w3 ; 1 -> 6 TCY (2 mod 4) addlw -1 btfsc STATUS,Z goto ds_w3 ; 2 -> 9 TCY (1 mod 4) ; FALLTHROUGH ; 3 -> 8 TCY (0 mod 4) goto $+1 goto $+1 ds_w3 nop ; force this loop to 4 Tcy in length btfsc TMR1H,7 goto ds_w3 ; Clobber output movfw gpioout movwf GPIO ; Enable interrupts bsf INTCON,GIE ; Disable timer 1 clrf T1CON cameratoggle return else ; ; Copy the GPIO status to the output pins driveservo movfw gpioout movwf GPIO return ; ; Toggle the camera output cameratoggle banksel TRISIO movlw 1<= 0x300 sublw 2 btfss STATUS,C goto prg_eos1 ; All ok goto prg_eosB ; Add one count back ; User has signaled that the edit is complete, ; save the current output servo position in FLASH prg_oservodone movfw servoH ; Copy the servo:16 value back to correct place movwf INDF decf FSR,F movfw servoL movwf INDF movfw cfg_servoidleL ; Restore servo to idle position movwf servoL movfw cfg_servoidleH movwf servoH goto prg_editok ; ; Input servo edit just allows you to position the control stick ; in the appropriate place prg_editiservo flashon 0 prg_eis1 call iflasher btfss GPIO,videoswitch goto prg_iservodone goto prg_eis1 ; Save the input position prg_iservodone btfsc rxstatus, rx_timeout goto prg_editok movfw TMR1L ; Copy the TMR1:16 value back to correct place movwf INDF incf FSR,F movfw TMR1H movwf INDF goto prg_editok ; ; Numeric entry flashes the current number and then uses ; fstickA to decrement the number and fstickB to increment the number prg_editnumber movlw 99 call prg_getnumber ; Save the number we have been editing prg_editok ledoff ; Turn off the LED call prg_editdone ; Complete and save data call prg_videowait ; Wait for jumper to be removed goto prg_mainlp ; All done ; ; Edit the value pointed to by FSR as an integer. ; Permitted values are 0 .. W cblock prg_gnlimit ; Maximum permitted value prg_gnten ; Number of tens prg_gnone ; Number of ones gnstatus ; status of this routine endc gn_ipause equ 0 ; We have done the initial pause gn_tendigit equ 1 ; Shown tens gn_tenpause equ 2 ; Done inter-digit pause prg_getnumber ; Remember the limit movwf prg_gnlimit prg_gnloop clrf gnstatus ; Divide into the 10s and the 1s.... clrf prg_gnten clrf prg_gnone movfw INDF btfsc STATUS,Z goto prg_gnnext ; Special case for zero... ; We need to count it out... movwf prg_count prg_gnlp1 incf prg_gnone,F movfw prg_gnone xorlw 10 btfss STATUS,Z goto prg_gnlp2 incf prg_gnten,F clrf prg_gnone prg_gnlp2 decfsz prg_count,F goto prg_gnlp1 prg_gnnext ; Decide what to do next btfsc gnstatus, gn_ipause goto prg_gn_ipause ; perform the initial pause bsf gnstatus, gn_ipause flashof 10 prg_gn_1flash movlw 1 movwf prg_count goto prg_gnflash prg_gn_ipause btfsc gnstatus, gn_tendigit goto prg_gn_tendigit ; display the tens digit bsf gnstatus, gn_tendigit movfw prg_gnten btfsc STATUS,Z goto prg_gn_tenpause prg_gn_adigit movwf prg_count addwf prg_count,F flashon 2 goto prg_gnflash prg_gn_tendigit btfsc gnstatus, gn_tenpause goto prg_gn_tenpause ; Display the tens pause bsf gnstatus, gn_tenpause flashof 6 goto prg_gn_1flash prg_gn_tenpause clrf gnstatus ; The next thing is to pause and start again ; Display the number of ones movfw prg_gnone btfss STATUS,Z goto prg_gn_adigit ; Display zero flashon 6 goto prg_gn_1flash prg_gnflash call iflasher btfss GPIO,videoswitch return btfsc pstatus,ps_fstickA goto prg_gnfA btfsc pstatus,ps_fstickB goto prg_gnfB btfss pstatus,ps_flshdone goto prg_gnflash ; Done the flash decf prg_count,F btfsc STATUS,Z goto prg_gnnext ; Do the next bit... btfsc gpioout,outled goto prg_gnfoff flashon 2 goto prg_gnflash prg_gnfoff flashof 2 goto prg_gnflash ; Stick A in decrements the config item number prg_gnfA decf INDF,F comf INDF,W btfss STATUS,Z goto prg_gnfAB movfw prg_gnlimit movwf INDF goto prg_gnfAB ; Stick B in increments the config item number prg_gnfB incf INDF,F movfw INDF subwf prg_gnlimit,W btfss STATUS,C clrf INDF prg_gnfAB call prg_centrewait goto prg_gnloop ; Force this code into the last page so ; that all the computed gotos will function if $ < 0300h org 0300h endif ; ; Initialise for the start of editing prg_editsetup clrf estatus ; Zap edit status movlw high prg_editsetup movwf PCLATH movfw prg_itemno addwf PCL,F goto emptyreturn ; 0 - do nothing... goto prg_es1 ; 1 goto prg_es2 ; 2 goto prg_es3 ; 3 goto prg_es4 ; 4 goto prg_es5 ; 5 goto prg_es6 ; 6 goto prg_es7 ; 7 goto prg_es8 ; 8 goto prg_es9 ; 9 goto prg_es10 ; 10 goto prg_es11 ; 11 ; parameter 1 prg_es1 movlw cfg_servoidleL prg_esosrvo movwf FSR ; Remember where this came from... bsf estatus,es_editoservo return ; Setup parameter 2 prg_es2 movlw cfg_servofocusL goto prg_esosrvo ; Setup paramater 3 prg_es3 movlw cfg_servoshutterL goto prg_esosrvo ; Setup parameter 4 prg_es4 movlw cfg_timefocus prg_esnumber movwf FSR bsf estatus,es_editnumber return ; Setup parameter 5 prg_es5 movlw cfg_timeshutter goto prg_esnumber ; Setup parameter 6 prg_es6 movlw cfg_timepost goto prg_esnumber ; Setup parameter 7 prg_es7 movlw cfg_timekalive goto prg_esnumber ; Setup parameter 8 prg_es8 movlw cfg_inputidleL prg_esiservo movwf FSR bsf estatus,es_editiservo return ; Setup parameter 9 prg_es9 movlw cfg_inputshutterL goto prg_esiservo ; Setup parameter 10 prg_es10 movlw cfg_inputpoweroffL goto prg_esiservo ; Setup parameter 11 prg_es11 movlw cfg_timepoweroff goto prg_esnumber ; ; Completion of editing prg_editdone decf prg_itemno,W addwf PCL,F goto prg_ed1 ; 1 goto prg_ed2 ; 2 goto prg_ed3 ; 3 goto prg_ed4 ; 4 goto prg_ed5 ; 5 goto prg_ed6 ; 6 goto prg_ed7 ; 7 goto prg_ed8 ; 8 goto prg_ed9 ; 9 goto prg_ed10 ; 10 goto prg_ed11 ; 11 ; Save parameter 1 prg_ed1 write_16bit 1, eep_sidle, cfg_servoidleL return ; Save parameter 2 prg_ed2 write_16bit 2, eep_sfocus, cfg_servofocusL return ; Save parameter 3 prg_ed3 write_16bit 3, eep_sshutter, cfg_servoshutterL return ; Save parameter 4 prg_ed4 write_8bit 4, eep_tfocus, cfg_timefocus return ; Save parameter 5 prg_ed5 write_8bit 5, eep_tshutter, cfg_timeshutter return ; Save parameter 6 prg_ed6 write_8bit 6, eep_tpost, cfg_timepost return ; Save parameter 7 prg_ed7 write_8bit 7, eep_tkalive, cfg_timekalive return ; Save parameter 8 prg_ed8 write_16bit 8, eep_iidle, cfg_inputidleL return ; Save parameter 9 prg_ed9 write_16bit 9, eep_ishutter, cfg_inputshutterL return ; Save parameter 10 prg_ed10 write_16bit 10,eep_ipoweroff, cfg_inputpoweroffL return ; Save parameter 11 prg_ed11 write_8bit 11,eep_tpoweroff, cfg_timepoweroff return ; ; -------- Fault configuration has occured ------- ; ; The configuration is faulty, so flash the fault code ; this is a sequence of short/long flashes, short ; flashes for OK and long flashes for fault... flash_faulty ; Show the fault status for all known config items i = 1 while i <= ncfgitems if i <= 8 movlw 1<<(i-1) call ffaultA else movlw 1<<(i-9) call ffaultB endif i = i + 1 endw flashof 12 ; Then a long delay fflt_l1 call flasher ; Update the LED flash, come back in ??msec btfss pstatus,ps_flshdone goto fflt_l1 goto flash_faulty ; And start again ; Test the value in cfg_faultA ffaultA andwf cfg_faultyA,W goto ffault ffaultB andwf cfg_faultyB,W ffault btfss STATUS,Z goto faulty flashon 2 ; OK so a short flash goto ffault1 faulty flashon 6 ffault1 call flasher btfss pstatus,ps_flshdone goto ffault1 flashof 2 ; And a pause ffault2 call flasher btfss pstatus,ps_flshdone goto ffault2 return endif end