

	list      p=12F683        ; list directive to define processor
	#include <p12F683.inc>    ; processor specific variable definitions

	errorlevel  -302          ; suppress message 302 from list file

	__CONFIG   _FCMEN_OFF & _IESO_OFF & _CP_OFF & _CPD_OFF & _BOD_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTOSCIO 

;***** VARIABLE DEFINITIONS******************
w_temp        EQU     0x70        ; variable used for context saving 
status_temp   EQU     0x71        ; variable used for context saving

FLAGS		EQU		0x20		;software state register
PULSER		EQU		0x21		;pulse on counter
DWELLTIMER	EQU		0x22		;pulse off counter
STATE		EQU		0x23		;programmed state
BUTTONHOLD	EQU		0x24
FREQR		EQU		0x25		;frequency value
TEMP1		EQU		0x26
TEMP2		EQU		0x27
PULSEL		EQU		0x28
DWELLTIMEL	EQU		0x29
TEMP5		EQU		0x2A
LEDBLINK	EQU		0x2B
TEMP3		EQU		0x2C

BURSTRATE	EQU		0x3E
BURST10		EQU		0x3F
FLAGS2		equ		0x41
SHADOWP		equ		0x42



;*******bits in FLAGS register***********
PULSEONR		equ		0
PULSEONL		equ		1
TRIGOUT			equ		2
LEDHI			equ		3
STATECHANGE		equ		4
BURSTACTIVE		equ		6
COD5MODE		equ		7

;******bits in FLAGS2 register
BDWELL		equ		0
BDWELL2		equ		1
BURSTONR	equ		2
BURSTONL	equ		3


;*******bits in STATE register***********
RIGHTACTIVE		equ		0
LEFTACTIVE		equ		1

;*********GPIO pin names*****************
LEDL			equ		5
LEDR			equ		4
BUTTONR			equ		2
BUTTONL			equ		3
TRIGGERR		equ		0
TRIGGERL		equ		1


;**********Speed settings: change these to change speed (0x05-0xFF)
FIRERATE1		equ		0x2F		;Halo3
FIRERATE2		equ		0x30		;COD5
FIRERATE3		equ		0x2D		;COD5 burst fast
FIRERATE4		equ		0x38		;COD4



;**********************************************************************
	ORG     0x000             ; processor reset vector
	goto    main              ; go to beginning of program
	

	ORG     0x004             ; interrupt vector location
	movwf   w_temp            ; save off current W register contents
	movf	STATUS,w          ; move status register into W register
	movwf	status_temp       ; save off contents of STATUS register

			;Take a good note here. OSC is left at default 4MHz.
			; We are running at 1MHz instruction cycle, or 1 micro second
			;Timer 2 is prescaled 1:4 and compared (PR2) to 250.
			; we now have hardware interupt that falls every 1ms exactly
			;within limitation of osctune. Main code is inconsequential.
			;PULSE and DWELL values control the signals precisely.
			;All pulse logic is switched within the few microseconds to 
			;service the interupt routine. DO NOT modify the ISR
			;with any kind of 'wait' or 'loop'. If you want to trigger
			; timed events do so by setting an open FLAG bit and have the 
			;event done in the main loop.


	btfss	PIR1, TMR2IF		;timer 2 int happened
	retfie

;**************** LED blinking *********************************************
								;Our main routine will turn the flag bit
								;LEDON on or off. The 10ms pulse is a duty cycle
								;for the code to work with both CG and
								;matrix controllers. 

BlinkLed	
	btfss	FLAGS, LEDHI
	goto	LedLow
	decfsz	LEDBLINK, f			;if pulse is active, count down 10ms
	goto	RightLED
	movlw	0x0A
	movwf	LEDBLINK
	bcf		FLAGS, LEDHI		;10ms done, turn off LEDHI bit
	goto	RightLED
LedLow
	decfsz	LEDBLINK, f			;LEDLO time, count down 10ms
	goto	RightLED
	movlw	0x0A
	movwf	LEDBLINK
	bsf		FLAGS, LEDHI		;10ms done, turn LEDHI bit on

