mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 01:55:48 -05:00
PlutoSDR input: implemented input class interim state (1)
This commit is contained in:
parent
e1c3a66983
commit
7b437e41ba
@ -19,6 +19,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <iio.h>
|
#include <iio.h>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
#include "deviceplutosdrbox.h"
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,6 +36,15 @@ public:
|
|||||||
int16_t q;
|
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(const std::string& uri);
|
||||||
~DevicePlutoSDRBox();
|
~DevicePlutoSDRBox();
|
||||||
bool isValid() const { return m_valid; }
|
bool isValid() const { return m_valid; }
|
||||||
@ -62,6 +71,8 @@ public:
|
|||||||
std::ptrdiff_t txBufferStep();
|
std::ptrdiff_t txBufferStep();
|
||||||
char* txBufferEnd();
|
char* txBufferEnd();
|
||||||
char* txBufferFirst();
|
char* txBufferFirst();
|
||||||
|
bool getRxSampleRates(SampleRates& sampleRates);
|
||||||
|
bool getTxSampleRates(SampleRates& sampleRates);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct iio_context *m_ctx;
|
struct iio_context *m_ctx;
|
||||||
@ -73,6 +84,8 @@ private:
|
|||||||
struct iio_buffer *m_rxBuf;
|
struct iio_buffer *m_rxBuf;
|
||||||
struct iio_buffer *m_txBuf;
|
struct iio_buffer *m_txBuf;
|
||||||
bool m_valid;
|
bool m_valid;
|
||||||
|
|
||||||
|
bool parseSampleRates(const std::string& rateStr, SampleRates& sampleRates);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DEVICES_PLUTOSDR_DEVICEPLUTOSDRBOX_H_ */
|
#endif /* DEVICES_PLUTOSDR_DEVICEPLUTOSDRBOX_H_ */
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "plutosdr/deviceplutosdrbox.h"
|
#include "plutosdr/deviceplutosdrbox.h"
|
||||||
|
|
||||||
#include "plutosdrinput.h"
|
#include "plutosdrinput.h"
|
||||||
|
#include "plutosdrinputthread.h"
|
||||||
|
|
||||||
#define PLUTOSDR_BLOCKSIZE (1024*1024) //complex samples per buffer
|
#define PLUTOSDR_BLOCKSIZE (1024*1024) //complex samples per buffer
|
||||||
|
|
||||||
@ -33,7 +34,8 @@ PlutoSDRInput::PlutoSDRInput(DeviceSourceAPI *deviceAPI) :
|
|||||||
m_fileSink(0),
|
m_fileSink(0),
|
||||||
m_deviceDescription("PlutoSDR"),
|
m_deviceDescription("PlutoSDR"),
|
||||||
m_running(false),
|
m_running(false),
|
||||||
m_plutoRxBuffer(0)
|
m_plutoRxBuffer(0),
|
||||||
|
m_plutoSDRInputThread(0)
|
||||||
{
|
{
|
||||||
char recFileNameCStr[30];
|
char recFileNameCStr[30];
|
||||||
sprintf(recFileNameCStr, "test_%d.sdriq", m_deviceAPI->getDeviceUID());
|
sprintf(recFileNameCStr, "test_%d.sdriq", m_deviceAPI->getDeviceUID());
|
||||||
@ -60,29 +62,37 @@ bool PlutoSDRInput::start()
|
|||||||
|
|
||||||
// start / stop streaming is done in the thread.
|
// start / stop streaming is done in the thread.
|
||||||
|
|
||||||
// if ((m_limeSDRInputThread = new LimeSDRInputThread(&m_streamId, &m_sampleFifo)) == 0)
|
if ((m_plutoSDRInputThread = new PlutoSDRInputThread(PLUTOSDR_BLOCKSIZE, m_deviceShared.m_deviceParams->getBox(), &m_sampleFifo)) == 0)
|
||||||
// {
|
{
|
||||||
// qFatal("LimeSDRInput::start: cannot create thread");
|
qFatal("PlutoSDRInput::start: cannot create thread");
|
||||||
// stop();
|
stop();
|
||||||
// return false;
|
return false;
|
||||||
// }
|
}
|
||||||
// else
|
else
|
||||||
// {
|
{
|
||||||
// qDebug("LimeSDRInput::start: thread created");
|
qDebug("PlutoSDRInput::start: thread created");
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// m_limeSDRInputThread->setLog2Decimation(m_settings.m_log2SoftDecim);
|
m_plutoSDRInputThread->setLog2Decimation(m_settings.m_log2Decim);
|
||||||
//
|
m_plutoSDRInputThread->startWork();
|
||||||
// m_limeSDRInputThread->startWork();
|
|
||||||
//
|
m_deviceShared.m_thread = m_plutoSDRInputThread;
|
||||||
// m_deviceShared.m_thread = m_limeSDRInputThread;
|
m_running = true;
|
||||||
// m_running = true;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlutoSDRInput::stop()
|
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
|
const QString& PlutoSDRInput::getDeviceDescription() const
|
||||||
@ -102,7 +112,19 @@ quint64 PlutoSDRInput::getCenterFrequency() const
|
|||||||
|
|
||||||
bool PlutoSDRInput::handleMessage(const Message& message)
|
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;
|
MsgFileRecord& conf = (MsgFileRecord&) message;
|
||||||
qDebug() << "PlutoSDRInput::handleMessage: MsgFileRecord: " << conf.getStartStop();
|
qDebug() << "PlutoSDRInput::handleMessage: MsgFileRecord: " << conf.getStartStop();
|
||||||
@ -219,5 +241,91 @@ void PlutoSDRInput::resumeBuddies()
|
|||||||
|
|
||||||
bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool force)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,33 @@
|
|||||||
|
|
||||||
class DeviceSourceAPI;
|
class DeviceSourceAPI;
|
||||||
class FileRecord;
|
class FileRecord;
|
||||||
|
class PlutoSDRInputThread;
|
||||||
|
|
||||||
class PlutoSDRInput : public DeviceSampleSource {
|
class PlutoSDRInput : public DeviceSampleSource {
|
||||||
public:
|
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 {
|
class MsgFileRecord : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
@ -70,6 +94,7 @@ public:
|
|||||||
bool m_running;
|
bool m_running;
|
||||||
DevicePlutoSDRShared m_deviceShared;
|
DevicePlutoSDRShared m_deviceShared;
|
||||||
struct iio_buffer *m_plutoRxBuffer;
|
struct iio_buffer *m_plutoRxBuffer;
|
||||||
|
PlutoSDRInputThread *m_plutoSDRInputThread;
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
|
|
||||||
bool openDevice();
|
bool openDevice();
|
||||||
|
@ -38,6 +38,7 @@ void PlutoSDRInputSettings::resetToDefaults()
|
|||||||
m_lpfBW = 1500000.0f;
|
m_lpfBW = 1500000.0f;
|
||||||
m_lpfFIREnable = false;
|
m_lpfFIREnable = false;
|
||||||
m_lpfFIRBW = 500000.0f;
|
m_lpfFIRBW = 500000.0f;
|
||||||
|
m_lpfFIRlog2Decim = 0;
|
||||||
m_gain = 40;
|
m_gain = 40;
|
||||||
m_antennaPath = RFPATH_A_BAL;
|
m_antennaPath = RFPATH_A_BAL;
|
||||||
m_gainMode = GAIN_MANUAL;
|
m_gainMode = GAIN_MANUAL;
|
||||||
@ -48,6 +49,7 @@ QByteArray PlutoSDRInputSettings::serialize() const
|
|||||||
SimpleSerializer s(1);
|
SimpleSerializer s(1);
|
||||||
|
|
||||||
s.writeS32(1, m_LOppmTenths);
|
s.writeS32(1, m_LOppmTenths);
|
||||||
|
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.writeS32(6, m_rateGovernor);
|
||||||
@ -77,8 +79,15 @@ bool PlutoSDRInputSettings::deserialize(const QByteArray& data)
|
|||||||
if (d.getVersion() == 1)
|
if (d.getVersion() == 1)
|
||||||
{
|
{
|
||||||
int intval;
|
int intval;
|
||||||
|
uint32_t uintval;
|
||||||
|
|
||||||
d.readS32(1, &m_LOppmTenths, 0);
|
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.readU32(4, &m_log2Decim, 0);
|
||||||
d.readS32(5, &intval, 0);
|
d.readS32(5, &intval, 0);
|
||||||
if ((intval < 0) || (intval > 2)) {
|
if ((intval < 0) || (intval > 2)) {
|
||||||
|
@ -58,18 +58,21 @@ struct PlutoSDRInputSettings {
|
|||||||
RATEGOV_END
|
RATEGOV_END
|
||||||
} RateGovernor;
|
} RateGovernor;
|
||||||
|
|
||||||
|
// global settings to be saved
|
||||||
quint64 m_centerFrequency;
|
quint64 m_centerFrequency;
|
||||||
fcPos_t m_fcPos;
|
|
||||||
qint32 m_LOppmTenths;
|
|
||||||
quint32 m_log2Decim;
|
|
||||||
quint64 m_devSampleRate;
|
quint64 m_devSampleRate;
|
||||||
RateGovernor m_rateGovernor;
|
RateGovernor m_rateGovernor;
|
||||||
|
// channel settings
|
||||||
|
fcPos_t m_fcPos;
|
||||||
|
qint32 m_LOppmTenths;
|
||||||
bool m_dcBlock;
|
bool m_dcBlock;
|
||||||
bool m_iqCorrection;
|
bool m_iqCorrection;
|
||||||
float m_lpfBW; //!< analog lowpass filter bandwidth (Hz)
|
quint32 m_log2Decim;
|
||||||
bool m_lpfFIREnable; //!< enable digital lowpass FIR filter
|
float m_lpfBW; //!< analog lowpass filter bandwidth (Hz)
|
||||||
float m_lpfFIRBW; //!< digital lowpass FIR filter bandwidth (Hz)
|
bool m_lpfFIREnable; //!< enable digital lowpass FIR filter
|
||||||
uint32_t m_gain; //!< "hardware" gain
|
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;
|
RFPath m_antennaPath;
|
||||||
GainMode m_gainMode;
|
GainMode m_gainMode;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user