Merge branch 'next' into raa

This commit is contained in:
Ismael Gomez 2018-02-02 19:33:24 +01:00
commit 3874eb0434
26 changed files with 689 additions and 528 deletions

View file

@ -353,11 +353,6 @@ void base_init() {
exit(-1); exit(-1);
} }
if (srslte_regs_set_cfi(&regs, cfi)) {
fprintf(stderr, "Error setting CFI\n");
exit(-1);
}
if (srslte_pdcch_init_enb(&pdcch, cell.nof_prb)) { if (srslte_pdcch_init_enb(&pdcch, cell.nof_prb)) {
fprintf(stderr, "Error creating PDCCH object\n"); fprintf(stderr, "Error creating PDCCH object\n");
exit(-1); exit(-1);

View file

@ -1029,7 +1029,7 @@ void *plot_thread_run(void *arg) {
} }
plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce); plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce[0]);
} }
plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d[0], nof_symbols); plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d[0], nof_symbols);

View file

@ -161,7 +161,7 @@ public:
virtual void out_of_sync() = 0; virtual void out_of_sync() = 0;
virtual void earfcn_end() = 0; virtual void earfcn_end() = 0;
virtual void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) = 0; virtual void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) = 0;
virtual void new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn = 0, uint32_t pci = 0) = 0; virtual void new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn = -1, int pci = -1) = 0;
}; };
// RRC interface for NAS // RRC interface for NAS

View file

@ -60,8 +60,8 @@ typedef enum SRSLTE_API {
/* PDCCH object */ /* PDCCH object */
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_cell_t cell; srslte_cell_t cell;
uint32_t nof_regs; uint32_t nof_regs[3];
uint32_t nof_cce; uint32_t nof_cce[3];
uint32_t max_bits; uint32_t max_bits;
uint32_t nof_rx_antennas; uint32_t nof_rx_antennas;
bool is_ue; bool is_ue;
@ -99,10 +99,7 @@ SRSLTE_API int srslte_pdcch_set_cell(srslte_pdcch_t *q,
SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q); SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q);
SRSLTE_API void srslte_pdcch_set_cfi(srslte_pdcch_t *q, SRSLTE_API float srslte_pdcch_coderate(uint32_t nof_bits,
uint32_t cfi);
SRSLTE_API float srslte_pdcch_coderate(uint32_t nof_bits,
uint32_t l); uint32_t l);
/* Encoding function */ /* Encoding function */
@ -134,6 +131,7 @@ SRSLTE_API int srslte_pdcch_decode_msg(srslte_pdcch_t *q,
srslte_dci_msg_t *msg, srslte_dci_msg_t *msg,
srslte_dci_location_t *location, srslte_dci_location_t *location,
srslte_dci_format_t format, srslte_dci_format_t format,
uint32_t cfi,
uint16_t *crc_rem); uint16_t *crc_rem);
SRSLTE_API int srslte_pdcch_dci_decode(srslte_pdcch_t *q, SRSLTE_API int srslte_pdcch_dci_decode(srslte_pdcch_t *q,

View file

@ -63,8 +63,6 @@ typedef struct SRSLTE_API {
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_cell_t cell; srslte_cell_t cell;
uint32_t max_ctrl_symbols; uint32_t max_ctrl_symbols;
uint32_t cfi;
bool cfi_initiated;
uint32_t ngroups_phich; uint32_t ngroups_phich;
srslte_phich_resources_t phich_res; srslte_phich_resources_t phich_res;
@ -83,27 +81,30 @@ SRSLTE_API int srslte_regs_init(srslte_regs_t *h,
srslte_cell_t cell); srslte_cell_t cell);
SRSLTE_API void srslte_regs_free(srslte_regs_t *h); SRSLTE_API void srslte_regs_free(srslte_regs_t *h);
SRSLTE_API int srslte_regs_set_cfi(srslte_regs_t *h,
uint32_t nof_ctrl_symbols);
SRSLTE_API uint32_t srslte_regs_pcfich_nregs(srslte_regs_t *h); SRSLTE_API int srslte_regs_pdcch_nregs(srslte_regs_t *h,
SRSLTE_API int srslte_regs_pcfich_put(srslte_regs_t *h, uint32_t cfi);
cf_t symbols[REGS_PCFICH_NSYM],
cf_t *slot_symbols); SRSLTE_API int srslte_regs_pdcch_ncce(srslte_regs_t *h,
uint32_t cfi);
SRSLTE_API int srslte_regs_pcfich_put(srslte_regs_t *h,
cf_t symbols[REGS_PCFICH_NSYM],
cf_t *slot_symbols);
SRSLTE_API int srslte_regs_pcfich_get(srslte_regs_t *h, SRSLTE_API int srslte_regs_pcfich_get(srslte_regs_t *h,
cf_t *slot_symbols, cf_t *slot_symbols,
cf_t symbols[REGS_PCFICH_NSYM]); cf_t symbols[REGS_PCFICH_NSYM]);
SRSLTE_API uint32_t srslte_regs_phich_nregs(srslte_regs_t *h); SRSLTE_API uint32_t srslte_regs_phich_nregs(srslte_regs_t *h);
SRSLTE_API int srslte_regs_phich_add(srslte_regs_t *h, SRSLTE_API int srslte_regs_phich_add(srslte_regs_t *h,
cf_t symbols[REGS_PHICH_NSYM], cf_t symbols[REGS_PHICH_NSYM],
uint32_t ngroup, uint32_t ngroup,
cf_t *slot_symbols); cf_t *slot_symbols);
SRSLTE_API int srslte_regs_phich_get(srslte_regs_t *h, SRSLTE_API int srslte_regs_phich_get(srslte_regs_t *h,
cf_t *slot_symbols, cf_t *slot_symbols,
cf_t symbols[REGS_PHICH_NSYM], cf_t symbols[REGS_PHICH_NSYM],
uint32_t ngroup); uint32_t ngroup);
@ -111,28 +112,26 @@ SRSLTE_API uint32_t srslte_regs_phich_ngroups(srslte_regs_t *h);
SRSLTE_API int srslte_regs_phich_reset(srslte_regs_t *h, SRSLTE_API int srslte_regs_phich_reset(srslte_regs_t *h,
cf_t *slot_symbols); cf_t *slot_symbols);
SRSLTE_API int srslte_regs_pdcch_nregs(srslte_regs_t *h, SRSLTE_API int srslte_regs_pdcch_put(srslte_regs_t *h,
uint32_t cfi); uint32_t cfi,
cf_t *d,
SRSLTE_API int srslte_regs_pdcch_ncce(srslte_regs_t *h,
uint32_t cfi);
SRSLTE_API int srslte_regs_pdcch_put(srslte_regs_t *h,
cf_t *d,
cf_t *slot_symbols); cf_t *slot_symbols);
SRSLTE_API int srslte_regs_pdcch_put_offset(srslte_regs_t *h, SRSLTE_API int srslte_regs_pdcch_put_offset(srslte_regs_t *h,
cf_t *d, uint32_t cfi,
cf_t *slot_symbols, cf_t *d,
uint32_t start_reg, cf_t *slot_symbols,
uint32_t nof_regs); uint32_t start_reg,
uint32_t nof_regs);
SRSLTE_API int srslte_regs_pdcch_get(srslte_regs_t *h, SRSLTE_API int srslte_regs_pdcch_get(srslte_regs_t *h,
cf_t *slot_symbols, uint32_t cfi,
cf_t *slot_symbols,
cf_t *d); cf_t *d);
SRSLTE_API int srslte_regs_pdcch_get_offset(srslte_regs_t *h, SRSLTE_API int srslte_regs_pdcch_get_offset(srslte_regs_t *h,
cf_t *slot_symbols, uint32_t cfi,
cf_t *slot_symbols,
cf_t *d, cf_t *d,
uint32_t start_reg, uint32_t start_reg,
uint32_t nof_regs); uint32_t nof_regs);

View file

@ -5,9 +5,11 @@
#include "srslte/config.h" #include "srslte/config.h"
#include <pthread.h> #include <pthread.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
typedef struct { typedef struct {
uint8_t *buffer; uint8_t *buffer;
bool active;
int capacity; int capacity;
int count; int count;
int wpm; int wpm;
@ -34,6 +36,7 @@ SRSLTE_API int srslte_ringbuffer_read(srslte_ringbuffer_t *q,
void *ptr, void *ptr,
int nof_bytes); int nof_bytes);
SRSLTE_API void srslte_ringbuffer_stop(srslte_ringbuffer_t *q);
#endif #endif

View file

@ -142,7 +142,6 @@ int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t cell)
if (q != NULL && if (q != NULL &&
srslte_cell_isvalid(&cell)) srslte_cell_isvalid(&cell))
{ {
srslte_enb_dl_set_cfi(q, 3);
q->tx_amp = SRSLTE_ENB_RF_AMP; q->tx_amp = SRSLTE_ENB_RF_AMP;
if (q->cell.id != cell.id || q->cell.nof_prb == 0) { if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
@ -207,10 +206,9 @@ void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, float amp)
q->tx_amp = amp; q->tx_amp = amp;
} }
void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q, uint32_t cfi) void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q, uint32_t cfi)
{ {
q->cfi = cfi; q->cfi = cfi;
srslte_regs_set_cfi(&q->regs, cfi);
} }
void srslte_enb_dl_set_power_allocation(srslte_enb_dl_t *q, float rho_a, float rho_b) void srslte_enb_dl_set_power_allocation(srslte_enb_dl_t *q, float rho_a, float rho_b)

View file

@ -45,16 +45,8 @@
#define PDCCH_FORMAT_NOF_REGS(i) ((1<<i)*9) #define PDCCH_FORMAT_NOF_REGS(i) ((1<<i)*9)
#define PDCCH_FORMAT_NOF_BITS(i) ((1<<i)*72) #define PDCCH_FORMAT_NOF_BITS(i) ((1<<i)*72)
static void set_cfi(srslte_pdcch_t *q, uint32_t cfi) { #define NOF_CCE(cfi) ((cfi>0&&cfi<4)?q->nof_cce[cfi-1]:0)
if (cfi > 0 && cfi < 4) { #define NOF_REGS(cfi) ((cfi>0&&cfi<4)?q->nof_regs[cfi-1]:0)
q->nof_regs = (srslte_regs_pdcch_nregs(q->regs, cfi) / 9) * 9;
q->nof_cce = q->nof_regs / 9;
}
}
void srslte_pdcch_set_cfi(srslte_pdcch_t *q, uint32_t cfi) {
set_cfi(q, cfi);
}
float srslte_pdcch_coderate(uint32_t nof_bits, uint32_t l) { float srslte_pdcch_coderate(uint32_t nof_bits, uint32_t l) {
return (float) (nof_bits+16)/(4*PDCCH_FORMAT_NOF_REGS(l)); return (float) (nof_bits+16)/(4*PDCCH_FORMAT_NOF_REGS(l));
@ -73,7 +65,7 @@ static int pdcch_init(srslte_pdcch_t *q, uint32_t max_prb, uint32_t nof_rx_anten
q->is_ue = is_ue; q->is_ue = is_ue;
/* Allocate memory for the maximum number of PDCCH bits (CFI=3) */ /* Allocate memory for the maximum number of PDCCH bits (CFI=3) */
q->max_bits = max_prb*3*12*2; q->max_bits = max_prb*3*12*2;
INFO("Init PDCCH: Max bits: %d\n", q->max_bits); INFO("Init PDCCH: Max bits: %d\n", q->max_bits);
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) { if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
@ -188,8 +180,13 @@ int srslte_pdcch_set_cell(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t
{ {
q->regs = regs; q->regs = regs;
for (int cfi=0;cfi<3;cfi++) {
q->nof_regs[cfi] = (srslte_regs_pdcch_nregs(q->regs, cfi+1) / 9) * 9;
q->nof_cce[cfi] = q->nof_regs[cfi]/ 9;
}
/* Allocate memory for the maximum number of PDCCH bits (CFI=3) */ /* Allocate memory for the maximum number of PDCCH bits (CFI=3) */
q->max_bits = (srslte_regs_pdcch_nregs(q->regs, 3) / 9) * 72; q->max_bits = (NOF_REGS(3)/ 9) * 72;
INFO("PDCCH: Cell config PCI=%d, %d ports.\n", INFO("PDCCH: Cell config PCI=%d, %d ports.\n",
q->cell.id, q->cell.nof_ports); q->cell.id, q->cell.nof_ports);
@ -214,8 +211,7 @@ int srslte_pdcch_set_cell(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t
uint32_t srslte_pdcch_ue_locations(srslte_pdcch_t *q, srslte_dci_location_t *c, uint32_t max_candidates, uint32_t srslte_pdcch_ue_locations(srslte_pdcch_t *q, srslte_dci_location_t *c, uint32_t max_candidates,
uint32_t nsubframe, uint32_t cfi, uint16_t rnti) uint32_t nsubframe, uint32_t cfi, uint16_t rnti)
{ {
set_cfi(q, cfi); return srslte_pdcch_ue_locations_ncce(NOF_CCE(cfi), c, max_candidates, nsubframe, rnti);
return srslte_pdcch_ue_locations_ncce(q->nof_cce, c, max_candidates, nsubframe, rnti);
} }
@ -286,8 +282,7 @@ uint32_t srslte_pdcch_ue_locations_ncce_L(uint32_t nof_cce, srslte_dci_location_
uint32_t srslte_pdcch_common_locations(srslte_pdcch_t *q, srslte_dci_location_t *c, uint32_t max_candidates, uint32_t srslte_pdcch_common_locations(srslte_pdcch_t *q, srslte_dci_location_t *c, uint32_t max_candidates,
uint32_t cfi) uint32_t cfi)
{ {
set_cfi(q, cfi); return srslte_pdcch_common_locations_ncce(NOF_CCE(cfi), c, max_candidates);
return srslte_pdcch_common_locations_ncce(q->nof_cce, c, max_candidates);
} }
uint32_t srslte_pdcch_common_locations_ncce(uint32_t nof_cce, srslte_dci_location_t *c, uint32_t max_candidates) uint32_t srslte_pdcch_common_locations_ncce(uint32_t nof_cce, srslte_dci_location_t *c, uint32_t max_candidates)
@ -298,9 +293,10 @@ uint32_t srslte_pdcch_common_locations_ncce(uint32_t nof_cce, srslte_dci_locatio
for (l = 3; l > 1; l--) { for (l = 3; l > 1; l--) {
L = (1 << l); L = (1 << l);
for (i = 0; i < SRSLTE_MIN(nof_cce, 16) / (L); i++) { for (i = 0; i < SRSLTE_MIN(nof_cce, 16) / (L); i++) {
if (k < max_candidates) { uint32_t ncce = (L) * (i % (nof_cce / (L)));
c[k].L = l; if (k < max_candidates && ncce + L <= nof_cce) {
c[k].ncce = (L) * (i % (nof_cce / (L))); c[k].L = l;
c[k].ncce = ncce;
DEBUG("Common SS Candidate %d: nCCE: %d, L: %d\n", DEBUG("Common SS Candidate %d: nCCE: %d, L: %d\n",
k, c[k].ncce, c[k].L); k, c[k].ncce, c[k].L);
k++; k++;
@ -370,7 +366,8 @@ int srslte_pdcch_dci_decode(srslte_pdcch_t *q, float *e, uint8_t *data, uint32_t
int srslte_pdcch_decode_msg(srslte_pdcch_t *q, int srslte_pdcch_decode_msg(srslte_pdcch_t *q,
srslte_dci_msg_t *msg, srslte_dci_msg_t *msg,
srslte_dci_location_t *location, srslte_dci_location_t *location,
srslte_dci_format_t format, srslte_dci_format_t format,
uint32_t cfi,
uint16_t *crc_rem) uint16_t *crc_rem)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -379,9 +376,9 @@ int srslte_pdcch_decode_msg(srslte_pdcch_t *q,
srslte_dci_location_isvalid(location)) srslte_dci_location_isvalid(location))
{ {
if (location->ncce * 72 + PDCCH_FORMAT_NOF_BITS(location->L) > if (location->ncce * 72 + PDCCH_FORMAT_NOF_BITS(location->L) >
q->nof_cce*72) { NOF_CCE(cfi)*72) {
fprintf(stderr, "Invalid location: nCCE: %d, L: %d, NofCCE: %d\n", fprintf(stderr, "Invalid location: nCCE: %d, L: %d, NofCCE: %d\n",
location->ncce, location->L, q->nof_cce); location->ncce, location->L, NOF_CCE(cfi));
} else { } else {
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
@ -457,9 +454,8 @@ int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q, cf_t *sf_symbols[SRSLTE_MA
cfi > 0 && cfi > 0 &&
cfi < 4) cfi < 4)
{ {
set_cfi(q, cfi);
uint32_t e_bits = 72*q->nof_cce; uint32_t e_bits = 72*NOF_CCE(cfi);
nof_symbols = e_bits/2; nof_symbols = e_bits/2;
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q->llr, sizeof(float) * q->max_bits); bzero(q->llr, sizeof(float) * q->max_bits);
@ -475,7 +471,7 @@ int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q, cf_t *sf_symbols[SRSLTE_MA
/* extract symbols */ /* extract symbols */
for (int j=0;j<q->nof_rx_antennas;j++) { for (int j=0;j<q->nof_rx_antennas;j++) {
int n = srslte_regs_pdcch_get(q->regs, sf_symbols[j], q->symbols[j]); int n = srslte_regs_pdcch_get(q->regs, cfi, sf_symbols[j], q->symbols[j]);
if (nof_symbols != n) { if (nof_symbols != n) {
fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n); fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n);
return ret; return ret;
@ -483,7 +479,7 @@ int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q, cf_t *sf_symbols[SRSLTE_MA
/* extract channel estimates */ /* extract channel estimates */
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < q->cell.nof_ports; i++) {
n = srslte_regs_pdcch_get(q->regs, ce[i][j], q->ce[i][j]); n = srslte_regs_pdcch_get(q->regs, cfi, ce[i][j], q->ce[i][j]);
if (nof_symbols != n) { if (nof_symbols != n) {
fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n); fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n);
return ret; return ret;
@ -595,13 +591,11 @@ int srslte_pdcch_encode(srslte_pdcch_t *q, srslte_dci_msg_t *msg, srslte_dci_loc
srslte_dci_location_isvalid(&location)) srslte_dci_location_isvalid(&location))
{ {
set_cfi(q, cfi);
uint32_t e_bits = PDCCH_FORMAT_NOF_BITS(location.L); uint32_t e_bits = PDCCH_FORMAT_NOF_BITS(location.L);
nof_symbols = e_bits/2; nof_symbols = e_bits/2;
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
if (location.ncce + PDCCH_FORMAT_NOF_CCE(location.L) <= q->nof_cce && if (location.ncce + PDCCH_FORMAT_NOF_CCE(location.L) <= NOF_CCE(cfi) &&
msg->nof_bits < SRSLTE_DCI_MAX_BITS - 16) msg->nof_bits < SRSLTE_DCI_MAX_BITS - 16)
{ {
DEBUG("Encoding DCI: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", DEBUG("Encoding DCI: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n",
@ -634,14 +628,14 @@ int srslte_pdcch_encode(srslte_pdcch_t *q, srslte_dci_msg_t *msg, srslte_dci_loc
/* mapping to resource elements */ /* mapping to resource elements */
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < q->cell.nof_ports; i++) {
srslte_regs_pdcch_put_offset(q->regs, q->symbols[i], sf_symbols[i], srslte_regs_pdcch_put_offset(q->regs, cfi, q->symbols[i], sf_symbols[i],
location.ncce * 9, PDCCH_FORMAT_NOF_REGS(location.L)); location.ncce * 9, PDCCH_FORMAT_NOF_REGS(location.L));
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} else { } else {
fprintf(stderr, "Illegal DCI message nCCE: %d, L: %d, nof_cce: %d, nof_bits=%d\n", location.ncce, location.L, q->nof_cce, msg->nof_bits); fprintf(stderr, "Illegal DCI message nCCE: %d, L: %d, nof_cce: %d, nof_bits=%d\n", location.ncce, location.L, NOF_CCE(cfi), msg->nof_bits);
} }
} else { } else {
fprintf(stderr, "Invalid parameters: cfi=%d, L=%d, nCCE=%d\n", cfi, location.L, location.ncce); fprintf(stderr, "Invalid parameters: cfi=%d, L=%d, nCCE=%d\n", cfi, location.L, location.ncce);

View file

@ -150,7 +150,8 @@ int srslte_ra_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_
// starting prb idx for slot 0 is as given by resource grant // starting prb idx for slot 0 is as given by resource grant
grant->n_prb[0] = n_prb_1; grant->n_prb[0] = n_prb_1;
if (n_prb_1 < n_rb_ho/2) { if (n_prb_1 < n_rb_ho/2) {
fprintf(stderr, "Invalid Frequency Hopping parameters. Offset: %d, n_prb_1: %d\n", n_rb_ho, n_prb_1); INFO("Invalid Frequency Hopping parameters. Offset: %d, n_prb_1: %d\n", n_rb_ho, n_prb_1);
return SRSLTE_ERROR;
} }
uint32_t n_prb_1_tilde = n_prb_1; uint32_t n_prb_1_tilde = n_prb_1;

View file

@ -111,7 +111,7 @@ int regs_pdcch_init(srslte_regs_t *h) {
} }
h->pdcch[cfi].nof_regs = m; h->pdcch[cfi].nof_regs = m;
h->pdcch[cfi].regs = malloc(sizeof(srslte_regs_reg_t*) * h->pdcch[cfi].nof_regs); h->pdcch[cfi].regs = malloc(sizeof(srslte_regs_reg_t*) * h->pdcch[cfi].nof_regs);
if (!h->pdcch[cfi].regs) { if (!h->pdcch[cfi].regs) {
perror("malloc"); perror("malloc");
@ -133,7 +133,7 @@ int regs_pdcch_init(srslte_regs_t *h) {
if (k < h->cell.id) { if (k < h->cell.id) {
kp = (h->pdcch[cfi].nof_regs + k-(h->cell.id%h->pdcch[cfi].nof_regs))%h->pdcch[cfi].nof_regs; kp = (h->pdcch[cfi].nof_regs + k-(h->cell.id%h->pdcch[cfi].nof_regs))%h->pdcch[cfi].nof_regs;
} else { } else {
kp = (k-h->cell.id)%h->pdcch[cfi].nof_regs; kp = (k-h->cell.id)%h->pdcch[cfi].nof_regs;
} }
h->pdcch[cfi].regs[m] = tmp[kp]; h->pdcch[cfi].regs[m] = tmp[kp];
k++; k++;
@ -141,7 +141,7 @@ int regs_pdcch_init(srslte_regs_t *h) {
} }
} }
h->pdcch[cfi].nof_regs = (h->pdcch[cfi].nof_regs/9)*9; h->pdcch[cfi].nof_regs = (h->pdcch[cfi].nof_regs/9)*9;
INFO("Init PDCCH REG space CFI %d. %d useful REGs (%d CCEs)\n",cfi+1, INFO("Init PDCCH REG space CFI %d. %d useful REGs (%d CCEs)\n",cfi+1,
h->pdcch[cfi].nof_regs, h->pdcch[cfi].nof_regs/9); h->pdcch[cfi].nof_regs, h->pdcch[cfi].nof_regs/9);
free(tmp); free(tmp);
tmp = NULL; tmp = NULL;
@ -168,11 +168,11 @@ int srslte_regs_pdcch_nregs(srslte_regs_t *h, uint32_t cfi) {
} }
int srslte_regs_pdcch_ncce(srslte_regs_t *h, uint32_t cfi) { int srslte_regs_pdcch_ncce(srslte_regs_t *h, uint32_t cfi) {
int nregs = srslte_regs_pdcch_nregs(h, cfi); int nregs = srslte_regs_pdcch_nregs(h, cfi);
if (nregs > 0) { if (nregs > 0) {
return (uint32_t) (nregs / 9); return (uint32_t) (nregs / 9);
} else { } else {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
} }
@ -180,53 +180,59 @@ int srslte_regs_pdcch_ncce(srslte_regs_t *h, uint32_t cfi) {
* second part of 6.8.5 in 36.211 * second part of 6.8.5 in 36.211
*/ */
int srslte_regs_pdcch_put_offset(srslte_regs_t *h, cf_t *d, cf_t *slot_symbols, uint32_t start_reg, uint32_t nof_regs) { int srslte_regs_pdcch_put_offset(srslte_regs_t *h, uint32_t cfi, cf_t *d, cf_t *slot_symbols, uint32_t start_reg, uint32_t nof_regs) {
if (h->cfi_initiated) { if (cfi < 1 || cfi > 3) {
if (start_reg + nof_regs <= h->pdcch[h->cfi].nof_regs) { fprintf(stderr, "Invalid CFI=%d\n", cfi);
uint32_t i, k;
k = 0;
for (i=start_reg;i<start_reg+nof_regs;i++) {
regs_put_reg(h->pdcch[h->cfi].regs[i], &d[k], slot_symbols, h->cell.nof_prb);
k += 4;
}
return k;
} else {
fprintf(stderr, "Out of range: start_reg + nof_reg must be lower than %d\n", h->pdcch[h->cfi].nof_regs);
return SRSLTE_ERROR;
}
} else {
fprintf(stderr, "Must call srslte_regs_set_cfi() first\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
} if (start_reg + nof_regs <= h->pdcch[cfi-1].nof_regs) {
uint32_t i, k;
int srslte_regs_pdcch_put(srslte_regs_t *h, cf_t *d, cf_t *slot_symbols) { k = 0;
return srslte_regs_pdcch_put_offset(h, d, slot_symbols, 0, h->pdcch[h->cfi].nof_regs); for (i=start_reg;i<start_reg+nof_regs;i++) {
} regs_put_reg(h->pdcch[cfi-1].regs[i], &d[k], slot_symbols, h->cell.nof_prb);
k += 4;
int srslte_regs_pdcch_get_offset(srslte_regs_t *h, cf_t *slot_symbols, cf_t *d, uint32_t start_reg, uint32_t nof_regs) {
if (h->cfi_initiated) {
if (start_reg + nof_regs <= h->pdcch[h->cfi].nof_regs) {
uint32_t i, k;
k = 0;
for (i=start_reg;i<start_reg + nof_regs;i++) {
regs_get_reg(h->pdcch[h->cfi].regs[i], slot_symbols, &d[k], h->cell.nof_prb);
k += 4;
}
return k;
} else {
fprintf(stderr, "Out of range: start_reg + nof_reg must be lower than %d\n", h->pdcch[h->cfi].nof_regs);
return SRSLTE_ERROR;
} }
return k;
} else { } else {
fprintf(stderr, "Must call srslte_regs_set_cfi() first\n"); fprintf(stderr, "Out of range: start_reg + nof_reg must be lower than %d\n", h->pdcch[cfi-1].nof_regs);
return SRSLTE_ERROR;
}
}
int srslte_regs_pdcch_put(srslte_regs_t *h, uint32_t cfi, cf_t *d, cf_t *slot_symbols) {
if (cfi < 1 || cfi > 3) {
fprintf(stderr, "Invalid CFI=%d\n", cfi);
return SRSLTE_ERROR;
}
return srslte_regs_pdcch_put_offset(h, cfi, d, slot_symbols, 0, h->pdcch[cfi-1].nof_regs);
}
int srslte_regs_pdcch_get_offset(srslte_regs_t *h, uint32_t cfi, cf_t *slot_symbols, cf_t *d, uint32_t start_reg, uint32_t nof_regs) {
if (cfi < 1 || cfi > 3) {
fprintf(stderr, "Invalid CFI=%d\n", cfi);
return SRSLTE_ERROR;
}
if (start_reg + nof_regs <= h->pdcch[cfi-1].nof_regs) {
uint32_t i, k;
k = 0;
for (i=start_reg;i<start_reg + nof_regs;i++) {
regs_get_reg(h->pdcch[cfi-1].regs[i], slot_symbols, &d[k], h->cell.nof_prb);
k += 4;
}
return k;
} else {
fprintf(stderr, "Out of range: start_reg + nof_reg must be lower than %d\n", h->pdcch[cfi-1].nof_regs);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
} }
int srslte_regs_pdcch_get(srslte_regs_t *h, cf_t *slot_symbols, cf_t *d) { int srslte_regs_pdcch_get(srslte_regs_t *h, uint32_t cfi, cf_t *slot_symbols, cf_t *d) {
return srslte_regs_pdcch_get_offset(h, slot_symbols, d, 0, h->pdcch[h->cfi].nof_regs); if (cfi < 1 || cfi > 3) {
fprintf(stderr, "Invalid CFI=%d\n", cfi);
return SRSLTE_ERROR;
}
return srslte_regs_pdcch_get_offset(h, cfi, slot_symbols, d, 0, h->pdcch[cfi-1].nof_regs);
} }
@ -668,25 +674,6 @@ void srslte_regs_free(srslte_regs_t *h) {
bzero(h, sizeof(srslte_regs_t)); bzero(h, sizeof(srslte_regs_t));
} }
/** Sets the CFI value for this subframe (CFI must be in the range 1..3).
*/
int srslte_regs_set_cfi(srslte_regs_t *h, uint32_t cfi) {
if (cfi > 0 && cfi <= 3) {
if (h->phich_len == SRSLTE_PHICH_EXT &&
((h->cell.nof_prb <= 10 && cfi < 2) || (h->cell.nof_prb >= 10 && cfi < 3))) {
fprintf(stderr, "PHICH length is extended. The number of control symbols should be at least 3.\n");
return SRSLTE_ERROR_INVALID_INPUTS;
} else {
h->cfi_initiated = true;
h->cfi = cfi - 1;
return SRSLTE_SUCCESS;
}
} else {
fprintf(stderr, "Invalid CFI %d\n", cfi);
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
/** /**
* Initializes REGs structure. * Initializes REGs structure.
* Sets all REG indices and initializes PCFICH, PHICH and PDCCH REGs * Sets all REG indices and initializes PCFICH, PHICH and PDCCH REGs
@ -709,7 +696,6 @@ int srslte_regs_init(srslte_regs_t *h, srslte_cell_t cell) {
vo = cell.id % 3; vo = cell.id % 3;
h->cell = cell; h->cell = cell;
h->max_ctrl_symbols = max_ctrl_symbols; h->max_ctrl_symbols = max_ctrl_symbols;
h->cfi_initiated = false;
h->phich_res = cell.phich_resources; h->phich_res = cell.phich_resources;
h->phich_len = cell.phich_length; h->phich_len = cell.phich_length;

View file

@ -167,10 +167,6 @@ int base_init() {
return -1; return -1;
} }
if (srslte_regs_set_cfi(&regs, cfi)) {
fprintf(stderr, "Error setting CFI %d\n", cfi);
return -1;
}
if (srslte_pdcch_init_ue(&pdcch, cell.nof_prb, 1)) { if (srslte_pdcch_init_ue(&pdcch, cell.nof_prb, 1)) {
fprintf(stderr, "Error creating PDCCH object\n"); fprintf(stderr, "Error creating PDCCH object\n");
exit(-1); exit(-1);
@ -252,7 +248,7 @@ int main(int argc, char **argv) {
} }
for (i=0;i<nof_locations && crc_rem != rnti;i++) { for (i=0;i<nof_locations && crc_rem != rnti;i++) {
if (srslte_pdcch_decode_msg(&pdcch, &dci_msg, &locations[i], dci_format, &crc_rem)) { if (srslte_pdcch_decode_msg(&pdcch, &dci_msg, &locations[i], dci_format, cfi, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n"); fprintf(stderr, "Error decoding DCI msg\n");
return -1; return -1;
} }

View file

@ -199,11 +199,6 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
if (srslte_regs_set_cfi(&regs, cfi)) {
fprintf(stderr, "Error setting CFI\n");
exit(-1);
}
if (srslte_pdcch_init_enb(&pdcch_tx, cell.nof_prb)) { if (srslte_pdcch_init_enb(&pdcch_tx, cell.nof_prb)) {
fprintf(stderr, "Error creating PDCCH object\n"); fprintf(stderr, "Error creating PDCCH object\n");
exit(-1); exit(-1);
@ -297,7 +292,7 @@ int main(int argc, char **argv) {
/* Decode DCIs */ /* Decode DCIs */
for (i=0;i<nof_dcis;i++) { for (i=0;i<nof_dcis;i++) {
uint16_t crc_rem; uint16_t crc_rem;
if (srslte_pdcch_decode_msg(&pdcch_rx, &testcases[i].dci_rx, &testcases[i].dci_location, testcases[i].dci_format, &crc_rem)) { if (srslte_pdcch_decode_msg(&pdcch_rx, &testcases[i].dci_rx, &testcases[i].dci_location, testcases[i].dci_format, cfi, &crc_rem)) {
fprintf(stderr, "Error decoding DCI message\n"); fprintf(stderr, "Error decoding DCI message\n");
goto quit; goto quit;
} }

View file

@ -71,7 +71,7 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
q->N_id_1 = 1000; q->N_id_1 = 1000;
q->cfo_ema_alpha = CFO_EMA_ALPHA; q->cfo_ema_alpha = CFO_EMA_ALPHA;
q->sss_alg = SSS_FULL; q->sss_alg = SSS_PARTIAL_3;
q->detect_cp = true; q->detect_cp = true;
q->sss_en = true; q->sss_en = true;

View file

@ -441,12 +441,7 @@ int srslte_ue_dl_decode_estimate_mbsfn(srslte_ue_dl_t *q, uint32_t sf_idx, uint3
INFO("Decoded CFI=%d with correlation %.2f, sf_idx=%d\n", *cfi, cfi_corr, sf_idx); INFO("Decoded CFI=%d with correlation %.2f, sf_idx=%d\n", *cfi, cfi_corr, sf_idx);
if (srslte_regs_set_cfi(&q->regs, *cfi)) { return SRSLTE_SUCCESS;
fprintf(stderr, "Error setting CFI\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
} else { } else {
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
@ -780,7 +775,7 @@ uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q) {
return q->last_location.ncce; return q->last_location.ncce;
} }
static int dci_blind_search(srslte_ue_dl_t *q, dci_blind_search_t *search_space, uint16_t rnti, srslte_dci_msg_t *dci_msg) static int dci_blind_search(srslte_ue_dl_t *q, dci_blind_search_t *search_space, uint16_t rnti, uint32_t cfi, srslte_dci_msg_t *dci_msg)
{ {
int ret = SRSLTE_ERROR; int ret = SRSLTE_ERROR;
uint16_t crc_rem = 0; uint16_t crc_rem = 0;
@ -792,7 +787,7 @@ static int dci_blind_search(srslte_ue_dl_t *q, dci_blind_search_t *search_space,
srslte_dci_format_string(search_space->format), search_space->loc[i].ncce, search_space->loc[i].L, srslte_dci_format_string(search_space->format), search_space->loc[i].ncce, search_space->loc[i].L,
i, search_space->nof_locations); i, search_space->nof_locations);
if (srslte_pdcch_decode_msg(&q->pdcch, dci_msg, &search_space->loc[i], search_space->format, &crc_rem)) { if (srslte_pdcch_decode_msg(&q->pdcch, dci_msg, &search_space->loc[i], search_space->format, cfi, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n"); fprintf(stderr, "Error decoding DCI msg\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -834,7 +829,8 @@ int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q, uint32_t cfi, uint32_t sf_idx, u
} }
// Configure and run DCI blind search // Configure and run DCI blind search
dci_blind_search_t search_space; dci_blind_search_t search_space;
search_space.nof_locations = 0;
dci_blind_search_t *current_ss = &search_space; dci_blind_search_t *current_ss = &search_space;
if (q->current_rnti == rnti) { if (q->current_rnti == rnti) {
current_ss = &q->current_ss_ue[cfi-1][sf_idx]; current_ss = &q->current_ss_ue[cfi-1][sf_idx];
@ -843,11 +839,9 @@ int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q, uint32_t cfi, uint32_t sf_idx, u
current_ss->nof_locations = srslte_pdcch_ue_locations(&q->pdcch, current_ss->loc, MAX_CANDIDATES_UE, sf_idx, cfi, rnti); current_ss->nof_locations = srslte_pdcch_ue_locations(&q->pdcch, current_ss->loc, MAX_CANDIDATES_UE, sf_idx, cfi, rnti);
} }
srslte_pdcch_set_cfi(&q->pdcch, cfi); current_ss->format = SRSLTE_DCI_FORMAT0;
current_ss->format = SRSLTE_DCI_FORMAT0;
INFO("Searching UL C-RNTI in %d ue locations\n", search_space.nof_locations); INFO("Searching UL C-RNTI in %d ue locations\n", search_space.nof_locations);
return dci_blind_search(q, current_ss, rnti, dci_msg); return dci_blind_search(q, current_ss, rnti, cfi, dci_msg);
} else { } else {
return 0; return 0;
} }
@ -880,7 +874,7 @@ static int find_dl_dci_type_siprarnti(srslte_ue_dl_t *q, uint32_t cfi, uint16_t
if (search_space.nof_locations > 0) { if (search_space.nof_locations > 0) {
for (int f=0;f<nof_common_formats;f++) { for (int f=0;f<nof_common_formats;f++) {
search_space.format = common_formats[f]; search_space.format = common_formats[f];
if ((ret = dci_blind_search(q, &search_space, rnti, dci_msg))) { if ((ret = dci_blind_search(q, &search_space, rnti, cfi, dci_msg))) {
return ret; return ret;
} }
} }
@ -907,8 +901,6 @@ static int find_dl_dci_type_crnti(srslte_ue_dl_t *q, uint32_t tm, uint32_t cfi,
// If locations are not pre-generated, generate them now // If locations are not pre-generated, generate them now
current_ss->nof_locations = srslte_pdcch_ue_locations(&q->pdcch, current_ss->loc, MAX_CANDIDATES_UE, sf_idx, cfi, rnti); current_ss->nof_locations = srslte_pdcch_ue_locations(&q->pdcch, current_ss->loc, MAX_CANDIDATES_UE, sf_idx, cfi, rnti);
} }
srslte_pdcch_set_cfi(&q->pdcch, cfi);
for (int f = 0; f < 2; f++) { for (int f = 0; f < 2; f++) {
srslte_dci_format_t format = ue_dci_formats[tm][f]; srslte_dci_format_t format = ue_dci_formats[tm][f];
@ -917,8 +909,8 @@ static int find_dl_dci_type_crnti(srslte_ue_dl_t *q, uint32_t tm, uint32_t cfi,
current_ss->nof_locations); current_ss->nof_locations);
current_ss->format = format; current_ss->format = format;
if ((ret = dci_blind_search(q, current_ss, rnti, dci_msg))) { if ((ret = dci_blind_search(q, current_ss, rnti, cfi, dci_msg))) {
return ret; return ret;
} }
} }
@ -930,13 +922,11 @@ static int find_dl_dci_type_crnti(srslte_ue_dl_t *q, uint32_t tm, uint32_t cfi,
current_ss->nof_locations = srslte_pdcch_common_locations(&q->pdcch, current_ss->loc, MAX_CANDIDATES_COM, cfi); current_ss->nof_locations = srslte_pdcch_common_locations(&q->pdcch, current_ss->loc, MAX_CANDIDATES_COM, cfi);
} }
srslte_pdcch_set_cfi(&q->pdcch, cfi); // Search for RNTI only if there is room for the common search space
// Search for RNTI only if there is room for the common search space
if (current_ss->nof_locations > 0) { if (current_ss->nof_locations > 0) {
current_ss->format = SRSLTE_DCI_FORMAT1A; current_ss->format = SRSLTE_DCI_FORMAT1A;
INFO("Searching DL C-RNTI in %d ue locations, format 1A\n", current_ss->nof_locations); INFO("Searching DL C-RNTI in %d ue locations, format 1A\n", current_ss->nof_locations);
return dci_blind_search(q, current_ss, rnti, dci_msg); return dci_blind_search(q, current_ss, rnti, cfi, dci_msg);
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -988,11 +978,11 @@ void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuf
srslte_vec_save_file("pcfich_eq_symbols", q->pcfich.d, q->pcfich.nof_symbols*sizeof(cf_t)); srslte_vec_save_file("pcfich_eq_symbols", q->pcfich.d, q->pcfich.nof_symbols*sizeof(cf_t));
srslte_vec_save_file("pcfich_llr", q->pcfich.data_f, PCFICH_CFI_LEN*sizeof(float)); srslte_vec_save_file("pcfich_llr", q->pcfich.data_f, PCFICH_CFI_LEN*sizeof(float));
srslte_vec_save_file("pdcch_ce0", q->pdcch.ce[0], q->pdcch.nof_cce*36*sizeof(cf_t)); srslte_vec_save_file("pdcch_ce0", q->pdcch.ce[0], q->pdcch.nof_cce[cfi-1]*36*sizeof(cf_t));
srslte_vec_save_file("pdcch_ce1", q->pdcch.ce[1], q->pdcch.nof_cce*36*sizeof(cf_t)); srslte_vec_save_file("pdcch_ce1", q->pdcch.ce[1], q->pdcch.nof_cce[cfi-1]*36*sizeof(cf_t));
srslte_vec_save_file("pdcch_symbols", q->pdcch.symbols[0], q->pdcch.nof_cce*36*sizeof(cf_t)); srslte_vec_save_file("pdcch_symbols", q->pdcch.symbols[0], q->pdcch.nof_cce[cfi-1]*36*sizeof(cf_t));
srslte_vec_save_file("pdcch_eq_symbols", q->pdcch.d, q->pdcch.nof_cce*36*sizeof(cf_t)); srslte_vec_save_file("pdcch_eq_symbols", q->pdcch.d, q->pdcch.nof_cce[cfi-1]*36*sizeof(cf_t));
srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce*72*sizeof(float)); srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce[cfi-1]*72*sizeof(float));
srslte_vec_save_file("pdsch_symbols", q->pdsch.d[0], q->pdsch_cfg.nbits[0].nof_re*sizeof(cf_t)); srslte_vec_save_file("pdsch_symbols", q->pdsch.d[0], q->pdsch_cfg.nbits[0].nof_re*sizeof(cf_t));

View file

@ -11,7 +11,7 @@ int srslte_ringbuffer_init(srslte_ringbuffer_t *q, int capacity)
if (!q->buffer) { if (!q->buffer) {
return -1; return -1;
} }
q->active = true;
q->capacity = capacity; q->capacity = capacity;
srslte_ringbuffer_reset(q); srslte_ringbuffer_reset(q);
@ -24,6 +24,7 @@ int srslte_ringbuffer_init(srslte_ringbuffer_t *q, int capacity)
void srslte_ringbuffer_free(srslte_ringbuffer_t *q) void srslte_ringbuffer_free(srslte_ringbuffer_t *q)
{ {
if (q) { if (q) {
srslte_ringbuffer_stop(q);
if (q->buffer) { if (q->buffer) {
free(q->buffer); free(q->buffer);
q->buffer = NULL; q->buffer = NULL;
@ -52,6 +53,9 @@ int srslte_ringbuffer_write(srslte_ringbuffer_t *q, void *p, int nof_bytes)
uint8_t *ptr = (uint8_t*) p; uint8_t *ptr = (uint8_t*) p;
int w_bytes = nof_bytes; int w_bytes = nof_bytes;
pthread_mutex_lock(&q->mutex); pthread_mutex_lock(&q->mutex);
if (!q->active) {
return 0;
}
if (q->count + w_bytes > q->capacity) { if (q->count + w_bytes > q->capacity) {
w_bytes = q->capacity - q->count; w_bytes = q->capacity - q->count;
fprintf(stderr, "Buffer overrun: lost %d bytes\n", nof_bytes - w_bytes); fprintf(stderr, "Buffer overrun: lost %d bytes\n", nof_bytes - w_bytes);
@ -77,9 +81,12 @@ int srslte_ringbuffer_read(srslte_ringbuffer_t *q, void *p, int nof_bytes)
{ {
uint8_t *ptr = (uint8_t*) p; uint8_t *ptr = (uint8_t*) p;
pthread_mutex_lock(&q->mutex); pthread_mutex_lock(&q->mutex);
while(q->count < nof_bytes) { while(q->count < nof_bytes && q->active) {
pthread_cond_wait(&q->cvar, &q->mutex); pthread_cond_wait(&q->cvar, &q->mutex);
} }
if (!q->active) {
return 0;
}
if (nof_bytes + q->rpm > q->capacity) { if (nof_bytes + q->rpm > q->capacity) {
int x = q->capacity - q->rpm; int x = q->capacity - q->rpm;
memcpy(ptr, &q->buffer[q->rpm], x); memcpy(ptr, &q->buffer[q->rpm], x);
@ -96,5 +103,9 @@ int srslte_ringbuffer_read(srslte_ringbuffer_t *q, void *p, int nof_bytes)
return nof_bytes; return nof_bytes;
} }
void srslte_ringbuffer_stop(srslte_ringbuffer_t *q) {
pthread_mutex_lock(&q->mutex);
pthread_cond_broadcast(&q->cvar);
pthread_mutex_unlock(&q->mutex);
}

View file

@ -82,6 +82,7 @@ bool read(std::string filename) {
written[thread][msg] = true; written[thread][msg] = true;
} else { } else {
perror("Wrong thread and/or msg"); perror("Wrong thread and/or msg");
fclose(f);
return false; return false;
} }
} }

View file

@ -697,7 +697,7 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST])
for(uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { for(uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
h->reset(tb); h->reset(tb);
} }
Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d\n", rnti, h->get_id()); Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d, cfi=%d\n", rnti, h->get_id(), current_cfi);
} }
} }
} }
@ -857,12 +857,22 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
if (needs_pdcch) { if (needs_pdcch) {
uint32_t aggr_level = user->get_aggr_level(srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT0, cfg.cell.nof_prb, cfg.cell.nof_ports)); uint32_t aggr_level = user->get_aggr_level(srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT0, cfg.cell.nof_prb, cfg.cell.nof_ports));
if (!generate_dci(&sched_result->pusch[nof_dci_elems].dci_location, if (!generate_dci(&sched_result->pusch[nof_dci_elems].dci_location,
user->get_locations(current_cfi, sf_idx), user->get_locations(current_cfi, sf_idx),
aggr_level)) aggr_level))
{ {
h->reset(0); h->reset(0);
log_h->warning("SCHED: Could not schedule UL DCI rnti=0x%x, pid=%d, L=%d\n", printf("SCHED: Could not schedule UL DCI rnti=0x%x, pid=%d, L=%d, sf_idx=%d\n",
rnti, h->get_id(), aggr_level); rnti, h->get_id(), aggr_level, sf_idx);
sched_ue::sched_dci_cce_t *loc=user->get_locations(current_cfi, sf_idx);
for (int i=0;i<loc->nof_loc[aggr_level];i++) {
printf("n=%d\n", loc->cce_start[aggr_level][i]);
}
printf("used=[");
for (int i=0;i<MAX_CCE;i++) {
printf("%d,", used_cce[i]);
}
printf("\n");
sched_result->pusch[nof_dci_elems].needs_pdcch = false; sched_result->pusch[nof_dci_elems].needs_pdcch = false;
} else { } else {
sched_result->pusch[nof_dci_elems].needs_pdcch = true; sched_result->pusch[nof_dci_elems].needs_pdcch = true;
@ -939,7 +949,7 @@ void sched::generate_cce_location(srslte_regs_t *regs_, sched_ue::sched_dci_cce_
nloc = srslte_pdcch_ue_locations_ncce(srslte_regs_pdcch_ncce(regs_, cfi), nloc = srslte_pdcch_ue_locations_ncce(srslte_regs_pdcch_ncce(regs_, cfi),
loc, 64, sf_idx, rnti); loc, 64, sf_idx, rnti);
} }
for (uint32_t l=0;l<=3;l++) { for (uint32_t l=0;l<=3;l++) {
int n=0; int n=0;
for (uint32_t i=0;i<nloc;i++) { for (uint32_t i=0;i<nloc;i++) {
@ -958,10 +968,12 @@ void sched::generate_cce_location(srslte_regs_t *regs_, sched_ue::sched_dci_cce_
bool sched::generate_dci(srslte_dci_location_t *sched_location, sched_ue::sched_dci_cce_t *locations, uint32_t aggr_level, sched_ue *user) bool sched::generate_dci(srslte_dci_location_t *sched_location, sched_ue::sched_dci_cce_t *locations, uint32_t aggr_level, sched_ue *user)
{ {
uint32_t ncand=0; uint32_t nof_cand = 0;
bool allocated=false; uint32_t test_cand = rand()%locations->nof_loc[aggr_level];
while(ncand<locations->nof_loc[aggr_level] && !allocated) { bool allocated=false;
uint32_t ncce = locations->cce_start[aggr_level][ncand];
while(nof_cand<locations->nof_loc[aggr_level] && !allocated) {
uint32_t ncce = locations->cce_start[aggr_level][test_cand];
bool used = false; bool used = false;
if (user) { if (user) {
used = user->pucch_sr_collision(current_tti, ncce); used = user->pucch_sr_collision(current_tti, ncce);
@ -972,7 +984,11 @@ bool sched::generate_dci(srslte_dci_location_t *sched_location, sched_ue::sched_
} }
} }
if (used) { if (used) {
ncand++; test_cand++;
if (test_cand==locations->nof_loc[aggr_level]) {
test_cand = 0;
}
nof_cand++;
} else { } else {
for (int j=0;j<NCCE(aggr_level) && !used;j++) { for (int j=0;j<NCCE(aggr_level) && !used;j++) {
used_cce[ncce+j] = true; used_cce[ncce+j] = true;
@ -984,7 +1000,7 @@ bool sched::generate_dci(srslte_dci_location_t *sched_location, sched_ue::sched_
if (allocated && sched_location) { if (allocated && sched_location) {
sched_location->L = aggr_level; sched_location->L = aggr_level;
sched_location->ncce = locations->cce_start[aggr_level][ncand]; sched_location->ncce = locations->cce_start[aggr_level][test_cand];
} }
return allocated; return allocated;

View file

@ -591,7 +591,7 @@ int main(int argc, char *argv[])
int setup_if_addr(char *ip_addr) int setup_if_addr(char *ip_addr)
{ {
char *dev = (char*) "tun_srsenb"; char *dev = (char*) "tun_srsenb";
int sock = 0; int sock = -1;
// Construct the TUN device // Construct the TUN device
int tun_fd = open("/dev/net/tun", O_RDWR); int tun_fd = open("/dev/net/tun", O_RDWR);
@ -642,10 +642,16 @@ int setup_if_addr(char *ip_addr)
perror("ioctl"); perror("ioctl");
goto clean_exit; goto clean_exit;
} }
shutdown(sock, SHUT_RDWR);
return(tun_fd); return(tun_fd);
clean_exit: clean_exit:
close(tun_fd); if (sock != -1) {
shutdown(sock, SHUT_RDWR);
}
if (tun_fd != -1) {
close(tun_fd);
}
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }

View file

@ -113,7 +113,7 @@ private:
void run_thread(); void run_thread();
static const int MAC_MAIN_THREAD_PRIO = -1; // Use default high-priority below UHD static const int MAC_MAIN_THREAD_PRIO = -1; // Use default high-priority below UHD
static const int MAC_PDU_THREAD_PRIO = -1; static const int MAC_PDU_THREAD_PRIO = DEFAULT_PRIORITY-5;
static const int MAC_NOF_HARQ_PROC = 2*HARQ_DELAY_MS; static const int MAC_NOF_HARQ_PROC = 2*HARQ_DELAY_MS;
// Interaction with PHY // Interaction with PHY

View file

@ -145,8 +145,13 @@ public:
private: private:
class ul_harq_process { class ul_harq_process {
public: public:
ul_harq_process() ul_harq_process() {
{ pid = 0;
harq_feedback = false;
log_h = NULL;
bzero(&softbuffer, sizeof(srslte_softbuffer_tx_t));
is_msg3 = false;
pdu_ptr = NULL;
current_tx_nb = 0; current_tx_nb = 0;
current_irv = 0; current_irv = 0;
is_initiated = false; is_initiated = false;
@ -329,7 +334,7 @@ private:
// HARQ entity requests an adaptive transmission // HARQ entity requests an adaptive transmission
if (grant) { if (grant) {
if (grant->rv) { if (grant->rv[0]) {
current_irv = irv_of_rv[grant->rv[0]%4]; current_irv = irv_of_rv[grant->rv[0]%4];
} }

View file

@ -166,7 +166,7 @@ private:
typedef enum {IDLE, MEASURE_OK, ERROR} ret_code; typedef enum {IDLE, MEASURE_OK, ERROR} ret_code;
~measure(); ~measure();
void init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, void init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, srslte::radio *radio_h,
uint32_t nof_rx_antennas, uint32_t nof_subframes = RSRP_MEASURE_NOF_FRAMES); uint32_t nof_rx_antennas, uint32_t nof_subframes = RSRP_MEASURE_NOF_FRAMES);
void reset(); void reset();
void set_cell(srslte_cell_t cell); void set_cell(srslte_cell_t cell);
@ -182,11 +182,12 @@ private:
srslte::log *log_h; srslte::log *log_h;
srslte_ue_dl_t ue_dl; srslte_ue_dl_t ue_dl;
cf_t *buffer[SRSLTE_MAX_PORTS]; cf_t *buffer[SRSLTE_MAX_PORTS];
srslte::radio *radio_h;
uint32_t cnt; uint32_t cnt;
uint32_t nof_subframes; uint32_t nof_subframes;
uint32_t current_prb; uint32_t current_prb;
float rx_gain_offset; float rx_gain_offset;
float mean_rsrp, mean_rsrq, mean_snr; float mean_rsrp, mean_rsrq, mean_snr, mean_rssi;
uint32_t final_offset; uint32_t final_offset;
const static int RSRP_MEASURE_NOF_FRAMES = 5; const static int RSRP_MEASURE_NOF_FRAMES = 5;
}; };
@ -201,13 +202,11 @@ private:
float rsrq; float rsrq;
uint32_t offset; uint32_t offset;
} cell_info_t; } cell_info_t;
void init(srslte::log *log_h, bool sic_pss_enabled); void init(srslte::log *log_h, bool sic_pss_enabled, uint32_t max_sf_window);
void reset(); void reset();
int find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_cell_t current_cell, uint32_t nof_sf, cell_info_t found_cells[MAX_CELLS]); int find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_cell_t current_cell, uint32_t nof_sf, cell_info_t found_cells[MAX_CELLS]);
private: private:
const static int DEFAULT_MEASUREMENT_LEN = 10;
cf_t *input_cfo_corrected; cf_t *input_cfo_corrected;
cf_t *sf_buffer[SRSLTE_MAX_PORTS]; cf_t *sf_buffer[SRSLTE_MAX_PORTS];
srslte::log *log_h; srslte::log *log_h;
@ -235,8 +234,10 @@ private:
void write(uint32_t tti, cf_t *data, uint32_t nsamples); void write(uint32_t tti, cf_t *data, uint32_t nsamples);
private: private:
void run_thread(); void run_thread();
const static int CAPTURE_LEN_SF = 15; const static int INTRA_FREQ_MEAS_LEN_MS = 20;
const static int INTRA_FREQ_MEAS_PERIOD_MS = 200; const static int INTRA_FREQ_MEAS_PERIOD_MS = 200;
const static int INTRA_FREQ_MEAS_PRIO = DEFAULT_PRIORITY + 5;
scell_recv scell; scell_recv scell;
rrc_interface_phy *rrc; rrc_interface_phy *rrc;
srslte::log *log_h; srslte::log *log_h;
@ -260,6 +261,8 @@ private:
srslte_ringbuffer_t ring_buffer; srslte_ringbuffer_t ring_buffer;
}; };
// 36.133 9.1.2.1 for band 7
const static float ABSOLUTE_RSRP_THRESHOLD_DBM = -125;
// Objects for internal use // Objects for internal use

View file

@ -51,6 +51,58 @@ using srslte::byte_buffer_t;
namespace srsue { namespace srsue {
class cell_t
{
public:
bool is_valid() {
return earfcn != 0 && srslte_cell_isvalid(&phy_cell);
}
bool equals(cell_t *x) {
return equals(x->earfcn, x->phy_cell.id);
}
bool equals(uint32_t earfcn, uint32_t pci) {
return earfcn == this->earfcn && pci == phy_cell.id;
}
bool greater(cell_t *x) {
return x->rsrp > rsrp;
}
bool plmn_equals(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
for (uint32_t i = 0; i < sib1.N_plmn_ids; i++) {
if (plmn_id.mcc == sib1.plmn_id[i].id.mcc && plmn_id.mnc == sib1.plmn_id[i].id.mnc) {
return true;
}
}
return false;
}
cell_t() {
this->has_valid_sib1 = false;
this->has_valid_sib2 = false;
this->has_valid_sib3 = false;
}
cell_t(srslte_cell_t phy_cell, uint32_t earfcn, float rsrp) {
this->has_valid_sib1 = false;
this->has_valid_sib2 = false;
this->has_valid_sib3 = false;
this->phy_cell = phy_cell;
this->rsrp = rsrp;
this->earfcn = earfcn;
}
uint32_t earfcn;
srslte_cell_t phy_cell;
float rsrp;
bool has_valid_sib1;
bool has_valid_sib2;
bool has_valid_sib3;
bool has_valid_sib13;
bool in_sync;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT sib13;
};
class rrc class rrc
:public rrc_interface_nas :public rrc_interface_nas
,public rrc_interface_phy ,public rrc_interface_phy
@ -100,7 +152,7 @@ public:
void out_of_sync(); void out_of_sync();
void earfcn_end(); void earfcn_end();
void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp); void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp);
void new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, uint32_t pci); void new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn, int pci);
// MAC interface // MAC interface
void ho_ra_completed(bool ra_successful); void ho_ra_completed(bool ra_successful);
@ -154,7 +206,7 @@ private:
bool first_stimsi_attempt; bool first_stimsi_attempt;
uint16_t ho_src_rnti; uint16_t ho_src_rnti;
int ho_src_cell_idx; cell_t ho_src_cell;
phy_interface_rrc::phy_cfg_t ho_src_phy_cfg; phy_interface_rrc::phy_cfg_t ho_src_phy_cfg;
mac_interface_rrc::mac_cfg_t ho_src_mac_cfg; mac_interface_rrc::mac_cfg_t ho_src_mac_cfg;
bool pending_mob_reconf; bool pending_mob_reconf;
@ -215,28 +267,18 @@ private:
} }
} }
typedef struct { // List of strongest neighbour cell
uint32_t earfcn; const static int NOF_NEIGHBOUR_CELLS = 8;
srslte_cell_t phy_cell; std::vector<cell_t*> neighbour_cells;
float rsrp; cell_t *serving_cell;
bool has_valid_sib1; void set_serving_cell(uint32_t cell_idx);
bool has_valid_sib2; void set_serving_cell(uint32_t earfcn, uint32_t pci);
bool has_valid_sib3;
bool has_valid_sib13;
bool in_sync;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT sib13;
} cell_t;
const static int MAX_KNOWN_CELLS = 64; int find_neighbour_cell(uint32_t earfcn, uint32_t pci);
cell_t known_cells[MAX_KNOWN_CELLS]; bool add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp);
cell_t *current_cell; bool add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp);
bool add_neighbour_cell(cell_t *cell);
int find_cell_idx(uint32_t earfcn, uint32_t pci); void sort_neighbour_cells();
cell_t* add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp);
uint32_t find_best_cell(uint32_t earfcn, srslte_cell_t *cell);
typedef enum { typedef enum {
SI_ACQUIRE_IDLE = 0, SI_ACQUIRE_IDLE = 0,
@ -253,7 +295,6 @@ private:
void select_next_cell_in_plmn(); void select_next_cell_in_plmn();
LIBLTE_RRC_PLMN_IDENTITY_STRUCT selected_plmn_id; LIBLTE_RRC_PLMN_IDENTITY_STRUCT selected_plmn_id;
int last_selected_cell;
bool thread_running; bool thread_running;
void run_thread(); void run_thread();
@ -395,10 +436,10 @@ private:
// Helpers // Helpers
void ho_failed(); void ho_failed();
bool ho_prepare(); bool ho_prepare();
void add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp);
void rrc_connection_release(); void rrc_connection_release();
void con_restablish_cell_reselected(); void con_restablish_cell_reselected();
void radio_link_failure(); void radio_link_failure();
void leave_connected();
static void* start_sib_thread(void *rrc_); static void* start_sib_thread(void *rrc_);
void sib_search(); void sib_search();

View file

@ -242,7 +242,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
"After the PSS estimation is below cfo_loop_pss_tol for cfo_loop_pss_timeout times consecutively, RS adjustments are allowed.") "After the PSS estimation is below cfo_loop_pss_tol for cfo_loop_pss_timeout times consecutively, RS adjustments are allowed.")
("expert.sic_pss_enabled", ("expert.sic_pss_enabled",
bpo::value<bool>(&args->expert.phy.sic_pss_enabled)->default_value(true), bpo::value<bool>(&args->expert.phy.sic_pss_enabled)->default_value(false),
"Applies Successive Interference Cancellation to PSS signals when searching for neighbour cells. Must be disabled if cells have identical channel and timing.") "Applies Successive Interference Cancellation to PSS signals when searching for neighbour cells. Must be disabled if cells have identical channel and timing.")
("expert.average_subframe_enabled", ("expert.average_subframe_enabled",

View file

@ -91,7 +91,7 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma
sfn_p.init(&ue_sync, sf_buffer, log_h); sfn_p.init(&ue_sync, sf_buffer, log_h);
// Initialize measurement class for the primary cell // Initialize measurement class for the primary cell
measure_p.init(sf_buffer, log_h, nof_rx_antennas); measure_p.init(sf_buffer, log_h, radio_h, nof_rx_antennas);
// Start intra-frequency measurement // Start intra-frequency measurement
intra_freq_meas.init(worker_com, rrc, log_h); intra_freq_meas.init(worker_com, rrc, log_h);
@ -617,6 +617,7 @@ void phch_recv::run_thread()
log_h->info("Sync OK. Camping on cell PCI=%d...\n", cell.id); log_h->info("Sync OK. Camping on cell PCI=%d...\n", cell.id);
phy_state = CELL_CAMP; phy_state = CELL_CAMP;
} else { } else {
log_h->info("Sync OK. Measuring PCI=%d...\n", cell.id);
measure_p.reset(); measure_p.reset();
phy_state = CELL_MEASURE; phy_state = CELL_MEASURE;
} }
@ -1037,8 +1038,10 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c
/********* /*********
* Measurement class * Measurement class
*/ */
void phch_recv::measure::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t nof_subframes) void phch_recv::measure::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, srslte::radio *radio_h, uint32_t nof_rx_antennas, uint32_t nof_subframes)
{ {
this->radio_h = radio_h;
this->log_h = log_h; this->log_h = log_h;
this->nof_subframes = nof_subframes; this->nof_subframes = nof_subframes;
for (int i=0;i<SRSLTE_MAX_PORTS;i++) { for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
@ -1061,6 +1064,7 @@ void phch_recv::measure::reset() {
mean_rsrp = 0; mean_rsrp = 0;
mean_rsrq = 0; mean_rsrq = 0;
mean_snr = 0; mean_snr = 0;
mean_rssi = 0;
} }
void phch_recv::measure::set_cell(srslte_cell_t cell) void phch_recv::measure::set_cell(srslte_cell_t cell)
@ -1121,7 +1125,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in
sf_idx ++; sf_idx ++;
} }
float max_rsrp = -99; float max_rsrp = -200;
int best_test_offset = 0; int best_test_offset = 0;
int test_offset = 0; int test_offset = 0;
bool found_best = false; bool found_best = false;
@ -1182,16 +1186,18 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx)
float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30 - rx_gain_offset; float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30 - rx_gain_offset;
float rsrq = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest)); float rsrq = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest));
float snr = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)); float snr = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest));
float rssi = 10*log10(srslte_vec_avg_power_cf(buffer[0], SRSLTE_SF_LEN_PRB(current_prb))) + 30;
if (cnt == 0) { if (cnt == 0) {
mean_rsrp = rsrp; mean_rsrp = rsrp;
mean_rsrq = rsrq; mean_rsrq = rsrq;
mean_snr = snr; mean_snr = snr;
mean_rssi = rssi;
} else { } else {
mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt); mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt);
mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt); mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt);
mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt); mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt);
mean_rssi = SRSLTE_VEC_CMA(rssi, mean_rssi, cnt);
} }
cnt++; cnt++;
@ -1199,6 +1205,20 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx)
cnt, nof_subframes, sf_idx, rsrp, snr); cnt, nof_subframes, sf_idx, rsrp, snr);
if (cnt >= nof_subframes) { if (cnt >= nof_subframes) {
// Calibrate RSRP if no gain offset measurements
if (rx_gain_offset == 0 && radio_h) {
float temporal_offset = 0;
if (radio_h->has_rssi()) {
temporal_offset = mean_rssi - radio_h->get_rssi() + 30;
} else {
temporal_offset = radio_h->get_rx_gain();
}
mean_rsrp -= temporal_offset;
}
}
if (cnt > 2) {
return MEASURE_OK; return MEASURE_OK;
} else { } else {
return IDLE; return IDLE;
@ -1214,7 +1234,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx)
* Secondary cell receiver * Secondary cell receiver
*/ */
void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled) void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint32_t max_sf_window)
{ {
this->log_h = log_h; this->log_h = log_h;
this->sic_pss_enabled = sic_pss_enabled; this->sic_pss_enabled = sic_pss_enabled;
@ -1227,23 +1247,24 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled)
sf_buffer[0] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*max_sf_size); sf_buffer[0] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*max_sf_size);
input_cfo_corrected = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*15*max_sf_size); input_cfo_corrected = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*15*max_sf_size);
measure_p.init(sf_buffer, log_h, 1, DEFAULT_MEASUREMENT_LEN); measure_p.init(sf_buffer, log_h, NULL, 1, max_sf_window);
//do this different we don't need all this search window. //do this different we don't need all this search window.
if(srslte_sync_init(&sync_find, 50*max_sf_size, 5*max_sf_size, max_fft_sz)) { if(srslte_sync_init(&sync_find, max_sf_window*max_sf_size, 5*max_sf_size, max_fft_sz)) {
fprintf(stderr, "Error initiating sync_find\n"); fprintf(stderr, "Error initiating sync_find\n");
return; return;
} }
srslte_sync_cp_en(&sync_find, false); srslte_sync_cp_en(&sync_find, false);
srslte_sync_set_threshold(&sync_find, 1.2); srslte_sync_set_cfo_pss_enable(&sync_find, true);
srslte_sync_set_em_alpha(&sync_find, 0.0); srslte_sync_set_threshold(&sync_find, 1.7);
srslte_sync_set_em_alpha(&sync_find, 0.3);
// Configure FIND object behaviour (this configuration is always the same) // Configure FIND object behaviour (this configuration is always the same)
srslte_sync_set_cfo_ema_alpha(&sync_find, 1.0); srslte_sync_set_cfo_ema_alpha(&sync_find, 1.0);
srslte_sync_set_cfo_i_enable(&sync_find, false); srslte_sync_set_cfo_i_enable(&sync_find, false);
srslte_sync_set_cfo_pss_enable(&sync_find, true); srslte_sync_set_cfo_pss_enable(&sync_find, true);
srslte_sync_set_pss_filt_enable(&sync_find, true); srslte_sync_set_pss_filt_enable(&sync_find, true);
srslte_sync_set_sss_eq_enable(&sync_find, true); srslte_sync_set_sss_eq_enable(&sync_find, false);
sync_find.pss.chest_on_filter = true; sync_find.pss.chest_on_filter = true;
@ -1280,39 +1301,55 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset,
srslte_cell_t found_cell; srslte_cell_t found_cell;
memcpy(&found_cell, &cell, sizeof(srslte_cell_t)); memcpy(&found_cell, &cell, sizeof(srslte_cell_t));
found_cell.id = 10000;
measure_p.set_rx_gain_offset(rx_gain_offset); measure_p.set_rx_gain_offset(rx_gain_offset);
for (uint32_t n_id_2=0;n_id_2<3;n_id_2++) { for (uint32_t n_id_2=0;n_id_2<3;n_id_2++) {
found_cell.id = 10000;
if (n_id_2 != (cell.id%3) || sic_pss_enabled) { if (n_id_2 != (cell.id%3) || sic_pss_enabled) {
srslte_sync_set_N_id_2(&sync_find, n_id_2); srslte_sync_set_N_id_2(&sync_find, n_id_2);
srslte_sync_find_ret_t sync_res; srslte_sync_find_ret_t sync_res, best_sync_res;
do { do {
srslte_sync_reset(&sync_find); srslte_sync_reset(&sync_find);
srslte_sync_cfo_reset(&sync_find); srslte_sync_cfo_reset(&sync_find);
int sf5_cnt=-1; best_sync_res = SRSLTE_SYNC_NOFOUND;
do { sync_res = SRSLTE_SYNC_NOFOUND;
sf5_cnt++; cell_id = 0;
sync_res = srslte_sync_find(&sync_find, input_buffer, sf5_cnt*5*sf_len, &peak_idx); float max_peak = -1;
} while(sync_res != SRSLTE_SYNC_FOUND && (uint32_t) sf5_cnt + 1 < nof_sf/5); uint32_t max_sf5 = 0;
uint32_t max_sf_idx = 0;
switch(sync_res) { for (uint32_t sf5_cnt=0;sf5_cnt<nof_sf/5;sf5_cnt++) {
sync_res = srslte_sync_find(&sync_find, input_buffer, sf5_cnt*5*sf_len, &peak_idx);
Info("INTRA: n_id_2=%d, cnt=%d/%d, sync_res=%d, sf_idx=%d, peak_idx=%d, peak_value=%f\n",
n_id_2, sf5_cnt, nof_sf/5, sync_res, srslte_sync_get_sf_idx(&sync_find), peak_idx, sync_find.peak_value);
if (sync_find.peak_value > max_peak && sync_res == SRSLTE_SYNC_FOUND) {
best_sync_res = sync_res;
max_sf5 = sf5_cnt;
max_sf_idx = srslte_sync_get_sf_idx(&sync_find);
cell_id = srslte_sync_get_cell_id(&sync_find);
}
}
switch(best_sync_res) {
case SRSLTE_SYNC_ERROR: case SRSLTE_SYNC_ERROR:
return SRSLTE_ERROR; return SRSLTE_ERROR;
fprintf(stderr, "Error finding correlation peak\n"); fprintf(stderr, "Error finding correlation peak\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
case SRSLTE_SYNC_FOUND: case SRSLTE_SYNC_FOUND:
sf_idx = srslte_sync_get_sf_idx(&sync_find);
cell_id = srslte_sync_get_cell_id(&sync_find); sf_idx = (10-max_sf_idx - 5*(max_sf5%2))%10;
if (cell_id >= 0) { if (cell_id >= 0) {
// We found the same cell as before, look another N_id_2 // We found the same cell as before, look another N_id_2
if ((uint32_t) cell_id == found_cell.id || (uint32_t) cell_id == cell.id) { if ((uint32_t) cell_id == found_cell.id || (uint32_t) cell_id == cell.id) {
Info("n_id_2=%d, PCI=%d, found_cell.id=%d, cell.id=%d\n", n_id_2, cell_id, found_cell.id, cell.id);
sync_res = SRSLTE_SYNC_NOFOUND; sync_res = SRSLTE_SYNC_NOFOUND;
} else { } else {
// We found a new cell ID // We found a new cell ID
@ -1321,34 +1358,42 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset,
measure_p.set_cell(found_cell); measure_p.set_cell(found_cell);
// Correct CFO // Correct CFO
/*
srslte_cfo_correct(&sync_find.cfo_corr_frame, srslte_cfo_correct(&sync_find.cfo_corr_frame,
input_buffer, input_buffer,
input_cfo_corrected, input_cfo_corrected,
-srslte_sync_get_cfo(&sync_find)/sync_find.fft_size); -srslte_sync_get_cfo(&sync_find)/sync_find.fft_size);
*/
switch(measure_p.run_multiple_subframes(input_buffer, peak_idx, sf_idx, nof_sf))
switch(measure_p.run_multiple_subframes(input_cfo_corrected, peak_idx+sf5_cnt*5*sf_len, sf_idx, nof_sf)) { {
case measure::MEASURE_OK: case measure::MEASURE_OK:
cells[nof_cells].pci = found_cell.id; // Consider a cell to be detectable 8.1.2.2.1.1 from 36.133. Currently only using first condition
cells[nof_cells].rsrp = measure_p.rsrp(); if (measure_p.rsrp() > ABSOLUTE_RSRP_THRESHOLD_DBM) {
cells[nof_cells].rsrq = measure_p.rsrq(); cells[nof_cells].pci = found_cell.id;
cells[nof_cells].offset = measure_p.frame_st_idx(); cells[nof_cells].rsrp = measure_p.rsrp();
cells[nof_cells].rsrq = measure_p.rsrq();
cells[nof_cells].offset = measure_p.frame_st_idx();
Info("INTRA: Found neighbour cell %d: PCI=%03d, RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f, sf5_cnt=%d, n_id_2=%d, CFO=%6.1f Hz\n", Info(
nof_cells, cell_id, measure_p.rsrp(), measure_p.frame_st_idx(), sync_find.peak_value, sf5_cnt, n_id_2, 15000*srslte_sync_get_cfo(&sync_find)); "INTRA: Found neighbour cell %d: PCI=%03d, RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f, sf=%d, max_sf=%d, n_id_2=%d, CFO=%6.1f Hz\n",
nof_cells, cell_id, measure_p.rsrp(), measure_p.frame_st_idx(), sync_find.peak_value,
sf_idx, max_sf5, n_id_2, 15000 * srslte_sync_get_cfo(&sync_find));
nof_cells++; nof_cells++;
if (sic_pss_enabled) { /*
srslte_pss_sic(&sync_find.pss, &input_buffer[sf5_cnt*5*sf_len+sf_len/2-fft_sz]); if (sic_pss_enabled) {
srslte_pss_sic(&sync_find.pss, &input_buffer[sf5_cnt * 5 * sf_len + sf_len / 2 - fft_sz]);
}*/
} }
break;
default:
Info("INTRA: Not enough samples to measure PCI=%d\n", cell_id);
break; break;
case measure::ERROR: case measure::ERROR:
Error("Measuring neighbour cell\n"); Error("Measuring neighbour cell\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
default:
break;
} }
} }
} else { } else {
@ -1414,20 +1459,21 @@ void phch_recv::intra_measure::init(phch_common *common, rrc_interface_phy *rrc,
receive_enabled = false; receive_enabled = false;
// Start scell // Start scell
scell.init(log_h, common->args->sic_pss_enabled); scell.init(log_h, common->args->sic_pss_enabled, INTRA_FREQ_MEAS_LEN_MS);
search_buffer = (cf_t*) srslte_vec_malloc(CAPTURE_LEN_SF*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB)*sizeof(cf_t)); search_buffer = (cf_t*) srslte_vec_malloc(INTRA_FREQ_MEAS_LEN_MS*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB)*sizeof(cf_t));
if (srslte_ringbuffer_init(&ring_buffer, sizeof(cf_t)*100*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) { if (srslte_ringbuffer_init(&ring_buffer, sizeof(cf_t)*INTRA_FREQ_MEAS_LEN_MS*2*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) {
return; return;
} }
running = true; running = true;
start(); start(INTRA_FREQ_MEAS_PRIO);
} }
void phch_recv::intra_measure::stop() { void phch_recv::intra_measure::stop() {
running = false; running = false;
srslte_ringbuffer_stop(&ring_buffer);
tti_sync.increase(); tti_sync.increase();
wait_thread_finish(); wait_thread_finish();
} }
@ -1480,7 +1526,6 @@ void phch_recv::intra_measure::rem_cell(int pci) {
} }
void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples) { void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples) {
/*
if (receive_enabled) { if (receive_enabled) {
if ((tti%INTRA_FREQ_MEAS_PERIOD_MS) == 0) { if ((tti%INTRA_FREQ_MEAS_PERIOD_MS) == 0) {
receiving = true; receiving = true;
@ -1494,14 +1539,13 @@ void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples
receiving = false; receiving = false;
} else { } else {
receive_cnt++; receive_cnt++;
if (receive_cnt == CAPTURE_LEN_SF) { if (receive_cnt == INTRA_FREQ_MEAS_LEN_MS) {
tti_sync.increase(); tti_sync.increase();
receiving = false; receiving = false;
} }
} }
} }
} }
*/
} }
void phch_recv::intra_measure::run_thread() void phch_recv::intra_measure::run_thread()
@ -1512,15 +1556,14 @@ void phch_recv::intra_measure::run_thread()
} }
if (running) { if (running) {
// Read 15 ms data from buffer // Read data from buffer and find cells in it
/* srslte_ringbuffer_read(&ring_buffer, search_buffer, INTRA_FREQ_MEAS_LEN_MS*current_sflen*sizeof(cf_t));
srslte_ringbuffer_read(&ring_buffer, search_buffer, CAPTURE_LEN_SF*current_sflen*sizeof(cf_t)); int found_cells = scell.find_cells(search_buffer, common->rx_gain_offset, primary_cell, INTRA_FREQ_MEAS_LEN_MS, info);
int found_cells = scell.find_cells(search_buffer, common->rx_gain_offset, primary_cell, CAPTURE_LEN_SF, info);
receiving = false; receiving = false;
for (int i=0;i<found_cells;i++) { for (int i=0;i<found_cells;i++) {
rrc->new_phy_meas(info[i].rsrp, info[i].rsrq, measure_tti, current_earfcn, info[i].pci); rrc->new_phy_meas(info[i].rsrp, info[i].rsrq, measure_tti, current_earfcn, info[i].pci);
}*/ }
// Look for other cells not found automatically // Look for other cells not found automatically
} }
} }

View file

@ -476,10 +476,10 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
srslte_ra_dl_dci_t dci_unpacked; srslte_ra_dl_dci_t dci_unpacked;
Debug("Looking for RNTI=0x%x\n", dl_rnti); Debug("Looking for RNTI=0x%x\n", dl_rnti);
if (srslte_ue_dl_find_dl_dci_type(&ue_dl, phy->config->dedicated.antenna_info_explicit_value.tx_mode, cfi, tti%10, if (srslte_ue_dl_find_dl_dci_type(&ue_dl, phy->config->dedicated.antenna_info_explicit_value.tx_mode, cfi, tti%10,
dl_rnti, type, &dci_msg) != 1) { dl_rnti, type, &dci_msg) != 1) {
return false; return false;
} }
if (srslte_dci_msg_to_dl_grant(&dci_msg, dl_rnti, cell.nof_prb, cell.nof_ports, &dci_unpacked, &grant->phy_grant.dl)) { if (srslte_dci_msg_to_dl_grant(&dci_msg, dl_rnti, cell.nof_prb, cell.nof_ports, &dci_unpacked, &grant->phy_grant.dl)) {
@ -743,7 +743,7 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
ul_rnti = phy->get_ul_rnti(tti); ul_rnti = phy->get_ul_rnti(tti);
if (ul_rnti) { if (ul_rnti) {
if (srslte_ue_dl_find_ul_dci(&ue_dl, cfi, tti%10, ul_rnti, &dci_msg) != 1) { if (srslte_ue_dl_find_ul_dci(&ue_dl, cfi, tti%10, ul_rnti, &dci_msg) != 1) {
return false; return false;
} }
if (srslte_dci_msg_to_ul_grant(&dci_msg, cell.nof_prb, pusch_hopping.hopping_offset, if (srslte_dci_msg_to_ul_grant(&dci_msg, cell.nof_prb, pusch_hopping.hopping_offset,
@ -1386,7 +1386,7 @@ void phch_worker::update_measurements()
phy->avg_rsrp_dbm = SRSLTE_VEC_EMA(rsrp_dbm, phy->avg_rsrp_dbm, snr_ema_coeff); phy->avg_rsrp_dbm = SRSLTE_VEC_EMA(rsrp_dbm, phy->avg_rsrp_dbm, snr_ema_coeff);
} }
if ((tti%phy->pcell_report_period) == 0 && phy->pcell_meas_enabled) { if ((tti%phy->pcell_report_period) == 0 && phy->pcell_meas_enabled) {
//phy->rrc->new_phy_meas(phy->avg_rsrp_dbm, phy->avg_rsrq_db, tti); phy->rrc->new_phy_meas(phy->avg_rsrp_dbm, phy->avg_rsrq_db, tti);
} }
} }

View file

@ -52,6 +52,7 @@ rrc::rrc()
{ {
n310_cnt = 0; n310_cnt = 0;
n311_cnt = 0; n311_cnt = 0;
serving_cell = new cell_t();
} }
static void liblte_rrc_handler(void *ctx, char *str) { static void liblte_rrc_handler(void *ctx, char *str) {
@ -89,8 +90,6 @@ void rrc::init(phy_interface_rrc *phy_,
state = RRC_STATE_IDLE; state = RRC_STATE_IDLE;
si_acquire_state = SI_ACQUIRE_IDLE; si_acquire_state = SI_ACQUIRE_IDLE;
bzero(known_cells, MAX_KNOWN_CELLS*sizeof(cell_t));
thread_running = true; thread_running = true;
start(); start();
@ -210,13 +209,13 @@ void rrc::run_thread() {
* Cell is selected when all SIBs downloaded or applied. * Cell is selected when all SIBs downloaded or applied.
*/ */
if (phy->sync_status()) { if (phy->sync_status()) {
if (!current_cell->has_valid_sib1) { if (!serving_cell->has_valid_sib1) {
si_acquire_state = SI_ACQUIRE_SIB1; si_acquire_state = SI_ACQUIRE_SIB1;
sysinfo_index = 0; sysinfo_index = 0;
} else if (!current_cell->has_valid_sib2) { } else if (!serving_cell->has_valid_sib2) {
si_acquire_state = SI_ACQUIRE_SIB2; si_acquire_state = SI_ACQUIRE_SIB2;
} else { } else {
apply_sib2_configs(&current_cell->sib2); apply_sib2_configs(&serving_cell->sib2);
si_acquire_state = SI_ACQUIRE_IDLE; si_acquire_state = SI_ACQUIRE_IDLE;
state = RRC_STATE_CELL_SELECTED; state = RRC_STATE_CELL_SELECTED;
} }
@ -228,6 +227,7 @@ void rrc::run_thread() {
rrc_log->info("RRC Cell Selecting: timeout expired. Starting Cell Search...\n"); rrc_log->info("RRC Cell Selecting: timeout expired. Starting Cell Search...\n");
plmn_select_timeout = 0; plmn_select_timeout = 0;
select_cell_timeout = 0; select_cell_timeout = 0;
serving_cell->in_sync = false;
phy->cell_search_start(); phy->cell_search_start();
} }
} }
@ -254,7 +254,7 @@ void rrc::run_thread() {
} else { } else {
rrc_log->info("RRC Cell Selected: Starting paging and going to IDLE...\n"); rrc_log->info("RRC Cell Selected: Starting paging and going to IDLE...\n");
mac->pcch_start_rx(); mac->pcch_start_rx();
state = RRC_STATE_IDLE; state = RRC_STATE_LEAVE_CONNECTED;
} }
break; break;
case RRC_STATE_CONNECTING: case RRC_STATE_CONNECTING:
@ -287,25 +287,7 @@ void rrc::run_thread() {
break; break;
case RRC_STATE_LEAVE_CONNECTED: case RRC_STATE_LEAVE_CONNECTED:
usleep(60000); usleep(60000);
rrc_log->console("RRC IDLE\n"); leave_connected();
rrc_log->info("Leaving RRC_CONNECTED state\n");
drb_up = false;
measurements.reset();
pdcp->reset();
rlc->reset();
phy->reset();
mac->reset();
set_phy_default();
set_mac_default();
mac_timers->timer_get(t310)->stop();
mac_timers->timer_get(t311)->stop();
if (phy->sync_status()) {
// Instruct MAC to look for P-RNTI
mac->pcch_start_rx();
// Instruct PHY to measure serving cell for cell reselection
phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci());
}
// Move to RRC_IDLE // Move to RRC_IDLE
state = RRC_STATE_IDLE; state = RRC_STATE_IDLE;
break; break;
@ -370,19 +352,19 @@ void rrc::run_si_acquisition_procedure()
break; break;
case SI_ACQUIRE_SIB2: case SI_ACQUIRE_SIB2:
// Instruct MAC to look for next SIB // Instruct MAC to look for next SIB
if(sysinfo_index < current_cell->sib1.N_sched_info) { if(sysinfo_index < serving_cell->sib1.N_sched_info) {
si_win_len = liblte_rrc_si_window_length_num[current_cell->sib1.si_window_length]; si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length];
x = sysinfo_index*si_win_len; x = sysinfo_index*si_win_len;
sf = x%10; sf = x%10;
offset = x/10; offset = x/10;
tti = mac->get_current_tti(); tti = mac->get_current_tti();
period = liblte_rrc_si_periodicity_num[current_cell->sib1.sched_info[sysinfo_index].si_periodicity]; period = liblte_rrc_si_periodicity_num[serving_cell->sib1.sched_info[sysinfo_index].si_periodicity];
si_win_start = sib_start_tti(tti, period, offset, sf); si_win_start = sib_start_tti(tti, period, offset, sf);
if (tti > last_win_start + 10) { if (tti > last_win_start + 10) {
last_win_start = si_win_start; last_win_start = si_win_start;
si_win_len = liblte_rrc_si_window_length_num[current_cell->sib1.si_window_length]; si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length];
mac->bcch_start_rx(si_win_start, si_win_len); mac->bcch_start_rx(si_win_start, si_win_len);
rrc_log->debug("Instructed MAC to search for system info, win_start=%d, win_len=%d\n", rrc_log->debug("Instructed MAC to search for system info, win_start=%d, win_len=%d\n",
@ -421,19 +403,15 @@ void rrc::run_si_acquisition_procedure()
*******************************************************************************/ *******************************************************************************/
uint16_t rrc::get_mcc() { uint16_t rrc::get_mcc() {
if (current_cell) { if (serving_cell->sib1.N_plmn_ids > 0) {
if (current_cell->sib1.N_plmn_ids > 0) { return serving_cell->sib1.plmn_id[0].id.mcc;
return current_cell->sib1.plmn_id[0].id.mcc;
}
} }
return 0; return 0;
} }
uint16_t rrc::get_mnc() { uint16_t rrc::get_mnc() {
if (current_cell) { if (serving_cell->sib1.N_plmn_ids > 0) {
if (current_cell->sib1.N_plmn_ids > 0) { return serving_cell->sib1.plmn_id[0].id.mnc;
return current_cell->sib1.plmn_id[0].id.mnc;
}
} }
return 0; return 0;
} }
@ -468,188 +446,263 @@ void rrc::plmn_select_rrc(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
// Sort cells according to RSRP // Sort cells according to RSRP
selected_plmn_id = plmn_id; selected_plmn_id = plmn_id;
last_selected_cell = -1;
select_cell_timeout = 0; select_cell_timeout = 0;
state = RRC_STATE_CELL_SELECTING; state = RRC_STATE_CELL_SELECTING;
select_next_cell_in_plmn();
} }
} else { } else {
rrc_log->warning("Requested PLMN select in incorrect state %s\n", rrc_state_text[state]); rrc_log->warning("Requested PLMN select in incorrect state %s\n", rrc_state_text[state]);
} }
} }
void rrc::select_next_cell_in_plmn() { void rrc::set_serving_cell(uint32_t earfcn, uint32_t pci) {
for (uint32_t i = last_selected_cell + 1; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; i++) { int cell_idx = find_neighbour_cell(earfcn, pci);
for (uint32_t j = 0; j < known_cells[i].sib1.N_plmn_ids; j++) { if (cell_idx >= 0) {
if (known_cells[i].sib1.plmn_id[j].id.mcc == selected_plmn_id.mcc || set_serving_cell(cell_idx);
known_cells[i].sib1.plmn_id[j].id.mnc == selected_plmn_id.mnc) { } else {
rrc_log->info("Selecting cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n", rrc_log->error("Setting serving cell: Unkonwn cell with earfcn=%d, PCI=%d\n", earfcn, pci);
known_cells[i].phy_cell.id, known_cells[i].earfcn, }
known_cells[i].sib1.cell_id); }
rrc_log->console("Select cell: PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
known_cells[i].phy_cell.id, known_cells[i].earfcn, void rrc::set_serving_cell(uint32_t cell_idx) {
known_cells[i].sib1.cell_id); if (cell_idx < neighbour_cells.size())
// Check that cell satisfies S criteria {
if (known_cells[i].in_sync) { // %% rsrp > S dbm // Remove future serving cell from neighbours to make space for current serving cell
// Try to select Cell cell_t *new_serving_cell = neighbour_cells[cell_idx];
if (phy->cell_select(known_cells[i].earfcn, known_cells[i].phy_cell)) if (!new_serving_cell) {
{ rrc_log->error("Setting serving cell. Index %d is empty\n", cell_idx);
last_selected_cell = i; return;
current_cell = &known_cells[i]; }
rrc_log->info("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x, addr=0x%x\n", neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[cell_idx]), neighbour_cells.end());
current_cell->phy_cell.id, current_cell->earfcn,
current_cell->sib1.cell_id, current_cell); // Move serving cell to neighbours list
return; if (serving_cell->is_valid()) {
} else { // Make sure it does not exist already
rrc_log->warning("Selecting cell EARFCN=%d, Cell ID=0x%x.\n", int serving_idx = find_neighbour_cell(serving_cell->earfcn, serving_cell->phy_cell.id);
known_cells[i].earfcn, known_cells[i].sib1.cell_id); if (serving_idx >= 0 && (uint32_t) serving_idx < neighbour_cells.size()) {
} printf("Error serving cell is already in the neighbour list. Removing it\n");
} neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[serving_idx]), neighbour_cells.end());
} }
// If not in the list, add it to the list of neighbours (sorted inside the function)
if (!add_neighbour_cell(serving_cell)) {
rrc_log->info("Serving cell not added to list of neighbours. Worse than current neighbours\n");
}
}
// Set new serving cell
serving_cell = new_serving_cell;
rrc_log->info("Setting serving cell idx=%d, earfcn=%d, PCI=%d, nof_neighbours=%d\n",
cell_idx, serving_cell->earfcn, serving_cell->phy_cell.id, neighbour_cells.size());
} else {
rrc_log->error("Setting invalid serving cell idx %d\n", cell_idx);
}
}
void rrc::select_next_cell_in_plmn() {
// Neighbour cells are sorted in descending order of RSRP
for (uint32_t i = 0; i < neighbour_cells.size(); i++) {
if (neighbour_cells[i]->plmn_equals(selected_plmn_id) &&
neighbour_cells[i]->in_sync) // matches S criteria
{
// Try to select Cell
if (phy->cell_select(neighbour_cells[i]->earfcn, neighbour_cells[i]->phy_cell)) {
set_serving_cell(i);
rrc_log->info("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
serving_cell->phy_cell.id, serving_cell->earfcn,
serving_cell->sib1.cell_id);
rrc_log->console("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
serving_cell->phy_cell.id, serving_cell->earfcn,
serving_cell->sib1.cell_id);
} else {
// Set to out-of-sync if can't synchronize
neighbour_cells[i]->in_sync = false;
rrc_log->warning("Selecting cell EARFCN=%d, Cell ID=0x%x.\n",
neighbour_cells[i]->earfcn, neighbour_cells[i]->sib1.cell_id);
}
return;
} }
} }
rrc_log->info("No more known cells. Starting again\n"); rrc_log->info("No more known cells. Starting again\n");
last_selected_cell = -1;
} }
void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, uint32_t pci) { void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int pci_i) {
if (earfcn_i < 0 || pci_i < 0) {
earfcn_i = serving_cell->earfcn;
pci_i = serving_cell->phy_cell.id;
}
uint32_t earfcn = (uint32_t) earfcn_i;
uint32_t pci = (uint32_t) pci_i;
// Measurements in RRC_CONNECTED go through measuremnt class to log reports etc.
if (state != RRC_STATE_IDLE) { if (state != RRC_STATE_IDLE) {
measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti);
} else {
// If measurement is of the serving cell, evaluate cell reselection criteria
if ((earfcn == phy->get_current_earfcn() && pci == phy->get_current_pci()) || (earfcn == 0 && pci == 0)) {
cell_reselection_eval(rsrp, rsrq);
current_cell->rsrp = rsrp;
rrc_log->info("MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti);
} else {
// Add/update cell measurement
srslte_cell_t cell;
phy->get_current_cell(&cell, NULL);
cell.id = pci;
add_new_cell(earfcn, cell, rsrp);
rrc_log->info("MEAS: New measurement PCI=%d, RSRP=%.1f dBm.\n", pci, rsrp); // Measurements in RRC_IDLE update serving cell and check for reselection
} else {
// Update serving cell
if (serving_cell->equals(earfcn, pci)) {
cell_reselection_eval(rsrp, rsrq);
serving_cell->rsrp = rsrp;
rrc_log->info("MEAS: New measurement serving cell in IDLE, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti);
// Or update/add neighbour cell
} else {
if (add_neighbour_cell(earfcn, pci, rsrp)) {
rrc_log->info("MEAS: New measurement neighbour in IDLE, PCI=%d, RSRP=%.1f dBm.\n", pci, rsrp);
} else {
rrc_log->info("MEAS: Neighbour Cell in IDLE PCI=%d, RSRP=%.1f dBm not added. Worse than current neighbours\n", pci, rsrp);
}
} }
srslte_cell_t best_cell; // Verify cell selection criteria with strongest neighbour cell (always first)
uint32_t best_cell_idx = find_best_cell(phy->get_current_earfcn(), &best_cell); if (cell_selection_eval(neighbour_cells[0]->rsrp) &&
neighbour_cells[0]->rsrp > serving_cell->rsrp + 5)
// Verify cell selection criteria
if (cell_selection_eval(known_cells[best_cell_idx].rsrp) &&
known_cells[best_cell_idx].rsrp > current_cell->rsrp + 5 &&
best_cell.id != phy->get_current_pci())
{ {
rrc_log->info("Selecting best neighbour cell PCI=%d, rsrp=%.1f dBm\n", best_cell.id, known_cells[best_cell_idx].rsrp); set_serving_cell(0);
rrc_log->info("Selecting best neighbour cell PCI=%d, rsrp=%.1f dBm\n", serving_cell->phy_cell.id, serving_cell->rsrp);
state = RRC_STATE_CELL_SELECTING; state = RRC_STATE_CELL_SELECTING;
current_cell = &known_cells[best_cell_idx]; phy->cell_select(serving_cell->earfcn, serving_cell->phy_cell);
phy->cell_select(phy->get_current_earfcn(), best_cell);
} }
} }
} }
void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
// find if cell_id-earfcn combination already exists bool found = false;
for (uint32_t i = 0; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; i++) { int cell_idx = -1;
if (earfcn == known_cells[i].earfcn && phy_cell.id == known_cells[i].phy_cell.id) {
current_cell = &known_cells[i]; if (serving_cell->equals(earfcn, phy_cell.id)) {
current_cell->rsrp = rsrp; serving_cell->rsrp = rsrp;
current_cell->in_sync = true; serving_cell->in_sync = true;
rrc_log->info("Updating cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n", current_cell->earfcn, found = true;
current_cell->phy_cell.id, current_cell->rsrp); } else {
// Check if cell is in our list of neighbour cells
if (!current_cell->has_valid_sib1) { cell_idx = find_neighbour_cell(earfcn, phy_cell.id);
si_acquire_state = SI_ACQUIRE_SIB1; if (cell_idx >= 0) {
} else if (state == RRC_STATE_PLMN_SELECTION) { set_serving_cell(cell_idx);
for (uint32_t j = 0; j < current_cell->sib1.N_plmn_ids; j++) { serving_cell->rsrp = rsrp;
nas->plmn_found(current_cell->sib1.plmn_id[j].id, current_cell->sib1.tracking_area_code); serving_cell->in_sync = true;
} found = true;
usleep(5000);
phy->cell_search_next();
}
return;
} }
} }
// add to list of known cells and set current_cell if (found) {
current_cell = add_new_cell(earfcn, phy_cell, rsrp); rrc_log->info("Updating %s cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n",
if(!current_cell) { cell_idx>=0?"neighbour":"serving",
current_cell = &known_cells[0]; serving_cell->earfcn,
rrc_log->error("Couldn't add new cell\n"); serving_cell->phy_cell.id,
return; serving_cell->rsrp);
}
if (!serving_cell->has_valid_sib1) {
si_acquire_state = SI_ACQUIRE_SIB1; si_acquire_state = SI_ACQUIRE_SIB1;
} else if (state == RRC_STATE_PLMN_SELECTION) {
rrc_log->info("New Cell: PCI=%d, PRB=%d, Ports=%d, EARFCN=%d, RSRP=%.1f dBm, addr=0x%x\n", for (uint32_t j = 0; j < serving_cell->sib1.N_plmn_ids; j++) {
current_cell->phy_cell.id, current_cell->phy_cell.nof_prb, current_cell->phy_cell.nof_ports, nas->plmn_found(serving_cell->sib1.plmn_id[j].id, serving_cell->sib1.tracking_area_code);
current_cell->earfcn, current_cell->rsrp, current_cell);
}
uint32_t rrc::find_best_cell(uint32_t earfcn, srslte_cell_t *cell) {
float best_rsrp = -INFINITY;
uint32_t best_cell_idx = 0;
for (int i=0;i<MAX_KNOWN_CELLS;i++) {
if (known_cells[i].earfcn == earfcn) {
if (known_cells[i].rsrp > best_rsrp) {
best_rsrp = known_cells[i].rsrp;
best_cell_idx = i;
} }
usleep(5000);
phy->cell_search_next();
}
} else {
// add to list of known cells and set current_cell
if (!add_neighbour_cell(earfcn, phy_cell, rsrp)) {
rrc_log->info("No more space for neighbour cells (detected cell RSRP=%.1f dBm worse than current %d neighbours)\n",
rsrp, NOF_NEIGHBOUR_CELLS);
usleep(5000);
phy->cell_search_next();
} else {
set_serving_cell(earfcn, phy_cell.id);
si_acquire_state = SI_ACQUIRE_SIB1;
rrc_log->info("New Cell: PCI=%d, PRB=%d, Ports=%d, EARFCN=%d, RSRP=%.1f dBm\n",
serving_cell->phy_cell.id, serving_cell->phy_cell.nof_prb, serving_cell->phy_cell.nof_ports,
serving_cell->earfcn, serving_cell->rsrp);
} }
} }
if (cell) {
memcpy(cell, &known_cells[best_cell_idx].phy_cell, sizeof(srslte_cell_t));
}
return best_cell_idx;
} }
rrc::cell_t* rrc::add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { bool sort_rsrp(cell_t *u1, cell_t *u2) {
return !u1->greater(u2);
}
// Sort neighbour cells by decreasing order of RSRP
void rrc::sort_neighbour_cells() {
for (uint32_t i=1;i<neighbour_cells.size();i++) {
if (neighbour_cells[i]->in_sync == false) {
rrc_log->info("Removing neighbour cell PCI=%d, out_of_sync\n", neighbour_cells[i]->phy_cell.id);
neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[i]), neighbour_cells.end());
}
}
std::sort(neighbour_cells.begin(), neighbour_cells.end(), sort_rsrp);
char ordered[512];
int n=0;
n += snprintf(ordered, 512, "[pci=%d, rsrsp=%.2f", neighbour_cells[0]->phy_cell.id, neighbour_cells[0]->rsrp);
for (uint32_t i=1;i<neighbour_cells.size();i++) {
n += snprintf(&ordered[n], 512-n, " | pci=%d, rsrp=%.2f", neighbour_cells[i]->phy_cell.id, neighbour_cells[i]->rsrp);
}
rrc_log->info("Sorted neighbour cells: %s]\n", ordered);
}
bool rrc::add_neighbour_cell(cell_t *new_cell) {
bool ret = false;
if (neighbour_cells.size() < NOF_NEIGHBOUR_CELLS - 1) {
ret = true;
} else if (!neighbour_cells[neighbour_cells.size()-1]->greater(new_cell)) {
// Delete old one
delete neighbour_cells[neighbour_cells.size()-1];
neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[neighbour_cells.size()-1]), neighbour_cells.end());
ret = true;
}
if (ret) {
neighbour_cells.push_back(new_cell);
}
rrc_log->info("Added neighbour cell EARFCN=%d, PCI=%d, nof_neighbours=%d\n",
new_cell->earfcn, new_cell->phy_cell.id, neighbour_cells.size());
sort_neighbour_cells();
return ret;
}
// If only neighbour PCI is provided, copy full cell from serving cell
bool rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) {
srslte_cell_t serving_phy;
serving_phy = serving_cell->phy_cell;
serving_phy.id = pci;
return add_neighbour_cell(earfcn, serving_phy, rsrp);
}
bool rrc::add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
if (earfcn == 0) { if (earfcn == 0) {
return NULL; earfcn = serving_cell->earfcn;
}
int idx = find_cell_idx(earfcn, phy_cell.id);
if (idx >= 0) {
known_cells[idx].rsrp = rsrp;
return &known_cells[idx];
} }
// if does not exist, find empty slot // First check if already exists
int i=0; int cell_idx = find_neighbour_cell(earfcn, phy_cell.id);
while(i<MAX_KNOWN_CELLS && known_cells[i].earfcn) {
i++; rrc_log->info("Adding PCI=%d, earfcn=%d, cell_idx=%d\n", phy_cell.id, earfcn, cell_idx);
}
if (i==MAX_KNOWN_CELLS) { // If exists, update RSRP, sort again and return
rrc_log->error("Can't add more cells\n"); if (cell_idx >= 0) {
return NULL; neighbour_cells[cell_idx]->rsrp = rsrp;
sort_neighbour_cells();
return true;
} }
known_cells[i].phy_cell = phy_cell; // If not, create a new one
known_cells[i].rsrp = rsrp; cell_t *new_cell = new cell_t(phy_cell, earfcn, rsrp);
known_cells[i].earfcn = earfcn;
known_cells[i].has_valid_sib1 = false; return add_neighbour_cell(new_cell);
known_cells[i].has_valid_sib2 = false;
known_cells[i].has_valid_sib3 = false;
return &known_cells[i];
} }
void rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) { int rrc::find_neighbour_cell(uint32_t earfcn, uint32_t pci) {
int idx = find_cell_idx(earfcn, pci); for (uint32_t i = 0; i < neighbour_cells.size(); i++) {
if (idx >= 0) { if (neighbour_cells[i]->equals(earfcn, pci)) {
known_cells[idx].rsrp = rsrp;
return;
}
rrc_log->info("Added neighbour cell earfcn=%d, pci=%d, rsrp=%f\n", earfcn, pci, rsrp);
srslte_cell_t cell;
cell = current_cell->phy_cell;
cell.id = pci;
add_new_cell(earfcn, cell, rsrp);
}
int rrc::find_cell_idx(uint32_t earfcn, uint32_t pci) {
for (uint32_t i = 0; i < MAX_KNOWN_CELLS; i++) {
if (earfcn == known_cells[i].earfcn && pci == known_cells[i].phy_cell.id) {
return (int) i; return (int) i;
} }
} }
@ -720,24 +773,28 @@ float rrc::get_squal(float Qqualmeas) {
* *
*******************************************************************************/ *******************************************************************************/
// Detection of physical layer problems (5.3.11.1) // Detection of physical layer problems in RRC_CONNECTED (5.3.11.1)
void rrc::out_of_sync() { void rrc::out_of_sync() {
current_cell->in_sync = false; serving_cell->in_sync = false;
if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) { if (state == RRC_STATE_CONNECTED) {
n310_cnt++; if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) {
if (n310_cnt == N310) { n310_cnt++;
mac_timers->timer_get(t310)->reset(); if (n310_cnt == N310) {
mac_timers->timer_get(t310)->run(); mac_timers->timer_get(t310)->reset();
n310_cnt = 0; mac_timers->timer_get(t310)->run();
phy->sync_reset(); n310_cnt = 0;
rrc_log->info("Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer\n", N310); phy->sync_reset();
rrc_log->info("Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer\n", N310);
}
} }
} else {
phy->sync_reset();
} }
} }
// Recovery of physical layer problems (5.3.11.2) // Recovery of physical layer problems (5.3.11.2)
void rrc::in_sync() { void rrc::in_sync() {
current_cell->in_sync = true; serving_cell->in_sync = true;
if (mac_timers->timer_get(t310)->is_running()) { if (mac_timers->timer_get(t310)->is_running()) {
n311_cnt++; n311_cnt++;
if (n311_cnt == N311) { if (n311_cnt == N311) {
@ -861,7 +918,7 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause,
uint8_t *msg_ptr = varShortMAC; uint8_t *msg_ptr = varShortMAC;
// ASN.1 encode byte-aligned VarShortMAC-Input // ASN.1 encode byte-aligned VarShortMAC-Input
liblte_rrc_pack_cell_identity_ie(current_cell->sib1.cell_id, &msg_ptr); liblte_rrc_pack_cell_identity_ie(serving_cell->sib1.cell_id, &msg_ptr);
msg_ptr = &varShortMAC[4]; msg_ptr = &varShortMAC[4];
liblte_rrc_pack_phys_cell_id_ie(phy->get_current_pci(), &msg_ptr); liblte_rrc_pack_phys_cell_id_ie(phy->get_current_pci(), &msg_ptr);
msg_ptr = &varShortMAC[4+2]; msg_ptr = &varShortMAC[4+2];
@ -869,7 +926,7 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause,
srslte_bit_pack_vector(varShortMAC, varShortMAC_packed, (4+2+4)*8); srslte_bit_pack_vector(varShortMAC, varShortMAC_packed, (4+2+4)*8);
rrc_log->info("Generated varShortMAC: cellId=0x%x, PCI=%d, rnti=%d\n", rrc_log->info("Generated varShortMAC: cellId=0x%x, PCI=%d, rnti=%d\n",
current_cell->sib1.cell_id, phy->get_current_pci(), crnti); serving_cell->sib1.cell_id, phy->get_current_pci(), crnti);
// Compute MAC-I // Compute MAC-I
uint8_t mac_key[4]; uint8_t mac_key[4];
@ -997,9 +1054,9 @@ bool rrc::ho_prepare() {
if (pending_mob_reconf) { if (pending_mob_reconf) {
rrc_log->info("Processing HO command to target PCell=%d\n", mob_reconf.mob_ctrl_info.target_pci); rrc_log->info("Processing HO command to target PCell=%d\n", mob_reconf.mob_ctrl_info.target_pci);
int cell_idx = find_cell_idx(phy->get_current_earfcn(), mob_reconf.mob_ctrl_info.target_pci); int target_cell_idx = find_neighbour_cell(serving_cell->earfcn, mob_reconf.mob_ctrl_info.target_pci);
if (cell_idx < 0) { if (target_cell_idx < 0) {
rrc_log->error("Could not find target cell pci=%d\n", mob_reconf.mob_ctrl_info.target_pci); rrc_log->error("Could not find target cell earfcn=%d, pci=%d\n", serving_cell->earfcn, mob_reconf.mob_ctrl_info.target_pci);
return false; return false;
} }
@ -1007,16 +1064,12 @@ bool rrc::ho_prepare() {
mac_timers->timer_get(t310)->stop(); mac_timers->timer_get(t310)->stop();
mac_timers->timer_get(t304)->set(this, liblte_rrc_t304_num[mob_reconf.mob_ctrl_info.t304]); mac_timers->timer_get(t304)->set(this, liblte_rrc_t304_num[mob_reconf.mob_ctrl_info.t304]);
if (mob_reconf.mob_ctrl_info.carrier_freq_eutra_present && if (mob_reconf.mob_ctrl_info.carrier_freq_eutra_present &&
mob_reconf.mob_ctrl_info.carrier_freq_eutra.dl_carrier_freq != current_cell->earfcn) { mob_reconf.mob_ctrl_info.carrier_freq_eutra.dl_carrier_freq != serving_cell->earfcn) {
rrc_log->warning("Received mobilityControlInfo for inter-frequency handover\n"); rrc_log->warning("Received mobilityControlInfo for inter-frequency handover\n");
} }
// Save cell and current configuration // Save serving cell and current configuration
ho_src_cell_idx = find_cell_idx(phy->get_current_earfcn(), phy->get_current_pci()); ho_src_cell = *serving_cell;
if (ho_src_cell_idx < 0) {
rrc_log->error("Source cell not found in known cells. Reconnecting to cell 0 in case of failure\n");
ho_src_cell_idx = 0;
}
phy->get_config(&ho_src_phy_cfg); phy->get_config(&ho_src_phy_cfg);
mac->get_config(&ho_src_mac_cfg); mac->get_config(&ho_src_mac_cfg);
mac_interface_rrc::ue_rnti_t uernti; mac_interface_rrc::ue_rnti_t uernti;
@ -1033,9 +1086,9 @@ bool rrc::ho_prepare() {
mac->set_ho_rnti(mob_reconf.mob_ctrl_info.new_ue_id, mob_reconf.mob_ctrl_info.target_pci); mac->set_ho_rnti(mob_reconf.mob_ctrl_info.new_ue_id, mob_reconf.mob_ctrl_info.target_pci);
apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common); apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common);
rrc_log->info("Selecting new cell pci=%d\n", known_cells[cell_idx].phy_cell.id); rrc_log->info("Selecting new cell pci=%d\n", neighbour_cells[target_cell_idx]->phy_cell.id);
if (!phy->cell_handover(known_cells[cell_idx].phy_cell)) { if (!phy->cell_handover(neighbour_cells[target_cell_idx]->phy_cell)) {
rrc_log->error("Could not synchronize with target cell pci=%d\n", known_cells[cell_idx].phy_cell.id); rrc_log->error("Could not synchronize with target cell pci=%d\n", neighbour_cells[target_cell_idx]->phy_cell.id);
return false; return false;
} }
@ -1110,8 +1163,8 @@ void rrc::ho_ra_completed(bool ra_successful) {
void rrc::ho_failed() { void rrc::ho_failed() {
// Instruct PHY to resync with source PCI // Instruct PHY to resync with source PCI
if (!phy->cell_handover(known_cells[ho_src_cell_idx].phy_cell)) { if (!phy->cell_handover(ho_src_cell.phy_cell)) {
rrc_log->error("Could not synchronize with target cell pci=%d\n", known_cells[ho_src_cell_idx].phy_cell.id); rrc_log->error("Could not synchronize with target cell pci=%d\n", ho_src_cell.phy_cell.id);
return; return;
} }
@ -1165,14 +1218,37 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU
} }
} }
/* Actions upon reception of RRCConnectionRelease 5.3.8.3 */ /* Actions upon reception of RRCConnectionRelease 5.3.8.3 */
void rrc::rrc_connection_release() { void rrc::rrc_connection_release() {
// Save idleModeMobilityControlInfo, etc. // Save idleModeMobilityControlInfo, etc.
state = RRC_STATE_LEAVE_CONNECTED; state = RRC_STATE_LEAVE_CONNECTED;
rrc_log->console("Received RRC Connection Release\n"); rrc_log->console("Received RRC Connection Release\n");
} }
/* Actions upon leaving RRC_CONNECTED 5.3.12 */
void rrc::leave_connected()
{
rrc_log->console("RRC IDLE\n");
rrc_log->info("Leaving RRC_CONNECTED state\n");
drb_up = false;
measurements.reset();
pdcp->reset();
rlc->reset();
phy->reset();
mac->reset();
set_phy_default();
set_mac_default();
mac_timers->timer_get(t301)->stop();
mac_timers->timer_get(t310)->stop();
mac_timers->timer_get(t311)->stop();
mac_timers->timer_get(t304)->stop();
if (phy->sync_status()) {
// Instruct MAC to look for P-RNTI
mac->pcch_start_rx();
// Instruct PHY to measure serving cell for cell reselection
phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci());
}
}
@ -1213,24 +1289,24 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) {
rrc_log->info("Processing SIB: %d\n", liblte_rrc_sys_info_block_type_num[dlsch_msg.sibs[i].sib_type]); rrc_log->info("Processing SIB: %d\n", liblte_rrc_sys_info_block_type_num[dlsch_msg.sibs[i].sib_type]);
if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == dlsch_msg.sibs[i].sib_type && SI_ACQUIRE_SIB1 == si_acquire_state) { if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == dlsch_msg.sibs[i].sib_type && SI_ACQUIRE_SIB1 == si_acquire_state) {
memcpy(&current_cell->sib1, &dlsch_msg.sibs[i].sib.sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT)); memcpy(&serving_cell->sib1, &dlsch_msg.sibs[i].sib.sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT));
current_cell->has_valid_sib1 = true; serving_cell->has_valid_sib1 = true;
handle_sib1(); handle_sib1();
} else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[i].sib_type && !current_cell->has_valid_sib2) { } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_valid_sib2) {
memcpy(&current_cell->sib2, &dlsch_msg.sibs[i].sib.sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT)); memcpy(&serving_cell->sib2, &dlsch_msg.sibs[i].sib.sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT));
current_cell->has_valid_sib2 = true; serving_cell->has_valid_sib2 = true;
handle_sib2(); handle_sib2();
} else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3 == dlsch_msg.sibs[i].sib_type && !current_cell->has_valid_sib3) { } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_valid_sib3) {
memcpy(&current_cell->sib3, &dlsch_msg.sibs[i].sib.sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT)); memcpy(&serving_cell->sib3, &dlsch_msg.sibs[i].sib.sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT));
current_cell->has_valid_sib3 = true; serving_cell->has_valid_sib3 = true;
handle_sib3(); handle_sib3();
}else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13 == dlsch_msg.sibs[i].sib_type && !current_cell->has_valid_sib13) { }else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_valid_sib13) {
memcpy(&current_cell->sib13, &dlsch_msg.sibs[0].sib.sib13, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT)); memcpy(&serving_cell->sib13, &dlsch_msg.sibs[0].sib.sib13, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT));
current_cell->has_valid_sib13 = true; serving_cell->has_valid_sib13 = true;
handle_sib13(); handle_sib13();
} }
} }
if(current_cell->has_valid_sib2) { if(serving_cell->has_valid_sib2) {
sysinfo_index++; sysinfo_index++;
} }
} }
@ -1238,16 +1314,16 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) {
void rrc::handle_sib1() void rrc::handle_sib1()
{ {
rrc_log->info("SIB1 received, CellID=%d, si_window=%d, sib2_period=%d\n", rrc_log->info("SIB1 received, CellID=%d, si_window=%d, sib2_period=%d\n",
current_cell->sib1.cell_id&0xfff, serving_cell->sib1.cell_id&0xfff,
liblte_rrc_si_window_length_num[current_cell->sib1.si_window_length], liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length],
liblte_rrc_si_periodicity_num[current_cell->sib1.sched_info[0].si_periodicity]); liblte_rrc_si_periodicity_num[serving_cell->sib1.sched_info[0].si_periodicity]);
// Print SIB scheduling info // Print SIB scheduling info
uint32_t i,j; uint32_t i,j;
for(i=0;i<current_cell->sib1.N_sched_info;i++){ for(i=0;i<serving_cell->sib1.N_sched_info;i++){
for(j=0;j<current_cell->sib1.sched_info[i].N_sib_mapping_info;j++){ for(j=0;j<serving_cell->sib1.sched_info[i].N_sib_mapping_info;j++){
LIBLTE_RRC_SIB_TYPE_ENUM t = current_cell->sib1.sched_info[i].sib_mapping_info[j].sib_type; LIBLTE_RRC_SIB_TYPE_ENUM t = serving_cell->sib1.sched_info[i].sib_mapping_info[j].sib_type;
LIBLTE_RRC_SI_PERIODICITY_ENUM p = current_cell->sib1.sched_info[i].si_periodicity; LIBLTE_RRC_SI_PERIODICITY_ENUM p = serving_cell->sib1.sched_info[i].si_periodicity;
rrc_log->debug("SIB scheduling info, sib_type=%d, si_periodicity=%d\n", rrc_log->debug("SIB scheduling info, sib_type=%d, si_periodicity=%d\n",
liblte_rrc_sib_type_num[t], liblte_rrc_sib_type_num[t],
liblte_rrc_si_periodicity_num[p]); liblte_rrc_si_periodicity_num[p]);
@ -1255,16 +1331,16 @@ void rrc::handle_sib1()
} }
// Set TDD Config // Set TDD Config
if(current_cell->sib1.tdd) { if(serving_cell->sib1.tdd) {
phy->set_config_tdd(&current_cell->sib1.tdd_cnfg); phy->set_config_tdd(&serving_cell->sib1.tdd_cnfg);
} }
current_cell->has_valid_sib1 = true; serving_cell->has_valid_sib1 = true;
// Send PLMN and TAC to NAS // Send PLMN and TAC to NAS
std::stringstream ss; std::stringstream ss;
for (uint32_t i = 0; i < current_cell->sib1.N_plmn_ids; i++) { for (uint32_t i = 0; i < serving_cell->sib1.N_plmn_ids; i++) {
nas->plmn_found(current_cell->sib1.plmn_id[i].id, current_cell->sib1.tracking_area_code); nas->plmn_found(serving_cell->sib1.plmn_id[i].id, serving_cell->sib1.tracking_area_code);
} }
// Jump to next state // Jump to next state
@ -1287,7 +1363,7 @@ void rrc::handle_sib2()
{ {
rrc_log->info("SIB2 received\n"); rrc_log->info("SIB2 received\n");
apply_sib2_configs(&current_cell->sib2); apply_sib2_configs(&serving_cell->sib2);
} }
@ -1295,7 +1371,7 @@ void rrc::handle_sib3()
{ {
rrc_log->info("SIB3 received\n"); rrc_log->info("SIB3 received\n");
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3 = &current_cell->sib3; LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3 = &serving_cell->sib3;
// cellReselectionInfoCommon // cellReselectionInfoCommon
cell_resel_cfg.q_hyst = liblte_rrc_q_hyst_num[sib3->q_hyst]; cell_resel_cfg.q_hyst = liblte_rrc_q_hyst_num[sib3->q_hyst];
@ -1317,9 +1393,9 @@ void rrc::handle_sib13()
{ {
rrc_log->info("SIB13 received\n"); rrc_log->info("SIB13 received\n");
// mac->set_config_mbsfn_sib13(&current_cell->sib13.mbsfn_area_info_list_r9[0], // mac->set_config_mbsfn_sib13(&serving_cell->sib13.mbsfn_area_info_list_r9[0],
// current_cell->sib13.mbsfn_area_info_list_r9_size, // serving_cell->sib13.mbsfn_area_info_list_r9_size,
// &current_cell->sib13.mbsfn_notification_config); // &serving_cell->sib13.mbsfn_notification_config);
} }
@ -1499,7 +1575,7 @@ void rrc::parse_dl_ccch(byte_buffer_t *pdu) {
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ: case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ:
rrc_log->info("Connection Reject received. Wait time: %d\n", rrc_log->info("Connection Reject received. Wait time: %d\n",
dl_ccch_msg.msg.rrc_con_rej.wait_time); dl_ccch_msg.msg.rrc_con_rej.wait_time);
state = RRC_STATE_IDLE; state = RRC_STATE_LEAVE_CONNECTED;
break; break;
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP: case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP:
rrc_log->info("Connection Setup received\n"); rrc_log->info("Connection Setup received\n");
@ -1607,7 +1683,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) {
* *
*******************************************************************************/ *******************************************************************************/
void rrc::enable_capabilities() { void rrc::enable_capabilities() {
bool enable_ul_64 = args.ue_category >= 5 && current_cell->sib2.rr_config_common_sib.pusch_cnfg.enable_64_qam; bool enable_ul_64 = args.ue_category >= 5 && serving_cell->sib2.rr_config_common_sib.pusch_cnfg.enable_64_qam;
rrc_log->info("%s 64QAM PUSCH\n", enable_ul_64 ? "Enabling" : "Disabling"); rrc_log->info("%s 64QAM PUSCH\n", enable_ul_64 ? "Enabling" : "Disabling");
phy->set_config_64qam_en(enable_ul_64); phy->set_config_64qam_en(enable_ul_64);
} }
@ -2272,14 +2348,20 @@ void rrc::rrc_meas::L3_filter(meas_value_t *value, float values[NOF_MEASUREMENTS
void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, float rsrq, uint32_t tti) void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, float rsrq, uint32_t tti)
{ {
float values[NOF_MEASUREMENTS] = {rsrp, rsrq}; float values[NOF_MEASUREMENTS] = {rsrp, rsrq};
// This indicates serving cell // This indicates serving cell
if (earfcn == 0) { if (parent->serving_cell->equals(earfcn, pci)) {
log_h->info("MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti); log_h->info("MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti);
L3_filter(&pcell_measurement, values); L3_filter(&pcell_measurement, values);
// Update serving cell measurement
parent->serving_cell->rsrp = rsrp;
} else { } else {
// Add to known cells
// Add to list of neighbour cells
parent->add_neighbour_cell(earfcn, pci, rsrp); parent->add_neighbour_cell(earfcn, pci, rsrp);
log_h->info("MEAS: New measurement earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n", earfcn, pci, rsrp, rsrq, tti); log_h->info("MEAS: New measurement earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n", earfcn, pci, rsrp, rsrq, tti);
@ -2299,8 +2381,6 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa
return; return;
} }
} }
parent->rrc_log->warning("MEAS: Received measurement from unknown EARFCN=%d\n", earfcn);
} }
} }