Merge branch 'next' into next_mimo

master
Xavier Arteaga 7 years ago
commit 0947173fc1

@ -97,11 +97,13 @@ public:
bool running; bool running;
}; };
timers(uint32_t nof_timers_) : timer_list(nof_timers_) { timers(uint32_t nof_timers_) : timer_list(nof_timers_),used_timers(nof_timers_) {
nof_timers = nof_timers_; nof_timers = nof_timers_;
next_timer = 0; next_timer = 0;
nof_used_timers = 0;
for (uint32_t i=0;i<nof_timers;i++) { for (uint32_t i=0;i<nof_timers;i++) {
timer_list[i].id = i; timer_list[i].id = i;
used_timers[i] = false;
} }
} }
@ -133,17 +135,36 @@ public:
return NULL; return NULL;
} }
} }
void release_id(uint32_t i) {
if (nof_used_timers > 0 && i < nof_timers) {
used_timers[i] = false;
nof_used_timers--;
} else {
fprintf(stderr, "Error releasing timer: nof_used_timers=%d, nof_timers=%d\n", nof_used_timers, nof_timers);
}
}
uint32_t get_unique_id() { uint32_t get_unique_id() {
if (next_timer == nof_timers){ if (nof_used_timers >= nof_timers) {
printf("No more unique timer ids (Only %d timers available)\n", nof_timers); fprintf(stderr, "Error getting uinque timer id: no more timers available\n");
next_timer = 0; return 0;
} else {
while(used_timers[next_timer]) {
next_timer++;
if (next_timer >= nof_timers) {
next_timer=0;
}
}
used_timers[next_timer] = true;
nof_used_timers++;
return next_timer;
} }
return next_timer++;
} }
private: private:
uint32_t nof_timers;
uint32_t next_timer; uint32_t next_timer;
std::vector<timer> timer_list; uint32_t nof_used_timers;
uint32_t nof_timers;
std::vector<timer> timer_list;
std::vector<bool> used_timers;
}; };
} // namespace srslte } // namespace srslte

@ -94,7 +94,8 @@ public:
typedef struct { typedef struct {
int priority; int priority;
int bsd; int bsd;
int pbr; int pbr;
int group;
enum {IDLE = 0, UL, DL, BOTH} direction; enum {IDLE = 0, UL, DL, BOTH} direction;
} ue_bearer_cfg_t; } ue_bearer_cfg_t;
@ -231,7 +232,7 @@ public:
/* UL information */ /* UL information */
virtual int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc) = 0; virtual int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc) = 0;
virtual int ul_sr_info(uint32_t tti, uint16_t rnti) = 0; virtual int ul_sr_info(uint32_t tti, uint16_t rnti) = 0;
virtual int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr) = 0; virtual int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value = true) = 0;
virtual int ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len) = 0; virtual int ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len) = 0;
virtual int ul_phr(uint16_t rnti, int phr) = 0; virtual int ul_phr(uint16_t rnti, int phr) = 0;
virtual int ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch_code) = 0; virtual int ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch_code) = 0;

@ -250,6 +250,9 @@ SRSLTE_API uint32_t srslte_N_ta_new_rar(uint32_t ta);
SRSLTE_API uint32_t srslte_N_ta_new(uint32_t N_ta_old, SRSLTE_API uint32_t srslte_N_ta_new(uint32_t N_ta_old,
uint32_t ta); uint32_t ta);
SRSLTE_API float srslte_coderate(uint32_t tbs,
uint32_t nof_re);
SRSLTE_API char *srslte_cp_string(srslte_cp_t cp); SRSLTE_API char *srslte_cp_string(srslte_cp_t cp);
SRSLTE_API srslte_mod_t srslte_str2mod (char * mod_str); SRSLTE_API srslte_mod_t srslte_str2mod (char * mod_str);

@ -96,10 +96,7 @@ SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t *q, SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t *q,
uint16_t rnti); uint16_t rnti);
SRSLTE_API float srslte_pdsch_coderate(uint32_t tbs, SRSLTE_API int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg,
uint32_t nof_re);
SRSLTE_API int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg,
srslte_cell_t cell, srslte_cell_t cell,
srslte_ra_dl_grant_t *grant, srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,

@ -108,7 +108,6 @@ typedef struct SRSLTE_API {
bool group_hopping_en; bool group_hopping_en;
float threshold_format1; float threshold_format1;
float threshold_format1a;
float last_corr; float last_corr;
uint32_t last_n_prb; uint32_t last_n_prb;
uint32_t last_n_pucch; uint32_t last_n_pucch;
@ -125,9 +124,8 @@ SRSLTE_API bool srslte_pucch_set_cfg(srslte_pucch_t* q,
srslte_pucch_cfg_t* cfg, srslte_pucch_cfg_t* cfg,
bool group_hopping_en); bool group_hopping_en);
SRSLTE_API void srslte_pucch_set_threshold(srslte_pucch_t *q, SRSLTE_API void srslte_pucch_set_threshold(srslte_pucch_t *q,
float format1, float format1_threshold);
float format1a);
SRSLTE_API int srslte_pucch_set_crnti(srslte_pucch_t *q, SRSLTE_API int srslte_pucch_set_crnti(srslte_pucch_t *q,
uint16_t c_rnti); uint16_t c_rnti);

@ -152,6 +152,9 @@ SRSLTE_API void srslte_vec_conj_cc(cf_t *x, cf_t *y, uint32_t len);
/* average vector power */ /* average vector power */
SRSLTE_API float srslte_vec_avg_power_cf(cf_t *x, uint32_t len); SRSLTE_API float srslte_vec_avg_power_cf(cf_t *x, uint32_t len);
/* Correlation between complex vectors x and y */
SRSLTE_API float srslte_vec_corr_ccc(cf_t *x, cf_t *y, uint32_t len);
/* return the index of the maximum value in the vector */ /* return the index of the maximum value in the vector */
SRSLTE_API uint32_t srslte_vec_max_fi(float *x, uint32_t len); SRSLTE_API uint32_t srslte_vec_max_fi(float *x, uint32_t len);
SRSLTE_API uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len); SRSLTE_API uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len);

@ -77,6 +77,7 @@ public:
// RRC interface // RRC interface
void reset(); void reset();
void empty_queue();
void add_bearer(uint32_t lcid); void add_bearer(uint32_t lcid);
void add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg); void add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg);

@ -56,6 +56,7 @@ public:
void configure(srslte_rlc_config_t cnfg); void configure(srslte_rlc_config_t cnfg);
void reset(); void reset();
void empty_queue();
bool active(); bool active();
rlc_mode_t get_mode(); rlc_mode_t get_mode();

@ -33,7 +33,7 @@
// Table 6.1.3.1-1 Buffer size levels for BSR // Table 6.1.3.1-1 Buffer size levels for BSR
static uint32_t btable[64] = { static uint32_t btable[64] = {
0, 5, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132, 0, 1, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132,
1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4667, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304, 1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4667, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304,
42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125, 150000}; 42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125, 150000};
@ -428,12 +428,16 @@ int sch_subh::get_bsr(uint32_t buff_size[4])
buff_size[2] = (payload[1]&0x0F) << 4 | (payload[1]&0xC0) >> 6; buff_size[2] = (payload[1]&0x0F) << 4 | (payload[1]&0xC0) >> 6;
buff_size[3] = (payload[2]&0x3F); buff_size[3] = (payload[2]&0x3F);
} else { } else {
uint32_t nonzero_lcg = (payload[0]&0xc0) >> 6; nonzero_lcg = (payload[0]&0xc0) >> 6;
buff_size[nonzero_lcg%4] = payload[0]&0x3f; buff_size[nonzero_lcg%4] = payload[0]&0x3f;
} }
for (int i=0;i<4;i++) { for (int i=0;i<4;i++) {
if (buff_size[i]) { if (buff_size[i]) {
buff_size[i] = btable[buff_size[i]%64]; if (buff_size[i]<63) {
buff_size[i] = btable[1+buff_size[i]];
} else {
buff_size[i] = btable[63];
}
} }
} }
return nonzero_lcg; return nonzero_lcg;

