;********************************************
;PIC 12F675 PWM FAN Controller
;2009/09/30 Written By H.Iwaoka
;        + -1 VDD  VSS 8-   -
;  STAT LED-2 GP5  GP0 7-Temp Sensor
;PWM Output-3 GP4  GP1 6-
;          -4 GP3  GP2 5-
;********************************************

list	p=12f675
#include	<p12f675.inc>

;*** VARIABLE DEFINITIONS
;eep_addr	EQU	0x00;

;Timing Constants
TMR0_30us		EQU	d'249';256-30+26(OverHead)

STAT_LED		EQU	d'5';GP5
PWM_OUT			EQU	d'4';GP3
SW1				EQU	d'2';GP2
TEMP_SEN		EQU d'0';GP0(Analog)
GUARD_TIME		EQU	d'10';約5秒

;
tmp_i			EQU	0x20;
tmp_j			EQU	0x21;
timer_1			EQU 0x22;

duty			EQU	0x23; 0<duty<10 (0%-100%)
flag_duty		EQU 0x24;

ad_tmp1		EQU	0x25; AD WorkMemory
ad_tmp2		EQU	0x26; AD WorkMemory
ad_tmp3		EQU	0x27; AD WorkMemory
ad_tmp4		EQU	0x28; AD WorkMemory
ad_tmp5		EQU	0x29; AD WorkMemory
ad_tmp6		EQU	0x2A; AD WorkMemory
ad_tmp7		EQU	0x2B; AD WorkMemory
ad_tmp8		EQU	0x2C; AD WorkMemory

guard		EQU	0x2D

ST_TEMP			EQU	0x5E; for Interrupt
W_TEMP			EQU	0x5F

;********************************************
	ORG	0x000	;RESET Vector
	nop			;for ICD
	goto	main;

;********************************************
	ORG	0x004	;Interrupt vector location

	movwf	W_TEMP		;レジスタ退避
	swapf	STATUS,W
	movwf	ST_TEMP
	bcf		STATUS,RP0

	btfsc	flag_duty,7	;30%
	bcf		GPIO,PWM_OUT
	clrwdt				;WDTリセット
	bcf		INTCON,T0IF	;割込みフラグクリア
	nop

	btfsc	flag_duty,6	;40%
	bcf		GPIO,PWM_OUT
	movf	timer_1,F	;タイマカウンタ減算
	btfss	STATUS,Z
	decf	timer_1,F

	btfsc	flag_duty,5	;50%
	bcf		GPIO,PWM_OUT
	nop
	nop
	nop

	btfsc	flag_duty,4	;60%
	bcf		GPIO,PWM_OUT
	nop
	nop
	nop

	btfsc	flag_duty,3	;70%
	bcf		GPIO,PWM_OUT
	nop
	nop
	nop

	btfsc	flag_duty,2	;80%
	bcf		GPIO,PWM_OUT
	nop
	nop
	nop

	btfsc	flag_duty,1	;90%
	bcf		GPIO,PWM_OUT
	nop
	movlw	TMR0_30us	;約30uS後に割込発生
	movwf	TMR0

	swapf	ST_TEMP,W	;レジスタ復旧開始
	bsf		GPIO,PWM_OUT	;出力ON
	movwf	STATUS
	swapf	W_TEMP,F
	swapf	W_TEMP,W

	retfie

;********************************************
	org		0x100
tbl_duty
	addwf	PCL,F
;			0    1    2    3    4    5    6    7
;			8    9    A    B    C    D    E    F
	dt		0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40;0
	dt		0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40
	dt		0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40;1	10C=0x14
	dt		0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40
	dt		0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40;2
	dt		0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40;	20C=0x28
	dt		0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40;3
	dt		0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x20;	30C=0x3D
	dt		0x20,0x20,0x20,0x20,0x10,0x10,0x10,0x10;4
	dt		0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08
	dt		0x04,0x04,0x04,0x04,0x04,0x04,0x02,0x02;5	40C=0x51
	dt		0x02,0x02,0x02,0x02,0x01,0x01,0x01,0x01
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01;6	50C=0x66
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01;7
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01;8
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01;9
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01;A
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01;B
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01;C
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01;D
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01;E
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01;F
	dt		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01


;********************************************

main					;オプションレジスタ設定
	movlw	0x0F		;Pullup Enable/INT Down Edge
	bsf		STATUS,RP0	;TMR0 Clk Int/TMR0 Clk UP Edge
	movwf	OPTION_REG	;Prescaller WDT/Prescaller 1:128

	call	0x3ff		;オシレーター校正
	movwf	OSCCAL

	movlw	0x00		;Interrupt Disable
	movwf	INTCON
	movwf	PIE1

	bcf		STATUS,RP0	;ポート初期化
	movlw	0xFF
	movwf	GPIO		;GPIO=H
	bsf		STATUS,RP0
	movlw	b'11001111'	;GP4/5 Output
	movwf	TRISIO
	movlw	0x11		;AD Clock=Fosc/8(2us)
	movwf	ANSEL		;AN0 = Analog input
	bcf		STATUS,RP0
	movlw	0x81		;Right fit/Vref=VDD
	movwf	ADCON0		;ch=AN0
;
	bsf		GPIO,PWM_OUT	;Fullpower Statup 3 Sec
	bcf		GPIO,STAT_LED
	movlw	d'250'
	call	dly_ms
	movlw	d'250'
	call	dly_ms
	movlw	d'250'
	call	dly_ms
	movlw	d'250'
	call	dly_ms
	movlw	d'250'
	call	dly_ms
	movlw	d'250'
	call	dly_ms
	movlw	d'250'
	call	dly_ms
	movlw	d'250'
	call	dly_ms
	movlw	d'250'
	call	dly_ms
	movlw	d'250'
	call	dly_ms
	movlw	d'250'
	call	dly_ms
	movlw	d'250'
	call	dly_ms

	movlw	0x01			;for table lookup
	movwf	PCLATH
	movlw	d'10'			;Start Duty 100%
	movwf	duty
	movlw	b'00000001'
	movwf	flag_duty

	movlw	TMR0_30us	;TMR0 START
	movwf	TMR0
	movlw	b'11100000'
	movwf	INTCON

	clrwdt
	clrf	tmp_i	;duty_work
	clrf	guard

main_loop
	movlw	ad_tmp1
	movwf	FSR
	movlw	d'8'	;Loop Count
	movwf	tmp_j

	movf	tmp_i,W
	andwf	flag_duty,W
	btfsc	STATUS,Z
	bcf		GPIO,STAT_LED	;STATUS LED ON
	bsf		STATUS,C
	rrf		tmp_i,F
	btfsc	STATUS,C
	clrf	tmp_i

ad_loop
	bsf		ADCON0,1		;ADC Start
	movlw	0xFF			;50uS ON
	movwf	timer_1
	movf	timer_1,F
	btfss	STATUS,Z
	goto	$-2
	movlw	0xFF			;50uS ON
	movwf	timer_1
	movf	timer_1,F
	btfss	STATUS,Z
	goto	$-2
	bsf		STATUS,RP0		;ADRES Read
	movf	ADRESL,W
	bcf		STATUS,RP0
	movwf	INDF
	movf	ADRESH,W
	andlw	0x03
	movlw	0xFF
	btfss	STATUS,Z
	movwf	INDF
	movlw	0xFF			;50uS OFF
	movwf	timer_1
	movf	timer_1,F
	btfss	STATUS,Z
	goto	$-2
	movlw	0xFF			;50uS OFF
	movwf	timer_1
	movf	timer_1,F
	btfss	STATUS,Z
	goto	$-2
	incf	FSR,F
	movlw	ad_tmp4
	xorwf	FSR,W
	btfsc	STATUS,Z
	bsf		GPIO,STAT_LED
	decfsz	tmp_j,F
	goto	ad_loop

	movf	ad_tmp2,W		;ad ave calcurate
	addwf	ad_tmp1,F
	rrf		ad_tmp1,F
	movf	ad_tmp4,W
	addwf	ad_tmp3,F
	rrf		ad_tmp3,F
	movf	ad_tmp6,W
	addwf	ad_tmp5,F
	rrf		ad_tmp5,F
	movf	ad_tmp8,W
	addwf	ad_tmp7,F
	rrf		ad_tmp7,F
	movf	ad_tmp3,W
	addwf	ad_tmp1,F
	rrf		ad_tmp1,F
	movf	ad_tmp7,W
	addwf	ad_tmp5,F
	rrf		ad_tmp5,F
	movf	ad_tmp5,W
	addwf	ad_tmp1,F
	rrf		ad_tmp1,F

	movf	ad_tmp1,W
	xorlw	0xff		;bit反転
	btfsc	STATUS,Z	;0xffならdec
	decf	ad_tmp1,F
	movf	ad_tmp1,W	;再度読込
	call	tbl_duty

	movwf	ad_tmp1		;一時保存

	subwf	flag_duty,W	;f-w
	btfsc	STATUS,Z	;変化なし
	goto	ad_loop1
	btfsc	STATUS,C	;Cが立っていれば、f>w=回転数アップ
	goto	ad_loop1

	movf	guard,F
	btfsc	STATUS,Z
	goto	ad_loop2

	decf	guard,F
	goto	main_loop
	
ad_loop2
	movlw	GUARD_TIME
	movwf	guard
ad_loop1
	movf	ad_tmp1,W
	movwf	flag_duty
	goto	main_loop





;1ms wait sub
;Wreg=x -> x ms wait
dly_ms
	movwf	tmp_i
dly_ms1
	movlw	d'248'
	movwf	tmp_j
dly_ms2
	clrwdt
	decfsz	tmp_j,F	
	goto	dly_ms2		
	decfsz	tmp_i,F
	goto	dly_ms1
	return





;********************************************
	ORG	0x3FF	;OSC CAL
	retlw	0x5c
	end
;********************************************
