home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 05 / co_dsp.asc < prev    next >
Text File  |  1991-03-15  |  21KB  |  529 lines

  1. _ADDING THE POWER OF DSP TO YOUR APPLICATIONS_
  2. by Jim Bittman
  3.  
  4. [LISTING ONE]
  5. /*-------------------- DDJ.C-----------------------------------------
  6. |  PC-Resident program for FFT and for controlling DSP co-processor
  7. |  The Makefile for this program is:
  8. |   .c.obj: 
  9. |         cl /AL -c -DANSI $<
  10. |   ddj.exe: ddj.obj dspif.obj dspif.h four1.obj realft.obj
  11. |         cl /AL ddj.obj dspif.obj four1.obj realft.obj \
  12. |             -link dsputill.lib hqmcil.lib
  13. |  This program assumes the DspHq environment and requires additional
  14. |  support files (menu definition and function specification files)
  15. |  not listed in the Makefile. However, it should not be difficult to
  16. |  excerpt the relevant portions of this code for standalone execution.
  17. +------------------------------------------------------------------*/
  18.  
  19. #include <stdio.h>              /* include for NULL define         */
  20. #include <math.h>               /* include for math functions      */
  21. #include "hq_ci_.h"             /* include for dsphq interface     */
  22. #include "nr.h"                 /* include nr function prototypes  */
  23. #include "nrutil.h"             /* include nr utility prototypes   */
  24. #include "dsputil.h"            /* include CAC prototypes          */
  25. #include "dspif.h"              /* dsp interface function header   */
  26.  
  27. /*---------- define the menu parameter types ----------------------*/
  28. typedef unsigned long parm1_type;       /* Buffer 1                */
  29. typedef unsigned long parm2_type;       /* Buffer 3                */
  30. typedef menu_float    parm3_type;       /* Cosine Amplitude        */
  31. typedef menu_float    parm4_type;       /* Cosine DC-offset        */
  32. typedef menu_float    parm5_type;       /* Cosine Frequency        */
  33. typedef menu_float    parm6_type;       /* Cosine Sammple Rate     */
  34. /*------------ constant definitions -------------------------------*/
  35. #define SQR(a) ((a)*(a))
  36. #define PI               (float) 3.141592654
  37. #define BAD_FUNC_NUM     (int) -1       /* user error code */
  38. /*----- Function Constants For Dsp32 'C' & Assembly Code ------*/
  39. #define DSP32_X     1      /* converts IEEE ==> DSP numbers */
  40. #define IEEE32_X    2      /* converts DSP  ==> IEEE numbers */
  41. /*----- Function Constants For Dsp32 'C' Code ----------------*/
  42. #define GENCOS_C    3      /* generate test cosine */
  43. #define REALFT_C    4      /* performs realft, from numerical recipes */
  44. #define IREALFT_C   5      /* performs inv_realft, from numerical recipes */
  45. #define LOGMAG_C    6      /* calculates log-magnitude */
  46. #define RFFTA_C     7      /* calculates real fft using app-lib */
  47. /*----- Function Constants For Dsp32 Assembly Code ------------*/
  48. #define RFFT_S      3      /* performs rfft, from AT&T application library */
  49. #define MAG_S       4      /* calculates magnitude-squared */
  50. #define LOG_S       5      /* calculates log */
  51. /*----- Function Prototypes ----------------------------------*/
  52. int     ilog2      (unsigned int);
  53. void    log_mag    (float far * i1, float far * o1, long bs);
  54. void    scale_data (float far *output1, float scale_val, long np);
  55. void    synth_cos  (float far *data1, long np, float a, float d, float f, 
  56.                                                                      float s);
  57. main(int argc, char *argv[])
  58. {  long                 indx;           /* used for loop index */
  59.    int                  func_num;       /* for function number from dsphq */
  60.    long                 np;             /* for block size from dsphq */
  61.    float far *          input1;         /* array address */
  62.    float far *          output1;        /* array address */
  63.    long                 bs;             /* address of DSP blocksize var */
  64.    long                 flag;           /* address of DSP funcnum flag */
  65.    parm1_type           b1;             /* DSP Buffer #1 */
  66.    parm2_type           b2;             /* DSP Buffer #2 */
  67.    parm3_type           amp;            /* cosine amplitude */
  68.    parm4_type           dco;            /* cosine DC offset */
  69.    parm5_type           freq;           /* cosine frequency */
  70.    parm6_type           samprate;       /* cosine sample rate */
  71.    init_intfc(argc, argv);              /* init dsphq interface */
  72.    func_num = get_func_num();           /* get the function number */
  73.    np = get_block_size();               /* get the block size */
  74.    /* get menu parameters */
  75.    b1   = get_parm(1);                  /* DSP Buffer #1 */
  76.    b2   = get_parm(2);                  /* DSP Buffer #2 */
  77.    amp  = get_parm(3);                  /* cosine amplitude */
  78.    dco  = get_parm(4);                  /* cosine DC offset */
  79.    freq = get_parm(5);                  /* cosine frequency */
  80.    samprate = get_parm(6);              /* cosine sample rate */
  81.    /* get array addresses */
  82.    input1  = get_data_in_ptr(1);        /* base address of input #1 */
  83.    output1 = get_data_out_ptr(1);       /* base address of output #1 */
  84.    /* perform selected function */
  85.    switch (func_num)
  86.    {
  87.       case 1 :       /*--- Synthesize Cosine Using PC ---------------------*/
  88.          synth_cos(output1, np, amp, dco, freq, samprate);
  89.          break;
  90.       case 2 :      /*---- Numerical Recipes Forward Real FFT Using PC ----*/
  91.          output1--;                             /* NR funcs index at 1     */
  92.          realft(output1, np>>1, 1);             /* forward real fft        */
  93.          break;
  94.       case 3 :       /*---- Numerical Recipes Inverse Real FFT Using PC ----*/
  95.          output1--;                             /* NR funcs index at 1      */
  96.          realft(output1, np>>1, -1);            /* inverse real fft         */
  97.          output1++;                             /* reallign address         */
  98.          scale_data(output1,1.0/(np >> 1),np);  /* restore original ampl.   */
  99.          break;
  100.       case 4 :     /*------ Calculate LOG(10)-[MAGNITUDE] using PC --------*/
  101.          if (input1)
  102.             log_mag(input1, output1, np);       /* take logmag of input     */
  103.          else
  104.             log_mag(output1, output1, np);      /* perform logmag in-place  */
  105.          break;
  106.       case 5 :     /*--------- Synthesize Cosine Using DSP-32C -------------*/
  107.          init_dsp("ddj_32c.32c",&flag,&bs,np);  /* download dsp code & init */
  108.          dsp_dl_fp(get_addr("amp"),amp);        /* download floats          */
  109.          dsp_dl_fp(get_addr("dco"),dco);
  110.          dsp_dl_fp(get_addr("freq"),freq);
  111.          dsp_dl_fp(get_addr("samprate"),samprate);
  112.          set_dspbuf("o1", b1);                  /* set dsp buffer address   */
  113.          dsp_dl_int(flag,GENCOS_C);             /* invoke function on dsp   */
  114.          wait4dsp(flag);                        /* wait for dsp to finish   */
  115.          ul_float(output1,np,flag,b1);          /* upload results           */
  116.          break;
  117.       case 6 :  /*---- Numerical Recipes Forward Real FFT Using DSP-32C ----*/
  118.          init_dsp("ddj_32c.32c",&flag,&bs,np);  /* download dsp code & init */
  119.          set_dspbuf("o1", b1);                  /* set dsp buffer address   */
  120.          dl_float(input1,np,flag,b1);           /* download float array     */
  121.          dsp_dl_int(flag,REALFT_C);             /* execute "realft" on dsp  */
  122.          wait4dsp(flag);                        /* wait for dsp to finish   */
  123.          ul_float(output1,np,flag,b1);          /* upload results           */
  124.          break;
  125.       case 7 : /*---- Numerical Recipes Inverse Real FFT Using DSP-32C -----*/
  126.          init_dsp("ddj_32c.32c",&flag,&bs,np);  /* download dsp code & init */
  127.          dl_float(input1,np,flag,b1);           /* download float array     */
  128.          set_dspbuf("o1", b1);                  /* set dsp buffer address   */
  129.          dsp_dl_int(flag,IREALFT_C);         /* execute "inv_realft" on dsp */
  130.          wait4dsp(flag);                        /* wait for dsp to finish   */
  131.          ul_float(output1,np,flag,b1);          /* upload results           */
  132.          break;
  133.       case 8 :      /*----- Calculate LOG(10)-[MAGNITUDE] using DSP-32C ----*/
  134.          init_dsp("ddj_32c.32c",&flag,&bs,np);  /* download dsp code & init */
  135.          dl_float(input1,np,flag,b1);           /* download float array     */
  136.          set_dspbuf("i1", b1);                  /* set dsp buffer address   */
  137.          set_dspbuf("o1", b2);                  /* set dsp buffer address   */
  138.          dsp_dl_int(flag,LOGMAG_C);          /* execute "inv_realft" on dsp */
  139.          wait4dsp(flag);                        /* wait for dsp to finish   */
  140.          ul_float(output1,np,flag,b2);          /* upload results           */
  141.          break;
  142.       case 9 :     /*------- Forward Real FFT Using DSP-32C App-Lib --------*/
  143.          init_dsp("ddj_32s.32c",&flag,&bs,np);  /* download dsp code & init */
  144.          dl_float(input1,np,flag,b1);           /* download float array     */
  145.          set_dspbuf("o1", b1);                  /* set dsp buffer address   */
  146.          dsp_dl_int(get_addr("stages"),ilog2(np));
  147.                                                 /* download int             */
  148.          dsp_dl_int(flag,RFFT_S);               /* execute "rfft" on dsp    */
  149.          wait4dsp(flag);                        /* wait for dsp to finish   */
  150.          ul_float(output1,np,flag,b1);          /* upload results           */
  151.          break;
  152.       case 10:     /*-------- Download Data To DSP-32C ---------------------*/
  153.          init_dsp("ddj_32s.32c",&flag,&bs,np);  /* download dsp code & init */
  154.          dl_float(input1,np,flag,b1);       /* download data from pc to dsp */
  155.          break;
  156.       case 11:    /*--------- Upload Data From DSP-32C ---------------------*/
  157.          init_dsp("ddj_32s.32c",&flag,&bs,np);  /* download dsp code & init */
  158.          ul_float(output1,np,flag,b1);          /* upload results           */
  159.          break;
  160.       default : set_err_return(BAD_FUNC_NUM); break;
  161.    }
  162. }
  163. /*--- This function returns the integer part of the log base 2 of x. ---*/
  164. int ilog2(unsigned int x)
  165. {
  166.    return( x >> 1 ? 1 + ilog2(x >> 1) : 0);
  167. }
  168. /*--- This function scales np elements of data1[] by scale_val. ---*/
  169. void scale_data(float far * data1, float scale_val, long np)
  170. {  long i;
  171.    for (i = 0; i < np; i++)   {
  172.       data1[i] *= scale_val;
  173.    }
  174. }
  175. /*--- Function generates cosine data: data[i] = A cos((2 pi f/s) i) + d ---*/
  176. void synth_cos(float far * data1, long np, float a, float d, float f, float s)
  177. {  long i;
  178.    float theta, angle_step;
  179.    angle_step = 2.0 * PI * f / s;
  180.    theta = 0.0;
  181.    for (i = 0; i < np; i++) {
  182.       data1[i] = (a * cos(theta)) + d;
  183.       theta += angle_step;
  184.    }
  185. }
  186. /*--- log_mag ---*/
  187. void log_mag(float far * i1, float far * o1, long bs)
  188. {  long i;
  189.    long n;
  190.    n = bs >> 1;
  191.    o1[0] = log10(SQR(i1[0]));
  192.    for (i = 1; i < n; i++)   {
  193.       o1[i] = log10(SQR(i1[2*i]) + SQR(i1[2*i+1]));
  194.    }
  195.    for (i = n; i < bs; i++)   {
  196.       o1[i] = 0.0;
  197.    }
  198. }
  199.  
  200.  
  201. [LISTING TWO]
  202.  
  203. /*-----------------DDJ_MP87.C-------------------------------------------
  204. |  MathPak 87 FFT Function Group Execution Source File 
  205. |  The makefile is: ddj_mp87.exe: ddj_mp87.c
  206. |                      cl /AL ddj_mp87.c -link hqmcil.lib mpak87.lib
  207. +----------------------------------------------------------------------*/
  208. #include <hq_ci_.h>                     /* include function prototypes */
  209. #include <mpak87.h>                     /* include math pak header */
  210. #define BAD_BLOCK_SIZE        -1        /* user defined error codes */
  211. #define BAD_FUNC_NUM          -2
  212.  
  213. int fft_stages(long fft_size); /*function prototype*/
  214.  
  215. void main(int argc, char *argv[])
  216. {
  217.    int         m;       /* number of fft stages */
  218.    far_array_of_double o1;  /* data pointer */
  219.    init_intfc(argc, argv); /* MUST do this before other interface functions */
  220.    o1 = get_data_out_ptr(1);   /* get address of data */
  221.    if ((m = fft_stages(get_block_size())) == 0)
  222.       set_err_return(BAD_BLOCK_SIZE);  /* won't happen if .fnc file correct */
  223.    else
  224.    switch(get_func_num())   {
  225.       case 1: rvfft(o1, m); break;    /* real fft from MathPak library     */
  226.       case 2: irvfft(o1, m); break;   /* inverse real fft from MathPak     */
  227.       default:                           
  228.         set_err_return(BAD_FUNC_NUM); /* won't happen if .fnc file correct */
  229.       break;
  230.    }
  231. /* return the log(base 2) of the input, or 0 if input is not a power of 2 */
  232. int fft_stages(long fft_size)
  233. {  int rtn;
  234.    int sw_fft;
  235.    sw_fft = fft_size;
  236.    switch(sw_fft)   {
  237.       case    8 : rtn =  3; break;
  238.       case   16 : rtn =  4; break;
  239.       case   32 : rtn =  5; break;
  240.       case   64 : rtn =  6; break;
  241.       case  128 : rtn =  7; break;
  242.       case  256 : rtn =  8; break;
  243.       case  512 : rtn =  9; break;
  244.       case 1024 : rtn = 10; break;
  245.       case 2048 : rtn = 11; break;
  246.       case 4096 : rtn = 12; break;
  247.       case 8192 : rtn = 13; break;
  248.       default   : rtn =  0; break;
  249.    }
  250.    return(rtn);
  251. }
  252.  
  253.  
  254.  
  255. [LISTING THREE]
  256.  
  257. /*--------------------DDJ_32C.C--------------------------------------
  258. | This file is will run on the DSP add-in board after compilation
  259. | by the AT&T C compiler d3cc. The makefile is:
  260. |  .c.o: 
  261. |       d3cc -c $<
  262. |  .s.o: 
  263. |       d3as -W -Q $<
  264. |   ddj_32c.32c: ddj_32c.o startup.o memory.map four1.o realft.o
  265. |       d3cc -lm -lap -o ddj_32c.32c ddj_32c.o four1.o realft.o \
  266. |        -s startup.o -m memory.map
  267. +--------------------------------------------------------------------*/
  268. #include <stdio.h>
  269. #include <math.h>
  270. #include <nr.h>
  271.  
  272. #define PI 3.1415926
  273. #define SQR(a) ((a)*(a))
  274.  
  275. asm(".global i1, i2, o1, o2");
  276. asm(".global funcnum, bs");
  277. asm(".global amp, dco, freq, samprate");
  278.  
  279. short funcnum;
  280. short bs;
  281. float *i1, *i2, *o1, *o2;
  282. float amp, dco, freq, samprate;
  283. /*------------------------------------------------------------*/
  284. short fft_stages(fft_size)   
  285. short fft_size;
  286. {
  287.    short rtn;
  288.    switch(fft_size)
  289.    {
  290.       case   32 :   rtn =  5;    break;
  291.       case   64 :   rtn =  6;    break;
  292.       case  128 :   rtn =  7;    break;
  293.       case  256 :   rtn =  8;    break;
  294.       case  512 :   rtn =  9;    break;
  295.       case 1024 :   rtn = 10;    break;
  296.       case 2048 :   rtn = 11;    break;
  297.       case 4096 :   rtn = 12;    break;
  298.       case 8192 :   rtn = 13;    break;
  299.       default   :   rtn =  0;    break;
  300.    }
  301.    return(rtn);
  302. }
  303. /*------------------------------------------------------------*/
  304. main()
  305. {    register float scal;
  306.      short n;
  307.      float *data1, *data2, temp;
  308.      register short i,j;
  309.  
  310.      while (1) {
  311.        funcnum=0;
  312.        while (!(funcnum))
  313.        ;       /* Wait for PC to Download Function Number */
  314.        n = bs >> 1;
  315.        switch(funcnum) {
  316.           case 1: /*--------- Convert to DSP Format ------------*/
  317.                     dsp32(bs,o1); /*IEEE-->DSP */
  318.                     break;
  319.           case 2: /*--------- Convert to IEEE format -----------*/
  320.                     ieee32(bs,o1); /*DSP-->IEEE*/
  321.                     break;
  322.           case 3: /*--------- Synthesize Cosine ----------------*/
  323.                     scal = 2.0 * PI * freq / samprate;
  324.                     j = 0;
  325.                     data1 = o1;
  326.                     for (i=bs; i-- > 0; j++) {
  327.                       *data1++ = (amp * cos(scal * j)) + dco;
  328.                     }
  329.                     break;
  330.           case 4: /*------- Forward FFT ------------------------*/
  331.                     data1 = o1;
  332.                     data1--;
  333.                     realft(data1,n,1); /*from numerical recipes*/
  334.                     break;
  335.           case 5: /*------- Inverse FFT ------------------------*/
  336.                     data1 = o1;
  337.                     data1--;
  338.                     realft(data1,n,-1); /*from numerical recipes*/
  339.                     /* scale by 1/n to retain original amplitude*/
  340.                     data1 = o1;
  341.                     scal = 1.0 / n;
  342.                     for (i=bs; i-- > 0; data1++) {
  343.                       *data1 = *data1 * scal;
  344.                     }
  345.                     break;
  346.           case 6: /*----- Calc LOG-MAGNITUDE (data output from NR-realft)--*/
  347.                     o1[0] = log10(SQR(i1[0]));
  348.                     temp  = log10(SQR(i1[1]));
  349.                     for (i=1;i<n;i++) {
  350.                       o1[i]=log10(SQR(i1[2*i])+SQR(i1[2*i+1]));
  351.                     }
  352.                     o1[n] = temp;
  353.                     for (i=n+1; i<bs; i++) {
  354.                       o1[i] = 0.0;
  355.                     }
  356.                     break;
  357.           case 7: /*------ Forward FFT ----------------------------------*/
  358.                     data1 = o1;
  359.                     rffta(bs,fft_stages(bs),data1); /*uses AT&T app lib*/
  360.                     break;
  361.           default : break;
  362.        }
  363.      }
  364. }
  365.  
  366.  
  367. [LISTING FOUR]
  368.  
  369. /*------ file DDJ_32S.S-----------------------------------------------
  370. | Assembly language version of FFT test. The makefile is as follows:
  371. |   ddj_32s.32c: ddj_32s.s
  372. |        d3make -o ddj_32s.32c -M6 -Q -W ddj_32s.s
  373. +---------------------------------------------------------------------*/
  374. #include <dspregs.h>
  375. /*--------------------------------------------------------------------*/
  376. .global i1,o1,o2
  377. .global funcnum, bs, stages
  378. .global endofcode
  379. /*--------------------------------------- initialization -------------*/
  380.        r5 = 0x0003
  381.        pcw = r5
  382.        ioc  = 0x30CC0
  383. /*--------------------------------------- wait until funcnum != 0 ----*/
  384. begin:
  385.        r5 = *funcnum
  386.        nop
  387.        if (eq) goto begin
  388.        nop
  389. /*--------------- switch on funcnum, which is set to function number --*/
  390. /* func 1:  IEEE-->DSP */
  391.      r5 = r5 - 1
  392.      if (eq) goto do_dsp32
  393. /* func 2: DSP-->IEEE */
  394.      r5 = r5 - 1
  395.      if (eq) goto do_ieee32
  396. /* func 3: invoke rffta, from AT&T app library */
  397.      r5 = r5 - 1
  398.      if (eq) goto rffta
  399. /* func 4: calc magnitude squared */
  400.      r5 = r5 - 1
  401.      if (eq) goto do_mag
  402.      nop
  403. /* func 5: calc log */
  404.      r5 = r5 - 1
  405.      if (eq) goto do_log10
  406.      nop
  407. /* illegal function number */
  408.      goto finished
  409.      nop
  410. /*---------------------------------call to _rffta -----------------*/
  411. rffta:
  412.        r2e = *o1
  413.        r1  = *bs
  414.        r3  = *stages
  415.        *fft_b = r2e
  416.        *fft_n = r1e
  417.        *fft_m = r3e
  418.        call _rffta (r14)
  419.        nop
  420. fft_lv: int24    localV
  421. fft_n:  int24    0
  422. fft_m:  int24    0
  423. fft_b:  int24    0
  424. .align 4
  425.        goto finished
  426.        nop
  427. /*---------------------------------calc magnitude------------------*/
  428. do_mag:
  429.        r8   = *bs
  430.        r10e = *i1
  431.        r8   = r8 - 2
  432.        r11e = *o1
  433.        nop
  434.        a0 = *r10++                 /* DC value */
  435.        nop
  436.        a2 = *r10++                 /* Nyquist  */
  437.        *r11++ = a0 = a0*a0         /* save DC mag */
  438. magloop:
  439.        a0 = *r10++
  440.        nop
  441.        a1 = *r10++
  442.        a0 = a0*a0
  443.        nop
  444.        a1 = a1*a1
  445.        nop
  446.        nop
  447.        *r11++ = a1 = a0 + a1
  448.        if (r8-->=0) goto magloop
  449.        nop
  450.        *r11++ = a0 = a2*a2         /* save Nyquist mag */
  451.        goto finished
  452.        nop
  453. /*---------------------------------calc log10------------------*/
  454. do_log10:
  455.        r12e = *i1
  456.        r11e = *o1
  457.        r13  = *bs
  458.        r10e = in
  459.        r9e  = out
  460.        r13  = r13 - 2
  461. logloop:
  462.        *r10 = a3 = *r12++
  463.        call _log10 (r14)
  464.        nop
  465.        int24     localV
  466.        int24     in, out
  467. .align 4
  468.        *r11++ = a3 = *r9
  469.        if (r13-->=0) goto logloop
  470.        nop
  471.        goto finished
  472.        nop
  473. /*--------------------------------------call _ieee32 converter-----*/
  474. do_ieee32:
  475.        r1e = *o1
  476.        r2 = *bs
  477.        *o1_ieee32 = r1e
  478.        *bs_ieee32 = r2e
  479.        call _ieee32 (r14)
  480.        nop
  481.             int24       localV
  482. bs_ieee32:  int24       0
  483. o1_ieee32:  int24       0
  484. .align 4
  485.        goto finished
  486.        nop
  487. /*--------------------------------------call _dsp32 converter-----*/
  488. do_dsp32:
  489.        r1e = *o1
  490.        r2 = *bs
  491.        *o1_dsp32 = r1e
  492.        *bs_dsp32 = r2e
  493.        call _dsp32 (r14)
  494.        nop
  495. bs_dsp32:  int24       0
  496. o1_dsp32:  int24       0
  497. .align 4
  498.        goto finished
  499.        nop
  500. /*-------------------------------finished, set funcnum=0 -----------*/
  501. finished: 
  502.        r1=0
  503.        goto begin
  504.        *funcnum=r1
  505. bs:         int 256
  506. stages:     int 8
  507. funcnum:    int 0
  508. .align 4
  509. i1: int24 0x2000
  510. o1: int24 0x2000
  511. o2: int24 0x3000
  512.  
  513. .align 4
  514. localV:   2*float   0.0
  515. in:       float     0.0
  516. out:      float     0.0
  517. max:      float     0.0
  518. scalefac: float     0.0
  519. #include <_rffta.asm>
  520. #include <_log10.asm>
  521. #include <_ieee32.asm>
  522. #include <_dsp32.asm>
  523. /*------------------------------------- mark end of code------------*/
  524. endofcode: int 0xDEAD, 0xC0DE
  525.  
  526.  
  527.  
  528.