I am trying to modify the Transmit and Receive LTE MIMO code given in the below link.
This code runs perfectly on AD RF SOM.
Now, I am trying the same example to run on ADRV9371.
ad9361_LTE() ( The code that's in the Legacy folder under LTE_MATLAB) uses IIO hence, I modified this code to 9371 and it works for the dummy data which is used in trData. (I was able to see LTE spectrum on the Spectrum Analyzer). Please note that I upsampled the enodeBOutput by 8 (to match 122.88Mhz) for Transnmission.
But, when I modify it to the above image and try to Transmit, MATLAB crashes. After a bit debugging, I understood that the buffer size that I have pre-allocated,is too large and that could be the reason for my Crash. (Not sure though)
Next, I changed the IIO objects to Adi Objects and used adi.AD9371.Tx and could similarly transmit the dummy Data but, when tried to Transmit the full grid, I get an error.
This error is related to SamplesPerFrame. The Final enodeBOutput is much larger than 2^20, Hence,I always get an error.
How, do I transmit this whole grid either using IIO objects or ADI objects?
Please suggest any work around.
Error using adi.AD9371.Base/set.SamplesPerFrame (line 65)Expected SamplesPerFrame to be a scalar with value <= 1.04858e+06.
Error in adi.AD9371.Tx/setupImpl (line 71) obj.SamplesPerFrame = size(data,1);
Error in ad9371_LTE_adi_Tx_3 (line 216)tx(eNodeBOutput);
There is a maximum bound on the samples you can transmit without modify HDL and the linux kernel. The bound we pre-set in the system object is conservative (2^20). You can try increasing this changing the value on this line: https://github.com/analogdevicesinc/MathWorks_tools/blob/master/%2Badi/%2BAD9371/Base.m#L66
It may be possible to extend this to 2^23.
Hi Travis, also another question.
How can I modify the HDL and linux kernel? Can you please point me to some documentation?
I would first recommend decreasing the sample rate so you don't need such a large buffer. This can be done through this tool: https://wiki.analog.com/resources/eval/user-guides/mykonos/software/filters
If you need to increase the maximum buffer size, first change the CMA of the kernel.
I don't think I can reduce the Sampling rate. My goal is to simulate an aggregated LTE signal of 60Mhz,so the sampling rate has to be 122.88Mhz.
I was not sure how do to the changes in CMA kernel to increase the buffer size to the said 2^23 or 2^24 as per documentation.
I tried breaking the final waveform into chunks of 5 frames nd transmitted repeatedly in a while loop forever.
tx(signal1); %% 5 frames worth samples 153600*5
tx(signal(2); so on..
collect 6 frames worth samples I;e 153600*6 (I need this to run 8 times as the Sampling rate is 122.88Mhz)
The issue is at the receiver I am not able to reconstruct/decode the original signal. Even the cellID is not getting decoded properly.
I tried increasing the delay between significant reception of bursts but nothing helped.
Can you please suggest any alternative?
If I cannot change buffer size in kernel and don't have the option to reduce Sampling rate, what other options do I have apart from the above said procedure?
This doesn't appear to be a buffer length issue since you can fit many frames inside the buffers. I assuming (153600*5) is the length of your entire LTE frame here.
To correctly capture a single frame requires 153600*5*2 samples, which is well within the standard DMA capture size. 2^22 and below worked fine for me with the standard SD card.
Are you using the same board to capture the transmitted signal? If so, how are you interleaving transmit and receive calls?
Hi Travis, the example that I'm trying to modify for 9371 is the below one.
I'm using adi board support package for 2018b.
Now, in this example, the image is packed into 5 frames, and the sampling rate there was 15.36 Mhz. So, now I upsampled the entire 5 frames by 8 to match the 122.88Mhz . please note the total size of my final output is 153600*5*8.
As you can see in my previous questions, when I tried to transmit this whole signal at once,it gave me the below error.
As per you suggestion I changed the buffer length value to 2^22 in the base.m file but even that didn't help.
So, now I split he entire signal in chunks of 153600*5 and looped it 8 times in an infinite while loop
while 1 for i=1:length(eNodeBOutput)/(153600*5) %% loops for 8 frames tx(eNodeBOutput((i-1)*153600*5+1:i*153600*5)); %% Transmit 5 frames one burst pause(2) endend
please note this transmitter code runs forever and receiver code has to be run on a different MATLAB instance.
to enable this, just before the while loop I save all the variables which are needed for the receiver code, and load them in the receiver.
In the receiver, I need to capture 6 frames to enable the receiver to decode the data as per the above said example. Hence the total size in receiver burtscaptures would be 153600*8x1x6.
After capturing these many samples I arranged them accordingly into 6 frames as needed for the code below.
I'm using the same board to transmission and reception but different matlab instances.
The SDcard image that i'm using is the 2018 version.
2^22 never worked for me even after I changed the value in base.m as per our earlier suggestion.
Please let me know if i'm doing any mistake.
Based on how your transmitter is written, you will never be able to receive data correctly. Let me just explain this a bit. Since your data rate of the device is 122.88 MSPS, this is faster than the data interface to the board itself (Ethernet). Therefore, every time you submit a new buffer to the board, a period of time has passed between when the next buffer is fully received by the board and the previous one is transmitted out. This creates gaps in the data, which will make the frame unrecoverable on the RX side.
In regards to buffer sizes, there is a software limit that restricts the maximum buffer size to avoid the IIO subsystem taking up all the system memory. By default this limit is 16MB, you can change it by setting the `industrialio_buffer_dma.max_block_size=` command line (This can be done by editing the uEnv.txt on the BOOT partition) option or by writing to the `/sys/module/industrialio_buffer_dma/parameters/max_block_size` file on the system. The size must be specified in bytes.
In addition to this, there is a limit on the total amount of memory that is available for DMA buffers. This limit can be configured by setting the 'cma=' kernel command line option. E.g. cma=256M.
Make sure that your system has enough memory available since memory reserved for DMA buffers can not be used for normal memory allocations.
Know that memory is shared between TX and RX, so you do not necessarily always have an upper limit of say 2^23 samples. It depends on what other TX or RX instances are doing.
I changed the iio max_block size to 32MB and also cma to 256M
also, I changed the value in base.m to 2^23.
Now, I don't get the error anymore.(error saying length is >2^20)
But, still the code doesn't work. The same code worked on 9361 at 61.44 Mhz.
I also tried capturing twice the number of samples per frame as you suggested but even this didn't work.
Am I missing any step during reception/transmission specific to 9371?
Are you handling the default rate differences between RX and TX?
I am using the filter profile given in GitHub. When I loaded the profile into TES, it says the Tx rate and Rx rate are same ie; 122.88Mhz.
Aren't they same?
Even if they were not same I tried capturing twice the samples as TX but still I don't see an change.
By default, TX is 2x RX, but if you are using a profile where they are the same, that should be fine.
Have you visually inspected the signal in both time and frequency to get what you expect?
Are you using cyclic buffers on the TX?
I tried to save the final output into a text file and load in TES. but I guess there is a limit on file size so it always pops an error message file not found.(the file size is around 63 MB).
I truncated the output to one frame ie:153600*8 since my upsampling factor is 8.
I see a frame on the receive data as expected, in frequency domain.
Yes, I am enabling the cyclic buffers.
And, in the receiver side, I flush the buffers as it was did in example codes.