Coverage Report

Created: 2026-10-28 07:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ocudu/lib/nrppa/nrppa_asn1_converters.h
Line
Count
Source
1
// SPDX-FileCopyrightText: Copyright (C) 2021-2026 Software Radio Systems Limited
2
// SPDX-FileCopyrightText: Copyright (C) 2026 OCUDU contributors
3
// SPDX-License-Identifier: BSD-3-Clause-Open-MPI
4
// Portions of this file may implement 3GPP specifications, which may be subject to additional licensing requirements.
5
6
#pragma once
7
8
#include "ocudu/asn1/asn1_utils.h"
9
#include "ocudu/asn1/nrppa/nrppa_ies.h"
10
#include "ocudu/nrppa/nrppa_e_cid.h"
11
#include "ocudu/ocudulog/ocudulog.h"
12
#include "ocudu/ran/cyclic_prefix.h"
13
#include "ocudu/ran/nr_cell_identity.h"
14
#include "ocudu/ran/nr_cgi.h"
15
#include "ocudu/ran/positioning/common.h"
16
#include "ocudu/ran/positioning/measurement_information.h"
17
#include "ocudu/ran/positioning/positioning_information_exchange.h"
18
#include "ocudu/ran/positioning/trp_information_exchange.h"
19
#include "ocudu/ran/srs/srs_configuration.h"
20
#include "ocudu/support/enum_utils.h"
21
#include <variant>
22
23
namespace ocudu::ocucp {
24
25
// Helper to create PDU from NRPPA message
26
template <class T>
27
byte_buffer pack_into_pdu(const T& msg, const char* context_name = nullptr)
28
0
{
29
0
  context_name = context_name == nullptr ? __FUNCTION__ : context_name;
30
0
  byte_buffer   pdu{};
31
0
  asn1::bit_ref bref{pdu};
32
0
  if (msg.pack(bref) == asn1::OCUDUASN_ERROR_ENCODE_FAIL) {
33
0
    ocudulog::fetch_basic_logger("NRPPA").error("Failed to pack message in {} - discarding it", context_name);
34
0
    pdu.clear();
35
0
  }
36
0
  return pdu;
37
0
}
38
39
inline meas_periodicity_t asn1_to_meas_periodicity(asn1::nrppa::meas_periodicity_e asn1_meas_periodicity)
40
0
{
41
0
  if (asn1_meas_periodicity == asn1::nrppa::meas_periodicity_opts::nulltype) {
42
0
    report_fatal_error("Unsupported NRPPa meas periodicity. NRPPa meas periodicity={}",
43
0
                       fmt::underlying(asn1_meas_periodicity.value));
44
0
  }
45
46
0
  return static_cast<meas_periodicity_t>(asn1_meas_periodicity.to_number());
47
0
}
48
49
inline nrppa_meas_quantities_item
50
asn1_to_meas_quantities_item(const asn1::nrppa::meas_quantities_item_s& asn1_meas_quantities_item)
51
0
{
52
0
  nrppa_meas_quantities_item meas_quantities_item;
53
54
0
  switch (asn1_meas_quantities_item.meas_quantities_value) {
55
0
    case asn1::nrppa::meas_quantities_value_e::cell_id:
56
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::cell_id;
57
0
      break;
58
0
    case asn1::nrppa::meas_quantities_value_e::angle_of_arrival:
59
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::angle_of_arrival;
60
0
      break;
61
0
    case asn1::nrppa::meas_quantities_value_e::timing_advance_type1:
62
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::timing_advance_type1;
63
0
      break;
64
0
    case asn1::nrppa::meas_quantities_value_e::timing_advance_type2:
65
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::timing_advance_type2;
66
0
      break;
67
0
    case asn1::nrppa::meas_quantities_value_e::rsrp:
68
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::rsrp;
69
0
      break;
70
0
    case asn1::nrppa::meas_quantities_value_e::rsrq:
71
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::rsrq;
72
0
      break;
73
0
    case asn1::nrppa::meas_quantities_value_e::ss_rsrp:
74
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::ss_rsrp;
75
0
      break;
76
0
    case asn1::nrppa::meas_quantities_value_e::ss_rsrq:
77
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::ss_rsrq;
78
0
      break;
79
0
    case asn1::nrppa::meas_quantities_value_e::csi_rsrp:
80
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::csi_rsrp;
81
0
      break;
82
0
    case asn1::nrppa::meas_quantities_value_e::csi_rsrq:
83
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::csi_rsrq;
84
0
      break;
85
0
    case asn1::nrppa::meas_quantities_value_e::angle_of_arrival_nr:
86
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::angle_of_arrival_nr;
87
0
      break;
88
0
    case asn1::nrppa::meas_quantities_value_e::timing_advance_nr:
89
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::timing_advance_nr;
90
0
      break;
91
0
    case asn1::nrppa::meas_quantities_value_e::ue_rx_tx_time_diff:
92
0
      meas_quantities_item.meas_quantities_value = nrppa_meas_quantities_value::ue_rx_tx_time_diff;
93
0
      break;
94
0
    default:
95
0
      report_fatal_error("Unsupported NRPPa meas quantities value. NRPPa meas quantities value={}",
96
0
                         asn1_meas_quantities_item.meas_quantities_value.to_number());
97
0
  }
98
99
0
  return meas_quantities_item;
100
0
}
101
102
inline asn1::nrppa::meas_quantities_item_s
103
meas_quantities_item_to_asn1(const nrppa_meas_quantities_item& meas_quantities_item)
104
0
{
105
0
  asn1::nrppa::meas_quantities_item_s asn1_meas_quantities_item;
106
0
107
0
  switch (meas_quantities_item.meas_quantities_value) {
108
0
    case nrppa_meas_quantities_value::cell_id:
109
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::cell_id;
110
0
      break;
111
0
    case nrppa_meas_quantities_value::angle_of_arrival:
112
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::angle_of_arrival;
113
0
      break;
114
0
    case nrppa_meas_quantities_value::timing_advance_type1:
115
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::timing_advance_type1;
116
0
      break;
117
0
    case nrppa_meas_quantities_value::timing_advance_type2:
118
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::timing_advance_type2;
119
0
      break;
120
0
    case nrppa_meas_quantities_value::rsrp:
121
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::rsrp;
122
0
      break;
123
0
    case nrppa_meas_quantities_value::rsrq:
124
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::rsrq;
125
0
      break;
126
0
    case nrppa_meas_quantities_value::ss_rsrp:
127
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::ss_rsrp;
128
0
      break;
129
0
    case nrppa_meas_quantities_value::ss_rsrq:
130
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::ss_rsrq;
131
0
      break;
132
0
    case nrppa_meas_quantities_value::csi_rsrp:
133
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::csi_rsrp;
134
0
      break;
135
0
    case nrppa_meas_quantities_value::csi_rsrq:
136
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::csi_rsrq;
137
0
      break;
138
0
    case nrppa_meas_quantities_value::angle_of_arrival_nr:
139
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::angle_of_arrival_nr;
140
0
      break;
141
0
    case nrppa_meas_quantities_value::timing_advance_nr:
142
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::timing_advance_nr;
143
0
      break;
144
0
    case nrppa_meas_quantities_value::ue_rx_tx_time_diff:
145
0
      asn1_meas_quantities_item.meas_quantities_value = asn1::nrppa::meas_quantities_value_opts::ue_rx_tx_time_diff;
146
0
      break;
147
0
    default:
148
0
      report_fatal_error("Unsupported NRPPa meas quantities value");
149
0
  }
150
0
151
0
  return asn1_meas_quantities_item;
152
0
}
153
154
inline asn1::nrppa::ng_ran_access_point_position_s
155
ng_ran_access_point_position_to_asn1(const ng_ran_access_point_position_t& ng_ran_access_point_position)
156
0
{
157
0
  asn1::nrppa::ng_ran_access_point_position_s asn1_ng_ran_access_point_position;
158
159
  // Fill latitude sign.
160
0
  asn1_ng_ran_access_point_position.latitude_sign.value =
161
0
      static_cast<asn1::nrppa::ng_ran_access_point_position_s::latitude_sign_opts::options>(
162
0
          ng_ran_access_point_position.latitude_sign);
163
164
  // Fill latutide.
165
0
  asn1_ng_ran_access_point_position.latitude = ng_ran_access_point_position.latitude;
166
167
  // Fill longitude.
168
0
  asn1_ng_ran_access_point_position.longitude = ng_ran_access_point_position.longitude;
169
170
  // Direction of altitude.
171
0
  asn1_ng_ran_access_point_position.direction_of_altitude.value =
172
0
      static_cast<asn1::nrppa::ng_ran_access_point_position_s::direction_of_altitude_opts::options>(
173
0
          ng_ran_access_point_position.direction_of_altitude);
174
175
  // Fill altitude.
176
0
  asn1_ng_ran_access_point_position.altitude = ng_ran_access_point_position.altitude;
177
178
  // Fill uncertainty semi major.
179
0
  asn1_ng_ran_access_point_position.uncertainty_semi_major = ng_ran_access_point_position.uncertainty_semi_major;
180
181
  // Fill uncertainty semi minor.
182
0
  asn1_ng_ran_access_point_position.uncertainty_semi_minor = ng_ran_access_point_position.uncertainty_semi_minor;
183
184
  // Fill orientation of major axis.
185
0
  asn1_ng_ran_access_point_position.orientation_of_major_axis = ng_ran_access_point_position.orientation_of_major_axis;
186
187
  // Fill uncertainty altitude.
188
0
  asn1_ng_ran_access_point_position.uncertainty_altitude = ng_ran_access_point_position.uncertainty_altitude;
189
190
  // Fill confidence.
191
0
  asn1_ng_ran_access_point_position.confidence = ng_ran_access_point_position.confidence;
192
193
0
  return asn1_ng_ran_access_point_position;
194
0
}
195
196
inline asn1::nrppa::e_c_id_meas_result_s e_cid_meas_result_to_asn1(const nrppa_e_cid_meas_result& meas_result)
197
0
{
198
0
  asn1::nrppa::e_c_id_meas_result_s asn1_meas_result;
199
200
  // Serving cell id.
201
0
  asn1_meas_result.serving_cell_id.ng_ran_cell.set_nr_cell_id().from_number(meas_result.serving_cell_id.nci.value());
202
0
  asn1_meas_result.serving_cell_id.plmn_id = meas_result.serving_cell_id.plmn_id.to_bytes();
203
204
  // Serving cell tac.
205
0
  asn1_meas_result.serving_cell_tac.from_number(meas_result.serving_cell_tac);
206
207
  // NG-RAN access point position.
208
0
  if (meas_result.ng_ran_access_point_position.has_value()) {
209
0
    asn1_meas_result.ng_ran_access_point_position_present = true;
210
0
    asn1_meas_result.ng_ran_access_point_position =
211
0
        ng_ran_access_point_position_to_asn1(meas_result.ng_ran_access_point_position.value());
212
0
  }
213
214
  // Measured results.
215
  // Note that only NR results are supported.
216
0
  for (const auto& measured_results_value : meas_result.measured_results) {
217
0
    asn1::nrppa::measured_results_value_c asn1_measured_results_value;
218
0
    auto&                                 result_nr = asn1_measured_results_value.set_choice_ext();
219
220
    // SS RSRP.
221
0
    if (const auto* result = std::get_if<std::vector<nrppa_result_ss_rsrp_item>>(&measured_results_value)) {
222
0
      asn1::nrppa::result_ss_rsrp_l rsrp_list;
223
224
0
      for (const auto& result_item : *result) {
225
0
        asn1::nrppa::result_ss_rsrp_item_s rsrp_item;
226
0
        rsrp_item.nr_pci   = result_item.nr_pci;
227
0
        rsrp_item.nr_arfcn = result_item.nr_arfcn.value();
228
229
0
        if (result_item.cgi_nr.has_value()) {
230
0
          rsrp_item.cgi_nr_present = true;
231
0
          rsrp_item.cgi_nr.nr_cell_id.from_number(result_item.cgi_nr->nci.value());
232
0
          rsrp_item.cgi_nr.plmn_id = result_item.cgi_nr->plmn_id.to_bytes();
233
0
        }
234
235
0
        if (result_item.value_ss_rsrp_cell.has_value()) {
236
0
          rsrp_item.value_ss_rsrp_cell_present = true;
237
0
          rsrp_item.value_ss_rsrp_cell         = result_item.value_ss_rsrp_cell.value();
238
0
        }
239
240
0
        for (const auto& rsrp_per_ssb_item : result_item.ss_rsrp_per_ssb) {
241
0
          asn1::nrppa::result_ss_rsrp_per_ssb_item_s asn1_rsrp_per_ssb_item;
242
0
          asn1_rsrp_per_ssb_item.ssb_idx       = rsrp_per_ssb_item.ssb_idx;
243
0
          asn1_rsrp_per_ssb_item.value_ss_rsrp = rsrp_per_ssb_item.value_ss_rsrp;
244
245
0
          rsrp_item.ss_rsrp_per_ssb.push_back(asn1_rsrp_per_ssb_item);
246
0
        }
247
248
0
        rsrp_list.push_back(rsrp_item);
249
0
      }
250
251
0
      result_nr->set(asn1::nrppa::measured_results_value_ext_ie_o::value_c::types_opts::result_ss_rsrp);
252
0
      result_nr->result_ss_rsrp() = rsrp_list;
253
0
    }
254
255
    // SS RSRQ.
256
0
    if (const auto* result = std::get_if<std::vector<nrppa_result_ss_rsrq_item>>(&measured_results_value)) {
257
0
      asn1::nrppa::result_ss_rsrq_l rsrq_list;
258
259
0
      for (const auto& result_item : *result) {
260
0
        asn1::nrppa::result_ss_rsrq_item_s rsrq_item;
261
0
        rsrq_item.nr_pci   = result_item.nr_pci;
262
0
        rsrq_item.nr_arfcn = result_item.nr_arfcn.value();
263
264
0
        if (result_item.cgi_nr.has_value()) {
265
0
          rsrq_item.cgi_nr_present = true;
266
0
          rsrq_item.cgi_nr.nr_cell_id.from_number(result_item.cgi_nr->nci.value());
267
0
          rsrq_item.cgi_nr.plmn_id = result_item.cgi_nr->plmn_id.to_bytes();
268
0
        }
269
270
0
        if (result_item.value_ss_rsrq_cell.has_value()) {
271
0
          rsrq_item.value_ss_rsrq_cell_present = true;
272
0
          rsrq_item.value_ss_rsrq_cell         = result_item.value_ss_rsrq_cell.value();
273
0
        }
274
275
0
        for (const auto& rsrq_per_ssb_item : result_item.ss_rsrq_per_ssb) {
276
0
          asn1::nrppa::result_ss_rsrq_per_ssb_item_s asn1_rsrq_per_ssb_item;
277
0
          asn1_rsrq_per_ssb_item.ssb_idx       = rsrq_per_ssb_item.ssb_idx;
278
0
          asn1_rsrq_per_ssb_item.value_ss_rsrq = rsrq_per_ssb_item.value_ss_rsrq;
279
280
0
          rsrq_item.ss_rsrq_per_ssb.push_back(asn1_rsrq_per_ssb_item);
281
0
        }
282
283
0
        rsrq_list.push_back(rsrq_item);
284
0
      }
285
286
0
      result_nr->set(asn1::nrppa::measured_results_value_ext_ie_o::value_c::types_opts::result_ss_rsrq);
287
0
      result_nr->result_ss_rsrq() = rsrq_list;
288
0
    }
289
290
    // CSI RSRP.
291
0
    if (const auto* result = std::get_if<std::vector<nrppa_result_csi_rsrp_item>>(&measured_results_value)) {
292
0
      asn1::nrppa::result_csi_rsrp_l rsrp_list;
293
294
0
      for (const auto& result_item : *result) {
295
0
        asn1::nrppa::result_csi_rsrp_item_s rsrp_item;
296
0
        rsrp_item.nr_pci   = result_item.nr_pci;
297
0
        rsrp_item.nr_arfcn = result_item.nr_arfcn.value();
298
299
0
        if (result_item.cgi_nr.has_value()) {
300
0
          rsrp_item.cgi_nr_present = true;
301
0
          rsrp_item.cgi_nr.nr_cell_id.from_number(result_item.cgi_nr->nci.value());
302
0
          rsrp_item.cgi_nr.plmn_id = result_item.cgi_nr->plmn_id.to_bytes();
303
0
        }
304
305
0
        if (result_item.value_csi_rsrp_cell.has_value()) {
306
0
          rsrp_item.value_csi_rsrp_cell_present = true;
307
0
          rsrp_item.value_csi_rsrp_cell         = result_item.value_csi_rsrp_cell.value();
308
0
        }
309
310
0
        for (const auto& csi_rsrp_per_csi_rs_item : result_item.csi_rsrp_per_csi_rs) {
311
0
          asn1::nrppa::result_csi_rsrp_per_csi_rs_item_s asn1_csi_rsrp_per_csi_rs_item;
312
0
          asn1_csi_rsrp_per_csi_rs_item.csi_rs_idx     = csi_rsrp_per_csi_rs_item.csi_rs_idx;
313
0
          asn1_csi_rsrp_per_csi_rs_item.value_csi_rsrp = csi_rsrp_per_csi_rs_item.value_csi_rsrp;
314
315
0
          rsrp_item.csi_rsrp_per_csi_rs.push_back(asn1_csi_rsrp_per_csi_rs_item);
316
0
        }
317
318
0
        rsrp_list.push_back(rsrp_item);
319
0
      }
320
321
0
      result_nr->set(asn1::nrppa::measured_results_value_ext_ie_o::value_c::types_opts::result_csi_rsrp);
322
0
      result_nr->result_csi_rsrp() = rsrp_list;
323
0
    }
324
325
    // CSI RSRQ.
326
0
    if (const auto* result = std::get_if<std::vector<nrppa_result_csi_rsrq_item>>(&measured_results_value)) {
327
0
      asn1::nrppa::result_csi_rsrq_l rsrq_list;
328
329
0
      for (const auto& result_item : *result) {
330
0
        asn1::nrppa::result_csi_rsrq_item_s rsrq_item;
331
0
        rsrq_item.nr_pci   = result_item.nr_pci;
332
0
        rsrq_item.nr_arfcn = result_item.nr_arfcn.value();
333
334
0
        if (result_item.cgi_nr.has_value()) {
335
0
          rsrq_item.cgi_nr_present = true;
336
0
          rsrq_item.cgi_nr.nr_cell_id.from_number(result_item.cgi_nr->nci.value());
337
0
          rsrq_item.cgi_nr.plmn_id = result_item.cgi_nr->plmn_id.to_bytes();
338
0
        }
339
340
0
        if (result_item.value_csi_rsrq_cell.has_value()) {
341
0
          rsrq_item.value_csi_rsrq_cell_present = true;
342
0
          rsrq_item.value_csi_rsrq_cell         = result_item.value_csi_rsrq_cell.value();
343
0
        }
344
345
0
        for (const auto& csi_rsrq_per_csi_rs_item : result_item.csi_rsrq_per_csi_rs) {
346
0
          asn1::nrppa::result_csi_rsrq_per_csi_rs_item_s asn1_csi_rsrq_per_csi_rs_item;
347
0
          asn1_csi_rsrq_per_csi_rs_item.csi_rs_idx     = csi_rsrq_per_csi_rs_item.csi_rs_idx;
348
0
          asn1_csi_rsrq_per_csi_rs_item.value_csi_rsrq = csi_rsrq_per_csi_rs_item.value_csi_rsrq;
349
350
0
          rsrq_item.csi_rsrq_per_csi_rs.push_back(asn1_csi_rsrq_per_csi_rs_item);
351
0
        }
352
353
0
        rsrq_list.push_back(rsrq_item);
354
0
      }
355
356
0
      result_nr->set(asn1::nrppa::measured_results_value_ext_ie_o::value_c::types_opts::result_csi_rsrq);
357
0
      result_nr->result_csi_rsrq() = rsrq_list;
358
0
    }
359
360
    // Angle of arrival.
361
0
    if (const auto* result = std::get_if<nrppa_ul_aoa>(&measured_results_value)) {
362
0
      asn1::nrppa::ul_ao_a_s asn1_aoa;
363
0
      asn1_aoa.azimuth_ao_a = result->azimuth_aoa;
364
365
0
      if (result->zenith_aoa.has_value()) {
366
0
        asn1_aoa.zenith_ao_a_present = true;
367
0
        asn1_aoa.zenith_ao_a         = result->zenith_aoa.value();
368
0
      }
369
370
0
      if (result->lcs_to_gcs_translation.has_value()) {
371
0
        asn1_aoa.lcs_to_gcs_translation_present = true;
372
0
        asn1_aoa.lcs_to_gcs_translation.alpha   = result->lcs_to_gcs_translation->alpha;
373
0
        asn1_aoa.lcs_to_gcs_translation.beta    = result->lcs_to_gcs_translation->beta;
374
0
        asn1_aoa.lcs_to_gcs_translation.gamma   = result->lcs_to_gcs_translation->gamma;
375
0
      }
376
377
0
      result_nr->set(asn1::nrppa::measured_results_value_ext_ie_o::value_c::types_opts::angle_of_arrival_nr);
378
0
      result_nr->angle_of_arrival_nr() = asn1_aoa;
379
0
    }
380
381
    // NR Timing advance.
382
0
    if (const auto* result = std::get_if<nrppa_nr_tadv>(&measured_results_value)) {
383
0
      result_nr->set(asn1::nrppa::measured_results_value_ext_ie_o::value_c::types_opts::nr_tadv);
384
0
      result_nr->nr_tadv() = static_cast<uint16_t>(*result);
385
0
    }
386
387
0
    asn1_meas_result.measured_results.push_back(asn1_measured_results_value);
388
0
  }
389
390
0
  return asn1_meas_result;
391
0
}
392
393
/// \brief Convert \c nrppa_cause_t type to NRPPA ASN.1 cause.
394
/// \param cause The nrppa_cause_t type.
395
/// \return The NRPPA ASN.1 cause.
396
inline asn1::nrppa::cause_c cause_to_asn1(nrppa_cause_t cause)
397
0
{
398
0
  asn1::nrppa::cause_c asn1_cause;
399
400
0
  if (const auto* result = std::get_if<nrppa_cause_radio_network_t>(&cause)) {
401
0
    asn1_cause.set_radio_network() = static_cast<asn1::nrppa::cause_radio_network_opts::options>(*result);
402
0
    return asn1_cause;
403
0
  }
404
0
  if (const auto* result = std::get_if<nrppa_cause_protocol_t>(&cause)) {
405
0
    asn1_cause.set_protocol() = static_cast<asn1::nrppa::cause_protocol_opts::options>(*result);
406
0
    return asn1_cause;
407
0
  }
408
0
  if (const auto* result = std::get_if<nrppa_cause_misc_t>(&cause)) {
409
0
    asn1_cause.set_misc() = static_cast<asn1::nrppa::cause_misc_opts::options>(*result);
410
0
    return asn1_cause;
411
0
  }
412
413
0
  report_fatal_error("Cannot convert cause to NRPPA type");
414
0
  return asn1_cause;
415
0
}
416
417
inline std::optional<trp_information_type_item_t>
418
asn1_to_trp_info_type_item(const asn1::nrppa::trp_info_type_item_e& asn1_trp_info_type_item)
419
0
{
420
0
  trp_information_type_item_t trp_info_type_item;
421
0
  switch (asn1_trp_info_type_item) {
422
0
    case asn1::nrppa::trp_info_type_item_opts::options::nr_pci:
423
0
      trp_info_type_item = trp_information_type_item_t::nr_pci;
424
0
      break;
425
0
    case asn1::nrppa::trp_info_type_item_opts::options::ng_ran_cgi:
426
0
      trp_info_type_item = trp_information_type_item_t::ng_ran_cgi;
427
0
      break;
428
0
    case asn1::nrppa::trp_info_type_item_opts::options::arfcn:
429
0
      trp_info_type_item = trp_information_type_item_t::arfcn;
430
0
      break;
431
0
    case asn1::nrppa::trp_info_type_item_opts::options::prs_cfg:
432
0
      trp_info_type_item = trp_information_type_item_t::prs_cfg;
433
0
      break;
434
0
    case asn1::nrppa::trp_info_type_item_opts::options::ssb_info:
435
0
      trp_info_type_item = trp_information_type_item_t::ssb_info;
436
0
      break;
437
0
    case asn1::nrppa::trp_info_type_item_opts::options::sfn_init_time:
438
0
      trp_info_type_item = trp_information_type_item_t::sfn_init_time;
439
0
      break;
440
0
    case asn1::nrppa::trp_info_type_item_opts::options::spatial_direct_info:
441
0
      trp_info_type_item = trp_information_type_item_t::spatial_direct_info;
442
0
      break;
443
0
    case asn1::nrppa::trp_info_type_item_opts::options::geo_coord:
444
0
      trp_info_type_item = trp_information_type_item_t::geo_coord;
445
0
      break;
446
0
    case asn1::nrppa::trp_info_type_item_opts::options::trp_type:
447
0
      trp_info_type_item = trp_information_type_item_t::trp_type;
448
0
      break;
449
0
    case asn1::nrppa::trp_info_type_item_opts::options::ondemand_pr_si_nfo:
450
0
      trp_info_type_item = trp_information_type_item_t::ondemand_prs_info;
451
0
      break;
452
0
    case asn1::nrppa::trp_info_type_item_opts::options::trp_tx_teg:
453
0
      trp_info_type_item = trp_information_type_item_t::trp_tx_teg;
454
0
      break;
455
0
    case asn1::nrppa::trp_info_type_item_opts::options::beam_ant_info:
456
0
      trp_info_type_item = trp_information_type_item_t::beam_ant_info;
457
0
      break;
458
0
    default:
459
0
      ocudulog::fetch_basic_logger("NRPPA").info("Unsupported NRPPa TRP info type item ({}). Ignoring it",
460
0
                                                 asn1_trp_info_type_item.to_string());
461
0
      return std::nullopt;
462
0
  }
463
464
0
  return trp_info_type_item;
465
0
}
466
467
inline asn1::nrppa::dl_prs_muting_pattern_c
468
dl_prs_muting_pattern_to_asn1(const dl_prs_muting_pattern_t& dl_prs_muting_pattern)
469
0
{
470
0
  asn1::nrppa::dl_prs_muting_pattern_c asn1_dl_prs_muting_pattern;
471
472
0
  if (dl_prs_muting_pattern.length == 2) {
473
0
    asn1_dl_prs_muting_pattern.set_two().from_number(dl_prs_muting_pattern.value);
474
0
  }
475
476
0
  if (dl_prs_muting_pattern.length == 4) {
477
0
    asn1_dl_prs_muting_pattern.set_four().from_number(dl_prs_muting_pattern.value);
478
0
  }
479
480
0
  if (dl_prs_muting_pattern.length == 6) {
481
0
    asn1_dl_prs_muting_pattern.set_six().from_number(dl_prs_muting_pattern.value);
482
0
  }
483
484
0
  if (dl_prs_muting_pattern.length == 8) {
485
0
    asn1_dl_prs_muting_pattern.set_eight().from_number(dl_prs_muting_pattern.value);
486
0
  }
487
488
0
  if (dl_prs_muting_pattern.length == 16) {
489
0
    asn1_dl_prs_muting_pattern.set_sixteen().from_number(dl_prs_muting_pattern.value);
490
0
  }
491
492
0
  if (dl_prs_muting_pattern.length == 32) {
493
0
    asn1_dl_prs_muting_pattern.set_thirty_two().from_number(dl_prs_muting_pattern.value);
494
0
  }
495
496
0
  return asn1_dl_prs_muting_pattern;
497
0
}
498
499
inline asn1::nrppa::prs_muting_s prs_muting_to_asn1(const prs_muting_t& prs_muting)
500
0
{
501
0
  asn1::nrppa::prs_muting_s asn1_prs_muting;
502
503
0
  if (prs_muting.prs_muting_option1.has_value()) {
504
0
    asn1_prs_muting.prs_muting_option1_present = true;
505
0
    asn1_prs_muting.prs_muting_option1.muting_pattern =
506
0
        dl_prs_muting_pattern_to_asn1(prs_muting.prs_muting_option1->muting_pattern);
507
0
    asn1::number_to_enum(asn1_prs_muting.prs_muting_option1.muting_bit_repeat_factor,
508
0
                         prs_muting.prs_muting_option1->muting_bit_repeat_factor);
509
0
  }
510
511
0
  if (prs_muting.prs_muting_option2.has_value()) {
512
0
    asn1_prs_muting.prs_muting_option2_present = true;
513
0
    asn1_prs_muting.prs_muting_option2.muting_pattern =
514
0
        dl_prs_muting_pattern_to_asn1(prs_muting.prs_muting_option2->muting_pattern);
515
0
  }
516
517
0
  return asn1_prs_muting;
518
0
}
519
520
inline asn1::nrppa::prs_res_set_item_s prs_resource_set_item_to_asn1(const prs_resource_set_item_t& prs_res_set_item)
521
0
{
522
0
  asn1::nrppa::prs_res_set_item_s asn1_prs_res_set_item;
523
524
0
  asn1_prs_res_set_item.prs_res_set_id = prs_res_set_item.prs_res_set_id;
525
0
  asn1::number_to_enum(asn1_prs_res_set_item.subcarrier_spacing, scs_to_khz(prs_res_set_item.scs));
526
0
  asn1_prs_res_set_item.pr_sbw    = prs_res_set_item.prs_bw;
527
0
  asn1_prs_res_set_item.start_prb = prs_res_set_item.start_prb;
528
0
  asn1_prs_res_set_item.point_a   = prs_res_set_item.point_a;
529
0
  asn1::number_to_enum(asn1_prs_res_set_item.comb_size, prs_res_set_item.comb_size);
530
0
  if (prs_res_set_item.cp_type == cyclic_prefix::options::NORMAL) {
531
0
    asn1_prs_res_set_item.cp_type = asn1::nrppa::prs_res_set_item_s::cp_type_opts::options::normal;
532
0
  } else {
533
0
    asn1_prs_res_set_item.cp_type = asn1::nrppa::prs_res_set_item_s::cp_type_opts::options::extended;
534
0
  }
535
0
  asn1::number_to_enum(asn1_prs_res_set_item.res_set_periodicity, prs_res_set_item.res_set_periodicity);
536
0
  asn1_prs_res_set_item.res_set_slot_offset = prs_res_set_item.res_set_slot_offset;
537
0
  asn1::number_to_enum(asn1_prs_res_set_item.res_repeat_factor, prs_res_set_item.res_repeat_factor);
538
0
  asn1::number_to_enum(asn1_prs_res_set_item.res_time_gap, prs_res_set_item.res_time_gap);
539
0
  asn1::number_to_enum(asn1_prs_res_set_item.res_numof_symbols, prs_res_set_item.res_numof_symbols);
540
0
  if (prs_res_set_item.prs_muting.has_value()) {
541
0
    asn1_prs_res_set_item.prs_muting_present = true;
542
0
    asn1_prs_res_set_item.prs_muting         = prs_muting_to_asn1(prs_res_set_item.prs_muting.value());
543
0
  }
544
0
  asn1_prs_res_set_item.prs_res_tx_pwr = prs_res_set_item.prs_res_tx_pwr;
545
0
  for (const auto& prs_res_item : prs_res_set_item.prs_res_list) {
546
0
    asn1::nrppa::prs_res_item_s asn1_prs_res_item;
547
0
    asn1_prs_res_item.prs_res_id        = prs_res_item.prs_res_id;
548
0
    asn1_prs_res_item.seq_id            = prs_res_item.seq_id;
549
0
    asn1_prs_res_item.re_offset         = prs_res_item.re_offset;
550
0
    asn1_prs_res_item.res_slot_offset   = prs_res_item.res_slot_offset;
551
0
    asn1_prs_res_item.res_symbol_offset = prs_res_item.res_symbol_offset;
552
0
    if (prs_res_item.qcl_info.has_value()) {
553
0
      asn1_prs_res_item.qcl_info_present = true;
554
555
0
      if (std::holds_alternative<ssb_t>(prs_res_item.qcl_info.value())) {
556
0
        asn1::nrppa::prs_res_qcl_source_ssb_s& asn1_pres_res_qcl_source_ssb =
557
0
            asn1_prs_res_item.qcl_info.set_qcl_source_ssb();
558
559
0
        const ssb_t& prs_res_qcl_source_ssb = std::get<ssb_t>(prs_res_item.qcl_info.value());
560
561
0
        asn1_pres_res_qcl_source_ssb.pci_nr = prs_res_qcl_source_ssb.pci_nr;
562
563
0
        if (prs_res_qcl_source_ssb.ssb_idx.has_value()) {
564
0
          asn1_pres_res_qcl_source_ssb.ssb_idx_present = true;
565
0
          asn1_pres_res_qcl_source_ssb.ssb_idx         = prs_res_qcl_source_ssb.ssb_idx.value();
566
0
        }
567
0
      } else {
568
0
        asn1::nrppa::prs_res_qcl_source_prs_s& asn1_prs_res_qcl_source_prs =
569
0
            asn1_prs_res_item.qcl_info.set_qcl_source_prs();
570
571
0
        const prs_resource_qcl_source_prs_t& prs_res_qcl_source_prs =
572
0
            std::get<prs_resource_qcl_source_prs_t>(prs_res_item.qcl_info.value());
573
574
0
        asn1_prs_res_qcl_source_prs.qcl_source_prs_res_set_id = prs_res_qcl_source_prs.qcl_source_prs_res_set_id;
575
0
        if (prs_res_qcl_source_prs.qcl_source_prs_res_id.has_value()) {
576
0
          asn1_prs_res_qcl_source_prs.qcl_source_prs_res_id_present = true;
577
0
          asn1_prs_res_qcl_source_prs.qcl_source_prs_res_id = prs_res_qcl_source_prs.qcl_source_prs_res_id.value();
578
0
        }
579
0
      }
580
0
    }
581
582
0
    asn1_prs_res_set_item.prs_res_list.push_back(asn1_prs_res_item);
583
0
  }
584
585
0
  return asn1_prs_res_set_item;
586
0
}
587
588
inline asn1::nrppa::ssb_info_item_s ssb_info_item_to_asn1(const ssb_info_item_t& ssb_info_item)
589
0
{
590
0
  asn1::nrppa::ssb_info_item_s asn1_ssb_info_item;
591
592
  // Fill SSB config.
593
0
  asn1_ssb_info_item.ssb_cfg.ssb_freq = ssb_info_item.ssb_cfg.ssb_freq;
594
0
  asn1::number_to_enum(asn1_ssb_info_item.ssb_cfg.ssb_subcarrier_spacing,
595
0
                       scs_to_khz(ssb_info_item.ssb_cfg.ssb_subcarrier_spacing));
596
0
  asn1_ssb_info_item.ssb_cfg.ssb_tx_pwr = ssb_info_item.ssb_cfg.ssb_tx_pwr;
597
0
  asn1::number_to_enum(asn1_ssb_info_item.ssb_cfg.ssb_periodicity, to_underlying(ssb_info_item.ssb_cfg.ssb_period));
598
0
  asn1_ssb_info_item.ssb_cfg.ssb_half_frame_offset = ssb_info_item.ssb_cfg.ssb_half_frame_offset;
599
0
  asn1_ssb_info_item.ssb_cfg.ssb_sfn_offset        = ssb_info_item.ssb_cfg.ssb_sfn_offset;
600
0
  if (ssb_info_item.ssb_cfg.ssb_burst_position.has_value()) {
601
0
    asn1_ssb_info_item.ssb_cfg.ssb_burst_position_present = true;
602
603
0
    if (ssb_info_item.ssb_cfg.ssb_burst_position.value().type == ssb_burst_position_t::bitmap_type_t::short_bitmap) {
604
0
      asn1_ssb_info_item.ssb_cfg.ssb_burst_position.set_short_bitmap();
605
0
      asn1_ssb_info_item.ssb_cfg.ssb_burst_position.short_bitmap().from_number(
606
0
          static_cast<uint8_t>(ssb_info_item.ssb_cfg.ssb_burst_position.value().bitmap));
607
0
    }
608
0
    if (ssb_info_item.ssb_cfg.ssb_burst_position.value().type == ssb_burst_position_t::bitmap_type_t::medium_bitmap) {
609
0
      asn1_ssb_info_item.ssb_cfg.ssb_burst_position.set_medium_bitmap();
610
0
      asn1_ssb_info_item.ssb_cfg.ssb_burst_position.medium_bitmap().from_number(
611
0
          static_cast<uint8_t>(ssb_info_item.ssb_cfg.ssb_burst_position.value().bitmap));
612
0
    }
613
0
    if (ssb_info_item.ssb_cfg.ssb_burst_position.value().type == ssb_burst_position_t::bitmap_type_t::long_bitmap) {
614
0
      asn1_ssb_info_item.ssb_cfg.ssb_burst_position.set_long_bitmap();
615
0
      asn1_ssb_info_item.ssb_cfg.ssb_burst_position.long_bitmap().from_number(
616
0
          ssb_info_item.ssb_cfg.ssb_burst_position.value().bitmap);
617
0
    }
618
0
  }
619
0
  if (ssb_info_item.ssb_cfg.sfn_initialization_time.has_value()) {
620
0
    asn1_ssb_info_item.ssb_cfg.sfn_initisation_time_present = true;
621
0
    asn1_ssb_info_item.ssb_cfg.sfn_initisation_time.from_number(ssb_info_item.ssb_cfg.sfn_initialization_time.value());
622
0
  }
623
624
  // Fill PCI NR.
625
0
  asn1_ssb_info_item.pci_nr = ssb_info_item.pci_nr;
626
627
0
  return asn1_ssb_info_item;
628
0
}
629
630
inline asn1::nrppa::spatial_direction_info_s
631
spatial_direction_info_to_asn1(const spatial_direction_info_t& spatial_direction_info)
632
0
{
633
0
  asn1::nrppa::spatial_direction_info_s asn1_spatial_direction_info;
634
635
  // Fill NR PRS beam info list.
636
0
  for (const auto& nr_prs_beam_info_item : spatial_direction_info.nr_prs_beam_info.nr_prs_beam_info_list) {
637
0
    asn1::nrppa::nr_prs_beam_info_item_s asn1_nr_prs_beam_info_item;
638
639
    // Fill PR SRES set ID.
640
0
    asn1_nr_prs_beam_info_item.pr_sres_set_id = nr_prs_beam_info_item.pr_sres_set_id;
641
642
    // Fill PRS angle.
643
0
    for (const auto& prs_angle : nr_prs_beam_info_item.prs_angle) {
644
0
      asn1::nrppa::prs_angle_item_s asn1_prs_angle_item;
645
646
0
      asn1_prs_angle_item.nr_prs_azimuth = prs_angle.nr_prs_azimuth;
647
0
      if (prs_angle.nr_prs_azimuth_fine.has_value()) {
648
0
        asn1_prs_angle_item.nr_prs_azimuth_fine_present = true;
649
0
        asn1_prs_angle_item.nr_prs_azimuth_fine         = prs_angle.nr_prs_azimuth_fine.value();
650
0
      }
651
0
      if (prs_angle.nr_prs_elevation.has_value()) {
652
0
        asn1_prs_angle_item.nr_prs_elevation_present = true;
653
0
        asn1_prs_angle_item.nr_prs_elevation         = prs_angle.nr_prs_elevation.value();
654
0
      }
655
0
      if (prs_angle.nr_prs_elevation_fine.has_value()) {
656
0
        asn1_prs_angle_item.nr_prs_elevation_fine_present = true;
657
0
        asn1_prs_angle_item.nr_prs_elevation_fine         = prs_angle.nr_prs_elevation_fine.value();
658
0
      }
659
660
0
      asn1::protocol_ext_field_s<asn1::nrppa::prs_angle_item_ext_ies_o> asn1_ie_exts_item;
661
0
      asn1_ie_exts_item.value().prs_res_id() = prs_angle.prs_res_id;
662
0
      asn1_prs_angle_item.ie_exts.push_back(asn1_ie_exts_item);
663
664
0
      asn1_nr_prs_beam_info_item.prs_angle.push_back(asn1_prs_angle_item);
665
0
    }
666
667
0
    asn1_spatial_direction_info.nr_prs_beam_info.nr_prs_beam_info_list.push_back(asn1_nr_prs_beam_info_item);
668
0
  }
669
670
  // Fill LCS to GCS translation list.
671
0
  for (const auto& lcs_to_gcs_translation_item : spatial_direction_info.nr_prs_beam_info.lcs_to_gcs_translation_list) {
672
0
    asn1::nrppa::lcs_to_gcs_translation_item_s asn1_lcs_to_gcs_translation_item;
673
0
    asn1_lcs_to_gcs_translation_item.alpha = lcs_to_gcs_translation_item.alpha;
674
0
    if (lcs_to_gcs_translation_item.alpha_fine.has_value()) {
675
0
      asn1_lcs_to_gcs_translation_item.alpha_fine_present = true;
676
0
      asn1_lcs_to_gcs_translation_item.alpha_fine         = lcs_to_gcs_translation_item.alpha_fine.value();
677
0
    }
678
0
    asn1_lcs_to_gcs_translation_item.beta = lcs_to_gcs_translation_item.beta;
679
0
    if (lcs_to_gcs_translation_item.beta_fine.has_value()) {
680
0
      asn1_lcs_to_gcs_translation_item.beta_fine_present = true;
681
0
      asn1_lcs_to_gcs_translation_item.beta_fine         = lcs_to_gcs_translation_item.beta_fine.value();
682
0
    }
683
0
    asn1_lcs_to_gcs_translation_item.gamma = lcs_to_gcs_translation_item.gamma;
684
0
    if (lcs_to_gcs_translation_item.gamma_fine.has_value()) {
685
0
      asn1_lcs_to_gcs_translation_item.gamma_fine_present = true;
686
0
      asn1_lcs_to_gcs_translation_item.gamma_fine         = lcs_to_gcs_translation_item.gamma_fine.value();
687
0
    }
688
689
0
    asn1_spatial_direction_info.nr_prs_beam_info.lcs_to_gcs_translation_list.push_back(
690
0
        asn1_lcs_to_gcs_translation_item);
691
0
  }
692
693
0
  return asn1_spatial_direction_info;
694
0
}
695
696
inline asn1::nrppa::ngran_high_accuracy_access_point_position_s ng_ran_high_accuracy_access_point_position_to_asn1(
697
    const ng_ran_high_accuracy_access_point_position_t& access_point_position)
698
0
{
699
0
  asn1::nrppa::ngran_high_accuracy_access_point_position_s asn1_access_point_position;
700
701
0
  asn1_access_point_position.latitude                  = access_point_position.latitude;
702
0
  asn1_access_point_position.longitude                 = access_point_position.longitude;
703
0
  asn1_access_point_position.altitude                  = access_point_position.altitude;
704
0
  asn1_access_point_position.uncertainty_semi_major    = access_point_position.uncertainty_semi_major;
705
0
  asn1_access_point_position.uncertainty_semi_minor    = access_point_position.uncertainty_semi_minor;
706
0
  asn1_access_point_position.orientation_of_major_axis = access_point_position.orientation_of_major_axis;
707
0
  asn1_access_point_position.horizontal_confidence     = access_point_position.horizontal_confidence;
708
0
  asn1_access_point_position.uncertainty_altitude      = access_point_position.uncertainty_altitude;
709
0
  asn1_access_point_position.vertical_confidence       = access_point_position.vertical_confidence;
710
711
0
  return asn1_access_point_position;
712
0
}
713
714
inline asn1::nrppa::relative_geodetic_location_s
715
relative_geodetic_location_to_asn1(const relative_geodetic_location_t& location)
716
0
{
717
0
  asn1::nrppa::relative_geodetic_location_s asn1_location;
718
719
0
  if (location.milli_arc_second_units == milli_arc_second_units_t::zerodot03) {
720
0
    asn1_location.milli_arc_second_units =
721
0
        asn1::nrppa::relative_geodetic_location_s::milli_arc_second_units_opts::zerodot03;
722
0
  } else if (location.milli_arc_second_units == milli_arc_second_units_t::zerodot3) {
723
0
    asn1_location.milli_arc_second_units =
724
0
        asn1::nrppa::relative_geodetic_location_s::milli_arc_second_units_opts::zerodot3;
725
0
  } else {
726
0
    asn1_location.milli_arc_second_units =
727
0
        asn1::nrppa::relative_geodetic_location_s::milli_arc_second_units_opts::three;
728
0
  }
729
730
0
  if (location.height_units == height_units_t::mm) {
731
0
    asn1_location.height_units = asn1::nrppa::relative_geodetic_location_s::height_units_opts::mm;
732
0
  } else if (location.height_units == height_units_t::cm) {
733
0
    asn1_location.height_units = asn1::nrppa::relative_geodetic_location_s::height_units_opts::cm;
734
0
  } else {
735
0
    asn1_location.height_units = asn1::nrppa::relative_geodetic_location_s::height_units_opts::m;
736
0
  }
737
738
0
  asn1_location.delta_latitude  = location.delta_latitude;
739
0
  asn1_location.delta_longitude = location.delta_longitude;
740
0
  asn1_location.delta_height    = location.delta_height;
741
742
0
  asn1_location.location_uncertainty.horizontal_uncertainty = location.location_uncertainty.horizontal_uncertainty;
743
0
  asn1_location.location_uncertainty.horizontal_confidence  = location.location_uncertainty.horizontal_confidence;
744
0
  asn1_location.location_uncertainty.vertical_uncertainty   = location.location_uncertainty.vertical_uncertainty;
745
0
  asn1_location.location_uncertainty.vertical_confidence    = location.location_uncertainty.vertical_confidence;
746
747
0
  return asn1_location;
748
0
}
749
750
inline asn1::nrppa::relative_cartesian_location_s
751
relative_cartesian_location_to_asn1(const relative_cartesian_location_t& location)
752
0
{
753
0
  asn1::nrppa::relative_cartesian_location_s asn1_location;
754
755
0
  if (location.xyz_unit == xyz_unit_t::mm) {
756
0
    asn1_location.xy_zunit = asn1::nrppa::relative_cartesian_location_s::xy_zunit_opts::options::mm;
757
0
  } else if (location.xyz_unit == xyz_unit_t::cm) {
758
0
    asn1_location.xy_zunit = asn1::nrppa::relative_cartesian_location_s::xy_zunit_opts::cm;
759
0
  } else {
760
0
    asn1_location.xy_zunit = asn1::nrppa::relative_cartesian_location_s::xy_zunit_opts::dm;
761
0
  }
762
763
0
  asn1_location.xvalue = location.xvalue;
764
0
  asn1_location.yvalue = location.yvalue;
765
0
  asn1_location.zvalue = location.zvalue;
766
767
0
  asn1_location.location_uncertainty.horizontal_uncertainty = location.location_uncertainty.horizontal_uncertainty;
768
0
  asn1_location.location_uncertainty.horizontal_confidence  = location.location_uncertainty.horizontal_confidence;
769
0
  asn1_location.location_uncertainty.vertical_uncertainty   = location.location_uncertainty.vertical_uncertainty;
770
0
  asn1_location.location_uncertainty.vertical_confidence    = location.location_uncertainty.vertical_confidence;
771
772
0
  return asn1_location;
773
0
}
774
775
inline asn1::nrppa::geographical_coordinates_s
776
geographical_coordinates_to_asn1(const geographical_coordinates_t& geographical_coordinates)
777
0
{
778
0
  asn1::nrppa::geographical_coordinates_s asn1_geographical_coordinates;
779
780
  // Fill TRP position definition type.
781
0
  if (std::holds_alternative<trp_position_direct_t>(geographical_coordinates.trp_position_definition_type)) {
782
0
    asn1::nrppa::trp_position_direct_s& asn1_trp_position_direct =
783
0
        asn1_geographical_coordinates.trp_position_definition_type.set_direct();
784
785
0
    const trp_position_direct_t& trp_position_direct =
786
0
        std::get<trp_position_direct_t>(geographical_coordinates.trp_position_definition_type);
787
788
    // Fill accuracy.
789
0
    if (std::holds_alternative<ng_ran_access_point_position_t>(trp_position_direct.accuracy)) {
790
0
      asn1_trp_position_direct.accuracy.set_trp_position() =
791
0
          ng_ran_access_point_position_to_asn1(std::get<ng_ran_access_point_position_t>(trp_position_direct.accuracy));
792
0
    } else {
793
0
      asn1_trp_position_direct.accuracy.set_trph_aposition() = ng_ran_high_accuracy_access_point_position_to_asn1(
794
0
          std::get<ng_ran_high_accuracy_access_point_position_t>(trp_position_direct.accuracy));
795
0
    }
796
0
  }
797
798
0
  if (std::holds_alternative<trp_position_refd_t>(geographical_coordinates.trp_position_definition_type)) {
799
0
    asn1::nrppa::trp_position_refd_s& asn1_trp_position_refd =
800
0
        asn1_geographical_coordinates.trp_position_definition_type.set_refd();
801
802
0
    const trp_position_refd_t& trp_position_refd =
803
0
        std::get<trp_position_refd_t>(geographical_coordinates.trp_position_definition_type);
804
805
    // Fill ref point.
806
0
    if (std::holds_alternative<uint16_t>(trp_position_refd.ref_point)) {
807
0
      asn1_trp_position_refd.ref_point.set_relative_coordinate_id() = std::get<uint16_t>(trp_position_refd.ref_point);
808
0
    } else if (std::holds_alternative<ng_ran_access_point_position_t>(trp_position_refd.ref_point)) {
809
0
      asn1_trp_position_refd.ref_point.set_ref_point_coordinate() =
810
0
          ng_ran_access_point_position_to_asn1(std::get<ng_ran_access_point_position_t>(trp_position_refd.ref_point));
811
0
    } else {
812
0
      asn1_trp_position_refd.ref_point.set_ref_point_coordinate_ha() =
813
0
          ng_ran_high_accuracy_access_point_position_to_asn1(
814
0
              std::get<ng_ran_high_accuracy_access_point_position_t>(trp_position_refd.ref_point));
815
0
    }
816
817
    // Fill ref point type.
818
0
    if (std::holds_alternative<relative_geodetic_location_t>(trp_position_refd.ref_point_type)) {
819
0
      asn1_trp_position_refd.ref_point_type.set_trp_position_relative_geodetic() =
820
0
          relative_geodetic_location_to_asn1(std::get<relative_geodetic_location_t>(trp_position_refd.ref_point_type));
821
0
    } else {
822
0
      asn1_trp_position_refd.ref_point_type.set_trp_position_relative_cartesian() = relative_cartesian_location_to_asn1(
823
0
          std::get<relative_cartesian_location_t>(trp_position_refd.ref_point_type));
824
0
    }
825
0
  }
826
827
0
  return asn1_geographical_coordinates;
828
0
}
829
830
inline asn1::nrppa::trp_type_e trp_type_to_asn1(const trp_type_t& trp_type)
831
0
{
832
0
  asn1::nrppa::trp_type_e asn1_trp_type;
833
834
0
  if (trp_type == trp_type_t::prs_only_tp) {
835
0
    asn1_trp_type = asn1::nrppa::trp_type_opts::prs_only_tp;
836
0
  } else if (trp_type == trp_type_t::srs_only_rp) {
837
0
    asn1_trp_type = asn1::nrppa::trp_type_opts::srs_only_rp;
838
0
  } else if (trp_type == trp_type_t::tp) {
839
0
    asn1_trp_type = asn1::nrppa::trp_type_opts::tp;
840
0
  } else if (trp_type == trp_type_t::rp) {
841
0
    asn1_trp_type = asn1::nrppa::trp_type_opts::rp;
842
0
  } else {
843
0
    asn1_trp_type = asn1::nrppa::trp_type_opts::trp;
844
0
  }
845
846
0
  return asn1_trp_type;
847
0
}
848
849
inline asn1::nrppa::on_demand_prs_info_s on_demand_prs_info_to_asn1(const on_demand_prs_info_t& on_demand_prs_info)
850
0
{
851
0
  asn1::nrppa::on_demand_prs_info_s asn1_on_demand_prs_info;
852
853
0
  asn1_on_demand_prs_info.on_demand_prs_request_allowed.from_number(on_demand_prs_info.on_demand_prs_request_allowed);
854
0
  if (on_demand_prs_info.allowed_res_set_periodicity_values.has_value()) {
855
0
    asn1_on_demand_prs_info.allowed_res_set_periodicity_values_present = true;
856
0
    asn1_on_demand_prs_info.allowed_res_set_periodicity_values.from_number(
857
0
        on_demand_prs_info.allowed_res_set_periodicity_values.value());
858
0
  }
859
0
  if (on_demand_prs_info.allowed_prs_bw_values.has_value()) {
860
0
    asn1_on_demand_prs_info.allowed_prs_bw_values_present = true;
861
0
    asn1_on_demand_prs_info.allowed_prs_bw_values.from_number(on_demand_prs_info.allowed_prs_bw_values.value());
862
0
  }
863
0
  if (on_demand_prs_info.allowed_res_repeat_factor_values.has_value()) {
864
0
    asn1_on_demand_prs_info.allowed_res_repeat_factor_values_present = true;
865
0
    asn1_on_demand_prs_info.allowed_res_repeat_factor_values.from_number(
866
0
        on_demand_prs_info.allowed_res_repeat_factor_values.value());
867
0
  }
868
0
  if (on_demand_prs_info.allowed_res_nof_symbols_values.has_value()) {
869
0
    asn1_on_demand_prs_info.allowed_res_nof_symbols_values_present = true;
870
0
    asn1_on_demand_prs_info.allowed_res_nof_symbols_values.from_number(
871
0
        on_demand_prs_info.allowed_res_nof_symbols_values.value());
872
0
  }
873
0
  if (on_demand_prs_info.allowed_comb_size_values.has_value()) {
874
0
    asn1_on_demand_prs_info.allowed_comb_size_values_present = true;
875
0
    asn1_on_demand_prs_info.allowed_comb_size_values.from_number(on_demand_prs_info.allowed_comb_size_values.value());
876
0
  }
877
878
0
  return asn1_on_demand_prs_info;
879
0
}
880
881
inline asn1::nrppa::trp_tx_teg_assoc_l trp_tx_teg_assoc_list_to_asn1(const std::vector<trpteg_item_t>& trp_tx_teg_assoc)
882
0
{
883
0
  asn1::nrppa::trp_tx_teg_assoc_l asn1_trp_tx_teg_assoc;
884
885
0
  for (const auto& trpteg_item : trp_tx_teg_assoc) {
886
0
    asn1::nrppa::trpteg_item_s asn1_trpteg_item;
887
888
0
    asn1_trpteg_item.trp_tx_teg_info.trp_tx_teg_id = trpteg_item.trp_tx_teg_info.trp_tx_teg_id;
889
0
    asn1::number_to_enum(asn1_trpteg_item.trp_tx_teg_info.trp_tx_timing_error_margin,
890
0
                         trpteg_item.trp_tx_teg_info.trp_tx_timing_error_margin);
891
892
0
    asn1_trpteg_item.dl_prs_res_set_id = trpteg_item.dl_prs_res_set_id;
893
894
0
    for (const auto& dl_prs_res_id_item : trpteg_item.dl_prs_res_id_list) {
895
0
      asn1::nrppa::dl_prs_res_id_item_s asn1_dl_prs_res_id_item;
896
0
      asn1_dl_prs_res_id_item.dl_prs_res_id = dl_prs_res_id_item.dl_prs_res_id;
897
0
      asn1_trpteg_item.dl_prs_res_id_list.push_back(asn1_dl_prs_res_id_item);
898
0
    }
899
900
0
    asn1_trp_tx_teg_assoc.push_back(asn1_trpteg_item);
901
0
  }
902
903
0
  return asn1_trp_tx_teg_assoc;
904
0
}
905
906
inline asn1::nrppa::trp_beam_ant_info_s trp_beam_ant_info_to_asn1(const trp_beam_ant_info_t& trp_beam_ant_info)
907
0
{
908
0
  asn1::nrppa::trp_beam_ant_info_s asn1_trp_beam_ant_info;
909
910
0
  if (std::holds_alternative<uint32_t>(trp_beam_ant_info.choice_trp_beam_ant_info_item)) {
911
0
    asn1_trp_beam_ant_info.choice_trp_beam_ant_info_item.set_ref() =
912
0
        std::get<uint32_t>(trp_beam_ant_info.choice_trp_beam_ant_info_item);
913
0
  } else {
914
0
    asn1::nrppa::trp_beam_ant_explicit_info_s& asn1_trp_beam_ant_explicit_info =
915
0
        asn1_trp_beam_ant_info.choice_trp_beam_ant_info_item.set_explicit_value();
916
0
    const trp_beam_ant_explicit_info_t& trp_beam_ant_explicit_info =
917
0
        std::get<trp_beam_ant_explicit_info_t>(trp_beam_ant_info.choice_trp_beam_ant_info_item);
918
919
    // Fill TRP beam ant angles.
920
0
    for (const auto& trp_beam_ant_angle : trp_beam_ant_explicit_info.trp_beam_ant_angles) {
921
0
      asn1::nrppa::trp_beam_ant_angles_list_item_s asn1_trp_beam_ant_angle;
922
0
      asn1_trp_beam_ant_angle.trp_azimuth_angle = trp_beam_ant_angle.trp_azimuth_angle;
923
0
      if (trp_beam_ant_angle.trp_azimuth_angle_fine.has_value()) {
924
0
        asn1_trp_beam_ant_angle.trp_azimuth_angle_fine_present = true;
925
0
        asn1_trp_beam_ant_angle.trp_azimuth_angle_fine         = trp_beam_ant_angle.trp_azimuth_angle_fine.value();
926
0
      }
927
0
      for (const auto& trp_elevation_angle : trp_beam_ant_angle.trp_elevation_angle_list) {
928
0
        asn1::nrppa::trp_elevation_angle_list_item_s asn1_trp_elevation_angle;
929
0
        asn1_trp_elevation_angle.trp_elevation_angle = trp_elevation_angle.trp_elevation_angle;
930
0
        if (trp_elevation_angle.trp_elevation_angle_fine.has_value()) {
931
0
          asn1_trp_elevation_angle.trp_elevation_angle_fine_present = true;
932
0
          asn1_trp_elevation_angle.trp_elevation_angle_fine = trp_elevation_angle.trp_elevation_angle_fine.value();
933
0
        }
934
935
0
        for (const auto& trp_beam_pwr_item : trp_elevation_angle.trp_beam_pwr_list) {
936
0
          asn1::nrppa::trp_beam_pwr_item_s asn1_trp_beam_pwr_item;
937
0
          if (trp_beam_pwr_item.prs_res_set_id.has_value()) {
938
0
            asn1_trp_beam_pwr_item.prs_res_set_id_present = true;
939
0
            asn1_trp_beam_pwr_item.prs_res_set_id         = trp_beam_pwr_item.prs_res_set_id.value();
940
0
          }
941
0
          asn1_trp_beam_pwr_item.prs_res_id   = trp_beam_pwr_item.prs_res_id;
942
0
          asn1_trp_beam_pwr_item.relative_pwr = trp_beam_pwr_item.relative_pwr;
943
0
          if (trp_beam_pwr_item.relative_pwr_fine.has_value()) {
944
0
            asn1_trp_beam_pwr_item.relative_pwr_fine_present = true;
945
0
            asn1_trp_beam_pwr_item.relative_pwr_fine         = trp_beam_pwr_item.relative_pwr_fine.value();
946
0
          }
947
948
0
          asn1_trp_elevation_angle.trp_beam_pwr_list.push_back(asn1_trp_beam_pwr_item);
949
0
        }
950
951
0
        asn1_trp_beam_ant_angle.trp_elevation_angle_list.push_back(asn1_trp_elevation_angle);
952
0
      }
953
954
0
      asn1_trp_beam_ant_explicit_info.trp_beam_ant_angles.push_back(asn1_trp_beam_ant_angle);
955
0
    }
956
957
    // Fill LCS to GCS translation.
958
0
    if (trp_beam_ant_explicit_info.lcs_to_gcs_translation.has_value()) {
959
0
      asn1_trp_beam_ant_explicit_info.lcs_to_gcs_translation_present = true;
960
0
      asn1_trp_beam_ant_explicit_info.lcs_to_gcs_translation.alpha =
961
0
          trp_beam_ant_explicit_info.lcs_to_gcs_translation->alpha;
962
0
      asn1_trp_beam_ant_explicit_info.lcs_to_gcs_translation.beta =
963
0
          trp_beam_ant_explicit_info.lcs_to_gcs_translation->beta;
964
0
      asn1_trp_beam_ant_explicit_info.lcs_to_gcs_translation.gamma =
965
0
          trp_beam_ant_explicit_info.lcs_to_gcs_translation->gamma;
966
0
    }
967
0
  }
968
969
0
  return asn1_trp_beam_ant_info;
970
0
}
971
972
inline asn1::nrppa::trp_info_list_trp_resp_item_s_ trp_information_list_trp_response_item_to_asn1(
973
    const trp_information_list_trp_response_item_t& trp_info_list_trp_response_item)
974
0
{
975
0
  asn1::nrppa::trp_info_list_trp_resp_item_s_ asn1_trp_info_list_trp_response_item;
976
977
  // Fill TRP ID.
978
0
  asn1_trp_info_list_trp_response_item.trp_info.trp_id = to_underlying(trp_info_list_trp_response_item.trp_info.trp_id);
979
980
  // Fill TRP info type response list.
981
0
  for (const auto& trp_info_type_resp_item : trp_info_list_trp_response_item.trp_info.trp_info_type_resp_list) {
982
0
    asn1::nrppa::trp_info_type_resp_item_c asn1_trp_info_type_resp_item;
983
984
0
    if (std::holds_alternative<pci_t>(trp_info_type_resp_item)) {
985
0
      asn1_trp_info_type_resp_item.set_pci_nr() = std::get<pci_t>(trp_info_type_resp_item);
986
0
    }
987
988
0
    if (std::holds_alternative<nr_cell_global_id_t>(trp_info_type_resp_item)) {
989
0
      asn1::nrppa::cgi_nr_s& cgi_nr = asn1_trp_info_type_resp_item.set_cgi_nr();
990
0
      cgi_nr.nr_cell_id.from_number(std::get<nr_cell_global_id_t>(trp_info_type_resp_item).nci.value());
991
0
      cgi_nr.plmn_id = std::get<nr_cell_global_id_t>(trp_info_type_resp_item).plmn_id.to_bytes();
992
0
    }
993
994
0
    if (std::holds_alternative<uint32_t>(trp_info_type_resp_item)) {
995
0
      asn1_trp_info_type_resp_item.set_arfcn() = std::get<uint32_t>(trp_info_type_resp_item);
996
0
    }
997
998
0
    if (std::holds_alternative<prs_cfg_t>(trp_info_type_resp_item)) {
999
0
      asn1::nrppa::prs_cfg_s& asn1_prs_cfg = asn1_trp_info_type_resp_item.set_prs_cfg();
1000
1001
0
      for (const auto& prs_resource_set_item : std::get<prs_cfg_t>(trp_info_type_resp_item).prs_res_set_list) {
1002
0
        asn1_prs_cfg.prs_res_set_list.push_back(prs_resource_set_item_to_asn1(prs_resource_set_item));
1003
0
      }
1004
0
    }
1005
1006
0
    if (std::holds_alternative<ssb_info_t>(trp_info_type_resp_item)) {
1007
0
      asn1::nrppa::ssb_info_s& asn1_ssb_info = asn1_trp_info_type_resp_item.set_ss_binfo();
1008
0
      for (const auto& ssb_info_item : std::get<ssb_info_t>(trp_info_type_resp_item).list_of_ssb_info) {
1009
0
        asn1_ssb_info.list_of_ssb_info.push_back(ssb_info_item_to_asn1(ssb_info_item));
1010
0
      }
1011
0
    }
1012
1013
0
    if (std::holds_alternative<uint64_t>(trp_info_type_resp_item)) {
1014
0
      asn1_trp_info_type_resp_item.set_sfn_initisation_time().from_number(std::get<uint64_t>(trp_info_type_resp_item));
1015
0
    }
1016
1017
0
    if (std::holds_alternative<spatial_direction_info_t>(trp_info_type_resp_item)) {
1018
0
      asn1_trp_info_type_resp_item.set_spatial_direction_info() =
1019
0
          spatial_direction_info_to_asn1(std::get<spatial_direction_info_t>(trp_info_type_resp_item));
1020
0
    }
1021
1022
0
    if (std::holds_alternative<geographical_coordinates_t>(trp_info_type_resp_item)) {
1023
0
      asn1_trp_info_type_resp_item.set_geographical_coordinates() =
1024
0
          geographical_coordinates_to_asn1(std::get<geographical_coordinates_t>(trp_info_type_resp_item));
1025
0
    }
1026
1027
0
    if (std::holds_alternative<trp_type_t>(trp_info_type_resp_item)) {
1028
0
      asn1::protocol_ie_single_container_s<asn1::nrppa::trp_info_type_resp_item_ext_ies_o>& asn1_ie_exts_container =
1029
0
          asn1_trp_info_type_resp_item.set_choice_ext();
1030
0
      asn1_ie_exts_container.value().trp_type() = trp_type_to_asn1(std::get<trp_type_t>(trp_info_type_resp_item));
1031
0
    }
1032
1033
0
    if (std::holds_alternative<on_demand_prs_info_t>(trp_info_type_resp_item)) {
1034
0
      asn1::protocol_ie_single_container_s<asn1::nrppa::trp_info_type_resp_item_ext_ies_o>& asn1_ie_exts_container =
1035
0
          asn1_trp_info_type_resp_item.set_choice_ext();
1036
0
      asn1_ie_exts_container.value().on_demand_prs() =
1037
0
          on_demand_prs_info_to_asn1(std::get<on_demand_prs_info_t>(trp_info_type_resp_item));
1038
0
    }
1039
1040
0
    if (std::holds_alternative<std::vector<trpteg_item_t>>(trp_info_type_resp_item)) {
1041
0
      asn1::protocol_ie_single_container_s<asn1::nrppa::trp_info_type_resp_item_ext_ies_o>& asn1_ie_exts_container =
1042
0
          asn1_trp_info_type_resp_item.set_choice_ext();
1043
0
      asn1_ie_exts_container.value().trp_tx_teg_assoc() =
1044
0
          trp_tx_teg_assoc_list_to_asn1(std::get<std::vector<trpteg_item_t>>(trp_info_type_resp_item));
1045
0
    }
1046
1047
0
    if (std::holds_alternative<trp_beam_ant_info_t>(trp_info_type_resp_item)) {
1048
0
      asn1::protocol_ie_single_container_s<asn1::nrppa::trp_info_type_resp_item_ext_ies_o>& asn1_ie_exts_container =
1049
0
          asn1_trp_info_type_resp_item.set_choice_ext();
1050
0
      asn1_ie_exts_container.value().trp_beam_ant_info() =
1051
0
          trp_beam_ant_info_to_asn1(std::get<trp_beam_ant_info_t>(trp_info_type_resp_item));
1052
0
    }
1053
1054
0
    asn1_trp_info_list_trp_response_item.trp_info.trp_info_type_resp_list.push_back(asn1_trp_info_type_resp_item);
1055
0
  }
1056
1057
0
  return asn1_trp_info_list_trp_response_item;
1058
0
}
1059
1060
inline ssb_info_t asn1_to_ssb_info(const asn1::nrppa::ssb_info_s& asn1_ssb_info)
1061
0
{
1062
0
  ssb_info_t ssb_info;
1063
1064
0
  for (const auto& asn1_ssb_info_item : asn1_ssb_info.list_of_ssb_info) {
1065
0
    ssb_info_item_t ssb_info_item;
1066
    // Fill SSB configuration.
1067
0
    ssb_info_item.ssb_cfg.ssb_freq = asn1_ssb_info_item.ssb_cfg.ssb_freq;
1068
0
    ssb_info_item.ssb_cfg.ssb_subcarrier_spacing =
1069
0
        khz_to_scs(asn1_ssb_info_item.ssb_cfg.ssb_subcarrier_spacing.to_number());
1070
0
    ssb_info_item.ssb_cfg.ssb_tx_pwr = asn1_ssb_info_item.ssb_cfg.ssb_tx_pwr;
1071
0
    ssb_info_item.ssb_cfg.ssb_period = ssb_periodicity(asn1_ssb_info_item.ssb_cfg.ssb_periodicity.to_number());
1072
0
    ssb_info_item.ssb_cfg.ssb_half_frame_offset = asn1_ssb_info_item.ssb_cfg.ssb_half_frame_offset;
1073
0
    ssb_info_item.ssb_cfg.ssb_sfn_offset        = asn1_ssb_info_item.ssb_cfg.ssb_sfn_offset;
1074
0
    if (asn1_ssb_info_item.ssb_cfg.ssb_burst_position_present) {
1075
0
      ssb_burst_position_t burst_position;
1076
      // short bitmap
1077
0
      if (asn1_ssb_info_item.ssb_cfg.ssb_burst_position.type() ==
1078
0
          asn1::nrppa::ssb_burst_position_c::types_opts::options::short_bitmap) {
1079
0
        burst_position.type   = ssb_burst_position_t::bitmap_type_t::short_bitmap;
1080
0
        burst_position.bitmap = asn1_ssb_info_item.ssb_cfg.ssb_burst_position.short_bitmap().to_number();
1081
0
      }
1082
      // medium bitmap
1083
0
      if (asn1_ssb_info_item.ssb_cfg.ssb_burst_position.type() ==
1084
0
          asn1::nrppa::ssb_burst_position_c::types_opts::options::medium_bitmap) {
1085
0
        burst_position.type   = ssb_burst_position_t::bitmap_type_t::medium_bitmap;
1086
0
        burst_position.bitmap = asn1_ssb_info_item.ssb_cfg.ssb_burst_position.medium_bitmap().to_number();
1087
0
      }
1088
      // long bitmap
1089
0
      if (asn1_ssb_info_item.ssb_cfg.ssb_burst_position.type() ==
1090
0
          asn1::nrppa::ssb_burst_position_c::types_opts::options::long_bitmap) {
1091
0
        burst_position.type   = ssb_burst_position_t::bitmap_type_t::long_bitmap;
1092
0
        burst_position.bitmap = asn1_ssb_info_item.ssb_cfg.ssb_burst_position.long_bitmap().to_number();
1093
0
      }
1094
0
      ssb_info_item.ssb_cfg.ssb_burst_position = burst_position;
1095
0
    }
1096
0
    if (asn1_ssb_info_item.ssb_cfg.sfn_initisation_time_present) {
1097
0
      ssb_info_item.ssb_cfg.sfn_initialization_time = asn1_ssb_info_item.ssb_cfg.sfn_initisation_time.to_number();
1098
0
    }
1099
1100
    // Fill PCI.
1101
0
    ssb_info_item.pci_nr = asn1_ssb_info_item.pci_nr;
1102
0
    ssb_info.list_of_ssb_info.push_back(ssb_info_item);
1103
0
  }
1104
1105
0
  return ssb_info;
1106
0
}
1107
1108
inline spatial_relation_info_t::reference_signal asn1_to_ref_sig(const asn1::nrppa::ref_sig_c& asn1_ref_sig)
1109
0
{
1110
0
  spatial_relation_info_t::reference_signal ref_sig;
1111
1112
0
  if (asn1_ref_sig.type() == asn1::nrppa::ref_sig_c::types_opts::options::nzp_csi_rs) {
1113
0
    ref_sig = nzp_csi_rs_res_id_t{asn1_ref_sig.nzp_csi_rs()};
1114
0
  } else if (asn1_ref_sig.type() == asn1::nrppa::ref_sig_c::types_opts::options::ssb) {
1115
0
    const asn1::nrppa::ssb_s& asn1_ssb = asn1_ref_sig.ssb();
1116
0
    ssb_t                     ssb;
1117
0
    ssb.pci_nr = asn1_ssb.pci_nr;
1118
0
    if (asn1_ssb.ssb_idx_present) {
1119
0
      ssb.ssb_idx = asn1_ssb.ssb_idx;
1120
0
    }
1121
0
    ref_sig = ssb;
1122
0
  } else if (asn1_ref_sig.type() == asn1::nrppa::ref_sig_c::types_opts::options::srs) {
1123
0
    ref_sig = srs_config::srs_res_id(asn1_ref_sig.srs());
1124
0
  } else if (asn1_ref_sig.type() == asn1::nrppa::ref_sig_c::types_opts::options::positioning_srs) {
1125
0
    ref_sig = srs_config::srs_pos_res_id(asn1_ref_sig.positioning_srs());
1126
0
  } else {
1127
0
    const asn1::nrppa::dl_prs_s& asn1_dl_prs = asn1_ref_sig.dl_prs();
1128
0
    dl_prs_t                     dl_prs;
1129
0
    dl_prs.prs_id            = asn1_dl_prs.prsid;
1130
0
    dl_prs.dl_prs_res_set_id = asn1_dl_prs.dl_prs_res_set_id;
1131
0
    if (asn1_dl_prs.dl_prs_res_id_present) {
1132
0
      dl_prs.dl_prs_res_id = asn1_dl_prs.dl_prs_res_id;
1133
0
    }
1134
1135
0
    ref_sig = dl_prs;
1136
0
  }
1137
1138
0
  return ref_sig;
1139
0
}
1140
1141
inline std::optional<requested_srs_tx_characteristics_t>
1142
asn1_to_requested_srs_tx_characteristics(const asn1::nrppa::requested_srs_tx_characteristics_s& asn1_req)
1143
0
{
1144
0
  requested_srs_tx_characteristics_t req;
1145
1146
0
  if (asn1_req.nof_txs_present) {
1147
0
    req.nof_txs = asn1_req.nof_txs;
1148
0
  }
1149
1150
0
  if (asn1_req.res_type == asn1::nrppa::requested_srs_tx_characteristics_s::res_type_opts::options::periodic) {
1151
0
    req.res_type = requested_srs_tx_characteristics_t::res_type_t::periodic;
1152
0
  } else if (asn1_req.res_type ==
1153
0
             asn1::nrppa::requested_srs_tx_characteristics_s::res_type_opts::options::semi_persistent) {
1154
0
    req.res_type = requested_srs_tx_characteristics_t::res_type_t::semi_persistent;
1155
0
  } else {
1156
0
    req.res_type = requested_srs_tx_characteristics_t::res_type_t::aperiodic;
1157
0
  }
1158
1159
0
  if (asn1_req.bw.type() == asn1::nrppa::bw_srs_c::types_opts::options::fr1) {
1160
0
    req.bw = asn1_req.bw.fr1().to_number();
1161
0
  } else if (asn1_req.bw.type() == asn1::nrppa::bw_srs_c::types_opts::options::fr2) {
1162
0
    req.bw = asn1_req.bw.fr2().to_number();
1163
0
  } else {
1164
    // BandwidthSRS is mandatory, so an unrecognized choice leaves the whole RequestedSRSTransmissionCharacteristics
1165
    // without a well-defined bandwidth, and it is dropped.
1166
0
    ocudulog::fetch_basic_logger("NRPPA").warning("Unsupported BandwidthSRS choice ({}). Ignoring the request",
1167
0
                                                  asn1_req.bw.type().to_string());
1168
0
    return std::nullopt;
1169
0
  }
1170
1171
0
  for (const auto& asn1_srs_res_set_item : asn1_req.list_of_srs_res_set) {
1172
0
    srs_res_set_item_t srs_res_set_item;
1173
1174
0
    if (asn1_srs_res_set_item.nof_srs_res_per_set_present) {
1175
0
      srs_res_set_item.nof_srs_res_per_set = asn1_srs_res_set_item.nof_srs_res_per_set;
1176
0
    }
1177
0
    for (const auto& asn1_period : asn1_srs_res_set_item.periodicity_list) {
1178
0
      periodicity_item_t period_item;
1179
0
      period_item.value = static_cast<periodicity_item_t::value_t>((unsigned)asn1_period.value);
1180
0
      srs_res_set_item.periodicity_list.push_back(period_item);
1181
0
    }
1182
0
    if (asn1_srs_res_set_item.spatial_relation_info_present) {
1183
0
      spatial_relation_info_t spatial_relation_info;
1184
0
      for (const auto& asn1_spatial_relation_for_res_id_item :
1185
0
           asn1_srs_res_set_item.spatial_relation_info.spatial_relationfor_res_id) {
1186
0
        spatial_relation_info_t::reference_signal ref_sig =
1187
0
            asn1_to_ref_sig(asn1_spatial_relation_for_res_id_item.ref_sig);
1188
0
        spatial_relation_info.reference_signals.push_back(ref_sig);
1189
0
      }
1190
0
      srs_res_set_item.spatial_relation_info = spatial_relation_info;
1191
0
    }
1192
1193
0
    req.list_of_srs_res_set.push_back(srs_res_set_item);
1194
0
  }
1195
1196
0
  if (asn1_req.ssb_info_present) {
1197
0
    req.ssb_info = asn1_to_ssb_info(asn1_req.ssb_info);
1198
0
  }
1199
1200
0
  if (asn1_req.ie_exts_present) {
1201
0
    if (asn1_req.ie_exts.srs_freq_present) {
1202
0
      req.srs_freqs.push_back(asn1_req.ie_exts.srs_freq);
1203
0
    }
1204
0
  }
1205
1206
0
  return req;
1207
0
}
1208
1209
inline srs_configuration_t asn1_to_srs_configuration(const asn1::nrppa::srs_configuration_s& asn1_srs_cfg)
1210
0
{
1211
0
  srs_configuration_t srs_cfg;
1212
  // Fill SRS carrier list.
1213
0
  for (const auto& asn1_srs_carrier_list_item : asn1_srs_cfg.srs_carrier_list) {
1214
0
    srs_carrier_list_item_t srs_carrier_list_item;
1215
1216
    // Fill point A.
1217
0
    srs_carrier_list_item.point_a = asn1_srs_carrier_list_item.point_a;
1218
1219
    // Fill UL CH BW per SCS list.
1220
0
    for (const auto& asn1_carrier : asn1_srs_carrier_list_item.ul_ch_bw_per_scs_list) {
1221
0
      scs_specific_carrier carrier;
1222
0
      carrier.offset_to_carrier = asn1_carrier.offset_to_carrier;
1223
0
      carrier.scs               = khz_to_scs(asn1_carrier.subcarrier_spacing.to_number());
1224
0
      carrier.carrier_bandwidth = asn1_carrier.carrier_bw;
1225
0
      srs_carrier_list_item.ul_ch_bw_per_scs_list.push_back(carrier);
1226
0
    }
1227
1228
    // Fill active UL BWP.
1229
0
    srs_carrier_list_item.active_ul_bwp.location_and_bw = asn1_srs_carrier_list_item.active_ul_bwp.location_and_bw;
1230
0
    srs_carrier_list_item.active_ul_bwp.scs =
1231
0
        khz_to_scs(asn1_srs_carrier_list_item.active_ul_bwp.subcarrier_spacing.to_number());
1232
0
    if (asn1_srs_carrier_list_item.active_ul_bwp.cp.value == asn1::nrppa::active_ul_bwp_s::cp_opts::options::normal) {
1233
0
      srs_carrier_list_item.active_ul_bwp.cp = cyclic_prefix::options::NORMAL;
1234
0
    } else {
1235
0
      srs_carrier_list_item.active_ul_bwp.cp = cyclic_prefix::options::EXTENDED;
1236
0
    }
1237
0
    srs_carrier_list_item.active_ul_bwp.tx_direct_current_location =
1238
0
        asn1_srs_carrier_list_item.active_ul_bwp.tx_direct_current_location;
1239
0
    if (asn1_srs_carrier_list_item.active_ul_bwp.shift7dot5k_hz_present) {
1240
0
      srs_carrier_list_item.active_ul_bwp.shift7dot5k_hz = asn1_srs_carrier_list_item.active_ul_bwp.shift7dot5k_hz;
1241
0
    }
1242
    // > Fill SRS configuration.
1243
    // >> Fill SRS res list.
1244
0
    for (const auto& asn1_srs_res : asn1_srs_carrier_list_item.active_ul_bwp.srs_cfg.srs_res_list) {
1245
0
      srs_config::srs_resource srs_res;
1246
0
      srs_res.id.ue_res_id = (srs_config::srs_res_id)asn1_srs_res.srs_res_id;
1247
0
      srs_res.nof_ports    = (srs_config::srs_resource::nof_srs_ports)asn1_srs_res.nrof_srs_ports.to_number();
1248
0
      if (asn1_srs_res.tx_comb.type() == asn1::nrppa::tx_comb_c::types_opts::options::n2) {
1249
0
        srs_res.tx_comb.size                 = tx_comb_size::n2;
1250
0
        srs_res.tx_comb.tx_comb_offset       = asn1_srs_res.tx_comb.n2().comb_offset_n2;
1251
0
        srs_res.tx_comb.tx_comb_cyclic_shift = asn1_srs_res.tx_comb.n2().cyclic_shift_n2;
1252
0
      } else if (asn1_srs_res.tx_comb.type() == asn1::nrppa::tx_comb_c::types_opts::options::n4) {
1253
0
        srs_res.tx_comb.size                 = tx_comb_size::n4;
1254
0
        srs_res.tx_comb.tx_comb_offset       = asn1_srs_res.tx_comb.n4().comb_offset_n4;
1255
0
        srs_res.tx_comb.tx_comb_cyclic_shift = asn1_srs_res.tx_comb.n4().cyclic_shift_n4;
1256
0
      } else {
1257
        // TxComb is mandatory for the SRS resource, so an unrecognized choice leaves its comb configuration
1258
        // without a well-defined value, and the resource is dropped.
1259
0
        ocudulog::fetch_basic_logger("NRPPA").warning("Unsupported TxComb choice ({}). Dropping the SRS resource",
1260
0
                                                      asn1_srs_res.tx_comb.type().to_string());
1261
0
        continue;
1262
0
      }
1263
0
      srs_res.res_mapping.start_pos   = asn1_srs_res.start_position;
1264
0
      srs_res.res_mapping.nof_symb    = (srs_nof_symbols)asn1_srs_res.nrof_symbols.to_number();
1265
0
      srs_res.res_mapping.rept_factor = (srs_nof_symbols)asn1_srs_res.repeat_factor.to_number();
1266
0
      srs_res.freq_domain_pos         = asn1_srs_res.freq_domain_position;
1267
0
      srs_res.freq_domain_shift       = asn1_srs_res.freq_domain_shift;
1268
0
      srs_res.freq_hop.c_srs          = asn1_srs_res.c_srs;
1269
0
      srs_res.freq_hop.b_srs          = asn1_srs_res.b_srs;
1270
0
      srs_res.freq_hop.b_hop          = asn1_srs_res.b_hop;
1271
0
      if (asn1_srs_res.group_or_seq_hop == asn1::nrppa::srs_res_s::group_or_seq_hop_opts::options::neither) {
1272
0
        srs_res.grp_or_seq_hop = srs_group_or_sequence_hopping::neither;
1273
0
      } else if (asn1_srs_res.group_or_seq_hop == asn1::nrppa::srs_res_s::group_or_seq_hop_opts::options::group_hop) {
1274
0
        srs_res.grp_or_seq_hop = srs_group_or_sequence_hopping::group_hopping;
1275
0
      } else {
1276
0
        srs_res.grp_or_seq_hop = srs_group_or_sequence_hopping::sequence_hopping;
1277
0
      }
1278
0
      if (asn1_srs_res.res_type.type() == asn1::nrppa::res_type_c::types_opts::options::periodic) {
1279
0
        srs_res.res_type = srs_resource_type::periodic;
1280
0
        srs_res.periodicity_and_offset.emplace();
1281
0
        srs_res.periodicity_and_offset->period =
1282
0
            (srs_periodicity)asn1_srs_res.res_type.periodic().periodicity.to_number();
1283
0
        srs_res.periodicity_and_offset->offset = asn1_srs_res.res_type.periodic().offset;
1284
0
      } else if (asn1_srs_res.res_type.type() == asn1::nrppa::res_type_c::types_opts::options::semi_persistent) {
1285
0
        srs_res.res_type = srs_resource_type::semi_persistent;
1286
0
        srs_res.periodicity_and_offset.emplace();
1287
0
        srs_res.periodicity_and_offset->period =
1288
0
            (srs_periodicity)asn1_srs_res.res_type.semi_persistent().periodicity.to_number();
1289
0
        srs_res.periodicity_and_offset->offset = asn1_srs_res.res_type.semi_persistent().offset;
1290
0
      } else if (asn1_srs_res.res_type.type() == asn1::nrppa::res_type_c::types_opts::options::aperiodic) {
1291
0
        srs_res.res_type = srs_resource_type::aperiodic;
1292
0
      } else {
1293
        // ResourceType is mandatory for the SRS resource, so an unrecognized choice leaves its resource type
1294
        // without a well-defined value, and the resource is dropped.
1295
0
        ocudulog::fetch_basic_logger("NRPPA").warning("Unsupported ResourceType choice ({}). Dropping the SRS resource",
1296
0
                                                      asn1_srs_res.res_type.type().to_string());
1297
0
        continue;
1298
0
      }
1299
0
      srs_res.sequence_id = asn1_srs_res.seq_id;
1300
1301
0
      srs_carrier_list_item.active_ul_bwp.srs_cfg.srs_res_list.push_back(srs_res);
1302
0
    }
1303
    // >> Fill pos SRS res list.
1304
0
    for (const auto& asn1_pos_srs_res : asn1_srs_carrier_list_item.active_ul_bwp.srs_cfg.pos_srs_res_list) {
1305
0
      srs_config::srs_pos_resource pos_srs_res;
1306
0
      pos_srs_res.id.ue_res_id = (srs_config::srs_res_id)asn1_pos_srs_res.srs_pos_res_id;
1307
0
      if (asn1_pos_srs_res.tx_comb_pos.type() == asn1::nrppa::tx_comb_pos_c::types_opts::options::n2) {
1308
0
        pos_srs_res.tx_comb.tx_comb_pos_offset       = asn1_pos_srs_res.tx_comb_pos.n2().comb_offset_n2;
1309
0
        pos_srs_res.tx_comb.tx_comb_pos_cyclic_shift = asn1_pos_srs_res.tx_comb_pos.n2().cyclic_shift_n2;
1310
0
      } else if (asn1_pos_srs_res.tx_comb_pos.type() == asn1::nrppa::tx_comb_pos_c::types_opts::options::n4) {
1311
0
        pos_srs_res.tx_comb.tx_comb_pos_offset       = asn1_pos_srs_res.tx_comb_pos.n4().comb_offset_n4;
1312
0
        pos_srs_res.tx_comb.tx_comb_pos_cyclic_shift = asn1_pos_srs_res.tx_comb_pos.n4().cyclic_shift_n4;
1313
0
      } else if (asn1_pos_srs_res.tx_comb_pos.type() == asn1::nrppa::tx_comb_pos_c::types_opts::options::n8) {
1314
0
        pos_srs_res.tx_comb.tx_comb_pos_offset       = asn1_pos_srs_res.tx_comb_pos.n8().comb_offset_n8;
1315
0
        pos_srs_res.tx_comb.tx_comb_pos_cyclic_shift = asn1_pos_srs_res.tx_comb_pos.n8().cyclic_shift_n8;
1316
0
      } else {
1317
        // TxCombPos is mandatory for the positioning SRS resource, so an unrecognized choice leaves its comb
1318
        // configuration without a well-defined value, and the resource is dropped.
1319
0
        ocudulog::fetch_basic_logger("NRPPA").warning(
1320
0
            "Unsupported TxCombPos choice ({}). Dropping the positioning SRS resource",
1321
0
            asn1_pos_srs_res.tx_comb_pos.type().to_string());
1322
0
        continue;
1323
0
      }
1324
0
      pos_srs_res.res_mapping.start_pos = asn1_pos_srs_res.start_position;
1325
0
      pos_srs_res.res_mapping.nof_symb  = (srs_nof_symbols)asn1_pos_srs_res.nrof_symbols.to_number();
1326
0
      pos_srs_res.freq_domain_shift     = asn1_pos_srs_res.freq_domain_shift;
1327
0
      pos_srs_res.c_srs                 = asn1_pos_srs_res.c_srs;
1328
0
      if (asn1_pos_srs_res.group_or_seq_hop ==
1329
0
          asn1::nrppa::pos_srs_res_item_s::group_or_seq_hop_opts::options::neither) {
1330
0
        pos_srs_res.grp_or_seq_hop = srs_group_or_sequence_hopping::neither;
1331
0
      } else if (asn1_pos_srs_res.group_or_seq_hop ==
1332
0
                 asn1::nrppa::pos_srs_res_item_s::group_or_seq_hop_opts::options::group_hop) {
1333
0
        pos_srs_res.grp_or_seq_hop = srs_group_or_sequence_hopping::group_hopping;
1334
0
      } else {
1335
0
        pos_srs_res.grp_or_seq_hop = srs_group_or_sequence_hopping::sequence_hopping;
1336
0
      }
1337
0
      if (asn1_pos_srs_res.res_type_pos.type() == asn1::nrppa::res_type_pos_c::types_opts::options::periodic) {
1338
0
        pos_srs_res.res_type = srs_resource_type::periodic;
1339
0
        pos_srs_res.periodicity_and_offset.emplace();
1340
0
        pos_srs_res.periodicity_and_offset->period =
1341
0
            (srs_periodicity)asn1_pos_srs_res.res_type_pos.periodic().srs_periodicity.to_number();
1342
0
        pos_srs_res.periodicity_and_offset->offset = asn1_pos_srs_res.res_type_pos.periodic().offset;
1343
0
      } else if (asn1_pos_srs_res.res_type_pos.type() ==
1344
0
                 asn1::nrppa::res_type_pos_c::types_opts::options::semi_persistent) {
1345
0
        pos_srs_res.res_type = srs_resource_type::semi_persistent;
1346
0
        pos_srs_res.periodicity_and_offset.emplace();
1347
0
        pos_srs_res.periodicity_and_offset->period =
1348
0
            (srs_periodicity)asn1_pos_srs_res.res_type_pos.semi_persistent().srs_periodicity.to_number();
1349
0
        pos_srs_res.periodicity_and_offset->offset = asn1_pos_srs_res.res_type_pos.semi_persistent().offset;
1350
0
      } else if (asn1_pos_srs_res.res_type_pos.type() == asn1::nrppa::res_type_pos_c::types_opts::options::aperiodic) {
1351
0
        pos_srs_res.res_type    = srs_resource_type::aperiodic;
1352
0
        pos_srs_res.slot_offset = asn1_pos_srs_res.res_type_pos.aperiodic().slot_offset;
1353
0
      } else {
1354
        // ResourceTypePos is mandatory for the positioning SRS resource, so an unrecognized choice leaves its
1355
        // resource type without a well-defined value, and the resource is dropped.
1356
0
        ocudulog::fetch_basic_logger("NRPPA").warning(
1357
0
            "Unsupported ResourceTypePos choice ({}). Dropping the positioning SRS resource",
1358
0
            asn1_pos_srs_res.res_type_pos.type().to_string());
1359
0
        continue;
1360
0
      }
1361
0
      pos_srs_res.sequence_id = asn1_pos_srs_res.seq_id;
1362
1363
0
      if (asn1_pos_srs_res.spatial_relation_pos_present) {
1364
0
        if (asn1_pos_srs_res.spatial_relation_pos.type() ==
1365
0
            asn1::nrppa::spatial_relation_pos_c::types_opts::options::ssb_pos) {
1366
0
          srs_config::srs_pos_resource::srs_spatial_relation_pos::ssb ssb;
1367
0
          ssb.pci_nr = asn1_pos_srs_res.spatial_relation_pos.ssb_pos().pci_nr;
1368
0
          if (asn1_pos_srs_res.spatial_relation_pos.ssb_pos().ssb_idx_present) {
1369
0
            ssb.ssb_idx = asn1_pos_srs_res.spatial_relation_pos.ssb_pos().ssb_idx;
1370
0
          }
1371
0
          pos_srs_res.spatial_relation_info.emplace();
1372
0
          pos_srs_res.spatial_relation_info->reference_signal = ssb;
1373
0
        } else if (asn1_pos_srs_res.spatial_relation_pos.type() ==
1374
0
                   asn1::nrppa::spatial_relation_pos_c::types_opts::options::pr_si_nformation_pos) {
1375
0
          srs_config::srs_pos_resource::srs_spatial_relation_pos::prs prs;
1376
0
          prs.id             = asn1_pos_srs_res.spatial_relation_pos.pr_si_nformation_pos().prs_id_pos;
1377
0
          prs.prs_res_set_id = asn1_pos_srs_res.spatial_relation_pos.pr_si_nformation_pos().prs_res_set_id_pos;
1378
0
          if (asn1_pos_srs_res.spatial_relation_pos.pr_si_nformation_pos().prs_res_id_pos_present) {
1379
0
            prs.prs_res_id = asn1_pos_srs_res.spatial_relation_pos.pr_si_nformation_pos().prs_res_id_pos;
1380
0
          }
1381
0
          pos_srs_res.spatial_relation_info.emplace();
1382
0
          pos_srs_res.spatial_relation_info->reference_signal = prs;
1383
0
        } else {
1384
0
          ocudulog::fetch_basic_logger("NRPPA").warning("Unsupported SpatialRelationPos choice ({}). Ignoring it",
1385
0
                                                        asn1_pos_srs_res.spatial_relation_pos.type().to_string());
1386
0
        }
1387
0
      }
1388
1389
0
      srs_carrier_list_item.active_ul_bwp.srs_cfg.pos_srs_res_list.push_back(pos_srs_res);
1390
0
    }
1391
1392
    // >> Fill SRS res set list.
1393
0
    for (const auto& asn1_srs_res_set : asn1_srs_carrier_list_item.active_ul_bwp.srs_cfg.srs_res_set_list) {
1394
0
      srs_config::srs_resource_set srs_res_set;
1395
0
      srs_res_set.id = (srs_config::srs_res_set_id)asn1_srs_res_set.srs_res_set_id1;
1396
0
      for (const auto& asn1_res_id : asn1_srs_res_set.srs_res_id_list) {
1397
0
        srs_res_set.srs_res_id_list.push_back((srs_config::srs_res_id)asn1_res_id);
1398
0
      }
1399
0
      if (asn1_srs_res_set.res_set_type.type() == asn1::nrppa::res_set_type_c::types_opts::options::periodic) {
1400
0
        srs_res_set.res_type = srs_config::srs_resource_set::periodic_resource_type{};
1401
0
      } else if (asn1_srs_res_set.res_set_type.type() ==
1402
0
                 asn1::nrppa::res_set_type_c::types_opts::options::semi_persistent) {
1403
0
        srs_res_set.res_type = srs_config::srs_resource_set::semi_persistent_resource_type{};
1404
0
      } else if (asn1_srs_res_set.res_set_type.type() == asn1::nrppa::res_set_type_c::types_opts::options::aperiodic) {
1405
0
        srs_config::srs_resource_set::aperiodic_resource_type aperiodic;
1406
0
        aperiodic.aperiodic_srs_res_trigger = asn1_srs_res_set.res_set_type.aperiodic().srs_res_trigger;
1407
0
        aperiodic.slot_offset               = asn1_srs_res_set.res_set_type.aperiodic().slotoffset;
1408
0
        srs_res_set.res_type                = aperiodic;
1409
0
      } else {
1410
        // ResourceSetType is mandatory for the SRS resource set, so an unrecognized choice leaves its resource
1411
        // type without a well-defined value, and the resource set is dropped.
1412
0
        ocudulog::fetch_basic_logger("NRPPA").warning(
1413
0
            "Unsupported ResourceSetType choice ({}). Dropping the SRS resource set",
1414
0
            asn1_srs_res_set.res_set_type.type().to_string());
1415
0
        continue;
1416
0
      }
1417
1418
0
      srs_carrier_list_item.active_ul_bwp.srs_cfg.srs_res_set_list.push_back(srs_res_set);
1419
0
    }
1420
1421
    // >> Fill pos SRS res set list.
1422
0
    for (const auto& asn1_pos_srs_res_set : asn1_srs_carrier_list_item.active_ul_bwp.srs_cfg.pos_srs_res_set_list) {
1423
0
      srs_config::srs_resource_set pos_srs_res_set;
1424
0
      pos_srs_res_set.id = (srs_config::srs_res_set_id)asn1_pos_srs_res_set.possrs_res_set_id;
1425
0
      for (const auto& asn1_pos_srs_res_id : asn1_pos_srs_res_set.poss_rs_res_id_per_set_list) {
1426
0
        pos_srs_res_set.srs_res_id_list.push_back((srs_config::srs_res_id)asn1_pos_srs_res_id);
1427
0
      }
1428
0
      if (asn1_pos_srs_res_set.posres_set_type.type() ==
1429
0
          asn1::nrppa::pos_res_set_type_c::types_opts::options::periodic) {
1430
0
        pos_srs_res_set.res_type = srs_config::srs_resource_set::periodic_resource_type{};
1431
0
      } else if (asn1_pos_srs_res_set.posres_set_type.type() ==
1432
0
                 asn1::nrppa::pos_res_set_type_c::types_opts::options::semi_persistent) {
1433
0
        pos_srs_res_set.res_type = srs_config::srs_resource_set::semi_persistent_resource_type{};
1434
0
      } else if (asn1_pos_srs_res_set.posres_set_type.type() ==
1435
0
                 asn1::nrppa::pos_res_set_type_c::types_opts::options::aperiodic) {
1436
0
        srs_config::srs_resource_set::aperiodic_resource_type aperiodic;
1437
0
        aperiodic.aperiodic_srs_res_trigger = asn1_pos_srs_res_set.posres_set_type.aperiodic().srs_res_trigger;
1438
0
        pos_srs_res_set.res_type            = aperiodic;
1439
0
      } else {
1440
        // PosResourceSetType is mandatory for the positioning SRS resource set, so an unrecognized choice leaves
1441
        // its resource type without a well-defined value, and the resource set is dropped.
1442
0
        ocudulog::fetch_basic_logger("NRPPA").warning(
1443
0
            "Unsupported PosResourceSetType choice ({}). Dropping the positioning SRS resource set",
1444
0
            asn1_pos_srs_res_set.posres_set_type.type().to_string());
1445
0
        continue;
1446
0
      }
1447
1448
0
      srs_carrier_list_item.active_ul_bwp.srs_cfg.pos_srs_res_set_list.push_back(pos_srs_res_set);
1449
0
    }
1450
1451
    // Fill PCI.
1452
0
    if (asn1_srs_carrier_list_item.pci_nr_present) {
1453
0
      srs_carrier_list_item.pci_nr = asn1_srs_carrier_list_item.pci_nr;
1454
0
    }
1455
1456
0
    srs_cfg.srs_carrier_list.push_back(srs_carrier_list_item);
1457
0
  }
1458
1459
0
  return srs_cfg;
1460
0
}
1461
1462
inline expected<nr_cell_global_id_t> cgi_from_asn1(const asn1::nrppa::cgi_nr_s& asn1_cgi)
1463
0
{
1464
0
  auto plmn = plmn_identity::from_bytes(asn1_cgi.plmn_id.to_bytes());
1465
0
  if (not plmn.has_value()) {
1466
0
    return make_unexpected(plmn.error());
1467
0
  }
1468
0
  auto nci = nr_cell_identity::create(asn1_cgi.nr_cell_id.to_number());
1469
0
  if (not nci.has_value()) {
1470
0
    return make_unexpected(nci.error());
1471
0
  }
1472
0
  return nr_cell_global_id_t{plmn.value(), nci.value()};
1473
0
}
1474
1475
inline trp_meas_request_item_t
1476
asn1_to_trp_meas_request_item(const asn1::nrppa::trp_meas_request_item_s& asn1_trp_meas_request_item)
1477
0
{
1478
0
  trp_meas_request_item_t trp_meas_request_item;
1479
1480
  // Fill TRP ID.
1481
0
  trp_meas_request_item.trp_id = uint_to_trp_id(asn1_trp_meas_request_item.trp_id);
1482
1483
  // Fill search window info.
1484
0
  if (asn1_trp_meas_request_item.search_win_info_present) {
1485
0
    trp_meas_request_item.search_win_info = {asn1_trp_meas_request_item.search_win_info.expected_propagation_delay,
1486
0
                                             asn1_trp_meas_request_item.search_win_info.delay_uncertainty};
1487
0
  }
1488
1489
  // Fill IE exts.
1490
0
  if (asn1_trp_meas_request_item.ie_exts_present) {
1491
    // Fill CGI NR.
1492
0
    if (asn1_trp_meas_request_item.ie_exts.cell_id_present) {
1493
0
      expected<nr_cell_global_id_t> cgi = cgi_from_asn1(asn1_trp_meas_request_item.ie_exts.cell_id);
1494
0
      ocudu_assert(cgi.has_value(), "Received invalid CGI NR");
1495
1496
0
      trp_meas_request_item.cgi_nr = cgi.value();
1497
0
    }
1498
1499
    // Fill AoA search window.
1500
0
    if (asn1_trp_meas_request_item.ie_exts.ao_a_search_win_present) {
1501
0
      aoa_assist_info_t aoa_search_win;
1502
1503
0
      if (asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.type() ==
1504
0
          asn1::nrppa::angle_meas_type_c::types_opts::options::expected_ul_ao_a) {
1505
0
        expected_ul_aoa_t expected_ul_aoa;
1506
0
        expected_ul_aoa.expected_azimuth_aoa.expected_azimuth_aoa_value =
1507
0
            asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_ul_ao_a()
1508
0
                .expected_azimuth_ao_a.expected_azimuth_ao_a_value;
1509
0
        expected_ul_aoa.expected_azimuth_aoa.expected_azimuth_aoa_uncertainty =
1510
0
            asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_ul_ao_a()
1511
0
                .expected_azimuth_ao_a.expected_azimuth_ao_a_uncertainty;
1512
1513
0
        if (asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_ul_ao_a()
1514
0
                .expected_zenith_ao_a_present) {
1515
0
          expected_zenith_aoa_t expected_zenith_aoa;
1516
1517
0
          expected_zenith_aoa.expected_zenith_aoa_value =
1518
0
              asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_ul_ao_a()
1519
0
                  .expected_zenith_ao_a.expected_zenith_ao_a_value;
1520
0
          expected_zenith_aoa.expected_zenith_aoa_uncertainty =
1521
0
              asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_ul_ao_a()
1522
0
                  .expected_zenith_ao_a.expected_zenith_ao_a_uncertainty;
1523
1524
0
          expected_ul_aoa.expected_zenith_aoa = expected_zenith_aoa;
1525
0
        }
1526
1527
0
        aoa_search_win.angle_meas = expected_ul_aoa;
1528
0
      } else {
1529
0
        expected_zoa_only_t expected_zoa_only;
1530
0
        expected_zoa_only.expected_zoa_only.expected_zenith_aoa_value =
1531
0
            asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_zo_a()
1532
0
                .expected_zo_a_only.expected_zenith_ao_a_value;
1533
0
        expected_zoa_only.expected_zoa_only.expected_zenith_aoa_uncertainty =
1534
0
            asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_zo_a()
1535
0
                .expected_zo_a_only.expected_zenith_ao_a_uncertainty;
1536
1537
0
        aoa_search_win.angle_meas = expected_zoa_only;
1538
0
      }
1539
1540
0
      trp_meas_request_item.aoa_search_win = aoa_search_win;
1541
0
    }
1542
1543
    // Fill number of TRP RX TEG.
1544
0
    if (asn1_trp_meas_request_item.ie_exts.nof_trp_rx_teg_present) {
1545
0
      trp_meas_request_item.nof_trp_rx_teg = asn1_trp_meas_request_item.ie_exts.nof_trp_rx_teg.to_number();
1546
0
    }
1547
1548
    // Fill number of TRP RX TX TEG.
1549
0
    if (asn1_trp_meas_request_item.ie_exts.nof_trp_rx_tx_teg_present) {
1550
0
      trp_meas_request_item.nof_trp_rx_tx_teg = asn1_trp_meas_request_item.ie_exts.nof_trp_rx_tx_teg.to_number();
1551
0
    }
1552
0
  }
1553
1554
0
  return trp_meas_request_item;
1555
0
}
1556
1557
inline asn1::nrppa::trp_meas_request_item_s
1558
trp_meas_request_item_to_asn1(const trp_meas_request_item_t& trp_meas_request_item)
1559
0
{
1560
0
  asn1::nrppa::trp_meas_request_item_s asn1_trp_meas_request_item;
1561
0
1562
0
  // Fill TRP ID.
1563
0
  asn1_trp_meas_request_item.trp_id = to_underlying(trp_meas_request_item.trp_id);
1564
0
1565
0
  // Fill search window info.
1566
0
  if (trp_meas_request_item.search_win_info.has_value()) {
1567
0
    asn1_trp_meas_request_item.search_win_info_present = true;
1568
0
    asn1_trp_meas_request_item.search_win_info.expected_propagation_delay =
1569
0
        trp_meas_request_item.search_win_info->expected_propagation_delay;
1570
0
    asn1_trp_meas_request_item.search_win_info.delay_uncertainty =
1571
0
        trp_meas_request_item.search_win_info->delay_uncertainty;
1572
0
  }
1573
0
1574
0
  // Fill IE exts.
1575
0
  // > Fill CGI NR.
1576
0
  if (trp_meas_request_item.cgi_nr.has_value()) {
1577
0
    asn1_trp_meas_request_item.ie_exts_present         = true;
1578
0
    asn1_trp_meas_request_item.ie_exts.cell_id_present = true;
1579
0
    asn1_trp_meas_request_item.ie_exts.cell_id.nr_cell_id.from_number(trp_meas_request_item.cgi_nr->nci.value());
1580
0
    asn1_trp_meas_request_item.ie_exts.cell_id.plmn_id = trp_meas_request_item.cgi_nr->plmn_id.to_bytes();
1581
0
  }
1582
0
1583
0
  // > Fill AoA search window.
1584
0
  if (trp_meas_request_item.aoa_search_win.has_value()) {
1585
0
    asn1_trp_meas_request_item.ie_exts_present                 = true;
1586
0
    asn1_trp_meas_request_item.ie_exts.ao_a_search_win_present = true;
1587
0
1588
0
    if (std::holds_alternative<expected_ul_aoa_t>(trp_meas_request_item.aoa_search_win->angle_meas)) {
1589
0
      const auto& expected_ul_aoa = std::get<expected_ul_aoa_t>(trp_meas_request_item.aoa_search_win->angle_meas);
1590
0
      asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.set_expected_ul_ao_a();
1591
0
      asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_ul_ao_a()
1592
0
          .expected_azimuth_ao_a.expected_azimuth_ao_a_value =
1593
0
          expected_ul_aoa.expected_azimuth_aoa.expected_azimuth_aoa_value;
1594
0
      asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_ul_ao_a()
1595
0
          .expected_azimuth_ao_a.expected_azimuth_ao_a_uncertainty =
1596
0
          expected_ul_aoa.expected_azimuth_aoa.expected_azimuth_aoa_uncertainty;
1597
0
1598
0
      if (expected_ul_aoa.expected_zenith_aoa.has_value()) {
1599
0
        asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_ul_ao_a().expected_zenith_ao_a_present =
1600
0
            true;
1601
0
        asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_ul_ao_a()
1602
0
            .expected_zenith_ao_a.expected_zenith_ao_a_value =
1603
0
            expected_ul_aoa.expected_zenith_aoa->expected_zenith_aoa_value;
1604
0
        asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_ul_ao_a()
1605
0
            .expected_zenith_ao_a.expected_zenith_ao_a_uncertainty =
1606
0
            expected_ul_aoa.expected_zenith_aoa->expected_zenith_aoa_uncertainty;
1607
0
      }
1608
0
    } else {
1609
0
      const auto& expected_zoa_only = std::get<expected_zoa_only_t>(trp_meas_request_item.aoa_search_win->angle_meas);
1610
0
      asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.set_expected_zo_a();
1611
0
      asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_zo_a()
1612
0
          .expected_zo_a_only.expected_zenith_ao_a_value =
1613
0
          expected_zoa_only.expected_zoa_only.expected_zenith_aoa_value;
1614
0
      asn1_trp_meas_request_item.ie_exts.ao_a_search_win.angle_meas.expected_zo_a()
1615
0
          .expected_zo_a_only.expected_zenith_ao_a_uncertainty =
1616
0
          expected_zoa_only.expected_zoa_only.expected_zenith_aoa_uncertainty;
1617
0
    }
1618
0
  }
1619
0
1620
0
  // > Fill number of TRP RX TEG.
1621
0
  if (trp_meas_request_item.nof_trp_rx_teg.has_value()) {
1622
0
    asn1_trp_meas_request_item.ie_exts_present                = true;
1623
0
    asn1_trp_meas_request_item.ie_exts.nof_trp_rx_teg_present = true;
1624
0
    asn1::number_to_enum(asn1_trp_meas_request_item.ie_exts.nof_trp_rx_teg,
1625
0
                         trp_meas_request_item.nof_trp_rx_teg.value());
1626
0
  }
1627
0
1628
0
  // > Fill number of TRP RX TX TEG.
1629
0
  if (trp_meas_request_item.nof_trp_rx_tx_teg.has_value()) {
1630
0
    asn1_trp_meas_request_item.ie_exts_present                   = true;
1631
0
    asn1_trp_meas_request_item.ie_exts.nof_trp_rx_tx_teg_present = true;
1632
0
    asn1::number_to_enum(asn1_trp_meas_request_item.ie_exts.nof_trp_rx_tx_teg,
1633
0
                         trp_meas_request_item.nof_trp_rx_tx_teg.value());
1634
0
  }
1635
0
1636
0
  return asn1_trp_meas_request_item;
1637
0
}
1638
1639
inline std::optional<trp_meas_quantities_list_item_t> asn1_to_trp_meas_quantities_list_item(
1640
    const asn1::nrppa::trp_meas_quantities_list_item_s& asn1_trp_meas_quantities_list_item)
1641
0
{
1642
0
  trp_meas_quantities_list_item_t trp_meas_quantities_list_item;
1643
1644
0
  switch (asn1_trp_meas_quantities_list_item.trp_meas_quantities_item) {
1645
0
    case asn1::nrppa::trp_meas_type_e::gnb_rx_tx_time_diff:
1646
0
      trp_meas_quantities_list_item.trp_meas_quantities_item = trp_meas_quantities_item_t::gnb_rx_tx_time_diff;
1647
0
      break;
1648
0
    case asn1::nrppa::trp_meas_type_e::ul_srs_rsrp:
1649
0
      trp_meas_quantities_list_item.trp_meas_quantities_item = trp_meas_quantities_item_t::ul_srs_rsrp;
1650
0
      break;
1651
0
    case asn1::nrppa::trp_meas_type_e::ul_ao_a:
1652
0
      trp_meas_quantities_list_item.trp_meas_quantities_item = trp_meas_quantities_item_t::ul_aoa;
1653
0
      break;
1654
0
    case asn1::nrppa::trp_meas_type_e::ul_rtoa:
1655
0
      trp_meas_quantities_list_item.trp_meas_quantities_item = trp_meas_quantities_item_t::ul_rtoa;
1656
0
      break;
1657
0
    case asn1::nrppa::trp_meas_type_e::multiple_ul_ao_a:
1658
0
      trp_meas_quantities_list_item.trp_meas_quantities_item = trp_meas_quantities_item_t::multiple_ul_aoa;
1659
0
      break;
1660
0
    case asn1::nrppa::trp_meas_type_e::ul_srs_rsrp_p:
1661
0
      trp_meas_quantities_list_item.trp_meas_quantities_item = trp_meas_quantities_item_t::ul_srs_rsrp_p;
1662
0
      break;
1663
0
    default:
1664
0
      ocudulog::fetch_basic_logger("NRPPA").debug(
1665
0
          "Unsupported NRPPa TRP meas quantities item ({}). Ignoring it",
1666
0
          asn1_trp_meas_quantities_list_item.trp_meas_quantities_item.to_string());
1667
0
      return std::nullopt;
1668
0
  }
1669
1670
0
  if (asn1_trp_meas_quantities_list_item.timing_report_granularity_factor_present) {
1671
0
    trp_meas_quantities_list_item.timing_report_granularity_factor =
1672
0
        asn1_trp_meas_quantities_list_item.timing_report_granularity_factor;
1673
0
  }
1674
1675
0
  return trp_meas_quantities_list_item;
1676
0
}
1677
1678
inline asn1::nrppa::trp_meas_quantities_list_item_s
1679
trp_meas_quantities_list_item_to_asn1(const trp_meas_quantities_list_item_t& trp_meas_quantities_list_item)
1680
0
{
1681
0
  asn1::nrppa::trp_meas_quantities_list_item_s asn1_trp_meas_quantities_list_item;
1682
0
1683
0
  switch (trp_meas_quantities_list_item.trp_meas_quantities_item) {
1684
0
    case trp_meas_quantities_item_t::gnb_rx_tx_time_diff:
1685
0
      asn1_trp_meas_quantities_list_item.trp_meas_quantities_item = asn1::nrppa::trp_meas_type_e::gnb_rx_tx_time_diff;
1686
0
      break;
1687
0
    case trp_meas_quantities_item_t::ul_srs_rsrp:
1688
0
      asn1_trp_meas_quantities_list_item.trp_meas_quantities_item = asn1::nrppa::trp_meas_type_e::ul_srs_rsrp;
1689
0
      break;
1690
0
    case trp_meas_quantities_item_t::ul_aoa:
1691
0
      asn1_trp_meas_quantities_list_item.trp_meas_quantities_item = asn1::nrppa::trp_meas_type_e::ul_ao_a;
1692
0
      break;
1693
0
    case trp_meas_quantities_item_t::ul_rtoa:
1694
0
      asn1_trp_meas_quantities_list_item.trp_meas_quantities_item = asn1::nrppa::trp_meas_type_e::ul_rtoa;
1695
0
      break;
1696
0
    case trp_meas_quantities_item_t::multiple_ul_aoa:
1697
0
      asn1_trp_meas_quantities_list_item.trp_meas_quantities_item = asn1::nrppa::trp_meas_type_e::multiple_ul_ao_a;
1698
0
      break;
1699
0
    case trp_meas_quantities_item_t::ul_srs_rsrp_p:
1700
0
      asn1_trp_meas_quantities_list_item.trp_meas_quantities_item = asn1::nrppa::trp_meas_type_e::ul_srs_rsrp_p;
1701
0
      break;
1702
0
    default:
1703
0
      report_fatal_error("Cannot convert NRPPa TRP meas quantities item to ASN.1");
1704
0
  }
1705
0
1706
0
  if (trp_meas_quantities_list_item.timing_report_granularity_factor.has_value()) {
1707
0
    asn1_trp_meas_quantities_list_item.timing_report_granularity_factor_present = true;
1708
0
    asn1_trp_meas_quantities_list_item.timing_report_granularity_factor =
1709
0
        trp_meas_quantities_list_item.timing_report_granularity_factor.value();
1710
0
  }
1711
0
1712
0
  return asn1_trp_meas_quantities_list_item;
1713
0
}
1714
1715
} // namespace ocudu::ocucp