Merge branch 'next' into epc.

master
Pedro Alvarez 7 years ago
commit 4b62c9cb06

@ -213,6 +213,6 @@ int main(int argc, char **argv) {
} }
} }
printf("Ok - wrote %d subframes\n", subframe_count); printf("\nOk - wrote %d subframes\n", subframe_count);
exit(0); exit(0);
} }

@ -45,6 +45,17 @@ public:
}; };
class srslte_gw_config_t
{
public:
srslte_gw_config_t(uint32_t lcid_ = 0)
:lcid(lcid_)
{}
uint32_t lcid;
};
class srslte_pdcp_config_t class srslte_pdcp_config_t
{ {
public: public:

@ -51,7 +51,7 @@ public:
logger_file(); logger_file();
logger_file(std::string file); logger_file(std::string file);
~logger_file(); ~logger_file();
void init(std::string file); void init(std::string file, int max_length = -1);
// Implementation of log_out // Implementation of log_out
void log(str_ptr msg); void log(str_ptr msg);
void log(const char *msg); void log(const char *msg);
@ -60,6 +60,9 @@ private:
void run_thread(); void run_thread();
void flush(); void flush();
uint32_t name_idx;
int64_t max_length;
int64_t cur_length;
FILE* logfile; FILE* logfile;
bool inited; bool inited;
bool not_done; bool not_done;

@ -53,7 +53,7 @@ public:
private: private:
void run_period() { void run_period() {
if (m) { if (m) {
metrics_t metric; metrics_t metric = {};
m->get_metrics(metric); m->get_metrics(metric);
for (uint32_t i=0;i<listeners.size();i++) { for (uint32_t i=0;i<listeners.size();i++) {
listeners[i]->set_metrics(metric); listeners[i]->set_metrics(metric);

@ -88,6 +88,7 @@ typedef struct SRSLTE_API {
float sss_signal5[SRSLTE_SSS_LEN]; float sss_signal5[SRSLTE_SSS_LEN];
float tx_amp; float tx_amp;
float rho_b;
uint8_t tmp[1024*128]; uint8_t tmp[1024*128];
@ -122,6 +123,14 @@ SRSLTE_API int srslte_enb_dl_set_cell(srslte_enb_dl_t *q,
SRSLTE_API void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q, SRSLTE_API void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q,
uint32_t cfi); uint32_t cfi);
SRSLTE_API void srslte_enb_dl_set_power_allocation(srslte_enb_dl_t *q,
float rho_a,
float rho_b);
SRSLTE_API void srslte_enb_dl_apply_power_allocation(srslte_enb_dl_t *q);
SRSLTE_API void srslte_enb_dl_prepare_power_allocation(srslte_enb_dl_t *q);
SRSLTE_API void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, SRSLTE_API void srslte_enb_dl_set_amp(srslte_enb_dl_t *q,
float amp); float amp);

@ -68,6 +68,7 @@ typedef struct SRSLTE_API {
uint32_t subband_diff_cqi_cw1; // if RI > 1 then 2N-bit width otherwise 0-bit width uint32_t subband_diff_cqi_cw1; // if RI > 1 then 2N-bit width otherwise 0-bit width
uint32_t pmi; // if RI > 1 then 2-bit width otherwise 1-bit width uint32_t pmi; // if RI > 1 then 2-bit width otherwise 1-bit width
uint32_t N; uint32_t N;
bool ri_present;
bool pmi_present; bool pmi_present;
bool four_antenna_ports; // If cell has 4 antenna ports then true otherwise false bool four_antenna_ports; // If cell has 4 antenna ports then true otherwise false
bool rank_is_not_one; // If rank > 1 then true otherwise false bool rank_is_not_one; // If rank > 1 then true otherwise false
@ -89,8 +90,19 @@ typedef struct SRSLTE_API {
transmission mode 8 configured without PMI/RI reporting). transmission mode 8 configured without PMI/RI reporting).
This is for PUCCH Format 2 reports This is for PUCCH Format 2 reports
*/ */
/* Table 5.2.3.3.1-2: UCI fields for channel quality and precoding information (CQI/PMI) feedback for
wideband reports (transmission mode 4, transmission mode 5 and transmission mode 6)
This is for PUCCH Format 2 reports
*/
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t wideband_cqi; // 4-bit width uint8_t wideband_cqi; // 4-bit width
uint8_t spatial_diff_cqi; // If Rank==1 then it is 0-bit width otherwise it is 3-bit width
uint8_t pmi;
bool pmi_present;
bool four_antenna_ports; // If cell has 4 antenna ports then true otherwise false
bool rank_is_not_one; // If rank > 1 then true otherwise false
} srslte_cqi_format2_wideband_t; } srslte_cqi_format2_wideband_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
@ -164,4 +176,6 @@ SRSLTE_API int srslte_cqi_hl_get_subband_size(int num_prbs);
SRSLTE_API int srslte_cqi_hl_get_no_subbands(int num_prbs); SRSLTE_API int srslte_cqi_hl_get_no_subbands(int num_prbs);
SRSLTE_API void srslte_cqi_to_str(const uint8_t *cqi_value, int cqi_len, char *str, int str_len);
#endif // CQI_ #endif // CQI_

@ -64,10 +64,6 @@ typedef struct SRSLTE_API {
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t uci_cqi[SRSLTE_CQI_MAX_BITS]; uint8_t uci_cqi[SRSLTE_CQI_MAX_BITS];
uint32_t uci_cqi_len; uint32_t uci_cqi_len;
uint8_t uci_dif_cqi[SRSLTE_DIF_CQI_MAX_BITS];
uint32_t uci_dif_cqi_len;
uint8_t uci_pmi[SRSLTE_PMI_MAX_BITS];
uint8_t uci_pmi_len;
uint8_t uci_ri; // Only 1-bit supported for RI uint8_t uci_ri; // Only 1-bit supported for RI
uint32_t uci_ri_len; uint32_t uci_ri_len;
uint8_t uci_ack; // 1st codeword bit for HARQ-ACK uint8_t uci_ack; // 1st codeword bit for HARQ-ACK

@ -97,6 +97,7 @@ typedef struct SRSLTE_API {
srslte_filesource_t file_source; srslte_filesource_t file_source;
bool file_mode; bool file_mode;
float file_cfo; float file_cfo;
bool file_wrap_enable;
srslte_cfo_t file_cfo_correct; srslte_cfo_t file_cfo_correct;
srslte_ue_sync_state_t state; srslte_ue_sync_state_t state;
@ -185,6 +186,9 @@ SRSLTE_API int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q,
SRSLTE_API void srslte_ue_sync_free(srslte_ue_sync_t *q); SRSLTE_API void srslte_ue_sync_free(srslte_ue_sync_t *q);
SRSLTE_API void srslte_ue_sync_file_wrap(srslte_ue_sync_t *q,
bool enable);
SRSLTE_API int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_set_cell(srslte_ue_sync_t *q,
srslte_cell_t cell); srslte_cell_t cell);

@ -48,16 +48,18 @@ logger_file::~logger_file() {
} }
} }
void logger_file::init(std::string file) { void logger_file::init(std::string file, int max_length) {
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&not_empty, NULL); pthread_cond_init(&not_empty, NULL);
pthread_cond_init(&not_full, NULL); pthread_cond_init(&not_full, NULL);
this->max_length = max_length*1024;
name_idx = 0;
filename = file; filename = file;
logfile = fopen(filename.c_str(), "w"); logfile = fopen(filename.c_str(), "w");
if(logfile==NULL) { if(logfile==NULL) {
printf("Error: could not create log file, no messages will be logged!\n"); printf("Error: could not create log file, no messages will be logged!\n");
} }
start(); start(-2);
inited = true; inited = true;
} }
@ -74,17 +76,33 @@ void logger_file::log(str_ptr msg) {
void logger_file::run_thread() { void logger_file::run_thread() {
while(not_done) { while(not_done) {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
while(buffer.empty()) { while(buffer.empty()) {
pthread_cond_wait(&not_empty, &mutex); pthread_cond_wait(&not_empty, &mutex);
} }
str_ptr s = buffer.front(); str_ptr s = buffer.front();
pthread_cond_signal(&not_full); pthread_cond_signal(&not_full);
int n = 0;
if(logfile) if(logfile)
fprintf(logfile, "%s", s->c_str()); n = fprintf(logfile, "%s", s->c_str());
delete s; delete s;
buffer.pop_front(); buffer.pop_front();
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
if (n > 0) {
cur_length += (int64_t) n;
if (cur_length >= max_length && max_length > 0) {
fclose(logfile);
name_idx++;
char numstr[21]; // enough to hold all numbers up to 64-bits
sprintf(numstr, ".%d", name_idx);
string newfilename = filename + numstr ;
logfile = fopen(newfilename.c_str(), "w");
if(logfile==NULL) {
printf("Error: could not create log file, no messages will be logged!\n");
}
cur_length = 0;
}
}
} }
} }

@ -213,6 +213,70 @@ void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q, uint32_t cfi)
srslte_regs_set_cfi(&q->regs, cfi); srslte_regs_set_cfi(&q->regs, cfi);
} }
void srslte_enb_dl_set_power_allocation(srslte_enb_dl_t *q, float rho_a, float rho_b)
{
if (q) {
q->rho_b = rho_b;
srslte_pdsch_set_power_allocation(&q->pdsch, rho_a);
}
}
void srslte_enb_dl_apply_power_allocation(srslte_enb_dl_t *q)
{
uint32_t nof_symbols_slot = SRSLTE_CP_NSYMB(q->cell.cp);
uint32_t nof_re_symbol = SRSLTE_NRE * q->cell.nof_prb;
if (q->rho_b != 0.0f && q->rho_b != 1.0f) {
float scaling = q->rho_b;
for (uint32_t i = 0; i < q->cell.nof_ports; i++) {
for (uint32_t j = 0; j < 2; j++) {
cf_t *ptr;
ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 0);
srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
if (q->cell.cp == SRSLTE_CP_NORM) {
ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 4);
srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
} else {
ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 3);
srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
}
if (q->cell.nof_ports == 4) {
ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 1);
srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
}
}
}
}
}
void srslte_enb_dl_prepare_power_allocation(srslte_enb_dl_t *q)
{
uint32_t nof_symbols_slot = SRSLTE_CP_NSYMB(q->cell.cp);
uint32_t nof_re_symbol = SRSLTE_NRE * q->cell.nof_prb;
if (q->rho_b != 0.0f && q->rho_b != 1.0f) {
float scaling = 1.0f / q->rho_b;
for (uint32_t i = 0; i < q->cell.nof_ports; i++) {
for (uint32_t j = 0; j < 2; j++) {
cf_t *ptr;
ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 0);
srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
if (q->cell.cp == SRSLTE_CP_NORM) {
ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 4);
srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
} else {
ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 3);
srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
}
if (q->cell.nof_ports == 4) {
ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 1);
srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
}
}
}
}
}
void srslte_enb_dl_clear_sf(srslte_enb_dl_t *q) void srslte_enb_dl_clear_sf(srslte_enb_dl_t *q)
{ {
for (int i=0;i<q->cell.nof_ports;i++) { for (int i=0;i<q->cell.nof_ports;i++) {

@ -292,9 +292,7 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS]; uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS];
if (q->users[rnti]) { if (q->users[rnti]) {
uint32_t nof_uci_bits = uci_data->ri_periodic_report ? uci_data->uci_ri_len : (uci_data->uci_cqi_len + uint32_t nof_uci_bits = uci_data->ri_periodic_report ? uci_data->uci_ri_len : (uci_data->uci_cqi_len);
uci_data->uci_dif_cqi_len +
uci_data->uci_pmi_len);
int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits, nof_uci_bits); int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits, nof_uci_bits);
// If we are looking for SR and ACK at the same time and ret=0, means there is no SR. // If we are looking for SR and ACK at the same time and ret=0, means there is no SR.
@ -323,15 +321,6 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
memcpy(uci_data->uci_cqi, pucch_bits, uci_data->uci_cqi_len*sizeof(uint8_t)); memcpy(uci_data->uci_cqi, pucch_bits, uci_data->uci_cqi_len*sizeof(uint8_t));
} }
if (uci_data->uci_dif_cqi_len) {
memcpy(uci_data->uci_dif_cqi, pucch_bits + uci_data->uci_cqi_len, uci_data->uci_dif_cqi_len*sizeof(uint8_t));
}
if (uci_data->uci_pmi_len) {
memcpy(uci_data->uci_pmi, pucch_bits + uci_data->uci_cqi_len + uci_data->uci_dif_cqi_len,
uci_data->uci_pmi_len*sizeof(uint8_t));
}
if (uci_data->uci_ri_len) { if (uci_data->uci_ri_len) {
uci_data->uci_ri = pucch_bits[0]; /* Assume only one bit of RI */ uci_data->uci_ri = pucch_bits[0]; /* Assume only one bit of RI */
} }

@ -42,7 +42,7 @@
#define DEFAULT_GAIN 100 #define DEFAULT_GAIN 100
#define DEFAULT_GAIN_16 10000 #define DEFAULT_GAIN_16 1000
#define VITERBI_16 #define VITERBI_16
#ifndef LV_HAVE_AVX2 #ifndef LV_HAVE_AVX2
@ -73,7 +73,7 @@ int decode37(void *o, uint8_t *symbols, uint8_t *data, uint32_t frame_length) {
} }
update_viterbi37_blk_port(q->ptr, q->tmp, TB_ITER*frame_length, &best_state); update_viterbi37_blk_port(q->ptr, q->tmp, TB_ITER*frame_length, &best_state);
chainback_viterbi37_port(q->ptr, q->tmp, TB_ITER*frame_length, best_state); chainback_viterbi37_port(q->ptr, q->tmp, TB_ITER*frame_length, best_state);
memcpy(data, q->tmp, frame_length*sizeof(uint8_t)); memcpy(data, &q->tmp[((int) (TB_ITER/2))*frame_length], frame_length*sizeof(uint8_t));
} else { } else {
update_viterbi37_blk_port(q->ptr, symbols, frame_length + q->K - 1, NULL); update_viterbi37_blk_port(q->ptr, symbols, frame_length + q->K - 1, NULL);
chainback_viterbi37_port(q->ptr, data, frame_length, 0); chainback_viterbi37_port(q->ptr, data, frame_length, 0);
@ -105,7 +105,7 @@ int decode37_sse(void *o, uint8_t *symbols, uint8_t *data, uint32_t frame_length
} }
update_viterbi37_blk_sse(q->ptr, q->tmp, TB_ITER*frame_length, &best_state); update_viterbi37_blk_sse(q->ptr, q->tmp, TB_ITER*frame_length, &best_state);
chainback_viterbi37_sse(q->ptr, q->tmp, TB_ITER*frame_length, best_state); chainback_viterbi37_sse(q->ptr, q->tmp, TB_ITER*frame_length, best_state);
memcpy(data, q->tmp, frame_length*sizeof(uint8_t)); memcpy(data, &q->tmp[((int) (TB_ITER/2))*frame_length], frame_length*sizeof(uint8_t));
} else { } else {
update_viterbi37_blk_sse(q->ptr, symbols, frame_length+q->K-1, NULL); update_viterbi37_blk_sse(q->ptr, symbols, frame_length+q->K-1, NULL);
chainback_viterbi37_sse(q->ptr, data, frame_length, 0); chainback_viterbi37_sse(q->ptr, data, frame_length, 0);
@ -151,7 +151,7 @@ int decode37_avx2_16bit(void *o, uint16_t *symbols, uint8_t *data, uint32_t fram
} }
update_viterbi37_blk_avx2_16bit(q->ptr, q->tmp_s, TB_ITER*frame_length, &best_state); update_viterbi37_blk_avx2_16bit(q->ptr, q->tmp_s, TB_ITER*frame_length, &best_state);
chainback_viterbi37_avx2_16bit(q->ptr, q->tmp, TB_ITER*frame_length, best_state); chainback_viterbi37_avx2_16bit(q->ptr, q->tmp, TB_ITER*frame_length, best_state);
memcpy(data, q->tmp, frame_length*sizeof(uint8_t)); memcpy(data, &q->tmp[((int) (TB_ITER/2))*frame_length], frame_length*sizeof(uint8_t));
} else { } else {
update_viterbi37_blk_avx2_16bit(q->ptr, symbols, frame_length+q->K-1, NULL); update_viterbi37_blk_avx2_16bit(q->ptr, symbols, frame_length+q->K-1, NULL);
chainback_viterbi37_avx2_16bit(q->ptr, data, frame_length, 0); chainback_viterbi37_avx2_16bit(q->ptr, data, frame_length, 0);
@ -192,7 +192,7 @@ int decode37_avx2(void *o, uint8_t *symbols, uint8_t *data, uint32_t frame_lengt
} }
update_viterbi37_blk_avx2(q->ptr, q->tmp, TB_ITER*frame_length, &best_state); update_viterbi37_blk_avx2(q->ptr, q->tmp, TB_ITER*frame_length, &best_state);
chainback_viterbi37_avx2(q->ptr, q->tmp, TB_ITER*frame_length, best_state); chainback_viterbi37_avx2(q->ptr, q->tmp, TB_ITER*frame_length, best_state);
memcpy(data, q->tmp, frame_length*sizeof(uint8_t)); memcpy(data, &q->tmp[((int) (TB_ITER/2))*frame_length], frame_length*sizeof(uint8_t));
} else { } else {
update_viterbi37_blk_avx2(q->ptr, symbols, frame_length+q->K-1, NULL); update_viterbi37_blk_avx2(q->ptr, symbols, frame_length+q->K-1, NULL);
chainback_viterbi37_avx2(q->ptr, data, frame_length, 0); chainback_viterbi37_avx2(q->ptr, data, frame_length, 0);
@ -237,7 +237,7 @@ int decode37_neon(void *o, uint8_t *symbols, uint8_t *data, uint32_t frame_lengt
} }
update_viterbi37_blk_neon(q->ptr, q->tmp, TB_ITER*frame_length, &best_state); update_viterbi37_blk_neon(q->ptr, q->tmp, TB_ITER*frame_length, &best_state);
chainback_viterbi37_neon(q->ptr, q->tmp, TB_ITER*frame_length, best_state); chainback_viterbi37_neon(q->ptr, q->tmp, TB_ITER*frame_length, best_state);
memcpy(data, q->tmp, frame_length*sizeof(uint8_t)); memcpy(data, &q->tmp[((int) (TB_ITER/2))*frame_length], frame_length*sizeof(uint8_t));
} else { } else {
update_viterbi37_blk_neon(q->ptr, symbols, frame_length+q->K-1, NULL); update_viterbi37_blk_neon(q->ptr, symbols, frame_length+q->K-1, NULL);
chainback_viterbi37_neon(q->ptr, data, frame_length, 0); chainback_viterbi37_neon(q->ptr, data, frame_length, 0);
@ -423,7 +423,7 @@ int init37_avx2_16bit(srslte_viterbi_t *q, int poly[3], uint32_t framebits, bool
q->R = 3; q->R = 3;
q->framebits = framebits; q->framebits = framebits;
q->gain_quant_s = 4; q->gain_quant_s = 4;
q->gain_quant = DEFAULT_GAIN; q->gain_quant = DEFAULT_GAIN_16;
q->tail_biting = tail_biting; q->tail_biting = tail_biting;
q->decode_s = decode37_avx2_16bit; q->decode_s = decode37_avx2_16bit;
q->free = free37_avx2_16bit; q->free = free37_avx2_16bit;
@ -537,7 +537,7 @@ int srslte_viterbi_decode_f(srslte_viterbi_t *q, float *symbols, uint8_t *data,
} }
} }
#ifdef VITERBI_16 #ifdef VITERBI_16
srslte_vec_quant_fus(symbols, q->symbols_us, DEFAULT_GAIN_16/max, 32767.5, 65535, len); srslte_vec_quant_fus(symbols, q->symbols_us, q->gain_quant/max, 32767.5, 65535, len);
return srslte_viterbi_decode_us(q, q->symbols_us, data, frame_length); return srslte_viterbi_decode_us(q, q->symbols_us, data, frame_length);
#else #else
srslte_vec_quant_fuc(symbols, q->symbols_uc, q->gain_quant/max, 127.5, 255, len); srslte_vec_quant_fuc(symbols, q->symbols_uc, q->gain_quant/max, 127.5, 255, len);

@ -301,7 +301,7 @@ void update_viterbi37_blk_avx2_16bit(void *p, unsigned short *syms, int nbits, u
} }
// See if we need to normalize // See if we need to normalize
if (vp->new_metrics->c[0] > 25600) { if (vp->new_metrics->c[0] > 12288) {
int i; int i;
uint16_t adjust; uint16_t adjust;

@ -88,11 +88,30 @@ int srslte_cqi_ue_subband_pack(srslte_cqi_ue_subband_t *msg, uint8_t buff[SRSLTE
return 4+2+msg->L; return 4+2+msg->L;
} }
/* Pack CQI following 3GPP TS 36.212 Tables 5.2.3.3.1-1 and 5.2.3.3.1-2 */
int srslte_cqi_format2_wideband_pack(srslte_cqi_format2_wideband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS]) int srslte_cqi_format2_wideband_pack(srslte_cqi_format2_wideband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS])
{ {
uint8_t *body_ptr = buff; uint8_t *body_ptr = buff;
srslte_bit_unpack(msg->wideband_cqi, &body_ptr, 4); srslte_bit_unpack(msg->wideband_cqi, &body_ptr, 4);
return 4;
if (msg->pmi_present) {
if (msg->four_antenna_ports) {
if (msg->rank_is_not_one) {
srslte_bit_unpack(msg->spatial_diff_cqi, &body_ptr, 3);
}
srslte_bit_unpack(msg->pmi, &body_ptr, 4);
} else {
if (msg->rank_is_not_one) {
srslte_bit_unpack(msg->spatial_diff_cqi, &body_ptr, 3);
srslte_bit_unpack(msg->pmi, &body_ptr, 1);
} else {
srslte_bit_unpack(msg->pmi, &body_ptr, 2);
}
}
}
return (int)(body_ptr - buff);
} }
int srslte_cqi_format2_subband_pack(srslte_cqi_format2_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS]) int srslte_cqi_format2_subband_pack(srslte_cqi_format2_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS])
@ -168,10 +187,27 @@ int srslte_cqi_ue_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_u
return 4+2+msg->L; return 4+2+msg->L;
} }
/* Unpack CQI following 3GPP TS 36.212 Tables 5.2.3.3.1-1 and 5.2.3.3.1-2 */
int srslte_cqi_format2_wideband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_format2_wideband_t *msg) int srslte_cqi_format2_wideband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_format2_wideband_t *msg)
{ {
uint8_t *body_ptr = buff; uint8_t *body_ptr = buff;
msg->wideband_cqi = srslte_bit_pack(&body_ptr, 4); msg->wideband_cqi = (uint8_t) srslte_bit_pack(&body_ptr, 4);
if (msg->pmi_present) {
if (msg->four_antenna_ports) {
if (msg->rank_is_not_one) {
msg->spatial_diff_cqi = (uint8_t) srslte_bit_pack(&body_ptr, 3);
}
msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 4);
} else {
if (msg->rank_is_not_one) {
msg->spatial_diff_cqi = (uint8_t) srslte_bit_pack(&body_ptr, 3);
msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 1);
} else {
msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 2);
}
}
}
return 4; return 4;
} }
@ -203,7 +239,26 @@ int srslte_cqi_size(srslte_cqi_value_t *value) {
switch(value->type) { switch(value->type) {
case SRSLTE_CQI_TYPE_WIDEBAND: case SRSLTE_CQI_TYPE_WIDEBAND:
/* Compute size according to 3GPP TS 36.212 Tables 5.2.3.3.1-1 and 5.2.3.3.1-2 */
size = 4; size = 4;
if (value->wideband.pmi_present) {
if (value->wideband.four_antenna_ports) {
if (value->wideband.rank_is_not_one) {
size += 3; // Differential
} else {
size += 0; // Differential
}
size += 4; // PMI
} else {
if (value->wideband.rank_is_not_one) {
size += 3; // Differential
size += 1; // PMI
} else {
size += 0; // Differential
size += 2; // PMI
}
}
}
break; break;
case SRSLTE_CQI_TYPE_SUBBAND: case SRSLTE_CQI_TYPE_SUBBAND:
size = 4 + (value->subband.subband_label_2_bits) ? 2 : 1; size = 4 + (value->subband.subband_label_2_bits) ? 2 : 1;
@ -398,3 +453,11 @@ int srslte_cqi_hl_get_no_subbands(int nof_prb)
return 0; return 0;
} }
} }
void srslte_cqi_to_str(const uint8_t *cqi_value, int cqi_len, char *str, int str_len) {
int i = 0;
for (i = 0; i < cqi_len && i < (str_len - 1); i++) {
str[i] = (cqi_value[i] == 0)?(char)'0':(char)'1';
}
str[i] = '\0';
}

@ -1135,8 +1135,8 @@ int dci_format2AB_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t
} }
// pack TPC command for PUCCH (not implemented) /* TCP command for PUCCH */
y+=2; srslte_bit_unpack(data->tpc_pucch, &y, 2);
/* harq process number */ /* harq process number */
srslte_bit_unpack(data->harq_process, &y, HARQ_PID_LEN); srslte_bit_unpack(data->harq_process, &y, HARQ_PID_LEN);

@ -819,6 +819,12 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
} }
} }
/* Set scaling configured by Power Allocation */
float scaling = 1.0f;
if (q->rho_a != 0.0f) {
scaling = q->rho_a;
}
// Layer mapping & precode if necessary // Layer mapping & precode if necessary
if (q->cell.nof_ports > 1) { if (q->cell.nof_ports > 1) {
int nof_symbols; int nof_symbols;
@ -842,9 +848,13 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
/* Precode */ /* Precode */
srslte_precoding_type(x, q->symbols, cfg->nof_layers, q->cell.nof_ports, cfg->codebook_idx, srslte_precoding_type(x, q->symbols, cfg->nof_layers, q->cell.nof_ports, cfg->codebook_idx,
nof_symbols, 1.0f, cfg->mimo_type); nof_symbols, scaling, cfg->mimo_type);
} else { } else {
memcpy(q->symbols[0], q->d[0], cfg->nbits[0].nof_re * sizeof(cf_t)); if (scaling == 1.0f) {
memcpy(q->symbols[0], q->d[0], cfg->nbits[0].nof_re * sizeof(cf_t));
} else {
srslte_vec_sc_prod_cfc(q->d[0], scaling, q->symbols[0], cfg->nbits[0].nof_re);
}
} }
/* mapping to resource elements */ /* mapping to resource elements */

@ -609,11 +609,11 @@ int srslte_pusch_decode(srslte_pusch_t *q,
// Set CQI len assuming RI = 1 (3GPP 36.212 Clause 5.2.4.1. Uplink control information on PUSCH without UL-SCH data) // Set CQI len assuming RI = 1 (3GPP 36.212 Clause 5.2.4.1. Uplink control information on PUSCH without UL-SCH data)
if (cqi_value) { if (cqi_value) {
if (cqi_value->type == SRSLTE_CQI_TYPE_SUBBAND_HL) { if (cqi_value->type == SRSLTE_CQI_TYPE_SUBBAND_HL && cqi_value->subband_hl.ri_present) {
cqi_value->subband_hl.rank_is_not_one = false; cqi_value->subband_hl.rank_is_not_one = false;
uci_data->uci_ri_len = (q->cell.nof_ports == 4) ? 2 : 1;
} }
uci_data->uci_cqi_len = (uint32_t) srslte_cqi_size(cqi_value); uci_data->uci_cqi_len = (uint32_t) srslte_cqi_size(cqi_value);
uci_data->uci_ri_len = (q->cell.nof_ports == 4) ? 2 : 1;
} }
// Decode RI/HARQ bits before descrambling // Decode RI/HARQ bits before descrambling

@ -754,15 +754,10 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
uint32_t nb_q = cfg->nbits.nof_bits; uint32_t nb_q = cfg->nbits.nof_bits;
uint32_t Qm = cfg->grant.Qm; uint32_t Qm = cfg->grant.Qm;
// Encode RI if CQI enabled if (uci_data.uci_ri_len > 0) {
if (uci_data.uci_ri_len > 0 || uci_data.uci_cqi_len > 0) {
/* If no RI is reported set it to zero as specified in 3GPP 36.213 clause 7.2.1 */
if (uci_data.uci_ri_len == 0) {
uci_data.uci_ri = 0;
}
float beta = beta_ri_offset[cfg->uci_cfg.I_offset_ri]; float beta = beta_ri_offset[cfg->uci_cfg.I_offset_ri];
if (cfg->cb_segm.tbs == 0) { if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
} }
uint8_t ri[2] = {uci_data.uci_ri, 0}; uint8_t ri[2] = {uci_data.uci_ri, 0};
ret = srslte_uci_encode_ack_ri(cfg, ri, uci_data.uci_ri_len, uci_data.uci_cqi_len, beta, nb_q/Qm, q->ack_ri_bits, true); ret = srslte_uci_encode_ack_ri(cfg, ri, uci_data.uci_ri_len, uci_data.uci_cqi_len, beta, nb_q/Qm, q->ack_ri_bits, true);

@ -581,7 +581,7 @@ static uint32_t encode_ri_ack(uint8_t data[2], uint32_t data_len, srslte_uci_bit
while(i < Qm) { while(i < Qm) {
q_encoded_bits[i++] = UCI_BIT_PLACEHOLDER; q_encoded_bits[i++] = UCI_BIT_PLACEHOLDER;
} }
} else { } else if (data_len == 2) {
q_encoded_bits[i++] = data[0] ? UCI_BIT_1 : UCI_BIT_0; q_encoded_bits[i++] = data[0] ? UCI_BIT_1 : UCI_BIT_0;
q_encoded_bits[i++] = data[1] ? UCI_BIT_1 : UCI_BIT_0; q_encoded_bits[i++] = data[1] ? UCI_BIT_1 : UCI_BIT_0;
while(i<Qm) { while(i<Qm) {
@ -638,6 +638,58 @@ static void decode_ri_ack_2bits(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_
data[2] -= q2 + q5; data[2] -= q2 + q5;
} }
/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit HARQ
*/
int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint8_t acks[2], uint32_t nof_acks,
uint32_t O_cqi, float beta, uint32_t H_prime_total,
srslte_uci_bit_t *ack_bits)
{
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta);
srslte_uci_bit_type_t q_encoded_bits[18];
uint32_t nof_encoded_bits = encode_ri_ack(acks, nof_acks, q_encoded_bits, cfg->grant.Qm);
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]);
uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ack_bits[cfg->grant.Qm*i]);
}
return (int) Qprime;
}
/* Encode UCI RI bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit RI
*/
int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
uint8_t ri,
uint32_t O_cqi, float beta, uint32_t H_prime_total,
srslte_uci_bit_t *ri_bits)
{
// FIXME: It supports RI of 1 bit only
uint8_t data[2] = {ri, 0};
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
srslte_uci_bit_type_t q_encoded_bits[18];
uint32_t nof_encoded_bits = encode_ri_ack(data, 1, q_encoded_bits, cfg->grant.Qm);
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ri_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]);
uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ri_bits[cfg->grant.Qm*i]);
}
return (int) Qprime;
}
/* Encode UCI ACK/RI bits as described in 5.2.2.6 of 36.212 /* Encode UCI ACK/RI bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit RI * Currently only supporting 1-bit RI
*/ */

@ -424,7 +424,7 @@ int rf_soapy_recv_with_time_multi(void *h,
cf_t *data_c = (cf_t*) data[i]; cf_t *data_c = (cf_t*) data[i];
buffs_ptr[i] = &data_c[n]; buffs_ptr[i] = &data_c[n];
} }
ret = SoapySDRDevice_readStream(handler->device, handler->rxStream, buffs_ptr, rx_samples, &flags, &timeNs, 10000); ret = SoapySDRDevice_readStream(handler->device, handler->rxStream, buffs_ptr, rx_samples, &flags, &timeNs, 1000000);
if(ret < 0) { if(ret < 0) {
// continue when getting overflows // continue when getting overflows
if (ret == SOAPY_SDR_OVERFLOW) { if (ret == SOAPY_SDR_OVERFLOW) {

@ -58,6 +58,10 @@ int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_n
return srslte_ue_sync_init_file_multi(q, nof_prb, file_name, offset_time, offset_freq, 1); return srslte_ue_sync_init_file_multi(q, nof_prb, file_name, offset_time, offset_freq, 1);
} }
void srslte_ue_sync_file_wrap(srslte_ue_sync_t *q, bool enable) {
q->file_wrap_enable = enable;
}
int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_name, int offset_time, int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_name, int offset_time,
float offset_freq, uint32_t nof_rx_ant) { float offset_freq, uint32_t nof_rx_ant) {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -69,6 +73,7 @@ int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q, uint32_t nof_prb, char *
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_ue_sync_t)); bzero(q, sizeof(srslte_ue_sync_t));
q->file_mode = true; q->file_mode = true;
q->file_wrap_enable = true;
q->sf_len = SRSLTE_SF_LEN(srslte_symbol_sz(nof_prb)); q->sf_len = SRSLTE_SF_LEN(srslte_symbol_sz(nof_prb));
q->file_cfo = -offset_freq; q->file_cfo = -offset_freq;
q->fft_size = srslte_symbol_sz(nof_prb); q->fft_size = srslte_symbol_sz(nof_prb);
@ -691,11 +696,15 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (n == 0) { if (n == 0) {
srslte_filesource_seek(&q->file_source, 0); if (q->file_wrap_enable) {
q->sf_idx = 9; srslte_filesource_seek(&q->file_source, 0);
n = srslte_filesource_read_multi(&q->file_source, (void **) input_buffer, q->sf_len, q->nof_rx_antennas); q->sf_idx = 9;
if (n < 0) { n = srslte_filesource_read_multi(&q->file_source, (void **) input_buffer, q->sf_len, q->nof_rx_antennas);
fprintf(stderr, "Error reading input file\n"); if (n < 0) {
fprintf(stderr, "Error reading input file\n");
return SRSLTE_ERROR;
}
} else {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
} }

@ -274,9 +274,6 @@ void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format
uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS], uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS],
uint8_t pucch2_bits[SRSLTE_PUCCH_MAX_BITS]) uint8_t pucch2_bits[SRSLTE_PUCCH_MAX_BITS])
{ {
uint8_t uci_buffer[SRSLTE_CQI_MAX_BITS];
uint8_t uci_buffer_len = 0;
if (format == SRSLTE_PUCCH_FORMAT_1A || format == SRSLTE_PUCCH_FORMAT_1B) { if (format == SRSLTE_PUCCH_FORMAT_1A || format == SRSLTE_PUCCH_FORMAT_1B) {
pucch_bits[0] = uci_data->uci_ack; pucch_bits[0] = uci_data->uci_ack;
pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a
@ -284,22 +281,12 @@ void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format
if (format >= SRSLTE_PUCCH_FORMAT_2) { if (format >= SRSLTE_PUCCH_FORMAT_2) {
/* Put RI (goes alone) */ /* Put RI (goes alone) */
if (uci_data->ri_periodic_report) { if (uci_data->ri_periodic_report) {
uci_buffer[0] = uci_data->uci_ri; // It assumes only 1 bit of RI uint8_t temp[2] = {uci_data->uci_ri, 0};
uci_buffer_len += uci_data->uci_ri_len; srslte_uci_encode_cqi_pucch(temp, uci_data->uci_ri_len, pucch_bits);
} else { } else {
/* Append CQI */ /* Put CQI Report*/
memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_cqi, uci_data->uci_cqi_len); srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_len, pucch_bits);
uci_buffer_len += uci_data->uci_cqi_len;
/* Append Differential CQI */
memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len);
uci_buffer_len += uci_data->uci_dif_cqi_len;
/* Append PMI */
memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_pmi, uci_data->uci_pmi_len);
uci_buffer_len += uci_data->uci_pmi_len;
} }
srslte_uci_encode_cqi_pucch(uci_buffer, uci_buffer_len, pucch_bits);
if (format > SRSLTE_PUCCH_FORMAT_2) { if (format > SRSLTE_PUCCH_FORMAT_2) {
pucch2_bits[0] = uci_data->uci_ack; pucch2_bits[0] = uci_data->uci_ack;
pucch2_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 2a pucch2_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 2a

@ -82,7 +82,7 @@ void srslte_vec_sc_prod_fff(const float *x, const float h, float *z, const uint3
} }
// Used throughout // Used throughout
void srslte_vec_sc_prod_cfc(const const cf_t *x, const float h, cf_t *z, const uint32_t len) { void srslte_vec_sc_prod_cfc(const cf_t *x, const float h, cf_t *z, const uint32_t len) {
srslte_vec_sc_prod_cfc_simd(x,h,z,len); srslte_vec_sc_prod_cfc_simd(x,h,z,len);
} }
@ -277,7 +277,7 @@ void srslte_vec_prod_ccc_split(const float *x_re, const float *x_im, const float
} }
// PRACH, CHEST UL, etc. // PRACH, CHEST UL, etc.
void srslte_vec_prod_conj_ccc(const const cf_t *x, const cf_t *y, cf_t *z, const uint32_t len) { void srslte_vec_prod_conj_ccc(const cf_t *x, const cf_t *y, cf_t *z, const uint32_t len) {
srslte_vec_prod_conj_ccc_simd(x,y,z,len); srslte_vec_prod_conj_ccc_simd(x,y,z,len);
} }
@ -298,12 +298,12 @@ void srslte_vec_div_fff(const float *x, const float *y, float *z, const uint32_t
} }
// PSS. convolution // PSS. convolution
cf_t srslte_vec_dot_prod_ccc(const const cf_t *x, const cf_t *y, const uint32_t len) { cf_t srslte_vec_dot_prod_ccc(const cf_t *x, const cf_t *y, const uint32_t len) {
return srslte_vec_dot_prod_ccc_simd(x, y, len); return srslte_vec_dot_prod_ccc_simd(x, y, len);
} }
// Convolution filter and in SSS search // Convolution filter and in SSS search
cf_t srslte_vec_dot_prod_cfc(const const cf_t *x, const float *y, const uint32_t len) { cf_t srslte_vec_dot_prod_cfc(const cf_t *x, const float *y, const uint32_t len) {
uint32_t i; uint32_t i;
cf_t res = 0; cf_t res = 0;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {

@ -948,7 +948,7 @@ void srslte_vec_abs_square_cf_simd(const cf_t *x, float *z, const int len) {
} }
void srslte_vec_sc_prod_cfc_simd(const cf_t *x, const float h, cf_t *z, const const int len) { void srslte_vec_sc_prod_cfc_simd(const cf_t *x, const float h, cf_t *z, const int len) {
int i = 0; int i = 0;
#if SRSLTE_SIMD_F_SIZE #if SRSLTE_SIMD_F_SIZE

@ -117,7 +117,7 @@ void basic_test()
rlc1.write_sdu(&sdu_bufs[i]); rlc1.write_sdu(&sdu_bufs[i]);
} }
assert(13 == rlc1.get_buffer_state()); assert(14 == rlc1.get_buffer_state());
// Read 5 PDUs from RLC1 (1 byte each) // Read 5 PDUs from RLC1 (1 byte each)
byte_buffer_t pdu_bufs[NBUFS]; byte_buffer_t pdu_bufs[NBUFS];
@ -197,7 +197,7 @@ void concat_test()
rlc1.write_sdu(&sdu_bufs[i]); rlc1.write_sdu(&sdu_bufs[i]);
} }
assert(13 == rlc1.get_buffer_state()); assert(14 == rlc1.get_buffer_state());
// Read 1 PDUs from RLC1 containing all 5 SDUs // Read 1 PDUs from RLC1 containing all 5 SDUs
byte_buffer_t pdu_buf; byte_buffer_t pdu_buf;
@ -263,7 +263,7 @@ void segment_test()
rlc1.write_sdu(&sdu_bufs[i]); rlc1.write_sdu(&sdu_bufs[i]);
} }
assert(58 == rlc1.get_buffer_state()); assert(59 == rlc1.get_buffer_state());
// Read PDUs from RLC1 (force segmentation) // Read PDUs from RLC1 (force segmentation)
byte_buffer_t pdu_bufs[20]; byte_buffer_t pdu_bufs[20];
@ -345,7 +345,7 @@ void retx_test()
rlc1.write_sdu(&sdu_bufs[i]); rlc1.write_sdu(&sdu_bufs[i]);
} }
assert(13 == rlc1.get_buffer_state()); assert(14 == rlc1.get_buffer_state());
// Read 5 PDUs from RLC1 (1 byte each) // Read 5 PDUs from RLC1 (1 byte each)
byte_buffer_t pdu_bufs[NBUFS]; byte_buffer_t pdu_bufs[NBUFS];
@ -443,7 +443,7 @@ void resegment_test_1()
rlc1.write_sdu(&sdu_bufs[i]); rlc1.write_sdu(&sdu_bufs[i]);
} }
assert(58 == rlc1.get_buffer_state()); assert(59 == rlc1.get_buffer_state());
// Read 5 PDUs from RLC1 (10 bytes each) // Read 5 PDUs from RLC1 (10 bytes each)
byte_buffer_t pdu_bufs[NBUFS]; byte_buffer_t pdu_bufs[NBUFS];
@ -553,7 +553,7 @@ void resegment_test_2()
rlc1.write_sdu(&sdu_bufs[i]); rlc1.write_sdu(&sdu_bufs[i]);
} }
assert(58 == rlc1.get_buffer_state()); assert(59 == rlc1.get_buffer_state());
// Read 5 PDUs from RLC1 (5 bytes, 10 bytes, 20 bytes, 10 bytes, 5 bytes) // Read 5 PDUs from RLC1 (5 bytes, 10 bytes, 20 bytes, 10 bytes, 5 bytes)
byte_buffer_t pdu_bufs[NBUFS]; byte_buffer_t pdu_bufs[NBUFS];
@ -660,7 +660,7 @@ void resegment_test_3()
rlc1.write_sdu(&sdu_bufs[i]); rlc1.write_sdu(&sdu_bufs[i]);
} }
assert(58 == rlc1.get_buffer_state()); assert(59 == rlc1.get_buffer_state());
// Read 5 PDUs from RLC1 (5 bytes, 5 bytes, 20 bytes, 10 bytes, 10 bytes) // Read 5 PDUs from RLC1 (5 bytes, 5 bytes, 20 bytes, 10 bytes, 10 bytes)
byte_buffer_t pdu_bufs[NBUFS]; byte_buffer_t pdu_bufs[NBUFS];
@ -763,7 +763,7 @@ void resegment_test_4()
rlc1.write_sdu(&sdu_bufs[i]); rlc1.write_sdu(&sdu_bufs[i]);
} }
assert(58 == rlc1.get_buffer_state()); assert(59 == rlc1.get_buffer_state());
// Read 5 PDUs from RLC1 (5 bytes, 5 bytes, 30 bytes, 5 bytes, 5 bytes) // Read 5 PDUs from RLC1 (5 bytes, 5 bytes, 30 bytes, 5 bytes, 5 bytes)
byte_buffer_t pdu_bufs[NBUFS]; byte_buffer_t pdu_bufs[NBUFS];
@ -866,7 +866,7 @@ void resegment_test_5()
rlc1.write_sdu(&sdu_bufs[i]); rlc1.write_sdu(&sdu_bufs[i]);
} }
assert(58 == rlc1.get_buffer_state()); assert(59 == rlc1.get_buffer_state());
// Read 5 PDUs from RLC1 (2 bytes, 3 bytes, 40 bytes, 3 bytes, 2 bytes) // Read 5 PDUs from RLC1 (2 bytes, 3 bytes, 40 bytes, 3 bytes, 2 bytes)
byte_buffer_t pdu_bufs[NBUFS]; byte_buffer_t pdu_bufs[NBUFS];
@ -975,7 +975,7 @@ void resegment_test_6()
rlc1.write_sdu(&sdu_bufs[i]); rlc1.write_sdu(&sdu_bufs[i]);
} }
assert(368 == rlc1.get_buffer_state()); assert(369 == rlc1.get_buffer_state());
// Read PDUs from RLC1 (10, 10, 10, 270, 54) // Read PDUs from RLC1 (10, 10, 10, 270, 54)
byte_buffer_t pdu_bufs[5]; byte_buffer_t pdu_bufs[5];

@ -102,11 +102,14 @@ filename = /tmp/enb.pcap
# #
# filename: File path to use for log output. Can be set to stdout # filename: File path to use for log output. Can be set to stdout
# to print logs to standard output # to print logs to standard output
# file_max_size: Maximum file size (in kilobytes). When passed, multiple files are created.
# If set to negative, a single log file will be created.
##################################################################### #####################################################################
[log] [log]
all_level = info all_level = info
all_hex_limit = 32 all_hex_limit = 32
filename = /tmp/enb.log filename = /tmp/enb.log
file_max_size = -1
[gui] [gui]
enable = false enable = false

@ -68,6 +68,7 @@ typedef struct {
uint32_t pci; uint32_t pci;
uint32_t nof_ports; uint32_t nof_ports;
uint32_t transmission_mode; uint32_t transmission_mode;
float p_a;
}enb_args_t; }enb_args_t;
typedef struct { typedef struct {
@ -111,6 +112,7 @@ typedef struct {
int gtpu_hex_limit; int gtpu_hex_limit;
int s1ap_hex_limit; int s1ap_hex_limit;
int all_hex_limit; int all_hex_limit;
int file_max_size;
std::string filename; std::string filename;
}log_args_t; }log_args_t;

@ -72,7 +72,7 @@ public:
void set_tti(uint32_t tti); void set_tti(uint32_t tti);
void config(uint16_t rnti, uint32_t nof_prb, sched_interface *sched, rrc_interface_mac *rrc_, rlc_interface_mac *rlc, srslte::log *log_h); void config(uint16_t rnti, uint32_t nof_prb, sched_interface *sched, rrc_interface_mac *rrc_, rlc_interface_mac *rlc, srslte::log *log_h);
uint8_t* generate_pdu(sched_interface::dl_sched_pdu_t pdu[sched_interface::MAX_RLC_PDU_LIST], uint8_t* generate_pdu(uint32_t tb_idx, sched_interface::dl_sched_pdu_t pdu[sched_interface::MAX_RLC_PDU_LIST],
uint32_t nof_pdu_elems, uint32_t grant_size); uint32_t nof_pdu_elems, uint32_t grant_size);
srslte_softbuffer_tx_t* get_tx_softbuffer(uint32_t harq_process, uint32_t tb_idx); srslte_softbuffer_tx_t* get_tx_softbuffer(uint32_t harq_process, uint32_t tb_idx);
@ -130,9 +130,9 @@ private:
uint8_t *pending_buffers[NOF_HARQ_PROCESSES]; uint8_t *pending_buffers[NOF_HARQ_PROCESSES];
// For DL there is a single buffer // For DL there are two buffers, one for each Transport block
const static int payload_buffer_len = 128*1024; const static int payload_buffer_len = 128*1024;
uint8_t tx_payload_buffer[payload_buffer_len]; uint8_t tx_payload_buffer[SRSLTE_MAX_TB][payload_buffer_len];
// For UL there are multiple buffers per PID and are managed by pdu_queue // For UL there are multiple buffers per PID and are managed by pdu_queue
srslte::pdu_queue pdus; srslte::pdu_queue pdus;

@ -72,6 +72,7 @@ public:
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg; srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
srslte_pusch_hopping_cfg_t hopping_cfg; srslte_pusch_hopping_cfg_t hopping_cfg;
srslte_pucch_cfg_t pucch_cfg; srslte_pucch_cfg_t pucch_cfg;
uint8_t pdsch_p_b;
phy_args_t params; phy_args_t params;
srslte::radio *radio; srslte::radio *radio;
@ -86,13 +87,28 @@ public:
bool is_pending[TTIMOD_SZ][SRSLTE_MAX_TB]; bool is_pending[TTIMOD_SZ][SRSLTE_MAX_TB];
uint16_t n_pdcch[TTIMOD_SZ]; uint16_t n_pdcch[TTIMOD_SZ];
} pending_ack_t; } pending_ack_t;
std::map<uint16_t,pending_ack_t> pending_ack;
void ack_add_rnti(uint16_t rnti); class common_ue {
void ack_rem_rnti(uint16_t rnti); public:
void ack_clear(uint32_t sf_idx); pending_ack_t pending_ack;
void ack_set_pending(uint32_t sf_idx, uint16_t rnti, uint32_t tb_idx, uint32_t n_pdcch); uint8_t ri;
bool ack_is_pending(uint32_t sf_idx, uint16_t rnti, uint32_t tb_idx, uint32_t *last_n_pdcch = NULL); int last_ul_tbs[2*HARQ_DELAY_MS];
srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS];
};
std::map<uint16_t, common_ue> common_ue_db;
void ue_db_add_rnti(uint16_t rnti);
void ue_db_rem_rnti(uint16_t rnti);
void ue_db_clear(uint32_t sf_idx);
void ue_db_set_ack_pending(uint32_t sf_idx, uint16_t rnti, uint32_t tb_idx, uint32_t n_pdcch);
bool ue_db_is_ack_pending(uint32_t sf_idx, uint16_t rnti, uint32_t tb_idx, uint32_t *last_n_pdcch = NULL);
void ue_db_set_ri(uint16_t rnti, uint8_t ri);
uint8_t ue_db_get_ri(uint16_t rnti);
void ue_db_set_last_ul_mod(uint16_t rnti, uint32_t tti, srslte_mod_t mcs);
srslte_mod_t ue_db_get_last_ul_mod(uint16_t rnti, uint32_t tti);
void ue_db_set_last_ul_tbs(uint16_t rnti, uint32_t tti, int tbs);
int ue_db_get_last_ul_tbs(uint16_t rnti, uint32_t tti);
private: private:
std::vector<pthread_mutex_t> tx_mutex; std::vector<pthread_mutex_t> tx_mutex;

@ -54,15 +54,15 @@ public:
/* These are used by the GUI plotting tools */ /* These are used by the GUI plotting tools */
int read_ce_abs(float *ce_abs); int read_ce_abs(float *ce_abs);
int read_ce_arg(float *ce_abs);
int read_pusch_d(cf_t *pusch_d); int read_pusch_d(cf_t *pusch_d);
int read_pucch_d(cf_t *pusch_d);
void start_plot(); void start_plot();
void set_conf_dedicated_ack(uint16_t rnti, void set_conf_dedicated_ack(uint16_t rnti,
bool rrc_completed); bool rrc_completed);
void set_config_dedicated(uint16_t rnti, void set_config_dedicated(uint16_t rnti,
srslte_uci_cfg_t *uci_cfg,
srslte_pucch_sched_t *pucch_sched,
srslte_refsignal_srs_cfg_t *srs_cfg, srslte_refsignal_srs_cfg_t *srs_cfg,
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated); LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated);
@ -121,8 +121,6 @@ private:
void metrics_ul(uint32_t mcs, float rssi, float sinr, uint32_t turbo_iters); void metrics_ul(uint32_t mcs, float rssi, float sinr, uint32_t turbo_iters);
int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS]; int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS];
int last_ul_tbs[2*HARQ_DELAY_MS];
srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS];
private: private:
phy_metrics_t metrics; phy_metrics_t metrics;

