;
; PC Fan Speed Control
;  Measure PWM and turn on 4 outputs at PWM percent setpoints
;
;
;    Copyright (C) 2010 Kevin Timmerman
;    kevinYYYY [@t] compendiumarcana [d0t] com  (YYYY == Current Year)
;    http://www.compendiumarcana.com/pcfan
;
;    This program is free software; you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation; either version 3 of the License, or
;    (at your option) any later version.
;
;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.
;
;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
;
;
; 

;#include <p12HV609.inc>							; Header for PIC12HV609
#include <p12HV615.inc>								; Header for PIC12HV615
													;
													; Config word
	__config _BOR_ON & _IOSCFS_8MHZ & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_ON & _INTOSCIO
													;
	radix dec										; Default to decimal
													;
	errorlevel -302									; Don't complain about bank
													;
	cblock 0x40										; - Register allocation
	sc_msb											; Sample count
	sc_lsb											;
	pwp_msb											; Pulse width
	pwp_lsb											;
	endc											;
													;
													;
	org			0									; Reset vector
	call		Init								;
	goto		Start								;
													;
	org			4									; ISR
	goto		$									;
													;
dsc2:												; Keep the loop isochronous
	goto		dsc									;
													;
Start												;
	clrwdt											;--- Measure the pulse width
													; Increment a counter whenever the pulse width input
													; is high. Do this 100 * 256 times. The pulse width
													; percent will be in the msb of the count.
													; This method does not require a CCP or division, and
													; works over a wide PWM frequency range.
													;
	movlw		100									; Setup loop count
	movwf		sc_msb								; 100 * 256 = 25,600
	clrf		sc_lsb								;
	clrf		pwp_msb								; Clear pulse width percent (pwp)
	clrf		pwp_lsb								;
													;
loop2:												; These two nop would make the loop fully isochronous
	;nop											; They are commented out to introduce some jitter
	;nop											; that will allow more accurate measuement of pulse
													; width when the sample rate is an integer or near
													; integer multiple of the PWM frequency
loop:												;
	btfss		GPIO, 5								; Test the PWM input
	goto		dsc2								; Skip the increment if low...
	incf		pwp_lsb, F							; Increment the Pulse Width Percent
	btfsc		STATUS, Z							; Inc msb if lsb overflows
	incf		pwp_msb, F							;
dsc:												;
	decfsz		sc_lsb, F							; Decrement sample count lsb
	goto		loop2								;
	decfsz		sc_msb, F							; Decrement sample count msb
	goto		loop								;
													;
													; --- Compare pulse width to setpoints
	movf		pwp_msb, W							; Compare pulse with percent to setpoint for speed 5
	addlw		-91									;
	btfsc		STATUS, C							;
	goto		speed5								; If greater than or equal to...
													;
	movf		pwp_msb, W							; Compare pulse with percent to setpoint for speed 4
	addlw		-71									;
	btfsc		STATUS, C							;
	goto		speed4								;
													;
	movf		pwp_msb, W							; Compare pulse with percent to setpoint for speed 3
	addlw		-51									;
	btfsc		STATUS, C							;
	goto		speed3								;
													;
	movf		pwp_msb, W							; Compare pulse with percent to setpoint for speed 2
	addlw		-31									;
	btfsc		STATUS, C							;
	goto		speed2								;
													;
	;goto		speed1								; Must be speed 1...
													;
													;
													; --- Turn on outputs based on setpoint comparison
speed1:												; 0 to 30
	movlw		(1 << 0)							;
	goto		set_speed							;
speed2:												; 31 to 50
	movlw		(1 << 1)							;
	goto		set_speed							;
speed3:												; 51 to 70
	movlw		(1 << 2)							;
	goto		set_speed							;
speed4:												; 71 to 90
	movlw		(1 << 4)							;
	goto		set_speed							;
speed5:												; 91 to 100
	movlw		0									;
	;goto		set_speed							;
													;
set_speed:											;
	movwf		GPIO								;
													;
	goto		Start								; --- Repeat forever
													;
													;
													;
													;
													;
Init												; - Setup I/O
	bsf			STATUS, RP0							;
													;
													; Make GP3 and GP5 inputs, all others output
	movlw		(1 << 3) | (1 << 5)					;
	movwf		TRISIO								;
													; *GPPU = 0 - WPU enabled
													; INTEDG = 0
													; T0CS = 1 - Internal clock source
													; T0SE = 1 - Inc on falling edge
													; PSA = 1 - Assign prescaller to WDT
													; PSx - WDT prescaler = 2 (32:1), 576 mS
	movlw		(1<<T0CS) | (1<<T0SE) | (1<<PSA) | (1<<PS2)
	movwf		OPTION_REG							; Set options
													;
#ifdef __12HV615									;
	clrf		ANSEL								; Make all inputs digital
#endif												;
													;
	movlw		0									; Setup pull-ups
	movwf		WPU									;
													;
													;
	bcf			STATUS, RP0							;
													;
	return											;
													;
	end												;

