;

		DEVICE	SX18,osc4mhz,TURBO
		DEVICE  stackx_optionx,watchdog
		RESET	Start_Point
		FREQ 	4_000_000

;### CALIBRATION CONSTANTS ###
BleedConstH	EQU	$28
BleedConstL	EQU	$F5		;4 G/Hr
OutputConstH	EQU	$F0
OutputConstM	EQU	$62
OutputConstL	EQU	$B6		;45000 ppg in, 47923 ppg out
;#############################

Global		EQU	$07
Math		EQU	$10

	org 	Global
CountIn		ds	2
CountOut	ds	2
ClockIn		ds	2	
ClockOut	ds	2
Flags		ds	1
	org	MATH
X_var		ds	3
Y_var		ds	3
Z_var		ds	3
counter		ds	1

SIG_IN		EQU	ra.2 		;Signal Input from Flow Sensor
SIG_OUT		EQU	ra.1 		;Signal Output to Tripminder

InFall		EQU	Flags.0		;set high on falling edge of input signal
No_Flow		EQU	Flags.1		;set high if output too low to count
Is_Zero		EQU	Flags.2		;low if test not zero
		
		org	0

;___________Interupt Routine_______________
isr		snb	SIG_IN
		clrb	InFall			;clear flag if signal high

		ijnz	ClockIn,:yes_flow		
		ijnz	ClockIn+1,:yes_flow	;inc clock count

		mov	CountIn,#$FF		
		mov	CountIn+1,#$FF		;set to highest value if overflow
		jmp	:out

:yes_flow	jb	InFall,:out
		jb	SIG_IN,:out		;jump if not falling edge

		mov	CountIn,ClockIn		
		mov	CountIn+1,ClockIn+1	;save period count
		clr	ClockIn
		clr	ClockIn+1		;clear clock count
		setb	InFall			;set flag
		
:out		ijnz	ClockOut,:end
		ijnz	ClockOut+1,:end		;inc clock count
		
		mov	ClockOut,CountOut
		mov	ClockOut+1,CountOut+1	;move new value to clock counter

		jb	No_Flow,:end		;jump if flag set

		xor	ra,#%0010		;invert output
		
:end		mov	w,#-50
		retiw

;___________Program Start_________________
Start_Point 	bank	MATH
		mode	Level
		mov	!ra,#%0000
		mov	!rb,#%00000000
		mode	Direction
		mov	!ra,#%0100
		mov	!rb,#%00000000
		clr	ra
		clr	rb
		mov	CountIn,#$FF
		mov	CountIn+1,#$FF
		mov	CountOut,#$FF
		mov	CountOut+1,#$FF
		mov	ClockOut,#$FF
		mov	ClockOut+1,#$FF
		
		mov	!option,#$8f	;initialize interrupt
				
		
;___________Main Loop______________________
Main		clr	!wdt
		mov	Z_var+2,#$FF
		mov	Z_var+1,#$FF
		mov	Z_var,#$FF
		clr	X_var+2
		mov	X_var+1,CountIn+1
		mov	X_var,CountIn
		call	Divide			;calculate input flow

		sub	Y_var+1,#BleedConstH	;subtract bleed flow
		jc	:not_over_1
		sub	Y_var+2,#1
		jnc	:no_Out			;jump if flow less than bleed
:not_over_1	sub	Y_var,#BleedConstL	
		jc	:not_over_2
		sub	Y_var+1,#1	
		jc	:not_over_2
		sub	Y_var+2,#1
		jnc	:no_Out			;jump if flow less than bleed
	
:not_over_2	setb	Is_Zero
		test	Y_var+2
		sz
		clrb	Is_Zero
		test	Y_var+1
		sz
		clrb	Is_Zero
		test	Y_var
		sz
		clrb	Is_Zero
		nop
		jb	Is_Zero,:no_Out		;jump if div by zero

		mov	Z_var+2,#OutputConstH
		mov	Z_var+1,#OutputConstM
		mov	Z_var,#OutputConstL
		mov	X_var+2,Y_var+2
		mov	X_var+1,Y_var+1
		mov	X_var,Y_var
		call	Divide			;calculate output period

		clc	
		rr	Y_var+2
		rr	Y_var+1
		rr	Y_var			;divide by 2, 50% duty

		test	Y_var+2
		jnz	:no_Out			;jump if count exceeds 2 bytes

		not	Y_var+1
		not	Y_var
		inc	Y_var
		snz
		inc	Y_var+1			;negate value, clock counts up

		mov	CountOut,Y_var
		mov	CountOut+1,Y_var+1	;save new value for next count
		
		clrb	No_Flow			;clear flag to turn on output

		jmp	Main

:no_Out		mov	CountOut,#$FF
		mov	CountOut+1,#$FF		;set new value to maximum
		
		setb	No_Flow			;set flag to turn off output

		jmp	Main

;__________Divide__________________________
	;Z_var/X_var=Y_var; zz_zz_zz / xx_xx_xx = yy_yy_yy
Divide		clr	counter
		clc
:dloop		rl	X_var
		rl	X_var+1
		rl	X_var+2
		inc	counter
		jnc	:dloop
		rr	X_var+2
		rr	X_var+1
		rr	X_var
		clr	Y_var
		clr	Y_var+1
		clr	Y_var+2

:ddloop		test	counter
		jz	:ddone
		clc
		rl	Y_var
		rl	Y_var+1
		rl	Y_var+2
		cjb	Z_var+2,X_var+2,:ddloop1
		cje	Z_var+2,X_var+2,:dequal
		jmp	:dfinish
:dequal		cjb	Z_var+1,X_var+1,:ddloop1
		cje	Z_var+1,X_var+1,:equalx
		jmp	:dfinish
:equalx		cjb	Z_var,X_var,:ddloop1
:dfinish	sub	Z_var+2,X_var+2
		sub	Z_var+1,X_var+1
		sc
		dec	Z_var+2
		sub	Z_var,X_var
		sc
		dec	Z_var+1
		inc	Y_var
		snz
		inc	Y_var+1
		snz
		inc	Y_var+2

:ddloop1	dec	counter
		clc
		rr	X_var+2
		rr	X_var+1
		rr	X_var
		jmp	:ddloop

:ddone		ret




