myriadrf / LimeSuite

Driver and GUI for LMS7002M-based SDR platforms
https://myriadrf.org/projects/lime-suite/
Apache License 2.0
470 stars 186 forks source link

Several problems with writeStream and readStreamStatus in SoapySDR support #125

Closed kb1vc closed 6 years ago

kb1vc commented 7 years ago

The test case for this issue can be found on github at

git@github.com:kb1vc/SoapySDR_Examples.git

The repo contains a CMakeLists.txt file and program source to create a test program called "WriteStreamTest"

Resolution of these issues would help make progress on the SoDaRadio effort to implement a HF/VHF/UHF transceiver with LimeSDR hardware.

WriteStreamTest illustrates some clear problems with transmit mode
in git commit aba07bf

    a) Note that when a 1kHz upper sideband tone is transmitted, there
       is a corresponding 3rd order product 3kHz below the nominal carrier.

       When a 2kHz upper sideband tone is transmitted, the 3rd order spur
       is 6kHz below the nominal carrier.

    b) At the end of a burst, if no further buffers are queued to the
       tx stream, the carrier will be transmitted with an amplitude
       corresponding to the magnitude of the last sample in the tx buffer.

    c) During a silent interval (all buffers queued have samples with
       magnitude 0) the beginning of the interval has a chirp that appears
       to be left over from the previous transmission.

    d) Despite the fact that the last buffer of each transmission is
       marked as an end-of-burst, the readStreamStatus does not detect
       the end of burst, and instead returns either TIME_ERROR or OVERFLOW
       for reasons that I cannot divine.

    e) Time does not move forward (that is, readings from getHardwareTime())
       unless an rx streamer has been created. This means that tx timeouts
       and read status timeouts don't work unless there is an rx stream.

    f) There appears to be no backpressure from calls to writeStream.  Perhaps
       this is the intent.  The comment in the Doxygen material is, for me,
       ambiguous.

The hardware configuration is: Device 0 Attr [addr] = [1d50:6108] Attr [driver] = [lime] Attr [label] = [LimeSDR-USB [USB 2.0] 9060B00461821] Attr [media] = [USB 2.0] Attr [module] = [STREAM] Attr [name] = [LimeSDR-USB] Attr [serial] = [0009060B00461821]

The DC offset and IQ balance settings were from a recent calibration that had test points within 5 kHz of the carrier. (That is, I did this: ./LimeSuiteCalibrate.py --freqStart 139.0e6 --freqStop 149.0e6 --freqStep 100e3 )

A picture of the 6kHz spur and the 2kHz upper sideband signal is included here. The nominal carrier is at 144.295 MHz. The tone is 1kHz above the carrier at 144.296. The spur is at 144.294. Note that carrier suppression is at least 25dB -- the coupling between the LimeSDR transmitter and the receiver that produced the spectrogram was very light to avoid intermod issues. Carrier suppression when the modulation envelope is 0 was a little disappointing, but the other issues are far more important.

6khz_spur

kb1vc commented 7 years ago

item D in the above report is the most important, from my point of view. This causes any application that relies on completing a burst to fail.

Also note that there appears to be a race between activateStream, deactivateStream, and writeStream that causes writes to fail if the stars aren't aligned properly.

I will furnish a test case for that, on request.

matt

kb1vc commented 7 years ago

I seem to be making progress on fixing the EndOfBuffer function. The root of the problem is that the feature is not implemented at all in the master branch up to commit 990ebebe5e.

I've added in detection and a sticky bit in the ILimeSDRStreamming Streamer object. The bit gets set in transmitPacketLoop when the marked buffer is sent to the FPGA. I want it to be cleared by the first WRITE to that stream. That would promote a pattern of

writeStream( data, END_BURST); loop: readStreamStatus(....) test for END_BURST; writeStream( new burst....)

I assume that is the behavior that was intended, based on the documentation.

Alternatively, the API could sprout a call that explicitly clears the END_OF_BURST state, or readStreamStatus could clear it. However, I have an aversion to things called "read" that have side effects, so opted for the more explicit path of triggering off Write.

At this point, I've got a problem where the ::Write method gets called by both WriteStream and ReceivePacketsLoop. Apparently, they are writing to the same Streamer object... sigh. I'll untangle that tomorrow night when I am less stuperous.

kb1vc commented 7 years ago

how did this get closed?

kb1vc commented 7 years ago

I have a fix for the EndOfBurst problem. It needs to be cleaned and prepared for merging. I'll do that tomorrow morning and send a pointer.

kb1vc commented 7 years ago

Anybody home?

Lots of experimentation and bringing in another receiver shows that the spurs located below the carrier are caused by an IP3 product in the test receiver. But the IP3 product is the result of the modulated (upper sideband) tone beating against the poorly suppressed carrier. Carrier suppression is a real issue here. I've turned on automatic DC correction, and calibrated the RX and TX. Is there something I should be doing to force IQ correction?

9600 commented 7 years ago

@IgnasJarusevicius could you review please.

IgnasJarusevicius commented 7 years ago

I recall Josh (@guruofquality) saying that he is simulating end of burst for bladerf using hardware timestamps and he would implement same for LimeSDR in SoapySDR layer. So I won't be merging this hack (simulation based on hardware timestamp sound like a better solution).

As for signal quality/calibration problems, please reproduce them using LimeSuiteGUI as its what people working with chip calibration/setting optimization are using. Then they can improve calibration algorithm or give suggestion of what chip settings should be changed to improve signal.

kb1vc commented 7 years ago

1 it is a really bad idea to call solutions offered by a customer "a hack" especially given your own rather sloppy and low quality code.

2 I reported bad behavior that was reproducible given your library. It isn't my job to do your research for you.

I'm done with lime for now. I'll wait until the code is up to a professional level.

Matt Reilly (Sent from my iPhone.)

On Jun 30, 2017, at 3:50 AM, IgnasJarusevicius notifications@github.com wrote:

I recall Josh (@guruofquality) saying that he is simulating end of burst for bladerf using hardware timestamps and he would implement same for LimeSDR in SoapySDR layer. So I won't be merging this hack (simulation based on hardware timestamp sound like a better solution).

As for signal quality/calibration problems, please reproduce them using LimeSuiteGUI as its what people working with chip calibration/setting optimization are using. Then they can improve calibration algorithm or give suggestion of what chip settings should be changed to improve signal.

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub, or mute the thread.