Raspberry Pi problem?

Add useful snippets of code or links to entire SDR projects.
jpsa
Posts: 23
Joined: Sun Nov 06, 2016 10:33 am

Raspberry Pi problem?

Post by jpsa » Fri Feb 10, 2017 6:15 pm

I've got some code, written against the SDRplay API, which searches for intermittent signals caused by reflections from the ionisation trails left by meteors. It does this by running an FFT over IQ samples and then searching the result for a spike caused by such a reflection. This seems to work nicely on my PC, and *nearly* works on a Raspberry Pi too.

In fact it works exactly the same as the PC for a while, but then apparently suffer from severe 'interference' for a while, before switching back to working again, and so on. Each state lasts for a variable period of typically an hour or two.

I do not believe this actually to be interference, though, because although it happens reliably on the RPi, if you wait long enough, I've never seen it on the PC.

Here's an image showing a transition from the 'interference' state back to working (time increases up the page at about 4 pixels/second, frequency to the right at about 2 Hz/pixel). It also shows a couple of real meteor signals.
1128.jpg
1128.jpg (230.31 KiB) Viewed 32303 times
.

In an attempt to isolate whether this is a bug in my code, I've tried writing out raw IQ samples to disk directly from the stream callback, and performing the analysis offline. The problem still appears in that mode, so I believe artefact to be present in the samples by the time I get my hands on them.

I'm passing

fsMHz=2.000
rfMHz=143.050
bwType=mir_sdr_BW_0_200
ifType=mir_sdr_IF_0_450

to mir_sdr_StreamInit()


Are there any known issues of this nature with the SDRplay API on Raspberry Pi?

Cheers,
John

Reason: No reason

jpsa
Posts: 23
Joined: Sun Nov 06, 2016 10:33 am

Re: Raspberry Pi problem?

Post by jpsa » Sat Feb 11, 2017 10:37 am

In fact the problem is visible directly in the IQ data passed to the stream callback...
iq.png
iq.png (72.64 KiB) Viewed 32279 times
Also suspicious is that the average spacing between noise bursts is 126 samples, which is exactly one quarter of the numSamples=504 samples passed to the stream callback.

This data was taken with no antenna plugged in, so I'm more convinced than ever that this is not real interference, but was generated internally to the RSP or SDRplay API somehow.

Reason: No reason

fventuri
Posts: 37
Joined: Sun Dec 25, 2016 4:24 pm

Re: Raspberry Pi problem?

Post by fventuri » Tue Feb 14, 2017 1:24 am

Can you try using a fs > 2.685MHz to see if that artifact goes away?

Franco
Last edited by fventuri on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

mikael
Posts: 18
Joined: Tue Dec 06, 2016 9:03 am

Re: Raspberry Pi problem?

Post by mikael » Tue Feb 14, 2017 6:20 am

That looks like HDMI interference to me.
Each state lasts for a variable period of typically an hour or two.
Does this happen to correlate with your screen saver? ;-)

Reason: No reason

jpsa
Posts: 23
Joined: Sun Nov 06, 2016 10:33 am

Re: Raspberry Pi problem?

Post by jpsa » Tue Feb 14, 2017 1:40 pm

mikael wrote:That looks like HDMI interference to me.
Each state lasts for a variable period of typically an hour or two.
Does this happen to correlate with your screen saver? ;-)
Thanks for the thought, but I'm pretty certain that's not it: the noise switches on and off in the middle of the night, it looks identical independent of whether an antenna is plugged in, and restarting the application reliably returns things to a no-noise state.

Cheers,
John

Reason: No reason

jpsa
Posts: 23
Joined: Sun Nov 06, 2016 10:33 am

Re: Raspberry Pi problem?

Post by jpsa » Tue Feb 14, 2017 1:56 pm

fventuri wrote:Can you try using a fs > 2.685MHz to see if that artifact goes away?

Franco
I'll try that... note, though, that I'm currently using a 450 kHz IF (see mir_sdr_StreamInit parameters listed in my original post, above), and this change will force me to switch to using an IF of zero, so presumably will change quite a lot of the internal processing in the SDRplay API.

What I have discovered is that the DC offset correction mode matters. I started with the calls

Code: Select all

mir_sdr_SetDcMode(4, 1);
mir_sdr_SetDcTrackTime(63);
taken directly from the sample code at the back of the API specification manual. If I change that first call to

Code: Select all

mir_sdr_SetDcMode(3, 1);
then the problem seems to go away -- I ran the application for 48 hours over the weekend without seeing the problem. So I guess I have a workround, if not a cure!

Cheers,
John

Reason: No reason

jpsa
Posts: 23
Joined: Sun Nov 06, 2016 10:33 am

