pothosware / SoapyBladeRF

Soapy SDR plugin for the Blade RF
https://github.com/pothosware/SoapyBladeRF/wiki
23 stars 19 forks source link

Activating the PLL clock refrerence #36

Open SignalWhisperer opened 3 years ago

SignalWhisperer commented 3 years ago

I'm using a 10 MHz external reference and need the bladeRF to enable the PLL so it considers it. Given setClockSource does nothing by default and I didn't find any option to enable the PLL, I had to code a workaround to get the native handle to the bladeRF device and make the library call myself, but I guess it shouldn't be too hard to implement. The question would be where is the most appropriate place to do so.

PLL API

bladerf_set_pll_enable(dev, true);
bladerf_set_pll_refclk(dev, 10000000); // already this value by default

I know in SoapyUHD they use a call to setClockSource("external"), but for the bladeRF you also need to be able to specify the clock frequency and the SoapySDR interface does not provide that. I'm thinking the best place would probably be in the SoapySDR Settings API, or maybe even a mix of both.

guruofquality commented 3 years ago

Maybe another option is to put the frequency into the clock source name. Though its not nice to enumerate options this way. Not exactly as intended :-)

There is also an unused setMasterClockRate(), its typically used to set the common clocking for the ADC/DAC, but i think configuring the reference clock is just as correct here.

So maybe setClockSource("PLL") and setMasterClockRate(10e6) is a good way to handle this

I think we should at least try to support these options through the API, even if a a "native" handle would work as well.

SignalWhisperer commented 3 years ago

I definitely don't want to go through the native handle. It's only as a last resort (and to support more advanced features while still retaining the simplicity of SoapySDR).

I Ilike the setClockSource("PLL") and the setMasterClockRate(10e6). It's elegant. I'll make a PR for it.

SignalWhisperer commented 3 years ago

I'm starting to think we need to rethink this.

Clock control PLL

These two APIs would be controlled by the same thing, and they would confuse anyone trying to do one but not the other. You can only have 1 clock selected, but you can have the PLL enabled and an external clock set.

Of course, we could ignore the clock select API and only add the PLL, which would work for my use case, but would be bad in the long term. We could also use the settings API to enable the PLL and set the frequency, although it's not as elegant.

In the end, you're the project owner, so I'll leave the final call to your wisdom.

SignalWhisperer commented 3 years ago

I've created a PR (#37) for what we had initially discussed, with just the PLL. I was unable to test it as I currently do not have direct access to a bladeRF (it is at my client's facilities), but it builds and I'll be testing it shortly.

guruofquality commented 3 years ago

clocking diagram for reference:

https://www.nuand.com/wp-content/uploads/2018/08/bladeRF-2.0-micro-Block-Diagram-4.png

guruofquality commented 3 years ago

I'm a little confused by the diagram, but I think the intention is to either feed the PLL an external reference like 10 MHz. Or to provide a "fundamental clock" from the clock output of one blade rf to the clock input of another. In this case, I think the digram just means that the fundamental clock is directly used in place of the PLL, passed into the clock buffer, and directly into the RFIC.

If I happen to be wrong, I still think that the options to setClockSource should enumerate real world options and that setClockSource() should be handling both select clock and enable pll.

SignalWhisperer commented 3 years ago

From what I gather of the diagram and the schematics, REF_IN only feeds into the ADF chip, which seems to connect to the SYNC_IN of the RFIC, which is used to synchronize multiple clocks. The clock from CLK_IN replaces the VCTCXO as the system clock. So both could technically be used at the same time, with CLK_IN being the master clock and REF_IN being used to pace the DAC.

The schematics I found are incomplete as a lot of signals get put into banks and nothing seems to be using them. I'm guessing they would be available to the FPGA, which means the rest depends on the firmware.

SignalWhisperer commented 3 years ago

