|
|
|
/**
|
|
|
|
*
|
|
|
|
* \section COPYRIGHT
|
|
|
|
*
|
|
|
|
* Copyright 2013-2020 Software Radio Systems Limited
|
|
|
|
*
|
|
|
|
* By using this file, you agree to the terms and conditions set
|
|
|
|
* forth in the LICENSE file which can be found at the top level of
|
|
|
|
* the distribution.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef SRSLTE_COMMON_H
|
|
|
|
#define SRSLTE_COMMON_H
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
INCLUDES
|
|
|
|
*******************************************************************************/
|
|
|
|
|
|
|
|
#include "srslte/adt/span.h"
|
|
|
|
#include <chrono>
|
|
|
|
#include <memory>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
DEFINES
|
|
|
|
*******************************************************************************/
|
|
|
|
|
|
|
|
#define SRSLTE_UE_CATEGORY 4
|
|
|
|
|
|
|
|
#define SRSLTE_N_SRB 3
|
|
|
|
#define SRSLTE_N_DRB 8
|
|
|
|
#define SRSLTE_N_RADIO_BEARERS 11
|
|
|
|
|
|
|
|
#define SRSLTE_N_MCH_LCIDS 32
|
|
|
|
|
|
|
|
#define FDD_HARQ_DELAY_DL_MS 4
|
|
|
|
#define FDD_HARQ_DELAY_UL_MS 4
|
|
|
|
#define MSG3_DELAY_MS 2 // Delay added to FDD_HARQ_DELAY_DL_MS
|
|
|
|
|
|
|
|
#define TTI_SUB(a, b) ((((a) + 10240) - (b)) % 10240)
|
|
|
|
#define TTI_ADD(a, b) (((a) + (b)) % 10240)
|
|
|
|
|
|
|
|
#define TTI_TX(tti) TTI_ADD(tti, FDD_HARQ_DELAY_DL_MS)
|
|
|
|
|
|
|
|
#define TTI_RX(tti) (TTI_SUB(tti, FDD_HARQ_DELAY_UL_MS))
|
|
|
|
#define TTI_RX_ACK(tti) (TTI_ADD(tti, FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS))
|
|
|
|
|
|
|
|
#define TTIMOD_SZ 20
|
|
|
|
#define TTIMOD(tti) (tti % TTIMOD_SZ)
|
|
|
|
|
|
|
|
#define INVALID_TTI 10241
|
|
|
|
#define TX_ENB_DELAY FDD_HARQ_DELAY_UL_MS
|
|
|
|
|
|
|
|
#define PHICH_MAX_SF 6 // Maximum PHICH in a subframe (1 in FDD, > 1 in TDD, see table 9.1.2-1 36.213)
|
|
|
|
|
|
|
|
#define ASYNC_DL_SCHED (FDD_HARQ_DELAY_UL_MS <= 4)
|
|
|
|
|
|
|
|
// Cat 4 UE - Max number of DL-SCH transport block bits received within a TTI
|
|
|
|
// 3GPP 36.306 v15.4.0 Table 4.1.1 for Category 11 with 2 layers and 256QAM
|
|
|
|
#define SRSLTE_MAX_TBSIZE_BITS 97896
|
|
|
|
#define SRSLTE_BUFFER_HEADER_OFFSET 1020
|
|
|
|
#define SRSLTE_MAX_BUFFER_SIZE_BITS (SRSLTE_MAX_TBSIZE_BITS + SRSLTE_BUFFER_HEADER_OFFSET)
|
|
|
|
#define SRSLTE_MAX_BUFFER_SIZE_BYTES (SRSLTE_MAX_TBSIZE_BITS / 8 + SRSLTE_BUFFER_HEADER_OFFSET)
|
|
|
|
|
|
|
|
//#define SRSLTE_BUFFER_POOL_LOG_ENABLED
|
|
|
|
|
|
|
|
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
|
|
|
|
#define pool_allocate (srslte::allocate_unique_buffer(*pool, __PRETTY_FUNCTION__))
|
|
|
|
#define pool_allocate_blocking (srslte::allocate_unique_buffer(*pool, __PRETTY_FUNCTION__, true))
|
|
|
|
#define SRSLTE_BUFFER_POOL_LOG_NAME_LEN 128
|
|
|
|
#else
|
|
|
|
#define pool_allocate (srslte::allocate_unique_buffer(*pool))
|
|
|
|
#define pool_allocate_blocking (srslte::allocate_unique_buffer(*pool, true))
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "srslte/srslte.h"
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
TYPEDEFS
|
|
|
|
*******************************************************************************/
|
|
|
|
|
|
|
|
namespace srslte {
|
|
|
|
|
|
|
|
#define ENABLE_TIMESTAMP
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* Byte and Bit buffers
|
|
|
|
*
|
|
|
|
* Generic buffers with headroom to accommodate packet headers and custom
|
|
|
|
* copy constructors & assignment operators for quick copying. Byte buffer
|
|
|
|
* holds a next pointer to support linked lists.
|
|
|
|
*****************************************************************************/
|
|
|
|
class byte_buffer_t
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
uint32_t N_bytes;
|
|
|
|
uint8_t buffer[SRSLTE_MAX_BUFFER_SIZE_BYTES];
|
|
|
|
uint8_t* msg;
|
|
|
|
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
|
|
|
|
char debug_name[SRSLTE_BUFFER_POOL_LOG_NAME_LEN];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
byte_buffer_t() : N_bytes(0)
|
|
|
|
{
|
|
|
|
bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES);
|
|
|
|
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
|
|
|
|
next = NULL;
|
|
|
|
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
|
|
|
|
bzero(debug_name, SRSLTE_BUFFER_POOL_LOG_NAME_LEN);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
byte_buffer_t(const byte_buffer_t& buf)
|
|
|
|
{
|
|
|
|
bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES);
|
|
|
|
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
|
|
|
|
next = NULL;
|
|
|
|
// copy actual contents
|
|
|
|
N_bytes = buf.N_bytes;
|
|
|
|
memcpy(msg, buf.msg, N_bytes);
|
|
|
|
}
|
|
|
|
byte_buffer_t& operator=(const byte_buffer_t& buf)
|
|
|
|
{
|
|
|
|
// avoid self assignment
|
|
|
|
if (&buf == this)
|
|
|
|
return *this;
|
|
|
|
bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES);
|
|
|
|
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
|
|
|
|
next = NULL;
|
|
|
|
N_bytes = buf.N_bytes;
|
|
|
|
memcpy(msg, buf.msg, N_bytes);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
void clear()
|
|
|
|
{
|
|
|
|
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
|
|
|
|
N_bytes = 0;
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
timestamp_is_set = false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
uint32_t get_headroom() { return msg - buffer; }
|
|
|
|
// Returns the remaining space from what is reported to be the length of msg
|
|
|
|
uint32_t get_tailroom() { return (sizeof(buffer) - (msg - buffer) - N_bytes); }
|
|
|
|
std::chrono::microseconds get_latency_us()
|
|
|
|
{
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
if (!timestamp_is_set) {
|
|
|
|
return std::chrono::microseconds{0};
|
|
|
|
}
|
|
|
|
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - tp);
|
|
|
|
#else
|
|
|
|
return std::chrono::microseconds{0};
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
std::chrono::high_resolution_clock::time_point get_timestamp() { return tp; }
|
|
|
|
|
|
|
|
void set_timestamp()
|
|
|
|
{
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
tp = std::chrono::high_resolution_clock::now();
|
|
|
|
timestamp_is_set = true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_timestamp(std::chrono::high_resolution_clock::time_point tp_)
|
|
|
|
{
|
|
|
|
tp = tp_;
|
|
|
|
timestamp_is_set = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void append_bytes(uint8_t* buf, uint32_t size)
|
|
|
|
{
|
|
|
|
memcpy(&msg[N_bytes], buf, size);
|
|
|
|
N_bytes += size;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
std::chrono::high_resolution_clock::time_point tp;
|
|
|
|
bool timestamp_is_set = false;
|
|
|
|
#endif
|
|
|
|
byte_buffer_t* next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct bit_buffer_t {
|
|
|
|
uint32_t N_bits;
|
|
|
|
uint8_t buffer[SRSLTE_MAX_BUFFER_SIZE_BITS];
|
|
|
|
uint8_t* msg;
|
|
|
|
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
|
|
|
|
char debug_name[128];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
bit_buffer_t() : N_bits(0)
|
|
|
|
{
|
|
|
|
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
timestamp_is_set = false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
bit_buffer_t(const bit_buffer_t& buf)
|
|
|
|
{
|
|
|
|
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
|
|
|
|
N_bits = buf.N_bits;
|
|
|
|
memcpy(msg, buf.msg, N_bits);
|
|
|
|
}
|
|
|
|
bit_buffer_t& operator=(const bit_buffer_t& buf)
|
|
|
|
{
|
|
|
|
// avoid self assignment
|
|
|
|
if (&buf == this) {
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
|
|
|
|
N_bits = buf.N_bits;
|
|
|
|
memcpy(msg, buf.msg, N_bits);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
void clear()
|
|
|
|
{
|
|
|
|
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
|
|
|
|
N_bits = 0;
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
timestamp_is_set = false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
uint32_t get_headroom() { return msg - buffer; }
|
|
|
|
long get_latency_us()
|
|
|
|
{
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
if (!timestamp_is_set)
|
|
|
|
return 0;
|
|
|
|
gettimeofday(×tamp[2], NULL);
|
|
|
|
return timestamp[0].tv_usec;
|
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
void set_timestamp()
|
|
|
|
{
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
gettimeofday(×tamp[1], NULL);
|
|
|
|
timestamp_is_set = true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
struct timeval timestamp[3];
|
|
|
|
bool timestamp_is_set;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
// Create a Managed Life-Time Byte Buffer
|
|
|
|
class byte_buffer_pool;
|
|
|
|
class byte_buffer_deleter
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit byte_buffer_deleter(byte_buffer_pool* pool_ = nullptr) : pool(pool_) {}
|
|
|
|
void operator()(byte_buffer_t* buf) const;
|
|
|
|
byte_buffer_pool* pool;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::unique_ptr<byte_buffer_t, byte_buffer_deleter> unique_byte_buffer_t;
|
|
|
|
|
|
|
|
///
|
|
|
|
/// Utilities to create a span out of a byte_buffer.
|
|
|
|
///
|
|
|
|
|
|
|
|
using byte_span = span<uint8_t>;
|
|
|
|
using const_byte_span = span<const uint8_t>;
|
|
|
|
|
|
|
|
inline byte_span make_span(byte_buffer_t& b)
|
|
|
|
{
|
|
|
|
return byte_span{b.msg, b.N_bytes};
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const_byte_span make_span(const byte_buffer_t& b)
|
|
|
|
{
|
|
|
|
return const_byte_span{b.msg, b.N_bytes};
|
|
|
|
}
|
|
|
|
|
|
|
|
inline byte_span make_span(unique_byte_buffer_t& b)
|
|
|
|
{
|
|
|
|
return byte_span{b->msg, b->N_bytes};
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const_byte_span make_span(const unique_byte_buffer_t& b)
|
|
|
|
{
|
|
|
|
return const_byte_span{b->msg, b->N_bytes};
|
|
|
|
}
|
|
|
|
|
|
|
|
// helper functions
|
|
|
|
inline const char* enum_to_text(const char* const array[], uint32_t nof_types, uint32_t enum_val)
|
|
|
|
{
|
|
|
|
return enum_val >= nof_types ? "" : array[enum_val];
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class ItemType>
|
|
|
|
ItemType enum_to_number(ItemType* array, uint32_t nof_types, uint32_t enum_val)
|
|
|
|
{
|
|
|
|
return enum_val >= nof_types ? -1 : array[enum_val];
|
|
|
|
}
|
|
|
|
|
|
|
|
enum class srslte_rat_t { lte, nr, nulltype };
|
|
|
|
inline std::string to_string(const srslte_rat_t& type)
|
|
|
|
{
|
|
|
|
constexpr static const char* options[] = {"LTE", "NR"};
|
|
|
|
return enum_to_text(options, (uint32_t)srslte_rat_t::nulltype, (uint32_t)type);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace srslte
|
|
|
|
|
|
|
|
#endif // SRSLTE_COMMON_H
|