Re: Raspberry Pi problem?

Post by jpsa » Sun Feb 19, 2017 9:53 am

OK, I've done some more experiments, all with an RSP1 and API version 2.09 running on a Raspberry Pi 3.

With an fs of any of 2.000, 2.400, 3.000; a decimation factor of 4; and an intermediate frequency of zero, the problem does not occur. I ran it for 24 hours each, which should have been plenty of time.

Reverting to my previous setting of fs=2.000, intermediate frequency=450 kHz (with an implied decimation of 4), the problem occurred seven times during the 24 hour run.

So I wrote a small test program to try to generate the issue...

Code: Select all

#include "mirsdrapi-rsp.h"
#include <assert.h>
#include <stdio.h>
#include <limits.h>
#include <unistd.h>

static long cbCount = 0;
static double em100 = 0;
static bool noisy = false;

static double emax (short *xi, short *xq, unsigned int numSamples)
{
	double em = 0;
	for (int j = 0; j < numSamples; ++j)
	{
		const double i = xi[j];
		const double q = xq[j];
		const double e = i*i + q*q;
		if (e > em) em = e;
	}
	return em;
}

static void s_callback (short *xi, short *xq, unsigned int firstSampleNum, int grChanged, int rfChanged, int fsChanged, unsigned int numSamples, unsigned int reset, void *cbContext)
{
	if (++cbCount <= 100)
	{

		// Use first 100 calls to find typical maximum signal level

		const double em = emax (xi, xq, numSamples);
		if (em > em100) em100 = em;
	}
	else
	{

		// Is this packet much noisier than normal?

		const double em = emax (xi, xq, numSamples);
		if ((cbCount % 10000) == 0)
		{
			printf ("*** Signal max power %.0f at callback %ld\n", (double) em, (long) cbCount);
			fflush (stdout);
		}
		const bool nn = em > 4 * em100;


		// Print message on transitions from normal->noisy and vice versa

		if (nn != noisy)
		{
			printf ("*** Noise state %d at callback %ld\n", (int) nn, (long) cbCount);
			fflush (stdout);
			noisy = nn;
		}
	}
}

static void s_callbackGC (unsigned int gRdB, unsigned int lnaGRdB, void *cbContext)
{
	mir_sdr_GainValuesT gv;
	const mir_sdr_ErrT err = mir_sdr_GetCurrentGain (&gv);
	assert (err == mir_sdr_Success);
}

int main (int, char**)
{
	mir_sdr_ErrT err; 

	float ver;
	err = mir_sdr_ApiVersion (&ver); 
	assert (err == mir_sdr_Success);
	assert (ver == MIR_SDR_API_VERSION);
	
	err = mir_sdr_DebugEnable (1);
	assert (err == mir_sdr_Success);

	err = mir_sdr_SetPpm (6.24);
	assert (err == mir_sdr_Success);

	err = mir_sdr_AgcControl (mir_sdr_AGC_DISABLE, 0, 0, 0, 0, 0, 0);
	assert (err == mir_sdr_Success);

	int newGr = 50;
	int sysGr = 0; 
	int samplePerPacket;

	err = mir_sdr_StreamInit (&newGr, 2.000, 143.050, mir_sdr_BW_0_200, mir_sdr_IF_0_450, 1, &sysGr, mir_sdr_USE_SET_GR_ALT_MODE, &samplePerPacket, s_callback, s_callbackGC, NULL);
	assert (err == mir_sdr_Success);

	err = mir_sdr_SetDcMode (4, 1); 
	assert (err == mir_sdr_Success);

	err = mir_sdr_SetDcTrackTime (63); 
	assert (err == mir_sdr_Success);

	mir_sdr_GainValuesT gv;
	err = mir_sdr_GetCurrentGain (&gv);
	assert (err == mir_sdr_Success);

	sleep (INT_MAX);
}
which produces some interesting output... in the normal (noise-free) state it writes messages like
*** Signal max power 3501 at callback 120000
*** Signal max power 2320 at callback 130000
*** Signal max power 2069 at callback 140000
*** Signal max power 3977 at callback 150000
*** Signal max power 1514 at callback 160000
but then it switches into the noisy state for a while with messages like
*** Signal max power 111454745 at callback 1760000
*** Signal max power 131692826 at callback 1770000
*** Signal max power 109825885 at callback 1780000
*** Signal max power 103865485 at callback 1790000
*** Signal max power 128117700 at callback 1800000
Perhaps significantly, the switch to a noisy state happens at the some time as the sdr API writes debug messages like
Warning: DriverCallback() transfer error 0x16e3208 0
No offset diff1=0x000001f8 diff2=0x000001f8
No offset samp1=0xc8efd0ba samp2=0xc8efd2b2 samp2=0xc8efd4aa
bufOffset=0
Gap=0x37182d32 e=0xc8eed2c2 a=0x6fff4
Gap=0xfffffe23 e=0x701ec a=0x7000f
Gap=0xfffbfdfc e=0x70207 a=0x30003
Gap=0x2fe0a e=0x301fb a=0x60005
Gap=0xafe07 e=0x601fd a=0x110004
Gap=0xfff9fe0a e=0x1101fc a=0xb0006
Gap=0xfffdfe0a e=0xb01fe a=0x90008
Gap=0xfff8fe09 e=0x90200 a=0x20009
Gap=0x3fe01 e=0x20201 a=0x60002
Gap=0xfe13 e=0x601fa a=0x7000d
Gap=0xfdfb e=0x70205 a=0x80000
Gap=0x2fe17 e=0x801f8 a=0xb000f
:
(and many, many similar lines)
:
Obviously I don't know what these messages mean, but the coincidence in timing seems certain to be significant!

