adding PHY embms support to the UE

master
yagoda 7 years ago
parent 84f4996584
commit e35672e234

@ -27,6 +27,9 @@
#ifndef SRSUE_PHCH_COMMON_H #ifndef SRSUE_PHCH_COMMON_H
#define SRSUE_PHCH_COMMON_H #define SRSUE_PHCH_COMMON_H
#define TX_MODE_CONTINUOUS 1
#include <pthread.h> #include <pthread.h>
#include <string.h> #include <string.h>
#include <vector> #include <vector>
@ -34,12 +37,12 @@
#include "srslte/interfaces/ue_interfaces.h" #include "srslte/interfaces/ue_interfaces.h"
#include "srslte/radio/radio.h" #include "srslte/radio/radio.h"
#include "srslte/common/log.h" #include "srslte/common/log.h"
#include "srslte/common/gen_mch_tables.h"
#include "phy_metrics.h" #include "phy_metrics.h"
namespace srsue { namespace srsue {
class chest_feedback_itf class chest_feedback_itf
{ {
public: public:
@ -48,6 +51,26 @@ public:
virtual void set_cfo(float cfo) = 0; virtual void set_cfo(float cfo) = 0;
}; };
typedef enum{
SUBFRAME_TYPE_REGULAR = 0,
SUBFRAME_TYPE_MBSFN,
SUBFRAME_TYPE_N_ITEMS,
} subframe_type_t;
static const char subframe_type_text[SUBFRAME_TYPE_N_ITEMS][20] = {"Regular", "MBSFN"};
/* Subframe config */
typedef struct {
subframe_type_t sf_type;
uint8_t mbsfn_area_id;
uint8_t non_mbsfn_region_length;
uint8_t mbsfn_mcs;
bool mbsfn_decode;
bool is_mcch;
} subframe_cfg_t;
/* Subclass that manages variables common to all workers */ /* Subclass that manages variables common to all workers */
class phch_common { class phch_common {
public: public:
@ -57,6 +80,7 @@ public:
phy_args_t *args; phy_args_t *args;
rrc_interface_phy *rrc; rrc_interface_phy *rrc;
mac_interface_phy *mac; mac_interface_phy *mac;
srslte_ue_ul_t ue_ul;
/* Power control variables */ /* Power control variables */
float pathloss; float pathloss;
@ -74,9 +98,12 @@ public:
float rx_gain_offset; float rx_gain_offset;
float avg_snr_db_cqi; float avg_snr_db_cqi;
float avg_snr_db_sync; float avg_snr_db_sync;
float avg_noise; float avg_noise;
bool pcell_meas_enabled;
uint32_t pcell_report_period; uint32_t pcell_report_period;
bool pcell_first_measurement;
// Save last TBS for mcs>28 cases // Save last TBS for mcs>28 cases
int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS]; int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS];
@ -85,7 +112,6 @@ public:
int last_ul_tbs[2*HARQ_DELAY_MS]; int last_ul_tbs[2*HARQ_DELAY_MS];
uint32_t last_ul_tti[2*HARQ_DELAY_MS]; uint32_t last_ul_tti[2*HARQ_DELAY_MS];
srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS]; srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS];
uint8_t last_ri; uint8_t last_ri;
uint8_t last_pmi; uint8_t last_pmi;
@ -122,6 +148,7 @@ public:
bool sr_enabled; bool sr_enabled;
int sr_last_tx_tti; int sr_last_tx_tti;
srslte::radio* get_radio(); srslte::radio* get_radio();
void set_cell(const srslte_cell_t &c); void set_cell(const srslte_cell_t &c);
@ -136,8 +163,21 @@ public:
void reset_ul(); void reset_ul();
void reset(); void reset();
// MBSFN helpers
void build_mch_table();
void build_mcch_table();
void set_mcch();
void get_sf_config(subframe_cfg_t *cfg, uint32_t phy_tti);
void set_mch_period_stop(uint32_t stop);
private: private:
bool have_mtch_stop;
pthread_mutex_t mtch_mutex;
pthread_cond_t mtch_cvar;
std::vector<pthread_mutex_t> tx_mutex; std::vector<pthread_mutex_t> tx_mutex;
bool is_first_of_burst; bool is_first_of_burst;
@ -182,8 +222,21 @@ private:
sync_metrics_t sync_metrics; sync_metrics_t sync_metrics;
uint32_t sync_metrics_count; uint32_t sync_metrics_count;
bool sync_metrics_read; bool sync_metrics_read;
// MBSFN
bool sib13_configured;
bool mcch_configured;
uint32_t mch_period_stop;
uint8_t mch_table[40];
uint8_t mcch_table[10];
bool is_mch_subframe(subframe_cfg_t *cfg, uint32_t phy_tti);
bool is_mcch_subframe(subframe_cfg_t *cfg, uint32_t phy_tti);
}; };
} // namespace srsue } // namespace srsue
#endif // SRSUE_PDCH_COMMON_H #endif // SRSUE_PDCH_COMMON_H

