1 //
2 // dsssframesync_example.c
3 //
4
5 #include <assert.h>
6 #include <getopt.h>
7 #include <math.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <time.h>
12
13 #include "liquid.h"
14
usage()15 void usage()
16 {
17 printf("dsssframesync_example [options]\n");
18 printf(" u/h : print usage\n");
19 printf(" s : signal-to-noise ratio [dB], default: 20\n");
20 printf(" F : carrier frequency offset, default: 0.01\n");
21 printf(" n : payload length [bytes], default: 480\n");
22 printf(" v : data integrity check: crc32 default\n");
23 liquid_print_crc_schemes();
24 printf(" c : coding scheme (inner): h74 default\n");
25 printf(" k : coding scheme (outer): none default\n");
26 liquid_print_fec_schemes();
27 printf(" d : enable debugging\n");
28 }
29
30 // dsssframesync callback function
31 static int callback(unsigned char * _header,
32 int _header_valid,
33 unsigned char * _payload,
34 unsigned int _payload_len,
35 int _payload_valid,
36 framesyncstats_s _stats,
37 void * _userdata);
38
main(int argc,char * argv[])39 int main(int argc, char * argv[])
40 {
41 srand(time(NULL));
42
43 // options
44 crc_scheme check = LIQUID_CRC_32; // data validity check
45 fec_scheme fec0 = LIQUID_FEC_NONE; // fec (inner)
46 fec_scheme fec1 = LIQUID_FEC_NONE; // fec (outer)
47 unsigned int payload_len = 20; // payload length
48 int debug_enabled = 0; // enable debugging?
49 float noise_floor = -60.0f; // noise floor
50 float SNRdB = -3.0f; // signal-to-noise ratio
51 float dphi = 0.03f; // carrier frequency offset
52
53 // get options
54 int dopt;
55 while ((dopt = getopt(argc, argv, "uhs:F:n:m:v:c:k:d")) != EOF) {
56 switch (dopt) {
57 case 'u':
58 case 'h': usage(); return 0;
59 case 's': SNRdB = atof(optarg); break;
60 case 'F': dphi = atof(optarg); break;
61 case 'n': payload_len = atol(optarg); break;
62 case 'v': check = liquid_getopt_str2crc(optarg); break;
63 case 'c': fec0 = liquid_getopt_str2fec(optarg); break;
64 case 'k': fec1 = liquid_getopt_str2fec(optarg); break;
65 case 'd': debug_enabled = 1; break;
66 default: exit(-1);
67 }
68 }
69
70 // derived values
71 unsigned int i;
72 float nstd = powf(10.0f, noise_floor / 20.0f); // noise std. dev.
73 float gamma = powf(10.0f, (SNRdB + noise_floor) / 20.0f); // channel gain
74
75 // create dsssframegen object
76 dsssframegenprops_s fgprops;
77 fgprops.check = check;
78 fgprops.fec0 = fec0;
79 fgprops.fec1 = fec1;
80 dsssframegen fg = dsssframegen_create(&fgprops);
81
82 // create dsssframesync object
83 dsssframesync fs = dsssframesync_create(callback, NULL);
84 if (debug_enabled) {
85 // dsssframesync_debug_enable(fs);
86 }
87
88 // assemble the frame (NULL pointers for default values)
89 dsssframegen_assemble(fg, NULL, NULL, payload_len);
90 // dsssframegen_print(fg);
91
92 // generate the frame in blocks
93 unsigned int buf_len = 256;
94 float complex x[buf_len];
95 float complex y[buf_len];
96
97 int frame_complete = 0;
98 float phi = 0.0f;
99 while (!frame_complete) {
100 frame_complete = dsssframegen_write_samples(fg, x, buf_len);
101
102 // add noise and push through synchronizer
103 for (i = 0; i < buf_len; i++) {
104 // apply channel gain and carrier offset to input
105 y[i] = gamma * x[i] * cexpf(_Complex_I * phi);
106 phi += dphi;
107
108 // add noise
109 y[i] += nstd * (randnf() + _Complex_I * randnf()) * M_SQRT1_2;
110 }
111
112 // run through frame synchronizer
113 dsssframesync_execute(fs, y, buf_len);
114 }
115
116 // export debugging file
117 if (debug_enabled) {
118 // dsssframesync_debug_print(fs, "dsssframesync_debug.m");
119 }
120
121 // dsssframesync_print(fs);
122 // destroy allocated objects
123 dsssframegen_destroy(fg);
124 dsssframesync_destroy(fs);
125
126 printf("done.\n");
127 return 0;
128 }
129
callback(unsigned char * _header,int _header_valid,unsigned char * _payload,unsigned int _payload_len,int _payload_valid,framesyncstats_s _stats,void * _userdata)130 static int callback(unsigned char * _header,
131 int _header_valid,
132 unsigned char * _payload,
133 unsigned int _payload_len,
134 int _payload_valid,
135 framesyncstats_s _stats,
136 void * _userdata)
137 {
138 printf("******** callback invoked\n");
139
140 // count bit errors (assuming all-zero message)
141 unsigned int bit_errors = 0;
142 unsigned int i;
143 for (i = 0; i < _payload_len; i++)
144 bit_errors += liquid_count_ones(_payload[i]);
145
146 framesyncstats_print(&_stats);
147 printf(" header crc : %s\n", _header_valid ? "pass" : "FAIL");
148 printf(" payload length : %u\n", _payload_len);
149 printf(" payload crc : %s\n", _payload_valid ? "pass" : "FAIL");
150 printf(" payload bit errors : %u / %u\n", bit_errors, 8 * _payload_len);
151
152 return 0;
153 }
154