pdsch ue working with 1 and 2 antennas

master
Ismael Gomez 8 years ago
parent e850caaf96
commit 0a5a6245f1

@ -129,9 +129,10 @@ void sig_int_handler(int signo)
} }
} }
int srslte_rf_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *q) { int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_RXANT], uint32_t nsamples, srslte_timestamp_t *q) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples); DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return srslte_rf_recv(h, data, nsamples, 1);
return srslte_rf_recv(h, data[0], nsamples, 1);
} }
enum receiver_state { DECODE_MIB, DECODE_SIB, MEASURE} state; enum receiver_state { DECODE_MIB, DECODE_SIB, MEASURE} state;
@ -141,7 +142,7 @@ enum receiver_state { DECODE_MIB, DECODE_SIB, MEASURE} state;
int main(int argc, char **argv) { int main(int argc, char **argv) {
int ret; int ret;
cf_t *sf_buffer; cf_t *sf_buffer[SRSLTE_MAX_RXANT] = {NULL, NULL};
prog_args_t prog_args; prog_args_t prog_args;
srslte_cell_t cell; srslte_cell_t cell;
int64_t sf_cnt; int64_t sf_cnt;
@ -180,6 +181,8 @@ int main(int argc, char **argv) {
} }
srslte_rf_set_rx_gain(&rf, 50); srslte_rf_set_rx_gain(&rf, 50);
} }
sf_buffer[0] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100));
sigset_t sigset; sigset_t sigset;
sigemptyset(&sigset); sigemptyset(&sigset);
@ -198,7 +201,7 @@ int main(int argc, char **argv) {
uint32_t ntrial=0; uint32_t ntrial=0;
do { do {
ret = rf_search_and_decode_mib(&rf, &cell_detect_config, prog_args.force_N_id_2, &cell, &cfo); ret = rf_search_and_decode_mib(&rf, 1, &cell_detect_config, prog_args.force_N_id_2, &cell, &cfo);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error searching for cell\n"); fprintf(stderr, "Error searching for cell\n");
exit(-1); exit(-1);
@ -234,11 +237,11 @@ int main(int argc, char **argv) {
srslte_rf_stop_rx_stream(&rf); srslte_rf_stop_rx_stream(&rf);
srslte_rf_flush_buffer(&rf); srslte_rf_flush_buffer(&rf);
if (srslte_ue_sync_init(&ue_sync, cell, srslte_rf_recv_wrapper, (void*) &rf)) { if (srslte_ue_sync_init(&ue_sync, cell, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n"); fprintf(stderr, "Error initiating ue_sync\n");
return -1; return -1;
} }
if (srslte_ue_dl_init(&ue_dl, cell)) { if (srslte_ue_dl_init(&ue_dl, cell, 1)) {
fprintf(stderr, "Error initiating UE downlink processing module\n"); fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1; return -1;
} }
@ -280,7 +283,7 @@ int main(int argc, char **argv) {
/* Main loop */ /* Main loop */
while ((sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1) && !go_exit) { while ((sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1) && !go_exit) {
ret = srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer); ret = srslte_ue_sync_zerocopy(&ue_sync, sf_buffer);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n"); fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
} }
@ -292,7 +295,7 @@ int main(int argc, char **argv) {
case DECODE_MIB: case DECODE_MIB:
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) { if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
srslte_pbch_decode_reset(&ue_mib.pbch); srslte_pbch_decode_reset(&ue_mib.pbch);
n = srslte_ue_mib_decode(&ue_mib, sf_buffer, bch_payload, NULL, &sfn_offset); n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n"); fprintf(stderr, "Error decoding UE MIB\n");
return -1; return -1;
@ -329,11 +332,11 @@ int main(int argc, char **argv) {
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) { if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
/* Run FFT for all subframe data */ /* Run FFT for all subframe data */
srslte_ofdm_rx_sf(&fft, sf_buffer, sf_symbols); srslte_ofdm_rx_sf(&fft, sf_buffer[0], sf_symbols);
srslte_chest_dl_estimate(&chest, sf_symbols, ce, srslte_ue_sync_get_sfidx(&ue_sync)); srslte_chest_dl_estimate(&chest, sf_symbols, ce, srslte_ue_sync_get_sfidx(&ue_sync));
rssi = SRSLTE_VEC_EMA(srslte_vec_avg_power_cf(sf_buffer,SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb))),rssi,0.05); rssi = SRSLTE_VEC_EMA(srslte_vec_avg_power_cf(sf_buffer[0],SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb))),rssi,0.05);
rssi_utra = SRSLTE_VEC_EMA(srslte_chest_dl_get_rssi(&chest),rssi_utra,0.05); rssi_utra = SRSLTE_VEC_EMA(srslte_chest_dl_get_rssi(&chest),rssi_utra,0.05);
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&chest),rsrq,0.05); rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&chest),rsrq,0.05);
rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&chest),rsrp,0.05); rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&chest),rsrp,0.05);

@ -120,9 +120,13 @@ void parse_args(int argc, char **argv) {
} }
} }
int srslte_rf_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) { int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_RXANT], uint32_t nsamples, srslte_timestamp_t *t) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples); DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return srslte_rf_recv((srslte_rf_t*) h, data, nsamples, 1); void *ptr[SRSLTE_MAX_RXANT];
for (int i=0;i<SRSLTE_MAX_RXANT;i++) {
ptr[i] = data[i];
}
return srslte_rf_recv_with_time_multi((srslte_rf_t*) h, ptr, nsamples, 1, NULL, NULL);
} }
bool go_exit = false; bool go_exit = false;
@ -200,7 +204,7 @@ int main(int argc, char **argv) {
bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t)); bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t));
if (srslte_ue_cellsearch_init(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, (void*) &rf)) { if (srslte_ue_cellsearch_init(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating UE cell detect\n"); fprintf(stderr, "Error initiating UE cell detect\n");
exit(-1); exit(-1);
} }
@ -228,7 +232,7 @@ int main(int argc, char **argv) {
srslte_cell_t cell; srslte_cell_t cell;
cell.id = found_cells[i].cell_id; cell.id = found_cells[i].cell_id;
cell.cp = found_cells[i].cp; cell.cp = found_cells[i].cp;
int ret = rf_mib_decoder(&rf, &cell_detect_config, &cell, NULL); int ret = rf_mib_decoder(&rf, 1, &cell_detect_config, &cell, NULL);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error decoding MIB\n"); fprintf(stderr, "Error decoding MIB\n");
exit(-1); exit(-1);

@ -260,10 +260,13 @@ void sig_int_handler(int signo)
cf_t *sf_buffer[2] = {NULL, NULL}; cf_t *sf_buffer[2] = {NULL, NULL};
#ifndef DISABLE_RF #ifndef DISABLE_RF
int srslte_rf_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) { int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_RXANT], uint32_t nsamples, srslte_timestamp_t *t) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples); DEBUG(" ---- Receive %d samples ---- \n", nsamples);
void *d[2] = {data, sf_buffer[1]}; void *ptr[SRSLTE_MAX_RXANT];
return srslte_rf_recv_with_time_multi(h, d, nsamples, true, NULL, NULL); for (int i=0;i<SRSLTE_MAX_RXANT;i++) {
ptr[i] = data[i];
}
return srslte_rf_recv_with_time_multi(h, ptr, nsamples, true, NULL, NULL);
} }
double srslte_rf_set_rx_gain_th_wrapper_(void *h, double f) { double srslte_rf_set_rx_gain_th_wrapper_(void *h, double f) {
@ -351,7 +354,7 @@ int main(int argc, char **argv) {
uint32_t ntrial=0; uint32_t ntrial=0;
do { do {
ret = rf_search_and_decode_mib(&rf, &cell_detect_config, prog_args.force_N_id_2, &cell, &cfo); ret = rf_search_and_decode_mib(&rf, prog_args.rf_nof_rx_ant, &cell_detect_config, prog_args.force_N_id_2, &cell, &cfo);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error searching for cell\n"); fprintf(stderr, "Error searching for cell\n");
exit(-1); exit(-1);
@ -386,7 +389,7 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
printf("Stopping RF and flushing buffer...\r",0); INFO("Stopping RF and flushing buffer...\r",0);
} }
#endif #endif
@ -408,7 +411,7 @@ int main(int argc, char **argv) {
} else { } else {
#ifndef DISABLE_RF #ifndef DISABLE_RF
if (srslte_ue_sync_init(&ue_sync, cell, srslte_rf_recv_wrapper, (void*) &rf)) { if (srslte_ue_sync_init(&ue_sync, cell, srslte_rf_recv_wrapper, prog_args.rf_nof_rx_ant, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n"); fprintf(stderr, "Error initiating ue_sync\n");
exit(-1); exit(-1);
} }
@ -420,7 +423,7 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
if (srslte_ue_dl_init(&ue_dl, cell)) { // This is the User RNTI if (srslte_ue_dl_init(&ue_dl, cell, prog_args.rf_nof_rx_ant)) { // This is the User RNTI
fprintf(stderr, "Error initiating UE downlink processing module\n"); fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1); exit(-1);
} }
@ -471,11 +474,11 @@ int main(int argc, char **argv) {
srslte_pbch_decode_reset(&ue_mib.pbch); srslte_pbch_decode_reset(&ue_mib.pbch);
printf("\nEntering main loop...\n\n", 0); INFO("\nEntering main loop...\n\n", 0);
/* Main loop */ /* Main loop */
while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) { while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {
ret = srslte_ue_sync_zerocopy(&ue_sync, sf_buffer[0]); ret = srslte_ue_sync_zerocopy(&ue_sync, sf_buffer);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n"); fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
} }
@ -517,7 +520,7 @@ int main(int argc, char **argv) {
if (decode_pdsch) { if (decode_pdsch) {
INFO("Attempting DL decode SFN=%d\n", sfn); INFO("Attempting DL decode SFN=%d\n", sfn);
n = srslte_ue_dl_decode(&ue_dl, n = srslte_ue_dl_decode(&ue_dl,
sf_buffer[0], sf_buffer,
data, data,
sfn*10+srslte_ue_sync_get_sfidx(&ue_sync)); sfn*10+srslte_ue_sync_get_sfidx(&ue_sync));
@ -698,7 +701,7 @@ void *plot_thread_run(void *arg) {
uint32_t nof_symbols = ue_dl.pdsch_cfg.nbits.nof_re; uint32_t nof_symbols = ue_dl.pdsch_cfg.nbits.nof_re;
if (!prog_args.disable_plots_except_constellation) { if (!prog_args.disable_plots_except_constellation) {
for (i = 0; i < nof_re; i++) { for (i = 0; i < nof_re; i++) {
tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i])); tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[0][i]));
if (isinf(tmp_plot[i])) { if (isinf(tmp_plot[i])) {
tmp_plot[i] = -80; tmp_plot[i] = -80;
} }
@ -707,7 +710,7 @@ void *plot_thread_run(void *arg) {
bzero(tmp_plot2, sizeof(float)*sz); bzero(tmp_plot2, sizeof(float)*sz);
int g = (sz - 12*ue_dl.cell.nof_prb)/2; int g = (sz - 12*ue_dl.cell.nof_prb)/2;
for (i = 0; i < 12*ue_dl.cell.nof_prb; i++) { for (i = 0; i < 12*ue_dl.cell.nof_prb; i++) {
tmp_plot2[g+i] = 20 * log10(cabs(ue_dl.ce[0][i])); tmp_plot2[g+i] = 20 * log10(cabs(ue_dl.ce[0][0][i]));
if (isinf(tmp_plot2[g+i])) { if (isinf(tmp_plot2[g+i])) {
tmp_plot2[g+i] = -80; tmp_plot2[g+i] = -80;
} }

@ -98,13 +98,13 @@ void parse_args(int argc, char **argv) {
} }
} }
int srslte_rf_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) { int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_RXANT], uint32_t nsamples, srslte_timestamp_t *t) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples); DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return srslte_rf_recv(h, data, nsamples, 1); return srslte_rf_recv(h, data[2], nsamples, 1);
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
cf_t *buffer; cf_t *buffer[SRSLTE_MAX_RXANT] = {NULL, NULL};
int n; int n;
srslte_rf_t rf; srslte_rf_t rf;
srslte_filesink_t sink; srslte_filesink_t sink;
@ -124,6 +124,8 @@ int main(int argc, char **argv) {
} }
srslte_rf_set_master_clock_rate(&rf, 30.72e6); srslte_rf_set_master_clock_rate(&rf, 30.72e6);
buffer[0] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100));
sigset_t sigset; sigset_t sigset;
sigemptyset(&sigset); sigemptyset(&sigset);
sigaddset(&sigset, SIGINT); sigaddset(&sigset, SIGINT);
@ -156,7 +158,7 @@ int main(int argc, char **argv) {
cell.nof_prb = nof_prb; cell.nof_prb = nof_prb;
cell.nof_ports = 1; cell.nof_ports = 1;
if (srslte_ue_sync_init(&ue_sync, cell, srslte_rf_recv_wrapper, (void*) &rf)) { if (srslte_ue_sync_init(&ue_sync, cell, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n"); fprintf(stderr, "Error initiating ue_sync\n");
exit(-1); exit(-1);
} }
@ -167,7 +169,7 @@ int main(int argc, char **argv) {
while((subframe_count < nof_subframes || nof_subframes == -1) while((subframe_count < nof_subframes || nof_subframes == -1)
&& !stop_capture) && !stop_capture)
{ {
n = srslte_ue_sync_get_buffer(&ue_sync, &buffer); n = srslte_ue_sync_zerocopy(&ue_sync, buffer);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error receiving samples\n"); fprintf(stderr, "Error receiving samples\n");
exit(-1); exit(-1);
@ -179,7 +181,7 @@ int main(int argc, char **argv) {
} }
} else { } else {
printf("Writing to file %6d subframes...\r", subframe_count); printf("Writing to file %6d subframes...\r", subframe_count);
srslte_filesink_write(&sink, buffer, SRSLTE_SF_LEN_PRB(nof_prb)); srslte_filesink_write(&sink, buffer[0], SRSLTE_SF_LEN_PRB(nof_prb));
subframe_count++; subframe_count++;
} }
} }

