Skip to content

Instantly share code, notes, and snippets.

@wowa-2017
Created October 17, 2017 17:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wowa-2017/49f15b2e47ad0fb6987a0c37a5d622aa to your computer and use it in GitHub Desktop.
Save wowa-2017/49f15b2e47ad0fb6987a0c37a5d622aa to your computer and use it in GitHub Desktop.
LimeSDR dualRX_01
/**
@file singleRX.cpp
@author Lime Microsystems (www.limemicro.com)
@brief RX example
*/
#include "lime/LimeSuite.h"
#include <iostream>
#include <chrono>
#ifdef USE_GNU_PLOT
#include "gnuPlotPipe.h"
#endif
#include "Writer.h"
using namespace std;
//Device structure, should be initialize to NULL
lms_device_t* device = NULL;
const double Fc = 1e9; // Гц
//const double Fc = 800e6; // Гц
const double Fs = 5e6;
//const double Fs = 8e6;
const double FsOvrFact = 2;
//const double FsOvrFact = 2;
const double Flpw = 120e6;
const int Gain = 10; // дБ
const double TgtTime = 0.1; // секунд
const long TgtSampCnt = TgtTime*Fs;
int error()
{
//print last error message
cout << "ERROR:" << LMS_GetLastErrorMessage();
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 = new lms_info_str_t[n]; //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; //free device list
//Initialize device with default configuration
//Do not use if you want to keep existing configuration
//Use LMS_LoadConfig(device, "/path/to/file.ini") to load config from INI
if (LMS_Init(device) != 0) {
cout << "Init attempt failed (" << LMS_GetLastError() << "): " << LMS_GetLastErrorMessage() << endl;
cout << "Trying to reset..." << endl;
if (LMS_Reset(device) != 0)
error();
cout << "Init attempt 2:" << endl;
if (LMS_Init(device) != 0)
error();
} // if
//Enable RX channel
//Channels are numbered starting at 0
if (LMS_EnableChannel(device, LMS_CH_RX, 0, true) != 0)
error();
if (LMS_EnableChannel(device, LMS_CH_RX, 1, true) != 0)
error();
//Set center frequency to 800 MHz
if (LMS_SetLOFrequency(device, LMS_CH_RX, 0, Fc) != 0)
error();
if (LMS_SetLOFrequency(device, LMS_CH_RX, 1, Fc) != 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";
//select antenna port
lms_name_t antenna_list[10]; //large enough list for antenna names.
//Alternatively, NULL can be passed to LMS_GetAntennaList() to obtain number of antennae
if ((n = LMS_GetAntennaList(device, LMS_CH_RX, 0, antenna_list)) < 0)
error();
cout << "Available antennae:\n"; //print available antennae names
for (int i = 0; i < n; i++)
cout << i << ": " << antenna_list[i] << endl;
if ((n = LMS_GetAntenna(device, LMS_CH_RX, 0)) < 0) //get currently selected antenna index
error();
//print antenna index and name
cout << "Automatically selected antenna: " << n << ": " << antenna_list[n] << endl;
if (LMS_SetAntenna(device, LMS_CH_RX, 0, LMS_PATH_LNAW) != 0) // manually select antenna
error();
if (LMS_SetAntenna(device, LMS_CH_RX, 1, LMS_PATH_LNAW) != 0) // manually select antenna
error();
if ((n = LMS_GetAntenna(device, LMS_CH_RX, 0)) < 0) //get currently selected antenna index
error();
//print antenna index and name
cout << "Manually selected antenna: " << n << ": " << antenna_list[n] << endl;
//Set sample rate to 8 MHz, preferred oversampling in RF 8x
//This set sampling rate for all channels
if (LMS_SetSampleRate(device, Fs, FsOvrFact/*8e6, 8*/) != 0)
error();
//print resulting sampling rates (interface to host , and ADC)
float_type rate, rf_rate;
if (LMS_GetSampleRate(device, LMS_CH_RX, 0, &rate, &rf_rate) != 0) //NULL can be passed
error();
cout << "\nHost interface sample rate: " << rate / 1e6 << " MHz\nRF ADC sample rate: " << rf_rate / 1e6 << "MHz\n\n";
//Example of getting allowed parameter value range
//There are also functions to get other parameter ranges (check LimeSuite.h)
//Get allowed LPF bandwidth range
lms_range_t range;
if (LMS_GetLOFrequencyRange(device, LMS_CH_RX, &range)!=0)
error();
cout << "RX center freq range: " << range.min / 1e6 << " - " << range.max / 1e6 << " MHz\n";
if (LMS_GetSampleRateRange(device, LMS_CH_RX, &range)!=0)
error();
cout << "RX sample rate range: " << range.min / 1e6 << " - " << range.max / 1e6 << " MHz\n";
if (LMS_GetLPFBWRange(device,LMS_CH_RX,&range)!=0)
error();
cout << "RX LPF bandwitdh range: " << range.min / 1e6 << " - " << range.max / 1e6 << " MHz\n\n";
//Configure LPF, bandwidth 8 MHz
if (LMS_SetLPFBW(device, LMS_CH_RX, 0, Flpw) != 0)
error();
if (LMS_SetLPFBW(device, LMS_CH_RX, 1, Flpw) != 0)
error();
//Set RX gain
if (LMS_SetGaindB(device, LMS_CH_RX, 0, Gain) != 0)
error();
if (LMS_SetGaindB(device, LMS_CH_RX, 1, Gain) != 0)
error();
/*if (LMS_SetNormalizedGain(device, LMS_CH_RX, 0, 0) != 0)
error();
if (LMS_SetNormalizedGain(device, LMS_CH_RX, 1, 0) != 0)
error();*/
//Print RX gain
float_type gain; //normalized gain
if (LMS_GetNormalizedGain(device, LMS_CH_RX, 0, &gain) != 0)
error();
cout << "Normalized RX Gain: " << gain << endl;
unsigned int gaindB; //gain in dB
if (LMS_GetGaindB(device, LMS_CH_RX, 0, &gaindB) != 0)
error();
cout << "RX Gain: " << gaindB << " dB" << endl;
//Perform automatic calibration
if (LMS_Calibrate(device, LMS_CH_RX, 0, Flpw, 0) != 0)
error();
if (LMS_Calibrate(device, LMS_CH_RX, 1, Flpw, 0) != 0)
error();/**/
// Switch off DC corrector
if (LMS_WriteParam(device, LMS7_DC_BYP_RXTSP, 1) != 0)
error();
//Enable test signal generation
//To receive data from RF, remove this line or change signal to LMS_TESTSIG_NONE
/*if (LMS_SetTestSignal(device, LMS_CH_RX, 0, LMS_TESTSIG_NONE, 0, 0) != 0)
error();
if (LMS_SetTestSignal(device, LMS_CH_RX, 1, LMS_TESTSIG_NONE, 0, 0) != 0)
error();/**/
/*if (LMS_SetTestSignal(device, LMS_CH_RX, 0, LMS_TESTSIG_NCODIV8, 0, 0) != 0)
error();
if (LMS_SetTestSignal(device, LMS_CH_RX, 1, LMS_TESTSIG_NCODIV8, 0, 0) != 0)
error();*/
if (!wrOpen("f:\\Sig\\lime_trace.dat")) {
cout << "Can't open output file!" << endl;
exit(-1);
} // if
if (!wrWriteSetCrTrHdrProps(pdu_DefLime, round(Fc), round(Fs), TgtSampCnt)) {
cout << "Can't write output file header!" << endl;
exit(-1);
} // if
//Streaming Setup
lms_stream_t::_dataFmt Fmt = lms_stream_t::LMS_FMT_I16;
double ThrVsLat = 1;
//Initialize stream
lms_stream_t streamId[2];
streamId[0].channel = 0; //channel number
streamId[0].fifoSize = 1024 * 1024; //fifo size in samples
streamId[0].throughputVsLatency = 1; //optimize for max throughput
streamId[0].isTx = false; //RX channel
streamId[0].dataFmt = Fmt;
if (LMS_SetupStream(device, &streamId[0]) != 0)
error();
streamId[1].channel = 1; //channel number
streamId[1].fifoSize = 1024 * 1024; //fifo size in samples
streamId[1].throughputVsLatency = 1; //optimize for max throughput
streamId[1].isTx = false; //RX channel
streamId[1].dataFmt = Fmt;
//if (LMS_SetupStream(device, &streamId[1]) != 0)
// error();
//Data buffers
const int bufersize = 50000; //complex samples per buffer
int16_t buffer[2][bufersize * 2]; //must hold I+Q values of each sample
//Start streaming
LMS_StartStream(&streamId[0]);
//LMS_StartStream(&streamId[1]);
auto t1 = chrono::high_resolution_clock::now();
auto t2 = t1;
long SampsWritten = 0;
lms_stream_meta_t rx_md[2]; //Use metadata for additional control over sample receive function behavior
rx_md[0].flushPartialPacket = false; //currently has no effect in RX
rx_md[0].waitForTimestamp = false; //currently has no effect in RX
rx_md[1].flushPartialPacket = false; //currently has no effect in RX
rx_md[1].waitForTimestamp = false; //currently has no effect in RX
lms_stream_status_t st[2];
//while (chrono::high_resolution_clock::now() - t1 < chrono::seconds(3)) //run for 10 seconds
while (SampsWritten < TgtSampCnt) {
int samplesRead[2];
//Receive samples
samplesRead[0] = LMS_RecvStream(&streamId[0], buffer[0], bufersize, &rx_md[0], 1000);
//I and Q samples are interleaved in buffer: IQIQIQ...
//samplesRead[1] = LMS_RecvStream(&streamId[1], buffer[1], bufersize, &rx_md[1], 1000);
LMS_GetStreamStatus(&streamId[0], &st[0]);
//LMS_GetStreamStatus(&streamId[1], &st[1]);
printf("%d/%d samples received at %I64u/%I64u\n", samplesRead[0], samplesRead[1], rx_md[0].timestamp, rx_md[0].timestamp);
printf("ovrrun: %d/%d, drops: %d/%d, samps recvd: %d/%d\n",
st[0].overrun, st[1].overrun, st[0].droppedPackets, st[1].droppedPackets, samplesRead[0], samplesRead[1]);
int Samps2Write = min(TgtSampCnt-SampsWritten, samplesRead[0]);
if (!wrWrite(buffer[0], 2 * Samps2Write * sizeof(__int16))) {
cout << "Can't write samples to output file!" << endl;
exit(-1);
} // if
SampsWritten += Samps2Write;
//Print stats (once per second)
if (chrono::high_resolution_clock::now() - t2 > chrono::milliseconds(500))
{
t2 = chrono::high_resolution_clock::now();
//Get stream status
//LMS_GetStreamStatus(&streamId[0], &st[0]);
//LMS_GetStreamStatus(&streamId[1], &status[1]);
cout << "RX_1 data rate: " << st[0].linkRate / 1e6 << " MB/s\n"; //link data rate
//cout << "RX_2 data rate: " << status[1].linkRate / 1e6 << " MB/s\n"; //link data rate
cout << "RX_1 sample rate: " << st[0].sampleRate / 1e6 << " MSamples/s\n"; //link data rate
//cout << "RX_2 sample rate: " << status[1].sampleRate / 1e6 << " MSamples/s\n"; //link data rate
cout << "RX_1 fifo: " << 100 * st[0].fifoFilledCount / st[0].fifoSize << "%" << endl; //percentage of FIFO filled
//cout << "RX_2 fifo: " << 100 * status[1].fifoFilledCount / status[1].fifoSize << "%" << endl; //percentage of FIFO filled
}
} // while
wrClose();
//Stop streaming
LMS_StopStream(&streamId[0]); //stream is stopped but can be started again with LMS_StartStream()
//LMS_StopStream(&streamId[1]); //stream is stopped but can be started again with LMS_StartStream()
LMS_DestroyStream(device, &streamId[0]); //stream is deallocated and can no longer be used
//LMS_DestroyStream(device, &streamId[1]); //stream is deallocated and can no longer be used
//Close device
LMS_Close(device);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment