Implement auto-device selection and enhance

channel handling

Refactored code to improve usability and error handling by implementing
automatic device selection when no device is explicitly specified. New
functionalities include opening devices based on provided info, and a
more robust way to retrieve and validate the number of RX and TX
channels. These changes streamline the device and channel setup process,
especially for systems with a single connected device.

- Introduced `openDevice` to encapsulate device opening logic with
fallback to the first available device.
- Added `getDeviceChannels` and `getChannelsFromInfo` for retrieving
channel information.
- Ensured LimeConfig struct now includes a `device` field to store the
selected device.
- Modified experiment setup to automatically select a device if not
configured and validate channel availability.
- Updated HDF attribute population to include device information.

These improvements should reduce the likelihood of user errors and
simplify the configuration process when working with LimeSDR devices.
This commit is contained in:
Kumi 2024-02-17 16:45:59 +01:00
parent 74c6bd6904
commit aed7255801
Signed by: kumi
GPG key ID: ECBCC9082395383F
2 changed files with 71 additions and 10 deletions

View file

@ -114,6 +114,48 @@ std::vector<string> getDeviceList() {
return deviceList; return deviceList;
} }
lms_device_t *openDevice(const std::string &info) {
// Open the device with the given info string
string info_string = info;
if (info_string.empty()) {
std::vector<string> deviceList = getDeviceList();
if (deviceList.size() == 0) {
std::cout << "No devices found" << std::endl;
error();
}
info_string = deviceList[0];
}
lms_device_t *dev = NULL;
if (LMS_Open(&dev, info.c_str(), NULL)) {
error();
}
return dev;
}
std::pair<int, int> getDeviceChannels(lms_device_t *dev) {
// Get the number of RX and TX channels of the device
lms_info_str_t list[10];
int rx = LMS_GetNumChannels(dev, LMS_CH_RX);
int tx = LMS_GetNumChannels(dev, LMS_CH_TX);
return std::make_pair(rx, tx);
}
std::pair<int, int> getChannelsFromInfo(const std::string &info) {
// Get the number of RX and TX channels from the device info string
lms_device_t *dev = openDevice(info);
std::pair<int, int> values = getDeviceChannels(dev);
LMS_Close(dev);
return values;
}
// Custom function to read back the gain of the RX/TX channels. The API function // Custom function to read back the gain of the RX/TX channels. The API function
// GetGaindB has to be avoided, as it also modifies the gain, which is useless // GetGaindB has to be avoided, as it also modifies the gain, which is useless
// and dangerous.. // and dangerous..
@ -192,6 +234,9 @@ int GetGainRXTX(int *RXgain, int *TXgain) {
std::vector<Config2HDFattr_t> getHDFAttributes(LimeConfig_t &LimeCfg) { std::vector<Config2HDFattr_t> getHDFAttributes(LimeConfig_t &LimeCfg) {
std::vector<Config2HDFattr_t> HDFattr = { std::vector<Config2HDFattr_t> HDFattr = {
{"dev", "Device",
H5::StrType(H5::PredType::C_S1, LimeCfg.device.length() + 1),
(void *)LimeCfg.device.c_str(), 1},
{"sra", "SampleRate [Hz]", H5::PredType::IEEE_F32LE, &LimeCfg.srate, 1}, {"sra", "SampleRate [Hz]", H5::PredType::IEEE_F32LE, &LimeCfg.srate, 1},
{"chn", "Channel", H5::PredType::NATIVE_INT, &LimeCfg.channel, 1}, {"chn", "Channel", H5::PredType::NATIVE_INT, &LimeCfg.channel, 1},
{"rmt", "RX Matching", H5::PredType::NATIVE_INT, &LimeCfg.RX_matching, 1}, {"rmt", "RX Matching", H5::PredType::NATIVE_INT, &LimeCfg.RX_matching, 1},
@ -400,6 +445,8 @@ LimeConfig_t initializeLimeConfig(int Npulses) {
// Set all the DEFAULT parameters. Command line arguments allow for // Set all the DEFAULT parameters. Command line arguments allow for
// modification! // modification!
LimeCfg.device = "";
LimeCfg.srate = 30.72e6; // sample rate of the IF DAC/ADC LimeCfg.srate = 30.72e6; // sample rate of the IF DAC/ADC
LimeCfg.channel = 0; // channel to use, LimeCfg.channel = 0; // channel to use,
LimeCfg.RX_matching = 0; // RX matching network - 0 to use previous logic LimeCfg.RX_matching = 0; // RX matching network - 0 to use previous logic
@ -830,19 +877,33 @@ int run_experiment(LimeConfig_t LimeCfg,
if (list.size() < 1) if (list.size() < 1)
return -1; return -1;
if (LimeCfg.device == "") {
LimeCfg.device = list[0];
cout << "Automatically selecting device: " << LimeCfg.device << endl;
}
// open the first device // open the first device
if (LMS_Open(&device, list[0].c_str(), NULL)) if (LMS_Open(&device, LimeCfg.device.c_str(), NULL))
error(); error();
// Get number of channels // Get number of channels
int num_rx_channels, num_tx_channels; std::pair <int, int> num_channels = getDeviceChannels(device);
if ((num_rx_channels = LMS_GetNumChannels(device, LMS_CH_RX)) < 0) int num_rx_channels = num_channels.first;
error(); int num_tx_channels = num_channels.second;
cout << "Number of RX channels: " << num_rx_channels << endl; cout << "Number of RX channels: " << num_rx_channels << endl;
if ((num_tx_channels = LMS_GetNumChannels(device, LMS_CH_TX)) < 0)
error();
cout << "Number of TX channels: " << num_tx_channels << endl; cout << "Number of TX channels: " << num_tx_channels << endl;
if (num_rx_channels < 1 || num_tx_channels < 1) {
cout << "No RX or TX channels found!" << endl;
error();
}
// Check if the channel selected in the config is valid
if (LimeCfg.channel < 0 || LimeCfg.channel >= num_rx_channels) {
cout << "Invalid channel selected: " << LimeCfg.channel << endl;
error();
}
// check if the settings are already there // check if the settings are already there
float_type frq_read; float_type frq_read;
if (LMS_GetLOFrequency(device, LMS_CH_RX, LimeCfg.channel, &frq_read) != 0) if (LMS_GetLOFrequency(device, LMS_CH_RX, LimeCfg.channel, &frq_read) != 0)
@ -1028,8 +1089,7 @@ DC_Q << endl;
error(); error();
// get and print antenna index and name // get and print antenna index and name
if ((rx_path = LMS_GetAntenna(device, LMS_CH_RX, LimeCfg.channel)) < if ((rx_path = LMS_GetAntenna(device, LMS_CH_RX, LimeCfg.channel)) < 0)
0)
error(); error();
cout << "Manually selected RX LNA: " << rx_path << ": " cout << "Manually selected RX LNA: " << rx_path << ": "
<< antenna_list[rx_path] << endl; << antenna_list[rx_path] << endl;
@ -1060,8 +1120,7 @@ DC_Q << endl;
error(); error();
// get and print print antenna index and name // get and print print antenna index and name
if ((tx_path = LMS_GetAntenna(device, LMS_CH_TX, LimeCfg.channel)) < if ((tx_path = LMS_GetAntenna(device, LMS_CH_TX, LimeCfg.channel)) < 0)
0)
error(); error();
cout << "Manually selected TX pathway: " << tx_path << ": " cout << "Manually selected TX pathway: " << tx_path << ": "
<< antenna_list[tx_path] << endl; << antenna_list[tx_path] << endl;

View file

@ -28,6 +28,8 @@
struct LimeConfig_t { struct LimeConfig_t {
std::string device;
float srate; float srate;
int channel; int channel;
int RX_matching; int RX_matching;