@ -43,17 +43,20 @@ SRSLTE_API int rf_rssi_scan(srslte_rf_t *rf,
int nsamp); int nsamp);
SRSLTE_API int rf_mib_decoder(srslte_rf_t *rf, SRSLTE_API int rf_mib_decoder(srslte_rf_t *rf,
uint32_t nof_rx_antennas,
cell_search_cfg_t *config, cell_search_cfg_t *config,
srslte_cell_t *cell, srslte_cell_t *cell,
float *cfo); float *cfo);
SRSLTE_API int rf_cell_search(srslte_rf_t *rf, SRSLTE_API int rf_cell_search(srslte_rf_t *rf,
uint32_t nof_rx_antennas,
cell_search_cfg_t *config, cell_search_cfg_t *config,
int force_N_id_2, int force_N_id_2,
srslte_cell_t *cell, srslte_cell_t *cell,
float *cfo); float *cfo);
SRSLTE_API int rf_search_and_decode_mib(srslte_rf_t *rf, SRSLTE_API int rf_search_and_decode_mib(srslte_rf_t *rf,
uint32_t nof_rx_antennas,
cell_search_cfg_t *config, cell_search_cfg_t *config,
int force_N_id_2, int force_N_id_2,
srslte_cell_t *cell, srslte_cell_t *cell,

@ -69,6 +69,9 @@ typedef struct SRSLTE_API {
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_ue_sync_t ue_sync; srslte_ue_sync_t ue_sync;
cf_t *sf_buffer[SRSLTE_MAX_RXANT];
uint32_t nof_rx_antennas;
uint32_t max_frames; uint32_t max_frames;
uint32_t nof_valid_frames; // number of 5 ms frames to scan uint32_t nof_valid_frames; // number of 5 ms frames to scan
@ -80,7 +83,8 @@ typedef struct SRSLTE_API {
SRSLTE_API int srslte_ue_cellsearch_init(srslte_ue_cellsearch_t *q, SRSLTE_API int srslte_ue_cellsearch_init(srslte_ue_cellsearch_t *q,
uint32_t max_frames_total, uint32_t max_frames_total,
int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*), int (recv_callback)(void*, cf_t*[SRSLTE_MAX_RXANT], uint32_t,srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler); void *stream_handler);
SRSLTE_API void srslte_ue_cellsearch_free(srslte_ue_cellsearch_t *q); SRSLTE_API void srslte_ue_cellsearch_free(srslte_ue_cellsearch_t *q);

@ -88,8 +88,10 @@ typedef struct SRSLTE_API {
srslte_ra_dl_dci_t dl_dci; srslte_ra_dl_dci_t dl_dci;
srslte_cell_t cell; srslte_cell_t cell;
cf_t *sf_symbols; uint32_t nof_rx_antennas;
cf_t *ce[SRSLTE_MAX_PORTS];
cf_t *sf_symbols[SRSLTE_MAX_RXANT];
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT];
srslte_dci_format_t dci_format; srslte_dci_format_t dci_format;
uint64_t pkt_errors; uint64_t pkt_errors;
@ -110,12 +112,13 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q,
srslte_cell_t cell); srslte_cell_t cell,
uint32_t nof_rx_antennas);
SRSLTE_API void srslte_ue_dl_free(srslte_ue_dl_t *q); SRSLTE_API void srslte_ue_dl_free(srslte_ue_dl_t *q);
SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
cf_t *input, cf_t *input[SRSLTE_MAX_RXANT],
uint32_t sf_idx, uint32_t sf_idx,
uint32_t *cfi); uint32_t *cfi);
@ -154,12 +157,12 @@ SRSLTE_API void srslte_ue_dl_set_sample_offset(srslte_ue_dl_t * q,
float sample_offset); float sample_offset);
SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t * q, SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t * q,
cf_t *input, cf_t *input[SRSLTE_MAX_RXANT],
uint8_t *data, uint8_t *data,
uint32_t tti); uint32_t tti);
SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t * q, SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t * q,
cf_t *input, cf_t *input[SRSLTE_MAX_RXANT],
uint8_t *data, uint8_t *data,
uint32_t tti, uint32_t tti,
uint16_t rnti); uint16_t rnti);

@ -100,12 +100,15 @@ SRSLTE_API int srslte_ue_mib_decode(srslte_ue_mib_t * q,
typedef struct { typedef struct {
srslte_ue_mib_t ue_mib; srslte_ue_mib_t ue_mib;
srslte_ue_sync_t ue_sync; srslte_ue_sync_t ue_sync;
cf_t *sf_buffer[SRSLTE_MAX_RXANT];
uint32_t nof_rx_antennas;
} srslte_ue_mib_sync_t; } srslte_ue_mib_sync_t;
SRSLTE_API int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q, SRSLTE_API int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q,
uint32_t cell_id, uint32_t cell_id,
srslte_cp_t cp, srslte_cp_t cp,
int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t *), int (recv_callback)(void*, cf_t*[SRSLTE_MAX_RXANT], uint32_t, srslte_timestamp_t *),
uint32_t nof_rx_antennas,
void *stream_handler); void *stream_handler);
SRSLTE_API void srslte_ue_mib_sync_free(srslte_ue_mib_sync_t *q); SRSLTE_API void srslte_ue_mib_sync_free(srslte_ue_mib_sync_t *q);

@ -75,9 +75,11 @@ typedef struct SRSLTE_API {
uint32_t agc_period; uint32_t agc_period;
void *stream; void *stream;
int (*recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*); int (*recv_callback)(void*, cf_t*[SRSLTE_MAX_RXANT], uint32_t, srslte_timestamp_t*);
srslte_timestamp_t last_timestamp; srslte_timestamp_t last_timestamp;
uint32_t nof_rx_antennas;
srslte_filesource_t file_source; srslte_filesource_t file_source;
bool file_mode; bool file_mode;
float file_cfo; float file_cfo;
@ -85,8 +87,6 @@ typedef struct SRSLTE_API {
srslte_ue_sync_state_t state; srslte_ue_sync_state_t state;
cf_t *input_buffer;
uint32_t frame_len; uint32_t frame_len;
uint32_t fft_size; uint32_t fft_size;
uint32_t nof_recv_sf; // Number of subframes received each call to srslte_ue_sync_get_buffer uint32_t nof_recv_sf; // Number of subframes received each call to srslte_ue_sync_get_buffer
@ -124,7 +124,8 @@ typedef struct SRSLTE_API {
SRSLTE_API int srslte_ue_sync_init(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_init(srslte_ue_sync_t *q,
srslte_cell_t cell, srslte_cell_t cell,
int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*), int (recv_callback)(void*, cf_t*[SRSLTE_MAX_RXANT], uint32_t, srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler); void *stream_handler);
SRSLTE_API int srslte_ue_sync_init_file(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_init_file(srslte_ue_sync_t *q,
@ -141,15 +142,12 @@ SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t *q,
SRSLTE_API uint32_t srslte_ue_sync_sf_len(srslte_ue_sync_t *q); SRSLTE_API uint32_t srslte_ue_sync_sf_len(srslte_ue_sync_t *q);
SRSLTE_API int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q,
cf_t **sf_symbols);
SRSLTE_API void srslte_ue_sync_set_agc_period(srslte_ue_sync_t *q, SRSLTE_API void srslte_ue_sync_set_agc_period(srslte_ue_sync_t *q,
uint32_t period); uint32_t period);
/* CAUTION: input_buffer MUST have space for 2 subframes */ /* CAUTION: input_buffer MUST have space for 2 subframes */
SRSLTE_API int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q,
cf_t *input_buffer); cf_t *input_buffer[SRSLTE_MAX_RXANT]);
SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q,
float cfo); float cfo);

@ -358,7 +358,6 @@ int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q, cf_t *input[SRSLTE_MAX_
{ {
for (uint32_t rxant=0;rxant<nof_rx_antennas;rxant++) { for (uint32_t rxant=0;rxant<nof_rx_antennas;rxant++) {
for (uint32_t port_id=0;port_id<q->cell.nof_ports;port_id++) { for (uint32_t port_id=0;port_id<q->cell.nof_ports;port_id++) {
printf("rxant=%d, port=%d, input=0x%x, ce=0x%x\n", rxant, port_id, input[rxant], ce[port_id][rxant]);
if (srslte_chest_dl_estimate_port(q, input[rxant], ce[port_id][rxant], sf_idx, port_id)) { if (srslte_chest_dl_estimate_port(q, input[rxant], ce[port_id][rxant], sf_idx, port_id)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }

@ -137,7 +137,7 @@ int base_init() {
exit(-1); exit(-1);
} }
if (srslte_ue_dl_init(&ue_dl, cell)) { if (srslte_ue_dl_init(&ue_dl, cell, 1)) {
fprintf(stderr, "Error initializing UE DL\n"); fprintf(stderr, "Error initializing UE DL\n");
return -1; return -1;
} }
@ -177,7 +177,7 @@ int main(int argc, char **argv) {
srslte_filesource_read(&fsrc, input_buffer, flen); srslte_filesource_read(&fsrc, input_buffer, flen);
INFO("Reading %d samples sub-frame %d\n", flen, sf_idx); INFO("Reading %d samples sub-frame %d\n", flen, sf_idx);
ret = srslte_ue_dl_decode(&ue_dl, input_buffer, data, sf_idx); ret = srslte_ue_dl_decode(&ue_dl, &input_buffer, data, sf_idx);
if(ret > 0) { if(ret > 0) {
printf("PDSCH Decoded OK!\n"); printf("PDSCH Decoded OK!\n");
} else if (ret == 0) { } else if (ret == 0) {

@ -82,11 +82,13 @@ free_and_exit:
return ret; return ret;
} }
cf_t data2[1920*160]; int srslte_rf_recv_wrapper_cs(void *h, cf_t *data[SRSLTE_MAX_RXANT], uint32_t nsamples, srslte_timestamp_t *t) {
int srslte_rf_recv_wrapper_cs(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples); DEBUG(" ---- Receive %d samples ---- \n", nsamples);
void *d[2] = {data, data2}; void *ptr[SRSLTE_MAX_RXANT];
return srslte_rf_recv_with_time_multi(h, d, nsamples, 1, NULL, NULL); for (int i=0;i<SRSLTE_MAX_RXANT;i++) {
ptr[i] = data[i];
}
return srslte_rf_recv_with_time_multi(h, ptr, nsamples, 1, NULL, NULL);
} }
double srslte_rf_set_rx_gain_th_wrapper(void *h, double f) { double srslte_rf_set_rx_gain_th_wrapper(void *h, double f) {
@ -96,12 +98,12 @@ double srslte_rf_set_rx_gain_th_wrapper(void *h, double f) {
/** This function is simply a wrapper to the ue_cell_search module for rf devices /** This function is simply a wrapper to the ue_cell_search module for rf devices
* Return 1 if the MIB is decoded, 0 if not or -1 on error. * Return 1 if the MIB is decoded, 0 if not or -1 on error.
*/ */
int rf_mib_decoder(srslte_rf_t *rf, cell_search_cfg_t *config, srslte_cell_t *cell, float *cfo) { int rf_mib_decoder(srslte_rf_t *rf, uint32_t nof_rx_antennas,cell_search_cfg_t *config, srslte_cell_t *cell, float *cfo) {
int ret = SRSLTE_ERROR; int ret = SRSLTE_ERROR;
srslte_ue_mib_sync_t ue_mib; srslte_ue_mib_sync_t ue_mib;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
if (srslte_ue_mib_sync_init(&ue_mib, cell->id, cell->cp, srslte_rf_recv_wrapper_cs, (void*) rf)) { if (srslte_ue_mib_sync_init(&ue_mib, cell->id, cell->cp, srslte_rf_recv_wrapper_cs, nof_rx_antennas, (void*) rf)) {
fprintf(stderr, "Error initiating srslte_ue_mib_sync\n"); fprintf(stderr, "Error initiating srslte_ue_mib_sync\n");
goto clean_exit; goto clean_exit;
} }
@ -152,8 +154,9 @@ clean_exit:
/** This function is simply a wrapper to the ue_cell_search module for rf devices /** This function is simply a wrapper to the ue_cell_search module for rf devices
*/ */
int rf_cell_search(srslte_rf_t *rf, cell_search_cfg_t *config, int rf_cell_search(srslte_rf_t *rf, uint32_t nof_rx_antennas,
int force_N_id_2, srslte_cell_t *cell, float *cfo) cell_search_cfg_t *config,
int force_N_id_2, srslte_cell_t *cell, float *cfo)
{ {
int ret = SRSLTE_ERROR; int ret = SRSLTE_ERROR;
srslte_ue_cellsearch_t cs; srslte_ue_cellsearch_t cs;
@ -161,7 +164,7 @@ int rf_cell_search(srslte_rf_t *rf, cell_search_cfg_t *config,
bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t)); bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t));
if (srslte_ue_cellsearch_init(&cs, config->max_frames_pss, srslte_rf_recv_wrapper_cs, (void*) rf)) { if (srslte_ue_cellsearch_init(&cs, config->max_frames_pss, srslte_rf_recv_wrapper_cs, nof_rx_antennas, (void*) rf)) {
fprintf(stderr, "Error initiating UE cell detect\n"); fprintf(stderr, "Error initiating UE cell detect\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -235,15 +238,15 @@ int rf_cell_search(srslte_rf_t *rf, cell_search_cfg_t *config,
* 0 if no cell was found or MIB could not be decoded, * 0 if no cell was found or MIB could not be decoded,
* -1 on error * -1 on error
*/ */
int rf_search_and_decode_mib(srslte_rf_t *rf, cell_search_cfg_t *config, int force_N_id_2, srslte_cell_t *cell, float *cfo) int rf_search_and_decode_mib(srslte_rf_t *rf, uint32_t nof_rx_antennas, cell_search_cfg_t *config, int force_N_id_2, srslte_cell_t *cell, float *cfo)
{ {
int ret = SRSLTE_ERROR; int ret = SRSLTE_ERROR;
printf("Searching for cell...\n"); printf("Searching for cell...\n");
ret = rf_cell_search(rf, config, force_N_id_2, cell, cfo); ret = rf_cell_search(rf, nof_rx_antennas, config, force_N_id_2, cell, cfo);
if (ret > 0) { if (ret > 0) {
printf("Decoding PBCH for cell %d (N_id_2=%d)\n", cell->id, cell->id%3); printf("Decoding PBCH for cell %d (N_id_2=%d)\n", cell->id, cell->id%3);
ret = rf_mib_decoder(rf, config, cell, cfo); ret = rf_mib_decoder(rf, nof_rx_antennas, config, cell, cfo);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Could not decode PBCH from CELL ID %d\n", cell->id); fprintf(stderr, "Could not decode PBCH from CELL ID %d\n", cell->id);
return SRSLTE_ERROR; return SRSLTE_ERROR;

@ -36,7 +36,9 @@
#include "srslte/utils/vector.h" #include "srslte/utils/vector.h"
int srslte_ue_cellsearch_init(srslte_ue_cellsearch_t * q, uint32_t max_frames, int srslte_ue_cellsearch_init(srslte_ue_cellsearch_t * q, uint32_t max_frames,
int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*), void *stream_handler) int (recv_callback)(void*, cf_t*[SRSLTE_MAX_RXANT], uint32_t,srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -50,11 +52,16 @@ int srslte_ue_cellsearch_init(srslte_ue_cellsearch_t * q, uint32_t max_frames,
cell.id = SRSLTE_CELL_ID_UNKNOWN; cell.id = SRSLTE_CELL_ID_UNKNOWN;
cell.nof_prb = SRSLTE_CS_NOF_PRB; cell.nof_prb = SRSLTE_CS_NOF_PRB;
if (srslte_ue_sync_init(&q->ue_sync, cell, recv_callback, stream_handler)) { if (srslte_ue_sync_init(&q->ue_sync, cell, recv_callback, nof_rx_antennas, stream_handler)) {
fprintf(stderr, "Error initiating ue_sync\n"); fprintf(stderr, "Error initiating ue_sync\n");
goto clean_exit; goto clean_exit;
} }
for (int i=0;i<nof_rx_antennas;i++) {
q->sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100));
}
q->nof_rx_antennas = nof_rx_antennas;
q->candidates = calloc(sizeof(srslte_ue_cellsearch_result_t), max_frames); q->candidates = calloc(sizeof(srslte_ue_cellsearch_result_t), max_frames);
if (!q->candidates) { if (!q->candidates) {
perror("malloc"); perror("malloc");
@ -86,6 +93,11 @@ clean_exit:
void srslte_ue_cellsearch_free(srslte_ue_cellsearch_t * q) void srslte_ue_cellsearch_free(srslte_ue_cellsearch_t * q)
{ {
for (int i=0;i<q->nof_rx_antennas;i++) {
if (q->sf_buffer[i]) {
free(q->sf_buffer[i]);
}
}
if (q->candidates) { if (q->candidates) {
free(q->candidates); free(q->candidates);
} }
@ -203,7 +215,6 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q,
srslte_ue_cellsearch_result_t *found_cell) srslte_ue_cellsearch_result_t *found_cell)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
cf_t *sf_buffer = NULL;
uint32_t nof_detected_frames = 0; uint32_t nof_detected_frames = 0;
uint32_t nof_scanned_frames = 0; uint32_t nof_scanned_frames = 0;
@ -215,7 +226,7 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q,
srslte_ue_sync_reset(&q->ue_sync); srslte_ue_sync_reset(&q->ue_sync);
do { do {
ret = srslte_ue_sync_get_buffer(&q->ue_sync, &sf_buffer); ret = srslte_ue_sync_zerocopy(&q->ue_sync, q->sf_buffer);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n"); fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
break; break;

@ -46,11 +46,13 @@ const uint32_t nof_common_formats = 2;
int srslte_ue_dl_init(srslte_ue_dl_t *q, int srslte_ue_dl_init(srslte_ue_dl_t *q,
srslte_cell_t cell) srslte_cell_t cell,
uint32_t nof_rx_antennas)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL &&
nof_rx_antennas <= SRSLTE_MAX_RXANT &&
srslte_cell_isvalid(&cell)) srslte_cell_isvalid(&cell))
{ {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
@ -62,6 +64,7 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
q->pkts_total = 0; q->pkts_total = 0;
q->pending_ul_dci_rnti = 0; q->pending_ul_dci_rnti = 0;
q->sample_offset = 0; q->sample_offset = 0;
q->nof_rx_antennas = nof_rx_antennas;
if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) { if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n"); fprintf(stderr, "Error initiating FFT\n");
@ -89,7 +92,7 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
goto clean_exit; goto clean_exit;
} }
if (srslte_pdsch_init(&q->pdsch, q->cell)) { if (srslte_pdsch_init_multi(&q->pdsch, q->cell, nof_rx_antennas)) {
fprintf(stderr, "Error creating PDSCH object\n"); fprintf(stderr, "Error creating PDSCH object\n");
goto clean_exit; goto clean_exit;
} }
@ -103,17 +106,19 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
} }
srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz); srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz);
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); for (int j=0;j<nof_rx_antennas;j++) {
if (!q->sf_symbols) { q->sf_symbols[j] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
perror("malloc"); if (!q->sf_symbols[j]) {
goto clean_exit;
}
for (uint32_t i=0;i<q->cell.nof_ports;i++) {
q->ce[i] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
if (!q->ce[i]) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
for (uint32_t i=0;i<q->cell.nof_ports;i++) {
q->ce[i][j] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
if (!q->ce[i][j]) {
perror("malloc");
goto clean_exit;
}
}
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
@ -140,12 +145,14 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
srslte_pdsch_free(&q->pdsch); srslte_pdsch_free(&q->pdsch);
srslte_cfo_free(&q->sfo_correct); srslte_cfo_free(&q->sfo_correct);
srslte_softbuffer_rx_free(&q->softbuffer); srslte_softbuffer_rx_free(&q->softbuffer);
if (q->sf_symbols) { for (int j=0;j<q->nof_rx_antennas;j++) {
free(q->sf_symbols); if (q->sf_symbols[j]) {
} free(q->sf_symbols[j]);
for (uint32_t i=0;i<q->cell.nof_ports;i++) { }
if (q->ce[i]) { for (uint32_t i=0;i<q->cell.nof_ports;i++) {
free(q->ce[i]); if (q->ce[i][j]) {
free(q->ce[i][j]);
}
} }
} }
bzero(q, sizeof(srslte_ue_dl_t)); bzero(q, sizeof(srslte_ue_dl_t));
@ -186,23 +193,25 @@ void srslte_ue_dl_set_sample_offset(srslte_ue_dl_t * q, float sample_offset) {
* - PDCCH decoding: Find DCI for RNTI given by previous call to srslte_ue_dl_set_rnti() * - PDCCH decoding: Find DCI for RNTI given by previous call to srslte_ue_dl_set_rnti()
* - PDSCH decoding: Decode TB scrambling with RNTI given by srslte_ue_dl_set_rnti() * - PDSCH decoding: Decode TB scrambling with RNTI given by srslte_ue_dl_set_rnti()
*/ */
int srslte_ue_dl_decode(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t tti) { int srslte_ue_dl_decode(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_RXANT], uint8_t *data, uint32_t tti) {
return srslte_ue_dl_decode_rnti(q, input, data, tti, q->current_rnti); return srslte_ue_dl_decode_rnti(q, input, data, tti, q->current_rnti);
} }
int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, cf_t *input, uint32_t sf_idx, uint32_t *cfi) { int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_RXANT], uint32_t sf_idx, uint32_t *cfi) {
if (input && q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) { if (input && q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) {
/* Run FFT for all subframe data */ /* Run FFT for all subframe data */
srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols); for (int j=0;j<q->nof_rx_antennas;j++) {
srslte_ofdm_rx_sf(&q->fft, input[j], q->sf_symbols[j]);
/* Correct SFO multiplying by complex exponential in the time domain */
if (q->sample_offset) { /* Correct SFO multiplying by complex exponential in the time domain */
for (int i=0;i<2*SRSLTE_CP_NSYMB(q->cell.cp);i++) { if (q->sample_offset) {
srslte_cfo_correct(&q->sfo_correct, for (int i=0;i<2*SRSLTE_CP_NSYMB(q->cell.cp);i++) {
&q->sf_symbols[i*q->cell.nof_prb*SRSLTE_NRE], srslte_cfo_correct(&q->sfo_correct,
&q->sf_symbols[i*q->cell.nof_prb*SRSLTE_NRE], &q->sf_symbols[j][i*q->cell.nof_prb*SRSLTE_NRE],
q->sample_offset / q->fft.symbol_sz); &q->sf_symbols[j][i*q->cell.nof_prb*SRSLTE_NRE],
q->sample_offset / q->fft.symbol_sz);
}
} }
} }
return srslte_ue_dl_decode_estimate(q, sf_idx, cfi); return srslte_ue_dl_decode_estimate(q, sf_idx, cfi);
@ -216,10 +225,14 @@ int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t *c
if (q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) { if (q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) {
/* Get channel estimates for each port */ /* Get channel estimates for each port */
srslte_chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, sf_idx); srslte_chest_dl_estimate_multi(&q->chest, q->sf_symbols, q->ce, sf_idx, q->nof_rx_antennas);
/* First decode PCFICH and obtain CFI */ /* First decode PCFICH and obtain CFI */
if (srslte_pcfich_decode(&q->pcfich, q->sf_symbols, q->ce, cf_t *ce0[SRSLTE_MAX_PORTS];
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ce0[i] = q->ce[i][0];
}
if (srslte_pcfich_decode(&q->pcfich, q->sf_symbols[0], ce0,
srslte_chest_dl_get_noise_estimate(&q->chest), srslte_chest_dl_get_noise_estimate(&q->chest),
sf_idx, cfi, &cfi_corr)<0) { sf_idx, cfi, &cfi_corr)<0) {
fprintf(stderr, "Error decoding PCFICH\n"); fprintf(stderr, "Error decoding PCFICH\n");
@ -245,7 +258,7 @@ int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint3
return srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rvidx); return srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rvidx);
} }
int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t tti, uint16_t rnti) int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_RXANT], uint8_t *data, uint32_t tti, uint16_t rnti)
{ {
srslte_dci_msg_t dci_msg; srslte_dci_msg_t dci_msg;
srslte_ra_dl_dci_t dci_unpacked; srslte_ra_dl_dci_t dci_unpacked;
@ -259,7 +272,11 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint
return ret; return ret;
} }
if (srslte_pdcch_extract_llr(&q->pdcch, q->sf_symbols, q->ce, srslte_chest_dl_get_noise_estimate(&q->chest), sf_idx, cfi)) { cf_t *ce0[SRSLTE_MAX_PORTS];
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ce0[i] = q->ce[i][0];
}
if (srslte_pdcch_extract_llr(&q->pdcch, q->sf_symbols[0], ce0, srslte_chest_dl_get_noise_estimate(&q->chest), sf_idx, cfi)) {
fprintf(stderr, "Error extracting LLRs\n"); fprintf(stderr, "Error extracting LLRs\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -299,7 +316,7 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint
float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest); float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest);
if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) { if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) {
ret = srslte_pdsch_decode(&q->pdsch, &q->pdsch_cfg, &q->softbuffer, ret = srslte_pdsch_decode_multi(&q->pdsch, &q->pdsch_cfg, &q->softbuffer,
q->sf_symbols, q->ce, q->sf_symbols, q->ce,
noise_estimate, noise_estimate,
rnti, data); rnti, data);
@ -502,7 +519,14 @@ bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_pr
INFO("Decoding PHICH sf_idx=%d, n_prb_lowest=%d, n_dmrs=%d, n_group=%d, n_seq=%d, Ngroups=%d, Nsf=%d\n", INFO("Decoding PHICH sf_idx=%d, n_prb_lowest=%d, n_dmrs=%d, n_group=%d, n_seq=%d, Ngroups=%d, Nsf=%d\n",
sf_idx, n_prb_lowest, n_dmrs, ngroup, nseq, sf_idx, n_prb_lowest, n_dmrs, ngroup, nseq,
srslte_phich_ngroups(&q->phich), srslte_phich_nsf(&q->phich)); srslte_phich_ngroups(&q->phich), srslte_phich_nsf(&q->phich));
if (!srslte_phich_decode(&q->phich, q->sf_symbols, q->ce, 0, ngroup, nseq, sf_idx, &ack_bit, &distance)) {
cf_t *ce0[SRSLTE_MAX_PORTS];
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ce0[i] = q->ce[i][0];
}
if (!srslte_phich_decode(&q->phich, q->sf_symbols[0], ce0, 0, ngroup, nseq, sf_idx, &ack_bit, &distance)) {
INFO("Decoded PHICH %d with distance %f\n", ack_bit, distance); INFO("Decoded PHICH %d with distance %f\n", ack_bit, distance);
} else { } else {
fprintf(stderr, "Error decoding PHICH\n"); fprintf(stderr, "Error decoding PHICH\n");

@ -164,10 +164,11 @@ int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input,
int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q, int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q,
uint32_t cell_id, uint32_t cell_id,
srslte_cp_t cp, srslte_cp_t cp,
int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*), int (recv_callback)(void*, cf_t*[SRSLTE_MAX_RXANT], uint32_t, srslte_timestamp_t*),
void *stream_handler) uint32_t nof_rx_antennas,
void *stream_handler)
{ {
srslte_cell_t cell; srslte_cell_t cell;
// If the ports are set to 0, ue_mib goes through 1, 2 and 4 ports to blindly detect nof_ports // If the ports are set to 0, ue_mib goes through 1, 2 and 4 ports to blindly detect nof_ports
@ -176,11 +177,16 @@ int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q,
cell.cp = cp; cell.cp = cp;
cell.nof_prb = SRSLTE_UE_MIB_NOF_PRB; cell.nof_prb = SRSLTE_UE_MIB_NOF_PRB;
for (int i=0;i<nof_rx_antennas;i++) {
q->sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
q->nof_rx_antennas = nof_rx_antennas;
if (srslte_ue_mib_init(&q->ue_mib, cell)) { if (srslte_ue_mib_init(&q->ue_mib, cell)) {
fprintf(stderr, "Error initiating ue_mib\n"); fprintf(stderr, "Error initiating ue_mib\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (srslte_ue_sync_init(&q->ue_sync, cell, recv_callback, stream_handler)) { if (srslte_ue_sync_init(&q->ue_sync, cell, recv_callback, nof_rx_antennas, stream_handler)) {
fprintf(stderr, "Error initiating ue_sync\n"); fprintf(stderr, "Error initiating ue_sync\n");
srslte_ue_mib_free(&q->ue_mib); srslte_ue_mib_free(&q->ue_mib);
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -190,6 +196,11 @@ int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q,
} }
void srslte_ue_mib_sync_free(srslte_ue_mib_sync_t *q) { void srslte_ue_mib_sync_free(srslte_ue_mib_sync_t *q) {
for (int i=0;i<q->nof_rx_antennas;i++) {
if (q->sf_buffer[i]) {
free(q->sf_buffer[i]);
}
}
srslte_ue_mib_free(&q->ue_mib); srslte_ue_mib_free(&q->ue_mib);
srslte_ue_sync_free(&q->ue_sync); srslte_ue_sync_free(&q->ue_sync);
} }
@ -207,7 +218,6 @@ int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q,
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
cf_t *sf_buffer = NULL;
uint32_t nof_frames = 0; uint32_t nof_frames = 0;
int mib_ret = SRSLTE_UE_MIB_NOTFOUND; int mib_ret = SRSLTE_UE_MIB_NOTFOUND;
@ -216,13 +226,13 @@ int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q,
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
do { do {
mib_ret = SRSLTE_UE_MIB_NOTFOUND; mib_ret = SRSLTE_UE_MIB_NOTFOUND;
ret = srslte_ue_sync_get_buffer(&q->ue_sync, &sf_buffer); ret = srslte_ue_sync_zerocopy(&q->ue_sync, q->sf_buffer);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n"); fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
break; break;
} else if (srslte_ue_sync_get_sfidx(&q->ue_sync) == 0) { } else if (srslte_ue_sync_get_sfidx(&q->ue_sync) == 0) {
if (ret == 1) { if (ret == 1) {
mib_ret = srslte_ue_mib_decode(&q->ue_mib, sf_buffer, bch_payload, nof_tx_ports, sfn_offset); mib_ret = srslte_ue_mib_decode(&q->ue_mib, q->sf_buffer[0], bch_payload, nof_tx_ports, sfn_offset);
} else { } else {
DEBUG("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt); DEBUG("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt);
srslte_ue_mib_reset(&q->ue_mib); srslte_ue_mib_reset(&q->ue_mib);

@ -39,7 +39,6 @@
#define MAX_TIME_OFFSET 128 #define MAX_TIME_OFFSET 128
cf_t dummy[MAX_TIME_OFFSET];
#define TRACK_MAX_LOST 4 #define TRACK_MAX_LOST 4
#define TRACK_FRAME_SIZE 32 #define TRACK_FRAME_SIZE 32
@ -47,7 +46,11 @@ cf_t dummy[MAX_TIME_OFFSET];
#define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0 #define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0
#define DEFAULT_SFO_EMA_COEFF 0.1 #define DEFAULT_SFO_EMA_COEFF 0.1
cf_t dummy_offset_buffer[1024*1024]; cf_t dummy_buffer0[15*2048/2];
cf_t dummy_buffer1[15*2048/2];
// FIXME: this will break for 4 antennas!!
cf_t *dummy_offset_buffer[SRSLTE_MAX_RXANT] = {dummy_buffer0, dummy_buffer1};
int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_name, int offset_time, float offset_freq) { int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_name, int offset_time, float offset_freq) {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -74,12 +77,6 @@ int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_n
goto clean_exit; goto clean_exit;
} }
q->input_buffer = srslte_vec_malloc(2 * q->sf_len * sizeof(cf_t));
if (!q->input_buffer) {
perror("malloc");
goto clean_exit;
}
INFO("Offseting input file by %d samples and %.1f kHz\n", offset_time, offset_freq/1000); INFO("Offseting input file by %d samples and %.1f kHz\n", offset_time, offset_freq/1000);
srslte_filesource_read(&q->file_source, dummy_offset_buffer, offset_time); srslte_filesource_read(&q->file_source, dummy_offset_buffer, offset_time);
@ -111,14 +108,16 @@ int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, double (set_gain_callback)(voi
int srslte_ue_sync_init(srslte_ue_sync_t *q, int srslte_ue_sync_init(srslte_ue_sync_t *q,
srslte_cell_t cell, srslte_cell_t cell,
int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*), int (recv_callback)(void*, cf_t*[SRSLTE_MAX_RXANT], uint32_t,srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler) void *stream_handler)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL &&
stream_handler != NULL && stream_handler != NULL &&
srslte_nofprb_isvalid(cell.nof_prb) && srslte_nofprb_isvalid(cell.nof_prb) &&
nof_rx_antennas <= SRSLTE_MAX_RXANT &&
recv_callback != NULL) recv_callback != NULL)
{ {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
@ -127,6 +126,7 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q,
q->stream = stream_handler; q->stream = stream_handler;
q->recv_callback = recv_callback; q->recv_callback = recv_callback;
q->nof_rx_antennas = nof_rx_antennas;
q->cell = cell; q->cell = cell;
q->fft_size = srslte_symbol_sz(q->cell.nof_prb); q->fft_size = srslte_symbol_sz(q->cell.nof_prb);
q->sf_len = SRSLTE_SF_LEN(q->fft_size); q->sf_len = SRSLTE_SF_LEN(q->fft_size);
@ -209,13 +209,6 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q,
} }
/* FIXME: Go for zerocopy only and eliminate this allocation */
q->input_buffer = srslte_vec_malloc(2*q->frame_len * sizeof(cf_t));
if (!q->input_buffer) {
perror("malloc");
goto clean_exit;
}
srslte_ue_sync_reset(q); srslte_ue_sync_reset(q);
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
@ -233,9 +226,6 @@ uint32_t srslte_ue_sync_sf_len(srslte_ue_sync_t *q) {
} }
void srslte_ue_sync_free(srslte_ue_sync_t *q) { void srslte_ue_sync_free(srslte_ue_sync_t *q) {
if (q->input_buffer) {
free(q->input_buffer);
}
if (q->do_agc) { if (q->do_agc) {
srslte_agc_free(&q->agc); srslte_agc_free(&q->agc);
} }
@ -309,7 +299,7 @@ void srslte_ue_sync_set_agc_period(srslte_ue_sync_t *q, uint32_t period) {
q->agc_period = period; q->agc_period = period;
} }
static int find_peak_ok(srslte_ue_sync_t *q, cf_t *input_buffer) { static int find_peak_ok(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE_MAX_RXANT]) {
if (srslte_sync_sss_detected(&q->sfind)) { if (srslte_sync_sss_detected(&q->sfind)) {
@ -408,7 +398,7 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) {
discard the offseted samples to align next frame */ discard the offseted samples to align next frame */
if (q->next_rf_sample_offset > 0 && q->next_rf_sample_offset < MAX_TIME_OFFSET) { if (q->next_rf_sample_offset > 0 && q->next_rf_sample_offset < MAX_TIME_OFFSET) {
DEBUG("Positive time offset %d samples.\n", q->next_rf_sample_offset); DEBUG("Positive time offset %d samples.\n", q->next_rf_sample_offset);
if (q->recv_callback(q->stream, dummy, (uint32_t) q->next_rf_sample_offset, &q->last_timestamp) < 0) { if (q->recv_callback(q->stream, dummy_offset_buffer, (uint32_t) q->next_rf_sample_offset, &q->last_timestamp) < 0) {
fprintf(stderr, "Error receiving from USRP\n"); fprintf(stderr, "Error receiving from USRP\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -443,7 +433,7 @@ static int track_peak_no(srslte_ue_sync_t *q) {
} }
static int receive_samples(srslte_ue_sync_t *q, cf_t *input_buffer) { static int receive_samples(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE_MAX_RXANT]) {
/* A negative time offset means there are samples in our buffer for the next subframe, /* A negative time offset means there are samples in our buffer for the next subframe,
because we are sampling too fast. because we are sampling too fast.
@ -453,7 +443,11 @@ static int receive_samples(srslte_ue_sync_t *q, cf_t *input_buffer) {
} }
/* Get N subframes from the USRP getting more samples and keeping the previous samples, if any */ /* Get N subframes from the USRP getting more samples and keeping the previous samples, if any */
if (q->recv_callback(q->stream, &input_buffer[q->next_rf_sample_offset], q->frame_len - q->next_rf_sample_offset, &q->last_timestamp) < 0) { cf_t *ptr[SRSLTE_MAX_RXANT];
for (int i=0;i<SRSLTE_MAX_RXANT;i++) {
ptr[i] = &input_buffer[i][q->next_rf_sample_offset];
}
if (q->recv_callback(q->stream, ptr, q->frame_len - q->next_rf_sample_offset, &q->last_timestamp) < 0) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -465,17 +459,8 @@ static int receive_samples(srslte_ue_sync_t *q, cf_t *input_buffer) {
bool first_track = true; bool first_track = true;
int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
int ret = srslte_ue_sync_zerocopy(q, q->input_buffer);
if (sf_symbols) {
*sf_symbols = q->input_buffer;
}
return ret;
}
/* Returns 1 if the subframe is synchronized in time, 0 otherwise */ /* Returns 1 if the subframe is synchronized in time, 0 otherwise */
int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) { int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE_MAX_RXANT]) {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
uint32_t track_idx; uint32_t track_idx;
@ -484,7 +469,7 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
{ {
if (q->file_mode) { if (q->file_mode) {
int n = srslte_filesource_read(&q->file_source, input_buffer, q->sf_len); int n = srslte_filesource_read(&q->file_source, input_buffer[0], q->sf_len);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error reading input file\n"); fprintf(stderr, "Error reading input file\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -492,7 +477,7 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
if (n == 0) { if (n == 0) {
srslte_filesource_seek(&q->file_source, 0); srslte_filesource_seek(&q->file_source, 0);
q->sf_idx = 9; q->sf_idx = 9;
int n = srslte_filesource_read(&q->file_source, input_buffer, q->sf_len); int n = srslte_filesource_read(&q->file_source, input_buffer[0], q->sf_len);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error reading input file\n"); fprintf(stderr, "Error reading input file\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -500,8 +485,8 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
} }
if (q->correct_cfo) { if (q->correct_cfo) {
srslte_cfo_correct(&q->file_cfo_correct, srslte_cfo_correct(&q->file_cfo_correct,
input_buffer, input_buffer[0],
input_buffer, input_buffer[0],
q->file_cfo / 15000 / q->fft_size); q->file_cfo / 15000 / q->fft_size);
} }
@ -519,7 +504,7 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
switch (q->state) { switch (q->state) {
case SF_FIND: case SF_FIND:
switch(srslte_sync_find(&q->sfind, input_buffer, 0, &q->peak_idx)) { switch(srslte_sync_find(&q->sfind, input_buffer[0], 0, &q->peak_idx)) {
case SRSLTE_SYNC_ERROR: case SRSLTE_SYNC_ERROR:
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
fprintf(stderr, "Error finding correlation peak (%d)\n", ret); fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
@ -539,7 +524,7 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
break; break;
} }
if (q->do_agc) { if (q->do_agc) {
srslte_agc_process(&q->agc, input_buffer, q->sf_len); srslte_agc_process(&q->agc, input_buffer[0], q->sf_len);
} }
break; break;
@ -557,7 +542,7 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
if (q->do_agc && (q->agc_period == 0 || if (q->do_agc && (q->agc_period == 0 ||
(q->agc_period && (q->frame_total_cnt%q->agc_period) == 0))) (q->agc_period && (q->frame_total_cnt%q->agc_period) == 0)))
{ {
srslte_agc_process(&q->agc, input_buffer, q->sf_len); srslte_agc_process(&q->agc, input_buffer[0], q->sf_len);
} }
#ifdef MEASURE_EXEC_TIME #ifdef MEASURE_EXEC_TIME
@ -570,7 +555,7 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
/* Track PSS/SSS around the expected PSS position /* Track PSS/SSS around the expected PSS position
* In tracking phase, the subframe carrying the PSS is always the last one of the frame * In tracking phase, the subframe carrying the PSS is always the last one of the frame
*/ */
switch(srslte_sync_find(&q->strack, input_buffer, switch(srslte_sync_find(&q->strack, input_buffer[0],
q->frame_len - q->sf_len/2 - q->fft_size - q->strack.max_offset/2, q->frame_len - q->sf_len/2 - q->fft_size - q->strack.max_offset/2,
&track_idx)) &track_idx))
{ {
@ -607,10 +592,12 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
q->frame_total_cnt++; q->frame_total_cnt++;
} }
if (q->correct_cfo) { if (q->correct_cfo) {
srslte_cfo_correct(&q->sfind.cfocorr, for (int i=0;i<q->nof_rx_antennas;i++) {
input_buffer, srslte_cfo_correct(&q->sfind.cfocorr,
input_buffer, input_buffer[i],
input_buffer[i],
-srslte_sync_get_cfo(&q->strack) / q->fft_size); -srslte_sync_get_cfo(&q->strack) / q->fft_size);
}
} }
break; break;
} }

Loading…
Cancel
Save