1 //
2 // modem_arb_example.c
3 //
4 // This example demonstrates the functionality of the arbitrary
5 // modem, a digital modulator/demodulator object with signal
6 // constellation points chosen arbitrarily.  A simple bit-error
7 // rate simulation is then run to test the performance of the
8 // modem.  The results are written to a file.
9 // SEE ALSO: modem_example.c
10 //
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <math.h>
16 #include <getopt.h>
17 
18 #include "liquid.h"
19 
20 #define OUTPUT_FILENAME "modem_arb_example.m"
21 
22 // print usage/help message
usage()23 void usage()
24 {
25     printf("modem_arb_example [options]\n");
26     printf("  u/h   : print usage\n");
27     printf("  p     : modulation depth (default 4 bits/symbol)\n");
28 }
29 
main(int argc,char * argv[])30 int main(int argc, char*argv[])
31 {
32     // options
33     unsigned int bps=6;         // bits per symbol
34     unsigned int n=1024;        // number of data points to evaluate
35 
36     int dopt;
37     while ((dopt = getopt(argc,argv,"uhp:")) != EOF) {
38         switch (dopt) {
39         case 'u':
40         case 'h': usage(); return 0;
41         case 'p': bps = atoi(optarg); break;
42         default:
43             exit(1);
44         }
45     }
46 
47     // validate input
48     if (bps == 0) {
49         fprintf(stderr,"error: %s, bits/symbol must be greater than zero\n", argv[0]);
50         exit(1);
51     }
52 
53     // derived values
54     unsigned int i;
55     unsigned int M = 1<<bps;    // constellation size
56 
57     // initialize constellation table
58     float complex constellation[M];
59     // initialize constellation (spiral)
60     for (i=0; i<M; i++) {
61         float r   = (float)i / logf((float)M) + 4.0f;
62         float phi = (float)i / logf((float)M);
63         constellation[i] = r * cexpf(_Complex_I*phi);
64     }
65 
66     // create mod/demod objects
67     modem mod   = modem_create_arbitrary(constellation, M);
68     modem demod = modem_create_arbitrary(constellation, M);
69 
70     modem_print(mod);
71 
72     // run simulation
73     float complex x[n];
74     unsigned int num_errors = 0;
75 
76     // run simple BER simulation
77     num_errors = 0;
78     unsigned int sym_in;
79     unsigned int sym_out;
80     for (i=0; i<n; i++) {
81         // generate and modulate random symbol
82         sym_in = modem_gen_rand_sym(mod);
83         modem_modulate(mod, sym_in, &x[i]);
84 
85         // add noise
86         x[i] += 0.05 * randnf() * cexpf(_Complex_I*M_PI*randf());
87 
88         // demodulate
89         modem_demodulate(demod, x[i], &sym_out);
90 
91         // accumulate errors
92         num_errors += count_bit_errors(sym_in,sym_out);
93     }
94     printf("num bit errors: %4u / %4u\n", num_errors, bps*n);
95 
96     // destroy modem objects
97     modem_destroy(mod);
98     modem_destroy(demod);
99 
100     //
101     // export output file
102     //
103     FILE * fid = fopen(OUTPUT_FILENAME,"w");
104     fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
105     fprintf(fid,"clear all;\n");
106     fprintf(fid,"close all;\n");
107     fprintf(fid,"bps = %u;\n", bps);
108     fprintf(fid,"M = %u;\n", M);
109 
110     for (i=0; i<n; i++) {
111         fprintf(fid,"x(%3u) = %12.4e + j*%12.4e;\n", i+1,
112                                                      crealf(x[i]),
113                                                      cimagf(x[i]));
114     }
115 
116     // plot results
117     fprintf(fid,"figure;\n");
118     fprintf(fid,"plot(x,'x','MarkerSize',1);\n");
119     fprintf(fid,"xlabel('in-phase');\n");
120     fprintf(fid,"ylabel('quadrature phase');\n");
121     fprintf(fid,"title(['Arbitrary ' num2str(M) '-QAM']);\n");
122     fprintf(fid,"axis([-1 1 -1 1]*1.9);\n");
123     fprintf(fid,"axis square;\n");
124     fprintf(fid,"grid on;\n");
125     fclose(fid);
126 
127     printf("results written to '%s'\n", OUTPUT_FILENAME);
128     printf("done.\n");
129 
130     return 0;
131 }
132