// // AUTOTEST: static channel filter, blind equalization on QPSK symbols // void autotest_eqlms_cccf_blind() { // parameters float tol = 2e-2f; // error tolerance unsigned int k = 2; // samples/symbol unsigned int m = 7; // filter delay float beta = 0.3f; // excess bandwidth factor unsigned int p = 7; // equalizer order float mu = 0.7f; // equalizer bandwidth unsigned int num_symbols = 400; // number of symbols to observe // create sequence generator for repeatability msequence ms = msequence_create_default(12); // create interpolating filter firinterp_crcf interp = firinterp_crcf_create_prototype(LIQUID_FIRFILT_ARKAISER,k,m,beta,0); // create equalizer eqlms_cccf eq = eqlms_cccf_create_rnyquist(LIQUID_FIRFILT_ARKAISER,k,p,beta,0); eqlms_cccf_set_bw(eq, mu); // create channel filter float complex h[5] = { { 1.00f, 0.00f}, { 0.00f, -0.01f}, {-0.11f, 0.02f}, { 0.02f, 0.01f}, {-0.09f, -0.04f} }; firfilt_cccf fchannel = firfilt_cccf_create(h,5); // arrays float complex buf[k]; // filter buffer float complex sym_in [num_symbols]; // input symbols float complex sym_out[num_symbols]; // equalized symbols // run equalization unsigned int i; unsigned int j; for (i=0; i<num_symbols; i++) { // generate input symbol sym_in[i] = ( msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2 ) + ( msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2 ) * _Complex_I; // interpolate firinterp_crcf_execute(interp, sym_in[i], buf); // apply channel filter (in place) firfilt_cccf_execute_block(fchannel, buf, k, buf); // apply equalizer as filter for (j=0; j<k; j++) { eqlms_cccf_push(eq, buf[j]); // decimate by k if ( (j%k) != 0 ) continue; eqlms_cccf_execute(eq, &sym_out[i]); // update equalization (blind operation) if (i > m + p) eqlms_cccf_step(eq, sym_out[i]/cabsf(sym_out[i]), sym_out[i]); } } // compare input, output unsigned int settling_delay = 285; for (i=m+p; i<num_symbols; i++) { // compensate for delay j = i-m-p; // absolute error float error = cabsf(sym_in[j]-sym_out[i]); if (liquid_autotest_verbose) { printf("x[%3u] = {%12.8f,%12.8f}, y[%3u] = {%12.8f,%12.8f}, error=%12.8f %s\n", j, crealf(sym_in [j]), cimagf(sym_in [j]), i, crealf(sym_out[i]), cimagf(sym_out[i]), error, error > tol ? "*" : ""); if (i == settling_delay + m + p) printf("--- start of test ---\n"); } // check error if (i > settling_delay + m + p) CONTEND_DELTA(error, 0.0f, tol); } // clean up objects firfilt_cccf_destroy(fchannel); eqlms_cccf_destroy(eq); msequence_destroy(ms); }
int main() { // options unsigned int num_samples = 600; // number of samples unsigned int m = 25; // prototype filter semi-length float As = 30.0f; // prototype filter stop-band suppression float f0 = 0.15f; // notch frequency // design filter from prototype firfilt_cccf q = firfilt_cccf_create_notch(m,As,f0); firfilt_cccf_print(q); // allocate memory for data arrays float complex x[num_samples]; // original input float complex y[num_samples]; // filtered signal // generate input signal unsigned int i; for (i=0; i<num_samples; i++) { x[i] = cexpf(_Complex_I*2*M_PI*0.037*i) + cexpf(_Complex_I*2*M_PI*f0* i); } // run notch filter firfilt_cccf_execute_block(q, x, num_samples, y); // destroy filter object firfilt_cccf_destroy(q); // // plot 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,"\n"); fprintf(fid,"num_samples=%u;\n",num_samples); fprintf(fid,"x=zeros(1,num_samples);\n"); fprintf(fid,"y=zeros(1,num_samples);\n"); // save input, output arrays 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])); } // plot output fprintf(fid,"t=0:(num_samples-1);\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(3,1,1);\n"); fprintf(fid," plot(t,real(x),'-','Color',[1 1 1]*0.5,'LineWidth',1,...\n"); fprintf(fid," t,imag(x),'-','Color',[0 0.2 0.5],'LineWidth',2);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('original input');\n"); fprintf(fid," legend('real','imag','location','northeast');\n"); fprintf(fid," axis([0 num_samples -2.2 2.2]);\n"); fprintf(fid," grid on;\n"); fprintf(fid,"subplot(3,1,2);\n"); fprintf(fid," plot(t,real(y),'-','Color',[1 1 1]*0.5,'LineWidth',1,...\n"); fprintf(fid," t,imag(y),'-','Color',[0 0.5 0.2],'LineWidth',2);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('notch filter output');\n"); fprintf(fid," legend('real','imag','location','northeast');\n"); fprintf(fid," axis([0 num_samples -2.2 2.2]);\n"); fprintf(fid," grid on;\n"); fprintf(fid,"subplot(3,1,3);\n"); fprintf(fid," nfft = 2^nextpow2(num_samples);\n"); fprintf(fid," f = [0:(nfft-1)]/nfft-0.5;\n"); fprintf(fid," X = 20*log10(abs(fftshift(fft(x,nfft))));\n"); fprintf(fid," Y = 20*log10(abs(fftshift(fft(y,nfft))));\n"); fprintf(fid," plot(f,X,'-','Color',[1 1 1]*0.5,'LineWidth',1,...\n"); fprintf(fid," f,Y,'-','Color',[0.5 0 0], 'LineWidth',2);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('PSD (dB)');\n"); fprintf(fid," legend('original','filtered','location','northeast');\n"); fprintf(fid," axis([-0.5 0.5 -20 60]);\n"); fprintf(fid," grid on;\n"); // close output file fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }