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