specwidget.cpp 12.1 KB
Newer Older
丁劲犇's avatar
丁劲犇 已提交
1 2 3 4 5 6
#include "specwidget.h"
#include "ui_specwidget.h"
#include "qtgui/bookmarks.h"
#include <QSettings>
specWidget::specWidget(QWidget *parent) :
	QWidget(parent),
M
manjaro 已提交
7 8
	ui(new Ui::specWidget),
	m_runth(new uhd_io_thread(this))
丁劲犇's avatar
丁劲犇 已提交
9 10 11 12 13
{
	ui->setupUi(this);
	Bookmarks::create();

	loadSettings();
M
manjaro 已提交
14
	ui->plotter->setFftFill(false);
丁劲犇's avatar
丁劲犇 已提交
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
	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->setCenterFreq(101700000);
	//选择频率
	//ui->plotter->setDemodCenterFreq(102300000);
	ui->plotter->setTooltipsEnabled(true);
	ui->plotter->setPeakDetection(false,128.0);


	//连接
M
manjaro 已提交
32
	//connect (ui->plotter,&CPlotter::newDemodFreq,ui->freqCtrl,&CFreqCtrl::setFrequency);
丁劲犇's avatar
丁劲犇 已提交
33 34 35 36 37 38 39 40
	connect (ui->plotter,&CPlotter::newCenterFreq,this, &specWidget::evt_newCenterFreq);
	connect (ui->plotter,&CPlotter::newDemodFreq,this, &specWidget::evt_newDemodFreq);
	connect (ui->plotter,&CPlotter::newDemodFreq,this, &specWidget::slot_newDemodFreq);
	connect (ui->plotter,&CPlotter::newLowCutFreq,this, &specWidget::evt_newLowCutFreq);
	connect (ui->plotter,&CPlotter::newHighCutFreq,this, &specWidget::evt_newHighCutFreq);
	connect (ui->plotter,&CPlotter::newFilterFreq,this, &specWidget::evt_newFilterFreq);
	connect (ui->plotter,&CPlotter::pandapterRangeChanged,this, &specWidget::evt_pandapterRangeChanged);
	connect (ui->plotter,&CPlotter::newZoomLevel,this, &specWidget::evt_newZoomLevel);
M
manjaro 已提交
41
	connect (ui->freqCtrl,&CFreqCtrl::newFrequency,this, &specWidget::setCenterFreq);
丁劲犇's avatar
丁劲犇 已提交
42

M
manjaro 已提交
43
	//resetFFT();
丁劲犇's avatar
丁劲犇 已提交
44 45 46 47 48
}

