diff --git a/cuhd/include/srslte/cuhd/cuhd.h b/cuhd/include/srslte/cuhd/cuhd.h index 0547db872..1608eab1e 100644 --- a/cuhd/include/srslte/cuhd/cuhd.h +++ b/cuhd/include/srslte/cuhd/cuhd.h @@ -94,6 +94,10 @@ SRSLTE_API double cuhd_set_tx_freq_offset(void *h, double freq, double offset); +SRSLTE_API void cuhd_get_time(void *h, + time_t *secs, + double *frac_secs); + SRSLTE_API int cuhd_send(void *h, void *data, uint32_t nsamples, diff --git a/cuhd/include/srslte/cuhd/radio_uhd.h b/cuhd/include/srslte/cuhd/radio_uhd.h index 55913120b..a4d219d7c 100644 --- a/cuhd/include/srslte/cuhd/radio_uhd.h +++ b/cuhd/include/srslte/cuhd/radio_uhd.h @@ -43,6 +43,7 @@ namespace srslte { bool init(); bool init(char *args); + void get_time(srslte_timestamp_t *now); bool tx(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); bool rx_now(void *buffer, uint32_t nof_samples, srslte_timestamp_t *rxd_time); bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time); diff --git a/cuhd/lib/cuhd_imp.cpp b/cuhd/lib/cuhd_imp.cpp index d95e13a1b..a0781259e 100644 --- a/cuhd/lib/cuhd_imp.cpp +++ b/cuhd/lib/cuhd_imp.cpp @@ -121,7 +121,7 @@ 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=512"); + handler->usrp = uhd::usrp::multi_usrp::make(_args + ", master_clock_rate=30720000"); // handler->usrp = uhd::usrp::multi_usrp::make(_args + ", master_clock_rate=50000000" + ", num_recv_frames=512"); handler->usrp->set_clock_source("internal"); @@ -273,6 +273,16 @@ double cuhd_set_tx_freq_offset(void *h, double freq, double off) { return handler->usrp->get_tx_freq(); } +void cuhd_get_time(void *h, time_t *secs, double *frac_secs) { + cuhd_handler *handler = static_cast < cuhd_handler * >(h); + uhd::time_spec_t now = handler->usrp->get_time_now(); + if (secs) { + *secs = now.get_full_secs(); + } + if (frac_secs) { + *frac_secs = now.get_frac_secs(); + } +} int cuhd_send(void *h, void *data, uint32_t nsamples, bool blocking) { @@ -305,12 +315,12 @@ int cuhd_send_timed(void *h, } int cuhd_send_timed2(void *h, - void *data, - int nsamples, - time_t secs, - double frac_secs, - bool is_start_of_burst, - bool is_end_of_burst) + void *data, + int nsamples, + time_t secs, + double frac_secs, + bool is_start_of_burst, + bool is_end_of_burst) { cuhd_handler* handler = static_cast(h); uhd::tx_metadata_t md; diff --git a/cuhd/lib/radio_uhd.cc b/cuhd/lib/radio_uhd.cc index 83cdec32d..74b67834b 100644 --- a/cuhd/lib/radio_uhd.cc +++ b/cuhd/lib/radio_uhd.cc @@ -62,6 +62,10 @@ bool radio_uhd::rx_now(void* buffer, uint32_t nof_samples, srslte_timestamp_t* r } } +void radio_uhd::get_time(srslte_timestamp_t *now) { + cuhd_get_time(uhd, &now->full_secs, &now->frac_secs); +} + bool radio_uhd::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) { if (cuhd_send_timed(uhd, buffer, nof_samples, tx_time.full_secs, tx_time.frac_secs) > 0) { diff --git a/srslte/examples/prach_ue.c b/srslte/examples/prach_ue.c index 605f6d8b5..f3504a973 100644 --- a/srslte/examples/prach_ue.c +++ b/srslte/examples/prach_ue.c @@ -285,9 +285,6 @@ int rar_unpack(uint8_t *buffer, rar_msg_t *msg) return(ret); } -#define kk -#define use_usrp - int main(int argc, char **argv) { int ret; srslte_cell_t cell; @@ -308,7 +305,6 @@ int main(int argc, char **argv) { parse_args(&prog_args, argc, argv); -#ifdef use_usrp printf("Opening UHD device...\n"); if (cuhd_open(prog_args.uhd_args, &uhd)) { fprintf(stderr, "Error opening uhd\n"); @@ -329,9 +325,7 @@ int main(int argc, char **argv) { 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); -#endif -#ifdef kk ret = cuhd_search_and_decode_mib(uhd, &cell_detect_config, prog_args.force_N_id_2, &cell); if (ret < 0) { fprintf(stderr, "Error searching for cell\n"); @@ -340,16 +334,6 @@ int main(int argc, char **argv) { printf("Cell not found\n"); exit(0); } -#else - cell.id = 1; - cell.nof_ports = 1; - cell.nof_prb = 25; - cell.cp = SRSLTE_CP_NORM; - cell.phich_length = SRSLTE_PHICH_NORM; - cell.phich_resources = SRSLTE_PHICH_R_1; -#endif - -#ifdef use_usrp /* set sampling frequency */ int srate = srslte_sampling_freq_hz(cell.nof_prb); @@ -365,7 +349,6 @@ int main(int argc, char **argv) { cuhd_stop_rx_stream(uhd); cuhd_flush_buffer(uhd); -#endif if (srslte_ue_mib_init(&ue_mib, cell)) { fprintf(stderr, "Error initaiting UE MIB decoder\n"); @@ -392,6 +375,8 @@ int main(int argc, char **argv) { exit(-1); } + srslte_ue_ul_set_cfo_enable(&ue_ul, true); + srslte_pusch_hopping_cfg_t hop_cfg; bzero(&hop_cfg, sizeof(srslte_pusch_hopping_cfg_t)); srslte_refsignal_drms_pusch_cfg_t drms_cfg; @@ -421,39 +406,28 @@ int main(int argc, char **argv) { sf_cnt = 0; -#ifdef use_usrp if (srslte_ue_sync_init(&ue_sync, cell, cuhd_recv_wrapper_timed, uhd)) { fprintf(stderr, "Error initiating ue_sync\n"); exit(-1); } cuhd_start_rx_stream(uhd); -#endif uint16_t ra_rnti; uint32_t conn_setup_trial = 0; uint32_t ul_sf_idx = 0; -#ifdef kk // Register Ctrl+C handler signal(SIGINT, sig_int_handler); state = DECODE_MIB; -#else - state = RECV_RAR; -#endif + /* Main loop */ while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) { -#ifdef kk ret = srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer); if (ret < 0) { fprintf(stderr, "Error calling srslte_ue_sync_work()\n"); } -#else - ret = 1; - srslte_timestamp_t rx_time, tx_time; - cf_t dummy[4]; -#endif - + /* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */ if (ret == 1) { @@ -485,7 +459,6 @@ int main(int argc, char **argv) { break; case SEND_PRACH: - #ifdef kk if (((sfn%2) == 1) && (srslte_ue_sync_get_sfidx(&ue_sync) == 1)) { srslte_ue_sync_get_last_timestamp(&ue_sync, &uhd_time); @@ -497,27 +470,15 @@ int main(int argc, char **argv) { cuhd_send_timed(uhd, prach_buffer, prach_buffer_len, next_tx_time.full_secs, next_tx_time.frac_secs); + srslte_vec_save_file("prach_ue", prach_buffer, prach_buffer_len*sizeof(cf_t)); + ra_rnti = 2; rar_window_start = sfn+1; rar_window_stop = sfn+3; state = RECV_RAR; } - #else - cuhd_recv_with_time(uhd, dummy, 4, 1, &rx_time.full_secs, &rx_time.frac_secs); - - srslte_timestamp_copy(&tx_time, &rx_time); - printf("Transmitting PRACH...\n"); - srslte_vec_save_file("srslte_prach_tx", prach_buffers[7], prach_buffer_len*sizeof(cf_t)); - while(1) { - srslte_timestamp_add(&tx_time, 0, 0.001); // send every (10 ms) - cuhd_send_timed(uhd, prach_buffers[7], prach_buffer_len, - tx_time.full_secs, tx_time.frac_secs); - - } - #endif break; case RECV_RAR: - #ifdef kk if ((sfn == rar_window_start && srslte_ue_sync_get_sfidx(&ue_sync) > 3) || sfn > rar_window_start) { printf("Looking for RAR in sfn: %d sf_idx: %d\n", sfn, srslte_ue_sync_get_sfidx(&ue_sync)); @@ -527,58 +488,55 @@ int main(int argc, char **argv) { } else if (n > 0) { rar_unpack(data_rx, &rar_msg); - //if (rar_msg.RAPID != prog_args.preamble_idx) { - // printf("Found RAR for sequence %d\n", rar_msg.RAPID); - //} else { - //cuhd_stop_rx_stream(uhd); - //cuhd_flush_buffer(uhd); - rar_msg_fprint(stdout, &rar_msg); - - srslte_dci_rar_to_ra_ul(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, cell.nof_prb, &ra_pusch); - srslte_ra_pusch_fprint(stdout, &ra_pusch, cell.nof_prb); + rar_msg_fprint(stdout, &rar_msg); + + srslte_dci_rar_to_ra_ul(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, cell.nof_prb, &ra_pusch); + srslte_ra_pusch_fprint(stdout, &ra_pusch, cell.nof_prb); - srslte_ra_ul_alloc(&ra_pusch.prb_alloc, &ra_pusch, 0, cell.nof_prb); + srslte_ra_ul_alloc(&ra_pusch.prb_alloc, &ra_pusch, 0, cell.nof_prb); - srslte_ue_sync_get_last_timestamp(&ue_sync, &uhd_time); - - srslte_bit_pack_vector((uint8_t*) conn_request_msg, data, ra_pusch.mcs.tbs); + srslte_ue_sync_get_last_timestamp(&ue_sync, &uhd_time); + + srslte_bit_pack_vector((uint8_t*) conn_request_msg, data, ra_pusch.mcs.tbs); - uint32_t n_ta = srslte_N_ta_new_rar(rar_msg.timing_adv_cmd); - printf("ta: %d, n_ta: %d\n", rar_msg.timing_adv_cmd, n_ta); - float time_adv_sec = SRSLTE_TA_OFFSET+((float) n_ta)*SRSLTE_LTE_TS; - if (prog_args.ta_usec >= 0) { - time_adv_sec = prog_args.ta_usec*1e-6; + uint32_t n_ta = srslte_N_ta_new_rar(rar_msg.timing_adv_cmd); + printf("ta: %d, n_ta: %d\n", rar_msg.timing_adv_cmd, n_ta); + float time_adv_sec = SRSLTE_TA_OFFSET+((float) n_ta)*SRSLTE_LTE_TS; + if (prog_args.ta_usec >= 0) { + time_adv_sec = prog_args.ta_usec*1e-6; + } +#define N_TX 1 + const uint32_t rv[N_TX]={0}; + for (int i=0; i 0) { printf("Received ConnectionSetup len: %d.\n", n); srslte_vec_fprint_hex(stdout, data_rx, n); + exit(0); } else { conn_setup_trial++; if (conn_setup_trial == 20) { diff --git a/srslte/include/srslte/common/radio.h b/srslte/include/srslte/common/radio.h index 0a5ee9770..934a97923 100644 --- a/srslte/include/srslte/common/radio.h +++ b/srslte/include/srslte/common/radio.h @@ -40,6 +40,7 @@ namespace srslte { class SRSLTE_API radio { public: + virtual void get_time(srslte_timestamp_t *now) = 0; virtual bool tx(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) = 0; virtual bool rx_now(void *buffer, uint32_t nof_samples, srslte_timestamp_t *rxd_time) = 0; virtual bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time) = 0; diff --git a/srslte/include/srslte/phch/phich.h b/srslte/include/srslte/phch/phich.h index 58828e962..e1fbd4067 100644 --- a/srslte/include/srslte/phch/phich.h +++ b/srslte/include/srslte/phch/phich.h @@ -41,7 +41,7 @@ #include "srslte/mimo/precoding.h" #include "srslte/mimo/layermap.h" #include "srslte/modem/mod.h" -#include "srslte/modem/demod_hard.h" +#include "srslte/modem/demod_soft.h" #include "srslte/scrambling/scrambling.h" #include "regs.h" @@ -59,11 +59,6 @@ #define SRSLTE_PHICH_NORM_NSF 4 #define SRSLTE_PHICH_EXT_NSF 2 -typedef struct SRSLTE_API { - uint32_t ngroup; - uint32_t nseq; -}srslte_phich_alloc_t; - /* phich object */ typedef struct SRSLTE_API { srslte_cell_t cell; @@ -81,10 +76,11 @@ typedef struct SRSLTE_API { /* bit message */ uint8_t data[SRSLTE_PHICH_NBITS]; + float data_rx[SRSLTE_PHICH_NBITS]; /* tx & rx objects */ srslte_modem_table_t mod; - srslte_demod_hard_t demod; + srslte_demod_soft_t demod; srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; srslte_precoding_t precoding; @@ -104,7 +100,7 @@ SRSLTE_API int srslte_phich_decode(srslte_phich_t *q, uint32_t nseq, uint32_t nsubframe, uint8_t *ack, - uint32_t *distance); + float *distance); SRSLTE_API int srslte_phich_encode(srslte_phich_t *q, uint8_t ack, @@ -118,4 +114,6 @@ SRSLTE_API void srslte_phich_reset(srslte_phich_t *q, SRSLTE_API uint32_t srslte_phich_ngroups(srslte_phich_t *q); +SRSLTE_API uint32_t srslte_phich_nsf(srslte_phich_t *q); + #endif // PHICH_ diff --git a/srslte/include/srslte/phch/ra.h b/srslte/include/srslte/phch/ra.h index 35ff4cd47..223f51fc8 100644 --- a/srslte/include/srslte/phch/ra.h +++ b/srslte/include/srslte/phch/ra.h @@ -130,6 +130,8 @@ typedef struct SRSLTE_API { srslte_ra_mcs_t mcs; uint32_t rv_idx; // If set to non-zero, a retransmission is requested with the same modulation // than before (SRSLTE_DCI_FORMAT0 message, see also 8.6.1 in 36.2313). + + uint32_t n_dmrs; bool ndi; bool cqi_request; diff --git a/srslte/include/srslte/sync/sync.h b/srslte/include/srslte/sync/sync.h index 697645aae..a21901ccc 100644 --- a/srslte/include/srslte/sync/sync.h +++ b/srslte/include/srslte/sync/sync.h @@ -137,6 +137,9 @@ SRSLTE_API int srslte_sync_get_cell_id(srslte_sync_t *q); /* Gets the CFO estimation from the last call to synch_run() */ SRSLTE_API float srslte_sync_get_cfo(srslte_sync_t *q); +/* Sets known CFO to avoid long transients due to average */ +SRSLTE_API void srslte_sync_set_cfo(srslte_sync_t *q, float cfo); + /* Gets the CP length estimation from the last call to synch_run() */ SRSLTE_API srslte_cp_t srslte_sync_get_cp(srslte_sync_t *q); diff --git a/srslte/include/srslte/ue/ue_cell_search.h b/srslte/include/srslte/ue/ue_cell_search.h index 3b37d21b4..adb64d416 100644 --- a/srslte/include/srslte/ue/ue_cell_search.h +++ b/srslte/include/srslte/ue/ue_cell_search.h @@ -73,6 +73,7 @@ typedef struct SRSLTE_API { float peak; float mode; float psr; + float cfo; } srslte_ue_cellsearch_result_t; diff --git a/srslte/include/srslte/ue/ue_dl.h b/srslte/include/srslte/ue/ue_dl.h index 57658898a..99540f371 100644 --- a/srslte/include/srslte/ue/ue_dl.h +++ b/srslte/include/srslte/ue/ue_dl.h @@ -39,6 +39,8 @@ #ifndef UEDL_H #define UEDL_H +#include + #include "srslte/ch_estimation/chest_dl.h" #include "srslte/dft/ofdm.h" #include "srslte/common/phy_common.h" @@ -62,6 +64,7 @@ typedef struct SRSLTE_API { srslte_pcfich_t pcfich; srslte_pdcch_t pdcch; srslte_pdsch_t pdsch; + srslte_phich_t phich; srslte_harq_t harq_process[SRSLTE_UE_UL_NOF_HARQ_PROCESSES]; srslte_regs_t regs; srslte_ofdm_t fft; @@ -132,6 +135,11 @@ SRSLTE_API int srslte_ue_dl_decode_rnti_rv(srslte_ue_dl_t * q, uint16_t rnti, uint32_t rvidx); +SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, + uint32_t sf_idx, + uint32_t n_prb_lowest, + uint32_t n_dmrs); + SRSLTE_API void srslte_ue_dl_reset(srslte_ue_dl_t *q); SRSLTE_API void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q, diff --git a/srslte/include/srslte/ue/ue_phy.h b/srslte/include/srslte/ue/ue_phy.h index c1b9e950c..26d513f2b 100644 --- a/srslte/include/srslte/ue/ue_phy.h +++ b/srslte/include/srslte/ue/ue_phy.h @@ -112,7 +112,7 @@ public: dl_buffer(srslte_cell_t cell); sched_grant get_ul_grant(pdcch_ul_search_t mode, uint32_t rnti); sched_grant get_dl_grant(pdcch_dl_search_t mode, uint32_t rnti); - bool decode_phich(srslte_phich_alloc_t assignment); + bool decode_phich(sched_grant pusch_grant); bool decode_pdsch(sched_grant pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/KO private: srslte_ue_dl_t ue_dl; diff --git a/srslte/include/srslte/ue/ue_sync.h b/srslte/include/srslte/ue/ue_sync.h index 7fc8573ed..c4fd312e6 100644 --- a/srslte/include/srslte/ue/ue_sync.h +++ b/srslte/include/srslte/ue/ue_sync.h @@ -128,6 +128,9 @@ 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_cfo(srslte_ue_sync_t *q, + float cfo); + SRSLTE_API void srslte_ue_sync_reset(srslte_ue_sync_t *q); SRSLTE_API void srslte_ue_sync_set_N_id_2(srslte_ue_sync_t *q, diff --git a/srslte/include/srslte/ue/ue_ul.h b/srslte/include/srslte/ue/ue_ul.h index 1eb8275f4..75aee63ec 100644 --- a/srslte/include/srslte/ue/ue_ul.h +++ b/srslte/include/srslte/ue/ue_ul.h @@ -59,6 +59,7 @@ typedef struct SRSLTE_API { srslte_cell_t cell; bool normalize_en; + bool cfo_en; float current_cfo; @@ -83,6 +84,9 @@ SRSLTE_API void srslte_ue_ul_free(srslte_ue_ul_t *q); SRSLTE_API void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q, float cur_cfo); +SRSLTE_API void srslte_ue_ul_set_cfo_enable(srslte_ue_ul_t *q, + bool enabled); + SRSLTE_API void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q, bool enabled); diff --git a/srslte/include/srslte/ue_itf/dl_buffer.h b/srslte/include/srslte/ue_itf/dl_buffer.h index 44839dfa3..e4bcbe3be 100644 --- a/srslte/include/srslte/ue_itf/dl_buffer.h +++ b/srslte/include/srslte/ue_itf/dl_buffer.h @@ -66,7 +66,7 @@ namespace ue { bool recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time); bool get_ul_grant(pdcch_ul_search_t mode, sched_grant *grant); bool get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant); - bool decode_phich(srslte_phich_alloc_t assignment); + bool decode_phich(srslte::ue::sched_grant pusch_grant); bool decode_pdsch(sched_grant pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/KO private: params *params_db; diff --git a/srslte/include/srslte/ue_itf/phy.h b/srslte/include/srslte/ue_itf/phy.h index dab348548..32352b729 100644 --- a/srslte/include/srslte/ue_itf/phy.h +++ b/srslte/include/srslte/ue_itf/phy.h @@ -75,6 +75,9 @@ public: // Indicate the PHY to send PRACH as soon as possible bool send_prach(uint32_t preamble_idx); + + // Returns TTI when PRACH was transmitted. -1 if not yet transmitted + int get_prach_transmitted_tti(); // Get handler to the radio radio* get_radio(); @@ -125,12 +128,15 @@ private: pthread_t phy_thread; float time_adv_sec; uint32_t n_ta; + bool radio_is_streaming; + srslte_timestamp_t last_rx_time; + float cellsearch_cfo; static void *phy_thread_fnc(void *arg); bool decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell, uint8_t payload[SRSLTE_BCH_PAYLOAD_LEN]); int sync_sfn(); void run_rx_tx_state(); bool init_radio_handler(char *args); - + ul_buffer* get_ul_buffer_adv(uint32_t tti); }; } diff --git a/srslte/include/srslte/ue_itf/prach.h b/srslte/include/srslte/ue_itf/prach.h index 7527578b1..b05055452 100644 --- a/srslte/include/srslte/ue_itf/prach.h +++ b/srslte/include/srslte/ue_itf/prach.h @@ -26,6 +26,7 @@ */ #include "srslte/srslte.h" +#include "srslte/common/radio.h" #include "srslte/ue_itf/queue.h" #include "srslte/ue_itf/params.h" @@ -41,7 +42,8 @@ namespace ue { void free_cell(); bool prepare_to_send(uint32_t preamble_idx); bool is_ready_to_send(uint32_t current_tti); - bool send(void *radio_handler, srslte_timestamp_t rx_time); + int get_transmitted_tti(); + bool send(srslte::radio* radio_handler, float cfo, srslte_timestamp_t rx_time); private: static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission params *params_db = NULL; @@ -50,6 +52,10 @@ namespace ue { uint32_t len; cf_t *buffer[64]; srslte_prach_t prach; + uint32_t transmitted_tti; + srslte_cell_t cell; + cf_t *signal_buffer; + srslte_cfo_t cfo_h; }; } diff --git a/srslte/include/srslte/ue_itf/sched_grant.h b/srslte/include/srslte/ue_itf/sched_grant.h index e54dd9b0c..825bba1f7 100644 --- a/srslte/include/srslte/ue_itf/sched_grant.h +++ b/srslte/include/srslte/ue_itf/sched_grant.h @@ -50,11 +50,14 @@ namespace ue { bool is_downlink(); void* get_grant_ptr(); uint32_t get_tbs(); + uint32_t get_current_tx_nb(); + void set_current_tx_nb(uint32_t current_tx_nb); protected: union { srslte_ra_pusch_t ul_grant; srslte_ra_pdsch_t dl_grant; }; + uint32_t current_tx_nb; direction_t dir; uint16_t rnti; }; diff --git a/srslte/include/srslte/ue_itf/ul_buffer.h b/srslte/include/srslte/ue_itf/ul_buffer.h index 795e0092f..81d645d3f 100644 --- a/srslte/include/srslte/ue_itf/ul_buffer.h +++ b/srslte/include/srslte/ue_itf/ul_buffer.h @@ -51,7 +51,7 @@ namespace ue { bool generate_pusch(sched_grant pusch_grant, uint8_t *payload); bool generate_pusch(sched_grant pusch_grant, uint8_t *payload, srslte_uci_data_t uci_data); bool generate_pucch(srslte_uci_data_t uci_data); - bool send_packet(radio* radio_handler, float time_adv_sec, srslte_timestamp_t rx_time); + bool send(radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time); static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission private: diff --git a/srslte/lib/phch/src/dci.c b/srslte/lib/phch/src/dci.c index 44ef83d72..f0848b506 100644 --- a/srslte/lib/phch/src/dci.c +++ b/srslte/lib/phch/src/dci.c @@ -92,8 +92,10 @@ int srslte_dci_msg_to_ra_dl(srslte_dci_msg_t *msg, uint16_t msg_rnti, ret = SRSLTE_SUCCESS; } else { - fprintf(stderr, "Unsupported message type: "); - srslte_dci_msg_type_fprint(stderr, type); + if (SRSLTE_VERBOSE_ISINFO()) { + fprintf(stderr, "Unsupported message type: "); + srslte_dci_msg_type_fprint(stderr, type); + } } } return ret; @@ -375,9 +377,10 @@ int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_pusch_t *data, uint32_t data->ndi = *y++ ? true : false; - // TCP and DM RS commands not implemented + // TPC and DM RS commands not implemented y += 5; - + data->n_dmrs = 0; + // CQI request data->cqi_request = *y++ ? true : false; diff --git a/srslte/lib/phch/src/phich.c b/srslte/lib/phch/src/phich.c index feb02d7a0..331c48c76 100644 --- a/srslte/lib/phch/src/phich.c +++ b/srslte/lib/phch/src/phich.c @@ -53,6 +53,14 @@ uint32_t srslte_phich_ngroups(srslte_phich_t *q) { return srslte_regs_phich_ngroups(q->regs); } +uint32_t srslte_phich_nsf(srslte_phich_t *q) { + if (SRSLTE_CP_ISNORM(q->cell.cp)) { + return SRSLTE_PHICH_NORM_NSF; + } else { + return SRSLTE_PHICH_EXT_NSF; + } +} + void srslte_phich_reset(srslte_phich_t *q, cf_t *slot_symbols[SRSLTE_MAX_PORTS]) { int i; for (i = 0; i < SRSLTE_MAX_PORTS; i++) { @@ -79,12 +87,13 @@ int srslte_phich_init(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell fprintf(stderr, "Error initializing precoding\n"); } - if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_BPSK, false)) { + if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_BPSK, true)) { goto clean; } - srslte_demod_hard_init(&q->demod); - srslte_demod_hard_table_set(&q->demod, SRSLTE_MOD_BPSK); + srslte_demod_soft_init(&q->demod, SRSLTE_PHICH_MAX_NSYMB); + srslte_demod_soft_table_set(&q->demod, &q->mod); + srslte_demod_soft_alg_set(&q->demod, SRSLTE_DEMOD_SOFT_ALG_APPROX); for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) { if (srslte_sequence_phich(&q->seq[nsf], 2 * nsf, q->cell.id)) { @@ -114,25 +123,29 @@ void srslte_phich_free(srslte_phich_t *q) { /* Decodes ACK * */ -uint8_t srslte_phich_ack_decode(uint8_t bits[SRSLTE_PHICH_NBITS], uint32_t *distance) { - int i, n; - - n = 0; - for (i = 0; i < SRSLTE_PHICH_NBITS; i++) { - n += bits[i]; +uint8_t srslte_phich_ack_decode(float bits[SRSLTE_PHICH_NBITS], float *distance) { + int i; + float ack_table[2][3] = {{-1.0, -1.0, -1.0}, {1.0, 1.0, 1.0}}; + float max_corr = -9999; + uint8_t index=0; + + if (SRSLTE_VERBOSE_ISINFO()) { + INFO("Received bits: ", 0); + srslte_vec_fprint_f(stdout, bits, SRSLTE_PHICH_NBITS); } - INFO("PHICH decoder: %d, %d, %d\n", bits[0], bits[1], bits[2]); - if (n >= 2) { - if (distance) { - *distance = 3 - n; - } - return 1; - } else { - if (distance) { - *distance = n; + + for (i = 0; i < 2; i++) { + float corr = srslte_vec_dot_prod_fff(ack_table[i], bits, SRSLTE_PHICH_NBITS); + INFO("Corr%d=%f\n", i, corr); + if (corr > max_corr) { + max_corr = corr; + if (distance) { + *distance = max_corr; + } + index = i; } - return 0; - } + } + return index; } /** Encodes the ACK @@ -147,7 +160,7 @@ void srslte_phich_ack_encode(uint8_t ack, uint8_t bits[SRSLTE_PHICH_NBITS]) { * Returns 1 if successfully decoded the CFI, 0 if not and -1 on error */ int srslte_phich_decode(srslte_phich_t *q, cf_t *slot_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate, - uint32_t ngroup, uint32_t nseq, uint32_t subframe, uint8_t *ack, uint32_t *distance) { + uint32_t ngroup, uint32_t nseq, uint32_t subframe, uint8_t *ack, float *distance) { /* Set pointers for layermapping & precoding */ int i, j; @@ -265,10 +278,10 @@ int srslte_phich_decode(srslte_phich_t *q, cf_t *slot_symbols, cf_t *ce[SRSLTE_M if (SRSLTE_VERBOSE_ISDEBUG()) srslte_vec_fprint_c(stdout, q->z, SRSLTE_PHICH_NBITS); - srslte_demod_hard_demodulate(&q->demod, q->z, q->data, SRSLTE_PHICH_NBITS); + srslte_demod_soft_demodulate(&q->demod, q->z, q->data_rx, SRSLTE_PHICH_NBITS); if (ack) { - *ack = srslte_phich_ack_decode(q->data, distance); + *ack = srslte_phich_ack_decode(q->data_rx, distance); } return SRSLTE_SUCCESS; diff --git a/srslte/lib/phch/src/prach.c b/srslte/lib/phch/src/prach.c index 86cc4e0cc..8d8875d99 100644 --- a/srslte/lib/phch/src/prach.c +++ b/srslte/lib/phch/src/prach.c @@ -44,6 +44,7 @@ #define PHI_4 2 // PRACH phi parameter for format 4 #define MAX_ROOTS 838 // Max number of root sequences +#define PRACH_AMP 0.5 /****************************************************** * Reference tables from 3GPP TS 36.211 v10.7.0 @@ -357,14 +358,14 @@ int srslte_prach_init(srslte_prach_t *p, return SRSLTE_ERROR; } srslte_dft_plan_set_mirror(p->zc_fft, false); - srslte_dft_plan_set_norm(p->zc_fft, false); + srslte_dft_plan_set_norm(p->zc_fft, true); p->zc_ifft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t)); if(srslte_dft_plan(p->zc_ifft, p->N_zc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)){ return SRSLTE_ERROR; } srslte_dft_plan_set_mirror(p->zc_ifft, false); - srslte_dft_plan_set_norm(p->zc_ifft, false); + srslte_dft_plan_set_norm(p->zc_ifft, true); // Generate our 64 sequences p->N_roots = 0; @@ -437,7 +438,7 @@ int srslte_prach_gen(srslte_prach_t *p, // Copy preamble sequence into buffer for(int i=0;iN_seq;i++){ - signal[p->N_cp+i] = p->ifft_out[i%p->N_ifft_prach]; + signal[p->N_cp+i] = PRACH_AMP*p->ifft_out[i%p->N_ifft_prach]; } ret = SRSLTE_SUCCESS; diff --git a/srslte/lib/phch/test/phich_file_test.c b/srslte/lib/phch/test/phich_file_test.c index c9be43a09..43af61a75 100644 --- a/srslte/lib/phch/test/phich_file_test.c +++ b/srslte/lib/phch/test/phich_file_test.c @@ -214,7 +214,7 @@ void base_free() { } int main(int argc, char **argv) { - uint32_t distance; + float distance; int n; uint32_t ngroup, nseq, max_nseq; uint8_t ack_rx; diff --git a/srslte/lib/phch/test/phich_test.c b/srslte/lib/phch/test/phich_test.c index d001a0407..c93d488ca 100644 --- a/srslte/lib/phch/test/phich_test.c +++ b/srslte/lib/phch/test/phich_test.c @@ -108,7 +108,8 @@ int main(int argc, char **argv) { int nof_re; cf_t *slot_symbols[SRSLTE_MAX_PORTS]; uint8_t ack[50][SRSLTE_PHICH_NORM_NSEQUENCES], ack_rx; - uint32_t nsf, distance; + uint32_t nsf; + float distance; int cid, max_cid; uint32_t ngroup, nseq, max_nseq; diff --git a/srslte/lib/sync/src/sync.c b/srslte/lib/sync/src/sync.c index 8c0074e6f..4ee0ebb1b 100644 --- a/srslte/lib/sync/src/sync.c +++ b/srslte/lib/sync/src/sync.c @@ -144,6 +144,10 @@ float srslte_sync_get_cfo(srslte_sync_t *q) { return q->mean_cfo; } +void srslte_sync_set_cfo(srslte_sync_t *q, float cfo) { + q->mean_cfo = cfo; +} + float srslte_sync_get_last_peak_value(srslte_sync_t *q) { return q->peak_value; } @@ -313,7 +317,7 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32 // Make sure we have enough space to estimate CFO if (peak_pos + find_offset >= q->fft_size) { float cfo = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset+peak_pos-q->fft_size]); - + /* compute cumulative moving average CFO */ q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, CFO_EMA_ALPHA); } else { diff --git a/srslte/lib/ue/src/ue_cell_search.c b/srslte/lib/ue/src/ue_cell_search.c index 272c27bac..e09b39a8f 100644 --- a/srslte/lib/ue/src/ue_cell_search.c +++ b/srslte/lib/ue/src/ue_cell_search.c @@ -175,6 +175,9 @@ static void get_cell(srslte_ue_cellsearch_t * q, uint32_t nof_detected_frames, s // PSR is already averaged so take the last value found_cell->psr = q->candidates[nof_detected_frames-1].psr; + + // CFO is also already averaged + found_cell->cfo = q->candidates[nof_detected_frames-1].cfo; } /** Finds up to 3 cells, one per each N_id_2=0,1,2 and stores ID and CP in the structure pointed by found_cell. @@ -235,6 +238,7 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q, uint32_t N_id_2 q->candidates[nof_detected_frames].cp = srslte_sync_get_cp(&q->ue_sync.strack); q->candidates[nof_detected_frames].peak = q->ue_sync.strack.pss.peak_value; q->candidates[nof_detected_frames].psr = srslte_sync_get_peak_value(&q->ue_sync.strack); + q->candidates[nof_detected_frames].cfo = srslte_ue_sync_get_cfo(&q->ue_sync); INFO ("CELL SEARCH: [%3d/%3d/%d]: Found peak PSR=%.3f, Cell_id: %d CP: %s\n", nof_detected_frames, nof_scanned_frames, q->nof_frames_to_scan, diff --git a/srslte/lib/ue/src/ue_dl.c b/srslte/lib/ue/src/ue_dl.c index 0393c1938..dda5fd843 100644 --- a/srslte/lib/ue/src/ue_dl.c +++ b/srslte/lib/ue/src/ue_dl.c @@ -70,6 +70,10 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q, fprintf(stderr, "Error creating PCFICH object\n"); goto clean_exit; } + if (srslte_phich_init(&q->phich, &q->regs, q->cell)) { + fprintf(stderr, "Error creating PHICH object\n"); + goto clean_exit; + } if (srslte_pdcch_init(&q->pdcch, &q->regs, q->cell)) { fprintf(stderr, "Error creating PDCCH object\n"); @@ -118,6 +122,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) { srslte_chest_dl_free(&q->chest); srslte_regs_free(&q->regs); srslte_pcfich_free(&q->pcfich); + srslte_phich_free(&q->phich); srslte_pdcch_free(&q->pdcch); srslte_pdsch_free(&q->pdsch); for (uint32_t i=0;iphich); + uint32_t ngroup = (n_prb_lowest+n_dmrs)%Ngroups; + uint32_t nseq = ((n_prb_lowest/Ngroups)+n_dmrs)%(2*srslte_phich_nsf(&q->phich)); + INFO("Decoding PHICH sf_idx=%d, n_prb_lowest=%d, n_dmrs=%d, n_group=%d, n_seq=%d\n", + sf_idx, n_prb_lowest, n_dmrs, ngroup, nseq); + if (!srslte_phich_decode(&q->phich, q->sf_symbols, q->ce, 0, ngroup, nseq, sf_idx, &ack_bit, &distance)) { + INFO("Decoded PHICH %d with distance %f\n", ack_bit, distance); + } else { + fprintf(stderr, "Error decoding PHICH\n"); + return false; + } + if (ack_bit && distance > 5.0) { + return true; + } else { + return false; + } +} + + + diff --git a/srslte/lib/ue/src/ue_sync.c b/srslte/lib/ue/src/ue_sync.c index 0e1ff1689..955106254 100644 --- a/srslte/lib/ue/src/ue_sync.c +++ b/srslte/lib/ue/src/ue_sync.c @@ -221,6 +221,10 @@ float srslte_ue_sync_get_cfo(srslte_ue_sync_t *q) { return 15000 * srslte_sync_get_cfo(&q->strack); } +void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, float cfo) { + srslte_sync_set_cfo(&q->strack, cfo/15000); +} + float srslte_ue_sync_get_sfo(srslte_ue_sync_t *q) { return 5000*q->mean_time_offset; } @@ -266,9 +270,6 @@ static int find_peak_ok(srslte_ue_sync_t *q) { q->frame_find_cnt = 0; q->mean_time_offset = 0; - /* Set tracking CFO average to find CFO */ - q->strack.mean_cfo = q->sfind.mean_cfo; - /* Goto Tracking state */ q->state = SF_TRACK; } @@ -455,13 +456,6 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) { -srslte_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/srslte/lib/ue/src/ue_ul.c b/srslte/lib/ue/src/ue_ul.c index 4feb7eff1..012bbb2fc 100644 --- a/srslte/lib/ue/src/ue_ul.c +++ b/srslte/lib/ue/src/ue_ul.c @@ -128,6 +128,11 @@ void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q, float cur_cfo) { q->current_cfo = cur_cfo; } +void srslte_ue_ul_set_cfo_enable(srslte_ue_ul_t *q, bool enabled) +{ + q->cfo_en = enabled; +} + void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q, bool enabled) { q->normalize_en = enabled; @@ -194,7 +199,7 @@ int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ fprintf(stderr, "Error configuring HARQ process\n"); return ret; } - printf("sf_idx: %d, rnti: %d\n", sf_idx, rnti); + if (srslte_pusch_encode_rnti(&q->pusch, &q->harq_process[0], data, rnti, q->sf_symbols)) { fprintf(stderr, "Error encoding TB\n"); return ret; @@ -214,7 +219,9 @@ int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); - //srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); + if (q->cfo_en) { + srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); + } if (q->normalize_en) { float norm_factor = (float) q->cell.nof_prb/10/sqrtf(q->harq_process[0].ul_alloc.L_prb); diff --git a/srslte/lib/ue_itf/src/dl_buffer.cc b/srslte/lib/ue_itf/src/dl_buffer.cc index 51163ec02..4d372ec98 100644 --- a/srslte/lib/ue_itf/src/dl_buffer.cc +++ b/srslte/lib/ue_itf/src/dl_buffer.cc @@ -65,20 +65,20 @@ void dl_buffer::free_cell() // FIXME: Avoid this memcpy modifying ue_sync to directly write into provided pointer bool dl_buffer::recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time) { + bool ret = false; if (signal_buffer) { INFO("DL Buffer TTI %d: Receiving packet\n", tti); cf_t *sf_buffer = NULL; + sf_symbols_and_ce_done = false; + pdcch_llr_extracted = false; if (srslte_ue_sync_get_buffer(ue_sync, &sf_buffer) == 1) { memcpy(signal_buffer, sf_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); - srslte_ue_sync_get_last_timestamp(ue_sync, rx_time); - sf_symbols_and_ce_done = false; - pdcch_llr_extracted = false; ready(); - return true; - } else { - return false; - } + ret = true; + } + srslte_ue_sync_get_last_timestamp(ue_sync, rx_time); } + return ret; } bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, sched_grant *grant) @@ -154,7 +154,7 @@ bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant) } } -bool dl_buffer::decode_phich(srslte_phich_alloc_t assignment) +bool dl_buffer::decode_phich(sched_grant pusch_grant) { if (signal_buffer && is_ready()) { if (!sf_symbols_and_ce_done) { @@ -163,7 +163,10 @@ bool dl_buffer::decode_phich(srslte_phich_alloc_t assignment) } sf_symbols_and_ce_done = true; } - return false; + + srslte_ra_pusch_t *ra_ul = (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr(); + + return srslte_ue_dl_decode_phich(&ue_dl, tti%10, ra_ul->prb_alloc.n_prb[0], ra_ul->n_dmrs); } } diff --git a/srslte/lib/ue_itf/src/phy.cc b/srslte/lib/ue_itf/src/phy.cc index f272d19a4..816fa3f15 100644 --- a/srslte/lib/ue_itf/src/phy.cc +++ b/srslte/lib/ue_itf/src/phy.cc @@ -53,12 +53,19 @@ bool phy::init(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_) params_db.set_param(params::CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD, 160); params_db.set_param(params::CELLSEARCH_TIMEOUT_MIB_NFRAMES, 100); - if (!pthread_create(&phy_thread, NULL, phy_thread_fnc, this)) { + pthread_attr_t attr; + struct sched_param param; + param.sched_priority = 99; + + pthread_attr_init(&attr); + pthread_attr_setschedpolicy(&attr, SCHED_FIFO); + pthread_attr_setschedparam(&attr, ¶m); + if (!pthread_create(&phy_thread, &attr, phy_thread_fnc, this)) { started = true; } else { perror("pthread_create"); } - + pthread_attr_destroy(&attr); return started; } @@ -120,6 +127,11 @@ bool phy::send_prach(uint32_t preamble_idx) return false; } +int phy::get_prach_transmitted_tti() +{ + return prach_buffer.get_transmitted_tti(); +} + // Do fast measurement on RSSI and/or PSS autocorrelation energy or PSR bool phy::measure() { @@ -134,11 +146,9 @@ bool phy::start_rxtx() if (phy_state == IDLE) { if (cell_is_set) { // Set RX/TX sampling rate - radio_handler->set_rx_srate(srslte_sampling_freq_hz(cell.nof_prb)); - radio_handler->set_tx_srate(srslte_sampling_freq_hz(cell.nof_prb)); + radio_handler->set_rx_srate((float) srslte_sampling_freq_hz(cell.nof_prb)); + radio_handler->set_tx_srate((float) srslte_sampling_freq_hz(cell.nof_prb)); - // Start streaming - radio_handler->start_rx(); phy_state = RXTX; return true; } else { @@ -202,6 +212,8 @@ bool phy::set_cell(srslte_cell_t cell_) { { if (!srslte_ue_sync_init(&ue_sync, cell, radio_recv_wrapper_cs, radio_handler)) { + + srslte_ue_sync_set_cfo(&ue_sync, cellsearch_cfo); if (prach_buffer.init_cell(cell, ¶ms_db)) { for(uint32_t i=0;i<6;i++) { ((ul_buffer*) ul_buffer_queue->get(i))->init_cell(cell, ¶ms_db); @@ -226,7 +238,12 @@ bool phy::set_cell(srslte_cell_t cell_) { ul_buffer* phy::get_ul_buffer(uint32_t tti) { - return (ul_buffer*) ul_buffer_queue->get(tti - ul_buffer::tx_advance_sf); + return (ul_buffer*) ul_buffer_queue->get(tti); +} + +ul_buffer* phy::get_ul_buffer_adv(uint32_t tti) +{ + return (ul_buffer*) ul_buffer_queue->get(tti + ul_buffer::tx_advance_sf); } dl_buffer* phy::get_dl_buffer(uint32_t tti) @@ -284,8 +301,9 @@ bool phy::decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell_ptr, uint8_t b // Save result cell_ptr->id = found_cells[max_peak_cell].cell_id; cell_ptr->cp = found_cells[max_peak_cell].cp; + cellsearch_cfo = found_cells[max_peak_cell].cfo; - INFO("\nFound CELL ID: %d CP: %s\n", cell_ptr->id, srslte_cp_string(cell_ptr->cp)); + INFO("\nFound CELL ID: %d CP: %s, CFO: %f\n", cell_ptr->id, srslte_cp_string(cell_ptr->cp), cellsearch_cfo); srslte_ue_mib_sync_t ue_mib_sync; @@ -351,6 +369,12 @@ void phy::run_rx_tx_state() { int ret; if (!is_sfn_synched) { + if (!radio_is_streaming) { + // Start streaming + radio_handler->start_rx(); + radio_is_streaming = true; + } + ret = sync_sfn(); switch(ret) { default: @@ -364,20 +388,24 @@ void phy::run_rx_tx_state() } } else { uint32_t current_tti = ttisync->get_producer_cntr(); - - // Receive alligned buffer for the current tti - srslte_timestamp_t rx_time; - get_dl_buffer(current_tti)->recv_ue_sync(&ue_sync, &rx_time); + float cfo = srslte_ue_sync_get_cfo(&ue_sync)/15000; + // Prepare transmission for the next tti + srslte_timestamp_add(&last_rx_time, 0, 1e-3); + // send prach if we have to if (prach_buffer.is_ready_to_send(current_tti)) { - prach_buffer.send(radio_handler, rx_time); + prach_buffer.send(radio_handler, cfo, last_rx_time); } // send ul buffer if we have to - if (get_ul_buffer(current_tti)->is_released()) { - get_ul_buffer(current_tti)->send_packet(radio_handler, time_adv_sec, rx_time); + if (get_ul_buffer_adv(current_tti)->is_released()) { + get_ul_buffer_adv(current_tti)->send(radio_handler, time_adv_sec, cfo, last_rx_time); } - ttisync->increase(); + + // Receive alligned buffer for the current tti + get_dl_buffer(current_tti)->recv_ue_sync(&ue_sync, &last_rx_time); + + ttisync->increase(); } } diff --git a/srslte/lib/ue_itf/src/prach.cc b/srslte/lib/ue_itf/src/prach.cc index 7a0b82a2e..6cb5caec6 100644 --- a/srslte/lib/ue_itf/src/prach.cc +++ b/srslte/lib/ue_itf/src/prach.cc @@ -47,12 +47,17 @@ void prach::free_cell() free(buffer[i]); } } + if (signal_buffer) { + free(signal_buffer); + } + srslte_cfo_free(&cfo_h); srslte_prach_free(&prach); } } -bool prach::init_cell(srslte_cell_t cell, params *params_db_) +bool prach::init_cell(srslte_cell_t cell_, params *params_db_) { + cell = cell_; params_db = params_db_; preamble_idx = -1; if (srslte_prach_init(&prach, srslte_symbol_sz(cell.nof_prb), @@ -73,14 +78,18 @@ bool prach::init_cell(srslte_cell_t cell, params *params_db_) return false; } } - initiated = true; - return true; + srslte_cfo_init(&cfo_h, len); + signal_buffer = (cf_t*) srslte_vec_malloc(len*sizeof(cf_t)); + initiated = signal_buffer?true:false; + transmitted_tti = -1; + return initiated; } bool prach::prepare_to_send(uint32_t preamble_idx_) { if (initiated && preamble_idx_ < 64) { preamble_idx = preamble_idx_; + transmitted_tti = -1; INFO("PRACH Buffer: Prepare to send preamble %d\n", preamble_idx); return true; } else { @@ -91,7 +100,7 @@ bool prach::prepare_to_send(uint32_t preamble_idx_) bool prach::is_ready_to_send(uint32_t current_tti_) { if (initiated && preamble_idx >= 0 && preamble_idx < 64 && params_db != NULL) { // consider the number of subframes the transmission must be anticipated - uint32_t current_tti = current_tti_ + tx_advance_sf; + uint32_t current_tti = (current_tti_ + tx_advance_sf)%10240; // Get SFN and sf_idx from the PRACH configuration index uint32_t config_idx = (uint32_t) params_db->get_param(params::PRACH_CONFIG_INDEX); @@ -104,7 +113,8 @@ bool prach::is_ready_to_send(uint32_t current_tti_) { srslte_prach_sf_config(config_idx, &sf_config); for (int i=0;itx(signal_buffer, len, tx_time); + INFO("PRACH transmitted CFO: %f, preamble=%d, len=%d rx_time=%f, tx_time=%f\n", cfo*15000, preamble_idx, len, rx_time.frac_secs, tx_time.frac_secs); + //srslte_vec_save_file("prach", buffer[preamble_idx], len*sizeof(cf_t)); + preamble_idx = -1; } } // namespace ue diff --git a/srslte/lib/ue_itf/src/sched_grant.cc b/srslte/lib/ue_itf/src/sched_grant.cc index 87913e328..c610c8d68 100644 --- a/srslte/lib/ue_itf/src/sched_grant.cc +++ b/srslte/lib/ue_itf/src/sched_grant.cc @@ -61,6 +61,17 @@ namespace ue { return dl_grant.mcs.tbs; } } + + uint32_t sched_grant::get_current_tx_nb() + { + return current_tx_nb; + } + + void sched_grant::set_current_tx_nb(uint32_t current_tx_nb_) + { + current_tx_nb = current_tx_nb_; + } + void sched_grant::set_rv(uint32_t rv) { if (dir == UPLINK) { diff --git a/srslte/lib/ue_itf/src/ul_buffer.cc b/srslte/lib/ue_itf/src/ul_buffer.cc index 856d06a41..a06aa79ac 100644 --- a/srslte/lib/ue_itf/src/ul_buffer.cc +++ b/srslte/lib/ue_itf/src/ul_buffer.cc @@ -38,13 +38,14 @@ namespace srslte { namespace ue { -bool ul_buffer::init_cell(srslte_cell_t cell_, params *params_db) { +bool ul_buffer::init_cell(srslte_cell_t cell_, params *params_db_) { cell = cell_; - params_db = params_db; + params_db = params_db_; current_tx_nb = 0; if (!srslte_ue_ul_init(&ue_ul, cell)) { signal_buffer = (cf_t*) srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); cell_initiated = signal_buffer?true:false; + srslte_ue_ul_set_cfo_enable(&ue_ul, false); return cell_initiated; } else { return false; @@ -69,8 +70,8 @@ bool ul_buffer::generate_pusch(sched_grant pusch_grant, } bool ul_buffer::generate_pusch(sched_grant pusch_grant, - uint8_t *payload, - srslte_uci_data_t uci_data) + uint8_t *payload, + srslte_uci_data_t uci_data) { if (is_ready()) { if (!pusch_grant.is_uplink()) { @@ -93,13 +94,13 @@ bool ul_buffer::generate_pusch(sched_grant pusch_grant, pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF : pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF; pusch_hopping.hopping_offset = params_db->get_param(params::PUSCH_HOPPING_OFFSET); - pusch_hopping.current_tx_nb = current_tx_nb; + pusch_hopping.current_tx_nb = pusch_grant.get_current_tx_nb(); srslte_ue_ul_set_pusch_cfg(&ue_ul, &drms_cfg, &pusch_hopping); int n = srslte_ue_ul_pusch_uci_encode_rnti(&ue_ul, (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr(), payload, uci_data, - (tti+tx_advance_sf)%10, pusch_grant.get_rnti(), + tti%10, pusch_grant.get_rnti(), signal_buffer); if (n < 0) { fprintf(stderr, "Error in UL buffer: Error encoding PUSCH\n"); @@ -119,17 +120,23 @@ bool ul_buffer::generate_pucch(srslte_uci_data_t uci_data) return false; } -bool ul_buffer::send_packet(radio *radio_handler, float time_adv_sec, srslte_timestamp_t rx_time) +bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time) { // send packet through usrp srslte_timestamp_t tx_time; srslte_timestamp_copy(&tx_time, &rx_time); srslte_timestamp_add(&tx_time, 0, tx_advance_sf*1e-3 - time_adv_sec); - INFO("Send PUSCH rx_time= %.6f tx_time = %.6f TA: %.1f us\n", + INFO("Send PUSCH TTI: %d, CFO: %f, len=%d, rx_time= %.6f tx_time = %.6f TA: %.1f us\n", + tti, cfo*15000, SRSLTE_SF_LEN_PRB(cell.nof_prb), srslte_timestamp_real(&rx_time), srslte_timestamp_real(&tx_time), time_adv_sec*1000000); + // Correct CFO before transmission + srslte_cfo_correct(&ue_ul.cfo, signal_buffer, signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb)); + radio_handler->tx(signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), tx_time); + + //srslte_vec_save_file("pusch", signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb)*sizeof(cf_t)); ready(); } diff --git a/srslte/lib/ue_itf/test/ue_itf_test_prach.cc b/srslte/lib/ue_itf/test/ue_itf_test_prach.cc index 2cfb4aa39..851bb32d3 100644 --- a/srslte/lib/ue_itf/test/ue_itf_test_prach.cc +++ b/srslte/lib/ue_itf/test/ue_itf_test_prach.cc @@ -40,26 +40,31 @@ typedef struct { float uhd_tx_freq; float uhd_rx_gain; float uhd_tx_gain; + bool continous; }prog_args_t; +prog_args_t prog_args; + void args_default(prog_args_t *args) { args->uhd_rx_freq = -1.0; args->uhd_tx_freq = -1.0; args->uhd_rx_gain = 60.0; args->uhd_tx_gain = 40.0; + args->continous = false; } void usage(prog_args_t *args, char *prog) { - printf("Usage: %s [gGv] -f rx_frequency -F tx_frequency (in Hz)\n", prog); + printf("Usage: %s [gGcv] -f rx_frequency -F tx_frequency (in Hz)\n", prog); printf("\t-g UHD RX gain [Default %.2f dB]\n", args->uhd_rx_gain); printf("\t-G UHD TX gain [Default %.2f dB]\n", args->uhd_tx_gain); + printf("\t-c Run continuously [Default only once]\n"); printf("\t-v [increase verbosity, default none]\n"); } void parse_args(prog_args_t *args, int argc, char **argv) { int opt; args_default(args); - while ((opt = getopt(argc, argv, "gGfFv")) != -1) { + while ((opt = getopt(argc, argv, "gGfFcv")) != -1) { switch (opt) { case 'g': args->uhd_rx_gain = atof(argv[optind]); @@ -73,6 +78,9 @@ void parse_args(prog_args_t *args, int argc, char **argv) { case 'F': args->uhd_tx_freq = atof(argv[optind]); break; + case 'c': + args->continous = true; + break; case 'v': srslte_verbose++; break; @@ -182,16 +190,19 @@ int rar_unpack(uint8_t *buffer, rar_msg_t *msg) srslte::ue::phy phy; -uint8_t payload[1024]; +uint8_t payload[102400]; const uint8_t conn_request_msg[] = {0x20, 0x06, 0x1F, 0x5C, 0x2C, 0x04, 0xB2, 0xAC, 0xF6, 0x00, 0x00, 0x00}; enum mac_state {RA, RAR, CONNSETUP} state = RA; -uint32_t ra_tti = 0, conreq_tti = 0; -uint32_t preamble_idx = 0; +uint32_t conreq_tti = 0; +uint32_t preamble_idx = 7; rar_msg_t rar_msg; uint32_t nof_rx_connsetup = 0, nof_rx_rar = 0, nof_tx_ra = 0; +uint32_t nof_rtx_connsetup = 0; +uint32_t rv_value[4] = {0, 2, 3, 1}; + void config_phy() { phy.set_param(srslte::ue::params::PRACH_CONFIG_INDEX, 0); phy.set_param(srslte::ue::params::PRACH_FREQ_OFFSET, 0); @@ -207,6 +218,14 @@ void config_phy() { } +uint32_t interval(uint32_t x1, uint32_t x2) { + if (x1 > x2) { + return x1-x2; + } else { + return 10240-x2+x1; + } +} + // This is the MAC implementation void run_tti(uint32_t tti) { INFO("MAC running tti: %d\n", tti); @@ -214,15 +233,12 @@ void run_tti(uint32_t tti) { // Get buffer srslte::ue::dl_buffer *dl_buffer = phy.get_dl_buffer(tti); - if (dl_buffer) { - fprintf(stderr, "Error getting DL buffer for tti %d\n", tti); - return; - } - if (state == RA) { + if (nof_tx_ra > 0 && !prog_args.continous) { + exit(0); + } // Indicate PHY to transmit the PRACH when possible if (phy.send_prach(preamble_idx)) { - ra_tti = tti; nof_tx_ra++; state = RAR; } else { @@ -231,84 +247,139 @@ void run_tti(uint32_t tti) { } } else if (state == RAR) { srslte::ue::sched_grant rar_grant(srslte::ue::sched_grant::DOWNLINK, 2); - // Assume the maximum RA-window - uint32_t interval = (tti-ra_tti)%10240; - if (interval >= 3 && interval <= 13) { - // Get DL grant for RA-RNTI=2 - if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_RARNTI, &rar_grant)) - { - // Decode packet - if (dl_buffer->decode_pdsch(rar_grant, payload)) { - INFO("RAR received tti: %d\n", tti); - rar_unpack(payload, &rar_msg); - - INFO("Received RAR for preamble %d\n", rar_msg.RAPID); - if (rar_msg.RAPID == preamble_idx) { - - nof_rx_rar++; - - if (SRSLTE_VERBOSE_ISINFO()) { - rar_msg_fprint(stdout, &rar_msg); - } - - // Set time advance - phy.set_timeadv_rar(rar_msg.timing_adv_cmd); - - // Generate Msg3 grant - srslte::ue::sched_grant connreq_grant(srslte::ue::sched_grant::UPLINK, rar_msg.temp_c_rnti); - phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant); - - // Pack Msg3 bits - srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs()); - - // Get UL buffer - srslte::ue::ul_buffer *ul_buffer = phy.get_ul_buffer(tti+6); - - // Generate PUSCH - if (ul_buffer) { - ul_buffer->generate_pusch(connreq_grant, payload); - - // Save transmission time - conreq_tti = tti; - state = CONNSETUP; - } else { - fprintf(stderr, "Error getting UL buffer for TTI %d\n", tti); - state = RA; - } - } - } - } + int ra_tti = phy.get_prach_transmitted_tti(); + if (ra_tti > 0) { + INFO("PRACH was transmitted at %d\n", ra_tti); + // Assume the maximum RA-window + uint32_t interval_ra = interval(tti, ra_tti); + INFO("Interval=%u\n", interval_ra); + if (interval_ra >= 3 && interval_ra <= 13) { + // Get DL grant for RA-RNTI=2 + if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_RARNTI, &rar_grant)) + { + // Decode packet + if (dl_buffer->decode_pdsch(rar_grant, payload)) { + INFO("RAR received tti: %d\n", tti); + rar_unpack(payload, &rar_msg); + + INFO("Received RAR for preamble %d\n", rar_msg.RAPID); + if (rar_msg.RAPID == preamble_idx) { + + INFO("Received RAR at TTI: %d\n", tti); + nof_rx_rar++; + + if (SRSLTE_VERBOSE_ISINFO()) { + rar_msg_fprint(stdout, &rar_msg); + } + + // Set time advance + phy.set_timeadv_rar(rar_msg.timing_adv_cmd); + + // Generate Msg3 grant + srslte::ue::sched_grant connreq_grant(srslte::ue::sched_grant::UPLINK, rar_msg.temp_c_rnti); + phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant); + + // Pack Msg3 bits + srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs()); + + // Get UL buffer + srslte::ue::ul_buffer *ul_buffer = phy.get_ul_buffer(tti+6); + + // Generate PUSCH + if (ul_buffer) { + connreq_grant.set_rv(0); + INFO("Generating PUSCH for TTI: %d\n", ul_buffer->tti); + //ul_buffer->generate_pusch(connreq_grant, payload); + + // Save transmission time + conreq_tti = ul_buffer->tti; + state = CONNSETUP; + } else { + fprintf(stderr, "Error getting UL buffer for TTI %d\n", tti); + state = RA; + } + } + } + } + } else if (interval_ra > 13 && interval_ra < 100) { // avoid wrapping + INFO("RAR not received at TTI=%d (interval_ra=%d)\n", tti, interval_ra); + state = RA; + } } } else { srslte::ue::sched_grant conn_setup_grant(srslte::ue::sched_grant::DOWNLINK, rar_msg.temp_c_rnti); - if ((tti - conreq_tti)%10240 == 4) { - // Get DL grant for RA-RNTI=2 - if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_TEMPORAL, &conn_setup_grant)) - { - // Decode packet - if (dl_buffer->decode_pdsch(conn_setup_grant, payload)) { - INFO("ConnSetup received tti=%d\n", tti); - nof_rx_connsetup++; + + uint32_t interval_conreq = interval(tti, conreq_tti); + if (interval_conreq == 4) { + + srslte::ue::sched_grant connreq_grant(srslte::ue::sched_grant::UPLINK, rar_msg.temp_c_rnti); + phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant); + + // Decode PHICH from Connection Request + if (!dl_buffer->decode_phich(connreq_grant)) { + + // Pack Msg3 bits + srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs()); + + // Get UL buffer + srslte::ue::ul_buffer *ul_buffer = phy.get_ul_buffer(tti+4); + + // Generate PUSCH + if (ul_buffer) { + nof_rtx_connsetup++; + if (nof_rtx_connsetup >= 5) { + state = RA; + } else { + connreq_grant.set_current_tx_nb(nof_rtx_connsetup); + connreq_grant.set_rv(rv_value[nof_rtx_connsetup%4]); + INFO("Generating PUSCH for TTI: %d\n", ul_buffer->tti); + ul_buffer->generate_pusch(connreq_grant, payload); + + // Save transmission time + conreq_tti = ul_buffer->tti; + state = CONNSETUP; + } + } else { + fprintf(stderr, "Error getting UL buffer for TTI %d\n", tti); state = RA; } + } else { + // Get DL grant for tmp_rnti + if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_TEMPORAL, &conn_setup_grant)) + { + // Decode packet + if (dl_buffer->decode_pdsch(conn_setup_grant, payload)) { + nof_rx_connsetup++; + state = RA; + nof_rtx_connsetup=0; + if (!prog_args.continous) { + printf("Connection Setup received (%d/%d)\n", nof_rx_connsetup, nof_tx_ra); + } + } else { + INFO("Error decoding PDSCH for Connection Request at TTI=%d\n", tti); + state = RA; + } + } else { + INFO("DCI for Connection Request not found on PDCCH at TTI=%d\n", tti); + state = RA; + } } } } - if (srslte_verbose == SRSLTE_VERBOSE_NONE) { - printf("RECV RAR %.1f \%% RECV ConnSetup %.1f \%% (total RA: %5u) \r", + + if (srslte_verbose == SRSLTE_VERBOSE_NONE && prog_args.continous) { + printf("RECV RAR %2.1f \%% RECV ConnSetup %2.1f \%% (%5u/%5u) \r", (float) 100*nof_rx_rar/nof_tx_ra, (float) 100*nof_rx_connsetup/nof_tx_ra, - nof_tx_ra); + nof_rx_connsetup, nof_tx_ra); } - - dl_buffer->ready(); + } int main(int argc, char *argv[]) { srslte_cell_t cell; uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; - prog_args_t prog_args; srslte::ue::tti_sync_cv ttisync(10240); srslte::radio_uhd radio_uhd;