
; This program reads a Sony Rotary Commander control stick and based on its input
; sends ASCII commands via 4800 baud RS-232


	device	pic12c509,irc_osc,wdt_on,protect_off,mclr_off

; Constants
bit_K		=	50     		; 4800 baud with 4MHz system clock
out_pot		=	11101110b	; Value to set GPIO.4 to output for pot.
in_pot		=	11111110b	; Value to set GPIO.4 to input for pot.
RepeatRate	=	64		; Speed at which slow buttons like track skip
					; repeat (not fast buttons like volume)

; Pins
serial_out	=	GPIO.0	; Pin assigned to RS-232 port Xmit pin
shift		=       GPIO.1  ; Pin assigned to control stick shift button
pot		=       GPIO.4	; Pin connected to (0.1uF cap to GND) and (Var Res to GND)



; Variables
        org     8
temp    ds      1       ; Temporary counter for delay.
potL    ds      1       ; Low byte of Pot measurement.
potH    ds      1       ; High byte of Pot measurement.

delay_cntr	ds	1		;Counter for serial delay routines
bit_cntr	ds	1		;Number of transmitted bits
msg_cntr	ds	1		;Offset in string
xmt_byte	ds	1		;The transmitted byte

Btn	ds	1
LastBtn	ds	1
LastBt2	ds	1
LastBt3	ds	1

StrPtr	ds	1

flags	ds	1
Preset	ds	1
RepCnt	ds	1



        org     0
	mov	OSCCAL, W

	mov	LastBtn, #0FFh
	clr	Flags

	jmp	Setup



ReadPot		; Read variable resistor
        setb    pot		; Start charging cap.
        mov     !GPIO,#out_pot
        mov     potL,#8		; Set up for 6-ms delay: 8 trips
:wait   djnz    temp,:wait	; through outside loop x 256
        djnz    potL,:wait	; x 3 cycles for inside loop = 6.1 ms.
        clr     potH
	mov	potL, #1
        mov     !GPIO,#in_pot	; Get input from pot.
:loop   jnb     pot,:done	; IF pot = 0 THEN :done
        inc     potL		; Incerement potL.
        snz			; If zero then potL overfolowed, so
        incsz   potH		; increment potH. If it overflows, exit.
        jmp     :loop		; Overflowed? No: loop.
:done

	ret


SlwrSnd	mov     potH, #64	; 1/20 second delay - used for delaying strings of
				; characters like the shuffle sequence
:wait1
	djnz    potL, :wait1
	djnz    potH, :wait1


SlowSnd	mov     potH, #64	; 1/20 second delay - used for delaying fast
				; repeating buttons like volume
:wait1
	djnz    potL, :wait1
	djnz    potH, :wait1


Send	mov	bit_cntr,#8	; Send a character now 
	setb	serial_out	

	call	BitDly		;Start bit. 

:loop	rr	xmt_byte	;Rotate right moves data bits into
				;carry, starting with bit 0. 
	movb	serial_out,/c

	call	BitDly		;Data bit. 
	djnz	bit_cntr,:loop	;Not eight bits yet? Send next data bit

	clrb	serial_out

	call	BitDly		;Stop bit. 

	clrwdt
	ret


BitDly	mov	delay_cntr, #bit_K
:loop	nop
	djnz	delay_cntr, :loop
	ret



ResTbl	jmp	PC+W

	retw	00h, 000h	; Above this is Power	0
	retw	00h, 017h	; Above this is Source	1
	retw	00h, 043h	; Above this is ATT	2	(mute)
	retw	00h, 070h	; Above this is Front	3	(list/disp)
	retw	00h, 09Eh	; Above this is Seek Dn	4	(seek up)
	retw	00h, 0D6h	; Above this is Seek Up	5	(seek dn)
	retw	01h, 026h	; Above this is Vol Dn	6	(vol up)
	retw	01h, 09Ah	; Above this is Vol Up	7	(vol dn)
	retw	02h, 042h	; Above this is Back	8	(select)
	retw	03h, 03Dh	; Above this is Bottom	9	(mode)


Setup	mov	!OPTION, #10001111b
	mov	!GPIO, #in_pot	; Set up port DDR

	mov	LastBtn, #0FFh
	mov	Preset, #'0'

Start	
	clrwdt
	call	ReadPot
	clrwdt

	test	potH
	jnz	:Skip1

	test	potL
	jnz	:Skip1

	mov	Btn, #0FFh
	jmp	:Skip3
:Skip1
	cja	potH, #10, Start
	
	mov	Btn, #20

:Loop1
	test	Btn
	jz	Start

	sub	Btn, #2

	mov	W, Btn
	call	ResTbl
	mov	temp, W

	cjb	potH, temp, :Loop1
	cja	potH, temp, :Skip5

	inc	Btn
	mov	W, Btn
	call	ResTbl
	mov	temp, W
	dec	Btn

	cjb	potL, temp, :Loop1
