PlutoSDR input: implemented input class interim state (1)

This commit is contained in:
f4exb 2017-09-06 18:48:58 +02:00
parent e1c3a66983
commit 7b437e41ba
6 changed files with 217 additions and 27 deletions

View File

@ -19,6 +19,7 @@
#include <cstring>
#include <regex>
#include <iio.h>
#include <boost/lexical_cast.hpp>
#include "deviceplutosdrbox.h"
@ -327,7 +328,38 @@ char* DevicePlutoSDRBox::txBufferFirst()
}
}
bool DevicePlutoSDRBox::parseSampleRates(const std::string& rateStr, SampleRates& sampleRates)
{
// Rx: "BBPLL:983040000 ADC:245760000 R2:122880000 R1:61440000 RF:30720000 RXSAMP:30720000"
// Tx: "BBPLL:983040000 DAC:122880000 T2:122880000 T1:61440000 TF:30720000 TXSAMP:30720000"
std::regex desc_regex("BBPLL:(.+) ..C:(.+) .2:(.+) .1:(.+) .F:(.+) .XSAMP:(.+)");
std::smatch desc_match;
std::regex_search(rateStr, desc_match, desc_regex);
std::string valueStr;
if (desc_match.size() == 7)
{
try
{
sampleRates.m_bbRate = boost::lexical_cast<uint32_t>(desc_match[1]);
sampleRates.m_addaConnvRate = boost::lexical_cast<uint32_t>(desc_match[2]);
sampleRates.m_hb3Rate = boost::lexical_cast<uint32_t>(desc_match[3]);
sampleRates.m_hb2Rate = boost::lexical_cast<uint32_t>(desc_match[4]);
sampleRates.m_hb1Rate = boost::lexical_cast<uint32_t>(desc_match[5]);
sampleRates.m_firRate = boost::lexical_cast<uint32_t>(desc_match[6]);
return true;
}
catch (const boost::bad_lexical_cast &e)
{
qWarning("DevicePlutoSDRBox::parseSampleRates: bad conversion to numeric");
return false;
}
}
else
{
return false;
}
}

View File

@ -36,6 +36,15 @@ public:
int16_t q;
};
struct SampleRates {
uint32_t m_bbRate; //!< Baseband PLL rate (Hz) - used internally
uint32_t m_addaConnvRate; //!< A/D or D/A converter rate (Hz) - this is the HB3 working sample rate
uint32_t m_hb3Rate; //!< Rate of the HB3/(DEC3 or INT3) filter (Rx: out, Tx: in) - this is the HB2 working sample rate
uint32_t m_hb2Rate; //!< Rate of the HB2 filter (Rx: out, Tx: in) - this is the HB1 working sample rate
uint32_t m_hb1Rate; //!< Rate of the HB1 filter (Rx: out, Tx: in) - this is the FIR working sample rate
uint32_t m_firRate; //!< Rate of FIR filter (Rx: out, Tx: in) - this is the host/device communication sample rate
};
DevicePlutoSDRBox(const std::string& uri);
~DevicePlutoSDRBox();
bool isValid() const { return m_valid; }
@ -62,6 +71,8 @@ public:
std::ptrdiff_t txBufferStep();
char* txBufferEnd();
char* txBufferFirst();
bool getRxSampleRates(SampleRates& sampleRates);
bool getTxSampleRates(SampleRates& sampleRates);
private:
struct iio_context *m_ctx;
@ -73,6 +84,8 @@ private:
struct iio_buffer *m_rxBuf;
struct iio_buffer *m_txBuf;
bool m_valid;
bool parseSampleRates(const std::string& rateStr, SampleRates& sampleRates);
};
#endif /* DEVICES_PLUTOSDR_DEVICEPLUTOSDRBOX_H_ */

View File

@ -23,6 +23,7 @@
#include "plutosdr/deviceplutosdrbox.h"
#include "plutosdrinput.h"
#include "plutosdrinputthread.h"
#define PLUTOSDR_BLOCKSIZE (1024*1024) //complex samples per buffer
@ -33,7 +34,8 @@ PlutoSDRInput::PlutoSDRInput(DeviceSourceAPI *deviceAPI) :
m_fileSink(0),
m_deviceDescription("PlutoSDR"),
m_running(false),
m_plutoRxBuffer(0)
m_plutoRxBuffer(0),
m_plutoSDRInputThread(0)
{
char recFileNameCStr[30];
sprintf(recFileNameCStr, "test_%d.sdriq", m_deviceAPI->getDeviceUID());
@ -60,29 +62,37 @@ bool PlutoSDRInput::start()
// start / stop streaming is done in the thread.
// if ((m_limeSDRInputThread = new LimeSDRInputThread(&m_streamId, &m_sampleFifo)) == 0)
// {
// qFatal("LimeSDRInput::start: cannot create thread");
// stop();
// return false;
// }
// else
// {
// qDebug("LimeSDRInput::start: thread created");
// }
//
// m_limeSDRInputThread->setLog2Decimation(m_settings.m_log2SoftDecim);
//
// m_limeSDRInputThread->startWork();
//
// m_deviceShared.m_thread = m_limeSDRInputThread;
// m_running = true;
if ((m_plutoSDRInputThread = new PlutoSDRInputThread(PLUTOSDR_BLOCKSIZE, m_deviceShared.m_deviceParams->getBox(), &m_sampleFifo)) == 0)
{
qFatal("PlutoSDRInput::start: cannot create thread");
stop();
return false;
}
else
{
qDebug("PlutoSDRInput::start: thread created");
}
m_plutoSDRInputThread->setLog2Decimation(m_settings.m_log2Decim);
m_plutoSDRInputThread->startWork();
m_deviceShared.m_thread = m_plutoSDRInputThread;
m_running = true;
return true;
}
void PlutoSDRInput::stop()
{
if (m_plutoSDRInputThread != 0)
{
m_plutoSDRInputThread->stopWork();
delete m_plutoSDRInputThread;
m_plutoSDRInputThread = 0;
}
m_deviceShared.m_thread = 0;
m_running = false;
}
const QString& PlutoSDRInput::getDeviceDescription() const
@ -102,7 +112,19 @@ quint64 PlutoSDRInput::getCenterFrequency() const
bool PlutoSDRInput::handleMessage(const Message& message)
{
if (MsgFileRecord::match(message))
if (MsgConfigurePlutoSDR::match(message))
{
MsgConfigurePlutoSDR& conf = (MsgConfigurePlutoSDR&) message;
qDebug() << "PlutoSDRInput::handleMessage: MsgConfigurePlutoSDR";
if (!applySettings(conf.getSettings(), conf.getForce()))
{
qDebug("PlutoSDRInput::handleMessage config error");
}
return true;
}
else if (MsgFileRecord::match(message))
{
MsgFileRecord& conf = (MsgFileRecord&) message;
qDebug() << "PlutoSDRInput::handleMessage: MsgFileRecord: " << conf.getStartStop();
@ -219,5 +241,91 @@ void PlutoSDRInput::resumeBuddies()
bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool force)
{
bool forwardChangeOwnDSP = false;
bool forwardChangeAllDSP = false;
bool suspendOwnThread = false;
bool ownThreadWasRunning = false;
bool suspendAllOtherThreads = false; // All others means Tx in fact
bool doCalibration = false;
// determine if buddies threads or own thread need to be suspended
// change of global baseband sample rate affecting all buddies can occur if
// - device to host sample rate is changed
// - rate governor is changed
// - FIR filter decimation is changed
if ((m_settings.m_devSampleRate != settings.m_devSampleRate) ||
(m_settings.m_rateGovernor != settings.m_rateGovernor) ||
(m_settings.m_lpfFIRlog2Decim != settings.m_lpfFIRlog2Decim) || force)
{
suspendAllOtherThreads = true;
suspendOwnThread = true;
}
else
{
suspendOwnThread = true;
}
if (suspendAllOtherThreads)
{
const std::vector<DeviceSinkAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
std::vector<DeviceSinkAPI*>::const_iterator itSink = sinkBuddies.begin();
for (; itSink != sinkBuddies.end(); ++itSink)
{
DevicePlutoSDRShared *buddySharedPtr = (DevicePlutoSDRShared *) (*itSink)->getBuddySharedPtr();
if (buddySharedPtr->m_thread) {
buddySharedPtr->m_thread->stopWork();
buddySharedPtr->m_threadWasRunning = true;
}
else
{
buddySharedPtr->m_threadWasRunning = false;
}
}
}
if (suspendOwnThread)
{
if (m_plutoSDRInputThread && m_plutoSDRInputThread->isRunning())
{
m_plutoSDRInputThread->stopWork();
ownThreadWasRunning = true;
}
}
// TODO: apply settings (all cases)
// Change affecting device baseband sample rate potentially affecting all buddies device/host sample rate
if ((m_settings.m_devSampleRate != settings.m_devSampleRate) ||
(m_settings.m_rateGovernor != settings.m_rateGovernor) ||
(m_settings.m_lpfFIRlog2Decim != settings.m_lpfFIRlog2Decim) || force)
{
forwardChangeAllDSP = true;
}
if (suspendAllOtherThreads)
{
const std::vector<DeviceSinkAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
std::vector<DeviceSinkAPI*>::const_iterator itSink = sinkBuddies.begin();
for (; itSink != sinkBuddies.end(); ++itSink)
{
DevicePlutoSDRShared *buddySharedPtr = (DevicePlutoSDRShared *) (*itSink)->getBuddySharedPtr();
if (buddySharedPtr->m_threadWasRunning) {
buddySharedPtr->m_thread->startWork();
}
}
}
if (suspendOwnThread)
{
if (ownThreadWasRunning) {
m_plutoSDRInputThread->startWork();
}
}
return false;
}

View File

@ -27,9 +27,33 @@
class DeviceSourceAPI;
class FileRecord;
class PlutoSDRInputThread;
class PlutoSDRInput : public DeviceSampleSource {
public:
class MsgConfigurePlutoSDR : public Message {
MESSAGE_CLASS_DECLARATION
public:
const PlutoSDRInputSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigurePlutoSDR* create(const PlutoSDRInputSettings& settings, bool force)
{
return new MsgConfigurePlutoSDR(settings, force);
}
private:
MsgConfigurePlutoSDR m_settings;
bool m_force;
MsgConfigurePlutoSDR(const PlutoSDRInputSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
class MsgFileRecord : public Message {
MESSAGE_CLASS_DECLARATION
@ -70,6 +94,7 @@ public:
bool m_running;
DevicePlutoSDRShared m_deviceShared;
struct iio_buffer *m_plutoRxBuffer;
PlutoSDRInputThread *m_plutoSDRInputThread;
QMutex m_mutex;
bool openDevice();

View File

@ -38,6 +38,7 @@ void PlutoSDRInputSettings::resetToDefaults()
m_lpfBW = 1500000.0f;
m_lpfFIREnable = false;
m_lpfFIRBW = 500000.0f;
m_lpfFIRlog2Decim = 0;
m_gain = 40;
m_antennaPath = RFPATH_A_BAL;
m_gainMode = GAIN_MANUAL;
@ -48,6 +49,7 @@ QByteArray PlutoSDRInputSettings::serialize() const
SimpleSerializer s(1);
s.writeS32(1, m_LOppmTenths);
s.writeU32(3, m_lpfFIRlog2Decim);
s.writeU32(4, m_log2Decim);
s.writeS32(5, m_fcPos);
s.writeS32(6, m_rateGovernor);
@ -77,8 +79,15 @@ bool PlutoSDRInputSettings::deserialize(const QByteArray& data)
if (d.getVersion() == 1)
{
int intval;
uint32_t uintval;
d.readS32(1, &m_LOppmTenths, 0);
d.readU32(3, &uintval, 0);
if (uintval > 2) {
m_lpfFIRlog2Decim = 2;
} else {
m_lpfFIRlog2Decim = uintval;
}
d.readU32(4, &m_log2Decim, 0);
d.readS32(5, &intval, 0);
if ((intval < 0) || (intval > 2)) {

View File

@ -58,18 +58,21 @@ struct PlutoSDRInputSettings {
RATEGOV_END
} RateGovernor;
// global settings to be saved
quint64 m_centerFrequency;
fcPos_t m_fcPos;
qint32 m_LOppmTenths;
quint32 m_log2Decim;
quint64 m_devSampleRate;
RateGovernor m_rateGovernor;
// channel settings
fcPos_t m_fcPos;
qint32 m_LOppmTenths;
bool m_dcBlock;
bool m_iqCorrection;
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)
uint32_t m_gain; //!< "hardware" gain
quint32 m_log2Decim;
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)
uint32_t m_gain; //!< "hardware" gain
RFPath m_antennaPath;
GainMode m_gainMode;