diff --git a/CMakeLists.txt b/CMakeLists.txt index 87d5a8d10..5bb92e8dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,19 +134,6 @@ MACRO(LIBLTE_SET_PIC) ENDIF( CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" ) ENDMACRO(LIBLTE_SET_PIC) -######################################################################## -# A macro for passing lists between different directories -# through an internal cache variable. -######################################################################## -MACRO (APPEND_INTERNAL_LIST LIST_NAME VALUE) - # If the list in not in the cache, create it. - IF (${LIST_NAME}) - SET (${LIST_NAME} "${${LIST_NAME}};${VALUE}" CACHE INTERNAL "Internal variable") - ELSE (${LIST_NAME}) - SET (${LIST_NAME} "${VALUE}" CACHE INTERNAL "Internal variable") - ENDIF (${LIST_NAME}) -ENDMACRO (APPEND_INTERNAL_LIST) - ######################################################################## # Print summary ######################################################################## @@ -156,15 +143,12 @@ MESSAGE(STATUS "Building for version: ${VERSION}") ######################################################################## # Add general includes and dependencies ######################################################################## -INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/common/include) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/srslte/include/) -INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/cuhd/include) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/mex/include) ######################################################################## # Add the subdirectories ######################################################################## -ADD_SUBDIRECTORY(common) -ADD_SUBDIRECTORY(cuhd) ADD_SUBDIRECTORY(srslte) -add_subdirectory(mex) +ADD_SUBDIRECTORY(mex) +ADD_SUBDIRECTORY(srsapps) diff --git a/cmake/modules/FindUHD.cmake b/cmake/modules/FindUHD.cmake index 4f989718f..52e37d3fb 100644 --- a/cmake/modules/FindUHD.cmake +++ b/cmake/modules/FindUHD.cmake @@ -16,8 +16,8 @@ FIND_LIBRARY( HINTS $ENV{UHD_DIR}/lib PATHS /usr/local/lib /usr/lib - /usr/local/lib64 - /usr/local/lib32 + /usr/local/lib64 + /usr/local/lib32 ) INCLUDE(FindPackageHandleStandardArgs) diff --git a/cuhd/CMakeLists.txt b/cuhd/CMakeLists.txt deleted file mode 100644 index c0ab96c17..000000000 --- a/cuhd/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2012-2013 The srsLTE Developers. See the -# COPYRIGHT file at the top-level directory of this distribution. -# -# 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/. -# - -######################################################################## -# Install headers -######################################################################## -INSTALL(DIRECTORY include/ - DESTINATION "${INCLUDE_DIR}" - FILES_MATCHING PATTERN "*.h" - PATTERN ".svn" EXCLUDE -) - -######################################################################## -# Add headers to cmake project (useful for IDEs) -######################################################################## -SET(HEADERS_ALL "") -FILE(GLOB headers *) -FOREACH (_header ${headers}) - IF(IS_DIRECTORY ${_header}) - FILE(GLOB_RECURSE tmp "${_header}/*.h") - LIST(APPEND HEADERS_ALL ${tmp}) - ENDIF(IS_DIRECTORY ${_header}) -ENDFOREACH() -ADD_CUSTOM_TARGET (add_cuhd_headers SOURCES ${HEADERS_ALL}) - -######################################################################## -# Add the subdirectories -######################################################################## -ADD_SUBDIRECTORY(lib) - diff --git a/cuhd/include/srslte/cuhd/cuhd_utils.h b/cuhd/include/srslte/cuhd/cuhd_utils.h deleted file mode 100644 index 7f6654c97..000000000 --- a/cuhd/include/srslte/cuhd/cuhd_utils.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * - * \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/config.h" - -SRSLTE_API int cuhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double fs, int nsamp); diff --git a/cuhd/lib/cuhd_utils.c b/cuhd/lib/cuhd_utils.c deleted file mode 100644 index 95d68686a..000000000 --- a/cuhd/lib/cuhd_utils.c +++ /dev/null @@ -1,79 +0,0 @@ -/** - * - * \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 -#include -#include - - -#include "srslte/cuhd/cuhd.h" -#include "srslte/utils/vector.h" -#include "srslte/utils/debug.h" - -int cuhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double fs, int nsamp) { - int i, j; - int ret = -1; - _Complex float *buffer; - double f; - - buffer = calloc(nsamp, sizeof(_Complex float)); - if (!buffer) { - goto free_and_exit; - } - - cuhd_set_rx_gain(uhd, 20.0); - cuhd_set_rx_srate(uhd, fs); - - for (i=0;i + +#ifndef BINSEM_H +#define BINSEM_H + +/** Implementation of a binary semaphore using POSIX condition variable and mutex + */ + +namespace srslte { + + class binsem + { + public: + binsem() { + pthread_mutex_init(&mutex, NULL); + pthread_cond_init(&cv, NULL); + state = true; + } + ~binsem() { + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cv); + } + void take() { + pthread_mutex_lock(&mutex); + while(!state) { + pthread_cond_wait(&cv, &mutex); + } + state = false; + pthread_mutex_unlock(&mutex); + } + void give() { + pthread_mutex_lock(&mutex); + pthread_cond_signal(&cv); + state = true; + pthread_mutex_unlock(&mutex); + } + private: + pthread_cond_t cv; + pthread_mutex_t mutex; + bool state; + }; +} + +#endif diff --git a/srslte/include/srslte/ue_itf/log.h b/srsapps/common/include/srsapps/common/log.h similarity index 100% rename from srslte/include/srslte/ue_itf/log.h rename to srsapps/common/include/srsapps/common/log.h diff --git a/srsapps/common/include/srsapps/common/log_stdout.h b/srsapps/common/include/srsapps/common/log_stdout.h new file mode 100644 index 000000000..cb2135493 --- /dev/null +++ b/srsapps/common/include/srsapps/common/log_stdout.h @@ -0,0 +1,77 @@ +/** + * + * \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 +#include + +#include "srsapps/common/log.h" + +/****************************************************************************** + * File: log_stout.h + * + * Description: Logging service through standard output. Inherits log interface + * + * Reference: + *****************************************************************************/ + +#ifndef LOGSTDOUT_H +#define LOGSTDOUT_H + +using namespace std; + +namespace srslte { + +class log_stdout : public log +{ +public: + + log_stdout(string service_name_) : log(service_name_) { } + + void error(uint32_t tti, string message, ...); + void warning(uint32_t tti, string message, ...); + void info(uint32_t tti, string message, ...); + void debug(uint32_t tti, string message, ...); + + // Same with line and file info + void error(uint32_t tti, string file, int line, string message, ...); + void warning(uint32_t tti, string file, int line, string message, ...); + void info(uint32_t tti, string file, int line, string message, ...); + void debug(uint32_t tti, string file, int line, string message, ...); + +private: + typedef enum { + ERROR=0, WARNING, INFO, DEBUG, NOF_LEVELS + } level_t; + void printlog(level_t level, uint32_t tti, string file, int line, string message, va_list args); + void printlog(level_t level, uint32_t tti, string message, va_list args); +}; + +} + +#endif + diff --git a/srslte/include/srslte/ue_itf/params_db.h b/srsapps/common/include/srsapps/common/params_db.h similarity index 98% rename from srslte/include/srslte/ue_itf/params_db.h rename to srsapps/common/include/srsapps/common/params_db.h index 879a96cf6..cf48d9e98 100644 --- a/srslte/include/srslte/ue_itf/params_db.h +++ b/srsapps/common/include/srsapps/common/params_db.h @@ -26,7 +26,7 @@ */ #include -#include "srslte/srslte.h" +#include "srslte/config.h" #ifndef PARAMS_H #define PARAMS_H diff --git a/srsapps/common/include/srsapps/common/qbuff.h b/srsapps/common/include/srsapps/common/qbuff.h new file mode 100644 index 000000000..fb885b525 --- /dev/null +++ b/srsapps/common/include/srsapps/common/qbuff.h @@ -0,0 +1,66 @@ + +#include +#include "srslte/config.h" + +#ifndef QBUFF_H +#define QBUFF_H + +/** Implementation of a lock-free single-producer single-consumer queue buffer + * Communication can be pointer-based or stream based. + * Only 1 thread can read and only 1 thread can write. + * + * Writer: + * - Call request, returns a pointer. + * - Writes to memory, up to max_msg_size bytes + * - Call to push() passing message size + * or + * - use send() + * + * Reader: + * - Call to pop, receive pointer and message size + * - Read memory contents + * - Call to release() to release the message buffer + * or + * - use recv() + */ + +namespace srslte { + + class SRSLTE_API qbuff + { + public: + qbuff(); + ~qbuff(); + bool init(uint32_t nof_messages, uint32_t max_msg_size); + void* request(); + bool push(uint32_t len); + void* pop(uint32_t *len, uint32_t idx); + void* pop(uint32_t *len); + void* pop(); + void release(); + bool isempty(); + bool isfull(); + void flush(); + bool send(void *buffer, uint32_t msg_size); + int recv(void* buffer, uint32_t buffer_size); + void move_to(qbuff *dst); + uint32_t pending_data(); + private: + typedef struct { + bool valid; + uint32_t len; + void *ptr; + } pkt_t; + + uint32_t nof_messages; + uint32_t max_msg_size; + uint32_t rp, wp; + + pkt_t *packets; + uint8_t *buffer; + + }; + +} + +#endif diff --git a/srslte/include/srslte/ue_itf/queue.h b/srsapps/common/include/srsapps/common/queue.h similarity index 97% rename from srslte/include/srslte/ue_itf/queue.h rename to srsapps/common/include/srsapps/common/queue.h index b34eebc05..666171d1b 100644 --- a/srslte/include/srslte/ue_itf/queue.h +++ b/srsapps/common/include/srsapps/common/queue.h @@ -34,13 +34,15 @@ * Reference: *****************************************************************************/ +#include "srslte/config.h" + #ifndef QUEUE_H #define QUEUE_H namespace srslte { namespace ue { -class queue +class SRSLTE_API queue { public: diff --git a/srsapps/common/include/srsapps/common/timers.h b/srsapps/common/include/srsapps/common/timers.h new file mode 100644 index 000000000..cbb28e8f0 --- /dev/null +++ b/srsapps/common/include/srsapps/common/timers.h @@ -0,0 +1,102 @@ + +#include +#include "srslte/config.h" + +#ifndef TIMERS_H +#define TIMERS_H + +namespace srslte { + +class SRSLTE_API timer_callback +{ + public: + virtual void timer_expired(uint32_t timer_id) = 0; +}; + +class SRSLTE_API timers +{ +public: + class SRSLTE_API timer + { + public: + timer() { counter = 0; timeout = 0; running = false; }; + void set(timer_callback *callback_, uint32_t timeout_) { + callback = callback_; + timeout = timeout_; + } + bool is_running() { + return counter < timeout; + } + bool is_expired() { + return counter == timeout; + } + void reset() { + counter = 0; + } + void step() { + if (running) { + counter++; + if (is_expired()) { + callback->timer_expired(id); + } + } + } + void stop() { + running = false; + } + void run() { + running = true; + } + uint32_t id; + private: + timer_callback *callback; + uint32_t timeout; + uint32_t counter; + bool running; + }; + + timers(uint32_t nof_timers_) { + nof_timers = nof_timers_; + timer_list = new timer[nof_timers]; + for (uint32_t i=0;istep(); + } + } + void stop_all() { + for (int i=0;istop(); + } + } + void run_all() { + for (int i=0;irun(); + } + } + void reset_all() { + for (int i=0;ireset(); + } + } + timer *get(uint32_t i) { + if (i < nof_timers) { + return &timer_list[i]; + } else { + return NULL; + } + } +private: + uint32_t nof_timers; + timer *timer_list; +}; +} + +#endif \ No newline at end of file diff --git a/srslte/include/srslte/ue_itf/tti_sync.h b/srsapps/common/include/srsapps/common/tti_sync.h similarity index 98% rename from srslte/include/srslte/ue_itf/tti_sync.h rename to srsapps/common/include/srsapps/common/tti_sync.h index a27b105a4..5d9035df2 100644 --- a/srslte/include/srslte/ue_itf/tti_sync.h +++ b/srsapps/common/include/srsapps/common/tti_sync.h @@ -26,7 +26,7 @@ */ #include -#include "srslte/srslte.h" +#include "srslte/config.h" #ifndef TTISYNC_H #define TTISYNC_H diff --git a/srslte/include/srslte/ue_itf/tti_sync_cv.h b/srsapps/common/include/srsapps/common/tti_sync_cv.h similarity index 95% rename from srslte/include/srslte/ue_itf/tti_sync_cv.h rename to srsapps/common/include/srsapps/common/tti_sync_cv.h index 8e09420c1..37cd8319a 100644 --- a/srslte/include/srslte/ue_itf/tti_sync_cv.h +++ b/srsapps/common/include/srsapps/common/tti_sync_cv.h @@ -26,8 +26,8 @@ */ #include -#include "srslte/ue_itf/tti_sync.h" -#include "srslte/srslte.h" +#include "srsapps/common/tti_sync.h" +#include "srslte/config.h" #ifndef TTISYNC_CV_H #define TTISYNC_CV_H diff --git a/srsapps/common/src/log_stdout.cc b/srsapps/common/src/log_stdout.cc new file mode 100644 index 000000000..e928c04c1 --- /dev/null +++ b/srsapps/common/src/log_stdout.cc @@ -0,0 +1,129 @@ +/** + * + * \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 +#include +#include + +#include "srsapps/common/log_stdout.h" + + +using namespace std; + +namespace srslte { + +const char* level_str[4] = {"[ERROR ", + "[WARN ", + "[INFO ", + "[DEBUG "}; + +void log_stdout::printlog(level_t type, uint32_t tti, string msg, va_list args) { + + printlog(type, tti, string(), -1, msg, args); +} + +void log_stdout::printlog(level_t type, uint32_t tti, string file, int line, string msg, va_list args) { + + printf("%s %s",level_str[type], get_service_name().c_str()); + if (file.length() > 0) { + printf("/%-14s", file.substr(file.find_last_of("/")+1,file.find_last_of(".")-1-file.find_last_of("/")).c_str()); + } + if (line >= 0) { + printf(" %5d]: ", tti); + } + vprintf(msg.c_str(), args); +} + +void log_stdout::error(uint32_t tti, string msg, ...) +{ + va_list args; + va_start(args, msg); + printlog(ERROR, tti, msg, args); + va_end(args); +} + +void log_stdout::info(uint32_t tti, string msg, ...) +{ + va_list args; + va_start(args, msg); + printlog(INFO, tti, msg, args); + va_end(args); +} + +void log_stdout::debug(uint32_t tti, string msg, ...) +{ + va_list args; + va_start(args, msg); + printlog(DEBUG, tti, msg, args); + va_end(args); +} + +void log_stdout::warning(uint32_t tti, string msg, ...) +{ + va_list args; + va_start(args, msg); + printlog(WARNING, tti, msg, args); + va_end(args); +} + + +void log_stdout::error(uint32_t tti, string file, int line, string msg, ...) +{ + va_list args; + va_start(args, msg); + printlog(ERROR, tti, file, line, msg, args); + va_end(args); +} + +void log_stdout::info(uint32_t tti, string file, int line, string msg, ...) +{ + va_list args; + va_start(args, msg); + printlog(INFO, tti, file, line, msg, args); + va_end(args); +} + +void log_stdout::debug(uint32_t tti, string file, int line, string msg, ...) +{ + va_list args; + va_start(args, msg); + printlog(DEBUG, tti, file, line, msg, args); + va_end(args); +} + +void log_stdout::warning(uint32_t tti, string file, int line, string msg, ...) +{ + va_list args; + va_start(args, msg); + printlog(WARNING, tti, file, line, msg, args); + va_end(args); +} + +} + + \ No newline at end of file diff --git a/srsapps/common/src/qbuff.cc b/srsapps/common/src/qbuff.cc new file mode 100644 index 000000000..abdd811d2 --- /dev/null +++ b/srsapps/common/src/qbuff.cc @@ -0,0 +1,185 @@ +#include +#include +#include + + +#include "srsapps/common/qbuff.h" + +namespace srslte { + + +qbuff::qbuff() +{ + nof_messages=0; + max_msg_size=0; + wp = 0; + rp = 0; + buffer = NULL; + packets = NULL; +} + +qbuff::~qbuff() +{ + free(buffer); + free(packets); +} + +bool qbuff::init(uint32_t nof_messages_, uint32_t max_msg_size_) +{ + nof_messages = nof_messages_; + max_msg_size = max_msg_size_; + + buffer = (uint8_t*) calloc(nof_messages,max_msg_size); + packets = (pkt_t*) calloc(nof_messages,sizeof(pkt_t)); + if (buffer && packets) { + flush(); + return true; + } else { + return false; + } +} + +void qbuff::flush() +{ + wp = 0; + rp = 0; + for (int i=0;i= nof_messages)?(1-nof_messages):1; +} + +void* qbuff::pop() +{ + return pop(NULL); +} + +void* qbuff::pop(uint32_t* len) +{ + if (!isempty()) { + if (len) { + *len = packets[rp].len; + } + return packets[rp].ptr; + } else { + return NULL; + } +} + +void* qbuff::pop(uint32_t* len, uint32_t idx) +{ + if (idx == 0) { + return pop(len); + } else { + uint32_t rpp = rp; + uint32_t i = 0; + while(i= nof_messages)?(1-nof_messages):1; + i++; + } + if (packets[rpp].valid) { + if (len) { + *len = packets[rpp].len; + } + return packets[rpp].ptr; + } else { + return NULL; + } + } +} + +void qbuff::release() +{ + packets[rp].valid = false; + packets[rp].len = 0; + rp += (rp+1 >= nof_messages)?(1-nof_messages):1; +} + +bool qbuff::send(void* buffer, uint32_t msg_size) +{ + if (msg_size <= max_msg_size) { + void *ptr = request(); + if (ptr) { + memcpy(ptr, buffer, msg_size); + push(msg_size); + } else { + return false; + } + } else { + return false; + } +} + +uint32_t qbuff::pending_data() +{ + uint32_t total_len = 0; + for (int i=0;irequest(); + if (ptr_dst) { + memcpy(ptr_dst, ptr_src, len); + dst->push(len); + release(); + } + } +} + + + +int qbuff::recv(void* buffer, uint32_t buffer_size) +{ + uint32_t len; + void *ptr = pop(&len); + if (ptr) { + if (len <= buffer_size) { + memcpy(buffer, ptr, len); + release(); + return len; + } else { + return -1; + } + } else { + return 0; + } +} + + + +} \ No newline at end of file diff --git a/srslte/lib/ue_itf/src/queue.cc b/srsapps/common/src/queue.cc similarity index 98% rename from srslte/lib/ue_itf/src/queue.cc rename to srsapps/common/src/queue.cc index cc45a1b9c..2caf5ccae 100644 --- a/srslte/lib/ue_itf/src/queue.cc +++ b/srsapps/common/src/queue.cc @@ -27,7 +27,7 @@ #include #include -#include "srslte/ue_itf/queue.h" +#include "srsapps/common/queue.h" namespace srslte { namespace ue { diff --git a/srslte/lib/ue_itf/src/tti_sync_cv.cc b/srsapps/common/src/tti_sync_cv.cc similarity index 97% rename from srslte/lib/ue_itf/src/tti_sync_cv.cc rename to srsapps/common/src/tti_sync_cv.cc index 05a13a7fb..67dc41988 100644 --- a/srslte/lib/ue_itf/src/tti_sync_cv.cc +++ b/srsapps/common/src/tti_sync_cv.cc @@ -27,7 +27,7 @@ #include -#include "srslte/ue_itf/tti_sync_cv.h" +#include "srsapps/common/tti_sync_cv.h" namespace srslte { namespace ue { diff --git a/cuhd/lib/CMakeLists.txt b/srsapps/radio/CMakeLists.txt similarity index 65% rename from cuhd/lib/CMakeLists.txt rename to srsapps/radio/CMakeLists.txt index 1c7a8bcd2..f0ed75dc6 100644 --- a/cuhd/lib/CMakeLists.txt +++ b/srsapps/radio/CMakeLists.txt @@ -22,20 +22,11 @@ FIND_PACKAGE(UHD) IF(UHD_FOUND) - - 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}) - - LIBLTE_SET_PIC(cuhd) - APPEND_INTERNAL_LIST(OPTIONAL_LIBS cuhd) - INSTALL(TARGETS cuhd DESTINATION ${LIBRARY_DIR}) - - MESSAGE(STATUS " cuhd UHD C wrapper will be installed.") - -ELSE(UHD_FOUND) - - MESSAGE(STATUS " UHD driver not found. CUHD library is not generated") - + FILE(GLOB SOURCES "src/*.cc") + ADD_LIBRARY(srsapps_radio SHARED ${SOURCES}) + INSTALL(TARGETS srsapps_radio DESTINATION ${LIBRARY_DIR}) + LIBLTE_SET_PIC(srsapps_radio) ENDIF(UHD_FOUND) + +FILE(GLOB SOURCES "include/srsapps/radio/*.h") +ADD_CUSTOM_TARGET (add_srsapps_radio_headers SOURCES ${HEADERS_ALL}) diff --git a/cuhd/include/srslte/cuhd/radio_uhd.h b/srsapps/radio/include/srsapps/radio/radio_uhd.h similarity index 100% rename from cuhd/include/srslte/cuhd/radio_uhd.h rename to srsapps/radio/include/srsapps/radio/radio_uhd.h diff --git a/cuhd/lib/radio_uhd.cc b/srsapps/radio/src/radio_uhd.cc similarity index 96% rename from cuhd/lib/radio_uhd.cc rename to srsapps/radio/src/radio_uhd.cc index 7e25be61c..30de38298 100644 --- a/cuhd/lib/radio_uhd.cc +++ b/srsapps/radio/src/radio_uhd.cc @@ -27,7 +27,7 @@ #include "srslte/srslte.h" #include "srslte/common/radio.h" -#include "srslte/cuhd/radio_uhd.h" +#include "srsapps/radio/radio_uhd.h" namespace srslte { @@ -49,7 +49,7 @@ bool radio_uhd::init(char *args) bool radio_uhd::rx_at(void* buffer, uint32_t nof_samples, srslte_timestamp_t rx_time) { - fprintf(stderr, "UHD Receive at time not implemented\n"); + fprintf(stderr, "Not implemented\n"); return false; } diff --git a/srsapps/ue/CMakeLists.txt b/srsapps/ue/CMakeLists.txt new file mode 100644 index 000000000..f09fc8c6b --- /dev/null +++ b/srsapps/ue/CMakeLists.txt @@ -0,0 +1,27 @@ +# +# Copyright 2012-2013 The srsLTE Developers. See the +# COPYRIGHT file at the top-level directory of this distribution. +# +# 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_DIRECTORIES(phy/include/) +INCLUDE_DIRECTORIES(mac/include/) + +add_subdirectory(phy) +add_subdirectory(mac) + diff --git a/srsapps/ue/mac/CMakeLists.txt b/srsapps/ue/mac/CMakeLists.txt new file mode 100644 index 000000000..899a09459 --- /dev/null +++ b/srsapps/ue/mac/CMakeLists.txt @@ -0,0 +1,29 @@ +# +# Copyright 2012-2013 The srsLTE Developers. See the +# COPYRIGHT file at the top-level directory of this distribution. +# +# 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/. +# + +FILE(GLOB SOURCES "src/*.cc") +ADD_LIBRARY(srsapps_ue_mac SHARED ${SOURCES}) +INSTALL(TARGETS srsapps_ue_mac DESTINATION ${LIBRARY_DIR}) +LIBLTE_SET_PIC(srsapps_ue_mac) + +FILE(GLOB SOURCES "include/*.h") +ADD_CUSTOM_TARGET (add_srsapps_ue_mac_headers SOURCES ${HEADERS_ALL}) + diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/demux.h b/srsapps/ue/mac/include/srsapps/ue/mac/demux.h new file mode 100644 index 000000000..af386555f --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/demux.h @@ -0,0 +1,53 @@ + +#include "srsapps/ue/phy/phy.h" +#include "srsapps/common/log.h" +#include "srsapps/ue/mac/mac_io.h" +#include "srsapps/common/timers.h" +#include "srsapps/ue/mac/mac_params.h" +#include "srsapps/ue/mac/mac_pdu.h" + +#ifndef DEMUX_H +#define DEMUX_H + +/* Logical Channel Demultiplexing and MAC CE dissassemble */ + +namespace srslte { +namespace ue { + +class demux +{ +public: + demux(); + void init(phy* phy_h_, log* log_h_, mac_io* mac_io_h_, timers* timers_db_); + + void push_pdu(uint32_t tti, uint8_t *mac_pdu, uint32_t nof_bits); + void push_pdu_bcch(uint32_t tti, uint8_t *mac_pdu, uint32_t nof_bits); + void push_pdu_temp_crnti(uint32_t tti, uint8_t *mac_pdu, uint32_t nof_bits); + bool is_temp_crnti_pending(); + void demultiplex_pending_pdu(uint32_t tti); + + uint64_t get_contention_resolution_id(); + +private: + mac_pdu mac_msg; + mac_pdu pending_mac_msg; + + void process_pdu(mac_pdu *pdu); + bool process_ce(mac_pdu::mac_subh *subheader); + + uint64_t contention_resolution_id; + bool pending_temp_rnti; + + phy *phy_h; + log *log_h; + mac_io *mac_io_h; + timers *timers_db; + uint32_t tti; +}; +} +} + +#endif + + + diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/dl_harq.h b/srsapps/ue/mac/include/srsapps/ue/mac/dl_harq.h new file mode 100644 index 000000000..f1aab3755 --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/dl_harq.h @@ -0,0 +1,74 @@ + + +#include "srsapps/common/log.h" +#include "srsapps/ue/phy/phy.h" +#include "srsapps/ue/mac/mac_params.h" +#include "srsapps/common/timers.h" +#include "srsapps/ue/mac/demux.h" + +#ifndef DLHARQ_H +#define DLHARQ_H + +/* Downlink HARQ entity as defined in 5.3.2 of 36.321 */ + +namespace srslte { +namespace ue { + +typedef _Complex float cf_t; + +class dl_harq_entity +{ +public: + + const static uint32_t NOF_HARQ_PROC = 8; + const static uint32_t HARQ_BCCH_PID = NOF_HARQ_PROC; + + dl_harq_entity(); + ~dl_harq_entity(); + bool init(srslte_cell_t cell, uint32_t max_payload_len, srslte::log *log_h_, timers *timers_, demux *demux_unit); + bool is_sps(uint32_t pid); + void set_harq_info(uint32_t tti, uint32_t pid, dl_sched_grant *grant); + void receive_data(uint32_t tti, uint32_t pid, dl_buffer *dl_buffer, phy *phy_h); + void reset(); + bool is_ack_pending_resolution(); + void send_pending_ack_contention_resolution(); +private: + + + class dl_harq_process { + public: + dl_harq_process(); + bool init(srslte_cell_t cell, uint32_t max_payload_len, dl_harq_entity *parent); + void set_harq_info(uint32_t tti, dl_sched_grant *grant); + void receive_data(uint32_t tti, dl_buffer *dl_buffer, phy *phy_h); + void reset(); + // Called after the contention resolution is terminated to send pending ACKs, if any + void send_pending_ack_contention_resolution(); + uint32_t pid; + private: + + dl_harq_entity *harq_entity; + uint8_t *payload; + uint32_t max_payload_len; + dl_sched_grant cur_grant; + dl_sched_grant pending_ack_grant; + ul_buffer *pending_ul_buffer; + bool is_first_tx; + bool is_first_decoded; + bool pending_ack; + srslte::log *log_h; + + srslte_softbuffer_rx_t softbuffer; + }; + + + dl_harq_process *proc; + timers *timers_db; + demux *demux_unit; + srslte::log *log_h; + int pending_ack_pid; +}; + +} +} +#endif \ No newline at end of file diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/dl_sps.h b/srsapps/ue/mac/include/srsapps/ue/mac/dl_sps.h new file mode 100644 index 000000000..4bbfeb0d4 --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/dl_sps.h @@ -0,0 +1,31 @@ + + +#include "srsapps/common/log.h" +#include "srsapps/ue/phy/phy.h" +#include "srsapps/ue/mac/mac_params.h" +#include "srsapps/common/timers.h" + +#ifndef DLSPS_H +#define DLSPS_H + +/* Downlink Semi-Persistent schedulign (Section 5.10.1) */ + +namespace srslte { +namespace ue { + +typedef _Complex float cf_t; + +class dl_sps +{ +public: + + void clear(); + void reset(uint32_t tti, dl_sched_grant *grant); + dl_sched_grant *get_pending_grant(uint32_t tti); +private: + +}; + +} +} +#endif \ No newline at end of file diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/mac.h b/srsapps/ue/mac/include/srsapps/ue/mac/mac.h new file mode 100644 index 000000000..6b77fdc29 --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/mac.h @@ -0,0 +1,116 @@ + + +#include "srsapps/common/log.h" +#include "srsapps/common/tti_sync.h" +#include "srsapps/ue/phy/phy.h" +#include "srsapps/ue/mac/mac_params.h" +#include "srsapps/ue/mac/dl_harq.h" +#include "srsapps/ue/mac/ul_harq.h" +#include "srsapps/ue/mac/dl_sps.h" +#include "srsapps/ue/mac/ul_sps.h" +#include "srsapps/common/timers.h" +#include "srsapps/ue/mac/mac_io.h" +#include "srsapps/ue/mac/proc_ra.h" +#include "srsapps/ue/mac/proc_sr.h" +#include "srsapps/ue/mac/proc_bsr.h" +#include "srsapps/ue/mac/proc_phr.h" +#include "srsapps/ue/mac/mux.h" +#include "srsapps/ue/mac/demux.h" + +#ifndef UEMAC_H +#define UEMAC_H + +namespace srslte { +namespace ue { + +typedef _Complex float cf_t; + +class mac : public timer_callback +{ +public: + mac() : timers_db((uint32_t) NOF_MAC_TIMERS) {} + bool init(phy *phy_h, tti_sync *ttisync, log *log_h); + void stop(); + int get_tti(); + void main_radio_loop(); // called after thread creation + + bool send_ccch_sdu(uint8_t *sdu_payload, uint32_t nbytes); + bool send_dtch0_sdu(uint8_t *sdu_payload, uint32_t nbytes); // SRB0 + bool send_dcch0_sdu(uint8_t *sdu_payload, uint32_t nbytes); // DRB0 + + int recv_bcch_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes); + int recv_ccch_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes); + int recv_dtch0_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes); // SRB0 + int recv_dcch0_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes); // DRB0 + + void set_dcch0_priority(uint32_t priority, int PBR_x_tti, uint32_t BSD); + void set_dtch0_priority(uint32_t priority, int PBR_x_tti, uint32_t BSD); + + void set_param(mac_params::mac_param_t param, int64_t value); + + void reconfiguration(); + void reset(); + + void timer_expired(uint32_t timer_id); + + enum { + HARQ_RTT = 0, + TIME_ALIGNMENT, + CONTENTION_TIMER, + NOF_MAC_TIMERS + } mac_timers_t; + +private: + // Interaction with PHY + tti_sync *ttisync; + phy *phy_h; + + log *log_h; + + /* Logical channel (lch) IO */ + mac_io mac_io_lch; + + + mac_params params_db; + pthread_t mac_thread; + static void* mac_thread_fnc(void*); + + int tti; + bool started = false; + bool is_synchronized; + bool is_first_temporal; + + /* Multiplexing/Demultiplexing Units */ + mux mux_unit; + demux demux_unit; + + /* DL/UL HARQ */ + dl_harq_entity dl_harq; + ul_harq_entity ul_harq; + + /* DL/UL Semi-Persistent Sched */ + dl_sps dl_sps_assig; + ul_sps ul_sps_assig; + uint32_t get_harq_sps_pid(uint32_t tti); + + /* MAC Uplink-related Procedures */ + ra_proc ra_procedure; + sr_proc sr_procedure; + bsr_proc bsr_procedure; + phr_proc phr_procedure; + + /* Other procedures */ + void process_dl_grants(uint32_t tti); + void process_ul_grants(uint32_t tti); + void receive_pch(uint32_t tti); + + /* Functions for MAC Timers */ + timers timers_db; + void setup_timers(); + void timeAlignmentTimerExpire(); + +}; + +} +} +#endif \ No newline at end of file diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/mac_io.h b/srsapps/ue/mac/include/srsapps/ue/mac/mac_io.h new file mode 100644 index 000000000..b2e98f92f --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/mac_io.h @@ -0,0 +1,84 @@ +#include +#include "srsapps/common/qbuff.h" + +#ifndef MACIO_H +#define MACIO_H + +/* Manages all MAC buffers including: + * - communication with higher layers through logical channels + * - communication between logical channels buffers and Dissassembly/Assembly unit + * - communication between Dissassembly/Assembly unit and Msg3 buffer + * + * For logical channels, IN means higher layers to MAC. OUT means MAC to higher layers. + * + * See queue.h for instructions on how to manage buffers + */ + +namespace srslte { +namespace ue { + + class mac_io + { + public: + + // list of logical channels + // Keep this order to match LoCH id with RB + typedef enum { + // Downlink (UE MAC -> UE RRC) + MAC_LCH_CCCH_DL = 0, // SRB0 + MAC_LCH_DCCH0_DL, // SRB1 + MAC_LCH_DCCH1_DL, // SRB2 + MAC_LCH_DTCH0_DL, // DRB0 + MAC_LCH_DTCH1_DL, // DRB1 + MAC_LCH_DTCH2_DL, // DRB2 + MAC_LCH_BCCH_DL, // N/A + MAC_LCH_PCCH_DL, // N/A + + // Uplink (UE RLC -> UE MAC) + MAC_LCH_CCCH_UL, // SRB0 + MAC_LCH_DCCH0_UL, // SRB1 + MAC_LCH_DCCH1_UL, // SRB2 + MAC_LCH_DTCH0_UL, // DRB0 + MAC_LCH_DTCH1_UL, // DRB1 + MAC_LCH_DTCH2_UL, // DRB2 + + MAC_NOF_QUEUES + } mac_lch_t; + + const static int NOF_DL_LCH = MAC_LCH_PCCH_DL - MAC_LCH_CCCH_DL; + const static int NOF_UL_LCH = MAC_LCH_DTCH2_UL - MAC_LCH_CCCH_UL; + + const static int DEFAULT_MSG_SZ = 8*1024; // 8 Kbytes + const static int DEFAULT_NOF_MESSAGES = 8; + + + qbuff* get(mac_lch_t ch) { + return get((uint32_t) ch); + } + + qbuff* get(int32_t lchid) { + if (lchid < MAC_NOF_QUEUES) { + return &queues[lchid]; + } else { + return NULL; + } + } + + // Move packets between queues with only 1 memcpy + void move(mac_lch_t src, mac_lch_t dst) { + get(src)->move_to(get(dst)); + } + + mac_io() { + for (int i=0;i +#include "srsapps/common/log.h" + +#ifndef MACPDU_H +#define MACPDU_H + +/* MAC PDU Packing/Unpacking functions */ + +namespace srslte { +namespace ue { + +class mac_pdu +{ +public: + + class mac_subh + { + public: + + typedef enum { + C_RNTI = 0, + CON_RES_ID, + TA_CMD, + PHD, + SDU + } cetype; + + // Reading functions + bool is_sdu(); + cetype ce_type(); + + uint32_t get_sdu_lcid(); + uint32_t get_sdu_nbytes(); + uint8_t* get_sdu_ptr(); + + uint16_t get_c_rnti(); + uint64_t get_con_res_id(); + uint8_t get_ta_cmd(); + uint8_t get_phd(); + + // Writing functions + bool set_sdu(uint8_t *ptr, uint32_t nof_bytes); + bool set_c_rnti(uint16_t crnti); + bool set_con_res_id(uint64_t con_res_id); + bool set_ta_cmd(uint8_t ta_cmd); + bool set_phd(uint8_t phd); + + private: + static const int MAX_CE_PAYLOAD_LEN = 8; + uint32_t lcid; + uint32_t nof_bytes; + uint8_t* sdu_payload_ptr; + uint8_t ce_payload[MAX_CE_PAYLOAD_LEN]; + }; + + mac_pdu(uint32_t max_subheaders); + + void reset(); + void init(uint32_t pdu_len); + + bool read_next(); + bool write_next(); + mac_subh* get(); + + bool write_packet(uint8_t *ptr); + void parse_packet(uint8_t *ptr); + + + +protected: + mac_subh *subheaders; + uint32_t pdu_len; + uint32_t rem_len; + uint32_t rp, wp; + uint32_t nof_subheaders; + uint32_t max_subheaders; +}; + +class mac_rar_pdu +{ +public: + class mac_rar + { + + public: + + static const uint32_t RAR_GRANT_LEN = 20; + + // Reading functions + uint32_t get_rapid(); + uint32_t get_ta_cmd(); + uint16_t get_temp_crnti(); + void get_sched_grant(uint8_t grant[RAR_GRANT_LEN]); + + // Writing functoins + void set_rapid(uint32_t rapid); + void set_ta_cmd(uint32_t ta); + void set_temp_crnti(uint16_t temp_rnti); + void set_sched_grant(uint8_t grant[RAR_GRANT_LEN]); + private: + uint8_t grant[RAR_GRANT_LEN]; + uint32_t ta; + uint16_t temp_rnti; + }; + + mac_rar_pdu(uint32_t max_rars); + + void reset(); + void init(uint32_t pdu_len); + + bool read_next(); + bool write_next(); + mac_rar* get(); + + void set_backoff(uint8_t bi); + bool is_backoff(); + uint8_t get_backoff(); + + bool write_packet(uint8_t *ptr); + void parse_packet(uint8_t *ptr); + + +private: + mac_rar *rars; + uint32_t pdu_len; + uint32_t rem_len; + uint32_t rp, wp; + uint32_t nof_rars; + uint32_t max_rars; + +}; + +} +} + +#endif + diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/mux.h b/srsapps/ue/mac/include/srsapps/ue/mac/mux.h new file mode 100644 index 000000000..f976709aa --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/mux.h @@ -0,0 +1,71 @@ +#include + +#include "srsapps/common/log.h" +#include "srsapps/ue/mac/mac_io.h" +#include "srsapps/ue/mac/mac_params.h" +#include "srsapps/ue/mac/mac_pdu.h" + +#ifndef MUX_H +#define MUX_H + +/* Logical Channel Multiplexing and Prioritization + Msg3 Buffer */ + +namespace srslte { +namespace ue { + +class mux +{ +public: + mux(); + void reset(); + void init(log *log_h, mac_io *mac_io_h); + + uint8_t* pdu_pop(uint32_t tti_, uint32_t pdu_sz); + bool pdu_move_to_msg3(uint32_t tti, uint32_t pdu_sz); + void pdu_release(); + + uint8_t* msg3_pop(uint32_t tti_, uint32_t pdu_sz); + void msg3_flush(); + void msg3_release(); + bool msg3_isempty(); + + void append_crnti_ce_next_tx(uint16_t crnti); + + void set_priority(uint32_t lch_id, uint32_t priority, int PBR_x_tti, uint32_t BSD); + +private: + bool assemble_pdu(uint32_t pdu_sz); + bool allocate_sdu(uint32_t lcid, mac_pdu *pdu, uint32_t *sdu_sz); + bool allocate_sdu(uint32_t lcid, mac_pdu *pdu); + + int64_t Bj[mac_io::NOF_UL_LCH]; + int PBR[mac_io::NOF_UL_LCH]; // -1 sets to infinity + uint32_t BSD[mac_io::NOF_UL_LCH]; + uint32_t priority[mac_io::NOF_UL_LCH]; + uint32_t priority_sorted[mac_io::NOF_UL_LCH]; + uint32_t lchid_sorted[mac_io::NOF_UL_LCH]; + uint32_t nof_tx_pkts[mac_io::NOF_UL_LCH]; + + // Mutex for priority setting from outside MAC + pthread_mutex_t mutex; + + log *log_h; + mac_io *mac_io_h; + uint32_t tti; + uint16_t pending_crnti_ce; + + /* Msg3 Buffer */ + static const uint32_t MSG3_BUFF_SZ = 128; + qbuff msg3_buff; + + /* PDU Buffer */ + static const uint32_t PDU_BUFF_SZ = 16*1024; + qbuff pdu_buff; + mac_pdu pdu_msg; + +}; +} +} + +#endif + diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/proc.h b/srsapps/ue/mac/include/srsapps/ue/mac/proc.h new file mode 100644 index 000000000..60189d57b --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/proc.h @@ -0,0 +1,34 @@ + +#include + +#ifndef PROC_H +#define PROC_H + +/* Interface for a MAC procedure */ + +namespace srslte { +namespace ue { + +class proc +{ +public: + proc() { + running = false; + } + void run() { + running = true; + } + void stop() { + running = false; + } + bool is_running() { + return running; + } + virtual void step(uint32_t tti) = 0; +private: + bool running; +}; +} +} + +#endif \ No newline at end of file diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/proc_bsr.h b/srsapps/ue/mac/include/srsapps/ue/mac/proc_bsr.h new file mode 100644 index 000000000..bf96b7174 --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/proc_bsr.h @@ -0,0 +1,30 @@ + +#include + +#include "srsapps/ue/mac/proc.h" + +#ifndef PROCBSR_H +#define PROCBSR_H + +/* Buffer status report procedure */ + +namespace srslte { +namespace ue { + +class bsr_proc : public proc +{ +public: + void step(uint32_t tti) { + if (is_running()) { + fprintf(stderr, "BSR procedure not implemented\n"); + } + } + void reset() { + + } + +}; +} +} + +#endif \ No newline at end of file diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/proc_phr.h b/srsapps/ue/mac/include/srsapps/ue/mac/proc_phr.h new file mode 100644 index 000000000..e44fcf61c --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/proc_phr.h @@ -0,0 +1,29 @@ + +#include + +#include "srsapps/ue/mac/proc.h" + +#ifndef PROCPHR_H +#define PROCPHR_H + +/* Power headroom report procedure */ + +namespace srslte { +namespace ue { + +class phr_proc : public proc +{ +public: + void step(uint32_t tti) { + if (is_running()) { + fprintf(stderr, "PHR procedure not implemented\n"); + } + } + void reset() { + + } +}; +} +} + +#endif \ No newline at end of file diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/proc_ra.h b/srsapps/ue/mac/include/srsapps/ue/mac/proc_ra.h new file mode 100644 index 000000000..19c3c3025 --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/proc_ra.h @@ -0,0 +1,133 @@ + +#include + +#include "srsapps/ue/phy/phy.h" +#include "srsapps/common/log.h" +#include "srsapps/ue/mac/mac_params.h" +#include "srsapps/common/qbuff.h" +#include "srsapps/ue/mac/proc.h" +#include "srsapps/common/timers.h" +#include "srsapps/ue/mac/mux.h" +#include "srsapps/ue/mac/demux.h" +#include "srsapps/ue/mac/mac_pdu.h" + +#ifndef PROCRA_H +#define PROCRA_H + +/* Random access procedure as specified in Section 5.1 of 36.321 */ + +namespace srslte { +namespace ue { + +class ra_proc : public proc,timer_callback +{ + public: + ra_proc() : rar_pdu(20) {}; + bool init(mac_params *params_db, phy *phy_h, log *log_h, timers *timers_db, + mux *mux_unit, demux *demux_unit); + void reset(); + void start_pdcch_order(); + void start_rlc_order(); + void start_mac_order(); + void step(uint32_t tti); + bool is_successful(); + bool is_contention_resolution(); + bool is_error(); + bool in_progress(); + void pdcch_to_crnti(bool is_ul_grant); + void timer_expired(uint32_t timer_id); +private: + + void process_timeadv_cmd(uint32_t tti, uint32_t ta_cmd); + void step_initialization(); + void step_resource_selection(); + void step_preamble_transmission(); + void step_response_reception(); + void step_response_error(); + void step_backoff_wait(); + void step_contention_resolution(); + void step_completition(); + + // Buffer to receive RAR PDU + static const uint32_t MAX_RAR_PDU_LEN = 2048; + uint8_t rar_pdu_buffer[MAX_RAR_PDU_LEN]; + mac_rar_pdu rar_pdu; + + // Random Access parameters provided by higher layers defined in 5.1.1 + // They are read from params_db during initialization init() + uint32_t configIndex; + uint32_t nof_preambles; + uint32_t nof_groupA_preambles; + uint32_t nof_groupB_preambles; + uint32_t messagePowerOffsetGroupB; + uint32_t messageSizeGroupA; + uint32_t Pcmax; + uint32_t deltaPreambleMsg3; + uint32_t responseWindowSize; + uint32_t powerRampingStep; + uint32_t preambleTransMax; + uint32_t iniReceivedTargetPower; + int delta_preamble_db; + uint32_t maxharq_msg3tx; + uint32_t contentionResolutionTimer; + uint32_t maskIndex; + int preambleIndex; + + // Internal variables + uint32_t tti; + uint32_t preambleTransmissionCounter; + uint32_t backoff_param_ms; + uint32_t sel_maskIndex; + uint32_t sel_preamble; + uint32_t backoff_interval_start; + uint32_t backoff_inteval; + int received_target_power_dbm; + uint32_t ra_rnti; + uint8_t payload[256]; // 56 bits is often enough + + enum { + IDLE = 0, + INITIALIZATION, // Section 5.1.1 + RESOURCE_SELECTION, // Section 5.1.2 + PREAMBLE_TRANSMISSION, // Section 5.1.3 + RESPONSE_RECEPTION, // Section 5.1.4 + RESPONSE_ERROR, + BACKOFF_WAIT, + CONTENTION_RESOLUTION, // Section 5.1.5 + COMPLETION, // Section 5.1.6 + RA_PROBLEM // Section 5.1.5 last part + } state; + + typedef enum {RA_GROUP_A, RA_GROUP_B} ra_group_t; + + ra_group_t last_msg3_group; + bool msg3_transmitted; + bool first_rar_received; + void read_params(); + + phy *phy_h; + log *log_h; + mac_params *params_db; + timers *timers_db; + mux *mux_unit; + demux *demux_unit; + + uint64_t received_contention_id; + uint64_t transmitted_contention_id; + uint16_t transmitted_crnti; + enum { + PDCCH_CRNTI_NOT_RECEIVED = 0, + PDCCH_CRNTI_UL_GRANT, + PDCCH_CRNTI_DL_GRANT + } pdcch_to_crnti_received; + + enum { + PDCCH_ORDER = 0, + RLC_ORDER, + MAC_ORDER + } start_mode; +}; +} +} + +#endif \ No newline at end of file diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/proc_sr.h b/srsapps/ue/mac/include/srsapps/ue/mac/proc_sr.h new file mode 100644 index 000000000..bdc191786 --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/proc_sr.h @@ -0,0 +1,30 @@ + +#include + +#include "srsapps/ue/mac/proc.h" + +#ifndef PROCSR_H +#define PROCSR_H + +/* Scheduling Request procedure */ + +namespace srslte { +namespace ue { + +class sr_proc : public proc +{ +public: + void step(uint32_t tti) { + if (is_running()) { + fprintf(stderr, "SR procedure not implemented\n"); + } + } + void reset() { + + } + +}; +} +} + +#endif \ No newline at end of file diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/ul_harq.h b/srsapps/ue/mac/include/srsapps/ue/mac/ul_harq.h new file mode 100644 index 000000000..616d04fc6 --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/ul_harq.h @@ -0,0 +1,85 @@ + + +#include "srsapps/ue/phy/phy.h" +#include "srsapps/common/log.h" +#include "srsapps/ue/mac/mac_params.h" +#include "srsapps/ue/mac/mux.h" +#include "srsapps/common/timers.h" + +#ifndef ULHARQ_H +#define ULHARQ_H + +/* Uplink HARQ entity as defined in 5.4.2 of 36.321 */ + +namespace srslte { +namespace ue { + +typedef _Complex float cf_t; + +class ul_harq_entity +{ +public: + + const static uint32_t NOF_HARQ_PROC = 8; + static uint32_t pidof(uint32_t tti); + + ul_harq_entity(); + ~ul_harq_entity(); + + bool init(srslte_cell_t cell, uint32_t max_payload_len, log *log_h, timers* timers_, mux *mux_unit); + void set_maxHARQ_Tx(uint32_t maxHARQ_Tx, uint32_t maxHARQ_Msg3Tx); + + void reset(); + void reset_ndi(); + bool is_sps(uint32_t pid); + void run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_); + void run_tti(uint32_t tti, phy *phy_); + bool is_last_retx_msg3(); + +private: + + class ul_harq_process { + public: + ul_harq_process(); + bool init(srslte_cell_t cell, uint32_t max_payload_len, ul_harq_entity *parent); + void reset(); + void reset_ndi(); + void set_maxHARQ_Tx(uint32_t maxHARQ_Tx_, uint32_t maxHARQ_Msg3Tx_); + + void generate_retx(ul_buffer *ul); + void generate_retx(ul_sched_grant *ul_grant, ul_buffer *ul); + void generate_new_tx(uint8_t *payload, bool is_msg3, ul_sched_grant* grant, ul_buffer *ul); + + bool has_grant(); + ul_sched_grant *get_grant(); + void set_harq_feedback(bool ack); + bool get_ndi(); + + private: + uint32_t current_tx_nb; + uint32_t current_irv; + bool harq_feedback; + bool ndi; + srslte::log *log_h; + ul_harq_entity *harq_entity; + ul_sched_grant cur_grant; + uint8_t *payload; + uint32_t max_payload_len; + bool is_grant_configured; + srslte_softbuffer_tx_t softbuffer; + uint32_t maxHARQ_Tx, maxHARQ_Msg3Tx; + bool is_msg3; + + void generate_tx(ul_buffer* ul); + }; + + bool last_retx_is_msg3; + timers *timers_db; + mux *mux_unit; + ul_harq_process *proc; + srslte::log *log_h; +}; + +} +} +#endif \ No newline at end of file diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/ul_sps.h b/srsapps/ue/mac/include/srsapps/ue/mac/ul_sps.h new file mode 100644 index 000000000..944847a53 --- /dev/null +++ b/srsapps/ue/mac/include/srsapps/ue/mac/ul_sps.h @@ -0,0 +1,31 @@ + + +#include "srsapps/common/log.h" +#include "srsapps/ue/phy/phy.h" +#include "srsapps/ue/mac/mac_params.h" +#include "srsapps/common/timers.h" + +#ifndef ULSPS_H +#define ULSPS_H + +/* Uplink Semi-Persistent schedulign (Section 5.10.2) */ + +namespace srslte { +namespace ue { + +typedef _Complex float cf_t; + +class ul_sps +{ +public: + + void clear() {} + void reset(uint32_t tti, sched_grant *grant) {} + ul_sched_grant *get_pending_grant(uint32_t tti) { return NULL; } +private: + +}; + +} +} +#endif \ No newline at end of file diff --git a/srsapps/ue/mac/src/demux.cc b/srsapps/ue/mac/src/demux.cc new file mode 100644 index 000000000..dcacd440a --- /dev/null +++ b/srsapps/ue/mac/src/demux.cc @@ -0,0 +1,150 @@ + +#include "srsapps/ue/mac/mac.h" +#include "srsapps/ue/mac/demux.h" + +namespace srslte { + namespace ue { + +demux::demux() : mac_msg(20),pending_mac_msg(20) +{ + contention_resolution_id = 0; + pending_temp_rnti = false; +} + +void demux::init(phy* phy_h_, log* log_h_, mac_io* mac_io_h_, timers* timers_db_) +{ + phy_h = phy_h_; + log_h = log_h_; + mac_io_h = mac_io_h_; + timers_db = timers_db_; +} + + +bool demux::is_temp_crnti_pending() +{ + return pending_temp_rnti; +} + +uint64_t demux::get_contention_resolution_id() +{ + uint64_t x = contention_resolution_id; + contention_resolution_id = 0; + return x; +} + + +/* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through + * the MAC in transparent mode + */ +void demux::push_pdu_bcch(uint32_t tti_, uint8_t *mac_pdu, uint32_t nof_bits) +{ + tti = tti_; + mac_io_h->get(mac_io::MAC_LCH_BCCH_DL)->send(mac_pdu, nof_bits); + Debug("Pushed BCCH MAC PDU in transparent mode\n"); +} + +/* Demultiplexing of MAC PDU associated with a Temporal C-RNTI. The PDU will + * remain in buffer until demultiplex_pending_pdu() is called. + * This features is provided to enable the Random Access Procedure to decide + * wether the PDU shall pass to upper layers or not, which depends on the + * Contention Resolution result + */ +void demux::push_pdu_temp_crnti(uint32_t tti_, uint8_t *mac_pdu, uint32_t nof_bits) +{ + tti = tti_; + if (!pending_temp_rnti) { + // Unpack DLSCH MAC PDU + pending_mac_msg.init(nof_bits); + pending_mac_msg.parse_packet(mac_pdu); + + // Look for Contention Resolution UE ID + contention_resolution_id = 0; + while(pending_mac_msg.read_next()) { + if (pending_mac_msg.get()->ce_type() == mac_pdu::mac_subh::CON_RES_ID) { + contention_resolution_id = pending_mac_msg.get()->get_con_res_id(); + } + } + pending_temp_rnti = true; + Debug("Saved MAC PDU with Temporal C-RNTI in buffer\n"); + } else { + Warning("Error pushing PDU with Temporal C-RNTI: Another PDU is still in pending\n"); + } +} + +/* Demultiplexing of logical channels and dissassemble of MAC CE */ +void demux::push_pdu(uint32_t tti_, uint8_t *mac_pdu, uint32_t nof_bits) +{ + tti = tti_; + // Unpack DLSCH MAC PDU + mac_msg.init(nof_bits); + mac_msg.parse_packet(mac_pdu); + process_pdu(&mac_msg); + Debug("Normal MAC PDU processed\n"); +} + +void demux::demultiplex_pending_pdu(uint32_t tti_) +{ + tti = tti_; + if (pending_temp_rnti) { + process_pdu(&pending_mac_msg); + Debug("Temporal C-RNTI MAC PDU processed\n"); + pending_temp_rnti = false; + pending_mac_msg.reset(); + } else { + Error("Error demultiplex pending PDU: No pending PDU\n"); + } +} + + + +void demux::process_pdu(mac_pdu *pdu) +{ + while(pdu->read_next()) { + if (pdu->get()->is_sdu()) { + // Route logical channel + if (pdu->get()->get_sdu_lcid() <= mac_io::MAC_LCH_DTCH2_DL) { + qbuff *dest_lch = mac_io_h->get(pdu->get()->get_sdu_lcid()); + if (dest_lch) { + dest_lch->send(pdu->get()->get_sdu_ptr(), pdu->get()->get_sdu_nbytes()*8); + Debug("Sent MAC SDU len=%d bytes to lchid=%d\n", + pdu->get()->get_sdu_nbytes(), pdu->get()->get_sdu_lcid()); + } else { + Error("Getting destination channel LCID=%d\n", pdu->get()->get_sdu_lcid()); + } + } else { + Warning("Received SDU for unsupported LCID=%d\n", pdu->get()->get_sdu_lcid()); + } + // Process MAC Control Element + } else { + if (!process_ce(pdu->get())) { + Warning("Received Subheader with invalid or unkonwn LCID\n"); + } + } + } +} + + +bool demux::process_ce(mac_pdu::mac_subh *subh) { + switch(subh->ce_type()) { + case mac_pdu::mac_subh::CON_RES_ID: + contention_resolution_id = subh->get_c_rnti(); + Debug("Saved Contention Resolution ID=%d\n", contention_resolution_id); + break; + case mac_pdu::mac_subh::TA_CMD: + phy_h->set_timeadv(subh->get_ta_cmd()); + + // Start or restart timeAlignmentTimer + timers_db->get(mac::TIME_ALIGNMENT)->reset(); + timers_db->get(mac::TIME_ALIGNMENT)->run(); + Debug("Set TimeAdvance Command %d\n", subh->get_ta_cmd()); + break; + default: + Error("MAC CE not supported\n"); + break; + } + return true; +} + + +} +} diff --git a/srsapps/ue/mac/src/dl_harq.cc b/srsapps/ue/mac/src/dl_harq.cc new file mode 100644 index 000000000..819e0d35e --- /dev/null +++ b/srsapps/ue/mac/src/dl_harq.cc @@ -0,0 +1,194 @@ +#include "srsapps/ue/phy/phy.h" +#include "srsapps/ue/phy/dl_sched_grant.h" + +#include "srsapps/ue/mac/mac.h" +#include "srsapps/ue/mac/dl_harq.h" + +namespace srslte { + namespace ue { + + + /*********************************************************** + * + * HARQ ENTITY + * + *********************************************************/ + +dl_harq_entity::dl_harq_entity() +{ + proc = new dl_harq_process[NOF_HARQ_PROC+1]; // BCCH process is separate + for (uint32_t i=0;i= 0; +} + +void dl_harq_entity::send_pending_ack_contention_resolution() +{ + if (is_ack_pending_resolution()) { + proc[pending_ack_pid].send_pending_ack_contention_resolution(); + pending_ack_pid = -1; + } +} + + /*********************************************************** + * + * HARQ PROCESS + * + *********************************************************/ + +dl_harq_entity::dl_harq_process::dl_harq_process() : cur_grant(0),pending_ack_grant(0) { + is_first_tx = true; + is_first_decoded = true; + bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant)); + payload = NULL; + max_payload_len = 0; +} + +void dl_harq_entity::dl_harq_process::reset() { + is_first_tx = true; + is_first_decoded = true; + bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant)); + srslte_softbuffer_rx_reset(&softbuffer); +} + +void dl_harq_entity::dl_harq_process::send_pending_ack_contention_resolution() +{ + if (pending_ul_buffer) { + pending_ul_buffer->generate_ack(pending_ack, &pending_ack_grant); + } +} + +void dl_harq_entity::dl_harq_process::receive_data(uint32_t tti, srslte::ue::dl_buffer *dl_buffer, phy *phy_h) +{ + bool ack = false; + pending_ul_buffer = NULL; + + if (payload) { + if (cur_grant.get_tbs() <= max_payload_len) { + Info("Decoding PDSCH data TBS=%d, RV=%d\n", cur_grant.get_tbs(), cur_grant.get_rv()); + if (dl_buffer->decode_data(&cur_grant, &softbuffer, payload)) { + Info("Decoded OK\n"); + // RX OK + Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.get_tbs()/8); + if (pid == HARQ_BCCH_PID) { + harq_entity->demux_unit->push_pdu_bcch(tti, payload, cur_grant.get_tbs()); + is_first_tx = true; + } else { + if (is_first_decoded) { + if (cur_grant.is_temp_rnti()) { + harq_entity->demux_unit->push_pdu_temp_crnti(tti, payload, cur_grant.get_tbs()); + } else { + harq_entity->demux_unit->push_pdu(tti, payload, cur_grant.get_tbs()); + } + is_first_decoded = false; + } + ack = true; + } + } else { + Warning("Decoded Error\n"); + // RX NOK + ack = false; + } + if (pid == HARQ_BCCH_PID || harq_entity->timers_db->get(mac::TIME_ALIGNMENT)->is_expired()) { + // Do not generate ACK + Debug("Not generating ACK\n"); + } else { + if (cur_grant.is_temp_rnti()) { + // Postpone ACK after contention resolution is resolved + pending_ack = ack; + pending_ul_buffer = phy_h->get_ul_buffer(tti+4); + harq_entity->pending_ack_pid = pid; + memcpy(&pending_ack_grant, &cur_grant, sizeof(dl_sched_grant)); + } else { + Debug("Generating ACK\n"); + // Generate ACK + srslte::ue::ul_buffer *ul_buffer = phy_h->get_ul_buffer(tti+4); + ul_buffer->generate_ack(ack, &cur_grant); + } + } + } else { + fprintf(stderr, "Error with DL grant. TBS (%d) exceeds payload buffer length (%d)\n", cur_grant.get_tbs(), max_payload_len); + } + } +} +// Implement 5.3.2.2 +void dl_harq_entity::dl_harq_process::set_harq_info(uint32_t tti, srslte::ue::dl_sched_grant* new_grant) { + bool is_new_transmission = false; + if (new_grant->get_ndi() && !cur_grant.get_ndi() || is_first_tx) { + is_new_transmission = true; + is_first_decoded = true; + is_first_tx = false; + Debug("Set HARQ Info for new transmission\n"); + } else { + is_new_transmission = false; + Debug("Set HARQ Info for retransmission\n"); + } + if (is_new_transmission || cur_grant.get_tbs() != new_grant->get_tbs()) { + Debug("Reset softbuffer RX\n"); + srslte_softbuffer_rx_reset(&softbuffer); + } + if (new_grant->get_tbs() <= max_payload_len) { + memcpy(&cur_grant, new_grant, sizeof(srslte::ue::dl_sched_grant)); + } else { + fprintf(stderr, "Error with DL grant. TBS (%d) exceeds payload buffer length (%d)\n", new_grant->get_tbs(), max_payload_len); + } +} +bool dl_harq_entity::dl_harq_process::init(srslte_cell_t cell, uint32_t max_payload_len_, dl_harq_entity *parent) { + max_payload_len = max_payload_len_; + if (srslte_softbuffer_rx_init(&softbuffer, cell)) { + fprintf(stderr, "Error initiating soft buffer\n"); + return false; + } else { + harq_entity = parent; + log_h = harq_entity->log_h; + payload = (uint8_t*) srslte_vec_malloc(sizeof(uint8_t) * max_payload_len); + return payload?true:false; + } +} + + +} +} \ No newline at end of file diff --git a/srsapps/ue/mac/src/dl_sps.cc b/srsapps/ue/mac/src/dl_sps.cc new file mode 100644 index 000000000..9073c37aa --- /dev/null +++ b/srsapps/ue/mac/src/dl_sps.cc @@ -0,0 +1,21 @@ +#include "srsapps/ue/mac/dl_sps.h" + +namespace srslte { + namespace ue { + + dl_sched_grant* dl_sps::get_pending_grant(uint32_t tti) + { + return NULL; + } + void dl_sps::reset(uint32_t tti, dl_sched_grant* grant) + { + + } + void dl_sps::clear() + { + + } + + + } +} \ No newline at end of file diff --git a/srsapps/ue/mac/src/mac.cc b/srsapps/ue/mac/src/mac.cc new file mode 100644 index 000000000..2f9d0fb6f --- /dev/null +++ b/srsapps/ue/mac/src/mac.cc @@ -0,0 +1,460 @@ +/** + * + * \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 +#include +#include + +#include "srsapps/ue/phy/phy.h" +#include "srsapps/common/log.h" +#include "srsapps/ue/mac/mac.h" +#include "srsapps/ue/mac/mac_params.h" + +namespace srslte { +namespace ue { + +bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_) +{ + started = false; + ttisync = ttisync_; + phy_h = phy_h_; + log_h = log_h_; + tti = 0; + is_synchronized = false; + + mux_unit.init(log_h, &mac_io_lch); + demux_unit.init(phy_h, log_h, &mac_io_lch, &timers_db); + ra_procedure.init(¶ms_db, phy_h, log_h, &timers_db, &mux_unit, &demux_unit); + + reset(); + + if (!pthread_create(&mac_thread, NULL, mac_thread_fnc, this)) { + started = true; + } else { + perror("pthread_create"); + } + return started; +} + +void mac::stop() +{ + started = false; + + pthread_join(mac_thread, NULL); +} + +int mac::get_tti() +{ + if (is_synchronized) { + return (int) tti; + } else { + return -1; + } +} + +// Implement Section 5.8 +void mac::reconfiguration() +{ + +} + +// Implement Section 5.9 +void mac::reset() +{ + timers_db.stop_all(); + timeAlignmentTimerExpire(); + ul_harq.reset_ndi(); + + mux_unit.msg3_flush(); + mux_unit.reset(); + + ra_procedure.stop(); + ra_procedure.reset(); + sr_procedure.stop(); + sr_procedure.reset(); + bsr_procedure.stop(); + bsr_procedure.reset(); + phr_procedure.stop(); + phr_procedure.reset(); + + dl_harq.reset(); + params_db.set_param(mac_params::RNTI_TEMP, 0); +} + +void* mac::mac_thread_fnc(void *arg) { + srslte::ue::mac* mac = static_cast(arg); + mac->main_radio_loop(); + return NULL; +} + +void mac::main_radio_loop() { + setup_timers(); + while(1) { + if (!is_synchronized) { + srslte_cell_t cell; + uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; + + if (phy_h->decode_mib_best(&cell, bch_payload)) { + + // Print MIB + srslte_cell_fprint(stdout, &cell, phy_h->get_current_tti()/10); + + // Init HARQ for this cell + Info("Init UL/DL HARQ\n"); + ul_harq.init(cell, 8*1024, log_h, &timers_db, &mux_unit); + dl_harq.init(cell, 8*1024, log_h, &timers_db, &demux_unit); + + // Set the current PHY cell to the detected cell + Info("Setting up PHY for cell_id=%d\n", cell.id); + if (phy_h->set_cell(cell)) { + Info("Starting RX streaming\n"); + if (phy_h->start_rxtx()) { + tti = ttisync->wait(); + Info("Receiver synchronized\n"); + + // Send MIB to RRC + mac_io_lch.get(mac_io::MAC_LCH_BCCH_DL)->send(bch_payload, SRSLTE_BCH_PAYLOAD_LEN); + + is_synchronized = true; + } else { + Error("Starting PHY receiver\n"); + exit(-1); + } + } else { + Error("Setting PHY cell\n"); + exit(-1); + } + } else { + Warning("Cell not found\n"); + } + sleep(1); + } + if (is_synchronized) { + /* Warning: Here order of invocation of procedures is important!! */ + + tti = ttisync->wait(); + + // Step all procedures + ra_procedure.step(tti); + sr_procedure.step(tti); + bsr_procedure.step(tti); + phr_procedure.step(tti); + + // Receive PCH, if requested + receive_pch(tti); + + // Process DL grants always + process_dl_grants(tti); + + // Send pending HARQ ACK, if any, and contention resolution is resolved + if (dl_harq.is_ack_pending_resolution()) { + if (ra_procedure.is_successful()) { + Info("Sending pending ACK for contention resolution\n"); + dl_harq.send_pending_ack_contention_resolution(); + } + } + + // Process UL grants if RA procedure is done or in contention resolution + if (ra_procedure.is_successful() || ra_procedure.is_contention_resolution()) { + Info("Processing UL grants\n"); + process_ul_grants(tti); + } + timers_db.step_all(); + } + } +} + +void mac::setup_timers() +{ + if (params_db.get_param(mac_params::TIMER_TIMEALIGN) > 0) { + timers_db.get(TIME_ALIGNMENT)->set(this, params_db.get_param(mac_params::TIMER_TIMEALIGN)); + } +} +static sched_grant::rnti_type_t rnti_type(int rnti_param_id) { + switch(rnti_param_id) { + case mac_params::RNTI_C: + return sched_grant::RNTI_TYPE_CRNTI; + case mac_params::RNTI_TEMP: + return sched_grant::RNTI_TYPE_TEMP; + case mac_params::RNTI_SPS: + return sched_grant::RNTI_TYPE_SPS; + case mac_params::RNTI_RA: + return sched_grant::RNTI_TYPE_RA; + } +} + +uint32_t mac::get_harq_sps_pid(uint32_t tti) { + uint32_t nof_proc = ((uint32_t) params_db.get_param(mac_params::SPS_DL_NOF_PROC)); + return tti/params_db.get_param(mac_params::SPS_DL_SCHED_INTERVAL)%nof_proc; + +} + +void mac::timer_expired(uint32_t timer_id) +{ + switch(timer_id) { + case TIME_ALIGNMENT: + timeAlignmentTimerExpire(); + break; + default: + break; + } +} + +/* Function called on expiry of TimeAlignmentTimer */ +void mac::timeAlignmentTimerExpire() { + dl_harq.reset(); + ul_harq.reset(); + dl_sps_assig.clear(); + ul_sps_assig.clear(); +} + +// Receive PCH when requested as defined in Section 5.5 +void mac::receive_pch(uint32_t tti) { + if (params_db.get_param(mac_params::PCCH_RECEIVE)) { + dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti); + dl_sched_grant pch_grant(sched_grant::RNTI_TYPE_PRNTI, SRSLTE_PRNTI); + if (dl_buffer->get_dl_grant(&pch_grant)) { + qbuff *pcch_buff = mac_io_lch.get(mac_io::MAC_LCH_PCCH_DL); + uint8_t *ptr = (uint8_t*) pcch_buff->request(); + if (ptr && pch_grant.get_tbs() <= mac_io_lch.DEFAULT_MSG_SZ) { + if (dl_buffer->decode_data(&pch_grant, ptr)) { + pcch_buff->release(); + } else { + Warning("Error decoding PCH\n"); + } + } else { + Error("Error getting pointer from PCCH buffer\n"); + } + } else { + Debug("No P-RNTI grant found while looking for PCH messages\n"); + } + } +} + +/* This function controls DL Grant Assignment as specified in Section 5.3.1 in 36.321 + * and issues commands to DL harq operation + */ +void mac::process_dl_grants(uint32_t tti) { + // Get DL buffer for this TTI + dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti); + + // 5.3.1 DL Assignment reception + for (int i = mac_params::RNTI_C;i<=mac_params::RNTI_RA;i++) { + // Check C-RNTI, SPS-RNTI and Temporal RNTI + if (params_db.get_param(i) != 0) { + Info("Searching DL grants for RNTI: %d\n", params_db.get_param(i)); + dl_sched_grant ue_grant(rnti_type(i), params_db.get_param(i)); + if (dl_buffer->get_dl_grant(&ue_grant)) { + // If PDCCH for C-RNTI and RA procedure in Contention Resolution, notify it + if (ra_procedure.is_contention_resolution() && i == mac_params::RNTI_C) { + ra_procedure.pdcch_to_crnti(false); + } + if (i != mac_params::RNTI_SPS) { + uint32_t harq_pid = ue_grant.get_harq_process(); + if (i == mac_params::RNTI_TEMP) { + ue_grant.set_ndi(is_first_temporal); + is_first_temporal = false; + } + if (i == mac_params::RNTI_C && dl_harq.is_sps(harq_pid)) { + ue_grant.set_ndi(true); + } + dl_harq.set_harq_info(tti, harq_pid, &ue_grant); + dl_harq.receive_data(tti, harq_pid, dl_buffer, phy_h); + } else { + uint32_t harq_pid = get_harq_sps_pid(tti); + if (ue_grant.get_ndi()) { + ue_grant.set_ndi(false); + dl_harq.set_harq_info(tti, harq_pid, &ue_grant); + dl_harq.receive_data(tti, harq_pid, dl_buffer, phy_h); + } else { + if (ue_grant.is_sps_release()) { + dl_sps_assig.clear(); + if (timers_db.get(TIME_ALIGNMENT)->is_running()) { + //phy_h->send_sps_ack(); + Warning("PHY Send SPS ACK not implemented\n"); + } + } else { + dl_sps_assig.reset(tti, &ue_grant); + ue_grant.set_ndi(true); + dl_harq.set_harq_info(tti, harq_pid, &ue_grant); + } + } + } + } + } + } + /* Process configured DL assingments (SPS) */ + dl_sched_grant *sps_grant = dl_sps_assig.get_pending_grant(tti); + if (sps_grant != NULL) { + Info("Processing SPS grant\n"); + uint32_t harq_pid = get_harq_sps_pid(tti); + sps_grant->set_ndi(true); + dl_harq.set_harq_info(tti, harq_pid, sps_grant); + dl_harq.receive_data(tti, harq_pid, dl_buffer, phy_h); + } + + /* Process SI-RNTI */ + uint32_t si_window_start = params_db.get_param(mac_params::BCCH_SI_WINDOW_ST); + uint32_t si_window_length = params_db.get_param(mac_params::BCCH_SI_WINDOW_LEN); + + if (tti >= si_window_start && tti < (si_window_start + si_window_length)) { + // Exclude subf 5 and sfn%2==0 unless it's a SIB1 message (window_length=1) (This is defined in 36.331 Sec 5.2.3) + if (!(phy_h->tti_to_subf(si_window_length) != 1 && + phy_h->tti_to_subf(si_window_start) == 5 && (phy_h->tti_to_SFN(tti)%2) == 0)) + { + Info("Searching for DL grant for SI-RNTI window_st=%d, window_len=%d\n", si_window_start, si_window_length); + dl_sched_grant si_grant(sched_grant::RNTI_TYPE_SIRNTI, SRSLTE_SIRNTI); + if (dl_buffer->get_dl_grant(&si_grant)) { + uint32_t k; + if (phy_h->tti_to_subf(si_window_start) == 5) { // This is SIB1, k is different + k = (phy_h->tti_to_SFN(tti)/2)%4; + } else { + k = phy_h->tti_to_subf(tti)%4; + } + si_grant.set_rv(((uint32_t) ceilf((float)1.5*k))%4); + Info("DL grant found, sending to HARQ with RV: %d\n", si_grant.get_rv()); + dl_harq.set_harq_info(tti, dl_harq_entity::HARQ_BCCH_PID, &si_grant); + dl_harq.receive_data(tti, dl_harq_entity::HARQ_BCCH_PID, dl_buffer, phy_h); + params_db.set_param(mac_params::BCCH_SI_WINDOW_ST, 0); + params_db.set_param(mac_params::BCCH_SI_WINDOW_LEN, 0); + } else { + Warning("DL grant not found\n"); + } + } + + } +} + +/* UL Grant reception and processin as defined in Section 5.4.1 in 36.321 */ +void mac::process_ul_grants(uint32_t tti) { + // Get DL buffer for this TTI to look for DCI grants + dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti); + + //if (timers_db.get(TIME_ALIGNMENT)->is_running()) { + if (1) { + for (int i = mac_params::RNTI_C;i<=mac_params::RNTI_TEMP;i++) { + // Check C-RNTI, SPS-RNTI and Temporal C-RNTI + if (params_db.get_param(i) != 0) { + ul_sched_grant ul_grant(rnti_type(i), params_db.get_param(i)); + if (dl_buffer->get_ul_grant(&ul_grant)) { + if (ra_procedure.is_contention_resolution() && i == mac_params::RNTI_C) { + ra_procedure.pdcch_to_crnti(true); + } + if (i == mac_params::RNTI_C || i == mac_params::RNTI_TEMP || ra_procedure.is_running()) { + if (i == mac_params::RNTI_C && ul_harq.is_sps(tti)) + ul_grant.set_ndi(true); + ul_harq.run_tti(tti, &ul_grant, phy_h); + if (i == mac_params::RNTI_TEMP) { + // Discard already processed RAR grant + dl_buffer->discard_pending_rar_grant(); + } + return; + } + else if (i == mac_params::RNTI_SPS) { + if (ul_grant.get_ndi()) { + ul_grant.set_ndi(false); + ul_harq.run_tti(tti, &ul_grant, phy_h); + } else { + if (ul_grant.is_sps_release()) { + ul_sps_assig.clear(); + } else { + ul_sps_assig.reset(tti, &ul_grant); + ul_grant.set_ndi(true); + ul_harq.run_tti(tti, &ul_grant, phy_h); + return; + } + } + } + } + } + } + /* Process configured UL assingments (SPS) */ + ul_sched_grant *sps_grant = ul_sps_assig.get_pending_grant(tti); + if (sps_grant != NULL) { + sps_grant->set_ndi(true); + ul_harq.run_tti(tti, sps_grant, phy_h); + return; + } + } + ul_harq.run_tti(tti, phy_h); +} + + +int mac::recv_bcch_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes) +{ + return mac_io_lch.get(mac_io::MAC_LCH_BCCH_DL)->recv(sdu_payload, buffer_len_nbytes); +} + +int mac::recv_ccch_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes) +{ + return mac_io_lch.get(mac_io::MAC_LCH_CCCH_DL)->recv(sdu_payload, buffer_len_nbytes); +} + +int mac::recv_dtch0_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes) +{ + return mac_io_lch.get(mac_io::MAC_LCH_DTCH0_DL)->recv(sdu_payload, buffer_len_nbytes); +} + +int mac::recv_dcch0_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes) +{ + return mac_io_lch.get(mac_io::MAC_LCH_DTCH0_DL)->recv(sdu_payload, buffer_len_nbytes); +} + + +bool mac::send_ccch_sdu(uint8_t* sdu_payload, uint32_t nbytes) +{ + return mac_io_lch.get(mac_io::MAC_LCH_CCCH_UL)->send(sdu_payload, nbytes); +} + +bool mac::send_dtch0_sdu(uint8_t* sdu_payload, uint32_t nbytes) +{ + return mac_io_lch.get(mac_io::MAC_LCH_DTCH0_UL)->send(sdu_payload, nbytes); +} + +bool mac::send_dcch0_sdu(uint8_t* sdu_payload, uint32_t nbytes) +{ + return mac_io_lch.get(mac_io::MAC_LCH_DCCH0_UL)->send(sdu_payload, nbytes); +} + +void mac::set_param(mac_params::mac_param_t param, int64_t value) +{ + params_db.set_param((uint32_t) param, value); +} + +void mac::set_dcch0_priority(uint32_t priority, int PBR_x_tti, uint32_t BSD) +{ + mux_unit.set_priority(mac_io::MAC_LCH_DCCH0_UL - mac_io::MAC_LCH_CCCH_UL, priority, PBR_x_tti, BSD); +} +void mac::set_dtch0_priority(uint32_t priority, int PBR_x_tti, uint32_t BSD) +{ + mux_unit.set_priority(mac_io::MAC_LCH_DTCH0_UL - mac_io::MAC_LCH_CCCH_UL, priority, PBR_x_tti, BSD); +} + + +} +} diff --git a/srsapps/ue/mac/src/mac_pdu.cc b/srsapps/ue/mac/src/mac_pdu.cc new file mode 100644 index 000000000..3cfe629da --- /dev/null +++ b/srsapps/ue/mac/src/mac_pdu.cc @@ -0,0 +1,187 @@ +#include "srsapps/ue/mac/mac_pdu.h" + +namespace srslte { + namespace ue { +mac_pdu::mac_subh* mac_pdu::get() +{ + +} +void mac_pdu::init(uint32_t pdu_len) +{ + +} +mac_pdu::mac_pdu(uint32_t max_subheaders) +{ + +} +mac_pdu::mac_subh::cetype mac_pdu::mac_subh::ce_type() +{ + +} +uint16_t mac_pdu::mac_subh::get_c_rnti() +{ + +} +uint64_t mac_pdu::mac_subh::get_con_res_id() +{ + +} +uint8_t mac_pdu::mac_subh::get_phd() +{ + +} +uint32_t mac_pdu::mac_subh::get_sdu_lcid() +{ + +} +uint32_t mac_pdu::mac_subh::get_sdu_nbytes() +{ + +} +uint8_t* mac_pdu::mac_subh::get_sdu_ptr() +{ + +} +uint8_t mac_pdu::mac_subh::get_ta_cmd() +{ + +} +bool mac_pdu::mac_subh::is_sdu() +{ + +} +bool mac_pdu::mac_subh::set_c_rnti(uint16_t crnti) +{ + +} +bool mac_pdu::mac_subh::set_con_res_id(uint64_t con_res_id) +{ + +} +bool mac_pdu::mac_subh::set_phd(uint8_t phd) +{ + +} +bool mac_pdu::mac_subh::set_sdu(uint8_t* ptr, uint32_t nof_bytes) +{ + +} +bool mac_pdu::mac_subh::set_ta_cmd(uint8_t ta_cmd) +{ + +} +void mac_pdu::parse_packet(uint8_t* ptr) +{ + +} +bool mac_pdu::read_next() +{ + +} +void mac_pdu::reset() +{ + +} +bool mac_pdu::write_next() +{ + +} +bool mac_pdu::write_packet(uint8_t* ptr) +{ + +} + + + +mac_rar_pdu::mac_rar* mac_rar_pdu::get() +{ + +} +uint8_t mac_rar_pdu::get_backoff() +{ + +} +void mac_rar_pdu::init(uint32_t pdu_len) +{ + +} +bool mac_rar_pdu::is_backoff() +{ + +} +uint32_t mac_rar_pdu::mac_rar::get_rapid() +{ + +} +void mac_rar_pdu::mac_rar::get_sched_grant(uint8_t grant[]) +{ + +} +uint32_t mac_rar_pdu::mac_rar::get_ta_cmd() +{ + +} +uint16_t mac_rar_pdu::mac_rar::get_temp_crnti() +{ + +} +void mac_rar_pdu::mac_rar::set_rapid(uint32_t rapid) +{ + +} +void mac_rar_pdu::mac_rar::set_sched_grant(uint8_t grant[]) +{ + +} +void mac_rar_pdu::mac_rar::set_ta_cmd(uint32_t ta) +{ + +} +void mac_rar_pdu::mac_rar::set_temp_crnti(uint16_t temp_rnti) +{ + +} +mac_rar_pdu::mac_rar_pdu(uint32_t max_rars) +{ + +} +void mac_rar_pdu::parse_packet(uint8_t* ptr) +{ + +} +bool mac_rar_pdu::read_next() +{ + +} +void mac_rar_pdu::reset() +{ + +} +void mac_rar_pdu::set_backoff(uint8_t bi) +{ + +} +bool mac_rar_pdu::write_next() +{ + +} +bool mac_rar_pdu::write_packet(uint8_t* ptr) +{ + +} + + + + + } +} + +#ifdef kk +bool demux::lcid_is_lch(uint32_t lcid) { + if (lcid <= LIBLTE_MAC_DLSCH_DCCH_LCID_END) { + return true; + } else { + return false; + } +} +#endif diff --git a/srsapps/ue/mac/src/mux.cc b/srsapps/ue/mac/src/mux.cc new file mode 100644 index 000000000..1fb98c3af --- /dev/null +++ b/srsapps/ue/mac/src/mux.cc @@ -0,0 +1,271 @@ + +#include "srsapps/ue/mac/mux.h" +#include "srsapps/ue/mac/mac.h" + +namespace srslte { +namespace ue { + +#define IO_IDX(lch) (lch + mac_io::MAC_LCH_CCCH_UL) +#define UL_IDX(lch) (lch - mac_io::MAC_LCH_CCCH_UL) + +mux::mux() : pdu_msg(20) +{ + msg3_buff.init(1, MSG3_BUFF_SZ); + pdu_buff.init(1, PDU_BUFF_SZ); + bzero(nof_tx_pkts, sizeof(uint32_t) * mac_io::NOF_UL_LCH); + pthread_mutex_init(&mutex, NULL); + + for (int i=0;i priority_sorted[new_index] && new_index < mac_io::NOF_UL_LCH) { + new_index++; + } + int old_index = 0; + while(lch_id != lchid_sorted[old_index] && new_index < mac_io::NOF_UL_LCH) { + old_index++; + } + if (new_index == mac_io::NOF_UL_LCH) { + Error("Can't find LchID=%d in sorted list\n", lch_id); + return; + } + // Replace goes in one direction or the other + int add=new_index>old_index?1:-1; + for (int i=old_index;i!=new_index;i+=add) { + priority_sorted[i] = priority_sorted[i+add]; + lchid_sorted[i] = lchid_sorted[i+add]; + } + priority_sorted[new_index] = set_priority; + lchid_sorted[new_index] = lch_id; + } + pthread_mutex_unlock(&mutex); +} + +void mux::pdu_release() +{ + pdu_buff.release(); +} + +bool mux::pdu_move_to_msg3(uint32_t tti_, uint32_t pdu_sz) +{ + tti = tti_; + if (pdu_buff.isempty()) { + if (assemble_pdu(pdu_sz)) { + if (pdu_buff.pending_data() < MSG3_BUFF_SZ) { + pdu_buff.move_to(&msg3_buff); + return true; + } else { + pdu_buff.release(); + Error("Assembled PDU size exceeds Msg3 buffer size\n"); + return false; + } + } else { + Error("Assembling PDU\n"); + return false; + } + } else { + Error("Generating PDU: PDU pending in buffer for transmission\n"); + return false; + } +} + +// Multiplexing and logical channel priorization as defined in Section 5.4.3 +uint8_t* mux::pdu_pop(uint32_t tti_, uint32_t pdu_sz) +{ + tti = tti_; + if (pdu_buff.isempty()) { + if (assemble_pdu(pdu_sz)) { + return (uint8_t*) pdu_buff.pop(); + } else { + return NULL; + } + } else { + Error("Generating PDU: PDU pending in buffer for transmission\n"); + return NULL; + } +} + +void mux::append_crnti_ce_next_tx(uint16_t crnti) { + pending_crnti_ce = crnti; +} + +bool mux::assemble_pdu(uint32_t pdu_sz) { + + uint8_t *buff = (uint8_t*) pdu_buff.request(); + if (!buff) { + Error("Assembling PDU: Buffer is not available\n"); + return false; + } + + // Make sure pdu_sz is byte-aligned + pdu_sz = 8*(pdu_sz/8); + + // Acquire mutex. Cannot change priorities, PBR or BSD after assemble finishes + pthread_mutex_lock(&mutex); + + // Update Bj + for (int i=0;i=mac_io::NOF_UL_LCH;i++) { + // Add PRB unless it's infinity + if (PBR[i] >= 0) { + Bj[i] += PBR[i]; + } + if (Bj[i] >= BSD[i]) { + Bj[i] = BSD[i]; + } + } + +// Logical Channel Procedure + + uint32_t sdu_sz = 0; + + pdu_msg.init(pdu_sz); + + // MAC control element for C-RNTI or data from UL-CCCH + if (!allocate_sdu(UL_IDX(mac_io::MAC_LCH_CCCH_UL), &pdu_msg)) { + if (pending_crnti_ce) { + if (pdu_msg.write_next()) { + if (!pdu_msg.get()->set_c_rnti(pending_crnti_ce)) { + Warning("Pending C-RNTI CE could not be inserted in MAC PDU\n"); + } + } + } + } + pending_crnti_ce = 0; + + // MAC control element for BSR, with exception of BSR included for padding; + // TODO + // MAC control element for PHR + // TODO + + // data from any Logical Channel, except data from UL-CCCH; + // first only those with positive Bj + for (int i=0;i 0 || PBR[i] < 0) && res) { + res = allocate_sdu(lchid_sorted[i], &pdu_msg, &sdu_sz); + if (res && PBR[i] >= 0) { + Bj[i] -= sdu_sz; + } + } + } + + // If resources remain, allocate regardless of their Bj value + for (int i=0;i 0) { + mac_io_h->get(IO_IDX(i))->release(); + nof_tx_pkts[i]--; + } + } + + /* Generate MAC PDU and save to buffer */ + if (pdu_msg.write_packet(buff)) { + pdu_buff.push(pdu_sz); + } else { + Error("Writing PDU message to packet\n"); + return false; + } + return true; +} + + +bool mux::allocate_sdu(uint32_t lcid, mac_pdu *pdu) +{ + return allocate_sdu(lcid, pdu, NULL); +} + +bool mux::allocate_sdu(uint32_t lcid, mac_pdu *pdu, uint32_t *sdu_sz) +{ + + // Get n-th pending SDU pointer and length + uint32_t buff_len; + uint8_t *buff_ptr = (uint8_t*) mac_io_h->get(lcid)->pop(&buff_len, nof_tx_pkts[lcid]); + + if (buff_ptr) { // there is pending SDU to allocate + if (pdu->write_next()) { // there is space for a new subheader + if (pdu->get()->set_sdu(buff_ptr, buff_len)) { // new SDU could be added + // Increase number of pop'ed packets from queue + nof_tx_pkts[lcid]++; + return true; + } + } + } + return false; +} + + + +void mux::msg3_flush() +{ + msg3_buff.flush(); +} + +bool mux::msg3_isempty() +{ + return msg3_buff.isempty(); +} + +/* Returns a pointer to the Msg3 buffer */ +uint8_t* mux::msg3_pop(uint32_t tti, uint32_t TB_size) +{ + uint32_t len; + uint8_t *msg3 = (uint8_t*) msg3_buff.pop(&len); + if (len < TB_size) { + // Pad with zeros without exceeding maximum buffer size + if (TB_size <= MSG3_BUFF_SZ) { + bzero(&msg3[len], (TB_size-len)*sizeof(uint8_t)); + } else { + Error("Requested TB size from Msg3 buffer exceeds buffer size (%d>%d)\n", TB_size, MSG3_BUFF_SZ); + return NULL; + } + } + return msg3; +} + +void mux::msg3_release() +{ + msg3_buff.release(); +} + + + +} +} diff --git a/srsapps/ue/mac/src/proc_ra.cc b/srsapps/ue/mac/src/proc_ra.cc new file mode 100644 index 000000000..e8d01de36 --- /dev/null +++ b/srsapps/ue/mac/src/proc_ra.cc @@ -0,0 +1,442 @@ + +#include +#include + +#include "srsapps/ue/mac/mac_params.h" +#include "srsapps/ue/mac/mac_io.h" +#include "srsapps/ue/mac/proc_ra.h" +#include "srsapps/ue/mac/mac.h" +#include "srsapps/ue/mac/mux.h" + +/* Random access procedure as specified in Section 5.1 of 36.321 */ + +namespace srslte { +namespace ue { + +// Table 7.2-1. Backoff Parameter values +uint32_t backoff_table[16] = {0, 10, 20, 30, 40, 60, 80, 120, 160, 240, 320, 480, 960, 960, 960, 960}; + +// Table 7.6-1: DELTA_PREAMBLE values. +int delta_preamble_db_table[5] = {0, 0, -3, -3, 8}; + +bool ra_proc::init(mac_params* params_db_, phy* phy_h_, srslte::log* log_h_, srslte::timers* timers_db_, + mux* mux_unit_, demux* demux_unit_) +{ + phy_h = phy_h_; + log_h = log_h_; + params_db = params_db_; + timers_db = timers_db_; + mux_unit = mux_unit_; + demux_unit= demux_unit_; + reset(); +} + +void ra_proc::reset() { + state = IDLE; +} + +void ra_proc::read_params() { + + // Read initialization parameters + configIndex = params_db->get_param(mac_params::RA_CONFIGINDEX); + preambleIndex = params_db->get_param(mac_params::RA_PREAMBLEINDEX); + maskIndex = params_db->get_param(mac_params::RA_MASKINDEX); + nof_preambles = params_db->get_param(mac_params::RA_NOFPREAMBLES); + if (!nof_preambles || nof_preambles > 64) { + nof_preambles = 64; + } + nof_groupA_preambles = params_db->get_param(mac_params::RA_NOFGROUPAPREAMBLES); + if (!nof_groupA_preambles) { + nof_groupA_preambles = nof_preambles; + } + if (nof_groupA_preambles > nof_preambles) { + nof_groupA_preambles = nof_preambles; + } + nof_groupB_preambles = nof_preambles - nof_groupA_preambles; + if (nof_groupB_preambles) { + messagePowerOffsetGroupB = params_db->get_param(mac_params::RA_MESSAGEPOWEROFFSETB); + messageSizeGroupA = params_db->get_param(mac_params::RA_MESSAGESIZEA); + Pcmax = params_db->get_param(mac_params::RA_PCMAX); + deltaPreambleMsg3 = params_db->get_param(mac_params::RA_DELTAPREAMBLEMSG3); + } + responseWindowSize = params_db->get_param(mac_params::RA_RESPONSEWINDOW); + powerRampingStep = params_db->get_param(mac_params::RA_POWERRAMPINGSTEP); + preambleTransMax = params_db->get_param(mac_params::RA_PREAMBLETRANSMAX); + iniReceivedTargetPower = params_db->get_param(mac_params::RA_INITRECEIVEDPOWER); + maxharq_msg3tx = params_db->get_param(mac_params::RA_MAXTXMSG3); + contentionResolutionTimer = params_db->get_param(mac_params::RA_CONTENTIONTIMER); + + delta_preamble_db = delta_preamble_db_table[configIndex]; + + if (contentionResolutionTimer > 0) { + timers_db->get(mac::CONTENTION_TIMER)->set(this, contentionResolutionTimer); + } + +} + +bool ra_proc::in_progress() +{ + return (state > IDLE && state != COMPLETION); +} + +bool ra_proc::is_successful() { + return state == COMPLETION; +} + +bool ra_proc::is_contention_resolution() { + return state == CONTENTION_RESOLUTION; +} + +bool ra_proc::is_error() { + return state == RA_PROBLEM; +} + +uint32_t interval(uint32_t x1, uint32_t x2) { + if (x1 > x2) { + return x1-x2; + } else { + return 10240-x2+x1; + } +} + +const char* state_str[10] = {"Idle", + "RA Initializat.: ", + "RA ResSelection: ", + "RA PreambleTx : ", + "RA PreambleRx : ", + "RA ResponseErr : ", + "RA BackoffWait : ", + "RA ContentResol: ", + "RA Completed : ", + "RA Problem : "}; + +#define rError(fmt, ...) Error("%s" fmt, state_str[state], ##__VA_ARGS__) +#define rInfo(fmt, ...) Info("%s" fmt, state_str[state], ##__VA_ARGS__) +#define rDebug(fmt, ...) Debug("%s" fmt, state_str[state], ##__VA_ARGS__) + + +// Process Timing Advance Command as defined in Section 5.2 +void ra_proc::process_timeadv_cmd(uint32_t tti, uint32_t ta) { + if (preambleIndex > 0) { + // Preamble not selected by UE MAC + phy_h->set_timeadv_rar(ta); + timers_db->get(mac::TIME_ALIGNMENT)->reset(); + timers_db->get(mac::TIME_ALIGNMENT)->run(); + Info("Applying RAR TA CMD %d\n", ta); + } else { + // Preamble selected by UE MAC + if (!timers_db->get(mac::TIME_ALIGNMENT)->is_running()) { + phy_h->set_timeadv_rar(ta); + timers_db->get(mac::TIME_ALIGNMENT)->run(); + Info("Applying RAR TA CMD %d\n", ta); + } else { + // Ignore TA CMD + Warning("Ignoring RAR TA CMD because timeAlignmentTimer still running\n"); + } + } +} + +void ra_proc::step_initialization() { + read_params(); + pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED; + received_contention_id = 0; + transmitted_contention_id = 0; + preambleTransmissionCounter = 1; + first_rar_received = true; + mux_unit->msg3_flush(); + backoff_param_ms = 0; + phy_h->init_prach(); + state = RESOURCE_SELECTION; + rInfo("Done\n"); + +} + +void ra_proc::step_resource_selection() { + ra_group_t sel_group; + if (preambleIndex > 0) { + // Preamble is chosen by Higher layers (ie Network) + sel_maskIndex = maskIndex; + sel_preamble = (uint32_t) preambleIndex%nof_preambles; + } else { + // Preamble is chosen by MAC UE + if (!msg3_transmitted) { + if (nof_groupB_preambles > 0) { // Check also messageSizeGroupA and pathloss (Pcmax,deltaPreamble and powerOffset) + sel_group = RA_GROUP_B; + } else { + sel_group = RA_GROUP_A; + } + last_msg3_group = sel_group; + } else { + sel_group = last_msg3_group; + } + if (sel_group == RA_GROUP_A) { + sel_preamble = rand()%(nof_groupA_preambles-1); + } else { + sel_preamble = nof_groupA_preambles + rand()%(nof_groupB_preambles-1); + } + sel_maskIndex = 0; + } + rInfo("Selected preambleIndex=%d maskIndex=%d nof_GroupApreambles=%d\n", sel_preamble, sel_maskIndex,nof_groupA_preambles); + state = PREAMBLE_TRANSMISSION; +} + +void ra_proc::step_preamble_transmission() { + received_target_power_dbm = iniReceivedTargetPower + + delta_preamble_db + + (preambleTransmissionCounter-1)*powerRampingStep; + + phy_h->send_prach(sel_preamble, sel_maskIndex - 1, received_target_power_dbm); + rInfo("Selected received_target_power_dbm=%d dBm\n", received_target_power_dbm); + state = RESPONSE_RECEPTION; +} + +void ra_proc::step_response_reception() { + int ra_tti = phy_h->get_prach_transmitted_tti(); + if (ra_tti > 0) { + + ra_rnti = 1+ra_tti%10; // f_id=0 for FDD + dl_sched_grant rar_grant(ra_rnti); + uint32_t interval_ra = interval(tti, ra_tti); + + // Try to decode RAR only within the RA response window + if (interval_ra >= 3 && interval_ra <= 3+responseWindowSize) { + + // Get DL grant for RA-RNTI + dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti); + if (dl_buffer->get_dl_grant(&rar_grant)) + { + rInfo("DL grant found RA-RNTI=%d\n", ra_rnti); + + if (rar_grant.get_tbs() > MAX_RAR_PDU_LEN) { + rError("RAR PDU exceeds local RAR PDU buffer (%d>%d)\n", rar_grant.get_tbs(), MAX_RAR_PDU_LEN); + state = RESPONSE_ERROR; + return; + } + + // Decode packet + if (dl_buffer->decode_data(&rar_grant, rar_pdu_buffer)) { + rar_pdu.init(rar_grant.get_tbs()); + + // Set Backoff parameter + if (rar_pdu.is_backoff()) { + backoff_param_ms = backoff_table[rar_pdu.get_backoff()%16]; + } else { + backoff_param_ms = 0; + } + + while(rar_pdu.read_next()) { + if (rar_pdu.get()->get_rapid() == sel_preamble) { + rInfo("Received RAPID=%d\n", sel_preamble); + + process_timeadv_cmd(tti, rar_pdu.get()->get_ta_cmd()); + + // FIXME: Indicate received target power + //phy_h->set_target_power_rar(iniReceivedTargetPower, (preambleTransmissionCounter-1)*powerRampingStep); + + // Indicate grant to PHY layer. RAR grants have 6 sf delay (4 is the default delay) + uint8_t grant[mac_rar_pdu::mac_rar::RAR_GRANT_LEN]; + rar_pdu.get()->get_sched_grant(grant); + phy_h->get_dl_buffer(tti+2)->set_rar_grant(grant); + + if (preambleIndex > 0) { + // Preamble selected by Network + state = COMPLETION; + } else { + // Preamble selected by UE MAC + params_db->set_param(mac_params::RNTI_TEMP, rar_pdu.get()->get_temp_crnti()); + if (first_rar_received) { + first_rar_received = false; + + // Save transmitted C-RNTI (if any) + transmitted_crnti = params_db->get_param(mac_params::RNTI_C); + + // Save transmitted UE contention id, as defined by higher layers + transmitted_contention_id = params_db->get_param(mac_params::CONTENTION_ID); + params_db->set_param(mac_params::CONTENTION_ID, 0); + + // If we have a C-RNTI, tell Mux unit to append C-RNTI CE if no CCCH SDU transmission + if (transmitted_crnti) { + mux_unit->append_crnti_ce_next_tx(transmitted_crnti); + } + + // Get TransportBlock size for the grant + ul_sched_grant msg3_grant(rar_pdu.get()->get_temp_crnti()); + phy_h->get_dl_buffer(tti+2)->get_ul_grant(&msg3_grant); + + // Move MAC PDU from Multiplexing and assembly unit to Msg3 + mux_unit->pdu_move_to_msg3(tti, msg3_grant.get_tbs()); // 56 is the minimum grant provided + + state = CONTENTION_RESOLUTION; + + // Start contention resolution timer + timers_db->get(mac::CONTENTION_TIMER)->reset(); + timers_db->get(mac::CONTENTION_TIMER)->run(); + } + } + } + } + } + } + } + if (interval_ra > 3+responseWindowSize && interval_ra < 10000) { + rInfo("Timeout while trying to receive RAR\n"); + state = RESPONSE_ERROR; + } + } +} + +void ra_proc::step_response_error() { + mux_unit->msg3_flush(); + + preambleTransmissionCounter++; + if (preambleTransmissionCounter == preambleTransMax + 1) { + rError("Maximum number of transmissions reached (%d)\n", preambleTransMax); + state = RA_PROBLEM; + } else { + backoff_interval_start = tti; + if (backoff_param_ms) { + backoff_inteval = rand()%backoff_param_ms; + } else { + backoff_inteval = 0; + } + if (backoff_inteval) { + rInfo("Backoff wait interval %d\n", backoff_inteval); + state = BACKOFF_WAIT; + } else { + rInfo("Transmitting inmediatly\n"); + state = RESOURCE_SELECTION; + } + } +} + +void ra_proc::step_backoff_wait() { + if (interval(tti, backoff_interval_start) >= backoff_inteval) { + state = RESOURCE_SELECTION; + } +} + +void ra_proc::step_contention_resolution() { + // If Msg3 has been sent + if (mux_unit->msg3_isempty()) { + msg3_transmitted = true; + if (pdcch_to_crnti_received != PDCCH_CRNTI_NOT_RECEIVED) + { + // Random Access initiated by MAC itself or PDCCH order (transmission of MAC C-RNTI CE) + if (start_mode == MAC_ORDER && pdcch_to_crnti_received == PDCCH_CRNTI_UL_GRANT || + start_mode == PDCCH_ORDER) + { + timers_db->get(mac::CONTENTION_TIMER)->stop(); + params_db->set_param(mac_params::RNTI_TEMP, 0); + state = COMPLETION; + } + pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED; + + } else if (demux_unit->is_temp_crnti_pending()) + { + // Random Access initiated by RRC by the transmission of CCCH SDU + received_contention_id = demux_unit->get_contention_resolution_id(); + if (received_contention_id) { + // MAC PDU successfully decoded and contains MAC CE contention Id + if (transmitted_contention_id == received_contention_id) { + + // UE Contention Resolution ID included in MAC CE matches the CCCH SDU transmitted in Msg3 + timers_db->get(mac::CONTENTION_TIMER)->stop(); + params_db->set_param(mac_params::RNTI_C, params_db->get_param(mac_params::RNTI_TEMP)); + + // finish the disassembly and demultiplexing of the MAC PDU + demux_unit->demultiplex_pending_pdu(tti); + state = COMPLETION; + } else { + // Discard MAC PDU + state = RESPONSE_ERROR; + } + params_db->set_param(mac_params::RNTI_TEMP, 0); + } + } + } +} + +void ra_proc::step_completition() { + params_db->set_param(mac_params::RA_PREAMBLEINDEX, 0); + params_db->set_param(mac_params::RA_MASKINDEX, 0); + mux_unit->msg3_flush(); + msg3_transmitted = false; +} + +void ra_proc::step(uint32_t tti_) +{ + tti = tti_; + if (is_running()) { + switch(state) { + case IDLE: + break; + case INITIALIZATION: + step_initialization(); + break; + case RESOURCE_SELECTION: + step_resource_selection(); + break; + case PREAMBLE_TRANSMISSION: + step_preamble_transmission(); + break; + case RESPONSE_RECEPTION: + step_response_reception(); + break; + case RESPONSE_ERROR: + step_response_error(); + break; + case BACKOFF_WAIT: + step_backoff_wait(); + break; + case CONTENTION_RESOLUTION: + step_contention_resolution(); + break; + case COMPLETION: + step_completition(); + break; + } + } +} + +void ra_proc::start_mac_order() +{ + if (state == IDLE || state == COMPLETION || state == RA_PROBLEM) { + start_mode = MAC_ORDER; + state = INITIALIZATION; + } +} + +void ra_proc::start_pdcch_order() +{ + if (state == IDLE || state == COMPLETION || state == RA_PROBLEM) { + start_mode = PDCCH_ORDER; + state = INITIALIZATION; + } +} + +void ra_proc::start_rlc_order() +{ + if (state == IDLE || state == COMPLETION || state == RA_PROBLEM) { + start_mode = RLC_ORDER; + state = INITIALIZATION; + } +} + +// Contention Resolution Timer is expired (Section 5.1.5) +void ra_proc::timer_expired(uint32_t timer_id) +{ + params_db->set_param(mac_params::RNTI_TEMP, 0); + state = RESPONSE_ERROR; +} + +void ra_proc::pdcch_to_crnti(bool is_uplink_grant) { + if (is_uplink_grant) { + pdcch_to_crnti_received = PDCCH_CRNTI_UL_GRANT; + } else { + pdcch_to_crnti_received = PDCCH_CRNTI_DL_GRANT; + } +} + +} +} + diff --git a/srsapps/ue/mac/src/ul_harq.cc b/srsapps/ue/mac/src/ul_harq.cc new file mode 100644 index 000000000..4cb5228c6 --- /dev/null +++ b/srsapps/ue/mac/src/ul_harq.cc @@ -0,0 +1,241 @@ +#include "srsapps/ue/phy/phy.h" +#include "srsapps/common/log.h" + +#include "srsapps/ue/mac/mac.h" +#include "srsapps/ue/mac/ul_harq.h" + +namespace srslte { + namespace ue { + + /*********************************************************** + * + * HARQ ENTITY + * + *********************************************************/ + +ul_harq_entity::ul_harq_entity() { + proc = new ul_harq_process[NOF_HARQ_PROC]; // BCCH process is separate +} +ul_harq_entity::~ul_harq_entity() { +delete proc; +} +bool ul_harq_entity::init(srslte_cell_t cell, uint32_t max_payload_len, log *log_h_, timers *timers_db_, mux *mux_unit_) { + log_h = log_h_; + mux_unit = mux_unit_; + timers_db = timers_db_; + + for (uint32_t i=0;iis_temp_rnti() && grant->get_ndi() != proc[pid].get_ndi()) || + (grant->is_crnti() && !proc[pid].has_grant()) || + grant->is_from_rar()) + { + // New transmission + uint8_t* msg3_ptr = (uint8_t*) mux_unit->msg3_pop(tti, grant->get_tbs()); + + // Uplink grant in a RAR + if (msg3_ptr && grant->is_from_rar()) { + proc[pid].generate_new_tx(msg3_ptr, true, grant, phy_h->get_ul_buffer(tti+4)); + mux_unit->msg3_release(); + + // Normal UL grant + } else { + // Request a MAC PDU from the Multiplexing & Assemble Unit + uint8_t* mac_pdu = mux_unit->pdu_pop(tti, grant->get_tbs()); + if (mac_pdu) { + proc[pid].generate_new_tx(mac_pdu, false, grant, phy_h->get_ul_buffer(tti+4)); + mux_unit->pdu_release(); + } else { + Warning("Uplink grant with MAC PDU available in Multiplex Unit\n"); + } + } + } else { + // Adaptive Re-TX + proc[pid].generate_retx(grant, phy_h->get_ul_buffer(tti+4)); + } + } else if (proc[pid].has_grant()) { + // Non-Adaptive Re-Tx + proc[pid].generate_retx(phy_h->get_ul_buffer(tti+4)); + } + + // Receive and route HARQ feedbacks + for (uint32_t i=0;iget_dl_buffer(tti)->decode_ack(proc[pid].get_grant())); + } + } +} + +bool ul_harq_entity::is_last_retx_msg3() +{ + return last_retx_is_msg3; +} + + + +/*********************************************************** + * + * HARQ PROCESS + * + *********************************************************/ + +static int rv_of_irv[4] = {0, 2, 3, 1}; +static int irv_of_rv[4] = {0, 3, 1, 2}; + +ul_harq_entity::ul_harq_process::ul_harq_process() : cur_grant(0) { + payload = NULL; + max_payload_len = 0; + current_tx_nb = 0; + current_irv = 0; + is_grant_configured = false; + bzero(&cur_grant, sizeof(ul_sched_grant)); +} +void ul_harq_entity::ul_harq_process::reset() { + current_tx_nb = 0; + current_irv = 0; + is_grant_configured = false; + bzero(&cur_grant, sizeof(ul_sched_grant)); + srslte_softbuffer_tx_reset(&softbuffer); +} +bool ul_harq_entity::ul_harq_process::has_grant() { + return is_grant_configured; +} +void ul_harq_entity::ul_harq_process::reset_ndi() { + ndi = false; +} +bool ul_harq_entity::ul_harq_process::get_ndi() +{ + return ndi; +} + +ul_sched_grant* ul_harq_entity::ul_harq_process::get_grant() +{ + return &cur_grant; +} + +void ul_harq_entity::ul_harq_process::set_harq_feedback(bool ack) { + harq_feedback = ack; +} +void ul_harq_entity::ul_harq_process::set_maxHARQ_Tx(uint32_t maxHARQ_Tx_, uint32_t maxHARQ_Msg3Tx_) { + maxHARQ_Tx = maxHARQ_Tx_; + maxHARQ_Msg3Tx = maxHARQ_Msg3Tx_; +} + +bool ul_harq_entity::ul_harq_process::init(srslte_cell_t cell, uint32_t max_payload_len_, ul_harq_entity *parent) { + max_payload_len = max_payload_len_; + if (srslte_softbuffer_tx_init(&softbuffer, cell)) { + fprintf(stderr, "Error initiating soft buffer\n"); + return false; + } else { + harq_entity = parent; + log_h = harq_entity->log_h; + payload = (uint8_t*) srslte_vec_malloc(sizeof(uint8_t) * max_payload_len); + return payload?true:false; + } +} + +// Retransmission with or w/o grant (Section 5.4.2.2) +void ul_harq_entity::ul_harq_process::generate_retx(ul_sched_grant* grant, ul_buffer* ul) +{ + current_tx_nb++; + + if (grant) { + // HARQ entity requests an adaptive transmission + memcpy(&cur_grant, grant, sizeof(grant)); + current_irv = irv_of_rv[grant->get_rv()%4]; + harq_feedback = false; + generate_tx(ul); + } else { + // HARQ entity requests a non-adaptive transmission + if (!harq_feedback) { + generate_tx(ul); + } + } + + // On every Msg3 retransmission, restart mac-ContentionResolutionTimer as defined in Section 5.1.5 + if (is_msg3) { + harq_entity->timers_db->get(mac::CONTENTION_TIMER)->reset(); + } +} + +// New transmission (Section 5.4.2.2) +void ul_harq_entity::ul_harq_process::generate_new_tx(uint8_t *pdu_payload, bool is_msg3_, ul_sched_grant* ul_grant, ul_buffer* ul) +{ + if (ul_grant && pdu_payload && ul_grant->get_tbs() < max_payload_len) { + current_tx_nb = 0; + current_irv = 0; + // Store MAC PDU in the HARQ buffer + srslte_bit_pack_vector(pdu_payload, payload, ul_grant->get_tbs()); + // Store the uplink grant + memcpy(&cur_grant, ul_grant, sizeof(ul_grant)); + harq_feedback = false; + generate_tx(ul); + is_grant_configured = true; + is_msg3 = is_msg3_; + } +} + +void ul_harq_entity::ul_harq_process::generate_retx(ul_buffer* ul) +{ + generate_retx(NULL, ul); +} + + // Transmission of pending frame (Section 5.4.2.2) +void ul_harq_entity::ul_harq_process::generate_tx(ul_buffer* ul) +{ + cur_grant.set_rv(rv_of_irv[current_irv%4]); + ul->set_current_tx_nb(current_tx_nb); + ul->generate_data(&cur_grant, &softbuffer, payload); + current_irv = (current_irv+1)%4; + if (is_msg3) { + if (current_tx_nb == maxHARQ_Msg3Tx) { + reset(); + } + } else { + if (current_tx_nb == maxHARQ_Tx) { + reset(); + } + } + +} + +} +} \ No newline at end of file diff --git a/srsapps/ue/mac/test/CMakeLists.txt b/srsapps/ue/mac/test/CMakeLists.txt new file mode 100644 index 000000000..e69de29bb diff --git a/srsapps/ue/mac/test/mac_test.cc b/srsapps/ue/mac/test/mac_test.cc new file mode 100644 index 000000000..84a7315fd --- /dev/null +++ b/srsapps/ue/mac/test/mac_test.cc @@ -0,0 +1,283 @@ + +#include + +#include "liblte_rrc.h" +#include "srsapps/radio/radio_uhd.h" +#include "srsapps/ue/phy/phy.h" +#include "srsapps/common/tti_sync_cv.h" +#include "srsapps/common/log_stdout.h" +#include "srsapps/ue/mac/mac.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 = 60.0; +} + +void usage(prog_args_t *args, char *prog) { + printf("Usage: %s [gv] -f rx_frequency (in Hz) -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 RX 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); + } +} + +// Determine SI messages scheduling as in 36.331 5.2.3 Acquisition of an SI message +uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t x) { + return (period*10*(1+tti/(period*10))+x)%10240; // the 1 means next opportunity +} + +void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::ue::mac *mac, srslte::ue::phy *phy) { + // RACH-CONFIGCOMMON + if (sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.present) { + mac->set_param(srslte::ue::mac_params::RA_NOFGROUPAPREAMBLES, + liblte_rrc_message_size_group_a_num[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.size_of_ra]); + mac->set_param(srslte::ue::mac_params::RA_MESSAGESIZEA, + liblte_rrc_message_size_group_a_num[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.msg_size]); + mac->set_param(srslte::ue::mac_params::RA_MESSAGEPOWEROFFSETB, + liblte_rrc_message_power_offset_group_b_num[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.msg_pwr_offset_group_b]); + } + mac->set_param(srslte::ue::mac_params::RA_NOFPREAMBLES, + liblte_rrc_number_of_ra_preambles_num[sib2->rr_config_common_sib.rach_cnfg.num_ra_preambles]); + mac->set_param(srslte::ue::mac_params::RA_POWERRAMPINGSTEP, + liblte_rrc_power_ramping_step_num[sib2->rr_config_common_sib.rach_cnfg.pwr_ramping_step]); + mac->set_param(srslte::ue::mac_params::RA_INITRECEIVEDPOWER, + liblte_rrc_preamble_initial_received_target_power_num[sib2->rr_config_common_sib.rach_cnfg.preamble_init_rx_target_pwr]); + mac->set_param(srslte::ue::mac_params::RA_PREAMBLETRANSMAX, + liblte_rrc_preamble_trans_max_num[sib2->rr_config_common_sib.rach_cnfg.preamble_trans_max]); + mac->set_param(srslte::ue::mac_params::RA_RESPONSEWINDOW, + liblte_rrc_ra_response_window_size_num[sib2->rr_config_common_sib.rach_cnfg.ra_resp_win_size]); + mac->set_param(srslte::ue::mac_params::RA_CONTENTIONTIMER, + liblte_rrc_mac_contention_resolution_timer_num[sib2->rr_config_common_sib.rach_cnfg.mac_con_res_timer]); + mac->set_param(srslte::ue::mac_params::RA_MAXTXMSG3, + sib2->rr_config_common_sib.rach_cnfg.max_harq_msg3_tx); + + printf("Set RACH ConfigCommon: NofPreambles=%d, ResponseWindow=%d\n", + liblte_rrc_number_of_ra_preambles_num[sib2->rr_config_common_sib.rach_cnfg.num_ra_preambles], + liblte_rrc_ra_response_window_size_num[sib2->rr_config_common_sib.rach_cnfg.ra_resp_win_size]); + + // PDSCH ConfigCommon + mac->set_param(srslte::ue::mac_params::PDSCH_RSPOWER, + sib2->rr_config_common_sib.pdsch_cnfg.rs_power); + mac->set_param(srslte::ue::mac_params::PDSCH_PB, + sib2->rr_config_common_sib.pdsch_cnfg.p_b); + + // PUSCH ConfigCommon + phy->set_param(srslte::ue::phy_params::PUSCH_EN_64QAM, + sib2->rr_config_common_sib.pusch_cnfg.enable_64_qam); + phy->set_param(srslte::ue::phy_params::PUSCH_HOPPING_OFFSET, + sib2->rr_config_common_sib.pusch_cnfg.pusch_hopping_offset); + phy->set_param(srslte::ue::phy_params::PUSCH_HOPPING_N_SB, + sib2->rr_config_common_sib.pusch_cnfg.n_sb); + phy->set_param(srslte::ue::phy_params::PUSCH_HOPPING_INTRA_SF, + sib2->rr_config_common_sib.pusch_cnfg.hopping_mode == LIBLTE_RRC_HOPPING_MODE_INTRA_AND_INTER_SUBFRAME?1:0); + phy->set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_HOPPING_EN, + sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_hopping_enabled?1:0); + phy->set_param(srslte::ue::phy_params::PUSCH_RS_SEQUENCE_HOPPING_EN, + sib2->rr_config_common_sib.pusch_cnfg.ul_rs.sequence_hopping_enabled?1:0); + phy->set_param(srslte::ue::phy_params::PUSCH_RS_CYCLIC_SHIFT, + sib2->rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift); + phy->set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_ASSIGNMENT, + sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch); + + printf("Set PUSCH ConfigCommon: HopOffset=%d, RSGroup=%d, RSNcs=%d\n", + sib2->rr_config_common_sib.pusch_cnfg.pusch_hopping_offset, + sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch, + sib2->rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift); + + // PUCCH ConfigCommon + phy->set_param(srslte::ue::phy_params::PUCCH_DELTA_SHIFT, + liblte_rrc_delta_pucch_shift_num[sib2->rr_config_common_sib.pucch_cnfg.delta_pucch_shift]); + phy->set_param(srslte::ue::phy_params::PUCCH_CYCLIC_SHIFT, + sib2->rr_config_common_sib.pucch_cnfg.n_cs_an); + phy->set_param(srslte::ue::phy_params::PUCCH_N_PUCCH_1, + sib2->rr_config_common_sib.pucch_cnfg.n1_pucch_an); + phy->set_param(srslte::ue::phy_params::PUCCH_N_RB_2, + sib2->rr_config_common_sib.pucch_cnfg.n_rb_cqi); + printf("Set PUCCH ConfigCommon: DeltaShift=%d, CyclicShift=%d, N1=%d, NRB=%d\n", + liblte_rrc_delta_pucch_shift_num[sib2->rr_config_common_sib.pucch_cnfg.delta_pucch_shift], + sib2->rr_config_common_sib.pucch_cnfg.n_cs_an, + sib2->rr_config_common_sib.pucch_cnfg.n1_pucch_an, + sib2->rr_config_common_sib.pucch_cnfg.n_rb_cqi); + + + // PRACH Configcommon + phy->set_param(srslte::ue::phy_params::PRACH_ROOT_SEQ_IDX, + sib2->rr_config_common_sib.prach_cnfg.root_sequence_index); + phy->set_param(srslte::ue::phy_params::PRACH_HIGH_SPEED_FLAG, + sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.high_speed_flag?1:0); + phy->set_param(srslte::ue::phy_params::PRACH_FREQ_OFFSET, + sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_freq_offset); + phy->set_param(srslte::ue::phy_params::PRACH_ZC_CONFIG, + sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.zero_correlation_zone_config); + phy->set_param(srslte::ue::phy_params::PRACH_CONFIG_INDEX, + sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_config_index); + + printf("Set PRACH ConfigCommon: SeqIdx=%d, HS=%d, FreqOffset=%d, ZC=%d, ConfigIndex=%d\n", + sib2->rr_config_common_sib.prach_cnfg.root_sequence_index, + sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.high_speed_flag?1:0, + sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_freq_offset, + sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.zero_correlation_zone_config, + sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_config_index); +} + +int main(int argc, char *argv[]) +{ + prog_args_t prog_args; + srslte::ue::tti_sync_cv ttisync(10240); + srslte::radio_uhd radio_uhd; + srslte::ue::phy phy; + srslte::ue::mac mac; + srslte::log_stdout log("MAC"); + + parse_args(&prog_args, argc, argv); + + // Init Radio + radio_uhd.init(); + + // Init PHY + phy.init(&radio_uhd, &ttisync); + + // Init MAC + mac.init(&phy, &ttisync, &log); + + // Set RX freq and gain + radio_uhd.set_rx_freq(prog_args.uhd_rx_freq); + radio_uhd.set_rx_gain(prog_args.uhd_rx_gain); + radio_uhd.set_tx_freq(prog_args.uhd_tx_freq); + radio_uhd.set_tx_gain(prog_args.uhd_tx_gain); + + LIBLTE_BIT_MSG_STRUCT bit_msg; + LIBLTE_RRC_MIB_STRUCT bch_msg; + LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT dlsch_msg; + LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg; + LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg; + + uint32_t si_window_len, sib2_period; + int tti; + enum {START, SIB1, SIB2, CONNECT} state = START; + int n; + + while(1) { + switch(state) { + case START: + n = mac.recv_bcch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE); + if (n > 0) { + bit_msg.N_bits = n; + liblte_rrc_unpack_bcch_bch_msg(&bit_msg, &bch_msg); + printf("MIB received %d bytes, BW=%s\n", n, liblte_rrc_dl_bandwidth_text[bch_msg.dl_bw]); + state = SIB1; + } + break; + case SIB1: + n = mac.recv_bcch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE); + if (n > 0) { + bit_msg.N_bits = n; + liblte_rrc_unpack_bcch_dlsch_msg(&bit_msg, &dlsch_msg); + si_window_len = liblte_rrc_si_window_length_num[dlsch_msg.sibs[0].sib.sib1.si_window_length]; + sib2_period = liblte_rrc_si_periodicity_num[dlsch_msg.sibs[0].sib.sib1.sched_info[0].si_periodicity]; + printf("SIB1 received %d bytes, CellID=%d, si_window=%d, sib2_period=%d\n", + n/8, dlsch_msg.sibs[0].sib.sib1.cell_id&0xfff, si_window_len, sib2_period); + printf("Payload: "); + srslte_vec_fprint_hex(stdout, bit_msg.msg, n); + state = SIB2; + } else { + tti = mac.get_tti(); + mac.set_param(srslte::ue::mac_params::BCCH_SI_WINDOW_ST, sib_start_tti(tti, 2, 5)); + mac.set_param(srslte::ue::mac_params::BCCH_SI_WINDOW_LEN, 1); + } + break; + case SIB2: + n = mac.recv_bcch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE); + if (n > 0) { + // Process SIB2 + bit_msg.N_bits = n; + liblte_rrc_unpack_bcch_dlsch_msg(&bit_msg, &dlsch_msg); + printf("SIB2 received %d bytes\n", n/8); + printf("Payload: "); + srslte_vec_fprint_hex(stdout, bit_msg.msg, n); + setup_mac_phy_sib2(&dlsch_msg.sibs[0].sib.sib2, &mac, &phy); + + // Prepare ConnectionRequest packet + ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ; + ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE; + ul_ccch_msg.msg.rrc_con_req.ue_id.random = 1000; + ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_DATA; + liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, &bit_msg); + + mac.set_param(srslte::ue::mac_params::CONTENTION_ID, ul_ccch_msg.msg.rrc_con_req.ue_id.random); + + // Send ConnectionRequest Packet + mac.send_ccch_sdu(bit_msg.msg, bit_msg.N_bits); + state = CONNECT; + } else { + tti = mac.get_tti(); + mac.set_param(srslte::ue::mac_params::BCCH_SI_WINDOW_ST, sib_start_tti(tti, sib2_period, 0)); + mac.set_param(srslte::ue::mac_params::BCCH_SI_WINDOW_LEN, si_window_len); + } + break; + case CONNECT: + // Waint for Connection Setup + n = mac.recv_ccch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE); + if (n > 0) { + printf("ConnSetup received %d bytes\n", n/8); + bit_msg.N_bits = n; + liblte_rrc_unpack_dl_ccch_msg(&bit_msg, &dl_ccch_msg); + printf("Response: %s\n", liblte_rrc_dl_ccch_msg_type_text[dl_ccch_msg.msg_type]); + if (dl_ccch_msg.msg_type == LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP) { + // Process ConnectionRequest + } + exit(0); + } + break; + } + + usleep(50000); + } +} + + + diff --git a/srsapps/ue/phy/CMakeLists.txt b/srsapps/ue/phy/CMakeLists.txt new file mode 100644 index 000000000..30a33f1fe --- /dev/null +++ b/srsapps/ue/phy/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# Copyright 2012-2013 The srsLTE Developers. See the +# COPYRIGHT file at the top-level directory of this distribution. +# +# 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/. +# + +FILE(GLOB SOURCES "src/*.cc") +ADD_LIBRARY(srsapps_ue_phy SHARED ${SOURCES}) +TARGET_LINK_LIBRARIES(srsapps_ue_phy srsapps_common) +INSTALL(TARGETS srsapps_ue_phy DESTINATION ${LIBRARY_DIR}) +LIBLTE_SET_PIC(srsapps_ue_phy) + +FILE(GLOB SOURCES "include/srsapps/ue/phy/*.h") +ADD_CUSTOM_TARGET (add_ue_phy_headers SOURCES ${HEADERS_ALL}) + +ADD_SUBDIRECTORY(test) + diff --git a/srslte/include/srslte/ue_itf/dl_buffer.h b/srsapps/ue/phy/include/srsapps/ue/phy/dl_buffer.h similarity index 93% rename from srslte/include/srslte/ue_itf/dl_buffer.h rename to srsapps/ue/phy/include/srsapps/ue/phy/dl_buffer.h index 70075f56f..dd3f93fe1 100644 --- a/srslte/include/srslte/ue_itf/dl_buffer.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/dl_buffer.h @@ -26,10 +26,10 @@ */ #include "srslte/srslte.h" -#include "srslte/ue_itf/queue.h" -#include "srslte/ue_itf/ul_sched_grant.h" -#include "srslte/ue_itf/dl_sched_grant.h" -#include "srslte/ue_itf/phy_params.h" +#include "srsapps/common/queue.h" +#include "srsapps/ue/phy/ul_sched_grant.h" +#include "srsapps/ue/phy/dl_sched_grant.h" +#include "srsapps/ue/phy/phy_params.h" #ifndef UEDLBUFFER_H #define UEDLBUFFER_H diff --git a/srslte/include/srslte/ue_itf/dl_sched_grant.h b/srsapps/ue/phy/include/srsapps/ue/phy/dl_sched_grant.h similarity index 98% rename from srslte/include/srslte/ue_itf/dl_sched_grant.h rename to srsapps/ue/phy/include/srsapps/ue/phy/dl_sched_grant.h index 76eab82e4..e4b589bab 100644 --- a/srslte/include/srslte/ue_itf/dl_sched_grant.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/dl_sched_grant.h @@ -27,7 +27,7 @@ #include #include "srslte/srslte.h" -#include "srslte/ue_itf/sched_grant.h" +#include "srsapps/ue/phy/sched_grant.h" #ifndef UEDLSCHEDGRANT_H #define UEDLSCHEDGRANT_H diff --git a/srslte/include/srslte/ue_itf/phy.h b/srsapps/ue/phy/include/srsapps/ue/phy/phy.h similarity index 94% rename from srslte/include/srslte/ue_itf/phy.h rename to srsapps/ue/phy/include/srsapps/ue/phy/phy.h index a822c1d71..d54da2db6 100644 --- a/srslte/include/srslte/ue_itf/phy.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/phy.h @@ -26,13 +26,13 @@ */ #include "srslte/srslte.h" -#include "srslte/ue_itf/tti_sync.h" -#include "srslte/ue_itf/dl_buffer.h" -#include "srslte/ue_itf/ul_buffer.h" -#include "srslte/ue_itf/prach.h" -#include "srslte/ue_itf/phy_params.h" -#include "srslte/ue_itf/sched_grant.h" -#include "srslte/ue_itf/queue.h" +#include "srsapps/common/tti_sync.h" +#include "srsapps/ue/phy/dl_buffer.h" +#include "srsapps/ue/phy/ul_buffer.h" +#include "srsapps/ue/phy/prach.h" +#include "srsapps/ue/phy/phy_params.h" +#include "srsapps/ue/phy/sched_grant.h" +#include "srsapps/common/queue.h" #include "srslte/common/radio.h" #ifndef UEPHY_H diff --git a/srslte/include/srslte/ue_itf/phy_params.h b/srsapps/ue/phy/include/srsapps/ue/phy/phy_params.h similarity index 98% rename from srslte/include/srslte/ue_itf/phy_params.h rename to srsapps/ue/phy/include/srsapps/ue/phy/phy_params.h index 44ca38710..7b34872f7 100644 --- a/srslte/include/srslte/ue_itf/phy_params.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/phy_params.h @@ -26,7 +26,7 @@ */ #include "srslte/srslte.h" -#include "srslte/ue_itf/params_db.h" +#include "srsapps/common/params_db.h" #ifndef PHYPARAMS_H #define PHYPARAMS_H diff --git a/srslte/include/srslte/ue_itf/prach.h b/srsapps/ue/phy/include/srsapps/ue/phy/prach.h similarity index 96% rename from srslte/include/srslte/ue_itf/prach.h rename to srsapps/ue/phy/include/srsapps/ue/phy/prach.h index a93c772ae..3e000132c 100644 --- a/srslte/include/srslte/ue_itf/prach.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/prach.h @@ -27,8 +27,8 @@ #include "srslte/srslte.h" #include "srslte/common/radio.h" -#include "srslte/ue_itf/queue.h" -#include "srslte/ue_itf/phy_params.h" +#include "srsapps/common/queue.h" +#include "srsapps/ue/phy/phy_params.h" #ifndef UEPRACH_H #define UEPRACH_H diff --git a/srslte/include/srslte/ue_itf/sched_grant.h b/srsapps/ue/phy/include/srsapps/ue/phy/sched_grant.h similarity index 98% rename from srslte/include/srslte/ue_itf/sched_grant.h rename to srsapps/ue/phy/include/srsapps/ue/phy/sched_grant.h index 2f411473b..59eb68fee 100644 --- a/srslte/include/srslte/ue_itf/sched_grant.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/sched_grant.h @@ -26,7 +26,7 @@ */ #include "srslte/srslte.h" -#include "queue.h" +#include "srsapps/common/queue.h" #ifndef UESCHEDGRANT_H #define UESCHEDGRANT_H diff --git a/srslte/include/srslte/ue_itf/ul_buffer.h b/srsapps/ue/phy/include/srsapps/ue/phy/ul_buffer.h similarity index 93% rename from srslte/include/srslte/ue_itf/ul_buffer.h rename to srsapps/ue/phy/include/srsapps/ue/phy/ul_buffer.h index 2774b49a9..89477c959 100644 --- a/srslte/include/srslte/ue_itf/ul_buffer.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/ul_buffer.h @@ -27,10 +27,10 @@ #include "srslte/srslte.h" #include "srslte/common/radio.h" -#include "srslte/ue_itf/queue.h" -#include "srslte/ue_itf/ul_sched_grant.h" -#include "srslte/ue_itf/dl_sched_grant.h" -#include "srslte/ue_itf/phy_params.h" +#include "srsapps/common/queue.h" +#include "srsapps/ue/phy/ul_sched_grant.h" +#include "srsapps/ue/phy/dl_sched_grant.h" +#include "srsapps/ue/phy/phy_params.h" #ifndef UEULBUFFER_H #define UEULBUFFER_H diff --git a/srslte/include/srslte/ue_itf/ul_sched_grant.h b/srsapps/ue/phy/include/srsapps/ue/phy/ul_sched_grant.h similarity index 98% rename from srslte/include/srslte/ue_itf/ul_sched_grant.h rename to srsapps/ue/phy/include/srsapps/ue/phy/ul_sched_grant.h index c80e87d32..43e88d9a0 100644 --- a/srslte/include/srslte/ue_itf/ul_sched_grant.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/ul_sched_grant.h @@ -27,7 +27,7 @@ #include #include "srslte/srslte.h" -#include "srslte/ue_itf/sched_grant.h" +#include "srsapps/ue/phy/sched_grant.h" #ifndef UEULSCHEDGRANT_H #define UEULSCHEDGRANT_H diff --git a/srslte/lib/ue_itf/src/dl_buffer.cc b/srsapps/ue/phy/src/dl_buffer.cc similarity index 97% rename from srslte/lib/ue_itf/src/dl_buffer.cc rename to srsapps/ue/phy/src/dl_buffer.cc index 392bb0aeb..6c4053367 100644 --- a/srslte/lib/ue_itf/src/dl_buffer.cc +++ b/srsapps/ue/phy/src/dl_buffer.cc @@ -30,10 +30,10 @@ #include #include "srslte/srslte.h" -#include "srslte/ue_itf/sched_grant.h" -#include "srslte/ue_itf/dl_buffer.h" -#include "srslte/ue_itf/phy.h" -#include "srslte/ue_itf/phy_params.h" +#include "srsapps/ue/phy/sched_grant.h" +#include "srsapps/ue/phy/dl_buffer.h" +#include "srsapps/ue/phy/phy.h" +#include "srsapps/ue/phy/phy_params.h" namespace srslte { diff --git a/srslte/lib/ue_itf/src/phy.cc b/srsapps/ue/phy/src/phy.cc similarity index 98% rename from srslte/lib/ue_itf/src/phy.cc rename to srsapps/ue/phy/src/phy.cc index fbecc53f3..9277d48ab 100644 --- a/srslte/lib/ue_itf/src/phy.cc +++ b/srsapps/ue/phy/src/phy.cc @@ -32,10 +32,10 @@ #include "srslte/srslte.h" -#include "srslte/ue_itf/phy.h" -#include "srslte/ue_itf/prach.h" -#include "srslte/ue_itf/ul_buffer.h" -#include "srslte/ue_itf/dl_buffer.h" +#include "srsapps/ue/phy/phy.h" +#include "srsapps/ue/phy/prach.h" +#include "srsapps/ue/phy/ul_buffer.h" +#include "srsapps/ue/phy/dl_buffer.h" namespace srslte { namespace ue { diff --git a/srslte/lib/ue_itf/src/prach.cc b/srsapps/ue/phy/src/prach.cc similarity index 98% rename from srslte/lib/ue_itf/src/prach.cc rename to srsapps/ue/phy/src/prach.cc index ecdb9ea8e..af1266568 100644 --- a/srslte/lib/ue_itf/src/prach.cc +++ b/srsapps/ue/phy/src/prach.cc @@ -31,9 +31,9 @@ #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/phy_params.h" +#include "srsapps/ue/phy/prach.h" +#include "srsapps/ue/phy/phy.h" +#include "srsapps/ue/phy/phy_params.h" namespace srslte { namespace ue { diff --git a/srslte/lib/ue_itf/src/ul_buffer.cc b/srsapps/ue/phy/src/ul_buffer.cc similarity index 98% rename from srslte/lib/ue_itf/src/ul_buffer.cc rename to srsapps/ue/phy/src/ul_buffer.cc index ccfcccf55..c10470ed7 100644 --- a/srslte/lib/ue_itf/src/ul_buffer.cc +++ b/srsapps/ue/phy/src/ul_buffer.cc @@ -30,10 +30,10 @@ #include #include "srslte/srslte.h" -#include "srslte/ue_itf/sched_grant.h" -#include "srslte/ue_itf/ul_buffer.h" -#include "srslte/ue_itf/phy.h" -#include "srslte/ue_itf/phy_params.h" +#include "srsapps/ue/phy/sched_grant.h" +#include "srsapps/ue/phy/ul_buffer.h" +#include "srsapps/ue/phy/phy.h" +#include "srsapps/ue/phy/phy_params.h" namespace srslte { namespace ue { diff --git a/srslte/lib/ue_itf/test/CMakeLists.txt b/srsapps/ue/phy/test/CMakeLists.txt similarity index 81% rename from srslte/lib/ue_itf/test/CMakeLists.txt rename to srsapps/ue/phy/test/CMakeLists.txt index ce9da9c20..14ef73de5 100644 --- a/srslte/lib/ue_itf/test/CMakeLists.txt +++ b/srsapps/ue/phy/test/CMakeLists.txt @@ -20,11 +20,10 @@ # -LIST(FIND OPTIONAL_LIBS cuhd CUHD_FIND) -IF(${CUHD_FIND} GREATER -1) +IF(UHD_FOUND) ADD_EXECUTABLE(ue_itf_test_sib1 ue_itf_test_sib1.cc) - TARGET_LINK_LIBRARIES(ue_itf_test_sib1 srslte++ cuhd) + TARGET_LINK_LIBRARIES(ue_itf_test_sib1 srsapps_ue_phy srsapps_radio srslte) 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) + TARGET_LINK_LIBRARIES(ue_itf_test_prach srsapps_ue_phy srsapps_radio srslte) +ENDIF(UHD_FOUND) diff --git a/srslte/lib/ue_itf/test/ue_itf_test_prach.cc b/srsapps/ue/phy/test/ue_itf_test_prach.cc similarity index 99% rename from srslte/lib/ue_itf/test/ue_itf_test_prach.cc rename to srsapps/ue/phy/test/ue_itf_test_prach.cc index 0d48a833a..45f45da26 100644 --- a/srslte/lib/ue_itf/test/ue_itf_test_prach.cc +++ b/srsapps/ue/phy/test/ue_itf_test_prach.cc @@ -28,9 +28,9 @@ #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" +#include "srsapps/ue/phy/phy.h" +#include "srsapps/common/tti_sync_cv.h" +#include "srsapps/radio/radio_uhd.h" /********************************************************************** * Program arguments processing diff --git a/srslte/lib/ue_itf/test/ue_itf_test_sib1.cc b/srsapps/ue/phy/test/ue_itf_test_sib1.cc similarity index 97% rename from srslte/lib/ue_itf/test/ue_itf_test_sib1.cc rename to srsapps/ue/phy/test/ue_itf_test_sib1.cc index 8e25ac6d6..e250d345b 100644 --- a/srslte/lib/ue_itf/test/ue_itf_test_sib1.cc +++ b/srsapps/ue/phy/test/ue_itf_test_sib1.cc @@ -28,9 +28,9 @@ #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" +#include "srsapps/ue/phy/phy.h" +#include "srsapps/common/tti_sync_cv.h" +#include "srsapps/radio/radio_uhd.h" /********************************************************************** diff --git a/srslte/CMakeLists.txt b/srslte/CMakeLists.txt index 0deb408ab..229624ea0 100644 --- a/srslte/CMakeLists.txt +++ b/srslte/CMakeLists.txt @@ -46,4 +46,3 @@ ADD_CUSTOM_TARGET (add_srslte_headers SOURCES ${HEADERS_ALL}) ######################################################################## ADD_SUBDIRECTORY(lib) ADD_SUBDIRECTORY(examples) -#add_subdirectory(tutorial_examples) diff --git a/srslte/examples/CMakeLists.txt b/srslte/examples/CMakeLists.txt index fed7b112a..6173ddc31 100644 --- a/srslte/examples/CMakeLists.txt +++ b/srslte/examples/CMakeLists.txt @@ -38,36 +38,27 @@ target_link_libraries(ll_example srslte) add_executable(synch_file synch_file.c) target_link_libraries(synch_file srslte) -LINK_DIRECTORIES(${UHD_LIBRARY_DIRS}) - - - ################################################################# # These can be compiled without UHD or graphics support ################################################################# -add_executable(pdsch_ue pdsch_ue.c cuhd_utils.c) -target_link_libraries(pdsch_ue srslte) +add_executable(pdsch_ue pdsch_ue.c) +target_link_libraries(pdsch_ue srslte pthread) add_executable(pdsch_enodeb pdsch_enodeb.c) target_link_libraries(pdsch_enodeb srslte pthread) -LIST(FIND OPTIONAL_LIBS cuhd CUHD_FIND) -IF(${CUHD_FIND} EQUAL -1) - SET_TARGET_PROPERTIES(pdsch_ue PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD") - SET_TARGET_PROPERTIES(pdsch_enodeb PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD") -ELSE(${CUHD_FIND} EQUAL -1) - target_link_libraries(pdsch_ue cuhd pthread) - target_link_libraries(pdsch_enodeb cuhd) -ENDIF(${CUHD_FIND} EQUAL -1) +IF(UHD_FOUND) +ELSE(UHD_FOUND) + add_definitions(-DDISABLE_UHD) + add_definitions(-DDISABLE_UHD) +ENDIF(UHD_FOUND) -FIND_PACKAGE(SRSGUI) IF(SRSGUI_FOUND) - include_directories(${SRSGUI_INCLUDE_DIRS}) target_link_libraries(pdsch_ue ${SRSGUI_LIBRARIES}) ELSE(SRSGUI_FOUND) - SET_TARGET_PROPERTIES(pdsch_ue PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS") + add_definitions(-DDISABLE_GRAPHICS) ENDIF(SRSGUI_FOUND) @@ -75,25 +66,29 @@ ENDIF(SRSGUI_FOUND) # These examples need the UHD driver ################################################################# -IF(${CUHD_FIND} GREATER -1) +IF(UHD_FOUND) - add_executable(cell_search cell_search.c cuhd_utils.c) - target_link_libraries(cell_search srslte cuhd ) + add_executable(cell_search cell_search.c) + target_link_libraries(cell_search srslte ) - add_executable(prach_ue prach_ue.c cuhd_utils.c) - target_link_libraries(prach_ue srslte cuhd) + add_executable(prach_ue prach_ue.c) + target_link_libraries(prach_ue srslte ) - add_executable(cell_measurement cell_measurement.c cuhd_utils.c) - target_link_libraries(cell_measurement cuhd srslte) + add_executable(cell_measurement cell_measurement.c) + target_link_libraries(cell_measurement srslte) - add_executable(usrp_capture usrp_capture.c cuhd_utils.c) - target_link_libraries(usrp_capture cuhd srslte) + add_executable(usrp_capture usrp_capture.c) + target_link_libraries(usrp_capture srslte) - add_executable(usrp_capture_sync usrp_capture_sync.c cuhd_utils.c) - target_link_libraries(usrp_capture_sync cuhd srslte) + add_executable(usrp_capture_sync usrp_capture_sync.c) + target_link_libraries(usrp_capture_sync srslte) MESSAGE(STATUS " UHD examples will be installed.") -ELSE(${CUHD_FIND} GREATER -1) - MESSAGE(STATUS " UHD examples NOT INSTALLED: CUHD library not compiled.") -ENDIF(${CUHD_FIND} GREATER -1) +ELSE(UHD_FOUND) + MESSAGE(STATUS " UHD examples NOT INSTALLED.") +ENDIF(UHD_FOUND) + +# Add subdirectories +add_subdirectory(tutorial_examples) + diff --git a/srslte/examples/cell_measurement.c b/srslte/examples/cell_measurement.c index 68a38f8e4..e96f12da3 100644 --- a/srslte/examples/cell_measurement.c +++ b/srslte/examples/cell_measurement.c @@ -38,7 +38,7 @@ #include "srslte/srslte.h" #include "srslte/cuhd/cuhd.h" -#include "cuhd_utils.h" +#include "srslte/cuhd/cuhd_utils.h" #define B210_DEFAULT_GAIN 40.0 #define B210_DEFAULT_GAIN_CORREC 110.0 // Gain of the Rx chain when the gain is set to 40 diff --git a/srslte/examples/cell_search.c b/srslte/examples/cell_search.c index c1c41385f..e42a0e511 100644 --- a/srslte/examples/cell_search.c +++ b/srslte/examples/cell_search.c @@ -37,7 +37,7 @@ #include "srslte/srslte.h" -#include "cuhd_utils.h" +#include "srslte/cuhd/cuhd_utils.h" #ifndef DISABLE_UHD diff --git a/srslte/examples/pdsch_enodeb.c b/srslte/examples/pdsch_enodeb.c index 92658284c..0c3d82b8a 100644 --- a/srslte/examples/pdsch_enodeb.c +++ b/srslte/examples/pdsch_enodeb.c @@ -39,6 +39,8 @@ #ifndef DISABLE_UHD #include "srslte/cuhd/cuhd.h" void *uhd; +#else +#warning Compiling pdsch_ue with no UHD support #endif char *output_file_name = NULL; diff --git a/srslte/examples/pdsch_ue.c b/srslte/examples/pdsch_ue.c index 4205afc89..d0dc73077 100644 --- a/srslte/examples/pdsch_ue.c +++ b/srslte/examples/pdsch_ue.c @@ -43,14 +43,15 @@ #ifndef DISABLE_UHD #include "srslte/cuhd/cuhd.h" -#include "cuhd_utils.h" +#include "srslte/cuhd/cuhd_utils.h" cell_search_cfg_t cell_detect_config = { 5000, 200, // nof_frames_total 10.0 // threshold }; - +#else +#warning Compiling pdsch_ue with no UHD support #endif //#define STDOUT_COMPACT @@ -374,11 +375,13 @@ int main(int argc, char **argv) { float rsrp=0.0, rsrq=0.0, snr=0.0; bool decode_pdsch; int pdcch_tx=0; - + +#ifndef DISABLE_UHD if (prog_args.uhd_gain < 0) { srslte_ue_sync_start_agc(&ue_sync, cuhd_set_rx_gain_th, cell_detect_config.init_agc); } - +#endif + INFO("\nEntering main loop...\n\n", 0); /* Main loop */ while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) { diff --git a/srslte/examples/prach_ue.c b/srslte/examples/prach_ue.c index 0114fe6d5..5fffb9d52 100644 --- a/srslte/examples/prach_ue.c +++ b/srslte/examples/prach_ue.c @@ -42,7 +42,7 @@ #include "srslte/cuhd/cuhd.h" -#include "cuhd_utils.h" +#include "srslte/cuhd/cuhd_utils.h" cell_search_cfg_t cell_detect_config = { 5000, diff --git a/srslte/tutorial_examples/CMakeLists.txt b/srslte/examples/tutorial_examples/CMakeLists.txt similarity index 71% rename from srslte/tutorial_examples/CMakeLists.txt rename to srslte/examples/tutorial_examples/CMakeLists.txt index b16301069..501db7792 100644 --- a/srslte/tutorial_examples/CMakeLists.txt +++ b/srslte/examples/tutorial_examples/CMakeLists.txt @@ -24,19 +24,16 @@ # EXAMPLES shown in WinnForum 2015 Tutorial ################################################################# +IF(SRSGUI_FOUND AND UHD_FOUND) -FIND_PACKAGE(SRSGUI) + add_executable(pss pss.c) + target_link_libraries(pss srslte ${SRSGUI_LIBRARIES}) -IF(SRSGUI_FOUND) - include_directories(${SRSGUI_INCLUDE_DIRS}) + add_executable(ue_rx ue_rx.c) + target_link_libraries(ue_rx srslte ${SRSGUI_LIBRARIES} pthread) - add_executable(pss pss.c) - target_link_libraries(pss srslte cuhd ${SRSGUI_LIBRARIES}) + add_executable(simple_tx simple_tx.c) + target_link_libraries(simple_tx srslte) - include_directories("../examples") - add_executable(ue_rx ue_rx.c ../examples/cuhd_utils.c) - target_link_libraries(ue_rx srslte cuhd ${SRSGUI_LIBRARIES} pthread) -ENDIF(SRSGUI_FOUND) +ENDIF(SRSGUI_FOUND AND UHD_FOUND) -add_executable(simple_tx simple_tx.c) -target_link_libraries(simple_tx srslte cuhd) diff --git a/srslte/tutorial_examples/pss.c b/srslte/examples/tutorial_examples/pss.c similarity index 100% rename from srslte/tutorial_examples/pss.c rename to srslte/examples/tutorial_examples/pss.c diff --git a/srslte/tutorial_examples/simple_tx.c b/srslte/examples/tutorial_examples/simple_tx.c similarity index 100% rename from srslte/tutorial_examples/simple_tx.c rename to srslte/examples/tutorial_examples/simple_tx.c diff --git a/srslte/tutorial_examples/ue_rx.c b/srslte/examples/tutorial_examples/ue_rx.c similarity index 100% rename from srslte/tutorial_examples/ue_rx.c rename to srslte/examples/tutorial_examples/ue_rx.c diff --git a/common/include/srslte/config.h b/srslte/include/srslte/config.h similarity index 100% rename from common/include/srslte/config.h rename to srslte/include/srslte/config.h diff --git a/cuhd/include/srslte/cuhd/cuhd.h b/srslte/include/srslte/cuhd/cuhd.h similarity index 99% rename from cuhd/include/srslte/cuhd/cuhd.h rename to srslte/include/srslte/cuhd/cuhd.h index d445956be..36088cd05 100644 --- a/cuhd/include/srslte/cuhd/cuhd.h +++ b/srslte/include/srslte/cuhd/cuhd.h @@ -34,7 +34,6 @@ extern "C" { #include #include "srslte/config.h" -#include "srslte/cuhd/cuhd_utils.h" SRSLTE_API int cuhd_open(char *args, void **handler); diff --git a/srslte/examples/cuhd_utils.h b/srslte/include/srslte/cuhd/cuhd_utils.h similarity index 58% rename from srslte/examples/cuhd_utils.h rename to srslte/include/srslte/cuhd/cuhd_utils.h index a1f4e4679..d1d75353a 100644 --- a/srslte/examples/cuhd_utils.h +++ b/srslte/include/srslte/cuhd/cuhd_utils.h @@ -33,20 +33,27 @@ typedef struct SRSLTE_API { uint32_t max_frames_pss; // maximum number of 5ms frames to capture for PSS correlation float threshold; // early-stops cell detection if mean PSR is above this value float init_agc; // 0 or negative to disable AGC -}cell_search_cfg_t; - -int cuhd_mib_decoder(void *uhd, - cell_search_cfg_t *config, - srslte_cell_t *cell); - -int cuhd_cell_search(void *uhd, - cell_search_cfg_t *config, - int force_N_id_2, - srslte_cell_t *cell); - -int cuhd_search_and_decode_mib(void *uhd, - cell_search_cfg_t *config, - int force_N_id_2, - srslte_cell_t *cell); +} cell_search_cfg_t; + +SRSLTE_API int cuhd_rssi_scan(void *uhd, + float *freqs, + float *rssi, + int nof_bands, + double fs, + int nsamp); + +SRSLTE_API int cuhd_mib_decoder(void *uhd, + cell_search_cfg_t *config, + srslte_cell_t *cell); + +SRSLTE_API int cuhd_cell_search(void *uhd, + cell_search_cfg_t *config, + int force_N_id_2, + srslte_cell_t *cell); + +SRSLTE_API int cuhd_search_and_decode_mib(void *uhd, + cell_search_cfg_t *config, + int force_N_id_2, + srslte_cell_t *cell); diff --git a/srslte/lib/CMakeLists.txt b/srslte/lib/CMakeLists.txt index 31b5da677..aae96a50f 100644 --- a/srslte/lib/CMakeLists.txt +++ b/srslte/lib/CMakeLists.txt @@ -25,8 +25,9 @@ ######################################################################## include(CheckFunctionExistsMath) +FIND_PACKAGE(SRSGUI) +FIND_PACKAGE(UHD) FIND_PACKAGE(FFTW3F REQUIRED) # TODO: distribute kissfft instead -INCLUDE_DIRECTORIES(${FFTW3F_INCLUDE_DIRS}) IF(${DISABLE_VOLK}) IF(${DISABLE_VOLK} EQUAL 0) @@ -38,7 +39,21 @@ ELSE(${DISABLE_VOLK}) FIND_PACKAGE(Volk) ENDIF(${DISABLE_VOLK}) -FIND_PACKAGE(SRSGUI) +IF(FFTW3F_FOUND) + INCLUDE_DIRECTORIES(${FFTW3F_INCLUDE_DIRS}) + LINK_DIRECTORIES(${FFTW3F_LIBRARY_DIRS}) +ENDIF(FFTW3F_FOUND) + +IF(UHD_FOUND) + INCLUDE_DIRECTORIES(${UHD_INCLUDE_DIRS}) + LINK_DIRECTORIES(${UHD_LIBRARY_DIRS}) +ENDIF(UHD_FOUND) + +IF(SRSGUI_FOUND) + INCLUDE_DIRECTORIES(${SRSGUI_INCLUDE_DIRS}) + LINK_DIRECTORIES(${SRSGUI_LIBRARY_DIRS}) +ENDIF(SRSGUI_FOUND) + ######################################################################## # Recurse subdirectories and compile all source files into the same lib @@ -47,13 +62,22 @@ FILE(GLOB modules *) SET(SOURCES_ALL "") FOREACH (_module ${modules}) IF(IS_DIRECTORY ${_module}) - FILE(GLOB_RECURSE tmp "${_module}/src/*.c") - LIST(APPEND SOURCES_ALL ${tmp}) + IF ((NOT ${_module} MATCHES "cuhd") OR UHD_FOUND) + FILE(GLOB_RECURSE tmp "${_module}/src/*.c") + LIST(APPEND SOURCES_ALL ${tmp}) + FILE(GLOB_RECURSE tmp2 "${_module}/src/*.cpp") + LIST(APPEND SOURCES_ALL ${tmp2}) + ENDIF ((NOT ${_module} MATCHES "cuhd") OR UHD_FOUND) ENDIF(IS_DIRECTORY ${_module}) ENDFOREACH() ADD_LIBRARY(srslte SHARED ${SOURCES_ALL}) + TARGET_LINK_LIBRARIES(srslte m ${FFTW3F_LIBRARIES}) +IF(UHD_FOUND) + TARGET_LINK_LIBRARIES(srslte ${UHD_LIBRARIES}) +ENDIF(UHD_FOUND) + INSTALL(TARGETS srslte DESTINATION ${LIBRARY_DIR}) LIBLTE_SET_PIC(srslte) @@ -77,20 +101,3 @@ FOREACH (_file ${cmakefiles}) ENDIF () ENDFOREACH() -######################################################################## -# Create C++ library -######################################################################## -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++) - diff --git a/cuhd/lib/cuhd_handler.hpp b/srslte/lib/cuhd/src/cuhd_handler.hpp similarity index 100% rename from cuhd/lib/cuhd_handler.hpp rename to srslte/lib/cuhd/src/cuhd_handler.hpp diff --git a/cuhd/lib/cuhd_imp.cpp b/srslte/lib/cuhd/src/cuhd_imp.cpp similarity index 100% rename from cuhd/lib/cuhd_imp.cpp rename to srslte/lib/cuhd/src/cuhd_imp.cpp diff --git a/srslte/examples/cuhd_utils.c b/srslte/lib/cuhd/src/cuhd_utils.c similarity index 85% rename from srslte/examples/cuhd_utils.c rename to srslte/lib/cuhd/src/cuhd_utils.c index 62233137d..e0a9ca2c2 100644 --- a/srslte/examples/cuhd_utils.c +++ b/srslte/lib/cuhd/src/cuhd_utils.c @@ -36,11 +36,53 @@ #include #include "srslte/srslte.h" -#include "cuhd_utils.h" - -#ifndef DISABLE_UHD #include "srslte/cuhd/cuhd.h" +#include "srslte/cuhd/cuhd_utils.h" + +int cuhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double fs, int nsamp) { + int i, j; + int ret = -1; + _Complex float *buffer; + double f; + + buffer = calloc(nsamp, sizeof(_Complex float)); + if (!buffer) { + goto free_and_exit; + } + + cuhd_set_rx_gain(uhd, 20.0); + cuhd_set_rx_srate(uhd, fs); + + for (i=0;i