void ampmodem_modulate(ampmodem _q, float _x, float complex *_y) { float complex x_hat = 0.0f; float complex y_hat; if (_q->type == LIQUID_AMPMODEM_DSB) { x_hat = _x; } else { // push through Hilbert transform // LIQUID_AMPMODEM_USB: // LIQUID_AMPMODEM_LSB: conjugate Hilbert transform output firhilbf_r2c_execute(_q->hilbert, _x, &x_hat); if (_q->type == LIQUID_AMPMODEM_LSB) x_hat = conjf(x_hat); } if (_q->suppressed_carrier) y_hat = x_hat; else y_hat = 0.5f*(x_hat + 1.0f); // mix up nco_crcf_mix_up(_q->oscillator, y_hat, _y); nco_crcf_step(_q->oscillator); }
int main() { // spectral periodogram options unsigned int nfft = 1200; // spectral periodogram FFT size unsigned int num_samples = 64000; // number of samples float fc = 0.20f; // carrier (relative to sampling rate) // create objects iirfilt_crcf filter_tx = iirfilt_crcf_create_lowpass(15, 0.05); nco_crcf mixer_tx = nco_crcf_create(LIQUID_VCO); nco_crcf mixer_rx = nco_crcf_create(LIQUID_VCO); iirfilt_crcf filter_rx = iirfilt_crcf_create_lowpass(7, 0.2); // set carrier frequencies nco_crcf_set_frequency(mixer_tx, fc * 2*M_PI); nco_crcf_set_frequency(mixer_rx, fc * 2*M_PI); // create objects for measuring power spectral density spgramcf spgram_tx = spgramcf_create_default(nfft); spgramf spgram_dac = spgramf_create_default(nfft); spgramcf spgram_rx = spgramcf_create_default(nfft); // run through loop one step at a time unsigned int i; for (i=0; i<num_samples; i++) { // STEP 1: generate input signal (filtered noise with offset tone) float complex v1 = (randnf() + randnf()*_Complex_I) + 3.0f*cexpf(-_Complex_I*0.2f*i); iirfilt_crcf_execute(filter_tx, v1, &v1); // save spectrum spgramcf_push(spgram_tx, v1); // STEP 2: mix signal up and save real part (DAC output) nco_crcf_mix_up(mixer_tx, v1, &v1); float v2 = crealf(v1); nco_crcf_step(mixer_tx); // save spectrum spgramf_push(spgram_dac, v2); // STEP 3: mix signal down and filter off image float complex v3; nco_crcf_mix_down(mixer_rx, v2, &v3); iirfilt_crcf_execute(filter_rx, v3, &v3); nco_crcf_step(mixer_rx); // save spectrum spgramcf_push(spgram_rx, v3); } // compute power spectral density output float psd_tx [nfft]; float psd_dac [nfft]; float psd_rx [nfft]; spgramcf_get_psd(spgram_tx, psd_tx); spgramf_get_psd( spgram_dac, psd_dac); spgramcf_get_psd(spgram_rx, psd_rx); // destroy objects spgramcf_destroy(spgram_tx); spgramf_destroy(spgram_dac); spgramcf_destroy(spgram_rx); iirfilt_crcf_destroy(filter_tx); nco_crcf_destroy(mixer_tx); nco_crcf_destroy(mixer_rx); iirfilt_crcf_destroy(filter_rx); // // export output file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"psd_tx = zeros(1,nfft);\n"); fprintf(fid,"psd_dac= zeros(1,nfft);\n"); fprintf(fid,"psd_rx = zeros(1,nfft);\n"); for (i=0; i<nfft; i++) { fprintf(fid,"psd_tx (%6u) = %12.4e;\n", i+1, psd_tx [i]); fprintf(fid,"psd_dac(%6u) = %12.4e;\n", i+1, psd_dac[i]); fprintf(fid,"psd_rx (%6u) = %12.4e;\n", i+1, psd_rx [i]); } fprintf(fid,"figure;\n"); fprintf(fid,"hold on;\n"); fprintf(fid," plot(f, psd_tx, '-', 'LineWidth',1.5,'Color',[0.7 0.7 0.7]);\n"); fprintf(fid," plot(f, psd_dac, '-', 'LineWidth',1.5,'Color',[0.0 0.5 0.3]);\n"); fprintf(fid," plot(f, psd_rx, '-', 'LineWidth',1.5,'Color',[0.0 0.3 0.5]);\n"); fprintf(fid,"hold off;\n"); fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid,"ylabel('Power Spectral Density [dB]');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([-0.5 0.5 -100 60]);\n"); fprintf(fid,"legend('transmit (complex)','DAC output (real)','receive (complex)','location','northeast');\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { 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[]) { srand(time(NULL)); // options unsigned int M = 64; // number of subcarriers unsigned int cp_len = 16; // cyclic prefix length unsigned int taper_len = 4; // taper length unsigned int payload_len = 120; // length of payload (bytes) modulation_scheme ms = LIQUID_MODEM_QPSK; fec_scheme fec0 = LIQUID_FEC_NONE; fec_scheme fec1 = LIQUID_FEC_HAMMING128; crc_scheme check = LIQUID_CRC_32; float noise_floor = -30.0f; // noise floor [dB] float SNRdB = 20.0f; // signal-to-noise ratio [dB] float dphi = 0.02f; // carrier frequency offset int debug_enabled = 0; // enable debugging? // get options int dopt; while((dopt = getopt(argc,argv,"uhds:F:M:C:n:m:v:c:k:")) != EOF){ switch (dopt) { case 'u': case 'h': usage(); return 0; case 'd': debug_enabled = 1; break; case 's': SNRdB = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 'M': M = atoi(optarg); break; case 'C': cp_len = atoi(optarg); break; case 'n': payload_len = atol(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 'v': // data integrity check check = liquid_getopt_str2crc(optarg); if (check == LIQUID_CRC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported CRC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'c': // inner FEC scheme fec0 = liquid_getopt_str2fec(optarg); if (fec0 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported inner FEC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'k': // outer FEC scheme fec1 = liquid_getopt_str2fec(optarg); if (fec1 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported outer FEC scheme \"%s\"\n\n",optarg); exit(1); } break; default: exit(-1); } } unsigned int i; // TODO : validate options // derived values unsigned int frame_len = M + cp_len; float complex buffer[frame_len]; // time-domain buffer float nstd = powf(10.0f, noise_floor/20.0f); float gamma = powf(10.0f, (SNRdB + noise_floor)/20.0f); // allocate memory for header, payload unsigned char header[8]; unsigned char payload[payload_len]; // initialize subcarrier allocation unsigned char p[M]; ofdmframe_init_default_sctype(M, p); // create frame generator ofdmflexframegenprops_s fgprops; ofdmflexframegenprops_init_default(&fgprops); fgprops.check = check; fgprops.fec0 = fec0; fgprops.fec1 = fec1; fgprops.mod_scheme = ms; ofdmflexframegen fg = ofdmflexframegen_create(M, cp_len, taper_len, p, &fgprops); // create frame synchronizer ofdmflexframesync fs = ofdmflexframesync_create(M, cp_len, taper_len, p, callback, (void*)payload); if (debug_enabled) ofdmflexframesync_debug_enable(fs); // initialize header/payload and assemble frame for (i=0; i<8; i++) header[i] = i & 0xff; for (i=0; i<payload_len; i++) payload[i] = rand() & 0xff; ofdmflexframegen_assemble(fg, header, payload, payload_len); ofdmflexframegen_print(fg); ofdmflexframesync_print(fs); // initialize frame synchronizer with noise for (i=0; i<1000; i++) { float complex noise = nstd*( randnf() + _Complex_I*randnf())*M_SQRT1_2; ofdmflexframesync_execute(fs, &noise, 1); } // generate frame, push through channel int last_symbol=0; nco_crcf nco = nco_crcf_create(LIQUID_VCO); nco_crcf_set_frequency(nco, dphi); while (!last_symbol) { // generate symbol last_symbol = ofdmflexframegen_writesymbol(fg, buffer); // apply channel for (i=0; i<frame_len; i++) { float complex noise = nstd*( randnf() + _Complex_I*randnf())*M_SQRT1_2; buffer[i] *= gamma; buffer[i] += noise; nco_crcf_mix_up(nco, buffer[i], &buffer[i]); nco_crcf_step(nco); } // receive symbol ofdmflexframesync_execute(fs, buffer, frame_len); } nco_crcf_destroy(nco); // export debugging file if (debug_enabled) ofdmflexframesync_debug_print(fs, "ofdmflexframesync_debug.m"); // destroy objects ofdmflexframegen_destroy(fg); ofdmflexframesync_destroy(fs); printf("done.\n"); return 0; }