Welcome to the new FlexRadio Community! Please review the new Community Rules and other important new Community information on the Message Board.
If you are having a problem, please refer to the product documentation or check the Help Center for known solutions.
Need technical support from FlexRadio? It's as simple as Creating a HelpDesk ticket.

How to use FlexLib API IQStream?

Kyle Gagner
Kyle Gagner Member
edited February 2020 in FLEX-6000 Signature Series
Hello, I am trying to figure out how to use the IQStream object to get raw IQ data from a Flex radio using the FlexLib API. I need some general guidance on how to use the API, which doesn't seem to have much documentation. I can figure out the specifics. I have a lot of C# experience and I have worked with .NET hardware APIs in the past. Part of my problem is that I do not fundamentally understand the exact functions of many of the objects in the API. I believe I will need to call CreateIQStream on my radio object to get an IQStream object, add a delegate to the IQStream object to handle the DataReady event, and call RequestIQStreamFromRadio on the IQStream object to begin receiving data. A few things confuse me: 1. Why do I have to give CreateIQStream a DAX channel? My understanding is that DAX is a technology for passing data streams by using virtual Windows audio devices. With the FlexLib API we should be avoiding DAX altogether, so what is this? Where do I get that number? 2. How do I set the frequency I am receiving on? My understanding of the radio is that it uses a digital downconversion to take a selected portion of the frequency spectrum down to baseband, and that the hardware responsible for this is an FPGA slice. Is this correct? Then, why is it when I create a slice in the API that I must specify a demodulation mode? All I want is IQ data. The slice, however, does have a frequency setting, so I think I do need to create a slice object. I'm just guessing at this point though. 3. Possibly unrelated to my primary question... What precisely is a panadapter? Is the panadapter just an FFT plot of a portion of the RF spectrum? Does the data used by the FFT come from a slice, or is the panadapter implemented separately from the slices? Do I even have to worry about panadapters if all I want is IQ data? This is what I have tried: I have tried creating a slice and then creating an IQStream object from the DAX channel that slice purports to use. Nothing crashed but my DataReady callback never ran. I'm guessing it's not the right approach. I'm really not sure what the right approach is. A tiny bit of sample code or little explanation of how this all works, just to show me how to set the frequency and begin receiving IQ data, would be great. Thanks! - Kyle Gagner P.S. My experience comes from being an avid hobby programmer, undergrad electrical engineering student, and intern at Keysight (formerly Agilent) last summer working on vector signal analyzers. I am not a ham radio operator, but my dad is (he bought the radio).

