1 //
2 // fskmodem_waterfall_example.c
3 //
4 // This example demostrates the M-ary frequency-shift keying
5 // (MFSK) modem in liquid by showing the resulting spectral
6 // waterfall.
7 //
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <getopt.h>
13 #include <math.h>
14
15 #include "liquid.h"
16
17 // print usage/help message
usage()18 void usage()
19 {
20 printf("fskmodem_waterfall_example -- frequency-shift keying waterfall example\n");
21 printf("options:\n");
22 printf(" -h : print help\n");
23 printf(" -m <bps> : bits/symbol, default: 2\n");
24 printf(" -b <bw> : signal bandwidth default: 0.2\n");
25 printf(" -n <num> : number of data symbols, default: 80\n");
26 printf(" -s <snr> : SNR [dB], default: 40\n");
27 }
28
main(int argc,char * argv[])29 int main(int argc, char*argv[])
30 {
31 // options
32 unsigned int m = 2; // number of bits/symbol
33 unsigned int num_symbols = 400; // number of data symbols
34 float SNRdB = 30.0f; // signal-to-noise ratio [dB]
35 float bandwidth = 0.10; // frequency spacing
36
37 int dopt;
38 while ((dopt = getopt(argc,argv,"hm:b:n:s:")) != EOF) {
39 switch (dopt) {
40 case 'h': usage(); return 0;
41 case 'm': m = atoi(optarg); break;
42 case 'b': bandwidth = atof(optarg); break;
43 case 'n': num_symbols = atoi(optarg); break;
44 case 's': SNRdB = atof(optarg); break;
45 default:
46 exit(1);
47 }
48 }
49
50 unsigned int i;
51 unsigned int j;
52
53 // derived values
54 unsigned int M = 1 << m; // constellation size
55 unsigned int k = 500 * M; // samples per symbol (highly over-sampled)
56 float nstd = powf(10.0f, -SNRdB/20.0f); // noise std. dev.
57
58 // validate input
59 if (k < M) {
60 fprintf(stderr,"errors: %s, samples/symbol must be at least modulation size (M=%u)\n", __FILE__,M);
61 exit(1);
62 } else if (k > 2048) {
63 fprintf(stderr,"errors: %s, samples/symbol exceeds maximum (2048)\n", __FILE__);
64 exit(1);
65 } else if (M > 1024) {
66 fprintf(stderr,"errors: %s, modulation size (M=%u) exceeds maximum (1024)\n", __FILE__, M);
67 exit(1);
68 } else if (bandwidth <= 0.0f || bandwidth >= 0.5f) {
69 fprintf(stderr,"errors: %s, bandwidht must be in (0,0.5)\n", __FILE__);
70 exit(1);
71 }
72
73 // create spectral waterfall object
74 unsigned int nfft = 1 << liquid_nextpow2(k);
75 int wtype = LIQUID_WINDOW_HAMMING;
76 unsigned int wlen = nfft/2;
77 unsigned int delay = nfft/2;
78 unsigned int time = 512;
79 spwaterfallcf periodogram = spwaterfallcf_create(nfft,wtype,wlen,delay,time);
80 spwaterfallcf_print(periodogram);
81
82 // create modulator/demodulator pair
83 fskmod mod = fskmod_create(m,k,bandwidth);
84
85 float complex buf_tx[k]; // transmit buffer
86 float complex buf_rx[k]; // transmit buffer
87
88 // modulate, demodulate, count errors
89 for (i=0; i<num_symbols; i++) {
90 // generate random symbol
91 unsigned int sym_in = rand() % M;
92
93 // modulate
94 fskmod_modulate(mod, sym_in, buf_tx);
95
96 // add noise
97 for (j=0; j<k; j++)
98 buf_rx[j] = buf_tx[j] + nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2;
99
100 // estimate power spectral density
101 spwaterfallcf_write(periodogram, buf_rx, k);
102 }
103
104 // export output files
105 spwaterfallcf_export(periodogram,"fskmodem_waterfall_example");
106
107 // destroy objects
108 spwaterfallcf_print(periodogram);
109 fskmod_destroy(mod);
110
111 return 0;
112 }
113