;
;  PIC16F688
;    Bluetooth and Rotary Commander Controller  Ver 0.5
;		Programmed by DD
;       2014/8/10
;
;	Data Format
;	+---------------+
;	| | |O|A|-|I|O|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
;			    AN3 => Commander Signal (Analog)
;
; 	Output Data
;		            RC0 => DN(Skip Forward)
;		            RC1 => UP(Skip Backward)
;		            RC3 => Play(Pause)
;		            RC4 => V+(Volume Up)
;		            RC5 => V-(Volume Down)
;		            RA0 => Piezo Speaker
;
;  Functions

	list    p=pic16F688
	include "p16f688.inc"

; Defining constant

;Threshold Voltage of Keys
TH_SOURCE	EQU	d'62'
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'
PLAY		EQU	2
SKIPF		EQU	4
SKIPB		EQU	5
VOLU		EQU	6
VOLD		EQU	7
SHIFT		EQU	8


;
;
	__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
	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'00011100'	;RA4,3,2:Input,   RA5,1,0: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	PORTA		;PORTA=0
	clrf	PORTC		;PORTC=0
	movlw	OPEN
	movwf	prev_ckey	;prev_ckey = OPEN	
	movwf	ckey		;ckey = OPEN

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
	bcf	WDTCON,0	;Stop Watch Dog Timer

;Check Status of Commander
CHK_CMD
	call	READAD

	movf	ckey,W		;check VOLUME DOWN
	sublw	VOLD
	btfss	STATUS,Z
	goto	$+7
	bsf	PORTC,5		;Volume Down Key
	movf	prev_ckey,W
	sublw	VOLD
	btfss	STATUS,Z
	call	peesnd
	goto	WDT_SET

	movf	ckey,W		;check VOLUME UP
	sublw	VOLU
	btfss	STATUS,Z
	goto	$+7
	bsf	PORTC,4		;Volume Up Key
	movf	prev_ckey,W
	sublw	VOLU
	btfss	STATUS,Z
	call	peesnd
	goto	WDT_SET

	movf	ckey,W		;check SKIP BACKWARD
	sublw	SKIPB
	btfss	STATUS,Z
	goto	$+7
	bsf	PORTC,1		;Skip Backward Key
	movf	prev_ckey,W
	sublw	SKIPB
	btfss	STATUS,Z
	call	peesnd
	goto	WDT_SET

	movf	ckey,W		;check SKIP FORWARD
	sublw	SKIPF
	btfss	STATUS,Z
	goto	$+7
	bsf	PORTC,0		;Skip Forward Key
	movf	prev_ckey,W
	sublw	SKIPF
	btfss	STATUS,Z
	call	peesnd
	goto	WDT_SET

	movf	ckey,W		;check PLAY
	sublw	PLAY
	btfss	STATUS,Z
	goto	$+7
	bsf	PORTC,3		;Play Key
	movf	prev_ckey,W
	sublw	PLAY
	btfss	STATUS,Z
	call	peesnd
	goto	WDT_SET

	bcf	PORTC,0
	bcf	PORTC,1
	bcf	PORTC,3
	bcf	PORTC,4
	bcf	PORTC,5

	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 PLAY
	sublw	TH_SOURCE
	btfss	STATUS,C	;if curr_ad<TH_SOURCE then
	goto	$+4		;   ckey=PLAY
	movlw	PLAY
	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

	btfsc	PORTA,1		;If SHIFT KEY then
	goto	$+4
	movlw	SHIFT
	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

;================================
;  Pee sound
;================================
peesnd
	bcf	STATUS,RP0	;Set bank0
	movlw	d'167'
	movwf	scnt
peesnd1	bsf	PORTA,0		;Set Speaker ON
	call	wait030		;Wait for 0.30msec
	bcf	PORTA,0		;Set Speaker OFF
	call	wait030		;Wait for 0.30msec
	decfsz	scnt,F
	goto	peesnd1
	return


;================================
;  wait 0.30ms
;================================
wait030
	movlw	d'50'
	movwf	wcnt1
	nop
	nop
	nop
	decfsz	wcnt1,F
	goto	$-4
	return

	end
