⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flat_rayleigh.cpp

📁 RayleighFiles: Rayleigh channel simulation
💻 CPP
字号:
/*****************************************************************************
 * Author: Christos Komninakis                                               *
 * Date: January 4, 2000.                                                    *
 * Content: C++ code file for the CLASS "flat_rayleigh".                     *
 *****************************************************************************/

#include "flat_rayleigh.h"

#define PI 3.14159265358979

/**************** Constructor ***************************************/
flat_rayleigh::flat_rayleigh(int seeed, double fD, double pwr, bool flag_indep)
{
	chan_seed = seeed; //-23;
	PWR = pwr;
	IndepFlag = flag_indep;
	chan_val = Complex(0.0, 0.0);
	K = 7; H = 7; H2 = 2*H;
	if (fD > 0.2) {
		cout << "Warning: Discrete Doppler fDT > 0.2, handled as fDT=0.2 exactly" << endl;
		I = 1;
	} else {
		I = (int) (0.2 / fD);
	}
	last_i = 0; IP = 0;
	int i, t, j, k;
  
	a = new double [K];
	b = new double [K];
	c = new double [K];
	d = new double [K];
	double A_o;
	st = new Complex* [3];
	for (i=0; i<3; i++){
		st[i] = new Complex [K];
	}
	sinc_matrix = new double* [I];
	for (i=0; i<I; i++){
		sinc_matrix[i] = new double [H2];
	}
	buff_f = new Complex [H2];

	/* Following are the values of a designed ROOT DOPPLER filter prototype,
	   consisting of K=7 biquads, with fD = 0.2 */

	a[0] = 0.98323218491754;    b[0] = 0.13953807910136;
	c[0] = -0.60134822489663;   d[0] = 0.48938674026073;
	a[1] = -0.58056307877395;   b[1] = 0.99977164701498;
	c[1] = -0.42846077703117;   d[1] = 0.24612477470991;
	a[2] = -0.50498097209321;   b[2] = 0.99986531836969;
	c[2] = -0.63050157648166;   d[2] = 0.9350218659307;
	a[3] = 0.20534422769486;    b[3] = 0.98691526068222;
	c[3] = -0.096351029308223;  d[3] = -0.060828833103004;
	a[4] = 1.2667005604552;     b[4] = 0.93699896920708;
	c[4] = -0.64949215100022;   d[4] = 0.80427856161307;
	a[5] = -0.60545728027338;   b[5] = 0.99998818741754;
	c[5] = -0.61939958040555;   d[5] = 0.99895172368533;
	a[6] = -0.29077222501287;   b[6] = 0.99832970528904;
	c[6] = -0.62124137243814;   d[6] = 0.98111826315356;
	A_o = 0.028241759549181;


	/* now really start */
	Ao = PWR * A_o / sqrt(2.0);
	/* produce the table storing all the values of the interpolating function,
	   windowed and in reversed order, so that filtering is straightforward */
	double scale = 0.0;
	for (i=0; i<I; i++) {
		for (j=0; j<H2; j++) {
			if ((i == 0) & (j == H)){
				sinc_matrix[i][j] = 1.0;
			} else {
				sinc_matrix[i][j] = sin(PI*(j-H)+(PI/I)*i) / (PI*(j-H)+(PI/I)*i) * 
						(0.5 - 0.5*cos(2.0*PI*(i+I*j)/(H2*I))); // windowed, Hanning			   //(0.54 - 0.46*cos(2.0*PI*(i+I*j)/(H2*I))); // windowed, Hamming
				//(0.42 - 0.5*cos(2.0*PI*(i+I*j)/(H2*I)) + 0.08*cos(4.0*PI*(i+I*j)/(H2*I))); // windowed, Blackman
			}
			scale += (sinc_matrix[i][j])*(sinc_matrix[i][j]);
		}
	}
	scale = sqrt(1.0/scale*I);
	// scale and swap
	double temp;
	for (i=0; i<I; i++) {
		for (j=0; j<H; j++) {
			temp = sinc_matrix[i][j];
			sinc_matrix[i][j] = scale * sinc_matrix[i][H2-1-j];
			sinc_matrix[i][H2-1-j] = scale * temp;
		}
	}
	sinc_matrix[0][H] *= scale;

	/* work the channel for some time, to overcome transients */
	for (t=0; t<I*4*(4*K+H2); t++) {
		if (last_i == I-1) {
			last_i = 0;

			/* now produce new element, and insert it into the buffer: buff_f[IP] */
			st[0][0] = Complex(Gaussian(&chan_seed), Gaussian(&chan_seed))*Ao -
						st[1][0]*c[0] - st[2][0]*d[0];
			for (k=1; k<K; k++){
				st[0][k] = st[0][k-1] + st[1][k-1]*a[k-1] + st[2][k-1]*b[k-1] -
				st[1][k]*c[k] - st[2][k]*d[k];
			}
			buff_f[IP] = st[0][K-1] + st[1][K-1]*a[K-1] + st[2][K-1]*b[K-1];
			for (k=0; k<K; k++) {
				st[2][k] = st[1][k];
				st[1][k] = st[0][k];
			}
			/* done, produced buff_f[IP], now move IP to next position */
			IP = (IP + 1) % H2;
		} else {
			last_i++;
		}
		// stop here, no need to interpolate, since idle run		
	}
}



