Example #1
0
/* Performs 1st order linear interpolation with out-of-bound interpolation */
void srslte_interp_linear_offset_cabs(cf_t *input, cf_t *output, 
                               uint32_t M, uint32_t len, 
                               uint32_t off_st, uint32_t off_end) 
{
  uint32_t i, j;
  float mag0=0, mag1=0, arg0=0, arg1=0, mag=0, arg=0;

  for (i=0;i<len-1;i++) {
    mag0 = cabsf(input[i]);
    mag1 = cabsf(input[i+1]);
    arg0 = cargf(input[i]);
    arg1 = cargf(input[i+1]);
    if (i==0) {
      for (j=0;j<off_st;j++) {
        mag = mag0 - (j+1)*(mag1-mag0)/M;
        arg = arg0 - (j+1)*(arg1-arg0)/M;
        output[j] = mag * cexpf(I * arg);
      }
    }
    for (j=0;j<M;j++) {
      mag = mag0 + j*(mag1-mag0)/M;
      arg = arg0 + j*(arg1-arg0)/M;
      output[i*M+j+off_st] = mag * cexpf(I * arg);
    }
  }
  if (len > 1) {
    for (j=0;j<off_end;j++) {
      mag = mag1 + j*(mag1-mag0)/M;
      arg = arg1 + j*(arg1-arg0)/M;
      output[i*M+j+off_st] = mag * cexpf(I * arg);
    }
  }
}
void autotest_nco_crcf_mix_block_up()
{
    // options
    unsigned int buf_len = 4096;
    float        phase   = 0.7123f;
    float        freq    = 0; //0.1324f;
    float        tol     = 1e-2f;

    // create object
    nco_crcf nco = nco_crcf_create(LIQUID_NCO);
    nco_crcf_set_phase    (nco, phase);
    nco_crcf_set_frequency(nco, freq);

    // generate signal
    float complex buf_0[buf_len];
    float complex buf_1[buf_len];
    unsigned int i;
    for (i=0; i<buf_len; i++)
        buf_0[i] = cexpf(_Complex_I*2*M_PI*randf());

    // mix signal
    nco_crcf_mix_block_up(nco, buf_0, buf_1, buf_len);

    // compare result to expected
    float phi = phase;
    for (i=0; i<buf_len; i++) {
        float complex v = buf_0[i] * cexpf(_Complex_I*phi);
        CONTEND_DELTA( crealf(buf_1[i]), crealf(v), tol);
        CONTEND_DELTA( cimagf(buf_1[i]), cimagf(v), tol);
        phi += freq;
    }

    // destroy object
    nco_crcf_destroy(nco);
}
Example #3
0
/* Performs 1st order linear interpolation with out-of-bound interpolation */
void interp_linear_offset(cf_t *input, cf_t *output, int M, int len, int off_st, int off_end) {
	int i, j;
	float mag0, mag1, arg0, arg1, mag, arg;

	for (i=0;i<len-1;i++) {
		mag0 = cabsf(input[i]);
		mag1 = cabsf(input[i+1]);
		arg0 = cargf(input[i]);
		arg1 = cargf(input[i+1]);
		if (i==0) {
			for (j=0;j<off_st;j++) {
				mag = mag0 - (j+1)*(mag1-mag0)/M;
				arg = arg0 - (j+1)*(arg1-arg0)/M;
				output[j] = mag * cexpf(I * arg);
			}
		}
		for (j=0;j<M;j++) {
			mag = mag0 + j*(mag1-mag0)/M;
			arg = arg0 + j*(arg1-arg0)/M;
			output[i*M+j+off_st] = mag * cexpf(I * arg);
		}
	}
	if (len > 1) {
		for (j=0;j<off_end;j++) {
			mag = mag1 + j*(mag1-mag0)/M;
			arg = arg1 + j*(arg1-arg0)/M;
			output[i*M+j+off_st] = mag * cexpf(I * arg);
		}
	}
}
Example #4
0
void myradon2_lop(bool adj, bool add, int nm, int nd, sf_complex *mm, sf_complex *dd)
/*< radon linear operator >*/
{
	int ix, ip;
	sf_complex sumc;

    	if (nm != np || nd != nx) sf_error("%s: mismatched data sizes",__FILE__);
	
	sf_cadjnull(adj, add, nm, nd, mm, dd);

	if(adj){// mm(p,w)=sum_{ix=0}^{nx} dd(xx[ix],w)*exp(i*w*p*xx[ix])
		for(ip=0; ip<np; ip++) // loop over slopes
		{
			sumc=sf_cmplx(0,0);
			for(ix=0; ix<nx; ix++) 
				sumc+=cexpf(I*w*p[ip]*xx[ix])*dd[ix];
			mm[ip]=sumc;
		}
	}else{// dd(xx,w)=sum_{ip=0}^{np} mm(p[ip],w)*exp(-i*w*p[ip]*xx)
		for(ix=0; ix<nx; ix++) 
		{
			sumc=sf_cmplx(0,0);
			for(ip=0; ip<np; ip++)
				sumc+=cexpf(-I*w*p[ip]*xx[ix])*mm[ip];
			dd[ix]=sumc;
		}
	}
}
Example #5
0
/*  _m          :   number of correlators                   */
PRESYNC() PRESYNC(_create)(TC *         _v,
                           unsigned int _n,
                           float        _dphi_max,
                           unsigned int _m)
{
    // validate input
    if (_n < 1) {
        fprintf(stderr, "error: bpresync_%s_create(), invalid input length\n", EXTENSION_FULL);
        exit(1);
    } else if (_m == 0) {
        fprintf(stderr, "error: bpresync_%s_create(), number of correlators must be at least 1\n", EXTENSION_FULL);
        exit(1);
    }

    // allocate main object memory and initialize
    PRESYNC() _q = (PRESYNC()) malloc(sizeof(struct PRESYNC(_s)));
    _q->n = _n;
    _q->m = _m;

    _q->n_inv = 1.0f / (float)(_q->n);

    unsigned int i;

    // create internal receive buffers
    _q->rx_i = WINDOW(_create)(_q->n);
    _q->rx_q = WINDOW(_create)(_q->n);

    // create internal array of frequency offsets
    _q->dphi = (float*) malloc( _q->m*sizeof(float) );

    // create internal synchronizers
    _q->sync_i = (DOTPROD()*) malloc( _q->m*sizeof(DOTPROD()) );
    _q->sync_q = (DOTPROD()*) malloc( _q->m*sizeof(DOTPROD()) );

    // buffer
    T vi_prime[_n];
    T vq_prime[_n];
    for (i=0; i<_q->m; i++) {

        // generate signal with frequency offset
        _q->dphi[i] = (float)i / (float)(_q->m-1)*_dphi_max;
        unsigned int k;
        for (k=0; k<_q->n; k++) {
            vi_prime[k] = REAL( _v[k] * cexpf(-_Complex_I*k*_q->dphi[i]) );
            vq_prime[k] = IMAG( _v[k] * cexpf(-_Complex_I*k*_q->dphi[i]) );
        }

        _q->sync_i[i] = DOTPROD(_create)(vi_prime, _q->n);
        _q->sync_q[i] = DOTPROD(_create)(vq_prime, _q->n);
    }

    // allocate memory for cross-correlation
    _q->rxy = (float*) malloc( _q->m*sizeof(float) );

    // reset object
    PRESYNC(_reset)(_q);

    return _q;
}
Example #6
0
static void init_wave(int init, 
		      int nx, float dx,
		      int nz, float dz,
		      sf_complex *pp /* [nx] */,
		      float wov, int nw, int iw)
{
    int ix;
    float x,x0,z0,phase,amp;
    
    x0 = nx*dx/3;
    z0 = nz*dz/3;

    switch(init) {
	case 1: /*  planar wave @ 15deg */
	    for (ix=0; ix < nx; ix++) {
		x = (ix+1)*dx - x0;
		phase  = wov*x*sinf(15*SF_PI/180.);
		pp[ix] = cexpf(sf_cmplx(0.,phase));
	    }
	    break;
	case 2: /* expanding spherical wave */
	    for (ix=0; ix < nx; ix++) {
		x = (ix+1)*dx - x0;
		phase  = wov*hypotf(z0,x);
		pp[ix] = cexpf(sf_cmplx(0.,phase));
	    }
	    break;
	case 3: /* point source */
	    for (ix=0; ix < nx; ix++) {
		pp[ix]=sf_cmplx(0.,0.);
	    }
	    pp[nx/3-1] = sf_cmplx(1.,0.);
	    break;
	case 4: /* collapsing spherical wave */
	    for (ix=0; ix < nx; ix++) {
		x = (ix+1)*dx - x0;
		phase  = -wov*hypotf(z0,x);
		pp[ix] = cexpf(sf_cmplx(0.,phase));
	    }
	    break;
	default:
	    sf_error("Unknown init=%d",init);
    }

    amp = (nw-iw+1.0)/nw;
    amp = cosf((1-amp)*(0.5*SF_PI));
    amp *= amp;

    for (ix=0; ix < nx; ix++) {
#ifdef SF_HAS_COMPLEX_H
	pp[ix] *= amp;
#else
	pp[ix] = sf_crmul(pp[ix],amp);
#endif
    }
}
Example #7
0
// [AC-Adaptive]
static void radial_self_delays(unsigned int N, float shifts[N], const float phi[N], const long dims[DIMS], const complex float* in)
{
	unsigned int d = 2;
	unsigned int flags = (1 << d);

	assert(N == dims[d]);

	long dims1[DIMS];
	md_select_dims(DIMS, ~flags, dims1, dims);

	complex float* tmp1 = md_alloc(DIMS, dims1, CFL_SIZE);
	complex float* tmp2 = md_alloc(DIMS, dims1, CFL_SIZE);

	long pos[DIMS] = { 0 };

	for (unsigned int i = 0; i < dims[d]; i++) {

		pos[d] = i;
		md_copy_block(DIMS, pos, dims1, tmp1, dims, in, CFL_SIZE);

		// find opposing spoke

		float mdelta = 0.;
		int mindex = 0;

		for (unsigned int j = 0; j < dims[d]; j++) {

			float delta = cabsf(cexpf(1.i * phi[j]) - cexpf(1.i * phi[i]));

			if (mdelta <= delta) {

				mdelta = delta;
				mindex = j;
			}
		}

		pos[d] = mindex;
		md_copy_block(DIMS, pos, dims1, tmp2, dims, in, CFL_SIZE);


		unsigned int d2 = 1;
		float rshifts[DIMS];
		md_flip(DIMS, dims1, MD_BIT(d2), tmp2, tmp2, CFL_SIZE); // could be done by iFFT in est_subpixel_shift
		est_subpixel_shift(DIMS, rshifts, dims1, MD_BIT(d2), tmp2, tmp1);

		float mshift = rshifts[d2] / 2.; // mdelta

		shifts[i] = mshift;
	}

	md_free(tmp1);
	md_free(tmp2);
}
Example #8
0
void xkolmog(sf_complex *trace1, sf_complex *trace2)
/*< convert Fourier-domain cross-correlation to minimum-phase >*/ 
{
    int i1;
    const double eps=1.e-32;

    for (i1=0; i1 < nk; i1++) {
#ifdef SF_HAS_COMPLEX_H
	fft1[i1] = clogf(trace1[i1]+eps)/nk;
#else
	fft1[i1] = sf_crmul(clogf(sf_cadd(trace1[i1],sf_cmplx(eps,0.))),
			    1.0/nk);
#endif
    }

    /* Inverse transform */
    kiss_fft(invs,(const kiss_fft_cpx *) fft1, (kiss_fft_cpx *) trace1);

#ifdef SF_HAS_COMPLEX_H
    trace1[0]    *= 0.5; trace2[0]    = trace1[0];
    trace1[nk/2] *= 0.5; trace2[nk/2] = trace1[nk/2];
#else
    trace1[0]    = sf_crmul(trace1[0],   0.5); trace2[0]    = trace1[0];
    trace1[nk/2] = sf_crmul(trace1[nk/2],0.5); trace2[nk/2] = trace1[nk/2];
#endif
    for (i1=1+nk/2; i1 < nk; i1++) {
	trace2[nk-i1] = trace1[i1];
	trace1[i1] = sf_cmplx(0.,0.);
	trace2[i1] = sf_cmplx(0.,0.);
    }

    /* Fourier transform */
    kiss_fft(forw,(const kiss_fft_cpx *) trace1, (kiss_fft_cpx *) fft1);
    kiss_fft(forw,(const kiss_fft_cpx *) trace2, (kiss_fft_cpx *) fft2);
    
    for (i1=0; i1 < nk; i1++) {
#ifdef SF_HAS_COMPLEX_H
	fft1[i1] = cexpf(fft1[i1])/nk;
	fft2[i1] = cexpf(fft2[i1])/nk;
#else
	fft1[i1] = sf_crmul(cexpf(fft1[i1]),1./nk);
	fft2[i1] = sf_crmul(cexpf(fft2[i1]),1./nk);
#endif
    }

    /* Inverse transform */
    kiss_fft(invs,(const kiss_fft_cpx *) fft1, (kiss_fft_cpx *) trace1);
    kiss_fft(invs,(const kiss_fft_cpx *) fft2, (kiss_fft_cpx *) trace2);

    for (i1=0; i1 < nk; i1++) {
	trace2[i1] = conjf(trace2[i1]);
    }
}
Example #9
0
sf_complex Green(float r1,float r2,float r3,float s1,float s2,float s3,float omega) 
/*< Green's function >*/
{
    double tt,amp;
    sf_complex val;

    GreenTtAmp(r1,r2,r3,s1,s2,s3,&tt,&amp);
#ifdef SF_HAS_COMPLEX_H
    val=amp*cexpf(sf_cmplx(0.,omega*tt)); 
#else
    val=sf_crmul(cexpf(sf_cmplx(0.,omega*tt)),amp); 
#endif
    return (val);
}
Example #10
0
void BornScatteredField(float xx,float xy,float xz,float *output)
/*< Born scattering field >*/
{
    int iw;
    double omega,scale;

    sf_complex  U,dU;
    sf_complex val,fkern;

    ZeroArray(u,  nt); 
    ZeroArray(du, nt); 
    *output=0.;

    for (iw=0; iw<nw; iw++) {
	omega=ow+dw*iw;

	scale =cos((SF_PI/2)*(((double) iw+1)/((double) nw+1)));
	scale*=scale*omega;

#ifdef SF_HAS_COMPLEX_H
	/* background field */
	U=Green(xx,xy,xz,sx,sy,sz,omega)*scale;
	    
	/* scattered field */
	val=Green(px,py,pz,sx,sy,sz,omega)*scale;
	val *= Green(xx,xy,xz,px,py,pz,omega);
	dU = val*(-omega*omega*dv);

	U += dU;
	fkern=cexpf(sf_cmplx(0.,-omega*0.6));
	val=fkern*U;
#else
	/* background field */
	U=sf_crmul(Green(xx,xy,xz,sx,sy,sz,omega),scale);
	    
	/* scattered field */
	val=sf_crmul(Green(px,py,pz,sx,sy,sz,omega),scale);
	val=sf_cmul(val,Green(xx,xy,xz,px,py,pz,omega));
	dU=sf_crmul(val,-omega*omega*dv);

	U=sf_cadd(U,dU);
	fkern=cexpf(sf_cmplx(0.,-omega*0.6));
	val=sf_cmul(fkern,U);
#endif

	*output+=crealf(val);
    }
    return;
}    
Example #11
0
// 
// Test AC gain control
//
void autotest_agc_crcf_ac_gain_control()
{
    // set paramaters
    float gamma = 0.1f;             // nominal signal level
    float bt    = 0.1f;             // bandwidth-time product
    float tol   = 0.001f;           // error tolerance
    float dphi  = 0.1f;             // NCO frequency

    // create AGC object and initialize
    agc_crcf q = agc_crcf_create();
    agc_crcf_set_bandwidth(q, bt);

    unsigned int i;
    float complex x;
    float complex y;
    for (i=0; i<256; i++) {
        x = gamma * cexpf(_Complex_I*i*dphi);
        agc_crcf_execute(q, x, &y);
    }

    if (liquid_autotest_verbose)
        printf("gamma : %12.8f, rssi : %12.8f\n", gamma, agc_crcf_get_signal_level(q));

    // Check results
    CONTEND_DELTA( agc_crcf_get_gain(q), 1.0f/gamma, tol);

    // destroy AGC object
    agc_crcf_destroy(q);
}
Example #12
0
void fbdip_init(float rad, int m1, int m2, 
	int *rect, int niter, float dip0, bool vb)
