
;	Signal Generator / 9/01 Luhan Monat
;
;Mode	Sine	Square	Triang	H-Pulse	L-Pulse Sweep	Burst
;--------------------------------------------------------------
;F1	freq	freq	freq	freq	freq	freq	freq	
;F2		sym	sym	width	width	cycles	cycles
;F3						delta	rate

	device	pic16f870	hs_osc,pwrte_on,wdt_off

MAXMODE	=	9


	org	20h
	
data	ds	1
temp	ds	3
count	ds	1
lights	ds	1	;front panel light image
del1	ds	1
del2	ds	1
del3	ds	1
val1	ds	1
val2	ds	1
accum	ds	3	;24 bit accumulator
step	ds	2	;16 bit
vstep	ds	2
looper	ds	2
select	ds	1	;select type of operation
vrate	ds	1	;rate of adjustment
mode	ds	1	;type of waveform
f1	ds	3	;24 bit f1
f2	ds	2
f3	ds	1
flags	ds	1
input	ds	1


ROT	=	input.7		;rotary encoder
BUT	=	input.6		;button
SPD	=	input.5		;adjust rate
DIR	=	input.3		;encoder direction

RACT	=	flags.0		;encoder active
BACT	=	flags.1		;button active
ON	=	flags.2
SACT	=	flags.3		;rate active
GEN	=	flags.4		;generate sinewave

FILT	=	rb.2		;bypass filter network

SRDAT	=	ra.0		;shift register data
SRCLK	=	ra.1		;s/r clock
SYNC	=	ra.3		;sync output


	org	0

	goto	start
	
	org	4
	
; go here on interrupt of port 7

intr	nop
	btfss	T0IF		;timeout?
	reti			;no - disallow interrupt process
		
	clrf	PCLATH
	bcf	RP0
	bcf	RP1
:no	movlw	10		;must match 10 times
	movwf	count
	movf	rb,w		;clear the interrupt source
	xorlw	0ffh		;invert bits
	movwf	input
:chk	movf	rb,w
	xorlw	0ffh
	xorwf	input,w
	btfss	z		;same?
	goto	:no		;start count over
	decfsz	count
	goto	:chk
	bcf	RBIF		;clear the flag bit
	goto	contin		;	

lmask	movf	select,w
	btfsc	SPD
	movf	vrate,w
	addwf	PCL
	retw	4,2,1,0

vrvals	addwf	PCL
	retw	33539>, 33539<, 500>, 500<
	retw	1676>,1676<, 25>, 25<
	retw	 67>, 67<, 1>, 1<
	

selmsk	addwf	PCL
	retw	4,2,1
	
vrmask	addwf	PCL
	retw	20h,10h,8
		

start	bsf	RP0
	movlw	110000b
	movwf	ra
	movlw	11111000b
	movwf	rb
	movlw	0
	movwf	rc
	movlw	00000111b	;256 count prescale to timer-0
	movwf	OPTION		;rb<4:7> pull ups
	movlw	6
	movwf	ADCON1		;all digital bits
	bcf	RP0

	movlw	0ffh
	movwf	rb	
	movlw	88h
	movwf	INTCON		;RB<4:7> interrupts enabled
	movlw	1
	movwf	f1
	clrf	f1+1
	clrf	f1+2
	clrf	step
	movlw	10
	movwf	step+1
	movlw	5
	movwf	f3
	movlw	50
	movwf	f2
	clrf	f2+1
	clrf	mode
	clrf	select
	clrf	vrate
	clrf	flags
	clrf	input
	call	lites
	call	dorate	

; continue here after controls are changed

contin	btfss	SPD		;new rate?
	goto	:nr
	bsf	SACT		;speed active
	goto	:done
:nr	btfss	BUT		;button down?
	goto	:adj		;no.
	bsf	BACT		;flag as active
	call	nolite
	btfss	ROT		;encoder active?
	goto	:done		;
	bsf	RACT		;flag rotor active.
	btfsc	DIR		;which way?
	goto	:dec
