// Helper function to keep code base small void matrixf_linsolve_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n) { // normalize number of iterations // time ~ _n ^ 2 *_num_iterations /= _n * _n; if (*_num_iterations < 1) *_num_iterations = 1; unsigned long int i; float A[_n*_n]; float b[_n]; float x[_n]; for (i=0; i<_n*_n; i++) A[i] = randnf(); for (i=0; i<_n; i++) b[i] = randnf(); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { matrixf_linsolve(A,_n,b,x,NULL); matrixf_linsolve(A,_n,b,x,NULL); matrixf_linsolve(A,_n,b,x,NULL); matrixf_linsolve(A,_n,b,x,NULL); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; }
// Helper function to keep code base small void polyf_fit_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _Q, unsigned int _N) { // normalize number of iterations // time ~ 0.2953 + 0.03381 * _N *_num_iterations /= 0.2953 + 0.03381 * _N; if (*_num_iterations < 1) *_num_iterations = 1; float p[_Q+1]; float x[_N]; float y[_N]; unsigned int i; for (i=0; i<_N; i++) { x[i] = randnf(); y[i] = randnf(); } // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { polyf_fit(x,y,_N, p,_Q+1); polyf_fit(x,y,_N, p,_Q+1); polyf_fit(x,y,_N, p,_Q+1); polyf_fit(x,y,_N, p,_Q+1); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; }
// Helper function to keep code base small void matrixf_mul_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // normalize number of iterations // time ~ _n ^ 2 *_num_iterations /= _n * _n; if (*_num_iterations < 1) *_num_iterations = 1; float a[_n*_n]; float b[_n*_n]; float c[_n*_n]; unsigned int i; for (i=0; i<_n*_n; i++) { a[i] = randnf(); b[i] = randnf(); } // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { matrixf_mul(a,_n,_n, b,_n,_n, c,_n,_n); matrixf_mul(a,_n,_n, b,_n,_n, c,_n,_n); matrixf_mul(a,_n,_n, b,_n,_n, c,_n,_n); matrixf_mul(a,_n,_n, b,_n,_n, c,_n,_n); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; }
// helper function (compare structured object to ordinal computation) void runtest_dotprod_cccf(unsigned int _n) { float tol = 1e-3; float complex h[_n]; float complex x[_n]; // generate random coefficients unsigned int i; for (i=0; i<_n; i++) { h[i] = randnf() + randnf() * _Complex_I; x[i] = randnf() + randnf() * _Complex_I; } // compute expected value (ordinal computation) float complex y_test; dotprod_cccf_run(h, x, _n, &y_test); // create and run dot product object float complex y; dotprod_cccf dp; dp = dotprod_cccf_create(h,_n); dotprod_cccf_execute(dp, x, &y); dotprod_cccf_destroy(dp); // print results if (liquid_autotest_verbose) { printf(" dotprod-cccf-%-4u : %12.8f + j%12.8f (expected %12.8f + j%12.8f)\n", _n, crealf(y), cimagf(y), crealf(y_test), cimagf(y_test)); } // validate result CONTEND_DELTA(crealf(y), crealf(y_test), tol); CONTEND_DELTA(cimagf(y), cimagf(y_test), tol); }
// Helper function to keep code base small void benchmark_framesync64( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { *_num_iterations /= 128; unsigned long int i; framegen64 fg = framegen64_create(); framegen64_print(fg); // frame data unsigned char header[8] = {0, 1, 2, 3, 4, 5, 6, 7}; unsigned char payload[64]; // initialize payload for (i=0; i<64; i++) payload[i] = rand() & 0xff; framedata fd = {0, 0, 0}; // create framesync64 object framesync64 fs = framesync64_create(callback,(void*)&fd); framesync64_print(fs); // generate the frame //unsigned int frame_len = framegen64_getframelen(fg); unsigned int frame_len = LIQUID_FRAME64_LEN; float complex frame[frame_len]; framegen64_execute(fg, header, payload, frame); // add some noise for (i=0; i<frame_len; i++) frame[i] += 0.01f*(randnf() + _Complex_I*randnf()) * M_SQRT1_2; // // start trials // getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { framesync64_execute(fs, frame, frame_len); } getrusage(RUSAGE_SELF, _finish); fd.num_frames_tx = *_num_iterations; printf(" frames detected/valid/transmitted : %6u / %6u / %6u\n", fd.num_frames_detected, fd.num_frames_valid, fd.num_frames_tx); framegen64_destroy(fg); framesync64_destroy(fs); }
void benchmark_gmskmodem_demodulate(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { // options unsigned int k=2; // filter samples/symbol unsigned int m=3; // filter delay (symbols) float BT=0.3f; // bandwidth-time product // create modem object gmskdem demod = gmskdem_create(k, m, BT); float complex x[k]; unsigned int symbol_out = 0; unsigned long int i; for (i=0; i<k; i++) x[i] = randnf()*cexpf(_Complex_I*2*M_PI*randf()); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { gmskdem_demodulate(demod, x, &symbol_out); gmskdem_demodulate(demod, x, &symbol_out); gmskdem_demodulate(demod, x, &symbol_out); gmskdem_demodulate(demod, x, &symbol_out); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; // destroy modem objects gmskdem_destroy(demod); }
// Helper function to keep code base small void eqrls_cccf_train_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _h_len) { // scale number of iterations appropriately // log(cycles/trial) ~ 5.57 + 2.74*log(_h_len) *_num_iterations *= 2400; *_num_iterations /= (unsigned int) expf(5.57f + 2.64f*logf(_h_len)); *_num_iterations = (*_num_iterations < 4) ? 4 : *_num_iterations; eqrls_cccf eq = eqrls_cccf_create(NULL,_h_len); unsigned long int i; // set up initial arrays to 'randomize' inputs/outputs float complex y[11]; for (i=0; i<11; i++) y[i] = randnf() + _Complex_I*randnf(); float complex d[13]; for (i=0; i<13; i++) d[i] = randnf() + _Complex_I*randnf(); unsigned int iy=0; unsigned int id=0; float complex z; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { eqrls_cccf_push(eq, y[iy]); // push input into equalizer eqrls_cccf_execute(eq, &z); // compute equalizer output eqrls_cccf_step(eq, d[id], z); // step equalizer internals // update counters iy = (iy+1)%11; id = (id+1)%13; } getrusage(RUSAGE_SELF, _finish); eqrls_cccf_destroy(eq); }
// Helper function to keep code base small void dotprod_crcf_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // normalize number of iterations *_num_iterations *= 100; *_num_iterations /= _n; if (*_num_iterations < 1) *_num_iterations = 1; float complex x[_n]; float h[_n]; float complex y[8]; unsigned int i; for (i=0; i<_n; i++) { x[i] = randnf() + _Complex_I*randnf(); h[i] = randnf(); } // create dotprod structure; dotprod_crcf dp = dotprod_crcf_create(h,_n); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { dotprod_crcf_execute(dp, x, &y[0]); dotprod_crcf_execute(dp, x, &y[1]); dotprod_crcf_execute(dp, x, &y[2]); dotprod_crcf_execute(dp, x, &y[3]); dotprod_crcf_execute(dp, x, &y[4]); dotprod_crcf_execute(dp, x, &y[5]); dotprod_crcf_execute(dp, x, &y[6]); dotprod_crcf_execute(dp, x, &y[7]); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 8; // clean up objects dotprod_crcf_destroy(dp); }
// Helper function to keep code base small void firfilt_crcf_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // adjust number of iterations: // cycles/trial ~ 107 + 4.3*_n *_num_iterations *= 1000; *_num_iterations /= (unsigned int)(107+4.3*_n); // generate coefficients float h[_n]; unsigned long int i; for (i=0; i<_n; i++) h[i] = randnf(); // create filter object firfilt_crcf f = firfilt_crcf_create(h,_n); // generate input vector float complex x[4]; for (i=0; i<4; i++) x[i] = randnf() + _Complex_I*randnf(); // output vector float complex y[4]; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { firfilt_crcf_push(f, x[0]); firfilt_crcf_execute(f, &y[0]); firfilt_crcf_push(f, x[1]); firfilt_crcf_execute(f, &y[1]); firfilt_crcf_push(f, x[2]); firfilt_crcf_execute(f, &y[2]); firfilt_crcf_push(f, x[3]); firfilt_crcf_execute(f, &y[3]); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; firfilt_crcf_destroy(f); }
int main() { // options unsigned int order=4; // filter order float fc=0.1f; // cutoff frequency float f0=0.25f; // center frequency (bandpass|bandstop) float Ap=1.0f; // pass-band ripple [dB] float As=40.0f; // stop-band attenuation [dB] liquid_iirdes_filtertype ftype = LIQUID_IIRDES_ELLIP; liquid_iirdes_bandtype btype = LIQUID_IIRDES_BANDPASS; liquid_iirdes_format format = LIQUID_IIRDES_SOS; // CREATE filter object (and print to stdout) iirfilt_crcf myfilter; myfilter = iirfilt_crcf_create_prototype(ftype, btype, format, order, fc, f0, Ap, As); iirfilt_crcf_print(myfilter); // allocate memory for data arrays unsigned int n=128; // number of samples float complex x[n]; // input samples array float complex y[n]; // output samples array // run filter unsigned int i; for (i=0; i<n; i++) { // initialize input x[i] = randnf() + _Complex_I*randnf(); // EXECUTE filter (repeat as many times as desired) iirfilt_crcf_execute(myfilter, x[i], &y[i]); } // DESTROY filter object iirfilt_crcf_destroy(myfilter); }
// benchmark regular frame synchronizer with noise; essentially test // complexity when no signal is present void benchmark_gmskframesync_noise(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations) { *_num_iterations /= 400; unsigned long int i; // options float SNRdB = 20.0f; // SNR // derived values float nstd = powf(10.0f, -SNRdB/20.0f); // create frame synchronizer gmskframesync fs = gmskframesync_create(NULL, NULL); // allocate memory for noise buffer and initialize unsigned int num_samples = 1024; float complex y[num_samples]; for (i=0; i<num_samples; i++) y[i] = nstd*(randnf() + randnf()*_Complex_I)*M_SQRT1_2; // // start trials // getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { // push samples through synchronizer gmskframesync_execute(fs, y, num_samples); } getrusage(RUSAGE_SELF, _finish); // scale result by number of samples in buffer *_num_iterations *= num_samples; // destroy framing objects gmskframesync_destroy(fs); }
// Helper function to keep code base small void fft_runbench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _nfft, int _direction) { // initialize arrays, plan float complex * x = (float complex *) malloc(_nfft*sizeof(float complex)); float complex * y = (float complex *) malloc(_nfft*sizeof(float complex)); int _method = 0; fftplan q = fft_create_plan(_nfft, x, y, _direction, _method); unsigned long int i; // initialize input with random values for (i=0; i<_nfft; i++) x[i] = randnf() + randnf()*_Complex_I; // scale number of iterations to keep execution time // relatively linear *_num_iterations /= _nfft; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { fft_execute(q); fft_execute(q); fft_execute(q); fft_execute(q); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; fft_destroy_plan(q); free(x); free(y); }
// // Test RSSI on noise input // void autotest_agc_crcf_rssi_noise() { // set paramaters float gamma = -30.0f; // nominal signal level [dB] float bt = 0.01f; // agc bandwidth float tol = 0.2f; // error tolerance [dB] // signal properties float nstd = powf(10.0f, gamma/20); // create AGC object and initialize agc_crcf q = agc_crcf_create(); agc_crcf_set_bandwidth(q, bt); unsigned int i; float complex x, y; for (i=0; i<2000; i++) { // generate sample (circular complex noise) x = nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2; // execute agc agc_crcf_execute(q, x, &y); } // get received signal strength indication float rssi = agc_crcf_get_rssi(q); if (liquid_autotest_verbose) printf("gamma : %12.8f, rssi : %12.8f\n", gamma, rssi); // Check results CONTEND_DELTA( rssi, gamma, tol ); // destroy agc object agc_crcf_destroy(q); }
int main() { // options unsigned int nfft = 64; // transform size unsigned int num_frames = 200; // total number of frames unsigned int msdelay = 50; // delay between transforms [ms] float noise_floor = -40.0f; // noise floor // initialize objects asgramf q = asgramf_create(nfft); asgramf_set_scale(q, noise_floor+15.0f, 5.0f); unsigned int i; unsigned int n; float theta = 0.0f; // current instantaneous phase float dtheta = 0.0f; // current instantaneous frequency float phi = 0.0f; // phase of sinusoidal frequency drift float dphi = 0.003f; // frequency of sinusoidal frequency drift float nstd = powf(10.0f,noise_floor/20.0f); // noise standard deviation for (n=0; n<num_frames; n++) { // generate a frame of data samples for (i=0; i<nfft; i++) { // cosine wave of time-varying frequency with noise float x = cosf(theta) + nstd*randnf(); // push sample into spectrogram object asgramf_push(q, x); // adjust frequency and phase theta += dtheta; dtheta = 0.5f*M_PI + 0.4f*M_PI*sinf(phi) * hamming(n, num_frames); phi += dphi; } // print the spectrogram to stdout asgramf_print(q); // sleep for some time before generating the next frame usleep(msdelay*1000); } asgramf_destroy(q); printf("done.\n"); return 0; }
// // AUTOTEST: polycf_findroots (random roots) // void xautotest_polycf_findroots_rand() { unsigned int n=5; float tol=1e-4f; float complex p[n]; float complex roots[n-1]; float complex p_hat[n]; unsigned int i; for (i=0; i<n; i++) p[i] = i == n-1 ? 1 : 3.0f * randnf(); polycf_findroots(p,n,roots); float complex roots_hat[n-1]; // convert form... for (i=0; i<n-1; i++) roots_hat[i] = -roots[i]; polycf_expandroots(roots_hat,n-1,p_hat); if (liquid_autotest_verbose) { printf("poly:\n"); for (i=0; i<n; i++) printf(" p[%3u] = %12.8f + j*%12.8f\n", i, crealf(p[i]), cimagf(p[i])); printf("roots:\n"); for (i=0; i<n-1; i++) printf(" r[%3u] = %12.8f + j*%12.8f\n", i, crealf(roots[i]), cimagf(roots[i])); printf("poly (expanded roots):\n"); for (i=0; i<n; i++) printf(" p[%3u] = %12.8f + j*%12.8f\n", i, crealf(p_hat[i]), cimagf(p_hat[i])); } for (i=0; i<n; i++) { CONTEND_DELTA(crealf(p[i]), crealf(p_hat[i]), tol); CONTEND_DELTA(cimagf(p[i]), cimagf(p_hat[i]), tol); } }
// Helper function to keep code base small void fft_r2r_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n, int _kind) { // initialize arrays, plan float x[_n], y[_n]; int _flags = 0; fftplan p = fft_create_plan_r2r_1d(_n, x, y, _kind, _flags); unsigned long int i; // initialize input with random values for (i=0; i<_n; i++) x[i] = randnf(); // scale number of iterations to keep execution time // relatively linear *_num_iterations /= _n * _n; *_num_iterations *= 10; *_num_iterations += 1; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { fft_execute(p); fft_execute(p); fft_execute(p); fft_execute(p); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; fft_destroy_plan(p); }
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(int argc, char*argv[]) { // options float noise_floor= -40.0f; // noise floor [dB] float SNRdB = 20.0f; // signal-to-noise ratio [dB] float bt = 0.05f; // loop bandwidth unsigned int num_symbols= 100; // number of iterations unsigned int d = 5; // print every d iterations unsigned int k = 2; // interpolation factor (samples/symbol) unsigned int m = 3; // filter delay (symbols) float beta = 0.3f; // filter excess bandwidth factor float dt = 0.0f; // filter fractional sample delay // derived values unsigned int num_samples=num_symbols*k; float gamma = powf(10.0f, (SNRdB+noise_floor)/20.0f); // channel gain float nstd = powf(10.0f, noise_floor / 20.0f); // arrays float complex x[num_samples]; float complex y[num_samples]; float rssi[num_samples]; // create objects modem mod = modem_create(LIQUID_MODEM_QPSK); firinterp_crcf interp = firinterp_crcf_create_prototype(LIQUID_FIRFILT_RRC,k,m,beta,dt); agc_crcf p = agc_crcf_create(); agc_crcf_set_bandwidth(p, bt); unsigned int i; // print info printf("automatic gain control // loop bandwidth: %4.2e\n",bt); unsigned int sym; float complex s; for (i=0; i<num_symbols; i++) { // generate random symbol sym = modem_gen_rand_sym(mod); modem_modulate(mod, sym, &s); s *= gamma; firinterp_crcf_execute(interp, s, &x[i*k]); } // add noise for (i=0; i<num_samples; i++) x[i] += nstd*(randnf() + _Complex_I*randnf()) * M_SQRT1_2; // run agc for (i=0; i<num_samples; i++) { agc_crcf_execute(p, x[i], &y[i]); rssi[i] = agc_crcf_get_rssi(p); } // destroy objects modem_destroy(mod); agc_crcf_destroy(p); firinterp_crcf_destroy(interp); // print results to screen printf("received signal strength indication (rssi):\n"); for (i=0; i<num_samples; i+=d) { printf("%4u : %8.2f\n", i, rssi[i]); } // // export results // FILE* fid = fopen(OUTPUT_FILENAME,"w"); if (!fid) { fprintf(stderr,"error: %s, could not open '%s' for writing\n", argv[0], OUTPUT_FILENAME); exit(1); } fprintf(fid,"%% %s: auto-generated file\n\n",OUTPUT_FILENAME); fprintf(fid,"n = %u;\n", num_samples); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); for (i=0; i<num_samples; i++) { fprintf(fid," x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i])); fprintf(fid," y(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i])); fprintf(fid,"rssi(%4u) = %12.4e;\n", i+1, rssi[i]); } fprintf(fid,"\n\n"); fprintf(fid,"n = length(x);\n"); fprintf(fid,"t = 0:(n-1);\n"); fprintf(fid,"figure('position',[100 100 800 600]);\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(t,rssi,'-k','LineWidth',2);\n"); fprintf(fid," xlabel('sample index');\n"); fprintf(fid," ylabel('rssi [dB]');\n"); fprintf(fid," grid on;\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(t,real(y),t,imag(y));\n"); fprintf(fid," xlabel('sample index');\n"); fprintf(fid," ylabel('agc output');\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[]) { srand(time(NULL)); // options unsigned int k=2; // filter samples/symbol unsigned int m=4; // filter delay (symbols) float beta=0.3f; // bandwidth-time product float dt = 0.0f; // fractional sample timing offset unsigned int num_sync_symbols = 64; // number of data symbols float SNRdB = 30.0f; // signal-to-noise ratio [dB] float dphi = 0.0f; // carrier frequency offset float phi = 0.0f; // carrier phase offset unsigned int num_delay_symbols = 12; unsigned int num_dphi_hat = 21; // number of frequency offset estimates float dphi_hat_step = 0.01f; // frequency offset step size int dopt; while ((dopt = getopt(argc,argv,"uhk:m:n:b:t:F:P:s:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'n': num_sync_symbols = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 't': dt = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 'P': phi = atof(optarg); break; case 's': SNRdB = atof(optarg); break; default: exit(1); } } unsigned int i; // validate input if (beta <= 0.0f || beta >= 1.0f) { fprintf(stderr,"error: %s, bandwidth-time product must be in (0,1)\n", argv[0]); exit(1); } else if (dt < -0.5 || dt > 0.5) { fprintf(stderr,"error: %s, fractional sample offset must be in (0,1)\n", argv[0]); exit(1); } // derived values unsigned int num_symbols = num_delay_symbols + num_sync_symbols + 2*m; unsigned int num_samples = k*num_symbols; unsigned int num_sync_samples = k*num_sync_symbols; float nstd = powf(10.0f, -SNRdB/20.0f); // arrays float complex seq[num_sync_symbols]; // data sequence (symbols) float complex s0[num_sync_samples]; // data sequence (interpolated samples) float complex x[num_samples]; // transmitted signal float complex y[num_samples]; // received signal float rxy[num_dphi_hat][num_samples]; // pre-demod output matrix // generate sequence for (i=0; i<num_sync_symbols; i++) { float sym_i = rand() % 2 ? M_SQRT1_2 : -M_SQRT1_2; float sym_q = rand() % 2 ? M_SQRT1_2 : -M_SQRT1_2; seq[i] = sym_i + _Complex_I*sym_q; } // create interpolated sequence, compensating for filter delay firinterp_crcf interp_seq = firinterp_crcf_create_rnyquist(LIQUID_RNYQUIST_RRC,k,m,beta,0.0f); for (i=0; i<num_sync_symbols+m; i++) { if (i < m) firinterp_crcf_execute(interp_seq, seq[i], &s0[0]); else if (i < num_sync_symbols) firinterp_crcf_execute(interp_seq, seq[i], &s0[k*(i-m)]); else firinterp_crcf_execute(interp_seq, 0, &s0[k*(i-m)]); } firinterp_crcf_destroy(interp_seq); // compute g = E{ |s0|^2 } float g = 0.0f; for (i=0; i<num_sync_samples; i++) g += crealf( s0[i]*conjf(s0[i]) ); // create transmit interpolator and generate sequence firinterp_crcf interp_tx = firinterp_crcf_create_rnyquist(LIQUID_RNYQUIST_RRC,k,m,beta,dt); unsigned int n=0; for (i=0; i<num_delay_symbols; i++) { firinterp_crcf_execute(interp_tx, 0, &x[k*n]); n++; } for (i=0; i<num_sync_symbols; i++) { firinterp_crcf_execute(interp_tx, seq[i], &x[k*n]); n++; } for (i=0; i<2*m; i++) { firinterp_crcf_execute(interp_tx, 0, &x[k*n]); n++; } assert(n==num_symbols); firinterp_crcf_destroy(interp_tx); // add channel impairments for (i=0; i<num_samples; i++) { y[i] = x[i]*cexp(_Complex_I*(dphi*i + phi)) + nstd*( randnf() + _Complex_I*randnf() ); } float complex z; // filter output sample for (n=0; n<num_dphi_hat; n++) { float dphi_hat = ((float)n - 0.5*(float)(num_dphi_hat-1)) * dphi_hat_step; printf(" dphi_hat : %12.8f\n", dphi_hat); // create flipped, conjugated coefficients float complex s1[num_sync_samples]; for (i=0; i<num_sync_samples; i++) s1[i] = conjf( s0[num_sync_samples-i-1]*cexpf(_Complex_I*(dphi_hat*i)) ); // create matched filter and detect signal firfilt_cccf fsync = firfilt_cccf_create(s1, num_sync_samples); for (i=0; i<num_samples; i++) { firfilt_cccf_push(fsync, y[i]); firfilt_cccf_execute(fsync, &z); rxy[n][i] = cabsf(z) / g; } // destroy filter firfilt_cccf_destroy(fsync); } // print results //printf("rxy (max) : %12.8f\n", rxy_max); // // 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,"beta = %f;\n", beta); fprintf(fid,"num_sync_symbols = %u;\n", num_sync_symbols); fprintf(fid,"num_sync_samples = k*num_sync_symbols;\n"); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"num_samples = %u;\n", num_samples); fprintf(fid,"num_dphi_hat = %u;\n", num_dphi_hat); fprintf(fid,"dphi_hat_step = %f;\n", dphi_hat_step); // save sequence symbols fprintf(fid,"seq = zeros(1,num_sync_symbols);\n"); for (i=0; i<num_sync_symbols; i++) fprintf(fid,"seq(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(seq[i]), cimagf(seq[i])); // save interpolated sequence fprintf(fid,"s = zeros(1,num_sync_samples);\n"); for (i=0; i<num_sync_samples; i++) fprintf(fid,"s(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(s0[i]), cimagf(s0[i])); 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(%6u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i])); fprintf(fid,"y(%6u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i])); } // save cross-correlation output fprintf(fid,"rxy = zeros(num_dphi_hat,num_samples);\n"); for (n=0; n<num_dphi_hat; n++) { for (i=0; i<num_samples; i++) { fprintf(fid,"rxy(%6u,%6u) = %12.8f;\n", n+1, i+1, rxy[n][i]); } } fprintf(fid,"t=[0:(num_samples-1)]/k;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(1:length(s),real(s), 1:length(s),imag(s));\n"); fprintf(fid,"dphi_hat = ( [0:(num_dphi_hat-1)] - (num_dphi_hat-1)/2 ) * dphi_hat_step;\n"); fprintf(fid,"mesh(dphi_hat, t, rxy');\n"); #if 0 fprintf(fid,"z = abs( z );\n"); fprintf(fid,"[zmax i] = max(z);\n"); fprintf(fid,"plot(1:length(z),z,'-x');\n"); fprintf(fid,"axis([(i-8*k) (i+8*k) 0 zmax*1.2]);\n"); fprintf(fid,"grid on\n"); #endif fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME); return 0; }
int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int k=2; // samples/symbol unsigned int m=3; // filter delay (symbols) float beta=0.9f; // filter excess bandwidth factor unsigned int order=2; unsigned int num_symbols=1024; float SNRdB = 30.0f; float bt=0.02f; // loop filter bandwidth float tau=0.2f; // fractional symbol offset float r = 1.00f; // resampled rate // use random data or 101010 phasing pattern int random_data=1; int dopt; while ((dopt = getopt(argc,argv,"uhk:m:b:o:s:w:n:t:r:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'o': order = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'w': bt = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 't': tau = atof(optarg); break; case 'r': r = atof(optarg); break; default: exit(1); } } // validate input if (k < 2) { fprintf(stderr,"error: k (samples/symbol) must be at least 2\n"); return 1; } else if (m < 1) { fprintf(stderr,"error: m (filter delay) must be greater than 0\n"); return 1; } else if (beta <= 0.0f || beta > 1.0f) { fprintf(stderr,"error: beta (excess bandwidth factor) must be in (0,1]\n"); return 1; } else if (order == 0) { fprintf(stderr,"error: number of polyphase filters must be greater than 0\n"); return 1; } else if (bt <= 0.0f) { fprintf(stderr,"error: timing PLL bandwidth must be greater than 0\n"); return 1; } else if (num_symbols == 0) { fprintf(stderr,"error: number of symbols must be greater than 0\n"); return 1; } else if (tau < -1.0f || tau > 1.0f) { fprintf(stderr,"error: timing phase offset must be in [-1,1]\n"); return 1; } else if (r < 0.5f || r > 2.0f) { fprintf(stderr,"error: timing frequency offset must be in [0.5,2]\n"); return 1; } // compute delay while (tau < 0) tau += 1.0f; // ensure positive tau float g = k*tau; // number of samples offset int ds=floorf(g); // additional symbol delay float dt = (g - (float)ds); // fractional sample offset unsigned int i, n=0; unsigned int num_samples = k*num_symbols; unsigned int num_samples_resamp = (unsigned int) ceilf(num_samples*r*1.1f) + 4; float complex s[num_symbols]; // data symbols float complex x[num_samples]; // interpolated samples float complex y[num_samples_resamp]; // resampled data (resamp_crcf) float complex z[num_symbols + 64]; // synchronized symbols for (i=0; i<num_symbols; i++) { if (random_data) { // random signal (QPSK) s[i] = cexpf(_Complex_I*0.5f*M_PI*((rand() % 4) + 0.5f)); } else { s[i] = (i%2) ? 1.0f : -1.0f; // 101010 phasing pattern } } // // create and run interpolator // // design interpolating filter unsigned int h_len = 2*k*m + 1; float h[h_len]; liquid_firdes_rcos(k,m,beta,dt,h); interp_crcf q = interp_crcf_create(k,h,h_len); for (i=0; i<num_symbols; i++) { interp_crcf_execute(q, s[i], &x[n]); n+=k; } assert(n == num_samples); interp_crcf_destroy(q); // // run resampler // unsigned int resamp_len = 10*k; // resampling filter semi-length (filter delay) float resamp_bw = 0.45f; // resampling filter bandwidth float resamp_As = 60.0f; // resampling filter stop-band attenuation unsigned int resamp_npfb = 64; // number of filters in bank resamp_crcf f = resamp_crcf_create(r, resamp_len, resamp_bw, resamp_As, resamp_npfb); unsigned int num_samples_resampled = 0; unsigned int num_written; for (i=0; i<num_samples; i++) { #if 0 // bypass arbitrary resampler y[i] = x[i]; num_samples_resampled = num_samples; #else // TODO : compensate for resampler filter delay resamp_crcf_execute(f, x[i], &y[num_samples_resampled], &num_written); num_samples_resampled += num_written; #endif } resamp_crcf_destroy(f); // // add noise // float nstd = powf(10.0f, -SNRdB/20.0f) / sqrtf(2.0f); for (i=0; i<num_samples_resampled; i++) y[i] += nstd*(randnf() + _Complex_I*randnf()); // // create and run symbol synchronizer // // create symbol synchronizer symsynclp_crcf d = symsynclp_crcf_create(k, order); symsynclp_crcf_set_lf_bw(d,bt); unsigned int num_symbols_sync=0; unsigned int nn; float tau_hat[num_samples]; for (i=ds; i<num_samples_resampled; i++) { tau_hat[num_symbols_sync] = symsynclp_crcf_get_tau(d); symsynclp_crcf_execute(d, &y[i], 1, &z[num_symbols_sync], &nn); num_symbols_sync += nn; } symsynclp_crcf_destroy(d); // print last several symbols to screen printf("z(t) :\n"); for (i=num_symbols_sync-10; i<num_symbols_sync; i++) printf(" z(%2u) = %8.4f + j*%8.4f;\n", i+1, crealf(z[i]), cimagf(z[i])); // // 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,"k=%u;\n",k); fprintf(fid,"m=%u;\n",m); fprintf(fid,"beta=%12.8f;\n",beta); fprintf(fid,"order=%u;\n",order); fprintf(fid,"num_symbols=%u;\n",num_symbols); for (i=0; i<h_len; i++) fprintf(fid,"h(%3u) = %12.5f;\n", i+1, h[i]); for (i=0; i<num_symbols; i++) fprintf(fid,"s(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(s[i]), cimagf(s[i])); for (i=0; i<num_samples; i++) fprintf(fid,"x(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i])); for (i=0; i<num_samples_resampled; i++) fprintf(fid,"y(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i])); for (i=0; i<num_symbols_sync; i++) fprintf(fid,"z(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(z[i]), cimagf(z[i])); for (i=0; i<num_symbols_sync; i++) fprintf(fid,"tau_hat(%3u) = %12.8f;\n", i+1, tau_hat[i]); fprintf(fid,"\n\n"); fprintf(fid,"ms = 8; %% marker size\n"); fprintf(fid,"zp = filter(h,1,y);\n"); fprintf(fid,"figure;\nhold on;\n"); fprintf(fid,"plot([0:length(s)-1], real(s), 'ob', 'MarkerSize',ms);\n"); fprintf(fid,"plot([0:length(y)-1]/k -m, real(y), '-', 'MarkerSize',ms, 'Color',[0.8 0.8 0.8]);\n"); fprintf(fid,"plot([0:length(zp)-1]/k -k*m, real(zp/k), '-b', 'MarkerSize',ms);\n"); fprintf(fid,"plot([0:length(z)-1] -k*m+1,real(z), 'xr', 'MarkerSize',ms);\n"); fprintf(fid,"hold off;\n"); fprintf(fid,"xlabel('Symbol Index');\n"); fprintf(fid,"ylabel('Output Signal');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"legend('sym in','interp','mf','sym out',0);\n"); fprintf(fid,"t0=1:floor(0.25*length(z));\n"); fprintf(fid,"t1=ceil(0.25*length(z)):length(z);\n"); fprintf(fid,"figure;\n"); fprintf(fid,"hold on;\n"); fprintf(fid,"plot(real(z(t0)),imag(z(t0)),'x','MarkerSize',ms,'Color',[0.6 0.6 0.6]);\n"); fprintf(fid,"plot(real(z(t1)),imag(z(t1)),'x','MarkerSize',ms,'Color',[0 0.25 0.5]);\n"); fprintf(fid,"hold off;\n"); fprintf(fid,"axis square; grid on;\n"); fprintf(fid,"axis([-1 1 -1 1]*1.2);\n"); fprintf(fid,"xlabel('In-phase');\n"); fprintf(fid,"ylabel('Quadrature');\n"); fprintf(fid,"legend(['first 25%%'],['last 75%%'],1);\n"); fprintf(fid,"figure;\n"); fprintf(fid,"tt = 0:(length(tau_hat)-1);\n"); fprintf(fid,"plot(tt,tau_hat,'-k','Color',[0 0 0]);\n"); fprintf(fid,"xlabel('time');\n"); fprintf(fid,"ylabel('tau-hat');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([0 length(tau_hat) 0 1]);\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); // clean it up printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int k=2; // filter samples/symbol unsigned int m=5; // filter delay (symbols) float beta=0.3f; // bandwidth-time product float dt = 0.0f; // fractional sample timing offset unsigned int num_sync_symbols = 64; // number of synchronization symbols float SNRdB = 20.0f; // signal-to-noise ratio [dB] float dphi = 0.02f; // carrier frequency offset float phi = 2*M_PI*randf(); // carrier phase offset int dopt; while ((dopt = getopt(argc,argv,"uhk:m:n:b:t:F:t:S:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'n': num_sync_symbols = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 't': dt = atof(optarg); break; case 'S': SNRdB = atof(optarg); break; default: exit(1); } } unsigned int i; // validate input if (beta <= 0.0f || beta >= 1.0f) { fprintf(stderr,"error: %s, bandwidth-time product must be in (0,1)\n", argv[0]); exit(1); } else if (dt < -0.5f || dt > 0.5f) { fprintf(stderr,"error: %s, fractional sample offset must be in [-0.5,0.5]\n", argv[0]); exit(1); } // derived values unsigned int num_symbols = num_sync_symbols + 2*m + 10; unsigned int num_samples = k*num_symbols; float nstd = powf(10.0f, -SNRdB/20.0f); // arrays float complex seq[num_sync_symbols]; // synchronization pattern (symbols) float complex s0[k*num_sync_symbols]; // synchronization pattern (samples) float complex x[num_samples]; // transmitted signal float complex y[num_samples]; // received signal float complex rxy[num_samples]; // pre-demod correlation output float dphi_hat[num_samples]; // carrier offset estimate // create transmit/receive interpolator/decimator firinterp_crcf interp = firinterp_crcf_create_prototype(LIQUID_FIRFILT_RRC,k,m,beta,dt); // generate synchronization pattern (BPSK) and interpolate for (i=0; i<num_sync_symbols + 2*m; i++) { float complex sym = 0.0f; if (i < num_sync_symbols) { sym = rand() % 2 ? -1.0f : 1.0f; seq[i] = sym; } if (i < 2*m) firinterp_crcf_execute(interp, sym, s0); else firinterp_crcf_execute(interp, sym, &s0[k*(i-2*m)]); } // reset interpolator firinterp_crcf_reset(interp); // interpolate input for (i=0; i<num_symbols; i++) { float complex sym = i < num_sync_symbols ? seq[i] : 0.0f; firinterp_crcf_execute(interp, sym, &x[k*i]); } // push through channel for (i=0; i<num_samples; i++) y[i] = x[i]*cexpf(_Complex_I*(dphi*i + phi)) + nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2; // create cross-correlator bpresync_cccf sync = bpresync_cccf_create(s0, k*num_sync_symbols, 0.05f, 11); bpresync_cccf_print(sync); // push signal through cross-correlator float rxy_max = 0.0f; // maximum cross-correlation float dphi_est = 0.0f; // carrier frequency offset estimate int delay_est = 0; // delay estimate for (i=0; i<num_samples; i++) { // correlate bpresync_cccf_push(sync, y[i]); bpresync_cccf_execute(sync, &rxy[i], &dphi_hat[i]); // detect... if (cabsf(rxy[i]) > 0.6f) { printf("****** preamble found, rxy = %12.8f (dphi-hat: %12.8f), i=%3u ******\n", cabsf(rxy[i]), dphi_hat[i], i); } // retain maximum if (cabsf(rxy[i]) > rxy_max) { rxy_max = cabsf(rxy[i]); dphi_est = dphi_hat[i]; delay_est = (int)i - (int)2*k*m + 1; } } // destroy objects firinterp_crcf_destroy(interp); bpresync_cccf_destroy(sync); // print results printf("\n"); printf("rxy (max) : %12.8f\n", rxy_max); printf("dphi est. : %12.8f ,error=%12.8f\n", dphi_est, dphi-dphi_est); printf("delay est.: %12d ,error=%3d sample(s)\n", delay_est, k*num_sync_symbols - delay_est); printf("\n"); // // 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,"num_samples = %u;\n", num_samples); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"k = %u;\n", k); fprintf(fid,"x = zeros(1,num_samples);\n"); fprintf(fid,"y = zeros(1,num_samples);\n"); fprintf(fid,"rxy = 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,"rxy(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(rxy[i]), cimagf(rxy[i])); } fprintf(fid,"t=[0:(num_samples-1)]/k;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(t,real(y), t,imag(y));\n"); fprintf(fid," axis([0 num_symbols -2 2]);\n"); fprintf(fid," grid on;\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('received signal');\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(t,abs(rxy));\n"); fprintf(fid," axis([0 num_symbols 0 1.5]);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('correlator output');\n"); fprintf(fid," grid on;\n"); fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME); return 0; }
int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int k = 2; // samples/symbol (input) unsigned int m = 3; // filter delay (symbols) float beta = 0.5f; // filter excess bandwidth factor unsigned int num_filters = 32; // number of filters in the bank float SNRdB = 30.0f; // signal-to-noise ratio float bt = 0.02f; // loop filter bandwidth unsigned int num_symbols = 400; // number of data symbols float tau = -0.20f; // fractional symbol offset // Nyquist filter type liquid_firfilt_type ftype = LIQUID_FIRFILT_KAISER; int dopt; while ((dopt = getopt(argc,argv,"uhk:m:b:B:s:w:n:t:")) != 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 'B': num_filters = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'w': bt = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 't': tau = atof(optarg); break; default: exit(1); } } unsigned int i; // validate input if (k < 2) { fprintf(stderr,"error: k (samples/symbol) must be at least 2\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 (num_filters == 0) { fprintf(stderr,"error: number of polyphase filters must be greater than 0\n"); exit(1); } else if (bt <= 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); } // derived values unsigned int num_samples = k*num_symbols; float complex x[num_samples]; // interpolated samples float complex y[num_samples]; // received signal (with noise) float tau_hat[num_samples]; // instantaneous timing offset estimate float complex sym_out[num_symbols + 64];// synchronized symbols // create sequence of Nyquist-interpolated QPSK symbols firinterp_crcf interp = firinterp_crcf_create_nyquist(ftype,k,m,beta,tau); for (i=0; i<num_symbols; i++) { // generate random QPSK symbol float complex s = ( rand() % 2 ? M_SQRT1_2 : -M_SQRT1_2 ) + ( rand() % 2 ? M_SQRT1_2 : -M_SQRT1_2 ) * _Complex_I; // interpolate symbol firinterp_crcf_execute(interp, s, &x[i*k]); } firinterp_crcf_destroy(interp); // add noise float nstd = powf(10.0f, -SNRdB/20.0f); for (i=0; i<num_samples; i++) y[i] = x[i] + nstd*(randnf() + _Complex_I*randnf()); // create and run symbol synchronizer symsync_crcf decim = symsync_crcf_create_kaiser(k, m, beta, num_filters); symsync_crcf_set_lf_bw(decim,bt); // set loop filter bandwidth // NOTE: we could just synchronize entire block (see following line); // however we would like to save the instantaneous timing offset // estimate for plotting purposes //symsync_crcf_execute(d, y, num_samples, sym_out, &num_symbols_sync); unsigned int num_symbols_sync = 0; unsigned int num_written=0; for (i=0; i<num_samples; i++) { // save instantaneous timing offset estimate tau_hat[i] = symsync_crcf_get_tau(decim); // execute one sample at a time symsync_crcf_execute(decim, &y[i], 1, &sym_out[num_symbols_sync], &num_written); // increment number of symbols synchronized num_symbols_sync += num_written; } symsync_crcf_destroy(decim); // print last several symbols to screen printf("output symbols:\n"); for (i=num_symbols_sync-10; i<num_symbols_sync; i++) printf(" sym_out(%2u) = %8.4f + j*%8.4f;\n", i+1, crealf(sym_out[i]), cimagf(sym_out[i])); // // 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,"k=%u;\n",k); fprintf(fid,"m=%u;\n",m); fprintf(fid,"beta=%12.8f;\n",beta); fprintf(fid,"num_filters=%u;\n",num_filters); fprintf(fid,"num_symbols=%u;\n",num_symbols); for (i=0; i<num_samples; i++) fprintf(fid,"x(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i])); for (i=0; i<num_samples; i++) fprintf(fid,"y(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i])); for (i=0; i<num_samples; i++) fprintf(fid,"tau_hat(%3u) = %12.8f;\n", i+1, tau_hat[i]); for (i=0; i<num_symbols_sync; i++) fprintf(fid,"sym_out(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(sym_out[i]), cimagf(sym_out[i])); fprintf(fid,"i0 = 1:round( 0.5*num_symbols );\n"); fprintf(fid,"i1 = round( 0.5*num_symbols ):num_symbols;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"hold on;\n"); fprintf(fid,"plot(real(sym_out(i0)),imag(sym_out(i0)),'x','MarkerSize',4,'Color',[0.6 0.6 0.6]);\n"); fprintf(fid,"plot(real(sym_out(i1)),imag(sym_out(i1)),'o','MarkerSize',4,'Color',[0 0.25 0.5]);\n"); fprintf(fid,"hold off;\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,"legend(['first 50%%'],['last 50%%'],1);\n"); fprintf(fid,"figure;\n"); fprintf(fid,"tt = 0:(length(tau_hat)-1);\n"); fprintf(fid,"b = floor(num_filters*tau_hat + 0.5);\n"); fprintf(fid,"stairs(tt,tau_hat*num_filters);\n"); fprintf(fid,"hold on;\n"); fprintf(fid,"plot(tt,b,'-k','Color',[0 0 0]);\n"); fprintf(fid,"hold off;\n"); fprintf(fid,"xlabel('time');\n"); fprintf(fid,"ylabel('filterbank index');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([0 length(tau_hat) -1 num_filters]);\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); // clean it up printf("done.\n"); return 0; }
void bpresync_test(bpresync_cccf _q, float complex * _x, unsigned int _n, float _SNRdB, float _dphi_max, float * _rxy_max, float * _dphi_err, float * _delay_err, unsigned int _num_trials, unsigned int _verbosity) { unsigned int max_delay = 64; float gamma = powf(10.0f, _SNRdB/20.0f); float nstd = 1.0f; // Farrow filter (for facilitating delay) unsigned int h_len = 49; unsigned int order = 4; float fc = 0.45f; float As = 60.0f; firfarrow_crcf fdelay = firfarrow_crcf_create(h_len, order, fc, As); unsigned int num_samples = _n + max_delay + (h_len-1)/2; float complex y[num_samples]; unsigned int t; for (t=0; t<_num_trials; t++) { unsigned int delay = rand() % max_delay; // sample delay float dt = randf() - 0.5f; // fractional sample delay float dphi = (2.0f*randf() - 1.0f) * _dphi_max; // carrier frequency offset float phi = 2*M_PI*randf(); // carrier phase offset // reset binary pre-demod synchronizer bpresync_cccf_reset(_q); // reset farrow filter firfarrow_crcf_clear(fdelay); firfarrow_crcf_set_delay(fdelay, dt); unsigned int i; unsigned int n=0; // generate signal: delay for (i=0; i<delay; i++) { firfarrow_crcf_push(fdelay, 0.0f); firfarrow_crcf_execute(fdelay, &y[n++]); } // generate signal: input sequence for (i=0; i<_n; i++) { firfarrow_crcf_push(fdelay, _x[i]); firfarrow_crcf_execute(fdelay, &y[n++]); } // generate signal: flush filter while (n < num_samples) { firfarrow_crcf_push(fdelay, 0.0f); firfarrow_crcf_execute(fdelay, &y[n++]); } // add channel gain, carrier offset, noise for (i=0; i<num_samples; i++) { y[i] *= gamma; y[i] *= cexpf(_Complex_I*(phi + i*dphi)); y[i] += nstd*( randnf() + randnf()*_Complex_I )*M_SQRT1_2; } // push through synchronizer _rxy_max[t] = 0.0f; _dphi_err[t] = 0.0f; _delay_err[t] = 0.0f; for (i=0; i<num_samples; i++) { // push through correlator float complex rxy; float dphi_est; bpresync_cccf_push(_q, y[i]); bpresync_cccf_correlate(_q, &rxy, &dphi_est); // retain maximum if ( cabsf(rxy) > _rxy_max[t] ) { _rxy_max[t] = cabsf(rxy); _dphi_err[t] = dphi_est - dphi; _delay_err[t] = (float)i - (float)(_n + delay + (h_len-1)/2) + 1.0f + dt; } } if (_verbosity == 0) { // do nothing } else if (_verbosity == 1) { // print progress bar if ( (t%100)==0 || t==_num_trials-1 ) { float percent = (float)(t+1) / (float)_num_trials; unsigned int bars = (unsigned int) (percent*60); printf("["); for (i=0; i<60; i++) printf("%c", i < bars ? '#' : ' '); printf("] %5.1f%%\r", percent*100); fflush(stdout); } } else { // print every trial printf(" %6u: rxy_max=%12.8f, dphi-err=%12.8f, delay-err=%12.8f\n", t, _rxy_max[t], _dphi_err[t], _delay_err[t]); } } // destroy Farrow filter firfarrow_crcf_destroy(fdelay); }
int main(int argc, char *argv[]) { //srand( time(NULL) ); // options modulation_scheme ms = LIQUID_MODEM_QPSK; // mod. scheme 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 = 120; // payload length int debug_enabled = 0; // enable debugging? float noise_floor = -60.0f; // noise floor float SNRdB = 20.0f; // signal-to-noise ratio float dphi = 0.01f; // carrier frequency offset // get options int dopt; while((dopt = getopt(argc,argv,"uhs:F:n:m:v:c:k:d")) != EOF){ switch (dopt) { case 'u': case 'h': usage(); return 0; case 's': SNRdB = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 'n': payload_len = atol(optarg); break; case 'm': ms = liquid_getopt_str2mod(optarg); break; case 'v': check = liquid_getopt_str2crc(optarg); break; case 'c': fec0 = liquid_getopt_str2fec(optarg); break; case 'k': fec1 = liquid_getopt_str2fec(optarg); break; case 'd': debug_enabled = 1; break; default: exit(-1); } } // derived values unsigned int i; 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 flexframegen object flexframegenprops_s fgprops; flexframegenprops_init_default(&fgprops); fgprops.mod_scheme = ms; fgprops.check = check; fgprops.fec0 = fec0; fgprops.fec1 = fec1; flexframegen fg = flexframegen_create(&fgprops); // frame data (header and payload) unsigned char header[14]; unsigned char payload[payload_len]; // create flexframesync object flexframesync fs = flexframesync_create(callback,NULL); if (debug_enabled) flexframesync_debug_enable(fs); // initialize header, payload for (i=0; i<14; i++) header[i] = i; for (i=0; i<payload_len; i++) payload[i] = rand() & 0xff; // assemble the frame flexframegen_assemble(fg, header, payload, payload_len); flexframegen_print(fg); // generate the frame in blocks unsigned int buf_len = 256; float complex x[buf_len]; float complex y[buf_len]; int frame_complete = 0; float phi = 0.0f; while (!frame_complete) { // write samples to buffer frame_complete = flexframegen_write_samples(fg, x, buf_len); // add noise and push through synchronizer for (i=0; i<buf_len; i++) { // apply channel gain and carrier offset to input y[i] = gamma * x[i] * cexpf(_Complex_I*phi); phi += dphi; // add noise y[i] += nstd*( randnf() + _Complex_I*randnf())*M_SQRT1_2; } // run through frame synchronizer flexframesync_execute(fs, y, buf_len); } // export debugging file if (debug_enabled) flexframesync_debug_print(fs, "flexframesync_debug.m"); flexframesync_print(fs); // destroy allocated objects flexframegen_destroy(fg); flexframesync_destroy(fs); printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { // set random number generator seed srand(time(NULL)); // options unsigned int M = 64; // number of subcarriers unsigned int cp_len = 16; // cyclic prefix length modulation_scheme ms = LIQUID_MODEM_BPSK; float SNRdB = 6.5f; // signal-to-noise ratio [dB] unsigned int hc_len = 1; // channel impulse response length unsigned int num_symbols = 40; // number of OFDM symbols // get options int dopt; while((dopt = getopt(argc,argv,"hs:M:C:m:n:c:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 's': SNRdB = atof(optarg); break; case 'M': M = atoi(optarg); break; case 'C': cp_len = atoi(optarg); break; case 'm': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported mod. scheme: %s\n", argv[0], optarg); exit(-1); } break; case 'n': num_symbols = atoi(optarg); break; case 'c': hc_len = atoi(optarg); break; default: exit(-1); } } unsigned int i; // validate options if (M < 4) { fprintf(stderr,"error: %s, must have at least 4 subcarriers\n", argv[0]); exit(1); } else if (hc_len == 0) { fprintf(stderr,"error: %s, must have at least 1 channel tap\n", argv[0]); exit(1); } // derived values unsigned int symbol_len = M + cp_len; float nstd = powf(10.0f, -SNRdB/20.0f); float fft_gain = 1.0f / sqrtf(M); // 'gain' due to taking FFT // buffers unsigned int sym_in[M]; // input data symbols unsigned int sym_out[M]; // output data symbols float complex x[M]; // time-domain buffer float complex X[M]; // freq-domain buffer float complex buffer[symbol_len]; // // create modulator/demodulator objects modem mod = modem_create(ms); modem demod = modem_create(ms); unsigned int bps = modem_get_bps(mod); // modem bits/symbol // create channel filter (random taps) float complex hc[hc_len]; hc[0] = 1.0f; for (i=1; i<hc_len; i++) hc[i] = 0.1f * (randnf() + _Complex_I*randnf()); firfilt_cccf fchannel = firfilt_cccf_create(hc, hc_len); // unsigned int n; unsigned int num_bit_errors = 0; for (n=0; n<num_symbols; n++) { // generate random data symbols and modulate onto subcarriers for (i=0; i<M; i++) { sym_in[i] = rand() % (1<<bps); modem_modulate(mod, sym_in[i], &X[i]); } // run inverse transform fft_run(M, X, x, LIQUID_FFT_BACKWARD, 0); // scale by FFT gain so E{|x|^2} = 1 for (i=0; i<M; i++) x[i] *= fft_gain; // apply channel impairments for (i=0; i<M + cp_len; i++) { // push samples through channel filter, starting with cyclic prefix firfilt_cccf_push(fchannel, x[(M-cp_len+i)%M]); // compute output firfilt_cccf_execute(fchannel, &buffer[i]); // add noise buffer[i] += nstd*( randnf() + _Complex_I*randnf() ) * M_SQRT1_2; } // run forward transform fft_run(M, &buffer[cp_len], X, LIQUID_FFT_FORWARD, 0); // TODO : apply equalizer to 'X' here // demodulate and compute bit errors for (i=0; i<M; i++) { // scale by fft size X[i] *= fft_gain; modem_demodulate(demod, X[i], &sym_out[i]); num_bit_errors += liquid_count_ones(sym_in[i] ^ sym_out[i]); } } // destroy objects modem_destroy(mod); modem_destroy(demod); firfilt_cccf_destroy(fchannel); // print results unsigned int total_bits = M*bps*num_symbols; float ber = (float)num_bit_errors / (float)total_bits; printf(" bit errors : %6u / %6u (%12.4e)\n", num_bit_errors, total_bits, ber); printf("done.\n"); return 0; }
int main() { // options unsigned int num_channels=4; // number of channels unsigned int p=3; // filter length (symbols) unsigned int num_symbols=6; // number of symbols // derived values unsigned int num_samples = num_channels * num_symbols; unsigned int i; unsigned int j; // generate synthesis filter // NOTE : these coefficients can be random; the purpose of this // exercise is to demonstrate mathematical equivalence unsigned int h_len = p*num_channels; float h[h_len]; for (i=0; i<h_len; i++) h[i] = randnf(); // generate analysis filter unsigned int g_len = p*num_channels; float g[g_len]; for (i=0; i<g_len; i++) g[i] = h[g_len-i-1]; // create synthesis/analysis filter objects firfilt_crcf fs = firfilt_crcf_create(h, h_len); firfilt_crcf fa = firfilt_crcf_create(g, g_len); // create synthesis/analysis filterbank channelizer objects firpfbch_crcf qs = firpfbch_crcf_create(LIQUID_SYNTHESIZER, num_channels, p, h); firpfbch_crcf qa = firpfbch_crcf_create(LIQUID_ANALYZER, num_channels, p, g); float complex x[num_samples]; // random input (noise) float complex Y0[num_symbols][num_channels]; // channelized output (filterbank) float complex Y1[num_symbols][num_channels]; // channelized output float complex z0[num_samples]; // time-domain output (filterbank) float complex z1[num_samples]; // time-domain output // generate input sequence (complex noise) for (i=0; i<num_samples; i++) x[i] = randnf() * cexpf(_Complex_I*randf()*2*M_PI); // // ANALYZERS // // // run analysis filter bank // for (i=0; i<num_symbols; i++) firpfbch_crcf_analyzer_execute(qa, &x[i*num_channels], &Y0[i][0]); // // run traditional down-converter (inefficient) // float dphi; // carrier frequency unsigned int n=0; for (i=0; i<num_channels; i++) { // reset filter firfilt_crcf_clear(fa); // set center frequency dphi = 2.0f * M_PI * (float)i / (float)num_channels; // reset symbol counter n=0; for (j=0; j<num_samples; j++) { // push down-converted sample into filter firfilt_crcf_push(fa, x[j]*cexpf(-_Complex_I*j*dphi)); // compute output at the appropriate sample time assert(n<num_symbols); if ( ((j+1)%num_channels)==0 ) { firfilt_crcf_execute(fa, &Y1[n][i]); n++; } } assert(n==num_symbols); } // // SYNTHESIZERS // // // run synthesis filter bank // for (i=0; i<num_symbols; i++) firpfbch_crcf_synthesizer_execute(qs, &Y0[i][0], &z0[i*num_channels]); // // run traditional up-converter (inefficient) // // clear output array for (i=0; i<num_samples; i++) z1[i] = 0.0f; float complex y_hat; for (i=0; i<num_channels; i++) { // reset filter firfilt_crcf_clear(fs); // set center frequency dphi = 2.0f * M_PI * (float)i / (float)num_channels; // reset input symbol counter n=0; for (j=0; j<num_samples; j++) { // interpolate sequence if ( (j%num_channels)==0 ) { assert(n<num_symbols); firfilt_crcf_push(fs, Y1[n][i]); n++; } else { firfilt_crcf_push(fs, 0); } firfilt_crcf_execute(fs, &y_hat); // accumulate up-converted sample z1[j] += y_hat * cexpf(_Complex_I*j*dphi); } assert(n==num_symbols); } // destroy objects firfilt_crcf_destroy(fs); firfilt_crcf_destroy(fa); firpfbch_crcf_destroy(qs); firpfbch_crcf_destroy(qa); // // RESULTS // // // analyzers // // print filterbank channelizer printf("\n"); printf("filterbank channelizer:\n"); for (i=0; i<num_symbols; i++) { printf("%3u: ", i); for (j=0; j<num_channels; j++) { printf(" %8.5f+j%8.5f, ", crealf(Y0[i][j]), cimagf(Y0[i][j])); } printf("\n"); } // print traditional channelizer printf("\n"); printf("traditional channelizer:\n"); for (i=0; i<num_symbols; i++) { printf("%3u: ", i); for (j=0; j<num_channels; j++) { printf(" %8.5f+j%8.5f, ", crealf(Y1[i][j]), cimagf(Y1[i][j])); } printf("\n"); } float mse_analyzer[num_channels]; float complex d; for (i=0; i<num_channels; i++) { mse_analyzer[i] = 0.0f; for (j=0; j<num_symbols; j++) { d = Y0[j][i] - Y1[j][i]; mse_analyzer[i] += crealf(d*conjf(d)); } mse_analyzer[i] /= num_symbols; } printf("\n"); printf("rmse: "); for (i=0; i<num_channels; i++) printf("%12.4e ", sqrt(mse_analyzer[i])); printf("\n"); // // synthesizers // printf("\n"); printf("output: filterbank: traditional:\n"); for (i=0; i<num_samples; i++) { printf("%3u: %10.5f+%10.5fj %10.5f+%10.5fj\n", i, crealf(z0[i]), cimagf(z0[i]), crealf(z1[i]), cimagf(z1[i])); } float mse_synthesizer = 0.0f; for (i=0; i<num_samples; i++) { d = z0[i] - z1[i]; mse_synthesizer += crealf(d*conjf(d)); } mse_synthesizer /= num_samples; printf("\n"); printf("rmse: %12.4e\n", sqrtf(mse_synthesizer)); // // EXPORT DATA TO 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"); fprintf(fid,"num_channels=%u;\n", num_channels); fprintf(fid,"num_symbols=%u;\n", num_symbols); fprintf(fid,"num_samples = num_channels*num_symbols;\n"); fprintf(fid,"x = zeros(1,num_samples);\n"); fprintf(fid,"y0 = zeros(num_symbols,num_channels);\n"); fprintf(fid,"y1 = zeros(num_symbols,num_channels);\n"); fprintf(fid,"z0 = zeros(1,num_samples);\n"); fprintf(fid,"z1 = zeros(1,num_samples);\n"); // input for (i=0; i<num_samples; i++) fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimag(x[i])); // analysis for (i=0; i<num_symbols; i++) { for (j=0; j<num_channels; j++) { fprintf(fid,"y0(%4u,%4u) = %12.4e + j*%12.4e;\n", i+1, j+1, crealf(Y0[i][j]), cimag(Y0[i][j])); fprintf(fid,"y1(%4u,%4u) = %12.4e + j*%12.4e;\n", i+1, j+1, crealf(Y1[i][j]), cimag(Y1[i][j])); } } // synthesis for (i=0; i<num_samples; i++) { fprintf(fid,"z0(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(z0[i]), cimag(z0[i])); fprintf(fid,"z1(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(z1[i]), cimag(z1[i])); } fprintf(fid,"z0 = z0 / num_channels;\n"); fprintf(fid,"z1 = z1 / num_channels;\n"); // plot results fprintf(fid,"\n\n"); fprintf(fid,"ts = 0:(num_symbols-1);\n"); fprintf(fid,"for i=1:num_channels,\n"); fprintf(fid,"figure;\n"); fprintf(fid,"title(['channel ' num2str(i)]);\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(ts,real(y0(:,i)),'-x', ts,real(y1(:,i)),'s');\n"); //fprintf(fid," axis([0 (num_symbols-1) -2 2]);\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(ts,imag(y0(:,i)),'-x', ts,imag(y1(:,i)),'s');\n"); //fprintf(fid," axis([0 (num_symbols-1) -2 2]);\n"); fprintf(fid,"end;\n"); fprintf(fid,"t = 0:(num_samples-1);\n"); fprintf(fid,"figure;\n"); fprintf(fid,"title('composite');\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(t,real(z0),'-x', t,real(z1),'s');\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(t,imag(z0),'-x', t,imag(z1),'s');\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=4; // filter samples/symbol unsigned int m=3; // filter delay (symbols) float BT=0.3f; // bandwidth-time product unsigned int num_data_symbols=200; // number of data symbols float SNRdB = 30.0f; // signal-to-noise ratio [dB] float phi = 0.0f; // carrier phase offset float dphi = 0.0f; // carrier frequency offset int dopt; while ((dopt = getopt(argc,argv,"uhk:m:n:b:s:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'n': num_data_symbols = atoi(optarg); break; case 'b': BT = atof(optarg); break; case 's': SNRdB = atof(optarg); break; default: exit(1); } } // validate input if (BT <= 0.0f || BT >= 1.0f) { fprintf(stderr,"error: %s, bandwidth-time product must be in (0,1)\n", argv[0]); exit(1); } // derived values unsigned int num_symbols = num_data_symbols + 2*m; unsigned int num_samples = k*num_symbols; float nstd = powf(10.0f,-SNRdB/20.0f); // noise standard deviation // create modulator gmskmod mod = gmskmod_create(k, m, BT); gmskmod_print(mod); // create demodulator gmskdem demod = gmskdem_create(k, m, BT); gmskdem_set_eq_bw(demod, 0.01f); gmskdem_print(demod); unsigned int i; unsigned int s[num_symbols]; float complex x[num_samples]; float complex y[num_samples]; unsigned int sym_out[num_symbols]; // generate random data sequence for (i=0; i<num_symbols; i++) s[i] = rand() % 2; // modulate signal for (i=0; i<num_symbols; i++) gmskmod_modulate(mod, s[i], &x[k*i]); // add channel impairments for (i=0; i<num_samples; i++) { y[i] = x[i]*cexpf(_Complex_I*(phi + i*dphi)); y[i] += nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2; } // demodulate signal for (i=0; i<num_symbols; i++) gmskdem_demodulate(demod, &y[k*i], &sym_out[i]); // destroy modem objects gmskmod_destroy(mod); gmskdem_destroy(demod); // print results to screen unsigned int delay = 2*m; unsigned int num_errors=0; for (i=delay; i<num_symbols; i++) { //printf(" %4u : %2u (%2u)\n", i, s[i-delay], sym_out[i]); num_errors += (s[i-delay] == sym_out[i]) ? 0 : 1; } printf("symbol errors : %4u / %4u\n", num_errors, num_data_symbols); // write results to 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"); fprintf(fid,"k = %u;\n", k); fprintf(fid,"m = %u;\n", m); fprintf(fid,"BT = %f;\n", BT); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"num_samples = %u;\n", num_samples); 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])); } fprintf(fid,"t=[0:(num_samples-1)]/k;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(t,real(y),t,imag(y));\n"); // artificially demodulate (generate receive filter, etc.) float hr[2*k*m+1]; liquid_firdes_gmskrx(k,m,BT,0,hr); for (i=0; i<2*k*m+1; i++) fprintf(fid,"hr(%3u) = %12.8f;\n", i+1, hr[i]); fprintf(fid,"z = filter(hr,1,arg( ([y(2:end) 0]).*conj(y) ))/k;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(t,z,t(k:k:end),z(k:k:end),'or');\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 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[]) { srand(time(NULL)); // options unsigned int k = 2; // samples/symbol (input) unsigned int k_out = 2; // samples/symbol (output) unsigned int m = 5; // filter delay (symbols) float beta = 0.5f; // filter excess bandwidth factor unsigned int num_filters = 32; // number of filters in the bank unsigned int num_symbols = 400; // number of data symbols float SNRdB = 30.0f; // signal-to-noise ratio // transmit/receive filter types liquid_firfilt_type ftype_tx = LIQUID_FIRFILT_RRC; liquid_firfilt_type ftype_rx = LIQUID_FIRFILT_RRC; float bt = 0.02f; // loop filter bandwidth float tau = -0.2f; // fractional symbol offset float r = 1.00f; // resampled rate // use random data or 101010 phasing pattern int random_data=1; int dopt; while ((dopt = getopt(argc,argv,"hT:k:K:m:b:B:s:w:n:t:r:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'T': if (strcmp(optarg,"gmsk")==0) { ftype_tx = LIQUID_FIRFILT_GMSKTX; ftype_rx = LIQUID_FIRFILT_GMSKRX; } else { ftype_tx = liquid_getopt_str2firfilt(optarg); ftype_rx = liquid_getopt_str2firfilt(optarg); } if (ftype_tx == LIQUID_FIRFILT_UNKNOWN) { fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg); exit(1); } break; case 'k': k = atoi(optarg); break; case 'K': k_out = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'B': num_filters = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'w': bt = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 't': tau = atof(optarg); break; case 'r': r = atof(optarg); break; default: exit(1); } } // validate input if (k < 2) { fprintf(stderr,"error: k (samples/symbol) must be at least 2\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 (num_filters == 0) { fprintf(stderr,"error: number of polyphase filters must be greater than 0\n"); exit(1); } else if (bt <= 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 (r < 0.5f || r > 2.0f) { fprintf(stderr,"error: timing frequency offset must be in [0.5,2]\n"); exit(1); } // compute delay while (tau < 0) tau += 1.0f; // ensure positive tau float g = k*tau; // number of samples offset int ds=floorf(g); // additional symbol delay float dt = (g - (float)ds); // fractional sample offset if (dt > 0.5f) { // force dt to be in [0.5,0.5] dt -= 1.0f; ds++; } unsigned int i, n=0; unsigned int num_samples = k*num_symbols; unsigned int num_samples_resamp = (unsigned int) ceilf(num_samples*r*1.1f) + 4; float complex s[num_symbols]; // data symbols float complex x[num_samples]; // interpolated samples float complex y[num_samples_resamp]; // resampled data (resamp_crcf) float complex z[k_out*num_symbols + 64];// synchronized samples float complex sym_out[num_symbols + 64];// synchronized symbols for (i=0; i<num_symbols; i++) { if (random_data) { // random signal (QPSK) s[i] = cexpf(_Complex_I*0.5f*M_PI*((rand() % 4) + 0.5f)); } else { s[i] = (i%2) ? 1.0f : -1.0f; // 101010 phasing pattern } } // // create and run interpolator // // design interpolating filter unsigned int h_len = 2*k*m+1; float h[h_len]; liquid_firdes_rnyquist(ftype_tx,k,m,beta,dt,h); firinterp_crcf q = firinterp_crcf_create(k,h,h_len); for (i=0; i<num_symbols; i++) { firinterp_crcf_execute(q, s[i], &x[n]); n+=k; } assert(n == num_samples); firinterp_crcf_destroy(q); // // run resampler // unsigned int resamp_len = 10*k; // resampling filter semi-length (filter delay) float resamp_bw = 0.45f; // resampling filter bandwidth float resamp_As = 60.0f; // resampling filter stop-band attenuation unsigned int resamp_npfb = 64; // number of filters in bank resamp_crcf f = resamp_crcf_create(r, resamp_len, resamp_bw, resamp_As, resamp_npfb); unsigned int num_samples_resampled = 0; unsigned int num_written; for (i=0; i<num_samples; i++) { #if 0 // bypass arbitrary resampler y[i] = x[i]; num_samples_resampled = num_samples; #else // TODO : compensate for resampler filter delay resamp_crcf_execute(f, x[i], &y[num_samples_resampled], &num_written); num_samples_resampled += num_written; #endif } resamp_crcf_destroy(f); // // add noise // float nstd = powf(10.0f, -SNRdB/20.0f); for (i=0; i<num_samples_resampled; i++) y[i] += nstd*(randnf() + _Complex_I*randnf()); // // create and run symbol synchronizer // symsync_crcf d = symsync_crcf_create_rnyquist(ftype_rx, k, m, beta, num_filters); symsync_crcf_set_lf_bw(d,bt); symsync_crcf_set_output_rate(d,k_out); unsigned int num_samples_sync=0; unsigned int nn; unsigned int num_symbols_sync = 0; float tau_hat[num_samples]; for (i=ds; i<num_samples_resampled; i++) { tau_hat[num_samples_sync] = symsync_crcf_get_tau(d); symsync_crcf_execute(d, &y[i], 1, &z[num_samples_sync], &nn); // decimate unsigned int j; for (j=0; j<nn; j++) { if ( (num_samples_sync%k_out)==0 ) sym_out[num_symbols_sync++] = z[num_samples_sync]; num_samples_sync++; } } symsync_crcf_destroy(d); // print last several symbols to screen printf("output symbols:\n"); printf(" ...\n"); for (i=num_symbols_sync-10; i<num_symbols_sync; i++) printf(" sym_out(%2u) = %8.4f + j*%8.4f;\n", i+1, crealf(sym_out[i]), cimagf(sym_out[i])); // // 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,"k=%u;\n",k); fprintf(fid,"m=%u;\n",m); fprintf(fid,"beta=%12.8f;\n",beta); fprintf(fid,"k_out=%u;\n",k_out); fprintf(fid,"num_filters=%u;\n",num_filters); fprintf(fid,"num_symbols=%u;\n",num_symbols); for (i=0; i<h_len; i++) fprintf(fid,"h(%3u) = %12.5f;\n", i+1, h[i]); for (i=0; i<num_symbols; i++) fprintf(fid,"s(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(s[i]), cimagf(s[i])); for (i=0; i<num_samples; i++) fprintf(fid,"x(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i])); for (i=0; i<num_samples_resampled; i++) fprintf(fid,"y(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i])); for (i=0; i<num_samples_sync; i++) fprintf(fid,"z(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(z[i]), cimagf(z[i])); for (i=0; i<num_symbols_sync; i++) fprintf(fid,"sym_out(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(sym_out[i]), cimagf(sym_out[i])); for (i=0; i<num_samples_sync; i++) fprintf(fid,"tau_hat(%3u) = %12.8f;\n", i+1, tau_hat[i]); fprintf(fid,"\n\n"); fprintf(fid,"%% scale QPSK in-phase by sqrt(2)\n"); fprintf(fid,"z = z*sqrt(2);\n"); fprintf(fid,"\n\n"); fprintf(fid,"tz = [0:length(z)-1]/k_out;\n"); fprintf(fid,"iz = 1:k_out:length(z);\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(tz, real(z), '-',...\n"); fprintf(fid," tz(iz), real(z(iz)),'or');\n"); fprintf(fid,"xlabel('Time');\n"); fprintf(fid,"ylabel('Output Signal (real)');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"legend('output time series','optimum timing','location','northeast');\n"); fprintf(fid,"iz0 = iz( 1:round(length(iz)*0.5) );\n"); fprintf(fid,"iz1 = iz( round(length(iz)*0.5):length(iz) );\n"); fprintf(fid,"figure;\n"); fprintf(fid,"hold on;\n"); fprintf(fid,"plot(real(z(iz0)),imag(z(iz0)),'x','MarkerSize',4,'Color',[0.6 0.6 0.6]);\n"); fprintf(fid,"plot(real(z(iz1)),imag(z(iz1)),'o','MarkerSize',4,'Color',[0 0.25 0.5]);\n"); fprintf(fid,"hold off;\n"); fprintf(fid,"axis square;\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([-1 1 -1 1]*2.0);\n"); fprintf(fid,"xlabel('In-phase');\n"); fprintf(fid,"ylabel('Quadrature');\n"); fprintf(fid,"legend(['first 50%%'],['last 50%%'],'location','northeast');\n"); fprintf(fid,"figure;\n"); fprintf(fid,"tt = 0:(length(tau_hat)-1);\n"); fprintf(fid,"b = floor(num_filters*tau_hat + 0.5);\n"); fprintf(fid,"stairs(tt,tau_hat*num_filters);\n"); fprintf(fid,"hold on;\n"); fprintf(fid,"plot(tt,b,'-k','Color',[0 0 0]);\n"); fprintf(fid,"hold off;\n"); fprintf(fid,"xlabel('time');\n"); fprintf(fid,"ylabel('filterbank index');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([0 length(tau_hat) -1 num_filters]);\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); // clean it up printf("done.\n"); return 0; }
int main() { // options unsigned int num_samples = 400; // number of samples float sig = 0.1f; // noise variance unsigned int num_iterations = 1000; // number of iterations to run float v[3] = {1, 1, 1}; unsigned int i; // range float xmin = 0.0f; float xmax = 6.0f; float dx = (xmax - xmin) / (num_samples-1); // generate data set float x[num_samples]; float y[num_samples]; for (i=0; i<num_samples; i++) { x[i] = xmin + i*dx; y[i] = sincf(x[i]) + randnf()*sig; } struct gsdataset q = {x, y, num_samples}; // create gradsearch object gradsearchprops_s gsprops; gradsearchprops_init_default(&gsprops); gsprops.delta = 1e-6f; // gradient approximation step size gsprops.gamma = 0.002f; // vector step size gsprops.alpha = 0.1f; // momentum parameter gsprops.mu = 0.999f; // decremental gamma paramter (best if not exactly 1.0) gradsearch gs = gradsearch_create((void*)&q, v, 3, gserror, LIQUID_OPTIM_MINIMIZE, &gsprops); float rmse; // execute search //rmse = gradsearch_run(gs, num_iterations, -1e-6f); // open 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"); // execute search one iteration at a time fprintf(fid,"u = zeros(1,%u);\n", num_iterations); for (i=0; i<num_iterations; i++) { rmse = gserror((void*)&q,v,3); fprintf(fid,"u(%3u) = %12.4e;\n", i+1, rmse); gradsearch_step(gs); if (((i+1)%100)==0) gradsearch_print(gs); } // print results printf("\n"); gradsearch_print(gs); printf(" c0 = %12.8f, opt = 1\n", v[0]); printf(" c1 = %12.8f, opt = 0\n", v[1]); printf(" c2 = %12.8f, opt = 1\n", v[2]); printf(" rmse = %12.4e\n", rmse); fprintf(fid,"figure;\n"); fprintf(fid,"semilogy(u);\n"); fprintf(fid,"xlabel('iteration');\n"); fprintf(fid,"ylabel('error');\n"); fprintf(fid,"title('gradient search results');\n"); fprintf(fid,"grid on;\n"); // save sampled data set for (i=0; i<num_samples; i++) { fprintf(fid," x(%4u) = %12.8f;\n", i+1, x[i]); fprintf(fid," y(%4u) = %12.8f;\n", i+1, y[i]); fprintf(fid," y_hat(%4u) = %12.8f;\n", i+1, gsfunc(x[i],v)); } fprintf(fid,"figure;\n"); fprintf(fid,"plot(x,y,'x', x,y_hat,'-');\n"); fprintf(fid,"xlabel('x');\n"); fprintf(fid,"ylabel('f(x)');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"legend('data','fit',1);\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); gradsearch_destroy(gs); return 0; }