/******* Function pass_through, without providing any CSI ************/
void flat_rayleigh::pass_through(int length, Complex *inp, Complex *outp)
{
	register int k, j, t;
	
	if (IndepFlag) {
		chan_seed += 1;	// reset the seed
		// clean-up and then run idle, to ensure transients are dead
		for (k=0; k<K; k++) {
			st[0][k] = Complex(0.0, 0.0);
			st[1][k] = Complex(0.0, 0.0);
			st[2][k] = Complex(0.0, 0.0);
		}
		for (j=0; j<H2; j++)
			buff_f[j] = Complex(0.0, 0.0);
		// and now run idle for a little...
		for (t=0; t<I*4*(4*K+H2); t++) {
			if (last_i == I-1) {
				last_i = 0;
				/* produce new element, and insert it into buff_f[IP] */
				st[0][0] = Complex( Gaussian(&chan_seed), Gaussian(&chan_seed) );
				st[0][0] = st[0][0]*Ao - st[1][0]*c[0] - st[2][0]*d[0];
				for (k=1; k<K; k++)
					st[0][k] = st[0][k-1] + st[1][k-1]*a[k-1] + st[2][k-1]*b[k-1] -
					st[1][k]*c[k] - st[2][k]*d[k];
				buff_f[IP] = st[0][K-1] + st[1][K-1]*a[K-1] + st[2][K-1]*b[K-1];
				for (k=0; k<K; k++) {
					st[2][k] = st[1][k];
					st[1][k] = st[0][k];
				}
				/* done, produced buff_f[IP], now move IP to next position */
				IP = (IP + 1) % H2;
			} else{
				last_i++;
			}
			// end here, don't produce chan_val, since idle run
		}
	} /* end of dry run for independence */

	/* run for real now */
	for (t=0; t<length; t++) {
		if (last_i == I-1) {
			last_i = 0;

			/* now produce new element, and insert it into the buffer: buff_f[IP] */
			st[0][0] = st[0][0] = Complex( Gaussian(&chan_seed), Gaussian(&chan_seed) );
			st[0][0] = st[0][0]*Ao - st[1][0]*c[0] - st[2][0]*d[0];
			for (k=1; k<K; k++){
				st[0][k] = st[0][k-1] + st[1][k-1]*a[k-1] + st[2][k-1]*b[k-1] -
				st[1][k]*c[k] - st[2][k]*d[k];
			}
			buff_f[IP] = st[0][K-1] + st[1][K-1]*a[K-1] + st[2][K-1]*b[K-1];
			for (k=0; k<K; k++) {
				st[2][k] = st[1][k];
				st[1][k] = st[0][k];
			}
			/* done, produced buff_f[IP], now move IP to next position */
			IP = (IP + 1) % H2;
		} else {
			last_i++;
		}

		buff_sinc = sinc_matrix[last_i];
		chan_val = Complex(0.0, 0.0);
		for (j=0; j<H2; j++){
			chan_val += buff_f[(IP + j) % H2] * buff_sinc[j];
		}
		outp[t] = inp[t] * chan_val;
	}
}



