Anda di halaman 1dari 12

Lab 2 Introduction to DSP Digital Signal Processors

S0002E DSP Systems In Practice

Andre Lundkvist
nadlun-5@student.ltu.se

Rikard Qvarnstrm o
rikqva-5@student.ltu.se

Lule 6th October 2009 a,

Abstract This report is for a lab in DSP - Systems in Practice (S0002E), that gives a elementary introduction to digital lter design in assembler on DSP chips. The focus of this report will be placed on the Finite Impulse Response (FIR) notch lter. This diers from an Innite Impulse Response (IIR) lter by only using the input signal, and no feedback from the output signal. The goal is to remove a sinusoid disturbance from a song. Because the frequency disturbance is xed, a notch lter will be designed to remove the disturbance. The lter coecients used will come from the previous lab. Due to the limitation of the hardware the coecients needs to be scaled to 1.15 binary format (displayed in HEX). The rst lter implementation in assembler will be for a second order notch lter, using straight forward manual updating of the buers. The code will be expanded to be able to handle a lter of arbitrary order. To be able to handle this implementation a circular buer is used to store the samples and coecients.

Contents
1 Introduction 1.1 Notch Filter Characteristics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Assignments 2.1 Assignment 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Assignment 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Assignment 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A Assembler Code A.1 Assignment 2 Memory Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . A.2 Assignment 2 Processing Section . . . . . . . . . . . . . . . . . . . . . . . . . . . A.3 Assignment 3 Memory Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . A.4 Assignment 3 Processing Section . . . . . . . . . . . . . . . . . . . . . . . . . . . B Matlab Code B.1 Decimal to 1.15 HEX Converter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 3 3 3 3 4 4 5 7 8 10 10

Introduction

This lab introduce the STUD-1 DSP development board, and the tools for compilation and loading the program. In lab 1, a notch lter was designed in MATLAB. The coecients was reused to implement the notch lter, see the subsection below for some basic introduction to the notch lter. The lter is meant to be used on real-time signals and therefore the program has to be fast enough to nish before the next sample. To get the lter working on the STUD-1 the lter function had to be converted to assembler code and imported to the STUD-1 DSP development board. Assembler is close to machine code so you have full control over the registers used and can therefore control the movement of all sampled values and coecients.

1.1

Notch Filter Characteristics

The notch lter is characterized by the sharp attenuation dip in frequency domain. This lter type is generally used to remove a disturbance of a known narrow band frequency. The width of the attenuation dip and the maximum attenuation depends on the order and implementation of the lter. The maximum gradient of the phase slope is at the center of the attenuation frequency.

2
2.1

Assignments
Assignment 1

The rst assignment was to setup the environment and test that all parts could work together. First download the code stub from the course page and Assemble, Link and Load it. The assembler used is the as219x, and linker ld21 which are a part of the open21xx tool suite from SharpShin. The bootable program le (*.bin) is loaded to the EEPROM on the STUD-1 DSP development board using PonyProg2000. To run the program on the development board all thats needed is to press the reset switch.

2.2

Assignment 2

In this assignment the notchlter designed in the previous lab is going to be implemented on the DSP. So the coecients are already dened but need to be converted to 1.15 binary format. First the coecients need to be scaled because the maximum value possible in the 1.15 format is 1 215 and the minimum value is 1. To convert the scaled values to 1.15 format a matlab script is used, see appendix B.1. The resulting coecients can be found in table 1. To use the Table 1: Coecients for the notch lter implemented on the DSP Coecient Dec value 1.15 HEX value A(1) 0.9998 0x7FFF A(2) 0.0000 0x0000 A(3) 0.0000 0x0000 B(1) 0.7070 0x5A80 B(2) -0.9999 0x8001 B(3) 0.7070 0x5A80

lter on the development board the lter algorithm has to be implemented in assembler. The code in appendix A.1 & A.2 is implemented for a second order lter in real-time, by utilizing the denition of the input-output dierence equation (1).
N M

ak y[n k] =
k=0 r=0

br x[n r]

(1)

2.3

Assignment 3

This assignment is based around the code from assignment 2 seen in appendix A.1 & A.2. The task is to rewrite the code so the input can be a FIR lter of arbitrary order. The main dierence in the code is that the previous version did everything manually without any loops. Here, to be able to make a lter of arbitrary order, the program has to be able to multiply a dened set of times each interrupt, this makes a loop required. To easily access the registers and keep the pointers circulating in a controllable way, a circular buer is used. The amount of loop iterations is dened as the length of the buer which stores the lter coecients. After the loop, the new value from the ADC is stored in the buer at the position of the oldest sample. And the pointer is placed to the newest value and stored in the datamemory to the next interrupt. The nal code can be seen appendix A.3 & A.4.

