1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-09-27 15:26:33 -04:00

PluoSDR: debug (1)

This commit is contained in:
f4exb 2017-09-09 03:09:17 +02:00
parent 3c20b02602
commit aa047c77cc
10 changed files with 523 additions and 187 deletions

View File

@ -19,7 +19,7 @@
const uint64_t DevicePlutoSDR::loLowLimitFreq = 70000000UL; // 70 MHz: take AD9364 specs const uint64_t DevicePlutoSDR::loLowLimitFreq = 70000000UL; // 70 MHz: take AD9364 specs
const uint64_t DevicePlutoSDR::loHighLimitFreq = 6000000000UL; // 6 GHz: take AD9364 specs const uint64_t DevicePlutoSDR::loHighLimitFreq = 6000000000UL; // 6 GHz: take AD9364 specs
const uint32_t DevicePlutoSDR::srLowLimitFreq = 200000; // 200 kS/s const uint32_t DevicePlutoSDR::srLowLimitFreq = 2100000; // 2.1 MS/s empirical
const uint32_t DevicePlutoSDR::srHighLimitFreq = 20000000; // 20 MS/s: take AD9363 speces const uint32_t DevicePlutoSDR::srHighLimitFreq = 20000000; // 20 MS/s: take AD9363 speces
const uint32_t DevicePlutoSDR::bbLPRxLowLimitFreq = 200000; // 200 kHz const uint32_t DevicePlutoSDR::bbLPRxLowLimitFreq = 200000; // 200 kHz

View File

@ -79,6 +79,7 @@ void DevicePlutoSDRBox::set_params(DeviceType devType,
const char *attr = 0; const char *attr = 0;
std::size_t pos; std::size_t pos;
int ret; int ret;
int type;
pos = it->find('='); pos = it->find('=');
@ -101,15 +102,35 @@ void DevicePlutoSDRBox::set_params(DeviceType devType,
if (chn) { if (chn) {
ret = iio_channel_attr_write(chn, attr, val.c_str()); ret = iio_channel_attr_write(chn, attr, val.c_str());
type = 0;
} else if (iio_device_find_attr(dev, attr)) { } else if (iio_device_find_attr(dev, attr)) {
ret = iio_device_attr_write(dev, attr, val.c_str()); ret = iio_device_attr_write(dev, attr, val.c_str());
type = 1;
} else { } else {
ret = iio_device_debug_attr_write(dev, attr, val.c_str()); ret = iio_device_debug_attr_write(dev, attr, val.c_str());
type = 2;
} }
if (ret < 0) if (ret < 0)
{ {
std::cerr << "DevicePlutoSDRBox::set_params: Unable to write attribute " << key << ": " << ret << std::endl; std::string item;
switch (type)
{
case 0:
item = "channel";
break;
case 1:
item = "device";
break;
case 2:
item = "debug";
break;
default:
item = "unknown";
break;
}
std::cerr << "DevicePlutoSDRBox::set_params: Unable to write " << item << " attribute " << key << "=" << val << ": " << ret << std::endl;
} }
} }
} }
@ -352,6 +373,7 @@ bool DevicePlutoSDRBox::getRxSampleRates(SampleRates& sampleRates)
std::string srStr; std::string srStr;
if (get_param(DEVICE_PHY, "rx_path_rates", srStr)) { if (get_param(DEVICE_PHY, "rx_path_rates", srStr)) {
qDebug("DevicePlutoSDRBox::getRxSampleRates: %s", srStr.c_str());
return parseSampleRates(srStr, sampleRates); return parseSampleRates(srStr, sampleRates);
} else { } else {
return false; return false;
@ -382,12 +404,12 @@ bool DevicePlutoSDRBox::parseSampleRates(const std::string& rateStr, SampleRates
{ {
try try
{ {
sampleRates.m_bbRate = boost::lexical_cast<uint32_t>(desc_match[1]) + 1; sampleRates.m_bbRate = boost::lexical_cast<uint32_t>(desc_match[1]);
sampleRates.m_addaConnvRate = boost::lexical_cast<uint32_t>(desc_match[2]) + 1; sampleRates.m_addaConnvRate = boost::lexical_cast<uint32_t>(desc_match[2]);
sampleRates.m_hb3Rate = boost::lexical_cast<uint32_t>(desc_match[3]) + 1; sampleRates.m_hb3Rate = boost::lexical_cast<uint32_t>(desc_match[3]);
sampleRates.m_hb2Rate = boost::lexical_cast<uint32_t>(desc_match[4]) + 1; sampleRates.m_hb2Rate = boost::lexical_cast<uint32_t>(desc_match[4]);
sampleRates.m_hb1Rate = boost::lexical_cast<uint32_t>(desc_match[5]) + 1; sampleRates.m_hb1Rate = boost::lexical_cast<uint32_t>(desc_match[5]);
sampleRates.m_firRate = boost::lexical_cast<uint32_t>(desc_match[6]) + 1; sampleRates.m_firRate = boost::lexical_cast<uint32_t>(desc_match[6]);
return true; return true;
} }
catch (const boost::bad_lexical_cast &e) catch (const boost::bad_lexical_cast &e)
@ -402,65 +424,106 @@ bool DevicePlutoSDRBox::parseSampleRates(const std::string& rateStr, SampleRates
} }
} }
void DevicePlutoSDRBox::setFIR(DeviceUse use, uint32_t intdec, uint32_t bw, int gain) void DevicePlutoSDRBox::setSampleRate(uint32_t sampleRate)
{
char buff[100];
std::vector<std::string> params;
snprintf(buff, sizeof(buff), "in_voltage_sampling_frequency=%d", sampleRate);
params.push_back(std::string(buff));
snprintf(buff, sizeof(buff), "out_voltage_sampling_frequency=%d", sampleRate);
params.push_back(std::string(buff));
set_params(DEVICE_PHY, params); // set end point frequency first
m_devSampleRate = sampleRate;
}
void DevicePlutoSDRBox::setFIR(uint32_t log2IntDec, uint32_t bw, int gain)
{ {
SampleRates sampleRates; SampleRates sampleRates;
std::ostringstream ostr; std::ostringstream ostr;
uint32_t nbTaps; uint32_t nbTaps;
double normalizedBW; double normalizedBW;
uint32_t intdec = 1<<(log2IntDec > 2 ? 2 : log2IntDec);
// set a dummy minimal filter first to get the sample rates right // set a dummy minimal filter first to get the sample rates right
formatFIRHeader(ostr, use, intdec, gain); setFIREnable(false); // disable first
formatFIRHeader(ostr, intdec, gain);
formatFIRCoefficients(ostr, 16, 0.5); formatFIRCoefficients(ostr, 16, 0.5);
setFilter(ostr.str()); setFilter(ostr.str());
ostr.str(""); // reset string stream ostr.str(""); // reset string stream
if (use == USE_RX) setFIREnable(true); // re-enable
{
if (!getRxSampleRates(sampleRates)) {
return;
}
uint32_t nbGroups = sampleRates.m_addaConnvRate / 16; if (!getRxSampleRates(sampleRates)) {
nbTaps = nbGroups*8 > 128 ? 128 : nbGroups*8; return;
normalizedBW = ((float) bw) / sampleRates.m_hb1Rate;
normalizedBW = normalizedBW < 0.1 ? 0.1 : normalizedBW > 0.9 ? 0.9 : normalizedBW;
} }
else
{
if (!getTxSampleRates(sampleRates)) {
return;
}
uint32_t nbGroups = sampleRates.m_addaConnvRate / 16; setFIREnable(false); // disable again
nbTaps = nbGroups*8 > 128 ? 128 : nbGroups*8;
nbTaps = intdec == 1 ? (nbTaps > 64 ? 64 : nbTaps) : nbTaps; uint32_t nbGroups = sampleRates.m_addaConnvRate / 16;
normalizedBW = ((float) bw) / sampleRates.m_hb1Rate; nbTaps = nbGroups*8 > 128 ? 128 : nbGroups*8;
normalizedBW = normalizedBW < 0.1 ? 0.1 : normalizedBW > 0.9 ? 0.9 : normalizedBW; nbTaps = intdec == 1 ? (nbTaps > 64 ? 64 : nbTaps) : nbTaps;
} normalizedBW = ((float) bw) / sampleRates.m_hb1Rate;
normalizedBW = normalizedBW < 0.1 ? 0.1 : normalizedBW > 0.9 ? 0.9 : normalizedBW;
qDebug("DevicePlutoSDRBox::setFIR: intdec: %u gain: %d nbTaps: %u BWin: %u BW: %f (%f)",
intdec,
gain,
nbTaps,
bw,
normalizedBW*sampleRates.m_hb1Rate,
normalizedBW);
// set the right filter // set the right filter
formatFIRHeader(ostr, use, intdec, gain); formatFIRHeader(ostr, intdec, gain);
formatFIRCoefficients(ostr, nbTaps, normalizedBW); formatFIRCoefficients(ostr, nbTaps, normalizedBW);
setFilter(ostr.str()); setFilter(ostr.str());
m_lpfFIRlog2Decim = log2IntDec;
m_lpfFIRBW = bw;
m_lpfFIRGain = gain;
} }
void DevicePlutoSDRBox::formatFIRHeader(std::ostringstream& ostr, DeviceUse use, uint32_t intdec, int32_t gain) void DevicePlutoSDRBox::setFIREnable(bool enable)
{ {
ostr << (use == USE_RX ? "RX 1" : "TX 1") << " GAIN " << gain << " DEC " << intdec << std::endl; char buff[100];
std::vector<std::string> params;
snprintf(buff, sizeof(buff), "in_out_voltage_filter_fir_en=%d", enable ? 1 : 0);
params.push_back(std::string(buff));
set_params(DEVICE_PHY, params);
m_lpfFIREnable = enable;
}
void DevicePlutoSDRBox::setLOPPMTenths(int ppmTenths)
{
char buff[100];
std::vector<std::string> params;
int64_t newXO = m_xoInitial + ((m_xoInitial*ppmTenths) / 10000000L);
snprintf(buff, sizeof(buff), "xo_correction=%ld", newXO);
params.push_back(std::string(buff));
set_params(DEVICE_PHY, params);
m_LOppmTenths = ppmTenths;
}
void DevicePlutoSDRBox::formatFIRHeader(std::ostringstream& ostr,uint32_t intdec, int32_t gain)
{
ostr << "RX 3 GAIN " << gain << " DEC " << intdec << std::endl;
ostr << "TX 3 GAIN " << gain << " INT " << intdec << std::endl;
} }
void DevicePlutoSDRBox::formatFIRCoefficients(std::ostringstream& ostr, uint32_t nbTaps, double normalizedBW) void DevicePlutoSDRBox::formatFIRCoefficients(std::ostringstream& ostr, uint32_t nbTaps, double normalizedBW)
{ {
double *fcoeffs = new double[nbTaps]; double *fcoeffs = new double[nbTaps];
WFIR::BasicFIR(fcoeffs, nbTaps, WFIR::LPF, 0.0, normalizedBW, WFIR::wtBLACKMAN_HARRIS, 0.0); WFIR::BasicFIR(fcoeffs, nbTaps, WFIR::LPF, normalizedBW, 0.0, WFIR::wtBLACKMAN_HARRIS, 0.0);
for (unsigned int i = 0; i < nbTaps; i++) { for (unsigned int i = 0; i < nbTaps; i++) {
ostr << (uint16_t) (fcoeffs[i] * 32768.0) << std::endl; ostr << (int16_t) (fcoeffs[i] * 32768.0) << ", " << (int16_t) (fcoeffs[i] * 32768.0) << std::endl;
} }
delete[] fcoeffs;
} }
void DevicePlutoSDRBox::getXO() void DevicePlutoSDRBox::getXO()
@ -477,4 +540,41 @@ void DevicePlutoSDRBox::getXO()
} }
} }
bool DevicePlutoSDRBox::getRSSI(std::string& rssiStr, unsigned int chan)
{
chan = chan % 2;
char buff[20];
snprintf(buff, sizeof(buff), "in_voltage%d_rssi", chan);
return get_param(DEVICE_PHY, buff, rssiStr);
}
bool DevicePlutoSDRBox::fetchTemp()
{
std::string temp_mC_str;
if (get_param(DEVICE_PHY, "in_temp0_input", temp_mC_str))
{
try
{
uint32_t temp_mC = boost::lexical_cast<uint32_t>(temp_mC_str);
m_temp = temp_mC / 1000.0;
return true;
}
catch (const boost::bad_lexical_cast &e)
{
std::cerr << "PlutoSDRDevice::getTemp: bad conversion to numeric" << std::endl;
return false;
}
}
else
{
return false;
}
}
bool DevicePlutoSDRBox::getRateGovernors(std::string& rateGovernors)
{
return get_param(DEVICE_PHY, "trx_rate_governor", rateGovernors);
}

View File

@ -52,6 +52,13 @@ public:
uint32_t m_firRate; //!< Rate of FIR filter (Rx: out, Tx: in) - this is the host/device communication sample rate uint32_t m_firRate; //!< Rate of FIR filter (Rx: out, Tx: in) - this is the host/device communication sample rate
}; };
uint64_t m_devSampleRate; //!< Host interface sample rate
int32_t m_LOppmTenths; //!< XO correction
bool m_lpfFIREnable; //!< enable digital lowpass FIR filter
float m_lpfFIRBW; //!< digital lowpass FIR filter bandwidth (Hz)
uint32_t m_lpfFIRlog2Decim; //!< digital lowpass FIR filter log2 of decimation factor (0..2)
int m_lpfFIRGain; //!< digital lowpass FIR filter gain (dB)
DevicePlutoSDRBox(const std::string& uri); DevicePlutoSDRBox(const std::string& uri);
~DevicePlutoSDRBox(); ~DevicePlutoSDRBox();
bool isValid() const { return m_valid; } bool isValid() const { return m_valid; }
@ -80,8 +87,14 @@ public:
char* txBufferFirst(); char* txBufferFirst();
bool getRxSampleRates(SampleRates& sampleRates); bool getRxSampleRates(SampleRates& sampleRates);
bool getTxSampleRates(SampleRates& sampleRates); bool getTxSampleRates(SampleRates& sampleRates);
void setFIR(DeviceUse use, uint32_t intdec, uint32_t bw, int gain); void setSampleRate(uint32_t sampleRate);
int64_t getInitialXO() const { return m_xoInitial; } void setFIR(uint32_t intdec, uint32_t bw, int gain);
void setFIREnable(bool enable);
void setLOPPMTenths(int ppmTenths);
bool getRSSI(std::string& rssiStr, unsigned int chan);
bool fetchTemp();
float getTemp() const { return m_temp; }
bool getRateGovernors(std::string& rateGovernors);
private: private:
struct iio_context *m_ctx; struct iio_context *m_ctx;
@ -94,10 +107,11 @@ private:
struct iio_buffer *m_txBuf; struct iio_buffer *m_txBuf;
bool m_valid; bool m_valid;
int64_t m_xoInitial; int64_t m_xoInitial;
float m_temp;
bool parseSampleRates(const std::string& rateStr, SampleRates& sampleRates); bool parseSampleRates(const std::string& rateStr, SampleRates& sampleRates);
void setFilter(const std::string& filterConfigStr); void setFilter(const std::string& filterConfigStr);
void formatFIRHeader(std::ostringstream& str, DeviceUse use, uint32_t intdec, int32_t gain); void formatFIRHeader(std::ostringstream& str, uint32_t intdec, int32_t gain);
void formatFIRCoefficients(std::ostringstream& str, uint32_t nbTaps, double normalizedBW); void formatFIRCoefficients(std::ostringstream& str, uint32_t nbTaps, double normalizedBW);
void getXO(); void getXO();
}; };

View File

