Changed directory structure. Compilation working with w/o UHD and srsGUI

master
ismagom 10 years ago
parent c57d8969be
commit 132c919dcf

@ -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)

@ -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)

@ -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);

@ -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 <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#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<nof_bands;i++) {
cuhd_stop_rx_stream(uhd);
f = (double) freqs[i];
cuhd_set_rx_freq(uhd, f);
cuhd_rx_wait_lo_locked(uhd);
usleep(10000);
cuhd_start_rx_stream(uhd);
/* discard first samples */
for (j=0;j<2;j++) {
if (cuhd_recv(uhd, buffer, nsamp, 1) != nsamp) {
goto free_and_exit;
}
}
rssi[i] = srslte_vec_avg_power_cf(buffer, nsamp);
printf("[%3d]: Freq %4.1f Mhz - RSSI: %3.2f dBm\r", i, f/1000000, 10*log10f(rssi[i]) + 30); fflush(stdout);
if (SRSLTE_VERBOSE_ISINFO()) {
printf("\n");
}
}
cuhd_stop_rx_stream(uhd);
ret = 0;
free_and_exit:
free(buffer);
return ret;
}

@ -19,24 +19,10 @@
# and at http://www.gnu.org/licenses/.
#
########################################################################
# Install headers
########################################################################
INSTALL(DIRECTORY include/ DESTINATION "${INCLUDE_DIR}"
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
INCLUDE_DIRECTORIES(radio/include/)
INCLUDE_DIRECTORIES(common/include/)
########################################################################
# 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_common_headers SOURCES ${HEADERS_ALL})
add_subdirectory(radio)
add_subdirectory(ue)
add_subdirectory(common)

@ -0,0 +1,28 @@
#
# 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_common SHARED ${SOURCES})
INSTALL(TARGETS srsapps_common DESTINATION ${LIBRARY_DIR})
LIBLTE_SET_PIC(srsapps_common)
FILE(GLOB SOURCES "include/srsapps/common/*.h")
ADD_CUSTOM_TARGET (add_srsapps_common_headers SOURCES ${HEADERS_ALL})

@ -0,0 +1,45 @@
#include <pthread.h>
#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

@ -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 <stdint.h>
#include <string>
#include <stdarg.h>
#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

@ -26,7 +26,7 @@
*/
#include <stdlib.h>
#include "srslte/srslte.h"
#include "srslte/config.h"
#ifndef PARAMS_H
#define PARAMS_H

@ -0,0 +1,66 @@
#include <stdint.h>
#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

@ -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:

@ -0,0 +1,102 @@
#include <stdint.h>
#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;i<nof_timers;i++) {
timer_list[i].id = i;
}
}
~timers() {
delete timer_list;
}
void step_all() {
for (int i=0;i<nof_timers;i++) {
get(i)->step();
}
}
void stop_all() {
for (int i=0;i<nof_timers;i++) {
get(i)->stop();
}
}
void run_all() {
for (int i=0;i<nof_timers;i++) {
get(i)->run();
}
}
void reset_all() {
for (int i=0;i<nof_timers;i++) {
get(i)->reset();
}
}
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

@ -26,7 +26,7 @@
*/
#include <stdint.h>
#include "srslte/srslte.h"
#include "srslte/config.h"
#ifndef TTISYNC_H
#define TTISYNC_H

@ -26,8 +26,8 @@
*/
#include <pthread.h>
#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

@ -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 <stdint.h>
#include <string>
#include <stdarg.h>
#include <stdio.h>
#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);
}
}

@ -0,0 +1,185 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#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;i++) {
packets[i].valid = false;
packets[i].ptr = &buffer[i*max_msg_size];
packets[i].len = 0;
}
}
bool qbuff::isempty()
{
return !packets[rp].valid;
}
bool qbuff::isfull()
{
return packets[wp].valid;
}
void* qbuff::request()
{
if (!isfull()) {
return packets[wp].ptr;
} else {
return NULL;
}
}
bool qbuff::push(uint32_t len)
{
packets[wp].len = len;
packets[wp].valid = true;
wp += (wp+1 >= 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<idx && packets[rpp].valid) {
rpp += (rpp+1 >= 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;i<nof_messages;i++) {
total_len += packets[i].len;
}
return total_len;
}
// Move packets between queues with only 1 memcpy
void qbuff::move_to(qbuff *dst) {
uint32_t len;
void *ptr_src = pop(&len);
if (ptr_src) {
void *ptr_dst = dst->request();
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;
}
}
}

@ -27,7 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "srslte/ue_itf/queue.h"
#include "srsapps/common/queue.h"
namespace srslte {
namespace ue {

@ -27,7 +27,7 @@
#include <pthread.h>
#include "srslte/ue_itf/tti_sync_cv.h"
#include "srsapps/common/tti_sync_cv.h"
namespace srslte {
namespace ue {

@ -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})

@ -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;
}

@ -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)

@ -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})

@ -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

@ -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

@ -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

@ -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

@ -0,0 +1,84 @@
#include <string.h>
#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<MAC_NOF_QUEUES;i++) {
queues[i].init(DEFAULT_NOF_MESSAGES, DEFAULT_MSG_SZ);
}
}
private:
qbuff queues[MAC_NOF_QUEUES];
};
}
}
#endif

@ -0,0 +1,67 @@
#include "srslte/srslte.h"
#include "srsapps/common/params_db.h"
#ifndef MACPARAMS_H
#define MACPARAMS_H
namespace srslte {
namespace ue {
class mac_params : public params_db
{
public:
mac_params() : params_db(NOF_PARAMS) {}
~mac_params() {}
typedef enum {
// These 4 parameters must be together!!
RNTI_C = 0,
RNTI_SPS,
RNTI_TEMP,
RNTI_RA,
SPS_DL_SCHED_INTERVAL,
SPS_DL_NOF_PROC,
BCCH_SI_WINDOW_ST,
BCCH_SI_WINDOW_LEN,
PCCH_RECEIVE,
CONTENTION_ID, // Transmitted UE Contention ID
TIMER_TIMEALIGN,
// Random Access parameters. See 5.1.1
RA_CONFIGINDEX,
RA_PREAMBLEINDEX,
RA_MASKINDEX,
RA_NOFPREAMBLES,
RA_NOFGROUPAPREAMBLES,
RA_MESSAGEPOWEROFFSETB,
RA_MESSAGESIZEA,
RA_PCMAX,
RA_DELTAPREAMBLEMSG3,
RA_RESPONSEWINDOW,
RA_POWERRAMPINGSTEP,
RA_PREAMBLETRANSMAX,
RA_INITRECEIVEDPOWER,
RA_CONTENTIONTIMER,
RA_MAXTXMSG3,
PDSCH_RSPOWER,
PDSCH_PB,
NOF_PARAMS,
} mac_param_t;
};
}
}
#endif

@ -0,0 +1,137 @@
#include <stdint.h>
#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

@ -0,0 +1,71 @@
#include <pthread.h>
#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

@ -0,0 +1,34 @@
#include <stdint.h>
#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

@ -0,0 +1,30 @@
#include <stdint.h>
#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

@ -0,0 +1,29 @@
#include <stdint.h>
#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

@ -0,0 +1,133 @@
#include <stdint.h>
#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

@ -0,0 +1,30 @@
#include <stdint.h>
#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

@ -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

@ -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

@ -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;
}
}
}

@ -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<NOF_HARQ_PROC+1;i++) {
proc[i].pid = i;
}
pending_ack_pid = -1;
}
dl_harq_entity::~dl_harq_entity()
{
delete proc;
}
bool dl_harq_entity::init(srslte_cell_t cell, uint32_t max_payload_len, log* log_h_, timers* timers_, demux *demux_unit_)
{
timers_db = timers_;
demux_unit = demux_unit_;
log_h = log_h_;
for (uint32_t i=0;i<NOF_HARQ_PROC+1;i++) {
if (!proc[i].init(cell, max_payload_len, this)) {
return false;
}
}
return true;
}
bool dl_harq_entity::is_sps(uint32_t pid)
{
return false;
}
void dl_harq_entity::set_harq_info(uint32_t tti, uint32_t pid, dl_sched_grant* grant)
{
proc[pid%(NOF_HARQ_PROC+1)].set_harq_info(tti, grant);
}
void dl_harq_entity::receive_data(uint32_t tti, uint32_t pid, dl_buffer* dl_buffer, phy* phy_h)
{
proc[pid%(NOF_HARQ_PROC+1)].receive_data(tti, dl_buffer, phy_h);
}
void dl_harq_entity::reset()
{
for (uint32_t i=0;i<NOF_HARQ_PROC+1;i++) {
proc[i].reset();
}
}
bool dl_harq_entity::is_ack_pending_resolution()
{
return pending_ack_pid >= 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;
}
}
}
}

@ -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()
{
}
}
}

@ -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 <string.h>
#include <strings.h>
#include <pthread.h>
#include <unistd.h>
#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(&params_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<srslte::ue::mac*>(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);
}
}
}

@ -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

@ -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<mac_io::NOF_UL_LCH;i++) {
priority[i] = 1;
priority_sorted[i] = 1;
PBR[i] = -1; // -1 is infinite
BSD[i] = 10;
lchid_sorted[i] = i;
}
}
void mux::init(log *log_h_, mac_io *mac_io_h_)
{
log_h = log_h_;
mac_io_h = mac_io_h_;
}
void mux::reset()
{
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
Bj[i] = 0;
}
}
void mux::set_priority(uint32_t lch_id, uint32_t set_priority, int set_PBR, uint32_t set_BSD)
{
pthread_mutex_lock(&mutex);
if (lch_id < mac_io::NOF_UL_LCH) {
priority[lch_id] = set_priority;
PBR[lch_id] = set_PBR;
BSD[lch_id] = set_BSD;
// Insert priority in sorted idx array
int new_index = 0;
while(set_priority > 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<mac_io::NOF_UL_LCH;i++) {
bool res = true;
while ((Bj[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<mac_io::NOF_UL_LCH;i++) {
while (allocate_sdu(lchid_sorted[i], &pdu_msg));
}
// MAC control element for BSR included for padding.
// TODO
pthread_mutex_unlock(&mutex);
/* Release SDUs */
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
while(nof_tx_pkts[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();
}
}
}

@ -0,0 +1,442 @@
#include <stdlib.h>
#include <stdint.h>
#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;
}
}
}
}

@ -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;i<NOF_HARQ_PROC;i++) {
if (!proc[i].init(cell, max_payload_len, this)) {
return false;
}
}
return true;
}
void ul_harq_entity::set_maxHARQ_Tx(uint32_t maxHARQ_Tx, uint32_t maxHARQ_Msg3Tx) {
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
proc[i].set_maxHARQ_Tx(maxHARQ_Tx, maxHARQ_Msg3Tx);
}
}
uint32_t ul_harq_entity::pidof(uint32_t tti) {
return tti%NOF_HARQ_PROC;
}
void ul_harq_entity::reset() {
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
proc[i].reset();
}
}
void ul_harq_entity::reset_ndi() {
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
proc[i].reset_ndi();
}
}
bool ul_harq_entity::is_sps(uint32_t pid) {
return false;
}
void ul_harq_entity::run_tti(uint32_t tti, phy *phy_) {
run_tti(tti, NULL, phy_);
}
// Implements Section 5.4.2.1
void ul_harq_entity::run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_h)
{
uint32_t pid = pidof(tti);
last_retx_is_msg3 = false;
if (grant) {
if ((grant->is_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;i<NOF_HARQ_PROC;i++) {
if (proc[pid].has_grant()) {
proc[pid].set_harq_feedback(phy_h->get_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();
}
}
}
}
}

@ -0,0 +1,283 @@
#include <unistd.h>
#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);
}
}

@ -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)

@ -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

@ -27,7 +27,7 @@
#include <string.h>
#include "srslte/srslte.h"
#include "srslte/ue_itf/sched_grant.h"
#include "srsapps/ue/phy/sched_grant.h"
#ifndef UEDLSCHEDGRANT_H
#define UEDLSCHEDGRANT_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

@ -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

@ -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

@ -26,7 +26,7 @@
*/
#include "srslte/srslte.h"
#include "queue.h"
#include "srsapps/common/queue.h"
#ifndef UESCHEDGRANT_H
#define UESCHEDGRANT_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

@ -27,7 +27,7 @@
#include <string.h>
#include "srslte/srslte.h"
#include "srslte/ue_itf/sched_grant.h"
#include "srsapps/ue/phy/sched_grant.h"
#ifndef UEULSCHEDGRANT_H
#define UEULSCHEDGRANT_H

@ -30,10 +30,10 @@
#include <pthread.h>
#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 {

@ -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 {

@ -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 {

@ -30,10 +30,10 @@
#include <pthread.h>
#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 {

@ -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)

@ -28,9 +28,9 @@
#include <unistd.h>
#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

@ -28,9 +28,9 @@
#include <unistd.h>
#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"
/**********************************************************************

@ -46,4 +46,3 @@ ADD_CUSTOM_TARGET (add_srslte_headers SOURCES ${HEADERS_ALL})
########################################################################
ADD_SUBDIRECTORY(lib)
ADD_SUBDIRECTORY(examples)
#add_subdirectory(tutorial_examples)

@ -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)

@ -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

@ -37,7 +37,7 @@
#include "srslte/srslte.h"
#include "cuhd_utils.h"
#include "srslte/cuhd/cuhd_utils.h"
#ifndef DISABLE_UHD

@ -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;

@ -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
@ -375,9 +376,11 @@ int main(int argc, char **argv) {
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 */

@ -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,

@ -24,19 +24,16 @@
# EXAMPLES shown in WinnForum 2015 Tutorial
#################################################################
FIND_PACKAGE(SRSGUI)
IF(SRSGUI_FOUND)
include_directories(${SRSGUI_INCLUDE_DIRS})
IF(SRSGUI_FOUND AND UHD_FOUND)
add_executable(pss pss.c)
target_link_libraries(pss srslte cuhd ${SRSGUI_LIBRARIES})
target_link_libraries(pss srslte ${SRSGUI_LIBRARIES})
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)
add_executable(ue_rx ue_rx.c)
target_link_libraries(ue_rx srslte ${SRSGUI_LIBRARIES} pthread)
add_executable(simple_tx simple_tx.c)
target_link_libraries(simple_tx srslte cuhd)
target_link_libraries(simple_tx srslte)
ENDIF(SRSGUI_FOUND AND UHD_FOUND)

@ -34,7 +34,6 @@ extern "C" {
#include <stdint.h>
#include "srslte/config.h"
#include "srslte/cuhd/cuhd_utils.h"
SRSLTE_API int cuhd_open(char *args,
void **handler);

@ -35,16 +35,23 @@ typedef struct SRSLTE_API {
float init_agc; // 0 or negative to disable AGC
} cell_search_cfg_t;
int cuhd_mib_decoder(void *uhd,
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);
int cuhd_cell_search(void *uhd,
SRSLTE_API 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,
SRSLTE_API int cuhd_search_and_decode_mib(void *uhd,
cell_search_cfg_t *config,
int force_N_id_2,
srslte_cell_t *cell);

@ -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})
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++)

@ -36,11 +36,53 @@
#include <unistd.h>
#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<nof_bands;i++) {
cuhd_stop_rx_stream(uhd);
f = (double) freqs[i];
cuhd_set_rx_freq(uhd, f);
cuhd_rx_wait_lo_locked(uhd);
usleep(10000);
cuhd_start_rx_stream(uhd);
/* discard first samples */
for (j=0;j<2;j++) {
if (cuhd_recv(uhd, buffer, nsamp, 1) != nsamp) {
goto free_and_exit;
}
}
rssi[i] = srslte_vec_avg_power_cf(buffer, nsamp);
printf("[%3d]: Freq %4.1f Mhz - RSSI: %3.2f dBm\r", i, f/1000000, 10*log10f(rssi[i]) + 30); fflush(stdout);
if (SRSLTE_VERBOSE_ISINFO()) {
printf("\n");
}
}
cuhd_stop_rx_stream(uhd);
ret = 0;
free_and_exit:
free(buffer);
return ret;
}
int cuhd_recv_wrapper_cs(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
@ -195,5 +237,3 @@ int cuhd_search_and_decode_mib(void *uhd, cell_search_cfg_t *config, int force_N
return ret;
}
#endif

@ -109,7 +109,7 @@ int main(int argc, char **argv) {
exit(-1);
}
w_buff_f = malloc(sizeof(float) * nof_rx_bits * 10);
if (!w_buff_c) {
if (!w_buff_f) {
perror("malloc");
exit(-1);
}
@ -128,6 +128,9 @@ int main(int argc, char **argv) {
bits[3*i+1] = SRSLTE_TX_NULL;
}
bzero(w_buff_c, nof_tx_bits * 10 * sizeof(uint8_t));
bzero(w_buff_f, nof_rx_bits * 10 * sizeof(float));
printf("BITS: ");
srslte_vec_fprint_b(stdout, bits, nof_tx_bits);

@ -23,32 +23,24 @@
# PROGRAM TO DEBUG PSS FROM USRP
########################################################################
LIST(FIND OPTIONAL_LIBS cuhd CUHD_FIND)
FIND_PACKAGE(SRSGUI)
ADD_EXECUTABLE(pss_file pss_file.c)
TARGET_LINK_LIBRARIES(pss_file srslte)
IF(SRSGUI_FOUND)
include_directories(${SRSGUI_INCLUDE_DIRS})
target_link_libraries(pss_file ${SRSGUI_LIBRARIES})
ELSE(SRSGUI_FOUND)
SET_TARGET_PROPERTIES(pss_file PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
ENDIF(SRSGUI_FOUND)
IF(${CUHD_FIND} GREATER -1)
IF(UHD_FOUND)
ADD_EXECUTABLE(pss_usrp pss_usrp.c)
TARGET_LINK_LIBRARIES(pss_usrp srslte cuhd)
TARGET_LINK_LIBRARIES(pss_usrp srslte)
IF(SRSGUI_FOUND)
include_directories(${SRSGUI_INCLUDE_DIRS})
target_link_libraries(pss_usrp ${SRSGUI_LIBRARIES})
ELSE(SRSGUI_FOUND)
SET_TARGET_PROPERTIES(pss_usrp PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
ENDIF(SRSGUI_FOUND)
ENDIF(${CUHD_FIND} GREATER -1)
ENDIF(UHD_FOUND)
BuildMex(MEXNAME pss SOURCES pss_mex.c LIBRARIES srslte srslte_mex)
BuildMex(MEXNAME sss SOURCES sss_mex.c LIBRARIES srslte srslte_mex)

Loading…
Cancel
Save