:Skip5
	clc
	rr	Btn
:Skip2	
	cjne	Btn, LastBtn, :Skip3
	cjne	LastBtn, LastBt2, :Skip3
	cjne	LastBt2, LastBt3, :Skip3

	mov	W, Btn
	jmp	PC+W
	jmp	:Btn0
	jmp	:Btn1
	jmp	:Btn2
	jmp	:Btn3
	jmp	:Btn4
	jmp	:Btn5
	jmp	:Btn6
	jmp	:Btn7
	jmp	:Btn8
	jmp	:Btn9

:Btn0				; Power
	jb	Flags.3, Start
	setb	Flags.3

	mov	W, #'\'
	jmp	Print

:Btn1				; Source
	jb	Flags.3, Start
	setb	Flags.3

	inc	Flags
	mov	temp, Flags
	and	temp, #00000011b
	cjne	temp, #00000011b, :Skip4

	and	Flags, #11111100b
:Skip4

	mov	W, #'['
	
	snb	Flags.0
	mov	W, #']'

	snb	Flags.1
	mov	W, #'='

	jmp	Print

:Btn2				; ATT		(mute)
	jb	Flags.3, Start
	setb	Flags.3

	xor	Flags, #00000100b

	sb	Flags.2
	mov	W, #'w'
	snb	Flags.2
	mov	W, #'c'
	jmp	Print

:Btn3				; Front		(list/disp)
	inc	RepCnt
	cje	RepCnt, #RepeatRate, :B3Skp1

	jb	Flags.3, Start
	setb	Flags.3
:B3Skp1
	clr	RepCnt

	mov	W, #'v'
	jmp	Print

:Btn4				; Seek Dn	(seek up)

	jnb	shift, :sskdn

	inc	RepCnt
	cje	RepCnt, #RepeatRate, :B4Skp1

	jb	Flags.3, Start
	setb	Flags.3
:B4Skp1
	clr	RepCnt

	mov	W, #'n'
	jnb	flags.0, Print

	dec	Preset

	cjbe	Preset, #'9', :B5Skp
	mov	Preset, #'0'

	jmp	:B5Skp

:sskdn	mov	W, #'f'
	jnb	flags.0, Print

	mov	xmt_byte, #';'
	call	Send

	mov	xmt_byte, #10
	call	SlwrSnd

	jmp	Start


:Btn5				; Seek Up	(seek dn)

	jnb	shift, :sskup

	inc	RepCnt
	cje	RepCnt, #RepeatRate, :B5Skp1

	jb	Flags.3, Start
	setb	Flags.3
:B5Skp1
	clr	RepCnt

	mov	W, #'p'
	jnb	flags.0, Print

	inc	Preset

	cjae	Preset, #'0', :B5Skp
	mov	Preset, #'9'

:B5Skp	mov	W, Preset
	jmp	Print

:sskup	mov	W, #'b'
	jnb	flags.0, Print

	mov	xmt_byte, #'.'
	call	Send

	mov	xmt_byte, #10
	call	SlwrSnd

	jmp	Start



:Btn6				; Vol Dn	(vol up)
	mov	W, #'+'
	jmp	Print

:Btn7				; Vol Up	(vol dn)
	mov	W, #'-'
	jmp	Print

:Btn8				; Back		(select)
	jb	Flags.3, Start
	setb	Flags.3

	mov	W, #'s'
	jmp	Print

:Btn9				; Bottom	(mode)
	jb	Flags.3, Start
	setb	Flags.3

	mov	xmt_byte, #'m'
	call	SlwrSnd	

	mov	xmt_byte, #10
	call	SlwrSnd	

	mov	xmt_byte, #'n'
	call	SlwrSnd	

	mov	xmt_byte, #10
	call	SlwrSnd	

	mov	xmt_byte, #'m'
	call	SlwrSnd	

	mov	xmt_byte, #10
	call	SlwrSnd	

	mov	xmt_byte, #'m'
	call	SlwrSnd	

	mov	xmt_byte, #10
	call	SlwrSnd	

	mov	xmt_byte, #'n'
	call	SlwrSnd	

	mov	xmt_byte, #10
	call	SlwrSnd	

        mov     potH, #10	; 2 second delay while shuffle mode is displayed
:wait1	djnz    temp, :wait1
	djnz    potL, :wait1
	clrwdt
	djnz    potH, :wait1

	mov	W, #'*'
	jmp	Print


:Skip3	mov	LastBt3, LastBt2
	mov	LastBt2, LastBtn
	mov	LastBtn, Btn

	clr	RepCnt

	clrb	Flags.3

	jmp	Start


Print	mov	xmt_byte, W
	call	Send

	mov	xmt_byte, #10
	call	SlowSnd

	jmp	Start





;	org	1023		// for oscilator calibration
;	mov	W, #0C0h