@ -28,6 +28,7 @@
#define PLUTOSDR_BLOCKSIZE (1024*1024) //complex samples per buffer (must be multiple of 64) #define PLUTOSDR_BLOCKSIZE (1024*1024) //complex samples per buffer (must be multiple of 64)
MESSAGE_CLASS_DEFINITION(PlutoSDRInput::MsgConfigurePlutoSDR, Message)
MESSAGE_CLASS_DEFINITION(PlutoSDRInput::MsgFileRecord, Message) MESSAGE_CLASS_DEFINITION(PlutoSDRInput::MsgFileRecord, Message)
PlutoSDRInput::PlutoSDRInput(DeviceSourceAPI *deviceAPI) : PlutoSDRInput::PlutoSDRInput(DeviceSourceAPI *deviceAPI) :
@ -38,17 +39,23 @@ PlutoSDRInput::PlutoSDRInput(DeviceSourceAPI *deviceAPI) :
m_plutoRxBuffer(0), m_plutoRxBuffer(0),
m_plutoSDRInputThread(0) m_plutoSDRInputThread(0)
{ {
suspendBuddies();
openDevice();
resumeBuddies();
char recFileNameCStr[30]; char recFileNameCStr[30];
sprintf(recFileNameCStr, "test_%d.sdriq", m_deviceAPI->getDeviceUID()); sprintf(recFileNameCStr, "test_%d.sdriq", m_deviceAPI->getDeviceUID());
m_fileSink = new FileRecord(std::string(recFileNameCStr)); m_fileSink = new FileRecord(std::string(recFileNameCStr));
m_deviceAPI->addSink(m_fileSink); m_deviceAPI->addSink(m_fileSink);
} }
PlutoSDRInput::~PlutoSDRInput() PlutoSDRInput::~PlutoSDRInput()
{ {
m_deviceAPI->removeSink(m_fileSink); m_deviceAPI->removeSink(m_fileSink);
delete m_fileSink; delete m_fileSink;
suspendBuddies();
closeDevice();
resumeBuddies();
} }
bool PlutoSDRInput::start() bool PlutoSDRInput::start()
@ -247,20 +254,21 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo
bool suspendOwnThread = false; bool suspendOwnThread = false;
bool ownThreadWasRunning = false; bool ownThreadWasRunning = false;
bool suspendAllOtherThreads = false; // All others means Tx in fact bool suspendAllOtherThreads = false; // All others means Tx in fact
bool firFilterSet = false;
DevicePlutoSDRBox *plutoBox = m_deviceShared.m_deviceParams->getBox(); DevicePlutoSDRBox *plutoBox = m_deviceShared.m_deviceParams->getBox();
// determine if buddies threads or own thread need to be suspended // determine if buddies threads or own thread need to be suspended
// change of global baseband sample rate affecting all buddies can occur if // changes affecting all buddies can occur if
// - device to host sample rate is changed // - device to host sample rate is changed
// - rate governor is changed
// - FIR filter decimation is changed
// - FIR filter is enabled or disabled // - FIR filter is enabled or disabled
// - FIR filter is changed
// - LO correction is changed
if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || if ((m_settings.m_devSampleRate != settings.m_devSampleRate) ||
(m_settings.m_rateGovernor != settings.m_rateGovernor) || (m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) ||
(m_settings.m_lpfFIRlog2Decim != settings.m_lpfFIRlog2Decim) || (m_settings.m_lpfFIRlog2Decim != settings.m_lpfFIRlog2Decim) ||
(m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) || force) (settings.m_lpfFIRBW != m_settings.m_lpfFIRBW) ||
(settings.m_lpfFIRGain != m_settings.m_lpfFIRGain) ||
(m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force)
{ {
suspendAllOtherThreads = true; suspendAllOtherThreads = true;
suspendOwnThread = true; suspendOwnThread = true;
@ -307,47 +315,16 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo
m_deviceAPI->configureCorrections(settings.m_dcBlock, m_settings.m_iqCorrection); m_deviceAPI->configureCorrections(settings.m_dcBlock, m_settings.m_iqCorrection);
} }
// Change affecting device sample rate chain potentially affecting other buddies device/host sample rate // Change affecting device sample rate chain and other buddies
if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || if ((m_settings.m_devSampleRate != settings.m_devSampleRate) ||
(m_settings.m_rateGovernor != settings.m_rateGovernor) || (m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) ||
(m_settings.m_lpfFIRlog2Decim != settings.m_lpfFIRlog2Decim) || (m_settings.m_lpfFIRlog2Decim != settings.m_lpfFIRlog2Decim) ||
(m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) || force) (settings.m_lpfFIRBW != m_settings.m_lpfFIRBW) ||
(settings.m_lpfFIRGain != m_settings.m_lpfFIRGain) || force)
{ {
std::vector<std::string> params; plutoBox->setSampleRate(settings.m_devSampleRate); // set end point frequency first
params.push_back(QString(tr("in_voltage_sampling_frequency=%1").arg(settings.m_devSampleRate)).toStdString()); plutoBox->setFIR(settings.m_lpfFIRlog2Decim, settings.m_lpfFIRBW, settings.m_lpfFIRGain);
QString rateGovStr; plutoBox->setFIREnable(settings.m_lpfFIREnable); // eventually enable/disable FIR
PlutoSDRInputSettings::translateGovernor(settings.m_rateGovernor, rateGovStr);
params.push_back(QString(tr("trx_rate_governor=%1").arg(rateGovStr)).toStdString());
plutoBox->set_params(DevicePlutoSDRBox::DEVICE_PHY, params); // set end point frequency and rate governor first
// Unless unconditionally forced to change settings change FIR settings if FIR is enabled AND
// - FIR was not enabled before OR
// - Host interface sample rate has changed OR
// - Decimation chain rate governor has changed OR
// - FIR decimation has changed
if ((settings.m_lpfFIREnable && (!m_settings.m_lpfFIREnable
|| (m_settings.m_devSampleRate != settings.m_devSampleRate)
|| (m_settings.m_rateGovernor != settings.m_rateGovernor)
|| (m_settings.m_lpfFIRlog2Decim != settings.m_lpfFIRlog2Decim))) || force)
{
plutoBox->setFIR(DevicePlutoSDRBox::USE_RX, (1<<settings.m_lpfFIRlog2Decim), settings.m_lpfFIRBW, settings.m_lpfFIRGain);
firFilterSet = true;
}
// Reset the filter if gain or bandwidth changes without change to any of the sample rates and not done at previous step
if (((settings.m_lpfFIRBW != m_settings.m_lpfFIRBW) ||
(settings.m_lpfFIRGain != m_settings.m_lpfFIRGain)) && !firFilterSet)
{
plutoBox->setFIR(DevicePlutoSDRBox::USE_RX, (1<<settings.m_lpfFIRlog2Decim), settings.m_lpfFIRBW, settings.m_lpfFIRGain);
firFilterSet = true;
}
if ((m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) || force)
{
params.clear();
params.push_back(QString(tr("in_voltage_filter_fir_en=%1").arg(settings.m_lpfFIREnable ? 1 : 0)).toStdString());
plutoBox->set_params(DevicePlutoSDRBox::DEVICE_PHY, params); // eventually enable/disable FIR
}
plutoBox->getRxSampleRates(m_deviceSampleRates); // pick up possible new rates plutoBox->getRxSampleRates(m_deviceSampleRates); // pick up possible new rates
qDebug() << "PlutoSDRInput::applySettings: BBPLL: " << m_deviceSampleRates.m_bbRate qDebug() << "PlutoSDRInput::applySettings: BBPLL: " << m_deviceSampleRates.m_bbRate
@ -386,9 +363,7 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo
if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force)
{ {
int64_t newXO = plutoBox->getInitialXO() + ((plutoBox->getInitialXO()*settings.m_LOppmTenths) / 10000000L); plutoBox->setLOPPMTenths(settings.m_LOppmTenths);
params.push_back(QString(tr("xo_correction=%1").arg(newXO)).toStdString());
paramsToSet = true;
} }
if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force)
@ -476,5 +451,26 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo
m_deviceAPI->getDeviceInputMessageQueue()->push(notif); m_deviceAPI->getDeviceInputMessageQueue()->push(notif);
} }
return false; return true;
}
void PlutoSDRInput::getRSSI(std::string& rssiStr)
{
DevicePlutoSDRBox *plutoBox = m_deviceShared.m_deviceParams->getBox();
if (!plutoBox->getRSSI(rssiStr, 0)) {
rssiStr = "xxx dB";
}
}
bool PlutoSDRInput::fetchTemperature()
{
DevicePlutoSDRBox *plutoBox = m_deviceShared.m_deviceParams->getBox();
return plutoBox->fetchTemp();
}
float PlutoSDRInput::getTemperature()
{
DevicePlutoSDRBox *plutoBox = m_deviceShared.m_deviceParams->getBox();
return plutoBox->getTemp();
} }

