提交 dbb467e9 编写于 作者: 丁劲犇's avatar 丁劲犇 😸

添加录音和播放

上级 852b429b
......@@ -10,8 +10,10 @@ specWidget::specWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::specWidget),
m_attenMod(new QStandardItemModel(this)),
m_runth(new uhd_io_thread(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))
{
......@@ -53,7 +55,7 @@ specWidget::specWidget(QWidget *parent) :
specWidget::~specWidget()
{
freeFFT();
stopProgram();
watcher->stop_and_wait();
delete ui;
}
......@@ -76,7 +78,9 @@ void specWidget::slot_newDemodFreq(qint64 freq, qint64 delta)/* delta is the off
void specWidget::slot_msg(QByteArray s, bool bStdErr)
{
ui->plainTextEdit_msg->appendPlainText(QString::fromUtf8(s));
ui->plainTextEdit_msg->appendPlainText(
(bStdErr?"STDERR>":"STDIO>") +
QString::fromUtf8(s));
}
void specWidget::setNewFftData(const double * rfftData, int size)
......@@ -120,7 +124,7 @@ void specWidget::setBookmarksEnabled(bool enabled){
void specWidget::setCenterFreq(quint64 f){
if (f<=0)
return;
f = set_center_freq(f);
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);
......@@ -166,7 +170,8 @@ void specWidget::setFreqDigits(int digits){
ui->plotter->setFreqDigits(digits);
}
void specWidget::setSampleRate(double rate){
rate = set_sample_rate(rate);
rate = set_rx_rate(rate);
set_tx_rate(rate);
ui->plotter->setSampleRate(rate);
}
double specWidget::getSampleRate(void){
......@@ -198,24 +203,16 @@ bool specWidget::saveWaterfall(const QString & filename)
void specWidget::on_pushButton_reset_clicked()
{
saveSettings();
if (m_runth->isRunning())
if (m_rxth->isRunning() || m_txth->isRunning())
{
if (m_nTimerID>=0)
{
killTimer(m_nTimerID);
m_nTimerID = -1;
}
stopProgram();
if (usrp)
{
close_device();
}
ui->pushButton_reset->setText(tr("Start"));
}
else
else if (ui->checkBox_rx->isChecked() || ui->checkBox_play->isChecked())
{
loadSettings();
resetFFT();
resetProgram();
}
}
......@@ -271,7 +268,7 @@ void specWidget::loadSettings()
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",200).toInt();
const int spinBox_bw = settings.value("spectrum/spinBox_bw",0).toInt();
ui->spinBox_bw->setValue(spinBox_bw);
......@@ -287,6 +284,22 @@ void specWidget::loadSettings()
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()
{
......@@ -316,80 +329,71 @@ void specWidget::saveSettings()
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);
}
void specWidget::freeFFT()
{
if (m_nTimerID>=0)
{
killTimer(m_nTimerID);
m_nTimerID = -1;
}
if (m_runth->isRunning())
{
stop_signal_called = true;
m_runth->wait();
m_saveth->wait();
}
if (m_pFFTPlan)
{
fftw_destroy_plan(m_pFFTPlan);
m_pFFTPlan = nullptr;
}
if (m_pFFTIn)
{
fftw_free(m_pFFTIn);
m_pFFTIn = nullptr;
}
if (m_pFFTOut)
{
fftw_free(m_pFFTOut);
m_pFFTOut = nullptr;
}
m_dHammingWnd.clear();
m_dFFTAmp.clear();
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::resetFFT()
void specWidget::resetProgram()
{
ui->pushButton_reset->setText(tr("Start"));
stopProgram();
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(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;
}
freeFFT();
int pg = ui->toolBox_tool->currentIndex();
ui->toolBox_tool->setCurrentIndex(2);
freeRx();
freeTx();
freeFFTW();
if (usrp)
{
close_device();
}
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;i<m_nFFTSize;++i)
{
m_dHammingWnd.push_back(0.54 - 0.46 * cos (2*3.1415927 * i / (m_nFFTSize-1)));
m_dFFTAmp.push_back(0);
}
int updateIntelv = 1000.0 /ui->spinBox_fftUpdate->value() + .5;
m_channel = ui->spinBox_chan->value();
if (!usrp)
{
open_device();
}
ui->doubleSpinBox_spr->setEnabled(true);
ui->spinBox_chan->setEnabled(true);
ui->spinBox_chan_tx->setEnabled(true);
}
if (!usrp)
{
return;
}
//开始
setSampleRate(getSampleRate());
void specWidget::initRx()
{
long long bw = ui->spinBox_bw->value()*1000;
bw = set_rx_bandwidth(bw);
ui->spinBox_bw->setValue(bw/1000);
......@@ -399,10 +403,12 @@ void specWidget::resetFFT()
set_rx_atn(atn.toStdString());
on_spinBox_gain_valueChanged(ui->spinBox_gain->value());
m_runth->setRunner([&](void){
run_IO();
m_rxth->setRunner([&](void){
run_RxIO();
});
if (!ui->checkBox_rx->isChecked())
return;
//保存文件
m_strFolder = ui->lineEdit_folder->text();
......@@ -412,18 +418,22 @@ void specWidget::resetFFT()
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 + 100 < rx_count)
if (save_count + m_rxblock_size < m_rx_points && save_count + batchsave < m_rx_points)
{
short * buf = m_buffer_iq[save_count % bufsz];
size_t len = m_buf_iqsize[save_count % bufsz];
++save_count;
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)
......@@ -444,7 +454,7 @@ void specWidget::resetFFT()
}
if (!m_bSaveToFile)
continue;
fOut.write((char *)buf,len * sizeof(short)*2);
fOut.write((char *)m_data_iq_rx[stasp],batchsave * sizeof(short)*2);
}
else
QThread::msleep(10);
......@@ -452,13 +462,141 @@ void specWidget::resetFFT()
if (fOut.isOpen())
fOut.close();
});
ui->toolBox_tool->setCurrentIndex(pg);
m_runth->start();
m_rxth->start();
m_saveth->start();
m_nTimerID = startTimer(updateIntelv);
ui->pushButton_reset->setText(tr("Stop"));
}
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();
});
read_count = m_rx_bufsz/2;
//读取文件
m_strFolder = ui->lineEdit_folder_play->text();
QDir cdir(m_strFolder);
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<QString> vec_fms;
foreach (QFileInfo in, lstFiles)
{
vec_fms<<in.absoluteFilePath();
}
const int szFiles = vec_fms.size();
int currfile = 0;
QFile fIn;
const size_t batchread = 65536;
while (!stop_signal_called)
{
if (m_tx_points + m_tx_bufsz/2 >= 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 (read_count < batchread )
{
fIn.close();
++currfile;
}
}
else
QThread::msleep(10);
}
if (fIn.isOpen())
fIn.close();
});
m_txth->start();
m_readth->start();
}
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;i<m_nFFTSize;++i)
{
m_dHammingWnd.push_back(0.54 - 0.46 * cos (2*3.1415927 * i / (m_nFFTSize-1)));
m_dFFTAmp.push_back(0);
}
}
void specWidget::freeFFTW()
{
if (m_pFFTPlan)
{
fftw_destroy_plan(m_pFFTPlan);
m_pFFTPlan = nullptr;
}
if (m_pFFTIn)
{
fftw_free(m_pFFTIn);
m_pFFTIn = nullptr;
}
if (m_pFFTOut)
{
fftw_free(m_pFFTOut);
m_pFFTOut = nullptr;
}
m_dHammingWnd.clear();
m_dFFTAmp.clear();
}
void specWidget::appendWavComplex(const double (* pWav)[2], const int count, double voltage_ref)
{
if (!m_pFFTIn || !m_pFFTOut || !m_pFFTPlan || m_dHammingWnd.size()!=m_nFFTSize
......@@ -491,49 +629,56 @@ void specWidget::timerEvent(QTimerEvent * e)
//int fft
if (e->timerId()==m_nTimerID )
{
const int num_blocks = m_nFFTSize/m_spb_size + 3;
if (!m_bSaveToFile)
if (ui->checkBox_rx->isChecked()==true)
{
double ref1v = 16384;
int curr_tx = (rx_count + bufsz - num_blocks ) % bufsz ;
int total_cp = 0;
//memset(pBufIQ,0,sizeof(double)*2*sppoints);
while (total_cp < m_nFFTSize)
if (!m_bSaveToFile)
{
const size_t sz = m_buf_iqsize[curr_tx];
const short (*datap)[2] = (const short (*)[2])m_buffer_iq[curr_tx];
for (size_t i=0;i<sz && total_cp < m_nFFTSize;++i,++total_cp)
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 )
{
pBufIQ[total_cp][0] =datap[i][0];
pBufIQ[total_cp][1] =datap[i][1];
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]);
}
++curr_tx;
curr_tx %= bufsz;
if (!sz)
break;
ui->lcdNumber_read->display(int(m_rx_points /1024 / 1024 ));
}
appendWavComplex(pBufIQ,m_nFFTSize,ref1v);
if (m_nCurrentCenter>=0 && m_nCurrentCenter < m_nFFTSize)
else
{
ui->sMeter->setLevel(m_dFFTAmp[m_nCurrentCenter]);
size_t he = m_rx_points - save_count;
ui->lcdNumber_saveBehind->display((double)he);
if (he >= m_rx_bufsz)
m_bSaveToFile = false;
}
ui->lcdNumber_saveBehind->display(int(rx_count * m_spb_size * 4 /1024 / 1024 ));
}
else
if (ui->checkBox_play->isChecked())
{
int he = rx_count - save_count;
size_t he = read_count - m_tx_points;
ui->lcdNumber_saveBehind->display(he);
ui->lcdNumber_tx->display((double)he/1024.0/1024.0);
if (he >= bufsz)
m_bSaveToFile = false;
if (he <= m_tx_bufsz/16)
stop_signal_called = true;
}
static int ccct = 0;
if (++ccct % 10==0)
{
if (!m_runth->isRunning())
if (!m_rxth->isRunning() && !m_txth->isRunning())
ui->pushButton_reset->setText(tr("Start"));
else
ui->pushButton_reset->setText(tr("Stop"));
......@@ -552,7 +697,7 @@ void specWidget::on_comboBox_fftSize_activated(int index)
if (m_nFFTSize<128)
m_nFFTSize = 128;
if (usrp)
resetFFT();
resetProgram();
saveSettings();
}
......@@ -568,7 +713,7 @@ void specWidget::on_spinBox_gain_valueChanged(int arg1)
{
if (usrp)
set_rx_gain(arg1);
//usrp->set_rx_agc(true,m_channel);
//usrp->set_rx_agc(true,m_rx_channel);
}
......@@ -593,7 +738,7 @@ void specWidget::on_comboBox_atn_currentIndexChanged(const QString &arg1)
void specWidget::on_spinBox_chan_valueChanged(int arg1)
{
m_channel = arg1;
m_rx_channel = arg1;
}
void specWidget::on_toolButton_br_clicked()
......@@ -613,8 +758,42 @@ void specWidget::on_spinBox_bw_valueChanged(int arg1)
double bw = arg1 * 1000;
if (bw > ui->plotter->getSampleRate())
bw = ui->plotter->getSampleRate();
if (bw <200000)
bw = 200000;
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->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);
}
......@@ -110,12 +110,26 @@ private slots:
void on_toolButton_br_clicked();
void on_checkBox_save_stateChanged(int arg1);
void on_spinBox_bw_valueChanged(int arg1);
void on_toolButton_br_play_clicked();
void on_checkBox_play_stateChanged(int arg1);
void on_doubleSpinBox_center_tx_valueChanged(double arg1);
void on_spinBox_chan_tx_valueChanged(int arg1);
void on_spinBox_gain_tx_valueChanged(int arg1);
void on_spinBox_bw_tx_valueChanged(int arg1);
private:
void loadSettings();
void saveSettings();
void resetFFT();
void freeFFT();
private:
void resetProgram();
void stopProgram();
void initFFTW();
void freeFFTW();
void initRx();
void initTx();
void freeRx();
void freeTx();
private:
Ui::specWidget *ui = nullptr;
QStandardItemModel * m_attenMod = nullptr;
......@@ -130,10 +144,14 @@ private:
int m_nCurrentCenter = 0;
double m_dManuAdd = 0;
//Thread
uhd_io_thread * m_runth = nullptr;
uhd_io_thread * m_rxth = nullptr;
uhd_io_thread * m_saveth = nullptr;
std::atomic<long long> save_count;
uhd_io_thread * m_txth = nullptr;
uhd_io_thread * m_readth = nullptr;
unsigned long long save_count;
unsigned long long read_count;
std::atomic<bool> m_bSaveToFile;
std::atomic<bool> m_bPlayFromFile;
QString m_strFolder;
//stdout reader
stdout_watcher * watcher = nullptr;
......
......@@ -51,6 +51,26 @@
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="lcdNumber_read">
<property name="digitCount">
<number>8</number>
</property>
<property name="segmentStyle">
<enum>QLCDNumber::Flat</enum>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="lcdNumber_tx">
<property name="digitCount">
<number>8</number>
</property>
<property name="segmentStyle">
<enum>QLCDNumber::Flat</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
......@@ -222,21 +242,21 @@
<x>0</x>
<y>0</y>
<width>320</width>
<height>478</height>
<height>504</height>
</rect>
</property>
<attribute name="label">
<string>Radio</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<item row="7" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Device</string>
<string>RX Gain</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="5" column="2" colspan="2">
<widget class="QDoubleSpinBox" name="doubleSpinBox_center">
<property name="decimals">
<number>6</number>
......@@ -252,78 +272,151 @@
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="spinBox_gain"/>
<item row="10" column="3">
<widget class="QToolButton" name="toolButton_br_play">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_10">
<item row="2" column="2" colspan="2">
<widget class="QDoubleSpinBox" name="doubleSpinBox_spr">
<property name="decimals">
<number>6</number>
</property>
<property name="minimum">
<double>0.000001000000000</double>
</property>
<property name="maximum">
<double>1024.000000000000000</double>
</property>
<property name="value">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Antenna</string>
<string>Device</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Center Freq(Mhz)</string>
<string>RX Channel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<item row="8" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Channel</string>
<string>BW(Khz)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBox_chan">
<item row="15" column="1">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>110</height>
</size>
</property>
</spacer>
</item>
<item row="11" column="2" colspan="2">
<widget class="QSpinBox" name="spinBox_chan_tx">
<property name="maximum">
<number>1</number>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_spr">
<property name="decimals">
<number>6</number>
<item row="12" column="0" colspan="2">
<widget class="QLabel" name="label_14">
<property name="text">
<string>TX Freq(Mhz)</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="2">
<widget class="QCheckBox" name="checkBox_save">
<property name="text">
<string>Save To</string>
</property>
</widget>
</item>
<item row="14" column="2" colspan="2">
<widget class="QSpinBox" name="spinBox_bw_tx">
<property name="minimum">
<double>0.000001000000000</double>
<number>0</number>
</property>
<property name="maximum">
<double>1024.000000000000000</double>
<number>200000</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="value">
<double>10.000000000000000</double>
<number>1000</number>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_12">
<item row="9" column="2">
<widget class="QLineEdit" name="lineEdit_folder"/>
</item>
<item row="13" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>BW(Khz)</string>
<string>TX Gain</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label">
<item row="14" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Sample Rate(Mhz)</string>
<string>TX BW(Khz)</string>
</property>
</widget>
</item>
<item row="10" column="2">
<widget class="QLineEdit" name="lineEdit_folder_play"/>
</item>
<item row="12" column="2" colspan="2">
<widget class="QDoubleSpinBox" name="doubleSpinBox_center_tx">
<property name="decimals">
<number>6</number>
</property>
<property name="minimum">
<double>0.000001000000000</double>
</property>
<property name="maximum">
<double>102400.000000000000000</double>
</property>
<property name="value">
<double>1200.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="4" column="2" colspan="2">
<widget class="QComboBox" name="comboBox_atn">
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit_dev"/>
<item row="10" column="0" colspan="2">
<widget class="QCheckBox" name="checkBox_play">
<property name="text">
<string>Play from</string>
</property>
</widget>
</item>
<item row="6" column="1">
<item row="8" column="2" colspan="2">
<widget class="QSpinBox" name="spinBox_bw">
<property name="minimum">
<number>0</number>
......@@ -339,25 +432,63 @@
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<item row="3" column="2" colspan="2">
<widget class="QSpinBox" name="spinBox_chan">
<property name="maximum">
<number>1</number>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Gain</string>
<string>TX Channel</string>
</property>
</widget>
</item>
<item row="7" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
<item row="1" column="2" colspan="2">
<widget class="QLineEdit" name="lineEdit_dev"/>
</item>
<item row="5" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>RX Freq(Mhz)</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>RX Antenna</string>
</property>
</spacer>
</widget>
</item>
<item row="7" column="2" colspan="2">
<widget class="QSpinBox" name="spinBox_gain"/>
</item>
<item row="13" column="2" colspan="2">
<widget class="QSpinBox" name="spinBox_gain_tx"/>
</item>
<item row="9" column="3">
<widget class="QToolButton" name="toolButton_br">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Sample Rate(Mhz)</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox_rx">
<property name="text">
<string>Rx is ON</string>
</property>
</widget>
</item>
</layout>
</widget>
......@@ -367,7 +498,7 @@
<x>0</x>
<y>0</y>
<width>320</width>
<height>478</height>
<height>504</height>
</rect>
</property>
<attribute name="label">
......@@ -531,13 +662,28 @@
<x>0</x>
<y>0</y>
<width>320</width>
<height>478</height>
<height>504</height>
</rect>
</property>
<attribute name="label">
<string>Log</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>1</number>
</property>
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<item>
<widget class="QPlainTextEdit" name="plainTextEdit_msg">
<property name="lineWrapMode">
......@@ -553,58 +699,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="save">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>320</width>
<height>478</height>
</rect>
</property>
<attribute name="label">
<string>Save</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="0">
<widget class="QCheckBox" name="checkBox_save">
<property name="text">
<string>Recording to Files</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Folder</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="toolButton_br">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="lineEdit_folder"/>
</item>
<item row="3" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
......
#include "uhd_device.h"
#include "uhd_device.h"
#include <QThread>
#include <QDebug>
#include <QCoreApplication>
......@@ -36,56 +36,30 @@ void uhd_io_thread::run()
uhd_device::uhd_device()
:stop_signal_called(false)
,streaming(false)
,rx_count(0)
,m_rx_streaming(false)
,m_rx_points(0)
{
m_buffer_tmFrag = new double [bufsz];
m_buffer_tmSec = new long long [bufsz];
m_buffer_iq_all = new short [bufsz * m_spb_size * 2];
m_buffer_iq = new short * [bufsz];
m_buf_iqsize = new int [bufsz];
for (size_t i=0;i<bufsz;++i)
{
m_buffer_tmFrag[i] = 0;
m_buffer_tmSec[i] = 0;
m_buffer_iq[i] = &m_buffer_iq_all[i * m_spb_size * 2];
m_buf_iqsize[i] = 0;
}
m_data_iq_rx = new short [m_rx_bufsz+1024*1024][2]{{0,0}};
}
uhd_device::uhd_device(const std::string &args)
:stop_signal_called(false)
,streaming(false)
,m_rx_streaming(false)
,m_dev_args (args)
,rx_count(0)
,m_rx_points(0)
{
m_buffer_tmFrag = new double [bufsz];
m_buffer_tmSec = new long long [bufsz];
m_buffer_iq_all = new short [bufsz * m_spb_size * 2];
m_buffer_iq = new short * [bufsz];
m_buf_iqsize = new int [bufsz];
for (int i=0;i<bufsz;++i)
{
m_buffer_tmFrag[i] = 0;
m_buffer_tmSec[i] = 0;
m_buffer_iq[i] = &m_buffer_iq_all[i * m_spb_size * 2];
m_buf_iqsize[i] = 0;
}
m_data_iq_rx = new short [m_rx_bufsz+1024*1024][2]{{0,0}};
}
uhd_device::~uhd_device()
{
stop_signal_called = true;
while (streaming)
while (m_rx_streaming)
{
QThread::msleep(100);
}
delete[] m_buffer_tmFrag;
delete[] m_buffer_tmSec;
delete[] m_buffer_iq_all ;
delete[] m_buffer_iq;
delete[] m_buf_iqsize;
delete[] m_data_iq_rx;
}
......@@ -143,7 +117,7 @@ bool uhd_device::open_device()
bool uhd_device::close_device()
{
stop_signal_called = true;
while (streaming)
while (m_rx_streaming)
{
QThread::msleep(1000);
}
......@@ -155,33 +129,36 @@ bool uhd_device::close_device()
/*!
* 范例落盘函数,使用环形队列保持跟随收发
*/
void uhd_device::run_IO()
void uhd_device::run_RxIO()
{
//创建流对象实例
uhd::stream_args_t stream_args_rx("sc16", "sc16");
stream_args_rx.channels.push_back(m_channel);
stream_args_rx.channels.push_back(m_rx_channel);
rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args_rx);
rx_count = 0;
m_rx_points = 0;
//接收线程
auto thcall_rx = [&]()->void{
uhd::rx_metadata_t md_rx;
uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
stream_cmd.num_samps = size_t(m_spb_size);
stream_cmd.num_samps = size_t(m_rxblock_size);
stream_cmd.stream_now = true;
stream_cmd.time_spec = uhd::time_spec_t();
streaming = true;
m_rx_streaming = true;
rx_stream->issue_stream_cmd(stream_cmd);
try {
while (!stop_signal_called)
{
const int off = rx_count % bufsz;
m_buf_iqsize[off] = rx_stream->recv((void *)(m_buffer_iq[off]),m_spb_size,md_rx,10,false);
++rx_count;
const size_t off = m_rx_points % m_rx_bufsz;
size_t real_size = rx_stream->recv((void *)(m_data_iq_rx[off]),m_rxblock_size,md_rx,10,false);
m_rx_points += real_size;
const size_t new_begin = m_rx_points % m_rx_bufsz;
if (new_begin < m_rxblock_size)
memcpy(m_data_iq_rx, &m_data_iq_rx[m_rx_bufsz], sizeof(short)*2*new_begin);
//md_rx可以读取时戳
m_buffer_tmFrag[off] = md_rx.time_spec.get_frac_secs();
m_buffer_tmSec[off] = md_rx.time_spec.get_full_secs();
//m_buffer_tmFrag[off] = md_rx.time_spec.get_frac_secs();
//m_buffer_tmSec[off] = md_rx.time_spec.get_full_secs();
if (md_rx.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT)
{
fputs("Tout",stderr);
......@@ -204,7 +181,7 @@ void uhd_device::run_IO()
}
stream_cmd.stream_now = false;
rx_stream->issue_stream_cmd(stream_cmd);
streaming = false;
m_rx_streaming = false;
};
//启动线程
uhd_io_thread * rx_thread = new uhd_io_thread(thcall_rx,0);
......@@ -212,7 +189,7 @@ void uhd_device::run_IO()
//主线程不断打印状态
while (!stop_signal_called)
{
//cerr<<"RX" << rx_count<<"\r";
//cerr<<"RX" << m_rx_points<<"\r";
std::this_thread::sleep_for(std::chrono::milliseconds(400));
}
//退出
......@@ -220,26 +197,26 @@ void uhd_device::run_IO()
rx_thread->deleteLater();
}
quint64 uhd_device::set_center_freq(const quint64 freq_in_hz)
quint64 uhd_device::set_rx_freq(const quint64 freq_in_hz)
{
if (usrp)
{
double rate = usrp->get_rx_rate(m_channel);
//double rate = usrp->get_rx_rate(m_rx_channel);
using uhd::tune_request_t;
tune_request_t tune_request_rx = tune_request_t((double)freq_in_hz/*,rate/2*/);
usrp->set_rx_freq(tune_request_rx,m_channel);
return (quint64)(usrp->get_rx_freq(m_channel));
usrp->set_rx_freq(tune_request_rx,m_rx_channel);
return (quint64)(usrp->get_rx_freq(m_rx_channel));
}
else
return freq_in_hz;
}
double uhd_device::set_sample_rate(const double sprate)
double uhd_device::set_rx_rate(const double sprate)
{
if (usrp)
{
usrp->set_rx_rate(sprate);
return usrp->get_rx_rate(m_channel);
return usrp->get_rx_rate(m_rx_channel);
}
return sprate;
}
......@@ -247,26 +224,74 @@ double uhd_device::set_sample_rate(const double sprate)
void uhd_device::set_rx_atn(const std::string & atn)
{
if (usrp)
usrp->set_rx_antenna(atn.c_str(),m_channel);
usrp->set_rx_antenna(atn.c_str(),m_rx_channel);
}
double uhd_device::set_rx_gain(double gain)
{
if (usrp)
usrp->set_rx_gain(gain,m_channel);
return usrp->get_rx_gain(m_channel);
usrp->set_rx_gain(gain,m_rx_channel);
return usrp->get_rx_gain(m_rx_channel);
}
double uhd_device::set_rx_bandwidth(double bw)
{
if (usrp && bw>=200000)
{
usrp->set_rx_bandwidth(bw,m_channel);
bw = usrp->get_rx_bandwidth(m_channel);
usrp->set_rx_bandwidth(bw,m_rx_channel);
bw = usrp->get_rx_bandwidth(m_rx_channel);
}
else if (usrp )
{
usrp->set_rx_bandwidth(usrp->get_rx_rate(m_rx_channel),m_rx_channel);
bw = usrp->get_rx_bandwidth(m_rx_channel);
}
return bw;
}
quint64 uhd_device::set_tx_freq(const quint64 freq_in_hz)
{
if (usrp)
{
double rate = usrp->get_tx_rate(m_tx_channel);
using uhd::tune_request_t;
tune_request_t tune_request_tx = tune_request_t((double)freq_in_hz/*,rate/2*/);
usrp->set_tx_freq(tune_request_tx,m_tx_channel);
return (quint64)(usrp->get_tx_freq(m_tx_channel));
}
else
return freq_in_hz;
}
double uhd_device::set_tx_rate(const double sprate)
{
if (usrp)
{
usrp->set_tx_rate(sprate);
return usrp->get_tx_rate(m_tx_channel);
}
return sprate;
}
double uhd_device::set_tx_gain(double gain)
{
if (usrp)
usrp->set_tx_gain(gain,m_tx_channel);
return usrp->get_tx_gain(m_tx_channel);
}
double uhd_device::set_tx_bandwidth(double bw)
{
if (usrp && bw>=200000)
{
usrp->set_tx_bandwidth(bw,m_tx_channel);
bw = usrp->get_tx_bandwidth(m_tx_channel);
}
else if (usrp )
{
usrp->set_rx_bandwidth(usrp->get_rx_rate(m_channel),m_channel);
bw = usrp->get_rx_bandwidth(m_channel);
usrp->set_tx_bandwidth(usrp->get_tx_rate(m_tx_channel),m_tx_channel);
bw = usrp->get_tx_bandwidth(m_tx_channel);
}
return bw;
......
#ifndef UHD_DEVICE_H
#ifndef UHD_DEVICE_H
#define UHD_DEVICE_H
#include <uhd/types/tune_request.hpp>
#include <uhd/usrp/multi_usrp.hpp>
......@@ -37,30 +37,32 @@ public:
public:
bool open_device();
bool close_device();
void run_IO();
void run_RxIO();
protected:
std::atomic<bool> stop_signal_called;
std::atomic<bool> streaming;
std::atomic<bool> m_rx_streaming;
std::string m_dev_args;
size_t m_spb_size = 65536;
size_t m_rxblock_size = 10000;
uhd::usrp::multi_usrp::sptr usrp;
size_t m_channel = 0;
size_t m_rx_channel = 0;
size_t m_tx_channel = 0;
protected:
//初始化队列
double * m_buffer_tmFrag;
long long * m_buffer_tmSec;
short * m_buffer_iq_all;
short * * m_buffer_iq;
int * m_buf_iqsize;
const size_t bufsz = 1024;
short (*m_data_iq_rx)[2] = nullptr;
size_t m_rx_bufsz = 1024*1024*16;
//收发计数
long long rx_count ;
unsigned long long m_rx_points = 0;
public:
quint64 set_center_freq(const quint64 freq_in_hz);
double set_sample_rate(const double sprate);
quint64 set_rx_freq(const quint64 freq_in_hz);
double set_rx_rate(const double sprate);
void set_rx_atn(const std::string & ana);
double set_rx_gain(double gain);
double set_rx_bandwidth(double bw);
public:
quint64 set_tx_freq(const quint64 freq_in_hz);
double set_tx_rate(const double sprate);
double set_tx_gain(double);
double set_tx_bandwidth(double bw);
};
#endif // UHD_DEVICE_H
......@@ -42,56 +42,33 @@ void uhd_io_thread::run()
uhd_device::uhd_device()
:stop_signal_called(false)
,streaming(false)
,rx_count(0)
,m_rx_streaming(false)
,m_rx_points(0)
{
m_buffer_tmFrag = new double [bufsz];
m_buffer_tmSec = new long long [bufsz];
m_buffer_iq_all = new short [bufsz * m_spb_size * 2];
m_buffer_iq = new short * [bufsz];
m_buf_iqsize = new size_t [bufsz];
for (int i=0;i<bufsz;++i)
{
m_buffer_tmFrag[i] = 0;
m_buffer_tmSec[i] = 0;
m_buffer_iq[i] = &m_buffer_iq_all[i * m_spb_size * 2];
m_buf_iqsize[i] = 0;
}
m_data_iq_rx = new short [m_rx_bufsz+1024*1024][2]{{0,0}};
m_data_iq_tx = new short [m_tx_bufsz+1024*1024][2]{{0,0}};
}
uhd_device::uhd_device(const std::string &args)
:stop_signal_called(false)
,streaming(false)
,m_rx_streaming(false)
,m_dev_args (args)
,rx_count(0)
,m_rx_points(0)
{
m_buffer_tmFrag = new double [bufsz];
m_buffer_tmSec = new long long [bufsz];
m_buffer_iq_all = new short [bufsz * m_spb_size * 2];
m_buffer_iq = new short * [bufsz];
m_buf_iqsize = new size_t [bufsz];
for (int i=0;i<bufsz;++i)
{
m_buffer_tmFrag[i] = 0;
m_buffer_tmSec[i] = 0;
m_buffer_iq[i] = &m_buffer_iq_all[i * m_spb_size * 2];
m_buf_iqsize[i] = 0;
}
m_data_iq_rx = new short [m_rx_bufsz+1024*1024][2]{{0,0}};
m_data_iq_tx = new short [m_tx_bufsz+1024*1024][2]{{0,0}};
}
uhd_device::~uhd_device()
{
stop_signal_called = true;
while (streaming)
while (m_rx_streaming)
{
QThread::msleep(100);
}
delete[] m_data_iq_rx;
delete[] m_data_iq_tx;
delete[] m_buffer_tmFrag;
delete[] m_buffer_tmSec;
delete[] m_buffer_iq_all ;
delete[] m_buffer_iq;
delete[] m_buf_iqsize;
}
......@@ -148,7 +125,7 @@ bool uhd_device::open_device()
bool uhd_device::close_device()
{
stop_signal_called = true;
while (streaming)
while (m_rx_streaming)
{
QThread::msleep(1000);
}
......@@ -161,7 +138,7 @@ bool uhd_device::close_device()
/*!
* 范例落盘函数,使用环形队列保持跟随收发
*/
void uhd_device::run_IO()
void uhd_device::run_RxIO()
{
//设置接收通道,母板号为0(multi-usrp支持级联)
//UHD_DO(uhd_usrp_set_rx_subdev_spec(usrp,0,0));
......@@ -172,7 +149,7 @@ void uhd_device::run_IO()
char rx_args[] = "";
const size_t rx_channel_count = 1;
//接收信号。MIMO时,可以指定0,1
size_t rx_channel[] = {(size_t)m_channel};
size_t rx_channel[] = {(size_t)m_rx_channel};
uhd_stream_args_t rx_stream_args = {
/*.cpu_format = */rx_cpu_format,
/*.otw_format = */rx_otw_format,
......@@ -184,7 +161,7 @@ void uhd_device::run_IO()
uhd_rx_metadata_handle rx_meta = 0;
rx_count = 0;
m_rx_points = 0;
//接收线程
auto thcall_rx = [&]()->void{
// Create RX streamer
......@@ -198,27 +175,32 @@ void uhd_device::run_IO()
/*.time_spec_full_secs = */0,
/*.time_spec_frac_secs = */0
};
streaming = true;
m_rx_streaming = true;
rx_stream_args.channel_list = rx_channel;
UHD_DO(uhd_usrp_get_rx_stream(usrp, &rx_stream_args, rx_streamer));
// Set up buffer
UHD_DO(uhd_rx_streamer_max_num_samps(rx_streamer, &m_spb_size));
fprintf(stderr, "Buffer size in samples: %zu\n", m_spb_size);
UHD_DO(uhd_rx_streamer_max_num_samps(rx_streamer, &m_rxblock_size));
fprintf(stderr, "Buffer size in samples: %zu\n", m_rxblock_size);
try {
UHD_DO(uhd_rx_streamer_issue_stream_cmd(rx_streamer, &rx_stream_cmd));
while (!stop_signal_called)
{
const int off = rx_count % bufsz;
UHD_DO(uhd_rx_streamer_recv(rx_streamer,(void **) &(m_buffer_iq[off]), m_spb_size, &rx_meta, 10, true, &m_buf_iqsize[off]));
++rx_count;
const size_t off = m_rx_points % m_rx_bufsz;
size_t real_size = 0;
void * addr = (void *)&m_data_iq_rx[off][0];
UHD_DO(uhd_rx_streamer_recv(rx_streamer,(void **) &addr, m_rxblock_size, &rx_meta, 10, true, &real_size));
m_rx_points += real_size;
const size_t new_begin = m_rx_points % m_rx_bufsz;
if (new_begin < m_rxblock_size)
memcpy(m_data_iq_rx, &m_data_iq_rx[m_rx_bufsz], sizeof(short)*2*new_begin);
//md_rx可以读取时戳
UHD_DO(uhd_rx_metadata_time_spec(rx_meta,&m_buffer_tmSec[off],&m_buffer_tmFrag[off]));
//UHD_DO(uhd_rx_metadata_time_spec(rx_meta,&m_buffer_tmSec[off],&m_buffer_tmFrag[off]));
uhd_rx_metadata_error_code_t error_code;
UHD_DO(uhd_rx_metadata_error_code(rx_meta, &error_code));
if(error_code != UHD_RX_METADATA_ERROR_CODE_NONE){
fprintf(stderr, "Warning: Error code 0x%x was returned during streaming.\n", error_code);
fprintf(stderr, "Warning: Error code 0x%x was returned during m_rx_streaming.\n", error_code);
uhd_usrp_last_error(usrp, error_string, 512);
fputs(error_string,stderr);
UHD_DO(uhd_rx_streamer_issue_stream_cmd(rx_streamer, &rx_stream_cmd));
......@@ -230,7 +212,7 @@ void uhd_device::run_IO()
}
rx_stream_cmd.stream_now = false;
UHD_DO(uhd_rx_streamer_issue_stream_cmd(rx_streamer, &rx_stream_cmd));
streaming = false;
m_rx_streaming = false;
};
//启动线程
uhd_io_thread * rx_thread = new uhd_io_thread(thcall_rx,0);
......@@ -238,7 +220,7 @@ void uhd_device::run_IO()
//主线程不断打印状态
while (!stop_signal_called)
{
//cerr<<"RX" << rx_count<<"\r";
//cerr<<"RX" << m_rx_points<<"\r";
std::this_thread::sleep_for(std::chrono::milliseconds(400));
}
if (rx_streamer) uhd_rx_streamer_free(&rx_streamer);
......@@ -248,12 +230,14 @@ void uhd_device::run_IO()
rx_thread->deleteLater();
}
quint64 uhd_device::set_center_freq(const quint64 freq_in_hz)
quint64 uhd_device::set_rx_freq(const quint64 freq_in_hz)
{
if (!usrp)
return freq_in_hz;
double srate = 0;
UHD_DO(uhd_usrp_get_rx_rate(usrp, m_channel, &srate));
//double srate = 0;
//UHD_DO(uhd_usrp_get_rx_rate(usrp, m_rx_channel, &srate));
fprintf(stderr, "Setting RX frequency: %f MHz...\n", freq_in_hz/1e6);
uhd_tune_result_t rx_tune_result;
......@@ -266,13 +250,13 @@ quint64 uhd_device::set_center_freq(const quint64 freq_in_hz)
/*.dsp_freq =*/ 0,
/*.args =*/ 0
};
UHD_DO(uhd_usrp_set_rx_freq(usrp, &rx_tune_request, m_channel, &rx_tune_result));
UHD_DO(uhd_usrp_set_rx_freq(usrp, &rx_tune_request, m_rx_channel, &rx_tune_result));
double freq = 0;
UHD_DO(uhd_usrp_get_rx_freq(usrp, m_channel, &freq));
UHD_DO(uhd_usrp_get_rx_freq(usrp, m_rx_channel, &freq));
fprintf(stderr, "Actual RX frequency: %f MHz...\n", freq / 1e6);
return (quint64)(freq +.5);
}
double uhd_device::set_sample_rate(const double sprate)
double uhd_device::set_rx_rate(const double sprate)
{
if (usrp)
{
......@@ -283,17 +267,17 @@ double uhd_device::set_sample_rate(const double sprate)
if (bw <200000 || bw > sprate)
bw = sprate;
fprintf(stderr, "Setting RX Rate: %f...\n", sprate);
UHD_DO(uhd_usrp_set_rx_rate(usrp, sprate, m_channel));
UHD_DO(uhd_usrp_set_rx_rate(usrp, sprate, m_rx_channel));
// See what rate actually is
UHD_DO(uhd_usrp_get_rx_rate(usrp, m_channel, &srate));
UHD_DO(uhd_usrp_get_rx_rate(usrp, m_rx_channel, &srate));
fprintf(stderr, "Actual RX Rate: %f...\n", srate);
fprintf(stderr, "Setting RX Bandwidth: %f MHz...\n", bw/1e6);
UHD_DO(uhd_usrp_set_rx_bandwidth(usrp, bw, m_channel));
UHD_DO(uhd_usrp_set_rx_bandwidth(usrp, bw, m_rx_channel));
//Band
UHD_DO(uhd_usrp_get_rx_bandwidth(usrp, m_channel, &bw));
UHD_DO(uhd_usrp_get_rx_bandwidth(usrp, m_rx_channel, &bw));
fprintf(stderr, "Actual RX Bandwidth: %f MHz...\n", bw / 1e6);
return srate;
......@@ -304,7 +288,7 @@ double uhd_device::set_sample_rate(const double sprate)
void uhd_device::set_rx_atn(const std::string & atn)
{
if (usrp)
uhd_usrp_set_rx_antenna(usrp,atn.c_str(),m_channel);
uhd_usrp_set_rx_antenna(usrp,atn.c_str(),m_rx_channel);
}
double uhd_device::set_rx_gain(double gain)
{
......@@ -312,10 +296,10 @@ double uhd_device::set_rx_gain(double gain)
return gain;
// Set gain
fprintf(stderr, "Setting RX Gain: %f dB...\n",(float) gain);
UHD_DO(uhd_usrp_set_rx_gain(usrp, gain,m_channel,""));
UHD_DO(uhd_usrp_set_rx_gain(usrp, gain,m_rx_channel,""));
// See what gain actually is
UHD_DO(uhd_usrp_get_rx_gain(usrp, m_channel,"", &gain));
UHD_DO(uhd_usrp_get_rx_gain(usrp, m_rx_channel,"", &gain));
fprintf(stderr, "Actual RX Gain: %lf...\n", gain);
return gain;
}
......@@ -325,19 +309,173 @@ double uhd_device::set_rx_bandwidth(double bw)
{
double srate = 0;
// See what rate actually is
UHD_DO(uhd_usrp_get_rx_rate(usrp, m_channel, &srate));
UHD_DO(uhd_usrp_get_rx_rate(usrp, m_rx_channel, &srate));
fprintf(stderr, "Current RX Rate: %f...\n", srate);
if (bw < 200000 || bw >=srate)
bw = srate;
fprintf(stderr, "Setting RX Bandwidth: %f MHz...\n", bw/1e6);
UHD_DO(uhd_usrp_set_rx_bandwidth(usrp, bw, m_channel));
UHD_DO(uhd_usrp_set_rx_bandwidth(usrp, bw, m_rx_channel));
//Band
UHD_DO(uhd_usrp_get_rx_bandwidth(usrp, m_channel, &bw));
UHD_DO(uhd_usrp_get_rx_bandwidth(usrp, m_rx_channel, &bw));
fprintf(stderr, "Actual RX Bandwidth: %f MHz...\n", bw / 1e6);
}
return bw;
}
void uhd_device::run_TxIO()
{
//创建流对象实例
char tx_cpu_format[] = "sc16";
char tx_otw_format[] = "sc16";
char tx_args[] = "";
const size_t tx_channel_count = 1;
//接收信号。MIMO时,可以指定0,1
size_t tx_channel[] = {(size_t)m_tx_channel};
uhd_stream_args_t tx_stream_args = {
/*.cpu_format = */tx_cpu_format,
/*.otw_format = */tx_otw_format,
/*.args = */tx_args,
/*.channel_list = */tx_channel,
/*.n_channels = */tx_channel_count
};
uhd_tx_streamer_handle tx_streamer = 0;
uhd_tx_metadata_handle tx_meta = 0;
m_tx_points = 0;
//发射线程
auto thcall_tx = [&]()->void{
// Create TX streamer
UHD_DO(uhd_tx_streamer_make(&tx_streamer));
// Create TX metadata
UHD_DO(uhd_tx_metadata_make(&tx_meta,false,0,0,true,false));
m_tx_streaming = true;
tx_stream_args.channel_list = tx_channel;
UHD_DO(uhd_usrp_get_tx_stream(usrp, &tx_stream_args, tx_streamer));
// Set up buffer
UHD_DO(uhd_tx_streamer_max_num_samps(tx_streamer, &m_txblock_size));
fprintf(stderr, "TX Buffer size in samples: %zu\n", m_txblock_size);
try {
while (!stop_signal_called)
{
const size_t off = m_tx_points % m_tx_bufsz;
const size_t new_begin = (m_tx_points +m_txblock_size ) % m_tx_bufsz;
if (new_begin < m_txblock_size)
memcpy(&m_data_iq_tx[m_tx_bufsz], m_data_iq_tx, sizeof(short)*2*new_begin);
size_t real_size = 0;
const void * addr = (void *)m_data_iq_tx[off];
UHD_DO(uhd_tx_streamer_send(tx_streamer, &addr, m_txblock_size, &tx_meta, 1, &real_size));
m_tx_points += real_size;
}
} catch (...) {
stop_signal_called = true;
}
m_tx_streaming = false;
};
//启动线程
uhd_io_thread * tx_thread = new uhd_io_thread(thcall_tx,0);
tx_thread->start(QThread::TimeCriticalPriority);
//主线程不断打印状态
while (!stop_signal_called)
{
std::this_thread::sleep_for(std::chrono::milliseconds(400));
}
if (tx_streamer) uhd_tx_streamer_free(&tx_streamer);
if (tx_meta) uhd_tx_metadata_free(&tx_meta);
//退出
tx_thread->wait();
tx_thread->deleteLater();
}
quint64 uhd_device::set_tx_freq(const quint64 freq_in_hz)
{
if (!usrp)
return freq_in_hz;
double srate = 0;
UHD_DO(uhd_usrp_get_tx_rate(usrp, m_rx_channel, &srate));
fprintf(stderr, "Setting TX frequency: %f MHz...\n", freq_in_hz/1e6);
uhd_tune_result_t tx_tune_result;
uhd_tune_request_t tx_tune_request =
{
/*.target_freq =*/ (double)freq_in_hz,
/*.rf_freq_policy =*/ UHD_TUNE_REQUEST_POLICY_AUTO,
/*.rf_freq =*/ 0,
/*.dsp_freq_policy = */UHD_TUNE_REQUEST_POLICY_AUTO,
/*.dsp_freq =*/ 0,
/*.args =*/ 0
};
UHD_DO(uhd_usrp_set_tx_freq(usrp, &tx_tune_request, m_tx_channel, &tx_tune_result));
double freq = 0;
UHD_DO(uhd_usrp_get_tx_freq(usrp, m_tx_channel, &freq));
fprintf(stderr, "Actual TX frequency: %f MHz...\n", freq / 1e6);
return (quint64)(freq +.5);
}
double uhd_device::set_tx_rate(const double sprate)
{
if (usrp)
{
double srate = sprate;
double bw = sprate;
if (bw >56e6)
bw = 56e6;
if (bw <200000 || bw > sprate)
bw = sprate;
fprintf(stderr, "Setting TX Rate: %f...\n", sprate);
UHD_DO(uhd_usrp_set_tx_rate(usrp, sprate, m_tx_channel));
// See what rate actually is
UHD_DO(uhd_usrp_get_tx_rate(usrp, m_tx_channel, &srate));
fprintf(stderr, "Actual TX Rate: %f...\n", srate);
fprintf(stderr, "Setting TX Bandwidth: %f MHz...\n", bw/1e6);
UHD_DO(uhd_usrp_set_tx_bandwidth(usrp, bw, m_tx_channel));
//Band
UHD_DO(uhd_usrp_get_tx_bandwidth(usrp, m_tx_channel, &bw));
fprintf(stderr, "Actual TX Bandwidth: %f MHz...\n", bw / 1e6);
return srate;
}
return sprate;
}
double uhd_device::set_tx_gain(double gain)
{
if (!usrp)
return gain;
// Set gain
fprintf(stderr, "Setting TX Gain: %f dB...\n",(float) gain);
UHD_DO(uhd_usrp_set_tx_gain(usrp, gain,m_tx_channel,""));
// See what gain actually is
UHD_DO(uhd_usrp_get_tx_gain(usrp, m_tx_channel,"", &gain));
fprintf(stderr, "Actual TX Gain: %lf...\n", gain);
return gain;
}
double uhd_device::set_tx_bandwidth(double bw)
{
if (usrp)
{
double srate = 0;
// See what rate actually is
UHD_DO(uhd_usrp_get_tx_rate(usrp, m_tx_channel, &srate));
fprintf(stderr, "Current TX Rate: %f...\n", srate);
if (bw < 200000 || bw >=srate)
bw = srate;
fprintf(stderr, "Setting TX Bandwidth: %f MHz...\n", bw/1e6);
UHD_DO(uhd_usrp_set_tx_bandwidth(usrp, bw, m_tx_channel));
//Band
UHD_DO(uhd_usrp_get_tx_bandwidth(usrp, m_tx_channel, &bw));
fprintf(stderr, "Actual RX Bandwidth: %f MHz...\n", bw / 1e6);
}
return bw;
}
#ifndef UHD_DEVICE_H
#ifndef UHD_DEVICE_H
#define UHD_DEVICE_H
#include <functional>
#include <vector>
......@@ -29,33 +29,41 @@ public:
public:
bool open_device();
bool close_device();
void run_IO();
void run_RxIO();
void run_TxIO();
protected:
std::atomic<bool> stop_signal_called;
std::atomic<bool> streaming;
std::atomic<bool> m_rx_streaming;
std::atomic<bool> m_tx_streaming;
std::string m_dev_args;
size_t m_spb_size = 10000;
size_t m_rxblock_size = 10000;
size_t m_txblock_size = 10000;
uhd_usrp_handle usrp = 0;
char error_string[512];
int return_code = 0;
int m_channel = 0;
int m_rx_channel = 0;
int m_tx_channel = 0;
protected:
//初始化队列
double * m_buffer_tmFrag;
long long * m_buffer_tmSec;
short * m_buffer_iq_all;
short * * m_buffer_iq;
size_t * m_buf_iqsize;
const int bufsz = 8192;
short (*m_data_iq_rx)[2] = nullptr;
size_t m_rx_bufsz = 1024*1024*8;
short (*m_data_iq_tx)[2] = nullptr;
size_t m_tx_bufsz = 1024*1024*8;
//收发计数
long long rx_count ;
unsigned long long m_rx_points = 0;
unsigned long long m_tx_points = 0;
public:
quint64 set_center_freq(const quint64 freq_in_hz);
double set_sample_rate(const double sprate);
quint64 set_rx_freq(const quint64 freq_in_hz);
double set_rx_rate(const double sprate);
void set_rx_atn(const std::string & ana);
double set_rx_gain(double);
double set_rx_bandwidth(double bw);
public:
quint64 set_tx_freq(const quint64 freq_in_hz);
double set_tx_rate(const double sprate);
double set_tx_gain(double);
double set_tx_bandwidth(double bw);
};
#endif // UHD_DEVICE_H
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册