1 //
2 // fskmodem_example.c
3 //
4 // This example demostrates the M-ary frequency-shift keying
5 // (MFSK) modem in liquid. A message signal is modulated and the
6 // resulting signal is recovered using a demodulator object.
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 #define OUTPUT_FILENAME "fskmodem_example.m"
18
19 // print usage/help message
usage()20 void usage()
21 {
22 printf("fskmodem_example -- frequency-shift keying example\n");
23 printf("options:\n");
24 printf(" h : print help\n");
25 printf(" m : bits/symbol, default: 3\n");
26 printf(" k : samples/symbol, default: 2*2^m\n");
27 printf(" b : signal bandwidth default: 0.2\n");
28 printf(" n : number of data symbols, default: 80\n");
29 printf(" s : SNR [dB], default: 40\n");
30 }
31
main(int argc,char * argv[])32 int main(int argc, char*argv[])
33 {
34 // options
35 unsigned int m = 3; // number of bits/symbol
36 unsigned int k = 0; // filter samples/symbol
37 unsigned int num_symbols = 8000; // number of data symbols
38 float SNRdB = 40.0f; // signal-to-noise ratio [dB]
39 float bandwidth = 0.20; // frequency spacing
40 unsigned int nfft = 1200; // FFT size for compute spectrum
41
42 int dopt;
43 while ((dopt = getopt(argc,argv,"hm:k:b:n:s:")) != EOF) {
44 switch (dopt) {
45 case 'h': usage(); return 0;
46 case 'm': m = atoi(optarg); break;
47 case 'k': k = atoi(optarg); break;
48 case 'b': bandwidth = atof(optarg); break;
49 case 'n': num_symbols = atoi(optarg); break;
50 case 's': SNRdB = atof(optarg); break;
51 default:
52 exit(1);
53 }
54 }
55
56 unsigned int i;
57 unsigned int j;
58
59 // derived values
60 if (k == 0)
61 k = 2 << m; // set samples per symbol if not otherwise specified
62 unsigned int M = 1 << m;
63 float nstd = powf(10.0f, -SNRdB/20.0f);
64
65 // validate input
66 if (k < M) {
67 fprintf(stderr,"errors: %s, samples/symbol must be at least modulation size (M=%u)\n", __FILE__,M);
68 exit(1);
69 } else if (k > 2048) {
70 fprintf(stderr,"errors: %s, samples/symbol exceeds maximum (2048)\n", __FILE__);
71 exit(1);
72 } else if (M > 1024) {
73 fprintf(stderr,"errors: %s, modulation size (M=%u) exceeds maximum (1024)\n", __FILE__, M);
74 exit(1);
75 } else if (bandwidth <= 0.0f || bandwidth >= 0.5f) {
76 fprintf(stderr,"errors: %s, bandwidht must be in (0,0.5)\n", __FILE__);
77 exit(1);
78 }
79
80 // create modulator/demodulator pair
81 fskmod mod = fskmod_create(m,k,bandwidth);
82 fskdem dem = fskdem_create(m,k,bandwidth);
83 fskdem_print(dem);
84
85 //
86 float complex buf_tx[k]; // transmit buffer
87 float complex buf_rx[k]; // transmit buffer
88
89 // spectral periodogram
90 spgramcf periodogram = spgramcf_create_default(nfft);
91
92 // modulate, demodulate, count errors
93 unsigned int num_symbol_errors = 0;
94 for (i=0; i<num_symbols; i++) {
95 // generate random symbol
96 unsigned int sym_in = rand() % M;
97
98 // modulate
99 fskmod_modulate(mod, sym_in, buf_tx);
100
101 // add noise
102 for (j=0; j<k; j++)
103 buf_rx[j] = buf_tx[j] + nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2;
104
105 // demodulate
106 unsigned int sym_out = fskdem_demodulate(dem, buf_rx);
107
108 // count errors
109 num_symbol_errors += (sym_in == sym_out) ? 0 : 1;
110
111 // estimate power spectral density
112 spgramcf_write(periodogram, buf_rx, k);
113 }
114
115 // destroy modulator/demodulator pair
116 fskmod_destroy(mod);
117 fskdem_destroy(dem);
118
119 printf("symbol errors: %u / %u\n", num_symbol_errors, num_symbols);
120
121 // compute power spectral density of received signal
122 float psd[nfft];
123 spgramcf_get_psd(periodogram, psd);
124 spgramcf_destroy(periodogram);
125
126 //
127 // export results
128 //
129
130 FILE * fid = fopen(OUTPUT_FILENAME,"w");
131 fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
132 fprintf(fid,"clear all\n");
133 fprintf(fid,"close all\n");
134 fprintf(fid,"k = %u;\n", k);
135 fprintf(fid,"M = %u;\n", M);
136 fprintf(fid,"num_symbols = %u;\n", num_symbols);
137 fprintf(fid,"nfft = %u;\n", nfft);
138
139 // save power spectral density
140 fprintf(fid,"psd = zeros(1,nfft);\n");
141 for (i=0; i<nfft; i++)
142 fprintf(fid,"psd(%4u) = %12.8f;\n", i+1, psd[i]);
143
144 // plot PSD
145 fprintf(fid,"figure('Color','white');\n");
146 fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n");
147 fprintf(fid,"plot(f,psd,'LineWidth',1.5,'Color',[0.5 0 0]);\n");
148 fprintf(fid,"axis([-0.5 0.5 -40 20]);\n");
149 fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n");
150 fprintf(fid,"ylabel('PSD [dB]');\n");
151 fprintf(fid,"grid on;\n");
152
153 fclose(fid);
154 printf("results written to '%s'\n", OUTPUT_FILENAME);
155
156 return 0;
157 }
158