Strange TX burst before intended transmission - LimeSDR-mini

LimeSDR-mini Background


I am a new Lime user, but have been using Ettus products for quite some time. I received my mini about a week ago and have been running various tests to vet its performance against some other SDRs I am working with. I followed the instructions here: https://wiki.myriadrf.org/Gr-limesdr_Plugin_for_GNURadio to get the mini working inside GnuRadio. I am running on a Centos7 VM with plenty of cores/RAM to handle almost anything. LimeQuickTest passes all of its checks. Below is the output.

$ LimeQuickTest 
[ TESTING STARTED ]
->Start time: Fri Oct 12 13:04:03 2018

->Device: LimeSDR Mini, media=USB 3.0, module=FT601, addr=24607:1027, serial=1D423D09745279
  Serial Number: 1D423D09745279

[ Clock Network Test ]
->REF clock test
  Test results: 46421; 59618; 7279 - PASSED
->VCTCXO test
  Results : 6711028 (min); 6711184 (max) - PASSED
->Clock Network Test PASSED

[ FPGA EEPROM Test ]
->Read EEPROM
->Read data: 12 07 19 12 07 19 02
->FPGA EEPROM Test PASSED

[ LMS7002M Test ]
->Perform Registers Test
->External Reset line test
  Reg 0x20: Write value 0xFFFD, Read value 0xFFFD
  Reg 0x20: value after reset 0x0FFFF
->LMS7002M Test PASSED

[ RF Loopback Test ]
->Configure LMS
->Run Tests (TX_2 -> LNA_W):
  CH0 (SXR=1000.0MHz, SXT=1005.0MHz): Result:(-13.4 dBFS, 5.00 MHz) - PASSED
->Run Tests (TX_1 -> LNA_H):
  CH0 (SXR=2100.0MHz, SXT=2105.0MHz): Result:(-13.5 dBFS, 5.00 MHz) - PASSED
->RF Loopback Test PASSED

=> Board tests PASSED <=

Elapsed time: 2.84 seconds

The Problem

The problem I have seems to occur at the beginning of every transmit. I am transmitting from the mini into an Ettus B200 (and multiple other USRPs, including an N200 and an X300). I have tried to transmit different ways, but the result is still the same; I get a strange ‘initialization’ (or so I am calling it) transmission prior to my actual desired transmission. I have tried transmitting a custom flowgraph, an example flowgraph, and simply from Python. Everytime I transmit I get some sort of multi-second, high power transmission prior to the real transmission. I have included screenshots of a few cases, plus screenshots of the FM_transmitter.grc example that ships with the gr-limesdr OOT, and the Python code I used to bypass GnuRadio to eliminate that variable


FM_transmitter.grc


Python siggen code example

########################################################################
## Simple signal generator for testing transmit
########################################################################

import SoapySDR
from SoapySDR import * #SOAPY_SDR_ constants
import numpy as np
from optparse import OptionParser
import time
import os
import math