I also think there's a missing interface in SoapySDR in that regards. SDRs tend to have two clock sources -- one is a systems clock, the other is for frequency accuracy/pacing -- yet SoapySDR only seems to support a single clock. There needs to be a way to define both a master clock and a reference clock. It's the reality of using SDRs in a professional setting, we all have/need those external references because 1 ppm just doesn't cut it. When you're doing MIMO, you want the samples to be coherent, so you also tie your master clocks together.

I think we're trying to fit this REF_IN/CLK_IN through an interface that does not support it properly.

SignalWhisperer commented 3 years ago

I've had a go at trying to improve the clocking API. See also https://github.com/JDRadio/SoapyBladeRF/commit/976abcc858f7ed06619f6916d0dc5445fe5053a6

guruofquality commented 3 years ago

From what I gather of the diagram and the schematics, REF_IN only feeds into the ADF chip, which seems to connect to the SYNC_IN of the RFIC, which is used to synchronize multiple clocks. The clock from CLK_IN replaces the VCTCXO as the system clock. So both could technically be used at the same time, with CLK_IN being the master clock and REF_IN being used to pace the DAC.

Sounds about right; this section of the FAQ is interesting https://www.nuand.com/frequently-asked-questions/#How_do_I_use_a_10_MHz_reference

But I'm just not seeing this two reference clock case. The external clock in replaces all of the VCTCXO with 38.4 MHz clock. And that should mean that anything that feeds the VCTCXO like the PLL and DAC are irrelevant.

I think these are pretty common use cases from what I have seen:

So I think that external clock support needs a little bit more supported in SoapyBladeRF than just the external clock selection. But I dont think I have yet seen a case for multiple reference clock frequencies. Usually between knowing the desired sample rate and the reference freq (whatever and wherever that may be) that dictates the rest for the driver. Maybe I should wait for someone interested in both SoapyBladeRF and external clock use case first. Hmmm...

SignalWhisperer commented 3 years ago

The external references are either 10 MHz GPSDO or PPS, at least in telecom and satcom (and if not, it's probably some pilot signal which has nothing to do with the SDR itself and is usually handled in software or sent to a PLL to act as a 10 MHz reference). We shouldn't have to specify the reference clock frequency (although we can specify the source between internal, 10 MHz, and PPS), but some libraries (libbladeRF for example) allow us to define it for some reason. The only clock that should be adjustable is the master clock. There should be possibility to set an external master clock for use in MIMO, and to set an external reference clock for frequency correction. So really, setting the reference clock frequency is not something that is part of commercial-grade SDRs, but is part of the bladeRF. This is extra functionality that is not that useful to most applications, but it adds flexibility.

I agree that we shouldn't have to set the reference clock frequency AND the master clock frequency (because we shouldn't have to set the reference clock frequency). We need to support setting the master clock frequency (although it's usually either fixed or automatic, it can be useful to manually set it to avoid aliasing), we need to support using either an internal or an external master clock, and we need to support using either an internal or an external reference clock. I think the proper solution is somewhere in-between the current API and the proposed API. What I was proposing was merely the general case that covers every possibility.

The bladeRF decided to support having a variable frequency for the external reference clock despite it not being a requirement of the industry as far as I know. It is not a commercial grade SDR for various reasons, and other hobby-grade SDRs have their own quirks like this which go either against the industry standards, or provide more flexibility than necessary. Should SoapySDR cover these edge cases? I honestly don't know. I think there should be a standard for what an SDR offers and how it offers it, but right now it's a war zone. Every manufacturer has their own way of doing things. I think SoapySDR should provide an interface to what the industry really needs, and the rest could be implemented through specific library calls (or extensions), say using that native driver handle we talked about recently.

This is just my opinion as a satcom engineer trying to use off-the-shelf SDRs for operations at the satellite ground segment. There are definitely use cases to which I am not exposed. I haven't used much of my personal SDRs for amateur radio due to lack of free time, but if anything, my ham radio requirements are far less strict than the ground segment requirements.