LMS API example
This page of the documentation shows the usage example using the old LMS API.
More examples written with this API can be found in the src/examples/legacy
directory.
Example dualRXTX
written with the legacy LimeSuite API
1/**
2 @file dualRXTX.cpp
3 @author Lime Microsystems (www.limemicro.com)
4 @brief Dual channel RX/TX example
5 */
6#include "lime/LimeSuite.h"
7#include <iostream>
8#include <chrono>
9
10using namespace std;
11
12//Device structure, should be initialize to NULL
13lms_device_t* device = NULL;
14
15int error()
16{
17 cout << "Error; exiting!" << endl;
18 if (device != NULL)
19 LMS_Close(device);
20 exit(-1);
21}
22
23int main(int argc, char** argv)
24{
25 //Find devices
26 int n;
27 lms_info_str_t list[8]; //should be large enough to hold all detected devices
28 if ((n = LMS_GetDeviceList(list)) < 0) //NULL can be passed to only get number of devices
29 error();
30
31 cout << "Devices found: " << n << endl; //print number of devices
32 if (n < 1)
33 return -1;
34
35 //open the first device
36 if (LMS_Open(&device, list[0], NULL))
37 error();
38
39 //Initialize device with default configuration
40 //Do not use if you want to keep existing configuration
41 //Use LMS_LoadConfig(device, "/path/to/file.ini") to load config from INI
42 if (LMS_Init(device) != 0)
43 error();
44
45 //Get number of channels
46 if ((n = LMS_GetNumChannels(device, LMS_CH_RX)) < 0)
47 error();
48 cout << "Number of RX channels: " << n << endl;
49 if ((n = LMS_GetNumChannels(device, LMS_CH_TX)) < 0)
50 error();
51 cout << "Number of TX channels: " << n << endl;
52
53 //Enable RX channel
54 //Channels are numbered starting at 0
55 if (LMS_EnableChannel(device, LMS_CH_RX, 0, true) != 0)
56 error();
57 if (LMS_EnableChannel(device, LMS_CH_RX, 1, true) != 0)
58 error();
59 //Enable TX channels
60 if (LMS_EnableChannel(device, LMS_CH_TX, 0, true) != 0)
61 error();
62 if (LMS_EnableChannel(device, LMS_CH_TX, 1, true) != 0)
63 error();
64
65 //Set RX center frequency to 1 GHz
66 if (LMS_SetLOFrequency(device, LMS_CH_RX, 0, 1e9) != 0)
67 error();
68 if (LMS_SetLOFrequency(device, LMS_CH_RX, 1, 1e9) != 0)
69 error();
70 //Set TX center frequency to 1.2 GHz
71 //Automatically selects antenna port
72 if (LMS_SetLOFrequency(device, LMS_CH_TX, 0, 1.2e9) != 0)
73 error();
74 if (LMS_SetLOFrequency(device, LMS_CH_TX, 1, 1.2e9) != 0)
75 error();
76
77 //Set sample rate to 10 MHz, preferred oversampling in RF 4x
78 //This set sampling rate for all channels
79 if (LMS_SetSampleRate(device, 10e6, 4) != 0)
80 error();
81
82 //Set RX gain
83 if (LMS_SetNormalizedGain(device, LMS_CH_RX, 0, 0.7) != 0)
84 error();
85 if (LMS_SetNormalizedGain(device, LMS_CH_RX, 1, 0.7) != 0)
86 error();
87 //Set TX gain
88 if (LMS_SetNormalizedGain(device, LMS_CH_TX, 0, 0.4) != 0)
89 error();
90 if (LMS_SetNormalizedGain(device, LMS_CH_TX, 1, 0.4) != 0)
91 error();
92
93 //Enable test signals generation in RX channels
94 //To receive data from RF, remove these lines or change signal to LMS_TESTSIG_NONE
95 if (LMS_SetTestSignal(device, LMS_CH_RX, 0, LMS_TESTSIG_NCODIV4, 0, 0) != 0)
96 error();
97 if (LMS_SetTestSignal(device, LMS_CH_RX, 1, LMS_TESTSIG_NCODIV8F, 0, 0) != 0)
98 error();
99
100 //Streaming Setup
101
102 const int chCount = 2; //number of RX/TX streams
103 lms_stream_t rx_streams[chCount];
104 lms_stream_t tx_streams[chCount];
105 //Initialize streams
106 //All streams setups should be done before starting streams. New streams cannot be set-up if at least stream is running.
107 for (int i = 0; i < chCount; ++i)
108 {
109 rx_streams[i].channel = i; //channel number
110 rx_streams[i].fifoSize = 1024 * 1024; //fifo size in samples
111 rx_streams[i].throughputVsLatency = 0.5; //some middle ground
112 rx_streams[i].isTx = false; //RX channel
113 rx_streams[i].dataFmt = lms_stream_t::LMS_FMT_I12; //12-bit integers
114 if (LMS_SetupStream(device, &rx_streams[i]) != 0)
115 error();
116 tx_streams[i].channel = i; //channel number
117 tx_streams[i].fifoSize = 1024 * 1024; //fifo size in samples
118 tx_streams[i].throughputVsLatency = 0.5; //some middle ground
119 tx_streams[i].isTx = true; //TX channel
120 tx_streams[i].dataFmt = lms_stream_t::LMS_FMT_I12; //12-bit integers
121 if (LMS_SetupStream(device, &tx_streams[i]) != 0)
122 error();
123 }
124
125 //Initialize data buffers
126 const int bufersize = 1024 * 8; //complex samples per buffer
127 int16_t* buffers[chCount];
128 for (int i = 0; i < chCount; ++i)
129 {
130 buffers[i] = new int16_t[bufersize * 2]; //buffer to hold complex values (2*samples))
131 }
132
133 //Start streaming
134 for (int i = 0; i < chCount; ++i)
135 {
136 LMS_StartStream(&rx_streams[i]);
137 LMS_StartStream(&tx_streams[i]);
138 }
139
140 //Streaming
141
142 lms_stream_meta_t rx_metadata; //Use metadata for additional control over sample receive function behavior
143 rx_metadata.flushPartialPacket = false; //currently has no effect in RX
144 rx_metadata.waitForTimestamp = false; //currently has no effect in RX
145
146 lms_stream_meta_t tx_metadata; //Use metadata for additional control over sample send function behavior
147 tx_metadata.flushPartialPacket = false; //do not force sending of incomplete packet
148 tx_metadata.waitForTimestamp = true; //Enable synchronization to HW timestamp
149
150 auto t1 = chrono::high_resolution_clock::now();
151 auto t2 = t1;
152
153 while (chrono::high_resolution_clock::now() - t1 < chrono::seconds(10)) //run for 10 seconds
154 {
155 for (int i = 0; i < chCount; ++i)
156 {
157 int samplesRead;
158 //Receive samples
159 samplesRead = LMS_RecvStream(&rx_streams[i], buffers[i], bufersize, &rx_metadata, 1000);
160
161 //Send samples with 1024*256 sample delay from RX (waitForTimestamp is enabled)
162
163 tx_metadata.timestamp = rx_metadata.timestamp + 1024 * 256;
164 LMS_SendStream(&tx_streams[i], buffers[i], samplesRead, &tx_metadata, 1000);
165 }
166
167 //Print stats every 1s
168 if (chrono::high_resolution_clock::now() - t2 > chrono::seconds(1))
169 {
170 t2 = chrono::high_resolution_clock::now();
171
172 //Print stats
173 lms_stream_status_t status;
174 LMS_GetStreamStatus(rx_streams, &status); //Obtain RX stream stats
175 cout << "RX rate: " << status.linkRate / 1e6 << " MB/s\n"; //link data rate (both channels))
176 cout << "RX 0 FIFO: " << 100 * status.fifoFilledCount / status.fifoSize << "%" << endl; //percentage of RX 0 fifo filled
177
178 LMS_GetStreamStatus(tx_streams, &status); //Obtain TX stream stats
179 cout << "TX rate: " << status.linkRate / 1e6 << " MB/s\n"; //link data rate (both channels))
180 cout << "TX 0 FIFO: " << 100 * status.fifoFilledCount / status.fifoSize << "%" << endl; //percentage of TX 0 fifo filled
181 }
182 }
183
184 //Stop streaming
185 for (int i = 0; i < chCount; ++i)
186 {
187 LMS_StopStream(&rx_streams[i]); //stream is stopped but can be started again with LMS_StartStream()
188 LMS_StopStream(&tx_streams[i]);
189 }
190 for (int i = 0; i < chCount; ++i)
191 {
192 LMS_DestroyStream(device, &rx_streams[i]); //stream is deallocated and can no longer be used
193 LMS_DestroyStream(device, &tx_streams[i]);
194 delete[] buffers[i];
195 }
196
197 //Close device
198 LMS_Close(device);
199
200 return 0;
201}