Beispiel #1
0
SoapySDR::RangeList SoapySDRPlay::getFrequencyRange(const int direction, const size_t channel, const std::string &name) const
{
    SoapySDR::RangeList rl;
    if (name == "RF")
    {
        rl.push_back(SoapySDR::Range(100000.0,2000000000.0));
    }
    return rl;
}
void SoapyRPCUnpacker::operator&(SoapySDR::RangeList &value)
{
    UNPACK_TYPE_HELPER(SOAPY_REMOTE_RANGE_LIST);
    int size = 0;
    *this & size;
    value.resize(size);
    for (size_t i = 0; i < size_t(size); i++) *this & value[i];
}
void SoapySDRInputGui::createRangesControl(
        ItemSettingGUI **settingGUI,
        const SoapySDR::RangeList& rangeList,
        const QString& text,
        const QString& unit)
{
    if (rangeList.size() == 0) { // return early if the range list is empty
        return;
    }

    bool rangeDiscrete = true; // discretes values
    bool rangeInterval = true; // intervals

    for (const auto &it : rangeList)
    {
        if (it.minimum() != it.maximum()) {
            rangeDiscrete = false;
        } else {
            rangeInterval = false;
        }
    }

    if (rangeDiscrete)
    {
        DiscreteRangeGUI *rangeGUI = new DiscreteRangeGUI(this);
        rangeGUI->setLabel(text);
        rangeGUI->setUnits(QString("k%1").arg(unit));

        for (const auto &it : rangeList) {
            rangeGUI->addItem(QString("%1").arg(QString::number(it.minimum()/1000.0, 'f', 0)), it.minimum());
        }

        *settingGUI = rangeGUI;
        QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
        layout->addWidget(rangeGUI);
    }
    else if (rangeInterval)
    {
        IntervalRangeGUI *rangeGUI = new IntervalRangeGUI(ui->scrollAreaWidgetContents);
        rangeGUI->setLabel(text);
        rangeGUI->setUnits(unit);

        for (const auto &it : rangeList) {
            rangeGUI->addInterval(it.minimum(), it.maximum());
        }

        rangeGUI->reset();

        *settingGUI = rangeGUI;
        QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
        layout->addWidget(rangeGUI);
    }
}
Beispiel #4
0
SoapySDR::RangeList SoapySDR::Device::getFrequencyRange(const int dir, const size_t chan) const
{
    //get a list of tunable components
    const std::vector<std::string> comps = this->listFrequencies(dir, chan);
    if (comps.empty()) return SoapySDR::RangeList();

    //get the range list for the RF component
    SoapySDR::RangeList ranges = this->getFrequencyRange(dir, chan, comps.front());

    //use bandwidth setting to clip the range
    const double bw = this->getBandwidth(dir, chan);

    //add to the range list given subsequent components
    for (size_t comp_i = 1; comp_i < comps.size(); comp_i++)
    {
        SoapySDR::RangeList subRange = this->getFrequencyRange(dir, chan, comps[comp_i]);
        if (subRange.empty()) continue;

        double subRangeLow = subRange.front().minimum();
        if (bw > 0.0) subRangeLow = std::max(-bw/2, subRangeLow);

        double subRangeHigh = subRange.back().maximum();
        if (bw > 0.0) subRangeHigh = std::min(bw/2, subRangeHigh);

        for (size_t range_i = 0; range_i < ranges.size(); range_i++)
        {
            SoapySDR::Range &range = ranges[range_i];
            range = SoapySDR::Range(
                range.minimum() + subRangeLow,
                range.maximum() + subRangeHigh);
        }
    }

    return ranges;
}
Beispiel #5
0
SoapySDR::ArgInfoList SoapySDR::Device::getFrequencyArgsInfo(const int dir, const size_t chan) const
{
    SoapySDR::ArgInfoList args;

    const std::vector<std::string> comps = this->listFrequencies(dir, chan);

    if (comps.size() < 2) return args; //no tuning options with single components

    //support offset tuning
    {
        SoapySDR::ArgInfo info;
        info.key = "OFFSET";
        info.name = "LO Offset";
        info.value = "0.0";
        info.units = "Hz";
        info.type = SoapySDR::ArgInfo::FLOAT;
        info.description = "Tune the LO with an offset and compensate with the baseband CORDIC.";
        SoapySDR::RangeList ranges = this->getFrequencyRange(dir, chan, comps.at(1));
        if (not ranges.empty()) info.range = ranges.front();
        args.push_back(info);
    }

    //every tunable component becomes an option
    for (size_t comp_i = 1; comp_i < comps.size(); comp_i++)
    {
        SoapySDR::ArgInfo info;
        info.key = comps[comp_i];
        info.value = "DEFAULT";
        info.units = "Hz";
        info.type = SoapySDR::ArgInfo::FLOAT;
        info.description = "Specify a specific value for this component or IGNORE to skip tuning it.";
        info.options.push_back("DEFAULT");
        info.optionNames.push_back("Default");
        info.options.push_back("IGNORE");
        info.optionNames.push_back("Ingore");
        SoapySDR::RangeList ranges = this->getFrequencyRange(dir, chan, comps.at(comp_i));
        if (not ranges.empty()) info.range = ranges.front();
        args.push_back(info);
    }

    return args;
}
Beispiel #6
0
std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remoteAddr, bool noInit) {

    if (SDREnumerator::devs[remoteAddr].size()) {
        return &SDREnumerator::devs[remoteAddr];
    }
    
    if (noInit) {
        return NULL;
    }
    
    if (!soapy_initialized) {
        std::cout << "SoapySDR init.." << std::endl;
        std::cout << "\tAPI Version: v" << SoapySDR::getAPIVersion() << std::endl;
        std::cout << "\tABI Version: v" << SoapySDR::getABIVersion() << std::endl;
        std::cout << "\tInstall root: " << SoapySDR::getRootPath() << std::endl;
        
        std::cout << "\tLoading modules... " << std::endl;
        
        std::string userModPath = wxGetApp().getModulePath();
        
        if (userModPath != "") {
            wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Loading SoapySDR modules from " + userModPath + "..");
            std::vector<std::string> localMods = SoapySDR::listModules(userModPath);
            for (std::vector<std::string>::iterator mods_i = localMods.begin(); mods_i != localMods.end(); mods_i++) {
                wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Initializing user specified SoapySDR module " + (*mods_i) + "..");
                std::cout << "Initializing user specified SoapySDR module " << (*mods_i) <<  ".." << std::endl;
                SoapySDR::loadModule(*mods_i);
            }
        } else {
            #ifdef BUNDLE_SOAPY_MODS
            bool localModPref = wxGetApp().getUseLocalMod();
            if (localModPref) {
                wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Loading SoapySDR modules..");
                std::cout << "Checking local system SoapySDR modules.." << std::flush;
                SoapySDR::loadModules();
            }

            wxFileName exePath = wxFileName(wxStandardPaths::Get().GetExecutablePath());
            std::vector<std::string> localMods = SoapySDR::listModules(exePath.GetPath().ToStdString() + "/modules/");
            for (std::vector<std::string>::iterator mods_i = localMods.begin(); mods_i != localMods.end(); mods_i++) {
                wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Initializing bundled SoapySDR module " + (*mods_i) + "..");
                std::cout << "Loading bundled SoapySDR module " << (*mods_i) <<  ".." << std::endl;
                SoapySDR::loadModule(*mods_i);
            }
        
            if (!localModPref) {
                wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Loading SoapySDR modules..");
                std::cout << "Checking system SoapySDR modules.." << std::flush;
                SoapySDR::loadModules();
            }
            #else
            wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Loading SoapySDR modules..");
            SoapySDR::loadModules();
            #endif

        }
        
        if (SDREnumerator::factories.size()) {
            SDREnumerator::factories.erase(SDREnumerator::factories.begin(), SDREnumerator::factories.end());
        }
        
        std::cout << "\tAvailable factories...";
        SoapySDR::FindFunctions factories = SoapySDR::Registry::listFindFunctions();
        for (SoapySDR::FindFunctions::const_iterator it = factories.begin(); it != factories.end(); ++it) {
            if (it != factories.begin()) {
                std::cout << ", ";
            }
            std::cout << it->first;
            
            if (it->first == "remote") {
                has_remote = true;
            }
            SDREnumerator::factories.push_back(it->first);
        }
        if (factories.empty()) {
            std::cout << "No factories found!" << std::endl;
        }
        if ((factories.size() == 1) && factories.find("null") != factories.end()) {
            std::cout << "Just 'null' factory found." << std::endl;
            wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_FAILED, std::string("No modules available."));
        }
        std::cout << std::endl;
        soapy_initialized = true;
    }
    
    modules = SoapySDR::listModules();

    std::vector<SoapySDR::Kwargs> results;
    SoapySDR::Kwargs enumArgs;
    bool isRemote = false;
    
    if (remoteAddr.length()) {
        std::cout << "Enumerating remote address: " << remoteAddr << std::endl;
        enumArgs["driver"] = "remote";
        enumArgs["remote"] = remoteAddr;
        isRemote = true;
        
        results = SoapySDR::Device::enumerate(enumArgs);
    } else {
        results = SoapySDR::Device::enumerate();
    }
    
    int manualsIdx = results.size();
    std::vector<std::string> manualParams;
    std::vector<bool> manualResult;
    
    if (manuals.size()) {
        for (std::vector<SDRManualDef>::const_iterator m_i = manuals.begin(); m_i != manuals.end(); m_i++) {
            std::vector<SoapySDR::Kwargs> manual_result;

            std::string strDevArgs = "driver="+m_i->factory+","+m_i->params;
            
            manualParams.push_back(m_i->params);
            
            wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Enumerating manual device '") + strDevArgs + "'..");

            manual_result = SoapySDR::Device::enumerate(strDevArgs);
            
            if (manual_result.size()) {
                for (std::vector<SoapySDR::Kwargs>::const_iterator i = manual_result.begin(); i != manual_result.end(); i++) {
                    results.push_back(*i);
                    manualResult.push_back(true);
                }
            } else {
                SoapySDR::Kwargs failedEnum;
                failedEnum = argsStrToKwargs(strDevArgs);
                failedEnum["label"] = "Not Found ("+m_i->factory+")";
                results.push_back(failedEnum);
                manualResult.push_back(false);
            }
        }
    }
    
    if (isRemote) {
        wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Opening remote server ") + remoteAddr + "..");
    }
    for (size_t i = 0; i < results.size(); i++) {
        SDRDeviceInfo *dev = new SDRDeviceInfo();
        
        SoapySDR::Kwargs deviceArgs = results[i];

        for (SoapySDR::Kwargs::const_iterator it = deviceArgs.begin(); it != deviceArgs.end(); ++it) {
            std::cout << "  " << it->first << " = " << it->second << std::endl;
            if (it->first == "driver") {
                dev->setDriver(it->second);
            } else if (it->first == "label" || it->first == "device") {
                dev->setName(it->second);
			}
        }
        
        
        if (deviceArgs.count("remote")) {
            isRemote = true;
        } else {
            isRemote = false;
        }
        
        dev->setRemote(isRemote);
        dev->setManual(i>=manualsIdx);
        if (i>=manualsIdx) {
            dev->setManualParams(manualParams[i-manualsIdx]);
        }
        
        std::cout << "Make device " << i << std::endl;
        if (i<manualsIdx || manualResult[i-manualsIdx]) try {
            SoapySDR::Device *device = SoapySDR::Device::make(deviceArgs);
            SoapySDR::Kwargs info = device->getHardwareInfo();
            for (SoapySDR::Kwargs::const_iterator it = info.begin(); it != info.end(); ++it) {
                std::cout << "  " << it->first << "=" << it->second << std::endl;
                if (it->first == "hardware") {
                    dev->setHardware(it->second);
                }
            }
            
            if (isRemote) {
                wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Querying remote " + remoteAddr + " device #" + std::to_string(i) + ": " + dev-> getName());
            } else {
                wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Querying device #") + std::to_string(i) + ": " + dev->getName());
            }

            SoapySDR::ArgInfoList settingsInfo = device->getSettingInfo();

            DeviceConfig *cfg = wxGetApp().getConfig()->getDevice(dev->getDeviceId());

            ConfigSettings devSettings = cfg->getSettings();
            if (devSettings.size()) {
                for (ConfigSettings::const_iterator set_i = devSettings.begin(); set_i != devSettings.end(); set_i++) {
                    deviceArgs[set_i->first] = set_i->second;
                }
                for (int j = 0; j < settingsInfo.size(); j++) {
                    if (deviceArgs.find(settingsInfo[j].key) != deviceArgs.end()) {
                        settingsInfo[j].value = deviceArgs[settingsInfo[j].key];
                    }
                }
            }
            
            dev->setDeviceArgs(deviceArgs);
            dev->setSettingsInfo(settingsInfo);

            int numChan = device->getNumChannels(SOAPY_SDR_RX);
            for (int i = 0; i < numChan; i++) {
                SDRDeviceChannel *chan = new SDRDeviceChannel();

                SoapySDR::RangeList rfRange = device->getFrequencyRange(SOAPY_SDR_RX, i);
                double rfMin = rfRange[0].minimum();
                double rfMax = rfRange[rfRange.size()-1].maximum();
                chan->setChannel(i);
                chan->setFullDuplex(device->getFullDuplex(SOAPY_SDR_RX, i));
                chan->setRx(true);
                chan->setTx(false);
                chan->getRFRange().setLow(rfMin);
                chan->getRFRange().setHigh(rfMax);

                std::vector<std::string> freqs = device->listFrequencies(SOAPY_SDR_RX,i);
                if (std::find(freqs.begin(), freqs.end(), "CORR") != freqs.end()) {
                    chan->setCORR(true);
                } else {
                    chan->setCORR(false);
                }
                
                if (device->hasDCOffsetMode(SOAPY_SDR_RX, i)) {
                    chan->setHardwareDC(true);
                } else {
                    chan->setHardwareDC(false);
                }
                
                std::vector<double> rates = device->listSampleRates(SOAPY_SDR_RX, i);
                for (std::vector<double>::iterator i = rates.begin(); i != rates.end(); i++) {
                    chan->getSampleRates().push_back((long)(*i));
                }
                
                ConfigSettings devStreamOpts = cfg->getStreamOpts();
                if (devStreamOpts.size()) {
                    dev->setStreamArgs(devStreamOpts);
                }
                
                SoapySDR::ArgInfoList optArgs = device->getStreamArgsInfo(SOAPY_SDR_RX, i);

                if (devStreamOpts.size()) {
                    for (int j = 0, jMax = optArgs.size(); j < jMax; j++) {
                        if (devStreamOpts.find(optArgs[j].key) != devStreamOpts.end()) {
                            optArgs[j].value = devStreamOpts[optArgs[j].key];
                        }
                    }
                }
                chan->setStreamArgsInfo(optArgs);
                
                std::vector<std::string> gainNames = device->listGains(SOAPY_SDR_RX, i);
                
                for (std::vector<std::string>::iterator gname = gainNames.begin(); gname!= gainNames.end(); gname++) {
                    chan->addGain((*gname),device->getGainRange(SOAPY_SDR_RX, i, (*gname)));
                }
                
                dev->addChannel(chan);
            }
            
            SoapySDR::Device::unmake(device);
            
            dev->setAvailable(true);
        } catch (const std::exception &ex) {
            std::cerr << "Error making device: " << ex.what() << std::endl;
            wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Error querying device #") + std::to_string(i));
            dev->setAvailable(false);
        } else {
            dev->setAvailable(false);
        }
        std::cout << std::endl;

        SDREnumerator::devs[remoteAddr].push_back(dev);
    }
    if (SDREnumerator::devs[remoteAddr].empty()) {
        wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("No devices found!"));
    }
    std::cout << std::endl;

    return &SDREnumerator::devs[remoteAddr];
}