@ -191,6 +191,11 @@ uint32_t srslte_N_ta_new(uint32_t N_ta_old, uint32_t ta) {
} }
} }
float srslte_coderate(uint32_t tbs, uint32_t nof_re)
{
return (float) (tbs + 24)/(nof_re);
}
/* Returns the new time advance as indicated by the random access response /* Returns the new time advance as indicated by the random access response
* as specified in Section 4.2.3 of 36.213 */ * as specified in Section 4.2.3 of 36.213 */
uint32_t srslte_N_ta_new_rar(uint32_t ta) { uint32_t srslte_N_ta_new_rar(uint32_t ta) {

@ -91,7 +91,7 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell,
srslte_prach_set_detect_factor(&q->prach, 60); srslte_prach_set_detect_factor(&q->prach, 60);
} }
srslte_pucch_set_threshold(&q->pucch, 0.5, 0.5); srslte_pucch_set_threshold(&q->pucch, 0.8);
if (srslte_chest_ul_init(&q->chest, cell)) { if (srslte_chest_ul_init(&q->chest, cell)) {
fprintf(stderr, "Error initiating channel estimator\n"); fprintf(stderr, "Error initiating channel estimator\n");

@ -57,12 +57,7 @@ extern int indices[100000];
extern int indices_ptr; extern int indices_ptr;
#endif #endif
float srslte_pdsch_coderate(uint32_t tbs, uint32_t nof_re) int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_grant_t *grant, uint32_t lstart_grant, uint32_t nsubframe, bool put)
{
return (float) (tbs + 24)/(nof_re);
}
int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_grant_t *grant, uint32_t lstart_grant, uint32_t nsubframe, bool put)
{ {
uint32_t s, n, l, lp, lstart, lend, nof_refs; uint32_t s, n, l, lp, lstart, lend, nof_refs;
bool is_pbch, is_sss; bool is_pbch, is_sss;

@ -214,15 +214,15 @@ uint32_t srslte_pucch_get_npucch(uint32_t n_cce, srslte_pucch_format_t format, b
{ {
uint32_t n_pucch = 0; uint32_t n_pucch = 0;
if (has_scheduling_request) { if (has_scheduling_request) {
n_pucch = pucch_sched->n_pucch_sr; n_pucch = pucch_sched->n_pucch_sr;
} else if (format < SRSLTE_PUCCH_FORMAT_2) { } else if (format < SRSLTE_PUCCH_FORMAT_2) {
if (pucch_sched->sps_enabled) { if (pucch_sched->sps_enabled) {
n_pucch = pucch_sched->n_pucch_1[pucch_sched->tpc_for_pucch%4]; n_pucch = pucch_sched->n_pucch_1[pucch_sched->tpc_for_pucch%4];
} else { } else {
n_pucch = n_cce + pucch_sched->N_pucch_1; n_pucch = n_cce + pucch_sched->N_pucch_1;
} }
} else { } else {
n_pucch = pucch_sched->n_pucch_2; n_pucch = pucch_sched->n_pucch_2;
} }
return n_pucch; return n_pucch;
} }
@ -411,9 +411,8 @@ static int pucch_get(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n
return pucch_cp(q, format, n_pucch, input, z, true); return pucch_cp(q, format, n_pucch, input, z, true);
} }
void srslte_pucch_set_threshold(srslte_pucch_t *q, float format1, float format1a) { void srslte_pucch_set_threshold(srslte_pucch_t *q, float format1_threshold) {
q->threshold_format1 = format1; q->threshold_format1 = format1_threshold;
q->threshold_format1a = format1a;
} }
/** Initializes the PDCCH transmitter and receiver */ /** Initializes the PDCCH transmitter and receiver */
@ -452,6 +451,8 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
q->z_tmp = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); q->z_tmp = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS);
q->ce = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); q->ce = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS);
q->threshold_format1 = 0.8;
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} }
return ret; return ret;
@ -612,6 +613,10 @@ static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_format_t format, uint8_t
// Declare this here, since we can not include refsignal_ul.h // Declare this here, since we can not include refsignal_ul.h
void srslte_refsignal_r_uv_arg_1prb(float *arg, uint32_t u); void srslte_refsignal_r_uv_arg_1prb(float *arg, uint32_t u);
float tmp_alpha;
uint32_t tmp_noc, tmp_nprime, tmp_woc;
static int pucch_encode_(srslte_pucch_t* q, srslte_pucch_format_t format, static int pucch_encode_(srslte_pucch_t* q, srslte_pucch_format_t format,
uint32_t n_pucch, uint32_t sf_idx, uint16_t rnti, uint32_t n_pucch, uint32_t sf_idx, uint16_t rnti,
uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS], bool signal_only) uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS], bool signal_only)
@ -655,8 +660,14 @@ static int pucch_encode_(srslte_pucch_t* q, srslte_pucch_format_t format,
if (n_prime_ns%2) { if (n_prime_ns%2) {
S_ns = M_PI/2; S_ns = M_PI/2;
} }
DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d, n_rb_2=%d\n", DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d, n_rb_2=%d\n",
__real__ q->d[0], __imag__ q->d[0], alpha, n_oc, n_prime_ns, q->pucch_cfg.n_rb_2); __real__ q->d[0], __imag__ q->d[0], alpha, n_oc, n_prime_ns, q->pucch_cfg.n_rb_2);
tmp_alpha = alpha;
tmp_noc = n_oc;
tmp_nprime = n_prime_ns;
tmp_woc = w_n_oc[N_sf_widx][n_oc%3][m];
for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) { for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) {
z[(ns%2)*N_sf_0*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = z[(ns%2)*N_sf_0*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] =
q->d[0]*cexpf(I*(w_n_oc[N_sf_widx][n_oc%3][m]+q->tmp_arg[n]+alpha*n+S_ns)); q->d[0]*cexpf(I*(w_n_oc[N_sf_widx][n_oc%3][m]+q->tmp_arg[n]+alpha*n+S_ns));
@ -767,7 +778,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
case SRSLTE_PUCCH_FORMAT_1: case SRSLTE_PUCCH_FORMAT_1:
bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
pucch_encode(q, format, n_pucch, sf_idx, rnti, bits, q->z_tmp); pucch_encode(q, format, n_pucch, sf_idx, rnti, bits, q->z_tmp);
corr = crealf(srslte_vec_dot_prod_conj_ccc(q->z, q->z_tmp, nof_re))/nof_re; corr = srslte_vec_corr_ccc(q->z, q->z_tmp, nof_re);
if (corr >= q->threshold_format1) { if (corr >= q->threshold_format1) {
ret = 1; ret = 1;
} else { } else {
@ -778,11 +789,11 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
break; break;
case SRSLTE_PUCCH_FORMAT_1A: case SRSLTE_PUCCH_FORMAT_1A:
bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
ret = 0; ret = 0;
for (int b=0;b<2;b++) { for (int b=0;b<2;b++) {
bits[0] = b; bits[0] = b;
pucch_encode(q, format, n_pucch, sf_idx, rnti, bits, q->z_tmp); pucch_encode(q, format, n_pucch, sf_idx, rnti, bits, q->z_tmp);
corr = crealf(srslte_vec_dot_prod_conj_ccc(q->z, q->z_tmp, nof_re))/nof_re; corr = srslte_vec_corr_ccc(q->z, q->z_tmp, nof_re);
if (corr > corr_max) { if (corr > corr_max) {
corr_max = corr; corr_max = corr;
b_max = b; b_max = b;
@ -790,7 +801,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
if (corr_max > q->threshold_format1) { // check with format1 in case ack+sr because ack only is binary if (corr_max > q->threshold_format1) { // check with format1 in case ack+sr because ack only is binary
ret = 1; ret = 1;
} }
DEBUG("format1a b=%d, corr=%f, nof_re=%d, th=%f\n", b, corr, nof_re, q->threshold_format1a); DEBUG("format1a b=%d, corr=%f, nof_re=%d\n", b, corr, nof_re);
} }
q->last_corr = corr_max; q->last_corr = corr_max;
bits[0] = b_max; bits[0] = b_max;

@ -380,7 +380,7 @@ int decode_cqi_long(srslte_uci_cqi_pusch_t *q, int16_t *q_bits, uint32_t Q,
ret = srslte_crc_checksum(&q->crc, q->tmp_cqi, nof_bits + 8); ret = srslte_crc_checksum(&q->crc, q->tmp_cqi, nof_bits + 8);
if (ret == 0) { if (ret == 0) {
memcpy(data, q->tmp_cqi, nof_bits*sizeof(uint8_t)); memcpy(data, q->tmp_cqi, nof_bits*sizeof(uint8_t));
ret = 1; ret = 1;
} else { } else {
ret = 0; ret = 0;
} }

@ -328,7 +328,7 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
if (args[0]=='\0') { if (args[0]=='\0') {
if (find_string(devices_str, "type=b200") && !strstr(args, "recv_frame_size")) { if (find_string(devices_str, "type=b200") && !strstr(args, "recv_frame_size")) {
// If B200 is available, use it // If B200 is available, use it
args = "type=b200"; args = "type=b200,master_clock_rate=30.72e6";
handler->devname = DEVNAME_B200; handler->devname = DEVNAME_B200;
} else if (find_string(devices_str, "type=x300")) { } else if (find_string(devices_str, "type=x300")) {
// Else if X300 is available, set master clock rate now (can't be changed later) // Else if X300 is available, set master clock rate now (can't be changed later)
@ -344,6 +344,8 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
handler->dynamic_rate = false; handler->dynamic_rate = false;
handler->devname = DEVNAME_X300; handler->devname = DEVNAME_X300;
} else if (strstr(args, "type=b200")) { } else if (strstr(args, "type=b200")) {
snprintf(args2, sizeof(args2), "%s,master_clock_rate=30.72e6", args);
args = args2;
handler->devname = DEVNAME_B200; handler->devname = DEVNAME_B200;
} }
} }
@ -400,6 +402,11 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
handler->nof_rx_channels = nof_channels; handler->nof_rx_channels = nof_channels;
handler->nof_tx_channels = nof_channels; handler->nof_tx_channels = nof_channels;
/* Set default rate to avoid decimation warnings */
uhd_usrp_set_rx_rate(handler->usrp, 1.92e6, 0);
uhd_usrp_set_tx_rate(handler->usrp, 1.92e6, 0);
/* Initialize rx and tx stremers */ /* Initialize rx and tx stremers */
uhd_rx_streamer_make(&handler->rx_stream); uhd_rx_streamer_make(&handler->rx_stream);
error = uhd_usrp_get_rx_stream(handler->usrp, &stream_args, handler->rx_stream); error = uhd_usrp_get_rx_stream(handler->usrp, &stream_args, handler->rx_stream);

@ -681,6 +681,15 @@ float srslte_vec_avg_power_cf(cf_t *x, uint32_t len) {
return crealf(srslte_vec_dot_prod_conj_ccc(x,x,len)) / len; return crealf(srslte_vec_dot_prod_conj_ccc(x,x,len)) / len;
} }
// Correlation assumes zero-mean x and y
float srslte_vec_corr_ccc(cf_t *x, cf_t *y, uint32_t len) {
// return crealf(srslte_vec_dot_prod_conj_ccc(x,y,len)) / len;
float s_x = crealf(srslte_vec_dot_prod_conj_ccc(x, x, len))/len;
float s_y = crealf(srslte_vec_dot_prod_conj_ccc(y, y, len))/len;
float cov = crealf(srslte_vec_dot_prod_conj_ccc(x, y, len))/len;
return cov/(sqrt(s_x*s_y));
}
void srslte_vec_abs_cf(cf_t *x, float *abs, uint32_t len) { void srslte_vec_abs_cf(cf_t *x, float *abs, uint32_t len) {
#ifndef HAVE_VOLK_MAG_FUNCTION #ifndef HAVE_VOLK_MAG_FUNCTION
int i; int i;

@ -336,7 +336,7 @@ void radio::set_tx_srate(float srate)
} else if (srate_khz == 15.36e3) { } else if (srate_khz == 15.36e3) {
nsamples = 131; nsamples = 131;
} else if (srate_khz == 23.04e3) { } else if (srate_khz == 23.04e3) {
nsamples = 175; nsamples = 150;
} else { } else {
/* Interpolate from known values */ /* Interpolate from known values */
printf("\nWarning TX/RX time offset for sampling rate %.0f KHz not calibrated. Using interpolated value\n\n", cur_tx_srate); printf("\nWarning TX/RX time offset for sampling rate %.0f KHz not calibrated. Using interpolated value\n\n", cur_tx_srate);
@ -356,7 +356,7 @@ void radio::set_tx_srate(float srate)
} else if (srate_khz == 15.36e3) { } else if (srate_khz == 15.36e3) {
nsamples = 86; nsamples = 86;
} else if (srate_khz == 23.04e3) { } else if (srate_khz == 23.04e3) {
nsamples = 119; nsamples = 110;
} else { } else {
/* Interpolate from known values */ /* Interpolate from known values */
printf("\nWarning TX/RX time offset for sampling rate %.0f KHz not calibrated. Using interpolated value\n\n", cur_tx_srate); printf("\nWarning TX/RX time offset for sampling rate %.0f KHz not calibrated. Using interpolated value\n\n", cur_tx_srate);

@ -102,6 +102,14 @@ void rlc::reset()
rlc_array[0].init(RLC_MODE_TM, rlc_log, default_lcid, pdcp, rrc, mac_timers); // SRB0 rlc_array[0].init(RLC_MODE_TM, rlc_log, default_lcid, pdcp, rrc, mac_timers); // SRB0
} }
void rlc::empty_queue()
{
for(uint32_t i=0; i<SRSLTE_N_RADIO_BEARERS; i++) {
if(rlc_array[i].active())
rlc_array[i].empty_queue();
}
}
/******************************************************************************* /*******************************************************************************
PDCP interface PDCP interface
*******************************************************************************/ *******************************************************************************/

@ -76,6 +76,12 @@ void rlc_entity::reset()
rlc = NULL; rlc = NULL;
} }
void rlc_entity::empty_queue()
{
rlc->empty_queue();
}
bool rlc_entity::active() bool rlc_entity::active()
{ {
return (rlc != NULL); return (rlc != NULL);

@ -15,14 +15,14 @@ qci_config = (
}; };
dl_um = { dl_um = {
sn_field_length = 10; sn_field_length = 10;
t_reordering = 80; t_reordering = 45;
}; };
}; };
logical_channel_config = { logical_channel_config = {
priority = 11; priority = 13;
prioritized_bit_rate = -1; prioritized_bit_rate = -1;
bucket_size_duration = 100; bucket_size_duration = 100;
log_chan_group = 3; log_chan_group = 2;
}; };
}, },
{ {

@ -57,8 +57,8 @@ drb_config = drb.conf
##################################################################### #####################################################################
[rf] [rf]
dl_earfcn = 3400 dl_earfcn = 3400
tx_gain = 70 tx_gain = 80
rx_gain = 50 rx_gain = 60
#device_name = auto #device_name = auto
#device_args = auto #device_args = auto
@ -121,7 +121,7 @@ enable = false
#pdsch_mcs = -1 #pdsch_mcs = -1
#pdsch_max_mcs = -1 #pdsch_max_mcs = -1
#pusch_mcs = -1 #pusch_mcs = -1
pusch_max_mcs = 16 #pusch_max_mcs = -1
nof_ctrl_symbols = 2 nof_ctrl_symbols = 2
##################################################################### #####################################################################
@ -141,9 +141,9 @@ nof_ctrl_symbols = 2
#pdsch_max_its = 4 #pdsch_max_its = 4
#nof_phy_threads = 2 #nof_phy_threads = 2
#pregenerate_signals = false #pregenerate_signals = false
#tx_amplitude = 0.8 #tx_amplitude = 0.6
#link_failure_nof_err = 50 #link_failure_nof_err = 50
#rrc_inactivity_timer = 30000 #rrc_inactivity_timer = 10000
#max_prach_offset_us = 30 #max_prach_offset_us = 30
##################################################################### #####################################################################

@ -108,7 +108,7 @@ public:
int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc); int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc);
int ul_sr_info(uint32_t tti, uint16_t rnti); int ul_sr_info(uint32_t tti, uint16_t rnti);
int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr); int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value = true);
int ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len); int ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len);
int ul_phr(uint16_t rnti, int phr); int ul_phr(uint16_t rnti, int phr);
int ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch_code); int ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch_code);

