Merge branch 'next' into guti_attach

master
Pedro Alvarez 7 years ago
commit 406a1d01b6

@ -30,6 +30,8 @@
#include <pthread.h> #include <pthread.h>
#include <vector> #include <vector>
#include <stack> #include <stack>
#include <map>
#include <string>
#include <algorithm> #include <algorithm>
/******************************************************************************* /*******************************************************************************
@ -76,8 +78,13 @@ public:
{ {
printf("%d buffers in queue\n", (int) used.size()); printf("%d buffers in queue\n", (int) used.size());
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED #ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
std::map<std::string, uint32_t> buffer_cnt;
for (uint32_t i=0;i<used.size();i++) { for (uint32_t i=0;i<used.size();i++) {
printf("%s\n", strlen(used[i]->debug_name)?used[i]->debug_name:"Undefined"); buffer_cnt[strlen(used[i]->debug_name)?used[i]->debug_name:"Undefined"]++;
}
std::map<std::string, uint32_t>::iterator it;
for (it = buffer_cnt.begin(); it != buffer_cnt.end(); it++) {
printf(" - %dx %s\n", it->second, it->first.c_str());
} }
#endif #endif
} }

@ -63,7 +63,7 @@
#define SRSLTE_MAX_BUFFER_SIZE_BYTES 12756 #define SRSLTE_MAX_BUFFER_SIZE_BYTES 12756
#define SRSLTE_BUFFER_HEADER_OFFSET 1024 #define SRSLTE_BUFFER_HEADER_OFFSET 1024
//#define SRSLTE_BUFFER_POOL_LOG_ENABLED #define SRSLTE_BUFFER_POOL_LOG_ENABLED
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED #ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
#define pool_allocate (pool->allocate(__FUNCTION__)) #define pool_allocate (pool->allocate(__FUNCTION__))

@ -160,7 +160,7 @@ public:
virtual void in_sync() = 0; virtual void in_sync() = 0;
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_camping(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp = NAN) = 0;
virtual void new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn = -1, int pci = -1) = 0; virtual void new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn = -1, int pci = -1) = 0;
}; };
@ -580,9 +580,8 @@ public:
/* Cell search and selection procedures */ /* Cell search and selection procedures */
virtual void cell_search_start() = 0; virtual void cell_search_start() = 0;
virtual void cell_search_stop() = 0;
virtual void cell_search_next() = 0; virtual void cell_search_next() = 0;
virtual bool cell_select(uint32_t earfcn, srslte_cell_t cell) = 0; virtual void cell_select(uint32_t earfcn, srslte_cell_t cell) = 0;
virtual bool cell_handover(srslte_cell_t cell) = 0; virtual bool cell_handover(srslte_cell_t cell) = 0;
/* Is the PHY downlink synchronized? */ /* Is the PHY downlink synchronized? */

@ -60,6 +60,7 @@ typedef struct {
SRSLTE_RF_ERROR_LATE, SRSLTE_RF_ERROR_LATE,
SRSLTE_RF_ERROR_UNDERFLOW, SRSLTE_RF_ERROR_UNDERFLOW,
SRSLTE_RF_ERROR_OVERFLOW, SRSLTE_RF_ERROR_OVERFLOW,
SRSLTE_RF_ERROR_RX,
SRSLTE_RF_ERROR_OTHER SRSLTE_RF_ERROR_OTHER
} type; } type;
int opt; int opt;

@ -72,6 +72,8 @@ namespace srslte {
trace_enabled = false; trace_enabled = false;
tti = 0; tti = 0;
agc_enabled = false; agc_enabled = false;
radio_is_streaming = false;
is_initialized = false;
}; };
bool init(char *args = NULL, char *devname = NULL, uint32_t nof_channels = 1); bool init(char *args = NULL, char *devname = NULL, uint32_t nof_channels = 1);
@ -119,13 +121,13 @@ namespace srslte {
void start_trace(); void start_trace();
void write_trace(std::string filename); void write_trace(std::string filename);
void start_rx(bool now = false);
void stop_rx();
void set_tti(uint32_t tti); void set_tti(uint32_t tti);
bool is_first_of_burst(); bool is_first_of_burst();
bool is_init();
void register_error_handler(srslte_rf_error_handler_t h); void register_error_handler(srslte_rf_error_handler_t h);
protected: protected:
@ -168,6 +170,9 @@ namespace srslte {
uint32_t tti; uint32_t tti;
bool agc_enabled; bool agc_enabled;
bool is_initialized = true;;
bool radio_is_streaming;
uint32_t saved_nof_channels; uint32_t saved_nof_channels;
char saved_args[128]; char saved_args[128];
char saved_devname[128]; char saved_devname[128];

@ -40,6 +40,7 @@ log_filter::log_filter()
do_tti = false; do_tti = false;
time_src = NULL; time_src = NULL;
time_format = TIME; time_format = TIME;
logger_h = NULL;
} }
log_filter::log_filter(std::string layer) log_filter::log_filter(std::string layer)

@ -35,6 +35,7 @@ namespace srslte{
logger_file::logger_file() logger_file::logger_file()
:inited(false) :inited(false)
,logfile(NULL)
,not_done(true) ,not_done(true)
,cur_length(0) ,cur_length(0)
,max_length(0) ,max_length(0)
@ -46,7 +47,9 @@ logger_file::~logger_file() {
if(inited) { if(inited) {
wait_thread_finish(); wait_thread_finish();
flush(); flush();
fclose(logfile); if (logfile) {
fclose(logfile);
}
} }
} }

@ -76,10 +76,14 @@ void pdu_queue::deallocate(uint8_t* pdu)
*/ */
void pdu_queue::push(uint8_t *ptr, uint32_t len, uint32_t tstamp) void pdu_queue::push(uint8_t *ptr, uint32_t len, uint32_t tstamp)
{ {
pdu_t *pdu = (pdu_t*) ptr; if (ptr) {
pdu->len = len; pdu_t *pdu = (pdu_t*) ptr;
pdu->tstamp = tstamp; pdu->len = len;
pdu_q.push(pdu); pdu->tstamp = tstamp;
pdu_q.push(pdu);
} else {
log_h->warning("Error pushing pdu: ptr is empty\n");
}
} }
bool pdu_queue::process_pdus() bool pdu_queue::process_pdus()

@ -540,22 +540,23 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui
} }
} }
} }
/* Compute RSRP for the channel estimates in this port */
uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
q->rsrp[rxant_id][port_id] = srslte_vec_avg_power_cf(q->pilot_estimates, npilots);
q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id);
} }
int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id) int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id)
{ {
uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
/* Get references from the input signal */ /* Get references from the input signal */
srslte_refsignal_cs_get_sf(q->cell, port_id, input, q->pilot_recv_signal); srslte_refsignal_cs_get_sf(q->cell, port_id, input, q->pilot_recv_signal);
/* Use the known CSR signal to compute Least-squares estimates */ /* Use the known CSR signal to compute Least-squares estimates */
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_refs.pilots[port_id/2][sf_idx], srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_refs.pilots[port_id/2][sf_idx],
q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); q->pilot_estimates, npilots);
/* Compute RSRP for the channel estimates in this port */
double energy = cabs(srslte_vec_acc_cc(q->pilot_estimates, npilots)/npilots);
q->rsrp[rxant_id][port_id] = energy*energy;
q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id);
chest_interpolate_noise_est(q, input, ce, sf_idx, port_id, rxant_id, SRSLTE_SF_NORM); chest_interpolate_noise_est(q, input, ce, sf_idx, port_id, rxant_id, SRSLTE_SF_NORM);

@ -45,6 +45,7 @@
#define FFTW_TYPE 0 #define FFTW_TYPE 0
#endif #endif
pthread_mutex_t fft_mutex = PTHREAD_MUTEX_INITIALIZER;
void srslte_dft_load() { void srslte_dft_load() {
#ifdef FFTW_WISDOM_FILE #ifdef FFTW_WISDOM_FILE
@ -58,10 +59,12 @@ void srslte_dft_exit() {
#ifdef FFTW_WISDOM_FILE #ifdef FFTW_WISDOM_FILE
fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE); fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE);
#endif #endif
fftwf_cleanup();
} }
int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir, int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir,
srslte_dft_mode_t mode) { srslte_dft_mode_t mode) {
bzero(plan, sizeof(srslte_dft_plan_t));
if(mode == SRSLTE_DFT_COMPLEX){ if(mode == SRSLTE_DFT_COMPLEX){
return srslte_dft_plan_c(plan,dft_points,dir); return srslte_dft_plan_c(plan,dft_points,dir);
} else { } else {
@ -99,10 +102,15 @@ int srslte_dft_replan_guru_c(srslte_dft_plan_t *plan, const int new_dft_points,
const fftwf_iodim iodim = {new_dft_points, istride, ostride}; const fftwf_iodim iodim = {new_dft_points, istride, ostride};
const fftwf_iodim howmany_dims = {how_many, idist, odist}; const fftwf_iodim howmany_dims = {how_many, idist, odist};
pthread_mutex_lock(&fft_mutex);
/* Destroy current plan */ /* Destroy current plan */
fftwf_destroy_plan(plan->p); fftwf_destroy_plan(plan->p);
plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE); plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE);
pthread_mutex_unlock(&fft_mutex);
if (!plan->p) { if (!plan->p) {
return -1; return -1;
} }
@ -114,11 +122,15 @@ int srslte_dft_replan_guru_c(srslte_dft_plan_t *plan, const int new_dft_points,
int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) { int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) {
int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
pthread_mutex_lock(&fft_mutex);
if (plan->p) { if (plan->p) {
fftwf_destroy_plan(plan->p); fftwf_destroy_plan(plan->p);
plan->p = NULL; plan->p = NULL;
} }
plan->p = fftwf_plan_dft_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE); plan->p = fftwf_plan_dft_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE);
pthread_mutex_unlock(&fft_mutex);
if (!plan->p) { if (!plan->p) {
return -1; return -1;
} }
@ -134,10 +146,14 @@ int srslte_dft_plan_guru_c(srslte_dft_plan_t *plan, const int dft_points, srslte
const fftwf_iodim iodim = {dft_points, istride, ostride}; const fftwf_iodim iodim = {dft_points, istride, ostride};
const fftwf_iodim howmany_dims = {how_many, idist, odist}; const fftwf_iodim howmany_dims = {how_many, idist, odist};
pthread_mutex_lock(&fft_mutex);
plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE); plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE);
if (!plan->p) { if (!plan->p) {
return -1; return -1;
} }
pthread_mutex_unlock(&fft_mutex);
plan->size = dft_points; plan->size = dft_points;
plan->init_size = plan->size; plan->init_size = plan->size;
plan->mode = SRSLTE_DFT_COMPLEX; plan->mode = SRSLTE_DFT_COMPLEX;
@ -154,8 +170,14 @@ int srslte_dft_plan_guru_c(srslte_dft_plan_t *plan, const int dft_points, srslte
int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) { int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) {
allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points); allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points);
pthread_mutex_lock(&fft_mutex);
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE); plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE);
pthread_mutex_unlock(&fft_mutex);
if (!plan->p) { if (!plan->p) {
return -1; return -1;
} }
@ -175,11 +197,15 @@ int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_
int srslte_dft_replan_r(srslte_dft_plan_t *plan, const int new_dft_points) { int srslte_dft_replan_r(srslte_dft_plan_t *plan, const int new_dft_points) {
int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R; int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R;
pthread_mutex_lock(&fft_mutex);
if (plan->p) { if (plan->p) {
fftwf_destroy_plan(plan->p); fftwf_destroy_plan(plan->p);
plan->p = NULL; plan->p = NULL;
} }
plan->p = fftwf_plan_r2r_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE); plan->p = fftwf_plan_r2r_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE);
pthread_mutex_unlock(&fft_mutex);
if (!plan->p) { if (!plan->p) {
return -1; return -1;
} }
@ -190,7 +216,11 @@ int srslte_dft_replan_r(srslte_dft_plan_t *plan, const int new_dft_points) {
int srslte_dft_plan_r(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) { int srslte_dft_plan_r(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) {
allocate(plan,sizeof(float),sizeof(float), dft_points); allocate(plan,sizeof(float),sizeof(float), dft_points);
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R; int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R;
pthread_mutex_lock(&fft_mutex);
plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE); plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE);
pthread_mutex_unlock(&fft_mutex);
if (!plan->p) { if (!plan->p) {
return -1; return -1;
} }
@ -309,11 +339,15 @@ void srslte_dft_run_r(srslte_dft_plan_t *plan, const float *in, float *out) {
void srslte_dft_plan_free(srslte_dft_plan_t *plan) { void srslte_dft_plan_free(srslte_dft_plan_t *plan) {
if (!plan) return; if (!plan) return;
if (!plan->size) return; if (!plan->size) return;
pthread_mutex_lock(&fft_mutex);
if (!plan->is_guru) { if (!plan->is_guru) {
if (plan->in) fftwf_free(plan->in); if (plan->in) fftwf_free(plan->in);
if (plan->out) fftwf_free(plan->out); if (plan->out) fftwf_free(plan->out);
} }
if (plan->p) fftwf_destroy_plan(plan->p); if (plan->p) fftwf_destroy_plan(plan->p);
pthread_mutex_unlock(&fft_mutex);
bzero(plan, sizeof(srslte_dft_plan_t)); bzero(plan, sizeof(srslte_dft_plan_t));
} }

@ -128,6 +128,8 @@ int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, c
if (sf_type == SRSLTE_SF_MBSFN) { if (sf_type == SRSLTE_SF_MBSFN) {
q->mbsfn_subframe = true; q->mbsfn_subframe = true;
q->non_mbsfn_region = 2; // default set to 2 q->non_mbsfn_region = 2; // default set to 2
} else {
q->mbsfn_subframe = false;
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;

@ -171,5 +171,8 @@ int main(int argc, char **argv) {
n_prb++; n_prb++;
} }
srslte_dft_exit();
exit(0); exit(0);
} }

@ -198,6 +198,8 @@ int main(int argc, char **argv) {
} }
srslte_rm_turbo_free_tables(); srslte_rm_turbo_free_tables();
free(rm_bits_s);
free(rm_bits_f);
free(rm_bits); free(rm_bits);
free(rm_bits2); free(rm_bits2);
free(rm_bits2_bytes); free(rm_bits2_bytes);

@ -96,6 +96,19 @@ static void log_underflow(rf_uhd_handler_t *h) {
} }
} }
static void log_rx_error(rf_uhd_handler_t *h) {
if (h->uhd_error_handler) {
char error_string[512];
uhd_usrp_last_error(h->usrp, error_string, 512);
fprintf(stderr, "USRP reported the following error: %s\n", error_string);
srslte_rf_error_t error;
bzero(&error, sizeof(srslte_rf_error_t));
error.type = SRSLTE_RF_ERROR_RX;
h->uhd_error_handler(error);
}
}
static void* async_thread(void *h) { static void* async_thread(void *h) {
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_async_metadata_handle md; uhd_async_metadata_handle md;
@ -334,11 +347,12 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
perror("malloc"); perror("malloc");
return -1; return -1;
} }
bzero(handler, sizeof(rf_uhd_handler_t));
*h = handler; *h = handler;
/* Set priority to UHD threads */ /* Set priority to UHD threads */
uhd_set_thread_priority(uhd_default_thread_priority, true); uhd_set_thread_priority(uhd_default_thread_priority, true);
/* Find available devices */ /* Find available devices */
uhd_string_vector_handle devices_str; uhd_string_vector_handle devices_str;
uhd_string_vector_make(&devices_str); uhd_string_vector_make(&devices_str);
@ -557,11 +571,12 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
uhd_meta_range_free(&gain_range); uhd_meta_range_free(&gain_range);
// Start low priority thread to receive async commands // Start low priority thread to receive async commands
handler->async_thread_running = true; /*
handler->async_thread_running = true;
if (pthread_create(&handler->async_thread, NULL, async_thread, handler)) { if (pthread_create(&handler->async_thread, NULL, async_thread, handler)) {
perror("pthread_create"); perror("pthread_create");
return -1; return -1;
} }*/
/* Restore priorities */ /* Restore priorities */
uhd_set_thread_priority(0, false); uhd_set_thread_priority(0, false);
@ -738,6 +753,7 @@ int rf_uhd_recv_with_time_multi(void *h,
num_rx_samples, md, 1.0, false, &rxd_samples); num_rx_samples, md, 1.0, false, &rxd_samples);
if (error) { if (error) {
fprintf(stderr, "Error receiving from UHD: %d\n", error); fprintf(stderr, "Error receiving from UHD: %d\n", error);
log_rx_error(handler);
return -1; return -1;
} }
@ -760,8 +776,12 @@ int rf_uhd_recv_with_time_multi(void *h,
} }
} }
} else { } else {
return uhd_rx_streamer_recv(handler->rx_stream, data, uhd_error error = uhd_rx_streamer_recv(handler->rx_stream, data, nsamples, md, 0.0, false, &rxd_samples);
nsamples, md, 0.0, false, &rxd_samples); if (error) {
fprintf(stderr, "Error receiving from UHD: %d\n", error);
log_rx_error(handler);
return -1;
}
} }
if (secs && frac_secs) { if (secs && frac_secs) {
uhd_rx_metadata_time_spec(handler->rx_md_first, secs, frac_secs); uhd_rx_metadata_time_spec(handler->rx_md_first, secs, frac_secs);

@ -74,7 +74,7 @@ void usage(char *prog) {
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "adgetvsfil")) != -1) { while ((opt = getopt(argc, argv, "adgetvnsfil")) != -1) {
switch (opt) { switch (opt) {
case 'a': case 'a':
rf_args = argv[optind]; rf_args = argv[optind];

@ -755,7 +755,9 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
if (q->do_agc) { if (q->do_agc) {
srslte_agc_process(&q->agc, input_buffer[0], q->sf_len); srslte_agc_process(&q->agc, input_buffer[0], q->sf_len);
} }
INFO("SYNC FIND: sf_idx=%d, ret=%d, next_state=%d\n", q->sf_idx, ret, q->state);
break; break;
case SF_TRACK: case SF_TRACK:
@ -817,6 +819,9 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
q->frame_total_cnt++; q->frame_total_cnt++;
} }
INFO("SYNC TRACK: sf_idx=%d, ret=%d, next_state=%d\n", q->sf_idx, ret, q->state);
break; break;
} }
} }

@ -157,6 +157,8 @@ int main(int argc, char **argv) {
if(test_dft(in) != 0) if(test_dft(in) != 0)
return -1; return -1;
srslte_dft_exit();
free(in); free(in);
printf("Done\n"); printf("Done\n");
exit(0); exit(0);

@ -71,7 +71,12 @@ bool radio::init(char *args, char *devname, uint32_t nof_channels)
} }
saved_nof_channels = nof_channels; saved_nof_channels = nof_channels;
return true; is_initialized = true;
return true;
}
bool radio::is_init() {
return is_initialized;
} }
void radio::stop() void radio::stop()
@ -82,11 +87,8 @@ void radio::stop()
void radio::reset() void radio::reset()
{ {
printf("Resetting Radio...\n"); printf("Resetting Radio...\n");
srslte_rf_close(&rf_device); srslte_rf_stop_rx_stream(&rf_device);
sleep(3); radio_is_streaming = false;
if (srslte_rf_open_devname(&rf_device, saved_devname, saved_args, saved_nof_channels)) {
fprintf(stderr, "Error opening RF device\n");
}
} }
void radio::set_manual_calibration(rf_cal_t* calibration) void radio::set_manual_calibration(rf_cal_t* calibration)
@ -141,6 +143,10 @@ bool radio::rx_at(void* buffer, uint32_t nof_samples, srslte_timestamp_t rx_time
bool radio::rx_now(void* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t* rxd_time) bool radio::rx_now(void* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t* rxd_time)
{ {
if (!radio_is_streaming) {
srslte_rf_start_rx_stream(&rf_device, false);
radio_is_streaming = true;
}
if (srslte_rf_recv_with_time_multi(&rf_device, buffer, nof_samples, true, if (srslte_rf_recv_with_time_multi(&rf_device, buffer, nof_samples, true,
rxd_time?&rxd_time->full_secs:NULL, rxd_time?&rxd_time->frac_secs:NULL) > 0) { rxd_time?&rxd_time->full_secs:NULL, rxd_time?&rxd_time->frac_secs:NULL) > 0) {
return true; return true;
@ -295,7 +301,9 @@ void radio::set_master_clock_rate(double rate)
void radio::set_rx_srate(double srate) void radio::set_rx_srate(double srate)
{ {
srslte_rf_stop_rx_stream(&rf_device);
srslte_rf_set_rx_srate(&rf_device, srate); srslte_rf_set_rx_srate(&rf_device, srate);
srslte_rf_start_rx_stream(&rf_device, false);
} }
void radio::set_tx_freq(double freq) void radio::set_tx_freq(double freq)
@ -446,16 +454,6 @@ void radio::set_tx_srate(double srate)
tx_adv_sec = nsamples/cur_tx_srate; tx_adv_sec = nsamples/cur_tx_srate;
} }
void radio::start_rx(bool now)
{
srslte_rf_start_rx_stream(&rf_device, now);
}
void radio::stop_rx()
{
srslte_rf_stop_rx_stream(&rf_device);
}
void radio::register_error_handler(srslte_rf_error_handler_t h) void radio::register_error_handler(srslte_rf_error_handler_t h)
{ {
srslte_rf_register_error_handler(&rf_device, h); srslte_rf_register_error_handler(&rf_device, h);

@ -37,6 +37,7 @@ bool radio_multi::init_multi(uint32_t nof_rx_antennas, char* args, char* devname
strncpy(saved_devname, devname, 127); strncpy(saved_devname, devname, 127);
} }
is_initialized = true;
return true; return true;
} }
@ -46,7 +47,11 @@ bool radio_multi::rx_now(cf_t *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, s
for (int i=0;i<SRSLTE_MAX_PORTS;i++) { for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ptr[i] = buffer[i]; ptr[i] = buffer[i];
} }
if (srslte_rf_recv_with_time_multi(&rf_device, ptr, nof_samples, true, if (!radio_is_streaming) {
srslte_rf_start_rx_stream(&rf_device, false);
radio_is_streaming = true;
}
if (srslte_rf_recv_with_time_multi(&rf_device, ptr, nof_samples, true,
rxd_time?&rxd_time->full_secs:NULL, rxd_time?&rxd_time->frac_secs:NULL) > 0) { rxd_time?&rxd_time->full_secs:NULL, rxd_time?&rxd_time->frac_secs:NULL) > 0) {
return true; return true;
} else { } else {

@ -72,6 +72,14 @@ rlc_am::~rlc_am()
{ {
// reset RLC and dealloc SDUs // reset RLC and dealloc SDUs
stop(); stop();
if(rx_sdu) {
pool->deallocate(rx_sdu);
}
if(tx_sdu) {
pool->deallocate(tx_sdu);
}
} }
void rlc_am::init(srslte::log *log_, void rlc_am::init(srslte::log *log_,

@ -136,11 +136,11 @@ void rlc_um::reset()
vr_uh = 0; vr_uh = 0;
pdu_lost = false; pdu_lost = false;
if(rx_sdu) { if(rx_sdu) {
rx_sdu->reset(); pool->deallocate(rx_sdu);
} }
if(tx_sdu) { if(tx_sdu) {
tx_sdu->reset(); pool->deallocate(tx_sdu);
} }
if(mac_timers) { if(mac_timers) {

@ -31,7 +31,8 @@ target_link_libraries(rlc_am_test srslte_upper srslte_phy srslte_common)
add_test(rlc_am_test rlc_am_test) add_test(rlc_am_test rlc_am_test)
add_executable(rlc_am_stress_test rlc_am_stress_test.cc) add_executable(rlc_am_stress_test rlc_am_stress_test.cc)
target_link_libraries(rlc_am_stress_test srslte_upper srslte_phy srslte_common) target_link_libraries(rlc_am_stress_test srslte_upper srslte_phy srslte_common ${Boost_LIBRARIES})
add_test(rlc_am_stress_test rlc_am_stress_test --duration 10)
add_executable(rlc_um_data_test rlc_um_data_test.cc) add_executable(rlc_um_data_test rlc_um_data_test.cc)
target_link_libraries(rlc_um_data_test srslte_upper srslte_phy srslte_common) target_link_libraries(rlc_um_data_test srslte_upper srslte_phy srslte_common)

@ -31,23 +31,70 @@
#include "srslte/common/logger_stdout.h" #include "srslte/common/logger_stdout.h"
#include "srslte/common/threads.h" #include "srslte/common/threads.h"
#include "srslte/upper/rlc.h" #include "srslte/upper/rlc.h"
#include <boost/program_options.hpp>
#include <boost/program_options/parsers.hpp>
#include <assert.h> #include <assert.h>
#define NBUFS 5
using namespace std;
using namespace srsue; using namespace srsue;
using namespace srslte; using namespace srslte;
namespace bpo = boost::program_options;
typedef struct {
uint32_t test_duration_sec;
float error_rate;
uint32_t sdu_gen_delay_usec;
uint32_t pdu_tx_delay_usec;
bool reestablish;
} stress_test_args_t;
void parse_args(stress_test_args_t *args, int argc, char *argv[]) {
// Command line only options
bpo::options_description general("General options");
general.add_options()
("help,h", "Produce help message")
("version,v", "Print version information and exit");
// Command line or config file options
bpo::options_description common("Configuration options");
common.add_options()
("duration", bpo::value<uint32_t>(&args->test_duration_sec)->default_value(10), "Duration (sec)")
("sdu_gen_delay", bpo::value<uint32_t>(&args->sdu_gen_delay_usec)->default_value(10), "SDU generation delay (usec)")
("pdu_tx_delay", bpo::value<uint32_t>(&args->pdu_tx_delay_usec)->default_value(10), "Delay in MAC for transfering PDU from tx'ing RLC to rx'ing RLC (usec)")
("error_rate", bpo::value<float>(&args->error_rate)->default_value(0.1), "Rate at which RLC PDUs are dropped")
("reestablish", bpo::value<bool>(&args->reestablish)->default_value(false), "Mimic RLC reestablish during execution");
// these options are allowed on the command line
bpo::options_description cmdline_options;
cmdline_options.add(common).add(general);
// parse the command line and store result in vm
bpo::variables_map vm;
bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).run(), vm);
bpo::notify(vm);
// help option was given - print usage and exit
if (vm.count("help")) {
cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl;
cout << common << endl << general << endl;
exit(0);
}
}
class mac_reader class mac_reader
:public thread :public thread
{ {
public: public:
mac_reader(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_) mac_reader(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_, uint32_t pdu_tx_delay_usec_)
{ {
rlc1 = rlc1_; rlc1 = rlc1_;
rlc2 = rlc2_; rlc2 = rlc2_;
fail_rate = fail_rate_; fail_rate = fail_rate_;
run_enable = true; run_enable = true;
running = false; running = false;
pdu_tx_delay_usec = pdu_tx_delay_usec_;
} }
void stop() void stop()
@ -82,7 +129,7 @@ private:
if(((float)rand()/RAND_MAX > fail_rate) && read>0) { if(((float)rand()/RAND_MAX > fail_rate) && read>0) {
rlc2->write_pdu(1, pdu->msg, opp_size); rlc2->write_pdu(1, pdu->msg, opp_size);
} }
usleep(100); usleep(pdu_tx_delay_usec);
} }
running = false; running = false;
byte_buffer_pool::get_instance()->deallocate(pdu); byte_buffer_pool::get_instance()->deallocate(pdu);
@ -91,6 +138,7 @@ private:
rlc_interface_mac *rlc1; rlc_interface_mac *rlc1;
rlc_interface_mac *rlc2; rlc_interface_mac *rlc2;
float fail_rate; float fail_rate;
uint32_t pdu_tx_delay_usec;
bool run_enable; bool run_enable;
bool running; bool running;
@ -100,9 +148,9 @@ class mac_dummy
:public srslte::mac_interface_timers :public srslte::mac_interface_timers
{ {
public: public:
mac_dummy(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_) mac_dummy(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_, uint32_t pdu_tx_delay)
:r1(rlc1_, rlc2_, fail_rate_) :r1(rlc1_, rlc2_, fail_rate_, pdu_tx_delay)
,r2(rlc2_, rlc1_, fail_rate_) ,r2(rlc2_, rlc1_, fail_rate_, pdu_tx_delay)
{ {
} }
@ -140,12 +188,13 @@ class rlc_am_tester
,public thread ,public thread
{ {
public: public:
rlc_am_tester(rlc_interface_pdcp *rlc_, std::string name_=""){ rlc_am_tester(rlc_interface_pdcp *rlc_, std::string name_, uint32_t sdu_gen_delay_usec_){
rlc = rlc_; rlc = rlc_;
run_enable = true; run_enable = true;
running = false; running = false;
rx_pdus = 0; rx_pdus = 0;
name = name_; name = name_;
sdu_gen_delay_usec = sdu_gen_delay_usec_;
} }
void stop() void stop()
@ -191,7 +240,7 @@ private:
pdu->N_bytes = 1500; pdu->N_bytes = 1500;
pdu->msg[0] = sn++; pdu->msg[0] = sn++;
rlc->write_sdu(1, pdu); rlc->write_sdu(1, pdu);
usleep(100); usleep(sdu_gen_delay_usec);
} }
running = false; running = false;
} }
@ -202,10 +251,12 @@ private:
std::string name; std::string name;
uint32_t sdu_gen_delay_usec;
rlc_interface_pdcp *rlc; rlc_interface_pdcp *rlc;
}; };
void stress_test() void stress_test(stress_test_args_t args)
{ {
srslte::log_filter log1("RLC_AM_1"); srslte::log_filter log1("RLC_AM_1");
srslte::log_filter log2("RLC_AM_2"); srslte::log_filter log2("RLC_AM_2");
@ -214,14 +265,12 @@ void stress_test()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
float fail_rate = 0.1;
rlc rlc1; rlc rlc1;
rlc rlc2; rlc rlc2;
rlc_am_tester tester1(&rlc1, "tester1"); rlc_am_tester tester1(&rlc1, "tester1", args.sdu_gen_delay_usec);
rlc_am_tester tester2(&rlc2, "tester2"); rlc_am_tester tester2(&rlc2, "tester2", args.sdu_gen_delay_usec);
mac_dummy mac(&rlc1, &rlc2, fail_rate); mac_dummy mac(&rlc1, &rlc2, args.error_rate, args.pdu_tx_delay_usec);
ue_interface ue; ue_interface ue;
rlc1.init(&tester1, &tester1, &ue, &log1, &mac, 0); rlc1.init(&tester1, &tester1, &ue, &log1, &mac, 0);
@ -245,7 +294,14 @@ void stress_test()
tester2.start(7); tester2.start(7);
mac.start(); mac.start();
usleep(100e6); for (uint32_t i = 0; i < args.test_duration_sec; i++) {
// if enabled, mimic reestablishment every second
if (args.reestablish) {
rlc1.reestablish();
rlc2.reestablish();
}
usleep(1e6);
}
tester1.stop(); tester1.stop();
tester2.stop(); tester2.stop();
@ -254,6 +310,9 @@ void stress_test()
int main(int argc, char **argv) { int main(int argc, char **argv) {
stress_test(); stress_test_args_t args;
parse_args(&args, argc, argv);
stress_test(args);
byte_buffer_pool::get_instance()->cleanup(); byte_buffer_pool::get_instance()->cleanup();
} }

@ -13,6 +13,8 @@
# mme_addr: IP address of MME for S1 connnection # mme_addr: IP address of MME for S1 connnection
# gtp_bind_addr: Local IP address to bind for GTP connection # gtp_bind_addr: Local IP address to bind for GTP connection
# n_prb: Number of Physical Resource Blocks (6,15,25,50,75,100) # n_prb: Number of Physical Resource Blocks (6,15,25,50,75,100)
# tm: Transmission mode 1-4 (TM1 default)
# nof_ports: Number of Tx ports (1 port default, set to 2 for TM2/3/4)
# #
##################################################################### #####################################################################
[enb] [enb]
@ -25,6 +27,9 @@ mnc = 01
mme_addr = 127.0.1.100 mme_addr = 127.0.1.100
gtp_bind_addr = 127.0.0.1 gtp_bind_addr = 127.0.0.1
n_prb = 50 n_prb = 50
#tm = 4
#nof_ports = 2
##################################################################### #####################################################################
# eNB configuration files # eNB configuration files

@ -104,9 +104,7 @@ void txrx::run_thread()
log_h->info("Starting RX/TX thread nof_prb=%d, sf_len=%d\n",worker_com->cell.nof_prb, sf_len); log_h->info("Starting RX/TX thread nof_prb=%d, sf_len=%d\n",worker_com->cell.nof_prb, sf_len);
// Start streaming RX samples
radio_h->start_rx();
// Set TTI so that first TX is at tti=0 // Set TTI so that first TX is at tti=0
tti = 10235; tti = 10235;

@ -196,6 +196,8 @@ private:
is_initiated = false; is_initiated = false;
ack = false; ack = false;
bzero(&cur_grant, sizeof(Tgrant)); bzero(&cur_grant, sizeof(Tgrant));
payload_buffer_ptr = NULL;
pthread_mutex_init(&mutex, NULL);
} }
~dl_tb_process() { ~dl_tb_process() {
@ -220,16 +222,24 @@ private:
} }
void reset(void) { void reset(void) {
pthread_mutex_lock(&mutex);
is_first_tb = true; is_first_tb = true;
ack = false; ack = false;
payload_buffer_ptr = NULL; if (payload_buffer_ptr) {
harq_entity->demux_unit->deallocate(payload_buffer_ptr);
payload_buffer_ptr = NULL;
}
bzero(&cur_grant, sizeof(Tgrant)); bzero(&cur_grant, sizeof(Tgrant));
if (is_initiated) { if (is_initiated) {
srslte_softbuffer_rx_reset(&softbuffer); srslte_softbuffer_rx_reset(&softbuffer);
} }
pthread_mutex_unlock(&mutex);
} }
void new_grant_dl(Tgrant grant, Taction *action) { void new_grant_dl(Tgrant grant, Taction *action) {
pthread_mutex_lock(&mutex);
// Compute RV for BCCH when not specified in PDCCH format // Compute RV for BCCH when not specified in PDCCH format
if (pid == HARQ_BCCH_PID && grant.rv[tid] == -1) { if (pid == HARQ_BCCH_PID && grant.rv[tid] == -1) {
uint32_t k; uint32_t k;
@ -253,14 +263,14 @@ private:
n_retx = 0; n_retx = 0;
} }
// Save grant
grant.last_ndi[tid] = cur_grant.ndi[tid];
grant.last_tti = cur_grant.tti;
memcpy(&cur_grant, &grant, sizeof(Tgrant));
// If data has not yet been successfully decoded // If data has not yet been successfully decoded
if (!ack) { if (!ack) {
// Save grant
grant.last_ndi[tid] = cur_grant.ndi[tid];
grant.last_tti = cur_grant.tti;
memcpy(&cur_grant, &grant, sizeof(Tgrant));
// Instruct the PHY To combine the received data and attempt to decode it // Instruct the PHY To combine the received data and attempt to decode it
if (pid == HARQ_BCCH_PID) { if (pid == HARQ_BCCH_PID) {
payload_buffer_ptr = harq_entity->demux_unit->request_buffer_bcch(cur_grant.n_bytes[tid]); payload_buffer_ptr = harq_entity->demux_unit->request_buffer_bcch(cur_grant.n_bytes[tid]);
@ -271,6 +281,7 @@ private:
if (!action->payload_ptr[tid]) { if (!action->payload_ptr[tid]) {
action->decode_enabled[tid] = false; action->decode_enabled[tid] = false;
Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes[tid]); Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes[tid]);
pthread_mutex_unlock(&mutex);
return; return;
} }
action->decode_enabled[tid]= true; action->decode_enabled[tid]= true;
@ -281,7 +292,8 @@ private:
} else { } else {
action->default_ack[tid] = true; action->default_ack[tid] = true;
Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK\n", pid); Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK (grant_tti=%d, ndi=%d, sz=%d)\n",
pid, cur_grant.tti, cur_grant.ndi[tid], cur_grant.n_bytes[tid]);
} }
if (pid == HARQ_BCCH_PID || harq_entity->timer_aligment_timer->is_expired()) { if (pid == HARQ_BCCH_PID || harq_entity->timer_aligment_timer->is_expired()) {
@ -298,9 +310,12 @@ private:
Debug("Generating ACK\n"); Debug("Generating ACK\n");
} }
} }
pthread_mutex_unlock(&mutex);
} }
void tb_decoded(bool ack_) { void tb_decoded(bool ack_) {
pthread_mutex_lock(&mutex);
ack = ack_; ack = ack_;
if (ack) { if (ack) {
if (pid == HARQ_BCCH_PID) { if (pid == HARQ_BCCH_PID) {
@ -331,11 +346,15 @@ private:
harq_entity->demux_unit->deallocate(payload_buffer_ptr); harq_entity->demux_unit->deallocate(payload_buffer_ptr);
} }
payload_buffer_ptr = NULL;
Info("DL %d (TB %d): %s tbs=%d, rv=%d, ack=%s, ndi=%d (%d), tti=%d (%d)\n", Info("DL %d (TB %d): %s tbs=%d, rv=%d, ack=%s, ndi=%d (%d), tti=%d (%d)\n",
pid, tid, is_new_transmission ? "newTX" : "reTX ", pid, tid, is_new_transmission ? "newTX" : "reTX ",
cur_grant.n_bytes[tid], cur_grant.rv[tid], ack ? "OK" : "KO", cur_grant.n_bytes[tid], cur_grant.rv[tid], ack ? "OK" : "KO",
cur_grant.ndi[tid], cur_grant.last_ndi[tid], cur_grant.tti, cur_grant.last_tti); cur_grant.ndi[tid], cur_grant.last_ndi[tid], cur_grant.tti, cur_grant.last_tti);
pthread_mutex_unlock(&mutex);
if (ack && pid == HARQ_BCCH_PID) { if (ack && pid == HARQ_BCCH_PID) {
reset(); reset();
} }
@ -363,6 +382,8 @@ private:
return is_new_transmission; return is_new_transmission;
} }
pthread_mutex_t mutex;
bool is_initiated; bool is_initiated;
dl_harq_entity *harq_entity; dl_harq_entity *harq_entity;
srslte::log *log_h; srslte::log *log_h;

@ -162,13 +162,24 @@ private:
void timer_alignment_expire(); void timer_alignment_expire();
srslte::timers timers; srslte::timers timers;
// pointer to MAC PCAP object // pointer to MAC PCAP object
srslte::mac_pcap* pcap; srslte::mac_pcap* pcap;
bool is_first_ul_grant; bool is_first_ul_grant;
mac_metrics_t metrics;
/* Class to run Timers in a dedicated thread */
class mac_timers : public periodic_thread {
public:
void init(srslte::timers *timers, srslte::log *log_h);
private:
void run_period();
srslte::timers *timers;
bool running;
srslte::log *log_h;
};
mac_metrics_t metrics; mac_timers mactimers;
/* Class to process MAC PDUs from DEMUX unit */ /* Class to process MAC PDUs from DEMUX unit */
class pdu_process : public thread { class pdu_process : public thread {

@ -104,7 +104,8 @@ private:
/* Msg3 Buffer */ /* Msg3 Buffer */
static const uint32_t MSG3_BUFF_SZ = 1024; static const uint32_t MSG3_BUFF_SZ = 1024;
uint8_t msg3_buff[MSG3_BUFF_SZ]; uint8_t msg3_buff[MSG3_BUFF_SZ];
uint8_t *msg3_buff_start_pdu;
/* PDU Buffer */ /* PDU Buffer */
srslte::sch_pdu pdu_msg; srslte::sch_pdu pdu_msg;
bool msg3_has_been_transmitted; bool msg3_has_been_transmitted;

@ -246,7 +246,6 @@ private:
} else { } else {
Warning("UL RAR grant available but no Msg3 on buffer\n"); Warning("UL RAR grant available but no Msg3 on buffer\n");
} }
printf("Transmitted Msg3\n");
// Normal UL grant // Normal UL grant
} else { } else {
@ -305,7 +304,7 @@ private:
bool is_msg3; bool is_msg3;
bool is_initiated; bool is_initiated;
uint32_t tti_last_tx; uint32_t tti_last_tx;
const static int payload_buffer_len = 128*1024; const static int payload_buffer_len = 128*1024;
uint8_t *payload_buffer; uint8_t *payload_buffer;

@ -61,9 +61,8 @@ public:
void reset_sync(); void reset_sync();
void cell_search_start(); void cell_search_start();
void cell_search_stop();
void cell_search_next(bool reset = false); void cell_search_next(bool reset = false);
bool cell_select(uint32_t earfcn, srslte_cell_t cell); void cell_select(uint32_t earfcn, srslte_cell_t cell);
bool cell_handover(srslte_cell_t cell); bool cell_handover(srslte_cell_t cell);
void meas_reset(); void meas_reset();
@ -95,7 +94,6 @@ private:
void reset(); void reset();
void radio_error(); void radio_error();
bool wait_radio_reset();
void set_ue_sync_opts(srslte_ue_sync_t *q, float cfo); void set_ue_sync_opts(srslte_ue_sync_t *q, float cfo);
void run_thread(); void run_thread();
@ -104,14 +102,11 @@ private:
bool set_cell(); bool set_cell();
void cell_search_inc(); void cell_search_inc();
void resync_sfn(bool is_connected = false, bool rx_now = false); void cell_reselect();
bool stop_sync();
void stop_rx(); uint32_t new_earfcn;
void start_rx(bool now = false); srslte_cell_t new_cell;
bool radio_is_rx;
bool radio_is_resetting;
bool running; bool running;
// Class to run cell search // Class to run cell search
@ -167,13 +162,14 @@ 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, srslte::radio *radio_h, void init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_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);
ret_code run_subframe(uint32_t sf_idx); ret_code run_subframe(uint32_t sf_idx);
ret_code run_subframe_sync(srslte_ue_sync_t *ue_sync, uint32_t sf_idx); ret_code run_subframe_sync(srslte_ue_sync_t *ue_sync, uint32_t sf_idx);
ret_code run_multiple_subframes(cf_t *buffer, uint32_t offset, uint32_t sf_idx, uint32_t nof_sf); ret_code run_multiple_subframes(cf_t *buffer, uint32_t offset, uint32_t sf_idx, uint32_t nof_sf);
float rssi();
float rsrp(); float rsrp();
float rsrq(); float rsrq();
float snr(); float snr();
@ -183,7 +179,6 @@ 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;
@ -235,7 +230,7 @@ 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 INTRA_FREQ_MEAS_LEN_MS = 20; const static int INTRA_FREQ_MEAS_LEN_MS = 50;
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; const static int INTRA_FREQ_MEAS_PRIO = DEFAULT_PRIORITY + 5;
@ -303,17 +298,18 @@ private:
const static uint32_t NOF_IN_SYNC_SF = 100; const static uint32_t NOF_IN_SYNC_SF = 100;
// State for primary cell // State for primary cell
enum { typedef enum {
IDLE = 0, IDLE = 0,
CELL_SEARCH, CELL_SEARCH,
CELL_SELECT, CELL_SELECT,
CELL_RESELECT, CELL_RESELECT,
CELL_MEASURE, CELL_MEASURE,
CELL_CAMP, CELL_CAMP,
IDLE_RX } phy_state_t;
} phy_state;
phy_state_t phy_state, prev_state;
bool is_in_idle, is_in_idle_rx; bool is_in_idle;
// Sampling rate mode (find is 1.96 MHz, camp is the full cell BW) // Sampling rate mode (find is 1.96 MHz, camp is the full cell BW)
enum { enum {
@ -335,7 +331,6 @@ private:
float ul_dl_factor; float ul_dl_factor;
uint32_t current_earfcn; uint32_t current_earfcn;
int cur_earfcn_index; int cur_earfcn_index;
bool cell_search_in_progress;
float dl_freq; float dl_freq;
float ul_freq; float ul_freq;

@ -119,7 +119,8 @@ private:
struct timeval tr_time[3]; struct timeval tr_time[3];
srslte::trace<uint32_t> tr_exec; srslte::trace<uint32_t> tr_exec;
bool trace_enabled; bool trace_enabled;
pthread_mutex_t mutex;
/* Common objects */ /* Common objects */
phch_common *phy; phch_common *phy;

@ -85,9 +85,8 @@ public:
void sync_reset(); void sync_reset();
void configure_ul_params(bool pregen_disabled = false); void configure_ul_params(bool pregen_disabled = false);
void cell_search_start(); void cell_search_start();
void cell_search_stop();
void cell_search_next(); void cell_search_next();
bool cell_select(uint32_t earfcn, srslte_cell_t phy_cell); void cell_select(uint32_t earfcn, srslte_cell_t phy_cell);
bool cell_handover(srslte_cell_t cell); bool cell_handover(srslte_cell_t cell);
void meas_reset(); void meas_reset();

@ -110,8 +110,6 @@ private:
srslte::log_filter gw_log; srslte::log_filter gw_log;
srslte::log_filter usim_log; srslte::log_filter usim_log;
srslte::byte_buffer_pool *pool;
all_args_t *args; all_args_t *args;
bool started; bool started;

@ -146,7 +146,7 @@ class ue_base
{ {
public: public:
ue_base(); ue_base();
virtual ~ue_base() {} virtual ~ue_base();
static ue_base* get_instance(srsue_instance_type_t type); static ue_base* get_instance(srsue_instance_type_t type);
@ -173,6 +173,9 @@ public:
std::string get_build_mode(); std::string get_build_mode();
std::string get_build_info(); std::string get_build_info();
std::string get_build_string(); std::string get_build_string();
private:
srslte::byte_buffer_pool *pool;
}; };
} // namespace srsue } // namespace srsue

@ -37,6 +37,7 @@
#include "srslte/common/security.h" #include "srslte/common/security.h"
#include "srslte/common/threads.h" #include "srslte/common/threads.h"
#include <math.h>
#include <map> #include <map>
#include <queue> #include <queue>
@ -65,12 +66,14 @@ class cell_t
return earfcn == this->earfcn && pci == phy_cell.id; return earfcn == this->earfcn && pci == phy_cell.id;
} }
bool greater(cell_t *x) { bool greater(cell_t *x) {
return x->rsrp > rsrp; return rsrp > x->rsrp;
} }
bool plmn_equals(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { bool plmn_equals(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
for (uint32_t i = 0; i < sib1.N_plmn_ids; i++) { if (has_valid_sib1) {
if (plmn_id.mcc == sib1.plmn_id[i].id.mcc && plmn_id.mnc == sib1.plmn_id[i].id.mnc) { for (uint32_t i = 0; i < sib1.N_plmn_ids; i++) {
return true; if (plmn_id.mcc == sib1.plmn_id[i].id.mcc && plmn_id.mnc == sib1.plmn_id[i].id.mnc) {
return true;
}
} }
} }
return false; return false;
@ -80,6 +83,7 @@ class cell_t
cell_t(tmp, 0, 0); cell_t(tmp, 0, 0);
} }
cell_t(srslte_cell_t phy_cell, uint32_t earfcn, float rsrp) { cell_t(srslte_cell_t phy_cell, uint32_t earfcn, float rsrp) {
gettimeofday(&last_update, NULL);
this->has_valid_sib1 = false; this->has_valid_sib1 = false;
this->has_valid_sib2 = false; this->has_valid_sib2 = false;
this->has_valid_sib3 = false; this->has_valid_sib3 = false;
@ -94,14 +98,108 @@ class cell_t
bzero(&sib13, sizeof(sib13)); bzero(&sib13, sizeof(sib13));
} }
uint32_t earfcn; uint32_t get_earfcn() {
return earfcn;
}
uint32_t get_pci() {
return phy_cell.id;
}
void set_rsrp(float rsrp) {
if (~isnan(rsrp)) {
this->rsrp = rsrp;
}
in_sync = true;
gettimeofday(&last_update, NULL);
}
float get_rsrp() {
return rsrp;
}
void set_sib1(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1) {
memcpy(&this->sib1, sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT));
has_valid_sib1 = true;
}
void set_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) {
memcpy(&this->sib2, sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT));
has_valid_sib2 = true;
}
void set_sib3(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3) {
memcpy(&this->sib3, sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT));
has_valid_sib3 = true;
}
void set_sib13(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13) {
memcpy(&this->sib13, sib13, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT));
has_valid_sib13 = true;
}
uint32_t timeout_secs(struct timeval now) {
struct timeval t[3];
memcpy(&t[2], &now, sizeof(struct timeval));
memcpy(&t[1], &last_update, sizeof(struct timeval));
get_time_interval(t);
return t[0].tv_sec;
}
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1ptr() {
return &sib1;
}
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2ptr() {
return &sib2;
}
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3ptr() {
return &sib3;
}
uint32_t get_cell_id() {
return sib1.cell_id;
}
bool has_sib1() {
return has_valid_sib1;
}
bool has_sib2() {
return has_valid_sib2;
}
bool has_sib3() {
return has_valid_sib3;
}
bool has_sib13() {
return has_valid_sib13;
}
uint16_t get_mcc() {
if (has_valid_sib1) {
if (sib1.N_plmn_ids > 0) {
return sib1.plmn_id[0].id.mcc;
}
}
return 0;
}
uint16_t get_mnc() {
if (has_valid_sib1) {
if (sib1.N_plmn_ids > 0) {
return sib1.plmn_id[0].id.mnc;
}
}
return 0;
}
srslte_cell_t phy_cell; srslte_cell_t phy_cell;
bool in_sync;
private:
float rsrp; float rsrp;
uint32_t earfcn;
struct timeval last_update;
bool has_valid_sib1; bool has_valid_sib1;
bool has_valid_sib2; bool has_valid_sib2;
bool has_valid_sib3; bool has_valid_sib3;
bool has_valid_sib13; bool has_valid_sib13;
bool in_sync;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1; LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2; LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3; LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3;
@ -157,7 +255,7 @@ public:
void in_sync(); void in_sync();
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_camping(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp);
void new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn, int pci); void new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn, int pci);
// MAC interface // MAC interface
@ -227,7 +325,7 @@ private:
static const uint32_t RRC_PLMN_SELECT_TIMEOUT = 10000; static const uint32_t RRC_PLMN_SELECT_TIMEOUT = 10000;
uint32_t select_cell_timeout; uint32_t select_cell_timeout;
static const uint32_t RRC_SELECT_CELL_TIMEOUT = 2000; static const uint32_t RRC_SELECT_CELL_TIMEOUT = 1000;
uint8_t k_rrc_enc[32]; uint8_t k_rrc_enc[32];
uint8_t k_rrc_int[32]; uint8_t k_rrc_int[32];
@ -274,6 +372,7 @@ private:
} }
// List of strongest neighbour cell // List of strongest neighbour cell
const static int NEIGHBOUR_TIMEOUT = 5;
const static int NOF_NEIGHBOUR_CELLS = 8; const static int NOF_NEIGHBOUR_CELLS = 8;
std::vector<cell_t*> neighbour_cells; std::vector<cell_t*> neighbour_cells;
cell_t *serving_cell; cell_t *serving_cell;
@ -285,6 +384,9 @@ private:
bool add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp); bool add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp);
bool add_neighbour_cell(cell_t *cell); bool add_neighbour_cell(cell_t *cell);
void sort_neighbour_cells(); void sort_neighbour_cells();
void clean_neighbours();
std::vector<cell_t*>::iterator delete_neighbour(std::vector<cell_t*>::iterator it);
void delete_neighbour(uint32_t cell_idx);
typedef enum { typedef enum {
SI_ACQUIRE_IDLE = 0, SI_ACQUIRE_IDLE = 0,
@ -315,6 +417,7 @@ private:
void run_tti(uint32_t tti); void run_tti(uint32_t tti);
bool timer_expired(uint32_t timer_id); bool timer_expired(uint32_t timer_id);
void ho_finish(); void ho_finish();
void delete_report(uint32_t earfcn, uint32_t pci);
private: private:
const static int NOF_MEASUREMENTS = 3; const static int NOF_MEASUREMENTS = 3;

@ -33,6 +33,7 @@ namespace srsue {
// RRC states (3GPP 36.331 v10.0.0) // RRC states (3GPP 36.331 v10.0.0)
typedef enum { typedef enum {
RRC_STATE_IDLE = 0, RRC_STATE_IDLE = 0,
RRC_STATE_PLMN_START,
RRC_STATE_PLMN_SELECTION, RRC_STATE_PLMN_SELECTION,
RRC_STATE_CELL_SELECTING, RRC_STATE_CELL_SELECTING,
RRC_STATE_CELL_SELECTED, RRC_STATE_CELL_SELECTED,
@ -44,11 +45,14 @@ typedef enum {
RRC_STATE_N_ITEMS, RRC_STATE_N_ITEMS,
} rrc_state_t; } rrc_state_t;
static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE",
"PLMN SELECTED",
"PLMN SELECTION", "PLMN SELECTION",
"CELL SELECTING", "CELL SELECTING",
"CELL SELECTED", "CELL SELECTED",
"CONNECTING", "CONNECTING",
"CONNECTED", "CONNECTED",
"HO PREPARE",
"HO PROCESS",
"LEAVE CONNECTED"}; "LEAVE CONNECTED"};
} // namespace srsue } // namespace srsue

@ -165,7 +165,14 @@ void demux::process_sch_pdu(srslte::sch_pdu *pdu_msg)
// Route logical channel // Route logical channel
if (route_pdu) { if (route_pdu) {
Info("Delivering PDU for lcid=%d, %d bytes\n", pdu_msg->get()->get_sdu_lcid(), pdu_msg->get()->get_payload_size()); Info("Delivering PDU for lcid=%d, %d bytes\n", pdu_msg->get()->get_sdu_lcid(), pdu_msg->get()->get_payload_size());
rlc->write_pdu(pdu_msg->get()->get_sdu_lcid(), pdu_msg->get()->get_sdu_ptr(), pdu_msg->get()->get_payload_size()); if (pdu_msg->get()->get_payload_size() < MAX_PDU_LEN) {
rlc->write_pdu(pdu_msg->get()->get_sdu_lcid(), pdu_msg->get()->get_sdu_ptr(), pdu_msg->get()->get_payload_size());
} else {
char tmp[1024];
srslte_vec_sprint_hex(tmp, pdu_msg->get()->get_sdu_ptr(), 32);
Error("PDU size %d exceeds maximum PDU buffer size, lcid=%d, hex=[%s]\n",
pdu_msg->get()->get_payload_size(), pdu_msg->get()->get_sdu_lcid(), tmp);
}
} }
} else { } else {
// Process MAC Control Element // Process MAC Control Element

@ -82,6 +82,7 @@ bool mac::init(phy_interface_mac *phy, rlc_interface_mac *rlc, rrc_interface_mac
started = true; started = true;
start(MAC_MAIN_THREAD_PRIO); start(MAC_MAIN_THREAD_PRIO);
mactimers.init(&timers, log_h);
return started; return started;
} }
@ -94,6 +95,7 @@ void mac::stop()
ttisync.increase(); ttisync.increase();
pdu_process_thread.stop(); pdu_process_thread.stop();
wait_thread_finish(); wait_thread_finish();
mactimers.stop();
} }
void mac::start_pcap(srslte::mac_pcap* pcap_) void mac::start_pcap(srslte::mac_pcap* pcap_)
@ -148,6 +150,17 @@ void mac::reset()
bzero(&uernti, sizeof(ue_rnti_t)); bzero(&uernti, sizeof(ue_rnti_t));
} }
void mac::mac_timers::init(srslte::timers *timers, srslte::log *log_h) {
this->timers = timers;
running = true;
this->log_h = log_h;
start_periodic(1000);
}
void mac::mac_timers::run_period() {
timers->step_all();
}
void mac::run_thread() { void mac::run_thread() {
int cnt=0; int cnt=0;
@ -165,7 +178,6 @@ void mac::run_thread() {
tti = ttisync.wait(); tti = ttisync.wait();
log_h->step(tti); log_h->step(tti);
timers.step_all();
// Step all procedures // Step all procedures
bsr_procedure.step(tti); bsr_procedure.step(tti);

@ -46,8 +46,9 @@ mux::mux(uint8_t nof_harq_proc_) : pdu_msg(MAX_NOF_SUBHEADERS), pid_has_bsr(nof_
log_h = NULL; log_h = NULL;
rlc = NULL; rlc = NULL;
bsr_procedure = NULL; bsr_procedure = NULL;
phr_procedure = NULL; phr_procedure = NULL;
msg3_buff_start_pdu = NULL;
msg3_flush(); msg3_flush();
} }
@ -347,6 +348,7 @@ void mux::msg3_flush()
msg3_has_been_transmitted = false; msg3_has_been_transmitted = false;
msg3_pending = false; msg3_pending = false;
bzero(msg3_buff, sizeof(MSG3_BUFF_SZ)); bzero(msg3_buff, sizeof(MSG3_BUFF_SZ));
msg3_buff_start_pdu = NULL;
} }
bool mux::msg3_is_transmitted() bool mux::msg3_is_transmitted()
@ -366,19 +368,22 @@ bool mux::msg3_is_pending() {
uint8_t* mux::msg3_get(uint8_t *payload, uint32_t pdu_sz) uint8_t* mux::msg3_get(uint8_t *payload, uint32_t pdu_sz)
{ {
if (pdu_sz < MSG3_BUFF_SZ - 32) { if (pdu_sz < MSG3_BUFF_SZ - 32) {
uint8_t* msg3_buff_start_pdu = pdu_get(msg3_buff, pdu_sz, 0, 0);
if (!msg3_buff_start_pdu) { if (!msg3_buff_start_pdu) {
Error("Moving PDU from Mux unit to Msg3 buffer\n"); msg3_buff_start_pdu = pdu_get(msg3_buff, pdu_sz, 0, 0);
return NULL; if (!msg3_buff_start_pdu) {
Error("Moving PDU from Mux unit to Msg3 buffer\n");
return NULL;
}
msg3_has_been_transmitted = true;
msg3_pending = false;
} }
memcpy(payload, msg3_buff_start_pdu, sizeof(uint8_t)*pdu_sz);
msg3_has_been_transmitted = true;
msg3_pending = false;
return payload;
} else { } else {
Error("Msg3 size (%d) is longer than internal msg3_buff size=%d, (see mux.h)\n", pdu_sz, MSG3_BUFF_SZ-32); Error("Msg3 size (%d) is longer than internal msg3_buff size=%d, (see mux.h)\n", pdu_sz, MSG3_BUFF_SZ-32);
return NULL; return NULL;
} }
memcpy(payload, msg3_buff_start_pdu, sizeof(uint8_t)*pdu_sz);
msg3_has_been_transmitted = true;
return payload;
} }

@ -159,11 +159,11 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
"Pregenerate uplink signals after attach. Improves CPU performance.") "Pregenerate uplink signals after attach. Improves CPU performance.")
("expert.rssi_sensor_enabled", ("expert.rssi_sensor_enabled",
bpo::value<bool>(&args->expert.phy.rssi_sensor_enabled)->default_value(true), bpo::value<bool>(&args->expert.phy.rssi_sensor_enabled)->default_value(false),
"Enable or disable RF frontend RSSI sensor. In some USRP devices can cause segmentation fault") "Enable or disable RF frontend RSSI sensor. In some USRP devices can cause segmentation fault")
("expert.rx_gain_offset", ("expert.rx_gain_offset",
bpo::value<float>(&args->expert.phy.rx_gain_offset)->default_value(10), bpo::value<float>(&args->expert.phy.rx_gain_offset)->default_value(62),
"RX Gain offset to add to rx_gain to correct RSRP value") "RX Gain offset to add to rx_gain to correct RSRP value")
("expert.prach_gain", ("expert.prach_gain",

@ -355,13 +355,16 @@ void phch_common::reset() {
void phch_common::reset_ul() void phch_common::reset_ul()
{ {
/*
is_first_tx = true; is_first_tx = true;
is_first_of_burst = true; is_first_of_burst = true;
for (uint32_t i=0;i<nof_mutex;i++) { for (uint32_t i=0;i<nof_mutex;i++) {
pthread_mutex_trylock(&tx_mutex[i]); pthread_mutex_trylock(&tx_mutex[i]);
pthread_mutex_unlock(&tx_mutex[i]); pthread_mutex_unlock(&tx_mutex[i]);
} }
radio_h->tx_end(); radio_h->tx_end();
*/
} }
} }

@ -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, radio_h, nof_rx_antennas); measure_p.init(sf_buffer, log_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);
@ -132,9 +132,7 @@ void phch_recv::reset()
next_offset = 0; next_offset = 0;
cell_is_set = false; cell_is_set = false;
srate_mode = SRATE_NONE; srate_mode = SRATE_NONE;
cell_search_in_progress = false;
current_earfcn = 0; current_earfcn = 0;
radio_is_resetting = false;
sfn_p.reset(); sfn_p.reset();
measure_p.reset(); measure_p.reset();
search_p.reset(); search_p.reset();
@ -144,33 +142,16 @@ void phch_recv::reset()
void phch_recv::radio_error() void phch_recv::radio_error()
{ {
log_h->error("SYNC: Receiving from radio.\n"); log_h->error("SYNC: Receiving from radio.\n");
phy_state = IDLE; phy_state = CELL_SEARCH;
radio_is_resetting=true;
// Need to find a method to effectively reset radio, reloading the driver does not work
//radio_h->reset();
radio_h->stop();
fprintf(stdout, "Error while receiving samples. Restart srsUE\n");
exit(-1);
reset(); reset();
radio_is_resetting=false; // Need to find a method to effectively reset radio, reloading the driver does not work
radio_h->reset();
} }
void phch_recv::set_cfo(float cfo) { void phch_recv::set_cfo(float cfo) {
srslte_ue_sync_set_cfo_ref(&ue_sync, cfo); srslte_ue_sync_set_cfo_ref(&ue_sync, cfo);
} }
bool phch_recv::wait_radio_reset() {
int cnt=0;
while(cnt < 20 && radio_is_resetting) {
sleep(1);
cnt++;
}
return radio_is_resetting;
}
void phch_recv::set_agc_enable(bool enable) void phch_recv::set_agc_enable(bool enable)
{ {
do_agc = enable; do_agc = enable;
@ -265,19 +246,6 @@ bool phch_recv::set_cell() {
return cell_is_set; return cell_is_set;
} }
void phch_recv::resync_sfn(bool is_connected, bool now) {
if (!now) {
wait_radio_reset();
stop_rx();
}
start_rx(now);
sfn_p.reset();
Info("SYNC: Starting SFN synchronization\n");
phy_state = is_connected?CELL_RESELECT:CELL_SELECT;
}
void phch_recv::set_earfcn(std::vector<uint32_t> earfcn) { void phch_recv::set_earfcn(std::vector<uint32_t> earfcn) {
this->earfcn = earfcn; this->earfcn = earfcn;
} }
@ -287,42 +255,24 @@ void phch_recv::force_freq(float dl_freq, float ul_freq) {
this->ul_freq = ul_freq; this->ul_freq = ul_freq;
} }
bool phch_recv::stop_sync() {
wait_radio_reset();
if (phy_state == IDLE && is_in_idle) {
return true;
} else {
Info("SYNC: Going to IDLE\n");
phy_state = IDLE;
int cnt = 0;
while (!is_in_idle && cnt < 100) {
usleep(10000);
cnt++;
}
if (!is_in_idle) {
Warning("SYNC: Could not go to IDLE\n");
}
return is_in_idle;
}
}
void phch_recv::reset_sync() { void phch_recv::reset_sync() {
Warning("SYNC: Resetting sync, cell_search_in_progress=%s\n", cell_search_in_progress?"yes":"no"); sfn_p.reset();
search_p.reset(); search_p.reset();
measure_p.reset();
srslte_ue_sync_reset(&ue_sync); srslte_ue_sync_reset(&ue_sync);
resync_sfn(true, true); Info("----- PHY RESET----\n");
phy_state = CELL_SELECT;
} }
void phch_recv::cell_search_inc() void phch_recv::cell_search_inc()
{ {
Info("cell_search_inc, cur_idx=%d, size=%d\n", cur_earfcn_index, earfcn.size());
cur_earfcn_index++; cur_earfcn_index++;
if (cur_earfcn_index >= 0) { if (cur_earfcn_index >= 0) {
if (cur_earfcn_index >= (int) earfcn.size()) { if (cur_earfcn_index >= (int) earfcn.size()) {
cur_earfcn_index = 0; cur_earfcn_index = 0;
phy_state = IDLE;
rrc->earfcn_end(); rrc->earfcn_end();
} else { } else {
Info("SYNC: Cell Search idx %d/%d\n", cur_earfcn_index, earfcn.size()); Info("SYNC: Cell Search idx %d/%d\n", cur_earfcn_index, earfcn.size());
@ -330,23 +280,16 @@ void phch_recv::cell_search_inc()
current_earfcn = earfcn[cur_earfcn_index]; current_earfcn = earfcn[cur_earfcn_index];
set_frequency(); set_frequency();
} }
phy_state = CELL_SEARCH;
} }
} }
} }
void phch_recv::cell_search_next(bool reset) { void phch_recv::cell_search_next(bool reset) {
if (cell_search_in_progress || reset) { if (reset) {
cell_search_in_progress = false; cur_earfcn_index = -1;
if (!stop_sync()) {
log_h->warning("SYNC: Couldn't stop PHY\n");
}
if (reset) {
cur_earfcn_index = -1;
}
cell_search_inc();
phy_state = CELL_SEARCH;
cell_search_in_progress = true;
} }
cell_search_inc();
} }
void phch_recv::cell_search_start() { void phch_recv::cell_search_start() {
@ -363,14 +306,6 @@ void phch_recv::cell_search_start() {
} }
} }
void phch_recv::cell_search_stop() {
Info("SYNC: Stopping Cell Search procedure...\n");
if (!stop_sync()) {
Error("SYNC: Stopping cell search\n");
}
cell_search_in_progress = false;
}
bool phch_recv::cell_handover(srslte_cell_t cell) bool phch_recv::cell_handover(srslte_cell_t cell)
{ {
int cnt = 0; int cnt = 0;
@ -383,20 +318,21 @@ bool phch_recv::cell_handover(srslte_cell_t cell)
bool ret = false; bool ret = false;
this->cell = cell; this->cell = cell;
Info("Cell HO: Stopping sync with current cell\n"); Info("Cell HO: Stopping sync with current cell\n");
worker_com->reset_ul(); phy_state = IDLE;
phy_state = IDLE_RX;
cnt = 0; cnt = 0;
while(!is_in_idle_rx && cnt<20) { while(!is_in_idle && cnt<20) {
usleep(1000); usleep(1000);
cnt++; cnt++;
} }
if (is_in_idle_rx) { for(uint32_t i=0;i<workers_pool->get_nof_workers();i++) {
((phch_worker*) workers_pool->get_worker(i))->reset();
}
worker_com->reset();
if (is_in_idle) {
Info("Cell HO: Reconfiguring cell\n"); Info("Cell HO: Reconfiguring cell\n");
if (set_cell()) { if (set_cell()) {
//resync_sfn(true, true);
sfn_p.reset();
phy_state = CELL_RESELECT;
Info("Cell HO: Synchronizing with new cell\n"); Info("Cell HO: Synchronizing with new cell\n");
phy_state = CELL_SELECT;
ret = true; ret = true;
} else { } else {
log_h->error("Cell HO: Configuring cell PCI=%d\n", cell.id); log_h->error("Cell HO: Configuring cell PCI=%d\n", cell.id);
@ -409,31 +345,35 @@ bool phch_recv::cell_handover(srslte_cell_t cell)
return ret; return ret;
} }
bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) { /* interface from higher layers to select a new cell */
void phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) {
new_earfcn = earfcn;
new_cell = cell;
phy_state = CELL_RESELECT;
}
/* Perform cell (re)-selection on IDLE or CAMP */
void phch_recv::cell_reselect()
{
uint32_t earfcn = new_earfcn;
srslte_cell_t cell = new_cell;
// Check if we are already camping in this cell Info("Reset from cell_reselect\n");
reset_sync();
// If we are already in the new cell, just resynchronize
if (earfcn == current_earfcn && this->cell.id == cell.id) { if (earfcn == current_earfcn && this->cell.id == cell.id) {
log_h->info("Cell Select: Already in cell EARFCN=%d\n", earfcn); log_h->info("Cell Select: Already in cell EARFCN=%d, PCI=%d\n", earfcn, cell.id);
cell_search_in_progress = false;
if (srate_mode != SRATE_CAMP) { if (srate_mode != SRATE_CAMP) {
set_sampling_rate(); set_sampling_rate();
log_h->info("Cell Select: Setting Camping sampling rate\n");
} }
if (phy_state < CELL_SELECT) {
resync_sfn();
}
return true;
} else { } else {
cell_search_in_progress = false;
if (!stop_sync()) {
log_h->warning("Still not in idle\n");
}
if (earfcn != current_earfcn) { if (earfcn != current_earfcn) {
if (set_frequency()) { if (set_frequency()) {
log_h->error("Cell Select: Configuring cell in EARFCN=%d, PCI=%d\n", earfcn, cell.id); log_h->error("Cell Select: Configuring cell in EARFCN=%d, PCI=%d\n", earfcn, cell.id);
return false;
} }
current_earfcn = earfcn; current_earfcn = earfcn;
} }
@ -443,13 +383,7 @@ bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) {
if (set_cell()) { if (set_cell()) {
log_h->info("Cell Select: Synchronizing on cell...\n"); log_h->info("Cell Select: Synchronizing on cell...\n");
resync_sfn();
usleep(500000); // Time offset we set start_rx to start receiving samples
return true;
} }
return false;
} }
} }
@ -514,22 +448,6 @@ void phch_recv::set_sampling_rate()
} }
} }
void phch_recv::stop_rx() {
if (radio_is_rx) {
Info("SYNC: Stopping RX streaming\n");
radio_h->stop_rx();
}
radio_is_rx = false;
}
void phch_recv::start_rx(bool now) {
if (!radio_is_rx) {
Info("SYNC: Starting RX streaming\n");
radio_h->start_rx(now);
}
radio_is_rx = true;
}
uint32_t phch_recv::get_current_tti() { uint32_t phch_recv::get_current_tti() {
return tti; return tti;
} }
@ -584,60 +502,61 @@ void phch_recv::run_thread()
uint32_t sf_idx = 0; uint32_t sf_idx = 0;
phy_state = IDLE; phy_state = IDLE;
is_in_idle = true; is_in_idle = true;
is_in_idle_rx = false;
cf_t *dummy_buffer[SRSLTE_MAX_PORTS];
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
dummy_buffer[i] = (cf_t*) malloc(sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100));
}
while (running) while (running)
{ {
if (phy_state != IDLE) { if (phy_state != IDLE) {
is_in_idle = false; is_in_idle = false;
Debug("SYNC: state=%d\n", phy_state);
}
if (phy_state != IDLE_RX) {
is_in_idle_rx = false;
} }
Debug("SYNC: state=%d\n", phy_state);
log_h->step(tti); log_h->step(tti);
log_phy_lib_h->step(tti); log_phy_lib_h->step(tti);
sf_idx = tti%10; sf_idx = tti%10;
prev_state = phy_state;
switch (phy_state) { switch (phy_state) {
case CELL_SEARCH: case CELL_SEARCH:
if (cell_search_in_progress) switch(search_p.run(&cell))
{ {
switch(search_p.run(&cell)) case search::CELL_FOUND:
{ if (!srslte_cell_isvalid(&cell)) {
case search::CELL_FOUND: Error("SYNC: Detected invalid cell\n");
if (!srslte_cell_isvalid(&cell)) { phy_state = IDLE;
Error("SYNC: Detected invalid cell\n");
phy_state = IDLE;
break;
}
if (set_cell()) {
set_sampling_rate();
resync_sfn();
}
break;
case search::CELL_NOT_FOUND:
if (cell_search_in_progress) {
cell_search_inc();
}
break;
default:
radio_error();
break; break;
} }
if (set_cell()) {
set_sampling_rate();
phy_state = CELL_SELECT;
}
break;
case search::CELL_NOT_FOUND:
cell_search_inc();
break;
default:
radio_error();
break;
} }
break; break;
case CELL_RESELECT: case CELL_RESELECT:
cell_reselect();
break;
case CELL_SELECT: case CELL_SELECT:
switch (sfn_p.run_subframe(&cell, &tti)) switch (sfn_p.run_subframe(&cell, &tti))
{ {
case sfn_sync::SFN_FOUND: case sfn_sync::SFN_FOUND:
if (!cell_search_in_progress) { if (prev_state != CELL_SEARCH) {
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;
rrc->cell_camping(earfcn[cur_earfcn_index], cell);
} else { } else {
log_h->info("Sync OK. Measuring PCI=%d...\n", cell.id); log_h->info("Sync OK. Measuring PCI=%d...\n", cell.id);
measure_p.reset(); measure_p.reset();
@ -645,13 +564,8 @@ void phch_recv::run_thread()
} }
break; break;
case sfn_sync::TIMEOUT: case sfn_sync::TIMEOUT:
if (cell_search_in_progress) { log_h->warning("SYNC: Timeout while synchronizing SFN. Going back to cell search\n");
log_h->warning("SYNC: Timeout while synchronizing SFN. Going back to cell search\n"); phy_state = CELL_SEARCH;
phy_state = CELL_SEARCH;
} else {
log_h->warning("SYNC: Timeout while synchronizing SFN. Reselecting cell\n");
resync_sfn(true, true);
}
break; break;
case sfn_sync::IDLE: case sfn_sync::IDLE:
break; break;
@ -661,12 +575,21 @@ void phch_recv::run_thread()
} }
break; break;
case CELL_MEASURE: case CELL_MEASURE:
switch(measure_p.run_subframe_sync(&ue_sync, sf_idx)) switch(measure_p.run_subframe_sync(&ue_sync, sf_idx))
{ {
case measure::MEASURE_OK: case measure::MEASURE_OK:
// Calibrate measure object since worker not yet calibrated
if (worker_com->args->rssi_sensor_enabled) {
measure_p.set_rx_gain_offset(measure_p.rssi() - radio_h->get_rssi() + 30);
} else {
measure_p.set_rx_gain_offset(worker_com->args->rx_gain_offset + radio_h->get_rx_gain());
}
log_h->info("SYNC: Measured OK. Camping on cell PCI=%d...\n", cell.id); log_h->info("SYNC: Measured OK. Camping on cell PCI=%d...\n", cell.id);
phy_state = CELL_CAMP; phy_state = CELL_CAMP;
rrc->cell_found(earfcn[cur_earfcn_index], cell, measure_p.rsrp()); rrc->cell_camping(earfcn[cur_earfcn_index], cell, measure_p.rsrp());
break; break;
case measure::IDLE: case measure::IDLE:
break; break;
@ -718,10 +641,11 @@ void phch_recv::run_thread()
tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex; tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex;
// Reset Uplink TX buffer to avoid mixing packets in TX queue // Reset Uplink TX buffer to avoid mixing packets in TX queue
/*
if (prach_buffer->is_pending()) { if (prach_buffer->is_pending()) {
Info("SYNC: PRACH pending: Reset UL\n"); Info("SYNC: PRACH pending: Reset UL\n");
worker_com->reset_ul(); radio_h->tx_end();
} }*/
// Check if we need to TX a PRACH // Check if we need to TX a PRACH
if (prach_buffer->is_ready_to_send(tti)) { if (prach_buffer->is_ready_to_send(tti)) {
@ -738,7 +662,9 @@ void phch_recv::run_thread()
if ((tti%5) == 0 && worker_com->args->sic_pss_enabled) { if ((tti%5) == 0 && worker_com->args->sic_pss_enabled) {
srslte_pss_sic(&ue_sync.strack.pss, &buffer[0][SRSLTE_SF_LEN_PRB(cell.nof_prb)/2-ue_sync.strack.fft_size]); srslte_pss_sic(&ue_sync.strack.pss, &buffer[0][SRSLTE_SF_LEN_PRB(cell.nof_prb)/2-ue_sync.strack.fft_size]);
} }
intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)); if (srslte_cell_isvalid(&cell)) {
intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
break; break;
case 0: case 0:
Warning("SYNC: Out-of-sync detected in PSS/SSS\n"); Warning("SYNC: Out-of-sync detected in PSS/SSS\n");
@ -756,28 +682,18 @@ void phch_recv::run_thread()
} }
break; break;
case IDLE: case IDLE:
if (!is_in_idle) { if (radio_h->is_init()) {
stop_rx(); uint32_t nsamples = 1920;
} if (current_srate > 0) {
is_in_idle = true; nsamples = current_srate/1000;
usleep(1000);
break;
case IDLE_RX:
if (!worker) {
worker = (phch_worker *) workers_pool->wait_worker(tti);
}
is_in_idle_rx = true;
if (worker) {
for (uint32_t i = 0; i < SRSLTE_MAX_PORTS; i++) {
buffer[i] = worker->get_buffer(i);
} }
if (!radio_h->rx_now(buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), NULL)) { if (!radio_h->rx_now(dummy_buffer, nsamples, NULL)) {
Error("SYNC: Receiving from radio while in IDLE_RX\n"); printf("SYNC: Receiving from radio while in IDLE_RX\n");
} }
} else { } else {
// wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here usleep(1000);
running = false;
} }
is_in_idle = true;
break; break;
} }
@ -897,8 +813,8 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell)
if (p->srate_mode != SRATE_FIND) { if (p->srate_mode != SRATE_FIND) {
p->srate_mode = SRATE_FIND; p->srate_mode = SRATE_FIND;
p->radio_h->set_rx_srate(1.92e6); p->radio_h->set_rx_srate(1.92e6);
Info("SYNC: Setting Cell Search sampling rate\n");
} }
p->start_rx();
/* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */ /* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */
uint32_t max_peak_cell = 0; uint32_t max_peak_cell = 0;
@ -918,7 +834,6 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell)
Error("SYNC: Error decoding MIB: Error searching PSS\n"); Error("SYNC: Error decoding MIB: Error searching PSS\n");
return ERROR; return ERROR;
} else if (ret == 0) { } else if (ret == 0) {
p->stop_rx();
Info("SYNC: Could not find any cell in this frequency\n"); Info("SYNC: Could not find any cell in this frequency\n");
return CELL_NOT_FOUND; return CELL_NOT_FOUND;
} }
@ -946,8 +861,6 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell)
ret = srslte_ue_mib_sync_decode(&ue_mib_sync, ret = srslte_ue_mib_sync_decode(&ue_mib_sync,
40, 40,
bch_payload, &cell->nof_ports, &sfn_offset); bch_payload, &cell->nof_ports, &sfn_offset);
p->stop_rx();
if (ret == 1) { if (ret == 1) {
srslte_pbch_mib_unpack(bch_payload, cell, NULL); srslte_pbch_mib_unpack(bch_payload, cell, NULL);
@ -1022,7 +935,7 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c
srslte_ue_sync_decode_sss_on_track(ue_sync, true); srslte_ue_sync_decode_sss_on_track(ue_sync, true);
int ret = srslte_ue_sync_zerocopy_multi(ue_sync, buffer); int ret = srslte_ue_sync_zerocopy_multi(ue_sync, buffer);
if (ret < 0) { if (ret < 0) {
Error("SYNC: Error calling ue_sync_get_buffer"); Error("SYNC: Error calling ue_sync_get_buffer.\n");
return ERROR; return ERROR;
} }
@ -1060,7 +973,7 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c
} }
} }
} else { } else {
Debug("SYNC: PSS/SSS not found...\n"); Info("SYNC: PSS/SSS not found...\n");
} }
cnt++; cnt++;
@ -1080,11 +993,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, srslte::radio *radio_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, 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++) {
this->buffer[i] = buffer[i]; this->buffer[i] = buffer[i];
@ -1117,17 +1029,21 @@ void phch_recv::measure::set_cell(srslte_cell_t cell)
} }
reset(); reset();
} }
float phch_recv::measure::rssi() {
return 10*log10(mean_rssi);
}
float phch_recv::measure::rsrp() { float phch_recv::measure::rsrp() {
return mean_rsrp; return 10*log10(mean_rsrp) + 30 - rx_gain_offset;
} }
float phch_recv::measure::rsrq() { float phch_recv::measure::rsrq() {
return mean_rsrq; return 10*log10(mean_rsrq);
} }
float phch_recv::measure::snr() { float phch_recv::measure::snr() {
return mean_snr; return 10*log10(mean_snr);
} }
uint32_t phch_recv::measure::frame_st_idx() { uint32_t phch_recv::measure::frame_st_idx() {
@ -1228,10 +1144,10 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx)
return ERROR; return ERROR;
} }
float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30 - rx_gain_offset; float rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest);
float rsrq = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest)); float rsrq = srslte_chest_dl_get_rsrq(&ue_dl.chest);
float snr = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)); float snr = 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; float rssi = srslte_vec_avg_power_cf(buffer[0], SRSLTE_SF_LEN_PRB(current_prb));
if (cnt == 0) { if (cnt == 0) {
mean_rsrp = rsrp; mean_rsrp = rsrp;
@ -1250,17 +1166,6 @@ 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 (fabsf(rx_gain_offset) < 1.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;
}
return MEASURE_OK; return MEASURE_OK;
} else { } else {
return IDLE; return IDLE;
@ -1289,7 +1194,7 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3
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, NULL, 1, max_sf_window); measure_p.init(sf_buffer, log_h, 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, max_sf_window*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)) {
@ -1594,6 +1499,7 @@ void phch_recv::intra_measure::run_thread()
} }
if (running) { if (running) {
// Read data from buffer and find cells in it // 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, INTRA_FREQ_MEAS_LEN_MS*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, INTRA_FREQ_MEAS_LEN_MS, info);

@ -140,29 +140,35 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h, srslte::log *log_ph
mem_initiated = true; mem_initiated = true;
pthread_mutex_init(&mutex, NULL);
return true; return true;
} }
bool phch_worker::set_cell(srslte_cell_t cell_) bool phch_worker::set_cell(srslte_cell_t cell_)
{ {
bool ret = false;
pthread_mutex_lock(&mutex);
if (cell.id != cell_.id || !cell_initiated) { if (cell.id != cell_.id || !cell_initiated) {
memcpy(&cell, &cell_, sizeof(srslte_cell_t)); memcpy(&cell, &cell_, sizeof(srslte_cell_t));
if (srslte_ue_dl_set_cell(&ue_dl, cell)) { if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
Error("Initiating UE DL\n"); Error("Initiating UE DL\n");
return false; goto unlock;
} }
if (srslte_ue_ul_set_cell(&ue_ul, cell)) { if (srslte_ue_ul_set_cell(&ue_ul, cell)) {
Error("Initiating UE UL\n"); Error("Initiating UE UL\n");
return false; goto unlock;
} }
srslte_ue_ul_set_normalization(&ue_ul, true); srslte_ue_ul_set_normalization(&ue_ul, true);
srslte_ue_ul_set_cfo_enable(&ue_ul, true); srslte_ue_ul_set_cfo_enable(&ue_ul, true);
cell_initiated = true; cell_initiated = true;
} }
return true; ret = true;
unlock:
pthread_mutex_unlock(&mutex);
return ret;
} }
cf_t* phch_worker::get_buffer(uint32_t antenna_idx) cf_t* phch_worker::get_buffer(uint32_t antenna_idx)
@ -195,7 +201,7 @@ void phch_worker::set_crnti(uint16_t rnti)
{ {
srslte_ue_dl_set_rnti(&ue_dl, rnti); srslte_ue_dl_set_rnti(&ue_dl, rnti);
srslte_ue_ul_set_rnti(&ue_ul, rnti); srslte_ue_ul_set_rnti(&ue_ul, rnti);
rnti_is_set = true; rnti_is_set = true;
} }
float phch_worker::get_ref_cfo() float phch_worker::get_ref_cfo()
@ -243,7 +249,9 @@ void phch_worker::work_imp()
if (!cell_initiated) { if (!cell_initiated) {
return; return;
} }
pthread_mutex_lock(&mutex);
Debug("TTI %d running\n", tti); Debug("TTI %d running\n", tti);
#ifdef LOG_EXECTIME #ifdef LOG_EXECTIME
@ -402,7 +410,7 @@ void phch_worker::work_imp()
update_measurements(); update_measurements();
if (chest_ok) { if (chest_ok) {
if (phy->avg_rsrp_dbm > -130.0 && phy->avg_snr_db > -30.0) { if (phy->avg_rsrp_dbm > -130.0 && phy->avg_snr_db > -20.0) {
log_h->debug("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n", log_h->debug("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n",
10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)), phy->avg_rsrp_dbm); 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)), phy->avg_rsrp_dbm);
chest_loop->in_sync(); chest_loop->in_sync();
@ -412,7 +420,9 @@ void phch_worker::work_imp()
chest_loop->out_of_sync(); chest_loop->out_of_sync();
} }
} }
pthread_mutex_unlock(&mutex);
/* Tell the plotting thread to draw the plots */ /* Tell the plotting thread to draw the plots */
#ifdef ENABLE_GUI #ifdef ENABLE_GUI
if ((int) get_id() == plot_worker_id) { if ((int) get_id() == plot_worker_id) {
@ -1211,6 +1221,7 @@ void phch_worker::enable_pregen_signals(bool enabled)
void phch_worker::set_ul_params(bool pregen_disabled) void phch_worker::set_ul_params(bool pregen_disabled)
{ {
phy_interface_rrc::phy_cfg_common_t *common = &phy->config->common; phy_interface_rrc::phy_cfg_common_t *common = &phy->config->common;
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &phy->config->dedicated; LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &phy->config->dedicated;
@ -1380,7 +1391,7 @@ void phch_worker::update_measurements()
/* Only worker 0 reads the RSSI sensor every ~1-nof_cores s */ /* Only worker 0 reads the RSSI sensor every ~1-nof_cores s */
if (get_id() == 0) { if (get_id() == 0) {
if (rssi_read_cnt) { if (!rssi_read_cnt) {
if (phy->get_radio()->has_rssi() && phy->args->rssi_sensor_enabled) { if (phy->get_radio()->has_rssi() && phy->args->rssi_sensor_enabled) {
phy->last_radio_rssi = phy->get_radio()->get_rssi(); phy->last_radio_rssi = phy->get_radio()->get_rssi();
phy->rx_gain_offset = phy->avg_rssi_dbm - phy->last_radio_rssi + 30; phy->rx_gain_offset = phy->avg_rssi_dbm - phy->last_radio_rssi + 30;

@ -256,11 +256,6 @@ void phy::cell_search_start()
sf_recv.cell_search_start(); sf_recv.cell_search_start();
} }
void phy::cell_search_stop()
{
sf_recv.cell_search_stop();
}
void phy::cell_search_next() void phy::cell_search_next()
{ {
sf_recv.cell_search_next(); sf_recv.cell_search_next();
@ -282,9 +277,9 @@ int phy::meas_stop(uint32_t earfcn, int pci) {
return sf_recv.meas_stop(earfcn, pci); return sf_recv.meas_stop(earfcn, pci);
} }
bool phy::cell_select(uint32_t earfcn, srslte_cell_t phy_cell) void phy::cell_select(uint32_t earfcn, srslte_cell_t phy_cell)
{ {
return sf_recv.cell_select(earfcn, phy_cell); sf_recv.cell_select(earfcn, phy_cell);
} }
bool phy::cell_handover(srslte_cell_t cell) { bool phy::cell_handover(srslte_cell_t cell) {
@ -366,8 +361,6 @@ void phy::reset()
workers[i].reset(); workers[i].reset();
} }
workers_common.reset(); workers_common.reset();
usleep(4000);
workers_common.reset_ul();
} }
uint32_t phy::get_current_tti() uint32_t phy::get_current_tti()

@ -40,12 +40,10 @@ namespace srsue{
ue::ue() ue::ue()
:started(false) :started(false)
{ {
pool = byte_buffer_pool::get_instance();
} }
ue::~ue() ue::~ue()
{ {
byte_buffer_pool::cleanup();
} }
bool ue::init(all_args_t *args_) bool ue::init(all_args_t *args_)
@ -306,8 +304,13 @@ void ue::rf_msg(srslte_rf_error_t error)
{ {
ue_base *ue = ue_base::get_instance(LTE); ue_base *ue = ue_base::get_instance(LTE);
ue->handle_rf_msg(error); ue->handle_rf_msg(error);
if(error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_OVERFLOW) { if (error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_OVERFLOW) {
ue->radio_overflow(); ue->radio_overflow();
} else
if (error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_RX) {
ue->stop();
ue->cleanup();
exit(-1);
} }
} }

@ -64,6 +64,12 @@ ue_base::ue_base() {
// load FFTW wisdom // load FFTW wisdom
srslte_dft_load(); srslte_dft_load();
pool = byte_buffer_pool::get_instance();
}
ue_base::~ue_base() {
byte_buffer_pool::cleanup();
} }
void ue_base::cleanup(void) void ue_base::cleanup(void)

@ -161,17 +161,21 @@ void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_
// RRC indicates that the UE has gone through all EARFCN and finished PLMN selection // RRC indicates that the UE has gone through all EARFCN and finished PLMN selection
void nas::plmn_search_end() { void nas::plmn_search_end() {
if (known_plmns.size() > 0) { if (known_plmns.size() > 0) {
nas_log->info("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n", if (home_plmn.mcc != known_plmns[0].mcc && home_plmn.mnc != known_plmns[0].mnc) {
plmn_id_to_string(home_plmn).c_str(), nas_log->info("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n",
plmn_id_to_string(known_plmns[0]).c_str()); plmn_id_to_string(home_plmn).c_str(),
plmn_id_to_string(known_plmns[0]).c_str());
nas_log->console("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n",
plmn_id_to_string(home_plmn).c_str(), nas_log->console("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n",
plmn_id_to_string(known_plmns[0]).c_str()); plmn_id_to_string(home_plmn).c_str(),
plmn_id_to_string(known_plmns[0]).c_str());
}
rrc->plmn_select(known_plmns[0]); rrc->plmn_select(known_plmns[0]);
} else { } else {
nas_log->debug("Finished searching PLMN in current EARFCN set but no networks were found.\n"); nas_log->info("Finished searching PLMN in current EARFCN set but no networks were found.\n");
if (state == EMM_STATE_REGISTERED_INITIATED && plmn_selection == PLMN_NOT_SELECTED) {
rrc->plmn_search();
}
} }
} }

@ -54,6 +54,7 @@ rrc::rrc()
n310_cnt = 0; n310_cnt = 0;
n311_cnt = 0; n311_cnt = 0;
serving_cell = new cell_t(); serving_cell = new cell_t();
neighbour_cells.reserve(NOF_NEIGHBOUR_CELLS);
} }
rrc::~rrc() rrc::~rrc()
@ -168,6 +169,7 @@ void rrc::set_args(rrc_args_t *args) {
void rrc::run_thread() { void rrc::run_thread() {
uint32_t failure_test = 0; uint32_t failure_test = 0;
uint32_t cell_clean_cnt = 0;
while (thread_running) { while (thread_running) {
@ -185,6 +187,7 @@ void rrc::run_thread() {
sleep(1); sleep(1);
rrc_log->info("RRC IDLE: NAS is attaching and camping on cell, reselecting...\n"); rrc_log->info("RRC IDLE: NAS is attaching and camping on cell, reselecting...\n");
plmn_select_rrc(selected_plmn_id); plmn_select_rrc(selected_plmn_id);
connection_requested = true;
} }
// If not camping on a cell // If not camping on a cell
} else { } else {
@ -200,15 +203,18 @@ void rrc::run_thread() {
// If not attached, PLMN selection will be triggered from higher layers // If not attached, PLMN selection will be triggered from higher layers
} }
break; break;
case RRC_STATE_PLMN_START:
rrc_log->info("RRC PLMN Search: Starting cell search\n");
plmn_select_timeout = 0;
phy->cell_search_start();
state = RRC_STATE_PLMN_SELECTION;
break;
case RRC_STATE_PLMN_SELECTION: case RRC_STATE_PLMN_SELECTION:
plmn_select_timeout++; plmn_select_timeout++;
if (plmn_select_timeout >= RRC_PLMN_SELECT_TIMEOUT) { if (plmn_select_timeout >= RRC_PLMN_SELECT_TIMEOUT) {
rrc_log->info("RRC PLMN Search: timeout expired\n"); rrc_log->info("RRC PLMN Search: timeout expired\n");
phy->cell_search_stop(); rrc_log->console("\nRRC PLMN Search: timeout expired.\n");
sleep(1); state = RRC_STATE_IDLE;
rrc_log->console("\nRRC PLMN Search: timeout expired. Searching again\n");
plmn_select_timeout = 0;
phy->cell_search_start();
} }
break; break;
case RRC_STATE_CELL_SELECTING: case RRC_STATE_CELL_SELECTING:
@ -217,26 +223,25 @@ 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 (!serving_cell->has_valid_sib1) { if (!serving_cell->has_sib1()) {
si_acquire_state = SI_ACQUIRE_SIB1; si_acquire_state = SI_ACQUIRE_SIB1;
sysinfo_index = 0; sysinfo_index = 0;
} else if (!serving_cell->has_valid_sib2) { } else if (!serving_cell->has_sib2()) {
si_acquire_state = SI_ACQUIRE_SIB2; si_acquire_state = SI_ACQUIRE_SIB2;
} else { } else {
apply_sib2_configs(&serving_cell->sib2); apply_sib2_configs(serving_cell->sib2ptr());
si_acquire_state = SI_ACQUIRE_IDLE; si_acquire_state = SI_ACQUIRE_IDLE;
state = RRC_STATE_CELL_SELECTED; state = RRC_STATE_CELL_SELECTED;
} }
} }
// Don't time out during restablishment (T311 running) // Don't time out during reestablishment (T311 running)
if (!mac_timers->timer_get(t311)->is_running()) { if (!mac_timers->timer_get(t311)->is_running() || !phy->sync_status()) {
select_cell_timeout++; select_cell_timeout++;
if (select_cell_timeout >= RRC_SELECT_CELL_TIMEOUT) { if (select_cell_timeout >= RRC_SELECT_CELL_TIMEOUT) {
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;
select_cell_timeout = 0; select_cell_timeout = 0;
state = RRC_STATE_PLMN_START;
serving_cell->in_sync = false; serving_cell->in_sync = false;
phy->cell_search_start();
} }
} }
break; break;
@ -302,6 +307,13 @@ void rrc::run_thread() {
default: default:
break; break;
} }
if (state == RRC_STATE_CONNECTED || RRC_STATE_IDLE) {
cell_clean_cnt++;
if (cell_clean_cnt==1000) {
clean_neighbours();
cell_clean_cnt = 0;
}
}
usleep(1000); usleep(1000);
} }
} }
@ -342,7 +354,7 @@ void rrc::run_si_acquisition_procedure()
tti = mac->get_current_tti(); tti = mac->get_current_tti();
si_win_start = sib_start_tti(tti, 2, 0, 5); si_win_start = sib_start_tti(tti, 2, 0, 5);
if (last_win_start == 0 || if (last_win_start == 0 ||
(srslte_tti_interval(last_win_start, tti) > 20 && srslte_tti_interval(last_win_start, tti) < 1000)) (srslte_tti_interval(tti, last_win_start) >= 20 && srslte_tti_interval(tti, last_win_start) < 1000))
{ {
last_win_start = si_win_start; last_win_start = si_win_start;
@ -363,24 +375,24 @@ 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 < serving_cell->sib1.N_sched_info) { if(sysinfo_index < serving_cell->sib1ptr()->N_sched_info) {
si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length]; si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->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[serving_cell->sib1.sched_info[sysinfo_index].si_periodicity]; period = liblte_rrc_si_periodicity_num[serving_cell->sib1ptr()->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);
si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length]; si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length];
if (last_win_start == 0 || if (last_win_start == 0 ||
(srslte_tti_interval(last_win_start, tti) > period*10 && srslte_tti_interval(last_win_start, tti) < 1000)) (srslte_tti_interval(tti, last_win_start) > period*10 && srslte_tti_interval(tti, last_win_start) < 1000))
{ {
last_win_start = si_win_start; last_win_start = si_win_start;
mac->bcch_start_rx(si_win_start, si_win_len); mac->bcch_start_rx(si_win_start, si_win_len);
rrc_log->info("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",
si_win_start, si_win_len); si_win_start, si_win_len);
} }
@ -416,24 +428,15 @@ void rrc::run_si_acquisition_procedure()
*******************************************************************************/ *******************************************************************************/
uint16_t rrc::get_mcc() { uint16_t rrc::get_mcc() {
if (serving_cell->sib1.N_plmn_ids > 0) { return serving_cell->get_mcc();
return serving_cell->sib1.plmn_id[0].id.mcc;
}
return 0;
} }
uint16_t rrc::get_mnc() { uint16_t rrc::get_mnc() {
if (serving_cell->sib1.N_plmn_ids > 0) { return serving_cell->get_mnc();
return serving_cell->sib1.plmn_id[0].id.mnc;
}
return 0;
} }
void rrc::plmn_search() { void rrc::plmn_search() {
rrc_log->info("Starting PLMN search procedure\n"); state = RRC_STATE_PLMN_START;
state = RRC_STATE_PLMN_SELECTION;
phy->cell_search_start();
plmn_select_timeout = 0;
} }
/* This is the NAS interface. When NAS requests to select a PLMN we have to /* This is the NAS interface. When NAS requests to select a PLMN we have to
@ -452,17 +455,30 @@ void rrc::plmn_select_rrc(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
if (state == RRC_STATE_IDLE || state == RRC_STATE_CONNECTED || state == RRC_STATE_PLMN_SELECTION) { if (state == RRC_STATE_IDLE || state == RRC_STATE_CONNECTED || state == RRC_STATE_PLMN_SELECTION) {
if (phy->sync_status() && selected_plmn_id.mcc == plmn_id.mcc && selected_plmn_id.mnc == plmn_id.mnc) { if (phy->sync_status() && selected_plmn_id.mcc == plmn_id.mcc && selected_plmn_id.mnc == plmn_id.mnc) {
rrc_log->info("Already camping on selected PLMN, connecting...\n"); rrc_log->info("Already camping on selected PLMN, connecting...\n");
state = RRC_STATE_CELL_SELECTING;
select_cell_timeout = 0;
} else { } else {
rrc_log->info("PLMN Id=%s selected\n", plmn_id_to_string(plmn_id).c_str());
// Sort cells according to RSRP
selected_plmn_id = plmn_id; selected_plmn_id = plmn_id;
select_cell_timeout = 0;
state = RRC_STATE_CELL_SELECTING; if (serving_cell->plmn_equals(selected_plmn_id)) {
phy->cell_select(serving_cell->get_earfcn(), serving_cell->phy_cell);
} else {
bool found = false;
for (uint32_t i=0;i<neighbour_cells.size() && !found;i++) {
if (neighbour_cells[i]->plmn_equals(selected_plmn_id)) {
rrc_log->info("PLMN Id=%s selected, PCI=%d\n", plmn_id_to_string(plmn_id).c_str(), neighbour_cells[i]->get_pci());
phy->cell_select(neighbour_cells[i]->get_earfcn(), neighbour_cells[i]->phy_cell);
found = true;
}
}
if (!found) {
rrc_log->warning("Could not find any cell for the selected PLMN\n");
state = RRC_STATE_IDLE;
return;
}
}
} }
state = RRC_STATE_CELL_SELECTING;
select_cell_timeout = 0;
} 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]);
} }
@ -491,7 +507,7 @@ void rrc::set_serving_cell(uint32_t cell_idx) {
// Move serving cell to neighbours list // Move serving cell to neighbours list
if (serving_cell->is_valid()) { if (serving_cell->is_valid()) {
// Make sure it does not exist already // Make sure it does not exist already
int serving_idx = find_neighbour_cell(serving_cell->earfcn, serving_cell->phy_cell.id); int serving_idx = find_neighbour_cell(serving_cell->get_earfcn(), serving_cell->phy_cell.id);
if (serving_idx >= 0 && (uint32_t) serving_idx < neighbour_cells.size()) { if (serving_idx >= 0 && (uint32_t) serving_idx < neighbour_cells.size()) {
printf("Error serving cell is already in the neighbour list. Removing it\n"); 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()); neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[serving_idx]), neighbour_cells.end());
@ -506,7 +522,7 @@ void rrc::set_serving_cell(uint32_t cell_idx) {
serving_cell = new_serving_cell; serving_cell = new_serving_cell;
rrc_log->info("Setting serving cell idx=%d, earfcn=%d, PCI=%d, nof_neighbours=%d\n", 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()); cell_idx, serving_cell->get_earfcn(), serving_cell->phy_cell.id, neighbour_cells.size());
} else { } else {
rrc_log->error("Setting invalid serving cell idx %d\n", cell_idx); rrc_log->error("Setting invalid serving cell idx %d\n", cell_idx);
@ -520,20 +536,14 @@ void rrc::select_next_cell_in_plmn() {
neighbour_cells[i]->in_sync) // matches S criteria neighbour_cells[i]->in_sync) // matches S criteria
{ {
// Try to select Cell // Try to select Cell
if (phy->cell_select(neighbour_cells[i]->earfcn, neighbour_cells[i]->phy_cell)) { phy->cell_select(neighbour_cells[i]->get_earfcn(), neighbour_cells[i]->phy_cell);
set_serving_cell(i); set_serving_cell(i);
rrc_log->info("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n", rrc_log->info("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
serving_cell->phy_cell.id, serving_cell->earfcn, serving_cell->phy_cell.id, serving_cell->get_earfcn(),
serving_cell->sib1.cell_id); serving_cell->get_cell_id());
rrc_log->console("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n", rrc_log->console("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
serving_cell->phy_cell.id, serving_cell->earfcn, serving_cell->phy_cell.id, serving_cell->get_earfcn(),
serving_cell->sib1.cell_id); serving_cell->get_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; return;
} }
} }
@ -543,7 +553,7 @@ void rrc::select_next_cell_in_plmn() {
void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int pci_i) { 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) { if (earfcn_i < 0 || pci_i < 0) {
earfcn_i = serving_cell->earfcn; earfcn_i = serving_cell->get_earfcn();
pci_i = serving_cell->phy_cell.id; pci_i = serving_cell->phy_cell.id;
} }
@ -560,7 +570,7 @@ void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int p
// Update serving cell // Update serving cell
if (serving_cell->equals(earfcn, pci)) { if (serving_cell->equals(earfcn, pci)) {
cell_reselection_eval(rsrp, rsrq); cell_reselection_eval(rsrp, rsrq);
serving_cell->rsrp = rsrp; serving_cell->set_rsrp(rsrp);
rrc_log->info("MEAS: New measurement serving cell in IDLE, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti); 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 // Or update/add neighbour cell
@ -573,43 +583,45 @@ void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int p
} }
// Verify cell selection criteria with strongest neighbour cell (always first) // Verify cell selection criteria with strongest neighbour cell (always first)
if (cell_selection_eval(neighbour_cells[0]->rsrp) && if (neighbour_cells.size() > 1 &&
neighbour_cells[0]->rsrp > serving_cell->rsrp + 5) cell_selection_eval(neighbour_cells[0]->get_rsrp()) &&
neighbour_cells[0]->get_rsrp() > serving_cell->get_rsrp() + 5)
{ {
set_serving_cell(0); 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); rrc_log->info("Selecting best neighbour cell PCI=%d, rsrp=%.1f dBm\n", serving_cell->phy_cell.id, serving_cell->get_rsrp());
state = RRC_STATE_CELL_SELECTING; state = RRC_STATE_CELL_SELECTING;
phy->cell_select(serving_cell->earfcn, serving_cell->phy_cell); phy->cell_select(serving_cell->get_earfcn(), serving_cell->phy_cell);
} }
} }
} }
void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { /* PHY begins camping in a cell. RRC updates RSRP measurement,
* proceeds with PLMN selection/cell search if applicable and sets
* new cell as current serving cell */
void rrc::cell_camping(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
bool found = false; bool found = false;
int cell_idx = -1; int cell_idx = -1;
if (serving_cell->equals(earfcn, phy_cell.id)) { if (serving_cell->equals(earfcn, phy_cell.id)) {
serving_cell->rsrp = rsrp; serving_cell->set_rsrp(rsrp);
serving_cell->in_sync = true;
found = true; found = true;
} else { } else {
// Check if cell is in our list of neighbour cells // Check if cell is in our list of neighbour cells
cell_idx = find_neighbour_cell(earfcn, phy_cell.id); cell_idx = find_neighbour_cell(earfcn, phy_cell.id);
if (cell_idx >= 0) { if (cell_idx >= 0) {
set_serving_cell(cell_idx); set_serving_cell(cell_idx);
serving_cell->rsrp = rsrp; serving_cell->set_rsrp(rsrp);
serving_cell->in_sync = true;
found = true; found = true;
} }
} }
if (found) { if (found) {
if (!serving_cell->has_valid_sib1) { if (!serving_cell->has_sib1()) {
si_acquire_state = SI_ACQUIRE_SIB1; si_acquire_state = SI_ACQUIRE_SIB1;
} else if (state == RRC_STATE_PLMN_SELECTION) { } else if (state == RRC_STATE_PLMN_SELECTION) {
for (uint32_t j = 0; j < serving_cell->sib1.N_plmn_ids; j++) { for (uint32_t j = 0; j < serving_cell->sib1ptr()->N_plmn_ids; j++) {
nas->plmn_found(serving_cell->sib1.plmn_id[j].id, serving_cell->sib1.tracking_area_code); nas->plmn_found(serving_cell->sib1ptr()->plmn_id[j].id, serving_cell->sib1ptr()->tracking_area_code);
} }
usleep(5000); usleep(5000);
phy->cell_search_next(); phy->cell_search_next();
@ -623,7 +635,6 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
phy->cell_search_next(); phy->cell_search_next();
} else { } else {
set_serving_cell(earfcn, phy_cell.id); set_serving_cell(earfcn, phy_cell.id);
si_acquire_state = SI_ACQUIRE_SIB1; si_acquire_state = SI_ACQUIRE_SIB1;
} }
} }
@ -631,22 +642,54 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
rrc_log->info("%s %s cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n", rrc_log->info("%s %s cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n",
found?"Updating":"Adding", found?"Updating":"Adding",
cell_idx>=0?"neighbour":"serving", cell_idx>=0?"neighbour":"serving",
serving_cell->earfcn, serving_cell->get_earfcn(),
serving_cell->phy_cell.id, serving_cell->phy_cell.id,
serving_cell->rsrp); serving_cell->get_rsrp());
} }
bool sort_rsrp(cell_t *u1, cell_t *u2) { bool sort_rsrp(cell_t *u1, cell_t *u2) {
return !u1->greater(u2); return u1->greater(u2);
} }
// Sort neighbour cells by decreasing order of RSRP void rrc::delete_neighbour(uint32_t cell_idx) {
void rrc::sort_neighbour_cells() { measurements.delete_report(neighbour_cells[cell_idx]->get_earfcn(), neighbour_cells[cell_idx]->get_pci());
delete neighbour_cells[cell_idx];
neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[cell_idx]), neighbour_cells.end());
}
for (uint32_t i=1;i<neighbour_cells.size();i++) { std::vector<cell_t*>::iterator rrc::delete_neighbour(std::vector<cell_t*>::iterator it) {
if (neighbour_cells[i]->in_sync == false) { measurements.delete_report((*it)->get_earfcn(), (*it)->get_pci());
rrc_log->info("Removing neighbour cell PCI=%d, out_of_sync\n", neighbour_cells[i]->phy_cell.id); delete (*it);
neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[i]), neighbour_cells.end()); return neighbour_cells.erase(it);
}
void rrc::clean_neighbours()
{
struct timeval now;
gettimeofday(&now, NULL);
std::vector<cell_t*>::iterator it = neighbour_cells.begin();
while(it != neighbour_cells.end()) {
if ((*it)->timeout_secs(now) > NEIGHBOUR_TIMEOUT) {
rrc_log->info("Neighbour PCI=%d timed out. Deleting\n", (*it)->get_pci());
it = delete_neighbour(it);
} else {
++it;
}
}
}
// Sort neighbour cells by decreasing order of RSRP
void rrc::sort_neighbour_cells()
{
// Remove out-of-sync cells
std::vector<cell_t*>::iterator it = neighbour_cells.begin();
while(it != neighbour_cells.end()) {
if ((*it)->in_sync == false) {
rrc_log->info("Neighbour PCI=%d is out-of-sync. Deleting\n", (*it)->get_pci());
it = delete_neighbour(it);
} else {
++it;
} }
} }
@ -654,28 +697,27 @@ void rrc::sort_neighbour_cells() {
char ordered[512]; char ordered[512];
int n=0; int n=0;
n += snprintf(ordered, 512, "[pci=%d, rsrsp=%.2f", neighbour_cells[0]->phy_cell.id, neighbour_cells[0]->rsrp); n += snprintf(ordered, 512, "[pci=%d, rsrsp=%.2f", neighbour_cells[0]->phy_cell.id, neighbour_cells[0]->get_rsrp());
for (uint32_t i=1;i<neighbour_cells.size();i++) { 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); n += snprintf(&ordered[n], 512-n, " | pci=%d, rsrp=%.2f", neighbour_cells[i]->get_pci(), neighbour_cells[i]->get_rsrp());
} }
rrc_log->info("Sorted neighbour cells: %s]\n", ordered); rrc_log->info("Neighbours: %s]\n", ordered);
} }
bool rrc::add_neighbour_cell(cell_t *new_cell) { bool rrc::add_neighbour_cell(cell_t *new_cell) {
bool ret = false; bool ret = false;
if (neighbour_cells.size() < NOF_NEIGHBOUR_CELLS - 1) { if (neighbour_cells.size() < NOF_NEIGHBOUR_CELLS) {
ret = true; ret = true;
} else if (!neighbour_cells[neighbour_cells.size()-1]->greater(new_cell)) { } else if (new_cell->greater(neighbour_cells[neighbour_cells.size()-1])) {
// Delete old one // Replace old one by new one
delete neighbour_cells[neighbour_cells.size()-1]; delete_neighbour(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; ret = true;
} }
if (ret) { if (ret) {
neighbour_cells.push_back(new_cell); neighbour_cells.push_back(new_cell);
} }
rrc_log->info("Added neighbour cell EARFCN=%d, PCI=%d, nof_neighbours=%d\n", 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()); new_cell->get_earfcn(), new_cell->get_pci(), neighbour_cells.size());
sort_neighbour_cells(); sort_neighbour_cells();
return ret; return ret;
} }
@ -690,7 +732,7 @@ bool rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) {
bool rrc::add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { bool rrc::add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
if (earfcn == 0) { if (earfcn == 0) {
earfcn = serving_cell->earfcn; earfcn = serving_cell->get_earfcn();
} }
// First check if already exists // First check if already exists
@ -700,7 +742,7 @@ bool rrc::add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp
// If exists, update RSRP, sort again and return // If exists, update RSRP, sort again and return
if (cell_idx >= 0) { if (cell_idx >= 0) {
neighbour_cells[cell_idx]->rsrp = rsrp; neighbour_cells[cell_idx]->set_rsrp(rsrp);
sort_neighbour_cells(); sort_neighbour_cells();
return true; return true;
} }
@ -727,10 +769,8 @@ void rrc::earfcn_end() {
// If searching for PLMN, indicate NAS we scanned all frequencies // If searching for PLMN, indicate NAS we scanned all frequencies
if (state == RRC_STATE_PLMN_SELECTION) { if (state == RRC_STATE_PLMN_SELECTION) {
nas->plmn_search_end(); nas->plmn_search_end();
} else if (state == RRC_STATE_CELL_SELECTING) { } else if (state == RRC_STATE_CONNECTED) {
select_cell_timeout = 0; leave_connected();
rrc_log->info("Starting cell search again\n");
phy->cell_search_start();
} }
} }
@ -791,11 +831,11 @@ void rrc::out_of_sync() {
if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) { if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) {
n310_cnt++; n310_cnt++;
if (n310_cnt == N310) { if (n310_cnt == N310) {
rrc_log->info("Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer %d ms\n",
N310, mac_timers->timer_get(t310)->get_timeout());
mac_timers->timer_get(t310)->reset(); mac_timers->timer_get(t310)->reset();
mac_timers->timer_get(t310)->run(); mac_timers->timer_get(t310)->run();
n310_cnt = 0; n310_cnt = 0;
phy->sync_reset();
rrc_log->info("Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer\n", N310);
} }
} }
} else { } else {
@ -822,7 +862,6 @@ void rrc::in_sync() {
void rrc::radio_link_failure() { void rrc::radio_link_failure() {
// TODO: Generate and store failure report // TODO: Generate and store failure report
phy->sync_reset();
rrc_log->warning("Detected Radio-Link Failure\n"); rrc_log->warning("Detected Radio-Link Failure\n");
rrc_log->console("Warning: Detected Radio-Link Failure\n"); rrc_log->console("Warning: Detected Radio-Link Failure\n");
if (state != RRC_STATE_CONNECTED) { if (state != RRC_STATE_CONNECTED) {
@ -929,7 +968,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(serving_cell->sib1.cell_id, &msg_ptr); liblte_rrc_pack_cell_identity_ie(serving_cell->get_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];
@ -937,7 +976,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",
serving_cell->sib1.cell_id, phy->get_current_pci(), crnti); serving_cell->get_cell_id(), phy->get_current_pci(), crnti);
// Compute MAC-I // Compute MAC-I
uint8_t mac_key[4]; uint8_t mac_key[4];
@ -962,7 +1001,6 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause,
break; break;
default: default:
rrc_log->info("Unsupported integrity algorithm during reestablishment\n"); rrc_log->info("Unsupported integrity algorithm during reestablishment\n");
return;
} }
// Prepare ConnectionRestalishmentRequest packet // Prepare ConnectionRestalishmentRequest packet
@ -982,6 +1020,7 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause,
set_phy_default(); set_phy_default();
mac->reset(); mac->reset();
set_mac_default(); set_mac_default();
phy->sync_reset();
state = RRC_STATE_CELL_SELECTING; state = RRC_STATE_CELL_SELECTING;
} }
@ -1065,10 +1104,10 @@ 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 target_cell_idx = find_neighbour_cell(serving_cell->earfcn, mob_reconf.mob_ctrl_info.target_pci); int target_cell_idx = find_neighbour_cell(serving_cell->get_earfcn(), mob_reconf.mob_ctrl_info.target_pci);
if (target_cell_idx < 0) { if (target_cell_idx < 0) {
rrc_log->console("Received HO command to unknown PCI=%d\n", mob_reconf.mob_ctrl_info.target_pci); rrc_log->console("Received HO command to unknown 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); rrc_log->error("Could not find target cell earfcn=%d, pci=%d\n", serving_cell->get_earfcn(), mob_reconf.mob_ctrl_info.target_pci);
return false; return false;
} }
@ -1076,7 +1115,7 @@ 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 != serving_cell->earfcn) { mob_reconf.mob_ctrl_info.carrier_freq_eutra.dl_carrier_freq != serving_cell->get_earfcn()) {
rrc_log->warning("Received mobilityControlInfo for inter-frequency handover\n"); rrc_log->warning("Received mobilityControlInfo for inter-frequency handover\n");
} }
@ -1095,13 +1134,14 @@ bool rrc::ho_prepare() {
pdcp->reestablish(); pdcp->reestablish();
rlc->reestablish(); rlc->reestablish();
mac->reset(); mac->reset();
phy->reset(); // PHY is reset inside cell_handover() function
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", neighbour_cells[target_cell_idx]->phy_cell.id); rrc_log->info("Selecting new cell pci=%d\n", neighbour_cells[target_cell_idx]->get_pci());
if (!phy->cell_handover(neighbour_cells[target_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", neighbour_cells[target_cell_idx]->phy_cell.id); rrc_log->error("Could not synchronize with target cell pci=%d\n", neighbour_cells[target_cell_idx]->get_pci());
return false; return false;
} }
@ -1177,7 +1217,7 @@ void rrc::ho_failed() {
// Instruct PHY to resync with source PCI // Instruct PHY to resync with source PCI
if (!phy->cell_handover(ho_src_cell.phy_cell)) { if (!phy->cell_handover(ho_src_cell.phy_cell)) {
rrc_log->error("Could not synchronize with target cell pci=%d\n", ho_src_cell.phy_cell.id); rrc_log->error("Could not synchronize with target cell pci=%d\n", ho_src_cell.get_pci());
return; return;
} }
@ -1302,27 +1342,23 @@ 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(&serving_cell->sib1, &dlsch_msg.sibs[i].sib.sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT)); serving_cell->set_sib1(&dlsch_msg.sibs[i].sib.sib1);
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 && !serving_cell->has_valid_sib2) { } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib2()) {
memcpy(&serving_cell->sib2, &dlsch_msg.sibs[i].sib.sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT)); serving_cell->set_sib2(&dlsch_msg.sibs[i].sib.sib2);
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 && !serving_cell->has_valid_sib3) { } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib3()) {
memcpy(&serving_cell->sib3, &dlsch_msg.sibs[i].sib.sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT)); serving_cell->set_sib3(&dlsch_msg.sibs[i].sib.sib3);
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 && !serving_cell->has_valid_sib13) { }else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib13()) {
memcpy(&serving_cell->sib13, &dlsch_msg.sibs[0].sib.sib13, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT)); serving_cell->set_sib13(&dlsch_msg.sibs[i].sib.sib13);
serving_cell->has_valid_sib13 = true;
handle_sib13(); handle_sib13();
} }
} }
last_win_start = 0; last_win_start = 0;
if(serving_cell->has_valid_sib2) { if(serving_cell->has_sib2()) {
sysinfo_index++; sysinfo_index++;
} }
} }
@ -1330,16 +1366,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",
serving_cell->sib1.cell_id&0xfff, serving_cell->get_cell_id()&0xfff,
liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length], liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length],
liblte_rrc_si_periodicity_num[serving_cell->sib1.sched_info[0].si_periodicity]); liblte_rrc_si_periodicity_num[serving_cell->sib1ptr()->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<serving_cell->sib1.N_sched_info;i++){ for(i=0;i<serving_cell->sib1ptr()->N_sched_info;i++){
for(j=0;j<serving_cell->sib1.sched_info[i].N_sib_mapping_info;j++){ for(j=0;j<serving_cell->sib1ptr()->sched_info[i].N_sib_mapping_info;j++){
LIBLTE_RRC_SIB_TYPE_ENUM t = serving_cell->sib1.sched_info[i].sib_mapping_info[j].sib_type; LIBLTE_RRC_SIB_TYPE_ENUM t = serving_cell->sib1ptr()->sched_info[i].sib_mapping_info[j].sib_type;
LIBLTE_RRC_SI_PERIODICITY_ENUM p = serving_cell->sib1.sched_info[i].si_periodicity; LIBLTE_RRC_SI_PERIODICITY_ENUM p = serving_cell->sib1ptr()->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]);
@ -1347,16 +1383,14 @@ void rrc::handle_sib1()
} }
// Set TDD Config // Set TDD Config
if(serving_cell->sib1.tdd) { if(serving_cell->sib1ptr()->tdd) {
phy->set_config_tdd(&serving_cell->sib1.tdd_cnfg); phy->set_config_tdd(&serving_cell->sib1ptr()->tdd_cnfg);
} }
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 < serving_cell->sib1.N_plmn_ids; i++) { for (uint32_t i = 0; i < serving_cell->sib1ptr()->N_plmn_ids; i++) {
nas->plmn_found(serving_cell->sib1.plmn_id[i].id, serving_cell->sib1.tracking_area_code); nas->plmn_found(serving_cell->sib1ptr()->plmn_id[i].id, serving_cell->sib1ptr()->tracking_area_code);
} }
// Jump to next state // Jump to next state
@ -1379,7 +1413,7 @@ void rrc::handle_sib2()
{ {
rrc_log->info("SIB2 received\n"); rrc_log->info("SIB2 received\n");
apply_sib2_configs(&serving_cell->sib2); apply_sib2_configs(serving_cell->sib2ptr());
} }
@ -1387,7 +1421,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 = &serving_cell->sib3; LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3 = serving_cell->sib3ptr();
// 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];
@ -1507,10 +1541,13 @@ byte_buffer_t* rrc::byte_align_and_pack(byte_buffer_t *pdu)
pdcp_buf = pool_allocate; pdcp_buf = pool_allocate;
} }
srslte_bit_pack_vector(bit_buf.msg, pdcp_buf->msg, bit_buf.N_bits); if (pdcp_buf != NULL) {
pdcp_buf->N_bytes = bit_buf.N_bits / 8; srslte_bit_pack_vector(bit_buf.msg, pdcp_buf->msg, bit_buf.N_bits);
pdcp_buf->set_timestamp(); pdcp_buf->N_bytes = bit_buf.N_bits / 8;
pdcp_buf->set_timestamp();
} else {
rrc_log->error("Fatal Error: Couldn't allocate PDU in byte_align_and_pack().\n");
}
return pdcp_buf; return pdcp_buf;
} }
@ -1518,20 +1555,21 @@ void rrc::send_ul_ccch_msg(byte_buffer_t *pdu)
{ {
liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf);
pdu = byte_align_and_pack(pdu); pdu = byte_align_and_pack(pdu);
if (pdu) {
// Set UE contention resolution ID in MAC
uint64_t uecri = 0;
uint8_t *ue_cri_ptr = (uint8_t *) &uecri;
uint32_t nbytes = 6;
for (uint32_t i = 0; i < nbytes; i++) {
ue_cri_ptr[nbytes - i - 1] = pdu->msg[i];
}
// Set UE contention resolution ID in MAC rrc_log->debug("Setting UE contention resolution ID: %d\n", uecri);
uint64_t uecri = 0; mac->set_contention_id(uecri);
uint8_t *ue_cri_ptr = (uint8_t *) &uecri;
uint32_t nbytes = 6;
for (uint32_t i = 0; i < nbytes; i++) {
ue_cri_ptr[nbytes - i - 1] = pdu->msg[i];
}
rrc_log->debug("Setting UE contention resolution ID: %d\n", uecri);
mac->set_contention_id(uecri);
rrc_log->info("Sending %s\n", liblte_rrc_ul_ccch_msg_type_text[ul_ccch_msg.msg_type]); rrc_log->info("Sending %s\n", liblte_rrc_ul_ccch_msg_type_text[ul_ccch_msg.msg_type]);
pdcp->write_sdu(RB_ID_SRB0, pdu); pdcp->write_sdu(RB_ID_SRB0, pdu);
}
} }
void rrc::send_ul_dcch_msg(byte_buffer_t *pdu) void rrc::send_ul_dcch_msg(byte_buffer_t *pdu)
@ -1539,9 +1577,10 @@ void rrc::send_ul_dcch_msg(byte_buffer_t *pdu)
liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf);
pdu = byte_align_and_pack(pdu); pdu = byte_align_and_pack(pdu);
if (pdu) {
rrc_log->info("Sending %s\n", liblte_rrc_ul_dcch_msg_type_text[ul_dcch_msg.msg_type]); rrc_log->info("Sending %s\n", liblte_rrc_ul_dcch_msg_type_text[ul_dcch_msg.msg_type]);
pdcp->write_sdu(RB_ID_SRB1, pdu); pdcp->write_sdu(RB_ID_SRB1, pdu);
}
} }
void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) {
@ -1699,7 +1738,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 && serving_cell->sib2.rr_config_common_sib.pusch_cnfg.enable_64_qam; bool enable_ul_64 = args.ue_category >= 5 && serving_cell->sib2ptr()->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);
} }
@ -2373,28 +2412,45 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa
L3_filter(&pcell_measurement, values); L3_filter(&pcell_measurement, values);
// Update serving cell measurement // Update serving cell measurement
parent->serving_cell->rsrp = rsrp; parent->serving_cell->set_rsrp(rsrp);
} else { } else {
// Add to list of neighbour cells // Add to list of neighbour cells
parent->add_neighbour_cell(earfcn, pci, rsrp); bool added = 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 %s earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n",
added?"added":"not added", earfcn, pci, rsrp, rsrq, tti);
// Save PHY measurement for all active measurements whose earfcn/pci matches
for(std::map<uint32_t, meas_t>::iterator iter=active.begin(); iter!=active.end(); ++iter) { // Only report measurements of 8th strongest cells
meas_t *m = &iter->second; if (added) {
if (objects[m->object_id].earfcn == earfcn) { // Save PHY measurement for all active measurements whose earfcn/pci matches
// If it's a newly discovered cell, add it to objects for(std::map<uint32_t, meas_t>::iterator iter=active.begin(); iter!=active.end(); ++iter) {
if (!m->cell_values.count(pci)) { meas_t *m = &iter->second;
uint32_t cell_idx = objects[m->object_id].cells.size(); if (objects[m->object_id].earfcn == earfcn) {
objects[m->object_id].cells[cell_idx].pci = pci; // If it's a newly discovered cell, add it to objects
objects[m->object_id].cells[cell_idx].q_offset = 0; if (!m->cell_values.count(pci)) {
uint32_t cell_idx = objects[m->object_id].cells.size();
objects[m->object_id].cells[cell_idx].pci = pci;
objects[m->object_id].cells[cell_idx].q_offset = 0;
}
// Update or add cell
L3_filter(&m->cell_values[pci], values);
return;
} }
// Update or add cell }
L3_filter(&m->cell_values[pci], values); }
return; }
}
// Remove all stored measurements for a given cell
void rrc::rrc_meas::delete_report(uint32_t earfcn, uint32_t pci) {
for(std::map<uint32_t, meas_t>::iterator iter=active.begin(); iter!=active.end(); ++iter) {
meas_t *m = &iter->second;
if (objects[m->object_id].earfcn == earfcn) {
if (m->cell_values.count(pci)) {
m->cell_values.erase(pci);
log_h->info("Deleting report PCI=%d from cell_values\n", pci);
} }
} }
} }

@ -118,6 +118,7 @@ enable = false
# ip_netmask: Netmask of the tun_srsue device. Default: 255.255.255.0 # ip_netmask: Netmask of the tun_srsue device. Default: 255.255.255.0
# rssi_sensor_enabled: Enable or disable RF frontend RSSI sensor. Required for RSRP metrics but # rssi_sensor_enabled: Enable or disable RF frontend RSSI sensor. Required for RSRP metrics but
# can cause UHD instability for long-duration testing. Default true. # can cause UHD instability for long-duration testing. Default true.
# rx_gain_offset: RX Gain offset to add to rx_gain to calibrate RSRP readings
# prach_gain: PRACH gain (dB). If defined, forces a gain for the tranmsission of PRACH only., # prach_gain: PRACH gain (dB). If defined, forces a gain for the tranmsission of PRACH only.,
# Default is to use tx_gain in [rf] section. # Default is to use tx_gain in [rf] section.
# cqi_max: Upper bound on the maximum CQI to be reported. Default 15. # cqi_max: Upper bound on the maximum CQI to be reported. Default 15.
@ -176,6 +177,7 @@ enable = false
[expert] [expert]
#ip_netmask = 255.255.255.0 #ip_netmask = 255.255.255.0
#rssi_sensor_enabled = false #rssi_sensor_enabled = false
#rx_gain_offset = 72
#prach_gain = 30 #prach_gain = 30
#cqi_max = 15 #cqi_max = 15
#cqi_fixed = 10 #cqi_fixed = 10

Loading…
Cancel
Save