View File

@ -87,6 +87,9 @@ public:
virtual bool handleMessage(const Message& message); virtual bool handleMessage(const Message& message);
uint32_t getADCSampleRate() const { return m_deviceSampleRates.m_addaConnvRate; } uint32_t getADCSampleRate() const { return m_deviceSampleRates.m_addaConnvRate; }
void getRSSI(std::string& rssiStr);
bool fetchTemperature();
float getTemperature();
private: private:
DeviceSourceAPI *m_deviceAPI; DeviceSourceAPI *m_deviceAPI;

View File

@ -15,7 +15,12 @@
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#include <stdio.h> #include <stdio.h>
#include <QDebug>
#include <QMessageBox>
#include "dsp/dspengine.h"
#include "dsp/dspcommands.h"
#include "gui/glspectrum.h"
#include "device/devicesourceapi.h" #include "device/devicesourceapi.h"
#include "plutosdr/deviceplutosdr.h" #include "plutosdr/deviceplutosdr.h"
#include "plutosdrinput.h" #include "plutosdrinput.h"
@ -31,7 +36,9 @@ PlutoSDRInputGui::PlutoSDRInputGui(DeviceSourceAPI *deviceAPI, QWidget* parent)
m_sampleSource(NULL), m_sampleSource(NULL),
m_sampleRate(0), m_sampleRate(0),
m_deviceCenterFrequency(0), m_deviceCenterFrequency(0),
m_lastEngineState((DSPDeviceSourceEngine::State)-1) m_lastEngineState((DSPDeviceSourceEngine::State)-1),
m_doApplySettings(true),
m_statusCounter(0)
{ {
m_sampleSource = new PlutoSDRInput(m_deviceAPI); m_sampleSource = new PlutoSDRInput(m_deviceAPI);
m_deviceAPI->setSource(m_sampleSource); m_deviceAPI->setSource(m_sampleSource);
@ -49,9 +56,12 @@ PlutoSDRInputGui::PlutoSDRInputGui(DeviceSourceAPI *deviceAPI, QWidget* parent)
ui->lpFIR->setColorMapper(ColorMapper(ColorMapper::GrayYellow)); ui->lpFIR->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
ui->lpFIR->setValueRange(5, 1U, 56000U); // will be dynamically recalculated ui->lpFIR->setValueRange(5, 1U, 56000U); // will be dynamically recalculated
ui->hwDecimLabel->setText(QString::fromUtf8("H\u2193"));
ui->swDecimLabel->setText(QString::fromUtf8("S\u2193")); ui->swDecimLabel->setText(QString::fromUtf8("S\u2193"));
blockApplySettings(true);
displaySettings();
blockApplySettings(false);
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
m_statusTimer.start(500); m_statusTimer.start(500);
@ -103,9 +113,10 @@ bool PlutoSDRInputGui::deserialize(const QByteArray& data)
{ {
if(m_settings.deserialize(data)) if(m_settings.deserialize(data))
{ {
// displaySettings(); blockApplySettings(true);
// m_forceSettings = true; displaySettings();
// sendSettings(); blockApplySettings(false);
sendSettings(true);
return true; return true;
} }
else else
@ -115,7 +126,258 @@ bool PlutoSDRInputGui::deserialize(const QByteArray& data)
} }
} }
bool PlutoSDRInputGui::handleMessage(const Message& message) bool PlutoSDRInputGui::handleMessage(const Message& message __attribute__((unused)))
{ {
return false; return false;
} }
void PlutoSDRInputGui::on_startStop_toggled(bool checked)
{
if (checked)
{
if (m_deviceAPI->initAcquisition())
{
m_deviceAPI->startAcquisition();
DSPEngine::instance()->startAudioOutput();
}
}
else
{
m_deviceAPI->stopAcquisition();
DSPEngine::instance()->stopAudioOutput();
}
}
void PlutoSDRInputGui::on_record_toggled(bool checked)
{
if (checked) {
ui->record->setStyleSheet("QToolButton { background-color : red; }");
} else {
ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
}
PlutoSDRInput::MsgFileRecord* message = PlutoSDRInput::MsgFileRecord::create(checked);
m_sampleSource->getInputMessageQueue()->push(message);
}
void PlutoSDRInputGui::on_centerFrequency_changed(quint64 value)
{
m_settings.m_centerFrequency = value * 1000;
sendSettings();
}
void PlutoSDRInputGui::on_loPPM_valueChanged(int value)
{
m_settings.m_LOppmTenths = value;
sendSettings();
}
void PlutoSDRInputGui::on_dcOffset_toggled(bool checked)
{
m_settings.m_dcBlock = checked;
sendSettings();
}
void PlutoSDRInputGui::on_iqImbalance_toggled(bool checked)
{
m_settings.m_iqCorrection = checked;
sendSettings();
}
void PlutoSDRInputGui::on_swDecim_currentIndexChanged(int index)
{
m_settings.m_log2Decim = index > 6 ? 6 : index;
sendSettings();
}
void PlutoSDRInputGui::on_fcPos_currentIndexChanged(int index)
{
m_settings.m_fcPos = (PlutoSDRInputSettings::fcPos_t) (index > 2 ? 2 : index);
sendSettings();
}
void PlutoSDRInputGui::on_sampleRate_changed(quint64 value)
{
m_settings.m_devSampleRate = value;
sendSettings();
}
void PlutoSDRInputGui::on_lpf_changed(quint64 value)
{
m_settings.m_lpfBW = value * 1000;
sendSettings();
}
void PlutoSDRInputGui::on_lpFIREnable_toggled(bool checked)
{
m_settings.m_lpfFIREnable = checked;
sendSettings();
}
void PlutoSDRInputGui::on_lpFIR_changed(quint64 value)
{
m_settings.m_lpfFIRBW = value * 1000;
sendSettings();
}
void PlutoSDRInputGui::on_lpFIRDecimation_currentIndexChanged(int index)
{
m_settings.m_lpfFIRlog2Decim = index > 2 ? 2 : index;
sendSettings();
}
void PlutoSDRInputGui::on_lpFIRGain_currentIndexChanged(int index)
{
m_settings.m_lpfFIRGain = 6*(index > 1 ? 1 : index) - 6;
sendSettings();
}
void PlutoSDRInputGui::on_gainMode_currentIndexChanged(int index)
{
m_settings.m_gainMode = (PlutoSDRInputSettings::GainMode) (index < PlutoSDRInputSettings::GAIN_END ? index : 0);
sendSettings();
}
void PlutoSDRInputGui::on_gain_valueChanged(int value)
{
m_settings.m_gain = value;
sendSettings();
}
void PlutoSDRInputGui::on_antenna_currentIndexChanged(int index)
{
m_settings.m_antennaPath = (PlutoSDRInputSettings::RFPath) (index < PlutoSDRInputSettings::RFPATH_END ? index : 0);
sendSettings();
}
void PlutoSDRInputGui::displaySettings()
{
ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
ui->sampleRate->setValue(m_settings.m_devSampleRate);
ui->dcOffset->setChecked(m_settings.m_dcBlock);
ui->iqImbalance->setChecked(m_settings.m_iqCorrection);
ui->swDecim->setCurrentIndex(m_settings.m_log2Decim);
ui->lpf->setValue(m_settings.m_lpfBW / 1000);
ui->lpFIREnable->setChecked(m_settings.m_lpfFIREnable);
ui->lpFIR->setValue(m_settings.m_lpfFIRBW / 1000);
ui->lpFIRDecimation->setCurrentIndex(m_settings.m_lpfFIRlog2Decim);
ui->lpFIRGain->setCurrentIndex((m_settings.m_lpfFIRGain + 6)/6);
ui->gainMode->setCurrentIndex((int) m_settings.m_gainMode);
ui->gain->setValue(m_settings.m_gain);
ui->gainText->setText(tr("%1").arg(m_settings.m_gain));
ui->antenna->setCurrentIndex((int) m_settings.m_antennaPath);
}
void PlutoSDRInputGui::sendSettings(bool forceSettings)
{
m_forceSettings = forceSettings;
if(!m_updateTimer.isActive()) { m_updateTimer.start(100); }
}
void PlutoSDRInputGui::updateHardware()
{
if (m_doApplySettings)
{
qDebug() << "PlutoSDRInputGui::updateHardware";
PlutoSDRInput::MsgConfigurePlutoSDR* message = PlutoSDRInput::MsgConfigurePlutoSDR::create(m_settings, m_forceSettings);
m_sampleSource->getInputMessageQueue()->push(message);
m_forceSettings = false;
m_updateTimer.stop();
}
}
void PlutoSDRInputGui::blockApplySettings(bool block)
{
m_doApplySettings = !block;
}
void PlutoSDRInputGui::updateStatus()
{
int state = m_deviceAPI->state();
if(m_lastEngineState != state)
{
switch(state)
{
case DSPDeviceSourceEngine::StNotStarted:
ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
break;
case DSPDeviceSourceEngine::StIdle:
ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
break;
case DSPDeviceSourceEngine::StRunning:
ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
break;
case DSPDeviceSourceEngine::StError:
ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
QMessageBox::information(this, tr("Message"), m_deviceAPI->errorMessage());
break;
default:
break;
}
m_lastEngineState = state;
}
if (m_statusCounter % 2 == 0) // 1s
{
uint32_t adcRate = ((PlutoSDRInput *) m_sampleSource)->getADCSampleRate();
if (adcRate < 100000000) {
ui->adcRateLabel->setText(tr("%1k").arg(QString::number(adcRate / 1000.0f, 'g', 5)));
} else {
ui->adcRateLabel->setText(tr("%1M").arg(QString::number(adcRate / 1000000.0f, 'g', 5)));
}
}
if (m_statusCounter % 4 == 0) // 2s
{
std::string rssiStr;
((PlutoSDRInput *) m_sampleSource)->getRSSI(rssiStr);
ui->rssiText->setText(QString::fromStdString(rssiStr));
}
if (m_statusCounter % 10 == 0) // 5s
{
if (m_deviceAPI->isBuddyLeader()) {
((PlutoSDRInput *) m_sampleSource)->fetchTemperature();
}
ui->temperatureText->setText(tr("%1C").arg(QString::number(((PlutoSDRInput *) m_sampleSource)->getTemperature(), 'f', 0)));
}
m_statusCounter++;
}
void PlutoSDRInputGui::handleDSPMessages()
{
Message* message;
while ((message = m_deviceAPI->getDeviceOutputMessageQueue()->pop()) != 0)
{
if (DSPSignalNotification::match(*message))
{
qDebug("LimeSDRInputGUI::handleMessagesToGUI: message: %s", message->getIdentifier());
DSPSignalNotification* notif = (DSPSignalNotification*) message;
m_sampleRate = notif->getSampleRate();
m_deviceCenterFrequency = notif->getCenterFrequency();
qDebug("LimeSDRInputGUI::handleMessagesToGUI: SampleRate: %d, CenterFrequency: %llu", notif->getSampleRate(), notif->getCenterFrequency());
updateSampleRateAndFrequency();
delete message;
}
}
}
void PlutoSDRInputGui::updateSampleRateAndFrequency()
{
m_deviceAPI->getSpectrum()->setSampleRate(m_sampleRate);
m_deviceAPI->getSpectrum()->setCenterFrequency(m_deviceCenterFrequency);
ui->deviceRateLabel->setText(tr("%1k").arg(QString::number(m_sampleRate / 1000.0f, 'g', 5)));
}

