; ********************************************************* ; LED Strobe ; ; Author: Pete Griffiths ; Date: June 2004 ; ; Latest release ; ; filename: ledstrobe-f.asm ; date: 1 April 2009. ; ; Changes: ; 1. Timing data moved to EEPROM to make customised time settings easier ; 2. If OSSCAL value is missing, code blinks LEDs to indicate error ; 3. Basic validation check on the EEPROM to test for corrupt data ; 4. other functionality remains the same. ; ; ; PIC generates a single or double output pulse at one of four ; user selectable repeat rates set by input on R0/R1 (pin 6/7). ; Pulse Width (PW) period is determined by the digital input applied ; GP4 (pin 3). ; Ouput is presented on GP2 (pin 5) and an inverted output is on GP5 (pin 2) ; Single / Double pulse is selected by digital input on GP3 (pin 4). ; ; Output can drive any LED but for the best strobe effect use a High Brightness ; LED with suitable current limiting resistor, or for more power drive the LED ; via a transistor or MOSFET. ; ; Pin functions for PIC 12F675 LED strobe ; Vdd -|1 8|- Vss ; ^Qout -|2 7|- R0 (internal weak pull-up enabled) ; PW -|3 6|- R1 (internal weak pull-up enabled) ; S/D -|4 5|- Qout ; ; ; Timing select input logic levels and default timings. ; (these timings can be altered by editing the TIMING DATA in next section) ; ; R1 R0 (Repeat rate) ; 0 0 1S ; 0 1 2S ; 1 0 3S ; 1 1 4S ; ; SD (single / double pulse mode select) ; 0 - Double pulse with 175mS gap ; 1 - Single pulse ; ; PW (pulse width) ; 0 30mS ; 1 100mS ; ; ; ; ******************************************************************************************************** ; ; Do this if processor type is set to 12F675 IFDEF __12F675 #include "p12f675.inc" ENDIF ; Do this if processor type is set to 12F629 IFDEF __12F629 #include "p12f629.inc" ENDIF ; ******************************************************************************************************** ; TIMING DATA ; Timing data values are stored in EEPROM and read back at power on. ; The default values are specified here and can either be altered in this file and ; the code reassembled. Alternatively, the preassembled .HEX file can be loaed into ; the programmer and the EEPROM data edited before writing to the PIC. radix decimal org 0x2100 ; Default : Setting ;----------------------------------------------------------------------------------------------- de 30 ; 30mS : pulse duration in mS; range (1-255) : jumper closed de 100 ; 100mS : pulse duration in mS; range (1-255) : jumper open de 175 ; 175mS : double flash gap in mS; range (1-255) de 10 ; 1S : off time in 100mS; range (1-255) : Jumper close close de 20 ; 2S : off time in 100mS; range (1-255) : Jumper close open de 30 ; 3S : off time in 100mS; range (1-255) : Jumper open close de 40 ; 4S : off time in 100mS; range (1-255) : Jumper open open ;----------------------------------------------------------------------------------------------- de 0xA9, 0X56 ; validaton bytes - DO NOT ALTER THESE TWO VALUES. ; ******************************************************************************************************** ; Write code revision text to EEPROM org 0x2110 de "LED Strobe Rev. F " de "http://picprojects.org.uk " ; ******************************************************************************************************** __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _CPD_OFF errorlevel -302 ; suppress banksel warning messages ; Define program variable memory locations cblock 0x20 input output dtime ltime pulse.jclosed pulse.jopen pulse.gap pulse.repeat1 pulse.repeat2 pulse.repeat3 pulse.repeat4 blink.count blink.code endc ; ; ******************************************************************************************************** ; Code execution starts from this address after reset ; org 0x000 ; reset vector ; ; Start of the main code. Here the PIC peripherals and I/O are configured. ; start bcf STATUS,RP0 ; Sel Bank 0 ;--------------------------------------- ; Test for loop caused by missing OSSCAL at address 0x3FF movlw .4 movf CMCON,F ; read value from CMCON, 0x00 at reset, 0x07 after initialisation skpz ; if value is 0x00 skip next goto error.mode ; if value isn't zero, we've already done this once so calibration ; word is missing, rather than running with incorrect timing ; the code stops and flashes output LEDs to indicate error ;--------------------------------------- movlw 0x07 ; movwf CMCON ; Disable Comparator on GPIO pins bsf STATUS,RP0 ; Sel Bank 1 bcf OPTION_REG, NOT_GPPU movlw b'00010011' movwf WPU IFDEF ANSEL clrf ANSEL ; Disable Analogue on GPIO pins ( 12F675 only) ENDIF movlw b'11011011' ; Specifiy GPIO port direction movwf TRISIO ; Set GPIO ports as xxOIIOII ; *************************************************************** ; Ensure factory calibration value is present at 0x3FF ; PICkit2 can recalibrate this if it has been erased ; If the value is missing code will detect this and enter an error state call 0x3FF ; calls RETLW with factory setting movwf OSCCAL ; Set int OSC to factory calibrated ; *************************************************************** bcf STATUS,RP0 ; Sel Bank 0 skip.osscal movlw 0x20 ; Initialize output movwf GPIO ; port to Q=0, ^Q=1 movlw .5 ; 500mS delay to allow things to settle. call _LDelay call read.timing ; read timing data from EEPROM ; initialisation complete ; ******************************************************************************************************** ; ; Main code loop. _strobe movf GPIO,W ; Get Digital inputs movwf input ; move to temporary working register movlw 0x04 ; Turn LED on (GP2 = 1 / GP5 =0) movwf GPIO movfw pulse.jclosed ; Pulse width jumper closed btfsc input,4 ; Look at GPIO port 4 data movfw pulse.jopen ; Pulse width jumper open call _Delay ; call LED on delay movlw 0x20 movwf GPIO ; Turn LED off (GP2 = 0 / GP5 = 1) btfsc GPIO,3 ; test GPIO bit 4 for double pulse goto _space ; skip if no double pulse required _dpulse movfw pulse.gap ; load W with double pulse delay call _Delay movlw 0x04 ; Turn LED on (GP2 = 1 / GP5 = 0) movwf GPIO movfw pulse.jclosed ; Pulse width jumper closed btfsc input,4 ; Look at GPIO port 4 data movfw pulse.jopen ; Pulse width jumper open call _Delay movlw 0x20 movwf GPIO ; Turn LED off (GP2 = 0 / GP5 = 1) _space movfw input ; read jumpers andlw 0x03 ; mask of unwanted bits addlw pulse.repeat1 ; add GPR address offset for first entry movwf FSR ; put result into FSR index register movfw INDF ; read timing value from GPR (indirect) call _LDelay ; and generate the delay goto _strobe ; Program loops ; ******************************************************************************************************** ; ; Read timing data from EEPROM into GPR ; main code accesses timing data from GPR memory so we transfer the values from EEPROM into GPR ; at startup. read.timing bsf STATUS,RP0 ; set Bank 1 movlw pulse.jclosed ; initialise FSR to point to base address for data movwf FSR movlw 0x00 ; initialise EEPROM address for reading to 0x00 movwf EEADR ; read.eeprom bsf EECON1,RD ; start EEPROM Read movf EEDATA,W ; Move data read from EEPROM to W movwf INDF ; Move W to GPR ( indirect ) incf EEADR,F ; increment EEPROM address incf FSR,F ; increment FSR pointer movfw FSR ; load FSR into W xorlw blink.code+1 ; compare with last address +1 skpz ; skip if we've read all data goto read.eeprom ; else read next data from eeprom bcf STATUS,RP0 ; set Bank 0 ; validation bytes should contain 0xA9 and 0x56 movfw blink.code ; test validation bytes xorwf blink.count,W ; XOR result should be 0xFF addlw .1 ; Wreg = Wreg+1 skpnz ; if result !=0 the validation failed return ; else we're good to start main code movlw .3 goto error.mode ; ******************************************************************************************************** ; blink leds to indicate error state ; call with number of blinks in W reg ; 3 == suspect eeprom data ; 4 == no calibration word ; error.mode movwf blink.code ; write W to blink.code on entry error.reload movfw blink.code ; copy blink.code movwf blink.count ; to blink.count error.loop movlw 0x04 movwf GPIO movlw .2 ; on 200mS call _LDelay movlw 0x20 movwf GPIO movlw .3 ; off 300mS call _LDelay decfsz blink.count,F ; repeat n times goto error.loop movlw .10 ; pause 1 Second call _LDelay goto error.reload ; repeat ; ******************************************************************************************************** ; ; Software delay function. Require 4Mhz oscillator for instruction cycle time Tcy of 1Mhz ; Call with delay time in W reg. W is destroyed on exit. ; There are two entry points for this function: ; _Delay for delays in mS intervals ; _LDelay for delays in 100mS intervals _Delay movwf dtime ; Call for W x 1mS __Dcall call __1mS decfsz dtime,F goto __Dcall __DlyEnd return _LDelay movwf ltime ; Call for W x 100mS __Dlcall movlw d'100' call _Delay decfsz ltime,F goto __Dlcall return __1mS movlw 0xC6 _next nop addlw 0xFF btfss STATUS,Z goto _next nop nop nop return end