File: firdecim_crcf_example.c

package info (click to toggle)
liquid-dsp 1.7.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,216 kB
  • sloc: ansic: 115,859; sh: 3,513; makefile: 1,350; python: 274; asm: 11
file content (147 lines) | stat: -rw-r--r-- 5,254 bytes parent folder | download | duplicates (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
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//
// firdecim_crcf_example.c
//
// This example demonstrates the interface to the firdecim (finite
// impulse response decimator) family of objects.
//
// SEE ALSO: firinterp_crcf_example.c
//

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <getopt.h>

#include "liquid.h"

#define OUTPUT_FILENAME "firdecim_crcf_example.m"

// print usage/help message
void usage()
{
    printf("firdecim_crcf_example:\n");
    printf("  -h         : print usage/help\n");
    printf("  -M <decim> : decimation factor, M > 1           default: 2\n");
    printf("  -m <delay> : filter delay (symbols), m > 0,     default: 2\n");
    printf("  -s <atten> : filter stop-band attenuation [dB], default: 60\n");
    printf("  -n <num>   : number of samples (after decim),   default: 8\n");
}


int main(int argc, char*argv[]) {
    // options
    unsigned int M           = 6;       // decimation factor
    unsigned int m           = 8;       // filter delay
    float        As          = 60.0f;   // filter stop-band attenuation
    unsigned int num_samples = 120;     // number of samples (after decim)

    int dopt;
    while ((dopt = getopt(argc,argv,"hM:m:s:n:")) != EOF) {
        switch (dopt) {
        case 'h': usage();                    return 0;
        case 'M': M           = atoi(optarg); break;
        case 'm': m           = atoi(optarg); break;
        case 's': As          = atof(optarg); break;
        case 'n': num_samples = atoi(optarg); break;
        default:
            usage();
            return 1;
        }
    }

    // validate options
    if (M < 2) {
        fprintf(stderr,"error: %s, decim factor must be greater than 1\n", argv[0]);
        return 1;
    } else if (m < 1) {
        fprintf(stderr,"error: %s, filter delay must be greater than 0\n", argv[0]);
        return 1;
    } else if (As <= 0.0) {
        fprintf(stderr,"error: %s, stop-band attenuation must be greater than zero\n", argv[0]);
        return 1;
    } else if (num_samples < 1) {
        fprintf(stderr,"error: %s, must have at least one sample\n", argv[0]);
        return 1;
    }

    // data arrays
    float complex x[M*num_samples]; // number of samples before decimation
    float complex y[  num_samples]; // number of samples after decimation

    // initialize input array
    unsigned int i;
    unsigned int w_len = (unsigned int)(0.9*M*num_samples);
    float f0 = 0.017f;
    float f1 = 0.021f;
    for (i=0; i<M*num_samples; i++) {
        x[i]  = 0.6f*cexpf(_Complex_I*2*M_PI*f0*i);
        x[i] += 0.4f*cexpf(_Complex_I*2*M_PI*f1*i);
        x[i] *= (i < w_len) ? liquid_hamming(i,w_len) : 0;
    }

    // create decimator object and set scale
    firdecim_crcf decim = firdecim_crcf_create_kaiser(M, m, As);
    firdecim_crcf_set_scale(decim, 1.0f/(float)M);

    // execute decimator
    firdecim_crcf_execute_block(decim, x, num_samples, y);

    // destroy decimator object
    firdecim_crcf_destroy(decim);

    // 
    // export results to file
    //
    FILE*fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n");
    fprintf(fid,"M  = %u;\n", M);
    fprintf(fid,"m  = %u;\n", m);
    fprintf(fid,"num_samples=%u;\n", num_samples);

    // inputs
    for (i=0; i<M*num_samples; i++)
        fprintf(fid,"x(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i]));

    // outputs
    for (i=0; i<num_samples; i++)
        fprintf(fid,"y(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i]));

    // plot results
    fprintf(fid,"figure('position',[100 100 600 800]);\n");
    fprintf(fid,"tx = [0:(M*num_samples-1)];\n");
    fprintf(fid,"ty = [0:(  num_samples-1)]*M - M*m;\n");
    fprintf(fid,"nfft=3*2^nextpow2(M*num_samples);\n");
    fprintf(fid,"fx = [0:(nfft-1)]/nfft-0.5;\n");
    fprintf(fid,"fy = fx/M;\n");
    fprintf(fid,"X=20*log10(abs(fftshift(fft(  x,nfft))));\n");
    fprintf(fid,"Y=20*log10(abs(fftshift(fft(M*y,nfft))));\n");
    fprintf(fid,"subplot(3,1,1);\n");
    fprintf(fid,"  plot(tx,real(x),'-',ty,real(y),'s');\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  axis([-M*m M*num_samples -1.2 1.2]);\n");
    fprintf(fid,"  xlabel('Input sample index');\n");
    fprintf(fid,"  ylabel('Real');\n");
    fprintf(fid,"  legend('original','decimated','location','northeast');");
    fprintf(fid,"subplot(3,1,2);\n");
    fprintf(fid,"  plot(tx,imag(x),'-',ty,imag(y),'s');\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  axis([-M*m M*num_samples -1.2 1.2]);\n");
    fprintf(fid,"  xlabel('Input sample index');\n");
    fprintf(fid,"  ylabel('Imag');\n");
    fprintf(fid,"  legend('original','decimated','location','northeast');");
    fprintf(fid,"subplot(3,1,3);\n");
    fprintf(fid,"  plot(fx,X,'Color',[0.5 0.5 0.5],fy,Y,'LineWidth',2);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  axis([-0.5 0.5 -40 60]);\n");
    fprintf(fid,"  xlabel('normalized frequency');\n");
    fprintf(fid,"  ylabel('PSD [dB]');\n");
    fprintf(fid,"  legend('original/real','transformed/decimated','location','northeast');");

    fclose(fid);
    printf("results written to %s\n", OUTPUT_FILENAME);

    printf("done.\n");
    return 0;
}