stable connection. Runs out of samples in ringbuffer if clock differences

This commit is contained in:
Ismael Gomez 2017-10-13 17:59:12 +02:00
parent db87a41d80
commit c4c1c62360
9 changed files with 152 additions and 38 deletions

View File

@ -17,17 +17,19 @@ typedef struct {
} srslte_ringbuffer_t;
SRSLTE_API int srslte_ringbuffer_init(srslte_ringbuffer_t *q,
SRSLTE_API int srslte_ringbuffer_init(srslte_ringbuffer_t *q,
int capacity);
SRSLTE_API void srslte_ringbuffer_free(srslte_ringbuffer_t *q,
int capacity);
SRSLTE_API int srslte_ringbuffer_write(srslte_ringbuffer_t *q,
SRSLTE_API int srslte_ringbuffer_status(srslte_ringbuffer_t *q);
SRSLTE_API int srslte_ringbuffer_write(srslte_ringbuffer_t *q,
void *ptr,
int nof_bytes);
SRSLTE_API int srslte_ringbuffer_read(srslte_ringbuffer_t *q,
SRSLTE_API int srslte_ringbuffer_read(srslte_ringbuffer_t *q,
void *ptr,
int nof_bytes);

View File

@ -34,6 +34,11 @@ void srslte_ringbuffer_free(srslte_ringbuffer_t *q, int capacity)
}
}
int srslte_ringbuffer_status(srslte_ringbuffer_t *q)
{
return q->count;
}
int srslte_ringbuffer_write(srslte_ringbuffer_t *q, void *p, int nof_bytes)
{
uint8_t *ptr = (uint8_t*) p;

View File

@ -67,7 +67,9 @@ public:
void set_time_adv_sec(float time_adv_sec);
void get_current_cell(srslte_cell_t *cell);
void scell_enable(bool enable);
const static int MUTEX_X_WORKER = 4;
int radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time);
@ -155,6 +157,7 @@ private:
float rsrp();
float rsrq();
float snr();
float cfo();
private:
srslte::log *log_h;
srslte_ue_dl_t ue_dl;
@ -162,7 +165,7 @@ private:
cf_t *buffer[SRSLTE_MAX_PORTS];
uint32_t cnt;
uint32_t nof_subframes;
float mean_rsrp, mean_rsrq, mean_snr;
float mean_rsrp, mean_rsrq, mean_snr, mean_cfo;
const static int RSRP_MEASURE_NOF_FRAMES = 5;
};
@ -172,9 +175,11 @@ private:
public:
void init(phch_recv *parent, srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t prio, int cpu_affinity = -1);
void stop();
void reset();
int recv(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time);
void write(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time);
bool is_enabled();
void set_cell(srslte_cell_t scell);
private:
void run_thread();
@ -192,6 +197,8 @@ private:
cf_t *sf_buffer[SRSLTE_MAX_PORTS];
srslte_ue_sync_t ue_sync;
srslte_cell_t cell;
uint32_t nof_rx_antennas;
uint32_t current_sflen;
measure measure_p;
sfn_sync sfn_p;

View File

@ -78,6 +78,8 @@ public:
void set_earfcn(std::vector<uint32_t> earfcns);
void force_freq(float dl_freq, float ul_freq);
void scell_enable(bool enable);
/********** RRC INTERFACE ********************/
void reset();
void sync_reset();

View File

@ -80,6 +80,7 @@ public:
void pregenerate_signals(bool enable);
void test_scell();
private:
virtual ~ue();

View File

@ -387,14 +387,20 @@ int main(int argc, char *argv[])
pthread_t input;
pthread_create(&input, NULL, &input_loop, &args);
bool scell_done = false;
bool plot_started = false;
bool signals_pregenerated = false;
while (running) {
if (ue->is_attached()) {
if (!signals_pregenerated && args.expert.pregenerate_signals) {
ue->pregenerate_signals(true);
signals_pregenerated = true;
}
if (!scell_done) {
((srsue::ue*) ue)->test_scell();
scell_done = true;
}
if (!plot_started && args.gui.enable) {
ue->start_plot();
plot_started = true;

View File

@ -64,7 +64,8 @@ phch_recv::phch_recv() {
void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_mac, rrc_interface_phy *_rrc,
prach *_prach_buffer, srslte::thread_pool *_workers_pool,
phch_common *_worker_com, srslte::log *_log_h, uint32_t nof_rx_antennas_, uint32_t prio,
int sync_cpu_affinity) {
int sync_cpu_affinity)
{
radio_h = _radio_handler;
log_h = _log_h;
mac = _mac;
@ -96,7 +97,7 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma
measure_p.init(&ue_sync, sf_buffer, log_h, nof_rx_antennas);
// Start scell
scell.init(this, log_h, nof_rx_antennas_, prio, sync_cpu_affinity);
scell.init(this, log_h, nof_rx_antennas_, prio-1, sync_cpu_affinity);
reset();
@ -106,7 +107,6 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma
} else {
start_cpu(prio, sync_cpu_affinity);
}
}
phch_recv::~phch_recv() {
@ -118,13 +118,15 @@ phch_recv::~phch_recv() {
srslte_ue_sync_free(&ue_sync);
}
void phch_recv::stop() {
void phch_recv::stop()
{
running = false;
wait_thread_finish();
}
void phch_recv::reset() {
void phch_recv::reset()
{
tx_mutex_cnt = 0;
running = true;
phy_state = IDLE;
@ -141,7 +143,8 @@ void phch_recv::reset() {
}
void phch_recv::radio_error() {
void phch_recv::radio_error()
{
log_h->error("SYNC: Receiving from radio.\n");
phy_state = IDLE;
radio_is_resetting=true;
@ -157,7 +160,8 @@ void phch_recv::radio_error() {
radio_is_resetting=false;
}
bool phch_recv::wait_radio_reset() {
bool phch_recv::wait_radio_reset()
{
int cnt=0;
while(cnt < 20 && radio_is_resetting) {
sleep(1);
@ -166,11 +170,13 @@ bool phch_recv::wait_radio_reset() {
return radio_is_resetting;
}
void phch_recv::set_agc_enable(bool enable) {
void phch_recv::set_agc_enable(bool enable)
{
do_agc = enable;
}
void phch_recv::set_time_adv_sec(float _time_adv_sec) {
void phch_recv::set_time_adv_sec(float _time_adv_sec)
{
if (TX_MODE_CONTINUOUS && !radio_h->is_first_of_burst()) {
int nsamples = ceil(current_srate*_time_adv_sec);
next_offset = -nsamples;
@ -179,7 +185,8 @@ void phch_recv::set_time_adv_sec(float _time_adv_sec) {
}
}
void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) {
void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q)
{
if (worker_com->args->cfo_integer_enabled) {
srslte_ue_sync_cfo_i_detec_en(q, true);
}
@ -473,9 +480,12 @@ int phch_recv::radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, s
next_offset = nsamples;
}
if (offset == 0) {
if (offset <= 0) {
scell.write(data, nsamples, rx_time);
}
log_h->debug("SYNC: received %d samples from radio\n", nsamples);
return nsamples;
} else {
return -1;
@ -487,7 +497,13 @@ int phch_recv::scell_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, s
return scell.recv(data, nsamples, rx_time);
}
void phch_recv::scell_enable(bool enable)
{
srslte_cell_t target_cell;
memcpy(&target_cell, &cell, sizeof(srslte_cell_t));
target_cell.id++;
scell.set_cell(target_cell);
}
@ -512,7 +528,6 @@ void phch_recv::run_thread()
Debug("SYNC: state=%d\n", phy_state);
}
tti = (tti+1) % 10240;
log_h->step(tti);
sf_idx = tti%10;
@ -635,7 +650,6 @@ void phch_recv::run_thread()
rrc->out_of_sync();
worker->release();
worker_com->reset_ul();
mac->tti_clock(tti);
break;
default:
radio_error();
@ -652,11 +666,12 @@ void phch_recv::run_thread()
}
is_in_idle = true;
usleep(1000);
// Keep running MAC timer from system clock
tti = (tti+1) % 10240;
mac->tti_clock(tti);
break;
}
// Increase TTI counter and trigger MAC clock (lower priority)
tti = (tti+1) % 10240;
mac->tti_clock(tti);
}
}
@ -860,6 +875,7 @@ bool phch_recv::sfn_sync::set_cell(srslte_cell_t cell)
Error("SYNC: Setting cell: initiating ue_mib\n");
return false;
}
reset();
return true;
}
@ -952,7 +968,8 @@ void phch_recv::measure::reset() {
cnt = 0;
mean_rsrp = 0;
mean_rsrq = 0;
mean_snr = 0;
mean_snr = 0;
mean_cfo = 0;
}
void phch_recv::measure::set_cell(srslte_cell_t cell)
@ -960,6 +977,7 @@ void phch_recv::measure::set_cell(srslte_cell_t cell)
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
Error("SYNC: Setting cell: initiating ue_dl_measure\n");
}
reset();
}
float phch_recv::measure::rsrp() {
@ -974,6 +992,10 @@ float phch_recv::measure::snr() {
return 10*log10(mean_snr);
}
float phch_recv::measure::cfo() {
return mean_cfo;
}
phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx)
{
int sync_res = srslte_ue_sync_zerocopy_multi(ue_sync, buffer);
@ -988,10 +1010,12 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx)
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 cfo = srslte_ue_sync_get_cfo(ue_sync);
mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt);
mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt);
mean_snr = SRSLTE_VEC_CMA(rsrq, mean_snr, cnt);
mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt);
mean_cfo = SRSLTE_VEC_CMA(cfo, mean_cfo, cnt);
cnt++;
log_h->info("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n",
@ -1022,19 +1046,20 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx)
void phch_recv::scell_recv::init(phch_recv *parent, srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t prio, int cpu_affinity)
{
this->p = parent;
this->log_h = log_h;
this->p = parent;
this->log_h = log_h;
this->nof_rx_antennas = nof_rx_antennas;
// Create the ringbuffer for secondary cell reception
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
if (srslte_ringbuffer_init(&ring_buffer[i], 5*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) {
Error("SYNC: Creating ringbuffer for SCell\n");
if (srslte_ringbuffer_init(&ring_buffer[i], 10*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) {
Error("SCELL: Creating ringbuffer for SCell\n");
return;
}
}
// and a separate ue_sync instance
if (srslte_ue_sync_init_multi(&ue_sync, SRSLTE_MAX_PRB, false, scell_recv_callback, nof_rx_antennas, this)) {
Error("SYNC: Initiating ue_sync\n");
if (srslte_ue_sync_init_multi(&ue_sync, SRSLTE_MAX_PRB, false, scell_recv_callback, nof_rx_antennas, parent)) {
Error("SCELL: Initiating ue_sync\n");
return;
}
@ -1043,6 +1068,9 @@ void phch_recv::scell_recv::init(phch_recv *parent, srslte::log *log_h, uint32_t
}
measure_p.init(&ue_sync, sf_buffer, log_h, nof_rx_antennas);
sfn_p.init(&ue_sync, sf_buffer, log_h);
reset();
running = true;
if (cpu_affinity < 0) {
@ -1058,6 +1086,26 @@ void phch_recv::scell_recv::stop()
wait_thread_finish();
}
void phch_recv::scell_recv::reset()
{
tti = 0;
measure_p.reset();
sfn_p.reset();
scell_state = IDLE;
}
void phch_recv::scell_recv::set_cell(srslte_cell_t scell) {
printf("SCELL: set scell to select, id=%d, prb=%d\n", scell.id, scell.nof_prb);
memcpy(&cell, &scell, sizeof(srslte_cell_t));
current_sflen = SRSLTE_SF_LEN_PRB(cell.nof_prb);
srslte_ue_sync_set_cell(&ue_sync, scell);
measure_p.set_cell(scell);
sfn_p.set_cell(scell);
scell_state = SCELL_SELECT;
}
bool phch_recv::scell_recv::is_enabled()
{
return scell_state != IDLE;
@ -1065,13 +1113,37 @@ bool phch_recv::scell_recv::is_enabled()
int phch_recv::scell_recv::recv(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time)
{
if (is_enabled()) {
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
srslte_ringbuffer_read(&ring_buffer[i], data[i], sizeof(cf_t)*nsamples);
if (is_enabled())
{
uint32_t read_samples = nsamples;
if (read_samples > current_sflen) {
read_samples = current_sflen;
}
if (nsamples < 10) {
read_samples = 0;
}
int n = 0;
for (uint32_t i=0;i<nof_rx_antennas;i++) {
n = srslte_ringbuffer_read(&ring_buffer[i], data[i], sizeof(cf_t)*read_samples);
if (n < 0) {
Error("SCELL: Receiving from SCell buffer\n");
return -1;
}
if ((uint32_t) n < read_samples*sizeof(cf_t)) {
Error("SCELL: SCell received %d<%d samples from port %d\n", n/sizeof(cf_t), read_samples, i);
return -1;
}
// Pad with zeros if requested more samples in order to avoid consuming the buffer
for (int j=read_samples;j<nsamples;j++) {
data[i][j] = 0;
}
}
log_h->debug("SCELL: tti=%d, read %d/%d samples from buffer, buffer size=%d\n",
tti, read_samples,nsamples, srslte_ringbuffer_status(&ring_buffer[0]));
return nsamples;
} else {
Error("SYNC: SCell reception not enabled\n");
Error("SCELL: Reception not enabled\n");
return -1;
}
}
@ -1079,7 +1151,7 @@ int phch_recv::scell_recv::recv(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples,
void phch_recv::scell_recv::write(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time)
{
if (is_enabled()) {
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
for (uint32_t i = 0; i < nof_rx_antennas; i++) {
srslte_ringbuffer_write(&ring_buffer[i], data[i], sizeof(cf_t) * nsamples);
}
}
@ -1090,16 +1162,19 @@ void phch_recv::scell_recv::run_thread()
while(running) {
switch(scell_state) {
case IDLE:
usleep(1000);
break;
case SCELL_SELECT:
switch (sfn_p.run_subframe(&cell, &tti))
{
case sfn_sync::SFN_FOUND:
log_h->info("SFN Sync OK. Camping on cell PCI=%d...\n", cell.id);
log_h->info("SCELL: SFN Sync OK. Camping on cell PCI=%d...\n", cell.id);
sfn_p.reset();
scell_state = SCELL_MEASURE;
break;
case sfn_sync::TIMEOUT:
log_h->info("SFN sync timeout\n");
log_h->info("SCELL: SFN sync timeout\n");
break;
case sfn_sync::IDLE:
break;
@ -1107,11 +1182,15 @@ void phch_recv::scell_recv::run_thread()
p->radio_error();
break;
}
break;
case SCELL_MEASURE:
switch (measure_p.run_subframe(tti%10)) {
case measure::MEASURE_OK:
log_h->info("SYNC: Measured OK\n");
log_h->info("SCELL: Measured OK TTI=%5d, RSRP=%.1f dBm, RSRQ=%.1f dB, SNR=%3.1f dB, CFO=%.1f KHz, Buff=%d\n",
tti, measure_p.rsrp(), measure_p.rsrq(), measure_p.snr(), measure_p.cfo()/1000,
srslte_ringbuffer_status(&ring_buffer[0]));
measure_p.reset();
break;
case measure::IDLE:
break;
@ -1121,6 +1200,8 @@ void phch_recv::scell_recv::run_thread()
}
break;
}
// Increase TTI counter
tti = (tti+1) % 10240;
}
}

View File

@ -243,6 +243,11 @@ void phy::cell_search_next()
sf_recv.cell_search_next();
}
void phy::scell_enable(bool enable)
{
sf_recv.scell_enable(enable);
}
void phy::sync_reset() {
sf_recv.reset_sync();
}

View File

@ -213,6 +213,11 @@ void ue::pregenerate_signals(bool enable)
phy.enable_pregen_signals(enable);
}
void ue::test_scell()
{
phy.scell_enable(true);
};
void ue::stop()
{
if(started)