On Thu, 13 Jun 2002, Edson Brusque (listas) wrote: > Hello All, > > > some months ago Olin posted the formula that changed DSP world: :) > Filt <-- Filt + (New - Filt)*FFrac > > Saddly, my 8 bit implementation have a problem that I can't surpass: > filt = filt + ((sig16)new - (sig16)filt) / 2; The filter can be written like so: Filt' = Filt + (New - Filt)*FFrac = Filt(1-FFrac) + New*FFrac Often, the FFrac is the ratio of two integers such that: FFrac = B/(A+B) 1-FFrac = A/(A+B) The sum of FFrac and (1-FFrac) is (A+B)/(A+B) or 1. Using this nomenclature, the filter can be rewritten: Filt' = (A*Filt + B*New)/(A+B) So far nothing new, just a rearrangement of terms. Now to apply rounding, there are few tricks that you can perform. Filt' = (A*Filt + B*New + A*New)/(A+B) - A*New/(A+B) Filt' = New + (Filt-New) * A/(A+B) ........... (1) > > The value never goes to 255 because of integer roundings: > filt = 254 + (255 - 254) / 2; > filt = 254 + (1)/2; > filt = 254; In this filter, A=B=1. If you use equation 1: filt = 255 + (254 - 255) / 2 = 255 - 1/2 = 255 Whoopee! This rounding also works for 0: New=0, Filt=1 Filt' = 0 + (1-0)/2 = 1/2 = 0 One way to implement this would be: ; W = New subwf Filt,W ;W = Filt-New subwf Filt,F ;Swap New and Filtered values movwf temp ;Save the difference rlf temp,w ;put sign bit into carry rrf temp,w ;signed right shift btfsc temp,7 ;If the difference is negative addlw 1 ; then round down subwf Filt,F This implementation does have a subtle bug. If the difference between the new and filtered values is greater than 0x7f, then the filter has a spurious response. To fix this, you need to check the signs of the difference versus the sign of the filt or new value. It can be done in 4 more instructions. BTW, an efficient implementation of this class of recursive, one-pole digital filters can be found: http://www.dattalo.com/technical/software/pic/twist.asm Scott -- http://www.piclist.com#nomail Going offline? Don't AutoReply us! email listserv@mitvma.mit.edu with SET PICList DIGEST in the body