mirror of https://github.com/PentHertz/srsLTE.git
Merge branch 'reporting' into enbmimo
This commit is contained in:
commit
d041431c13
|
@ -326,7 +326,8 @@ srslte_netsink_t net_sink, net_sink_signal;
|
|||
#define PRINT_LINE_ADVANCE_CURSOR() printf("\033[%dB", prev_nof_lines + 1)
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int ret;
|
||||
struct timeval t[3];
|
||||
int ret;
|
||||
int decimate = 1;
|
||||
srslte_cell_t cell;
|
||||
int64_t sf_cnt;
|
||||
|
@ -559,7 +560,7 @@ int main(int argc, char **argv) {
|
|||
// Variables for measurements
|
||||
uint32_t nframes=0;
|
||||
uint8_t ri = 0, pmi = 0;
|
||||
float rsrp0=0.0, rsrp1=0.0, rsrq=0.0, noise=0.0, enodebrate = 0.0, uerate = 0.0,
|
||||
float rsrp0=0.0, rsrp1=0.0, rsrq=0.0, noise=0.0, enodebrate = 0.0, uerate = 0.0, procrate = 0.0,
|
||||
sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS], cn = 0.0;
|
||||
bool decode_pdsch = false;
|
||||
|
||||
|
@ -655,6 +656,7 @@ int main(int argc, char **argv) {
|
|||
decode_pdsch = false;
|
||||
}
|
||||
}
|
||||
gettimeofday(&t[1], NULL);
|
||||
if (decode_pdsch) {
|
||||
if(sfidx != 1 || prog_args.mbsfn_area_id < 0){ // Not an MBSFN subframe
|
||||
if (cell.nof_ports == 1) {
|
||||
|
@ -690,6 +692,8 @@ int main(int argc, char **argv) {
|
|||
INFO("mbsfn PDU size is %d\n", n);
|
||||
}
|
||||
}
|
||||
gettimeofday(&t[2], NULL);
|
||||
get_time_interval(t);
|
||||
if (n < 0) {
|
||||
// fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
|
||||
} else if (n > 0) {
|
||||
|
@ -723,16 +727,19 @@ int main(int argc, char **argv) {
|
|||
|
||||
}
|
||||
|
||||
nof_trials++;
|
||||
|
||||
|
||||
nof_trials++;
|
||||
|
||||
uint32_t nof_bits = ((acks[0]?ue_dl.pdsch_cfg.grant.mcs[0].tbs:0) + (acks[1]?ue_dl.pdsch_cfg.grant.mcs[1].tbs:0));
|
||||
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.1f);
|
||||
rsrp0 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 0), rsrp0, 0.05f);
|
||||
rsrp1 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 1), rsrp1, 0.05f);
|
||||
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05f);
|
||||
enodebrate = SRSLTE_VEC_EMA((ue_dl.pdsch_cfg.grant.mcs[0].tbs + ue_dl.pdsch_cfg.grant.mcs[1].tbs)/1000.0f, enodebrate, 0.05f);
|
||||
uerate = SRSLTE_VEC_EMA(((acks[0]?ue_dl.pdsch_cfg.grant.mcs[0].tbs:0) + (acks[1]?ue_dl.pdsch_cfg.grant.mcs[1].tbs:0))/1000.0f, uerate, 0.01f);
|
||||
|
||||
enodebrate = SRSLTE_VEC_EMA(nof_bits/1000.0f, enodebrate, 0.05f);
|
||||
uerate = SRSLTE_VEC_EMA(nof_bits/1000.0f, uerate, 0.001f);
|
||||
float elapsed = (float) t[0].tv_usec + t[0].tv_sec*1.0e+6f;
|
||||
if (elapsed != 0.0f) {
|
||||
procrate = SRSLTE_VEC_EMA(nof_bits/elapsed, procrate, 0.01f);
|
||||
}
|
||||
|
||||
nframes++;
|
||||
if (isnan(rsrq)) {
|
||||
|
@ -769,7 +776,7 @@ int main(int argc, char **argv) {
|
|||
PRINT_LINE("nof codewords: %d", SRSLTE_RA_DL_GRANT_NOF_TB(&ue_dl.pdsch_cfg.grant));
|
||||
PRINT_LINE(" CFO: %+5.2f kHz", srslte_ue_sync_get_cfo(&ue_sync) / 1000);
|
||||
PRINT_LINE(" SNR: %+5.1f dB | %+5.1f dB", 10 * log10(rsrp0 / noise), 10 * log10(rsrp1 / noise));
|
||||
PRINT_LINE(" Rb: %6.2f / %6.2f Mbps (net/maximum)", uerate, enodebrate);
|
||||
PRINT_LINE(" Rb: %6.2f / %6.2f / %6.2f Mbps (net/maximum/processing)", uerate, enodebrate, procrate);
|
||||
PRINT_LINE(" PDCCH-Miss: %5.2f%%", 100 * (1 - (float) ue_dl.nof_detected / nof_trials));
|
||||
PRINT_LINE(" PDSCH-BLER: %5.2f%%", (float) 100 * ue_dl.pdsch_pkt_errors / ue_dl.pdsch_pkts_total);
|
||||
if(prog_args.mbsfn_area_id > -1){
|
||||
|
|
|
@ -123,8 +123,6 @@ public:
|
|||
used.erase(elem);
|
||||
available.push(b);
|
||||
ret = true;
|
||||
} else {
|
||||
printf("Error deallocating from buffer pool: buffer not created in this pool.\n");
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return ret;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
#define HARQ_DELAY_MS 4
|
||||
#define MSG3_DELAY_MS 2 // Delay added to HARQ_DELAY_MS
|
||||
#define TTI_RX(tti) (tti>HARQ_DELAY_MS?((tti-HARQ_DELAY_MS)%10240):(10240+tti-HARQ_DELAY_MS))
|
||||
#define TTI_TX(tti) ((tti+HARQ_DELAY_MS)%10240)
|
||||
#define TTI_RX_ACK(tti) ((tti+(2*HARQ_DELAY_MS))%10240)
|
||||
|
||||
|
|
|
@ -55,13 +55,22 @@ typedef struct {
|
|||
} srslte_cqi_periodic_cfg_t;
|
||||
|
||||
/* Table 5.2.2.6.2-1: Fields for channel quality information feedback for higher layer configured subband
|
||||
CQI reports
|
||||
(transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and
|
||||
transmission mode 8 configured without PMI/RI reporting). */
|
||||
CQI reports (transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and
|
||||
transmission mode 8 configured without PMI/RI reporting). */
|
||||
|
||||
/* Table 5.2.2.6.2-2: Fields for channel quality information (CQI) feedback for higher layer configured subband CQI
|
||||
reports (transmission mode 4, transmission mode 5 and transmission mode 6). */
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
uint8_t wideband_cqi; // 4-bit width
|
||||
uint32_t subband_diff_cqi; // 2N-bit width
|
||||
uint32_t N;
|
||||
uint8_t wideband_cqi_cw0; // 4-bit width
|
||||
uint32_t subband_diff_cqi_cw0; // 2N-bit width
|
||||
uint8_t wideband_cqi_cw1; // if RI > 1 then 4-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 N;
|
||||
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_hl_subband_t;
|
||||
|
||||
/* Table 5.2.2.6.3-1: Fields for channel quality information feedback for UE selected subband CQI
|
||||
|
|
|
@ -44,11 +44,38 @@
|
|||
*******************************************************/
|
||||
int srslte_cqi_hl_subband_pack(srslte_cqi_hl_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS])
|
||||
{
|
||||
uint8_t *body_ptr = buff;
|
||||
srslte_bit_unpack(msg->wideband_cqi, &body_ptr, 4);
|
||||
srslte_bit_unpack(msg->subband_diff_cqi, &body_ptr, 2*msg->N);
|
||||
|
||||
return 4+2*msg->N;
|
||||
uint8_t *body_ptr = buff;
|
||||
uint32_t bit_count = 0;
|
||||
|
||||
/* Unpack codeword 0, common for 3GPP 36.212 Tables 5.2.2.6.2-1 and 5.2.2.6.2-2 */
|
||||
srslte_bit_unpack(msg->wideband_cqi_cw0, &body_ptr, 4);
|
||||
srslte_bit_unpack(msg->subband_diff_cqi_cw0, &body_ptr, 2*msg->N);
|
||||
bit_count += 4+2*msg->N;
|
||||
|
||||
/* Unpack codeword 1, 3GPP 36.212 Table 5.2.2.6.2-2 */
|
||||
if (msg->rank_is_not_one) {
|
||||
srslte_bit_unpack(msg->wideband_cqi_cw1, &body_ptr, 4);
|
||||
srslte_bit_unpack(msg->subband_diff_cqi_cw1, &body_ptr, 2*msg->N);
|
||||
bit_count += 4+2*msg->N;
|
||||
}
|
||||
|
||||
/* If PMI is present, unpack it */
|
||||
if (msg->pmi_present) {
|
||||
if (msg->four_antenna_ports) {
|
||||
srslte_bit_unpack(msg->pmi, &body_ptr, 4);
|
||||
bit_count += 4;
|
||||
} else {
|
||||
if (msg->rank_is_not_one) {
|
||||
srslte_bit_unpack(msg->pmi, &body_ptr, 1);
|
||||
bit_count += 1;
|
||||
} else {
|
||||
srslte_bit_unpack(msg->pmi, &body_ptr, 2);
|
||||
bit_count += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bit_count;
|
||||
}
|
||||
|
||||
int srslte_cqi_ue_subband_pack(srslte_cqi_ue_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS])
|
||||
|
@ -98,11 +125,37 @@ int srslte_cqi_value_pack(srslte_cqi_value_t *value, uint8_t buff[SRSLTE_CQI_MAX
|
|||
|
||||
int srslte_cqi_hl_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_hl_subband_t *msg)
|
||||
{
|
||||
uint8_t *body_ptr = buff;
|
||||
msg->wideband_cqi = srslte_bit_pack(&body_ptr, 4);
|
||||
msg->subband_diff_cqi = srslte_bit_pack(&body_ptr, 2*msg->N);
|
||||
|
||||
return 4+2*msg->N;
|
||||
uint8_t *body_ptr = buff;
|
||||
uint32_t bit_count = 0;
|
||||
|
||||
msg->wideband_cqi_cw0 = (uint8_t) srslte_bit_pack(&body_ptr, 4);
|
||||
msg->subband_diff_cqi_cw0 = srslte_bit_pack(&body_ptr, 2*msg->N);
|
||||
bit_count += 4+2*msg->N;
|
||||
|
||||
/* Unpack codeword 1, 3GPP 36.212 Table 5.2.2.6.2-2 */
|
||||
if (msg->rank_is_not_one) {
|
||||
msg->wideband_cqi_cw1 = (uint8_t) srslte_bit_pack(&body_ptr, 4);
|
||||
msg->subband_diff_cqi_cw1 = srslte_bit_pack(&body_ptr, 2*msg->N);
|
||||
bit_count += 4+2*msg->N;
|
||||
}
|
||||
|
||||
/* If PMI is present, unpack it */
|
||||
if (msg->pmi_present) {
|
||||
if (msg->four_antenna_ports) {
|
||||
msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 4);
|
||||
bit_count += 4;
|
||||
} else {
|
||||
if (msg->rank_is_not_one) {
|
||||
msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 1);
|
||||
bit_count += 1;
|
||||
} else {
|
||||
msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 2);
|
||||
bit_count += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bit_count;
|
||||
}
|
||||
|
||||
int srslte_cqi_ue_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_ue_subband_t *msg)
|
||||
|
|
|
@ -291,6 +291,13 @@ int rf_uhd_open(char *args, void **h)
|
|||
return rf_uhd_open_multi(args, h, 1);
|
||||
}
|
||||
|
||||
#define REMOVE_SUBSTRING_WITHCOMAS(S, TOREMOVE) \
|
||||
remove_substring(S, TOREMOVE ",");\
|
||||
remove_substring(S, TOREMOVE ", ");\
|
||||
remove_substring(S, "," TOREMOVE);\
|
||||
remove_substring(S, ", " TOREMOVE);\
|
||||
remove_substring(S, TOREMOVE)
|
||||
|
||||
static void remove_substring(char *s,const char *toremove)
|
||||
{
|
||||
while((s=strstr(s,toremove))) {
|
||||
|
@ -298,6 +305,17 @@ static void remove_substring(char *s,const char *toremove)
|
|||
}
|
||||
}
|
||||
|
||||
static void copy_subdev_string(char *dst, char *src) {
|
||||
int n = 0;
|
||||
size_t len = strlen(src);
|
||||
/* Copy until end of string or comma */
|
||||
while (n < len && src != '\0' && src[n] != ',') {
|
||||
dst[n] = src[n];
|
||||
n++;
|
||||
}
|
||||
dst[n] = '\0';
|
||||
}
|
||||
|
||||
int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
|
||||
{
|
||||
if (h) {
|
||||
|
@ -336,11 +354,11 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
|
|||
// Check external clock argument
|
||||
enum {DEFAULT, EXTERNAL, GPSDO} clock_src;
|
||||
if (strstr(args, "clock=external")) {
|
||||
remove_substring(args, "clock=external");
|
||||
REMOVE_SUBSTRING_WITHCOMAS(args, "clock=external");
|
||||
clock_src = EXTERNAL;
|
||||
} else if (strstr(args, "clock=gpsdo")) {
|
||||
printf("Using GPSDO clock\n");
|
||||
remove_substring(args, "clock=gpsdo");
|
||||
REMOVE_SUBSTRING_WITHCOMAS(args, "clock=gpsdo");
|
||||
clock_src = GPSDO;
|
||||
} else {
|
||||
clock_src = DEFAULT;
|
||||
|
@ -349,14 +367,36 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
|
|||
// Set over the wire format
|
||||
char *otw_format = "sc16";
|
||||
if (strstr(args, "otw_format=sc12")) {
|
||||
REMOVE_SUBSTRING_WITHCOMAS(args, "otw_format=sc12");
|
||||
otw_format = "sc12";
|
||||
} else if (strstr(args, "otw_format=sc16")) {
|
||||
REMOVE_SUBSTRING_WITHCOMAS(args, "otw_format=sc16");
|
||||
/* Do nothing */
|
||||
} else if (strstr(args, "otw_format=")) {
|
||||
fprintf(stderr, "Wrong over the wire format. Valid formats: sc12, sc16\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set transmitter subdevice spec string
|
||||
const char tx_subdev_arg[] = "tx_subdev_spec=";
|
||||
char tx_subdev_str[64] = {0};
|
||||
char *tx_subdev_ptr = strstr(args, tx_subdev_arg);
|
||||
if (tx_subdev_ptr) {
|
||||
copy_subdev_string(tx_subdev_str, tx_subdev_ptr + strlen(tx_subdev_arg));
|
||||
remove_substring(args, tx_subdev_arg);
|
||||
remove_substring(args, tx_subdev_str);
|
||||
}
|
||||
|
||||
// Set receiver subdevice spec string
|
||||
const char rx_subdev_arg[] = "rx_subdev_spec=";
|
||||
char rx_subdev_str[64] = {0};
|
||||
char *rx_subdev_ptr = strstr(args, rx_subdev_arg);
|
||||
if (rx_subdev_ptr) {
|
||||
copy_subdev_string(rx_subdev_str, rx_subdev_ptr + strlen(rx_subdev_arg));
|
||||
remove_substring(args, rx_subdev_arg);
|
||||
remove_substring(args, rx_subdev_str);
|
||||
}
|
||||
|
||||
/* If device type or name not given in args, choose a B200 */
|
||||
if (args[0]=='\0') {
|
||||
if (find_string(devices_str, "type=b200") && !strstr(args, "recv_frame_size")) {
|
||||
|
@ -396,7 +436,29 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
|
|||
fprintf(stderr, "Error opening UHD: code %d\n", error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Set transmitter subdev spec if specified */
|
||||
if (strlen(tx_subdev_str)) {
|
||||
uhd_subdev_spec_handle subdev_spec_handle = {0};
|
||||
|
||||
printf("Setting tx_subdev_spec to '%s'\n", tx_subdev_str);
|
||||
|
||||
uhd_subdev_spec_make(&subdev_spec_handle, tx_subdev_str);
|
||||
uhd_usrp_set_tx_subdev_spec(handler->usrp, subdev_spec_handle, 0);
|
||||
uhd_subdev_spec_free(&subdev_spec_handle);
|
||||
}
|
||||
|
||||
/* Set receiver subdev spec if specified */
|
||||
if (strlen(rx_subdev_str)) {
|
||||
uhd_subdev_spec_handle subdev_spec_handle = {0};
|
||||
|
||||
printf("Setting rx_subdev_spec to '%s'\n", rx_subdev_str);
|
||||
|
||||
uhd_subdev_spec_make(&subdev_spec_handle, rx_subdev_str);
|
||||
uhd_usrp_set_rx_subdev_spec(handler->usrp, subdev_spec_handle, 0);
|
||||
uhd_subdev_spec_free(&subdev_spec_handle);
|
||||
}
|
||||
|
||||
if (!handler->devname) {
|
||||
char dev_str[1024];
|
||||
uhd_usrp_get_mboard_name(handler->usrp, 0, dev_str, 1024);
|
||||
|
|
|
@ -201,8 +201,14 @@ uint32_t rlc_am::get_total_buffer_state()
|
|||
rlc_amd_retx_t retx = retx_queue.front();
|
||||
log->debug("Buffer state - retx - SN: %d, Segment: %s, %d:%d\n", retx.sn, retx.is_segment ? "true" : "false", retx.so_start, retx.so_end);
|
||||
if(tx_window.end() != tx_window.find(retx.sn)) {
|
||||
n_bytes += required_buffer_size(retx);
|
||||
int req_bytes = required_buffer_size(retx);
|
||||
if (req_bytes < 0) {
|
||||
log->error("In get_total_buffer_state(): Removing retx.sn=%d from queue\n", retx.sn);
|
||||
retx_queue.pop_front();
|
||||
} else {
|
||||
n_bytes += req_bytes;
|
||||
log->debug("Buffer state - retx: %d bytes\n", n_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,7 +256,13 @@ uint32_t rlc_am::get_buffer_state()
|
|||
rlc_amd_retx_t retx = retx_queue.front();
|
||||
log->debug("Buffer state - retx - SN: %d, Segment: %s, %d:%d\n", retx.sn, retx.is_segment ? "true" : "false", retx.so_start, retx.so_end);
|
||||
if(tx_window.end() != tx_window.find(retx.sn)) {
|
||||
n_bytes = required_buffer_size(retx);
|
||||
int req_bytes = required_buffer_size(retx);
|
||||
if (req_bytes < 0) {
|
||||
log->error("In get_buffer_state(): Removing retx.sn=%d from queue\n", retx.sn);
|
||||
retx_queue.pop_front();
|
||||
goto unlock_and_return;
|
||||
}
|
||||
n_bytes = (uint32_t) req_bytes;
|
||||
log->debug("Buffer state - retx: %d bytes\n", n_bytes);
|
||||
goto unlock_and_return;
|
||||
}
|
||||
|
@ -296,8 +308,9 @@ int rlc_am::read_pdu(uint8_t *payload, uint32_t nof_bytes)
|
|||
}
|
||||
// RETX if required
|
||||
if(retx_queue.size() > 0) {
|
||||
int ret = build_retx_pdu(payload, nof_bytes);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return build_retx_pdu(payload, nof_bytes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Build a PDU from SDUs
|
||||
|
@ -438,16 +451,33 @@ int rlc_am::build_status_pdu(uint8_t *payload, uint32_t nof_bytes)
|
|||
|
||||
int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
|
||||
{
|
||||
// Check there is at least 1 element before calling front()
|
||||
if (retx_queue.empty()) {
|
||||
log->error("In build_retx_pdu(): retx_queue is empty\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rlc_amd_retx_t retx = retx_queue.front();
|
||||
|
||||
// Sanity check - drop any retx SNs not present in tx_window
|
||||
while(tx_window.end() == tx_window.find(retx.sn)) {
|
||||
retx_queue.pop_front();
|
||||
retx = retx_queue.front();
|
||||
if (!retx_queue.empty()) {
|
||||
retx = retx_queue.front();
|
||||
} else {
|
||||
log->error("In build_retx_pdu(): retx_queue is empty during sanity check\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Is resegmentation needed?
|
||||
if(retx.is_segment || required_buffer_size(retx) > (int)nof_bytes) {
|
||||
int req_size = required_buffer_size(retx);
|
||||
if (req_size < 0) {
|
||||
log->error("In build_retx_pdu(): Removing retx.sn=%d from queue\n", retx.sn);
|
||||
retx_queue.pop_front();
|
||||
return -1;
|
||||
}
|
||||
if(retx.is_segment || req_size > (int)nof_bytes) {
|
||||
log->debug("%s build_retx_pdu - resegmentation required\n", rrc->get_rb_name(lcid).c_str());
|
||||
return build_segment(payload, nof_bytes, retx);
|
||||
}
|
||||
|
@ -481,6 +511,10 @@ int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
|
|||
|
||||
int rlc_am::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t retx)
|
||||
{
|
||||
if (!tx_window[retx.sn].buf) {
|
||||
log->error("In build_segment: retx.sn=%d has null buffer\n", retx.sn);
|
||||
return 0;
|
||||
}
|
||||
if(!retx.is_segment){
|
||||
retx.so_start = 0;
|
||||
retx.so_end = tx_window[retx.sn].buf->N_bytes;
|
||||
|
@ -1147,7 +1181,17 @@ bool rlc_am::add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rlc_amd_rx_pd
|
|||
int rlc_am::required_buffer_size(rlc_amd_retx_t retx)
|
||||
{
|
||||
if(!retx.is_segment){
|
||||
return rlc_am_packed_length(&tx_window[retx.sn].header) + tx_window[retx.sn].buf->N_bytes;
|
||||
if (tx_window.count(retx.sn)) {
|
||||
if (tx_window[retx.sn].buf) {
|
||||
return rlc_am_packed_length(&tx_window[retx.sn].header) + tx_window[retx.sn].buf->N_bytes;
|
||||
} else {
|
||||
log->warning("retx.sn=%d has null ptr in required_buffer_size()\n", retx.sn);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
log->warning("retx.sn=%d does not exist in required_buffer_size()\n", retx.sn);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Construct new header
|
||||
|
|
|
@ -498,7 +498,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
|
|||
if (ue_db[rnti].cqi_en) {
|
||||
wideband_cqi_value = cqi_value.wideband.wideband_cqi;
|
||||
} else if (grants[i].grant.cqi_request) {
|
||||
wideband_cqi_value = cqi_value.subband_hl.wideband_cqi;
|
||||
wideband_cqi_value = cqi_value.subband_hl.wideband_cqi_cw0;
|
||||
}
|
||||
snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value);
|
||||
}
|
||||
|
|
|
@ -219,7 +219,7 @@ private:
|
|||
|
||||
// Receive and route HARQ feedbacks
|
||||
if (grant) {
|
||||
if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi()) ||
|
||||
if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi() && grant->phy_grant.ul.mcs.idx < 29) ||
|
||||
(grant->rnti_type == SRSLTE_RNTI_USER && !has_grant()) ||
|
||||
grant->is_from_rar)
|
||||
{
|
||||
|
@ -245,7 +245,7 @@ private:
|
|||
Warning("Uplink grant but no MAC PDU in Multiplex Unit buffer\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (has_grant()) {
|
||||
// Adaptive Re-TX
|
||||
if (current_tx_nb >= max_retx) {
|
||||
Info("UL %d: Maximum number of ReTX reached (%d). Discarting TB.\n", pid, max_retx);
|
||||
|
@ -254,6 +254,8 @@ private:
|
|||
} else {
|
||||
generate_retx(tti_tx, grant, action);
|
||||
}
|
||||
} else {
|
||||
Warning("UL %d: Received mcs=%d but no previous grant available for this PID.\n", pid, grant->phy_grant.ul.mcs.idx);
|
||||
}
|
||||
} else if (has_grant()) {
|
||||
// Non-Adaptive Re-Tx
|
||||
|
|
|
@ -127,6 +127,8 @@ private:
|
|||
|
||||
// RRC constants and timers
|
||||
srslte::mac_interface_timers *mac_timers;
|
||||
uint32_t sync_reset_cnt;
|
||||
const static uint32_t SYNC_RESET_TIMEOUT = 10;
|
||||
uint32_t n310_cnt, N310;
|
||||
uint32_t n311_cnt, N311;
|
||||
uint32_t t301, t310, t311;
|
||||
|
|
|
@ -286,7 +286,7 @@ bool mux::sched_sdu(lchid_t *ch, int *sdu_space, int max_sdu_sz)
|
|||
}
|
||||
|
||||
log_h->info("SDU: scheduled lcid=%d, rlc_buffer=%d, allocated=%d/%d\n",
|
||||
ch->id, ch->buffer_len, sched_len, *sdu_space);
|
||||
ch->id, ch->buffer_len, sched_len, sdu_space?*sdu_space:0);
|
||||
|
||||
*sdu_space -= sched_len;
|
||||
ch->buffer_len -= sched_len;
|
||||
|
@ -309,12 +309,11 @@ bool mux::allocate_sdu(uint32_t lcid, srslte::sch_pdu* pdu_msg, int max_sdu_sz)
|
|||
sdu_len = max_sdu_sz;
|
||||
}
|
||||
int sdu_space = pdu_msg->get_sdu_space();
|
||||
if (sdu_len > sdu_space) {
|
||||
if (sdu_len > sdu_space || max_sdu_sz < 0) {
|
||||
sdu_len = sdu_space;
|
||||
}
|
||||
}
|
||||
if (sdu_len > MIN_RLC_SDU_LEN) {
|
||||
if (pdu_msg->new_subh()) { // there is space for a new subheader
|
||||
int sdu_len2 = sdu_len;
|
||||
sdu_len = pdu_msg->get()->set_sdu(lcid, sdu_len, rlc);
|
||||
if (sdu_len > 0) { // new SDU could be added
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "phy/phch_worker.h"
|
||||
#include "srslte/srslte.h"
|
||||
#include "srslte/interfaces/ue_interfaces.h"
|
||||
#include "srslte/asn1/liblte_rrc.h"
|
||||
|
||||
|
@ -40,8 +41,6 @@
|
|||
#ifdef ENABLE_GUI
|
||||
#include "srsgui/srsgui.h"
|
||||
#include <semaphore.h>
|
||||
#include "srslte/srslte.h"
|
||||
#include "srslte/interfaces/ue_interfaces.h"
|
||||
|
||||
void init_plots(srsue::phch_worker *worker);
|
||||
pthread_t plot_thread;
|
||||
|
@ -290,9 +289,9 @@ void phch_worker::work_imp()
|
|||
ul_action.tti_offset = HARQ_DELAY_MS;
|
||||
|
||||
/* Send UL grant or HARQ information (from PHICH) to MAC */
|
||||
if (ul_grant_available && ul_ack_available) {
|
||||
if (ul_grant_available && ul_ack_available && ul_mac_grant.phy_grant.ul.mcs.idx < 29) {
|
||||
phy->mac->new_grant_ul_ack(ul_mac_grant, ul_ack, &ul_action);
|
||||
} else if (ul_grant_available && !ul_ack_available) {
|
||||
} else if (ul_grant_available && (!ul_ack_available || ul_mac_grant.phy_grant.ul.mcs.idx < 29)) {
|
||||
phy->mac->new_grant_ul(ul_mac_grant, &ul_action);
|
||||
} else if (!ul_grant_available && ul_ack_available) {
|
||||
phy->mac->harq_recv(tti, ul_ack, &ul_action);
|
||||
|
@ -485,11 +484,15 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
|
|||
|
||||
grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS));
|
||||
|
||||
// Set last TBS for this TB (pid) in case of mcs>29 (7.1.7.2 of 36.213)
|
||||
// Set last TBS for this TB (pid) in case of mcs>28 (7.1.7.2 of 36.213)
|
||||
for (int i=0;i<SRSLTE_MAX_CODEWORDS;i++) {
|
||||
if (grant->phy_grant.dl.mcs[i].tbs < 0) {
|
||||
if (grant->phy_grant.dl.mcs[i].idx > 28) {
|
||||
grant->phy_grant.dl.mcs[i].tbs = last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i];
|
||||
}
|
||||
if(grant->phy_grant.dl.mcs[i].tbs < 0) {
|
||||
Info("Invalid TBS size for PDSCH grant\n");
|
||||
grant->phy_grant.dl.mcs[i].tbs = 0;
|
||||
}
|
||||
// save it
|
||||
last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i] = grant->phy_grant.dl.mcs[i].tbs;
|
||||
}
|
||||
|
@ -544,10 +547,15 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant);
|
||||
switch(phy->config->dedicated.antenna_info_explicit_value.tx_mode) {
|
||||
/* Implemented Tx Modes */
|
||||
case LIBLTE_RRC_TRANSMISSION_MODE_1:
|
||||
mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
|
||||
if (nof_tb != 1) {
|
||||
Error("Wrong number of transport blocks (%d) for single antenna.", nof_tb);
|
||||
valid_config = false;
|
||||
}
|
||||
break;
|
||||
case LIBLTE_RRC_TRANSMISSION_MODE_2:
|
||||
if (cell.nof_ports > 1) {
|
||||
|
@ -555,26 +563,30 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
|
|||
} else {
|
||||
mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
|
||||
}
|
||||
if (nof_tb != 1) {
|
||||
Error("Wrong number of transport blocks (%d) for transmit diversity.", nof_tb);
|
||||
valid_config = false;
|
||||
}
|
||||
break;
|
||||
case LIBLTE_RRC_TRANSMISSION_MODE_3:
|
||||
if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 1) {
|
||||
if (nof_tb == 1) {
|
||||
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
||||
} else if (ue_dl.nof_rx_antennas > 1 && SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 2) {
|
||||
} else if (ue_dl.nof_rx_antennas > 1 && nof_tb == 2) {
|
||||
mimo_type = SRSLTE_MIMO_TYPE_CDD;
|
||||
} else {
|
||||
Error("Wrong combination of antennas (%d) or transport blocks (%d) for TM3\n", ue_dl.nof_rx_antennas,
|
||||
SRSLTE_RA_DL_GRANT_NOF_TB(grant));
|
||||
nof_tb);
|
||||
valid_config = false;
|
||||
}
|
||||
break;
|
||||
case LIBLTE_RRC_TRANSMISSION_MODE_4:
|
||||
if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 1) {
|
||||
if (nof_tb == 1) {
|
||||
mimo_type = (grant->pinfo == 0) ? SRSLTE_MIMO_TYPE_TX_DIVERSITY : SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
||||
} else if (ue_dl.nof_rx_antennas > 1 && SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 2) {
|
||||
} else if (ue_dl.nof_rx_antennas > 1 && nof_tb == 2) {
|
||||
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
||||
} else {
|
||||
Error("Wrong combination of antennas (%d) or transport blocks (%d) for TM3\n", ue_dl.nof_rx_antennas,
|
||||
SRSLTE_RA_DL_GRANT_NOF_TB(grant));
|
||||
nof_tb);
|
||||
valid_config = false;
|
||||
}
|
||||
break;
|
||||
|
@ -745,16 +757,17 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
|
|||
if (ret) {
|
||||
|
||||
// Use last TBS for this TB in case of mcs>28
|
||||
if (grant->phy_grant.ul.mcs.tbs < 0) {
|
||||
grant->phy_grant.ul.mcs.tbs = last_ul_tbs[tti%(2*HARQ_DELAY_MS)];
|
||||
if (grant->phy_grant.ul.mcs.idx > 28) {
|
||||
grant->phy_grant.ul.mcs.tbs = last_ul_tbs[TTI_RX(tti)%(2*HARQ_DELAY_MS)];
|
||||
Info("RETX: mcs=%d, old_tbs=%d pid=%d\n", grant->phy_grant.ul.mcs.idx, grant->phy_grant.ul.mcs.tbs, TTI_TX(tti)%(2*HARQ_DELAY_MS));
|
||||
}
|
||||
last_ul_tbs[tti%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.tbs;
|
||||
last_ul_tbs[TTI_RX(tti)%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.tbs;
|
||||
|
||||
if (grant->phy_grant.ul.mcs.mod == SRSLTE_MOD_LAST) {
|
||||
grant->phy_grant.ul.mcs.mod = last_ul_mod[tti%(2*HARQ_DELAY_MS)];
|
||||
grant->phy_grant.ul.mcs.mod = last_ul_mod[TTI_RX(tti)%(2*HARQ_DELAY_MS)];
|
||||
grant->phy_grant.ul.Qm = srslte_mod_bits_x_symbol(grant->phy_grant.ul.mcs.mod);
|
||||
}
|
||||
last_ul_mod[tti%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.mod;
|
||||
last_ul_mod[TTI_RX(tti)%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.mod;
|
||||
}
|
||||
|
||||
/* Limit UL modulation if not supported by the UE or disabled by higher layers */
|
||||
|
@ -883,18 +896,71 @@ void phch_worker::set_uci_aperiodic_cqi()
|
|||
reported RI. For other transmission modes they are reported conditioned on rank 1.
|
||||
*/
|
||||
if (rnti_is_set) {
|
||||
srslte_cqi_value_t cqi_report;
|
||||
srslte_cqi_value_t cqi_report = {0};
|
||||
cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND_HL;
|
||||
cqi_report.subband_hl.wideband_cqi = srslte_cqi_from_snr(phy->avg_snr_db);
|
||||
cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(phy->avg_snr_db);
|
||||
|
||||
// TODO: implement subband CQI properly
|
||||
cqi_report.subband_hl.subband_diff_cqi = 0; // Always report zero offset on all subbands
|
||||
cqi_report.subband_hl.subband_diff_cqi_cw0 = 0; // Always report zero offset on all subbands
|
||||
cqi_report.subband_hl.N = (cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(cell.nof_prb) : 0;
|
||||
|
||||
Info("PUSCH: Aperiodic CQI=%d, SNR=%.1f dB, for %d subbands\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db, cqi_report.subband_hl.N);
|
||||
uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi);
|
||||
}
|
||||
break;
|
||||
case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31:
|
||||
/* only Higher Layer-configured subband feedback support right now, according to TS36.213 section 7.2.1
|
||||
- A single precoding matrix is selected from the codebook subset assuming transmission on set S subbands
|
||||
- A UE shall report one subband CQI value per codeword for each set S subband which are calculated assuming
|
||||
the use of the single precoding matrix in all subbands and assuming transmission in the corresponding
|
||||
subband.
|
||||
- A UE shall report a wideband CQI value per codeword which is calculated assuming the use of the single
|
||||
precoding matrix in all subbands and transmission on set S subbands
|
||||
- The UE shall report the single selected precoding matrix indicator.
|
||||
- For transmission mode 4 the reported PMI and CQI values are calculated conditioned on the reported RI. For
|
||||
other transmission modes they are reported conditioned on rank 1.
|
||||
*/
|
||||
if (rnti_is_set) {
|
||||
/* Compute RI, PMI and SINR */
|
||||
compute_ri();
|
||||
|
||||
/* Select RI, PMI and SINR */
|
||||
uint32_t ri = ue_dl.ri; // Select RI (0: 1 layer, 1: 2 layer, otherwise: not implemented)
|
||||
uint32_t pmi = ue_dl.pmi[ri]; // Select PMI
|
||||
float sinr_db = 10 * log10(ue_dl.sinr[ri][pmi]);
|
||||
|
||||
/* Fill CQI Report */
|
||||
srslte_cqi_value_t cqi_report = {0};
|
||||
cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND_HL;
|
||||
|
||||
cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(sinr_db);
|
||||
cqi_report.subband_hl.subband_diff_cqi_cw0 = 0; // Always report zero offset on all subbands
|
||||
|
||||
if (ri > 0) {
|
||||
cqi_report.subband_hl.rank_is_not_one = true;
|
||||
cqi_report.subband_hl.wideband_cqi_cw1 = srslte_cqi_from_snr(sinr_db);
|
||||
cqi_report.subband_hl.subband_diff_cqi_cw1 = 0; // Always report zero offset on all subbands
|
||||
}
|
||||
|
||||
cqi_report.subband_hl.pmi = pmi;
|
||||
cqi_report.subband_hl.pmi_present = true;
|
||||
cqi_report.subband_hl.four_antenna_ports = (cell.nof_ports == 4);
|
||||
|
||||
// TODO: implement subband CQI properly
|
||||
cqi_report.subband_hl.N = (uint32_t) ((cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(cell.nof_prb) : 0);
|
||||
|
||||
if (cqi_report.subband_hl.rank_is_not_one) {
|
||||
Info("PUSCH: Aperiodic ri~1, CQI=%02d/%02d, SINR=%2.1f/%2.1fdB, pmi=%d for %d subbands\n",
|
||||
cqi_report.subband_hl.wideband_cqi_cw0, cqi_report.subband_hl.wideband_cqi_cw1,
|
||||
sinr_db, sinr_db, pmi, cqi_report.subband_hl.N);
|
||||
} else {
|
||||
Info("PUSCH: Aperiodic ri=1, CQI=%d/%d, SINR=%2.1f dB, for %d subbands\n",
|
||||
cqi_report.wideband.wideband_cqi,
|
||||
phy->avg_snr_db, cqi_report.subband_hl.N);
|
||||
}
|
||||
uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Warning("Received CQI request but mode %s is not supported\n",
|
||||
liblte_rrc_cqi_report_mode_aperiodic_text[phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic]);
|
||||
|
|
|
@ -199,9 +199,10 @@ void phy::set_timeadv_rar(uint32_t ta_cmd) {
|
|||
}
|
||||
|
||||
void phy::set_timeadv(uint32_t ta_cmd) {
|
||||
n_ta = srslte_N_ta_new(n_ta, ta_cmd);
|
||||
sf_recv.set_time_adv_sec(((float) n_ta)*SRSLTE_LTE_TS);
|
||||
Info("PHY: Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, ((float) n_ta)*SRSLTE_LTE_TS*1e6);
|
||||
uint32_t new_nta = srslte_N_ta_new(n_ta, ta_cmd);
|
||||
sf_recv.set_time_adv_sec(((float) (new_nta - n_ta))*SRSLTE_LTE_TS);
|
||||
Info("PHY: Set TA: ta_cmd: %d, n_ta: %d, old_n_ta: %d, ta_usec: %.1f\n", ta_cmd, new_nta, n_ta, ((float) new_nta)*SRSLTE_LTE_TS*1e6);
|
||||
n_ta = new_nta;
|
||||
}
|
||||
|
||||
void phy::configure_prach_params()
|
||||
|
|
|
@ -480,6 +480,7 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) {
|
|||
sec_mode_cmd.nas_ksi.tsc_flag != LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE) {
|
||||
sec_mode_rej.emm_cause = LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH;
|
||||
nas_log->warning("Sending Security Mode Reject due to security capabilities mismatch\n");
|
||||
nas_log->console("Unsupported Security Mode Command settings: use ciphering algorithm EEA0 and integrity check EIA1 or EIA2.\n");
|
||||
success = false;
|
||||
} else {
|
||||
// Generate NAS encryption key and integrity protection key
|
||||
|
|
|
@ -48,6 +48,9 @@ rrc::rrc()
|
|||
:state(RRC_STATE_IDLE)
|
||||
,drb_up(false)
|
||||
{
|
||||
sync_reset_cnt = 0;
|
||||
n310_cnt = 0;
|
||||
n311_cnt = 0;
|
||||
}
|
||||
|
||||
static void liblte_rrc_handler(void *ctx, char *str) {
|
||||
|
@ -489,13 +492,17 @@ void rrc::earfcn_end() {
|
|||
|
||||
// Detection of physical layer problems (5.3.11.1)
|
||||
void rrc::out_of_sync() {
|
||||
// attempt resync
|
||||
sync_reset_cnt++;
|
||||
if (sync_reset_cnt >= SYNC_RESET_TIMEOUT) {
|
||||
rrc_log->info("Detected %d out-of-sync from PHY. Resynchronizing PHY.\n", sync_reset_cnt);
|
||||
phy->sync_reset();
|
||||
sync_reset_cnt = 0;
|
||||
}
|
||||
current_cell->in_sync = false;
|
||||
if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) {
|
||||
n310_cnt++;
|
||||
if (n310_cnt == N310) {
|
||||
// attempt resync
|
||||
//phy->sync_reset();
|
||||
|
||||
mac_timers->timer_get(t310)->reset();
|
||||
mac_timers->timer_get(t310)->run();
|
||||
n310_cnt = 0;
|
||||
|
|
Loading…
Reference in New Issue