Hi Jaco,
Are you waiting a sufficient amount of time between trasmitting the last sample and shutting off the TX module? Disabling the TX module occurs as quickly as it can -- it
does not inherently flush all remaining samples, so it's possible that you can shut the module off before the samples are actually transmitted.
Another possibility is that your bladerf_sync_rx() calls are simply "missing" the samples -- they hit the FPGA before the RX side is ready to buffer them. When using the sync interface, the worker thread that manages buffers doesn't launch until your first bladerf_sync_rx() call. (This is done to ensure that the underlying stream doesn't time out between you configuring it and making the first bladerf_sync_rx() call.)
You may be able to catch the samples if you use a fairly large timeout and number of buffers on the RX side, and performing an bladerf_sync_rx() call prior to your first bladerf_sync_tx() call. This will ensure the underlying RX worker is actively filling buffers with incoming data until you make your bladerf_sync_rx() call to consume those samples.
However, you'll need to be careful in doing the above. If you're transmitting a fairly large set of samples, your RX buffers may overrun or you may timeout. As such, I consider the above to be a bit of a kludgy solution.
What I would instead advise is that you kick off a thread to RX samples to a file before you even begin TX'ing. You'll probably wind up with a bunch of extra samples before and after your desired data, but the data should be easy to prune in MATLAB.
Your procedure would then become something like...
- Enable the desired loopback mode
- Configure the TX streams
- Fill a TX buffer with the waveform .bin file
- Launch your RX thread
- Enable the TX module
- Transmit the samples in the TX buffer
- Wait some amount of time to ensure the samples are transmitted and then received
- Disable the TX module
- Signal the RX thread to cleanup and shut down
- Join the RX thread
The RX thread might look like this...
- Open a file to save samples to
- Configure the RX stream
- Enable the RX module
- While we haven't been signaled to shut down...
- Receive samples
- Write them to a file
- Close the file
- Disable the RX module
- Exit the thread's function
For completeness, I've tried to provide some useful answers to your specific questions:
Jaco wrote:
My files are simply a list of IQ pairs, e.g. I1 Q1 I2 Q2 etc., is this correct?
Yes. For the SC16Q11 format, each component is a right-aligned, sign-extended, little-endian 12-bit value. The values [-2048, 2048) represent [-1.0, 1.0). Note that the upper bound is
exclusive here! (Keep the positive values to 2047 or less.)
Jaco wrote:
Is the loopback mode even an appropriate method to test my transmit / receive routines?
For what you're describing, I think you should be able to make use of these.
The firmware loopback mode will loop back the
exact data, and you'll generally want things running full duplex to keep samples moving, since the buffers in the FX3 are relatively small.
The other loopback modes pass your data through the analog paths on the LMS6002D, so this probably what you want. Generally, the baseband loopback modes will be a little "cleaner," but I think you should be just fine with the RF loopback modes.
Jaco wrote:
Is the synchronous interface sufficient for what I'm trying to do?
Nothing from your description is jumping out at me to suggest that it would be insufficient. This interface only becomes insufficient if you need very fine-grained control over buffer management, have very low-latency requirements, or are really customizing something on the FX3 or FPGA side of things.
Hope that helps!
- Jon