[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