:inc	incf	mode
	movf	mode,w
	xorlw	MAXMODE		;too high?
	btfss	z		;
	goto	:done		;no.
:dec	decf	mode
	btfss	mode,7		;underflow?
	goto	:done		;no.
	clrf	mode
	goto	:done
:adj	btfss	ROT		;encoder active?
	goto	:norot		;no.
	call	adjust
	goto	:done
:norot	btfss	SACT
	goto	:nos
	bcf	SACT
	call	newrate
	goto	:lite	
:nos	btfss	BACT		;previously hit?
	goto	:lite		;no.
	bcf	BACT
	btfsc	RACT		;was mode changed?
	goto	:lite		;no.
	incf	select
	movf	select,w
	xorlw	3		;too high
	btfsc	z
	clrf	select		;wrap to zero
:lite	bcf	RACT
	call	lites		;turn on light
	goto	:done		

:done	movlw	-250
	movwf	TMR0
	bcf	T0IF
	bsf	GIE
	nop

run	clrf	PCLATH
	movf	mode,w		;get the mode
	addwf	PCL		;compute the jump
	goto	sine
	goto	trian
	goto	square
	goto	saw
	goto	hpulse
	goto	lpulse
	goto	burst
	goto	sweep
	goto	noise
	goto	start		;just in case!

newrate	incf	vrate
dorate	movf	vrate,w
	xorlw	3
	btfsc	z
	clrf	vrate
	movf	vrate,w
	movwf	temp
	bcf	c
	rlf	temp
	bcf	c
	rlf	temp
	movf	temp,w
	call	vrvals
	movwf	step
	incf	temp
	movf	temp,w
	call	vrvals
	movwf	step+1
	incf	temp
	movf	temp,w
	call	vrvals
	movwf	vstep
	incf	temp
	movf	temp,w
	call	vrvals
	movwf	vstep+1
	ret


sine	bsf	FILT
	movlw	3
	movwf	PCLATH
:nxt	movf	f1,w
	addwf	accum
	movf	f1+1,w
	btfsc	c
	incfsz	f1+1,w
	addwf	accum+1
	movf	f1+2,w
	btfsc	c
	incfsz	f1+2,w
	addwf	accum+2
	movf	accum+2,w
	call	getsv
	movwf	rc
	goto	:nxt
	

trian	bsf	FILT
:nxt	movf	f1,w
	addwf	accum
	movf	f1+1,w
	btfsc	c
	incfsz	f1+1,w
	addwf	accum+1
	movf	f1+2,w
	btfsc	c
	incfsz	f1+2,w
	addwf	accum+2
	movf	accum+2,w
	addwf	accum+2,w
	btfsc	c
	sublw	255
	movwf	rc
	nop
	nop
	nop
	goto	:nxt
	

square	bcf	FILT
:clr	clrf	accum
	clrf	accum+1
	clrf	accum+2
:nxt	movf	f1,w
	addwf	accum
	movf	f1+1,w
	btfsc	c
	incfsz	f1+1,w
	addwf	accum+1
	movf	f1+2,w
	btfsc	c
	incfsz	f1+2,w
	addwf	accum+2
	nop
	nop
	nop
	nop
	clrw
	btfsc	accum+2,7
	movlw	255
	movwf	rc
	goto	:nxt

	
saw	bcf	FILT
:nxt	movf	f1,w
	addwf	accum
	movf	f1+1,w
	btfsc	c
	incfsz	f1+1,w
	addwf	accum+1
	movf	f1+2,w
	btfsc	c
	incfsz	f1+2,w
	addwf	accum+2
	movf	accum+2,w
	nop
	nop
	nop
	nop
	nop
	nop
	movwf	rc
	goto	:nxt
	

	
hpulse	movlw	255
	movwf	val1
	clrf	val2
	goto	pulse
lpulse	movlw	255
	movwf	val2
	clrf	val1
pulse	bcf	FILT
:lp	movf	val1,w
	movwf	rc		;start pulse
	movf	f2,w
	movwf	temp
	movf	f2+1,w
	movwf	temp+1
	call	time
	movf	val2,w
	movwf	rc		;end of pulse
	movf	f1,w
	movwf	temp
	movf	f1+1,w
	movwf	temp+1
	movf	f1+2,w
	movwf	temp+2
	call	xtime
	goto	:lp

	
sweep	bsf	FILT
	movlw	3
	movwf	PCLATH
	clrf	accum
	clrf	accum+1
	clrf	accum+2	
	bsf	GEN
	movf	f1,w
	movwf	temp
	movf	f1+1,w
	movwf	temp+1
	movf	f1+2,w
	movwf	temp+2
	bsf	GEN
	bsf	SYNC
	call	:brst
	bcf	GEN
	bcf	SYNC
	call	:brst
	goto	sweep
	
:brst	movf	f3,w
	movwf	count
:br2	clrf	accum+2
	incf	accum+2
	call	cycle		;do some cycles
	movf	f2,w
	addwf	temp
	btfsc	c
	incf	temp+1
	btfsc	z
	incf	temp+2
	movf	f2+1,w
	addwf	temp+1
	btfsc	c
	incf	temp+2
	decfsz	count
	goto	:br2
	ret



burst	bsf	FILT
	movlw	3
	movwf	PCLATH
	clrf	accum
	clrf	accum+1
	clrf	accum+2	
	bsf	SYNC		;start of sync
	movf	f3,w
	movwf	count
	bsf	GEN
	movf	f1,w
	movwf	temp
	movf	f1+1,w
	movwf	temp+1
	movf	f1+2,w
	movwf	temp+2
:brst	clrf	accum+2
	incf	accum+2
	call	cycle		;do some cycles
	decfsz	count
	goto	:brst
	bcf	SYNC		;end of sync
	movlw	127
	movwf	rc
	bcf	GEN
	movf	f2,w
	movwf	del1
	movf	f2+1,w
	movwf	del2
	incf	del2
:wait	clrf	accum+2
	incf	accum+2
	call	cycle
	decfsz	del1
	goto	:wait
	decfsz	del2
	goto	:wait
	goto	burst


cycle	movf	temp,w		;get low byte
	addwf	accum		;add to low byte
	btfsc	c		;possible carry bit
	incf	accum+1
	btfsc	z
	incf	accum+2
	movf	temp+1,w
	addwf	accum+1
	btfsc	c
	incf	accum+2
	movf	temp+2,w
	addwf	accum+2
	btfsc	c
	ret
	movf	accum+2,w
	btfsc	z
	ret
	call	getsv
	btfsc	GEN
	movwf	rc
	goto	cycle

	

noise	call	pseudo
	movwf	rc
	movf	f2,w
	movwf	temp
	movf	f2+1,w
	movwf	temp+1
	call	time
	goto	noise

pseudo	movf	del1,w
	addwf	del2,w
	movwf	del2
	addwf	del3,w
	movwf	del3
	bcf	c
	rlf	del3
	btfsc	c
	incf	del3
	addwf	del1
	ret

	

adjust	movf	select,w
	btfsc	z
	goto	:f1
	addlw	-1
	btfsc	z
	goto	:f2

:f3	btfsc	DIR
	goto	:f3dn
	incfsz	f3
	ret
	decf	f3
	ret
:f3dn	decfsz	f3
	ret
	incf	f3
	ret
	

:f2	btfsc	DIR		;which way
	goto	:f2dn
	movf	vstep,w
	addwf	f2
	btfsc	c
	incf	f2+1
	movf	vstep+1,w
	addwf	f2+1
	btfss	f2+1,7
	ret

:f2dn	movf	vstep,w
	bsf	SYNC
	subwf	f2
	movf	vstep+1,w
	btfss	c
	incf	vstep+1,w
	subwf	f2+1
	btfss	f2+1,7
	ret
	clrf	f2
	incf	f2
	clrf	f2+1
	bcf	SYNC
	ret


