int main(int argc, char*argv[]) { srand( time(NULL) ); // options float SNRdB = 20.0f; // signal-to-noise ratio float noise_floor = -20.0f; // noise floor float dphi = 0.01f; // carrier frequency offset float theta = 0.0f; // carrier phase offset float dt = -0.2f; // fractional sample timing offset crc_scheme check = LIQUID_CRC_32; // data validity check fec_scheme fec0 = LIQUID_FEC_NONE; // fec (inner) fec_scheme fec1 = LIQUID_FEC_NONE; // fec (outer) unsigned int payload_len = 200; // payload length int debug_enabled = 0; // get options int dopt; while((dopt = getopt(argc,argv,"hdS:F:P:T:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'd': debug_enabled = 1; break; case 'S': SNRdB = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 'P': theta = atof(optarg); break; case 'T': dt = atof(optarg); break; default: exit(-1); } } // derived values float nstd = powf(10.0f, noise_floor/20.0f); // noise std. dev. float gamma = powf(10.0f, (SNRdB+noise_floor)/20.0f); // channel gain // create frame generator fskframegen fg = fskframegen_create(); fskframegen_print(fg); // create frame synchronizer using default properties fskframesync fs = fskframesync_create(callback,NULL); fskframesync_print(fs); if (debug_enabled) fskframesync_debug_enable(fs); // data payload unsigned int i; // initialize header and payload data for (i=0; i<8; i++) header[i] = i; for (i=0; i<200; i++) payload[i] = rand() & 0xff; // allocate memory for the frame samples unsigned int buf_len = 64; float complex buf_tx[buf_len]; // receive buffer float complex buf_rx[buf_len]; // transmit buffer // assemble the frame fskframegen_assemble(fg, header, payload, payload_len, check, fec0, fec1); // spectral periodogram unsigned int nfft = 4200; spgramcf periodogram = spgramcf_create_default(nfft); // write frame in blocks int frame_complete = 0; while (!frame_complete) { frame_complete = fskframegen_write_samples(fg, buf_tx, buf_len); // add noise, channel gain for (i=0; i<buf_len; i++) buf_rx[i] = buf_tx[i]*gamma + nstd*(randnf() + randnf()*_Complex_I)*M_SQRT1_2; // synchronize/receive the frame fskframesync_execute_block(fs, buf_rx, buf_len); // estimate power spectral density spgramcf_write(periodogram, buf_rx, buf_len); } // compute power spectral density of received signal float psd[nfft]; spgramcf_get_psd(periodogram, psd); // clean up allocated objects spgramcf_destroy(periodogram); fskframegen_destroy(fg); fskframesync_destroy(fs); // // export results // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"nfft = %u;\n", nfft); // save power spectral density fprintf(fid,"psd = zeros(1,nfft);\n"); for (i=0; i<nfft; i++) fprintf(fid,"psd(%4u) = %12.8f;\n", i+1, psd[i]); // plot PSD fprintf(fid,"figure('Color','white');\n"); fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"plot(f,psd,'LineWidth',1.5,'Color',[0.5 0 0]);\n"); fprintf(fid,"axis([-0.5 0.5 -30 30]);\n"); fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid,"ylabel('PSD [dB]');\n"); fprintf(fid,"grid on;\n"); fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { // options int ftype = LIQUID_FIRFILT_ARKAISER; int ms = LIQUID_MODEM_QPSK; unsigned int k = 2; // samples per symbol unsigned int m = 7; // filter delay (symbols) float beta = 0.20f; // filter excess bandwidth factor unsigned int num_symbols = 4000; // number of data symbols unsigned int hc_len = 4; // channel filter length float noise_floor = -60.0f; // noise floor [dB] float SNRdB = 30.0f; // signal-to-noise ratio [dB] float bandwidth = 0.02f; // loop filter bandwidth float tau = -0.2f; // fractional symbol offset float rate = 1.001f; // sample rate offset float dphi = 0.01f; // carrier frequency offset [radians/sample] float phi = 2.1f; // carrier phase offset [radians] unsigned int nfft = 2400; // spectral periodogram FFT size unsigned int num_samples = 200000; // number of samples int dopt; while ((dopt = getopt(argc,argv,"hk:m:b:s:w:n:t:r:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 's': SNRdB = atof(optarg); break; case 'w': bandwidth = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 't': tau = atof(optarg); break; case 'r': rate = atof(optarg); break; default: exit(1); } } // validate input if (k < 2) { fprintf(stderr,"error: k (samples/symbol) must be greater than 1\n"); exit(1); } else if (m < 1) { fprintf(stderr,"error: m (filter delay) must be greater than 0\n"); exit(1); } else if (beta <= 0.0f || beta > 1.0f) { fprintf(stderr,"error: beta (excess bandwidth factor) must be in (0,1]\n"); exit(1); } else if (bandwidth <= 0.0f) { fprintf(stderr,"error: timing PLL bandwidth must be greater than 0\n"); exit(1); } else if (num_symbols == 0) { fprintf(stderr,"error: number of symbols must be greater than 0\n"); exit(1); } else if (tau < -1.0f || tau > 1.0f) { fprintf(stderr,"error: timing phase offset must be in [-1,1]\n"); exit(1); } else if (rate > 1.02f || rate < 0.98f) { fprintf(stderr,"error: timing rate offset must be in [1.02,0.98]\n"); exit(1); } unsigned int i; // buffers unsigned int buf_len = 400; // buffer size float complex x [buf_len]; // original signal float complex y [buf_len*2]; // channel output (larger to accommodate resampler) float complex syms[buf_len]; // recovered symbols // window for saving last few symbols windowcf sym_buf = windowcf_create(buf_len); // create stream generator symstreamcf gen = symstreamcf_create_linear(ftype,k,m,beta,ms); // create channel emulator and add impairments channel_cccf channel = channel_cccf_create(); channel_cccf_add_awgn (channel, noise_floor, SNRdB); channel_cccf_add_carrier_offset(channel, dphi, phi); channel_cccf_add_multipath (channel, NULL, hc_len); channel_cccf_add_resamp (channel, 0.0f, rate); // create symbol tracking synchronizer symtrack_cccf symtrack = symtrack_cccf_create(ftype,k,m,beta,ms); symtrack_cccf_set_bandwidth(symtrack,0.05f); // create spectral periodogram for estimating spectrum spgramcf periodogram = spgramcf_create_default(nfft); unsigned int total_samples = 0; unsigned int ny; unsigned int total_symbols = 0; while (total_samples < num_samples) { // write samples to buffer symstreamcf_write_samples(gen, x, buf_len); // apply channel channel_cccf_execute(channel, x, buf_len, y, &ny); // push resulting sample through periodogram spgramcf_write(periodogram, y, ny); // run resulting stream through synchronizer unsigned int num_symbols_sync; symtrack_cccf_execute_block(symtrack, y, ny, syms, &num_symbols_sync); total_symbols += num_symbols_sync; // write resulting symbols to window buffer for plotting windowcf_write(sym_buf, syms, num_symbols_sync); // accumulated samples total_samples += buf_len; } printf("total samples: %u\n", total_samples); printf("total symbols: %u\n", total_symbols); // write accumulated power spectral density estimate float psd[nfft]; spgramcf_get_psd(periodogram, psd); // // export output file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s, auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); // read buffer and write last symbols to file float complex * rc; windowcf_read(sym_buf, &rc); fprintf(fid,"syms = zeros(1,%u);\n", buf_len); for (i=0; i<buf_len; i++) fprintf(fid,"syms(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(rc[i]), cimagf(rc[i])); // power spectral density estimate fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"f=[0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"psd = zeros(1,nfft);\n"); for (i=0; i<nfft; i++) fprintf(fid,"psd(%3u) = %12.8f;\n", i+1, psd[i]); fprintf(fid,"figure('Color','white','position',[500 500 1400 400]);\n"); fprintf(fid,"subplot(1,3,1);\n"); fprintf(fid,"plot(real(syms),imag(syms),'x','MarkerSize',4);\n"); fprintf(fid," axis square;\n"); fprintf(fid," grid on;\n"); fprintf(fid," axis([-1 1 -1 1]*1.6);\n"); fprintf(fid," xlabel('In-phase');\n"); fprintf(fid," ylabel('Quadrature');\n"); fprintf(fid," title('Last %u symbols');\n", buf_len); fprintf(fid,"subplot(1,3,2:3);\n"); fprintf(fid," plot(f, psd, 'LineWidth',1.5,'Color',[0 0.5 0.2]);\n"); fprintf(fid," grid on;\n"); fprintf(fid," pmin = 10*floor(0.1*min(psd - 5));\n"); fprintf(fid," pmax = 10*ceil (0.1*max(psd + 5));\n"); fprintf(fid," axis([-0.5 0.5 pmin pmax]);\n"); fprintf(fid," xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid," ylabel('Power Spectral Density [dB]');\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); // destroy objects symstreamcf_destroy (gen); spgramcf_destroy (periodogram); channel_cccf_destroy (channel); symtrack_cccf_destroy(symtrack); windowcf_destroy (sym_buf); // clean it up printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { // options unsigned int m = 3; // number of bits/symbol unsigned int k = 0; // filter samples/symbol unsigned int num_symbols = 8000; // number of data symbols float SNRdB = 40.0f; // signal-to-noise ratio [dB] float bandwidth = 0.20; // frequency spacing unsigned int nfft = 1200; // FFT size for compute spectrum int dopt; while ((dopt = getopt(argc,argv,"hm:k:b:n:s:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'm': m = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'b': bandwidth = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; default: exit(1); } } unsigned int i; unsigned int j; // derived values if (k == 0) k = 2 << m; // set samples per symbol if not otherwise specified unsigned int M = 1 << m; float nstd = powf(10.0f, -SNRdB/20.0f); // validate input if (k < M) { fprintf(stderr,"errors: %s, samples/symbol must be at least modulation size (M=%u)\n", __FILE__,M); exit(1); } else if (k > 2048) { fprintf(stderr,"errors: %s, samples/symbol exceeds maximum (2048)\n", __FILE__); exit(1); } else if (M > 1024) { fprintf(stderr,"errors: %s, modulation size (M=%u) exceeds maximum (1024)\n", __FILE__, M); exit(1); } else if (bandwidth <= 0.0f || bandwidth >= 0.5f) { fprintf(stderr,"errors: %s, bandwidht must be in (0,0.5)\n", __FILE__); exit(1); } // create modulator/demodulator pair fskmod mod = fskmod_create(m,k,bandwidth); fskdem dem = fskdem_create(m,k,bandwidth); fskdem_print(dem); // float complex buf_tx[k]; // transmit buffer float complex buf_rx[k]; // transmit buffer // spectral periodogram spgramcf periodogram = spgramcf_create_default(nfft); // modulate, demodulate, count errors unsigned int num_symbol_errors = 0; for (i=0; i<num_symbols; i++) { // generate random symbol unsigned int sym_in = rand() % M; // modulate fskmod_modulate(mod, sym_in, buf_tx); // add noise for (j=0; j<k; j++) buf_rx[j] = buf_tx[j] + nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2; // demodulate unsigned int sym_out = fskdem_demodulate(dem, buf_rx); // count errors num_symbol_errors += (sym_in == sym_out) ? 0 : 1; // estimate power spectral density spgramcf_write(periodogram, buf_rx, k); } printf("symbol errors: %u / %u\n", num_symbol_errors, num_symbols); // compute power spectral density of received signal float psd[nfft]; spgramcf_get_psd(periodogram, psd); spgramcf_destroy(periodogram); // // export results // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"k = %u;\n", k); fprintf(fid,"M = %u;\n", M); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"nfft = %u;\n", nfft); // save power spectral density fprintf(fid,"psd = zeros(1,nfft);\n"); for (i=0; i<nfft; i++) fprintf(fid,"psd(%4u) = %12.8f;\n", i+1, psd[i]); // plot PSD fprintf(fid,"figure('Color','white');\n"); fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"plot(f,psd,'LineWidth',1.5,'Color',[0.5 0 0]);\n"); fprintf(fid,"axis([-0.5 0.5 -40 20]);\n"); fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid,"ylabel('PSD [dB]');\n"); fprintf(fid,"grid on;\n"); fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME); return 0; }