📄 sub_fir_filter.s
字号:
;START_HEADER
;
; dsPIC30F6014 Demo Source File
; (c) Copyright 2005 Microchip Technology, All rights reserved
;
; --------------------------------------------------------------------------
; File Revision History:
; --------------------------------------------------------------------------
;
; $Log: sub_fir_filter.s,v $
; Revision 1.2 2005/04/04 23:38:53 VasukiH
; Updated comments in header
;
; Revision 1.1.1.1 2003/08/23 00:38:33 VasukiH
; First import of demo source into CVS Repository
;
;
;
; --------------------------------------------------------------------------
;
; Software and Development Tools Info:
; --------------------------------------------------------------------------
; Tool Version
; --------------------------------------------------------------------------
; MPLAB IDE 7.0
; MPLAB C30 Toolsuite 1.30
; dsPICDEM(TM) Processor Board 1.10
; --------------------------------------------------------------------------
;
; File Notes:
; Block FIR implementation for Microchip's dsPIC30F 16-bit MCU.
; This file should be assembled and linked against filter coefficients
; generated by dsPicFD -- filter design software by Momentum Data Systems.
;
;
; Module Re-entrancy:
; Module re-entrancy is not supported
;
;
; Input: for routine BlockFIRFilter
;
; w0 = pointer to FIR filter structure
; w1 = pointer to input sample buffer
; w2 = pointer to output sample buffer
; w3 = number of output samples to generate
;
;
; System Resource usage:
; w0, w3 used not restored
; w1, w2 used not restored
; w4, w5, w6 used not restored
; w8, w10 used, saved and restored
; Acc A used not restored
; MODCON register used for modulo addressing, saved and restored
; XMODSTRT, XMODEND used, saved and restored
; YMODSTRT, YMODEND used, saved and restored
; CORCON used, saved and restored
;
; Input: for FIRFilterInit
; w0 = pointer to filter structure
;
;
; do and repeat instruction usage
; 1 level do instruction
; 1 level repeat instruction
;
;
; Module Cycle Count
; _sub_fir_filter: 48 + N*(4 + M) (+2 if PSV)
; _FIRFilterInit: 7 + M
; with N: number of samples per block, M: number of taps in filter.
;
;END_HEADER
; offsets into FIR Filter structure (entries are word wide -- hence +=2)
.equ oNumTaps, 0 ; number of filter coefficients
.equ oTapsBase, 2 ; base address of filter coefficients
; if coefficients are in data memory
; must be an even address
; base address offset from program page boundary
; if coefficients are in program memory
.equ oTapsEnd, 4 ; end address of filter coefficients
; must be an odd address
; end address offset from program page boundary
; if coefficients are in program memory
.equ oTapsPage, 6 ; 0xFF00 if coefficients are in data space
; coefficient buffer page number
; if coefficients are in program memory
.equ oDelayBase, 8 ; base address of delay buffer
.equ oDelayEnd, 10 ; end address + 1 of delay buffer
.equ oDelayPtr, 12 ; starting value of delay pointer
.text
.global _sub_fir_filter
_sub_fir_filter:
; Entry context save of selected registers
push MODCON ; save context of MODCON
push w8 ; save context of w8
push w10 ; save context of w10
push XMODSRT ; save context of XMODSRT
push XMODEND ; save context of XMODEND
push YMODSRT ; save context of YMODSRT
push YMODEND ; save context of YMODEND
push CORCON ; save context of CORCON
push PSVPAG ; save context of PSVPAG
; Check if filter-taps are stored in Program Space or Data Space and enable
; PSV and set up PSVPAG accordingly
mov [w0+oTapsPage], w10
mov #0xFF00, w8
cp w8, w10 ; perform w8-w10 (if w10 = FF00 then do not enable PSV)
bra z, no_psv ; branch if compare true (coefficients are in data space)
mov #0x00B4,w8 ; Enable enable Program Space Visibility,
; Accumulator A Saturation and Data Space write Saturation
; as bits 2, 5 and 7 are set in CORCON
; Also note bits 2, 5 and 7 are in low order byte which is
; the first byte of a 2 byte word in a little endian
; processor such as the dsPIC30
; also, enable unbiased (convergent) rounding mode,
; 1.39 saturation enabled, fractional mult.
mov w10, PSVPAG ; PSVPAG = Program Space page containing filter taps
bra SetupPointers
no_psv:
mov #0x00B0,w8 ; Enable Accumulator A Saturation and
; Data Space write Saturation
; as bits 5 and 7 are set in CORCON
; Setup pointers and modulo addressing
SetupPointers:
mov w8, CORCON ; set PSV and saturation options
mov [w0+oTapsEnd],w8
mov w8, XMODEND ; XMODEND = end address of filter coefficients
mov [w0+oTapsBase],w8 ; w8 = base address of taps/filter coefficients
mov w8, XMODSRT ; XMODSRT = base address of filter coefficients
mov [w0+oDelayEnd],w10
mov w10, YMODEND ; YMODEND = end address of delay line
mov [w0+oDelayBase],w10
mov w10, YMODSRT ; YMODSRT = base address of delay line
mov [w0+oNumTaps],w4
sub w4,#3, w4 ; w4 = numTaps-3 (for do loop control)
mov #0xC0A8, w10 ; set XMD = W8 and YMD = W10
mov w10, MODCON ; enable X & Y Modulus
dec w3,w3 ; w3 is do loop counter - set to 1 less than count
mov [w0+oDelayPtr],w10 ; w10 = pointer to current delay sample
; Perform Block FIR filtering
do w3, blockLoop ; loop until all input samples have been processed
mov [w1++],[w10] ; store new sample into delay line
; clear a, prefetch tap and sample pair, update ptrs
clr a, [w8]+=2, w5, [w10]+=2, w6
repeat w4 ; perform macs (except for last two)
mac w5*w6, a, [w8]+=2, w5, [w10]+=2, w6
mac w5*w6, a, [w8]+=2, w5, [w10], w6 ; perform second-to-last mac
mac w5*w6, a ; perform last mac
; round and store result in AccA to output buffer
sac.r a, [w2]
blockLoop:
asr [w2], [w2++] ; this is the last instruction in the loop controlled
; by W3
mov w10,[w0+oDelayPtr] ; update delay line pointer
; note: that the delay line pointer can have multiple
; wraps depending on the number of input samples
; Cleanup(Context restore of selected registers)
clr MODCON ; disable modulo addressing
nop
pop PSVPAG ; restore context of PSVPAG
pop CORCON ; restore context of CORCON
pop YMODEND ; restore context of YMODEND
pop YMODSRT ; restore context of YMODSRT
pop XMODEND ; restore context of XMODEND
pop XMODSRT ; restore context of XMODSRT
pop w10 ; restore context of w10
pop w8 ; restore context of w8
pop MODCON ; restore context of MODCON
nop
return ; exit from _BlockFir
;Subroutine: Filter State initialization
; Input:
; w0 = pointer to filter structure
.section .text
.global _FIRFilterInit
_FIRFilterInit:
mov [w0+oDelayBase], w1 ; w1 = base address of delay line
mov [w0+oNumTaps], w0 ; w0 = num taps
dec w0,w0 ; w0 -=1
repeat w0
clr [w1++] ; init delay line (i.e. fill with zeros)
return ; exit from _InitFir
.end ;EOF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -