// destroy frame synchronizer object, freeing all internal memory void flexframesync_destroy(flexframesync _q) { #if DEBUG_FLEXFRAMESYNC // clean up debug objects (if created) if (_q->debug_objects_created) { windowcf_destroy(_q->debug_x); } #endif // destroy synchronization objects detector_cccf_destroy(_q->frame_detector); // frame detector windowcf_destroy(_q->buffer); // p/n sample buffer firpfb_crcf_destroy(_q->mf); // matched filter firpfb_crcf_destroy(_q->dmf); // derivative matched filter nco_crcf_destroy(_q->nco_coarse); // coarse NCO nco_crcf_destroy(_q->nco_fine); // fine-tuned NCO modem_destroy(_q->demod_header); // header demodulator packetizer_destroy(_q->p_header); // header packetizer modem_destroy(_q->demod_payload); // payload demodulator packetizer_destroy(_q->p_payload); // payload decoder // free buffers and arrays free(_q->payload_mod); // free(_q->payload_enc); // free(_q->payload_dec); // // free main object memory free(_q); }
// destroy frame synchronizer object, freeing all internal memory void flexframesync_destroy(flexframesync _q) { #if DEBUG_FLEXFRAMESYNC // clean up debug objects (if created) if (_q->debug_objects_created) windowcf_destroy(_q->debug_x); #endif // free allocated arrays free(_q->preamble_pn); free(_q->preamble_rx); free(_q->header_sym); free(_q->header_mod); free(_q->header_dec); free(_q->payload_sym); free(_q->payload_dec); // destroy synchronization objects qpilotsync_destroy (_q->header_pilotsync); // header demodulator/decoder qpacketmodem_destroy (_q->header_decoder); // header demodulator/decoder modem_destroy (_q->payload_demod); // payload demodulator (for PLL) qpacketmodem_destroy (_q->payload_decoder); // payload demodulator/decoder qdetector_cccf_destroy(_q->detector); // frame detector firpfb_crcf_destroy (_q->mf); // matched filter nco_crcf_destroy (_q->mixer); // oscillator (coarse) nco_crcf_destroy (_q->pll); // oscillator (fine) #if FLEXFRAMESYNC_ENABLE_EQ eqlms_cccf_destroy (_q->equalizer); // LMS equalizer #endif // free main object memory free(_q); }
void ofdmflexframesync_destroy(ofdmflexframesync _q) { // destroy internal objects ofdmframesync_destroy(_q->fs); packetizer_destroy(_q->p_header); modem_destroy(_q->mod_header); packetizer_destroy(_q->p_payload); modem_destroy(_q->mod_payload); // free internal buffers/arrays free(_q->p); free(_q->payload_enc); free(_q->payload_dec); // free main object memory free(_q); }
ModemDPSK::~ModemDPSK() { modem_destroy(demodDPSK2); modem_destroy(demodDPSK4); modem_destroy(demodDPSK8); modem_destroy(demodDPSK16); modem_destroy(demodDPSK32); modem_destroy(demodDPSK64); modem_destroy(demodDPSK128); modem_destroy(demodDPSK256); }
void ofdmflexframegen_destroy(ofdmflexframegen _q) { // destroy internal objects ofdmframegen_destroy(_q->fg); // OFDM frame generator packetizer_destroy(_q->p_header); // header packetizer modem_destroy(_q->mod_header); // header modulator packetizer_destroy(_q->p_payload); // payload packetizer modem_destroy(_q->mod_payload); // payload modulator // free buffers/arrays free(_q->payload_enc); // encoded payload bytes free(_q->payload_mod); // modulated payload symbols free(_q->X); // frequency-domain buffer free(_q->p); // subcarrier allocation // free main object memory free(_q); }
ModemQAM::~ModemQAM() { modem_destroy(demodQAM4); modem_destroy(demodQAM8); modem_destroy(demodQAM16); modem_destroy(demodQAM32); modem_destroy(demodQAM64); modem_destroy(demodQAM128); modem_destroy(demodQAM256); }
// Helper function to keep code base small void modem_modulate_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, modulation_scheme _ms) { // normalize number of iterations switch (_ms) { case LIQUID_MODEM_UNKNOWN: fprintf(stderr,"error: modem_modulate_bench(), unknown modem scheme\n"); exit(1); case LIQUID_MODEM_BPSK: *_num_iterations *= 64; break; case LIQUID_MODEM_QPSK: *_num_iterations *= 64; break; case LIQUID_MODEM_OOK: *_num_iterations *= 64; break; case LIQUID_MODEM_SQAM32: *_num_iterations *= 16; break; case LIQUID_MODEM_SQAM128: *_num_iterations *= 16; break; case LIQUID_MODEM_V29: *_num_iterations *= 100; break; case LIQUID_MODEM_ARB16OPT: *_num_iterations *= 100; break; case LIQUID_MODEM_ARB32OPT: *_num_iterations *= 100; break; case LIQUID_MODEM_ARB64OPT: *_num_iterations *= 100; break; case LIQUID_MODEM_ARB128OPT: *_num_iterations *= 100; break; case LIQUID_MODEM_ARB256OPT: *_num_iterations *= 100; break; case LIQUID_MODEM_ARB64VT: *_num_iterations *= 100; break; default:; *_num_iterations *= 32; } if (*_num_iterations < 1) *_num_iterations = 1; // initialize modulator modem mod = modem_create(_ms); float complex x; unsigned int symbol_in = 0; unsigned long int i; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { modem_modulate(mod, symbol_in, &x); modem_modulate(mod, symbol_in, &x); modem_modulate(mod, symbol_in, &x); modem_modulate(mod, symbol_in, &x); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; modem_destroy(mod); }
// Help function to keep code base small void modem_test_demodsoft(modulation_scheme _ms) { // generate mod/demod modem mod = modem_create(_ms); modem demod = modem_create(_ms); // unsigned int bps = modem_get_bps(demod); // run the test unsigned int i, s, M=1<<bps; unsigned int sym_soft; unsigned char soft_bits[bps]; float complex x; for (i=0; i<M; i++) { // modulate symbol modem_modulate(mod, i, &x); // demodulate using soft-decision modem_demodulate_soft(demod, x, &s, soft_bits); // check hard-decision output CONTEND_EQUALITY(s, i); // check soft bits liquid_pack_soft_bits(soft_bits, bps, &sym_soft); CONTEND_EQUALITY(sym_soft, i); // check phase error, evm, etc. //CONTEND_DELTA( modem_get_demodulator_phase_error(demod), 0.0f, 1e-3f); //CONTEND_DELTA( modem_get_demodulator_evm(demod), 0.0f, 1e-3f); } // clean it up modem_destroy(mod); modem_destroy(demod); }
int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int M = 64; // number of subcarriers unsigned int cp_len = 16; // cyclic prefix length unsigned int taper_len = 0; // taper length unsigned int num_symbols = 1000; // number of data symbols modulation_scheme ms = LIQUID_MODEM_QPSK; // get options int dopt; while((dopt = getopt(argc,argv,"hM:C:T:N:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'M': M = atoi(optarg); break; case 'C': cp_len = atoi(optarg); break; case 'T': taper_len = atoi(optarg); break; case 'N': num_symbols = atoi(optarg); break; default: exit(1); } } unsigned int i; // derived values unsigned int frame_len = M + cp_len; // initialize subcarrier allocation unsigned char p[M]; ofdmframe_init_default_sctype(M, p); // create frame generator ofdmframegen fg = ofdmframegen_create(M, cp_len, taper_len, p); ofdmframegen_print(fg); modem mod = modem_create(ms); float complex X[M]; // channelized symbols float complex buffer[frame_len];// output time series float * PAPR = (float*) malloc(num_symbols*sizeof(float)); // histogram display float xmin = -1.29f + 0.70f*log2f(M); float xmax = 8.97f + 0.34f*log2f(M); unsigned int num_bins = 30; float bin_width = (xmax - xmin) / (num_bins); unsigned int hist[num_bins]; for (i=0; i<num_bins; i++) hist[i] = 0; // modulate data symbols unsigned int j; unsigned int s; float PAPR_min = 0.0f; float PAPR_max = 0.0f; float PAPR_mean = 0.0f; for (i=0; i<num_symbols; i++) { // data symbol for (j=0; j<M; j++) { s = modem_gen_rand_sym(mod); modem_modulate(mod,s,&X[j]); } // generate symbol ofdmframegen_writesymbol(fg, X, buffer); #if 0 // preamble if (i==0) ofdmframegen_write_S0a(fg, buffer); // S0 symbol (first) else if (i==1) ofdmframegen_write_S0b(fg, buffer); // S0 symbol (second) else if (i==2) ofdmframegen_write_S1( fg, buffer); // S1 symbol #endif // compute PAPR PAPR[i] = ofdmframe_PAPR(buffer, frame_len); // compute bin index unsigned int index; float ihat = num_bins * (PAPR[i] - xmin) / (xmax - xmin); if (ihat < 0.0f) index = 0; else index = (unsigned int)ihat; if (index >= num_bins) index = num_bins-1; hist[index]++; // save min/max PAPR values if (i==0 || PAPR[i] < PAPR_min) PAPR_min = PAPR[i]; if (i==0 || PAPR[i] > PAPR_max) PAPR_max = PAPR[i]; PAPR_mean += PAPR[i]; } PAPR_mean /= (float)num_symbols; // destroy objects ofdmframegen_destroy(fg); modem_destroy(mod); // print results to screen // find max(hist) unsigned int hist_max = 0; for (i=0; i<num_bins; i++) hist_max = hist[i] > hist_max ? hist[i] : hist_max; printf("%8s : %6s [%6s]\n", "PAPR[dB]", "count", "prob."); for (i=0; i<num_bins; i++) { printf("%8.2f : %6u [%6.4f]", xmin + i*bin_width, hist[i], (float)hist[i] / (float)num_symbols); unsigned int k; unsigned int n = round(60 * (float)hist[i] / (float)hist_max); for (k=0; k<n; k++) printf("#"); printf("\n"); } printf("\n"); printf("min PAPR: %12.4f dB\n", PAPR_min); printf("max PAPR: %12.4f dB\n", PAPR_max); printf("mean PAPR: %12.4f dB\n", PAPR_mean); // // export output file // // count subcarrier types unsigned int M_data = 0; unsigned int M_pilot = 0; unsigned int M_null = 0; ofdmframe_validate_sctype(p, M, &M_null, &M_pilot, &M_data); 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\n"); fprintf(fid,"M = %u;\n", M); fprintf(fid,"M_data = %u;\n", M_data); fprintf(fid,"M_pilot = %u;\n", M_pilot); fprintf(fid,"M_null = %u;\n", M_null); fprintf(fid,"cp_len = %u;\n", cp_len); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"PAPR = zeros(1,num_symbols);\n"); for (i=0; i<num_symbols; i++) fprintf(fid," PAPR(%6u) = %12.4e;\n", i+1, PAPR[i]); fprintf(fid,"\n"); fprintf(fid,"figure;\n"); fprintf(fid,"hist(PAPR,25);\n"); fprintf(fid,"\n"); fprintf(fid,"figure;\n"); fprintf(fid,"cdf = [(1:num_symbols)-0.5]/num_symbols;\n"); fprintf(fid,"semilogy(sort(PAPR),1-cdf);\n"); fprintf(fid,"xlabel('PAPR [dB]');\n"); fprintf(fid,"ylabel('Complementary CDF');\n"); fclose(fid); printf("results written to %s\n", OUTPUT_FILENAME); // free allocated array free(PAPR); printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { // create mod/demod objects modulation_scheme ms = LIQUID_MODEM_ARB64VT; modulation_scheme mref = LIQUID_MODEM_QAM64; float alpha = 1.0f; int dopt; while ((dopt = getopt(argc,argv,"uhp:m:r:a:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'm': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme '%s'\n", argv[0], optarg); return 1; } break; case 'r': mref = liquid_getopt_str2mod(optarg); if (mref == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme '%s'\n", argv[0], optarg); return 1; } break; case 'a': alpha = atof(optarg); break; default: exit(1); } } // validate input unsigned int i; unsigned int j; // initialize reference points modem qref = modem_create(mref); unsigned int kref = modem_get_bps(qref); unsigned int p = 1 << kref; float complex cref[p]; for (i=0; i<p; i++) { modem_modulate(qref, i, &cref[i]); cref[i] *= alpha; } modem_destroy(qref); // generate the constellation modem q = modem_create(ms); unsigned int bps = modem_get_bps(q); unsigned int M = 1 << bps; float complex constellation[M]; for (i=0; i<M; i++) modem_modulate(q, i, &constellation[i]); modem_destroy(q); // perform search unsigned char * link = NULL; unsigned int num_unassigned=M; unsigned char unassigned[M]; unsigned int s=0; // number of points per reference // run search until all points are found do { // increment number of points per reference s++; // reallocte memory for links link = (unsigned char*) realloc(link, p*s); // search for nearest constellation points to reference points modem_arbref_search(constellation, M, cref, p, link, s); // find unassigned constellation points num_unassigned = modem_arbref_search_unassigned(link,M,p,s,unassigned); printf("%3u : number of unassigned points: %3u / %3u\n", s, num_unassigned, M); } while (num_unassigned > 0); // print table printf("\n"); printf("unsigned char modem_demodulate_gentab[%u][%u] = {\n", p, s); for (i=0; i<p; i++) { printf(" {"); for (j=0; j<s; j++) { printf("%3u%s", link[i*s+j], j==(s-1) ? "" : ","); } printf("}%s", i==(p-1) ? "};\n" : ",\n"); } // // 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"); fprintf(fid,"bps = %u;\n", bps); fprintf(fid,"M = %u;\n", M); fprintf(fid,"p = %u;\n", p); fprintf(fid,"s = %u;\n", s); // save constellation points for (i=0; i<M; i++) { fprintf(fid,"c(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(constellation[i]), cimagf(constellation[i])); } // save reference points for (i=0; i<p; i++) fprintf(fid,"cref(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(cref[i]), cimagf(cref[i])); // save reference matrix fprintf(fid,"link = zeros(p,s);\n"); for (i=0; i<p; i++) { for (j=0; j<s; j++) { fprintf(fid,"link(%3u,%3u) = %u;\n", i+1, j+1, link[i*s+j]+1); } } // plot results fprintf(fid,"figure;\n"); fprintf(fid,"plot(real(c), imag(c), 'bx',\n"); fprintf(fid," real(cref), imag(cref),'or');\n"); // draw lines between reference points and associated constellation points fprintf(fid,"hold on;\n"); fprintf(fid," for i=1:p,\n"); fprintf(fid," for j=1:s,\n"); fprintf(fid," plot([real(cref(i)) real(c(link(i,j)))], [imag(cref(i)) imag(c(link(i,j)))], '-', 'Color', 0.8*[1 1 1]);\n"); fprintf(fid," end;\n"); fprintf(fid," end;\n"); fprintf(fid,"hold off;\n"); fprintf(fid,"xlabel('in-phase');\n"); fprintf(fid,"ylabel('quadrature phase');\n"); fprintf(fid,"%%legend('constellation','reference','links',0);\n"); fprintf(fid,"title(['Arbitrary ' num2str(M) '-QAM']);\n"); fprintf(fid,"axis([-1 1 -1 1]*1.9);\n"); fprintf(fid,"axis square;\n"); fprintf(fid,"grid on;\n"); fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME); printf("done.\n"); // free allocated memory free(link); 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 num_symbols=500; // number of symbols to observe float SNRdB = 30.0f; // signal-to-noise ratio [dB] unsigned int hc_len=5; // channel filter length unsigned int k=2; // matched filter samples/symbol unsigned int m=3; // matched filter delay (symbols) float beta=0.3f; // matched filter excess bandwidth factor unsigned int p=3; // equalizer length (symbols, hp_len = 2*k*p+1) float mu = 0.08f; // learning rate // modulation type/depth modulation_scheme ms = LIQUID_MODEM_QPSK; int dopt; while ((dopt = getopt(argc,argv,"hn:s:c:k:m:b:p:u:M:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'c': hc_len = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'p': p = atoi(optarg); break; case 'u': mu = atof(optarg); break; case 'M': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme '%s'\n", argv[0], optarg); return 1; } break; default: exit(1); } } // validate input if (num_symbols == 0) { fprintf(stderr,"error: %s, number of symbols must be greater than zero\n", argv[0]); exit(1); } else if (hc_len == 0) { fprintf(stderr,"error: %s, channel must have at least 1 tap\n", argv[0]); exit(1); } else if (k < 2) { fprintf(stderr,"error: %s, samples/symbol must be at least 2\n", argv[0]); exit(1); } else if (m == 0) { fprintf(stderr,"error: %s, filter semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (beta < 0.0f || beta > 1.0f) { fprintf(stderr,"error: %s, filter excess bandwidth must be in [0,1]\n", argv[0]); exit(1); } else if (p == 0) { fprintf(stderr,"error: %s, equalizer semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (mu < 0.0f || mu > 1.0f) { fprintf(stderr,"error: %s, equalizer learning rate must be in [0,1]\n", argv[0]); exit(1); } // derived values unsigned int hm_len = 2*k*m+1; // matched filter length unsigned int hp_len = 2*k*p+1; // equalizer filter length unsigned int num_samples = k*num_symbols; // bookkeeping variables float complex sym_tx[num_symbols]; // transmitted data sequence float complex x[num_samples]; // interpolated time series float complex y[num_samples]; // channel output float complex z[num_samples]; // equalized output float hm[hm_len]; // matched filter response float complex hc[hc_len]; // channel filter coefficients float complex hp[hp_len]; // equalizer filter coefficients unsigned int i; // generate matched filter response liquid_firdes_rnyquist(LIQUID_FIRFILT_RRC, k, m, beta, 0.0f, hm); firinterp_crcf interp = firinterp_crcf_create(k, hm, hm_len); // create the modem objects modem mod = modem_create(ms); modem demod = modem_create(ms); unsigned int M = 1 << modem_get_bps(mod); // generate channel impulse response, filter hc[0] = 1.0f; for (i=1; i<hc_len; i++) hc[i] = 0.09f*(randnf() + randnf()*_Complex_I); firfilt_cccf fchannel = firfilt_cccf_create(hc, hc_len); // generate random symbols for (i=0; i<num_symbols; i++) modem_modulate(mod, rand()%M, &sym_tx[i]); // interpolate for (i=0; i<num_symbols; i++) firinterp_crcf_execute(interp, sym_tx[i], &x[i*k]); // push through channel float nstd = powf(10.0f, -SNRdB/20.0f); for (i=0; i<num_samples; i++) { firfilt_cccf_push(fchannel, x[i]); firfilt_cccf_execute(fchannel, &y[i]); // add noise y[i] += nstd*(randnf() + randnf()*_Complex_I)*M_SQRT1_2; } // push through equalizer // create equalizer, intialized with square-root Nyquist filter eqlms_cccf eq = eqlms_cccf_create_rnyquist(LIQUID_FIRFILT_RRC, k, p, beta, 0.0f); eqlms_cccf_set_bw(eq, mu); // get initialized weights eqlms_cccf_get_weights(eq, hp); // filtered error vector magnitude (emperical RMS error) float evm_hat = 0.03f; float complex d_hat = 0.0f; for (i=0; i<num_samples; i++) { // print filtered evm (emperical rms error) if ( ((i+1)%50)==0 ) printf("%4u : rms error = %12.8f dB\n", i+1, 10*log10(evm_hat)); eqlms_cccf_push(eq, y[i]); eqlms_cccf_execute(eq, &d_hat); // store output z[i] = d_hat; // decimate by k if ( (i%k) != 0 ) continue; // estimate transmitted signal unsigned int sym_out; // output symbol float complex d_prime; // estimated input sample modem_demodulate(demod, d_hat, &sym_out); modem_get_demodulator_sample(demod, &d_prime); // update equalizer eqlms_cccf_step(eq, d_prime, d_hat); // update filtered evm estimate float evm = crealf( (d_prime-d_hat)*conjf(d_prime-d_hat) ); evm_hat = 0.98f*evm_hat + 0.02f*evm; } // get equalizer weights eqlms_cccf_get_weights(eq, hp); // destroy objects eqlms_cccf_destroy(eq); firinterp_crcf_destroy(interp); firfilt_cccf_destroy(fchannel); modem_destroy(mod); modem_destroy(demod); // // export output // 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,"k = %u;\n", k); fprintf(fid,"m = %u;\n", m); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"num_samples = num_symbols*k;\n"); // save transmit matched-filter response fprintf(fid,"hm_len = 2*k*m+1;\n"); fprintf(fid,"hm = zeros(1,hm_len);\n"); for (i=0; i<hm_len; i++) fprintf(fid,"hm(%4u) = %12.4e;\n", i+1, hm[i]); // save channel impulse response fprintf(fid,"hc_len = %u;\n", hc_len); fprintf(fid,"hc = zeros(1,hc_len);\n"); for (i=0; i<hc_len; i++) fprintf(fid,"hc(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(hc[i]), cimagf(hc[i])); // save equalizer response fprintf(fid,"hp_len = %u;\n", hp_len); fprintf(fid,"hp = zeros(1,hp_len);\n"); for (i=0; i<hp_len; i++) fprintf(fid,"hp(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(hp[i]), cimagf(hp[i])); // save sample sets fprintf(fid,"x = zeros(1,num_samples);\n"); fprintf(fid,"y = zeros(1,num_samples);\n"); fprintf(fid,"z = zeros(1,num_samples);\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,"z(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(z[i]), cimagf(z[i])); } // plot time response fprintf(fid,"t = 0:(num_samples-1);\n"); fprintf(fid,"tsym = 1:k:num_samples;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(t,real(z),...\n"); fprintf(fid," t(tsym),real(z(tsym)),'x');\n"); // plot constellation fprintf(fid,"tsym0 = tsym(1:(length(tsym)/2));\n"); fprintf(fid,"tsym1 = tsym((length(tsym)/2):end);\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(real(z(tsym0)),imag(z(tsym0)),'x','Color',[1 1 1]*0.7,...\n"); fprintf(fid," real(z(tsym1)),imag(z(tsym1)),'x','Color',[1 1 1]*0.0);\n"); fprintf(fid,"xlabel('In-Phase');\n"); fprintf(fid,"ylabel('Quadrature');\n"); fprintf(fid,"axis([-1 1 -1 1]*1.5);\n"); fprintf(fid,"axis square;\n"); fprintf(fid,"grid on;\n"); // compute composite response fprintf(fid,"g = real(conv(conv(hm,hc),hp));\n"); // plot responses fprintf(fid,"nfft = 1024;\n"); fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"Hm = 20*log10(abs(fftshift(fft(hm/k,nfft))));\n"); fprintf(fid,"Hc = 20*log10(abs(fftshift(fft(hc, nfft))));\n"); fprintf(fid,"Hp = 20*log10(abs(fftshift(fft(hp, nfft))));\n"); fprintf(fid,"G = 20*log10(abs(fftshift(fft(g/k, nfft))));\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(f,Hm, f,Hc, f,Hp, f,G,'-k','LineWidth',2, [-0.5/k 0.5/k],[-6.026 -6.026],'or');\n"); fprintf(fid,"xlabel('Normalized Frequency');\n"); fprintf(fid,"ylabel('Power Spectral Density');\n"); fprintf(fid,"legend('transmit','channel','equalizer','composite','half-power points',1);\n"); fprintf(fid,"axis([-0.5 0.5 -12 8]);\n"); fprintf(fid,"grid on;\n"); fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME); return 0; }
MAskFunction::~MAskFunction() { modem_destroy(_mod); }
ModemQPSK::~ModemQPSK() { modem_destroy(demodQPSK); }
int main(int argc, char*argv[]) { // options unsigned int bps=6; // bits per symbol unsigned int n=1024; // number of data points to evaluate int dopt; while ((dopt = getopt(argc,argv,"uhp:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'p': bps = atoi(optarg); break; default: exit(1); } } // validate input if (bps == 0) { fprintf(stderr,"error: %s, bits/symbol must be greater than zero\n", argv[0]); exit(1); } // derived values unsigned int i; unsigned int M = 1<<bps; // constellation size // initialize constellation table float complex constellation[M]; // initialize constellation (spiral) for (i=0; i<M; i++) { float r = (float)i / logf((float)M) + 4.0f; float phi = (float)i / logf((float)M); constellation[i] = r * cexpf(_Complex_I*phi); } // create mod/demod objects modem mod = modem_create_arbitrary(constellation, M); modem demod = modem_create_arbitrary(constellation, M); modem_print(mod); // run simulation float complex x[n]; unsigned int num_errors = 0; // run simple BER simulation num_errors = 0; unsigned int sym_in; unsigned int sym_out; for (i=0; i<n; i++) { // generate and modulate random symbol sym_in = modem_gen_rand_sym(mod); modem_modulate(mod, sym_in, &x[i]); // add noise x[i] += 0.05 * randnf() * cexpf(_Complex_I*M_PI*randf()); // demodulate modem_demodulate(demod, x[i], &sym_out); // accumulate errors num_errors += count_bit_errors(sym_in,sym_out); } printf("num bit errors: %4u / %4u\n", num_errors, bps*n); // destroy modem objects modem_destroy(mod); modem_destroy(demod); // // 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"); fprintf(fid,"bps = %u;\n", bps); fprintf(fid,"M = %u;\n", M); for (i=0; i<n; i++) { fprintf(fid,"x(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i])); } // plot results fprintf(fid,"figure;\n"); fprintf(fid,"plot(x,'x','MarkerSize',1);\n"); fprintf(fid,"xlabel('in-phase');\n"); fprintf(fid,"ylabel('quadrature phase');\n"); fprintf(fid,"title(['Arbitrary ' num2str(M) '-QAM']);\n"); fprintf(fid,"axis([-1 1 -1 1]*1.9);\n"); fprintf(fid,"axis square;\n"); fprintf(fid,"grid on;\n"); fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main() { // options unsigned int num_channels=6; // for now, must be even number unsigned int num_symbols=32; // num symbols unsigned int m=2; // ofdm/oqam symbol delay float beta = 0.99f; // excess bandwidth factor float dt = 0.0f; // timing offset (fractional sample) modulation_scheme ms = LIQUID_MODEM_QAM4; // modulation scheme // number of frames (compensate for filter delay) unsigned int num_frames = num_symbols + 2*m; unsigned int num_samples = num_channels * num_frames; // create synthesizer/analyzer objects ofdmoqam cs = ofdmoqam_create(num_channels, m, beta, dt, LIQUID_SYNTHESIZER,0); ofdmoqam ca = ofdmoqam_create(num_channels, m, beta, dt, LIQUID_ANALYZER,0); // modem modem mod = modem_create(ms); FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\nclose all;\n\n"); fprintf(fid,"num_channels=%u;\n", num_channels); fprintf(fid,"num_symbols=%u;\n", num_symbols); fprintf(fid,"num_frames = %u;\n", num_frames); fprintf(fid,"num_samples = num_frames*num_channels;\n"); fprintf(fid,"X = zeros(%u,%u);\n", num_channels, num_frames); fprintf(fid,"y = zeros(1,%u);\n", num_samples); fprintf(fid,"Y = zeros(%u,%u);\n", num_channels, num_frames); unsigned int i, j, n=0; unsigned int s[num_symbols][num_channels]; float complex X[num_channels]; // channelized symbols float complex y[num_channels]; // interpolated time-domain samples float complex Y[num_channels]; // received symbols // generate random symbols for (i=0; i<num_symbols; i++) { for (j=0; j<num_channels; j++) { s[i][j] = modem_gen_rand_sym(mod); } } for (i=0; i<num_frames; i++) { // generate frame data for (j=0; j<num_channels; j++) { if (i<num_symbols) { modem_modulate(mod,s[i][j],&X[j]); } else { X[j] = 0.0f; } } // execute synthesyzer ofdmoqam_execute(cs, X, y); // channel // execute analyzer ofdmoqam_execute(ca, y, Y); // write output to file for (j=0; j<num_channels; j++) { // frequency data fprintf(fid,"X(%4u,%4u) = %12.4e + j*%12.4e;\n", j+1, i+1, crealf(X[j]), cimagf(X[j])); // time data fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", n+1, crealf(y[j]), cimag(y[j])); // received data fprintf(fid,"Y(%4u,%4u) = %12.4e + j*%12.4e;\n", j+1, i+1, crealf(Y[j]), cimagf(Y[j])); n++; } } // print results fprintf(fid,"\n\n"); fprintf(fid,"X0 = X(:,1:%u);\n", num_symbols); fprintf(fid,"Y0 = Y(:,%u:%u);\n", 2*m+1, num_symbols + 2*m); fprintf(fid,"for i=1:num_channels,\n"); fprintf(fid," figure;\n"); fprintf(fid," subplot(2,1,1);\n"); fprintf(fid," plot(1:num_symbols,real(X0(i,:)),'-x',1:num_symbols,real(Y0(i,:)),'-x');\n"); fprintf(fid," ylabel('Re');\n"); fprintf(fid," title(['channel ' num2str(i-1)]);\n"); fprintf(fid," subplot(2,1,2);\n"); fprintf(fid," plot(1:num_symbols,imag(X0(i,:)),'-x',1:num_symbols,imag(Y0(i,:)),'-x');\n"); fprintf(fid," ylabel('Im');\n"); fprintf(fid," pause(0.2);\n"); fprintf(fid,"end;\n"); // print results fprintf(fid,"\n\n"); fprintf(fid,"t = 0:(num_samples-1);\n"); fprintf(fid," figure;\n"); fprintf(fid," plot(t,real(y),'-', t,imag(y),'-');\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('signal');\n"); fclose(fid); printf("results written to %s\n", OUTPUT_FILENAME); // destroy objects ofdmoqam_destroy(cs); ofdmoqam_destroy(ca); modem_destroy(mod); printf("done.\n"); return 0; }
// Helper function to keep code base small void ofdmframesync_rxsymbol_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _num_subcarriers, unsigned int _cp_len) { // options modulation_scheme ms = LIQUID_MODEM_QPSK; unsigned int M = _num_subcarriers; unsigned int cp_len = _cp_len; unsigned int taper_len = 0; // create synthesizer/analyzer objects ofdmframegen fg = ofdmframegen_create(M, cp_len, taper_len, NULL); //ofdmframegen_print(fg); modem mod = modem_create(ms); ofdmframesync fs = ofdmframesync_create(M,cp_len,taper_len,NULL,NULL,NULL); unsigned int i; float complex X[M]; // channelized symbol float complex x[M+cp_len]; // time-domain symbol // synchronize short sequence (first) ofdmframegen_write_S0a(fg, x); ofdmframesync_execute(fs, x, M+cp_len); // synchronize short sequence (second) ofdmframegen_write_S0b(fg, x); ofdmframesync_execute(fs, x, M+cp_len); // synchronize long sequence ofdmframegen_write_S1(fg, x); ofdmframesync_execute(fs, x, M+cp_len); // modulate data symbols (use same symbol, ignore pilot phase) unsigned int s; for (i=0; i<M; i++) { s = modem_gen_rand_sym(mod); modem_modulate(mod,s,&X[i]); } ofdmframegen_writesymbol(fg, X, x); // add noise for (i=0; i<M+cp_len; i++) x[i] += 0.02f*randnf()*cexpf(_Complex_I*2*M_PI*randf()); // normalize number of iterations *_num_iterations /= M; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { // receive data symbols (ignoring pilots) ofdmframesync_execute(fs, x, M+cp_len); ofdmframesync_execute(fs, x, M+cp_len); ofdmframesync_execute(fs, x, M+cp_len); ofdmframesync_execute(fs, x, M+cp_len); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; // destroy objects ofdmframegen_destroy(fg); ofdmframesync_destroy(fs); modem_destroy(mod); }
int main(int argc, char*argv[]) { srand( time(NULL) ); // options int verbose = 1; // verbose output flag float phi_max_abs = M_PI/4.0f; // absolute maximum phase offset unsigned int num_phi = 21; // number of phase steps unsigned int num_trials = 1000; // number of trials float SNRdB = 12.0f; // signal-to-noise ratio [dB] modulation_scheme ms = LIQUID_MODEM_QPSK; char filename[256] = ""; // output filename int dopt; while ((dopt = getopt(argc,argv,"uhvqn:t:s:P:m:o:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'v': verbose = 1; break; case 'q': verbose = 0; break; case 'n': num_phi = atoi(optarg); break; case 't': num_trials = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'P': phi_max_abs = atof(optarg); break; case 'm': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme \"%s\"\n", argv[0], optarg); return 1; } break; case 'o': strncpy(filename,optarg,255); break; default: exit(1); } } // validate input if (phi_max_abs <= 0.0f) { fprintf(stderr,"error: %s, maximum absolute phase offset must be greater than 0\n", argv[0]); exit(1); } else if (num_phi < 3) { fprintf(stderr,"error: %s, number of phase steps must be at least 3\n", argv[0]); exit(1); fprintf(stderr,"error: %s, number of trials must be greater than 0\n", argv[0]); exit(1); } unsigned int bps = modulation_types[ms].bps; // generate filenames if ( strcmp(filename,"")==0 ) sprintf(filename,"figures.gen/modem_phase_error_%s%u.dat", modulation_types[ms].name, 1<<bps); // derived values float phi_min = 0.0f; //phi_max_abs; float phi_max = phi_max_abs; float phi_step = (phi_max - phi_min) / (float)(num_phi-1); float nstd = powf(10.0f, -SNRdB/20.0f); // arrays float phi_hat_mean[num_phi]; // phase error estimate float phi_hat_mean_smooth[num_phi]; // phase error estimate (smoothed) // create modulator/demodulator modem mod = modem_create(ms); modem demod = modem_create(ms); unsigned int M = 1 << bps; // unsigned int i; unsigned int sym_in; unsigned int sym_out; unsigned int n=0; // trials counter float complex x; float phi_hat; float phi=0.0f; for (i=0; i<num_phi; i++) { phi = phi_min + i*phi_step; phi_hat_mean[i] = 0.0f; // reset number of trials n = 0; do { for (sym_in=0; sym_in<M; sym_in++) { // modulate modem_modulate(mod, sym_in, &x); // channel (phase offset) x *= cexpf(_Complex_I*phi); x += nstd * (randnf() + _Complex_I*randnf()) * M_SQRT1_2; // demodulate modem_demodulate(demod, x, &sym_out); // get error phi_hat = modem_get_demodulator_phase_error(demod); // accumulate average phi_hat_mean[i] += phi_hat; } n += M; } while (n < num_trials); // scale by bps^2 //phi_hat_mean[i] *= bps*bps; // normalize mean by number of trials phi_hat_mean[i] /= (float) (n); // print results if (verbose) printf("%6u / %6u : phi=%12.8f, phi-hat=%12.8f\n", i+1, num_phi, phi, phi_hat_mean[i]); } // compute smoothed curve float phi_hat_tmp[num_phi]; memmove(phi_hat_mean_smooth, phi_hat_mean, num_phi*sizeof(float)); unsigned int j; for (j=0; j<5; j++) { memmove(phi_hat_tmp, phi_hat_mean_smooth, num_phi*sizeof(float)); for (i=0; i<num_phi; i++) { if (i==0 || i == num_phi-1) { phi_hat_mean_smooth[i] = phi_hat_tmp[i]; } else { phi_hat_mean_smooth[i] = 0.20f*phi_hat_tmp[i-1] + 0.60f*phi_hat_tmp[i ] + 0.20f*phi_hat_tmp[i+1]; } } } // destroy objects modem_destroy(mod); modem_destroy(demod); // // export output file // FILE * fid = fopen(filename,"w"); if (!fid) { fprintf(stderr,"error: %s, cannot open '%s' for writing\n", argv[0], filename); exit(1); } fprintf(fid, "# %s : auto-generated file\n", filename); fprintf(fid, "# \n"); // low SNR fprintf(fid, "# %12s %12s %12s\n", "phi", "phi-hat", "phi-hat-smooth"); for (i=0; i<num_phi; i++) { phi = phi_min + i*phi_step; fprintf(fid," %12.8f %12.8f %12.8f\n", phi, phi_hat_mean[i], phi_hat_mean_smooth[i]); } fclose(fid); if (verbose) printf("results written to '%s'\n", filename); return 0; }
ModemOOK::~ModemOOK() { modem_destroy(demodOOK); }
// Helper function to keep code base small void modem_demodulate_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, modulation_scheme _ms) { // normalize number of iterations switch (_ms) { case LIQUID_MODEM_UNKNOWN: fprintf(stderr,"error: modem_demodulate_bench(), unknown modem scheme\n"); exit(1); case LIQUID_MODEM_BPSK: *_num_iterations *= 2; break; case LIQUID_MODEM_QPSK: *_num_iterations *= 2; break; case LIQUID_MODEM_OOK: *_num_iterations *= 2; break; case LIQUID_MODEM_SQAM32: *_num_iterations /= 10; break; case LIQUID_MODEM_SQAM128: *_num_iterations /= 20; break; case LIQUID_MODEM_V29: *_num_iterations /= 16; break; case LIQUID_MODEM_ARB16OPT: *_num_iterations /= 8; break; case LIQUID_MODEM_ARB32OPT: *_num_iterations /= 16; break; case LIQUID_MODEM_ARB64OPT: *_num_iterations /= 32; break; case LIQUID_MODEM_ARB128OPT: *_num_iterations /= 64; break; case LIQUID_MODEM_ARB256OPT: *_num_iterations /= 128; break; case LIQUID_MODEM_ARB64VT: *_num_iterations /= 64; break; default:; *_num_iterations /= 8; } if (*_num_iterations < 1) *_num_iterations = 1; // initialize modulator modem demod = modem_create(_ms); unsigned long int i; // generate input vector to demodulate (spiral) float complex x[20]; for (i=0; i<20; i++) x[i] = 0.07 * i * cexpf(_Complex_I*2*M_PI*0.1*i); unsigned int symbol_out; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { modem_demodulate(demod, x[ 0], &symbol_out); modem_demodulate(demod, x[ 1], &symbol_out); modem_demodulate(demod, x[ 2], &symbol_out); modem_demodulate(demod, x[ 3], &symbol_out); modem_demodulate(demod, x[ 4], &symbol_out); modem_demodulate(demod, x[ 5], &symbol_out); modem_demodulate(demod, x[ 6], &symbol_out); modem_demodulate(demod, x[ 7], &symbol_out); modem_demodulate(demod, x[ 8], &symbol_out); modem_demodulate(demod, x[ 9], &symbol_out); modem_demodulate(demod, x[10], &symbol_out); modem_demodulate(demod, x[11], &symbol_out); modem_demodulate(demod, x[12], &symbol_out); modem_demodulate(demod, x[13], &symbol_out); modem_demodulate(demod, x[14], &symbol_out); modem_demodulate(demod, x[15], &symbol_out); modem_demodulate(demod, x[16], &symbol_out); modem_demodulate(demod, x[17], &symbol_out); modem_demodulate(demod, x[18], &symbol_out); modem_demodulate(demod, x[19], &symbol_out); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 20; modem_destroy(demod); }
int main(int argc, char*argv[]) { srand( time(NULL) ); // parameters float phase_offset = M_PI/10; float frequency_offset = 0.001f; float SNRdB = 30.0f; float pll_bandwidth = 0.02f; modulation_scheme ms = LIQUID_MODEM_QPSK; unsigned int n=256; // number of iterations int dopt; while ((dopt = getopt(argc,argv,"uhs:b:n:P:F:m:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 's': SNRdB = atof(optarg); break; case 'b': pll_bandwidth = atof(optarg); break; case 'n': n = atoi(optarg); break; case 'P': phase_offset = atof(optarg); break; case 'F': frequency_offset= atof(optarg); break; case 'm': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme \"%s\"\n", argv[0], optarg); return 1; } break; default: exit(1); } } unsigned int d=n/32; // print every "d" lines FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid, "%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid, "clear all;\n"); fprintf(fid, "phi=zeros(1,%u);\n",n); fprintf(fid, "r=zeros(1,%u);\n",n); // objects nco_crcf nco_tx = nco_crcf_create(LIQUID_VCO); nco_crcf nco_rx = nco_crcf_create(LIQUID_VCO); modem mod = modem_create(ms); modem demod = modem_create(ms); unsigned int bps = modem_get_bps(mod); // initialize objects nco_crcf_set_phase(nco_tx, phase_offset); nco_crcf_set_frequency(nco_tx, frequency_offset); nco_crcf_pll_set_bandwidth(nco_rx, pll_bandwidth); float noise_power = powf(10.0f, -SNRdB/20.0f); // print parameters printf("PLL example :\n"); printf("modem : %u-%s\n", 1<<bps, modulation_types[ms].name); printf("frequency offset: %6.3f, phase offset: %6.3f, SNR: %6.2fdB, pll b/w: %6.3f\n", frequency_offset, phase_offset, SNRdB, pll_bandwidth); // run loop unsigned int i, M=1<<bps, sym_in, sym_out, num_errors=0; float phase_error; float complex x, r, v, noise; for (i=0; i<n; i++) { // generate random symbol sym_in = rand() % M; // modulate modem_modulate(mod, sym_in, &x); // channel //r = nco_crcf_cexpf(nco_tx); nco_crcf_mix_up(nco_tx, x, &r); // add complex white noise crandnf(&noise); r += noise * noise_power; // //v = nco_crcf_cexpf(nco_rx); nco_crcf_mix_down(nco_rx, r, &v); // demodulate modem_demodulate(demod, v, &sym_out); num_errors += count_bit_errors(sym_in, sym_out); // error estimation //phase_error = cargf(r*conjf(v)); phase_error = modem_get_demodulator_phase_error(demod); // perfect error estimation //phase_error = nco_tx->theta - nco_rx->theta; // print every line in a format that octave can read fprintf(fid, "phi(%u) = %10.6E;\n", i+1, phase_error); fprintf(fid, "r(%u) = %10.6E + j*%10.6E;\n", i+1, crealf(v), cimagf(v)); if ((i+1)%d == 0 || i==n-1) { printf(" %4u: e_hat : %6.3f, phase error : %6.3f, freq error : %6.3f\n", i+1, // iteration phase_error, // estimated phase error nco_crcf_get_phase(nco_tx) - nco_crcf_get_phase(nco_rx),// true phase error nco_crcf_get_frequency(nco_tx) - nco_crcf_get_frequency(nco_rx)// true frequency error ); } // update tx nco object nco_crcf_step(nco_tx); // update pll nco_crcf_pll_step(nco_rx, phase_error); // update rx nco object nco_crcf_step(nco_rx); } fprintf(fid, "figure;\n"); fprintf(fid, "plot(1:length(phi),phi,'LineWidth',2,'Color',[0 0.25 0.5]);\n"); fprintf(fid, "xlabel('Symbol Index');\n"); fprintf(fid, "ylabel('Phase Error [radians]');\n"); fprintf(fid, "grid on;\n"); fprintf(fid, "t0 = round(0.25*length(r));\n"); fprintf(fid, "figure;\n"); fprintf(fid, "plot(r(1:t0),'x','Color',[0.6 0.6 0.6],r(t0:end),'x','Color',[0 0.25 0.5]);\n"); fprintf(fid, "grid on;\n"); fprintf(fid, "axis([-1.5 1.5 -1.5 1.5]);\n"); fprintf(fid, "axis('square');\n"); fprintf(fid, "xlabel('In-Phase');\n"); fprintf(fid, "ylabel('Quadrature');\n"); fprintf(fid, "legend(['first 25%%'],['last 75%%'],1);\n"); fclose(fid); printf("results written to %s.\n",OUTPUT_FILENAME); nco_crcf_destroy(nco_tx); nco_crcf_destroy(nco_rx); modem_destroy(mod); modem_destroy(demod); printf("bit errors: %u / %u\n", num_errors, bps*n); printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { // create mod/demod objects float gnuplot_version=0.0; enum {GNUPLOT_TERM_PNG=0, GNUPLOT_TERM_JPG, GNUPLOT_TERM_EPS } gnuplot_term = 0; char input_filename[256] = "datafile.dat"; char output_filename[256] = "modem.gnu"; //char figure_title[256] = "constellation"; modulation_scheme ms = LIQUID_MODEM_QPSK; int dopt; while ((dopt = getopt(argc,argv,"uhg:t:d:f:m:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'g': gnuplot_version = atof(optarg); break; case 't': gnuplot_term = atoi(optarg); break; case 'd': strncpy(input_filename,optarg,256); break; case 'f': strncpy(output_filename,optarg,256); break; case 'm': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme \"%s\"\n", argv[0], optarg); return 1; } break; default: exit(1); } } // TODO : validate input if (ms == LIQUID_MODEM_UNKNOWN || ms >= LIQUID_MODEM_NUM_SCHEMES) { fprintf(stderr,"error: %s, invalid modulation scheme \n", argv[0]); return 1; } // derived options/values unsigned int bps = modulation_types[ms].bps; int plot_labels = (gnuplot_version > 4.1) && (bps < 8); int plot_long_labels = 0; unsigned int i; // generate modem, compute constellation, derive plot style accordingly unsigned int M = 1<<bps; float complex constellation[M]; modem q = modem_create(ms); for (i=0; i<M; i++) modem_modulate(q, i, &constellation[i]); modem_destroy(q); float range = 1.5f; enum {AXES_POLAR, AXES_CART} axes = AXES_POLAR; switch (ms) { // Phase-shift keying (PSK) case LIQUID_MODEM_PSK2: case LIQUID_MODEM_PSK4: case LIQUID_MODEM_PSK8: case LIQUID_MODEM_PSK16: case LIQUID_MODEM_PSK32: case LIQUID_MODEM_PSK64: case LIQUID_MODEM_PSK128: case LIQUID_MODEM_PSK256: // Differential phase-shift keying (DPSK) case LIQUID_MODEM_DPSK2: case LIQUID_MODEM_DPSK4: case LIQUID_MODEM_DPSK8: case LIQUID_MODEM_DPSK16: case LIQUID_MODEM_DPSK32: case LIQUID_MODEM_DPSK64: case LIQUID_MODEM_DPSK128: case LIQUID_MODEM_DPSK256: range = 1.2f; axes = AXES_POLAR; break; // amplitude-shift keying (ASK) case LIQUID_MODEM_ASK2: range = 1.2f; axes = AXES_CART; break; case LIQUID_MODEM_ASK4: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_ASK8: range = 1.75f; axes = AXES_CART; break; case LIQUID_MODEM_ASK16: range = 2.00f; axes = AXES_CART; break; case LIQUID_MODEM_ASK32: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_ASK64: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_ASK128: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_ASK256: range = 1.5f; axes = AXES_CART; break; // rectangular quadrature amplitude-shift keying (QAM) case LIQUID_MODEM_QAM4: range = 1.75f; axes = AXES_CART; break; case LIQUID_MODEM_QAM8: range = 1.75f; axes = AXES_CART; break; case LIQUID_MODEM_QAM16: range = 1.75f; axes = AXES_CART; break; case LIQUID_MODEM_QAM32: range = 1.75f; axes = AXES_CART; break; case LIQUID_MODEM_QAM64: range = 1.75f; axes = AXES_CART; break; case LIQUID_MODEM_QAM128: range = 1.75f; axes = AXES_CART; break; case LIQUID_MODEM_QAM256: range = 1.75f; axes = AXES_CART; break; // amplitude phase-shift keying (APSK) case LIQUID_MODEM_APSK4: range = 1.5f; axes = AXES_POLAR; break; case LIQUID_MODEM_APSK8: range = 1.5f; axes = AXES_POLAR; break; case LIQUID_MODEM_APSK16: range = 1.5f; axes = AXES_POLAR; break; case LIQUID_MODEM_APSK32: range = 1.5f; axes = AXES_POLAR; break; case LIQUID_MODEM_APSK64: range = 1.5f; axes = AXES_POLAR; break; case LIQUID_MODEM_APSK128: range = 1.5f; axes = AXES_POLAR; break; case LIQUID_MODEM_APSK256: range = 1.5f; axes = AXES_POLAR; break; // specific modems case LIQUID_MODEM_BPSK: range = 1.5f; axes = AXES_POLAR; break; case LIQUID_MODEM_QPSK: range = 1.5f; axes = AXES_POLAR; break; case LIQUID_MODEM_OOK: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_SQAM32: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_SQAM128: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_V29: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_ARB16OPT: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_ARB32OPT: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_ARB64OPT: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_ARB128OPT: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_ARB256OPT: range = 1.5f; axes = AXES_CART; break; case LIQUID_MODEM_ARB64VT: range = 2.0f; axes = AXES_CART; break; default: fprintf(stderr,"error: %s, invalid modulation scheme\n", argv[0]); exit(1); } // determine minimum distance between any two points float dmin = 0.0f; for (i=0; i<M; i++) { unsigned int j; for (j=i+1; j<M; j++) { float d = cabsf(constellation[i] - constellation[j]); if ( (d < dmin) || (i==0 && j==1) ) dmin = d; } } plot_long_labels = dmin < 0.34 ? 0 : 1; // write output file FILE * fid = fopen(output_filename,"w"); if (fid == NULL) { fprintf(stderr,"error: %s, could not open file \"%s\" for writing.\n", argv[0],output_filename); exit(1); } // print header fprintf(fid,"# %s : auto-generated file (do not edit)\n", output_filename); fprintf(fid,"# invoked as :"); for (i=0; i<argc; i++) fprintf(fid," %s",argv[i]); fprintf(fid,"\n"); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); // TODO : set range according to scheme fprintf(fid,"set xrange [-%4.2f:%4.2f]\n",range,range); fprintf(fid,"set yrange [-%4.2f:%4.2f]\n",range,range); fprintf(fid,"set size square\n"); //fprintf(fid,"set title \"%s\"\n", figure_title); fprintf(fid,"set xlabel \"I\"\n"); fprintf(fid,"set ylabel \"Q\"\n"); fprintf(fid,"set nokey # disable legned\n"); // TODO : set grid type (e.g. polar) according to scheme // if (axes == AXES_POLAR) fprintf(fid,"set grid polar\n"); else fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' linewidth 1\n",LIQUID_DOC_COLOR_GRID); fprintf(fid,"set pointsize 1.0\n"); if (!plot_labels) { // do not print labels fprintf(fid,"plot '%s' using 1:2 with points pointtype 7 linecolor rgb '#004080'\n",input_filename); } else { // print labels fprintf(fid,"xoffset = %8.6f\n", plot_long_labels ? 0.0 : 0.045f); fprintf(fid,"yoffset = %8.6f\n", plot_long_labels ? 0.06f : 0.045f); unsigned int label_line = plot_long_labels ? 3 : 4; fprintf(fid,"plot '%s' using 1:2 with points pointtype 7 linecolor rgb '#004080',\\\n",input_filename); fprintf(fid," '%s' using ($1+xoffset):($2+yoffset):%u with labels font 'arial,10'\n", input_filename,label_line); } // close it up fclose(fid); return 0; }
int main(int argc, char *argv[]) { char IMEI[15]; modem_status_t status; modem_err_t err; modem_ret_t ret; (void)argv; (void)argc; // if (argc < 2) { // printf("Set device to operate.\n"); // return EXIT_FAILURE; // } printf("Started, device '%s' used\n", argv[1]); __modem_start: ret = modem_init("/dev/ttyUSB0"); if (ret != MODEM_RET_OK) { printf("Error initializing modem=%d\n", ret); return EXIT_FAILURE; } ret = __modem_configure(); if (ret != 0) { printf("Error configuring modem=%d\n", ret); return EXIT_FAILURE; } ret = __get_IMEI(IMEI); if (ret == 0) printf("IMEI> %s\n", IMEI); else { printf("No IMEI received: %d\n", ret); return EXIT_FAILURE; } #if 0 for (;;) { modem_get_status(&status, &err); printf("Status=%04X, error=%04X, auth=%d\n", status, err, __auth); if ((status & MODEM_STATUS_ONLINE) == 0) { /* Full restart */ modem_destroy(); goto __modem_start; } if ((status & MODEM_STATUS_REG) == 0) { /* No network registration */ modem_send_cmd(MODEM_CMD_CREG_GET, NULL, NULL, NULL, 1); continue; } ret = modem_conn_start(BP_SERVICE_PROF); if (ret != MODEM_RET_OK) { ret = modem_conn_stop(BP_SERVICE_PROF); continue; } sleep(10); __get_bin(status); } #endif for (;;) { sleep(1); modem_get_status(&status, &err); printf("Status=%04X, error=%04X, auth=%d\n", status, err, __auth); if ((status & MODEM_STATUS_ONLINE) == 0) { /* Full restart */ modem_destroy(); goto __modem_start; } if ((status & MODEM_STATUS_REG) == 0) { /* No network registration */ modem_send_cmd(MODEM_CMD_CREG_GET, NULL, NULL, NULL, 1); continue; } if ((status & MODEM_STATUS_CONN) == 0) { ret = modem_conn_start(TCS_SERVICE_PROF); if (ret != MODEM_RET_OK) { ret = modem_conn_stop(TCS_SERVICE_PROF); } continue; } __client_auth(status); } return EXIT_SUCCESS; }
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; }
ModemST::~ModemST() { modem_destroy(demodST); }
// Helper function to keep code base small void modem_test_demodstats(modulation_scheme _ms) { // generate mod/demod modem mod = modem_create(_ms); modem demod = modem_create(_ms); // run the test unsigned int i, s, M = 1 << modem_get_bps(mod); float complex x; float complex x_hat; // rotated symbol float demodstats; float phi = 0.01f; for (i=0; i<M; i++) { // reset modem objects modem_reset(mod); modem_reset(demod); // modulate symbol modem_modulate(mod, i, &x); // ignore rare condition where modulated symbol is (0,0) // (e.g. APSK-8) if (cabsf(x) < 1e-3f) continue; // add phase offsets x_hat = x * cexpf( phi*_Complex_I); // demod positive phase signal, and ensure demodulator // maps to appropriate symbol modem_demodulate(demod, x_hat, &s); if (s != i) AUTOTEST_WARN("modem_test_demodstats(), output symbol does not match"); demodstats = modem_get_demodulator_phase_error(demod); CONTEND_EXPRESSION(demodstats > 0.0f); } // repeat with negative phase error for (i=0; i<M; i++) { // reset modem objects modem_reset(mod); modem_reset(demod); // modulate symbol modem_modulate(mod, i, &x); // ignore rare condition where modulated symbol is (0,0) // (e.g. APSK-8) if (cabsf(x) < 1e-3f) continue; // add phase offsets x_hat = x * cexpf(-phi*_Complex_I); // demod positive phase signal, and ensure demodulator // maps to appropriate symbol modem_demodulate(demod, x_hat, &s); if (s != i) AUTOTEST_WARN("modem_test_demodstats(), output symbol does not match"); demodstats = modem_get_demodulator_phase_error(demod); CONTEND_EXPRESSION(demodstats < 0.0f); } // clean up allocated objects up modem_destroy(mod); modem_destroy(demod); }
int main(int argc, char*argv[]) { // options unsigned int num_symbols=500; // number of symbols to observe float SNRdB = 30.0f; // signal-to-noise ratio [dB] unsigned int hc_len=5; // channel filter length unsigned int k=2; // matched filter samples/symbol unsigned int m=3; // matched filter delay (symbols) float beta=0.3f; // matched filter excess bandwidth factor unsigned int p=3; // equalizer length (symbols, gr_len = 2*k*p+1) float mu = 0.09f; // LMS learning rate // modulation type/depth modulation_scheme ms = LIQUID_MODEM_QPSK; // plotting options unsigned int nfft = 512; // fft size float gnuplot_version = 4.2; char filename_base[256] = "figures.gen/eqlms_cccf_blind"; int dopt; while ((dopt = getopt(argc,argv,"hf:g:n:s:c:k:m:b:p:u:M:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'f': strncpy(filename_base,optarg,256); break; case 'g': gnuplot_version = atoi(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'c': hc_len = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'p': p = atoi(optarg); break; case 'u': mu = atof(optarg); break; case 'M': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme '%s'\n", argv[0], optarg); return 1; } break; default: exit(1); } } // validate input if (num_symbols == 0) { fprintf(stderr,"error: %s, number of symbols must be greater than zero\n", argv[0]); exit(1); } else if (hc_len == 0) { fprintf(stderr,"error: %s, channel must have at least 1 tap\n", argv[0]); exit(1); } else if (k < 2) { fprintf(stderr,"error: %s, samples/symbol must be at least 2\n", argv[0]); exit(1); } else if (m == 0) { fprintf(stderr,"error: %s, filter semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (beta < 0.0f || beta > 1.0f) { fprintf(stderr,"error: %s, filter excess bandwidth must be in [0,1]\n", argv[0]); exit(1); } else if (p == 0) { fprintf(stderr,"error: %s, equalizer semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (mu < 0.0f || mu > 1.0f) { fprintf(stderr,"error: %s, equalizer learning rate must be in [0,1]\n", argv[0]); exit(1); } // set 'random' seed on options srand( hc_len + p + nfft ); // derived values unsigned int gt_len = 2*k*m+1; // matched filter length unsigned int gr_len = 2*k*p+1; // equalizer filter length unsigned int num_samples = k*num_symbols; // bookkeeping variables float complex sym_tx[num_symbols]; // transmitted data sequence float complex x[num_samples]; // interpolated time series float complex y[num_samples]; // channel output float complex z[num_samples]; // equalized output // least mean-squares (LMS) equalizer float mse[num_symbols]; // equalizer mean-squared error float complex gr[gr_len]; // equalizer filter coefficients unsigned int i; // generate matched filter response float gtf[gt_len]; // matched filter response liquid_firdes_rnyquist(LIQUID_RNYQUIST_RRC, k, m, beta, 0.0f, gtf); // convert to complex coefficients float complex gt[gt_len]; for (i=0; i<gt_len; i++) gt[i] = gtf[i]; //+ 0.1f*(randnf() + _Complex_I*randnf()); // create interpolator interp_cccf interp = interp_cccf_create(k, gt, gt_len); // create the modem objects modem mod = modem_create(ms); modem demod = modem_create(ms); unsigned int bps = modem_get_bps(mod); unsigned int M = 1 << bps; // generate channel impulse response, filter #if 0 float complex hc[hc_len]; // channel filter coefficients hc[0] = 1.0f; for (i=1; i<hc_len; i++) hc[i] = 0.09f*(randnf() + randnf()*_Complex_I); #else // use fixed channel hc_len = 8; float complex hc[hc_len]; // channel filter coefficients hc[0] = 1.00000000+ 0.00000000*_Complex_I; hc[1] = 0.08077553+ -0.00247592*_Complex_I; hc[2] = 0.03625883+ -0.09219734*_Complex_I; hc[3] = 0.05764082+ 0.03277601*_Complex_I; hc[4] = -0.04773349+ -0.18766306*_Complex_I; hc[5] = -0.00101735+ -0.00270737*_Complex_I; hc[6] = -0.05796884+ -0.12665297*_Complex_I; hc[7] = 0.03805391+ -0.07609370*_Complex_I; #endif firfilt_cccf fchannel = firfilt_cccf_create(hc, hc_len); firfilt_cccf_print(fchannel); // generate random symbols for (i=0; i<num_symbols; i++) modem_modulate(mod, rand()%M, &sym_tx[i]); // interpolate for (i=0; i<num_symbols; i++) interp_cccf_execute(interp, sym_tx[i], &x[i*k]); // push through channel float nstd = powf(10.0f, -SNRdB/20.0f); for (i=0; i<num_samples; i++) { firfilt_cccf_push(fchannel, x[i]); firfilt_cccf_execute(fchannel, &y[i]); // add noise y[i] += nstd*(randnf() + randnf()*_Complex_I)*M_SQRT1_2; } // push through equalizers float grf[gr_len]; liquid_firdes_rnyquist(LIQUID_RNYQUIST_RRC, k, p, beta, 0.0f, grf); for (i=0; i<gr_len; i++) { gr[i] = grf[i] / (float)k; } // create LMS equalizer eqlms_cccf eq = eqlms_cccf_create(gr, gr_len); eqlms_cccf_set_bw(eq, mu); // filtered error vector magnitude (emperical MSE) //float zeta=0.05f; // smoothing factor (small zeta -> smooth MSE) float complex d_hat = 0.0f; unsigned int num_symbols_rx=0; for (i=0; i<num_samples; i++) { // push samples into equalizers eqlms_cccf_push(eq, y[i]); // compute outputs eqlms_cccf_execute(eq, &d_hat); // store outputs z[i] = d_hat; // check to see if buffer is full if ( i < gr_len) continue; // decimate by k if ( (i%k) != 0 ) continue; // estimate transmitted signal unsigned int sym_out; // output symbol float complex d_prime; // estimated input sample // LMS modem_demodulate(demod, d_hat, &sym_out); modem_get_demodulator_sample(demod, &d_prime); // update equalizers eqlms_cccf_step(eq, d_prime, d_hat); #if 0 // update filtered evm estimate float evm = crealf( (d_prime-d_hat)*conjf(d_prime-d_hat) ); if (num_symbols_rx == 0) { mse[num_symbols_rx] = evm; } else { mse[num_symbols_rx] = mse[num_symbols_rx-1]*(1-zeta) + evm*zeta; } #else // compute ISI for entire system eqlms_cccf_get_weights(eq, gr); mse[num_symbols_rx] = eqlms_cccf_isi(k, gt, gt_len, hc, hc_len, gr, gr_len); #endif // print filtered evm (emperical rms error) if ( ((num_symbols_rx+1)%100) == 0 ) printf("%4u : mse = %12.8f dB\n", num_symbols_rx+1, 20*log10f(mse[num_symbols_rx])); // increment output symbol counter num_symbols_rx++; } // get equalizer weights eqlms_cccf_get_weights(eq, gr); // destroy objects eqlms_cccf_destroy(eq); interp_cccf_destroy(interp); firfilt_cccf_destroy(fchannel); modem_destroy(mod); modem_destroy(demod); // // export output // FILE * fid = NULL; char filename[300]; // // const: constellation // strncpy(filename, filename_base, 256); strcat(filename, "_const.gnu"); fid = fopen(filename,"w"); if (!fid) { fprintf(stderr,"error: %s, could not open file '%s' for writing\n", argv[0], filename); return 1; } fprintf(fid,"# %s: auto-generated file\n\n", filename); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); fprintf(fid,"set size ratio 1\n"); fprintf(fid,"set xrange [-1.5:1.5];\n"); fprintf(fid,"set yrange [-1.5:1.5];\n"); fprintf(fid,"set xlabel 'In-phase'\n"); fprintf(fid,"set ylabel 'Quadrature phase'\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' linewidth 1\n",LIQUID_DOC_COLOR_GRID); fprintf(fid,"plot '-' using 1:2 with points pointtype 7 pointsize 0.5 linecolor rgb '%s' title 'first 50%%',\\\n", LIQUID_DOC_COLOR_GRAY); fprintf(fid," '-' using 1:2 with points pointtype 7 pointsize 0.7 linecolor rgb '%s' title 'last 50%%'\n", LIQUID_DOC_COLOR_RED); // first half of symbols for (i=2*p; i<num_symbols/2; i+=k) fprintf(fid," %12.4e %12.4e\n", crealf(y[i]), cimagf(y[i])); fprintf(fid,"e\n"); // second half of symbols for ( ; i<num_symbols; i+=k) fprintf(fid," %12.4e %12.4e\n", crealf(z[i]), cimagf(z[i])); fprintf(fid,"e\n"); fclose(fid); printf("results written to '%s'\n", filename); // // mse : mean-squared error // strncpy(filename, filename_base, 256); strcat(filename, "_mse.gnu"); fid = fopen(filename,"w"); if (!fid) { fprintf(stderr,"error: %s, could not open file '%s' for writing\n", argv[0], filename); return 1; } fprintf(fid,"# %s: auto-generated file\n\n", filename); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); fprintf(fid,"set size ratio 0.3\n"); fprintf(fid,"set xrange [0:%u];\n", num_symbols); fprintf(fid,"set yrange [1e-3:1e-1];\n"); fprintf(fid,"set format y '10^{%%L}'\n"); fprintf(fid,"set log y\n"); fprintf(fid,"set xlabel 'symbol index'\n"); fprintf(fid,"set ylabel 'mean-squared error'\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' linewidth 1\n",LIQUID_DOC_COLOR_GRID); fprintf(fid,"plot '-' using 1:2 with lines linewidth 4 linetype 1 linecolor rgb '%s' title 'LMS MSE'\n", LIQUID_DOC_COLOR_RED); // LMS for (i=0; i<num_symbols_rx; i++) fprintf(fid," %4u %16.8e\n", i, mse[i]); fprintf(fid,"e\n"); fclose(fid); printf("results written to '%s'\n", filename); // // psd : power spectral density // // scale transmit filter appropriately for (i=0; i<gt_len; i++) gt[i] /= (float)k; float complex Gt[nfft]; // transmit matched filter float complex Hc[nfft]; // channel response float complex Gr[nfft]; // equalizer response liquid_doc_compute_psdcf(gt, gt_len, Gt, nfft, LIQUID_DOC_PSDWINDOW_NONE, 0); liquid_doc_compute_psdcf(hc, hc_len, Hc, nfft, LIQUID_DOC_PSDWINDOW_NONE, 0); liquid_doc_compute_psdcf(gr, gr_len, Gr, nfft, LIQUID_DOC_PSDWINDOW_NONE, 0); fft_shift(Gt, nfft); fft_shift(Hc, nfft); fft_shift(Gr, nfft); float freq[nfft]; for (i=0; i<nfft; i++) freq[i] = (float)(i) / (float)nfft - 0.5f; strncpy(filename, filename_base, 256); strcat(filename, "_freq.gnu"); fid = fopen(filename,"w"); if (!fid) { fprintf(stderr,"error: %s, could not open file '%s' for writing\n", argv[0], filename); return 1; } fprintf(fid,"# %s: auto-generated file\n\n", filename); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); fprintf(fid,"set size ratio 0.6\n"); fprintf(fid,"set xrange [-0.5:0.5];\n"); fprintf(fid,"set yrange [-10:6]\n"); fprintf(fid,"set xlabel 'Normalized Frequency'\n"); fprintf(fid,"set ylabel 'Power Spectral Density [dB]'\n"); fprintf(fid,"set key top right nobox\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' lw 1\n",LIQUID_DOC_COLOR_GRID); fprintf(fid,"plot '-' using 1:2 with lines linetype 1 linewidth 1.5 linecolor rgb '%s' title 'transmit',\\\n", LIQUID_DOC_COLOR_GRAY); fprintf(fid," '-' using 1:2 with lines linetype 1 linewidth 1.5 linecolor rgb '%s' title 'channel',\\\n", LIQUID_DOC_COLOR_RED); fprintf(fid," '-' using 1:2 with lines linetype 1 linewidth 1.5 linecolor rgb '%s' title 'equalizer',\\\n", LIQUID_DOC_COLOR_GREEN); fprintf(fid," '-' using 1:2 with lines linetype 1 linewidth 4.0 linecolor rgb '%s' title 'composite',\\\n", LIQUID_DOC_COLOR_BLUE); fprintf(fid," '-' using 1:2 with points pointtype 7 pointsize 0.6 linecolor rgb '%s' notitle\n", LIQUID_DOC_COLOR_BLUE); // received signal for (i=0; i<nfft; i++) fprintf(fid,"%12.8f %12.4e\n", freq[i], 20*log10f(cabsf(Gt[i])) ); fprintf(fid,"e\n"); // channel for (i=0; i<nfft; i++) fprintf(fid,"%12.8f %12.4e\n", freq[i], 20*log10f(cabsf(Hc[i])) ); fprintf(fid,"e\n"); // equalizer for (i=0; i<nfft; i++) fprintf(fid,"%12.8f %12.4e\n", freq[i], 20*log10f(cabsf(Gr[i])) ); fprintf(fid,"e\n"); // composite for (i=0; i<nfft; i++) fprintf(fid,"%12.8f %12.4e\n", freq[i], 20*log10f( cabsf(Gt[i])*cabsf(Hc[i])*cabsf(Gr[i])) ); fprintf(fid,"e\n"); // composite fprintf(fid,"%12.8f %12.4e\n", -0.5f/(float)k, 20*log10f(0.5f)); fprintf(fid,"%12.8f %12.4e\n", 0.5f/(float)k, 20*log10f(0.5f)); fprintf(fid,"e\n"); fclose(fid); printf("results written to '%s'\n", filename); // // time... // strncpy(filename, filename_base, 256); strcat(filename, "_time.gnu"); fid = fopen(filename,"w"); if (!fid) { fprintf(stderr,"error: %s, could not open file '%s' for writing\n", argv[0], filename); return 1; } fprintf(fid,"# %s: auto-generated file\n\n", filename); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); fprintf(fid,"set xrange [0:%u];\n",num_symbols); fprintf(fid,"set yrange [-1.5:1.5]\n"); fprintf(fid,"set size ratio 0.3\n"); fprintf(fid,"set xlabel 'Symbol Index'\n"); fprintf(fid,"set key top right nobox\n"); //fprintf(fid,"set ytics -5,1,5\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set pointsize 0.6\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' lw 1\n", LIQUID_DOC_COLOR_GRID); fprintf(fid,"set multiplot layout 2,1 scale 1.0,1.0\n"); // real fprintf(fid,"# real\n"); fprintf(fid,"set ylabel 'Real'\n"); fprintf(fid,"plot '-' using 1:2 with lines linetype 1 linewidth 1 linecolor rgb '#999999' notitle,\\\n"); fprintf(fid," '-' using 1:2 with points pointtype 7 linecolor rgb '%s' notitle'\n", LIQUID_DOC_COLOR_BLUE); // for (i=0; i<num_samples; i++) fprintf(fid,"%12.8f %12.4e\n", (float)i/(float)k, crealf(z[i])); fprintf(fid,"e\n"); // for (i=0; i<num_samples; i+=k) fprintf(fid,"%12.8f %12.4e\n", (float)i/(float)k, crealf(z[i])); fprintf(fid,"e\n"); // imag fprintf(fid,"# imag\n"); fprintf(fid,"set ylabel 'Imag'\n"); fprintf(fid,"plot '-' using 1:2 with lines linetype 1 linewidth 1 linecolor rgb '#999999' notitle,\\\n"); fprintf(fid," '-' using 1:2 with points pointtype 7 linecolor rgb '%s' notitle'\n", LIQUID_DOC_COLOR_GREEN); // for (i=0; i<num_samples; i++) fprintf(fid,"%12.8f %12.4e\n", (float)i/(float)k, cimagf(z[i])); fprintf(fid,"e\n"); // for (i=0; i<num_samples; i+=k) fprintf(fid,"%12.8f %12.4e\n", (float)i/(float)k, cimagf(z[i])); fprintf(fid,"e\n"); fprintf(fid,"unset multiplot\n"); // close output file fclose(fid); printf("results written to '%s'\n", filename); return 0; }