; Written by Andrew Warren [fastfwd at 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: mov W, #00001111B ;MASK OFF ALL BUT THE FRACTIONAL and AVFRAC, W ;PART OF THE OLD AVERAGE ;(AVFRAC'S HI-NIBBLE CAN ;CONTAIN GARBAGE). mov W, AVE ;NEW = NEW - AVE. sub NEW, W ;CARRY = 0 IF THE DIFFERENCE IS ;NEGATIVE, CARRY = 1 IF POSITIVE. mov W, <>AVE;HI-NIBBLE OF W = MIDDLE NIBBLE ;OF 16*AVE. mov TEMP, W ;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. sb C ;IF (NEW - AVE) WAS NEGATIVE, dec TEMP ;ADJUST THE HI-NIBBLE OF 16*AVE. and W, #11110000B ;W = LO-BYTE OF 16*AVE. or W, AVFRAC ;(INCLUDE AVE'S FRACTIONAL ;PART). add W, NEW ;W = LO-BYTE OF ;((NEW-AVE) + 16*AVE). ;CARRY = 1 IF SUM > 255, ;CARRY = 0 OTHERWISE. mov AVFRAC, W ;LO-NIBBLE OF AVFRAC = ;FRACTIONAL PART OF FINAL ;RESULT. HI-NIBBLE = GARBAGE. and W, #11110000B ;W = (LO-NIBBLE OF ;((15*AVE+NEW)/16)) * 16. mov AVE, W ;AVE = (LO-NIBBLE OF ;((15*AVE+NEW)/16)) * 16. swap 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. snb C ;LO-NIBBLE OF TEMP = inc TEMP ;HI-NIBBLE OF ((15*AVE+NEW)/16). mov W, <>TEMP ;HI-NIBBLE OF W = HI-NIBBLE OF and W, #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. or AVE, W ;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.
.