@ -104,7 +104,8 @@ public:
void set_alloc(ul_alloc_t alloc); void set_alloc(ul_alloc_t alloc);
void same_alloc(); void same_alloc();
bool is_adaptive_retx(); bool is_adaptive_retx();
void reset_pending_data();
bool has_pending_ack(); bool has_pending_ack();
uint32_t get_pending_data(); uint32_t get_pending_data();

@ -62,7 +62,7 @@ public:
void rem_bearer(uint32_t lc_id); void rem_bearer(uint32_t lc_id);
void dl_buffer_state(uint8_t lc_id, uint32_t tx_queue, uint32_t retx_queue); void dl_buffer_state(uint8_t lc_id, uint32_t tx_queue, uint32_t retx_queue);
void ul_buffer_state(uint8_t lc_id, uint32_t bsr); void ul_buffer_state(uint8_t lc_id, uint32_t bsr, bool set_value = true);
void ul_phr(int phr); void ul_phr(int phr);
void mac_buffer_state(uint32_t ce_code); void mac_buffer_state(uint32_t ce_code);
void ul_recv_len(uint32_t lcid, uint32_t len); void ul_recv_len(uint32_t lcid, uint32_t len);
@ -114,8 +114,10 @@ public:
uint32_t get_max_retx(); uint32_t get_max_retx();
bool get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2], uint32_t *L); bool get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2], uint32_t *L);
bool pucch_sr_collision(uint32_t current_tti, uint32_t n_cce); bool pucch_sr_collision(uint32_t current_tti, uint32_t n_cce);
uint32_t get_pending_ul_old_data();
private: private:
typedef struct { typedef struct {
@ -126,12 +128,13 @@ private:
} ue_bearer_t; } ue_bearer_t;
bool is_sr_triggered(); bool is_sr_triggered();
uint32_t get_pending_ul_old_data(); int alloc_pdu(int tbs, sched_interface::dl_sched_pdu_t* pdu);
int alloc_pdu(int tbs, sched_interface::dl_sched_pdu_t* pdu);
static uint32_t format1_count_prb(uint32_t bitmask, uint32_t cell_nof_prb); static uint32_t format1_count_prb(uint32_t bitmask, uint32_t cell_nof_prb);
static int cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t max_mcs, uint32_t *mcs); static int cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t max_mcs, uint32_t max_Qm, uint32_t *mcs);
static int alloc_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, uint32_t max_mcs, int *mcs); int alloc_tbs_dl(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, int *mcs);
int alloc_tbs_ul(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, int *mcs);
int alloc_tbs(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, bool is_ul, int *mcs);
static bool bearer_is_ul(ue_bearer_t *lch); static bool bearer_is_ul(ue_bearer_t *lch);
static bool bearer_is_dl(ue_bearer_t *lch); static bool bearer_is_dl(ue_bearer_t *lch);

@ -58,6 +58,10 @@ public:
} }
virtual ~ue() { virtual ~ue() {
for (int i=0;i<NOF_HARQ_PROCESSES;i++) {
srslte_softbuffer_rx_free(&softbuffer_rx[i]);
srslte_softbuffer_tx_free(&softbuffer_tx[i]);
}
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
} }
@ -81,7 +85,9 @@ public:
uint32_t rl_failure(); uint32_t rl_failure();
void rl_failure_reset(); void rl_failure_reset();
void set_lcg(uint32_t lcid, uint32_t lcg);
void metrics_read(srsenb::mac_metrics_t* metrics); void metrics_read(srsenb::mac_metrics_t* metrics);
void metrics_rx(bool crc, uint32_t tbs); void metrics_rx(bool crc, uint32_t tbs);
void metrics_tx(bool crc, uint32_t tbs); void metrics_tx(bool crc, uint32_t tbs);
@ -96,7 +102,9 @@ private:
void allocate_ce(srslte::sch_pdu *pdu, uint32_t lcid); void allocate_ce(srslte::sch_pdu *pdu, uint32_t lcid);
void metrics_phr(float phr); void metrics_phr(float phr);
uint32_t phr_counter; uint32_t phr_counter;
std::vector<uint32_t> lc_groups[4];
mac_metrics_t metrics; mac_metrics_t metrics;

@ -9,7 +9,7 @@ mac_cnfg =
ulsch_cnfg = ulsch_cnfg =
{ {
max_harq_tx = 4; max_harq_tx = 4;
periodic_bsr_timer = 5; // in ms periodic_bsr_timer = 40; // in ms
retx_bsr_timer = 320; // in ms retx_bsr_timer = 320; // in ms
}; };
@ -28,7 +28,7 @@ phy_cnfg =
{ {
beta_offset_ack_idx = 10; beta_offset_ack_idx = 10;
beta_offset_ri_idx = 5; beta_offset_ri_idx = 5;
beta_offset_cqi_idx = 5; beta_offset_cqi_idx = 10;
}; };
// PUCCH-SR resources are scheduled on time-frequeny domain first, then multiplexed in the same resource. // PUCCH-SR resources are scheduled on time-frequeny domain first, then multiplexed in the same resource.

@ -23,9 +23,9 @@ sib2 =
rach_cnfg = rach_cnfg =
{ {
num_ra_preambles = 52; num_ra_preambles = 52;
preamble_init_rx_target_pwr = -108; preamble_init_rx_target_pwr = -104;
pwr_ramping_step = 6; // in dB pwr_ramping_step = 6; // in dB
preamble_trans_max = 7; preamble_trans_max = 10;
ra_resp_win_size = 10; // in ms ra_resp_win_size = 10; // in ms
mac_con_res_timer = 64; // in ms mac_con_res_timer = 64; // in ms
max_harq_msg3_tx = 4; max_harq_msg3_tx = 4;
@ -53,14 +53,14 @@ sib2 =
pdsch_cnfg = pdsch_cnfg =
{ {
p_b = 0; p_b = 0;
rs_power = -4; rs_power = 20;
}; };
pusch_cnfg = pusch_cnfg =
{ {
n_sb = 1; n_sb = 1;
hopping_mode = "inter-subframe"; hopping_mode = "inter-subframe";
pusch_hopping_offset = 2; pusch_hopping_offset = 2;
enable_64_qam = false; enable_64_qam = false; // 64QAM PUSCH is not currently enabled
ul_rs = ul_rs =
{ {
cyclic_shift = 0; cyclic_shift = 0;
@ -71,25 +71,25 @@ sib2 =
}; };
pucch_cnfg = pucch_cnfg =
{ {
delta_pucch_shift = 1; delta_pucch_shift = 2;
n_rb_cqi = 1; n_rb_cqi = 2;
n_cs_an = 0; n_cs_an = 0;
n1_pucch_an = 2; n1_pucch_an = 12;
}; };
ul_pwr_ctrl = ul_pwr_ctrl =
{ {
p0_nominal_pusch = -108; p0_nominal_pusch = -85;
alpha = 1.0; alpha = 0.7;
p0_nominal_pucch = -88; p0_nominal_pucch = -107;
delta_flist_pucch = delta_flist_pucch =
{ {
format_1 = 2; format_1 = 0;
format_1b = 3; format_1b = 3;
format_2 = 0; format_2 = 1;
format_2a = 0; format_2a = 2;
format_2b = 0; format_2b = 2;
}; };
delta_preamble_msg3 = 4; delta_preamble_msg3 = 8;
}; };
ul_cp_length = "Normal"; ul_cp_length = "Normal";
}; };

@ -33,6 +33,7 @@
#include <strings.h> #include <strings.h>
#include <pthread.h> #include <pthread.h>
#include <unistd.h> #include <unistd.h>
#include <srslte/interfaces/sched_interface.h>
#include "srslte/common/log.h" #include "srslte/common/log.h"
#include "mac/mac.h" #include "mac/mac.h"
@ -163,7 +164,9 @@ int mac::rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint
int mac::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) int mac::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg)
{ {
if (ue_db.count(rnti)) { if (ue_db.count(rnti)) {
// configure BSR group in UE
ue_db[rnti]->set_lcg(lc_id, (uint32_t) cfg->group);
return scheduler.bearer_ue_cfg(rnti, lc_id, cfg); return scheduler.bearer_ue_cfg(rnti, lc_id, cfg);
} else { } else {
Error("User rnti=0x%x not found\n", rnti); Error("User rnti=0x%x not found\n", rnti);
@ -259,7 +262,7 @@ void mac::rl_failure(uint16_t rnti)
if (ue_db.count(rnti)) { if (ue_db.count(rnti)) {
uint32_t nof_fails = ue_db[rnti]->rl_failure(); uint32_t nof_fails = ue_db[rnti]->rl_failure();
if (nof_fails >= (uint32_t) args.link_failure_nof_err && args.link_failure_nof_err > 0) { if (nof_fails >= (uint32_t) args.link_failure_nof_err && args.link_failure_nof_err > 0) {
Info("Detected PUSCH failure for rnti=0x%x\n", rnti); Info("Detected Uplink failure for rnti=0x%x\n", rnti);
rrc_h->rl_failure(rnti); rrc_h->rl_failure(rnti);
ue_db[rnti]->rl_failure_reset(); ue_db[rnti]->rl_failure_reset();
} }

@ -302,12 +302,12 @@ int sched::ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch
return ret; return ret;
} }
int sched::ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr) int sched::ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
int ret = 0; int ret = 0;
if (ue_db.count(rnti)) { if (ue_db.count(rnti)) {
ue_db[rnti].ul_buffer_state(lcid, bsr); ue_db[rnti].ul_buffer_state(lcid, bsr, set_value);
} else { } else {
Error("User rnti=0x%x not found\n", rnti); Error("User rnti=0x%x not found\n", rnti);
ret = -1; ret = -1;
@ -792,13 +792,13 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
user->unset_sr(); user->unset_sr();
} }
log_h->info("SCHED: %s %s rnti=0x%x, pid=%d, dci=%d,%d, grant=%d,%d, n_rtx=%d, tbs=%d, bsr=%d (%d)\n", log_h->info("SCHED: %s %s rnti=0x%x, pid=%d, dci=%d,%d, grant=%d,%d, n_rtx=%d, tbs=%d, bsr=%d (%d-%d)\n",
is_rar?"RAR":"UL", is_rar?"RAR":"UL",
is_newtx?"tx":"retx", is_newtx?"tx":"retx",
rnti, h->get_id(), rnti, h->get_id(),
sched_result->pusch[nof_dci_elems].dci_location.L, sched_result->pusch[nof_dci_elems].dci_location.ncce, sched_result->pusch[nof_dci_elems].dci_location.L, sched_result->pusch[nof_dci_elems].dci_location.ncce,
alloc.RB_start, alloc.L, h->nof_retx(), sched_result->pusch[nof_dci_elems].tbs, alloc.RB_start, alloc.L, h->nof_retx(), sched_result->pusch[nof_dci_elems].tbs,
user->get_pending_ul_new_data(current_tti),pending_data_before); user->get_pending_ul_new_data(current_tti),pending_data_before, user->get_pending_ul_old_data());
nof_dci_elems++; nof_dci_elems++;
} else { } else {
@ -812,8 +812,16 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
} }
} }
} }
} }
// Update pending data counters after this TTI
for(std::map<uint16_t, sched_ue>::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) {
sched_ue *user = (sched_ue *) &iter->second;
uint16_t rnti = (uint16_t) iter->first;
user->get_ul_harq(current_tti)->reset_pending_data();
}
sched_result->nof_dci_elems = nof_dci_elems; sched_result->nof_dci_elems = nof_dci_elems;
sched_result->nof_phich_elems = nof_phich_elems; sched_result->nof_phich_elems = nof_phich_elems;

@ -98,7 +98,7 @@ bool harq_proc::get_ack()
void harq_proc::set_ack(bool ack_) void harq_proc::set_ack(bool ack_)
{ {
ack = ack_; ack = ack_;
ack_received = true; ack_received = true;
log_h->debug("ACK=%d received pid=%d, n_rtx=%d, max_retx=%d\n", ack_, id, n_rtx, max_retx); log_h->debug("ACK=%d received pid=%d, n_rtx=%d, max_retx=%d\n", ack_, id, n_rtx, max_retx);
if (n_rtx >= max_retx) { if (n_rtx >= max_retx) {
Warning("SCHED: discarting TB pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", id, tti, max_retx); Warning("SCHED: discarting TB pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", id, tti, max_retx);
@ -229,13 +229,22 @@ bool ul_harq_proc::has_pending_ack()
active = false; active = false;
} }
if (!active) { if (!active) {
pending_data = 0; need_ack = false;
need_ack = false;
} }
return ret; return ret;
} }
uint32_t ul_harq_proc::get_pending_data()
void ul_harq_proc::reset_pending_data()
{
if (!active) {
pending_data = 0;
}
}
uint32_t ul_harq_proc::get_pending_data()
{ {
return pending_data; return pending_data;
} }

@ -26,6 +26,8 @@
#include <string.h> #include <string.h>
#include <boost/concept_check.hpp> #include <boost/concept_check.hpp>
#include <srslte/interfaces/sched_interface.h>
#include <srslte/phy/phch/pucch.h>
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "srslte/common/pdu.h" #include "srslte/common/pdu.h"
@ -163,12 +165,17 @@ void sched_ue::phy_config_enabled(uint32_t tti, bool enabled)
phy_config_dedicated_enabled = enabled; phy_config_dedicated_enabled = enabled;
} }
void sched_ue::ul_buffer_state(uint8_t lc_id, uint32_t bsr) void sched_ue::ul_buffer_state(uint8_t lc_id, uint32_t bsr, bool set_value)
{ {
if (lc_id < sched_interface::MAX_LC) { if (lc_id < sched_interface::MAX_LC) {
lch[lc_id].bsr = bsr; if (set_value) {
Debug("SCHED: UL lcid=%d buffer_state=%d\n", lc_id, bsr); lch[lc_id].bsr = bsr;
} } else {
lch[lc_id].bsr += bsr;
}
}
Debug("SCHED: bsr=%d, lcid=%d, bsr={%d,%d,%d,%d}\n", bsr, lc_id,
lch[0].bsr, lch[1].bsr, lch[2].bsr, lch[3].bsr);
} }
void sched_ue::ul_phr(int phr) void sched_ue::ul_phr(int phr)
@ -230,7 +237,8 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2], uint32
if (!phy_config_dedicated_enabled) { if (!phy_config_dedicated_enabled) {
return false; return false;
} }
srslte_pucch_sched_t pucch_sched; srslte_pucch_sched_t pucch_sched;
pucch_sched.sps_enabled = false;
pucch_sched.n_pucch_sr = cfg.sr_N_pucch; pucch_sched.n_pucch_sr = cfg.sr_N_pucch;
pucch_sched.n_pucch_2 = cfg.n_pucch_cqi; pucch_sched.n_pucch_2 = cfg.n_pucch_cqi;
pucch_sched.N_pucch_1 = cfg.pucch_cfg.n1_pucch_an; pucch_sched.N_pucch_1 = cfg.pucch_cfg.n1_pucch_an;
@ -239,7 +247,7 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2], uint32
// First check if it has pending ACKs // First check if it has pending ACKs
for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) { for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) {
if (((dl_harq[i].get_tti()+8)%10240) == current_tti) { if (((dl_harq[i].get_tti()+4)%10240) == current_tti) {
uint32_t n_pucch = srslte_pucch_get_npucch(dl_harq[i].get_n_cce(), SRSLTE_PUCCH_FORMAT_1A, has_sr, &pucch_sched); uint32_t n_pucch = srslte_pucch_get_npucch(dl_harq[i].get_n_cce(), SRSLTE_PUCCH_FORMAT_1A, has_sr, &pucch_sched);
if (prb_idx) { if (prb_idx) {
for (int i=0;i<2;i++) { for (int i=0;i<2;i++) {
@ -249,7 +257,7 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2], uint32
if (L) { if (L) {
*L = 1; *L = 1;
} }
Debug("SCHED: Reserved Format1A PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d\n", rnti, prb_idx[0], prb_idx[1], n_pucch); Info("SCHED: Reserved Format1A PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d\n", rnti, prb_idx[0], prb_idx[1], n_pucch);
return true; return true;
} }
} }
@ -263,9 +271,24 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2], uint32
if (L) { if (L) {
*L = 1; *L = 1;
} }
Debug("SCHED: Reserved Format1 PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d\n", rnti, prb_idx[0], prb_idx[1], cfg.sr_N_pucch); Info("SCHED: Reserved Format1 PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d\n", rnti, prb_idx[0], prb_idx[1], cfg.sr_N_pucch);
return true; return true;
} }
// Finally check Format2 (periodic CQI)
if (cfg.cqi_enabled && srslte_cqi_send(cfg.cqi_idx, current_tti)) {
if (prb_idx) {
for (int i=0;i<2;i++) {
prb_idx[i] = srslte_pucch_n_prb(&cfg.pucch_cfg, SRSLTE_PUCCH_FORMAT_2, cfg.cqi_pucch, cell.nof_prb, cell.cp, i);
}
}
if(L) {
*L = 2;
}
Info("SCHED: Reserved Format2 PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d, pmi_idx=%d\n",
rnti, prb_idx[0], prb_idx[1], cfg.cqi_pucch, cfg.cqi_idx);
return true;
}
return false; return false;
} }
@ -297,6 +320,8 @@ void sched_ue::ul_recv_len(uint32_t lcid, uint32_t len)
} }
} }
} }
Debug("SCHED: recv_len=%d, lcid=%d, bsr={%d,%d,%d,%d}\n", len, lcid,
lch[0].bsr, lch[1].bsr, lch[2].bsr, lch[3].bsr);
} }
void sched_ue::set_ul_crc(uint32_t tti, bool crc_res) void sched_ue::set_ul_crc(uint32_t tti, bool crc_res)
@ -370,7 +395,7 @@ int sched_ue::generate_format1(dl_harq_proc *h,
uint32_t nof_ctrl_symbols = cfi+(cell.nof_prb<10?1:0); uint32_t nof_ctrl_symbols = cfi+(cell.nof_prb<10?1:0);
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);
if (fixed_mcs_dl < 0) { if (fixed_mcs_dl < 0) {
tbs = alloc_tbs(dl_cqi, nof_prb, nof_re, req_bytes, max_mcs_dl, &mcs); tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs);
} else { } else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), nof_prb); tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), nof_prb);
mcs = fixed_mcs_dl; mcs = fixed_mcs_dl;
@ -441,7 +466,7 @@ int sched_ue::generate_format0(ul_harq_proc *h,
uint32_t N_srs = 0; uint32_t N_srs = 0;
uint32_t nof_re = (2*(SRSLTE_CP_NSYMB(cell.cp)-1) - N_srs)*allocation.L*SRSLTE_NRE; uint32_t nof_re = (2*(SRSLTE_CP_NSYMB(cell.cp)-1) - N_srs)*allocation.L*SRSLTE_NRE;
if (fixed_mcs_ul < 0) { if (fixed_mcs_ul < 0) {
tbs = alloc_tbs(ul_cqi, allocation.L, nof_re, req_bytes, max_mcs_ul, &mcs); tbs = alloc_tbs_ul(allocation.L, nof_re, req_bytes, &mcs);
} else { } else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_ul), allocation.L); tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_ul), allocation.L);
mcs = fixed_mcs_ul; mcs = fixed_mcs_ul;
@ -554,6 +579,10 @@ uint32_t sched_ue::get_pending_ul_new_data(uint32_t tti)
} else { } else {
pending_data = 0; pending_data = 0;
} }
if (pending_data) {
Debug("SCHED: pending_data=%d, pending_ul_data=%d, bsr={%d,%d,%d,%d}\n", pending_data,pending_ul_data,
lch[0].bsr, lch[1].bsr, lch[2].bsr, lch[3].bsr);
}
return pending_data; return pending_data;
} }
@ -581,7 +610,7 @@ uint32_t sched_ue::get_required_prb_dl(uint32_t req_bytes, uint32_t nof_ctrl_sym
for (n=1;n<cell.nof_prb && nbytes < req_bytes;n++) { for (n=1;n<cell.nof_prb && nbytes < req_bytes;n++) {
nof_re = srslte_ra_dl_approx_nof_re(cell, n, nof_ctrl_symbols); nof_re = srslte_ra_dl_approx_nof_re(cell, n, nof_ctrl_symbols);
if (fixed_mcs_dl < 0) { if (fixed_mcs_dl < 0) {
tbs = alloc_tbs(dl_cqi, n, nof_re, 0, max_mcs_dl, &mcs); tbs = alloc_tbs_dl(n, nof_re, 0, &mcs);
} else { } else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), n); tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), n);
} }
@ -610,7 +639,7 @@ uint32_t sched_ue::get_required_prb_ul(uint32_t req_bytes)
uint32_t nof_re = (2*(SRSLTE_CP_NSYMB(cell.cp)-1) - N_srs)*n*SRSLTE_NRE; uint32_t nof_re = (2*(SRSLTE_CP_NSYMB(cell.cp)-1) - N_srs)*n*SRSLTE_NRE;
int tbs = 0; int tbs = 0;
if (fixed_mcs_ul < 0) { if (fixed_mcs_ul < 0) {
tbs = alloc_tbs(ul_cqi, n, nof_re, 0, max_mcs_ul, &mcs); tbs = alloc_tbs_ul(n, nof_re, 0, &mcs);
} else { } else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_ul), n); tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_ul), n);
} }
@ -731,36 +760,60 @@ uint32_t sched_ue::format1_count_prb(uint32_t bitmask, uint32_t cell_nof_prb) {
return nof_prb; return nof_prb;
} }
int sched_ue::cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t max_mcs, uint32_t *mcs) { int sched_ue::cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t max_mcs, uint32_t max_Qm, uint32_t *mcs) {
float max_coderate = srslte_cqi_to_coderate(cqi); float max_coderate = srslte_cqi_to_coderate(cqi);
int sel_mcs = max_mcs+1; int sel_mcs = max_mcs+1;
float coderate = 99; float coderate = 99;
float eff_coderate = 99;
uint32_t Qm = 1;
int tbs = 0; int tbs = 0;
do { do {
sel_mcs--; sel_mcs--;
uint32_t tbs_idx = srslte_ra_tbs_idx_from_mcs(sel_mcs); uint32_t tbs_idx = srslte_ra_tbs_idx_from_mcs(sel_mcs);
tbs = srslte_ra_tbs_from_idx(tbs_idx, nof_prb); tbs = srslte_ra_tbs_from_idx(tbs_idx, nof_prb);
coderate = srslte_pdsch_coderate(tbs, nof_re); coderate = srslte_coderate(tbs, nof_re);
} while(sel_mcs > 0 && coderate >= max_coderate); Qm = SRSLTE_MIN(max_Qm, srslte_mod_bits_x_symbol(srslte_ra_mod_from_mcs(sel_mcs)));
eff_coderate = coderate/Qm;
} while((sel_mcs > 0 && coderate > max_coderate) || eff_coderate > 0.930);
if (mcs) { if (mcs) {
*mcs = (uint32_t) sel_mcs; *mcs = (uint32_t) sel_mcs;
} }
return tbs; return tbs;
} }
/* In this scheduler we tend to use all the available bandwidth and select the MCS int sched_ue::alloc_tbs_dl(uint32_t nof_prb,
uint32_t nof_re,
uint32_t req_bytes,
int *mcs)
{
return alloc_tbs(nof_prb, nof_re, req_bytes, false, mcs);
}
int sched_ue::alloc_tbs_ul(uint32_t nof_prb,
uint32_t nof_re,
uint32_t req_bytes,
int *mcs)
{
return alloc_tbs(nof_prb, nof_re, req_bytes, true, mcs);
}
/* In this scheduler we tend to use all the available bandwidth and select the MCS
* that approximates the minimum between the capacity and the requested rate * that approximates the minimum between the capacity and the requested rate
*/ */
int sched_ue::alloc_tbs(uint32_t cqi, int sched_ue::alloc_tbs(uint32_t nof_prb,
uint32_t nof_prb, uint32_t nof_re,
uint32_t nof_re, uint32_t req_bytes,
uint32_t req_bytes, bool is_ul,
uint32_t max_mcs, int *mcs)
int *mcs) {
{ uint32_t sel_mcs = 0;
uint32_t sel_mcs = 0;
int tbs = cqi_to_tbs(cqi, nof_prb, nof_re, max_mcs, &sel_mcs)/8; uint32_t cqi = is_ul?ul_cqi:dl_cqi;
uint32_t max_mcs = is_ul?max_mcs_ul:max_mcs_dl;
uint32_t max_Qm = is_ul?4:6; // Allow 16-QAM in PUSCH Only
int tbs = cqi_to_tbs(cqi, nof_prb, nof_re, max_mcs, max_Qm, &sel_mcs)/8;
/* If less bytes are requested, lower the MCS */ /* If less bytes are requested, lower the MCS */
if (tbs > (int) req_bytes && req_bytes > 0) { if (tbs > (int) req_bytes && req_bytes > 0) {

@ -58,8 +58,14 @@ void ue::config(uint16_t rnti_, uint32_t nof_prb, sched_interface *sched_, rrc_i
for(int i=0;i<NOF_HARQ_PROCESSES;i++) { for(int i=0;i<NOF_HARQ_PROCESSES;i++) {
pending_buffers[i] = NULL; pending_buffers[i] = NULL;
} }
// Set LCID group for SRB0 and SRB1
set_lcg(0, 0);
set_lcg(1, 0);
} }
void ue::reset() void ue::reset()
{ {
bzero(&metrics, sizeof(mac_metrics_t)); bzero(&metrics, sizeof(mac_metrics_t));
@ -86,7 +92,16 @@ void ue::rl_failure_reset()
{ {
nof_failures = 0; nof_failures = 0;
} }
void ue::set_lcg(uint32_t lcid, uint32_t lcg)
{
// find and remove if already exists
for (int i=0;i<4;i++) {
lc_groups[lcg].erase(std::remove(lc_groups[lcg].begin(), lc_groups[lcg].end(), lcid), lc_groups[lcg].end());
}
lc_groups[lcg].push_back(lcid);
}
srslte_softbuffer_rx_t* ue::get_rx_softbuffer(uint32_t tti) srslte_softbuffer_rx_t* ue::get_rx_softbuffer(uint32_t tti)
{ {
return &softbuffer_rx[tti%NOF_HARQ_PROCESSES]; return &softbuffer_rx[tti%NOF_HARQ_PROCESSES];
@ -136,63 +151,83 @@ void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, uint32_t tstamp)
if (pcap) { if (pcap) {
pcap->write_ul_crnti(pdu, nof_bytes, rnti, true, last_tti); pcap->write_ul_crnti(pdu, nof_bytes, rnti, true, last_tti);
} }
uint32_t lcid_most_data = 0;
int most_data = -99;
while(mac_msg_ul.next()) { while(mac_msg_ul.next()) {
assert(mac_msg_ul.get()); assert(mac_msg_ul.get());
if (mac_msg_ul.get()->is_sdu()) if (mac_msg_ul.get()->is_sdu()) {
{
// Route logical channel // Route logical channel
log_h->debug_hex(mac_msg_ul.get()->get_sdu_ptr(), mac_msg_ul.get()->get_payload_size(), log_h->debug_hex(mac_msg_ul.get()->get_sdu_ptr(), mac_msg_ul.get()->get_payload_size(),
"PDU: rnti=0x%x, lcid=%d, %d bytes\n", "PDU: rnti=0x%x, lcid=%d, %d bytes\n",
rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size()); rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size());
/* In some cases, an uplink transmission with only CQI has all zeros and gets routed to RRC /* In some cases, an uplink transmission with only CQI has all zeros and gets routed to RRC
* Compute the checksum if lcid=0 and avoid routing in that case * Compute the checksum if lcid=0 and avoid routing in that case
*/ */
bool route_pdu = true; bool route_pdu = true;
if (mac_msg_ul.get()->get_sdu_lcid() == 0) { if (mac_msg_ul.get()->get_sdu_lcid() == 0) {
uint8_t *x = mac_msg_ul.get()->get_sdu_ptr(); uint8_t *x = mac_msg_ul.get()->get_sdu_ptr();
uint32_t sum = 0; uint32_t sum = 0;
for (uint32_t i=0;i<mac_msg_ul.get()->get_payload_size();i++) { for (uint32_t i = 0; i < mac_msg_ul.get()->get_payload_size(); i++) {
sum += x[i]; sum += x[i];
} }
if (sum == 0) { if (sum == 0) {
route_pdu = false; route_pdu = false;
Warning("Received all zero PDU\n"); Warning("Received all zero PDU\n");
} }
} }
if (route_pdu) { if (route_pdu) {
rlc->write_pdu(rnti, rlc->write_pdu(rnti,
mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_sdu_lcid(),
mac_msg_ul.get()->get_sdu_ptr(), mac_msg_ul.get()->get_sdu_ptr(),
mac_msg_ul.get()->get_payload_size()); mac_msg_ul.get()->get_payload_size());
} }
// Indicate scheduler to update BSR counters // Indicate scheduler to update BSR counters
sched->ul_recv_len(rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size()); sched->ul_recv_len(rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size());
if ((int) mac_msg_ul.get()->get_payload_size() > most_data) {
most_data = (int) mac_msg_ul.get()->get_payload_size();
lcid_most_data = mac_msg_ul.get()->get_sdu_lcid();
}
// Save contention resolution if lcid == 0 // Save contention resolution if lcid == 0
if (mac_msg_ul.get()->get_sdu_lcid() == 0 && route_pdu) { if (mac_msg_ul.get()->get_sdu_lcid() == 0 && route_pdu) {
uint32_t nbytes = srslte::sch_subh::MAC_CE_CONTRES_LEN; uint32_t nbytes = srslte::sch_subh::MAC_CE_CONTRES_LEN;
if (mac_msg_ul.get()->get_payload_size() >= nbytes) { if (mac_msg_ul.get()->get_payload_size() >= nbytes) {
uint8_t *ue_cri_ptr = (uint8_t*) &conres_id; uint8_t *ue_cri_ptr = (uint8_t *) &conres_id;
uint8_t *pkt_ptr = mac_msg_ul.get()->get_sdu_ptr(); // Warning here: we want to include the uint8_t *pkt_ptr = mac_msg_ul.get()->get_sdu_ptr(); // Warning here: we want to include the
for (uint32_t i=0;i<nbytes;i++) { for (uint32_t i = 0; i < nbytes; i++) {
ue_cri_ptr[nbytes-i-1] = pkt_ptr[i]; ue_cri_ptr[nbytes - i - 1] = pkt_ptr[i];
} }
} else { } else {
Error("Received CCCH UL message of invalid size=%d bytes\n", mac_msg_ul.get()->get_payload_size()); Error("Received CCCH UL message of invalid size=%d bytes\n", mac_msg_ul.get()->get_payload_size());
} }
}
} else {
// Process MAC Control Element
if (!process_ce(mac_msg_ul.get())) {
Warning("Received Subheader with invalid or unkonwn LCID\n");
} }
} }
} }
mac_msg_ul.reset();
/* Process CE after all SDUs because we need to update BSR after */
bool bsr_received = false;
while(mac_msg_ul.next()) {
assert(mac_msg_ul.get());
if (!mac_msg_ul.get()->is_sdu()) {
// Process MAC Control Element
bsr_received |= process_ce(mac_msg_ul.get());
}
}
// If BSR is not received means that new data has arrived and there is no space for BSR transmission
if (!bsr_received && lcid_most_data > 2) {
// Add BSR to the LCID for which most data was received
sched->ul_bsr(rnti, lcid_most_data, 256, false); // false adds BSR instead of setting
Debug("BSR not received. Giving extra grant\n");
}
Debug("MAC PDU processed\n"); Debug("MAC PDU processed\n");
@ -220,9 +255,10 @@ void ue::push_pdu(uint32_t tti, uint32_t len)
bool ue::process_ce(srslte::sch_subh *subh) { bool ue::process_ce(srslte::sch_subh *subh) {
uint32_t buff_size[4] = {0, 0, 0, 0}; uint32_t buff_size[4] = {0, 0, 0, 0};
uint32_t idx = 0; float phr = 0;
float phr = 0; int idx = 0;
uint16_t old_rnti = 0; uint16_t old_rnti = 0;
bool is_bsr = false;
switch(subh->ce_type()) { switch(subh->ce_type()) {
case srslte::sch_subh::PHR_REPORT: case srslte::sch_subh::PHR_REPORT:
phr = subh->get_phr(); phr = subh->get_phr();
@ -241,23 +277,26 @@ bool ue::process_ce(srslte::sch_subh *subh) {
} }
break; break;
case srslte::sch_subh::TRUNC_BSR: case srslte::sch_subh::TRUNC_BSR:
case srslte::sch_subh::SHORT_BSR: case srslte::sch_subh::SHORT_BSR:
case srslte::sch_subh::LONG_BSR:
idx = subh->get_bsr(buff_size); idx = subh->get_bsr(buff_size);
if (idx > 0) { for (uint32_t i=0;i<lc_groups[idx].size();i++) {
// Indicate BSR to scheduler // Indicate BSR to scheduler
sched->ul_bsr(rnti, idx, buff_size[idx]); sched->ul_bsr(rnti, lc_groups[idx][i], buff_size[idx]);
Info("CE: Received BSR rnti=0x%x, lcid=%d, value=%d\n", rnti, idx, buff_size[idx]); }
} else if (idx == 0) { Info("CE: Received %s BSR rnti=0x%x, lcg=%d, value=%d\n",
// TODO: map lcid group to lcid subh->ce_type()==srslte::sch_subh::SHORT_BSR?"Short":"Trunc", rnti, idx, buff_size[idx]);
for (int i=0;i<4;i++) { is_bsr = true;
sched->ul_bsr(rnti, i, buff_size[i]); break;
case srslte::sch_subh::LONG_BSR:
subh->get_bsr(buff_size);
for (int idx=0;idx<4;idx++) {
for (uint32_t i=0;i<lc_groups[idx].size();i++) {
sched->ul_bsr(rnti, lc_groups[idx][i], buff_size[idx]);
} }
Info("CE: Received Long BSR rnti=0x%x, value=%d,%d,%d,%d\n", rnti,
buff_size[0], buff_size[1], buff_size[2], buff_size[3]);
} else {
printf("Error!\n");
} }
is_bsr = true;
Info("CE: Received Long BSR rnti=0x%x, value=%d,%d,%d,%d\n", rnti,
buff_size[0], buff_size[1], buff_size[2], buff_size[3]);
break; break;
case srslte::sch_subh::PADDING: case srslte::sch_subh::PADDING:
Debug("CE: Received padding for rnti=0x%x\n", rnti); Debug("CE: Received padding for rnti=0x%x\n", rnti);
@ -266,7 +305,7 @@ bool ue::process_ce(srslte::sch_subh *subh) {
Error("CE: Invalid lcid=0x%x\n", subh->ce_type()); Error("CE: Invalid lcid=0x%x\n", subh->ce_type());
break; break;
} }
return true; return is_bsr;
} }

@ -130,7 +130,7 @@ void parse_args(all_args_t *args, int argc, char* argv[]) {
bpo::value<int>(&args->expert.mac.sched.pusch_mcs)->default_value(-1), bpo::value<int>(&args->expert.mac.sched.pusch_mcs)->default_value(-1),
"Optional fixed PUSCH MCS (ignores reported CQIs if specified)") "Optional fixed PUSCH MCS (ignores reported CQIs if specified)")
("scheduler.pusch_max_mcs", ("scheduler.pusch_max_mcs",
bpo::value<int>(&args->expert.mac.sched.pusch_max_mcs)->default_value(16), bpo::value<int>(&args->expert.mac.sched.pusch_max_mcs)->default_value(-1),
"Optional PUSCH MCS limit") "Optional PUSCH MCS limit")
("scheduler.nof_ctrl_symbols", ("scheduler.nof_ctrl_symbols",
bpo::value<int>(&args->expert.mac.sched.nof_ctrl_symbols)->default_value(3), bpo::value<int>(&args->expert.mac.sched.nof_ctrl_symbols)->default_value(3),
@ -152,7 +152,7 @@ void parse_args(all_args_t *args, int argc, char* argv[]) {
"Maximum number of turbo decoder iterations") "Maximum number of turbo decoder iterations")
("expert.tx_amplitude", ("expert.tx_amplitude",
bpo::value<float>(&args->expert.phy.tx_amplitude)->default_value(0.8), bpo::value<float>(&args->expert.phy.tx_amplitude)->default_value(0.6),
"Transmit amplitude factor") "Transmit amplitude factor")
("expert.nof_phy_threads", ("expert.nof_phy_threads",
@ -176,7 +176,7 @@ void parse_args(all_args_t *args, int argc, char* argv[]) {
"Chooses the coefficients for the 3-tap channel estimator centered filter.") "Chooses the coefficients for the 3-tap channel estimator centered filter.")
("expert.rrc_inactivity_timer", ("expert.rrc_inactivity_timer",
bpo::value<uint32_t>(&args->expert.rrc_inactivity_timer)->default_value(30000), bpo::value<uint32_t>(&args->expert.rrc_inactivity_timer)->default_value(10000),
"Inactivity timer in ms") "Inactivity timer in ms")

@ -49,6 +49,8 @@ using namespace std;
#ifdef ENABLE_GUI #ifdef ENABLE_GUI
#include "srsgui/srsgui.h" #include "srsgui/srsgui.h"
#include <semaphore.h> #include <semaphore.h>
#include <srslte/phy/phch/ra.h>
void init_plots(srsenb::phch_worker *worker); void init_plots(srsenb::phch_worker *worker);
pthread_t plot_thread; pthread_t plot_thread;
sem_t plot_sem; sem_t plot_sem;
@ -109,7 +111,7 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_)
return; return;
} }
srslte_pucch_set_threshold(&enb_ul.pucch, 0.8, 0.5); srslte_pucch_set_threshold(&enb_ul.pucch, 0.8);
srslte_sch_set_max_noi(&enb_ul.pusch.ul_sch, phy->params.pusch_max_its); srslte_sch_set_max_noi(&enb_ul.pusch.ul_sch, phy->params.pusch_max_its);
srslte_enb_dl_set_amp(&enb_dl, phy->params.tx_amplitude); srslte_enb_dl_set_amp(&enb_dl, phy->params.tx_amplitude);
@ -178,8 +180,8 @@ void phch_worker::set_config_dedicated(uint16_t rnti,
srslte_enb_ul_cfg_ue(&enb_ul, rnti, uci_cfg, pucch_sched, srs_cfg); srslte_enb_ul_cfg_ue(&enb_ul, rnti, uci_cfg, pucch_sched, srs_cfg);
ue_db[rnti].I_sr = I_sr; ue_db[rnti].I_sr = I_sr;
ue_db[rnti].I_sr_en = true; ue_db[rnti].I_sr_en = true;
if (pucch_cqi) { if (pucch_cqi) {
ue_db[rnti].pmi_idx = pmi_idx; ue_db[rnti].pmi_idx = pmi_idx;
ue_db[rnti].cqi_en = true; ue_db[rnti].cqi_en = true;
@ -355,7 +357,6 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch,
} }
if (cqi_enabled) { if (cqi_enabled) {
uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value);
Info("cqi enabled len=%d\n", uci_data.uci_cqi_len);
} }
// mark this tti as having an ul grant to avoid pucch // mark this tti as having an ul grant to avoid pucch
@ -364,7 +365,11 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch,
srslte_ra_ul_grant_t phy_grant; srslte_ra_ul_grant_t phy_grant;
int res = -1; int res = -1;
if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant, tti%8)) { if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant, tti%8)) {
res = srslte_enb_ul_get_pusch(&enb_ul, &phy_grant, grants[i].softbuffer, if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) {
phy_grant.mcs.mod = SRSLTE_MOD_16QAM;
}
phy_grant.Qm = SRSLTE_MIN(phy_grant.Qm, 4);
res = srslte_enb_ul_get_pusch(&enb_ul, &phy_grant, grants[i].softbuffer,
rnti, grants[i].rv_idx, rnti, grants[i].rv_idx,
grants[i].current_tx_nb, grants[i].current_tx_nb,
grants[i].data, grants[i].data,
@ -415,7 +420,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch,
} }
*/ */
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\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\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,

@ -83,11 +83,11 @@ void rlc::reset(uint16_t rnti)
void rlc::clear_buffer(uint16_t rnti) void rlc::clear_buffer(uint16_t rnti)
{ {
if (users.count(rnti)) { if (users.count(rnti)) {
log_h->info("Clearing buffer rnti=0x%x\n", rnti); users[rnti].rlc->empty_queue();
users[rnti].rlc->reset();
for (int i=0;i<SRSLTE_N_RADIO_BEARERS;i++) { for (int i=0;i<SRSLTE_N_RADIO_BEARERS;i++) {
mac->rlc_buffer_state(rnti, i, 0, 0); mac->rlc_buffer_state(rnti, i, 0, 0);
} }
log_h->info("Cleared buffer rnti=0x%x\n", rnti);
} }
} }

@ -24,6 +24,8 @@
* *
*/ */
#include <srslte/interfaces/sched_interface.h>
#include <srslte/asn1/liblte_rrc.h>
#include "srslte/asn1/liblte_mme.h" #include "srslte/asn1/liblte_mme.h"
#include "upper/rrc.h" #include "upper/rrc.h"
@ -312,12 +314,11 @@ void rrc::release_complete(uint16_t rnti)
if (!users[rnti].is_idle()) { if (!users[rnti].is_idle()) {
rlc->clear_buffer(rnti); rlc->clear_buffer(rnti);
users[rnti].send_connection_release(); users[rnti].send_connection_release();
// There is no RRCReleaseComplete message from UE thus sleep to enable all retx in PHY +50% // There is no RRCReleaseComplete message from UE thus wait ~100 subframes for tx
usleep(1.5*8*1e3*cfg.mac_cnfg.ulsch_cnfg.max_harq_tx); usleep(100000);
} }
rem_user(rnti); rem_user(rnti);
} else { } else {
rrc_log->error("Received ReleaseComplete for unknown rnti=0x%x\n", rnti); rrc_log->error("Received ReleaseComplete for unknown rnti=0x%x\n", rnti);
} }
} }
@ -437,7 +438,7 @@ void rrc::add_paging_id(uint32_t ueid, LIBLTE_S1AP_UEPAGINGID_STRUCT UEPagingID)
// Described in Section 7 of 36.304 // Described in Section 7 of 36.304
bool rrc::is_paging_opportunity(uint32_t tti, uint32_t *payload_len) bool rrc::is_paging_opportunity(uint32_t tti, uint32_t *payload_len)
{ {
int sf_pattern[4][3] = {{9, 4, 0}, {-1, 9, 4}, {-1, -1, 5}, {-1, -1, 9}}; int sf_pattern[4][4] = {{9, 4, -1, 0}, {-1, 9, -1, 4}, {-1, -1, -1, 5}, {-1, -1, -1, 9}};
if (pending_paging.empty()) { if (pending_paging.empty()) {
return false; return false;
@ -466,7 +467,7 @@ bool rrc::is_paging_opportunity(uint32_t tti, uint32_t *payload_len)
if ((sfn % T) == (T/N) * (ueid % N)) { if ((sfn % T) == (T/N) * (ueid % N)) {
int sf_idx = sf_pattern[i_s%4][(Ns-1)%3]; int sf_idx = sf_pattern[i_s%4][(Ns-1)%4];
if (sf_idx < 0) { if (sf_idx < 0) {
rrc_log->error("SF pattern is N/A for Ns=%d, i_s=%d, imsi_decimal=%d\n", Ns, i_s, ueid); rrc_log->error("SF pattern is N/A for Ns=%d, i_s=%d, imsi_decimal=%d\n", Ns, i_s, ueid);
} else if ((uint32_t) sf_idx == (tti%10)) { } else if ((uint32_t) sf_idx == (tti%10)) {
@ -1311,7 +1312,9 @@ void rrc::ue::send_connection_reconf(srslte::byte_buffer_t *pdu)
// Add SRB2 and DRB1 to the scheduler // Add SRB2 and DRB1 to the scheduler
srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg; srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg;
bearer_cfg.direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; bearer_cfg.direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH;
bearer_cfg.group = 0;
parent->mac->bearer_ue_cfg(rnti, 2, &bearer_cfg); parent->mac->bearer_ue_cfg(rnti, 2, &bearer_cfg);
bearer_cfg.group = conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[0].lc_cnfg.ul_specific_params.log_chan_group;
parent->mac->bearer_ue_cfg(rnti, 3, &bearer_cfg); parent->mac->bearer_ue_cfg(rnti, 3, &bearer_cfg);
// Configure SRB2 in RLC and PDCP // Configure SRB2 in RLC and PDCP

@ -173,7 +173,7 @@ void s1ap::build_tai_cgi()
void s1ap::initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu) void s1ap::initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu)
{ {
ue_ctxt_map[rnti].eNB_UE_S1AP_ID = next_eNB_UE_S1AP_ID++; ue_ctxt_map[rnti].eNB_UE_S1AP_ID = next_eNB_UE_S1AP_ID++;
ue_ctxt_map[rnti].stream_id = next_ue_stream_id++; ue_ctxt_map[rnti].stream_id = 1;
ue_ctxt_map[rnti].release_requested = false; ue_ctxt_map[rnti].release_requested = false;
enbid_to_rnti_map[ue_ctxt_map[rnti].eNB_UE_S1AP_ID] = rnti; enbid_to_rnti_map[ue_ctxt_map[rnti].eNB_UE_S1AP_ID] = rnti;
send_initialuemessage(rnti, pdu, false); send_initialuemessage(rnti, pdu, false);
@ -182,7 +182,7 @@ void s1ap::initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu)
void s1ap::initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu, uint32_t m_tmsi, uint8_t mmec) void s1ap::initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu, uint32_t m_tmsi, uint8_t mmec)
{ {
ue_ctxt_map[rnti].eNB_UE_S1AP_ID = next_eNB_UE_S1AP_ID++; ue_ctxt_map[rnti].eNB_UE_S1AP_ID = next_eNB_UE_S1AP_ID++;
ue_ctxt_map[rnti].stream_id = next_ue_stream_id++; ue_ctxt_map[rnti].stream_id = 1;
ue_ctxt_map[rnti].release_requested = false; ue_ctxt_map[rnti].release_requested = false;
enbid_to_rnti_map[ue_ctxt_map[rnti].eNB_UE_S1AP_ID] = rnti; enbid_to_rnti_map[ue_ctxt_map[rnti].eNB_UE_S1AP_ID] = rnti;
send_initialuemessage(rnti, pdu, true, m_tmsi, mmec); send_initialuemessage(rnti, pdu, true, m_tmsi, mmec);
@ -594,7 +594,7 @@ bool s1ap::handle_uectxtreleasecommand(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMMA
s1ap_log->warning("Not handling S1AP message extension\n"); s1ap_log->warning("Not handling S1AP message extension\n");
} }
uint16_t rnti; uint16_t rnti = 0;
if(msg->UE_S1AP_IDs.choice_type == LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_UE_S1AP_ID_PAIR) { if(msg->UE_S1AP_IDs.choice_type == LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_UE_S1AP_ID_PAIR) {
if(msg->UE_S1AP_IDs.choice.uE_S1AP_ID_pair.ext) { if(msg->UE_S1AP_IDs.choice.uE_S1AP_ID_pair.ext) {

@ -27,6 +27,7 @@
#include <unistd.h> #include <unistd.h>
#include <sstream> #include <sstream>
#include <srslte/asn1/liblte_rrc.h>
#include "upper/rrc.h" #include "upper/rrc.h"
#include "srslte/phy/utils/bit.h" #include "srslte/phy/utils/bit.h"
@ -78,7 +79,14 @@ void rrc::init(phy_interface_rrc *phy_,
nas = nas_; nas = nas_;
usim = usim_; usim = usim_;
rrc_log = rrc_log_; rrc_log = rrc_log_;
// Use MAC timers
mac_timers = mac_timers_; mac_timers = mac_timers_;
t301 = mac_timers->get_unique_id();
t310 = mac_timers->get_unique_id();
t311 = mac_timers->get_unique_id();
safe_reset_timer = mac_timers->get_unique_id();
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
@ -1084,8 +1092,11 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT
current_cfg->ul_pwr_ctrl_ded.accumulation_en = true; current_cfg->ul_pwr_ctrl_ded.accumulation_en = true;
current_cfg->ul_pwr_ctrl_ded.p0_ue_pucch = 0; current_cfg->ul_pwr_ctrl_ded.p0_ue_pucch = 0;
current_cfg->ul_pwr_ctrl_ded.p_srs_offset = 7; current_cfg->ul_pwr_ctrl_ded.p_srs_offset = 7;
current_cfg->ul_pwr_ctrl_ded.filter_coeff = LIBLTE_RRC_FILTER_COEFFICIENT_FC4; }
current_cfg->ul_pwr_ctrl_ded.filter_coeff_present = true; if (phy_cnfg->ul_pwr_ctrl_ded.filter_coeff_present) {
current_cfg->ul_pwr_ctrl_ded.filter_coeff = phy_cnfg->ul_pwr_ctrl_ded.filter_coeff;
} else {
current_cfg->ul_pwr_ctrl_ded.filter_coeff = LIBLTE_RRC_FILTER_COEFFICIENT_FC4;
} }
if(phy_cnfg->tpc_pdcch_cnfg_pucch_present) { if(phy_cnfg->tpc_pdcch_cnfg_pucch_present) {
memcpy(&current_cfg->tpc_pdcch_cnfg_pucch, &phy_cnfg->tpc_pdcch_cnfg_pucch, sizeof(LIBLTE_RRC_TPC_PDCCH_CONFIG_STRUCT)); memcpy(&current_cfg->tpc_pdcch_cnfg_pucch, &phy_cnfg->tpc_pdcch_cnfg_pucch, sizeof(LIBLTE_RRC_TPC_PDCCH_CONFIG_STRUCT));
@ -1488,10 +1499,6 @@ void rrc::set_mac_default()
void rrc::set_rrc_default() { void rrc::set_rrc_default() {
N310 = 1; N310 = 1;
N311 = 1; N311 = 1;
t301 = mac_timers->get_unique_id();
t310 = mac_timers->get_unique_id();
t311 = mac_timers->get_unique_id();
safe_reset_timer = mac_timers->get_unique_id();
mac_timers->get(t310)->set(this, 1000); mac_timers->get(t310)->set(this, 1000);
mac_timers->get(t311)->set(this, 1000); mac_timers->get(t311)->set(this, 1000);
mac_timers->get(safe_reset_timer)->set(this, 10); mac_timers->get(safe_reset_timer)->set(this, 10);

@ -23,10 +23,10 @@
[rf] [rf]
dl_freq = 2685000000 dl_freq = 2685000000
ul_freq = 2565000000 ul_freq = 2565000000
tx_gain = 70 tx_gain = 80
rx_gain = 50 rx_gain = 60
#nof_rx_ant = 1 nof_rx_ant = 2
#device_name = auto #device_name = auto
#device_args = auto #device_args = auto
#time_adv_nsamples = auto #time_adv_nsamples = auto

Loading…
Cancel
Save