SDRplay, Linrad, and MAP65 for EME on 1296

327 views
Skip to first unread message

Joe Taylor

unread,
Oct 26, 2022, 12:41:32 PM10/26/22
to Linrad
Hi all,

The message appended below was posted earlier today to the "Moon-Net"
reflector. For the interest of Linrad users who do not subscribe to
Moon-Net, I'm also posting it here. As mentioned near the message's
end, we'll be very interested in communicating with others who are doing
anything similar with SDRplay hardware and Linrad.

-- 73, Joe, K1JT

###########################################################################
Hello EME Friends,

Yesterday we upgraded the 1296 EME setup at club station W2ZQ to include
wideband receiving and Q65 decoding using Linrad and MAP65. For the
possible interest of others, I'll give a brief description of our
present setup and what it does.

Our LNA and 250 W SSPA are located at the 3m dish. We're now using the
following chain of hardware and software components in the shack:

CWtype/paddles
|
v
IC-9700 -> PTRX -> RSPduo -> Linrad -> MAP65
^ |
| |
v V
WSJT-X headphones

(In case this diagram displays poorly in you email reader, an equivalent
.txt file is attached.)

Our Icom IC-9700 is outfitted with the Leo-Bodnar board for GPS locking
and the PTRX-9700 to provide wideband IF at 367 MHz. The PTRX sends the
IF signal to an RSPduo controlled by the Linrad-5.01 version built by
Franco Venturi, K4VZ:

https://github.com/fventuri/linrad

Franco's Linrad build has excellent plug-and-play support for the
SDRplay v3.11 API.

Linrad sends I/Q data in timf2 format to MAP65. The Linrad wide
waterfall is configured to display a 90 kHz sub-band, 1296.000 to
1296.090, and its high-resolution graph provides a zoomed-in display 3
kHz wide at the selected Rx frequency. MAP65's "Wide Graph" waterfall
displays the same 90 kHz sub-band, also with an accompanying zoomed-in
display, and the program decodes all Q65-60C activity found in the 90
kHz range. When interested mainly in Q65 QSOs, we move the displayed
range up to something more like 1296.040 - 1296.130.

For Q65 QSOs we activate WSJT-X to take care of Doppler control,
transmitting, and narrow-band reception of our QSO partner. For CW QSOs
we activate CWtype and terminate WSJT-X.

We find that this setup provides an extremely capable receiving system
for 1296 EME in both CW and Q65, with high-sensitivity waterfalls
showing all CW and Q65 activity in a 90 kHz wide EME sub-band. MAP65
decodes all Q65-60C signals in the displayed range, WSJT-X conducts Q65
QSOs, and a simple mouse-click sends any visible CW signal to the
headphones for CW QSOs.

We'll be very interested in communicating with others who are doing
something similar to what's described here. If we haven't already
worked you in the ARRL EME contest, please look for us in either CW or
Q65 during the November 12-13 weekend!

One further comment, for possible future discussion. MAP65 v3.0
currently supports only the 60-second submodes of Q65. Our experience
is that most 1296 EME stations (say, 2m dish or larger) can work each
other easily using Q65-30B -- an obvious potential advantage of twice
the QSO rate in EME contests. Would it be useful to agree on some
sub-band, perhaps 1296.100 to 1296.150, for Q65-30B activity? MAP65
might then be upgraded accordingly, to handle 30-second sequencing.

With best wishes,

-- 73, Joe, K1JT
w2zq_setup.txt

Simon Brown

unread,
Dec 31, 2022, 2:00:01 AM12/31/22
to Linrad
Hi,

I'm looking for documentation for the UDP IQ interface used here. I've looked through MAP65 and LINRAD sources but not found anything I understand.

Pointers are most welcome.

Franco Venturi

unread,
Dec 31, 2022, 11:36:49 AM12/31/22
to Linrad
Simon,
reading though Leif's notes on 'MAP65 With Linrad' (http://sm5bsz.com/lir/map65/map65.htm), it looks like Linrad is using the 16 bit TIMF2 format.

I think the Linrad function that is used to send out this format is 'lir_send_timf2' (https://github.com/fventuri/linrad/blob/main/network.c#L390-L395), which uses the structure 'net_rxdata_timf2', whose type is 'NET_RX_STRUCT' (https://github.com/fventuri/linrad/blob/main/globdef.h#L1213-L1223).

That code to populate that structure is in the source file 'rxin.c' - for the 16 bit timf2 format I believe the relevant code is here: https://github.com/fventuri/linrad/blob/main/rxin.c#L918-L942 and here: https://github.com/fventuri/linrad/blob/main/rxin.c#L971-L994

Also be aware that MAP65 only accepts a very limited set of sample rates as input (I think only 48ksps and 96ksps, but I am not 100% sure), so you may need to do some resampling if your sample rates are different (I don't think Linrad can do it for the I/Q stream).

Best of luck and I'll be happy to help if you have any questions.

Franco K4VZ

Simon Brown

unread,
Dec 31, 2022, 11:47:30 AM12/31/22
to Linrad
Thanks,

That's a good start. Ideally the SDR software could send 32-bit complex floats, but backward compatibility is required here.

Roger Rehr

unread,
Dec 31, 2022, 11:54:26 AM12/31/22
to lin...@googlegroups.com

I haven't messed around with this for nearly a decade, so my info is dated, and I can't add to what is in some old notes that I posted on a related topic long ago.

What you want may be contained in this page:
https://w3sz.com/LinradMAP65.htm

Others who have used this system more recently than I have queried me on this topic as recently as this season, so I know that there are others out there who can offer you more recent experiences than I can.

If the above link is not germane, then I apologize for wasting bandwidth.

73,

Roger

W3SZ

--
There is an excellent Linrad User Guide by Gaetan, ON4KHG, at:
http://w3sz.com/Linrad%20Installation%20&%20Configuration%20User%20Guide%20-%20V1-0.pdf
---
You received this message because you are subscribed to the Google Groups "Linrad" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linrad+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/linrad/a0c04b22-4163-45da-9df2-a814956df005n%40googlegroups.com.

Simon Brown

unread,
Jan 1, 2023, 1:24:44 AM1/1/23
to Linrad
Franco,

I looked at this code and have given up. The header I understand, but the IQ buffer I just don't. What I need to know is:
  • Valid sample rates,
  • Formation of the IQ buffer.
If the interface is properly documented then other SDR programs such as SDR#, SDR Uno etc. would be able to offer support to the WSJT programs.
On Saturday, 31 December 2022 at 16:36:49 UTC fven...@comcast.net wrote:

Joe Taylor

unread,
Jan 1, 2023, 9:40:52 AM1/1/23
to lin...@googlegroups.com
Hi Simon,

It might help to have an overview of what you're trying to do, and why.

MAP65 was written fifteen years ago, mainly for my own use. Today it's
being maintained, sort of, but not particularly enhanced.

MAP65 accepts the "timf2" format of I/Q data from Linrad at a fixed
sample rate, 96000 frames per second. Data can be either 16-bit
integers or 32-bit floats. A "frame" is either two samples (I and Q for
one polarization) or four samples (I qnd Q for two orthogonal
polarizations).

[Because of early popularity of the SDR-IQ receiver from RF Space, I
also made it possible to use a sample rate it can produce, approximately
95238.1 Hz. Such data are resampled in MAP65 as needed.]

Linrad sends its "timf2" data in UDP packets. Each packet has a header,
which you say you understand, followed by a data block. Details of the
data block can have one of four forms:

- One RF channel, 16-bit integer data
- One RF channel, 32-bit float data
- Two RF channels, 16-bit integer data
- Two RF channels, 32-bit float data

Somewhat oddly, the basic Linrad timf2 packet size has 87 frames. I
don't know why. Perhaps you can understand the way MAP65 unpacks the
data from one of the arrays buf4, buf8, or buf16 and stuffs them into
array dd(), in the attached Fortran subroutine.

-- 73, Joe, K1JT

On 1/1/2023 1:24 AM, Simon Brown wrote:
> Franco,
>
> I looked at this code and have given up. The header I understand, but
> the IQ buffer I just don't. What I need to know is:
>
> * Valid sample rates,
> * Formation of the IQ buffer.
>
> If the interface is properly documented then other SDR programs such as
> SDR#, SDR Uno etc. would be able to offer support to the WSJT programs.
>
> Simon Brown
> https://g4eli.com <https://g4eli.com/>
> https://sdr-radio.com <https://sdr-radio.com/>
>
> On Saturday, 31 December 2022 at 16:36:49 UTC fven...@comcast.net wrote:
>
> Simon,
> reading though Leif's notes on 'MAP65 With Linrad'
> (http://sm5bsz.com/lir/map65/map65.htm
> <http://sm5bsz.com/lir/map65/map65.htm>), it looks like Linrad is
> using the 16 bit TIMF2 format.
>
> I think the Linrad function that is used to send out this format is
> 'lir_send_timf2'
> (https://github.com/fventuri/linrad/blob/main/network.c#L390-L395
> <https://github.com/fventuri/linrad/blob/main/network.c#L390-L395>),
> which uses the structure 'net_rxdata_timf2', whose type is
> 'NET_RX_STRUCT'
> (https://github.com/fventuri/linrad/blob/main/globdef.h#L1213-L1223
> <https://github.com/fventuri/linrad/blob/main/globdef.h#L1213-L1223>).
>
> That code to populate that structure is in the source file 'rxin.c'
> - for the 16 bit timf2 format I believe the relevant code is here:
> https://github.com/fventuri/linrad/blob/main/rxin.c#L918-L942
> <https://github.com/fventuri/linrad/blob/main/rxin.c#L918-L942> and
> here: https://github.com/fventuri/linrad/blob/main/rxin.c#L971-L994
> <https://github.com/fventuri/linrad/blob/main/rxin.c#L971-L994>
>
> Also be aware that MAP65 only accepts a very limited set of sample
> rates as input (I think only 48ksps and 96ksps, but I am not 100%
> sure), so you may need to do some resampling if your sample rates
> are different (I don't think Linrad can do it for the I/Q stream).
>
> Best of luck and I'll be happy to help if you have any questions.
>
> Franco K4VZ
>
>
>
> On Saturday, December 31, 2022 at 2:00:01 AM UTC-5
> simon...@gmail.com wrote:
>
> Hi,
>
> I'm looking for documentation for the UDP IQ interface used
> here. I've looked through MAP65 and LINRAD sources but not found
> anything I understand.
>
> Pointers are most welcome.
>
> Simon Brown
> https://g4eli.com <https://g4eli.com/>
> https://sdr-radio.com <https://sdr-radio.com/>
> --
> There is an excellent Linrad User Guide by Gaetan, ON4KHG, at:
> http://w3sz.com/Linrad%20Installation%20&%20Configuration%20User%20Guide%20-%20V1-0.pdf <http://w3sz.com/Linrad%20Installation%20&%20Configuration%20User%20Guide%20-%20V1-0.pdf>
> ---
> You received this message because you are subscribed to the Google
> Groups "Linrad" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to linrad+un...@googlegroups.com
> <mailto:linrad+un...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/linrad/4e4f8f5d-30bc-44df-aba2-02913531133cn%40googlegroups.com <https://groups.google.com/d/msgid/linrad/4e4f8f5d-30bc-44df-aba2-02913531133cn%40googlegroups.com?utm_medium=email&utm_source=footer>.
recvpkt.f90

Leif Asbrink

unread,
Jan 1, 2023, 1:18:13 PM1/1/23
to lin...@googlegroups.com
Simon,

Linrad and MAP65 can use 16 bit integers or 32 bit floats for timf2.
The variable swfloat = TRUE means that timf2 is a 32 bit float.

I wrote the code for a Pentium MMX. Using 16 bit integers with the
SIMD instructions made it possible to implement the smart blanker.
Today I think there is no need for 16 bit format any more. Setup
is simpler with the float format since truncation noise is no issue then.


Fill header:
net_rxdata_timf2.time=rx_read_time; // milliseconds since midnight
net_rxdata_timf2.passband_center=rx_passband_center_mhz;
net_rxdata_timf2.passband_direction=-1;
// Set userx_freq to sampling speed.
// speed originally had to be 96000.
// It can also be 960605 for SDR-14 or SDR-IQ (clock=66.6666 MHz)
// Joe can answer what rates will be acceptable for MAP65
net_rxdata_timf2.userx_freq=timf1_sampling_speed;
// set mm to the number of blocks we want to transfer this time.
mm=((timf2_pn2-timf2_pt+timf2_size)&timf2_mask);
if(mm>(timf2_neg))mm=0;
// mm now number of valid bytes
j=snd[RXAD].block_bytes;
if( (ui.rx_input_mode&DWORD_INPUT) != 0)j/=2;
if( mm <= j/2)
{
mm=0;
}
else
{
if( mm > 1.25*j)
{
mm=1.25*j;
}
}
j=0;
//*****************************************************
if(swfloat) //If your data is in 32 bit float format
{
// Set userx_no to the number of receiver RF channels with
// the sign negative to indicate float format.
net_rxdata_timf2.userx_no=-ui.rx_rf_channels;
mm*=2;
while(j < mm) // fill mm blocks with data for one point of all channels
{
za=(float*)&net_rxdata_timf2.buf[netsend_ptr_timf2]; //buffer
zb=&timf2_float[timf2_pt]; //source of data
for(nn=0; nn<twice_rxchan; nn++) //I and Q for one or two channels
{
za[nn]=hg_map65_gain*(zb[nn]+hg.map65_strong*zb[twice_rxchan+nn]);
}
netsend_ptr_timf2+=twice_rxchan*sizeof(float); //increment pointers
j+=twice_rxchan*sizeof(float); //increment block counter by no of bytes
timf2_pt=(timf2_pt+2*twice_rxchan)&timf2_mask; //increment pointers
// check whether a network buffer is full and send it away in case it is
if(netsend_ptr_timf2 >= NET_MULTICAST_PAYLOAD)
{
nettimf2_blknum++;
net_rxdata_timf2.block_no=nettimf2_blknum;
net_rxdata_timf2.ptr=(2*timf2_pt)&(snd[RXAD].block_bytes-1);
lir_send_timf2();
netsend_ptr_timf2=0;
}
}
//**************************************************************
else
{
// Set userx_no to the number of receiver RF channels.
// a positive number means 16 bit integer data.
// the same logcs as above.
net_rxdata_timf2.userx_no=ui.rx_rf_channels;
while(j < mm)
{
ya=(short int*)(&net_rxdata_timf2.buf[netsend_ptr_timf2]);
yb=(short int*)(&timf2_shi[timf2_pt]);
for(nn=0; nn<twice_rxchan; nn++)
{
ya[nn]=hg_map65_gain*(yb[nn]+hg.map65_strong*yb[twice_rxchan+nn]);
}
netsend_ptr_timf2+=twice_rxchan*sizeof(short int);
j+=twice_rxchan*sizeof(short int);
timf2_pt=(timf2_pt+2*twice_rxchan)&timf2_mask;
if(netsend_ptr_timf2 >= NET_MULTICAST_PAYLOAD)
{
nettimf2_blknum++;
net_rxdata_timf2.block_no=nettimf2_blknum;
net_rxdata_timf2.ptr=timf2_pt&(snd[RXAD].block_bytes-1);
lir_send_timf2();
netsend_ptr_timf2=0;
}
}

I hope this helps

73

Leif








> Franco,
>
> I looked at this code and have given up. The header I understand, but the
> IQ buffer I just don't. What I need to know is:
>
> - Valid sample rates,
> - Formation of the IQ buffer.
> --
> There is an excellent Linrad User Guide by Gaetan, ON4KHG, at:
> http://w3sz.com/Linrad%20Installation%20&%20Configuration%20User%20Guide%20-%20V1-0.pdf
> ---
> You received this message because you are subscribed to the Google Groups "Linrad" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linrad+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/linrad/4e4f8f5d-30bc-44df-aba2-02913531133cn%40googlegroups.com.

Simon Brown

unread,
Jan 2, 2023, 1:01:35 AM1/2/23
to Linrad
Leif, Joe,

I believe I now have enough info to start this coding in a week or so. I can use IQ recordings with known signals. If I get stuck with this I'll be in contact.

Leif Asbrink

unread,
Jan 2, 2023, 1:10:40 PM1/2/23
to lin...@googlegroups.com
Hi Joe and Simon,

When I wrote the network code for Linrad, the information I had
said that the maximum payload was 1400 bytes. Larger packages
would be split into smaller ones on the actual network. Max frame
size is 16 bytes, four float variables, so I selected 87 frames
to make the payload 1392 bytes to avoid problems when a sub-package
was lost.

73

Leif
> To unsubscribe from this group and stop receiving emails from it, send an email to linrad+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/linrad/660f21d6-ab23-7b1a-6d88-62fbd09a7398%40princeton.edu.

Joe Taylor

unread,
Jan 2, 2023, 1:58:00 PM1/2/23
to lin...@googlegroups.com
Hi Leif,

Thanks for the explanation. I think you may have told me these facts
once before, but I had long since forgotten them.

Also: I agree with your comment that today it's nearly always better to
use floats rather than 16-bit ints for timf2 data. I have kept a
capability to use 16-bit data mainly for backward compatibility, and
perhaps for use with legacy hardware.

-- Joe
Reply all
Reply to author
Forward
0 new messages