MAC/PHY compiling

master
ismagom 10 years ago
parent f65aa3be1d
commit 309ebd80e5

@ -53,9 +53,12 @@ public:
uint32_t pid; uint32_t pid;
uint32_t tti; uint32_t tti;
bool ndi; bool ndi;
uint32_t tbs; uint32_t n_bytes;
uint32_t rv; uint32_t rv;
uint16_t rnti; uint16_t rnti;
bool is_from_rar;
bool is_sps_release;
srslte_rnti_type_t rnti_type;
srslte_phy_grant_t phy_grant; srslte_phy_grant_t phy_grant;
} mac_grant_t; } mac_grant_t;
@ -65,6 +68,9 @@ public:
uint16_t rnti; uint16_t rnti;
bool generate_ack; bool generate_ack;
bool default_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; uint8_t *payload_ptr;
srslte_softbuffer_rx_t *softbuffer; srslte_softbuffer_rx_t *softbuffer;
srslte_phy_grant_t phy_grant; srslte_phy_grant_t phy_grant;
@ -97,7 +103,7 @@ public:
virtual void tb_decoded_ok(uint32_t harq_pid) = 0; virtual void tb_decoded_ok(uint32_t harq_pid) = 0;
/* Indicate successfull decoding of BCH TB through PBCH */ /* 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 /* Function called every start of a subframe (TTI). Warning, this function is called
* from a high priority thread and should terminate asap * from a high priority thread and should terminate asap
@ -113,7 +119,9 @@ public:
/* RLC configures a logical channel */ /* 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 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 reconfiguration() = 0;
virtual void reset() = 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 */ /* 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; 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. */ /* MAC calls RLC to get RLC segment of nof_bytes length. Segmentation happens in this function. RLC PDU is stored in
virtual void read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) = 0; * 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 /* MAC calls RLC to push an RLC PDU. This function is called from an independent MAC thread. PDU gets placed into the
when the last segment is received * 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(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_SCHED_INTERVAL,
SPS_DL_NOF_PROC, SPS_DL_NOF_PROC,
RNTI_TEMP,
RNTI_C,
BCCH_SI_WINDOW_ST, BCCH_SI_WINDOW_ST,
BCCH_SI_WINDOW_LEN, BCCH_SI_WINDOW_LEN,

@ -133,23 +133,12 @@ public:
virtual void sync_start() = 0; virtual void sync_start() = 0;
virtual void sync_stop() = 0; virtual void sync_stop() = 0;
/* Functions to initialize and transmit PRACH in the next opportunity. virtual void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) = 0;
* This function returns at the start of the rar reception window, ie the transmission virtual int prach_tx_tti() = 0;
* 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;
/* Indicates the transmission of a SR signal in the next opportunity */ /* Indicates the transmission of a SR signal in the next opportunity */
virtual void sr_send() = 0; virtual void sr_send() = 0;
virtual int sr_last_tx_tti() = 0;
/* Time advance commands */ /* Time advance commands */
virtual void set_timeadv_rar(uint32_t ta_cmd) = 0; 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) #include <pthread.h>
{ #include "srsapps/common/tti_sync.h"
return NULL;
}
void dl_sps::reset(uint32_t tti, dl_sched_grant* grant)
{
} #ifndef TTISYNC_CV_H
void dl_sps::clear() #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/ue/phy/phy.h"
#include "srsapps/common/mac_interface.h"
#include "srsapps/common/log.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/common/timers.h"
#include "srsapps/ue/mac/mac_params.h" #include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/pdu.h" #include "srsapps/ue/mac/pdu.h"
#include "srsapps/ue/mac/sdu_handler.h"
#ifndef DEMUX_H #ifndef DEMUX_H
#define DEMUX_H #define DEMUX_H
@ -47,13 +47,15 @@ class demux
{ {
public: public:
demux(); 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_temp_crnti_pending();
bool is_contention_resolution_id_pending(); bool is_contention_resolution_id_pending();
void demultiplex_pending_pdu(); void demultiplex_pending_pdu();
@ -62,24 +64,38 @@ public:
uint64_t get_contention_resolution_id(); uint64_t get_contention_resolution_id();
private: 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 mac_msg;
sch_pdu pending_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); bool process_ce(sch_subh *subheader);
bool find_unused_queue(uint8_t *idx);
// Mutex for exclusive access bool find_nonempty_queue(uint8_t *idx);
pthread_mutex_t mutex; void push_buffer(uint8_t *buff, uint32_t nof_bytes);
uint64_t contention_resolution_id; uint64_t contention_resolution_id;
bool pending_temp_rnti; bool pending_temp_rnti;
bool has_pending_contention_resolution_id; 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; // Mutex for exclusive access
log *log_h; pthread_mutex_t mutex;
mac_io *mac_io_h; pthread_cond_t cvar;
timers *timers_db; qbuff pdu_q[NOF_PDU_Q];
sdu_handler *sdu_handler_; 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/ue/mac/mac_params.h"
#include "srsapps/common/timers.h" #include "srsapps/common/timers.h"
#include "srsapps/ue/mac/demux.h" #include "srsapps/ue/mac/demux.h"
#include "srsapps/ue/mac/dl_sps.h"
#include "srsapps/ue/mac/mac_pcap.h" #include "srsapps/ue/mac/mac_pcap.h"
#ifndef DLHARQ_H #ifndef DLHARQ_H
@ -43,8 +44,6 @@
namespace srslte { namespace srslte {
namespace ue { namespace ue {
typedef _Complex float cf_t;
class dl_harq_entity class dl_harq_entity
{ {
public: public:
@ -53,49 +52,56 @@ public:
const static uint32_t HARQ_BCCH_PID = NOF_HARQ_PROC; const static uint32_t HARQ_BCCH_PID = NOF_HARQ_PROC;
dl_harq_entity(); dl_harq_entity();
bool init(srslte_cell_t cell, uint32_t max_payload_len, srslte::log *log_h_, timers *timers_, demux *demux_unit); bool init(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); /***************** 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(); void reset();
bool is_ack_pending_resolution();
void send_pending_ack_contention_resolution();
void start_pcap(mac_pcap* pcap); void start_pcap(mac_pcap* pcap);
private: private:
class dl_harq_process { class dl_harq_process {
public: public:
dl_harq_process(); dl_harq_process();
bool init(srslte_cell_t cell, uint32_t max_payload_len, dl_harq_entity *parent); bool init(uint32_t pid, 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);
void reset(); void reset();
// Called after the contention resolution is terminated to send pending ACKs, if any bool is_sps();
void send_pending_ack_contention_resolution(); bool is_new_transmission(mac_interface_phy::mac_grant_t grant);
uint32_t pid; void new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t *action);
void tb_decoded_ok();
private: private:
bool is_initiated; bool is_initiated;
dl_harq_entity *harq_entity; dl_harq_entity *harq_entity;
uint8_t *payload; log *log_h;
uint32_t max_payload_len;
dl_sched_grant cur_grant; uint32_t pid;
dl_sched_grant pending_ack_grant; uint8_t *payload_buffer_ptr;
ul_buffer *pending_ul_buffer; bool ack;
bool pending_ack;
srslte::log *log_h; 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; timers *timers_db;
demux *demux_unit; demux *demux_unit;
srslte::log *log_h; log *log_h;
int pending_ack_pid;
mac_pcap *pcap; mac_pcap *pcap;
uint16_t last_temporal_crnti;
}; };
} }

@ -41,15 +41,15 @@
namespace srslte { namespace srslte {
namespace ue { namespace ue {
typedef _Complex float cf_t;
class dl_sps class dl_sps
{ {
public: public:
void clear(); void clear() {}
void reset(uint32_t tti, dl_sched_grant *grant); void reset() {}
dl_sched_grant *get_pending_grant(uint32_t tti); bool get_pending_grant(uint32_t tti, mac_interface_phy::mac_grant_t *grant) {
return false;
}
private: private:
}; };

@ -25,29 +25,22 @@
* *
*/ */
#include <pthread.h>
#include "srsapps/common/log.h" #include "srsapps/common/log.h"
#include "srsapps/ue/phy/phy.h" #include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/mac/mac_params.h" #include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/dl_harq.h" #include "srsapps/ue/mac/dl_harq.h"
#include "srsapps/ue/mac/ul_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/common/timers.h"
#include "srsapps/ue/mac/mac_io.h"
#include "srsapps/ue/mac/proc_ra.h" #include "srsapps/ue/mac/proc_ra.h"
#include "srsapps/ue/mac/proc_sr.h" #include "srsapps/ue/mac/proc_sr.h"
#include "srsapps/ue/mac/proc_bsr.h" #include "srsapps/ue/mac/proc_bsr.h"
#include "srsapps/ue/mac/proc_phr.h" #include "srsapps/ue/mac/proc_phr.h"
#include "srsapps/ue/mac/mux.h" #include "srsapps/ue/mac/mux.h"
#include "srsapps/ue/mac/demux.h" #include "srsapps/ue/mac/demux.h"
#include "srsapps/ue/mac/sdu_handler.h"
#include "srsapps/ue/mac/mac_pcap.h" #include "srsapps/ue/mac/mac_pcap.h"
#include "srsapps/common/trace.h"
#include "srsapps/common/mac_interface.h" #include "srsapps/common/mac_interface.h"
#include "srsapps/common/tti_sync_cv.h"
#include "srsapps/common/threads.h"
#ifndef UEMAC_H #ifndef UEMAC_H
@ -56,95 +49,68 @@
namespace srslte { namespace srslte {
namespace ue { namespace ue {
typedef _Complex float cf_t; class mac : public thread, timer_callback, mac_interface_phy, mac_interface_rlc, mac_interface_params
class mac : public timer_callback, mac_interface_phy, mac_interface_rlc
{ {
public: 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; } mac();
bool init(phy *phy_h, tti_sync *ttisync, log *log_h); bool init(phy_interface *phy, rlc_interface_mac *rlc, log *log_h);
void stop(); 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); /******** Interface from PHY (PHY -> MAC) ****************/
int recv_bcch_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes); /* see mac_interface.h for comments */
int recv_ccch_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes); void new_grant_ul(mac_grant_t grant, uint8_t *payload_ptr, tb_action_ul_t *action);
int recv_dtch0_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes); // SRB0 void new_grant_ul_ack(mac_grant_t grant, uint8_t *payload_ptr, bool ack, tb_action_ul_t *action);
int recv_dcch0_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes); // DRB0 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 reconfiguration();
void reset(); void reset();
void start_trace(); /******** MAC parameters ****************/
void write_trace(std::string filename); 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 timer_expired(uint32_t timer_id);
void start_pcap(mac_pcap* pcap); void start_pcap(mac_pcap* pcap);
uint32_t get_current_tti();
enum { enum {
HARQ_RTT = 0, HARQ_RTT,
TIME_ALIGNMENT, TIME_ALIGNMENT,
CONTENTION_TIMER, CONTENTION_TIMER,
BSR_TIMER_PERIODIC, BSR_TIMER_PERIODIC,
BSR_TIMER_RETX, BSR_TIMER_RETX,
NOF_MAC_TIMERS NOF_MAC_TIMERS
} mac_timers_t; } 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: 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 static const int MAC_THREAD_PRIO = 5;
tti_sync *ttisync;
phy *phy_h;
log *log_h;
/* Logical channel (lch) IO */ // Interaction with PHY
mac_io mac_io_lch; tti_sync_cv ttisync;
phy_interface *phy_h;
rlc_interface_mac *rlc_h;
log *log_h;
mac_params params_db; mac_params params_db;
pthread_t mac_thread;
static void* mac_thread_fnc(void*);
int tti; uint32_t tti;
bool started; bool started;
bool is_synchronized; bool is_synchronized;
uint16_t last_temporal_crnti; uint16_t last_temporal_crnti;
uint16_t phy_rnti;
/* Multiplexing/Demultiplexing Units */ /* Multiplexing/Demultiplexing Units */
mux mux_unit; mux mux_unit;
@ -154,46 +120,22 @@ private:
dl_harq_entity dl_harq; dl_harq_entity dl_harq;
ul_harq_entity ul_harq; ul_harq_entity ul_harq;
/* DL/UL Semi-Persistent Sched */ int si_window_start, si_window_length;
dl_sps dl_sps_assig;
ul_sps ul_sps_assig;
uint32_t get_harq_sps_pid(uint32_t tti);
/* MAC Uplink-related Procedures */ /* MAC Uplink-related Procedures */
ra_proc ra_procedure; ra_proc ra_procedure;
sr_proc sr_procedure; sr_proc sr_procedure;
bsr_proc bsr_procedure; bsr_proc bsr_procedure;
phr_proc phr_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 */ /* Functions for MAC Timers */
timers timers_db; timers timers_db;
uint16_t phy_rnti;
void setup_timers(); void setup_timers();
void timeAlignmentTimerExpire(); void timeAlignmentTimerExpire();
// pointer to MAC PCAP object // pointer to MAC PCAP object
mac_pcap* pcap; 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 "srslte/srslte.h"
#include "srsapps/common/params_db.h" #include "srsapps/common/params_db.h"
#include "srsapps/common/mac_interface.h"
#ifndef MACPARAMS_H #ifndef MACPARAMS_H
#define MACPARAMS_H #define MACPARAMS_H
@ -41,7 +42,7 @@ namespace ue {
{ {
public: public:
mac_params() : params_db(NOF_PARAMS) {} mac_params() : params_db(mac_interface_params::NOF_PARAMS) {}
~mac_params() {} ~mac_params() {}

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

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

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

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

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

@ -25,13 +25,11 @@
* *
*/ */
#include "srsapps/common/mac_interface.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/log.h" #include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac_params.h" #include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mux.h" #include "srsapps/ue/mac/mux.h"
#include "srsapps/ue/mac/ul_sps.h"
#include "srsapps/ue/mac/mac_pcap.h" #include "srsapps/ue/mac/mac_pcap.h"
#include "srsapps/common/timers.h" #include "srsapps/common/timers.h"
@ -43,8 +41,6 @@
namespace srslte { namespace srslte {
namespace ue { namespace ue {
typedef _Complex float cf_t;
class ul_harq_entity class ul_harq_entity
{ {
public: public:
@ -52,56 +48,73 @@ public:
const static uint32_t NOF_HARQ_PROC = 8; const static uint32_t NOF_HARQ_PROC = 8;
static uint32_t pidof(uint32_t tti); static uint32_t pidof(uint32_t tti);
ul_harq_entity() { pcap = NULL; } ul_harq_entity() { pcap = NULL; }
bool init(srslte_cell_t cell, mac_params *params_db, log *log_h, timers* timers_, mux *mux_unit); bool init(log *log_h, mac_params *params_db, timers* timers_, mux *mux_unit);
void reset(); void reset();
void reset_ndi(); 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); 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: private:
class ul_harq_process { class ul_harq_process {
public: public:
ul_harq_process(); 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();
void reset_ndi(); 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_retx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action);
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::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(); uint32_t get_rv();
bool has_grant(); bool has_grant();
ul_sched_grant *get_grant();
void set_harq_feedback(bool ack); void set_harq_feedback(bool ack);
bool get_ndi(); bool get_ndi();
bool is_sps();
uint32_t last_tx_tti(); uint32_t last_tx_tti();
uint32_t pid; uint32_t get_nof_retx();
private: private:
mac_interface_phy::mac_grant_t cur_grant;
uint32_t pid;
uint32_t current_tx_nb; uint32_t current_tx_nb;
uint32_t current_irv; uint32_t current_irv;
bool harq_feedback; bool harq_feedback;
bool ndi; bool ndi;
log *log_h; log *log_h;
ul_harq_entity *harq_entity; ul_harq_entity *harq_entity;
ul_sched_grant cur_grant;
bool is_grant_configured; bool is_grant_configured;
srslte_softbuffer_tx_t softbuffer; srslte_softbuffer_tx_t softbuffer;
bool is_msg3; bool is_msg3;
bool is_initiated; bool is_initiated;
uint32_t tti_last_tx; 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; timers *timers_db;
mux *mux_unit; mux *mux_unit;
ul_harq_process proc[NOF_HARQ_PROC]; ul_harq_process proc[NOF_HARQ_PROC];

@ -48,8 +48,8 @@ class ul_sps
public: public:
void clear() {} void clear() {}
void reset(uint32_t tti, sched_grant *grant) {} void reset(uint32_t tti) {}
ul_sched_grant *get_pending_grant(uint32_t tti) { return NULL; } bool get_pending_grant(uint32_t tti, mac_interface_phy::mac_grant_t *grant) { return false; }
private: private:
}; };

@ -30,32 +30,30 @@
#include "srsapps/ue/mac/demux.h" #include "srsapps/ue/mac/demux.h"
namespace srslte { 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; contention_resolution_id = 0;
pending_temp_rnti = false; pending_temp_rnti = false;
has_pending_contention_resolution_id = 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_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_; phy_h = phy_h_;
log_h = log_h_; log_h = log_h_;
mac_io_h = mac_io_h_; rlc = rlc_;
timers_db = timers_db_; timers_db = timers_db_;
} }
void demux::add_sdu_handler(sdu_handler* handler)
{
sdu_handler_ = handler;
}
bool demux::is_temp_crnti_pending() bool demux::is_temp_crnti_pending()
{ {
return pending_temp_rnti; return pending_temp_rnti;
@ -73,28 +71,95 @@ uint64_t demux::get_contention_resolution_id()
return x; 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 /* 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"); 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 /* Demultiplexing of MAC PDU associated with a Temporal C-RNTI. The PDU will
* remain in buffer until demultiplex_pending_pdu() is called. * remain in buffer until demultiplex_pending_pdu() is called.
* This features is provided to enable the Random Access Procedure to decide * 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 * 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) { if (!pending_temp_rnti) {
// Unpack DLSCH MAC PDU // Unpack DLSCH MAC PDU
pending_mac_msg.init(nof_bits/8); pending_mac_msg.init(nof_bytes);
pending_mac_msg.parse_packet(mac_pdu); pending_mac_msg.parse_packet(buff);
//pending_mac_msg.fprint(stdout); //pending_mac_msg.fprint(stdout);
// Look for Contention Resolution UE ID // 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_mac_msg.reset();
pending_temp_rnti = true; pending_temp_rnti = true;
Debug("Saved MAC PDU with Temporal C-RNTI in buffer\n"); Debug("Saved MAC PDU with Temporal C-RNTI in buffer\n");
push_buffer(buff, 0);
} else { } else {
Warning("Error pushing PDU with Temporal C-RNTI: Another PDU is still in pending\n"); Warning("Error pushing PDU with Temporal C-RNTI: Another PDU is still in pending\n");
} }
} }
/* Demultiplexing of logical channels and dissassemble of MAC CE */ /* Demultiplexing of logical channels and dissassemble of MAC CE
void demux::push_pdu(uint8_t *mac_pdu, uint32_t nof_bits) * 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 // Unpack DLSCH MAC PDU
mac_msg.init(nof_bits/8); mac_msg.init(nof_bytes);
mac_msg.parse_packet(mac_pdu); mac_msg.parse_packet(mac_pdu);
//mac_msg.fprint(stdout); mac_msg.fprint(stdout);
process_pdu(&mac_msg); process_sch_pdu(&mac_msg);
Debug("Normal MAC PDU processed\n"); Debug("Normal MAC PDU processed\n");
pthread_mutex_unlock(&mutex);
} }
void demux::discard_pending_pdu() void demux::discard_pending_pdu()
@ -138,40 +221,21 @@ void demux::discard_pending_pdu()
void demux::demultiplex_pending_pdu() void demux::demultiplex_pending_pdu()
{ {
if (pending_temp_rnti) { if (pending_temp_rnti) {
process_pdu(&pending_mac_msg); process_sch_pdu(&pending_mac_msg);
discard_pending_pdu(); discard_pending_pdu();
} else { } else {
Error("Error demultiplex pending PDU: No pending PDU\n"); Error("Error demultiplex pending PDU: No pending PDU\n");
} }
} }
void demux::process_sch_pdu(sch_pdu *pdu_msg)
void demux::process_pdu(sch_pdu *pdu_msg)
{ {
while(pdu_msg->next()) { while(pdu_msg->next()) {
if (pdu_msg->get()->is_sdu()) { if (pdu_msg->get()->is_sdu()) {
// Route logical channel // Route logical channel
if (pdu_msg->get()->get_sdu_lcid() <= mac_io::MAC_LCH_DTCH2_DL) { rlc->write_pdu(pdu_msg->get()->get_sdu_lcid(), pdu_msg->get()->get_sdu_ptr(), pdu_msg->get()->get_sdu_nbytes());
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
} else { } else {
// Process MAC Control Element
if (!process_ce(pdu_msg->get())) { if (!process_ce(pdu_msg->get())) {
Warning("Received Subheader with invalid or unkonwn LCID\n"); 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) { bool demux::process_ce(sch_subh *subh) {
switch(subh->ce_type()) { switch(subh->ce_type()) {
case sch_subh::CON_RES_ID: case sch_subh::CON_RES_ID:

@ -26,7 +26,6 @@
*/ */
#include "srsapps/ue/phy/phy.h" #include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/phy/dl_sched_grant.h"
#include "srsapps/ue/mac/mac.h" #include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/dl_harq.h" #include "srsapps/ue/mac/dl_harq.h"
@ -43,19 +42,15 @@ namespace srslte {
dl_harq_entity::dl_harq_entity() 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; 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_; timers_db = timers_;
demux_unit = demux_unit_; demux_unit = demux_unit_;
log_h = log_h_; log_h = log_h_;
for (uint32_t i=0;i<NOF_HARQ_PROC+1;i++) { 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; return false;
} }
} }
@ -68,190 +63,241 @@ void dl_harq_entity::start_pcap(mac_pcap* pcap_)
pcap = pcap_; pcap = pcap_;
} }
bool dl_harq_entity::is_sps(uint32_t pid) void dl_harq_entity::reset()
{
return false;
}
void dl_harq_entity::set_harq_info(uint32_t pid, dl_sched_grant* grant)
{ {
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) uint32_t dl_harq_entity::get_harq_sps_pid(uint32_t tti) {
{ /*
proc[pid%(NOF_HARQ_PROC+1)].receive_data(tti, dl_buffer, phy_h); 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()) { demux *demux_unit = (demux*) arg;
proc[pending_ack_pid].send_pending_ack_contention_resolution(); return demux_unit->is_contention_resolution_id_pending();
pending_ack_pid = -1;
}
} }
/*********************************************************** /***********************************************************
* *
* HARQ PROCESS * 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; is_initiated = false;
ack = false; ack = false;
bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant)); bzero(&cur_grant, sizeof(mac_interface_phy::mac_grant_t));
payload = NULL;
max_payload_len = 0;
} }
void dl_harq_entity::dl_harq_process::reset() { void dl_harq_entity::dl_harq_process::reset() {
ack = false; 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) { if (is_initiated) {
srslte_softbuffer_rx_reset(&softbuffer); srslte_softbuffer_rx_reset(&softbuffer);
} }
} }
void dl_harq_entity::dl_harq_process::send_pending_ack_contention_resolution() bool dl_harq_entity::dl_harq_process::init(uint32_t pid_, dl_harq_entity *parent) {
{ if (srslte_softbuffer_rx_init(&softbuffer, 100)) {
if (pending_ul_buffer) { Error("Error initiating soft buffer\n");
pending_ul_buffer->generate_ack(pending_ack, &pending_ack_grant); 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; return false;
}
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;
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; bool is_new_tb = true;
if (srslte_tti_interval(new_grant->get_tti(), cur_grant.get_tti()) <= 8 && if (srslte_tti_interval(grant.tti, cur_grant.tti) <= 8 && grant.n_bytes == cur_grant.n_bytes) {
new_grant->get_tbs() == cur_grant.get_tbs())
{
is_new_tb = false; is_new_tb = false;
} }
if ((new_grant->get_ndi() != cur_grant.get_ndi() && !is_new_tb) || // NDI toggled for same TB if ((grant.ndi != cur_grant.ndi && !is_new_tb) || // NDI toggled for same TB
is_new_tb || // is new TB is_new_tb || // is new TB
(pid == HARQ_BCCH_PID && new_grant->get_rv() == 0)) // Broadcast PID and 1st TX (RV=0) (pid == HARQ_BCCH_PID && grant.rv == 0)) // Broadcast PID and 1st TX (RV=0)
{ {
is_new_transmission = true; is_new_transmission = true;
Debug("Set HARQ Info for new transmission\n"); Debug("Set HARQ Info for new transmission\n");
} else { } else {
if (!is_new_tb) { 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(), 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);
cur_grant.get_tti(), new_grant->get_tti());
} }
is_new_transmission = false; is_new_transmission = false;
Debug("Set HARQ Info for retransmission\n"); 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(), Info("DL PID %d: %s RV=%d, NDI=%d, LastNDI=%d\n", pid, is_new_transmission?"new TX":"reTX", grant.rv,
new_grant->get_ndi(), cur_grant.get_ndi(), new_grant->get_dciformat_string()); 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; ack = false;
srslte_softbuffer_rx_reset(&softbuffer); 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 { } 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_; void dl_harq_entity::dl_harq_process::tb_decoded_ok()
if (srslte_softbuffer_rx_init(&softbuffer, cell)) { {
Error("Error initiating soft buffer\n"); ack = true;
return false; 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 { } else {
is_initiated = true; if (harq_entity->pcap) {
harq_entity = parent; harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes, cur_grant.rnti, ack, cur_grant.tti);
log_h = harq_entity->log_h; }
payload = (uint8_t*) srslte_vec_malloc(sizeof(uint8_t) * max_payload_len); if (ack) {
return payload?true:false; 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 <pthread.h>
#include <unistd.h> #include <unistd.h>
#include "srsapps/common/threads.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/log.h" #include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac.h" #include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/pcap.h" #include "srsapps/ue/mac/pcap.h"
namespace srslte { namespace srslte {
namespace ue { 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; started = false;
ttisync = ttisync_; phy_h = phy;
phy_h = phy_h_; rlc_h = rlc;
log_h = log_h_; log_h = log_h_;
tti = 0; tti = 0;
is_synchronized = false; is_synchronized = false;
last_temporal_crnti = 0; last_temporal_crnti = 0;
phy_rnti = 0; phy_rnti = 0;
is_first_tx = true;
bsr_procedure.init(log_h, &timers_db, &params_db, &mac_io_lch); bsr_procedure.init( rlc_h, log_h, &params_db, &timers_db);
mux_unit.init(log_h, &mac_io_lch, &bsr_procedure); mux_unit.init ( rlc_h, log_h, &bsr_procedure);
demux_unit.init(phy_h, log_h, &mac_io_lch, &timers_db); demux_unit.init (phy_h, rlc_h, log_h, &timers_db);
ra_procedure.init(&params_db, phy_h, log_h, &timers_db, &mux_unit, &demux_unit); ra_procedure.init (phy_h, log_h, &params_db, &timers_db, &mux_unit, &demux_unit);
sr_procedure.init(log_h, &params_db, phy_h); sr_procedure.init (phy_h, log_h, &params_db);
is_first_of_burst = true; ul_harq.init ( log_h, &params_db, &timers_db, &mux_unit);
reset(); dl_harq.init ( log_h, &timers_db, &demux_unit);
for (int i=0;i<NOF_TTI_THREADS;i++) { reset();
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;
}
}
if (threads_new_rt_prio(&mac_thread, mac_thread_fnc, this, 1)) { start(MAC_THREAD_PRIO);
started = true;
}
return started; return started;
} }
@ -80,20 +74,7 @@ bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
void mac::stop() void mac::stop()
{ {
started = false; started = false;
pthread_join(mac_thread, NULL); wait_thread_finish();
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;
}
} }
void mac::start_pcap(mac_pcap* pcap_) void mac::start_pcap(mac_pcap* pcap_)
@ -104,60 +85,6 @@ void mac::start_pcap(mac_pcap* pcap_)
ra_procedure.start_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 // Implement Section 5.8
void mac::reconfiguration() void mac::reconfiguration()
{ {
@ -184,546 +111,187 @@ void mac::reset()
phr_procedure.reset(); phr_procedure.reset();
dl_harq.reset(); dl_harq.reset();
params_db.set_param(mac_params::RNTI_TEMP, 0); phy_h->pdcch_dl_search_reset();
} phy_h->pdcch_ul_search_reset();
void* mac::mac_thread_fnc(void *arg) { params_db.set_param(mac_interface_params::BCCH_SI_WINDOW_ST, -1);
srslte::ue::mac* mac = static_cast<srslte::ue::mac*>(arg); params_db.set_param(mac_interface_params::BCCH_SI_WINDOW_LEN, -1);
mac->main_radio_loop();
return NULL;
} }
void mac::main_radio_loop() { void mac::run_thread() {
setup_timers(); 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) { while(started) {
if (!is_synchronized) {
srslte_cell_t cell; /* Warning: Here order of invocation of procedures is important!! */
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; tti = ttisync.wait();
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());
Info("Receiver synchronized\n"); log_h->step(tti);
// Send MIB to RRC // Step all procedures
mac_io_lch.get(mac_io::MAC_LCH_BCCH_DL)->send(bch_payload, SRSLTE_BCH_PAYLOAD_LEN); bsr_procedure.step(tti);
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();
// Trigger execution of corresponding TTI processor thread // Check if BSR procedure need to start SR
//printf("triggering tti=%d\n", tti);
tti_threads_sync[tti%NOF_TTI_THREADS].increase(); if (bsr_procedure.need_to_send_sr()) {
//tti_threads[0].run_tti(tti); 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 { // Check SR if we need to start RA
phy *phy_ptr; if (sr_procedure.need_random_access()) {
log *log_h; Warning("Starting RA procedure by MAC order is DISABLED\n");
uint16_t crnti; //ra_procedure.start_mac_order();
}; }
void *pregen_phy_thread(void *arg) { ra_procedure.step(tti);
struct phy_crnti *a = (struct phy_crnti*) arg; //phr_procedure.step(tti);
a->log_h->info("Setting PHY RNTI=%d\n", a->crnti);
a->phy_ptr->set_crnti(a->crnti); timers_db.step_all();
a->phy_ptr->pregen_signals();
a->log_h->info("Done Setting PHY RNTI\n"); search_si_rnti();
free(a);
return NULL; demux_unit.process_pdus();
}
} }
void mac::pregen_phy(uint16_t phy_rnti) void mac::search_si_rnti()
{ {
pthread_t rnti_thread; // Reset PDCCH search
struct phy_crnti *arg = (struct phy_crnti*) malloc(sizeof(struct phy_crnti)); if (si_window_length >= 0 && si_window_start >= 0) {
arg->crnti = phy_rnti; if (tti >= si_window_start + si_window_length) {
arg->phy_ptr = phy_h; phy_h->pdcch_dl_search_reset();
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");
} }
// 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) { void mac::tti_clock(uint32_t tti)
demux_unit.add_sdu_handler(handler);
}
void mac::setup_timers()
{ {
if (params_db.get_param(mac_params::TIMER_TIMEALIGN) > 0) { ttisync.increase();
timers_db.get(TIME_ALIGNMENT)->set(this, params_db.get_param(mac_params::TIMER_TIMEALIGN));
}
}
static sched_grant::rnti_type_t rnti_type(int rnti_param_id) {
switch(rnti_param_id) {
case mac_params::RNTI_C:
return sched_grant::RNTI_TYPE_CRNTI;
case mac_params::RNTI_TEMP:
return sched_grant::RNTI_TYPE_TEMP;
case mac_params::RNTI_SPS:
return sched_grant::RNTI_TYPE_SPS;
case mac_params::RNTI_RA:
return sched_grant::RNTI_TYPE_RA;
}
}
uint32_t mac::get_harq_sps_pid(uint32_t tti) {
uint32_t nof_proc = ((uint32_t) params_db.get_param(mac_params::SPS_DL_NOF_PROC));
return tti/params_db.get_param(mac_params::SPS_DL_SCHED_INTERVAL)%nof_proc;
} }
void mac::timer_expired(uint32_t timer_id) void mac::bch_decoded_ok(uint8_t* payload, uint32_t len)
{ {
switch(timer_id) { // Send MIB to RRC
case TIME_ALIGNMENT: rlc_h->write_pdu_bcch_bch(payload, len);
timeAlignmentTimerExpire();
break;
default:
break;
}
}
/* Function called on expiry of TimeAlignmentTimer */
void mac::timeAlignmentTimerExpire() {
dl_harq.reset();
ul_harq.reset();
dl_sps_assig.clear();
ul_sps_assig.clear();
}
// Receive PCH when requested as defined in Section 5.5
void mac::receive_pch(uint32_t tti) {
if (params_db.get_param(mac_params::PCCH_RECEIVE)) {
dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti);
dl_sched_grant pch_grant(sched_grant::RNTI_TYPE_PRNTI, SRSLTE_PRNTI);
if (dl_buffer->get_dl_grant(&pch_grant)) {
qbuff *pcch_buff = mac_io_lch.get(mac_io::MAC_LCH_PCCH_DL);
uint8_t *ptr = (uint8_t*) pcch_buff->request();
if (ptr && pch_grant.get_tbs() <= mac_io_lch.DEFAULT_MSG_SZ) {
if (dl_buffer->decode_data(&pch_grant, ptr)) {
pcch_buff->release();
} else {
Warning("Error decoding PCH\n");
}
} else {
Error("Error getting pointer from PCCH buffer\n");
}
} else {
Debug("No P-RNTI grant found while looking for PCH messages\n");
}
}
}
/* This function controls DL Grant Assignment as specified in Section 5.3.1 in 36.321
* and issues commands to DL harq operation
*/
void mac::process_dl_grants(uint32_t tti) {
// Get DL buffer for this TTI
dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti);
// 5.3.1 DL Assignment reception if (pcap) {
for (int i = mac_params::RNTI_C;i<=mac_params::RNTI_RA;i++) { pcap->write_dl_bch(payload, len, true, phy_h->get_current_tti());
// 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);
}
}
}
}
}
} }
/* 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 */ void mac::harq_recv(uint32_t tti, bool ack, mac_interface_phy::tb_action_ul_t* action)
bool mac::process_ul_grants(uint32_t tti) { {
// Get DL buffer for this TTI to look for DCI grants ul_harq.harq_recv(tti, ack, action);
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::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action)
int mac::recv_sdu(uint32_t lcid, uint8_t* sdu_payload, uint32_t nbytes)
{ {
if (lcid <= mac_io::MAC_LCH_PCCH_DL) { if (grant.rnti_type == SRSLTE_RNTI_RAR) {
return mac_io_lch.get(lcid)->recv(sdu_payload, nbytes); ra_procedure.new_grant_dl(grant, action);
} else { } else {
Error("Receiving SDU: Invalid lcid=%d\n", lcid); dl_harq.new_grant_dl(grant, action);
return -1;
} }
} }
int mac::recv_bcch_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_BCCH_DL)->recv(sdu_payload, buffer_len_nbytes);
}
int mac::recv_ccch_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
{ {
return mac_io_lch.get(mac_io::MAC_LCH_CCCH_DL)->recv(sdu_payload, buffer_len_nbytes); 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);
} }
void mac::tb_decoded_ok(uint32_t harq_pid)
bool mac::send_sdu(uint32_t lcid, uint8_t* sdu_payload, uint32_t nbytes)
{ {
lcid += mac_io::MAC_LCH_CCCH_UL; if (ra_procedure.in_progress()) {
if (lcid <= mac_io::MAC_LCH_DTCH2_UL) { ra_procedure.tb_decoded_ok();
return mac_io_lch.get(lcid)->send(sdu_payload, nbytes);
} else { } else {
Error("Receiving SDU: Invalid lcid=%d\n", lcid); dl_harq.tb_decoded_ok(harq_pid);
return -1;
} }
} }
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); 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); 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) 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); mux_unit.set_priority(lcid, priority, PBR_x_tti, BSD);
bsr_procedure.setup_lcg(lcid, lcg); bsr_procedure.setup_lcg(lcid, lcg);
bsr_procedure.set_priority(lcid, priority); 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) uint16_t crnti, uint8_t direction, uint8_t rnti_type)
{ {
if (enable_write) { if (enable_write) {
if (pdu_len_bytes < max_pdu_len) { MAC_Context_Info_t context =
MAC_Context_Info_t context = {
{ FDD_RADIO, direction, rnti_type,
FDD_RADIO, direction, rnti_type, crnti, /* RNTI */
crnti, /* RNTI */ ue_id, /* UEId */
ue_id, /* UEId */ reTX, /* Retx */
reTX, /* Retx */ crc_ok, /* CRC Stsatus (i.e. OK) */
crc_ok, /* CRC Stsatus (i.e. OK) */ tti/10, /* Sysframe number */
tti/10, /* Sysframe number */ tti%10 /* Subframe number */
tti%10 /* Subframe number */ };
}; if (pdu) {
if (pdu) { MAC_LTE_PCAP_WritePDU(pcap_file, &context, pdu, pdu_len_bytes);
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);
} }
} }
} }

@ -32,18 +32,14 @@
namespace srslte { namespace srslte {
namespace ue { 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) mux::mux() : pdu_msg(20)
{ {
msg3_buff.init(mac::NOF_TTI_THREADS, MSG3_BUFF_SZ); msg3_buff.init(1, 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);
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
msg3_has_been_transmitted = false; 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[i] = i;
priority_sorted[i] = i; priority_sorted[i] = i;
PBR[i] = -1; // -1 is infinite 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_; log_h = log_h_;
mac_io_h = mac_io_h_; rlc = rlc_;
bsr_procedure = bsr_procedure_; bsr_procedure = bsr_procedure_;
} }
void mux::reset() 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; Bj[i] = 0;
} }
} }
@ -73,8 +69,8 @@ bool mux::is_pending_ccch_sdu()
bool mux::is_pending_any_sdu() bool mux::is_pending_any_sdu()
{ {
for (int i=0;i<mac_io::NOF_UL_LCH;i++) { for (int i=0;i<NOF_UL_LCH;i++) {
if (!mac_io_h->get(i)->isempty()) { if (rlc->get_buffer_state(i)) {
return true; return true;
} }
} }
@ -82,30 +78,27 @@ bool mux::is_pending_any_sdu()
} }
bool mux::is_pending_sdu(uint32_t lch_id) { bool mux::is_pending_sdu(uint32_t lch_id) {
lch_id += (uint32_t) mac_io::MAC_LCH_CCCH_UL; return rlc->get_buffer_state(lch_id)>0;
if (lch_id < mac_io::MAC_NOF_QUEUES) {
return !mac_io_h->get(lch_id)->isempty();
}
} }
void mux::set_priority(uint32_t lch_id, uint32_t set_priority, int set_PBR, uint32_t set_BSD) void mux::set_priority(uint32_t lch_id, uint32_t set_priority, int set_PBR, uint32_t set_BSD)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (lch_id < mac_io::NOF_UL_LCH) { if (lch_id < NOF_UL_LCH) {
priority[lch_id] = set_priority; priority[lch_id] = set_priority;
PBR[lch_id] = set_PBR; PBR[lch_id] = set_PBR;
BSD[lch_id] = set_BSD; BSD[lch_id] = set_BSD;
// Insert priority in sorted idx array // Insert priority in sorted idx array
int new_index = 0; 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++; new_index++;
} }
int old_index = 0; 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++; 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); Error("Can't find LchID=%d in sorted list\n", lch_id);
return; 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) { sch_subh::cetype bsr_format_convert(bsr_proc::bsr_format_t format) {
switch(format) { switch(format) {
case bsr_proc::LONG_BSR: 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: case bsr_proc::SHORT_BSR:
return sch_subh::SHORT_BSR; return sch_subh::SHORT_BSR;
case bsr_proc::TRUNC_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) { int pkt_num = 0;
Error("Assembling PDU: Buffer is not available\n");
return false; // Multiplexing and logical channel priorization as defined in Section 5.4.3
} bool mux::pdu_get(uint8_t *payload, uint32_t pdu_sz)
{
// Make sure pdu_sz is byte-aligned
pdu_sz_nbits = 8*(pdu_sz_nbits/8); pthread_mutex_lock(&mutex);
// Update Bj // 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 // Add PRB unless it's infinity
if (PBR[i] >= 0) { if (PBR[i] >= 0) {
Bj[i] += PBR[i]; Bj[i] += PBR[i];
@ -207,16 +147,14 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
} }
// Logical Channel Procedure // Logical Channel Procedure
uint32_t sdu_sz = 0; pdu_msg.init(pdu_sz, true);
pdu_msg.init(pdu_sz_nbits/8, true);
// MAC control element for C-RNTI or data from UL-CCCH // MAC control element for C-RNTI or data from UL-CCCH
bool is_first = true; 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 (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(); pdu_msg.next();
if (!pdu_msg.get()->set_c_rnti(pending_crnti_ce)) { if (!pdu_msg.get()->set_c_rnti(pending_crnti_ce)) {
Warning("Pending C-RNTI CE could not be inserted in MAC PDU\n"); 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; // data from any Logical Channel, except data from UL-CCCH;
// first only those with positive Bj // first only those with positive Bj
for (int i=0;i<mac_io::NOF_UL_LCH;i++) { uint32_t sdu_sz = 0;
bool res = true; for (int i=0;i<NOF_UL_LCH;i++) {
while ((Bj[i] > 0 || PBR[i] < 0) && res) { uint32_t lcid = lchid_sorted[i];
res = allocate_sdu(lchid_sorted[i], &pdu_msg, &sdu_sz, &is_first); if (lcid != 0) {
if (res && PBR[i] >= 0) { bool res = true;
Bj[i] -= sdu_sz; 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 // 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)); 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); bool send_bsr = bsr_procedure->generate_bsr_on_ul_grant(pdu_msg.rem_size(), &bsr);
// Insert Padding BSR if not inserted Regular/Periodic BSR // Insert Padding BSR if not inserted Regular/Periodic BSR
if (!bsr_payload_sz && send_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); 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); Debug("Assembled MAC PDU msg size %d/%d bytes\n", pdu_msg.size(), pdu_sz);
//pdu_msg.fprint(stdout);
pthread_mutex_unlock(&mutex);
/* Generate MAC PDU and save to buffer */ /* Generate MAC PDU and save to buffer */
if (pdu_msg.write_packet(buff)) { if (!pdu_msg.write_packet(payload, rlc)) {
pdu_buff.push(pdu_sz_nbits);
} else {
Error("Writing PDU message to packet\n"); Error("Writing PDU message to packet\n");
return false; return false;
} } else {
return true; 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) 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) 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 // Get n-th pending SDU pointer and length
uint32_t buff_len = 0; uint32_t sdu_len = rlc->get_buffer_state(lcid);
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;
if (buff_ptr && buff_len > 0) { // there is pending SDU to allocate if (sdu_len > 0) { // there is pending SDU to allocate
if (sdu_sz) { if (sdu_len > max_sdu_sz && max_sdu_sz >= 0) {
*sdu_sz = buff_len; 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 if (pdu_msg->new_subh()) { // there is space for a new subheader
pdu_msg->next(); 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) { if (is_first) {
*is_first = false; *is_first = false;
} }
Info("Allocated SDU lcid=%d nbytes=%d\n", lcid, nbytes); if (sdu_sz) {
// Increase number of pop'ed packets from queue *sdu_sz = sdu_len;
nof_tx_pkts[lcid]++; }
Info("Allocated SDU lcid=%d nbytes=%d\n", lcid, sdu_len);
return true; return true;
} else { } else {
if (pdu_msg->rem_size() > 10) { Error("Could not add SDU rem_size=%d, sdu_len=%d\n", pdu_msg->rem_size(), sdu_len);
Info("Could not allocate SDU in current grant. SDU length: %d bytes. Grant space: %d bytes\n", nbytes,
pdu_msg->rem_size());
}
pdu_msg->del_subh(); 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; return false;
} }
void mux::msg3_flush() void mux::msg3_flush()
{ {
msg3_buff.flush(); msg3_buff.flush();
@ -361,23 +296,37 @@ bool mux::msg3_is_transmitted()
return msg3_has_been_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.request();
uint8_t *msg3 = (uint8_t*) msg3_buff.pop(&len);
if (msg3) { if (msg3) {
if (len < TB_size) { if (pdu_get(msg3, pdu_sz)) {
// Pad with zeros without exceeding maximum buffer size msg3_buff.push(pdu_sz);
if (TB_size <= MSG3_BUFF_SZ) { return true;
bzero(&msg3[len], (TB_size-len)*sizeof(uint8_t)); } else {
} else { Error("Assembling PDU\n");
Error("Requested TB size from Msg3 buffer exceeds buffer size (%d>%d)\n", TB_size, MSG3_BUFF_SZ); }
return NULL; } 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 // 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; uint8_t *init_ptr = ptr;
bool last_is_padding = false; bool last_is_padding = false;
@ -159,16 +159,16 @@ bool sch_pdu::write_packet(uint8_t* ptr)
// Write payloads in the same order // Write payloads in the same order
for (int i=0;i<nof_subheaders;i++) { for (int i=0;i<nof_subheaders;i++) {
if (!subheaders[i].is_sdu()) { if (!subheaders[i].is_sdu()) {
subheaders[i].write_payload(&ptr); subheaders[i].write_payload(&ptr, rlc);
} }
} }
for (int i=0;i<nof_subheaders;i++) { for (int i=0;i<nof_subheaders;i++) {
if (subheaders[i].is_sdu()) { if (subheaders[i].is_sdu()) {
subheaders[i].write_payload(&ptr); subheaders[i].write_payload(&ptr, rlc);
} }
} }
// Set paddint to zeros (if any) // Set paddint to zeros (if any)
bzero(ptr, rem_len*sizeof(uint8_t)*8); bzero(ptr, rem_len*sizeof(uint8_t));
return true; return true;
} }
@ -235,8 +235,8 @@ void sch_subh::init()
{ {
lcid = 0; lcid = 0;
nof_bytes = 0; nof_bytes = 0;
sdu_payload_ptr = NULL; payload = NULL;
bzero(ce_payload, sizeof(uint8_t) * MAX_CE_PAYLOAD_LEN); bzero(payload, sizeof(uint8_t) * MAX_CE_PAYLOAD_LEN);
} }
sch_subh::cetype sch_subh::ce_type() sch_subh::cetype sch_subh::ce_type()
@ -296,29 +296,36 @@ bool sch_subh::is_sdu()
} }
uint16_t sch_subh::get_c_rnti() uint16_t sch_subh::get_c_rnti()
{ {
uint8_t *ptr = ce_payload; if (payload) {
uint16_t ret = (uint16_t) srslte_bit_unpack(&ptr, 16); return (uint16_t) payload[0] | payload[1]<<8;
return ret; } else {
return 0;
}
} }
uint64_t sch_subh::get_con_res_id() uint64_t sch_subh::get_con_res_id()
{ {
uint8_t *ptr = ce_payload; if (payload) {
uint64_t ret = (uint64_t) srslte_bit_unpack_l(&ptr, 48); return ((uint64_t) payload[0]) | ((uint64_t) payload[1])<<8 | ((uint64_t) payload[2])<<16 | ((uint64_t) payload[3])<<24 |
return ret; ((uint64_t) payload[4])<<32 | ((uint64_t) payload[5])<<48;
} else {
return 0;
}
} }
uint8_t sch_subh::get_phd() uint8_t sch_subh::get_phd()
{ {
uint8_t *ptr = ce_payload; if (payload) {
ptr += 2; return (uint8_t) payload[0]&0x3f;
uint8_t ret = (uint8_t) srslte_bit_unpack(&ptr, 6); } else {
return ret; return 0;
}
} }
uint8_t sch_subh::get_ta_cmd() uint8_t sch_subh::get_ta_cmd()
{ {
uint8_t *ptr = ce_payload; if (payload) {
ptr += 2; return (uint8_t) payload[0]&0x3f;
uint8_t ret = (uint8_t) srslte_bit_unpack(&ptr, 6); } else {
return ret; return 0;
}
} }
uint32_t sch_subh::get_sdu_lcid() 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() uint8_t* sch_subh::get_sdu_ptr()
{ {
return sdu_payload_ptr; return payload;
} }
void sch_subh::set_padding(uint32_t padding_len) 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; uint32_t ce_size = format==LONG_BSR?3:1;
if (((sch_pdu*)parent)->has_space_ce(ce_size) || !update_size) { if (((sch_pdu*)parent)->has_space_ce(ce_size) || !update_size) {
uint8_t *ptr = ce_payload;
if (format==LONG_BSR) { if (format==LONG_BSR) {
bzero(ce_payload, 3*8*sizeof(uint8_t)); w_payload_ce[0] = (buff_size_table(buff_size[0])&0x3f) << 2 | (buff_size_table(buff_size[1])&0xc0)>>6;
for (int i=0;i<4;i++) { w_payload_ce[1] = (buff_size_table(buff_size[1])&0xf) << 4 | (buff_size_table(buff_size[2])&0xf0)>>4;
srslte_bit_pack(buff_size_table(buff_size[i]), &ptr, 6); w_payload_ce[2] = (buff_size_table(buff_size[2])&0x3) << 6 | (buff_size_table(buff_size[3])&0x3f);
}
} else { } else {
bzero(ce_payload, 8*sizeof(uint8_t)); w_payload_ce[0] = (nonzero_lcg&0x3)<<6 | buff_size_table(buff_size[nonzero_lcg])&0x3f;
srslte_bit_pack(nonzero_lcg, &ptr, 2);
srslte_bit_pack(buff_size_table(buff_size[nonzero_lcg]), &ptr, 6);
} }
lcid = format; lcid = format;
if (update_size) { 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) bool sch_subh::set_c_rnti(uint16_t crnti)
{ {
if (((sch_pdu*)parent)->has_space_ce(2)) { if (((sch_pdu*)parent)->has_space_ce(2)) {
w_payload_ce[0] = (uint8_t) (crnti&0xff00)>>8;
*((uint16_t*) ce_payload) = crnti; w_payload_ce[1] = (uint8_t) (crnti&0x00ff);
lcid = C_RNTI; lcid = C_RNTI;
uint8_t *ptr = ce_payload;
srslte_bit_pack(crnti, &ptr, 16);
((sch_pdu*)parent)->update_space_ce(2); ((sch_pdu*)parent)->update_space_ce(2);
return true; return true;
} else { } 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) bool sch_subh::set_con_res_id(uint64_t con_res_id)
{ {
if (((sch_pdu*)parent)->has_space_ce(6)) { if (((sch_pdu*)parent)->has_space_ce(6)) {
uint8_t *ptr = ce_payload; w_payload_ce[0] = (uint8_t) ((con_res_id&0xff0000000000)>>48);
srslte_bit_pack_l(con_res_id, &ptr, 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; lcid = CON_RES_ID;
((sch_pdu*)parent)->update_space_ce(6); ((sch_pdu*)parent)->update_space_ce(6);
return true; 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) bool sch_subh::set_phd(uint8_t phd)
{ {
if (((sch_pdu*)parent)->has_space_ce(1)) { if (((sch_pdu*)parent)->has_space_ce(1)) {
uint8_t *ptr = ce_payload; w_payload_ce[0] = phd&0x3f;
srslte_bit_pack(0, &ptr, 2);
srslte_bit_pack(phd, &ptr, 6);
lcid = PHD_REPORT; lcid = PHD_REPORT;
((sch_pdu*)parent)->update_space_ce(1); ((sch_pdu*)parent)->update_space_ce(1);
return true; 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)) { if (((sch_pdu*)parent)->has_space_sdu(nof_bytes_, is_first)) {
sdu_payload_ptr = ptr;
nof_bytes = nof_bytes_; nof_bytes = nof_bytes_;
lcid = lcid_; lcid = lcid_;
((sch_pdu*)parent)->update_space_sdu(nof_bytes_, is_first); ((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; 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 // Section 6.2.1
void sch_subh::write_subheader(uint8_t** ptr, bool is_last) void sch_subh::write_subheader(uint8_t** ptr, bool is_last)
{ {
if (is_sdu()) { if (is_sdu()) {
// MAC SDU: R/R/E/LCID/F/L subheader // MAC SDU: R/R/E/LCID/F/L subheader
srslte_bit_pack(0, ptr, 2); // R, R *(*ptr + 0) = (uint8_t) is_last<<5 | (lcid & 0x1f);
srslte_bit_pack(is_last?0:1, ptr, 1); // E
srslte_bit_pack(lcid, ptr, 5); // LCID
// 2nd and 3rd octet // 2nd and 3rd octet
if (!is_last) { if (!is_last) {
srslte_bit_pack(F_bit?1:0, ptr, 1); // F if (nof_bytes >= 128) {
srslte_bit_pack(nof_bytes, ptr, nof_bytes<128?7:15); // L *(*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 { } else {
// MAC CE: R/R/E/LCID MAC Subheader // MAC CE: R/R/E/LCID MAC Subheader
srslte_bit_pack(0, ptr, 2); // R, R *(*ptr + 0) = (uint8_t) is_last<<5 | (lcid & 0x1f);
srslte_bit_pack(is_last?0:1, ptr, 1); // E
srslte_bit_pack(lcid, ptr, 5); // LCID
} }
} }
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()) { if (is_sdu()) {
src = sdu_payload_ptr; // Read data from RLC interface
rlc->read_pdu(lcid, *ptr, nof_bytes);
} else { } else {
nof_bytes = sizeof_ce(lcid, parent->is_ul()); 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;
*ptr += nof_bytes*8;
} }
bool sch_subh::read_subheader(uint8_t** ptr) bool sch_subh::read_subheader(uint8_t** ptr)
{ {
// Skip R // Skip R
*ptr += 2; bool e_bit = (bool) *(*ptr + 0) & 0x20;
bool e_bit = srslte_bit_unpack(ptr, 1)?true:false; lcid = (uint8_t) *(*ptr + 0) & 0x1f;
lcid = srslte_bit_unpack(ptr, 5);
if (is_sdu()) { if (is_sdu()) {
if (e_bit) { if (e_bit) {
F_bit = srslte_bit_unpack(ptr, 1)?true:false; F_bit = (bool) *(*ptr + 1) & 0x80;
nof_bytes = srslte_bit_unpack(ptr, F_bit?15:7); nof_bytes = (uint32_t)*(*ptr + 1) & 0x7f;
if (F_bit) {
nof_bytes = nof_bytes<<8 | (uint32_t) *(*ptr + 2) & 0xff;
}
} else { } else {
nof_bytes = 0; nof_bytes = 0;
F_bit = 0; F_bit = 0;
@ -498,16 +502,34 @@ bool sch_subh::read_subheader(uint8_t** ptr)
} }
void sch_subh::read_payload(uint8_t** ptr) void sch_subh::read_payload(uint8_t** ptr)
{ {
if (is_sdu()) { payload = *ptr;
sdu_payload_ptr = *ptr; *ptr += nof_bytes;
} else {
memcpy(ce_payload, *ptr, 8*nof_bytes*sizeof(uint8_t));
}
*ptr += nof_bytes*8;
} }
// 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 // 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 // Write Backoff Indicator, if any
if (has_backoff_indicator) { if (has_backoff_indicator) {
if (nof_subheaders > 0) { if (nof_subheaders > 0) {
srslte_bit_pack(1, &ptr, 1); // E *(ptr) = 1<<7 | backoff_indicator&0xf;
srslte_bit_pack(0, &ptr, 1); // T
srslte_bit_pack(0, &ptr, 2); // R, R
srslte_bit_pack(backoff_indicator, &ptr, 4);
} }
} }
// Write RAR subheaders // Write RAR subheaders
@ -569,10 +588,10 @@ bool rar_pdu::write_packet(uint8_t* ptr)
} }
// Write payload // Write payload
for (int i=0;i<nof_subheaders;i++) { 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) // Set paddint to zeros (if any)
bzero(ptr, rem_len*sizeof(uint8_t)*8); bzero(ptr, rem_len*sizeof(uint8_t));
return true; return true;
} }
@ -620,63 +639,45 @@ void rar_subh::set_temp_crnti(uint16_t temp_rnti_)
// Section 6.2.2 // Section 6.2.2
void rar_subh::write_subheader(uint8_t** ptr, bool is_last) void rar_subh::write_subheader(uint8_t** ptr, bool is_last)
{ {
srslte_bit_pack(is_last?0:1, ptr, 1); // E *(*ptr + 0) = (uint8_t) (is_last<<7 | 1<<6 | preamble & 0x3f);
srslte_bit_pack(1, ptr, 1); // T
srslte_bit_pack(preamble, ptr, 6); // RAPID
} }
// Section 6.2.3 // 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 *(*ptr + 0) = (uint8_t) (ta&0x7f0)>>4;
srslte_bit_pack(ta, ptr, 11); // Timing Adv Cmd *(*ptr + 1) = (uint8_t) (ta&0xf) <<4 | grant[0]<<3 | grant[1] << 2 | grant[2] << 1 | grant[3];
memcpy(*ptr, grant, 20*sizeof(uint8_t)); // UL grant uint8_t *x = &grant[4];
*ptr += 20; *(*ptr + 2) = (uint8_t) srslte_bit_unpack(&x, 8);
srslte_bit_pack(temp_rnti, ptr, 16); // Temp C-RNTI *(*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) void rar_subh::read_payload(uint8_t** ptr)
{ {
*ptr += 1; // R ta = *(*ptr + 0)&0x7f << 4 | (*(*ptr + 1)&0xf0)>>4;
ta = srslte_bit_unpack(ptr, 11); // Timing Adv Cmd grant[0] = *(*ptr + 1)&0x8;
memcpy(grant, *ptr, 20*sizeof(uint8_t)); // UL Grant grant[1] = *(*ptr + 1)&0x4;
*ptr += 20; grant[2] = *(*ptr + 1)&0x2;
temp_rnti = srslte_bit_unpack(ptr, 16); // Temp C-RNTI 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 rar_subh::read_subheader(uint8_t** ptr)
{ {
bool e_bit = srslte_bit_unpack(ptr, 1); // E bool e_bit = *(*ptr + 0) & 0x80;
bool type = srslte_bit_unpack(ptr, 1); // T bool type = *(*ptr + 0) & 0x40;
if (type) { if (type) {
preamble = srslte_bit_unpack(ptr, 6); // RAPID preamble = *(*ptr + 0) & 0x3f;
} else { } else {
// Read Backoff ((rar_pdu*)parent)->set_backoff(*(*ptr + 0) & 0xf);
*ptr += 2; // R, R
((rar_pdu*)parent)->set_backoff((uint8_t) srslte_bit_unpack(ptr, 4));
} }
return e_bit; 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/proc_bsr.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mac.h" #include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/mux.h" #include "srsapps/ue/mac/mux.h"
@ -48,11 +47,11 @@ bsr_proc::bsr_proc()
triggered_bsr_type=NONE; 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_; log_h = log_h_;
rlc = rlc_;
params_db = params_db_; params_db = params_db_;
mac_io_h = mac_io_h_;
timers_db = timers_db_; timers_db = timers_db_;
initiated = true; initiated = true;
} }
@ -85,12 +84,12 @@ void bsr_proc::timer_expired(uint32_t timer_id) {
bool bsr_proc::check_highest_channel() { bool bsr_proc::check_highest_channel() {
int pending_data_lcid = -1; 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 (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; pending_data_lcid = i;
for (int j=0;j<mac_io::NOF_UL_LCH;j++) { for (int j=0;j<MAX_LCID;j++) {
if (!mac_io_h->get(j+mac_io::MAC_LCH_CCCH_UL)->isempty()) { if (rlc->get_buffer_state(j) > 0) {
if (priorities[j] > priorities[i]) { if (priorities[j] > priorities[i]) {
pending_data_lcid = -1; pending_data_lcid = -1;
} }
@ -101,7 +100,7 @@ bool bsr_proc::check_highest_channel() {
} }
if (pending_data_lcid >= 0) { if (pending_data_lcid >= 0) {
// If there is new data available for this logical channel // 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 (nbytes > last_pending_data[pending_data_lcid])
{ {
if (triggered_bsr_type != REGULAR) { if (triggered_bsr_type != REGULAR) {
@ -119,16 +118,16 @@ bool bsr_proc::check_single_channel() {
uint32_t pending_data_lcid = 0; uint32_t pending_data_lcid = 0;
uint32_t nof_nonzero_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 (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; pending_data_lcid = i;
nof_nonzero_lcid++; nof_nonzero_lcid++;
} }
} }
} }
if (nof_nonzero_lcid == 1) { 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 there is new data available for this logical channel
if (nbytes > last_pending_data[pending_data_lcid]) { if (nbytes > last_pending_data[pending_data_lcid]) {
triggered_bsr_type = REGULAR; triggered_bsr_type = REGULAR;
@ -140,8 +139,8 @@ bool bsr_proc::check_single_channel() {
} }
void bsr_proc::update_pending_data() { void bsr_proc::update_pending_data() {
for (int i=0;i<mac_io_h->NOF_UL_LCH;i++) { for (int i=0;i<MAX_LCID;i++) {
last_pending_data[i] = mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8; 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; bool ret = false;
uint32_t nof_lcg=0; uint32_t nof_lcg=0;
bzero(bsr, sizeof(bsr_t)); 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) { 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; bsr->buff_size[lcg[i]] += n;
if (n > 0) { if (n > 0) {
nof_lcg++; nof_lcg++;
@ -196,16 +195,16 @@ void bsr_proc::step(uint32_t tti)
} }
if (!timer_periodic) { 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; 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 (!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; 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) { if ((tti - last_print)%10240 > 40) {
char str[128]; char str[128];
bzero(str, 128); bzero(str, 128);
for (int i=0;i<mac_io::NOF_UL_LCH;i++) { for (int i=0;i<MAX_LCID;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]); sprintf(str, "%s%d (%d), ", str, rlc->get_buffer_state(i), last_pending_data[i]);
} }
Info("QUEUE status: %s\n", str); Info("QUEUE status: %s\n", str);
last_print = tti; 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; uint32_t bsr_sz = 0;
if (triggered_bsr_type == PERIODIC || triggered_bsr_type == REGULAR) { 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 */ /* 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 total_data = 0;
uint32_t idx = 0; for (int i=0;i<MAX_LCID && total_data < grant_size;i++) {
uint32_t sdu_len = 0; total_data += sch_pdu::size_plus_header_sdu(rlc->get_buffer_state(i));
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);
}
} }
total_data--; // Because last SDU has no size header total_data--; // Because last SDU has no size header

@ -30,8 +30,6 @@
#include <stdint.h> #include <stdint.h>
#include <signal.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/proc_ra.h"
#include "srsapps/ue/mac/mac.h" #include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/mux.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. // Table 7.6-1: DELTA_PREAMBLE values.
int delta_preamble_db_table[5] = {0, 0, -3, -3, 8}; int delta_preamble_db_table[5] = {0, 0, -3, -3, 8};
bool ra_proc::init(phy_interface* phy_h_, log* log_h_, mac_params* params_db_, timers* timers_db_,
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_,
mux* mux_unit_, demux* demux_unit_) mux* mux_unit_, demux* demux_unit_)
{ {
phy_h = phy_h_; 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_; timers_db = timers_db_;
mux_unit = mux_unit_; mux_unit = mux_unit_;
demux_unit= demux_unit_; demux_unit= demux_unit_;
start_prach_init = false; srslte_softbuffer_rx_init(&softbuffer_rar, 10);
if (pthread_create(&pt_init_prach, NULL, init_prach_thread, this)) {
perror("pthread_create");
}
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
reset(); reset();
} }
@ -96,32 +71,32 @@ void ra_proc::start_pcap(mac_pcap* pcap_)
void ra_proc::read_params() { void ra_proc::read_params() {
// Read initialization parameters // Read initialization parameters
configIndex = params_db->get_param(mac_params::RA_CONFIGINDEX); configIndex = params_db->get_param(mac_interface_params::RA_CONFIGINDEX);
preambleIndex = params_db->get_param(mac_params::RA_PREAMBLEINDEX); preambleIndex = params_db->get_param(mac_interface_params::RA_PREAMBLEINDEX);
maskIndex = params_db->get_param(mac_params::RA_MASKINDEX); maskIndex = params_db->get_param(mac_interface_params::RA_MASKINDEX);
nof_preambles = params_db->get_param(mac_params::RA_NOFPREAMBLES); nof_preambles = params_db->get_param(mac_interface_params::RA_NOFPREAMBLES);
if (!nof_preambles || nof_preambles > 64) { if (!nof_preambles || nof_preambles > 64) {
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) { if (!nof_groupA_preambles) {
nof_groupA_preambles = nof_preambles; nof_groupA_preambles = nof_preambles;
} }
if (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; nof_groupB_preambles = nof_preambles - nof_groupA_preambles;
if (nof_groupB_preambles) { if (nof_groupB_preambles) {
messagePowerOffsetGroupB = params_db->get_param(mac_params::RA_MESSAGEPOWEROFFSETB); messagePowerOffsetGroupB= params_db->get_param(mac_interface_params::RA_MESSAGEPOWEROFFSETB);
messageSizeGroupA = params_db->get_param(mac_params::RA_MESSAGESIZEA); messageSizeGroupA = params_db->get_param(mac_interface_params::RA_MESSAGESIZEA);
Pcmax = params_db->get_param(mac_params::RA_PCMAX); Pcmax = params_db->get_param(mac_interface_params::RA_PCMAX);
deltaPreambleMsg3 = params_db->get_param(mac_params::RA_DELTAPREAMBLEMSG3); deltaPreambleMsg3 = params_db->get_param(mac_interface_params::RA_DELTAPREAMBLEMSG3);
} }
responseWindowSize = params_db->get_param(mac_params::RA_RESPONSEWINDOW); responseWindowSize = params_db->get_param(mac_interface_params::RA_RESPONSEWINDOW);
powerRampingStep = params_db->get_param(mac_params::RA_POWERRAMPINGSTEP); powerRampingStep = params_db->get_param(mac_interface_params::RA_POWERRAMPINGSTEP);
preambleTransMax = params_db->get_param(mac_params::RA_PREAMBLETRANSMAX); preambleTransMax = params_db->get_param(mac_interface_params::RA_PREAMBLETRANSMAX);
iniReceivedTargetPower = params_db->get_param(mac_params::RA_INITRECEIVEDPOWER); iniReceivedTargetPower = params_db->get_param(mac_interface_params::RA_INITRECEIVEDPOWER);
contentionResolutionTimer = params_db->get_param(mac_params::RA_CONTENTIONTIMER); contentionResolutionTimer = params_db->get_param(mac_interface_params::RA_CONTENTIONTIMER);
delta_preamble_db = delta_preamble_db_table[configIndex%5]; delta_preamble_db = delta_preamble_db_table[configIndex%5];
@ -154,9 +129,9 @@ bool ra_proc::is_error() {
const char* state_str[11] = {"Idle", const char* state_str[11] = {"Idle",
"RA Initializat.: ", "RA Initializat.: ",
"RA Initial.Wait: ",
"RA ResSelection: ", "RA ResSelection: ",
"RA PreambleTx : ", "RA PreambleTx : ",
"RA PDCCH setup : ",
"RA PreambleRx : ", "RA PreambleRx : ",
"RA ResponseErr : ", "RA ResponseErr : ",
"RA BackoffWait : ", "RA BackoffWait : ",
@ -199,28 +174,9 @@ void ra_proc::step_initialization() {
mux_unit->msg3_flush(); mux_unit->msg3_flush();
backoff_param_ms = 0; backoff_param_ms = 0;
// Instruct phy prach init thread to start initialization // Instruct phy to configure PRACH
pthread_mutex_lock(&mutex); phy_h->configure_prach_params();
start_prach_init = true; state = RESOURCE_SELECTION;
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;
}
}
} }
void ra_proc::step_resource_selection() { void ra_proc::step_resource_selection() {
@ -249,7 +205,8 @@ void ra_proc::step_resource_selection() {
sel_maskIndex = 0; 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; state = PREAMBLE_TRANSMISSION;
} }
@ -258,118 +215,113 @@ void ra_proc::step_preamble_transmission() {
delta_preamble_db + delta_preamble_db +
(preambleTransmissionCounter-1)*powerRampingStep; (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); 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() { void ra_proc::step_pdcch_setup() {
int ra_tti = phy_h->get_prach_transmitted_tti(); int ra_tti = phy_h->prach_tx_tti();
if (ra_tti > 0) { if (ra_tti > 0) {
ra_rnti = 1+ra_tti%10;
ra_rnti = 1+ra_tti%10; // f_id=0 for FDD phy_h->pdcch_dl_search(SRSLTE_RNTI_RAR, ra_rnti, ra_tti+3, responseWindowSize);
dl_sched_grant rar_grant(ra_rnti); state = RESPONSE_RECEPTION;
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);
}
if (ack) { void ra_proc::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action)
rDebug("RAR decoded successfully TBS=%d\n", rar_grant.get_tbs()); {
if (grant.n_bytes < MAX_RAR_PDU_LEN) {
rar_pdu_msg.init(rar_grant.get_tbs()/8); rInfo("DL grant found RA-RNTI=%d\n", ra_rnti);
rar_pdu_msg.parse_packet(rar_pdu_buffer); 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 // Save transmitted C-RNTI (if any)
if (rar_pdu_msg.has_backoff()) { transmitted_crnti = params_db->get_param(mac_interface_params::RNTI_C);
backoff_param_ms = backoff_table[rar_pdu_msg.get_backoff()%16];
} else {
backoff_param_ms = 0;
}
while(rar_pdu_msg.next()) { // Save transmitted UE contention id, as defined by higher layers
if (rar_pdu_msg.get()->get_rapid() == sel_preamble) { transmitted_contention_id = params_db->get_param(mac_interface_params::CONTENTION_ID);
rInfo("Received RAPID=%d\n", sel_preamble); params_db->set_param(mac_interface_params::CONTENTION_ID, 0);
process_timeadv_cmd(rar_pdu_msg.get()->get_ta_cmd()); // If we have a C-RNTI, tell Mux unit to append C-RNTI CE if no CCCH SDU transmission
if (transmitted_crnti) {
// FIXME: Indicate received target power mux_unit->append_crnti_ce_next_tx(transmitted_crnti);
//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) rDebug("Going to Contention Resolution state\n");
uint8_t grant[rar_subh::RAR_GRANT_LEN]; state = CONTENTION_RESOLUTION;
rar_pdu_msg.get()->get_sched_grant(grant);
phy_h->get_dl_buffer(tti+2)->set_rar_grant(grant); // Start contention resolution timer
timers_db->get(mac::CONTENTION_TIMER)->reset();
if (preambleIndex > 0) { timers_db->get(mac::CONTENTION_TIMER)->run();
// Preamble selected by Network }
state = COMPLETION; } else {
} else { rDebug("Found RAR for preamble %d\n", rar_pdu_msg.get()->get_rapid());
// 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;
} }
} }
} }
void ra_proc::step_response_reception() {
// do nothing. Processing done in tb_decoded_ok()
}
void ra_proc::step_response_error() { void ra_proc::step_response_error() {
preambleTransmissionCounter++; preambleTransmissionCounter++;
@ -377,7 +329,7 @@ void ra_proc::step_response_error() {
rError("Maximum number of transmissions reached (%d)\n", preambleTransMax); rError("Maximum number of transmissions reached (%d)\n", preambleTransMax);
state = RA_PROBLEM; state = RA_PROBLEM;
} else { } else {
backoff_interval_start = tti; backoff_interval_start = phy_h->get_current_tti();
if (backoff_param_ms) { if (backoff_param_ms) {
backoff_inteval = rand()%backoff_param_ms; backoff_inteval = rand()%backoff_param_ms;
} else { } else {
@ -394,7 +346,7 @@ void ra_proc::step_response_error() {
} }
void ra_proc::step_backoff_wait() { 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; state = RESOURCE_SELECTION;
} }
} }
@ -411,7 +363,7 @@ void ra_proc::step_contention_resolution() {
start_mode == PDCCH_ORDER) start_mode == PDCCH_ORDER)
{ {
timers_db->get(mac::CONTENTION_TIMER)->stop(); 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; state = COMPLETION;
} }
pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED; 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) { if (transmitted_contention_id == rx_contention_id) {
rDebug("MAC PDU Contention Resolution ID matches the one transmitted in CCCH SDU\n"); 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 // 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 // finish the disassembly and demultiplexing of the MAC PDU
demux_unit->demultiplex_pending_pdu(); demux_unit->demultiplex_pending_pdu();
state = COMPLETION; state = COMPLETION;
@ -441,7 +393,7 @@ void ra_proc::step_contention_resolution() {
// FIXME: Need to flush Msg3 HARQ buffer. Why? // FIXME: Need to flush Msg3 HARQ buffer. Why?
state = RESPONSE_ERROR; state = RESPONSE_ERROR;
} }
params_db->set_param(mac_params::RNTI_TEMP, 0); params_db->set_param(mac_interface_params::RNTI_TEMP, 0);
} }
} }
} else { } else {
@ -451,15 +403,14 @@ void ra_proc::step_contention_resolution() {
} }
void ra_proc::step_completition() { void ra_proc::step_completition() {
params_db->set_param(mac_params::RA_PREAMBLEINDEX, 0); params_db->set_param(mac_interface_params::RA_PREAMBLEINDEX, 0);
params_db->set_param(mac_params::RA_MASKINDEX, 0); params_db->set_param(mac_interface_params::RA_MASKINDEX, 0);
mux_unit->msg3_flush(); mux_unit->msg3_flush();
msg3_transmitted = false; msg3_transmitted = false;
} }
void ra_proc::step(uint32_t tti_) void ra_proc::step(uint32_t tti_)
{ {
tti = tti_;
if (is_running()) { if (is_running()) {
switch(state) { switch(state) {
case IDLE: case IDLE:
@ -467,15 +418,15 @@ void ra_proc::step(uint32_t tti_)
case INITIALIZATION: case INITIALIZATION:
step_initialization(); step_initialization();
break; break;
case INITIALIZATION_WAIT:
step_initialization_wait();
break;
case RESOURCE_SELECTION: case RESOURCE_SELECTION:
step_resource_selection(); step_resource_selection();
break; break;
case PREAMBLE_TRANSMISSION: case PREAMBLE_TRANSMISSION:
step_preamble_transmission(); step_preamble_transmission();
break; break;
case PDCCH_SETUP:
step_pdcch_setup();
break;
case RESPONSE_RECEPTION: case RESPONSE_RECEPTION:
step_response_reception(); step_response_reception();
break; break;
@ -529,7 +480,7 @@ void ra_proc::start_rlc_order()
void ra_proc::timer_expired(uint32_t timer_id) void ra_proc::timer_expired(uint32_t timer_id)
{ {
rInfo("Contention Resolution Timer expired. Going to Response Error\n"); 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; state = RESPONSE_ERROR;
} }

@ -36,7 +36,7 @@ sr_proc::sr_proc() {
initiated = false; 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_; log_h = log_h_;
params_db = params_db_; 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() void sr_proc::reset()
{ {
is_pending_sr = false; is_pending_sr = false;
phy_h->send_sr(false);
} }
void sr_proc::step(uint32_t tti) void sr_proc::step(uint32_t tti)
{ {
if (initiated) { if (initiated) {
if (is_pending_sr) { 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) { if (sr_counter < dsr_transmax) {
int last_tx_tti = phy_h->sr_last_tx_tti(); int last_tx_tti = phy_h->sr_last_tx_tti();
if (last_tx_tti >= 0 && last_tx_tti + 4 < tti) { if (last_tx_tti >= 0 && last_tx_tti + 4 < tti) {
sr_counter++; sr_counter++;
Info("SR signalling PHY. sr_counter=%d, PHY TTI=%d\n", sr_counter, phy_h->get_current_tti()); 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 { } else {
do_ra = true; do_ra = true;
@ -93,7 +92,7 @@ void sr_proc::start()
sr_counter = 0; sr_counter = 0;
is_pending_sr = true; 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); 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/common/log.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mac.h" #include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/ul_harq.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_; log_h = log_h_;
mux_unit = mux_unit_; mux_unit = mux_unit_;
params_db = params_db_; params_db = params_db_;
timers_db = timers_db_; timers_db = timers_db_;
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) { for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
if (!proc[i].init(cell, this)) { if (!proc[i].init(i, this)) {
return false; return false;
} }
proc[i].pid = i;
} }
return true; return true;
} }
@ -67,50 +63,83 @@ void ul_harq_entity::reset() {
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) { for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
proc[i].reset(); proc[i].reset();
} }
ul_sps_assig.clear();
} }
void ul_harq_entity::reset_ndi() { void ul_harq_entity::reset_ndi() {
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) { for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
proc[i].reset_ndi(); 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) { // Implements Section 5.4.1
run_tti(tti, NULL, phy_h); 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 // Implements Section 5.4.2.1
// Called with UL grant // 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 tti_tx = (tti+4)%10240;
uint32_t pid = pidof(tti_tx); uint32_t pid = pidof(tti_tx);
// Receive and route HARQ feedbacks // 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) {
if ((!grant->is_temp_rnti() && grant->get_ndi() != proc[pid].get_ndi()) || if ((!grant->rnti_type == SRSLTE_RNTI_TEMP && grant->ndi != proc[pid].get_ndi()) ||
(grant->is_crnti() && !proc[pid].has_grant()) || (grant->rnti_type == SRSLTE_RNTI_USER && !proc[pid].has_grant()) ||
grant->is_from_rar()) grant->is_from_rar)
{ {
// New transmission // New transmission
uint8_t* msg3_ptr = (uint8_t*) mux_unit->msg3_pop(grant->get_tbs());
// Uplink grant in a RAR // Uplink grant in a RAR
if (grant->is_from_rar()) { if (grant->is_from_rar) {
if (msg3_ptr) { if (mux_unit->msg3_get(payload_ptr, grant->n_bytes)) {
proc[pid].generate_new_tx(tti_tx, msg3_ptr, true, grant, phy_h->get_ul_buffer(tti_tx)); proc[pid].generate_new_tx(tti_tx, true, grant, action);
mux_unit->msg3_transmitted();
} else { } else {
Warning("UL RAR grant available but no Msg3 on buffer\n"); 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 // Normal UL grant
} else { } else {
// Request a MAC PDU from the Multiplexing & Assemble Unit // Request a MAC PDU from the Multiplexing & Assemble Unit
uint8_t* mac_pdu = mux_unit->pdu_pop(grant->get_tbs()); if (mux_unit->pdu_get(payload_ptr, grant->n_bytes)) {
if (mac_pdu) { proc[pid].generate_new_tx(tti_tx, false, grant, action);
// 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));
} else { } else {
mux_unit->pdu_release();
Warning("Uplink grant but no MAC PDU in Multiplex Unit buffer\n"); Warning("Uplink grant but no MAC PDU in Multiplex Unit buffer\n");
} }
} }
} else { } else {
// Adaptive Re-TX // 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()) { } else if (proc[pid].has_grant()) {
// Non-Adaptive Re-Tx // 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 rv_of_irv[4] = {0, 2, 3, 1};
static int irv_of_rv[4] = {0, 3, 1, 2}; 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_tx_nb = 0;
current_irv = 0; current_irv = 0;
is_initiated = false; is_initiated = false;
is_grant_configured = false; is_grant_configured = false;
tti_last_tx = 0; 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() { void ul_harq_entity::ul_harq_process::reset() {
current_tx_nb = 0; current_tx_nb = 0;
current_irv = 0; current_irv = 0;
tti_last_tx = 0; tti_last_tx = 0;
is_grant_configured = false; is_grant_configured = false;
bzero(&cur_grant, sizeof(ul_sched_grant));
if (is_initiated) { if (is_initiated) {
srslte_softbuffer_tx_reset(&softbuffer); srslte_softbuffer_tx_reset(&softbuffer);
} }
bzero(&cur_grant, sizeof(mac_interface_phy::mac_grant_t));
} }
bool ul_harq_entity::ul_harq_process::has_grant() { bool ul_harq_entity::ul_harq_process::has_grant() {
return is_grant_configured; return is_grant_configured;
} }
void ul_harq_entity::ul_harq_process::reset_ndi() { void ul_harq_entity::ul_harq_process::reset_ndi() {
ndi = false; ndi = false;
} }
bool ul_harq_entity::ul_harq_process::get_ndi() bool ul_harq_entity::ul_harq_process::get_ndi()
{ {
return ndi; return ndi;
@ -185,11 +216,6 @@ uint32_t ul_harq_entity::ul_harq_process::get_rv()
return rv_of_irv[current_irv%4]; 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) { void ul_harq_entity::ul_harq_process::set_harq_feedback(bool ack) {
harq_feedback = ack; harq_feedback = ack;
// UL packet successfully delivered // 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) { bool ul_harq_entity::ul_harq_process::init(uint32_t pid_, ul_harq_entity* parent) {
if (srslte_softbuffer_tx_init(&softbuffer, cell)) { if (srslte_softbuffer_tx_init(&softbuffer, 100)) {
fprintf(stderr, "Error initiating soft buffer\n"); fprintf(stderr, "Error initiating soft buffer\n");
return false; return false;
} else { } else {
is_initiated = true; is_initiated = true;
harq_entity = parent; harq_entity = parent;
log_h = harq_entity->log_h; log_h = harq_entity->log_h;
pid = pid_;
return true; 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) // 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++; current_tx_nb++;
if (grant) { if (grant) {
// HARQ entity requests an adaptive transmission // HARQ entity requests an adaptive transmission
memcpy(&cur_grant, grant, sizeof(ul_sched_grant)); current_irv = irv_of_rv[grant->rv%4];
current_irv = irv_of_rv[grant->get_rv()%4];
harq_feedback = false; 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()); Info("UL PID %d: Adaptive retx=%d, RV=%d, TBS=%d\n",
generate_tx(tti_tx, NULL, ul); pid, current_tx_nb, get_rv(), grant->n_bytes);
generate_tx(tti_tx, action);
} else { } 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 // HARQ entity requests a non-adaptive transmission
if (!harq_feedback) { 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) // 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); 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; harq_feedback = false;
is_grant_configured = true; is_grant_configured = true;
current_tx_nb = 0; current_tx_nb = 0;
current_irv = 0; current_irv = 0;
is_msg3 = is_msg3_; 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(), Info("UL PID %d: New TX%s, RV=%d, TBS=%d, RNTI=%d\n",
cur_grant.get_mcs(), cur_grant.get_rnti()); pid, is_msg3?" for Msg3":"", get_rv(), cur_grant.n_bytes, cur_grant.rnti);
generate_tx(tti_tx, pdu_payload, ul); generate_tx(tti_tx, action);
} }
} }
// Transmission of pending frame (Section 5.4.2.2) // 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()); action->current_tx_nb = current_tx_nb;
ul->set_current_tx_nb(current_tx_nb); action->expect_ack = true;
ul->generate_data(&cur_grant, &softbuffer, pdu_payload); action->rnti = is_msg3?harq_entity->params_db->get_param(mac_interface_params::RNTI_TEMP):cur_grant.rnti;
action->rv = get_rv();
if (harq_entity->pcap) { action->softbuffer = &softbuffer;
harq_entity->pcap->write_ul_crnti(pdu_payload, cur_grant.get_tbs()/8, cur_grant.get_rnti(), current_tx_nb, tti_tx); action->tx_enabled = true;
} memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(srslte_phy_grant_t));
current_irv = (current_irv+1)%4; current_irv = (current_irv+1)%4;
tti_last_tx = tti_tx; tti_last_tx = tti_tx;
if (is_msg3) { 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, 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(); reset();
action->expect_ack = false;
} }
} else { } 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, 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(); 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() uint32_t ul_harq_entity::ul_harq_process::last_tx_tti()
{ {
return tti_last_tx; 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 "liblte_rrc.h"
#include "srsapps/radio/radio_uhd.h" #include "srsapps/radio/radio_uhd.h"
#include "srsapps/ue/phy/phy.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/common/log_stdout.h"
#include "srsapps/ue/mac/mac.h" #include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/mac_pcap.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) { void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::ue::mac *mac, srslte::ue::phy *phy) {
// RACH-CONFIGCOMMON // RACH-CONFIGCOMMON
if (sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.present) { 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]); 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]); 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]); 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]); 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]); 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]); 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]); 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]); 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]); 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); 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", 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]); liblte_rrc_preamble_trans_max_num[sib2->rr_config_common_sib.rach_cnfg.preamble_trans_max]);
// PDSCH ConfigCommon // 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); 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); sib2->rr_config_common_sib.pdsch_cnfg.p_b);
// PUSCH ConfigCommon // PUSCH ConfigCommon
phy->set_param(srslte::ue::phy_params::PUSCH_BETA, 10); phy->set_param(srslte::ue::phy_interface_params::PUSCH_BETA, 10);
phy->set_param(srslte::ue::phy_params::PUSCH_EN_64QAM, phy->set_param(srslte::ue::phy_interface_params::PUSCH_EN_64QAM,
sib2->rr_config_common_sib.pusch_cnfg.enable_64_qam); 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); 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); 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); 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); 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); 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); 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); 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", 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); sib2->rr_config_common_sib.pusch_cnfg.n_sb);
// PUCCH ConfigCommon // PUCCH ConfigCommon
phy->set_param(srslte::ue::phy_params::PUCCH_BETA, 10); phy->set_param(srslte::ue::phy_interface_params::PUCCH_BETA, 10);
phy->set_param(srslte::ue::phy_params::PUCCH_DELTA_SHIFT, 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]); 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); 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); 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); sib2->rr_config_common_sib.pucch_cnfg.n_rb_cqi);
printf("Set PUCCH ConfigCommon: DeltaShift=%d, CyclicShift=%d, N1=%d, NRB=%d\n", 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], 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 // 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); 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); 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); 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); 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); 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", 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 // SRS ConfigCommon
if (sib2->rr_config_common_sib.srs_ul_cnfg.present) { 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_interface_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_interface_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_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", 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: // FIXME: There's an error parsing the connectionSetup message. This value is hard-coded:
if (msg->rr_cnfg.phy_cnfg_ded_present) { 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); 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); 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_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_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_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_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) { 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_interface_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_interface_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_interface_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_interface_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_interface_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_interface_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_interface_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_interface_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_interface_params::SRS_IS_CONFIGURED, 1);
phy->set_param(srslte::ue::phy_params::SRS_BETA, 10);
} }
} }
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", 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.srs_hopping_bandwidth,
msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.cyclic_shift); 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]); 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]); 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]); 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]); 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", 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) { if (prog_args.do_trace) {
//radio_uhd.write_trace("radio"); //radio_uhd.write_trace("radio");
phy.write_trace("phy"); phy.write_trace("phy");
mac.write_trace("mac");
} }
if (prog_args.do_pcap) { if (prog_args.do_pcap) {
mac_pcap.close(); mac_pcap.close();
@ -334,10 +332,139 @@ void sig_int_handler(int signo)
exit(0); 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[]) int main(int argc, char *argv[])
{ {
srslte::ue::tti_sync_cv ttisync(10240);
srslte::log_stdout mac_log("MAC"), phy_log("PHY"); srslte::log_stdout mac_log("MAC"), phy_log("PHY");
parse_args(&prog_args, argc, argv); parse_args(&prog_args, argc, argv);
@ -358,7 +485,6 @@ int main(int argc, char *argv[])
signal(SIGINT, sig_int_handler); signal(SIGINT, sig_int_handler);
//radio_uhd.start_trace(); //radio_uhd.start_trace();
phy.start_trace(); phy.start_trace();
mac.start_trace();
} }
if (prog_args.do_pcap) { if (prog_args.do_pcap) {
@ -374,144 +500,32 @@ int main(int argc, char *argv[])
radio_uhd.init(); radio_uhd.init();
radio_uhd.set_rx_gain(prog_args.uhd_rx_gain); radio_uhd.set_rx_gain(prog_args.uhd_rx_gain);
radio_uhd.set_tx_gain(prog_args.uhd_tx_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 { } else {
radio_uhd.init_agc(); radio_uhd.init_agc();
radio_uhd.set_tx_rx_gain_offset(0); 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 // Init MAC
mac.init(&phy, &ttisync, &mac_log); mac.init(&phy, &my_rlc, &mac_log);
// Set RX freq // Set RX freq
radio_uhd.set_rx_freq(prog_args.uhd_rx_freq); radio_uhd.set_rx_freq(prog_args.uhd_rx_freq);
radio_uhd.set_tx_freq(prog_args.uhd_tx_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) { while(1) {
switch(state) { uint32_t tti;
case START: if (my_rlc.mib_decoded) {
n = mac.recv_bcch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE); if (!my_rlc.sib1_decoded) {
if (n > 0) { tti = mac.get_current_tti();
bit_msg.N_bits = n; mac.set_param(srslte::ue::mac_interface_params::BCCH_SI_WINDOW_ST, sib_start_tti(tti, 2, 5));
liblte_rrc_unpack_bcch_bch_msg(&bit_msg, &bch_msg); mac.set_param(srslte::ue::mac_interface_params::BCCH_SI_WINDOW_LEN, 1);
printf("MIB received %d bytes, BW=%s\n", n, liblte_rrc_dl_bandwidth_text[bch_msg.dl_bw]); } else {
state = SIB1; 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));
break; mac.set_param(srslte::ue::mac_interface_params::BCCH_SI_WINDOW_LEN, my_rlc.si_window_len);
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;
} }
usleep(10000); 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); void worker_end(uint32_t tti, bool tx_enable, cf_t *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time);
bool sr_enabled; bool sr_enabled;
int sr_last_tx_tti;
private: private:
pthread_mutex_t tx_mutex; pthread_mutex_t tx_mutex;

@ -106,6 +106,9 @@ private:
uint16_t ul_rnti; uint16_t ul_rnti;
uint8_t *ul_payload; 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 // UL configuration parameters
srslte_refsignal_srs_cfg_t srs_cfg; srslte_refsignal_srs_cfg_t srs_cfg;
srslte_pucch_cfg_t pucch_cfg; srslte_pucch_cfg_t pucch_cfg;

@ -71,7 +71,7 @@ public:
void write_trace(std::string filename); void write_trace(std::string filename);
/********** MAC INTERFACE ********************/ /********** 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_prach_params();
void configure_ul_params(); void configure_ul_params();
@ -79,11 +79,13 @@ public:
void sync_start(); void sync_start();
void sync_stop(); void sync_stop();
/* Functions to initialize and transmit PRACH in the next opportunity */ /* Transmits PRACH in the next opportunity */
void prach_send(prach_cfg_t *cfg); 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 */ /* Indicates the transmission of a SR signal in the next opportunity */
void sr_send(); void sr_send();
int sr_last_tx_tti();
// Time advance commands // Time advance commands
void set_timeadv_rar(uint32_t ta_cmd); void set_timeadv_rar(uint32_t ta_cmd);

@ -49,10 +49,9 @@ namespace ue {
void init(phy_params *params_db, log *log_h); void init(phy_params *params_db, log *log_h);
bool init_cell(srslte_cell_t cell); bool init_cell(srslte_cell_t cell);
void free_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 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); 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); bool send(radio* radio_handler, float cfo, srslte_timestamp_t rx_time);
@ -66,12 +65,11 @@ namespace ue {
uint32_t len; uint32_t len;
cf_t *buffer[64]; cf_t *buffer[64];
srslte_prach_t prach_obj; srslte_prach_t prach_obj;
uint32_t transmitted_tti; int transmitted_tti;
srslte_cell_t cell; srslte_cell_t cell;
cf_t *signal_buffer; cf_t *signal_buffer;
srslte_cfo_t cfo_h; 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) { if (ret == 1) {
srslte_pbch_mib_unpack(bch_payload, &cell, NULL); srslte_pbch_mib_unpack(bch_payload, &cell, NULL);
srslte_cell_fprint(stdout, &cell, 0); srslte_cell_fprint(stdout, &cell, 0);
mac->bch_decoded_ok(bch_payload); mac->bch_decoded_ok(bch_payload, SRSLTE_BCH_PAYLOAD_LEN);
return true; return true;
} else { } else {
Warning("Error decoding MIB: Error decoding PBCH\n"); 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)) { if (prach_buffer->is_ready_to_send(tti)) {
srslte_timestamp_t cur_time; srslte_timestamp_t cur_time;
radio_h->get_time(&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 // send prach if we have to
prach_buffer->send(radio_h, cfo, tx_time); prach_buffer->send(radio_h, cfo, tx_time);
radio_h->tx_end(); 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);
} }
workers_pool->start_worker(worker); 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); 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); 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) { if (dl_action.generate_ack) {
set_uci_ack(dl_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 */ /* Fill MAC grant structure */
grant->ndi = dci_unpacked.ndi; grant->ndi = dci_unpacked.ndi;
grant->pid = dci_unpacked.harq_process; 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->tti = tti;
grant->rv = dci_unpacked.rv_idx; grant->rv = dci_unpacked.rv_idx;
grant->rnti = dl_rnti; 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 (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, 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"); Debug("TB decoded OK\n");
return true; return true;
} else { } 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"); Error("Converting RAR message to UL grant\n");
return false; return false;
} }
grant->is_from_rar = true;
Info("RAR grant found for TTI=%d\n", tti); Info("RAR grant found for TTI=%d\n", tti);
rar_cqi_request = rar_grant.cqi_request; rar_cqi_request = rar_grant.cqi_request;
ret = true; 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"); Error("Converting DCI message to UL grant\n");
return false; return false;
} }
grant->is_from_rar = false;
ret = true; ret = true;
Info("PDCCH: UL DCI Format0 cce_index=%d, n_data_bits=%d\n", ue_dl.last_n_cce, dci_msg.nof_bits); 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) { if (ret) {
grant->ndi = dci_unpacked.ndi; grant->ndi = dci_unpacked.ndi;
grant->pid = 0; // This is computed by MAC from TTI 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->tti = tti;
grant->rnti = ul_rnti; 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)) { if (srslte_ue_ul_sr_send_tti(I_sr, tti+4)) {
Info("SR transmission at TTI=%d\n", tti+4); Info("SR transmission at TTI=%d\n", tti+4);
uci_data.scheduling_request = true; uci_data.scheduling_request = true;
phy->sr_last_tx_tti = tti+4;
phy->sr_enabled = false; 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"); 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, if (srslte_ue_ul_pusch_encode_rnti_softbuffer(&ue_ul,
ul_payload, uci_data, payload_bits, uci_data,
softbuffer, softbuffer,
rnti, rnti,
signal_buffer)) signal_buffer))

@ -187,14 +187,19 @@ void phy::get_current_cell(srslte_cell_t *cell)
sf_recv.get_current_cell(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"); Error("Preparing PRACH to send\n");
} }
} }
int phy::prach_tx_tti()
{
return prach_buffer.tx_tti();
}
void phy::reset() void phy::reset()
{ {
// TODO // TODO
@ -210,6 +215,11 @@ void phy::sr_send()
workers_common.sr_enabled = true; workers_common.sr_enabled = true;
} }
int phy::sr_last_tx_tti()
{
return workers_common.sr_last_tx_tti;
}
bool phy::status_is_sync() bool phy::status_is_sync()
{ {
return sf_recv.status_is_sync(); return sf_recv.status_is_sync();

@ -95,16 +95,6 @@ bool prach::init_cell(srslte_cell_t cell_)
return initiated; 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) bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_, float target_power_dbm)
{ {
if (initiated && preamble_idx_ < 64) { if (initiated && preamble_idx_ < 64) {
@ -137,17 +127,8 @@ bool prach::is_ready_to_send(uint32_t current_tti_) {
return false; return false;
} }
void prach::get_rar_cfg(uint16_t *rar_rnti, uint32_t *tti_start, uint32_t *tti_end) int prach::tx_tti() {
{ return transmitted_tti;
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;
}
} }
bool prach::send(radio *radio_handler, float cfo, srslte_timestamp_t tx_time) 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 class testmac : public srslte::ue::mac_interface_phy
{ {
public: 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) { void new_grant_ul(mac_grant_t grant, uint8_t *payload_ptr, tb_action_ul_t *action) {
printf("New grant UL\n"); 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->current_tx_nb = nof_rtx_connsetup;
action->rv = rv_value[nof_rtx_connsetup%4]; action->rv = rv_value[nof_rtx_connsetup%4];
action->softbuffer = &softbuffer_tx; action->softbuffer = &softbuffer_tx;
@ -272,7 +289,7 @@ public:
temp_c_rnti = rar_msg.temp_c_rnti; 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]; uint8_t rar_grant[SRSLTE_RAR_GRANT_LEN];
memcpy(rar_grant, &payload[20], sizeof(uint8_t)*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); 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"); printf("BCH decoded\n");
bch_decoded = true; bch_decoded = true;
srslte_cell_t cell; srslte_cell_t cell;
my_phy.get_current_cell(&cell); my_phy.get_current_cell(&cell);
srslte_softbuffer_rx_init(&softbuffer_rx, cell); srslte_softbuffer_rx_init(&softbuffer_rx, cell.nof_prb);
srslte_softbuffer_tx_init(&softbuffer_tx, cell); srslte_softbuffer_tx_init(&softbuffer_tx, cell.nof_prb);
} }
private: private:
mac_grant_t last_grant; mac_grant_t last_grant;
}; };
@ -347,13 +365,7 @@ int main(int argc, char *argv[])
config_phy(); config_phy();
/* Instruct PHY to send PRACH and prepare it for receiving RAR */ /* Instruct PHY to send PRACH and prepare it for receiving RAR */
srslte::ue::phy_interface::prach_cfg_t prach_cfg; my_phy.prach_send(preamble_idx);
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);
/* go to idle and process each tti */ /* go to idle and process each tti */
bool running = true; bool running = true;

@ -127,13 +127,14 @@ public:
total_oks++; total_oks++;
} }
void bch_decoded_ok(uint8_t *payload) { void bch_decoded_ok(uint8_t *payload, uint32_t len) {
printf("BCH decoded\n"); printf("BCH decoded\n");
bch_decoded = true; bch_decoded = true;
srslte_cell_t cell; srslte_cell_t cell;
my_phy.get_current_cell(&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); 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"); fprintf(stderr, "Error initiating soft buffer\n");
exit(-1); exit(-1);
} }

@ -53,14 +53,14 @@ typedef struct SRSLTE_API {
} srslte_softbuffer_tx_t; } srslte_softbuffer_tx_t;
SRSLTE_API int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t * q, 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_reset(srslte_softbuffer_rx_t *p);
SRSLTE_API void srslte_softbuffer_rx_free(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_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); 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) #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; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL) { 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)); 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) { if (ret != SRSLTE_ERROR) {
q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1; 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; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL) { 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)); 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) { if (ret != SRSLTE_ERROR) {
q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1; 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); 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"); mexErrMsgTxt("Error initiating DL-SCH soft buffer\n");
return; return;
} }

@ -183,12 +183,12 @@ int main(int argc, char **argv) {
srslte_pdsch_set_rnti(&pdsch, 1234); 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"); fprintf(stderr, "Error initiating TX soft buffer\n");
goto quit; 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"); fprintf(stderr, "Error initiating RX soft buffer\n");
goto quit; 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)); 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"); mexErrMsgTxt("Error initiating soft buffer\n");
return; return;
} }

@ -139,7 +139,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_softbuffer_tx_t softbuffer; 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"); mexErrMsgTxt("Error initiating soft buffer\n");
return; return;
} }

@ -207,7 +207,7 @@ int main(int argc, char **argv) {
} }
gettimeofday(&t[1], NULL); 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"); fprintf(stderr, "Error initiating soft buffer\n");
goto quit; goto quit;
} }

@ -69,7 +69,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
cell.id=1; cell.id=1;
cell.cp=SRSLTE_CP_NORM; 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"); mexErrMsgTxt("Error initiating HARQ\n");
return; return;
} }

@ -86,7 +86,7 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
fprintf(stderr, "Error creating PDSCH object\n"); fprintf(stderr, "Error creating PDSCH object\n");
goto clean_exit; 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"); fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit; goto clean_exit;
} }

@ -74,7 +74,7 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
fprintf(stderr, "Error creating PUSCH object\n"); fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit; 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"); fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit; goto clean_exit;
} }

Loading…
Cancel
Save