Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zzha zzha
OpenXG-RAN
Commits
051fb056
Commit
051fb056
authored
Jul 29, 2023
by
Robert Schmidt
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/fr2-interdigital-usrp-interface' into integration_2023_w30
parents
9bc00465
76ccc2f5
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
156 additions
and
53 deletions
+156
-53
executables/nr-ru.c
executables/nr-ru.c
+98
-38
openair2/ENB_APP/enb_paramdef.h
openair2/ENB_APP/enb_paramdef.h
+4
-0
radio/COMMON/common_lib.h
radio/COMMON/common_lib.h
+6
-0
radio/USRP/usrp_lib.cpp
radio/USRP/usrp_lib.cpp
+48
-15
No files found.
executables/nr-ru.c
View file @
051fb056
...
...
@@ -726,6 +726,49 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
stop_meas
(
&
ru
->
rx_fhaul
);
}
static
radio_tx_gpio_flag_t
get_gpio_flags
(
RU_t
*
ru
,
int
slot
)
{
radio_tx_gpio_flag_t
flags_gpio
=
0
;
NR_DL_FRAME_PARMS
*
fp
=
ru
->
nr_frame_parms
;
openair0_config_t
*
cfg0
=
&
ru
->
openair0_cfg
;
switch
(
cfg0
->
gpio_controller
)
{
case
RU_GPIO_CONTROL_GENERIC
:
// currently we switch beams at the beginning of a slot and we take the beam index of the first symbol of this slot
// we only send the beam to the gpio if the beam is different from the previous slot
if
(
ru
->
common
.
beam_id
)
{
int
prev_slot
=
(
slot
-
1
+
fp
->
slots_per_frame
)
%
fp
->
slots_per_frame
;
const
uint8_t
*
beam_ids
=
ru
->
common
.
beam_id
[
0
];
int
prev_beam
=
beam_ids
[
prev_slot
*
fp
->
symbols_per_slot
];
int
beam
=
beam_ids
[
slot
*
fp
->
symbols_per_slot
];
if
(
prev_beam
!=
beam
)
{
flags_gpio
=
beam
|
TX_GPIO_CHANGE
;
// enable change of gpio
LOG_I
(
HW
,
"slot %d, beam %d
\n
"
,
slot
,
ru
->
common
.
beam_id
[
0
][
slot
*
fp
->
symbols_per_slot
]);
}
}
break
;
case
RU_GPIO_CONTROL_INTERDIGITAL
:
{
// the beam index is written in bits 8-10 of the flags
// bit 11 enables the gpio programming
int
beam
=
0
;
if
((
slot
%
10
==
0
)
&&
ru
->
common
.
beam_id
&&
(
ru
->
common
.
beam_id
[
0
][
slot
*
fp
->
symbols_per_slot
]
<
64
))
{
// beam = ru->common.beam_id[0][slot*fp->symbols_per_slot] | 64;
beam
=
1024
;
// hardcoded now for beam32 boresight
// beam = 127; //for the sake of trying beam63
LOG_D
(
HW
,
"slot %d, beam %d
\n
"
,
slot
,
beam
);
}
flags_gpio
=
beam
|
TX_GPIO_CHANGE
;
// flags_gpio |= beam << 8; // MSB 8 bits are used for beam
LOG_I
(
HW
,
"slot %d, beam %d, flags_gpio %d
\n
"
,
slot
,
beam
,
flags_gpio
);
break
;
}
default:
AssertFatal
(
false
,
"illegal GPIO controller %d
\n
"
,
cfg0
->
gpio_controller
);
}
return
flags_gpio
;
}
void
tx_rf
(
RU_t
*
ru
,
int
frame
,
int
slot
,
uint64_t
timestamp
)
{
RU_proc_t
*
proc
=
&
ru
->
proc
;
...
...
@@ -783,47 +826,47 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
flags_burst
=
proc
->
first_tx
==
1
?
TX_BURST_START
:
TX_BURST_MIDDLE
;
}
if
(
fp
->
freq_range
==
nr_FR2
)
{
// currently we switch beams at the beginning of a slot and we take the beam index of the first symbol of this slot
// we only send the beam to the gpio if the beam is different from the previous slot
if
(
ru
->
common
.
beam_id
)
{
int
prev_slot
=
(
slot
-
1
+
fp
->
slots_per_frame
)
%
fp
->
slots_per_frame
;
const
uint8_t
*
beam_ids
=
ru
->
common
.
beam_id
[
0
];
int
prev_beam
=
beam_ids
[
prev_slot
*
fp
->
symbols_per_slot
];
int
beam
=
beam_ids
[
slot
*
fp
->
symbols_per_slot
];
if
(
prev_beam
!=
beam
)
{
flags_gpio
=
beam
|
TX_GPIO_CHANGE
;
// enable change of gpio
LOG_D
(
HW
,
"slot %d, beam %d
\n
"
,
slot
,
ru
->
common
.
beam_id
[
0
][
slot
*
fp
->
symbols_per_slot
]);
}
}
}
const
int
flags
=
flags_burst
|
flags_gpio
<<
4
;
if
(
fp
->
freq_range
==
nr_FR2
)
flags_gpio
=
get_gpio_flags
(
ru
,
slot
);
if
(
proc
->
first_tx
==
1
)
proc
->
first_tx
=
0
;
const
int
flags
=
flags_burst
|
(
flags_gpio
<<
4
)
;
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS
,
flags
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU
,
frame
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU
,
slot
);
if
(
proc
->
first_tx
==
1
)
proc
->
first_tx
=
0
;
for
(
i
=
0
;
i
<
ru
->
nb_tx
;
i
++
)
txp
[
i
]
=
(
void
*
)
&
ru
->
common
.
txdata
[
i
][
fp
->
get_samples_slot_timestamp
(
slot
,
fp
,
0
)]
-
sf_extension
*
sizeof
(
int32_t
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST
,
(
timestamp
+
ru
->
ts_offset
-
ru
->
openair0_cfg
.
tx_sample_advance
)
&
0xffffffff
);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE
,
1
);
// prepare tx buffer pointers
txs
=
ru
->
rfdevice
.
trx_write_func
(
&
ru
->
rfdevice
,
timestamp
+
ru
->
ts_offset
-
ru
->
openair0_cfg
.
tx_sample_advance
-
sf_extension
,
txp
,
siglen
+
sf_extension
,
ru
->
nb_tx
,
flags
);
LOG_D
(
PHY
,
"[TXPATH] RU %d aa %d tx_rf, writing to TS %llu, %d.%d, unwrapped_frame %d, slot %d, flags %d, siglen+sf_extension %d, returned %d, E %f
\n
"
,
ru
->
idx
,
i
,
(
long
long
unsigned
int
)(
timestamp
+
ru
->
ts_offset
-
ru
->
openair0_cfg
.
tx_sample_advance
-
sf_extension
),
frame
,
slot
,
proc
->
frame_tx_unwrap
,
slot
,
flags
,
siglen
+
sf_extension
,
txs
,
10
*
log10
((
double
)
signal_energy
(
txp
[
0
],
siglen
+
sf_extension
)));
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE
,
0
);
//AssertFatal(txs == 0,"trx write function error %d\n", txs);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS
,
flags
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU
,
frame
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU
,
slot
);
for
(
i
=
0
;
i
<
ru
->
nb_tx
;
i
++
)
txp
[
i
]
=
(
void
*
)
&
ru
->
common
.
txdata
[
i
][
fp
->
get_samples_slot_timestamp
(
slot
,
fp
,
0
)]
-
sf_extension
*
sizeof
(
int32_t
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST
,
(
timestamp
+
ru
->
ts_offset
-
ru
->
openair0_cfg
.
tx_sample_advance
)
&
0xffffffff
);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE
,
1
);
// prepare tx buffer pointers
txs
=
ru
->
rfdevice
.
trx_write_func
(
&
ru
->
rfdevice
,
timestamp
+
ru
->
ts_offset
-
ru
->
openair0_cfg
.
tx_sample_advance
-
sf_extension
,
txp
,
siglen
+
sf_extension
,
ru
->
nb_tx
,
flags
);
LOG_D
(
PHY
,
"[TXPATH] RU %d aa %d tx_rf, writing to TS %llu, %d.%d, unwrapped_frame %d, slot %d, flags %d, siglen+sf_extension %d, "
"returned %d, E %f
\n
"
,
ru
->
idx
,
i
,
(
long
long
unsigned
int
)(
timestamp
+
ru
->
ts_offset
-
ru
->
openair0_cfg
.
tx_sample_advance
-
sf_extension
),
frame
,
slot
,
proc
->
frame_tx_unwrap
,
slot
,
flags
,
siglen
+
sf_extension
,
txs
,
10
*
log10
((
double
)
signal_energy
(
txp
[
0
],
siglen
+
sf_extension
)));
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE
,
0
);
// AssertFatal(txs == 0,"trx write function error %d\n", txs);
}
// this is for RU with local RF unit
...
...
@@ -1881,6 +1924,23 @@ static void NRRCconfig_RU(void)
RC
.
ru
[
j
]
->
openair0_cfg
.
sdr_addrs
=
strdup
(
*
(
RUParamList
.
paramarray
[
j
][
RU_SDR_ADDRS
].
strptr
));
}
if
(
config_isparamset
(
RUParamList
.
paramarray
[
j
],
RU_GPIO_CONTROL
))
{
if
(
strcmp
(
*
RUParamList
.
paramarray
[
j
][
RU_GPIO_CONTROL
].
strptr
,
"generic"
)
==
0
)
{
RC
.
ru
[
j
]
->
openair0_cfg
.
gpio_controller
=
RU_GPIO_CONTROL_GENERIC
;
LOG_I
(
PHY
,
"RU GPIO control set as 'generic'
\n
"
);
}
else
if
(
strcmp
(
*
RUParamList
.
paramarray
[
j
][
RU_GPIO_CONTROL
].
strptr
,
"interdigital"
)
==
0
)
{
RC
.
ru
[
j
]
->
openair0_cfg
.
gpio_controller
=
RU_GPIO_CONTROL_INTERDIGITAL
;
LOG_I
(
PHY
,
"RU GPIO control set as 'interdigital'
\n
"
);
}
else
{
AssertFatal
(
false
,
"bad GPIO controller in configuration file: '%s'
\n
"
,
*
(
RUParamList
.
paramarray
[
j
][
RU_GPIO_CONTROL
].
strptr
));
}
}
else
{
RC
.
ru
[
j
]
->
openair0_cfg
.
gpio_controller
=
RU_GPIO_CONTROL_GENERIC
;
LOG_I
(
PHY
,
"RU GPIO control set as 'generic'
\n
"
);
}
if
(
config_isparamset
(
RUParamList
.
paramarray
[
j
],
RU_TX_SUBDEV
))
{
RC
.
ru
[
j
]
->
openair0_cfg
.
tx_subdev
=
strdup
(
*
(
RUParamList
.
paramarray
[
j
][
RU_TX_SUBDEV
].
strptr
));
LOG_I
(
PHY
,
"RU USRP tx subdev == %s
\n
"
,
RC
.
ru
[
j
]
->
openair0_cfg
.
tx_subdev
);
...
...
openair2/ENB_APP/enb_paramdef.h
View file @
051fb056
...
...
@@ -112,6 +112,7 @@ typedef enum {
#define CONFIG_STRING_RU_NUM_INTERFACES "num_interfaces"
#define CONFIG_STRING_RU_HALF_SLOT_PARALLELIZATION "half_slot_parallelization"
#define CONFIG_STRING_RU_RU_THREAD_CORE "ru_thread_core"
#define CONFIG_STRING_RU_GPIO_CONTROL "gpio_controller"
#define HLP_RU_SF_AHEAD "LTE TX processing advance"
#define HLP_RU_SL_AHEAD "NR TX processing advance"
...
...
@@ -124,6 +125,7 @@ typedef enum {
#define HLP_RU_NUM_INTERFACES "Number of network interfaces for RU"
#define HLP_RU_HALF_SLOT_PARALLELIZATION "run half slots in parallel in RU FEP"
#define HLP_RU_RU_THREAD_CORE "id of core to pin ru_thread, -1 is default"
#define HLP_RU_GPIO_CONTROL "set the GPIO control type for the RU"
#define RU_LOCAL_IF_NAME_IDX 0
#define RU_LOCAL_ADDRESS_IDX 1
...
...
@@ -167,6 +169,7 @@ typedef enum {
#define RU_NUM_INTERFACES 39
#define RU_HALF_SLOT_PARALLELIZATION 40
#define RU_RU_THREAD_CORE 41
#define RU_GPIO_CONTROL 42
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
/* RU configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
...
...
@@ -215,6 +218,7 @@ typedef enum {
{CONFIG_STRING_RU_NUM_INTERFACES, HLP_RU_NUM_INTERFACES, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_HALF_SLOT_PARALLELIZATION, HLP_RU_HALF_SLOT_PARALLELIZATION, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_RU_THREAD_CORE, HLP_RU_RU_THREAD_CORE, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_GPIO_CONTROL, HLP_RU_GPIO_CONTROL, 0, .strptr=NULL, .defstrval="generic", TYPE_STRING, 0}, \
}
// clang-format on
...
...
radio/COMMON/common_lib.h
View file @
051fb056
...
...
@@ -173,6 +173,10 @@ typedef struct {
notifiedFIFO_t
*
resp
;
}
udp_ctx_t
;
typedef
enum
{
RU_GPIO_CONTROL_GENERIC
,
RU_GPIO_CONTROL_INTERDIGITAL
,
}
gpio_control_t
;
/*! \brief RF frontend parameters set by application */
typedef
struct
{
...
...
@@ -275,6 +279,8 @@ typedef struct {
int
rxfh_cores
[
4
];
//! Core IDs for TX FH
int
txfh_cores
[
4
];
//! select the GPIO control method
gpio_control_t
gpio_controller
;
}
openair0_config_t
;
/*! \brief RF mapping */
...
...
radio/USRP/usrp_lib.cpp
View file @
051fb056
...
...
@@ -263,7 +263,42 @@ static int sync_to_gps(openair0_device *device) {
#define ATR_MASK 0x7f //pins controlled by ATR
#define ATR_RX 0x50 //data[4] and data[6]
#define ATR_XX 0x20 //data[5]
#define MAN_MASK ATR_MASK^0xFFF //manually controlled pins
#define MAN_MASK ATR_MASK ^ 0xFFF // manually controlled pins
static
void
trx_usrp_start_interdigital_gpio
(
openair0_device
*
device
,
usrp_state_t
*
s
)
{
AssertFatal
(
device
->
type
==
USRP_X400_DEV
,
"interdigital frontend device for beam management can only be used together with an X400
\n
"
);
// s->gpio_bank="GPIO0";
std
::
vector
<
std
::
string
>
sxx
{
12
,
"DB0_RF0"
};
// set every pin on GPIO0 to be ocntrolled by DB1_RF0
s
->
usrp
->
set_gpio_src
(
s
->
gpio_bank
,
sxx
);
// set data direction register (DDR) to output
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"DDR"
,
0xfff
,
0xfff
);
// set lower GPIO#1 to be controlled automatically by ATR (the rest bits are controlled manually)
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"CTRL"
,
(
1
<<
1
),
(
1
<<
1
));
// set GPIO1 (Tx/Rx1) to 1 for MHU1 for transmistting
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"ATR_XX"
,
(
1
<<
1
),
(
1
<<
1
));
// set GPIO4 (ID0) to 1 and GPIO2 (TX/RX2) &GPIO3 (ID1) to 0
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"OUT"
,
(
1
<<
4
),
0x1c
);
}
static
void
trx_usrp_start_generic_gpio
(
openair0_device
*
device
,
usrp_state_t
*
s
)
{
// setup GPIO for TDD, GPIO(4) = ATR_RX
// set data direction register (DDR) to output
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"DDR"
,
0xfff
,
0xfff
);
// set bits to be controlled automatically by ATR
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"CTRL"
,
ATR_MASK
,
0xfff
);
// set bits to 1 when the radio is only receiving (ATR_RX)
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"ATR_RX"
,
ATR_RX
,
ATR_MASK
);
// set bits to 1 when the radio is transmitting and receiveing (ATR_XX)
// (we use full duplex here, because our RX is on all the time - this might need to change later)
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"ATR_XX"
,
ATR_XX
,
ATR_MASK
);
// set all other pins to manual
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"OUT"
,
MAN_MASK
,
0xfff
);
}
/*! \brief Called to start the USRP transceiver. Return 0 if OK, < 0 if error
@param device pointer to the device structure specific to the RF hardware target
...
...
@@ -280,21 +315,19 @@ static int trx_usrp_start(openair0_device *device) {
s
->
gpio_bank
=
(
char
*
)
"GPIO0"
;
s
->
usrp
->
set_gpio_src
(
s
->
gpio_bank
,
sxx
);
}
#endif
#endif
switch
(
device
->
openair0_cfg
->
gpio_controller
)
{
case
RU_GPIO_CONTROL_GENERIC
:
trx_usrp_start_generic_gpio
(
device
,
s
);
break
;
case
RU_GPIO_CONTROL_INTERDIGITAL
:
trx_usrp_start_interdigital_gpio
(
device
,
s
);
break
;
default:
AssertFatal
(
false
,
"illegal GPIO controller %d
\n
"
,
device
->
openair0_cfg
->
gpio_controller
);
}
// setup GPIO for TDD, GPIO(4) = ATR_RX
//set data direction register (DDR) to output
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"DDR"
,
0xfff
,
0xfff
);
//set bits to be controlled automatically by ATR
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"CTRL"
,
ATR_MASK
,
0xfff
);
//set bits to 1 when the radio is only receiving (ATR_RX)
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"ATR_RX"
,
ATR_RX
,
ATR_MASK
);
// set bits to 1 when the radio is transmitting and receiveing (ATR_XX)
// (we use full duplex here, because our RX is on all the time - this might need to change later)
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"ATR_XX"
,
ATR_XX
,
ATR_MASK
);
// set all other pins to manual
s
->
usrp
->
set_gpio_attr
(
s
->
gpio_bank
,
"OUT"
,
MAN_MASK
,
0xfff
);
s
->
wait_for_first_pps
=
1
;
s
->
rx_count
=
0
;
s
->
tx_count
=
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment