File: gmskmodem_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 (143 lines) | stat: -rw-r--r-- 4,729 bytes parent folder | download | duplicates (5)
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
// 
// gmskmodem_example.c
//

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

#define OUTPUT_FILENAME "gmskmodem_example.m"

// print usage/help message
void usage()
{
    printf("gmskmodem_example -- Gaussian minimum-shift keying modem example\n");
    printf("options (default values in <>):\n");
    printf("  u/h   : print usage/help\n");
    printf("  k     : samples/symbol, default: 4\n");
    printf("  m     : filter delay [symbols], default: 3\n");
    printf("  n     : number of data symbols, default: 200\n");
    printf("  b     : bandwidth-time product, 0 <= b <= 1, default: 0.3\n");
    printf("  s     : SNR [dB], default: 30\n");
}

int main(int argc, char*argv[]) {
    // options
    unsigned int k=4;                   // filter samples/symbol
    unsigned int m=3;                   // filter delay (symbols)
    float BT=0.3f;                      // bandwidth-time product
    unsigned int num_data_symbols=200;  // number of data symbols
    float SNRdB = 30.0f;                // signal-to-noise ratio [dB]
    float phi = 0.0f;                   // carrier phase offset
    float dphi = 0.0f;                  // carrier frequency offset

    int dopt;
    while ((dopt = getopt(argc,argv,"uhk:m:n:b:s:")) != EOF) {
        switch (dopt) {
        case 'u':
        case 'h': usage();              return 0;
        case 'k': k = atoi(optarg); break;
        case 'm': m = atoi(optarg); break;
        case 'n': num_data_symbols = atoi(optarg); break;
        case 'b': BT = atof(optarg); break;
        case 's': SNRdB = atof(optarg); break;
        default:
            exit(1);
        }
    }

    // validate input
    if (BT <= 0.0f || BT >= 1.0f) {
        fprintf(stderr,"error: %s, bandwidth-time product must be in (0,1)\n", argv[0]);
        exit(1);
    }

    // derived values
    unsigned int num_symbols = num_data_symbols + 2*m;
    unsigned int num_samples = k*num_symbols;
    float nstd = powf(10.0f,-SNRdB/20.0f);  // noise standard deviation

    // create modulator
    gmskmod mod   = gmskmod_create(k, m, BT);
    gmskmod_print(mod);

    // create demodulator
    gmskdem demod = gmskdem_create(k, m, BT);
    gmskdem_set_eq_bw(demod, 0.01f);
    gmskdem_print(demod);

    unsigned int i;
    unsigned int s[num_symbols];
    float complex x[num_samples];
    float complex y[num_samples];
    unsigned int sym_out[num_symbols];

    // generate random data sequence
    for (i=0; i<num_symbols; i++)
        s[i] = rand() % 2;

    // modulate signal
    for (i=0; i<num_symbols; i++)
        gmskmod_modulate(mod, s[i], &x[k*i]);

    // add channel impairments
    for (i=0; i<num_samples; i++) {
        y[i]  = x[i]*cexpf(_Complex_I*(phi + i*dphi));
        y[i] += nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2;
    }

    // demodulate signal
    for (i=0; i<num_symbols; i++)
        gmskdem_demodulate(demod, &y[k*i], &sym_out[i]);

    // destroy modem objects
    gmskmod_destroy(mod);
    gmskdem_destroy(demod);

    // print results to screen
    unsigned int delay = 2*m;
    unsigned int num_errors=0;
    for (i=delay; i<num_symbols; i++) {
        //printf("  %4u : %2u (%2u)\n", i, s[i-delay], sym_out[i]);
        num_errors += (s[i-delay] == sym_out[i]) ? 0 : 1;
    }
    printf("symbol errors : %4u / %4u\n", num_errors, num_data_symbols);

    // write results to output 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,"k = %u;\n", k);
    fprintf(fid,"m = %u;\n", m);
    fprintf(fid,"BT = %f;\n", BT);
    fprintf(fid,"num_symbols = %u;\n", num_symbols);
    fprintf(fid,"num_samples = %u;\n", num_samples);

    fprintf(fid,"x = zeros(1,num_samples);\n");
    fprintf(fid,"y = zeros(1,num_samples);\n");
    for (i=0; i<num_samples; i++) {
        fprintf(fid,"x(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i]));
        fprintf(fid,"y(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i]));
    }
    fprintf(fid,"t=[0:(num_samples-1)]/k;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(t,real(y),t,imag(y));\n");

    // artificially demodulate (generate receive filter, etc.)
    float hr[2*k*m+1];
    liquid_firdes_gmskrx(k,m,BT,0,hr);
    for (i=0; i<2*k*m+1; i++)
        fprintf(fid,"hr(%3u) = %12.8f;\n", i+1, hr[i]);
    fprintf(fid,"z = filter(hr,1,arg( ([y(2:end) 0]).*conj(y) ))/k;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(t,z,t(k:k:end),z(k:k:end),'or');\n");
    fprintf(fid,"grid on;\n");

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

    return 0;
}