1 //
2 // scramble_example.c
3 //
4 // Data-scrambling example.  Physical layer synchronization of
5 // received waveforms relies on independent and identically
6 // distributed underlying data symbols.  If the message sequence,
7 // however, is '00000....' and the modulation scheme is BPSK,
8 // the synchronizer probably won't be able to recover the symbol
9 // timing.  It is imperative to increase the entropy of the data
10 // for this to happen.  The data scrambler routine attempts to
11 // 'whiten' the data sequence with a bit mask in order to achieve
12 // maximum entropy.  This example demonstrates the interface.
13 //
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <math.h>
19 #include "liquid.h"
20 
21 float compute_entropy(unsigned char * _x,
22                       unsigned int _n);
23 
main()24 int main() {
25     unsigned int n=32;  // number of data bytes
26 
27     unsigned char x[n]; // input data
28     unsigned char y[n]; // scrambled data
29     unsigned char z[n]; // unscrambled data
30 
31     unsigned int i;
32 
33     // generate data
34     for (i=0; i<n; i++)
35         x[i] = rand() % 2 ? 0x0f : 0xc8;
36 
37     // scramble input
38     memmove(y,x,n);
39     scramble_data(y,n);
40 
41     // unscramble result
42     memmove(z,y,n);
43     unscramble_data(z,n);
44 
45     float Hx = compute_entropy(x,n);
46     float Hy = compute_entropy(y,n);
47 
48     // print results
49     printf("i\tx\ty\tz\n");
50     printf("--\t--\t--\t--\n");
51     for (i=0; i<n; i++)
52         printf("%u\t%.2x\t%.2x\t%.2x\n", i, x[i], y[i], z[i]);
53 
54     printf("H(x) = %12.8f\n", Hx);
55     printf("H(y) = %12.8f\n", Hy);
56 
57     printf("done.\n");
58     return 0;
59 }
60 
61 // raw entropy calculation, orders 1, 2, 4, 8
compute_entropy(unsigned char * _x,unsigned int _n)62 float compute_entropy(unsigned char * _x,
63                       unsigned int _n)
64 {
65     unsigned int i;
66     unsigned int j;
67 
68     // initialize counter arrays
69     unsigned int c1[2];     // 1-bit symbols
70     unsigned int c2[4];     // 2-bit symbols
71     unsigned int c4[16];    // 4-bit symbols
72     unsigned int c8[256];   // 8-bit symbols
73 
74     for (i=0; i<2;   i++) c1[i] = 0;
75     for (i=0; i<4;   i++) c2[i] = 0;
76     for (i=0; i<16;  i++) c4[i] = 0;
77     for (i=0; i<256; i++) c8[i] = 0;
78 
79     for (i=0; i<_n; i++) {
80         // b:1
81         for (j=0; j<8; j++)  c1[ (_x[i] >> j) & 0x01 ]++;
82 
83         // b:2
84         for (j=0; j<8; j+=2) c2[ (_x[i] >> j) & 0x03 ]++;
85 
86         // b:4
87         for (j=0; j<8; j+=4) c4[ (_x[i] >> j) & 0x0f ]++;
88 
89         // b:8
90         c8[ _x[i] ]++;
91     }
92 
93     // compute entropy
94     float H1 = 0.0f;
95     float H2 = 0.0f;
96     float H4 = 0.0f;
97     float H8 = 0.0f;
98 
99     float p;
100     for (i=0; i<2; i++) {
101         p = (float) c1[i] / (float)(8*_n);
102         H1 -= p * log2f(p+1e-12f);
103     }
104     H1 /= 1.0f;
105 
106     for (i=0; i<4; i++) {
107         p = (float) c2[i] / (float)(4*_n);
108         H2 -= p * log2f(p+1e-12f);
109     }
110     H2 /= 2.0f;
111 
112     for (i=0; i<16; i++) {
113         p = (float) c4[i] / (float)(2*_n);
114         H4 -= p * log2f(p+1e-12f);
115     }
116     H4 /= 4.0f;
117 
118     for (i=0; i<256; i++) {
119         p = (float) c8[i] / (float)(_n);
120         H8 -= p * log2f(p+1e-12f);
121     }
122     H8 /= 8.0f;
123 
124 #if 0
125     printf("H1 : %12.8f\n", H1);
126     printf("H2 : %12.8f\n", H2);
127     printf("H4 : %12.8f\n", H4);
128     printf("H8 : %12.8f\n", H8);
129 #endif
130 
131     // not sure if product is truly the entropy, but
132     // it is a fair assessment
133     return H1 * H2 * H4 * H8;
134 }
135 
136