Change LimeSDR Clock Source using SoapyLMS7

#1

Hello,

I am currently developing a phased array system using two LimeSDR-USB boards. For this, I need to enable one of the two boards to run off of an external clock supplied by the other board. I know it is possible to do this using the LimeSuite GUI from this discussion. Unfortunately, because I am making this for more users than just myself. I do not want the other people using the system to accidentally break something (requiring me to constantly fix it) while trying to load a config file (the normal work around) or running a command line application (like here).

It would be best if the SoapyLMS7 interface had a way to enable the external reference clock. I think I have found a quick work around for this, and I would like to see what everyone on the forum thinks.

From this discussion post and from this code from the myriadrf/LimeSuite/src/API/lms7_device.cpp github repo:

int LMS7_Device::SetClockFreq(unsigned clk_id, double freq, int channel)
{
    lms_chip_id = channel == -1 ? lms_chip_id : channel/2;
    lime::LMS7002M* lms = lms_list[lms_chip_id];
    switch (clk_id)
    {
    case LMS_CLOCK_REF:
        if (freq <= 0)
        {
            lime::ReportError(EINVAL, "Invalid frequency value.");
            return -1;
        }
        lms->SetReferenceClk_SX(lime::LMS7002M::Tx, freq);
        return 0;
    case LMS_CLOCK_SXR:
        if (freq <= 0)
            return lms->TuneVCO(lime::LMS7002M::VCO_SXR);
        if (channel != -1)
        {
            rx_channels[channel].cF_offset_nco = 0.0;
            rx_channels[channel].freq = freq;
        }
        return lms->SetFrequencySX(false, freq);
    case LMS_CLOCK_SXT:
        if (freq <= 0)
            return lms->TuneVCO(lime::LMS7002M::VCO_SXT);
        if (channel != -1)
        {
            tx_channels[channel].cF_offset_nco = 0.0;
            tx_channels[channel].freq = freq;
        }
        return lms->SetFrequencySX(true, freq);
    case LMS_CLOCK_CGEN:
    {
        int ret =0;
        lms->Modify_SPI_Reg_bits(LMS7param(MAC),1);
        if (freq <= 0)
        {
            ret = lms->TuneVCO(lime::LMS7002M::VCO_CGEN);
        }
        else
        {
            ret = lms->SetInterfaceFrequency(freq, lms->Get_SPI_Reg_bits(LMS7param(HBI_OVR_TXTSP)), lms->Get_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP)));
        }
        if (ret != 0)
            return -1;
        return SetFPGAInterfaceFreq();
    }
    case LMS_CLOCK_RXTSP:
        lime::ReportError(ENOTSUP, "Setting TSP clocks is not supported.");
        return -1;
    case LMS_CLOCK_TXTSP:
        lime::ReportError(ENOTSUP, "Setting TSP clocks is not supported.");
        return -1;
    case LMS_CLOCK_EXTREF:
        {
            if (freq <= 0)
            {
                lime::info("Disabling external reference clock");
                double val;
                uint8_t id = 0;
                connection->CustomParameterRead(&id, &val, 1, nullptr);
                connection->CustomParameterWrite(&id, &val, 1, "");
                return 0;
            }

            lime::ADF4002 module;
            module.SetDefaults();
            double fvco = lms->GetReferenceClk_SX(lime::LMS7002M::Rx);
            int dummy;
            module.SetFrefFvco(freq/1e6, fvco/1e6, dummy, dummy);
            unsigned char data[12];
            module.GetConfig(data);

            std::vector<uint32_t> dataWr;
            for(int i=0; i<12; i+=3)
                dataWr.push_back((uint32_t)data[i] << 16 | (uint32_t)data[i+1] << 8 | data[i+2]);
            return connection->TransactSPI(0x30, dataWr.data(), nullptr, 4);
        }
    default:
        lime::ReportError(EINVAL, "Invalid clock ID.");
        return -1;
    }
}

It appears that by passing LMS_CLOCK_EXTREF into the LMS7_Device::SetClockFreq method sets up the ADF4002 module to accept an external clock of variable frequency. I am going to test this out and implement the setClockSource() Soapy API to see if this will work for what I am trying to do.

Is anyone interested in this feature being added to the official SoapyLMS7? Does someone have a better idea on how to do it?

Thanks,
Jayden Booth

#2

@IgnasJ is there anything you would suggest here?