Hi Andrew. I got some time and tried to rewrite your filter code to optimize it a little bit. The formula can be rewritten as: Ave' = Ave + ( New - Ave )/16 ; Used the same names for variables. TEMP cell isn't used. I having more and more believing that 12 is some magical number for small completed code fragments. ;) ; Initially written by Andrew Warren (fastfwd@ix.netcom.com). ; Optimized by Dmitry A. Kiryashov (zews@aha.ru) 06/18/2000 ; 12 clocks/words Filter: movfw AVE subwf NEW,F ;NEW - AVE swapf NEW,W andlw 0x0F ;get /16 int part skpc ;result is neg? iorlw 0xF0 ;yes addwf AVE,F swapf NEW,W andlw 0xF0 ;get /16 frac part addwf AVFRAC,F skpnc incf AVE,F ; ; low nibble of AVFRAC isn't used ; so we can utilize it for other purposes ;) WBR Dmitry. > ; Written by Andrew Warren (fastfwd@ix.netcom.com). > ; > ; (NEW - AVE) + 16*AVE > ; AVE = -------------------- > ; 16 > > NEW EQU [ANY FILE REGISTER] ;HOLDS NEW SAMPLE [0-255]. > AVE EQU [ANY FILE REGISTER[ ;HOLDS THE AVERAGE [0-255]. > AVFRAC EQU [ANY FILE REGISTER] ;HOLDS THE FRACTIONAL PART > ;OF THE AVERAGE [0-15]. > TEMP EQU [ANY FILE REGISTER] ;TEMPORARY STORAGE. > > FILTER: > > MOVLW 00001111B ;MASK OFF ALL BUT THE FRACTIONAL > ANDWF AVFRAC ;PART OF THE OLD AVERAGE > ;(AVFRAC'S HI-NIBBLE CAN > ;CONTAIN GARBAGE). > > MOVF AVE,W ;NEW = NEW - AVE. > SUBWF NEW ;CARRY = 0 IF THE DIFFERENCE IS > ;NEGATIVE, CARRY = 1 IF POSITIVE. > > SWAPF AVE,W ;HI-NIBBLE OF W = MIDDLE NIBBLE > ;OF 16*AVE. > > MOVWF TEMP ;LO-NIBBLE OF TEMP = HI-NIBBLE > ;OF 16*AVE (LO-NIBBLE OF 16*AVE > ;IS ALWAYS 0000). > > ; NEW CONTAINS (NEW - AVE) AND [TEMP:W] HOLDS 16*AVE. > ; ADD THEM TOGETHER. > > SKPC ;IF (NEW - AVE) WAS NEGATIVE, > DECF TEMP ;ADJUST THE HI-NIBBLE OF 16*AVE. > > ANDLW 11110000B ;W = LO-BYTE OF 16*AVE. > IORWF AVFRAC,W ;(INCLUDE AVE'S FRACTIONAL > ;PART). > > ADDWF NEW,W ;W = LO-BYTE OF > ;((NEW-AVE) + 16*AVE). > ;CARRY = 1 IF SUM > 255, > ;CARRY = 0 OTHERWISE. > > MOVWF AVFRAC ;LO-NIBBLE OF AVFRAC = > ;FRACTIONAL PART OF FINAL > ;RESULT. HI-NIBBLE = GARBAGE. > > ANDLW 11110000B ;W = (LO-NIBBLE OF > ;((15*AVE+NEW)/16)) * 16. > > MOVWF AVE ;AVE = (LO-NIBBLE OF > ;((15*AVE+NEW)/16)) * 16. > > SWAPF AVE ;AVE = LO-NIBBLE OF > ;((15*AVE+NEW)/16). > > ; AVE'S LO-NIBBLE CONTAINS THE LO-NIBBLE OF THE FINAL RESULT. > ; AVE'S HI-NIBBLE = 0000. > > SKPNC ;LO-NIBBLE OF TEMP = > INCF TEMP ;HI-NIBBLE OF ((15*AVE+NEW)/16). > > SWAPF TEMP,W ;HI-NIBBLE OF W = HI-NIBBLE OF > ANDLW 11110000B ;((15*AVE+NEW)/16). > ;LO-NIBBLE OF W = 0000. > > ; W'S HI-NIBBLE CONTAINS THE HI-NIBBLE OF THE FINAL RESULT. > ; LO-NIBBLE = 0000. > > IORWF AVE ;COMBINE THE HI- AND LO-NIBBLES > ;AND STORE THE FINAL RESULT IN > ;AVE. > > ; AVE CONTAINS THE NEW AVERAGE. > > See? That wasn't too hard; just 20 words of program space and > 20 instruction cycles... And not a single floating-point > operation anywhere in there. > > > 2/ The filter is great for downward changing signals only, as an > > upward change will not be reflected until the delta is greater > > than the width > > Untrue. In the code above, AVFRAC accumulates deltas smaller > than the width until their sum is large enough to affect the > average. > > > 3/ The impulse response is dependant on the width etc. > > No kidding. Isn't that, um, THE POINT? > > -Andy > > === Andrew Warren - fastfwd@ix.netcom.com > === Fast Forward Engineering - San Diego, California > === http://www.geocities.com/SiliconValley/2499