; LEDblinker.asm					2005/03/28 17:29:35

; GP5 not use	input
; GP4 AN3	analoginput 点滅周期
; GP3 not use	input
; GP2 LED3	output H
; GP1 LED2	output H
; GP0 LED1	output H
; TRISIO	b'xx111000'

	list		p=PIC12F675
	#include	<P12F675.INC>

	__CONFIG	 _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT

	CBLOCK	20H
	adbuf3			; 点滅周期 A/D変換値
	cntduty			; 点滅周期
	cnttim			; MIN点滅周期
	GPIO_buff		; GPIO出力バッファ
	cnt20u			; カウンタ for 20μsec timer
	W_temp
	FSR_temp
	STATUS_temp
	PCLATH_temp
	ENDC

#define sel_bank0	bcf     STATUS,RP0
#define sel_bank1	bsf     STATUS,RP0

	org	0
init	sel_bank1
	bcf	PCON,1		; パワーONでリセットする
	bsf	PCON,0		; ブラウンアウトリセットしない
	goto	start

	org	4
	movwf	W_temp		; save W
	movf	STATUS,W
	movwf	STATUS_temp	; save STATUS
	movf	FSR,W
	movwf	FSR_temp	; save FSR
	movf	PCLATH,W
	movwf	PCLATH_temp	; save PCLATH
	call	intrqt
	movf	PCLATH_temp,W
	movwf	PCLATH		; restore PCLATH
	movf	FSR_temp,W
	movwf	FSR		; restore FSR
	movf	STATUS_temp,W
	movwf	STATUS		; restore STATUS
	swapf	W_temp,F
	swapf	W_temp,W	; restore W
	retfie

start	call	h'3FF'		; 4MHz発振の補正値を入れる
	movwf	OSCCAL
	movlw	b'00011000'	; fosc/8  AN3
	movwf	ANSEL

	sel_bank0
	clrf	GPIO		; GPIOを初期化する
	movlw	b'00000111'	; コンパレータ未使用
	movwf	CMCON
	movlw	b'00001100'	; select AN3
	movwf	ADCON0		; 左詰め Vdd turn off A/D

	sel_bank1
	movlw	b'00111000'	; GP5～GP3 input GP2～GP0 output
	movwf	TRISIO
	movlw	b'01010111'	; pullup on TMR0CLK=osc/4
	movwf	OPTION_REG	; prescaler=1/256  256μsec

	sel_bank0
	movlw	adbuf3
	movwf	FSR
start1	clrf	INDF		; clear memory
	incf	FSR,F
	movlw	PCLATH_temp+1
	subwf	FSR,W
	btfss	STATUS,Z
	goto	start1

	movlw	b'00000000'
	movwf	GPIO_buff	; GPIO_buff 初期化
	movlw	d'12'		; MIN点滅周期初期化(4.096ms*15=49.152ms)
	movwf	cnttim
	movlw	d'20'
	movwf	cntduty		; cntduty 初期化(dummy 4.096ms*20=81.92msec)
	movlw	d'240'		; set timer value 256-4.096ms/0.256ms = 240
	movwf	TMR0		; TMR0 = 4.096ms
	movlw	b'10100000'	; GIE=1,T0IE=1
	movwf	INTCON		; interrupt enable

main	nop			; 何もしない
	nop			; すべてtimer interruptルーチンで処理する
	goto	main

; -------------------------------interrupt routine-------------------------

intrqt	btfss	INTCON,T0IF	; skip if time out interruption
	return			; return at illegal interrupt
	movlw	d'240'		; set timer value 256-4.096ms/0.256ms = 240
	movwf	TMR0		; TMR0 = 4.096ms
	bcf	INTCON,T0IF	; clear timer int flag
	movf	cnttim,F
	btfsc	STATUS,Z	; skip if cnttim<>0
	goto	intr1
	decf	cnttim,F
	goto	ad_conv

intr1	decfsz	cntduty,F	;skip if cntduty-1=0
	goto	ad_conv
	movlw	d'12'		; MIN点滅周期再設定
	movwf	cnttim
	movf	adbuf3,W	; 点滅周期再設定
	movwf	cntduty
	rrf	cntduty,F
	rrf	cntduty,F
	movlw	d'63'
	andwf	cntduty,F
	incf	cntduty,F	; 0～63を1～64にする

	movlw	b'00000000'
	xorwf	GPIO_buff,W
	btfss	STATUS,Z	; skip if LED1,2,3 off
	goto	intr2
	movlw	b'00000001'	; set LED1
	goto	intr5

intr2	movlw	b'00000001'
	xorwf	GPIO_buff,W
	btfss	STATUS,Z	; skip if LED1 on
	goto	intr3
	movlw	b'00000011'	; set LED1 & LED2
	goto	intr5

intr3	movlw	b'00000011'
	xorwf	GPIO_buff,W
	btfss	STATUS,Z	; skip if LED1 & LED2 on
	goto	intr4
	movlw	b'00000111'	; set LED1 & LED2 & LED3
	goto	intr5

intr4	movlw	b'00000111'
	xorwf	GPIO_buff,W
	btfss	STATUS,Z	; skip if LED1 & LED2 & LED3 on
	goto	ad_conv
	movlw	b'00000000'	; set LED1,2,3 off
intr5	movwf	GPIO_buff
	movwf	GPIO		; output LED pattern


;	A/D変換

ad_conv	movlw	b'00001101'	; select AN3
	movwf	ADCON0
	call	wait2u		; 18+2μsec wait
	bsf	ADCON0,GO	; A/D start
adloop	btfsc	ADCON0,GO	; skip if A/D done
	goto	adloop
	movf	ADRESH,W	; get A/D data
	movwf	adbuf3		; A/D -> adbuf3
	movlw	b'00001100'	; turn off A/D
	movwf	ADCON0
	return

;	20μsec wait

wait2u	movlw	d'5'		; 1 (3n+3)*1サイクル時間(4/fosc)
	movwf	cnt20u		; 1	4MHz 4/4=1μsec 18μsec
wait21	decfsz	cnt20u,F	; 1*(n-1)+2
	goto	wait21		; 2*(n-1)
	return			; 2

	end
