;******************************************************************* ; ICEBREAKER FIRING PROGRAM ; Designed for 16F628A prototype board - change I/O for production circuit ; Includes the NEW 4-MHz clock routine. ; Includes timed mode and manual mode, ; Includes manual mode time limit. ;******************************************************************* ; DISABLE MASTERCLEAR AND WDT WHEN PROGRAMMING. ;******************************************************************* ; ;==========COMPILER DIRECTIVES SECTION=============================== LIST p=16F628A ;Tell the assembler to use 16F628A include "P16F628A.INC" ;Tell the compiler to include defaults for 16F628A cblock 0x20 ;Prepare the general purpose registers count1 ;Used in delay routine counta ;Used in delay routine countb ;Used in delay routine countv ;Used in manual mode (maximum fire time limit) endc ;==========CPU EQUATES SECTION======================================= SOL Equ 0 ;Set constant for PortB - solenoid (left green LED) SOLLED Equ 1 ;Set constant for PortB - solenoid LED (left green LED) LEDMAN Equ 3 ;Set constant for PortB - manual mode LED (middle left green LED) LEDTIMED Equ 5 ;Set constant for PortB - timed mode LED (middle right green LED) POWERLED Equ 7 ;Set constant for PortB - power indicator LED (red LED) TRIG Equ 0 ;Set constant for PortA - trigger (top switch) MODESW Equ 1 ;Set constant for PortA - mode switch (middle switch) INPORT Equ PORTA ;Set constant for PortA - "INPORT" OUTPORT Equ PORTB ;Set constant for PortB - "OUTPORT" ;===========DATA DEFINITIONS SETUP=================================== org 0x0000 ;Start program movlw 0x07 ;Prepare binary 111 for CMCON movwf CMCON ;Turn comparators off, allow for general I/O. bsf STATUS, RP0 ;Select bank 1 to edit terminal direction assignments movlw b'00011111' ;Move full binary into W register (all inputs) movwf TRISA ;Move W into PortA tristate controller movlw b'00000000' ;Move null binary into W register (all outputs) movwf TRISB ;Move W into PortB tristate controller bcf STATUS, RP0 ;Deselect bank 1, autoselect bank 0. ;===========MAIN PROGRAM======================================= clrf PORTB ;Ensure all outputs are off at this point. bsf PORTB, POWERLED ;Turn on the indicator LED and keep it on forver! Loop ;Input scan routine begin here <--- nop ;Wait for 2-µS to before completing the loop instruction nop ; (this compensates for program pointer delays) bcf PORTB, SOL ;Ensure the solenoid and firing LED are off! bcf PORTB, SOLLED btfss PORTA, MODESW ;Check the mode switch, skip next instruction if it's high... goto Manmode ;If low, jump to "Manual-mode" goto Timedmode ;If high, jump to "Timed-mode" ; The program will return to check the mode switch each time it loops ^^ ; ;===========ACTION SUBROUTINES=================================== Manmode bsf PORTB, LEDMAN ;Turn timed-mode LED off, turn manual-mode LED on bcf PORTB, LEDTIMED btfsc PORTA, TRIG ;Check the trigger, skip next instruction if it's low (firing)... goto Loop ;If high, loop and keep checking it continuously. movlw d'20' ;If low, we must debounce the signal before firing Call Delay ;Wait for the number of milliseconds in ^^ above line ^^ btfsc PORTA, TRIG ;Post-debounce...check the trigger again (skip next if low) goto Loop ;If high, it was a false positive...loop and start over bsf PORTB, SOL ;If low, set the solenoid and firing LED bits bsf PORTB, SOLLED clrf countv ;Reset the valve open counter "countv" movlw d'25' ;Prepare valve override counter value (number of loops) ; (20-ms)(25 loops) = 500ms for the manual mode override time movwf countv ;Put that number in the valve dwell counter Manfire ;Loop back to this line when keeping the solenoid open movlw d'20' ;Wait this milliseconds between trigger checks (loop time) Call Delay btfsc PORTA, TRIG ;It's been a few milliseconds....was the trigger released? goto Firedis ;If high (released), cease firing! Decfsz countv, f ;Decrement valve dwell counter, skip next if ==0 goto Manfire ;If countv>0, keep solenoid energized and loop. goto Firedis ;If countv=0, auto shutoff solenoid and lock the trigger. ; Timedmode bcf PORTB, LEDMAN ;Turn manual-mode LED off, turn timed-mode LED on bsf PORTB, LEDTIMED btfsc PORTA, TRIG ;Check the trigger, skip next instruction if it's low (firing) goto Loop ;If high, loop and keep doing it continuously. movlw d'20' ;If low, we must debounce the signal before firing Call Delay ;Wait for the number of milliseconds in ^^ above line ^^ btfsc PORTA, TRIG ;Post-debounce, check the trigger again (skip next if low) goto Loop ;If high, it was a false positive...loop and start over bsf PORTB, SOL ;If low, set the solenoid and firing LED bits bsf PORTB, SOLLED movlw d'100' ;Prepare the solenoid dwell time value (milliseconds) Call Delay ;Wait for the dwell time in ^^ above line ^^ nop ;Firing complete, fall thru to Firedis routine.... Firedis ;Use this subroutine to cease firing and lock the trigger. bcf PORTB, SOL ;Deactivate the solenoid and LED, this mayhem has to stop! bcf PORTB, SOLLED btfss PORTA, TRIG ;Scan the trigger continuously - skip next if high (released) goto Firedis ;If low, loop and wait for trigger to be released goto Loop ;If high, you're ready to fire again....loop from the beginning. ;===========GLOBAL SUBROUTINES================================= Delay ;4-MHz delay subroutine movwf count1 ;Master loop - assign this to the W value before the CALL d1 movlw 0xC7 movwf counta ;Assign "counta" (inner loop) movlw 0x01 movwf countb ;Assign "countb" to 1 millisecond (outer loop) Delay_0 decfsz counta, f ;Decrement inner loop, skip next line if ==0 goto $+2 ;Loop and repeat until it reaches 0. decfsz countb, f ;Inner loop complete....decrement outer loop...skip next line if ==0 goto Delay_0 ;1-ms has not expired...loop and decrement again. decfsz count1, f ;1-ms has expired...decrement master count by 1-ms, test, skip next if ==0 goto d1 ;Master count hasn't expired...loop and remove another millisecond. retlw 0x00 ;If master count ==0, exit subroutine because the count is up! ; Reset W register before returning to program (W=0x00). end ;END OF PROGRAM