OBECA Receive Process
Public Member Functions | List of all members
CasFrameProcessor Class Reference

Frame processor for CAS subframes. More...

#include <CasFrameProcessor.h>

Public Member Functions

 CasFrameProcessor (const libconfig::Config &cfg, Phy &phy, srslte::rlc &rlc, RestHandler &rest)
 Default constructor. More...
 
virtual ~CasFrameProcessor ()
 Default destructor.
 
bool init ()
 Initialize signal- and softbuffers, init all underlying components. More...
 
bool process (uint32_t tti)
 Process the sample data in the signal buffer. More...
 
void set_cell (srslte_cell_t cell)
 Set the parameters for the cell (Nof PRB, etc). More...
 
cf_t ** rx_buffer ()
 Get a handle of the signal buffer to store samples for processing in.
 
uint32_t rx_buffer_size ()
 Size of the signal buffer.
 
std::vector< uint8_t > ce_values ()
 Get the CE values (time domain) for displaying the spectrum of the received signal.
 
std::vector< uint8_t > pdsch_data ()
 Get the constellation diagram data (I/Q data of the subcarriers after CE)
 
float cinr_db ()
 Get the CINR estimate (in dB)
 

Detailed Description

Frame processor for CAS subframes.

Handles the complete processing chain for a CAS subframe: calls FFT and channel estimation, decodes PCFICH and PDCCH and gets DCI(s), decodes PDSCH and passes received PDUs to RLC.

Definition at line 38 of file CasFrameProcessor.h.

Constructor & Destructor Documentation

◆ CasFrameProcessor()

CasFrameProcessor::CasFrameProcessor ( const libconfig::Config &  cfg,
Phy &  phy,
srslte::rlc &  rlc,
RestHandler &  rest 
)
inline

Default constructor.

Parameters
cfgConfig singleton reference
phyPHY reference
rlcRLC reference
restRESTful API handler reference

Definition at line 48 of file CasFrameProcessor.h.

49  : _cfg(cfg)
50  , _phy(phy)
51  , _rest(rest)
52  , _rlc(rlc) {}

Member Function Documentation

◆ init()

auto CasFrameProcessor::init ( )

Initialize signal- and softbuffers, init all underlying components.

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

Definition at line 24 of file CasFrameProcessor.cpp.

24  {
25  _signal_buffer_max_samples = 3 * SRSLTE_SF_LEN_PRB(MAX_PRB);
26 
27  _signal_buffer_rx[0] = srslte_vec_cf_malloc(_signal_buffer_max_samples);
28  if (!_signal_buffer_rx[0]) {
29  spdlog::error("Could not allocate regular DL signal buffer\n");
30  return false;
31  }
32 
33  if (srslte_ue_dl_init(&_ue_dl, _signal_buffer_rx, MAX_PRB, 1)) {
34  spdlog::error("Could not init ue_dl\n");
35  return false;;
36  }
37 
38  srslte_softbuffer_rx_init(&_softbuffer, 100);
39 
40  _ue_dl_cfg.snr_to_cqi_offset = 0;
41 
42  for (auto & i : _data) {
43  i = srslte_vec_u8_malloc(2000 * 8);
44  if (!i) {
45  spdlog::error("Allocating data");
46  return false;
47  }
48  }
49 
50  srslte_chest_dl_cfg_t* chest_cfg = &_ue_dl_cfg.chest_cfg;
51  bzero(chest_cfg, sizeof(srslte_chest_dl_cfg_t));
52  chest_cfg->filter_coef[0] = 4;
53  chest_cfg->filter_coef[1] = 1.0f;
54  chest_cfg->filter_type = SRSLTE_CHEST_FILTER_GAUSS;
55  chest_cfg->noise_alg = SRSLTE_NOISE_ALG_EMPTY;
56  chest_cfg->rsrp_neighbour = false;
57  chest_cfg->sync_error_enable = false;
58  chest_cfg->estimator_alg = SRSLTE_ESTIMATOR_ALG_AVERAGE;
59  chest_cfg->cfo_estimate_enable = true;
60  chest_cfg->cfo_estimate_sf_mask = 1023;
61 
62  _ue_dl_cfg.cfg.pdsch.csi_enable = true;
63  _ue_dl_cfg.cfg.pdsch.max_nof_iterations = 8;
64  _ue_dl_cfg.cfg.pdsch.meas_evm_en = false;
65  _ue_dl_cfg.cfg.pdsch.decoder_type = SRSLTE_MIMO_DECODER_MMSE;
66  _ue_dl_cfg.cfg.pdsch.softbuffers.rx[0] = &_softbuffer;
67 
68  return true;
69 }

◆ process()

auto CasFrameProcessor::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 87 of file CasFrameProcessor.cpp.

87  {
88  _sf_cfg.tti = tti;
89  _sf_cfg.sf_type = SRSLTE_SF_NORM;
90 
91  if ((tti/10)%100 == 0) {
92  _rest._pdsch.total = 0;
93  _rest._pdsch.errors = 0;
94  }
95 
96  _rest._pdsch.total++;
97 
98  // Run the FFT and do channel estimation
99  if (srslte_ue_dl_decode_fft_estimate(&_ue_dl, &_sf_cfg, &_ue_dl_cfg) < 0) {
100  _rest._pdsch.errors++;
101  spdlog::error("Getting PDCCH FFT estimate\n");
102  return false;
103  }
104 
105  // Feedback the CFO from CE to the Phy
106  _phy.set_cfo_from_channel_estimation(_ue_dl.chest_res.cfo);
107 
108  // Try to decode DCIs from PDCCH
109  srslte_dci_dl_t dci[SRSLTE_MAX_CARRIERS] = {}; // NOLINT
110  int nof_grants = srslte_ue_dl_find_dl_dci(&_ue_dl, &_sf_cfg, &_ue_dl_cfg, SRSLTE_SIRNTI_MBMS_DEDICATED, dci);
111  for (int k = 0; k < nof_grants; k++) {
112  char str[512]; // NOLINT
113  srslte_dci_dl_info(&dci[k], str, 512);
114  _rest._pdsch.mcs = dci[k].tb[0].mcs_idx;
115  spdlog::debug("Decoded PDCCH: {}, snr={} dB\n", str, _ue_dl.chest_res.snr_db);
116 
117  if (srslte_ue_dl_dci_to_pdsch_grant(&_ue_dl, &_sf_cfg, &_ue_dl_cfg, &dci[k], &_ue_dl_cfg.cfg.pdsch.grant)) {
118  spdlog::error("Converting DCI message to DL dci\n");
119  return false;
120  }
121 
122  // We can construct a DL grant
123  _ue_dl_cfg.cfg.pdsch.rnti = dci[k].rnti;
124  srslte_pdsch_cfg_t* pdsch_cfg = &_ue_dl_cfg.cfg.pdsch;
125 
126  srslte_pdsch_res_t pdsch_res[SRSLTE_MAX_CODEWORDS] = {}; // NOLINT
127  for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
128  if (pdsch_cfg->grant.tb[i].enabled) {
129  if (pdsch_cfg->grant.tb[i].rv < 0) {
130  uint32_t sfn = tti / 10;
131  uint32_t k = (sfn / 2) % 4;
132  pdsch_cfg->grant.tb[i].rv = ((int32_t)ceilf(static_cast<float>(1.5) * k)) % 4;
133  }
134  pdsch_res[i].payload = _data[i];
135  pdsch_res[i].crc = false;
136  srslte_softbuffer_rx_reset_tbs(pdsch_cfg->softbuffers.rx[i], (uint32_t)pdsch_cfg->grant.tb[i].tbs);
137  }
138  }
139 
140  // Decode PDSCH..
141  if (srslte_ue_dl_decode_pdsch(&_ue_dl, &_sf_cfg, &_ue_dl_cfg.cfg.pdsch, pdsch_res)) {
142  spdlog::error("Error decoding PDSCH\n");
143  _rest._pdsch.errors++;
144  } else {
145  spdlog::debug("Decoded PDSCH, BER {}", _softbuffer.ber);
146  _rest._pdsch.ber = _softbuffer.ber;
147  for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
148  // .. and pass received PDUs to RLC for further processing
149  if (pdsch_cfg->grant.tb[i].enabled) {
150  _rlc.write_pdu_bcch_dlsch(_data[i], (uint32_t)pdsch_cfg->grant.tb[i].tbs);
151  }
152  }
153  }
154  }
155  return true;
156 }

◆ set_cell()

void CasFrameProcessor::set_cell ( srslte_cell_t  cell)

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

Parameters
cellThe cell we're camping on

Definition at line 81 of file CasFrameProcessor.cpp.

81  {
82  _cell = cell;
83  spdlog::debug("CAS processor setting cell ({} PRB / {} MBSFN PRB).", cell.nof_prb, cell.mbsfn_prb);
84  srslte_ue_dl_set_cell(&_ue_dl, cell);
85 }

The documentation for this class was generated from the following files:
RestHandler::_pdsch
ChannelInfo _pdsch
RX info for PDSCH.
Definition: RestHandler.h:101
Phy::set_cfo_from_channel_estimation
void set_cfo_from_channel_estimation(float cfo)
Set the CFO value from channel estimation.
Definition: Phy.h:114