def siggen_app(
    args,
    rate,
    ampl=0.7,
    freq=None,
    txBw=None,
    txChan=0,
    rxChan=0,
    txGain=None,
    txAnt=None,
    clockRate=None,
    waveFreq=None
):
    if waveFreq is None: waveFreq = rate/10

    sdr = SoapySDR.Device(args)
    #set clock rate first
    if clockRate is not None: sdr.setMasterClockRate(clockRate)

    #set sample rate
    sdr.setSampleRate(SOAPY_SDR_TX, txChan, rate)
    print("Actual Tx Rate %f Msps"%(sdr.getSampleRate(SOAPY_SDR_TX, txChan)/1e6))

    #set bandwidth
    if txBw is not None: sdr.setBandwidth(SOAPY_SDR_TX, txChan, txBw)

    #set antenna
    print("Set the antenna")
    if txAnt is not None: sdr.setAntenna(SOAPY_SDR_TX, txChan, txAnt)

    #set overall gain
    print("Set the gain")
    if txGain is not None: sdr.setGain(SOAPY_SDR_TX, txChan, txGain)

    #tune frontends
    print("Tune the frontend")
    if freq is not None: sdr.setFrequency(SOAPY_SDR_TX, txChan, freq)

    #tx loop
    #create tx stream
    print("Create Tx stream")
    txStream = sdr.setupStream(SOAPY_SDR_TX, "CF32", [txChan])
    print("Activate Tx Stream")
    sdr.activateStream(txStream)
    phaseAcc = 0
    phaseInc = 2*math.pi*waveFreq/rate
    streamMTU = sdr.getStreamMTU(txStream)
    sampsCh0 = np.array([ampl]*streamMTU, np.complex64)
    
    timeLastPrint = time.time()
    totalSamps = 0
    while True:
        phaseAccNext = phaseAcc + streamMTU*phaseInc
        sampsCh0 = ampl*np.exp(1j*np.linspace(phaseAcc, phaseAccNext, streamMTU)).astype(np.complex64)
        phaseAcc = phaseAccNext
        while phaseAcc > math.pi*2: phaseAcc -= math.pi*2

        sr = sdr.writeStream(txStream, [sampsCh0], sampsCh0.size, timeoutUs=1000000)
        if sr.ret != sampsCh0.size:
            raise Exception("Expected writeStream() to consume all samples! %d"%sr.ret)
        totalSamps += sr.ret

        if time.time() > timeLastPrint + 5.0:
            print("Python siggen rate: %f Msps"%(totalSamps/(time.time()-timeLastPrint)/1e6))
            totalSamps = 0
            timeLastPrint = time.time()

    #cleanup streams
    print("Cleanup stream")
    sdr.deactivateStream(txStream)
    sdr.closeStream(txStream)
    print("Done!")

def main():
    parser = OptionParser()
    parser.add_option("--args", type="string", dest="args", help="device factor arguments", default="")
    parser.add_option("--rate", type="float", dest="rate", help="Tx and Rx sample rate", default=1e6)
    parser.add_option("--ampl", type="float", dest="ampl", help="Tx digital amplitude rate", default=0.7)
    parser.add_option("--txAnt", type="string", dest="txAnt", help="Optional Tx antenna", default=None)
    parser.add_option("--txGain", type="float", dest="txGain", help="Optional Tx gain (dB)", default=None)
    parser.add_option("--txChan", type="int", dest="txChan", help="Transmitter channel (def=0)", default=0)
    parser.add_option("--freq", type="float", dest="freq", help="Optional Tx and Rx freq (Hz)", default=None)
    parser.add_option("--txBw", type="float", dest="txBw", help="Optional Tx filter bw (Hz)", default=None)
    parser.add_option("--waveFreq", type="float", dest="waveFreq", help="Baseband waveform freq (Hz)", default=None)
    parser.add_option("--clockRate", type="float", dest="clockRate", help="Optional clock rate (Hz)", default=None)
    (options, args) = parser.parse_args()
    siggen_app(
        args=options.args,
        rate=options.rate,
        ampl=options.ampl,
        freq=options.freq,
        txBw=options.txBw,
        txAnt=options.txAnt,
        txGain=options.txGain,
        txChan=options.txChan,
        clockRate=options.clockRate,
        waveFreq=options.waveFreq,
    )

if __name__ == '__main__': main()

Python siggen recieve (large DC centered tone is the ‘init’, real tone is offset)


FM_transmitter Recieved (notice the band before the actual FM tone)


Custom Burst (large tone/init occurs before actual burst which is offtuned)


Questions

  1. Is this something else that people have seen?
  2. Is this normal? If so, what is it and why is it necessary?
  3. Is there anything (different firmware, etc.) that can be used to correct it?

I have also observed similar behavior.

Thanks yindra. Do you have any idea what it is or why it is there?

I assumed it was the transient response time (“settling” period) for the analog filter in the LimeSDR, and didn’t think too much about it.

It may be due to the slow interface:

Try if it gets better by using cacheCalibrations:

args = dict(driver='lime', cacheCalibrations='1')
self.sdr_device = SoapySDR.Device(args)

Thanks for sharing gasparka! I just barely got around to trying your code snippet. Unfortunately it doesn’t appear to do anything at all to the ‘transient’ before my actual transmission. It is the same duration and power as before. If you can think of anything else, feel free to comment more! I am hoping I can get to the bottom of this. I would prefer to transmit no energy over RF except for my actual transmission.

