update
This commit is contained in:
@@ -13,10 +13,199 @@
|
||||
#include "nr_common.h"
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#define C_SRS_NUMBER (64)
|
||||
#define B_SRS_NUMBER (4)
|
||||
|
||||
void nr_pdsch_rank_capacity_scores(const float eigenvalues[NR_MAX_NB_LAYERS],
|
||||
uint8_t max_rank,
|
||||
float noise_power,
|
||||
float scores[NR_MAX_NB_LAYERS])
|
||||
{
|
||||
AssertFatal(max_rank >= 1 && max_rank <= NR_MAX_NB_LAYERS,
|
||||
"Invalid maximum PDSCH rank %u\n",
|
||||
max_rank);
|
||||
const float finite_noise = isfinite(noise_power) && noise_power > 0.0f ? noise_power : 1.0f;
|
||||
for (int rank = 1; rank <= NR_MAX_NB_LAYERS; rank++) {
|
||||
scores[rank - 1] = 0.0f;
|
||||
if (rank > max_rank)
|
||||
continue;
|
||||
for (int layer = 0; layer < rank; layer++) {
|
||||
const float eigenvalue = isfinite(eigenvalues[layer]) && eigenvalues[layer] > 0.0f
|
||||
? eigenvalues[layer]
|
||||
: 0.0f;
|
||||
scores[rank - 1] += log2f(1.0f + eigenvalue / (rank * finite_noise));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t nr_pdsch_select_rank(const float scores[NR_MAX_NB_LAYERS],
|
||||
uint8_t max_rank,
|
||||
float relative_margin)
|
||||
{
|
||||
AssertFatal(max_rank >= 1 && max_rank <= NR_MAX_NB_LAYERS,
|
||||
"Invalid maximum PDSCH rank %u\n",
|
||||
max_rank);
|
||||
const float margin = isfinite(relative_margin) && relative_margin > 0.0f ? relative_margin : 0.0f;
|
||||
uint8_t best_rank = 1;
|
||||
float best_score = isfinite(scores[0]) ? scores[0] : 0.0f;
|
||||
for (uint8_t rank = 2; rank <= max_rank; rank++) {
|
||||
const float candidate = isfinite(scores[rank - 1]) ? scores[rank - 1] : 0.0f;
|
||||
if (candidate > best_score * (1.0f + margin)) {
|
||||
best_rank = rank;
|
||||
best_score = candidate;
|
||||
}
|
||||
}
|
||||
return best_rank;
|
||||
}
|
||||
|
||||
uint8_t nr_type1_sp_4x1_i11_count(uint8_t layers)
|
||||
{
|
||||
switch (layers) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
return 16;
|
||||
case 7:
|
||||
case 8:
|
||||
return 8;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t nr_type1_sp_4x1_i13_count(uint8_t layers)
|
||||
{
|
||||
switch (layers) {
|
||||
case 1:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
return 1;
|
||||
case 2:
|
||||
return 4;
|
||||
case 3:
|
||||
case 4:
|
||||
return 3;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t nr_type1_sp_4x1_i2_count(uint8_t layers)
|
||||
{
|
||||
if (layers == 1)
|
||||
return 4;
|
||||
return layers >= 2 && layers <= 8 ? 2 : 0;
|
||||
}
|
||||
|
||||
bool nr_type1_sp_4x1_weights(uint8_t layers,
|
||||
uint8_t i11,
|
||||
uint8_t i13,
|
||||
uint8_t i2,
|
||||
c16_t weights[NR_MAX_NB_LAYERS][NR_MAX_CSI_PORTS])
|
||||
{
|
||||
memset(weights, 0, NR_MAX_NB_LAYERS * NR_MAX_CSI_PORTS * sizeof(**weights));
|
||||
const uint8_t i11_count = nr_type1_sp_4x1_i11_count(layers);
|
||||
const uint8_t i13_count = nr_type1_sp_4x1_i13_count(layers);
|
||||
const uint8_t i2_count = nr_type1_sp_4x1_i2_count(layers);
|
||||
if (i11_count == 0 || i11 >= i11_count || i13 >= i13_count || i2 >= i2_count)
|
||||
return false;
|
||||
|
||||
/* TS 38.214 Tables 5.2.2.2.1-5--12, specialized to the one-dimensional
|
||||
* N1=4 panel. O1=4, so adjacent orthogonal DFT beams are four indices
|
||||
* apart. Values 0..3 below encode 1, -1, phi, and -phi respectively. */
|
||||
uint8_t beam_offset[NR_MAX_NB_LAYERS] = {0};
|
||||
uint8_t polarization[NR_MAX_NB_LAYERS] = {0};
|
||||
switch (layers) {
|
||||
case 1:
|
||||
polarization[0] = 2;
|
||||
break;
|
||||
case 2:
|
||||
beam_offset[1] = 4 * i13;
|
||||
polarization[0] = 2;
|
||||
polarization[1] = 3;
|
||||
break;
|
||||
case 3:
|
||||
case 4: {
|
||||
const uint8_t offset = 4 * (i13 + 1);
|
||||
beam_offset[1] = offset;
|
||||
beam_offset[3] = offset;
|
||||
polarization[0] = 2;
|
||||
polarization[1] = 2;
|
||||
polarization[2] = 3;
|
||||
polarization[3] = 3;
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
const uint8_t offsets[] = {0, 0, 4, 4, 8};
|
||||
const uint8_t polarizations[] = {2, 3, 0, 1, 0};
|
||||
memcpy(beam_offset, offsets, sizeof(offsets));
|
||||
memcpy(polarization, polarizations, sizeof(polarizations));
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
const uint8_t offsets[] = {0, 0, 4, 4, 8, 8};
|
||||
const uint8_t polarizations[] = {2, 3, 2, 3, 0, 1};
|
||||
memcpy(beam_offset, offsets, sizeof(offsets));
|
||||
memcpy(polarization, polarizations, sizeof(polarizations));
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
const uint8_t offsets[] = {0, 0, 4, 8, 8, 12, 12};
|
||||
const uint8_t polarizations[] = {2, 3, 2, 0, 1, 0, 1};
|
||||
memcpy(beam_offset, offsets, sizeof(offsets));
|
||||
memcpy(polarization, polarizations, sizeof(polarizations));
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
const uint8_t offsets[] = {0, 0, 4, 4, 8, 8, 12, 12};
|
||||
const uint8_t polarizations[] = {2, 3, 2, 3, 0, 1, 0, 1};
|
||||
memcpy(beam_offset, offsets, sizeof(offsets));
|
||||
memcpy(polarization, polarizations, sizeof(polarizations));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const float scale = 1.0f / sqrtf((float)layers);
|
||||
const float phi_re = cosf((float)M_PI * i2 / 2.0f);
|
||||
const float phi_im = sinf((float)M_PI * i2 / 2.0f);
|
||||
for (int layer = 0; layer < layers; layer++) {
|
||||
const int beam = i11 + beam_offset[layer];
|
||||
float pol_re = 1.0f;
|
||||
float pol_im = 0.0f;
|
||||
switch (polarization[layer]) {
|
||||
case 1:
|
||||
pol_re = -1.0f;
|
||||
break;
|
||||
case 2:
|
||||
pol_re = phi_re;
|
||||
pol_im = phi_im;
|
||||
break;
|
||||
case 3:
|
||||
pol_re = -phi_re;
|
||||
pol_im = -phi_im;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int element = 0; element < 4; element++) {
|
||||
const float angle = 2.0f * (float)M_PI * element * beam / 16.0f;
|
||||
const float beam_re = cosf(angle);
|
||||
const float beam_im = sinf(angle);
|
||||
weights[layer][element].r = lrintf(SHRT_MAX * scale * beam_re);
|
||||
weights[layer][element].i = lrintf(SHRT_MAX * scale * beam_im);
|
||||
weights[layer][element + 4].r = lrintf(SHRT_MAX * scale * (pol_re * beam_re - pol_im * beam_im));
|
||||
weights[layer][element + 4].i = lrintf(SHRT_MAX * scale * (pol_re * beam_im + pol_im * beam_re));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* TS 38.211 Table 6.4.1.4.3-1: SRS bandwidth configuration */
|
||||
static const unsigned short srs_bandwidth_config[C_SRS_NUMBER][B_SRS_NUMBER][2] = {
|
||||
/* B_SRS = 0 B_SRS = 1 B_SRS = 2 B_SRS = 3 */
|
||||
|
||||
Reference in New Issue
Block a user