⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 8th_order_fir.s90

📁 硬件设计资料,刚上网查找资料,是个新手,望大家提携了,
💻 S90
字号:
;*****************************************************
;* File: 8th_order_FIR.s90
;*
;*	Version: 1.0
;*	Date:	01.06.15 [yy.mm.dd]
;*	Author: jllassen
;*
;*  Last modified 02.02.20, by jllassen
;*    Changes: ported the code from the AVR assembler to IAR assembler/compiler
;*
;* Target device: AVRs with HW multiplier
;*
;* Compiler:
;*      IAR EWAVR 2.26C
;*
;* Describtion: 
;*		8th order FIR filter. 
;*		10-bit signed data. 
;*      16-bit signed filter coefficients.
;*
;* Usage:
;*		Implemented so that the filter can be called from IAR EWAVR C compiler.
;*      address to the filter nodes and filter coefficients should be provided
;*      as first calling argument (will thus be placed in R16:R17) and the new 
;*      input sample to the filter should be provided as the second calling
;*      argument (placed in R18:R19).
;*      
;*      int FIR_filter(*myFilter, newDataSample);
;*
;*      The structure for the filter nodes and filter coefficients should be
;*      as follows:
;*      
;*      struct FIR_filter{
;*	      int filterNodes[FILTER_ORDER];			  //memory nodes required to store x(n-0), x(n-1), ..., x(n-8)
;*	      int filterCoefficients[(FILTER_ORDER)+1];   //filter coefficients B0, B1, B2, ..., B8
;*	      } myFilter = {0,0,0,0,0,0,0,0, 
              B0,B1,B2,B3,B4,B5,B6,B7,B8}; 
;*
;*      The filter nodes should be initialized prior to the first call of the 
;*      filter function and the filter coefficients should be scaled to use
;*      signed 16-bit resolution (max)
;*      
;* Registers usage:
;*		r0-4, r16-23, Z (all scratch/volatile registers)
;*      r14-r15 (stored and restored as required)
;*
;* Memory usage for variables and constants:
;*		16 bytes SRAM for filter nodes (filter memory)
;*      18 bytes SRAM for filter coefficients
;*
;* Stats:
;*		INIT:  Depending on compiler settings (399 cycles)
;*		FILTER:  220 instructions; 317 cycles (excl. ret)
;*****************************************************
	NAME	assembly(16)
	PUBLIC	FIR8
	RSEG	CODE

;ZERO register (used to add carry flag)
#define ZERO  r2

#define ZL R30
#define SW_STACK Y

;Accumulator - 32bit
#define AC3 r14
#define AC2 r15
#define AC1 r16
#define AC0 r17

;First argument passed in the function call: the address to the filter struct (16 bit address pointer)
#define FILTER_POINTER r16

;Second argument passed in the function call: the new data sample
#define NDATAL R18
#define NDATAH R19

;Data samples mul register (used in multiplication)
#define DATAL R20
#define DATAH R21

;Filter coefficient mul register (used in multiplication)
#define COEFL R22
#define COEFH R23

;Filter nodes offset relative to filter struct address
#define X1  0*2
#define X2  1*2
#define X3  2*2
#define X4  3*2
#define X5  4*2
#define X6  5*2
#define X7  6*2
#define X8  7*2

;Filter coefficient offset relative to filter struct address
#define B0  8*2
#define B1  9*2
#define B2  10*2
#define B3  11*2
#define B4  12*2
#define B5  13*2
#define B6  14*2
#define B7  15*2
#define B8  16*2

;**************************************************
;* MACROS
;**************************************************
STORE_REGISTER MACRO
    st  -Y, AC3
    st  -Y, AC2
    ENDM
    
RESTORE_REGISTER MACRO
    ld  AC2, Y+
    ld  AC3, Y+
    ENDM
    
LOAD_NODE MACRO
	ldd	  DATAL,Z+\1		; Load low byte of node 
	ldd	  DATAH,Z+\1+1		; Load high byte of node
    ENDM

UPDATE_NODE MACRO
	std	  Z+\1, DATAL		; Update low byte of node to prepare next filter run
	std	  Z+\1+1, DATAH		; Update high byte of node to prepare next filter run
    ENDM

LOAD_COEF MACRO
	ldd	  COEFL,Z+\1		; Load low byte of node 
	ldd	  COEFH,Z+\1+1		; Load high byte of node
    ENDM

MUL_MOV_32 MACRO
	muls	COEFH, DATAH	; Signed multiply, coefficient high byte and data high byte
	movw    AC3, r0			; Copy result word into accumulator byte 2:3
    	
	mul	COEFL, DATAL		; Unsigned multiply, coefficient low byte and data low byte
	movw	AC1, r0			; Copy result word into accumulator byte 2:3

	mulsu	COEFH, DATAL	; Signed-unsigned multiply, coefficient high byte and data low byte
	sbc	AC3, ZERO			; Sign extention
	add	AC1, r0				; Add low byte of result to accumulator byte 1
	adc	AC2, r1				; Add with carry high byte of result to accumulator byte 2
	adc	AC3, ZERO			; Add carry to accumulator byte 3

	mulsu	DATAH, COEFL	; Signed-unsigned multiply, data high byte and coefficient low byte
	sbc	AC3, ZERO			; Sign extention
	add	AC1, r0				; Add low byte of result to accumulator byte 1
	adc	AC2, r1				; Add with carry high byte of result to accumulator byte 2
	adc	AC3, ZERO			; Add carry to accumulator byte 3
    ENDM

;SMAC32:
SMAC32 MACRO
	muls	COEFH, DATAH	; Signed multiply, coefficient high byte and data high byte
	add	AC2, r0				; Add low byte of result to accumulator byte 2
	adc	AC3, r1				; Add with carry high byte of result to accumulator byte 3

	mul	COEFL, DATAL		; Unsigned multiply, coefficient low byte and data low byte
	add	AC0, r0				; Add low byte of result to accumulator byte 0
	adc	AC1, r1				; Add with carry high byte of result to accumulator byte 1
	adc	AC2, ZERO			; Add carry to accumulator byte 2
	adc	AC3, ZERO			; Add carry to accumulator byte 3

	mulsu	COEFH, DATAL	; Signed-unsigned multiply, coefficient high byte and data low byte 
	sbc	AC3, ZERO			; Sign extention
	add	AC1, r0				; Add low byte of result to accumulator byte 1
	adc	AC2, r1				; Add with carry high byte of result to accumulator byte 2
	adc	AC3, ZERO			; Add carry to accumulator byte 3

	mulsu	DATAH, COEFL 	; Signed-unsigned multiply, data high byte and coefficient low byte
	sbc	AC3, ZERO			; Sign extention
	add	AC1, r0				; Add low byte of result to accumulator byte 1
	adc	AC2, r1				; Add with carry high byte of result to accumulator byte 2
	adc	AC3, ZERO			; Add carry to accumulator byte 3
;	ret
    ENDM
	
;*****************************************************
; FIR filter function
;*****************************************************
FIR8:
	clr   ZERO					; Clear ZERO register 
	movw  ZL, FILTER_POINTER	; Move Struct pointer to the Z-pointer (r30:r31)
	STORE_REGISTER
	
;B8*x[n-8]
	LOAD_COEF B8
	LOAD_NODE X8
    MUL_MOV_32

;B7*x[n-7]
	LOAD_COEF   B7
	LOAD_NODE   X7
	UPDATE_NODE X8
    SMAC32
;    rcall  SMAC32

;B6*x[n-6]
	LOAD_COEF   B6
	LOAD_NODE   X6
	UPDATE_NODE X7
    SMAC32
;    rcall  SMAC32

;B5*x[n-5]
	LOAD_COEF   B5
	LOAD_NODE   X5
	UPDATE_NODE X6
    SMAC32
;    rcall  SMAC32

;B4*x[n-4]
	LOAD_COEF   B4
	LOAD_NODE   X4
	UPDATE_NODE X5
    SMAC32
;    rcall  SMAC32

;B3*x[n-3]
	LOAD_COEF   B3
	LOAD_NODE   X3
	UPDATE_NODE X4
    SMAC32
;    rcall  SMAC32

;B2*x[n-2]
	LOAD_COEF   B2
	LOAD_NODE   X2
	UPDATE_NODE X3
    SMAC32
;    rcall  SMAC32

;B1*x[n-1]
	LOAD_COEF   B1
	LOAD_NODE   X1
	UPDATE_NODE X2
    SMAC32
;    rcall  SMAC32
	
;B0*x[n]
	LOAD_COEF   B0
	movw        DATAL, NDATAL	; Load new sample into data multiply register
	UPDATE_NODE X1
    SMAC32
;    rcall  SMAC32

;Due to coefficient scaling (gain factor 2^15) the output requires "unscaling"
	lsl   AC1           ; Scaling to gain factor 2^16
	rol   AC2			; --
	rol	  AC3			; --

	mov   AC1,AC2       ; Scaling to gain factor 2^0
	mov   AC2,AC3       ; --

;Return the value stored in accumulator AC2 and AC1 (which are the return registers)
	RESTORE_REGISTER
	ret
    
    END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -