5G-MAG Reference Tools - MBMS Modem
Public Member Functions | Private Attributes | Static Private Attributes | List of all members
MbsfnFrameProcessor Class Reference

Frame processor for MBSFN subframes. More...

#include <MbsfnFrameProcessor.h>

Collaboration diagram for MbsfnFrameProcessor:
Collaboration graph

Public Member Functions

 MbsfnFrameProcessor (const libconfig::Config &cfg, srsran::rlc &rlc, Phy &phy, srslog::basic_logger &log_h, RestHandler &rest, unsigned rx_channels)
 Default constructor. More...
 
virtual ~MbsfnFrameProcessor ()
 Default destructor. More...
 
bool init ()
 Initialize signal- and softbuffers, init all underlying components. More...
 
int process (uint32_t tti)
 Process the sample data in the signal buffer. More...
 
void set_cell (srsran_cell_t cell)
 Set the parameters for the cell (Nof PRB, etc). More...
 
cf_t ** get_rx_buffer_and_lock ()
 Get a handle of the signal buffer to store samples for processing in, and lock this processor. More...
 
uint32_t rx_buffer_size ()
 Size of the signal buffer. More...
 
void configure_mbsfn (uint8_t area_id, srsran_scs_t subcarrier_spacing)
 Set MBSFN parameters: area ID and subcarrier spacing. More...
 
bool mbsfn_configured ()
 Returns tru if MBSFN params have already been configured. More...
 
void unlock ()
 Unlock the processor. More...
 
void lock ()
 Lock the processor. More...
 
const std::vector< uint8_t > mch_data () const
 Get the constellation diagram data (I/Q data of the subcarriers after CE) More...
 
float cinr_db ()
 Get the CINR estimate (in dB) More...
 

Private Attributes

const libconfig::Config & _cfg
 
srsran::rlc & _rlc
 
Phy_phy
 
srsran_cell_t _cell
 
cf_t * _signal_buffer_rx [SRSRAN_MAX_PORTS] = {}
 
uint32_t _signal_buffer_max_samples = 0
 
uint8_t _payload_buffer [_payload_buffer_sz]
 
srsran_softbuffer_rx_t _softbuffer
 
srsran_ue_dl_t _ue_dl = {}
 
srsran_ue_dl_cfg_t _ue_dl_cfg = {}
 
srsran_dl_sf_cfg_t _sf_cfg = {}
 
srsran_pmch_cfg_t _pmch_cfg = {}
 
uint8_t _area_id = 1
 
bool _mbsfn_configured = false
 
srsran::mch_pdu mch_mac_msg
 
std::mutex _mutex
 
RestHandler_rest
 
unsigned _rx_channels
 
bool _allow_rrc_sn_across_periods = false
 

Static Private Attributes

static const uint32_t _payload_buffer_sz = SRSRAN_MAX_BUFFER_SIZE_BYTES
 
static std::mutex _sched_stop_mutex
 
static std::map< uint8_t, uint16_t > _sched_stops
 
static std::mutex _rlc_mutex
 
static int _current_mcs
 

Detailed Description

Frame processor for MBSFN subframes.

Handles the complete processing chain for a CAS subframe: calls FFT and channel estimation, decodes PDSCH and passes received PDUs to RLC.

Definition at line 39 of file MbsfnFrameProcessor.h.

Constructor & Destructor Documentation

◆ MbsfnFrameProcessor()

MbsfnFrameProcessor::MbsfnFrameProcessor ( const libconfig::Config &  cfg,
srsran::rlc &  rlc,
Phy phy,
srslog::basic_logger &  log_h,
RestHandler rest,
unsigned  rx_channels 
)
inline

Default constructor.

Parameters
cfgConfig singleton reference
phyPHY reference
rlcRLC reference
log_hsrsLTE log handle for the MCH MAC msg decoder
restRESTful API handler reference

Definition at line 50 of file MbsfnFrameProcessor.h.

51  : _cfg(cfg)
52  , _rlc(rlc)
53  , _phy(phy)
54  , _rest(rest)
55  , mch_mac_msg(20, log_h)
56  , _rx_channels(rx_channels)
57  {
59  cfg.lookupValue("modem.phy.allow_rrc_sn_across_periods", _allow_rrc_sn_across_periods);
60  }
srsran::mch_pdu mch_mac_msg
const libconfig::Config & _cfg
static Config cfg
Global configuration object.
Definition: main.cpp:172

◆ ~MbsfnFrameProcessor()

MbsfnFrameProcessor::~MbsfnFrameProcessor ( )
virtual

Default destructor.

Definition at line 73 of file MbsfnFrameProcessor.cpp.

73  {
74  srsran_softbuffer_rx_free(&_softbuffer);
75  srsran_ue_dl_free(&_ue_dl);
76 }
srsran_softbuffer_rx_t _softbuffer

Member Function Documentation

◆ cinr_db()

float MbsfnFrameProcessor::cinr_db ( )
inline

Get the CINR estimate (in dB)

Definition at line 135 of file MbsfnFrameProcessor.h.

135 { return _ue_dl.chest_res.snr_db; }

◆ configure_mbsfn()

void MbsfnFrameProcessor::configure_mbsfn ( uint8_t  area_id,
srsran_scs_t  subcarrier_spacing 
)

Set MBSFN parameters: area ID and subcarrier spacing.

Definition at line 246 of file MbsfnFrameProcessor.cpp.

246  {
247  _sf_cfg.subcarrier_spacing = subcarrier_spacing;
248  srsran_ue_dl_set_mbsfn_subcarrier_spacing(&_ue_dl, subcarrier_spacing);
249 
250 
251  srsran_ue_dl_set_mbsfn_area_id(&_ue_dl, area_id);
252  _area_id = area_id;
253  _mbsfn_configured = true;
254 }
srsran_dl_sf_cfg_t _sf_cfg

◆ get_rx_buffer_and_lock()

cf_t** MbsfnFrameProcessor::get_rx_buffer_and_lock ( )
inline

Get a handle of the signal buffer to store samples for processing in, and lock this processor.

The processor unlocks itself after (failed or successful) frame processing in process(). If process() is not called by the application after calling this method, it must unlock the processor itself by calling unlock()

Definition at line 96 of file MbsfnFrameProcessor.h.

96 { _mutex.lock(); return _signal_buffer_rx; }
cf_t * _signal_buffer_rx[SRSRAN_MAX_PORTS]

◆ init()

auto MbsfnFrameProcessor::init ( )

Initialize signal- and softbuffers, init all underlying components.

Must be called once before the first call to process().

Definition at line 28 of file MbsfnFrameProcessor.cpp.

28  {
29  _signal_buffer_max_samples = 3 * SRSRAN_SF_LEN_PRB(MAX_PRB);
30 
31  for (auto ch = 0; ch < _rx_channels; ch++) {
32  _signal_buffer_rx[ch] = srsran_vec_cf_malloc(_signal_buffer_max_samples);
33  if (!_signal_buffer_rx[ch]) {
34  spdlog::error("Could not allocate regular DL signal buffer\n");
35  return false;
36  }
37  }
38 
39  if (srsran_ue_dl_init(&_ue_dl, _signal_buffer_rx, MAX_PRB, _rx_channels) != 0) {
40  spdlog::error("Could not init ue_dl\n");
41  return false;;
42  }
43 
44  srsran_softbuffer_rx_init(&_softbuffer, 100);
45 
46  _ue_dl_cfg.snr_to_cqi_offset = 0;
47 
48  srsran_chest_dl_cfg_t* chest_cfg = &_ue_dl_cfg.chest_cfg;
49  bzero(chest_cfg, sizeof(srsran_chest_dl_cfg_t));
50  chest_cfg->filter_coef[0] = 0.1;
51  chest_cfg->filter_type = SRSRAN_CHEST_FILTER_NONE;
52  chest_cfg->noise_alg = SRSRAN_NOISE_ALG_EMPTY;
53  chest_cfg->rsrp_neighbour = false;
54  chest_cfg->sync_error_enable = true;
55  chest_cfg->estimator_alg = SRSRAN_ESTIMATOR_ALG_INTERPOLATE;
56  chest_cfg->cfo_estimate_enable = false;
57 
58  _ue_dl_cfg.cfg.pdsch.csi_enable = true;
59  _ue_dl_cfg.cfg.pdsch.max_nof_iterations = 8;
60  _ue_dl_cfg.cfg.pdsch.meas_evm_en = false;
61  _ue_dl_cfg.cfg.pdsch.decoder_type = SRSRAN_MIMO_DECODER_MMSE;
62  _ue_dl_cfg.cfg.pdsch.softbuffers.rx[0] = &_softbuffer;
63 
64  _pmch_cfg.pdsch_cfg.csi_enable = true;
65  _pmch_cfg.pdsch_cfg.max_nof_iterations = 8;
66  _pmch_cfg.pdsch_cfg.meas_evm_en = false;
67  _pmch_cfg.pdsch_cfg.decoder_type = SRSRAN_MIMO_DECODER_MMSE;
68 
69  _sf_cfg.sf_type = SRSRAN_SF_MBSFN;
70  return true;
71 }
constexpr unsigned int MAX_PRB
Definition: Phy.h:35
srsran_ue_dl_cfg_t _ue_dl_cfg
srsran_pmch_cfg_t _pmch_cfg

◆ lock()

void MbsfnFrameProcessor::lock ( )
inline

Lock the processor.

Used when getting the BLER values.

Definition at line 125 of file MbsfnFrameProcessor.h.

125 { _mutex.lock(); }

◆ mbsfn_configured()

bool MbsfnFrameProcessor::mbsfn_configured ( )
inline

Returns tru if MBSFN params have already been configured.

Definition at line 111 of file MbsfnFrameProcessor.h.

111 { return _mbsfn_configured; }

◆ mch_data()

auto MbsfnFrameProcessor::mch_data ( ) const

Get the constellation diagram data (I/Q data of the subcarriers after CE)

Definition at line 256 of file MbsfnFrameProcessor.cpp.

256  {
257  const uint8_t* data = reinterpret_cast<uint8_t*>(_ue_dl.pmch.d);
258  return std::move(std::vector<uint8_t>( data, data + _pmch_cfg.pdsch_cfg.grant.nof_re * sizeof(cf_t)));
259 }

◆ process()

auto MbsfnFrameProcessor::process ( uint32_t  tti)

Process the sample data in the signal buffer.

Data must already be present in the buffer obtained through the handle returnd by rx_buffer()

Parameters
ttiTTI of the subframe the data belongs to

Definition at line 83 of file MbsfnFrameProcessor.cpp.

83  {
84  spdlog::trace("Processing MBSFN TTI {}", tti);
85 
86  uint32_t sfn = tti / 10;
87  uint8_t sf = tti % 10;
88 
89  unsigned mch_idx = 0;
90  _sf_cfg.tti = tti;
91  _pmch_cfg.area_id = _area_id;
92  srsran_mbsfn_cfg_t mbsfn_cfg = _phy.mbsfn_config_for_tti(tti, mch_idx);
93  _ue_dl_cfg.chest_cfg.mbsfn_area_id = _area_id;
94  //srsran_ue_dl_set_mbsfn_area_id(&_ue_dl, mbsfn_cfg.mbsfn_area_id);
95 
96  if (!_cell.mbms_dedicated) {
97  srsran_ue_dl_set_non_mbsfn_region(&_ue_dl, mbsfn_cfg.non_mbsfn_region_length);
98  }
99 
100  if (!mbsfn_cfg.enable) {
101  spdlog::trace("PMCH: tti {}: neither MCCH nor MCH enabled. Skipping subframe");
102  _mutex.unlock();
103  return -1;
104  }
105 
106  if (mbsfn_cfg.is_mcch) {
107  _rest._mcch.total++;
108  } else {
109  _rest._mch[mch_idx].total++;
110  }
111 
112  if (srsran_ue_dl_decode_fft_estimate(&_ue_dl, &_sf_cfg, &_ue_dl_cfg) < 0) {
113  if (mbsfn_cfg.is_mcch) {
114  _rest._mcch.errors++;
115  } else {
116  _rest._mch[mch_idx].errors++;
117  }
118  spdlog::error("Getting PDCCH FFT estimate");
119  _mutex.unlock();
120  return -1;
121  }
122 
123  srsran_configure_pmch(&_pmch_cfg, &_cell, &mbsfn_cfg);
124  srsran_ra_dl_compute_nof_re(&_cell, &_sf_cfg, &_pmch_cfg.pdsch_cfg.grant);
125 
126  _pmch_cfg.area_id = _area_id;
127 
128  srsran_softbuffer_rx_reset_cb(&_softbuffer, 1);
129 
130  srsran_pdsch_res_t pmch_dec = {};
131  _pmch_cfg.pdsch_cfg.softbuffers.rx[0] = &_softbuffer;
132  pmch_dec.payload = _payload_buffer;
133  srsran_softbuffer_rx_reset_tbs(_pmch_cfg.pdsch_cfg.softbuffers.rx[0], _pmch_cfg.pdsch_cfg.grant.tb[0].tbs);
134 
135  if (srsran_ue_dl_decode_pmch(&_ue_dl, &_sf_cfg, &_pmch_cfg, &pmch_dec) != 0) {
136  if (mbsfn_cfg.is_mcch) {
137  _rest._mcch.errors++;
138  } else {
139  _rest._mch[mch_idx].errors++;
140  }
141  spdlog::warn("Error decoding PMCH");
142  _mutex.unlock();
143  return -1;
144  }
145 
146  spdlog::trace("PMCH: tti: {}, l_crb={}, tbs={}, mcs={}, crc={}, snr={} dB, n_iter={}\n",
147  tti,
148  _pmch_cfg.pdsch_cfg.grant.nof_prb,
149  _pmch_cfg.pdsch_cfg.grant.tb[0].tbs / 8,
150  _pmch_cfg.pdsch_cfg.grant.tb[0].mcs_idx,
151  pmch_dec.crc ? "OK" : "KO",
152  _ue_dl.chest_res.snr_db,
153  pmch_dec.avg_iterations_block);
154 
155  if (mbsfn_cfg.is_mcch) {
157  _rest._mcch.mcs = _pmch_cfg.pdsch_cfg.grant.tb[0].mcs_idx;
158  } else {
159  _rest._mch[mch_idx].SetData(mch_data());
160  _rest._mch[mch_idx].mcs = _pmch_cfg.pdsch_cfg.grant.tb[0].mcs_idx;
161  _rest._mch[mch_idx].present = true;
162  }
163 
164  if (pmch_dec.crc) {
165  mch_mac_msg.init_rx(
166  static_cast<uint32_t>(_pmch_cfg.pdsch_cfg.grant.tb[0].tbs) / 8);
167  mch_mac_msg.parse_packet(_payload_buffer);
168 
169  while (mch_mac_msg.next()) {
170  if (srsran::mch_lcid::MCH_SCHED_INFO == mch_mac_msg.get()->mch_ce_type()) {
171  uint16_t stop = 0;
172  uint8_t lcid = 0;
173  while (mch_mac_msg.get()->get_next_mch_sched_info(&lcid, &stop)) {
174  const std::lock_guard<std::mutex> lock(_sched_stop_mutex);
175  spdlog::debug("Scheduling stop for LCID {} in sf {}", lcid, stop);
176  _sched_stops[ lcid ] = stop;
177  }
178  } else if (mch_mac_msg.get()->is_sdu()) {
179  uint32_t lcid = mch_mac_msg.get()->get_sdu_lcid();
180  spdlog::trace("Processing MAC MCH PDU entered, lcid {}", lcid);
181 
182  if (lcid >= SRSRAN_N_MCH_LCIDS) {
183  spdlog::warn("Radio bearer id must be in [0:%d] - %d", SRSRAN_N_MCH_LCIDS, lcid);
184  if (mbsfn_cfg.is_mcch) {
185  _rest._mcch.errors++;
186  } else {
187  _rest._mch[mch_idx].errors++;
188  }
189  _mutex.unlock();
190  return -1;
191  }
192 
193  {
194  _phy._mcs = mbsfn_cfg.mbsfn_mcs;
195  const std::lock_guard<std::mutex> lock(_rlc_mutex);
196  _rlc.write_pdu_mch(mch_idx, lcid, mch_mac_msg.get()->get_sdu_ptr(), mch_mac_msg.get()->get_payload_size());
197  }
198  }
199  }
200  } else {
201  if (mbsfn_cfg.is_mcch) {
202  _rest._mcch.errors++;
203  } else {
204  _rest._mch[mch_idx].errors++;
205  }
206 
207  spdlog::trace("PMCH in TTI {} failed with CRC error", tti);
208  _mutex.unlock();
209  return -1;
210  }
211 
212  if (!mbsfn_cfg.is_mcch) {
213  for (uint32_t i = 0; i < _phy.mcch().nof_pmch_info; i++) {
214  unsigned fn_in_scheduling_period = sfn % srsran::enum_to_number(_phy.mcch().pmch_info_list[i].mch_sched_period);
215  unsigned sf_idx;
216  if (_cell.mbms_dedicated) {
217  sf_idx = fn_in_scheduling_period * 10 + sf - (fn_in_scheduling_period / 4) - 1;
218  } else {
219  sf_idx = fn_in_scheduling_period * 6 + (sf < 6 ? sf - 1 : sf - 3);
220  }
221  spdlog::debug("tti{}, sfn {}, sf {}, fn_in_scheduling_period {}, sf_idf {}", tti, sfn, sf, fn_in_scheduling_period, sf_idx);
222 
223  const std::lock_guard<std::mutex> lock(_sched_stop_mutex);
224  for (auto itr = _sched_stops.cbegin() ; itr != _sched_stops.cend() ;) {
225  if ( sf_idx >= itr->second ) {
226  spdlog::debug("Stopping LCID {} in tti {} (idx in rf {})", itr->first, tti, sf_idx);
227  const std::lock_guard<std::mutex> lock(_rlc_mutex);
229  _rlc.stop_mch(i, itr->first);
230  }
231  itr = _sched_stops.erase(itr);
232  } else {
233  itr = std::next(itr);
234  }
235  }
236  }
237  } else {
238  const std::lock_guard<std::mutex> lock(_rlc_mutex);
239  _rlc.stop_mch(0, 0);
240  _rest._mcch.present = true;
241  }
242  _mutex.unlock();
243  return mbsfn_cfg.is_mcch ? 0 : 1;
244 }
static std::map< uint8_t, uint16_t > _sched_stops
void lock()
Lock the processor.
static std::mutex _rlc_mutex
uint8_t _payload_buffer[_payload_buffer_sz]
static std::mutex _sched_stop_mutex
const std::vector< uint8_t > mch_data() const
Get the constellation diagram data (I/Q data of the subcarriers after CE)
srsran_mbsfn_cfg_t mbsfn_config_for_tti(uint32_t tti, unsigned &area)
Returns the MBSFN configuration (MCS, etc) for the subframe with the passed TTI.
Definition: Phy.cpp:329
int _mcs
Definition: Phy.h:289
srsran::mcch_msg_t & mcch()
Definition: Phy.h:287
void SetData(std::vector< uint8_t > data)
Definition: RestHandler.h:80
ChannelInfo _mcch
RX info for MCCH.
Definition: RestHandler.h:134
std::map< uint32_t, ChannelInfo > _mch
RX info for MCHs.
Definition: RestHandler.h:139

◆ rx_buffer_size()

uint32_t MbsfnFrameProcessor::rx_buffer_size ( )
inline

Size of the signal buffer.

Definition at line 101 of file MbsfnFrameProcessor.h.

101 { return _signal_buffer_max_samples; }

◆ set_cell()

void MbsfnFrameProcessor::set_cell ( srsran_cell_t  cell)

Set the parameters for the cell (Nof PRB, etc).

Parameters
cellThe cell we're camping on

Definition at line 78 of file MbsfnFrameProcessor.cpp.

78  {
79  _cell = cell;
80  srsran_ue_dl_set_cell(&_ue_dl, cell);
81 }

◆ unlock()

void MbsfnFrameProcessor::unlock ( )
inline

Unlock the processor.

See also
get_rx_buffer_and_lock()

Definition at line 118 of file MbsfnFrameProcessor.h.

118 { _mutex.unlock(); }

Member Data Documentation

◆ _allow_rrc_sn_across_periods

bool MbsfnFrameProcessor::_allow_rrc_sn_across_periods = false
private

Definition at line 166 of file MbsfnFrameProcessor.h.

◆ _area_id

uint8_t MbsfnFrameProcessor::_area_id = 1
private

Definition at line 156 of file MbsfnFrameProcessor.h.

◆ _cell

srsran_cell_t MbsfnFrameProcessor::_cell
private

Definition at line 142 of file MbsfnFrameProcessor.h.

◆ _cfg

const libconfig::Config& MbsfnFrameProcessor::_cfg
private

Definition at line 138 of file MbsfnFrameProcessor.h.

◆ _current_mcs

int MbsfnFrameProcessor::_current_mcs
staticprivate

Definition at line 171 of file MbsfnFrameProcessor.h.

◆ _mbsfn_configured

bool MbsfnFrameProcessor::_mbsfn_configured = false
private

Definition at line 157 of file MbsfnFrameProcessor.h.

◆ _mutex

std::mutex MbsfnFrameProcessor::_mutex
private

Definition at line 160 of file MbsfnFrameProcessor.h.

◆ _payload_buffer

uint8_t MbsfnFrameProcessor::_payload_buffer[_payload_buffer_sz]
private

Definition at line 148 of file MbsfnFrameProcessor.h.

◆ _payload_buffer_sz

const uint32_t MbsfnFrameProcessor::_payload_buffer_sz = SRSRAN_MAX_BUFFER_SIZE_BYTES
staticprivate

Definition at line 147 of file MbsfnFrameProcessor.h.

◆ _phy

Phy& MbsfnFrameProcessor::_phy
private

Definition at line 140 of file MbsfnFrameProcessor.h.

◆ _pmch_cfg

srsran_pmch_cfg_t MbsfnFrameProcessor::_pmch_cfg = {}
private

Definition at line 154 of file MbsfnFrameProcessor.h.

◆ _rest

RestHandler& MbsfnFrameProcessor::_rest
private

Definition at line 162 of file MbsfnFrameProcessor.h.

◆ _rlc

srsran::rlc& MbsfnFrameProcessor::_rlc
private

Definition at line 139 of file MbsfnFrameProcessor.h.

◆ _rlc_mutex

std::mutex MbsfnFrameProcessor::_rlc_mutex
staticprivate

Definition at line 170 of file MbsfnFrameProcessor.h.

◆ _rx_channels

unsigned MbsfnFrameProcessor::_rx_channels
private

Definition at line 164 of file MbsfnFrameProcessor.h.

◆ _sched_stop_mutex

std::mutex MbsfnFrameProcessor::_sched_stop_mutex
staticprivate

Definition at line 167 of file MbsfnFrameProcessor.h.

◆ _sched_stops

std::map< uint8_t, uint16_t > MbsfnFrameProcessor::_sched_stops
staticprivate

Definition at line 168 of file MbsfnFrameProcessor.h.

◆ _sf_cfg

srsran_dl_sf_cfg_t MbsfnFrameProcessor::_sf_cfg = {}
private

Definition at line 153 of file MbsfnFrameProcessor.h.

◆ _signal_buffer_max_samples

uint32_t MbsfnFrameProcessor::_signal_buffer_max_samples = 0
private

Definition at line 145 of file MbsfnFrameProcessor.h.

◆ _signal_buffer_rx

cf_t* MbsfnFrameProcessor::_signal_buffer_rx[SRSRAN_MAX_PORTS] = {}
private

Definition at line 144 of file MbsfnFrameProcessor.h.

◆ _softbuffer

srsran_softbuffer_rx_t MbsfnFrameProcessor::_softbuffer
private

Definition at line 149 of file MbsfnFrameProcessor.h.

◆ _ue_dl

srsran_ue_dl_t MbsfnFrameProcessor::_ue_dl = {}
private

Definition at line 151 of file MbsfnFrameProcessor.h.

◆ _ue_dl_cfg

srsran_ue_dl_cfg_t MbsfnFrameProcessor::_ue_dl_cfg = {}
private

Definition at line 152 of file MbsfnFrameProcessor.h.

◆ mch_mac_msg

srsran::mch_pdu MbsfnFrameProcessor::mch_mac_msg
private

Definition at line 159 of file MbsfnFrameProcessor.h.


The documentation for this class was generated from the following files: