#include "specwidget.h" #include "ui_specwidget.h" #include "qtgui/bookmarks.h" #include #include #include #include #include specWidget::specWidget(QWidget *parent) : QWidget(parent), ui(new Ui::specWidget), m_attenMod(new QStandardItemModel(this)), m_rxth(new uhd_io_thread(this)), m_saveth(new uhd_io_thread(this)), m_txth(new uhd_io_thread(this)), m_readth(new uhd_io_thread(this)), m_bSaveToFile(false), watcher(new stdout_watcher(this)) { ui->setupUi(this); Bookmarks::create(); ui->plotter->setFftFill(false); ui->plotter->setPeakHold(true); ui->plotter->setFftPlotColor(QColor(255,255,255)); ui->plotter->setRunningState(true); ui->plotter->setFreqUnits(1000000);//MHz //选择带宽 ui->plotter->setFilterBoxEnabled(true); ui->plotter->setTooltipsEnabled(true); ui->plotter->setPeakDetection(false,128.0); m_attenMod->appendRow(new QStandardItem("TX/RX")); m_attenMod->appendRow(new QStandardItem("RX2")); ui->comboBox_atn->setModel(m_attenMod); //连接 //connect (ui->plotter,&CPlotter::newDemodFreq,ui->freqCtrl,&CFreqCtrl::setFrequency); connect (ui->plotter,&CPlotter::newDemodFreq,this, &specWidget::slot_newDemodFreq); connect (ui->freqCtrl,&CFreqCtrl::newFrequency,this, &specWidget::setCenterFreq); connect (watcher,&stdout_watcher::evt_stdata,this,&specWidget::slot_msg,Qt::QueuedConnection); loadSettings(); watcher->start(); } specWidget::~specWidget() { stopProgram(); watcher->stop_and_wait(); delete ui; } void specWidget::slot_newDemodFreq(qint64 freq, qint64 delta)/* delta is the offset from the center */ { qint64 offfreq = freq - ui->plotter->getCenterFreq(); if (ui->plotter->getSpanFreq()==0) return; double ratio = offfreq *1.0/ ui->plotter->getSpanFreq() + 0.5; int v = m_nFFTSize * ratio + .5; if (v<0) v = 0; if (v>=m_nFFTSize) v = m_nFFTSize - 1; m_nCurrentCenter = v; } void specWidget::slot_msg(QByteArray s, bool bStdErr) { ui->plainTextEdit_msg->appendPlainText( (bStdErr?"STDERR>":"STDIO>") + QString::fromUtf8(s)); } void specWidget::setCenterFreq(quint64 f){ if (f<=0) return; f = set_rx_freq(f); ui->plotter->setCenterFreq(f); if (ui->doubleSpinBox_center->value() * 1e6 !=ui->freqCtrl->getFrequency()) ui->doubleSpinBox_center->setValue(ui->freqCtrl->getFrequency()/1e6); //ui->plotter->setCenterFreq(f); } void specWidget::setSampleRate(double rate){ rate = set_rx_rate(rate); set_tx_rate(rate); ui->plotter->setSampleRate(rate); } void specWidget::on_pushButton_reset_clicked() { saveSettings(); if (m_rxth->isRunning() || m_txth->isRunning()) { stopProgram(); ui->pushButton_reset->setText(tr("Start")); } else if (ui->checkBox_rx->isChecked() || ui->checkBox_play->isChecked()) { loadSettings(); resetProgram(); } } void specWidget::loadSettings() { QSettings settings(QCoreApplication::applicationFilePath()+".ini", QSettings::IniFormat); const bool checkBox_iq = true; const double doubleSpinBox_spr = settings.value("spectrum/doubleSpinBox_spr",10).toDouble(); ui->doubleSpinBox_spr->setValue(doubleSpinBox_spr); //Sample Rate ui->plotter->setSampleRate(doubleSpinBox_spr*1000000/(checkBox_iq?1:2)); const double doubleSpinBox_center = settings.value("spectrum/doubleSpinBox_center",1200).toDouble(); ui->doubleSpinBox_center->setValue(doubleSpinBox_center); //中心频率 ui->plotter->setCenterFreq(doubleSpinBox_center * 1000000); //选择频率 ui->plotter->setDemodCenterFreq(doubleSpinBox_center*1000000); ui->plotter->setHiLowCutFrequencies(-1000000,1000000); if (checkBox_iq) { ui->plotter->setSpanFreq(doubleSpinBox_spr*1000000); //选择带宽 ui->plotter->setMaxBandiwdth(doubleSpinBox_spr*1000000); } else { ui->plotter->setSpanFreq(doubleSpinBox_spr*1000000/2); //选择带宽 ui->plotter->setMaxBandiwdth(doubleSpinBox_spr*1000000/2); } const int spinBox_fftUpdate = settings.value("spectrum/spinBox_fftUpdate",20).toInt(); ui->spinBox_fftUpdate->setValue(spinBox_fftUpdate); const int comboBox_fftSize = settings.value("spectrum/comboBox_fftSize",6).toInt(); ui->comboBox_fftSize->setCurrentIndex(comboBox_fftSize); m_nFFTSize = (1<65536) m_nFFTSize = 65536; if (m_nFFTSize<128) m_nFFTSize = 128; const int comboBox_atn = settings.value("spectrum/comboBox_atn",0).toInt(); ui->comboBox_atn->setCurrentIndex(comboBox_atn); const int spinBox_chan = settings.value("spectrum/spinBox_chan",0).toInt(); ui->spinBox_chan->setValue(spinBox_chan); const int spinBox_gain = settings.value("spectrum/spinBox_gain",0).toInt(); ui->spinBox_gain->setValue(spinBox_gain); const int spinBox_bw = settings.value("spectrum/spinBox_bw",0).toInt(); ui->spinBox_bw->setValue(spinBox_bw); const double doubleSpinBox_range_max = settings.value("spectrum/doubleSpinBox_range_max",0).toInt(); ui->doubleSpinBox_range_max->setValue(doubleSpinBox_range_max); const double doubleSpinBox_range_min = settings.value("spectrum/doubleSpinBox_range_min",-150).toInt(); ui->doubleSpinBox_range_min->setValue(doubleSpinBox_range_min); const QString lineEdit_dev = settings.value("spectrum/lineEdit_dev","").toString(); ui->lineEdit_dev->setText(lineEdit_dev); const QString lineEdit_folder = settings.value("spectrum/lineEdit_folder","./").toString(); ui->lineEdit_folder->setText(lineEdit_folder); const QString lineEdit_folder_play = settings.value("spectrum/lineEdit_folder_play","./").toString(); ui->lineEdit_folder_play->setText(lineEdit_folder_play); const double doubleSpinBox_center_tx = settings.value("tx/doubleSpinBox_center_tx",1200).toDouble(); ui->doubleSpinBox_center_tx->setValue(doubleSpinBox_center_tx); const int spinBox_chan_tx = settings.value("tx/spinBox_chan_tx",0).toInt(); ui->spinBox_chan_tx->setValue(spinBox_chan_tx); const int spinBox_gain_tx = settings.value("tx/spinBox_gain_tx",0).toInt(); ui->spinBox_gain_tx->setValue(spinBox_gain_tx); const int spinBox_bw_tx = settings.value("tx/spinBox_bw_tx",0).toInt(); ui->spinBox_bw_tx->setValue(spinBox_bw_tx); } void specWidget::saveSettings() { QSettings settings(QCoreApplication::applicationFilePath()+".ini", QSettings::IniFormat); const double doubleSpinBox_spr = ui->doubleSpinBox_spr->value(); settings.setValue("spectrum/doubleSpinBox_spr",doubleSpinBox_spr); const double doubleSpinBox_center = ui->doubleSpinBox_center->value(); settings.setValue("spectrum/doubleSpinBox_center",doubleSpinBox_center); const int spinBox_fftUpdate = ui->spinBox_fftUpdate->value(); settings.setValue("spectrum/spinBox_fftUpdate",spinBox_fftUpdate); const int comboBox_fftSize = ui->comboBox_fftSize->currentIndex(); settings.setValue("spectrum/comboBox_fftSize",comboBox_fftSize); const int comboBox_atn = ui->comboBox_atn->currentIndex(); settings.setValue("spectrum/comboBox_atn",comboBox_atn); const int spinBox_gain = ui->spinBox_gain->value(); settings.setValue("spectrum/spinBox_gain",spinBox_gain); const int spinBox_bw = ui->spinBox_bw->value(); settings.setValue("spectrum/spinBox_bw",spinBox_bw); const int spinBox_chan = ui->spinBox_chan->value(); settings.setValue("spectrum/spinBox_chan",spinBox_chan); const double doubleSpinBox_range_max = ui->doubleSpinBox_range_max->value(); settings.setValue("spectrum/doubleSpinBox_range_max",doubleSpinBox_range_max); const double doubleSpinBox_range_min = ui->doubleSpinBox_range_min->value(); settings.setValue("spectrum/doubleSpinBox_range_min",doubleSpinBox_range_min); const QString lineEdit_dev = ui->lineEdit_dev->text(); settings.setValue("spectrum/lineEdit_dev",lineEdit_dev); const QString lineEdit_folder = ui->lineEdit_folder->text(); settings.setValue("spectrum/lineEdit_folder",lineEdit_folder); const QString lineEdit_folder_play = ui->lineEdit_folder_play->text(); settings.setValue("spectrum/lineEdit_folder_play",lineEdit_folder_play); const double doubleSpinBox_center_tx = ui->doubleSpinBox_center_tx->value(); settings.setValue("tx/doubleSpinBox_center_tx",doubleSpinBox_center_tx); const int spinBox_chan_tx = ui->spinBox_chan_tx->value(); settings.setValue("tx/spinBox_chan_tx",spinBox_chan_tx); const int spinBox_gain_tx = ui->spinBox_gain_tx->value(); settings.setValue("tx/spinBox_gain_tx",spinBox_gain_tx); const int spinBox_bw_tx = ui->spinBox_bw_tx->value(); settings.setValue("tx/spinBox_bw_tx",spinBox_bw_tx); } void specWidget::resetProgram() { ui->pushButton_reset->setText(tr("Start")); stopProgram(); setDevArgs(ui->lineEdit_dev->text().toStdString()); int pg = ui->toolBox_tool->currentIndex(); ui->toolBox_tool->setCurrentIndex(2); initFFTW(); m_rx_channel = ui->spinBox_chan->value(); if (!usrp) open_device(); if (!usrp) return; int updateIntelv = 1000.0 /ui->spinBox_fftUpdate->value() + .5; //开始 setSampleRate(ui->plotter->getSampleRate()); initRx(); initTx(); m_nTimerID = startTimer(updateIntelv); ui->pushButton_reset->setText(tr("Stop")); ui->toolBox_tool->setCurrentIndex(pg); ui->doubleSpinBox_spr->setEnabled(false); ui->spinBox_chan->setEnabled(false); ui->spinBox_chan_tx->setEnabled(false); } void specWidget::stopProgram() { if (m_nTimerID>=0) { killTimer(m_nTimerID); m_nTimerID = -1; } freeRx(); freeTx(); freeFFTW(); if (usrp) close_device(); ui->doubleSpinBox_spr->setEnabled(true); ui->spinBox_chan->setEnabled(true); ui->spinBox_chan_tx->setEnabled(true); } void specWidget::initRx() { long long bw = ui->spinBox_bw->value()*1000; bw = set_rx_bandwidth(bw); ui->spinBox_bw->setValue(bw/1000); setCenterFreq(ui->plotter->getCenterFreq()); QString atn = ui->comboBox_atn->currentText(); if (atn.size()) set_rx_atn(atn.toStdString()); on_spinBox_gain_valueChanged(ui->spinBox_gain->value()); m_rxth->setRunner([&](void){ run_RxIO(); }); if (!ui->checkBox_rx->isChecked()) return; //保存文件 m_strFolder = ui->lineEdit_folder->text(); m_rx_points = 0; save_count = 0; m_bSaveToFile = ui->checkBox_save->isChecked(); double dfreq = ui->doubleSpinBox_center->value(); double spr = ui->doubleSpinBox_spr->value(); m_saveth->setRunner([&,dfreq,spr](void){ QFile fOut; const size_t batchsave = 65536; while (!stop_signal_called) { if (save_count + m_rxblock_size < m_rx_points && save_count + batchsave < m_rx_points) { size_t stasp = (save_count) % m_rx_bufsz; size_t endsp = (save_count +batchsave) % m_rx_bufsz; save_count += batchsave; if (!m_bSaveToFile) { QThread::msleep(10); continue; } if (endsp < batchsave) memcpy(&m_data_iq_rx[m_rx_bufsz], m_data_iq_rx, endsp * 2 * sizeof(short) ); if (fOut.isOpen()) { if (fOut.size()>=1024*1024*1024) fOut.close(); } if (!fOut.isOpen()) { QDir dir; dir.mkpath(m_strFolder); QDateTime dtm = QDateTime::currentDateTime(); QString sdtm = dtm.toString("yyyy_MM_dd_HH_mm_ss.zzz"); QString fm = m_strFolder + "/"; fm += QString("%1MHz_%2Sps_%3.iq.sc16Intel.pcm").arg(dfreq,0,'f',6) .arg(spr,0,'f',6).arg(sdtm); fOut.setFileName(fm); if (!fOut.open(QIODevice::WriteOnly)) m_bSaveToFile = false; } if (!m_bSaveToFile) continue; fOut.write((char *)m_data_iq_rx[stasp],batchsave * sizeof(short)*2); } else QThread::msleep(10); } if (fOut.isOpen()) fOut.close(); }); m_rxth->start(QThread::TimeCriticalPriority); m_saveth->start(); } void specWidget::freeRx() { if (m_rxth->isRunning()||m_saveth->isRunning()) { stop_signal_called = true; m_rxth->wait(); m_saveth->wait(); } } void specWidget::initTx() { long long bw = ui->spinBox_bw_tx->value()*1000; bw = set_tx_bandwidth(bw); ui->spinBox_bw_tx->setValue(bw/1000); set_tx_freq(ui->doubleSpinBox_center_tx->value()*1e6); set_tx_gain(ui->spinBox_gain_tx->value()); m_txth->setRunner([&](void){ run_TxIO(); }); m_dataproduce_ok = false; read_count = m_rx_bufsz/2; m_tx_points = 0; //读取文件 m_strFolderPlay = ui->lineEdit_folder_play->text(); QDir cdir(m_strFolderPlay); QStringList lst_filter; lst_filter << "*.pcm"; QFileInfoList lstFiles = cdir.entryInfoList(lst_filter,QDir::Files|QDir::Readable,QDir::Name); if (!ui->checkBox_play->isChecked() || lstFiles.empty()) return; m_readth->setRunner([&,lstFiles](void){ QVector vec_fms; foreach (QFileInfo in, lstFiles) { vec_fms<= read_count ) { if (!fIn.isOpen()) { fIn.setFileName(vec_fms[currfile % szFiles]); if (false==fIn.open(QIODevice::ReadOnly)) { fprintf (stderr,"File Can not be opened."); stop_signal_called = true; continue; } } const size_t cur_begin = read_count % m_tx_bufsz; char * addr = (char *)&m_data_iq_tx[cur_begin][0]; int real_size = fIn.read(addr, batchread * sizeof(short) * 2)/(sizeof(short) * 2); read_count += real_size; const size_t new_begin = read_count % m_tx_bufsz; if (new_begin < batchread) memcpy(m_data_iq_tx, &m_data_iq_tx[m_tx_bufsz],sizeof(short)*2*new_begin); if (real_size < batchread ) { fIn.close(); ++currfile; } } else { if (!m_dataproduce_ok) m_dataproduce_ok = true; QThread::msleep(10); } } if (fIn.isOpen()) fIn.close(); }); m_readth->start(); while (!m_dataproduce_ok && ! stop_signal_called) QThread::msleep(10); m_txth->start(QThread::TimeCriticalPriority); } void specWidget::freeTx() { if (m_txth->isRunning() || m_readth->isRunning()) { stop_signal_called = true; m_txth->wait(); m_readth->wait(); } } void specWidget::initFFTW() { m_pFFTIn = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * m_nFFTSize); m_pFFTOut = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * m_nFFTSize); m_pFFTPlan = fftw_plan_dft_1d(m_nFFTSize,m_pFFTIn,m_pFFTOut,FFTW_FORWARD,FFTW_ESTIMATE); for (int i=0;iplotter->setNewFftData(m_dFFTAmp.data(),m_nFFTSize); } void specWidget::timerEvent(QTimerEvent * e) { static std::shared_ptr ppbuf(new double [65536*16]); static double (*pBufIQ)[2] = (double (*)[2])ppbuf.get(); //int fft if (e->timerId()==m_nTimerID ) { if (ui->checkBox_rx->isChecked()==true) { if (!m_bSaveToFile) { double ref1v = 16384; size_t curr_red =(m_rx_points + m_rx_bufsz - m_nFFTSize) % m_rx_bufsz ; if (curr_red + m_nFFTSize <= m_rx_bufsz ) { int i = 0; while (i < m_nFFTSize) { pBufIQ[i][0] = m_data_iq_rx[i + curr_red][0]; pBufIQ[i][1] = m_data_iq_rx[i + curr_red][1]; ++i; } appendWavComplex(pBufIQ,m_nFFTSize,ref1v); } if (m_nCurrentCenter>=0 && m_nCurrentCenter < m_nFFTSize) { ui->sMeter->setLevel(m_dFFTAmp[m_nCurrentCenter]); } ui->lcdNumber_read->display(int(m_rx_points /1024 / 1024 )); } else { int he = m_rx_points - save_count; ui->lcdNumber_saveBehind->display((double)he); if (he >= m_rx_bufsz) m_bSaveToFile = false; } } if (ui->checkBox_play->isChecked()) { size_t he = read_count - m_tx_points; ui->lcdNumber_tx->display((double)he/1024.0/1024.0); if (he <= m_tx_bufsz/16) stop_signal_called = true; } static int ccct = 0; if (++ccct % 10==0) { if (!m_rxth->isRunning() && !m_txth->isRunning()) ui->pushButton_reset->setText(tr("Start")); else ui->pushButton_reset->setText(tr("Stop")); } } } void specWidget::on_comboBox_fftSize_activated(int index) { if (index) m_nFFTSize = 128 * (1<65536) m_nFFTSize = 65536; if (m_nFFTSize<128) m_nFFTSize = 128; if (usrp) { freeFFTW(); initFFTW(); } saveSettings(); } void specWidget::on_doubleSpinBox_center_valueChanged(double arg1) { if (arg1 * 1e6 != ui->freqCtrl->getFrequency()) { ui->freqCtrl->setFrequency(arg1 * 1e6); } } void specWidget::on_spinBox_gain_valueChanged(int arg1) { if (usrp) set_rx_gain(arg1); //usrp->set_rx_agc(true,m_rx_channel); } void specWidget::on_doubleSpinBox_range_max_valueChanged(double arg1) { ui->plotter->setWaterfallRange(ui->doubleSpinBox_range_min->value(),ui->doubleSpinBox_range_max->value()); } void specWidget::on_doubleSpinBox_range_min_valueChanged(double arg1) { ui->plotter->setWaterfallRange(ui->doubleSpinBox_range_min->value(),ui->doubleSpinBox_range_max->value()); } void specWidget::on_comboBox_atn_currentIndexChanged(const QString &arg1) { if (arg1.size()) { if (usrp) set_rx_atn(arg1.toStdString()); } } void specWidget::on_spinBox_chan_valueChanged(int arg1) { m_rx_channel = arg1; } void specWidget::on_toolButton_br_clicked() { QString str = QFileDialog::getExistingDirectory(this,tr("Output to"),ui->lineEdit_folder->text()); if (str.length()) ui->lineEdit_folder->setText(str); } void specWidget::on_checkBox_save_stateChanged(int arg1) { m_bSaveToFile = arg1==0?false:true; } void specWidget::on_spinBox_bw_valueChanged(int arg1) { double bw = arg1 * 1000; if (bw > ui->plotter->getSampleRate()) bw = ui->plotter->getSampleRate(); if (bw <0) bw = 0; bw = set_rx_bandwidth(bw); } void specWidget::on_toolButton_br_play_clicked() { QString str = QFileDialog::getExistingDirectory(this,tr("Input from"),ui->lineEdit_folder_play->text()); if (str.length()) ui->lineEdit_folder_play->setText(str); } void specWidget::on_checkBox_play_stateChanged(int arg1) { m_bPlayFromFile = arg1==0?false:true; } void specWidget::on_doubleSpinBox_center_tx_valueChanged(double arg1) { set_tx_freq(arg1 * 1e6); } void specWidget::on_spinBox_chan_tx_valueChanged(int arg1) { m_tx_channel = arg1; } void specWidget::on_spinBox_gain_tx_valueChanged(int arg1) { set_tx_gain(arg1); } void specWidget::on_spinBox_bw_tx_valueChanged(int arg1) { double bw = arg1 * 1000; bw = set_tx_bandwidth(bw); }