#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!