mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-15 05:30:29 +00:00
Compare commits
3 Commits
pre-commit
...
bladerf-2t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61a3666f3a | ||
|
|
8469f4e2cd | ||
|
|
8bf955b128 |
@@ -32,6 +32,9 @@ typedef struct {
|
||||
//! (using the first discovered backend)
|
||||
struct bladerf *dev;
|
||||
|
||||
int num_rx;
|
||||
int num_tx;
|
||||
|
||||
//! Number of buffers
|
||||
unsigned int num_buffers;
|
||||
//! Buffer size
|
||||
@@ -123,29 +126,37 @@ static int trx_brf_start(openair0_device_t *device)
|
||||
|
||||
/* Configure the device's TX module for use with the sync interface.
|
||||
* SC16 Q11 samples *with* metadata are used. */
|
||||
status = bladerf_sync_config(brf->dev, BLADERF_CHANNEL_TX(0), format,
|
||||
brf->num_buffers, brf->buffer_size, brf->num_transfers, brf->tx_timeout_ms);
|
||||
BLADERF_CHECK(status == 0,
|
||||
"Set TX sync interface num_buffers %u, buffer_size %u, num_transfer %u, tx_timeout_ms %u",
|
||||
brf->num_buffers, brf->buffer_size, brf->num_transfers, brf->tx_timeout_ms);
|
||||
for (int tx = 0; tx < brf->num_tx; ++tx) {
|
||||
status = bladerf_sync_config(brf->dev, BLADERF_CHANNEL_TX(tx), format,
|
||||
brf->num_buffers, brf->buffer_size, brf->num_transfers, brf->tx_timeout_ms);
|
||||
BLADERF_CHECK(status == 0,
|
||||
"Set TX%d sync interface num_buffers %u, buffer_size %u, num_transfer %u, tx_timeout_ms %u",
|
||||
tx, brf->num_buffers, brf->buffer_size, brf->num_transfers, brf->tx_timeout_ms);
|
||||
}
|
||||
|
||||
/* Configure the device's RX module for use with the sync interface.
|
||||
* SC16 Q11 samples *with* metadata are used. */
|
||||
status = bladerf_sync_config(brf->dev, BLADERF_CHANNEL_RX(0), format,
|
||||
brf->num_buffers, brf->buffer_size, brf->num_transfers, brf->rx_timeout_ms);
|
||||
BLADERF_CHECK(status == 0,
|
||||
"Set RX sync interface num_buffers %u, buffer_size %u, num_transfer %u, rx_timeout_ms %u",
|
||||
brf->num_buffers, brf->buffer_size, brf->num_transfers, brf->rx_timeout_ms);
|
||||
for (int rx = 0; rx < brf->num_rx; ++rx) {
|
||||
status = bladerf_sync_config(brf->dev, BLADERF_CHANNEL_RX(rx), format,
|
||||
brf->num_buffers, brf->buffer_size, brf->num_transfers, brf->rx_timeout_ms);
|
||||
BLADERF_CHECK(status == 0,
|
||||
"Set RX%d sync interface num_buffers %u, buffer_size %u, num_transfer %u, rx_timeout_ms %u",
|
||||
rx, brf->num_buffers, brf->buffer_size, brf->num_transfers, brf->rx_timeout_ms);
|
||||
}
|
||||
|
||||
/* We must always enable the TX module after calling bladerf_sync_config(), and
|
||||
* before attempting to TX samples via bladerf_sync_tx(). */
|
||||
status = bladerf_enable_module(brf->dev, BLADERF_CHANNEL_TX(0), true);
|
||||
BLADERF_CHECK(status == 0, "Enable TX0 module");
|
||||
for (int tx = 0; tx < brf->num_tx; ++tx) {
|
||||
status = bladerf_enable_module(brf->dev, BLADERF_CHANNEL_TX(tx), true);
|
||||
BLADERF_CHECK(status == 0, "Enable TX%d module", tx);
|
||||
}
|
||||
|
||||
/* We must always enable the RX module after calling bladerf_sync_config(), and
|
||||
* before attempting to RX samples via bladerf_sync_rx(). */
|
||||
status = bladerf_enable_module(brf->dev, BLADERF_CHANNEL_RX(0), true);
|
||||
BLADERF_CHECK(status == 0, "Enable RX module");
|
||||
for (int rx = 0; rx < brf->num_rx; ++rx) {
|
||||
status = bladerf_enable_module(brf->dev, BLADERF_CHANNEL_RX(rx), true);
|
||||
BLADERF_CHECK(status == 0, "Enable RX%d module", rx);
|
||||
}
|
||||
|
||||
// in case it was set to verbosity before, disable now because otherwise the
|
||||
// terminal will be flooded
|
||||
@@ -154,6 +165,20 @@ static int trx_brf_start(openair0_device_t *device)
|
||||
}
|
||||
|
||||
|
||||
static void interleave_2chan(const void **l, int len, int cc, void *out)
|
||||
{
|
||||
uint32_t total_len = 2 * len * cc;
|
||||
uint16_t *a = (uint16_t *)l[0], *b = (uint16_t *)l[1];
|
||||
uint16_t *result = out;
|
||||
for (uint32_t i = 0; i < total_len; i += 4) {
|
||||
uint32_t idx = i >> 1;
|
||||
result[i] = a[idx];
|
||||
result[i+1] = a[idx + 1];
|
||||
result[i+2] = b[idx];
|
||||
result[i+3] = b[idx + 1];
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Called to send samples to the BladeRF RF target
|
||||
\param device pointer to the device structure specific to the RF hardware target
|
||||
\param timestamp The timestamp at which the first sample MUST be sent
|
||||
@@ -168,7 +193,15 @@ static int trx_brf_write(openair0_device_t *device, openair0_timestamp_t ptimest
|
||||
brf_state_t *brf = device->priv;
|
||||
|
||||
/* BRF has only 1 rx/tx chaine : is it correct? TODO: now, handle also two! */
|
||||
int16_t *samples = (int16_t *)buff[0];
|
||||
uint32_t samp_interleaved[nsamps * cc];
|
||||
int16_t *samples;
|
||||
if (brf->num_tx == 1) {
|
||||
samples = (int16_t *)buff[0];
|
||||
} else {
|
||||
DevAssert(brf->num_tx == 2);
|
||||
samples = (int16_t *) samp_interleaved;
|
||||
interleave_2chan((const void **)buff, nsamps, cc, samp_interleaved);
|
||||
}
|
||||
ptimestamp -= device->openair0_cfg->command_line_sample_advance - device->openair0_cfg->tx_sample_advance;
|
||||
|
||||
// When BLADERF_META_FLAG_TX_NOW is used the timestamp is not used, so one can't schedule a tx
|
||||
@@ -196,6 +229,21 @@ static int trx_brf_write(openair0_device_t *device, openair0_timestamp_t ptimest
|
||||
return nsamps; // brf->meta_tx.actual_count;
|
||||
}
|
||||
|
||||
static void deinterleave_2chan(const void *l, int len, int cc, void **out)
|
||||
{
|
||||
uint32_t total_len = 2 * len * cc;
|
||||
uint16_t *a = out[0];
|
||||
uint16_t *b = out[1];
|
||||
const uint16_t *x = (const uint16_t *)l;
|
||||
for (uint32_t i = 0; i < total_len; i += 4) {
|
||||
uint32_t idx = i >> 1;
|
||||
a[idx] = x[i];
|
||||
a[idx + 1] = x[i + 1];
|
||||
b[idx] = x[i + 2];
|
||||
b[idx + 1] = x[i + 3];
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Receive samples from hardware.
|
||||
* Read \ref nsamps samples from each channel to buffers. buff[0] is the array for
|
||||
* the first channel. *ptimestamp is the time at which the first sample
|
||||
@@ -212,7 +260,14 @@ static int trx_brf_read(openair0_device_t *device, openair0_timestamp_t *ptimest
|
||||
brf_state_t *brf = device->priv;
|
||||
|
||||
// BRF has only one rx/tx chain
|
||||
int16_t *samples = (int16_t *)buff[0];
|
||||
uint32_t samp_interleaved[nsamps * cc];
|
||||
int16_t *samples;
|
||||
if (brf->num_rx == 1) {
|
||||
samples = (int16_t *)buff[0];
|
||||
} else {
|
||||
DevAssert(brf->num_rx == 2);
|
||||
samples = (int16_t *) samp_interleaved;
|
||||
}
|
||||
|
||||
brf->meta_rx.actual_count = 0;
|
||||
brf->meta_rx.flags = BLADERF_META_FLAG_RX_NOW;
|
||||
@@ -235,6 +290,10 @@ static int trx_brf_read(openair0_device_t *device, openair0_timestamp_t *ptimest
|
||||
LOG_E(HW, "RX bad samples count, wanted %d, got %d\n", nsamps, brf->meta_rx.actual_count);
|
||||
}
|
||||
|
||||
if (brf->num_rx > 1) {
|
||||
deinterleave_2chan(samp_interleaved, nsamps, cc, buff);
|
||||
}
|
||||
|
||||
brf->rx_current_ts = brf->meta_rx.timestamp;
|
||||
brf->rx_actual_nsamps += brf->meta_rx.actual_count;
|
||||
brf->rx_nsamps += nsamps;
|
||||
@@ -254,10 +313,12 @@ static void trx_brf_end(openair0_device_t *device)
|
||||
// Disable RX module, shutting down our underlying RX stream
|
||||
|
||||
int status;
|
||||
if ((status = bladerf_enable_module(brf->dev, BLADERF_CHANNEL_RX(0), false)) != 0)
|
||||
LOG_E(HW, "Failed: Disable RX module: %s\n", bladerf_strerror(status));
|
||||
if ((status = bladerf_enable_module(brf->dev, BLADERF_CHANNEL_TX(0), false)) != 0)
|
||||
LOG_E(HW, "Failed: Disable TX module: %s\n", bladerf_strerror(status));
|
||||
for (int rx = 0; rx < brf->num_rx; ++rx)
|
||||
if ((status = bladerf_enable_module(brf->dev, BLADERF_CHANNEL_RX(rx), false)) != 0)
|
||||
LOG_E(HW, "Failed: Disable RX%d module: %s\n", rx, bladerf_strerror(status));
|
||||
for (int tx = 0; tx < brf->num_tx; ++tx)
|
||||
if ((status = bladerf_enable_module(brf->dev, BLADERF_CHANNEL_TX(tx), false)) != 0)
|
||||
LOG_E(HW, "Failed: Disable TX%d module: %s\n", tx, bladerf_strerror(status));
|
||||
bladerf_close(brf->dev);
|
||||
}
|
||||
|
||||
@@ -300,13 +361,17 @@ static int trx_brf_set_freq(openair0_device_t *device, openair0_config_t *openai
|
||||
brf_state_t *brf = device->priv;
|
||||
openair0_config_t *openair0_cfg = (openair0_config_t *)device->openair0_cfg;
|
||||
|
||||
unsigned int tx_freq = (unsigned int)openair0_cfg->tx_freq[0];
|
||||
status = bladerf_set_frequency(brf->dev, BLADERF_CHANNEL_TX(0), tx_freq);
|
||||
BLADERF_CHECK(status == 0, "Set TX frequency %u", tx_freq);
|
||||
for (int tx = 0; tx < brf->num_tx; ++tx) {
|
||||
unsigned int tx_freq = (unsigned int)openair0_cfg->tx_freq[tx];
|
||||
status = bladerf_set_frequency(brf->dev, BLADERF_CHANNEL_TX(tx), tx_freq);
|
||||
BLADERF_CHECK(status == 0, "Set TX%d frequency %u", tx, tx_freq);
|
||||
}
|
||||
|
||||
unsigned int rx_freq = (unsigned int)openair0_cfg->rx_freq[0];
|
||||
status = bladerf_set_frequency(brf->dev, BLADERF_CHANNEL_RX(0), rx_freq);
|
||||
BLADERF_CHECK(status == 0, "Set RX frequency %u", rx_freq);
|
||||
for (int rx = 0; rx < brf->num_rx; ++rx) {
|
||||
unsigned int rx_freq = (unsigned int)openair0_cfg->rx_freq[rx];
|
||||
status = bladerf_set_frequency(brf->dev, BLADERF_CHANNEL_RX(rx), rx_freq);
|
||||
BLADERF_CHECK(status == 0, "Set RX%d frequency %u", rx, rx_freq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -369,7 +434,10 @@ static int configure_channel(struct bladerf *dev, channel_config_t *c)
|
||||
int device_init(openair0_device_t *device, openair0_config_t *openair0_cfg)
|
||||
{
|
||||
int status;
|
||||
brf_state_t brf = {0};
|
||||
brf_state_t brf = {
|
||||
.num_rx = openair0_cfg->rx_num_channels,
|
||||
.num_tx = openair0_cfg->tx_num_channels,
|
||||
};
|
||||
|
||||
switch ((long) openair0_cfg->sample_rate) {
|
||||
case 46080000:
|
||||
@@ -473,16 +541,7 @@ int device_init(openair0_device_t *device, openair0_config_t *openair0_cfg)
|
||||
|
||||
status = bladerf_set_gain_mode(brf.dev, BLADERF_CHANNEL_RX(0), BLADERF_GAIN_MGC);
|
||||
BLADERF_CHECK(status == 0, "Disable AGC");
|
||||
|
||||
channel_config_t rx_chan = {
|
||||
.channel = BLADERF_CHANNEL_RX(0),
|
||||
.frequency = openair0_cfg->rx_freq[0],
|
||||
.sample_rate = openair0_cfg->sample_rate,
|
||||
.bandwidth = openair0_cfg->rx_bw,
|
||||
.gain = openair0_cfg->rx_gain[0],
|
||||
};
|
||||
configure_channel(brf.dev, &rx_chan);
|
||||
|
||||
//
|
||||
// This is a hack. The USRP library currently does max_gain-tx_gain (tx_gain
|
||||
// is the attenuation, so completely illogical), but let's keep what users
|
||||
// would expect by doing the same. Existing configs can then be reused.
|
||||
@@ -492,14 +551,28 @@ int device_init(openair0_device_t *device, openair0_config_t *openair0_cfg)
|
||||
const struct bladerf_range *g = NULL;
|
||||
status = bladerf_get_gain_range(brf.dev, BLADERF_CHANNEL_TX(0), &g);
|
||||
BLADERF_CHECK(status == 0 && g != NULL, "Get TX0 gain range");
|
||||
|
||||
for (int rx = 0; rx < brf.num_rx; ++rx) {
|
||||
channel_config_t rx_chan = {
|
||||
.channel = BLADERF_CHANNEL_RX(rx),
|
||||
.frequency = openair0_cfg->rx_freq[rx],
|
||||
.sample_rate = openair0_cfg->sample_rate,
|
||||
.bandwidth = openair0_cfg->rx_bw,
|
||||
.gain = openair0_cfg->rx_gain[rx],
|
||||
};
|
||||
configure_channel(brf.dev, &rx_chan);
|
||||
}
|
||||
|
||||
for (int tx = 0; tx < brf.num_tx; ++tx) {
|
||||
channel_config_t tx_chan = {
|
||||
.channel = BLADERF_CHANNEL_TX(0),
|
||||
.frequency = openair0_cfg->tx_freq[0],
|
||||
.channel = BLADERF_CHANNEL_TX(tx),
|
||||
.frequency = openair0_cfg->tx_freq[tx],
|
||||
.sample_rate = openair0_cfg->sample_rate,
|
||||
.bandwidth = openair0_cfg->tx_bw,
|
||||
.gain = g->max - openair0_cfg->tx_gain[0], // see comment above
|
||||
.gain = g->max - openair0_cfg->tx_gain[tx], // see comment above
|
||||
};
|
||||
configure_channel(brf.dev, &tx_chan);
|
||||
}
|
||||
|
||||
LOG_I(HW, "BLADERF: Initializing device done\n");
|
||||
device->type = BLADERF_DEV;
|
||||
|
||||
@@ -2,6 +2,10 @@ Active_gNBs = ( "gNB-OAI");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
device = {
|
||||
name = "oai_bladerfdevif";
|
||||
}
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
@@ -17,6 +21,8 @@ gNBs =
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
pdsch_AntennaPorts_XP = 2;
|
||||
pusch_AntennaPorts = 2;
|
||||
min_rxtxtime = 2;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
@@ -188,8 +194,8 @@ L1s = (
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
nb_tx = 2
|
||||
nb_rx = 2
|
||||
att_tx = 0;
|
||||
att_rx = 0;
|
||||
bands = [78];
|
||||
|
||||
Reference in New Issue
Block a user