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

📄 exp7.html

📁 (Ebook-Pdf) Dsp - Real Time Digital Signal Processing (Usando Tms320-55Xx). 有书
💻 HTML
📖 第 1 页 / 共 4 页
字号:
</span><![endif]>Profile the DSP run-time cycles for 128 points and 1024 points
FFT. Record the memory usage of the fixed-point function <span
style='font-family:"Courier New"'>bit_rev() </span>and <span style='font-family:
"Courier New"'>function fft()</span>.</p>

<p style='margin-right:1.0in;margin-left:1.0in'>&nbsp;</p>

<p><a href="#top"><span style='font-size:7.5pt'>Back to Top</span></a> 

<input type=button value="go back" onclick="history.go(-1)">

</p>


<div class=MsoNormal align=center style='text-align:center'>

<hr size=3 width="100%" align=center>

</div>


<p style='margin-right:1.0in;margin-left:1.0in'><span style='font-size:13.5pt;
color:blue'>Experiment 7B - Radix-2 Complex FFT in C55x Assembly Language</span></p>

<p style='margin-right:1.0in;margin-left:1.0in'>Assembly routines provide the
most efficiency in terms of run time and code density. For digital signal
processing applications such as filtering and FFT, the assembly language is
usually used. This experiment uses the C55x assembly routines to perform the
same FFT function as the previous experiment. The assembly routine <a
href="exp7/fft.asm"><span style='font-family:"Courier New"'>fft.asm</span></a>
in Table E7-6 closely follows the code flow in fixed-point C function for
easier understand. As mentioned in the book, there are many ways readers can
use to improve the run time efficiency of the FFT routine.</p>

<p align=center style='margin-right:.5in;margin-left:.5in;text-align:center'>Table
E7-6 Assembly routine <span style='font-family:"Courier New"'>fft.asm</span></p>

<form>

<p align=center style='margin-right:.5in;margin-left:.5in;text-align:center'><TEXTAREA ROWS="7" COLS="70" NAME="fft.asm">;&#13;&#10;;   fft.asm - Radix-2 complex FFT (for N=2^EXP points)&#13;&#10;;             Using table lookup method&#13;&#10;;                               &#13;&#10;;   Prototype: void fft(complex *, int, complex *, int); &#13;&#10;;&#13;&#10;;   Entry:  arg0: AR0-FFT input sample buffer pointer   &#13;&#10;;           arg1: T0-number of FFT stage, EXP&#13;&#10;;           arg2: AR1-twiddle factor array pointer     &#13;&#10;;           arg3: T1-scale flag &#13;&#10;;                 if scale needed, (T1==1) SCALE=2;&#13;&#10;;                 if don't need scale (T1==0) SCALE=1;&#13;&#10;;                                                      &#13;&#10;;   Note: 1. When used as the FFT routine it takes in time domain &#13;&#10;;         samples in Q15 and generates Q14 frequency domain samples&#13;&#10;;         2. When used as the IFFT routine it takes in frequency domain &#13;&#10;;         samples in Q14 and generates Q15 time domain samples&#13;&#10;;&#13;&#10;;    Revised: Dec. 3, 2001&#13;&#10;;             Add an instruction to copy XAR0 to XAR5 for addressing extended page&#13;&#10;&#13;&#10;        .global _fft&#13;&#10;&#13;&#10;;&#13;&#10;;&#9;Declare local variables in SP address mode for C-callable&#13;&#10;;&#13;&#10;ARGS    .set    0       ; Number of variables passed via stack&#13;&#10;&#13;&#10;FFT_var .struct         ; Define local variable structure&#13;&#10;d_temp      .int (2)    ; Temporary variables (Re, Im)&#13;&#10;d_L         .int&#13;&#10;d_N         .int  &#13;&#10;d_T2        .int        ; Used to save content of T2&#13;&#10;d_ST1       .int        ; Used to save content of ST1&#13;&#10;d_ST3       .int        ; Used to save content of ST3&#13;&#10;return_addr .int        ; Space for routine return address&#13;&#10;Size        .endstruct&#13;&#10;fft         .set 0&#13;&#10;fft         .tag FFT_var  &#13;&#10;&#13;&#10;    .sect &quot;fft_code&quot;       &#13;&#10;&#9;&#13;&#10;_fft:&#13;&#10;    aadd #(ARGS-Size+1),SP      ; Adjust stack for local vars&#13;&#10;&#13;&#10;    mov  mmap(ST1_55),AR2       ; Save ST1,ST3&#13;&#10;    mov  mmap(ST3_55),AR3   &#13;&#10;    mov  AR2,fft.d_ST1&#13;&#10;    mov  AR3,fft.d_ST3&#13;&#10;    btst @#0,T1,TC1             ; Check SCALE flag set&#9;&#9;&#13;&#10;    mov  #0x6340,mmap(ST1_55)   ; Set CPL,XF,SATD,SXAM,FRCT (SCALE=1) &#13;&#10;    mov  #0x1f22,mmap(ST3_55)   ; Set: HINT,SATA,SMUL   &#13;&#10;    xcc  do_scale,TC1&#13;&#10;    mov  #0x6300,mmap(ST1_55)   ; Set CPL,XF,SATD,SXAM (SCALE=2) &#13;&#10;do_scale&#13;&#10;    &#13;&#10;    mov  T2,fft.d_T2            ; Save T2                     &#13;&#10;||  mov  #1,AC0&#13;&#10;    mov  AC0,fft.d_L            ; Initialize L=1&#13;&#10;||  sfts AC0,T0                 ; T0=EXP&#13;&#10;    mov  AC0,fft.d_N            ; N=1&lt;&lt;EXP&#13;&#10;    mov  XAR1,XCDP              ; CDP = pointer to U[]&#13;&#10;    mov  XSP,XAR4&#9;&#13;&#10;    add  #fft.d_temp,AR4        ; AR4 = pointer to temp&#13;&#10;    mov  XAR0,XAR1              ; AR1 points to sample buffer&#13;&#10;    mov  T0,T1&#13;&#10;    mov  XAR0,XAR5              ; Copy externd bits to XAR5&#13;&#10;&#9;&#9;&#9;&#13;&#10;outer_loop                      ; for (L=1; L&lt;=EXP; L++)    &#13;&#10;    mov  fft.d_L,T0             ; note: Since the buffer is&#13;&#10;||  mov  #2,AC0                 ;       arranged in re,im pairs&#13;&#10;    sfts AC0,T0                 ;       the index to the buffer&#13;&#10;    neg  T0&#9;                    ;       is doubled&#13;&#10;||  mov  fft.d_N,AC1            ;       But the repeat coutners&#13;&#10;    sftl AC1,T0                 ;       are not doubled&#13;&#10;    mov  AC0,T0                 ; LE=2&lt;&lt;L &#9;&#13;&#10;||  sfts AC0,#-1  &#13;&#10;    mov  AC0,AR0                ; LE1=LE&gt;&gt;1           &#13;&#10;||  sfts AC0,#-1                              &#13;&#10;    sub  #1,AC0                 ; Init mid_loop counter&#13;&#10;    mov  mmap(AC0L),BRC0        ;   BRC0=LE1-1&#13;&#10;    sub  #1,AC1                 ; Init inner loop counter&#13;&#10;    mov  mmap(AC1L),BRC1        ;   BRC1=(N&gt;&gt;L)-1   &#13;&#10;    add  AR1,AR0   &#13;&#10;    mov  #0,T2                  ; j=0 &#13;&#10;||  rptblocal mid_loop-1        ; for (j=0; j&lt;LE1;j++) &#13;&#10;    mov  T2,AR5                 ; AR5=id=i+LE1&#13;&#10;    mov  T2,AR3&#9;&#13;&#10;    add  AR0,AR5                ; AR5 = pointer to X[id].re   &#13;&#10;    add  #1,AR5,AR2             ; AR2 = pointer to X[id].im  &#13;&#10;    add  AR1,AR3                ; AR3 = pointer to X[i].re &#13;&#10;||  rptblocal inner_loop-1      ; for(i=j; i&lt;N; i+=LE) &#13;&#10;    mpy  *AR5+,*CDP+,AC0        ; AC0=(X[id].re*U.re&#13;&#10;::  mpy  *AR2-,*CDP+,AC1        ;     -X[id].im*U.im)/SCALE&#9; &#13;&#10;    masr *AR5-,*CDP-,AC0        ; AC1=(X[id].im*U.re                       &#13;&#10;::  macr *AR2+,*CDP-,AC1        ;     +X[id].re*U.im)/SCALE&#13;&#10;    mov  pair(hi(AC0)),dbl(*AR4); AC0H=temp.re AC1H=temp.im &#13;&#10;||  mov  dbl(*AR3),AC2&#13;&#10;    xcc  scale,TC1&#13;&#10;||  mov  AC2&gt;&gt;#1,dual(*AR3)     ; Scale X[i] by 1/SCALE&#13;&#10;    mov  dbl(*AR3),AC2  &#13;&#10;scale&#13;&#10;    add  T0,AR2&#13;&#10;||  sub  dual(*AR4),AC2,AC1     ; X[id].re=X[i].re/SCALE-temp.re&#13;&#10;    mov  AC1,dbl(*(AR5+T0))     ; X[id].im=X[i].im/SCALE-temp.im&#13;&#10;||  add  dual(*AR4),AC2         ; X[i].re=X[i].re/SCALE+temp.re&#13;&#10;    mov  AC2,dbl(*(AR3+T0))     ; X[i].im=X[i].im/SCALE+temp.im&#13;&#10;inner_loop                      ; End of inner loop       &#13;&#10;    amar *CDP+&#13;&#10;    amar *CDP+                  ; Update k for pointer to U[k]&#13;&#10;||  add  #2,T2                  ; Update j    &#13;&#10;mid_loop                        ; End of mid-loop      &#13;&#10;    sub  #1,T1          &#13;&#10;    add  #1,fft.d_L             ; Update L&#13;&#10;    bcc  outer_loop,T1&gt;0        ; End of outer-loop&#13;&#10;&#13;&#10;    mov  fft.d_ST1,AR2          ; Restore ST1,ST3,T2&#13;&#10;    mov  fft.d_ST3,AR3&#13;&#10;    mov  AR2,mmap(ST1_55)&#13;&#10;    mov  AR3,mmap(ST3_55)                              &#13;&#10;    mov  fft.d_T2,T2&#13;&#10;    aadd #(Size-ARGS-1),SP      ; Reset SP&#13;&#10;    ret&#13;&#10;&#13;&#10;    .end &#13;&#10;</TEXTAREA></p>

</form>

<p style='margin-right:1.0in;margin-left:1.0in'>&nbsp;</p>

<p style='margin-right:1.0in;margin-left:1.0in'>Since the DSP provides a
special addressing mode, the bit-reversal addressing, for efficient FFT
implementation, we use the C55x bit-reversal addressing mode for the <a
href="exp7/bit_rev.asm"><span style='font-family:"Courier New"'>bit_rev.asm</span></a>
routine, see Table E7-7. Since C does not support the bit reversal addressing
mode, the assembly routine does not follow the C function in this case.</p>

<p align=center style='margin-right:.5in;margin-left:.5in;text-align:center'>Table
E7-7 Bit reversal using the C55x bit reversal addressing mode</p>

<form>

<p align=center style='margin-right:.5in;margin-left:.5in;text-align:center'><TEXTAREA ROWS="7" COLS="70" NAME="bit_rev.asm">;&#13;&#10;;    bit_rev.asm - Bit-reversal for FFT (N=2^EXP points)&#13;&#10;;                               &#13;&#10;;    Prototype: void bit_rev(complex *, int); &#13;&#10;;&#13;&#10;;    Entry: arg0: AR0-FFT input sample buffer pointer   &#13;&#10;;           arg1: T0-number of FFT stage, EXP&#13;&#10;;&#13;&#10;&#13;&#10;     .global  _bit_rev&#13;&#10;&#9;&#13;&#10;     .sect    &quot;fft_code&quot;&#13;&#10;&#9;&#13;&#10;_bit_rev&#13;&#10;    psh  mmap(ST2_55)        ; Save ST2&#13;&#10;    bclr ARMS                ; Reset ARMS bit&#13;&#10;    mov&#9; #1,AC0&#13;&#10;    sfts AC0,T0&#9;             ; T0=EXP, AC0=N=2^EXP&#13;&#10;    mov  AC0,T0              ; T0=N&#13;&#10;    mov  T0,T1              &#13;&#10;    add  T0,T1              &#13;&#10;    mov  mmap(T1),BK03       ; Circular buffer size=2N&#13;&#10;    mov  mmap(AR0),BSA01     ; Init circular buffer base&#13;&#10;    sub  #2,AC0&#13;&#10;    mov  mmap(AC0L),BRC0     ; Init repeat counter to N-1&#13;&#10;    mov  #0,AR0              ; Set buffer start address&#13;&#10;    mov  #0,AR1              ;   as offset = 0&#13;&#10;    bset AR0LC               ; Enable AR0 and AR1 as&#13;&#10;    bset AR1LC               ;   circular pointers&#13;&#10;||  rptblocal loop_end-1     ; Start bit reversal loop&#13;&#10;    mov&#9; dbl(*AR0),AC0       ;   Get a pair of sample&#13;&#10;||  amov AR1,T1  &#13;&#10;    mov  dbl(*AR1),AC1       ;   Get another pair&#13;&#10;||  asub AR0,T1&#13;&#10;    xccpart swap1,T1&gt;=#0&#13;&#10;||  mov  AC1,dbl(*AR0+)      ;   Swap samples if j&gt;=i&#13;&#10;swap1               &#13;&#10;    xccpart loop_end,T1&gt;=#0    &#13;&#10;||  mov  AC0,dbl(*(AR1+T0B)) &#13;&#10;loop_end                     ; End bit reversal loop&#13;&#10;&#13;&#10;    pop  mmap(ST2_55)        ; Restore ST2&#13;&#10;    ret&#13;&#10;    &#13;&#10;    .end&#13;&#10;</TEXTAREA></p>

</form>

<p style='margin-right:.5in;margin-left:.5in'>&nbsp;</p>

<p style='margin-right:1.0in;margin-left:1.0in'>Another function that the FFT
uses is the twiddle factor generator. In our experiment, <a
href="exp7/w_table.c"><span style='font-family:"Courier New"'>w_table.c</span></a>
is used to create the twiddle factor table. The table lookup method trades the
program space with the execution speed. The twiddle factor can also be
generated using the recursive computation as the floating-point C example. The
function that generate the twiddle factor is listed in Table E7-8.</p>

<p align=center style='margin-right:.5in;margin-left:.5in;text-align:center'>Table
E7-8 Generating twiddle factor</p>

<form>

<p align=center style='margin-right:.5in;margin-left:.5in;text-align:center'><TEXTAREA ROWS="7" COLS="70" NAME="w_table.c">/*&#13;&#10;    w_table.c - Generate twiddle factor lookup table&#13;&#10;*/                                                  &#13;&#10;&#13;&#10;#include &quot;icomplex.h&quot;&#13;&#10;#include &lt;math.h&gt;&#13;&#10;&#13;&#10;#define pi 3.1415926535897&#13;&#10;&#13;&#10;void w_table(complex *U, unsigned int EXP)&#13;&#10;{&#13;&#10;    complex W;               /* Twiddle factor W^k                  */&#13;&#10;    unsigned int i,j,l;&#13;&#10;    unsigned int SL;         /* Number of points in sub DFT at stage L&#13;&#10;                                and offset to next DFT in stage      */&#13;&#10;    unsigned int SL1;        /* Number of butterflies in one DFT at&#13;&#10;                                stage L.  Also is offset to lower point&#13;&#10;                                in butterfly at stage L              */&#13;&#10;&#13;&#10;    for (i=0, l=1; l&lt;=EXP; l++) &#13;&#10;    {&#13;&#10;        SL=1&lt;&lt;l;        &#9;/* LE=2^L=points of sub DFT */&#13;&#10;        SL1=SL&gt;&gt;1;     &#9;&#9;/* Number of twiddle factors in sub-DFT */&#13;&#10;        for (j=0; j&lt;SL1; j++)&#13;&#10;        {                             &#13;&#10;            W.re = (int)((0x7fff*cos(j*pi/SL1))+0.5);&#13;&#10;            W.im = -(int)((0x7fff*sin(j*pi/SL1))+0.5);        &#13;&#10;            U[i++] = W;&#13;&#10;        }&#13;&#10;    }&#13;&#10;}&#13;&#10;</TEXTAREA></p>

</form>

<p style='margin-right:.5in;margin-left:.5in'>&nbsp;</p>

<p style='margin-right:1.0in;margin-left:1.0in'>Finally, the C function <a
href="exp7/exp7b.c"><span style='font-family:"Courier New"'>exp7b.c</span></a>
in Table E7-9 is used to control the experiment.</p>

<p align=center style='margin-right:.5in;margin-left:.5in;text-align:center'>Table
E7-9 List of <span style='font-family:"Courier New"'>epx7b.c</span></p>

<form>

<p align=center style='margin-right:.5in;margin-left:.5in;text-align:center'><TEXTAREA ROWS="7" COLS="70" NAME="exp7b.c">/*&#13;&#10;     exp7b.c - Example to test FFT (fixed-point)&#13;&#10;               Use Twiddle lookup-table method&#13;&#10;*/&#13;&#10;&#13;&#10;#include &quot;icomplex.h&quot;&#13;&#10;#include &quot;input7_i.dat&quot; /* Experiment data */&#13;&#10;&#13;&#10;extern void fft(complex *, unsigned int, complex *, unsigned int);&#13;&#10;extern void bit_rev(complex *, unsigned int);&#13;&#10;extern void w_table(complex *, unsigned int);&#13;&#10;&#13;&#10;#define N 128           /* Number of FFT points */&#13;&#10;#define EXP 7           /* log2(N)              */&#13;&#10;&#13;&#10;#pragma DATA_SECTION(U, &quot;fft_coef&quot;);&#13;&#10;#pragma DATA_SECTION(X, &quot;fft_in&quot;);  &#13;&#10;#pragma DATA_SECTION(spectrum, &quot;fft_out&quot;);&#13;&#10;#pragma DATA_SECTION(ltemp, &quot;fft_temp&quot;); &#13;&#10;#pragma DATA_SECTION(temp, &quot;fft_temp&quot;); &#13;&#10;#pragma CODE_SECTION(main, &quot;fft_code&quot;); &#13;&#10;                          &#13;&#10;complex X[N];           /* Declare input array  */&#13;&#10;complex U[N];           /* Twiddle e^(-j2pi/N) table */    &#13;&#10;complex temp;&#13;&#10;lcomplex ltemp;&#13;&#10;int spectrum[N];&#13;&#10;int re1[N],im1[N];&#13;&#10;&#13;&#10;void main()&#13;&#10;{&#13;&#10;    unsigned int i,j;&#13;&#10;    &#13;&#10;    /* Create Twiddle lookup table for FFT */&#13;&#10;    w_table(U,EXP);      &#13;&#10;  &#13;&#10;    /* Start FFT test */   &#13;&#10;    j=0;&#13;&#10;    for (;;)&#13;&#10;    {&#13;&#10;        for (i=0; i&lt;N; i++)  &#13;&#10;        {&#13;&#10;            /* Generate input samples */&#13;&#10;            X[i].re = input7_i[j++];&#13;&#10;            X[i].im = 0;&#13;&#10;            /* Copy to reference buffer */&#13;&#10;            re1[i] = X[i].re;&#13;&#10;            im1[i] = X[i].im;        &#13;&#10;&#13;&#10;            if (j==1664)&#13;&#10;                j=0;&#13;&#10;    &#9;}&#13;&#10;    &#13;&#10;        bit_rev(X,EXP);   /* Arrange sample in bit reversal order */&#13;&#10;        fft(X,EXP,U,1);   /* Perform FFT */&#13;&#10;    &#13;&#10;        for (i=0; i&lt;N; i++) /* Verify FFT result */ &#13;&#10;        {&#13;&#10;            ltemp.re = (long)X[i].re*X[i].re;&#13;&#10;            ltemp.im = (long)X[i].im*X[i].im;        &#13;&#10;            spectrum[i] = (int)((ltemp.re+ltemp.im)&gt;&gt;13); &#13;&#10;        }&#13;&#10;    }&#13;&#10;}&#13;&#10;&#13;&#10;</TEXTAREA></p>

</form>

<p style='margin-right:.5in;margin-left:.5in'>&nbsp;</p>

<p style='margin-right:1.0in;margin-left:1.0in'>For Experiment 7B, complete the
following steps:</p>

<p class=MsoNormal style='margin-right:1.0in;mso-margin-top-alt:auto;
mso-margin-bottom-alt:auto;margin-left:1.5in;text-indent:-.25in;mso-list:l4 level1 lfo6;
tab-stops:list .5in'><![if !supportLists]>1.<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;
</span><![endif]>Create the project <span style='font-family:"Courier New"'>exp7b</span>,
and include <span style='font-family:"Courier New"'>exp7.cmd</span>, <span
style='font-family:"Courier New"'>exp7b.c</span>, <span style='font-family:
"Courier New"'>w_table.c</span>, <span style='font-family:"Courier New"'>fft.asm</span>,
and <span style='font-family:"Courier New"'>bit_rev.asm</span> from the
experimental software package.</p>

<p class=MsoNormal style='margin-right:1.0in;mso-margin-top-alt:auto;
mso-margin-bottom-alt:auto;margin-left:1.5in;text-indent:-.25in;mso-list:l4 level1 lfo6;
tab-stops:list .5in'><![if !supportLists]>2.<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;
</span><![endif]>Build and verify the FFT function, and compare your results
with Experiment 7A. Make sure that the scale flag for the FFT routine is set to
1.</p>

<p class=MsoNormal style='margin-right:1.0in;mso-margin-top-alt:auto;
mso-margin-bottom-alt:auto;margin-left:1.5in;text-indent:-.25in;mso-list:l4 level1 lfo6;
tab-stops:list .5in'><![if !supportLists]>3.<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;
</span><![endif]>Profile the FFT run-time and its memory usage. Compare these
results with those obtained in Experiment 7A.</p>

<p>&nbsp;</p>

<p><a href="#top"><span style='font-size:7.5pt'>Back to Top</span></a> 

<input type=button value="go back" onclick="history.go(-1)">

</p>


<div class=MsoNormal align=center style='text-align:center'>

<hr size=3 width="100%" align=center>

</div>


<p style='margin-right:1.0in;margin-left:1.0in'><span style='font-size:13.5pt;
color:blue'>Experiment 7C - Radix-2 Complex FFT and IFFT</span></p>

<p style='margin-right:1.0in;margin-left:1.0in'>Inverse FFT (IFFT) is very
similar to the FFT computation. The DSP implementation of IFFT can use the FFT
routine from the previous experiment. In this experiment, we will show you how
to modify the FFT routine and data so the FFT routine can be used for the IFFT.</p>

<p style='margin-right:1.0in;margin-left:1.0in'>First, in order to use FFT
routine for the IFFT function, the sign of the imaginary portion of the sample
must be reversed. This is done by the experiment control function <a
href="exp7/exp7c.c"><span style='font-family:"Courier New"'>exp7c.c</span></a>,
see Table E7-10. To compare the experiment result, two temporary buffers <span
style='font-family:"Courier New"'>re1[]</span> and <span style='font-family:
"Courier New"'>re2[]</span> are used to store the input and out output samples,
respectively.</p>

<p align=center style='margin-right:.5in;margin-left:.5in;text-align:center'>Table

⌨️ 快捷键说明

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