From Tony Nixon [sales at picnpoke.com] and Scott Dattalo
Tony says:
Heres a simple setup using the FSR. Averages for 8 readings though.
CBLOCK
Average: 8h
tempH
tempL
ENDC
movlw Average ; initialise FSR
movwf FSR
...
;
; PLACE A2D RESULTS INTO A ROTATING BUFFER
;
movf ADRES,W
movwf INDF
incf FSR
movlw Average + 8h
xorwf FSR,W
btfss STATUS,Z
goto NFSR
movlw Average
movwf FSR
NFSR ...
;Scott Dattalo interjects:
;If you have only 8 samples, and you were willing to align the array on a mod 8
;boundary, then advancing the pointer could be done easily:
incf fsr,w
andlw 7
addlw Average
movwf fsr
;if you don't wish to align the array, then try this instead:
incf fsr,w
addlw -Average
andlw 7
addlw Average
movwf fsr
;
; AVERAGE OUT THE 8 STORED VALUES WHEN A RESULT IS NEEDED
;
movlw Average
movwf FSR
clrf tempH
clrf tempL
avLoop movf INDF,W ; add up 8 word values
addwf tempL
btfsc STATUS,C
incf tempH
incf FSR
movlw Average +8h
xorwf FSR,W
btfss STATUS,Z
goto avLoop
movlw Average
movwf FSR
bcf STATUS,C ; div result by 8
rrf tempH
rrf tempL
bcf STATUS,C
rrf tempH
rrf tempL
bcf STATUS,C
rrf tempH
rrf tempL
....
And Scott also says:
Again, I think the best way to maintain a running average is by subtracting
the oldest value and adding in the newest. Here's something I'll whip out
as fast as I can type it - which means there's a good chance for a thinko.
; avg_lo:avg_hi - 16bit cumulative sum of last 8 samples
; samples - a circular array that holds the last 8 samples
; assume that samples and avg_lo:avg_hi are initialized to zero
;
; FSR is initialized to the start of samples
;
; W = newest sample
AVERAGE:
addwf avg_lo,f ;add newest sample to the average
skpnc
incf avg_hi,f
xorwf indf,f ; swap oldest and newest samples
xorwf indf,w
xorwf indf,f
subwf avg_lo,f ;remove the oldest sample from the average
skpc
decf avg_hi,f
incf fsr,w ;advance the sample pointer
addlw -sample
andlw 7
addlw sample
movwf fsr
return
There - no more looping through all of the data after every sample is acquired.
Now, I'm assuming that the division is not needed at every iteration. I tend to
put off the difficult stuff as long as possible - often times, the intermediate
calculations are more than sufficient.
But, if you want, then this is how I'd do it:
rrf avg_hi,w
movwf temp_hi
rrf avg_lo,w
movwf temp_lo
rrf temp_hi,f
rrf temp_lo,f
rrf temp_hi,f
rrf temp_lo,w
and if you wanted rounding:
skpnc
addlw 1
(You don't need to worry about clearing the carry because the average is
guranteed to be less than or equal to 255.)