RightLED
	btfsc	STATE, RIGHTACTIVE	;is RF on?
	goto	OutputRightLED
	bsf		STATUS, RP0			;bank 1
	bsf		TRISIO, LEDR		;tristate LED
	bcf		STATUS, RP0			;bank 0
	goto	LeftLED
OutputRightLED
	btfsc	FLAGS, LEDHI		;if ledhi true,
	bsf		GPIO, LEDR			;turn output hi
	btfss	FLAGS, LEDHI		;if ledhi flase,
	bcf		GPIO, LEDR			;turn led output lo
	bsf		STATUS, RP0			;bank 1
	bcf		TRISIO, LEDR		;turn output on
	bcf		STATUS, RP0			;bank 0

LeftLED
	btfsc	STATE, LEFTACTIVE	;is RF on?
	goto	OutputleftLED
	bsf		STATUS, RP0			;bank 1
	bsf		TRISIO, LEDL		;tristate LED
	bcf		STATUS, RP0			;bank 0
	goto	RightTrigger
OutputleftLED
	btfsc	FLAGS, LEDHI		;if ledhi true,
	bsf		GPIO, LEDL			;turn output hi
	btfss	FLAGS, LEDHI		;if ledhi flase,
	bcf		GPIO, LEDL			;turn led output lo
	bsf		STATUS, RP0			;bank 1
	bcf		TRISIO, LEDL		;turn output on
	bcf		STATUS, RP0			;bank 0

;**************** Right trigger logic***************************************	
RightTrigger
	btfsc	STATE, RIGHTACTIVE	;is RF on?
	goto	ActiveR
	bsf		STATUS, RP0			;bank 1
	bsf		TRISIO, TRIGGERR	;output off
	bcf		STATUS, RP0			;bank 0	
	goto	LeftTrigger

ActiveR
	btfss	FLAGS, TRIGOUT		;controllertype 
	bcf		GPIO, TRIGGERR		;determines
	btfsc	FLAGS, TRIGOUT		;output state
	bsf		GPIO, TRIGGERR	
	btfsc	FLAGS, BURSTACTIVE
	goto	BurstfireR

	btfss	FLAGS, PULSEONR		;is pulse active?
	goto	OffstateR
	decfsz	PULSER, f			;if pulse is active, count down 10ms
	goto	LeftTrigger
	bcf		FLAGS, PULSEONR		;10ms is over, clear flags and 
	bsf		STATUS, RP0			;bank 1
	bsf		TRISIO, TRIGGERR	;tristate output
	bcf		STATUS, RP0			;bank 0	
	movf	FREQR, w			;and reset pulse time.
	movwf	PULSER
	btfss	FLAGS, COD5MODE			;test COD5 mode
	goto	LeftTrigger
	bcf		STATUS, C
	rrf		PULSER, f			;25% DUTYCYCLE for COD5 release
	goto	LeftTrigger

OffstateR
	decfsz	DWELLTIMER, f		;count down dwell time to next pulse
	goto	LeftTrigger
	bsf		FLAGS, PULSEONR		;if dwell is done turn on outputs
	bsf		STATUS, RP0			;bank 1
	bcf		TRISIO, TRIGGERR	;and reset pulse time
	bcf		STATUS, RP0			;bank 0	
	movf	FREQR, w			;from frequency value
	movwf	DWELLTIMER
	btfss	FLAGS, COD5MODE			;test COD5 mode
	goto	LeftTrigger
	bcf		STATUS, C
	rrf		DWELLTIMER, f	
	addwf	DWELLTIMER, f		;75% dutycycle for pull

