Welcome to the new FlexRadio Community! Please review the new Community Rules and other important new Community information on the Message Board.
Need the latest SmartSDR, Power Genius, Tuner Genius and Antenna Genius Software?
SmartSDR v3.8.21 and the SmartSDR v3.8.21 Release Notes
SmartSDR v2.12.1 and the SmartSDR v2.12.1 Release Notes
Power Genius XL Utility v3.8.9 and the Power Genius XL Release Notes v3.8.9
Tuner Genius XL Utility v1.2.11 and the Tuner Genius XL Release Notes v1.2.11
Antenna Genius Utility v4.1.8
SmartSDR v3.8.21 and the SmartSDR v3.8.21 Release Notes
SmartSDR v2.12.1 and the SmartSDR v2.12.1 Release Notes
Power Genius XL Utility v3.8.9 and the Power Genius XL Release Notes v3.8.9
Tuner Genius XL Utility v1.2.11 and the Tuner Genius XL Release Notes v1.2.11
Antenna Genius Utility v4.1.8
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.
Need technical support from FlexRadio? It's as simple as Creating a HelpDesk ticket.
How to use FlexLib API IQStream?
Kyle Gagner
Member
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).
0
Answers
-
Isn't DAX just a stream of audio from one memory location to another? I'm trying to underatand this too.
Jay - NO5J1 -
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.0
-
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.0
-
And thanks for helping me clarify!0
-
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!0
-
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.0 -
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.1
-
Thanks for making an old a machine language and assembler fossil feel that there may be a future.0
-
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.0
-
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!0 -
These are excellent questions. Thanks for bringing them to the table. First, let me define some terms:
1. IQ Stream. This is a stream coming from the radio in IQ format that is tied to a particular Panadapter through the channel number.
2. Audio Stream. This is a stream coming from the radio in 24kHz audio that is tied to particular Slice through the channel number.
3. DAX. Stands for Digital Audio eXchange. This is used as a bridge for one or more of the above objects to talk to the Windows Audio subsystem. Note that this is just one application for the above streams, but it happens to be the only one we have officially implemented in an application at this point as it provides the necessary interface to legacy 3rd party programs.
It is unfortunate that we called the channels DAXChannel (and DAXIQChannel) and use "dax=<num> and "daxiq=<num>" in the over-the-wire command to request it. Nevertheless, the above definitions give a better picture of the system as a whole.
Now that we have the terms down, I think what you're wanting is an IQ Stream without having to deal with the Windows Audio side of things. This makes complete sense and is where we'd like to see things move.
You are on the right track. First call the radio.CreateIQStream function and specify which channel. Then subscribe to the PropertyChanged event and call the iqStream.RequestIQStreamFromRadio function waiting for the RadioAck property to go true. This signifies that the radio has accept the request and sent any necessary configuration data back to the client.
The other end of things is that there needs to be a Panadapter with that same channel selected. IQStreams go with Panadapters (today) and AudioStreams go with Slices. This is a convention we may change at some point to give more flexibility to developers. But today, that is how it works. In order to "tune" the IQStream, you simply update the CenterFrequency property on the Panadapter.
With the IQStream in place and the Panadapter on the same channel, you should begin receiving DataReady events with new data. This is exactly how the radio side of DAX works.
Panadapters and Slices are completely independent objects -- or as independent as we could possibly make them though they sometimes shares FPGA resources. This is all hidden from view though and can be treated as completely separate in the APIs.
As such, the only things that are shared in terms of our objects are that Slices always use the RX Antenna of the Panadapter in which they are shown. Changing the antenna in one place (Slices or Panadapter) will update the others. Beyond that, there should be no changes to a Panadapter due to a change in a Slice and vice versa.
Let me know if you need more info and thanks again for asking the questions.5 -
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.
0 -
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.0
-
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.0
-
Definately interested in seeing your code. IQ data is just one of several things I'm trying to understand and work with. james WD5GWY1
-
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?0
-
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.0 -
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.0
-
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?
0 -
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.1 -
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.
0 -
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?
0 -
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.0 -
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.0 -
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.0 -
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
0
Leave a Comment
Categories
- All Categories
- 299 Community Topics
- 2.1K New Ideas
- 546 The Flea Market
- 7.6K Software
- 6.1K SmartSDR for Windows
- 149 SmartSDR for Maestro and M models
- 378 SmartSDR for Mac
- 253 SmartSDR for iOS
- 227 SmartSDR CAT
- 165 DAX
- 361 SmartSDR API
- 8.9K Radios and Accessories
- 7K FLEX-6000 Signature Series
- 67 FLEX-8000 Signature Series
- 870 Maestro
- 45 FlexControl
- 849 FLEX Series (Legacy) Radios
- 819 Genius Products
- 427 Power Genius XL Amplifier
- 286 Tuner Genius XL
- 95 Antenna Genius
- 252 Shack Infrastructure
- 173 Networking
- 411 Remote Operation (SmartLink)
- 120 Contesting
- 664 Peripherals & Station Integration
- 128 Amateur Radio Interests
- 895 Third-Party Software