One other oddity, which may or may not be significant: even when working noise-free, the sdr API writes messages like
238096: iDCoffset=1275.313558262 qDCoffset=0.000000000
mir_sdr_SetGrAltMode: in: 0 1 (1) 0 0 0
mir_sdr_SetGrAltMode: GR->50[50,0,0,0] gRset->0x32 DCCALmode=4 DCCALspd=1 GrToggle->1
mir_sdr_GetCurrentGainVal : hwVer=1 freq=143.05 bw=200 if=450, bbGr=50, lnaState=0, minGr=20, amPort1En=0, apiDownConvert=1
mir_sdr_GetCurrentGainVal : hwVer=1 freq=143.05 group=4 gainState=0, corr=-9.50, freq0=120.00 freq1=146.00 gain0=114.03 gain1=114.52: curr_no_b
b=104.96 max=84.96 min=3.28 curr=54.96
mir_sdr_SetGrAltMode: out: 50 1 50 0 0
mir_sdr_ReadPacket: Gain update confirmed: Gr=50dB GrToggle=1 gset=0x32
grChanged @ 238475
DCoffsetCorrection: switched to tracking mode diff=2 curr=830.26 last=832.58
every couple of minutes. These look as if they are something to do with DC correction, which surprised me because the code is running in DcMode=4 (one-shot), and my code does not perform any gain changes which might re-trigger the correction. In addition, I notice that the qDCoffset value printed in the first line of these sequences is always 0.000000000, which also seemed odd.

Hopefully this should be enough to allow you (SDRplay) to reproduce and track down the problem, but if you need any more information from me, please ask!

Cheers,
John

Reason: No reason

sdrplay
Posts: 978
Joined: Wed Jan 07, 2015 7:58 am

Re: Raspberry Pi problem?

Post by sdrplay » Tue Feb 21, 2017 9:20 am

Gaps in the stream normally mean that the samples aren't being processed quick enough - maybe you are maxing out a single core?

In one shot mode there is a regular update every minute or two for offset correction as you say. The reason the Q channel is 0.0 is because you are in Low-IF mode. Only the I channel is used and then that is down converted to produce IQ samples to the callback.

Best regards,

SDRplay Support

Reason: No reason

jpsa
Posts: 23
Joined: Sun Nov 06, 2016 10:33 am

Re: Raspberry Pi problem?

Post by jpsa » Tue Feb 21, 2017 10:16 am

I don't think maxing out the processor should be the problem, because the stream callback is doing very little in the cut-down example provided above: just calculating I*I+Q*Q for each sample. The processor is only running at about 35% according to 'top' (I believe this number to be relative to a single core, as I've seen figures consistently well over 100% here when running other code).

In addition, even if I strip everything out of the stream callback so the example code becomes

Code: Select all

#include "mirsdrapi-rsp.h"
#include <assert.h>
#include <stdio.h>
#include <limits.h>
#include <unistd.h>

static void s_callback (short *xi, short *xq, unsigned int firstSampleNum, int grChanged, int rfChanged, int fsChanged, unsigned int numSamples, unsigned int reset, void *cbContext)
{
}

static void s_callbackGC (unsigned int gRdB, unsigned int lnaGRdB, void *cbContext)
{
}

