PIC Microcontroller DSP Math Method

8bit 16 step Averageing filter by Andrew Warren

    ; 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:

            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.