diff --git a/openair1/SIMULATION/TOOLS/multipath_channel.c b/openair1/SIMULATION/TOOLS/multipath_channel.c index aeaa4f811f..de12663f1f 100644 --- a/openair1/SIMULATION/TOOLS/multipath_channel.c +++ b/openair1/SIMULATION/TOOLS/multipath_channel.c @@ -28,147 +28,144 @@ uint8_t multipath_channel_nosigconv(channel_desc_t *desc) { - random_channel(desc,0); - return(1); + random_channel(desc, 0); + return (1); +} + +void interleave_channel_output(float **rx_sig_re, float **rx_sig_im, float **output_interleaved, int nb_rx, int num_samples) +{ + for (int i = 0; i < nb_rx; i++) { + for (int j = 0; j < num_samples; j++) { + output_interleaved[i][2 * j] = rx_sig_re[i][j]; + output_interleaved[i][2 * j + 1] = rx_sig_im[i][j]; + } + } } //#define CHANNEL_SSE + #ifdef CHANNEL_SSE -void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *desc, - double tx_sig_re[NB_ANTENNAS_TX][30720*2], - double tx_sig_im[NB_ANTENANS_TX][30720*2], - double rx_sig_re[NB_ANTENNAS_RX][30720*2], - double rx_sig_im[NB_ANTENNAS_RX][30720*2], - uint32_t length, - uint8_t keep_channel, - int log_channel) +void __attribute__((no_sanitize_address)) multipath_channel(channel_desc_t *desc, + double **tx_sig_re, + double **tx_sig_im, + double **rx_sig_re, + double **rx_sig_im, + uint32_t length, + uint8_t keep_channel, + int log_channel) { + int i, ii, j, l; + // int simd_length; + // int simd_length, tail_start; + simde__m128d rx_tmp128_re, rx_tmp128_im, tx128_re, tx128_im, ch128_r, ch128_i, pathloss128; - int i,ii,j,l; - int length1, length2, tail; - simde__m128d rx_tmp128_re_f, rx_tmp128_im_f, rx_tmp128_re, rx_tmp128_im, rx_tmp128_1, rx_tmp128_2, rx_tmp128_3, rx_tmp128_4, - tx128_re, tx128_im, ch128_x, ch128_y, pathloss128; - - double path_loss = pow(10,desc->path_loss_dB/20); + double path_loss = pow(10, desc->path_loss_dB / 20); uint64_t dd = desc->channel_offset; pathloss128 = simde_mm_set1_pd(path_loss); -#ifdef DEBUG_CH - printf("[CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %lu, len %d \n",keep_channel,path_loss,desc->path_loss_dB,desc->nb_rx,desc->nb_tx,dd,desc->channel_length); -#endif - - if (keep_channel) { - // do nothing - keep channel - } else { - random_channel(desc,0); + if (keep_channel == 0) { + random_channel(desc, 0); } - start_meas(&desc->convolution); + // simd_length = (length - dd) / 2; + // tail_start = simd_length * 2; -#ifdef DEBUG_CH + for (i = 0; i < (int)(length - dd); i += 2) { + for (ii = 0; ii < desc->nb_rx; ii++) { + rx_tmp128_re = simde_mm_setzero_pd(); + rx_tmp128_im = simde_mm_setzero_pd(); - for (int l = 0; l<(int)desc->channel_length; l++) { - printf("%p (%f,%f) ",desc->ch[0],desc->ch[0][l].x,desc->ch[0][l].y); - } - - printf("\n"); -#endif - - tail = ((int)length-dd)%2; - - if(tail) - length1 = ((int)length-dd)-1; - else - length1 = ((int)length-dd); - - length2 = length1/2; - - for (i=0; inb_rx; ii++) { - // rx_tmp.x = 0; - // rx_tmp.y = 0; - rx_tmp128_re_f = simde_mm_setzero_pd(); - rx_tmp128_im_f = simde_mm_setzero_pd(); - - for (j=0; jnb_tx; j++) { - for (l = 0; l<(int)desc->channel_length; l++) { - if ((i>=0) && (i-l)>=0) { //SIMD correct only if length1 > 2*channel_length...which is almost always satisfied - // tx.x = tx_sig_re[j][i-l]; - // tx.y = tx_sig_im[j][i-l]; - tx128_re = simde_mm_loadu_pd(&tx_sig_re[j][2 * i - l]); // tx_sig_re[j][i-l+1], tx_sig_re[j][i-l] - tx128_im = simde_mm_loadu_pd(&tx_sig_im[j][2 * i - l]); - } else { - //tx.x =0; - //tx.y =0; - tx128_re = simde_mm_setzero_pd(); - tx128_im = simde_mm_setzero_pd(); + for (i = 0; i < (int)(length - dd); i += 2) { + for (ii = 0; ii < desc->nb_rx; ii++) { + rx_tmp128_re = simde_mm_setzero_pd(); + rx_tmp128_im = simde_mm_setzero_pd(); + for (j = 0; j < desc->nb_tx; j++) { + for (l = 0; l < (int)desc->channel_length; l++) { + double tx_re[2] = {0.0, 0.0}, tx_im[2] = {0.0, 0.0}; + if ((i - l) >= 0) + tx_re[0] = tx_sig_re[j][i - l]; + if ((i + 1 - l) >= 0) + tx_re[1] = tx_sig_re[j][i + 1 - l]; + if ((i - l) >= 0) + tx_im[0] = tx_sig_im[j][i - l]; + if ((i + 1 - l) >= 0) + tx_im[1] = tx_sig_im[j][i + 1 - l]; + tx128_re = simde_mm_loadu_pd(tx_re); + tx128_im = simde_mm_loadu_pd(tx_im); + ch128_r = simde_mm_set1_pd(desc->ch[ii + (j * desc->nb_rx)][l].r); + ch128_i = simde_mm_set1_pd(desc->ch[ii + (j * desc->nb_rx)][l].i); + rx_tmp128_re = + simde_mm_add_pd(rx_tmp128_re, + simde_mm_sub_pd(simde_mm_mul_pd(tx128_re, ch128_r), simde_mm_mul_pd(tx128_im, ch128_i))); + rx_tmp128_im = + simde_mm_add_pd(rx_tmp128_im, + simde_mm_add_pd(simde_mm_mul_pd(tx128_re, ch128_i), simde_mm_mul_pd(tx128_im, ch128_r))); + } } - - ch128_x = simde_mm_set1_pd(desc->ch[ii + (j * desc->nb_rx)][l].x); - ch128_y = simde_mm_set1_pd(desc->ch[ii + (j * desc->nb_rx)][l].y); - // rx_tmp.x += (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].x) - (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].y); - // rx_tmp.y += (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].x) + (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].y); - rx_tmp128_1 = simde_mm_mul_pd(tx128_re, ch128_x); - rx_tmp128_2 = simde_mm_mul_pd(tx128_re, ch128_y); - rx_tmp128_3 = simde_mm_mul_pd(tx128_im, ch128_x); - rx_tmp128_4 = simde_mm_mul_pd(tx128_im, ch128_y); - rx_tmp128_re = simde_mm_sub_pd(rx_tmp128_1, rx_tmp128_4); - rx_tmp128_im = simde_mm_add_pd(rx_tmp128_2, rx_tmp128_3); - rx_tmp128_re_f = simde_mm_add_pd(rx_tmp128_re_f, rx_tmp128_re); - rx_tmp128_im_f = simde_mm_add_pd(rx_tmp128_im_f, rx_tmp128_im); - } //l - } // j - - //rx_sig_re[ii][i+dd] = rx_tmp.x*path_loss; - //rx_sig_im[ii][i+dd] = rx_tmp.y*path_loss; - rx_tmp128_re_f = simde_mm_mul_pd(rx_tmp128_re_f, pathloss128); - rx_tmp128_im_f = simde_mm_mul_pd(rx_tmp128_im_f, pathloss128); - simde_mm_storeu_pd(&rx_sig_re[ii][2 * i + dd], rx_tmp128_re_f); // max index: length-dd -1 + dd = length -1 - simde_mm_storeu_pd(&rx_sig_im[ii][2 * i + dd], rx_tmp128_im_f); - /* - if ((ii==0)&&((i%32)==0)) { - printf("%p %p %f,%f => %e,%e\n",rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]); + simde_mm_storeu_pd(&rx_sig_re[ii][i + dd], simde_mm_mul_pd(rx_tmp128_re, pathloss128)); + simde_mm_storeu_pd(&rx_sig_im[ii][i + dd], simde_mm_mul_pd(rx_tmp128_im, pathloss128)); + } } - */ - //rx_sig_re[ii][i] = sqrt(.5)*(tx_sig_re[0][i] + tx_sig_re[1][i]); - //rx_sig_im[ii][i] = sqrt(.5)*(tx_sig_im[0][i] + tx_sig_im[1][i]); - } // ii } // i - stop_meas(&desc->convolution); - + // Handle the final sample if the length is odd + if ((length - dd) % 2) { + int i_tail = length - dd - 1; + for (ii = 0; ii < desc->nb_rx; ii++) { + struct complexd rx_tmp = {0}; + for (j = 0; j < desc->nb_tx; j++) { + struct complexd *chan = desc->ch[ii + (j * desc->nb_rx)]; + for (l = 0; l < (int)desc->channel_length; l++) { + if ((i_tail - l) >= 0) { + struct complexd tx; + tx.r = tx_sig_re[j][i_tail - l]; + tx.i = tx_sig_im[j][i_tail - l]; + rx_tmp.r += (tx.r * chan[l].r) - (tx.i * chan[l].i); + rx_tmp.i += (tx.i * chan[l].r) + (tx.r * chan[l].i); + } + } + } + rx_sig_re[ii][i_tail + dd] = rx_tmp.r * path_loss; + rx_sig_im[ii][i_tail + dd] = rx_tmp.i * path_loss; + } + } } #else -void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *desc, - double *tx_sig_re[NB_ANTENNAS_TX], - double *tx_sig_im[NB_ANTENNAS_TX], - double *rx_sig_re[NB_ANTENNAS_RX], - double *rx_sig_im[NB_ANTENNAS_RX], - uint32_t length, - uint8_t keep_channel, - int log_channel) +void __attribute__((no_sanitize_address)) multipath_channel(channel_desc_t *desc, + double **tx_sig_re, + double **tx_sig_im, + double **rx_sig_re, + double **rx_sig_im, + uint32_t length, + uint8_t keep_channel, + int log_channel) { - - double path_loss = pow(10,desc->path_loss_dB/20); + double path_loss = pow(10, desc->path_loss_dB / 20); uint64_t dd = desc->channel_offset; #ifdef DEBUG_CH printf("[CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %lu, len %d \n", - keep_channel, path_loss, desc->path_loss_dB, desc->nb_rx, desc->nb_tx, dd, desc->channel_length); + keep_channel, + path_loss, + desc->path_loss_dB, + desc->nb_rx, + desc->nb_tx, + dd, + desc->channel_length); #endif if (keep_channel) { // do nothing - keep channel } else { - random_channel(desc,0); + random_channel(desc, 0); } #ifdef DEBUG_CH - for (int l = 0; l<(int)desc->channel_length; l++) { + for (int l = 0; l < (int)desc->channel_length; l++) { printf("ch[%i] = (%f, %f)\n", l, desc->ch[0][l].r, desc->ch[0][l].i); } #endif @@ -178,27 +175,27 @@ void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *des get_cexp_doppler(cexp_doppler, desc, length); } - for (int i=0; i<((int)length-dd); i++) { - for (int ii=0; iinb_rx; ii++) { - struct complexd rx_tmp={0}; - for (int j=0; jnb_tx; j++) { - struct complexd *chan=desc->ch[ii+(j*desc->nb_rx)]; - for (int l = 0; l<(int)desc->channel_length; l++) { - if ((i>=0) && (i-l)>=0) { + for (int i = 0; i < ((int)length - dd); i++) { + for (int ii = 0; ii < desc->nb_rx; ii++) { + struct complexd rx_tmp = {0}; + for (int j = 0; j < desc->nb_tx; j++) { + struct complexd *chan = desc->ch[ii + (j * desc->nb_rx)]; + for (int l = 0; l < (int)desc->channel_length; l++) { + if ((i >= 0) && (i - l) >= 0) { struct complexd tx; - tx.r = tx_sig_re[j][i-l]; - tx.i = tx_sig_im[j][i-l]; + tx.r = tx_sig_re[j][i - l]; + tx.i = tx_sig_im[j][i - l]; rx_tmp.r += (tx.r * chan[l].r) - (tx.i * chan[l].i); rx_tmp.i += (tx.i * chan[l].r) + (tx.r * chan[l].i); } - #if 0 +#if 0 if (i==0 && log_channel == 1) { printf("channel[%d][%d][%d] = %f dB \t(%e, %e)\n", ii, j, l, 10 * log10(pow(chan[l].r, 2.0) + pow(chan[l].i, 2.0)), chan[l].r, chan[l].i); } - #endif - } //l - } // j +#endif + } // l + } // j #if 0 if (desc->max_Doppler != 0.0) rx_tmp = cdMul(rx_tmp, cexp_doppler[i]); @@ -206,26 +203,190 @@ void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *des #ifdef DOPPLER_DEBUG printf("[k %2i] cexp_doppler = (%7.4f, %7.4f), abs(cexp_doppler) = %.4f\n", - i, - cexp_doppler[i].r, - cexp_doppler[i].i, - sqrt(cexp_doppler[i].r * cexp_doppler[i].r + cexp_doppler[i].i * cexp_doppler[i].i)); + i, + cexp_doppler[i].r, + cexp_doppler[i].i, + sqrt(cexp_doppler[i].r * cexp_doppler[i].r + cexp_doppler[i].i * cexp_doppler[i].i)); #endif - rx_sig_re[ii][i+dd] = rx_tmp.r*path_loss; - rx_sig_im[ii][i+dd] = rx_tmp.i*path_loss; + rx_sig_re[ii][i + dd] = rx_tmp.r * path_loss; + rx_sig_im[ii][i + dd] = rx_tmp.i * path_loss; #ifdef DEBUG_CH - if ((i%32)==0) { - printf("rx aa %d: %f, %f => %e, %e\n", - ii, rx_tmp.r, rx_tmp.i, rx_sig_re[ii][i-dd], rx_sig_im[ii][i-dd]); - } -#endif - //rx_sig_re[ii][i] = sqrt(.5)*(tx_sig_re[0][i] + tx_sig_re[1][i]); - //rx_sig_im[ii][i] = sqrt(.5)*(tx_sig_im[0][i] + tx_sig_im[1][i]); + if ((i % 32) == 0) { + printf("rx aa %d: %f, %f => %e, %e\n", ii, rx_tmp.r, rx_tmp.i, rx_sig_re[ii][i - dd], rx_sig_im[ii][i - dd]); + } +#endif + // rx_sig_re[ii][i] = sqrt(.5)*(tx_sig_re[0][i] + tx_sig_re[1][i]); + // rx_sig_im[ii][i] = sqrt(.5)*(tx_sig_im[0][i] + tx_sig_im[1][i]); } // ii } // i } #endif +#ifdef CHANNEL_SSE +void __attribute__((no_sanitize_address)) multipath_channel_float(channel_desc_t *desc, + float **tx_sig_interleaved, + float **rx_sig_re, + float **rx_sig_im, + uint32_t length, + uint8_t keep_channel, + int log_channel) +{ + int i, ii, j, l; + simde__m128 rx_tmp128_re, rx_tmp128_im, tx128_re, tx128_im, ch128_r, ch128_i, pathloss128; + uint64_t dd = desc->channel_offset; + if (keep_channel == 0) { + random_channel(desc, 0); + } + + struct complexd cexp_doppler[length]; + if (desc->max_Doppler != 0.0) { + get_cexp_doppler(cexp_doppler, desc, length); + } + + if (dd >= length) { + return; // No samples to process + } + + for (i = 0; i <= (int)(length - dd) - 4; i += 4) { + for (ii = 0; ii < desc->nb_rx; ii++) { + rx_tmp128_re = simde_mm_setzero_ps(); + rx_tmp128_im = simde_mm_setzero_ps(); + + for (j = 0; j < desc->nb_tx; j++) { + for (l = 0; l < (int)desc->channel_length; l++) { + int idx = i - l; + if (idx >= 0) { + // Load 2 complex numbers (4 floats) => {I0, Q0, I1, Q1} + simde__m128 vec0 = simde_mm_loadu_ps(&tx_sig_interleaved[j][2 * idx]); + simde__m128 vec1 = simde_mm_loadu_ps(&tx_sig_interleaved[j][2 * (idx + 2)]); + tx128_re = simde_mm_shuffle_ps(vec0, vec1, SIMDE_MM_SHUFFLE(2, 0, 2, 0)); // {I0,I1,I2,I3} + tx128_im = simde_mm_shuffle_ps(vec0, vec1, SIMDE_MM_SHUFFLE(3, 1, 3, 1)); // {Q0,Q1,Q2,Q3} + } else { + tx128_re = simde_mm_setzero_ps(); + tx128_im = simde_mm_setzero_ps(); + } + + ch128_r = simde_mm_set1_ps((float)desc->ch[ii + (j * desc->nb_rx)][l].r); + ch128_i = simde_mm_set1_ps((float)desc->ch[ii + (j * desc->nb_rx)][l].i); + + // re = (tx_re * ch_r) - (tx_im * ch_i) + rx_tmp128_re = simde_mm_add_ps(rx_tmp128_re, + simde_mm_sub_ps(simde_mm_mul_ps(tx128_re, ch128_r), simde_mm_mul_ps(tx128_im, ch128_i))); + // im = (tx_re * ch_i) + (tx_im * ch_r) + rx_tmp128_im = simde_mm_add_ps(rx_tmp128_im, + simde_mm_add_ps(simde_mm_mul_ps(tx128_re, ch128_i), simde_mm_mul_ps(tx128_im, ch128_r))); + } + } + +#if 0 + if (desc->max_Doppler != 0.0) { + float doppler_re[4] = {(float)cexp_doppler[i].r, (float)cexp_doppler[i+1].r, (float)cexp_doppler[i+2].r, (float)cexp_doppler[i+3].r}; + float doppler_im[4] = {(float)cexp_doppler[i].i, (float)cexp_doppler[i+1].i, (float)cexp_doppler[i+2].i, (float)cexp_doppler[i+3].i}; + + simde__m128 doppler128_r = simde_mm_loadu_ps(doppler_re); + simde__m128 doppler128_i = simde_mm_loadu_ps(doppler_im); + + simde__m128 temp_re = rx_tmp128_re; + simde__m128 temp_im = rx_tmp128_im; + + rx_tmp128_re = simde_mm_sub_ps(simde_mm_mul_ps(temp_re, doppler128_r), simde_mm_mul_ps(temp_im, doppler128_i)); + rx_tmp128_im = simde_mm_add_ps(simde_mm_mul_ps(temp_im, doppler128_r), simde_mm_mul_ps(temp_re, doppler128_i)); + } +#endif + simde_mm_storeu_ps(&rx_sig_re[ii][i + dd], rx_tmp128_re); + simde_mm_storeu_ps(&rx_sig_im[ii][i + dd], rx_tmp128_im); + } + } + + // Handle remaining samples (tail loop) that are not a multiple of 4 + for (; i < (int)(length - dd); i++) { + for (ii = 0; ii < desc->nb_rx; ii++) { + struct complexf rx_tmp = {0.0f, 0.0f}; + for (j = 0; j < desc->nb_tx; j++) { + struct complexd *chan = desc->ch[ii + (j * desc->nb_rx)]; + for (l = 0; l < (int)desc->channel_length; l++) { + if ((i - l) >= 0) { + struct complexf tx; + tx.r = tx_sig_interleaved[j][2 * (i - l)]; + tx.i = tx_sig_interleaved[j][2 * (i - l) + 1]; + rx_tmp.r += (tx.r * (float)chan[l].r) - (tx.i * (float)chan[l].i); + rx_tmp.i += (tx.i * (float)chan[l].r) + (tx.r * (float)chan[l].i); + } + } + } +#if 0 + if (desc->max_Doppler != 0.0) { + struct complexf doppler_factor = {(float)cexp_doppler[i].r, (float)cexp_doppler[i].i}; + struct complexf temp = rx_tmp; + rx_tmp.r = (temp.r * doppler_factor.r) - (temp.i * doppler_factor.i); + rx_tmp.i = (temp.i * doppler_factor.r) + (temp.r * doppler_factor.i); + } +#endif + rx_sig_re[ii][i + dd] = rx_tmp.r; + rx_sig_im[ii][i + dd] = rx_tmp.i; + } + } +} + +#else +void multipath_channel_float(channel_desc_t *desc, + float **tx_sig_interleaved, + float **rx_sig_re, + float **rx_sig_im, + uint32_t length, + uint8_t keep_channel, + int log_channel) +{ + uint64_t dd = desc->channel_offset; + + if (keep_channel == 0) { + random_channel(desc, 0); + } + + struct complexd cexp_doppler[length]; + if (desc->max_Doppler != 0.0) { + get_cexp_doppler(cexp_doppler, desc, length); + } + + if (dd >= length) { + return; + } + + for (int i = 0; i < ((int)length - dd); i++) { + for (int ii = 0; ii < desc->nb_rx; ii++) { + struct complexf rx_tmp = {0.0f, 0.0f}; + + for (int j = 0; j < desc->nb_tx; j++) { + struct complexd *chan = desc->ch[ii + (j * desc->nb_rx)]; + + for (int l = 0; l < (int)desc->channel_length; l++) { + if ((i - l) >= 0) { + struct complexf tx; + tx.r = tx_sig_interleaved[j][2 * (i - l)]; + tx.i = tx_sig_interleaved[j][2 * (i - l) + 1]; + rx_tmp.r += (tx.r * (float)chan[l].r) - (tx.i * (float)chan[l].i); + rx_tmp.i += (tx.i * (float)chan[l].r) + (tx.r * (float)chan[l].i); + } + } // l (channel_length) + } // j (nb_tx) + +#if 0 + if (desc->max_Doppler != 0.0) { + // Perform complex multiplication: rx_tmp = rx_tmp * cexp_doppler[i] + struct complexf doppler_factor = {(float)cexp_doppler[i].r, (float)cexp_doppler[i].i}; + struct complexf temp = rx_tmp; + rx_tmp.r = (temp.r * doppler_factor.r) - (temp.i * doppler_factor.i); + rx_tmp.i = (temp.i * doppler_factor.r) + (temp.r * doppler_factor.i); + } +#endif + rx_sig_re[ii][i + dd] = rx_tmp.r; + rx_sig_im[ii][i + dd] = rx_tmp.i; + + } // ii (nb_rx) + } // i (length) +} + +#endif diff --git a/openair1/SIMULATION/TOOLS/phase_noise.c b/openair1/SIMULATION/TOOLS/phase_noise.c index 5bb6df3b5e..e443629ee1 100644 --- a/openair1/SIMULATION/TOOLS/phase_noise.c +++ b/openair1/SIMULATION/TOOLS/phase_noise.c @@ -22,12 +22,11 @@ #include #include "sim.h" - /* linear phase noise model */ void phase_noise(double ts, int16_t *InRe, int16_t *InIm) { - static uint64_t i=0; - double fd = 300;//0.01*30000 + static uint64_t i = 0; + double fd = 300; // 0.01*30000 double phase = (double)(i * fd * ts); c16_t rot = get_sin_cos(phase); c16_t val = {.r = *InRe, .i = *InIm}; @@ -61,3 +60,29 @@ void add_noise(c16_t **rxdata, } } } + +void add_noise_float(c16_t **rxdata, + const float **r_re, + const float **r_im, + const float sigma, + const int length, + const int slot_offset, + const double ts, + const int delay, + bool apply_phase_noise, + const uint8_t nb_antennas_rx) +{ + float sqrt_sigma_div2 = sqrtf(sigma / 2.0f); + + for (int i = 0; i < length; i++) { + for (int ap = 0; ap < nb_antennas_rx; ap++) { + c16_t *rxd = &rxdata[ap][slot_offset + i + delay]; + rxd->r = (int16_t)(r_re[ap][i] + (gaussZiggurat(0.0, 1.0) * sqrt_sigma_div2)); + rxd->i = (int16_t)(r_im[ap][i] + (gaussZiggurat(0.0, 1.0) * sqrt_sigma_div2)); + + if (apply_phase_noise) { + phase_noise(ts, &rxd->r, &rxd->i); + } + } + } +} diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index d31109a836..24f1c053f9 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -412,13 +412,39 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag); */ void multipath_channel(channel_desc_t *desc, - double *tx_sig_re[NB_ANTENNAS_TX], - double *tx_sig_im[NB_ANTENNAS_TX], - double *rx_sig_re[NB_ANTENNAS_RX], - double *rx_sig_im[NB_ANTENNAS_RX], + double **tx_sig_re, + double **tx_sig_im, + double **rx_sig_re, + double **rx_sig_im, uint32_t length, uint8_t keep_channel, int log_channel); + +void multipath_channel_float(channel_desc_t *desc, + float **tx_sig_interleaved, + float **rx_sig_re, + float **rx_sig_im, + uint32_t length, + uint8_t keep_channel, + int log_channel); + +void interleave_channel_output(float **rx_sig_re, + float **rx_sig_im, + float **output_interleaved, + int nb_rx, + int num_samples); + +void add_noise_float(c16_t **rxdata, + const float **r_re, + const float **r_im, + const float sigma2, + const int length, + const int slot_offset, + const double ts, + const int delay, + bool apply_phase_noise, + const uint8_t nb_antennas_rx); + /* \fn double compute_pbch_sinr(channel_desc_t *desc, channel_desc_t *desc_i1,