specWidget::~specWidget()
{
	freeFFT();
M
manjaro 已提交
49

丁劲犇's avatar
丁劲犇 已提交
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
	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::setNewFftData(const double *  rfftData, int size)
{
	ui->plotter->setNewFftData(rfftData,size);
}
void specWidget::setNewFftDataWf(const double *  rfftData, const double *  rwfData, int size)
{
	ui->plotter->setNewFftData(rfftData,rwfData,size);
}
void specWidget::setMaxPixmapSize(int w, int h)
{
	ui->plotter->setMaxPixmapSize(QSize(w,h));
}
void specWidget::setRunningState(bool running)
{
	ui->plotter->setRunningState(running);
}
void specWidget::setClickResolution(int clickres)
{
	ui->plotter->setClickResolution(clickres);
}
void specWidget::setFilterClickResolution(int clickres)
{
	ui->plotter->setFilterClickResolution(clickres);
}
void specWidget::setFilterBoxEnabled(bool enabled)
{
	ui->plotter->setFilterBoxEnabled(enabled);
}
void specWidget::setCenterLineEnabled(bool enabled)
{
	ui->plotter->setCenterLineEnabled(enabled);
}
void specWidget::setTooltipsEnabled(bool enabled){
	ui->plotter->setTooltipsEnabled(enabled);
}
void specWidget::setBookmarksEnabled(bool enabled){
	ui->plotter->setBookmarksEnabled(enabled);
}
void specWidget::setCenterFreq(quint64 f){
M
manjaro 已提交
108 109 110 111 112 113 114 115 116 117 118
	if (usrp)
	{
		using uhd::tune_request_t;
		tune_request_t tune_request_rx = tune_request_t((double)f, 0);
		usrp->set_rx_freq(tune_request_rx,m_channel);
		ui->plotter->setCenterFreq(usrp->get_rx_freq(m_channel));

	}
	if (ui->doubleSpinBox_center->value() * 1e6 !=ui->freqCtrl->getFrequency())
		ui->doubleSpinBox_center->setValue(ui->freqCtrl->getFrequency()/1e6);
	//ui->plotter->setCenterFreq(f);
丁劲犇's avatar
丁劲犇 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
}
void specWidget::setFreqUnits(qint32 unit){
	ui->plotter->setFreqUnits(unit);
}
void specWidget::setDemodCenterFreq(quint64 f){
	ui->plotter->setDemodCenterFreq(f);
}
void specWidget::setFilterOffset(qint64 freq_hz){
	ui->plotter->setFilterOffset(freq_hz);
}
qint64 specWidget::getFilterOffset(void){
	return ui->plotter->getFilterOffset();
}
int specWidget::getFilterBw(){
	return ui->plotter->getFilterBw();
}
void specWidget::setHiLowCutFrequencies(int LowCut, int HiCut){
	ui->plotter->setHiLowCutFrequencies(LowCut,HiCut);
}
void specWidget::getHiLowCutFrequencies(int *LowCut, int *HiCut){
	ui->plotter->getHiLowCutFrequencies(LowCut,HiCut);
}
void specWidget::setDemodRanges(int FLowCmin, int FLowCmax, int FHiCmin, int FHiCmax, bool symetric){
	ui->plotter->setDemodRanges(FLowCmin, FLowCmax, FHiCmin, FHiCmax, symetric);
}
void specWidget::setSpanFreq(quint32 s){
	ui->plotter->setSpanFreq(s);
}
void specWidget::setMaxBandiwdth(int m){
	ui->plotter->setMaxBandiwdth(m);
}
void specWidget::setHdivDelta(int delta){
	ui->plotter->setHdivDelta(delta);
}
void specWidget::setVdivDelta(int delta){
	ui->plotter->setVdivDelta(delta);
}
void specWidget::setFreqDigits(int digits){
	ui->plotter->setFreqDigits(digits);
}
void specWidget::setSampleRate(double rate){
M
manjaro 已提交
160 161 162 163 164 165 166 167 168 169 170 171
	if (usrp)
	{
		double bw = rate;
		if (bw >56e6)
			bw = 56e6;
		if (bw <200000)
			bw = 200000;
		fprintf(stderr,"bw = %lf\n",bw);
		usrp->set_rx_rate(rate);
		usrp->set_rx_bandwidth(bw,m_channel);
		ui->plotter->setSampleRate(usrp->get_rx_rate(m_channel));
	}
丁劲犇's avatar
丁劲犇 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
}
double specWidget::getSampleRate(void){
	return ui->plotter->getSampleRate();
}
void specWidget::setFftCenterFreq(qint64 f){
	ui->plotter->setFftCenterFreq(f);
}
int     specWidget::getNearestPeak(QPoint pt){
	return ui->plotter->getNearestPeak(pt);
}
void    specWidget::setWaterfallSpan(quint64 span_ms){
	ui->plotter->setWaterfallSpan(span_ms);
}
quint64 specWidget::getWfTimeRes(void){
	return ui->plotter->getWfTimeRes();
}
void    specWidget::setFftRate(int rate_hz){
	ui->plotter->setFftRate(rate_hz);
}
void    specWidget::clearWaterfall(void){
	return ui->plotter->clearWaterfall();
}
bool    specWidget::saveWaterfall(const QString & filename)
{
	return ui->plotter->saveWaterfall(filename);
}

void specWidget::on_pushButton_reset_clicked()
{
	saveSettings();
	loadSettings();
	resetFFT();
}

void specWidget::loadSettings()
{
	QSettings settings(QCoreApplication::applicationFilePath()+".ini", QSettings::IniFormat);

M
manjaro 已提交
210
	const bool checkBox_iq = true;
丁劲犇's avatar
丁劲犇 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
	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<<comboBox_fftSize) * 128;
	if (m_nFFTSize>65536)
		m_nFFTSize = 65536;
	if (m_nFFTSize<128)
		m_nFFTSize = 128;

}
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);
}
void specWidget::freeFFT()
{
	if (m_nTimerID>=0)
	{
		killTimer(m_nTimerID);
		m_nTimerID = -1;
	}
	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::resetFFT()
{
	freeFFT();
	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;
	if (m_nTimerID>=0)
		killTimer(m_nTimerID);

M
manjaro 已提交
302
	if (usrp)
丁劲犇's avatar
丁劲犇 已提交
303
	{
M
manjaro 已提交
304
		close_device();
丁劲犇's avatar
丁劲犇 已提交
305 306
	}

M
manjaro 已提交
307 308 309 310
	if (!usrp)
		open_device();

	if (!usrp)
丁劲犇's avatar
丁劲犇 已提交
311 312
		return;

M
manjaro 已提交
313 314
	setSampleRate(getSampleRate());
	setCenterFreq(ui->plotter->getCenterFreq());
丁劲犇's avatar
丁劲犇 已提交
315

M
manjaro 已提交
316
	if (m_runth->isRunning())
丁劲犇's avatar
丁劲犇 已提交
317
	{
M
manjaro 已提交
318 319
		stop_signal_called = true;
		m_runth->wait();
丁劲犇's avatar
丁劲犇 已提交
320 321
	}

M
manjaro 已提交
322 323 324 325 326 327
	m_runth->setRunner([&](void){
		run_IO();
	});
	m_runth->start();
	m_nTimerID = startTimer(updateIntelv);

丁劲犇's avatar
丁劲犇 已提交
328
}
M
manjaro 已提交
329

丁劲犇's avatar
丁劲犇 已提交
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
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
			|| m_dFFTAmp.size()!=m_nFFTSize)
		return;
	memset(m_pFFTIn,0,sizeof(fftw_complex)*m_nFFTSize);
	const int nFFTCp = m_nFFTSize<count?m_nFFTSize:count;
	for (long long i=0;i<nFFTCp ;++i)
	{
		long long nHammingIdx = i * m_nFFTSize / nFFTCp;
		m_pFFTIn[i][0] = pWav[i][0] * m_dHammingWnd[nHammingIdx];
		m_pFFTIn[i][1] = pWav[i][1] * m_dHammingWnd[nHammingIdx];
	}
	fftw_execute(m_pFFTPlan);
	const double minus = 10 *log(m_nFFTSize * voltage_ref * m_nFFTSize)/log(10);

	for (long i = 0; i< m_nFFTSize ;++i)
	{
		m_dFFTAmp[(i+m_nFFTSize/2) % m_nFFTSize] = 5 * log (m_pFFTOut[i][0] * m_pFFTOut[i][0] + m_pFFTOut[i][1] * m_pFFTOut[i][1])/log(10) - minus + m_dManuAdd;
	}

	setNewFftData(m_dFFTAmp.data(),m_nFFTSize);
}