Looks like a bug, made an issue:

Hopefully it gets some attention.

Thanks! I hope it does too!

Anyone else have any ideas/input on this? If I cannot get this large ‘init’ transmission to go away, this will be a non-starter for using the lime on any projects.

Wondering if this is calibration related, looks like things normalize after the DC goes down i.e. calibration finishes.
Could it be fixed by keeping the TX disabled during calibration?
Pinging @IgnasJ for ideas.

I would agree that it appears to happen during the calibration stage. If it is possible to disable TX during calibration (not sure why you would want to actually push stuff out over RF during calibration), but I think that would solve my problem.

Well, this is just a theory. Might be that the TX is already disabled and something else is causing this. Hopefully we get some input from the Lime guys.

Thanks again gasparka for all your help! At this point I think I am going to put my Lime’s on a shelf as they are little use to me if they have a giant 5 second tone before every burst. I am slightly disappointed that none of the Lime people have chimed in, but from my past experience with other vendors, the silence usually means you found an actual problem. Hopefully this will someday get resolved, but for now it is back to Ettus. Thanks again!

Hi @scott,

Our guess is that you see calibration output. It is easy to check - just set Calibration: OFF in TX Sink block and check if you get the same behavior as before. This will prove if this is calibration procedure output.

Hi Zack, thanks for the reply. I just tested again with Calibration:OFF and Calibration:ON, but there was no difference (I tired both my custom flowgraph and the FM_trasmitter example provided by Lime). The unwanted/unexplained pre-transmission tone is still present. Another observation is that the unwanted tone appears during the LIme’s “device_handler::set_analog_filter()”

Hi @scott,

OK, could you then make one more experiment for me - try to disable analog filter by setting “Analog filter” option to OFF.

Yep. Just tried multiple flowgraphs (including the FM_transmitter example provided in gr-limesdr) and toggling the analog filter ON/OFF didn’t change anything. There is still a long and large tone transmitted prior to the actual desired transmission.

Below is the console output for the FM_transmitter flowgraph. The tone is transmitted between the set_analog_filter (which is disabled now) and the Filter calibrated (Calibration is also off).

INFO: device_handler::set_chip_mode(): SISO mode set for device number 0.
INFO: device_handler::set_rf_freq(): RF frequency set [TX]: 312.2 MHz.
INFO: device_handler::set_samp_rate(): set sampling rate: 2 MS/s.
INFO: device_handler::set_analog_filter(): analog filter channel 0 [TX]: disabled (maximum value set).
Filter calibrated. Filter order-2nd, set to 130 MHz
TX LPF configured
INFO: device_handler::set_digital_filter(): digital filter channel 0 [TX]: 0.1 MHz.
INFO: device_handler::set_antenna(): channel 0 antenna set [TX]: BAND1.
INFO: device_handler::set_gain(): set gain [TX]: 30 dB.
INFO: device_handler::calibrate(): calibration channel 0 [TX]: disabled.
INFO: sink_impl::init_stream(): sink channel 0 (device nr. 0) stream setup done.

image

Thanks!

I am looking at the same thing with my LimeSDR Mini, also tried the steps recommended here to no effect.

Does this happen on every device, or are we the lucky ones? Is there a way to avoid that pre-transmission burst?

I am not sure. I have two LimeSDR Minis that both do it. I also have an XTRX board that is exhibiting similar symptoms. My new theory is that is is not necessarily the hardware, but the driver (soapy). When running examples with the XTRX that do not use soapy, I get no such pre-transmission tone. Whenever I attempt to use soapy however, I get a tone between the period when soapy is initializing everything and samples actually begin to transmit. Below is a screenshot of the XTRX. You can see the actual burst…and a tone (looks like the carrier) that gets transmitted for nearly 10 seconds prior and during the actual transmission. Would love to get these issues resolved as a lot of this hardware is very promising for different purposes…but for now the only stuff that works fairly well out of the box is Ettus/Epiq (which obviously have more mature products/software). Let me know if you make any progress!

But you also tested with gr-limesdr and had similar results? gr-limesdr is not using Soapy, as far as i know…