; Pulse Counter - written by: Christopher Cole
; OSC = 4 MHz (internal) --> 1 cyc = 1 uS
; Pins: 1=Gnd, 3&4=4 MHz xtal, 5=pulse_in, 6=Rx, 7=Tx, 8=+5V

	TITLE	"Pulse Counter"
	LIST	P=12C508a

#include "C:\progra~1\mplab\p12c508a.inc"

	__FUSES _MCLRE_ON & _CP_OFF & _WDT_OFF & _XT_OSC

;----------------------------------------------------------------------------------------------------
#define TXpin232	GPIO,0	; (pin 7) output
#define RXpin232	GPIO,1	; (pin 6) input
;----------------------------------------------------------------------------------------------------
RAMbase	EQU	0x07		; beginning of general purpose registers
;----------------------------------------------------------------------------------------------------
; DNOP - Double NOP. Delay of 2 cycles, takes only one instruction
DNOP		MACRO		;
		LOCAL	Label	;
Label		GOTO	Label+1	;
		ENDM		;
;----------------------------------------------------------------------------------------------------
; Delay3W - Delay 3 * W cycles, three instructions
Delay3W	MACRO			;
		LOCAL	Label	;
		MOVWF	delay	;
Label		DECFSZ	delay	;
		GOTO	Label	;
		ENDM		;
;----------------------------------------------------------------------------------------------------
CBLOCK	RAMbase			;
		delay		;
		BitsToGo	;
		SerByte		;
		inputIdle	; is the input pulse normally high, or normally low?
		edgeCountHigh	;
		edgeCountLow	;
		pulseOnes	;
		pulseTens	;
		pulseHundreds	;
		pulseThousands	;
ENDC				;
;----------------------------------------------------------------------------------------------------
	ORG	0		;
;	movwf   OSCCAL          ; Set oscillator calibration reg. - NOT NEEDED
	GOTO	Main		;
;----------------------------------------------------------------------------------------------------
Main				;
Init				;
	movlw   b'11000000'     ;
	option                  ;
	movlw	0		; init ports
	movwf	GPIO		;
	movlw	b'00000110'	; GPIO 0 is output, GPIO 1 and 2 are inputs
	tris	GPIO		;
	bsf	TXpin232	; Tx set high (idle state)
	clrf	edgeCountHigh	;
	clrf	edgeCountLow	;
	clrf	pulseOnes	;
	clrf	pulseTens	;
	clrf	pulseHundreds	;
	clrf	pulseThousands	;
	call	SetInputIdle	;
	call	Ready		;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
GetEdge				;
	btfsc	inputIdle,0	;
	  GOTO	LookForLow	;
;	GOTO	LookForHigh	;	
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
LookForHigh			;
	movf	GPIO,w		; get current state of all input pins
	andlw	0x04		; look at pulse input
	xorlw	0x04		; test bit
	btfss	STATUS,Z	; is zero flag set?
	  GOTO	LookForHigh	;
	movlw	0x01		;
	movwf	inputIdle	;
	movlw	'/'		;
	call	SendChar232	;
	GOTO	IncEdgeCount	;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
LookForLow			;
	movf	GPIO,w		; get current state of all input pins
	andlw	0x04		; look at pulse input
	xorlw	0x04		; test bit
	btfsc	STATUS,Z	; is zero flag set?
	  GOTO	LookForLow	;
	movlw	0x00		;
	movwf	inputIdle	;
	movlw	'\\'		;
	call	SendChar232	;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
IncEdgeCount			;
	incf	edgeCountLow	;
	btfsc	STATUS,Z	;
	  incf	edgeCountHigh	;
	btfsc	edgeCountLow,0	;
	  return		;
IncDecimal			; we have completed a pulse (a pair of edges detected)
	incf	pulseOnes	;
	movlw	0x0a		;
	xorwf	pulseOnes,w	; did we count to ten yet?
	btfss	STATUS,Z	;
	  GOTO	DoneIncDecimal	;
	clrf	pulseOnes	;
	incf	pulseTens	;
	movlw	0x0a		;
	xorwf	pulseTens,w	; did we count to a hundred yet?
	btfss	STATUS,Z	;
	  GOTO	DoneIncDecimal	;
	clrf	pulseTens	;
	incf	pulseHundreds	;
	movlw	0x0a		;
	xorwf	pulseHundreds,w	; did we count to a thousand yet?
	btfss	STATUS,Z	;
	  GOTO	DoneIncDecimal	;
	clrf	pulseHundreds	;
	incf	pulseThousands	;
	movlw	0x0a		;
	xorwf	pulseThousands,w; did we count to ten thousand yet?
	btfss	STATUS,Z	;
	  GOTO	DoneIncDecimal	;
	clrf	pulseThousands	;
DoneIncDecimal			;
	movlw	' '		;
	call	SendChar232	;
	movlw	'0'		;
	addwf	pulseThousands,w;
	call	SendChar232	;
	movlw	'0'		;
	addwf	pulseHundreds,w	;
	call	SendChar232	;
	movlw	'0'		;
	addwf	pulseTens,w	;
	call	SendChar232	;
	movlw	'0'		;
	addwf	pulseOnes,w	;
	call	SendChar232	;
	movlw	0x0a		;
	call	SendChar232	;
	movlw	0x0d		;
	call	SendChar232	;
	return			;
	GOTO	GetEdge		;
