1 //
2 // modem_demodulate_soft_test.c
3 //
4 // Tests soft demoulation using log-likelihood ratio
5 //
6 
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <math.h>
11 #include <time.h>
12 
13 #include "liquid.h"
14 
15 #define OUTPUT_FILENAME "modem_demodulate_soft_test.m"
16 
main()17 int main() {
18     srand(time(NULL));
19 
20     // options
21     modulation_scheme ms = LIQUID_MODEM_QAM16;  // modulation scheme
22     float complex e = 0.1f + _Complex_I*0.2f;   // error
23 
24     unsigned int i;
25 
26     // derived values
27     float sig = 0.2f;           // noise standard deviation
28 
29     // generate constellation
30     modem q = modem_create(ms);
31     unsigned int bps = modem_get_bps(q);
32     unsigned int M = 1 << bps;  // constellation size
33     float complex c[M];         // constellation
34     for (i=0; i<M; i++)
35         modem_modulate(q, i, &c[i]);
36     modem_destroy(q);
37 
38     // select input symbol and compute received symbol
39     unsigned int sym_in = rand() % M;
40     float complex r = c[sym_in] + e;
41 
42     // run soft demodulation for each bit
43     float soft_bits[bps];
44     unsigned int k;
45     for (k=0; k<bps; k++) {
46         printf("\n");
47         printf("********* bit index %u ************\n", k);
48         // reset soft bit value
49         soft_bits[k] = 0.0f;
50         float bit_0 = 0.0f;
51         float bit_1 = 0.0f;
52 
53         // compute LLR for this bit
54         for (i=0; i<M; i++) {
55             // compute distance between received point and symbol
56             float d = crealf( (r-c[i])*conjf(r-c[i]) );
57             float t = expf( -d / (2.0f*sig*sig) );
58 
59             // check if this symbol has a '0' or '1' at this bit index
60             unsigned int bit = (i >> (bps-k-1)) & 0x01;
61             //printf("%c", bit ? '1' : '0');
62 
63             if (bit) bit_1 += t;
64             else     bit_0 += t;
65 
66             printf("  symbol : ");
67             unsigned int j;
68             for (j=0; j<bps; j++)
69                 printf("%c", (i >> (bps-j-1)) & 0x01 ? '1' : '0');
70             printf(" [%c]", bit ? '1' : '0');
71             printf(" { %7.4f %7.4f}, d=%7.4f, t=%12.8f\n", crealf(c[i]), cimagf(c[i]), d, t);
72 
73         }
74 
75         soft_bits[k] = logf(bit_1) - logf(bit_0);
76         printf(" {0 : %12.8f, 1 : %12.8f}\n", bit_0, bit_1);
77     }
78 
79     // print results
80     printf("\n");
81     printf("  input symbol : ");
82     for (k=0; k<bps; k++)
83         printf("%c", (sym_in >> (bps-k-1)) & 0x01 ? '1' : '0');
84     printf(" {%12.8f, %12.8f}\n", crealf(c[sym_in]), cimagf(c[sym_in]));
85 
86     printf("  soft bits :\n");
87     for (k=0; k<bps; k++) {
88         printf("    %1u : ", (sym_in >> (bps-k-1)) & 0x01);
89         printf("%12.8f > ", soft_bits[k]);
90         int soft_bit = (soft_bits[k]*16 + 127);
91         if (soft_bit > 255) soft_bit = 255;
92         if (soft_bit <   0) soft_bit =   0;
93         printf("%5d > %1u\n", soft_bit, soft_bit & 0x80 ? 1 : 0);
94     }
95 
96     //
97     // export results to file
98     //
99     FILE * fid = fopen(OUTPUT_FILENAME,"w");
100     fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
101     fprintf(fid,"clear all;\n");
102     fprintf(fid,"close all;\n\n");
103     fprintf(fid,"m = %u;\n", bps);
104     fprintf(fid,"M = %u;\n", 1<<bps);
105     fprintf(fid,"c = zeros(1,M);\n");
106     fprintf(fid,"i_str = cell(1,M);\n");
107 
108     for (i=0; i<M; i++) {
109         // write symbol to output file
110         fprintf(fid,"c(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(c[i]), cimagf(c[i]));
111         fprintf(fid,"i_str{%3u} = '", i+1);
112         unsigned int j;
113         for (j=0; j<bps; j++)
114             fprintf(fid,"%c", (i >> (bps-j-1)) & 0x01 ? '1' : '0');
115         fprintf(fid,"';\n");
116     }
117     fprintf(fid,"x = %12.8f + j*%12.8f;\n", crealf(c[sym_in]), cimagf(c[sym_in]));
118     fprintf(fid,"r = %12.8f + j*%12.8f;\n", crealf(r), cimagf(r));
119 
120     // plot results
121     fprintf(fid,"\n\n");
122     fprintf(fid,"figure;\n");
123     fprintf(fid,"plot(c,'o','MarkerSize',4,r,'rx',[x r]);\n");
124     fprintf(fid,"hold on;\n");
125     fprintf(fid,"text(real(c)+0.02, imag(c)+0.02, i_str);\n");
126     fprintf(fid,"hold off;\n");
127     fprintf(fid,"axis([-1 1 -1 1]*1.6);\n");
128     fprintf(fid,"axis square;\n");
129     fprintf(fid,"grid on;\n");
130     fprintf(fid,"xlabel('in phase');\n");
131     fprintf(fid,"ylabel('quadrature phase');\n");
132 
133     fclose(fid);
134     printf("results written to %s.\n", OUTPUT_FILENAME);
135 
136 
137     printf("done.\n");
138     return 0;
139 }
140