View File

@ -60,6 +60,35 @@ private:
int m_sampleRate; int m_sampleRate;
quint64 m_deviceCenterFrequency; //!< Center frequency in device quint64 m_deviceCenterFrequency; //!< Center frequency in device
int m_lastEngineState; int m_lastEngineState;
bool m_doApplySettings;
uint32_t m_statusCounter;
void displaySettings();
void sendSettings(bool forceSettings = false);
void blockApplySettings(bool block);
void updateSampleRateAndFrequency();
private slots:
void on_startStop_toggled(bool checked);
void on_record_toggled(bool checked);
void on_centerFrequency_changed(quint64 value);
void on_loPPM_valueChanged(int value);
void on_dcOffset_toggled(bool checked);
void on_iqImbalance_toggled(bool checked);
void on_swDecim_currentIndexChanged(int index);
void on_fcPos_currentIndexChanged(int index);
void on_sampleRate_changed(quint64 value);
void on_lpf_changed(quint64 value);
void on_lpFIREnable_toggled(bool checked);
void on_lpFIR_changed(quint64 value);
void on_lpFIRDecimation_currentIndexChanged(int index);
void on_lpFIRGain_currentIndexChanged(int index);
void on_gainMode_currentIndexChanged(int index);
void on_gain_valueChanged(int value);
void on_antenna_currentIndexChanged(int index);
void updateHardware();
void updateStatus();
void handleDSPMessages();
}; };
#endif /* PLUGINS_SAMPLESOURCE_PLUTOSDRINPUT_PLUTOSDRINPUTGUI_H_ */ #endif /* PLUGINS_SAMPLESOURCE_PLUTOSDRINPUT_PLUTOSDRINPUTGUI_H_ */

View File

@ -301,42 +301,6 @@
<property name="topMargin"> <property name="topMargin">
<number>2</number> <number>2</number>
</property> </property>
<item>
<widget class="QLabel" name="hwDecimLabel">
<property name="text">
<string>Hw</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="hwDecim">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Hardware decimation governor</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>3</string>
</property>
</item>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="swDecimLabel"> <widget class="QLabel" name="swDecimLabel">
<property name="text"> <property name="text">
@ -613,14 +577,14 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="lpfUnits_2"> <widget class="QLabel" name="lpfFIRUnits">
<property name="text"> <property name="text">
<string>kHz</string> <string>kHz</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QComboBox" name="firDecimation"> <widget class="QComboBox" name="lpFIRDecimation">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>50</width> <width>50</width>
@ -648,7 +612,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QComboBox" name="firGain"> <widget class="QComboBox" name="lpFIRGain">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>50</width> <width>50</width>
@ -658,11 +622,6 @@
<property name="toolTip"> <property name="toolTip">
<string>FIR gain (dB)</string> <string>FIR gain (dB)</string>
</property> </property>
<item>
<property name="text">
<string>-12</string>
</property>
</item>
<item> <item>
<property name="text"> <property name="text">
<string>-6</string> <string>-6</string>
@ -673,11 +632,6 @@
<string>0</string> <string>0</string>
</property> </property>
</item> </item>
<item>
<property name="text">
<string>+6</string>
</property>
</item>
</widget> </widget>
</item> </item>
<item> <item>
@ -704,7 +658,7 @@
<number>2</number> <number>2</number>
</property> </property>
<item> <item>
<widget class="QComboBox" name="gainCtlMode"> <widget class="QComboBox" name="gainMode">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>54</width> <width>54</width>
@ -922,8 +876,17 @@
</item> </item>
<item> <item>
<widget class="QLabel" name="rssiText"> <widget class="QLabel" name="rssiText">
<property name="minimumSize">
<size>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="text"> <property name="text">
<string>-100.0 dB</string> <string>100.00 dB</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -31,13 +31,12 @@ void PlutoSDRInputSettings::resetToDefaults()
m_fcPos = FC_POS_CENTER; m_fcPos = FC_POS_CENTER;
m_LOppmTenths = 0; m_LOppmTenths = 0;
m_log2Decim = 0; m_log2Decim = 0;
m_devSampleRate = 1536 * 1000; m_devSampleRate = 2500 * 1000;
m_rateGovernor = RATEGOV_NORMAL;
m_dcBlock = false; m_dcBlock = false;
m_iqCorrection = false; m_iqCorrection = false;
m_lpfBW = 1500000.0f; m_lpfBW = 1500000.0f;
m_lpfFIREnable = false; m_lpfFIREnable = false;
m_lpfFIRBW = 500000.0f; m_lpfFIRBW = 500000U;
m_lpfFIRlog2Decim = 0; m_lpfFIRlog2Decim = 0;
m_gain = 40; m_gain = 40;
m_antennaPath = RFPATH_A_BAL; m_antennaPath = RFPATH_A_BAL;
@ -53,12 +52,11 @@ QByteArray PlutoSDRInputSettings::serialize() const
s.writeU32(3, m_lpfFIRlog2Decim); s.writeU32(3, m_lpfFIRlog2Decim);
s.writeU32(4, m_log2Decim); s.writeU32(4, m_log2Decim);
s.writeS32(5, m_fcPos); s.writeS32(5, m_fcPos);
s.writeS32(6, m_rateGovernor);
s.writeBool(7, m_dcBlock); s.writeBool(7, m_dcBlock);
s.writeBool(8, m_iqCorrection); s.writeBool(8, m_iqCorrection);
s.writeFloat(9, m_lpfBW); s.writeFloat(9, m_lpfBW);
s.writeBool(10, m_lpfFIREnable); s.writeBool(10, m_lpfFIREnable);
s.writeFloat(11, m_lpfFIRBW); s.writeU32(11, m_lpfFIRBW);
s.writeU64(12, m_devSampleRate); s.writeU64(12, m_devSampleRate);
s.writeU32(13, m_gain); s.writeU32(13, m_gain);
s.writeS32(14, (int) m_antennaPath); s.writeS32(14, (int) m_antennaPath);
@ -97,17 +95,11 @@ bool PlutoSDRInputSettings::deserialize(const QByteArray& data)
} else { } else {
m_fcPos = (fcPos_t) intval; m_fcPos = (fcPos_t) intval;
} }
d.readS32(6, &intval, 0);
if ((intval >= 0) && (intval < (int) RATEGOV_END)) {
m_rateGovernor = (RateGovernor) intval;
} else {
m_rateGovernor = RATEGOV_NORMAL;
}
d.readBool(7, &m_dcBlock, false); d.readBool(7, &m_dcBlock, false);
d.readBool(8, &m_iqCorrection, false); d.readBool(8, &m_iqCorrection, false);
d.readFloat(9, &m_lpfBW, 1500000.0f); d.readFloat(9, &m_lpfBW, 1500000.0f);
d.readBool(10, &m_lpfFIREnable, false); d.readBool(10, &m_lpfFIREnable, false);
d.readFloat(11, &m_lpfFIRBW, 500000.0f); d.readU32(11, &m_lpfFIRBW, 500000U);
d.readU64(12, &m_devSampleRate, 1536000U); d.readU64(12, &m_devSampleRate, 1536000U);
d.readU32(13, &m_gain, 40); d.readU32(13, &m_gain, 40);
d.readS32(14, &intval, 0); d.readS32(14, &intval, 0);
@ -132,22 +124,6 @@ bool PlutoSDRInputSettings::deserialize(const QByteArray& data)
} }
} }
void PlutoSDRInputSettings::translateGovernor(RateGovernor gov, QString& s)
{
switch(gov)
{
case RATEGOV_NORMAL:
s = "normal";
break;
case RATEGOV_HIGHOSR:
s = "highest_osr";
break;
default:
s = "highest_osr";
break;
}
}
void PlutoSDRInputSettings::translateRFPath(RFPath path, QString& s) void PlutoSDRInputSettings::translateRFPath(RFPath path, QString& s)
{ {
switch(path) switch(path)

View File

@ -52,27 +52,21 @@ struct PlutoSDRInputSettings {
GAIN_END GAIN_END
} GainMode; } GainMode;
typedef enum {
RATEGOV_NORMAL,
RATEGOV_HIGHOSR,
RATEGOV_END
} RateGovernor;
// global settings to be saved // global settings to be saved
quint64 m_centerFrequency; quint64 m_centerFrequency;
quint64 m_devSampleRate; // common device settings
RateGovernor m_rateGovernor; quint64 m_devSampleRate; //!< Host interface sample rate
// channel settings qint32 m_LOppmTenths; //!< XO correction
bool m_lpfFIREnable; //!< enable digital lowpass FIR filter
quint32 m_lpfFIRBW; //!< digital lowpass FIR filter bandwidth (Hz)
quint32 m_lpfFIRlog2Decim; //!< digital lowpass FIR filter log2 of decimation factor (0..2)
int m_lpfFIRGain; //!< digital lowpass FIR filter gain (dB)
// individual channel settings
fcPos_t m_fcPos; fcPos_t m_fcPos;
qint32 m_LOppmTenths;
bool m_dcBlock; bool m_dcBlock;
bool m_iqCorrection; bool m_iqCorrection;
quint32 m_log2Decim; quint32 m_log2Decim;
float m_lpfBW; //!< analog lowpass filter bandwidth (Hz) float m_lpfBW; //!< analog lowpass filter bandwidth (Hz)
bool m_lpfFIREnable; //!< enable digital lowpass FIR filter
float m_lpfFIRBW; //!< digital lowpass FIR filter bandwidth (Hz)
quint32 m_lpfFIRlog2Decim; //!< digital lowpass FIR filter log2 of decimation factor (0..2)
int m_lpfFIRGain; //!< digital lowpass FIR filter gain (dB)
uint32_t m_gain; //!< "hardware" gain uint32_t m_gain; //!< "hardware" gain
RFPath m_antennaPath; RFPath m_antennaPath;
GainMode m_gainMode; GainMode m_gainMode;
@ -82,7 +76,6 @@ struct PlutoSDRInputSettings {
void resetToDefaults(); void resetToDefaults();
QByteArray serialize() const; QByteArray serialize() const;
bool deserialize(const QByteArray& data); bool deserialize(const QByteArray& data);
static void translateGovernor(RateGovernor gov, QString& s);
static void translateRFPath(RFPath path, QString& s); static void translateRFPath(RFPath path, QString& s);
static void translateGainMode(GainMode mod, QString& s); static void translateGainMode(GainMode mod, QString& s);
}; };