Answers

  • Jay Nation
    Jay Nation Member ✭✭
    edited May 2019
    Isn't DAX just a stream of audio from one memory location to another? I'm trying to underatand this too.
    Jay - NO5J
  • Kyle Gagner
    Kyle Gagner Member
    edited February 2015
    That's what I believe but, more specifically, I think it does it with virtual audio devices. There are many alternatives for passing streams of data between programs, such as TCP sockets, Windows pipes, conceivably shared DLLs (never tried this one particularly), and audio devices. Audio APIs are pretty widely available so it's a good solution for many programmers. However, compiling code to directly use an API for the radio should circumvent the need for such data passing mechanisms since the network packets will go directly to your code. I think that DAX finds its primary application in interfacing third party programs with SDRs where the intention is that an SDR from one of many different manufacturers who support DAX could be used. This is my understanding of the subject and I could very well be wrong.
  • Jay Nation
    Jay Nation Member ✭✭
    edited August 2016
    We're thinking alike, I think. Let's hope we're thinking right. I've let my programming skills atrophy, I need to work on C, C#, and .Net and WPF and spend less time mucking around in bash, and python. I've wondered what I was going to do with retirement, time to get busy. Call it Retirement 2.0, dream it and DO IT, or die.  
  • Jay Nation
    Jay Nation Member ✭✭
    edited August 2016
    And thanks for helping me clarify!
  • Kyle Gagner
    Kyle Gagner Member
    edited February 2015
    C is my main, but I am a fan of C#, Python, and VB.NET as well. I am not so much of a fan of WPF, and Winforms is here to stay anyway (I think). I've also been doing hardware design in Verilog / SystemVerilog lately. Programming is fun!
  • Jay Nation
    Jay Nation Member ✭✭
    edited August 2016
    Life is just a hobby!
    Just something to keep you busy between birth and death.
    I love my hobbies. They save my life sometimes. Time to get to work.
  • Jay Nation
    Jay Nation Member ✭✭
    edited August 2016
    Being pre-Unix, but actively programming since learning BASIC, I can usually get a computer to at least do most of what I want, but I've been a little lazy about actually creating anything in C, and beyond. I can read it, debug alot of it, and follow along for the most part, I wrote some Assembly stuff back when people still did that so, I think can figure this out. I didn't get left behind, I just forgot to keep moving ahead.
  • KY6LA_Howard
    KY6LA_Howard Member ✭✭✭
    edited February 2015
    Thanks for making an old a machine language and assembler fossil feel that there may be a future.
  • Jay Nation
    Jay Nation Member ✭✭
    edited August 2016
    We're not fossils yet, first you have to get buried underground, then theres still a long long time, till you become a fossil. Theres always a future, there only used to be a past, can't go there anymore. Might be someplace else to live.
  • Jay Nation
    Jay Nation Member ✭✭
    edited August 2016
    We've been able to sync data streams remotely over a network for something like 4+ decades, kinda obvious now that it occured to my feeble mind. Hopefully someones working on this, Oh yeah, me first!
    Last one across the finish lines a rotten egg!
  • Kyle Gagner
    Kyle Gagner Member
    edited February 2015
    This is very clarifying. I will keep working on it this weekend and see where I get with this new information; I think I should be able to make it work now. Thank you for the detailed response.
  • Kyle Gagner
    Kyle Gagner Member
    edited March 2015
    Hello, I was delayed a bit in getting back to this (research projects, midterms, etc.) but I have some time today so I've been giving it another go. I can get the radio to acknowledge my request for an IQStream, but I am having difficulty with the Panadapter. Does it matter when I request the Panadapter? Currently I am requesting it after the IQStream request is acknowledged, like so: void sdrstream_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "RadioAck" && sdrstream.RadioAck) { Debug.WriteLine("IQ Stream Acknowledged"); panadapter = radio.CreatePanadapter(new System.Windows.Size()); panadapter.PropertyChanged += panadapter_PropertyChanged; panadapter.DAXIQChannel = sdrstream.DAXIQChannel; panadapter.RequestPanadapterFromRadio(); } } I see two puzzling messages in the debug console before the acknowledgement for the IQStream. I'm going to try to dive into the API and figure out what they mean next, but it might be a red herring. Radio::ParseStatus: Unparsed status (S79D2CCD0|daxiq 1 pan=0x0 rate=48000 capacity=16 available=16) IQStream::StatusUpdate: Key not parsed (pan=0x0) IQ Stream Acknowledged I wasn't sure what to put for window size as I'm not really using the Panadapter, just the IQStream, so I put nothing. I've also tried 512, 512.
  • Kyle Gagner
    Kyle Gagner Member
    edited March 2015
    Well, I've got it working now. It's super buggy, so I'll keep working on it and post, some time in the next two weeks, what I've got, for anyone interested in trying to demod IQ data.
  • James Whiteway
    edited March 2015
    Definately interested in seeing your code. IQ data is just one of several things I'm trying to understand and work with. james WD5GWY
  • Mark Erbaugh
    Mark Erbaugh Member ✭✭
    edited February 2020
    Could someone explain the RadioAck property and the sequencing?  I see in Kyle's code above that it waits for a property change callback. Is this the best way to determine that radio has accepted a command?  In my code, I've been sending commands and assuming that the radio accepted them. Are there certain commands that must be ack'ed before proceeding?
  • Kyle Gagner
    Kyle Gagner Member
    edited March 2015
    In my observation, it took some amount time for the radio to acknowledge my request for an IQ stream. If it is imperative that your setup sequence occur in a certain order, a race condition can occur if you don't wait for RadioACK, but one way to check that would be to rewrite the sequence out of order and see if it breaks. I don't understand the API well enough yet to say whether things necessarily need to come in some order. I'm back at school for finals week and my dad has all of the project files on his computer at home, so I can't do it myself now, but if I were you, I'd go into the source code for the API and see where RadioACK is set to false. For functions that set RadioACK to false, one of two things is true:
    1. The resulting change of state in the radio is not guaranteed immediately after the function is used, so RadioACK must be observed to determine when the radio's state is valid
    2. The instruction may be one which the radio is not guaranteed to act on and acknowledge at all, so RadioACK must be observed to determine whether the radio has decided to change state
    My first instinct is to go with 1, but after using the API this weekend, I'm not sure whether the sequence of events is critical. It may be that race conditions are not a concern. I've also made requests to the radio (for panadapters) that never went serviced. These things make me think option 2 may be the case. That makes the API harder to use.
    One feature of Visual Studio that I have found exceedingly useful is the debugger's watch window. You can see the state of all of the objects in your program change and track what is going wrong as the flow of control passes on events, rather than a linear procedure.
    One last observation. I do not think the API is consistent in raising the PropertyChanged event. For example. Radio.Connected changing to true never raised a PropertyChanged on Radio for me.
  • Kyle Gagner
    Kyle Gagner Member
    edited March 2015
    I'm not sure I know what I'm doing yet, but I'll continue working on this over spring break next week and post my code when I'm more confident that I'm using the API correctly.
  • Wayne, W5XD
    Wayne, W5XD Member
    edited February 2017
    I too would like to construct an application to read an I/Q stream, but I would prefer not to go through DAX. (My aversion to DAX is simply that I have found the DAX audio channels are buffered about 200msec behind real time in both transmit and receive--I don't want my application to be that far behind and hope--without knowing for sure--that the VITA-49 data for the I/Q streams are not buffered that deeply.) This page says, "Streaming data is sent from the radio in the VITA-49 format from UDP/IP port 4991 to targeted clients." But I haven't found the right incantation to become a "targeted client", presumably to be sent via IP port 4992 via the command API?
  • Eric-KE5DTO
    Eric-KE5DTO Administrator, FlexRadio Employee admin
    edited December 2016
    Today the radio requires a Panadapter in order to run an IQStream.  The command to create the IQ stream over ethernet is "stream create daxiq=<channel> ip=<ip> port=<port>"  Note that is the IP and Port are left off, it will use sensible defaults.

    Once that stream has been created and a Panadapter object has set it's daxiq to the same channel, the VITA-49 data should appear at the requested port.  That's the nuts and bolts.
  • Wayne, W5XD
    Wayne, W5XD Member
    edited July 2015
    Ah, thank you. I'll try that. Looking back at the wiki, I believe I have an excellent excuse for having failed to find the documentation. There is a broken link here for the stream command.
  • Wayne, W5XD
    Wayne, W5XD Member
    edited February 2017
    I got far enough along to try this. I get buffers delivered to my UDP port, but I cannot tell what they are. That is, once my application has send the specified command over an IP connection to port 4992:
    stream create daxiq=1 ip=<ip> port=<port>
    and once I have used SmartSDR's "DAX" button on one of its Panadapters to set "DAXIQ" channel to  "1", thereafter, I receive buffers at my UDP server at my ip/port. The buffers stop coming if I use SmartSDR to change its Panadapter DAXIQ to anything other than "1". So far, so good.

    I get roughly 95 packets per second, and each is of size 4128 bytes. Nothing I do in the "DAX Control Panel" application appears to affect the buffer size or frequency (I am hoping to be able to select the sample rate int the 24K to 192K range. How might I do that?) The only sensible deduction I can make from the received buffers is that their rate is roughly equivalent to 48K samples-per-second times 2 channels times 4 bytes per sample.

    My primary reference for the format of the buffers I expected is the source code at hal_listener.c, from the published documentation for the "SmartSDR Waveform API". I am now 99% certain I am not getting VITA-49 data and that instead I have wandered off the trail and am lost in the deep weeds. Can anyone lead me back? It feels like there must be a book or web page somewhere that explains all this, but I have so far failed to find it.

    While I am asking... For my current application, I would much rather have the FFT'd I/Q data rather than the time data. Does the radio source FFT'd data? and, if so, what is the appropriate incantation?
  • Eric-KE5DTO
    Eric-KE5DTO Administrator, FlexRadio Employee admin
    edited December 2016
    In a situation like this, I usually fire up Wireshark to look at what the data looks like coming across the wire to see if I can make heads or tails of things.

    You can set the sample rate with the command "dax iq set <channel> rate=<new rate>".  The allowed settings are those shown in the DAX application (24, 49, 96, 192kHz).

    For FFT data, you should probably look at the Panadapter options.  We actually render the FFT for the display size.  In the ethernet API, look at the display command.  In FlexLib, you can take a look at the class in Panadapter.cs.
  • Wayne, W5XD
    Wayne, W5XD Member
    edited February 2017
    Eric, your help is appreciated yet again. Thank you. I was not quite as far off in the deep weeds as I had feared. I didn't use wireshark--looking at the received buffers in the debugger was good enough--and figured out that I had simply confused myself between the network-byte-reversal and the fact that I was mislead by a google search showing how Vita-49 fit into a single ethernet frame, so I got confused by a 4K byte packet. All makes sense now.

    I am now fishing around looking for how to set the panadapter's center frequency from the ethernet command processor. I see how to do it via the .NET API, and I can make do with a mixed mode client for now (mixing .NET calls with ethernet command strings and VITA-49) but I would like to move my code that deals with the I/Q channel to work purely through the ethernet API.

    Editing after submitting: didn't read the doc's carefully enough before my previous post. I see the "display" command and how to set the panadapter via the ethernet command API.
  • Eric-KE5DTO
    Eric-KE5DTO Administrator, FlexRadio Employee admin
    edited December 2016
    Note that you can also grab the FlexLib source and just reference the .NET class and look at the string it uses to send the commands since it is all built on top of the ethernet API.

    For others wondering, to tune a panadapter, use the "display pan set <Stream ID> center=<MHz>" command.
  • Aaron Olinger
    Aaron Olinger Member
    edited April 2019
    Hi Kyle, I just stumbled across this thread and am interested in how you managed to obtain the raw IQ data using the flexlib API. I myself am doing some research with respect to what you accomplished and am confused about how to use the API correctly.Did you end up posting your code?
    Aaron 

Leave a Comment

Rich Text Editor. To edit a paragraph's style, hit tab to get to the paragraph menu. From there you will be able to pick one style. Nothing defaults to paragraph. An inline formatting menu will show up when you select text. Hit tab to get into that menu. Some elements, such as rich link embeds, images, loading indicators, and error messages may get inserted into the editor. You may navigate to these using the arrow keys inside of the editor and delete them with the delete or backspace key.