A
A.1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

Assembler Code
Assignment 2 Memory Handling

/ S0002E Lab 2 Assignment 2 Andre Lundkvist nadlun5@student.ltu.se Rikard Qvarnstrom rikqva5@student.ltu.se / / / / DM data / / / // AD1885 stereochannel data holders used for // DSP processing of audio data recieved from codec // Input samples
.var .var Left_Channel; Right_Channel; . section / dm data0 ;

// Filter Buffers
.var .var .var .var L e f t _ i n _ B u f f e r [3] = 0 x0000 , 0 x0000 , 0 x0000 ; R i g h t _ i n _ B u f f e r [3] = 0 x0000 , 0 x0000 , 0 x0000 ; L e f t _ o u t _ B u f f e r [3] = 0 x0000 , 0 x0000 , 0 x0000 ; R i g h t _ o u t _ B u f f e r [3] = 0 x0000 , 0 x0000 , 0 x0000 ;

// Output samples
.var .var .var Left_Channel_Out; Right_Channel_Out; IOPG_TMP ;

/ / / PM DATA / / /
. section / pm program0 ; .var FB_A [] = " A_Coeffs . dat " ; .var FB_B [] = " B_Coeffs . dat " ;

// Create program memory variables //.var FB_A[3] = 0x7FFF, 0x0000, 0x0000; //.var FB_B[3] = 0x5A80, 0x8000, 0x5A80;

A.2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

Assignment 2 Processing Section


their corresponding HEX value = 0x7FFF = 0x0000 = 0x0000 = 0x5A80 = 0x8001 = 0x5A80

// Process input samples here... // Coefficients and // A(1) [0.9998] // A(2) [0.0000] // A(3) [0.0000] // B(1) [0.7070] // B(2) [0.9999] // B(3) [0.7070]

// // Filter the Right Channel: // Clear registers


MR = 0;

// Do the right channel filtering


AR = DM ( R i g h t _ C h a n n e l ) ;

// Update the right in buffer


AR = DM ( R i g h t _ i n _ B u f f e r +1) ; DM ( R i g h t _ i n _ B u f f e r +2) = AR ; AR = DM ( R i g h t _ i n _ B u f f e r +0) ; DM ( R i g h t _ i n _ B u f f e r +1) = AR ; AR = DM ( R i g h t _ C h a n n e l ) ; DM ( R i g h t _ i n _ B u f f e r +0) = AR ;

// Start multiply and accumulate the right channel


MX0 = DM ( R i g h t _ i n _ B u f f e r +0) ; MY0 = DM ( FB_B +0) ; // should be in PM.. MR = MR + MX0 * MY0 ( SS ) ; MX0 = DM ( R i g h t _ i n _ B u f f e r +1) ; MY0 = DM ( FB_B +1) ; // should be in PM.. MR = MR + MX0 * MY0 ( SS ) ; MX0 = DM ( R i g h t _ i n _ B u f f e r +2) ; MY0 = DM ( FB_B +2) ; // should be in PM.. MR = MR + MX0 * MY0 ( SS ) ; MX0 = DM ( R i g h t _ o u t _ B u f f e r +1) ; MY0 = DM ( FB_A +1) ; // should be in PM.. MR = MR - MX0 * MY0 ( SS ) ; MX0 = DM ( R i g h t _ o u t _ B u f f e r +2) ; MY0 = DM ( FB_A +2) ; // should be in PM.. MR = MR - MX0 * MY0 ( SS ) ;

// Multiply MR with constant FB_A(0) (given as 1/a0)


AR = MR1 ; MX0 = AR ; MY0 = DM ( FB_A +0) ; MR = MX0 * MY0 ( SS ) ;

// Take the new output value from the multiplyer


DM ( R i g h t _ C h a n n e l _ O u t ) = MR1 ;

// Update the right out buffer


AR = DM ( R i g h t _ o u t _ B u f f e r +1) ; DM ( R i g h t _ o u t _ B u f f e r +2) = AR ; AR = DM ( R i g h t _ o u t _ B u f f e r +0) ; DM ( R i g h t _ o u t _ B u f f e r +1) = AR ; AR = DM ( R i g h t _ C h a n n e l _ O u t ) ; DM ( R i g h t _ o u t _ B u f f e r +0) = AR ;

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123

// // Filter the Left Channel: // Clear registers


MR = 0;

// Do the left channel filtering


AR = DM ( L e f t _ C h a n n e l ) ;

// Update the left in buffer


AR = DM ( L e f t _ i n _ B u f f e r +1) ; DM ( L e f t _ i n _ B u f f e r +2) = AR ; AR = DM ( L e f t _ i n _ B u f f e r +0) ; DM ( L e f t _ i n _ B u f f e r +1) = AR ; AR = DM ( L e f t _ C h a n n e l ) ; DM ( L e f t _ i n _ B u f f e r +0) = AR ;

// Start multiply and accumulate the left channel


MX0 = DM ( L e f t _ i n _ B u f f e r +0) ; MY0 = DM ( FB_B +0) ; // should be in PM.. MR = MR + MX0 * MY0 ( SS ) ; MX0 = DM ( L e f t _ i n _ B u f f e r +1) ; MY0 = DM ( FB_B +1) ; // should be in PM.. MR = MR + MX0 * MY0 ( SS ) ; MX0 = DM ( L e f t _ i n _ B u f f e r +2) ; MY0 = DM ( FB_B +2) ; // should be in PM.. MR = MR + MX0 * MY0 ( SS ) ; MX0 = DM ( L e f t _ o u t _ B u f f e r +1) ; MY0 = DM ( FB_A +1) ; // should be in PM.. MR = MR - MX0 * MY0 ( SS ) ; MX0 = DM ( L e f t _ o u t _ B u f f e r +2) ; MY0 = DM ( FB_A +2) ; // should be in PM.. MR = MR - MX0 * MY0 ( SS ) ;

// Multiply MR with constant FB_A(0) (given as 1/a0)


AR = MR1 ; MX0 = AR ; MY0 = DM ( FB_A +0) ; MR = MX0 * MY0 ( SS ) ;

// Take the new output value from the multiplyer


DM ( L e f t _ C h a n n e l _ O u t ) = MR1 ;

// Update the right out buffer


AR = DM ( L e f t _ o u t _ B u f f e r +1) ; DM ( L e f t _ o u t _ B u f f e r +2) = AR ; AR = DM ( L e f t _ o u t _ B u f f e r +0) ; DM ( L e f t _ o u t _ B u f f e r +1) = AR ; AR = DM ( L e f t _ C h a n n e l _ O u t ) ; DM ( L e f t _ o u t _ B u f f e r +0) = AR ;

// End of sample processing...

A.3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

Assignment 3 Memory Handling

/ S0002E Lab 2 Assignment 3 Andre Lundkvist nadlun5@student.ltu.se Rikard Qvarnstrom rikqva5@student.ltu.se / / / / DM data / / / // AD1885 stereochannel data holders used for // DSP processing of audio data recieved from codec // Input samples
.var .var Left_Channel; Right_Channel; . section / dm data0 ;

// Length of coefficients
.var .var A_Length = length ( FB_A ) ; B_Length = length ( FB_B ) ;

// Filter Buffers
.var .var .var .var L e f t _ i n _ B u f f e r [] = " B_Coeffs . dat " ; R i g h t _ i n _ B u f f e r [] = " B_Coeffs . dat " ; L e f t _ o u t _ B u f f e r [] = " A_Coeffs . dat " ; R i g h t _ o u t _ B u f f e r [] = " A_Coeffs . dat " ;

// Initialize to x_Coeffs to get the correct length // Note {...} = Set all elements to ... // Output samples
.var .var .var Left_Channel_Out; Right_Channel_Out; IOPG_TMP ;

// Store the adress pointer to the next interrupt


.var .var Init_I0_Right = Right_in_Buffer; Init_I0_Left = Left_in_Buffer;

/ / / PM data / / /
. section / pm program0 ; .var FB_A [] = " A_Coeffs . dat " ; .var FB_B [] = " B_Coeffs . dat " ;

// Create program memory variables //.var FB_A[3] = 0x7FFF, 0x0000, 0x0000; //.var FB_B[3] = 0x5A80, 0x8000, 0x5A80;

A.4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

Assignment 3 Processing Section


their corresponding HEX value = 0x7FFF = 0x0000 = 0x0000 = 0x5A80 = 0x8001 = 0x5A80

// Process input samples here... // Coefficients and // A(1) [0.9998] // A(2) [0.0000] // A(3) [0.0000] // B(1) [0.7070] // B(2) [0.9999] // B(3) [0.7070]

// // Filter the Right Channel: // Clear registers and start processing of Right Channel; MR = 0; // Clear MAC Output // Initialize circ Buffer for Right_in_Buffer DMPG1 = Page ( R i g h t _ i n _ B u f f e r ) ; // Set DAG0 page 1 for Right_in_Buffer I0 = DM ( I n i t _ I 0 _ R i g h t ) ; // Set the start pointer I0 to the newest value in buffer. L0 = length ( R i g h t _ i n _ B u f f e r ) ; // Set the length of the buffer M0 = 1; // Set the increment value = +1
AX0 = R i g h t _ i n _ B u f f e r ; Reg ( B0 ) = AX0 ;

