Merge pull request #570 from softwareradiosystems/feature_256qam_fix

Resource allocation extended tables and PDSCH table 2 for 256QAM
master
Xavier Arteaga 6 years ago committed by GitHub
commit 5e49aca835
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -79,6 +79,7 @@ int mbsfn_area_id = -1;
char *rf_args = ""; char *rf_args = "";
char *rf_dev = ""; char *rf_dev = "";
float rf_amp = 0.8, rf_gain = 60.0, rf_freq = 2400000000; float rf_amp = 0.8, rf_gain = 60.0, rf_freq = 2400000000;
static bool enable_256qam = false;
float output_file_snr = +INFINITY; float output_file_snr = +INFINITY;
@ -145,13 +146,14 @@ void usage(char *prog) {
printf("\t-u listen TCP/UDP port for input data (if mbsfn is active then the stream is over mbsfn only) (-1 is random) [Default %d]\n", net_port); printf("\t-u listen TCP/UDP port for input data (if mbsfn is active then the stream is over mbsfn only) (-1 is random) [Default %d]\n", net_port);
printf("\t-v [set srslte_verbose to debug, default none]\n"); printf("\t-v [set srslte_verbose to debug, default none]\n");
printf("\t-s output file SNR [Default %f]\n", output_file_snr); printf("\t-s output file SNR [Default %f]\n", output_file_snr);
printf("\t-q Enable/Disable 256QAM modulation (default %s)\n", enable_256qam ? "enabled" : "disabled");
printf("\n"); printf("\n");
printf("\t*: See 3GPP 36.212 Table 5.3.3.1.5-4 for more information\n"); printf("\t*: See 3GPP 36.212 Table 5.3.3.1.5-4 for more information\n");
} }
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "IadglfmoncpvutxbwMsB")) != -1) { while ((opt = getopt(argc, argv, "IadglfmoncpqvutxbwMsB")) != -1) {
switch (opt) { switch (opt) {
case 'I': case 'I':
@ -208,6 +210,9 @@ void parse_args(int argc, char **argv) {
case 'B': case 'B':
mbsfn_sf_mask = atoi(argv[optind]); mbsfn_sf_mask = atoi(argv[optind]);
break; break;
case 'q':
enable_256qam ^= true;
break;
default: default:
usage(argv[0]); usage(argv[0]);
exit(-1); exit(-1);
@ -920,7 +925,7 @@ int main(int argc, char **argv) {
} }
/* Configure pdsch_cfg parameters */ /* Configure pdsch_cfg parameters */
if (srslte_ra_dl_dci_to_grant(&cell, &dl_sf, transmission_mode, &dci_dl, &pdsch_cfg.grant)) { if (srslte_ra_dl_dci_to_grant(&cell, &dl_sf, transmission_mode, enable_256qam, &dci_dl, &pdsch_cfg.grant)) {
ERROR("Error configuring PDSCH\n"); ERROR("Error configuring PDSCH\n");
exit(-1); exit(-1);
} }
@ -955,7 +960,7 @@ int main(int argc, char **argv) {
dci_dl.format = SRSLTE_DCI_FORMAT1; dci_dl.format = SRSLTE_DCI_FORMAT1;
/* Configure pdsch_cfg parameters */ /* Configure pdsch_cfg parameters */
if (srslte_ra_dl_dci_to_grant(&cell, &dl_sf, SRSLTE_TM1, &dci_dl, &pmch_cfg.pdsch_cfg.grant)) { if (srslte_ra_dl_dci_to_grant(&cell, &dl_sf, SRSLTE_TM1, enable_256qam, &dci_dl, &pmch_cfg.pdsch_cfg.grant)) {
ERROR("Error configuring PDSCH\n"); ERROR("Error configuring PDSCH\n");
exit(-1); exit(-1);
} }

@ -81,12 +81,12 @@ typedef struct {
int cpu_affinity; int cpu_affinity;
bool disable_plots; bool disable_plots;
bool disable_plots_except_constellation; bool disable_plots_except_constellation;
bool disable_cfo; bool disable_cfo;
uint32_t time_offset; uint32_t time_offset;
int force_N_id_2; int force_N_id_2;
uint16_t rnti; uint16_t rnti;
char *input_file_name; char *input_file_name;
int file_offset_time; int file_offset_time;
float file_offset_freq; float file_offset_freq;
uint32_t file_nof_prb; uint32_t file_nof_prb;
uint32_t file_nof_ports; uint32_t file_nof_ports;
@ -94,13 +94,13 @@ typedef struct {
bool enable_cfo_ref; bool enable_cfo_ref;
bool average_subframe; bool average_subframe;
char *rf_dev; char *rf_dev;
char *rf_args; char* rf_args;
uint32_t rf_nof_rx_ant; uint32_t rf_nof_rx_ant;
double rf_freq; double rf_freq;
float rf_gain; float rf_gain;
int net_port; int net_port;
char *net_address; char* net_address;
int net_port_signal; int net_port_signal;
char *net_address_signal; char *net_address_signal;
int decimate; int decimate;
int32_t mbsfn_area_id; int32_t mbsfn_area_id;
@ -109,31 +109,33 @@ typedef struct {
int tdd_special_sf; int tdd_special_sf;
int sf_config; int sf_config;
int verbose; int verbose;
bool enable_256qam;
}prog_args_t; }prog_args_t;
void args_default(prog_args_t* args) void args_default(prog_args_t* args)
{ {
args->disable_plots = false; args->disable_plots = false;
args->disable_plots_except_constellation = false; args->disable_plots_except_constellation = false;
args->nof_subframes = -1; args->nof_subframes = -1;
args->rnti = SRSLTE_SIRNTI; args->rnti = SRSLTE_SIRNTI;
args->force_N_id_2 = -1; // Pick the best args->force_N_id_2 = -1; // Pick the best
args->tdd_special_sf = -1; args->tdd_special_sf = -1;
args->sf_config = -1; args->sf_config = -1;
args->input_file_name = NULL; args->input_file_name = NULL;
args->disable_cfo = false; args->disable_cfo = false;
args->time_offset = 0; args->time_offset = 0;
args->file_nof_prb = 25; args->file_nof_prb = 25;
args->file_nof_ports = 1; args->file_nof_ports = 1;
args->file_cell_id = 0; args->file_cell_id = 0;
args->file_offset_time = 0; args->file_offset_time = 0;
args->file_offset_freq = 0; args->file_offset_freq = 0;
args->rf_dev = ""; args->rf_dev = "";
args->rf_args = ""; args->rf_args = "";
args->rf_freq = -1.0; args->rf_freq = -1.0;
args->rf_nof_rx_ant = 1; args->rf_nof_rx_ant = 1;
args->enable_cfo_ref = false; args->enable_cfo_ref = false;
args->average_subframe = false; args->average_subframe = false;
args->enable_256qam = false;
#ifdef ENABLE_AGC_DEFAULT #ifdef ENABLE_AGC_DEFAULT
args->rf_gain = -1.0; args->rf_gain = -1.0;
#else #else
@ -192,6 +194,7 @@ void usage(prog_args_t *args, char *prog) {
printf("\t-U remote TCP address to send data [Default %s]\n", args->net_address); printf("\t-U remote TCP address to send data [Default %s]\n", args->net_address);
printf("\t-M MBSFN area id [Default %d]\n", args->mbsfn_area_id); printf("\t-M MBSFN area id [Default %d]\n", args->mbsfn_area_id);
printf("\t-N Non-MBSFN region [Default %d]\n", args->non_mbsfn_region); printf("\t-N Non-MBSFN region [Default %d]\n", args->non_mbsfn_region);
printf("\t-q Enable/Disable 256QAM modulation (default %s)\n", args->enable_256qam ? "enabled" : "disabled");
printf("\t-v [set srslte_verbose to debug, default none]\n"); printf("\t-v [set srslte_verbose to debug, default none]\n");
} }
@ -199,7 +202,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
int opt; int opt;
args_default(args); args_default(args);
while ((opt = getopt(argc, argv, "adAogliIpPcOCtdDFRnvrfuUsSZyWMNBTG")) != -1) { while ((opt = getopt(argc, argv, "adAogliIpPcOCtdDFRqnvrfuUsSZyWMNBTG")) != -1) {
switch (opt) { switch (opt) {
case 'i': case 'i':
args->input_file_name = argv[optind]; args->input_file_name = argv[optind];
@ -301,6 +304,9 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
case 'B': case 'B':
args->mbsfn_sf_mask = atoi(argv[optind]); args->mbsfn_sf_mask = atoi(argv[optind]);
break; break;
case 'q':
args->enable_256qam ^= true;
break;
default: default:
usage(args, argv[0]); usage(args, argv[0]);
exit(-1); exit(-1);
@ -393,7 +399,7 @@ int main(int argc, char **argv) {
#endif /* ENABLE_GUI */ #endif /* ENABLE_GUI */
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
data[i] = srslte_vec_malloc(sizeof(uint8_t) * 1500 * 8); data[i] = srslte_vec_malloc(sizeof(uint8_t) * 2000 * 8);
if (!data[i]) { if (!data[i]) {
ERROR("Allocating data"); ERROR("Allocating data");
go_exit = true; go_exit = true;
@ -783,6 +789,7 @@ int main(int argc, char **argv) {
dl_sf.tti = tti; dl_sf.tti = tti;
dl_sf.sf_type = sf_type; dl_sf.sf_type = sf_type;
ue_dl_cfg.cfg.tm = (srslte_tm_t)tm; ue_dl_cfg.cfg.tm = (srslte_tm_t)tm;
ue_dl_cfg.pdsch_use_tbs_index_alt = prog_args.enable_256qam;
if ((ue_dl_cfg.cfg.tm == SRSLTE_TM1 && cell.nof_ports == 1) || if ((ue_dl_cfg.cfg.tm == SRSLTE_TM1 && cell.nof_ports == 1) ||
(ue_dl_cfg.cfg.tm > SRSLTE_TM1 && cell.nof_ports > 1)) { (ue_dl_cfg.cfg.tm > SRSLTE_TM1 && cell.nof_ports > 1)) {

@ -72,8 +72,8 @@ typedef struct SRSLTE_API {
float *csi[SRSLTE_MAX_CODEWORDS]; /* Channel Strengh Indicator */ float *csi[SRSLTE_MAX_CODEWORDS]; /* Channel Strengh Indicator */
/* tx & rx objects */ /* tx & rx objects */
srslte_modem_table_t mod[4]; srslte_modem_table_t mod[5];
// This is to generate the scrambling seq for multiple CRNTIs // This is to generate the scrambling seq for multiple CRNTIs
srslte_pdsch_user_t **users; srslte_pdsch_user_t **users;

@ -103,6 +103,8 @@ SRSLTE_API int srslte_ra_tbs_idx_from_mcs(uint32_t mcs, bool is_ul);
SRSLTE_API srslte_mod_t srslte_ra_dl_mod_from_mcs(uint32_t mcs); SRSLTE_API srslte_mod_t srslte_ra_dl_mod_from_mcs(uint32_t mcs);
SRSLTE_API srslte_mod_t srslte_ra_dl_mod_from_mcs2(uint32_t mcs);
SRSLTE_API srslte_mod_t srslte_ra_ul_mod_from_mcs(uint32_t mcs); SRSLTE_API srslte_mod_t srslte_ra_ul_mod_from_mcs(uint32_t mcs);
SRSLTE_API int srslte_ra_mcs_from_tbs_idx(uint32_t tbs_idx, bool is_ul); SRSLTE_API int srslte_ra_mcs_from_tbs_idx(uint32_t tbs_idx, bool is_ul);

@ -44,10 +44,11 @@
**************************************************/ **************************************************/
/** Functions to generate a grant from a received DCI */ /** Functions to generate a grant from a received DCI */
SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_cell_t* cell, SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_cell_t* cell,
srslte_dl_sf_cfg_t* sf, srslte_dl_sf_cfg_t* sf,
srslte_tm_t tm, srslte_tm_t tm,
srslte_dci_dl_t* dci, bool pdsch_use_tbs_index_alt,
srslte_dci_dl_t* dci,
srslte_pdsch_grant_t* grant); srslte_pdsch_grant_t* grant);
SRSLTE_API int srslte_ra_dl_grant_to_grant_prb_allocation(srslte_dci_dl_t* dci, SRSLTE_API int srslte_ra_dl_grant_to_grant_prb_allocation(srslte_dci_dl_t* dci,
@ -60,7 +61,7 @@ SRSLTE_API uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t* cell, uint32_t nof
SRSLTE_API uint32_t srslte_ra_dl_grant_nof_re(srslte_cell_t* cell, srslte_dl_sf_cfg_t* sf, srslte_pdsch_grant_t* grant); SRSLTE_API uint32_t srslte_ra_dl_grant_nof_re(srslte_cell_t* cell, srslte_dl_sf_cfg_t* sf, srslte_pdsch_grant_t* grant);
/** Others */ /** Others */
SRSLTE_API int srslte_dl_fill_ra_mcs(srslte_ra_tb_t* tb, int last_tbs, uint32_t nprb); SRSLTE_API int srslte_dl_fill_ra_mcs(srslte_ra_tb_t* tb, int last_tbs, uint32_t nprb, bool pdsch_use_tbs_index_alt);
SRSLTE_API void srslte_ra_dl_compute_nof_re(srslte_cell_t* cell, srslte_dl_sf_cfg_t* sf, srslte_pdsch_grant_t* grant); SRSLTE_API void srslte_ra_dl_compute_nof_re(srslte_cell_t* cell, srslte_dl_sf_cfg_t* sf, srslte_pdsch_grant_t* grant);

@ -121,6 +121,7 @@ typedef struct SRSLTE_API {
srslte_dci_cfg_t dci_cfg; srslte_dci_cfg_t dci_cfg;
uint32_t last_ri; uint32_t last_ri;
float snr_to_cqi_offset; float snr_to_cqi_offset;
bool pdsch_use_tbs_index_alt;
} srslte_ue_dl_cfg_t; } srslte_ue_dl_cfg_t;
typedef struct { typedef struct {

@ -31,7 +31,7 @@
#define Nc 1600 #define Nc 1600
#define MAX_SEQ_LEN (128*1024) #define MAX_SEQ_LEN (256 * 1024)
#define static_memory #define static_memory

@ -43,8 +43,8 @@ int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t *q, uint32_t nof_prb) {
if (q != NULL) { if (q != NULL) {
bzero(q, sizeof(srslte_softbuffer_rx_t)); bzero(q, sizeof(srslte_softbuffer_rx_t));
ret = srslte_ra_tbs_from_idx(26, nof_prb); ret = srslte_ra_tbs_from_idx(33, nof_prb);
if (ret != SRSLTE_ERROR) { if (ret != SRSLTE_ERROR) {
q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1; q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1;
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
@ -154,8 +154,8 @@ int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t *q, uint32_t nof_prb) {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_softbuffer_tx_t)); bzero(q, sizeof(srslte_softbuffer_tx_t));
ret = srslte_ra_tbs_from_idx(26, nof_prb); ret = srslte_ra_tbs_from_idx(33, nof_prb);
if (ret != SRSLTE_ERROR) { if (ret != SRSLTE_ERROR) {
q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1; q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1;

@ -212,32 +212,32 @@ inline void hard_qam256_demod(const cf_t* in, uint8_t* out, uint32_t N)
out[8 * s + 4] = 0x1; out[8 * s + 4] = 0x1;
out[8 * s + 6] = 0x1; out[8 * s + 6] = 0x1;
} else if ((__real__ in[s] > QAM256_THRESHOLD_6) || (__real__ in[s] < -QAM256_THRESHOLD_6)) { } else if ((__real__ in[s] > QAM256_THRESHOLD_6) || (__real__ in[s] < -QAM256_THRESHOLD_6)) {
out[6 * s + 2] = 0x1; out[8 * s + 2] = 0x1;
out[6 * s + 4] = 0x1; out[8 * s + 4] = 0x1;
out[8 * s + 6] = 0x0; out[8 * s + 6] = 0x0;
} else if ((__real__ in[s] > QAM256_THRESHOLD_5) || (__real__ in[s] < -QAM256_THRESHOLD_5)) { } else if ((__real__ in[s] > QAM256_THRESHOLD_5) || (__real__ in[s] < -QAM256_THRESHOLD_5)) {
out[6 * s + 2] = 0x1; out[8 * s + 2] = 0x1;
out[6 * s + 4] = 0x0; out[8 * s + 4] = 0x0;
out[8 * s + 6] = 0x0; out[8 * s + 6] = 0x0;
} else if ((__real__ in[s] > QAM256_THRESHOLD_4) || (__real__ in[s] < -QAM256_THRESHOLD_4)) { } else if ((__real__ in[s] > QAM256_THRESHOLD_4) || (__real__ in[s] < -QAM256_THRESHOLD_4)) {
out[6 * s + 2] = 0x1; out[8 * s + 2] = 0x1;
out[6 * s + 4] = 0x0; out[8 * s + 4] = 0x0;
out[8 * s + 6] = 0x1; out[8 * s + 6] = 0x1;
} else if ((__real__ in[s] > QAM256_THRESHOLD_3) || (__real__ in[s] < -QAM256_THRESHOLD_3)) { } else if ((__real__ in[s] > QAM256_THRESHOLD_3) || (__real__ in[s] < -QAM256_THRESHOLD_3)) {
out[6 * s + 2] = 0x0; out[8 * s + 2] = 0x0;
out[6 * s + 4] = 0x0; out[8 * s + 4] = 0x0;
out[8 * s + 6] = 0x1; out[8 * s + 6] = 0x1;
} else if ((__real__ in[s] > QAM256_THRESHOLD_2) || (__real__ in[s] < -QAM256_THRESHOLD_2)) { } else if ((__real__ in[s] > QAM256_THRESHOLD_2) || (__real__ in[s] < -QAM256_THRESHOLD_2)) {
out[6 * s + 2] = 0x0; out[8 * s + 2] = 0x0;
out[6 * s + 4] = 0x1; out[8 * s + 4] = 0x1;
out[8 * s + 6] = 0x1; out[8 * s + 6] = 0x1;
} else if ((__real__ in[s] > QAM256_THRESHOLD_1) || (__real__ in[s] < -QAM256_THRESHOLD_1)) { } else if ((__real__ in[s] > QAM256_THRESHOLD_1) || (__real__ in[s] < -QAM256_THRESHOLD_1)) {
out[6 * s + 2] = 0x0; out[8 * s + 2] = 0x0;
out[6 * s + 4] = 0x1; out[8 * s + 4] = 0x1;
out[8 * s + 6] = 0x0; out[8 * s + 6] = 0x0;
} else { } else {
out[6 * s + 2] = 0x0; out[8 * s + 2] = 0x0;
out[6 * s + 4] = 0x0; out[8 * s + 4] = 0x0;
out[8 * s + 6] = 0x0; out[8 * s + 6] = 0x0;
} }
@ -252,32 +252,32 @@ inline void hard_qam256_demod(const cf_t* in, uint8_t* out, uint32_t N)
out[8 * s + 5] = 0x1; out[8 * s + 5] = 0x1;
out[8 * s + 7] = 0x1; out[8 * s + 7] = 0x1;
} else if ((__imag__ in[s] > QAM256_THRESHOLD_6) || (__imag__ in[s] < -QAM256_THRESHOLD_6)) { } else if ((__imag__ in[s] > QAM256_THRESHOLD_6) || (__imag__ in[s] < -QAM256_THRESHOLD_6)) {
out[6 * s + 3] = 0x1; out[8 * s + 3] = 0x1;
out[6 * s + 5] = 0x1; out[8 * s + 5] = 0x1;
out[8 * s + 7] = 0x0; out[8 * s + 7] = 0x0;
} else if ((__imag__ in[s] > QAM256_THRESHOLD_5) || (__imag__ in[s] < -QAM256_THRESHOLD_5)) { } else if ((__imag__ in[s] > QAM256_THRESHOLD_5) || (__imag__ in[s] < -QAM256_THRESHOLD_5)) {
out[6 * s + 3] = 0x1; out[8 * s + 3] = 0x1;
out[6 * s + 5] = 0x0; out[8 * s + 5] = 0x0;
out[8 * s + 7] = 0x0; out[8 * s + 7] = 0x0;
} else if ((__imag__ in[s] > QAM256_THRESHOLD_4) || (__imag__ in[s] < -QAM256_THRESHOLD_4)) { } else if ((__imag__ in[s] > QAM256_THRESHOLD_4) || (__imag__ in[s] < -QAM256_THRESHOLD_4)) {
out[6 * s + 3] = 0x1; out[8 * s + 3] = 0x1;
out[6 * s + 5] = 0x0; out[8 * s + 5] = 0x0;
out[8 * s + 7] = 0x1; out[8 * s + 7] = 0x1;
} else if ((__imag__ in[s] > QAM256_THRESHOLD_3) || (__imag__ in[s] < -QAM256_THRESHOLD_3)) { } else if ((__imag__ in[s] > QAM256_THRESHOLD_3) || (__imag__ in[s] < -QAM256_THRESHOLD_3)) {
out[6 * s + 3] = 0x0; out[8 * s + 3] = 0x0;
out[6 * s + 5] = 0x0; out[8 * s + 5] = 0x0;
out[8 * s + 7] = 0x1; out[8 * s + 7] = 0x1;
} else if ((__imag__ in[s] > QAM256_THRESHOLD_2) || (__imag__ in[s] < -QAM256_THRESHOLD_2)) { } else if ((__imag__ in[s] > QAM256_THRESHOLD_2) || (__imag__ in[s] < -QAM256_THRESHOLD_2)) {
out[6 * s + 3] = 0x0; out[8 * s + 3] = 0x0;
out[6 * s + 5] = 0x1; out[8 * s + 5] = 0x1;
out[8 * s + 7] = 0x1; out[8 * s + 7] = 0x1;
} else if ((__imag__ in[s] > QAM256_THRESHOLD_1) || (__imag__ in[s] < -QAM256_THRESHOLD_1)) { } else if ((__imag__ in[s] > QAM256_THRESHOLD_1) || (__imag__ in[s] < -QAM256_THRESHOLD_1)) {
out[6 * s + 3] = 0x0; out[8 * s + 3] = 0x0;
out[6 * s + 5] = 0x1; out[8 * s + 5] = 0x1;
out[8 * s + 7] = 0x0; out[8 * s + 7] = 0x0;
} else { } else {
out[6 * s + 3] = 0x0; out[8 * s + 3] = 0x0;
out[6 * s + 5] = 0x0; out[8 * s + 5] = 0x0;
out[8 * s + 7] = 0x0; out[8 * s + 7] = 0x0;
} }
} }

@ -23,17 +23,17 @@
/* Assume perfect amplitude and phase alignment. /* Assume perfect amplitude and phase alignment.
* Check threshold values for real case * Check threshold values for real case
* or implement dynamic threshold adjustent as a function of received symbol amplitudes */ * or implement dynamic threshold adjustent as a function of received symbol amplitudes */
#define QAM16_THRESHOLD 2/sqrt(10) #define QAM16_THRESHOLD (2 / sqrtf(10))
#define QAM64_THRESHOLD_1 2/sqrt(42) #define QAM64_THRESHOLD_1 (2 / sqrtf(42))
#define QAM64_THRESHOLD_2 4/sqrt(42) #define QAM64_THRESHOLD_2 (4 / sqrtf(42))
#define QAM64_THRESHOLD_3 6/sqrt(42) #define QAM64_THRESHOLD_3 (6 / sqrtf(42))
#define QAM256_THRESHOLD_1 2 / sqrt(170) #define QAM256_THRESHOLD_1 (2 / sqrtf(170))
#define QAM256_THRESHOLD_2 4 / sqrt(170) #define QAM256_THRESHOLD_2 (4 / sqrtf(170))
#define QAM256_THRESHOLD_3 6 / sqrt(170) #define QAM256_THRESHOLD_3 (6 / sqrtf(170))
#define QAM256_THRESHOLD_4 8 / sqrt(170) #define QAM256_THRESHOLD_4 (8 / sqrtf(170))
#define QAM256_THRESHOLD_5 10 / sqrt(170) #define QAM256_THRESHOLD_5 (10 / sqrtf(170))
#define QAM256_THRESHOLD_6 12 / sqrt(170) #define QAM256_THRESHOLD_6 (12 / sqrtf(170))
#define QAM256_THRESHOLD_7 14 / sqrt(170) #define QAM256_THRESHOLD_7 (14 / sqrtf(170))
void hard_bpsk_demod(const cf_t* in, void hard_bpsk_demod(const cf_t* in,
uint8_t* out, uint8_t* out,

@ -29,13 +29,13 @@ add_test(modem_bpsk modem_test -n 1024 -m 1)
add_test(modem_qpsk modem_test -n 1024 -m 2) add_test(modem_qpsk modem_test -n 1024 -m 2)
add_test(modem_qam16 modem_test -n 1024 -m 4) add_test(modem_qam16 modem_test -n 1024 -m 4)
add_test(modem_qam64 modem_test -n 1008 -m 6) add_test(modem_qam64 modem_test -n 1008 -m 6)
#add_test(modem_qam256 modem_test -n 1024 -m 8) add_test(modem_qam256 modem_test -n 1024 -m 8)
add_test(modem_bpsk_soft modem_test -n 1024 -m 1) add_test(modem_bpsk_soft modem_test -n 1024 -m 1)
add_test(modem_qpsk_soft modem_test -n 1024 -m 2) add_test(modem_qpsk_soft modem_test -n 1024 -m 2)
add_test(modem_qam16_soft modem_test -n 1024 -m 4) add_test(modem_qam16_soft modem_test -n 1024 -m 4)
add_test(modem_qam64_soft modem_test -n 1008 -m 6) add_test(modem_qam64_soft modem_test -n 1008 -m 6)
#add_test(modem_qam256_soft modem_test -n 1024 -m 8) add_test(modem_qam256_soft modem_test -n 1024 -m 8)
add_executable(soft_demod_test soft_demod_test.c) add_executable(soft_demod_test soft_demod_test.c)
target_link_libraries(soft_demod_test srslte_phy) target_link_libraries(soft_demod_test srslte_phy)

@ -39,7 +39,7 @@ srslte_mod_t modulation = SRSLTE_MOD_BPSK;
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [nmse]\n", prog); printf("Usage: %s [nmse]\n", prog);
printf("\t-n num_bits [Default %d]\n", num_bits); printf("\t-n num_bits [Default %d]\n", num_bits);
printf("\t-m modulation (1: BPSK, 2: QPSK, 3: QAM16, 4: QAM64) [Default BPSK]\n"); printf("\t-m modulation (1: BPSK, 2: QPSK, 4: QAM16, 6: QAM64, 8: QAM256) [Default BPSK]\n");
} }
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
@ -68,7 +68,7 @@ void parse_args(int argc, char **argv) {
break; break;
default: default:
ERROR("Invalid modulation %d. Possible values: " ERROR("Invalid modulation %d. Possible values: "
"(1: BPSK, 2: QPSK, 3: QAM16, 4: QAM64)\n", "(1: BPSK, 2: QPSK, 4: QAM16, 6: QAM64, 8: QAM256)\n",
atoi(argv[optind])); atoi(argv[optind]));
break; break;
} }

@ -46,8 +46,8 @@ const static float pdsch_cfg_cell_specific_ratio_table[2][4] = {
/* One antenna port */ {1.0f / 1.0f, 4.0f / 5.0f, 3.0f / 5.0f, 2.0f / 5.0f}, /* One antenna port */ {1.0f / 1.0f, 4.0f / 5.0f, 3.0f / 5.0f, 2.0f / 5.0f},
/* Two or more antenna port */ {5.0f / 4.0f, 1.0f / 1.0f, 3.0f / 4.0f, 1.0f / 2.0f}}; /* Two or more antenna port */ {5.0f / 4.0f, 1.0f / 1.0f, 3.0f / 4.0f, 1.0f / 2.0f}};
const static srslte_mod_t modulations[4] = const static srslte_mod_t modulations[5] = {
{ SRSLTE_MOD_BPSK, SRSLTE_MOD_QPSK, SRSLTE_MOD_16QAM, SRSLTE_MOD_64QAM }; SRSLTE_MOD_BPSK, SRSLTE_MOD_QPSK, SRSLTE_MOD_16QAM, SRSLTE_MOD_64QAM, SRSLTE_MOD_256QAM};
typedef struct { typedef struct {
/* Thread identifier: they must set before thread creation */ /* Thread identifier: they must set before thread creation */
@ -247,7 +247,7 @@ static int pdsch_init(srslte_pdsch_t *q, uint32_t max_prb, bool is_ue, uint32_t
INFO("Init PDSCH: %d PRBs, max_symbols: %d\n", max_prb, q->max_re); INFO("Init PDSCH: %d PRBs, max_symbols: %d\n", max_prb, q->max_re);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 5; i++) {
if (srslte_modem_table_lte(&q->mod[i], modulations[i])) { if (srslte_modem_table_lte(&q->mod[i], modulations[i])) {
goto clean; goto clean;
} }
@ -261,7 +261,7 @@ static int pdsch_init(srslte_pdsch_t *q, uint32_t max_prb, bool is_ue, uint32_t
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
// Allocate int16_t for reception (LLRs) // Allocate int16_t for reception (LLRs)
q->e[i] = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)); q->e[i] = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_256QAM));
if (!q->e[i]) { if (!q->e[i]) {
goto clean; goto clean;
} }
@ -297,7 +297,7 @@ static int pdsch_init(srslte_pdsch_t *q, uint32_t max_prb, bool is_ue, uint32_t
goto clean; goto clean;
} }
if (srslte_sequence_init(&q->tmp_seq, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { if (srslte_sequence_init(&q->tmp_seq, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_256QAM))) {
goto clean; goto clean;
} }
@ -439,7 +439,7 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
srslte_sequence_free(&q->tmp_seq); srslte_sequence_free(&q->tmp_seq);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 5; i++) {
srslte_modem_table_free(&q->mod[i]); srslte_modem_table_free(&q->mod[i]);
} }
@ -485,7 +485,7 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) {
j, j,
2 * i, 2 * i,
q->cell.id, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_256QAM))) {
ERROR("Error initializing PDSCH scrambling sequence\n"); ERROR("Error initializing PDSCH scrambling sequence\n");
srslte_pdsch_free_rnti(q, rnti); srslte_pdsch_free_rnti(q, rnti);
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -589,6 +589,9 @@ static void csi_correction(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, uint32_t
case SRSLTE_MOD_64QAM: case SRSLTE_MOD_64QAM:
qm = 6; qm = 6;
break; break;
case SRSLTE_MOD_256QAM:
qm = 8;
break;
default: default:
ERROR("No modulation"); ERROR("No modulation");
} }
@ -656,6 +659,17 @@ static void csi_correction(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, uint32_t
break; break;
case SRSLTE_MOD_BPSK: case SRSLTE_MOD_BPSK:
break; break;
case SRSLTE_MOD_256QAM:
for (; i < cfg->grant.tb[tb_idx].nof_bits - 7; i += 8) {
__m128 _csi = _mm_set1_ps(*(csi_v++));
_csi = _mm_mul_ps(_csi, _csi_scale);
_e[0] = _mm_mulhi_pi16(_e[0], _mm_cvtps_pi16(_csi));
_e[1] = _mm_mulhi_pi16(_e[1], _mm_cvtps_pi16(_csi));
_e += 2;
}
break;
} }
i /= qm; i /= qm;

@ -397,8 +397,10 @@ void srslte_configure_pmch(srslte_pmch_cfg_t* pmch_cfg, srslte_cell_t* cell, srs
pmch_cfg->pdsch_cfg.grant.tb[0].enabled = mbsfn_cfg->enable; pmch_cfg->pdsch_cfg.grant.tb[0].enabled = mbsfn_cfg->enable;
pmch_cfg->pdsch_cfg.grant.tb[0].rv = SRSLTE_PMCH_RV; pmch_cfg->pdsch_cfg.grant.tb[0].rv = SRSLTE_PMCH_RV;
pmch_cfg->pdsch_cfg.grant.last_tbs[0] = 0; pmch_cfg->pdsch_cfg.grant.last_tbs[0] = 0;
srslte_dl_fill_ra_mcs( srslte_dl_fill_ra_mcs(&pmch_cfg->pdsch_cfg.grant.tb[0],
&pmch_cfg->pdsch_cfg.grant.tb[0], pmch_cfg->pdsch_cfg.grant.last_tbs[0], pmch_cfg->pdsch_cfg.grant.nof_prb); pmch_cfg->pdsch_cfg.grant.last_tbs[0],
pmch_cfg->pdsch_cfg.grant.nof_prb,
false);
pmch_cfg->pdsch_cfg.grant.nof_tb = 1; pmch_cfg->pdsch_cfg.grant.nof_tb = 1;
pmch_cfg->pdsch_cfg.grant.nof_layers = 1; pmch_cfg->pdsch_cfg.grant.nof_layers = 1;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {

@ -151,7 +151,7 @@ srslte_mod_t srslte_ra_dl_mod_from_mcs(uint32_t mcs)
return SRSLTE_MOD_16QAM; return SRSLTE_MOD_16QAM;
} else { } else {
return SRSLTE_MOD_64QAM; return SRSLTE_MOD_64QAM;
} }
} }
srslte_mod_t srslte_ra_ul_mod_from_mcs(uint32_t mcs) srslte_mod_t srslte_ra_ul_mod_from_mcs(uint32_t mcs)
@ -196,7 +196,7 @@ int srslte_ra_mcs_from_tbs_idx(uint32_t tbs_idx, bool is_ul)
/* Table 7.1.7.2.1-1: Transport block size table on 36.213 */ /* Table 7.1.7.2.1-1: Transport block size table on 36.213 */
int srslte_ra_tbs_from_idx(uint32_t tbs_idx, uint32_t n_prb) int srslte_ra_tbs_from_idx(uint32_t tbs_idx, uint32_t n_prb)
{ {
if (tbs_idx < 27 && n_prb > 0 && n_prb <= SRSLTE_MAX_PRB) { if (tbs_idx < 34 && n_prb > 0 && n_prb <= SRSLTE_MAX_PRB) {
return tbs_table[tbs_idx][n_prb - 1]; return tbs_table[tbs_idx][n_prb - 1];
} else { } else {
return SRSLTE_ERROR; return SRSLTE_ERROR;

@ -26,6 +26,7 @@
#include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h" #include "srslte/phy/utils/vector.h"
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "tbs_tables.h"
#include <math.h> #include <math.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
@ -316,27 +317,46 @@ int srslte_ra_dl_grant_to_grant_prb_allocation(srslte_dci_dl_t* dci, srslte_pdsc
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
int srslte_dl_fill_ra_mcs(srslte_ra_tb_t* tb, int last_tbs, uint32_t nprb) int srslte_dl_fill_ra_mcs(srslte_ra_tb_t* tb, int last_tbs, uint32_t nprb, bool pdsch_use_tbs_index_alt)
{ {
int i_tbs = 0; int i_tbs = 0;
if (tb->mcs_idx < 10) { if (!pdsch_use_tbs_index_alt) {
tb->mod = SRSLTE_MOD_QPSK; // Implements 3GPP 36.211 Table 3.56.35-431
i_tbs = tb->mcs_idx; if (tb->mcs_idx < 10) {
} else if (tb->mcs_idx < 17) { tb->mod = SRSLTE_MOD_QPSK;
tb->mod = SRSLTE_MOD_16QAM; i_tbs = tb->mcs_idx;
i_tbs = tb->mcs_idx - 1; } else if (tb->mcs_idx < 17) {
} else if (tb->mcs_idx < 29) { tb->mod = SRSLTE_MOD_16QAM;
tb->mod = SRSLTE_MOD_64QAM; i_tbs = tb->mcs_idx - 1;
i_tbs = tb->mcs_idx - 2; } else if (tb->mcs_idx < 29) {
} else if (tb->mcs_idx == 29) { tb->mod = SRSLTE_MOD_64QAM;
tb->mod = SRSLTE_MOD_QPSK; i_tbs = tb->mcs_idx - 2;
i_tbs = -1; } else if (tb->mcs_idx == 29) {
} else if (tb->mcs_idx == 30) { tb->mod = SRSLTE_MOD_QPSK;
tb->mod = SRSLTE_MOD_16QAM; i_tbs = -1;
i_tbs = -1; } else if (tb->mcs_idx == 30) {
} else if (tb->mcs_idx == 31) { tb->mod = SRSLTE_MOD_16QAM;
tb->mod = SRSLTE_MOD_64QAM; i_tbs = -1;
i_tbs = -1; } else if (tb->mcs_idx == 31) {
tb->mod = SRSLTE_MOD_64QAM;
i_tbs = -1;
}
} else {
if (tb->mcs_idx < 28) {
i_tbs = dl_mcs_tbs_idx_table2[tb->mcs_idx];
} else {
i_tbs = SRSLTE_ERROR;
}
if (tb->mcs_idx < 5 || tb->mcs_idx == 28) {
tb->mod = SRSLTE_MOD_QPSK;
} else if (tb->mcs_idx < 11 || tb->mcs_idx == 29) {
tb->mod = SRSLTE_MOD_16QAM;
} else if (tb->mcs_idx < 20 || tb->mcs_idx == 30) {
tb->mod = SRSLTE_MOD_64QAM;
} else {
tb->mod = SRSLTE_MOD_256QAM;
}
} }
// If i_tbs = -1, TBS is determined from the latest PDCCH for this TB (7.1.7.2 36.213) // If i_tbs = -1, TBS is determined from the latest PDCCH for this TB (7.1.7.2 36.213)
@ -353,7 +373,7 @@ int srslte_dl_fill_ra_mcs(srslte_ra_tb_t* tb, int last_tbs, uint32_t nprb)
/* Modulation order and transport block size determination 7.1.7 in 36.213 /* Modulation order and transport block size determination 7.1.7 in 36.213
* */ * */
static int dl_dci_compute_tb(srslte_dci_dl_t* dci, srslte_pdsch_grant_t* grant) static int dl_dci_compute_tb(bool pdsch_use_tbs_index_alt, srslte_dci_dl_t* dci, srslte_pdsch_grant_t* grant)
{ {
uint32_t n_prb = 0; uint32_t n_prb = 0;
int tbs = -1; int tbs = -1;
@ -408,7 +428,7 @@ static int dl_dci_compute_tb(srslte_dci_dl_t* dci, srslte_pdsch_grant_t* grant)
} }
for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (grant->tb[i].enabled) { if (grant->tb[i].enabled) {
grant->tb[i].tbs = srslte_dl_fill_ra_mcs(&grant->tb[i], grant->last_tbs[i], n_prb); grant->tb[i].tbs = srslte_dl_fill_ra_mcs(&grant->tb[i], grant->last_tbs[i], n_prb, pdsch_use_tbs_index_alt);
if (grant->tb[i].tbs < 0) { if (grant->tb[i].tbs < 0) {
ERROR("Computing TBS from MCS=%d, n_prb=%d\n", grant->tb[i].mcs_idx, n_prb); ERROR("Computing TBS from MCS=%d, n_prb=%d\n", grant->tb[i].mcs_idx, n_prb);
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -606,8 +626,12 @@ static int config_mimo(srslte_cell_t* cell, srslte_tm_t tm, srslte_dci_dl_t* dci
**********/ **********/
/** Compute the DL grant parameters */ /** Compute the DL grant parameters */
int srslte_ra_dl_dci_to_grant( int srslte_ra_dl_dci_to_grant(srslte_cell_t* cell,
srslte_cell_t* cell, srslte_dl_sf_cfg_t* sf, srslte_tm_t tm, srslte_dci_dl_t* dci, srslte_pdsch_grant_t* grant) srslte_dl_sf_cfg_t* sf,
srslte_tm_t tm,
bool pdsch_use_tbs_index_alt,
srslte_dci_dl_t* dci,
srslte_pdsch_grant_t* grant)
{ {
bzero(grant, sizeof(srslte_pdsch_grant_t)); bzero(grant, sizeof(srslte_pdsch_grant_t));
@ -615,7 +639,7 @@ int srslte_ra_dl_dci_to_grant(
int ret = srslte_ra_dl_grant_to_grant_prb_allocation(dci, grant, cell->nof_prb); int ret = srslte_ra_dl_grant_to_grant_prb_allocation(dci, grant, cell->nof_prb);
if (ret == SRSLTE_SUCCESS) { if (ret == SRSLTE_SUCCESS) {
// Compute MCS // Compute MCS
ret = dl_dci_compute_tb(dci, grant); ret = dl_dci_compute_tb(pdsch_use_tbs_index_alt, dci, grant);
if (ret == SRSLTE_SUCCESS) { if (ret == SRSLTE_SUCCESS) {
// Compute number of RE and number of ack_value in grant // Compute number of RE and number of ack_value in grant
srslte_ra_dl_compute_nof_re(cell, sf, grant); srslte_ra_dl_compute_nof_re(cell, sf, grant);

@ -20,281 +20,248 @@
*/ */
/* Modulation and TBS index table for PDSCH from 3GPP TS 36.213 v10.3.0 table 7.1.7.1-1 */ /* Modulation and TBS index table for PDSCH from 3GPP TS 36.213 v10.3.0 table 7.1.7.1-1 */
const int dl_mcs_tbs_idx_table[29] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, static const int dl_mcs_tbs_idx_table[29] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13,
14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}; 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26};
/* Modulation and TBS index table for PUSCH from 3GPP TS 36.213 v10.3.0 table 8.6.1-1 */ /* Modulation and TBS index table for PDSCH from 3GPP TS 36.213 v12.13.0 table 7.1.7.1-1A */
const int ul_mcs_tbs_idx_table[29] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, static const int dl_mcs_tbs_idx_table2[28] = {0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18,
14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26}; 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33};
/* Transport Block Size from 3GPP TS 36.213 v10.3.0 table 7.1.7.2.1-1 */ /* Modulation and TBS index table for PUSCH from 3GPP TS 36.213 v10.3.0 table 8.6.1-1A */
const int tbs_table[27][110] = {{ 16, 32, 56, 88, 120, 152, 176, 208, 224, 256, 288, static const int ul_mcs_tbs_idx_table[29] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13,
328, 344, 376, 392, 424, 456, 488, 504, 536, 568, 600, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26};
616, 648, 680, 712, 744, 776, 776, 808, 840, 872, 904,
936, 968, 1000, 1032, 1032, 1064, 1096, 1128, 1160, 1192, 1224, /* Transport Block Size from 3GPP TS 36.213 v12.13.0 table 7.1.7.2.1-1 */
1256, 1256, 1288, 1320, 1352, 1384, 1416, 1416, 1480, 1480, 1544, static const int tbs_table[34][110] = {
1544, 1608, 1608, 1608, 1672, 1672, 1736, 1736, 1800, 1800, 1800, {16, 32, 56, 88, 120, 152, 176, 208, 224, 256, 288, 328, 344, 376, 392, 424, 456, 488, 504,
1864, 1864, 1928, 1928, 1992, 1992, 2024, 2088, 2088, 2088, 2152, 536, 568, 600, 616, 648, 680, 712, 744, 776, 776, 808, 840, 872, 904, 936, 968, 1000, 1032, 1032,
2152, 2216, 2216, 2280, 2280, 2280, 2344, 2344, 2408, 2408, 2472, 1064, 1096, 1128, 1160, 1192, 1224, 1256, 1256, 1288, 1320, 1352, 1384, 1416, 1416, 1480, 1480, 1544, 1544, 1608,
2472, 2536, 2536, 2536, 2600, 2600, 2664, 2664, 2728, 2728, 2728, 1608, 1608, 1672, 1672, 1736, 1736, 1800, 1800, 1800, 1864, 1864, 1928, 1928, 1992, 1992, 2024, 2088, 2088, 2088,
2792, 2792, 2856, 2856, 2856, 2984, 2984, 2984, 2984, 2984, 3112}, 2152, 2152, 2216, 2216, 2280, 2280, 2280, 2344, 2344, 2408, 2408, 2472, 2472, 2536, 2536, 2536, 2600, 2600, 2664,
{ 24, 56, 88, 144, 176, 208, 224, 256, 328, 344, 376, 2664, 2728, 2728, 2728, 2792, 2792, 2856, 2856, 2856, 2984, 2984, 2984, 2984, 2984, 3112},
424, 456, 488, 520, 568, 600, 632, 680, 712, 744, 776, {24, 56, 88, 144, 176, 208, 224, 256, 328, 344, 376, 424, 456, 488, 520, 568, 600, 632, 680,
808, 872, 904, 936, 968, 1000, 1032, 1064, 1128, 1160, 1192, 712, 744, 776, 808, 872, 904, 936, 968, 1000, 1032, 1064, 1128, 1160, 1192, 1224, 1256, 1288, 1352, 1384,
1224, 1256, 1288, 1352, 1384, 1416, 1416, 1480, 1544, 1544, 1608, 1416, 1416, 1480, 1544, 1544, 1608, 1608, 1672, 1736, 1736, 1800, 1800, 1864, 1864, 1928, 1992, 1992, 2024, 2088,
1608, 1672, 1736, 1736, 1800, 1800, 1864, 1864, 1928, 1992, 1992, 2088, 2152, 2152, 2216, 2280, 2280, 2344, 2344, 2408, 2472, 2472, 2536, 2536, 2600, 2600, 2664, 2728, 2728, 2792,
2024, 2088, 2088, 2152, 2152, 2216, 2280, 2280, 2344, 2344, 2408, 2792, 2856, 2856, 2856, 2984, 2984, 2984, 3112, 3112, 3112, 3240, 3240, 3240, 3240, 3368, 3368, 3368, 3496, 3496,
2472, 2472, 2536, 2536, 2600, 2600, 2664, 2728, 2728, 2792, 2792, 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3752, 3752, 3880, 3880, 3880, 4008, 4008, 4008},
2856, 2856, 2856, 2984, 2984, 2984, 3112, 3112, 3112, 3240, 3240, {32, 72, 144, 176, 208, 256, 296, 328, 376, 424, 472, 520, 568, 616, 648, 696, 744, 776, 840,
3240, 3240, 3368, 3368, 3368, 3496, 3496, 3496, 3496, 3624, 3624, 872, 936, 968, 1000, 1064, 1096, 1160, 1192, 1256, 1288, 1320, 1384, 1416, 1480, 1544, 1544, 1608, 1672, 1672,
3624, 3752, 3752, 3752, 3752, 3880, 3880, 3880, 4008, 4008, 4008}, 1736, 1800, 1800, 1864, 1928, 1992, 2024, 2088, 2088, 2152, 2216, 2216, 2280, 2344, 2344, 2408, 2472, 2536, 2536,
{ 32, 72, 144, 176, 208, 256, 296, 328, 376, 424, 472, 2600, 2664, 2664, 2728, 2792, 2856, 2856, 2856, 2984, 2984, 3112, 3112, 3112, 3240, 3240, 3240, 3368, 3368, 3368,
520, 568, 616, 648, 696, 744, 776, 840, 872, 936, 968, 3496, 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880, 3880, 3880, 4008, 4008, 4008, 4136, 4136, 4136, 4264, 4264,
1000, 1064, 1096, 1160, 1192, 1256, 1288, 1320, 1384, 1416, 1480, 4264, 4392, 4392, 4392, 4584, 4584, 4584, 4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968},
1544, 1544, 1608, 1672, 1672, 1736, 1800, 1800, 1864, 1928, 1992, {40, 104, 176, 208, 256, 328, 392, 440, 504, 568, 616, 680, 744, 808, 872, 904, 968, 1032, 1096,
2024, 2088, 2088, 2152, 2216, 2216, 2280, 2344, 2344, 2408, 2472, 1160, 1224, 1256, 1320, 1384, 1416, 1480, 1544, 1608, 1672, 1736, 1800, 1864, 1928, 1992, 2024, 2088, 2152, 2216,
2536, 2536, 2600, 2664, 2664, 2728, 2792, 2856, 2856, 2856, 2984, 2280, 2344, 2408, 2472, 2536, 2536, 2600, 2664, 2728, 2792, 2856, 2856, 2984, 2984, 3112, 3112, 3240, 3240, 3368,
2984, 3112, 3112, 3112, 3240, 3240, 3240, 3368, 3368, 3368, 3496, 3368, 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880, 3880, 4008, 4008, 4136, 4136, 4264, 4264, 4392, 4392, 4392,
3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880, 3880, 3880, 4008, 4584, 4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968, 4968, 5160, 5160, 5160, 5352, 5352, 5352, 5352, 5544, 5544,
4008, 4008, 4136, 4136, 4136, 4264, 4264, 4264, 4392, 4392, 4392, 5544, 5736, 5736, 5736, 5736, 5992, 5992, 5992, 5992, 6200, 6200, 6200, 6200, 6456, 6456},
4584, 4584, 4584, 4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968}, {56, 120, 208, 256, 328, 408, 488, 552, 632, 696, 776, 840, 904, 1000, 1064, 1128, 1192, 1288, 1352,
{ 40, 104, 176, 208, 256, 328, 392, 440, 504, 568, 616, 1416, 1480, 1544, 1608, 1736, 1800, 1864, 1928, 1992, 2088, 2152, 2216, 2280, 2344, 2408, 2472, 2600, 2664, 2728,
680, 744, 808, 872, 904, 968, 1032, 1096, 1160, 1224, 1256, 2792, 2856, 2984, 2984, 3112, 3112, 3240, 3240, 3368, 3496, 3496, 3624, 3624, 3752, 3752, 3880, 4008, 4008, 4136,
1320, 1384, 1416, 1480, 1544, 1608, 1672, 1736, 1800, 1864, 1928, 4136, 4264, 4264, 4392, 4392, 4584, 4584, 4584, 4776, 4776, 4968, 4968, 4968, 5160, 5160, 5160, 5352, 5352, 5544,
1992, 2024, 2088, 2152, 2216, 2280, 2344, 2408, 2472, 2536, 2536, 5544, 5544, 5736, 5736, 5736, 5992, 5992, 5992, 5992, 6200, 6200, 6200, 6456, 6456, 6456, 6456, 6712, 6712, 6712,
2600, 2664, 2728, 2792, 2856, 2856, 2984, 2984, 3112, 3112, 3240, 6968, 6968, 6968, 6968, 7224, 7224, 7224, 7480, 7480, 7480, 7480, 7736, 7736, 7736, 7992},
3240, 3368, 3368, 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880, {72, 144, 224, 328, 424, 504, 600, 680, 776, 872, 968, 1032, 1128, 1224, 1320, 1384, 1480, 1544, 1672,
3880, 4008, 4008, 4136, 4136, 4264, 4264, 4392, 4392, 4392, 4584, 1736, 1864, 1928, 2024, 2088, 2216, 2280, 2344, 2472, 2536, 2664, 2728, 2792, 2856, 2984, 3112, 3112, 3240, 3368,
4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968, 4968, 5160, 5160, 3496, 3496, 3624, 3752, 3752, 3880, 4008, 4008, 4136, 4264, 4392, 4392, 4584, 4584, 4776, 4776, 4776, 4968, 4968,
5160, 5352, 5352, 5352, 5352, 5544, 5544, 5544, 5736, 5736, 5736, 5160, 5160, 5352, 5352, 5544, 5544, 5736, 5736, 5736, 5992, 5992, 5992, 6200, 6200, 6200, 6456, 6456, 6712, 6712,
5736, 5992, 5992, 5992, 5992, 6200, 6200, 6200, 6200, 6456, 6456}, 6712, 6968, 6968, 6968, 7224, 7224, 7224, 7480, 7480, 7480, 7736, 7736, 7736, 7992, 7992, 7992, 8248, 8248, 8248,
{ 56, 120, 208, 256, 328, 408, 488, 552, 632, 696, 776, 8504, 8504, 8760, 8760, 8760, 8760, 9144, 9144, 9144, 9144, 9528, 9528, 9528, 9528, 9528},
840, 904, 1000, 1064, 1128, 1192, 1288, 1352, 1416, 1480, 1544, {328, 176, 256, 392, 504, 600, 712, 808, 936, 1032, 1128, 1224, 1352, 1480, 1544, 1672,
1608, 1736, 1800, 1864, 1928, 1992, 2088, 2152, 2216, 2280, 2344, 1736, 1864, 1992, 2088, 2216, 2280, 2408, 2472, 2600, 2728, 2792, 2984, 2984, 3112, 3240, 3368,
2408, 2472, 2600, 2664, 2728, 2792, 2856, 2984, 2984, 3112, 3112, 3496, 3496, 3624, 3752, 3880, 4008, 4136, 4136, 4264, 4392, 4584, 4584, 4776, 4776, 4968, 4968,
3240, 3240, 3368, 3496, 3496, 3624, 3624, 3752, 3752, 3880, 4008, 5160, 5160, 5352, 5352, 5544, 5736, 5736, 5992, 5992, 5992, 6200, 6200, 6456, 6456, 6456, 6712,
4008, 4136, 4136, 4264, 4264, 4392, 4392, 4584, 4584, 4584, 4776, 6712, 6968, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7736, 7992, 7992, 8248, 8248, 8248,
4776, 4968, 4968, 4968, 5160, 5160, 5160, 5352, 5352, 5544, 5544, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, 9144, 9528, 9528, 9528, 9528, 9912, 9912, 9912,
5544, 5736, 5736, 5736, 5992, 5992, 5992, 5992, 6200, 6200, 6200, 10296, 10296, 10296, 10296, 10680, 10680, 10680, 10680, 11064, 11064, 11064, 11448, 11448, 11448},
6456, 6456, 6456, 6456, 6712, 6712, 6712, 6968, 6968, 6968, 6968, {104, 224, 328, 472, 584, 712, 840, 968, 1096, 1224, 1320, 1480, 1608, 1672, 1800, 1928,
7224, 7224, 7224, 7480, 7480, 7480, 7480, 7736, 7736, 7736, 7992}, 2088, 2216, 2344, 2472, 2536, 2664, 2792, 2984, 3112, 3240, 3368, 3368, 3496, 3624, 3752, 3880,
{ 72, 144, 224, 328, 424, 504, 600, 680, 776, 872, 968, 4008, 4136, 4264, 4392, 4584, 4584, 4776, 4968, 4968, 5160, 5352, 5352, 5544, 5736, 5736, 5992,
1032, 1128, 1224, 1320, 1384, 1480, 1544, 1672, 1736, 1864, 1928, 5992, 6200, 6200, 6456, 6456, 6712, 6712, 6712, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736,
2024, 2088, 2216, 2280, 2344, 2472, 2536, 2664, 2728, 2792, 2856, 7992, 7992, 8248, 8248, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, 9528, 9528, 9528, 9912,
2984, 3112, 3112, 3240, 3368, 3496, 3496, 3624, 3752, 3752, 3880, 9912, 9912, 10296, 10296, 10296, 10680, 10680, 10680, 11064, 11064, 11064, 11448, 11448, 11448, 11448, 11832,
4008, 4008, 4136, 4264, 4392, 4392, 4584, 4584, 4776, 4776, 4776, 11832, 11832, 12216, 12216, 12216, 12576, 12576, 12576, 12960, 12960, 12960, 12960, 13536, 13536},
4968, 4968, 5160, 5160, 5352, 5352, 5544, 5544, 5736, 5736, 5736, {120, 256, 392, 536, 680, 808, 968, 1096, 1256, 1384, 1544, 1672, 1800, 1928, 2088, 2216,
5992, 5992, 5992, 6200, 6200, 6200, 6456, 6456, 6712, 6712, 6712, 2344, 2536, 2664, 2792, 2984, 3112, 3240, 3368, 3496, 3624, 3752, 3880, 4008, 4264, 4392, 4584,
6968, 6968, 6968, 7224, 7224, 7224, 7480, 7480, 7480, 7736, 7736, 4584, 4776, 4968, 4968, 5160, 5352, 5544, 5544, 5736, 5992, 5992, 6200, 6200, 6456, 6456, 6712,
7736, 7992, 7992, 7992, 8248, 8248, 8248, 8504, 8504, 8760, 8760, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7992, 7992, 8248, 8504, 8504, 8760, 8760, 9144,
8760, 8760, 9144, 9144, 9144, 9144, 9528, 9528, 9528, 9528, 9528}, 9144, 9144, 9528, 9528, 9528, 9912, 9912, 9912, 10296, 10296, 10680, 10680, 10680, 11064, 11064, 11064,
{ 328, 176, 256, 392, 504, 600, 712, 808, 936, 1032, 1128, 11448, 11448, 11448, 11832, 11832, 12216, 12216, 12216, 12576, 12576, 12576, 12960, 12960, 12960, 13536, 13536,
1224, 1352, 1480, 1544, 1672, 1736, 1864, 1992, 2088, 2216, 2280, 13536, 13536, 14112, 14112, 14112, 14112, 14688, 14688, 14688, 14688, 15264, 15264, 15264, 15264},
2408, 2472, 2600, 2728, 2792, 2984, 2984, 3112, 3240, 3368, 3496, {136, 296, 456, 616, 776, 936, 1096, 1256, 1416, 1544, 1736, 1864, 2024, 2216, 2344, 2536,
3496, 3624, 3752, 3880, 4008, 4136, 4136, 4264, 4392, 4584, 4584, 2664, 2856, 2984, 3112, 3368, 3496, 3624, 3752, 4008, 4136, 4264, 4392, 4584, 4776, 4968, 5160,
4776, 4776, 4968, 4968, 5160, 5160, 5352, 5352, 5544, 5736, 5736, 5160, 5352, 5544, 5736, 5736, 5992, 6200, 6200, 6456, 6712, 6712, 6968, 6968, 7224, 7480, 7480,
5992, 5992, 5992, 6200, 6200, 6456, 6456, 6456, 6712, 6712, 6968, 7736, 7992, 7992, 8248, 8248, 8504, 8760, 8760, 9144, 9144, 9144, 9528, 9528, 9912, 9912, 10296,
6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7736, 7992, 7992, 10296, 10296, 10680, 10680, 11064, 11064, 11064, 11448, 11448, 11832, 11832, 11832, 12216, 12216, 12576, 12576,
8248, 8248, 8248, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, 12960, 12960, 12960, 13536, 13536, 13536, 13536, 14112, 14112, 14112, 14112, 14688, 14688, 14688, 15264, 15264,
9144, 9528, 9528, 9528, 9528, 9912, 9912, 9912,10296,10296,10296, 15264, 15264, 15840, 15840, 15840, 16416, 16416, 16416, 16416, 16992, 16992, 16992, 16992, 17568},
10296,10680,10680,10680,10680,11064,11064,11064,11448,11448,11448}, {144, 328, 504, 680, 872, 1032, 1224, 1384, 1544, 1736, 1928, 2088, 2280, 2472, 2664, 2792,
{ 104, 224, 328, 472, 584, 712, 840, 968, 1096, 1224, 1320, 2984, 3112, 3368, 3496, 3752, 3880, 4008, 4264, 4392, 4584, 4776, 4968, 5160, 5352, 5544, 5736,
1480, 1608, 1672, 1800, 1928, 2088, 2216, 2344, 2472, 2536, 2664, 5736, 5992, 6200, 6200, 6456, 6712, 6712, 6968, 7224, 7480, 7480, 7736, 7992, 7992, 8248, 8504,
2792, 2984, 3112, 3240, 3368, 3368, 3496, 3624, 3752, 3880, 4008, 8504, 8760, 9144, 9144, 9144, 9528, 9528, 9912, 9912, 10296, 10296, 10680, 10680, 11064, 11064, 11448,
4136, 4264, 4392, 4584, 4584, 4776, 4968, 4968, 5160, 5352, 5352, 11448, 11448, 11832, 11832, 12216, 12216, 12576, 12576, 12960, 12960, 12960, 13536, 13536, 13536, 14112, 14112,
5544, 5736, 5736, 5992, 5992, 6200, 6200, 6456, 6456, 6712, 6712, 14112, 14688, 14688, 14688, 14688, 15264, 15264, 15264, 15840, 15840, 15840, 16416, 16416, 16416, 16992, 16992,
6712, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7992, 7992, 16992, 16992, 17568, 17568, 17568, 18336, 18336, 18336, 18336, 18336, 19080, 19080, 19080, 19080},
8248, 8248, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, 9528, {176, 376, 584, 776, 1000, 1192, 1384, 1608, 1800, 2024, 2216, 2408, 2600, 2792, 2984, 3240,
9528, 9528, 9912, 9912, 9912,10296,10296,10296,10680,10680,10680, 3496, 3624, 3880, 4008, 4264, 4392, 4584, 4776, 4968, 5352, 5544, 5736, 5992, 5992, 6200, 6456,
11064,11064,11064,11448,11448,11448,11448,11832,11832,11832,12216, 6712, 6968, 6968, 7224, 7480, 7736, 7736, 7992, 8248, 8504, 8760, 8760, 9144, 9144, 9528, 9528,
12216,12216,12576,12576,12576,12960,12960,12960,12960,13536,13536}, 9912, 9912, 10296, 10680, 10680, 11064, 11064, 11448, 11448, 11832, 11832, 12216, 12216, 12576, 12576, 12960,
{ 120, 256, 392, 536, 680, 808, 968, 1096, 1256, 1384, 1544, 12960, 13536, 13536, 13536, 14112, 14112, 14112, 14688, 14688, 14688, 15264, 15264, 15840, 15840, 15840, 16416,
1672, 1800, 1928, 2088, 2216, 2344, 2536, 2664, 2792, 2984, 3112, 16416, 16416, 16992, 16992, 16992, 17568, 17568, 17568, 18336, 18336, 18336, 18336, 19080, 19080, 19080, 19080,
3240, 3368, 3496, 3624, 3752, 3880, 4008, 4264, 4392, 4584, 4584, 19848, 19848, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 21384, 21384, 22152, 22152, 22152},
4776, 4968, 4968, 5160, 5352, 5544, 5544, 5736, 5992, 5992, 6200, {208, 440, 680, 904, 1128, 1352, 1608, 1800, 2024, 2280, 2472, 2728, 2984, 3240, 3368, 3624,
6200, 6456, 6456, 6712, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 3880, 4136, 4392, 4584, 4776, 4968, 5352, 5544, 5736, 5992, 6200, 6456, 6712, 6712, 6968, 7224,
7736, 7992, 7992, 8248, 8504, 8504, 8760, 8760, 9144, 9144, 9144, 7480, 7736, 7992, 8248, 8504, 8760, 8760, 9144, 9528, 9528, 9912, 9912, 10296, 10680, 10680, 11064,
9528, 9528, 9528, 9912, 9912, 9912,10296,10296,10680,10680,10680, 11064, 11448, 11832, 11832, 12216, 12216, 12576, 12576, 12960, 12960, 13536, 13536, 14112, 14112, 14112, 14688,
11064,11064,11064,11448,11448,11448,11832,11832,12216,12216,12216, 14688, 15264, 15264, 15264, 15840, 15840, 16416, 16416, 16416, 16992, 16992, 17568, 17568, 17568, 18336, 18336,
12576,12576,12576,12960,12960,12960,13536,13536,13536,13536,14112, 18336, 19080, 19080, 19080, 19080, 19848, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 21384, 21384, 22152,
14112,14112,14112,14688,14688,14688,14688,15264,15264,15264,15264}, 22152, 22152, 22920, 22920, 22920, 23688, 23688, 23688, 23688, 24496, 24496, 24496, 24496, 25456},
{ 136, 296, 456, 616, 776, 936, 1096, 1256, 1416, 1544, 1736, {224, 488, 744, 1000, 1256, 1544, 1800, 2024, 2280, 2536, 2856, 3112, 3368, 3624, 3880, 4136,
1864, 2024, 2216, 2344, 2536, 2664, 2856, 2984, 3112, 3368, 3496, 4392, 4584, 4968, 5160, 5352, 5736, 5992, 6200, 6456, 6712, 6968, 7224, 7480, 7736, 7992, 8248,
3624, 3752, 4008, 4136, 4264, 4392, 4584, 4776, 4968, 5160, 5160, 8504, 8760, 9144, 9144, 9528, 9912, 9912, 10296, 10680, 10680, 11064, 11448, 11448, 11832, 12216, 12216,
5352, 5544, 5736, 5736, 5992, 6200, 6200, 6456, 6712, 6712, 6968, 12576, 12960, 12960, 13536, 13536, 14112, 14112, 14688, 14688, 14688, 15264, 15264, 15840, 15840, 16416, 16416,
6968, 7224, 7480, 7480, 7736, 7992, 7992, 8248, 8248, 8504, 8760, 16992, 16992, 16992, 17568, 17568, 18336, 18336, 18336, 19080, 19080, 19080, 19848, 19848, 19848, 20616, 20616,
8760, 9144, 9144, 9144, 9528, 9528, 9912, 9912,10296,10296,10296, 20616, 21384, 21384, 21384, 22152, 22152, 22152, 22920, 22920, 22920, 23688, 23688, 23688, 24496, 24496, 24496,
10680,10680,11064,11064,11064,11448,11448,11832,11832,11832,12216, 25456, 25456, 25456, 25456, 26416, 26416, 26416, 26416, 27376, 27376, 27376, 27376, 28336, 28336},
12216,12576,12576,12960,12960,12960,13536,13536,13536,13536,14112, {256, 552, 840, 1128, 1416, 1736, 1992, 2280, 2600, 2856, 3112, 3496, 3752, 4008, 4264, 4584,
14112,14112,14112,14688,14688,14688,15264,15264,15264,15264,15840, 4968, 5160, 5544, 5736, 5992, 6200, 6456, 6968, 7224, 7480, 7736, 7992, 8248, 8504, 8760, 9144,
15840,15840,16416,16416,16416,16416,16992,16992,16992,16992,17568}, 9528, 9912, 9912, 10296, 10680, 11064, 11064, 11448, 11832, 12216, 12216, 12576, 12960, 12960, 13536, 13536,
{ 144, 328, 504, 680, 872, 1032, 1224, 1384, 1544, 1736, 1928, 14112, 14112, 14688, 14688, 15264, 15264, 15840, 15840, 16416, 16416, 16992, 16992, 17568, 17568, 18336, 18336,
2088, 2280, 2472, 2664, 2792, 2984, 3112, 3368, 3496, 3752, 3880, 18336, 19080, 19080, 19848, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 22152, 22152, 22152, 22920, 22920,
4008, 4264, 4392, 4584, 4776, 4968, 5160, 5352, 5544, 5736, 5736, 22920, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 25456, 25456, 26416, 26416, 26416, 27376, 27376, 27376,
5992, 6200, 6200, 6456, 6712, 6712, 6968, 7224, 7480, 7480, 7736, 28336, 28336, 28336, 28336, 29296, 29296, 29296, 29296, 30576, 30576, 30576, 30576, 31704, 31704},
7992, 7992, 8248, 8504, 8504, 8760, 9144, 9144, 9144, 9528, 9528, {280, 600, 904, 1224, 1544, 1800, 2152, 2472, 2728, 3112, 3368, 3624, 4008, 4264, 4584, 4968,
9912, 9912,10296,10296,10680,10680,11064,11064,11448,11448,11448, 5160, 5544, 5736, 6200, 6456, 6712, 6968, 7224, 7736, 7992, 8248, 8504, 8760, 9144, 9528, 9912,
11832,11832,12216,12216,12576,12576,12960,12960,12960,13536,13536, 10296, 10296, 10680, 11064, 11448, 11832, 11832, 12216, 12576, 12960, 12960, 13536, 13536, 14112, 14688, 14688,
13536,14112,14112,14112,14688,14688,14688,14688,15264,15264,15264, 15264, 15264, 15840, 15840, 16416, 16416, 16992, 16992, 17568, 17568, 18336, 18336, 18336, 19080, 19080, 19848,
15840,15840,15840,16416,16416,16416,16992,16992,16992,16992,17568, 19848, 20616, 20616, 20616, 21384, 21384, 22152, 22152, 22152, 22920, 22920, 23688, 23688, 23688, 24496, 24496,
17568,17568,18336,18336,18336,18336,18336,19080,19080,19080,19080}, 24496, 25456, 25456, 25456, 26416, 26416, 26416, 27376, 27376, 27376, 28336, 28336, 28336, 29296, 29296, 29296,
{ 176, 376, 584, 776, 1000, 1192, 1384, 1608, 1800, 2024, 2216, 29296, 30576, 30576, 30576, 30576, 31704, 31704, 31704, 31704, 32856, 32856, 32856, 34008, 34008},
2408, 2600, 2792, 2984, 3240, 3496, 3624, 3880, 4008, 4264, 4392, {328, 632, 968, 1288, 1608, 1928, 2280, 2600, 2984, 3240, 3624, 3880, 4264, 4584, 4968, 5160,
4584, 4776, 4968, 5352, 5544, 5736, 5992, 5992, 6200, 6456, 6712, 5544, 5992, 6200, 6456, 6712, 7224, 7480, 7736, 7992, 8504, 8760, 9144, 9528, 9912, 9912, 10296,
6968, 6968, 7224, 7480, 7736, 7736, 7992, 8248, 8504, 8760, 8760, 10680, 11064, 11448, 11832, 12216, 12216, 12576, 12960, 13536, 13536, 14112, 14112, 14688, 14688, 15264, 15840,
9144, 9144, 9528, 9528, 9912, 9912,10296,10680,10680,11064,11064, 15840, 16416, 16416, 16992, 16992, 17568, 17568, 18336, 18336, 19080, 19080, 19848, 19848, 19848, 20616, 20616,
11448,11448,11832,11832,12216,12216,12576,12576,12960,12960,13536, 21384, 21384, 22152, 22152, 22152, 22920, 22920, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 25456, 26416,
13536,13536,14112,14112,14112,14688,14688,14688,15264,15264,15840, 26416, 26416, 27376, 27376, 27376, 28336, 28336, 28336, 29296, 29296, 29296, 30576, 30576, 30576, 30576, 31704,
15840,15840,16416,16416,16416,16992,16992,16992,17568,17568,17568, 31704, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 34008, 34008, 35160, 35160, 35160, 35160},
18336,18336,18336,18336,19080,19080,19080,19080,19848,19848,19848, {336, 696, 1064, 1416, 1800, 2152, 2536, 2856, 3240, 3624, 4008, 4392, 4776, 5160, 5352, 5736,
19848,20616,20616,20616,21384,21384,21384,21384,22152,22152,22152}, 6200, 6456, 6712, 7224, 7480, 7992, 8248, 8760, 9144, 9528, 9912, 10296, 10296, 10680, 11064, 11448,
{ 208, 440, 680, 904, 1128, 1352, 1608, 1800, 2024, 2280, 2472, 11832, 12216, 12576, 12960, 13536, 13536, 14112, 14688, 14688, 15264, 15264, 15840, 16416, 16416, 16992, 17568,
2728, 2984, 3240, 3368, 3624, 3880, 4136, 4392, 4584, 4776, 4968, 17568, 18336, 18336, 19080, 19080, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 22152, 22152, 22920, 22920,
5352, 5544, 5736, 5992, 6200, 6456, 6712, 6712, 6968, 7224, 7480, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 26416, 26416, 26416, 27376, 27376, 27376, 28336, 28336, 29296,
7736, 7992, 8248, 8504, 8760, 8760, 9144, 9528, 9528, 9912, 9912, 29296, 29296, 30576, 30576, 30576, 30576, 31704, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 34008, 35160,
10296,10680,10680,11064,11064,11448,11832,11832,12216,12216,12576, 35160, 35160, 35160, 36696, 36696, 36696, 36696, 37888, 37888, 37888, 39232, 39232, 39232, 39232},
12576,12960,12960,13536,13536,14112,14112,14112,14688,14688,15264, {376, 776, 1160, 1544, 1992, 2344, 2792, 3112, 3624, 4008, 4392, 4776, 5160, 5544, 5992, 6200,
15264,15264,15840,15840,16416,16416,16416,16992,16992,17568,17568, 6712, 7224, 7480, 7992, 8248, 8760, 9144, 9528, 9912, 10296, 10680, 11064, 11448, 11832, 12216, 12576,
17568,18336,18336,18336,19080,19080,19080,19080,19848,19848,19848, 12960, 13536, 14112, 14112, 14688, 15264, 15264, 15840, 16416, 16416, 16992, 17568, 17568, 18336, 18336, 19080,
20616,20616,20616,21384,21384,21384,21384,22152,22152,22152,22920, 19080, 19848, 19848, 20616, 21384, 21384, 22152, 22152, 22920, 22920, 23688, 23688, 24496, 24496, 24496, 25456,
22920,22920,23688,23688,23688,23688,24496,24496,24496,24496,25456}, 25456, 26416, 26416, 27376, 27376, 27376, 28336, 28336, 29296, 29296, 29296, 30576, 30576, 30576, 31704, 31704,
{ 224, 488, 744, 1000, 1256, 1544, 1800, 2024, 2280, 2536, 2856, 31704, 32856, 32856, 32856, 34008, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 37888,
3112, 3368, 3624, 3880, 4136, 4392, 4584, 4968, 5160, 5352, 5736, 37888, 39232, 39232, 39232, 40576, 40576, 40576, 40576, 42368, 42368, 42368, 42368, 43816, 43816},
5992, 6200, 6456, 6712, 6968, 7224, 7480, 7736, 7992, 8248, 8504, {408, 840, 1288, 1736, 2152, 2600, 2984, 3496, 3880, 4264, 4776, 5160, 5544, 5992, 6456, 6968,
8760, 9144, 9144, 9528, 9912, 9912,10296,10680,10680,11064,11448, 7224, 7736, 8248, 8504, 9144, 9528, 9912, 10296, 10680, 11064, 11448, 12216, 12576, 12960, 13536, 13536,
11448,11832,12216,12216,12576,12960,12960,13536,13536,14112,14112, 14112, 14688, 15264, 15264, 15840, 16416, 16992, 16992, 17568, 18336, 18336, 19080, 19080, 19848, 20616, 20616,
14688,14688,14688,15264,15264,15840,15840,16416,16416,16992,16992, 21384, 21384, 22152, 22152, 22920, 22920, 23688, 24496, 24496, 25456, 25456, 25456, 26416, 26416, 27376, 27376,
16992,17568,17568,18336,18336,18336,19080,19080,19080,19848,19848, 28336, 28336, 29296, 29296, 29296, 30576, 30576, 30576, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 34008,
19848,20616,20616,20616,21384,21384,21384,22152,22152,22152,22920, 35160, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 37888, 39232, 39232, 39232, 40576, 40576, 40576, 40576,
22920,22920,23688,23688,23688,24496,24496,24496,25456,25456,25456, 42368, 42368, 42368, 43816, 43816, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 46888},
25456,26416,26416,26416,26416,27376,27376,27376,27376,28336,28336}, {440, 904, 1384, 1864, 2344, 2792, 3240, 3752, 4136, 4584, 5160, 5544, 5992, 6456, 6968, 7480,
{ 256, 552, 840, 1128, 1416, 1736, 1992, 2280, 2600, 2856, 3112, 7992, 8248, 8760, 9144, 9912, 10296, 10680, 11064, 11448, 12216, 12576, 12960, 13536, 14112, 14688, 14688,
3496, 3752, 4008, 4264, 4584, 4968, 5160, 5544, 5736, 5992, 6200, 15264, 15840, 16416, 16992, 16992, 17568, 18336, 18336, 19080, 19848, 19848, 20616, 20616, 21384, 22152, 22152,
6456, 6968, 7224, 7480, 7736, 7992, 8248, 8504, 8760, 9144, 9528, 22920, 22920, 23688, 24496, 24496, 25456, 25456, 26416, 26416, 27376, 27376, 28336, 28336, 29296, 29296, 29296,
9912, 9912,10296,10680,11064,11064,11448,11832,12216,12216,12576, 30576, 30576, 31704, 31704, 31704, 32856, 32856, 34008, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696,
12960,12960,13536,13536,14112,14112,14688,14688,15264,15264,15840, 37888, 37888, 39232, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 42368, 42368, 43816, 43816, 43816, 45352,
15840,16416,16416,16992,16992,17568,17568,18336,18336,18336,19080, 45352, 45352, 46888, 46888, 46888, 46888, 48936, 48936, 48936, 48936, 48936, 51024, 51024, 51024},
19080,19848,19848,19848,20616,20616,20616,21384,21384,22152,22152, {488, 1000, 1480, 1992, 2472, 2984, 3496, 4008, 4584, 4968, 5544, 5992, 6456, 6968, 7480, 7992,
22152,22920,22920,22920,23688,23688,24496,24496,24496,25456,25456, 8504, 9144, 9528, 9912, 10680, 11064, 11448, 12216, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 15840,
25456,25456,26416,26416,26416,27376,27376,27376,28336,28336,28336, 16416, 16992, 17568, 18336, 18336, 19080, 19848, 19848, 20616, 21384, 21384, 22152, 22920, 22920, 23688, 24496,
28336,29296,29296,29296,29296,30576,30576,30576,30576,31704,31704}, 24496, 25456, 25456, 26416, 26416, 27376, 27376, 28336, 28336, 29296, 29296, 30576, 30576, 31704, 31704, 31704,
{ 280, 600, 904, 1224, 1544, 1800, 2152, 2472, 2728, 3112, 3368, 32856, 32856, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 39232, 39232, 39232, 40576,
3624, 4008, 4264, 4584, 4968, 5160, 5544, 5736, 6200, 6456, 6712, 40576, 40576, 42368, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 46888, 48936,
6968, 7224, 7736, 7992, 8248, 8504, 8760, 9144, 9528, 9912,10296, 48936, 48936, 48936, 51024, 51024, 51024, 51024, 52752, 52752, 52752, 52752, 55056, 55056, 55056},
10296,10680,11064,11448,11832,11832,12216,12576,12960,12960,13536, {520, 1064, 1608, 2152, 2664, 3240, 3752, 4264, 4776, 5352, 5992, 6456, 6968, 7480, 7992, 8504,
13536,14112,14688,14688,15264,15264,15840,15840,16416,16416,16992, 9144, 9528, 10296, 10680, 11448, 11832, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 16992,
16992,17568,17568,18336,18336,18336,19080,19080,19848,19848,20616, 17568, 18336, 19080, 19080, 19848, 20616, 21384, 21384, 22152, 22920, 22920, 23688, 24496, 24496, 25456, 25456,
20616,20616,21384,21384,22152,22152,22152,22920,22920,23688,23688, 26416, 27376, 27376, 28336, 28336, 29296, 29296, 30576, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 34008,
23688,24496,24496,24496,25456,25456,25456,26416,26416,26416,27376, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 42368, 43816,
27376,27376,28336,28336,28336,29296,29296,29296,29296,30576,30576, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 48936, 48936, 48936, 48936, 51024, 51024, 51024, 51024,
30576,30576,31704,31704,31704,31704,32856,32856,32856,34008,34008}, 52752, 52752, 52752, 55056, 55056, 55056, 55056, 57336, 57336, 57336, 57336, 59256, 59256, 59256},
{ 328, 632, 968, 1288, 1608, 1928, 2280, 2600, 2984, 3240, 3624, {552, 1128, 1736, 2280, 2856, 3496, 4008, 4584, 5160, 5736, 6200, 6968, 7480, 7992, 8504, 9144,
3880, 4264, 4584, 4968, 5160, 5544, 5992, 6200, 6456, 6712, 7224, 9912, 10296, 11064, 11448, 12216, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336,
7480, 7736, 7992, 8504, 8760, 9144, 9528, 9912, 9912,10296,10680, 19080, 19848, 19848, 20616, 21384, 22152, 22152, 22920, 23688, 24496, 24496, 25456, 25456, 26416, 27376, 27376,
11064,11448,11832,12216,12216,12576,12960,13536,13536,14112,14112, 28336, 28336, 29296, 29296, 30576, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 36696, 36696,
14688,14688,15264,15840,15840,16416,16416,16992,16992,17568,17568, 37888, 37888, 37888, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 45352,
18336,18336,19080,19080,19848,19848,19848,20616,20616,21384,21384, 46888, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056,
22152,22152,22152,22920,22920,23688,23688,24496,24496,24496,25456, 55056, 57336, 57336, 57336, 57336, 59256, 59256, 59256, 59256, 61664, 61664, 61664, 61664, 63776},
25456,25456,26416,26416,26416,27376,27376,27376,28336,28336,28336, {584, 1192, 1800, 2408, 2984, 3624, 4264, 4968, 5544, 5992, 6712, 7224, 7992, 8504, 9144, 9912,
29296,29296,29296,30576,30576,30576,30576,31704,31704,31704,31704, 10296, 11064, 11448, 12216, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848,
32856,32856,32856,34008,34008,34008,34008,35160,35160,35160,35160}, 19848, 20616, 21384, 22152, 22920, 22920, 23688, 24496, 25456, 25456, 26416, 26416, 27376, 28336, 28336, 29296,
{ 336, 696, 1064, 1416, 1800, 2152, 2536, 2856, 3240, 3624, 4008, 29296, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 39232,
4392, 4776, 5160, 5352, 5736, 6200, 6456, 6712, 7224, 7480, 7992, 39232, 40576, 40576, 42368, 42368, 42368, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 48936, 48936,
8248, 8760, 9144, 9528, 9912,10296,10296,10680,11064,11448,11832, 48936, 51024, 51024, 51024, 52752, 52752, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, 57336, 59256,
12216,12576,12960,13536,13536,14112,14688,14688,15264,15264,15840, 59256, 59256, 61664, 61664, 61664, 61664, 63776, 63776, 63776, 63776, 66592, 66592, 66592, 66592},
16416,16416,16992,17568,17568,18336,18336,19080,19080,19848,19848, {616, 1256, 1864, 2536, 3112, 3752, 4392, 5160, 5736, 6200, 6968, 7480, 8248, 8760, 9528, 10296,
20616,20616,20616,21384,21384,22152,22152,22920,22920,23688,23688, 10680, 11448, 12216, 12576, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 20616,
24496,24496,24496,25456,25456,26416,26416,26416,27376,27376,27376, 20616, 21384, 22152, 22920, 23688, 24496, 24496, 25456, 26416, 26416, 27376, 28336, 28336, 29296, 29296, 30576,
28336,28336,29296,29296,29296,30576,30576,30576,30576,31704,31704, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 36696, 36696, 37888, 37888, 39232, 39232, 40576, 40576,
31704,32856,32856,32856,34008,34008,34008,35160,35160,35160,35160, 40576, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 46888, 46888, 46888, 48936, 48936, 48936, 51024, 51024,
36696,36696,36696,36696,37888,37888,37888,39232,39232,39232,39232}, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 59256, 61664, 61664,
{ 376, 776, 1160, 1544, 1992, 2344, 2792, 3112, 3624, 4008, 4392, 61664, 61664, 63776, 63776, 63776, 63776, 66592, 66592, 66592, 66592, 68808, 68808, 68808, 71112},
4776, 5160, 5544, 5992, 6200, 6712, 7224, 7480, 7992, 8248, 8760, {712, 1480, 2216, 2984, 3752, 4392, 5160, 5992, 6712, 7480, 8248, 8760, 9528, 10296, 11064, 11832,
9144, 9528, 9912,10296,10680,11064,11448,11832,12216,12576,12960, 12576, 13536, 14112, 14688, 15264, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688,
13536,14112,14112,14688,15264,15264,15840,16416,16416,16992,17568, 24496, 25456, 25456, 26416, 27376, 28336, 29296, 29296, 30576, 30576, 31704, 32856, 32856, 34008, 35160, 35160,
17568,18336,18336,19080,19080,19848,19848,20616,21384,21384,22152, 36696, 36696, 37888, 37888, 39232, 40576, 40576, 40576, 42368, 42368, 43816, 43816, 45352, 45352, 46888, 46888,
22152,22920,22920,23688,23688,24496,24496,24496,25456,25456,26416, 48936, 48936, 48936, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 55056, 57336, 57336, 57336, 59256,
26416,27376,27376,27376,28336,28336,29296,29296,29296,30576,30576, 59256, 59256, 61664, 61664, 61664, 63776, 63776, 63776, 66592, 66592, 66592, 68808, 68808, 68808, 71112, 71112,
30576,31704,31704,31704,32856,32856,32856,34008,34008,34008,35160, 71112, 73712, 73712, 75376, 75376, 75376, 75376, 75376, 75376, 75376, 75376, 75376, 75376, 75376},
35160,35160,36696,36696,36696,37888,37888,37888,37888,39232,39232, {648, 1320, 1992, 2664, 3368, 4008, 4584, 5352, 5992, 6712, 7224, 7992, 8504, 9144, 9912,
39232,40576,40576,40576,40576,42368,42368,42368,42368,43816,43816}, 10680, 11448, 11832, 12576, 12960, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848,
{ 408, 840, 1288, 1736, 2152, 2600, 2984, 3496, 3880, 4264, 4776, 20616, 21384, 22152, 22920, 22920, 23688, 24496, 25456, 25456, 26416, 27376, 27376, 28336, 29296, 29296,
5160, 5544, 5992, 6456, 6968, 7224, 7736, 8248, 8504, 9144, 9528, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 36696, 37888, 39232, 39232, 40576, 40576, 42368,
9912,10296,10680,11064,11448,12216,12576,12960,13536,13536,14112, 42368, 43816, 43816, 43816, 45352, 46888, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 51024, 52752,
14688,15264,15264,15840,16416,16992,16992,17568,18336,18336,19080, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 59256, 59256, 61664, 61664, 61664,
19080,19848,20616,20616,21384,21384,22152,22152,22920,22920,23688, 63776, 63776, 63776, 63776, 66592, 66592, 66592, 66592, 68808, 68808, 71112, 71112, 71112, 71112, 73712},
24496,24496,25456,25456,25456,26416,26416,27376,27376,28336,28336, {680, 1384, 2088, 2792, 3496, 4264, 4968, 5544, 6200, 6968, 7736, 8504, 9144, 9912, 10680, 11064,
29296,29296,29296,30576,30576,30576,31704,31704,32856,32856,32856, 11832, 12576, 13536, 14112, 14688, 15264, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22152,
34008,34008,34008,35160,35160,35160,36696,36696,36696,37888,37888, 22920, 23668, 24496, 25456, 26416, 26416, 27376, 28336, 29296, 29296, 30576, 31704, 32856, 34008, 34008, 35160,
37888,39232,39232,39232,40576,40576,40576,40576,42368,42368,42368, 35160, 36696, 36696, 37888, 39232, 29232, 40576, 40576, 42368, 42368, 42368, 43816, 43816, 45352, 45352, 46888,
43816,43816,43816,43816,45352,45352,45352,46888,46888,46888,46888}, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336,
{ 440, 904, 1384, 1864, 2344, 2792, 3240, 3752, 4136, 4584, 5160, 59256, 59256, 59256, 61664, 61664, 61664, 61664, 63776, 63776, 63776, 66592, 66592, 66592, 66592, 68808, 68808,
5544, 5992, 6456, 6968, 7480, 7992, 8248, 8760, 9144, 9912,10296, 68808, 71112, 71112, 71112, 73712, 73712, 75376, 75376, 76208, 76208},
10680,11064,11448,12216,12576,12960,13536,14112,14688,14688,15264, {712, 1480, 2216, 2984, 3752, 4392, 5160, 5992, 6712, 7480, 8248, 4760, 9528, 10296, 11064, 11832,
15840,16416,16992,16992,17568,18336,18336,19080,19848,19848,20616, 12576, 13536, 14112, 14668, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 61384, 22152, 22920, 23688,
20616,21384,22152,22152,22920,22920,23688,24496,24496,25456,25456, 24496, 25456, 26416, 26416, 27376, 28336, 29296, 29296, 30576, 31704, 31704, 32856, 34008, 34008, 35160, 35160,
26416,26416,27376,27376,28336,28336,29296,29296,29296,30576,30576, 36696, 36696, 37888, 39232, 39232, 40576, 40576, 42368, 42368, 43816, 43816, 45352, 45352, 45352, 46888, 46888,
31704,31704,31704,32856,32856,34008,34008,34008,35160,35160,35160, 48936, 48936, 48936, 51024, 51024, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 59256,
36696,36696,36696,37888,37888,39232,39232,39232,40576,40576,40576, 61664, 61664, 61664, 63776, 63776, 63776, 63776, 66592, 66592, 66592, 66592, 68808, 68808, 68808, 71112, 71112,
42368,42368,42368,42368,43816,43816,43816,45352,45352,45352,46888, 71112, 73712, 73712, 73712, 75376, 76208, 76208, 76208, 78704, 78704, 78704, 81176, 81176, 81176},
46888,46888,46888,48936,48936,48936,48936,48936,51024,51024,51024}, {776, 1544, 2344, 3112, 3880, 4776, 5544, 3200, 3938, 7736, 8504, 9528, 10296, 11064, 11832, 12576,
{ 488, 1000, 1480, 1992, 2472, 2984, 3496, 4008, 4584, 4968, 5544, 13536, 14112, 14688, 15840, 16416, 16992, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 25456,
5992, 6456, 6968, 7480, 7992, 8504, 9144, 9528, 9912,10680,11064, 25456, 26416, 27276, 28336, 29296, 29296, 30576, 31704, 31704, 32856, 34008, 34008, 35160, 36696, 36696, 37888,
11448,12216,12576,12960,13536,14112,14688,15264,15840,15840,16416, 37888, 39232, 40576, 40576, 42368, 42368, 43816, 43816, 45352, 45352, 46888, 46888, 46888, 48936, 48936, 51024,
16992,17568,18336,18336,19080,19848,19848,20616,21384,21384,22152, 51024, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 63776, 63776,
22920,22920,23688,24496,24496,25456,25456,26416,26416,27376,27376, 63776, 63776, 66592, 66592, 66592, 68808, 68808, 68808, 71112, 71112, 71112, 73712, 73712, 75376, 75376, 76208,
28336,28336,29296,29296,30576,30576,31704,31704,31704,32856,32856, 76208, 78704, 78704, 78704, 81176, 81176, 81176, 81176, 84760, 84760, 84760, 84760, 87936},
34008,34008,35160,35160,35160,36696,36696,36696,37888,37888,39232, {808, 1608, 2472, 3240, 4136, 4968, 5736, 6456, 7480, 8248, 9144, 9912, 10680, 11148, 12216, 12960,
39232,39232,40576,40576,40576,42368,42368,42368,43816,43816,43816, 14112, 14688, 15840, 16416, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 25456, 26416,
45352,45352,45352,46888,46888,46888,46888,48936,48936,48936,48936, 27376, 28336, 29296, 29296, 30576, 31704, 31704, 32856, 34008, 35160, 35160, 36696, 36696, 37888, 39232, 39232,
51024,51024,51024,51024,52752,52752,52752,52752,55056,55056,55056}, 40576, 40576, 42368, 42368, 43816, 45352, 45352, 46888, 46888, 46888, 48396, 48396, 51024, 51024, 52752, 52752,
{ 520, 1064, 1608, 2152, 2664, 3240, 3752, 4264, 4776, 5352, 5992, 52752, 55056, 55056, 55056, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 63776, 63776, 63776, 66592, 66592,
6456, 6968, 7480, 7992, 8504, 9144, 9528,10296,10680,11448,11832, 66592, 68808, 68808, 68808, 71112, 71112, 71112, 73712, 73715, 73712, 75376, 76208, 76208, 78704, 78704, 78704,
12576,12960,13536,14112,14688,15264,15840,16416,16992,16992,17568, 81176, 81176, 81176, 81176, 84760, 84760, 84760, 84760, 87936, 87936, 87936, 87936, 90816, 90816},
18336,19080,19080,19848,20616,21384,21384,22152,22920,22920,23688, {840, 1672, 2536, 3368, 4264, 5160, 5992, 6712, 7736, 8504, 9528, 10296, 11064, 11832, 12960, 13536,
24496,24496,25456,25456,26416,27376,27376,28336,28336,29296,29296, 14688, 15264, 16416, 16992, 17458, 19080, 19848, 20616, 21348, 22152, 22920, 23688, 24496, 25456, 26416, 27376,
30576,30576,31704,31704,32856,32856,34008,34008,34008,35160,35160, 28336, 29296, 29296, 30576, 31704, 32856, 32856, 34008, 35160, 35160, 36696, 37888, 37888, 39232, 39232, 40576,
36696,36696,36696,37888,37888,39232,39232,40576,40576,40576,42368, 40576, 42368, 42368, 43816, 43816, 45352, 46888, 46888, 46888, 48936, 48936, 51024, 51024, 52752, 52752, 52752,
42368,42368,43816,43816,43816,45352,45352,45352,46888,46888,46888, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 61664, 61664, 61664, 63776, 63776, 63776, 66592, 66592,
48936,48936,48936,48936,51024,51024,51024,51024,52752,52752,52752, 66592, 68808, 68808, 71112, 71112, 71112, 71112, 73712, 73712, 73712, 75376, 76208, 76208, 78704, 78704, 78704,
55056,55056,55056,55056,57336,57336,57336,57336,59256,59256,59256}, 81176, 81176, 81176, 84760, 84760, 84760, 84760, 87936, 87936, 87936, 90816, 90816, 93800, 93800},
{ 552, 1128, 1736, 2280, 2856, 3496, 4008, 4584, 5160, 5736, 6200, {968, 1992, 2984, 4008, 4968, 5992, 6968, 7992, 8760, 9912, 10680, 11832, 12960, 13536, 14688, 15840,
6968, 7480, 7992, 8504, 9144, 9912,10296,11064,11448,12216,12576, 16992, 17568, 19080, 19848, 20616, 21384, 22920, 23688, 24496, 25456, 26416, 27376, 28336, 29296, 30576, 31704,
12960,13536,14112,14688,15264,15840,16416,16992,17568,18336,19080, 32856, 34008, 35160, 35160, 36696, 37888, 39232, 39232, 40576, 40576, 42368, 43816, 43816, 45352, 46888, 46888,
19848,19848,20616,21384,22152,22152,22920,23688,24496,24496,25456, 48936, 48936, 51024, 51024, 52752, 52752, 55056, 55056, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 63776,
25456,26416,27376,27376,28336,28336,29296,29296,30576,30576,31704, 63776, 63776, 66592, 66592, 68808, 68808, 71112, 71112, 71112, 73712, 75376, 76208, 73208, 76208, 78704, 78704,
31704,32856,32856,34008,34008,35160,35160,36696,36696,37888,37888, 81176, 81176, 81176, 81176, 84760, 84760, 84760, 87636, 87936, 87936, 90816, 90816, 90816, 93800, 93800, 93800,
37888,39232,39232,40576,40576,40576,42368,42368,43816,43816,43816, 93800, 97896, 97896, 97896, 97896, 97896, 97896, 97896, 97896, 97896, 97896, 97896, 97896, 97896}};
45352,45352,45352,46888,46888,46888,48936,48936,48936,51024,51024,
51024,51024,52752,52752,52752,55056,55056,55056,55056,57336,57336,
57336,57336,59256,59256,59256,59256,61664,61664,61664,61664,63776},
{ 584, 1192, 1800, 2408, 2984, 3624, 4264, 4968, 5544, 5992, 6712,
7224, 7992, 8504, 9144, 9912,10296,11064,11448,12216,12960,13536,
14112,14688,15264,15840,16416,16992,17568,18336,19080,19848,19848,
20616,21384,22152,22920,22920,23688,24496,25456,25456,26416,26416,
27376,28336,28336,29296,29296,30576,31704,31704,32856,32856,34008,
34008,35160,35160,36696,36696,36696,37888,37888,39232,39232,40576,
40576,42368,42368,42368,43816,43816,45352,45352,45352,46888,46888,
46888,48936,48936,48936,51024,51024,51024,52752,52752,52752,52752,
55056,55056,55056,57336,57336,57336,57336,59256,59256,59256,61664,
61664,61664,61664,63776,63776,63776,63776,66592,66592,66592,66592},
{ 616, 1256, 1864, 2536, 3112, 3752, 4392, 5160, 5736, 6200, 6968,
7480, 8248, 8760, 9528,10296,10680,11448,12216,12576,13536,14112,
14688,15264,15840,16416,16992,17568,18336,19080,19848,20616,20616,
21384,22152,22920,23688,24496,24496,25456,26416,26416,27376,28336,
28336,29296,29296,30576,31704,31704,32856,32856,34008,34008,35160,
35160,36696,36696,37888,37888,39232,39232,40576,40576,40576,42368,
42368,43816,43816,43816,45352,45352,46888,46888,46888,48936,48936,
48936,51024,51024,51024,52752,52752,52752,55056,55056,55056,55056,
57336,57336,57336,59256,59256,59256,61664,61664,61664,61664,63776,
63776,63776,63776,66592,66592,66592,66592,68808,68808,68808,71112},
{ 712, 1480, 2216, 2984, 3752, 4392, 5160, 5992, 6712, 7480, 8248,
8760, 9528,10296,11064,11832,12576,13536,14112,14688,15264,16416,
16992,17568,18336,19080,19848,20616,21384,22152,22920,23688,24496,
25456,25456,26416,27376,28336,29296,29296,30576,30576,31704,32856,
32856,34008,35160,35160,36696,36696,37888,37888,39232,40576,40576,
40576,42368,42368,43816,43816,45352,45352,46888,46888,48936,48936,
48936,51024,51024,52752,52752,52752,55056,55056,55056,55056,57336,
57336,57336,59256,59256,59256,61664,61664,61664,63776,63776,63776,
66592,66592,66592,68808,68808,68808,71112,71112,71112,73712,73712,
75376,75376,75376,75376,75376,75376,75376,75376,75376,75376,75376}};

@ -123,6 +123,14 @@ add_test(pdsch_test_cdd_50 pdsch_test -x 3 -a 2 -t 0 -n 50)
add_test(pdsch_test_cdd_75 pdsch_test -x 3 -a 2 -t 0 -n 75) add_test(pdsch_test_cdd_75 pdsch_test -x 3 -a 2 -t 0 -n 75)
add_test(pdsch_test_cdd_100 pdsch_test -x 3 -a 2 -t 0 -n 100) add_test(pdsch_test_cdd_100 pdsch_test -x 3 -a 2 -t 0 -n 100)
# PDSCH test for CDD transmision mode (2 codeword) and 256QAM
add_test(pdsch_test_cdd_6 pdsch_test -x 3 -a 2 -t 0 -m 27 -M 27 -n 6 -q)
add_test(pdsch_test_cdd_12 pdsch_test -x 3 -a 2 -t 0 -m 27 -M 27 -n 12 -q)
add_test(pdsch_test_cdd_25 pdsch_test -x 3 -a 2 -t 0 -m 27 -M 27 -n 25 -q)
add_test(pdsch_test_cdd_50 pdsch_test -x 3 -a 2 -t 0 -m 27 -M 27 -n 50 -q)
add_test(pdsch_test_cdd_75 pdsch_test -x 3 -a 2 -t 0 -m 27 -M 27 -n 75 -q)
add_test(pdsch_test_cdd_100 pdsch_test -x 3 -a 2 -t 0 -m 27 -M 27 -n 100 -q)
# PDSCH test for Spatial Multiplex transmision mode with PMI = 0 (1 codeword) # PDSCH test for Spatial Multiplex transmision mode with PMI = 0 (1 codeword)
add_test(pdsch_test_multiplex1cw_p0_6 pdsch_test -x 4 -a 2 -p 0 -n 6) add_test(pdsch_test_multiplex1cw_p0_6 pdsch_test -x 4 -a 2 -p 0 -n 6)
add_test(pdsch_test_multiplex1cw_p0_12 pdsch_test -x 4 -a 2 -p 0 -n 12) add_test(pdsch_test_multiplex1cw_p0_12 pdsch_test -x 4 -a 2 -p 0 -n 12)

@ -53,7 +53,7 @@ static bool enable_coworker = false;
static uint32_t pmi = 0; static uint32_t pmi = 0;
static char* input_file = NULL; static char* input_file = NULL;
static int M = 1; static int M = 1;
static bool enable_256qam = false;
static bool use_8_bit = false; static bool use_8_bit = false;
void usage(char *prog) { void usage(char *prog) {
@ -76,11 +76,12 @@ void usage(char *prog) {
printf("\t-w Swap Transport Blocks\n"); printf("\t-w Swap Transport Blocks\n");
printf("\t-j Enable PDSCH decoder coworker\n"); printf("\t-j Enable PDSCH decoder coworker\n");
printf("\t-v [set srslte_verbose to debug, default none]\n"); printf("\t-v [set srslte_verbose to debug, default none]\n");
printf("\t-q Enable/Disable 256QAM modulation (default %s)\n", enable_256qam ? "enabled" : "disabled");
} }
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "fmMcsbrtRFpnawvXxj")) != -1) { while ((opt = getopt(argc, argv, "fmMcsbrtRFpnqawvXxj")) != -1) {
switch(opt) { switch(opt) {
case 'f': case 'f':
input_file = argv[optind]; input_file = argv[optind];
@ -136,6 +137,9 @@ void parse_args(int argc, char **argv) {
case 'v': case 'v':
srslte_verbose++; srslte_verbose++;
break; break;
case 'q':
enable_256qam ^= true;
break;
default: default:
usage(argv[0]); usage(argv[0]);
exit(-1); exit(-1);
@ -143,6 +147,40 @@ void parse_args(int argc, char **argv) {
} }
} }
static int check_softbits(
srslte_pdsch_t* pdsch_enb, srslte_pdsch_t* pdsch_ue, srslte_pdsch_cfg_t* pdsch_cfg, uint32_t sf_idx, int tb)
{
int ret = SRSLTE_SUCCESS;
if (!pdsch_ue->llr_is_8bit && !tb_cw_swap) {
// Generate sequence
srslte_sequence_pdsch(&pdsch_ue->tmp_seq,
rnti,
pdsch_cfg->grant.tb[tb].cw_idx,
2 * (sf_idx % 10),
cell.id,
pdsch_cfg->grant.tb[tb].nof_bits);
// Scramble
srslte_scrambling_s_offset(&pdsch_ue->tmp_seq, pdsch_ue->e[tb], 0, pdsch_cfg->grant.tb[tb].nof_bits);
int16_t* rx = pdsch_ue->e[tb];
uint8_t* rx_bytes = pdsch_ue->e[tb];
for (int i = 0, k = 0; i < pdsch_cfg->grant.tb[tb].nof_bits / 8; i++) {
uint8_t w = 0;
for (int j = 0; j < 8; j++, k++) {
w |= (rx[k] > 0) ? (1 << (7 - j)) : 0;
}
rx_bytes[i] = w;
}
if (memcmp(pdsch_ue->e[tb], pdsch_enb->e[tb], pdsch_cfg->grant.tb[tb].nof_bits / 8) != 0) {
ret = SRSLTE_ERROR;
}
}
return ret;
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
int ret = -1; int ret = -1;
struct timeval t[3] = {}; struct timeval t[3] = {};
@ -235,7 +273,7 @@ int main(int argc, char **argv) {
pdsch_cfg.p_b = (tm > SRSLTE_TM1) ? 1 : 0; // 0 dB pdsch_cfg.p_b = (tm > SRSLTE_TM1) ? 1 : 0; // 0 dB
/* Generate dci from DCI */ /* Generate dci from DCI */
if (srslte_ra_dl_dci_to_grant(&cell, &dl_sf, tm, &dci, &pdsch_cfg.grant)) { if (srslte_ra_dl_dci_to_grant(&cell, &dl_sf, tm, enable_256qam, &dci, &pdsch_cfg.grant)) {
ERROR("Error computing resource allocation\n"); ERROR("Error computing resource allocation\n");
return ret; return ret;
} }
@ -470,17 +508,22 @@ int main(int argc, char **argv) {
/* Check Tx and Rx bytes */ /* Check Tx and Rx bytes */
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (pdsch_cfg.grant.tb[tb].enabled) { if (pdsch_cfg.grant.tb[tb].enabled) {
for (int byte = 0; byte < pdsch_cfg.grant.tb[tb].tbs / 8; byte++) { if (check_softbits(&pdsch_tx, &pdsch_rx, &pdsch_cfg, subframe, tb)) {
if (data_tx[tb][byte] != data_rx[tb][byte]) { printf("TB%d: The received softbits in subframe %d DO NOT match the encoded bits (crc=%d)\n",
ERROR("Found BYTE (%d) error in TB %d (%02X != %02X), quiting...", tb,
byte, subframe,
tb, pdsch_res[tb].crc);
data_tx[tb][byte], } else {
data_rx[tb][byte]); for (int byte = 0; byte < pdsch_cfg.grant.tb[tb].tbs / 8; byte++) {
// printf("Tx: "); srslte_vec_fprint_byte(stdout, data_tx[tb], dci.mcs[tb].tbs / 8); if (data_tx[tb][byte] != data_rx[tb][byte]) {
// printf("Rx: "); srslte_vec_fprint_byte(stdout, data_rx[tb], dci.mcs[tb].tbs / 8); ERROR("Found BYTE (%d) error in TB %d (%02X != %02X), quitting...",
ret = SRSLTE_ERROR; byte,
goto quit; tb,
data_tx[tb][byte],
data_rx[tb][byte]);
ret = SRSLTE_ERROR;
goto quit;
}
} }
} }
} }

@ -210,7 +210,7 @@ int main(int argc, char **argv) {
dci.type0_alloc.rbg_bitmask = 0xffffffff; dci.type0_alloc.rbg_bitmask = 0xffffffff;
dci.tb[0].mcs_idx = 2; dci.tb[0].mcs_idx = 2;
SRSLTE_DCI_TB_DISABLE(dci.tb[1]); SRSLTE_DCI_TB_DISABLE(dci.tb[1]);
srslte_ra_dl_dci_to_grant(&cell, &dl_sf, SRSLTE_TM1, &dci, &pmch_cfg.pdsch_cfg.grant); srslte_ra_dl_dci_to_grant(&cell, &dl_sf, SRSLTE_TM1, false, &dci, &pmch_cfg.pdsch_cfg.grant);
srslte_pdsch_res_t pdsch_res; srslte_pdsch_res_t pdsch_res;
pdsch_res.payload = data; pdsch_res.payload = data;

@ -246,7 +246,7 @@ int main(int argc, char **argv) {
dci.type0_alloc.rbg_bitmask = 0xffffffff; dci.type0_alloc.rbg_bitmask = 0xffffffff;
dci.tb[0].mcs_idx = mcs_idx; dci.tb[0].mcs_idx = mcs_idx;
SRSLTE_DCI_TB_DISABLE(dci.tb[1]); SRSLTE_DCI_TB_DISABLE(dci.tb[1]);
srslte_ra_dl_dci_to_grant(&cell, &dl_sf, SRSLTE_TM1, &dci, &pmch_cfg.pdsch_cfg.grant); srslte_ra_dl_dci_to_grant(&cell, &dl_sf, SRSLTE_TM1, false, &dci, &pmch_cfg.pdsch_cfg.grant);
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (pmch_cfg.pdsch_cfg.grant.tb[i].enabled) { if (pmch_cfg.pdsch_cfg.grant.tb[i].enabled) {

@ -651,7 +651,7 @@ int srslte_ue_dl_dci_to_pdsch_grant(srslte_ue_dl_t* q,
srslte_dci_dl_t* dci, srslte_dci_dl_t* dci,
srslte_pdsch_grant_t* grant) srslte_pdsch_grant_t* grant)
{ {
return srslte_ra_dl_dci_to_grant(&q->cell, sf, cfg->cfg.tm, dci, grant); return srslte_ra_dl_dci_to_grant(&q->cell, sf, cfg->cfg.tm, cfg->pdsch_use_tbs_index_alt, dci, grant);
} }
int srslte_ue_dl_decode_pdsch(srslte_ue_dl_t* q, int srslte_ue_dl_decode_pdsch(srslte_ue_dl_t* q,

@ -31,17 +31,28 @@ set(ue_dl_max_mcs 28)
set(ue_dl_step_mcs 7) set(ue_dl_step_mcs 7)
foreach (cell_n_prb 6 15 25 50 75 100) foreach (cell_n_prb 6 15 25 50 75 100)
foreach (ue_dl_tm 1 2 3 4) foreach (allow_256 0 1)
foreach (ue_dl_mcs RANGE ${ue_dl_min_mcs} ${ue_dl_max_mcs} ${ue_dl_step_mcs}) foreach (ue_dl_tm 1 2 3 4)
set(phy_dl_test_args "") foreach (ue_dl_mcs RANGE ${ue_dl_min_mcs} ${ue_dl_max_mcs} ${ue_dl_step_mcs})
set(phy_dl_test_args "")
set(phy_dl_test_args ${phy_dl_test_args} -p ${cell_n_prb}) set(phy_dl_test_args ${phy_dl_test_args} -p ${cell_n_prb})
set(phy_dl_test_args ${phy_dl_test_args} -t ${ue_dl_tm}) set(phy_dl_test_args ${phy_dl_test_args} -t ${ue_dl_tm})
set(phy_dl_test_args ${phy_dl_test_args} -m ${ue_dl_mcs}) if (${allow_256})
if (${ue_dl_mcs} EQUAL 28)
if (${cell_n_prb} EQUAL 15)
set(ue_dl_mcs 26)
else (${cell_n_prb} EQUAL 15)
set(ue_dl_mcs 27)
endif (${cell_n_prb} EQUAL 15)
endif (${ue_dl_mcs} EQUAL 28)
string(REGEX REPLACE "\ " "" test_name_args ${phy_dl_test_args}) set(phy_dl_test_args ${phy_dl_test_args} -q)
endif (${allow_256})
add_test(phy_dl_test${test_name_args} phy_dl_test ${phy_dl_test_args}) set(phy_dl_test_args ${phy_dl_test_args} -m ${ue_dl_mcs})
endforeach (ue_dl_mcs) string(REGEX REPLACE "\ " "" test_name_args ${phy_dl_test_args})
endforeach(ue_dl_tm) add_test(phy_dl_test${test_name_args} phy_dl_test ${phy_dl_test_args})
endforeach (ue_dl_mcs)
endforeach (ue_dl_tm)
endforeach (allow_256 0 1)
endforeach (cell_n_prb) endforeach (cell_n_prb)

@ -37,14 +37,15 @@ srslte_cell_t cell = {
.phich_length = SRSLTE_PHICH_NORM .phich_length = SRSLTE_PHICH_NORM
}; };
uint32_t transmission_mode = 1; static uint32_t transmission_mode = 1;
uint32_t cfi = 1; static uint32_t cfi = 1;
uint32_t nof_rx_ant = 1; static uint32_t nof_rx_ant = 1;
uint32_t nof_subframes = 0; static uint32_t nof_subframes = 0;
uint16_t rnti = 0x1234; static uint16_t rnti = 0x1234;
bool print_dci_table; static bool print_dci_table;
uint32_t mcs = 20; static uint32_t mcs = 20;
int cross_carrier_indicator = -1; static int cross_carrier_indicator = -1;
static bool enable_256qam = false;
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [cfpndvs]\n", prog); printf("Usage: %s [cfpndvs]\n", prog);
@ -62,6 +63,7 @@ void usage(char *prog) {
printf("\t\t-a carrier-indicator [Default none]\n"); printf("\t\t-a carrier-indicator [Default none]\n");
} }
printf("\t-v [set srslte_verbose to debug, default none]\n"); printf("\t-v [set srslte_verbose to debug, default none]\n");
printf("\t-q Enable/Disable 256QAM modulation (default %s)\n", enable_256qam ? "enabled" : "disabled");
} }
void parse_extensive_param(char* param, char* arg) void parse_extensive_param(char* param, char* arg)
@ -81,7 +83,17 @@ void parse_extensive_param(char* param, char* arg)
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "cfapndvstm")) != -1) {
// Load default transmission mode to avoid wrong number of ports/antennas
if (transmission_mode == 0) {
cell.nof_ports = 1;
nof_rx_ant = 1;
} else if (transmission_mode < 4) {
cell.nof_ports = 2;
nof_rx_ant = 2;
}
while ((opt = getopt(argc, argv, "cfapndvqstm")) != -1) {
switch (opt) { switch (opt) {
case 't': case 't':
transmission_mode = (uint32_t)strtol(argv[optind], NULL, 10) - 1; transmission_mode = (uint32_t)strtol(argv[optind], NULL, 10) - 1;
@ -118,6 +130,9 @@ void parse_args(int argc, char **argv) {
case 'v': case 'v':
srslte_verbose++; srslte_verbose++;
break; break;
case 'q':
enable_256qam = (enable_256qam) ? false : true;
break;
default: default:
usage(argv[0]); usage(argv[0]);
exit(-1); exit(-1);
@ -145,7 +160,7 @@ int work_enb(srslte_enb_dl_t* enb_dl,
// Create pdsch config // Create pdsch config
srslte_pdsch_cfg_t pdsch_cfg; srslte_pdsch_cfg_t pdsch_cfg;
if (srslte_ra_dl_dci_to_grant(&cell, dl_sf, transmission_mode, dci, &pdsch_cfg.grant)) { if (srslte_ra_dl_dci_to_grant(&cell, dl_sf, transmission_mode, enable_256qam, dci, &pdsch_cfg.grant)) {
ERROR("Computing DL grant sf_idx=%d\n", dl_sf->tti); ERROR("Computing DL grant sf_idx=%d\n", dl_sf->tti);
goto quit; goto quit;
} }
@ -211,7 +226,8 @@ int work_ue(srslte_ue_dl_t* ue_dl,
srslte_dci_dl_info(&dci_dl[0], str, 512); srslte_dci_dl_info(&dci_dl[0], str, 512);
INFO("UE PDCCH: rnti=0x%x, %s\n", rnti, str); INFO("UE PDCCH: rnti=0x%x, %s\n", rnti, str);
if (srslte_ra_dl_dci_to_grant(&cell, sf_cfg_dl, transmission_mode, &dci_dl[0], &ue_dl_cfg->cfg.pdsch.grant)) { if (srslte_ra_dl_dci_to_grant(
&cell, sf_cfg_dl, transmission_mode, enable_256qam, &dci_dl[0], &ue_dl_cfg->cfg.pdsch.grant)) {
ERROR("Computing DL grant sf_idx=%d\n", sf_idx); ERROR("Computing DL grant sf_idx=%d\n", sf_idx);
return -1; return -1;
} }
@ -236,34 +252,31 @@ int work_ue(srslte_ue_dl_t* ue_dl,
unsigned int unsigned int
reverse(register unsigned int x) { reverse(register unsigned int x) {
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); x = (((x & (uint32_t)0xaaaaaaaa) >> (uint32_t)1) | ((x & (uint32_t)0x55555555) << (uint32_t)1));
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); x = (((x & (uint32_t)0xcccccccc) >> (uint32_t)2) | ((x & (uint32_t)0x33333333) << (uint32_t)2));
x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); x = (((x & (uint32_t)0xf0f0f0f0) >> (uint32_t)4) | ((x & (uint32_t)0x0f0f0f0f) << (uint32_t)4));
x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); x = (((x & (uint32_t)0xff00ff00) >> (uint32_t)8) | ((x & (uint32_t)0x00ff00ff) << (uint32_t)8));
return ((x >> 16) | (x << 16)); return ((x >> (uint32_t)16) | (x << (uint32_t)16));
} }
uint32_t prbset_to_bitmask() { uint32_t prbset_to_bitmask() {
uint32_t mask = 0; uint32_t mask = 0;
int nb = (int)ceilf((float)cell.nof_prb / srslte_ra_type0_P(cell.nof_prb)); uint32_t nb = (uint32_t)ceilf((float)cell.nof_prb / srslte_ra_type0_P(cell.nof_prb));
for (int i = 0; i < nb; i++) { for (uint32_t i = 0; i < nb; i++) {
if (i >= prbset_orig && i < prbset_orig + prbset_num) { if (i >= prbset_orig && i < prbset_orig + prbset_num) {
mask = mask | (0x1 << i); mask = mask | ((uint32_t)0x1 << i);
} }
} }
return reverse(mask) >> (32 - nb); return reverse(mask) >> (uint32_t)(32 - nb);
} }
static srslte_enb_dl_t enb_dl; static int
static srslte_ue_dl_t ue_dl; check_softbits(srslte_enb_dl_t* enb_dl, srslte_ue_dl_t* ue_dl, srslte_ue_dl_cfg_t* ue_dl_cfg, uint32_t sf_idx, int tb)
static int check_softbits(srslte_ue_dl_cfg_t* ue_dl_cfg, uint32_t sf_idx, int tb)
{ {
int ret = SRSLTE_SUCCESS; int ret = SRSLTE_SUCCESS;
// Generate sequence // Generate sequence
srslte_sequence_pdsch(&ue_dl.pdsch.tmp_seq, srslte_sequence_pdsch(&ue_dl->pdsch.tmp_seq,
rnti, rnti,
ue_dl_cfg->cfg.pdsch.grant.tb[tb].cw_idx, ue_dl_cfg->cfg.pdsch.grant.tb[tb].cw_idx,
2 * (sf_idx % 10), 2 * (sf_idx % 10),
@ -271,32 +284,35 @@ static int check_softbits(srslte_ue_dl_cfg_t* ue_dl_cfg, uint32_t sf_idx, int tb
ue_dl_cfg->cfg.pdsch.grant.tb[tb].nof_bits); ue_dl_cfg->cfg.pdsch.grant.tb[tb].nof_bits);
// Scramble // Scramble
if (ue_dl.pdsch.llr_is_8bit) { if (ue_dl->pdsch.llr_is_8bit) {
srslte_scrambling_sb_offset(&ue_dl.pdsch.tmp_seq, ue_dl.pdsch.e[tb], 0, ue_dl_cfg->cfg.pdsch.grant.tb[tb].nof_bits); srslte_scrambling_sb_offset(
&ue_dl->pdsch.tmp_seq, ue_dl->pdsch.e[tb], 0, ue_dl_cfg->cfg.pdsch.grant.tb[tb].nof_bits);
} else { } else {
srslte_scrambling_s_offset(&ue_dl.pdsch.tmp_seq, ue_dl.pdsch.e[tb], 0, ue_dl_cfg->cfg.pdsch.grant.tb[tb].nof_bits); srslte_scrambling_s_offset(
&ue_dl->pdsch.tmp_seq, ue_dl->pdsch.e[tb], 0, ue_dl_cfg->cfg.pdsch.grant.tb[tb].nof_bits);
} }
int16_t* rx = ue_dl.pdsch.e[tb]; int16_t* rx = ue_dl->pdsch.e[tb];
uint8_t* rx_bytes = ue_dl.pdsch.e[tb]; uint8_t* rx_bytes = ue_dl->pdsch.e[tb];
for (int i = 0, k = 0; i < ue_dl_cfg->cfg.pdsch.grant.tb[tb].nof_bits / 8; i++) { for (int i = 0, k = 0; i < ue_dl_cfg->cfg.pdsch.grant.tb[tb].nof_bits / 8; i++) {
uint8_t w = 0; uint8_t w = 0;
for (int j = 0; j < 8; j++, k++) { for (int j = 0; j < 8; j++, k++) {
w |= (rx[k] > 0) ? (1 << (7 - j)) : 0; w |= (rx[k] > 0) ? ((uint32_t)1 << (uint32_t)(7 - j)) : 0;
} }
rx_bytes[i] = w; rx_bytes[i] = w;
} }
if (memcmp(ue_dl.pdsch.e[tb], enb_dl.pdsch.e[tb], ue_dl_cfg->cfg.pdsch.grant.tb[tb].nof_bits / 8) != 0) { if (memcmp(ue_dl->pdsch.e[tb], enb_dl->pdsch.e[tb], ue_dl_cfg->cfg.pdsch.grant.tb[tb].nof_bits / 8) != 0) {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
} }
return ret; return ret;
} }
static int check_evm(srslte_ue_dl_cfg_t* ue_dl_cfg, int tb) static int check_evm(srslte_enb_dl_t* enb_dl, srslte_ue_dl_t* ue_dl, srslte_ue_dl_cfg_t* ue_dl_cfg, int tb)
{ {
int ret = SRSLTE_SUCCESS; int ret = SRSLTE_SUCCESS;
srslte_vec_sub_ccc(enb_dl.pdsch.d[tb], ue_dl.pdsch.d[tb], enb_dl.pdsch.d[tb], ue_dl_cfg->cfg.pdsch.grant.nof_re); srslte_vec_sub_ccc(enb_dl->pdsch.d[tb], ue_dl->pdsch.d[tb], enb_dl->pdsch.d[tb], ue_dl_cfg->cfg.pdsch.grant.nof_re);
float evm = srslte_vec_avg_power_cf(enb_dl.pdsch.d[tb], ue_dl_cfg->cfg.pdsch.grant.nof_re); uint32_t evm_max_i = srslte_vec_max_abs_ci(enb_dl->pdsch.d[tb], ue_dl_cfg->cfg.pdsch.grant.nof_re);
float evm = cabsf(enb_dl->pdsch.d[tb][evm_max_i]);
if (evm > 0.1f) { if (evm > 0.1f) {
printf("TB%d Constellation EVM (%.3f) is too high\n", tb, evm); printf("TB%d Constellation EVM (%.3f) is too high\n", tb, evm);
@ -307,6 +323,8 @@ static int check_evm(srslte_ue_dl_cfg_t* ue_dl_cfg, int tb)
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
srslte_enb_dl_t* enb_dl = srslte_vec_malloc(sizeof(srslte_enb_dl_t));
srslte_ue_dl_t* ue_dl = srslte_vec_malloc(sizeof(srslte_ue_dl_t));
srslte_random_t random = srslte_random_init(0); srslte_random_t random = srslte_random_init(0);
struct timeval t[3] = {}; struct timeval t[3] = {};
size_t tx_nof_bits = 0, rx_nof_bits = 0; size_t tx_nof_bits = 0, rx_nof_bits = 0;
@ -374,17 +392,17 @@ int main(int argc, char **argv) {
/* /*
* Initialise eNb * Initialise eNb
*/ */
if (srslte_enb_dl_init(&enb_dl, signal_buffer, cell.nof_prb)) { if (srslte_enb_dl_init(enb_dl, signal_buffer, cell.nof_prb)) {
ERROR("Error initiating eNb downlink\n"); ERROR("Error initiating eNb downlink\n");
goto quit; goto quit;
} }
if (srslte_enb_dl_set_cell(&enb_dl, cell)) { if (srslte_enb_dl_set_cell(enb_dl, cell)) {
ERROR("Error setting eNb DL cell\n"); ERROR("Error setting eNb DL cell\n");
goto quit; goto quit;
} }
if (srslte_enb_dl_add_rnti(&enb_dl, rnti)) { if (srslte_enb_dl_add_rnti(enb_dl, rnti)) {
ERROR("Error adding RNTI\n"); ERROR("Error adding RNTI\n");
goto quit; goto quit;
} }
@ -392,17 +410,17 @@ int main(int argc, char **argv) {
/* /*
* Initialise UE * Initialise UE
*/ */
if (srslte_ue_dl_init(&ue_dl, signal_buffer, cell.nof_prb, nof_rx_ant)) { if (srslte_ue_dl_init(ue_dl, signal_buffer, cell.nof_prb, nof_rx_ant)) {
ERROR("Error initiating UE downlink\n"); ERROR("Error initiating UE downlink\n");
goto quit; goto quit;
} }
if (srslte_ue_dl_set_cell(&ue_dl, cell)) { if (srslte_ue_dl_set_cell(ue_dl, cell)) {
ERROR("Error setting UE downlink cell\n"); ERROR("Error setting UE downlink cell\n");
goto quit; goto quit;
} }
srslte_ue_dl_set_rnti(&ue_dl, rnti); srslte_ue_dl_set_rnti(ue_dl, rnti);
/* /*
* Create PDCCH Allocations * Create PDCCH Allocations
@ -417,7 +435,7 @@ int main(int argc, char **argv) {
sf_cfg_dl.cfi = cfi; sf_cfg_dl.cfi = cfi;
sf_cfg_dl.sf_type = SRSLTE_SF_NORM; sf_cfg_dl.sf_type = SRSLTE_SF_NORM;
nof_locations[i] = srslte_pdcch_ue_locations(&enb_dl.pdcch, &sf_cfg_dl, dci_locations[i], MAX_CANDIDATES_UE, rnti); nof_locations[i] = srslte_pdcch_ue_locations(&enb_dl->pdcch, &sf_cfg_dl, dci_locations[i], MAX_CANDIDATES_UE, rnti);
location_counter += nof_locations[i]; location_counter += nof_locations[i];
} }
@ -529,7 +547,7 @@ int main(int argc, char **argv) {
INFO("--- Process eNb ---\n"); INFO("--- Process eNb ---\n");
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
if (work_enb(&enb_dl, &sf_cfg_dl, &dci_cfg, &dci, softbuffer_tx, data_tx)) { if (work_enb(enb_dl, &sf_cfg_dl, &dci_cfg, &dci, softbuffer_tx, data_tx)) {
goto quit; goto quit;
} }
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
@ -576,6 +594,7 @@ int main(int argc, char **argv) {
ue_dl_cfg.chest_cfg.cfo_estimate_sf_mask = false; ue_dl_cfg.chest_cfg.cfo_estimate_sf_mask = false;
ue_dl_cfg.chest_cfg.sync_error_enable = false; ue_dl_cfg.chest_cfg.sync_error_enable = false;
ue_dl_cfg.dci_cfg = dci_cfg; ue_dl_cfg.dci_cfg = dci_cfg;
ue_dl_cfg.pdsch_use_tbs_index_alt = enable_256qam;
srslte_pdsch_res_t pdsch_res[SRSLTE_MAX_CODEWORDS]; srslte_pdsch_res_t pdsch_res[SRSLTE_MAX_CODEWORDS];
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
@ -584,7 +603,7 @@ int main(int argc, char **argv) {
pdsch_res[i].crc = false; pdsch_res[i].crc = false;
ue_dl_cfg.cfg.pdsch.softbuffers.rx[i] = softbuffer_rx[i]; ue_dl_cfg.cfg.pdsch.softbuffers.rx[i] = softbuffer_rx[i];
} }
if (work_ue(&ue_dl, &sf_cfg_dl, &ue_dl_cfg, dci_dl, sf_idx, pdsch_res)) { if (work_ue(ue_dl, &sf_cfg_dl, &ue_dl_cfg, dci_dl, sf_idx, pdsch_res)) {
goto quit; goto quit;
} }
@ -594,15 +613,15 @@ int main(int argc, char **argv) {
for (int i = 0; i < SRSLTE_MAX_TB; i++) { for (int i = 0; i < SRSLTE_MAX_TB; i++) {
if (ue_dl_cfg.cfg.pdsch.grant.tb[i].enabled) { if (ue_dl_cfg.cfg.pdsch.grant.tb[i].enabled) {
if (check_evm(&ue_dl_cfg, i)) { if (check_evm(enb_dl, ue_dl, &ue_dl_cfg, i)) {
count_failures++; count_failures++;
} else if (check_softbits(&ue_dl_cfg, sf_idx, i) != SRSLTE_SUCCESS) { } else if (check_softbits(enb_dl, ue_dl, &ue_dl_cfg, sf_idx, i) != SRSLTE_SUCCESS) {
printf("TB%d: The received softbits in subframe %d DO NOT match the encoded bits (crc=%d)\n", printf("TB%d: The received softbits in subframe %d DO NOT match the encoded bits (crc=%d)\n",
i, i,
sf_idx, sf_idx,
pdsch_res[i].crc); pdsch_res[i].crc);
srslte_vec_fprint_byte(stdout, (uint8_t*)enb_dl.pdsch.e[i], ue_dl_cfg.cfg.pdsch.grant.tb[i].nof_bits / 8); srslte_vec_fprint_byte(stdout, (uint8_t*)enb_dl->pdsch.e[i], ue_dl_cfg.cfg.pdsch.grant.tb[i].nof_bits / 8);
srslte_vec_fprint_byte(stdout, (uint8_t*)ue_dl.pdsch.e[i], ue_dl_cfg.cfg.pdsch.grant.tb[i].nof_bits / 8); srslte_vec_fprint_byte(stdout, (uint8_t*)ue_dl->pdsch.e[i], ue_dl_cfg.cfg.pdsch.grant.tb[i].nof_bits / 8);
count_failures++; count_failures++;
} else if (!pdsch_res[i].crc || } else if (!pdsch_res[i].crc ||
memcmp(data_tx[i], data_rx[i], (uint32_t)ue_dl_cfg.cfg.pdsch.grant.tb[i].tbs / 8) != 0) { memcmp(data_tx[i], data_rx[i], (uint32_t)ue_dl_cfg.cfg.pdsch.grant.tb[i].tbs / 8) != 0) {
@ -637,18 +656,14 @@ int main(int argc, char **argv) {
printf("BLER: %5.1f%%\n", (float) count_failures / (float) count_tbs * 100.0f); printf("BLER: %5.1f%%\n", (float) count_failures / (float) count_tbs * 100.0f);
quit: quit:
srslte_enb_dl_free(&enb_dl); srslte_enb_dl_free(enb_dl);
srslte_ue_dl_free(&ue_dl); srslte_ue_dl_free(ue_dl);
srslte_random_free(random); srslte_random_free(random);
for ( for (int i = 0; i < cell.nof_ports; i++) {
int i = 0; if (signal_buffer[i]) {
i < cell. free(signal_buffer[i]);
nof_ports; }
i++) {
if (signal_buffer[i]) {
free(signal_buffer[i]);
}
} }
for ( for (
@ -672,6 +687,12 @@ int main(int argc, char **argv) {
free(data_rx[i]); free(data_rx[i]);
} }
} }
if (enb_dl) {
free(enb_dl);
}
if (ue_dl) {
free(ue_dl);
}
if (ret) { if (ret) {
printf("Error\n"); printf("Error\n");

@ -779,7 +779,7 @@ int sf_worker::encode_pdsch(stack_interface_phy_lte::dl_sched_grant_t* grants, u
// Compute DL grant // Compute DL grant
if (srslte_ra_dl_dci_to_grant( if (srslte_ra_dl_dci_to_grant(
&phy->cell, &dl_sf, ue_db[rnti]->dl_cfg.tm, &grants[i].dci, &ue_db[rnti]->dl_cfg.pdsch.grant)) { &phy->cell, &dl_sf, ue_db[rnti]->dl_cfg.tm, false, &grants[i].dci, &ue_db[rnti]->dl_cfg.pdsch.grant)) {
Error("Computing DL grant\n"); Error("Computing DL grant\n");
} }

@ -696,8 +696,8 @@ int mac::get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_t* dl_sched_res)
srslte_ra_tb_t mcs_data; srslte_ra_tb_t mcs_data;
mcs.mcs_idx = this->sib13.mbsfn_area_info_list_r9[0].mcch_cfg_r9.sig_mcs_r9; mcs.mcs_idx = this->sib13.mbsfn_area_info_list_r9[0].mcch_cfg_r9.sig_mcs_r9;
mcs_data.mcs_idx = this->mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].pmch_cfg_r9.data_mcs_r9; mcs_data.mcs_idx = this->mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].pmch_cfg_r9.data_mcs_r9;
srslte_dl_fill_ra_mcs(&mcs, 0, this->cell_config.cell.nof_prb); srslte_dl_fill_ra_mcs(&mcs, 0, this->cell_config.cell.nof_prb, false);
srslte_dl_fill_ra_mcs(&mcs_data, 0, this->cell_config.cell.nof_prb); srslte_dl_fill_ra_mcs(&mcs_data, 0, this->cell_config.cell.nof_prb, false);
if (is_mcch) { if (is_mcch) {
build_mch_sched(mcs_data.tbs); build_mch_sched(mcs_data.tbs);

@ -772,8 +772,8 @@ void sched_tester::test_collisions()
for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_data_elems; ++i) { for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_data_elems; ++i) {
alloc_mask.reset(); alloc_mask.reset();
srslte_pdsch_grant_t grant; srslte_pdsch_grant_t grant;
CondError(srslte_ra_dl_dci_to_grant(&cfg.cell, &dl_sf, SRSLTE_TM1, &tti_data.sched_result_dl.data[i].dci, &grant) == CondError(srslte_ra_dl_dci_to_grant(
SRSLTE_ERROR, &cfg.cell, &dl_sf, SRSLTE_TM1, false, &tti_data.sched_result_dl.data[i].dci, &grant) == SRSLTE_ERROR,
"Failed to decode PDSCH grant\n"); "Failed to decode PDSCH grant\n");
for (uint32_t i = 0; i < alloc_mask.size(); ++i) { for (uint32_t i = 0; i < alloc_mask.size(); ++i) {
if (grant.prb_idx[0][i]) { if (grant.prb_idx[0][i]) {
@ -792,8 +792,8 @@ void sched_tester::test_collisions()
} }
for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_bc_elems; ++i) { for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_bc_elems; ++i) {
srslte_pdsch_grant_t grant; srslte_pdsch_grant_t grant;
CondError(srslte_ra_dl_dci_to_grant(&cfg.cell, &dl_sf, SRSLTE_TM1, &tti_data.sched_result_dl.bc[i].dci, &grant) == CondError(srslte_ra_dl_dci_to_grant(
SRSLTE_ERROR, &cfg.cell, &dl_sf, SRSLTE_TM1, false, &tti_data.sched_result_dl.bc[i].dci, &grant) == SRSLTE_ERROR,
"Failed to decode PDSCH grant\n"); "Failed to decode PDSCH grant\n");
alloc_mask.reset(); alloc_mask.reset();
for (uint32_t i = 0; i < alloc_mask.size(); ++i) { for (uint32_t i = 0; i < alloc_mask.size(); ++i) {
@ -811,8 +811,8 @@ void sched_tester::test_collisions()
for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_rar_elems; ++i) { for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_rar_elems; ++i) {
alloc_mask.reset(); alloc_mask.reset();
srslte_pdsch_grant_t grant; srslte_pdsch_grant_t grant;
CondError(srslte_ra_dl_dci_to_grant(&cfg.cell, &dl_sf, SRSLTE_TM1, &tti_data.sched_result_dl.rar[i].dci, &grant) == CondError(srslte_ra_dl_dci_to_grant(
SRSLTE_ERROR, &cfg.cell, &dl_sf, SRSLTE_TM1, false, &tti_data.sched_result_dl.rar[i].dci, &grant) == SRSLTE_ERROR,
"Failed to decode PDSCH grant\n"); "Failed to decode PDSCH grant\n");
for (uint32_t i = 0; i < alloc_mask.size(); ++i) { for (uint32_t i = 0; i < alloc_mask.size(); ++i) {
if (grant.prb_idx[0][i]) { if (grant.prb_idx[0][i]) {

@ -1230,6 +1230,14 @@ void cc_worker::set_pcell_config(phy_interface_rrc_lte::phy_cfg_t* phy_cfg)
ue_dl_cfg.cfg.cqi_report.aperiodic_configured = true; ue_dl_cfg.cfg.cqi_report.aperiodic_configured = true;
ue_dl_cfg.cfg.cqi_report.aperiodic_mode = aperiodic_mode(dedicated->cqi_report_cfg.cqi_report_mode_aperiodic); ue_dl_cfg.cfg.cqi_report.aperiodic_mode = aperiodic_mode(dedicated->cqi_report_cfg.cqi_report_mode_aperiodic);
} }
if (dedicated->cqi_report_cfg_pcell_v1250_present) {
auto cqi_report_cfg_pcell_v1250 = dedicated->cqi_report_cfg_pcell_v1250.get();
if (cqi_report_cfg_pcell_v1250->alt_cqi_table_r12_present) {
ue_dl_cfg.pdsch_use_tbs_index_alt = true;
}
} else {
ue_dl_cfg.pdsch_use_tbs_index_alt = false;
}
if (pregen_enabled) { if (pregen_enabled) {
Info("Pre-generating UL signals...\n"); Info("Pre-generating UL signals...\n");

@ -2620,7 +2620,7 @@ void rrc::send_rrc_ue_cap_info()
for (uint32_t i = 0; i < args.nof_supported_bands; i++) { for (uint32_t i = 0; i < args.nof_supported_bands; i++) {
supported_band_eutra_v1250_s supported_band_eutra_v1250; supported_band_eutra_v1250_s supported_band_eutra_v1250;
// According to 3GPP 36.306 v12 Table 4.1A-1, 256QAM is supported for ue_category_dl 11-16 // According to 3GPP 36.306 v12 Table 4.1A-1, 256QAM is supported for ue_category_dl 11-16
supported_band_eutra_v1250.dl_minus256_qam_r12_present = false; supported_band_eutra_v1250.dl_minus256_qam_r12_present = true;
// According to 3GPP 36.331 v12 UE-EUTRA-Capability field descriptions // According to 3GPP 36.331 v12 UE-EUTRA-Capability field descriptions
// This field is only present when the field ue-CategoryUL is considered to 5 or 13. // This field is only present when the field ue-CategoryUL is considered to 5 or 13.
@ -2901,6 +2901,11 @@ void rrc::apply_phy_config_dedicated(const phys_cfg_ded_s& phy_cnfg)
current_cfg->pucch_cfg_ded = phy_cnfg.pucch_cfg_ded; current_cfg->pucch_cfg_ded = phy_cnfg.pucch_cfg_ded;
} }
if (phy_cnfg.cqi_report_cfg_pcell_v1250_present) {
current_cfg->cqi_report_cfg_pcell_v1250_present = true;
current_cfg->cqi_report_cfg_pcell_v1250 = phy_cnfg.cqi_report_cfg_pcell_v1250;
}
if (phy_cnfg.pucch_cfg_ded_v1020_present) { if (phy_cnfg.pucch_cfg_ded_v1020_present) {
current_cfg->pucch_cfg_ded_v1020_present = true; current_cfg->pucch_cfg_ded_v1020_present = true;
current_cfg->pucch_cfg_ded_v1020 = phy_cnfg.pucch_cfg_ded_v1020; current_cfg->pucch_cfg_ded_v1020 = phy_cnfg.pucch_cfg_ded_v1020;

Loading…
Cancel
Save