kopia lustrzana https://github.com/f4exb/sdrangel
				
				
				
			PlutoSDR input: implemented input class interim state (1)
							rodzic
							
								
									e1c3a66983
								
							
						
					
					
						commit
						7b437e41ba
					
				| 
						 | 
				
			
			@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_ */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue