示例#1
0
//
// test phase-locked loop
//  _type           :   NCO type (e.g. LIQUID_NCO)
//  _phase_offset   :   initial phase offset
//  _freq_offset    :   initial frequency offset
//  _pll_bandwidth  :   bandwidth of phase-locked loop
//  _num_iterations :   number of iterations to run
//  _tol            :   error tolerance
void nco_crcf_pll_test(int          _type,
                       float        _phase_offset,
                       float        _freq_offset,
                       float        _pll_bandwidth,
                       unsigned int _num_iterations,
                       float        _tol)
{
    // objects
    nco_crcf nco_tx = nco_crcf_create(_type);
    nco_crcf nco_rx = nco_crcf_create(_type);

    // initialize objects
    nco_crcf_set_phase(nco_tx, _phase_offset);
    nco_crcf_set_frequency(nco_tx, _freq_offset);
    nco_crcf_pll_set_bandwidth(nco_rx, _pll_bandwidth);

    // run loop
    unsigned int i;
    float phase_error;
    float complex r, v;
    for (i=0; i<_num_iterations; i++) {
        // received complex signal
        nco_crcf_cexpf(nco_tx,&r);
        nco_crcf_cexpf(nco_rx,&v);

        // error estimation
        phase_error = cargf(r*conjf(v));

        // update pll
        nco_crcf_pll_step(nco_rx, phase_error);

        // update nco objects
        nco_crcf_step(nco_tx);
        nco_crcf_step(nco_rx);
    }

    // ensure phase of oscillators is locked
    float nco_tx_phase = nco_crcf_get_phase(nco_tx);
    float nco_rx_phase = nco_crcf_get_phase(nco_rx);
    CONTEND_DELTA(nco_tx_phase, nco_rx_phase, _tol);

    // ensure frequency of oscillators is locked
    float nco_tx_freq = nco_crcf_get_frequency(nco_tx);
    float nco_rx_freq = nco_crcf_get_frequency(nco_rx);
    CONTEND_DELTA(nco_tx_freq, nco_rx_freq, _tol);

    // clean it up
    nco_crcf_destroy(nco_tx);
    nco_crcf_destroy(nco_rx);
}
示例#2
0
size_t demodulator_recv(demodulator *d, const sample_t *samples, size_t sample_len,
                        float complex *symbols) {
    if (!d) {
        return 0;
    }

    if (sample_len % d->opt.samples_per_symbol != 0) {
        printf("must receive multiple of samples_per_symbol samples");
        return 0;
    }

    float complex post_mixer[d->opt.samples_per_symbol];
    size_t written = 0;
    for (size_t i = 0; i < sample_len; i += d->opt.samples_per_symbol) {
        for (size_t j = 0; j < d->opt.samples_per_symbol; j++) {
            nco_crcf_mix_down(d->nco, samples[i + j], &post_mixer[j]);
            nco_crcf_step(d->nco);
        }

        if (d->decim) {
            firdecim_crcf_execute(d->decim, &post_mixer[0],
                                  &symbols[(i / d->opt.samples_per_symbol)]);
            symbols[(i / d->opt.samples_per_symbol)] /=
                d->opt.samples_per_symbol;
        } else {
            symbols[i] = post_mixer[0];
        }
        written++;
    }

    return written;
}
示例#3
0
void gmskframesync_execute_rxpreamble(gmskframesync _q,
                                      float complex _x)
{
    // validate input
    if (_q->preamble_counter == _q->preamble_len) {
        fprintf(stderr,"warning: gmskframesync_execute_rxpn(), p/n buffer already full!\n");
        return;
    }

    // mix signal down
    float complex y;
    nco_crcf_mix_down(_q->nco_coarse, _x, &y);
    nco_crcf_step(_q->nco_coarse);

    // update instantanenous frequency estimate
    gmskframesync_update_fi(_q, y);

    // update symbol synchronizer
    float mf_out = 0.0f;
    int sample_available = gmskframesync_update_symsync(_q, _q->fi_hat, &mf_out);

    // compute output if timeout
    if (sample_available) {
        // save output in p/n symbols buffer
        _q->preamble_rx[ _q->preamble_counter ] = mf_out / (float)(_q->k);

        // update counter
        _q->preamble_counter++;

        if (_q->preamble_counter == _q->preamble_len) {
            gmskframesync_syncpn(_q);
            _q->state = STATE_RXHEADER;
        }
    }
}
示例#4
0
void ampmodem_modulate(ampmodem _q,
                       float _x,
                       float complex *_y)
{
    float complex x_hat = 0.0f;
    float complex y_hat;

    if (_q->type == LIQUID_AMPMODEM_DSB) {
        x_hat = _x;
    } else {
        // push through Hilbert transform
        // LIQUID_AMPMODEM_USB:
        // LIQUID_AMPMODEM_LSB: conjugate Hilbert transform output
        firhilbf_r2c_execute(_q->hilbert, _x, &x_hat);

        if (_q->type == LIQUID_AMPMODEM_LSB)
            x_hat = conjf(x_hat);
    }

    if (_q->suppressed_carrier)
        y_hat = x_hat;
    else
        y_hat = 0.5f*(x_hat + 1.0f);
    
    // mix up
    nco_crcf_mix_up(_q->oscillator, y_hat, _y);
    nco_crcf_step(_q->oscillator);
}
示例#5
0
// modulate sample
//  _q      :   frequency modulator object
//  _s      :   input symbol
//  _y      :   output sample array [size: _k x 1]
void fskmod_modulate(fskmod          _q,
                     unsigned int    _s,
                     float complex * _y)
{
    // validate input
    if (_s >= _q->M) {
        fprintf(stderr,"warning: fskmod_modulate(), input symbol (%u) exceeds maximum (%u)\n",
                _s, _q->M);
        _s = 0;
    }

    // compute appropriate frequency
    float dphi = ((float)_s - _q->M2) * 2 * M_PI * _q->bandwidth / _q->M2;

    // set frequency appropriately
    nco_crcf_set_frequency(_q->oscillator, dphi);

    // generate output tone
    unsigned int i;
    for (i=0; i<_q->k; i++) {
        // compute complex output
        nco_crcf_cexpf(_q->oscillator, &_y[i]);

        // step oscillator
        nco_crcf_step(_q->oscillator);
    }
}
示例#6
0
// execute synchronizer, receiving p/n sequence
//  _q     :   frame synchronizer object
//  _x      :   input sample
//  _sym    :   demodulated symbol
void flexframesync_execute_rxpn(flexframesync _q,
                                float complex _x)
{
    // validate input
    if (_q->pn_counter == 64) {
        fprintf(stderr,"warning: flexframesync_execute_rxpn(), p/n buffer already full!\n");
        return;
    }

    // mix signal down
    float complex y;
    nco_crcf_mix_down(_q->nco_coarse, _x*0.5f/_q->gamma_hat, &y);
    nco_crcf_step(_q->nco_coarse);

    // update symbol synchronizer
    float complex mf_out = 0.0f;
    int sample_available = flexframesync_update_symsync(_q, y, &mf_out);

    // compute output if timeout
    if (sample_available) {
        // save output in p/n symbols buffer
        _q->preamble_rx[ _q->pn_counter ] = mf_out;

        // update p/n counter
        _q->pn_counter++;

        if (_q->pn_counter == 64) {
            flexframesync_syncpn(_q);
            _q->state = STATE_RXHEADER;
        }
    }
}
//
// test floating point precision nco
//
void autotest_nco_basic() {
    nco_crcf p = nco_crcf_create(LIQUID_NCO);

    unsigned int i;     // loop index
    float s, c;         // sine/cosine result
    float tol=1e-4f;    // error tolerance
    float f=0.0f;       // frequency to test

    nco_crcf_set_phase( p, 0.0f);
    CONTEND_DELTA( nco_crcf_cos(p), 1.0f, tol );
    CONTEND_DELTA( nco_crcf_sin(p), 0.0f, tol );
    nco_crcf_sincos(p, &s, &c);
    CONTEND_DELTA( s, 0.0f, tol );
    CONTEND_DELTA( c, 1.0f, tol );

    nco_crcf_set_phase(p, M_PI/2);
    CONTEND_DELTA( nco_crcf_cos(p), 0.0f, tol );
    CONTEND_DELTA( nco_crcf_sin(p), 1.0f, tol );
    nco_crcf_sincos(p, &s, &c);
    CONTEND_DELTA( s, 1.0f, tol );
    CONTEND_DELTA( c, 0.0f, tol );

    // cycle through one full period in 64 steps
    nco_crcf_set_phase(p, 0.0f);
    f = 2.0f * M_PI / 64.0f;
    nco_crcf_set_frequency(p, f);
    for (i=0; i<128; i++) {
        nco_crcf_sincos(p, &s, &c);
        CONTEND_DELTA( s, sinf(i*f), tol );
        CONTEND_DELTA( c, cosf(i*f), tol );
        nco_crcf_step(p);
    }

    // double frequency: cycle through one full period in 32 steps
    nco_crcf_set_phase(p, 0.0f);
    f = 2.0f * M_PI / 32.0f;
    nco_crcf_set_frequency(p, f);
    for (i=0; i<128; i++) {
        nco_crcf_sincos(p, &s, &c);
        CONTEND_DELTA( s, sinf(i*f), tol );
        CONTEND_DELTA( c, cosf(i*f), tol );
        nco_crcf_step(p);
    }

    // destroy NCO object
    nco_crcf_destroy(p);
}
示例#8
0
// execute framing synchronizer on input buffer
//  _q      :   framing synchronizer object
//  _buffer :   input buffer [size: _n x 1]
//  _n      :   input buffer size
void wlanframesync_execute(wlanframesync          _q,
                           liquid_float_complex * _buffer,
                           unsigned int           _n)
{
    unsigned int i;
    float complex x;
    for (i=0; i<_n; i++) {
        x = _buffer[i];

        // correct for carrier frequency offset (only if not in
        // initial 'seek PLCP' state)
        if (_q->state != WLANFRAMESYNC_STATE_SEEKPLCP) {
            nco_crcf_mix_down(_q->nco_rx, x, &x);
            nco_crcf_step(_q->nco_rx);
        }

        // save input sample to buffer
        windowcf_push(_q->input_buffer,x);

#if DEBUG_WLANFRAMESYNC
        if (_q->debug_enabled) {
            // apply agc (estimate initial signal gain)
            float complex y;
            agc_crcf_execute(_q->agc_rx, x, &y);

            windowcf_push(_q->debug_x, x);
            windowf_push(_q->debug_rssi, agc_crcf_get_rssi(_q->agc_rx));
        }
#endif

        switch (_q->state) {
        case WLANFRAMESYNC_STATE_SEEKPLCP:
            wlanframesync_execute_seekplcp(_q);
            break;
        case WLANFRAMESYNC_STATE_RXSHORT0:
            wlanframesync_execute_rxshort0(_q);
            break;
        case WLANFRAMESYNC_STATE_RXSHORT1:
            wlanframesync_execute_rxshort1(_q);
            break;
        case WLANFRAMESYNC_STATE_RXLONG0:
            wlanframesync_execute_rxlong0(_q);
            break;
        case WLANFRAMESYNC_STATE_RXLONG1:
            wlanframesync_execute_rxlong1(_q);
            break;
        case WLANFRAMESYNC_STATE_RXSIGNAL:
            wlanframesync_execute_rxsignal(_q);
            break;
        case WLANFRAMESYNC_STATE_RXDATA:
            wlanframesync_execute_rxdata(_q);
            break;
        default:;
            // should never get to this point
            fprintf(stderr,"error: wlanframesync_execute(), invalid state\n");
            exit(1);
        }
    } // for (i=0; i<_n; i++)
}
void PfbSynthesizerComponent::process()
{

  //Get input DataSets
  std::size_t curSize = 0;
  vector< DataSet< complex<float> >* > inSets(nChans_x);
  for(int i=0;i<nChans_x;i++)
  {
    stringstream ss;
    ss << "input";
    ss << i;
    getInputDataSet(ss.str(), inSets[i]);
    std::size_t s = inSets[i]->data.size();
    if(s != curSize && curSize > 0)
      LOG(LWARNING) << "Input channel sizes do not match.";
    curSize = s;
  }

  //Get output DataSet
  DataSet< complex<float> >* writeDataSet = NULL;
  getOutputDataSet("output1", writeDataSet, curSize*nChans_x);
  writeDataSet->sampleRate = inSets[0]->sampleRate*nChans_x;
  writeDataSet->timeStamp = inSets[0]->timeStamp;

  // Execute the synthesizer
  for(int i=0;i<curSize;i++)
  {
    for (int j=0; j<nChans_x; j++)
      buf[j] = inSets[j]->data[i];

    firpfbch_crcf_synthesizer_execute(channelizer, &buf[0], &outBuf[0]);
    copy(outBuf.begin(), outBuf.end(), writeDataSet->data.begin()+i*nChans_x);
  }

  // mix signal down
  for(int i=0;i<writeDataSet->data.size();i++)
  {
    complex<float>* x = &writeDataSet->data[i];
    nco_crcf_mix_down(nco, *x, x);
    nco_crcf_step(nco);
  }

  //Release the DataSets
  for(int i=0;i<nChans_x;i++)
  {
    stringstream ss;
    ss << "input";
    ss << i;
    releaseInputDataSet(ss.str(), inSets[i]);
  }
  releaseOutputDataSet("output1", writeDataSet);

}
示例#10
0
// push buffered p/n sequence through synchronizer
void gmskframesync_pushpn(gmskframesync _q)
{
    unsigned int i;

    // reset filterbanks
    firpfb_rrrf_reset(_q->mf);
    firpfb_rrrf_reset(_q->dmf);

    // read buffer
    float complex * rc;
    windowcf_read(_q->buffer, &rc);

    // compute delay and filterbank index
    //  tau_hat < 0 :   delay = 2*k*m-1, index = round(   tau_hat *npfb), flag = 0
    //  tau_hat > 0 :   delay = 2*k*m-2, index = round((1-tau_hat)*npfb), flag = 0
    assert(_q->tau_hat < 0.5f && _q->tau_hat > -0.5f);
    unsigned int delay = 2*_q->k*_q->m - 1; // samples to buffer before computing output
    _q->pfb_soft       = -_q->tau_hat*_q->npfb;
    _q->pfb_index      = (int) roundf(_q->pfb_soft);
    while (_q->pfb_index < 0) {
        delay         -= 1;
        _q->pfb_index += _q->npfb;
        _q->pfb_soft  += _q->npfb;
    }
    _q->pfb_timer = 0;

    // set coarse carrier frequency offset
    nco_crcf_set_frequency(_q->nco_coarse, _q->dphi_hat);
    
    unsigned int buffer_len = (_q->preamble_len + _q->m) * _q->k;
    for (i=0; i<buffer_len; i++) {
        if (i < delay) {
            float complex y;
            nco_crcf_mix_down(_q->nco_coarse, rc[i], &y);
            nco_crcf_step(_q->nco_coarse);

            // update instantanenous frequency estimate
            gmskframesync_update_fi(_q, y);

            // push initial samples into filterbanks
            firpfb_rrrf_push(_q->mf,  _q->fi_hat);
            firpfb_rrrf_push(_q->dmf, _q->fi_hat);
        } else {
            // run remaining samples through p/n sequence recovery
            gmskframesync_execute_rxpreamble(_q, rc[i]);
        }
    }

    // set state (still need a few more samples before entire p/n
    // sequence has been received)
    _q->state = STATE_RXPREAMBLE;
}
示例#11
0
void ampmodem_demodulate(ampmodem _q,
                         float complex _y,
                         float *_x)
{
#if DEBUG_AMPMODEM
    windowcf_push(_q->debug_x, _y);
#endif

    if (_q->suppressed_carrier) {
        // single side-band suppressed carrier
        if (_q->type != LIQUID_AMPMODEM_DSB) {
            *_x = crealf(_y);
            return;
        }

        // coherent demodulation
        
        // mix signal down
        float complex y_hat;
        nco_crcf_mix_down(_q->oscillator, _y, &y_hat);

        // compute phase error
        float phase_error = tanhf( crealf(y_hat) * cimagf(y_hat) );
#if DEBUG_AMPMODEM
        // compute frequency error
        float nco_freq   = nco_crcf_get_frequency(_q->oscillator);
        float freq_error = nco_freq/(2*M_PI) - _q->fc/(2*M_PI);

        // retain phase and frequency errors
        windowf_push(_q->debug_phase_error, phase_error);
        windowf_push(_q->debug_freq_error, freq_error);
#endif

        // adjust nco, pll objects
        nco_crcf_pll_step(_q->oscillator, phase_error);

        // step NCO
        nco_crcf_step(_q->oscillator);

        // set output
        *_x = crealf(y_hat);
    } else {
        // non-coherent demodulation (peak detector)
        float t = cabsf(_y);

        // remove DC bias
        _q->ssb_q_hat = (    _q->ssb_alpha)*t +
                        (1 - _q->ssb_alpha)*_q->ssb_q_hat;
        *_x = 2.0f*(t - _q->ssb_q_hat);
    }
}
示例#12
0
void ofdmframesync_execute(ofdmframesync _q,
                           float complex * _x,
                           unsigned int _n)
{
    unsigned int i;
    float complex x;
    for (i=0; i<_n; i++) {
        x = _x[i];

        // correct for carrier frequency offset
        if (_q->state != OFDMFRAMESYNC_STATE_SEEKPLCP) {
            nco_crcf_mix_down(_q->nco_rx, x, &x);
            nco_crcf_step(_q->nco_rx);
        }

        // save input sample to buffer
        windowcf_push(_q->input_buffer,x);

#if DEBUG_OFDMFRAMESYNC
        if (_q->debug_enabled) {
            windowcf_push(_q->debug_x, x);
            windowf_push(_q->debug_rssi, crealf(x)*crealf(x) + cimagf(x)*cimagf(x));
        }
#endif

        switch (_q->state) {
        case OFDMFRAMESYNC_STATE_SEEKPLCP:
            ofdmframesync_execute_seekplcp(_q);
            break;
        case OFDMFRAMESYNC_STATE_PLCPSHORT0:
            ofdmframesync_execute_S0a(_q);
            break;
        case OFDMFRAMESYNC_STATE_PLCPSHORT1:
            ofdmframesync_execute_S0b(_q);
            break;
        case OFDMFRAMESYNC_STATE_PLCPLONG:
            ofdmframesync_execute_S1(_q);
            break;
        case OFDMFRAMESYNC_STATE_RXSYMBOLS:
            ofdmframesync_execute_rxsymbols(_q);
            break;
        default:;
        }

    } // for (i=0; i<_n; i++)
} // ofdmframesync_execute()
示例#13
0
// once p/n symbols are buffered, estimate residual carrier
// frequency and phase offsets, push through fine-tuned NCO
void flexframesync_syncpn(flexframesync _q)
{
    unsigned int i;

    // estimate residual carrier frequency offset from p/n symbols
    float complex dphi_metric = 0.0f;
    float complex r0 = 0.0f;
    float complex r1 = 0.0f;
    for (i=0; i<64; i++) {
        r0 = r1;
        r1 = _q->preamble_rx[i]*_q->preamble_pn[i];
        dphi_metric += r1 * conjf(r0);
    }
    float dphi_hat = cargf(dphi_metric);

    // estimate carrier phase offset from p/n symbols
    float complex theta_metric = 0.0f;
    for (i=0; i<64; i++)
        theta_metric += _q->preamble_rx[i]*liquid_cexpjf(-dphi_hat*i)*_q->preamble_pn[i];
    float theta_hat = cargf(theta_metric);
    // TODO: compute gain correction factor

    // initialize fine-tuned nco
    nco_crcf_set_frequency(_q->nco_fine, dphi_hat);
    nco_crcf_set_phase(    _q->nco_fine, theta_hat);

    // correct for carrier offset, pushing through phase-locked loop
    for (i=0; i<64; i++) {
        // mix signal down
        nco_crcf_mix_down(_q->nco_fine, _q->preamble_rx[i], &_q->preamble_rx[i]);
        
        // push through phase-locked loop
        float phase_error = cimagf(_q->preamble_rx[i]*_q->preamble_pn[i]);
        nco_crcf_pll_step(_q->nco_fine, phase_error);
#if DEBUG_FLEXFRAMESYNC
        //_q->debug_nco_phase[i] = nco_crcf_get_phase(_q->nco_fine);
#endif

        // update nco phase
        nco_crcf_step(_q->nco_fine);
    }
}
示例#14
0
int main() {
    // create the NCO object
    nco_crcf p = nco_crcf_create(LIQUID_NCO);
    nco_crcf_set_phase(p, 0.0f);
    nco_crcf_set_frequency(p, M_PI/10);

    unsigned int i;
    float s, c;
    for (i=0; i<11; i++) {
        nco_crcf_sincos(p, &s, &c);
        printf("  %3u : %8.5f + j %8.5f\n",
               i, c, s);
        nco_crcf_step(p);
    }

    // clean up allocated memory
    nco_crcf_destroy(p);

    printf("done.\n");
    return 0;
}
示例#15
0
// step receiver mixer, matched filter, decimator
//  _q      :   frame synchronizer
//  _x      :   input sample
//  _y      :   output symbol
int flexframesync_step(flexframesync   _q,
                       float complex   _x,
                       float complex * _y)
{
    // mix sample down
    float complex v;
    nco_crcf_mix_down(_q->mixer, _x, &v);
    nco_crcf_step    (_q->mixer);
    
    // push sample into filterbank
    firpfb_crcf_push   (_q->mf, v);
    firpfb_crcf_execute(_q->mf, _q->pfb_index, &v);

#if FLEXFRAMESYNC_ENABLE_EQ
    // push sample through equalizer
    eqlms_cccf_push(_q->equalizer, v);
#endif

    // increment counter to determine if sample is available
    _q->mf_counter++;
    int sample_available = (_q->mf_counter >= 1) ? 1 : 0;
    
    // set output sample if available
    if (sample_available) {
#if FLEXFRAMESYNC_ENABLE_EQ
        // compute equalizer output
        eqlms_cccf_execute(_q->equalizer, &v);
#endif

        // set output
        *_y = v;

        // decrement counter by k=2 samples/symbol
        _q->mf_counter -= 2;
    }

    // return flag
    return sample_available;
}
示例#16
0
//
// test nco mixing
//
void autotest_nco_mixing() {
    // frequency, phase
    float f = 0.1f;
    float phi = M_PI;

    // error tolerance (high for NCO)
    float tol = 0.05f;

    // initialize nco object
    nco_crcf p = nco_crcf_create(LIQUID_NCO);
    nco_crcf_set_frequency(p, f);
    nco_crcf_set_phase(p, phi);

    unsigned int i;
    float nco_i, nco_q;
    for (i=0; i<64; i++) {
        // generate sin/cos
        nco_crcf_sincos(p, &nco_q, &nco_i);

        // mix back to zero phase
        complex float nco_cplx_in = nco_i + _Complex_I*nco_q;
        complex float nco_cplx_out;
        nco_crcf_mix_down(p, nco_cplx_in, &nco_cplx_out);

        // assert mixer output is correct
        CONTEND_DELTA(crealf(nco_cplx_out), 1.0f, tol);
        CONTEND_DELTA(cimagf(nco_cplx_out), 0.0f, tol);
        //printf("%3u : %12.8f + j*%12.8f\n", i, crealf(nco_cplx_out), cimagf(nco_cplx_out));

        // step nco
        nco_crcf_step(p);
    }

    // destroy NCO object
    nco_crcf_destroy(p);
}
示例#17
0
// execute synchronizer, receiving header
//  _q      :   frame synchronizer object
//  _x      :   input sample
void flexframesync_execute_rxheader(flexframesync _q,
                                    float complex _x)
{
    // mix signal down
    float complex y;
    nco_crcf_mix_down(_q->nco_coarse, _x*0.5f/_q->gamma_hat, &y);
    nco_crcf_step(_q->nco_coarse);

    // update symbol synchronizer
    float complex mf_out = 0.0f;
    int sample_available = flexframesync_update_symsync(_q, y, &mf_out);

    // compute output if timeout
    if (sample_available) {
        // push through fine-tuned nco
        nco_crcf_mix_down(_q->nco_fine, mf_out, &mf_out);

#if DEBUG_FLEXFRAMESYNC
        if (_q->debug_enabled)
            _q->header_sym[_q->header_counter] = mf_out;
#endif
        
        // demodulate
        unsigned int sym_out = 0;
#if DEMOD_HEADER_SOFT
        unsigned char bpsk_soft_bit = 0;
        modem_demodulate_soft(_q->demod_header, mf_out, &sym_out, &bpsk_soft_bit);
        _q->header_mod[_q->header_counter] = bpsk_soft_bit;
#else
        modem_demodulate(_q->demod_header, mf_out, &sym_out);
        _q->header_mod[_q->header_counter] = (unsigned char)sym_out;
#endif

        // update phase-locked loop and fine-tuned NCO
        float phase_error = modem_get_demodulator_phase_error(_q->demod_header);
        nco_crcf_pll_step(_q->nco_fine, phase_error);
        nco_crcf_step(_q->nco_fine);

        // update error vector magnitude
        float evm = modem_get_demodulator_evm(_q->demod_header);
        _q->framestats.evm += evm*evm;

        // increment counter
        _q->header_counter++;

        if (_q->header_counter == FLEXFRAME_H_SYM) {
            // decode header and invoke callback
            flexframesync_decode_header(_q);
            
            // invoke callback if header is invalid
            if (!_q->header_valid && _q->callback != NULL) {
                // set framestats internals
                _q->framestats.evm           = 20*log10f(sqrtf(_q->framestats.evm / FLEXFRAME_H_SYM));
                _q->framestats.rssi          = 20*log10f(_q->gamma_hat);
                _q->framestats.cfo           = nco_crcf_get_frequency(_q->nco_coarse) +
                                               nco_crcf_get_frequency(_q->nco_fine) / 2.0f; //(float)(_q->k);
                _q->framestats.framesyms     = NULL;
                _q->framestats.num_framesyms = 0;
                _q->framestats.mod_scheme    = LIQUID_MODEM_UNKNOWN;
                _q->framestats.mod_bps       = 0;
                _q->framestats.check         = LIQUID_CRC_UNKNOWN;
                _q->framestats.fec0          = LIQUID_FEC_UNKNOWN;
                _q->framestats.fec1          = LIQUID_FEC_UNKNOWN;

                // invoke callback method
                _q->callback(_q->header,
                             _q->header_valid,
                             NULL,
                             0,
                             0,
                             _q->framestats,
                             _q->userdata);
            }
            
            if (!_q->header_valid) {
                flexframesync_reset(_q);
                return;
            }

            
            // update state
            _q->state = STATE_RXPAYLOAD;
        }
    }
}
示例#18
0
int main() {
    // spectral periodogram options
    unsigned int nfft=256;              // spectral periodogram FFT size
    unsigned int num_samples = 2001;    // number of samples
    float beta = 10.0f;                 // Kaiser-Bessel window parameter

    // allocate memory for data arrays
    float complex x[num_samples];       // input signal
    float complex X[nfft];              // output spectrum
    float psd[nfft];                    // power spectral density

    unsigned int ramp = num_samples/20 < 10 ? 10 : num_samples/20;

    // create spectral periodogram
    unsigned int window_size = nfft/2;  // spgram window size
    unsigned int delay       = nfft/8;  // samples between transforms
    spgram q = spgram_create_kaiser(nfft, window_size, beta);

    unsigned int i;

    // generate signal
    nco_crcf nco = nco_crcf_create(LIQUID_VCO);
    for (i=0; i<num_samples; i++) {
        nco_crcf_set_frequency(nco, 0.1f*(1.2f+sinf(0.007f*i)) );
        nco_crcf_cexpf(nco, &x[i]);
        nco_crcf_step(nco);
    }
    nco_crcf_destroy(nco);

    // add soft ramping functions
    for (i=0; i<ramp; i++) {
        x[i]                    *= 0.5f - 0.5f*cosf(M_PI*(float)i          / (float)ramp);
        x[num_samples-ramp+i-1] *= 0.5f - 0.5f*cosf(M_PI*(float)(ramp-i-1) / (float)ramp);
    }

    // 
    // export output file(s)
    //
    FILE * fid;
    
    // 
    // export time-doman data
    //
    fid = fopen(OUTPUT_FILENAME_TIME,"w");
    fprintf(fid,"# %s : auto-generated file\n", OUTPUT_FILENAME_TIME);
    for (i=0; i<num_samples; i++)
        fprintf(fid,"%12u %12.8f %12.8f\n", i, crealf(x[i]), cimagf(x[i]));
    fclose(fid);
    printf("results written to %s.\n", OUTPUT_FILENAME_TIME);
    
    // 
    // export freq-doman data
    //
    fid = fopen(OUTPUT_FILENAME_FREQ,"w");
    fprintf(fid,"# %s : auto-generated file\n", OUTPUT_FILENAME_FREQ);

    unsigned int t=0;
    for (i=0; i<num_samples; i++) {
        // push sample into periodogram
        spgram_push(q, &x[i], 1);

        if ( ((i+1)%delay)==0 ) {
            // compute spectral periodogram output
            spgram_execute(q, X);

            unsigned int k;

            // compute PSD and FFT shift
            for (k=0; k<nfft; k++)
                psd[k] = 20*log10f( cabsf(X[(k+nfft/2)%nfft]) );
#if 1
            for (k=0; k<nfft; k++)
                fprintf(fid,"%12u %12.8f %12.8f\n", t, (float)k/(float)nfft - 0.5f, psd[k]);
#else
            for (k=0; k<nfft; k++)
                fprintf(fid,"%12.8f ", psd[k]);
#endif
            fprintf(fid,"\n");
            t++;
        }
    }

    // destroy spectral periodogram object
    spgram_destroy(q);

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

    printf("done.\n");
    return 0;
}
示例#19
0
void gmskframesync_execute_rxpayload(gmskframesync _q,
                                     float complex _x)
{
    // mix signal down
    float complex y;
    nco_crcf_mix_down(_q->nco_coarse, _x, &y);
    nco_crcf_step(_q->nco_coarse);

    // update instantanenous frequency estimate
    gmskframesync_update_fi(_q, y);

    // update symbol synchronizer
    float mf_out = 0.0f;
    int sample_available = gmskframesync_update_symsync(_q, _q->fi_hat, &mf_out);

    // compute output if timeout
    if (sample_available) {
        // demodulate
        unsigned char s = mf_out > 0.0f ? 1 : 0;

        // TODO: update evm

        // save payload
        _q->payload_byte <<= 1;
        _q->payload_byte |= s ? 0x01 : 0x00;
        _q->payload_enc[_q->payload_counter/8] = _q->payload_byte;

        // increment counter
        _q->payload_counter++;

        if (_q->payload_counter == 8*_q->payload_enc_len) {
            // decode payload
            _q->payload_valid = packetizer_decode(_q->p_payload,
                                                  _q->payload_enc,
                                                  _q->payload_dec);

            // invoke callback
            if (_q->callback != NULL) {
                // set framestats internals
                _q->framestats.rssi          = 20*log10f(_q->gamma_hat);
                _q->framestats.evm           = 0.0f;
                _q->framestats.framesyms     = NULL;
                _q->framestats.num_framesyms = 0;
                _q->framestats.mod_scheme    = LIQUID_MODEM_UNKNOWN;
                _q->framestats.mod_bps       = 1;
                _q->framestats.check         = _q->check;
                _q->framestats.fec0          = _q->fec0;
                _q->framestats.fec1          = _q->fec1;

                // invoke callback method
                _q->callback(_q->header_dec,
                             _q->header_valid,
                             _q->payload_dec,
                             _q->payload_dec_len,
                             _q->payload_valid,
                             _q->framestats,
                             _q->userdata);
            }

            // reset frame synchronizer
            gmskframesync_reset(_q);
        }
    }
}
示例#20
0
void gmskframesync_execute_rxheader(gmskframesync _q,
                                    float complex _x)
{
    // mix signal down
    float complex y;
    nco_crcf_mix_down(_q->nco_coarse, _x, &y);
    nco_crcf_step(_q->nco_coarse);

    // update instantanenous frequency estimate
    gmskframesync_update_fi(_q, y);

    // update symbol synchronizer
    float mf_out = 0.0f;
    int sample_available = gmskframesync_update_symsync(_q, _q->fi_hat, &mf_out);

    // compute output if timeout
    if (sample_available) {
        // demodulate
        unsigned char s = mf_out > 0.0f ? 1 : 0;

        // TODO: update evm

        // save bit in buffer
        _q->header_mod[_q->header_counter] = s;

        // increment header counter
        _q->header_counter++;
        if (_q->header_counter == GMSKFRAME_H_SYM) {
            // decode header
            gmskframesync_decode_header(_q);

            // invoke callback if header is invalid
            if (!_q->header_valid && _q->callback != NULL) {
                // set framestats internals
                _q->framestats.rssi          = 20*log10f(_q->gamma_hat);
                _q->framestats.evm           = 0.0f;
                _q->framestats.framesyms     = NULL;
                _q->framestats.num_framesyms = 0;
                _q->framestats.mod_scheme    = LIQUID_MODEM_UNKNOWN;
                _q->framestats.mod_bps       = 1;
                _q->framestats.check         = LIQUID_CRC_UNKNOWN;
                _q->framestats.fec0          = LIQUID_FEC_UNKNOWN;
                _q->framestats.fec1          = LIQUID_FEC_UNKNOWN;

                // invoke callback method
                _q->callback(_q->header_dec,
                             _q->header_valid,
                             NULL,
                             0,
                             0,
                             _q->framestats,
                             _q->userdata);

                gmskframesync_reset(_q);
            }

            // reset if invalid
            if (!_q->header_valid) {
                gmskframesync_reset(_q);
                return;
            }

            // update state
            _q->state = STATE_RXPAYLOAD;
        }
    }
}
示例#21
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[])
{
    // options
    unsigned int sequence_len =   80;   // number of sync symbols
    unsigned int k            =    2;   // samples/symbol
    unsigned int m            =    7;   // filter delay [symbols]
    float        beta         = 0.3f;   // excess bandwidth factor
    int          ftype        = LIQUID_FIRFILT_ARKAISER;
    float        gamma        = 10.0f;  // channel gain
    float        tau          = -0.3f;  // fractional sample timing offset
    float        dphi         = -0.01f; // carrier frequency offset
    float        phi          =  0.5f;  // carrier phase offset
    float        SNRdB        = 20.0f;  // signal-to-noise ratio [dB]
    float        threshold    =  0.5f;  // detection threshold

    int dopt;
    while ((dopt = getopt(argc,argv,"hn:k:m:b:F:T:S:t:")) != EOF) {
        switch (dopt) {
        case 'h': usage();                      return 0;
        case 'n': sequence_len  = atoi(optarg); break;
        case 'k': k             = atoi(optarg); break;
        case 'm': m             = atoi(optarg); break;
        case 'b': beta          = atof(optarg); break;
        case 'F': dphi          = atof(optarg); break;
        case 'T': tau           = atof(optarg); break;
        case 'S': SNRdB         = atof(optarg); break;
        case 't': threshold     = atof(optarg); break;
        default:
            exit(1);
        }
    }

    unsigned int i;

    // validate input
    if (tau < -0.5f || tau > 0.5f) {
        fprintf(stderr,"error: %s, fractional sample offset must be in [-0.5,0.5]\n", argv[0]);
        exit(1);
    }

    // generate synchronization sequence (QPSK symbols)
    float complex sequence[sequence_len];
    for (i=0; i<sequence_len; i++) {
        sequence[i] = (rand() % 2 ? 1.0f : -1.0f) * M_SQRT1_2 +
                      (rand() % 2 ? 1.0f : -1.0f) * M_SQRT1_2 * _Complex_I;
    }

    //
    float tau_hat   = 0.0f;
    float gamma_hat = 0.0f;
    float dphi_hat  = 0.0f;
    float phi_hat   = 0.0f;
    int   frame_detected = 0;

    // create detector
    qdetector_cccf q = qdetector_cccf_create_linear(sequence, sequence_len, ftype, k, m, beta);
    qdetector_cccf_set_threshold(q, threshold);
    qdetector_cccf_print(q);

    //
    unsigned int seq_len     = qdetector_cccf_get_seq_len(q);
    unsigned int buf_len     = qdetector_cccf_get_buf_len(q);
    unsigned int num_samples = 2*buf_len;   // double buffer length to ensure detection
    unsigned int num_symbols = buf_len;

    // arrays
    float complex y[num_samples];       // received signal
    float complex syms_rx[num_symbols]; // recovered symbols

    // get pointer to sequence and generate full sequence
    float complex * v = (float complex*) qdetector_cccf_get_sequence(q);
    unsigned int filter_delay = 15;
    firfilt_crcf filter = firfilt_crcf_create_kaiser(2*filter_delay+1, 0.4f, 60.0f, -tau);
    float        nstd        = 0.1f;
    for (i=0; i<num_samples; i++) {
        // add delay
        firfilt_crcf_push(filter, i < seq_len ? v[i] : 0);
        firfilt_crcf_execute(filter, &y[i]);

        // channel gain
        y[i] *= gamma;

        // carrier offset
        y[i] *= cexpf(_Complex_I*(dphi*i + phi));
        
        // noise
        y[i] += nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2;
    }
    firfilt_crcf_destroy(filter);

    // run detection on sequence
    for (i=0; i<num_samples; i++) {
        v = qdetector_cccf_execute(q,y[i]);

        if (v != NULL) {
            printf("\nframe detected!\n");
            frame_detected = 1;

            // get statistics
            tau_hat   = qdetector_cccf_get_tau(q);
            gamma_hat = qdetector_cccf_get_gamma(q);
            dphi_hat  = qdetector_cccf_get_dphi(q);
            phi_hat   = qdetector_cccf_get_phi(q);
            break;
        }
    }

    unsigned int num_syms_rx = 0;   // output symbol counter
    unsigned int counter     = 0;   // decimation counter
    if (frame_detected) {
        // recover symbols
        firfilt_crcf mf = firfilt_crcf_create_rnyquist(ftype, k, m, beta, tau_hat);
        firfilt_crcf_set_scale(mf, 1.0f / (float)(k*gamma_hat));
        nco_crcf     nco = nco_crcf_create(LIQUID_VCO);
        nco_crcf_set_frequency(nco, dphi_hat);
        nco_crcf_set_phase    (nco,  phi_hat);

        for (i=0; i<buf_len; i++) {
            // 
            float complex sample;
            nco_crcf_mix_down(nco, v[i], &sample);
            nco_crcf_step(nco);

            // apply decimator
            firfilt_crcf_push(mf, sample);
            counter++;
            if (counter == k-1)
                firfilt_crcf_execute(mf, &syms_rx[num_syms_rx++]);
            counter %= k;
        }

        nco_crcf_destroy(nco);
        firfilt_crcf_destroy(mf);
    }

    // destroy objects
    qdetector_cccf_destroy(q);

    // print results
    printf("\n");
    printf("frame detected  :   %s\n", frame_detected ? "yes" : "no");
    printf("  gamma hat     : %8.3f, actual=%8.3f (error=%8.3f)\n",            gamma_hat, gamma, gamma_hat - gamma);
    printf("  tau hat       : %8.3f, actual=%8.3f (error=%8.3f) samples\n",    tau_hat,   tau,   tau_hat   - tau  );
    printf("  dphi hat      : %8.5f, actual=%8.5f (error=%8.5f) rad/sample\n", dphi_hat,  dphi,  dphi_hat  - dphi );
    printf("  phi hat       : %8.5f, actual=%8.5f (error=%8.5f) radians\n",    phi_hat,   phi,   phi_hat   - phi  );
    printf("  symbols rx    : %u\n", num_syms_rx);
    printf("\n");

    // 
    // export results
    //
    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,"sequence_len= %u;\n", sequence_len);
    fprintf(fid,"num_samples = %u;\n", num_samples);

    fprintf(fid,"y = zeros(1,num_samples);\n");
    for (i=0; i<num_samples; i++)
        fprintf(fid,"y(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i]));

    fprintf(fid,"num_syms_rx = %u;\n", num_syms_rx);
    fprintf(fid,"syms_rx     = zeros(1,num_syms_rx);\n");
    for (i=0; i<num_syms_rx; i++)
        fprintf(fid,"syms_rx(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(syms_rx[i]), cimagf(syms_rx[i]));

    fprintf(fid,"t=[0:(num_samples-1)];\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(4,1,1);\n");
    fprintf(fid,"  plot(t,real(y), t,imag(y));\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('received signal');\n");
    fprintf(fid,"subplot(4,1,2:4);\n");
    fprintf(fid,"  plot(real(syms_rx), imag(syms_rx), 'x');\n");
    fprintf(fid,"  axis([-1 1 -1 1]*1.5);\n");
    fprintf(fid,"  axis square;\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  xlabel('real');\n");
    fprintf(fid,"  ylabel('imag');\n");

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

    return 0;
}
void ofdmoqamframe64sync_rxpayload(ofdmoqamframe64sync _q,
                                   float complex * _Y0,
                                   float complex * _Y1)
{
    unsigned int j=0;
    unsigned int t=0;
    int sctype;
    unsigned int pilot_phase = msequence_advance(_q->ms_pilot);

    // gain correction (equalizer)
    unsigned int i;
    for (i=0; i<_q->num_subcarriers; i++) {
        _Y0[i] *= _q->G[i];// * _q->zeta;
        _Y1[i] *= _q->G[i];// * _q->zeta;
    }

    // TODO : extract pilots
    for (i=0; i<_q->num_subcarriers; i++) {
        sctype = ofdmoqamframe64_getsctype(i);
        if (sctype==OFDMOQAMFRAME64_SCTYPE_PILOT) {
            // pilot subcarrier : use p/n sequence for pilot phase
            float complex y0 = ((i%2)==0 ? _Y0[i] : _Y1[i]) / _q->zeta;
            float complex y1 = ((i%2)==0 ? _Y1[i] : _Y0[i]) / _q->zeta;
            float complex p = (pilot_phase ? 1.0f : -1.0f);
            float phi_hat =
            ofdmoqamframe64sync_estimate_pilot_phase(y0,y1,p);
            _q->y_phase[t] = phi_hat;
            t++;
#if DEBUG_OFDMOQAMFRAME64SYNC_PRINT
            printf("i = %u\n", i);
            printf("y0 = %12.8f + j*%12.8f;\n", crealf(y0),cimagf(y0));
            printf("y1 = %12.8f + j*%12.8f;\n", crealf(y1),cimagf(y1));
            printf("phi_hat = %12.8f\n", phi_hat);
#endif
            /*
            printf("exiting prematurely\n");
            ofdmoqamframe64sync_destroy(_q);
            exit(1);
            */
        }
    }
    assert(t==4);
 
    // pilot phase correction
    /*
    _q->y_phase[0] = cargf(_q->X[11]);  // -21
    _q->y_phase[1] = cargf(_q->X[25]);  //  -7
    _q->y_phase[2] = cargf(_q->X[39]);  //   7
    _q->y_phase[3] = cargf(_q->X[53]);  //  21
    */

    // try to unwrap phase
    for (i=1; i<4; i++) {
        while ((_q->y_phase[i] - _q->y_phase[i-1]) >  M_PI)
            _q->y_phase[i] -= 2*M_PI;
        while ((_q->y_phase[i] - _q->y_phase[i-1]) < -M_PI)
            _q->y_phase[i] += 2*M_PI;
    }

    // fit phase to 1st-order polynomial (2 coefficients)
    polyf_fit(_q->x_phase, _q->y_phase, 4, _q->p_phase, 2);

    //nco_crcf_step(_q->nco_pilot);
    float theta_hat = nco_crcf_get_phase(_q->nco_pilot);
    float phase_error = _q->p_phase[0] - theta_hat;
    while (phase_error >  M_PI) phase_error -= 2.0f*M_PI;
    while (phase_error < -M_PI) phase_error += 2.0f*M_PI;
    pll_step(_q->pll_pilot, _q->nco_pilot, 0.1f*phase_error);

#if DEBUG_OFDMOQAMFRAME64SYNC_PRINT
    // print phase results
    for (i=0; i<4; i++) {
        printf("x(%3u) = %12.8f; y(%3u) = %12.8f;\n", i+1, _q->x_phase[i], i+1, _q->y_phase[i]);
    }
    printf("p(1) = %12.8f\n", _q->p_phase[0]);
    printf("p(2) = %12.8f\n", _q->p_phase[1]);
#endif

#if DEBUG_OFDMOQAMFRAME64SYNC
    windowf_push(_q->debug_pilotphase,      _q->p_phase[0]);
    windowf_push(_q->debug_pilotphase_hat,  theta_hat);
#endif

    // compensate for phase shift due to timing offset
    float theta;
    _q->p_phase[0] = theta_hat;
    _q->p_phase[1] = 0.0f;
    for (i=0; i<_q->num_subcarriers; i++) {
        // TODO : compute phase for delayed symbol (different from non-delayed symbol)
        theta = polyf_val(_q->p_phase, 2, (float)(i)-32.0f);
        _Y0[i] *= liquid_cexpjf(-theta);
        _Y1[i] *= liquid_cexpjf(-theta);
    }
    nco_crcf_step(_q->nco_pilot);

    // strip data subcarriers
    for (i=0; i<_q->num_subcarriers; i++) {
        sctype = ofdmoqamframe64_getsctype(i);
        if (sctype==OFDMOQAMFRAME64_SCTYPE_NULL) {
            // disabled subcarrier
        } else if (sctype==OFDMOQAMFRAME64_SCTYPE_PILOT) {
            // pilot subcarrier
        } else {
            // data subcarrier
            if ((i%2)==0) {
                // even subcarrier
                _q->data[j] = crealf(_Y0[i]) + 
                              cimagf(_Y1[i]) * _Complex_I;
            } else {
                // odd subcarrier
                _q->data[j] = cimagf(_Y0[i]) * _Complex_I +
                              crealf(_Y1[i]);
            }
            // scaling factor
            _q->data[j] /= _q->zeta;
            j++;
        }
    }
    assert(j==48);

#if DEBUG_OFDMOQAMFRAME64SYNC
    for (i=0; i<48; i++)
        windowcf_push(_q->debug_framesyms,_q->data[i]);
#endif

    if (_q->callback != NULL) {
        int retval = _q->callback(_q->data, _q->userdata);
        if (retval == -1) {
            printf("exiting prematurely\n");
            ofdmoqamframe64sync_destroy(_q);
            exit(0);
        } else if (retval == 1) {
#if DEBUG_OFDMOQAMFRAME64SYNC_PRINT
            printf("resetting synchronizer\n");
#endif
            ofdmoqamframe64sync_reset(_q);
        } else {
            // do nothing
        }
    }

}
示例#24
0
void quiet_beacon_encoder_emit(quiet_beacon_encoder *e, quiet_beacon_sample_t *buf, size_t buflen) {
    for (size_t i = 0; i < buflen; i++) {
        buf[i] = nco_crcf_cos(e->nco) * e->gain;
        nco_crcf_step(e->nco);
    }
}
示例#25
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;
}
示例#26
0
int main()
{
    // spectral periodogram options
    unsigned int nfft        =   1200;  // spectral periodogram FFT size
    unsigned int num_samples =  64000;  // number of samples
    float        fc          =   0.20f; // carrier (relative to sampling rate)

    // create objects
    iirfilt_crcf   filter_tx    = iirfilt_crcf_create_lowpass(15, 0.05);
    nco_crcf       mixer_tx     = nco_crcf_create(LIQUID_VCO);
    nco_crcf       mixer_rx     = nco_crcf_create(LIQUID_VCO);
    iirfilt_crcf   filter_rx    = iirfilt_crcf_create_lowpass(7, 0.2);

    // set carrier frequencies
    nco_crcf_set_frequency(mixer_tx, fc * 2*M_PI);
    nco_crcf_set_frequency(mixer_rx, fc * 2*M_PI);

    // create objects for measuring power spectral density
    spgramcf spgram_tx  = spgramcf_create_default(nfft);
    spgramf  spgram_dac = spgramf_create_default(nfft);
    spgramcf spgram_rx  = spgramcf_create_default(nfft);

    // run through loop one step at a time
    unsigned int i;
    for (i=0; i<num_samples; i++) {
        // STEP 1: generate input signal (filtered noise with offset tone)
        float complex v1 = (randnf() + randnf()*_Complex_I) + 3.0f*cexpf(-_Complex_I*0.2f*i);
        iirfilt_crcf_execute(filter_tx, v1, &v1);

        // save spectrum
        spgramcf_push(spgram_tx, v1);

        // STEP 2: mix signal up and save real part (DAC output)
        nco_crcf_mix_up(mixer_tx, v1, &v1);
        float v2 = crealf(v1);
        nco_crcf_step(mixer_tx);

        // save spectrum
        spgramf_push(spgram_dac, v2);

        // STEP 3: mix signal down and filter off image
        float complex v3;
        nco_crcf_mix_down(mixer_rx, v2, &v3);
        iirfilt_crcf_execute(filter_rx, v3, &v3);
        nco_crcf_step(mixer_rx);

        // save spectrum
        spgramcf_push(spgram_rx, v3);
    }

    // compute power spectral density output
    float   psd_tx  [nfft];
    float   psd_dac [nfft];
    float   psd_rx  [nfft];
    spgramcf_get_psd(spgram_tx,  psd_tx);
    spgramf_get_psd( spgram_dac, psd_dac);
    spgramcf_get_psd(spgram_rx,  psd_rx);

    // destroy objects
    spgramcf_destroy(spgram_tx);
    spgramf_destroy(spgram_dac);
    spgramcf_destroy(spgram_rx);

    iirfilt_crcf_destroy(filter_tx);
    nco_crcf_destroy(mixer_tx);
    nco_crcf_destroy(mixer_rx);
    iirfilt_crcf_destroy(filter_rx);

    // 
    // export output file
    //
    FILE * fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n\n");

    fprintf(fid,"nfft   = %u;\n", nfft);
    fprintf(fid,"f      = [0:(nfft-1)]/nfft - 0.5;\n");
    fprintf(fid,"psd_tx = zeros(1,nfft);\n");
    fprintf(fid,"psd_dac= zeros(1,nfft);\n");
    fprintf(fid,"psd_rx = zeros(1,nfft);\n");
    
    for (i=0; i<nfft; i++) {
        fprintf(fid,"psd_tx (%6u) = %12.4e;\n", i+1, psd_tx [i]);
        fprintf(fid,"psd_dac(%6u) = %12.4e;\n", i+1, psd_dac[i]);
        fprintf(fid,"psd_rx (%6u) = %12.4e;\n", i+1, psd_rx [i]);
    }

    fprintf(fid,"figure;\n");
    fprintf(fid,"hold on;\n");
    fprintf(fid,"  plot(f, psd_tx,  '-', 'LineWidth',1.5,'Color',[0.7 0.7 0.7]);\n");
    fprintf(fid,"  plot(f, psd_dac, '-', 'LineWidth',1.5,'Color',[0.0 0.5 0.3]);\n");
    fprintf(fid,"  plot(f, psd_rx,  '-', 'LineWidth',1.5,'Color',[0.0 0.3 0.5]);\n");
    fprintf(fid,"hold off;\n");
    fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n");
    fprintf(fid,"ylabel('Power Spectral Density [dB]');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"axis([-0.5 0.5 -100 60]);\n");
    fprintf(fid,"legend('transmit (complex)','DAC output (real)','receive (complex)','location','northeast');\n");

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

    printf("done.\n");
    return 0;
}
示例#27
0
void ModemFMStereo::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
    ModemKitFMStereo *fmkit = (ModemKitFMStereo *)kit;
    size_t bufSize = input->data.size();
    liquid_float_complex u, v, w, x, y;
    
    double audio_resample_ratio = fmkit->audioResampleRatio;
    
    if (demodOutputData.size() != bufSize) {
        if (demodOutputData.capacity() < bufSize) {
            demodOutputData.reserve(bufSize);
        }
        demodOutputData.resize(bufSize);
    }
    
    size_t audio_out_size = (size_t)ceil((double) (bufSize) * audio_resample_ratio) + 512;
    
    freqdem_demodulate_block(demodFM, &input->data[0], bufSize, &demodOutputData[0]);
    
    if (resampledOutputData.size() != audio_out_size) {
        if (resampledOutputData.capacity() < audio_out_size) {
            resampledOutputData.reserve(audio_out_size);
        }
        resampledOutputData.resize(audio_out_size);
    }
    
    unsigned int numAudioWritten;
    
    msresamp_rrrf_execute(fmkit->audioResampler, &demodOutputData[0], bufSize, &resampledOutputData[0], &numAudioWritten);
    
    if (demodStereoData.size() != bufSize) {
        if (demodStereoData.capacity() < bufSize) {
            demodStereoData.reserve(bufSize);
        }
        demodStereoData.resize(bufSize);
    }
    
    float phase_error = 0;
    
    for (size_t i = 0; i < bufSize; i++) {
        // real -> complex
        firhilbf_r2c_execute(fmkit->firStereoR2C, demodOutputData[i], &x);
        
        // 19khz pilot band-pass
        iirfilt_crcf_execute(fmkit->iirStereoPilot, x, &v);
        nco_crcf_cexpf(fmkit->stereoPilot, &w);
        
        w.imag = -w.imag; // conjf(w)
        
        // multiply u = v * conjf(w)
        u.real = v.real * w.real - v.imag * w.imag;
        u.imag = v.real * w.imag + v.imag * w.real;
        
        // cargf(u)
        phase_error = atan2f(u.imag,u.real);
        
        // step pll
        nco_crcf_pll_step(fmkit->stereoPilot, phase_error);
        nco_crcf_step(fmkit->stereoPilot);
        
        // 38khz down-mix
        nco_crcf_mix_down(fmkit->stereoPilot, x, &y);
        nco_crcf_mix_down(fmkit->stereoPilot, y, &x);
        
        // complex -> real
        firhilbf_c2r_execute(fmkit->firStereoC2R, x, &demodStereoData[i]);
    }
    
    //            std::cout << "[PLL] phase error: " << phase_error;
    //            std::cout << " freq:" << (((nco_crcf_get_frequency(stereoPilot) / (2.0 * M_PI)) * inp->sampleRate)) << std::endl;
    
    if (audio_out_size != resampledStereoData.size()) {
        if (resampledStereoData.capacity() < audio_out_size) {
            resampledStereoData.reserve(audio_out_size);
        }
        resampledStereoData.resize(audio_out_size);
    }
    
    msresamp_rrrf_execute(fmkit->stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten);
    
    audioOut->channels = 2;
    if (audioOut->data.capacity() < (numAudioWritten * 2)) {
        audioOut->data.reserve(numAudioWritten * 2);
    }
    audioOut->data.resize(numAudioWritten * 2);
    for (size_t i = 0; i < numAudioWritten; i++) {
        float l, r;
        float ld, rd;

        if (fmkit->demph) {
            iirfilt_rrrf_execute(fmkit->iirDemphL, 0.568f * (resampledOutputData[i] - (resampledStereoData[i])), &ld);
            iirfilt_rrrf_execute(fmkit->iirDemphR, 0.568f * (resampledOutputData[i] + (resampledStereoData[i])), &rd);
            
            firfilt_rrrf_push(fmkit->firStereoLeft, ld);
            firfilt_rrrf_execute(fmkit->firStereoLeft, &l);
            
            firfilt_rrrf_push(fmkit->firStereoRight, rd);
            firfilt_rrrf_execute(fmkit->firStereoRight, &r);
        } else {
            firfilt_rrrf_push(fmkit->firStereoLeft, 0.568f * (resampledOutputData[i] - (resampledStereoData[i])));
            firfilt_rrrf_execute(fmkit->firStereoLeft, &l);
            
            firfilt_rrrf_push(fmkit->firStereoRight, 0.568f * (resampledOutputData[i] + (resampledStereoData[i])));
            firfilt_rrrf_execute(fmkit->firStereoRight, &r);
        }
        
        audioOut->data[i * 2] = l;
        audioOut->data[i * 2 + 1] = r;
    }
}
示例#28
0
// execute synchronizer, receiving payload
//  _q     :   frame synchronizer object
//  _x      :   input sample
//  _sym    :   demodulated symbol
void flexframesync_execute_rxpayload(flexframesync _q,
                                     float complex _x)
{
    // mix signal down
    float complex y;
    nco_crcf_mix_down(_q->nco_coarse, _x*0.5f/_q->gamma_hat, &y);
    nco_crcf_step(_q->nco_coarse);

    // update symbol synchronizer
    float complex mf_out = 0.0f;
    int sample_available = flexframesync_update_symsync(_q, y, &mf_out);

    // compute output if timeout
    if (sample_available) {

        // push through fine-tuned nco
        nco_crcf_mix_down(_q->nco_fine, mf_out, &mf_out);
        // save payload symbols for callback (up to 256 values)
        if (_q->payload_counter < 256)
            _q->payload_sym[_q->payload_counter] = mf_out;
        
        // demodulate
        unsigned int sym_out = 0;
        modem_demodulate(_q->demod_payload, mf_out, &sym_out);
        _q->payload_mod[_q->payload_counter] = (unsigned char)sym_out;

        // update phase-locked loop and fine-tuned NCO
        float phase_error = modem_get_demodulator_phase_error(_q->demod_payload);
        nco_crcf_pll_step(_q->nco_fine, phase_error);
        nco_crcf_step(_q->nco_fine);

        // increment counter
        _q->payload_counter++;

        if (_q->payload_counter == _q->payload_mod_len) {
            // decode payload and invoke callback
            flexframesync_decode_payload(_q);

            // invoke callback
            if (_q->callback != NULL) {
                // set framestats internals
                _q->framestats.evm           = 20*log10f(sqrtf(_q->framestats.evm / FLEXFRAME_H_SYM));
                _q->framestats.rssi          = 20*log10f(_q->gamma_hat);
                _q->framestats.cfo           = nco_crcf_get_frequency(_q->nco_coarse) +
                                               nco_crcf_get_frequency(_q->nco_fine) / 2.0f; //(float)(_q->k);
                _q->framestats.framesyms     = _q->payload_sym;
                _q->framestats.num_framesyms = _q->payload_mod_len > 256 ? 256 : _q->payload_mod_len;
                _q->framestats.mod_scheme    = _q->ms_payload;
                _q->framestats.mod_bps       = _q->bps_payload;
                _q->framestats.check         = _q->check;
                _q->framestats.fec0          = _q->fec0;
                _q->framestats.fec1          = _q->fec1;

                // invoke callback method
                _q->callback(_q->header,
                             _q->header_valid,
                             _q->payload_dec,
                             _q->payload_dec_len,
                             _q->payload_valid,
                             _q->framestats,
                             _q->userdata);
            }

            // reset frame synchronizer
            flexframesync_reset(_q);
            return;
        }
    }
}
int main() {
    // options
    unsigned int num_channels=8;    // number of channels
    unsigned int m=2;               // filter delay
    float As=-60;                   // stop-band attenuation
    unsigned int num_frames=25;     // number of frames

    // create objects
    firpfbch_crcf c = firpfbch_crcf_create_kaiser(LIQUID_ANALYZER, num_channels, m, As);

    //firpfbch_crcf_print(c);

    FILE*fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME);
    fprintf(fid,"clear all;\nclose all;\n\n");
    fprintf(fid,"num_channels=%u;\n", num_channels);
    fprintf(fid,"num_frames=%u;\n", num_frames);

    fprintf(fid,"x = zeros(1,%u);\n",  num_channels * num_frames);
    fprintf(fid,"y  = zeros(%u,%u);\n", num_channels, num_frames);

    unsigned int i, j, n=0;
    float complex x[num_channels];  // time-domain input
    float complex y[num_channels];  // channelized output

    // create nco: sweeps entire range of frequencies over the evaluation interval
    nco_crcf nco_tx = nco_crcf_create(LIQUID_VCO);
    nco_crcf_set_frequency(nco_tx, 0.0f);
    float df = 2*M_PI/(num_channels*num_frames);
    printf("fr/ch:");
    for (j=0; j<num_channels; j++)  printf("%3u",j);
    printf("\n");
    for (i=0; i<num_frames; i++) {

        // generate frame of data
        for (j=0; j<num_channels; j++) {
            nco_crcf_cexpf(nco_tx, &x[j]);
            nco_crcf_adjust_frequency(nco_tx, df);
            nco_crcf_step(nco_tx);
        }

        // execute analysis filter bank
        firpfbch_crcf_analyzer_execute(c, x, y);

        printf("%4u : ", i);
        for (j=0; j<num_channels; j++) {
            if (cabsf(y[j]) > num_channels / 4)
                printf(" x ");
            else
                printf(" . ");
        }
        printf("\n");

        // write output to file
        for (j=0; j<num_channels; j++) {
            // frequency data
            fprintf(fid,"y(%4u,%4u) = %12.4e + j*%12.4e;\n", j+1, i+1, crealf(y[j]), cimagf(y[j]));

            // time data
            fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", n+1, crealf(x[j]), cimag(x[j]));
            n++;
        }
    }

    // destroy objects
    nco_crcf_destroy(nco_tx);
    firpfbch_crcf_destroy(c);

    // plot results
    fprintf(fid,"\n\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"  plot(1:length(x),real(x),1:length(x),imag(x));\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('signal');\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"  plot(20*log10(abs(y.')/num_channels));\n");
    fprintf(fid,"  xlabel('time (decimated)');\n");
    fprintf(fid,"  ylabel('channelized energy [dB]');\n");

    fprintf(fid,"n=min(num_channels,8);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"for i=1:n\n");
    fprintf(fid,"  subplot(n,1,i);\n");
    fprintf(fid,"  plot(1:num_frames,real(y(i,:)),1:num_frames,imag(y(i,:)));\n");
    fprintf(fid,"  axis off;\n");
    fprintf(fid,"  ylabel(num2str(i));\n");
    fprintf(fid,"end;\n");


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

    printf("done.\n");
    return 0;
}
示例#30
0
// execute synchronizer, receiving payload
//  _q      :   frame synchronizer object
//  _x      :   input sample
//  _sym    :   demodulated symbol
void flexframesync_execute_rxpayload(flexframesync _q,
                                     float complex _x)
{
    // step synchronizer
    float complex mf_out = 0.0f;
    int sample_available = flexframesync_step(_q, _x, &mf_out);

    // compute output if timeout
    if (sample_available) {
        // TODO: clean this up
        // mix down with fine-tuned oscillator
        nco_crcf_mix_down(_q->pll, mf_out, &mf_out);
        // track phase, accumulate error-vector magnitude
        unsigned int sym;
        modem_demodulate(_q->payload_demod, mf_out, &sym);
        float phase_error = modem_get_demodulator_phase_error(_q->payload_demod);
        float evm         = modem_get_demodulator_evm        (_q->payload_demod);
        nco_crcf_pll_step(_q->pll, phase_error);
        nco_crcf_step(_q->pll);
        _q->framesyncstats.evm += evm*evm;

        // save payload symbols (modem input/output)
        _q->payload_sym[_q->symbol_counter] = mf_out;

        // increment counter
        _q->symbol_counter++;

        if (_q->symbol_counter == _q->payload_sym_len) {
            // decode payload
            _q->payload_valid = qpacketmodem_decode(_q->payload_decoder,
                                                    _q->payload_sym,
                                                    _q->payload_dec);

            // update statistics
            _q->framedatastats.num_frames_detected++;
            _q->framedatastats.num_headers_valid++;
            _q->framedatastats.num_payloads_valid += _q->payload_valid;
            _q->framedatastats.num_bytes_received += _q->payload_dec_len;

            // invoke callback
            if (_q->callback != NULL) {
                // set framestats internals
                int ms = qpacketmodem_get_modscheme(_q->payload_decoder);
                _q->framesyncstats.evm           = 10*log10f(_q->framesyncstats.evm / (float)_q->payload_sym_len);
                _q->framesyncstats.rssi          = 20*log10f(_q->gamma_hat);
                _q->framesyncstats.cfo           = nco_crcf_get_frequency(_q->mixer);
                _q->framesyncstats.framesyms     = _q->payload_sym;
                _q->framesyncstats.num_framesyms = _q->payload_sym_len;
                _q->framesyncstats.mod_scheme    = ms;
                _q->framesyncstats.mod_bps       = modulation_types[ms].bps;
                _q->framesyncstats.check         = qpacketmodem_get_crc(_q->payload_decoder);
                _q->framesyncstats.fec0          = qpacketmodem_get_fec0(_q->payload_decoder);
                _q->framesyncstats.fec1          = qpacketmodem_get_fec1(_q->payload_decoder);

                // invoke callback method
                _q->callback(_q->header_dec,
                             _q->header_valid,
                             _q->payload_dec,
                             _q->payload_dec_len,
                             _q->payload_valid,
                             _q->framesyncstats,
                             _q->userdata);
            }

            // reset frame synchronizer
            flexframesync_reset(_q);
            return;
        }
    }
}