Nuand / bladeRF

bladeRF USB 3.0 Superspeed Software Defined Radio Source Code
http://nuand.com
Other
1.15k stars 459 forks source link

bladerf_set_sample_rate issue on multiple output (MO) mode #675

Closed f4exb closed 6 years ago

f4exb commented 6 years ago

I am reporting this as an issue following this post in the forum: https://nuand.com/forums/viewtopic.php?f=9&t=4999&p=9076#p9076

When both Tx are engaged the output is garbled if bladerf_set_sample_rate is set with the sample rate of one channel. I realized by chance that doubling the sample rate value would fix the problem.

However according to the post mentioned this is not expected. Indeed on the Rx side you would use the sample rate of one channel when working in multiple input (MI) mode.

A consequence of doubling the sample rate on the Tx side is that it is also doubled on the Rx side since the sample rate is common to all channels.

Edit: this is with libbladeRF 2018.08 release

rtucker commented 6 years ago

I believe the expected behavior for this should be that the sample rate be the sample rate of one channel; e.g. 10 MSps should be 10 MSps for each channel, whether one or two are in use. This would be the "least surprising" interpretation of it.

Thanks for the report! I will dig in...

rtucker commented 6 years ago

10M samples, 10 MSps...

RX with channel=1:

[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: RX1 ch_en=1 ch_pend=1 dir_en=1 dir_pend=1 be_clr=0 reg=0xf8000001->0xf8008083 nsec=1538668660431187000 (delta: 12561629000)
[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: RX1 ch_en=0 ch_pend=1 dir_en=0 dir_pend=1 be_clr=0 reg=0xf8008083->0xf8000001 nsec=1538668661496262000 (delta: 1065075000)

TX with channel=1:

[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: TX1 ch_en=1 ch_pend=1 dir_en=1 dir_pend=1 be_clr=0 reg=0xf8000001->0xf8011005 nsec=1538668679638741000 (delta: 18142479000)
[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: TX1 ch_en=0 ch_pend=1 dir_en=0 dir_pend=1 be_clr=0 reg=0xf8011005->0xf8000001 nsec=1538668680709531000 (delta: 1070790000)

RX with channel=1,2:

[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: RX1 ch_en=1 ch_pend=1 dir_en=1 dir_pend=1 be_clr=0 reg=0xf8000001->0xf8008083 nsec=1538668692890623000 (delta: 12181092000)
[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: RX2 ch_en=1 ch_pend=1 dir_en=1 dir_pend=0 be_clr=1 reg=0xf8008083->0xf8028283 nsec=1538668692892078000 (delta: 1455000)
[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: RX1 ch_en=0 ch_pend=1 dir_en=1 dir_pend=0 be_clr=0 reg=0xf8028283->0xf8020203 nsec=1538668693417561000 (delta: 525483000)
[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: RX2 ch_en=0 ch_pend=1 dir_en=0 dir_pend=1 be_clr=0 reg=0xf8020203->0xf8000001 nsec=1538668693429982000 (delta: 12421000)

TX with channel=1,2:

[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: TX1 ch_en=1 ch_pend=1 dir_en=1 dir_pend=1 be_clr=0 reg=0xf8000001->0xf8011005 nsec=1538668883516623000 (delta: 190086641000)
[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: TX2 ch_en=1 ch_pend=1 dir_en=1 dir_pend=0 be_clr=0 reg=0xf8011005->0xf8055005 nsec=1538668883519528000 (delta: 2905000)
[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: TX1 ch_en=0 ch_pend=1 dir_en=1 dir_pend=0 be_clr=0 reg=0xf8055005->0xf8044005 nsec=1538668884050209000 (delta: 530681000)
[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: TX2 ch_en=0 ch_pend=1 dir_en=0 dir_pend=1 be_clr=0 reg=0xf8044005->0xf8000001 nsec=1538668884060456000 (delta: 10247000)

Looking at the deltas between ch_en=1 and ch_en=0:

RX 1 ch: 1065075000 (1065 ms) RX 2 ch: 525483000 (525 ms) TX 1 ch: 1070790000 (1071 ms) TX 2 ch: 530681000 (531 ms)

So this seems reasonably consistent at first glance, and it doesn't seem like what I was afraid it would be.

@f4exb , do you have a test case to reproduce this? Are you using bladeRF-cli, or your own code? I'm wondering if it's an interleaving thing.

f4exb commented 6 years ago

In fact this is the code in SDRangel I am currently developing to support the 2.0 micro. It is a bit complex since both Tx streams are handled each by its own instance of the Tx code. Since the actual stream is interleaved only one thread instance takes care of the call to bladerf_sync_tx. The thread pointer is shared between all instances of the rest of the Tx code.

Everything revolves around these three files:

https://github.com/f4exb/sdrangel/blob/dev/devices/bladerf2/devicebladerf2.cpp contains common routines including an "openTx" and "closeTx" that encapsulates the call to bladerf_enable_module to enable or disable channels.

https://github.com/f4exb/sdrangel/blob/dev/plugins/samplesink/bladerf2output/bladerf2output.cpp there is one instance for each channel. It is responsible of managing the unique thread and will make calls to "openTx" and "closeTx" mentioned above

https://github.com/f4exb/sdrangel/blob/dev/plugins/samplesink/bladerf2output/bladerf2outputthread.cpp this is the unique thread described above. It will make a call to bladerf_sync_config then run bladerf_sync_tx in a loop. Before calling bladerf_sync_tx the buffer is prepared in callbackMO() where the bladerf_interleave_stream_buffer is called to interleave samples from both buffers.

The order of calls to the libbladeRF methods is thus the following:

bladerf_set_sample_rate is called in bladerf2output.cpp whenever the sample rate is changed from the GUI.

Note: there are no particular issues on the Rx side using the same scheme:

I hope this helps.

rtucker commented 6 years ago

Hmm okay... so I'm giving this a try with the HEAD of the dev branch (39c001f95e3a09656c7f86cb147f88e663202d22), with two NBFM modulators, one at -30 kHz, one at +30 kHz. I believe I have things configured to send the -30 kHz output to TX1 and the +30 kHz output to TX2, but it turns out I am getting both modulators on TX1 and nothing at all on TX2.

I'm a first-time SDRangel user, so there is a very good chance I am doing this wrong. I'm going to crank up some debugging to see what's happening underneath, though.

Here's my setup for T1:

sdrangel-t1

And for T2:

sdrangel-t2

f4exb commented 6 years ago

Hi, according to the screenshots this is correct:

I proceed the same way for my test just adding a bit of software interpolation (the Int combo box).

How do you conclude that only Tx1 is used? Maybe this is the issue.

rtucker commented 6 years ago

I tossed a bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_VERBOSE); into DeviceBladeRF2::open_bladerf_from_serial() to see what's going on in libbladeRF, and it looks like TX1 is being enabled twice:

[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: TX1 ch_en=1 ch_pend=1 dir_en=1 dir_pend=1 be_clr=0 reg=0xf8000001->0xf8011005 nsec=1539029951533835785 (delta: 1539029951533835785)
[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: TX1 ch_en=0 ch_pend=1 dir_en=0 dir_pend=1 be_clr=0 reg=0xf8011005->0xf8000001 nsec=1539029992533098616 (delta: 40999262831)
[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: TX1 ch_en=1 ch_pend=1 dir_en=1 dir_pend=1 be_clr=0 reg=0xf8000001->0xf8011005 nsec=1539029993738350112 (delta: 1205251496)
[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1878] bladerf2_enable_module: TX1 ch_en=1 ch_pend=0 dir_en=1 dir_pend=0 be_clr=0 reg=0xf8011005->0xf8011005 nsec=1539029993739171494 (delta: 821382)
[DEBUG @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:1889] bladerf2_enable_module: reg value unchanged? (f8011005)

(Line 3 would be the first call to enable TX1, lines 4 and 5 would be the second call)

f4exb commented 6 years ago

I just had another look at my DeviceBladeRF2::openTx() routine and the error was sitting there right in front of my eyes: status = bladerf_enable_module(m_dev, BLADERF_CHANNEL_TX(0), true); This should be changed to (of course): status = bladerf_enable_module(m_dev, BLADERF_CHANNEL_TX(channel), true); As done for the Rx which explains the difference of behavior between Rx and Tx.

I'll try that and close this issue if successful.

f4exb commented 6 years ago

Yes. That was the issue. Thanks for directing me to the real problem and sorry for the inconvenience. https://github.com/f4exb/sdrangel/issues/225 opened to fix the issue.

rtucker commented 6 years ago

You're welcome! I've done this exact thing a few times. :woman_facepalming:

Thanks!!