Add channel configuration and update Lime Suite

interactions

Enhanced the Lime driver by introducing channel selection configuration
which enables specifying the channel to be used within the driver's
processes. Adapted various Lime Suite API calls throughout the
`run_experiment` function to utilize the `LimeCfg.channel` as an
argument, ensuring dynamic channel management. This update facilitates
operations with multi-channel setups and aligns API calls with the new
configuration option. Additionally, improved code comments and removed
redundant TX FIFO slot updates.

Bumped version number to reflect new features and improvements.
This commit is contained in:
Kumi 2024-02-11 08:50:46 +01:00
parent 9271d46756
commit 73abc06d6e
Signed by: kumi
GPG key ID: ECBCC9082395383F
2 changed files with 68 additions and 41 deletions

View file

@ -14,6 +14,7 @@ h5c++ -shlib limedriver.cpp -std=c++11 -lLimeSuite -o limedriver
*/ */
#include "limedriver.h" #include "limedriver.h"
#include <H5PredType.h>
#include <lime/LimeSuite.h> #include <lime/LimeSuite.h>
#include <vector> #include <vector>
@ -192,6 +193,7 @@ 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 = {
{"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},
{"lof", "LO Frequency [Hz]", H5::PredType::IEEE_F32LE, &LimeCfg.frq, 1}, {"lof", "LO Frequency [Hz]", H5::PredType::IEEE_F32LE, &LimeCfg.frq, 1},
{"rlp", "RX LowPass BW [Hz]", H5::PredType::IEEE_F32LE, &LimeCfg.RX_LPF, {"rlp", "RX LowPass BW [Hz]", H5::PredType::IEEE_F32LE, &LimeCfg.RX_LPF,
1}, 1},
@ -397,6 +399,7 @@ LimeConfig_t initializeLimeConfig(int Npulses) {
// modification! // modification!
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.frq = 50e6; // LO carrier frequency LimeCfg.frq = 50e6; // LO carrier frequency
LimeCfg.RX_gain = 20; // total gain of the receiver LimeCfg.RX_gain = 20; // total gain of the receiver
LimeCfg.TX_gain = 30; // total gain of the transmitter LimeCfg.TX_gain = 30; // total gain of the transmitter
@ -852,11 +855,12 @@ int run_experiment(LimeConfig_t LimeCfg,
// 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, 0, &frq_read) != 0) if (LMS_GetLOFrequency(device, LMS_CH_RX, LimeCfg.channel, &frq_read) != 0)
error(); error();
float_type srate_read, rf_rate; float_type srate_read, rf_rate;
if (LMS_GetSampleRate(device, LMS_CH_RX, 0, &srate_read, &rf_rate) != 0) if (LMS_GetSampleRate(device, LMS_CH_RX, LimeCfg.channel, &srate_read,
&rf_rate) != 0)
error(); error();
bool frqdev = fabs(frq_read - LimeCfg.frq) > 1.0; bool frqdev = fabs(frq_read - LimeCfg.frq) > 1.0;
@ -922,7 +926,7 @@ int run_experiment(LimeConfig_t LimeCfg,
// First mute the TX output, as the init commands create a lot of garbage // First mute the TX output, as the init commands create a lot of garbage
if (LMS_WriteParam(device, LMS7_PD_TLOBUF_TRF, 1) != 0) if (LMS_WriteParam(device, LMS7_PD_TLOBUF_TRF, 1) != 0)
error(); error();
if (LMS_SetGaindB(device, LMS_CH_TX, 0, 0) != 0) { if (LMS_SetGaindB(device, LMS_CH_TX, LimeCfg.channel, 0) != 0) {
cout << "Initializing device first!" << endl; cout << "Initializing device first!" << endl;
@ -931,33 +935,44 @@ int run_experiment(LimeConfig_t LimeCfg,
if (LMS_Init(device) != 0) if (LMS_Init(device) != 0)
error(); error();
// retry // retry
if (LMS_SetGaindB(device, LMS_CH_TX, 0, 0) != 0) if (LMS_SetGaindB(device, LMS_CH_TX, LimeCfg.channel, 0) != 0)
error(); error();
} }
if (LMS_SetNormalizedGain(device, LMS_CH_TX, 0, 0.0) != 0) if (LMS_SetNormalizedGain(device, LMS_CH_TX, LimeCfg.channel, 0.0) != 0)
error(); error();
// Set RX center frequency // Set RX center frequency
if (LMS_SetLOFrequency(device, LMS_CH_RX, 0, LimeCfg.frq) != 0) if (LMS_SetLOFrequency(device, LMS_CH_RX, LimeCfg.channel, LimeCfg.frq) !=
0)
error(); error();
// Set TX center frequency // Set TX center frequency
if (LMS_SetLOFrequency(device, LMS_CH_TX, 0, LimeCfg.frq) != 0) if (LMS_SetLOFrequency(device, LMS_CH_TX, LimeCfg.channel, LimeCfg.frq) !=
0)
error(); error();
// Read back the updated frequency for later storage // Read back the updated frequency for later storage
if (LMS_GetLOFrequency(device, LMS_CH_RX, 0, &frq_read) != 0) if (LMS_GetLOFrequency(device, LMS_CH_RX, LimeCfg.channel, &frq_read) != 0)
error(); error();
// Enable RX channel // Enable RX channel
// Channels are numbered starting at 0 // Channels are numbered starting at 0
if (LMS_EnableChannel(device, LMS_CH_RX, 0, true) != 0) if (LMS_EnableChannel(device, LMS_CH_RX, LimeCfg.channel, true) != 0)
error(); error();
// Enable TX channels // Enable TX channels
if (LMS_EnableChannel(device, LMS_CH_TX, 0, true) != 0) if (LMS_EnableChannel(device, LMS_CH_TX, LimeCfg.channel, true) != 0)
error();
// fwd the TX1 LO to TX2
if (LMS_WriteParam(device, LMS7_EN_NEXTTX_TRF, true) != 0)
error();
if (LMS_WriteParam(device, LMS7_EN_NEXTRX_RFE, true) != 0)
error(); error();
// apply DC offset in TxTSP // apply DC offset in TxTSP
if (LMS_WriteParam(device, LMS7_MAC, LimeCfg.channel + 1) != 0)
error();
// if (LMS_WriteParam(device, LMS7_MAC, LimeCfg.channel) != 0) error();
uint16_t DC_I, DC_Q, DC_EN; uint16_t DC_I, DC_Q, DC_EN;
DC_EN = 0; DC_EN = 0;
if (LMS_WriteParam(device, LMS7_DCCORRI_TXTSP, LimeCfg.TX_IcorrDC) != 0) if (LMS_WriteParam(device, LMS7_DCCORRI_TXTSP, LimeCfg.TX_IcorrDC) != 0)
@ -982,8 +997,11 @@ int run_experiment(LimeConfig_t LimeCfg,
// added by me as the IQ calibration did not happen on the chip from python // added by me as the IQ calibration did not happen on the chip from python
// or c++ // or c++
if (LMS_WriteParam(device, LMS7_MAC, 1) != 0) if (LMS_WriteParam(device, LMS7_MAC, LimeCfg.channel + 1) != 0)
error(); error();
// if (LMS_WriteParam(device, LMS7_MAC, LimeCfg.channel) != 0)
// error();
/* /*
// read back DC offset in TxTSP // read back DC offset in TxTSP
if (LMS_ReadParam(device, LMS7_DCCORRI_TXTSP, &DC_I) != 0) error(); if (LMS_ReadParam(device, LMS7_DCCORRI_TXTSP, &DC_I) != 0) error();
@ -999,8 +1017,8 @@ DC_Q << endl;
// Alternatively, NULL can be passed to LMS_GetAntennaList() to obtain // Alternatively, NULL can be passed to LMS_GetAntennaList() to obtain
// number of antennae // number of antennae
int num_antennas; int num_antennas;
if ((num_antennas = if ((num_antennas = LMS_GetAntennaList(device, LMS_CH_RX, LimeCfg.channel,
LMS_GetAntennaList(device, LMS_CH_RX, 0, antenna_list)) < 0) antenna_list)) < 0)
error(); error();
cout << "Available RX LNAs:\n"; // print available antennae names cout << "Available RX LNAs:\n"; // print available antennae names
@ -1008,17 +1026,19 @@ DC_Q << endl;
cout << i << ": " << antenna_list[i] << endl; cout << i << ": " << antenna_list[i] << endl;
// get and print antenna index and name // get and print antenna index and name
int antenna_index; int antenna_index;
if ((antenna_index = LMS_GetAntenna(device, LMS_CH_RX, 0)) < 0) if ((antenna_index = LMS_GetAntenna(device, LMS_CH_RX, LimeCfg.channel)) <
0)
error(); error();
cout << "Automatically selected RX LNA: " << antenna_index << ": " cout << "Automatically selected RX LNA: " << antenna_index << ": "
<< antenna_list[antenna_index] << endl; << antenna_list[antenna_index] << endl;
// manually select antenna // manually select antenna
if (LMS_SetAntenna(device, LMS_CH_RX, 0, LMS_PATH_LNAL) != 0) if (LMS_SetAntenna(device, LMS_CH_RX, LimeCfg.channel, LMS_PATH_LNAL) != 0)
error(); error();
// get and print antenna index and name // get and print antenna index and name
if ((antenna_index = LMS_GetAntenna(device, LMS_CH_RX, 0)) < 0) if ((antenna_index = LMS_GetAntenna(device, LMS_CH_RX, LimeCfg.channel)) <
0)
error(); error();
cout << "Manually selected RX LNA: " << antenna_index << ": " cout << "Manually selected RX LNA: " << antenna_index << ": "
<< antenna_list[antenna_index] << endl; << antenna_list[antenna_index] << endl;
@ -1026,8 +1046,8 @@ DC_Q << endl;
// select antenna port // select antenna port
// Alternatively, NULL can be passed to LMS_GetAntennaList() to obtain // Alternatively, NULL can be passed to LMS_GetAntennaList() to obtain
// number of antennae // number of antennae
if ((num_antennas = if ((num_antennas = LMS_GetAntennaList(device, LMS_CH_TX, LimeCfg.channel,
LMS_GetAntennaList(device, LMS_CH_TX, 0, antenna_list)) < 0) antenna_list)) < 0)
error(); error();
cout << "Available TX pathways:\n"; // print available antennae names cout << "Available TX pathways:\n"; // print available antennae names
@ -1035,20 +1055,23 @@ DC_Q << endl;
cout << i << ": " << antenna_list[i] << endl; cout << i << ": " << antenna_list[i] << endl;
// get and print print antenna index and name // get and print print antenna index and name
if ((antenna_index = LMS_GetAntenna(device, LMS_CH_TX, 0)) < 0) if ((antenna_index = LMS_GetAntenna(device, LMS_CH_TX, LimeCfg.channel)) <
0)
error(); error();
cout << "Automatically selected TX pathway: " << antenna_index << ": " cout << "Automatically selected TX pathway: " << antenna_index << ": "
<< antenna_list[antenna_index] << endl; << antenna_list[antenna_index] << endl;
// manually select antenna // manually select antenna
int mychoice = LMS_PATH_TX1; int tx_path = LMS_PATH_TX1;
if (LimeCfg.frq > 1500e6) if (LimeCfg.frq > 1500e6)
mychoice = LMS_PATH_TX2; tx_path = LMS_PATH_TX2;
if (LMS_SetAntenna(device, LMS_CH_TX, 0, mychoice) != 0)
if (LMS_SetAntenna(device, LMS_CH_TX, LimeCfg.channel, tx_path) != 0)
error(); error();
// get and print print antenna index and name // get and print print antenna index and name
if ((antenna_index = LMS_GetAntenna(device, LMS_CH_TX, 0)) < 0) if ((antenna_index = LMS_GetAntenna(device, LMS_CH_TX, LimeCfg.channel)) <
0)
error(); error();
cout << "Manually selected TX pathway: " << antenna_index << ": " cout << "Manually selected TX pathway: " << antenna_index << ": "
<< antenna_list[antenna_index] << endl; << antenna_list[antenna_index] << endl;
@ -1058,6 +1081,11 @@ DC_Q << endl;
if (LMS_SetSampleRate(device, LimeCfg.srate, 1) != 0) if (LMS_SetSampleRate(device, LimeCfg.srate, 1) != 0)
error(); error();
// Invsinc, which removes that non-causal wiggle in timedomain // Invsinc, which removes that non-causal wiggle in timedomain
// if (LMS_WriteParam(device, LMS7_MAC, chn) != 0) error();
if (LMS_WriteParam(device, LMS7_MAC, LimeCfg.channel + 1) != 0)
error();
if (LMS_WriteParam(device, LMS7_ISINC_BYP_TXTSP, 1) != 0) if (LMS_WriteParam(device, LMS7_ISINC_BYP_TXTSP, 1) != 0)
error(); error();
// CMIX: Disable, as it is not used // CMIX: Disable, as it is not used
@ -1076,9 +1104,9 @@ DC_Q << endl;
error(); error();
// Set RX and TX to the gain values // Set RX and TX to the gain values
if (LMS_SetGaindB(device, LMS_CH_TX, 0, LimeCfg.TX_gain) != 0) if (LMS_SetGaindB(device, LMS_CH_TX, LimeCfg.channel, LimeCfg.TX_gain) != 0)
error(); error();
if (LMS_SetGaindB(device, LMS_CH_RX, 0, LimeCfg.RX_gain) != 0) if (LMS_SetGaindB(device, LMS_CH_RX, LimeCfg.channel, LimeCfg.RX_gain) != 0)
error(); error();
cout << "After gain setting: " << endl; cout << "After gain setting: " << endl;
@ -1126,16 +1154,16 @@ DC_Q << endl;
cout << "TX LPF bandwitdh range: " << range.min / 1e6 << " - " cout << "TX LPF bandwitdh range: " << range.min / 1e6 << " - "
<< range.max / 1e6 << " MHz\n\n"; << range.max / 1e6 << " MHz\n\n";
if (LMS_SetLPFBW(device, LMS_CH_RX, 0, LimeCfg.RX_LPF) != 0) if (LMS_SetLPFBW(device, LMS_CH_RX, LimeCfg.channel, LimeCfg.RX_LPF) != 0)
error(); error();
if (LMS_SetLPFBW(device, LMS_CH_TX, 0, LimeCfg.TX_LPF) != 0) if (LMS_SetLPFBW(device, LMS_CH_TX, LimeCfg.channel, LimeCfg.TX_LPF) != 0)
error(); error();
float_type LPFBW; // lowpass bandwidth float_type LPFBW; // lowpass bandwidth
if (LMS_GetLPFBW(device, LMS_CH_RX, 0, &LPFBW) != 0) if (LMS_GetLPFBW(device, LMS_CH_RX, LimeCfg.channel, &LPFBW) != 0)
error(); error();
cout << "RX LPFBW: " << LPFBW / 1e6 << " MHz" << endl; cout << "RX LPFBW: " << LPFBW / 1e6 << " MHz" << endl;
if (LMS_GetLPFBW(device, LMS_CH_TX, 0, &LPFBW) != 0) if (LMS_GetLPFBW(device, LMS_CH_TX, LimeCfg.channel, &LPFBW) != 0)
error(); error();
cout << "TX LPFBW: " << LPFBW / 1e6 << " MHz" << endl; cout << "TX LPFBW: " << LPFBW / 1e6 << " MHz" << endl;
@ -1189,7 +1217,7 @@ DC_Q << endl;
// All streams setups should be done before starting streams. New streams // All streams setups should be done before starting streams. New streams
// cannot be set-up if at least stream is running. // cannot be set-up if at least stream is running.
for (int ii = 0; ii < chCount; ++ii) { for (int ii = 0; ii < chCount; ++ii) {
rx_streams[ii].channel = ii; // channel number rx_streams[ii].channel = LimeCfg.channel; // channel number
rx_streams[ii].fifoSize = rx_streams[ii].fifoSize =
buffersize * N_buffers_per_fifo; // fifo size in samples buffersize * N_buffers_per_fifo; // fifo size in samples
rx_streams[ii].throughputVsLatency = rx_streams[ii].throughputVsLatency =
@ -1200,7 +1228,7 @@ DC_Q << endl;
if (LMS_SetupStream(device, &rx_streams[ii]) != 0) if (LMS_SetupStream(device, &rx_streams[ii]) != 0)
error(); error();
tx_streams[ii].channel = ii; // channel number tx_streams[ii].channel = LimeCfg.channel; // channel number
tx_streams[ii].fifoSize = tx_streams[ii].fifoSize =
buffersize * N_buffers_per_fifo; // fifo size in samples buffersize * N_buffers_per_fifo; // fifo size in samples
tx_streams[ii].throughputVsLatency = tx_streams[ii].throughputVsLatency =
@ -1768,7 +1796,6 @@ DC_Q << endl;
ii_TXrep++; ii_TXrep++;
// in case the entire experiment fits within the TX FIFO // in case the entire experiment fits within the TX FIFO
if (ii_TXrep == LimeCfg.repetitions) { if (ii_TXrep == LimeCfg.repetitions) {
TXFIFO_slots = 0;
break; break;
} }
} }
@ -1783,7 +1810,6 @@ DC_Q << endl;
ii_TXrep++; ii_TXrep++;
// in case the entire experiment fits within the TX FIFO // in case the entire experiment fits within the TX FIFO
if (ii_TXrep == LimeCfg.repetitions) { if (ii_TXrep == LimeCfg.repetitions) {
TXFIFO_slots = 0;
break; break;
} }
} }
@ -1794,14 +1820,14 @@ DC_Q << endl;
} }
} }
/*
// Check for the TX buffer and keep it filled // Check for the TX buffer and keep it filled
LMS_GetStreamStatus(tx_streams, &status); //Obtain TX stream stats LMS_GetStreamStatus(tx_streams, &status); // Obtain TX stream stats
if (status.fifoFilledCount != 0) cout << TXFIFO_slots <<" TXFIFO slots free if (status.fifoFilledCount != 0)
before start: " << status.fifoFilledCount << " samples of " << status.fifoSize cout << TXFIFO_slots
<< " with HW stamp " << status.timestamp <<" at RX timestamp" << << " TXFIFO slots free before start: " << status.fifoFilledCount
rx_metadata.timestamp << endl; << " samples of " << status.fifoSize << " with HW stamp "
*/ << status.timestamp << " at RX timestamp" << rx_metadata.timestamp
<< endl;
// Main acquisition loop // Main acquisition loop
while (ii_acq < LimeCfg.repetitions * LimeCfg.averages * num_phavar) { while (ii_acq < LimeCfg.repetitions * LimeCfg.averages * num_phavar) {

View file

@ -24,11 +24,12 @@
#include <direct.h> // _mkdir #include <direct.h> // _mkdir
#endif #endif
#define VERSION "0.1.0" #define VERSION "0.2.0"
struct LimeConfig_t { struct LimeConfig_t {
float srate; float srate;
float channel;
float frq; float frq;
float frq_set; float frq_set;
float RX_LPF; float RX_LPF;