void specWidget::timerEvent(QTimerEvent * e)
{
	static std::shared_ptr<double> ppbuf(new double [65536*4]);
M
manjaro 已提交
358 359 360
	static double (*pBufIQ)[2] = (double (*)[2])ppbuf.get();

	const int fft_bytes_needed = m_nFFTSize *2 * 2;
丁劲犇's avatar
丁劲犇 已提交
361
	//int fft
M
manjaro 已提交
362
	if (e->timerId()==m_nTimerID)
丁劲犇's avatar
丁劲犇 已提交
363
	{
M
manjaro 已提交
364
		const int sppoints = fft_bytes_needed/(sizeof(short))/(2);
丁劲犇's avatar
丁劲犇 已提交
365
		Q_ASSERT(sppoints == m_nFFTSize);
M
manjaro 已提交
366 367 368 369 370
		double ref1v = 16384;
		int curr_tx = (rx_count + bufsz -  100) % bufsz ;
		int total_cp = 0;
		memset(pBufIQ,0,sizeof(double)*2*sppoints);
		while (total_cp < sppoints)
丁劲犇's avatar
丁劲犇 已提交
371
		{
M
manjaro 已提交
372 373 374
			const size_t sz = vec_buffersz[curr_tx];
			const short (*datap)[2]  = (const short (*)[2])vec_buffer[curr_tx].get();
			for (size_t i=0;i<sz  &&  total_cp < sppoints;++i,++total_cp)
丁劲犇's avatar
丁劲犇 已提交
375
			{
M
manjaro 已提交
376 377 378 379
				double hv = (1 -0.46 ) - 0.46 * cos(2*3.1415926*total_cp/(sppoints-1));
				pBufIQ[total_cp][0] =datap[i][0] * hv;
				pBufIQ[total_cp][1] =datap[i][1] * hv;

丁劲犇's avatar
丁劲犇 已提交
380
			}
M
manjaro 已提交
381 382 383 384
			++curr_tx;
			curr_tx %= bufsz;
			if (!sz)
				break;
丁劲犇's avatar
丁劲犇 已提交
385
		}
M
manjaro 已提交
386
		appendWavComplex(pBufIQ,sppoints,ref1v);
丁劲犇's avatar
丁劲犇 已提交
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413

		if (m_nCurrentCenter>=0 && m_nCurrentCenter < m_nFFTSize)
		{
			ui->sMeter->setLevel(m_dFFTAmp[m_nCurrentCenter]);
			//ui->sMeter->setSqlLevel(m_dFFTAmp[m_nCurrentCenter]);
		}

	}
}



void specWidget::on_doubleSpinBox_center_2_valueChanged(double arg1)
{
	m_dManuAdd = arg1;
}

void specWidget::on_comboBox_fftSize_activated(int index)
{
	if (index)
		m_nFFTSize = 128 * (1<<index);
	if (m_nFFTSize>65536)
		m_nFFTSize = 65536;
	if (m_nFFTSize<128)
		m_nFFTSize = 128;
	saveSettings();
}
M
manjaro 已提交
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439

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)
		usrp->set_rx_gain(arg1,m_channel);
	//usrp->set_rx_agc(true,m_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());
}