int main (int, char**)
{
        mir_sdr_ErrT err;

        float ver;
        err = mir_sdr_ApiVersion (&ver);
        assert (err == mir_sdr_Success);
        assert (ver == MIR_SDR_API_VERSION);

        err = mir_sdr_DebugEnable (1);
        assert (err == mir_sdr_Success);

        err = mir_sdr_SetPpm (6.24);
        assert (err == mir_sdr_Success);

        err = mir_sdr_AgcControl (mir_sdr_AGC_DISABLE, 0, 0, 0, 0, 0, 0);
        assert (err == mir_sdr_Success);

        int newGr = 50;
        int sysGr = 0;
        int samplePerPacket;

        err = mir_sdr_StreamInit (&newGr, 2.000, 143.050, mir_sdr_BW_0_200, mir_sdr_IF_0_450, 1, &sysGr, mir_sdr_USE_SET_GR_ALT_MODE, &samplePerPacket, s_callback, s_callbackGC, NULL);
        assert (err == mir_sdr_Success);

        err = mir_sdr_SetDcMode (4, 1);
        assert (err == mir_sdr_Success);

        err = mir_sdr_SetDcTrackTime (63);
        assert (err == mir_sdr_Success);

        mir_sdr_GainValuesT gv;
        err = mir_sdr_GetCurrentGain (&gv);
        assert (err == mir_sdr_Success);

        sleep (INT_MAX);
}
Then I still get
Warning: DriverCallback() transfer error 0x1521740 0
No offset diff1=0x0008000a diff2=0xfff50001
No offset samp1=0x0004fffd samp2=0x000d0007 samp2=0x00020008
Offset diff1=0x000001f8 diff2=0x000001f8
Offset samp1=0x56262332 samp2=0x5626252a samp2=0x56262722
bufOffset=512
Gap=0x2d678 e=0x5622fdfa a=0x5625d472
Warning: DriverCallback() transfer error 0x1521740 0
No offset diff1=0xfff20000 diff2=0x000dffff
No offset samp1=0x00060007 samp2=0xfff80007 samp2=0x00060006
Offset diff1=0x000001f8 diff2=0x000001f8
Offset samp1=0x5728d9ea samp2=0x5728dbe2 samp2=0x5728ddda
bufOffset=512
Gap=0xa8e33f95 e=0x5726c072 a=0xa0007
Gap=0xfffafe05 e=0xa01ff a=0x50004
Gap=0x3fe15 e=0x501fc a=0x90011
Gap=0xfffefe03 e=0x90209 a=0x8000c
Gap=0xfe02 e=0x80204 a=0x90006
Gap=0xafe0c e=0x901fe a=0x14000a
Gap=0xfff3fdff e=0x140202 a=0x80001
Gap=0xfffcfe0f e=0x801f9 a=0x50008
Gap=0x6fe08 e=0x50200 a=0xc0008
Gap=0x3fe0e e=0xc0200 a=0x10000e
Gap=0xffecfdf3 e=0x100206 a=0xfffcfff9
Gap=0x6fe15 e=0xfffd01f1 a=0x40006
Gap=0xfffefe03 e=0x401fe a=0x30001
Gap=0x1fe0e e=0x301f9 a=0x50007
Gap=0x1fe01 e=0x501ff a=0x70000
Gap=0xfffafe0c e=0x701f8 a=0x20004
Gap=0x9fe0c e=0x201fc a=0xc0008

(etc.)
after a while.

Does this happen for you, too, if you run this example code?

*

Thank you also for the explanation of the intermittent DC offset corrections: perhaps the API documentation could be corrected, as it says
one shot mode (correction applied each time gain update performed)
and does not mention that there's a periodic update in addition to this.

Cheers,
John

Reason: No reason

sdrplay
Posts: 978
Joined: Wed Jan 07, 2015 7:58 am

Re: Raspberry Pi problem?

Post by sdrplay » Tue Feb 21, 2017 11:18 am

How long is a while? Your simple test code has been running on my RPi3 for about 10 minutes without a problem.

Press '1' when running top to see the individual core load. On my system your test app takes 50% on one core.

How are you building your app? I'm using this simple Makefile...

Code: Select all

EXE = example

RM = /bin/rm -f
MV = /bin/mv -f
MKDIR = /bin/mkdir -p

CC = gcc -g
LD = gcc -g
LN = ln

CFLAGS = -O3 -fPIC -Wall

INCS = -I/usr/local/include

LINKFLAGS =

LIB_OBJS = example.o

all: $(EXE)

$(EXE): $(LIB_OBJS)
        @$(LD) $(LINKFLAGS) -o $(EXE) $(LIB_OBJS) -lpthread -lc -lm -ldl -lmirsd
rapi-rsp

%.o: %.c
        @echo "Compiling" $<
        @$(CC) $(CFLAGS) $(INCS) -c $<

clean:
        @echo "Remove all object files"
        @$(RM) $(LIB_OBJS) $(EXE) *.h~ *.c~ Makefile~
Your test code is still running fine here. Not sure what to suggest unless you can give me something that breaks repeatably in a short time?

Best regards,

SDRplay Support

Reason: No reason

Post Reply