1 /**
2 @file LimeUtil.cpp
3 @author Lime Microsystems
4 @brief Command line test app
5 */
6
7 #include <VersionInfo.h>
8 #include <SystemResources.h>
9 #include <ConnectionRegistry.h>
10 #include <IConnection.h>
11 #include <iostream>
12 #include <cstdlib>
13 #include <ciso646>
14 #include <getopt.h>
15 #include <fstream>
16 #include "Logger.h"
17 #include "LMS64CProtocol.h"
18 #include "lms7_device.h"
19 #include "device_constants.h"
20
21 using namespace lime;
22
23 int deviceTestTiming(const std::string &argStr);
24 int deviceCalSweep(
25 const std::string &argStr,
26 const double start,
27 const double stop,
28 const double step,
29 const double bw,
30 const std::string &dir,
31 const std::string &chans);
32
33 /***********************************************************************
34 * print help
35 **********************************************************************/
printHelp(void)36 static int printHelp(void)
37 {
38 std::cout << "Usage LimeUtil [options]" << std::endl;
39 std::cout << " Options summary:" << std::endl;
40 std::cout << " --help \t\t\t\t Print this help message" << std::endl;
41 std::cout << " --info \t\t\t\t Print module information" << std::endl;
42 std::cout << " --find[=\"module=foo,serial=bar\"] \t Discover available devices" << std::endl;
43 std::cout << " --make[=\"module=foo,serial=bar\"] \t Create a device instance" << std::endl;
44 std::cout << " --force \t\t\t\t Force operaton" << std::endl;
45 std::cout << std::endl;
46 std::cout << " Advanced options:" << std::endl;
47 std::cout << " --args[=\"module=foo,serial=bar\"] \t Arguments for the options below" << std::endl;
48 std::cout << " --update \t\t\t Automatic firmware sync + flash" << std::endl;
49 std::cout << " --fpga=\"filename\" \t\t\t Program FPGA gateware to flash" << std::endl;
50 std::cout << " --fw=\"filename\" \t\t\t Program FX3 firmware to flash" << std::endl;
51 std::cout << " --timing \t\t\t Time interfaces and operations" << std::endl;
52 std::cout << std::endl;
53 std::cout << " Calibrations sweep:" << std::endl;
54 std::cout << " --cal[=\"module=foo,serial=bar\"] \t Calibrate device, optional device args..." << std::endl;
55 std::cout << " --start[=freqStart] \t Frequency start for the sweep(Hz)" << std::endl;
56 std::cout << " --stop[=freqStop] \t Frequency stop for the sweep(Hz)" << std::endl;
57 std::cout << " --step[=freqStep, default=1MHz] \t Frequency step for the sweep(Hz)" << std::endl;
58 std::cout << " --bw[=bandwidth, default=30MHz] \t Desired calibration bandwidth(Hz)" << std::endl;
59 std::cout << " --dir[=direction, default=BOTH] \t Calibration direction, RX, TX, BOTH" << std::endl;
60 std::cout << " --chans[=channels, default=ALL] \t Calibration channels, 0, 1, ALL" << std::endl;
61 std::cout << std::endl;
62 return EXIT_SUCCESS;
63 }
64
65 /***********************************************************************
66 * print info
67 **********************************************************************/
printInfo(void)68 static int printInfo(void)
69 {
70 std::cout << "######################################################" << std::endl;
71 std::cout << "## LimeSuite information summary" << std::endl;
72 std::cout << "######################################################" << std::endl;
73 std::cout << std::endl;
74
75 std::cout << "Version information:" << std::endl;
76 std::cout << " Library version:\tv" << lime::GetLibraryVersion() << std::endl;
77 std::cout << " Build timestamp:\t" << lime::GetBuildTimestamp() << std::endl;
78 std::cout << " Interface version:\tv" << lime::GetAPIVersion() << std::endl;
79 std::cout << " Binary interface:\t" << lime::GetABIVersion() << std::endl;
80 std::cout << std::endl;
81
82 std::cout << "System resources:" << std::endl;
83 std::cout << " Installation root:\t" << lime::getLimeSuiteRoot() << std::endl;
84 std::cout << " User home directory:\t" << lime::getHomeDirectory() << std::endl;
85 std::cout << " App data directory:\t" << lime::getAppDataDirectory() << std::endl;
86 std::cout << " Config directory:\t" << lime::getConfigDirectory() << std::endl;
87 std::cout << " Image search paths:" << std::endl;
88 for (const auto &name : lime::listImageSearchPaths()) std::cout << " - " << name << std::endl;
89 std::cout << std::endl;
90
91 std::cout << "Supported connections:" << std::endl;
92 for (const auto &name : ConnectionRegistry::moduleNames()) std::cout << " * " << name << std::endl;
93 std::cout << std::endl;
94 return EXIT_SUCCESS;
95 }
96
97 /***********************************************************************
98 * find devices
99 **********************************************************************/
findDevices(void)100 static int findDevices(void)
101 {
102 std::string argStr;
103 if (optarg != NULL) argStr = "none," + std::string(optarg);
104 ConnectionHandle hint(argStr);
105
106 auto handles = ConnectionRegistry::findConnections(hint);
107 for (const auto &handle : handles)
108 {
109 std::cout << " * [" << handle.serialize() << "]" << std::endl;
110 }
111
112 std::cout << std::endl;
113 return EXIT_SUCCESS;
114 }
115
116 /***********************************************************************
117 * make a device
118 **********************************************************************/
makeDevice(void)119 static int makeDevice(void)
120 {
121 std::string argStr = "none,";
122 if (optarg != NULL) argStr += optarg;
123 ConnectionHandle handle(argStr);
124
125 std::cout << "Make device " << argStr.substr(5) << std::endl;
126 auto conn = ConnectionRegistry::makeConnection(handle);
127 if (conn == nullptr)
128 {
129 std::cout << "No available device!" << std::endl;
130 return EXIT_FAILURE;
131 }
132 if (not conn->IsOpen())
133 {
134 std::cout << "Connection not open!" << std::endl;
135 ConnectionRegistry::freeConnection(conn);
136 return EXIT_FAILURE;
137 }
138
139 auto info = conn->GetDeviceInfo();
140 std::cout << " Device name: " << info.deviceName << std::endl;
141 std::cout << " Expansion name: " << info.expansionName << std::endl;
142 std::cout << " Firmware version: " << info.firmwareVersion << std::endl;
143 std::cout << " Hardware version: " << info.hardwareVersion << std::endl;
144 std::cout << " Protocol version: " << info.protocolVersion << std::endl;
145 std::cout << " Gateware version: " << info.gatewareVersion << std::endl;
146 std::cout << " Gateware revision: " << info.gatewareRevision << std::endl;
147 std::cout << " Gateware target: " << info.gatewareTargetBoard << std::endl;
148 std::cout << " Serial number: " << std::hex << "0x" << info.boardSerialNumber << std::dec << std::endl;
149
150 std::cout << " Free connection... " << std::flush;
151 ConnectionRegistry::freeConnection(conn);
152 std::cout << "OK" << std::endl;
153 std::cout << std::endl;
154 return EXIT_SUCCESS;
155 }
156
157 /***********************************************************************
158 * Program update (sync images and flash support)
159 **********************************************************************/
programUpdate(const bool force,const std::string & argStr)160 static int programUpdate(const bool force, const std::string &argStr)
161 {
162 auto handles = ConnectionRegistry::findConnections(argStr);
163 if(handles.size() == 0)
164 {
165 std::cout << "No devices found" << std::endl;
166 return EXIT_FAILURE;
167 }
168 std::cout << "Connected to [" << handles[0].ToString() << "]" << std::endl;
169 auto conn = ConnectionRegistry::makeConnection(handles[0]);
170
171 auto progCallback = [](int bsent, int btotal, const char* progressMsg)
172 {
173 printf("[%3i%%] %5i/%5i Bytes %s\r", int(100.0*bsent/btotal+0.5), bsent, btotal, progressMsg);
174 fflush(stdout);
175 return 0;
176 };
177
178 auto status = conn->ProgramUpdate(true/*yes download*/, force, progCallback);
179
180 std::cout << std::endl;
181 if(status == 0)
182 {
183 std::cout << "Programming update complete!" << std::endl;
184 }
185 else
186 {
187 std::cout << "Programming update failed!" << std::endl;
188 }
189
190 ConnectionRegistry::freeConnection(conn);
191 return (status==0)?EXIT_SUCCESS:EXIT_FAILURE;
192 }
193
194 /***********************************************************************
195 * Program gateware
196 **********************************************************************/
programGateware(const std::string & argStr)197 static int programGateware(const std::string &argStr)
198 {
199 //load file
200 std::ifstream file;
201 file.open(optarg, std::ios::in | std::ios::binary);
202 if(not file.good())
203 {
204 std::cout << "File not found: " << optarg << std::endl;
205 return EXIT_FAILURE;
206 }
207
208 std::streampos fileSize;
209 file.seekg(0, std::ios::end);
210 fileSize = file.tellg();
211 file.seekg(0, std::ios::beg);
212 std::vector<char> progData(fileSize, 0);
213 file.read(progData.data(), fileSize);
214
215 auto handles = ConnectionRegistry::findConnections(argStr);
216 if(handles.size() == 0)
217 {
218 std::cout << "No devices found" << std::endl;
219 return EXIT_FAILURE;
220 }
221 std::cout << "Connected to [" << handles[0].ToString() << "]" << std::endl;
222 auto device = LMS7_Device::CreateDevice(handles[0]);
223
224 auto progCallback = [](int bsent, int btotal, const char* progressMsg)
225 {
226 printf("[%3i%%] %5i/%5i Bytes %s\r", int(100.0*bsent/btotal+0.5), bsent, btotal, progressMsg);
227 fflush(stdout);
228 return 0;
229 };
230
231 auto status = device->Program(program_mode::fpgaFlash, progData.data(), progData.size(), progCallback);
232 std::cout << std::endl;
233 if(status != 0)
234 std::cout << "Programming failed!" << std::endl;
235 delete device;
236 return (status==0)?EXIT_SUCCESS:EXIT_FAILURE;
237 }
238
239 /***********************************************************************
240 * Program gateware
241 **********************************************************************/
programFirmware(const std::string & argStr)242 static int programFirmware(const std::string &argStr)
243 {
244 //load file
245 std::ifstream file;
246 file.open(optarg, std::ios::in | std::ios::binary);
247 if(not file.good())
248 {
249 std::cout << "File not found: " << optarg << std::endl;
250 return EXIT_FAILURE;
251 }
252
253 std::streampos fileSize;
254 file.seekg(0, std::ios::end);
255 fileSize = file.tellg();
256 file.seekg(0, std::ios::beg);
257 std::vector<char> progData(fileSize, 0);
258 file.read(progData.data(), fileSize);
259
260 auto handles = ConnectionRegistry::findConnections(argStr);
261 if(handles.size() == 0)
262 {
263 std::cout << "No devices found" << std::endl;
264 return EXIT_FAILURE;
265 }
266 std::cout << "Connected to [" << handles[0].ToString() << "]" << std::endl;
267 auto device = LMS7_Device::CreateDevice(handles[0]);
268
269 auto progCallback = [](int bsent, int btotal, const char* progressMsg)
270 {
271 printf("[%3i%%] %5i/%5i Bytes %s\r", int(100.0*bsent/btotal+0.5), bsent, btotal, progressMsg);
272 fflush(stdout);
273 return 0;
274 };
275
276 auto status = device->Program(program_mode::fx3Flash, progData.data(), progData.size(), progCallback);
277 std::cout << std::endl;
278 if(status != 0)
279 std::cout << "Programming failed!" << std::endl;
280 delete device;
281 return (status==0)?EXIT_SUCCESS:EXIT_FAILURE;
282 }
283
284 /***********************************************************************
285 * main entry point
286 **********************************************************************/
main(int argc,char * argv[])287 int main(int argc, char *argv[])
288 {
289 static struct option long_options[] = {
290 {"help", no_argument, 0, 'h'},
291 {"info", optional_argument, 0, 'i'},
292 {"find", optional_argument, 0, 'f'},
293 {"make", optional_argument, 0, 'm'},
294 {"force", no_argument, 0, 'F'},
295 {"args", optional_argument, 0, 'a'},
296 {"update", no_argument, 0, 'u'},
297 {"fpga", required_argument, 0, 'g'},
298 {"fw", required_argument, 0, 'w'},
299 {"timing", no_argument, 0, 't'},
300 {"cal", optional_argument, 0, 'l'},
301 {"start", required_argument, 0, 's'},
302 {"stop", required_argument, 0, 'p'},
303 {"step", required_argument, 0, 'e'},
304 {"bw", required_argument, 0, 'b'},
305 {"dir", required_argument, 0, 'd'},
306 {"chans", required_argument, 0, 'c'},
307 {0, 0, 0, 0}
308 };
309
310 std::string argStr, dir("BOTH"), chans("ALL");
311 double start(0.0), stop(0.0), step(1e6), bw(30e6);
312 bool testTiming(false), calSweep(false), update(false), force(false);
313 int long_index = 0;
314 int option = 0;
315 while ((option = getopt_long_only(argc, argv, "", long_options, &long_index)) != -1)
316 {
317 switch (option)
318 {
319 case 'h': return printHelp();
320 case 'i': return printInfo();
321 case 'f': return findDevices();
322 case 'm': return makeDevice();
323 case 'a':
324 if (optarg != NULL) argStr = "none," + std::string(optarg);
325 break;
326 case 'u': update = true; break;
327 case 'g': return programGateware(argStr);
328 case 'w': return programFirmware(argStr);
329 case 't': testTiming = true; break;
330 case 'l':
331 calSweep = true;
332 if (optarg != NULL) argStr = "none," + std::string(optarg);
333 break;
334 case 's': if (optarg != NULL) start = std::stod(optarg); break;
335 case 'p': if (optarg != NULL) stop = std::stod(optarg); break;
336 case 'e': if (optarg != NULL) step = std::stod(optarg); break;
337 case 'b': if (optarg != NULL) bw = std::stod(optarg); break;
338 case 'd': if (optarg != NULL) dir = optarg; break;
339 case 'c': if (optarg != NULL) chans = optarg; break;
340 case 'F': force = true; break;
341 }
342 }
343
344 if (testTiming) return deviceTestTiming(argStr);
345 if (calSweep) return deviceCalSweep(argStr, start, stop, step, bw, dir, chans);
346 if (update) return programUpdate(force, argStr);
347
348 //unknown or unspecified options, do help...
349 return printHelp();
350 }
351