BurstfireR
	btfss	FLAGS2, BURSTONR
	goto	LeftTrigger
	btfsc	FLAGS2, BDWELL		;burst fire
	goto	BurstDwellR

	btfss	FLAGS, PULSEONR			;is pulse active?
	goto	OffstateR2
	decfsz	PULSER, f			;if pulse is active, count down 10ms
	goto	LeftTrigger

	bcf		FLAGS, PULSEONR		;10ms is over, clear flags and output 
	bsf		STATUS, RP0		;bank 1
	bsf		TRISIO, TRIGGERR	;and reset pulse time.
	bcf		STATUS, RP0		;bank 0	
	movf	FREQR, w
	movwf	PULSER
	btfsc	FLAGS, COD5MODE			;test COD5 mode
	rrf		PULSER, f
	decfsz	BURST10, f				;count down burst shots
	goto	LeftTrigger
	movf	BURSTRATE, w			;reset counter
	movwf	BURST10
	bsf		FLAGS2, BDWELL			;signal dwell
	movf	FREQR, w
	movwf	DWELLTIMER				;reset dwell counter
	btfss	FLAGS, COD5MODE			;test COD5 mode
	goto	LeftTrigger
	bcf		STATUS, C
	rrf		DWELLTIMER, f
	addwf	DWELLTIMER, f
	goto	LeftTrigger

OffstateR2
	decfsz	DWELLTIMER, f		;count down dwell time to next pulse
	goto	LeftTrigger
	bsf		FLAGS, PULSEONR		;if dwell is done turn on outputs
	bsf		STATUS, RP0		;bank 1
	bcf		TRISIO, TRIGGERR	;and reset pulse time
	bcf		STATUS, RP0		;bank 0	
	movf	FREQR, w			;from frequency value
	movwf	DWELLTIMER
	btfss	FLAGS, COD5MODE			;test COD5 mode
	goto	LeftTrigger
	bcf		STATUS, C
	rrf		DWELLTIMER, f
	addwf	DWELLTIMER, f
	goto	LeftTrigger

BurstDwellR
	btfss	FLAGS, TRIGOUT
	goto	CGBurst
	btfss	GPIO, TRIGGERR
	goto	LeftTrigger
	goto	BurstReset

CGBurst
	btfsc	GPIO, TRIGGERR
	goto	LeftTrigger

BurstReset
	bcf		FLAGS, PULSEONR		;if dwell is done turn on outputs
	bcf		FLAGS2, BDWELL
	bcf		FLAGS2, BURSTONR


LeftTrigger
	btfsc	STATE, LEFTACTIVE	;is RF on?
	goto	ActiveL
	bsf		STATUS, RP0			;bank 1
	bsf		TRISIO, TRIGGERL	;output off
	bcf		STATUS, RP0			;bank 0	
	goto	EndInterupt

ActiveL
	btfss	FLAGS, TRIGOUT		;controllertype 
	bcf		GPIO, TRIGGERL		;determines
	btfsc	FLAGS, TRIGOUT		;output state
	bsf		GPIO, TRIGGERL	
	btfss	FLAGS, PULSEONL		;is pulse active?
	goto	OffstateL
	decfsz	PULSEL, f			;if pulse is active, count down 10ms
	goto	EndInterupt
	bcf		FLAGS, PULSEONL		;10ms is over, clear flags and 
	bsf		STATUS, RP0			;bank 1
	bsf		TRISIO, TRIGGERL	;tristate output
	bcf		STATUS, RP0			;bank 0	
	movf	FREQR, w			;and reset pulse time.
	movwf	PULSEL
	goto	EndInterupt

OffstateL
	decfsz	DWELLTIMEL, f		;count down dwell time to next pulse
	goto	EndInterupt
	bsf		FLAGS, PULSEONL		;if dwell is done turn on outputs
	bsf		STATUS, RP0			;bank 1
	bcf		TRISIO, TRIGGERL	;and reset pulse time
	bcf		STATUS, RP0			;bank 0
	movf	FREQR, w			;from frequency value
	movwf	DWELLTIMEL

EndInterupt
	bcf		PIR1, TMR2IF

	movf    status_temp,w     ; retrieve copy of STATUS register
	movwf	STATUS            ; restore pre-isr STATUS register contents
	swapf   w_temp,f
	swapf   w_temp,w          ; restore pre-isr W register contents
	retfie                    ; return from interrupt


;*************************************SUBROUTINES**********************************

Wait10ms
	clrf	TEMP2
	movlw	0x0D
	movwf	TEMP1				;rough 10ms timer for button debounce.

Loop1
	decfsz	TEMP2, f			;count down 256*3=768 cycles
	goto	Loop1
	decfsz	TEMP1, f			;count down 768*13=9986 cycles
	goto	Loop1
	return
	
			;*************************************************************
ReadEE
	bsf     STATUS    , RP0		;Bank1
	movlw	0x02
    movwf   EEADR
    bsf     EECON1    , RD		;start read
    movf    EEDAT    , W
	bcf     STATUS    , RP0		;Bank0
    return
			;*************************************************************

WriteEE
	bsf     STATUS    , RP0
	movwf	EEDAT
	movlw	0x02
	movwf	EEADR
	bsf		EECON1,WREN 		;Enable write
	bcf		INTCON, GIE 		;Disable INTs
	btfsc	INTCON, GIE 		;See AN576
	goto	$-2 
	movlw 	0x55 				;Unlock write
	movwf 	EECON2 
	movlw 	0xAA
	movwf 	EECON2 
	bsf 	EECON1, WR 			;Start the write
WaitForEEWrite
	btfsc   EECON1, WR			;wait for hardware to clear (done writing)
    goto    WaitForEEWrite
	bcf     STATUS    , RP0		;Bank0
	bsf 	INTCON, GIE 		;Enable INTS
    return

;*******************Burst fire test*******************************
BursttestCG
	btfss	FLAGS, BURSTACTIVE	;is burst active?
	return
	btfss	STATE, RIGHTACTIVE
	return
	btfsc	GPIO, TRIGGERR		;is trigger pulled on CG?
	bsf		FLAGS2, BURSTONR	;activate burstfire
	return

BursttestMX
	btfss	FLAGS, BURSTACTIVE	;is burst active?
	return
	btfss	STATE, RIGHTACTIVE
	return
	btfss	GPIO, TRIGGERR		;is trigger pulled on MX?
	bsf		FLAGS2, BURSTONR	;activate burstfire
	return

;**********************************************************************************
;**********************************************************************************
;**********************************************************************************
main

	clrf	GPIO
	clrf	FLAGS				;clear outputs and code status register
	clrf	FLAGS2
	movlw	0x07
	movwf	CMCON0				;comparators off
	bsf		STATUS, RP0			;bank 1
	movlw	0x0F				;start with 0-3 inputs (ADC read)
	movwf	TRISIO				;pin 0 & 1 & 5 out, all other inputs
	movlw	0x51				;Fosc/16, pin 0 analog
	movwf	ANSEL				;Right trigger is analog input
	movlw	0x04
	movwf	WPU					;enable week pullups
	bcf		OPTION_REG, 7		;enable all week pullups 
	bcf		STATUS, RP0			;bank 0

	movlw	0x01				;Left just, Vdd, channel 0
	movwf	ADCON0				;module on.
	movlw	0x10
	movwf	TEMP1
Wait4ADC
	decfsz	TEMP1, f
	goto	Wait4ADC			;acquisition time
	bsf		ADCON0, 1			;start ADC
	btfsc	ADCON0, 1
	goto	$-1					;wait for conversion to be done
	movlw	0x40				;about 0.5V from 2V ref
	subwf	ADRESH, w			;if f > W, C=1
	btfsc	STATUS, C			;ie- if trigger > 0.5V, then matrix
	bsf		FLAGS, TRIGOUT		;matrix config sources (output high)
	bsf		STATUS, RP0			;bank 1
	movlw	0x0C				;restore pin IO
	movwf	TRISIO	
	clrf	ANSEL				;all digital now
	bcf		STATUS, RP0			;bank 0

	movlw	0x0A				;start with 10ms pulse width
	movwf	LEDBLINK			;for the LEDs
	movlw	FIRERATE1			;this will get overwritten,
	movwf	PULSER				; but start with a default value
	movwf	PULSEL
	movwf	DWELLTIMER
	movwf	DWELLTIMEL
	movlw	0x05				;init burst rate
	movwf	BURSTRATE
	movwf	BURST10
	call	ReadEE				;get state value
	movwf	STATE

	movlw	0x01
	movwf	T2CON				;timer 2, prescale 1:4, no postscale
	bsf		STATUS, RP0			;bank 1
	movlw	0xFA
	movwf	PR2					;setup 1ms hardware interupt
	bsf		PIE1, TMR2IE		;enable timer2 interupt
	bcf		STATUS, RP0			;bank 0
	bsf		T2CON, TMR2ON		;turn on timer2
	movlw	0xC0
	movwf	INTCON				;turn on interupts globally
	goto	InitState			;get first firerate value

;******MAIN LOOP***************
Start
	btfss	FLAGS, TRIGOUT		;check trigger for burstfire
	call	BursttestCG
	btfsc	FLAGS, TRIGOUT
	call	BursttestMX

TestLeft
	btfsc	GPIO, BUTTONL
	goto	TestRight			;Test for left button press
	call	Wait10ms
	btfsc	GPIO, BUTTONL		;button is down for 10ms
	goto	TestRight
ReleaseLeft
	btfss	GPIO, BUTTONL		;wait for button release			
	goto	ReleaseLeft
	call	Wait10ms
	btfss	GPIO, BUTTONL		;wait for button release			
	goto	ReleaseLeft

	movlw	0x02
	xorwf	STATE, f			;toggle left trigger
	call	WriteEE				;store state

TestRight
	btfsc	GPIO, BUTTONR
	goto	Start
;	goto	DisplayState		;Test for right button press
	call	Wait10ms
	btfsc	GPIO, BUTTONR		;button is down for min 10ms
	goto	Start
;	goto	DisplayState
	movlw	0x80
	movwf	BUTTONHOLD			;setup for 2 second hold
First2seconds
	call	Wait10ms
	btfsc	GPIO, BUTTONR		;button is down for more than 10ms
	goto	ReleaseRight
	decfsz	BUTTONHOLD, f 
	goto	First2seconds
	movlw	0x80
	movwf	BUTTONHOLD			;setup for 2 second hold
Second2seconds
	call	Wait10ms
	btfsc	GPIO, BUTTONR		
	goto	ReleaseRight
	decfsz	BUTTONHOLD, f 		
	goto	Second2seconds		;button down for 4 seconds, change firerate
	
NextState
	movlw	0x40
	addwf	STATE, f			;change firerate state
InitState						;begin test for
	btfsc	STATE, 7			;state 1 or 2
	goto	State3
	btfsc	STATE, 6
	goto	State2
State1
	movlw	FIRERATE1				;state 1
	movwf	FREQR
	bcf		FLAGS, COD5MODE			;turn COD5 mode off
	bcf		FLAGS, BURSTACTIVE
;	bsf		FLAGS, BURSTACTIVE		;uncomment to activate burstfire for state 1
;	movlw	0X04
;	movwf	BURSTRATE
	bcf		STATE, RIGHTACTIVE		;led off
	movlw	0x0A
	movwf	TEMP3
Loop01
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop01
	bsf		STATE, RIGHTACTIVE		;led on
	bsf		FLAGS, STATECHANGE		;notify a state change
	goto	ReleaseRight

State2
	movlw	FIRERATE2				;state 2
	movwf	FREQR
	bsf		FLAGS, COD5MODE			;turn COD5 mode on
	bcf		FLAGS, BURSTACTIVE
;	bsf		FLAGS, BURSTACTIVE		;uncomment to activate burstfire for state 2
;	movlw	0X04
;	movwf	BURSTRATE
	bcf		STATE, RIGHTACTIVE		;blink twice, led off
	movlw	0x0A
	movwf	TEMP3
