TDL channel model implementation for low, medium and high correlation scenarios

This commit is contained in:
Roberto Louro Magueta
2022-10-27 17:07:25 +01:00
committed by luis_pereira87
parent ac39d3b48c
commit 3d966b09e8
4 changed files with 190 additions and 30 deletions
@@ -31,7 +31,6 @@
uint8_t multipath_channel_nosigconv(channel_desc_t *desc)
{
random_channel(desc,0);
return(1);
}
@@ -163,7 +162,8 @@ void multipath_channel(channel_desc_t *desc,
dd = abs(desc->channel_offset);
#ifdef DEBUG_CH
printf("[CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %d, len %d \n",keep_channel,path_loss,desc->path_loss_dB,desc->nb_rx,desc->nb_tx,dd,desc->channel_length);
printf("[CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %d, 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) {
@@ -173,12 +173,9 @@ void multipath_channel(channel_desc_t *desc,
}
#ifdef DEBUG_CH
for (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("ch[%i] = (%f, %f)\n", l, desc->ch[0][l].r, desc->ch[0][l].i);
}
printf("\n");
#endif
for (i=0; i<((int)length-dd); i++) {
@@ -200,7 +197,8 @@ void multipath_channel(channel_desc_t *desc,
rx_tmp.i += (tx.i * desc->ch[ii+(j*desc->nb_rx)][l].r) + (tx.r * desc->ch[ii+(j*desc->nb_rx)][l].i);
if (i==0 && log_channel == 1) {
printf("channel[%d][%d][%d] = %f dB (%e,%e)\n",ii,j,l,10*log10(pow(desc->ch[ii+(j*desc->nb_rx)][l].r,2.0)+pow(desc->ch[ii+(j*desc->nb_rx)][l].i,2.0)),
printf("channel[%d][%d][%d] = %f dB \t(%e, %e)\n",
ii, j, l, 10*log10(pow(desc->ch[ii+(j*desc->nb_rx)][l].r,2.0)+pow(desc->ch[ii+(j*desc->nb_rx)][l].i,2.0)),
desc->ch[ii+(j*desc->nb_rx)][l].r,
desc->ch[ii+(j*desc->nb_rx)][l].i);
}
@@ -209,9 +207,10 @@ void multipath_channel(channel_desc_t *desc,
rx_sig_re[ii][i+dd] = rx_tmp.r*path_loss;
rx_sig_im[ii][i+dd] = rx_tmp.i*path_loss;
#ifdef DEBUG_CHANNEL
#ifdef DEBUG_CH
if ((i%32)==0) {
printf("rx aa %d: %p %p %f,%f => %e,%e\n",ii,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]);
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]);
+78 -20
View File
@@ -375,6 +375,7 @@ void tdlModel(int tdl_paths, double *tdl_delays, double *tdl_amps_dB, double DS
chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *));
chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *));
chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *));
chan_desc->ricean_factor = 1.0;
for (int i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd));
@@ -385,27 +386,69 @@ void tdlModel(int tdl_paths, double *tdl_delays, double *tdl_amps_dB, double DS
for (int i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd));
chan_desc->R_sqrt = (struct complexd **) malloc(tdl_pathsby3*sizeof(struct complexd **));
// FIXME: Remove this hardcoded value
chan_desc->corr_level = CORR_LEVEL_LOW;
if (nb_tx==2 && nb_rx==2) {
for (int i = 0; i<(tdl_pathsby3); i++)
chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0];
} else if (nb_tx==2 && nb_rx==1) {
for (int i = 0; i<(tdl_pathsby3); i++)
chan_desc->R_sqrt[i] = (struct complexd *) &R21_sqrt[i][0];
} else if (nb_tx==1 && nb_rx==2) {
for (int i = 0; i<(tdl_pathsby3); i++)
chan_desc->R_sqrt[i] = (struct complexd *) &R12_sqrt[i][0];
} else {
for (int i = 0; i<(tdl_pathsby3); i++) {
chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd));
for (int j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) {
chan_desc->R_sqrt[i][j].r = 1.0;
chan_desc->R_sqrt[i][j].i = 0.0;
int matrix_size = nb_tx*nb_rx;
double *correlation_matrix[matrix_size];
if (chan_desc->corr_level!=CORR_LEVEL_LOW) {
if (nb_rx==1 && nb_tx==2) {
for (int row = 0; row < matrix_size; row++) {
correlation_matrix[row] = R12_medium_high[row];
}
} else if (nb_rx==1 && nb_tx==4) {
for (int row = 0; row < matrix_size; row++) {
correlation_matrix[row] = R14_medium_high[row];
}
} else if (nb_rx==1 && nb_tx==8) {
for (int row = 0; row < matrix_size; row++) {
correlation_matrix[row] = R18_medium_high[row];
}
} else if (nb_rx==2 && nb_tx==2 && chan_desc->corr_level==CORR_LEVEL_MEDIUM) {
for (int row = 0; row < matrix_size; row++) {
correlation_matrix[row] = R22_medium[row];
}
} else if (nb_rx==2 && nb_tx==4 && chan_desc->corr_level==CORR_LEVEL_MEDIUM) {
for (int row = 0; row < matrix_size; row++) {
correlation_matrix[row] = R24_medium[row];
}
} else if (nb_rx==4 && nb_tx==4 && chan_desc->corr_level==CORR_LEVEL_MEDIUM) {
for (int row = 0; row < matrix_size; row++) {
correlation_matrix[row] = R44_medium[row];
}
} else if (nb_rx==2 && nb_tx==2 && chan_desc->corr_level==CORR_LEVEL_HIGH) {
for (int row = 0; row < matrix_size; row++) {
correlation_matrix[row] = R22_high[row];
}
} else if (nb_rx==2 && nb_tx==4 && chan_desc->corr_level==CORR_LEVEL_HIGH) {
for (int row = 0; row < matrix_size; row++) {
correlation_matrix[row] = R24_high[row];
}
} else if (nb_rx==4 && nb_tx==4 && chan_desc->corr_level==CORR_LEVEL_HIGH) {
for (int row = 0; row < matrix_size; row++) {
correlation_matrix[row] = R44_high[row];
}
} else {
for (int row = 0; row < matrix_size; row++) {
correlation_matrix[row] = NULL;
}
}
} else {
for (int row = 0; row < matrix_size; row++) {
correlation_matrix[row] = NULL;
}
}
LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx);
chan_desc->R_sqrt = (struct complexd **) malloc(matrix_size*sizeof(struct complexd **));
for (int row = 0; row < matrix_size; row++) {
chan_desc->R_sqrt[row] = (struct complexd *) calloc(1, matrix_size*sizeof(struct complexd));
if (correlation_matrix[row] == NULL) {
// TS 38.104 - Table G.2.3.1.2-4: MIMO correlation matrices for low correlation
chan_desc->R_sqrt[row][row].r = 1.0;
} else {
for (int col = 0; col < matrix_size; col++) {
chan_desc->R_sqrt[row][col].r = correlation_matrix[row][col];
}
}
}
}
@@ -1574,6 +1617,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
struct complexd phase, alpha, beta;
start_meas(&desc->random_channel);
bzero(acorr,desc->nb_tx*desc->nb_rx*sizeof(struct complexd));
for (i=0; i<(int)desc->nb_taps; i++) {
for (aarx=0; aarx<desc->nb_rx; aarx++) {
for (aatx=0; aatx<desc->nb_tx; aatx++) {
@@ -1612,8 +1657,21 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
*/
//apply correlation matrix
//compute acorr = R_sqrt[i] * anew
bzero(acorr,desc->nb_tx*desc->nb_rx*sizeof(struct complexd));
cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) desc->R_sqrt[i/3], (void *) anew, 1, (void *) acorr, 1);
if (desc->modelid >= TDL_A && desc->modelid <= TDL_E) {
for (aatx = 0; aatx < desc->nb_tx; aatx++) {
for (aarx=0; aarx<desc->nb_rx; aarx++) {
cblas_zaxpy(desc->nb_tx*desc->nb_rx,
(void *) &anew[aarx+(aatx*desc->nb_rx)],
(void *) desc->R_sqrt[aarx+(aatx*desc->nb_rx)],
1,
(void *) acorr,
1);
}
}
} else {
bzero(acorr,desc->nb_tx*desc->nb_rx*sizeof(struct complexd));
cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) desc->R_sqrt[i/3], (void *) anew, 1, (void *) acorr, 1);
}
/*
FIXME: Function cblas_zgemv has an undefined output (for the same input) after a second call in RHEL8 (acorr = nan)
+94
View File
@@ -43,3 +43,97 @@ static double R12_sqrt[6][8] = {
{0.991912, 0.000000,0.041738, -0.119870,0.041738, 0.119870,0.991912, 0.000000},
{0.968169, 0.000000,0.216594, -0.125443,0.216594, 0.125443,0.968169, 0.000000},
};
// TS 38.104 - Table G.2.3.1.2-2: MIMO correlation matrices for high correlation
static double R22_high[4][4] = {
{1.0, 0.9, 0.9, 0.81},
{0.9, 1.0, 0.81, 0.9},
{0.9, 0.81, 1.0, 0.9},
{0.81, 0.9, 0.9, 1}
};
static double R24_high[8][8] = {
{1.0000, 0.9883, 0.9542, 0.8999, 0.8999, 0.8894, 0.8587, 0.8099},
{0.9883, 1.0000, 0.9883, 0.9542, 0.8894, 0.8999, 0.8894, 0.8587},
{0.9542, 0.9883, 1.0000, 0.9883, 0.8587, 0.8894, 0.8999, 0.8894},
{0.8999, 0.9542, 0.9883, 1.0000, 0.8099, 0.8587, 0.8894, 0.8999},
{0.8999, 0.8894, 0.8587, 0.8099, 1.0000, 0.9883, 0.9542, 0.8999},
{0.8894, 0.8999, 0.8894, 0.8587, 0.9883, 1.0000, 0.9883, 0.9542},
{0.8587, 0.8894, 0.8999, 0.8894, 0.9542, 0.9883, 1.0000, 0.9883},
{0.8099, 0.8587, 0.8894, 0.8999, 0.8999, 0.9542, 0.9883, 1.0000}
};
static double R44_high[16][16] = {
{1.0000, 0.9882, 0.9541, 0.8999, 0.9882, 0.9767, 0.9430, 0.8894, 0.9541, 0.9430, 0.9105, 0.8587, 0.8999, 0.8894, 0.8587, 0.8099},
{0.9882, 1.0000, 0.9882, 0.9541, 0.9767, 0.9882, 0.9767, 0.9430, 0.9430, 0.9541, 0.9430, 0.9105, 0.8894, 0.8999, 0.8894, 0.8587},
{0.9541, 0.9882, 1.0000, 0.9882, 0.9430, 0.9767, 0.9882, 0.9767, 0.9105, 0.9430, 0.9541, 0.9430, 0.8587, 0.8894, 0.8999, 0.8894},
{0.8999, 0.9541, 0.9882, 1.0000, 0.8894, 0.9430, 0.9767, 0.9882, 0.8587, 0.9105, 0.9430, 0.9541, 0.8099, 0.8587, 0.8894, 0.8999},
{0.9882, 0.9767, 0.9430, 0.8894, 1.0000, 0.9882, 0.9541, 0.8999, 0.9882, 0.9767, 0.9430, 0.8894, 0.9541, 0.9430, 0.9105, 0.8587},
{0.9767, 0.9882, 0.9767, 0.9430, 0.9882, 1.0000, 0.9882, 0.9541, 0.9767, 0.9882, 0.9767, 0.9430, 0.9430, 0.9541, 0.9430, 0.9105},
{0.9430, 0.9767, 0.9882, 0.9767, 0.9541, 0.9882, 1.0000, 0.9882, 0.9430, 0.9767, 0.9882, 0.9767, 0.9105, 0.9430, 0.9541, 0.9430},
{0.8894, 0.9430, 0.9767, 0.9882, 0.8999, 0.9541, 0.9882, 1.0000, 0.8894, 0.9430, 0.9767, 0.9882, 0.8587, 0.9105, 0.9430, 0.9541},
{0.9541, 0.9430, 0.9105, 0.8587, 0.9882, 0.9767, 0.9430, 0.8894, 1.0000, 0.9882, 0.9541, 0.8999, 0.9882, 0.9767, 0.9430, 0.8894},
{0.9430, 0.9541, 0.9430, 0.9105, 0.9767, 0.9882, 0.9767, 0.9430, 0.9882, 1.0000, 0.9882, 0.9541, 0.9767, 0.9882, 0.9767, 0.9430},
{0.9105, 0.9430, 0.9541, 0.9430, 0.9430, 0.9767, 0.9882, 0.9767, 0.9541, 0.9882, 1.0000, 0.9882, 0.9430, 0.9767, 0.9882, 0.9767},
{0.8587, 0.9105, 0.9430, 0.9541, 0.8894, 0.9430, 0.9767, 0.9882, 0.8999, 0.9541, 0.9882, 1.0000, 0.8894, 0.9430, 0.9767, 0.9882},
{0.8999, 0.8894, 0.8587, 0.8099, 0.9541, 0.9430, 0.9105, 0.8587, 0.9882, 0.9767, 0.9430, 0.8894, 1.0000, 0.9882, 0.9541, 0.8999},
{0.8894, 0.8999, 0.8894, 0.8587, 0.9430, 0.9541, 0.9430, 0.9105, 0.9767, 0.9882, 0.9767, 0.9430, 0.9882, 1.0000, 0.9882, 0.9541},
{0.8587, 0.8894, 0.8999, 0.8894, 0.9105, 0.9430, 0.9541, 0.9430, 0.9430, 0.9767, 0.9882, 0.9767, 0.9541, 0.9882, 1.0000, 0.9882},
{0.8099, 0.8587, 0.8894, 0.8999, 0.8587, 0.9105, 0.9430, 0.9541, 0.8894, 0.9430, 0.9767, 0.9882, 0.8999, 0.9541, 0.9882, 1.0000}
};
// TS 38.104 - Table G.2.3.1.2-3: MIMO correlation matrices for medium correlation
static double R22_medium[4][4] = {
{1.0000, 0.9000, 0.3000, 0.2700},
{0.9000, 1.0000, 0.2700, 0.3000},
{0.3000, 0.2700, 1.0000, 0.9000},
{0.2700, 0.3000, 0.9000, 1.0000}
};
static double R24_medium[8][8] = {
{1.0000, 0.9884, 0.9543, 0.9000, 0.3000, 0.2965, 0.2863, 0.2700},
{0.9884, 1.0000, 0.9884, 0.9543, 0.2965, 0.3000, 0.2965, 0.2863},
{0.9543, 0.9884, 1.0000, 0.9884, 0.2863, 0.2965, 0.3000, 0.2965},
{0.9000, 0.9543, 0.9884, 1.0000, 0.2700, 0.2863, 0.2965, 0.3000},
{0.3000, 0.2965, 0.2863, 0.2700, 1.0000, 0.9884, 0.9543, 0.9000},
{0.2965, 0.3000, 0.2965, 0.2863, 0.9884, 1.0000, 0.9884, 0.9543},
{0.2863, 0.2965, 0.3000, 0.2965, 0.9543, 0.9884, 1.0000, 0.9884},
{0.2700, 0.2863, 0.2965, 0.3000, 0.9000, 0.9543, 0.9884, 1.0000}
};
static double R44_medium[16][16] = {
{1.0000, 0.9882, 0.9541, 0.8999, 0.8747, 0.8645, 0.8347, 0.7872, 0.5855, 0.5787, 0.5588, 0.5270, 0.3000, 0.2965, 0.2862, 0.2700},
{0.9882, 1.0000, 0.9882, 0.9541, 0.8645, 0.8747, 0.8645, 0.8347, 0.5787, 0.5855, 0.5787, 0.5588, 0.2965, 0.3000, 0.2965, 0.2862},
{0.9541, 0.9882, 1.0000, 0.9882, 0.8347, 0.8645, 0.8747, 0.8645, 0.5588, 0.5787, 0.5855, 0.5787, 0.2862, 0.2965, 0.3000, 0.2965},
{0.8999, 0.9541, 0.9882, 1.0000, 0.7872, 0.8347, 0.8645, 0.8747, 0.5270, 0.5588, 0.5787, 0.5855, 0.2700, 0.2862, 0.2965, 0.3000},
{0.8747, 0.8645, 0.8347, 0.7872, 1.0000, 0.9882, 0.9541, 0.8999, 0.8747, 0.8645, 0.8347, 0.7872, 0.5855, 0.5787, 0.5588, 0.5270},
{0.8645, 0.8747, 0.8645, 0.8347, 0.9882, 1.0000, 0.9882, 0.9541, 0.8645, 0.8747, 0.8645, 0.8347, 0.5787, 0.5855, 0.5787, 0.5588},
{0.8347, 0.8645, 0.8747, 0.8645, 0.9541, 0.9882, 1.0000, 0.9882, 0.8347, 0.8645, 0.8747, 0.8645, 0.5588, 0.5787, 0.5855, 0.5787},
{0.7872, 0.8347, 0.8645, 0.8747, 0.8999, 0.9541, 0.9882, 1.0000, 0.7872, 0.8347, 0.8645, 0.8747, 0.5270, 0.5588, 0.5787, 0.5855},
{0.5855, 0.5787, 0.5588, 0.5270, 0.8747, 0.8645, 0.8347, 0.7872, 1.0000, 0.9882, 0.9541, 0.8999, 0.8747, 0.8645, 0.8347, 0.7872},
{0.5787, 0.5855, 0.5787, 0.5588, 0.8645, 0.8747, 0.8645, 0.8347, 0.9882, 1.0000, 0.9882, 0.9541, 0.8645, 0.8747, 0.8645, 0.8347},
{0.5588, 0.5787, 0.5855, 0.5787, 0.8347, 0.8645, 0.8747, 0.8645, 0.9541, 0.9882, 1.0000, 0.9882, 0.8347, 0.8645, 0.8747, 0.8645},
{0.5270, 0.5588, 0.5787, 0.5855, 0.7872, 0.8347, 0.8645, 0.8747, 0.8999, 0.9541, 0.9882, 1.0000, 0.7872, 0.8347, 0.8645, 0.8747},
{0.3000, 0.2965, 0.2862, 0.2700, 0.5855, 0.5787, 0.5588, 0.5270, 0.8747, 0.8645, 0.8347, 0.7872, 1.0000, 0.9882, 0.9541, 0.8999},
{0.2965, 0.3000, 0.2965, 0.2862, 0.5787, 0.5855, 0.5787, 0.5588, 0.8645, 0.8747, 0.8645, 0.8347, 0.9882, 1.0000, 0.9882, 0.9541},
{0.2862, 0.2965, 0.3000, 0.2965, 0.5588, 0.5787, 0.5855, 0.5787, 0.8347, 0.8645, 0.8747, 0.8645, 0.9541, 0.9882, 1.0000, 0.9882},
{0.2700, 0.2862, 0.2965, 0.3000, 0.5270, 0.5588, 0.5787, 0.5855, 0.7872, 0.8347, 0.8645, 0.8747, 0.8999, 0.9541, 0.9882, 1.0000}
};
// Matrices computed based on TS 38.104 - Tables G.2.3.1.1-3 and G.2.3.1.2-1
static double R12_medium_high[2][2] = {
{1.0, 0.9},
{0.9, 1.0}
};
static double R14_medium_high[4][4] = {
{1.000000, 0.988362, 0.954253, 0.900000},
{0.988362, 1.000000, 0.988362, 0.954253},
{0.954253, 0.988362, 1.000000, 0.988362},
{0.900000, 0.954253, 0.988362, 1.000000},
};
static double R18_medium_high[8][8] = {
{1.000000, 0.997852, 0.991436, 0.980834, 0.966182, 0.947664, 0.925512, 0.900000},
{0.997852, 1.000000, 0.997852, 0.991436, 0.980834, 0.966182, 0.947664, 0.925512},
{0.991436, 0.997852, 1.000000, 0.997852, 0.991436, 0.980834, 0.966182, 0.947664},
{0.980834, 0.991436, 0.997852, 1.000000, 0.997852, 0.991436, 0.980834, 0.966182},
{0.966182, 0.980834, 0.991436, 0.997852, 1.000000, 0.997852, 0.991436, 0.980834},
{0.947664, 0.966182, 0.980834, 0.991436, 0.997852, 1.000000, 0.997852, 0.991436},
{0.925512, 0.947664, 0.966182, 0.980834, 0.991436, 0.997852, 1.000000, 0.997852},
{0.900000, 0.925512, 0.947664, 0.966182, 0.980834, 0.991436, 0.997852, 1.000000}
};
+10 -1
View File
@@ -50,6 +50,13 @@ typedef enum {
#define CHANMODEL_FREE_RSQRT_6 1<<1
#define CHANMODEL_FREE_RSQRT_NTAPS 1<<2
#define CHANMODEL_FREE_AMPS 1<<3
typedef enum {
CORR_LEVEL_LOW,
CORR_LEVEL_MEDIUM,
CORR_LEVEL_HIGH
} corr_level_t;
typedef struct {
///Number of tx antennas
uint8_t nb_tx;
@@ -75,8 +82,10 @@ typedef struct {
double channel_bandwidth;
///System sampling rate in Msps.
double sampling_rate;
///Ricean factor of first tap wrt other taps (0..1, where 0 means AWGN and 1 means Rayleigh channel).
///Ricean factor, sqrt(1/(K+1)), of first tap wrt other taps (0..1, where 0 means AWGN and 1 means Rayleigh channel).
double ricean_factor;
///Correlation level of correlation channel matrix
corr_level_t corr_level;
///Angle of arrival of wavefront (in radians). For Ricean channel only. This assumes that both RX and TX have linear antenna arrays with lambda/2 antenna spacing. Furhter it is assumed that the arrays are parallel to each other and that they are far enough apart so that we can safely assume plane wave propagation.
double aoa;
///If set to 1, aoa is randomized according to a uniform random distribution