mirror of https://github.com/PentHertz/srsLTE.git
Merge branch 'next' into guti_attach
This commit is contained in:
commit
406a1d01b6
|
@ -30,6 +30,8 @@
|
|||
#include <pthread.h>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -76,8 +78,13 @@ public:
|
|||
{
|
||||
printf("%d buffers in queue\n", (int) used.size());
|
||||
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
|
||||
std::map<std::string, uint32_t> buffer_cnt;
|
||||
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
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
#define SRSLTE_MAX_BUFFER_SIZE_BYTES 12756
|
||||
#define SRSLTE_BUFFER_HEADER_OFFSET 1024
|
||||
|
||||
//#define SRSLTE_BUFFER_POOL_LOG_ENABLED
|
||||
#define SRSLTE_BUFFER_POOL_LOG_ENABLED
|
||||
|
||||
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
|
||||
#define pool_allocate (pool->allocate(__FUNCTION__))
|
||||
|
|
|
@ -160,7 +160,7 @@ public:
|
|||
virtual void in_sync() = 0;
|
||||
virtual void out_of_sync() = 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;
|
||||
};
|
||||
|
||||
|
@ -580,9 +580,8 @@ public:
|
|||
|
||||
/* Cell search and selection procedures */
|
||||
virtual void cell_search_start() = 0;
|
||||
virtual void cell_search_stop() = 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;
|
||||
|
||||
/* Is the PHY downlink synchronized? */
|
||||
|
|
|
@ -60,6 +60,7 @@ typedef struct {
|
|||
SRSLTE_RF_ERROR_LATE,
|
||||
SRSLTE_RF_ERROR_UNDERFLOW,
|
||||
SRSLTE_RF_ERROR_OVERFLOW,
|
||||
SRSLTE_RF_ERROR_RX,
|
||||
SRSLTE_RF_ERROR_OTHER
|
||||
} type;
|
||||
int opt;
|
||||
|
|
|
@ -72,6 +72,8 @@ namespace srslte {
|
|||
trace_enabled = false;
|
||||
tti = 0;
|
||||
agc_enabled = false;
|
||||
radio_is_streaming = false;
|
||||
is_initialized = false;
|
||||
};
|
||||
|
||||
bool init(char *args = NULL, char *devname = NULL, uint32_t nof_channels = 1);
|
||||
|
@ -119,13 +121,13 @@ namespace srslte {
|
|||
|
||||
void start_trace();
|
||||
void write_trace(std::string filename);
|
||||
void start_rx(bool now = false);
|
||||
void stop_rx();
|
||||
|
||||
|
||||
void set_tti(uint32_t tti);
|
||||
|
||||
bool is_first_of_burst();
|
||||
|
||||
bool is_init();
|
||||
|
||||
void register_error_handler(srslte_rf_error_handler_t h);
|
||||
|
||||
protected:
|
||||
|
@ -168,6 +170,9 @@ namespace srslte {
|
|||
uint32_t tti;
|
||||
bool agc_enabled;
|
||||
|
||||
bool is_initialized = true;;
|
||||
bool radio_is_streaming;
|
||||
|
||||
uint32_t saved_nof_channels;
|
||||
char saved_args[128];
|
||||
char saved_devname[128];
|
||||
|
|
|
@ -40,6 +40,7 @@ log_filter::log_filter()
|
|||
do_tti = false;
|
||||
time_src = NULL;
|
||||
time_format = TIME;
|
||||
logger_h = NULL;
|
||||
}
|
||||
|
||||
log_filter::log_filter(std::string layer)
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace srslte{
|
|||
|
||||
logger_file::logger_file()
|
||||
:inited(false)
|
||||
,logfile(NULL)
|
||||
,not_done(true)
|
||||
,cur_length(0)
|
||||
,max_length(0)
|
||||
|
@ -46,7 +47,9 @@ logger_file::~logger_file() {
|
|||
if(inited) {
|
||||
wait_thread_finish();
|
||||
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)
|
||||
{
|
||||
pdu_t *pdu = (pdu_t*) ptr;
|
||||
pdu->len = len;
|
||||
pdu->tstamp = tstamp;
|
||||
pdu_q.push(pdu);
|
||||
if (ptr) {
|
||||
pdu_t *pdu = (pdu_t*) ptr;
|
||||
pdu->len = len;
|
||||
pdu->tstamp = tstamp;
|
||||
pdu_q.push(pdu);
|
||||
} else {
|
||||
log_h->warning("Error pushing pdu: ptr is empty\n");
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
|
||||
|
||||
/* Get references from the input 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 */
|
||||
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);
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#define FFTW_TYPE 0
|
||||
#endif
|
||||
|
||||
pthread_mutex_t fft_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void srslte_dft_load() {
|
||||
#ifdef FFTW_WISDOM_FILE
|
||||
|
@ -58,10 +59,12 @@ void srslte_dft_exit() {
|
|||
#ifdef FFTW_WISDOM_FILE
|
||||
fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE);
|
||||
#endif
|
||||
fftwf_cleanup();
|
||||
}
|
||||
|
||||
int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir,
|
||||
srslte_dft_mode_t mode) {
|
||||
bzero(plan, sizeof(srslte_dft_plan_t));
|
||||
if(mode == SRSLTE_DFT_COMPLEX){
|
||||
return srslte_dft_plan_c(plan,dft_points,dir);
|
||||
} 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 howmany_dims = {how_many, idist, odist};
|
||||
|
||||
pthread_mutex_lock(&fft_mutex);
|
||||
|
||||
/* Destroy current plan */
|
||||
fftwf_destroy_plan(plan->p);
|
||||
|
||||
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) {
|
||||
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 sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
|
||||
|
||||
pthread_mutex_lock(&fft_mutex);
|
||||
if (plan->p) {
|
||||
fftwf_destroy_plan(plan->p);
|
||||
plan->p = NULL;
|
||||
}
|
||||
plan->p = fftwf_plan_dft_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE);
|
||||
pthread_mutex_unlock(&fft_mutex);
|
||||
|
||||
if (!plan->p) {
|
||||
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 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);
|
||||
if (!plan->p) {
|
||||
return -1;
|
||||
}
|
||||
pthread_mutex_unlock(&fft_mutex);
|
||||
|
||||
plan->size = dft_points;
|
||||
plan->init_size = plan->size;
|
||||
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) {
|
||||
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;
|
||||
plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE);
|
||||
|
||||
pthread_mutex_unlock(&fft_mutex);
|
||||
|
||||
if (!plan->p) {
|
||||
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 sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R;
|
||||
|
||||
pthread_mutex_lock(&fft_mutex);
|
||||
if (plan->p) {
|
||||
fftwf_destroy_plan(plan->p);
|
||||
plan->p = NULL;
|
||||
}
|
||||
plan->p = fftwf_plan_r2r_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE);
|
||||
pthread_mutex_unlock(&fft_mutex);
|
||||
|
||||
if (!plan->p) {
|
||||
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) {
|
||||
allocate(plan,sizeof(float),sizeof(float), dft_points);
|
||||
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);
|
||||
pthread_mutex_unlock(&fft_mutex);
|
||||
|
||||
if (!plan->p) {
|
||||
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) {
|
||||
if (!plan) return;
|
||||
if (!plan->size) return;
|
||||
|
||||
pthread_mutex_lock(&fft_mutex);
|
||||
if (!plan->is_guru) {
|
||||
if (plan->in) fftwf_free(plan->in);
|
||||
if (plan->out) fftwf_free(plan->out);
|
||||
}
|
||||
if (plan->p) fftwf_destroy_plan(plan->p);
|
||||
pthread_mutex_unlock(&fft_mutex);
|
||||
|
||||
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) {
|
||||
q->mbsfn_subframe = true;
|
||||
q->non_mbsfn_region = 2; // default set to 2
|
||||
} else {
|
||||
q->mbsfn_subframe = false;
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
|
|
|
@ -171,5 +171,8 @@ int main(int argc, char **argv) {
|
|||
|
||||
n_prb++;
|
||||
}
|
||||
|
||||
srslte_dft_exit();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -198,6 +198,8 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
srslte_rm_turbo_free_tables();
|
||||
free(rm_bits_s);
|
||||
free(rm_bits_f);
|
||||
free(rm_bits);
|
||||
free(rm_bits2);
|
||||
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) {
|
||||
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
|
||||
uhd_async_metadata_handle md;
|
||||
|
@ -334,11 +347,12 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
|
|||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
bzero(handler, sizeof(rf_uhd_handler_t));
|
||||
*h = handler;
|
||||
|
||||
|
||||
/* Set priority to UHD threads */
|
||||
uhd_set_thread_priority(uhd_default_thread_priority, true);
|
||||
|
||||
|
||||
/* Find available devices */
|
||||
uhd_string_vector_handle 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);
|
||||
|
||||
// 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)) {
|
||||
perror("pthread_create");
|
||||
return -1;
|
||||
}
|
||||
}*/
|
||||
|
||||
/* Restore priorities */
|
||||
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);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error receiving from UHD: %d\n", error);
|
||||
log_rx_error(handler);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -760,8 +776,12 @@ int rf_uhd_recv_with_time_multi(void *h,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
return uhd_rx_streamer_recv(handler->rx_stream, data,
|
||||
nsamples, md, 0.0, false, &rxd_samples);
|
||||
uhd_error error = uhd_rx_streamer_recv(handler->rx_stream, data, 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) {
|
||||
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) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "adgetvsfil")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "adgetvnsfil")) != -1) {
|
||||
switch (opt) {
|
||||
case 'a':
|
||||
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) {
|
||||
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;
|
||||
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++;
|
||||
}
|
||||
|
||||
INFO("SYNC TRACK: sf_idx=%d, ret=%d, next_state=%d\n", q->sf_idx, ret, q->state);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,6 +157,8 @@ int main(int argc, char **argv) {
|
|||
if(test_dft(in) != 0)
|
||||
return -1;
|
||||
|
||||
srslte_dft_exit();
|
||||
|
||||
free(in);
|
||||
printf("Done\n");
|
||||
exit(0);
|
||||
|
|
|
@ -71,7 +71,12 @@ bool radio::init(char *args, char *devname, uint32_t nof_channels)
|
|||
}
|
||||
saved_nof_channels = nof_channels;
|
||||
|
||||
return true;
|
||||
is_initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool radio::is_init() {
|
||||
return is_initialized;
|
||||
}
|
||||
|
||||
void radio::stop()
|
||||
|
@ -82,11 +87,8 @@ void radio::stop()
|
|||
void radio::reset()
|
||||
{
|
||||
printf("Resetting Radio...\n");
|
||||
srslte_rf_close(&rf_device);
|
||||
sleep(3);
|
||||
if (srslte_rf_open_devname(&rf_device, saved_devname, saved_args, saved_nof_channels)) {
|
||||
fprintf(stderr, "Error opening RF device\n");
|
||||
}
|
||||
srslte_rf_stop_rx_stream(&rf_device);
|
||||
radio_is_streaming = false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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,
|
||||
rxd_time?&rxd_time->full_secs:NULL, rxd_time?&rxd_time->frac_secs:NULL) > 0) {
|
||||
return true;
|
||||
|
@ -295,7 +301,9 @@ void radio::set_master_clock_rate(double rate)
|
|||
|
||||
void radio::set_rx_srate(double srate)
|
||||
{
|
||||
srslte_rf_stop_rx_stream(&rf_device);
|
||||
srslte_rf_set_rx_srate(&rf_device, srate);
|
||||
srslte_rf_start_rx_stream(&rf_device, false);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
is_initialized = 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++) {
|
||||
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) {
|
||||
return true;
|
||||
} else {
|
||||
|
|
|
@ -72,6 +72,14 @@ rlc_am::~rlc_am()
|
|||
{
|
||||
// reset RLC and dealloc SDUs
|
||||
stop();
|
||||
|
||||
if(rx_sdu) {
|
||||
pool->deallocate(rx_sdu);
|
||||
}
|
||||
|
||||
if(tx_sdu) {
|
||||
pool->deallocate(tx_sdu);
|
||||
}
|
||||
}
|
||||
|
||||
void rlc_am::init(srslte::log *log_,
|
||||
|
|
|
@ -136,11 +136,11 @@ void rlc_um::reset()
|
|||
vr_uh = 0;
|
||||
pdu_lost = false;
|
||||
if(rx_sdu) {
|
||||
rx_sdu->reset();
|
||||
pool->deallocate(rx_sdu);
|
||||
}
|
||||
|
||||
if(tx_sdu) {
|
||||
tx_sdu->reset();
|
||||
pool->deallocate(tx_sdu);
|
||||
}
|
||||
|
||||
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_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)
|
||||
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/threads.h"
|
||||
#include "srslte/upper/rlc.h"
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
#include <assert.h>
|
||||
#define NBUFS 5
|
||||
|
||||
using namespace std;
|
||||
using namespace srsue;
|
||||
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
|
||||
:public thread
|
||||
{
|
||||
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_;
|
||||
rlc2 = rlc2_;
|
||||
fail_rate = fail_rate_;
|
||||
run_enable = true;
|
||||
running = false;
|
||||
pdu_tx_delay_usec = pdu_tx_delay_usec_;
|
||||
}
|
||||
|
||||
void stop()
|
||||
|
@ -82,7 +129,7 @@ private:
|
|||
if(((float)rand()/RAND_MAX > fail_rate) && read>0) {
|
||||
rlc2->write_pdu(1, pdu->msg, opp_size);
|
||||
}
|
||||
usleep(100);
|
||||
usleep(pdu_tx_delay_usec);
|
||||
}
|
||||
running = false;
|
||||
byte_buffer_pool::get_instance()->deallocate(pdu);
|
||||
|
@ -91,6 +138,7 @@ private:
|
|||
rlc_interface_mac *rlc1;
|
||||
rlc_interface_mac *rlc2;
|
||||
float fail_rate;
|
||||
uint32_t pdu_tx_delay_usec;
|
||||
|
||||
bool run_enable;
|
||||
bool running;
|
||||
|
@ -100,9 +148,9 @@ class mac_dummy
|
|||
:public srslte::mac_interface_timers
|
||||
{
|
||||
public:
|
||||
mac_dummy(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_)
|
||||
:r1(rlc1_, rlc2_, fail_rate_)
|
||||
,r2(rlc2_, rlc1_, 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_, pdu_tx_delay)
|
||||
,r2(rlc2_, rlc1_, fail_rate_, pdu_tx_delay)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -140,12 +188,13 @@ class rlc_am_tester
|
|||
,public thread
|
||||
{
|
||||
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_;
|
||||
run_enable = true;
|
||||
running = false;
|
||||
rx_pdus = 0;
|
||||
name = name_;
|
||||
sdu_gen_delay_usec = sdu_gen_delay_usec_;
|
||||
}
|
||||
|
||||
void stop()
|
||||
|
@ -191,7 +240,7 @@ private:
|
|||
pdu->N_bytes = 1500;
|
||||
pdu->msg[0] = sn++;
|
||||
rlc->write_sdu(1, pdu);
|
||||
usleep(100);
|
||||
usleep(sdu_gen_delay_usec);
|
||||
}
|
||||
running = false;
|
||||
}
|
||||
|
@ -202,10 +251,12 @@ private:
|
|||
|
||||
std::string name;
|
||||
|
||||
uint32_t sdu_gen_delay_usec;
|
||||
|
||||
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 log2("RLC_AM_2");
|
||||
|
@ -214,14 +265,12 @@ void stress_test()
|
|||
log1.set_hex_limit(-1);
|
||||
log2.set_hex_limit(-1);
|
||||
|
||||
float fail_rate = 0.1;
|
||||
|
||||
rlc rlc1;
|
||||
rlc rlc2;
|
||||
|
||||
rlc_am_tester tester1(&rlc1, "tester1");
|
||||
rlc_am_tester tester2(&rlc2, "tester2");
|
||||
mac_dummy mac(&rlc1, &rlc2, fail_rate);
|
||||
rlc_am_tester tester1(&rlc1, "tester1", args.sdu_gen_delay_usec);
|
||||
rlc_am_tester tester2(&rlc2, "tester2", args.sdu_gen_delay_usec);
|
||||
mac_dummy mac(&rlc1, &rlc2, args.error_rate, args.pdu_tx_delay_usec);
|
||||
ue_interface ue;
|
||||
|
||||
rlc1.init(&tester1, &tester1, &ue, &log1, &mac, 0);
|
||||
|
@ -245,7 +294,14 @@ void stress_test()
|
|||
tester2.start(7);
|
||||
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();
|
||||
tester2.stop();
|
||||
|
@ -254,6 +310,9 @@ void stress_test()
|
|||
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
# mme_addr: IP address of MME for S1 connnection
|
||||
# gtp_bind_addr: Local IP address to bind for GTP connection
|
||||
# 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]
|
||||
|
@ -25,6 +27,9 @@ mnc = 01
|
|||
mme_addr = 127.0.1.100
|
||||
gtp_bind_addr = 127.0.0.1
|
||||
n_prb = 50
|
||||
#tm = 4
|
||||
#nof_ports = 2
|
||||
|
||||
|
||||
#####################################################################
|
||||
# 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);
|
||||
|
||||
// Start streaming RX samples
|
||||
radio_h->start_rx();
|
||||
|
||||
|
||||
// Set TTI so that first TX is at tti=0
|
||||
tti = 10235;
|
||||
|
||||
|
|
|
@ -196,6 +196,8 @@ private:
|
|||
is_initiated = false;
|
||||
ack = false;
|
||||
bzero(&cur_grant, sizeof(Tgrant));
|
||||
payload_buffer_ptr = NULL;
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
}
|
||||
|
||||
~dl_tb_process() {
|
||||
|
@ -220,16 +222,24 @@ private:
|
|||
}
|
||||
|
||||
void reset(void) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
is_first_tb = true;
|
||||
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));
|
||||
if (is_initiated) {
|
||||
srslte_softbuffer_rx_reset(&softbuffer);
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
void new_grant_dl(Tgrant grant, Taction *action) {
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
// Compute RV for BCCH when not specified in PDCCH format
|
||||
if (pid == HARQ_BCCH_PID && grant.rv[tid] == -1) {
|
||||
uint32_t k;
|
||||
|
@ -253,14 +263,14 @@ private:
|
|||
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 (!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
|
||||
if (pid == HARQ_BCCH_PID) {
|
||||
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]) {
|
||||
action->decode_enabled[tid] = false;
|
||||
Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes[tid]);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return;
|
||||
}
|
||||
action->decode_enabled[tid]= true;
|
||||
|
@ -281,7 +292,8 @@ private:
|
|||
|
||||
} else {
|
||||
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()) {
|
||||
|
@ -298,9 +310,12 @@ private:
|
|||
Debug("Generating ACK\n");
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
void tb_decoded(bool ack_) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
ack = ack_;
|
||||
if (ack) {
|
||||
if (pid == HARQ_BCCH_PID) {
|
||||
|
@ -331,11 +346,15 @@ private:
|
|||
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",
|
||||
pid, tid, is_new_transmission ? "newTX" : "reTX ",
|
||||
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);
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
if (ack && pid == HARQ_BCCH_PID) {
|
||||
reset();
|
||||
}
|
||||
|
@ -363,6 +382,8 @@ private:
|
|||
return is_new_transmission;
|
||||
}
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
bool is_initiated;
|
||||
dl_harq_entity *harq_entity;
|
||||
srslte::log *log_h;
|
||||
|
|
|
@ -162,13 +162,24 @@ private:
|
|||
void timer_alignment_expire();
|
||||
srslte::timers timers;
|
||||
|
||||
|
||||
// pointer to MAC PCAP object
|
||||
srslte::mac_pcap* pcap;
|
||||
bool is_first_ul_grant;
|
||||
|
||||
mac_metrics_t metrics;
|
||||
|
||||
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_timers mactimers;
|
||||
|
||||
/* Class to process MAC PDUs from DEMUX unit */
|
||||
class pdu_process : public thread {
|
||||
|
|
|
@ -104,7 +104,8 @@ private:
|
|||
/* Msg3 Buffer */
|
||||
static const uint32_t MSG3_BUFF_SZ = 1024;
|
||||
uint8_t msg3_buff[MSG3_BUFF_SZ];
|
||||
|
||||
uint8_t *msg3_buff_start_pdu;
|
||||
|
||||
/* PDU Buffer */
|
||||
srslte::sch_pdu pdu_msg;
|
||||
bool msg3_has_been_transmitted;
|
||||
|
|
|
@ -246,7 +246,6 @@ private:
|
|||
} else {
|
||||
Warning("UL RAR grant available but no Msg3 on buffer\n");
|
||||
}
|
||||
printf("Transmitted Msg3\n");
|
||||
|
||||
// Normal UL grant
|
||||
} else {
|
||||
|
@ -305,7 +304,7 @@ private:
|
|||
bool is_msg3;
|
||||
bool is_initiated;
|
||||
uint32_t tti_last_tx;
|
||||
|
||||
|
||||
|
||||
const static int payload_buffer_len = 128*1024;
|
||||
uint8_t *payload_buffer;
|
||||
|
|
|
@ -61,9 +61,8 @@ public:
|
|||
|
||||
void reset_sync();
|
||||
void cell_search_start();
|
||||
void cell_search_stop();
|
||||
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);
|
||||
|
||||
void meas_reset();
|
||||
|
@ -95,7 +94,6 @@ private:
|
|||
|
||||
void reset();
|
||||
void radio_error();
|
||||
bool wait_radio_reset();
|
||||
void set_ue_sync_opts(srslte_ue_sync_t *q, float cfo);
|
||||
void run_thread();
|
||||
|
||||
|
@ -104,14 +102,11 @@ private:
|
|||
bool set_cell();
|
||||
|
||||
void cell_search_inc();
|
||||
void resync_sfn(bool is_connected = false, bool rx_now = false);
|
||||
bool stop_sync();
|
||||
void cell_reselect();
|
||||
|
||||
void stop_rx();
|
||||
void start_rx(bool now = false);
|
||||
bool radio_is_rx;
|
||||
uint32_t new_earfcn;
|
||||
srslte_cell_t new_cell;
|
||||
|
||||
bool radio_is_resetting;
|
||||
bool running;
|
||||
|
||||
// Class to run cell search
|
||||
|
@ -167,13 +162,14 @@ private:
|
|||
typedef enum {IDLE, MEASURE_OK, ERROR} ret_code;
|
||||
|
||||
~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);
|
||||
void reset();
|
||||
void set_cell(srslte_cell_t cell);
|
||||
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_multiple_subframes(cf_t *buffer, uint32_t offset, uint32_t sf_idx, uint32_t nof_sf);
|
||||
float rssi();
|
||||
float rsrp();
|
||||
float rsrq();
|
||||
float snr();
|
||||
|
@ -183,7 +179,6 @@ private:
|
|||
srslte::log *log_h;
|
||||
srslte_ue_dl_t ue_dl;
|
||||
cf_t *buffer[SRSLTE_MAX_PORTS];
|
||||
srslte::radio *radio_h;
|
||||
uint32_t cnt;
|
||||
uint32_t nof_subframes;
|
||||
uint32_t current_prb;
|
||||
|
@ -235,7 +230,7 @@ private:
|
|||
void write(uint32_t tti, cf_t *data, uint32_t nsamples);
|
||||
private:
|
||||
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_PRIO = DEFAULT_PRIORITY + 5;
|
||||
|
||||
|
@ -303,17 +298,18 @@ private:
|
|||
const static uint32_t NOF_IN_SYNC_SF = 100;
|
||||
|
||||
// State for primary cell
|
||||
enum {
|
||||
typedef enum {
|
||||
IDLE = 0,
|
||||
CELL_SEARCH,
|
||||
CELL_SELECT,
|
||||
CELL_RESELECT,
|
||||
CELL_MEASURE,
|
||||
CELL_CAMP,
|
||||
IDLE_RX
|
||||
} phy_state;
|
||||
} phy_state_t;
|
||||
|
||||
bool is_in_idle, is_in_idle_rx;
|
||||
phy_state_t phy_state, prev_state;
|
||||
|
||||
bool is_in_idle;
|
||||
|
||||
// Sampling rate mode (find is 1.96 MHz, camp is the full cell BW)
|
||||
enum {
|
||||
|
@ -335,7 +331,6 @@ private:
|
|||
float ul_dl_factor;
|
||||
uint32_t current_earfcn;
|
||||
int cur_earfcn_index;
|
||||
bool cell_search_in_progress;
|
||||
|
||||
float dl_freq;
|
||||
float ul_freq;
|
||||
|
|
|
@ -119,7 +119,8 @@ private:
|
|||
struct timeval tr_time[3];
|
||||
srslte::trace<uint32_t> tr_exec;
|
||||
bool trace_enabled;
|
||||
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
/* Common objects */
|
||||
phch_common *phy;
|
||||
|
|
|
@ -85,9 +85,8 @@ public:
|
|||
void sync_reset();
|
||||
void configure_ul_params(bool pregen_disabled = false);
|
||||
void cell_search_start();
|
||||
void cell_search_stop();
|
||||
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);
|
||||
|
||||
void meas_reset();
|
||||
|
|
|
@ -110,8 +110,6 @@ private:
|
|||
srslte::log_filter gw_log;
|
||||
srslte::log_filter usim_log;
|
||||
|
||||
srslte::byte_buffer_pool *pool;
|
||||
|
||||
all_args_t *args;
|
||||
bool started;
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ class ue_base
|
|||
{
|
||||
public:
|
||||
ue_base();
|
||||
virtual ~ue_base() {}
|
||||
virtual ~ue_base();
|
||||
|
||||
static ue_base* get_instance(srsue_instance_type_t type);
|
||||
|
||||
|
@ -173,6 +173,9 @@ public:
|
|||
std::string get_build_mode();
|
||||
std::string get_build_info();
|
||||
std::string get_build_string();
|
||||
|
||||
private:
|
||||
srslte::byte_buffer_pool *pool;
|
||||
};
|
||||
|
||||
} // namespace srsue
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "srslte/common/security.h"
|
||||
#include "srslte/common/threads.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
|
@ -65,12 +66,14 @@ class cell_t
|
|||
return earfcn == this->earfcn && pci == phy_cell.id;
|
||||
}
|
||||
bool greater(cell_t *x) {
|
||||
return x->rsrp > rsrp;
|
||||
return rsrp > x->rsrp;
|
||||
}
|
||||
bool plmn_equals(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
|
||||
for (uint32_t i = 0; i < sib1.N_plmn_ids; i++) {
|
||||
if (plmn_id.mcc == sib1.plmn_id[i].id.mcc && plmn_id.mnc == sib1.plmn_id[i].id.mnc) {
|
||||
return true;
|
||||
if (has_valid_sib1) {
|
||||
for (uint32_t i = 0; i < sib1.N_plmn_ids; i++) {
|
||||
if (plmn_id.mcc == sib1.plmn_id[i].id.mcc && plmn_id.mnc == sib1.plmn_id[i].id.mnc) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -80,6 +83,7 @@ class cell_t
|
|||
cell_t(tmp, 0, 0);
|
||||
}
|
||||
cell_t(srslte_cell_t phy_cell, uint32_t earfcn, float rsrp) {
|
||||
gettimeofday(&last_update, NULL);
|
||||
this->has_valid_sib1 = false;
|
||||
this->has_valid_sib2 = false;
|
||||
this->has_valid_sib3 = false;
|
||||
|
@ -94,14 +98,108 @@ class cell_t
|
|||
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;
|
||||
bool in_sync;
|
||||
|
||||
private:
|
||||
float rsrp;
|
||||
uint32_t earfcn;
|
||||
struct timeval last_update;
|
||||
|
||||
bool has_valid_sib1;
|
||||
bool has_valid_sib2;
|
||||
bool has_valid_sib3;
|
||||
bool has_valid_sib13;
|
||||
bool in_sync;
|
||||
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1;
|
||||
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2;
|
||||
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3;
|
||||
|
@ -157,7 +255,7 @@ public:
|
|||
void in_sync();
|
||||
void out_of_sync();
|
||||
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);
|
||||
|
||||
// MAC interface
|
||||
|
@ -227,7 +325,7 @@ private:
|
|||
static const uint32_t RRC_PLMN_SELECT_TIMEOUT = 10000;
|
||||
|
||||
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_int[32];
|
||||
|
@ -274,6 +372,7 @@ private:
|
|||
}
|
||||
|
||||
// List of strongest neighbour cell
|
||||
const static int NEIGHBOUR_TIMEOUT = 5;
|
||||
const static int NOF_NEIGHBOUR_CELLS = 8;
|
||||
std::vector<cell_t*> neighbour_cells;
|
||||
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(cell_t *cell);
|
||||
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 {
|
||||
SI_ACQUIRE_IDLE = 0,
|
||||
|
@ -315,6 +417,7 @@ private:
|
|||
void run_tti(uint32_t tti);
|
||||
bool timer_expired(uint32_t timer_id);
|
||||
void ho_finish();
|
||||
void delete_report(uint32_t earfcn, uint32_t pci);
|
||||
private:
|
||||
|
||||
const static int NOF_MEASUREMENTS = 3;
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace srsue {
|
|||
// RRC states (3GPP 36.331 v10.0.0)
|
||||
typedef enum {
|
||||
RRC_STATE_IDLE = 0,
|
||||
RRC_STATE_PLMN_START,
|
||||
RRC_STATE_PLMN_SELECTION,
|
||||
RRC_STATE_CELL_SELECTING,
|
||||
RRC_STATE_CELL_SELECTED,
|
||||
|
@ -44,11 +45,14 @@ typedef enum {
|
|||
RRC_STATE_N_ITEMS,
|
||||
} rrc_state_t;
|
||||
static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE",
|
||||
"PLMN SELECTED",
|
||||
"PLMN SELECTION",
|
||||
"CELL SELECTING",
|
||||
"CELL SELECTED",
|
||||
"CONNECTING",
|
||||
"CONNECTED",
|
||||
"HO PREPARE",
|
||||
"HO PROCESS",
|
||||
"LEAVE CONNECTED"};
|
||||
|
||||
} // namespace srsue
|
||||
|
|
|
@ -165,7 +165,14 @@ void demux::process_sch_pdu(srslte::sch_pdu *pdu_msg)
|
|||
// Route logical channel
|
||||
if (route_pdu) {
|
||||
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 {
|
||||
// Process MAC Control Element
|
||||
|
|
|
@ -82,6 +82,7 @@ bool mac::init(phy_interface_mac *phy, rlc_interface_mac *rlc, rrc_interface_mac
|
|||
started = true;
|
||||
start(MAC_MAIN_THREAD_PRIO);
|
||||
|
||||
mactimers.init(&timers, log_h);
|
||||
|
||||
return started;
|
||||
}
|
||||
|
@ -94,6 +95,7 @@ void mac::stop()
|
|||
ttisync.increase();
|
||||
pdu_process_thread.stop();
|
||||
wait_thread_finish();
|
||||
mactimers.stop();
|
||||
}
|
||||
|
||||
void mac::start_pcap(srslte::mac_pcap* pcap_)
|
||||
|
@ -148,6 +150,17 @@ void mac::reset()
|
|||
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() {
|
||||
int cnt=0;
|
||||
|
||||
|
@ -165,7 +178,6 @@ void mac::run_thread() {
|
|||
tti = ttisync.wait();
|
||||
|
||||
log_h->step(tti);
|
||||
timers.step_all();
|
||||
|
||||
// Step all procedures
|
||||
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;
|
||||
rlc = NULL;
|
||||
bsr_procedure = NULL;
|
||||
phr_procedure = NULL;
|
||||
|
||||
phr_procedure = NULL;
|
||||
msg3_buff_start_pdu = NULL;
|
||||
|
||||
msg3_flush();
|
||||
}
|
||||
|
||||
|
@ -347,6 +348,7 @@ void mux::msg3_flush()
|
|||
msg3_has_been_transmitted = false;
|
||||
msg3_pending = false;
|
||||
bzero(msg3_buff, sizeof(MSG3_BUFF_SZ));
|
||||
msg3_buff_start_pdu = NULL;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
Error("Moving PDU from Mux unit to Msg3 buffer\n");
|
||||
return NULL;
|
||||
msg3_buff_start_pdu = pdu_get(msg3_buff, pdu_sz, 0, 0);
|
||||
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 {
|
||||
Error("Msg3 size (%d) is longer than internal msg3_buff size=%d, (see mux.h)\n", pdu_sz, MSG3_BUFF_SZ-32);
|
||||
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.")
|
||||
|
||||
("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")
|
||||
|
||||
("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")
|
||||
|
||||
("expert.prach_gain",
|
||||
|
|
|
@ -355,13 +355,16 @@ void phch_common::reset() {
|
|||
|
||||
void phch_common::reset_ul()
|
||||
{
|
||||
/*
|
||||
is_first_tx = true;
|
||||
is_first_of_burst = true;
|
||||
is_first_of_burst = true;
|
||||
|
||||
for (uint32_t i=0;i<nof_mutex;i++) {
|
||||
pthread_mutex_trylock(&tx_mutex[i]);
|
||||
pthread_mutex_unlock(&tx_mutex[i]);
|
||||
}
|
||||
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);
|
||||
|
||||
// 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
|
||||
intra_freq_meas.init(worker_com, rrc, log_h);
|
||||
|
@ -132,9 +132,7 @@ void phch_recv::reset()
|
|||
next_offset = 0;
|
||||
cell_is_set = false;
|
||||
srate_mode = SRATE_NONE;
|
||||
cell_search_in_progress = false;
|
||||
current_earfcn = 0;
|
||||
radio_is_resetting = false;
|
||||
sfn_p.reset();
|
||||
measure_p.reset();
|
||||
search_p.reset();
|
||||
|
@ -144,33 +142,16 @@ void phch_recv::reset()
|
|||
void phch_recv::radio_error()
|
||||
{
|
||||
log_h->error("SYNC: Receiving from radio.\n");
|
||||
phy_state = IDLE;
|
||||
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);
|
||||
|
||||
phy_state = CELL_SEARCH;
|
||||
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) {
|
||||
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)
|
||||
{
|
||||
do_agc = enable;
|
||||
|
@ -265,19 +246,6 @@ bool phch_recv::set_cell() {
|
|||
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) {
|
||||
this->earfcn = earfcn;
|
||||
}
|
||||
|
@ -287,42 +255,24 @@ void phch_recv::force_freq(float dl_freq, float 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() {
|
||||
|
||||
Warning("SYNC: Resetting sync, cell_search_in_progress=%s\n", cell_search_in_progress?"yes":"no");
|
||||
|
||||
sfn_p.reset();
|
||||
search_p.reset();
|
||||
measure_p.reset();
|
||||
srslte_ue_sync_reset(&ue_sync);
|
||||
resync_sfn(true, true);
|
||||
Info("----- PHY RESET----\n");
|
||||
phy_state = CELL_SELECT;
|
||||
}
|
||||
|
||||
void phch_recv::cell_search_inc()
|
||||
{
|
||||
Info("cell_search_inc, cur_idx=%d, size=%d\n", cur_earfcn_index, earfcn.size());
|
||||
cur_earfcn_index++;
|
||||
if (cur_earfcn_index >= 0) {
|
||||
if (cur_earfcn_index >= (int) earfcn.size()) {
|
||||
cur_earfcn_index = 0;
|
||||
phy_state = IDLE;
|
||||
rrc->earfcn_end();
|
||||
} else {
|
||||
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];
|
||||
set_frequency();
|
||||
}
|
||||
phy_state = CELL_SEARCH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void phch_recv::cell_search_next(bool reset) {
|
||||
if (cell_search_in_progress || reset) {
|
||||
cell_search_in_progress = false;
|
||||
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;
|
||||
if (reset) {
|
||||
cur_earfcn_index = -1;
|
||||
}
|
||||
cell_search_inc();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
@ -383,20 +318,21 @@ bool phch_recv::cell_handover(srslte_cell_t cell)
|
|||
bool ret = false;
|
||||
this->cell = cell;
|
||||
Info("Cell HO: Stopping sync with current cell\n");
|
||||
worker_com->reset_ul();
|
||||
phy_state = IDLE_RX;
|
||||
phy_state = IDLE;
|
||||
cnt = 0;
|
||||
while(!is_in_idle_rx && cnt<20) {
|
||||
while(!is_in_idle && cnt<20) {
|
||||
usleep(1000);
|
||||
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");
|
||||
if (set_cell()) {
|
||||
//resync_sfn(true, true);
|
||||
sfn_p.reset();
|
||||
phy_state = CELL_RESELECT;
|
||||
Info("Cell HO: Synchronizing with new cell\n");
|
||||
phy_state = CELL_SELECT;
|
||||
ret = true;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
// Check if we are already camping in this 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;
|
||||
|
||||
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) {
|
||||
log_h->info("Cell Select: Already in cell EARFCN=%d\n", earfcn);
|
||||
cell_search_in_progress = false;
|
||||
log_h->info("Cell Select: Already in cell EARFCN=%d, PCI=%d\n", earfcn, cell.id);
|
||||
if (srate_mode != SRATE_CAMP) {
|
||||
set_sampling_rate();
|
||||
log_h->info("Cell Select: Setting Camping sampling rate\n");
|
||||
}
|
||||
if (phy_state < CELL_SELECT) {
|
||||
resync_sfn();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
|
||||
cell_search_in_progress = false;
|
||||
|
||||
if (!stop_sync()) {
|
||||
log_h->warning("Still not in idle\n");
|
||||
}
|
||||
|
||||
if (earfcn != current_earfcn) {
|
||||
if (set_frequency()) {
|
||||
log_h->error("Cell Select: Configuring cell in EARFCN=%d, PCI=%d\n", earfcn, cell.id);
|
||||
return false;
|
||||
}
|
||||
current_earfcn = earfcn;
|
||||
}
|
||||
|
@ -443,13 +383,7 @@ bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) {
|
|||
|
||||
if (set_cell()) {
|
||||
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() {
|
||||
return tti;
|
||||
}
|
||||
|
@ -584,60 +502,61 @@ void phch_recv::run_thread()
|
|||
uint32_t sf_idx = 0;
|
||||
phy_state = IDLE;
|
||||
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)
|
||||
{
|
||||
if (phy_state != IDLE) {
|
||||
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_phy_lib_h->step(tti);
|
||||
|
||||
sf_idx = tti%10;
|
||||
|
||||
prev_state = phy_state;
|
||||
|
||||
switch (phy_state) {
|
||||
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)) {
|
||||
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();
|
||||
case search::CELL_FOUND:
|
||||
if (!srslte_cell_isvalid(&cell)) {
|
||||
Error("SYNC: Detected invalid cell\n");
|
||||
phy_state = IDLE;
|
||||
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;
|
||||
case CELL_RESELECT:
|
||||
cell_reselect();
|
||||
break;
|
||||
case CELL_SELECT:
|
||||
switch (sfn_p.run_subframe(&cell, &tti))
|
||||
{
|
||||
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);
|
||||
phy_state = CELL_CAMP;
|
||||
rrc->cell_camping(earfcn[cur_earfcn_index], cell);
|
||||
} else {
|
||||
log_h->info("Sync OK. Measuring PCI=%d...\n", cell.id);
|
||||
measure_p.reset();
|
||||
|
@ -645,13 +564,8 @@ void phch_recv::run_thread()
|
|||
}
|
||||
break;
|
||||
case sfn_sync::TIMEOUT:
|
||||
if (cell_search_in_progress) {
|
||||
log_h->warning("SYNC: Timeout while synchronizing SFN. Going back to cell search\n");
|
||||
phy_state = CELL_SEARCH;
|
||||
} else {
|
||||
log_h->warning("SYNC: Timeout while synchronizing SFN. Reselecting cell\n");
|
||||
resync_sfn(true, true);
|
||||
}
|
||||
log_h->warning("SYNC: Timeout while synchronizing SFN. Going back to cell search\n");
|
||||
phy_state = CELL_SEARCH;
|
||||
break;
|
||||
case sfn_sync::IDLE:
|
||||
break;
|
||||
|
@ -661,12 +575,21 @@ void phch_recv::run_thread()
|
|||
}
|
||||
break;
|
||||
case CELL_MEASURE:
|
||||
|
||||
switch(measure_p.run_subframe_sync(&ue_sync, sf_idx))
|
||||
{
|
||||
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);
|
||||
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;
|
||||
case measure::IDLE:
|
||||
break;
|
||||
|
@ -718,10 +641,11 @@ void phch_recv::run_thread()
|
|||
tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex;
|
||||
|
||||
// Reset Uplink TX buffer to avoid mixing packets in TX queue
|
||||
/*
|
||||
if (prach_buffer->is_pending()) {
|
||||
Info("SYNC: PRACH pending: Reset UL\n");
|
||||
worker_com->reset_ul();
|
||||
}
|
||||
radio_h->tx_end();
|
||||
}*/
|
||||
|
||||
// Check if we need to TX a PRACH
|
||||
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) {
|
||||
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;
|
||||
case 0:
|
||||
Warning("SYNC: Out-of-sync detected in PSS/SSS\n");
|
||||
|
@ -756,28 +682,18 @@ void phch_recv::run_thread()
|
|||
}
|
||||
break;
|
||||
case IDLE:
|
||||
if (!is_in_idle) {
|
||||
stop_rx();
|
||||
}
|
||||
is_in_idle = true;
|
||||
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->is_init()) {
|
||||
uint32_t nsamples = 1920;
|
||||
if (current_srate > 0) {
|
||||
nsamples = current_srate/1000;
|
||||
}
|
||||
if (!radio_h->rx_now(buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), NULL)) {
|
||||
Error("SYNC: Receiving from radio while in IDLE_RX\n");
|
||||
if (!radio_h->rx_now(dummy_buffer, nsamples, NULL)) {
|
||||
printf("SYNC: Receiving from radio while in IDLE_RX\n");
|
||||
}
|
||||
} else {
|
||||
// wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here
|
||||
running = false;
|
||||
usleep(1000);
|
||||
}
|
||||
is_in_idle = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -897,8 +813,8 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell)
|
|||
if (p->srate_mode != SRATE_FIND) {
|
||||
p->srate_mode = SRATE_FIND;
|
||||
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 */
|
||||
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");
|
||||
return ERROR;
|
||||
} else if (ret == 0) {
|
||||
p->stop_rx();
|
||||
Info("SYNC: Could not find any cell in this frequency\n");
|
||||
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,
|
||||
40,
|
||||
bch_payload, &cell->nof_ports, &sfn_offset);
|
||||
p->stop_rx();
|
||||
|
||||
if (ret == 1) {
|
||||
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);
|
||||
int ret = srslte_ue_sync_zerocopy_multi(ue_sync, buffer);
|
||||
if (ret < 0) {
|
||||
Error("SYNC: Error calling ue_sync_get_buffer");
|
||||
Error("SYNC: Error calling ue_sync_get_buffer.\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
@ -1060,7 +973,7 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c
|
|||
}
|
||||
}
|
||||
} else {
|
||||
Debug("SYNC: PSS/SSS not found...\n");
|
||||
Info("SYNC: PSS/SSS not found...\n");
|
||||
}
|
||||
|
||||
cnt++;
|
||||
|
@ -1080,11 +993,10 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c
|
|||
/*********
|
||||
* 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;
|
||||
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
|
||||
this->buffer[i] = buffer[i];
|
||||
|
@ -1117,17 +1029,21 @@ void phch_recv::measure::set_cell(srslte_cell_t cell)
|
|||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
float phch_recv::measure::rssi() {
|
||||
return 10*log10(mean_rssi);
|
||||
}
|
||||
|
||||
float phch_recv::measure::rsrp() {
|
||||
return mean_rsrp;
|
||||
return 10*log10(mean_rsrp) + 30 - rx_gain_offset;
|
||||
}
|
||||
|
||||
float phch_recv::measure::rsrq() {
|
||||
return mean_rsrq;
|
||||
return 10*log10(mean_rsrq);
|
||||
}
|
||||
|
||||
float phch_recv::measure::snr() {
|
||||
return mean_snr;
|
||||
return 10*log10(mean_snr);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30 - rx_gain_offset;
|
||||
float rsrq = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest));
|
||||
float snr = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest));
|
||||
float rssi = 10*log10(srslte_vec_avg_power_cf(buffer[0], SRSLTE_SF_LEN_PRB(current_prb))) + 30;
|
||||
float rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest);
|
||||
float rsrq = srslte_chest_dl_get_rsrq(&ue_dl.chest);
|
||||
float snr = srslte_chest_dl_get_snr(&ue_dl.chest);
|
||||
float rssi = srslte_vec_avg_power_cf(buffer[0], SRSLTE_SF_LEN_PRB(current_prb));
|
||||
|
||||
if (cnt == 0) {
|
||||
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);
|
||||
|
||||
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;
|
||||
} else {
|
||||
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);
|
||||
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.
|
||||
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) {
|
||||
|
||||
// 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));
|
||||
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;
|
||||
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool phch_worker::set_cell(srslte_cell_t cell_)
|
||||
{
|
||||
bool ret = false;
|
||||
pthread_mutex_lock(&mutex);
|
||||
if (cell.id != cell_.id || !cell_initiated) {
|
||||
memcpy(&cell, &cell_, sizeof(srslte_cell_t));
|
||||
|
||||
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
|
||||
Error("Initiating UE DL\n");
|
||||
return false;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (srslte_ue_ul_set_cell(&ue_ul, cell)) {
|
||||
Error("Initiating UE UL\n");
|
||||
return false;
|
||||
goto unlock;
|
||||
}
|
||||
srslte_ue_ul_set_normalization(&ue_ul, true);
|
||||
srslte_ue_ul_set_cfo_enable(&ue_ul, 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)
|
||||
|
@ -195,7 +201,7 @@ void phch_worker::set_crnti(uint16_t rnti)
|
|||
{
|
||||
srslte_ue_dl_set_rnti(&ue_dl, rnti);
|
||||
srslte_ue_ul_set_rnti(&ue_ul, rnti);
|
||||
rnti_is_set = true;
|
||||
rnti_is_set = true;
|
||||
}
|
||||
|
||||
float phch_worker::get_ref_cfo()
|
||||
|
@ -243,7 +249,9 @@ void phch_worker::work_imp()
|
|||
if (!cell_initiated) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
Debug("TTI %d running\n", tti);
|
||||
|
||||
#ifdef LOG_EXECTIME
|
||||
|
@ -402,7 +410,7 @@ void phch_worker::work_imp()
|
|||
update_measurements();
|
||||
|
||||
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",
|
||||
10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)), phy->avg_rsrp_dbm);
|
||||
chest_loop->in_sync();
|
||||
|
@ -412,7 +420,9 @@ void phch_worker::work_imp()
|
|||
chest_loop->out_of_sync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
/* Tell the plotting thread to draw the plots */
|
||||
#ifdef ENABLE_GUI
|
||||
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)
|
||||
{
|
||||
|
||||
phy_interface_rrc::phy_cfg_common_t *common = &phy->config->common;
|
||||
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 */
|
||||
if (get_id() == 0) {
|
||||
if (rssi_read_cnt) {
|
||||
if (!rssi_read_cnt) {
|
||||
if (phy->get_radio()->has_rssi() && phy->args->rssi_sensor_enabled) {
|
||||
phy->last_radio_rssi = phy->get_radio()->get_rssi();
|
||||
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();
|
||||
}
|
||||
|
||||
void phy::cell_search_stop()
|
||||
{
|
||||
sf_recv.cell_search_stop();
|
||||
}
|
||||
|
||||
void phy::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);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -366,8 +361,6 @@ void phy::reset()
|
|||
workers[i].reset();
|
||||
}
|
||||
workers_common.reset();
|
||||
usleep(4000);
|
||||
workers_common.reset_ul();
|
||||
}
|
||||
|
||||
uint32_t phy::get_current_tti()
|
||||
|
|
|
@ -40,12 +40,10 @@ namespace srsue{
|
|||
ue::ue()
|
||||
:started(false)
|
||||
{
|
||||
pool = byte_buffer_pool::get_instance();
|
||||
}
|
||||
|
||||
ue::~ue()
|
||||
{
|
||||
byte_buffer_pool::cleanup();
|
||||
}
|
||||
|
||||
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->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();
|
||||
} 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
|
||||
srslte_dft_load();
|
||||
|
||||
pool = byte_buffer_pool::get_instance();
|
||||
}
|
||||
|
||||
ue_base::~ue_base() {
|
||||
byte_buffer_pool::cleanup();
|
||||
}
|
||||
|
||||
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
|
||||
void nas::plmn_search_end() {
|
||||
if (known_plmns.size() > 0) {
|
||||
nas_log->info("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n",
|
||||
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(),
|
||||
plmn_id_to_string(known_plmns[0]).c_str());
|
||||
if (home_plmn.mcc != known_plmns[0].mcc && home_plmn.mnc != known_plmns[0].mnc) {
|
||||
nas_log->info("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n",
|
||||
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(),
|
||||
plmn_id_to_string(known_plmns[0]).c_str());
|
||||
}
|
||||
rrc->plmn_select(known_plmns[0]);
|
||||
} 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;
|
||||
n311_cnt = 0;
|
||||
serving_cell = new cell_t();
|
||||
neighbour_cells.reserve(NOF_NEIGHBOUR_CELLS);
|
||||
}
|
||||
|
||||
rrc::~rrc()
|
||||
|
@ -168,6 +169,7 @@ void rrc::set_args(rrc_args_t *args) {
|
|||
void rrc::run_thread() {
|
||||
|
||||
uint32_t failure_test = 0;
|
||||
uint32_t cell_clean_cnt = 0;
|
||||
|
||||
while (thread_running) {
|
||||
|
||||
|
@ -185,6 +187,7 @@ void rrc::run_thread() {
|
|||
sleep(1);
|
||||
rrc_log->info("RRC IDLE: NAS is attaching and camping on cell, reselecting...\n");
|
||||
plmn_select_rrc(selected_plmn_id);
|
||||
connection_requested = true;
|
||||
}
|
||||
// If not camping on a cell
|
||||
} else {
|
||||
|
@ -200,15 +203,18 @@ void rrc::run_thread() {
|
|||
// If not attached, PLMN selection will be triggered from higher layers
|
||||
}
|
||||
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:
|
||||
plmn_select_timeout++;
|
||||
if (plmn_select_timeout >= RRC_PLMN_SELECT_TIMEOUT) {
|
||||
rrc_log->info("RRC PLMN Search: timeout expired\n");
|
||||
phy->cell_search_stop();
|
||||
sleep(1);
|
||||
rrc_log->console("\nRRC PLMN Search: timeout expired. Searching again\n");
|
||||
plmn_select_timeout = 0;
|
||||
phy->cell_search_start();
|
||||
rrc_log->console("\nRRC PLMN Search: timeout expired.\n");
|
||||
state = RRC_STATE_IDLE;
|
||||
}
|
||||
break;
|
||||
case RRC_STATE_CELL_SELECTING:
|
||||
|
@ -217,26 +223,25 @@ void rrc::run_thread() {
|
|||
* Cell is selected when all SIBs downloaded or applied.
|
||||
*/
|
||||
if (phy->sync_status()) {
|
||||
if (!serving_cell->has_valid_sib1) {
|
||||
if (!serving_cell->has_sib1()) {
|
||||
si_acquire_state = SI_ACQUIRE_SIB1;
|
||||
sysinfo_index = 0;
|
||||
} else if (!serving_cell->has_valid_sib2) {
|
||||
} else if (!serving_cell->has_sib2()) {
|
||||
si_acquire_state = SI_ACQUIRE_SIB2;
|
||||
} else {
|
||||
apply_sib2_configs(&serving_cell->sib2);
|
||||
apply_sib2_configs(serving_cell->sib2ptr());
|
||||
si_acquire_state = SI_ACQUIRE_IDLE;
|
||||
state = RRC_STATE_CELL_SELECTED;
|
||||
}
|
||||
}
|
||||
// Don't time out during restablishment (T311 running)
|
||||
if (!mac_timers->timer_get(t311)->is_running()) {
|
||||
// Don't time out during reestablishment (T311 running)
|
||||
if (!mac_timers->timer_get(t311)->is_running() || !phy->sync_status()) {
|
||||
select_cell_timeout++;
|
||||
if (select_cell_timeout >= RRC_SELECT_CELL_TIMEOUT) {
|
||||
rrc_log->info("RRC Cell Selecting: timeout expired. Starting Cell Search...\n");
|
||||
plmn_select_timeout = 0;
|
||||
select_cell_timeout = 0;
|
||||
state = RRC_STATE_PLMN_START;
|
||||
serving_cell->in_sync = false;
|
||||
phy->cell_search_start();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -302,6 +307,13 @@ void rrc::run_thread() {
|
|||
default:
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -342,7 +354,7 @@ void rrc::run_si_acquisition_procedure()
|
|||
tti = mac->get_current_tti();
|
||||
si_win_start = sib_start_tti(tti, 2, 0, 5);
|
||||
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;
|
||||
|
@ -363,24 +375,24 @@ void rrc::run_si_acquisition_procedure()
|
|||
break;
|
||||
case SI_ACQUIRE_SIB2:
|
||||
// Instruct MAC to look for next SIB
|
||||
if(sysinfo_index < serving_cell->sib1.N_sched_info) {
|
||||
si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length];
|
||||
if(sysinfo_index < serving_cell->sib1ptr()->N_sched_info) {
|
||||
si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length];
|
||||
x = sysinfo_index*si_win_len;
|
||||
sf = x%10;
|
||||
offset = x/10;
|
||||
|
||||
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_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 ||
|
||||
(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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -416,24 +428,15 @@ void rrc::run_si_acquisition_procedure()
|
|||
*******************************************************************************/
|
||||
|
||||
uint16_t rrc::get_mcc() {
|
||||
if (serving_cell->sib1.N_plmn_ids > 0) {
|
||||
return serving_cell->sib1.plmn_id[0].id.mcc;
|
||||
}
|
||||
return 0;
|
||||
return serving_cell->get_mcc();
|
||||
}
|
||||
|
||||
uint16_t rrc::get_mnc() {
|
||||
if (serving_cell->sib1.N_plmn_ids > 0) {
|
||||
return serving_cell->sib1.plmn_id[0].id.mnc;
|
||||
}
|
||||
return 0;
|
||||
return serving_cell->get_mnc();
|
||||
}
|
||||
|
||||
void rrc::plmn_search() {
|
||||
rrc_log->info("Starting PLMN search procedure\n");
|
||||
state = RRC_STATE_PLMN_SELECTION;
|
||||
phy->cell_search_start();
|
||||
plmn_select_timeout = 0;
|
||||
state = RRC_STATE_PLMN_START;
|
||||
}
|
||||
|
||||
/* 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 (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");
|
||||
state = RRC_STATE_CELL_SELECTING;
|
||||
select_cell_timeout = 0;
|
||||
} 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;
|
||||
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 {
|
||||
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
|
||||
if (serving_cell->is_valid()) {
|
||||
// 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()) {
|
||||
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());
|
||||
|
@ -506,7 +522,7 @@ void rrc::set_serving_cell(uint32_t cell_idx) {
|
|||
serving_cell = new_serving_cell;
|
||||
|
||||
rrc_log->info("Setting serving cell idx=%d, earfcn=%d, PCI=%d, nof_neighbours=%d\n",
|
||||
cell_idx, serving_cell->earfcn, serving_cell->phy_cell.id, neighbour_cells.size());
|
||||
cell_idx, serving_cell->get_earfcn(), serving_cell->phy_cell.id, neighbour_cells.size());
|
||||
|
||||
} else {
|
||||
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
|
||||
{
|
||||
// Try to select Cell
|
||||
if (phy->cell_select(neighbour_cells[i]->earfcn, neighbour_cells[i]->phy_cell)) {
|
||||
set_serving_cell(i);
|
||||
rrc_log->info("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
|
||||
serving_cell->phy_cell.id, serving_cell->earfcn,
|
||||
serving_cell->sib1.cell_id);
|
||||
rrc_log->console("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
|
||||
serving_cell->phy_cell.id, serving_cell->earfcn,
|
||||
serving_cell->sib1.cell_id);
|
||||
} else {
|
||||
// Set to out-of-sync if can't synchronize
|
||||
neighbour_cells[i]->in_sync = false;
|
||||
rrc_log->warning("Selecting cell EARFCN=%d, Cell ID=0x%x.\n",
|
||||
neighbour_cells[i]->earfcn, neighbour_cells[i]->sib1.cell_id);
|
||||
}
|
||||
phy->cell_select(neighbour_cells[i]->get_earfcn(), neighbour_cells[i]->phy_cell);
|
||||
set_serving_cell(i);
|
||||
rrc_log->info("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
|
||||
serving_cell->phy_cell.id, serving_cell->get_earfcn(),
|
||||
serving_cell->get_cell_id());
|
||||
rrc_log->console("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
|
||||
serving_cell->phy_cell.id, serving_cell->get_earfcn(),
|
||||
serving_cell->get_cell_id());
|
||||
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) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -560,7 +570,7 @@ void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int p
|
|||
// Update serving cell
|
||||
if (serving_cell->equals(earfcn, pci)) {
|
||||
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);
|
||||
|
||||
// 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)
|
||||
if (cell_selection_eval(neighbour_cells[0]->rsrp) &&
|
||||
neighbour_cells[0]->rsrp > serving_cell->rsrp + 5)
|
||||
if (neighbour_cells.size() > 1 &&
|
||||
cell_selection_eval(neighbour_cells[0]->get_rsrp()) &&
|
||||
neighbour_cells[0]->get_rsrp() > serving_cell->get_rsrp() + 5)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
int cell_idx = -1;
|
||||
|
||||
if (serving_cell->equals(earfcn, phy_cell.id)) {
|
||||
serving_cell->rsrp = rsrp;
|
||||
serving_cell->in_sync = true;
|
||||
serving_cell->set_rsrp(rsrp);
|
||||
found = true;
|
||||
} else {
|
||||
// Check if cell is in our list of neighbour cells
|
||||
cell_idx = find_neighbour_cell(earfcn, phy_cell.id);
|
||||
if (cell_idx >= 0) {
|
||||
set_serving_cell(cell_idx);
|
||||
serving_cell->rsrp = rsrp;
|
||||
serving_cell->in_sync = true;
|
||||
serving_cell->set_rsrp(rsrp);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
|
||||
if (!serving_cell->has_valid_sib1) {
|
||||
if (!serving_cell->has_sib1()) {
|
||||
si_acquire_state = SI_ACQUIRE_SIB1;
|
||||
} else if (state == RRC_STATE_PLMN_SELECTION) {
|
||||
for (uint32_t j = 0; j < serving_cell->sib1.N_plmn_ids; j++) {
|
||||
nas->plmn_found(serving_cell->sib1.plmn_id[j].id, serving_cell->sib1.tracking_area_code);
|
||||
for (uint32_t j = 0; j < serving_cell->sib1ptr()->N_plmn_ids; j++) {
|
||||
nas->plmn_found(serving_cell->sib1ptr()->plmn_id[j].id, serving_cell->sib1ptr()->tracking_area_code);
|
||||
}
|
||||
usleep(5000);
|
||||
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();
|
||||
} else {
|
||||
set_serving_cell(earfcn, phy_cell.id);
|
||||
|
||||
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",
|
||||
found?"Updating":"Adding",
|
||||
cell_idx>=0?"neighbour":"serving",
|
||||
serving_cell->earfcn,
|
||||
serving_cell->get_earfcn(),
|
||||
serving_cell->phy_cell.id,
|
||||
serving_cell->rsrp);
|
||||
serving_cell->get_rsrp());
|
||||
}
|
||||
|
||||
bool sort_rsrp(cell_t *u1, cell_t *u2) {
|
||||
return !u1->greater(u2);
|
||||
return u1->greater(u2);
|
||||
}
|
||||
|
||||
void rrc::delete_neighbour(uint32_t cell_idx) {
|
||||
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());
|
||||
}
|
||||
|
||||
std::vector<cell_t*>::iterator rrc::delete_neighbour(std::vector<cell_t*>::iterator it) {
|
||||
measurements.delete_report((*it)->get_earfcn(), (*it)->get_pci());
|
||||
delete (*it);
|
||||
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() {
|
||||
|
||||
for (uint32_t i=1;i<neighbour_cells.size();i++) {
|
||||
if (neighbour_cells[i]->in_sync == false) {
|
||||
rrc_log->info("Removing neighbour cell PCI=%d, out_of_sync\n", neighbour_cells[i]->phy_cell.id);
|
||||
neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[i]), neighbour_cells.end());
|
||||
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];
|
||||
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++) {
|
||||
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 ret = false;
|
||||
if (neighbour_cells.size() < NOF_NEIGHBOUR_CELLS - 1) {
|
||||
if (neighbour_cells.size() < NOF_NEIGHBOUR_CELLS) {
|
||||
ret = true;
|
||||
} else if (!neighbour_cells[neighbour_cells.size()-1]->greater(new_cell)) {
|
||||
// Delete old one
|
||||
delete neighbour_cells[neighbour_cells.size()-1];
|
||||
neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[neighbour_cells.size()-1]), neighbour_cells.end());
|
||||
} else if (new_cell->greater(neighbour_cells[neighbour_cells.size()-1])) {
|
||||
// Replace old one by new one
|
||||
delete_neighbour(neighbour_cells.size()-1);
|
||||
ret = true;
|
||||
}
|
||||
if (ret) {
|
||||
neighbour_cells.push_back(new_cell);
|
||||
}
|
||||
rrc_log->info("Added neighbour cell EARFCN=%d, PCI=%d, nof_neighbours=%d\n",
|
||||
new_cell->earfcn, new_cell->phy_cell.id, neighbour_cells.size());
|
||||
new_cell->get_earfcn(), new_cell->get_pci(), neighbour_cells.size());
|
||||
sort_neighbour_cells();
|
||||
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) {
|
||||
if (earfcn == 0) {
|
||||
earfcn = serving_cell->earfcn;
|
||||
earfcn = serving_cell->get_earfcn();
|
||||
}
|
||||
|
||||
// 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 (cell_idx >= 0) {
|
||||
neighbour_cells[cell_idx]->rsrp = rsrp;
|
||||
neighbour_cells[cell_idx]->set_rsrp(rsrp);
|
||||
sort_neighbour_cells();
|
||||
return true;
|
||||
}
|
||||
|
@ -727,10 +769,8 @@ void rrc::earfcn_end() {
|
|||
// If searching for PLMN, indicate NAS we scanned all frequencies
|
||||
if (state == RRC_STATE_PLMN_SELECTION) {
|
||||
nas->plmn_search_end();
|
||||
} else if (state == RRC_STATE_CELL_SELECTING) {
|
||||
select_cell_timeout = 0;
|
||||
rrc_log->info("Starting cell search again\n");
|
||||
phy->cell_search_start();
|
||||
} else if (state == RRC_STATE_CONNECTED) {
|
||||
leave_connected();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -791,11 +831,11 @@ void rrc::out_of_sync() {
|
|||
if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) {
|
||||
n310_cnt++;
|
||||
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)->run();
|
||||
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 {
|
||||
|
@ -822,7 +862,6 @@ void rrc::in_sync() {
|
|||
void rrc::radio_link_failure() {
|
||||
// TODO: Generate and store failure report
|
||||
|
||||
phy->sync_reset();
|
||||
rrc_log->warning("Detected Radio-Link Failure\n");
|
||||
rrc_log->console("Warning: Detected Radio-Link Failure\n");
|
||||
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;
|
||||
|
||||
// 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];
|
||||
liblte_rrc_pack_phys_cell_id_ie(phy->get_current_pci(), &msg_ptr);
|
||||
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);
|
||||
|
||||
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
|
||||
uint8_t mac_key[4];
|
||||
|
@ -962,7 +1001,6 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause,
|
|||
break;
|
||||
default:
|
||||
rrc_log->info("Unsupported integrity algorithm during reestablishment\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare ConnectionRestalishmentRequest packet
|
||||
|
@ -982,6 +1020,7 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause,
|
|||
set_phy_default();
|
||||
mac->reset();
|
||||
set_mac_default();
|
||||
phy->sync_reset();
|
||||
state = RRC_STATE_CELL_SELECTING;
|
||||
}
|
||||
|
||||
|
@ -1065,10 +1104,10 @@ bool rrc::ho_prepare() {
|
|||
if (pending_mob_reconf) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1076,7 +1115,7 @@ bool rrc::ho_prepare() {
|
|||
mac_timers->timer_get(t310)->stop();
|
||||
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 &&
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -1095,13 +1134,14 @@ bool rrc::ho_prepare() {
|
|||
pdcp->reestablish();
|
||||
rlc->reestablish();
|
||||
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);
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1177,7 +1217,7 @@ void rrc::ho_failed() {
|
|||
|
||||
// Instruct PHY to resync with source PCI
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
|
||||
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->has_valid_sib1 = true;
|
||||
serving_cell->set_sib1(&dlsch_msg.sibs[i].sib.sib1);
|
||||
handle_sib1();
|
||||
} else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_valid_sib2) {
|
||||
memcpy(&serving_cell->sib2, &dlsch_msg.sibs[i].sib.sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT));
|
||||
serving_cell->has_valid_sib2 = true;
|
||||
} else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib2()) {
|
||||
serving_cell->set_sib2(&dlsch_msg.sibs[i].sib.sib2);
|
||||
handle_sib2();
|
||||
} else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_valid_sib3) {
|
||||
memcpy(&serving_cell->sib3, &dlsch_msg.sibs[i].sib.sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT));
|
||||
serving_cell->has_valid_sib3 = true;
|
||||
} else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib3()) {
|
||||
serving_cell->set_sib3(&dlsch_msg.sibs[i].sib.sib3);
|
||||
handle_sib3();
|
||||
}else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_valid_sib13) {
|
||||
memcpy(&serving_cell->sib13, &dlsch_msg.sibs[0].sib.sib13, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT));
|
||||
serving_cell->has_valid_sib13 = true;
|
||||
}else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib13()) {
|
||||
serving_cell->set_sib13(&dlsch_msg.sibs[i].sib.sib13);
|
||||
handle_sib13();
|
||||
}
|
||||
}
|
||||
|
||||
last_win_start = 0;
|
||||
|
||||
if(serving_cell->has_valid_sib2) {
|
||||
if(serving_cell->has_sib2()) {
|
||||
sysinfo_index++;
|
||||
}
|
||||
}
|
||||
|
@ -1330,16 +1366,16 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) {
|
|||
void rrc::handle_sib1()
|
||||
{
|
||||
rrc_log->info("SIB1 received, CellID=%d, si_window=%d, sib2_period=%d\n",
|
||||
serving_cell->sib1.cell_id&0xfff,
|
||||
liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length],
|
||||
liblte_rrc_si_periodicity_num[serving_cell->sib1.sched_info[0].si_periodicity]);
|
||||
serving_cell->get_cell_id()&0xfff,
|
||||
liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length],
|
||||
liblte_rrc_si_periodicity_num[serving_cell->sib1ptr()->sched_info[0].si_periodicity]);
|
||||
|
||||
// Print SIB scheduling info
|
||||
uint32_t i,j;
|
||||
for(i=0;i<serving_cell->sib1.N_sched_info;i++){
|
||||
for(j=0;j<serving_cell->sib1.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_SI_PERIODICITY_ENUM p = serving_cell->sib1.sched_info[i].si_periodicity;
|
||||
for(i=0;i<serving_cell->sib1ptr()->N_sched_info;i++){
|
||||
for(j=0;j<serving_cell->sib1ptr()->sched_info[i].N_sib_mapping_info;j++){
|
||||
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->sib1ptr()->sched_info[i].si_periodicity;
|
||||
rrc_log->debug("SIB scheduling info, sib_type=%d, si_periodicity=%d\n",
|
||||
liblte_rrc_sib_type_num[t],
|
||||
liblte_rrc_si_periodicity_num[p]);
|
||||
|
@ -1347,16 +1383,14 @@ void rrc::handle_sib1()
|
|||
}
|
||||
|
||||
// Set TDD Config
|
||||
if(serving_cell->sib1.tdd) {
|
||||
phy->set_config_tdd(&serving_cell->sib1.tdd_cnfg);
|
||||
if(serving_cell->sib1ptr()->tdd) {
|
||||
phy->set_config_tdd(&serving_cell->sib1ptr()->tdd_cnfg);
|
||||
}
|
||||
|
||||
serving_cell->has_valid_sib1 = true;
|
||||
|
||||
// Send PLMN and TAC to NAS
|
||||
std::stringstream ss;
|
||||
for (uint32_t i = 0; i < serving_cell->sib1.N_plmn_ids; i++) {
|
||||
nas->plmn_found(serving_cell->sib1.plmn_id[i].id, serving_cell->sib1.tracking_area_code);
|
||||
for (uint32_t i = 0; i < serving_cell->sib1ptr()->N_plmn_ids; i++) {
|
||||
nas->plmn_found(serving_cell->sib1ptr()->plmn_id[i].id, serving_cell->sib1ptr()->tracking_area_code);
|
||||
}
|
||||
|
||||
// Jump to next state
|
||||
|
@ -1379,7 +1413,7 @@ void rrc::handle_sib2()
|
|||
{
|
||||
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");
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
srslte_bit_pack_vector(bit_buf.msg, pdcp_buf->msg, bit_buf.N_bits);
|
||||
pdcp_buf->N_bytes = bit_buf.N_bits / 8;
|
||||
pdcp_buf->set_timestamp();
|
||||
|
||||
if (pdcp_buf != NULL) {
|
||||
srslte_bit_pack_vector(bit_buf.msg, pdcp_buf->msg, bit_buf.N_bits);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
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
|
||||
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];
|
||||
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]);
|
||||
pdcp->write_sdu(RB_ID_SRB0, pdu);
|
||||
}
|
||||
|
||||
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]);
|
||||
pdcp->write_sdu(RB_ID_SRB0, 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);
|
||||
|
||||
pdu = byte_align_and_pack(pdu);
|
||||
|
||||
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);
|
||||
if (pdu) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
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");
|
||||
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);
|
||||
|
||||
// Update serving cell measurement
|
||||
parent->serving_cell->rsrp = rsrp;
|
||||
parent->serving_cell->set_rsrp(rsrp);
|
||||
|
||||
} else {
|
||||
|
||||
// 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) {
|
||||
meas_t *m = &iter->second;
|
||||
if (objects[m->object_id].earfcn == earfcn) {
|
||||
// If it's a newly discovered cell, add it to objects
|
||||
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;
|
||||
// Only report measurements of 8th strongest cells
|
||||
if (added) {
|
||||
// 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) {
|
||||
meas_t *m = &iter->second;
|
||||
if (objects[m->object_id].earfcn == earfcn) {
|
||||
// If it's a newly discovered cell, add it to objects
|
||||
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
|
||||
# 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.
|
||||
# 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.,
|
||||
# Default is to use tx_gain in [rf] section.
|
||||
# cqi_max: Upper bound on the maximum CQI to be reported. Default 15.
|
||||
|
@ -176,6 +177,7 @@ enable = false
|
|||
[expert]
|
||||
#ip_netmask = 255.255.255.0
|
||||
#rssi_sensor_enabled = false
|
||||
#rx_gain_offset = 72
|
||||
#prach_gain = 30
|
||||
#cqi_max = 15
|
||||
#cqi_fixed = 10
|
||||
|
|
Loading…
Reference in New Issue