@ -89,8 +89,9 @@ private:
/* Internal methods */ /* Internal methods */
bool extract_fft_and_pdcch_llr();
void compute_ri(uint8_t *ri, uint8_t *pmi, float *sinr); void compute_ri(uint8_t *ri, uint8_t *pmi, float *sinr);
bool extract_fft_and_pdcch_llr(subframe_cfg_t sf_cfg);
/* ... for DL */ /* ... for DL */
bool decode_pdcch_ul(mac_interface_phy::mac_grant_t *grant); bool decode_pdcch_ul(mac_interface_phy::mac_grant_t *grant);
@ -105,6 +106,11 @@ private:
uint32_t pid, uint32_t pid,
bool acks[SRSLTE_MAX_CODEWORDS]); bool acks[SRSLTE_MAX_CODEWORDS]);
bool decode_pmch(srslte_ra_dl_grant_t *grant,
uint8_t *payload,
srslte_softbuffer_rx_t* softbuffer,
uint16_t mbsfn_area_id);
/* ... for UL */ /* ... for UL */
void encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, uint32_t current_tx_nb, srslte_softbuffer_tx_t *softbuffer, void encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, uint32_t current_tx_nb, srslte_softbuffer_tx_t *softbuffer,
uint32_t rv, uint16_t rnti, bool is_from_rar); uint32_t rv, uint16_t rnti, bool is_from_rar);

@ -128,6 +128,12 @@ public:
void set_config_common(phy_cfg_common_t *common); void set_config_common(phy_cfg_common_t *common);
void set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd); void set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd);
void set_config_64qam_en(bool enable); void set_config_64qam_en(bool enable);
void set_config_mbsfn_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2);
void set_config_mbsfn_sib13(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13);
void set_config_mbsfn_mcch(LIBLTE_RRC_MCCH_MSG_STRUCT *mcch);
/*Set MAC->PHY MCH period stopping point*/
void set_mch_period_stop(uint32_t stop);
float get_phr(); float get_phr();

@ -26,6 +26,7 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <sstream>
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "srsue/hdr/phy/phch_common.h" #include "srsue/hdr/phy/phch_common.h"
@ -71,6 +72,8 @@ phch_common::phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_)
reset(); reset();
sib13_configured = false;
mcch_configured = false;
} }
void phch_common::init(phy_interface_rrc::phy_cfg_t *_config, phy_args_t *_args, srslte::log *_log, srslte::radio *_radio, rrc_interface_phy *_rrc, mac_interface_phy *_mac) void phch_common::init(phy_interface_rrc::phy_cfg_t *_config, phy_args_t *_args, srslte::log *_log, srslte::radio *_radio, rrc_interface_phy *_rrc, mac_interface_phy *_mac)
@ -369,4 +372,172 @@ void phch_common::reset_ul()
*/ */
} }
/* Convert 6-bit maps to 10-element subframe tables
bitmap = |0|0|0|0|0|0|
subframe index = |1|2|3|6|7|8|
*/
void phch_common::build_mch_table()
{
// First reset tables
bzero(&mch_table[0], sizeof(uint8_t)*40);
// 40 element table represents 4 frames (40 subframes)
srslte::generate_mch_table(&mch_table[0], config->mbsfn.mbsfn_subfr_cnfg.subfr_alloc,(LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE == config->mbsfn.mbsfn_subfr_cnfg.subfr_alloc_num_frames)?1:4);
// Debug
std::stringstream ss;
ss << "|";
for(uint32_t j=0; j<40; j++) {
ss << (int) mch_table[j] << "|";
}
Info("MCH table: %s\n", ss.str().c_str());
}
void phch_common::build_mcch_table()
{
// First reset tables
bzero(&mcch_table[0], sizeof(uint8_t)*10);
srslte::generate_mcch_table(&mcch_table[0], config->mbsfn.mbsfn_area_info.sf_alloc_info_r9);
// Debug
std::stringstream ss;
ss << "|";
for(uint32_t j=0; j<10; j++) {
ss << (int) mcch_table[j] << "|";
}
Info("MCCH table: %s\n", ss.str().c_str());
sib13_configured = true;
}
void phch_common::set_mcch()
{
mcch_configured = true;
}
void phch_common::set_mch_period_stop(uint32_t stop)
{
pthread_mutex_lock(&mtch_mutex);
have_mtch_stop = true;
mch_period_stop = stop;
pthread_cond_signal(&mtch_cvar);
pthread_mutex_unlock(&mtch_mutex);
}
bool phch_common::is_mch_subframe(subframe_cfg_t *cfg, uint32_t phy_tti)
{
uint32_t sfn; // System Frame Number
uint8_t sf; // Subframe
uint8_t offset;
uint8_t period;
sfn = phy_tti/10;
sf = phy_tti%10;
// Set some defaults
cfg->mbsfn_area_id = 0;
cfg->non_mbsfn_region_length = 1;
cfg->mbsfn_mcs = 2;
cfg->mbsfn_decode = false;
cfg->is_mcch = false;
// Check for MCCH
if(is_mcch_subframe(cfg, phy_tti)) {
cfg->is_mcch = true;
return true;
}
// Not MCCH, check for MCH
LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT *subfr_cnfg = &config->mbsfn.mbsfn_subfr_cnfg;
LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT *area_info = &config->mbsfn.mbsfn_area_info;
offset = subfr_cnfg->radio_fr_alloc_offset;
period = liblte_rrc_radio_frame_allocation_period_num[subfr_cnfg->radio_fr_alloc_period];
if(LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE == subfr_cnfg->subfr_alloc_num_frames) {
if((sfn%period == offset) && (mch_table[sf] > 0)) {
if(sib13_configured) {
cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9;
cfg->non_mbsfn_region_length = liblte_rrc_non_mbsfn_region_length_num[area_info->non_mbsfn_region_length];
if(mcch_configured) {
// Iterate through PMCH configs to see which one applies in the current frame
LIBLTE_RRC_MCCH_MSG_STRUCT *mcch = &config->mbsfn.mcch;
uint32_t mbsfn_per_frame = mcch->pmch_infolist_r9[0].pmch_config_r9.sf_alloc_end_r9/mcch->pmch_infolist_r9[0].pmch_config_r9.mch_schedulingperiod_r9;
uint32_t frame_alloc_idx = sfn%liblte_rrc_mbsfn_common_sf_alloc_period_r9_num[mcch->commonsf_allocperiod_r9];
uint32_t sf_alloc_idx = frame_alloc_idx*mbsfn_per_frame + ((sf<4)?sf-1:sf-3);
pthread_mutex_lock(&mtch_mutex);
while(!have_mtch_stop) {
pthread_cond_wait(&mtch_cvar, &mtch_mutex);
}
pthread_mutex_unlock(&mtch_mutex);
for(uint32_t i=0; i<mcch->pmch_infolist_r9_size; i++) {
if(sf_alloc_idx <= mch_period_stop) {
//trigger conditional variable, has ot be untriggered by mtch stop location
cfg->mbsfn_mcs = mcch->pmch_infolist_r9[i].pmch_config_r9.datamcs_r9;
cfg->mbsfn_decode = true;
} else {
//have_mtch_stop = false;
}
}
Debug("MCH subframe TTI:%d\n", phy_tti);
}
}
return true;
}
}else if(LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_FOUR == subfr_cnfg->subfr_alloc_num_frames) {
uint8_t idx = sfn%period;
if((idx >= offset) && (idx < offset+4)) {
if(mch_table[(idx*10)+sf] > 0){
if(sib13_configured) {
cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9;
cfg->non_mbsfn_region_length = liblte_rrc_non_mbsfn_region_length_num[area_info->non_mbsfn_region_length];
// TODO: check for MCCH configuration, set MCS and decode
}
return true;
}
}
}
return false;
}
bool phch_common::is_mcch_subframe(subframe_cfg_t *cfg, uint32_t phy_tti)
{
uint32_t sfn; // System Frame Number
uint8_t sf; // Subframe
uint8_t offset;
uint8_t period;
sfn = phy_tti/10;
sf = phy_tti%10;
if(sib13_configured) {
LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT *subfr_cnfg = &config->mbsfn.mbsfn_subfr_cnfg;
LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT *area_info = &config->mbsfn.mbsfn_area_info;
offset = area_info->mcch_offset_r9;
period = liblte_rrc_mcch_repetition_period_r9_num[area_info->mcch_repetition_period_r9];
if((sfn%period == offset) && mcch_table[sf] > 0) {
cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9;
cfg->non_mbsfn_region_length = liblte_rrc_non_mbsfn_region_length_num[area_info->non_mbsfn_region_length];
cfg->mbsfn_mcs = liblte_rrc_mcch_signalling_mcs_r9_num[area_info->signalling_mcs_r9];
cfg->mbsfn_decode = true;
have_mtch_stop = false;
Debug("MCCH subframe TTI:%d\n", phy_tti);
return true;
}
}
return false;
}
void phch_common::get_sf_config(subframe_cfg_t *cfg, uint32_t phy_tti)
{
if(is_mch_subframe(cfg, phy_tti)) {
cfg->sf_type = SUBFRAME_TYPE_MBSFN;
}else{
cfg->sf_type = SUBFRAME_TYPE_REGULAR;
}
}
} }

@ -158,6 +158,10 @@ bool phch_worker::set_cell(srslte_cell_t cell_)
goto unlock; goto unlock;
} }
if(srslte_ue_dl_set_mbsfn_area_id(&ue_dl, 1)){
Error("Setting mbsfn id\n");
}
if (srslte_ue_ul_set_cell(&ue_ul, cell)) { if (srslte_ue_ul_set_cell(&ue_ul, cell)) {
Error("Initiating UE UL\n"); Error("Initiating UE UL\n");
goto unlock; goto unlock;
@ -247,6 +251,10 @@ void phch_worker::work_imp()
reset_uci(); reset_uci();
subframe_cfg_t sf_cfg;
phy->get_sf_config(&sf_cfg, tti);
Debug("TTI: %d, Subframe type: %s\n", tti, subframe_type_text[sf_cfg.sf_type]);
bool dl_grant_available = false; bool dl_grant_available = false;
bool ul_grant_available = false; bool ul_grant_available = false;
bool dl_ack[SRSLTE_MAX_CODEWORDS] = {false}; bool dl_ack[SRSLTE_MAX_CODEWORDS] = {false};
@ -266,15 +274,27 @@ void phch_worker::work_imp()
phy->avg_rssi_dbm = SRSLTE_VEC_EMA(rssi_dbm, phy->avg_rssi_dbm, phy->args->snr_ema_coeff); phy->avg_rssi_dbm = SRSLTE_VEC_EMA(rssi_dbm, phy->avg_rssi_dbm, phy->args->snr_ema_coeff);
} }
/* Do FFT and extract PDCCH LLR, or quit if no actions are required in this subframe */ bool mch_decoded = false;
bool chest_ok = extract_fft_and_pdcch_llr(); srslte_ra_dl_grant_t mch_grant;
// Call feedback loop for chest // Call feedback loop for chest
if (chest_loop && ((1<<(tti%10)) & phy->args->cfo_ref_mask)) { if (chest_loop && ((1<<(tti%10)) & phy->args->cfo_ref_mask)) {
chest_loop->set_cfo(srslte_chest_dl_get_cfo(&ue_dl.chest)); chest_loop->set_cfo(srslte_chest_dl_get_cfo(&ue_dl.chest));
} }
bool chest_ok = false;
bool snr_th_ok = false;
if (chest_ok) { /***** Downlink Processing *******/
if(SUBFRAME_TYPE_REGULAR == sf_cfg.sf_type) {
/* Do FFT and extract PDCCH LLR, or quit if no actions are required in this subframe */
chest_ok = extract_fft_and_pdcch_llr(sf_cfg);
snr_th_ok = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))>1.0;
if (chest_ok && snr_th_ok) {
/***** Downlink Processing *******/ /***** Downlink Processing *******/
@ -311,6 +331,47 @@ void phch_worker::work_imp()
} }
} }
} else if(SUBFRAME_TYPE_MBSFN == sf_cfg.sf_type) {
srslte_ue_dl_set_non_mbsfn_region(&ue_dl, sf_cfg.non_mbsfn_region_length);
/* Do FFT and extract PDCCH LLR, or quit if no actions are required in this subframe */
if (extract_fft_and_pdcch_llr(sf_cfg)) {
dl_grant_available = decode_pdcch_dl(&dl_mac_grant);
phy->mac->new_grant_dl(dl_mac_grant, &dl_action);
/* Set DL ACKs to default */
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
dl_ack[tb] = dl_action.default_ack[tb];
}
if(sf_cfg.mbsfn_decode) {
mch_grant.sf_type = SRSLTE_SF_MBSFN;
mch_grant.mcs[0].idx = sf_cfg.mbsfn_mcs;
mch_grant.tb_en[0] = true;
for(uint32_t i=1;i<SRSLTE_MAX_CODEWORDS;i++) {
mch_grant.tb_en[i] = false;
}
mch_grant.nof_prb = ue_dl.pmch.cell.nof_prb;
srslte_dl_fill_ra_mcs(&mch_grant.mcs[0], mch_grant.nof_prb);
for(int j = 0; j < 2; j++){
for(uint32_t f = 0; f < mch_grant.nof_prb; f++){
mch_grant.prb_idx[j][f] = true;
}
}
mch_grant.Qm[0] = srslte_mod_bits_x_symbol(mch_grant.mcs[0].mod);
/* Get MCH action for this TB */
phy->mac->new_mch_dl(mch_grant, &dl_action);
srslte_softbuffer_rx_reset_tbs(dl_action.softbuffers[0], mch_grant.mcs[0].tbs);
Debug("TBS=%d, Softbuffer max_cb=%d\n", mch_grant.mcs[0].tbs, dl_action.softbuffers[0]->max_cb);
if(dl_action.decode_enabled[0]) {
mch_decoded = decode_pmch(&mch_grant, dl_action.payload_ptr[0], dl_action.softbuffers[0], sf_cfg.mbsfn_area_id);
}
}
}
}
// Process RAR before UL to enable zero-delay Msg3 // Process RAR before UL to enable zero-delay Msg3
bool rar_delivered = false; bool rar_delivered = false;
if (HARQ_DELAY_MS == MSG3_DELAY_MS && dl_mac_grant.rnti_type == SRSLTE_RNTI_RAR) { if (HARQ_DELAY_MS == MSG3_DELAY_MS && dl_mac_grant.rnti_type == SRSLTE_RNTI_RAR) {
@ -390,6 +451,7 @@ void phch_worker::work_imp()
phy->worker_end(tx_tti, signal_ready, &signal_ptr[-next_offset], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); phy->worker_end(tx_tti, signal_ready, &signal_ptr[-next_offset], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time);
} }
if(SUBFRAME_TYPE_REGULAR == sf_cfg.sf_type) {
if (!dl_action.generate_ack_callback) { if (!dl_action.generate_ack_callback) {
if (dl_mac_grant.rnti_type == SRSLTE_RNTI_PCH && dl_action.decode_enabled[0]) { if (dl_mac_grant.rnti_type == SRSLTE_RNTI_PCH && dl_action.decode_enabled[0]) {
if (dl_ack[0]) { if (dl_ack[0]) {
@ -403,8 +465,17 @@ void phch_worker::work_imp()
} }
} }
} }
} else if (SUBFRAME_TYPE_MBSFN == sf_cfg.sf_type && sf_cfg.mbsfn_decode) {
if(mch_decoded) {
phy->mac->mch_decoded_ok(mch_grant.mcs[0].tbs/8);
} else if(sf_cfg.is_mcch) {
//release lock in phch_common
phy->set_mch_period_stop(0);
}
}
if(SUBFRAME_TYPE_REGULAR == sf_cfg.sf_type){
update_measurements(); update_measurements();
}
if (chest_ok) { if (chest_ok) {
if (phy->avg_rsrp_sync_dbm > -130.0 && phy->avg_snr_db_sync > -10.0) { if (phy->avg_rsrp_sync_dbm > -130.0 && phy->avg_snr_db_sync > -10.0) {
@ -452,7 +523,9 @@ void phch_worker::compute_ri(uint8_t *ri, uint8_t *pmi, float *sinr) {
} }
} }
bool phch_worker::extract_fft_and_pdcch_llr() {
bool phch_worker::extract_fft_and_pdcch_llr(subframe_cfg_t sf_cfg) {
bool decode_pdcch = true; bool decode_pdcch = true;
// Do always channel estimation to keep track of out-of-sync and send measurements to RRC // Do always channel estimation to keep track of out-of-sync and send measurements to RRC
@ -471,19 +544,22 @@ bool phch_worker::extract_fft_and_pdcch_llr() {
srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_PSS); srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_PSS);
} }
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, tti%10, &cfi) < 0) {
Error("Getting PDCCH FFT estimate\n");
return false;
}
chest_done = true;
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, tti%10, &cfi) < 0) { int decode_fft = 0;
if(SUBFRAME_TYPE_MBSFN == sf_cfg.sf_type) {
srslte_ue_dl_set_non_mbsfn_region(&ue_dl, sf_cfg.non_mbsfn_region_length);
decode_fft = srslte_ue_dl_decode_fft_estimate_mbsfn(&ue_dl, tti%10, &cfi, SRSLTE_SF_MBSFN);
}else{
decode_fft = srslte_ue_dl_decode_fft_estimate(&ue_dl, tti%10, &cfi);
}
if (decode_fft < 0) {
Error("Getting PDCCH FFT estimate\n"); Error("Getting PDCCH FFT estimate\n");
return false; return false;
} }
chest_done = true; chest_done = true;
if (chest_done && decode_pdcch) { /* and not in DRX mode */ if (chest_done && decode_pdcch) { /* and not in DRX mode */
float noise_estimate = phy->avg_noise; float noise_estimate = phy->avg_noise;
@ -748,6 +824,73 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
return ret; return ret;
} }
bool phch_worker::decode_pmch(srslte_ra_dl_grant_t *grant, uint8_t *payload,
srslte_softbuffer_rx_t* softbuffer, uint16_t mbsfn_area_id)
{
char timestr[64];
timestr[0]='\0';
Debug("DL Buffer TTI %d: Decoding PMCH\n", tti);
/* Setup PMCH configuration */
srslte_ue_dl_set_mbsfn_area_id(&ue_dl, mbsfn_area_id);
if (!srslte_ue_dl_cfg_grant(&ue_dl, grant, cfi, tti%10, SRSLTE_PMCH_RV, SRSLTE_MIMO_TYPE_SINGLE_ANTENNA)) {
if (ue_dl.pmch_cfg.grant.mcs[0].mod > 0 && ue_dl.pmch_cfg.grant.mcs[0].tbs >= 0) {
Debug("Decoding PMCH SF: %d, MBSFN area ID: 0x%x, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d, C_prb=%d, cfi=%d\n",
ue_dl.pmch_cfg.sf_idx, mbsfn_area_id, srslte_mod_string(ue_dl.pmch_cfg.grant.mcs[0].mod), ue_dl.pmch_cfg.grant.mcs[0].tbs, ue_dl.pmch_cfg.nbits[0].nof_re,
ue_dl.pmch_cfg.nbits[0].nof_bits, 0, ue_dl.pmch_cfg.grant.nof_prb, ue_dl.pmch_cfg.nbits[0].lstart-1);
float noise_estimate = srslte_chest_dl_get_noise_estimate(&ue_dl.chest);
if (!phy->args->equalizer_mode.compare("zf")) {
noise_estimate = 0;
}
/* Set decoder iterations */
// TODO: Add separate arg for pmch_max_its
if (phy->args->pdsch_max_its > 0) {
srslte_sch_set_max_noi(&ue_dl.pmch.dl_sch, phy->args->pdsch_max_its);
}
#ifdef LOG_EXECTIME
struct timeval t[3];
gettimeofday(&t[1], NULL);
#endif
bool ack = srslte_pmch_decode_multi(&ue_dl.pmch, &ue_dl.pmch_cfg, softbuffer, ue_dl.sf_symbols_m,
ue_dl.ce_m, noise_estimate, mbsfn_area_id, payload) == 0;
#ifdef LOG_EXECTIME
gettimeofday(&t[2], NULL);
get_time_interval(t);
snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec);
#endif
Info("PMCH: l_crb=%2d, tbs=%d, mcs=%d, crc=%s, snr=%.1f dB, n_iter=%d%s\n",
grant->nof_prb,
grant->mcs[0].tbs/8, grant->mcs[0].idx,
ack?"OK":"KO",
10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)),
srslte_pmch_last_noi(&ue_dl.pmch),
timestr);
//printf("tti=%d, cfo=%f\n", tti, cfo*15000);
//srslte_vec_save_file("pdsch", signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
// Store metrics
//dl_metrics.mcs = grant->mcs.idx;
return ack;
} else {
Warning("Received grant for TBS=0\n");
}
} else {
Error("Error configuring DL grant\n");
}
return true;
}
bool phch_worker::decode_phich(bool *ack) bool phch_worker::decode_phich(bool *ack)
{ {
uint32_t I_lowest, n_dmrs; uint32_t I_lowest, n_dmrs;

@ -437,4 +437,40 @@ void phy::set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT* tdd)
memcpy(&config.common.tdd_cnfg, tdd, sizeof(LIBLTE_RRC_TDD_CONFIG_STRUCT)); memcpy(&config.common.tdd_cnfg, tdd, sizeof(LIBLTE_RRC_TDD_CONFIG_STRUCT));
} }
void phy::set_config_mbsfn_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2)
{
if(sib2->mbsfn_subfr_cnfg_list_size > 1) {
Warning("SIB2 has %d MBSFN subframe configs - only 1 supported\n", sib2->mbsfn_subfr_cnfg_list_size);
}
if(sib2->mbsfn_subfr_cnfg_list_size > 0) {
memcpy(&config.mbsfn.mbsfn_subfr_cnfg, &sib2->mbsfn_subfr_cnfg_list[0], sizeof(LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT));
workers_common.build_mch_table();
}
}
void phy::set_config_mbsfn_sib13(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13)
{
memcpy(&config.mbsfn.mbsfn_notification_cnfg, &sib13->mbsfn_notification_config, sizeof(LIBLTE_RRC_MBSFN_NOTIFICATION_CONFIG_STRUCT));
if(sib13->mbsfn_area_info_list_r9_size > 1) {
Warning("SIB13 has %d MBSFN area info elements - only 1 supported\n", sib13->mbsfn_area_info_list_r9_size);
}
if(sib13->mbsfn_area_info_list_r9_size > 0) {
memcpy(&config.mbsfn.mbsfn_area_info, &sib13->mbsfn_area_info_list_r9[0], sizeof(LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT));
workers_common.build_mcch_table();
}
}
void phy::set_config_mbsfn_mcch(LIBLTE_RRC_MCCH_MSG_STRUCT *mcch)
{
memcpy(&config.mbsfn.mcch, mcch, sizeof(LIBLTE_RRC_MCCH_MSG_STRUCT));
mac->set_mbsfn_config(config.mbsfn.mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9_size);
workers_common.set_mch_period_stop(config.mbsfn.mcch.pmch_infolist_r9[0].pmch_config_r9.sf_alloc_end_r9);
workers_common.set_mcch();
}
void phy::set_mch_period_stop(uint32_t stop)
{
workers_common.set_mch_period_stop(stop);
}
} }

Loading…
Cancel
Save