[sdiy] IIR Shift Filter problem - help with bug spotting in PIC ASM

Tom Wiltshire tom at electricdruid.net
Thu Mar 9 14:23:21 CET 2017


Hi All,

If you could cast your eyes over this, I'd be grateful. I'm having one of those "can't see the wood for the trees" moments.

The code below is a simple single-pole IIR filter (a digital RC LPF). The INPUT is a 10-bit variable, which is left-aligned, so I have six empty bits below it.

Now, I've actually got this code working (the good version below), but what I don't understand is why the BAD version doesn't do the same thing. I don't see why testing the Borrow flag and sticking the bits in "manually" is really any different from shifting the Borrow flag in. What am I missing, oh wise SynthDIY list? ;)

Thanks for any pointers!
Tom

; The Good Version

WaveformSmoothing:
	; Subtract FILTER from new INPUT 
	movf	FILTER_LO, w
	subwf	INPUT_LO, f			; INPUT = INPUT - FILTER
	movf	FILTER_HI, w
	subwfb	INPUT_HI, f
	
	; Borrow is zero if result required borrow (negative result)
	; Is borrow set?
	bcf		FLAGS, 3
	btfss	BORROW			; Skip if positive
	bsf		FLAGS, 3			; Flag set if negative
	
	; Do the downshifts (x 1/16th effectively)
	lsrf		INPUT_HI, f
	rrf		INPUT_LO, f
	lsrf		INPUT_HI, f
	rrf		INPUT_LO, f
	lsrf		INPUT_HI, f
	rrf		INPUT_LO, f
	lsrf		INPUT_HI, f
	rrf		INPUT_LO, f			; 4 shifts total
	
	; Add the extra bits back in if negative
	movlw	0xF0
	btfsc	FLAGS, 3
	addwf	INPUT_HI, f

	; Add it to FILTER
	movf	INPUT_LO, w
	addwf	FILTER_LO, f
	movf	INPUT_HI, w
	addwfc	FILTER_HI, f
	; We now have a smoothed copy of our INPUT in FILTER


; The BAD Version

WaveformSmoothing:
	; Subtract FILTER from new INPUT 
	movf	FILTER_LO, w
	subwf	INPUT_LO, f			; INPUT = INPUT - FILTER
	movf	FILTER_HI, w
	subwfb	INPUT_HI, f

	; Borrow is zero if result required borrow (negative result)
	 ; Flip the state of the borrow flag
 	movlw	0x01
	xorwf	STATUS, f				; Borrow set if negative
	
	; Do the downshifts (x 1/16th effectively)
	rrf		INPUT_HI, f			; Rotate the borrow flag in
	rrf		INPUT_LO, f
	asrf		INPUT_HI, f			; Propagate it down to lower bits
	rrf		INPUT_LO, f
	asrf		INPUT_HI, f
	rrf		INPUT_LO, f
	asrf		INPUT_HI, f
	rrf		INPUT_LO, f			; 4 shifts total

	; Add it to FILTER
	movf	INPUT_LO, w
	addwf	FILTER_LO, f
	movf	INPUT_HI, w
	addwfc	FILTER_HI, f
	; We now have a smoothed copy of our INPUT in FILTER



If you'd like to know more about this technique, full details are here (I've brought this useful StackExchange post up here before):

http://electronics.stackexchange.com/questions/30370/fast-and-memory-efficient-moving-average-calculation

The crucial part is the filter equation:
	FILT <-- FILT + FF(NEW - FILT)



More information about the Synth-diy mailing list