/******* Overloaded Function pass_through, providing CSI also ************/
void flat_rayleigh::pass_through(int length, Complex *inp,
                                  Complex *outp, Complex *csi)
{
	register int k, j, t;

	if (IndepFlag) {
		chan_seed += 1;	// reset the seed
		// clean-up and then run idle, to ensure transients are dead
		for (k=0; k<K; k++) {
			st[0][k] = Complex(0.0, 0.0);
			st[1][k] = Complex(0.0, 0.0);
			st[2][k] = Complex(0.0, 0.0);
		}
		for (j=0; j<H2; j++){
			buff_f[j] = Complex(0.0, 0.0);
		}
		// and now run idle for a little...
		for (t=0; t<I*4*(4*K+H2); t++) {
			if (last_i == I-1) {
				last_i = 0;
				/* produce new element, and insert it into buff_f[IP] */
				st[0][0] = Complex( Gaussian(&chan_seed), Gaussian(&chan_seed) );
				st[0][0] = st[0][0]*Ao - st[1][0]*c[0] - st[2][0]*d[0];
				for (k=1; k<K; k++){
					st[0][k] = st[0][k-1] + st[1][k-1]*a[k-1] + st[2][k-1]*b[k-1] -
					st[1][k]*c[k] - st[2][k]*d[k];
				}
				buff_f[IP] = st[0][K-1] + st[1][K-1]*a[K-1] + st[2][K-1]*b[K-1];
				for (k=0; k<K; k++) {
					st[2][k] = st[1][k];
					st[1][k] = st[0][k];
				}
				/* done, produced buff_f[IP], now move IP to next position */
				IP = (IP + 1) % H2;
			} else {
				last_i++;
			}
			// end here, don't produce chan_val, since idle run
		}
	} /* end of dry run for independence */
	
	for (t=0; t<length; t++) {
		if (last_i == I-1) {
			last_i = 0;

			/* now produce new element, and insert it into the buffer: buff_f[IP] */
			st[0][0] = Complex( Gaussian(&chan_seed), Gaussian(&chan_seed) )*Ao -
				st[1][0]*c[0] - st[2][0]*d[0];
			for (k=1; k<K; k++){
				st[0][k] = st[0][k-1] + st[1][k-1]*a[k-1] + st[2][k-1]*b[k-1] -
				st[1][k]*c[k] - st[2][k]*d[k];
			}
			buff_f[IP] = st[0][K-1] + st[1][K-1]*a[K-1] + st[2][K-1]*b[K-1];
			for (k=0; k<K; k++) {
				st[2][k] = st[1][k];
				st[1][k] = st[0][k];
			}
			/* done, produced buff_f[IP], now move IP to next position */
			IP = (IP + 1) % H2;
		} else {
			last_i++;
		}

		buff_sinc = sinc_matrix[last_i];
		chan_val = Complex(0.0, 0.0);
		for (j=0; j<H2; j++){
			chan_val += buff_f[(IP + j) % H2] * buff_sinc[j];
		}
		csi[t] = chan_val;
		outp[t] = inp[t] * chan_val;
	}
}



/***** Overloaded Function pass_through, providing AMPLITUDE CSI only *****/
void flat_rayleigh::pass_through(int length, Complex *inp,
                                 Complex *outp, double *amp_csi)
{
	register int k, j, t;
	
	if (IndepFlag) {
		chan_seed += 1;	// reset the seed
		// clean-up and then run idle, to ensure transients are dead
		for (k=0; k<K; k++) {
			st[0][k] = Complex(0.0, 0.0);
			st[1][k] = Complex(0.0, 0.0);
			st[2][k] = Complex(0.0, 0.0);
		}
		for (j=0; j<H2; j++){
			buff_f[j] = Complex(0.0, 0.0);
		}
		// and now run idle for a little...
		for (t=0; t<I*4*(4*K+H2); t++) {
			if (last_i == I-1) {
				last_i = 0;
				/* produce new element, and insert it into buff_f[IP] */
				st[0][0] = Complex( Gaussian(&chan_seed), Gaussian(&chan_seed) );
				st[0][0] = st[0][0]*Ao - st[1][0]*c[0] - st[2][0]*d[0];
				for (k=1; k<K; k++){
					st[0][k] = st[0][k-1] + st[1][k-1]*a[k-1] + st[2][k-1]*b[k-1] -
					st[1][k]*c[k] - st[2][k]*d[k];
				}
				buff_f[IP] = st[0][K-1] + st[1][K-1]*a[K-1] + st[2][K-1]*b[K-1];
				for (k=0; k<K; k++) {
					st[2][k] = st[1][k];
					st[1][k] = st[0][k];
				}
				/* done, produced buff_f[IP], now move IP to next position */
				IP = (IP + 1) % H2;
			} else {
				last_i++;
			}
			// end here, don't produce chan_val, since idle run
		}
	} /* end of dry run for independence */

	for (t=0; t<length; t++) {
		if (last_i == I-1) {
			last_i = 0;

			/* now produce new element, and insert it into the buffer: buff_f[IP] */
			st[0][0] = Complex( Gaussian(&chan_seed), Gaussian(&chan_seed) )*Ao -
				st[1][0]*c[0] - st[2][0]*d[0];
			for (k=1; k<K; k++){
				st[0][k] = st[0][k-1] + st[1][k-1]*a[k-1] + st[2][k-1]*b[k-1] -
				st[1][k]*c[k] - st[2][k]*d[k];
			}
			buff_f[IP] = st[0][K-1] + st[1][K-1]*a[K-1] + st[2][K-1]*b[K-1];
			for (k=0; k<K; k++) {
				st[2][k] = st[1][k];
				st[1][k] = st[0][k];
			}
			/* done, produced buff_f[IP], now move IP to next position */
			IP = (IP + 1) % H2;
		} else {
			last_i++;
		}

		buff_sinc = sinc_matrix[last_i];
		chan_val = Complex(0.0, 0.0);
		for (j=0; j<H2; j++){
			chan_val += buff_f[(IP + j) % H2] * buff_sinc[j];
		}
		amp_csi[t] = sqrt(abs(chan_val));
		outp[t] = inp[t] * chan_val;
	}
}
    
    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -