		device	pic16c54,xt_osc,wdt_off

		reset	start

al		=	10h
ah		=	11h
bl		=	12h
bh		=	13h
cl		=	14h
ch		=	15h
dl		=	16h
dh		=	17h

bitmask		=	18h
tristate	=	19h
outstate	=	1ah

temp		=	1ch
pwm		=	1dh
number_ptr	=	1eh
temp2		=	1fh

lookup_number	jmp	pc+w
;		retw	12,13,80h
;		retw	2,2,2,2,2,2,2,2,2,2,2,2,2,80h
;		retw	9,9,0,1,9,1,6,7,2,5,1,7,8,9,80h
;		retw	9,9,0,1,9,1,6,7,2,1,8,2,1,7,80h
;		retw	5,6,6,3,2,3,1,80h
;		retw	5,80h
;		retw	1,4,7,10,2,5,8,0,3,6,9,11,12,13,14,15,80h
;		retw	9,3,1,6,6,1,8,8,5,80h
		retw	5,0,7,2,9,5,2,80h
;		retw	8,8,9,8,4,9,80h
;		retw	5,6,3,2,5,6,8,80h
;		retw	0,1,1,3,5,8,0,5,6,6,3,2,3,1,11,80h
;		retw	7,2,1,8,2,1,7,80h
;		retw	9,7,2,0,9,7,0,0ffh

;
;
; Frequency formula:	 c = Freq/(4000000/4/66/8/256) = Freq/7.40
;			 |    |       |    | |  |  |
;             constant --|    |       |    | |  |  |
;     target frequency ------ |       |    | |  |  |
;  cpu clock frequency ---------------|    | |  |  |
; 4:1 instruction rate --------------------| |  |  |
;          cycles/loop ----------------------|  |  |
;     samples/sinewave -------------------------|  |
;	    c/256 rate ----------------------------|
;
r1		=	94	;697 Hz
r2		=	104	;770 Hz
r3		=	115	;852 Hz
r4		=	127	;941 Hz
c1		=	163	;1209 Hz
c2		=	181	;1336 Hz
c3		=	200	;1477 Hz
c4		=	221	;1632 Hz

lookup_freqs	jmp	pc+w			;lookup row and col frequencies
		retw	r4,c2	;0
		retw	r1,c1	;1
		retw	r1,c2	;2
		retw	r1,c3	;3
		retw	r2,c1	;4
		retw	r2,c2	;5
		retw	r2,c3	;6
		retw	r3,c1	;7
		retw	r3,c2	;8
		retw	r3,c3	;9
		retw	r4,c1	;*
		retw	r4,c3	;#
		retw	r1,c4	;A
		retw	r2,c4	;B
		retw	r3,c4	;C
		retw	r4,c4	;D

lookup_sine	jmp	pc+w
		retw	3,5,6,5,3,1,0,1

lookup_pwm	jmp	pc+w
		retw	000000b
		retw	100000b
		retw	010000b
		retw	100100b
		retw	010100b
		retw	101010b
		retw	011010b
		retw	110110b
		retw	011101b
		retw	111011b
		retw	011111b
		retw	111111b
		retw	111111b

start		mov	bitmask,#00000100b
		mov	tristate,#00000000b
		mov	outstate,#00000000b

		mov	!rb,tristate

		clr	number_ptr
:loop		mov	w,number_ptr
		inc	number_ptr

		call	lookup_number
		mov	dh,w
		jb	dh.7,:done
		clc
		rl	dh
		mov	w,dh
		call	lookup_freqs
		mov	al,w
		mov	w,++dh
		call	lookup_freqs
		mov	ah,w
		call	dtmf_output
		mov	dh,#040h
:slow		djnz	dl,:slow
		djnz	dh,:slow
		jmp	:loop

:done		jmp	$
;
;
; DTMF output
;
; in:	al=tone1, ah=tone2
; uses:	bl,bh,cl,ch,dl,dh
;
dtmf_output	mov	dh,#125
		clr	bl
		clr	bh
		clr	fsr
		clr	cl
		clr	ch

:loop		add	bl,al		;2	;update tone1
		snc			;1
		inc	cl		;1
		clrb	cl.3		;1

		mov	w,outstate	;1	;output bit3
		snb	pwm.3		;1
		or	w,bitmask	;1
		mov	rb,w		;1

		add	bh,ah		;2	;update tone2
		snc			;1
		inc	ch		;1
		clrb	ch.3		;1

		inc	fsr		;1	;inc time
		snz			;1
		inc	dh		;1

		mov	w,outstate	;1	;output bit2
		snb	pwm.2		;1
		or	w,bitmask	;1
		mov	rb,w		;1

		mov	w,cl		;1	;lookup sine1
		call	lookup_sine	;6
		mov	temp,w		;1

		mov	w,outstate	;1	;output bit1
		snb	pwm.1		;1
		or	w,bitmask	;1
		mov	rb,w		;1

		mov	w,ch		;1	;lookup sine2
		call	lookup_sine	;6
		add	temp,w		;1

		mov	w,outstate	;1	;output bit0
		snb	pwm.0		;1
		or	w,bitmask	;1
		mov	rb,w		;1

		mov	w,temp		;1	;lookup pwm
		call	lookup_pwm	;6
		mov	pwm,w		;1

		mov	w,outstate	;1	;output bit5 (1/2 bit)
		snb	pwm.5		;1
		or	w,bitmask	;1
		mov	rb,w		;1

		jmp	$+1		;2

		mov	w,outstate	;1	;output bit4
		snb	pwm.4		;1
		or	w,bitmask	;1
		mov	rb,w		;1

		movsz	w,++dh		;1	;loop if not done
		jmp	:loop		;2	;66us/loop

		mov	rb,outstate	;call	set_low
		ret