:f1	btfsc	DIR		;which way
	goto	:f1dn
	movf	step,w
	addwf	f1
	btfsc	c
	incf	f1+1
	btfsc	z
	incf	f1+2
	movf	step+1,w
	addwf	f1+1
	btfsc	c
	incf	f1+2
	btfss	f1+2,6
	ret

:f1dn	movf	step,w
	subwf	f1
	movf	step+1,w
	btfss	c
	incfsz	step+1,w
	subwf	f1+1
	btfss	c
	decf	f1+2
	btfss	f1+2,7
	ret
:clr	clrf	f1
	clrf	f1+1
	clrf	f1+2
	ret


xtime	movf	temp,w
	iorwf	temp+1,w
	iorwf	temp+2,w
	btfsc	z
	ret
	movlw	-1
	addwf	temp
	btfss	c
	addwf	temp+1
	btfss	c
	addwf	temp+2
	goto	xtime
		

; linear time delay del2/del1

time	movf	temp,w
	iorwf	temp+1,w
	btfsc	z
	ret
	movlw	-1
	addwf	temp
	btfss	c
	decf	temp+1
	goto	time
	
	

; approx 5ms/count

delay	movwf	del1
	clrf	del2
:dx	nop
	nop
	decfsz	del2
	goto	:dx
	decfsz	del1
	goto	:dx
	ret


nolite	clrf	temp
	goto	nosel
lites	movf	select,w
	call	selmsk
	movwf	temp
nosel	movf	vrate,w
	call	vrmask
	iorwf	temp
	movlw	6
	movwf	count
	bcf	SRCLK
:nxt	btfss	temp,0
	bcf	SRDAT
	btfsc	temp,0
	bsf	SRDAT
	bsf	SRCLK
	bcf	SRCLK
	rrf	temp
	decfsz	count
	goto	:nxt
	ret
	
	

flash	bsf	ra,2
	movlw	200
	call	delay
	bcf	ra,2
	movlw	200
	call	delay
	bsf	ra,2
	ret


	org	2ffh

getsv	addwf	PCL
	
sintab	retw	127,130,133,136,139,142,145,148		;127
	retw	151,154,157,160,163,166,169,172
	retw	175,178,181,184,186,189,192,194
	retw	197,200,202,205,207,209,212,214
	retw	216,218,221,223,225,227,228,230
	retw	232,234,235,237,238,240,241,243
	retw	244,245,246,247,248,249,250,250
	retw	251,252,252,253,253,253,253,253
	retw	253,253,253,253,253,253,252,252
	retw	251,250,250,249,248,247,246,245
	retw	244,243,241,240,239,237,236,234
	retw	232,230,229,227,225,223,221,219
	retw	216,214,212,210,207,205,202,200
	retw	197,195,192,189,187,184,181,178
	retw	175,172,169,167,164,161,158,155
	retw	151,148,145,142,139,136,133,130
	retw	127,124,120,117,114,111,108,105
	retw	102,99,96,93,90,87,84,81
	retw	78,75,72,70,67,64,61,59
	retw	56,54,51,49,46,44,41,39
	retw	37,35,33,31,28,27,25,23
	retw	21,19,18,16,15,13,12,11
	retw	 9, 8, 7, 6, 5, 4, 3, 3
	retw	 2, 1, 1, 0, 0, 0, 0, 0
	retw	 0, 0, 0, 0, 0, 0, 1, 1
	retw	 2, 3, 3, 4, 5, 6, 7, 8
	retw	 9,10,12,13,14,16,17,19
	retw	21,22,24,26,28,30,32,34
	retw	36,39,41,43,46,48,51,53
	retw	56,58,61,64,66,69,72,75
	retw	78,80,83,86,89,92,95,98
	retw	101,104,107,111,114,117,120,123		;123

	end
	
   

        
        
        QED¨           c í                   