;----------------------------------------------------------------------------------------------------
Wait232				; blocking process
	btfsc	RXpin232	;
	  goto	Wait232		;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Get232				; returns serial value in w register
	movlw	8		;
	movwf	BitsToGo	;
	movlw	0x30		;
	Delay3W			; wait for startbit to pass (312+(312/2) cycles) and get into middle of first bit
GetNextBit232			;
	bcf	STATUS,C	; [1] zero out CARRY to begin with
	btfsc	RXpin232	; [1]
	  bsf	STATUS,C	; [1]
	rrf	SerByte		; [1] rotate right, bring in carry bit on left side
	movlw	0x20		; [1]
	Delay3W			; [96]
	decfsz	BitsToGo	; [1]
	  goto	GetNextBit232	; [2]
	movf	SerByte,w	;
	return			;
;----------------------------------------------------------------------------------------------------
SendChar232			;
	movwf	SerByte		; store char to send out
	movlw	8		;
	movwf	BitsToGo	; # bits to send out
	bcf	TXpin232	; [1]send out start bit
	movlw	0x22		; [1] set length for start bit
	Delay3W			; [102]
TXLoop232			;
	rrf	SerByte		; [1]
	btfsc	STATUS,C	; [1] is it a 1?
	  goto	TXOne232	; [2] yes - send a '1'
	bcf	TXpin232	; [1]
	nop			; [1]
	movlw	0x20		; [1]
	Delay3W			; [96]
	decfsz	BitsToGo	; [1]
	  goto	TXLoop232	; [2]
	goto	DoneByte232	;
TXOne232			;
	bsf	TXpin232	; [1]
	movlw	0x20		; [1]
	Delay3W			; [96]
	decfsz	BitsToGo	; [1]
	  goto	TXLoop232	; [2]
DoneByte232			;
	bsf	TXpin232	; [1] send out stop bit
	movlw	0x20		; [1]
	Delay3W			; [96]
	bsf	TXpin232	; idle state for TXpin
	return			;
;----------------------------------------------------------------------------------------------------
Ready
	movlw	'R'		;
	call	SendChar232	;
	movlw	'e'		;
	call	SendChar232	;
	movlw	'a'		;
	call	SendChar232	;
	movlw	'd'		;
	call	SendChar232	;
	movlw	'y'		;
	call	SendChar232	;
	movlw	'.'		;
	call	SendChar232	;
	movlw	0x0a		;
	call	SendChar232	;
	movlw	0x0d		;
	call	SendChar232	;
	return			;
;----------------------------------------------------------------------------------------------------
SetInputIdle			; figure out initial state of pulse input pin
	movlw	0x0a		;
	call	SendChar232	;
	movlw	0x0d		;
	call	SendChar232	;
	movlw	'N'		;
	call	SendChar232	;
	movlw	'o'		;
	call	SendChar232	;
	movlw	'r'		;
	call	SendChar232	;
	movlw	'm'		;
	call	SendChar232	;
	movlw	'a'		;
	call	SendChar232	;
	movlw	'l'		;
	call	SendChar232	;
	movlw	'l'		;
	call	SendChar232	;
	movlw	'y'		;
	call	SendChar232	;
	movlw	' '		;
	call	SendChar232	;
	movf	GPIO,w		; get current state of all input pins
	andlw	0x04		; look at pulse input
	xorlw	0x04		; test bit
	btfsc	STATUS,Z	; is zero flag set?
	  GOTO	InputIdleHigh	;
	GOTO	InputIdleLow	;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
InputIdleHigh			;
	movlw	0x01		;
	movwf	inputIdle	; set high flag
	movlw	'H'		;
	call	SendChar232	;
	movlw	'I'		;
	call	SendChar232	;
	movlw	'G'		;
	call	SendChar232	;
	movlw	'H'		;
	call	SendChar232	;
	GOTO	Detected	;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
InputIdleLow			;
	movlw	0x00		;
	movwf	inputIdle	; set low flag
	movlw	'L'		;
	call	SendChar232	;
	movlw	'O'		;
	call	SendChar232	;
	movlw	'W'		;
	call	SendChar232	;
;	GOTO	Detected	;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Detected			;
	movlw	' '		;
	call	SendChar232	;
	movlw	'D'		;
	call	SendChar232	;
	movlw	'e'		;
	call	SendChar232	;
	movlw	't'		;
	call	SendChar232	;
	movlw	'e'		;
	call	SendChar232	;
	movlw	'c'		;
	call	SendChar232	;
	movlw	't'		;
	call	SendChar232	;
	movlw	'e'		;
	call	SendChar232	;
	movlw	'd'		;
	call	SendChar232	;
	movlw	'.'		;
	call	SendChar232	;
	movlw	0x0a		;
	call	SendChar232	;
	movlw	0x0d		;
	call	SendChar232	;
	return			;
;----------------------------------------------------------------------------------------------------
	END			;