@ -80,6 +80,7 @@ typedef struct {
LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT mac_cnfg; LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT mac_cnfg;
LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT pusch_cfg; LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT pusch_cfg;
LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT antenna_info; LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT antenna_info;
LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM pdsch_cfg;
rrc_cfg_sr_t sr_cfg; rrc_cfg_sr_t sr_cfg;
rrc_cfg_cqi_t cqi_cfg; rrc_cfg_cqi_t cqi_cfg;
rrc_cfg_qci_t qci_cfg[MAX_NOF_QCI]; rrc_cfg_qci_t qci_cfg[MAX_NOF_QCI];
@ -186,6 +187,7 @@ public:
void handle_rrc_con_req(LIBLTE_RRC_CONNECTION_REQUEST_STRUCT *msg); void handle_rrc_con_req(LIBLTE_RRC_CONNECTION_REQUEST_STRUCT *msg);
void handle_rrc_con_reest_req(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT *msg); void handle_rrc_con_reest_req(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT *msg);
void handle_rrc_con_setup_complete(LIBLTE_RRC_CONNECTION_SETUP_COMPLETE_STRUCT *msg, srslte::byte_buffer_t *pdu); void handle_rrc_con_setup_complete(LIBLTE_RRC_CONNECTION_SETUP_COMPLETE_STRUCT *msg, srslte::byte_buffer_t *pdu);
void handle_rrc_reconf_complete(LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *msg, srslte::byte_buffer_t *pdu);
void handle_security_mode_complete(LIBLTE_RRC_SECURITY_MODE_COMPLETE_STRUCT *msg); void handle_security_mode_complete(LIBLTE_RRC_SECURITY_MODE_COMPLETE_STRUCT *msg);
void handle_security_mode_failure(LIBLTE_RRC_SECURITY_MODE_FAILURE_STRUCT *msg); void handle_security_mode_failure(LIBLTE_RRC_SECURITY_MODE_FAILURE_STRUCT *msg);
void handle_ue_cap_info(LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *msg); void handle_ue_cap_info(LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *msg);

@ -72,7 +72,7 @@ bool enb::init(all_args_t *args_)
if (!args->log.filename.compare("stdout")) { if (!args->log.filename.compare("stdout")) {
logger = &logger_stdout; logger = &logger_stdout;
} else { } else {
logger_file.init(args->log.filename); logger_file.init(args->log.filename, args->log.file_max_size);
logger_file.log("\n\n"); logger_file.log("\n\n");
logger = &logger_file; logger = &logger_file;
} }

@ -844,9 +844,17 @@ int enb::parse_rr(all_args_t* args, rrc_cfg_t* rrc_cfg)
{ {
/* Transmission mode config section */ /* Transmission mode config section */
if (args->enb.transmission_mode < 0 || args->enb.transmission_mode > LIBLTE_RRC_TRANSMISSION_MODE_N_ITEMS) { if (args->enb.transmission_mode < 0 || args->enb.transmission_mode > 4) {
ERROR("Invalid transmission mode (%d). Only indexes 1-4 are implemented.\n", args->enb.transmission_mode); ERROR("Invalid transmission mode (%d). Only indexes 1-4 are implemented.\n", args->enb.transmission_mode);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} else if (args->enb.transmission_mode == 1 && args->enb.nof_ports > 1) {
ERROR("Invalid number of ports (%d) for transmission mode (%d). Only one antenna port is allowed.\n",
args->enb.nof_ports, args->enb.transmission_mode);
return SRSLTE_ERROR;
} else if (args->enb.transmission_mode > 1 && args->enb.nof_ports != 2) {
ERROR("The selected number of ports (%d) are insufficient for the selected transmission mode (%d).\n",
args->enb.nof_ports, args->enb.transmission_mode);
return SRSLTE_ERROR;
} }
bzero(&rrc_cfg->antenna_info, sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT)); bzero(&rrc_cfg->antenna_info, sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT));
@ -854,9 +862,11 @@ int enb::parse_rr(all_args_t* args, rrc_cfg_t* rrc_cfg)
if (rrc_cfg->antenna_info.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { if (rrc_cfg->antenna_info.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) {
rrc_cfg->antenna_info.ue_tx_antenna_selection_setup = LIBLTE_RRC_UE_TX_ANTENNA_SELECTION_OPEN_LOOP; rrc_cfg->antenna_info.ue_tx_antenna_selection_setup = LIBLTE_RRC_UE_TX_ANTENNA_SELECTION_OPEN_LOOP;
rrc_cfg->antenna_info.ue_tx_antenna_selection_setup_present = true; rrc_cfg->antenna_info.ue_tx_antenna_selection_setup_present = false;
rrc_cfg->antenna_info.codebook_subset_restriction_choice = LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM3; rrc_cfg->antenna_info.codebook_subset_restriction_choice = LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM3;
rrc_cfg->antenna_info.codebook_subset_restriction = 0b11;
rrc_cfg->antenna_info.codebook_subset_restriction_present = true;
} else if (rrc_cfg->antenna_info.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { } else if (rrc_cfg->antenna_info.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
rrc_cfg->antenna_info.ue_tx_antenna_selection_setup = LIBLTE_RRC_UE_TX_ANTENNA_SELECTION_CLOSED_LOOP; rrc_cfg->antenna_info.ue_tx_antenna_selection_setup = LIBLTE_RRC_UE_TX_ANTENNA_SELECTION_CLOSED_LOOP;
rrc_cfg->antenna_info.ue_tx_antenna_selection_setup_present = true; rrc_cfg->antenna_info.ue_tx_antenna_selection_setup_present = true;
@ -866,6 +876,18 @@ int enb::parse_rr(all_args_t* args, rrc_cfg_t* rrc_cfg)
rrc_cfg->antenna_info.codebook_subset_restriction_present = true; rrc_cfg->antenna_info.codebook_subset_restriction_present = true;
} }
/* Parse power allocation */
rrc_cfg->pdsch_cfg = LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS;
for (int i = 0; i < LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS; i++) {
if (args->enb.p_a == liblte_rrc_pdsch_config_p_a_num[i]) {
rrc_cfg->pdsch_cfg = (LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM) i;
}
}
if (rrc_cfg->pdsch_cfg == LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS) {
ERROR("Invalid p_a value (%f) only -6, -4.77, -3, -1.77, 0, 1, 2, 3 values allowed.", args->enb.p_a);
return SRSLTE_ERROR;
}
/* MAC config section */ /* MAC config section */
parser::section mac_cnfg("mac_cnfg"); parser::section mac_cnfg("mac_cnfg");

@ -481,7 +481,8 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res)
if (sched_result.data[i].nof_pdu_elems[tb] > 0) { if (sched_result.data[i].nof_pdu_elems[tb] > 0) {
/* Get PDU if it's a new transmission */ /* Get PDU if it's a new transmission */
dl_sched_res->sched_grants[n].data[tb] = ue_db[rnti]->generate_pdu(sched_result.data[i].pdu[tb], dl_sched_res->sched_grants[n].data[tb] = ue_db[rnti]->generate_pdu(tb,
sched_result.data[i].pdu[tb],
sched_result.data[i].nof_pdu_elems[tb], sched_result.data[i].nof_pdu_elems[tb],
sched_result.data[i].tbs[tb]); sched_result.data[i].tbs[tb]);

@ -648,7 +648,7 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST])
user->get_locations(current_cfi, sf_idx), user->get_locations(current_cfi, sf_idx),
aggr_level, user)) aggr_level, user))
{ {
bool is_newtx = h->is_empty(0); bool is_newtx = h->is_empty(0) && h->is_empty(1) ;
int tbs = 0; int tbs = 0;
switch(dci_format) { switch(dci_format) {
case SRSLTE_DCI_FORMAT1: case SRSLTE_DCI_FORMAT1:
@ -663,7 +663,7 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST])
default: default:
Error("DCI format (%d) not implemented\n", dci_format); Error("DCI format (%d) not implemented\n", dci_format);
} }
if (tbs >= 0) { if (tbs > 0) {
log_h->info("SCHED: DL %s rnti=0x%x, pid=%d, mask=0x%x, dci=%d,%d, n_rtx=%d, tbs=%d, buffer=%d, tb_en={%s,%s}\n", log_h->info("SCHED: DL %s rnti=0x%x, pid=%d, mask=0x%x, dci=%d,%d, n_rtx=%d, tbs=%d, buffer=%d, tb_en={%s,%s}\n",
!is_newtx?"retx":"tx", rnti, h->get_id(), h->get_rbgmask(), !is_newtx?"retx":"tx", rnti, h->get_id(), h->get_rbgmask(),
data[nof_data_elems].dci_location.L, data[nof_data_elems].dci_location.ncce, h->nof_retx(0) + h->nof_retx(1), data[nof_data_elems].dci_location.L, data[nof_data_elems].dci_location.ncce, h->nof_retx(0) + h->nof_retx(1),

@ -471,7 +471,7 @@ int sched_ue::generate_format2a(dl_harq_proc *h,
srslte_ra_dl_grant_t grant; srslte_ra_dl_grant_t grant;
srslte_ra_dl_dci_to_grant_prb_allocation(dci, &grant, cell.nof_prb); srslte_ra_dl_dci_to_grant_prb_allocation(dci, &grant, cell.nof_prb);
uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols); uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols);
uint32_t req_bytes = get_pending_dl_new_data(tti); bool no_retx = true;
if (dl_ri == 0) { if (dl_ri == 0) {
if (h->is_empty(1)) { if (h->is_empty(1)) {
@ -483,7 +483,6 @@ int sched_ue::generate_format2a(dl_harq_proc *h,
} }
} else { } else {
/* Two layers, retransmit what TBs that have not been Acknowledged */ /* Two layers, retransmit what TBs that have not been Acknowledged */
bool no_retx = true;
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
if (!h->is_empty(tb)) { if (!h->is_empty(tb)) {
tb_en[tb] = true; tb_en[tb] = true;
@ -498,35 +497,33 @@ int sched_ue::generate_format2a(dl_harq_proc *h,
} }
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
uint32_t req_bytes = get_pending_dl_new_data(tti);
int mcs = 0; int mcs = 0;
int tbs = 0; int tbs = 0;
if (tb_en[tb]) { if (!h->is_empty(tb)) {
if (h->is_empty(tb)) { h->new_retx(tb, tti, &mcs, &tbs);
if (fixed_mcs_dl < 0) { Debug("SCHED: Alloc format2/2a previous mcs=%d, tbs=%d\n", mcs, tbs);
tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs); } else if (tb_en[tb] && req_bytes && no_retx) {
} else { if (fixed_mcs_dl < 0) {
tbs = srslte_ra_tbs_from_idx((uint32_t) srslte_ra_tbs_idx_from_mcs((uint32_t) fixed_mcs_dl), nof_prb) / 8; tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs);
mcs = fixed_mcs_dl;
}
h->new_tx(tb, tti, mcs, tbs, data->dci_location.ncce);
int rem_tbs = tbs;
int x = 0;
do {
x = alloc_pdu(rem_tbs, &data->pdu[tb][data->nof_pdu_elems[tb]]);
rem_tbs -= x;
if (x) {
data->nof_pdu_elems[tb]++;
}
} while (rem_tbs > 0 && x > 0);
Debug("SCHED: Alloc format2/2a new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes);
} else { } else {
h->new_retx(tb, tti, &mcs, &tbs); tbs = srslte_ra_tbs_from_idx((uint32_t) srslte_ra_tbs_idx_from_mcs((uint32_t) fixed_mcs_dl), nof_prb) / 8;
Debug("SCHED: Alloc format2/2a previous mcs=%d, tbs=%d\n", mcs, tbs); mcs = fixed_mcs_dl;
} }
h->new_tx(tb, tti, mcs, tbs, data->dci_location.ncce);
int rem_tbs = tbs;
int x = 0;
do {
x = alloc_pdu(rem_tbs, &data->pdu[tb][data->nof_pdu_elems[tb]]);
rem_tbs -= x;
if (x) {
data->nof_pdu_elems[tb]++;
}
} while (rem_tbs > 0 && x > 0);
Debug("SCHED: Alloc format2/2a new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes);
} }
/* Fill DCI TB dedicated fields */ /* Fill DCI TB dedicated fields */
@ -546,12 +543,6 @@ int sched_ue::generate_format2a(dl_harq_proc *h,
data->tbs[tb] = 0; data->tbs[tb] = 0;
dci->tb_en[tb] = false; dci->tb_en[tb] = false;
} }
if ( req_bytes > (uint32_t) tbs) {
req_bytes -= tbs;
} else {
req_bytes = 0;
}
} }
/* Fill common fields */ /* Fill common fields */
@ -596,6 +587,7 @@ int sched_ue::generate_format0(ul_harq_proc *h,
ul_harq_proc::ul_alloc_t allocation = h->get_alloc(); ul_harq_proc::ul_alloc_t allocation = h->get_alloc();
bool is_newtx = true;
if (h->get_rar_mcs(&mcs)) { if (h->get_rar_mcs(&mcs)) {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8; tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8;
h->new_tx(tti, mcs, tbs); h->new_tx(tti, mcs, tbs);
@ -616,6 +608,7 @@ int sched_ue::generate_format0(ul_harq_proc *h,
} else { } else {
h->new_retx(0, tti, &mcs, NULL); h->new_retx(0, tti, &mcs, NULL);
is_newtx = false;
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8; tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8;
} }
@ -625,8 +618,12 @@ int sched_ue::generate_format0(ul_harq_proc *h,
if (tbs > 0) { if (tbs > 0) {
dci->type2_alloc.L_crb = allocation.L; dci->type2_alloc.L_crb = allocation.L;
dci->type2_alloc.RB_start = allocation.RB_start; dci->type2_alloc.RB_start = allocation.RB_start;
dci->mcs_idx = mcs;
dci->rv_idx = sched::get_rvidx(h->nof_retx(0)); dci->rv_idx = sched::get_rvidx(h->nof_retx(0));
if (!is_newtx && h->is_adaptive_retx()) {
dci->mcs_idx = 28+dci->rv_idx;
} else {
dci->mcs_idx = mcs;
}
dci->ndi = h->get_ndi(0); dci->ndi = h->get_ndi(0);
dci->cqi_request = cqi_request; dci->cqi_request = cqi_request;
dci->freq_hop_fl = srslte_ra_ul_dci_t::SRSLTE_RA_PUSCH_HOP_DISABLED; dci->freq_hop_fl = srslte_ra_ul_dci_t::SRSLTE_RA_PUSCH_HOP_DISABLED;

@ -359,14 +359,14 @@ void ue::allocate_ce(srslte::sch_pdu *pdu, uint32_t lcid)
} }
} }
uint8_t* ue::generate_pdu(sched_interface::dl_sched_pdu_t pdu[sched_interface::MAX_RLC_PDU_LIST], uint8_t* ue::generate_pdu(uint32_t tb_idx, sched_interface::dl_sched_pdu_t pdu[sched_interface::MAX_RLC_PDU_LIST],
uint32_t nof_pdu_elems, uint32_t grant_size) uint32_t nof_pdu_elems, uint32_t grant_size)
{ {
uint8_t *ret = NULL; uint8_t *ret = NULL;
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (rlc) if (rlc)
{ {
mac_msg_dl.init_tx(tx_payload_buffer, grant_size, false); mac_msg_dl.init_tx(tx_payload_buffer[tb_idx], grant_size, false);
for (uint32_t i=0;i<nof_pdu_elems;i++) { for (uint32_t i=0;i<nof_pdu_elems;i++) {
if (pdu[i].lcid <= srslte::sch_subh::PHR_REPORT) { if (pdu[i].lcid <= srslte::sch_subh::PHR_REPORT) {
allocate_sdu(&mac_msg_dl, pdu[i].lcid, pdu[i].nbytes); allocate_sdu(&mac_msg_dl, pdu[i].lcid, pdu[i].nbytes);
@ -408,7 +408,11 @@ void ue::metrics_phr(float phr) {
} }
void ue::metrics_dl_ri(uint32_t dl_ri) { void ue::metrics_dl_ri(uint32_t dl_ri) {
metrics.dl_ri = SRSLTE_VEC_EMA((float) dl_ri, metrics.dl_ri, 0.5f); if (metrics.dl_ri == 0.0f) {
metrics.dl_ri = (float) dl_ri + 1.0f;
} else {
metrics.dl_ri = SRSLTE_VEC_EMA((float) dl_ri + 1.0f, metrics.dl_ri, 0.5f);
}
dl_ri_counter++; dl_ri_counter++;
} }

@ -79,6 +79,7 @@ void parse_args(all_args_t *args, int argc, char* argv[]) {
("enb.n_prb", bpo::value<uint32_t>(&args->enb.n_prb)->default_value(25), "Number of PRB") ("enb.n_prb", bpo::value<uint32_t>(&args->enb.n_prb)->default_value(25), "Number of PRB")
("enb.nof_ports", bpo::value<uint32_t>(&args->enb.nof_ports)->default_value(1), "Number of ports") ("enb.nof_ports", bpo::value<uint32_t>(&args->enb.nof_ports)->default_value(1), "Number of ports")
("enb.tm", bpo::value<uint32_t>(&args->enb.transmission_mode)->default_value(1), "Transmission mode (1-8)") ("enb.tm", bpo::value<uint32_t>(&args->enb.transmission_mode)->default_value(1), "Transmission mode (1-8)")
("enb.p_a", bpo::value<float>(&args->enb.p_a)->default_value(0.0f), "Power allocation rho_a (-6, -4.77, -3, -1.77, 0, 1, 2, 3)")
("enb_files.sib_config", bpo::value<string>(&args->enb_files.sib_config)->default_value("sib.conf"), "SIB configuration files") ("enb_files.sib_config", bpo::value<string>(&args->enb_files.sib_config)->default_value("sib.conf"), "SIB configuration files")
("enb_files.rr_config", bpo::value<string>(&args->enb_files.rr_config)->default_value("rr.conf"), "RR configuration files") ("enb_files.rr_config", bpo::value<string>(&args->enb_files.rr_config)->default_value("rr.conf"), "RR configuration files")
@ -120,6 +121,7 @@ void parse_args(all_args_t *args, int argc, char* argv[]) {
("log.all_hex_limit", bpo::value<int>(&args->log.all_hex_limit)->default_value(32), "ALL log hex dump limit") ("log.all_hex_limit", bpo::value<int>(&args->log.all_hex_limit)->default_value(32), "ALL log hex dump limit")
("log.filename", bpo::value<string>(&args->log.filename)->default_value("/tmp/ue.log"),"Log filename") ("log.filename", bpo::value<string>(&args->log.filename)->default_value("/tmp/ue.log"),"Log filename")
("log.file_max_size", bpo::value<int>(&args->log.file_max_size)->default_value(-1), "Maximum file size (in kilobytes). When passed, multiple files are created. Default -1 (single file)")
/* MCS section */ /* MCS section */
("scheduler.pdsch_mcs", ("scheduler.pdsch_mcs",

@ -123,7 +123,7 @@ void metrics_stdout::print_metrics()
cout << std::hex << metrics.mac[i].rnti << " "; cout << std::hex << metrics.mac[i].rnti << " ";
cout << float_to_string(metrics.mac[i].dl_cqi, 2); cout << float_to_string(metrics.mac[i].dl_cqi, 2);
cout << float_to_string(metrics.mac[i].dl_ri + 1, 3); cout << float_to_string(metrics.mac[i].dl_ri, 3);
cout << float_to_string(metrics.phy[i].dl.mcs, 2); cout << float_to_string(metrics.phy[i].dl.mcs, 2);
if (metrics.mac[i].tx_brate > 0 && metrics_report_period) { if (metrics.mac[i].tx_brate > 0 && metrics_report_period) {
cout << float_to_eng_string((float) metrics.mac[i].tx_brate/metrics_report_period, 2); cout << float_to_eng_string((float) metrics.mac[i].tx_brate/metrics_report_period, 2);

@ -93,45 +93,45 @@ void phch_common::worker_end(uint32_t tx_mutex_cnt, cf_t* buffer[SRSLTE_MAX_PORT
mac->tti_clock(); mac->tti_clock();
} }
void phch_common::ack_clear(uint32_t sf_idx) void phch_common::ue_db_clear(uint32_t sf_idx)
{ {
for(std::map<uint16_t,pending_ack_t>::iterator iter=pending_ack.begin(); iter!=pending_ack.end(); ++iter) { for(std::map<uint16_t,common_ue>::iterator iter=common_ue_db.begin(); iter!=common_ue_db.end(); ++iter) {
pending_ack_t *p = (pending_ack_t*) &iter->second; pending_ack_t *p = &((common_ue*)&iter->second)->pending_ack;
for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) {
p->is_pending[sf_idx][tb_idx] = false; p->is_pending[sf_idx][tb_idx] = false;
} }
} }
} }
void phch_common::ack_add_rnti(uint16_t rnti) void phch_common::ue_db_add_rnti(uint16_t rnti)
{ {
for (int sf_idx=0;sf_idx<TTIMOD_SZ;sf_idx++) { for (int sf_idx=0;sf_idx<TTIMOD_SZ;sf_idx++) {
for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) {
pending_ack[rnti].is_pending[sf_idx][tb_idx] = false; common_ue_db[rnti].pending_ack.is_pending[sf_idx][tb_idx] = false;
} }
} }
} }
void phch_common::ack_rem_rnti(uint16_t rnti) void phch_common::ue_db_rem_rnti(uint16_t rnti)
{ {
pending_ack.erase(rnti); common_ue_db.erase(rnti);
} }
void phch_common::ack_set_pending(uint32_t sf_idx, uint16_t rnti, uint32_t tb_idx, uint32_t last_n_pdcch) void phch_common::ue_db_set_ack_pending(uint32_t sf_idx, uint16_t rnti, uint32_t tb_idx, uint32_t last_n_pdcch)
{ {
if (pending_ack.count(rnti)) { if (common_ue_db.count(rnti)) {
pending_ack[rnti].is_pending[sf_idx][tb_idx] = true; common_ue_db[rnti].pending_ack.is_pending[sf_idx][tb_idx] = true;
pending_ack[rnti].n_pdcch[sf_idx] = (uint16_t) last_n_pdcch; common_ue_db[rnti].pending_ack.n_pdcch[sf_idx] = (uint16_t) last_n_pdcch;
} }
} }
bool phch_common::ack_is_pending(uint32_t sf_idx, uint16_t rnti, uint32_t tb_idx, uint32_t *last_n_pdcch) { bool phch_common::ue_db_is_ack_pending(uint32_t sf_idx, uint16_t rnti, uint32_t tb_idx, uint32_t *last_n_pdcch) {
if (pending_ack.count(rnti)) { if (common_ue_db.count(rnti)) {
bool ret = pending_ack[rnti].is_pending[sf_idx][tb_idx]; bool ret = common_ue_db[rnti].pending_ack.is_pending[sf_idx][tb_idx];
pending_ack[rnti].is_pending[sf_idx][tb_idx] = false; common_ue_db[rnti].pending_ack.is_pending[sf_idx][tb_idx] = false;
if (ret && last_n_pdcch) { if (ret && last_n_pdcch) {
*last_n_pdcch = pending_ack[rnti].n_pdcch[sf_idx]; *last_n_pdcch = common_ue_db[rnti].pending_ack.n_pdcch[sf_idx];
} }
return ret; return ret;
} else { } else {
@ -139,4 +139,41 @@ bool phch_common::ack_is_pending(uint32_t sf_idx, uint16_t rnti, uint32_t tb_idx
} }
} }
void phch_common::ue_db_set_ri(uint16_t rnti, uint8_t ri) {
if (common_ue_db.count(rnti)) {
common_ue_db[rnti].ri = ri;
}
}
uint8_t phch_common::ue_db_get_ri(uint16_t rnti) {
uint8_t ret = 0;
if (common_ue_db.count(rnti)) {
ret = common_ue_db[rnti].ri;
}
return ret;
}
void phch_common::ue_db_set_last_ul_mod(uint16_t rnti, uint32_t tti, srslte_mod_t mcs) {
if (common_ue_db.count(rnti)) {
common_ue_db[rnti].last_ul_mod[TTI_RX(tti)%(2*HARQ_DELAY_MS)] = mcs;
}
}
srslte_mod_t phch_common::ue_db_get_last_ul_mod(uint16_t rnti, uint32_t tti) {
srslte_mod_t ret = SRSLTE_MOD_BPSK;
if (common_ue_db.count(rnti)) {
ret = common_ue_db[rnti].last_ul_mod[TTI_RX(tti)%(2*HARQ_DELAY_MS)];
}
return ret;
}
void phch_common::ue_db_set_last_ul_tbs(uint16_t rnti, uint32_t tti, int tbs) {
if (common_ue_db.count(rnti)) {
common_ue_db[rnti].last_ul_tbs[TTI_RX(tti)%(2*HARQ_DELAY_MS)] = tbs;
}
}
int phch_common::ue_db_get_last_ul_tbs(uint16_t rnti, uint32_t tti) {
int ret = 0;
if (common_ue_db.count(rnti)) {
ret = common_ue_db[rnti].last_ul_tbs[TTI_RX(tti)%(2*HARQ_DELAY_MS)];
}
return ret;
}
} }

@ -228,45 +228,81 @@ void phch_worker::set_conf_dedicated_ack(uint16_t rnti, bool ack){
} }
void phch_worker::set_config_dedicated(uint16_t rnti, void phch_worker::set_config_dedicated(uint16_t rnti,
srslte_uci_cfg_t *uci_cfg,
srslte_pucch_sched_t *pucch_sched,
srslte_refsignal_srs_cfg_t *srs_cfg, srslte_refsignal_srs_cfg_t *srs_cfg,
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated) LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated)
{ {
uint32_t I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx;
bool pucch_cqi = dedicated->cqi_report_cnfg.report_periodic_setup_present;
uint32_t pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx;
bool pucch_cqi_ack = dedicated->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi; bool pucch_cqi_ack = dedicated->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi;
bool pucch_ri = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present; bool pucch_ri = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present;
uint32_t ri_idx = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx;
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (ue_db.count(rnti)) { if (ue_db.count(rnti)) {
pucch_sched->N_pucch_1 = phy->pucch_cfg.n1_pucch_an; /* PUSCH UCI and scheduling configuration */
srslte_enb_ul_cfg_ue(&enb_ul, rnti, uci_cfg, pucch_sched, srs_cfg); srslte_uci_cfg_t uci_cfg = {0};
if (dedicated->pusch_cnfg_ded_present && dedicated->sched_request_cnfg_present) {
ue_db[rnti].I_sr = I_sr; uci_cfg.I_offset_ack = dedicated->pusch_cnfg_ded.beta_offset_ack_idx;
ue_db[rnti].I_sr_en = true; uci_cfg.I_offset_cqi = dedicated->pusch_cnfg_ded.beta_offset_cqi_idx;
uci_cfg.I_offset_ri = dedicated->pusch_cnfg_ded.beta_offset_ri_idx;
srslte_pucch_sched_t pucch_sched = {false};
pucch_sched.N_pucch_1 = phy->pucch_cfg.n1_pucch_an;
pucch_sched.n_pucch_2 = dedicated->cqi_report_cnfg.report_periodic.pucch_resource_idx;
pucch_sched.n_pucch_sr = dedicated->sched_request_cnfg.sr_pucch_resource_idx;
srslte_enb_ul_cfg_ue(&enb_ul, rnti, &uci_cfg, &pucch_sched, srs_cfg);
ue_db[rnti].I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx;
ue_db[rnti].I_sr_en = true;
}
if (pucch_cqi) { /* CQI Reporting */
ue_db[rnti].pmi_idx = pmi_idx; if (dedicated->cqi_report_cnfg.report_periodic_setup_present) {
ue_db[rnti].cqi_en = true; ue_db[rnti].pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx;
ue_db[rnti].cqi_en = true;
ue_db[rnti].pucch_cqi_ack = pucch_cqi_ack; ue_db[rnti].pucch_cqi_ack = pucch_cqi_ack;
} else { } else {
ue_db[rnti].pmi_idx = 0; ue_db[rnti].pmi_idx = 0;
ue_db[rnti].cqi_en = false; ue_db[rnti].cqi_en = false;
} }
/* RI reporting */
if (pucch_ri) { if (pucch_ri) {
ue_db[rnti].ri_idx = ri_idx; ue_db[rnti].ri_idx = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx;
ue_db[rnti].ri_en = true; ue_db[rnti].ri_en = true;
} else { } else {
ue_db[rnti].ri_idx = 0; ue_db[rnti].ri_idx = 0;
ue_db[rnti].ri_en = false; ue_db[rnti].ri_en = false;
} }
/* Copy all dedicated RRC configuration to UE */ if (dedicated->antenna_info_present) {
memcpy(&ue_db[rnti].dedicated, dedicated, sizeof(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT)); /* If default antenna info then follow 3GPP 36.331 clause 9.2.4 Default physical channel configuration */
if (dedicated->antenna_info_default_value) {
if (enb_dl.cell.nof_ports == 1) {
ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode = LIBLTE_RRC_TRANSMISSION_MODE_1;
} else {
ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode = LIBLTE_RRC_TRANSMISSION_MODE_2;
}
ue_db[rnti].dedicated.antenna_info_explicit_value.codebook_subset_restriction_present = false;
ue_db[rnti].dedicated.antenna_info_explicit_value.ue_tx_antenna_selection_setup_present = false;
ue_db[rnti].ri_idx = 0;
ue_db[rnti].ri_en = false;
} else {
/* Physical channel reconfiguration according to 3GPP 36.331 clause 5.3.10.6 */
memcpy(&ue_db[rnti].dedicated.antenna_info_explicit_value,
&dedicated->antenna_info_explicit_value,
sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT));
if (dedicated->antenna_info_explicit_value.tx_mode != LIBLTE_RRC_TRANSMISSION_MODE_3 &&
dedicated->antenna_info_explicit_value.tx_mode != LIBLTE_RRC_TRANSMISSION_MODE_4 &&
ue_db[rnti].ri_en) {
ue_db[rnti].ri_idx = 0;
ue_db[rnti].ri_en = false;
}
}
}
/* Set PDSCH power allocation */
if (dedicated->pdsch_cnfg_ded_present) {
ue_db[rnti].dedicated.pdsch_cnfg_ded_present = true;
ue_db[rnti].dedicated.pdsch_cnfg_ded = dedicated->pdsch_cnfg_ded;
}
} else { } else {
Error("Setting config dedicated: rnti=0x%x does not exist\n"); Error("Setting config dedicated: rnti=0x%x does not exist\n");
} }
@ -362,7 +398,7 @@ void phch_worker::work_imp()
encode_phich(ul_grants[t_tx_ul].phich, ul_grants[t_tx_ul].nof_phich); encode_phich(ul_grants[t_tx_ul].phich, ul_grants[t_tx_ul].nof_phich);
// Prepare for receive ACK for DL grants in t_tx_dl+4 // Prepare for receive ACK for DL grants in t_tx_dl+4
phy->ack_clear(TTIMOD(TTI_TX(t_tx_dl))); phy->ue_db_clear(TTIMOD(TTI_TX(t_tx_dl)));
for (uint32_t i=0;i<dl_grants[t_tx_dl].nof_grants;i++) { for (uint32_t i=0;i<dl_grants[t_tx_dl].nof_grants;i++) {
// SI-RNTI and RAR-RNTI do not have ACK // SI-RNTI and RAR-RNTI do not have ACK
uint16_t rnti = dl_grants[t_tx_dl].sched_grants[i].rnti; uint16_t rnti = dl_grants[t_tx_dl].sched_grants[i].rnti;
@ -371,7 +407,10 @@ void phch_worker::work_imp()
for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) {
/* If TB enabled, set pending ACK */ /* If TB enabled, set pending ACK */
if (dl_grants[t_tx_dl].sched_grants[i].grant.tb_en[tb_idx]) { if (dl_grants[t_tx_dl].sched_grants[i].grant.tb_en[tb_idx]) {
phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), rnti, tb_idx, dl_grants[t_tx_dl].sched_grants[i].location.ncce); phy->ue_db_set_ack_pending(TTIMOD(TTI_TX(t_tx_dl)),
rnti,
tb_idx,
dl_grants[t_tx_dl].sched_grants[i].location.ncce);
} }
} }
} }
@ -408,10 +447,9 @@ unlock:
int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
{ {
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data = {0};
bzero(&uci_data, sizeof(srslte_uci_data_t)); uint32_t wideband_cqi_value = 0, wideband_pmi = 0;
bool wideband_pmi_present = false;
uint32_t wideband_cqi_value = 0;
uint32_t n_rb_ho = 0; uint32_t n_rb_ho = 0;
for (uint32_t i=0;i<nof_pusch;i++) { for (uint32_t i=0;i<nof_pusch;i++) {
@ -428,7 +466,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
// Get pending ACKs with an associated PUSCH transmission // Get pending ACKs with an associated PUSCH transmission
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
acks_pending[tb] = phy->ack_is_pending(t_rx, rnti, tb); acks_pending[tb] = phy->ue_db_is_ack_pending(t_rx, rnti, tb);
if (acks_pending[tb]) { if (acks_pending[tb]) {
uci_data.uci_ack_len++; uci_data.uci_ack_len++;
} }
@ -437,24 +475,29 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
// Configure PUSCH CQI channel // Configure PUSCH CQI channel
srslte_cqi_value_t cqi_value = {0}; srslte_cqi_value_t cqi_value = {0};
bool cqi_enabled = false; bool cqi_enabled = false;
#if 0
if (ue_db[rnti].cqi_en && ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx) ) { if (ue_db[rnti].cqi_en && ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx) ) {
uci_data.uci_ri_len = 1; /* Asumes only 1 bit for RI */ uci_data.uci_ri_len = 1; /* Asumes only 1 bit for RI */
ri_enabled = true; uci_data.ri_periodic_report = true;
} else if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { } else if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
cqi_enabled = true; cqi_enabled = true;
if (ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { if (ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
//uci_data.uci_dif_cqi_len = 3; cqi_value.wideband.pmi_present = true;
uci_data.uci_pmi_len = 2; cqi_value.wideband.rank_is_not_one = phy->ue_db_get_ri(rnti) > 0;
} }
} else } else if (grants[i].grant.cqi_request) {
#endif
if (grants[i].grant.cqi_request) {
cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL; cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL;
if (ue_db[rnti].dedicated.antenna_info_present && (
ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3 ||
ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4
)) {
cqi_value.subband_hl.ri_present = true;
}
cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0; cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0;
cqi_value.subband_hl.four_antenna_ports = (phy->cell.nof_ports == 4); cqi_value.subband_hl.four_antenna_ports = (phy->cell.nof_ports == 4);
cqi_value.subband_hl.pmi_present = (ue_db[rnti].dedicated.cqi_report_cnfg.report_mode_aperiodic == LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31); cqi_value.subband_hl.pmi_present = (ue_db[rnti].dedicated.cqi_report_cnfg.report_mode_aperiodic == LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31);
cqi_value.subband_hl.rank_is_not_one = phy->ue_db_get_ri(rnti) > 0;
cqi_enabled = true; cqi_enabled = true;
} }
@ -468,16 +511,16 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
// Handle Format0 adaptive retx // Handle Format0 adaptive retx
// Use last TBS for this TB in case of mcs>28 // Use last TBS for this TB in case of mcs>28
if (phy_grant.mcs.idx > 28) { if (phy_grant.mcs.idx > 28) {
phy_grant.mcs.tbs = ue_db[rnti].last_ul_tbs[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)]; phy_grant.mcs.tbs = phy->ue_db_get_last_ul_tbs(rnti, tti_rx);
Info("RETX: mcs=%d, old_tbs=%d pid=%d\n", phy_grant.mcs.idx, phy_grant.mcs.tbs, TTI_TX(tti_rx)%(2*HARQ_DELAY_MS)); Info("RETX: mcs=%d, old_tbs=%d pid=%d\n", phy_grant.mcs.idx, phy_grant.mcs.tbs, TTI_TX(tti_rx)%(2*HARQ_DELAY_MS));
} }
ue_db[rnti].last_ul_tbs[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)] = phy_grant.mcs.tbs; phy->ue_db_set_last_ul_tbs(rnti, tti_rx, phy_grant.mcs.tbs);
if (phy_grant.mcs.mod == SRSLTE_MOD_LAST) { if (phy_grant.mcs.mod == SRSLTE_MOD_LAST) {
phy_grant.mcs.mod = ue_db[rnti].last_ul_mod[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)]; phy_grant.mcs.mod = phy->ue_db_get_last_ul_mod(rnti, tti_rx);
phy_grant.Qm = srslte_mod_bits_x_symbol(phy_grant.mcs.mod); phy_grant.Qm = srslte_mod_bits_x_symbol(phy_grant.mcs.mod);
} }
ue_db[rnti].last_ul_mod[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)] = phy_grant.mcs.mod; phy->ue_db_set_last_ul_mod(rnti, tti_rx, phy_grant.mcs.mod);
if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) { if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) {
@ -512,9 +555,15 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
if (cqi_enabled) { if (cqi_enabled) {
if (ue_db[rnti].cqi_en) { if (ue_db[rnti].cqi_en) {
wideband_cqi_value = cqi_value.wideband.wideband_cqi; wideband_cqi_value = cqi_value.wideband.wideband_cqi;
if (cqi_value.wideband.pmi_present) {
wideband_pmi_present = true;
wideband_pmi = cqi_value.wideband.pmi;
}
} else if (grants[i].grant.cqi_request) { } else if (grants[i].grant.cqi_request) {
wideband_cqi_value = cqi_value.subband_hl.wideband_cqi_cw0; wideband_cqi_value = cqi_value.subband_hl.wideband_cqi_cw0;
if (cqi_value.subband_hl.pmi_present) { if (cqi_value.subband_hl.pmi_present) {
wideband_pmi_present = true;
wideband_pmi = cqi_value.subband_hl.pmi;
if (cqi_value.subband_hl.rank_is_not_one) { if (cqi_value.subband_hl.rank_is_not_one) {
Info("PUSCH: Aperiodic ri~1, CQI=%02d/%02d, pmi=%d for %d subbands\n", Info("PUSCH: Aperiodic ri~1, CQI=%02d/%02d, pmi=%d for %d subbands\n",
cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.wideband_cqi_cw1, cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.wideband_cqi_cw1,
@ -529,7 +578,8 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.N); cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.N);
} }
} }
snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value); srslte_cqi_to_str(uci_data.uci_cqi, uci_data.uci_cqi_len, cqi_str, 64);
//snprintf(cqi_str, 64, ", cqi=%s", wideband_cqi_value);
} }
float snr_db = 10*log10(srslte_chest_ul_get_snr(&enb_ul.chest)); float snr_db = 10*log10(srslte_chest_ul_get_snr(&enb_ul.chest));
@ -546,18 +596,20 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
exit(-1); exit(-1);
} }
*/ */
log_h->info_hex(grants[i].data, phy_grant.mcs.tbs/8, log_h->info_hex(grants[i].data, phy_grant.mcs.tbs / 8,
"PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s%s\n", "PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s%s%s%s\n",
rnti, phy_grant.n_prb[0], phy_grant.n_prb[0]+phy_grant.L_prb, rnti, phy_grant.n_prb[0], phy_grant.n_prb[0] + phy_grant.L_prb,
phy_grant.mcs.tbs/8, phy_grant.mcs.idx, grants[i].grant.rv_idx, phy_grant.mcs.tbs / 8, phy_grant.mcs.idx, grants[i].grant.rv_idx,
snr_db, snr_db,
srslte_pusch_last_noi(&enb_ul.pusch), srslte_pusch_last_noi(&enb_ul.pusch),
crc_res?"OK":"KO", crc_res ? "OK" : "KO",
(uci_data.uci_ack_len)?(uci_data.uci_ack?"1":"0"):"", (acks_pending[0] || acks_pending[1]) ? ", ack=" : "",
(uci_data.uci_ack_len > 1)?(uci_data.uci_ack_2?"1":"0"):"", (acks_pending[0]) ? (uci_data.uci_ack ? "1" : "0") : "",
uci_data.uci_cqi_len>0?cqi_str:"", (acks_pending[1]) ? (uci_data.uci_ack_2 ? "1" : "0") : "",
uci_data.uci_ri_len>0?(uci_data.uci_ri?", ri=0":", ri=1"):"", uci_data.uci_cqi_len > 0 ? ", cqi=" : "",
timestr); uci_data.uci_cqi_len > 0 ? cqi_str : "",
uci_data.uci_ri_len > 0 ? ((uci_data.uci_ri == 0) ? ", ri=0" : ", ri=1") : "",
timestr);
// Notify MAC of RL status // Notify MAC of RL status
if (grants[i].grant.rv_idx == 0) { if (grants[i].grant.rv_idx == 0) {
@ -589,9 +641,10 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
} }
if (uci_data.uci_ri_len > 0 && crc_res) { if (uci_data.uci_ri_len > 0 && crc_res) {
phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri); phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri);
phy->ue_db_set_ri(rnti, uci_data.uci_ri);
} }
if (cqi_value.subband_hl.pmi_present && crc_res) { if (wideband_pmi_present && crc_res) {
phy->mac->pmi_info(tti_rx, rnti, cqi_value.subband_hl.pmi); phy->mac->pmi_info(tti_rx, rnti, wideband_pmi);
} }
// Save metrics stats // Save metrics stats
@ -611,8 +664,7 @@ int phch_worker::decode_pucch()
if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END && ue_db[rnti].has_grant_tti != (int) tti_rx) { if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END && ue_db[rnti].has_grant_tti != (int) tti_rx) {
// Check if user needs to receive PUCCH // Check if user needs to receive PUCCH
bool needs_pucch = false, needs_ack[SRSLTE_MAX_TB] = {false}, needs_sr = false, needs_cqi = false, bool needs_pucch = false, needs_ack[SRSLTE_MAX_TB] = {false}, needs_sr = false, needs_cqi = false;
needs_ri = false;
uint32_t last_n_pdcch = 0; uint32_t last_n_pdcch = 0;
bzero(&uci_data, sizeof(srslte_uci_data_t)); bzero(&uci_data, sizeof(srslte_uci_data_t));
@ -625,31 +677,30 @@ int phch_worker::decode_pucch()
} }
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
needs_ack[tb] = phy->ack_is_pending(t_rx, rnti, tb, &last_n_pdcch); needs_ack[tb] = phy->ue_db_is_ack_pending(t_rx, rnti, tb, &last_n_pdcch);
if (needs_ack[tb]) { if (needs_ack[tb]) {
needs_pucch = true; needs_pucch = true;
uci_data.uci_ack_len++; uci_data.uci_ack_len++;
} }
} }
srslte_cqi_value_t cqi_value; srslte_cqi_value_t cqi_value = {0};
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &ue_db[rnti].dedicated; LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &ue_db[rnti].dedicated;
LIBLTE_RRC_TRANSMISSION_MODE_ENUM tx_mode = dedicated->antenna_info_explicit_value.tx_mode; LIBLTE_RRC_TRANSMISSION_MODE_ENUM tx_mode = dedicated->antenna_info_explicit_value.tx_mode;
if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack[0] || !needs_ack[1])) { if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack[0] || !needs_ack[1])) {
if (ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx)) { if (ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx)) {
needs_pucch = true; needs_pucch = true;
needs_ri = true;
uci_data.uci_ri_len = 1; uci_data.uci_ri_len = 1;
uci_data.ri_periodic_report = true; uci_data.ri_periodic_report = true;
} else if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { } else if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
needs_pucch = true; needs_pucch = true;
needs_cqi = true; needs_cqi = true;
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value);
if (tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { if (tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
//uci_data.uci_dif_cqi_len = 3; cqi_value.wideband.pmi_present = true;
uci_data.uci_pmi_len = 2; cqi_value.wideband.rank_is_not_one = phy->ue_db_get_ri(rnti) > 0;
} }
uci_data.uci_cqi_len = (uint32_t) srslte_cqi_size(&cqi_value);
} }
} }
@ -671,25 +722,21 @@ int phch_worker::decode_pucch()
phy->mac->sr_detected(tti_rx, rnti); phy->mac->sr_detected(tti_rx, rnti);
} }
char cqi_ri_str[64]; char cqi_ri_str[64] = {0};
if (srslte_pucch_get_last_corr(&enb_ul.pucch) > PUCCH_RL_CORR_TH) { if (srslte_pucch_get_last_corr(&enb_ul.pucch) > PUCCH_RL_CORR_TH) {
if (uci_data.uci_ri_len && needs_ri) { if (uci_data.ri_periodic_report) {
phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri); phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri);
phy->ue_db_set_ri(rnti, uci_data.uci_ri);
sprintf(cqi_ri_str, ", ri=%d", uci_data.uci_ri); sprintf(cqi_ri_str, ", ri=%d", uci_data.uci_ri);
} else if (uci_data.uci_cqi_len && needs_cqi) { } else if (uci_data.uci_cqi_len && needs_cqi) {
srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value);
phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi);
sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi);
if (uci_data.uci_pmi_len) { if (cqi_value.type == SRSLTE_CQI_TYPE_WIDEBAND && cqi_value.wideband.pmi_present) {
uint32_t packed_pmi = uci_data.uci_pmi[0]; phy->mac->pmi_info(tti_rx, rnti, cqi_value.wideband.pmi);
if (uci_data.uci_pmi_len > 1) { sprintf(cqi_ri_str, "%s, pmi=%d", cqi_ri_str, cqi_value.wideband.pmi);
packed_pmi = (packed_pmi << 1) + uci_data.uci_pmi[1];
}
phy->mac->pmi_info(tti_rx, rnti, packed_pmi);
sprintf(cqi_ri_str, "%s, pmi=%c", cqi_ri_str, packed_pmi + 0x30);
} }
} }
} }
log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s%s\n", log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s%s\n",
@ -699,7 +746,7 @@ int phch_worker::decode_pucch()
(uci_data.uci_ack_len)?(uci_data.uci_ack?", ack=1":", ack=0"):"", (uci_data.uci_ack_len)?(uci_data.uci_ack?", ack=1":", ack=0"):"",
(uci_data.uci_ack_len > 1)?(uci_data.uci_ack_2?"1":"0"):"", (uci_data.uci_ack_len > 1)?(uci_data.uci_ack_2?"1":"0"):"",
needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"", needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"",
(needs_cqi || needs_ri)?cqi_ri_str:""); (needs_cqi || uci_data.ri_periodic_report)?cqi_ri_str:"");
// Notify MAC of RL status // Notify MAC of RL status
@ -776,6 +823,10 @@ int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_gra
} }
int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants) { int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants) {
/* Scales the Resources Elements affected by the power allocation (p_b) */
srslte_enb_dl_prepare_power_allocation(&enb_dl);
for (uint32_t i = 0; i < nof_grants; i++) { for (uint32_t i = 0; i < nof_grants; i++) {
uint16_t rnti = grants[i].rnti; uint16_t rnti = grants[i].rnti;
if (rnti) { if (rnti) {
@ -852,13 +903,11 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
char tbstr[SRSLTE_MAX_TB][128]; char tbstr[SRSLTE_MAX_TB][128];
for (int tb = 0; tb < SRSLTE_MAX_TB; tb++) { for (int tb = 0; tb < SRSLTE_MAX_TB; tb++) {
if (phy_grant.tb_en[tb]) { if (phy_grant.tb_en[tb]) {
snprintf(tbstr[tb], 128, ", TB%d: tbs=%d, mcs=%d, rv=%d%s%s", snprintf(tbstr[tb], 128, ", TB%d: tbs=%d, mcs=%d, rv=%d",
tb, tb,
phy_grant.mcs[tb].tbs / 8, phy_grant.mcs[tb].tbs / 8,
phy_grant.mcs[tb].idx, phy_grant.mcs[tb].idx,
(tb == 0) ? grants[i].grant.rv_idx : grants[i].grant.rv_idx_1, (tb == 0) ? grants[i].grant.rv_idx : grants[i].grant.rv_idx_1);
grants[i].softbuffers[tb]==NULL?", \e[31msoftbuffer=NULL\e[0m":"",
grants[i].data[tb]==NULL?", \e[31mdata=NULL\e[0m":"");
} else { } else {
tbstr[tb][0] = '\0'; tbstr[tb][0] = '\0';
} }
@ -871,6 +920,19 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, grants[i].grant.rv_idx_1}; int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, grants[i].grant.rv_idx_1};
/* Set power allocation */
float rho_a = ((enb_dl.cell.nof_ports == 1) ? 1.0f : sqrtf(2.0f)), rho_b = 1.0f;
uint32_t pdsch_cnfg_ded = ue_db[rnti].dedicated.pdsch_cnfg_ded;
if (pdsch_cnfg_ded < (uint32_t) LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS) {
float rho_a_db = liblte_rrc_pdsch_config_p_a_num[pdsch_cnfg_ded];
rho_a *= powf(10.0f, rho_a_db / 20.0f);
}
if (phy->pdsch_p_b < 4) {
uint32_t idx0 = (phy->cell.nof_ports == 1) ? 0 : 1;
float cell_specific_ratio = pdsch_cfg_cell_specific_ratio_table[idx0][phy->pdsch_p_b];
rho_b = sqrtf(cell_specific_ratio);
}
srslte_enb_dl_set_power_allocation(&enb_dl, rho_a, rho_b);
if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_tx, grants[i].data, mimo_type)) { if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_tx, grants[i].data, mimo_type)) {
fprintf(stderr, "Error putting PDSCH %d\n", i); fprintf(stderr, "Error putting PDSCH %d\n", i);
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -880,6 +942,9 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
ue_db[rnti].metrics_dl(phy_grant.mcs[0].idx); ue_db[rnti].metrics_dl(phy_grant.mcs[0].idx);
} }
} }
srslte_enb_dl_apply_power_allocation(&enb_dl);
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -964,6 +1029,20 @@ int phch_worker::read_ce_abs(float *ce_abs) {
return sz; return sz;
} }
int phch_worker::read_ce_arg(float *ce_arg) {
uint32_t i=0;
int sz = srslte_symbol_sz(phy->cell.nof_prb);
bzero(ce_arg, sizeof(float)*sz);
int g = (sz - 12*phy->cell.nof_prb)/2;
for (i = 0; i < 12*phy->cell.nof_prb; i++) {
ce_arg[g+i] = cargf(enb_ul.ce[i]) * 180.0f / (float) M_PI;
if (isinf(ce_arg[g+i])) {
ce_arg[g+i] = -80;
}
}
return sz;
}
int phch_worker::read_pusch_d(cf_t* pdsch_d) int phch_worker::read_pusch_d(cf_t* pdsch_d)
{ {
int nof_re = 400;//enb_ul.pusch_cfg.nbits.nof_re int nof_re = 400;//enb_ul.pusch_cfg.nbits.nof_re
@ -971,6 +1050,13 @@ int phch_worker::read_pusch_d(cf_t* pdsch_d)
return nof_re; return nof_re;
} }
int phch_worker::read_pucch_d(cf_t* pdsch_d)
{
int nof_re = SRSLTE_PUCCH_MAX_BITS/2;//enb_ul.pusch_cfg.nbits.nof_re
memcpy(pdsch_d, enb_ul.pucch.z_tmp, nof_re*sizeof(cf_t));
return nof_re;
}
} }
@ -983,12 +1069,15 @@ int phch_worker::read_pusch_d(cf_t* pdsch_d)
#ifdef ENABLE_GUI #ifdef ENABLE_GUI
plot_real_t pce; plot_real_t pce, pce_arg;
plot_scatter_t pconst; plot_scatter_t pconst;
plot_scatter_t pconst2;
#define SCATTER_PUSCH_BUFFER_LEN (20*6*SRSLTE_SF_LEN_RE(SRSLTE_MAX_PRB, SRSLTE_CP_NORM)) #define SCATTER_PUSCH_BUFFER_LEN (20*6*SRSLTE_SF_LEN_RE(SRSLTE_MAX_PRB, SRSLTE_CP_NORM))
#define SCATTER_PUSCH_PLOT_LEN 4000 #define SCATTER_PUSCH_PLOT_LEN 4000
float tmp_plot[SCATTER_PUSCH_BUFFER_LEN]; float tmp_plot[SCATTER_PUSCH_BUFFER_LEN];
float tmp_plot_arg[SCATTER_PUSCH_BUFFER_LEN];
cf_t tmp_plot2[SRSLTE_SF_LEN_RE(SRSLTE_MAX_PRB, SRSLTE_CP_NORM)]; cf_t tmp_plot2[SRSLTE_SF_LEN_RE(SRSLTE_MAX_PRB, SRSLTE_CP_NORM)];
cf_t tmp_pucch_plot[SRSLTE_PUCCH_MAX_BITS/2];
void *plot_thread_run(void *arg) { void *plot_thread_run(void *arg) {
srsenb::phch_worker *worker = (srsenb::phch_worker*) arg; srsenb::phch_worker *worker = (srsenb::phch_worker*) arg;
@ -999,24 +1088,42 @@ void *plot_thread_run(void *arg) {
plot_real_setLabels(&pce, (char*) "Index", (char*) "dB"); plot_real_setLabels(&pce, (char*) "Index", (char*) "dB");
plot_real_setYAxisScale(&pce, -40, 40); plot_real_setYAxisScale(&pce, -40, 40);
plot_real_init(&pce_arg);
plot_real_setTitle(&pce_arg, (char*) "Channel Response - Argument");
plot_real_setLabels(&pce_arg, (char*) "Angle", (char*) "deg");
plot_real_setYAxisScale(&pce_arg, -180, 180);
plot_scatter_init(&pconst); plot_scatter_init(&pconst);
plot_scatter_setTitle(&pconst, (char*) "PUSCH - Equalized Symbols"); plot_scatter_setTitle(&pconst, (char*) "PUSCH - Equalized Symbols");
plot_scatter_setXAxisScale(&pconst, -4, 4); plot_scatter_setXAxisScale(&pconst, -4, 4);
plot_scatter_setYAxisScale(&pconst, -4, 4); plot_scatter_setYAxisScale(&pconst, -4, 4);
plot_scatter_init(&pconst2);
plot_scatter_setTitle(&pconst2, (char*) "PUCCH - Equalized Symbols");
plot_scatter_setXAxisScale(&pconst2, -4, 4);
plot_scatter_setYAxisScale(&pconst2, -4, 4);
plot_real_addToWindowGrid(&pce, (char*)"srsenb", 0, 0); plot_real_addToWindowGrid(&pce, (char*)"srsenb", 0, 0);
plot_real_addToWindowGrid(&pce_arg, (char*)"srsenb", 1, 0);
plot_scatter_addToWindowGrid(&pconst, (char*)"srsenb", 0, 1); plot_scatter_addToWindowGrid(&pconst, (char*)"srsenb", 0, 1);
plot_scatter_addToWindowGrid(&pconst2, (char*)"srsenb", 1, 1);
int n; int n, n_arg, n_pucch;
int readed_pusch_re=0; int readed_pusch_re=0;
while(1) { while(1) {
sem_wait(&plot_sem); sem_wait(&plot_sem);
n = worker->read_pusch_d(tmp_plot2); n = worker->read_pusch_d(tmp_plot2);
n_pucch = worker->read_pucch_d(tmp_pucch_plot);
plot_scatter_setNewData(&pconst, tmp_plot2, n); plot_scatter_setNewData(&pconst, tmp_plot2, n);
plot_scatter_setNewData(&pconst2, tmp_pucch_plot, n_pucch);
n = worker->read_ce_abs(tmp_plot); n = worker->read_ce_abs(tmp_plot);
plot_real_setNewData(&pce, tmp_plot, n); plot_real_setNewData(&pce, tmp_plot, n);
n_arg = worker->read_ce_arg(tmp_plot_arg);
plot_real_setNewData(&pce_arg, tmp_plot_arg, n_arg);
} }
return NULL; return NULL;
} }

@ -80,7 +80,10 @@ void phy::parse_config(phy_cfg_t* cfg)
workers_common.pucch_cfg.N_cs = cfg->pucch_cnfg.n_cs_an; workers_common.pucch_cfg.N_cs = cfg->pucch_cnfg.n_cs_an;
workers_common.pucch_cfg.n_rb_2 = cfg->pucch_cnfg.n_rb_cqi; workers_common.pucch_cfg.n_rb_2 = cfg->pucch_cnfg.n_rb_cqi;
workers_common.pucch_cfg.srs_configured = false; workers_common.pucch_cfg.srs_configured = false;
workers_common.pucch_cfg.n1_pucch_an = cfg->pucch_cnfg.n1_pucch_an;; workers_common.pucch_cfg.n1_pucch_an = cfg->pucch_cnfg.n1_pucch_an;
// PDSCH configuration
workers_common.pdsch_p_b = cfg->pdsch_cnfg.p_b;
} }
bool phy::init(phy_args_t *args, bool phy::init(phy_args_t *args,
@ -153,7 +156,7 @@ uint32_t phy::tti_to_subf(uint32_t tti) {
int phy::add_rnti(uint16_t rnti) int phy::add_rnti(uint16_t rnti)
{ {
if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END) { if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END) {
workers_common.ack_add_rnti(rnti); workers_common.ue_db_add_rnti(rnti);
} }
for (uint32_t i=0;i<nof_workers;i++) { for (uint32_t i=0;i<nof_workers;i++) {
if (workers[i].add_rnti(rnti)) { if (workers[i].add_rnti(rnti)) {
@ -166,7 +169,7 @@ int phy::add_rnti(uint16_t rnti)
void phy::rem_rnti(uint16_t rnti) void phy::rem_rnti(uint16_t rnti)
{ {
if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END) { if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END) {
workers_common.ack_rem_rnti(rnti); workers_common.ue_db_rem_rnti(rnti);
} }
for (uint32_t i=0;i<nof_workers;i++) { for (uint32_t i=0;i<nof_workers;i++) {
workers[i].rem_rnti(rnti); workers[i].rem_rnti(rnti);
@ -216,23 +219,8 @@ void phy::set_conf_dedicated_ack(uint16_t rnti, bool ack)
void phy::set_config_dedicated(uint16_t rnti, LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated) void phy::set_config_dedicated(uint16_t rnti, LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated)
{ {
// Parse RRC config
srslte_uci_cfg_t uci_cfg;
srslte_pucch_sched_t pucch_sched;
/* PUSCH UCI configuration */
bzero(&uci_cfg, sizeof(srslte_uci_cfg_t));
uci_cfg.I_offset_ack = dedicated->pusch_cnfg_ded.beta_offset_ack_idx;
uci_cfg.I_offset_cqi = dedicated->pusch_cnfg_ded.beta_offset_cqi_idx;
uci_cfg.I_offset_ri = dedicated->pusch_cnfg_ded.beta_offset_ri_idx;
/* PUCCH Scheduling configuration */
bzero(&pucch_sched, sizeof(srslte_pucch_sched_t));
pucch_sched.n_pucch_2 = dedicated->cqi_report_cnfg.report_periodic.pucch_resource_idx;
pucch_sched.n_pucch_sr = dedicated->sched_request_cnfg.sr_pucch_resource_idx;
for (uint32_t i=0;i<nof_workers;i++) { for (uint32_t i=0;i<nof_workers;i++) {
workers[i].set_config_dedicated(rnti, &uci_cfg, &pucch_sched, NULL, dedicated); workers[i].set_config_dedicated(rnti, NULL, dedicated);
} }
} }

@ -820,6 +820,7 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, byte_buffer_t *pdu)
parent->s1ap->write_pdu(rnti, pdu); parent->s1ap->write_pdu(rnti, pdu);
break; break;
case LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE: case LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE:
handle_rrc_reconf_complete(&ul_dcch_msg.msg.rrc_con_reconfig_complete, pdu);
parent->rrc_log->console("User 0x%x connected\n", rnti); parent->rrc_log->console("User 0x%x connected\n", rnti);
state = RRC_STATE_REGISTERED; state = RRC_STATE_REGISTERED;
break; break;
@ -887,6 +888,16 @@ void rrc::ue::handle_rrc_con_setup_complete(LIBLTE_RRC_CONNECTION_SETUP_COMPLETE
state = RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE; state = RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE;
} }
void rrc::ue::handle_rrc_reconf_complete(LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *msg, srslte::byte_buffer_t *pdu)
{
parent->rrc_log->info("RRCReconfigurationComplete transaction ID: %d\n", msg->rrc_transaction_id);
// Acknowledge Dedicated Configuration
parent->phy->set_conf_dedicated_ack(rnti, true);
parent->mac->phy_config_enabled(rnti, true);
}
void rrc::ue::handle_security_mode_complete(LIBLTE_RRC_SECURITY_MODE_COMPLETE_STRUCT *msg) void rrc::ue::handle_security_mode_complete(LIBLTE_RRC_SECURITY_MODE_COMPLETE_STRUCT *msg)
{ {
parent->rrc_log->info("SecurityModeComplete transaction ID: %d\n", msg->rrc_transaction_id); parent->rrc_log->info("SecurityModeComplete transaction ID: %d\n", msg->rrc_transaction_id);
@ -1132,12 +1143,8 @@ void rrc::ue::send_connection_setup(bool is_setup)
phy_cfg->sched_request_cnfg.setup_present = true; phy_cfg->sched_request_cnfg.setup_present = true;
phy_cfg->sched_request_cnfg.dsr_trans_max = parent->cfg.sr_cfg.dsr_max; phy_cfg->sched_request_cnfg.dsr_trans_max = parent->cfg.sr_cfg.dsr_max;
if (parent->cfg.antenna_info.tx_mode > LIBLTE_RRC_TRANSMISSION_MODE_1) { phy_cfg->antenna_info_default_value = true;
memcpy(&phy_cfg->antenna_info_explicit_value, &parent->cfg.antenna_info, phy_cfg->antenna_info_present = false;
sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT));
phy_cfg->antenna_info_present = true;
phy_cfg->antenna_info_default_value = false;
}
if (is_setup) { if (is_setup) {
if (sr_allocate(parent->cfg.sr_cfg.period, &phy_cfg->sched_request_cnfg.sr_cnfg_idx, &phy_cfg->sched_request_cnfg.sr_pucch_resource_idx)) { if (sr_allocate(parent->cfg.sr_cfg.period, &phy_cfg->sched_request_cnfg.sr_cnfg_idx, &phy_cfg->sched_request_cnfg.sr_pucch_resource_idx)) {
@ -1156,29 +1163,23 @@ void rrc::ue::send_connection_setup(bool is_setup)
phy_cfg->ul_pwr_ctrl_ded.p0_ue_pucch = 0, phy_cfg->ul_pwr_ctrl_ded.p0_ue_pucch = 0,
phy_cfg->ul_pwr_ctrl_ded.p_srs_offset = 3; phy_cfg->ul_pwr_ctrl_ded.p_srs_offset = 3;
// PDSCH
phy_cfg->pdsch_cnfg_ded_present = true; phy_cfg->pdsch_cnfg_ded_present = true;
phy_cfg->pdsch_cnfg_ded = LIBLTE_RRC_PDSCH_CONFIG_P_A_DB_0; phy_cfg->pdsch_cnfg_ded = parent->cfg.pdsch_cfg;
// PUCCH
phy_cfg->pucch_cnfg_ded_present = true;
phy_cfg->pucch_cnfg_ded.ack_nack_repetition_n1_pucch_an = 0;
phy_cfg->cqi_report_cnfg_present = true; phy_cfg->cqi_report_cnfg_present = true;
if(parent->cfg.cqi_cfg.mode == RRC_CFG_CQI_MODE_APERIODIC) { if(parent->cfg.cqi_cfg.mode == RRC_CFG_CQI_MODE_APERIODIC) {
phy_cfg->cqi_report_cnfg.report_mode_aperiodic_present = true; phy_cfg->cqi_report_cnfg.report_mode_aperiodic_present = true;
if (phy_cfg->antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30;
phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31;
} else {
phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30;
}
} else { } else {
phy_cfg->cqi_report_cnfg.report_periodic_present = true; phy_cfg->cqi_report_cnfg.report_periodic_present = true;
phy_cfg->cqi_report_cnfg.report_periodic_setup_present = true; phy_cfg->cqi_report_cnfg.report_periodic_setup_present = true;
phy_cfg->cqi_report_cnfg.report_periodic.format_ind_periodic = LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_WIDEBAND_CQI; phy_cfg->cqi_report_cnfg.report_periodic.format_ind_periodic = LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_WIDEBAND_CQI;
phy_cfg->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi = parent->cfg.cqi_cfg.simultaneousAckCQI; phy_cfg->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi = false;
if (phy_cfg->antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3 ||
phy_cfg->antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present = true;
phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx = 483;
} else {
phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present = false;
}
if (is_setup) { if (is_setup) {
if (cqi_allocate(parent->cfg.cqi_cfg.period, if (cqi_allocate(parent->cfg.cqi_cfg.period,
&phy_cfg->cqi_report_cnfg.report_periodic.pmi_cnfg_idx, &phy_cfg->cqi_report_cnfg.report_periodic.pmi_cnfg_idx,
@ -1317,18 +1318,30 @@ void rrc::ue::send_connection_reconf_upd(srslte::byte_buffer_t *pdu)
phy_cfg->cqi_report_cnfg_present = true; phy_cfg->cqi_report_cnfg_present = true;
if (cqi_allocated) { if (cqi_allocated) {
cqi_get(&phy_cfg->cqi_report_cnfg.report_periodic.pmi_cnfg_idx,
&phy_cfg->cqi_report_cnfg.report_periodic.pucch_resource_idx);
phy_cfg->cqi_report_cnfg.report_periodic_present = true; phy_cfg->cqi_report_cnfg.report_periodic_present = true;
phy_cfg->cqi_report_cnfg.report_periodic_setup_present = true; phy_cfg->cqi_report_cnfg.report_periodic_setup_present = true;
phy_cfg->cqi_report_cnfg.report_periodic.format_ind_periodic = LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_WIDEBAND_CQI; phy_cfg->cqi_report_cnfg.report_periodic.format_ind_periodic =
phy_cfg->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi = false; LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_WIDEBAND_CQI;
phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present = false; phy_cfg->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi = parent->cfg.cqi_cfg.simultaneousAckCQI;
phy_cfg->cqi_report_cnfg.report_periodic.pucch_resource_idx = cqi_pucch; if (parent->cfg.antenna_info.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3 ||
phy_cfg->cqi_report_cnfg.report_periodic.pmi_cnfg_idx = cqi_idx; parent->cfg.antenna_info.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present = true;
phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx = 483; /* TODO: HARDCODED! Add to UL scheduler */
} else {
phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present = false;
}
} else { } else {
phy_cfg->cqi_report_cnfg.report_mode_aperiodic_present = true; phy_cfg->cqi_report_cnfg.report_mode_aperiodic_present = true;
phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30; if (phy_cfg->antenna_info_present &&
phy_cfg->cqi_report_cnfg.nom_pdsch_rs_epre_offset = 0; parent->cfg.antenna_info.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31;
} else {
phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30;
}
} }
parent->phy->set_config_dedicated(rnti, phy_cfg);
sr_get(&phy_cfg->sched_request_cnfg.sr_cnfg_idx, &phy_cfg->sched_request_cnfg.sr_pucch_resource_idx); sr_get(&phy_cfg->sched_request_cnfg.sr_cnfg_idx, &phy_cfg->sched_request_cnfg.sr_pucch_resource_idx);
@ -1358,6 +1371,50 @@ void rrc::ue::send_connection_reconf(srslte::byte_buffer_t *pdu)
conn_reconf->mob_ctrl_info_present = false; conn_reconf->mob_ctrl_info_present = false;
conn_reconf->sec_cnfg_ho_present = false; conn_reconf->sec_cnfg_ho_present = false;
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cfg = &conn_reconf->rr_cnfg_ded.phy_cnfg_ded;
bzero(phy_cfg, sizeof(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT));
conn_reconf->rr_cnfg_ded.phy_cnfg_ded_present = true;
if (parent->cfg.antenna_info.tx_mode > LIBLTE_RRC_TRANSMISSION_MODE_1) {
memcpy(&phy_cfg->antenna_info_explicit_value, &parent->cfg.antenna_info,
sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT));
phy_cfg->antenna_info_present = true;
phy_cfg->antenna_info_default_value = false;
}
// Configure PHY layer
phy_cfg->cqi_report_cnfg_present = true;
if(parent->cfg.cqi_cfg.mode == RRC_CFG_CQI_MODE_APERIODIC) {
phy_cfg->cqi_report_cnfg.report_mode_aperiodic_present = true;
if (phy_cfg->antenna_info_present &&
phy_cfg->antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31;
} else {
phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30;
}
} else {
cqi_get(&phy_cfg->cqi_report_cnfg.report_periodic.pmi_cnfg_idx,
&phy_cfg->cqi_report_cnfg.report_periodic.pucch_resource_idx);
phy_cfg->cqi_report_cnfg.report_periodic_present = true;
phy_cfg->cqi_report_cnfg.report_periodic_setup_present = true;
phy_cfg->cqi_report_cnfg.report_periodic.format_ind_periodic = LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_WIDEBAND_CQI;
phy_cfg->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi = parent->cfg.cqi_cfg.simultaneousAckCQI;
if (phy_cfg->antenna_info_present &&
(phy_cfg->antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3 ||
phy_cfg->antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4)) {
phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present = true;
phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx = 483;
} else {
phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present = false;
}
}
phy_cfg->cqi_report_cnfg.nom_pdsch_rs_epre_offset = 0;
parent->phy->set_config_dedicated(rnti, phy_cfg);
parent->phy->set_conf_dedicated_ack(rnti, false);
parent->mac->set_dl_ant_info(rnti, &phy_cfg->antenna_info_explicit_value);
parent->mac->phy_config_enabled(rnti, false);
// Add SRB2 to the message // Add SRB2 to the message
conn_reconf->rr_cnfg_ded.srb_to_add_mod_list_size = 1; conn_reconf->rr_cnfg_ded.srb_to_add_mod_list_size = 1;
conn_reconf->rr_cnfg_ded.srb_to_add_mod_list[0].srb_id = 2; conn_reconf->rr_cnfg_ded.srb_to_add_mod_list[0].srb_id = 2;

@ -76,7 +76,7 @@ private:
/* Internal methods */ /* Internal methods */
bool extract_fft_and_pdcch_llr(); bool extract_fft_and_pdcch_llr();
void compute_ri(); void compute_ri(uint8_t *ri, uint8_t *pmi, float *sinr);
/* ... for DL */ /* ... for DL */
bool decode_pdcch_ul(mac_interface_phy::mac_grant_t *grant); bool decode_pdcch_ul(mac_interface_phy::mac_grant_t *grant);

@ -99,6 +99,7 @@ typedef struct {
int nas_hex_limit; int nas_hex_limit;
int usim_hex_limit; int usim_hex_limit;
int all_hex_limit; int all_hex_limit;
int file_max_size;
std::string filename; std::string filename;
}log_args_t; }log_args_t;

@ -31,6 +31,7 @@
#include "srslte/common/log.h" #include "srslte/common/log.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/common/msg_queue.h" #include "srslte/common/msg_queue.h"
#include "srslte/common/interfaces_common.h"
#include "srslte/interfaces/ue_interfaces.h" #include "srslte/interfaces/ue_interfaces.h"
#include "srslte/common/threads.h" #include "srslte/common/threads.h"
#include "gw_metrics.h" #include "gw_metrics.h"
@ -46,7 +47,7 @@ class gw
{ {
public: public:
gw(); gw();
void init(pdcp_interface_gw *pdcp_, nas_interface_gw *nas_, srslte::log *gw_log_, uint32_t lcid_); void init(pdcp_interface_gw *pdcp_, nas_interface_gw *nas_, srslte::log *gw_log_, srslte::srslte_gw_config_t);
void stop(); void stop();
void get_metrics(gw_metrics_t &m); void get_metrics(gw_metrics_t &m);
@ -72,13 +73,13 @@ private:
srslte::byte_buffer_pool *pool; srslte::byte_buffer_pool *pool;
srslte::log *gw_log; srslte::log *gw_log;
srslte::srslte_gw_config_t cfg;
bool running; bool running;
bool run_enable; bool run_enable;
int32 tun_fd; int32 tun_fd;
struct ifreq ifr; struct ifreq ifr;
int32 sock; int32 sock;
bool if_up; bool if_up;
uint32_t lcid;
uint32_t current_ip_addr; uint32_t current_ip_addr;

@ -163,7 +163,7 @@ private:
// timeouts in ms // timeouts in ms
uint32_t connecting_timeout; uint32_t connecting_timeout;
static const uint32_t RRC_CONNECTING_TIMEOUT = 1000; static const uint32_t RRC_CONNECTING_TIMEOUT = 5000;
uint32_t plmn_select_timeout; uint32_t plmn_select_timeout;
static const uint32_t RRC_PLMN_SELECT_TIMEOUT = 10000; static const uint32_t RRC_PLMN_SELECT_TIMEOUT = 10000;

@ -120,6 +120,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
("log.all_hex_limit", bpo::value<int>(&args->log.all_hex_limit)->default_value(32), "ALL log hex dump limit") ("log.all_hex_limit", bpo::value<int>(&args->log.all_hex_limit)->default_value(32), "ALL log hex dump limit")
("log.filename", bpo::value<string>(&args->log.filename)->default_value("/tmp/ue.log"), "Log filename") ("log.filename", bpo::value<string>(&args->log.filename)->default_value("/tmp/ue.log"), "Log filename")
("log.file_max_size", bpo::value<int>(&args->log.file_max_size)->default_value(-1), "Maximum file size (in kilobytes). When passed, multiple files are created. Default -1 (single file)")
("usim.algo", bpo::value<string>(&args->usim.algo), "USIM authentication algorithm") ("usim.algo", bpo::value<string>(&args->usim.algo), "USIM authentication algorithm")
("usim.op", bpo::value<string>(&args->usim.op), "USIM operator variant") ("usim.op", bpo::value<string>(&args->usim.op), "USIM operator variant")

@ -382,39 +382,21 @@ void phch_worker::work_imp()
#endif #endif
} }
void phch_worker::compute_ri() { void phch_worker::compute_ri(uint8_t *ri, uint8_t *pmi, float *sinr) {
if (uci_data.uci_ri_len > 0) { if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) {
/* Do nothing */
} else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) {
if (ue_dl.nof_rx_antennas > 1) { if (ue_dl.nof_rx_antennas > 1) {
/* If 2 ort more receiving antennas, select RI */ /* If 2 ort more receiving antennas, select RI */
float cn = 0.0f; float cn = 0.0f;
srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); srslte_ue_dl_ri_select(&ue_dl, ri, &cn);
Info("RI select %d layers, κ=%fdB\n", uci_data.uci_ri + 1, cn); Debug("TM3 RI select %d layers, κ=%fdB\n", (*ri) + 1, cn);
} else { } else {
/* If only one receiving antenna, force RI for 1 layer */ /* If only one receiving antenna, force RI for 1 layer */
uci_data.uci_ri = 0; uci_data.uci_ri = 0;
Warning("Only one receiving antenna with TM3. Forcing RI=1 layer.\n");
} }
uci_data.uci_ri_len = 1; uci_data.uci_ri_len = 1;
} else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
float sinr = 0.0f; srslte_ue_dl_ri_pmi_select(&ue_dl, ri, pmi, sinr);
uint8 packed_pmi = 0; Debug("TM4 ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]]));
srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr);
if (uci_data.uci_ri == 0) {
uci_data.uci_pmi_len = 2;
uci_data.uci_dif_cqi_len = 0;
} else {
uci_data.uci_pmi_len = 1;
uci_data.uci_dif_cqi_len = 3;
}
srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, uci_data.uci_pmi_len);
Info("ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]]));
/* If only one antenna in TM4 print limitation warning */
if (ue_dl.nof_rx_antennas < 2) {
Warning("Only one receiving antenna with TM4. Forcing RI=1 layer (PMI=%d).\n", packed_pmi);
}
uci_data.uci_ri_len = 1; uci_data.uci_ri_len = 1;
} }
} }
@ -868,22 +850,27 @@ void phch_worker::set_uci_periodic_cqi()
int cqi_fixed = phy->args->cqi_fixed; int cqi_fixed = phy->args->cqi_fixed;
int cqi_max = phy->args->cqi_max; int cqi_max = phy->args->cqi_max;
uint8_t ri = (uint8_t) ue_dl.ri;
uint8_t pmi = (uint8_t) ue_dl.pmi[ri];
float sinr = ue_dl.sinr[ri][pmi];
if (period_cqi.configured && rnti_is_set) { if (period_cqi.configured && rnti_is_set) {
if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) { if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) {
/* Compute RI, PMI and SINR */ /* Compute RI, PMI and SINR */
compute_ri(); compute_ri(&ri, &pmi, &sinr);
uci_data.uci_ri = ri;
uci_data.uci_ri_len = 1;
uci_data.ri_periodic_report = true; uci_data.ri_periodic_report = true;
Info("PUCCH: Periodic RI=%d\n", uci_data.uci_ri); Debug("PUCCH: Periodic ri=%d\n", ri);
} else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) { } else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) {
srslte_cqi_value_t cqi_report; srslte_cqi_value_t cqi_report = {0};
if (period_cqi.format_is_subband) { if (period_cqi.format_is_subband) {
// TODO: Implement subband periodic reports // TODO: Implement subband periodic reports
cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND; cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND;
cqi_report.subband.subband_cqi = srslte_cqi_from_snr(phy->avg_snr_db); cqi_report.subband.subband_cqi = srslte_cqi_from_snr(phy->avg_snr_db);
cqi_report.subband.subband_label = 0; cqi_report.subband.subband_label = 0;
log_h->console("Warning: Subband CQI periodic reports not implemented\n"); log_h->console("Warning: Subband CQI periodic reports not implemented\n");
Info("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.subband.subband_cqi, phy->avg_snr_db); Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.subband.subband_cqi, phy->avg_snr_db);
} else { } else {
cqi_report.type = SRSLTE_CQI_TYPE_WIDEBAND; cqi_report.type = SRSLTE_CQI_TYPE_WIDEBAND;
if (cqi_fixed >= 0) { if (cqi_fixed >= 0) {
@ -894,19 +881,14 @@ void phch_worker::set_uci_periodic_cqi()
if (cqi_max >= 0 && cqi_report.wideband.wideband_cqi > cqi_max) { if (cqi_max >= 0 && cqi_report.wideband.wideband_cqi > cqi_max) {
cqi_report.wideband.wideband_cqi = cqi_max; cqi_report.wideband.wideband_cqi = cqi_max;
} }
Info("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db); if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
} cqi_report.wideband.pmi_present = true;
if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { cqi_report.wideband.pmi = pmi;
if (ue_dl.ri == 0) { cqi_report.wideband.rank_is_not_one = (ri != 0);
uci_data.uci_pmi_len = 2;
} else {
uci_data.uci_pmi_len = 1;
uci_data.uci_dif_cqi_len = 3;
} }
uint8_t *ptr = uci_data.uci_pmi; Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db);
srslte_bit_unpack(ue_dl.pmi[ue_dl.ri], &ptr, uci_data.uci_pmi_len);
} }
uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); uci_data.uci_cqi_len = (uint32_t) srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi);
rar_cqi_request = false; rar_cqi_request = false;
} }
} }
@ -914,9 +896,13 @@ void phch_worker::set_uci_periodic_cqi()
void phch_worker::set_uci_aperiodic_cqi() void phch_worker::set_uci_aperiodic_cqi()
{ {
uint8_t ri = (uint8_t) ue_dl.ri;
uint8_t pmi = (uint8_t) ue_dl.pmi[ri];
float sinr = ue_dl.sinr[ri][pmi];
if (phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic_present) { if (phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic_present) {
/* Compute RI, PMI and SINR */ /* Compute RI, PMI and SINR */
compute_ri(); compute_ri(&ri, &pmi, &sinr);
switch(phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic) { switch(phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic) {
case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30: case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30:
@ -1054,14 +1040,20 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
snprintf(timestr, 64, ", tot_time=%4d us", (int) logtime_start[0].tv_usec); snprintf(timestr, 64, ", tot_time=%4d us", (int) logtime_start[0].tv_usec);
#endif #endif
char cqi_str[32] = "";
srslte_cqi_to_str(uci_data.uci_cqi, uci_data.uci_cqi_len, cqi_str, 32);
uint8_t dummy[2] = {0,0}; uint8_t dummy[2] = {0,0};
log_h->info("PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d, ack=%s, ri=%s, cfo=%.1f KHz%s\n", log_h->info("PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d%s%s%s, cfo=%.1f KHz%s%s%s\n",
(tti+HARQ_DELAY_MS)%10240, (tti + HARQ_DELAY_MS) % 10240,
grant->n_prb[0], grant->n_prb[0]+grant->L_prb, grant->n_prb[0], grant->n_prb[0] + grant->L_prb,
grant->mcs.tbs/8, grant->mcs.idx, rv, grant->mcs.tbs / 8, grant->mcs.idx, rv,
uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", uci_data.uci_ack_len > 0 ? (uci_data.uci_ack ? ", ack=1" : "0") : "",
uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no", uci_data.uci_ack_len > 1 ? (uci_data.uci_ack_2 ? "1" : "0") : "",
cfo*15, timestr); uci_data.uci_ri_len > 0 ? (uci_data.uci_ri ? ", ri=1" : ", ri=0") : "",
cfo * 15, timestr,
uci_data.uci_cqi_len > 0 ? ", cqi=" : "",
uci_data.uci_cqi_len > 0 ? cqi_str : "");
// Store metrics // Store metrics
ul_metrics.mcs = grant->mcs.idx; ul_metrics.mcs = grant->mcs.idx;
@ -1102,16 +1094,19 @@ void phch_worker::encode_pucch()
float tx_power = srslte_ue_ul_pucch_power(&ue_ul, phy->pathloss, ue_ul.last_pucch_format, uci_data.uci_cqi_len, uci_data.uci_ack_len); float tx_power = srslte_ue_ul_pucch_power(&ue_ul, phy->pathloss, ue_ul.last_pucch_format, uci_data.uci_cqi_len, uci_data.uci_ack_len);
float gain = set_power(tx_power); float gain = set_power(tx_power);
Info("PUCCH: tti_tx=%d, n_pucch=%d, n_prb=%d, ack=%s%s, ri=%s, pmi=%s%s, sr=%s, cfo=%.1f KHz%s\n", char str_cqi[32] = "";
(tti+4)%10240, srslte_cqi_to_str(uci_data.uci_cqi, uci_data.uci_cqi_len, str_cqi, 32);
Info("PUCCH: tti_tx=%d, n_pucch=%d, n_prb=%d, ack=%s%s%s%s%s, sr=%s, cfo=%.1f KHz%s\n",
(tti + 4) % 10240,
ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb, ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb,
uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", uci_data.uci_ack_len > 0 ? (uci_data.uci_ack ? "1" : "0") : "no",
uci_data.uci_ack_len>1?(uci_data.uci_ack_2?"1":"0"):"", uci_data.uci_ack_len > 1 ? (uci_data.uci_ack_2 ? "1" : "0") : "",
uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no", uci_data.uci_ri_len > 0 ? (uci_data.uci_ri ? ", ri=1" : ", ri=0") : "",
uci_data.uci_pmi_len>0?(uci_data.uci_pmi[1]?"1":"0"):"no", uci_data.uci_cqi_len > 0 ? ", cqi=" : "",
uci_data.uci_pmi_len>0?(uci_data.uci_pmi[0]?"1":"0"):"", uci_data.uci_cqi_len > 0 ? str_cqi : "",
uci_data.scheduling_request?"yes":"no", uci_data.scheduling_request ? "yes" : "no",
cfo*15, timestr); cfo * 15, timestr);
} }
if (uci_data.scheduling_request) { if (uci_data.scheduling_request) {

@ -55,7 +55,7 @@ bool ue::init(all_args_t *args_)
if (!args->log.filename.compare("stdout")) { if (!args->log.filename.compare("stdout")) {
logger = &logger_stdout; logger = &logger_stdout;
} else { } else {
logger_file.init(args->log.filename); logger_file.init(args->log.filename, args->log.file_max_size);
logger_file.log("\n\n"); logger_file.log("\n\n");
logger_file.log(get_build_string().c_str()); logger_file.log(get_build_string().c_str());
logger = &logger_file; logger = &logger_file;

@ -47,13 +47,13 @@ gw::gw()
default_netmask = true; default_netmask = true;
} }
void gw::init(pdcp_interface_gw *pdcp_, nas_interface_gw *nas_, srslte::log *gw_log_, uint32_t lcid_) void gw::init(pdcp_interface_gw *pdcp_, nas_interface_gw *nas_, srslte::log *gw_log_, srslte::srslte_gw_config_t cfg_)
{ {
pool = srslte::byte_buffer_pool::get_instance(); pool = srslte::byte_buffer_pool::get_instance();
pdcp = pdcp_; pdcp = pdcp_;
nas = nas_; nas = nas_;
gw_log = gw_log_; gw_log = gw_log_;
lcid = lcid_; cfg = cfg_;
run_enable = true; run_enable = true;
gettimeofday(&metrics_time[1], NULL); gettimeofday(&metrics_time[1], NULL);
@ -273,9 +273,9 @@ void gw::run_thread()
{ {
gw_log->info_hex(pdu->msg, pdu->N_bytes, "TX PDU"); gw_log->info_hex(pdu->msg, pdu->N_bytes, "TX PDU");
while(run_enable && !pdcp->is_drb_enabled(lcid) && attach_attempts < ATTACH_MAX_ATTEMPTS) { while(run_enable && !pdcp->is_drb_enabled(cfg.lcid) && attach_attempts < ATTACH_MAX_ATTEMPTS) {
if (attach_cnt == 0) { if (attach_cnt == 0) {
gw_log->info("LCID=%d not active, requesting NAS attach (%d/%d)\n", lcid, attach_attempts, ATTACH_MAX_ATTEMPTS); gw_log->info("LCID=%d not active, requesting NAS attach (%d/%d)\n", cfg.lcid, attach_attempts, ATTACH_MAX_ATTEMPTS);
nas->attach_request(); nas->attach_request();
attach_attempts++; attach_attempts++;
} }
@ -287,7 +287,7 @@ void gw::run_thread()
} }
if (attach_attempts == ATTACH_MAX_ATTEMPTS) { if (attach_attempts == ATTACH_MAX_ATTEMPTS) {
gw_log->warning("LCID=%d was not active after %d attempts\n", lcid, ATTACH_MAX_ATTEMPTS); gw_log->warning("LCID=%d was not active after %d attempts\n", cfg.lcid, ATTACH_MAX_ATTEMPTS);
} }
attach_attempts = 0; attach_attempts = 0;
@ -298,10 +298,10 @@ void gw::run_thread()
} }
// Send PDU directly to PDCP // Send PDU directly to PDCP
if (pdcp->is_drb_enabled(lcid)) { if (pdcp->is_drb_enabled(cfg.lcid)) {
pdu->set_timestamp(); pdu->set_timestamp();
ul_tput_bytes += pdu->N_bytes; ul_tput_bytes += pdu->N_bytes;
pdcp->write_sdu(lcid, pdu); pdcp->write_sdu(cfg.lcid, pdu);
do { do {
pdu = pool_allocate; pdu = pool_allocate;

@ -70,12 +70,15 @@ nas_filename = /tmp/nas.pcap
# #
# filename: File path to use for log output. Can be set to stdout # filename: File path to use for log output. Can be set to stdout
# to print logs to standard output # to print logs to standard output
# file_max_size: Maximum file size (in kilobytes). When passed, multiple files are created.
# If set to negative, a single log file will be created.
##################################################################### #####################################################################
[log] [log]
all_level = info all_level = info
phy_lib_level = none phy_lib_level = none
all_hex_limit = 32 all_hex_limit = 32
filename = /tmp/ue.log filename = /tmp/ue.log
file_max_size = -1
##################################################################### #####################################################################
# USIM configuration # USIM configuration

Loading…
Cancel
Save