please dont rip this site

SX Microcontroller Input / Ouput Method

Averaging A2D results

By Nikolai Golovchenko, Tony Nixon [sales at picnpoke.com] and Scott Dattalo

        DEVICE SX28L, OSCHS2, TURBO, STACKX, OPTIONX
        RESET start

        ORG $08         ;global bank
rand0   DS 1            ;random generator state
count   DS 1            ;general purpose counter
temp	DS 1		;temp needed in Scott's version
tempH   DS 1            ;temps needed in Tony's version
tempL   DS 1            ;

        ORG $10         ;bank 0
av_bank EQU $
samples EQU $           ;alias name for 'average'
average DS 8            ;circular buffer for 8 bytes
av_ptr  DS 1            ;circular buffer pointer (0..7)
avg_lo  DS 1            ;cumulative average (required in Scott's version)
avg_hi  DS 1            ;

        ORG $000        ;page 0

;************************************************************************
start

;make w addressable
        mov w, #$7F
        mov !OPTION, w
;x--- ----      0 = register 01h addresses w 
;-x-- ----      1 = RTCC roll-over interrupt is disabled
;--x- ----      1 = RTCC increments upon transition on RTCC pin
;---x ----      1 = RTCC increments on high-to-low transitions
;---- x---      1 = Prescaler is assigned to WDT, and divide rate on
;                   RTCC is 1:1
;---- -xxx      111 = Prescaler divider 1:128 (WDT)


; * METHOD 1 *

;enter 8 entries in the buffer and calculate the average
;using method 1

        bank av_bank    ;select working bank

        clr rand0       ;init the random generator state
        clr av_ptr      ;clear buffer pointer
        mov w, #8
        mov count, w
loop1
        call Rand8      ;generate a random input value in w
        call av_put     ;put it into the buffer
        decsz count     
         jmp loop1      ;repeat 8 times

        call av_calc    ;calculate average and return in w

	;input data = 35,F6,93,1C,61,F2,1F,F8
        ;result w = 88

; * METHOD 2 *

;enter 8 entries in the buffer and calculate the average
;using method 2

        bank av_bank    ;select working bank

        clr rand0       ;init the random generator state
	call av_init2	;init average calculation

        mov w, #8
        mov count, w
        
loop2
        call Rand8      ;generate a random input value in w
        call av_put2    ;put it into the buffer
        decsz count     
         jmp loop2      ;repeat 8 times
        
        call av_calc2   ;calculate average and return in w
        ;result w = 88

        call av_calc3   ;calculate average and round
        ;result w = 89


        jmp $           ;halt
;************************************************************************
Rand8
        clc
        rl      rand0           ; w = (32 * rand) % 256
        mov     w, <>rand0
        and     w, #$E0
        rr      rand0           ; restore rand
        add     w, rand0        ; rand' = (w + 3 * rand) % 256=
        add     w, rand0        ;       = (32 * rand + 3 * rand) % 256
        add     rand0, w
        not     rand0           ; rand'' = -rand'-1
        mov     w, #$36         ; rand = (53 - 32 * rand - 3 * rand) % 256
        add     rand0, w
        mov     w, rand0        ; copy result to w
        retp                    ; Done

;************************************************************************
;
; PLACE A2D RESULTS (w) INTO A ROTATING BUFFER
; (by Tony Nixon and Scott Dattalo)
;
;************************************************************************
av_put
        mov     temp, w         ;save w in temp (in global bank)

        mov     w, #average     ;initialise FSR
        mov     FSR, w
        mov     w, av_ptr
        add     FSR, w

        mov     w, temp         ;get input
        mov     IND, w          ;save in buffer

                                ;update pointer
        mov     w, ++av_ptr     
        and     w, #$07         ;implement wrap-around
        mov     av_ptr, w

        retp

;************************************************************************
;
; AVERAGE OUT THE 8 STORED VALUES WHEN A RESULT IS NEEDED (return in w)
;
;************************************************************************
av_calc
        mov     w, #average     ;initialise FSR
        mov     FSR, w
        clr     tempH
        clr     tempL

;add up 8 word values
av_loop
        mov     w, IND          ;load pointed value
        add     tempL, w        ;add to tempH:tempL
        snc
         inc    tempH

        inc     FSR
        mov     w, #average + 8
        xor     w, FSR
        sz
         jmp    av_loop

;div result by 8
        rr      tempH
        rr      tempL
        rr      tempH
        rr      tempL
        rr      tempH
        mov     w, >>tempL      ;last shift result place in w

        retp                    ;return with result in w

;************************************************************************
; Scott Dattalo says:
; Again, I think the best way to maintain a running average is by
; subtracting the oldest value and adding in the newest.
;
; 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
;************************************************************************
av_put2
	mov 	temp, w		;save input
        mov     w, #average     ;initialise FSR
        mov     FSR, w
        mov     w, av_ptr
        add     FSR, w
        
	mov	w, temp		;read input      
        add     avg_lo, w       ;add newest sample to the average
        snc
         inc    avg_hi

        xor     IND, w          ;swap oldest and newest samples
        xor     w, IND
        xor     IND, w

        sub     avg_lo, w       ;remove the oldest sample from the average
        sc
         dec    avg_hi

        mov     w, ++av_ptr     ;advance the sample pointer
        and     w, #$07
        mov     av_ptr, w

        retp
;************************************************************************
;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:
;************************************************************************
av_calc2
        bank    av_bank         ;select working bank

        mov     w, >>avg_hi
        mov     temp, w
        mov     w, >>avg_lo
        rr      temp
        rr      WREG
        rr      temp
        rr      WREG
        retp        

;and if you wanted rounding:
av_calc3
        bank    av_bank         ;select working bank

        mov     w, >>avg_hi
        mov     temp, w
        mov     w, >>avg_lo
        rr      temp
        rr      WREG
        rr      temp
        rr      WREG
        snc
         inc    WREG
        retp

;************************************************************************
; Initialize buffer
;************************************************************************
av_init2
        mov w, #average	;init bank and FSR pointer
        mov FSR, w
        clr av_ptr      ;clear buffer pointer
        clr avg_hi      ;clear running average
        clr avg_lo      ;
        mov w, #8
        mov temp, w
av_init2_loop
        clr IND		;clear the buffer
        inc FSR
        decsz temp
         jmp av_init2_loop
        retp
;************************************************************************

	ORG $200	;page 1

file: /Techref/scenix/lib/math/dsp/avga2d_sx.htm, 8KB, , updated: 2004/6/10 13:40, local time: 2024/11/15 11:45,
TOP NEW HELP FIND: 
3.142.194.27:LOG IN

 ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://linistepper.com/techref/scenix/lib/math/dsp/avga2d_sx.htm"> PIC Microcontroller Input / Ouput Method Averaging A2D results</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?