/*< initialize >*/
{
	int n, nn[2];
	n1 = m1;
	n2 = m2;
	verb = vb;

	u1 = sf_floatalloc2(n1, n2);
	u2 = sf_floatalloc2(n1, n2);
	u3 = sf_floatalloc2(n1, n2);
	u4 = sf_floatalloc2(n1, n2);
	u5 = sf_floatalloc2(n1, n2);
	p = sf_complexalloc2(n1, n2);

	r=rad;
	p0 = rad*cexpf(sf_cmplx(0, dip0));
	
	if(rect[0]>0 && rect[1]>0)
	{
		n = n1*n2;
		nn[0] = n1;
		nn[1] = n2;
		sf_divn_init (2, n, nn, rect, niter, false);
		use_divn=true;
	}else 	use_divn=false;
}
Example #13
0
// create freqmod object
//  _kf     :   modulation factor
FREQMOD() FREQMOD(_create)(float _kf)
{
    // validate input
    if (_kf <= 0.0f || _kf > 1.0) {
        fprintf(stderr,"error: freqmod_create(), modulation factor %12.4e out of range [0,1]\n", _kf);
        exit(1);
    }

    // create main object memory
    FREQMOD() q = (freqmod) malloc(sizeof(struct FREQMOD(_s)));

    // set modulation factor
    q->kf  = _kf;
    q->ref = q->kf * (1<<16);

    // initialize look-up table
    q->sincos_table_len = 1024;
    q->sincos_table     = (TC*) malloc( q->sincos_table_len*sizeof(TC) );
    unsigned int i;
    for (i=0; i<q->sincos_table_len; i++) {
        q->sincos_table[i] = cexpf(_Complex_I*2*M_PI*(float)i / (float)(q->sincos_table_len) );
    }

    // reset modem object
    FREQMOD(_reset)(q);

    // return object
    return q;
}
Example #14
0
void benchmark_gmskmodem_demodulate(struct rusage *_start,
                                    struct rusage *_finish,
                                    unsigned long int *_num_iterations)
{
    // options
    unsigned int k=2;   // filter samples/symbol
    unsigned int m=3;   // filter delay (symbols)
    float BT=0.3f;      // bandwidth-time product

    // create modem object
    gmskdem demod = gmskdem_create(k, m, BT);

    float complex x[k];
    unsigned int symbol_out = 0;
    
    unsigned long int i;
    for (i=0; i<k; i++)
        x[i] = randnf()*cexpf(_Complex_I*2*M_PI*randf());

    // start trials
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        gmskdem_demodulate(demod, x, &symbol_out);
        gmskdem_demodulate(demod, x, &symbol_out);
        gmskdem_demodulate(demod, x, &symbol_out);
        gmskdem_demodulate(demod, x, &symbol_out);
    }
    getrusage(RUSAGE_SELF, _finish);
    *_num_iterations *= 4;

    // destroy modem objects
    gmskdem_destroy(demod);
}
Example #15
0
/*------------------------------------------------------------*/
void cam3_ssf(
    sf_complex       w /* frequency */,
    sf_complex   ***wx /* wavefield */,
    cub3d          cub,
    cam3d          cam,
    tap3d          tap,
    slo3d          slo,
    int            imz,
    int         ompith
    )
/*< Wavefield extrapolation by SSF >*/
{
    sf_complex co,cs,cr,w2,khy,kss,krr;
    float s, kmy, d,dsc,drc;
    int imy,imx,ihx,jmy, js,jr;

    co = sf_cmplx(0,0);
#ifdef SF_HAS_COMPLEX_H
    w2 = w*w;
#else
    w2 = sf_cmul(w,w);
#endif
    
#ifdef SF_HAS_COMPLEX_H
    LOOP( s = slo->so[ompith][ cam->jy[imy] ][ cam->is[ihx][imx] ] 
	  +   slo->so[ompith][ cam->jy[imy] ][ cam->ir[ihx][imx] ];
	  wx[ihx][imy][imx] *= cexpf(-w*s* cub->amz.d/2); );
Example #16
0
File: pclin.c Project: anj1/cdac
/* inputs:
 *  pdx,pf,n: piecewise linear function dx, values, and length
 *  w: desired angular frequency
 * returns fourier coefficient as complex number (ISO C99).
 * If the input is a complex function, the following can be called twice
 * with the second coefficient multiplied by _Complex_I and added to the
 * first (see pclin_fourier_trans_cplx).
 * It is assumed that the length of the x-axis is 2*pi. If it is not, it
 * should be normalized to 2*pi before calling this function.
 */
float complex pclin_fourier(float *pdx, float *pf, int n, float w)
{
	int i;
	float x1,x2;
	float f1,f2;
	float slope,offset;
	
	float complex sum;
	float complex alpha;
	float complex invalpha;
	
	x1 = 0.0;
	sum = 0.0;
	f1=pf[n-1];

	/* different behavior for zero w */
	if(w==0.0){
		for(i=0;i<n;i++){
			sum += 0.5*pdx[i]*(f1 + pf[i]);
			x1 += pdx[i];
			f1 = pf[i];
		}
		return sum;
	}
	
	/* regular behavior for nonzero w */
	alpha = -_Complex_I*w;
	invalpha = 1/alpha;
	for(i=0;i<n;i++){
		f2 =     pf[i];
		x2 = x1+pdx[i];
		
		/* calculate product of fourier wave with function */
		/* first, calculate slope and offset of curve */
		slope=(f2-f1)/(x2-x1);
		offset=f1-slope*x1;
		
		/* now use formula (refer to pclin_fourier.tex) */
		sum += cexpf(alpha*x2)*(slope*(x2-invalpha)+offset) -
		       cexpf(alpha*x1)*(slope*(x1-invalpha)+offset);
		
		f1 = f2;
		x1 = x2;
	}
	
	return sum/alpha;
}
Example #17
0
// recover symbol, correcting for gain, pilot phase, etc.
void wlanframesync_rxsymbol(wlanframesync _q)
{
    // apply gain
    unsigned int i;
    for (i=0; i<64; i++)
        _q->X[i] *= _q->R[i];

    // polynomial curve-fit
    float x_phase[4] = {-21.0f, -7.0f, 7.0f, 21.0f};
    float y_phase[4];
    float p_phase[2];

    // update pilot phase
    unsigned int pilot_phase = wlan_lfsr_advance(_q->ms_pilot);

    y_phase[0] = pilot_phase ? cargf(-_q->X[43]) : cargf( _q->X[43]);
    y_phase[1] = pilot_phase ? cargf(-_q->X[57]) : cargf( _q->X[57]);
    y_phase[2] = pilot_phase ? cargf(-_q->X[ 7]) : cargf( _q->X[ 7]);
    y_phase[3] = pilot_phase ? cargf( _q->X[21]) : cargf(-_q->X[21]);

    // unwrap phase
    if ( (y_phase[1]-y_phase[0]) >  M_PI ) y_phase[1] -= 2*M_PI;
    if ( (y_phase[1]-y_phase[0]) < -M_PI ) y_phase[1] += 2*M_PI;

    if ( (y_phase[2]-y_phase[1]) >  M_PI ) y_phase[2] -= 2*M_PI;
    if ( (y_phase[2]-y_phase[1]) < -M_PI ) y_phase[2] += 2*M_PI;

    if ( (y_phase[3]-y_phase[2]) >  M_PI ) y_phase[3] -= 2*M_PI;
    if ( (y_phase[3]-y_phase[2]) < -M_PI ) y_phase[3] += 2*M_PI;

#if 0
    printf("    x = [-21 -7 7 21]; y = [%6.3f %6.3f %6.3f %6.3f];\n", y_phase[0], y_phase[1], y_phase[2], y_phase[3]);
#endif

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

    // compensate for phase offset
    // TODO : find more computationally efficient way to do this
    for (i=0; i<64; i++) {
        float fx    = (i > 31) ? (float)i - (float)(64) : (float)i;
        float theta = polyf_val(p_phase, 2, fx);
        _q->X[i] *= cexpf(-_Complex_I*theta);
    }

    // adjust NCO frequency based on differential phase
    if (_q->num_symbols > 0) {
        // compute phase error (unwrapped)
        float dphi_prime = p_phase[0] - _q->phi_prime;
        if (dphi_prime >  M_PI) dphi_prime -= M_2_PI;
        if (dphi_prime < -M_PI) dphi_prime += M_2_PI;

        // adjust NCO proportionally to phase error
        nco_crcf_adjust_frequency(_q->nco_rx, 1e-3f*dphi_prime);
    }
    // set internal phase state
    _q->phi_prime = p_phase[0];
}
Example #18
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 #19
0
/*  _m          :   number of correlators                   */
BPRESYNC() BPRESYNC(_create)(TC *         _v,
                             unsigned int _n,
                             float        _dphi_max,
                             unsigned int _m)
{
    // validate input
    if (_n < 1) {
        fprintf(stderr, "error: bpresync_%s_create(), invalid input length\n", EXTENSION_FULL);
        exit(1);
    } else if (_m == 0) {
        fprintf(stderr, "error: bpresync_%s_create(), number of correlators must be at least 1\n", EXTENSION_FULL);
        exit(1);
    }

    // allocate main object memory and initialize
    BPRESYNC() _q = (BPRESYNC()) malloc(sizeof(struct BPRESYNC(_s)));
    _q->n = _n;
    _q->m = _m;

    _q->n_inv = 1.0f / (float)(_q->n);

    unsigned int i;

    // create internal receive buffers
    _q->rx_i = bsequence_create(_q->n);
    _q->rx_q = bsequence_create(_q->n);

    // create internal array of frequency offsets
    _q->dphi = (float*) malloc( _q->m*sizeof(float) );

    // create internal synchronizers
    _q->sync_i = (bsequence*) malloc( _q->m*sizeof(bsequence) );
    _q->sync_q = (bsequence*) malloc( _q->m*sizeof(bsequence) );

    for (i=0; i<_q->m; i++) {

        _q->sync_i[i] = bsequence_create(_q->n);
        _q->sync_q[i] = bsequence_create(_q->n);

        // generate signal with frequency offset
        _q->dphi[i] = (float)i / (float)(_q->m-1)*_dphi_max;
        unsigned int k;
        for (k=0; k<_q->n; k++) {
            TC v_prime = _v[k] * cexpf(-_Complex_I*k*_q->dphi[i]);
            bsequence_push(_q->sync_i[i], crealf(v_prime)>0);
            bsequence_push(_q->sync_q[i], cimagf(v_prime)>0);
        }
    }

    // allocate memory for cross-correlation
    _q->rxy = (float*) malloc( _q->m*sizeof(float) );

    // reset object
    BPRESYNC(_reset)(_q);

    return _q;
}
Example #20
0
void rweone_ssh(
    sf_complex *v,
    float w,
    float *aa)
/*< space-domain phase shift >*/
{
    int ig;
    sf_complex ikz;

    for(ig=0;ig<ag.n;ig++) {
	ikz = sf_cmplx(0.,w * aa[ig]);
#ifdef SF_HAS_COMPLEX_H
	v[ig] *= cexpf( ikz * at.d );
#else
	v[ig] = sf_cmul(v[ig],cexpf(sf_crmul( ikz, at.d )));
#endif
    }
}
int main() {
    unsigned int m=5;           // filter semi-length
    float fc=0.2f;              // input tone frequency
    unsigned int N=128;         // number of input samples
    float As=60.0f;             // stop-band attenuation [dB]

    // create/print the half-band resampler, centered on
    // tone frequency with a specified stop-band attenuation
    resamp2_cccf f = resamp2_cccf_create(m,fc,As);
    resamp2_cccf_print(f);

    // open output file
    FILE*fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s: auto-generated file\n",OUTPUT_FILENAME);
    fprintf(fid,"clear all;\nclose all;\n\n");
    fprintf(fid,"h_len=%u;\n", 4*m+1);
    fprintf(fid,"N=%u;\n", N);

    unsigned int i;
    float theta=0.0f, dtheta=2*M_PI*fc;
    float complex x, y[2];
    for (i=0; i<N; i++) {
        // generate input : complex sinusoid
        x = cexpf(_Complex_I*theta) * (i<N/2 ? 2.0f*1.8534f*hamming(i,N/2) : 0.0f);
        theta += dtheta;

        // run the interpolator
        resamp2_cccf_interp_execute(f, x, y);

        // save results to output file
        fprintf(fid,"x(%3u) = %12.4e + j*%12.4e;\n", i+1,   crealf(x),    cimagf(x));
        fprintf(fid,"y(%3u) = %12.4e + j*%12.4e;\n", 2*i+1, crealf(y[0]), cimagf(y[0]));
        fprintf(fid,"y(%3u) = %12.4e + j*%12.4e;\n", 2*i+2, crealf(y[1]), cimagf(y[1]));

        printf("y(%3u) = %8.4f + j*%8.4f;\n", 2*i+1, crealf(y[0]), cimagf(y[0]));
        printf("y(%3u) = %8.4f + j*%8.4f;\n", 2*i+2, crealf(y[1]), cimagf(y[1]));
    }

    fprintf(fid,"nfft=512;\n");
    fprintf(fid,"X=20*log10(abs(fftshift(fft(x/N,    nfft))));\n");
    fprintf(fid,"Y=20*log10(abs(fftshift(fft(y/(2*N),nfft))));\n");
    fprintf(fid,"f=[0:(nfft-1)]/nfft-0.5;\n");
    fprintf(fid,"figure; plot(f/2,X,'Color',[0.5 0.5 0.5],f,Y,'LineWidth',2);\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"xlabel('normalized frequency');\n");
    fprintf(fid,"ylabel('PSD [dB]');\n");
    fprintf(fid,"legend('original','interpolated',1);");
    fprintf(fid,"axis([-0.5 0.5 -100 10]);\n");

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

    // clean up allocated objects
    resamp2_cccf_destroy(f);
    printf("done.\n");
    return 0;
}
Example #22
0
void rweone_ssf(
    sf_complex *v,
    float w,
    float *aa,
    float  a0)
/*< split-step Fourier correction >*/
{
    int ig;
    sf_complex ikz;

    for(ig=0; ig<ag.n; ig++) {	
	ikz = sf_cmplx(0.,w * (aa[ig] - a0));
#ifdef SF_HAS_COMPLEX_H
	v[ig] *= cexpf( ikz * ( at.d) );
#else
	v[ig] = sf_cmul(v[ig],cexpf(sf_crmul(ikz, at.d)));
#endif
    }
}
Example #23
0
void rweone_phs(
    sf_complex *v,
    float w,
    float a0,
    float b0
    )
/*< Fourier-domain phase shift >*/
{
    int ig,ikg;
    float kg;

    float a2,b2,k2;
    sf_complex iw,ikt,w2;

    a2 = a0*a0;
    b2 = b0*b0;

    iw = sf_cmplx(2e-3,-w);
#ifdef SF_HAS_COMPLEX_H
    w2 = iw*iw;
#else
    w2 = sf_cmul(iw,iw);
#endif

    rweone_fft(false,(kiss_fft_cpx*) v);

    for(ig=0;ig<ag.n;ig++) {
	ikg = KMAP(ig,ag.n);
	kg = okg + ikg * dkg;
	k2 = kg*kg;
	
#ifdef SF_HAS_COMPLEX_H
	ikt = csqrtf( w2*a2 + k2*b2 );
	v[ig] *= cexpf(-ikt*at.d);
#else
	ikt = csqrtf(sf_cadd(sf_crmul(w2,a2),sf_cmplx(k2*b2,0.)));
	v[ig] = sf_cmul(v[ig],cexpf(sf_crmul(ikt,-at.d)));
#endif
    }
    
    rweone_fft( true,(kiss_fft_cpx*) v);
}
Example #24
0
// Compute group delay for an IIR filter
//  _b      : filter coefficients array (numerator), [size: _nb x 1]
//  _nb     : filter length (numerator)
//  _a      : filter coefficients array (denominator), [size: _na x 1]
//  _na     : filter length (denominator)
//  _fc     : frequency at which delay is evaluated (-0.5 < _fc < 0.5)
float iir_group_delay(float * _b,
                      unsigned int _nb,
                      float * _a,
                      unsigned int _na,
                      float _fc)
{
    // validate input
    if (_nb == 0) {
        fprintf(stderr,"error: iir_group_delay(), numerator length must be greater than zero\n");
        exit(1);
    } else if (_na == 0) {
        fprintf(stderr,"error: iir_group_delay(), denominator length must be greater than zero\n");
        exit(1);
    } else if (_fc < -0.5 || _fc > 0.5) {
        fprintf(stderr,"error: iir_group_delay(), _fc must be in [-0.5,0.5]\n");
        exit(1);
    }

    // compute c = conv(b,fliplr(a))
    //         c(z) = b(z)*a(1/z)*z^(-_na)
    unsigned int nc = _na + _nb - 1;
    float c[nc];
    unsigned int i,j;
    for (i=0; i<nc; i++)
        c[i] = 0.0;

    for (i=0; i<_na; i++) {
        for (j=0; j<_nb; j++) {
            c[i+j] += conjf(_a[_na-i-1])*_b[j];
        }
    }

    // compute 
    //      sum(c[i] * exp(j 2 pi fc i) * i)
    //      --------------------------------
    //      sum(c[i] * exp(j 2 pi fc i))
    float complex t0=0.0f;
    float complex t1=0.0f;
    float complex c0;
    for (i=0; i<nc; i++) {
        c0  = c[i] * cexpf(_Complex_I*2*M_PI*_fc*i);
        t0 += c0*i;
        t1 += c0;
    }

    // prevent divide-by-zero (check magnitude for tolerance range)
    float tol = 1e-5f;
    if (cabsf(t1)<tol)
        return 0.0f;

    // return result, scaled by length of denominator
    return crealf(t0/t1) - (_na - 1);
}
Example #25
0
// Compute relative out-of-band energy
//
//  _h      :   filter coefficients [size: _h_len x 1]
//  _h_len  :   filter length
//  _fc     :   analysis cut-off frequency
//  _nfft   :   fft size
float liquid_filter_energy(float *      _h,
                           unsigned int _h_len,
                           float        _fc,
                           unsigned int _nfft)
{
    // validate input
    if (_fc < 0.0f || _fc > 0.5f) {
        fprintf(stderr,"error: liquid_filter_energy(), cut-off frequency must be in [0,0.5]\n");
        exit(1);
    } else if (_h_len == 0) {
        fprintf(stderr,"error: liquid_filter_energy(), filter length must be greater than zero\n");
        exit(1);
    } else if (_nfft == 0) {
        fprintf(stderr,"error: liquid_filter_energy(), fft size must be greater than zero\n");
        exit(1);
    }

    // allocate memory for complex phasor
    float complex expjwt[_h_len];

    // initialize accumulators
    float e_total = 0.0f;       // total energy
    float e_stopband = 0.0f;    // stop-band energy

    // create dotprod object
    dotprod_crcf dp = dotprod_crcf_create(_h,_h_len);

    unsigned int i;
    unsigned int k;
    for (i=0; i<_nfft; i++) {
        float f = 0.5f * (float)i / (float)(_nfft);
        
        // initialize complex phasor
        for (k=0; k<_h_len; k++)
            expjwt[k] = cexpf(_Complex_I*2*M_PI*f*k);

        // compute vector dot product
        float complex v;
        dotprod_crcf_execute(dp, expjwt, &v);

        // accumulate output
        float e2 = crealf( v*conjf(v) );
        e_total += e2;
        e_stopband += (f >= _fc) ? e2 : 0.0f;
    }

    // destroy dotprod object
    dotprod_crcf_destroy(dp);

    // return energy ratio
    return e_stopband / e_total;
}
Example #26
0
// create firhilb object
//  _m      :   filter semi-length (delay: 2*m+1)
//  _As     :   stop-band attenuation [dB]
FIRHILB() FIRHILB(_create)(unsigned int _m,
                           float        _As)
{
    // validate firhilb inputs
    if (_m < 2) {
        fprintf(stderr,"error: firhilb_create(), filter semi-length (m) must be at least 2\n");
        exit(1);
    }

    // allocate memory for main object
    FIRHILB() q = (FIRHILB()) malloc(sizeof(struct FIRHILB(_s)));
    q->m  = _m;         // filter semi-length
    q->As = fabsf(_As); // stop-band attenuation

    // set filter length and allocate memory for coefficients
    q->h_len = 4*(q->m) + 1;
    q->h     = (T *)         malloc((q->h_len)*sizeof(T));
    q->hc    = (T complex *) malloc((q->h_len)*sizeof(T complex));

    // allocate memory for quadrature filter component
    q->hq_len = 2*(q->m);
    q->hq     = (T *) malloc((q->hq_len)*sizeof(T));

    // compute filter coefficients for half-band filter
    liquid_firdes_kaiser(q->h_len, 0.25f, q->As, 0.0f, q->h);

    // alternate sign of non-zero elements
    unsigned int i;
    for (i=0; i<q->h_len; i++) {
        float t = (float)i - (float)(q->h_len-1)/2.0f;
        q->hc[i] = q->h[i] * cexpf(_Complex_I*0.5f*M_PI*t);
        q->h[i]  = cimagf(q->hc[i]);
    }

    // resample, reverse direction
    unsigned int j=0;
    for (i=1; i<q->h_len; i+=2)
        q->hq[j++] = q->h[q->h_len - i - 1];

    // create windows for upper and lower polyphase filter branches
    q->w1 = WINDOW(_create)(2*(q->m));
    q->w0 = WINDOW(_create)(2*(q->m));
    WINDOW(_clear)(q->w0);
    WINDOW(_clear)(q->w1);

    // create internal dot product object
    q->dpq = DOTPROD(_create)(q->hq, q->hq_len);

    // reset internal state and return object
    FIRHILB(_reset)(q);
    return q;
}
Example #27
0
// Compute analog zeros, poles, gain of low-pass Butterworth
// filter, grouping complex conjugates together. If filter
// order is odd, the single real pole (-1) is at the end of
// the array.  There are no zeros for the analog Butterworth
// filter.  The gain is unity.
//  _n      :   filter order
//  _za     :   output analog zeros [length:  0]
//  _pa     :   output analog poles [length: _n]
//  _ka     :   output analog gain
void butter_azpkf(unsigned int _n,
                  liquid_float_complex * _za,
                  liquid_float_complex * _pa,
                  liquid_float_complex * _ka)
{
    unsigned int r = _n%2;
    unsigned int L = (_n - r)/2;
    
    unsigned int i;
    unsigned int k=0;
    for (i=0; i<L; i++) {
        float theta = (float)(2*(i+1) + _n - 1)*M_PI/(float)(2*_n);
        _pa[k++] = cexpf( _Complex_I*theta);
        _pa[k++] = cexpf(-_Complex_I*theta);
    }

    if (r) _pa[k++] = -1.0f;

    assert(k==_n);

    *_ka = 1.0;
}
Example #28
0
// 
// AUTOTEST: bsync_crcf/simple correlation with phase
//           offset
//
void xautotest_bsync_crcf_phase_15()
{
    // generate sequence (15-bit msequence)
    float h[15] = {
         1.0,  1.0,  1.0,  1.0, 
        -1.0,  1.0, -1.0,  1.0, 
         1.0, -1.0, -1.0,  1.0, 
        -1.0, -1.0, -1.0
    };
    float tol = 1e-3f;
    float theta = 0.3f;

    // generate synchronizer
    bsync_crcf fs = bsync_crcf_create(15,h);

    // 
    // run tests
    //
    unsigned int i;
    float complex rxy;

    // fill buffer with sequence
    for (i=0; i<15; i++)
        bsync_crcf_correlate(fs,h[i]*cexpf(_Complex_I*theta),&rxy);

    // correlation should be 1.0
    CONTEND_DELTA( crealf(rxy), 1.0f*cosf(theta), tol );
    CONTEND_DELTA( cimagf(rxy), 1.0f*sinf(theta), tol );

    // all other cross-correlations should be exactly -1/15
    for (i=0; i<14; i++) {
        bsync_crcf_correlate(fs,h[i]*cexpf(_Complex_I*theta),&rxy);
        CONTEND_DELTA( crealf(rxy), -1.0f/15.0f*cosf(theta), tol );
        CONTEND_DELTA( cimagf(rxy), -1.0f/15.0f*sinf(theta), tol );
    }

    // clean it up
    bsync_crcf_destroy(fs);
}
Example #29
0
void _fft(cplx buf[], cplx out[], int n, int step){
    int i;
    if (step < n) {
        _fft(out, buf, n, step * 2);
        _fft(out + step, buf + step, n, step * 2);

        for (i = 0; i < n; i += 2 * step){
                cplx t = cexpf(-I * PI * i / n) * out[i + step];
                buf[i / 2]     = out[i] + t;
                buf[(i + n)/2] = out[i] - t;
        }
    }
}
//
// test nco block mixing
//
void autotest_nco_block_mixing()
{
    // frequency, phase
    float f = 0.1f;
    float phi = M_PI;

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

    unsigned int i;

    // number of samples
    unsigned int num_samples = 1024;

    // store samples
    float complex * x = (float complex*)malloc(num_samples*sizeof(float complex));
    float complex * y = (float complex*)malloc(num_samples*sizeof(float complex));

    // generate complex sin/cos
    for (i=0; i<num_samples; i++)
        x[i] = cexpf(_Complex_I*(f*i + phi));

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

    // mix signal back to zero phase (in pieces)
    unsigned int num_remaining = num_samples;
    i = 0;
    while (num_remaining > 0) {
        unsigned int n = 7 < num_remaining ? 7 : num_remaining;
        nco_crcf_mix_block_down(p, &x[i], &y[i], n);

        i += n;
        num_remaining -= n;
    }

    // assert mixer output is correct
    for (i=0; i<num_samples; i++) {
        CONTEND_DELTA( crealf(y[i]), 1.0f, tol );
        CONTEND_DELTA( cimagf(y[i]), 0.0f, tol );
    }

    // free those buffers
    free(x);
    free(y);

    // destroy NCO object
    nco_crcf_destroy(p);
}