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