;	for universal Pic board, sequencer with hold off
;
; This program executes continuosly, never sleeps or interrupts. RA0 RA1 RA2 and RA4 are monitored
;  and correspond to RC0 RC1 RC2 and RC3 which go high to drive the PMOS.
;
;	RA0  RA1  RA2  RA4  INPUTS
;	
;	RC0  RC1  RC2  RC3 ARE THE SEQUENCED OUPUTS
;
;	April 9 2013 Changed to use internal delay only
;	test and use RA0 RC0 RC1 RC2 RC3
;	which means no resistors are needed between ports
;	to couple the logic
;
; 28 uS in transmit
; 24 us in receive
;
;    SETUP PORTS
;    PORT A    ---------------------------inputs--------------------------------------------------------------------------------
;	I/O	0	0	I	I 	I	I
;	pins 	2	3	4	11	12	13
;		RA5	RA4	RA3	RA2	RA1	RA0	
;	TRISA	1	1	1	1	1	1	0x3F
;	IOCA	0	0	0	0	0	0	Ox00
;	WPUA	0	0	0	0	0	0	0x00
;
;     PORT C    ---------------------------outouts--------------------------------------------------------------------------------
;	I/O	in		SEN	CLK	DATA	O
;	pins	5	6	7	8	9	10
;		RC5	RC4	RC3	RC2  	RC1 	RC0
;	TRISC	1	1	1	1	1	1	0x3F 
;
;                     -------------------------------------------------------------------------------------------------------------------------------
;
P=16F630
		include P16F630.inc
		errorlevel  -302        ; suppress message 302 from list file
	    				; RC internal clock
	    				; RA0 and RA1 as I/O
	    				; pin 3 function as MCLR 
	         __config 0x3FA4   	; watchdog timer off 
				    	; power-up timer on
	                            	; code protect   off
	         radix    hex 
;			 
;************************************************************************
	cblock 0x20
;
regC  			; delay register
regD  			; delay register
regE  			; delay register
w_temp			; store a copy of W register while int
status_temp		; store a copy of Status Reg while int
;
	endc
;
;
;************************************************************************
;
	ORG     0x00          	; startup address = 0000
	goto	start	
;
;*************************************************************************
;			store W and STATUS
;
	ORG     0x04       	; interrupt vector location
;
	MOVWF 	w_temp 		; copy W to temp register,
				; could be in either bank
	SWAPF 	STATUS,W 	; swap status to be saved into W
	BCF	STATUS,RP0 	; change to bank 0 regardless of
				; current bank
	MOVWF	status_temp 	; save status to bank 0 register
;	BCF	INTCON, RAIF	; clear RA flag
	GOTO	PER_INT
;
;---------------------------
start
;	call    0x3FF		; retrieve factory calibration value
;Bank1
	MOVLW	0x44		; restore historic osccal value
        bsf     STATUS,RP0	; set file register bank to 1 
        movwf   OSCCAL		; update register with factory cal value 
        bcf     STATUS,RP0	; set file register bank to 0
;
;
;			PORTC INIT
;Bank0
	BCF 	STATUS, RP0	; Bank0
	CLRF 	PORTC 		; Initialize PORTC by clearing output data latches
	BSF 	STATUS, RP0 	;   Bank1
	MOVLW 	0x00		;   Value used to initialize data direction
	MOVWF 	TRISC 		;   see notes ABOVE
	BCF 	STATUS, RP0	; Bank0
	MOVWF	PORTC
	BCF 	STATUS, RP0	; Bank0
;
;			PORTA INIT
;Bank0
	BCF 	STATUS, RP0	; Bank0
	CLRF 	PORTA 		; Initialize PORTA by clearing output data latches
	movlw	0X47		; Set RA<2:0> to   b(1000111)
	movwf	CMCON		; digital I/O
;Bank1
	BSF 	STATUS, RP0 	;   Bank1	
	MOVLW 	0x3F		;   used to initialize data direction
	MOVWF 	TRISA 		;   ALL AS INPUT
	CLRF	PIE1		;   disable tmr1 - other stuff we don't need
	MOVLW	0x00		;   IOCA register (is in bank1)
	MOVWF 	IOCA		;   set interrupt-on-change 
	BSF	OPTION_REG, 7	;   DISable all weak pull-ups
	MOVLW	0x00		;   enable weak p/u on indiv pins
	MOVWF	WPUA		;   do it (enabled = 1)
	CLRF	PIE1		;   disable TMR0 int (bank 1)
;Bank0
	BCF 	STATUS, RP0 	; Bank0
	CLRF	INTCON 		; Disable interrupts and clear some flags
	CLRF	PIR1 		; Clear all flag bits - bank 0
;
	BCF	INTCON, 4	; INTE - external Interrupt Enable (1=enable)
	BCF	INTCON, 5	; TIMER OVERFLOW INT ENABLE ( 1 = enable)
	BCF	INTCON, 6	; rising edge trigger ( 1 = enable)
	BCF	INTCON, 2	; TIMER INT DISABLE
	BCF	INTCON, 0	; RAIF - Clear Flag Bit Just In Case
	BCF	INTCON, 1	; INTF - Clear Flag Bit Just In Case
	BCF	INTCON, 3	; RA interrupt enable (1=enable)
	BCF	INTCON, 7	; Global int enable
	BCF	PORTC, 0
	BCF	PORTC, 1
	BCF	PORTC, 2
	BCF	PORTC, 3
;
; begin main loop
;
main	
	BTFSS	PORTA, 0		; is RA0=0 ? keying input
	goto	receive
transmit

	BTFSS	PORTA, 0	; still keyed ? clr if not keyed
	GOTO	receive		; skip if RA0 set
	BTFSS	PORTC, 0	; skip if already set
	BSF	PORTC, 0	; set RC0
;=====================================	
	BTFSS	PORTA, 0	; still keyed ? clr if not keyed
	GOTO	receive		; skip if RA0 set
	BTFSS	PORTC, 1	; skip if already set
	CALL	delay2		; set RC1
;=====================================
	BTFSS	PORTA, 0	; still keyed ? clr if not keyed
	GOTO	receive		; skip if RA0 set 
	BTFSS	PORTC, 2	; skip if already set
	CALL	delay3		; set RC2 after rc1 delay
;=====================================
	BTFSS	PORTA, 0	; still keyed ? clr if not keyed
	GOTO	receive		; skip if RA0 set 
	BTFSS	PORTC, 3	; skip if already set
	CALL	delay4		; set RC3 after rc2 delay
;=====================================

	GOTO	main
;**********************************************************
;	RA0  RA1  RA2  RA4  RA5 INPUTS
;	
;	RC0  RC1  RC2  RC3 ARE SEQ OUPUTS
receive
;=====================================
	BTFSC	PORTA, 0	; still keyed ? skip next if key up
	GOTO	transmit	; 
	BTFSC	PORTC, 3	; skip next if already clear 
	BCF	PORTC, 3	; clear RC3 immediately
;=====================================
	BTFSC	PORTA, 0	; still keyed ? skip next if key up
	GOTO	transmit	; 
	BTFSC	PORTC, 2	; skip next if already clear	;
	CALL	delay6		; if RC3 is clear, clear RC2
;=====================================
	BTFSC	PORTA, 0	; still keyed ? skip next if key up
	GOTO	transmit	; 
	BTFSC	PORTC, 1	; skip next if already clear
	CALL	delay7		; if RC2 is clear, clear RC1
;=====================================
	BTFSC	PORTA, 0	; still keyed ? skip next if key up
	GOTO	transmit	; 
	BTFSC	PORTC, 0	; skip next if already clear
	CALL	delay8		; if RC1 is clear, clear RC0
;=====================================
	GOTO	main
;
;  END MAIN LOOP

;*************************************************************************
;
delay1
	CALL	dly200
	BSF	PORTC, 0	;
	RETURN
delay2
	CALL	dly200
	BSF	PORTC, 1	;
	RETURN
delay3
	CALL	dly200
	BSF	PORTC, 2	;
	RETURN
delay4
	CALL	dly200
	BSF	PORTC, 3	;
	RETURN
;
;---------------------------------
delay5
	CALL	dly200
	BCF	PORTC, 3	; clear RC3, last on, first off
	RETURN
delay6
	CALL	dly200
	BCF	PORTC, 2	;
	RETURN
delay7
	CALL	dly200
	BCF	PORTC, 1	;
	RETURN
delay8
   	CALL	dly200
	BCF	PORTC, 0	; clear RC0, first on, last off
	RETURN
;
;   INTERRUPT SERVICE ROUTINE
;
PER_INT 			
	NOP	
;
;Restore registers
;
	SWAPF 	status_temp,W	; swap STATUS_TEMP register into
				; W, sets bank to original state
	MOVWF	STATUS 		; move W into STATUS register
	SWAPF	w_temp,F 	; swap W_TEMP with F
	SWAPF	w_temp,W 	; swap W_TEMP into W
	MOVWF	0X00
	MOVWF	INTCON		; Clear EVERYTHING	
	RETFIE 			; Return from interrupt
;
;   END INTERRUPT SERVICE ROUTINES
;
;**********************************************************************
;
; 100 MSEC DELAY ROUTINE (for dot and dash length routines)
;
dly700	MOVLW   0x82        	; 0x82 = 130 decimal-- change here
        MOVWF   regD
wait7   DECFSZ  regC, F     	
        GOTO    wait7		; each 100 increment in this subroutine
        DECFSZ  regD, F		; is dependent on the length of the clock      	
        GOTO    wait7		; period
dly600	MOVLW   0x82        	; 0x82 = 130  decimal-- change here 		
        MOVWF   regD		; Use of an external RC with 220 pF and 6K8 
wait6   DECFSZ  regC, F		; resistor gives approx 2 uS clock period. 
        GOTO    wait6		; For a 4 MHz (the default) of the internal
        DECFSZ  regD, F		; calibrated oscillator, 016h should be changed 
        GOTO    wait6		; to 82h in seven places.
dly500	MOVLW   0x82        	; 0x82 = 130  decimal-- change here 
        MOVWF   regD		
wait5   DECFSZ  regC, F		; = 3F84 @ 2007h     	
        GOTO    wait5		; FOSC2:FOSC0 = 100 for 4 MHZ internal osc.
        DECFSZ  regD, F      	
        GOTO    wait5
dly400	MOVLW   0x82        	; 0x82 = 130  decimal-- change here 	       	
        MOVWF   regD
wait4   DECFSZ  regC, F     	
        GOTO    wait4
        DECFSZ  regD, F      	
        GOTO    wait4
dly300	MOVLW   0x82        	; 0x82 = 130  decimal-- change here        	
        MOVWF   regD
wait3   DECFSZ  regC, F     	
        GOTO    wait3
        DECFSZ  regD, F      	
        GOTO    wait3
dly200	MOVLW   0x82        	; 0x82 = 130  decimal-- change here        	
        MOVWF   regD
wait2   DECFSZ  regC, F     	
        GOTO    wait2
        DECFSZ  regD, F      	
        GOTO    wait2
dly100	MOVLW   0x82        	; 0x82 = 130  decimal-- change here        	
        MOVWF   regD
wait1   DECFSZ  regC, F     	
        GOTO    wait1
        DECFSZ  regD, F      	
        GOTO    wait1
;	
        RETURN
	end