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";
    }
}
示例#2
0
// create OFDM framing synchronizer object
//  _M          :   number of subcarriers, >10 typical
//  _cp_len     :   cyclic prefix length
//  _taper_len  :   taper length (OFDM symbol overlap)
//  _p          :   subcarrier allocation (null, pilot, data), [size: _M x 1]
//  _callback   :   user-defined callback function
//  _userdata   :   user-defined data pointer
ofdmframesync ofdmframesync_create(unsigned int           _M,
                                   unsigned int           _cp_len,
                                   unsigned int           _taper_len,
                                   unsigned char *        _p,
                                   ofdmframesync_callback _callback,
                                   void *                 _userdata)
{
    ofdmframesync q = (ofdmframesync) malloc(sizeof(struct ofdmframesync_s));

    // validate input
    if (_M < 8) {
        fprintf(stderr,"warning: ofdmframesync_create(), less than 8 subcarriers\n");
    } else if (_M % 2) {
        fprintf(stderr,"error: ofdmframesync_create(), number of subcarriers must be even\n");
        exit(1);
    } else if (_cp_len > _M) {
        fprintf(stderr,"error: ofdmframesync_create(), cyclic prefix length cannot exceed number of subcarriers\n");
        exit(1);
    }
    q->M = _M;
    q->cp_len = _cp_len;

    // derived values
    q->M2 = _M/2;

    // subcarrier allocation
    q->p = (unsigned char*) malloc((q->M)*sizeof(unsigned char));
    if (_p == NULL) {
        ofdmframe_init_default_sctype(q->M, q->p);
    } else {
        memmove(q->p, _p, q->M*sizeof(unsigned char));
    }

    // validate and count subcarrier allocation
    ofdmframe_validate_sctype(q->p, q->M, &q->M_null, &q->M_pilot, &q->M_data);
    if ( (q->M_pilot + q->M_data) == 0) {
        fprintf(stderr,"error: ofdmframesync_create(), must have at least one enabled subcarrier\n");
        exit(1);
    } else if (q->M_data == 0) {
        fprintf(stderr,"error: ofdmframesync_create(), must have at least one data subcarriers\n");
        exit(1);
    } else if (q->M_pilot < 2) {
        fprintf(stderr,"error: ofdmframesync_create(), must have at least two pilot subcarriers\n");
        exit(1);
    }

    // create transform object
    q->X = (float complex*) malloc((q->M)*sizeof(float complex));
    q->x = (float complex*) malloc((q->M)*sizeof(float complex));
    q->fft = FFT_CREATE_PLAN(q->M, q->x, q->X, FFT_DIR_FORWARD, FFT_METHOD);
 
    // create input buffer the length of the transform
    q->input_buffer = windowcf_create(q->M + q->cp_len);

    // allocate memory for PLCP arrays
    q->S0 = (float complex*) malloc((q->M)*sizeof(float complex));
    q->s0 = (float complex*) malloc((q->M)*sizeof(float complex));
    q->S1 = (float complex*) malloc((q->M)*sizeof(float complex));
    q->s1 = (float complex*) malloc((q->M)*sizeof(float complex));
    ofdmframe_init_S0(q->p, q->M, q->S0, q->s0, &q->M_S0);
    ofdmframe_init_S1(q->p, q->M, q->S1, q->s1, &q->M_S1);

    // compute scaling factor
    q->g_data = sqrtf(q->M) / sqrtf(q->M_pilot + q->M_data);
    q->g_S0   = sqrtf(q->M) / sqrtf(q->M_S0);
    q->g_S1   = sqrtf(q->M) / sqrtf(q->M_S1);

    // gain
    q->g0 = 1.0f;
    q->G0 = (float complex*) malloc((q->M)*sizeof(float complex));
    q->G1 = (float complex*) malloc((q->M)*sizeof(float complex));
    q->G  = (float complex*) malloc((q->M)*sizeof(float complex));
    q->B  = (float complex*) malloc((q->M)*sizeof(float complex));
    q->R  = (float complex*) malloc((q->M)*sizeof(float complex));

#if 1
    memset(q->G0, 0x00, q->M*sizeof(float complex));
    memset(q->G1, 0x00, q->M*sizeof(float complex));
    memset(q->G , 0x00, q->M*sizeof(float complex));
    memset(q->B,  0x00, q->M*sizeof(float complex));
#endif

    // timing backoff
    q->backoff = q->cp_len < 2 ? q->cp_len : 2;
    float phi = (float)(q->backoff)*2.0f*M_PI/(float)(q->M);
    unsigned int i;
    for (i=0; i<q->M; i++)
        q->B[i] = liquid_cexpjf(i*phi);

    // set callback data
    q->callback = _callback;
    q->userdata = _userdata;

    // 
    // synchronizer objects
    //

    // numerically-controlled oscillator
    q->nco_rx = nco_crcf_create(LIQUID_NCO);

    // set pilot sequence
    q->ms_pilot = msequence_create_default(8);

#if OFDMFRAMESYNC_ENABLE_SQUELCH
    // coarse detection
    q->squelch_threshold = -25.0f;
    q->squelch_enabled = 0;
#endif

    // reset object
    ofdmframesync_reset(q);

#if DEBUG_OFDMFRAMESYNC
    q->debug_enabled = 0;
    q->debug_objects_created = 0;

    q->debug_x =        NULL;
    q->debug_rssi =     NULL;
    q->debug_framesyms =NULL;
    
    q->G_hat = NULL;
    q->px    = NULL;
    q->py    = NULL;
    
    q->debug_pilot_0 = NULL;
    q->debug_pilot_1 = NULL;
#endif

    // return object
    return q;
}
示例#3
0
// create OFDM framing generator object
//  _M          :   number of subcarriers, >10 typical
//  _cp_len     :   cyclic prefix length
//  _taper_len  :   taper length (OFDM symbol overlap)
//  _p          :   subcarrier allocation (null, pilot, data), [size: _M x 1]
ofdmframegen ofdmframegen_create(unsigned int    _M,
                                 unsigned int    _cp_len,
                                 unsigned int    _taper_len,
                                 unsigned char * _p)
{
    // validate input
    if (_M < 2) {
        fprintf(stderr,"error: ofdmframegen_create(), number of subcarriers must be at least 2\n");
        exit(1);
    } else if (_M % 2) {
        fprintf(stderr,"error: ofdmframegen_create(), number of subcarriers must be even\n");
        exit(1);
    } else if (_cp_len > _M) {
        fprintf(stderr,"error: ofdmframegen_create(), cyclic prefix cannot exceed symbol length\n");
        exit(1);
    } else if (_taper_len > _cp_len) {
        fprintf(stderr,"error: ofdmframegen_create(), taper length cannot exceed cyclic prefix\n");
        exit(1);
    }

    ofdmframegen q = (ofdmframegen) malloc(sizeof(struct ofdmframegen_s));
    q->M         = _M;
    q->cp_len    = _cp_len;
    q->taper_len = _taper_len;

    // allocate memory for subcarrier allocation IDs
    q->p = (unsigned char*) malloc((q->M)*sizeof(unsigned char));
    if (_p == NULL) {
        // initialize default subcarrier allocation
        ofdmframe_init_default_sctype(q->M, q->p);
    } else {
        // copy user-defined subcarrier allocation
        memmove(q->p, _p, q->M*sizeof(unsigned char));
    }

    // validate and count subcarrier allocation
    ofdmframe_validate_sctype(q->p, q->M, &q->M_null, &q->M_pilot, &q->M_data);
    if ( (q->M_pilot + q->M_data) == 0) {
        fprintf(stderr,"error: ofdmframegen_create(), must have at least one enabled subcarrier\n");
        exit(1);
    } else if (q->M_data == 0) {
        fprintf(stderr,"error: ofdmframegen_create(), must have at least one data subcarriers\n");
        exit(1);
    } else if (q->M_pilot < 2) {
        fprintf(stderr,"error: ofdmframegen_create(), must have at least two pilot subcarriers\n");
        exit(1);
    }

    unsigned int i;

    // allocate memory for transform objects
    q->X = (float complex*) malloc((q->M)*sizeof(float complex));
    q->x = (float complex*) malloc((q->M)*sizeof(float complex));
    q->ifft = FFT_CREATE_PLAN(q->M, q->X, q->x, FFT_DIR_BACKWARD, FFT_METHOD);

    // allocate memory for PLCP arrays
    q->S0 = (float complex*) malloc((q->M)*sizeof(float complex));
    q->s0 = (float complex*) malloc((q->M)*sizeof(float complex));
    q->S1 = (float complex*) malloc((q->M)*sizeof(float complex));
    q->s1 = (float complex*) malloc((q->M)*sizeof(float complex));
    ofdmframe_init_S0(q->p, q->M, q->S0, q->s0, &q->M_S0);
    ofdmframe_init_S1(q->p, q->M, q->S1, q->s1, &q->M_S1);

    // create tapering window and transition buffer
    q->taper   = (float*)         malloc(q->taper_len * sizeof(float));
    q->postfix = (float complex*) malloc(q->taper_len * sizeof(float complex));
    for (i=0; i<q->taper_len; i++) {
        float t = ((float)i + 0.5f) / (float)(q->taper_len);
        float g = sinf(M_PI_2*t);
        q->taper[i] = g*g;
    }
#if 0
    // validate window symmetry
    for (i=0; i<q->taper_len; i++) {
        printf("    taper[%2u] = %12.8f (%12.8f)\n", i, q->taper[i],
            q->taper[i] + q->taper[q->taper_len - i - 1]);
    }
#endif

    // compute scaling factor
    q->g_data = 1.0f / sqrtf(q->M_pilot + q->M_data);

    // set pilot sequence
    q->ms_pilot = msequence_create_default(8);

    return q;
}
示例#4
0
// create ofdmflexframesync object
//  _M          :   number of subcarriers
//  _cp_len     :   length of cyclic prefix [samples]
//  _taper_len  :   taper length (OFDM symbol overlap)
//  _p          :   subcarrier allocation (PILOT/NULL/DATA) [size: _M x 1]
//  _callback   :   user-defined callback function
//  _userdata   :   user-defined data structure passed to callback
ofdmflexframesync ofdmflexframesync_create(unsigned int       _M,
        unsigned int       _cp_len,
        unsigned int       _taper_len,
        unsigned char *    _p,
        framesync_callback _callback,
        void *             _userdata)
{
    ofdmflexframesync q = (ofdmflexframesync) malloc(sizeof(struct ofdmflexframesync_s));

    // validate input
    if (_M < 8) {
        fprintf(stderr,"warning: ofdmflexframesync_create(), less than 8 subcarriers\n");
    } else if (_M % 2) {
        fprintf(stderr,"error: ofdmflexframesync_create(), number of subcarriers must be even\n");
        exit(1);
    } else if (_cp_len > _M) {
        fprintf(stderr,"error: ofdmflexframesync_create(), cyclic prefix length cannot exceed number of subcarriers\n");
        exit(1);
    }

    // set internal properties
    q->M         = _M;
    q->cp_len    = _cp_len;
    q->taper_len = _taper_len;
    q->callback  = _callback;
    q->userdata  = _userdata;

    // allocate memory for subcarrier allocation IDs
    q->p = (unsigned char*) malloc((q->M)*sizeof(unsigned char));
    if (_p == NULL) {
        // initialize default subcarrier allocation
        ofdmframe_init_default_sctype(q->M, q->p);
    } else {
        // copy user-defined subcarrier allocation
        memmove(q->p, _p, q->M*sizeof(unsigned char));
    }

    // validate and count subcarrier allocation
    ofdmframe_validate_sctype(q->p, q->M, &q->M_null, &q->M_pilot, &q->M_data);

    // create internal framing object
    q->fs = ofdmframesync_create(_M, _cp_len, _taper_len, _p, ofdmflexframesync_internal_callback, (void*)q);

    // create header objects
    q->mod_header = modem_create(OFDMFLEXFRAME_H_MOD);
    q->p_header   = packetizer_create(OFDMFLEXFRAME_H_DEC,
                                      OFDMFLEXFRAME_H_CRC,
                                      OFDMFLEXFRAME_H_FEC,
                                      LIQUID_FEC_NONE);
    assert(packetizer_get_enc_msg_len(q->p_header)==OFDMFLEXFRAME_H_ENC);

    // frame properties (default values to be overwritten when frame
    // header is received and properly decoded)
    q->ms_payload   = LIQUID_MODEM_QPSK;
    q->bps_payload  = 2;
    q->payload_len  = 1;
    q->check        = LIQUID_CRC_NONE;
    q->fec0         = LIQUID_FEC_NONE;
    q->fec1         = LIQUID_FEC_NONE;

    // create payload objects (initally QPSK, etc but overridden by received properties)
    q->mod_payload = modem_create(q->ms_payload);
    q->p_payload   = packetizer_create(q->payload_len, q->check, q->fec0, q->fec1);
    q->payload_enc_len = packetizer_get_enc_msg_len(q->p_payload);
    q->payload_enc = (unsigned char*) malloc(q->payload_enc_len*sizeof(unsigned char));
    q->payload_dec = (unsigned char*) malloc(q->payload_len*sizeof(unsigned char));
    q->payload_mod_len = 0;

    // reset state
    ofdmflexframesync_reset(q);

    // return object
    return q;
}
// Helper function to keep code base small
//  _num_subcarriers    :   number of subcarriers
//  _cp_len             :   cyclic prefix lenght
//  _taper_len          :   taper length
void ofdmframesync_acquire_test(unsigned int _num_subcarriers,
                                unsigned int _cp_len,
                                unsigned int _taper_len)
{
    // options
    unsigned int M         = _num_subcarriers;  // number of subcarriers
    unsigned int cp_len    = _cp_len;           // cyclic prefix lenght
    unsigned int taper_len = _taper_len;        // taper length
    float tol              = 1e-2f;             // error tolerance

    //
    float dphi = 1.0f / (float)M;       // carrier frequency offset

    // subcarrier allocation (initialize to default)
    unsigned char p[M];
    ofdmframe_init_default_sctype(M, p);

    // derived values
    unsigned int num_samples = (3 + 1)*(M + cp_len);

    // create synthesizer/analyzer objects
    ofdmframegen fg = ofdmframegen_create(M, cp_len, taper_len, p);
    //ofdmframegen_print(fg);

    float complex X[M];         // original data sequence
    float complex X_test[M];    // recovered data sequence
    ofdmframesync fs = ofdmframesync_create(M,cp_len,taper_len,p,ofdmframesync_autotest_callback,(void*)X_test);

    unsigned int i;
    float complex s0[M];            // short PLCP sequence
    float complex s1[M];            // long PLCP sequence
    float complex y[num_samples];   // frame samples

    // assemble full frame
    unsigned int n=0;

    // write first S0 symbol
    ofdmframegen_write_S0a(fg, &y[n]);
    n += M + cp_len;

    // write second S0 symbol
    ofdmframegen_write_S0b(fg, &y[n]);
    n += M + cp_len;

    // write S1 symbol
    ofdmframegen_write_S1( fg, &y[n]);
    n += M + cp_len;

    // generate data symbol (random)
    for (i=0; i<M; i++) {
        X[i]      = cexpf(_Complex_I*2*M_PI*randf());
        X_test[i] = 0.0f;
    }

    // write data symbol
    ofdmframegen_writesymbol(fg, X, &y[n]);
    n += M + cp_len;

    // validate frame length
    assert(n == num_samples);

    // add carrier offset
    for (i=0; i<num_samples; i++)
        y[i] *= cexpf(_Complex_I*dphi*i);

    // run receiver
    ofdmframesync_execute(fs,y,num_samples);

    // check output
    for (i=0; i<M; i++) {
        if (p[i] == OFDMFRAME_SCTYPE_DATA) {
            float e = crealf( (X[i] - X_test[i])*conjf(X[i] - X_test[i]) );
            CONTEND_DELTA( cabsf(e), 0.0f, tol );
        }
    }

    // destroy objects
    ofdmframegen_destroy(fg);
    ofdmframesync_destroy(fs);
}
示例#6
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;
}
示例#7
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   = 0;    // taper length
    unsigned int num_symbols = 1000; // number of data symbols
    modulation_scheme ms = LIQUID_MODEM_QPSK;

    // get options
    int dopt;
    while((dopt = getopt(argc,argv,"hM:C:T:N:")) != EOF){
        switch (dopt) {
        case 'h': usage();                      return 0;
        case 'M': M           = atoi(optarg);   break;
        case 'C': cp_len      = atoi(optarg);   break;
        case 'T': taper_len   = atoi(optarg);   break;
        case 'N': num_symbols = atoi(optarg);   break;
        default:
            exit(1);
        }
    }

    unsigned int i;

    // derived values
    unsigned int frame_len = M + cp_len;

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

    // create frame generator
    ofdmframegen fg = ofdmframegen_create(M, cp_len, taper_len, p);
    ofdmframegen_print(fg);

    modem mod = modem_create(ms);

    float complex X[M];             // channelized symbols
    float complex buffer[frame_len];// output time series
    float * PAPR = (float*) malloc(num_symbols*sizeof(float));

    // histogram display
    float xmin = -1.29f + 0.70f*log2f(M);
    float xmax =  8.97f + 0.34f*log2f(M);
    unsigned int num_bins = 30;
    float bin_width = (xmax - xmin) / (num_bins);
    unsigned int hist[num_bins];
    for (i=0; i<num_bins; i++)
        hist[i] = 0;

    // modulate data symbols
    unsigned int j;
    unsigned int s;
    float PAPR_min  = 0.0f;
    float PAPR_max  = 0.0f;
    float PAPR_mean = 0.0f;
    for (i=0; i<num_symbols; i++) {
        // data symbol
        for (j=0; j<M; j++) {
            s = modem_gen_rand_sym(mod);
            modem_modulate(mod,s,&X[j]);
        }
        // generate symbol
        ofdmframegen_writesymbol(fg, X, buffer);
#if 0
        // preamble
        if      (i==0) ofdmframegen_write_S0a(fg, buffer); // S0 symbol (first)
        else if (i==1) ofdmframegen_write_S0b(fg, buffer); // S0 symbol (second)
        else if (i==2) ofdmframegen_write_S1( fg, buffer); // S1 symbol
#endif

        // compute PAPR
        PAPR[i] = ofdmframe_PAPR(buffer, frame_len);

        // compute bin index
        unsigned int index;
        float ihat = num_bins * (PAPR[i] - xmin) / (xmax - xmin);
        if (ihat < 0.0f) index = 0;
        else             index = (unsigned int)ihat;
        
        if (index >= num_bins)
            index = num_bins-1;

        hist[index]++;

        // save min/max PAPR values
        if (i==0 || PAPR[i] < PAPR_min) PAPR_min = PAPR[i];
        if (i==0 || PAPR[i] > PAPR_max) PAPR_max = PAPR[i];
        PAPR_mean += PAPR[i];
    }
    PAPR_mean /= (float)num_symbols;

    // destroy objects
    ofdmframegen_destroy(fg);
    modem_destroy(mod);

    // print results to screen
    // find max(hist)
    unsigned int hist_max = 0;
    for (i=0; i<num_bins; i++)
        hist_max = hist[i] > hist_max ? hist[i] : hist_max;

    printf("%8s : %6s [%6s]\n", "PAPR[dB]", "count", "prob.");
    for (i=0; i<num_bins; i++) {
        printf("%8.2f : %6u [%6.4f]", xmin + i*bin_width, hist[i], (float)hist[i] / (float)num_symbols);

        unsigned int k;
        unsigned int n = round(60 * (float)hist[i] / (float)hist_max);
        for (k=0; k<n; k++)
            printf("#");
        printf("\n");
    }
    printf("\n");
    printf("min  PAPR: %12.4f dB\n", PAPR_min);
    printf("max  PAPR: %12.4f dB\n", PAPR_max);
    printf("mean PAPR: %12.4f dB\n", PAPR_mean);

    // 
    // export output file
    //

    // count subcarrier types
    unsigned int M_data  = 0;
    unsigned int M_pilot = 0;
    unsigned int M_null  = 0;
    ofdmframe_validate_sctype(p, M, &M_null, &M_pilot, &M_data);

    FILE * fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME);
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n\n");
    fprintf(fid,"M           = %u;\n", M);
    fprintf(fid,"M_data      = %u;\n", M_data);
    fprintf(fid,"M_pilot     = %u;\n", M_pilot);
    fprintf(fid,"M_null      = %u;\n", M_null);
    fprintf(fid,"cp_len      = %u;\n", cp_len);
    fprintf(fid,"num_symbols = %u;\n", num_symbols);

    fprintf(fid,"PAPR = zeros(1,num_symbols);\n");
    for (i=0; i<num_symbols; i++)
        fprintf(fid,"  PAPR(%6u) = %12.4e;\n", i+1, PAPR[i]);

    fprintf(fid,"\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"hist(PAPR,25);\n");

    fprintf(fid,"\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"cdf = [(1:num_symbols)-0.5]/num_symbols;\n");
    fprintf(fid,"semilogy(sort(PAPR),1-cdf);\n");
    fprintf(fid,"xlabel('PAPR [dB]');\n");
    fprintf(fid,"ylabel('Complementary CDF');\n");

    fclose(fid);
    printf("results written to %s\n", OUTPUT_FILENAME);

    // free allocated array
    free(PAPR);

    printf("done.\n");
    return 0;
}
示例#8
0
// create OFDM flexible framing generator object
//  _M          :   number of subcarriers, >10 typical
//  _cp_len     :   cyclic prefix length
//  _taper_len  :   taper length (OFDM symbol overlap)
//  _p          :   subcarrier allocation (null, pilot, data), [size: _M x 1]
//  _fgprops    :   frame properties (modulation scheme, etc.)
ofdmflexframegen ofdmflexframegen_create(unsigned int              _M,
                                         unsigned int              _cp_len,
                                         unsigned int              _taper_len,
                                         unsigned char *           _p,
                                         ofdmflexframegenprops_s * _fgprops)
{
    // validate input
    if (_M < 2) {
        fprintf(stderr,"error: ofdmflexframegen_create(), number of subcarriers must be at least 2\n");
        exit(1);
    } else if (_M % 2) {
        fprintf(stderr,"error: ofdmflexframegen_create(), number of subcarriers must be even\n");
        exit(1);
    }

    ofdmflexframegen q = (ofdmflexframegen) malloc(sizeof(struct ofdmflexframegen_s));
    q->M         = _M;          // number of subcarriers
    q->cp_len    = _cp_len;     // cyclic prefix length
    q->taper_len = _taper_len;  // taper length

    // allocate memory for transform buffers
    q->X = (float complex*) malloc((q->M)*sizeof(float complex));

    // allocate memory for subcarrier allocation IDs
    q->p = (unsigned char*) malloc((q->M)*sizeof(unsigned char));
    if (_p == NULL) {
        // initialize default subcarrier allocation
        ofdmframe_init_default_sctype(q->M, q->p);
    } else {
        // copy user-defined subcarrier allocation
        memmove(q->p, _p, q->M*sizeof(unsigned char));
    }

    // validate and count subcarrier allocation
    ofdmframe_validate_sctype(q->p, q->M, &q->M_null, &q->M_pilot, &q->M_data);

    // create internal OFDM frame generator object
    q->fg = ofdmframegen_create(q->M, q->cp_len, q->taper_len, q->p);

    // create header objects
    q->mod_header = modem_create(OFDMFLEXFRAME_H_MOD);
    q->p_header   = packetizer_create(OFDMFLEXFRAME_H_DEC,
                                      OFDMFLEXFRAME_H_CRC,
                                      OFDMFLEXFRAME_H_FEC,
                                      LIQUID_FEC_NONE);
    assert(packetizer_get_enc_msg_len(q->p_header)==OFDMFLEXFRAME_H_ENC);

    // compute number of header symbols
    div_t d = div(OFDMFLEXFRAME_H_SYM, q->M_data);
    q->num_symbols_header = d.quot + (d.rem ? 1 : 0);

    // initial memory allocation for payload
    q->payload_dec_len = 1;
    q->p_payload = packetizer_create(q->payload_dec_len,
                                     LIQUID_CRC_NONE,
                                     LIQUID_FEC_NONE,
                                     LIQUID_FEC_NONE);
    q->payload_enc_len = packetizer_get_enc_msg_len(q->p_payload);
    q->payload_enc = (unsigned char*) malloc(q->payload_enc_len*sizeof(unsigned char));

    q->payload_mod_len = 1;
    q->payload_mod = (unsigned char*) malloc(q->payload_mod_len*sizeof(unsigned char));

    // create payload modem (initially QPSK, overridden by properties)
    q->mod_payload = modem_create(LIQUID_MODEM_QPSK);

    // initialize properties
    ofdmflexframegen_setprops(q, _fgprops);

    // reset
    ofdmflexframegen_reset(q);

    // return pointer to main object
    return q;
}