;
;  PIC16F688
;    Bluetooth and Rotary Commander Controller  Ver 0.1
;		Programmed by DD
;       2010/3/9
;
;	Data Format
;	+---------------+
;	| | |A|A|I|-|-|O|   PORTA  I:Input   O:Output   A:Analog Input
;       +---------------+   
;
;	+---------------+
;	| | |O|O|O|O|O|O|   PORTC  I:Input   O:Output   A:Analog Input
;       +---------------+   
;
;       Input Data
;                           RA1 => Commander Shift (Analog)
;			    AN3 => Commander Signal (Analog)
;			    RA2 => Navi Mute (Active Low)
;
; 	Output Data
;		            RC0 => Skip Forward
;		            RC1 => Skip Backward
;		            RC2 => Amp Remote
;		            RC3 => Volume Up
;		            RC4 => Volume Down
;		            RC5 => Play/Pause
;		            RA0 => Piezo Speaker
;
;
;  Functions

	list    p=pic16F688
	include "p16f688.inc"

; Defining constant

;Threshold Voltage of Keys
TH_POFF		EQU	d'23'
TH_SOURCE	EQU	d'62'
TH_MUTE		EQU	d'99'
TH_SKIPF	EQU	d'129'
TH_SKIPB	EQU	d'150'
TH_VOLU		EQU	d'169'
TH_VOLD		EQU	d'217'

;Key Definitions
OPEN		EQU	d'255'
POFF		EQU	1
SOURCE		EQU	2
MUTE		EQU	3
SKIPF		EQU	4
SKIPB		EQU	5
VOLU		EQU	6
VOLD		EQU	7


;
;
	__FUSES _CPD_OFF & _CP_OFF & _BOD_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

	cblock  0x20    ;Store variables above control registers
	ckey		;commander key (Refer constant definition)
	prev_ckey	;previous key
	prev_ad		;previous a/d value
	curr_ad		;current a/d value
	amppwr		;Amp power status (0:Off 1:ON)
	wcnt1		;Wait Counter1 (For Wait)
	wcnt2		;Wait Counter2 (For Wait)
	wcnt3		;Wait Counter3 (For Wait)
	scnt		;counter for sound
	endc


	org 0x00		;Start of Code Space
;=========================================
;  Start Program (& Wake up from Sleep)
;=========================================
START
	btfss	STATUS,NOT_TO	;If WDT reset
	goto	WDT_INT		;    go to WDT_INT

	bcf	STATUS,RP0	;Set Bank0
	bcf	STATUS,RP1
	movlw	b'00000111'	;Set I/O
	movwf	CMCON0
	bsf	STATUS,RP0	;Set Bank1
	movlw	b'00001000'	;AN3 is analog input
	movwf	ANSEL
	movlw	b'00111110'	;RA5,4,3,2,1:Input,   RA0:Output
	movwf	TRISA
	movlw	b'00111111'	;Weak pullup enable
	movwf	WPUA
	clrw			;Interrupt on change disabled
	movwf	IOCA
	movlw	b'01110000'	;Set A/D clock
	movwf	ADCON1
	clrw			;RC0-5:Output
	movwf	TRISC
	movlw	b'00000000'
	movwf	OPTION_REG
	bcf	STATUS,RP0	;Set bank0
	movlw	b'00001101'
	movwf	ADCON0

	clrf	amppwr		;AMP POWER = OFF
	movlw	OPEN
	movwf	prev_ckey	;prev_ckey = OPEN	
	movwf	ckey		;ckey = OPEN
	clrf	PORTA		;PORTA=0
	clrf	PORTC		;PORTC=0

WDT_SET
	movf	ckey,W
	movwf	prev_ckey	;prev_ckey = ckey
	bcf	STATUS,RP0	;Set bank0
	clrwdt			;Clear WDT
	movlw	b'00001101'	;Set WDTCON 64ms and start
	movwf	WDTCON
	sleep

WDT_INT
;Check Navi Mute
;	AMP REMOTE	amppwr	Navi-mute(active low)
;		0	  0	   don't care
;		1	  1	   1	
;		0	  1	   0

	bcf	WDTCON,0	;Stop Watch Dog Timer
	btfsc	amppwr,0	;If amppwr=0
	goto	$+3
	bcf	PORTC,2		;AMP REMOTE OFF
	goto	CHK_CMD
	btfss	PORTA,2		;If NAVI_MUTE = 0
	goto	$-3		;   AMP REMOTE OFF
	bsf	PORTC,2		;else AMP REMOTE ON

;Check Status of Commander
CHK_CMD
	call	READAD

	movf	ckey,W		;check VOLUME DOWN
	sublw	VOLD
	btfss	STATUS,Z
	goto	$+3
	bsf	PORTC,4		;Volume Down Key
	goto	WDT_SET

	movf	ckey,W		;check VOLUME UP
	sublw	VOLU
	btfss	STATUS,Z
	goto	$+3
	bsf	PORTC,3		;Volume Up Key
	goto	WDT_SET

	movf	ckey,W		;check SKIP BACKWARD
	sublw	SKIPB
	btfss	STATUS,Z
	goto	$+3
	bsf	PORTC,1		;Skip Backward Key
	goto	WDT_SET

	movf	ckey,W		;check SKIP FORWARD
	sublw	SKIPF
	btfss	STATUS,Z
	goto	$+3
	bsf	PORTC,0		;Skip Forward Key
	goto	WDT_SET

	movf	ckey,W		;check MUTE
	sublw	MUTE
	btfss	STATUS,Z
	goto	$+4
	bsf	PORTC,0		;Skip Forward & Play/Pause
	bsf	PORTC,5
	goto	WDT_SET

	movf	ckey,W		;check SOURCE
	sublw	SOURCE
	btfss	STATUS,Z
	goto	CHK_POFF
	movf	prev_ckey,W	;W=prev_ckey
	sublw	SOURCE
	btfsc	STATUS,Z	;if prev_ckey = SOURCE
	goto	WDT_SET		;   go to WDT_SET

	bsf	PORTC,5		;Play/Pause
	btfsc	amppwr,0	;If amppwr=1
	goto	WDT_SET		;   go to WDT_SET
AMP_ON
	bsf	PORTC,2		;AMP REMOTE ON
	bsf	amppwr,0	;amppwr=1
	call	amponsnd	;Amp On sound
	goto	WDT_SET

CHK_POFF
	bcf	PORTC,0
	bcf	PORTC,1
	bcf	PORTC,3
	bcf	PORTC,4
	bcf	PORTC,5

	movf	ckey,W		;check POFF
	sublw	POFF
	btfss	STATUS,Z
	goto	WDT_SET
	movf	prev_ckey,W	;W=prev_ckey
	sublw	POFF
	btfsc	STATUS,Z	;if prev_ckey = POFF
	goto	WDT_SET		;   go to WDT_SET

	btfss	amppwr,0	;If amppwr=0
	goto	AMP_ON		;  go to AMP ON

	bcf	PORTC,2		;AMP REMOTE OFF
	bcf	amppwr,0	;amppwr=0
	call	ampoffsnd	;Amp Off sound
	goto	WDT_SET



;Subroutine
;================================
;  Read A/D
;================================
READAD
	clrf	prev_ad		;prev_ad=0
READADLP
	bsf	ADCON0,GO	;GO=1
	call	wait10ms	;Wait for 10msec
	btfsc	ADCON0,GO	;If GO=1
	goto	$-1		;  go to $-1
	movf	ADRESH,W	;W=ADRESH
	subwf	prev_ad,W	;W=W-prev_ad
	btfsc	STATUS,Z	;If W<>0
	goto	$+4
	movf	ADRESH,W	;W=ADRESH
	movwf	prev_ad		;prev_ad = W
	goto	READADLP	;   go to READADLP

	movf	ADRESH,W	;W=ADRESH
	movwf	curr_ad		;Set current A/D value
	
	movlw	OPEN		;ckey=OPEN
	movwf	ckey
	
	movf	curr_ad,W	;ckeck POFF
	sublw	TH_POFF
	btfss	STATUS,C	;if curr_ad<TH_POFF then
	goto	$+4		;   ckey=POFF
	movlw	POFF
	movwf	ckey
	return
	
	movf	curr_ad,W	;ckeck SOURCE
	sublw	TH_SOURCE
	btfss	STATUS,C	;if curr_ad<TH_SOURCE then
	goto	$+4		;   ckey=SOURCE
	movlw	SOURCE
	movwf	ckey
	return
	
	movf	curr_ad,W	;ckeck MUTE
	sublw	TH_MUTE
	btfss	STATUS,C	;if curr_ad<TH_MUTE then
	goto	$+4		;   ckey=MUTE
	movlw	MUTE
	movwf	ckey
	return
	
	movf	curr_ad,W	;ckeck SKIPF
	sublw	TH_SKIPF
	btfss	STATUS,C	;if curr_ad<TH_SKIPF then
	goto	$+4		;   ckey=SKIPF
	movlw	SKIPF
	movwf	ckey
	return
	
	movf	curr_ad,W	;ckeck SKIPB
	sublw	TH_SKIPB
	btfss	STATUS,C	;if curr_ad<TH_SKIPB then
	goto	$+4		;   ckey=SKIPB
	movlw	SKIPB
	movwf	ckey
	return
	
	movf	curr_ad,W	;ckeck VOLU
	sublw	TH_VOLU
	btfss	STATUS,C	;if curr_ad<TH_VOLU then
	goto	$+4		;   ckey=VOLU
	movlw	VOLU
	movwf	ckey
	return
	
	movf	curr_ad,W	;ckeck VOLD
	sublw	TH_VOLD
	btfss	STATUS,C	;if curr_ad<TH_VOLD then
	goto	$+4		;   ckey=VOLD
	movlw	VOLD
	movwf	ckey
	return
	
	movlw	OPEN		;ckey=OPEN
	movwf	ckey

	return


;================================
;  Wait for 10msec
;================================
wait10ms
	movlw	d'13'		;*13
	movwf	wcnt2
waitlp2	clrf	wcnt1
waitlp1	decfsz	wcnt1,F
	goto	waitlp1
	decfsz	wcnt2,F
	goto	waitlp2
	return

;================================
;  Amp ON Sound
;================================
amponsnd
	bcf	STATUS,RP0	;Set bank0
	movlw	d'88'
	movwf	scnt
ampon1	bsf	PORTA,0		;Set Speaker ON
	call	wait057		;Wait for 0.57msec
	bcf	PORTA,0		;Set Speaker OFF
	call	wait057		;Wait for 0.57msec
	decfsz	scnt,F
	goto	ampon1
	movlw	d'100'
	movwf	scnt
ampon2	bsf	PORTA,0		;Set Speaker ON
	call	wait050		;Wait for 0.50msec
	bcf	PORTA,0		;Set Speaker OFF
	call	wait050		;Wait for 0.50msec
	decfsz	scnt,F
	goto	ampon2
	return

;================================
;  Amp OFF Sound
;================================
ampoffsnd
	bcf	STATUS,RP0	;Set bank0
	movlw	d'100'
	movwf	scnt
ampoff1	bsf	PORTA,0		;Set Speaker ON
	call	wait050		;Wait for 0.50msec
	bcf	PORTA,0		;Set Speaker OFF
	call	wait050		;Wait for 0.50msec
	decfsz	scnt,F
	goto	ampoff1
	movlw	d'88'
	movwf	scnt
ampoff2	bsf	PORTA,0		;Set Speaker ON
	call	wait057		;Wait for 0.57msec
	bcf	PORTA,0		;Set Speaker OFF
	call	wait057		;Wait for 0.57msec
	decfsz	scnt,F
	goto	ampoff2
	return


;================================
;  wait 0.57ms
;================================
wait057
	movlw	d'94'
	movwf	wcnt1
	nop
	nop
	nop
	decfsz	wcnt1,F
	goto	$-4
	return

;================================
;  wait 0.50ms
;================================
wait050
	movlw	d'83'
	movwf	wcnt1
	nop
	nop
	nop
	decfsz	wcnt1,F
	goto	$-4
	return

	end