Loop02
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop02
	bsf		STATE, RIGHTACTIVE		;led on
	movlw	0x0A
	movwf	TEMP3
Loop03
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop03
	bcf		STATE, RIGHTACTIVE		;led off
	movlw	0x0A
	movwf	TEMP3
Loop04
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop04
	bsf		STATE, RIGHTACTIVE		;led on
	bsf		FLAGS, STATECHANGE		;notify a state change
	goto	ReleaseRight

State3
	btfsc	STATE, 6
	goto	State4
	movlw	FIRERATE3			;state 3
	movwf	FREQR
	bsf		FLAGS, COD5MODE			;turn COD5 mode on
	bcf		FLAGS, BURSTACTIVE
	bsf		FLAGS, BURSTACTIVE		;uncomment to activate burstfire for state 3
	movlw	0X04
	movwf	BURSTRATE
	bcf		STATE, RIGHTACTIVE		;blink 3 times, led off
	movlw	0x0A
	movwf	TEMP3
Loop05
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop05
	bsf		STATE, RIGHTACTIVE		;led on
	movlw	0x0A
	movwf	TEMP3
Loop06
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop06
	bcf		STATE, RIGHTACTIVE		;led off
	movlw	0x0A
	movwf	TEMP3
Loop07
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop07
	bsf		STATE, RIGHTACTIVE		;led on
	movlw	0x0A
	movwf	TEMP3
Loop08
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop08
	bcf		STATE, RIGHTACTIVE		;led off
	movlw	0x0A
	movwf	TEMP3
Loop09
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop09
	bsf		STATE, RIGHTACTIVE		;led on
	bsf		FLAGS, STATECHANGE		;notify a state change
	goto	ReleaseRight

State4
	movlw	FIRERATE4			;state 4, 22ms cycle
	movwf	FREQR
	bcf		FLAGS, COD5MODE			;turn COD5 mode off
	bcf		FLAGS, BURSTACTIVE
;	bsf		FLAGS, BURSTACTIVE		;uncomment to activate burstfire for state 4
;	movlw	0X04
;	movwf	BURSTRATE
	bcf		STATE, RIGHTACTIVE		;blink 4 times, led off
	movlw	0x0A
	movwf	TEMP3
Loop10
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop10
	bsf		STATE, RIGHTACTIVE		;led on
	movlw	0x0A
	movwf	TEMP3
Loop11
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop11
	bcf		STATE, RIGHTACTIVE		;led off
	movlw	0x0A
	movwf	TEMP3
Loop12
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop12
	bsf		STATE, RIGHTACTIVE		;led on
	movlw	0x0A
	movwf	TEMP3
Loop13
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop13
	bcf		STATE, RIGHTACTIVE		;led off
	movlw	0x0A
	movwf	TEMP3
Loop14
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop14
	bsf		STATE, RIGHTACTIVE		;led on
	movlw	0x0A
	movwf	TEMP3
Loop15
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop15
	bcf		STATE, RIGHTACTIVE		;led off
	movlw	0x0A
	movwf	TEMP3
Loop16
	call	Wait10ms				;100 ms
	decfsz	TEMP3, f
	goto	Loop16
	bsf		STATE, RIGHTACTIVE	;led on
	bsf		FLAGS, STATECHANGE	;notify a state change

ReleaseRight
	btfss	GPIO, BUTTONR		;wait for button release			
	goto	ReleaseRight
	call	Wait10ms
	btfss	GPIO, BUTTONL		;wait for button release			
	goto	ReleaseRight
	btfsc	FLAGS, STATECHANGE	;test for button tap or state change
	goto	Continue01
	movlw	0x01
	xorwf	STATE, f			;toggle left trigger if button tap
Continue01
	bcf		FLAGS, STATECHANGE
	call	WriteEE				;store state
	goto	Start




	
; initialize eeprom locations

	ORG	0x2100
	DE	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07


	END                       ; directive 'end of program'

