;Filename:	ssuba.asm
;Author:	David Hill	
;Date:  	March 2004
;Version:	1.0

	list      p=12F629        		; list directive to define processor
	#include <p12f629.inc>          ; processor specific variable definitions

	errorlevel  -302               ; suppress message 302 from list file

	__CONFIG   _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT  

#define	BANK1		bsf STATUS,RP0
#define	BANK0		bcf STATUS,RP0
#define	COMPCONTROL	b'00010100'		;Used to configure Comparator
#define	HIGHVOLT	b'10001110'		;voltage from IR when diaphragm at bottom (IR wide open)
#define	LOWVOLT		b'10100111'		;voltage from IR when diaphragm at top (IR closed)
#define INPUTS		b'11011111'		;GP5 is the output
#define TIMER1ON	b'00000001'		;setup timer 1 control register
#define TIMER1OFF	b'00000000'		;setup timer 1 control register

;1.8 ms and 18.2 ms
#define FillTimerLowMSB  0xB8 ;low portion of 50 hz signal
#define FillTimerLowLSB  0xf5
#define FillTimerHighMSB 0xF9 ;high portion of 50 hz signal
#define FillTimerHighLSB 0x04

;1.2 ms and 18.8 ms
#define VentTimerLowMSB  0xB6 ;low portion of 50 hz signal
#define VentTimerLowLSB  0x9D
#define VentTimerHighMSB 0xFB ;high portion of 50 hz signal
#define VentTimerHighLSB 0x5C


	;1 millisecond high = 65536 - 1000 + 12 = 0xFC24
	;19 millisecond low = 65536 - 19000 + 13 = 0xB5D5

	;2 millisecond high = 65536 - 2000 + 12 = 0xF8C3
	;18 millisecond low = 65536 - 18000 + 13 = 0xB9BD

	;1.8 ms high = 65536 - 1800 + 12 = 0xF904
	;18.2 ms low = 65536 - 18200 + 13 = 0xB8F5

	;1.2 ms high = 65536 - 1200 + 12 = 0xFB5C
	;18.8 ms low = 65536 - 18800 + 13 = 0xB69D

	cblock	0x20
	TimerLowMSB
	TimerLowLSB
	TimerHighMSB
	TimerHighLSB
	Delay
	DelayDone
	endc

;****************************************************************************
;start
;****************************************************************************
	ORG     0x0000           ; startup code is at 0x000
	goto	START

	ORG 0x0004
			;interupt entry point, we only have the 16 bit timer1 interupt enabled.
			;internal clock is 4 Mhz, a timer cycle is 4 clock cycles or 1 Mhz.
			;the 16 bit timer counts up once every timer cycle, one million times
			;a second. One microsecond = 1,000 counts. 20 microseconds = 20,000 counts.
			;the high and low pulse counts are loaded into the variables depending on
			;which state the machine is in. We are trying to output 50 hertz pulses,
			;the high part of the pulse is between 1 and 2 milliseconds,
			;the low part is 18 to 19 milliseconds,
			;the sum of the low and high times must equal 20 milliseconds to maintain 50 hz.
			;It takes 12 and 13 cycles to get through the timer code and get the
			;timer running again, ought to subtract that from the high/low constants.
			;So if I want 1.5 milliseconds high time (servo centered) I need
			;18.5 milliseconds of low time, I need to set
			;TimerHigh to 65536 - 1500 + 12 = 0xFA msb and 0x30 lsb
			;and set TimerLow to 65536 - 18500 + 13 = 0xB7 msb and 0xC9 lsb

			;1 millisecond high = 65536 - 1000 + 12 = 0xFC24
			;19 millisecond low = 65536 - 19000 + 13 = 0xB5D5

			;2 millisecond high = 65536 - 2000 + 12 = 0xF8C3
			;18 millisecond low = 65536 - 18000 + 13 = 0xB9BD
	BANK0

	movlw	TIMER1OFF
	movwf	T1CON

	bcf		PIR1,TMR1IF	;clear the timer 1 interupt flag
	btfss	GPIO,GPIO5
	goto	GO_HIGH
GO_LOW 		;if GPIO5 is currently HIGH

	decfsz	Delay, F ;decrement the vent cycle delay counter 50 times a second
	goto DELAY_NOT_DONE
	bcf DelayDone, 0
DELAY_NOT_DONE

	bcf		GPIO,GPIO5
	movf	TimerLowLSB,W
	movwf	TMR1L
	movf	TimerLowMSB,W
	movwf	TMR1H

	movlw	TIMER1ON
	movwf	T1CON

	retfie
GO_HIGH		;if GPIO5 is currently LOW
	bsf 	GPIO,GPIO5
	movf 	TimerHighLSB,W
	movwf 	TMR1L
	movf 	TimerHighMSB,W
	movwf 	TMR1H

	movlw	TIMER1ON
	movwf	T1CON

	retfie

START
	BANK1
	call 	3ffh
	movwf 	OSCCAL

	BANK0
	clrf	GPIO	;set all output latches to zero

	BANK1
	movlw	INPUTS
	movwf	TRISIO
	bsf		PIE1,TMR1IE	;enable timer 1 interupt

	BANK0
	movlw	TIMER1ON
	movwf	T1CON

	bsf		INTCON,GIE	;Turn on Global Interrupts
	bsf		INTCON,PEIE	;enable peripheral interupts
	bcf		PIR1,TMR1IF	;clear the timer 1 interupt

	movlw	COMPCONTROL	
	movwf	CMCON		;Configure Comparator 	

Fill_State		; stay in this state until the comparitor goes below the low voltage threshold

	BANK1
	movlw	LOWVOLT
	movwf 	VRCON

	BANK0
	movlw	FillTimerLowLSB
	movwf	TimerLowLSB
	movlw	FillTimerLowMSB
	movwf	TimerLowMSB

	movlw	FillTimerHighLSB
	movwf	TimerHighLSB
	movlw	FillTimerHighMSB
	movwf	TimerHighMSB

Fill_State_Loop

	btfsc	CMCON,COUT	;clears when pin voltage drops below low voltage
	goto	Fill_State_Loop

Vent_State	;stay in this state for a fixed amount of time. The Delay counter decrements 50 times a sec

	BANK0
	movlw	VentTimerLowLSB
	movwf	TimerLowLSB
	movlw	VentTimerLowMSB
	movwf	TimerLowMSB

	movlw	VentTimerHighLSB
	movwf	TimerHighLSB
	movlw	VentTimerHighMSB
	movwf	TimerHighMSB

	movlw 	0x10 ;50 = 1 second
	movwf	Delay
    bsf DelayDone, 0
NextDelay
	btfsc DelayDone,0
	goto NextDelay
	goto	Fill_State
	end

