LimeSDR Streaming problem

#include “lime/LimeSuite.h”
#include
#include
#include
#include <math.h>
#include “…/gnuPlotPipe.h”

using namespace std;

//Device structure, should be initialize to NULL
lms_device_t* device = NULL;

int error()
{
if (device != NULL)
LMS_Close(device);
exit(-1);
}

int main(int argc, char** argv)
{
//Find devices
//First we find number of devices, then allocate large enough list, and then populate the list
int n;
if ((n = LMS_GetDeviceList(NULL)) < 0)//Pass NULL to only obtain number of devices
error();
cout << "Devices found: " << n << endl;
if (n < 1)
return -1;

lms_info_str_t list[8]; //allocate device list

if (LMS_GetDeviceList(list) < 0)                //Populate device list
    error();

for (int i = 0; i < n; i++)                     //print device list
    cout << i << ": " << list[i] << endl;
cout << endl;

//Open the first device
if (LMS_Open(&device, list[0], NULL))
    error();

//delete [] list;       

//Initialize device with default configuration
if (LMS_Init(device) != 0)

    error();

//Enable TX channel,Channels are numbered starting at 0
if (LMS_EnableChannel(device, LMS_CH_TX, 0, true) != 0)
error();
// Enable RX channel
//Channels are numbered starting at 0
if (LMS_EnableChannel(device, LMS_CH_RX, 0, true) != 0)
error();

//Set RX center frequency to 800 MHz

if (LMS_SetLOFrequency(device, LMS_CH_RX, 0, 800e6) != 0)

    error();

//Set TX center frequency to 800 MHz

if (LMS_SetLOFrequency(device, LMS_CH_TX, 0, 800e6) != 0)

    error();

//print currently set center frequency

// float_type freq;

// if (LMS_GetLOFrequency(device, LMS_CH_RX, 0, &freq) != 0)

// error();

// cout << “\nCenter frequency: " << freq / 1e6 << " MHz\n”;

// if (LMS_GetLOFrequency(device, LMS_CH_TX, 0, &freq) != 0)

// error();

// cout << “\nCenter frequency: " << freq / 1e6 << " MHz\n”;

//Set sample rate to 10 MHz, preferred oversampling in RF 4x

//This set sampling rate for all channels

if (LMS_SetSampleRate(device, 10e6, 2) != 0)

    error();

//Perform automatic calibration
LMS_Calibrate(device, LMS_CH_TX, 0, 10e6, 0);
LMS_Calibrate(device, LMS_CH_RX, 0, 10e6, 0);

//Set RX gain and TX gain

if (LMS_SetNormalizedGain(device, LMS_CH_RX, 0, 0.9) != 0)
error();
if (LMS_SetNormalizedGain(device, LMS_CH_TX, 0, 0.5) != 0)
error();

//Streaming Setup

lms_stream_t rx_stream;
lms_stream_t tx_stream;

//Initialize streams
//All streams setups should be done before starting streams. New streams cannot be set-up if at least stream is running.

    rx_stream.channel = 0; 
    rx_stream.fifoSize = 1024*1024; //fifo size in samples
    rx_stream.throughputVsLatency = 1.0; //some middle ground
    rx_stream.isTx = false; //RX channel
    rx_stream.dataFmt = lms_stream_t::LMS_FMT_F32; //32-bit float
    if (LMS_SetupStream(device, &rx_stream) != 0)
        error();

    tx_stream.channel = 0; 
    tx_stream.fifoSize = 1024*1024; //fifo size in samples
    tx_stream.throughputVsLatency = 1.0; //some middle ground
    tx_stream.isTx = true; //TX channel
    tx_stream.dataFmt = lms_stream_t::LMS_FMT_F32; //32-bit float
    if (LMS_SetupStream(device, &tx_stream) != 0)
        error();


const int buffer_size = 200;
float tx_buffer[2*buffer_size]; //buffer to hold complex values (2samples))
float rx_buffer[2*buffer_size]; 
for (int i = 0; i <buffer_size; i++) { //generate TX tone
const double pi = acos(-1);
double w = 2 * pi * i * 0.1;
tx_buffer[2*i] = cos(w);
tx_buffer[2*i+1] = sin(w);

}

//Start streaming

LMS_StartStream(&rx_stream);
LMS_StartStream(&tx_stream);

const int send_cnt = int(buffer_size*0.1) / 0.1;
//Streaming
int samplesWrite;
int samplesRead;

auto t1 = chrono::high_resolution_clock::now();
auto t2 = t1;

while (chrono::high_resolution_clock::now() - t1 < chrono::seconds(10)) //run for 10 seconds
{
        

       
        //Receive samples
        samplesRead = LMS_RecvStream(&rx_stream, rx_buffer, buffer_size, nullptr, 1000);
    
   //Send samples 
        
        samplesWrite = LMS_SendStream(&tx_stream, tx_buffer, send_cnt, nullptr, 1000);

    //Print stats every 1s
    if (chrono::high_resolution_clock::now() - t2 > chrono::seconds(1))
    {
        t2 = chrono::high_resolution_clock::now();

        //Print stats
        lms_stream_status_t status;
        LMS_GetStreamStatus(&rx_stream, &status); //Obtain RX stream stats
        cout << "RX rate: " << status.linkRate / 1e6 << " MB/s\n"; //link data rate (both channels))
        // cout << "RX 0 FIFO: " << 100 * status.fifoFilledCount / status.fifoSize << "%" << endl; //percentage of RX 0 fifo filled

        LMS_GetStreamStatus(&tx_stream, &status); //Obtain TX stream stats
        cout << "TX rate: " << status.linkRate / 1e6 << " MB/s\n"; //link data rate (both channels))
        // cout << "TX 0 FIFO: " << 100 * status.fifoFilledCount / status.fifoSize << "%" << endl; //percentage of TX 0 fifo filled
    }
}


//Plot tx samples
GNUPlotPipe gp_tx;
gp_tx.write("set size square\n set xrange[-1:1]\n set yrange[-1:1]\n");
gp_tx.write("plot '-' with points\n");
for (int k = 0; k < samplesWrite; ++k)
    gp_tx.writef("%f %f\n", tx_buffer[2 * k], tx_buffer[2 * k + 1]);
gp_tx.write("e\n");
gp_tx.flush();


//Plot rx samples
GNUPlotPipe gp_rx;
gp_rx.write("set size square\n set xrange[-1:1]\n set yrange[-1:1]\n");
gp_rx.write("plot '-' with points\n");
for (int j = 0; j < samplesRead; ++j)
    gp_rx.writef("%f %f\n", rx_buffer[2 * j], rx_buffer[2 * j + 1]);
gp_rx.write("e\n");
gp_rx.flush();



//Save file
ofstream outfile;
outfile.open("tx_file.txt");
for(int i=0; i < samplesWrite; i++)
{
    outfile << "I[" << 2*i << "]=" << tx_buffer[2*i] << "\t";
    outfile << "Q[" << 2*i+1 << "]=" << tx_buffer[2*i+1] << "\n";
}
outfile.close();

outfile.open("rx_file.txt");
for(int j=0; j < samplesRead; j++)
{
    outfile << "I[" << 2*j << "]=" << rx_buffer[2*j] << "\t";
    outfile << "Q[" << 2*j+1 << "]=" << rx_buffer[2*j+1] << "\n";
}
outfile.close();



//Stop streaming
    LMS_StopStream(&rx_stream); //stream is stopped but can be started again with LMS_StartStream()
    LMS_StopStream(&tx_stream);

    LMS_DestroyStream(device, &rx_stream); //stream is deallocated and can no longer be used
    LMS_DestroyStream(device, &tx_stream);    

//Close device
LMS_Close(device);

return 0;

}

Why does it need to use send_cnt instead of using buffersize directly? Does the sequence of receivestream function and senstream function make sense? I am new here to study and looking forward to your help!

You do not need to use send_cnt - you just have to realize that, although it usually will send and receive the number of samples requested - it sometimes sends or receives less than the number of samples requested - so you need to check the number and buffer as required.

No, the sequence does not make sense.

Thank you very much!