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 float alpha = 0.01f; // PSD accumulation constant 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_kaiser(nfft, nfft/2, 8.0f); // 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_accumulate_psd(periodogram, buf_rx, alpha, k); } printf("symbol errors: %u / %u\n", num_symbol_errors, num_symbols); // compute power spectral density of received signal float psd[nfft]; spgramcf_write_accumulation(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; }
int main(int argc, char*argv[]) { // options unsigned int bps = 1; // number of bits/symbol float h = 0.5f; // modulation index (h=1/2 for MSK) unsigned int k = 4; // filter samples/symbol unsigned int m = 3; // filter delay (symbols) float beta = 0.35f; // GMSK bandwidth-time factor unsigned int num_symbols = 20; // number of data symbols float SNRdB = 40.0f; // signal-to-noise ratio [dB] float cfo = 0.0f; // carrier frequency offset float cpo = 0.0f; // carrier phase offset float tau = 0.0f; // fractional symbol timing offset int filter_type = LIQUID_CPFSK_SQUARE; int dopt; while ((dopt = getopt(argc,argv,"ht:p:H:k:m:b:n:s:F:P:T:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 't': if (strcmp(optarg,"square")==0) { filter_type = LIQUID_CPFSK_SQUARE; } else if (strcmp(optarg,"rcos-full")==0) { filter_type = LIQUID_CPFSK_RCOS_FULL; } else if (strcmp(optarg,"rcos-half")==0) { filter_type = LIQUID_CPFSK_RCOS_PARTIAL; } else if (strcmp(optarg,"gmsk")==0) { filter_type = LIQUID_CPFSK_GMSK; } else { fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg); exit(1); } break; case 'p': bps = atoi(optarg); break; case 'H': h = atof(optarg); break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'F': cfo = atof(optarg); break; case 'P': cpo = atof(optarg); break; case 'T': tau = atof(optarg); break; default: exit(1); } } unsigned int i; // derived values unsigned int num_samples = k*num_symbols; unsigned int M = 1 << bps; // constellation size float nstd = powf(10.0f, -SNRdB/20.0f); // arrays unsigned int sym_in[num_symbols]; // input symbols float complex x[num_samples]; // transmitted signal float complex y[num_samples]; // received signal unsigned int sym_out[num_symbols]; // output symbols // create modem objects cpfskmod mod = cpfskmod_create(bps, h, k, m, beta, filter_type); cpfskdem dem = cpfskdem_create(bps, h, k, m, beta, filter_type); // print modulator cpfskmod_print(mod); // generate message signal for (i=0; i<num_symbols; i++) sym_in[i] = rand() % M; // modulate signal for (i=0; i<num_symbols; i++) cpfskmod_modulate(mod, sym_in[i], &x[k*i]); // push through channel float sample_offset = -tau * k; int sample_delay = (int)roundf(sample_offset); float dt = sample_offset - (float)sample_delay; printf("symbol delay : %f\n", tau); printf("sample delay : %f = %d + %f\n", sample_offset, sample_delay, dt); firfilt_crcf fchannel = firfilt_crcf_create_kaiser(8*k+2*sample_delay+1, 0.45f, 40.0f, dt); for (i=0; i<num_samples; i++) { // push through channel delay firfilt_crcf_push(fchannel, x[i]); firfilt_crcf_execute(fchannel, &y[i]); // add carrier frequency/phase offset y[i] *= cexpf(_Complex_I*(cfo*i + cpo)); // add noise y[i] += nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2; } firfilt_crcf_destroy(fchannel); // demodulate signal unsigned int nw=0; cpfskdem_demodulate(dem, y, num_samples, sym_out, &nw); printf("demodulator wrote %u symbols\n", nw); // destroy modem objects cpfskmod_destroy(mod); cpfskdem_destroy(dem); // compute power spectral density of transmitted signal unsigned int nfft = 1024; float psd[nfft]; spgramcf periodogram = spgramcf_create_kaiser(nfft, nfft/2, 8.0f); spgramcf_estimate_psd(periodogram, x, num_samples, 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,"h = %f;\n", h); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"num_samples = %u;\n", num_samples); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"delay = %u; %% receive filter delay\n", m); fprintf(fid,"x = zeros(1,num_samples);\n"); fprintf(fid,"y = zeros(1,num_samples);\n"); for (i=0; i<num_samples; i++) { fprintf(fid,"x(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i])); fprintf(fid,"y(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i])); } // 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]); fprintf(fid,"t=[0:(num_samples-1)]/k;\n"); fprintf(fid,"i = 1:k:num_samples;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(3,4,1:3);\n"); fprintf(fid," plot(t,real(x),'-', t(i),real(x(i)),'ob',...\n"); fprintf(fid," t,imag(x),'-', t(i),imag(x(i)),'og');\n"); fprintf(fid," axis([0 num_symbols -1.2 1.2]);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('x(t)');\n"); fprintf(fid," grid on;\n"); fprintf(fid,"subplot(3,4,5:7);\n"); fprintf(fid," plot(t,real(y),'-', t(i),real(y(i)),'ob',...\n"); fprintf(fid," t,imag(y),'-', t(i),imag(y(i)),'og');\n"); fprintf(fid," axis([0 num_symbols -1.2 1.2]);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('y(t)');\n"); fprintf(fid," grid on;\n"); // plot I/Q constellations fprintf(fid,"subplot(3,4,4);\n"); fprintf(fid," plot(real(x),imag(x),'-',real(x(i)),imag(x(i)),'rs','MarkerSize',4);\n"); fprintf(fid," xlabel('I');\n"); fprintf(fid," ylabel('Q');\n"); fprintf(fid," axis([-1 1 -1 1]*1.2);\n"); fprintf(fid," axis square;\n"); fprintf(fid," grid on;\n"); fprintf(fid,"subplot(3,4,8);\n"); fprintf(fid," plot(real(y),imag(y),'-',real(y(i)),imag(y(i)),'rs','MarkerSize',4);\n"); fprintf(fid," xlabel('I');\n"); fprintf(fid," ylabel('Q');\n"); fprintf(fid," axis([-1 1 -1 1]*1.2);\n"); fprintf(fid," axis square;\n"); fprintf(fid," grid on;\n"); // plot PSD fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"subplot(3,4,9:12);\n"); fprintf(fid," plot(f,psd,'LineWidth',1.5);\n"); fprintf(fid," axis([-0.5 0.5 -60 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; }
int main() { // msource parameters int ms = LIQUID_MODEM_QPSK; unsigned int k = 4; unsigned int m = 9; float beta = 0.30f; // spectral periodogram options unsigned int nfft = 2400; // spectral periodogram FFT size unsigned int num_samples = 48000; // number of samples float alpha = 0.05f; // PSD estimate bandwidth unsigned int i; // create spectral periodogram unsigned int window_size = nfft/2; // spgramcf window size spgramcf periodogram = spgramcf_create_kaiser(nfft, window_size, 10.0f); unsigned int buf_len = 1024; float complex buf[buf_len]; // create stream generator msourcecf gen = msourcecf_create(); int id; // add noise source (wide-band) id = msourcecf_add_noise(gen, 1.00f); msourcecf_set_gain(gen, id, -60.0f); // add noise source (narrow-band) id = msourcecf_add_noise(gen, 0.10f); msourcecf_set_frequency(gen, id, 0.4*2*M_PI); msourcecf_set_gain(gen, id, -20.0f); // add tone id = msourcecf_add_tone(gen); msourcecf_set_frequency(gen, id, -0.4*2*M_PI); msourcecf_set_gain(gen, id, -40.0f); // add modulated data id = msourcecf_add_modem(gen,ms,k,m,beta); //msourcecf_set_frequency(gen, id, -0.2*2*M_PI); //msourcecf_set_gain(gen, id, 0.1f); // print source generator object msourcecf_print(gen); unsigned int total_samples = 0; while (total_samples < num_samples) { // write samples to buffer msourcecf_write_samples(gen, buf, buf_len); // push resulting sample through periodogram spgramcf_accumulate_psd(periodogram, buf, alpha, buf_len); // accumulated samples total_samples += buf_len; } printf("total samples: %u\n", total_samples); // compute power spectral density output float psd[nfft]; spgramcf_write_accumulation(periodogram, psd); // destroy objects msourcecf_destroy(gen); spgramcf_destroy(periodogram); // // export output file // 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\n"); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"H = zeros(1,nfft);\n"); for (i=0; i<nfft; i++) fprintf(fid,"H(%6u) = %12.4e;\n", i+1, psd[i]); fprintf(fid,"figure;\n"); fprintf(fid,"plot(f, H, '-', 'LineWidth',1.5);\n"); fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid,"ylabel('Power Spectral Density [dB]');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([-0.5 0.5 -80 20]);\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() { // spectral periodogram options unsigned int nfft = 1200; // spectral periodogram FFT size unsigned int num_samples = 64000; // number of samples float fc = 0.20f; // carrier (relative to sampling rate) // create objects iirfilt_crcf filter_tx = iirfilt_crcf_create_lowpass(15, 0.05); nco_crcf mixer_tx = nco_crcf_create(LIQUID_VCO); nco_crcf mixer_rx = nco_crcf_create(LIQUID_VCO); iirfilt_crcf filter_rx = iirfilt_crcf_create_lowpass(7, 0.2); // set carrier frequencies nco_crcf_set_frequency(mixer_tx, fc * 2*M_PI); nco_crcf_set_frequency(mixer_rx, fc * 2*M_PI); // create objects for measuring power spectral density spgramcf spgram_tx = spgramcf_create_default(nfft); spgramf spgram_dac = spgramf_create_default(nfft); spgramcf spgram_rx = spgramcf_create_default(nfft); // run through loop one step at a time unsigned int i; for (i=0; i<num_samples; i++) { // STEP 1: generate input signal (filtered noise with offset tone) float complex v1 = (randnf() + randnf()*_Complex_I) + 3.0f*cexpf(-_Complex_I*0.2f*i); iirfilt_crcf_execute(filter_tx, v1, &v1); // save spectrum spgramcf_push(spgram_tx, v1); // STEP 2: mix signal up and save real part (DAC output) nco_crcf_mix_up(mixer_tx, v1, &v1); float v2 = crealf(v1); nco_crcf_step(mixer_tx); // save spectrum spgramf_push(spgram_dac, v2); // STEP 3: mix signal down and filter off image float complex v3; nco_crcf_mix_down(mixer_rx, v2, &v3); iirfilt_crcf_execute(filter_rx, v3, &v3); nco_crcf_step(mixer_rx); // save spectrum spgramcf_push(spgram_rx, v3); } // compute power spectral density output float psd_tx [nfft]; float psd_dac [nfft]; float psd_rx [nfft]; spgramcf_get_psd(spgram_tx, psd_tx); spgramf_get_psd( spgram_dac, psd_dac); spgramcf_get_psd(spgram_rx, psd_rx); // destroy objects spgramcf_destroy(spgram_tx); spgramf_destroy(spgram_dac); spgramcf_destroy(spgram_rx); iirfilt_crcf_destroy(filter_tx); nco_crcf_destroy(mixer_tx); nco_crcf_destroy(mixer_rx); iirfilt_crcf_destroy(filter_rx); // // export output file // 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\n"); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"psd_tx = zeros(1,nfft);\n"); fprintf(fid,"psd_dac= zeros(1,nfft);\n"); fprintf(fid,"psd_rx = zeros(1,nfft);\n"); for (i=0; i<nfft; i++) { fprintf(fid,"psd_tx (%6u) = %12.4e;\n", i+1, psd_tx [i]); fprintf(fid,"psd_dac(%6u) = %12.4e;\n", i+1, psd_dac[i]); fprintf(fid,"psd_rx (%6u) = %12.4e;\n", i+1, psd_rx [i]); } fprintf(fid,"figure;\n"); fprintf(fid,"hold on;\n"); fprintf(fid," plot(f, psd_tx, '-', 'LineWidth',1.5,'Color',[0.7 0.7 0.7]);\n"); fprintf(fid," plot(f, psd_dac, '-', 'LineWidth',1.5,'Color',[0.0 0.5 0.3]);\n"); fprintf(fid," plot(f, psd_rx, '-', 'LineWidth',1.5,'Color',[0.0 0.3 0.5]);\n"); fprintf(fid,"hold off;\n"); fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid,"ylabel('Power Spectral Density [dB]');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([-0.5 0.5 -100 60]);\n"); fprintf(fid,"legend('transmit (complex)','DAC output (real)','receive (complex)','location','northeast');\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { // options unsigned int k = 8; // filter samples/symbol unsigned int bps= 1; // number of bits/symbol float h = 0.5f; // modulation index (h=1/2 for MSK) unsigned int num_data_symbols = 20; // number of data symbols float SNRdB = 80.0f; // signal-to-noise ratio [dB] float cfo = 0.0f; // carrier frequency offset float cpo = 0.0f; // carrier phase offset float tau = 0.0f; // fractional symbol offset enum { TXFILT_SQUARE=0, TXFILT_RCOS_FULL, TXFILT_RCOS_HALF, TXFILT_GMSK, } tx_filter_type = TXFILT_SQUARE; float gmsk_bt = 0.35f; // GMSK bandwidth-time factor int dopt; while ((dopt = getopt(argc,argv,"ht:k:b:H:B:n:s:F:P:T:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 't': if (strcmp(optarg,"square")==0) { tx_filter_type = TXFILT_SQUARE; } else if (strcmp(optarg,"rcos-full")==0) { tx_filter_type = TXFILT_RCOS_FULL; } else if (strcmp(optarg,"rcos-half")==0) { tx_filter_type = TXFILT_RCOS_HALF; } else if (strcmp(optarg,"gmsk")==0) { tx_filter_type = TXFILT_GMSK; } else { fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg); exit(1); } break; case 'k': k = atoi(optarg); break; case 'b': bps = atoi(optarg); break; case 'H': h = atof(optarg); break; case 'B': gmsk_bt = atof(optarg); break; case 'n': num_data_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'F': cfo = atof(optarg); break; case 'P': cpo = atof(optarg); break; case 'T': tau = atof(optarg); break; default: exit(1); } } unsigned int i; // derived values unsigned int num_symbols = num_data_symbols; unsigned int num_samples = k*num_symbols; unsigned int M = 1 << bps; // constellation size float nstd = powf(10.0f, -SNRdB/20.0f); // arrays unsigned char sym_in[num_symbols]; // input symbols float phi[num_samples]; // transmitted phase float complex x[num_samples]; // transmitted signal float complex y[num_samples]; // received signal float complex z[num_samples]; // output... //unsigned char sym_out[num_symbols]; // output symbols unsigned int ht_len = 0; unsigned int tx_delay = 0; float * ht = NULL; switch (tx_filter_type) { case TXFILT_SQUARE: // regular MSK ht_len = k; tx_delay = 1; ht = (float*) malloc(ht_len *sizeof(float)); for (i=0; i<ht_len; i++) ht[i] = h * M_PI / (float)k; break; case TXFILT_RCOS_FULL: // full-response raised-cosine pulse ht_len = k; tx_delay = 1; ht = (float*) malloc(ht_len *sizeof(float)); for (i=0; i<ht_len; i++) ht[i] = h * M_PI / (float)k * (1.0f - cosf(2.0f*M_PI*i/(float)ht_len)); break; case TXFILT_RCOS_HALF: // partial-response raised-cosine pulse ht_len = 3*k; tx_delay = 2; ht = (float*) malloc(ht_len *sizeof(float)); for (i=0; i<ht_len; i++) ht[i] = 0.0f; for (i=0; i<2*k; i++) ht[i+k/2] = h * 0.5f * M_PI / (float)k * (1.0f - cosf(2.0f*M_PI*i/(float)(2*k))); break; case TXFILT_GMSK: ht_len = 2*k*3+1+k; tx_delay = 4; ht = (float*) malloc(ht_len *sizeof(float)); for (i=0; i<ht_len; i++) ht[i] = 0.0f; liquid_firdes_gmsktx(k,3,gmsk_bt,0.0f,&ht[k/2]); for (i=0; i<ht_len; i++) ht[i] *= h * 2.0f / (float)k; break; default: fprintf(stderr,"error: %s, invalid tx filter type\n", argv[0]); exit(1); } for (i=0; i<ht_len; i++) printf("ht(%3u) = %12.8f;\n", i+1, ht[i]); firinterp_rrrf interp_tx = firinterp_rrrf_create(k, ht, ht_len); // generate symbols and interpolate // phase-accumulating filter (trapezoidal integrator) float b[2] = {0.5f, 0.5f}; if (tx_filter_type == TXFILT_SQUARE) { // square filter: rectangular integration with one sample of delay b[0] = 0.0f; b[1] = 1.0f; } float a[2] = {1.0f, -1.0f}; iirfilt_rrrf integrator = iirfilt_rrrf_create(b,2,a,2); float theta = 0.0f; for (i=0; i<num_symbols; i++) { sym_in[i] = rand() % M; float v = 2.0f*sym_in[i] - (float)(M-1); // +/-1, +/-3, ... +/-(M-1) firinterp_rrrf_execute(interp_tx, v, &phi[k*i]); // accumulate phase unsigned int j; for (j=0; j<k; j++) { iirfilt_rrrf_execute(integrator, phi[i*k+j], &theta); x[i*k+j] = cexpf(_Complex_I*theta); } } iirfilt_rrrf_destroy(integrator); // push through channel for (i=0; i<num_samples; i++) { // add carrier frequency/phase offset y[i] = x[i]*cexpf(_Complex_I*(cfo*i + cpo)); // add noise y[i] += nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2; } // create decimator unsigned int m = 3; float bw = 0.0f; float beta = 0.0f; firfilt_crcf decim_rx = NULL; switch (tx_filter_type) { case TXFILT_SQUARE: //bw = 0.9f / (float)k; bw = 0.4f; decim_rx = firfilt_crcf_create_kaiser(2*k*m+1, bw, 60.0f, 0.0f); firfilt_crcf_set_scale(decim_rx, 2.0f * bw); break; case TXFILT_RCOS_FULL: if (M==2) { decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k,m,0.5f,0); firfilt_crcf_set_scale(decim_rx, 1.33f / (float)k); } else { decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k/2,2*m,0.9f,0); firfilt_crcf_set_scale(decim_rx, 3.25f / (float)k); } break; case TXFILT_RCOS_HALF: if (M==2) { decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k,m,0.3f,0); firfilt_crcf_set_scale(decim_rx, 1.10f / (float)k); } else { decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k/2,2*m,0.27f,0); firfilt_crcf_set_scale(decim_rx, 2.90f / (float)k); } break; case TXFILT_GMSK: bw = 0.5f / (float)k; // TODO: figure out beta value here beta = (M == 2) ? 0.8*gmsk_bt : 1.0*gmsk_bt; decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k,m,beta,0); firfilt_crcf_set_scale(decim_rx, 2.0f * bw); break; default: fprintf(stderr,"error: %s, invalid tx filter type\n", argv[0]); exit(1); } printf("bw = %f\n", bw); // run receiver unsigned int n=0; unsigned int num_errors = 0; unsigned int num_symbols_checked = 0; float complex z_prime = 0.0f; for (i=0; i<num_samples; i++) { // push through filter firfilt_crcf_push(decim_rx, y[i]); firfilt_crcf_execute(decim_rx, &z[i]); // decimate output if ( (i%k)==0 ) { // compute instantaneous frequency scaled by modulation index float phi_hat = cargf(conjf(z_prime) * z[i]) / (h * M_PI); // estimate transmitted symbol float v = (phi_hat + (M-1.0))*0.5f; unsigned int sym_out = ((int) roundf(v)) % M; // save current point z_prime = z[i]; // print result to screen printf("%3u : %12.8f + j%12.8f, <f=%8.4f : %8.4f> (%1u)", n, crealf(z[i]), cimagf(z[i]), phi_hat, v, sym_out); if (n >= m+tx_delay) { num_errors += (sym_out == sym_in[n-m-tx_delay]) ? 0 : 1; num_symbols_checked++; printf(" (%1u)\n", sym_in[n-m-tx_delay]); } else { printf("\n"); } n++; } } // print number of errors printf("errors : %3u / %3u\n", num_errors, num_symbols_checked); // destroy objects firinterp_rrrf_destroy(interp_tx); firfilt_crcf_destroy(decim_rx); // compute power spectral density of transmitted signal unsigned int nfft = 1024; float psd[nfft]; spgramcf periodogram = spgramcf_create_kaiser(nfft, nfft/2, 8.0f); spgramcf_estimate_psd(periodogram, y, num_samples, 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,"h = %f;\n", h); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"num_samples = %u;\n", num_samples); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"delay = %u; %% receive filter delay\n", tx_delay); fprintf(fid,"x = zeros(1,num_samples);\n"); fprintf(fid,"y = zeros(1,num_samples);\n"); fprintf(fid,"z = zeros(1,num_samples);\n"); fprintf(fid,"phi = zeros(1,num_samples);\n"); for (i=0; i<num_samples; i++) { fprintf(fid,"x(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i])); fprintf(fid,"y(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i])); fprintf(fid,"z(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(z[i]), cimagf(z[i])); fprintf(fid,"phi(%4u) = %12.8f;\n", i+1, phi[i]); } // save PSD fprintf(fid,"psd = zeros(1,nfft);\n"); for (i=0; i<nfft; i++) fprintf(fid,"psd(%4u) = %12.8f;\n", i+1, psd[i]); fprintf(fid,"t=[0:(num_samples-1)]/k;\n"); fprintf(fid,"i = 1:k:num_samples;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(3,4,1:3);\n"); fprintf(fid," plot(t,real(x),'-', t(i),real(x(i)),'bs','MarkerSize',4,...\n"); fprintf(fid," t,imag(x),'-', t(i),imag(x(i)),'gs','MarkerSize',4);\n"); fprintf(fid," axis([0 num_symbols -1.2 1.2]);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('x(t)');\n"); fprintf(fid," grid on;\n"); fprintf(fid,"subplot(3,4,5:7);\n"); fprintf(fid," plot(t-delay,real(z),'-', t(i)-delay,real(z(i)),'bs','MarkerSize',4,...\n"); fprintf(fid," t-delay,imag(z),'-', t(i)-delay,imag(z(i)),'gs','MarkerSize',4);\n"); fprintf(fid," axis([0 num_symbols -1.2 1.2]);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('\"matched\" filter output');\n"); fprintf(fid," grid on;\n"); // plot I/Q constellations fprintf(fid,"subplot(3,4,4);\n"); fprintf(fid," plot(real(y),imag(y),'-',real(y(i)),imag(y(i)),'rs','MarkerSize',3);\n"); fprintf(fid," xlabel('I');\n"); fprintf(fid," ylabel('Q');\n"); fprintf(fid," axis([-1 1 -1 1]*1.2);\n"); fprintf(fid," axis square;\n"); fprintf(fid," grid on;\n"); fprintf(fid,"subplot(3,4,8);\n"); fprintf(fid," plot(real(z),imag(z),'-',real(z(i)),imag(z(i)),'rs','MarkerSize',3);\n"); fprintf(fid," xlabel('I');\n"); fprintf(fid," ylabel('Q');\n"); fprintf(fid," axis([-1 1 -1 1]*1.2);\n"); fprintf(fid," axis square;\n"); fprintf(fid," grid on;\n"); // plot PSD fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"subplot(3,4,9:12);\n"); fprintf(fid," plot(f,psd,'LineWidth',1.5);\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"); #if 0 fprintf(fid,"figure;\n"); fprintf(fid," %% compute instantaneous received frequency\n"); fprintf(fid," freq_rx = arg( conj(z(:)) .* circshift(z(:),-1) )';\n"); fprintf(fid," freq_rx(1:(k*delay)) = 0;\n"); fprintf(fid," freq_rx(end) = 0;\n"); fprintf(fid," %% compute instantaneous tx/rx phase\n"); if (tx_filter_type == TXFILT_SQUARE) { fprintf(fid," theta_tx = filter([0 1],[1 -1],phi)/(h*pi);\n"); fprintf(fid," theta_rx = filter([0 1],[1 -1],freq_rx)/(h*pi);\n"); } else { fprintf(fid," theta_tx = filter([0.5 0.5],[1 -1],phi)/(h*pi);\n"); fprintf(fid," theta_rx = filter([0.5 0.5],[1 -1],freq_rx)/(h*pi);\n"); } fprintf(fid," %% plot instantaneous tx/rx phase\n"); fprintf(fid," plot(t, theta_tx,'-b', t(i), theta_tx(i),'sb',...\n"); fprintf(fid," t-delay,theta_rx,'-r', t(i)-delay,theta_rx(i),'sr');\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('instantaneous phase/(h \\pi)');\n"); fprintf(fid," legend('transmitted','syms','received/filtered','syms','location','northwest');\n"); fprintf(fid," grid on;\n"); #else // plot filter response fprintf(fid,"ht_len = %u;\n", ht_len); fprintf(fid,"ht = zeros(1,ht_len);\n"); for (i=0; i<ht_len; i++) fprintf(fid,"ht(%4u) = %12.8f;\n", i+1, ht[i]); fprintf(fid,"gt1 = filter([0.5 0.5],[1 -1],ht) / (pi*h);\n"); fprintf(fid,"gt2 = filter([0.0 1.0],[1 -1],ht) / (pi*h);\n"); fprintf(fid,"tfilt = [0:(ht_len-1)]/k - delay + 0.5;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(tfilt,ht, '-x','MarkerSize',4,...\n"); fprintf(fid," tfilt,gt1,'-x','MarkerSize',4,...\n"); fprintf(fid," tfilt,gt2,'-x','MarkerSize',4);\n"); fprintf(fid,"axis([tfilt(1) tfilt(end) -0.1 1.1]);\n"); fprintf(fid,"legend('pulse','trap. int.','rect. int.','location','northwest');\n"); fprintf(fid,"grid on;\n"); #endif fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME); // free allocated filter memory free(ht); return 0; }
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() { // symstream parameters int ftype = LIQUID_FIRFILT_ARKAISER; unsigned int k = 4; unsigned int m = 9; float beta = 0.30f; int ms = LIQUID_MODEM_QPSK; // spectral periodogram options unsigned int nfft = 2400; // spectral periodogram FFT size unsigned int num_samples = 80000; // number of samples float alpha = 0.01f; // PSD estimate bandwidth unsigned int i; // create spectral periodogram unsigned int window_size = nfft/2; // spgramcf window size spgramcf periodogram = spgramcf_create_kaiser(nfft, window_size, 10.0f); unsigned int buf_len = 1024; float complex buf[buf_len]; // create stream generator symstreamcf gen = symstreamcf_create_linear(ftype,k,m,beta,ms); unsigned int total_samples = 0; while (total_samples < num_samples) { // write samples to buffer symstreamcf_write_samples(gen, buf, buf_len); // push resulting sample through periodogram spgramcf_accumulate_psd(periodogram, buf, alpha, buf_len); // accumulated samples total_samples += buf_len; } printf("total samples: %u\n", total_samples); // compute power spectral density output float psd[nfft]; spgramcf_write_accumulation(periodogram, psd); // destroy objects symstreamcf_destroy(gen); spgramcf_destroy(periodogram); // // export output file // 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\n"); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"H = zeros(1,nfft);\n"); for (i=0; i<nfft; i++) fprintf(fid,"H(%6u) = %12.4e;\n", i+1, psd[i]); fprintf(fid,"figure;\n"); fprintf(fid,"plot(f, H, '-', 'LineWidth',1.5);\n"); fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid,"ylabel('Power Spectral Density [dB]');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([-0.5 0.5 -120 20]);\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int k = 2; // samples per symbol unsigned int m = 7; // filter delay (symbols) float beta = 0.25f; // filter excess bandwidth factor unsigned int num_symbols = 4000; // number of data symbols unsigned int hc_len = 5; // 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.00f; // carrier frequency offset [radians/sample] float phi = 2.1f; // carrier phase offset [radians] modulation_scheme ms = LIQUID_MODEM_QPSK; int dopt; while ((dopt = getopt(argc,argv,"hk:m:b:H:n:s:w: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 'H': hc_len = atoi(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'w': bandwidth = atof(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; // derived/fixed values unsigned int nx = num_symbols*k; unsigned int ny = (unsigned int) ceilf(rate * nx) + 64; float complex x[nx]; // input (interpolated) samples float complex y[ny]; // channel output samples float complex sym_out[num_symbols + 64];// synchronized symbols // // generate input sequence using symbol stream generator // symstreamcf gen = symstreamcf_create_linear(LIQUID_FIRFILT_ARKAISER,k,m,beta,ms); symstreamcf_write_samples(gen, x, nx); symstreamcf_destroy(gen); // create channel channel_cccf channel = channel_cccf_create(); // add channel impairments 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_shadowing (channel, 1.0f, 0.1f); channel_cccf_add_resamp (channel, 0.0f, rate); // print channel internals channel_cccf_print(channel); // apply channel to input signal channel_cccf_execute(channel, x, nx, y, &ny); // destroy channel channel_cccf_destroy(channel); // // create and run symbol synchronizer // symtrack_cccf symtrack = symtrack_cccf_create(LIQUID_FIRFILT_RRC,k,m,beta,ms); // set tracking bandwidth symtrack_cccf_set_bandwidth(symtrack,0.05f); unsigned int num_symbols_sync = 0; symtrack_cccf_execute_block(symtrack, y, ny, sym_out, &num_symbols_sync); symtrack_cccf_destroy(symtrack); // print results printf("symbols in : %u\n", num_symbols); printf("symbols out : %u\n", num_symbols_sync); // estimate spectrum unsigned int nfft = 1200; float psd[nfft]; spgramcf periodogram = spgramcf_create_kaiser(nfft, nfft/2, 8.0f); spgramcf_estimate_psd(periodogram, y, ny, psd); spgramcf_destroy(periodogram); // // export output file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s, auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"close all;\nclear all;\n\n"); fprintf(fid,"num_symbols=%u;\n",num_symbols_sync); for (i=0; i<num_symbols_sync; i++) fprintf(fid,"z(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(sym_out[i]), cimagf(sym_out[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,"iz0 = 1:round(length(z)*0.5);\n"); fprintf(fid,"iz1 = round(length(z)*0.5):length(z);\n"); fprintf(fid,"figure('Color','white','position',[500 500 800 800]);\n"); fprintf(fid,"subplot(2,2,1);\n"); fprintf(fid,"plot(real(z(iz0)),imag(z(iz0)),'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('First 50%% of symbols');\n"); fprintf(fid,"subplot(2,2,2);\n"); fprintf(fid," plot(real(z(iz1)),imag(z(iz1)),'x','MarkerSize',4);\n"); fprintf(fid," axis square;\n"); fprintf(fid," grid on;\n"); fprintf(fid," axis([-1 1 -1 1]*1.5);\n"); fprintf(fid," xlabel('In-phase');\n"); fprintf(fid," ylabel('Quadrature');\n"); fprintf(fid," title('Last 50%% of symbols');\n"); fprintf(fid,"subplot(2,2,3:4);\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); // clean it up printf("done.\n"); return 0; }