diff --git a/cuhd/include/srslte/cuhd/radio_uhd.h b/cuhd/include/srslte/cuhd/radio_uhd.h new file mode 100644 index 000000000..55913120b --- /dev/null +++ b/cuhd/include/srslte/cuhd/radio_uhd.h @@ -0,0 +1,67 @@ + /** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/srslte.h" +#include "srslte/common/radio.h" +#include "srslte/cuhd/cuhd.h" + +#ifndef RADIO_UHD_H +#define RADIO_UHD_H + + +namespace srslte { + +/* Interface to the RF frontend. + */ + class SRSLTE_API radio_uhd : public radio + { + public: + bool init(); + bool init(char *args); + + 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); + + void set_tx_gain(float gain); + void set_rx_gain(float gain); + + void set_tx_freq(float freq); + void set_rx_freq(float freq); + + void set_tx_srate(float srate); + void set_rx_srate(float srate); + + void start_rx(); + void stop_rx(); + + private: + void *uhd; + }; +} + +#endif diff --git a/cuhd/lib/CMakeLists.txt b/cuhd/lib/CMakeLists.txt index bd2877d32..1c7a8bcd2 100644 --- a/cuhd/lib/CMakeLists.txt +++ b/cuhd/lib/CMakeLists.txt @@ -23,7 +23,7 @@ FIND_PACKAGE(UHD) IF(UHD_FOUND) - ADD_LIBRARY(cuhd SHARED cuhd_imp.cpp cuhd_utils.c) + ADD_LIBRARY(cuhd SHARED cuhd_imp.cpp cuhd_utils.c radio_uhd.cc) INCLUDE_DIRECTORIES(${UHD_INCLUDE_DIRS}) LINK_DIRECTORIES(${UHD_LIBRARY_DIRS}) TARGET_LINK_LIBRARIES(cuhd ${UHD_LIBRARIES}) diff --git a/cuhd/lib/radio_uhd.cc b/cuhd/lib/radio_uhd.cc new file mode 100644 index 000000000..83cdec32d --- /dev/null +++ b/cuhd/lib/radio_uhd.cc @@ -0,0 +1,116 @@ + /** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/srslte.h" +#include "srslte/common/radio.h" +#include "srslte/cuhd/radio_uhd.h" + + +namespace srslte { + +bool radio_uhd::init() +{ + return init((char*) ""); +} + +bool radio_uhd::init(char *args) +{ + printf("Opening UHD device...\n"); + if (cuhd_open(args, &uhd)) { + fprintf(stderr, "Error opening uhd\n"); + return false; + } + return true; +} + +bool radio_uhd::rx_at(void* buffer, uint32_t nof_samples, srslte_timestamp_t rx_time) +{ + fprintf(stderr, "Not implemented\n"); + return false; +} + +bool radio_uhd::rx_now(void* buffer, uint32_t nof_samples, srslte_timestamp_t* rxd_time) +{ + if (cuhd_recv_with_time(uhd, buffer, nof_samples, true, &rxd_time->full_secs, &rxd_time->frac_secs) > 0) { + return true; + } else { + return false; + } +} + +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) { + return true; + } else { + return false; + } +} + +void radio_uhd::set_rx_freq(float freq) +{ + cur_rx_freq = cuhd_set_rx_freq(uhd, freq); +} + +void radio_uhd::set_rx_gain(float gain) +{ + cur_rx_gain = cuhd_set_rx_gain(uhd, gain); +} + +void radio_uhd::set_rx_srate(float srate) +{ + cur_rx_srate = cuhd_set_rx_srate(uhd, srate); +} + +void radio_uhd::set_tx_freq(float freq) +{ + cur_tx_freq = cuhd_set_tx_freq(uhd, freq); +} + +void radio_uhd::set_tx_gain(float gain) +{ + cur_tx_gain = cuhd_set_tx_gain(uhd, gain); +} + +void radio_uhd::set_tx_srate(float srate) +{ + cur_tx_srate = cuhd_set_tx_srate(uhd, srate); +} + +void radio_uhd::start_rx() +{ + cuhd_start_rx_stream(uhd); +} + +void radio_uhd::stop_rx() +{ + cuhd_stop_rx_stream(uhd); +} + + +} + diff --git a/srslte/examples/prach_ue.c b/srslte/examples/prach_ue.c index 41da9bcc1..605f6d8b5 100644 --- a/srslte/examples/prach_ue.c +++ b/srslte/examples/prach_ue.c @@ -543,7 +543,7 @@ int main(int argc, char **argv) { srslte_bit_pack_vector((uint8_t*) conn_request_msg, data, ra_pusch.mcs.tbs); - uint32_t n_ta = srssrslte_N_ta_new_rar(rar_msg.timing_adv_cmd); + 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) { diff --git a/srslte/include/srslte/common/phy_common.h b/srslte/include/srslte/common/phy_common.h index aafa98134..ac04844be 100644 --- a/srslte/include/srslte/common/phy_common.h +++ b/srslte/include/srslte/common/phy_common.h @@ -197,7 +197,7 @@ SRSLTE_API bool srslte_N_id_2_isvalid(uint32_t N_id_2); SRSLTE_API bool srslte_N_id_1_isvalid(uint32_t N_id_1); -SRSLTE_API bool srssrslte_symbol_sz_isvalid(uint32_t symbol_sz); +SRSLTE_API bool srslte_symbol_sz_isvalid(uint32_t symbol_sz); SRSLTE_API int srslte_symbol_sz(uint32_t nof_prb); @@ -213,7 +213,7 @@ SRSLTE_API uint32_t srslte_voffset(uint32_t symbol_id, uint32_t cell_id, uint32_t nof_ports); -SRSLTE_API uint32_t srssrslte_N_ta_new_rar(uint32_t ta); +SRSLTE_API uint32_t srslte_N_ta_new_rar(uint32_t ta); SRSLTE_API uint32_t srslte_N_ta_new(uint32_t N_ta_old, uint32_t ta); diff --git a/srslte/include/srslte/common/radio.h b/srslte/include/srslte/common/radio.h new file mode 100644 index 000000000..0a5ee9770 --- /dev/null +++ b/srslte/include/srslte/common/radio.h @@ -0,0 +1,78 @@ + /** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * srsLTE 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. + * + * srsLTE 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 +#include "srslte/srslte.h" +#include "srslte/common/timestamp.h" + +#ifndef RADIO_H +#define RADIO_H + + +namespace srslte { + +/* Interface to the RF frontend. + */ + class SRSLTE_API radio + { + public: + 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; + + virtual void set_tx_gain(float gain) = 0; + virtual void set_rx_gain(float gain) = 0; + + virtual void set_tx_freq(float freq) = 0; + virtual void set_rx_freq(float freq) = 0; + + virtual void set_tx_srate(float srate) = 0; + virtual void set_rx_srate(float srate) = 0; + + virtual void start_rx() = 0; + virtual void stop_rx() = 0; + + float get_tx_gain() { return cur_tx_gain; } + float get_rx_gain() { return cur_rx_gain; } + + float get_tx_freq() { return cur_tx_freq; } + float get_rx_freq() { return cur_rx_freq; } + + float get_tx_srate() { return cur_tx_srate; } + float get_rx_srate() { return cur_rx_srate; } + + protected: + float cur_tx_gain; + float cur_rx_gain; + float cur_tx_freq; + float cur_rx_freq; + float cur_tx_srate; + float cur_rx_srate; + }; +} + +#endif diff --git a/srslte/include/srslte/ue_itf/dl_buffer.h b/srslte/include/srslte/ue_itf/dl_buffer.h index 1ea5eb4d6..44839dfa3 100644 --- a/srslte/include/srslte/ue_itf/dl_buffer.h +++ b/srslte/include/srslte/ue_itf/dl_buffer.h @@ -64,8 +64,8 @@ namespace ue { bool init_cell(srslte_cell_t cell, params *params_db); void free_cell(); bool recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time); - bool get_ul_grant(pdcch_ul_search_t mode, uint32_t rnti, sched_grant *grant); - bool get_dl_grant(pdcch_dl_search_t mode, uint32_t rnti, sched_grant *grant); + 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_pdsch(sched_grant pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/KO private: diff --git a/srslte/include/srslte/ue_itf/phy.h b/srslte/include/srslte/ue_itf/phy.h index b53dc3ee7..dab348548 100644 --- a/srslte/include/srslte/ue_itf/phy.h +++ b/srslte/include/srslte/ue_itf/phy.h @@ -33,6 +33,7 @@ #include "srslte/ue_itf/params.h" #include "srslte/ue_itf/sched_grant.h" #include "srslte/ue_itf/queue.h" +#include "srslte/common/radio.h" #ifndef UEPHY_H #define UEPHY_H @@ -59,7 +60,7 @@ class SRSLTE_API phy { public: - bool init(tti_sync *ttisync); + bool init(radio *radio_handler, tti_sync *ttisync); void stop(); // These functions can be called only if PHY is in IDLE (ie, not RX/TX) @@ -75,11 +76,15 @@ public: // Indicate the PHY to send PRACH as soon as possible bool send_prach(uint32_t preamble_idx); - // Control USRP freq/gain - void set_tx_gain(float gain); - void set_rx_gain(float gain); - void set_tx_freq(float freq); - void set_rx_freq(float freq); + // Get handler to the radio + radio* get_radio(); + + // Time advance commands + void set_timeadv_rar(uint32_t ta_cmd); + void set_timeadv(uint32_t ta_cmd); + + // Generate Msg3 UL grant from RAR + void rar_ul_grant(uint32_t rba, uint32_t trunc_mcs, bool hopping_flag, sched_grant *grant); // Get status bool status_is_idle(); @@ -102,7 +107,8 @@ private: } phy_state; tti_sync *ttisync; - + radio *radio_handler; + srslte_cell_t cell; bool cell_is_set; bool is_sfn_synched = false; @@ -116,9 +122,10 @@ private: prach prach_buffer; params params_db; - pthread_t radio_thread; - void *radio_handler; - static void *radio_thread_fnc(void *arg); + pthread_t phy_thread; + float time_adv_sec; + uint32_t n_ta; + 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(); diff --git a/srslte/include/srslte/ue_itf/prach.h b/srslte/include/srslte/ue_itf/prach.h index 5eea4a029..7527578b1 100644 --- a/srslte/include/srslte/ue_itf/prach.h +++ b/srslte/include/srslte/ue_itf/prach.h @@ -39,10 +39,11 @@ namespace ue { public: bool init_cell(srslte_cell_t cell, params *params_db); void free_cell(); - bool ready_to_send(uint32_t preamble_idx); + 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); private: + static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission params *params_db = NULL; int preamble_idx; bool initiated = false; diff --git a/srslte/include/srslte/ue_itf/queue.h b/srslte/include/srslte/ue_itf/queue.h index e18475aad..b34eebc05 100644 --- a/srslte/include/srslte/ue_itf/queue.h +++ b/srslte/include/srslte/ue_itf/queue.h @@ -47,29 +47,23 @@ public: class element { public: - ~element(); - bool release() + element() { + state = READY; + tti = 0; + } + ~element(); + void release() { - if (state == READY) { - state = RELEASED; - return true; - } else { - return false; - } + state = RELEASED; } bool is_released() { return state == RELEASED; } - bool ready_to_send() { - if (state == RELEASED) { - state = READY; - return true; - } else { - return false; - } + void ready() { + state = READY; } - bool is_ready_to_send() { + bool is_ready() { return state == READY; } uint32_t tti; diff --git a/srslte/include/srslte/ue_itf/sched_grant.h b/srslte/include/srslte/ue_itf/sched_grant.h index fbc47f63a..e54dd9b0c 100644 --- a/srslte/include/srslte/ue_itf/sched_grant.h +++ b/srslte/include/srslte/ue_itf/sched_grant.h @@ -39,7 +39,7 @@ namespace ue { public: typedef enum {DOWNLINK=0, UPLINK=1} direction_t; - sched_grant(uint16_t rnti); + sched_grant(direction_t direction, uint16_t rnti); uint16_t get_rnti(); uint32_t get_rv(); void set_rv(uint32_t rv); diff --git a/srslte/include/srslte/ue_itf/ul_buffer.h b/srslte/include/srslte/ue_itf/ul_buffer.h index 30797c399..795e0092f 100644 --- a/srslte/include/srslte/ue_itf/ul_buffer.h +++ b/srslte/include/srslte/ue_itf/ul_buffer.h @@ -26,6 +26,7 @@ */ #include "srslte/srslte.h" +#include "srslte/common/radio.h" #include "srslte/ue_itf/queue.h" #include "srslte/ue_itf/sched_grant.h" #include "srslte/ue_itf/params.h" @@ -47,18 +48,18 @@ namespace ue { void free_cell(); void set_tti(uint32_t tti); void set_current_tx_nb(uint32_t current_tx_nb); + 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(void *radio_handler, srslte_timestamp_t rx_time); + bool send_packet(radio* radio_handler, float time_adv_sec, srslte_timestamp_t rx_time); + static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission private: params *params_db; srslte_cell_t cell; srslte_ue_ul_t ue_ul; - bool signal_generated; bool cell_initiated; cf_t* signal_buffer; - uint32_t tti; uint32_t current_tx_nb; }; diff --git a/srslte/lib/CMakeLists.txt b/srslte/lib/CMakeLists.txt index 53cb5ec07..31b5da677 100644 --- a/srslte/lib/CMakeLists.txt +++ b/srslte/lib/CMakeLists.txt @@ -78,23 +78,19 @@ FOREACH (_file ${cmakefiles}) ENDFOREACH() ######################################################################## -# Create C++ library only if UHD is found +# Create C++ library ######################################################################## -LIST(FIND OPTIONAL_LIBS cuhd CUHD_FIND) -IF(${CUHD_FIND} GREATER -1) - - FILE(GLOB modules *) - SET(SOURCES_CPP_ALL "") - FOREACH (_module ${modules}) - IF(IS_DIRECTORY ${_module}) - FILE(GLOB_RECURSE tmp "${_module}/src/*.cc") - LIST(APPEND SOURCES_CPP_ALL ${tmp}) - ENDIF(IS_DIRECTORY ${_module}) - ENDFOREACH() +FILE(GLOB modules *) +SET(SOURCES_CPP_ALL "") +FOREACH (_module ${modules}) + IF(IS_DIRECTORY ${_module}) + FILE(GLOB_RECURSE tmp "${_module}/src/*.cc") + LIST(APPEND SOURCES_CPP_ALL ${tmp}) + ENDIF(IS_DIRECTORY ${_module}) +ENDFOREACH() - ADD_LIBRARY(srslte++ SHARED ${SOURCES_CPP_ALL}) - TARGET_LINK_LIBRARIES(srslte++ cuhd srslte m pthread ${FFTW3F_LIBRARIES}) - INSTALL(TARGETS srslte++ DESTINATION ${LIBRARY_DIR}) - LIBLTE_SET_PIC(srslte++) +ADD_LIBRARY(srslte++ SHARED ${SOURCES_CPP_ALL}) +TARGET_LINK_LIBRARIES(srslte++ cuhd srslte m pthread ${FFTW3F_LIBRARIES}) +INSTALL(TARGETS srslte++ DESTINATION ${LIBRARY_DIR}) +LIBLTE_SET_PIC(srslte++) -ENDIF(${CUHD_FIND} GREATER -1) diff --git a/srslte/lib/common/src/phy_common.c b/srslte/lib/common/src/phy_common.c index c14c9df4d..be1fa6561 100644 --- a/srslte/lib/common/src/phy_common.c +++ b/srslte/lib/common/src/phy_common.c @@ -211,7 +211,7 @@ uint32_t srslte_N_ta_new(uint32_t N_ta_old, uint32_t ta) { /* Returns the new time advance as indicated by the random access response * as specified in Section 4.2.3 of 36.213 */ -uint32_t srssrslte_N_ta_new_rar(uint32_t ta) { +uint32_t srslte_N_ta_new_rar(uint32_t ta) { if (ta > 1282) { ta = 1282; } @@ -263,7 +263,7 @@ int srslte_symbol_sz(uint32_t nof_prb) { return SRSLTE_ERROR; } -bool srssrslte_symbol_sz_isvalid(uint32_t symbol_sz) { +bool srslte_symbol_sz_isvalid(uint32_t symbol_sz) { if (symbol_sz == 128 || symbol_sz == 256 || symbol_sz == 512 || diff --git a/srslte/lib/ue_itf/src/dl_buffer.cc b/srslte/lib/ue_itf/src/dl_buffer.cc index c2b7947c4..51163ec02 100644 --- a/srslte/lib/ue_itf/src/dl_buffer.cc +++ b/srslte/lib/ue_itf/src/dl_buffer.cc @@ -71,13 +71,17 @@ bool dl_buffer::recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_t 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; } } } -bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, uint32_t rnti, sched_grant *grant) +bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, sched_grant *grant) { if (signal_buffer) { if (!sf_symbols_and_ce_done) { @@ -94,7 +98,7 @@ bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, uint32_t rnti, sched_grant } srslte_dci_msg_t dci_msg; - if (srslte_ue_dl_find_ul_dci(&ue_dl, &dci_msg, cfi, tti%10, rnti)) { + if (srslte_ue_dl_find_ul_dci(&ue_dl, &dci_msg, cfi, tti%10, grant->get_rnti())) { return false; } @@ -110,9 +114,9 @@ bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, uint32_t rnti, sched_grant } -bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, uint32_t rnti, sched_grant *grant) +bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant) { - if (signal_buffer) { + if (signal_buffer && is_ready()) { INFO("DL Buffer TTI %d: Getting DL grant\n", tti); if (!sf_symbols_and_ce_done) { INFO("DL Buffer TTI %d: Getting DL grant. Calling fft estimate\n", tti); @@ -137,11 +141,11 @@ bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, uint32_t rnti, sched_grant } srslte_dci_msg_t dci_msg; - if (srslte_ue_dl_find_dl_dci(&ue_dl, &dci_msg, cfi, tti%10, rnti) != 1) { + if (srslte_ue_dl_find_dl_dci(&ue_dl, &dci_msg, cfi, tti%10, grant->get_rnti()) != 1) { return false; } - if (srslte_dci_msg_to_ra_dl(&dci_msg, rnti, cell, cfi, + if (srslte_dci_msg_to_ra_dl(&dci_msg, grant->get_rnti(), cell, cfi, (srslte_ra_pdsch_t*) grant->get_grant_ptr())) { return false; } @@ -152,7 +156,7 @@ bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, uint32_t rnti, sched_grant bool dl_buffer::decode_phich(srslte_phich_alloc_t assignment) { - if (signal_buffer) { + if (signal_buffer && is_ready()) { if (!sf_symbols_and_ce_done) { if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) { return false; @@ -165,10 +169,10 @@ bool dl_buffer::decode_phich(srslte_phich_alloc_t assignment) bool dl_buffer::decode_pdsch(sched_grant pdsch_grant, uint8_t *payload) { - if (signal_buffer) { + if (signal_buffer && is_ready()) { INFO("DL Buffer TTI %d: Decoding PDSCH\n", tti); if (!sf_symbols_and_ce_done) { - INFO("DL Buffer TTI %d: Decoding PDSCH. Calling fft estimate\n", tti); + INFO("DL Buffer TTI %d: Decoding PDSCH. Calling fft estimate\n", tti); if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) { return false; } diff --git a/srslte/lib/ue_itf/src/phy.cc b/srslte/lib/ue_itf/src/phy.cc index 9cb39677c..f272d19a4 100644 --- a/srslte/lib/ue_itf/src/phy.cc +++ b/srslte/lib/ue_itf/src/phy.cc @@ -31,7 +31,6 @@ #include #include "srslte/srslte.h" -#include "srslte/cuhd/cuhd.h" #include "srslte/ue_itf/phy.h" #include "srslte/ue_itf/prach.h" @@ -40,21 +39,12 @@ namespace srslte { namespace ue { - - -bool phy::init_radio_handler(char *args) { - printf("Opening UHD device...\n"); - if (cuhd_open(args, &radio_handler)) { - fprintf(stderr, "Error opening uhd\n"); - return false; - } - return true; -} - -bool phy::init(tti_sync *ttisync_) + +bool phy::init(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_) { started = false; ttisync = ttisync_; + radio_handler = radio_handler_; ul_buffer_queue = new queue(6, sizeof(ul_buffer)); dl_buffer_queue = new queue(6, sizeof(dl_buffer)); @@ -62,12 +52,13 @@ bool phy::init(tti_sync *ttisync_) params_db.set_param(params::CELLSEARCH_TIMEOUT_PSS_NFRAMES, 100); params_db.set_param(params::CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD, 160); params_db.set_param(params::CELLSEARCH_TIMEOUT_MIB_NFRAMES, 100); - - if (init_radio_handler((char*) "")) { - pthread_create(&radio_thread, NULL, radio_thread_fnc, this); - started = true; + if (!pthread_create(&phy_thread, NULL, phy_thread_fnc, this)) { + started = true; + } else { + perror("pthread_create"); } + return started; } @@ -75,7 +66,7 @@ void phy::stop() { started = false; - pthread_join(radio_thread, NULL); + pthread_join(phy_thread, NULL); for (int i=0;i<6;i++) { ((ul_buffer*) ul_buffer_queue->get(i))->free_cell(); @@ -88,24 +79,31 @@ void phy::stop() prach_buffer.free_cell(); } -void phy::set_tx_gain(float gain) { - float x = cuhd_set_tx_gain(radio_handler, gain); - printf("Set TX gain to %.1f dB\n", x); +radio* phy::get_radio() { + return radio_handler; } -void phy::set_rx_gain(float gain) { - float x = cuhd_set_rx_gain(radio_handler, gain); - printf("Set RX gain to %.1f dB\n", x); +void phy::set_timeadv_rar(uint32_t ta_cmd) { + n_ta = srslte_N_ta_new_rar(ta_cmd); + time_adv_sec = SRSLTE_TA_OFFSET+((float) n_ta)*SRSLTE_LTE_TS; + INFO("Set TA RAR: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, time_adv_sec*1e6); } -void phy::set_tx_freq(float freq) { - float x = cuhd_set_tx_freq(radio_handler, freq); - printf("Set TX freq to %.1f MHz\n", x/1000000); +void phy::set_timeadv(uint32_t ta_cmd) { + n_ta = srslte_N_ta_new(n_ta, ta_cmd); + time_adv_sec = SRSLTE_TA_OFFSET+((float) n_ta)*SRSLTE_LTE_TS; + INFO("Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, time_adv_sec*1e6); } -void phy::set_rx_freq(float freq) { - float x = cuhd_set_rx_freq(radio_handler, freq); - printf("Set RX freq to %.1f MHz\n", x/1000000); +void phy::rar_ul_grant(uint32_t rba, uint32_t trunc_mcs, bool hopping_flag, sched_grant *grant) +{ + uint32_t n_ho = params_db.get_param(params::PUSCH_HOPPING_OFFSET); + srslte_ra_pusch_t *ra_pusch = (srslte_ra_pusch_t*) grant->get_grant_ptr(); + srslte_dci_rar_to_ra_ul(rba, trunc_mcs, hopping_flag, cell.nof_prb, ra_pusch); + srslte_ra_ul_alloc(&ra_pusch->prb_alloc, ra_pusch, n_ho, cell.nof_prb); + if (SRSLTE_VERBOSE_ISINFO()) { + srslte_ra_pusch_fprint(stdout, ra_pusch, cell.nof_prb); + } } void phy::set_param(params::param_t param, int64_t value) { @@ -117,8 +115,9 @@ void phy::set_param(params::param_t param, int64_t value) { bool phy::send_prach(uint32_t preamble_idx) { if (phy_state == RXTX) { - prach_buffer.ready_to_send(preamble_idx); - } + return prach_buffer.prepare_to_send(preamble_idx); + } + return false; } // Do fast measurement on RSSI and/or PSS autocorrelation energy or PSR @@ -135,11 +134,11 @@ bool phy::start_rxtx() if (phy_state == IDLE) { if (cell_is_set) { // Set RX/TX sampling rate - cuhd_set_rx_srate(radio_handler, srslte_sampling_freq_hz(cell.nof_prb)); - cuhd_set_tx_srate(radio_handler, srslte_sampling_freq_hz(cell.nof_prb)); + radio_handler->set_rx_srate(srslte_sampling_freq_hz(cell.nof_prb)); + radio_handler->set_tx_srate(srslte_sampling_freq_hz(cell.nof_prb)); // Start streaming - cuhd_start_rx_stream(radio_handler); + radio_handler->start_rx(); phy_state = RXTX; return true; } else { @@ -155,7 +154,7 @@ bool phy::stop_rxtx() { if (phy_state == RXTX) { // Stop streaming - cuhd_stop_rx_stream(radio_handler); + radio_handler->stop_rx(); phy_state = IDLE; return true; } else { @@ -183,15 +182,16 @@ uint32_t phy::tti_to_subf(uint32_t tti) { return tti%10; } -void* phy::radio_thread_fnc(void *arg) { +void* phy::phy_thread_fnc(void *arg) { phy* phy = static_cast(arg); phy->main_radio_loop(); return NULL; } -int radio_recv_wrapper_cs(void *h,void *data, uint32_t nsamples, srslte_timestamp_t*) +int radio_recv_wrapper_cs(void *h,void *data, uint32_t nsamples, srslte_timestamp_t *rx_time) { - return cuhd_recv(h, data, nsamples, 1); + radio *radio_handler = (radio*) h; + return radio_handler->rx_now(data, nsamples, rx_time); } bool phy::set_cell(srslte_cell_t cell_) { @@ -204,9 +204,11 @@ bool phy::set_cell(srslte_cell_t cell_) { { if (prach_buffer.init_cell(cell, ¶ms_db)) { for(uint32_t i=0;i<6;i++) { - get_ul_buffer(i)->init_cell(cell, ¶ms_db); - get_dl_buffer(i)->init_cell(cell, ¶ms_db); - get_dl_buffer(i)->buffer_id = i; + ((ul_buffer*) ul_buffer_queue->get(i))->init_cell(cell, ¶ms_db); + ((dl_buffer*) dl_buffer_queue->get(i))->init_cell(cell, ¶ms_db); + ((dl_buffer*) dl_buffer_queue->get(i))->buffer_id = i; + ((ul_buffer*) ul_buffer_queue->get(i))->ready(); + ((dl_buffer*) dl_buffer_queue->get(i))->release(); } cell_is_set = true; } @@ -224,15 +226,14 @@ 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); + return (ul_buffer*) ul_buffer_queue->get(tti - ul_buffer::tx_advance_sf); } dl_buffer* phy::get_dl_buffer(uint32_t tti) { return (dl_buffer*) dl_buffer_queue->get(tti); } - - + bool phy::decode_mib(uint32_t N_id_2, srslte_cell_t *cell, uint8_t payload[SRSLTE_BCH_PAYLOAD_LEN]) { return decode_mib_N_id_2((int) N_id_2, cell, payload); } @@ -253,10 +254,11 @@ bool phy::decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell_ptr, uint8_t b } srslte_ue_cellsearch_set_nof_frames_to_scan(&cs, params_db.get_param(params::CELLSEARCH_TIMEOUT_PSS_NFRAMES)); - srslte_ue_cellsearch_set_threshold(&cs, (float) params_db.get_param(params::CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD)/10); + srslte_ue_cellsearch_set_threshold(&cs, (float) + params_db.get_param(params::CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD)/10); - cuhd_set_rx_srate(radio_handler, 1920000.0); - cuhd_start_rx_stream(radio_handler); + radio_handler->set_rx_srate(1920000.0); + radio_handler->start_rx(); /* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */ uint32_t max_peak_cell = 0; @@ -267,8 +269,8 @@ bool phy::decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell_ptr, uint8_t b } else { ret = srslte_ue_cellsearch_scan(&cs, found_cells, &max_peak_cell); } - - cuhd_stop_rx_stream(radio_handler); + + radio_handler->stop_rx(); srslte_ue_cellsearch_free(&cs); if (ret < 0) { @@ -294,10 +296,10 @@ bool phy::decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell_ptr, uint8_t b /* Find and decode MIB */ uint32_t sfn, sfn_offset; - cuhd_start_rx_stream(radio_handler); + radio_handler->start_rx(); ret = srslte_ue_mib_sync_decode(&ue_mib_sync, params_db.get_param(params::CELLSEARCH_TIMEOUT_MIB_NFRAMES), bch_payload, &cell_ptr->nof_ports, &sfn_offset); - cuhd_stop_rx_stream(radio_handler); + radio_handler->stop_rx(); srslte_ue_mib_sync_free(&ue_mib_sync); if (ret == 1) { @@ -372,8 +374,8 @@ void phy::run_rx_tx_state() prach_buffer.send(radio_handler, rx_time); } // send ul buffer if we have to - if (get_ul_buffer(current_tti)->is_ready_to_send()) { - get_ul_buffer(current_tti)->send_packet(radio_handler, rx_time); + if (get_ul_buffer(current_tti)->is_released()) { + get_ul_buffer(current_tti)->send_packet(radio_handler, time_adv_sec, rx_time); } ttisync->increase(); } diff --git a/srslte/lib/ue_itf/src/prach.cc b/srslte/lib/ue_itf/src/prach.cc index 138a9fec6..7a0b82a2e 100644 --- a/srslte/lib/ue_itf/src/prach.cc +++ b/srslte/lib/ue_itf/src/prach.cc @@ -28,8 +28,9 @@ #include #include #include -#include "srslte/srslte.h" +#include "srslte/srslte.h" +#include "srslte/cuhd/cuhd.h" #include "srslte/ue_itf/prach.h" #include "srslte/ue_itf/phy.h" #include "srslte/ue_itf/params.h" @@ -76,20 +77,26 @@ bool prach::init_cell(srslte_cell_t cell, params *params_db_) return true; } -bool prach::ready_to_send(uint32_t preamble_idx_) +bool prach::prepare_to_send(uint32_t preamble_idx_) { if (initiated && preamble_idx_ < 64) { preamble_idx = preamble_idx_; + INFO("PRACH Buffer: Prepare to send preamble %d\n", preamble_idx); return true; } else { return false; } } -bool prach::is_ready_to_send(uint32_t current_tti) { - if (preamble_idx >= 0 && preamble_idx < 64 && params_db != NULL) { +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; + + // Get SFN and sf_idx from the PRACH configuration index uint32_t config_idx = (uint32_t) params_db->get_param(params::PRACH_CONFIG_INDEX); srslte_prach_sfn_t prach_sfn = srslte_prach_get_sfn(config_idx); + if (prach_sfn == SRSLTE_PRACH_SFN_EVEN && ((current_tti/10)%2)==0 || prach_sfn == SRSLTE_PRACH_SFN_ANY) { @@ -97,17 +104,25 @@ bool prach::is_ready_to_send(uint32_t current_tti) { srslte_prach_sf_config(config_idx, &sf_config); for (int i=0;iget_param(params::PUSCH_BETA); - drms_cfg.group_hopping_en = params_db->get_param(params::PUSCH_RS_GROUP_HOPPING_EN); - drms_cfg.sequence_hopping_en = params_db->get_param(params::PUSCH_RS_SEQUENCE_HOPPING_EN); - drms_cfg.cyclic_shift = params_db->get_param(params::PUSCH_RS_CYCLIC_SHIFT); - drms_cfg.delta_ss = params_db->get_param(params::PUSCH_RS_GROUP_ASSIGNMENT); - - srslte_pusch_hopping_cfg_t pusch_hopping; - pusch_hopping.n_sb = params_db->get_param(params::PUSCH_HOPPING_N_SB); - pusch_hopping.hop_mode = params_db->get_param(params::PUSCH_HOPPING_INTRA_SF) ? - 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; - - srslte_ue_ul_set_pusch_cfg(&ue_ul, &drms_cfg, &pusch_hopping); + if (is_ready()) { + if (!pusch_grant.is_uplink()) { + fprintf(stderr, "Error in UL buffer: Invalid scheduling grant. Grant is for Downlink\n"); + return false; + } + + srslte_refsignal_drms_pusch_cfg_t drms_cfg; + bzero(&drms_cfg, sizeof(srslte_refsignal_drms_pusch_cfg_t)); + + drms_cfg.beta_pusch = (float) params_db->get_param(params::PUSCH_BETA)/10; + drms_cfg.group_hopping_en = params_db->get_param(params::PUSCH_RS_GROUP_HOPPING_EN); + drms_cfg.sequence_hopping_en = params_db->get_param(params::PUSCH_RS_SEQUENCE_HOPPING_EN); + drms_cfg.cyclic_shift = params_db->get_param(params::PUSCH_RS_CYCLIC_SHIFT); + drms_cfg.delta_ss = params_db->get_param(params::PUSCH_RS_GROUP_ASSIGNMENT); + + srslte_pusch_hopping_cfg_t pusch_hopping; + pusch_hopping.n_sb = params_db->get_param(params::PUSCH_HOPPING_N_SB); + pusch_hopping.hop_mode = params_db->get_param(params::PUSCH_HOPPING_INTRA_SF) ? + 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; + + 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%10, pusch_grant.get_rnti(), - signal_buffer); - if (n < 0) { - fprintf(stderr, "Error encoding PUSCH\n"); + 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(), + signal_buffer); + if (n < 0) { + fprintf(stderr, "Error in UL buffer: Error encoding PUSCH\n"); + return false; + } + release(); + return true; + } else { + fprintf(stderr, "Error in UL buffer: buffer not released\n"); return false; } - - signal_generated = true; - - /* This is done by the transmission thread - srslte_vec_sc_prod_cfc(signal_buffer, beta_pusch, signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb)); - float time_adv_sec = TA_OFFSET + ((float) n_ta)*LTE_TS; - srslte_timestamp_t next_tx_time; - srslte_timestamp_copy(&next_tx_time, &last_rx_time); - srslte_timestamp_add(&next_tx_time, 0, 0.003 - time_adv_sec); - */ - // Send through radio - - return true; } bool ul_buffer::generate_pucch(srslte_uci_data_t uci_data) @@ -118,9 +119,19 @@ bool ul_buffer::generate_pucch(srslte_uci_data_t uci_data) return false; } -bool ul_buffer::send_packet(void *radio_handler, srslte_timestamp_t rx_time) +bool ul_buffer::send_packet(radio *radio_handler, float time_adv_sec, 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", + srslte_timestamp_real(&rx_time), + srslte_timestamp_real(&tx_time), time_adv_sec*1000000); + + radio_handler->tx(signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), tx_time); + + ready(); } } // namespace ue diff --git a/srslte/lib/ue_itf/test/CMakeLists.txt b/srslte/lib/ue_itf/test/CMakeLists.txt index 389c4c484..ce9da9c20 100644 --- a/srslte/lib/ue_itf/test/CMakeLists.txt +++ b/srslte/lib/ue_itf/test/CMakeLists.txt @@ -24,4 +24,7 @@ LIST(FIND OPTIONAL_LIBS cuhd CUHD_FIND) IF(${CUHD_FIND} GREATER -1) ADD_EXECUTABLE(ue_itf_test_sib1 ue_itf_test_sib1.cc) TARGET_LINK_LIBRARIES(ue_itf_test_sib1 srslte++ cuhd) + + ADD_EXECUTABLE(ue_itf_test_prach ue_itf_test_prach.cc) + TARGET_LINK_LIBRARIES(ue_itf_test_prach srslte++ cuhd) ENDIF(${CUHD_FIND} GREATER -1) diff --git a/srslte/lib/ue_itf/test/ue_itf_test_prach.cc b/srslte/lib/ue_itf/test/ue_itf_test_prach.cc new file mode 100644 index 000000000..2cfb4aa39 --- /dev/null +++ b/srslte/lib/ue_itf/test/ue_itf_test_prach.cc @@ -0,0 +1,361 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * srsLTE 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. + * + * srsLTE 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 + +#include "srslte/utils/debug.h" +#include "srslte/ue_itf/phy.h" +#include "srslte/ue_itf/tti_sync_cv.h" +#include "srslte/cuhd/radio_uhd.h" + +/********************************************************************** + * Program arguments processing + ***********************************************************************/ +typedef struct { + float uhd_rx_freq; + float uhd_tx_freq; + float uhd_rx_gain; + float uhd_tx_gain; +}prog_args_t; + +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; +} + +void usage(prog_args_t *args, char *prog) { + printf("Usage: %s [gGv] -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-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) { + switch (opt) { + case 'g': + args->uhd_rx_gain = atof(argv[optind]); + break; + case 'G': + args->uhd_tx_gain = atof(argv[optind]); + break; + case 'f': + args->uhd_rx_freq = atof(argv[optind]); + break; + case 'F': + args->uhd_tx_freq = atof(argv[optind]); + break; + case 'v': + srslte_verbose++; + break; + default: + usage(args, argv[0]); + exit(-1); + } + } + if (args->uhd_rx_freq < 0 || args->uhd_tx_freq < 0) { + usage(args, argv[0]); + exit(-1); + } +} + + + +typedef enum{ + rar_tpc_n6dB = 0, + rar_tpc_n4dB, + rar_tpc_n2dB, + rar_tpc_0dB, + rar_tpc_2dB, + rar_tpc_4dB, + rar_tpc_6dB, + rar_tpc_8dB, + rar_tpc_n_items, +}rar_tpc_command_t; +static const char tpc_command_text[rar_tpc_n_items][8] = {"-6dB", "-4dB", "-2dB", "0dB", "2dB", "4dB", "6dB", "8dB"}; +typedef enum{ + rar_header_type_bi = 0, + rar_header_type_rapid, + rar_header_type_n_items, +}rar_header_t; +static const char rar_header_text[rar_header_type_n_items][8] = {"BI", "RAPID"}; + +typedef struct { + rar_header_t hdr_type; + bool hopping_flag; + rar_tpc_command_t tpc_command; + bool ul_delay; + bool csi_req; + uint16_t rba; + uint16_t timing_adv_cmd; + uint16_t temp_c_rnti; + uint8_t mcs; + uint8_t RAPID; + uint8_t BI; +}rar_msg_t; + +char *bool_to_string(bool x) { + if (x) { + return (char*) "Enabled"; + } else { + return (char*) "Disabled"; + } +} + +void rar_msg_fprint(FILE *stream, rar_msg_t *msg) +{ + fprintf(stream, "Header type: %s\n", rar_header_text[msg->hdr_type]); + fprintf(stream, "Hopping flag: %s\n", bool_to_string(msg->hopping_flag)); + fprintf(stream, "TPC command: %s\n", tpc_command_text[msg->tpc_command]); + fprintf(stream, "UL delay: %s\n", bool_to_string(msg->ul_delay)); + fprintf(stream, "CSI required: %s\n", bool_to_string(msg->csi_req)); + fprintf(stream, "RBA: %d\n", msg->rba); + fprintf(stream, "TA: %d\n", msg->timing_adv_cmd); + fprintf(stream, "T-CRNTI: %d\n", msg->temp_c_rnti); + fprintf(stream, "MCS: %d\n", msg->mcs); + fprintf(stream, "RAPID: %d\n", msg->RAPID); + fprintf(stream, "BI: %d\n", msg->BI); +} + +int rar_unpack(uint8_t *buffer, rar_msg_t *msg) +{ + int ret = SRSLTE_ERROR; + uint8_t *ptr = buffer; + + if(buffer != NULL && + msg != NULL) + { + ptr++; + msg->hdr_type = (rar_header_t) *ptr++; + if(msg->hdr_type == rar_header_type_bi) { + ptr += 2; + msg->BI = srslte_bit_unpack(&ptr, 4); + ret = SRSLTE_SUCCESS; + } else if (msg->hdr_type == rar_header_type_rapid) { + msg->RAPID = srslte_bit_unpack(&ptr, 6); + ptr++; + + msg->timing_adv_cmd = srslte_bit_unpack(&ptr, 11); + msg->hopping_flag = *ptr++; + msg->rba = srslte_bit_unpack(&ptr, 10); + msg->mcs = srslte_bit_unpack(&ptr, 4); + msg->tpc_command = (rar_tpc_command_t) srslte_bit_unpack(&ptr, 3); + msg->ul_delay = *ptr++; + msg->csi_req = *ptr++; + msg->temp_c_rnti = srslte_bit_unpack(&ptr, 16); + ret = SRSLTE_SUCCESS; + } + } + + return(ret); +} + + + +srslte::ue::phy phy; + +uint8_t payload[1024]; +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; +rar_msg_t rar_msg; +uint32_t nof_rx_connsetup = 0, nof_rx_rar = 0, nof_tx_ra = 0; + +void config_phy() { + phy.set_param(srslte::ue::params::PRACH_CONFIG_INDEX, 0); + phy.set_param(srslte::ue::params::PRACH_FREQ_OFFSET, 0); + phy.set_param(srslte::ue::params::PRACH_HIGH_SPEED_FLAG, 0); + phy.set_param(srslte::ue::params::PRACH_ROOT_SEQ_IDX, 0); + phy.set_param(srslte::ue::params::PRACH_ZC_CONFIG, 1); + + phy.set_param(srslte::ue::params::PUSCH_BETA, 10); + phy.set_param(srslte::ue::params::PUSCH_RS_GROUP_HOPPING_EN, 0); + phy.set_param(srslte::ue::params::PUSCH_RS_SEQUENCE_HOPPING_EN, 0); + phy.set_param(srslte::ue::params::PUSCH_RS_CYCLIC_SHIFT, 0); + phy.set_param(srslte::ue::params::PUSCH_HOPPING_OFFSET, 0); + +} + +// This is the MAC implementation +void run_tti(uint32_t tti) { + INFO("MAC running tti: %d\n", 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) { + // Indicate PHY to transmit the PRACH when possible + if (phy.send_prach(preamble_idx)) { + ra_tti = tti; + nof_tx_ra++; + state = RAR; + } else { + fprintf(stderr, "Error sending PRACH\n"); + exit(-1); + } + } 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; + } + } + } + } + } + } 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++; + state = RA; + } + } + } + } + if (srslte_verbose == SRSLTE_VERBOSE_NONE) { + printf("RECV RAR %.1f \%% RECV ConnSetup %.1f \%% (total RA: %5u) \r", + (float) 100*nof_rx_rar/nof_tx_ra, + (float) 100*nof_rx_connsetup/nof_tx_ra, + 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; + + parse_args(&prog_args, argc, argv); + + // Init Radio + radio_uhd.init(); + + // Init PHY + phy.init(&radio_uhd, &ttisync); + + // Give it time to create thread + sleep(1); + + // Setup PHY parameters + config_phy(); + + // Set RX freq and gain + phy.get_radio()->set_rx_freq(prog_args.uhd_rx_freq); + phy.get_radio()->set_tx_freq(prog_args.uhd_tx_freq); + phy.get_radio()->set_rx_gain(prog_args.uhd_rx_gain); + phy.get_radio()->set_tx_gain(prog_args.uhd_tx_gain); + + /* Instruct the PHY to decode BCH */ + if (!phy.decode_mib_best(&cell, bch_payload)) { + exit(-1); + } + // Print MIB + srslte_cell_fprint(stdout, &cell, phy.get_current_tti()/10); + + // Set the current PHY cell to the detected cell + if (!phy.set_cell(cell)) { + printf("Error setting cell\n"); + exit(-1); + } + + /* Instruct the PHY to start RX streaming and synchronize */ + if (!phy.start_rxtx()) { + printf("Could not start RX\n"); + exit(-1); + } + /* go to idle and process each tti */ + while(1) { + uint32_t tti = ttisync.wait(); + run_tti(tti); + } +} + + + diff --git a/srslte/lib/ue_itf/test/ue_itf_test_sib1.cc b/srslte/lib/ue_itf/test/ue_itf_test_sib1.cc index 416ec88d0..74ac09836 100644 --- a/srslte/lib/ue_itf/test/ue_itf_test_sib1.cc +++ b/srslte/lib/ue_itf/test/ue_itf_test_sib1.cc @@ -30,7 +30,7 @@ #include "srslte/utils/debug.h" #include "srslte/ue_itf/phy.h" #include "srslte/ue_itf/tti_sync_cv.h" - +#include "srslte/cuhd/radio_uhd.h" /********************************************************************** @@ -92,35 +92,33 @@ uint8_t payload[1024]; // This is the MAC implementation void run_tti(uint32_t tti) { - srslte::ue::sched_grant grant = srslte::ue::sched_grant(SRSLTE_SIRNTI); + srslte::ue::sched_grant grant = srslte::ue::sched_grant(srslte::ue::sched_grant::DOWNLINK, SRSLTE_SIRNTI); INFO("MAC running tti: %d\n", tti); // SIB1 is scheduled in subframe #5 of even frames if ((phy.tti_to_SFN(tti)%2) == 0 && phy.tti_to_subf(tti) == 5) { - // Get buffer srslte::ue::dl_buffer *buffer = phy.get_dl_buffer(tti); // Get DL grant - if (buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_SIRNTI, SRSLTE_SIRNTI, &grant)) + if (buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_SIRNTI, &grant)) { total_dci++; - - // MAC sets RV and RNTI + // MAC sets RV grant.set_rv(((uint32_t) ceilf((float)3*((phy.tti_to_SFN(tti)/2)%4)/2))%4); // Decode packet if (!buffer->decode_pdsch(grant, payload)) { total_errors++; } - } + } total_pkts++; } if (srslte_verbose == SRSLTE_VERBOSE_NONE) { printf("PDCCH BLER %.1f \%% PDSCH BLER %.1f \%% (total pkts: %5u) \r", 100-(float) 100*total_dci/total_pkts, (float) 100*total_errors/total_pkts, - total_pkts); + total_pkts); } } @@ -130,18 +128,22 @@ int main(int argc, char *argv[]) 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; parse_args(&prog_args, argc, argv); + // Init Radio + radio_uhd.init(); + // Init PHY - phy.init(&ttisync); + phy.init(&radio_uhd, &ttisync); // Give it time to create thread sleep(1); // Set RX freq and gain - phy.set_rx_freq(prog_args.uhd_freq); - phy.set_rx_gain(prog_args.uhd_gain); + phy.get_radio()->set_rx_freq(prog_args.uhd_freq); + phy.get_radio()->set_rx_gain(prog_args.uhd_gain); /* Instruct the PHY to decode BCH */ if (!phy.decode_mib_best(&cell, bch_payload)) {