MAC/PHY compiling

master
ismagom 10 years ago
parent f65aa3be1d
commit 309ebd80e5

@ -53,9 +53,12 @@ public:
uint32_t pid;
uint32_t tti;
bool ndi;
uint32_t tbs;
uint32_t n_bytes;
uint32_t rv;
uint16_t rnti;
bool is_from_rar;
bool is_sps_release;
srslte_rnti_type_t rnti_type;
srslte_phy_grant_t phy_grant;
} mac_grant_t;
@ -65,6 +68,9 @@ public:
uint16_t rnti;
bool generate_ack;
bool default_ack;
// If non-null, called after tb_decoded_ok to determine if ack needs to be sent
bool (*generate_ack_callback)(void*);
void *generate_ack_callback_arg;
uint8_t *payload_ptr;
srslte_softbuffer_rx_t *softbuffer;
srslte_phy_grant_t phy_grant;
@ -97,7 +103,7 @@ public:
virtual void tb_decoded_ok(uint32_t harq_pid) = 0;
/* Indicate successfull decoding of BCH TB through PBCH */
virtual void bch_decoded_ok(uint8_t *payload) = 0;
virtual void bch_decoded_ok(uint8_t *payload, uint32_t len) = 0;
/* Function called every start of a subframe (TTI). Warning, this function is called
* from a high priority thread and should terminate asap
@ -113,7 +119,9 @@ public:
/* RLC configures a logical channel */
virtual void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD) = 0;
virtual uint32_t get_current_tti() = 0;
virtual void reconfiguration() = 0;
virtual void reset() = 0;
};
@ -126,13 +134,17 @@ public:
/* MAC calls RLC to get buffer state for a logical channel. This function should return quickly */
virtual uint32_t get_buffer_state(uint32_t lcid) = 0;
/* MAC calls RLC to get RLC segment of nof_bytes length. Segmentation happens in this function. RLC PDU is stored in payload. */
virtual void read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) = 0;
/* MAC calls RLC to get RLC segment of nof_bytes length. Segmentation happens in this function. RLC PDU is stored in
* payload. */
virtual uint32_t read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) = 0;
/* MAC calls RLC to push an RLC PDU. This function is called from an independent MAC thread. PDU gets placed into the PDCP buffer and higher layer thread gets notified
when the last segment is received
/* MAC calls RLC to push an RLC PDU. This function is called from an independent MAC thread. PDU gets placed into the
* PDCP buffer and higher layer thread gets notified
* when the last segment is received
*/
virtual void write_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) = 0;
virtual void write_pdu_bcch_bch(uint8_t *payload, uint32_t nof_bytes) = 0;
virtual void write_pdu_bcch_dlsch(uint8_t *payload, uint32_t nof_bytes) = 0;
};
@ -145,6 +157,9 @@ public:
SPS_DL_SCHED_INTERVAL,
SPS_DL_NOF_PROC,
RNTI_TEMP,
RNTI_C,
BCCH_SI_WINDOW_ST,
BCCH_SI_WINDOW_LEN,

@ -133,23 +133,12 @@ public:
virtual void sync_start() = 0;
virtual void sync_stop() = 0;
/* Functions to initialize and transmit PRACH in the next opportunity.
* This function returns at the start of the rar reception window, ie the transmission
* TTI + rar_start
*/
typedef struct {
uint32_t preamble_idx;
bool allowed_subframe_enabled;
uint32_t allowed_subframe;
float target_power_dbm;
uint16_t rar_rnti;
uint32_t rar_start;
uint32_t rar_window;
} prach_cfg_t;
virtual void prach_send(prach_cfg_t *cfg) = 0;
virtual void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) = 0;
virtual int prach_tx_tti() = 0;
/* Indicates the transmission of a SR signal in the next opportunity */
virtual void sr_send() = 0;
virtual int sr_last_tx_tti() = 0;
/* Time advance commands */
virtual void set_timeadv_rar(uint32_t ta_cmd) = 0;

@ -0,0 +1,80 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 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 Affero 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 Affero General Public License for more details.
*
* A copy of the GNU Affero 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>
#ifndef TTISYNC_H
#define TTISYNC_H
namespace srslte {
namespace ue {
/* Interface used for PHY-MAC synchronization (producer-consumer model).
* The consumer waits while its counter is lower than the producer counter.
* The PHY is the consumer. The MAC is the producer.
*/
class tti_sync
{
public:
tti_sync(uint32_t modulus_)
{
modulus = modulus_;
increment = 1;
init_counters(0);
}
virtual void increase() = 0;
virtual void resync() = 0;
virtual uint32_t wait() = 0;
virtual void set_producer_cntr(uint32_t) = 0;
uint32_t get_producer_cntr() { return producer_cntr; }
uint32_t get_consumer_cntr() { return consumer_cntr; }
void set_increment(uint32_t increment_) {
increment = increment_;
}
protected:
void increase_producer() { producer_cntr = (producer_cntr + increment)%modulus; }
void increase_consumer() { consumer_cntr = (consumer_cntr + increment)%modulus; }
bool wait_condition() { return producer_cntr == consumer_cntr; }
void init_counters(uint32_t val)
{
consumer_cntr = val;
producer_cntr = val;
}
uint32_t increment;
uint32_t modulus;
uint32_t producer_cntr;
uint32_t consumer_cntr;
};
}
}
#endif

@ -25,24 +25,37 @@
*
*/
#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)
{
#include <pthread.h>
#include "srsapps/common/tti_sync.h"
}
void dl_sps::clear()
{
#ifndef TTISYNC_CV_H
#define TTISYNC_CV_H
}
}
}
namespace srslte {
namespace ue {
/* Implements tti_sync interface with condition variables.
*/
class tti_sync_cv : public tti_sync
{
public:
tti_sync_cv(uint32_t modulus = 10240);
~tti_sync_cv();
void increase();
uint32_t wait();
void resync();
void set_producer_cntr(uint32_t producer_cntr);
private:
pthread_cond_t cond;
pthread_mutex_t mutex;
};
}
}
#endif

@ -28,12 +28,12 @@
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/mac_interface.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac_io.h"
#include "srsapps/common/qbuff.h"
#include "srsapps/common/timers.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/pdu.h"
#include "srsapps/ue/mac/sdu_handler.h"
#ifndef DEMUX_H
#define DEMUX_H
@ -47,13 +47,15 @@ class demux
{
public:
demux();
void init(phy* phy_h_, log* log_h_, mac_io* mac_io_h_, timers* timers_db_);
void init(phy_interface* phy_h_, rlc_interface_mac *rlc, log* log_h_, timers* timers_db_);
void add_sdu_handler(sdu_handler *handler);
void process_pdus();
uint8_t* request_buffer(uint32_t len);
void release_pdu(uint8_t *buff, uint32_t nof_bytes);
void release_pdu_bcch(uint8_t *buff, uint32_t nof_bytes);
void release_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes);
void push_pdu(uint8_t *mac_pdu, uint32_t nof_bits);
void push_pdu_bcch(uint8_t *mac_pdu, uint32_t nof_bits);
void push_pdu_temp_crnti(uint8_t *mac_pdu, uint32_t nof_bits);
bool is_temp_crnti_pending();
bool is_contention_resolution_id_pending();
void demultiplex_pending_pdu();
@ -62,24 +64,38 @@ public:
uint64_t get_contention_resolution_id();
private:
const static int NOF_PDU_Q = 3; // prevents threads from being locked
const static int MAX_PDU_LEN = 128*1024;
sch_pdu mac_msg;
sch_pdu pending_mac_msg;
void process_pdu(sch_pdu *pdu);
void process_pdu(uint8_t *pdu, uint32_t nof_bytes);
void process_sch_pdu(sch_pdu *pdu);
bool process_ce(sch_subh *subheader);
// Mutex for exclusive access
pthread_mutex_t mutex;
bool find_unused_queue(uint8_t *idx);
bool find_nonempty_queue(uint8_t *idx);
void push_buffer(uint8_t *buff, uint32_t nof_bytes);
uint64_t contention_resolution_id;
bool pending_temp_rnti;
bool has_pending_contention_resolution_id;
typedef struct {
uint8_t idx;
uint8_t dummy[15]; // FIXME: This it to keep 128-bit alignment
} buff_header_t;
phy *phy_h;
log *log_h;
mac_io *mac_io_h;
timers *timers_db;
sdu_handler *sdu_handler_;
// Mutex for exclusive access
pthread_mutex_t mutex;
pthread_cond_t cvar;
qbuff pdu_q[NOF_PDU_Q];
bool used_q[NOF_PDU_Q];
phy_interface *phy_h;
log *log_h;
timers *timers_db;
rlc_interface_mac *rlc;
};
}
}

@ -33,6 +33,7 @@
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/common/timers.h"
#include "srsapps/ue/mac/demux.h"
#include "srsapps/ue/mac/dl_sps.h"
#include "srsapps/ue/mac/mac_pcap.h"
#ifndef DLHARQ_H
@ -43,8 +44,6 @@
namespace srslte {
namespace ue {
typedef _Complex float cf_t;
class dl_harq_entity
{
public:
@ -53,49 +52,56 @@ public:
const static uint32_t HARQ_BCCH_PID = NOF_HARQ_PROC;
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 pid, dl_sched_grant *grant);
void receive_data(uint32_t tti, uint32_t pid, dl_buffer *dl_buffer, phy *phy_h);
bool init(log *log_h_, timers *timers_, demux *demux_unit);
/***************** PHY->MAC interface for DL processes **************************/
void new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t *action);
void tb_decoded_ok(uint32_t harq_pid);
void reset();
bool is_ack_pending_resolution();
void send_pending_ack_contention_resolution();
void start_pcap(mac_pcap* pcap);
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(dl_sched_grant *grant);
void receive_data(uint32_t tti, dl_buffer *dl_buffer, phy *phy_h);
bool init(uint32_t pid, dl_harq_entity *parent);
void reset();
// Called after the contention resolution is terminated to send pending ACKs, if any
void send_pending_ack_contention_resolution();
uint32_t pid;
bool is_sps();
bool is_new_transmission(mac_interface_phy::mac_grant_t grant);
void new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t *action);
void tb_decoded_ok();
private:
bool is_initiated;
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 pending_ack;
srslte::log *log_h;
log *log_h;
uint32_t pid;
uint8_t *payload_buffer_ptr;
bool ack;
mac_interface_phy::mac_grant_t cur_grant;
srslte_softbuffer_rx_t softbuffer;
srslte_softbuffer_rx_t softbuffer;
bool ack;
};
static bool generate_ack_callback(void *arg);
uint32_t get_harq_sps_pid(uint32_t tti);
dl_sps dl_sps_assig;
dl_harq_process proc[NOF_HARQ_PROC+1];
dl_harq_process proc[NOF_HARQ_PROC+1];
timers *timers_db;
demux *demux_unit;
srslte::log *log_h;
int pending_ack_pid;
log *log_h;
mac_pcap *pcap;
uint16_t last_temporal_crnti;
};
}

@ -41,15 +41,15 @@
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);
void clear() {}
void reset() {}
bool get_pending_grant(uint32_t tti, mac_interface_phy::mac_grant_t *grant) {
return false;
}
private:
};

@ -25,29 +25,22 @@
*
*/
#include <pthread.h>
#include "srsapps/common/log.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"
#include "srsapps/ue/mac/sdu_handler.h"
#include "srsapps/ue/mac/mac_pcap.h"
#include "srsapps/common/trace.h"
#include "srsapps/common/mac_interface.h"
#include "srsapps/common/tti_sync_cv.h"
#include "srsapps/common/threads.h"
#ifndef UEMAC_H
@ -56,95 +49,68 @@
namespace srslte {
namespace ue {
typedef _Complex float cf_t;
class mac : public timer_callback, mac_interface_phy, mac_interface_rlc
class mac : public thread, timer_callback, mac_interface_phy, mac_interface_rlc, mac_interface_params
{
public:
mac() : timers_db((uint32_t) NOF_MAC_TIMERS), tr_exec_total(1024*10), tr_exec_dl(1024*10), tr_exec_ul(1024*10) {started=false; pcap = NULL; }
bool init(phy *phy_h, tti_sync *ttisync, log *log_h);
mac();
bool init(phy_interface *phy, rlc_interface_mac *rlc, log *log_h);
void stop();
int get_tti();
void main_radio_loop(); // called after thread creation
void add_sdu_handler(sdu_handler *handler);
bool send_sdu(uint32_t lcid, uint8_t *sdu_payload, uint32_t nbytes);
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_sdu(uint32_t lcid, uint8_t *sdu_payload, uint32_t nbytes);
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
/******** Interface from PHY (PHY -> MAC) ****************/
/* see mac_interface.h for comments */
void new_grant_ul(mac_grant_t grant, uint8_t *payload_ptr, tb_action_ul_t *action);
void new_grant_ul_ack(mac_grant_t grant, uint8_t *payload_ptr, bool ack, tb_action_ul_t *action);
void harq_recv(uint32_t tti, bool ack, tb_action_ul_t *action);
void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action);
void tb_decoded_ok(uint32_t harq_pid);
void bch_decoded_ok(uint8_t *payload, uint32_t len);
void tti_clock(uint32_t tti);
void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD);
void set_param(mac_params::mac_param_t param, int64_t value);
int64_t get_param(mac_params::mac_param_t param);
/******** Interface from RLC (RLC -> MAC) ****************/
void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD);
void reconfiguration();
void reset();
void start_trace();
void write_trace(std::string filename);
/******** MAC parameters ****************/
void set_param(mac_interface_params::mac_param_t param, int64_t value);
int64_t get_param(mac_interface_params::mac_param_t param);
void timer_expired(uint32_t timer_id);
void start_pcap(mac_pcap* pcap);
uint32_t get_current_tti();
enum {
HARQ_RTT = 0,
HARQ_RTT,
TIME_ALIGNMENT,
CONTENTION_TIMER,
BSR_TIMER_PERIODIC,
BSR_TIMER_RETX,
NOF_MAC_TIMERS
} mac_timers_t;
class tti_thread {
public:
bool init(mac *parent, tti_sync_cv *ttysync);
void run();
void run_tti(uint32_t tti);
void stop();
private:
bool started;
log *log_h;
mac *parent;
tti_sync_cv *sync;
pthread_t thread;
};
static const int NOF_TTI_THREADS = 2;
private:
void run_thread();
void search_si_rnti();
// TTI processing threads
tti_thread tti_threads[NOF_TTI_THREADS];
tti_sync_cv tti_threads_sync[NOF_TTI_THREADS];
pthread_mutex_t tti_threads_sync_tx[NOF_TTI_THREADS];
bool is_first_tx;
// Interaction with PHY
tti_sync *ttisync;
phy *phy_h;
log *log_h;
static const int MAC_THREAD_PRIO = 5;
/* Logical channel (lch) IO */
mac_io mac_io_lch;
// Interaction with PHY
tti_sync_cv ttisync;
phy_interface *phy_h;
rlc_interface_mac *rlc_h;
log *log_h;
mac_params params_db;
pthread_t mac_thread;
static void* mac_thread_fnc(void*);
int tti;
uint32_t tti;
bool started;
bool is_synchronized;
uint16_t last_temporal_crnti;
uint16_t phy_rnti;
/* Multiplexing/Demultiplexing Units */
mux mux_unit;
@ -154,46 +120,22 @@ private:
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);
int si_window_start, si_window_length;
/* 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);
bool process_ul_grants(uint32_t tti);
void receive_pch(uint32_t tti);
/* Functions for MAC Timers */
timers timers_db;
uint16_t phy_rnti;
void setup_timers();
void timeAlignmentTimerExpire();
// pointer to MAC PCAP object
mac_pcap* pcap;
// Variables for Execution time Trace
trace<uint32_t> tr_exec_total;
trace<uint32_t> tr_exec_dl;
trace<uint32_t> tr_exec_ul;
struct timeval tr_time_total[3];
struct timeval tr_time_ul[3];
struct timeval tr_time_dl[3];
bool tr_enabled;
bool is_first_of_burst;
void tr_log_start(uint32_t tti);
void tr_log_end(uint32_t tti);
void tr_log_dl(uint32_t tti);
void tr_log_ul(uint32_t tti);
void pregen_phy(uint16_t phy_rnti);
};
}

@ -1,112 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 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 Affero 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 Affero General Public License for more details.
*
* A copy of the GNU Affero 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 "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 = 64;
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

@ -29,6 +29,7 @@
#include "srslte/srslte.h"
#include "srsapps/common/params_db.h"
#include "srsapps/common/mac_interface.h"
#ifndef MACPARAMS_H
#define MACPARAMS_H
@ -41,7 +42,7 @@ namespace ue {
{
public:
mac_params() : params_db(NOF_PARAMS) {}
mac_params() : params_db(mac_interface_params::NOF_PARAMS) {}
~mac_params() {}

@ -56,9 +56,6 @@ private:
uint32_t ue_id;
void pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reTX, bool crc_ok, uint32_t tti,
uint16_t crnti_, uint8_t direction, uint8_t rnti_type);
static const uint32_t max_pdu_len = 16*1024;
uint8_t pdu_pcap_tmp[max_pdu_len];
};
}

@ -28,8 +28,9 @@
#include <pthread.h>
#include "srsapps/common/qbuff.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac_io.h"
#include "srsapps/common/mac_interface.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/pdu.h"
#include "srsapps/ue/mac/proc_bsr.h"
@ -47,17 +48,15 @@ class mux
public:
mux();
void reset();
void init(log *log_h, mac_io *mac_io_h, bsr_proc *bsr_procedure);
void init(rlc_interface_mac *rlc, log *log_h, bsr_proc *bsr_procedure);
bool is_pending_ccch_sdu();
bool is_pending_any_sdu();
bool is_pending_sdu(uint32_t lcid);
uint8_t* pdu_pop(uint32_t pdu_sz);
bool pdu_move_to_msg3(uint32_t pdu_sz);
void pdu_release();
bool pdu_get(uint8_t *payload, uint32_t pdu_sz);
uint8_t* msg3_pop(uint32_t pdu_sz);
bool msg3_get(uint8_t *payload, uint32_t pdu_sz);
void msg3_flush();
void msg3_transmitted();
bool msg3_is_transmitted();
@ -67,34 +66,33 @@ public:
void set_priority(uint32_t lcid, uint32_t priority, int PBR_x_tti, uint32_t BSD);
private:
bool assemble_pdu(uint32_t pdu_sz);
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu);
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, bool *is_first);
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, uint32_t *sdu_sz, bool *is_first);
bool pdu_move_to_msg3(uint32_t pdu_sz);
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu);
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, bool *is_first);
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, int max_sdu_sz, uint32_t *sdu_sz, bool *is_first);
const static int NOF_UL_LCH = 10;
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];
int64_t Bj[NOF_UL_LCH];
int PBR[NOF_UL_LCH]; // -1 sets to infinity
uint32_t BSD[NOF_UL_LCH];
uint32_t priority[NOF_UL_LCH];
uint32_t priority_sorted[NOF_UL_LCH];
uint32_t lchid_sorted[NOF_UL_LCH];
// Mutex for exclusive access
pthread_mutex_t mutex;
log *log_h;
mac_io *mac_io_h;
bsr_proc *bsr_procedure;
uint16_t pending_crnti_ce;
log *log_h;
rlc_interface_mac *rlc;
bsr_proc *bsr_procedure;
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 = 128*1024;
qbuff pdu_buff;
sch_pdu pdu_msg;
bool msg3_has_been_transmitted;

@ -28,6 +28,7 @@
#include <stdint.h>
#include "srsapps/common/log.h"
#include "srsapps/common/mac_interface.h"
#include <vector>
#include <stdio.h>
@ -139,7 +140,7 @@ public:
return pdu_is_ul;
}
virtual bool write_packet(uint8_t *ptr) = 0;
virtual bool write_packet(uint8_t *ptr, rlc_interface_mac *rlc) = 0;
protected:
std::vector<SubH> subheaders;
@ -156,11 +157,11 @@ class subh
{
public:
virtual bool read_subheader(uint8_t** ptr) = 0;
virtual void read_payload(uint8_t **ptr) = 0;
virtual void write_subheader(uint8_t** ptr, bool is_last) = 0;
virtual void write_payload(uint8_t **ptr) = 0;
virtual void fprint(FILE *stream) = 0;
virtual bool read_subheader(uint8_t** ptr) = 0;
virtual void read_payload(uint8_t **ptr) = 0;
virtual void write_subheader(uint8_t** ptr, bool is_last) = 0;
virtual void write_payload(uint8_t **ptr, rlc_interface_mac *rlc) = 0;
virtual void fprint(FILE *stream) = 0;
pdu<SubH>* parent;
@ -207,9 +208,9 @@ public:
// Writing functions
void write_subheader(uint8_t** ptr, bool is_last);
void write_payload(uint8_t **ptr);
bool set_sdu(uint32_t lcid, uint8_t *ptr, uint32_t nof_bytes);
bool set_sdu(uint32_t lcid, uint8_t *ptr, uint32_t nof_bytes, bool is_first);
void write_payload(uint8_t **ptr, rlc_interface_mac *rlc);
bool set_sdu(uint32_t lcid, uint32_t nof_bytes);
bool set_sdu(uint32_t lcid, uint32_t nof_bytes, bool is_first);
bool set_c_rnti(uint16_t crnti);
bool set_bsr(uint32_t buff_size[4], sch_subh::cetype format, bool update_size);
bool set_con_res_id(uint64_t con_res_id);
@ -225,9 +226,9 @@ private:
static const int MAX_CE_PAYLOAD_LEN = 8;
uint32_t lcid;
uint32_t nof_bytes;
uint8_t* sdu_payload_ptr;
uint8_t* payload;
uint8_t w_payload_ce[8];
bool F_bit;
uint8_t ce_payload[MAX_CE_PAYLOAD_LEN*8];
uint32_t sizeof_ce(uint32_t lcid, bool is_ul);
uint8_t buff_size_table(uint32_t buffer_size);
};
@ -239,7 +240,7 @@ public:
sch_pdu(uint32_t max_rars) : pdu(max_rars) {}
void parse_packet(uint8_t *ptr);
bool write_packet(uint8_t *ptr);
bool write_packet(uint8_t *ptr, rlc_interface_mac *rlc);
bool has_space_ce(uint32_t nbytes);
bool has_space_sdu(uint32_t nbytes);
bool has_space_sdu(uint32_t nbytes, bool is_first);
@ -249,7 +250,7 @@ public:
bool update_space_ce(uint32_t nbytes);
bool update_space_sdu(uint32_t nbytes);
bool update_space_sdu(uint32_t nbytes, bool is_first);
void fprint(FILE *stream);
void fprint(FILE *stream);
};
@ -269,7 +270,7 @@ public:
// Writing functoins
void write_subheader(uint8_t** ptr, bool is_last);
void write_payload(uint8_t** ptr);
void write_payload(uint8_t** ptr, rlc_interface_mac *rlc);
void set_rapid(uint32_t rapid);
void set_ta_cmd(uint32_t ta);
void set_temp_crnti(uint16_t temp_rnti);
@ -295,7 +296,7 @@ public:
bool has_backoff();
uint8_t get_backoff();
bool write_packet(uint8_t* ptr);
bool write_packet(uint8_t* ptr, rlc_interface_mac *rlc);
void fprint(FILE *stream);
private:

@ -31,8 +31,8 @@
#include "srsapps/common/log.h"
#include "srsapps/ue/mac/proc.h"
#include "srsapps/common/mac_interface.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mac_io.h"
#include "srsapps/common/timers.h"
#ifndef PROCBSR_H
@ -47,7 +47,7 @@ class bsr_proc : public proc, timer_callback
{
public:
bsr_proc();
void init(log *log_h, timers *timers_db, mac_params *params_db, mac_io *mac_io_h);
void init(rlc_interface_mac *rlc, log *log_h, mac_params *params_db, timers *timers_db);
void step(uint32_t tti);
void reset();
void setup_lcg(uint32_t lcid, uint32_t new_lcg);
@ -74,9 +74,9 @@ private:
bool reset_sr;
mac_params *params_db;
mac_io *mac_io_h;
timers *timers_db;
log *log_h;
rlc_interface_mac *rlc;
bool initiated;
const static int MAX_LCID = 20;
int lcg[MAX_LCID];

@ -52,8 +52,7 @@ class ra_proc : public proc,timer_callback
{
public:
ra_proc() : rar_pdu_msg(20) {pcap = NULL;};
bool init(mac_params *params_db, phy *phy_h, log *log_h, timers *timers_db,
mux *mux_unit, demux *demux_unit);
bool init(phy_interface *phy_h, log *log_h, mac_params *params_db, timers *timers_db, mux *mux_unit, demux *demux_unit);
void reset();
void start_pdcch_order();
void start_rlc_order();
@ -67,15 +66,18 @@ class ra_proc : public proc,timer_callback
void pdcch_to_crnti(bool is_ul_grant);
void timer_expired(uint32_t timer_id);
void new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action);
void tb_decoded_ok();
void* run_prach_thread();
void start_pcap(mac_pcap* pcap);
private:
void process_timeadv_cmd(uint32_t ta_cmd);
void step_initialization();
void step_initialization_wait();
void step_resource_selection();
void step_preamble_transmission();
void step_pdcch_setup();
void step_response_reception();
void step_response_error();
void step_backoff_wait();
@ -107,7 +109,6 @@ private:
int preambleIndex;
// Internal variables
uint32_t tti;
uint32_t preambleTransmissionCounter;
uint32_t backoff_param_ms;
uint32_t sel_maskIndex;
@ -116,14 +117,15 @@ private:
uint32_t backoff_inteval;
int received_target_power_dbm;
uint32_t ra_rnti;
uint8_t payload[256]; // 56 bits is often enough
srslte_softbuffer_rx_t softbuffer_rar;
enum {
IDLE = 0,
INITIALIZATION, // Section 5.1.1
INITIALIZATION_WAIT,
RESOURCE_SELECTION, // Section 5.1.2
PREAMBLE_TRANSMISSION, // Section 5.1.3
PDCCH_SETUP,
RESPONSE_RECEPTION, // Section 5.1.4
RESPONSE_ERROR,
BACKOFF_WAIT,
@ -139,21 +141,17 @@ private:
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;
mac_pcap *pcap;
pthread_t pt_init_prach;
pthread_cond_t cond;
pthread_mutex_t mutex;
bool start_prach_init;
phy_interface *phy_h;
log *log_h;
mac_params *params_db;
timers *timers_db;
mux *mux_unit;
demux *demux_unit;
mac_pcap *pcap;
uint64_t transmitted_contention_id;
uint16_t transmitted_crnti;
enum {
PDCCH_CRNTI_NOT_RECEIVED = 0,
PDCCH_CRNTI_UL_GRANT,
@ -165,6 +163,8 @@ private:
RLC_ORDER,
MAC_ORDER
} start_mode;
uint32_t rar_grant_nbytes;
uint32_t rar_grant_tti;
};
}
}

@ -45,20 +45,22 @@ class sr_proc : public proc
{
public:
sr_proc();
void init(log *log_h, mac_params *params_db, phy *phy_h);
void init(phy_interface *phy_h, log *log_h, mac_params *params_db);
void step(uint32_t tti);
void reset();
void start();
bool need_random_access();
private:
uint32_t sr_counter;
uint32_t dsr_transmax;
bool is_pending_sr;
mac_params *params_db;
phy *phy_h;
log *log_h;
bool initiated;
bool do_ra;
uint32_t sr_counter;
uint32_t dsr_transmax;
bool is_pending_sr;
mac_params *params_db;
phy_interface *phy_h;
log *log_h;
bool initiated;
bool do_ra;
};
}
}

@ -25,13 +25,11 @@
*
*/
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/mac_interface.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mux.h"
#include "srsapps/ue/mac/ul_sps.h"
#include "srsapps/ue/mac/mac_pcap.h"
#include "srsapps/common/timers.h"
@ -43,8 +41,6 @@
namespace srslte {
namespace ue {
typedef _Complex float cf_t;
class ul_harq_entity
{
public:
@ -52,56 +48,73 @@ public:
const static uint32_t NOF_HARQ_PROC = 8;
static uint32_t pidof(uint32_t tti);
ul_harq_entity() { pcap = NULL; }
bool init(srslte_cell_t cell, mac_params *params_db, log *log_h, timers* timers_, mux *mux_unit);
ul_harq_entity() { pcap = NULL; }
bool init(log *log_h, mac_params *params_db, timers* timers_, mux *mux_unit);
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_);
void start_pcap(mac_pcap* pcap);
/***************** PHY->MAC interface for UL processes **************************/
void new_grant_ul(mac_interface_phy::mac_grant_t grant, uint8_t *payload_ptr,
mac_interface_phy::tb_action_ul_t *action);
void new_grant_ul_ack(mac_interface_phy::mac_grant_t grant, uint8_t *payload_ptr, bool ack,
mac_interface_phy::tb_action_ul_t *action);
void harq_recv(uint32_t tti, bool ack, mac_interface_phy::tb_action_ul_t *action);
private:
class ul_harq_process {
public:
ul_harq_process();
bool init(srslte_cell_t cell, ul_harq_entity *parent);
bool init(uint32_t pid, ul_harq_entity *parent);
void reset();
void reset_ndi();
void generate_retx(uint32_t tti_tx, ul_buffer *ul);
void generate_retx(uint32_t tti_tx, ul_sched_grant *ul_grant, ul_buffer *ul);
void generate_new_tx(uint32_t tti_tx, uint8_t *payload, bool is_msg3, ul_sched_grant* grant, ul_buffer *ul);
void generate_retx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action);
void generate_retx(uint32_t tti_tx, mac_interface_phy::mac_grant_t *grant,
mac_interface_phy::tb_action_ul_t *action);
void generate_new_tx(uint32_t tti_tx, bool is_msg3, mac_interface_phy::mac_grant_t *grant,
mac_interface_phy::tb_action_ul_t *action);
uint32_t get_rv();
bool has_grant();
ul_sched_grant *get_grant();
void set_harq_feedback(bool ack);
bool get_ndi();
bool is_sps();
uint32_t last_tx_tti();
uint32_t pid;
uint32_t get_nof_retx();
private:
mac_interface_phy::mac_grant_t cur_grant;
uint32_t pid;
uint32_t current_tx_nb;
uint32_t current_irv;
bool harq_feedback;
bool ndi;
log *log_h;
ul_harq_entity *harq_entity;
ul_sched_grant cur_grant;
bool is_grant_configured;
srslte_softbuffer_tx_t softbuffer;
bool is_msg3;
bool is_initiated;
uint32_t tti_last_tx;
bool is_initiated;
uint32_t tti_last_tx;
void generate_tx(uint32_t tti_tx, uint8_t *pdu_payload, ul_buffer* ul);
void generate_tx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action);
};
uint8_t mac_pdu_buffer[NOF_HARQ_PROC][64*1024];
void run_tti(uint32_t tti, mac_interface_phy::mac_grant_t *grant, uint8_t* payload_ptr,
mac_interface_phy::tb_action_ul_t* action);
void set_ack(uint32_t tti, bool ack);
ul_sps ul_sps_assig;
timers *timers_db;
mux *mux_unit;
ul_harq_process proc[NOF_HARQ_PROC];

@ -48,8 +48,8 @@ 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; }
void reset(uint32_t tti) {}
bool get_pending_grant(uint32_t tti, mac_interface_phy::mac_grant_t *grant) { return false; }
private:
};

@ -30,32 +30,30 @@
#include "srsapps/ue/mac/demux.h"
namespace srslte {
namespace ue {
namespace ue {
demux::demux() : mac_msg(20),pending_mac_msg(20)
demux::demux() : mac_msg(20), pending_mac_msg(20)
{
contention_resolution_id = 0;
pending_temp_rnti = false;
has_pending_contention_resolution_id = false;
sdu_handler_ = NULL;
for (int i=0;i<NOF_PDU_Q;i++) {
pdu_q[i].init(8, MAX_PDU_LEN);
used_q[i] = false;
}
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cvar, NULL);
}
void demux::init(phy* phy_h_, log* log_h_, mac_io* mac_io_h_, timers* timers_db_)
void demux::init(phy_interface* phy_h_, rlc_interface_mac *rlc_, log* log_h_, timers* timers_db_)
{
phy_h = phy_h_;
log_h = log_h_;
mac_io_h = mac_io_h_;
rlc = rlc_;
timers_db = timers_db_;
}
void demux::add_sdu_handler(sdu_handler* handler)
{
sdu_handler_ = handler;
}
bool demux::is_temp_crnti_pending()
{
return pending_temp_rnti;
@ -73,28 +71,95 @@ uint64_t demux::get_contention_resolution_id()
return x;
}
bool demux::find_unused_queue(uint8_t *idx) {
for (uint8_t i=0;i<NOF_PDU_Q;i++) {
if (!used_q[i]) {
if (idx) {
*idx = i;
}
return true;
}
}
return false;
}
// Read packets from queues in round robin
bool demux::find_nonempty_queue(uint8_t *idx) {
for (uint8_t i=0;i<NOF_PDU_Q;i++) {
if (!pdu_q[(i+*idx)%NOF_PDU_Q].isempty()) {
if (idx) {
*idx = i;
}
return true;
}
}
return false;
}
uint8_t* demux::request_buffer(uint32_t len)
{
if (len >= MAX_PDU_LEN - sizeof(buff_header_t)) {
return NULL;
}
pthread_mutex_lock(&mutex);
uint8_t idx;
while(find_unused_queue(&idx)) {
pthread_cond_wait(&cvar, &mutex);
}
if (idx > 0) {
Debug("Using queue %d for MAC PDU\n");
}
used_q[idx] = true;
uint8_t *buff = (uint8_t*) pdu_q[idx].request();
buff_header_t *head = (buff_header_t*) buff;
head->idx = idx;
pthread_mutex_unlock(&mutex);
return &buff[sizeof(buff_header_t)];
}
void demux::push_buffer(uint8_t *buff, uint32_t nof_bytes) {
buff_header_t *head = (buff_header_t*) (buff-sizeof(buff_header_t));
if (head->idx < NOF_PDU_Q) {
pthread_mutex_lock(&mutex);
if (nof_bytes > 0) {
if (!pdu_q[head->idx].push(nof_bytes)) {
Warning("Full queue %d when pushing MAC PDU %d bytes\n", head->idx, nof_bytes);
}
}
used_q[head->idx] = false;
pthread_cond_signal(&cvar);
pthread_mutex_unlock(&mutex);
}
}
/* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through
* the MAC in transparent mode
* the MAC in transparent mode.
* Warning: this function sends the message to RLC now, since SI blocks do not
* require ACK feedback to be transmitted quickly.
*/
void demux::push_pdu_bcch(uint8_t *mac_pdu, uint32_t nof_bits)
void demux::release_pdu_bcch(uint8_t *buff, uint32_t nof_bytes)
{
mac_io_h->get(mac_io::MAC_LCH_BCCH_DL)->send(mac_pdu, nof_bits);
Debug("Pushed BCCH MAC PDU in transparent mode\n");
rlc->write_pdu_bcch_dlsch(buff, nof_bytes);
push_buffer(buff, 0);
}
/* 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
* Contention Resolution result.
*
* Warning: this function does some processing here assuming ACK deadline is not an
* issue here because Temp C-RNTI messages have small payloads
*/
void demux::push_pdu_temp_crnti(uint8_t *mac_pdu, uint32_t nof_bits)
void demux::release_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes)
{
if (!pending_temp_rnti) {
// Unpack DLSCH MAC PDU
pending_mac_msg.init(nof_bits/8);
pending_mac_msg.parse_packet(mac_pdu);
pending_mac_msg.init(nof_bytes);
pending_mac_msg.parse_packet(buff);
//pending_mac_msg.fprint(stdout);
// Look for Contention Resolution UE ID
@ -108,25 +173,43 @@ void demux::push_pdu_temp_crnti(uint8_t *mac_pdu, uint32_t nof_bits)
pending_mac_msg.reset();
pending_temp_rnti = true;
Debug("Saved MAC PDU with Temporal C-RNTI in buffer\n");
push_buffer(buff, 0);
} 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(uint8_t *mac_pdu, uint32_t nof_bits)
/* Demultiplexing of logical channels and dissassemble of MAC CE
* This function enqueues the packet and returns quicly because ACK
* deadline is important here.
*/
void demux::release_pdu(uint8_t *buff, uint32_t nof_bytes)
{
pthread_mutex_lock(&mutex);
push_buffer(buff, nof_bytes);
}
void demux::process_pdus()
{
uint32_t len;
uint8_t idx;
while(find_nonempty_queue(&idx)) {
uint8_t *mac_pdu = (uint8_t*) pdu_q[idx].pop(&len);
if (mac_pdu) {
process_pdu(mac_pdu, len);
pdu_q[idx].release();
}
idx++;
}
}
void demux::process_pdu(uint8_t *mac_pdu, uint32_t nof_bytes)
{
// Unpack DLSCH MAC PDU
mac_msg.init(nof_bits/8);
mac_msg.init(nof_bytes);
mac_msg.parse_packet(mac_pdu);
//mac_msg.fprint(stdout);
process_pdu(&mac_msg);
mac_msg.fprint(stdout);
process_sch_pdu(&mac_msg);
Debug("Normal MAC PDU processed\n");
pthread_mutex_unlock(&mutex);
}
void demux::discard_pending_pdu()
@ -138,40 +221,21 @@ void demux::discard_pending_pdu()
void demux::demultiplex_pending_pdu()
{
if (pending_temp_rnti) {
process_pdu(&pending_mac_msg);
process_sch_pdu(&pending_mac_msg);
discard_pending_pdu();
} else {
Error("Error demultiplex pending PDU: No pending PDU\n");
}
}
void demux::process_pdu(sch_pdu *pdu_msg)
void demux::process_sch_pdu(sch_pdu *pdu_msg)
{
while(pdu_msg->next()) {
if (pdu_msg->get()->is_sdu()) {
// Route logical channel
if (pdu_msg->get()->get_sdu_lcid() <= mac_io::MAC_LCH_DTCH2_DL) {
qbuff *dest_lch = mac_io_h->get(pdu_msg->get()->get_sdu_lcid());
if (dest_lch) {
dest_lch->send(pdu_msg->get()->get_sdu_ptr(), pdu_msg->get()->get_sdu_nbytes()*8);
Debug("Sent MAC SDU len=%d bytes to lchid=%d\n",
pdu_msg->get()->get_sdu_nbytes(), pdu_msg->get()->get_sdu_lcid());
if (sdu_handler_) {
sdu_handler_->notify_new_sdu(pdu_msg->get()->get_sdu_lcid());
Debug("Notified SDU handler len=%d bytes to lchid=%d\n",
pdu_msg->get()->get_sdu_nbytes(), pdu_msg->get()->get_sdu_lcid());
}
} else {
Error("Getting destination channel LCID=%d\n", pdu_msg->get()->get_sdu_lcid());
}
} else {
Warning("Received SDU for unsupported LCID=%d\n", pdu_msg->get()->get_sdu_lcid());
}
// Process MAC Control Element
rlc->write_pdu(pdu_msg->get()->get_sdu_lcid(), pdu_msg->get()->get_sdu_ptr(), pdu_msg->get()->get_sdu_nbytes());
} else {
// Process MAC Control Element
if (!process_ce(pdu_msg->get())) {
Warning("Received Subheader with invalid or unkonwn LCID\n");
}
@ -179,7 +243,6 @@ void demux::process_pdu(sch_pdu *pdu_msg)
}
}
bool demux::process_ce(sch_subh *subh) {
switch(subh->ce_type()) {
case sch_subh::CON_RES_ID:

@ -26,7 +26,6 @@
*/
#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"
@ -43,19 +42,15 @@ namespace srslte {
dl_harq_entity::dl_harq_entity()
{
for (uint32_t i=0;i<NOF_HARQ_PROC+1;i++) {
proc[i].pid = i;
}
pending_ack_pid = -1;
pcap = NULL;
}
bool dl_harq_entity::init(srslte_cell_t cell, uint32_t max_payload_len, log* log_h_, timers* timers_, demux *demux_unit_)
bool dl_harq_entity::init(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)) {
if (!proc[i].init(i, this)) {
return false;
}
}
@ -68,190 +63,241 @@ void dl_harq_entity::start_pcap(mac_pcap* pcap_)
pcap = pcap_;
}
bool dl_harq_entity::is_sps(uint32_t pid)
{
return false;
}
void dl_harq_entity::set_harq_info(uint32_t pid, dl_sched_grant* grant)
void dl_harq_entity::reset()
{
proc[pid%(NOF_HARQ_PROC+1)].set_harq_info(grant);
for (uint32_t i=0;i<NOF_HARQ_PROC+1;i++) {
proc[i].reset();
}
dl_sps_assig.clear();
}
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);
uint32_t dl_harq_entity::get_harq_sps_pid(uint32_t tti) {
/*
uint32_t nof_proc = ((uint32_t) params_db->get_param(mac_interface_params::SPS_DL_NOF_PROC));
return tti/params_db.get_param(mac_interface_params::SPS_DL_SCHED_INTERVAL)%nof_proc;
*/
}
void dl_harq_entity::reset()
void dl_harq_entity::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action)
{
for (uint32_t i=0;i<NOF_HARQ_PROC+1;i++) {
proc[i].reset();
// If PDCCH for C-RNTI and RA procedure in Contention Resolution, notify it
if (grant.rnti_type == SRSLTE_RNTI_USER) {
Warning("Not implemented ra_procedure_crnti\n");
//ra_procedure.pdcch_to_crnti(false);
}
if (grant.rnti_type != SRSLTE_RNTI_SPS) {
uint32_t harq_pid;
// Set BCCH PID for SI RNTI
if (grant.rnti_type == SRSLTE_RNTI_SI) {
harq_pid = HARQ_BCCH_PID;
} else {
harq_pid = grant.pid%NOF_HARQ_PROC;
}
if (grant.rnti_type == SRSLTE_RNTI_TEMP && last_temporal_crnti != grant.rnti) {
grant.ndi = true;
Info("Set NDI=1 for Temp-RNTI DL grant\n");
last_temporal_crnti = grant.rnti;
}
if (grant.rnti_type == SRSLTE_RNTI_USER && proc[harq_pid].is_sps()) {
grant.ndi = true;
Info("Set NDI=1 for C-RNTI DL grant\n");
}
proc[harq_pid].new_grant_dl(grant, action);
} else {
/* This is for SPS scheduling */
uint32_t harq_pid = get_harq_sps_pid(grant.tti)%NOF_HARQ_PROC;
if (grant.ndi) {
grant.ndi = false;
proc[harq_pid].new_grant_dl(grant, action);
} else {
if (grant.is_sps_release) {
dl_sps_assig.clear();
if (timers_db->get(mac::TIME_ALIGNMENT)->is_running()) {
//phy_h->send_sps_ack();
Warning("PHY Send SPS ACK not implemented\n");
}
} else {
Error("SPS not implemented\n");
//dl_sps_assig.reset(grant.tti, grant);
//grant.ndi = true;
//procs[harq_pid].save_grant();
}
}
}
}
bool dl_harq_entity::is_ack_pending_resolution()
void dl_harq_entity::tb_decoded_ok(uint32_t harq_pid)
{
return pending_ack_pid >= 0;
proc[harq_pid%NOF_HARQ_PROC].tb_decoded_ok();
}
void dl_harq_entity::send_pending_ack_contention_resolution()
bool dl_harq_entity::generate_ack_callback(void *arg)
{
if (is_ack_pending_resolution()) {
proc[pending_ack_pid].send_pending_ack_contention_resolution();
pending_ack_pid = -1;
}
demux *demux_unit = (demux*) arg;
return demux_unit->is_contention_resolution_id_pending();
}
/***********************************************************
*
* HARQ PROCESS
*
*********************************************************/
dl_harq_entity::dl_harq_process::dl_harq_process() : cur_grant(0),pending_ack_grant(0) {
dl_harq_entity::dl_harq_process::dl_harq_process() {
is_initiated = false;
ack = false;
bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant));
payload = NULL;
max_payload_len = 0;
bzero(&cur_grant, sizeof(mac_interface_phy::mac_grant_t));
}
void dl_harq_entity::dl_harq_process::reset() {
ack = false;
bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant));
payload_buffer_ptr = NULL;
bzero(&cur_grant, sizeof(mac_interface_phy::mac_grant_t));
if (is_initiated) {
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);
}
bool dl_harq_entity::dl_harq_process::init(uint32_t pid_, dl_harq_entity *parent) {
if (srslte_softbuffer_rx_init(&softbuffer, 100)) {
Error("Error initiating soft buffer\n");
return false;
} else {
pid = pid_;
is_initiated = true;
harq_entity = parent;
log_h = harq_entity->log_h;
return true;
}
}
void dl_harq_entity::dl_harq_process::receive_data(uint32_t tti, srslte::ue::dl_buffer *dl_buffer, phy *phy_h)
bool dl_harq_entity::dl_harq_process::is_sps()
{
pending_ul_buffer = NULL;
if (payload) {
if (cur_grant.get_tbs() <= max_payload_len) {
// If data has not yet been successfully decoded
if (ack == false) {
// Combine the received data and attempt to decode it
if (dl_buffer->decode_data(&cur_grant, &softbuffer, payload)) {
ack = true;
} else {
ack = false;
}
Info("DL PID %d: TBS=%d, RV=%d, MCS=%d, crc=%s\n", pid, cur_grant.get_tbs(), cur_grant.get_rv(), cur_grant.get_mcs(), ack?"OK":"NOK");
if (pid == HARQ_BCCH_PID) {
if (ack) {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.get_tbs()/8);
harq_entity->demux_unit->push_pdu_bcch(payload, cur_grant.get_tbs());
}
if (harq_entity->pcap) {
harq_entity->pcap->write_dl_sirnti(payload, cur_grant.get_tbs()/8, ack, tti);
}
} else {
if (ack) {
if (cur_grant.is_temp_rnti()) {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n",
cur_grant.get_tbs()/8);
harq_entity->demux_unit->push_pdu_temp_crnti(payload, cur_grant.get_tbs());
} else {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.get_tbs()/8);
harq_entity->demux_unit->push_pdu(payload, cur_grant.get_tbs());
}
}
if (harq_entity->pcap) {
harq_entity->pcap->write_dl_crnti(payload, cur_grant.get_tbs()/8, cur_grant.get_rnti(), ack, tti);
}
}
} else {
Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK\n", pid);
}
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));
Debug("ACK pending contention resolution\n");
} 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(srslte::ue::dl_sched_grant* new_grant) {
bool is_new_transmission = false;
return false;
}
bool dl_harq_entity::dl_harq_process::is_new_transmission(mac_interface_phy::mac_grant_t grant) {
bool is_new_transmission;
bool is_new_tb = true;
if (srslte_tti_interval(new_grant->get_tti(), cur_grant.get_tti()) <= 8 &&
new_grant->get_tbs() == cur_grant.get_tbs())
{
if (srslte_tti_interval(grant.tti, cur_grant.tti) <= 8 && grant.n_bytes == cur_grant.n_bytes) {
is_new_tb = false;
}
if ((new_grant->get_ndi() != cur_grant.get_ndi() && !is_new_tb) || // NDI toggled for same TB
is_new_tb || // is new TB
(pid == HARQ_BCCH_PID && new_grant->get_rv() == 0)) // Broadcast PID and 1st TX (RV=0)
if ((grant.ndi != cur_grant.ndi && !is_new_tb) || // NDI toggled for same TB
is_new_tb || // is new TB
(pid == HARQ_BCCH_PID && grant.rv == 0)) // Broadcast PID and 1st TX (RV=0)
{
is_new_transmission = true;
Debug("Set HARQ Info for new transmission\n");
} else {
if (!is_new_tb) {
Info("old_tbs=%d, new_tbs=%d, old_tti=%d new_tti=%d\n", cur_grant.get_tbs(), new_grant->get_tbs(),
cur_grant.get_tti(), new_grant->get_tti());
Info("old_tbs=%d, new_tbs=%d, old_tti=%d new_tti=%d\n", cur_grant.n_bytes, grant.n_bytes, cur_grant.tti, grant.tti);
}
is_new_transmission = false;
Debug("Set HARQ Info for retransmission\n");
}
Info("DL PID %d: %s RV=%d, NDI=%d, LastNDI=%d, DCI %s\n", pid, is_new_transmission?"new TX":"reTX", new_grant->get_rv(),
new_grant->get_ndi(), cur_grant.get_ndi(), new_grant->get_dciformat_string());
Info("DL PID %d: %s RV=%d, NDI=%d, LastNDI=%d\n", pid, is_new_transmission?"new TX":"reTX", grant.rv,
grant.ndi, cur_grant.ndi);
if (is_new_transmission) {
return is_new_transmission;
}
void dl_harq_entity::dl_harq_process::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action)
{
if (is_new_transmission(grant)) {
ack = false;
srslte_softbuffer_rx_reset(&softbuffer);
}
if (new_grant->get_tbs() <= max_payload_len) {
memcpy(&cur_grant, new_grant, sizeof(srslte::ue::dl_sched_grant));
// Save grant
memcpy(&cur_grant, &grant, sizeof(mac_interface_phy::mac_grant_t));
action->default_ack = ack;
action->generate_ack = true;
// If data has not yet been successfully decoded
if (ack == false) {
// Instruct the PHY To combine the received data and attempt to decode it
action->decode_enabled = true;
action->rv = cur_grant.rv;
action->rnti = cur_grant.rnti;
action->softbuffer = &softbuffer;
payload_buffer_ptr = harq_entity->demux_unit->request_buffer(cur_grant.n_bytes);
action->payload_ptr = payload_buffer_ptr;
if (!action->payload_ptr) {
action->decode_enabled = false;
Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes);
return;
}
memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(mac_interface_phy::mac_grant_t));
Info("DL PID %d: TBS=%d, RV=%d, crc=%s\n", pid, cur_grant.n_bytes, cur_grant.rv, ack?"OK":"NOK");
} else {
Error("Error with DL grant. TBS (%d) exceeds payload buffer length (%d)\n", new_grant->get_tbs(), max_payload_len);
Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK\n", pid);
}
if (pid == HARQ_BCCH_PID || harq_entity->timers_db->get(mac::TIME_ALIGNMENT)->is_expired()) {
// Do not generate ACK
Debug("Not generating ACK\n");
action->generate_ack = false;
if (pid == HARQ_BCCH_PID) {
// Compute RV
uint32_t k;
if (grant.tti%10 == 5) { // This is SIB1, k is different
k = (grant.tti/20)%4;
} else {
k = (grant.tti/10)%4;
}
action->rv = ((uint32_t) ceilf((float)1.5*k))%4;
}
} else {
if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP) {
// Postpone ACK after contention resolution is resolved
action->generate_ack_callback = harq_entity->generate_ack_callback;
action->generate_ack_callback_arg = harq_entity->demux_unit;
Debug("ACK pending contention resolution\n");
} else {
Debug("Generating ACK\n");
}
}
}
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)) {
Error("Error initiating soft buffer\n");
return false;
void dl_harq_entity::dl_harq_process::tb_decoded_ok()
{
ack = true;
if (pid == HARQ_BCCH_PID) {
if (harq_entity->pcap) {
harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.n_bytes, ack, cur_grant.tti);
}
if (ack) {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.n_bytes);
harq_entity->demux_unit->release_pdu_bcch(payload_buffer_ptr, cur_grant.n_bytes);
}
} else {
is_initiated = true;
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;
}
if (harq_entity->pcap) {
harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes, cur_grant.rnti, ack, cur_grant.tti);
}
if (ack) {
if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP) {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n", cur_grant.n_bytes);
harq_entity->demux_unit->release_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes);
} else {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes);
harq_entity->demux_unit->release_pdu(payload_buffer_ptr, cur_grant.n_bytes);
}
}
}
}
}
}

@ -30,49 +30,43 @@
#include <pthread.h>
#include <unistd.h>
#include "srsapps/common/threads.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"
#include "srsapps/ue/mac/pcap.h"
namespace srslte {
namespace ue {
mac::mac() : ttisync(10240), timers_db((uint32_t) NOF_MAC_TIMERS)
{
started = false;
pcap = NULL;
si_window_start = -1;
si_window_length = -1;
}
bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
bool mac::init(phy_interface *phy, rlc_interface_mac *rlc, log *log_h_)
{
started = false;
ttisync = ttisync_;
phy_h = phy_h_;
phy_h = phy;
rlc_h = rlc;
log_h = log_h_;
tti = 0;
is_synchronized = false;
last_temporal_crnti = 0;
phy_rnti = 0;
is_first_tx = true;
bsr_procedure.init(log_h, &timers_db, &params_db, &mac_io_lch);
mux_unit.init(log_h, &mac_io_lch, &bsr_procedure);
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);
sr_procedure.init(log_h, &params_db, phy_h);
is_first_of_burst = true;
reset();
bsr_procedure.init( rlc_h, log_h, &params_db, &timers_db);
mux_unit.init ( rlc_h, log_h, &bsr_procedure);
demux_unit.init (phy_h, rlc_h, log_h, &timers_db);
ra_procedure.init (phy_h, log_h, &params_db, &timers_db, &mux_unit, &demux_unit);
sr_procedure.init (phy_h, log_h, &params_db);
ul_harq.init ( log_h, &params_db, &timers_db, &mux_unit);
dl_harq.init ( log_h, &timers_db, &demux_unit);
for (int i=0;i<NOF_TTI_THREADS;i++) {
pthread_mutex_init(&tti_threads_sync_tx[i], NULL);
tti_threads_sync[i].set_increment(NOF_TTI_THREADS);
if (!tti_threads[i].init(this, &tti_threads_sync[i])) {
return false;
}
}
reset();
if (threads_new_rt_prio(&mac_thread, mac_thread_fnc, this, 1)) {
started = true;
}
start(MAC_THREAD_PRIO);
return started;
}
@ -80,20 +74,7 @@ bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
void mac::stop()
{
started = false;
pthread_join(mac_thread, NULL);
for (int i=0;i<NOF_TTI_THREADS;i++) {
tti_threads[i].stop();
pthread_mutex_destroy(&tti_threads_sync_tx[i]);
}
}
int mac::get_tti()
{
if (is_synchronized) {
return (int) tti;
} else {
return -1;
}
wait_thread_finish();
}
void mac::start_pcap(mac_pcap* pcap_)
@ -104,60 +85,6 @@ void mac::start_pcap(mac_pcap* pcap_)
ra_procedure.start_pcap(pcap);
}
void mac::start_trace()
{
tr_enabled = true;
}
void mac::write_trace(std::string filename)
{
tr_exec_total.writeToBinary(filename + ".total");
tr_exec_dl.writeToBinary(filename + ".dl");
tr_exec_ul.writeToBinary(filename + ".ul");
}
void mac::tr_log_start(uint32_t tti)
{
if (tr_enabled) {
gettimeofday(&tr_time_total[1], NULL);
}
}
void mac::tr_log_end(uint32_t tti)
{
if (tr_enabled) {
/* compute total execution time */
gettimeofday(&tr_time_total[2], NULL);
get_time_interval(tr_time_total);
tr_exec_total.push(tti, tr_time_total[0].tv_usec);
/* ul execution time is from the call to tr_log_ul */
memcpy(&tr_time_ul[2], &tr_time_total[2], sizeof(struct timeval));
get_time_interval(tr_time_ul);
tr_exec_ul.push(tti, tr_time_ul[0].tv_usec);
}
}
void mac::tr_log_ul(uint32_t tti)
{
if (tr_enabled) {
/* DL execution time is from the call to tr_log_dl to the call to tr_log_ul */
gettimeofday(&tr_time_dl[2], NULL);
get_time_interval(tr_time_dl);
tr_exec_dl.push(tti, tr_time_dl[0].tv_usec);
memcpy(&tr_time_ul[1], &tr_time_dl[2], sizeof(struct timeval));
}
}
void mac::tr_log_dl(uint32_t tti)
{
if (tr_enabled) {
gettimeofday(&tr_time_dl[1], NULL);
}
}
// Implement Section 5.8
void mac::reconfiguration()
{
@ -184,546 +111,187 @@ void mac::reset()
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;
phy_h->pdcch_dl_search_reset();
phy_h->pdcch_ul_search_reset();
params_db.set_param(mac_interface_params::BCCH_SI_WINDOW_ST, -1);
params_db.set_param(mac_interface_params::BCCH_SI_WINDOW_LEN, -1);
}
void mac::main_radio_loop() {
void mac::run_thread() {
setup_timers();
Info("Waiting PHY to synchronize with cell\n");
phy_h->sync_start();
while(!phy_h->get_current_tti()) {
usleep(50000);
}
ttisync.set_producer_cntr(phy_h->get_current_tti());
while(started) {
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);
if (pcap) {
pcap->write_dl_bch(bch_payload, SRSLTE_BCH_PAYLOAD_LEN/8, true, phy_h->get_current_tti());
}
// Init HARQ for this cell
Info("Init UL/DL HARQ\n");
ul_harq.init(cell, &params_db, log_h, &timers_db, &mux_unit);
dl_harq.init(cell, 1024*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()) {
log_h->step(ttisync->wait());
/* Warning: Here order of invocation of procedures is important!! */
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);
ttisync->resync();
Info("Wait for AGC, CFO estimation, etc. \n");
for (int i=0;i<1000;i++) {
tti = ttisync->wait();
}
for (int i=0;i<NOF_TTI_THREADS;i++) {
tti_threads_sync[i].set_producer_cntr(tti+i);
tti_threads_sync[i].resync();
}
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();
tr_log_start(tti);
log_h->step(tti);
// Step all procedures
bsr_procedure.step(tti);
// Check if BSR procedure need to start SR
if (bsr_procedure.need_to_send_sr()) {
Debug("Starting SR procedure by BSR request, PHY TTI=%d\n", phy_h->get_current_tti());
sr_procedure.start();
}
if (bsr_procedure.need_to_reset_sr()) {
Debug("Resetting SR procedure by BSR request\n");
sr_procedure.reset();
}
sr_procedure.step(tti);
// Check SR if we need to start RA
if (sr_procedure.need_random_access()) {
Warning("Starting RA procedure by MAC order is DISABLED\n");
//ra_procedure.start_mac_order();
}
ra_procedure.step(tti);
//phr_procedure.step(tti);
timers_db.step_all();
log_h->step(tti);
// Step all procedures
bsr_procedure.step(tti);
// Trigger execution of corresponding TTI processor thread
//printf("triggering tti=%d\n", tti);
tti_threads_sync[tti%NOF_TTI_THREADS].increase();
//tti_threads[0].run_tti(tti);
// Check if BSR procedure need to start SR
if (bsr_procedure.need_to_send_sr()) {
Debug("Starting SR procedure by BSR request, PHY TTI=%d\n", phy_h->get_current_tti());
sr_procedure.start();
}
}
}
if (bsr_procedure.need_to_reset_sr()) {
Debug("Resetting SR procedure by BSR request\n");
sr_procedure.reset();
}
sr_procedure.step(tti);
struct phy_crnti {
phy *phy_ptr;
log *log_h;
uint16_t crnti;
};
void *pregen_phy_thread(void *arg) {
struct phy_crnti *a = (struct phy_crnti*) arg;
a->log_h->info("Setting PHY RNTI=%d\n", a->crnti);
a->phy_ptr->set_crnti(a->crnti);
a->phy_ptr->pregen_signals();
a->log_h->info("Done Setting PHY RNTI\n");
free(a);
return NULL;
// Check SR if we need to start RA
if (sr_procedure.need_random_access()) {
Warning("Starting RA procedure by MAC order is DISABLED\n");
//ra_procedure.start_mac_order();
}
ra_procedure.step(tti);
//phr_procedure.step(tti);
timers_db.step_all();
search_si_rnti();
demux_unit.process_pdus();
}
}
void mac::pregen_phy(uint16_t phy_rnti)
void mac::search_si_rnti()
{
pthread_t rnti_thread;
struct phy_crnti *arg = (struct phy_crnti*) malloc(sizeof(struct phy_crnti));
arg->crnti = phy_rnti;
arg->phy_ptr = phy_h;
arg->log_h = log_h;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
if (pthread_create(&rnti_thread, &attr, pregen_phy_thread, arg)) {
perror("pthread_create");
// Reset PDCCH search
if (si_window_length >= 0 && si_window_start >= 0) {
if (tti >= si_window_start + si_window_length) {
phy_h->pdcch_dl_search_reset();
}
}
// Setup PDCCH search
int _si_window_start = params_db.get_param(mac_interface_params::BCCH_SI_WINDOW_ST);
int _si_window_length = params_db.get_param(mac_interface_params::BCCH_SI_WINDOW_LEN);
if (_si_window_length > 0 && _si_window_start >= 0) {
si_window_length = _si_window_length;
si_window_start = _si_window_start;
Debug("Searching for DL grant for SI-RNTI window_st=%d, window_len=%d\n", si_window_start, si_window_length);
phy_h->pdcch_dl_search(SRSLTE_RNTI_SI, 0xffff, si_window_start, si_window_length);
params_db.set_param(mac_interface_params::BCCH_SI_WINDOW_ST, -1);
params_db.set_param(mac_interface_params::BCCH_SI_WINDOW_LEN, -1);
}
}
void mac::add_sdu_handler(sdu_handler *handler) {
demux_unit.add_sdu_handler(handler);
}
void mac::setup_timers()
void mac::tti_clock(uint32_t tti)
{
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;
ttisync.increase();
}
void mac::timer_expired(uint32_t timer_id)
void mac::bch_decoded_ok(uint8_t* payload, uint32_t len)
{
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);
// Send MIB to RRC
rlc_h->write_pdu_bcch_bch(payload, len);
// 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) {
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 && last_temporal_crnti != params_db.get_param(i)) {
ue_grant.set_ndi(true);
Info("Set NDI=1 for Temp-RNTI DL grant\n");
last_temporal_crnti = params_db.get_param(i);
}
if (i == mac_params::RNTI_C && dl_harq.is_sps(harq_pid)) {
ue_grant.set_ndi(true);
Info("Set NDI=1 for C-RNTI DL grant\n");
}
dl_harq.set_harq_info(harq_pid, &ue_grant);
dl_harq.receive_data(tti, harq_pid, dl_buffer, phy_h);
} else {
/* This is for SPS scheduling */
uint32_t harq_pid = get_harq_sps_pid(tti);
if (ue_grant.get_ndi()) {
ue_grant.set_ndi(false);
dl_harq.set_harq_info(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(harq_pid, &ue_grant);
}
}
}
}
}
if (pcap) {
pcap->write_dl_bch(payload, len, true, phy_h->get_current_tti());
}
/* 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(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))
{
Debug("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(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);
}
}
}
}
/* UL Grant reception and processin as defined in Section 5.4.1 in 36.321 */
bool 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 (ul_grant.is_from_rar()) {
dl_buffer->discard_pending_rar_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);
return true;
}
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 true;
}
}
}
}
}
}
/* 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 true;
}
}
ul_harq.run_tti(tti, phy_h);
return false;
void mac::harq_recv(uint32_t tti, bool ack, mac_interface_phy::tb_action_ul_t* action)
{
ul_harq.harq_recv(tti, ack, action);
}
int mac::recv_sdu(uint32_t lcid, uint8_t* sdu_payload, uint32_t nbytes)
void mac::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action)
{
if (lcid <= mac_io::MAC_LCH_PCCH_DL) {
return mac_io_lch.get(lcid)->recv(sdu_payload, nbytes);
if (grant.rnti_type == SRSLTE_RNTI_RAR) {
ra_procedure.new_grant_dl(grant, action);
} else {
Error("Receiving SDU: Invalid lcid=%d\n", lcid);
return -1;
dl_harq.new_grant_dl(grant, action);
}
}
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)
uint32_t mac::get_current_tti()
{
return mac_io_lch.get(mac_io::MAC_LCH_CCCH_DL)->recv(sdu_payload, buffer_len_nbytes);
return phy_h->get_current_tti();
}
int mac::recv_dtch0_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
void mac::new_grant_ul(mac_interface_phy::mac_grant_t grant, uint8_t* payload_ptr,
mac_interface_phy::tb_action_ul_t* action)
{
return mac_io_lch.get(mac_io::MAC_LCH_DTCH0_DL)->recv(sdu_payload, buffer_len_nbytes);
ul_harq.new_grant_ul(grant, payload_ptr, action);
}
int mac::recv_dcch0_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
void mac::new_grant_ul_ack(mac_interface_phy::mac_grant_t grant, uint8_t* payload_ptr, bool ack,
mac_interface_phy::tb_action_ul_t* action)
{
return mac_io_lch.get(mac_io::MAC_LCH_DCCH0_DL)->recv(sdu_payload, buffer_len_nbytes);
ul_harq.new_grant_ul_ack(grant, payload_ptr, ack, action);
}
bool mac::send_sdu(uint32_t lcid, uint8_t* sdu_payload, uint32_t nbytes)
void mac::tb_decoded_ok(uint32_t harq_pid)
{
lcid += mac_io::MAC_LCH_CCCH_UL;
if (lcid <= mac_io::MAC_LCH_DTCH2_UL) {
return mac_io_lch.get(lcid)->send(sdu_payload, nbytes);
if (ra_procedure.in_progress()) {
ra_procedure.tb_decoded_ok();
} else {
Error("Receiving SDU: Invalid lcid=%d\n", lcid);
return -1;
dl_harq.tb_decoded_ok(harq_pid);
}
}
bool mac::send_ccch_sdu(uint8_t* sdu_payload, uint32_t nbytes)
void mac::setup_timers()
{
return mac_io_lch.get(mac_io::MAC_LCH_CCCH_UL)->send(sdu_payload, nbytes);
if (params_db.get_param(mac_interface_params::TIMER_TIMEALIGN) > 0) {
timers_db.get(TIME_ALIGNMENT)->set(this, params_db.get_param(mac_interface_params::TIMER_TIMEALIGN));
}
}
bool mac::send_dtch0_sdu(uint8_t* sdu_payload, uint32_t nbytes)
void mac::timer_expired(uint32_t timer_id)
{
return mac_io_lch.get(mac_io::MAC_LCH_DTCH0_UL)->send(sdu_payload, nbytes);
switch(timer_id) {
case TIME_ALIGNMENT:
timeAlignmentTimerExpire();
break;
default:
break;
}
}
bool mac::send_dcch0_sdu(uint8_t* sdu_payload, uint32_t nbytes)
/* Function called on expiry of TimeAlignmentTimer */
void mac::timeAlignmentTimerExpire()
{
return mac_io_lch.get(mac_io::MAC_LCH_DCCH0_UL)->send(sdu_payload, nbytes);
dl_harq.reset();
ul_harq.reset();
}
void mac::set_param(mac_params::mac_param_t param, int64_t value)
void mac::set_param(mac_interface_params::mac_param_t param, int64_t value)
{
params_db.set_param((uint32_t) param, value);
}
int64_t mac::get_param(mac_params::mac_param_t param)
int64_t mac::get_param(mac_interface_params::mac_param_t param)
{
return params_db.get_param((uint32_t) param);
}
void mac::setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD)
{
Info("Logical Channel Setup: LCID=%d, LCG=%d, priority=%d, PBR=%d, BSd=%d\n", lcid, lcg, priority, PBR_x_tti, BSD);
Info("Logical Channel Setup: LCID=%d, LCG=%d, priority=%d, PBR=%d, BSd=%d\n",
lcid, lcg, priority, PBR_x_tti, BSD);
mux_unit.set_priority(lcid, priority, PBR_x_tti, BSD);
bsr_procedure.setup_lcg(lcid, lcg);
bsr_procedure.set_priority(lcid, priority);
}
void* tti_thread_runner(void *arg) {
mac::tti_thread* x = (mac::tti_thread*) arg;
x->run();
return NULL;
}
bool mac::tti_thread::init(mac* parent_, tti_sync_cv *sync_)
{
parent = parent_;
log_h = parent->log_h;
sync = sync_;
started = threads_new_rt(&thread, tti_thread_runner, this);
return started;
}
void mac::tti_thread::stop()
{
started = false;
pthread_join(thread, NULL);
}
void mac::tti_thread::run()
{
while(started) {
uint32_t tti = sync->wait();
if (parent->is_synchronized) {
run_tti((tti+1)%10240);
}
}
}
void mac::tti_thread::run_tti(uint32_t tti) {
//printf("running tti=%d\n", tti);
// Receive PCH, if requested
parent->receive_pch(tti);
// Process DL grants always
parent->process_dl_grants(tti);
// Send pending HARQ ACK, if any, and contention resolution is resolved
if (parent->dl_harq.is_ack_pending_resolution()) {
parent->ra_procedure.step(tti);
if (parent->ra_procedure.is_successful() || parent->ra_procedure.is_response_error()) {
Info("Sending pending ACK for contention resolution PHY TTI: %d\n", parent->phy_h->get_current_tti());
parent->dl_harq.send_pending_ack_contention_resolution();
}
}
// Process UL grants if RA procedure is done or in contention resolution
if (parent->ra_procedure.is_contention_resolution() || parent->ra_procedure.is_successful()) {
parent->process_ul_grants(tti);
}
// If ACK/SR was pending but there was no PUSCH transmission, transmit now through PUCCH
ul_buffer *ul_buffer = parent->phy_h->get_ul_buffer(tti+4);
// Generate scheduling request if we have to
if (parent->phy_h->sr_is_ready_to_send(tti+4)) {
ul_buffer->generate_sr();
}
// If the packet was not generated by an UL grant, means it's PUCCH or SRS. Generate now the signal
if (!ul_buffer->is_released() && (ul_buffer->uci_ready() || ul_buffer->srs_is_ready_to_send())) {
ul_buffer->generate_data();
}
// Wait for previous TTI to be transmitted
if (!parent->is_first_tx) {
pthread_mutex_lock(&parent->tti_threads_sync_tx[tti%parent->NOF_TTI_THREADS]);
}
parent->is_first_tx = false;
// Send now to the radio
if (ul_buffer->is_released()) {
ul_buffer->send();
ul_buffer->ready();
parent->is_first_of_burst = false;
} else {
if (!parent->is_first_of_burst) {
ul_buffer->send_end_of_burst();
parent->is_first_of_burst = true;
}
}
// Allow next TTI to be transmitted
pthread_mutex_unlock(&parent->tti_threads_sync_tx[(tti+1)%parent->NOF_TTI_THREADS]);
// Check if there is pending CCCH SDU in Multiplexing Unit
if (parent->mux_unit.is_pending_ccch_sdu()) {
// Start RA procedure
if (!parent->ra_procedure.in_progress() && !parent->ra_procedure.is_successful()) {
parent->ra_procedure.start_rlc_order();
}
}
if (parent->ra_procedure.is_successful() &&
parent->phy_rnti != parent->params_db.get_param(mac_params::RNTI_C) &&
parent->params_db.get_param(mac_params::RNTI_C) > 0 &&
parent->phy_h->get_param(srslte::ue::phy_params::SRS_IS_CONFIGURED) == 1)
{
parent->phy_rnti = parent->params_db.get_param(mac_params::RNTI_C);
parent->pregen_phy(parent->phy_rnti);
}
}
}
}

@ -55,23 +55,18 @@ void mac_pcap::pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reT
uint16_t crnti, uint8_t direction, uint8_t rnti_type)
{
if (enable_write) {
if (pdu_len_bytes < max_pdu_len) {
MAC_Context_Info_t context =
{
FDD_RADIO, direction, rnti_type,
crnti, /* RNTI */
ue_id, /* UEId */
reTX, /* Retx */
crc_ok, /* CRC Stsatus (i.e. OK) */
tti/10, /* Sysframe number */
tti%10 /* Subframe number */
};
if (pdu) {
srslte_bit_unpack_vector(pdu, pdu_pcap_tmp, pdu_len_bytes*8);
MAC_LTE_PCAP_WritePDU(pcap_file, &context, pdu_pcap_tmp, pdu_len_bytes);
}
} else {
fprintf(stderr, "MAC PCAP: PDU len %d exceeds maximum allowed length (%d bytes)\n", pdu_len_bytes, max_pdu_len);
MAC_Context_Info_t context =
{
FDD_RADIO, direction, rnti_type,
crnti, /* RNTI */
ue_id, /* UEId */
reTX, /* Retx */
crc_ok, /* CRC Stsatus (i.e. OK) */
tti/10, /* Sysframe number */
tti%10 /* Subframe number */
};
if (pdu) {
MAC_LTE_PCAP_WritePDU(pcap_file, &context, pdu, pdu_len_bytes);
}
}
}

@ -32,18 +32,14 @@
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(mac::NOF_TTI_THREADS, MSG3_BUFF_SZ);
pdu_buff.init(mac::NOF_TTI_THREADS, PDU_BUFF_SZ);
bzero(nof_tx_pkts, sizeof(uint32_t) * mac_io::NOF_UL_LCH);
msg3_buff.init(1, MSG3_BUFF_SZ);
pthread_mutex_init(&mutex, NULL);
msg3_has_been_transmitted = false;
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
for (int i=0;i<NOF_UL_LCH;i++) {
priority[i] = i;
priority_sorted[i] = i;
PBR[i] = -1; // -1 is infinite
@ -52,16 +48,16 @@ mux::mux() : pdu_msg(20)
}
}
void mux::init(log *log_h_, mac_io *mac_io_h_, bsr_proc *bsr_procedure_)
void mux::init(rlc_interface_mac *rlc_, log *log_h_, bsr_proc *bsr_procedure_)
{
log_h = log_h_;
mac_io_h = mac_io_h_;
rlc = rlc_;
bsr_procedure = bsr_procedure_;
}
void mux::reset()
{
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
for (int i=0;i<NOF_UL_LCH;i++) {
Bj[i] = 0;
}
}
@ -73,8 +69,8 @@ bool mux::is_pending_ccch_sdu()
bool mux::is_pending_any_sdu()
{
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
if (!mac_io_h->get(i)->isempty()) {
for (int i=0;i<NOF_UL_LCH;i++) {
if (rlc->get_buffer_state(i)) {
return true;
}
}
@ -82,30 +78,27 @@ bool mux::is_pending_any_sdu()
}
bool mux::is_pending_sdu(uint32_t lch_id) {
lch_id += (uint32_t) mac_io::MAC_LCH_CCCH_UL;
if (lch_id < mac_io::MAC_NOF_QUEUES) {
return !mac_io_h->get(lch_id)->isempty();
}
return rlc->get_buffer_state(lch_id)>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) {
if (lch_id < 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) {
while(set_priority > priority_sorted[new_index] && new_index < NOF_UL_LCH) {
new_index++;
}
int old_index = 0;
while(lch_id != lchid_sorted[old_index] && new_index < mac_io::NOF_UL_LCH) {
while(lch_id != lchid_sorted[old_index] && new_index < NOF_UL_LCH) {
old_index++;
}
if (new_index == mac_io::NOF_UL_LCH) {
if (new_index == NOF_UL_LCH) {
Error("Can't find LchID=%d in sorted list\n", lch_id);
return;
}
@ -122,56 +115,6 @@ void mux::set_priority(uint32_t lch_id, uint32_t set_priority, int set_PBR, uint
}
void mux::pdu_release()
{
pdu_buff.release();
pthread_mutex_unlock(&mutex);
}
bool mux::pdu_move_to_msg3(uint32_t pdu_sz)
{
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 pdu_sz)
{
// Acquire mutex. Will be released after a call to pdu_release
pthread_mutex_lock(&mutex);
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;
}
sch_subh::cetype bsr_format_convert(bsr_proc::bsr_format_t format) {
switch(format) {
case bsr_proc::LONG_BSR:
@ -179,24 +122,21 @@ sch_subh::cetype bsr_format_convert(bsr_proc::bsr_format_t format) {
case bsr_proc::SHORT_BSR:
return sch_subh::SHORT_BSR;
case bsr_proc::TRUNC_BSR:
return sch_subh::TRUNC_BSR;
return sch_subh::TRUNC_BSR;
}
}
int pkt_num=0;
bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
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_nbits = 8*(pdu_sz_nbits/8);
int pkt_num = 0;
// Multiplexing and logical channel priorization as defined in Section 5.4.3
bool mux::pdu_get(uint8_t *payload, uint32_t pdu_sz)
{
pthread_mutex_lock(&mutex);
// Update Bj
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
for (int i=0;i<NOF_UL_LCH;i++) {
// Add PRB unless it's infinity
if (PBR[i] >= 0) {
Bj[i] += PBR[i];
@ -207,16 +147,14 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
}
// Logical Channel Procedure
uint32_t sdu_sz = 0;
pdu_msg.init(pdu_sz_nbits/8, true);
pdu_msg.init(pdu_sz, true);
// MAC control element for C-RNTI or data from UL-CCCH
bool is_first = true;
if (!allocate_sdu(UL_IDX(mac_io::MAC_LCH_CCCH_UL), &pdu_msg, &is_first)) {
if (!allocate_sdu(0, &pdu_msg, &is_first)) {
if (pending_crnti_ce) {
if (pdu_msg.new_subh()) {
if (pdu_msg.new_subh()) {http://moodycamel.com/blog/2014/detailed-design-of-a-lock-free-queue
pdu_msg.next();
if (!pdu_msg.get()->set_c_rnti(pending_crnti_ce)) {
Warning("Pending C-RNTI CE could not be inserted in MAC PDU\n");
@ -250,29 +188,25 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
// 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, &is_first);
if (res && PBR[i] >= 0) {
Bj[i] -= sdu_sz;
uint32_t sdu_sz = 0;
for (int i=0;i<NOF_UL_LCH;i++) {
uint32_t lcid = lchid_sorted[i];
if (lcid != 0) {
bool res = true;
while ((Bj[lcid] > 0 || PBR[lcid] < 0) && res) {
res = allocate_sdu(lcid, &pdu_msg, Bj[lcid], &sdu_sz, &is_first);
if (res && PBR[lcid] >= 0) {
Bj[lcid] -= sdu_sz;
}
}
}
}
// If resources remain, allocate regardless of their Bj value
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
for (int i=0;i<NOF_UL_LCH;i++) {
while (allocate_sdu(lchid_sorted[i], &pdu_msg));
}
/* Release all 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]--;
}
}
bool send_bsr = bsr_procedure->generate_bsr_on_ul_grant(pdu_msg.rem_size(), &bsr);
// Insert Padding BSR if not inserted Regular/Periodic BSR
if (!bsr_payload_sz && send_bsr) {
@ -287,55 +221,58 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
bsr_subh->set_bsr(bsr.buff_size, bsr_format_convert(bsr.format), bsr_payload_sz?false:true);
}
Debug("Assembled MAC PDU msg size %d/%d bytes\n", pdu_msg.size(), pdu_sz_nbits/8);
//pdu_msg.fprint(stdout);
Debug("Assembled MAC PDU msg size %d/%d bytes\n", pdu_msg.size(), pdu_sz);
pthread_mutex_unlock(&mutex);
/* Generate MAC PDU and save to buffer */
if (pdu_msg.write_packet(buff)) {
pdu_buff.push(pdu_sz_nbits);
} else {
if (!pdu_msg.write_packet(payload, rlc)) {
Error("Writing PDU message to packet\n");
return false;
}
return true;
} else {
return true;
}
}
void mux::append_crnti_ce_next_tx(uint16_t crnti) {
pending_crnti_ce = crnti;
}
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg)
{
return allocate_sdu(lcid, pdu_msg, NULL, NULL);
return allocate_sdu(lcid, pdu_msg, -1, NULL, NULL);
}
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, bool *is_first)
{
return allocate_sdu(lcid, pdu_msg, NULL, is_first);
return allocate_sdu(lcid, pdu_msg, -1, NULL, is_first);
}
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, uint32_t *sdu_sz, bool *is_first)
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, int max_sdu_sz, uint32_t *sdu_sz, bool *is_first)
{
// Get n-th pending SDU pointer and length
uint32_t buff_len = 0;
uint8_t *buff_ptr = (uint8_t*) mac_io_h->get(mac_io::MAC_LCH_CCCH_UL + lcid)->pop(&buff_len, nof_tx_pkts[lcid]);
uint32_t nbytes = (buff_len-1)/8 + 1;
uint32_t sdu_len = rlc->get_buffer_state(lcid);
if (buff_ptr && buff_len > 0) { // there is pending SDU to allocate
if (sdu_sz) {
*sdu_sz = buff_len;
if (sdu_len > 0) { // there is pending SDU to allocate
if (sdu_len > max_sdu_sz && max_sdu_sz >= 0) {
sdu_len = max_sdu_sz;
}
if (sdu_len > pdu_msg->rem_size() - pdu_msg->size_plus_header_sdu(sdu_len)) {
sdu_len = pdu_msg->rem_size() - pdu_msg->size_plus_header_sdu(sdu_len);
}
if (pdu_msg->new_subh()) { // there is space for a new subheader
pdu_msg->next();
if (pdu_msg->get()->set_sdu(lcid, buff_ptr, nbytes, is_first?*is_first:false)) { // new SDU could be added
if (pdu_msg->get()->set_sdu(lcid, sdu_len, is_first?*is_first:false)) { // new SDU could be added
if (is_first) {
*is_first = false;
}
Info("Allocated SDU lcid=%d nbytes=%d\n", lcid, nbytes);
// Increase number of pop'ed packets from queue
nof_tx_pkts[lcid]++;
if (sdu_sz) {
*sdu_sz = sdu_len;
}
Info("Allocated SDU lcid=%d nbytes=%d\n", lcid, sdu_len);
return true;
} else {
if (pdu_msg->rem_size() > 10) {
Info("Could not allocate SDU in current grant. SDU length: %d bytes. Grant space: %d bytes\n", nbytes,
pdu_msg->rem_size());
}
Error("Could not add SDU rem_size=%d, sdu_len=%d\n", pdu_msg->rem_size(), sdu_len);
pdu_msg->del_subh();
}
}
@ -343,8 +280,6 @@ bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, uint32_t *sdu_sz, bool *
return false;
}
void mux::msg3_flush()
{
msg3_buff.flush();
@ -361,23 +296,37 @@ bool mux::msg3_is_transmitted()
return msg3_has_been_transmitted;
}
/* Returns a pointer to the Msg3 buffer */
uint8_t* mux::msg3_pop(uint32_t TB_size)
bool mux::pdu_move_to_msg3(uint32_t pdu_sz)
{
uint32_t len;
uint8_t *msg3 = (uint8_t*) msg3_buff.pop(&len);
uint8_t *msg3 = (uint8_t*) msg3_buff.request();
if (msg3) {
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;
}
}
if (pdu_get(msg3, pdu_sz)) {
msg3_buff.push(pdu_sz);
return true;
} else {
Error("Assembling PDU\n");
}
} else {
Error("Generating PDU: PDU pending in buffer for transmission\n");
}
return false;
}
/* Returns a pointer to the Msg3 buffer */
bool mux::msg3_get(uint8_t *payload, uint32_t pdu_sz)
{
if (pdu_move_to_msg3(pdu_sz)) {
uint8_t *msg3 = (uint8_t*) msg3_buff.pop();
if (msg3) {
memcpy(payload, msg3, sizeof(uint8_t)*pdu_sz);
msg3_buff.release();
return true;
} else {
Error("Generating Msg3\n");
}
}
return msg3;
return false;
}

@ -104,7 +104,7 @@ void sch_pdu::parse_packet(uint8_t *ptr)
}
// Section 6.1.2
bool sch_pdu::write_packet(uint8_t* ptr)
bool sch_pdu::write_packet(uint8_t* ptr, rlc_interface_mac *rlc)
{
uint8_t *init_ptr = ptr;
bool last_is_padding = false;
@ -159,16 +159,16 @@ bool sch_pdu::write_packet(uint8_t* ptr)
// Write payloads in the same order
for (int i=0;i<nof_subheaders;i++) {
if (!subheaders[i].is_sdu()) {
subheaders[i].write_payload(&ptr);
subheaders[i].write_payload(&ptr, rlc);
}
}
for (int i=0;i<nof_subheaders;i++) {
if (subheaders[i].is_sdu()) {
subheaders[i].write_payload(&ptr);
subheaders[i].write_payload(&ptr, rlc);
}
}
// Set paddint to zeros (if any)
bzero(ptr, rem_len*sizeof(uint8_t)*8);
bzero(ptr, rem_len*sizeof(uint8_t));
return true;
}
@ -235,8 +235,8 @@ void sch_subh::init()
{
lcid = 0;
nof_bytes = 0;
sdu_payload_ptr = NULL;
bzero(ce_payload, sizeof(uint8_t) * MAX_CE_PAYLOAD_LEN);
payload = NULL;
bzero(payload, sizeof(uint8_t) * MAX_CE_PAYLOAD_LEN);
}
sch_subh::cetype sch_subh::ce_type()
@ -296,29 +296,36 @@ bool sch_subh::is_sdu()
}
uint16_t sch_subh::get_c_rnti()
{
uint8_t *ptr = ce_payload;
uint16_t ret = (uint16_t) srslte_bit_unpack(&ptr, 16);
return ret;
if (payload) {
return (uint16_t) payload[0] | payload[1]<<8;
} else {
return 0;
}
}
uint64_t sch_subh::get_con_res_id()
{
uint8_t *ptr = ce_payload;
uint64_t ret = (uint64_t) srslte_bit_unpack_l(&ptr, 48);
return ret;
if (payload) {
return ((uint64_t) payload[0]) | ((uint64_t) payload[1])<<8 | ((uint64_t) payload[2])<<16 | ((uint64_t) payload[3])<<24 |
((uint64_t) payload[4])<<32 | ((uint64_t) payload[5])<<48;
} else {
return 0;
}
}
uint8_t sch_subh::get_phd()
{
uint8_t *ptr = ce_payload;
ptr += 2;
uint8_t ret = (uint8_t) srslte_bit_unpack(&ptr, 6);
return ret;
if (payload) {
return (uint8_t) payload[0]&0x3f;
} else {
return 0;
}
}
uint8_t sch_subh::get_ta_cmd()
{
uint8_t *ptr = ce_payload;
ptr += 2;
uint8_t ret = (uint8_t) srslte_bit_unpack(&ptr, 6);
return ret;
if (payload) {
return (uint8_t) payload[0]&0x3f;
} else {
return 0;
}
}
uint32_t sch_subh::get_sdu_lcid()
{
@ -330,7 +337,7 @@ uint32_t sch_subh::get_sdu_nbytes()
}
uint8_t* sch_subh::get_sdu_ptr()
{
return sdu_payload_ptr;
return payload;
}
void sch_subh::set_padding(uint32_t padding_len)
{
@ -353,16 +360,12 @@ bool sch_subh::set_bsr(uint32_t buff_size[4], sch_subh::cetype format, bool upda
}
uint32_t ce_size = format==LONG_BSR?3:1;
if (((sch_pdu*)parent)->has_space_ce(ce_size) || !update_size) {
uint8_t *ptr = ce_payload;
if (format==LONG_BSR) {
bzero(ce_payload, 3*8*sizeof(uint8_t));
for (int i=0;i<4;i++) {
srslte_bit_pack(buff_size_table(buff_size[i]), &ptr, 6);
}
w_payload_ce[0] = (buff_size_table(buff_size[0])&0x3f) << 2 | (buff_size_table(buff_size[1])&0xc0)>>6;
w_payload_ce[1] = (buff_size_table(buff_size[1])&0xf) << 4 | (buff_size_table(buff_size[2])&0xf0)>>4;
w_payload_ce[2] = (buff_size_table(buff_size[2])&0x3) << 6 | (buff_size_table(buff_size[3])&0x3f);
} else {
bzero(ce_payload, 8*sizeof(uint8_t));
srslte_bit_pack(nonzero_lcg, &ptr, 2);
srslte_bit_pack(buff_size_table(buff_size[nonzero_lcg]), &ptr, 6);
w_payload_ce[0] = (nonzero_lcg&0x3)<<6 | buff_size_table(buff_size[nonzero_lcg])&0x3f;
}
lcid = format;
if (update_size) {
@ -377,11 +380,9 @@ bool sch_subh::set_bsr(uint32_t buff_size[4], sch_subh::cetype format, bool upda
bool sch_subh::set_c_rnti(uint16_t crnti)
{
if (((sch_pdu*)parent)->has_space_ce(2)) {
*((uint16_t*) ce_payload) = crnti;
w_payload_ce[0] = (uint8_t) (crnti&0xff00)>>8;
w_payload_ce[1] = (uint8_t) (crnti&0x00ff);
lcid = C_RNTI;
uint8_t *ptr = ce_payload;
srslte_bit_pack(crnti, &ptr, 16);
((sch_pdu*)parent)->update_space_ce(2);
return true;
} else {
@ -391,8 +392,12 @@ bool sch_subh::set_c_rnti(uint16_t crnti)
bool sch_subh::set_con_res_id(uint64_t con_res_id)
{
if (((sch_pdu*)parent)->has_space_ce(6)) {
uint8_t *ptr = ce_payload;
srslte_bit_pack_l(con_res_id, &ptr, 48);
w_payload_ce[0] = (uint8_t) ((con_res_id&0xff0000000000)>>48);
w_payload_ce[1] = (uint8_t) ((con_res_id&0x00ff00000000)>>32);
w_payload_ce[2] = (uint8_t) ((con_res_id&0x0000ff000000)>>24);
w_payload_ce[3] = (uint8_t) ((con_res_id&0x000000ff0000)>>16);
w_payload_ce[4] = (uint8_t) ((con_res_id&0x00000000ff00)>>8);
w_payload_ce[5] = (uint8_t) ((con_res_id&0x0000000000ff));
lcid = CON_RES_ID;
((sch_pdu*)parent)->update_space_ce(6);
return true;
@ -403,9 +408,7 @@ bool sch_subh::set_con_res_id(uint64_t con_res_id)
bool sch_subh::set_phd(uint8_t phd)
{
if (((sch_pdu*)parent)->has_space_ce(1)) {
uint8_t *ptr = ce_payload;
srslte_bit_pack(0, &ptr, 2);
srslte_bit_pack(phd, &ptr, 6);
w_payload_ce[0] = phd&0x3f;
lcid = PHD_REPORT;
((sch_pdu*)parent)->update_space_ce(1);
return true;
@ -414,15 +417,26 @@ bool sch_subh::set_phd(uint8_t phd)
}
}
bool sch_subh::set_sdu(uint32_t lcid_, uint8_t* ptr, uint32_t nof_bytes_)
bool sch_subh::set_ta_cmd(uint8_t ta_cmd)
{
if (((sch_pdu*)parent)->has_space_ce(1)) {
w_payload_ce[0] = ta_cmd&0x3f;
lcid = TA_CMD;
((sch_pdu*)parent)->update_space_ce(1);
return true;
} else {
return false;
}
}
bool sch_subh::set_sdu(uint32_t lcid_, uint32_t nof_bytes_)
{
return set_sdu(lcid_, ptr, nof_bytes_, false);
return set_sdu(lcid_, nof_bytes_, false);
}
bool sch_subh::set_sdu(uint32_t lcid_, uint8_t* ptr, uint32_t nof_bytes_, bool is_first)
bool sch_subh::set_sdu(uint32_t lcid_, uint32_t nof_bytes_, bool is_first)
{
if (((sch_pdu*)parent)->has_space_sdu(nof_bytes_, is_first)) {
sdu_payload_ptr = ptr;
nof_bytes = nof_bytes_;
lcid = lcid_;
((sch_pdu*)parent)->update_space_sdu(nof_bytes_, is_first);
@ -431,62 +445,52 @@ bool sch_subh::set_sdu(uint32_t lcid_, uint8_t* ptr, uint32_t nof_bytes_, bool i
return false;
}
}
bool sch_subh::set_ta_cmd(uint8_t ta_cmd)
{
if (((sch_pdu*)parent)->has_space_ce(1)) {
uint8_t *ptr = ce_payload;
srslte_bit_pack(0, &ptr, 2);
srslte_bit_pack(ta_cmd, &ptr, 6);
lcid = TA_CMD;
((sch_pdu*)parent)->update_space_ce(1);
return true;
} else {
return false;
}
}
// Section 6.2.1
void sch_subh::write_subheader(uint8_t** ptr, bool is_last)
{
if (is_sdu()) {
// MAC SDU: R/R/E/LCID/F/L subheader
srslte_bit_pack(0, ptr, 2); // R, R
srslte_bit_pack(is_last?0:1, ptr, 1); // E
srslte_bit_pack(lcid, ptr, 5); // LCID
*(*ptr + 0) = (uint8_t) is_last<<5 | (lcid & 0x1f);
// 2nd and 3rd octet
if (!is_last) {
srslte_bit_pack(F_bit?1:0, ptr, 1); // F
srslte_bit_pack(nof_bytes, ptr, nof_bytes<128?7:15); // L
if (nof_bytes >= 128) {
*(*ptr + 1) = (uint8_t) 1<<7 | ((nof_bytes & 0x7f00) >> 8);
*(*ptr + 2) = (uint8_t) (nof_bytes & 0xff);
} else {
*(*ptr + 1) = (uint8_t) (nof_bytes & 0x7f);
}
}
} else {
// MAC CE: R/R/E/LCID MAC Subheader
srslte_bit_pack(0, ptr, 2); // R, R
srslte_bit_pack(is_last?0:1, ptr, 1); // E
srslte_bit_pack(lcid, ptr, 5); // LCID
*(*ptr + 0) = (uint8_t) is_last<<5 | (lcid & 0x1f);
}
}
void sch_subh::write_payload(uint8_t** ptr)
void sch_subh::write_payload(uint8_t** ptr, rlc_interface_mac *rlc)
{
uint8_t *src;
if (is_sdu()) {
src = sdu_payload_ptr;
// Read data from RLC interface
rlc->read_pdu(lcid, *ptr, nof_bytes);
} else {
nof_bytes = sizeof_ce(lcid, parent->is_ul());
src = ce_payload;
memcpy(*ptr, w_payload_ce, nof_bytes*sizeof(uint8_t));
}
memcpy(*ptr, src, nof_bytes*8*sizeof(uint8_t));
*ptr += nof_bytes*8;
*ptr += nof_bytes;
}
bool sch_subh::read_subheader(uint8_t** ptr)
{
// Skip R
*ptr += 2;
bool e_bit = srslte_bit_unpack(ptr, 1)?true:false;
lcid = srslte_bit_unpack(ptr, 5);
bool e_bit = (bool) *(*ptr + 0) & 0x20;
lcid = (uint8_t) *(*ptr + 0) & 0x1f;
if (is_sdu()) {
if (e_bit) {
F_bit = srslte_bit_unpack(ptr, 1)?true:false;
nof_bytes = srslte_bit_unpack(ptr, F_bit?15:7);
F_bit = (bool) *(*ptr + 1) & 0x80;
nof_bytes = (uint32_t)*(*ptr + 1) & 0x7f;
if (F_bit) {
nof_bytes = nof_bytes<<8 | (uint32_t) *(*ptr + 2) & 0xff;
}
} else {
nof_bytes = 0;
F_bit = 0;
@ -498,16 +502,34 @@ bool sch_subh::read_subheader(uint8_t** ptr)
}
void sch_subh::read_payload(uint8_t** ptr)
{
if (is_sdu()) {
sdu_payload_ptr = *ptr;
} else {
memcpy(ce_payload, *ptr, 8*nof_bytes*sizeof(uint8_t));
}
*ptr += nof_bytes*8;
payload = *ptr;
*ptr += nof_bytes;
}
// Table 6.1.3.1-1 Buffer size levels for BSR
uint32_t btable[61] = {
10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132,
1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4667, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304,
42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125};
uint8_t sch_subh::buff_size_table(uint32_t buffer_size) {
if (buffer_size == 0) {
return 0;
} else if (buffer_size > 150000) {
return 63;
} else {
for (int i=0;i<61;i++) {
if (buffer_size < btable[i]) {
return 1+i;
}
}
return 62;
}
}
@ -552,15 +574,12 @@ void rar_pdu::set_backoff(uint8_t bi)
}
// Section 6.1.5
bool rar_pdu::write_packet(uint8_t* ptr)
bool rar_pdu::write_packet(uint8_t* ptr, rlc_interface_mac *rlc)
{
// Write Backoff Indicator, if any
if (has_backoff_indicator) {
if (nof_subheaders > 0) {
srslte_bit_pack(1, &ptr, 1); // E
srslte_bit_pack(0, &ptr, 1); // T
srslte_bit_pack(0, &ptr, 2); // R, R
srslte_bit_pack(backoff_indicator, &ptr, 4);
*(ptr) = 1<<7 | backoff_indicator&0xf;
}
}
// Write RAR subheaders
@ -569,10 +588,10 @@ bool rar_pdu::write_packet(uint8_t* ptr)
}
// Write payload
for (int i=0;i<nof_subheaders;i++) {
subheaders[i].write_payload(&ptr);
subheaders[i].write_payload(&ptr, rlc);
}
// Set paddint to zeros (if any)
bzero(ptr, rem_len*sizeof(uint8_t)*8);
bzero(ptr, rem_len*sizeof(uint8_t));
return true;
}
@ -620,63 +639,45 @@ void rar_subh::set_temp_crnti(uint16_t temp_rnti_)
// Section 6.2.2
void rar_subh::write_subheader(uint8_t** ptr, bool is_last)
{
srslte_bit_pack(is_last?0:1, ptr, 1); // E
srslte_bit_pack(1, ptr, 1); // T
srslte_bit_pack(preamble, ptr, 6); // RAPID
*(*ptr + 0) = (uint8_t) (is_last<<7 | 1<<6 | preamble & 0x3f);
}
// Section 6.2.3
void rar_subh::write_payload(uint8_t** ptr)
void rar_subh::write_payload(uint8_t** ptr, rlc_interface_mac *rlc)
{
srslte_bit_pack(0, ptr, 1); // R
srslte_bit_pack(ta, ptr, 11); // Timing Adv Cmd
memcpy(*ptr, grant, 20*sizeof(uint8_t)); // UL grant
*ptr += 20;
srslte_bit_pack(temp_rnti, ptr, 16); // Temp C-RNTI
*(*ptr + 0) = (uint8_t) (ta&0x7f0)>>4;
*(*ptr + 1) = (uint8_t) (ta&0xf) <<4 | grant[0]<<3 | grant[1] << 2 | grant[2] << 1 | grant[3];
uint8_t *x = &grant[4];
*(*ptr + 2) = (uint8_t) srslte_bit_unpack(&x, 8);
*(*ptr + 3) = (uint8_t) srslte_bit_unpack(&x, 8);
*(*ptr + 4) = (uint8_t) ((temp_rnti&0xff00) >> 8);
*(*ptr + 5) = (uint8_t) (temp_rnti&0x00ff);
}
void rar_subh::read_payload(uint8_t** ptr)
{
*ptr += 1; // R
ta = srslte_bit_unpack(ptr, 11); // Timing Adv Cmd
memcpy(grant, *ptr, 20*sizeof(uint8_t)); // UL Grant
*ptr += 20;
temp_rnti = srslte_bit_unpack(ptr, 16); // Temp C-RNTI
ta = *(*ptr + 0)&0x7f << 4 | (*(*ptr + 1)&0xf0)>>4;
grant[0] = *(*ptr + 1)&0x8;
grant[1] = *(*ptr + 1)&0x4;
grant[2] = *(*ptr + 1)&0x2;
grant[3] = *(*ptr + 1)&0x1;
uint8_t *x = &grant[4];
srslte_bit_pack(*(*ptr+2), &x, 8);
srslte_bit_pack(*(*ptr+3), &x, 8);
temp_rnti = *(*ptr + 4)<<8 | *(*ptr + 5);
}
bool rar_subh::read_subheader(uint8_t** ptr)
{
bool e_bit = srslte_bit_unpack(ptr, 1); // E
bool type = srslte_bit_unpack(ptr, 1); // T
bool e_bit = *(*ptr + 0) & 0x80;
bool type = *(*ptr + 0) & 0x40;
if (type) {
preamble = srslte_bit_unpack(ptr, 6); // RAPID
preamble = *(*ptr + 0) & 0x3f;
} else {
// Read Backoff
*ptr += 2; // R, R
((rar_pdu*)parent)->set_backoff((uint8_t) srslte_bit_unpack(ptr, 4));
((rar_pdu*)parent)->set_backoff(*(*ptr + 0) & 0xf);
}
return e_bit;
}
// Table 6.1.3.1-1 Buffer size levels for BSR
uint32_t btable[61] = {
10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132,
1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4667, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304,
42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125};
uint8_t sch_subh::buff_size_table(uint32_t buffer_size) {
if (buffer_size == 0) {
return 0;
} else if (buffer_size > 150000) {
return 63;
} else {
for (int i=0;i<61;i++) {
if (buffer_size < btable[i]) {
return 1+i;
}
}
return 62;
}
}
}
}

@ -26,7 +26,6 @@
*/
#include "srsapps/ue/mac/proc_bsr.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/mux.h"
@ -48,11 +47,11 @@ bsr_proc::bsr_proc()
triggered_bsr_type=NONE;
}
void bsr_proc::init(log* log_h_, timers *timers_db_, mac_params* params_db_, mac_io *mac_io_h_)
void bsr_proc::init(rlc_interface_mac *rlc_, log* log_h_, mac_params* params_db_, timers *timers_db_)
{
log_h = log_h_;
rlc = rlc_;
params_db = params_db_;
mac_io_h = mac_io_h_;
timers_db = timers_db_;
initiated = true;
}
@ -85,12 +84,12 @@ void bsr_proc::timer_expired(uint32_t timer_id) {
bool bsr_proc::check_highest_channel() {
int pending_data_lcid = -1;
for (int i=0;i<mac_io::NOF_UL_LCH && pending_data_lcid == -1;i++) {
for (int i=0;i<MAX_LCID && pending_data_lcid == -1;i++) {
if (lcg[i] >= 0) {
if (!mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->isempty()) {
if (rlc->get_buffer_state(i) > 0) {
pending_data_lcid = i;
for (int j=0;j<mac_io::NOF_UL_LCH;j++) {
if (!mac_io_h->get(j+mac_io::MAC_LCH_CCCH_UL)->isempty()) {
for (int j=0;j<MAX_LCID;j++) {
if (rlc->get_buffer_state(j) > 0) {
if (priorities[j] > priorities[i]) {
pending_data_lcid = -1;
}
@ -101,7 +100,7 @@ bool bsr_proc::check_highest_channel() {
}
if (pending_data_lcid >= 0) {
// If there is new data available for this logical channel
uint32_t nbytes = mac_io_h->get(pending_data_lcid+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8;
uint32_t nbytes = rlc->get_buffer_state(pending_data_lcid);
if (nbytes > last_pending_data[pending_data_lcid])
{
if (triggered_bsr_type != REGULAR) {
@ -119,16 +118,16 @@ bool bsr_proc::check_single_channel() {
uint32_t pending_data_lcid = 0;
uint32_t nof_nonzero_lcid = 0;
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
for (int i=0;i<MAX_LCID;i++) {
if (lcg[i] >= 0) {
if (!mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->isempty()) {
if (rlc->get_buffer_state(i) > 0) {
pending_data_lcid = i;
nof_nonzero_lcid++;
}
}
}
if (nof_nonzero_lcid == 1) {
uint32_t nbytes = mac_io_h->get(pending_data_lcid+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8;
uint32_t nbytes = rlc->get_buffer_state(pending_data_lcid);
// If there is new data available for this logical channel
if (nbytes > last_pending_data[pending_data_lcid]) {
triggered_bsr_type = REGULAR;
@ -140,8 +139,8 @@ bool bsr_proc::check_single_channel() {
}
void bsr_proc::update_pending_data() {
for (int i=0;i<mac_io_h->NOF_UL_LCH;i++) {
last_pending_data[i] = mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8;
for (int i=0;i<MAX_LCID;i++) {
last_pending_data[i] = rlc->get_buffer_state(i);
}
}
@ -149,9 +148,9 @@ bool bsr_proc::generate_bsr(bsr_t *bsr, uint32_t nof_padding_bytes) {
bool ret = false;
uint32_t nof_lcg=0;
bzero(bsr, sizeof(bsr_t));
for (int i=0;i<mac_io_h->NOF_UL_LCH;i++) {
for (int i=0;i<MAX_LCID;i++) {
if (lcg[i] >= 0) {
uint32_t n = mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8;
uint32_t n = rlc->get_buffer_state(i);
bsr->buff_size[lcg[i]] += n;
if (n > 0) {
nof_lcg++;
@ -196,16 +195,16 @@ void bsr_proc::step(uint32_t tti)
}
if (!timer_periodic) {
if (params_db->get_param(mac_params::BSR_TIMER_PERIODIC)) {
if (params_db->get_param(mac_interface_params::BSR_TIMER_PERIODIC)) {
timer_periodic = true;
timers_db->get(mac::BSR_TIMER_PERIODIC)->set(this, params_db->get_param(mac_params::BSR_TIMER_PERIODIC));
timers_db->get(mac::BSR_TIMER_PERIODIC)->set(this, params_db->get_param(mac_interface_params::BSR_TIMER_PERIODIC));
}
}
if (!timer_retx) {
if (params_db->get_param(mac_params::BSR_TIMER_RETX)) {
if (params_db->get_param(mac_interface_params::BSR_TIMER_RETX)) {
timer_retx = true;
timers_db->get(mac::BSR_TIMER_RETX)->set(this, params_db->get_param(mac_params::BSR_TIMER_RETX));
timers_db->get(mac::BSR_TIMER_RETX)->set(this, params_db->get_param(mac_interface_params::BSR_TIMER_RETX));
}
}
@ -222,8 +221,8 @@ void bsr_proc::step(uint32_t tti)
if ((tti - last_print)%10240 > 40) {
char str[128];
bzero(str, 128);
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
sprintf(str, "%s%d (%d), ", str, mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8, last_pending_data[i]);
for (int i=0;i<MAX_LCID;i++) {
sprintf(str, "%s%d (%d), ", str, rlc->get_buffer_state(i), last_pending_data[i]);
}
Info("QUEUE status: %s\n", str);
last_print = tti;
@ -257,15 +256,10 @@ uint32_t bsr_proc::need_to_send_bsr_on_ul_grant(uint32_t grant_size)
{
uint32_t bsr_sz = 0;
if (triggered_bsr_type == PERIODIC || triggered_bsr_type == REGULAR) {
uint32_t total_data = 0;
/* Check if grant + MAC SDU headers is enough to accomodate all pending data */
for (int i=0;i<mac_io_h->NOF_UL_LCH && total_data < grant_size;i++) {
uint32_t idx = 0;
uint32_t sdu_len = 0;
while(mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pop(&sdu_len, idx) && total_data < grant_size) {
idx++;
total_data += sch_pdu::size_plus_header_sdu(sdu_len/8);
}
uint32_t total_data = 0;
for (int i=0;i<MAX_LCID && total_data < grant_size;i++) {
total_data += sch_pdu::size_plus_header_sdu(rlc->get_buffer_state(i));
}
total_data--; // Because last SDU has no size header

@ -30,8 +30,6 @@
#include <stdint.h>
#include <signal.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"
@ -47,26 +45,7 @@ uint32_t backoff_table[16] = {0, 10, 20, 30, 40, 60, 80, 120, 160, 240, 320, 480
// Table 7.6-1: DELTA_PREAMBLE values.
int delta_preamble_db_table[5] = {0, 0, -3, -3, 8};
void* init_prach_thread(void *arg) {
ra_proc* ra = (ra_proc*) arg;
return ra->run_prach_thread();
}
void* ra_proc::run_prach_thread() {
pthread_mutex_lock(&mutex);
while(!start_prach_init) {
pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);
if (phy_h->init_prach()) {
return (void*) 0;
} else {
return (void*) -1;
}
}
bool ra_proc::init(mac_params* params_db_, phy* phy_h_, srslte::log* log_h_, srslte::timers* timers_db_,
bool ra_proc::init(phy_interface* phy_h_, log* log_h_, mac_params* params_db_, timers* timers_db_,
mux* mux_unit_, demux* demux_unit_)
{
phy_h = phy_h_;
@ -75,12 +54,8 @@ bool ra_proc::init(mac_params* params_db_, phy* phy_h_, srslte::log* log_h_, srs
timers_db = timers_db_;
mux_unit = mux_unit_;
demux_unit= demux_unit_;
start_prach_init = false;
if (pthread_create(&pt_init_prach, NULL, init_prach_thread, this)) {
perror("pthread_create");
}
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
srslte_softbuffer_rx_init(&softbuffer_rar, 10);
reset();
}
@ -96,32 +71,32 @@ void ra_proc::start_pcap(mac_pcap* pcap_)
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);
configIndex = params_db->get_param(mac_interface_params::RA_CONFIGINDEX);
preambleIndex = params_db->get_param(mac_interface_params::RA_PREAMBLEINDEX);
maskIndex = params_db->get_param(mac_interface_params::RA_MASKINDEX);
nof_preambles = params_db->get_param(mac_interface_params::RA_NOFPREAMBLES);
if (!nof_preambles || nof_preambles > 64) {
nof_preambles = 64;
}
nof_groupA_preambles = params_db->get_param(mac_params::RA_NOFGROUPAPREAMBLES);
nof_groupA_preambles = params_db->get_param(mac_interface_params::RA_NOFGROUPAPREAMBLES);
if (!nof_groupA_preambles) {
nof_groupA_preambles = nof_preambles;
nof_groupA_preambles = nof_preambles;
}
if (nof_groupA_preambles > nof_preambles) {
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);
messagePowerOffsetGroupB= params_db->get_param(mac_interface_params::RA_MESSAGEPOWEROFFSETB);
messageSizeGroupA = params_db->get_param(mac_interface_params::RA_MESSAGESIZEA);
Pcmax = params_db->get_param(mac_interface_params::RA_PCMAX);
deltaPreambleMsg3 = params_db->get_param(mac_interface_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);
contentionResolutionTimer = params_db->get_param(mac_params::RA_CONTENTIONTIMER);
responseWindowSize = params_db->get_param(mac_interface_params::RA_RESPONSEWINDOW);
powerRampingStep = params_db->get_param(mac_interface_params::RA_POWERRAMPINGSTEP);
preambleTransMax = params_db->get_param(mac_interface_params::RA_PREAMBLETRANSMAX);
iniReceivedTargetPower = params_db->get_param(mac_interface_params::RA_INITRECEIVEDPOWER);
contentionResolutionTimer = params_db->get_param(mac_interface_params::RA_CONTENTIONTIMER);
delta_preamble_db = delta_preamble_db_table[configIndex%5];
@ -154,9 +129,9 @@ bool ra_proc::is_error() {
const char* state_str[11] = {"Idle",
"RA Initializat.: ",
"RA Initial.Wait: ",
"RA ResSelection: ",
"RA PreambleTx : ",
"RA PDCCH setup : ",
"RA PreambleRx : ",
"RA ResponseErr : ",
"RA BackoffWait : ",
@ -199,28 +174,9 @@ void ra_proc::step_initialization() {
mux_unit->msg3_flush();
backoff_param_ms = 0;
// Instruct phy prach init thread to start initialization
pthread_mutex_lock(&mutex);
start_prach_init = true;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
state = INITIALIZATION_WAIT;
}
void ra_proc::step_initialization_wait() {
int n = pthread_kill(pt_init_prach, 0);
if (n) {
void *status;
pthread_join(pt_init_prach, &status);
if (status) {
rError("Initializing PRACH on PHY\n");
state = RA_PROBLEM;
} else {
rInfo("PRACH init OK\n");
state = RESOURCE_SELECTION;
}
}
// Instruct phy to configure PRACH
phy_h->configure_prach_params();
state = RESOURCE_SELECTION;
}
void ra_proc::step_resource_selection() {
@ -249,7 +205,8 @@ void ra_proc::step_resource_selection() {
sel_maskIndex = 0;
}
rInfo("Selected preambleIndex=%d maskIndex=%d nof_GroupApreambles=%d\n", sel_preamble, sel_maskIndex,nof_groupA_preambles);
rInfo("Selected preambleIndex=%d maskIndex=%d nof_GroupApreambles=%d\n",
sel_preamble, sel_maskIndex,nof_groupA_preambles);
state = PREAMBLE_TRANSMISSION;
}
@ -258,118 +215,113 @@ void ra_proc::step_preamble_transmission() {
delta_preamble_db +
(preambleTransmissionCounter-1)*powerRampingStep;
phy_h->send_prach(sel_preamble, sel_maskIndex - 1, received_target_power_dbm);
phy_h->prach_send(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;
state = PDCCH_SETUP;
}
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 = srslte_tti_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
dl_buffer->reset_softbuffer();
bool ack = dl_buffer->decode_data(&rar_grant, rar_pdu_buffer);
if (pcap) {
pcap->write_dl_crnti(payload, rar_grant.get_tbs()/8, ra_rnti, ack, tti);
}
void ra_proc::step_pdcch_setup() {
int ra_tti = phy_h->prach_tx_tti();
if (ra_tti > 0) {
ra_rnti = 1+ra_tti%10;
phy_h->pdcch_dl_search(SRSLTE_RNTI_RAR, ra_rnti, ra_tti+3, responseWindowSize);
state = RESPONSE_RECEPTION;
}
}
if (ack) {
rDebug("RAR decoded successfully TBS=%d\n", rar_grant.get_tbs());
rar_pdu_msg.init(rar_grant.get_tbs()/8);
rar_pdu_msg.parse_packet(rar_pdu_buffer);
void ra_proc::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action)
{
if (grant.n_bytes < MAX_RAR_PDU_LEN) {
rInfo("DL grant found RA-RNTI=%d\n", ra_rnti);
action->decode_enabled = true;
action->default_ack = false;
action->generate_ack = false;
action->payload_ptr = rar_pdu_buffer;
action->rnti = grant.rnti;
memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t));
action->rv = grant.rv;
action->softbuffer = &softbuffer_rar;
rar_grant_nbytes = grant.n_bytes;
rar_grant_tti = grant.tti;
if (action->rv == 0) {
srslte_softbuffer_rx_reset(&softbuffer_rar);
}
} else {
rError("Received RAR grant exceeds buffer length (%d>%d)\n", grant.n_bytes, MAX_RAR_PDU_LEN);
action->decode_enabled = false;
state = RESPONSE_ERROR;
}
}
void ra_proc::tb_decoded_ok() {
if (pcap) {
pcap->write_dl_crnti(rar_pdu_buffer, rar_grant_nbytes, ra_rnti, true, rar_grant_tti);
}
rDebug("RAR decoded successfully TBS=%d\n", rar_grant_nbytes);
rar_pdu_msg.init(rar_grant_nbytes);
rar_pdu_msg.parse_packet(rar_pdu_buffer);
// Set Backoff parameter
if (rar_pdu_msg.has_backoff()) {
backoff_param_ms = backoff_table[rar_pdu_msg.get_backoff()%16];
} else {
backoff_param_ms = 0;
}
while(rar_pdu_msg.next()) {
if (rar_pdu_msg.get()->get_rapid() == sel_preamble) {
rInfo("Received RAPID=%d\n", sel_preamble);
process_timeadv_cmd(rar_pdu_msg.get()->get_ta_cmd());
// FIXME: Indicate received target power
//phy_h->set_target_power_rar(iniReceivedTargetPower, (preambleTransmissionCounter-1)*powerRampingStep);
uint8_t grant[rar_subh::RAR_GRANT_LEN];
rar_pdu_msg.get()->get_sched_grant(grant);
phy_h->set_rar_grant(rar_grant_tti, grant);
if (preambleIndex > 0) {
// Preamble selected by Network
state = COMPLETION;
} else {
// Preamble selected by UE MAC
params_db->set_param(mac_interface_params::RNTI_TEMP, rar_pdu_msg.get()->get_temp_crnti());
if (first_rar_received) {
first_rar_received = false;
// Set Backoff parameter
if (rar_pdu_msg.has_backoff()) {
backoff_param_ms = backoff_table[rar_pdu_msg.get_backoff()%16];
} else {
backoff_param_ms = 0;
}
// Save transmitted C-RNTI (if any)
transmitted_crnti = params_db->get_param(mac_interface_params::RNTI_C);
while(rar_pdu_msg.next()) {
if (rar_pdu_msg.get()->get_rapid() == sel_preamble) {
rInfo("Received RAPID=%d\n", sel_preamble);
process_timeadv_cmd(rar_pdu_msg.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[rar_subh::RAR_GRANT_LEN];
rar_pdu_msg.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_msg.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(sched_grant::RNTI_TYPE_TEMP, rar_pdu_msg.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
rInfo("Generating Msg3 for TBS=%d\n", msg3_grant.get_tbs());
mux_unit->pdu_move_to_msg3(msg3_grant.get_tbs()); // 56 is the minimum grant provided
}
rDebug("Going to Contention Resolution state\n");
state = CONTENTION_RESOLUTION;
// Start contention resolution timer
timers_db->get(mac::CONTENTION_TIMER)->reset();
timers_db->get(mac::CONTENTION_TIMER)->run();
}
} else {
rDebug("Found RAR for preamble %d\n", rar_pdu_msg.get()->get_rapid());
}
}
}
}
srslte_verbose = SRSLTE_VERBOSE_NONE;
}
if (interval_ra > 3+responseWindowSize && interval_ra < 10000) {
rInfo("Timeout while trying to receive RAR\n");
state = RESPONSE_ERROR;
// Save transmitted UE contention id, as defined by higher layers
transmitted_contention_id = params_db->get_param(mac_interface_params::CONTENTION_ID);
params_db->set_param(mac_interface_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);
}
}
rDebug("Going to Contention Resolution state\n");
state = CONTENTION_RESOLUTION;
// Start contention resolution timer
timers_db->get(mac::CONTENTION_TIMER)->reset();
timers_db->get(mac::CONTENTION_TIMER)->run();
}
} else {
rDebug("Found RAR for preamble %d\n", rar_pdu_msg.get()->get_rapid());
}
}
}
void ra_proc::step_response_reception() {
// do nothing. Processing done in tb_decoded_ok()
}
void ra_proc::step_response_error() {
preambleTransmissionCounter++;
@ -377,7 +329,7 @@ void ra_proc::step_response_error() {
rError("Maximum number of transmissions reached (%d)\n", preambleTransMax);
state = RA_PROBLEM;
} else {
backoff_interval_start = tti;
backoff_interval_start = phy_h->get_current_tti();
if (backoff_param_ms) {
backoff_inteval = rand()%backoff_param_ms;
} else {
@ -394,7 +346,7 @@ void ra_proc::step_response_error() {
}
void ra_proc::step_backoff_wait() {
if (srslte_tti_interval(tti, backoff_interval_start) >= backoff_inteval) {
if (srslte_tti_interval(phy_h->get_current_tti(), backoff_interval_start) >= backoff_inteval) {
state = RESOURCE_SELECTION;
}
}
@ -411,7 +363,7 @@ void ra_proc::step_contention_resolution() {
start_mode == PDCCH_ORDER)
{
timers_db->get(mac::CONTENTION_TIMER)->stop();
params_db->set_param(mac_params::RNTI_TEMP, 0);
params_db->set_param(mac_interface_params::RNTI_TEMP, 0);
state = COMPLETION;
}
pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED;
@ -428,7 +380,7 @@ void ra_proc::step_contention_resolution() {
if (transmitted_contention_id == rx_contention_id) {
rDebug("MAC PDU Contention Resolution ID matches the one transmitted in CCCH SDU\n");
// UE Contention Resolution ID included in MAC CE matches the CCCH SDU transmitted in Msg3
params_db->set_param(mac_params::RNTI_C, params_db->get_param(mac_params::RNTI_TEMP));
params_db->set_param(mac_interface_params::RNTI_C, params_db->get_param(mac_interface_params::RNTI_TEMP));
// finish the disassembly and demultiplexing of the MAC PDU
demux_unit->demultiplex_pending_pdu();
state = COMPLETION;
@ -441,7 +393,7 @@ void ra_proc::step_contention_resolution() {
// FIXME: Need to flush Msg3 HARQ buffer. Why?
state = RESPONSE_ERROR;
}
params_db->set_param(mac_params::RNTI_TEMP, 0);
params_db->set_param(mac_interface_params::RNTI_TEMP, 0);
}
}
} else {
@ -451,15 +403,14 @@ void ra_proc::step_contention_resolution() {
}
void ra_proc::step_completition() {
params_db->set_param(mac_params::RA_PREAMBLEINDEX, 0);
params_db->set_param(mac_params::RA_MASKINDEX, 0);
params_db->set_param(mac_interface_params::RA_PREAMBLEINDEX, 0);
params_db->set_param(mac_interface_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:
@ -467,15 +418,15 @@ void ra_proc::step(uint32_t tti_)
case INITIALIZATION:
step_initialization();
break;
case INITIALIZATION_WAIT:
step_initialization_wait();
break;
case RESOURCE_SELECTION:
step_resource_selection();
break;
case PREAMBLE_TRANSMISSION:
step_preamble_transmission();
break;
case PDCCH_SETUP:
step_pdcch_setup();
break;
case RESPONSE_RECEPTION:
step_response_reception();
break;
@ -529,7 +480,7 @@ void ra_proc::start_rlc_order()
void ra_proc::timer_expired(uint32_t timer_id)
{
rInfo("Contention Resolution Timer expired. Going to Response Error\n");
params_db->set_param(mac_params::RNTI_TEMP, 0);
params_db->set_param(mac_interface_params::RNTI_TEMP, 0);
state = RESPONSE_ERROR;
}

@ -36,7 +36,7 @@ sr_proc::sr_proc() {
initiated = false;
}
void sr_proc::init(log* log_h_, mac_params* params_db_, phy* phy_h_)
void sr_proc::init(phy_interface* phy_h_, log* log_h_, mac_params* params_db_)
{
log_h = log_h_;
params_db = params_db_;
@ -48,20 +48,19 @@ void sr_proc::init(log* log_h_, mac_params* params_db_, phy* phy_h_)
void sr_proc::reset()
{
is_pending_sr = false;
phy_h->send_sr(false);
}
void sr_proc::step(uint32_t tti)
{
if (initiated) {
if (is_pending_sr) {
if (params_db->get_param(mac_params::SR_PUCCH_CONFIGURED)) {
if (params_db->get_param(mac_interface_params::SR_PUCCH_CONFIGURED)) {
if (sr_counter < dsr_transmax) {
int last_tx_tti = phy_h->sr_last_tx_tti();
if (last_tx_tti >= 0 && last_tx_tti + 4 < tti) {
sr_counter++;
Info("SR signalling PHY. sr_counter=%d, PHY TTI=%d\n", sr_counter, phy_h->get_current_tti());
phy_h->send_sr(true);
phy_h->sr_send();
}
} else {
do_ra = true;
@ -93,7 +92,7 @@ void sr_proc::start()
sr_counter = 0;
is_pending_sr = true;
}
dsr_transmax = params_db->get_param(mac_params::SR_TRANS_MAX);
dsr_transmax = params_db->get_param(mac_interface_params::SR_TRANS_MAX);
Info("SR starting dsrTransMax=%d. sr_counter=%d\n", dsr_transmax, sr_counter);
}
}

@ -25,10 +25,7 @@
*
*/
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/ul_harq.h"
@ -41,16 +38,15 @@ namespace srslte {
*
*********************************************************/
bool ul_harq_entity::init(srslte_cell_t cell, mac_params *params_db_, log *log_h_, timers *timers_db_, mux *mux_unit_) {
bool ul_harq_entity::init(log *log_h_, mac_params *params_db_, timers *timers_db_, mux *mux_unit_) {
log_h = log_h_;
mux_unit = mux_unit_;
params_db = params_db_;
timers_db = timers_db_;
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
if (!proc[i].init(cell, this)) {
if (!proc[i].init(i, this)) {
return false;
}
proc[i].pid = i;
}
return true;
}
@ -67,50 +63,83 @@ void ul_harq_entity::reset() {
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
proc[i].reset();
}
ul_sps_assig.clear();
}
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::set_ack(uint32_t tti, bool ack) {
int tti_harq = (int) tti - 4;
if (tti_harq < 0) {
tti_harq += 10240;
}
uint32_t pid_harq = pidof(tti_harq);
if (proc[pid_harq].has_grant() && proc[pid_harq].last_tx_tti() <= tti_harq) {
proc[pid_harq].set_harq_feedback(ack);
}
}
void ul_harq_entity::harq_recv(uint32_t tti, bool ack, mac_interface_phy::tb_action_ul_t* action)
{
set_ack(tti, ack);
run_tti(tti, NULL, NULL, action);
}
// Called with no UL grant
void ul_harq_entity::run_tti(uint32_t tti, phy *phy_h) {
run_tti(tti, NULL, phy_h);
// Implements Section 5.4.1
void ul_harq_entity::new_grant_ul(mac_interface_phy::mac_grant_t grant, uint8_t* payload_ptr,
mac_interface_phy::tb_action_ul_t* action)
{
if (grant.rnti_type == SRSLTE_RNTI_USER ||
grant.rnti_type == SRSLTE_RNTI_TEMP ||
grant.rnti_type == SRSLTE_RNTI_RAR)
{
if (grant.rnti_type == SRSLTE_RNTI_USER && proc[pidof(grant.tti)].is_sps()) {
grant.ndi = true;
}
run_tti(grant.tti, &grant, payload_ptr, action);
} else if (grant.rnti_type == SRSLTE_RNTI_SPS) {
if (grant.ndi) {
grant.ndi = proc[pidof(grant.tti)].get_ndi();
run_tti(grant.tti, &grant, payload_ptr, action);
} else {
Info("Not implemented\n");
}
}
}
void ul_harq_entity::new_grant_ul_ack(mac_interface_phy::mac_grant_t grant, uint8_t* payload_ptr, bool ack,
mac_interface_phy::tb_action_ul_t* action)
{
set_ack(grant.tti, ack);
new_grant_ul(grant, payload_ptr, action);
}
// Implements Section 5.4.2.1
// Called with UL grant
void ul_harq_entity::run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_h)
void ul_harq_entity::run_tti(uint32_t tti, mac_interface_phy::mac_grant_t *grant, uint8_t* payload_ptr,
mac_interface_phy::tb_action_ul_t* action)
{
uint32_t tti_tx = (tti+4)%10240;
uint32_t pid = pidof(tti_tx);
// Receive and route HARQ feedbacks
int tti_harq = (int) tti - 4;
if (tti_harq < 0) {
tti_harq += 10240;
}
uint32_t pid_harq = pidof(tti_harq);
if (proc[pid_harq].has_grant() && proc[pid_harq].last_tx_tti() <= tti_harq) {
proc[pid_harq].set_harq_feedback(phy_h->get_dl_buffer(tti)->decode_ack(proc[pid_harq].get_grant()));
}
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())
if ((!grant->rnti_type == SRSLTE_RNTI_TEMP && grant->ndi != proc[pid].get_ndi()) ||
(grant->rnti_type == SRSLTE_RNTI_USER && !proc[pid].has_grant()) ||
grant->is_from_rar)
{
// New transmission
uint8_t* msg3_ptr = (uint8_t*) mux_unit->msg3_pop(grant->get_tbs());
// Uplink grant in a RAR
if (grant->is_from_rar()) {
if (msg3_ptr) {
proc[pid].generate_new_tx(tti_tx, msg3_ptr, true, grant, phy_h->get_ul_buffer(tti_tx));
mux_unit->msg3_transmitted();
if (grant->is_from_rar) {
if (mux_unit->msg3_get(payload_ptr, grant->n_bytes)) {
proc[pid].generate_new_tx(tti_tx, true, grant, action);
} else {
Warning("UL RAR grant available but no Msg3 on buffer\n");
}
@ -118,26 +147,24 @@ void ul_harq_entity::run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_h)
// Normal UL grant
} else {
// Request a MAC PDU from the Multiplexing & Assemble Unit
uint8_t* mac_pdu = mux_unit->pdu_pop(grant->get_tbs());
if (mac_pdu) {
// FIXME: This is inefficient. too many memcopies
memcpy(mac_pdu_buffer[pid], mac_pdu, grant->get_tbs()*sizeof(uint8_t));
mux_unit->pdu_release();
proc[pid].generate_new_tx(tti_tx, mac_pdu_buffer[pid], false, grant, phy_h->get_ul_buffer(tti_tx));
if (mux_unit->pdu_get(payload_ptr, grant->n_bytes)) {
proc[pid].generate_new_tx(tti_tx, false, grant, action);
} else {
mux_unit->pdu_release();
Warning("Uplink grant but no MAC PDU in Multiplex Unit buffer\n");
}
}
} else {
// Adaptive Re-TX
proc[pid].generate_retx(tti_tx, grant, phy_h->get_ul_buffer(tti_tx));
proc[pid].generate_retx(tti_tx, grant, action);
}
} else if (proc[pid].has_grant()) {
// Non-Adaptive Re-Tx
proc[pid].generate_retx(tti_tx, phy_h->get_ul_buffer(tti_tx));
proc[pid].generate_retx(tti_tx, action);
}
if (pcap) {
pcap->write_ul_crnti(payload_ptr, grant->n_bytes, grant->rnti, proc[pid].get_nof_retx(), tti_tx);
}
}
@ -151,30 +178,34 @@ void ul_harq_entity::run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_h)
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) {
ul_harq_entity::ul_harq_process::ul_harq_process() {
current_tx_nb = 0;
current_irv = 0;
is_initiated = false;
is_grant_configured = false;
tti_last_tx = 0;
bzero(&cur_grant, sizeof(ul_sched_grant));
bzero(&cur_grant, sizeof(mac_interface_phy::mac_grant_t));
}
void ul_harq_entity::ul_harq_process::reset() {
current_tx_nb = 0;
current_irv = 0;
tti_last_tx = 0;
is_grant_configured = false;
bzero(&cur_grant, sizeof(ul_sched_grant));
if (is_initiated) {
srslte_softbuffer_tx_reset(&softbuffer);
}
bzero(&cur_grant, sizeof(mac_interface_phy::mac_grant_t));
}
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;
@ -185,11 +216,6 @@ uint32_t ul_harq_entity::ul_harq_process::get_rv()
return rv_of_irv[current_irv%4];
}
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;
// UL packet successfully delivered
@ -201,39 +227,42 @@ void ul_harq_entity::ul_harq_process::set_harq_feedback(bool ack) {
}
}
bool ul_harq_entity::ul_harq_process::init(srslte_cell_t cell, ul_harq_entity *parent) {
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
bool ul_harq_entity::ul_harq_process::init(uint32_t pid_, ul_harq_entity* parent) {
if (srslte_softbuffer_tx_init(&softbuffer, 100)) {
fprintf(stderr, "Error initiating soft buffer\n");
return false;
} else {
is_initiated = true;
harq_entity = parent;
log_h = harq_entity->log_h;
pid = pid_;
return true;
}
}
void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, ul_buffer* ul)
void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action)
{
generate_retx(tti_tx, NULL, ul);
generate_retx(tti_tx, NULL, action);
}
// Retransmission with or w/o grant (Section 5.4.2.2)
void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, ul_sched_grant* grant, ul_buffer* ul)
void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, mac_interface_phy::mac_grant_t *grant,
mac_interface_phy::tb_action_ul_t *action)
{
current_tx_nb++;
if (grant) {
// HARQ entity requests an adaptive transmission
memcpy(&cur_grant, grant, sizeof(ul_sched_grant));
current_irv = irv_of_rv[grant->get_rv()%4];
current_irv = irv_of_rv[grant->rv%4];
harq_feedback = false;
Info("UL PID %d: Adaptive retx=%d, RV=%d, TBS=%d, MCS=%d\n", pid, current_tx_nb, get_rv(), grant->get_tbs(), grant->get_mcs());
generate_tx(tti_tx, NULL, ul);
Info("UL PID %d: Adaptive retx=%d, RV=%d, TBS=%d\n",
pid, current_tx_nb, get_rv(), grant->n_bytes);
generate_tx(tti_tx, action);
} else {
Info("UL PID %d: Non-Adaptive retx=%d, RV=%d, TBS=%d, MCS=%d\n", pid, current_tx_nb, get_rv(), cur_grant.get_tbs(), cur_grant.get_mcs());
Info("UL PID %d: Non-Adaptive retx=%d, RV=%d, TBS=%d\n",
pid, current_tx_nb, get_rv(), cur_grant.n_bytes);
// HARQ entity requests a non-adaptive transmission
if (!harq_feedback) {
generate_tx(tti_tx, NULL, ul);
generate_tx(tti_tx, action);
}
}
@ -244,56 +273,69 @@ void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, ul_sched_gr
}
// New transmission (Section 5.4.2.2)
void ul_harq_entity::ul_harq_process::generate_new_tx(uint32_t tti_tx, uint8_t *pdu_payload, bool is_msg3_, ul_sched_grant* ul_grant, ul_buffer* ul)
void ul_harq_entity::ul_harq_process::generate_new_tx(uint32_t tti_tx, bool is_msg3_,
mac_interface_phy::mac_grant_t *grant,
mac_interface_phy::tb_action_ul_t *action)
{
if (ul_grant && pdu_payload) {
if (grant) {
srslte_softbuffer_tx_reset(&softbuffer);
memcpy(&cur_grant, ul_grant, sizeof(ul_sched_grant));
memcpy(&cur_grant, grant, sizeof(mac_interface_phy::mac_grant_t));
harq_feedback = false;
is_grant_configured = true;
current_tx_nb = 0;
current_irv = 0;
is_msg3 = is_msg3_;
Info("UL PID %d: New TX%s, RV=%d, TBS=%d, MCS=%d, RNTI=%d\n", pid, is_msg3?" for Msg3":"", get_rv(), cur_grant.get_tbs(),
cur_grant.get_mcs(), cur_grant.get_rnti());
generate_tx(tti_tx, pdu_payload, ul);
Info("UL PID %d: New TX%s, RV=%d, TBS=%d, RNTI=%d\n",
pid, is_msg3?" for Msg3":"", get_rv(), cur_grant.n_bytes, cur_grant.rnti);
generate_tx(tti_tx, action);
}
}
// Transmission of pending frame (Section 5.4.2.2)
void ul_harq_entity::ul_harq_process::generate_tx(uint32_t tti_tx, uint8_t *pdu_payload, ul_buffer* ul)
void ul_harq_entity::ul_harq_process::generate_tx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action)
{
cur_grant.set_rv(get_rv());
ul->set_current_tx_nb(current_tx_nb);
ul->generate_data(&cur_grant, &softbuffer, pdu_payload);
if (harq_entity->pcap) {
harq_entity->pcap->write_ul_crnti(pdu_payload, cur_grant.get_tbs()/8, cur_grant.get_rnti(), current_tx_nb, tti_tx);
}
action->current_tx_nb = current_tx_nb;
action->expect_ack = true;
action->rnti = is_msg3?harq_entity->params_db->get_param(mac_interface_params::RNTI_TEMP):cur_grant.rnti;
action->rv = get_rv();
action->softbuffer = &softbuffer;
action->tx_enabled = true;
memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(srslte_phy_grant_t));
current_irv = (current_irv+1)%4;
tti_last_tx = tti_tx;
if (is_msg3) {
if (current_tx_nb == harq_entity->params_db->get_param(mac_params::HARQ_MAXMSG3TX)) {
if (current_tx_nb == harq_entity->params_db->get_param(mac_interface_params::HARQ_MAXMSG3TX)) {
Info("UL PID %d: Maximum number of ReTX for Msg3 reached (%d). Discarting TB.\n", pid,
harq_entity->params_db->get_param(mac_params::HARQ_MAXMSG3TX));
harq_entity->params_db->get_param(mac_interface_params::HARQ_MAXMSG3TX));
reset();
action->expect_ack = false;
}
} else {
if (current_tx_nb == harq_entity->params_db->get_param(mac_params::HARQ_MAXTX)) {
if (current_tx_nb == harq_entity->params_db->get_param(mac_interface_params::HARQ_MAXTX)) {
Info("UL PID %d: Maximum number of ReTX reached (%d). Discarting TB.\n", pid,
harq_entity->params_db->get_param(mac_params::HARQ_MAXTX));
harq_entity->params_db->get_param(mac_interface_params::HARQ_MAXTX));
reset();
action->expect_ack = false;
}
}
}
bool ul_harq_entity::ul_harq_process::is_sps()
{
return false;
}
uint32_t ul_harq_entity::ul_harq_process::last_tx_tti()
{
return tti_last_tx;
}
uint32_t ul_harq_entity::ul_harq_process::get_nof_retx()
{
return current_tx_nb;
}
}
}

@ -32,7 +32,7 @@
#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/mac_interface.h"
#include "srsapps/common/log_stdout.h"
#include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/mac_pcap.h"
@ -116,26 +116,26 @@ uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t x) {
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,
mac->set_param(srslte::ue::mac_interface_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,
mac->set_param(srslte::ue::mac_interface_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,
mac->set_param(srslte::ue::mac_interface_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,
mac->set_param(srslte::ue::mac_interface_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,
mac->set_param(srslte::ue::mac_interface_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,
mac->set_param(srslte::ue::mac_interface_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,
mac->set_param(srslte::ue::mac_interface_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,
mac->set_param(srslte::ue::mac_interface_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,
mac->set_param(srslte::ue::mac_interface_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::HARQ_MAXMSG3TX,
mac->set_param(srslte::ue::mac_interface_params::HARQ_MAXMSG3TX,
sib2->rr_config_common_sib.rach_cnfg.max_harq_msg3_tx);
printf("Set RACH ConfigCommon: NofPreambles=%d, ResponseWindow=%d, ContentionResolutionTimer=%d ms, MaxTrials=%d\n",
@ -145,28 +145,28 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u
liblte_rrc_preamble_trans_max_num[sib2->rr_config_common_sib.rach_cnfg.preamble_trans_max]);
// PDSCH ConfigCommon
mac->set_param(srslte::ue::mac_params::PDSCH_RSPOWER,
mac->set_param(srslte::ue::mac_interface_params::PDSCH_RSPOWER,
sib2->rr_config_common_sib.pdsch_cnfg.rs_power);
mac->set_param(srslte::ue::mac_params::PDSCH_PB,
mac->set_param(srslte::ue::mac_interface_params::PDSCH_PB,
sib2->rr_config_common_sib.pdsch_cnfg.p_b);
// PUSCH ConfigCommon
phy->set_param(srslte::ue::phy_params::PUSCH_BETA, 10);
phy->set_param(srslte::ue::phy_params::PUSCH_EN_64QAM,
phy->set_param(srslte::ue::phy_interface_params::PUSCH_BETA, 10);
phy->set_param(srslte::ue::phy_interface_params::PUSCH_EN_64QAM,
sib2->rr_config_common_sib.pusch_cnfg.enable_64_qam);
phy->set_param(srslte::ue::phy_params::PUSCH_HOPPING_OFFSET,
phy->set_param(srslte::ue::phy_interface_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,
phy->set_param(srslte::ue::phy_interface_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,
phy->set_param(srslte::ue::phy_interface_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::DMRS_GROUP_HOPPING_EN,
phy->set_param(srslte::ue::phy_interface_params::DMRS_GROUP_HOPPING_EN,
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_hopping_enabled?1:0);
phy->set_param(srslte::ue::phy_params::DMRS_SEQUENCE_HOPPING_EN,
phy->set_param(srslte::ue::phy_interface_params::DMRS_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,
phy->set_param(srslte::ue::phy_interface_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,
phy->set_param(srslte::ue::phy_interface_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_sb=%d\n",
@ -176,14 +176,14 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u
sib2->rr_config_common_sib.pusch_cnfg.n_sb);
// PUCCH ConfigCommon
phy->set_param(srslte::ue::phy_params::PUCCH_BETA, 10);
phy->set_param(srslte::ue::phy_params::PUCCH_DELTA_SHIFT,
phy->set_param(srslte::ue::phy_interface_params::PUCCH_BETA, 10);
phy->set_param(srslte::ue::phy_interface_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,
phy->set_param(srslte::ue::phy_interface_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,
phy->set_param(srslte::ue::phy_interface_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,
phy->set_param(srslte::ue::phy_interface_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],
@ -193,15 +193,15 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u
// PRACH Configcommon
phy->set_param(srslte::ue::phy_params::PRACH_ROOT_SEQ_IDX,
phy->set_param(srslte::ue::phy_interface_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,
phy->set_param(srslte::ue::phy_interface_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,
phy->set_param(srslte::ue::phy_interface_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,
phy->set_param(srslte::ue::phy_interface_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,
phy->set_param(srslte::ue::phy_interface_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",
@ -213,9 +213,9 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u
// SRS ConfigCommon
if (sib2->rr_config_common_sib.srs_ul_cnfg.present) {
phy->set_param(srslte::ue::phy_params::SRS_CS_BWCFG, sib2->rr_config_common_sib.srs_ul_cnfg.bw_cnfg);
phy->set_param(srslte::ue::phy_params::SRS_CS_SFCFG, sib2->rr_config_common_sib.srs_ul_cnfg.subfr_cnfg);
phy->set_param(srslte::ue::phy_params::SRS_CS_ACKNACKSIMUL, sib2->rr_config_common_sib.srs_ul_cnfg.ack_nack_simul_tx);
phy->set_param(srslte::ue::phy_interface_params::SRS_CS_BWCFG, sib2->rr_config_common_sib.srs_ul_cnfg.bw_cnfg);
phy->set_param(srslte::ue::phy_interface_params::SRS_CS_SFCFG, sib2->rr_config_common_sib.srs_ul_cnfg.subfr_cnfg);
phy->set_param(srslte::ue::phy_interface_params::SRS_CS_ACKNACKSIMUL, sib2->rr_config_common_sib.srs_ul_cnfg.ack_nack_simul_tx);
}
printf("Set SRS ConfigCommon: BW-Configuration=%d, SF-Configuration=%d, ACKNACK=%d\n",
@ -229,25 +229,24 @@ void process_connsetup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *msg, srslte::ue::mac
// FIXME: There's an error parsing the connectionSetup message. This value is hard-coded:
if (msg->rr_cnfg.phy_cnfg_ded_present) {
phy->set_param(srslte::ue::phy_params::PUCCH_N_PUCCH_SR,
phy->set_param(srslte::ue::phy_interface_params::PUCCH_N_PUCCH_SR,
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_pucch_resource_idx);
phy->set_param(srslte::ue::phy_params::SR_CONFIG_INDEX,
phy->set_param(srslte::ue::phy_interface_params::SR_CONFIG_INDEX,
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_cnfg_idx);
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_ACK, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ack_idx);
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_CQI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_cqi_idx);
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_RI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ri_idx);
phy->set_param(srslte::ue::phy_interface_params::UCI_I_OFFSET_ACK, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ack_idx);
phy->set_param(srslte::ue::phy_interface_params::UCI_I_OFFSET_CQI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_cqi_idx);
phy->set_param(srslte::ue::phy_interface_params::UCI_I_OFFSET_RI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ri_idx);
if (msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded_present && msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.setup_present) {
phy->set_param(srslte::ue::phy_params::SRS_UE_CS, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.cyclic_shift);
phy->set_param(srslte::ue::phy_params::SRS_UE_DURATION, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.duration);
phy->set_param(srslte::ue::phy_params::SRS_UE_NRRC, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.freq_domain_pos);
phy->set_param(srslte::ue::phy_params::SRS_UE_BW, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_bandwidth);
phy->set_param(srslte::ue::phy_params::SRS_UE_CONFIGINDEX, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_cnfg_idx);
phy->set_param(srslte::ue::phy_params::SRS_UE_HOP, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_hopping_bandwidth);
phy->set_param(srslte::ue::phy_params::SRS_UE_CYCLICSHIFT, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.cyclic_shift);
phy->set_param(srslte::ue::phy_params::SRS_UE_TXCOMB, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.tx_comb);
phy->set_param(srslte::ue::phy_params::SRS_IS_CONFIGURED, 1);
phy->set_param(srslte::ue::phy_params::SRS_BETA, 10);
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_CS, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.cyclic_shift);
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_DURATION, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.duration);
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_NRRC, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.freq_domain_pos);
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_BW, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_bandwidth);
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_CONFIGINDEX, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_cnfg_idx);
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_HOP, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_hopping_bandwidth);
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_CYCLICSHIFT, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.cyclic_shift);
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_TXCOMB, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.tx_comb);
phy->set_param(srslte::ue::phy_interface_params::SRS_IS_CONFIGURED, 1);
}
}
printf("Set PHY configuration: SR-n_pucch=%d, SR-ConfigIndex=%d, SRS-ConfigIndex=%d, SRS-bw=%d, SRS-Nrcc=%d, SRS-hop=%d, SRS-Ncs=%d\n",
@ -259,15 +258,15 @@ void process_connsetup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *msg, srslte::ue::mac
msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_hopping_bandwidth,
msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.cyclic_shift);
mac->set_param(srslte::ue::mac_params::HARQ_MAXTX,
mac->set_param(srslte::ue::mac_interface_params::HARQ_MAXTX,
liblte_rrc_max_harq_tx_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.max_harq_tx]);
mac->set_param(srslte::ue::mac_params::SR_TRANS_MAX,
mac->set_param(srslte::ue::mac_interface_params::SR_TRANS_MAX,
liblte_rrc_dsr_trans_max_num[msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.dsr_trans_max]);
mac->set_param(srslte::ue::mac_params::SR_PUCCH_CONFIGURED, 1);
mac->set_param(srslte::ue::mac_interface_params::SR_PUCCH_CONFIGURED, 1);
mac->set_param(srslte::ue::mac_params::BSR_TIMER_RETX,
mac->set_param(srslte::ue::mac_interface_params::BSR_TIMER_RETX,
liblte_rrc_retransmission_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.retx_bsr_timer]);
mac->set_param(srslte::ue::mac_params::BSR_TIMER_PERIODIC,
mac->set_param(srslte::ue::mac_interface_params::BSR_TIMER_PERIODIC,
liblte_rrc_periodic_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.periodic_bsr_timer]);
printf("Set MAC configuration: dsr-TransMAX: %d, harq-MaxReTX=%d, bsr-TimerReTX=%d, bsr-TimerPeriodic=%d\n",
@ -325,7 +324,6 @@ void sig_int_handler(int signo)
if (prog_args.do_trace) {
//radio_uhd.write_trace("radio");
phy.write_trace("phy");
mac.write_trace("mac");
}
if (prog_args.do_pcap) {
mac_pcap.close();
@ -334,10 +332,139 @@ void sig_int_handler(int signo)
exit(0);
}
class my_rlc : public srslte::ue::rlc_interface_mac {
public:
bool mib_decoded;
bool sib1_decoded;
bool sib2_decoded;
bool connsetup_decoded;
int nsegm_dcch;
uint8_t si_window_len, sib2_period;
my_rlc() {
mib_decoded = false;
sib1_decoded = false;
sib2_decoded = false;
connsetup_decoded = false;
nsegm_dcch = 0;
si_window_len = 0;
sib2_period = 0;
}
uint32_t get_buffer_state(uint32_t lcid) {
if (lcid == 0) {
if (sib2_decoded && !connsetup_decoded) {
return 6;
}
} else if (lcid == 1) {
if (connsetup_decoded && nsegm_dcch < 2) {
return lengths[nsegm_dcch];
} else if (nsegm_dcch == 2) {
return 2;
}
}
return 0;
}
uint32_t read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes)
{
if (lcid == 0) {
LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg;
// 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_SIGNALLING;
liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, &bit_msg);
uint64_t uecri=0;
uint8_t *ue_cri_ptr = (uint8_t*) &uecri;
uint32_t nbytes = bit_msg.N_bits/8;
uint8_t *ptr = bit_msg.msg;
for (int i=0;i<nbytes;i++) {
ue_cri_ptr[nbytes-i-1] = (uint8_t) srslte_bit_unpack(&ptr, 8);
}
mac.set_param(srslte::ue::mac_interface_params::CONTENTION_ID, uecri);
// Send ConnectionRequest Packet
printf("Send ConnectionRequest %d/%d bytes\n", nbytes, nof_bytes);
memcpy(payload, nbytes, nbytes*sizeof(uint8_t));
bzero(&payload[nbytes], (nof_bytes-nbytes)*sizeof(uint8_t));
} else if (lcid == 1) {
if (nsegm_dcch < 2) {
printf("Sending Connection Setup Complete %d length %d\n", nsegm_dcch, lengths[nsegm_dcch]);
memcpy(payload, setupComplete_segm[nsegm_dcch], lengths[nsegm_dcch]);
nsegm_dcch++;
} else if (nsegm_dcch == 2) {
printf("Send RLC ACK\n");
memcpy(payload, reply, 2*sizeof(uint8_t));
nsegm_dcch++;
}
}
}
void write_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) {
if (lcid == 0) {
LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg;
printf("ConnSetup received %d bytes\n", nof_bytes);
srslte_bit_pack_vector(payload, bit_msg.msg, nof_bytes*8);
bit_msg.N_bits = nof_bytes*8;
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]);
switch (dl_ccch_msg.msg_type) {
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP:
// Process ConnectionSetup
process_connsetup(&dl_ccch_msg.msg.rrc_con_setup, &mac, &phy);
connsetup_decoded = true;
break;
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ:
mac.set_param(srslte::ue::mac_interface_params::RNTI_C, 0);
break;
}
} else if (lcid == 1) {
printf("Received on DCCH0 %d bytes\n", nof_bytes);
}
}
void write_pdu_bcch_bch(uint8_t *payload, uint32_t nof_bytes)
{
LIBLTE_RRC_MIB_STRUCT mib;
srslte_bit_pack_vector(payload, bit_msg.msg, nof_bytes*8);
bit_msg.N_bits = nof_bytes*8;
liblte_rrc_unpack_bcch_bch_msg(&bit_msg, &mib);
printf("MIB received %d bytes, BW=%s\n", nof_bytes, liblte_rrc_dl_bandwidth_text[mib.dl_bw]);
mib_decoded = true;
}
void write_pdu_bcch_dlsch(uint8_t *payload, uint32_t nof_bytes)
{
LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT dlsch_msg;
srslte_bit_pack_vector(payload, bit_msg.msg, nof_bytes*8);
bit_msg.N_bits = nof_bytes*8;
liblte_rrc_unpack_bcch_dlsch_msg(&bit_msg, &dlsch_msg);
if (dlsch_msg.N_sibs > 0) {
if (dlsch_msg.sibs[0].sib_type == LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1) {
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",
nof_bytes, dlsch_msg.sibs[0].sib.sib1.cell_id&0xfff, si_window_len, sib2_period);
sib1_decoded = true;
} else if (dlsch_msg.sibs[0].sib_type == LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2) {
printf("SIB2 received %d bytes\n", nof_bytes);
setup_mac_phy_sib2(&dlsch_msg.sibs[0].sib.sib2, &mac, &phy);
sib2_decoded = true;
}
}
}
private:
LIBLTE_BIT_MSG_STRUCT bit_msg;
LIBLTE_BYTE_MSG_STRUCT byte_msg;
};
int main(int argc, char *argv[])
{
srslte::ue::tti_sync_cv ttisync(10240);
srslte::log_stdout mac_log("MAC"), phy_log("PHY");
parse_args(&prog_args, argc, argv);
@ -358,7 +485,6 @@ int main(int argc, char *argv[])
signal(SIGINT, sig_int_handler);
//radio_uhd.start_trace();
phy.start_trace();
mac.start_trace();
}
if (prog_args.do_pcap) {
@ -374,144 +500,32 @@ int main(int argc, char *argv[])
radio_uhd.init();
radio_uhd.set_rx_gain(prog_args.uhd_rx_gain);
radio_uhd.set_tx_gain(prog_args.uhd_tx_gain);
phy.init(&radio_uhd, &ttisync, &phy_log);
phy.init(&radio_uhd, &mac, &phy_log);
} else {
radio_uhd.init_agc();
radio_uhd.set_tx_rx_gain_offset(0);
phy.init_agc(&radio_uhd, &ttisync, &phy_log);
phy.init_agc(&radio_uhd, &mac, &phy_log);
}
// Init MAC
mac.init(&phy, &ttisync, &mac_log);
mac.init(&phy, &my_rlc, &mac_log);
// Set RX freq
radio_uhd.set_rx_freq(prog_args.uhd_rx_freq);
radio_uhd.set_tx_freq(prog_args.uhd_tx_freq);
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, SETUPCOMPLETE, IDLE} 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);
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);
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_SIGNALLING;
liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, &bit_msg);
uint64_t uecri=0;
uint8_t *ue_cri_ptr = (uint8_t*) &uecri;
uint32_t nbytes = bit_msg.N_bits/8;
uint8_t *ptr = bit_msg.msg;
for (int i=0;i<nbytes;i++) {
ue_cri_ptr[nbytes-i-1] = (uint8_t) srslte_bit_unpack(&ptr, 8);
}
mac.set_param(srslte::ue::mac_params::CONTENTION_ID, uecri);
// Send ConnectionRequest Packet
printf("Send ConnectionRequest %d bytes\n", nbytes);
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:
// Wait 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;
srslte_vec_fprint_hex(stdout, bit_msg.msg, 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]);
switch (dl_ccch_msg.msg_type) {
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP:
// Process ConnectionSetup
process_connsetup(&dl_ccch_msg.msg.rrc_con_setup, &mac, &phy);
// Generate and send ConnectionSetupComplete
for (int i=0;i<2;i++) {
printf("Sending Connection Setup Complete %d\n", i);
srslte_bit_pack_vector(setupComplete_segm[i], bit_msg.msg, lengths[i]*8);
n=mac.send_dcch0_sdu(bit_msg.msg, lengths[i]*8);
if (n < 0) {
fprintf(stderr, "Error writting to DCCH0\n");
exit(-1);
}
}
state = SETUPCOMPLETE;
break;
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ:
mac.set_param(srslte::ue::mac_params::RNTI_C, 0);
break;
}
// exit(0);
}
break;
case SETUPCOMPLETE:
// Wait for ConnectionSetup
n = mac.recv_dcch0_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE);
if (n > 0) {
printf("Received on DCCH0 %d bytes\n", n/8);
printf("Send RLC ACK\n");
srslte_bit_pack_vector(reply, bit_msg.msg, 2*8);
n=mac.send_dcch0_sdu(bit_msg.msg, 2*8);
if (n < 0) {
fprintf(stderr, "Error writting to DCCH0\n");
exit(-1);
}
state = IDLE;
}
break;
case IDLE:
break;
uint32_t tti;
if (my_rlc.mib_decoded) {
if (!my_rlc.sib1_decoded) {
tti = mac.get_current_tti();
mac.set_param(srslte::ue::mac_interface_params::BCCH_SI_WINDOW_ST, sib_start_tti(tti, 2, 5));
mac.set_param(srslte::ue::mac_interface_params::BCCH_SI_WINDOW_LEN, 1);
} else {
tti = mac.get_current_tti();
mac.set_param(srslte::ue::mac_interface_params::BCCH_SI_WINDOW_ST, sib_start_tti(tti, my_rlc.sib2_period, 0));
mac.set_param(srslte::ue::mac_interface_params::BCCH_SI_WINDOW_LEN, my_rlc.si_window_len);
}
}
usleep(10000);
}
}

@ -73,6 +73,7 @@ namespace ue {
void worker_end(uint32_t tti, bool tx_enable, cf_t *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time);
bool sr_enabled;
int sr_last_tx_tti;
private:
pthread_mutex_t tx_mutex;

@ -106,6 +106,9 @@ private:
uint16_t ul_rnti;
uint8_t *ul_payload;
// FIXME: THIS IS TEMPORAL. Need to change srslte to accept bits for payload
uint8_t payload_bits[64*1024];
// UL configuration parameters
srslte_refsignal_srs_cfg_t srs_cfg;
srslte_pucch_cfg_t pucch_cfg;

@ -71,7 +71,7 @@ public:
void write_trace(std::string filename);
/********** MAC INTERFACE ********************/
/* Instructs the PHY to configure using the parameters written with set_param() */
/* Instructs the PHY to configure using the parameters written by set_param() */
void configure_prach_params();
void configure_ul_params();
@ -79,11 +79,13 @@ public:
void sync_start();
void sync_stop();
/* Functions to initialize and transmit PRACH in the next opportunity */
void prach_send(prach_cfg_t *cfg);
/* Transmits PRACH in the next opportunity */
void prach_send(uint32_t preamble_idx, int allowed_subframe = -1, float target_power_dbm = 0.0);
int prach_tx_tti();
/* Indicates the transmission of a SR signal in the next opportunity */
void sr_send();
int sr_last_tx_tti();
// Time advance commands
void set_timeadv_rar(uint32_t ta_cmd);

@ -49,10 +49,9 @@ namespace ue {
void init(phy_params *params_db, log *log_h);
bool init_cell(srslte_cell_t cell);
void free_cell();
bool prepare_to_send(phy_interface::prach_cfg_t* cfg);
bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe = -1, float target_power_dbm = -1);
bool is_ready_to_send(uint32_t current_tti);
void get_rar_cfg(uint16_t* rar_rnti, uint32_t* tti_start, uint32_t* tti_end);
int tx_tti();
bool send(radio* radio_handler, float cfo, srslte_timestamp_t rx_time);
@ -66,12 +65,11 @@ namespace ue {
uint32_t len;
cf_t *buffer[64];
srslte_prach_t prach_obj;
uint32_t transmitted_tti;
int transmitted_tti;
srslte_cell_t cell;
cf_t *signal_buffer;
srslte_cfo_t cfo_h;
phy_interface::prach_cfg_t prach_cfg;
};
}

@ -201,7 +201,7 @@ bool phch_recv::cell_search(int force_N_id_2)
if (ret == 1) {
srslte_pbch_mib_unpack(bch_payload, &cell, NULL);
srslte_cell_fprint(stdout, &cell, 0);
mac->bch_decoded_ok(bch_payload);
mac->bch_decoded_ok(bch_payload, SRSLTE_BCH_PAYLOAD_LEN);
return true;
} else {
Warning("Error decoding MIB: Error decoding PBCH\n");
@ -305,16 +305,11 @@ void phch_recv::run_thread()
if (prach_buffer->is_ready_to_send(tti)) {
srslte_timestamp_t cur_time;
radio_h->get_time(&cur_time);
Info("TX PRACH now. RX time: %d:%f, Now: %d:%f\n", rx_time.full_secs, rx_time.frac_secs, cur_time.full_secs, cur_time.frac_secs);
Info("TX PRACH now. RX time: %d:%f, Now: %d:%f\n", rx_time.full_secs, rx_time.frac_secs,
cur_time.full_secs, cur_time.frac_secs);
// send prach if we have to
prach_buffer->send(radio_h, cfo, tx_time);
radio_h->tx_end();
/* Setup DL RNTI search to look for RAR as configured by MAC */
uint16_t rar_rnti;
uint32_t rar_start, rar_end;
prach_buffer->get_rar_cfg(&rar_rnti, &rar_start, &rar_end);
worker_com->set_dl_rnti(SRSLTE_RNTI_RAR, rar_rnti, (int) rar_start, (int) rar_end);
radio_h->tx_end();
}
workers_pool->start_worker(worker);
}

@ -158,6 +158,9 @@ void phch_worker::work_imp()
dl_ack = decode_pdsch(&dl_action.phy_grant.dl, dl_action.payload_ptr, dl_action.softbuffer, dl_action.rv, dl_action.rnti);
phy->mac->tb_decoded_ok(dl_mac_grant.pid);
}
if (dl_action.generate_ack_callback) {
dl_action.generate_ack = dl_action.generate_ack_callback(dl_action.generate_ack_callback_arg);
}
if (dl_action.generate_ack) {
set_uci_ack(dl_ack);
}
@ -273,7 +276,7 @@ bool phch_worker::decode_pdcch_dl(srslte::ue::mac_interface_phy::mac_grant_t* gr
/* Fill MAC grant structure */
grant->ndi = dci_unpacked.ndi;
grant->pid = dci_unpacked.harq_process;
grant->tbs = grant->phy_grant.dl.mcs.tbs;
grant->n_bytes = grant->phy_grant.dl.mcs.tbs/8;
grant->tti = tti;
grant->rv = dci_unpacked.rv_idx;
grant->rnti = dl_rnti;
@ -299,8 +302,10 @@ bool phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload,
if (ue_dl.pdsch_cfg.grant.mcs.mod > 0 && ue_dl.pdsch_cfg.grant.mcs.tbs >= 0) {
if (srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffer, ue_dl.sf_symbols,
ue_dl.ce, 0, rnti, payload) == 0)
ue_dl.ce, 0, rnti, payload_bits) == 0)
{
// FIXME: TEMPORAL
srslte_bit_unpack_vector(payload_bits, payload, grant->mcs.tbs);
Debug("TB decoded OK\n");
return true;
} else {
@ -354,6 +359,7 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
Error("Converting RAR message to UL grant\n");
return false;
}
grant->is_from_rar = true;
Info("RAR grant found for TTI=%d\n", tti);
rar_cqi_request = rar_grant.cqi_request;
ret = true;
@ -372,6 +378,7 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
Error("Converting DCI message to UL grant\n");
return false;
}
grant->is_from_rar = false;
ret = true;
Info("PDCCH: UL DCI Format0 cce_index=%d, n_data_bits=%d\n", ue_dl.last_n_cce, dci_msg.nof_bits);
}
@ -379,7 +386,7 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
if (ret) {
grant->ndi = dci_unpacked.ndi;
grant->pid = 0; // This is computed by MAC from TTI
grant->tbs = grant->phy_grant.ul.mcs.tbs;
grant->n_bytes = grant->phy_grant.ul.mcs.tbs/8;
grant->tti = tti;
grant->rnti = ul_rnti;
@ -412,6 +419,7 @@ void phch_worker::set_uci_sr()
if (srslte_ue_ul_sr_send_tti(I_sr, tti+4)) {
Info("SR transmission at TTI=%d\n", tti+4);
uci_data.scheduling_request = true;
phy->sr_last_tx_tti = tti+4;
phy->sr_enabled = false;
}
}
@ -457,8 +465,11 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint32_t current_tx_
Error("Configuring UL grant\n");
}
// FIXME: TEMPORAL
srslte_bit_pack_vector(ul_payload, payload_bits, grant->mcs.tbs);
if (srslte_ue_ul_pusch_encode_rnti_softbuffer(&ue_ul,
ul_payload, uci_data,
payload_bits, uci_data,
softbuffer,
rnti,
signal_buffer))

@ -187,14 +187,19 @@ void phy::get_current_cell(srslte_cell_t *cell)
sf_recv.get_current_cell(cell);
}
void phy::prach_send(phy_interface::prach_cfg_t* cfg)
void phy::prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm)
{
if (!prach_buffer.prepare_to_send(cfg)) {
if (!prach_buffer.prepare_to_send(preamble_idx, allowed_subframe, target_power_dbm)) {
Error("Preparing PRACH to send\n");
}
}
int phy::prach_tx_tti()
{
return prach_buffer.tx_tti();
}
void phy::reset()
{
// TODO
@ -210,6 +215,11 @@ void phy::sr_send()
workers_common.sr_enabled = true;
}
int phy::sr_last_tx_tti()
{
return workers_common.sr_last_tx_tti;
}
bool phy::status_is_sync()
{
return sf_recv.status_is_sync();

@ -95,16 +95,6 @@ bool prach::init_cell(srslte_cell_t cell_)
return initiated;
}
bool prach::prepare_to_send(phy_interface::prach_cfg_t* cfg)
{
int allowed_sf = cfg->allowed_subframe_enabled?(int) cfg->allowed_subframe:-1;
bool ret = prepare_to_send(cfg->preamble_idx, allowed_sf, cfg->target_power_dbm);
if (ret) {
memcpy(&prach_cfg, cfg, sizeof(phy_interface::prach_cfg_t));
}
return ret;
}
bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_, float target_power_dbm)
{
if (initiated && preamble_idx_ < 64) {
@ -137,17 +127,8 @@ bool prach::is_ready_to_send(uint32_t current_tti_) {
return false;
}
void prach::get_rar_cfg(uint16_t *rar_rnti, uint32_t *tti_start, uint32_t *tti_end)
{
if (rar_rnti) {
*rar_rnti = prach_cfg.rar_rnti;
}
if (tti_start) {
*tti_start = transmitted_tti + prach_cfg.rar_start;
}
if (tti_end) {
*tti_end = transmitted_tti + prach_cfg.rar_start + prach_cfg.rar_window;
}
int prach::tx_tti() {
return transmitted_tti;
}
bool prach::send(radio *radio_handler, float cfo, srslte_timestamp_t tx_time)

@ -202,9 +202,26 @@ uint16_t temp_c_rnti;
class testmac : public srslte::ue::mac_interface_phy
{
public:
testmac() {
rar_rnti_set = false;
}
bool rar_rnti_set;
void tti_clock(uint32_t tti) {
if (!rar_rnti_set) {
int prach_tti = my_phy.prach_tx_tti();
if (prach_tti > 0) {
my_phy.pdcch_dl_search(SRSLTE_RNTI_RAR, 1+prach_tti%10, prach_tti+3, 10);
rar_rnti_set = true;
}
}
}
void new_grant_ul(mac_grant_t grant, uint8_t *payload_ptr, tb_action_ul_t *action) {
printf("New grant UL\n");
srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload_ptr, grant.tbs);
srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload_ptr, grant.n_bytes*8);
action->current_tx_nb = nof_rtx_connsetup;
action->rv = rv_value[nof_rtx_connsetup%4];
action->softbuffer = &softbuffer_tx;
@ -272,7 +289,7 @@ public:
temp_c_rnti = rar_msg.temp_c_rnti;
if (last_grant.tbs > 20 + SRSLTE_RAR_GRANT_LEN) {
if (last_grant.n_bytes*8 > 20 + SRSLTE_RAR_GRANT_LEN) {
uint8_t rar_grant[SRSLTE_RAR_GRANT_LEN];
memcpy(rar_grant, &payload[20], sizeof(uint8_t)*SRSLTE_RAR_GRANT_LEN);
my_phy.set_rar_grant(last_grant.tti, rar_grant);
@ -286,14 +303,15 @@ public:
}
}
void bch_decoded_ok(uint8_t *payload) {
void bch_decoded_ok(uint8_t *payload, uint32_t len) {
printf("BCH decoded\n");
bch_decoded = true;
srslte_cell_t cell;
my_phy.get_current_cell(&cell);
srslte_softbuffer_rx_init(&softbuffer_rx, cell);
srslte_softbuffer_tx_init(&softbuffer_tx, cell);
srslte_softbuffer_rx_init(&softbuffer_rx, cell.nof_prb);
srslte_softbuffer_tx_init(&softbuffer_tx, cell.nof_prb);
}
private:
mac_grant_t last_grant;
};
@ -347,13 +365,7 @@ int main(int argc, char *argv[])
config_phy();
/* Instruct PHY to send PRACH and prepare it for receiving RAR */
srslte::ue::phy_interface::prach_cfg_t prach_cfg;
prach_cfg.allowed_subframe_enabled = false;
prach_cfg.preamble_idx = preamble_idx;
prach_cfg.rar_rnti = 2;
prach_cfg.rar_start = 3;
prach_cfg.rar_window = 10;
my_phy.prach_send(&prach_cfg);
my_phy.prach_send(preamble_idx);
/* go to idle and process each tti */
bool running = true;

@ -127,13 +127,14 @@ public:
total_oks++;
}
void bch_decoded_ok(uint8_t *payload) {
void bch_decoded_ok(uint8_t *payload, uint32_t len) {
printf("BCH decoded\n");
bch_decoded = true;
srslte_cell_t cell;
my_phy.get_current_cell(&cell);
srslte_softbuffer_rx_init(&softbuffer, cell);
srslte_softbuffer_rx_init(&softbuffer, cell.nof_prb);
}
void tti_clock(uint32_t tti) {
}
};

@ -259,7 +259,7 @@ void base_init() {
srslte_pdsch_set_rnti(&pdsch, UE_CRNTI);
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
fprintf(stderr, "Error initiating soft buffer\n");
exit(-1);
}

@ -53,14 +53,14 @@ typedef struct SRSLTE_API {
} srslte_softbuffer_tx_t;
SRSLTE_API int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t * q,
srslte_cell_t cell);
uint32_t nof_prb);
SRSLTE_API void srslte_softbuffer_rx_reset(srslte_softbuffer_rx_t *p);
SRSLTE_API void srslte_softbuffer_rx_free(srslte_softbuffer_rx_t *p);
SRSLTE_API int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t * q,
srslte_cell_t cell);
uint32_t nof_prb);
SRSLTE_API void srslte_softbuffer_tx_reset(srslte_softbuffer_tx_t *p);

@ -44,7 +44,7 @@
#define MAX_PDSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12)
int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t *q, srslte_cell_t cell) {
int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t *q, uint32_t nof_prb) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL) {
@ -52,7 +52,7 @@ int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t *q, srslte_cell_t cell) {
bzero(q, sizeof(srslte_softbuffer_rx_t));
ret = srslte_ra_tbs_from_idx(26, cell.nof_prb);
ret = srslte_ra_tbs_from_idx(26, nof_prb);
if (ret != SRSLTE_ERROR) {
q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1;
@ -106,7 +106,7 @@ void srslte_softbuffer_rx_reset(srslte_softbuffer_rx_t *q) {
int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t *q, srslte_cell_t cell) {
int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t *q, uint32_t nof_prb) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL) {
@ -114,7 +114,7 @@ int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t *q, srslte_cell_t cell) {
bzero(q, sizeof(srslte_softbuffer_tx_t));
ret = srslte_ra_tbs_from_idx(26, cell.nof_prb);
ret = srslte_ra_tbs_from_idx(26, nof_prb);
if (ret != SRSLTE_ERROR) {
q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1;

@ -91,7 +91,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mxFree(mod_str);
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
mexErrMsgTxt("Error initiating DL-SCH soft buffer\n");
return;
}

@ -183,12 +183,12 @@ int main(int argc, char **argv) {
srslte_pdsch_set_rnti(&pdsch, 1234);
if (srslte_softbuffer_tx_init(&softbuffer_tx, cell)) {
if (srslte_softbuffer_tx_init(&softbuffer_tx, cell.nof_prb)) {
fprintf(stderr, "Error initiating TX soft buffer\n");
goto quit;
}
if (srslte_softbuffer_rx_init(&softbuffer_rx, cell)) {
if (srslte_softbuffer_rx_init(&softbuffer_rx, cell.nof_prb)) {
fprintf(stderr, "Error initiating RX soft buffer\n");
goto quit;
}

@ -93,7 +93,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
}
srslte_pdsch_set_rnti(&pdsch, (uint16_t) (rnti32 & 0xffff));
if (srslte_softbuffer_rx_init(&softbuffer, cell)) {
if (srslte_softbuffer_rx_init(&softbuffer, cell.nof_prb)) {
mexErrMsgTxt("Error initiating soft buffer\n");
return;
}

@ -139,7 +139,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_softbuffer_tx_t softbuffer;
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
mexErrMsgTxt("Error initiating soft buffer\n");
return;
}

@ -207,7 +207,7 @@ int main(int argc, char **argv) {
}
gettimeofday(&t[1], NULL);
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
fprintf(stderr, "Error initiating soft buffer\n");
goto quit;
}

@ -69,7 +69,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
cell.id=1;
cell.cp=SRSLTE_CP_NORM;
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
mexErrMsgTxt("Error initiating HARQ\n");
return;
}

@ -86,7 +86,7 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
fprintf(stderr, "Error creating PDSCH object\n");
goto clean_exit;
}
if (srslte_softbuffer_rx_init(&q->softbuffer, q->cell)) {
if (srslte_softbuffer_rx_init(&q->softbuffer, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit;
}

@ -74,7 +74,7 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit;
}
if (srslte_softbuffer_tx_init(&q->softbuffer, q->cell)) {
if (srslte_softbuffer_tx_init(&q->softbuffer, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit;
}

Loading…
Cancel
Save