mirror of https://github.com/PentHertz/srsLTE.git
MAC/PHY compiling
This commit is contained in:
parent
f65aa3be1d
commit
309ebd80e5
|
@ -53,9 +53,12 @@ public:
|
|||
uint32_t pid;
|
||||
uint32_t tti;
|
||||
bool ndi;
|
||||
uint32_t tbs;
|
||||
uint32_t n_bytes;
|
||||
uint32_t rv;
|
||||
uint16_t rnti;
|
||||
bool is_from_rar;
|
||||
bool is_sps_release;
|
||||
srslte_rnti_type_t rnti_type;
|
||||
srslte_phy_grant_t phy_grant;
|
||||
} mac_grant_t;
|
||||
|
||||
|
@ -65,6 +68,9 @@ public:
|
|||
uint16_t rnti;
|
||||
bool generate_ack;
|
||||
bool default_ack;
|
||||
// If non-null, called after tb_decoded_ok to determine if ack needs to be sent
|
||||
bool (*generate_ack_callback)(void*);
|
||||
void *generate_ack_callback_arg;
|
||||
uint8_t *payload_ptr;
|
||||
srslte_softbuffer_rx_t *softbuffer;
|
||||
srslte_phy_grant_t phy_grant;
|
||||
|
@ -97,7 +103,7 @@ public:
|
|||
virtual void tb_decoded_ok(uint32_t harq_pid) = 0;
|
||||
|
||||
/* Indicate successfull decoding of BCH TB through PBCH */
|
||||
virtual void bch_decoded_ok(uint8_t *payload) = 0;
|
||||
virtual void bch_decoded_ok(uint8_t *payload, uint32_t len) = 0;
|
||||
|
||||
/* Function called every start of a subframe (TTI). Warning, this function is called
|
||||
* from a high priority thread and should terminate asap
|
||||
|
@ -113,7 +119,9 @@ public:
|
|||
|
||||
/* RLC configures a logical channel */
|
||||
virtual void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD) = 0;
|
||||
|
||||
|
||||
virtual uint32_t get_current_tti() = 0;
|
||||
|
||||
virtual void reconfiguration() = 0;
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
@ -126,13 +134,17 @@ public:
|
|||
/* MAC calls RLC to get buffer state for a logical channel. This function should return quickly */
|
||||
virtual uint32_t get_buffer_state(uint32_t lcid) = 0;
|
||||
|
||||
/* MAC calls RLC to get RLC segment of nof_bytes length. Segmentation happens in this function. RLC PDU is stored in payload. */
|
||||
virtual void read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) = 0;
|
||||
/* MAC calls RLC to get RLC segment of nof_bytes length. Segmentation happens in this function. RLC PDU is stored in
|
||||
* payload. */
|
||||
virtual uint32_t read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) = 0;
|
||||
|
||||
/* MAC calls RLC to push an RLC PDU. This function is called from an independent MAC thread. PDU gets placed into the PDCP buffer and higher layer thread gets notified
|
||||
when the last segment is received
|
||||
/* MAC calls RLC to push an RLC PDU. This function is called from an independent MAC thread. PDU gets placed into the
|
||||
* PDCP buffer and higher layer thread gets notified
|
||||
* when the last segment is received
|
||||
*/
|
||||
virtual void write_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) = 0;
|
||||
virtual void write_pdu_bcch_bch(uint8_t *payload, uint32_t nof_bytes) = 0;
|
||||
virtual void write_pdu_bcch_dlsch(uint8_t *payload, uint32_t nof_bytes) = 0;
|
||||
|
||||
|
||||
};
|
||||
|
@ -145,6 +157,9 @@ public:
|
|||
SPS_DL_SCHED_INTERVAL,
|
||||
SPS_DL_NOF_PROC,
|
||||
|
||||
RNTI_TEMP,
|
||||
RNTI_C,
|
||||
|
||||
BCCH_SI_WINDOW_ST,
|
||||
BCCH_SI_WINDOW_LEN,
|
||||
|
||||
|
|
|
@ -133,23 +133,12 @@ public:
|
|||
virtual void sync_start() = 0;
|
||||
virtual void sync_stop() = 0;
|
||||
|
||||
/* Functions to initialize and transmit PRACH in the next opportunity.
|
||||
* This function returns at the start of the rar reception window, ie the transmission
|
||||
* TTI + rar_start
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t preamble_idx;
|
||||
bool allowed_subframe_enabled;
|
||||
uint32_t allowed_subframe;
|
||||
float target_power_dbm;
|
||||
uint16_t rar_rnti;
|
||||
uint32_t rar_start;
|
||||
uint32_t rar_window;
|
||||
} prach_cfg_t;
|
||||
virtual void prach_send(prach_cfg_t *cfg) = 0;
|
||||
|
||||
virtual void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) = 0;
|
||||
virtual int prach_tx_tti() = 0;
|
||||
|
||||
/* Indicates the transmission of a SR signal in the next opportunity */
|
||||
virtual void sr_send() = 0;
|
||||
virtual int sr_last_tx_tti() = 0;
|
||||
|
||||
/* Time advance commands */
|
||||
virtual void set_timeadv_rar(uint32_t ta_cmd) = 0;
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2015 The srsLTE Developers. See the
|
||||
* COPYRIGHT file at the top-level directory of this distribution.
|
||||
*
|
||||
* \section LICENSE
|
||||
*
|
||||
* This file is part of the srsLTE library.
|
||||
*
|
||||
* srsLTE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsLTE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#ifndef TTISYNC_H
|
||||
#define TTISYNC_H
|
||||
|
||||
|
||||
namespace srslte {
|
||||
namespace ue {
|
||||
|
||||
/* Interface used for PHY-MAC synchronization (producer-consumer model).
|
||||
* The consumer waits while its counter is lower than the producer counter.
|
||||
* The PHY is the consumer. The MAC is the producer.
|
||||
*/
|
||||
class tti_sync
|
||||
{
|
||||
public:
|
||||
tti_sync(uint32_t modulus_)
|
||||
{
|
||||
modulus = modulus_;
|
||||
increment = 1;
|
||||
init_counters(0);
|
||||
}
|
||||
virtual void increase() = 0;
|
||||
virtual void resync() = 0;
|
||||
virtual uint32_t wait() = 0;
|
||||
virtual void set_producer_cntr(uint32_t) = 0;
|
||||
uint32_t get_producer_cntr() { return producer_cntr; }
|
||||
uint32_t get_consumer_cntr() { return consumer_cntr; }
|
||||
void set_increment(uint32_t increment_) {
|
||||
increment = increment_;
|
||||
}
|
||||
protected:
|
||||
void increase_producer() { producer_cntr = (producer_cntr + increment)%modulus; }
|
||||
void increase_consumer() { consumer_cntr = (consumer_cntr + increment)%modulus; }
|
||||
bool wait_condition() { return producer_cntr == consumer_cntr; }
|
||||
void init_counters(uint32_t val)
|
||||
{
|
||||
consumer_cntr = val;
|
||||
producer_cntr = val;
|
||||
}
|
||||
uint32_t increment;
|
||||
uint32_t modulus;
|
||||
uint32_t producer_cntr;
|
||||
uint32_t consumer_cntr;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -25,24 +25,37 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsapps/ue/mac/dl_sps.h"
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include "srsapps/common/tti_sync.h"
|
||||
|
||||
|
||||
#ifndef TTISYNC_CV_H
|
||||
#define TTISYNC_CV_H
|
||||
|
||||
|
||||
namespace srslte {
|
||||
namespace ue {
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
dl_sched_grant* dl_sps::get_pending_grant(uint32_t tti)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
void dl_sps::reset(uint32_t tti, dl_sched_grant* grant)
|
||||
{
|
||||
|
||||
}
|
||||
void dl_sps::clear()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -28,12 +28,12 @@
|
|||
|
||||
|
||||
#include "srsapps/ue/phy/phy.h"
|
||||
#include "srsapps/common/mac_interface.h"
|
||||
#include "srsapps/common/log.h"
|
||||
#include "srsapps/ue/mac/mac_io.h"
|
||||
#include "srsapps/common/qbuff.h"
|
||||
#include "srsapps/common/timers.h"
|
||||
#include "srsapps/ue/mac/mac_params.h"
|
||||
#include "srsapps/ue/mac/pdu.h"
|
||||
#include "srsapps/ue/mac/sdu_handler.h"
|
||||
|
||||
#ifndef DEMUX_H
|
||||
#define DEMUX_H
|
||||
|
@ -47,13 +47,15 @@ class demux
|
|||
{
|
||||
public:
|
||||
demux();
|
||||
void init(phy* phy_h_, log* log_h_, mac_io* mac_io_h_, timers* timers_db_);
|
||||
void init(phy_interface* phy_h_, rlc_interface_mac *rlc, log* log_h_, timers* timers_db_);
|
||||
|
||||
void add_sdu_handler(sdu_handler *handler);
|
||||
void process_pdus();
|
||||
uint8_t* request_buffer(uint32_t len);
|
||||
|
||||
void release_pdu(uint8_t *buff, uint32_t nof_bytes);
|
||||
void release_pdu_bcch(uint8_t *buff, uint32_t nof_bytes);
|
||||
void release_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes);
|
||||
|
||||
void push_pdu(uint8_t *mac_pdu, uint32_t nof_bits);
|
||||
void push_pdu_bcch(uint8_t *mac_pdu, uint32_t nof_bits);
|
||||
void push_pdu_temp_crnti(uint8_t *mac_pdu, uint32_t nof_bits);
|
||||
bool is_temp_crnti_pending();
|
||||
bool is_contention_resolution_id_pending();
|
||||
void demultiplex_pending_pdu();
|
||||
|
@ -62,24 +64,38 @@ public:
|
|||
uint64_t get_contention_resolution_id();
|
||||
|
||||
private:
|
||||
const static int NOF_PDU_Q = 3; // prevents threads from being locked
|
||||
const static int MAX_PDU_LEN = 128*1024;
|
||||
|
||||
sch_pdu mac_msg;
|
||||
sch_pdu pending_mac_msg;
|
||||
|
||||
void process_pdu(sch_pdu *pdu);
|
||||
void process_pdu(uint8_t *pdu, uint32_t nof_bytes);
|
||||
void process_sch_pdu(sch_pdu *pdu);
|
||||
bool process_ce(sch_subh *subheader);
|
||||
|
||||
// Mutex for exclusive access
|
||||
pthread_mutex_t mutex;
|
||||
bool find_unused_queue(uint8_t *idx);
|
||||
bool find_nonempty_queue(uint8_t *idx);
|
||||
void push_buffer(uint8_t *buff, uint32_t nof_bytes);
|
||||
|
||||
uint64_t contention_resolution_id;
|
||||
bool pending_temp_rnti;
|
||||
bool has_pending_contention_resolution_id;
|
||||
|
||||
typedef struct {
|
||||
uint8_t idx;
|
||||
uint8_t dummy[15]; // FIXME: This it to keep 128-bit alignment
|
||||
} buff_header_t;
|
||||
|
||||
phy *phy_h;
|
||||
log *log_h;
|
||||
mac_io *mac_io_h;
|
||||
timers *timers_db;
|
||||
sdu_handler *sdu_handler_;
|
||||
// Mutex for exclusive access
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cvar;
|
||||
qbuff pdu_q[NOF_PDU_Q];
|
||||
bool used_q[NOF_PDU_Q];
|
||||
|
||||
phy_interface *phy_h;
|
||||
log *log_h;
|
||||
timers *timers_db;
|
||||
rlc_interface_mac *rlc;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "srsapps/ue/mac/mac_params.h"
|
||||
#include "srsapps/common/timers.h"
|
||||
#include "srsapps/ue/mac/demux.h"
|
||||
#include "srsapps/ue/mac/dl_sps.h"
|
||||
#include "srsapps/ue/mac/mac_pcap.h"
|
||||
|
||||
#ifndef DLHARQ_H
|
||||
|
@ -43,8 +44,6 @@
|
|||
namespace srslte {
|
||||
namespace ue {
|
||||
|
||||
typedef _Complex float cf_t;
|
||||
|
||||
class dl_harq_entity
|
||||
{
|
||||
public:
|
||||
|
@ -53,49 +52,56 @@ public:
|
|||
const static uint32_t HARQ_BCCH_PID = NOF_HARQ_PROC;
|
||||
|
||||
dl_harq_entity();
|
||||
bool init(srslte_cell_t cell, uint32_t max_payload_len, srslte::log *log_h_, timers *timers_, demux *demux_unit);
|
||||
bool is_sps(uint32_t pid);
|
||||
void set_harq_info(uint32_t pid, dl_sched_grant *grant);
|
||||
void receive_data(uint32_t tti, uint32_t pid, dl_buffer *dl_buffer, phy *phy_h);
|
||||
bool init(log *log_h_, timers *timers_, demux *demux_unit);
|
||||
|
||||
|
||||
/***************** PHY->MAC interface for DL processes **************************/
|
||||
void new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t *action);
|
||||
void tb_decoded_ok(uint32_t harq_pid);
|
||||
|
||||
|
||||
void reset();
|
||||
bool is_ack_pending_resolution();
|
||||
void send_pending_ack_contention_resolution();
|
||||
void start_pcap(mac_pcap* pcap);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
class dl_harq_process {
|
||||
public:
|
||||
dl_harq_process();
|
||||
bool init(srslte_cell_t cell, uint32_t max_payload_len, dl_harq_entity *parent);
|
||||
void set_harq_info(dl_sched_grant *grant);
|
||||
void receive_data(uint32_t tti, dl_buffer *dl_buffer, phy *phy_h);
|
||||
bool init(uint32_t pid, dl_harq_entity *parent);
|
||||
void reset();
|
||||
// Called after the contention resolution is terminated to send pending ACKs, if any
|
||||
void send_pending_ack_contention_resolution();
|
||||
uint32_t pid;
|
||||
bool is_sps();
|
||||
bool is_new_transmission(mac_interface_phy::mac_grant_t grant);
|
||||
void new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t *action);
|
||||
void tb_decoded_ok();
|
||||
|
||||
private:
|
||||
|
||||
bool is_initiated;
|
||||
dl_harq_entity *harq_entity;
|
||||
uint8_t *payload;
|
||||
uint32_t max_payload_len;
|
||||
dl_sched_grant cur_grant;
|
||||
dl_sched_grant pending_ack_grant;
|
||||
ul_buffer *pending_ul_buffer;
|
||||
bool pending_ack;
|
||||
srslte::log *log_h;
|
||||
log *log_h;
|
||||
|
||||
uint32_t pid;
|
||||
uint8_t *payload_buffer_ptr;
|
||||
bool ack;
|
||||
|
||||
mac_interface_phy::mac_grant_t cur_grant;
|
||||
srslte_softbuffer_rx_t softbuffer;
|
||||
|
||||
srslte_softbuffer_rx_t softbuffer;
|
||||
bool ack;
|
||||
};
|
||||
static bool generate_ack_callback(void *arg);
|
||||
|
||||
uint32_t get_harq_sps_pid(uint32_t tti);
|
||||
|
||||
dl_harq_process proc[NOF_HARQ_PROC+1];
|
||||
dl_sps dl_sps_assig;
|
||||
|
||||
dl_harq_process proc[NOF_HARQ_PROC+1];
|
||||
timers *timers_db;
|
||||
demux *demux_unit;
|
||||
srslte::log *log_h;
|
||||
int pending_ack_pid;
|
||||
log *log_h;
|
||||
mac_pcap *pcap;
|
||||
uint16_t last_temporal_crnti;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -41,15 +41,15 @@
|
|||
namespace srslte {
|
||||
namespace ue {
|
||||
|
||||
typedef _Complex float cf_t;
|
||||
|
||||
class dl_sps
|
||||
{
|
||||
public:
|
||||
|
||||
void clear();
|
||||
void reset(uint32_t tti, dl_sched_grant *grant);
|
||||
dl_sched_grant *get_pending_grant(uint32_t tti);
|
||||
void clear() {}
|
||||
void reset() {}
|
||||
bool get_pending_grant(uint32_t tti, mac_interface_phy::mac_grant_t *grant) {
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
|
||||
};
|
||||
|
|
|
@ -25,29 +25,22 @@
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "srsapps/common/log.h"
|
||||
#include "srsapps/ue/phy/phy.h"
|
||||
#include "srsapps/ue/mac/mac_params.h"
|
||||
#include "srsapps/ue/mac/dl_harq.h"
|
||||
#include "srsapps/ue/mac/ul_harq.h"
|
||||
#include "srsapps/ue/mac/dl_sps.h"
|
||||
#include "srsapps/ue/mac/ul_sps.h"
|
||||
#include "srsapps/common/timers.h"
|
||||
#include "srsapps/ue/mac/mac_io.h"
|
||||
#include "srsapps/ue/mac/proc_ra.h"
|
||||
#include "srsapps/ue/mac/proc_sr.h"
|
||||
#include "srsapps/ue/mac/proc_bsr.h"
|
||||
#include "srsapps/ue/mac/proc_phr.h"
|
||||
#include "srsapps/ue/mac/mux.h"
|
||||
#include "srsapps/ue/mac/demux.h"
|
||||
#include "srsapps/ue/mac/sdu_handler.h"
|
||||
#include "srsapps/ue/mac/mac_pcap.h"
|
||||
#include "srsapps/common/trace.h"
|
||||
#include "srsapps/common/mac_interface.h"
|
||||
#include "srsapps/common/tti_sync_cv.h"
|
||||
#include "srsapps/common/threads.h"
|
||||
|
||||
|
||||
#ifndef UEMAC_H
|
||||
|
@ -56,95 +49,68 @@
|
|||
namespace srslte {
|
||||
namespace ue {
|
||||
|
||||
typedef _Complex float cf_t;
|
||||
|
||||
class mac : public timer_callback, mac_interface_phy, mac_interface_rlc
|
||||
class mac : public thread, timer_callback, mac_interface_phy, mac_interface_rlc, mac_interface_params
|
||||
{
|
||||
public:
|
||||
mac() : timers_db((uint32_t) NOF_MAC_TIMERS), tr_exec_total(1024*10), tr_exec_dl(1024*10), tr_exec_ul(1024*10) {started=false; pcap = NULL; }
|
||||
bool init(phy *phy_h, tti_sync *ttisync, log *log_h);
|
||||
mac();
|
||||
bool init(phy_interface *phy, rlc_interface_mac *rlc, log *log_h);
|
||||
void stop();
|
||||
int get_tti();
|
||||
void main_radio_loop(); // called after thread creation
|
||||
|
||||
void add_sdu_handler(sdu_handler *handler);
|
||||
/******** Interface from PHY (PHY -> MAC) ****************/
|
||||
/* see mac_interface.h for comments */
|
||||
void new_grant_ul(mac_grant_t grant, uint8_t *payload_ptr, tb_action_ul_t *action);
|
||||
void new_grant_ul_ack(mac_grant_t grant, uint8_t *payload_ptr, bool ack, tb_action_ul_t *action);
|
||||
void harq_recv(uint32_t tti, bool ack, tb_action_ul_t *action);
|
||||
void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action);
|
||||
void tb_decoded_ok(uint32_t harq_pid);
|
||||
void bch_decoded_ok(uint8_t *payload, uint32_t len);
|
||||
void tti_clock(uint32_t tti);
|
||||
|
||||
|
||||
bool send_sdu(uint32_t lcid, uint8_t *sdu_payload, uint32_t nbytes);
|
||||
bool send_ccch_sdu(uint8_t *sdu_payload, uint32_t nbytes);
|
||||
bool send_dtch0_sdu(uint8_t *sdu_payload, uint32_t nbytes); // SRB0
|
||||
bool send_dcch0_sdu(uint8_t *sdu_payload, uint32_t nbytes); // DRB0
|
||||
|
||||
int recv_sdu(uint32_t lcid, uint8_t *sdu_payload, uint32_t nbytes);
|
||||
int recv_bcch_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes);
|
||||
int recv_ccch_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes);
|
||||
int recv_dtch0_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes); // SRB0
|
||||
int recv_dcch0_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes); // DRB0
|
||||
|
||||
/******** Interface from RLC (RLC -> MAC) ****************/
|
||||
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);
|
||||
|
||||
void reconfiguration();
|
||||
void reset();
|
||||
|
||||
void start_trace();
|
||||
void write_trace(std::string filename);
|
||||
|
||||
/******** MAC parameters ****************/
|
||||
void set_param(mac_interface_params::mac_param_t param, int64_t value);
|
||||
int64_t get_param(mac_interface_params::mac_param_t param);
|
||||
|
||||
void timer_expired(uint32_t timer_id);
|
||||
void start_pcap(mac_pcap* pcap);
|
||||
|
||||
|
||||
uint32_t get_current_tti();
|
||||
|
||||
|
||||
enum {
|
||||
HARQ_RTT = 0,
|
||||
HARQ_RTT,
|
||||
TIME_ALIGNMENT,
|
||||
CONTENTION_TIMER,
|
||||
BSR_TIMER_PERIODIC,
|
||||
BSR_TIMER_RETX,
|
||||
NOF_MAC_TIMERS
|
||||
} mac_timers_t;
|
||||
|
||||
class tti_thread {
|
||||
public:
|
||||
bool init(mac *parent, tti_sync_cv *ttysync);
|
||||
void run();
|
||||
void run_tti(uint32_t tti);
|
||||
void stop();
|
||||
private:
|
||||
bool started;
|
||||
log *log_h;
|
||||
mac *parent;
|
||||
tti_sync_cv *sync;
|
||||
pthread_t thread;
|
||||
};
|
||||
|
||||
static const int NOF_TTI_THREADS = 2;
|
||||
|
||||
private:
|
||||
void run_thread();
|
||||
void search_si_rnti();
|
||||
|
||||
|
||||
// TTI processing threads
|
||||
tti_thread tti_threads[NOF_TTI_THREADS];
|
||||
tti_sync_cv tti_threads_sync[NOF_TTI_THREADS];
|
||||
pthread_mutex_t tti_threads_sync_tx[NOF_TTI_THREADS];
|
||||
bool is_first_tx;
|
||||
|
||||
static const int MAC_THREAD_PRIO = 5;
|
||||
|
||||
// Interaction with PHY
|
||||
tti_sync *ttisync;
|
||||
phy *phy_h;
|
||||
log *log_h;
|
||||
|
||||
/* Logical channel (lch) IO */
|
||||
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;
|
||||
pthread_t mac_thread;
|
||||
static void* mac_thread_fnc(void*);
|
||||
|
||||
int tti;
|
||||
uint32_t tti;
|
||||
bool started;
|
||||
bool is_synchronized;
|
||||
uint16_t last_temporal_crnti;
|
||||
uint16_t phy_rnti;
|
||||
|
||||
/* Multiplexing/Demultiplexing Units */
|
||||
mux mux_unit;
|
||||
|
@ -154,46 +120,22 @@ private:
|
|||
dl_harq_entity dl_harq;
|
||||
ul_harq_entity ul_harq;
|
||||
|
||||
/* DL/UL Semi-Persistent Sched */
|
||||
dl_sps dl_sps_assig;
|
||||
ul_sps ul_sps_assig;
|
||||
uint32_t get_harq_sps_pid(uint32_t tti);
|
||||
|
||||
int si_window_start, si_window_length;
|
||||
|
||||
/* MAC Uplink-related Procedures */
|
||||
ra_proc ra_procedure;
|
||||
sr_proc sr_procedure;
|
||||
bsr_proc bsr_procedure;
|
||||
phr_proc phr_procedure;
|
||||
|
||||
/* Other procedures */
|
||||
void process_dl_grants(uint32_t tti);
|
||||
bool process_ul_grants(uint32_t tti);
|
||||
void receive_pch(uint32_t tti);
|
||||
|
||||
/* Functions for MAC Timers */
|
||||
timers timers_db;
|
||||
uint16_t phy_rnti;
|
||||
void setup_timers();
|
||||
void timeAlignmentTimerExpire();
|
||||
|
||||
// pointer to MAC PCAP object
|
||||
mac_pcap* pcap;
|
||||
|
||||
// Variables for Execution time Trace
|
||||
trace<uint32_t> tr_exec_total;
|
||||
trace<uint32_t> tr_exec_dl;
|
||||
trace<uint32_t> tr_exec_ul;
|
||||
struct timeval tr_time_total[3];
|
||||
struct timeval tr_time_ul[3];
|
||||
struct timeval tr_time_dl[3];
|
||||
bool tr_enabled;
|
||||
bool is_first_of_burst;
|
||||
void tr_log_start(uint32_t tti);
|
||||
void tr_log_end(uint32_t tti);
|
||||
void tr_log_dl(uint32_t tti);
|
||||
void tr_log_ul(uint32_t tti);
|
||||
void pregen_phy(uint16_t phy_rnti);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2015 The srsLTE Developers. See the
|
||||
* COPYRIGHT file at the top-level directory of this distribution.
|
||||
*
|
||||
* \section LICENSE
|
||||
*
|
||||
* This file is part of the srsLTE library.
|
||||
*
|
||||
* srsLTE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsLTE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include "srsapps/common/qbuff.h"
|
||||
|
||||
#ifndef MACIO_H
|
||||
#define MACIO_H
|
||||
|
||||
/* Manages all MAC buffers including:
|
||||
* - communication with higher layers through logical channels
|
||||
* - communication between logical channels buffers and Dissassembly/Assembly unit
|
||||
* - communication between Dissassembly/Assembly unit and Msg3 buffer
|
||||
*
|
||||
* For logical channels, IN means higher layers to MAC. OUT means MAC to higher layers.
|
||||
*
|
||||
* See queue.h for instructions on how to manage buffers
|
||||
*/
|
||||
|
||||
namespace srslte {
|
||||
namespace ue {
|
||||
|
||||
class mac_io
|
||||
{
|
||||
public:
|
||||
|
||||
// list of logical channels
|
||||
// Keep this order to match LoCH id with RB
|
||||
typedef enum {
|
||||
// Downlink (UE MAC -> UE RRC)
|
||||
MAC_LCH_CCCH_DL = 0, // SRB0
|
||||
MAC_LCH_DCCH0_DL, // SRB1
|
||||
MAC_LCH_DCCH1_DL, // SRB2
|
||||
MAC_LCH_DTCH0_DL, // DRB0
|
||||
MAC_LCH_DTCH1_DL, // DRB1
|
||||
MAC_LCH_DTCH2_DL, // DRB2
|
||||
MAC_LCH_BCCH_DL, // N/A
|
||||
MAC_LCH_PCCH_DL, // N/A
|
||||
|
||||
// Uplink (UE RLC -> UE MAC)
|
||||
MAC_LCH_CCCH_UL, // SRB0
|
||||
MAC_LCH_DCCH0_UL, // SRB1
|
||||
MAC_LCH_DCCH1_UL, // SRB2
|
||||
MAC_LCH_DTCH0_UL, // DRB0
|
||||
MAC_LCH_DTCH1_UL, // DRB1
|
||||
MAC_LCH_DTCH2_UL, // DRB2
|
||||
|
||||
MAC_NOF_QUEUES
|
||||
} mac_lch_t;
|
||||
|
||||
const static int NOF_DL_LCH = MAC_LCH_PCCH_DL - MAC_LCH_CCCH_DL;
|
||||
const static int NOF_UL_LCH = MAC_LCH_DTCH2_UL - MAC_LCH_CCCH_UL;
|
||||
|
||||
const static int DEFAULT_MSG_SZ = 8*1024; // 8 Kbytes
|
||||
const static int DEFAULT_NOF_MESSAGES = 64;
|
||||
|
||||
|
||||
qbuff* get(mac_lch_t ch) {
|
||||
return get((uint32_t) ch);
|
||||
}
|
||||
|
||||
qbuff* get(int32_t lchid) {
|
||||
if (lchid < MAC_NOF_QUEUES) {
|
||||
return &queues[lchid];
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Move packets between queues with only 1 memcpy
|
||||
void move(mac_lch_t src, mac_lch_t dst) {
|
||||
get(src)->move_to(get(dst));
|
||||
}
|
||||
|
||||
mac_io() {
|
||||
for (int i=0;i<MAC_NOF_QUEUES;i++) {
|
||||
queues[i].init(DEFAULT_NOF_MESSAGES, DEFAULT_MSG_SZ);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
qbuff queues[MAC_NOF_QUEUES];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "srslte/srslte.h"
|
||||
#include "srsapps/common/params_db.h"
|
||||
#include "srsapps/common/mac_interface.h"
|
||||
|
||||
#ifndef MACPARAMS_H
|
||||
#define MACPARAMS_H
|
||||
|
@ -41,7 +42,7 @@ namespace ue {
|
|||
{
|
||||
public:
|
||||
|
||||
mac_params() : params_db(NOF_PARAMS) {}
|
||||
mac_params() : params_db(mac_interface_params::NOF_PARAMS) {}
|
||||
~mac_params() {}
|
||||
|
||||
|
||||
|
|
|
@ -56,9 +56,6 @@ private:
|
|||
uint32_t ue_id;
|
||||
void pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reTX, bool crc_ok, uint32_t tti,
|
||||
uint16_t crnti_, uint8_t direction, uint8_t rnti_type);
|
||||
|
||||
static const uint32_t max_pdu_len = 16*1024;
|
||||
uint8_t pdu_pcap_tmp[max_pdu_len];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -28,8 +28,9 @@
|
|||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "srsapps/common/qbuff.h"
|
||||
#include "srsapps/common/log.h"
|
||||
#include "srsapps/ue/mac/mac_io.h"
|
||||
#include "srsapps/common/mac_interface.h"
|
||||
#include "srsapps/ue/mac/mac_params.h"
|
||||
#include "srsapps/ue/mac/pdu.h"
|
||||
#include "srsapps/ue/mac/proc_bsr.h"
|
||||
|
@ -47,17 +48,15 @@ class mux
|
|||
public:
|
||||
mux();
|
||||
void reset();
|
||||
void init(log *log_h, mac_io *mac_io_h, bsr_proc *bsr_procedure);
|
||||
void init(rlc_interface_mac *rlc, log *log_h, bsr_proc *bsr_procedure);
|
||||
|
||||
bool is_pending_ccch_sdu();
|
||||
bool is_pending_any_sdu();
|
||||
bool is_pending_sdu(uint32_t lcid);
|
||||
|
||||
uint8_t* pdu_pop(uint32_t pdu_sz);
|
||||
bool pdu_move_to_msg3(uint32_t pdu_sz);
|
||||
void pdu_release();
|
||||
bool pdu_get(uint8_t *payload, uint32_t pdu_sz);
|
||||
|
||||
uint8_t* msg3_pop(uint32_t pdu_sz);
|
||||
bool msg3_get(uint8_t *payload, uint32_t pdu_sz);
|
||||
void msg3_flush();
|
||||
void msg3_transmitted();
|
||||
bool msg3_is_transmitted();
|
||||
|
@ -67,34 +66,33 @@ public:
|
|||
void set_priority(uint32_t lcid, uint32_t priority, int PBR_x_tti, uint32_t BSD);
|
||||
|
||||
private:
|
||||
bool assemble_pdu(uint32_t pdu_sz);
|
||||
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu);
|
||||
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, bool *is_first);
|
||||
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, uint32_t *sdu_sz, bool *is_first);
|
||||
bool pdu_move_to_msg3(uint32_t pdu_sz);
|
||||
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu);
|
||||
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, bool *is_first);
|
||||
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, int max_sdu_sz, uint32_t *sdu_sz, bool *is_first);
|
||||
|
||||
int64_t Bj[mac_io::NOF_UL_LCH];
|
||||
int PBR[mac_io::NOF_UL_LCH]; // -1 sets to infinity
|
||||
uint32_t BSD[mac_io::NOF_UL_LCH];
|
||||
uint32_t priority[mac_io::NOF_UL_LCH];
|
||||
uint32_t priority_sorted[mac_io::NOF_UL_LCH];
|
||||
uint32_t lchid_sorted[mac_io::NOF_UL_LCH];
|
||||
uint32_t nof_tx_pkts[mac_io::NOF_UL_LCH];
|
||||
const static int NOF_UL_LCH = 10;
|
||||
|
||||
int64_t Bj[NOF_UL_LCH];
|
||||
int PBR[NOF_UL_LCH]; // -1 sets to infinity
|
||||
uint32_t BSD[NOF_UL_LCH];
|
||||
uint32_t priority[NOF_UL_LCH];
|
||||
uint32_t priority_sorted[NOF_UL_LCH];
|
||||
uint32_t lchid_sorted[NOF_UL_LCH];
|
||||
|
||||
// Mutex for exclusive access
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
log *log_h;
|
||||
mac_io *mac_io_h;
|
||||
bsr_proc *bsr_procedure;
|
||||
uint16_t pending_crnti_ce;
|
||||
log *log_h;
|
||||
rlc_interface_mac *rlc;
|
||||
bsr_proc *bsr_procedure;
|
||||
uint16_t pending_crnti_ce;
|
||||
|
||||
/* Msg3 Buffer */
|
||||
static const uint32_t MSG3_BUFF_SZ = 128;
|
||||
qbuff msg3_buff;
|
||||
|
||||
/* PDU Buffer */
|
||||
static const uint32_t PDU_BUFF_SZ = 128*1024;
|
||||
qbuff pdu_buff;
|
||||
sch_pdu pdu_msg;
|
||||
bool msg3_has_been_transmitted;
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include "srsapps/common/log.h"
|
||||
#include "srsapps/common/mac_interface.h"
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -139,7 +140,7 @@ public:
|
|||
return pdu_is_ul;
|
||||
}
|
||||
|
||||
virtual bool write_packet(uint8_t *ptr) = 0;
|
||||
virtual bool write_packet(uint8_t *ptr, rlc_interface_mac *rlc) = 0;
|
||||
|
||||
protected:
|
||||
std::vector<SubH> subheaders;
|
||||
|
@ -156,11 +157,11 @@ class subh
|
|||
{
|
||||
public:
|
||||
|
||||
virtual bool read_subheader(uint8_t** ptr) = 0;
|
||||
virtual void read_payload(uint8_t **ptr) = 0;
|
||||
virtual void write_subheader(uint8_t** ptr, bool is_last) = 0;
|
||||
virtual void write_payload(uint8_t **ptr) = 0;
|
||||
virtual void fprint(FILE *stream) = 0;
|
||||
virtual bool read_subheader(uint8_t** ptr) = 0;
|
||||
virtual void read_payload(uint8_t **ptr) = 0;
|
||||
virtual void write_subheader(uint8_t** ptr, bool is_last) = 0;
|
||||
virtual void write_payload(uint8_t **ptr, rlc_interface_mac *rlc) = 0;
|
||||
virtual void fprint(FILE *stream) = 0;
|
||||
|
||||
pdu<SubH>* parent;
|
||||
|
||||
|
@ -207,9 +208,9 @@ public:
|
|||
|
||||
// Writing functions
|
||||
void write_subheader(uint8_t** ptr, bool is_last);
|
||||
void write_payload(uint8_t **ptr);
|
||||
bool set_sdu(uint32_t lcid, uint8_t *ptr, uint32_t nof_bytes);
|
||||
bool set_sdu(uint32_t lcid, uint8_t *ptr, uint32_t nof_bytes, bool is_first);
|
||||
void write_payload(uint8_t **ptr, rlc_interface_mac *rlc);
|
||||
bool set_sdu(uint32_t lcid, uint32_t nof_bytes);
|
||||
bool set_sdu(uint32_t lcid, uint32_t nof_bytes, bool is_first);
|
||||
bool set_c_rnti(uint16_t crnti);
|
||||
bool set_bsr(uint32_t buff_size[4], sch_subh::cetype format, bool update_size);
|
||||
bool set_con_res_id(uint64_t con_res_id);
|
||||
|
@ -225,9 +226,9 @@ private:
|
|||
static const int MAX_CE_PAYLOAD_LEN = 8;
|
||||
uint32_t lcid;
|
||||
uint32_t nof_bytes;
|
||||
uint8_t* sdu_payload_ptr;
|
||||
uint8_t* payload;
|
||||
uint8_t w_payload_ce[8];
|
||||
bool F_bit;
|
||||
uint8_t ce_payload[MAX_CE_PAYLOAD_LEN*8];
|
||||
uint32_t sizeof_ce(uint32_t lcid, bool is_ul);
|
||||
uint8_t buff_size_table(uint32_t buffer_size);
|
||||
};
|
||||
|
@ -239,7 +240,7 @@ public:
|
|||
sch_pdu(uint32_t max_rars) : pdu(max_rars) {}
|
||||
|
||||
void parse_packet(uint8_t *ptr);
|
||||
bool write_packet(uint8_t *ptr);
|
||||
bool write_packet(uint8_t *ptr, rlc_interface_mac *rlc);
|
||||
bool has_space_ce(uint32_t nbytes);
|
||||
bool has_space_sdu(uint32_t nbytes);
|
||||
bool has_space_sdu(uint32_t nbytes, bool is_first);
|
||||
|
@ -249,7 +250,7 @@ public:
|
|||
bool update_space_ce(uint32_t nbytes);
|
||||
bool update_space_sdu(uint32_t nbytes);
|
||||
bool update_space_sdu(uint32_t nbytes, bool is_first);
|
||||
void fprint(FILE *stream);
|
||||
void fprint(FILE *stream);
|
||||
|
||||
};
|
||||
|
||||
|
@ -269,7 +270,7 @@ public:
|
|||
|
||||
// Writing functoins
|
||||
void write_subheader(uint8_t** ptr, bool is_last);
|
||||
void write_payload(uint8_t** ptr);
|
||||
void write_payload(uint8_t** ptr, rlc_interface_mac *rlc);
|
||||
void set_rapid(uint32_t rapid);
|
||||
void set_ta_cmd(uint32_t ta);
|
||||
void set_temp_crnti(uint16_t temp_rnti);
|
||||
|
@ -295,7 +296,7 @@ public:
|
|||
bool has_backoff();
|
||||
uint8_t get_backoff();
|
||||
|
||||
bool write_packet(uint8_t* ptr);
|
||||
bool write_packet(uint8_t* ptr, rlc_interface_mac *rlc);
|
||||
void fprint(FILE *stream);
|
||||
|
||||
private:
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
|
||||
#include "srsapps/common/log.h"
|
||||
#include "srsapps/ue/mac/proc.h"
|
||||
#include "srsapps/common/mac_interface.h"
|
||||
#include "srsapps/ue/mac/mac_params.h"
|
||||
#include "srsapps/ue/mac/mac_io.h"
|
||||
#include "srsapps/common/timers.h"
|
||||
|
||||
#ifndef PROCBSR_H
|
||||
|
@ -47,7 +47,7 @@ class bsr_proc : public proc, timer_callback
|
|||
{
|
||||
public:
|
||||
bsr_proc();
|
||||
void init(log *log_h, timers *timers_db, mac_params *params_db, mac_io *mac_io_h);
|
||||
void init(rlc_interface_mac *rlc, log *log_h, mac_params *params_db, timers *timers_db);
|
||||
void step(uint32_t tti);
|
||||
void reset();
|
||||
void setup_lcg(uint32_t lcid, uint32_t new_lcg);
|
||||
|
@ -74,9 +74,9 @@ private:
|
|||
|
||||
bool reset_sr;
|
||||
mac_params *params_db;
|
||||
mac_io *mac_io_h;
|
||||
timers *timers_db;
|
||||
log *log_h;
|
||||
rlc_interface_mac *rlc;
|
||||
bool initiated;
|
||||
const static int MAX_LCID = 20;
|
||||
int lcg[MAX_LCID];
|
||||
|
|
|
@ -52,8 +52,7 @@ class ra_proc : public proc,timer_callback
|
|||
{
|
||||
public:
|
||||
ra_proc() : rar_pdu_msg(20) {pcap = NULL;};
|
||||
bool init(mac_params *params_db, phy *phy_h, log *log_h, timers *timers_db,
|
||||
mux *mux_unit, demux *demux_unit);
|
||||
bool init(phy_interface *phy_h, log *log_h, mac_params *params_db, timers *timers_db, mux *mux_unit, demux *demux_unit);
|
||||
void reset();
|
||||
void start_pdcch_order();
|
||||
void start_rlc_order();
|
||||
|
@ -67,15 +66,18 @@ class ra_proc : public proc,timer_callback
|
|||
void pdcch_to_crnti(bool is_ul_grant);
|
||||
void timer_expired(uint32_t timer_id);
|
||||
|
||||
void new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action);
|
||||
void tb_decoded_ok();
|
||||
|
||||
void* run_prach_thread();
|
||||
void start_pcap(mac_pcap* pcap);
|
||||
private:
|
||||
|
||||
void process_timeadv_cmd(uint32_t ta_cmd);
|
||||
void step_initialization();
|
||||
void step_initialization_wait();
|
||||
void step_resource_selection();
|
||||
void step_preamble_transmission();
|
||||
void step_pdcch_setup();
|
||||
void step_response_reception();
|
||||
void step_response_error();
|
||||
void step_backoff_wait();
|
||||
|
@ -107,7 +109,6 @@ private:
|
|||
int preambleIndex;
|
||||
|
||||
// Internal variables
|
||||
uint32_t tti;
|
||||
uint32_t preambleTransmissionCounter;
|
||||
uint32_t backoff_param_ms;
|
||||
uint32_t sel_maskIndex;
|
||||
|
@ -116,14 +117,15 @@ private:
|
|||
uint32_t backoff_inteval;
|
||||
int received_target_power_dbm;
|
||||
uint32_t ra_rnti;
|
||||
uint8_t payload[256]; // 56 bits is often enough
|
||||
|
||||
srslte_softbuffer_rx_t softbuffer_rar;
|
||||
|
||||
enum {
|
||||
IDLE = 0,
|
||||
INITIALIZATION, // Section 5.1.1
|
||||
INITIALIZATION_WAIT,
|
||||
RESOURCE_SELECTION, // Section 5.1.2
|
||||
PREAMBLE_TRANSMISSION, // Section 5.1.3
|
||||
PDCCH_SETUP,
|
||||
RESPONSE_RECEPTION, // Section 5.1.4
|
||||
RESPONSE_ERROR,
|
||||
BACKOFF_WAIT,
|
||||
|
@ -139,21 +141,17 @@ private:
|
|||
bool first_rar_received;
|
||||
void read_params();
|
||||
|
||||
phy *phy_h;
|
||||
log *log_h;
|
||||
mac_params *params_db;
|
||||
timers *timers_db;
|
||||
mux *mux_unit;
|
||||
demux *demux_unit;
|
||||
mac_pcap *pcap;
|
||||
|
||||
pthread_t pt_init_prach;
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t mutex;
|
||||
bool start_prach_init;
|
||||
|
||||
phy_interface *phy_h;
|
||||
log *log_h;
|
||||
mac_params *params_db;
|
||||
timers *timers_db;
|
||||
mux *mux_unit;
|
||||
demux *demux_unit;
|
||||
mac_pcap *pcap;
|
||||
|
||||
uint64_t transmitted_contention_id;
|
||||
uint16_t transmitted_crnti;
|
||||
|
||||
enum {
|
||||
PDCCH_CRNTI_NOT_RECEIVED = 0,
|
||||
PDCCH_CRNTI_UL_GRANT,
|
||||
|
@ -165,6 +163,8 @@ private:
|
|||
RLC_ORDER,
|
||||
MAC_ORDER
|
||||
} start_mode;
|
||||
uint32_t rar_grant_nbytes;
|
||||
uint32_t rar_grant_tti;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,20 +45,22 @@ class sr_proc : public proc
|
|||
{
|
||||
public:
|
||||
sr_proc();
|
||||
void init(log *log_h, mac_params *params_db, phy *phy_h);
|
||||
void init(phy_interface *phy_h, log *log_h, mac_params *params_db);
|
||||
void step(uint32_t tti);
|
||||
void reset();
|
||||
void start();
|
||||
bool need_random_access();
|
||||
|
||||
private:
|
||||
uint32_t sr_counter;
|
||||
uint32_t dsr_transmax;
|
||||
bool is_pending_sr;
|
||||
mac_params *params_db;
|
||||
phy *phy_h;
|
||||
log *log_h;
|
||||
bool initiated;
|
||||
bool do_ra;
|
||||
uint32_t sr_counter;
|
||||
uint32_t dsr_transmax;
|
||||
bool is_pending_sr;
|
||||
mac_params *params_db;
|
||||
|
||||
phy_interface *phy_h;
|
||||
log *log_h;
|
||||
bool initiated;
|
||||
bool do_ra;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,13 +25,11 @@
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include "srsapps/ue/phy/phy.h"
|
||||
#include "srsapps/common/mac_interface.h"
|
||||
#include "srsapps/common/log.h"
|
||||
#include "srsapps/ue/mac/mac_params.h"
|
||||
#include "srsapps/ue/mac/mux.h"
|
||||
#include "srsapps/ue/mac/ul_sps.h"
|
||||
#include "srsapps/ue/mac/mac_pcap.h"
|
||||
#include "srsapps/common/timers.h"
|
||||
|
||||
|
@ -43,8 +41,6 @@
|
|||
namespace srslte {
|
||||
namespace ue {
|
||||
|
||||
typedef _Complex float cf_t;
|
||||
|
||||
class ul_harq_entity
|
||||
{
|
||||
public:
|
||||
|
@ -52,56 +48,73 @@ public:
|
|||
const static uint32_t NOF_HARQ_PROC = 8;
|
||||
static uint32_t pidof(uint32_t tti);
|
||||
|
||||
ul_harq_entity() { pcap = NULL; }
|
||||
bool init(srslte_cell_t cell, mac_params *params_db, log *log_h, timers* timers_, mux *mux_unit);
|
||||
|
||||
ul_harq_entity() { pcap = NULL; }
|
||||
bool init(log *log_h, mac_params *params_db, timers* timers_, mux *mux_unit);
|
||||
void reset();
|
||||
void reset_ndi();
|
||||
bool is_sps(uint32_t pid);
|
||||
void run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_);
|
||||
void run_tti(uint32_t tti, phy *phy_);
|
||||
|
||||
void start_pcap(mac_pcap* pcap);
|
||||
|
||||
|
||||
/***************** PHY->MAC interface for UL processes **************************/
|
||||
void new_grant_ul(mac_interface_phy::mac_grant_t grant, uint8_t *payload_ptr,
|
||||
mac_interface_phy::tb_action_ul_t *action);
|
||||
void new_grant_ul_ack(mac_interface_phy::mac_grant_t grant, uint8_t *payload_ptr, bool ack,
|
||||
mac_interface_phy::tb_action_ul_t *action);
|
||||
void harq_recv(uint32_t tti, bool ack, mac_interface_phy::tb_action_ul_t *action);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
class ul_harq_process {
|
||||
public:
|
||||
ul_harq_process();
|
||||
bool init(srslte_cell_t cell, ul_harq_entity *parent);
|
||||
bool init(uint32_t pid, ul_harq_entity *parent);
|
||||
void reset();
|
||||
void reset_ndi();
|
||||
|
||||
void generate_retx(uint32_t tti_tx, ul_buffer *ul);
|
||||
void generate_retx(uint32_t tti_tx, ul_sched_grant *ul_grant, ul_buffer *ul);
|
||||
void generate_new_tx(uint32_t tti_tx, uint8_t *payload, bool is_msg3, ul_sched_grant* grant, ul_buffer *ul);
|
||||
|
||||
|
||||
void generate_retx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action);
|
||||
void generate_retx(uint32_t tti_tx, mac_interface_phy::mac_grant_t *grant,
|
||||
mac_interface_phy::tb_action_ul_t *action);
|
||||
void generate_new_tx(uint32_t tti_tx, bool is_msg3, mac_interface_phy::mac_grant_t *grant,
|
||||
mac_interface_phy::tb_action_ul_t *action);
|
||||
|
||||
uint32_t get_rv();
|
||||
bool has_grant();
|
||||
ul_sched_grant *get_grant();
|
||||
|
||||
void set_harq_feedback(bool ack);
|
||||
bool get_ndi();
|
||||
bool is_sps();
|
||||
uint32_t last_tx_tti();
|
||||
uint32_t pid;
|
||||
uint32_t get_nof_retx();
|
||||
|
||||
private:
|
||||
mac_interface_phy::mac_grant_t cur_grant;
|
||||
|
||||
uint32_t pid;
|
||||
uint32_t current_tx_nb;
|
||||
uint32_t current_irv;
|
||||
bool harq_feedback;
|
||||
bool ndi;
|
||||
log *log_h;
|
||||
ul_harq_entity *harq_entity;
|
||||
ul_sched_grant cur_grant;
|
||||
bool is_grant_configured;
|
||||
srslte_softbuffer_tx_t softbuffer;
|
||||
bool is_msg3;
|
||||
bool is_initiated;
|
||||
uint32_t tti_last_tx;
|
||||
bool is_initiated;
|
||||
uint32_t tti_last_tx;
|
||||
|
||||
void generate_tx(uint32_t tti_tx, uint8_t *pdu_payload, ul_buffer* ul);
|
||||
void generate_tx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action);
|
||||
};
|
||||
|
||||
uint8_t mac_pdu_buffer[NOF_HARQ_PROC][64*1024];
|
||||
|
||||
|
||||
void run_tti(uint32_t tti, mac_interface_phy::mac_grant_t *grant, uint8_t* payload_ptr,
|
||||
mac_interface_phy::tb_action_ul_t* action);
|
||||
void set_ack(uint32_t tti, bool ack);
|
||||
|
||||
ul_sps ul_sps_assig;
|
||||
|
||||
timers *timers_db;
|
||||
mux *mux_unit;
|
||||
ul_harq_process proc[NOF_HARQ_PROC];
|
||||
|
|
|
@ -48,8 +48,8 @@ class ul_sps
|
|||
public:
|
||||
|
||||
void clear() {}
|
||||
void reset(uint32_t tti, sched_grant *grant) {}
|
||||
ul_sched_grant *get_pending_grant(uint32_t tti) { return NULL; }
|
||||
void reset(uint32_t tti) {}
|
||||
bool get_pending_grant(uint32_t tti, mac_interface_phy::mac_grant_t *grant) { return false; }
|
||||
private:
|
||||
|
||||
};
|
||||
|
|
|
@ -30,32 +30,30 @@
|
|||
#include "srsapps/ue/mac/demux.h"
|
||||
|
||||
namespace srslte {
|
||||
namespace ue {
|
||||
namespace ue {
|
||||
|
||||
demux::demux() : mac_msg(20),pending_mac_msg(20)
|
||||
demux::demux() : mac_msg(20), pending_mac_msg(20)
|
||||
{
|
||||
contention_resolution_id = 0;
|
||||
pending_temp_rnti = false;
|
||||
has_pending_contention_resolution_id = false;
|
||||
sdu_handler_ = NULL;
|
||||
|
||||
for (int i=0;i<NOF_PDU_Q;i++) {
|
||||
pdu_q[i].init(8, MAX_PDU_LEN);
|
||||
used_q[i] = false;
|
||||
}
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
pthread_cond_init(&cvar, NULL);
|
||||
|
||||
}
|
||||
|
||||
void demux::init(phy* phy_h_, log* log_h_, mac_io* mac_io_h_, timers* timers_db_)
|
||||
void demux::init(phy_interface* phy_h_, rlc_interface_mac *rlc_, log* log_h_, timers* timers_db_)
|
||||
{
|
||||
phy_h = phy_h_;
|
||||
log_h = log_h_;
|
||||
mac_io_h = mac_io_h_;
|
||||
rlc = rlc_;
|
||||
timers_db = timers_db_;
|
||||
}
|
||||
|
||||
void demux::add_sdu_handler(sdu_handler* handler)
|
||||
{
|
||||
sdu_handler_ = handler;
|
||||
}
|
||||
|
||||
bool demux::is_temp_crnti_pending()
|
||||
{
|
||||
return pending_temp_rnti;
|
||||
|
@ -73,28 +71,95 @@ uint64_t demux::get_contention_resolution_id()
|
|||
return x;
|
||||
}
|
||||
|
||||
bool demux::find_unused_queue(uint8_t *idx) {
|
||||
for (uint8_t i=0;i<NOF_PDU_Q;i++) {
|
||||
if (!used_q[i]) {
|
||||
if (idx) {
|
||||
*idx = i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read packets from queues in round robin
|
||||
bool demux::find_nonempty_queue(uint8_t *idx) {
|
||||
for (uint8_t i=0;i<NOF_PDU_Q;i++) {
|
||||
if (!pdu_q[(i+*idx)%NOF_PDU_Q].isempty()) {
|
||||
if (idx) {
|
||||
*idx = i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* demux::request_buffer(uint32_t len)
|
||||
{
|
||||
if (len >= MAX_PDU_LEN - sizeof(buff_header_t)) {
|
||||
return NULL;
|
||||
}
|
||||
pthread_mutex_lock(&mutex);
|
||||
uint8_t idx;
|
||||
while(find_unused_queue(&idx)) {
|
||||
pthread_cond_wait(&cvar, &mutex);
|
||||
}
|
||||
if (idx > 0) {
|
||||
Debug("Using queue %d for MAC PDU\n");
|
||||
}
|
||||
used_q[idx] = true;
|
||||
uint8_t *buff = (uint8_t*) pdu_q[idx].request();
|
||||
buff_header_t *head = (buff_header_t*) buff;
|
||||
head->idx = idx;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
return &buff[sizeof(buff_header_t)];
|
||||
}
|
||||
|
||||
void demux::push_buffer(uint8_t *buff, uint32_t nof_bytes) {
|
||||
buff_header_t *head = (buff_header_t*) (buff-sizeof(buff_header_t));
|
||||
if (head->idx < NOF_PDU_Q) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
if (nof_bytes > 0) {
|
||||
if (!pdu_q[head->idx].push(nof_bytes)) {
|
||||
Warning("Full queue %d when pushing MAC PDU %d bytes\n", head->idx, nof_bytes);
|
||||
}
|
||||
}
|
||||
used_q[head->idx] = false;
|
||||
pthread_cond_signal(&cvar);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through
|
||||
* the MAC in transparent mode
|
||||
* the MAC in transparent mode.
|
||||
* Warning: this function sends the message to RLC now, since SI blocks do not
|
||||
* require ACK feedback to be transmitted quickly.
|
||||
*/
|
||||
void demux::push_pdu_bcch(uint8_t *mac_pdu, uint32_t nof_bits)
|
||||
void demux::release_pdu_bcch(uint8_t *buff, uint32_t nof_bytes)
|
||||
{
|
||||
mac_io_h->get(mac_io::MAC_LCH_BCCH_DL)->send(mac_pdu, nof_bits);
|
||||
Debug("Pushed BCCH MAC PDU in transparent mode\n");
|
||||
rlc->write_pdu_bcch_dlsch(buff, nof_bytes);
|
||||
push_buffer(buff, 0);
|
||||
}
|
||||
|
||||
/* Demultiplexing of MAC PDU associated with a Temporal C-RNTI. The PDU will
|
||||
* remain in buffer until demultiplex_pending_pdu() is called.
|
||||
* This features is provided to enable the Random Access Procedure to decide
|
||||
* wether the PDU shall pass to upper layers or not, which depends on the
|
||||
* Contention Resolution result
|
||||
* Contention Resolution result.
|
||||
*
|
||||
* Warning: this function does some processing here assuming ACK deadline is not an
|
||||
* issue here because Temp C-RNTI messages have small payloads
|
||||
*/
|
||||
void demux::push_pdu_temp_crnti(uint8_t *mac_pdu, uint32_t nof_bits)
|
||||
void demux::release_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes)
|
||||
{
|
||||
if (!pending_temp_rnti) {
|
||||
// Unpack DLSCH MAC PDU
|
||||
pending_mac_msg.init(nof_bits/8);
|
||||
pending_mac_msg.parse_packet(mac_pdu);
|
||||
pending_mac_msg.init(nof_bytes);
|
||||
pending_mac_msg.parse_packet(buff);
|
||||
//pending_mac_msg.fprint(stdout);
|
||||
|
||||
// Look for Contention Resolution UE ID
|
||||
|
@ -108,25 +173,43 @@ void demux::push_pdu_temp_crnti(uint8_t *mac_pdu, uint32_t nof_bits)
|
|||
pending_mac_msg.reset();
|
||||
pending_temp_rnti = true;
|
||||
Debug("Saved MAC PDU with Temporal C-RNTI in buffer\n");
|
||||
push_buffer(buff, 0);
|
||||
} else {
|
||||
Warning("Error pushing PDU with Temporal C-RNTI: Another PDU is still in pending\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Demultiplexing of logical channels and dissassemble of MAC CE */
|
||||
void demux::push_pdu(uint8_t *mac_pdu, uint32_t nof_bits)
|
||||
/* Demultiplexing of logical channels and dissassemble of MAC CE
|
||||
* This function enqueues the packet and returns quicly because ACK
|
||||
* deadline is important here.
|
||||
*/
|
||||
void demux::release_pdu(uint8_t *buff, uint32_t nof_bytes)
|
||||
{
|
||||
pthread_mutex_lock(&mutex);
|
||||
push_buffer(buff, nof_bytes);
|
||||
}
|
||||
|
||||
void demux::process_pdus()
|
||||
{
|
||||
uint32_t len;
|
||||
uint8_t idx;
|
||||
while(find_nonempty_queue(&idx)) {
|
||||
uint8_t *mac_pdu = (uint8_t*) pdu_q[idx].pop(&len);
|
||||
if (mac_pdu) {
|
||||
process_pdu(mac_pdu, len);
|
||||
pdu_q[idx].release();
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
void demux::process_pdu(uint8_t *mac_pdu, uint32_t nof_bytes)
|
||||
{
|
||||
// Unpack DLSCH MAC PDU
|
||||
mac_msg.init(nof_bits/8);
|
||||
mac_msg.init(nof_bytes);
|
||||
mac_msg.parse_packet(mac_pdu);
|
||||
//mac_msg.fprint(stdout);
|
||||
process_pdu(&mac_msg);
|
||||
mac_msg.fprint(stdout);
|
||||
process_sch_pdu(&mac_msg);
|
||||
Debug("Normal MAC PDU processed\n");
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
}
|
||||
|
||||
void demux::discard_pending_pdu()
|
||||
|
@ -138,40 +221,21 @@ void demux::discard_pending_pdu()
|
|||
void demux::demultiplex_pending_pdu()
|
||||
{
|
||||
if (pending_temp_rnti) {
|
||||
process_pdu(&pending_mac_msg);
|
||||
process_sch_pdu(&pending_mac_msg);
|
||||
discard_pending_pdu();
|
||||
} else {
|
||||
Error("Error demultiplex pending PDU: No pending PDU\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void demux::process_pdu(sch_pdu *pdu_msg)
|
||||
void demux::process_sch_pdu(sch_pdu *pdu_msg)
|
||||
{
|
||||
while(pdu_msg->next()) {
|
||||
if (pdu_msg->get()->is_sdu()) {
|
||||
// Route logical channel
|
||||
if (pdu_msg->get()->get_sdu_lcid() <= mac_io::MAC_LCH_DTCH2_DL) {
|
||||
qbuff *dest_lch = mac_io_h->get(pdu_msg->get()->get_sdu_lcid());
|
||||
if (dest_lch) {
|
||||
dest_lch->send(pdu_msg->get()->get_sdu_ptr(), pdu_msg->get()->get_sdu_nbytes()*8);
|
||||
Debug("Sent MAC SDU len=%d bytes to lchid=%d\n",
|
||||
pdu_msg->get()->get_sdu_nbytes(), pdu_msg->get()->get_sdu_lcid());
|
||||
if (sdu_handler_) {
|
||||
sdu_handler_->notify_new_sdu(pdu_msg->get()->get_sdu_lcid());
|
||||
Debug("Notified SDU handler len=%d bytes to lchid=%d\n",
|
||||
pdu_msg->get()->get_sdu_nbytes(), pdu_msg->get()->get_sdu_lcid());
|
||||
}
|
||||
|
||||
} else {
|
||||
Error("Getting destination channel LCID=%d\n", pdu_msg->get()->get_sdu_lcid());
|
||||
}
|
||||
} else {
|
||||
Warning("Received SDU for unsupported LCID=%d\n", pdu_msg->get()->get_sdu_lcid());
|
||||
}
|
||||
// Process MAC Control Element
|
||||
rlc->write_pdu(pdu_msg->get()->get_sdu_lcid(), pdu_msg->get()->get_sdu_ptr(), pdu_msg->get()->get_sdu_nbytes());
|
||||
} else {
|
||||
// Process MAC Control Element
|
||||
if (!process_ce(pdu_msg->get())) {
|
||||
Warning("Received Subheader with invalid or unkonwn LCID\n");
|
||||
}
|
||||
|
@ -179,7 +243,6 @@ void demux::process_pdu(sch_pdu *pdu_msg)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool demux::process_ce(sch_subh *subh) {
|
||||
switch(subh->ce_type()) {
|
||||
case sch_subh::CON_RES_ID:
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
*/
|
||||
|
||||
#include "srsapps/ue/phy/phy.h"
|
||||
#include "srsapps/ue/phy/dl_sched_grant.h"
|
||||
|
||||
#include "srsapps/ue/mac/mac.h"
|
||||
#include "srsapps/ue/mac/dl_harq.h"
|
||||
|
@ -43,19 +42,15 @@ namespace srslte {
|
|||
|
||||
dl_harq_entity::dl_harq_entity()
|
||||
{
|
||||
for (uint32_t i=0;i<NOF_HARQ_PROC+1;i++) {
|
||||
proc[i].pid = i;
|
||||
}
|
||||
pending_ack_pid = -1;
|
||||
pcap = NULL;
|
||||
}
|
||||
bool dl_harq_entity::init(srslte_cell_t cell, uint32_t max_payload_len, log* log_h_, timers* timers_, demux *demux_unit_)
|
||||
bool dl_harq_entity::init(log* log_h_, timers* timers_, demux *demux_unit_)
|
||||
{
|
||||
timers_db = timers_;
|
||||
demux_unit = demux_unit_;
|
||||
log_h = log_h_;
|
||||
for (uint32_t i=0;i<NOF_HARQ_PROC+1;i++) {
|
||||
if (!proc[i].init(cell, max_payload_len, this)) {
|
||||
if (!proc[i].init(i, this)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -68,189 +63,240 @@ void dl_harq_entity::start_pcap(mac_pcap* pcap_)
|
|||
pcap = pcap_;
|
||||
}
|
||||
|
||||
bool dl_harq_entity::is_sps(uint32_t pid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
void dl_harq_entity::set_harq_info(uint32_t pid, dl_sched_grant* grant)
|
||||
{
|
||||
proc[pid%(NOF_HARQ_PROC+1)].set_harq_info(grant);
|
||||
}
|
||||
|
||||
void dl_harq_entity::receive_data(uint32_t tti, uint32_t pid, dl_buffer* dl_buffer, phy* phy_h)
|
||||
{
|
||||
proc[pid%(NOF_HARQ_PROC+1)].receive_data(tti, dl_buffer, phy_h);
|
||||
}
|
||||
|
||||
void dl_harq_entity::reset()
|
||||
{
|
||||
for (uint32_t i=0;i<NOF_HARQ_PROC+1;i++) {
|
||||
proc[i].reset();
|
||||
}
|
||||
dl_sps_assig.clear();
|
||||
}
|
||||
|
||||
bool dl_harq_entity::is_ack_pending_resolution()
|
||||
{
|
||||
return pending_ack_pid >= 0;
|
||||
uint32_t dl_harq_entity::get_harq_sps_pid(uint32_t tti) {
|
||||
/*
|
||||
uint32_t nof_proc = ((uint32_t) params_db->get_param(mac_interface_params::SPS_DL_NOF_PROC));
|
||||
return tti/params_db.get_param(mac_interface_params::SPS_DL_SCHED_INTERVAL)%nof_proc;
|
||||
*/
|
||||
}
|
||||
|
||||
void dl_harq_entity::send_pending_ack_contention_resolution()
|
||||
void dl_harq_entity::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action)
|
||||
{
|
||||
if (is_ack_pending_resolution()) {
|
||||
proc[pending_ack_pid].send_pending_ack_contention_resolution();
|
||||
pending_ack_pid = -1;
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dl_harq_entity::tb_decoded_ok(uint32_t harq_pid)
|
||||
{
|
||||
proc[harq_pid%NOF_HARQ_PROC].tb_decoded_ok();
|
||||
}
|
||||
|
||||
bool dl_harq_entity::generate_ack_callback(void *arg)
|
||||
{
|
||||
demux *demux_unit = (demux*) arg;
|
||||
return demux_unit->is_contention_resolution_id_pending();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************
|
||||
*
|
||||
* HARQ PROCESS
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
dl_harq_entity::dl_harq_process::dl_harq_process() : cur_grant(0),pending_ack_grant(0) {
|
||||
dl_harq_entity::dl_harq_process::dl_harq_process() {
|
||||
is_initiated = false;
|
||||
ack = false;
|
||||
bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant));
|
||||
payload = NULL;
|
||||
max_payload_len = 0;
|
||||
bzero(&cur_grant, sizeof(mac_interface_phy::mac_grant_t));
|
||||
}
|
||||
|
||||
void dl_harq_entity::dl_harq_process::reset() {
|
||||
ack = false;
|
||||
bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant));
|
||||
payload_buffer_ptr = NULL;
|
||||
bzero(&cur_grant, sizeof(mac_interface_phy::mac_grant_t));
|
||||
if (is_initiated) {
|
||||
srslte_softbuffer_rx_reset(&softbuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void dl_harq_entity::dl_harq_process::send_pending_ack_contention_resolution()
|
||||
{
|
||||
if (pending_ul_buffer) {
|
||||
pending_ul_buffer->generate_ack(pending_ack, &pending_ack_grant);
|
||||
}
|
||||
bool dl_harq_entity::dl_harq_process::init(uint32_t pid_, dl_harq_entity *parent) {
|
||||
if (srslte_softbuffer_rx_init(&softbuffer, 100)) {
|
||||
Error("Error initiating soft buffer\n");
|
||||
return false;
|
||||
} else {
|
||||
pid = pid_;
|
||||
is_initiated = true;
|
||||
harq_entity = parent;
|
||||
log_h = harq_entity->log_h;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void dl_harq_entity::dl_harq_process::receive_data(uint32_t tti, srslte::ue::dl_buffer *dl_buffer, phy *phy_h)
|
||||
bool dl_harq_entity::dl_harq_process::is_sps()
|
||||
{
|
||||
pending_ul_buffer = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dl_harq_entity::dl_harq_process::is_new_transmission(mac_interface_phy::mac_grant_t grant) {
|
||||
bool is_new_transmission;
|
||||
|
||||
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 is_new_tb = true;
|
||||
if (srslte_tti_interval(new_grant->get_tti(), cur_grant.get_tti()) <= 8 &&
|
||||
new_grant->get_tbs() == cur_grant.get_tbs())
|
||||
{
|
||||
if (srslte_tti_interval(grant.tti, cur_grant.tti) <= 8 && grant.n_bytes == cur_grant.n_bytes) {
|
||||
is_new_tb = false;
|
||||
}
|
||||
|
||||
if ((new_grant->get_ndi() != cur_grant.get_ndi() && !is_new_tb) || // NDI toggled for same TB
|
||||
is_new_tb || // is new TB
|
||||
(pid == HARQ_BCCH_PID && new_grant->get_rv() == 0)) // Broadcast PID and 1st TX (RV=0)
|
||||
if ((grant.ndi != cur_grant.ndi && !is_new_tb) || // NDI toggled for same TB
|
||||
is_new_tb || // is new TB
|
||||
(pid == HARQ_BCCH_PID && grant.rv == 0)) // Broadcast PID and 1st TX (RV=0)
|
||||
{
|
||||
is_new_transmission = true;
|
||||
Debug("Set HARQ Info for new transmission\n");
|
||||
} else {
|
||||
if (!is_new_tb) {
|
||||
Info("old_tbs=%d, new_tbs=%d, old_tti=%d new_tti=%d\n", cur_grant.get_tbs(), new_grant->get_tbs(),
|
||||
cur_grant.get_tti(), new_grant->get_tti());
|
||||
Info("old_tbs=%d, new_tbs=%d, old_tti=%d new_tti=%d\n", cur_grant.n_bytes, grant.n_bytes, cur_grant.tti, grant.tti);
|
||||
}
|
||||
is_new_transmission = false;
|
||||
Debug("Set HARQ Info for retransmission\n");
|
||||
}
|
||||
|
||||
Info("DL PID %d: %s RV=%d, NDI=%d, LastNDI=%d, DCI %s\n", pid, is_new_transmission?"new TX":"reTX", new_grant->get_rv(),
|
||||
new_grant->get_ndi(), cur_grant.get_ndi(), new_grant->get_dciformat_string());
|
||||
Info("DL PID %d: %s RV=%d, NDI=%d, LastNDI=%d\n", pid, is_new_transmission?"new TX":"reTX", grant.rv,
|
||||
grant.ndi, cur_grant.ndi);
|
||||
|
||||
if (is_new_transmission) {
|
||||
return is_new_transmission;
|
||||
}
|
||||
|
||||
void dl_harq_entity::dl_harq_process::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action)
|
||||
{
|
||||
|
||||
if (is_new_transmission(grant)) {
|
||||
ack = false;
|
||||
srslte_softbuffer_rx_reset(&softbuffer);
|
||||
}
|
||||
if (new_grant->get_tbs() <= max_payload_len) {
|
||||
memcpy(&cur_grant, new_grant, sizeof(srslte::ue::dl_sched_grant));
|
||||
|
||||
// Save grant
|
||||
memcpy(&cur_grant, &grant, sizeof(mac_interface_phy::mac_grant_t));
|
||||
action->default_ack = ack;
|
||||
action->generate_ack = true;
|
||||
|
||||
// If data has not yet been successfully decoded
|
||||
if (ack == false) {
|
||||
|
||||
// Instruct the PHY To combine the received data and attempt to decode it
|
||||
action->decode_enabled = true;
|
||||
action->rv = cur_grant.rv;
|
||||
action->rnti = cur_grant.rnti;
|
||||
action->softbuffer = &softbuffer;
|
||||
payload_buffer_ptr = harq_entity->demux_unit->request_buffer(cur_grant.n_bytes);
|
||||
action->payload_ptr = payload_buffer_ptr;
|
||||
if (!action->payload_ptr) {
|
||||
action->decode_enabled = false;
|
||||
Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes);
|
||||
return;
|
||||
}
|
||||
memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(mac_interface_phy::mac_grant_t));
|
||||
|
||||
Info("DL PID %d: TBS=%d, RV=%d, crc=%s\n", pid, cur_grant.n_bytes, cur_grant.rv, ack?"OK":"NOK");
|
||||
|
||||
} else {
|
||||
Error("Error with DL grant. TBS (%d) exceeds payload buffer length (%d)\n", new_grant->get_tbs(), max_payload_len);
|
||||
Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK\n", pid);
|
||||
}
|
||||
|
||||
if (pid == HARQ_BCCH_PID || harq_entity->timers_db->get(mac::TIME_ALIGNMENT)->is_expired()) {
|
||||
// Do not generate ACK
|
||||
Debug("Not generating ACK\n");
|
||||
action->generate_ack = false;
|
||||
|
||||
if (pid == HARQ_BCCH_PID) {
|
||||
// Compute RV
|
||||
uint32_t k;
|
||||
if (grant.tti%10 == 5) { // This is SIB1, k is different
|
||||
k = (grant.tti/20)%4;
|
||||
} else {
|
||||
k = (grant.tti/10)%4;
|
||||
}
|
||||
action->rv = ((uint32_t) ceilf((float)1.5*k))%4;
|
||||
}
|
||||
} else {
|
||||
if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP) {
|
||||
// Postpone ACK after contention resolution is resolved
|
||||
action->generate_ack_callback = harq_entity->generate_ack_callback;
|
||||
action->generate_ack_callback_arg = harq_entity->demux_unit;
|
||||
Debug("ACK pending contention resolution\n");
|
||||
} else {
|
||||
Debug("Generating ACK\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dl_harq_entity::dl_harq_process::tb_decoded_ok()
|
||||
{
|
||||
ack = true;
|
||||
if (pid == HARQ_BCCH_PID) {
|
||||
if (harq_entity->pcap) {
|
||||
harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.n_bytes, ack, cur_grant.tti);
|
||||
}
|
||||
if (ack) {
|
||||
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.n_bytes);
|
||||
harq_entity->demux_unit->release_pdu_bcch(payload_buffer_ptr, cur_grant.n_bytes);
|
||||
}
|
||||
} else {
|
||||
if (harq_entity->pcap) {
|
||||
harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes, cur_grant.rnti, ack, cur_grant.tti);
|
||||
}
|
||||
if (ack) {
|
||||
if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP) {
|
||||
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n", cur_grant.n_bytes);
|
||||
harq_entity->demux_unit->release_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes);
|
||||
} else {
|
||||
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes);
|
||||
harq_entity->demux_unit->release_pdu(payload_buffer_ptr, cur_grant.n_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool dl_harq_entity::dl_harq_process::init(srslte_cell_t cell, uint32_t max_payload_len_, dl_harq_entity *parent) {
|
||||
max_payload_len = max_payload_len_;
|
||||
if (srslte_softbuffer_rx_init(&softbuffer, cell)) {
|
||||
Error("Error initiating soft buffer\n");
|
||||
return false;
|
||||
} else {
|
||||
is_initiated = true;
|
||||
harq_entity = parent;
|
||||
log_h = harq_entity->log_h;
|
||||
payload = (uint8_t*) srslte_vec_malloc(sizeof(uint8_t) * max_payload_len);
|
||||
return payload?true:false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -30,49 +30,43 @@
|
|||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "srsapps/common/threads.h"
|
||||
#include "srsapps/ue/phy/phy.h"
|
||||
#include "srsapps/common/log.h"
|
||||
#include "srsapps/ue/mac/mac.h"
|
||||
#include "srsapps/ue/mac/mac_params.h"
|
||||
#include "srsapps/ue/mac/pcap.h"
|
||||
|
||||
namespace srslte {
|
||||
namespace ue {
|
||||
|
||||
|
||||
mac::mac() : ttisync(10240), timers_db((uint32_t) NOF_MAC_TIMERS)
|
||||
{
|
||||
started = false;
|
||||
pcap = NULL;
|
||||
si_window_start = -1;
|
||||
si_window_length = -1;
|
||||
}
|
||||
|
||||
bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
|
||||
bool mac::init(phy_interface *phy, rlc_interface_mac *rlc, log *log_h_)
|
||||
{
|
||||
started = false;
|
||||
ttisync = ttisync_;
|
||||
phy_h = phy_h_;
|
||||
phy_h = phy;
|
||||
rlc_h = rlc;
|
||||
log_h = log_h_;
|
||||
tti = 0;
|
||||
is_synchronized = false;
|
||||
last_temporal_crnti = 0;
|
||||
phy_rnti = 0;
|
||||
is_first_tx = true;
|
||||
|
||||
bsr_procedure.init(log_h, &timers_db, ¶ms_db, &mac_io_lch);
|
||||
mux_unit.init(log_h, &mac_io_lch, &bsr_procedure);
|
||||
demux_unit.init(phy_h, log_h, &mac_io_lch, &timers_db);
|
||||
ra_procedure.init(¶ms_db, phy_h, log_h, &timers_db, &mux_unit, &demux_unit);
|
||||
sr_procedure.init(log_h, ¶ms_db, phy_h);
|
||||
is_first_of_burst = true;
|
||||
bsr_procedure.init( rlc_h, log_h, ¶ms_db, &timers_db);
|
||||
mux_unit.init ( rlc_h, log_h, &bsr_procedure);
|
||||
demux_unit.init (phy_h, rlc_h, log_h, &timers_db);
|
||||
ra_procedure.init (phy_h, log_h, ¶ms_db, &timers_db, &mux_unit, &demux_unit);
|
||||
sr_procedure.init (phy_h, log_h, ¶ms_db);
|
||||
ul_harq.init ( log_h, ¶ms_db, &timers_db, &mux_unit);
|
||||
dl_harq.init ( log_h, &timers_db, &demux_unit);
|
||||
|
||||
reset();
|
||||
|
||||
for (int i=0;i<NOF_TTI_THREADS;i++) {
|
||||
pthread_mutex_init(&tti_threads_sync_tx[i], NULL);
|
||||
tti_threads_sync[i].set_increment(NOF_TTI_THREADS);
|
||||
if (!tti_threads[i].init(this, &tti_threads_sync[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (threads_new_rt_prio(&mac_thread, mac_thread_fnc, this, 1)) {
|
||||
started = true;
|
||||
}
|
||||
start(MAC_THREAD_PRIO);
|
||||
|
||||
return started;
|
||||
}
|
||||
|
@ -80,20 +74,7 @@ bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
|
|||
void mac::stop()
|
||||
{
|
||||
started = false;
|
||||
pthread_join(mac_thread, NULL);
|
||||
for (int i=0;i<NOF_TTI_THREADS;i++) {
|
||||
tti_threads[i].stop();
|
||||
pthread_mutex_destroy(&tti_threads_sync_tx[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int mac::get_tti()
|
||||
{
|
||||
if (is_synchronized) {
|
||||
return (int) tti;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
wait_thread_finish();
|
||||
}
|
||||
|
||||
void mac::start_pcap(mac_pcap* pcap_)
|
||||
|
@ -104,60 +85,6 @@ void mac::start_pcap(mac_pcap* pcap_)
|
|||
ra_procedure.start_pcap(pcap);
|
||||
}
|
||||
|
||||
void mac::start_trace()
|
||||
{
|
||||
tr_enabled = true;
|
||||
}
|
||||
|
||||
void mac::write_trace(std::string filename)
|
||||
{
|
||||
tr_exec_total.writeToBinary(filename + ".total");
|
||||
tr_exec_dl.writeToBinary(filename + ".dl");
|
||||
tr_exec_ul.writeToBinary(filename + ".ul");
|
||||
}
|
||||
|
||||
void mac::tr_log_start(uint32_t tti)
|
||||
{
|
||||
if (tr_enabled) {
|
||||
gettimeofday(&tr_time_total[1], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void mac::tr_log_end(uint32_t tti)
|
||||
{
|
||||
if (tr_enabled) {
|
||||
/* compute total execution time */
|
||||
gettimeofday(&tr_time_total[2], NULL);
|
||||
get_time_interval(tr_time_total);
|
||||
tr_exec_total.push(tti, tr_time_total[0].tv_usec);
|
||||
|
||||
/* ul execution time is from the call to tr_log_ul */
|
||||
memcpy(&tr_time_ul[2], &tr_time_total[2], sizeof(struct timeval));
|
||||
get_time_interval(tr_time_ul);
|
||||
tr_exec_ul.push(tti, tr_time_ul[0].tv_usec);
|
||||
}
|
||||
}
|
||||
|
||||
void mac::tr_log_ul(uint32_t tti)
|
||||
{
|
||||
if (tr_enabled) {
|
||||
/* DL execution time is from the call to tr_log_dl to the call to tr_log_ul */
|
||||
gettimeofday(&tr_time_dl[2], NULL);
|
||||
get_time_interval(tr_time_dl);
|
||||
tr_exec_dl.push(tti, tr_time_dl[0].tv_usec);
|
||||
|
||||
memcpy(&tr_time_ul[1], &tr_time_dl[2], sizeof(struct timeval));
|
||||
}
|
||||
}
|
||||
|
||||
void mac::tr_log_dl(uint32_t tti)
|
||||
{
|
||||
if (tr_enabled) {
|
||||
gettimeofday(&tr_time_dl[1], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Implement Section 5.8
|
||||
void mac::reconfiguration()
|
||||
{
|
||||
|
@ -184,173 +111,148 @@ void mac::reset()
|
|||
phr_procedure.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();
|
||||
|
||||
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::mac_thread_fnc(void *arg) {
|
||||
srslte::ue::mac* mac = static_cast<srslte::ue::mac*>(arg);
|
||||
mac->main_radio_loop();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void mac::main_radio_loop() {
|
||||
void mac::run_thread() {
|
||||
setup_timers();
|
||||
|
||||
Info("Waiting PHY to synchronize with cell\n");
|
||||
phy_h->sync_start();
|
||||
while(!phy_h->get_current_tti()) {
|
||||
usleep(50000);
|
||||
}
|
||||
|
||||
ttisync.set_producer_cntr(phy_h->get_current_tti());
|
||||
|
||||
while(started) {
|
||||
if (!is_synchronized) {
|
||||
srslte_cell_t cell;
|
||||
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
|
||||
|
||||
if (phy_h->decode_mib_best(&cell, bch_payload)) {
|
||||
|
||||
// Print MIB
|
||||
srslte_cell_fprint(stdout, &cell, phy_h->get_current_tti()/10);
|
||||
|
||||
if (pcap) {
|
||||
pcap->write_dl_bch(bch_payload, SRSLTE_BCH_PAYLOAD_LEN/8, true, phy_h->get_current_tti());
|
||||
}
|
||||
|
||||
// Init HARQ for this cell
|
||||
Info("Init UL/DL HARQ\n");
|
||||
ul_harq.init(cell, ¶ms_db, log_h, &timers_db, &mux_unit);
|
||||
dl_harq.init(cell, 1024*1024, log_h, &timers_db, &demux_unit);
|
||||
|
||||
// Set the current PHY cell to the detected cell
|
||||
Info("Setting up PHY for cell_id=%d\n", cell.id);
|
||||
if (phy_h->set_cell(cell)) {
|
||||
Info("Starting RX streaming\n");
|
||||
if (phy_h->start_rxtx()) {
|
||||
log_h->step(ttisync->wait());
|
||||
/* Warning: Here order of invocation of procedures is important!! */
|
||||
tti = ttisync.wait();
|
||||
|
||||
Info("Receiver synchronized\n");
|
||||
|
||||
// Send MIB to RRC
|
||||
mac_io_lch.get(mac_io::MAC_LCH_BCCH_DL)->send(bch_payload, SRSLTE_BCH_PAYLOAD_LEN);
|
||||
|
||||
ttisync->resync();
|
||||
Info("Wait for AGC, CFO estimation, etc. \n");
|
||||
for (int i=0;i<1000;i++) {
|
||||
tti = ttisync->wait();
|
||||
}
|
||||
for (int i=0;i<NOF_TTI_THREADS;i++) {
|
||||
tti_threads_sync[i].set_producer_cntr(tti+i);
|
||||
tti_threads_sync[i].resync();
|
||||
}
|
||||
is_synchronized = true;
|
||||
} else {
|
||||
Error("Starting PHY receiver\n");
|
||||
exit(-1);
|
||||
}
|
||||
} else {
|
||||
Error("Setting PHY cell\n");
|
||||
exit(-1);
|
||||
}
|
||||
} else {
|
||||
Warning("Cell not found\n");
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
if (is_synchronized) {
|
||||
/* Warning: Here order of invocation of procedures is important!! */
|
||||
tti = ttisync->wait();
|
||||
tr_log_start(tti);
|
||||
log_h->step(tti);
|
||||
|
||||
// Step all procedures
|
||||
bsr_procedure.step(tti);
|
||||
|
||||
// Check if BSR procedure need to start SR
|
||||
|
||||
if (bsr_procedure.need_to_send_sr()) {
|
||||
Debug("Starting SR procedure by BSR request, PHY TTI=%d\n", phy_h->get_current_tti());
|
||||
sr_procedure.start();
|
||||
}
|
||||
if (bsr_procedure.need_to_reset_sr()) {
|
||||
Debug("Resetting SR procedure by BSR request\n");
|
||||
sr_procedure.reset();
|
||||
}
|
||||
sr_procedure.step(tti);
|
||||
|
||||
// Check SR if we need to start RA
|
||||
if (sr_procedure.need_random_access()) {
|
||||
Warning("Starting RA procedure by MAC order is DISABLED\n");
|
||||
//ra_procedure.start_mac_order();
|
||||
}
|
||||
|
||||
ra_procedure.step(tti);
|
||||
//phr_procedure.step(tti);
|
||||
|
||||
timers_db.step_all();
|
||||
log_h->step(tti);
|
||||
|
||||
// Trigger execution of corresponding TTI processor thread
|
||||
//printf("triggering tti=%d\n", tti);
|
||||
tti_threads_sync[tti%NOF_TTI_THREADS].increase();
|
||||
//tti_threads[0].run_tti(tti);
|
||||
|
||||
// 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();
|
||||
|
||||
search_si_rnti();
|
||||
|
||||
demux_unit.process_pdus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct phy_crnti {
|
||||
phy *phy_ptr;
|
||||
log *log_h;
|
||||
uint16_t crnti;
|
||||
};
|
||||
|
||||
void *pregen_phy_thread(void *arg) {
|
||||
struct phy_crnti *a = (struct phy_crnti*) arg;
|
||||
a->log_h->info("Setting PHY RNTI=%d\n", a->crnti);
|
||||
a->phy_ptr->set_crnti(a->crnti);
|
||||
a->phy_ptr->pregen_signals();
|
||||
a->log_h->info("Done Setting PHY RNTI\n");
|
||||
free(a);
|
||||
return NULL;
|
||||
void mac::search_si_rnti()
|
||||
{
|
||||
// Reset PDCCH search
|
||||
if (si_window_length >= 0 && si_window_start >= 0) {
|
||||
if (tti >= si_window_start + si_window_length) {
|
||||
phy_h->pdcch_dl_search_reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Setup PDCCH search
|
||||
int _si_window_start = params_db.get_param(mac_interface_params::BCCH_SI_WINDOW_ST);
|
||||
int _si_window_length = params_db.get_param(mac_interface_params::BCCH_SI_WINDOW_LEN);
|
||||
|
||||
if (_si_window_length > 0 && _si_window_start >= 0) {
|
||||
si_window_length = _si_window_length;
|
||||
si_window_start = _si_window_start;
|
||||
Debug("Searching for DL grant for SI-RNTI window_st=%d, window_len=%d\n", si_window_start, si_window_length);
|
||||
phy_h->pdcch_dl_search(SRSLTE_RNTI_SI, 0xffff, si_window_start, si_window_length);
|
||||
params_db.set_param(mac_interface_params::BCCH_SI_WINDOW_ST, -1);
|
||||
params_db.set_param(mac_interface_params::BCCH_SI_WINDOW_LEN, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void mac::pregen_phy(uint16_t phy_rnti)
|
||||
void mac::tti_clock(uint32_t tti)
|
||||
{
|
||||
pthread_t rnti_thread;
|
||||
struct phy_crnti *arg = (struct phy_crnti*) malloc(sizeof(struct phy_crnti));
|
||||
arg->crnti = phy_rnti;
|
||||
arg->phy_ptr = phy_h;
|
||||
arg->log_h = log_h;
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
|
||||
if (pthread_create(&rnti_thread, &attr, pregen_phy_thread, arg)) {
|
||||
perror("pthread_create");
|
||||
ttisync.increase();
|
||||
}
|
||||
|
||||
void mac::bch_decoded_ok(uint8_t* payload, uint32_t len)
|
||||
{
|
||||
// Send MIB to RRC
|
||||
rlc_h->write_pdu_bcch_bch(payload, len);
|
||||
|
||||
if (pcap) {
|
||||
pcap->write_dl_bch(payload, len, true, phy_h->get_current_tti());
|
||||
}
|
||||
}
|
||||
|
||||
void mac::add_sdu_handler(sdu_handler *handler) {
|
||||
demux_unit.add_sdu_handler(handler);
|
||||
void mac::harq_recv(uint32_t tti, bool ack, mac_interface_phy::tb_action_ul_t* action)
|
||||
{
|
||||
ul_harq.harq_recv(tti, ack, action);
|
||||
}
|
||||
|
||||
void mac::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action)
|
||||
{
|
||||
if (grant.rnti_type == SRSLTE_RNTI_RAR) {
|
||||
ra_procedure.new_grant_dl(grant, action);
|
||||
} else {
|
||||
dl_harq.new_grant_dl(grant, action);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t mac::get_current_tti()
|
||||
{
|
||||
return phy_h->get_current_tti();
|
||||
}
|
||||
|
||||
void mac::new_grant_ul(mac_interface_phy::mac_grant_t grant, uint8_t* payload_ptr,
|
||||
mac_interface_phy::tb_action_ul_t* action)
|
||||
{
|
||||
ul_harq.new_grant_ul(grant, payload_ptr, action);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
ul_harq.new_grant_ul_ack(grant, payload_ptr, ack, action);
|
||||
}
|
||||
|
||||
void mac::tb_decoded_ok(uint32_t harq_pid)
|
||||
{
|
||||
if (ra_procedure.in_progress()) {
|
||||
ra_procedure.tb_decoded_ok();
|
||||
} else {
|
||||
dl_harq.tb_decoded_ok(harq_pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mac::setup_timers()
|
||||
{
|
||||
if (params_db.get_param(mac_params::TIMER_TIMEALIGN) > 0) {
|
||||
timers_db.get(TIME_ALIGNMENT)->set(this, params_db.get_param(mac_params::TIMER_TIMEALIGN));
|
||||
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));
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
@ -364,366 +266,32 @@ void mac::timer_expired(uint32_t timer_id)
|
|||
}
|
||||
|
||||
/* Function called on expiry of TimeAlignmentTimer */
|
||||
void mac::timeAlignmentTimerExpire() {
|
||||
void mac::timeAlignmentTimerExpire()
|
||||
{
|
||||
dl_harq.reset();
|
||||
ul_harq.reset();
|
||||
dl_sps_assig.clear();
|
||||
ul_sps_assig.clear();
|
||||
}
|
||||
|
||||
// Receive PCH when requested as defined in Section 5.5
|
||||
void mac::receive_pch(uint32_t tti) {
|
||||
if (params_db.get_param(mac_params::PCCH_RECEIVE)) {
|
||||
dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti);
|
||||
dl_sched_grant pch_grant(sched_grant::RNTI_TYPE_PRNTI, SRSLTE_PRNTI);
|
||||
if (dl_buffer->get_dl_grant(&pch_grant)) {
|
||||
qbuff *pcch_buff = mac_io_lch.get(mac_io::MAC_LCH_PCCH_DL);
|
||||
uint8_t *ptr = (uint8_t*) pcch_buff->request();
|
||||
if (ptr && pch_grant.get_tbs() <= mac_io_lch.DEFAULT_MSG_SZ) {
|
||||
if (dl_buffer->decode_data(&pch_grant, ptr)) {
|
||||
pcch_buff->release();
|
||||
} else {
|
||||
Warning("Error decoding PCH\n");
|
||||
}
|
||||
} else {
|
||||
Error("Error getting pointer from PCCH buffer\n");
|
||||
}
|
||||
} else {
|
||||
Debug("No P-RNTI grant found while looking for PCH messages\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function controls DL Grant Assignment as specified in Section 5.3.1 in 36.321
|
||||
* and issues commands to DL harq operation
|
||||
*/
|
||||
void mac::process_dl_grants(uint32_t tti) {
|
||||
// Get DL buffer for this TTI
|
||||
dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti);
|
||||
|
||||
// 5.3.1 DL Assignment reception
|
||||
for (int i = mac_params::RNTI_C;i<=mac_params::RNTI_RA;i++) {
|
||||
// Check C-RNTI, SPS-RNTI and Temporal RNTI
|
||||
if (params_db.get_param(i) != 0) {
|
||||
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 */
|
||||
bool mac::process_ul_grants(uint32_t tti) {
|
||||
// Get DL buffer for this TTI to look for DCI grants
|
||||
dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti);
|
||||
|
||||
//if (timers_db.get(TIME_ALIGNMENT)->is_running()) {
|
||||
if (1) {
|
||||
for (int i = mac_params::RNTI_C;i<=mac_params::RNTI_TEMP;i++) {
|
||||
// Check C-RNTI, SPS-RNTI and Temporal C-RNTI
|
||||
if (params_db.get_param(i) != 0) {
|
||||
ul_sched_grant ul_grant(rnti_type(i), params_db.get_param(i));
|
||||
if (dl_buffer->get_ul_grant(&ul_grant)) {
|
||||
if (ul_grant.is_from_rar()) {
|
||||
dl_buffer->discard_pending_rar_grant();
|
||||
}
|
||||
if (ra_procedure.is_contention_resolution() && i == mac_params::RNTI_C) {
|
||||
ra_procedure.pdcch_to_crnti(true);
|
||||
}
|
||||
if (i == mac_params::RNTI_C || i == mac_params::RNTI_TEMP || ra_procedure.is_running()) {
|
||||
if (i == mac_params::RNTI_C && ul_harq.is_sps(tti)) {
|
||||
ul_grant.set_ndi(true);
|
||||
}
|
||||
ul_harq.run_tti(tti, &ul_grant, phy_h);
|
||||
return true;
|
||||
}
|
||||
else if (i == mac_params::RNTI_SPS) {
|
||||
if (ul_grant.get_ndi()) {
|
||||
ul_grant.set_ndi(false);
|
||||
ul_harq.run_tti(tti, &ul_grant, phy_h);
|
||||
} else {
|
||||
if (ul_grant.is_sps_release()) {
|
||||
ul_sps_assig.clear();
|
||||
} else {
|
||||
ul_sps_assig.reset(tti, &ul_grant);
|
||||
ul_grant.set_ndi(true);
|
||||
ul_harq.run_tti(tti, &ul_grant, phy_h);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Process configured UL assingments (SPS) */
|
||||
ul_sched_grant *sps_grant = ul_sps_assig.get_pending_grant(tti);
|
||||
if (sps_grant != NULL) {
|
||||
sps_grant->set_ndi(true);
|
||||
ul_harq.run_tti(tti, sps_grant, phy_h);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
ul_harq.run_tti(tti, phy_h);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int mac::recv_sdu(uint32_t lcid, uint8_t* sdu_payload, uint32_t nbytes)
|
||||
{
|
||||
if (lcid <= mac_io::MAC_LCH_PCCH_DL) {
|
||||
return mac_io_lch.get(lcid)->recv(sdu_payload, nbytes);
|
||||
} else {
|
||||
Error("Receiving SDU: Invalid lcid=%d\n", lcid);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int mac::recv_bcch_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
|
||||
{
|
||||
return mac_io_lch.get(mac_io::MAC_LCH_BCCH_DL)->recv(sdu_payload, buffer_len_nbytes);
|
||||
}
|
||||
|
||||
int mac::recv_ccch_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
|
||||
{
|
||||
return mac_io_lch.get(mac_io::MAC_LCH_CCCH_DL)->recv(sdu_payload, buffer_len_nbytes);
|
||||
}
|
||||
|
||||
int mac::recv_dtch0_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
|
||||
{
|
||||
return mac_io_lch.get(mac_io::MAC_LCH_DTCH0_DL)->recv(sdu_payload, buffer_len_nbytes);
|
||||
}
|
||||
|
||||
int mac::recv_dcch0_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
|
||||
{
|
||||
return mac_io_lch.get(mac_io::MAC_LCH_DCCH0_DL)->recv(sdu_payload, buffer_len_nbytes);
|
||||
}
|
||||
|
||||
|
||||
bool mac::send_sdu(uint32_t lcid, uint8_t* sdu_payload, uint32_t nbytes)
|
||||
{
|
||||
lcid += mac_io::MAC_LCH_CCCH_UL;
|
||||
if (lcid <= mac_io::MAC_LCH_DTCH2_UL) {
|
||||
return mac_io_lch.get(lcid)->send(sdu_payload, nbytes);
|
||||
} else {
|
||||
Error("Receiving SDU: Invalid lcid=%d\n", lcid);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool mac::send_ccch_sdu(uint8_t* sdu_payload, uint32_t nbytes)
|
||||
{
|
||||
return mac_io_lch.get(mac_io::MAC_LCH_CCCH_UL)->send(sdu_payload, nbytes);
|
||||
}
|
||||
|
||||
bool mac::send_dtch0_sdu(uint8_t* sdu_payload, uint32_t nbytes)
|
||||
{
|
||||
return mac_io_lch.get(mac_io::MAC_LCH_DTCH0_UL)->send(sdu_payload, nbytes);
|
||||
}
|
||||
|
||||
bool mac::send_dcch0_sdu(uint8_t* sdu_payload, uint32_t nbytes)
|
||||
{
|
||||
return mac_io_lch.get(mac_io::MAC_LCH_DCCH0_UL)->send(sdu_payload, nbytes);
|
||||
}
|
||||
|
||||
void mac::set_param(mac_params::mac_param_t param, int64_t value)
|
||||
void mac::set_param(mac_interface_params::mac_param_t param, int64_t value)
|
||||
{
|
||||
params_db.set_param((uint32_t) param, value);
|
||||
}
|
||||
|
||||
int64_t mac::get_param(mac_params::mac_param_t param)
|
||||
int64_t mac::get_param(mac_interface_params::mac_param_t param)
|
||||
{
|
||||
return params_db.get_param((uint32_t) param);
|
||||
}
|
||||
|
||||
void mac::setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD)
|
||||
{
|
||||
Info("Logical Channel Setup: LCID=%d, LCG=%d, priority=%d, PBR=%d, BSd=%d\n", lcid, lcg, priority, PBR_x_tti, BSD);
|
||||
Info("Logical Channel Setup: LCID=%d, LCG=%d, priority=%d, PBR=%d, BSd=%d\n",
|
||||
lcid, lcg, priority, PBR_x_tti, BSD);
|
||||
mux_unit.set_priority(lcid, priority, PBR_x_tti, BSD);
|
||||
bsr_procedure.setup_lcg(lcid, lcg);
|
||||
bsr_procedure.set_priority(lcid, priority);
|
||||
}
|
||||
|
||||
|
||||
void* tti_thread_runner(void *arg) {
|
||||
mac::tti_thread* x = (mac::tti_thread*) arg;
|
||||
x->run();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool mac::tti_thread::init(mac* parent_, tti_sync_cv *sync_)
|
||||
{
|
||||
parent = parent_;
|
||||
log_h = parent->log_h;
|
||||
sync = sync_;
|
||||
|
||||
started = threads_new_rt(&thread, tti_thread_runner, this);
|
||||
return started;
|
||||
}
|
||||
|
||||
void mac::tti_thread::stop()
|
||||
{
|
||||
started = false;
|
||||
pthread_join(thread, NULL);
|
||||
}
|
||||
|
||||
void mac::tti_thread::run()
|
||||
{
|
||||
while(started) {
|
||||
uint32_t tti = sync->wait();
|
||||
|
||||
if (parent->is_synchronized) {
|
||||
run_tti((tti+1)%10240);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mac::tti_thread::run_tti(uint32_t tti) {
|
||||
//printf("running tti=%d\n", tti);
|
||||
// Receive PCH, if requested
|
||||
parent->receive_pch(tti);
|
||||
|
||||
// Process DL grants always
|
||||
parent->process_dl_grants(tti);
|
||||
|
||||
// Send pending HARQ ACK, if any, and contention resolution is resolved
|
||||
if (parent->dl_harq.is_ack_pending_resolution()) {
|
||||
parent->ra_procedure.step(tti);
|
||||
if (parent->ra_procedure.is_successful() || parent->ra_procedure.is_response_error()) {
|
||||
Info("Sending pending ACK for contention resolution PHY TTI: %d\n", parent->phy_h->get_current_tti());
|
||||
parent->dl_harq.send_pending_ack_contention_resolution();
|
||||
}
|
||||
}
|
||||
|
||||
// Process UL grants if RA procedure is done or in contention resolution
|
||||
if (parent->ra_procedure.is_contention_resolution() || parent->ra_procedure.is_successful()) {
|
||||
parent->process_ul_grants(tti);
|
||||
}
|
||||
|
||||
// If ACK/SR was pending but there was no PUSCH transmission, transmit now through PUCCH
|
||||
ul_buffer *ul_buffer = parent->phy_h->get_ul_buffer(tti+4);
|
||||
|
||||
// Generate scheduling request if we have to
|
||||
if (parent->phy_h->sr_is_ready_to_send(tti+4)) {
|
||||
ul_buffer->generate_sr();
|
||||
}
|
||||
|
||||
// If the packet was not generated by an UL grant, means it's PUCCH or SRS. Generate now the signal
|
||||
if (!ul_buffer->is_released() && (ul_buffer->uci_ready() || ul_buffer->srs_is_ready_to_send())) {
|
||||
ul_buffer->generate_data();
|
||||
}
|
||||
|
||||
// Wait for previous TTI to be transmitted
|
||||
if (!parent->is_first_tx) {
|
||||
pthread_mutex_lock(&parent->tti_threads_sync_tx[tti%parent->NOF_TTI_THREADS]);
|
||||
}
|
||||
parent->is_first_tx = false;
|
||||
|
||||
// Send now to the radio
|
||||
if (ul_buffer->is_released()) {
|
||||
ul_buffer->send();
|
||||
ul_buffer->ready();
|
||||
parent->is_first_of_burst = false;
|
||||
} else {
|
||||
if (!parent->is_first_of_burst) {
|
||||
ul_buffer->send_end_of_burst();
|
||||
parent->is_first_of_burst = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Allow next TTI to be transmitted
|
||||
pthread_mutex_unlock(&parent->tti_threads_sync_tx[(tti+1)%parent->NOF_TTI_THREADS]);
|
||||
|
||||
// Check if there is pending CCCH SDU in Multiplexing Unit
|
||||
if (parent->mux_unit.is_pending_ccch_sdu()) {
|
||||
// Start RA procedure
|
||||
if (!parent->ra_procedure.in_progress() && !parent->ra_procedure.is_successful()) {
|
||||
parent->ra_procedure.start_rlc_order();
|
||||
}
|
||||
}
|
||||
if (parent->ra_procedure.is_successful() &&
|
||||
parent->phy_rnti != parent->params_db.get_param(mac_params::RNTI_C) &&
|
||||
parent->params_db.get_param(mac_params::RNTI_C) > 0 &&
|
||||
parent->phy_h->get_param(srslte::ue::phy_params::SRS_IS_CONFIGURED) == 1)
|
||||
{
|
||||
parent->phy_rnti = parent->params_db.get_param(mac_params::RNTI_C);
|
||||
parent->pregen_phy(parent->phy_rnti);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -55,23 +55,18 @@ void mac_pcap::pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reT
|
|||
uint16_t crnti, uint8_t direction, uint8_t rnti_type)
|
||||
{
|
||||
if (enable_write) {
|
||||
if (pdu_len_bytes < max_pdu_len) {
|
||||
MAC_Context_Info_t context =
|
||||
{
|
||||
FDD_RADIO, direction, rnti_type,
|
||||
crnti, /* RNTI */
|
||||
ue_id, /* UEId */
|
||||
reTX, /* Retx */
|
||||
crc_ok, /* CRC Stsatus (i.e. OK) */
|
||||
tti/10, /* Sysframe number */
|
||||
tti%10 /* Subframe number */
|
||||
};
|
||||
if (pdu) {
|
||||
srslte_bit_unpack_vector(pdu, pdu_pcap_tmp, pdu_len_bytes*8);
|
||||
MAC_LTE_PCAP_WritePDU(pcap_file, &context, pdu_pcap_tmp, pdu_len_bytes);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "MAC PCAP: PDU len %d exceeds maximum allowed length (%d bytes)\n", pdu_len_bytes, max_pdu_len);
|
||||
MAC_Context_Info_t context =
|
||||
{
|
||||
FDD_RADIO, direction, rnti_type,
|
||||
crnti, /* RNTI */
|
||||
ue_id, /* UEId */
|
||||
reTX, /* Retx */
|
||||
crc_ok, /* CRC Stsatus (i.e. OK) */
|
||||
tti/10, /* Sysframe number */
|
||||
tti%10 /* Subframe number */
|
||||
};
|
||||
if (pdu) {
|
||||
MAC_LTE_PCAP_WritePDU(pcap_file, &context, pdu, pdu_len_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,18 +32,14 @@
|
|||
namespace srslte {
|
||||
namespace ue {
|
||||
|
||||
#define IO_IDX(lch) (lch + mac_io::MAC_LCH_CCCH_UL)
|
||||
#define UL_IDX(lch) (lch - mac_io::MAC_LCH_CCCH_UL)
|
||||
|
||||
mux::mux() : pdu_msg(20)
|
||||
{
|
||||
msg3_buff.init(mac::NOF_TTI_THREADS, MSG3_BUFF_SZ);
|
||||
pdu_buff.init(mac::NOF_TTI_THREADS, PDU_BUFF_SZ);
|
||||
bzero(nof_tx_pkts, sizeof(uint32_t) * mac_io::NOF_UL_LCH);
|
||||
msg3_buff.init(1, MSG3_BUFF_SZ);
|
||||
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
msg3_has_been_transmitted = false;
|
||||
|
||||
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
|
||||
for (int i=0;i<NOF_UL_LCH;i++) {
|
||||
priority[i] = i;
|
||||
priority_sorted[i] = i;
|
||||
PBR[i] = -1; // -1 is infinite
|
||||
|
@ -52,16 +48,16 @@ mux::mux() : pdu_msg(20)
|
|||
}
|
||||
}
|
||||
|
||||
void mux::init(log *log_h_, mac_io *mac_io_h_, bsr_proc *bsr_procedure_)
|
||||
void mux::init(rlc_interface_mac *rlc_, log *log_h_, bsr_proc *bsr_procedure_)
|
||||
{
|
||||
log_h = log_h_;
|
||||
mac_io_h = mac_io_h_;
|
||||
rlc = rlc_;
|
||||
bsr_procedure = bsr_procedure_;
|
||||
}
|
||||
|
||||
void mux::reset()
|
||||
{
|
||||
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
|
||||
for (int i=0;i<NOF_UL_LCH;i++) {
|
||||
Bj[i] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -73,8 +69,8 @@ bool mux::is_pending_ccch_sdu()
|
|||
|
||||
bool mux::is_pending_any_sdu()
|
||||
{
|
||||
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
|
||||
if (!mac_io_h->get(i)->isempty()) {
|
||||
for (int i=0;i<NOF_UL_LCH;i++) {
|
||||
if (rlc->get_buffer_state(i)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -82,30 +78,27 @@ bool mux::is_pending_any_sdu()
|
|||
}
|
||||
|
||||
bool mux::is_pending_sdu(uint32_t lch_id) {
|
||||
lch_id += (uint32_t) mac_io::MAC_LCH_CCCH_UL;
|
||||
if (lch_id < mac_io::MAC_NOF_QUEUES) {
|
||||
return !mac_io_h->get(lch_id)->isempty();
|
||||
}
|
||||
return rlc->get_buffer_state(lch_id)>0;
|
||||
}
|
||||
|
||||
void mux::set_priority(uint32_t lch_id, uint32_t set_priority, int set_PBR, uint32_t set_BSD)
|
||||
{
|
||||
pthread_mutex_lock(&mutex);
|
||||
if (lch_id < mac_io::NOF_UL_LCH) {
|
||||
if (lch_id < NOF_UL_LCH) {
|
||||
priority[lch_id] = set_priority;
|
||||
PBR[lch_id] = set_PBR;
|
||||
BSD[lch_id] = set_BSD;
|
||||
|
||||
// Insert priority in sorted idx array
|
||||
int new_index = 0;
|
||||
while(set_priority > priority_sorted[new_index] && new_index < mac_io::NOF_UL_LCH) {
|
||||
while(set_priority > priority_sorted[new_index] && new_index < NOF_UL_LCH) {
|
||||
new_index++;
|
||||
}
|
||||
int old_index = 0;
|
||||
while(lch_id != lchid_sorted[old_index] && new_index < mac_io::NOF_UL_LCH) {
|
||||
while(lch_id != lchid_sorted[old_index] && new_index < NOF_UL_LCH) {
|
||||
old_index++;
|
||||
}
|
||||
if (new_index == mac_io::NOF_UL_LCH) {
|
||||
if (new_index == NOF_UL_LCH) {
|
||||
Error("Can't find LchID=%d in sorted list\n", lch_id);
|
||||
return;
|
||||
}
|
||||
|
@ -122,56 +115,6 @@ void mux::set_priority(uint32_t lch_id, uint32_t set_priority, int set_PBR, uint
|
|||
|
||||
}
|
||||
|
||||
void mux::pdu_release()
|
||||
{
|
||||
pdu_buff.release();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
bool mux::pdu_move_to_msg3(uint32_t pdu_sz)
|
||||
{
|
||||
if (pdu_buff.isempty()) {
|
||||
if (assemble_pdu(pdu_sz)) {
|
||||
if (pdu_buff.pending_data() < MSG3_BUFF_SZ) {
|
||||
pdu_buff.move_to(&msg3_buff);
|
||||
return true;
|
||||
} else {
|
||||
pdu_buff.release();
|
||||
Error("Assembled PDU size exceeds Msg3 buffer size\n");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Error("Assembling PDU\n");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Error("Generating PDU: PDU pending in buffer for transmission\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Multiplexing and logical channel priorization as defined in Section 5.4.3
|
||||
uint8_t* mux::pdu_pop(uint32_t pdu_sz)
|
||||
{
|
||||
// Acquire mutex. Will be released after a call to pdu_release
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
if (pdu_buff.isempty()) {
|
||||
if (assemble_pdu(pdu_sz)) {
|
||||
return (uint8_t*) pdu_buff.pop();
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
Error("Generating PDU: PDU pending in buffer for transmission\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void mux::append_crnti_ce_next_tx(uint16_t crnti) {
|
||||
pending_crnti_ce = crnti;
|
||||
}
|
||||
|
||||
sch_subh::cetype bsr_format_convert(bsr_proc::bsr_format_t format) {
|
||||
switch(format) {
|
||||
case bsr_proc::LONG_BSR:
|
||||
|
@ -179,24 +122,21 @@ sch_subh::cetype bsr_format_convert(bsr_proc::bsr_format_t format) {
|
|||
case bsr_proc::SHORT_BSR:
|
||||
return sch_subh::SHORT_BSR;
|
||||
case bsr_proc::TRUNC_BSR:
|
||||
return sch_subh::TRUNC_BSR;
|
||||
|
||||
return sch_subh::TRUNC_BSR;
|
||||
}
|
||||
}
|
||||
int pkt_num=0;
|
||||
bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
|
||||
|
||||
uint8_t *buff = (uint8_t*) pdu_buff.request();
|
||||
if (!buff) {
|
||||
Error("Assembling PDU: Buffer is not available\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure pdu_sz is byte-aligned
|
||||
pdu_sz_nbits = 8*(pdu_sz_nbits/8);
|
||||
|
||||
|
||||
int pkt_num = 0;
|
||||
|
||||
// Multiplexing and logical channel priorization as defined in Section 5.4.3
|
||||
bool mux::pdu_get(uint8_t *payload, uint32_t pdu_sz)
|
||||
{
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
// Update Bj
|
||||
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
|
||||
for (int i=0;i<NOF_UL_LCH;i++) {
|
||||
// Add PRB unless it's infinity
|
||||
if (PBR[i] >= 0) {
|
||||
Bj[i] += PBR[i];
|
||||
|
@ -207,16 +147,14 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
|
|||
}
|
||||
|
||||
// Logical Channel Procedure
|
||||
|
||||
uint32_t sdu_sz = 0;
|
||||
|
||||
pdu_msg.init(pdu_sz_nbits/8, true);
|
||||
|
||||
pdu_msg.init(pdu_sz, true);
|
||||
|
||||
// MAC control element for C-RNTI or data from UL-CCCH
|
||||
bool is_first = true;
|
||||
if (!allocate_sdu(UL_IDX(mac_io::MAC_LCH_CCCH_UL), &pdu_msg, &is_first)) {
|
||||
if (!allocate_sdu(0, &pdu_msg, &is_first)) {
|
||||
if (pending_crnti_ce) {
|
||||
if (pdu_msg.new_subh()) {
|
||||
if (pdu_msg.new_subh()) {http://moodycamel.com/blog/2014/detailed-design-of-a-lock-free-queue
|
||||
pdu_msg.next();
|
||||
if (!pdu_msg.get()->set_c_rnti(pending_crnti_ce)) {
|
||||
Warning("Pending C-RNTI CE could not be inserted in MAC PDU\n");
|
||||
|
@ -250,29 +188,25 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
|
|||
|
||||
// data from any Logical Channel, except data from UL-CCCH;
|
||||
// first only those with positive Bj
|
||||
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
|
||||
bool res = true;
|
||||
while ((Bj[i] > 0 || PBR[i] < 0) && res) {
|
||||
res = allocate_sdu(lchid_sorted[i], &pdu_msg, &sdu_sz, &is_first);
|
||||
if (res && PBR[i] >= 0) {
|
||||
Bj[i] -= sdu_sz;
|
||||
uint32_t sdu_sz = 0;
|
||||
for (int i=0;i<NOF_UL_LCH;i++) {
|
||||
uint32_t lcid = lchid_sorted[i];
|
||||
if (lcid != 0) {
|
||||
bool res = true;
|
||||
while ((Bj[lcid] > 0 || PBR[lcid] < 0) && res) {
|
||||
res = allocate_sdu(lcid, &pdu_msg, Bj[lcid], &sdu_sz, &is_first);
|
||||
if (res && PBR[lcid] >= 0) {
|
||||
Bj[lcid] -= sdu_sz;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If resources remain, allocate regardless of their Bj value
|
||||
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
|
||||
for (int i=0;i<NOF_UL_LCH;i++) {
|
||||
while (allocate_sdu(lchid_sorted[i], &pdu_msg));
|
||||
}
|
||||
|
||||
/* Release all SDUs */
|
||||
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
|
||||
while(nof_tx_pkts[i] > 0) {
|
||||
mac_io_h->get(IO_IDX(i))->release();
|
||||
nof_tx_pkts[i]--;
|
||||
}
|
||||
}
|
||||
|
||||
bool send_bsr = bsr_procedure->generate_bsr_on_ul_grant(pdu_msg.rem_size(), &bsr);
|
||||
// Insert Padding BSR if not inserted Regular/Periodic BSR
|
||||
if (!bsr_payload_sz && send_bsr) {
|
||||
|
@ -287,55 +221,58 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
|
|||
bsr_subh->set_bsr(bsr.buff_size, bsr_format_convert(bsr.format), bsr_payload_sz?false:true);
|
||||
}
|
||||
|
||||
Debug("Assembled MAC PDU msg size %d/%d bytes\n", pdu_msg.size(), pdu_sz_nbits/8);
|
||||
//pdu_msg.fprint(stdout);
|
||||
Debug("Assembled MAC PDU msg size %d/%d bytes\n", pdu_msg.size(), pdu_sz);
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
/* Generate MAC PDU and save to buffer */
|
||||
if (pdu_msg.write_packet(buff)) {
|
||||
pdu_buff.push(pdu_sz_nbits);
|
||||
} else {
|
||||
if (!pdu_msg.write_packet(payload, rlc)) {
|
||||
Error("Writing PDU message to packet\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void mux::append_crnti_ce_next_tx(uint16_t crnti) {
|
||||
pending_crnti_ce = crnti;
|
||||
}
|
||||
|
||||
|
||||
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg)
|
||||
{
|
||||
return allocate_sdu(lcid, pdu_msg, NULL, NULL);
|
||||
return allocate_sdu(lcid, pdu_msg, -1, NULL, NULL);
|
||||
}
|
||||
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, bool *is_first)
|
||||
{
|
||||
return allocate_sdu(lcid, pdu_msg, NULL, is_first);
|
||||
return allocate_sdu(lcid, pdu_msg, -1, NULL, is_first);
|
||||
}
|
||||
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, uint32_t *sdu_sz, bool *is_first)
|
||||
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, int max_sdu_sz, uint32_t *sdu_sz, bool *is_first)
|
||||
{
|
||||
|
||||
// Get n-th pending SDU pointer and length
|
||||
uint32_t buff_len = 0;
|
||||
uint8_t *buff_ptr = (uint8_t*) mac_io_h->get(mac_io::MAC_LCH_CCCH_UL + lcid)->pop(&buff_len, nof_tx_pkts[lcid]);
|
||||
uint32_t sdu_len = rlc->get_buffer_state(lcid);
|
||||
|
||||
uint32_t nbytes = (buff_len-1)/8 + 1;
|
||||
|
||||
if (buff_ptr && buff_len > 0) { // there is pending SDU to allocate
|
||||
if (sdu_sz) {
|
||||
*sdu_sz = buff_len;
|
||||
if (sdu_len > 0) { // there is pending SDU to allocate
|
||||
if (sdu_len > max_sdu_sz && max_sdu_sz >= 0) {
|
||||
sdu_len = max_sdu_sz;
|
||||
}
|
||||
if (sdu_len > pdu_msg->rem_size() - pdu_msg->size_plus_header_sdu(sdu_len)) {
|
||||
sdu_len = pdu_msg->rem_size() - pdu_msg->size_plus_header_sdu(sdu_len);
|
||||
}
|
||||
if (pdu_msg->new_subh()) { // there is space for a new subheader
|
||||
pdu_msg->next();
|
||||
if (pdu_msg->get()->set_sdu(lcid, buff_ptr, nbytes, is_first?*is_first:false)) { // new SDU could be added
|
||||
if (pdu_msg->get()->set_sdu(lcid, sdu_len, is_first?*is_first:false)) { // new SDU could be added
|
||||
if (is_first) {
|
||||
*is_first = false;
|
||||
}
|
||||
Info("Allocated SDU lcid=%d nbytes=%d\n", lcid, nbytes);
|
||||
// Increase number of pop'ed packets from queue
|
||||
nof_tx_pkts[lcid]++;
|
||||
if (sdu_sz) {
|
||||
*sdu_sz = sdu_len;
|
||||
}
|
||||
Info("Allocated SDU lcid=%d nbytes=%d\n", lcid, sdu_len);
|
||||
return true;
|
||||
} else {
|
||||
if (pdu_msg->rem_size() > 10) {
|
||||
Info("Could not allocate SDU in current grant. SDU length: %d bytes. Grant space: %d bytes\n", nbytes,
|
||||
pdu_msg->rem_size());
|
||||
}
|
||||
Error("Could not add SDU rem_size=%d, sdu_len=%d\n", pdu_msg->rem_size(), sdu_len);
|
||||
pdu_msg->del_subh();
|
||||
}
|
||||
}
|
||||
|
@ -343,8 +280,6 @@ bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, uint32_t *sdu_sz, bool *
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mux::msg3_flush()
|
||||
{
|
||||
msg3_buff.flush();
|
||||
|
@ -361,23 +296,37 @@ bool mux::msg3_is_transmitted()
|
|||
return msg3_has_been_transmitted;
|
||||
}
|
||||
|
||||
/* Returns a pointer to the Msg3 buffer */
|
||||
uint8_t* mux::msg3_pop(uint32_t TB_size)
|
||||
|
||||
bool mux::pdu_move_to_msg3(uint32_t pdu_sz)
|
||||
{
|
||||
uint32_t len;
|
||||
uint8_t *msg3 = (uint8_t*) msg3_buff.pop(&len);
|
||||
uint8_t *msg3 = (uint8_t*) msg3_buff.request();
|
||||
if (msg3) {
|
||||
if (len < TB_size) {
|
||||
// Pad with zeros without exceeding maximum buffer size
|
||||
if (TB_size <= MSG3_BUFF_SZ) {
|
||||
bzero(&msg3[len], (TB_size-len)*sizeof(uint8_t));
|
||||
} else {
|
||||
Error("Requested TB size from Msg3 buffer exceeds buffer size (%d>%d)\n", TB_size, MSG3_BUFF_SZ);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (pdu_get(msg3, pdu_sz)) {
|
||||
msg3_buff.push(pdu_sz);
|
||||
return true;
|
||||
} else {
|
||||
Error("Assembling PDU\n");
|
||||
}
|
||||
} else {
|
||||
Error("Generating PDU: PDU pending in buffer for transmission\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Returns a pointer to the Msg3 buffer */
|
||||
bool mux::msg3_get(uint8_t *payload, uint32_t pdu_sz)
|
||||
{
|
||||
if (pdu_move_to_msg3(pdu_sz)) {
|
||||
uint8_t *msg3 = (uint8_t*) msg3_buff.pop();
|
||||
if (msg3) {
|
||||
memcpy(payload, msg3, sizeof(uint8_t)*pdu_sz);
|
||||
msg3_buff.release();
|
||||
return true;
|
||||
} else {
|
||||
Error("Generating Msg3\n");
|
||||
}
|
||||
}
|
||||
return msg3;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ void sch_pdu::parse_packet(uint8_t *ptr)
|
|||
}
|
||||
|
||||
// Section 6.1.2
|
||||
bool sch_pdu::write_packet(uint8_t* ptr)
|
||||
bool sch_pdu::write_packet(uint8_t* ptr, rlc_interface_mac *rlc)
|
||||
{
|
||||
uint8_t *init_ptr = ptr;
|
||||
bool last_is_padding = false;
|
||||
|
@ -159,16 +159,16 @@ bool sch_pdu::write_packet(uint8_t* ptr)
|
|||
// Write payloads in the same order
|
||||
for (int i=0;i<nof_subheaders;i++) {
|
||||
if (!subheaders[i].is_sdu()) {
|
||||
subheaders[i].write_payload(&ptr);
|
||||
subheaders[i].write_payload(&ptr, rlc);
|
||||
}
|
||||
}
|
||||
for (int i=0;i<nof_subheaders;i++) {
|
||||
if (subheaders[i].is_sdu()) {
|
||||
subheaders[i].write_payload(&ptr);
|
||||
subheaders[i].write_payload(&ptr, rlc);
|
||||
}
|
||||
}
|
||||
// Set paddint to zeros (if any)
|
||||
bzero(ptr, rem_len*sizeof(uint8_t)*8);
|
||||
bzero(ptr, rem_len*sizeof(uint8_t));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -235,8 +235,8 @@ void sch_subh::init()
|
|||
{
|
||||
lcid = 0;
|
||||
nof_bytes = 0;
|
||||
sdu_payload_ptr = NULL;
|
||||
bzero(ce_payload, sizeof(uint8_t) * MAX_CE_PAYLOAD_LEN);
|
||||
payload = NULL;
|
||||
bzero(payload, sizeof(uint8_t) * MAX_CE_PAYLOAD_LEN);
|
||||
}
|
||||
|
||||
sch_subh::cetype sch_subh::ce_type()
|
||||
|
@ -296,29 +296,36 @@ bool sch_subh::is_sdu()
|
|||
}
|
||||
uint16_t sch_subh::get_c_rnti()
|
||||
{
|
||||
uint8_t *ptr = ce_payload;
|
||||
uint16_t ret = (uint16_t) srslte_bit_unpack(&ptr, 16);
|
||||
return ret;
|
||||
if (payload) {
|
||||
return (uint16_t) payload[0] | payload[1]<<8;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
uint64_t sch_subh::get_con_res_id()
|
||||
{
|
||||
uint8_t *ptr = ce_payload;
|
||||
uint64_t ret = (uint64_t) srslte_bit_unpack_l(&ptr, 48);
|
||||
return ret;
|
||||
if (payload) {
|
||||
return ((uint64_t) payload[0]) | ((uint64_t) payload[1])<<8 | ((uint64_t) payload[2])<<16 | ((uint64_t) payload[3])<<24 |
|
||||
((uint64_t) payload[4])<<32 | ((uint64_t) payload[5])<<48;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
uint8_t sch_subh::get_phd()
|
||||
{
|
||||
uint8_t *ptr = ce_payload;
|
||||
ptr += 2;
|
||||
uint8_t ret = (uint8_t) srslte_bit_unpack(&ptr, 6);
|
||||
return ret;
|
||||
if (payload) {
|
||||
return (uint8_t) payload[0]&0x3f;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
uint8_t sch_subh::get_ta_cmd()
|
||||
{
|
||||
uint8_t *ptr = ce_payload;
|
||||
ptr += 2;
|
||||
uint8_t ret = (uint8_t) srslte_bit_unpack(&ptr, 6);
|
||||
return ret;
|
||||
if (payload) {
|
||||
return (uint8_t) payload[0]&0x3f;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
uint32_t sch_subh::get_sdu_lcid()
|
||||
{
|
||||
|
@ -330,7 +337,7 @@ uint32_t sch_subh::get_sdu_nbytes()
|
|||
}
|
||||
uint8_t* sch_subh::get_sdu_ptr()
|
||||
{
|
||||
return sdu_payload_ptr;
|
||||
return payload;
|
||||
}
|
||||
void sch_subh::set_padding(uint32_t padding_len)
|
||||
{
|
||||
|
@ -353,16 +360,12 @@ bool sch_subh::set_bsr(uint32_t buff_size[4], sch_subh::cetype format, bool upda
|
|||
}
|
||||
uint32_t ce_size = format==LONG_BSR?3:1;
|
||||
if (((sch_pdu*)parent)->has_space_ce(ce_size) || !update_size) {
|
||||
uint8_t *ptr = ce_payload;
|
||||
if (format==LONG_BSR) {
|
||||
bzero(ce_payload, 3*8*sizeof(uint8_t));
|
||||
for (int i=0;i<4;i++) {
|
||||
srslte_bit_pack(buff_size_table(buff_size[i]), &ptr, 6);
|
||||
}
|
||||
w_payload_ce[0] = (buff_size_table(buff_size[0])&0x3f) << 2 | (buff_size_table(buff_size[1])&0xc0)>>6;
|
||||
w_payload_ce[1] = (buff_size_table(buff_size[1])&0xf) << 4 | (buff_size_table(buff_size[2])&0xf0)>>4;
|
||||
w_payload_ce[2] = (buff_size_table(buff_size[2])&0x3) << 6 | (buff_size_table(buff_size[3])&0x3f);
|
||||
} else {
|
||||
bzero(ce_payload, 8*sizeof(uint8_t));
|
||||
srslte_bit_pack(nonzero_lcg, &ptr, 2);
|
||||
srslte_bit_pack(buff_size_table(buff_size[nonzero_lcg]), &ptr, 6);
|
||||
w_payload_ce[0] = (nonzero_lcg&0x3)<<6 | buff_size_table(buff_size[nonzero_lcg])&0x3f;
|
||||
}
|
||||
lcid = format;
|
||||
if (update_size) {
|
||||
|
@ -377,11 +380,9 @@ bool sch_subh::set_bsr(uint32_t buff_size[4], sch_subh::cetype format, bool upda
|
|||
bool sch_subh::set_c_rnti(uint16_t crnti)
|
||||
{
|
||||
if (((sch_pdu*)parent)->has_space_ce(2)) {
|
||||
|
||||
*((uint16_t*) ce_payload) = crnti;
|
||||
w_payload_ce[0] = (uint8_t) (crnti&0xff00)>>8;
|
||||
w_payload_ce[1] = (uint8_t) (crnti&0x00ff);
|
||||
lcid = C_RNTI;
|
||||
uint8_t *ptr = ce_payload;
|
||||
srslte_bit_pack(crnti, &ptr, 16);
|
||||
((sch_pdu*)parent)->update_space_ce(2);
|
||||
return true;
|
||||
} else {
|
||||
|
@ -391,8 +392,12 @@ bool sch_subh::set_c_rnti(uint16_t crnti)
|
|||
bool sch_subh::set_con_res_id(uint64_t con_res_id)
|
||||
{
|
||||
if (((sch_pdu*)parent)->has_space_ce(6)) {
|
||||
uint8_t *ptr = ce_payload;
|
||||
srslte_bit_pack_l(con_res_id, &ptr, 48);
|
||||
w_payload_ce[0] = (uint8_t) ((con_res_id&0xff0000000000)>>48);
|
||||
w_payload_ce[1] = (uint8_t) ((con_res_id&0x00ff00000000)>>32);
|
||||
w_payload_ce[2] = (uint8_t) ((con_res_id&0x0000ff000000)>>24);
|
||||
w_payload_ce[3] = (uint8_t) ((con_res_id&0x000000ff0000)>>16);
|
||||
w_payload_ce[4] = (uint8_t) ((con_res_id&0x00000000ff00)>>8);
|
||||
w_payload_ce[5] = (uint8_t) ((con_res_id&0x0000000000ff));
|
||||
lcid = CON_RES_ID;
|
||||
((sch_pdu*)parent)->update_space_ce(6);
|
||||
return true;
|
||||
|
@ -403,9 +408,7 @@ bool sch_subh::set_con_res_id(uint64_t con_res_id)
|
|||
bool sch_subh::set_phd(uint8_t phd)
|
||||
{
|
||||
if (((sch_pdu*)parent)->has_space_ce(1)) {
|
||||
uint8_t *ptr = ce_payload;
|
||||
srslte_bit_pack(0, &ptr, 2);
|
||||
srslte_bit_pack(phd, &ptr, 6);
|
||||
w_payload_ce[0] = phd&0x3f;
|
||||
lcid = PHD_REPORT;
|
||||
((sch_pdu*)parent)->update_space_ce(1);
|
||||
return true;
|
||||
|
@ -414,31 +417,29 @@ 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)
|
||||
{
|
||||
return set_sdu(lcid_, ptr, nof_bytes_, false);
|
||||
}
|
||||
|
||||
bool sch_subh::set_sdu(uint32_t lcid_, uint8_t* ptr, uint32_t nof_bytes_, bool is_first)
|
||||
{
|
||||
if (((sch_pdu*)parent)->has_space_sdu(nof_bytes_, is_first)) {
|
||||
sdu_payload_ptr = ptr;
|
||||
nof_bytes = nof_bytes_;
|
||||
lcid = lcid_;
|
||||
((sch_pdu*)parent)->update_space_sdu(nof_bytes_, is_first);
|
||||
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_ta_cmd(uint8_t ta_cmd)
|
||||
|
||||
bool sch_subh::set_sdu(uint32_t lcid_, uint32_t nof_bytes_)
|
||||
{
|
||||
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 set_sdu(lcid_, nof_bytes_, false);
|
||||
}
|
||||
|
||||
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)) {
|
||||
nof_bytes = nof_bytes_;
|
||||
lcid = lcid_;
|
||||
((sch_pdu*)parent)->update_space_sdu(nof_bytes_, is_first);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -449,44 +450,47 @@ void sch_subh::write_subheader(uint8_t** ptr, bool is_last)
|
|||
{
|
||||
if (is_sdu()) {
|
||||
// MAC SDU: R/R/E/LCID/F/L subheader
|
||||
srslte_bit_pack(0, ptr, 2); // R, R
|
||||
srslte_bit_pack(is_last?0:1, ptr, 1); // E
|
||||
srslte_bit_pack(lcid, ptr, 5); // LCID
|
||||
*(*ptr + 0) = (uint8_t) is_last<<5 | (lcid & 0x1f);
|
||||
|
||||
// 2nd and 3rd octet
|
||||
if (!is_last) {
|
||||
srslte_bit_pack(F_bit?1:0, ptr, 1); // F
|
||||
srslte_bit_pack(nof_bytes, ptr, nof_bytes<128?7:15); // L
|
||||
if (nof_bytes >= 128) {
|
||||
*(*ptr + 1) = (uint8_t) 1<<7 | ((nof_bytes & 0x7f00) >> 8);
|
||||
*(*ptr + 2) = (uint8_t) (nof_bytes & 0xff);
|
||||
} else {
|
||||
*(*ptr + 1) = (uint8_t) (nof_bytes & 0x7f);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// MAC CE: R/R/E/LCID MAC Subheader
|
||||
srslte_bit_pack(0, ptr, 2); // R, R
|
||||
srslte_bit_pack(is_last?0:1, ptr, 1); // E
|
||||
srslte_bit_pack(lcid, ptr, 5); // LCID
|
||||
*(*ptr + 0) = (uint8_t) is_last<<5 | (lcid & 0x1f);
|
||||
}
|
||||
}
|
||||
void sch_subh::write_payload(uint8_t** ptr)
|
||||
|
||||
void sch_subh::write_payload(uint8_t** ptr, rlc_interface_mac *rlc)
|
||||
{
|
||||
uint8_t *src;
|
||||
if (is_sdu()) {
|
||||
src = sdu_payload_ptr;
|
||||
// Read data from RLC interface
|
||||
rlc->read_pdu(lcid, *ptr, nof_bytes);
|
||||
} else {
|
||||
nof_bytes = sizeof_ce(lcid, parent->is_ul());
|
||||
src = ce_payload;
|
||||
memcpy(*ptr, w_payload_ce, nof_bytes*sizeof(uint8_t));
|
||||
}
|
||||
memcpy(*ptr, src, nof_bytes*8*sizeof(uint8_t));
|
||||
*ptr += nof_bytes*8;
|
||||
*ptr += nof_bytes;
|
||||
}
|
||||
|
||||
bool sch_subh::read_subheader(uint8_t** ptr)
|
||||
{
|
||||
// Skip R
|
||||
*ptr += 2;
|
||||
bool e_bit = srslte_bit_unpack(ptr, 1)?true:false;
|
||||
lcid = srslte_bit_unpack(ptr, 5);
|
||||
bool e_bit = (bool) *(*ptr + 0) & 0x20;
|
||||
lcid = (uint8_t) *(*ptr + 0) & 0x1f;
|
||||
if (is_sdu()) {
|
||||
if (e_bit) {
|
||||
F_bit = srslte_bit_unpack(ptr, 1)?true:false;
|
||||
nof_bytes = srslte_bit_unpack(ptr, F_bit?15:7);
|
||||
F_bit = (bool) *(*ptr + 1) & 0x80;
|
||||
nof_bytes = (uint32_t)*(*ptr + 1) & 0x7f;
|
||||
if (F_bit) {
|
||||
nof_bytes = nof_bytes<<8 | (uint32_t) *(*ptr + 2) & 0xff;
|
||||
}
|
||||
} else {
|
||||
nof_bytes = 0;
|
||||
F_bit = 0;
|
||||
|
@ -498,16 +502,34 @@ bool sch_subh::read_subheader(uint8_t** ptr)
|
|||
}
|
||||
void sch_subh::read_payload(uint8_t** ptr)
|
||||
{
|
||||
if (is_sdu()) {
|
||||
sdu_payload_ptr = *ptr;
|
||||
} else {
|
||||
memcpy(ce_payload, *ptr, 8*nof_bytes*sizeof(uint8_t));
|
||||
}
|
||||
*ptr += nof_bytes*8;
|
||||
payload = *ptr;
|
||||
*ptr += nof_bytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Table 6.1.3.1-1 Buffer size levels for BSR
|
||||
uint32_t btable[61] = {
|
||||
10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132,
|
||||
1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4667, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304,
|
||||
42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125};
|
||||
|
||||
uint8_t sch_subh::buff_size_table(uint32_t buffer_size) {
|
||||
if (buffer_size == 0) {
|
||||
return 0;
|
||||
} else if (buffer_size > 150000) {
|
||||
return 63;
|
||||
} else {
|
||||
for (int i=0;i<61;i++) {
|
||||
if (buffer_size < btable[i]) {
|
||||
return 1+i;
|
||||
}
|
||||
}
|
||||
return 62;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -552,15 +574,12 @@ void rar_pdu::set_backoff(uint8_t bi)
|
|||
}
|
||||
|
||||
// Section 6.1.5
|
||||
bool rar_pdu::write_packet(uint8_t* ptr)
|
||||
bool rar_pdu::write_packet(uint8_t* ptr, rlc_interface_mac *rlc)
|
||||
{
|
||||
// Write Backoff Indicator, if any
|
||||
if (has_backoff_indicator) {
|
||||
if (nof_subheaders > 0) {
|
||||
srslte_bit_pack(1, &ptr, 1); // E
|
||||
srslte_bit_pack(0, &ptr, 1); // T
|
||||
srslte_bit_pack(0, &ptr, 2); // R, R
|
||||
srslte_bit_pack(backoff_indicator, &ptr, 4);
|
||||
*(ptr) = 1<<7 | backoff_indicator&0xf;
|
||||
}
|
||||
}
|
||||
// Write RAR subheaders
|
||||
|
@ -569,10 +588,10 @@ bool rar_pdu::write_packet(uint8_t* ptr)
|
|||
}
|
||||
// Write payload
|
||||
for (int i=0;i<nof_subheaders;i++) {
|
||||
subheaders[i].write_payload(&ptr);
|
||||
subheaders[i].write_payload(&ptr, rlc);
|
||||
}
|
||||
// Set paddint to zeros (if any)
|
||||
bzero(ptr, rem_len*sizeof(uint8_t)*8);
|
||||
bzero(ptr, rem_len*sizeof(uint8_t));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -620,63 +639,45 @@ void rar_subh::set_temp_crnti(uint16_t temp_rnti_)
|
|||
// Section 6.2.2
|
||||
void rar_subh::write_subheader(uint8_t** ptr, bool is_last)
|
||||
{
|
||||
srslte_bit_pack(is_last?0:1, ptr, 1); // E
|
||||
srslte_bit_pack(1, ptr, 1); // T
|
||||
srslte_bit_pack(preamble, ptr, 6); // RAPID
|
||||
*(*ptr + 0) = (uint8_t) (is_last<<7 | 1<<6 | preamble & 0x3f);
|
||||
}
|
||||
// Section 6.2.3
|
||||
void rar_subh::write_payload(uint8_t** ptr)
|
||||
void rar_subh::write_payload(uint8_t** ptr, rlc_interface_mac *rlc)
|
||||
{
|
||||
srslte_bit_pack(0, ptr, 1); // R
|
||||
srslte_bit_pack(ta, ptr, 11); // Timing Adv Cmd
|
||||
memcpy(*ptr, grant, 20*sizeof(uint8_t)); // UL grant
|
||||
*ptr += 20;
|
||||
srslte_bit_pack(temp_rnti, ptr, 16); // Temp C-RNTI
|
||||
*(*ptr + 0) = (uint8_t) (ta&0x7f0)>>4;
|
||||
*(*ptr + 1) = (uint8_t) (ta&0xf) <<4 | grant[0]<<3 | grant[1] << 2 | grant[2] << 1 | grant[3];
|
||||
uint8_t *x = &grant[4];
|
||||
*(*ptr + 2) = (uint8_t) srslte_bit_unpack(&x, 8);
|
||||
*(*ptr + 3) = (uint8_t) srslte_bit_unpack(&x, 8);
|
||||
*(*ptr + 4) = (uint8_t) ((temp_rnti&0xff00) >> 8);
|
||||
*(*ptr + 5) = (uint8_t) (temp_rnti&0x00ff);
|
||||
}
|
||||
|
||||
void rar_subh::read_payload(uint8_t** ptr)
|
||||
{
|
||||
*ptr += 1; // R
|
||||
ta = srslte_bit_unpack(ptr, 11); // Timing Adv Cmd
|
||||
memcpy(grant, *ptr, 20*sizeof(uint8_t)); // UL Grant
|
||||
*ptr += 20;
|
||||
temp_rnti = srslte_bit_unpack(ptr, 16); // Temp C-RNTI
|
||||
ta = *(*ptr + 0)&0x7f << 4 | (*(*ptr + 1)&0xf0)>>4;
|
||||
grant[0] = *(*ptr + 1)&0x8;
|
||||
grant[1] = *(*ptr + 1)&0x4;
|
||||
grant[2] = *(*ptr + 1)&0x2;
|
||||
grant[3] = *(*ptr + 1)&0x1;
|
||||
uint8_t *x = &grant[4];
|
||||
srslte_bit_pack(*(*ptr+2), &x, 8);
|
||||
srslte_bit_pack(*(*ptr+3), &x, 8);
|
||||
temp_rnti = *(*ptr + 4)<<8 | *(*ptr + 5);
|
||||
}
|
||||
|
||||
bool rar_subh::read_subheader(uint8_t** ptr)
|
||||
{
|
||||
bool e_bit = srslte_bit_unpack(ptr, 1); // E
|
||||
bool type = srslte_bit_unpack(ptr, 1); // T
|
||||
bool e_bit = *(*ptr + 0) & 0x80;
|
||||
bool type = *(*ptr + 0) & 0x40;
|
||||
if (type) {
|
||||
preamble = srslte_bit_unpack(ptr, 6); // RAPID
|
||||
preamble = *(*ptr + 0) & 0x3f;
|
||||
} else {
|
||||
// Read Backoff
|
||||
*ptr += 2; // R, R
|
||||
((rar_pdu*)parent)->set_backoff((uint8_t) srslte_bit_unpack(ptr, 4));
|
||||
((rar_pdu*)parent)->set_backoff(*(*ptr + 0) & 0xf);
|
||||
}
|
||||
return e_bit;
|
||||
}
|
||||
|
||||
|
||||
// Table 6.1.3.1-1 Buffer size levels for BSR
|
||||
uint32_t btable[61] = {
|
||||
10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132,
|
||||
1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4667, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304,
|
||||
42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125};
|
||||
|
||||
uint8_t sch_subh::buff_size_table(uint32_t buffer_size) {
|
||||
if (buffer_size == 0) {
|
||||
return 0;
|
||||
} else if (buffer_size > 150000) {
|
||||
return 63;
|
||||
} else {
|
||||
for (int i=0;i<61;i++) {
|
||||
if (buffer_size < btable[i]) {
|
||||
return 1+i;
|
||||
}
|
||||
}
|
||||
return 62;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
*/
|
||||
|
||||
#include "srsapps/ue/mac/proc_bsr.h"
|
||||
#include "srsapps/ue/mac/mac_params.h"
|
||||
#include "srsapps/ue/mac/mac.h"
|
||||
#include "srsapps/ue/mac/mux.h"
|
||||
|
||||
|
@ -48,11 +47,11 @@ bsr_proc::bsr_proc()
|
|||
triggered_bsr_type=NONE;
|
||||
}
|
||||
|
||||
void bsr_proc::init(log* log_h_, timers *timers_db_, mac_params* params_db_, mac_io *mac_io_h_)
|
||||
void bsr_proc::init(rlc_interface_mac *rlc_, log* log_h_, mac_params* params_db_, timers *timers_db_)
|
||||
{
|
||||
log_h = log_h_;
|
||||
rlc = rlc_;
|
||||
params_db = params_db_;
|
||||
mac_io_h = mac_io_h_;
|
||||
timers_db = timers_db_;
|
||||
initiated = true;
|
||||
}
|
||||
|
@ -85,12 +84,12 @@ void bsr_proc::timer_expired(uint32_t timer_id) {
|
|||
bool bsr_proc::check_highest_channel() {
|
||||
int pending_data_lcid = -1;
|
||||
|
||||
for (int i=0;i<mac_io::NOF_UL_LCH && pending_data_lcid == -1;i++) {
|
||||
for (int i=0;i<MAX_LCID && pending_data_lcid == -1;i++) {
|
||||
if (lcg[i] >= 0) {
|
||||
if (!mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->isempty()) {
|
||||
if (rlc->get_buffer_state(i) > 0) {
|
||||
pending_data_lcid = i;
|
||||
for (int j=0;j<mac_io::NOF_UL_LCH;j++) {
|
||||
if (!mac_io_h->get(j+mac_io::MAC_LCH_CCCH_UL)->isempty()) {
|
||||
for (int j=0;j<MAX_LCID;j++) {
|
||||
if (rlc->get_buffer_state(j) > 0) {
|
||||
if (priorities[j] > priorities[i]) {
|
||||
pending_data_lcid = -1;
|
||||
}
|
||||
|
@ -101,7 +100,7 @@ bool bsr_proc::check_highest_channel() {
|
|||
}
|
||||
if (pending_data_lcid >= 0) {
|
||||
// If there is new data available for this logical channel
|
||||
uint32_t nbytes = mac_io_h->get(pending_data_lcid+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8;
|
||||
uint32_t nbytes = rlc->get_buffer_state(pending_data_lcid);
|
||||
if (nbytes > last_pending_data[pending_data_lcid])
|
||||
{
|
||||
if (triggered_bsr_type != REGULAR) {
|
||||
|
@ -119,16 +118,16 @@ bool bsr_proc::check_single_channel() {
|
|||
uint32_t pending_data_lcid = 0;
|
||||
uint32_t nof_nonzero_lcid = 0;
|
||||
|
||||
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
|
||||
for (int i=0;i<MAX_LCID;i++) {
|
||||
if (lcg[i] >= 0) {
|
||||
if (!mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->isempty()) {
|
||||
if (rlc->get_buffer_state(i) > 0) {
|
||||
pending_data_lcid = i;
|
||||
nof_nonzero_lcid++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nof_nonzero_lcid == 1) {
|
||||
uint32_t nbytes = mac_io_h->get(pending_data_lcid+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8;
|
||||
uint32_t nbytes = rlc->get_buffer_state(pending_data_lcid);
|
||||
// If there is new data available for this logical channel
|
||||
if (nbytes > last_pending_data[pending_data_lcid]) {
|
||||
triggered_bsr_type = REGULAR;
|
||||
|
@ -140,8 +139,8 @@ bool bsr_proc::check_single_channel() {
|
|||
}
|
||||
|
||||
void bsr_proc::update_pending_data() {
|
||||
for (int i=0;i<mac_io_h->NOF_UL_LCH;i++) {
|
||||
last_pending_data[i] = mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8;
|
||||
for (int i=0;i<MAX_LCID;i++) {
|
||||
last_pending_data[i] = rlc->get_buffer_state(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,9 +148,9 @@ bool bsr_proc::generate_bsr(bsr_t *bsr, uint32_t nof_padding_bytes) {
|
|||
bool ret = false;
|
||||
uint32_t nof_lcg=0;
|
||||
bzero(bsr, sizeof(bsr_t));
|
||||
for (int i=0;i<mac_io_h->NOF_UL_LCH;i++) {
|
||||
for (int i=0;i<MAX_LCID;i++) {
|
||||
if (lcg[i] >= 0) {
|
||||
uint32_t n = mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8;
|
||||
uint32_t n = rlc->get_buffer_state(i);
|
||||
bsr->buff_size[lcg[i]] += n;
|
||||
if (n > 0) {
|
||||
nof_lcg++;
|
||||
|
@ -196,16 +195,16 @@ void bsr_proc::step(uint32_t tti)
|
|||
}
|
||||
|
||||
if (!timer_periodic) {
|
||||
if (params_db->get_param(mac_params::BSR_TIMER_PERIODIC)) {
|
||||
if (params_db->get_param(mac_interface_params::BSR_TIMER_PERIODIC)) {
|
||||
timer_periodic = true;
|
||||
timers_db->get(mac::BSR_TIMER_PERIODIC)->set(this, params_db->get_param(mac_params::BSR_TIMER_PERIODIC));
|
||||
timers_db->get(mac::BSR_TIMER_PERIODIC)->set(this, params_db->get_param(mac_interface_params::BSR_TIMER_PERIODIC));
|
||||
}
|
||||
}
|
||||
|
||||
if (!timer_retx) {
|
||||
if (params_db->get_param(mac_params::BSR_TIMER_RETX)) {
|
||||
if (params_db->get_param(mac_interface_params::BSR_TIMER_RETX)) {
|
||||
timer_retx = true;
|
||||
timers_db->get(mac::BSR_TIMER_RETX)->set(this, params_db->get_param(mac_params::BSR_TIMER_RETX));
|
||||
timers_db->get(mac::BSR_TIMER_RETX)->set(this, params_db->get_param(mac_interface_params::BSR_TIMER_RETX));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,8 +221,8 @@ void bsr_proc::step(uint32_t tti)
|
|||
if ((tti - last_print)%10240 > 40) {
|
||||
char str[128];
|
||||
bzero(str, 128);
|
||||
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
|
||||
sprintf(str, "%s%d (%d), ", str, mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8, last_pending_data[i]);
|
||||
for (int i=0;i<MAX_LCID;i++) {
|
||||
sprintf(str, "%s%d (%d), ", str, rlc->get_buffer_state(i), last_pending_data[i]);
|
||||
}
|
||||
Info("QUEUE status: %s\n", str);
|
||||
last_print = tti;
|
||||
|
@ -257,15 +256,10 @@ uint32_t bsr_proc::need_to_send_bsr_on_ul_grant(uint32_t grant_size)
|
|||
{
|
||||
uint32_t bsr_sz = 0;
|
||||
if (triggered_bsr_type == PERIODIC || triggered_bsr_type == REGULAR) {
|
||||
uint32_t total_data = 0;
|
||||
/* Check if grant + MAC SDU headers is enough to accomodate all pending data */
|
||||
for (int i=0;i<mac_io_h->NOF_UL_LCH && total_data < grant_size;i++) {
|
||||
uint32_t idx = 0;
|
||||
uint32_t sdu_len = 0;
|
||||
while(mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pop(&sdu_len, idx) && total_data < grant_size) {
|
||||
idx++;
|
||||
total_data += sch_pdu::size_plus_header_sdu(sdu_len/8);
|
||||
}
|
||||
uint32_t total_data = 0;
|
||||
for (int i=0;i<MAX_LCID && total_data < grant_size;i++) {
|
||||
total_data += sch_pdu::size_plus_header_sdu(rlc->get_buffer_state(i));
|
||||
}
|
||||
total_data--; // Because last SDU has no size header
|
||||
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "srsapps/ue/mac/mac_params.h"
|
||||
#include "srsapps/ue/mac/mac_io.h"
|
||||
#include "srsapps/ue/mac/proc_ra.h"
|
||||
#include "srsapps/ue/mac/mac.h"
|
||||
#include "srsapps/ue/mac/mux.h"
|
||||
|
@ -47,26 +45,7 @@ uint32_t backoff_table[16] = {0, 10, 20, 30, 40, 60, 80, 120, 160, 240, 320, 480
|
|||
// Table 7.6-1: DELTA_PREAMBLE values.
|
||||
int delta_preamble_db_table[5] = {0, 0, -3, -3, 8};
|
||||
|
||||
|
||||
void* init_prach_thread(void *arg) {
|
||||
ra_proc* ra = (ra_proc*) arg;
|
||||
return ra->run_prach_thread();
|
||||
}
|
||||
|
||||
void* ra_proc::run_prach_thread() {
|
||||
pthread_mutex_lock(&mutex);
|
||||
while(!start_prach_init) {
|
||||
pthread_cond_wait(&cond, &mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
if (phy_h->init_prach()) {
|
||||
return (void*) 0;
|
||||
} else {
|
||||
return (void*) -1;
|
||||
}
|
||||
|
||||
}
|
||||
bool ra_proc::init(mac_params* params_db_, phy* phy_h_, srslte::log* log_h_, srslte::timers* timers_db_,
|
||||
bool ra_proc::init(phy_interface* phy_h_, log* log_h_, mac_params* params_db_, timers* timers_db_,
|
||||
mux* mux_unit_, demux* demux_unit_)
|
||||
{
|
||||
phy_h = phy_h_;
|
||||
|
@ -75,12 +54,8 @@ bool ra_proc::init(mac_params* params_db_, phy* phy_h_, srslte::log* log_h_, srs
|
|||
timers_db = timers_db_;
|
||||
mux_unit = mux_unit_;
|
||||
demux_unit= demux_unit_;
|
||||
start_prach_init = false;
|
||||
if (pthread_create(&pt_init_prach, NULL, init_prach_thread, this)) {
|
||||
perror("pthread_create");
|
||||
}
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
pthread_cond_init(&cond, NULL);
|
||||
srslte_softbuffer_rx_init(&softbuffer_rar, 10);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
|
@ -96,32 +71,32 @@ void ra_proc::start_pcap(mac_pcap* pcap_)
|
|||
void ra_proc::read_params() {
|
||||
|
||||
// Read initialization parameters
|
||||
configIndex = params_db->get_param(mac_params::RA_CONFIGINDEX);
|
||||
preambleIndex = params_db->get_param(mac_params::RA_PREAMBLEINDEX);
|
||||
maskIndex = params_db->get_param(mac_params::RA_MASKINDEX);
|
||||
nof_preambles = params_db->get_param(mac_params::RA_NOFPREAMBLES);
|
||||
configIndex = params_db->get_param(mac_interface_params::RA_CONFIGINDEX);
|
||||
preambleIndex = params_db->get_param(mac_interface_params::RA_PREAMBLEINDEX);
|
||||
maskIndex = params_db->get_param(mac_interface_params::RA_MASKINDEX);
|
||||
nof_preambles = params_db->get_param(mac_interface_params::RA_NOFPREAMBLES);
|
||||
if (!nof_preambles || nof_preambles > 64) {
|
||||
nof_preambles = 64;
|
||||
}
|
||||
nof_groupA_preambles = params_db->get_param(mac_params::RA_NOFGROUPAPREAMBLES);
|
||||
nof_groupA_preambles = params_db->get_param(mac_interface_params::RA_NOFGROUPAPREAMBLES);
|
||||
if (!nof_groupA_preambles) {
|
||||
nof_groupA_preambles = nof_preambles;
|
||||
nof_groupA_preambles = nof_preambles;
|
||||
}
|
||||
if (nof_groupA_preambles > nof_preambles) {
|
||||
nof_groupA_preambles = nof_preambles;
|
||||
nof_groupA_preambles = nof_preambles;
|
||||
}
|
||||
nof_groupB_preambles = nof_preambles - nof_groupA_preambles;
|
||||
if (nof_groupB_preambles) {
|
||||
messagePowerOffsetGroupB = params_db->get_param(mac_params::RA_MESSAGEPOWEROFFSETB);
|
||||
messageSizeGroupA = params_db->get_param(mac_params::RA_MESSAGESIZEA);
|
||||
Pcmax = params_db->get_param(mac_params::RA_PCMAX);
|
||||
deltaPreambleMsg3 = params_db->get_param(mac_params::RA_DELTAPREAMBLEMSG3);
|
||||
messagePowerOffsetGroupB= params_db->get_param(mac_interface_params::RA_MESSAGEPOWEROFFSETB);
|
||||
messageSizeGroupA = params_db->get_param(mac_interface_params::RA_MESSAGESIZEA);
|
||||
Pcmax = params_db->get_param(mac_interface_params::RA_PCMAX);
|
||||
deltaPreambleMsg3 = params_db->get_param(mac_interface_params::RA_DELTAPREAMBLEMSG3);
|
||||
}
|
||||
responseWindowSize = params_db->get_param(mac_params::RA_RESPONSEWINDOW);
|
||||
powerRampingStep = params_db->get_param(mac_params::RA_POWERRAMPINGSTEP);
|
||||
preambleTransMax = params_db->get_param(mac_params::RA_PREAMBLETRANSMAX);
|
||||
iniReceivedTargetPower = params_db->get_param(mac_params::RA_INITRECEIVEDPOWER);
|
||||
contentionResolutionTimer = params_db->get_param(mac_params::RA_CONTENTIONTIMER);
|
||||
responseWindowSize = params_db->get_param(mac_interface_params::RA_RESPONSEWINDOW);
|
||||
powerRampingStep = params_db->get_param(mac_interface_params::RA_POWERRAMPINGSTEP);
|
||||
preambleTransMax = params_db->get_param(mac_interface_params::RA_PREAMBLETRANSMAX);
|
||||
iniReceivedTargetPower = params_db->get_param(mac_interface_params::RA_INITRECEIVEDPOWER);
|
||||
contentionResolutionTimer = params_db->get_param(mac_interface_params::RA_CONTENTIONTIMER);
|
||||
|
||||
delta_preamble_db = delta_preamble_db_table[configIndex%5];
|
||||
|
||||
|
@ -154,9 +129,9 @@ bool ra_proc::is_error() {
|
|||
|
||||
const char* state_str[11] = {"Idle",
|
||||
"RA Initializat.: ",
|
||||
"RA Initial.Wait: ",
|
||||
"RA ResSelection: ",
|
||||
"RA PreambleTx : ",
|
||||
"RA PDCCH setup : ",
|
||||
"RA PreambleRx : ",
|
||||
"RA ResponseErr : ",
|
||||
"RA BackoffWait : ",
|
||||
|
@ -199,28 +174,9 @@ void ra_proc::step_initialization() {
|
|||
mux_unit->msg3_flush();
|
||||
backoff_param_ms = 0;
|
||||
|
||||
// Instruct phy prach init thread to start initialization
|
||||
pthread_mutex_lock(&mutex);
|
||||
start_prach_init = true;
|
||||
pthread_cond_signal(&cond);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
state = INITIALIZATION_WAIT;
|
||||
|
||||
}
|
||||
|
||||
void ra_proc::step_initialization_wait() {
|
||||
int n = pthread_kill(pt_init_prach, 0);
|
||||
if (n) {
|
||||
void *status;
|
||||
pthread_join(pt_init_prach, &status);
|
||||
if (status) {
|
||||
rError("Initializing PRACH on PHY\n");
|
||||
state = RA_PROBLEM;
|
||||
} else {
|
||||
rInfo("PRACH init OK\n");
|
||||
state = RESOURCE_SELECTION;
|
||||
}
|
||||
}
|
||||
// Instruct phy to configure PRACH
|
||||
phy_h->configure_prach_params();
|
||||
state = RESOURCE_SELECTION;
|
||||
}
|
||||
|
||||
void ra_proc::step_resource_selection() {
|
||||
|
@ -249,7 +205,8 @@ void ra_proc::step_resource_selection() {
|
|||
sel_maskIndex = 0;
|
||||
}
|
||||
|
||||
rInfo("Selected preambleIndex=%d maskIndex=%d nof_GroupApreambles=%d\n", sel_preamble, sel_maskIndex,nof_groupA_preambles);
|
||||
rInfo("Selected preambleIndex=%d maskIndex=%d nof_GroupApreambles=%d\n",
|
||||
sel_preamble, sel_maskIndex,nof_groupA_preambles);
|
||||
state = PREAMBLE_TRANSMISSION;
|
||||
}
|
||||
|
||||
|
@ -258,116 +215,111 @@ void ra_proc::step_preamble_transmission() {
|
|||
delta_preamble_db +
|
||||
(preambleTransmissionCounter-1)*powerRampingStep;
|
||||
|
||||
phy_h->send_prach(sel_preamble, sel_maskIndex - 1, received_target_power_dbm);
|
||||
phy_h->prach_send(sel_preamble, sel_maskIndex - 1, received_target_power_dbm);
|
||||
rInfo("Selected received_target_power_dbm=%d dBm\n", received_target_power_dbm);
|
||||
state = RESPONSE_RECEPTION;
|
||||
state = PDCCH_SETUP;
|
||||
}
|
||||
|
||||
void ra_proc::step_pdcch_setup() {
|
||||
int ra_tti = phy_h->prach_tx_tti();
|
||||
if (ra_tti > 0) {
|
||||
ra_rnti = 1+ra_tti%10;
|
||||
phy_h->pdcch_dl_search(SRSLTE_RNTI_RAR, ra_rnti, ra_tti+3, responseWindowSize);
|
||||
state = RESPONSE_RECEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
void ra_proc::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action)
|
||||
{
|
||||
if (grant.n_bytes < MAX_RAR_PDU_LEN) {
|
||||
rInfo("DL grant found RA-RNTI=%d\n", ra_rnti);
|
||||
action->decode_enabled = true;
|
||||
action->default_ack = false;
|
||||
action->generate_ack = false;
|
||||
action->payload_ptr = rar_pdu_buffer;
|
||||
action->rnti = grant.rnti;
|
||||
memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t));
|
||||
action->rv = grant.rv;
|
||||
action->softbuffer = &softbuffer_rar;
|
||||
rar_grant_nbytes = grant.n_bytes;
|
||||
rar_grant_tti = grant.tti;
|
||||
if (action->rv == 0) {
|
||||
srslte_softbuffer_rx_reset(&softbuffer_rar);
|
||||
}
|
||||
} else {
|
||||
rError("Received RAR grant exceeds buffer length (%d>%d)\n", grant.n_bytes, MAX_RAR_PDU_LEN);
|
||||
action->decode_enabled = false;
|
||||
state = RESPONSE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
void ra_proc::tb_decoded_ok() {
|
||||
if (pcap) {
|
||||
pcap->write_dl_crnti(rar_pdu_buffer, rar_grant_nbytes, ra_rnti, true, rar_grant_tti);
|
||||
}
|
||||
|
||||
rDebug("RAR decoded successfully TBS=%d\n", rar_grant_nbytes);
|
||||
|
||||
rar_pdu_msg.init(rar_grant_nbytes);
|
||||
rar_pdu_msg.parse_packet(rar_pdu_buffer);
|
||||
|
||||
// Set Backoff parameter
|
||||
if (rar_pdu_msg.has_backoff()) {
|
||||
backoff_param_ms = backoff_table[rar_pdu_msg.get_backoff()%16];
|
||||
} else {
|
||||
backoff_param_ms = 0;
|
||||
}
|
||||
|
||||
while(rar_pdu_msg.next()) {
|
||||
if (rar_pdu_msg.get()->get_rapid() == sel_preamble) {
|
||||
rInfo("Received RAPID=%d\n", sel_preamble);
|
||||
|
||||
process_timeadv_cmd(rar_pdu_msg.get()->get_ta_cmd());
|
||||
|
||||
// FIXME: Indicate received target power
|
||||
//phy_h->set_target_power_rar(iniReceivedTargetPower, (preambleTransmissionCounter-1)*powerRampingStep);
|
||||
|
||||
uint8_t grant[rar_subh::RAR_GRANT_LEN];
|
||||
rar_pdu_msg.get()->get_sched_grant(grant);
|
||||
|
||||
phy_h->set_rar_grant(rar_grant_tti, grant);
|
||||
|
||||
if (preambleIndex > 0) {
|
||||
// Preamble selected by Network
|
||||
state = COMPLETION;
|
||||
} else {
|
||||
// Preamble selected by UE MAC
|
||||
params_db->set_param(mac_interface_params::RNTI_TEMP, rar_pdu_msg.get()->get_temp_crnti());
|
||||
if (first_rar_received) {
|
||||
first_rar_received = false;
|
||||
|
||||
// Save transmitted C-RNTI (if any)
|
||||
transmitted_crnti = params_db->get_param(mac_interface_params::RNTI_C);
|
||||
|
||||
// Save transmitted UE contention id, as defined by higher layers
|
||||
transmitted_contention_id = params_db->get_param(mac_interface_params::CONTENTION_ID);
|
||||
params_db->set_param(mac_interface_params::CONTENTION_ID, 0);
|
||||
|
||||
// If we have a C-RNTI, tell Mux unit to append C-RNTI CE if no CCCH SDU transmission
|
||||
if (transmitted_crnti) {
|
||||
mux_unit->append_crnti_ce_next_tx(transmitted_crnti);
|
||||
}
|
||||
}
|
||||
rDebug("Going to Contention Resolution state\n");
|
||||
state = CONTENTION_RESOLUTION;
|
||||
|
||||
// Start contention resolution timer
|
||||
timers_db->get(mac::CONTENTION_TIMER)->reset();
|
||||
timers_db->get(mac::CONTENTION_TIMER)->run();
|
||||
}
|
||||
} else {
|
||||
rDebug("Found RAR for preamble %d\n", rar_pdu_msg.get()->get_rapid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ra_proc::step_response_reception() {
|
||||
int ra_tti = phy_h->get_prach_transmitted_tti();
|
||||
if (ra_tti > 0) {
|
||||
|
||||
ra_rnti = 1+ra_tti%10; // f_id=0 for FDD
|
||||
dl_sched_grant rar_grant(ra_rnti);
|
||||
uint32_t interval_ra = srslte_tti_interval(tti, ra_tti);
|
||||
|
||||
// Try to decode RAR only within the RA response window
|
||||
if (interval_ra >= 3 && interval_ra <= 3+responseWindowSize) {
|
||||
|
||||
// Get DL grant for RA-RNTI
|
||||
dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti);
|
||||
if (dl_buffer->get_dl_grant(&rar_grant))
|
||||
{
|
||||
rInfo("DL grant found RA-RNTI=%d\n", ra_rnti);
|
||||
if (rar_grant.get_tbs() > MAX_RAR_PDU_LEN) {
|
||||
rError("RAR PDU exceeds local RAR PDU buffer (%d>%d)\n", rar_grant.get_tbs(), MAX_RAR_PDU_LEN);
|
||||
state = RESPONSE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
// Decode packet
|
||||
dl_buffer->reset_softbuffer();
|
||||
bool ack = dl_buffer->decode_data(&rar_grant, rar_pdu_buffer);
|
||||
if (pcap) {
|
||||
pcap->write_dl_crnti(payload, rar_grant.get_tbs()/8, ra_rnti, ack, tti);
|
||||
}
|
||||
|
||||
if (ack) {
|
||||
rDebug("RAR decoded successfully TBS=%d\n", rar_grant.get_tbs());
|
||||
|
||||
rar_pdu_msg.init(rar_grant.get_tbs()/8);
|
||||
rar_pdu_msg.parse_packet(rar_pdu_buffer);
|
||||
|
||||
// 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);
|
||||
|
||||
// Indicate grant to PHY layer. RAR grants have 6 sf delay (4 is the default delay)
|
||||
uint8_t grant[rar_subh::RAR_GRANT_LEN];
|
||||
rar_pdu_msg.get()->get_sched_grant(grant);
|
||||
phy_h->get_dl_buffer(tti+2)->set_rar_grant(grant);
|
||||
|
||||
if (preambleIndex > 0) {
|
||||
// Preamble selected by Network
|
||||
state = COMPLETION;
|
||||
} else {
|
||||
// Preamble selected by UE MAC
|
||||
params_db->set_param(mac_params::RNTI_TEMP, rar_pdu_msg.get()->get_temp_crnti());
|
||||
if (first_rar_received) {
|
||||
first_rar_received = false;
|
||||
|
||||
// Save transmitted C-RNTI (if any)
|
||||
transmitted_crnti = params_db->get_param(mac_params::RNTI_C);
|
||||
|
||||
// Save transmitted UE contention id, as defined by higher layers
|
||||
transmitted_contention_id = params_db->get_param(mac_params::CONTENTION_ID);
|
||||
params_db->set_param(mac_params::CONTENTION_ID, 0);
|
||||
|
||||
// If we have a C-RNTI, tell Mux unit to append C-RNTI CE if no CCCH SDU transmission
|
||||
if (transmitted_crnti) {
|
||||
mux_unit->append_crnti_ce_next_tx(transmitted_crnti);
|
||||
}
|
||||
|
||||
// Get TransportBlock size for the grant
|
||||
ul_sched_grant msg3_grant(sched_grant::RNTI_TYPE_TEMP, rar_pdu_msg.get()->get_temp_crnti());
|
||||
phy_h->get_dl_buffer(tti+2)->get_ul_grant(&msg3_grant);
|
||||
|
||||
// Move MAC PDU from Multiplexing and assembly unit to Msg3
|
||||
rInfo("Generating Msg3 for TBS=%d\n", msg3_grant.get_tbs());
|
||||
mux_unit->pdu_move_to_msg3(msg3_grant.get_tbs()); // 56 is the minimum grant provided
|
||||
}
|
||||
rDebug("Going to Contention Resolution state\n");
|
||||
state = CONTENTION_RESOLUTION;
|
||||
|
||||
// Start contention resolution timer
|
||||
timers_db->get(mac::CONTENTION_TIMER)->reset();
|
||||
timers_db->get(mac::CONTENTION_TIMER)->run();
|
||||
}
|
||||
} else {
|
||||
rDebug("Found RAR for preamble %d\n", rar_pdu_msg.get()->get_rapid());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
srslte_verbose = SRSLTE_VERBOSE_NONE;
|
||||
}
|
||||
if (interval_ra > 3+responseWindowSize && interval_ra < 10000) {
|
||||
rInfo("Timeout while trying to receive RAR\n");
|
||||
state = RESPONSE_ERROR;
|
||||
}
|
||||
}
|
||||
// do nothing. Processing done in tb_decoded_ok()
|
||||
}
|
||||
|
||||
void ra_proc::step_response_error() {
|
||||
|
@ -377,7 +329,7 @@ void ra_proc::step_response_error() {
|
|||
rError("Maximum number of transmissions reached (%d)\n", preambleTransMax);
|
||||
state = RA_PROBLEM;
|
||||
} else {
|
||||
backoff_interval_start = tti;
|
||||
backoff_interval_start = phy_h->get_current_tti();
|
||||
if (backoff_param_ms) {
|
||||
backoff_inteval = rand()%backoff_param_ms;
|
||||
} else {
|
||||
|
@ -394,7 +346,7 @@ void ra_proc::step_response_error() {
|
|||
}
|
||||
|
||||
void ra_proc::step_backoff_wait() {
|
||||
if (srslte_tti_interval(tti, backoff_interval_start) >= backoff_inteval) {
|
||||
if (srslte_tti_interval(phy_h->get_current_tti(), backoff_interval_start) >= backoff_inteval) {
|
||||
state = RESOURCE_SELECTION;
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +363,7 @@ void ra_proc::step_contention_resolution() {
|
|||
start_mode == PDCCH_ORDER)
|
||||
{
|
||||
timers_db->get(mac::CONTENTION_TIMER)->stop();
|
||||
params_db->set_param(mac_params::RNTI_TEMP, 0);
|
||||
params_db->set_param(mac_interface_params::RNTI_TEMP, 0);
|
||||
state = COMPLETION;
|
||||
}
|
||||
pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED;
|
||||
|
@ -428,7 +380,7 @@ void ra_proc::step_contention_resolution() {
|
|||
if (transmitted_contention_id == rx_contention_id) {
|
||||
rDebug("MAC PDU Contention Resolution ID matches the one transmitted in CCCH SDU\n");
|
||||
// UE Contention Resolution ID included in MAC CE matches the CCCH SDU transmitted in Msg3
|
||||
params_db->set_param(mac_params::RNTI_C, params_db->get_param(mac_params::RNTI_TEMP));
|
||||
params_db->set_param(mac_interface_params::RNTI_C, params_db->get_param(mac_interface_params::RNTI_TEMP));
|
||||
// finish the disassembly and demultiplexing of the MAC PDU
|
||||
demux_unit->demultiplex_pending_pdu();
|
||||
state = COMPLETION;
|
||||
|
@ -441,7 +393,7 @@ void ra_proc::step_contention_resolution() {
|
|||
// FIXME: Need to flush Msg3 HARQ buffer. Why?
|
||||
state = RESPONSE_ERROR;
|
||||
}
|
||||
params_db->set_param(mac_params::RNTI_TEMP, 0);
|
||||
params_db->set_param(mac_interface_params::RNTI_TEMP, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -451,15 +403,14 @@ void ra_proc::step_contention_resolution() {
|
|||
}
|
||||
|
||||
void ra_proc::step_completition() {
|
||||
params_db->set_param(mac_params::RA_PREAMBLEINDEX, 0);
|
||||
params_db->set_param(mac_params::RA_MASKINDEX, 0);
|
||||
params_db->set_param(mac_interface_params::RA_PREAMBLEINDEX, 0);
|
||||
params_db->set_param(mac_interface_params::RA_MASKINDEX, 0);
|
||||
mux_unit->msg3_flush();
|
||||
msg3_transmitted = false;
|
||||
}
|
||||
|
||||
void ra_proc::step(uint32_t tti_)
|
||||
{
|
||||
tti = tti_;
|
||||
if (is_running()) {
|
||||
switch(state) {
|
||||
case IDLE:
|
||||
|
@ -467,15 +418,15 @@ void ra_proc::step(uint32_t tti_)
|
|||
case INITIALIZATION:
|
||||
step_initialization();
|
||||
break;
|
||||
case INITIALIZATION_WAIT:
|
||||
step_initialization_wait();
|
||||
break;
|
||||
case RESOURCE_SELECTION:
|
||||
step_resource_selection();
|
||||
break;
|
||||
case PREAMBLE_TRANSMISSION:
|
||||
step_preamble_transmission();
|
||||
break;
|
||||
case PDCCH_SETUP:
|
||||
step_pdcch_setup();
|
||||
break;
|
||||
case RESPONSE_RECEPTION:
|
||||
step_response_reception();
|
||||
break;
|
||||
|
@ -529,7 +480,7 @@ void ra_proc::start_rlc_order()
|
|||
void ra_proc::timer_expired(uint32_t timer_id)
|
||||
{
|
||||
rInfo("Contention Resolution Timer expired. Going to Response Error\n");
|
||||
params_db->set_param(mac_params::RNTI_TEMP, 0);
|
||||
params_db->set_param(mac_interface_params::RNTI_TEMP, 0);
|
||||
state = RESPONSE_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ sr_proc::sr_proc() {
|
|||
initiated = false;
|
||||
}
|
||||
|
||||
void sr_proc::init(log* log_h_, mac_params* params_db_, phy* phy_h_)
|
||||
void sr_proc::init(phy_interface* phy_h_, log* log_h_, mac_params* params_db_)
|
||||
{
|
||||
log_h = log_h_;
|
||||
params_db = params_db_;
|
||||
|
@ -48,20 +48,19 @@ void sr_proc::init(log* log_h_, mac_params* params_db_, phy* phy_h_)
|
|||
void sr_proc::reset()
|
||||
{
|
||||
is_pending_sr = false;
|
||||
phy_h->send_sr(false);
|
||||
}
|
||||
|
||||
void sr_proc::step(uint32_t tti)
|
||||
{
|
||||
if (initiated) {
|
||||
if (is_pending_sr) {
|
||||
if (params_db->get_param(mac_params::SR_PUCCH_CONFIGURED)) {
|
||||
if (params_db->get_param(mac_interface_params::SR_PUCCH_CONFIGURED)) {
|
||||
if (sr_counter < dsr_transmax) {
|
||||
int last_tx_tti = phy_h->sr_last_tx_tti();
|
||||
if (last_tx_tti >= 0 && last_tx_tti + 4 < tti) {
|
||||
sr_counter++;
|
||||
Info("SR signalling PHY. sr_counter=%d, PHY TTI=%d\n", sr_counter, phy_h->get_current_tti());
|
||||
phy_h->send_sr(true);
|
||||
phy_h->sr_send();
|
||||
}
|
||||
} else {
|
||||
do_ra = true;
|
||||
|
@ -93,7 +92,7 @@ void sr_proc::start()
|
|||
sr_counter = 0;
|
||||
is_pending_sr = true;
|
||||
}
|
||||
dsr_transmax = params_db->get_param(mac_params::SR_TRANS_MAX);
|
||||
dsr_transmax = params_db->get_param(mac_interface_params::SR_TRANS_MAX);
|
||||
Info("SR starting dsrTransMax=%d. sr_counter=%d\n", dsr_transmax, sr_counter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsapps/ue/phy/phy.h"
|
||||
#include "srsapps/common/log.h"
|
||||
|
||||
#include "srsapps/ue/mac/mac_params.h"
|
||||
#include "srsapps/ue/mac/mac.h"
|
||||
#include "srsapps/ue/mac/ul_harq.h"
|
||||
|
||||
|
@ -41,16 +38,15 @@ namespace srslte {
|
|||
*
|
||||
*********************************************************/
|
||||
|
||||
bool ul_harq_entity::init(srslte_cell_t cell, mac_params *params_db_, log *log_h_, timers *timers_db_, mux *mux_unit_) {
|
||||
bool ul_harq_entity::init(log *log_h_, mac_params *params_db_, timers *timers_db_, mux *mux_unit_) {
|
||||
log_h = log_h_;
|
||||
mux_unit = mux_unit_;
|
||||
params_db = params_db_;
|
||||
timers_db = timers_db_;
|
||||
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
|
||||
if (!proc[i].init(cell, this)) {
|
||||
if (!proc[i].init(i, this)) {
|
||||
return false;
|
||||
}
|
||||
proc[i].pid = i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -67,50 +63,83 @@ void ul_harq_entity::reset() {
|
|||
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
|
||||
proc[i].reset();
|
||||
}
|
||||
ul_sps_assig.clear();
|
||||
}
|
||||
void ul_harq_entity::reset_ndi() {
|
||||
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
|
||||
proc[i].reset_ndi();
|
||||
}
|
||||
}
|
||||
bool ul_harq_entity::is_sps(uint32_t pid) {
|
||||
return false;
|
||||
}
|
||||
// Called with no UL grant
|
||||
void ul_harq_entity::run_tti(uint32_t tti, phy *phy_h) {
|
||||
run_tti(tti, NULL, phy_h);
|
||||
}
|
||||
|
||||
// Implements Section 5.4.2.1
|
||||
// Called with UL grant
|
||||
void ul_harq_entity::run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_h)
|
||||
{
|
||||
uint32_t tti_tx = (tti+4)%10240;
|
||||
uint32_t pid = pidof(tti_tx);
|
||||
|
||||
// Receive and route HARQ feedbacks
|
||||
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(phy_h->get_dl_buffer(tti)->decode_ack(proc[pid_harq].get_grant()));
|
||||
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);
|
||||
}
|
||||
|
||||
// Implements Section 5.4.1
|
||||
void ul_harq_entity::new_grant_ul(mac_interface_phy::mac_grant_t grant, uint8_t* payload_ptr,
|
||||
mac_interface_phy::tb_action_ul_t* action)
|
||||
{
|
||||
if (grant.rnti_type == SRSLTE_RNTI_USER ||
|
||||
grant.rnti_type == SRSLTE_RNTI_TEMP ||
|
||||
grant.rnti_type == SRSLTE_RNTI_RAR)
|
||||
{
|
||||
if (grant.rnti_type == SRSLTE_RNTI_USER && proc[pidof(grant.tti)].is_sps()) {
|
||||
grant.ndi = true;
|
||||
}
|
||||
run_tti(grant.tti, &grant, payload_ptr, action);
|
||||
} else if (grant.rnti_type == SRSLTE_RNTI_SPS) {
|
||||
if (grant.ndi) {
|
||||
grant.ndi = proc[pidof(grant.tti)].get_ndi();
|
||||
run_tti(grant.tti, &grant, payload_ptr, action);
|
||||
} else {
|
||||
Info("Not implemented\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ul_harq_entity::new_grant_ul_ack(mac_interface_phy::mac_grant_t grant, uint8_t* payload_ptr, bool ack,
|
||||
mac_interface_phy::tb_action_ul_t* action)
|
||||
{
|
||||
set_ack(grant.tti, ack);
|
||||
new_grant_ul(grant, payload_ptr, action);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Implements Section 5.4.2.1
|
||||
// Called with UL grant
|
||||
void ul_harq_entity::run_tti(uint32_t tti, mac_interface_phy::mac_grant_t *grant, uint8_t* payload_ptr,
|
||||
mac_interface_phy::tb_action_ul_t* action)
|
||||
{
|
||||
|
||||
uint32_t tti_tx = (tti+4)%10240;
|
||||
uint32_t pid = pidof(tti_tx);
|
||||
|
||||
// Receive and route HARQ feedbacks
|
||||
if (grant) {
|
||||
if ((!grant->is_temp_rnti() && grant->get_ndi() != proc[pid].get_ndi()) ||
|
||||
(grant->is_crnti() && !proc[pid].has_grant()) ||
|
||||
grant->is_from_rar())
|
||||
if ((!grant->rnti_type == SRSLTE_RNTI_TEMP && grant->ndi != proc[pid].get_ndi()) ||
|
||||
(grant->rnti_type == SRSLTE_RNTI_USER && !proc[pid].has_grant()) ||
|
||||
grant->is_from_rar)
|
||||
{
|
||||
// New transmission
|
||||
uint8_t* msg3_ptr = (uint8_t*) mux_unit->msg3_pop(grant->get_tbs());
|
||||
|
||||
// Uplink grant in a RAR
|
||||
if (grant->is_from_rar()) {
|
||||
if (msg3_ptr) {
|
||||
proc[pid].generate_new_tx(tti_tx, msg3_ptr, true, grant, phy_h->get_ul_buffer(tti_tx));
|
||||
mux_unit->msg3_transmitted();
|
||||
if (grant->is_from_rar) {
|
||||
if (mux_unit->msg3_get(payload_ptr, grant->n_bytes)) {
|
||||
proc[pid].generate_new_tx(tti_tx, true, grant, action);
|
||||
} else {
|
||||
Warning("UL RAR grant available but no Msg3 on buffer\n");
|
||||
}
|
||||
|
@ -118,26 +147,24 @@ void ul_harq_entity::run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_h)
|
|||
// Normal UL grant
|
||||
} else {
|
||||
// Request a MAC PDU from the Multiplexing & Assemble Unit
|
||||
uint8_t* mac_pdu = mux_unit->pdu_pop(grant->get_tbs());
|
||||
if (mac_pdu) {
|
||||
// FIXME: This is inefficient. too many memcopies
|
||||
memcpy(mac_pdu_buffer[pid], mac_pdu, grant->get_tbs()*sizeof(uint8_t));
|
||||
mux_unit->pdu_release();
|
||||
proc[pid].generate_new_tx(tti_tx, mac_pdu_buffer[pid], false, grant, phy_h->get_ul_buffer(tti_tx));
|
||||
if (mux_unit->pdu_get(payload_ptr, grant->n_bytes)) {
|
||||
proc[pid].generate_new_tx(tti_tx, false, grant, action);
|
||||
} else {
|
||||
mux_unit->pdu_release();
|
||||
Warning("Uplink grant but no MAC PDU in Multiplex Unit buffer\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Adaptive Re-TX
|
||||
proc[pid].generate_retx(tti_tx, grant, phy_h->get_ul_buffer(tti_tx));
|
||||
proc[pid].generate_retx(tti_tx, grant, action);
|
||||
}
|
||||
} else if (proc[pid].has_grant()) {
|
||||
// Non-Adaptive Re-Tx
|
||||
proc[pid].generate_retx(tti_tx, phy_h->get_ul_buffer(tti_tx));
|
||||
proc[pid].generate_retx(tti_tx, action);
|
||||
}
|
||||
|
||||
if (pcap) {
|
||||
pcap->write_ul_crnti(payload_ptr, grant->n_bytes, grant->rnti, proc[pid].get_nof_retx(), tti_tx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -151,30 +178,34 @@ void ul_harq_entity::run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_h)
|
|||
static int rv_of_irv[4] = {0, 2, 3, 1};
|
||||
static int irv_of_rv[4] = {0, 3, 1, 2};
|
||||
|
||||
ul_harq_entity::ul_harq_process::ul_harq_process() : cur_grant(0) {
|
||||
ul_harq_entity::ul_harq_process::ul_harq_process() {
|
||||
current_tx_nb = 0;
|
||||
current_irv = 0;
|
||||
is_initiated = false;
|
||||
is_grant_configured = false;
|
||||
tti_last_tx = 0;
|
||||
bzero(&cur_grant, sizeof(ul_sched_grant));
|
||||
bzero(&cur_grant, sizeof(mac_interface_phy::mac_grant_t));
|
||||
}
|
||||
|
||||
void ul_harq_entity::ul_harq_process::reset() {
|
||||
current_tx_nb = 0;
|
||||
current_irv = 0;
|
||||
tti_last_tx = 0;
|
||||
is_grant_configured = false;
|
||||
bzero(&cur_grant, sizeof(ul_sched_grant));
|
||||
if (is_initiated) {
|
||||
srslte_softbuffer_tx_reset(&softbuffer);
|
||||
}
|
||||
bzero(&cur_grant, sizeof(mac_interface_phy::mac_grant_t));
|
||||
}
|
||||
|
||||
bool ul_harq_entity::ul_harq_process::has_grant() {
|
||||
return is_grant_configured;
|
||||
}
|
||||
|
||||
void ul_harq_entity::ul_harq_process::reset_ndi() {
|
||||
ndi = false;
|
||||
}
|
||||
|
||||
bool ul_harq_entity::ul_harq_process::get_ndi()
|
||||
{
|
||||
return ndi;
|
||||
|
@ -185,11 +216,6 @@ uint32_t ul_harq_entity::ul_harq_process::get_rv()
|
|||
return rv_of_irv[current_irv%4];
|
||||
}
|
||||
|
||||
ul_sched_grant* ul_harq_entity::ul_harq_process::get_grant()
|
||||
{
|
||||
return &cur_grant;
|
||||
}
|
||||
|
||||
void ul_harq_entity::ul_harq_process::set_harq_feedback(bool ack) {
|
||||
harq_feedback = ack;
|
||||
// UL packet successfully delivered
|
||||
|
@ -201,39 +227,42 @@ void ul_harq_entity::ul_harq_process::set_harq_feedback(bool ack) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ul_harq_entity::ul_harq_process::init(srslte_cell_t cell, ul_harq_entity *parent) {
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
|
||||
bool ul_harq_entity::ul_harq_process::init(uint32_t pid_, ul_harq_entity* parent) {
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, 100)) {
|
||||
fprintf(stderr, "Error initiating soft buffer\n");
|
||||
return false;
|
||||
} else {
|
||||
is_initiated = true;
|
||||
harq_entity = parent;
|
||||
log_h = harq_entity->log_h;
|
||||
pid = pid_;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, ul_buffer* ul)
|
||||
void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action)
|
||||
{
|
||||
generate_retx(tti_tx, NULL, ul);
|
||||
generate_retx(tti_tx, NULL, action);
|
||||
}
|
||||
|
||||
// Retransmission with or w/o grant (Section 5.4.2.2)
|
||||
void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, ul_sched_grant* grant, ul_buffer* ul)
|
||||
void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, mac_interface_phy::mac_grant_t *grant,
|
||||
mac_interface_phy::tb_action_ul_t *action)
|
||||
{
|
||||
current_tx_nb++;
|
||||
if (grant) {
|
||||
// HARQ entity requests an adaptive transmission
|
||||
memcpy(&cur_grant, grant, sizeof(ul_sched_grant));
|
||||
current_irv = irv_of_rv[grant->get_rv()%4];
|
||||
current_irv = irv_of_rv[grant->rv%4];
|
||||
harq_feedback = false;
|
||||
Info("UL PID %d: Adaptive retx=%d, RV=%d, TBS=%d, MCS=%d\n", pid, current_tx_nb, get_rv(), grant->get_tbs(), grant->get_mcs());
|
||||
generate_tx(tti_tx, NULL, ul);
|
||||
Info("UL PID %d: Adaptive retx=%d, RV=%d, TBS=%d\n",
|
||||
pid, current_tx_nb, get_rv(), grant->n_bytes);
|
||||
generate_tx(tti_tx, action);
|
||||
} else {
|
||||
Info("UL PID %d: Non-Adaptive retx=%d, RV=%d, TBS=%d, MCS=%d\n", pid, current_tx_nb, get_rv(), cur_grant.get_tbs(), cur_grant.get_mcs());
|
||||
Info("UL PID %d: Non-Adaptive retx=%d, RV=%d, TBS=%d\n",
|
||||
pid, current_tx_nb, get_rv(), cur_grant.n_bytes);
|
||||
// HARQ entity requests a non-adaptive transmission
|
||||
if (!harq_feedback) {
|
||||
generate_tx(tti_tx, NULL, ul);
|
||||
generate_tx(tti_tx, action);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,56 +273,69 @@ void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, ul_sched_gr
|
|||
}
|
||||
|
||||
// New transmission (Section 5.4.2.2)
|
||||
void ul_harq_entity::ul_harq_process::generate_new_tx(uint32_t tti_tx, uint8_t *pdu_payload, bool is_msg3_, ul_sched_grant* ul_grant, ul_buffer* ul)
|
||||
void ul_harq_entity::ul_harq_process::generate_new_tx(uint32_t tti_tx, bool is_msg3_,
|
||||
mac_interface_phy::mac_grant_t *grant,
|
||||
mac_interface_phy::tb_action_ul_t *action)
|
||||
{
|
||||
if (ul_grant && pdu_payload) {
|
||||
if (grant) {
|
||||
srslte_softbuffer_tx_reset(&softbuffer);
|
||||
memcpy(&cur_grant, ul_grant, sizeof(ul_sched_grant));
|
||||
memcpy(&cur_grant, grant, sizeof(mac_interface_phy::mac_grant_t));
|
||||
harq_feedback = false;
|
||||
is_grant_configured = true;
|
||||
current_tx_nb = 0;
|
||||
current_irv = 0;
|
||||
is_msg3 = is_msg3_;
|
||||
Info("UL PID %d: New TX%s, RV=%d, TBS=%d, MCS=%d, RNTI=%d\n", pid, is_msg3?" for Msg3":"", get_rv(), cur_grant.get_tbs(),
|
||||
cur_grant.get_mcs(), cur_grant.get_rnti());
|
||||
generate_tx(tti_tx, pdu_payload, ul);
|
||||
Info("UL PID %d: New TX%s, RV=%d, TBS=%d, RNTI=%d\n",
|
||||
pid, is_msg3?" for Msg3":"", get_rv(), cur_grant.n_bytes, cur_grant.rnti);
|
||||
generate_tx(tti_tx, action);
|
||||
}
|
||||
}
|
||||
|
||||
// Transmission of pending frame (Section 5.4.2.2)
|
||||
void ul_harq_entity::ul_harq_process::generate_tx(uint32_t tti_tx, uint8_t *pdu_payload, ul_buffer* ul)
|
||||
void ul_harq_entity::ul_harq_process::generate_tx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action)
|
||||
{
|
||||
cur_grant.set_rv(get_rv());
|
||||
ul->set_current_tx_nb(current_tx_nb);
|
||||
ul->generate_data(&cur_grant, &softbuffer, pdu_payload);
|
||||
|
||||
if (harq_entity->pcap) {
|
||||
harq_entity->pcap->write_ul_crnti(pdu_payload, cur_grant.get_tbs()/8, cur_grant.get_rnti(), current_tx_nb, tti_tx);
|
||||
}
|
||||
action->current_tx_nb = current_tx_nb;
|
||||
action->expect_ack = true;
|
||||
action->rnti = is_msg3?harq_entity->params_db->get_param(mac_interface_params::RNTI_TEMP):cur_grant.rnti;
|
||||
action->rv = get_rv();
|
||||
action->softbuffer = &softbuffer;
|
||||
action->tx_enabled = true;
|
||||
memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(srslte_phy_grant_t));
|
||||
|
||||
current_irv = (current_irv+1)%4;
|
||||
tti_last_tx = tti_tx;
|
||||
if (is_msg3) {
|
||||
if (current_tx_nb == harq_entity->params_db->get_param(mac_params::HARQ_MAXMSG3TX)) {
|
||||
if (current_tx_nb == harq_entity->params_db->get_param(mac_interface_params::HARQ_MAXMSG3TX)) {
|
||||
Info("UL PID %d: Maximum number of ReTX for Msg3 reached (%d). Discarting TB.\n", pid,
|
||||
harq_entity->params_db->get_param(mac_params::HARQ_MAXMSG3TX));
|
||||
harq_entity->params_db->get_param(mac_interface_params::HARQ_MAXMSG3TX));
|
||||
reset();
|
||||
action->expect_ack = false;
|
||||
}
|
||||
} else {
|
||||
if (current_tx_nb == harq_entity->params_db->get_param(mac_params::HARQ_MAXTX)) {
|
||||
if (current_tx_nb == harq_entity->params_db->get_param(mac_interface_params::HARQ_MAXTX)) {
|
||||
Info("UL PID %d: Maximum number of ReTX reached (%d). Discarting TB.\n", pid,
|
||||
harq_entity->params_db->get_param(mac_params::HARQ_MAXTX));
|
||||
harq_entity->params_db->get_param(mac_interface_params::HARQ_MAXTX));
|
||||
reset();
|
||||
action->expect_ack = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool ul_harq_entity::ul_harq_process::is_sps()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ul_harq_entity::ul_harq_process::last_tx_tti()
|
||||
{
|
||||
return tti_last_tx;
|
||||
}
|
||||
|
||||
uint32_t ul_harq_entity::ul_harq_process::get_nof_retx()
|
||||
{
|
||||
return current_tx_nb;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@
|
|||
#include "liblte_rrc.h"
|
||||
#include "srsapps/radio/radio_uhd.h"
|
||||
#include "srsapps/ue/phy/phy.h"
|
||||
#include "srsapps/common/tti_sync_cv.h"
|
||||
#include "srsapps/common/mac_interface.h"
|
||||
#include "srsapps/common/log_stdout.h"
|
||||
#include "srsapps/ue/mac/mac.h"
|
||||
#include "srsapps/ue/mac/mac_pcap.h"
|
||||
|
@ -116,26 +116,26 @@ uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t x) {
|
|||
void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::ue::mac *mac, srslte::ue::phy *phy) {
|
||||
// RACH-CONFIGCOMMON
|
||||
if (sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.present) {
|
||||
mac->set_param(srslte::ue::mac_params::RA_NOFGROUPAPREAMBLES,
|
||||
mac->set_param(srslte::ue::mac_interface_params::RA_NOFGROUPAPREAMBLES,
|
||||
liblte_rrc_message_size_group_a_num[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.size_of_ra]);
|
||||
mac->set_param(srslte::ue::mac_params::RA_MESSAGESIZEA,
|
||||
mac->set_param(srslte::ue::mac_interface_params::RA_MESSAGESIZEA,
|
||||
liblte_rrc_message_size_group_a_num[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.msg_size]);
|
||||
mac->set_param(srslte::ue::mac_params::RA_MESSAGEPOWEROFFSETB,
|
||||
mac->set_param(srslte::ue::mac_interface_params::RA_MESSAGEPOWEROFFSETB,
|
||||
liblte_rrc_message_power_offset_group_b_num[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.msg_pwr_offset_group_b]);
|
||||
}
|
||||
mac->set_param(srslte::ue::mac_params::RA_NOFPREAMBLES,
|
||||
mac->set_param(srslte::ue::mac_interface_params::RA_NOFPREAMBLES,
|
||||
liblte_rrc_number_of_ra_preambles_num[sib2->rr_config_common_sib.rach_cnfg.num_ra_preambles]);
|
||||
mac->set_param(srslte::ue::mac_params::RA_POWERRAMPINGSTEP,
|
||||
mac->set_param(srslte::ue::mac_interface_params::RA_POWERRAMPINGSTEP,
|
||||
liblte_rrc_power_ramping_step_num[sib2->rr_config_common_sib.rach_cnfg.pwr_ramping_step]);
|
||||
mac->set_param(srslte::ue::mac_params::RA_INITRECEIVEDPOWER,
|
||||
mac->set_param(srslte::ue::mac_interface_params::RA_INITRECEIVEDPOWER,
|
||||
liblte_rrc_preamble_initial_received_target_power_num[sib2->rr_config_common_sib.rach_cnfg.preamble_init_rx_target_pwr]);
|
||||
mac->set_param(srslte::ue::mac_params::RA_PREAMBLETRANSMAX,
|
||||
mac->set_param(srslte::ue::mac_interface_params::RA_PREAMBLETRANSMAX,
|
||||
liblte_rrc_preamble_trans_max_num[sib2->rr_config_common_sib.rach_cnfg.preamble_trans_max]);
|
||||
mac->set_param(srslte::ue::mac_params::RA_RESPONSEWINDOW,
|
||||
mac->set_param(srslte::ue::mac_interface_params::RA_RESPONSEWINDOW,
|
||||
liblte_rrc_ra_response_window_size_num[sib2->rr_config_common_sib.rach_cnfg.ra_resp_win_size]);
|
||||
mac->set_param(srslte::ue::mac_params::RA_CONTENTIONTIMER,
|
||||
mac->set_param(srslte::ue::mac_interface_params::RA_CONTENTIONTIMER,
|
||||
liblte_rrc_mac_contention_resolution_timer_num[sib2->rr_config_common_sib.rach_cnfg.mac_con_res_timer]);
|
||||
mac->set_param(srslte::ue::mac_params::HARQ_MAXMSG3TX,
|
||||
mac->set_param(srslte::ue::mac_interface_params::HARQ_MAXMSG3TX,
|
||||
sib2->rr_config_common_sib.rach_cnfg.max_harq_msg3_tx);
|
||||
|
||||
printf("Set RACH ConfigCommon: NofPreambles=%d, ResponseWindow=%d, ContentionResolutionTimer=%d ms, MaxTrials=%d\n",
|
||||
|
@ -145,28 +145,28 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u
|
|||
liblte_rrc_preamble_trans_max_num[sib2->rr_config_common_sib.rach_cnfg.preamble_trans_max]);
|
||||
|
||||
// PDSCH ConfigCommon
|
||||
mac->set_param(srslte::ue::mac_params::PDSCH_RSPOWER,
|
||||
mac->set_param(srslte::ue::mac_interface_params::PDSCH_RSPOWER,
|
||||
sib2->rr_config_common_sib.pdsch_cnfg.rs_power);
|
||||
mac->set_param(srslte::ue::mac_params::PDSCH_PB,
|
||||
mac->set_param(srslte::ue::mac_interface_params::PDSCH_PB,
|
||||
sib2->rr_config_common_sib.pdsch_cnfg.p_b);
|
||||
|
||||
// PUSCH ConfigCommon
|
||||
phy->set_param(srslte::ue::phy_params::PUSCH_BETA, 10);
|
||||
phy->set_param(srslte::ue::phy_params::PUSCH_EN_64QAM,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUSCH_BETA, 10);
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUSCH_EN_64QAM,
|
||||
sib2->rr_config_common_sib.pusch_cnfg.enable_64_qam);
|
||||
phy->set_param(srslte::ue::phy_params::PUSCH_HOPPING_OFFSET,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUSCH_HOPPING_OFFSET,
|
||||
sib2->rr_config_common_sib.pusch_cnfg.pusch_hopping_offset);
|
||||
phy->set_param(srslte::ue::phy_params::PUSCH_HOPPING_N_SB,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUSCH_HOPPING_N_SB,
|
||||
sib2->rr_config_common_sib.pusch_cnfg.n_sb);
|
||||
phy->set_param(srslte::ue::phy_params::PUSCH_HOPPING_INTRA_SF,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUSCH_HOPPING_INTRA_SF,
|
||||
sib2->rr_config_common_sib.pusch_cnfg.hopping_mode == LIBLTE_RRC_HOPPING_MODE_INTRA_AND_INTER_SUBFRAME?1:0);
|
||||
phy->set_param(srslte::ue::phy_params::DMRS_GROUP_HOPPING_EN,
|
||||
phy->set_param(srslte::ue::phy_interface_params::DMRS_GROUP_HOPPING_EN,
|
||||
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_hopping_enabled?1:0);
|
||||
phy->set_param(srslte::ue::phy_params::DMRS_SEQUENCE_HOPPING_EN,
|
||||
phy->set_param(srslte::ue::phy_interface_params::DMRS_SEQUENCE_HOPPING_EN,
|
||||
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.sequence_hopping_enabled?1:0);
|
||||
phy->set_param(srslte::ue::phy_params::PUSCH_RS_CYCLIC_SHIFT,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUSCH_RS_CYCLIC_SHIFT,
|
||||
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift);
|
||||
phy->set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_ASSIGNMENT,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUSCH_RS_GROUP_ASSIGNMENT,
|
||||
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch);
|
||||
|
||||
printf("Set PUSCH ConfigCommon: HopOffset=%d, RSGroup=%d, RSNcs=%d, N_sb=%d\n",
|
||||
|
@ -176,14 +176,14 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u
|
|||
sib2->rr_config_common_sib.pusch_cnfg.n_sb);
|
||||
|
||||
// PUCCH ConfigCommon
|
||||
phy->set_param(srslte::ue::phy_params::PUCCH_BETA, 10);
|
||||
phy->set_param(srslte::ue::phy_params::PUCCH_DELTA_SHIFT,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUCCH_BETA, 10);
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUCCH_DELTA_SHIFT,
|
||||
liblte_rrc_delta_pucch_shift_num[sib2->rr_config_common_sib.pucch_cnfg.delta_pucch_shift]);
|
||||
phy->set_param(srslte::ue::phy_params::PUCCH_CYCLIC_SHIFT,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUCCH_CYCLIC_SHIFT,
|
||||
sib2->rr_config_common_sib.pucch_cnfg.n_cs_an);
|
||||
phy->set_param(srslte::ue::phy_params::PUCCH_N_PUCCH_1,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUCCH_N_PUCCH_1,
|
||||
sib2->rr_config_common_sib.pucch_cnfg.n1_pucch_an);
|
||||
phy->set_param(srslte::ue::phy_params::PUCCH_N_RB_2,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUCCH_N_RB_2,
|
||||
sib2->rr_config_common_sib.pucch_cnfg.n_rb_cqi);
|
||||
printf("Set PUCCH ConfigCommon: DeltaShift=%d, CyclicShift=%d, N1=%d, NRB=%d\n",
|
||||
liblte_rrc_delta_pucch_shift_num[sib2->rr_config_common_sib.pucch_cnfg.delta_pucch_shift],
|
||||
|
@ -193,15 +193,15 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u
|
|||
|
||||
|
||||
// PRACH Configcommon
|
||||
phy->set_param(srslte::ue::phy_params::PRACH_ROOT_SEQ_IDX,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PRACH_ROOT_SEQ_IDX,
|
||||
sib2->rr_config_common_sib.prach_cnfg.root_sequence_index);
|
||||
phy->set_param(srslte::ue::phy_params::PRACH_HIGH_SPEED_FLAG,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PRACH_HIGH_SPEED_FLAG,
|
||||
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.high_speed_flag?1:0);
|
||||
phy->set_param(srslte::ue::phy_params::PRACH_FREQ_OFFSET,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PRACH_FREQ_OFFSET,
|
||||
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_freq_offset);
|
||||
phy->set_param(srslte::ue::phy_params::PRACH_ZC_CONFIG,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PRACH_ZC_CONFIG,
|
||||
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.zero_correlation_zone_config);
|
||||
phy->set_param(srslte::ue::phy_params::PRACH_CONFIG_INDEX,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PRACH_CONFIG_INDEX,
|
||||
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_config_index);
|
||||
|
||||
printf("Set PRACH ConfigCommon: SeqIdx=%d, HS=%d, FreqOffset=%d, ZC=%d, ConfigIndex=%d\n",
|
||||
|
@ -213,9 +213,9 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u
|
|||
|
||||
// SRS ConfigCommon
|
||||
if (sib2->rr_config_common_sib.srs_ul_cnfg.present) {
|
||||
phy->set_param(srslte::ue::phy_params::SRS_CS_BWCFG, sib2->rr_config_common_sib.srs_ul_cnfg.bw_cnfg);
|
||||
phy->set_param(srslte::ue::phy_params::SRS_CS_SFCFG, sib2->rr_config_common_sib.srs_ul_cnfg.subfr_cnfg);
|
||||
phy->set_param(srslte::ue::phy_params::SRS_CS_ACKNACKSIMUL, sib2->rr_config_common_sib.srs_ul_cnfg.ack_nack_simul_tx);
|
||||
phy->set_param(srslte::ue::phy_interface_params::SRS_CS_BWCFG, sib2->rr_config_common_sib.srs_ul_cnfg.bw_cnfg);
|
||||
phy->set_param(srslte::ue::phy_interface_params::SRS_CS_SFCFG, sib2->rr_config_common_sib.srs_ul_cnfg.subfr_cnfg);
|
||||
phy->set_param(srslte::ue::phy_interface_params::SRS_CS_ACKNACKSIMUL, sib2->rr_config_common_sib.srs_ul_cnfg.ack_nack_simul_tx);
|
||||
}
|
||||
|
||||
printf("Set SRS ConfigCommon: BW-Configuration=%d, SF-Configuration=%d, ACKNACK=%d\n",
|
||||
|
@ -229,25 +229,24 @@ void process_connsetup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *msg, srslte::ue::mac
|
|||
// FIXME: There's an error parsing the connectionSetup message. This value is hard-coded:
|
||||
|
||||
if (msg->rr_cnfg.phy_cnfg_ded_present) {
|
||||
phy->set_param(srslte::ue::phy_params::PUCCH_N_PUCCH_SR,
|
||||
phy->set_param(srslte::ue::phy_interface_params::PUCCH_N_PUCCH_SR,
|
||||
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_pucch_resource_idx);
|
||||
phy->set_param(srslte::ue::phy_params::SR_CONFIG_INDEX,
|
||||
phy->set_param(srslte::ue::phy_interface_params::SR_CONFIG_INDEX,
|
||||
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_cnfg_idx);
|
||||
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_ACK, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ack_idx);
|
||||
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_CQI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_cqi_idx);
|
||||
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_RI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ri_idx);
|
||||
phy->set_param(srslte::ue::phy_interface_params::UCI_I_OFFSET_ACK, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ack_idx);
|
||||
phy->set_param(srslte::ue::phy_interface_params::UCI_I_OFFSET_CQI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_cqi_idx);
|
||||
phy->set_param(srslte::ue::phy_interface_params::UCI_I_OFFSET_RI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ri_idx);
|
||||
|
||||
if (msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded_present && msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.setup_present) {
|
||||
phy->set_param(srslte::ue::phy_params::SRS_UE_CS, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.cyclic_shift);
|
||||
phy->set_param(srslte::ue::phy_params::SRS_UE_DURATION, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.duration);
|
||||
phy->set_param(srslte::ue::phy_params::SRS_UE_NRRC, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.freq_domain_pos);
|
||||
phy->set_param(srslte::ue::phy_params::SRS_UE_BW, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_bandwidth);
|
||||
phy->set_param(srslte::ue::phy_params::SRS_UE_CONFIGINDEX, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_cnfg_idx);
|
||||
phy->set_param(srslte::ue::phy_params::SRS_UE_HOP, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_hopping_bandwidth);
|
||||
phy->set_param(srslte::ue::phy_params::SRS_UE_CYCLICSHIFT, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.cyclic_shift);
|
||||
phy->set_param(srslte::ue::phy_params::SRS_UE_TXCOMB, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.tx_comb);
|
||||
phy->set_param(srslte::ue::phy_params::SRS_IS_CONFIGURED, 1);
|
||||
phy->set_param(srslte::ue::phy_params::SRS_BETA, 10);
|
||||
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_CS, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.cyclic_shift);
|
||||
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_DURATION, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.duration);
|
||||
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_NRRC, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.freq_domain_pos);
|
||||
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_BW, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_bandwidth);
|
||||
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_CONFIGINDEX, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_cnfg_idx);
|
||||
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_HOP, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_hopping_bandwidth);
|
||||
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_CYCLICSHIFT, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.cyclic_shift);
|
||||
phy->set_param(srslte::ue::phy_interface_params::SRS_UE_TXCOMB, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.tx_comb);
|
||||
phy->set_param(srslte::ue::phy_interface_params::SRS_IS_CONFIGURED, 1);
|
||||
}
|
||||
}
|
||||
printf("Set PHY configuration: SR-n_pucch=%d, SR-ConfigIndex=%d, SRS-ConfigIndex=%d, SRS-bw=%d, SRS-Nrcc=%d, SRS-hop=%d, SRS-Ncs=%d\n",
|
||||
|
@ -259,15 +258,15 @@ void process_connsetup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *msg, srslte::ue::mac
|
|||
msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_hopping_bandwidth,
|
||||
msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.cyclic_shift);
|
||||
|
||||
mac->set_param(srslte::ue::mac_params::HARQ_MAXTX,
|
||||
mac->set_param(srslte::ue::mac_interface_params::HARQ_MAXTX,
|
||||
liblte_rrc_max_harq_tx_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.max_harq_tx]);
|
||||
mac->set_param(srslte::ue::mac_params::SR_TRANS_MAX,
|
||||
mac->set_param(srslte::ue::mac_interface_params::SR_TRANS_MAX,
|
||||
liblte_rrc_dsr_trans_max_num[msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.dsr_trans_max]);
|
||||
mac->set_param(srslte::ue::mac_params::SR_PUCCH_CONFIGURED, 1);
|
||||
mac->set_param(srslte::ue::mac_interface_params::SR_PUCCH_CONFIGURED, 1);
|
||||
|
||||
mac->set_param(srslte::ue::mac_params::BSR_TIMER_RETX,
|
||||
mac->set_param(srslte::ue::mac_interface_params::BSR_TIMER_RETX,
|
||||
liblte_rrc_retransmission_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.retx_bsr_timer]);
|
||||
mac->set_param(srslte::ue::mac_params::BSR_TIMER_PERIODIC,
|
||||
mac->set_param(srslte::ue::mac_interface_params::BSR_TIMER_PERIODIC,
|
||||
liblte_rrc_periodic_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.periodic_bsr_timer]);
|
||||
|
||||
printf("Set MAC configuration: dsr-TransMAX: %d, harq-MaxReTX=%d, bsr-TimerReTX=%d, bsr-TimerPeriodic=%d\n",
|
||||
|
@ -325,7 +324,6 @@ void sig_int_handler(int signo)
|
|||
if (prog_args.do_trace) {
|
||||
//radio_uhd.write_trace("radio");
|
||||
phy.write_trace("phy");
|
||||
mac.write_trace("mac");
|
||||
}
|
||||
if (prog_args.do_pcap) {
|
||||
mac_pcap.close();
|
||||
|
@ -334,10 +332,139 @@ void sig_int_handler(int signo)
|
|||
exit(0);
|
||||
}
|
||||
|
||||
class my_rlc : public srslte::ue::rlc_interface_mac {
|
||||
public:
|
||||
bool mib_decoded;
|
||||
bool sib1_decoded;
|
||||
bool sib2_decoded;
|
||||
bool connsetup_decoded;
|
||||
int nsegm_dcch;
|
||||
uint8_t si_window_len, sib2_period;
|
||||
|
||||
my_rlc() {
|
||||
mib_decoded = false;
|
||||
sib1_decoded = false;
|
||||
sib2_decoded = false;
|
||||
connsetup_decoded = false;
|
||||
nsegm_dcch = 0;
|
||||
si_window_len = 0;
|
||||
sib2_period = 0;
|
||||
}
|
||||
|
||||
uint32_t get_buffer_state(uint32_t lcid) {
|
||||
if (lcid == 0) {
|
||||
if (sib2_decoded && !connsetup_decoded) {
|
||||
return 6;
|
||||
}
|
||||
} else if (lcid == 1) {
|
||||
if (connsetup_decoded && nsegm_dcch < 2) {
|
||||
return lengths[nsegm_dcch];
|
||||
} else if (nsegm_dcch == 2) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes)
|
||||
{
|
||||
if (lcid == 0) {
|
||||
LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg;
|
||||
// Prepare ConnectionRequest packet
|
||||
ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ;
|
||||
ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE;
|
||||
ul_ccch_msg.msg.rrc_con_req.ue_id.random = 1000;
|
||||
ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING;
|
||||
liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, &bit_msg);
|
||||
|
||||
uint64_t uecri=0;
|
||||
uint8_t *ue_cri_ptr = (uint8_t*) &uecri;
|
||||
uint32_t nbytes = bit_msg.N_bits/8;
|
||||
uint8_t *ptr = bit_msg.msg;
|
||||
for (int i=0;i<nbytes;i++) {
|
||||
ue_cri_ptr[nbytes-i-1] = (uint8_t) srslte_bit_unpack(&ptr, 8);
|
||||
}
|
||||
mac.set_param(srslte::ue::mac_interface_params::CONTENTION_ID, uecri);
|
||||
|
||||
// Send ConnectionRequest Packet
|
||||
printf("Send ConnectionRequest %d/%d bytes\n", nbytes, nof_bytes);
|
||||
memcpy(payload, nbytes, nbytes*sizeof(uint8_t));
|
||||
bzero(&payload[nbytes], (nof_bytes-nbytes)*sizeof(uint8_t));
|
||||
} else if (lcid == 1) {
|
||||
if (nsegm_dcch < 2) {
|
||||
printf("Sending Connection Setup Complete %d length %d\n", nsegm_dcch, lengths[nsegm_dcch]);
|
||||
memcpy(payload, setupComplete_segm[nsegm_dcch], lengths[nsegm_dcch]);
|
||||
nsegm_dcch++;
|
||||
} else if (nsegm_dcch == 2) {
|
||||
printf("Send RLC ACK\n");
|
||||
memcpy(payload, reply, 2*sizeof(uint8_t));
|
||||
nsegm_dcch++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void write_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) {
|
||||
if (lcid == 0) {
|
||||
LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg;
|
||||
printf("ConnSetup received %d bytes\n", nof_bytes);
|
||||
srslte_bit_pack_vector(payload, bit_msg.msg, nof_bytes*8);
|
||||
bit_msg.N_bits = nof_bytes*8;
|
||||
liblte_rrc_unpack_dl_ccch_msg(&bit_msg, &dl_ccch_msg);
|
||||
printf("Response: %s\n", liblte_rrc_dl_ccch_msg_type_text[dl_ccch_msg.msg_type]);
|
||||
switch (dl_ccch_msg.msg_type) {
|
||||
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP:
|
||||
// Process ConnectionSetup
|
||||
process_connsetup(&dl_ccch_msg.msg.rrc_con_setup, &mac, &phy);
|
||||
connsetup_decoded = true;
|
||||
break;
|
||||
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ:
|
||||
mac.set_param(srslte::ue::mac_interface_params::RNTI_C, 0);
|
||||
break;
|
||||
}
|
||||
} else if (lcid == 1) {
|
||||
printf("Received on DCCH0 %d bytes\n", nof_bytes);
|
||||
}
|
||||
}
|
||||
void write_pdu_bcch_bch(uint8_t *payload, uint32_t nof_bytes)
|
||||
{
|
||||
LIBLTE_RRC_MIB_STRUCT mib;
|
||||
srslte_bit_pack_vector(payload, bit_msg.msg, nof_bytes*8);
|
||||
bit_msg.N_bits = nof_bytes*8;
|
||||
liblte_rrc_unpack_bcch_bch_msg(&bit_msg, &mib);
|
||||
printf("MIB received %d bytes, BW=%s\n", nof_bytes, liblte_rrc_dl_bandwidth_text[mib.dl_bw]);
|
||||
mib_decoded = true;
|
||||
}
|
||||
|
||||
void write_pdu_bcch_dlsch(uint8_t *payload, uint32_t nof_bytes)
|
||||
{
|
||||
LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT dlsch_msg;
|
||||
srslte_bit_pack_vector(payload, bit_msg.msg, nof_bytes*8);
|
||||
bit_msg.N_bits = nof_bytes*8;
|
||||
liblte_rrc_unpack_bcch_dlsch_msg(&bit_msg, &dlsch_msg);
|
||||
if (dlsch_msg.N_sibs > 0) {
|
||||
if (dlsch_msg.sibs[0].sib_type == LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1) {
|
||||
si_window_len = liblte_rrc_si_window_length_num[dlsch_msg.sibs[0].sib.sib1.si_window_length];
|
||||
sib2_period = liblte_rrc_si_periodicity_num[dlsch_msg.sibs[0].sib.sib1.sched_info[0].si_periodicity];
|
||||
printf("SIB1 received %d bytes, CellID=%d, si_window=%d, sib2_period=%d\n",
|
||||
nof_bytes, dlsch_msg.sibs[0].sib.sib1.cell_id&0xfff, si_window_len, sib2_period);
|
||||
sib1_decoded = true;
|
||||
} else if (dlsch_msg.sibs[0].sib_type == LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2) {
|
||||
|
||||
printf("SIB2 received %d bytes\n", nof_bytes);
|
||||
setup_mac_phy_sib2(&dlsch_msg.sibs[0].sib.sib2, &mac, &phy);
|
||||
sib2_decoded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
LIBLTE_BIT_MSG_STRUCT bit_msg;
|
||||
LIBLTE_BYTE_MSG_STRUCT byte_msg;
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
srslte::ue::tti_sync_cv ttisync(10240);
|
||||
srslte::log_stdout mac_log("MAC"), phy_log("PHY");
|
||||
|
||||
parse_args(&prog_args, argc, argv);
|
||||
|
@ -358,7 +485,6 @@ int main(int argc, char *argv[])
|
|||
signal(SIGINT, sig_int_handler);
|
||||
//radio_uhd.start_trace();
|
||||
phy.start_trace();
|
||||
mac.start_trace();
|
||||
}
|
||||
|
||||
if (prog_args.do_pcap) {
|
||||
|
@ -374,144 +500,32 @@ int main(int argc, char *argv[])
|
|||
radio_uhd.init();
|
||||
radio_uhd.set_rx_gain(prog_args.uhd_rx_gain);
|
||||
radio_uhd.set_tx_gain(prog_args.uhd_tx_gain);
|
||||
phy.init(&radio_uhd, &ttisync, &phy_log);
|
||||
phy.init(&radio_uhd, &mac, &phy_log);
|
||||
} else {
|
||||
radio_uhd.init_agc();
|
||||
radio_uhd.set_tx_rx_gain_offset(0);
|
||||
phy.init_agc(&radio_uhd, &ttisync, &phy_log);
|
||||
phy.init_agc(&radio_uhd, &mac, &phy_log);
|
||||
}
|
||||
// Init MAC
|
||||
mac.init(&phy, &ttisync, &mac_log);
|
||||
mac.init(&phy, &my_rlc, &mac_log);
|
||||
|
||||
// Set RX freq
|
||||
radio_uhd.set_rx_freq(prog_args.uhd_rx_freq);
|
||||
radio_uhd.set_tx_freq(prog_args.uhd_tx_freq);
|
||||
|
||||
LIBLTE_BIT_MSG_STRUCT bit_msg;
|
||||
LIBLTE_RRC_MIB_STRUCT bch_msg;
|
||||
LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT dlsch_msg;
|
||||
LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg;
|
||||
LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg;
|
||||
|
||||
uint32_t si_window_len, sib2_period;
|
||||
int tti;
|
||||
enum {START, SIB1, SIB2, CONNECT, SETUPCOMPLETE, IDLE} state = START;
|
||||
int n;
|
||||
|
||||
while(1) {
|
||||
switch(state) {
|
||||
case START:
|
||||
n = mac.recv_bcch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE);
|
||||
if (n > 0) {
|
||||
bit_msg.N_bits = n;
|
||||
liblte_rrc_unpack_bcch_bch_msg(&bit_msg, &bch_msg);
|
||||
printf("MIB received %d bytes, BW=%s\n", n, liblte_rrc_dl_bandwidth_text[bch_msg.dl_bw]);
|
||||
state = SIB1;
|
||||
}
|
||||
break;
|
||||
case SIB1:
|
||||
n = mac.recv_bcch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE);
|
||||
if (n > 0) {
|
||||
bit_msg.N_bits = n;
|
||||
liblte_rrc_unpack_bcch_dlsch_msg(&bit_msg, &dlsch_msg);
|
||||
si_window_len = liblte_rrc_si_window_length_num[dlsch_msg.sibs[0].sib.sib1.si_window_length];
|
||||
sib2_period = liblte_rrc_si_periodicity_num[dlsch_msg.sibs[0].sib.sib1.sched_info[0].si_periodicity];
|
||||
printf("SIB1 received %d bytes, CellID=%d, si_window=%d, sib2_period=%d\n",
|
||||
n/8, dlsch_msg.sibs[0].sib.sib1.cell_id&0xfff, si_window_len, sib2_period);
|
||||
state = SIB2;
|
||||
} else {
|
||||
tti = mac.get_tti();
|
||||
mac.set_param(srslte::ue::mac_params::BCCH_SI_WINDOW_ST, sib_start_tti(tti, 2, 5));
|
||||
mac.set_param(srslte::ue::mac_params::BCCH_SI_WINDOW_LEN, 1);
|
||||
}
|
||||
break;
|
||||
case SIB2:
|
||||
n = mac.recv_bcch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE);
|
||||
if (n > 0) {
|
||||
// Process SIB2
|
||||
bit_msg.N_bits = n;
|
||||
liblte_rrc_unpack_bcch_dlsch_msg(&bit_msg, &dlsch_msg);
|
||||
printf("SIB2 received %d bytes\n", n/8);
|
||||
setup_mac_phy_sib2(&dlsch_msg.sibs[0].sib.sib2, &mac, &phy);
|
||||
|
||||
// Prepare ConnectionRequest packet
|
||||
ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ;
|
||||
ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE;
|
||||
ul_ccch_msg.msg.rrc_con_req.ue_id.random = 1000;
|
||||
ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING;
|
||||
liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, &bit_msg);
|
||||
|
||||
uint64_t uecri=0;
|
||||
uint8_t *ue_cri_ptr = (uint8_t*) &uecri;
|
||||
uint32_t nbytes = bit_msg.N_bits/8;
|
||||
uint8_t *ptr = bit_msg.msg;
|
||||
for (int i=0;i<nbytes;i++) {
|
||||
ue_cri_ptr[nbytes-i-1] = (uint8_t) srslte_bit_unpack(&ptr, 8);
|
||||
}
|
||||
mac.set_param(srslte::ue::mac_params::CONTENTION_ID, uecri);
|
||||
|
||||
// Send ConnectionRequest Packet
|
||||
printf("Send ConnectionRequest %d bytes\n", nbytes);
|
||||
mac.send_ccch_sdu(bit_msg.msg, bit_msg.N_bits);
|
||||
state = CONNECT;
|
||||
} else {
|
||||
tti = mac.get_tti();
|
||||
mac.set_param(srslte::ue::mac_params::BCCH_SI_WINDOW_ST, sib_start_tti(tti, sib2_period, 0));
|
||||
mac.set_param(srslte::ue::mac_params::BCCH_SI_WINDOW_LEN, si_window_len);
|
||||
}
|
||||
break;
|
||||
case CONNECT:
|
||||
// Wait for Connection Setup
|
||||
n = mac.recv_ccch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE);
|
||||
if (n > 0) {
|
||||
printf("ConnSetup received %d bytes\n", n/8);
|
||||
bit_msg.N_bits = n;
|
||||
srslte_vec_fprint_hex(stdout, bit_msg.msg, n);
|
||||
liblte_rrc_unpack_dl_ccch_msg(&bit_msg, &dl_ccch_msg);
|
||||
printf("Response: %s\n", liblte_rrc_dl_ccch_msg_type_text[dl_ccch_msg.msg_type]);
|
||||
switch (dl_ccch_msg.msg_type) {
|
||||
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP:
|
||||
// Process ConnectionSetup
|
||||
process_connsetup(&dl_ccch_msg.msg.rrc_con_setup, &mac, &phy);
|
||||
|
||||
// Generate and send ConnectionSetupComplete
|
||||
for (int i=0;i<2;i++) {
|
||||
printf("Sending Connection Setup Complete %d\n", i);
|
||||
srslte_bit_pack_vector(setupComplete_segm[i], bit_msg.msg, lengths[i]*8);
|
||||
n=mac.send_dcch0_sdu(bit_msg.msg, lengths[i]*8);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "Error writting to DCCH0\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
state = SETUPCOMPLETE;
|
||||
break;
|
||||
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ:
|
||||
mac.set_param(srslte::ue::mac_params::RNTI_C, 0);
|
||||
break;
|
||||
}
|
||||
// exit(0);
|
||||
}
|
||||
break;
|
||||
case SETUPCOMPLETE:
|
||||
// Wait for ConnectionSetup
|
||||
n = mac.recv_dcch0_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE);
|
||||
if (n > 0) {
|
||||
printf("Received on DCCH0 %d bytes\n", n/8);
|
||||
printf("Send RLC ACK\n");
|
||||
srslte_bit_pack_vector(reply, bit_msg.msg, 2*8);
|
||||
n=mac.send_dcch0_sdu(bit_msg.msg, 2*8);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "Error writting to DCCH0\n");
|
||||
exit(-1);
|
||||
}
|
||||
state = IDLE;
|
||||
}
|
||||
break;
|
||||
case IDLE:
|
||||
break;
|
||||
uint32_t tti;
|
||||
if (my_rlc.mib_decoded) {
|
||||
if (!my_rlc.sib1_decoded) {
|
||||
tti = mac.get_current_tti();
|
||||
mac.set_param(srslte::ue::mac_interface_params::BCCH_SI_WINDOW_ST, sib_start_tti(tti, 2, 5));
|
||||
mac.set_param(srslte::ue::mac_interface_params::BCCH_SI_WINDOW_LEN, 1);
|
||||
} else {
|
||||
tti = mac.get_current_tti();
|
||||
mac.set_param(srslte::ue::mac_interface_params::BCCH_SI_WINDOW_ST, sib_start_tti(tti, my_rlc.sib2_period, 0));
|
||||
mac.set_param(srslte::ue::mac_interface_params::BCCH_SI_WINDOW_LEN, my_rlc.si_window_len);
|
||||
}
|
||||
}
|
||||
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ namespace ue {
|
|||
void worker_end(uint32_t tti, bool tx_enable, cf_t *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time);
|
||||
|
||||
bool sr_enabled;
|
||||
int sr_last_tx_tti;
|
||||
|
||||
private:
|
||||
pthread_mutex_t tx_mutex;
|
||||
|
|
|
@ -106,6 +106,9 @@ private:
|
|||
uint16_t ul_rnti;
|
||||
uint8_t *ul_payload;
|
||||
|
||||
// FIXME: THIS IS TEMPORAL. Need to change srslte to accept bits for payload
|
||||
uint8_t payload_bits[64*1024];
|
||||
|
||||
// UL configuration parameters
|
||||
srslte_refsignal_srs_cfg_t srs_cfg;
|
||||
srslte_pucch_cfg_t pucch_cfg;
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
void write_trace(std::string filename);
|
||||
|
||||
/********** MAC INTERFACE ********************/
|
||||
/* Instructs the PHY to configure using the parameters written with set_param() */
|
||||
/* Instructs the PHY to configure using the parameters written by set_param() */
|
||||
void configure_prach_params();
|
||||
void configure_ul_params();
|
||||
|
||||
|
@ -79,11 +79,13 @@ public:
|
|||
void sync_start();
|
||||
void sync_stop();
|
||||
|
||||
/* Functions to initialize and transmit PRACH in the next opportunity */
|
||||
void prach_send(prach_cfg_t *cfg);
|
||||
|
||||
/* Transmits PRACH in the next opportunity */
|
||||
void prach_send(uint32_t preamble_idx, int allowed_subframe = -1, float target_power_dbm = 0.0);
|
||||
int prach_tx_tti();
|
||||
|
||||
/* Indicates the transmission of a SR signal in the next opportunity */
|
||||
void sr_send();
|
||||
int sr_last_tx_tti();
|
||||
|
||||
// Time advance commands
|
||||
void set_timeadv_rar(uint32_t ta_cmd);
|
||||
|
|
|
@ -49,10 +49,9 @@ namespace ue {
|
|||
void init(phy_params *params_db, log *log_h);
|
||||
bool init_cell(srslte_cell_t cell);
|
||||
void free_cell();
|
||||
bool prepare_to_send(phy_interface::prach_cfg_t* cfg);
|
||||
bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe = -1, float target_power_dbm = -1);
|
||||
bool is_ready_to_send(uint32_t current_tti);
|
||||
void get_rar_cfg(uint16_t* rar_rnti, uint32_t* tti_start, uint32_t* tti_end);
|
||||
int tx_tti();
|
||||
|
||||
bool send(radio* radio_handler, float cfo, srslte_timestamp_t rx_time);
|
||||
|
||||
|
@ -66,12 +65,11 @@ namespace ue {
|
|||
uint32_t len;
|
||||
cf_t *buffer[64];
|
||||
srslte_prach_t prach_obj;
|
||||
uint32_t transmitted_tti;
|
||||
int transmitted_tti;
|
||||
srslte_cell_t cell;
|
||||
cf_t *signal_buffer;
|
||||
srslte_cfo_t cfo_h;
|
||||
|
||||
phy_interface::prach_cfg_t prach_cfg;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ bool phch_recv::cell_search(int force_N_id_2)
|
|||
if (ret == 1) {
|
||||
srslte_pbch_mib_unpack(bch_payload, &cell, NULL);
|
||||
srslte_cell_fprint(stdout, &cell, 0);
|
||||
mac->bch_decoded_ok(bch_payload);
|
||||
mac->bch_decoded_ok(bch_payload, SRSLTE_BCH_PAYLOAD_LEN);
|
||||
return true;
|
||||
} else {
|
||||
Warning("Error decoding MIB: Error decoding PBCH\n");
|
||||
|
@ -305,16 +305,11 @@ void phch_recv::run_thread()
|
|||
if (prach_buffer->is_ready_to_send(tti)) {
|
||||
srslte_timestamp_t cur_time;
|
||||
radio_h->get_time(&cur_time);
|
||||
Info("TX PRACH now. RX time: %d:%f, Now: %d:%f\n", rx_time.full_secs, rx_time.frac_secs, cur_time.full_secs, cur_time.frac_secs);
|
||||
Info("TX PRACH now. RX time: %d:%f, Now: %d:%f\n", rx_time.full_secs, rx_time.frac_secs,
|
||||
cur_time.full_secs, cur_time.frac_secs);
|
||||
// send prach if we have to
|
||||
prach_buffer->send(radio_h, cfo, tx_time);
|
||||
radio_h->tx_end();
|
||||
|
||||
/* Setup DL RNTI search to look for RAR as configured by MAC */
|
||||
uint16_t rar_rnti;
|
||||
uint32_t rar_start, rar_end;
|
||||
prach_buffer->get_rar_cfg(&rar_rnti, &rar_start, &rar_end);
|
||||
worker_com->set_dl_rnti(SRSLTE_RNTI_RAR, rar_rnti, (int) rar_start, (int) rar_end);
|
||||
radio_h->tx_end();
|
||||
}
|
||||
workers_pool->start_worker(worker);
|
||||
}
|
||||
|
|
|
@ -158,6 +158,9 @@ void phch_worker::work_imp()
|
|||
dl_ack = decode_pdsch(&dl_action.phy_grant.dl, dl_action.payload_ptr, dl_action.softbuffer, dl_action.rv, dl_action.rnti);
|
||||
phy->mac->tb_decoded_ok(dl_mac_grant.pid);
|
||||
}
|
||||
if (dl_action.generate_ack_callback) {
|
||||
dl_action.generate_ack = dl_action.generate_ack_callback(dl_action.generate_ack_callback_arg);
|
||||
}
|
||||
if (dl_action.generate_ack) {
|
||||
set_uci_ack(dl_ack);
|
||||
}
|
||||
|
@ -273,7 +276,7 @@ bool phch_worker::decode_pdcch_dl(srslte::ue::mac_interface_phy::mac_grant_t* gr
|
|||
/* Fill MAC grant structure */
|
||||
grant->ndi = dci_unpacked.ndi;
|
||||
grant->pid = dci_unpacked.harq_process;
|
||||
grant->tbs = grant->phy_grant.dl.mcs.tbs;
|
||||
grant->n_bytes = grant->phy_grant.dl.mcs.tbs/8;
|
||||
grant->tti = tti;
|
||||
grant->rv = dci_unpacked.rv_idx;
|
||||
grant->rnti = dl_rnti;
|
||||
|
@ -299,8 +302,10 @@ bool phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload,
|
|||
if (ue_dl.pdsch_cfg.grant.mcs.mod > 0 && ue_dl.pdsch_cfg.grant.mcs.tbs >= 0) {
|
||||
|
||||
if (srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffer, ue_dl.sf_symbols,
|
||||
ue_dl.ce, 0, rnti, payload) == 0)
|
||||
ue_dl.ce, 0, rnti, payload_bits) == 0)
|
||||
{
|
||||
// FIXME: TEMPORAL
|
||||
srslte_bit_unpack_vector(payload_bits, payload, grant->mcs.tbs);
|
||||
Debug("TB decoded OK\n");
|
||||
return true;
|
||||
} else {
|
||||
|
@ -354,6 +359,7 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
|
|||
Error("Converting RAR message to UL grant\n");
|
||||
return false;
|
||||
}
|
||||
grant->is_from_rar = true;
|
||||
Info("RAR grant found for TTI=%d\n", tti);
|
||||
rar_cqi_request = rar_grant.cqi_request;
|
||||
ret = true;
|
||||
|
@ -372,6 +378,7 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
|
|||
Error("Converting DCI message to UL grant\n");
|
||||
return false;
|
||||
}
|
||||
grant->is_from_rar = false;
|
||||
ret = true;
|
||||
Info("PDCCH: UL DCI Format0 cce_index=%d, n_data_bits=%d\n", ue_dl.last_n_cce, dci_msg.nof_bits);
|
||||
}
|
||||
|
@ -379,7 +386,7 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
|
|||
if (ret) {
|
||||
grant->ndi = dci_unpacked.ndi;
|
||||
grant->pid = 0; // This is computed by MAC from TTI
|
||||
grant->tbs = grant->phy_grant.ul.mcs.tbs;
|
||||
grant->n_bytes = grant->phy_grant.ul.mcs.tbs/8;
|
||||
grant->tti = tti;
|
||||
grant->rnti = ul_rnti;
|
||||
|
||||
|
@ -412,6 +419,7 @@ void phch_worker::set_uci_sr()
|
|||
if (srslte_ue_ul_sr_send_tti(I_sr, tti+4)) {
|
||||
Info("SR transmission at TTI=%d\n", tti+4);
|
||||
uci_data.scheduling_request = true;
|
||||
phy->sr_last_tx_tti = tti+4;
|
||||
phy->sr_enabled = false;
|
||||
}
|
||||
}
|
||||
|
@ -457,8 +465,11 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint32_t current_tx_
|
|||
Error("Configuring UL grant\n");
|
||||
}
|
||||
|
||||
// FIXME: TEMPORAL
|
||||
srslte_bit_pack_vector(ul_payload, payload_bits, grant->mcs.tbs);
|
||||
|
||||
if (srslte_ue_ul_pusch_encode_rnti_softbuffer(&ue_ul,
|
||||
ul_payload, uci_data,
|
||||
payload_bits, uci_data,
|
||||
softbuffer,
|
||||
rnti,
|
||||
signal_buffer))
|
||||
|
|
|
@ -187,14 +187,19 @@ void phy::get_current_cell(srslte_cell_t *cell)
|
|||
sf_recv.get_current_cell(cell);
|
||||
}
|
||||
|
||||
void phy::prach_send(phy_interface::prach_cfg_t* cfg)
|
||||
void phy::prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm)
|
||||
{
|
||||
|
||||
if (!prach_buffer.prepare_to_send(cfg)) {
|
||||
if (!prach_buffer.prepare_to_send(preamble_idx, allowed_subframe, target_power_dbm)) {
|
||||
Error("Preparing PRACH to send\n");
|
||||
}
|
||||
}
|
||||
|
||||
int phy::prach_tx_tti()
|
||||
{
|
||||
return prach_buffer.tx_tti();
|
||||
}
|
||||
|
||||
void phy::reset()
|
||||
{
|
||||
// TODO
|
||||
|
@ -210,6 +215,11 @@ void phy::sr_send()
|
|||
workers_common.sr_enabled = true;
|
||||
}
|
||||
|
||||
int phy::sr_last_tx_tti()
|
||||
{
|
||||
return workers_common.sr_last_tx_tti;
|
||||
}
|
||||
|
||||
bool phy::status_is_sync()
|
||||
{
|
||||
return sf_recv.status_is_sync();
|
||||
|
|
|
@ -95,16 +95,6 @@ bool prach::init_cell(srslte_cell_t cell_)
|
|||
return initiated;
|
||||
}
|
||||
|
||||
bool prach::prepare_to_send(phy_interface::prach_cfg_t* cfg)
|
||||
{
|
||||
int allowed_sf = cfg->allowed_subframe_enabled?(int) cfg->allowed_subframe:-1;
|
||||
bool ret = prepare_to_send(cfg->preamble_idx, allowed_sf, cfg->target_power_dbm);
|
||||
if (ret) {
|
||||
memcpy(&prach_cfg, cfg, sizeof(phy_interface::prach_cfg_t));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_, float target_power_dbm)
|
||||
{
|
||||
if (initiated && preamble_idx_ < 64) {
|
||||
|
@ -137,17 +127,8 @@ bool prach::is_ready_to_send(uint32_t current_tti_) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void prach::get_rar_cfg(uint16_t *rar_rnti, uint32_t *tti_start, uint32_t *tti_end)
|
||||
{
|
||||
if (rar_rnti) {
|
||||
*rar_rnti = prach_cfg.rar_rnti;
|
||||
}
|
||||
if (tti_start) {
|
||||
*tti_start = transmitted_tti + prach_cfg.rar_start;
|
||||
}
|
||||
if (tti_end) {
|
||||
*tti_end = transmitted_tti + prach_cfg.rar_start + prach_cfg.rar_window;
|
||||
}
|
||||
int prach::tx_tti() {
|
||||
return transmitted_tti;
|
||||
}
|
||||
|
||||
bool prach::send(radio *radio_handler, float cfo, srslte_timestamp_t tx_time)
|
||||
|
|
|
@ -202,9 +202,26 @@ uint16_t temp_c_rnti;
|
|||
class testmac : public srslte::ue::mac_interface_phy
|
||||
{
|
||||
public:
|
||||
|
||||
testmac() {
|
||||
rar_rnti_set = false;
|
||||
}
|
||||
|
||||
bool rar_rnti_set;
|
||||
|
||||
void tti_clock(uint32_t tti) {
|
||||
if (!rar_rnti_set) {
|
||||
int prach_tti = my_phy.prach_tx_tti();
|
||||
if (prach_tti > 0) {
|
||||
my_phy.pdcch_dl_search(SRSLTE_RNTI_RAR, 1+prach_tti%10, prach_tti+3, 10);
|
||||
rar_rnti_set = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void new_grant_ul(mac_grant_t grant, uint8_t *payload_ptr, tb_action_ul_t *action) {
|
||||
printf("New grant UL\n");
|
||||
srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload_ptr, grant.tbs);
|
||||
srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload_ptr, grant.n_bytes*8);
|
||||
action->current_tx_nb = nof_rtx_connsetup;
|
||||
action->rv = rv_value[nof_rtx_connsetup%4];
|
||||
action->softbuffer = &softbuffer_tx;
|
||||
|
@ -272,7 +289,7 @@ public:
|
|||
|
||||
temp_c_rnti = rar_msg.temp_c_rnti;
|
||||
|
||||
if (last_grant.tbs > 20 + SRSLTE_RAR_GRANT_LEN) {
|
||||
if (last_grant.n_bytes*8 > 20 + SRSLTE_RAR_GRANT_LEN) {
|
||||
uint8_t rar_grant[SRSLTE_RAR_GRANT_LEN];
|
||||
memcpy(rar_grant, &payload[20], sizeof(uint8_t)*SRSLTE_RAR_GRANT_LEN);
|
||||
my_phy.set_rar_grant(last_grant.tti, rar_grant);
|
||||
|
@ -286,14 +303,15 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void bch_decoded_ok(uint8_t *payload) {
|
||||
void bch_decoded_ok(uint8_t *payload, uint32_t len) {
|
||||
printf("BCH decoded\n");
|
||||
bch_decoded = true;
|
||||
srslte_cell_t cell;
|
||||
my_phy.get_current_cell(&cell);
|
||||
srslte_softbuffer_rx_init(&softbuffer_rx, cell);
|
||||
srslte_softbuffer_tx_init(&softbuffer_tx, cell);
|
||||
srslte_softbuffer_rx_init(&softbuffer_rx, cell.nof_prb);
|
||||
srslte_softbuffer_tx_init(&softbuffer_tx, cell.nof_prb);
|
||||
}
|
||||
|
||||
private:
|
||||
mac_grant_t last_grant;
|
||||
};
|
||||
|
@ -347,13 +365,7 @@ int main(int argc, char *argv[])
|
|||
config_phy();
|
||||
|
||||
/* Instruct PHY to send PRACH and prepare it for receiving RAR */
|
||||
srslte::ue::phy_interface::prach_cfg_t prach_cfg;
|
||||
prach_cfg.allowed_subframe_enabled = false;
|
||||
prach_cfg.preamble_idx = preamble_idx;
|
||||
prach_cfg.rar_rnti = 2;
|
||||
prach_cfg.rar_start = 3;
|
||||
prach_cfg.rar_window = 10;
|
||||
my_phy.prach_send(&prach_cfg);
|
||||
my_phy.prach_send(preamble_idx);
|
||||
|
||||
/* go to idle and process each tti */
|
||||
bool running = true;
|
||||
|
|
|
@ -127,13 +127,14 @@ public:
|
|||
total_oks++;
|
||||
}
|
||||
|
||||
void bch_decoded_ok(uint8_t *payload) {
|
||||
void bch_decoded_ok(uint8_t *payload, uint32_t len) {
|
||||
printf("BCH decoded\n");
|
||||
bch_decoded = true;
|
||||
srslte_cell_t cell;
|
||||
my_phy.get_current_cell(&cell);
|
||||
srslte_softbuffer_rx_init(&softbuffer, cell);
|
||||
|
||||
srslte_softbuffer_rx_init(&softbuffer, cell.nof_prb);
|
||||
}
|
||||
void tti_clock(uint32_t tti) {
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
@ -259,7 +259,7 @@ void base_init() {
|
|||
|
||||
srslte_pdsch_set_rnti(&pdsch, UE_CRNTI);
|
||||
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating soft buffer\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
|
|
@ -53,14 +53,14 @@ typedef struct SRSLTE_API {
|
|||
} srslte_softbuffer_tx_t;
|
||||
|
||||
SRSLTE_API int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t * q,
|
||||
srslte_cell_t cell);
|
||||
uint32_t nof_prb);
|
||||
|
||||
SRSLTE_API void srslte_softbuffer_rx_reset(srslte_softbuffer_rx_t *p);
|
||||
|
||||
SRSLTE_API void srslte_softbuffer_rx_free(srslte_softbuffer_rx_t *p);
|
||||
|
||||
SRSLTE_API int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t * q,
|
||||
srslte_cell_t cell);
|
||||
uint32_t nof_prb);
|
||||
|
||||
SRSLTE_API void srslte_softbuffer_tx_reset(srslte_softbuffer_tx_t *p);
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
#define MAX_PDSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12)
|
||||
|
||||
int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t *q, srslte_cell_t cell) {
|
||||
int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t *q, uint32_t nof_prb) {
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL) {
|
||||
|
@ -52,7 +52,7 @@ int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t *q, srslte_cell_t cell) {
|
|||
|
||||
bzero(q, sizeof(srslte_softbuffer_rx_t));
|
||||
|
||||
ret = srslte_ra_tbs_from_idx(26, cell.nof_prb);
|
||||
ret = srslte_ra_tbs_from_idx(26, nof_prb);
|
||||
if (ret != SRSLTE_ERROR) {
|
||||
q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1;
|
||||
|
||||
|
@ -106,7 +106,7 @@ void srslte_softbuffer_rx_reset(srslte_softbuffer_rx_t *q) {
|
|||
|
||||
|
||||
|
||||
int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t *q, srslte_cell_t cell) {
|
||||
int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t *q, uint32_t nof_prb) {
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL) {
|
||||
|
@ -114,7 +114,7 @@ int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t *q, srslte_cell_t cell) {
|
|||
|
||||
bzero(q, sizeof(srslte_softbuffer_tx_t));
|
||||
|
||||
ret = srslte_ra_tbs_from_idx(26, cell.nof_prb);
|
||||
ret = srslte_ra_tbs_from_idx(26, nof_prb);
|
||||
if (ret != SRSLTE_ERROR) {
|
||||
q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1;
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
|
||||
mxFree(mod_str);
|
||||
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
|
||||
mexErrMsgTxt("Error initiating DL-SCH soft buffer\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -183,12 +183,12 @@ int main(int argc, char **argv) {
|
|||
|
||||
srslte_pdsch_set_rnti(&pdsch, 1234);
|
||||
|
||||
if (srslte_softbuffer_tx_init(&softbuffer_tx, cell)) {
|
||||
if (srslte_softbuffer_tx_init(&softbuffer_tx, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating TX soft buffer\n");
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (srslte_softbuffer_rx_init(&softbuffer_rx, cell)) {
|
||||
if (srslte_softbuffer_rx_init(&softbuffer_rx, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating RX soft buffer\n");
|
||||
goto quit;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
}
|
||||
srslte_pdsch_set_rnti(&pdsch, (uint16_t) (rnti32 & 0xffff));
|
||||
|
||||
if (srslte_softbuffer_rx_init(&softbuffer, cell)) {
|
||||
if (srslte_softbuffer_rx_init(&softbuffer, cell.nof_prb)) {
|
||||
mexErrMsgTxt("Error initiating soft buffer\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
|
||||
|
||||
srslte_softbuffer_tx_t softbuffer;
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
|
||||
mexErrMsgTxt("Error initiating soft buffer\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -207,7 +207,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
gettimeofday(&t[1], NULL);
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating soft buffer\n");
|
||||
goto quit;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
cell.id=1;
|
||||
cell.cp=SRSLTE_CP_NORM;
|
||||
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
|
||||
mexErrMsgTxt("Error initiating HARQ\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
|
|||
fprintf(stderr, "Error creating PDSCH object\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
if (srslte_softbuffer_rx_init(&q->softbuffer, q->cell)) {
|
||||
if (srslte_softbuffer_rx_init(&q->softbuffer, q->cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating soft buffer\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
|
|||
fprintf(stderr, "Error creating PUSCH object\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
if (srslte_softbuffer_tx_init(&q->softbuffer, q->cell)) {
|
||||
if (srslte_softbuffer_tx_init(&q->softbuffer, q->cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating soft buffer\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue