read DBT from csv
This commit is contained in:
@@ -77,6 +77,7 @@
|
|||||||
#define CONFIG_STRING_MACRLC_BEAM_DURATION "beam_duration"
|
#define CONFIG_STRING_MACRLC_BEAM_DURATION "beam_duration"
|
||||||
#define CONFIG_STRING_MACRLC_BEAMS_PERIOD "beams_per_period"
|
#define CONFIG_STRING_MACRLC_BEAMS_PERIOD "beams_per_period"
|
||||||
#define CONFIG_STRING_MACRLC_BEAM_WEIGHTS_LIST "beam_weights"
|
#define CONFIG_STRING_MACRLC_BEAM_WEIGHTS_LIST "beam_weights"
|
||||||
|
#define CONFIG_STRING_MACRLC_DBT_FILE "dbt_file"
|
||||||
#define CONFIG_STRING_MACRLC_PUSCH_RSSI_THRESHOLD "pusch_RSSI_Threshold"
|
#define CONFIG_STRING_MACRLC_PUSCH_RSSI_THRESHOLD "pusch_RSSI_Threshold"
|
||||||
#define CONFIG_STRING_MACRLC_PUCCH_RSSI_THRESHOLD "pucch_RSSI_Threshold"
|
#define CONFIG_STRING_MACRLC_PUCCH_RSSI_THRESHOLD "pucch_RSSI_Threshold"
|
||||||
#define CONFIG_STRING_MACRLC_STATS_MAX_UE "stats_max_ue"
|
#define CONFIG_STRING_MACRLC_STATS_MAX_UE "stats_max_ue"
|
||||||
@@ -97,6 +98,7 @@
|
|||||||
#define HLP_MACRLC_AB "Flag to enable analog beamforming"
|
#define HLP_MACRLC_AB "Flag to enable analog beamforming"
|
||||||
#define HLP_MACRLC_BEAM_DURATION "number of consecutive slots for a given set of beams"
|
#define HLP_MACRLC_BEAM_DURATION "number of consecutive slots for a given set of beams"
|
||||||
#define HLP_MACRLC_BEAMS_PERIOD "set of beams that can be simultaneously allocated in a period"
|
#define HLP_MACRLC_BEAMS_PERIOD "set of beams that can be simultaneously allocated in a period"
|
||||||
|
#define HLP_MACRLC_DBT_FILE "File path to CSV file to read digital beamforming table"
|
||||||
#define HLP_MACRLC_PUSCH_RSSI_THRESHOLD "Limits PUSCH TPC commands based on RSSI to prevent ADC railing. Value range [-1280, 0], unit 0.1 dBm/dBFS"
|
#define HLP_MACRLC_PUSCH_RSSI_THRESHOLD "Limits PUSCH TPC commands based on RSSI to prevent ADC railing. Value range [-1280, 0], unit 0.1 dBm/dBFS"
|
||||||
#define HLP_MACRLC_PUCCH_RSSI_THRESHOLD "Limits PUCCH TPC commands based on RSSI to prevent ADC railing. Value range [-1280, 0], unit 0.1 dBm/dBFS"
|
#define HLP_MACRLC_PUCCH_RSSI_THRESHOLD "Limits PUCCH TPC commands based on RSSI to prevent ADC railing. Value range [-1280, 0], unit 0.1 dBm/dBFS"
|
||||||
#define HLP_MACRLC_STATS_MAX_UE "Maximum number of UEs before disabling periodical output (0 to disable)"
|
#define HLP_MACRLC_STATS_MAX_UE "Maximum number of UEs before disabling periodical output (0 to disable)"
|
||||||
@@ -147,6 +149,7 @@
|
|||||||
{CONFIG_STRING_MACRLC_BEAM_DURATION, HLP_MACRLC_BEAM_DURATION, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
|
{CONFIG_STRING_MACRLC_BEAM_DURATION, HLP_MACRLC_BEAM_DURATION, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
|
||||||
{CONFIG_STRING_MACRLC_BEAMS_PERIOD, HLP_MACRLC_BEAMS_PERIOD, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
|
{CONFIG_STRING_MACRLC_BEAMS_PERIOD, HLP_MACRLC_BEAMS_PERIOD, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
|
||||||
{CONFIG_STRING_MACRLC_BEAM_WEIGHTS_LIST, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY,0}, \
|
{CONFIG_STRING_MACRLC_BEAM_WEIGHTS_LIST, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY,0}, \
|
||||||
|
{CONFIG_STRING_MACRLC_DBT_FILE, HLP_MACRLC_DBT_FILE, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||||
{CONFIG_STRING_MACRLC_PUSCH_RSSI_THRESHOLD, HLP_MACRLC_PUSCH_RSSI_THRESHOLD, \
|
{CONFIG_STRING_MACRLC_PUSCH_RSSI_THRESHOLD, HLP_MACRLC_PUSCH_RSSI_THRESHOLD, \
|
||||||
0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
|
0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
|
||||||
{CONFIG_STRING_MACRLC_PUCCH_RSSI_THRESHOLD, HLP_MACRLC_PUCCH_RSSI_THRESHOLD, \
|
{CONFIG_STRING_MACRLC_PUCCH_RSSI_THRESHOLD, HLP_MACRLC_PUCCH_RSSI_THRESHOLD, \
|
||||||
@@ -195,9 +198,10 @@
|
|||||||
#define MACRLC_ANALOG_BEAM_DURATION_IDX 37
|
#define MACRLC_ANALOG_BEAM_DURATION_IDX 37
|
||||||
#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 38
|
#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 38
|
||||||
#define MACRLC_BEAMWEIGHTS_IDX 39
|
#define MACRLC_BEAMWEIGHTS_IDX 39
|
||||||
#define MACRLC_PUSCH_RSSI_THRES_IDX 40
|
#define MACRLC_DBT_FILE_IDX 40
|
||||||
#define MACRLC_PUCCH_RSSI_THRES_IDX 41
|
#define MACRLC_PUSCH_RSSI_THRES_IDX 41
|
||||||
#define MACRLC_STATS_MAX_UE_IDX 42
|
#define MACRLC_PUCCH_RSSI_THRES_IDX 42
|
||||||
|
#define MACRLC_STATS_MAX_UE_IDX 43
|
||||||
|
|
||||||
#define MACRLCPARAMS_CHECK { \
|
#define MACRLCPARAMS_CHECK { \
|
||||||
{ .s5 = { NULL } }, \
|
{ .s5 = { NULL } }, \
|
||||||
@@ -243,6 +247,7 @@
|
|||||||
{ .s5 = { NULL } }, \
|
{ .s5 = { NULL } }, \
|
||||||
{ .s5 = { NULL } }, \
|
{ .s5 = { NULL } }, \
|
||||||
{ .s5 = { NULL } }, \
|
{ .s5 = { NULL } }, \
|
||||||
|
{ .s5 = { NULL } }, \
|
||||||
{ .s2 = { config_check_intrange, {-1280, 0}} }, /* PUSCH RSSI threshold range */ \
|
{ .s2 = { config_check_intrange, {-1280, 0}} }, /* PUSCH RSSI threshold range */ \
|
||||||
{ .s2 = { config_check_intrange, {-1280, 0}} }, /* PUCCH RSSI threshold range */ \
|
{ .s2 = { config_check_intrange, {-1280, 0}} }, /* PUCCH RSSI threshold range */ \
|
||||||
{ .s5 = { NULL } }, \
|
{ .s5 = { NULL } }, \
|
||||||
|
|||||||
@@ -28,6 +28,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gnb_config.h"
|
#include "gnb_config.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <complex.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@@ -1361,6 +1364,97 @@ static void get_bwp_config(nr_mac_config_t *configuration, const NR_ServingCellC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool parse_complex_token(const char *tok, double complex *out)
|
||||||
|
{
|
||||||
|
double re = 0.0;
|
||||||
|
double im = 0.0;
|
||||||
|
if (sscanf(tok, "%lf%lfi", &re, &im) == 2 || sscanf(tok, "%lf%lfj", &re, &im) == 2) {
|
||||||
|
*out = re + I * im;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (sscanf(tok, "%lfi", &im) == 1 || sscanf(tok, "%lfj", &im) == 1) {
|
||||||
|
*out = I * im;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (sscanf(tok, "%lf", &re) == 1) {
|
||||||
|
*out = re;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double complex **read_dbt_from_csv(const char *filename,
|
||||||
|
int *num_beams,
|
||||||
|
int *num_weights_per_beam,
|
||||||
|
uint16_t **beam_ids)
|
||||||
|
{
|
||||||
|
FILE *fp = fopen(filename, "r");
|
||||||
|
AssertFatal(fp != NULL, "Failed to open DBT CSV file '%s'\n", filename);
|
||||||
|
|
||||||
|
char line[16384];
|
||||||
|
AssertFatal(fgets(line, sizeof(line), fp) != NULL, "Failed to read DBT CSV header from '%s'\n", filename);
|
||||||
|
|
||||||
|
int weights = 1;
|
||||||
|
for (char *p = line; *p; ++p)
|
||||||
|
if (*p == ',')
|
||||||
|
weights++;
|
||||||
|
weights -= 1; // first column is beam ID
|
||||||
|
AssertFatal(weights > 0, "DBT CSV '%s' has no weight columns\n", filename);
|
||||||
|
|
||||||
|
int beams = 0;
|
||||||
|
while (fgets(line, sizeof(line), fp))
|
||||||
|
beams++;
|
||||||
|
AssertFatal(beams > 0, "No DBT beam rows found in CSV file '%s'\n", filename);
|
||||||
|
|
||||||
|
rewind(fp);
|
||||||
|
AssertFatal(fgets(line, sizeof(line), fp) != NULL, "Failed to reread DBT CSV header from '%s'\n", filename);
|
||||||
|
|
||||||
|
double complex **table = calloc_or_fail(beams, sizeof(*table));
|
||||||
|
uint16_t *ids = calloc_or_fail(beams, sizeof(*ids));
|
||||||
|
|
||||||
|
int b = 0;
|
||||||
|
while (fgets(line, sizeof(line), fp)) {
|
||||||
|
line[strcspn(line, "\r\n")] = '\0';
|
||||||
|
char *saveptr = NULL;
|
||||||
|
char *tok = strtok_r(line, ",", &saveptr);
|
||||||
|
AssertFatal(tok != NULL, "Malformed DBT row %d in '%s'\n", b + 1, filename);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
char *endptr = NULL;
|
||||||
|
long beam_id = strtol(tok, &endptr, 10);
|
||||||
|
AssertFatal(endptr != tok && errno != ERANGE && *endptr == '\0' && beam_id >= 0 && beam_id <= UINT16_MAX,
|
||||||
|
"Invalid DBT beam id '%s' in file '%s', beam row %d\n",
|
||||||
|
tok,
|
||||||
|
filename,
|
||||||
|
b + 1);
|
||||||
|
ids[b] = (uint16_t)beam_id;
|
||||||
|
|
||||||
|
table[b] = calloc_or_fail(weights, sizeof(*table[b]));
|
||||||
|
for (int w = 0; w < weights; ++w) {
|
||||||
|
tok = strtok_r(NULL, ",", &saveptr);
|
||||||
|
AssertFatal(tok != NULL, "Missing DBT weight in file '%s', beam row %d column %d\n", filename, b + 1, w + 1);
|
||||||
|
AssertFatal(parse_complex_token(tok, &table[b][w]),
|
||||||
|
"Invalid DBT complex weight '%s' in file '%s', beam row %d column %d\n",
|
||||||
|
tok,
|
||||||
|
filename,
|
||||||
|
b + 1,
|
||||||
|
w + 1);
|
||||||
|
}
|
||||||
|
AssertFatal(strtok_r(NULL, ",", &saveptr) == NULL,
|
||||||
|
"Too many DBT columns in file '%s', beam row %d\n",
|
||||||
|
filename,
|
||||||
|
b + 1);
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
AssertFatal(b == beams, "Parsed %d DBT rows but counted %d in file '%s'\n", b, beams, filename);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
*num_beams = beams;
|
||||||
|
*num_weights_per_beam = weights;
|
||||||
|
*beam_ids = ids;
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||||
{
|
{
|
||||||
int j = 0;
|
int j = 0;
|
||||||
@@ -1620,6 +1714,16 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
|||||||
for (int b = 0; b < n; b++)
|
for (int b = 0; b < n; b++)
|
||||||
config.bw_list[b] = MacRLC_ParamList.paramarray[j][MACRLC_BEAMWEIGHTS_IDX].iptr[b];
|
config.bw_list[b] = MacRLC_ParamList.paramarray[j][MACRLC_BEAMWEIGHTS_IDX].iptr[b];
|
||||||
}
|
}
|
||||||
|
config.bt.num_beams = 0;
|
||||||
|
config.bt.num_weights_per_beam = 0;
|
||||||
|
config.bt.beam_ids = NULL;
|
||||||
|
config.bt.beam_weights = NULL;
|
||||||
|
char **fptr = MacRLC_ParamList.paramarray[j][MACRLC_DBT_FILE_IDX].strptr;
|
||||||
|
if (fptr && *fptr && **fptr != '\0') {
|
||||||
|
LOG_I(GNB_APP, "loading DBT table from file %s\n", *fptr);
|
||||||
|
config.bt.beam_weights =
|
||||||
|
read_dbt_from_csv(*fptr, &config.bt.num_beams, &config.bt.num_weights_per_beam, &config.bt.beam_ids);
|
||||||
|
}
|
||||||
// triggers also PHY initialization in case we have L1 via FAPI
|
// triggers also PHY initialization in case we have L1 via FAPI
|
||||||
nr_mac_config_scc(RC.nrmac[j], scc, &config);
|
nr_mac_config_scc(RC.nrmac[j], scc, &config);
|
||||||
} // for (j=0;j<RC.nb_nr_macrlc_inst;j++)
|
} // for (j=0;j<RC.nb_nr_macrlc_inst;j++)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <complex.h>
|
#include <complex.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -64,6 +65,41 @@ c16_t convert_precoder_weight(double complex c_in)
|
|||||||
return (c16_t) {.r = round(SHRT_MAX*creal(c_in)), .i = round(SHRT_MAX*cimag(c_in))};
|
return (c16_t) {.r = round(SHRT_MAX*creal(c_in)), .i = round(SHRT_MAX*cimag(c_in))};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_dbt_config(nfapi_nr_dbt_pdu_t *dbt)
|
||||||
|
{
|
||||||
|
if (!dbt || !dbt->dig_beam_list)
|
||||||
|
return;
|
||||||
|
for (int i = 0; i < dbt->num_dig_beams; ++i)
|
||||||
|
free(dbt->dig_beam_list[i].txru_list);
|
||||||
|
free(dbt->dig_beam_list);
|
||||||
|
dbt->dig_beam_list = NULL;
|
||||||
|
dbt->num_dig_beams = 0;
|
||||||
|
dbt->num_txrus = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_dbt_table(const nr_beam_table_t *bt)
|
||||||
|
{
|
||||||
|
if (!bt || bt->num_beams <= 0 || bt->num_weights_per_beam <= 0 || !bt->beam_weights)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOG_I(NR_MAC, "DBT dump: num_beams=%d num_weights_per_beam=%d\n", bt->num_beams, bt->num_weights_per_beam);
|
||||||
|
|
||||||
|
for (int b = 0; b < bt->num_beams; ++b) {
|
||||||
|
uint16_t beam_id = bt->beam_ids ? bt->beam_ids[b] : b;
|
||||||
|
const int max_line = 2048;
|
||||||
|
char line[max_line];
|
||||||
|
int off = snprintf(line, sizeof(line), "DBT beam[%d] id=%u:", b, beam_id);
|
||||||
|
for (int w = 0; w < bt->num_weights_per_beam && off > -1 && off < max_line - 1; ++w)
|
||||||
|
off += snprintf(line + off,
|
||||||
|
sizeof(line) - off,
|
||||||
|
" w[%d]=(%0.6f,%0.6f)",
|
||||||
|
w,
|
||||||
|
creal(bt->beam_weights[b][w]),
|
||||||
|
cimag(bt->beam_weights[b][w]));
|
||||||
|
LOG_I(NR_MAC, "%s\n", line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers)
|
void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers)
|
||||||
{
|
{
|
||||||
// num of allowed k1 and k2 according to 5.2.2.2.1-3 and -4 in 38.214
|
// num of allowed k1 and k2 according to 5.2.2.2.1-3 and -4 in 38.214
|
||||||
@@ -395,6 +431,45 @@ static void config_common(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, NR
|
|||||||
{
|
{
|
||||||
nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0];
|
nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0];
|
||||||
nrmac->common_channels[0].ServingCellConfigCommon = scc;
|
nrmac->common_channels[0].ServingCellConfigCommon = scc;
|
||||||
|
free_dbt_config(&cfg->dbt_config);
|
||||||
|
if (config->bt.num_beams > 0) {
|
||||||
|
AssertFatal(config->bt.beam_weights != NULL,
|
||||||
|
"DBT config invalid: num_beams=%d but beam_weights is NULL\n",
|
||||||
|
config->bt.num_beams);
|
||||||
|
AssertFatal(config->bt.num_weights_per_beam > 0,
|
||||||
|
"DBT config invalid: num_weights_per_beam=%d\n",
|
||||||
|
config->bt.num_weights_per_beam);
|
||||||
|
AssertFatal(config->bt.num_weights_per_beam <= UINT16_MAX,
|
||||||
|
"DBT num_weights_per_beam %d exceeds uint16 max\n",
|
||||||
|
config->bt.num_weights_per_beam);
|
||||||
|
AssertFatal(config->bt.num_beams <= UINT16_MAX,
|
||||||
|
"DBT num_beams %d exceeds uint16 max\n",
|
||||||
|
config->bt.num_beams);
|
||||||
|
|
||||||
|
cfg->dbt_config.num_dig_beams = (uint16_t)config->bt.num_beams;
|
||||||
|
cfg->dbt_config.num_txrus = (uint16_t)config->bt.num_weights_per_beam;
|
||||||
|
cfg->dbt_config.dig_beam_list = calloc_or_fail(cfg->dbt_config.num_dig_beams, sizeof(*cfg->dbt_config.dig_beam_list));
|
||||||
|
for (uint16_t b = 0; b < cfg->dbt_config.num_dig_beams; ++b) {
|
||||||
|
nfapi_nr_dig_beam_t *beam = &cfg->dbt_config.dig_beam_list[b];
|
||||||
|
beam->beam_idx = config->bt.beam_ids ? config->bt.beam_ids[b] : b;
|
||||||
|
beam->txru_list = calloc_or_fail(cfg->dbt_config.num_txrus, sizeof(*beam->txru_list));
|
||||||
|
for (uint16_t w = 0; w < cfg->dbt_config.num_txrus; ++w) {
|
||||||
|
float re = crealf(config->bt.beam_weights[b][w]);
|
||||||
|
float im = cimagf(config->bt.beam_weights[b][w]);
|
||||||
|
AssertFatal(re > -1.0f && re < 1.0f, "DBT real weight out of range [-1,1]: %f\n", re);
|
||||||
|
AssertFatal(im > -1.0f && im < 1.0f, "DBT imag weight out of range [-1,1]: %f\n", im);
|
||||||
|
c16_t q15 = convert_precoder_weight(config->bt.beam_weights[b][w]);
|
||||||
|
beam->txru_list[w].dig_beam_weight_Re = (uint16_t)q15.r;
|
||||||
|
beam->txru_list[w].dig_beam_weight_Im = (uint16_t)q15.i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_I(NR_MAC,
|
||||||
|
"Loaded DBT: num_beams=%d num_weights_per_beam=%d\n",
|
||||||
|
config->bt.num_beams,
|
||||||
|
config->bt.num_weights_per_beam);
|
||||||
|
log_dbt_table(&config->bt);
|
||||||
|
}
|
||||||
|
|
||||||
// Carrier configuration
|
// Carrier configuration
|
||||||
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
|
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <complex.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "common/utils/ds/seq_arr.h"
|
#include "common/utils/ds/seq_arr.h"
|
||||||
#include "common/utils/nr/nr_common.h"
|
#include "common/utils/nr/nr_common.h"
|
||||||
@@ -184,6 +185,13 @@ typedef enum {
|
|||||||
SSB_SINR,
|
SSB_SINR,
|
||||||
} nr_config_report_type_t;
|
} nr_config_report_type_t;
|
||||||
|
|
||||||
|
typedef struct nr_beam_table {
|
||||||
|
int num_weights_per_beam;
|
||||||
|
int num_beams;
|
||||||
|
uint16_t *beam_ids;
|
||||||
|
double complex **beam_weights;
|
||||||
|
} nr_beam_table_t;
|
||||||
|
|
||||||
typedef struct nr_mac_config_s {
|
typedef struct nr_mac_config_s {
|
||||||
nr_pdsch_AntennaPorts_t pdsch_AntennaPorts;
|
nr_pdsch_AntennaPorts_t pdsch_AntennaPorts;
|
||||||
int pusch_AntennaPorts;
|
int pusch_AntennaPorts;
|
||||||
@@ -213,6 +221,7 @@ typedef struct nr_mac_config_s {
|
|||||||
nr_redcap_config_t *redcap;
|
nr_redcap_config_t *redcap;
|
||||||
nr_ptrs_config_t *ptrs;
|
nr_ptrs_config_t *ptrs;
|
||||||
nr_config_report_type_t report_type;
|
nr_config_report_type_t report_type;
|
||||||
|
nr_beam_table_t bt;
|
||||||
} nr_mac_config_t;
|
} nr_mac_config_t;
|
||||||
|
|
||||||
typedef struct NR_preamble_ue {
|
typedef struct NR_preamble_ue {
|
||||||
|
|||||||
Reference in New Issue
Block a user