Page 1 of 1

Can't use 2 RX channels in libbladeRF with metadata?

Posted: Wed Sep 06, 2023 1:26 pm
by mikedon1
Update: I'm only having the following problem when using BLADERF_FORMAT_SC16_Q11_META, with BLADERF_FORMAT_SC16_Q11 it works fine.

I'm trying to sample 2 RX channel simultaneously with the BladeRF micro using libbladeRF. I've been having trouble finding simple example code, so I've started with the example in bladeRF/host/libraries/libbladeRF_test/test_sync that was made for the original BladeRF, and am trying to modify it. If someone could point me to an easy example, it would be very helpful. If not, below is some more detail on the questions/problems I've been having. I've also added some code and program output to the bottom of the post.

What needs to be done for each channel? What should I change when switching the test_sync example from 1 to 2 channels? Some of the things I'm doing for 1 channel are:
bladerf_set_sample_rate
bladerf_set_frequency
bladerf_set_gain_mode
bladerf_set_gain_mode
bladerf_sync_config
bladerf_enable_module
bladerf_sync_rx

It sounds like the sample rate and freq. will be the same for both, and that bladerf_sync_rx will receive interleaved samples from both channels. I'm not sure about bladerf_sync_config and bladerf_enable_module, should I do these for both, or if I do it for RX2, will it apply to RX1 as well? It looks like I should double the num_samples for bladerf_sync_rx to acquire for the same period of time as with 1 RX channel, and therefore I need to double my sample buffer size too.

I've played around with it, and when I use 1 RX channel at a sampling rate of 1 MHz, the RX timestamp increases by 2048 for each rx of 2048 samples. But for 2 RX channels, the timestamp is only increasing by 255 for every 4096 samples I'm trying to read! I've tried a few configurations, doubling some of the parameters in bladerf_sync_config, etc., without success. I've started looking at the bladeRF-cli code which does seem to support 2 RX channels, but it is a much more complicated example that I'm having trouble going through.

Thanks in advance for any advice, -Mike

Here's a code example I've added after my original post. This is a streamlined version of the test_sync example. I use a n_channels var to configure 1 or 2 channels. I've also noticed that the bladerf_get_gain always returns 60 for some reason, even though the set gain seems to be working.

Code: Select all

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libbladeRF.h>
int main()
{
    unsigned int samplerate_actual;
    uint64_t frequency_actual;
    int gain_actual;
    struct bladerf_metadata meta;
    struct bladerf *dev;
    int16_t *samples;
    int i;
    int ch;
    unsigned int block_size=2048;
    int n_channels=1; // 1 or 2 for BladeRF micro
    unsigned int read_size=block_size/n_channels; //have to halve if using 2 channels?
    bladerf_channel_layout channel_layout = n_channels == 2 ? BLADERF_RX_X2 : BLADERF_RX_X1;
        
    //allocate memory
    memset(&meta, 0, sizeof(meta));
    meta.flags = BLADERF_META_FLAG_RX_NOW;
    samples = (int16_t *)calloc(block_size, 2 * sizeof(samples[0]));
    if (samples == NULL) return -1;
    
    //open BladeRF
    if ( bladerf_open(&dev, "*:serial=bdd7") != 0 ) return -1;
    if ( bladerf_is_fpga_configured(dev) <= 0 ) return -1;
    
    //setup BladeRF, these specify a "bladerf_channel"
    for (ch=0; ch<n_channels; ch++) {
        if ( bladerf_set_sample_rate(dev, BLADERF_CHANNEL_RX(ch), 1000000, &samplerate_actual) != 0 ) return -1;
        if ( bladerf_set_frequency(dev, BLADERF_CHANNEL_RX(ch), 2400000000) != 0 ) return -1;
        if ( bladerf_get_frequency(dev, BLADERF_CHANNEL_RX(ch), &frequency_actual) != 0 ) return -1;
        if ( bladerf_set_gain_mode(dev,BLADERF_CHANNEL_RX(ch),BLADERF_GAIN_MGC) != 0 ) return -1;
        if ( bladerf_set_gain(dev, BLADERF_CHANNEL_RX(ch), 55) != 0 ) return -1;
        if ( bladerf_get_gain(dev, BLADERF_CHANNEL_RX(ch), &gain_actual) != 0 ) return -1;
        printf("Channel %d: Fs=%d, Freq=%ld, gain=%d\n",ch,samplerate_actual,frequency_actual,gain_actual);
    }
    
    //configure rx, this uses a "bladerf_channel_layout", BLADERF_RX_X2 configures for x2 RX
    if ( bladerf_sync_config(dev,channel_layout,BLADERF_FORMAT_SC16_Q11_META,32,8192,16,1000) !=0 ) return -1;

    //enable, this uses a "bladerf_channel"
    for (ch=0; ch<n_channels; ch++) {
        if ( bladerf_enable_module(dev, BLADERF_CHANNEL_RX(ch), true) !=0 ) return -1;
    }
    
    //do rx 5 times, check last sample
    printf("Starting rx, read_size = %d\n",read_size);
    for (i=0; i<5; i++) {
        if ( bladerf_sync_rx(dev, samples, read_size,  &meta, 1000) !=0 ) return -1;
        printf("rx time %ld, last sample=%d\n",meta.timestamp,samples[block_size*2-1]);
    }
    
    //clean up
    free(samples);
    for (ch=0; ch<n_channels; ch++) {
        if ( bladerf_enable_module(dev, BLADERF_CHANNEL_RX(ch), false) !=0 ) return -1;
    }
    bladerf_close(dev);
    printf("Bye!\n");
    return 0;
}
When I use 1 channel, it works fine. The time increments by 2048 for each read, and the samples look like they're written, here's an example output:

Channel 0: Fs=1000000, Freq=2400000000, gain=60
Starting rx, read_size = 2048
rx time 3, last sample=345
rx time 2051, last sample=270
rx time 4099, last sample=246
rx time 6147, last sample=155
rx time 8195, last sample=131
Bye!

When I use 2 channels, the time increments by 255 for each read, and the last sample isn't written, here's example output:

Channel 0: Fs=1000000, Freq=2400000000, gain=60
Channel 1: Fs=1000000, Freq=2400000000, gain=60
Starting rx, read_size = 1024
rx time 3, last sample=0
rx time 258, last sample=0
rx time 513, last sample=0
rx time 768, last sample=0
rx time 1023, last sample=0
Bye!

Re: Can't use 2 RX channels in libbladeRF with metadata?

Posted: Mon Sep 18, 2023 5:21 pm
by shc
I am seeing a similar (or probably the same) problem. I have a program that reads data in 2-channel mode and processes it. Metadata is enabled so I can verify that I am not losing data. Works fine with FPGA code releases 0.11.0 and 0.11.1. Does not work with 0.12.0 through 0.15.0.

A few observations:

With FPGA rev 0.11.x, the timestamp increment from metadata block to metadata block is 508 in single channel mode and 254 in dual channel mode.
With FPGA rev 0.12.0 ff, the timestamp increment is 508 in single channel mode and 255 in dual channel mode.

With 0.12.0 ff, the transfer stalls after about 1794 x 1024-sample buffers (or 897 x 2048 samples, etc) and I get timeout errors like this:
[ERROR @ host/libraries/libbladeRF/src/backend/usb/libusb.c:1089] Transfer timed out for buffer 0x5588232ca0

0.12.0 ff seem to work OK in single-channel mode.

Firmware/software versions used for testing:
FPGA: 0.12.0 ("0.12.0") (also 0.11.0, 0.11.1, 0.14.0, 0.15.0)
FW: 2.4.0 ("2.4.0-git-a3d5c55f")
Lib: 2.5.0 ("2.5.0-git-c123d839")

Any input would be appreciated ...

Re: Can't use 2 RX channels in libbladeRF with metadata?

Posted: Mon Jun 03, 2024 1:29 pm
by androidmarv
This problem was put into an issue back in 2022: https://github.com/Nuand/bladeRF/issues/855. The fix for it was released in v0.15.3 of the FPGA image. Nuand's website now hosts bitstreams for it, so you shouldn't have to do any building. If you ever find that you need a more recent version than what you can find on the site, though, I found the process for building the FPGA bitstream from the repo to be very lengthy but fairly straightforward.

Re: Can't use 2 RX channels in libbladeRF with metadata?

Posted: Mon Jun 10, 2024 9:54 pm
by derlean
Always ensure your bladeRF device is running the latest firmware and FPGA images. These updates often include fixes Nightmare Kart and improvements for dual-channel operations.

Re: Can't use 2 RX channels in libbladeRF with metadata?

Posted: Fri Jun 14, 2024 9:51 am
by lopz77
About the fact that the gain doesn't work properly, I realized that the set gain functions must be called after activating the channel to work properly...

Re: Can't use 2 RX channels in libbladeRF with metadata?

Posted: Sun Jun 16, 2024 6:59 pm
by helgaella99
Sampling Two RX Channels Simultaneously with BladeRF Micro
When sampling two RX channels simultaneously with the BladeRF micro using libbladeRF, there are several key points and configurations to consider. Below is a detailed explanation and a streamlined code example to help you achieve this.
Key Points
Sample Rate and Frequency:
Both channels will share the same sample rate and frequency settings.
Ensure you set these parameters for each channel individually.
Buffer Size and Sample Count:
When using two channels, the samples will be interleaved.
You need to double the buffer size and the number of samples to accommodate both channels.
Configuration and Enabling Modules:
Use bladerf_sync_config with the appropriate channel layout (BLADERF_RX_X2 for two channels).
Enable each RX module separately.
Metadata Handling:
When using BLADERF_FORMAT_SC16_Q11_META, ensure you handle the metadata correctly to track timestamps and other information.
Example Code
Here is a streamlined version of the code to sample two RX channels:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libbladeRF.h>

int main() {
unsigned int samplerate_actual;
uint64_t frequency_actual;
int gain_actual;
struct bladerf_metadata meta;
struct bladerf *dev;
int16_t *samples;
int i, ch;
unsigned int block_size = 2048;
int n_channels = 2; // Set to 2 for BladeRF micro
unsigned int read_size = block_size * n_channels; // Adjust for 2 channels
bladerf_channel_layout channel_layout = BLADERF_RX_X2;

// Allocate memory
memset(&meta, 0, sizeof(meta));
meta.flags = BLADERF_META_FLAG_RX_NOW;
samples = (int16_t *)calloc(read_size, 2 * sizeof(samples[0]));
if (samples == NULL) return -1;

// Open BladeRF
if (bladerf_open(&dev, "*:serial=bdd7") != 0) return -1;
if (bladerf_is_fpga_configured(dev) <= 0) return -1;

// Setup BladeRF for each channel
for (ch = 0; ch < n_channels; ch++) {
if (bladerf_set_sample_rate(dev, BLADERF_CHANNEL_RX(ch), 1000000, &samplerate_actual) != 0) return -1;
if (bladerf_set_frequency(dev, BLADERF_CHANNEL_RX(ch), 2400000000) != 0) return -1;
if (bladerf_get_frequency(dev, BLADERF_CHANNEL_RX(ch), &frequency_actual) != 0) return -1;
if (bladerf_set_gain_mode(dev, BLADERF_CHANNEL_RX(ch), BLADERF_GAIN_MGC) != 0) return -1;
if (bladerf_set_gain(dev, BLADERF_CHANNEL_RX(ch), 55) != 0) return -1;
if (bladerf_get_gain(dev, BLADERF_CHANNEL_RX(ch), &gain_actual) != 0) return -1;
printf("Channel %d: Fs=%d, Freq=%ld, gain=%d\n", ch, samplerate_actual, frequency_actual, gain_actual);
}

// Configure RX
if (bladerf_sync_config(dev, channel_layout, BLADERF_FORMAT_SC16_Q11_META, 32, 8192, 16, 1000) != 0) return -1;

// Enable modules
for (ch = 0; ch < n_channels; ch++) {
if (bladerf_enable_module(dev, BLADERF_CHANNEL_RX(ch), true) != 0) return -1;
}

// Perform RX
printf("Starting rx, read_size = %d\n", read_size);
for (i = 0; i < 5; i++) {
if (bladerf_sync_rx(dev, samples, read_size, &meta, 1000) != 0) return -1;
printf("rx time %ld, last sample=%d\n", meta.timestamp, samples[read_size * 2 - 1]);
}

// Clean up
free(samples);
for (ch = 0; ch < n_channels; ch++) {
if (bladerf_enable_module(dev, BLADERF_CHANNEL_RX(ch), false) != 0) return -1;
}
bladerf_close(dev);
printf("Bye!\n");
return 0;
}
Explanation
Memory Allocation: The buffer size is adjusted to accommodate samples from both channels.
Device Setup: Each channel is configured with the same sample rate, frequency, and gain settings.
Configuration: bladerf_sync_config is called with BLADERF_RX_X2 to configure for two RX channels.
Enabling Modules: Each RX module is enabled separately.
Receiving Samples: The bladerf_sync_rx function is called to receive interleaved samples from both channels.
This should help you get started with sampling two RX channels simultaneously using the BladeRF micro. If you encounter further issues, consider checking the official documentation or reaching out to the community for more specific guidance.

Re: Can't use 2 RX channels in libbladeRF with metadata?

Posted: Mon Jun 17, 2024 6:04 am
by lopz77
Thanks for sharing. Running the example code you shared, the gain is still not be applied to the RX channels, still return 60 when i read using bladerf_get_gain, whetever value i set. Is there any special configuration for this to happen?

Re: Can't use 2 RX channels in libbladeRF with metadata?

Posted: Tue Aug 27, 2024 1:18 am
by climbdestroy
The sync_rx method appears to be incompatible with the incoming buffer structure when metadata is used, resulting in discontinuities. This prevents, for example, TX and RX synchronization. This is in addition to the concerns with gr-osmosdr, which led to the first suspicion that samples went missing.