From 6fe535f8a48a49f10b37dfeb16d17423ca38e0a6 Mon Sep 17 00:00:00 2001 From: ismagom Date: Thu, 5 Mar 2015 17:36:15 +0000 Subject: [PATCH] Improved synch. Fixed some bugs. Added ue_ul --- cuhd/include/liblte/cuhd/cuhd.h | 58 ++--- cuhd/lib/cuhd_imp.cpp | 96 +++----- lte/examples/cell_measurement.c | 8 +- lte/examples/pdsch_ue.c | 12 +- lte/examples/prach_ue.c | 57 ++--- .../liblte/phy/ch_estimation/chest_dl.h | 3 +- .../include/liblte/phy/common/phy_common.h | 5 +- lte/phy/include/liblte/phy/phch/dci.h | 7 +- lte/phy/include/liblte/phy/phch/harq.h | 2 - lte/phy/include/liblte/phy/phch/pusch.h | 19 +- lte/phy/include/liblte/phy/phch/ra.h | 11 +- lte/phy/include/liblte/phy/phy.h | 1 + lte/phy/include/liblte/phy/ue/ue_dl.h | 39 +++- lte/phy/include/liblte/phy/ue/ue_ul.h | 114 ++++++++++ lte/phy/lib/ch_estimation/src/chest_dl.c | 24 +- lte/phy/lib/ch_estimation/src/refsignal_ul.c | 6 +- lte/phy/lib/phch/src/dci.c | 31 +++ lte/phy/lib/phch/src/harq.c | 4 +- lte/phy/lib/phch/src/pbch.c | 15 +- lte/phy/lib/phch/src/pusch.c | 18 +- lte/phy/lib/phch/test/pusch_test.c | 11 +- lte/phy/lib/resampling/src/interp.c | 9 +- lte/phy/lib/sync/src/sss.c | 10 +- lte/phy/lib/sync/test/pss_usrp.c | 33 +-- lte/phy/lib/ue/src/ue_dl.c | 182 ++++++++------- lte/phy/lib/ue/src/ue_mib.c | 6 +- lte/phy/lib/ue/src/ue_sync.c | 65 +++--- lte/phy/lib/ue/src/ue_ul.c | 210 ++++++++++++++++++ matlab/tests/pusch_test.m | 6 +- 29 files changed, 711 insertions(+), 351 deletions(-) create mode 100644 lte/phy/include/liblte/phy/ue/ue_ul.h create mode 100644 lte/phy/lib/ue/src/ue_ul.c diff --git a/cuhd/include/liblte/cuhd/cuhd.h b/cuhd/include/liblte/cuhd/cuhd.h index a78288424..52652a831 100644 --- a/cuhd/include/liblte/cuhd/cuhd.h +++ b/cuhd/include/liblte/cuhd/cuhd.h @@ -62,29 +62,12 @@ LIBLTE_API double cuhd_set_rx_freq(void *h, double freq); LIBLTE_API double cuhd_set_rx_freq_offset(void *h, - double freq, - double off); - -LIBLTE_API void cuhd_get_time(void *h, - time_t *secs, - double *frac_secs); - -LIBLTE_API double cuhd_set_tx_srate(void *h, - double freq); - -LIBLTE_API void cuhd_set_tx_antenna(void *h, - char *name); - -LIBLTE_API double cuhd_set_tx_gain(void *h, - double gain); - -LIBLTE_API double cuhd_set_tx_freq(void *h, - double freq); - -LIBLTE_API double cuhd_set_tx_freq_offset(void *h, - double freq, + double freq, double off); +LIBLTE_API double cuhd_set_rx_freq_offset(void *h, + double freq, + double off); LIBLTE_API int cuhd_recv(void *h, void *data, @@ -94,22 +77,28 @@ LIBLTE_API int cuhd_recv(void *h, LIBLTE_API int cuhd_recv_with_time(void *h, void *data, uint32_t nsamples, + bool blocking, time_t *secs, double *frac_secs); -LIBLTE_API int cuhd_recv_timed(void *h, - void *data, - uint32_t nsamples, - time_t secs, - double frac_secs); +LIBLTE_API double cuhd_set_tx_srate(void *h, + double freq); + +LIBLTE_API double cuhd_set_tx_gain(void *h, + double gain); + +LIBLTE_API double cuhd_set_tx_freq(void *h, + double freq); + +LIBLTE_API double cuhd_set_tx_freq_offset(void *h, + double freq, + double offset); + +LIBLTE_API int cuhd_send(void *h, + void *data, + uint32_t nsamples, + bool blocking); -LIBLTE_API int cuhd_recv_timed2(void *h, - void *data, - uint32_t nsamples, - time_t secs, - double frac_secs, - bool is_start_of_burst, - bool is_end_of_burst); LIBLTE_API int cuhd_send(void *h, void *data, @@ -131,7 +120,6 @@ LIBLTE_API int cuhd_send_timed2(void *h, bool is_start_of_burst, bool is_end_of_burst); - #ifdef __cplusplus } -#endif +#endif \ No newline at end of file diff --git a/cuhd/lib/cuhd_imp.cpp b/cuhd/lib/cuhd_imp.cpp index 719100fa1..cb5eba946 100644 --- a/cuhd/lib/cuhd_imp.cpp +++ b/cuhd/lib/cuhd_imp.cpp @@ -121,8 +121,9 @@ int cuhd_open(char *args, void **h) { cuhd_handler *handler = new cuhd_handler(); std::string _args = std::string(args); - handler->usrp = uhd::usrp::multi_usrp::make(_args + ", master_clock_rate=30720000"); -// "num_recv_frames=1,num_send_frames=1,recv_frame_size=15360,send_frame_size=15360"); + handler->usrp = uhd::usrp::multi_usrp::make(_args + ", master_clock_rate=30720000" + ", num_recv_frames=512"); + +// handler->usrp = uhd::usrp::multi_usrp::make(_args + ", master_clock_rate=50000000" + ", num_recv_frames=512"); handler->usrp->set_clock_source("internal"); #ifdef HIDE_MESSAGES @@ -133,7 +134,6 @@ int cuhd_open(char *args, void **h) otw = "sc16"; cpu = "fc32"; uhd::stream_args_t stream_args(cpu, otw); - stream_args.args["spp"] = "120"; // Set the property handler->rx_stream = handler->usrp->get_rx_stream(stream_args); handler->tx_stream = handler->usrp->get_tx_stream(stream_args); @@ -154,15 +154,7 @@ double cuhd_set_rx_srate(void *h, double freq) { cuhd_handler *handler = static_cast < cuhd_handler * >(h); handler->usrp->set_rx_rate(freq); - - double ret = handler->usrp->get_rx_rate(); - /* - if ((int) ret != (int) freq) { - handler->usrp->set_master_clock_rate(freq); - handler->usrp->set_rx_rate(freq); - } - */ - return freq; + return freq; } double cuhd_set_rx_gain(void *h, double gain) @@ -179,9 +171,9 @@ double cuhd_set_rx_freq(void *h, double freq) return freq; } -double cuhd_set_rx_freq_offset(void *h, double freq, double off) { +double cuhd_set_rx_freq_offset(void *h, double freq, double off) { cuhd_handler* handler = static_cast(h); - handler->usrp->set_rx_freq(uhd::tune_request_t(freq,off)); + handler->usrp->set_rx_freq(uhd::tune_request_t(freq, off)); return handler->usrp->get_rx_freq(); } @@ -217,59 +209,41 @@ int cuhd_recv(void *h, void *data, uint32_t nsamples, bool blocking) int cuhd_recv_with_time(void *h, void *data, uint32_t nsamples, + bool blocking, time_t *secs, double *frac_secs) { - cuhd_handler* handler = static_cast(h); + cuhd_handler *handler = static_cast < cuhd_handler * >(h); uhd::rx_metadata_t md; - int p = handler->rx_stream->recv(data, nsamples, md, 0.0); + uint32_t nof_packets = 0; + int ret = -1; + if (blocking) { + int n = 0, p; + complex_t *data_c = (complex_t *) data; + do { + p = handler->rx_stream->recv(&data_c[n], nsamples - n, md); + if (p == -1) { + return -1; + } + n += p; +#ifdef METADATA_VERBOSE + if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) { + std::cout << "\nError code: " << md.to_pp_string() << "\n\n"; + } +#endif + nof_packets++; + } while (n < nsamples && + md.error_code == uhd::rx_metadata_t::ERROR_CODE_NONE && + nof_packets < 10); + ret = nsamples; + } else { + ret = handler->rx_stream->recv(data, nsamples, md, 0.0); + } if (secs && frac_secs) { *secs = md.time_spec.get_full_secs(); *frac_secs = md.time_spec.get_frac_secs(); } - return p; -} - -int cuhd_recv_timed(void *h, - void *data, - uint32_t nsamples, - time_t secs, - double frac_secs) -{ - return cuhd_recv_timed2(h, data, nsamples, secs, frac_secs, true, true); -} - - -int cuhd_recv_timed2(void *h, - void *data, - uint32_t nsamples, - time_t secs, - double frac_secs, - bool is_start_of_burst, - bool is_end_of_burst) -{ - cuhd_handler* handler = static_cast(h); - uhd::rx_metadata_t md; - md.start_of_burst = is_start_of_burst; - md.end_of_burst = is_end_of_burst; - md.has_time_spec = true; - md.time_spec = uhd::time_spec_t(secs, frac_secs); - - return handler->rx_stream->recv(data, nsamples, md); -} - -void cuhd_get_time(void *h, time_t *secs, double *frac_secs) -{ - cuhd_handler* handler = static_cast(h); - uhd::time_spec_t now = handler->usrp->get_time_now(); - *secs = now.get_full_secs(); - *frac_secs = now.get_frac_secs(); -} - -void cuhd_set_tx_antenna(void *h, char *name) -{ - cuhd_handler *handler = static_cast < cuhd_handler * >(h); - handler->usrp->set_tx_antenna(name, 0); + return ret; } double cuhd_set_tx_gain(void *h, double gain) { @@ -292,7 +266,8 @@ double cuhd_set_tx_freq(void *h, double freq) return handler->usrp->get_tx_freq(); } -double cuhd_set_tx_freq_offset(void *h, double freq, double off) { + +double cuhd_set_tx_freq_offset(void *h, double freq, double off) { cuhd_handler* handler = static_cast(h); handler->usrp->set_tx_freq(uhd::tune_request_t(freq, off)); return handler->usrp->get_tx_freq(); @@ -319,6 +294,7 @@ int cuhd_send(void *h, void *data, uint32_t nsamples, bool blocking) } } + int cuhd_send_timed(void *h, void *data, int nsamples, diff --git a/lte/examples/cell_measurement.c b/lte/examples/cell_measurement.c index 6e1ae4ee9..8b795c9f7 100644 --- a/lte/examples/cell_measurement.c +++ b/lte/examples/cell_measurement.c @@ -125,8 +125,6 @@ int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples, timestamp_t *q) { return cuhd_recv(h, data, nsamples, 1); } -extern float mean_exec_time; - enum receiver_state { DECODE_MIB, DECODE_SIB, MEASURE} state; #define MAX_SINFO 10 @@ -261,15 +259,15 @@ int main(int argc, char **argv) { case DECODE_SIB: /* We are looking for SI Blocks, search only in appropiate places */ if ((ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) { - n = ue_dl_decode_sib(&ue_dl, sf_buffer, data, ue_sync_get_sfidx(&ue_sync), SIRNTI, + n = ue_dl_decode_rnti_rv(&ue_dl, sf_buffer, data, ue_sync_get_sfidx(&ue_sync), SIRNTI, ((int) ceilf((float)3*(((sfn)/2)%4)/2))%4); if (n < 0) { fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); return -1; } else if (n == 0) { - printf("CFO: %+6.4f KHz, SFO: %+6.4f Khz, ExecTime: %5.1f us, NOI: %.2f, PDCCH-Det: %.3f\r", + printf("CFO: %+6.4f KHz, SFO: %+6.4f Khz, NOI: %.2f, PDCCH-Det: %.3f\r", ue_sync_get_cfo(&ue_sync)/1000, ue_sync_get_sfo(&ue_sync)/1000, - mean_exec_time, sch_average_noi(&ue_dl.pdsch.dl_sch), + sch_average_noi(&ue_dl.pdsch.dl_sch), (float) ue_dl.nof_pdcch_detected/nof_trials); nof_trials++; } else { diff --git a/lte/examples/pdsch_ue.c b/lte/examples/pdsch_ue.c index 2d372354a..04bf5f142 100644 --- a/lte/examples/pdsch_ue.c +++ b/lte/examples/pdsch_ue.c @@ -83,6 +83,7 @@ typedef struct { uint32_t file_nof_prb; char *uhd_args; float uhd_freq; + float uhd_freq_offset; float uhd_gain; int net_port; char *net_address; @@ -98,6 +99,7 @@ void args_default(prog_args_t *args) { args->file_nof_prb = 6; args->uhd_args = ""; args->uhd_freq = -1.0; + args->uhd_freq = 8000000.0; args->uhd_gain = 60.0; args->net_port = -1; args->net_address = "127.0.0.1"; @@ -110,6 +112,7 @@ void usage(prog_args_t *args, char *prog) { #ifndef DISABLE_UHD printf("\t-a UHD args [Default %s]\n", args->uhd_args); printf("\t-g UHD RX gain [Default %.2f dB]\n", args->uhd_gain); + printf("\t-o UHD RX freq offset [Default %.1f MHz]\n", args->uhd_freq_offset/1000000); #else printf("\t UHD is disabled. CUHD library not available\n"); #endif @@ -133,7 +136,7 @@ void usage(prog_args_t *args, char *prog) { void parse_args(prog_args_t *args, int argc, char **argv) { int opt; args_default(args); - while ((opt = getopt(argc, argv, "aglipdnvrfuUsS")) != -1) { + while ((opt = getopt(argc, argv, "aoglipdnvrfuUsS")) != -1) { switch (opt) { case 'i': args->input_file_name = argv[optind]; @@ -147,6 +150,9 @@ void parse_args(prog_args_t *args, int argc, char **argv) { case 'g': args->uhd_gain = atof(argv[optind]); break; + case 'o': + args->uhd_freq_offset = atof(argv[optind]); + break; case 'f': args->uhd_freq = atof(argv[optind]); break; @@ -261,7 +267,7 @@ int main(int argc, char **argv) { cuhd_set_rx_gain(uhd, prog_args.uhd_gain); /* set receiver frequency */ - cuhd_set_rx_freq(uhd, (double) prog_args.uhd_freq); + cuhd_set_rx_freq_offset(uhd, (double) prog_args.uhd_freq, prog_args.uhd_freq_offset); cuhd_rx_wait_lo_locked(uhd); printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.uhd_freq/1000000); @@ -394,7 +400,7 @@ int main(int argc, char **argv) { if (prog_args.rnti != SIRNTI) { n = ue_dl_decode(&ue_dl, sf_buffer, data_packed, ue_sync_get_sfidx(&ue_sync)); } else { - n = ue_dl_decode_sib(&ue_dl, sf_buffer, data_packed, ue_sync_get_sfidx(&ue_sync), SIRNTI, + n = ue_dl_decode_rnti_rv(&ue_dl, sf_buffer, data_packed, ue_sync_get_sfidx(&ue_sync), SIRNTI, ((int) ceilf((float)3*(((sfn)/2)%4)/2))%4); } if (n < 0) { diff --git a/lte/examples/prach_ue.c b/lte/examples/prach_ue.c index 155ba2079..935eba234 100644 --- a/lte/examples/prach_ue.c +++ b/lte/examples/prach_ue.c @@ -151,7 +151,7 @@ void sig_int_handler(int signo) int cuhd_recv_wrapper_timed(void *h, void *data, uint32_t nsamples, timestamp_t *uhd_time) { DEBUG(" ---- Receive %d samples ---- \n", nsamples); - return cuhd_recv_with_time(h, data, nsamples, &uhd_time->full_secs, &uhd_time->frac_secs); + return cuhd_recv_with_time(h, data, nsamples, true, &uhd_time->full_secs, &uhd_time->frac_secs); } extern float mean_exec_time; @@ -314,7 +314,7 @@ int main(int argc, char **argv) { uint32_t rar_window_start = 0, rar_trials = 0, rar_window_stop = 0; timestamp_t uhd_time; timestamp_t next_tx_time; - const uint8_t conn_request_msg[] = {0x20, 0x06, 0x1F, 0x5C, 0x2C, 0x04, 0xB2, 0xAC, 0xF6}; + const uint8_t conn_request_msg[] = {0x20, 0x06, 0x1F, 0x5C, 0x2C, 0x04, 0xB2, 0xAC, 0xF6, 0x00, 0x00, 0x00}; uint8_t data[100]; parse_args(&prog_args, argc, argv); @@ -327,7 +327,7 @@ int main(int argc, char **argv) { /* Set receiver gain */ cuhd_set_rx_gain(uhd, prog_args.uhd_gain); - cuhd_set_tx_gain(uhd, prog_args.uhd_gain); + cuhd_set_tx_gain(uhd, prog_args.uhd_gain*2); //cuhd_set_tx_antenna(uhd, "TX/RX"); @@ -336,7 +336,6 @@ int main(int argc, char **argv) { cuhd_rx_wait_lo_locked(uhd); printf("Tunning RX receiver to %.3f MHz\n", (double ) prog_args.uhd_rx_freq/1000000); - cuhd_set_tx_freq(uhd, prog_args.uhd_tx_freq); cuhd_set_tx_freq_offset(uhd, prog_args.uhd_tx_freq, prog_args.uhd_tx_freq_offset); printf("Tunning TX receiver to %.3f MHz\n", (double ) prog_args.uhd_tx_freq/1000000); @@ -383,24 +382,15 @@ int main(int argc, char **argv) { generate_prach_sequences(); refsignal_ul_t drms; - refsignal_drms_pusch_cfg_t pusch_cfg; - bzero(&pusch_cfg, sizeof(refsignal_drms_pusch_cfg_t)); - pusch_cfg.nof_prb = 3; - pusch_cfg.beta_pusch = 1.0; if (refsignal_ul_init(&drms, cell)) { fprintf(stderr, "Error initiating refsignal_ul\n"); exit(-1); } - cf_t *drms_signal = vec_malloc(2*RE_X_RB*pusch_cfg.nof_prb*sizeof(cf_t)); + cf_t *drms_signal = vec_malloc(2*RE_X_RB*cell.nof_prb*sizeof(cf_t)); if (!drms_signal) { perror("malloc"); exit(-1); } - for (uint32_t i=0;i<2;i++) { - if (refsignal_dmrs_pusch_gen(&drms, &pusch_cfg, 2*4+i, &drms_signal[i*RE_X_RB*pusch_cfg.nof_prb])) { - fprintf(stderr, "Error generating PUSCH DRMS signals\n"); - } - } if (pusch_init(&pusch, cell)) { fprintf(stderr, "Error initiating PUSCH\n"); @@ -438,7 +428,7 @@ int main(int argc, char **argv) { exit(-1); } - if (ue_dl_init(&ue_dl, cell)) { // This is the User RNTI + if (ue_dl_init(&ue_dl, cell)) { fprintf(stderr, "Error initiating UE downlink processing module\n"); exit(-1); } @@ -503,7 +493,7 @@ int main(int argc, char **argv) { if ((sfn == rar_window_start && ue_sync_get_sfidx(&ue_sync) > 3) || sfn > rar_window_start) { gettimeofday(&tdata[1], NULL); printf("Looking for RAR in sfn: %d sf_idx: %d\n", sfn, ue_sync_get_sfidx(&ue_sync)); - n = ue_dl_decode_rnti(&ue_dl, sf_buffer, data_rx, ra_rnti, ue_sync_get_sfidx(&ue_sync)); + n = ue_dl_decode_rnti(&ue_dl, sf_buffer, data_rx, ue_sync_get_sfidx(&ue_sync), ra_rnti); if (n < 0) { fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); } else if (n > 0) { @@ -522,7 +512,8 @@ int main(int argc, char **argv) { ra_ul_alloc(&prb_alloc, &ra_pusch, 0, cell.nof_prb); - if (harq_setup_ul(&pusch_harq, ra_pusch.mcs, 0, (ue_sync_get_sfidx(&ue_sync)+6)%10, &prb_alloc)) { + uint32_t ul_sf_idx = (ue_sync_get_sfidx(&ue_sync)+6)%10; + if (harq_setup_ul(&pusch_harq, ra_pusch.mcs, 0, ul_sf_idx, &prb_alloc)) { fprintf(stderr, "Error configuring HARQ process\n"); exit(-1);; } @@ -532,12 +523,28 @@ int main(int argc, char **argv) { fprintf(stderr, "Error encoding TB\n"); exit(-1); } + + refsignal_drms_pusch_cfg_t pusch_cfg; + bzero(&pusch_cfg, sizeof(refsignal_drms_pusch_cfg_t)); + pusch_cfg.nof_prb = prb_alloc.L_prb; + pusch_cfg.beta_pusch = 1.0; + for (uint32_t i=0;i<2;i++) { - refsignal_drms_pusch_put(&drms, &pusch_cfg, &drms_signal[i*RE_X_RB*pusch_cfg.nof_prb], i, prb_alloc.n_prb[i], sf_symbols); + if (refsignal_dmrs_pusch_gen(&drms, &pusch_cfg, 2*ul_sf_idx+i, drms_signal)) { + fprintf(stderr, "Error generating PUSCH DRMS signals\n"); + exit(-1); + } + refsignal_drms_pusch_put(&drms, &pusch_cfg, drms_signal, i, + prb_alloc.n_prb[i], sf_symbols); } lte_ifft_run_sf(&fft, sf_symbols, ul_signal); + cfo_correct(&ue_sync.sfind.cfocorr, + ul_signal, ul_signal, + sync_get_cfo(&ue_sync.strack) / lte_symbol_sz(cell.nof_prb)); + + gettimeofday(&tdata[2], NULL); get_time_interval(tdata); printf("time exec UL: %d\n",tdata[0].tv_usec); @@ -551,16 +558,16 @@ int main(int argc, char **argv) { ue_sync_get_last_timestamp(&ue_sync, &uhd_time); - float time_adv_sec = ((float) rar_msg.timing_adv_cmd - 31 - 25) * 16 /(15000*2048); - + //float time_adv_sec = ((float) rar_msg.timing_adv_cmd - 31 - 25) * 16 /(15000*2048); + float time_adv_sec = ((float) rar_msg.timing_adv_cmd - 31) * 16 /(15000*2048); vec_sc_prod_cfc(ul_signal, 2, ul_signal, SF_LEN_PRB(cell.nof_prb)); - vec_fprint_c(stdout, sf_symbols, 300); - timestamp_copy(&next_tx_time, &uhd_time); timestamp_add(&next_tx_time, 0, 0.006 + time_adv_sec); // send after 6 sub-frames (6 ms) - printf("Send %d samples PUSCH sfn: %d. Last frame time = %.6f, send PUSCH time = %.6f TA: %f\n", - SF_LEN_PRB(cell.nof_prb), sfn, timestamp_real(&uhd_time), timestamp_real(&next_tx_time), time_adv_sec); + printf("Send %d samples PUSCH sfn: %d. Last frame time = %.6f" + "send PUSCH time = %.6f TA: %.1f us\n", + SF_LEN_PRB(cell.nof_prb), sfn, timestamp_real(&uhd_time), + timestamp_real(&next_tx_time), time_adv_sec*1000000); cuhd_send_timed(uhd, ul_signal, SF_LEN_PRB(cell.nof_prb), next_tx_time.full_secs, next_tx_time.frac_secs); @@ -569,7 +576,7 @@ int main(int argc, char **argv) { if (sfn >= rar_window_stop) { state = SEND_PRACH; rar_trials++; - if (rar_trials >= 10) { + if (rar_trials >= 4) { go_exit = 1; } } diff --git a/lte/phy/include/liblte/phy/ch_estimation/chest_dl.h b/lte/phy/include/liblte/phy/ch_estimation/chest_dl.h index 145facc41..10a2928a0 100644 --- a/lte/phy/include/liblte/phy/ch_estimation/chest_dl.h +++ b/lte/phy/include/liblte/phy/ch_estimation/chest_dl.h @@ -66,7 +66,8 @@ typedef struct { cf_t *tmp_noise; cf_t *tmp_freqavg; cf_t *tmp_timeavg[CHEST_MAX_FILTER_TIME_LEN]; - + cf_t *tmp_timeavg_mult; + interp_linvec_t interp_linvec; interp_lin_t interp_lin; diff --git a/lte/phy/include/liblte/phy/common/phy_common.h b/lte/phy/include/liblte/phy/common/phy_common.h index 4c34eece1..66292693c 100644 --- a/lte/phy/include/liblte/phy/common/phy_common.h +++ b/lte/phy/include/liblte/phy/common/phy_common.h @@ -119,12 +119,13 @@ typedef enum {CPNORM, CPEXT} lte_cp_t; typedef _Complex float cf_t; -typedef enum LIBLTE_API { PHICH_NORM, PHICH_EXT} phich_length_t; -typedef enum LIBLTE_API { R_1_6, R_1_2, R_1, R_2} phich_resources_t; +typedef enum LIBLTE_API { PHICH_NORM = 0, PHICH_EXT} phich_length_t; +typedef enum LIBLTE_API { R_1_6 = 0, R_1_2, R_1, R_2} phich_resources_t; typedef struct LIBLTE_API { uint32_t nof_prb; uint32_t nof_ports; + uint32_t bw_idx; uint32_t id; lte_cp_t cp; phich_length_t phich_length; diff --git a/lte/phy/include/liblte/phy/phch/dci.h b/lte/phy/include/liblte/phy/phch/dci.h index b1dd4d74b..7ec83fe59 100644 --- a/lte/phy/include/liblte/phy/phch/dci.h +++ b/lte/phy/include/liblte/phy/phch/dci.h @@ -80,14 +80,11 @@ LIBLTE_API int dci_msg_to_ra_dl(dci_msg_t *msg, uint32_t cfi, ra_pdsch_t *ra_dl); -/* TODO LIBLTE_API int dci_msg_to_ra_ul(dci_msg_t *msg, - uint16_t msg_rnti, - uint16_t c_rnti, lte_cell_t cell, - uint32_t cfi, + uint32_t n_rb_ho, ra_pusch_t *ra_ul); -*/ + LIBLTE_API dci_format_t dci_format_from_string(char *str); LIBLTE_API char* dci_format_string(dci_format_t format); diff --git a/lte/phy/include/liblte/phy/phch/harq.h b/lte/phy/include/liblte/phy/phch/harq.h index a960ba9ef..c817ab991 100644 --- a/lte/phy/include/liblte/phy/phch/harq.h +++ b/lte/phy/include/liblte/phy/phch/harq.h @@ -51,8 +51,6 @@ typedef struct LIBLTE_API { ra_ul_alloc_t ul_alloc; lte_cell_t cell; - ra_ul_hopping_t ul_hopping; - uint32_t nof_re; // Number of RE per subframe uint32_t nof_bits; // Number of bits per subframe uint32_t nof_symb; // Number of symbols per subframe diff --git a/lte/phy/include/liblte/phy/phch/pusch.h b/lte/phy/include/liblte/phy/phch/pusch.h index f3cf0e4cd..a96da1c21 100644 --- a/lte/phy/include/liblte/phy/phch/pusch.h +++ b/lte/phy/include/liblte/phy/phch/pusch.h @@ -45,9 +45,23 @@ typedef _Complex float cf_t; + +typedef struct { + enum { + hop_mode_inter_sf = 1, + hop_mode_intra_sf = 0 + } hop_mode; + uint32_t current_tx_nb; + uint32_t hopping_offset; + uint32_t n_sb; +} pusch_hopping_cfg_t; + + /* PUSCH object */ typedef struct LIBLTE_API { lte_cell_t cell; + + pusch_hopping_cfg_t hopping_cfg; uint32_t max_re; bool rnti_is_set; @@ -77,13 +91,14 @@ typedef struct LIBLTE_API { }pusch_t; - - LIBLTE_API int pusch_init(pusch_t *q, lte_cell_t cell); LIBLTE_API void pusch_free(pusch_t *q); +LIBLTE_API void pusch_set_hopping_cfg(pusch_t *q, + pusch_hopping_cfg_t *cfg); + LIBLTE_API int pusch_set_rnti(pusch_t *q, uint16_t rnti); diff --git a/lte/phy/include/liblte/phy/phch/ra.h b/lte/phy/include/liblte/phy/phch/ra.h index 6f6aacd8d..1c9d724b5 100644 --- a/lte/phy/include/liblte/phy/phch/ra.h +++ b/lte/phy/include/liblte/phy/phch/ra.h @@ -84,20 +84,11 @@ typedef struct LIBLTE_API { typedef struct LIBLTE_API { uint32_t n_prb[2]; + uint32_t n_prb_tilde[2]; uint32_t L_prb; uint32_t freq_hopping; } ra_ul_alloc_t; -typedef struct { - enum { - hop_mode_inter_sf = 1, - hop_mode_intra_sf = 0 - } hop_mode; - uint32_t current_tx_nb; - uint32_t hopping_offset; - uint32_t n_sb; -} ra_ul_hopping_t; - typedef struct LIBLTE_API { uint16_t rnti; ra_type_t alloc_type; diff --git a/lte/phy/include/liblte/phy/phy.h b/lte/phy/include/liblte/phy/phy.h index 8a1a3cbdb..5d7c8d099 100644 --- a/lte/phy/include/liblte/phy/phy.h +++ b/lte/phy/include/liblte/phy/phy.h @@ -108,6 +108,7 @@ #include "liblte/phy/ue/ue_mib.h" #include "liblte/phy/ue/ue_cell_search.h" #include "liblte/phy/ue/ue_dl.h" +#include "liblte/phy/ue/ue_ul.h" #include "liblte/phy/scrambling/scrambling.h" diff --git a/lte/phy/include/liblte/phy/ue/ue_dl.h b/lte/phy/include/liblte/phy/ue/ue_dl.h index 360758265..9563dcb94 100644 --- a/lte/phy/include/liblte/phy/ue/ue_dl.h +++ b/lte/phy/include/liblte/phy/ue/ue_dl.h @@ -41,7 +41,6 @@ #include "liblte/phy/common/phy_common.h" #include "liblte/phy/phch/dci.h" -#include "liblte/phy/phch/pbch.h" #include "liblte/phy/phch/pcfich.h" #include "liblte/phy/phch/pdcch.h" #include "liblte/phy/phch/pdsch.h" @@ -57,7 +56,6 @@ #define NOF_HARQ_PROCESSES 8 typedef struct LIBLTE_API { - pbch_t pbch; pcfich_t pcfich; pdcch_t pdcch; pdsch_t pdsch; @@ -66,6 +64,8 @@ typedef struct LIBLTE_API { lte_fft_t fft; chest_dl_t chest; + ra_pdsch_t ra_dl; + lte_cell_t cell; cf_t *sf_symbols; @@ -84,6 +84,25 @@ LIBLTE_API int ue_dl_init(ue_dl_t *q, LIBLTE_API void ue_dl_free(ue_dl_t *q); +LIBLTE_API int ue_dl_decode_fft_estimate(ue_dl_t *q, + cf_t *input, + uint32_t sf_idx, + uint32_t *cfi); + +LIBLTE_API int ue_dl_decode_rnti_rv_packet(ue_dl_t *q, + dci_msg_t *dci_msg, + uint8_t *data, + uint32_t cfi, + uint32_t sf_idx, + uint16_t rnti, + uint32_t rvidx); + +LIBLTE_API int ue_dl_find_ul_dci(ue_dl_t *q, + dci_msg_t *dci_msg, + uint32_t cfi, + uint32_t sf_idx, + uint16_t rnti); + LIBLTE_API int ue_dl_decode(ue_dl_t * q, cf_t *input, uint8_t *data, @@ -92,15 +111,15 @@ LIBLTE_API int ue_dl_decode(ue_dl_t * q, LIBLTE_API int ue_dl_decode_rnti(ue_dl_t * q, cf_t *input, uint8_t *data, - uint16_t rnti, - uint32_t sf_idx); + uint32_t sf_idx, + uint16_t rnti); -LIBLTE_API int ue_dl_decode_sib(ue_dl_t * q, - cf_t *input, - uint8_t * data, - uint32_t sf_idx, - uint16_t rnti, - uint32_t rvidx); +LIBLTE_API int ue_dl_decode_rnti_rv(ue_dl_t * q, + cf_t *input, + uint8_t * data, + uint32_t sf_idx, + uint16_t rnti, + uint32_t rvidx); LIBLTE_API void ue_dl_reset(ue_dl_t *q); diff --git a/lte/phy/include/liblte/phy/ue/ue_ul.h b/lte/phy/include/liblte/phy/ue/ue_ul.h new file mode 100644 index 000000000..999d67fbd --- /dev/null +++ b/lte/phy/include/liblte/phy/ue/ue_ul.h @@ -0,0 +1,114 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The libLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the libLTE library. + * + * libLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * libLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * A copy of the GNU Lesser General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#ifndef UEUL_H +#define UEUL_H + +/******************************************************* + * + * This module is a frontend to all the data and control channels processing + * modules. + ********************************************************/ + + + +#include "liblte/phy/ch_estimation/chest_dl.h" +#include "liblte/phy/common/fft.h" +#include "liblte/phy/common/phy_common.h" +#include "liblte/phy/ch_estimation/refsignal_ul.h" +#include "liblte/phy/phch/pusch.h" +#include "liblte/phy/phch/ra.h" +#include "liblte/phy/sync/cfo.h" +#include "liblte/phy/utils/vector.h" +#include "liblte/phy/utils/debug.h" + +#include "liblte/config.h" + +#define NOF_HARQ_PROCESSES 8 + +typedef struct LIBLTE_API { + lte_fft_t fft; + cfo_t cfo; + lte_cell_t cell; + + float current_cfo; + + refsignal_drms_pusch_cfg_t pusch_drms_cfg; + + refsignal_ul_t drms; + harq_t harq_process[NOF_HARQ_PROCESSES]; + pusch_t pusch; + + cf_t *refsignal; + cf_t *sf_symbols; + + uint16_t current_rnti; +}ue_ul_t; + +/* This function shall be called just after the initial synchronization */ +LIBLTE_API int ue_ul_init(ue_ul_t *q, + lte_cell_t cell); + +LIBLTE_API void ue_ul_free(ue_ul_t *q); + +LIBLTE_API void ue_ul_set_cfo(ue_ul_t *q, + float cur_cfo); + +LIBLTE_API void ue_ul_set_pusch_cfg(ue_ul_t *q, + refsignal_drms_pusch_cfg_t *pusch_drms_cfg, + pusch_hopping_cfg_t *pusch_hopping_cfg); + +LIBLTE_API int ue_ul_pusch_encode(ue_ul_t *q, + ra_pusch_t *ra_ul, + uint8_t *data, + cf_t *output_signal); + +LIBLTE_API int ue_ul_pusch_encode_rnti(ue_ul_t *q, + ra_pusch_t *ra_ul, + uint8_t *data, + uint16_t rnti, + cf_t *output_signal); + +LIBLTE_API int ue_ul_pusch_uci_encode(ue_ul_t *q, + ra_pusch_t *ra_ul, + uint8_t *data, + uci_data_t uci_data, + cf_t *output_signal); + +LIBLTE_API int ue_ul_pusch_uci_encode_rnti(ue_ul_t *q, + ra_pusch_t *ra_ul, + uint8_t *data, + uci_data_t uci_data, + uint16_t rnti, + cf_t *output_signal); + +LIBLTE_API void ue_ul_reset(ue_ul_t *q); + +LIBLTE_API void ue_ul_set_rnti(ue_ul_t *q, + uint16_t rnti); + +#endif \ No newline at end of file diff --git a/lte/phy/lib/ch_estimation/src/chest_dl.c b/lte/phy/lib/ch_estimation/src/chest_dl.c index 3b039e8d6..12c5cdd7d 100644 --- a/lte/phy/lib/ch_estimation/src/chest_dl.c +++ b/lte/phy/lib/ch_estimation/src/chest_dl.c @@ -87,6 +87,12 @@ int chest_dl_init(chest_dl_t *q, lte_cell_t cell) } bzero(q->tmp_timeavg[i], sizeof(cf_t) * 2*cell.nof_prb); } + q->tmp_timeavg_mult = vec_malloc(sizeof(cf_t) * 2*cell.nof_prb); + if (!q->tmp_timeavg_mult) { + perror("malloc"); + goto clean_exit; + } + bzero(q->tmp_timeavg_mult, sizeof(cf_t) * 2*cell.nof_prb); for (int i=0;ipilot_estimates[i] = vec_malloc(sizeof(cf_t) * REFSIGNAL_NUM_SF(cell.nof_prb, i)); @@ -117,14 +123,14 @@ int chest_dl_init(chest_dl_t *q, lte_cell_t cell) } /* Set default time/freq filters */ - float f[3]={0.15, 0.7, 0.15}; - chest_dl_set_filter_freq(q, f, 3); + //float f[3]={0.1, 0.8, 0.1}; + //chest_dl_set_filter_freq(q, f, 3); - //float f[5]={0.05, 0.15, 0.6, 0.15, 0.05}; - //chest_dl_set_filter_freq(q, f, 5); + float f[5]={0.05, 0.2, 0.5, 0.2, 0.05}; + chest_dl_set_filter_freq(q, f, 5); float t[2]={0.2, 0.8}; - chest_dl_set_filter_time(q, t, 2); + chest_dl_set_filter_time(q, t, 0); q->cell = cell; } @@ -153,6 +159,9 @@ void chest_dl_free(chest_dl_t *q) free(q->tmp_timeavg[i]); } } + if (q->tmp_timeavg_mult) { + free(q->tmp_timeavg_mult); + } interp_linear_vector_free(&q->interp_linvec); interp_linear_free(&q->interp_lin); @@ -239,10 +248,11 @@ static void average_pilots(chest_dl_t *q, uint32_t port_id) conv_same_cf(&pilot_est(0), q->filter_freq, &pilot_tmp(0), nref, q->filter_freq_len); /* Adjust extremes using linear interpolation */ + pilot_tmp(0) += interp_linear_onesample(pilot_est(1), pilot_est(0)) - * q->filter_freq[q->filter_freq_len/2-1]; + * q->filter_freq[q->filter_freq_len/2-1]*1.2; pilot_tmp(nref-1) += interp_linear_onesample(pilot_est(nref-2), pilot_est(nref-1)) - * q->filter_freq[q->filter_freq_len/2+1]; + * q->filter_freq[q->filter_freq_len/2+1]*1.2; } else { memcpy(&pilot_tmp(0), &pilot_est(0), nref * sizeof(cf_t)); } diff --git a/lte/phy/lib/ch_estimation/src/refsignal_ul.c b/lte/phy/lib/ch_estimation/src/refsignal_ul.c index 3323d2c60..1fff84404 100644 --- a/lte/phy/lib/ch_estimation/src/refsignal_ul.c +++ b/lte/phy/lib/ch_estimation/src/refsignal_ul.c @@ -243,7 +243,11 @@ bool refsignal_drms_pusch_cfg_isvalid(refsignal_ul_t *q, refsignal_drms_pusch_cf } } -void refsignal_drms_pusch_put(refsignal_ul_t *q, refsignal_drms_pusch_cfg_t *cfg, cf_t *r_pusch, uint32_t ns_idx, uint32_t n_prb, cf_t *sf_symbols) { +void refsignal_drms_pusch_put(refsignal_ul_t *q, refsignal_drms_pusch_cfg_t *cfg, + cf_t *r_pusch, + uint32_t ns_idx, uint32_t n_prb, + cf_t *sf_symbols) +{ if (ns_idx < 2) { uint32_t L = (ns_idx+1)*CP_NSYMB(q->cell.cp)-4; memcpy(&sf_symbols[RE_IDX(q->cell.nof_prb, L, n_prb*RE_X_RB)], r_pusch, cfg->nof_prb*RE_X_RB*sizeof(cf_t)); diff --git a/lte/phy/lib/phch/src/dci.c b/lte/phy/lib/phch/src/dci.c index d9aa1d145..73ccf5bf3 100644 --- a/lte/phy/lib/phch/src/dci.c +++ b/lte/phy/lib/phch/src/dci.c @@ -97,6 +97,37 @@ int dci_msg_to_ra_dl(dci_msg_t *msg, uint16_t msg_rnti, return ret; } +int dci_msg_to_ra_ul(dci_msg_t *msg, lte_cell_t cell, uint32_t n_rb_ho, ra_pusch_t *ra_ul) +{ + int ret = LIBLTE_ERROR_INVALID_INPUTS; + + if (msg != NULL && + ra_ul != NULL && + lte_cell_isvalid(&cell)) + { + ret = LIBLTE_ERROR; + + bzero(ra_ul, sizeof(ra_pusch_t)); + + if (dci_msg_unpack_pusch(msg, ra_ul, cell.nof_prb)) { + fprintf(stderr, "Can't unpack PDSCH message\n"); + return ret; + } + + if (VERBOSE_ISINFO()) { + ra_pusch_fprint(stdout, ra_ul, cell.nof_prb); + } + + if (ra_ul_alloc(&ra_ul->prb_alloc, ra_ul, n_rb_ho, cell.nof_prb)) { + fprintf(stderr, "Error computing resource allocation\n"); + return ret; + } + + ret = LIBLTE_SUCCESS; + } + return ret; +} + int dci_location_set(dci_location_t *c, uint32_t L, uint32_t nCCE) { if (L <= 3) { c->L = L; diff --git a/lte/phy/lib/phch/src/harq.c b/lte/phy/lib/phch/src/harq.c index 139ee7bad..6e444e2a7 100644 --- a/lte/phy/lib/phch/src/harq.c +++ b/lte/phy/lib/phch/src/harq.c @@ -106,13 +106,13 @@ int harq_init(harq_t *q, lte_cell_t cell) { if (ret != LIBLTE_ERROR) { q->max_cb = (uint32_t) ret / (MAX_LONG_CB - 24) + 1; - q->pdsch_w_buff_f = malloc(sizeof(float*) * q->max_cb); + q->pdsch_w_buff_f = vec_malloc(sizeof(float*) * q->max_cb); if (!q->pdsch_w_buff_f) { perror("malloc"); return LIBLTE_ERROR; } - q->pdsch_w_buff_c = malloc(sizeof(uint8_t*) * q->max_cb); + q->pdsch_w_buff_c = vec_malloc(sizeof(uint8_t*) * q->max_cb); if (!q->pdsch_w_buff_c) { perror("malloc"); return LIBLTE_ERROR; diff --git a/lte/phy/lib/phch/src/pbch.c b/lte/phy/lib/phch/src/pbch.c index 80b6337f9..63ccd9b26 100644 --- a/lte/phy/lib/phch/src/pbch.c +++ b/lte/phy/lib/phch/src/pbch.c @@ -42,9 +42,10 @@ #include "liblte/phy/utils/debug.h" const uint8_t crc_mask[4][16] = { - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 } }; + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 } }; bool pbch_exists(int nframe, int nslot) { return (!(nframe % 5) && nslot == 1); @@ -246,10 +247,10 @@ void pbch_free(pbch_t *q) { * msg buffer must be 24 byte length at least */ void pbch_mib_unpack(uint8_t *msg, lte_cell_t *cell, uint32_t *sfn) { - int bw, phich_res; + int phich_res; - bw = bit_unpack(&msg, 3); - switch (bw) { + cell->bw_idx = bit_unpack(&msg, 3); + switch (cell->bw_idx) { case 0: cell->nof_prb = 6; break; @@ -257,7 +258,7 @@ void pbch_mib_unpack(uint8_t *msg, lte_cell_t *cell, uint32_t *sfn) { cell->nof_prb = 15; break; default: - cell->nof_prb = (bw - 1) * 25; + cell->nof_prb = (cell->bw_idx - 1) * 25; break; } if (*msg) { diff --git a/lte/phy/lib/phch/src/pusch.c b/lte/phy/lib/phch/src/pusch.c index c365e1615..ef7aa5619 100644 --- a/lte/phy/lib/phch/src/pusch.c +++ b/lte/phy/lib/phch/src/pusch.c @@ -57,7 +57,7 @@ static int f_hop_sum(pusch_t *q, uint32_t i) { return sum; } -static int f_hop(pusch_t *q, ra_ul_hopping_t *hopping, int i) { +static int f_hop(pusch_t *q, pusch_hopping_cfg_t *hopping, int i) { if (i == -1) { return 0; } else { @@ -71,7 +71,7 @@ static int f_hop(pusch_t *q, ra_ul_hopping_t *hopping, int i) { } } -static int f_m(pusch_t *q, ra_ul_hopping_t *hopping, uint32_t i) { +static int f_m(pusch_t *q, pusch_hopping_cfg_t *hopping, uint32_t i) { if (hopping->n_sb == 1) { if (hopping->hop_mode == hop_mode_inter_sf) { return hopping->current_tx_nb%2; @@ -87,7 +87,7 @@ int pusch_cp(pusch_t *q, harq_t *harq, cf_t *input, cf_t *output, bool advance_i { cf_t *in_ptr = input; cf_t *out_ptr = output; - ra_ul_hopping_t *hopping = &harq->ul_hopping; + pusch_hopping_cfg_t *hopping = &q->hopping_cfg; uint32_t L_ref = 3; if (CP_ISEXT(q->cell.cp)) { @@ -128,6 +128,7 @@ int pusch_cp(pusch_t *q, harq_t *harq, cf_t *input, cf_t *output, bool advance_i } } + harq->ul_alloc.n_prb_tilde[slot] = n_prb_tilde; INFO("Allocating PUSCH %d PRB to index %d at slot %d\n",harq->ul_alloc.L_prb, n_prb_tilde,slot); for (uint32_t l=0;lcell.cp);l++) { if (l != L_ref) { @@ -278,6 +279,11 @@ void pusch_free(pusch_t *q) { } +void pusch_set_hopping_cfg(pusch_t *q, pusch_hopping_cfg_t *cfg) +{ + memcpy(&q->hopping_cfg, cfg, sizeof(pusch_hopping_cfg_t)); +} + /* Precalculate the PUSCH scramble sequences for a given RNTI. This function takes a while * to execute, so shall be called once the final C-RNTI has been allocated for the session. * For the connection procedure, use pusch_encode_rnti() or pusch_decode_rnti() functions */ @@ -412,9 +418,6 @@ int pusch_uci_encode_rnti(pusch_t *q, harq_t *harq, uint8_t *data, uci_data_t uc return LIBLTE_ERROR; } - printf("before scram: "); - vec_fprint_b(stdout, q->pusch_q, harq->nof_bits); - if (rnti != q->rnti) { sequence_t seq; if (sequence_pusch(&seq, rnti, 2 * harq->sf_idx, q->cell.id, harq->nof_bits)) { @@ -426,9 +429,6 @@ int pusch_uci_encode_rnti(pusch_t *q, harq_t *harq, uint8_t *data, uci_data_t uc scrambling_b_offset_pusch(&q->seq_pusch[harq->sf_idx], (uint8_t*) q->pusch_q, 0, harq->nof_bits); } - printf("after scram: "); - vec_fprint_b(stdout, q->pusch_q, harq->nof_bits); - mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->pusch_q, q->pusch_d, harq->nof_bits); dft_precoding(&q->dft_precoding, q->pusch_d, q->pusch_z, diff --git a/lte/phy/lib/phch/test/pusch_test.c b/lte/phy/lib/phch/test/pusch_test.c index 469ea5e6c..d70a30781 100644 --- a/lte/phy/lib/phch/test/pusch_test.c +++ b/lte/phy/lib/phch/test/pusch_test.c @@ -191,10 +191,13 @@ int main(int argc, char **argv) { fprintf(stderr, "Error configuring HARQ process\n"); goto quit; } - harq_process.ul_hopping.n_sb = 1; - harq_process.ul_hopping.hopping_offset = 0; - harq_process.ul_hopping.hop_mode = hop_mode_inter_sf; - harq_process.ul_hopping.current_tx_nb = 0; + pusch_hopping_cfg_t ul_hopping; + ul_hopping.n_sb = 1; + ul_hopping.hopping_offset = 0; + ul_hopping.hop_mode = hop_mode_inter_sf; + ul_hopping.current_tx_nb = 0; + + pusch_set_hopping_cfg(&pusch, &ul_hopping); uint32_t nof_re = RE_X_RB*cell.nof_prb*2*CP_NSYMB(cell.cp); sf_symbols = vec_malloc(sizeof(cf_t) * nof_re); diff --git a/lte/phy/lib/resampling/src/interp.c b/lte/phy/lib/resampling/src/interp.c index 3988e463e..0aeb13616 100644 --- a/lte/phy/lib/resampling/src/interp.c +++ b/lte/phy/lib/resampling/src/interp.c @@ -37,14 +37,7 @@ /*************** STATIC FUNCTIONS ***********************/ cf_t interp_linear_onesample(cf_t input0, cf_t input1) { - float mag0=0, mag1=0, arg0=0, arg1=0, mag=0, arg=0; - mag0 = cabsf(input0); - mag1 = cabsf(input1); - arg0 = cargf(input0); - arg1 = cargf(input1); - mag = 2*mag1 -mag0; - arg = 2*arg1-arg0; - return mag * cexpf(I * arg); + return 2*input1-input0; } cf_t interp_linear_onesample_cabs(cf_t input0, cf_t input1) { diff --git a/lte/phy/lib/sync/src/sss.c b/lte/phy/lib/sync/src/sss.c index fbbd517e2..dd66aa29b 100644 --- a/lte/phy/lib/sync/src/sss.c +++ b/lte/phy/lib/sync/src/sss.c @@ -149,15 +149,7 @@ int sss_synch_N_id_1(sss_synch_t *q, uint32_t m0, uint32_t m1) { } else { N_id_1 = q->N_id_1_table[m1][m0 - 1]; } - if (N_id_1 == 0) { - if (m0 == 0 && m1 == 1) { - return N_id_1; - } else { - return LIBLTE_ERROR; - } - } else { - return N_id_1; - } + return N_id_1; } /** High-level API */ diff --git a/lte/phy/lib/sync/test/pss_usrp.c b/lte/phy/lib/sync/test/pss_usrp.c index cfbe03894..fdd140b44 100644 --- a/lte/phy/lib/sync/test/pss_usrp.c +++ b/lte/phy/lib/sync/test/pss_usrp.c @@ -194,6 +194,7 @@ int main(int argc, char **argv) { frame_cnt = 0; last_peak = 0; mean_peak = 0; + int peak_offset = 0; float cfo; float mean_cfo = 0; uint32_t m0, m1; @@ -204,27 +205,12 @@ int main(int argc, char **argv) { bzero(&ssync, sizeof(sync_t)); ssync.fft_size = fft_size; - - timestamp_t cur_time; - cuhd_get_time(uhd, &cur_time.full_secs, &cur_time.frac_secs); - - // wait 1 sec to start - timestamp_add(&cur_time, 1, 0); - double period = 0.005; // 5 ms - double period_diff = 0; - double nsamples_offset_x_sf; - - int last_peak_idx = 0; - bool is_first = true; while(frame_cnt < nof_frames || nof_frames == -1) { - timestamp_add(&cur_time, 0, period + period_diff); - - n = cuhd_recv_timed2(uhd, buffer, flen, cur_time.full_secs, cur_time.frac_secs, is_first, false); + n = cuhd_recv(uhd, buffer, flen - peak_offset, 1); if (n < 0) { fprintf(stderr, "Error receiving samples\n"); exit(-1); } - is_first = false; peak_idx = pss_synch_find_pss(&pss, buffer, &peak_value); if (peak_idx < 0) { @@ -236,13 +222,7 @@ int main(int argc, char **argv) { if (peak_value >= threshold) { nof_det++; - - if (last_peak_idx) { - nsamples_offset_x_sf = VEC_CMA(((double) peak_idx - (double) last_peak_idx ), nsamples_offset_x_sf, frame_cnt); - period_diff += nsamples_offset_x_sf / (flen*2*100); - } - last_peak_idx = peak_idx; - + if (peak_idx >= fft_size) { // Estimate CFO @@ -273,7 +253,7 @@ int main(int argc, char **argv) { INFO("Diff N_id_1: %d\n", sss_synch_N_id_1(&sss, m0, m1)); sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 1, NULL, &m0, &m0_value, &m1, &m1_value); if (sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { - sss_error1++; + sss_error1++; } INFO("Full N_id_1: %d\n", sss_synch_N_id_1(&sss, m0, m1)); } @@ -308,10 +288,10 @@ int main(int argc, char **argv) { frame_cnt++; - printf("[%5d]: Pos: %5d (%f), PSR: %4.1f (~%4.1f) Pdet: %4.2f, " + printf("[%5d]: Pos: %5d, PSR: %4.1f (~%4.1f) Pdet: %4.2f, " "FA: %4.2f, CFO: %+4.1f KHz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f\%\r", frame_cnt, - peak_idx, period_diff*1000000, + peak_idx, peak_value, mean_peak, (float) nof_det/frame_cnt, (float) nof_nopeakdet/frame_cnt, mean_cfo*15, @@ -408,4 +388,3 @@ void do_plots_sss(float *corr_m0, float *corr_m1) { } #endif - diff --git a/lte/phy/lib/ue/src/ue_dl.c b/lte/phy/lib/ue/src/ue_dl.c index 3ecf5709f..e1ac686d4 100644 --- a/lte/phy/lib/ue/src/ue_dl.c +++ b/lte/phy/lib/ue/src/ue_dl.c @@ -66,10 +66,6 @@ int ue_dl_init(ue_dl_t *q, fprintf(stderr, "Error initiating REGs\n"); goto clean_exit; } - if (pbch_init(&q->pbch, q->cell)) { - fprintf(stderr, "Error creating PBCH object\n"); - goto clean_exit; - } if (pcfich_init(&q->pcfich, &q->regs, q->cell)) { fprintf(stderr, "Error creating PCFICH object\n"); goto clean_exit; @@ -121,7 +117,6 @@ void ue_dl_free(ue_dl_t *q) { lte_fft_free(&q->fft); chest_dl_free(&q->chest); regs_free(&q->regs); - pbch_free(&q->pbch); pcfich_free(&q->pcfich); pdcch_free(&q->pdcch); pdsch_free(&q->pdsch); @@ -155,8 +150,6 @@ void ue_dl_reset(ue_dl_t *q) { harq_reset(&q->harq_process[0]); } -LIBLTE_API float mean_exec_time=0; - dci_format_t ue_formats[] = {Format1,Format1A}; // Format1B should go here also const uint32_t nof_ue_formats = 2; @@ -171,48 +164,116 @@ const uint32_t nof_common_formats = 2; * - PDSCH decoding: Decode TB scrambling with RNTI given by ue_dl_set_rnti() */ int ue_dl_decode(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx) { - return ue_dl_decode_sib(q, input, data, sf_idx, q->current_rnti, 0); + return ue_dl_decode_rnti_rv(q, input, data, sf_idx, q->current_rnti, 0); } -int ue_dl_decode_rnti(ue_dl_t *q, cf_t *input, uint8_t *data, uint16_t rnti, uint32_t sf_idx) { - return ue_dl_decode_sib(q, input, data, sf_idx, rnti, 0); +int ue_dl_decode_rnti(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti) { + return ue_dl_decode_rnti_rv(q, input, data, sf_idx, rnti, 0); } -int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx) -{ - uint32_t cfi, i; +int ue_dl_decode_fft_estimate(ue_dl_t *q, cf_t *input, uint32_t sf_idx, uint32_t *cfi) { float cfi_corr; - ra_pdsch_t ra_dl; - dci_location_t locations[MAX_CANDIDATES]; - dci_msg_t dci_msg; - uint32_t nof_locations; - uint16_t crc_rem; + if (input && q && cfi && sf_idx < NSUBFRAMES_X_FRAME) { + + /* Run FFT for all subframe data */ + lte_fft_run_sf(&q->fft, input, q->sf_symbols); + + /* Get channel estimates for each port */ + chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, sf_idx); + + /* First decode PCFICH and obtain CFI */ + if (pcfich_decode(&q->pcfich, q->sf_symbols, q->ce, + chest_dl_get_noise_estimate(&q->chest), sf_idx, cfi, &cfi_corr)<0) { + fprintf(stderr, "Error decoding PCFICH\n"); + return LIBLTE_ERROR; + } + + INFO("Decoded CFI=%d with correlation %.2f\n", cfi, cfi_corr); + + if (regs_set_cfi(&q->regs, *cfi)) { + fprintf(stderr, "Error setting CFI\n"); + return LIBLTE_ERROR; + } + + /* Extract all PDCCH symbols and get LLRs */ + if (pdcch_extract_llr(&q->pdcch, q->sf_symbols, q->ce, chest_dl_get_noise_estimate(&q->chest), sf_idx, *cfi)) { + fprintf(stderr, "Error extracting LLRs\n"); + return LIBLTE_ERROR; + } + + + return LIBLTE_SUCCESS; + } else { + return LIBLTE_ERROR_INVALID_INPUTS; + } +} + +int ue_dl_decode_rnti_rv_packet(ue_dl_t *q, dci_msg_t *dci_msg, uint8_t *data, + uint32_t cfi, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx) +{ int ret = LIBLTE_ERROR; - struct timeval t[3]; - uint32_t nof_formats; - dci_format_t *formats = NULL; - /* Run FFT for all subframe data */ - lte_fft_run_sf(&q->fft, input, q->sf_symbols); - - gettimeofday(&t[1], NULL); - - /* Get channel estimates for each port */ - chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, sf_idx); - - /* First decode PCFICH and obtain CFI */ - if (pcfich_decode(&q->pcfich, q->sf_symbols, q->ce, - chest_dl_get_noise_estimate(&q->chest), sf_idx, &cfi, &cfi_corr)<0) { - fprintf(stderr, "Error decoding PCFICH\n"); + q->nof_pdcch_detected++; + if (dci_msg_to_ra_dl(dci_msg, rnti, q->cell, cfi, &q->ra_dl)) { + fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n"); return LIBLTE_ERROR; } - INFO("Decoded CFI=%d with correlation %.2f\n", cfi, cfi_corr); - - if (regs_set_cfi(&q->regs, cfi)) { - fprintf(stderr, "Error setting CFI\n"); + if (rnti != SIRNTI) { + rvidx = q->ra_dl.rv_idx; + } + if (harq_setup_dl(&q->harq_process[0], q->ra_dl.mcs, rvidx, sf_idx, &q->ra_dl.prb_alloc)) { + fprintf(stderr, "Error configuring HARQ process\n"); return LIBLTE_ERROR; } + if (q->harq_process[0].mcs.mod > 0 && q->harq_process[0].mcs.tbs >= 0) { + ret = pdsch_decode_rnti(&q->pdsch, &q->harq_process[0], q->sf_symbols, + q->ce, chest_dl_get_noise_estimate(&q->chest), + rnti, data); + if (ret == LIBLTE_ERROR) { + q->pkt_errors++; + } else if (ret == LIBLTE_ERROR_INVALID_INPUTS) { + fprintf(stderr, "Error calling pdsch_decode()\n"); + } else if (ret == LIBLTE_SUCCESS) { + if (VERBOSE_ISINFO()) { + INFO("Decoded Message: ", 0); + vec_fprint_hex(stdout, data, q->ra_dl.mcs.tbs); + } + } + q->pkts_total++; + } + return ret; +} + +int ue_dl_find_ul_dci(ue_dl_t *q, dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, uint16_t rnti) +{ + dci_location_t locations[MAX_CANDIDATES]; + uint32_t nof_locations = pdcch_ue_locations(&q->pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, rnti); + uint16_t crc_rem = 0; + for (uint32_t i=0;ipdcch, dci_msg, &locations[i], Format0, &crc_rem)) { + fprintf(stderr, "Error decoding DCI msg\n"); + return LIBLTE_ERROR; + } + INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem); + } + return crc_rem == rnti; +} + +int ue_dl_decode_rnti_rv(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx) +{ + uint32_t cfi, i; + dci_msg_t dci_msg; + dci_location_t locations[MAX_CANDIDATES]; + uint32_t nof_locations; + uint16_t crc_rem; + int ret = LIBLTE_ERROR; + uint32_t nof_formats; + dci_format_t *formats = NULL; + + if ((ret = ue_dl_decode_fft_estimate(q, input, sf_idx, &cfi)) < 0) { + return ret; + } /* Generate PDCCH candidates */ if (rnti == SIRNTI) { @@ -225,11 +286,6 @@ int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, ui nof_formats = nof_ue_formats; } - /* Extract all PDCCH symbols and get LLRs */ - if (pdcch_extract_llr(&q->pdcch, q->sf_symbols, q->ce, chest_dl_get_noise_estimate(&q->chest), sf_idx, cfi)) { - fprintf(stderr, "Error extracting LLRs\n"); - return LIBLTE_ERROR; - } /* For all possible locations, try to decode a DCI message */ crc_rem = 0; uint32_t found_dci = 0; @@ -242,50 +298,14 @@ int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, ui INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem); if (crc_rem == rnti) { - - found_dci++; - q->nof_pdcch_detected++; - if (dci_msg_to_ra_dl(&dci_msg, rnti, q->cell, cfi, &ra_dl)) { - fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n"); - return LIBLTE_ERROR; - } - - if (rnti != SIRNTI) { - rvidx = ra_dl.rv_idx; - } - if (harq_setup_dl(&q->harq_process[0], ra_dl.mcs, rvidx, sf_idx, &ra_dl.prb_alloc)) { - fprintf(stderr, "Error configuring HARQ process\n"); - return LIBLTE_ERROR; - } - if (q->harq_process[0].mcs.mod > 0 && q->harq_process[0].mcs.tbs >= 0) { - ret = pdsch_decode_rnti(&q->pdsch, &q->harq_process[0], q->sf_symbols, - q->ce, chest_dl_get_noise_estimate(&q->chest), - rnti, data); - if (ret == LIBLTE_ERROR) { - q->pkt_errors++; - } else if (ret == LIBLTE_ERROR_INVALID_INPUTS) { - fprintf(stderr, "Error calling pdsch_decode()\n"); - return LIBLTE_ERROR; - } else if (ret == LIBLTE_SUCCESS) { - if (VERBOSE_ISINFO()) { - INFO("Decoded Message: ", 0); - vec_fprint_hex(stdout, data, ra_dl.mcs.tbs); - } - } - q->pkts_total++; - } + found_dci++; + ret = ue_dl_decode_rnti_rv_packet(q, &dci_msg, data, cfi, sf_idx, rnti, rvidx); } } } - - - gettimeofday(&t[2], NULL); - get_time_interval(t); - mean_exec_time = (float) VEC_EMA((float) t[0].tv_usec, mean_exec_time, 0.01); - if (found_dci > 0 && ret == LIBLTE_SUCCESS) { - return ra_dl.mcs.tbs; + return q->ra_dl.mcs.tbs; } else { return 0; } diff --git a/lte/phy/lib/ue/src/ue_mib.c b/lte/phy/lib/ue/src/ue_mib.c index 512aeca99..15661c7b8 100644 --- a/lte/phy/lib/ue/src/ue_mib.c +++ b/lte/phy/lib/ue/src/ue_mib.c @@ -121,7 +121,7 @@ int ue_mib_decode(ue_mib_t * q, cf_t *input, /* Run FFT for the slot symbols */ lte_fft_run_sf(&q->fft, input, q->sf_symbols); - /* Get channel estimates of slot #1 for each port */ + /* Get channel estimates of sf idx #0 for each port */ ret = chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, 0); if (ret < 0) { return LIBLTE_ERROR; @@ -214,9 +214,7 @@ int ue_mib_sync_decode(ue_mib_sync_t * q, break; } else if (ue_sync_get_sfidx(&q->ue_sync) == 0) { if (ret == 1) { - ue_mib_reset(&q->ue_mib); - mib_ret = ue_mib_decode(&q->ue_mib, sf_buffer, bch_payload, nof_tx_ports, sfn_offset); - + mib_ret = ue_mib_decode(&q->ue_mib, sf_buffer, bch_payload, nof_tx_ports, sfn_offset); } else { INFO("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt); ue_mib_reset(&q->ue_mib); diff --git a/lte/phy/lib/ue/src/ue_sync.c b/lte/phy/lib/ue/src/ue_sync.c index 137342d7e..a38eb3d5d 100644 --- a/lte/phy/lib/ue/src/ue_sync.c +++ b/lte/phy/lib/ue/src/ue_sync.c @@ -42,7 +42,7 @@ #define MAX_TIME_OFFSET 128 cf_t dummy[MAX_TIME_OFFSET]; -#define TRACK_MAX_LOST 10 +#define TRACK_MAX_LOST 4 #define TRACK_FRAME_SIZE 32 #define FIND_NOF_AVG_FRAMES 2 @@ -140,7 +140,7 @@ int ue_sync_init(ue_sync_t *q, sync_set_threshold(&q->sfind, 1.3); sync_set_em_alpha(&q->sfind, 0.01); q->nof_avg_find_frames = FIND_NOF_AVG_FRAMES; - sync_set_threshold(&q->strack, 1.2); + sync_set_threshold(&q->strack, 1.0); } else { sync_set_N_id_2(&q->sfind, cell.id%3); @@ -155,8 +155,8 @@ int ue_sync_init(ue_sync_t *q, */ sync_set_em_alpha(&q->sfind, 1); q->nof_avg_find_frames = 1; - sync_set_threshold(&q->sfind, 2.0); - sync_set_threshold(&q->strack, 1.2); + sync_set_threshold(&q->sfind, 4.0); + sync_set_threshold(&q->strack, 1.3); /* Correct CFO in the find state but not in the track state, since is called only * 1 every 5 subframes. Will do it in the ue_sync_get_buffer() function. @@ -286,33 +286,33 @@ static int track_peak_ok(ue_sync_t *q, uint32_t track_idx) { q->strack.m0, q->strack.m0_value, q->strack.m1, q->strack.m1_value); q->sf_idx = sync_get_sf_idx(&q->strack); } - } else { - // Adjust time offset - q->time_offset = ((int) track_idx - (int) q->strack.frame_size/2 - (int) q->strack.fft_size); - - if (q->time_offset) { - INFO("Time offset adjustment: %d samples\n", q->time_offset); - } - - /* compute cumulative moving average time offset */ - q->mean_time_offset = (float) VEC_CMA((float) q->time_offset, q->mean_time_offset, q->frame_total_cnt); - - /* If the PSS peak is beyond the frame (we sample too slowly), - discard the offseted samples to align next frame */ - if (q->time_offset > 0 && q->time_offset < MAX_TIME_OFFSET) { - INFO("\nPositive time offset %d samples. Mean time offset %f.\n", q->time_offset, q->mean_time_offset); - if (q->recv_callback(q->stream, dummy, (uint32_t) q->time_offset, &q->last_timestamp) < 0) { - fprintf(stderr, "Error receiving from USRP\n"); - return LIBLTE_ERROR; - } - q->time_offset = 0; - } - - q->peak_idx = q->sf_len/2 + q->time_offset; - q->frame_ok_cnt++; - q->frame_no_cnt = 0; } + // Adjust time offset + q->time_offset = ((int) track_idx - (int) q->strack.frame_size/2 - (int) q->strack.fft_size); + + if (q->time_offset) { + INFO("Time offset adjustment: %d samples\n", q->time_offset); + } + + /* compute cumulative moving average time offset */ + q->mean_time_offset = (float) VEC_CMA((float) q->time_offset, q->mean_time_offset, q->frame_total_cnt); + + /* If the PSS peak is beyond the frame (we sample too slowly), + discard the offseted samples to align next frame */ + if (q->time_offset > 0 && q->time_offset < MAX_TIME_OFFSET) { + INFO("Positive time offset %d samples. Mean time offset %f.\n", q->time_offset, q->mean_time_offset); + if (q->recv_callback(q->stream, dummy, (uint32_t) q->time_offset, &q->last_timestamp) < 0) { + fprintf(stderr, "Error receiving from USRP\n"); + return LIBLTE_ERROR; + } + q->time_offset = 0; + } + + q->peak_idx = q->sf_len/2 + q->time_offset; + q->frame_ok_cnt++; + q->frame_no_cnt = 0; + return 1; } @@ -456,6 +456,13 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) { -sync_get_cfo(&q->strack) / q->fft_size); } + /* + if (track_idx > q->fft_size + q->strack.frame_size/2) { + *sf_symbols = &q->input_buffer[track_idx - q->fft_size - q->strack.frame_size/2]; + } else { + *sf_symbols = q->input_buffer; + } + */ *sf_symbols = q->input_buffer; break; diff --git a/lte/phy/lib/ue/src/ue_ul.c b/lte/phy/lib/ue/src/ue_ul.c new file mode 100644 index 000000000..0c6d96a09 --- /dev/null +++ b/lte/phy/lib/ue/src/ue_ul.c @@ -0,0 +1,210 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The libLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the libLTE library. + * + * libLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * libLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * A copy of the GNU Lesser General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "liblte/phy/ue/ue_ul.h" + +#include +#include + +#define CURRENT_FFTSIZE lte_symbol_sz(q->cell.nof_prb) +#define CURRENT_SFLEN SF_LEN(CURRENT_FFTSIZE, q->cell.cp) + +#define CURRENT_SLOTLEN_RE SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) +#define CURRENT_SFLEN_RE SF_LEN_RE(q->cell.nof_prb, q->cell.cp) + + +int ue_ul_init(ue_ul_t *q, + lte_cell_t cell) +{ + int ret = LIBLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + lte_cell_isvalid(&cell)) + { + ret = LIBLTE_ERROR; + + bzero(q, sizeof(ue_ul_t)); + + q->cell = cell; + + if (lte_fft_init(&q->fft, q->cell.cp, q->cell.nof_prb)) { + fprintf(stderr, "Error initiating FFT\n"); + goto clean_exit; + } + lte_fft_set_freq_shift(&q->fft, 0.5); + + if (cfo_init(&q->cfo, CURRENT_SFLEN)) { + fprintf(stderr, "Error creating CFO object\n"); + goto clean_exit; + } + + if (pusch_init(&q->pusch, q->cell)) { + fprintf(stderr, "Error creating PUSCH object\n"); + goto clean_exit; + } + for (uint32_t i=0;iharq_process[i], q->cell)) { + fprintf(stderr, "Error initiating HARQ process\n"); + goto clean_exit; + } + } + if (refsignal_ul_init(&q->drms, cell)) { + fprintf(stderr, "Error initiating refsignal_ul\n"); + goto clean_exit; + } + q->sf_symbols = vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); + if (!q->sf_symbols) { + perror("malloc"); + goto clean_exit; + } + q->refsignal = vec_malloc(RE_X_RB * q->cell.nof_prb * sizeof(cf_t)); + if (!q->refsignal) { + perror("malloc"); + goto clean_exit; + } + + ret = LIBLTE_SUCCESS; + } else { + fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", + cell.id, cell.nof_ports, cell.nof_prb); + } + +clean_exit: + if (ret == LIBLTE_ERROR) { + ue_ul_free(q); + } + return ret; +} + +void ue_ul_free(ue_ul_t *q) { + if (q) { + lte_fft_free(&q->fft); + pusch_free(&q->pusch); + for (uint32_t i=0;iharq_process[i]); + } + cfo_free(&q->cfo); + refsignal_ul_free(&q>drms); + if (q->sf_symbols) { + free(q->sf_symbols); + } + if (q->refsignal) { + free(q->refsignal); + } + bzero(q, sizeof(ue_ul_t)); + } +} + +void ue_ul_set_cfo(ue_ul_t *q, float cur_cfo) { + q->current_cfo = cur_cfo; +} + +/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while + * to execute, so shall be called once the final C-RNTI has been allocated for the session. + * For the connection procedure, use pusch_encode_rnti() or pusch_decode_rnti() functions + */ +void ue_ul_set_rnti(ue_ul_t *q, uint16_t rnti) { + q->current_rnti = rnti; + pusch_set_rnti(&q->pusch, rnti); +} + +void ue_ul_reset(ue_ul_t *q) { + harq_reset(&q->harq_process[0]); +} + +void ue_ul_set_pusch_cfg(ue_ul_t *q, refsignal_drms_pusch_cfg_t *pusch_drms_cfg, pusch_hopping_cfg_t *pusch_hopping_cfg) +{ + pusch_set_hopping_cfg(&q->pusch, pusch_hopping_cfg); +} + +int ue_ul_pusch_encode(ue_ul_t *q, ra_pusch_t *ra_ul, uint8_t *data, uint32_t sf_idx, cf_t *output_signal) +{ + uci_data_t uci_data; + bzero(&uci_data, sizeof(uci_data_t)); + return ue_ul_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, q->current_rnti, output_signal); +} + +int ue_ul_pusch_encode_rnti(ue_ul_t *q, ra_pusch_t *ra_ul, uint8_t *data, uint16_t rnti, uint32_t sf_idx, cf_t *output_signal) +{ + uci_data_t uci_data; + bzero(&uci_data, sizeof(uci_data_t)); + return ue_ul_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, rnti, output_signal); +} + +int ue_ul_pusch_uci_encode(ue_ul_t *q, ra_pusch_t *ra_ul, uint8_t *data, uci_data_t uci_data, uint32_t sf_idx, cf_t *output_signal) +{ + return ue_ul_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, q->current_rnti, output_signal); +} + +int ue_ul_pusch_uci_encode_rnti(ue_ul_t *q, ra_pusch_t *ra_ul, uint8_t *data, uci_data_t uci_data, + uint32_t sf_idx, uint16_t rnti, + cf_t *output_signal) +{ + int ret = LIBLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + ra_ul != NULL && + data != NULL && + output_signal != NULL) + { + + if (ra_ul->prb_alloc.L_prb == 0) { + fprintf(stderr, "Invalid UL PRB allocation (L_prb=0)\n" ; + return ret; + } + } + + ret = LIBLTE_ERROR; + + if (harq_setup_ul(&q->harq_process[0], ra_ul->mcs, ra_ul->rv_idx, sf_idx, &ra_ul->prb_alloc)) { + fprintf(stderr, "Error configuring HARQ process\n"); + return ret; + } + + if (pusch_encode_rnti(&q->pusch, &q->harq_process[0], data, rnti, q->sf_symbols)) { + fprintf(stderr, "Error encoding TB\n"); + return ret; + } + + q->pusch_drms_cfg.nof_prb = ra_ul->prb_alloc.L_prb; + + for (uint32_t i=0;i<2;i++) { + // FIXME: Pregenerate for all possible number of prb + if (refsignal_dmrs_pusch_gen(&q->drms, &q->pusch_drms_cfg, 2*sf_idx+i, q->refsignal)) { + fprintf(stderr, "Error generating PUSCH DRMS signals\n"); + return ret; + } + refsignal_drms_pusch_put(&q->drms, &q->pusch_drms_cfg, q->refsignal, i, + ra_ul->prb_alloc.n_prb_tilde[i], q->sf_symbols); + } + + lte_ifft_run_sf(&q->fft, q->sf_symbols, output_signal); + + cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / lte_symbol_sz(q->cell.nof_prb)); + + ret = LIBLTE_SUCCESS; + } diff --git a/matlab/tests/pusch_test.m b/matlab/tests/pusch_test.m index 9c2bce604..2b4bc92f1 100644 --- a/matlab/tests/pusch_test.m +++ b/matlab/tests/pusch_test.m @@ -1,6 +1,6 @@ clear -ueConfig=struct('NCellID',0,'NULRB',25,'NSubframe',4,'RNTI',82,'CyclicPrefixUL','Normal','NTxAnts',1); -puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',[0 1 2]','Modulation','QPSK','RV',0,'Shortened',0); +ueConfig=struct('NCellID',1,'NULRB',25,'NSubframe',4,'RNTI',82,'CyclicPrefixUL','Normal','NTxAnts',1); +puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',[21:24]','Modulation','QPSK','RV',0,'Shortened',0); addpath('../../debug/lte/phy/lib/phch/test') @@ -10,7 +10,7 @@ addpath('../../debug/lte/phy/lib/phch/test') % rvs=0; % betas=0:3:11; -TBs=56; +TBs=88; cqilen=0; mods={'QPSK'}; rvs=0;