Example #1
0
// Helper function to keep code base small
void window_read_bench(struct rusage *_start,
                       struct rusage *_finish,
                       unsigned long int *_num_iterations,
                       unsigned int _n)
{
    // normalize number of iterations
    if (*_num_iterations < 1) *_num_iterations = 1;

    // initialize port
    windowcf w = windowcf_create(_n);

    unsigned long int i;

    float complex * r;

    // start trials:
    //   write to buffer, read from buffer
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        windowcf_push(w,1.0f);  windowcf_read(w, &r);
        windowcf_push(w,1.0f);  windowcf_read(w, &r);
        windowcf_push(w,1.0f);  windowcf_read(w, &r);
        windowcf_push(w,1.0f);  windowcf_read(w, &r);
    }
    getrusage(RUSAGE_SELF, _finish);
    *_num_iterations *= 4;

    windowcf_destroy(w);
}
Example #2
0
// frame detection
void wlanframesync_execute_rxshort0(wlanframesync _q)
{
    _q->timer++;
    if (_q->timer < 16)
        return;

    // reset timer
    _q->timer = 0;

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

    // re-estimate S0 gain
    wlanframesync_estimate_gain_S0(_q, &rc[16], _q->G0a);

    float complex s_hat;
    wlanframesync_S0_metrics(_q, _q->G0a, &s_hat);
    //float g = agc_crcf_get_gain(_q->agc_rx);
    s_hat *= _q->g0;

    // save first 'short' symbol statistic
    _q->s0a_hat = s_hat;

#if DEBUG_WLANFRAMESYNC_PRINT
    float tau_hat  = cargf(s_hat) * 16.0f / (2*M_PI);
    printf("********** S0[a] received ************\n");
    printf("    s_hat   :   %12.8f <%12.8f>\n", cabsf(s_hat), cargf(s_hat));
    printf("  tau_hat   :   %12.8f\n", tau_hat);
#endif

    _q->state = WLANFRAMESYNC_STATE_RXSHORT1;
}
void ofdmoqamframe64sync_execute_plcplong1(ofdmoqamframe64sync _q, float complex _x)
{
    // cross-correlator
    float complex rxy;
    firfilt_cccf_push(_q->crosscorr, _x);
    firfilt_cccf_execute(_q->crosscorr, &rxy);

    rxy *= _q->g;

#if DEBUG_OFDMOQAMFRAME64SYNC
    windowcf_push(_q->debug_rxy, rxy);
#endif

    _q->timer++;
    if (_q->timer < _q->num_subcarriers-8) {
        return;
    } else if (_q->timer > _q->num_subcarriers+8) {
#if DEBUG_OFDMOQAMFRAME64SYNC_PRINT
        printf("warning: ofdmoqamframe64sync could not find second PLCP long sequence; resetting synchronizer\n");
#endif
        ofdmoqamframe64sync_reset(_q);
        return;
    }

    if (cabsf(rxy) > 0.7f*(_q->rxy_thresh)*(_q->num_subcarriers)) {
#if DEBUG_OFDMOQAMFRAME64SYNC_PRINT
        printf("rxy[1] : %12.8f at input[%3u]\n", cabsf(rxy), _q->num_samples);
#endif

        // 
        float complex * rc;
        windowcf_read(_q->input_buffer, &rc);
        memmove(_q->S1b, rc, 64*sizeof(float complex));

        // estimate frequency offset
        float complex rxy_hat=0.0f;
        unsigned int j;
        for (j=0; j<64; j++) {
            rxy_hat += _q->S1a[j] * conjf(_q->S1b[j]) * hamming(j,64);
        }
        float nu_hat1 = -cargf(rxy_hat);
        if (nu_hat1 >  M_PI) nu_hat1 -= 2.0f*M_PI;
        if (nu_hat1 < -M_PI) nu_hat1 += 2.0f*M_PI;
        nu_hat1 /= 64.0f;
#if DEBUG_OFDMOQAMFRAME64SYNC_PRINT
        printf("nu_hat[0] = %12.8f\n", _q->nu_hat);
        printf("nu_hat[1] = %12.8f\n", nu_hat1);
#endif
        nco_crcf_adjust_frequency(_q->nco_rx, nu_hat1);

        /*
        printf("exiting prematurely\n");
        ofdmoqamframe64sync_destroy(_q);
        exit(1);
        */
        _q->state = OFDMOQAMFRAME64SYNC_STATE_RXSYMBOLS;
    }

}
Example #4
0
// frame detection
void wlanframesync_execute_rxshort1(wlanframesync _q)
{
    _q->timer++;
    if (_q->timer < 16)
        return;

    // reset timer
    _q->timer = 0;

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

    // estimate S0 gain
    wlanframesync_estimate_gain_S0(_q, &rc[16], _q->G0b);

    float complex s_hat;
    wlanframesync_S0_metrics(_q, _q->G0b, &s_hat);
    //float g = agc_crcf_get_gain(_q->agc_rx);
    s_hat *= _q->g0;

    // save second 'short' symbol statistic
    _q->s0b_hat = s_hat;

#if DEBUG_WLANFRAMESYNC_PRINT
    float tau_hat  = cargf(s_hat) * 16.0f / (2*M_PI);
    printf("********** S0[b] received ************\n");
    printf("    s_hat   :   %12.8f <%12.8f>\n", cabsf(s_hat), cargf(s_hat));
    printf("  tau_hat   :   %12.8f\n", tau_hat);
    
    // new timing offset estimate
    tau_hat  = cargf(_q->s0a_hat + _q->s0b_hat) * 16.0f / (2*M_PI);
    printf("  tau_hat * :   %12.8f\n", tau_hat);
#endif

#if 0
    // compute carrier frequency offset estimate using ML method
    float complex t0 = 0.0f;
    for (i=0; i<48; i++) {
        t0 += conjf(rc[i])   *       wlanframe_s0[i] * 
                    rc[i+16] * conjf(wlanframe_s0[i+16]);
    }
    float nu_hat = cargf(t0) / (float)(_q->M2);
#else
    // compute carrier frequency offset estimate using freq. domain method
    float nu_hat = wlanframesync_estimate_cfo_S0(_q->G0a, _q->G0b);
#endif

    // set NCO frequency
    nco_crcf_set_frequency(_q->nco_rx, nu_hat);

#if DEBUG_WLANFRAMESYNC_PRINT
    printf("   nu_hat[0]:   %12.8f\n", nu_hat);
#endif

    // set state
    _q->state = WLANFRAMESYNC_STATE_RXLONG0;
}
Example #5
0
void wlanframesync_execute_rxlong0(wlanframesync _q)
{
    // set timer to 16, wait for phase to be relatively small
    
    _q->timer++;
    if (_q->timer < 16)
        return;

    // reset timer
    _q->timer = 0;

    // run fft
    float complex * rc;
    windowcf_read(_q->input_buffer, &rc);

    // estimate S1 gain, adding backoff in gain estimation
    wlanframesync_estimate_gain_S1(_q, &rc[16-2], _q->G1a);

    // compute S1 metrics
    float complex s_hat;
    wlanframesync_S1_metrics(_q, _q->G1a, &s_hat);
    s_hat *= _q->g0;    // scale output by raw gain estimate

    // rotate by complex phasor relative to timing backoff
    //s_hat *= cexpf(_Complex_I * 2.0f * 2.0f * M_PI / 64.0f);
    s_hat *= cexpf(_Complex_I * 0.19635f);

    // save first 'long' symbol statistic
    _q->s1a_hat = s_hat;

#if DEBUG_WLANFRAMESYNC_PRINT
    printf("    s_hat   :   %12.8f <%12.8f>\n", cabsf(s_hat), cargf(s_hat));
#endif

    float s_hat_abs = cabsf(s_hat);
    float s_hat_arg = cargf(s_hat);
    if (s_hat_arg >  M_PI) s_hat_arg -= 2.0f*M_PI;
    if (s_hat_arg < -M_PI) s_hat_arg += 2.0f*M_PI;
    
    // check conditions for s_hat:
    //  1. magnitude should be large (near unity) when aligned
    //  2. phase should be very near zero (time aligned)
    if (s_hat_abs        > WLANFRAMESYNC_S1A_ABS_THRESH &&
        fabsf(s_hat_arg) < WLANFRAMESYNC_S1A_ARG_THRESH)
    {
#if DEBUG_WLANFRAMESYNC_PRINT
        printf("    acquisition S1[a]\n");
#endif
        
        // set state
        _q->state = WLANFRAMESYNC_STATE_RXLONG1;

        // reset timer
        _q->timer = 0;
    }

}
Example #6
0
// export debugging file
void ampmodem_debug_print(ampmodem _q,
                          const char * _filename)
{
    FILE * fid = fopen(_filename,"w");
    if (!fid) {
        fprintf(stderr,"error: ofdmframe_debug_print(), could not open '%s' for writing\n", _filename);
        return;
    }
    fprintf(fid,"%% %s : auto-generated file\n", DEBUG_AMPMODEM_FILENAME);
#if DEBUG_AMPMODEM
    fprintf(fid,"close all;\n");
    fprintf(fid,"clear all;\n");
    fprintf(fid,"n = %u;\n", DEBUG_AMPMODEM_BUFFER_LEN);
    unsigned int i;
    float complex * rc;
    float * r;

    // plot received signal
    fprintf(fid,"x = zeros(1,n);\n");
    windowcf_read(_q->debug_x, &rc);
    for (i=0; i<DEBUG_AMPMODEM_BUFFER_LEN; i++)
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(0:(n-1),real(x),0:(n-1),imag(x));\n");
    fprintf(fid,"xlabel('sample index');\n");
    fprintf(fid,"ylabel('received signal, x');\n");

    // plot phase/freq error
    fprintf(fid,"phase_error = zeros(1,n);\n");
    windowf_read(_q->debug_phase_error, &r);
    for (i=0; i<DEBUG_AMPMODEM_BUFFER_LEN; i++)
        fprintf(fid,"phase_error(%4u) = %12.4e;\n", i+1, r[i]);

    fprintf(fid,"freq_error = zeros(1,n);\n");
    windowf_read(_q->debug_freq_error, &r);
    for (i=0; i<DEBUG_AMPMODEM_BUFFER_LEN; i++)
        fprintf(fid,"freq_error(%4u) = %12.4e;\n", i+1, r[i]);

    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1),\n");
    fprintf(fid,"  plot(0:(n-1),phase_error);\n");
    fprintf(fid,"  xlabel('sample index');\n");
    fprintf(fid,"  ylabel('phase error');\n");
    fprintf(fid,"subplot(2,1,2),\n");
    fprintf(fid,"  plot(0:(n-1),freq_error);\n");
    fprintf(fid,"  xlabel('sample index');\n");
    fprintf(fid,"  ylabel('freq error');\n");

#else
    fprintf(fid,"disp('no debugging info available');\n");
#endif

    fclose(fid);
    printf("ampmodem/debug: results written to '%s'\n", _filename);
}
Example #7
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;
}
Example #8
0
// frame detection
void ofdmframesync_execute_S0a(ofdmframesync _q)
{
    //printf("t : %u\n", _q->timer);
    _q->timer++;

    if (_q->timer < _q->M2)
        return;

    // reset timer
    _q->timer = 0;

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

    // TODO : re-estimate nominal gain

    // estimate S0 gain
    ofdmframesync_estimate_gain_S0(_q, &rc[_q->cp_len], _q->G0);

    float complex s_hat;
    ofdmframesync_S0_metrics(_q, _q->G0, &s_hat);
    s_hat *= _q->g0;

    _q->s_hat_0 = s_hat;

#if DEBUG_OFDMFRAMESYNC_PRINT
    float tau_hat  = cargf(s_hat) * (float)(_q->M2) / (2*M_PI);
    printf("********** S0[0] received ************\n");
    printf("    s_hat   :   %12.8f <%12.8f>\n", cabsf(s_hat), cargf(s_hat));
    printf("  tau_hat   :   %12.8f\n", tau_hat);
#endif

#if 0
    // TODO : also check for phase of s_hat (should be small)
    if (cabsf(s_hat) < 0.3f) {
        // false alarm
#if DEBUG_OFDMFRAMESYNC_PRINT
        printf("false alarm S0[0]\n");
#endif
        ofdmframesync_reset(_q);
        return;
    }
#endif
    _q->state = OFDMFRAMESYNC_STATE_PLCPSHORT1;
}
void ofdmoqamframe64sync_execute_plcplong0(ofdmoqamframe64sync _q, float complex _x)
{
    // cross-correlator
    float complex rxy;
    firfilt_cccf_push(_q->crosscorr, _x);
    firfilt_cccf_execute(_q->crosscorr, &rxy);

    rxy *= _q->g;

#if DEBUG_OFDMOQAMFRAME64SYNC
    windowcf_push(_q->debug_rxy, rxy);
#endif

    _q->timer++;
    if (_q->timer > 10*(_q->num_subcarriers)) {
#if DEBUG_OFDMOQAMFRAME64SYNC_PRINT
        printf("warning: ofdmoqamframe64sync could not find first PLCP long sequence; resetting synchronizer\n");
#endif
        ofdmoqamframe64sync_reset(_q);
        return;
    }

    if (cabsf(rxy) > (_q->rxy_thresh)*(_q->num_subcarriers)) {
#if DEBUG_OFDMOQAMFRAME64SYNC_PRINT
        printf("rxy[0] : %12.8f at input[%3u]\n", cabsf(rxy), _q->num_samples);
#endif

        // run analyzers
        //firpfbch_analyzer_run(_q->ca0, _q->S1a);
        //firpfbch_analyzer_run(_q->ca1, _q->S1b);

        _q->sample_phase = (_q->num_samples + (_q->num_subcarriers)/2) % _q->num_subcarriers;
        //_q->sample_phase = (_q->num_samples) % _q->num_subcarriers;
#if DEBUG_OFDMOQAMFRAME64SYNC_PRINT
        printf("sample phase : %u\n",_q->sample_phase);
#endif
        // 
        float complex * rc;
        windowcf_read(_q->input_buffer, &rc);
        memmove(_q->S1a, rc, 64*sizeof(float complex));

        _q->state = OFDMOQAMFRAME64SYNC_STATE_PLCPLONG1;
        _q->timer = 0;
    }
}
Example #10
0
void do_spectrum() {
    std::complex<float> *data_in;
    windowcf_read(w, &data_in);
    fftplan q = fft_create_plan(SPECTRUM_FFT_LENGTH,data_in,spectrum_fft_output,LIQUID_FFT_FORWARD,0);

    fft_execute(q);
    fft_destroy_plan(q);

    spectrum_fft_magnitude[0] = 0.0; //Do not consider DC comp

    int maxIdx = 0;
    float maxVal = 0;
    double total_power = 0;
    double psd = 0;
    for (int i = 1; i < SPECTRUM_FFT_LENGTH/2; i++) {
        spectrum_fft_magnitude[i] = std::norm(spectrum_fft_output[i]);
        total_power += spectrum_fft_magnitude[i];
        if (spectrum_fft_magnitude[i] > maxVal) {
            maxIdx = i;
            maxVal = spectrum_fft_magnitude[i];
        } 
    }
    // TODO normalize so window size does not affect this threshold.
    psd = maxVal / total_power;

    if (shm_settings.auto_magnitude_thresholding == 0) {
        if (psd > shm_settings.spectrum_magnitude_threshold && (current_sample_count - old_spectrum_sample_count > shm_settings.spectrum_cooldown_samples)) {
            shm_results_spectrum.most_recent_ping_magnitude = maxVal;
            shm_results_spectrum.most_recent_ping_frequency = (double) SAMPLING_FREQUENCY / (double) SPECTRUM_FFT_LENGTH * (double) maxIdx;
            shm_results_spectrum.most_recent_ping_count++;
            old_spectrum_sample_count = current_sample_count;
            shm_setg(hydrophones_results_spectrum, shm_results_spectrum);
        }
        prev_psd = psd;
    }
    else {
        //IMPLEMENTE AUTO THRESHOLDING AND ASSOCIATED PING STUFF
    } 
}
Example #11
0
void ofdmframesync_execute_rxsymbols(ofdmframesync _q)
{
    // wait for timeout
    _q->timer--;

    if (_q->timer == 0) {

        // run fft
        float complex * rc;
        windowcf_read(_q->input_buffer, &rc);
        memmove(_q->x, &rc[_q->cp_len-_q->backoff], (_q->M)*sizeof(float complex));
        FFT_EXECUTE(_q->fft);

        // recover symbol in internal _q->X buffer
        ofdmframesync_rxsymbol(_q);

#if DEBUG_OFDMFRAMESYNC
        if (_q->debug_enabled) {
            unsigned int i;
            for (i=0; i<_q->M; i++) {
                if (_q->p[i] == OFDMFRAME_SCTYPE_DATA)
                    windowcf_push(_q->debug_framesyms, _q->X[i]);
            }
        }
#endif
        // invoke callback
        if (_q->callback != NULL) {
            int retval = _q->callback(_q->X, _q->p, _q->M, _q->userdata);

            if (retval != 0)
                ofdmframesync_reset(_q);
        }

        // reset timer
        _q->timer = _q->M + _q->cp_len;
    }

}
Example #12
0
void do_track(){
    if (local_track_freq != shm_settings.track_frequency_target) {
       if (ff.sosMap.count(shm_settings.track_frequency_target)) { //frequency key exists
            if (track_filterA != NULL)
                iirfilt_crcf_destroy(track_filterA);
            if (track_filterB != NULL)
                iirfilt_crcf_destroy(track_filterB);
            if (track_filterC != NULL)
                iirfilt_crcf_destroy(track_filterC);

            float *b = &((ff.sosMap[shm_settings.track_frequency_target]->b)[0]);
            float *a = &((ff.sosMap[shm_settings.track_frequency_target]->a)[0]);
            track_filterA = iirfilt_crcf_create_sos(b,a,NUMBER_OF_SECTIONS);
            track_filterB = iirfilt_crcf_create_sos(b,a,NUMBER_OF_SECTIONS);
            track_filterC = iirfilt_crcf_create_sos(b,a,NUMBER_OF_SECTIONS);

            shm_results_track.track_state = 0;

            local_track_freq = shm_settings.track_frequency_target;
            float normalized_frequency = (float) shm_settings.track_frequency_target / (float) SAMPLING_FREQUENCY;
            nco_crcf_set_frequency(nco,2*M_PI*normalized_frequency);
        }
        else { //frequency key does not exist. Trigger error state
            shm_results_track.track_state = -1;
            std::cerr << shm_settings.track_frequency_target << " WARN TRACK FREQ NOT IN SOS TABLE" << std::endl;
        }

        shm_setg(hydrophones_results_track, shm_results_track);
    }

    std::complex<float> *chA_ptr, *chA_filtered_ptr;
    std::complex<float> *chB_ptr, *chB_filtered_ptr;
    std::complex<float> *chC_ptr, *chC_filtered_ptr;

    float *mag_ptr;
    windowcf_read(wchA,&chA_ptr);
    windowcf_read(wchB,&chB_ptr);
    windowcf_read(wchC,&chC_ptr);

    std::complex<float> filtOutA, filtOutB, filtOutC;

    for (int i = 0; i < SAMPLING_DEPTH; i++) {
        iirfilt_crcf_execute(track_filterA,chA_ptr[i],&filtOutA);
        iirfilt_crcf_execute(track_filterB,chB_ptr[i],&filtOutB);
        iirfilt_crcf_execute(track_filterC,chC_ptr[i],&filtOutC);
        
        windowcf_read(wchA_filtered,&chA_filtered_ptr);
        windowcf_read(wchB_filtered,&chB_filtered_ptr);
        windowcf_read(wchC_filtered,&chC_filtered_ptr);

        windowcf_push(wchA_filtered,filtOutA);
        windowcf_push(wchB_filtered,filtOutB);
        windowcf_push(wchC_filtered,filtOutC);

        float b_sqrd = std::pow(std::real(filtOutB),2);

        pwr_sum += b_sqrd;
        windowf_read(wmag_buffer,&mag_ptr);
        pwr_sum -= mag_ptr[0];
        windowf_push(wmag_buffer,b_sqrd);

        double normalized_pwr = pwr_sum / (double)TRACK_LENGTH;
        if (normalized_pwr > shm_settings.track_magnitude_threshold &&
            (track_sample_idx - shm_results_track.tracked_ping_time) >= shm_settings.track_cooldown_samples) {
            std::complex<float> dtft_coeff_A = goertzelNonInteger(chA_filtered_ptr,TRACK_LENGTH,shm_settings.track_frequency_target,SAMPLING_FREQUENCY);
            std::complex<float> dtft_coeff_B = goertzelNonInteger(chB_filtered_ptr,TRACK_LENGTH,shm_settings.track_frequency_target,SAMPLING_FREQUENCY);
            std::complex<float> dtft_coeff_C = goertzelNonInteger(chC_filtered_ptr,TRACK_LENGTH,shm_settings.track_frequency_target,SAMPLING_FREQUENCY);
             
            float phaseA = std::arg(dtft_coeff_A);
            float phaseB = std::arg(dtft_coeff_B);
            float phaseC = std::arg(dtft_coeff_C);

            shm_results_track.diff_phase_y = phase_difference(phaseC,phaseB);
            shm_results_track.diff_phase_x = phase_difference(phaseA,phaseB);

            float kx = SOUND_SPEED * shm_results_track.diff_phase_x / (NIPPLE_DISTANCE * 2 * M_PI * shm_settings.track_frequency_target);
            float ky = SOUND_SPEED * shm_results_track.diff_phase_y / (NIPPLE_DISTANCE * 2 * M_PI * shm_settings.track_frequency_target);

            float kz_2 = 1 - kx * kx - ky * ky;
            if (kz_2 < 0) {
              std::cerr << "WARNING: z mag is negative! " << kz_2 << std::endl;
              kz_2 = 0;
            }

            shm_results_track.tracked_ping_heading_radians = std::atan2(ky, kx);
            shm_results_track.tracked_ping_elevation_radians = std::acos(std::sqrt(kz_2));

            shm_results_track.tracked_ping_count++;
            shm_results_track.tracked_ping_frequency = shm_results_spectrum.most_recent_ping_frequency;  
            shm_results_track.tracked_ping_time = track_sample_idx; 

            std::cout << "PING DETECTED @ n=" << track_sample_idx << " w/ pwr="<< normalized_pwr<< std::endl;
            std::cout << "@ HEADING=" << shm_results_track.tracked_ping_heading_radians*(180.0f/M_PI) << std::endl; 

            shm_setg(hydrophones_results_track, shm_results_track);
        }
        track_sample_idx++;

    }
}
Example #13
0
// receive the 'SIGNAL' field
void wlanframesync_execute_rxsignal(wlanframesync _q)
{
    _q->timer++;
    if (_q->timer < 80)
        return;

    // reset timer
    _q->timer = 0;

    // run fft
    float complex * rc;
    windowcf_read(_q->input_buffer, &rc);
    memmove(_q->x, &rc[16-2], 64*sizeof(float complex));

    // compute fft, storing result into _q->X
    FFT_EXECUTE(_q->fft);
  
    // recover symbol, correcting for gain, pilot phase, etc.
    wlanframesync_rxsymbol(_q);
    
    // demodulate, decode, ...
    memset(_q->signal_int, 0x00, 6*sizeof(unsigned char));

    _q->signal_int[0] |= crealf(_q->X[38]) > 0.0f ? 0x80 : 0x00;
    _q->signal_int[0] |= crealf(_q->X[39]) > 0.0f ? 0x40 : 0x00;
    _q->signal_int[0] |= crealf(_q->X[40]) > 0.0f ? 0x20 : 0x00;
    _q->signal_int[0] |= crealf(_q->X[41]) > 0.0f ? 0x10 : 0x00;
    _q->signal_int[0] |= crealf(_q->X[42]) > 0.0f ? 0x08 : 0x00;
    //  43 : pilot
    _q->signal_int[0] |= crealf(_q->X[44]) > 0.0f ? 0x04 : 0x00;
    _q->signal_int[0] |= crealf(_q->X[45]) > 0.0f ? 0x02 : 0x00;
    _q->signal_int[0] |= crealf(_q->X[46]) > 0.0f ? 0x01 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[47]) > 0.0f ? 0x80 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[48]) > 0.0f ? 0x40 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[49]) > 0.0f ? 0x20 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[50]) > 0.0f ? 0x10 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[51]) > 0.0f ? 0x08 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[52]) > 0.0f ? 0x04 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[53]) > 0.0f ? 0x02 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[54]) > 0.0f ? 0x01 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[55]) > 0.0f ? 0x80 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[56]) > 0.0f ? 0x40 : 0x00;
    //  57 : pilot
    _q->signal_int[2] |= crealf(_q->X[58]) > 0.0f ? 0x20 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[59]) > 0.0f ? 0x10 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[60]) > 0.0f ? 0x08 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[61]) > 0.0f ? 0x04 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[62]) > 0.0f ? 0x02 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[63]) > 0.0f ? 0x01 : 0x00;
    //   0 : NULL
    _q->signal_int[3] |= crealf(_q->X[ 1]) > 0.0f ? 0x80 : 0x00;
    _q->signal_int[3] |= crealf(_q->X[ 2]) > 0.0f ? 0x40 : 0x00;
    _q->signal_int[3] |= crealf(_q->X[ 3]) > 0.0f ? 0x20 : 0x00;
    _q->signal_int[3] |= crealf(_q->X[ 4]) > 0.0f ? 0x10 : 0x00;
    _q->signal_int[3] |= crealf(_q->X[ 5]) > 0.0f ? 0x08 : 0x00;
    _q->signal_int[3] |= crealf(_q->X[ 6]) > 0.0f ? 0x04 : 0x00;
    //   7 : pilot
    _q->signal_int[3] |= crealf(_q->X[ 8]) > 0.0f ? 0x02 : 0x00;
    _q->signal_int[3] |= crealf(_q->X[ 9]) > 0.0f ? 0x01 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[10]) > 0.0f ? 0x80 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[11]) > 0.0f ? 0x40 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[12]) > 0.0f ? 0x20 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[13]) > 0.0f ? 0x10 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[14]) > 0.0f ? 0x08 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[15]) > 0.0f ? 0x04 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[16]) > 0.0f ? 0x02 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[17]) > 0.0f ? 0x01 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[18]) > 0.0f ? 0x80 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[19]) > 0.0f ? 0x40 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[20]) > 0.0f ? 0x20 : 0x00;
    //  21 : pilot
    _q->signal_int[5] |= crealf(_q->X[22]) > 0.0f ? 0x10 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[23]) > 0.0f ? 0x08 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[24]) > 0.0f ? 0x04 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[25]) > 0.0f ? 0x02 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[26]) > 0.0f ? 0x01 : 0x00;

    // decode SIGNAL field
    wlanframesync_decode_signal(_q);

    // validate proper decoding
    if (!_q->signal_valid) {
        // reset synchronizer and return
        wlanframesync_reset(_q);
        return;
    }

    // set state
    _q->state = WLANFRAMESYNC_STATE_RXDATA;
}
Example #14
0
int main(int argc, char*argv[])
{
    // options
    int          ftype       = LIQUID_FIRFILT_ARKAISER;
    int          ms          = LIQUID_MODEM_QPSK;
    unsigned int k           = 2;       // samples per symbol
    unsigned int m           = 7;       // filter delay (symbols)
    float        beta        = 0.20f;   // filter excess bandwidth factor
    unsigned int num_symbols = 4000;    // number of data symbols
    unsigned int hc_len      =   4;     // channel filter length
    float        noise_floor = -60.0f;  // noise floor [dB]
    float        SNRdB       = 30.0f;   // signal-to-noise ratio [dB]
    float        bandwidth   =  0.02f;  // loop filter bandwidth
    float        tau         = -0.2f;   // fractional symbol offset
    float        rate        = 1.001f;  // sample rate offset
    float        dphi        =  0.01f;  // carrier frequency offset [radians/sample]
    float        phi         =  2.1f;   // carrier phase offset [radians]

    unsigned int nfft        =   2400;  // spectral periodogram FFT size
    unsigned int num_samples = 200000;  // number of samples

    int dopt;
    while ((dopt = getopt(argc,argv,"hk:m:b:s:w:n:t:r:")) != EOF) {
        switch (dopt) {
        case 'h':   usage();                        return 0;
        case 'k':   k           = atoi(optarg);     break;
        case 'm':   m           = atoi(optarg);     break;
        case 'b':   beta        = atof(optarg);     break;
        case 's':   SNRdB       = atof(optarg);     break;
        case 'w':   bandwidth   = atof(optarg);     break;
        case 'n':   num_symbols = atoi(optarg);     break;
        case 't':   tau         = atof(optarg);     break;
        case 'r':   rate        = atof(optarg);     break;
        default:
            exit(1);
        }
    }

    // validate input
    if (k < 2) {
        fprintf(stderr,"error: k (samples/symbol) must be greater than 1\n");
        exit(1);
    } else if (m < 1) {
        fprintf(stderr,"error: m (filter delay) must be greater than 0\n");
        exit(1);
    } else if (beta <= 0.0f || beta > 1.0f) {
        fprintf(stderr,"error: beta (excess bandwidth factor) must be in (0,1]\n");
        exit(1);
    } else if (bandwidth <= 0.0f) {
        fprintf(stderr,"error: timing PLL bandwidth must be greater than 0\n");
        exit(1);
    } else if (num_symbols == 0) {
        fprintf(stderr,"error: number of symbols must be greater than 0\n");
        exit(1);
    } else if (tau < -1.0f || tau > 1.0f) {
        fprintf(stderr,"error: timing phase offset must be in [-1,1]\n");
        exit(1);
    } else if (rate > 1.02f || rate < 0.98f) {
        fprintf(stderr,"error: timing rate offset must be in [1.02,0.98]\n");
        exit(1);
    }

    unsigned int i;

    // buffers
    unsigned int    buf_len = 400;      // buffer size
    float complex   x   [buf_len];      // original signal
    float complex   y   [buf_len*2];    // channel output (larger to accommodate resampler)
    float complex   syms[buf_len];      // recovered symbols
    // window for saving last few symbols
    windowcf sym_buf = windowcf_create(buf_len);

    // create stream generator
    symstreamcf gen = symstreamcf_create_linear(ftype,k,m,beta,ms);

    // create channel emulator and add impairments
    channel_cccf channel = channel_cccf_create();
    channel_cccf_add_awgn          (channel, noise_floor, SNRdB);
    channel_cccf_add_carrier_offset(channel, dphi, phi);
    channel_cccf_add_multipath     (channel, NULL, hc_len);
    channel_cccf_add_resamp        (channel, 0.0f, rate);

    // create symbol tracking synchronizer
    symtrack_cccf symtrack = symtrack_cccf_create(ftype,k,m,beta,ms);
    symtrack_cccf_set_bandwidth(symtrack,0.05f);

    // create spectral periodogram for estimating spectrum
    spgramcf periodogram = spgramcf_create_default(nfft);

    unsigned int total_samples = 0;
    unsigned int ny;
    unsigned int total_symbols = 0;
    while (total_samples < num_samples)
    {
        // write samples to buffer
        symstreamcf_write_samples(gen, x, buf_len);

        // apply channel
        channel_cccf_execute(channel, x, buf_len, y, &ny);

        // push resulting sample through periodogram
        spgramcf_write(periodogram, y, ny);

        // run resulting stream through synchronizer
        unsigned int num_symbols_sync;
        symtrack_cccf_execute_block(symtrack, y, ny, syms, &num_symbols_sync);
        total_symbols += num_symbols_sync;

        // write resulting symbols to window buffer for plotting
        windowcf_write(sym_buf, syms, num_symbols_sync);

        // accumulated samples
        total_samples += buf_len;
    }
    printf("total samples: %u\n", total_samples);
    printf("total symbols: %u\n", total_symbols);

    // write accumulated power spectral density estimate
    float psd[nfft];
    spgramcf_get_psd(periodogram, psd);

    //
    // export output file
    //

    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");

    // read buffer and write last symbols to file
    float complex * rc;
    windowcf_read(sym_buf, &rc);
    fprintf(fid,"syms = zeros(1,%u);\n", buf_len);
    for (i=0; i<buf_len; i++)
        fprintf(fid,"syms(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(rc[i]), cimagf(rc[i]));

    // power spectral density estimate
    fprintf(fid,"nfft = %u;\n", nfft);
    fprintf(fid,"f=[0:(nfft-1)]/nfft - 0.5;\n");
    fprintf(fid,"psd = zeros(1,nfft);\n");
    for (i=0; i<nfft; i++)
        fprintf(fid,"psd(%3u) = %12.8f;\n", i+1, psd[i]);

    fprintf(fid,"figure('Color','white','position',[500 500 1400 400]);\n");
    fprintf(fid,"subplot(1,3,1);\n");
    fprintf(fid,"plot(real(syms),imag(syms),'x','MarkerSize',4);\n");
    fprintf(fid,"  axis square;\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  axis([-1 1 -1 1]*1.6);\n");
    fprintf(fid,"  xlabel('In-phase');\n");
    fprintf(fid,"  ylabel('Quadrature');\n");
    fprintf(fid,"  title('Last %u symbols');\n", buf_len);
    fprintf(fid,"subplot(1,3,2:3);\n");
    fprintf(fid,"  plot(f, psd, 'LineWidth',1.5,'Color',[0 0.5 0.2]);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  pmin = 10*floor(0.1*min(psd - 5));\n");
    fprintf(fid,"  pmax = 10*ceil (0.1*max(psd + 5));\n");
    fprintf(fid,"  axis([-0.5 0.5 pmin pmax]);\n");
    fprintf(fid,"  xlabel('Normalized Frequency [f/F_s]');\n");
    fprintf(fid,"  ylabel('Power Spectral Density [dB]');\n");

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

    // destroy objects
    symstreamcf_destroy  (gen);
    spgramcf_destroy     (periodogram);
    channel_cccf_destroy (channel);
    symtrack_cccf_destroy(symtrack);
    windowcf_destroy     (sym_buf);

    // clean it up
    printf("done.\n");
    return 0;
}
void ofdmoqamframe64sync_debug_print(ofdmoqamframe64sync _q)
{
    FILE * fid = fopen(DEBUG_OFDMOQAMFRAME64SYNC_FILENAME,"w");
    if (!fid) {
        printf("error: ofdmoqamframe64_debug_print(), could not open file for writing\n");
        return;
    }
    fprintf(fid,"%% %s : auto-generated file\n", DEBUG_OFDMOQAMFRAME64SYNC_FILENAME);
    fprintf(fid,"close all;\n");
    fprintf(fid,"clear all;\n");
    fprintf(fid,"n = %u;\n", DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN);
    unsigned int i;
    float complex * rc;
    float * r;

    // gain vectors
    fprintf(fid,"g = %12.4e;\n", _q->g);
    for (i=0; i<_q->num_subcarriers; i++) {
        fprintf(fid,"G(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->G[i]), cimagf(_q->G[i]));
        //fprintf(fid,"G0(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->G0[i]), cimagf(_q->G0[i]));
        //fprintf(fid,"G1(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->G1[i]), cimagf(_q->G1[i]));
    }
    for (i=0; i<4; i++) {
        fprintf(fid,"phi(%3u) = %12.8f;\n", i+1, _q->y_phase[i]);
    }
    fprintf(fid,"figure;\n");
    fprintf(fid,"f = -32:31;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"    plot(f,fftshift(abs(G)));\n");
    fprintf(fid,"    xlabel('subcarrier index');\n");
    fprintf(fid,"    ylabel('|G|');\n");
    fprintf(fid,"    grid on;\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"    plot(f,fftshift(arg(G)));\n");
    fprintf(fid,"    xlabel('subcarrier index');\n");
    fprintf(fid,"    ylabel('arg\\{G\\}');\n");
    fprintf(fid,"    grid on;\n");

    // CFO estimate
    fprintf(fid,"nu_hat = %12.4e;\n", _q->nu_hat);

    // short, long, training sequences
    for (i=0; i<_q->num_subcarriers; i++) {
        fprintf(fid,"S0(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->S0[i]), cimagf(_q->S0[i]));
        fprintf(fid,"S1(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->S1[i]), cimagf(_q->S1[i]));
        fprintf(fid,"S2(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->S2[i]), cimagf(_q->S2[i]));
    }

    fprintf(fid,"x = zeros(1,n);\n");
    windowcf_read(_q->debug_x, &rc);
    for (i=0; i<DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN; i++)
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(0:(n-1),real(x),0:(n-1),imag(x));\n");
    fprintf(fid,"xlabel('sample index');\n");
    fprintf(fid,"ylabel('received signal, x');\n");

    fprintf(fid,"rxx = zeros(1,n);\n");
    windowcf_read(_q->debug_rxx, &rc);
    for (i=0; i<DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN; i++)
        fprintf(fid,"rxx(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(0:(n-1),abs(rxx),'-k','LineWidth',2);\n");
    fprintf(fid,"xlabel('sample index');\n");
    fprintf(fid,"ylabel('|r_{xx}|');\n");

    fprintf(fid,"rxy = zeros(1,n);\n");
    windowcf_read(_q->debug_rxy, &rc);
    for (i=0; i<DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN; i++)
        fprintf(fid,"rxy(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(0:(n-1),abs(rxy));\n");
    fprintf(fid,"xlabel('sample index');\n");
    fprintf(fid,"ylabel('|r_{xy}|');\n");
    // decoded long sequences
    fprintf(fid,"S1  = zeros(1,64);\n");
    fprintf(fid,"S1a = zeros(1,64);\n");
    fprintf(fid,"S1b = zeros(1,64);\n");
    fprintf(fid,"Y0  = zeros(1,64);\n");
    fprintf(fid,"Y1  = zeros(1,64);\n");
    for (i=0; i<64; i++) {
        fprintf(fid,"S1(%4u)  = %12.4e + j*%12.4e;\n", i+1, crealf(_q->S1[i]),  cimagf(_q->S1[i]));
        fprintf(fid,"S1a(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->S1a[i]), cimagf(_q->S1a[i]));
        fprintf(fid,"S1b(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->S1b[i]), cimagf(_q->S1b[i]));
        fprintf(fid,"Y0(%4u)  = %12.4e + j*%12.4e;\n", i+1, crealf(_q->Y0[i]),  cimagf(_q->Y0[i]));
        fprintf(fid,"Y1(%4u)  = %12.4e + j*%12.4e;\n", i+1, crealf(_q->Y1[i]),  cimagf(_q->Y1[i]));
    }
    fprintf(fid,"zeta = 64/sqrt(52/2);\n");
    fprintf(fid,"S1  = S1 / zeta;\n");
    fprintf(fid,"S1a = S1a / zeta;\n");
    fprintf(fid,"S1b = S1b / zeta;\n");
    fprintf(fid,"Y0  = Y0  / zeta;\n");
    fprintf(fid,"Y1  = Y1  / zeta;\n");
    fprintf(fid,"t0 = 1:2:64;\n");
    fprintf(fid,"t1 = 2:2:64;\n");
    fprintf(fid,"S = zeros(1,64);\n");
    fprintf(fid,"S(t0) = real(S1a(t0)) + j*imag(S1b(t0));\n");
    fprintf(fid,"S(t1) = real(S1b(t1)) + j*imag(S1a(t1));\n");
    fprintf(fid,"Y = zeros(1,64);\n");
    fprintf(fid,"Y(t0) = real(Y0(t0)) + j*imag(Y1(t0));\n");
    fprintf(fid,"Y(t1) = real(Y1(t1)) + j*imag(Y0(t1));\n");

    fprintf(fid,"figure;\n");
    //fprintf(fid,"f = [(0:63)]/64 - 0.5;\n");
    //fprintf(fid,"plot(S1,'x',S1a,'x',S1b,'x');\n");
    fprintf(fid,"plot(S1,'x',S,'x',S1a,'x',S1b,'x');\n");
    fprintf(fid,"legend('S1','S','S1a','S1b',0);\n");
    fprintf(fid,"xlabel('I');\n");
    fprintf(fid,"ylabel('Q');\n");
    fprintf(fid,"axis square;\n");
    fprintf(fid,"axis([-1 1 -1 1]*1.3);\n");
    fprintf(fid,"title('PLCP long sequences');\n");

  
    // pilot phase
    fprintf(fid,"pilotphase = zeros(1,n);\n");
    windowf_read(_q->debug_pilotphase, &r);
    for (i=0; i<DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN; i++)
        fprintf(fid,"pilotphase(%4u) = %12.4e;\n", i+1, r[i]);

    fprintf(fid,"pilotphase_hat = zeros(1,n);\n");
    windowf_read(_q->debug_pilotphase_hat, &r);
    for (i=0; i<DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN; i++)
        fprintf(fid,"pilotphase_hat(%4u) = %12.4e;\n", i+1, r[i]);
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(0:(127),pilotphase([n-128+1]:n),'-k',0:(127),pilotphase_hat([n-128+1]:n),'-k','LineWidth',2);\n");
    fprintf(fid,"xlabel('sample index');\n");
    fprintf(fid,"ylabel('pilot phase');\n");

    // rssi (received signal strength indication)
    fprintf(fid,"rssi = zeros(1,n);\n");
    windowf_read(_q->debug_rssi, &r);
    for (i=0; i<DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN; i++)
        fprintf(fid,"rssi(%4u) = %12.4e;\n", i+1, r[i]);
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(0:(n-1),rssi,'-k','LineWidth',2);\n");
    fprintf(fid,"xlabel('sample index');\n");
    fprintf(fid,"ylabel('RSSI');\n");

    // frame symbols
    fprintf(fid,"framesyms = zeros(1,n);\n");
    windowcf_read(_q->debug_framesyms, &rc);
    for (i=0; i<DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN; i++)
        fprintf(fid,"framesyms(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(real(framesyms),imag(framesyms),'x','MarkerSize',1);\n");
    fprintf(fid,"axis square;\n");
    fprintf(fid,"axis([-1.5 1.5 -1.5 1.5]);\n");
    fprintf(fid,"xlabel('in-phase');\n");
    fprintf(fid,"ylabel('quadrature phase');\n");
    fprintf(fid,"title('Frame Symbols');\n");

    fclose(fid);
    printf("ofdmoqamframe64sync/debug: results written to %s\n", DEBUG_OFDMOQAMFRAME64SYNC_FILENAME);
}
Example #16
0
// print debugging information
void flexframesync_debug_print(flexframesync _q,
                               const char *  _filename)
{
#if DEBUG_FLEXFRAMESYNC
    if (!_q->debug_objects_created) {
        fprintf(stderr,"error: flexframesync_debug_print(), debugging objects don't exist; enable debugging first\n");
        return;
    }
    unsigned int i;
    float complex * rc;
    FILE* fid = fopen(_filename,"w");
    fprintf(fid,"%% %s: auto-generated file", _filename);
    fprintf(fid,"\n\n");
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n\n");
    fprintf(fid,"n = %u;\n", DEBUG_BUFFER_LEN);
    
    // main figure
    fprintf(fid,"figure('Color','white','position',[100 100 800 600]);\n");

    // write x
    fprintf(fid,"x = zeros(1,n);\n");
    windowcf_read(_q->debug_x, &rc);
    for (i=0; i<DEBUG_BUFFER_LEN; i++)
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));
    fprintf(fid,"\n\n");
    fprintf(fid,"subplot(3,2,1:2);\n");
    fprintf(fid,"plot(1:length(x),real(x), 1:length(x),imag(x));\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"xlabel('sample index');\n");
    fprintf(fid,"ylabel('received signal, x');\n");

    // write p/n sequence
    fprintf(fid,"preamble_pn = zeros(1,64);\n");
    rc = _q->preamble_pn;
    for (i=0; i<64; i++)
        fprintf(fid,"preamble_pn(%4u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));

    // write p/n symbols
    fprintf(fid,"preamble_rx = zeros(1,64);\n");
    rc = _q->preamble_rx;
    for (i=0; i<64; i++)
        fprintf(fid,"preamble_rx(%4u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));

    // write recovered header symbols (after qpilotsync)
    fprintf(fid,"header_mod = zeros(1,%u);\n", _q->header_mod_len);
    rc = _q->header_mod;
    for (i=0; i<_q->header_mod_len; i++)
        fprintf(fid,"header_mod(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));

    // write raw payload symbols
    fprintf(fid,"payload_sym = zeros(1,%u);\n", _q->payload_sym_len);
    rc = _q->payload_sym;
    for (i=0; i<_q->payload_sym_len; i++)
        fprintf(fid,"payload_sym(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));

    fprintf(fid,"subplot(3,2,[3 5]);\n");
    fprintf(fid,"plot(real(header_mod),imag(header_mod),'o');\n");
    fprintf(fid,"xlabel('in-phase');\n");
    fprintf(fid,"ylabel('quadrature phase');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"axis([-1 1 -1 1]*1.5);\n");
    fprintf(fid,"axis square;\n");
    fprintf(fid,"title('Received Header Symbols');\n");

    fprintf(fid,"subplot(3,2,[4 6]);\n");
    fprintf(fid,"plot(real(payload_sym),imag(payload_sym),'+');\n");
    fprintf(fid,"xlabel('in-phase');\n");
    fprintf(fid,"ylabel('quadrature phase');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"axis([-1 1 -1 1]*1.5);\n");
    fprintf(fid,"axis square;\n");
    fprintf(fid,"title('Received Payload Symbols');\n");

    fprintf(fid,"\n\n");
    fclose(fid);

    printf("flexframesync/debug: results written to %s\n", _filename);
#else
    fprintf(stderr,"flexframesync_debug_print(): compile-time debugging disabled\n");
#endif
}
int main() {
    // options
    unsigned int num_channels=64;   // must be even number
    unsigned int num_symbols=16;    // number of symbols
    unsigned int m=3;               // filter delay (symbols)
    float beta = 0.9f;              // filter excess bandwidth factor
    float phi = 0.0f;               // carrier phase offset;
    float dphi = 0.04f;            // carrier frequency offset

    // number of frames (compensate for filter delay)
    unsigned int num_frames = num_symbols + 2*m;
    unsigned int num_samples = num_channels * num_frames;
    unsigned int i;
    unsigned int j;

    // create filter prototype
    unsigned int h_len = 2*num_channels*m + 1;
    float h[h_len];
    float complex hc[h_len];
    float complex gc[h_len];
    liquid_firdes_rkaiser(num_channels, m, beta, 0.0f, h);
    unsigned int g_len = 2*num_channels*m;
    for (i=0; i<g_len; i++) {
        hc[i] = h[i];
        gc[i] = h[g_len-i-1] * cexpf(_Complex_I*dphi*i);
    }

    // data arrays
    float complex s[num_channels];                  // input symbols
    float complex y[num_samples];                   // time-domain samples
    float complex Y0[num_frames][num_channels];     // channelized output
    float complex Y1[num_frames][num_channels];     // channelized output

    // create ofdm/oqam generator object and generate data
    ofdmoqam qs = ofdmoqam_create(num_channels, m, beta, 0.0f, LIQUID_SYNTHESIZER, 0);
    for (i=0; i<num_frames; i++) {
        for (j=0; j<num_channels; j++) {
            if (i<num_symbols) {
#if 0
                // QPSK on all subcarriers
                s[j] = (rand() % 2 ? 1.0f : -1.0f) +
                       (rand() % 2 ? 1.0f : -1.0f) * _Complex_I;
                s[j] *= 1.0f / sqrtf(2.0f);
#else
                // BPSK on even subcarriers
                s[j] =  rand() % 2 ? 1.0f : -1.0f;
                s[j] *= (j%2)==0 ? 1.0f : 0.0f;
#endif
            } else {
                s[j] = 0.0f;
            }
        }

        // run synthesizer
        ofdmoqam_execute(qs, s, &y[i*num_channels]);
    }
    ofdmoqam_destroy(qs);

    // channel
    for (i=0; i<num_samples; i++)
        y[i] *= cexpf(_Complex_I*(phi + dphi*i));


    //
    // analysis filterbank (receiver)
    //

    // create filterbank manually
    dotprod_cccf dp[num_channels];  // vector dot products
    windowcf w[num_channels];       // window buffers

#if DEBUG
    // print coefficients
    printf("h_prototype:\n");
    for (i=0; i<h_len; i++)
        printf("  h[%3u] = %12.8f\n", i, h[i]);
#endif

    // create objects
    unsigned int gc_sub_len = 2*m;
    float complex gc_sub[gc_sub_len];
    for (i=0; i<num_channels; i++) {
        // sub-sample prototype filter, loading coefficients in
        // reverse order
#if 0
        for (j=0; j<gc_sub_len; j++)
            gc_sub[j] = h[j*num_channels+i];
#else
        for (j=0; j<gc_sub_len; j++)
            gc_sub[gc_sub_len-j-1] = gc[j*num_channels+i];
#endif

        // create window buffer and dotprod objects
        dp[i] = dotprod_cccf_create(gc_sub, gc_sub_len);
        w[i]  = windowcf_create(gc_sub_len);

#if DEBUG
        printf("gc_sub[%u] : \n", i);
        for (j=0; j<gc_sub_len; j++)
            printf("  g[%3u] = %12.8f + %12.8f\n", j, crealf(gc_sub[j]), cimagf(gc_sub[j]));
#endif
    }

    // generate DFT object
    float complex x[num_channels];  // time-domain buffer
    float complex X[num_channels];  // freq-domain buffer
#if 0
    fftplan fft = fft_create_plan(num_channels, X, x, FFT_REVERSE, 0);
#else
    fftplan fft = fft_create_plan(num_channels, X, x, FFT_FORWARD, 0);
#endif

    // 
    // run analysis filter bank
    //
#if 0
    unsigned int filter_index = 0;
#else
    unsigned int filter_index = num_channels-1;
#endif
    float complex y_hat;    // input sample
    float complex * r;      // read pointer
    for (i=0; i<num_frames; i++) {

        // load buffers
        for (j=0; j<num_channels; j++) {
            // grab sample
            y_hat = y[i*num_channels + j];

            // push sample into buffer at filter index
            windowcf_push(w[filter_index], y_hat);

            // decrement filter index
            filter_index = (filter_index + num_channels - 1) % num_channels;
            //filter_index = (filter_index + 1) % num_channels;
        }

        // execute filter outputs, reversing order of output (not
        // sure why this is necessary)
        for (j=0; j<num_channels; j++) {
            windowcf_read(w[j], &r);
            dotprod_cccf_execute(dp[j], r, &X[num_channels-j-1]);
        }

#if 1
        // compensate for carrier frequency offset (before transform)
        for (j=0; j<num_channels; j++) {
            X[j] *= cexpf(-_Complex_I*(dphi*i*num_channels));
        }
#endif

        // execute DFT, store result in buffer 'x'
        fft_execute(fft);

#if 0
        // compensate for carrier frequency offset (after transform)
        for (j=0; j<num_channels; j++) {
            x[j] *= cexpf(-_Complex_I*(dphi*i*num_channels));
        }
#endif

        // move to output array
        for (j=0; j<num_channels; j++)
            Y0[i][j] = x[j];
    }


    // destroy objects
    for (i=0; i<num_channels; i++) {
        dotprod_cccf_destroy(dp[i]);
        windowcf_destroy(w[i]);
    }
    fft_destroy_plan(fft);

#if 0
    // print filterbank channelizer
    printf("\n");
    printf("filterbank channelizer:\n");
    for (i=0; i<num_symbols; i++) {
        printf("%3u: ", i);
        for (j=0; j<num_channels; j++) {
            printf("  %8.5f+j%8.5f, ", crealf(Y0[i][j]), cimagf(Y0[i][j]));
        }
        printf("\n");
    }
#endif

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

    fprintf(fid,"y = zeros(1,%u);\n",  num_samples);
    fprintf(fid,"Y0 = zeros(%u,%u);\n", num_frames, num_channels);
    fprintf(fid,"Y1 = zeros(%u,%u);\n", num_frames, num_channels);
    
    for (i=0; i<num_frames; i++) {
        for (j=0; j<num_channels; j++) {
            fprintf(fid,"Y0(%4u,%4u) = %12.4e + j*%12.4e;\n", i+1, j+1, crealf(Y0[i][j]), cimagf(Y0[i][j]));
            fprintf(fid,"Y1(%4u,%4u) = %12.4e + j*%12.4e;\n", i+1, j+1, crealf(Y1[i][j]), cimagf(Y1[i][j]));
        }
    }

    // plot BPSK results
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(Y0(:,1:2:end),'x');\n");
    fprintf(fid,"axis([-1 1 -1 1]*1.2*sqrt(num_channels));\n");
    fprintf(fid,"axis square;\n");
    fprintf(fid,"grid on;\n");

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

    printf("done.\n");
    return 0;
}
Example #18
0
void wlanframesync_debug_print(wlanframesync _q,
                               const char * _filename)
{
#if DEBUG_WLANFRAMESYNC
    if (_q->agc_rx          == NULL ||
        _q->debug_x         == NULL ||
        _q->debug_rssi      == NULL ||
        _q->debug_framesyms == NULL)
    {
        fprintf(stderr,"error: wlanframe_debug_print(), debugging objects don't exist; enable debugging first\n");
        return;
    }

    FILE * fid = fopen(_filename,"w");
    if (!fid) {
        fprintf(stderr,"error: wlanframe_debug_print(), could not open '%s' for writing\n", _filename);
        return;
    }
    fprintf(fid,"%% %s : auto-generated file\n", _filename);

    fprintf(fid,"close all;\n");
    fprintf(fid,"clear all;\n");
    fprintf(fid,"n = %u;\n", DEBUG_WLANFRAMESYNC_BUFFER_LEN);
    unsigned int i;
    float complex * rc;
    float * r;

    fprintf(fid,"x = zeros(1,n);\n");
    windowcf_read(_q->debug_x, &rc);
    for (i=0; i<DEBUG_WLANFRAMESYNC_BUFFER_LEN; i++)
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(0:(n-1),real(x),0:(n-1),imag(x));\n");
    fprintf(fid,"xlabel('sample index');\n");
    fprintf(fid,"ylabel('received signal, x');\n");

    // write agc_rssi
    fprintf(fid,"\n\n");
    fprintf(fid,"agc_rssi = zeros(1,%u);\n", DEBUG_WLANFRAMESYNC_BUFFER_LEN);
    windowf_read(_q->debug_rssi, &r);
    for (i=0; i<DEBUG_WLANFRAMESYNC_BUFFER_LEN; i++)
        fprintf(fid,"agc_rssi(%4u) = %12.4e;\n", i+1, r[i]);
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(agc_rssi)\n");
    fprintf(fid,"ylabel('RSSI [dB]');\n");
    
    // write frame symbols
    fprintf(fid,"framesyms = zeros(1,n);\n");
    windowcf_read(_q->debug_framesyms, &rc);
    for (i=0; i<DEBUG_WLANFRAMESYNC_BUFFER_LEN; i++)
        fprintf(fid,"framesyms(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(real(framesyms),imag(framesyms),'x','MarkerSize',2);\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");

    // write gain arrays
    fprintf(fid,"\n\n");
    fprintf(fid,"G0a = zeros(1,64);\n");
    fprintf(fid,"G0b = zeros(1,64);\n");
    fprintf(fid,"G1a = zeros(1,64);\n");
    fprintf(fid,"G1b = zeros(1,64);\n");
    fprintf(fid,"G   = zeros(1,64);\n");
    for (i=0; i<64; i++) {
        unsigned int k = (i + 32) % 64;
        fprintf(fid,"G0a(%3u) = %12.8f + j*%12.8f;\n", k+1, crealf(_q->G0a[i]), cimagf(_q->G0a[i]));
        fprintf(fid,"G0b(%3u) = %12.8f + j*%12.8f;\n", k+1, crealf(_q->G0b[i]), cimagf(_q->G0b[i]));
        fprintf(fid,"G1a(%3u) = %12.8f + j*%12.8f;\n", k+1, crealf(_q->G1a[i]), cimagf(_q->G1a[i]));
        fprintf(fid,"G1b(%3u) = %12.8f + j*%12.8f;\n", k+1, crealf(_q->G1b[i]), cimagf(_q->G1b[i]));
        fprintf(fid,"G(%3u)   = %12.8f + j*%12.8f;\n", k+1, crealf(_q->G[i]),   cimagf(_q->G[i]));
    }
    fprintf(fid,"%% apply timing offset (backoff) phase shift\n");
    fprintf(fid,"f = -32:31;\n");
    fprintf(fid,"b = 2;\n");
    fprintf(fid,"G0a = G0a.*exp(j*b*2*pi*f/64);\n");
    fprintf(fid,"G0b = G0b.*exp(j*b*2*pi*f/64);\n");
    fprintf(fid,"G1a = G1a.*exp(j*b*2*pi*f/64);\n");
    fprintf(fid,"G1b = G1b.*exp(j*b*2*pi*f/64);\n");
    fprintf(fid,"G   = G.*exp(j*b*2*pi*f/64);\n");

    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"  plot(f,abs(G1a),'x', f,abs(G1b),'x', f,abs(G),'-k','LineWidth',2);\n");
    fprintf(fid,"  ylabel('G (mag)');\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"  plot(f,arg(G1a),'x', f,arg(G1b),'x', f,arg(G),'-k','LineWidth',2);\n");
    fprintf(fid,"  ylabel('G (phase)');\n");

    fclose(fid);
    printf("wlanframesync/debug: results written to '%s'\n", _filename);
#else
    fprintf(stderr,"wlanframesync_debug_print(): compile-time debugging disabled\n");
#endif
}
Example #19
0
void gmskframesync_debug_print(gmskframesync _q,
                               const char *  _filename)
{
#if DEBUG_GMSKFRAMESYNC
    if (!_q->debug_objects_created) {
        fprintf(stderr,"error: gmskframe_debug_print(), debugging objects don't exist; enable debugging first\n");
        return;
    }

    FILE* fid = fopen(_filename,"w");
    if (!fid) {
        fprintf(stderr, "error: gmskframesync_debug_print(), could not open '%s' for writing\n", _filename);
        return;
    }
    fprintf(fid,"%% %s: auto-generated file", _filename);
    fprintf(fid,"\n\n");
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n\n");

    fprintf(fid,"num_samples = %u;\n", DEBUG_GMSKFRAMESYNC_BUFFER_LEN);
    fprintf(fid,"t = 0:(num_samples-1);\n");
    unsigned int i;
    float complex * rc;

    // write x
    fprintf(fid,"x = zeros(1,num_samples);\n");
    windowcf_read(_q->debug_x, &rc);
    for (i=0; i<DEBUG_GMSKFRAMESYNC_BUFFER_LEN; i++)
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));
    fprintf(fid,"\n\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(1:length(x),real(x), 1:length(x),imag(x));\n");
    fprintf(fid,"ylabel('received signal, x');\n");
    fprintf(fid,"\n\n");

    // write instantaneous frequency
    float * r;
    fprintf(fid,"fi = zeros(1,num_samples);\n");
    windowf_read(_q->debug_fi, &r);
    for (i=0; i<DEBUG_GMSKFRAMESYNC_BUFFER_LEN; i++)
        fprintf(fid,"fi(%4u) = %12.4e;\n", i+1, r[i]);
    fprintf(fid,"\n\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(1:length(fi),fi);\n");
    fprintf(fid,"ylabel('Inst. Freq.');\n");
    fprintf(fid,"\n\n");

    // write matched filter output
    fprintf(fid,"mf = zeros(1,num_samples);\n");
    windowf_read(_q->debug_mf, &r);
    for (i=0; i<DEBUG_GMSKFRAMESYNC_BUFFER_LEN; i++)
        fprintf(fid,"mf(%4u) = %12.4e;\n", i+1, r[i]);
    fprintf(fid,"\n\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(1:length(mf),mf);\n");
    fprintf(fid,"ylabel('MF output');\n");
    fprintf(fid,"\n\n");

#if 0
    // write framesyms
    fprintf(fid,"framesyms = zeros(1,num_samples);\n");
    windowf_read(_q->debug_framesyms, &r);
    for (i=0; i<DEBUG_GMSKFRAMESYNC_BUFFER_LEN; i++)
        fprintf(fid,"framesyms(%4u) = %12.4e;\n", i+1, r[i]);
    fprintf(fid,"\n\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(t,framesyms,'x')\n");
    fprintf(fid,"xlabel('time (symbol index)');\n");
    fprintf(fid,"ylabel('GMSK demodulator output');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"\n\n");
#endif

    fclose(fid);

    printf("gmskframesync/debug: results written to '%s'\n", _filename);
#else
    fprintf(stderr,"gmskframesync_debug_print(): compile-time debugging disabled\n");
#endif

}
Example #20
0
// compute ISI for entire system
//  _gt     :   transmit filter [size: _gt_len x 1]
//  _hc     :   channel filter  [size: _hc_len x 1]
//  _gr     :   receive filter  [size: _gr_len x 1]
float eqlms_cccf_isi(unsigned int    _k,
                     float complex * _gt,
                     unsigned int    _gt_len,
                     float complex * _hc,
                     unsigned int    _hc_len,
                     float complex * _gr,
                     unsigned int    _gr_len)
{
    // generate composite by convolving all filters together
    unsigned int i;
   
#if 0
    printf("\n");
    for (i=0; i<_gt_len; i++)
        printf("  gt(%3u) = %16.12f + j*%16.12f;\n", i+1, crealf(_gt[i]), cimagf(_gt[i]));

    printf("\n");
    for (i=0; i<_hc_len; i++)
        printf("  hc(%3u) = %16.12f + j*%16.12f;\n", i+1, crealf(_hc[i]), cimagf(_hc[i]));

    printf("\n");
    for (i=0; i<_gr_len; i++)
        printf("  gr(%3u) = %16.12f + j*%16.12f;\n", i+1, crealf(_gr[i]), cimagf(_gr[i]));
    
    printf("\n");
#endif

    windowcf w;
    float complex * rc;

    // start by convolving transmit and channel filters
    unsigned int gthc_len = _gt_len + _hc_len - 1;
    float complex gthc[gthc_len];
    w = windowcf_create(_gt_len);
    for (i=0; i<gthc_len; i++) {
        if (i < _hc_len) windowcf_push(w, conjf(_hc[_hc_len-i-1]));
        else             windowcf_push(w, 0.0f);

        windowcf_read(w, &rc);
        dotprod_cccf_run(_gt, rc, _gt_len, &gthc[i]);
    }
    windowcf_destroy(w);

#if 0
    printf("composite filter:\n");
    for (i=0; i<gthc_len; i++)
        printf("  gthc(%3u) = %16.12f + j*%16.12f;\n", i+1, crealf(gthc[i]), cimagf(gthc[i]));
#endif
    
    // convolve result with equalizer
    unsigned int h_len = gthc_len + _gr_len - 1;
    float complex h[h_len];
    w = windowcf_create(gthc_len);
    for (i=0; i<h_len; i++) {
        if (i < _gr_len) windowcf_push(w, conjf(_gr[i]));
        else             windowcf_push(w, 0.0f);

        windowcf_read(w, &rc);
        dotprod_cccf_run(gthc, rc, gthc_len, &h[i]);
    }
    windowcf_destroy(w);

#if 0
    printf("composite filter:\n");
    for (i=0; i<h_len; i++)
        printf("  h(%3u) = %16.12f + j*%16.12f;\n", i+1, crealf(h[i]), cimagf(h[i]));
#endif

    // compute resulting ISI
    unsigned int n0 = (_gt_len + _gr_len + (_gt_len + _gr_len)%2)/2 - 1;
    float isi = 0.0f;
    unsigned int n=0;
    for (i=0; i<h_len; i++) {
        if (i == n0)
            continue;
        else if ( (i%_k)==0 ) {
            isi += crealf( h[i]*conjf(h[i]) );
            n++;
        }
    }
    isi /= crealf( h[n0]*conjf(h[n0]) );
    isi = sqrtf(isi / (float)n);

    return isi;
}
Example #21
0
void ofdmframesync_execute_S1(ofdmframesync _q)
{
    _q->timer--;

    if (_q->timer > 0)
        return;

    // increment number of symbols observed
    _q->num_symbols++;

    // run fft
    float complex * rc;
    windowcf_read(_q->input_buffer, &rc);

    // estimate S1 gain
    // TODO : add backoff in gain estimation
    ofdmframesync_estimate_gain_S1(_q, &rc[_q->cp_len], _q->G);

    // compute detector output
    float complex g_hat = 0.0f;
    unsigned int i;
    for (i=0; i<_q->M; i++) {
        //g_hat += _q->G[(i+1+_q->M)%_q->M]*conjf(_q->G[(i+_q->M)%_q->M]);
        g_hat += _q->G[(i+1)%_q->M]*conjf(_q->G[i]);
    }
    g_hat /= _q->M_S1; // normalize output
    g_hat *= _q->g0;

    // rotate by complex phasor relative to timing backoff
    g_hat *= liquid_cexpjf((float)(_q->backoff)*2.0f*M_PI/(float)(_q->M));

#if DEBUG_OFDMFRAMESYNC_PRINT
    printf("    g_hat   :   %12.4f <%12.8f>\n", cabsf(g_hat), cargf(g_hat));
#endif

    // check conditions for g_hat:
    //  1. magnitude should be large (near unity) when aligned
    //  2. phase should be very near zero (time aligned)
    if (cabsf(g_hat) > _q->plcp_sync_thresh && fabsf(cargf(g_hat)) < 0.1f*M_PI ) {
        //printf("    acquisition\n");
        _q->state = OFDMFRAMESYNC_STATE_RXSYMBOLS;
        // reset timer
        _q->timer = _q->M + _q->cp_len + _q->backoff;
        _q->num_symbols = 0;

        // normalize gain by subcarriers, apply timing backoff correction
        float g = (float)(_q->M) / sqrtf(_q->M_pilot + _q->M_data);
        for (i=0; i<_q->M; i++) {
            _q->G[i] *= g;          // gain due to relative subcarrier allocation
            _q->G[i] *= _q->B[i];   // timing backoff correction
        }

#if 0
        // TODO : choose number of taps more appropriately
        //unsigned int ntaps = _q->M / 4;
        unsigned int ntaps = (_q->M < 8) ? 2 : 8;
        // FIXME : this is by far the most computationally complex part of synchronization
        ofdmframesync_estimate_eqgain(_q, ntaps);
#else
        unsigned int poly_order = 4;
        if (poly_order >= _q->M_pilot + _q->M_data)
            poly_order = _q->M_pilot + _q->M_data - 1;
        ofdmframesync_estimate_eqgain_poly(_q, poly_order);
#endif

#if 1
        // compute composite gain
        unsigned int i;
        for (i=0; i<_q->M; i++)
            _q->R[i] = _q->B[i] / _q->G[i];
#endif

        return;
#if 0
        printf("exiting prematurely\n");
        ofdmframesync_destroy(_q);
        exit(1);
#endif
    }

    // check if we are stuck searching for the S1 symbol
    if (_q->num_symbols == 16) {
#if DEBUG_OFDMFRAMESYNC_PRINT
        printf("could not find S1 symbol. bailing...\n");
#endif
        ofdmframesync_reset(_q);
    }

    // 'reset' timer (wait another half symbol)
    _q->timer = _q->M2;
}
Example #22
0
// frame detection
void wlanframesync_execute_seekplcp(wlanframesync _q)
{
    _q->timer++;

    // TODO : only check every 100 - 150 (decimates/reduced complexity)
    if (_q->timer < 64)
        return;

    // reset timer
    _q->timer = 0;

    // read contents of input buffer
    float complex * rc;
    windowcf_read(_q->input_buffer, &rc);
    
    // estimate gain
    // TODO : use gain from result of FFT
    unsigned int i;
    float g = 0.0f;
    for (i=16; i<80; i+=4) {
        // compute |rc[i]|^2 efficiently
        g += crealf(rc[i  ])*crealf(rc[i  ]) + cimagf(rc[i  ])*cimagf(rc[i  ]);
        g += crealf(rc[i+1])*crealf(rc[i+1]) + cimagf(rc[i+1])*cimagf(rc[i+1]);
        g += crealf(rc[i+2])*crealf(rc[i+2]) + cimagf(rc[i+2])*cimagf(rc[i+2]);
        g += crealf(rc[i+3])*crealf(rc[i+3]) + cimagf(rc[i+3])*cimagf(rc[i+3]);
    }
    g = 64.0f / (g + 1e-12f);
    
    // save gain (permits dynamic invocation of get_rssi() method)
    _q->g0 = g;

    // estimate S0 gain
    wlanframesync_estimate_gain_S0(_q, &rc[16], _q->G0a);
    
    // compute S0 metrics
    float complex s_hat;
    wlanframesync_S0_metrics(_q, _q->G0a, &s_hat);
    s_hat *= g;

    float tau_hat  = cargf(s_hat) * (float)(16.0f) / (2*M_PI);
#if DEBUG_WLANFRAMESYNC_PRINT
    printf(" - gain=%12.3f, rssi=%8.2f dB, s_hat=%12.4f <%12.8f>, tau_hat=%8.3f\n",
            sqrt(g),
            -10*log10(g),
            cabsf(s_hat), cargf(s_hat),
            tau_hat);
#endif

    // 
    if (cabsf(s_hat) > WLANFRAMESYNC_S0A_ABS_THRESH) {

        int dt = (int)roundf(tau_hat);
        // set timer appropriately...
        _q->timer = (16 + dt) % 16;
        //_q->timer += 32; // add delay to help ensure good S0 estimate (multiple of 16)
        _q->state = WLANFRAMESYNC_STATE_RXSHORT0;

#if DEBUG_WLANFRAMESYNC_PRINT
        printf("********** frame detected! ************\n");
        printf("    s_hat   :   %12.8f <%12.8f>\n", cabsf(s_hat), cargf(s_hat));
        printf("  tau_hat   :   %12.8f\n", tau_hat);
        printf("    dt      :   %12d\n", dt);
        printf("    timer   :   %12u\n", _q->timer);
#endif
    }

}
Example #23
0
void ofdmframesync_debug_print(ofdmframesync _q,
                               const char * _filename)
{
#if DEBUG_OFDMFRAMESYNC
    if (!_q->debug_objects_created) {
        fprintf(stderr,"error: ofdmframe_debug_print(), debugging objects don't exist; enable debugging first\n");
        return;
    }

    FILE * fid = fopen(_filename,"w");
    if (!fid) {
        fprintf(stderr,"error: ofdmframe_debug_print(), could not open '%s' for writing\n", _filename);
        return;
    }
    fprintf(fid,"%% %s : auto-generated file\n", DEBUG_OFDMFRAMESYNC_FILENAME);
    fprintf(fid,"close all;\n");
    fprintf(fid,"clear all;\n");
    fprintf(fid,"n = %u;\n", DEBUG_OFDMFRAMESYNC_BUFFER_LEN);
    fprintf(fid,"M = %u;\n", _q->M);
    fprintf(fid,"M_null  = %u;\n", _q->M_null);
    fprintf(fid,"M_pilot = %u;\n", _q->M_pilot);
    fprintf(fid,"M_data  = %u;\n", _q->M_data);
    unsigned int i;
    float complex * rc;
    float * r;

    // save subcarrier allocation
    fprintf(fid,"p = zeros(1,M);\n");
    for (i=0; i<_q->M; i++)
        fprintf(fid,"p(%4u) = %d;\n", i+1, _q->p[i]);
    fprintf(fid,"i_null  = find(p==%d);\n", OFDMFRAME_SCTYPE_NULL);
    fprintf(fid,"i_pilot = find(p==%d);\n", OFDMFRAME_SCTYPE_PILOT);
    fprintf(fid,"i_data  = find(p==%d);\n", OFDMFRAME_SCTYPE_DATA);

    // short, long, training sequences
    for (i=0; i<_q->M; i++) {
        fprintf(fid,"S0(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->S0[i]), cimagf(_q->S0[i]));
        fprintf(fid,"S1(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->S1[i]), cimagf(_q->S1[i]));
    }

    fprintf(fid,"x = zeros(1,n);\n");
    windowcf_read(_q->debug_x, &rc);
    for (i=0; i<DEBUG_OFDMFRAMESYNC_BUFFER_LEN; i++)
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(0:(n-1),real(x),0:(n-1),imag(x));\n");
    fprintf(fid,"xlabel('sample index');\n");
    fprintf(fid,"ylabel('received signal, x');\n");


    fprintf(fid,"s1 = [];\n");
    for (i=0; i<_q->M; i++)
        fprintf(fid,"s1(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->s1[i]), cimagf(_q->s1[i]));


    // write agc_rssi
    fprintf(fid,"\n\n");
    fprintf(fid,"agc_rssi = zeros(1,%u);\n", DEBUG_OFDMFRAMESYNC_BUFFER_LEN);
    windowf_read(_q->debug_rssi, &r);
    for (i=0; i<DEBUG_OFDMFRAMESYNC_BUFFER_LEN; i++)
        fprintf(fid,"agc_rssi(%4u) = %12.4e;\n", i+1, r[i]);
    fprintf(fid,"agc_rssi = filter([0.00362168 0.00724336 0.00362168],[1 -1.82269490 0.83718163],agc_rssi);\n");
    fprintf(fid,"agc_rssi = 10*log10( agc_rssi );\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(agc_rssi)\n");
    fprintf(fid,"ylabel('RSSI [dB]');\n");

    // write short, long symbols
    fprintf(fid,"\n\n");
    fprintf(fid,"S0 = zeros(1,M);\n");
    fprintf(fid,"S1 = zeros(1,M);\n");
    for (i=0; i<_q->M; i++) {
        fprintf(fid,"S0(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(_q->S0[i]), cimagf(_q->S0[i]));
        fprintf(fid,"S1(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(_q->S1[i]), cimagf(_q->S1[i]));
    }


    // write gain arrays
    fprintf(fid,"\n\n");
    fprintf(fid,"G0     = zeros(1,M);\n");
    fprintf(fid,"G1     = zeros(1,M);\n");
    fprintf(fid,"G_hat  = zeros(1,M);\n");
    fprintf(fid,"G      = zeros(1,M);\n");
    for (i=0; i<_q->M; i++) {
        fprintf(fid,"G0(%3u)    = %12.8f + j*%12.8f;\n", i+1, crealf(_q->G0[i]),   cimagf(_q->G0[i]));
        fprintf(fid,"G1(%3u)    = %12.8f + j*%12.8f;\n", i+1, crealf(_q->G1[i]),   cimagf(_q->G1[i]));
        fprintf(fid,"G_hat(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(_q->G_hat[i]),cimagf(_q->G_hat[i]));
        fprintf(fid,"G(%3u)     = %12.8f + j*%12.8f;\n", i+1, crealf(_q->G[i]),    cimagf(_q->G[i]));
    }
    fprintf(fid,"f = [0:(M-1)];\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"  plot(f, fftshift(abs(G_hat)),'sb',...\n");
    fprintf(fid,"       f, fftshift(abs(G)),'-k','LineWidth',2);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  xlabel('subcarrier index');\n");
    fprintf(fid,"  ylabel('gain estimate (mag)');\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"  plot(f, fftshift(arg(G_hat).*[abs(G0) > 1e-3]),'sb',...\n");
    fprintf(fid,"       f, fftshift(arg(G)),'-k','LineWidth',2);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  xlabel('subcarrier index');\n");
    fprintf(fid,"  ylabel('gain estimate (phase)');\n");

    // write pilot response
    fprintf(fid,"\n\n");
    fprintf(fid,"px = zeros(1,M_pilot);\n");
    fprintf(fid,"py = zeros(1,M_pilot);\n");
    for (i=0; i<_q->M_pilot; i++) {
        fprintf(fid,"px(%3u) = %12.8f;\n", i+1, _q->px[i]);
        fprintf(fid,"py(%3u) = %12.8f;\n", i+1, _q->py[i]);
    }
    fprintf(fid,"p_phase(1) = %12.8f;\n", _q->p_phase[0]);
    fprintf(fid,"p_phase(2) = %12.8f;\n", _q->p_phase[1]);

    // save pilot history
    fprintf(fid,"p0 = zeros(1,M);\n");
    windowf_read(_q->debug_pilot_0, &r);
    for (i=0; i<DEBUG_OFDMFRAMESYNC_BUFFER_LEN; i++)
        fprintf(fid,"p0(%4u) = %12.4e;\n", i+1, r[i]);

    fprintf(fid,"p1 = zeros(1,M);\n");
    windowf_read(_q->debug_pilot_1, &r);
    for (i=0; i<DEBUG_OFDMFRAMESYNC_BUFFER_LEN; i++)
        fprintf(fid,"p1(%4u) = %12.4e;\n", i+1, r[i]);

    fprintf(fid,"figure;\n");
    fprintf(fid,"fp = (-M/2):(M/2);\n");
    fprintf(fid,"subplot(3,1,1);\n");
    fprintf(fid,"  plot(px, py, 'sb',...\n");
    fprintf(fid,"       fp, polyval(p_phase, fp), '-k');\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  legend('pilots','polyfit',0);\n");
    fprintf(fid,"  xlabel('subcarrier');\n");
    fprintf(fid,"  ylabel('phase');\n");
    fprintf(fid,"subplot(3,1,2);\n");
    fprintf(fid,"  plot(1:length(p0), p0);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  ylabel('p0 (phase offset)');\n");
    fprintf(fid,"subplot(3,1,3);\n");
    fprintf(fid,"  plot(1:length(p1), p1);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  ylabel('p1 (phase slope)');\n");

    // write frame symbols
    fprintf(fid,"framesyms = zeros(1,n);\n");
    windowcf_read(_q->debug_framesyms, &rc);
    for (i=0; i<DEBUG_OFDMFRAMESYNC_BUFFER_LEN; i++)
        fprintf(fid,"framesyms(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(real(framesyms), imag(framesyms), 'x');\n");
    fprintf(fid,"xlabel('I');\n");
    fprintf(fid,"ylabel('Q');\n");
    fprintf(fid,"axis([-1 1 -1 1]*1.6);\n");
    fprintf(fid,"axis square;\n");
    fprintf(fid,"grid on;\n");

    fclose(fid);
    printf("ofdmframesync/debug: results written to '%s'\n", _filename);
#else
    fprintf(stderr,"ofdmframesync_debug_print(): compile-time debugging disabled\n");
#endif
}
Example #24
0
void wlanframesync_execute_rxlong1(wlanframesync _q)
{
    _q->timer++;
    if (_q->timer < 64)
        return;

    // run fft
    float complex * rc;
    windowcf_read(_q->input_buffer, &rc);

    // estimate S1 gain, adding backoff in gain estimation
    wlanframesync_estimate_gain_S1(_q, &rc[16-2], _q->G1b);

    // compute S1 metrics
    float complex s_hat;
    wlanframesync_S1_metrics(_q, _q->G1b, &s_hat);
    s_hat *= _q->g0;    // scale output by raw gain estimate

    // rotate by complex phasor relative to timing backoff
    //s_hat *= cexpf(_Complex_I * 2.0f * 2.0f * M_PI / 64.0f);
    s_hat *= cexpf(_Complex_I * 0.19635f);

    // save second 'long' symbol statistic
    _q->s1b_hat = s_hat;

    // rotate by complex phasor relative to timing backoff
    //s_hat *= liquid_cexpjf((float)(_q->backoff)*2.0f*M_PI/(float)(_q->M));

#if DEBUG_WLANFRAMESYNC_PRINT
    printf("    s_hat   :   %12.8f <%12.8f>\n", cabsf(s_hat), cargf(s_hat));
#endif

    // check conditions for s_hat
    float s_hat_abs = cabsf(s_hat);
    float s_hat_arg = cargf(s_hat);
    if (s_hat_arg >  M_PI) s_hat_arg -= 2.0f*M_PI;
    if (s_hat_arg < -M_PI) s_hat_arg += 2.0f*M_PI;
        
    // check conditions for s_hat:
    //  1. magnitude should be large (near unity) when aligned
    //  2. phase should be very near zero (time aligned)
    if (s_hat_abs        > WLANFRAMESYNC_S1B_ABS_THRESH &&
        fabsf(s_hat_arg) < WLANFRAMESYNC_S1B_ARG_THRESH)
    {
#if DEBUG_WLANFRAMESYNC_PRINT
        printf("    acquisition S1[b]\n");
#endif
        
        // refine CFO estimate with G1a, G1b and adjust NCO appropriately
        float nu_hat = wlanframesync_estimate_cfo_S1(_q->G1a, _q->G1b);
        nco_crcf_adjust_frequency(_q->nco_rx, nu_hat);
#if DEBUG_WLANFRAMESYNC_PRINT
        printf("   nu_hat[1]:   %12.8f\n", nu_hat);
#endif
        // TODO : de-rotate S1b by phase offset (help with equalizer)

        // estimate equalizer with G1a, G1b
        wlanframesync_estimate_eqgain_poly(_q);
        
        // set state
        _q->state = WLANFRAMESYNC_STATE_RXLONG1;

        // reset timer
        _q->timer = 0;
    }

    // set state
    _q->state = WLANFRAMESYNC_STATE_RXSIGNAL;

    // reset timer
    _q->timer = 0;

}
Example #25
0
// frame detection
void ofdmframesync_execute_seekplcp(ofdmframesync _q)
{
    _q->timer++;

    if (_q->timer < _q->M)
        return;

    // reset timer
    _q->timer = 0;

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

    // estimate gain
    unsigned int i;
    float g = 0.0f;
    for (i=_q->cp_len; i<_q->M + _q->cp_len; i++) {
        // compute |rc[i]|^2 efficiently
        g += crealf(rc[i])*crealf(rc[i]) + cimagf(rc[i])*cimagf(rc[i]);
    }
    g = (float)(_q->M) / g;

#if OFDMFRAMESYNC_ENABLE_SQUELCH
    // TODO : squelch here
    if ( -10*log10f( sqrtf(g) ) < _q->squelch_threshold &&
         _q->squelch_enabled)
    {
        printf("squelch\n");
        return;
    }
#endif

    // estimate S0 gain
    ofdmframesync_estimate_gain_S0(_q, &rc[_q->cp_len], _q->G0);

    float complex s_hat;
    ofdmframesync_S0_metrics(_q, _q->G0, &s_hat);
    s_hat *= g;

    float tau_hat  = cargf(s_hat) * (float)(_q->M2) / (2*M_PI);
#if DEBUG_OFDMFRAMESYNC_PRINT
    printf(" - gain=%12.3f, rssi=%12.8f, s_hat=%12.4f <%12.8f>, tau_hat=%8.3f\n",
            sqrt(g),
            -10*log10(g),
            cabsf(s_hat), cargf(s_hat),
            tau_hat);
#endif

    // save gain (permits dynamic invocation of get_rssi() method)
    _q->g0 = g;

    // 
    if (cabsf(s_hat) > _q->plcp_detect_thresh) {

        int dt = (int)roundf(tau_hat);
        // set timer appropriately...
        _q->timer = (_q->M + dt) % (_q->M2);
        _q->timer += _q->M; // add delay to help ensure good S0 estimate
        _q->state = OFDMFRAMESYNC_STATE_PLCPSHORT0;

#if DEBUG_OFDMFRAMESYNC_PRINT
        printf("********** frame detected! ************\n");
        printf("    s_hat   :   %12.8f <%12.8f>\n", cabsf(s_hat), cargf(s_hat));
        printf("  tau_hat   :   %12.8f\n", tau_hat);
        printf("    dt      :   %12d\n", dt);
        printf("    timer   :   %12u\n", _q->timer);
#endif
        //printf("exiting prematurely\n");
        //ofdmframesync_destroy(_q);
        //exit(1);
    }

}
Example #26
0
// receive data symbols
void wlanframesync_execute_rxdata(wlanframesync _q)
{
    _q->timer++;
    if (_q->timer < 80)
        return;

    //printf("    receiving symbol %u...\n", _q->num_symbols);

    // reset timer
    _q->timer = 0;

    // run fft
    float complex * rc;
    windowcf_read(_q->input_buffer, &rc);
    memmove(_q->x, &rc[16-2], 64*sizeof(float complex));

    // compute fft, storing result into _q->X
    FFT_EXECUTE(_q->fft);
  
    // recover symbol, correcting for gain, pilot phase, etc.
    wlanframesync_rxsymbol(_q);
   
    // demodulate and pack
    unsigned int i;
    unsigned int n=0;
    unsigned int sym;
    for (i=0; i<64; i++) {
        unsigned int k = (i + 32) % 64;

        if ( k==0 || (k > 26 && k < 38) ) {
            // NULL subcarrier
        } else if (k==43 || k==57 || k==7 || k==21) {
            // PILOT subcarrier
        } else {
            // DATA subcarrier
            assert(n<48);
            sym = wlan_demodulate(_q->mod_scheme, _q->X[k]);
            _q->modem_syms[n] = sym;
            n++;
#if DEBUG_WLANFRAMESYNC
            // TODO : move this outside loop
            if (_q->debug_enabled)
                windowcf_push(_q->debug_framesyms, _q->X[k]);
#endif

        }
    }
    assert(n==48);

    // pack modem symbols
    //printf("  %3u = %3u * %3u\n", _q->enc_msg_len, _q->nsym, _q->bytes_per_symbol);
    unsigned int num_written;
    liquid_wlan_repack_bytes(_q->modem_syms, _q->nbpsc, 48,
                             &_q->msg_enc[_q->num_symbols * _q->bytes_per_symbol], 8, _q->bytes_per_symbol,
                             &num_written);
    assert(num_written == _q->bytes_per_symbol);

    // increment number of received symbols
    _q->num_symbols++;

    // check number of symbols
    if (_q->num_symbols == _q->nsym) {
        // decode message
        wlan_packet_decode(_q->rate, _q->seed, _q->length, _q->msg_enc, _q->msg_dec);

        // assemble RX vector
        struct wlan_rxvector_s rxvector;
        rxvector.LENGTH     = _q->length;
        rxvector.RSSI       = 200 + (unsigned int) (10*log10f(_q->g0));
        rxvector.DATARATE   = _q->rate;
        rxvector.SERVICE    = 0;

        // invoke callback
        if (_q->callback != NULL) {
            //int retval = 
            _q->callback(_q->msg_dec, rxvector, _q->userdata);
        }

        // reset and return
        wlanframesync_reset(_q);
    }
}
Example #27
0
// frame detection
void ofdmframesync_execute_S0b(ofdmframesync _q)
{
    //printf("t = %u\n", _q->timer);
    _q->timer++;

    if (_q->timer < _q->M2)
        return;

    // reset timer
    _q->timer = _q->M + _q->cp_len - _q->backoff;

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

    // estimate S0 gain
    ofdmframesync_estimate_gain_S0(_q, &rc[_q->cp_len], _q->G1);

    float complex s_hat;
    ofdmframesync_S0_metrics(_q, _q->G1, &s_hat);
    s_hat *= _q->g0;

    _q->s_hat_1 = s_hat;

#if DEBUG_OFDMFRAMESYNC_PRINT
    float tau_hat  = cargf(s_hat) * (float)(_q->M2) / (2*M_PI);
    printf("********** S0[1] received ************\n");
    printf("    s_hat   :   %12.8f <%12.8f>\n", cabsf(s_hat), cargf(s_hat));
    printf("  tau_hat   :   %12.8f\n", tau_hat);

    // new timing offset estimate
    tau_hat  = cargf(_q->s_hat_0 + _q->s_hat_1) * (float)(_q->M2) / (2*M_PI);
    printf("  tau_hat * :   %12.8f\n", tau_hat);

    printf("**********\n");
#endif

    // re-adjust timer accordingly
    float tau_prime = cargf(_q->s_hat_0 + _q->s_hat_1) * (float)(_q->M2) / (2*M_PI);
    _q->timer -= (int)roundf(tau_prime);

#if 0
    if (cabsf(s_hat) < 0.3f) {
#if DEBUG_OFDMFRAMESYNC_PRINT
        printf("false alarm S0[1]\n");
#endif
        // false alarm
        ofdmframesync_reset(_q);
        return;
    }
#endif

    float complex g_hat = 0.0f;
    unsigned int i;
    for (i=0; i<_q->M; i++)
        g_hat += _q->G1[i] * conjf(_q->G0[i]);

#if 0
    // compute carrier frequency offset estimate using freq. domain method
    float nu_hat = 2.0f * cargf(g_hat) / (float)(_q->M);
#else
    // compute carrier frequency offset estimate using ML method
    float complex t0 = 0.0f;
    for (i=0; i<_q->M2; i++) {
        t0 += conjf(rc[i])       *       _q->s0[i] * 
                    rc[i+_q->M2] * conjf(_q->s0[i+_q->M2]);
    }
    float nu_hat = cargf(t0) / (float)(_q->M2);
#endif

#if DEBUG_OFDMFRAMESYNC_PRINT
    printf("   nu_hat   :   %12.8f\n", nu_hat);
#endif

    // set NCO frequency
    nco_crcf_set_frequency(_q->nco_rx, nu_hat);

    _q->state = OFDMFRAMESYNC_STATE_PLCPLONG;
}
int main() {
    // options
    unsigned int num_channels=4;    // number of channels
    unsigned int m=5;               // filter delay
    unsigned int num_symbols=12;    // number of symbols

    // derived values
    unsigned int num_samples = num_channels * num_symbols;

    unsigned int i;
    unsigned int j;

    // generate filter
    // NOTE : these coefficients can be random; the purpose of this
    //        exercise is to demonstrate mathematical equivalence
    unsigned int h_len = 2*m*num_channels;
    float h[h_len];
    for (i=0; i<h_len; i++) h[i] = randnf();
    //for (i=0; i<h_len; i++) h[i] = 0.1f*i;
    //for (i=0; i<h_len; i++) h[i] = (i<=m) ? 1.0f : 0.0f;
    //for (i=0; i<h_len; i++) h[i] = 1.0f;

    // create filterbank manually
    dotprod_crcf dp[num_channels];  // vector dot products
    windowcf w[num_channels];       // window buffers

#if DEBUG
    // print coefficients
    printf("h_prototype:\n");
    for (i=0; i<h_len; i++)
        printf("  h[%3u] = %12.8f\n", i, h[i]);
#endif

    // create objects
    unsigned int h_sub_len = 2*m;
    float h_sub[h_sub_len];
    for (i=0; i<num_channels; i++) {
        // sub-sample prototype filter, loading coefficients in
        // reverse order
#if 0
        for (j=0; j<h_sub_len; j++)
            h_sub[j] = h[j*num_channels+i];
#else
        for (j=0; j<h_sub_len; j++)
            h_sub[h_sub_len-j-1] = h[j*num_channels+i];
#endif

        // create window buffer and dotprod objects
        dp[i] = dotprod_crcf_create(h_sub, h_sub_len);
        w[i]  = windowcf_create(h_sub_len);

#if DEBUG
        printf("h_sub[%u] : \n", i);
        for (j=0; j<h_sub_len; j++)
            printf("  h[%3u] = %12.8f\n", j, h_sub[j]);
#endif
    }

    // generate DFT object
    float complex x[num_channels];  // time-domain buffer
    float complex X[num_channels];  // freq-domain buffer
#if 0
    fftplan fft = fft_create_plan(num_channels, X, x, LIQUID_FFT_BACKWARD, 0);
#else
    fftplan fft = fft_create_plan(num_channels, X, x, LIQUID_FFT_FORWARD, 0);
#endif

    // generate filter object
    firfilt_crcf f = firfilt_crcf_create(h, h_len);

    float complex y[num_samples];                   // time-domain input
    float complex Y0[num_symbols][num_channels];    // channelized output
    float complex Y1[num_symbols][num_channels];    // channelized output

    // generate input sequence (complex noise)
    for (i=0; i<num_samples; i++)
        y[i] = randnf() * cexpf(_Complex_I*randf()*2*M_PI);

    // 
    // run analysis filter bank
    //
#if 0
    unsigned int filter_index = 0;
#else
    unsigned int filter_index = num_channels-1;
#endif
    float complex y_hat;    // input sample
    float complex * r;      // read pointer
    for (i=0; i<num_symbols; i++) {

        // load buffers
        for (j=0; j<num_channels; j++) {
            // grab sample
            y_hat = y[i*num_channels + j];

            // push sample into buffer at filter index
            windowcf_push(w[filter_index], y_hat);

            // decrement filter index
            filter_index = (filter_index + num_channels - 1) % num_channels;
            //filter_index = (filter_index + 1) % num_channels;
        }

        // execute filter outputs, reversing order of output (not
        // sure why this is necessary)
        for (j=0; j<num_channels; j++) {
            windowcf_read(w[j], &r);
            dotprod_crcf_execute(dp[j], r, &X[num_channels-j-1]);
        }

        // execute DFT, store result in buffer 'x'
        fft_execute(fft);

        // move to output array
        for (j=0; j<num_channels; j++)
            Y0[i][j] = x[j];
    }

    // 
    // run traditional down-converter (inefficient)
    //
    float dphi; // carrier frequency
    unsigned int n=0;
    for (i=0; i<num_channels; i++) {

        // reset filter
        firfilt_crcf_reset(f);

        // set center frequency
        dphi = 2.0f * M_PI * (float)i / (float)num_channels;

        // reset symbol counter
        n=0;

        for (j=0; j<num_samples; j++) {
            // push down-converted sample into filter
            firfilt_crcf_push(f, y[j]*cexpf(-_Complex_I*j*dphi));

            // compute output at the appropriate sample time
            assert(n<num_symbols);
            if ( ((j+1)%num_channels)==0 ) {
                firfilt_crcf_execute(f, &Y1[n][i]);
                n++;
            }
        }
        assert(n==num_symbols);

    }

    // destroy objects
    for (i=0; i<num_channels; i++) {
        dotprod_crcf_destroy(dp[i]);
        windowcf_destroy(w[i]);
    }
    fft_destroy_plan(fft);

    firfilt_crcf_destroy(f);

    // print filterbank channelizer
    printf("\n");
    printf("filterbank channelizer:\n");
    for (i=0; i<num_symbols; i++) {
        printf("%3u: ", i);
        for (j=0; j<num_channels; j++) {
            printf("  %8.5f+j%8.5f, ", crealf(Y0[i][j]), cimagf(Y0[i][j]));
        }
        printf("\n");
    }

    // print traditional channelizer
    printf("\n");
    printf("traditional channelizer:\n");
    for (i=0; i<num_symbols; i++) {
        printf("%3u: ", i);
        for (j=0; j<num_channels; j++) {
            printf("  %8.5f+j%8.5f, ", crealf(Y1[i][j]), cimagf(Y1[i][j]));
        }
        printf("\n");
    }

    // 
    // compare results
    // 
    float mse[num_channels];
    float complex d;
    for (i=0; i<num_channels; i++) {
        mse[i] = 0.0f;
        for (j=0; j<num_symbols; j++) {
            d = Y0[j][i] - Y1[j][i];
            mse[i] += crealf(d*conjf(d));
        }

        mse[i] /= num_symbols;
    }
    printf("\n");
    printf("rmse: ");
    for (i=0; i<num_channels; i++)
        printf("%12.4e          ", sqrt(mse[i]));
    printf("\n");

    printf("done.\n");
    return 0;

}
Example #29
0
// print debugging information
void flexframesync_debug_print(flexframesync  _q,
                               const char * _filename)
{
#if DEBUG_FLEXFRAMESYNC
    if (!_q->debug_objects_created) {
        fprintf(stderr,"error: flexframesync_debug_print(), debugging objects don't exist; enable debugging first\n");
        return;
    }
    unsigned int i;
    float complex * rc;
    float         * r;
    FILE* fid = fopen(_filename,"w");
    fprintf(fid,"%% %s: auto-generated file", _filename);
    fprintf(fid,"\n\n");
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n\n");
    fprintf(fid,"n = %u;\n", DEBUG_BUFFER_LEN);

    // write x
    fprintf(fid,"x = zeros(1,n);\n");
    windowcf_read(_q->debug_x, &rc);
    for (i=0; i<DEBUG_BUFFER_LEN; i++)
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));
    fprintf(fid,"\n\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(1:length(x),real(x), 1:length(x),imag(x));\n");
    fprintf(fid,"ylabel('received signal, x');\n");

    // write pre-demod sample buffer
    fprintf(fid,"k = %u;\n", _q->k);
    fprintf(fid,"m = %u;\n", _q->m);
    fprintf(fid,"presync_samples = zeros(1,k*(64+m));\n");
    windowcf_read(_q->buffer, &rc);
    for (i=0; i<_q->k*(64+_q->m); i++)
        fprintf(fid,"presync_samples(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));

    // write p/n sequence
    fprintf(fid,"preamble_pn = zeros(1,64);\n");
    r = _q->preamble_pn;
    for (i=0; i<64; i++)
        fprintf(fid,"preamble_pn(%4u) = %12.4e;\n", i+1, r[i]);

    // write p/n symbols
    fprintf(fid,"preamble_rx = zeros(1,64);\n");
    rc = _q->preamble_rx;
    for (i=0; i<64; i++)
        fprintf(fid,"preamble_rx(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));

    // write payload symbols
    unsigned int num_payload_syms = _q->payload_mod_len > 256 ? 256 : _q->payload_mod_len;
    fprintf(fid,"payload_syms = zeros(1,%u);\n", num_payload_syms);
    rc = _q->payload_sym;
    for (i=0; i<num_payload_syms; i++)
        fprintf(fid,"payload_syms(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i]));

    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(real(payload_syms),imag(payload_syms),'x',...\n");
    fprintf(fid,"     real(preamble_rx),     imag(preamble_rx),     'x');\n");
    fprintf(fid,"xlabel('in-phase');\n");
    fprintf(fid,"ylabel('quadrature phase');\n");
    fprintf(fid,"legend('p/n syms','payload syms','location','northeast');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"axis([-1 1 -1 1]*1.5);\n");
    fprintf(fid,"axis square;\n");

#if 0
    // NCO, timing, etc.
    fprintf(fid,"symsync_index = zeros(1,664);\n");
    fprintf(fid,"nco_phase     = zeros(1,664);\n");
    for (i=0; i<664; i++) {
        fprintf(fid,"symsync_index(%4u) = %12.4e;\n", i+1, _q->debug_symsync_index[i]);
        fprintf(fid,"nco_phase(%4u)     = %12.4e;\n", i+1, _q->debug_nco_phase[i]);
    }
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"  plot(nco_phase);\n");
    fprintf(fid,"  ylabel('nco phase');\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"  plot(symsync_index);\n");
    fprintf(fid,"  ylabel('symsync index');\n");
    fprintf(fid,"  grid on;\n");
#endif

    fprintf(fid,"\n\n");
    fclose(fid);

    printf("flexframesync/debug: results written to %s\n", _filename);
#else
    fprintf(stderr,"flexframesync_debug_print(): compile-time debugging disabled\n");
#endif
}
Example #30
0
// main program
int main (int argc, char **argv)
{
    // command-line options
    int verbose = 1;

    int ppm_error = 0;
    int gain = 0;
    unsigned int nfft    = 64;
    float offset         = -65.0f;
    float scale          = 5.0f;
    float fft_rate       = 10.0f;
    float rx_resamp_rate;
    float bandwidth      = 800e3f;
    unsigned int logsize = 4096;
    char filename[256]   = "rtl_asgram.dat";
    int r, n_read;

    uint32_t frequency = 100000000;
    uint32_t samp_rate = DEFAULT_SAMPLE_RATE;
    uint32_t out_block_size = DEFAULT_BUF_LENGTH;
    uint8_t *buffer;

    int dev_index = 0;
    int dev_given = 0;

    struct sigaction sigact;
    normalizer_t *norm;

    //
    int d;
    while ((d = getopt(argc,argv,"hf:b:B:G:n:p:s:o:r:L:F:")) != EOF) {
        switch (d) {
        case 'h':
            usage();
            return 0;
        case 'f':
            frequency   = atof(optarg);
            break;
        case 'b':
            bandwidth   = atof(optarg);
            break;
        case 'B':
            out_block_size = (uint32_t)atof(optarg);
            break;
        case 'G':
            gain = (int)(atof(optarg) * 10);
            break;
        case 'n':
            nfft        = atoi(optarg);
            break;
        case 'o':
            offset      = atof(optarg);
            break;
        case 'p':
            ppm_error = atoi(optarg);
            break;
        case 's':
            samp_rate = (uint32_t)atofs(optarg);
            break;
        case 'r':
            fft_rate    = atof(optarg);
            break;
        case 'L':
            logsize     = atoi(optarg);
            break;
        case 'F':
            strncpy(filename,optarg,255);
            break;
        case 'd':
            dev_index = verbose_device_search(optarg);
            dev_given = 1;
            break;
        default:
            usage();
            return 1;
        }
    }

    // validate parameters
    if (fft_rate <= 0.0f || fft_rate > 100.0f) {
        fprintf(stderr,"error: %s, fft rate must be in (0, 100) Hz\n", argv[0]);
        exit(1);
    }

    if (!dev_given) {
        dev_index = verbose_device_search("0");
    }

    if (dev_index < 0) {
        exit(1);
    }

    r = rtlsdr_open(&dev, (uint32_t)dev_index);
    if (r < 0) {
        fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index);
        exit(1);
    }

    sigact.sa_handler = sighandler;
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigaction(SIGINT, &sigact, NULL);
    sigaction(SIGTERM, &sigact, NULL);
    sigaction(SIGQUIT, &sigact, NULL);
    sigaction(SIGPIPE, &sigact, NULL);

    /* Set the sample rate */
    verbose_set_sample_rate(dev, samp_rate);

    /* Set the frequency */
    verbose_set_frequency(dev, frequency);

    if (0 == gain) {
        /* Enable automatic gain */
        verbose_auto_gain(dev);
    } else {
        /* Enable manual gain */
        gain = nearest_gain(dev, gain);
        verbose_gain_set(dev, gain);
    }

    verbose_ppm_set(dev, ppm_error);

    rx_resamp_rate = bandwidth/samp_rate;

    printf("frequency       :   %10.4f [MHz]\n", frequency*1e-6f);
    printf("bandwidth       :   %10.4f [kHz]\n", bandwidth*1e-3f);
    printf("sample rate     :   %10.4f kHz = %10.4f kHz * %8.6f\n",
           samp_rate * 1e-3f,
           bandwidth    * 1e-3f,
           1.0f / rx_resamp_rate);
    printf("verbosity       :    %s\n", (verbose?"enabled":"disabled"));

    unsigned int i;

    // add arbitrary resampling component
    msresamp_crcf resamp = msresamp_crcf_create(rx_resamp_rate, 60.0f);
    assert(resamp);

    // create buffer for sample logging
    windowcf log = windowcf_create(logsize);

    // create ASCII spectrogram object
    float maxval;
    float maxfreq;
    char ascii[nfft+1];
    ascii[nfft] = '\0'; // append null character to end of string
    asgram q = asgram_create(nfft);
    asgram_set_scale(q, offset, scale);

    // assemble footer
    unsigned int footer_len = nfft + 16;
    char footer[footer_len+1];
    for (i=0; i<footer_len; i++)
        footer[i] = ' ';
    footer[1] = '[';
    footer[nfft/2 + 3] = '+';
    footer[nfft + 4] = ']';
    sprintf(&footer[nfft+6], "%8.3f MHz", frequency*1e-6f);
    unsigned int msdelay = 1000 / fft_rate;

    // create/initialize Hamming window
    float w[nfft];
    for (i=0; i<nfft; i++)
        w[i] = hamming(i,nfft);

    //allocate recv buffer
    buffer = malloc(out_block_size * sizeof(uint8_t));
    assert(buffer);

    // create buffer for arbitrary resamper output
    int b_len = ((int)(out_block_size * rx_resamp_rate) + 64) >> 1;
    complex float buffer_resamp[b_len];
    debug("resamp_buffer_len: %d", b_len);

    // timer to control asgram output
    timer t1 = timer_create();
    timer_tic(t1);

    norm = normalizer_create();

    verbose_reset_buffer(dev);

    while (!do_exit) {
        // grab data from device
        r = rtlsdr_read_sync(dev, buffer, out_block_size, &n_read);
        if (r < 0) {
            fprintf(stderr, "WARNING: sync read failed.\n");
            break;
        }

        if ((bytes_to_read > 0) && (bytes_to_read < (uint32_t)n_read)) {
            n_read = bytes_to_read;
            do_exit = 1;
        }

        // push data through arbitrary resampler and give to frame synchronizer
        // TODO : apply bandwidth-dependent gain
        for (i=0; i<n_read/2; i++) {
            // grab sample from usrp buffer
            complex float rtlsdr_sample = normalizer_normalize(norm, *((uint16_t*)buffer+i));

            // push through resampler (one at a time)
            unsigned int nw;
            msresamp_crcf_execute(resamp, &rtlsdr_sample, 1, buffer_resamp, &nw);

            // push resulting samples into asgram object
            asgram_push(q, buffer_resamp, nw);

            // write samples to log
            windowcf_write(log, buffer_resamp, nw);
        }

        if ((uint32_t)n_read < out_block_size) {
            fprintf(stderr, "Short read, samples lost, exiting!\n");
            break;
        }

        if (bytes_to_read > 0)
            bytes_to_read -= n_read;

        if (timer_toc(t1) > msdelay*1e-3f) {
            // reset timer
            timer_tic(t1);

            // run the spectrogram
            asgram_execute(q, ascii, &maxval, &maxfreq);

            // print the spectrogram
            printf(" > %s < pk%5.1fdB [%5.2f]\n", ascii, maxval, maxfreq);
            printf("%s\r", footer);
            fflush(stdout);
        }
    }

    // try to write samples to file
    FILE * fid = fopen(filename,"w");
    if (fid != NULL) {
        // write header
        fprintf(fid, "# %s : auto-generated file\n", filename);
        fprintf(fid, "#\n");
        fprintf(fid, "# num_samples :   %u\n", logsize);
        fprintf(fid, "# frequency   :   %12.8f MHz\n", frequency*1e-6f);
        fprintf(fid, "# bandwidth   :   %12.8f kHz\n", bandwidth*1e-3f);

        // save results to file
        complex float * rc;   // read pointer
        windowcf_read(log, &rc);
        for (i=0; i<logsize; i++)
            fprintf(fid, "%12.4e %12.4e\n", crealf(rc[i]), cimagf(rc[i]));

        // close it up
        fclose(fid);
        printf("results written to '%s'\n", filename);
    } else {
        fprintf(stderr,"error: %s, could not open '%s' for writing\n", argv[0], filename);
    }

    // destroy objects
    normalizer_destroy(&norm);
    msresamp_crcf_destroy(resamp);
    windowcf_destroy(log);
    asgram_destroy(q);
    timer_destroy(t1);

    rtlsdr_close(dev);
    free (buffer);

    return 0;
}