void LiquidOfdmModComponent::initialize()
{
    // print capabilities of liquid
    if (debug_x) {
        liquid_print_modulation_schemes();
        liquid_print_fec_schemes();
        liquid_print_crc_schemes();
    }

    // initialize subcarrier allocation
    unsigned char p[noSubcarriers_x];
    ofdmframe_init_default_sctype(noSubcarriers_x, p);

    // create frame generator properties object and initialize to default
    ofdmflexframegenprops_s fgProps;
    ofdmflexframegenprops_init_default(&fgProps);
    modulation_scheme ms = liquid_getopt_str2mod(modulationScheme_x.c_str());
    fec_scheme fec0 = liquid_getopt_str2fec(fecZero_x.c_str());
    fec_scheme fec1 = liquid_getopt_str2fec(fecOne_x.c_str());
    crc_scheme check = liquid_getopt_str2crc(crcScheme_x.c_str());

    fgProps.mod_scheme = ms;
    fgProps.fec0 = fec0;
    fgProps.fec1 = fec1;
    fgProps.check = check;

    gain_factor_  = powf(10.0f, gain_x/20.0f);

    // create frame generator object
    try {
        frameGenerator_ = ofdmflexframegen_create(noSubcarriers_x, cyclicPrefixLength_x, taperLength_x, p, &fgProps);
        ofdmflexframegen_print(frameGenerator_);
    }
    catch(...)
    {
        LOG(LERROR) << "Unexpected exception caught during frame generator generation";
    }
}
void LiquidOfdmModComponent::parameterHasChanged(std::string name)
{
    ofdmflexframegenprops_s fgProps;
    ofdmflexframegen_getprops(frameGenerator_, &fgProps);
    if (name == "modulation") {
        modulation_scheme ms = liquid_getopt_str2mod(modulationScheme_x.c_str());
        fgProps.mod_scheme = ms;
    }
    if (name == "fec0") {
        fec_scheme fec0 = liquid_getopt_str2fec(fecZero_x.c_str());
        fgProps.fec0 = fec0;
    }
    if (name == "fec1") {
        fec_scheme fec1 = liquid_getopt_str2fec(fecOne_x.c_str());
        fgProps.fec1 = fec1;
    }
    if (name == "crc") {
        crc_scheme check = liquid_getopt_str2crc(crcScheme_x.c_str());
        fgProps.check = check;
    }
    ofdmflexframegen_setprops(frameGenerator_, &fgProps);

    if (name == "gain") {
        gain_factor_  = powf(10.0f, gain_x/20.0f);
    }

    if (name == "subcarriers" ||
        name == "prefixlength" ||
        name == "taperlength")
    {
      //Need to destroy and recreate the frame generator
      if (frameGenerator_)
        ofdmflexframegen_destroy(frameGenerator_);
      initialize();
    }
}
Example #3
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;
}
Example #4
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;
}
Example #5
0
int main(int argc, char*argv[])
{
    srand( time(NULL) );

    // options
    int verbose = 1;
    int which_ber_per  = ESTIMATE_SNR_BER;
    int which_snr_ebn0 = ESTIMATE_SNR;
    float error_rate = 1e-3f;
    unsigned int frame_len = 1024;
    unsigned long int max_trials = 0;

    modulation_scheme ms = LIQUID_MODEM_QPSK;
    fec_scheme fec0 = LIQUID_FEC_NONE;  // inner code
    fec_scheme fec1 = LIQUID_FEC_NONE;  // outer code
    int soft_decoding = 0;

    int dopt;
    while ((dopt = getopt(argc,argv,"uhvqBPseSHE:n:x:c:m:")) != EOF) {
        switch (dopt) {
        case 'u':
        case 'h': usage();                          return 0;
        case 'v': verbose = 1;                      break;
        case 'q': verbose = 0;                      break;
        case 'B': which_ber_per = ESTIMATE_SNR_BER; break;
        case 'P': which_ber_per = ESTIMATE_SNR_PER; break;
        case 's': which_snr_ebn0 = ESTIMATE_SNR;    break;
        case 'e': which_snr_ebn0 = ESTIMATE_EBN0;   break;
        case 'S': soft_decoding = 1;                break;
        case 'H': soft_decoding = 0;                break;
        case 'E': error_rate = atof(optarg);        break;
        case 'n': frame_len = atoi(optarg);         break;
        case 'x': max_trials = atoi(optarg);        break;
        case 'c':
            // 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 'm':
            ms = liquid_getopt_str2mod(optarg);
            if (ms == LIQUID_MODEM_UNKNOWN) {
                fprintf(stderr,"error: modem_example, unknown/unsupported modulation scheme \"%s\"\n", optarg);
                return 1;
            }
            break;
        default:
            exit(1);
        }
    }

    // validate input
    if (error_rate <= 0.0f) {
        fprintf(stderr,"error: error rate must be greater than 0\n");
        exit(1);
    } else if (frame_len == 0 || frame_len > 10000) {
        fprintf(stderr,"error: frame length must be in [1, 10,000]\n");
        exit(1);
    } else if (which_ber_per == ESTIMATE_SNR_BER && error_rate >= 0.5) {
        fprintf(stderr,"error: error rate must be less than 0.5 when simulating BER\n");
        exit(1);
    } else if (error_rate >= 1.0f) {
        fprintf(stderr,"error: error rate must be less than 1\n");
        exit(1);
    }

    if (max_trials == 0) {
        // unspecified: use defaults
        if (which_ber_per == ESTIMATE_SNR_BER)
            max_trials = 800000;
        else
            max_trials = 200;
    }

    simulate_per_opts opts;
    opts.ms     = ms;
    opts.fec0   = fec0;
    opts.fec1   = fec1;
    opts.dec_msg_len = frame_len;
    opts.soft_decoding = soft_decoding;
    
    unsigned int bps = modulation_types[ms].bps;

    // minimum number of errors to simulate
    opts.min_packet_errors  = which_ber_per==ESTIMATE_SNR_PER ? 10      : 0;
    opts.min_bit_errors     = which_ber_per==ESTIMATE_SNR_BER ? 50      : 0;

    // minimum number of trials to simulate
    opts.min_packet_trials  = which_ber_per==ESTIMATE_SNR_PER ? 500     : 0;
    opts.min_bit_trials     = which_ber_per==ESTIMATE_SNR_BER ? 5000    : 0;

    // maximum number of trials to simulate (before bailing and
    // deeming simulation unsuccessful)
    opts.max_packet_trials  = which_ber_per==ESTIMATE_SNR_PER ? max_trials : -1; 
    opts.max_bit_trials     = which_ber_per==ESTIMATE_SNR_BER ? max_trials : -1; 

    // estimate SNR for a specific PER
    printf("%u-%s // %s // %s (%s: %e)\n", 1<<bps,
                                           modulation_types[opts.ms].name,
                                           fec_scheme_str[opts.fec0][0],
                                           fec_scheme_str[opts.fec1][0],
                                           which_ber_per == ESTIMATE_SNR_BER ? "BER" : "PER",
                                           error_rate);

    // run estimation
    float x_hat = estimate_snr(opts, which_ber_per, which_snr_ebn0, error_rate);

    // compute rate [b/s/Hz]
    float rate = bps * fec_get_rate(opts.fec0) * fec_get_rate(opts.fec1);

    // set estimated values
    float SNRdB_hat;
    float EbN0dB_hat;
    if (which_snr_ebn0==ESTIMATE_SNR) {
        SNRdB_hat = x_hat;
        EbN0dB_hat = SNRdB_hat - 10*log10f(rate);
    } else {
        SNRdB_hat = x_hat + 10*log10f(rate);
        EbN0dB_hat = x_hat;
    }
    if (verbose) {
        printf("++ SNR (est) : %8.4fdB (Eb/N0 = %8.4fdB) for %s: %12.4e\n",
                SNRdB_hat,
                EbN0dB_hat,
                which_ber_per == ESTIMATE_SNR_BER ? "BER" : "PER",
                error_rate);
    }


    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;  // modulation scheme
    fec_scheme        fec0        = LIQUID_FEC_NONE;    // inner code
    fec_scheme        fec1        = LIQUID_FEC_HAMMING128; // outer code
    crc_scheme        check       = LIQUID_CRC_32;      // validity check
    float             noise_floor = -80.0f;             // noise floor [dB]
    float             SNRdB       = 20.0f;              // signal-to-noise ratio [dB]
    float             dphi        = 0.02f;              // carrier frequency offset
    int               debug       =  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       = 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); 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;
        default:
            exit(-1);
        }
    }

    unsigned int i;

    // TODO : validate options

    // derived values
    unsigned int  buf_len = 256;
    float complex buf[buf_len]; // time-domain buffer

    // allocate memory for header, payload
    unsigned char header[8];
    unsigned char payload[payload_len];

    // 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, NULL, &fgprops);

    // create frame synchronizer
    ofdmflexframesync fs = ofdmflexframesync_create(M, cp_len, taper_len, NULL, callback, (void*)payload);
    if (debug)
        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);

    // create channel and add impairments
    channel_cccf channel = channel_cccf_create();
    channel_cccf_add_awgn(channel, noise_floor, SNRdB);
    channel_cccf_add_carrier_offset(channel, dphi, 0.0f);

    // generate frame, push through channel
    int last_symbol=0;
    while (!last_symbol) {
        // generate symbol
        last_symbol = ofdmflexframegen_write(fg, buf, buf_len);

        // apply channel to buffer (in place)
        channel_cccf_execute_block(channel, buf, buf_len, buf);

        // push samples through synchronizer
        ofdmflexframesync_execute(fs, buf, buf_len);
    }

    // export debugging file
    if (debug)
        ofdmflexframesync_debug_print(fs, "ofdmflexframesync_debug.m");

    // destroy objects
    ofdmflexframegen_destroy(fg);
    ofdmflexframesync_destroy(fs);
    channel_cccf_destroy(channel);

    printf("done.\n");
    return 0;
}
int main(int argc, char*argv[]) {
    srand( time(NULL) );

    // options
    simulate_per_opts opts;
    opts.ms = LIQUID_MODEM_BPSK;
    opts.bps = 1;
    opts.fec0 = LIQUID_FEC_NONE;
    opts.fec1 = LIQUID_FEC_NONE;
    opts.dec_msg_len = 1024;
    opts.soft_decoding = 1;

    opts.min_packet_errors  = 5;
    opts.min_bit_errors     = 10;
    opts.min_packet_trials  = 50;
    opts.min_bit_trials     = 10000;

    opts.max_packet_trials  = 1000;
    opts.max_bit_trials     = 1000000;

    // read command-line options
    int dopt;
    while((dopt = getopt(argc,argv,"uhn:p:m:c:k:SH")) != EOF){
        switch (dopt) {
        case 'h':
        case 'u': usage();                          return 0;
        case 'n': opts.dec_msg_len = atoi(optarg);  break;
        case 'p': opts.bps = atoi(optarg);          break;
        case 'm':
            opts.ms = liquid_getopt_str2mod(optarg);
            if (opts.ms == LIQUID_MODEM_UNKNOWN) {
                fprintf(stderr,"error: modem_example, unknown/unsupported modulation scheme \"%s\"\n", optarg);
                exit(1);
            }
            break;
        case 'c':
            // inner FEC scheme
            opts.fec0 = liquid_getopt_str2fec(optarg);
            if (opts.fec0 == LIQUID_FEC_UNKNOWN) {
                fprintf(stderr,"error: unknown/unsupported modulation scheme \"%s\"\n\n",optarg);
                exit(-1);
            }
            break;
        case 'k':
            // outer FEC scheme
            opts.fec1 = liquid_getopt_str2fec(optarg);
            if (opts.fec1 == LIQUID_FEC_UNKNOWN) {
                fprintf(stderr,"error: unknown/unsupported modulation scheme \"%s\"\n\n",optarg);
                exit(-1);
            }
            break;
        case 'S': opts.soft_decoding = 1;   break;
        case 'H': opts.soft_decoding = 0;   break;
        default:
            exit(1);
        }
    }


    // SNR range, steps
    float SNRdB_min = 0.0f;
    float SNRdB_max = 20.0f;
    unsigned int num_steps = 21;

    // derived values
    float SNRdB_step = (SNRdB_max - SNRdB_min)/(float)(num_steps-1);

    //
    float SNRdB;

    // generate results structure
    simulate_per_results results;

    // array for BER
    float BER[num_steps];

    unsigned int i;
    for (i=0; i<num_steps; i++) {
        SNRdB = SNRdB_min + i*SNRdB_step;

        simulate_per(opts, SNRdB, &results);

        //printf("  %12.8f : %12.4e\n", SNRdB, PER);
        printf(" %c SNR: %6.2f, bits: %8lu / %8lu (%12.4e), packets: %6lu / %6lu (%6.2f%%)\n",
                results.success ? '*' : ' ',
                SNRdB,
                results.num_bit_errors,     results.num_bit_trials,     results.BER,
                results.num_packet_errors,  results.num_packet_trials,  results.PER*100.0f);

        // save BER in array
        BER[i] = results.BER;
    }

    // 
    // export data
    //
    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", OUTPUT_FILENAME);
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n");
    for (i=0; i<num_steps; i++) {
        fprintf(fid,"SNRdB(%3u) = %12.8f;\n", i+1, SNRdB_min + i*SNRdB_step);
        fprintf(fid,"BER(%3u)   = %12.4e;\n", i+1, BER[i]);
    }
    fprintf(fid,"\n\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"semilogy(SNRdB, 0.5*erfc(sqrt(10.^[SNRdB/10]))+1e-12,'-x',\n");
    fprintf(fid,"         SNRdB, BER + 1e-12,  '-x');\n");
    fprintf(fid,"axis([%f %f 1e-6 1]);\n", SNRdB_min, SNRdB_max);
    fprintf(fid,"xlabel('SNR [dB]');\n");
    fprintf(fid,"ylabel('Bit Error Rate');\n");
    fprintf(fid,"legend('uncoded BPSK','modem: %s (M=%u) // fec: %s',1);\n",
            modulation_types[opts.ms].name, 1<<opts.bps, fec_scheme_str[opts.fec0][0]);
    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[])
{
    // 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;
}
Example #9
0
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;
}
Example #10
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;
}
Example #11
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;
}
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;
}
Example #13
0
int main(int argc, char *argv[]) {
    srand( time(NULL) );

    // define parameters
    float SNRdB_start       = -5.0f;
    float SNRdB_step        = 1.0f;
    float SNRdB_max         = 10.0f;
    unsigned int num_frames = 1000;
    //float noise_floor       = -30.0f;
    const char * filename   = "ofdmflexframe_fer_results.dat";
    modulation_scheme ms    = LIQUID_MODEM_QPSK;
    unsigned int M          = 64;
    unsigned int cp_len     = 16;
    unsigned int payload_len= 256;
    crc_scheme check        = LIQUID_CRC_32;
    fec_scheme fec0         = LIQUID_FEC_HAMMING128;
    fec_scheme fec1         = LIQUID_FEC_NONE;
    int verbose             = 1;

    // get command-line options
    int dopt;
    while((dopt = getopt(argc,argv,"uho:s:d:x:n:f:M:C:m:c:k:")) != EOF){
        switch (dopt) {
        case 'h':
        case 'u': usage(); return 0;
        case 'o': filename = optarg;            break;
        case 's': SNRdB_start = atof(optarg);   break;
        case 'd': SNRdB_step = atof(optarg);    break;
        case 'x': SNRdB_max = atof(optarg);     break;
        case 'n': num_frames = atol(optarg);    break;
        case 'f': payload_len = atol(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) {
                printf("error: unknown/unsupported mod. scheme: %s\n", optarg);
                exit(1);
            }
            break;
        case 'c':
            fec0 = liquid_getopt_str2fec(optarg);
            if (fec0 == LIQUID_FEC_UNKNOWN) {
                printf("error: unknown/unsupported fec scheme \"%s\"\n", optarg);
                exit(1);
            }
            break;
        case 'k':
            fec1 = liquid_getopt_str2fec(optarg);
            if (fec1 == LIQUID_FEC_UNKNOWN) {
                printf("error: unknown/unsupported fec scheme \"%s\"\n", optarg);
                exit(1);
            }
            break;
        default:
            fprintf(stderr,"error: %s, unknown option\n", argv[0]);
            exit(1);
        }
    }

    // validate options
    if (SNRdB_step <= 0.0f) {
        printf("error: SNRdB_step must be greater than zero\n");
        exit(-1);
    } else if (SNRdB_max < SNRdB_start) {
        printf("error: SNRdB_max must be greater than SNRdB_start\n");
        exit(-1);
    }

    // set up framing simulation options
    ofdmflexframe_fer_opts opts;
    opts.M          = M;
    opts.cp_len     = cp_len;
    opts.p          = NULL;
    opts.ms         = ms;
    opts.check      = check;
    opts.fec0       = fec0;
    opts.fec1       = fec1;
    opts.payload_len= payload_len;
    opts.num_frames = num_frames;
    opts.verbose    = verbose;

    // create results objects
    fer_results results;

    // bookkeeping variables
    unsigned int i;
    float SNRdB = SNRdB_start;

    // open output file
    FILE * fid = fopen(filename,"w");
    if (!fid) {
        fprintf(stderr,"error: could not open '%s' for writing\n", filename);
        exit(1);
    }
    fprintf(fid,"# %s : auto-generated file\n", filename);
    fprintf(fid,"# invoked as: ");
    for (i=0; i<argc; i++) fprintf(fid,"%s ", argv[i]);
    fprintf(fid,"\n");
    fprintf(fid,"#\n");
    fprintf(fid,"#  M (subcarriers)     :   %u\n", opts.M);
    fprintf(fid,"#  cyclic prefix       :   %u\n", opts.cp_len);
    fprintf(fid,"#  allocation          :   \n"); // ofdmframe_print_sctype(opts.p, opts.M);
    fprintf(fid,"#  modulation scheme   :   %s\n", modulation_types[opts.ms].fullname);
    fprintf(fid,"#  modulation depth    :   %u bits/symbol\n", modulation_types[opts.ms].bps);
    fprintf(fid,"#  check               :   %s\n", crc_scheme_str[opts.check][1]);
    fprintf(fid,"#  fec (inner)         :   %s\n", fec_scheme_str[opts.fec0][1]);
    fprintf(fid,"#  fec (outer)         :   %s\n", fec_scheme_str[opts.fec1][1]);
    fprintf(fid,"#  payload length      :   %u bytes\n", opts.payload_len);
    fprintf(fid,"#  frame trials        :   %u\n", opts.num_frames);
    fprintf(fid,"#\n");
    fprintf(fid,"# %8s %12s %12s %12s %12s %12s %12s %12s\n",
            "SNR [dB]",
            "FER (frame)",
            "HER (header)",
            "PER (packet)",
            "frames",
            "headers",
            "packets",
            "num trials");
    fclose(fid);

    // start running batch trials
    while (SNRdB <= SNRdB_max) {

        // run trials
        ofdmflexframe_fer(opts, SNRdB, &results);

        // append results to file
        fid = fopen(filename,"a");
        fprintf(fid,"  %8.2f %12.10f %12.10f %12.10f %12u %12u %12u %12u\n",
                SNRdB,
                results.FER,
                results.HER,
                results.PER,
                results.num_missed_frames,
                results.num_header_errors,
                results.num_packet_errors,
                results.num_frames);
        fclose(fid);

        SNRdB += SNRdB_step;
    }

    printf("results written to '%s'\n", filename);

    return 0;
}
Example #14
0
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;
}
Example #15
0
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;
}