Forums › SM Series Discussions › Queued Sweep Synchronizations
- This topic has 14 replies, 2 voices, and was last updated 5 years, 2 months ago by Andrew.
- AuthorPosts
kaiserParticipantThe SM200A is working great so far for me. Right now I’m looking into the best way to synchronize external actions with seeps.
For example, right now I queue up 12 sweeps, and start them with sm_api.smStartSweep(handle,i) and then continuously read them with
SmStatus status = sm_api.smFinishSweep(handle, queuePos, null,sweepsMax[j], ref sweeptimeEpoch[j]);
sm_api.smStartSweep(handle, queuePos);
I would like to synchronize some external events with start/stop of these queued sweeps. So, I guess my question is, is finish sweep basically the end of the sweep with minimum latency?
Based upon what I’ve seen, I have ~0.1ms for the LO to get back in position to start the next sweep. I’d like to issue a notice to some equipment before the next sweep starts. Is FinishSweep a good spot to do that, or is there some other synchronization that I can do? I know that I can twiddle GPIO ports, but my output is happening on the same system that’s working with the SignalHound.
I could also connect GPS, get time counts on sweeps, and run an external synchronization thread that looks at when the sweeps are executed, and send the commands at appropriate sweep intervals, but I’m concerned about >0.1ms deviation from system clock synchronization to SM200A GPS clock, and how to keep locked. If there was a way to query the SM200A clock, then I could likely synchronize also, but then even on Linux you’re getting into minimum system timeslice concerns, but interrupts could probably be generated to get good alignment.
It would be a lot easier if smFinishSweep is basically immediately returned post sweep, but my guess is that it returns once the data is present, which is a bit after the sweep, and thus not suitable to inter-process synchronization.
kaiserParticipantI guess that in a perfect world, it would be neat to be able to register/get interrupts using functions similar to the GPIO setup; hey give me an interrupt when I pass X frequency, or whatever.
AndrewModeratorHi Kaiser,
It sounds like most of your assumptions about the API are correct regarding timings/etc.
FinishSweep returns when the data has returned and that data has been processed. One of the issues here is that the API will batch several operations/transfers together when we can, and in the event of queued sweeps, if you queue up several small sweeps, it might collect and process all these sweeps at the “same time” as seen by the PC (all the data is returned from the FPGA in the same transfer). So the FinishSweep might return and all the sweeps might already be done. It’s not until you get to wider span sweeps where FinishSweep could return when the next sweep has only just started.
I think the only way to guarantee some action occurs between two sweeps (at a software level) is to start/finish 1 sweep at a time.
If you can operate in a 40MHz bandwidth, using I/Q streaming with external triggers into the device to help sync would be a good way to go.
The software interrupts are an interesting idea, but I do think they would suffer from the same issue, where USB commands and data xfers would be batched together at times and it would be impossible to insert a software interrupt between two very small sweeps since they would occur back to back all on the FPGA. (FFTs for ‘fast sweep mode’ occur on the FPGA, so once the data is xferred back to the PC it doesn’t undergo any extensive processing.)
The GPIO sweeping mechanism (changing the GPIO on frequency crossings) was designed with this type of problem in mind and it sounds like you have already evaluated this feature.
Would an external trigger indicating a sweep is starting/ending be of interest? It’s not something we can do right now, but maybe we could consider it for a future update.
Regards,
Andrew
kaiserParticipantThanks for the detailed reply Andrew. Like I said, interrupts would be the best case. I’ve extensively used to National Instruments samplers, and my understanding form talking to their engineers is that they open multiple pipes on the USB connection; one for high bandwidth streaming, and one for low latency notification. So, for example if I’m sampling 32 inputs at 16-bits, 30kHz I get a stream very similar to what I get from the SM200A, but also can have extremely low latency notifications (non-deterministic of course, but low latency) of events like sample start / sample end or change detection on some pins. I imagine that it would complicate your drivers somewhat and might not be worth it. Like I said, in a perfect world 🙂
What I’ve done is grabbed one of our microcontrollers (a SAME54 board) from the back, and am working to integrate that. The thought is that I can use the GPIO of the SM200A to notify the microcontroller of when a sweep end. The microcontroller gets an interrupt, and then communicates with the attached equipment to prepare it for the next sweep while the SM200A is running.
Basically, I need to keep the SM200A sweeping my 100MHz band of interest at the 0.3ms sweep time that I am getting now, but also in between sweeps configure my support hardware for the next sweep. I can’t afford to let the sweep time increase any, and I have to sweep the entire 100MHz, can’t get it down to 40MHz.
The microcontroller in debug mode yesterday could update the support hardware at >100kHz, so I should be able to keep the SM200A in fast sweeping mode, and just upon notification of the sweep end (or that the sweep has hit a certain frequency to account for any latency), update the equipment while the SM200A prepares for the next sweep.
I’m running through a couple hundred test states of the support equipment while this happens. So, the best way would be for the GPIO to essentially increment/change every scan. But I don’t see exactly how I could do that with the GPIO; it seems to be more inter-scan focused than intra-scan focused or time-based (which might work).
So let’s talk GPIO:
If I use GPIO sweeping, does it reset every sweep, or run independently? Say I.m sweeping up to 2.9-3GHz. If I set the GPIO sweeping to increment every time I pass 2.99GHz, would it continue to increment every sweep, or reset? If it just continually incremented down the list, that would be awesome. If it resets, then I can probably make it work, but then move a ton of functionality to the microcontroller and end up with potential for them to get out of sync (microcontroller counting pulses, and running the show rather than the main computer telling it which state to go into). Guess that I can probably test this.
With GPIO switching — the examples I saw show it going alongside IQ streaming, and the API indicates that it’s “output while the device is streaming IQ data”. So I assume that it doesn’t work with regular sweeping? If it did, is the timing good enough between it and the sweep, that I could get/keep them synchronized? I didn’t see a great mechanism for that, and am unsure how I would synchronize, but could be missing something.
Still just trying to find the right way to skin the cat here 🙂
kaiserParticipant- This reply was modified 5 years, 9 months ago by kaiser.
Also, real quickly. Why is the C# API declaration for smSetGPIOSweep commented out for the structs? It should be fairly simple to pass an array of structs from C# to C++, like so:
[StructLayout(LayoutKind.Sequential)]
public struct SmGPIOStep
{public double freq;
public Byte mask; // gpio bitspublic SmGPIOStep(double f, Byte m)
{
this.freq = f;
this.mask = m;
}
}[DllImport(“sm_api.dll”, CallingConvention = CallingConvention.Cdecl)]
public static extern SmStatus smSetGPIOSweep(int device,[In, Out]SmGPIOStep[] steps, int stepCount);Is there some mismatch or oddities on the other side? It’s just two fairly straightforward variables.
Edit: If I put one of the GPIO’s on the O-scope, and run the GPIO Sweep sample code with this change in C#, I get a waveform that looks about right….
AndrewModeratorKaiser,
I don’t think the GPIO sweep switching is going to be adequate for your task since you are doing the 100MHz spans. It was originally designed to antenna switch over multiple GHz sweeps. It only operates at the granularity of the LO step freq which is 160MHz in your case, or 40MHz in the slower sweeps.
The I/Q GPIO switching you saw does not work in sweep mode.
Thinking about what we could add to the API, what if the API gave you the ability to queue GPIO switches in between sweeps. For instance, insert a single GPIO switch in between StartSweeps? Do you think this would be adequate for your measurements?
I don’t think it would slow down the sweep speed at all.
Given the 100MHz span, I think you would have to give up sweep speed to accomplish what you need with our current API.
If you think the proposed solution would work, I can potentially look into adding this for a future update? You could simulate this by calling
smGetSweep() -> smSetGPIOState() -> etc..
albeit at a slower sweep speed.Regards,
Andrew
kaiserParticipant- This reply was modified 5 years, 9 months ago by kaiser.
Yea, the GPIO change between sweeps would be amazing for what I’m trying to do. I simulated putting it in my queued sweeps, and it kept up for about 30 sweeps before I crash the thing 🙂 I know that’s not what exactly you were proposing, but that’s what code I had in front of me to test with 🙂 Seems like the WriteImm is pretty quick, and wouldn’t be a lot of overhead for commanded-sweeps. But I really need the speed of the queued sweeps.
With the queued sweeps, if I do increase my frequency range, then I do get a waveform I can use. Not ideal, but I can alter the architecture to make it work, and future maintenance will just be a bit of a hassle. The slowdown is *probably* manageable. It’s sweeping now in 0.4ms instead of 0.3ms. It’ll reduce the amount of data I collect to be able to say the equipment is working right, but we might still get enough. Only one way to try.
So, the 160MHz sweep bins; how do I calculate those? Like when I was scanning 100MHz, and it was taking 0.3ms you said that it was likely spanning two of the 160MHz bins. If I’m upping the spectrum I’m capturing to make this go, I’d like to intelligently add it to the left and/or right side based upon where these bins are instead of ending up spanning 4 bins and having to iteratively test a bunch to find the optimal spot…
Thanks again! Sorry for all the questions!
AndrewModeratorKaiser,
OK, I’m glad to hear that would be an adequate feature for you. I will look into seeing what it would take to introduce this.
For the record, attempting to call setGPIO between StartSweeps will crash the device. It currently does not check whether any active USB transfers are occurring before sending the GPIO command, potentially clobbering the sweep transfers.
You should be able to simulate it with crashing by finishing each sweep before setting the GPIO.
Regards
kaiserParticipantThanks Andrew. Anywhere to point me regarding the 160MHz frequency bin locations for calculating what bins my sweeps land in? I played with some settings of going wider, and it was hit or miss on whether I increased 0.2ms, 0.1ms, or got the GPIO working. Like I was missing a piece of the puzzle 🙂
AndrewModeratorHi Kaiser,
We don’t have any documentation on the step locations, and after reviewing the code I suspect there is not an easy way to determine this information based on settings alone. I had incorrectly remembered it being easier to determine than I originally thought.
I apologize for the inconvenience.
Regards,
Andrew
kaiserParticipantThanks for looking into it for me.
kaiserParticipant- This reply was modified 5 years, 8 months ago by kaiser.
To pick up this thread some Andrew, I’m currently running into something that may or may not be an issue.
For example, if I set GPIOs like this:
int gpiosteps = 2;
SmGPIOStep Steps[gpiosteps];Steps[0].freq = 2.40e9;
Steps[0].mask = 0x00;
Steps[1].freq = 2.47e9;
Steps[1].mask = 0x0F;and look at it on the O-Scope, I get the exact same pulse as if I set something like this:
int gpiosteps = 2;
SmGPIOStep Steps[gpiosteps];Steps[0].freq = 2.40e9;
Steps[0].mask = 0x00;
Steps[1].freq = 2.49e9;
Steps[1].mask = 0x0F;With the frequency of the second step 20MHz further down the line.
So, my concern is when the GPIO goes low, what frequency is it actually going low at? Is it 2.4GHz, or that plus/minus 40MHz? 60MHz? 160MHz?
Like I said, I’m triggering external test equipment, and in this example Step2, when the GPIO goes high, it causes an interrupt in our microcontroller that goes and sets up the next piece of equipment. We’ve gotten the timing such that that setup is done and complete before the GPIO waveform goes low, but not by much.
But we know that it going low isn’t happening *exactly* at 2.4GHz, and so we might be making our timing…or we might not.
So, I understand that figuring out where those GPIO transitions ARE happening is tough; but I really do need to know. I can do complex things, or if it’s just a one-off where you can just tell me where it’s happening based upon my sweep parameters, that’d be great. If I need to write 500 lines of code to figure it out, great also. If I request certain frequencies, and the SM200A comes back to me with what it’s actually going to do, that would work also. But I do need to know…
This is literally our last hurdle to fielding this capability, and I’d really like to get it figured out, shipped and move onto our next fun project 🙂
Thanks!
AndrewModeratorKaiser,
For normal sweep speed, (via the smSetSweepSpeed function) the resolution on which we can change the GPIO output is multiples of 39.0625 MHz. (N * 39.0625 MHz) If you are using the fast sweep speed, that number is 156.25 MHz but can be offset by a multiple of 39.0625 MHz. (N * 156.25M + 39.0625M * [0,1,2,3 depending on factors]) If you use the same sweep settings, the API will be consistent about what LO steps it changes the GPIO on.
I believe the logic is, that if your GPIO freq exceeds the freq calculated from the equations above, then we perform the switch. If you use these multiples directly, pick a number slightly higher to force the switch.
It sounds like you just need to nail this down for just a couple sweep configurations? This should be enough information for you to start adjusting the frequency on the GPIO steps and choosing the best values for your sweeps?
Regards,
Andrew
kaiserParticipant[StructLayout(LayoutKind.Sequential)]
public struct SmGPIOStep
{public double freq;
public Byte mask; // gpio bitspublic SmGPIOStep(double f, Byte m)
{
this.freq = f;
this.mask = m;
}
}[DllImport(“sm_api.dll”, CallingConvention = CallingConvention.Cdecl)]
public static extern SmStatus smSetGPIOSweep(int device,[In, Out]SmGPIOStep[] steps, int stepCount);I just downloaded the latest API, and was running it against some of my code. I had to edit the sm_api.cs again to add this in, so that I could set up GPIO Sweeps from C#. It seems to work great again. This is the 3rd project where I’ve had to make this edit, as suggested here. Is there any reason why this bugfix hasn’t been included in the sm_api.cs file yet?
AndrewModerator- AuthorPosts
You must be logged in to reply to this topic.