;***************************************************************************** ; lights.asm LED Lighting System ;***************************************************************************** ; Bruce Abbott bhabbott@paradise.net.nz ; ; for Microchip PIC 12F629 or 12F675. ; ;============================================================================= ; Summary of Changes ; ; 2005/03/15 V0.0 - Created from RXDecode.asm ; 2005/08/06 V0.1 - Two strobe lights, adjustable flash sequence. ; 2005/12/17 V0.2 - 3 position switch selects Landing, Lights On, Lights Off. ; 2008/08/30 V0.3 - Active High outputs (driving external transistors) ; ----------------------------------------------------------------------------- radix dec #DEFINE version "0.3" ;#DEFINE __12C508 ; enable if processor not specified elsewhere ;#DEFINE __12F675 ; MPLAB users should use menu ;#DEFINE NO_OSCCAL ; enable if OSCCAL value was erased! ifdef __12C508 PROCESSOR PIC12C508 INCLUDE __CONFIG _MCLRE_OFF&_CP_OFF&_WDT_ON&_IntRC_OSC else PROCESSOR PIC12F675 INCLUDE __CONFIG _MCLRE_OFF&_CP_OFF&_WDT_ON&_BODEN_ON&_INTRC_OSC_NOCLKOUT endif errorlevel 0,-305,-302 #DEFINE TIME 4 ; number of servo pulses per strobe state ;#DEFINE ACTIVE_LOW ; active Low outputs (direct LED drive) ; Bit definitions for the GPIO register and the TRIS register #DEFINE STRB1 5 ; pin 2 Strobe Light #1 #DEFINE STRB2 4 ; pin 3 Strobe Light #2 #DEFINE SERVO 3 ; pin 4 servo pulse input #DEFINE LAND 2 ; pin 5 Landing Lights #DEFINE LED1 1 ; pin 6 Fixed lighting (eg. Navigation Lights) #DEFINE LED2 0 ; pin 7 More Fixed Lighting (eg. Cabin Lights) ; #DEFINE TrisBits (1<1 goto $+1 ; 2 clocks NO_OP_COUNT SET NO_OP_COUNT-2 ENDW IF NO_OP_COUNT nop ; 1 clock ENDIF ENDM ;=========================================================================== ; Macro to create offsets for variables in RAM ; ifdef __12C508 ByteAddr SET 7 else ByteAddr SET 32 ; user RAM starts here endif BYTE MACRO ByteName ByteName EQU ByteAddr ByteAddr SET ByteAddr+1 ENDM ; ========================================================================== ; RAM Variable Definitions ; BYTE Flags ; various boolean flags BYTE ServoCount ; servo pulse length. 1~255 = 0.01~2.55mS BYTE Timer ; delay timer for strobes BYTE Strobe1 ; strobe 1 sequencer BYTE Strobe2 ; strobe 2 sequencer BYTE Glitches ; number of consecutive bad servo pulses BYTE Temp1 BYTE Temp2 ; flag values ; #DEFINE WATCH 0 ; Watchdog timed out #DEFINE STROBE1 1 ; strobe 1 on #DEFINE STROBE2 2 ; strobe 2 on #DEFINE LANDING 3 ; Landing lights on ;**************************************************************************** ; Code ; ORG 0 goto ColdStart ;-------------------------- version string ---------------------------------- ifdef __12F629 dt "NAVL629" endif ifdef __12F675 dt "NAVL675" endif dt "--V" dt version dt "--" ;============================================================================ ColdStart: bcf Flags,WATCH btfss STATUS,NOT_TO ; copy Watchdog timeout flag bsf Flags,WATCH ; get oscillator calibration value and use it to fine-tune clock frequency. ; 12C508/9 has value in W at startup, 12F629/75 gets it from RETLW at 0x3ff. ifdef __12C508 ifdef NO_OSCCAL movlw 0x90 ; replace with value for your PIC! endif movwf OSCCAL ; set oscillator calibration else bsf STATUS,RP0 ; register bank 1 (12F629/75) call 0x3ff ; get OSCCAL value movwf OSCCAL ; set oscillator calibration bcf STATUS, RP0 ; register bank 0 endif ; set options ifdef __12C508 movlw OptionBits option else bsf STATUS,RP0 ; register bank 1 (12F629/75) movlw OptionBits movwf OPTION_REG bcf STATUS,RP0 ; register bank 0 endif ;======================================================================== ; initialise I/O registers movlw ALL_OFF ; all outputs will be off movwf GPIO ifdef __12C508 movlw TrisBits TRIS GPIO ; set I/O pin directions (12F509) else bsf STATUS,RP0 ; register bank 1 (12F629/75) movlw TrisBits movwf TRISIO ; set I/O pin directions (12F629/75) ifdef ANSEL clrf ANSEL ; disable analog inputs (12F675) endif bcf STATUS,RP0 ; register bank 0 ifdef CMCON movlw b'00000111' movwf CMCON ; Comparator off endif endif ; CPU specific stuff done, now we can start the main program! goto Main SeqStrobe1: ifdef PCLATH clrf PCLATH endif movf Strobe1,w addwf PCL retlw b'00000001' retlw b'00000000' retlw b'00000001' retlw b'00000000' retlw b'00000001' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'10000000' ; bit 7 set = end of sequence SeqStrobe2: ifdef PCLATH clrf PCLATH endif movf Strobe2,w addwf PCL retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000001' retlw b'00000000' retlw b'00000001' retlw b'00000000' retlw b'00000001' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'10000000' ; bit 7 set = end of sequence ;------------------------------------------------------------------------------- ; Millisecond Delay Timer ;------------------------------------------------------------------------------- ; Input: W = number of milliseconds to wait (max 256mS) ; dx1k: movwf Temp1 _dx1k1: movlw (1000-5)/5 movwf Temp2 _dx1k2: clrwdt ; avoid watchdog timeout nop decfsz Temp2 ; wait 1mS goto _dx1k2 decfsz Temp1 goto _dx1k1 retlw 0 ;******************************************************************************* ; Main ;******************************************************************************* Main: btfsc Flags,WATCH ; did the watchdog timeout ? goto MainLoop ; oops! try to keep going ... clrf Flags ; clear all flags movlw 250 ; wait 250mS for power to stabilise call dx1k movlw ALL_ON ; all LEDs on movwf GPIO movlw 250 ; wait 250mS call dx1k movlw ALL_OFF ; all LEDs off movwf GPIO movlw TIME movwf Timer clrf Strobe1 clrf Strobe2 clrf Glitches MainLoop: clrf TMR0 ; start timer WaitLow: clrwdt ; avoid watchdog timeout btfsc TMR0,7 ; timer reached 33mS ? goto NoSignal btfsc GPIO,SERVO ; wait for no servo pulse goto WaitLow clrf TMR0 ; start timer waitpulse: clrwdt ; avoid watchdog timeout btfsc TMR0,7 ; timer reached 33mS ? goto NoSignal btfss GPIO,SERVO ; wait for start of servo pulse goto waitpulse clrf ServoCount measure: clrwdt ;1 incf ServoCount ;2 count = pulse width (* 10uS) skpnz ;3 > 2.55mS ? goto BadPulse ;4 Yes, error NO_OP 3 ;5~7 btfsc GPIO,SERVO ;8 servo pulse finished ? goto measure ;9,10 no, continue measuring movlw 70 subwf ServoCount,w ; less than 0.7mS ? skpc goto BadPulse ; yes, bad pulse bcf Flags,LANDING ; assume landing lights are off movlw 130 subwf ServoCount,w ; less than 1.3mS ? skpc bsf Flags,LANDING ; yes, landing lights on movlw 170 subwf ServoCount,w ; less than 1.7mS ? skpc goto power_on ; yes, power on power_off movlw ALL_OFF movwf GPIO ; All lights OFF goto GoodPulse power_on: LED1_ON ; fixed lights ON LED2_ON landing_lights: btfss Flags,LANDING LAND_OFF ; Landing lights OFF btfsc Flags,LANDING LAND_ON ; Landing lights ON strobes: decfsz Timer ; time for next strobe change? goto GoodPulse ; no, done movlw TIME movwf Timer ; restart timer call SeqStrobe1 ; get Strobe 1 state movwf Temp1 incf Strobe1 ; next state btfsc Temp1,7 ; end of sequence ? clrf Strobe1 ; restart sequence bcf Flags,STROBE1 btfsc Temp1,0 ; strobe 1 to be on ? bsf Flags,STROBE1 call SeqStrobe2 ; get Strobe2 state movwf Temp1 incf Strobe2 ; next state btfsc Temp1,7 ; end of sequence ? clrf Strobe2 ; restart sequence bcf Flags,STROBE2 btfsc Temp1,0 ; strobe 2 to be on ? bsf Flags,STROBE2 btfsc Flags,STROBE1 STRB1_ON ; flash strobe 1 btfss Flags,STROBE1 STRB1_OFF btfsc Flags,STROBE2 STRB2_ON ; flash strobe 2 btfss Flags,STROBE2 STRB2_OFF GoodPulse: tstf Glitches skpnz goto done decf Glitches ; another good pulse received goto done BadPulse: incf Glitches ; another bad pulse! movlw 10 subwf Glitches,w skpc ; too many bad pulses? goto done decf Glitches NoSignal: movlw ALL_OFF movwf GPIO ; turn off all outputs done: goto MainLoop ;---------- Oscillator Calibration Subroutine (12F629/75 only) -------------- ifdef __12F675 org 0x3ff retlw 0x90 ; replace with oscal value for your PIC! endif END