// Set the base adress for DAG0

// initialize circ Buffer for FB_B // Same as above but for DAG1 and fb_b coefficient buffer.
DMPG1 = Page ( FB_B ) ; I1 = FB_B ; L1 = length ( FB_B ) ; M1 = 1; AX0 = FB_B ; Reg ( B1 ) = AX0 ;

// Loop

// end loop

CNTR = L1 ; // Set loop length to the length of fbbuffer. DO loopR UNTIL CE ; MX0 = DM ( I0 += M0 ) ; MY0 = DM ( I1 += M1 ) ; MR = MR + MX0 * MY0 ( SS ) ; // MAC right buffer fb_b loopR : nop ; // Preserved..

AR = DM ( R i g h t _ C h a n n e l ) ; M0 = -1; MODIFY ( I0 += M0 ) ; DM ( I0 +0) = AR ; DM ( I n i t _ I 0 _ R i g h t ) = I0 ;

// // // // //

Read in a new value for right channel. Because DAG has cycled one lap... ... go back to last sample in buffer... ... and store the new value there. Store the new value pointer to Init_I0

// Right Channel Output:


DM ( R i g h t _ C h a n n e l _ O u t ) = MR1 ;

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

// // Filter the Left Channel: // Clear registers and start processing of Left Channel; // See comments for Right Channel (it has the same structure) MR = 0; // Clear MAC Output // Initialize circ Buffer for Left_in_Buffer
DMPG1 = Page ( L e f t _ i n _ B u f f e r ) ; I0 = DM ( I n i t _ I 0 _ L e f t ) ; L0 = length ( L e f t _ i n _ B u f f e r ) ; M0 = 1; AX0 = L e f t _ i n _ B u f f e r ; Reg ( B0 ) = AX0 ;

// initialize circ Buffer for FB_B


DMPG1 = Page ( FB_B ) ; I1 = FB_B ; L1 = length ( FB_B ) ; M1 = 1; AX0 = FB_B ; Reg ( B1 ) = AX0 ;

// Loop
CNTR = L1 ; DO loopL UNTIL CE ; MX0 = DM ( I0 += M0 ) ; MY0 = DM ( I1 += M1 ) ; MR = MR + MX0 * MY0 ( SS ) ; loopL : nop ;

// end loop

AR = DM ( L e f t _ C h a n n e l ) ; M0 = -1; MODIFY ( I0 += M0 ) ; DM ( I0 +0) = AR ; DM ( I n i t _ I 0 _ L e f t ) = I0 ;

// Left Channel Output:


DM ( L e f t _ C h a n n e l _ O u t ) = MR1 ;

// End of sample processing...

B
B.1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

Matlab Code
Decimal to 1.15 HEX Converter

% dec2q15hex Decimal number to hex 1.15 (q15) string conversion. % h = dec2q15hex(d,Nbits) converts the decimal number d to % hex 1.15 fractional format. The number d must be within % the range [1,12^(15)]. % % % (Patrik Pjrvi 2003)
function res = dec2q15hex ( dec ) format long ;

% dec must be within [1,12^(15)]


i f ( dec > 1 -2^( -15) ) || ( dec < -1) error ( ERROR : dec2q15hex ( dec ) - > > dec must be within [ -1 ,1 -2^( -15) ] ) end

% If dec is positive, convert to hex


i f dec > 0 dec = c e i l ( dec *2^15) ; h = dec2base ( dec ,16) ;

% If dec is zero, set h to 0 % (dec2base cant handle zeros)


e l s e i f dec == 0 h = 0 ;

% If dec is negative, convert to binary, % do twos complement, convert to hex


else dec = c e i l (abs( dec ) *2^15) -1; bin = dec2base ( dec ,2) ;

% Make binary vector 16 bits long


f o r idx = 1:16 - length ( bin ) bin = strcat ( 0 , bin ) ; end

% Do twos complement
twosbin = zeros (1 ,16) ; f o r idx = 1: length ( bin ) bin2s ( idx ) = num2str( mod (str2num( bin ( idx ) ) +1 ,2) ) ; end d = base2dec ( bin2s ,2) ; h = dec2base (d ,16) ; end

% Convert to hex

% Put in form: 0xNNNN


i f length ( h ) == 1 h = strcat ( 0 x000 ,h ) ; e l s e i f length ( h ) == 2 h = strcat ( 0 x00 ,h ) ; e l s e i f length ( h ) == 3 h = strcat ( 0 x0 ,h ) ; else h = strcat ( 0 x ,h ) ; end format; res = h ;

10

Anda mungkin juga menyukai