;    Copyright (c) 2007 Noriaki Mitsunaga
	list	p=12f675		; PIC12F675用のプログラムであることを宣言
	#include p12f675.inc		; PIC12F675用のヘッダ・ファイルを読み込む
	__config _INTRC_OSC_NOCLKOUT & _CP_OFF & _BODEN_ON & _PWRTE_ON & _WDT_OFF & _MCLRE_OFF & (1<<12 | 0xff)

	;; コンフィギュレーション：
	;;	内蔵発振子を使う（出力なし）
	;;	ブラウンアウトリセット有効
	;;	パワーアップタイマ使用
	;;	WDT off
	;;	MCLR は使用しない
	;;	BGDATA:	1
	;;	OSCAL:	0xD0 (0x3f に書く)
	
	;; ピン8は GND 
	;; ピン7は A/D入力にする
	;; ピン6はデジタル出力 GP1 で、PGA2311 の SDI (3) へ
	;; ピン5はデジタル出力 GP2 で、PGA2311 の SCLK (6) へ
	;; ピン4はデジタル入力 GP3 で、外部プルアップ
	;; ピン3はデジタル出力 GP4 で、PGA2311 の \CS (2) へ
	;; ピン2はデジタル出力 GP5 で、PGA2311, TA2020 の \MUTE (8) へ
	;; ピン1は 5V
	
CT_DELAY1MS	equ	0x20
CT_DELAYNS	equ	0x21
GPIO_		equ	0x22	; GPIO のバッファ
TMP		equ	0x23
VOL		equ	0x24
SL_LOOP	equ	0x25
SL_DATA	equ	0x26

PGA2311_SDI	equ	1
PGA2311_SCLK	equ	2
PGA2311_CS	equ	4
MUTE		equ	5
	
	org	0x3ff		; 補正値は0x3ffに書く
	retlw	0xD0		; PICを買ったら最初に読み出し補正値をメモしておく
	
	org	0x0		; プログラムは0x0から始まる

	; 初期設定をする
	bcf	STATUS, RP0	; バンク0にする

	movlw	B'010000'	;
	movwf	GPIO_
	movwf	GPIO		; GPIOの出力を CS, MUTE のみ 1 にする

	movlw	0x07		; コンパレータを使わずGP0、GP1、GP2を
	movwf	CMCON		; ディジタル入出力またはA-Dコンバータに割り当て

	bsf	STATUS,RP0	; バンク1にする

	call	0x3FF		; 内部発振子の補正値を読み
	movwf	OSCCAL		; OSCALに書く

	movlw	B'0010001'	; A-Dコンバータの設定 (8TOSC、AN0のみ使う)
	movwf	ANSEL
	
	movlw	B'001001'	; GP1, GP2, GP4, GP5 を出力ピンとして設定する
	movwf	TRISIO

	bcf	STATUS, RP0	; バンク0にする

	movlw	B'00000001'	; A-Dコンバータの設定(左詰め、リファレンスはVDD、AN0入力、ADON=1)
	movwf	ADCON0

	clrf	VOL

	; 初期設定は終了

	; wait 1[s]
	movlw	D'250'
	call	delayns		; wait 250x2 = 500[ms]
	movlw	D'250'
	call	delayns		; wait 250x2 = 500[ms]

	; mute 解除
	bsf	GPIO_, MUTE
	movfw	GPIO_
	movwf	GPIO
	
	; メイン・ルーチン
loop
	; A-D 変換する
	bsf	ADCON0, GO	; A-D 変換開始
	
	btfsc	ADCON0, GO	; A-D 変換終了まで待つ
 	goto	$-1		

	movfw	ADRESH		; A/D　変換結果を読む
	subwf	VOL, w		; 
	movwf	TMP		; TMP = VOL - ADRESH

	btfsc	STATUS, Z	; ADRESH == VOL ならスキップ
	goto	loop_end

	movlw	D'1'
	subwf	TMP, w
	btfsc	STATUS, Z	; VOL - ADRESH -1 == 0 ならスキップ
	goto	loop_end

	movlw	D'1'
	addwf	TMP, w
	btfsc	STATUS, Z	; VOL - ADRESH +1 == 0 ならスキップ
	goto	loop_end
	
	;; 現在の値を記憶
	movfw	ADRESH
	movwf	VOL
		
	;; PGA2311 に新しいボリュームの値を設定する
	
	; \CS を 0 にする
	bcf	GPIO_, PGA2311_CS
	movfw	GPIO_
	movwf	GPIO

	; 右側のボリュームの値をセット
	movfw	ADRESH
	call	send_level

	; 左側のボリュームの値をセット
	movfw	ADRESH
	call	send_level

	; \CS を 1 にする
	bsf	GPIO_, PGA2311_CS	
	movfw	GPIO_
	movwf	GPIO
	
loop_end:
	;; 0.1[s] 待つ
	movlw	D'50'
	call	delayns		; wait 50x2 = 100[ms]

	goto	loop
	; メイン・ルーチンは、ここまで

	;; PGA2311へデータを送る
send_level:	
	movwf	SL_DATA
	movlw	D'8'
	movwf	SL_LOOP

send_level_lp:	
	;; set data
	bcf	GPIO_, PGA2311_SDI
	rlf	SL_DATA, f
	btfsc	STATUS, C
	bsf	GPIO_, PGA2311_SDI

	movfw	GPIO_
	movwf	GPIO
	
	;; toggle SCLK
	bsf	GPIO_, PGA2311_SCLK
	movfw	GPIO_
	movwf	GPIO

	bcf	GPIO_, PGA2311_SCLK
	movfw	GPIO_
	movwf	GPIO

	decfsz	SL_LOOP, f
	goto	send_level_lp

	return

delay10us:
	goto	$+1		; 2
	goto	$+1		; 2
	goto	$+1		; 2

	return			; 2

delay1ms:
	movlw	D'76'		; 1
	movwf	CT_DELAY1MS	; 1
delay1msl1:
	call	delay10us	; 10
	decfsz	CT_DELAY1MS, f	; 1(次の行を実行)、2(次の行はとばす)
	goto	delay1msl1	; 2

	nop			; 1
	goto	$+1		; 2
	goto	$+1		; 2
	goto	$+1		; 2

	return			; 2

delayns:
	movwf	CT_DELAYNS	; 1
	movf	CT_DELAYNS, f	; 1
	btfsc	STATUS, Z	; 1
	return			; 2
delaynsl1:
	call	delay1ms	; 1000
	call	delay1ms	; 1000
	decfsz	CT_DELAYNS, f	; 1(次の行を実行)、2(次の行はとばす)
	goto	delaynsl1	; 2

	return			; 2
 	
	end
