Merge pull request #143 from cjcliffe/master

update lab
This commit is contained in:
Charles J. Cliffe 2015-09-12 14:11:55 -04:00
commit eaaf6cd02e
26 changed files with 310 additions and 152 deletions

View File

@ -2,8 +2,8 @@ cmake_minimum_required (VERSION 2.8)
SET(CUBICSDR_VERSION_MAJOR "0")
SET(CUBICSDR_VERSION_MINOR "1")
SET(CUBICSDR_VERSION_PATCH "3")
SET(CUBICSDR_VERSION_REL "beta")
SET(CUBICSDR_VERSION_PATCH "6")
SET(CUBICSDR_VERSION_REL "beta-issue140")
SET(CUBICSDR_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}-${CUBICSDR_VERSION_REL}")
SET(CPACK_PACKAGE_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}")
@ -264,6 +264,7 @@ SET (cubicsdr_sources
src/process/ScopeVisualProcessor.cpp
src/process/SpectrumVisualProcessor.cpp
src/process/FFTVisualDataThread.cpp
src/process/FFTDataDistributor.cpp
src/process/SpectrumVisualDataThread.cpp
src/ui/GLPanel.cpp
external/rtaudio/RtAudio.cpp
@ -319,6 +320,7 @@ SET (cubicsdr_headers
src/process/ScopeVisualProcessor.h
src/process/SpectrumVisualProcessor.h
src/process/FFTVisualDataThread.h
src/process/FFTDataDistributor.h
src/process/SpectrumVisualDataThread.h
src/ui/GLPanel.h
src/ui/UITestCanvas.cpp
@ -423,6 +425,13 @@ IF (MSVC)
set(CMAKE_CREATE_WIN32_EXE "/SUBSYSTEM:WINDOWS /ENTRY:\"mainCRTStartup\"")
ENDIF(MSVC)
IF (APPLE)
ADD_DEFINITIONS(
-DHAVE_TYPE_TRAITS=1
-mmacosx-version-min=10.9
)
ENDIF(APPLE)
IF (APPLE AND BUNDLE_APP)
PROJECT(CubicSDR)
SET(MACOSX_BUNDLE_BUNDLE_NAME CubicSDR)
@ -431,8 +440,6 @@ IF (APPLE AND BUNDLE_APP)
-std=c++0x
-pthread
-D_OSX_APP_
-DHAVE_TYPE_TRAITS=1
-mmacosx-version-min=10.9
)
ADD_EXECUTABLE(CubicSDR

View File

@ -42,7 +42,7 @@ Features and Status:
- [x] Spectrum
- [x] Waterfall
- [x] Add faint grid for sense of scale
- [ ] Audio Spectrum
- [x] Audio Spectrum
- [ ] X/Y Scope
- [ ] Indicate outer spectrum edges when zoomed
- [ ] 3D visuals
@ -67,8 +67,8 @@ Features and Status:
- [x] Display audio output selection
- [x] Volume control
- [x] Direct frequency input
- [ ] Mute
- [ ] Waterfall speed
- [x] Mute
- [x] Waterfall speed
- [ ] RTL-SDR Gain
- Basic Input Controls
- [x] Drag spectrum to change center frequency
@ -123,7 +123,7 @@ Features and Status:
- Optimization
- [x] Eliminate large waterfall texture uploads
- [ ] Update visuals to OpenGL 3.x / OpenGL ES
- [ ] Resolve constant refresh on visuals that don't change often
- [x] Resolve constant refresh on visuals that don't change often
- [ ] Resolve all driver/platform vertical sync issues
- [ ] Group and divide IQ data distribution workload instead of 100% distribution per instance

Binary file not shown.

View File

@ -49,7 +49,7 @@ AppFrame::AppFrame() :
wxBoxSizer *demodTray = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *demodScopeTray = new wxBoxSizer(wxVERTICAL);
int attribList[] = { WX_GL_RGBA, WX_GL_STENCIL_SIZE, 8, WX_GL_BUFFER_SIZE, 24, WX_GL_DOUBLEBUFFER, 0 };
int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
demodModeSelector = new ModeSelectorCanvas(this, attribList);
demodModeSelector->addChoice(DEMOD_TYPE_FM, "FM");
@ -104,6 +104,7 @@ AppFrame::AppFrame() :
demodSpectrumCanvas->attachWaterfallCanvas(demodWaterfallCanvas);
demodVisuals->Add(demodWaterfallCanvas, 6, wxEXPAND | wxALL, 0);
wxGetApp().getDemodSpectrumProcessor()->attachOutput(demodWaterfallCanvas->getVisualDataQueue());
demodWaterfallCanvas->getVisualDataQueue()->set_max_num_items(3);
demodTray->Add(demodVisuals, 30, wxEXPAND | wxALL, 0);
@ -148,6 +149,7 @@ AppFrame::AppFrame() :
demodMuteButton->setHighlightColor(RGBA4f(0.8,0.2,0.2));
demodMuteButton->setHelpTip("Demodulator Mute Toggle");
demodMuteButton->setToggleMode(true);
demodMuteButton->setSelection(-1);
demodGainTray->Add(demodMuteButton, 1, wxEXPAND | wxALL, 0);
@ -422,6 +424,7 @@ AppFrame::AppFrame() :
waterfallSpeedMeter->setLevel(sqrt(wflps));
waterfallDataThread->setLinesPerSecond(wflps);
waterfallCanvas->setLinesPerSecond(wflps);
ThemeMgr::mgr.setTheme(wxGetApp().getConfig()->getTheme());
@ -534,6 +537,7 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
spectrumCanvas->setBandwidth(wxGetApp().getSampleRate());
spectrumCanvas->setCenterFrequency(wxGetApp().getFrequency());
waterfallDataThread->setLinesPerSecond(DEFAULT_WATERFALL_LPS);
waterfallCanvas->setLinesPerSecond(DEFAULT_WATERFALL_LPS);
waterfallSpeedMeter->setLevel(sqrt(DEFAULT_WATERFALL_LPS));
wxGetApp().getSpectrumProcessor()->setFFTAverageRate(0.65);
spectrumAvgMeter->setLevel(0.65);
@ -893,6 +897,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
float val = waterfallSpeedMeter->getInputValue();
waterfallSpeedMeter->setLevel(val);
waterfallDataThread->setLinesPerSecond((int)ceil(val*val));
waterfallCanvas->setLinesPerSecond((int)ceil(val*val));
GetStatusBar()->SetStatusText(wxString::Format(wxT("Waterfall max speed changed to %d lines per second."),(int)ceil(val*val)));
}
@ -900,8 +905,10 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
wproc->setBandwidth(waterfallCanvas->getBandwidth());
wproc->setCenterFrequency(waterfallCanvas->getCenterFrequency());
waterfallCanvas->processInputQueue();
demodWaterfallCanvas->processInputQueue();
// waterfallCanvas->processInputQueue();
// waterfallCanvas->Refresh();
// demodWaterfallCanvas->processInputQueue();
// demodWaterfallCanvas->Refresh();
if (!this->IsActive()) {
std::this_thread::sleep_for(std::chrono::milliseconds(25));

View File

@ -89,7 +89,7 @@ bool CubicSDR::OnInit() {
pipeSpectrumIQVisualData->set_max_num_items(1);
pipeWaterfallIQVisualData = new DemodulatorThreadInputQueue();
pipeWaterfallIQVisualData->set_max_num_items(DEFAULT_WATERFALL_LPS);
pipeWaterfallIQVisualData->set_max_num_items(128);
spectrumDistributor.attachOutput(pipeDemodIQVisualData);
spectrumDistributor.attachOutput(pipeSpectrumIQVisualData);
@ -113,7 +113,7 @@ bool CubicSDR::OnInit() {
sdrThread->setOutputQueue("IQDataOutput",pipeSDRIQData);
sdrPostThread = new SDRPostThread();
sdrPostThread->setNumVisSamples(BUF_SIZE);
// sdrPostThread->setNumVisSamples(BUF_SIZE);
sdrPostThread->setInputQueue("IQDataInput", pipeSDRIQData);
sdrPostThread->setOutputQueue("IQVisualDataOutput", pipeIQVisualData);
sdrPostThread->setOutputQueue("IQDataOutput", pipeWaterfallIQVisualData);
@ -321,7 +321,7 @@ SpectrumVisualProcessor *CubicSDR::getDemodSpectrumProcessor() {
return demodVisualThread->getProcessor();
}
VisualDataDistributor<DemodulatorThreadIQData> *CubicSDR::getSpectrumDistributor() {
VisualDataReDistributor<DemodulatorThreadIQData> *CubicSDR::getSpectrumDistributor() {
return &spectrumDistributor;
}
@ -450,6 +450,10 @@ void CubicSDR::showFrequencyInput(FrequencyDialog::FrequencyDialogTarget targetM
fdialog.ShowModal();
}
AppFrame *CubicSDR::getAppFrame() {
return appframe;
}
void CubicSDR::setFrequencySnap(int snap) {
if (snap > 1000000) {
snap = 1000000;

View File

@ -60,7 +60,7 @@ public:
ScopeVisualProcessor *getScopeProcessor();
SpectrumVisualProcessor *getSpectrumProcessor();
SpectrumVisualProcessor *getDemodSpectrumProcessor();
VisualDataDistributor<DemodulatorThreadIQData> *getSpectrumDistributor();
VisualDataReDistributor<DemodulatorThreadIQData> *getSpectrumDistributor();
DemodulatorThreadOutputQueue* getAudioVisualQueue();
DemodulatorThreadInputQueue* getIQVisualQueue();
@ -80,7 +80,8 @@ public:
int getPPM();
void showFrequencyInput(FrequencyDialog::FrequencyDialogTarget targetMode = FrequencyDialog::FDIALOG_TARGET_DEFAULT);
AppFrame *getAppFrame();
private:
AppFrame *appframe;
AppConfig config;
@ -110,7 +111,7 @@ private:
ScopeVisualProcessor scopeProcessor;
VisualDataDistributor<DemodulatorThreadIQData> spectrumDistributor;
VisualDataReDistributor<DemodulatorThreadIQData> spectrumDistributor;
std::thread *t_SDR;
std::thread *t_PostSDR;

View File

@ -8,6 +8,7 @@
#include <iostream>
#include "ThreadQueue.h"
#include "Timer.h"
struct map_string_less : public std::binary_function<std::string,std::string,bool>
{
@ -112,9 +113,9 @@ public:
void setOutputQueue(std::string qname, ThreadQueueBase *threadQueue);
void *getOutputQueue(std::string qname);
protected:
std::map<std::string, ThreadQueueBase *, map_string_less> input_queues;
std::map<std::string, ThreadQueueBase *, map_string_less> output_queues;
std::atomic_bool terminated;
Timer gTimer;
};

View File

@ -81,6 +81,13 @@ public:
}
DemodulatorThreadIQData & operator=(const DemodulatorThreadIQData &other) {
frequency = other.frequency;
sampleRate = other.sampleRate;
data.assign(other.data.begin(), other.data.end());
return *this;
}
~DemodulatorThreadIQData() {
}

View File

@ -7,7 +7,7 @@
DemodulatorMgr::DemodulatorMgr() :
activeDemodulator(NULL), lastActiveDemodulator(NULL), activeVisualDemodulator(NULL), lastBandwidth(DEFAULT_DEMOD_BW), lastDemodType(
DEFAULT_DEMOD_TYPE), lastSquelchEnabled(false), lastSquelch(0), lastGain(1.0), lastStereo(false) {
DEFAULT_DEMOD_TYPE), lastSquelchEnabled(false), lastSquelch(0), lastGain(1.0), lastStereo(false), lastMuted(false) {
}

View File

@ -696,8 +696,8 @@ void DemodulatorThread::run() {
}
ati->data.resize(numAudioWritten * 2);
for (int i = 0; i < numAudioWritten; i++) {
ati->data[i * 2] = (*inputData)[i].real;
ati->data[i * 2 + 1] = (*inputData)[i].imag;
ati->data[i * 2] = (*inputData)[i].imag;
ati->data[i * 2 + 1] = (*inputData)[i].real;
}
} else if (stereo && inp->sampleRate >= 100000) {
ati->channels = 2;

View File

@ -4,8 +4,16 @@
#include <iostream>
#include <iomanip>
#include "ColorTheme.h"
#include "CubicSDRDefs.h"
SpectrumPanel::SpectrumPanel() : floorValue(0), ceilValue(1), showDb(false), fftSize(2048) {
SpectrumPanel::SpectrumPanel() {
floorValue = 0;
ceilValue = 1;
showDb = false;
fftSize = DEFAULT_FFT_SIZE;
bandwidth = DEFAULT_DEMOD_BW;
freq = 0;
setFill(GLPANEL_FILL_GRAD_Y);
setFillColor(ThemeMgr::mgr.currentTheme->fftBackground * 2.0, ThemeMgr::mgr.currentTheme->fftBackground);
@ -233,15 +241,18 @@ void SpectrumPanel::drawPanelContents() {
float dbPanelHeight = (1.0/viewHeight)*14.0;
std::stringstream ssLabel;
ssLabel << std::fixed << std::setprecision(1) << (20.0 * log10(2.0*(getCeilValue())/(double)fftSize)) << "dB";
std::stringstream ssLabel("");
if (getCeilValue() != getFloorValue() && fftSize) {
ssLabel << std::fixed << std::setprecision(1) << (20.0 * log10(2.0*(getCeilValue())/(double)fftSize)) << "dB";
}
dbPanelCeil.setText(ssLabel.str(), GLFont::GLFONT_ALIGN_RIGHT);
dbPanelCeil.setSize(dbPanelWidth, dbPanelHeight);
dbPanelCeil.setPosition(-1.0 + dbPanelWidth, 1.0 - dbPanelHeight);
ssLabel.str("");
ssLabel << (20.0 * log10(2.0*(getFloorValue())/(double)fftSize)) << "dB";
if (getCeilValue() != getFloorValue() && fftSize) {
ssLabel << (20.0 * log10(2.0*(getFloorValue())/(double)fftSize)) << "dB";
}
dbPanelFloor.setText(ssLabel.str(), GLFont::GLFONT_ALIGN_RIGHT);
dbPanelFloor.setSize(dbPanelWidth, dbPanelHeight);

View File

@ -0,0 +1,81 @@
#include "FFTDataDistributor.h"
FFTDataDistributor::FFTDataDistributor() : linesPerSecond(DEFAULT_WATERFALL_LPS), lineRateAccum(0.0), fftSize(DEFAULT_FFT_SIZE) {
}
void FFTDataDistributor::setFFTSize(int fftSize) {
this->fftSize = fftSize;
}
void FFTDataDistributor::setLinesPerSecond(int lines) {
this->linesPerSecond = lines;
}
int FFTDataDistributor::getLinesPerSecond() {
return this->linesPerSecond;
}
void FFTDataDistributor::process() {
while (!input->empty()) {
if (!isAnyOutputEmpty()) {
return;
}
DemodulatorThreadIQData *inp;
input->pop(inp);
if (inp) {
if (inputBuffer.sampleRate != inp->sampleRate || inputBuffer.frequency != inp->frequency) {
inputBuffer.sampleRate = inp->sampleRate;
inputBuffer.frequency = inp->frequency;
inputBuffer.data.assign(inp->data.begin(), inp->data.end());
} else {
inputBuffer.data.insert(inputBuffer.data.end(), inp->data.begin(), inp->data.end());
}
inp->decRefCount();
} else {
continue;
}
// number of seconds contained in input
double inputTime = (double)inputBuffer.data.size() / (double)inputBuffer.sampleRate;
// number of lines in input
double inputLines = (double)inputBuffer.data.size()/(double)fftSize;
// ratio required to achieve the desired rate
double lineRateStep = ((double)linesPerSecond * inputTime)/(double)inputLines;
if (inputBuffer.data.size() >= fftSize) {
int numProcessed = 0;
if (lineRateAccum + (lineRateStep * ((double)inputBuffer.data.size()/(double)fftSize)) < 1.0) {
// move along, nothing to see here..
lineRateAccum += (lineRateStep * ((double)inputBuffer.data.size()/(double)fftSize));
numProcessed = inputBuffer.data.size();
} else {
for (int i = 0, iMax = inputBuffer.data.size(); i < iMax; i += fftSize) {
if ((i + fftSize) > iMax) {
break;
}
lineRateAccum += lineRateStep;
if (lineRateAccum >= 1.0) {
DemodulatorThreadIQData *outp = outputBuffers.getBuffer();
outp->frequency = inputBuffer.frequency;
outp->sampleRate = inputBuffer.sampleRate;
outp->data.assign(inputBuffer.data.begin()+i,inputBuffer.data.begin()+i+fftSize);
distribute(outp);
while (lineRateAccum >= 1.0) {
lineRateAccum -= 1.0;
}
}
numProcessed += fftSize;
}
}
if (numProcessed) {
inputBuffer.data.erase(inputBuffer.data.begin(), inputBuffer.data.begin() + numProcessed);
}
}
}
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "VisualProcessor.h"
#include "DemodDefs.h"
#include <cmath>
class FFTDataDistributor : public VisualProcessor<DemodulatorThreadIQData, DemodulatorThreadIQData> {
public:
FFTDataDistributor();
void setFFTSize(int fftSize);
void setLinesPerSecond(int lines);
int getLinesPerSecond();
protected:
void process();
DemodulatorThreadIQData inputBuffer, tempBuffer;
ReBuffer<DemodulatorThreadIQData> outputBuffers;
int fftSize;
int linesPerSecond;
double lineRateAccum;
};

View File

@ -1,7 +1,8 @@
#include "FFTVisualDataThread.h"
#include "CubicSDR.h"
FFTVisualDataThread::FFTVisualDataThread() : linesPerSecond(DEFAULT_WATERFALL_LPS) {
FFTVisualDataThread::FFTVisualDataThread() {
linesPerSecond.store(DEFAULT_WATERFALL_LPS);
lpsChanged.store(true);
}
@ -36,7 +37,8 @@ void FFTVisualDataThread::run() {
while(!terminated) {
std::this_thread::sleep_for(std::chrono::milliseconds(12));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
// std::this_thread::yield();
int fftSize = wproc.getDesiredInputSize();
@ -48,7 +50,7 @@ void FFTVisualDataThread::run() {
if (lpsChanged.load()) {
fftDistrib.setLinesPerSecond(linesPerSecond.load());
pipeIQDataIn->set_max_num_items(linesPerSecond.load());
// pipeIQDataIn->set_max_num_items(linesPerSecond.load());
lpsChanged.store(false);
}

View File

@ -2,6 +2,7 @@
#include "IOThread.h"
#include "SpectrumVisualProcessor.h"
#include "FFTDataDistributor.h"
class FFTVisualDataThread : public IOThread {
public:

View File

@ -16,7 +16,8 @@ void SpectrumVisualDataThread::run() {
std::cout << "Spectrum visual data thread started." << std::endl;
while(!terminated) {
std::this_thread::sleep_for(std::chrono::milliseconds(12));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
// std::this_thread::yield();
sproc.run();
}

View File

@ -69,75 +69,3 @@ private:
std::atomic_int desiredInputSize;
std::mutex busy_run;
};
class FFTDataDistributor : public VisualProcessor<DemodulatorThreadIQData, DemodulatorThreadIQData> {
public:
FFTDataDistributor() : linesPerSecond(DEFAULT_WATERFALL_LPS), lineRateAccum(0.0) {
}
void setFFTSize(int fftSize) {
this->fftSize = fftSize;
}
void setLinesPerSecond(int lines) {
this->linesPerSecond = lines;
}
int getLinesPerSecond() {
return this->linesPerSecond;
}
protected:
void process() {
while (!input->empty()) {
if (!isAnyOutputEmpty()) {
return;
}
DemodulatorThreadIQData *inp;
input->pop(inp);
int fftSize = this->fftSize;
if (fftSize > inp->data.size()) {
fftSize = inp->data.size();
}
// number of milliseconds contained in input
double inputTime = (double)inp->data.size() / (double)inp->sampleRate;
// number of lines in input
int inputLines = floor((double)inp->data.size()/(double)fftSize);
// ratio required to achieve the desired rate
double lineRateStep = ((double)linesPerSecond * inputTime)/(double)inputLines;
if (inp) {
if (inp->data.size() >= fftSize) {
if (lineRateAccum + (lineRateStep * floor((double)inp->data.size()/(double)fftSize)) < 1.0) {
// move along, nothing to see here..
lineRateAccum += (lineRateStep * inp->data.size()/fftSize);
} else for (int i = 0, iMax = inp->data.size()-fftSize; i <= iMax; i += fftSize) {
lineRateAccum += lineRateStep;
if (lineRateAccum >= 1.0) {
DemodulatorThreadIQData *outp = outputBuffers.getBuffer();
outp->frequency = inp->frequency;
outp->sampleRate = inp->sampleRate;
outp->data.assign(inp->data.begin()+i,inp->data.begin()+i+fftSize);
distribute(outp);
while (lineRateAccum >= 1.0) {
lineRateAccum -= 1.0;
}
}
}
}
inp->decRefCount();
}
}
}
ReBuffer<DemodulatorThreadIQData> outputBuffers;
int fftSize;
int linesPerSecond;
double lineRateAccum;
};

View File

@ -107,3 +107,25 @@ protected:
}
};
template<class OutputDataType = ReferenceCounter>
class VisualDataReDistributor : public VisualProcessor<OutputDataType, OutputDataType> {
protected:
void process() {
while (!VisualProcessor<OutputDataType, OutputDataType>::input->empty()) {
if (!VisualProcessor<OutputDataType, OutputDataType>::isAnyOutputEmpty()) {
return;
}
OutputDataType *inp;
VisualProcessor<OutputDataType, OutputDataType>::input->pop(inp);
if (inp) {
OutputDataType *outp = buffers.getBuffer();
(*outp) = (*inp);
inp->decRefCount();
VisualProcessor<OutputDataType, OutputDataType>::distribute(outp);
}
}
}
ReBuffer<OutputDataType> buffers;
};

View File

@ -6,7 +6,7 @@
#include <deque>
SDRPostThread::SDRPostThread() : IOThread(),
iqDataInQueue(NULL), iqDataOutQueue(NULL), iqVisualQueue(NULL), dcFilter(NULL), num_vis_samples(16384*2) {
iqDataInQueue(NULL), iqDataOutQueue(NULL), iqVisualQueue(NULL), dcFilter(NULL){
swapIQ.store(false);
@ -50,14 +50,6 @@ void SDRPostThread::removeDemodulator(DemodulatorInstance *demod) {
busy_demod.unlock();
}
void SDRPostThread::setNumVisSamples(int num_vis_samples_in) {
num_vis_samples = num_vis_samples_in;
}
int SDRPostThread::getNumVisSamples() {
return num_vis_samples;
}
void SDRPostThread::setSwapIQ(bool swapIQ) {
this->swapIQ.store(swapIQ);
}
@ -93,7 +85,6 @@ void SDRPostThread::run() {
iqDataInQueue->pop(data_in);
// std::lock_guard < std::mutex > lock(data_in->m_mutex);
int num_vis_samples = this->num_vis_samples;
if (data_in && data_in->data.size()) {
int dataSize = data_in->data.size()/2;
@ -118,21 +109,19 @@ void SDRPostThread::run() {
iirfilt_crcf_execute_block(dcFilter, &fpData[0], dataSize, &dataOut[0]);
if (iqVisualQueue != NULL && iqVisualQueue->empty()) {
if (iqVisualQueue != NULL && !iqVisualQueue->full()) {
DemodulatorThreadIQData *visualDataOut = visualDataBuffers.getBuffer();
visualDataOut->setRefCount(1);
if (num_vis_samples > dataOut.size()) {
num_vis_samples = dataOut.size();
}
int num_vis_samples = dataOut.size();
if (visualDataOut->data.size() < num_vis_samples) {
if (visualDataOut->data.capacity() < num_vis_samples) {
visualDataOut->data.reserve(num_vis_samples);
}
visualDataOut->data.resize(num_vis_samples);
}
// if (visualDataOut->data.size() < num_vis_samples) {
// if (visualDataOut->data.capacity() < num_vis_samples) {
// visualDataOut->data.reserve(num_vis_samples);
// }
// visualDataOut->data.resize(num_vis_samples);
// }
//
visualDataOut->frequency = data_in->frequency;
visualDataOut->sampleRate = data_in->sampleRate;
visualDataOut->data.assign(dataOut.begin(), dataOut.begin() + num_vis_samples);

View File

@ -11,9 +11,6 @@ public:
void bindDemodulator(DemodulatorInstance *demod);
void removeDemodulator(DemodulatorInstance *demod);
void setNumVisSamples(int num_vis_samples_in);
int getNumVisSamples();
void setSwapIQ(bool swapIQ);
bool getSwapIQ();
@ -28,7 +25,6 @@ protected:
std::mutex busy_demod;
std::vector<DemodulatorInstance *> demodulators;
iirfilt_crcf dcFilter;
int num_vis_samples;
std::atomic_bool swapIQ;
ReBuffer<DemodulatorThreadIQData> visualDataBuffers;

View File

@ -1,11 +1,14 @@
#include "Timer.h"
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
#include <mmsystem.h>
#endif
Timer::Timer(void) : time_elapsed(0), system_milliseconds(0), start_time(0), end_time(0), last_update(0), num_updates(0), paused_time(0), offset(0), paused_state(false), lock_state(0), lock_rate(0)
#include <iostream>
Timer::Timer(void) : time_elapsed(0), system_milliseconds(0), start_time(0), end_time(0), last_update(0), num_updates(0), paused_time(0), offset(0), paused_state(false), lock_state(false), lock_rate(0)
{
}
@ -75,8 +78,10 @@ void Timer::update(void)
}
else
{
#ifdef WIN32
#ifdef _WIN32
system_milliseconds = timeGetTime ();
#else
gettimeofday(&time_val,&time_zone);
@ -157,3 +162,14 @@ bool Timer::paused()
{
return paused_state;
}
void Timer::timerTestFunc() {
update();
if (getNumUpdates() % 120 == 0) {
std::cout << getNumUpdates() << "," << getSeconds() << " Rate: " << ((double)getNumUpdates()/getSeconds()) << "/sec" << std::endl;
}
if (getNumUpdates() >= 600) {
reset();
}
}

View File

@ -24,7 +24,7 @@ private:
unsigned long paused_time;
unsigned long offset;
#ifndef WIN32
#ifndef _WIN32
struct timeval time_val;
struct timezone time_zone;
#endif
@ -155,6 +155,9 @@ public:
* \return Current pause state, true if paused, false otherwise
*/
bool paused();
void timerTestFunc();
};
#endif

View File

@ -36,6 +36,7 @@ MeterCanvas::~MeterCanvas() {
void MeterCanvas::setLevel(float level_in) {
level = level_in;
Refresh();
}
float MeterCanvas::getLevel() {
return level;
@ -43,10 +44,12 @@ float MeterCanvas::getLevel() {
void MeterCanvas::setMax(float max_in) {
level_max = max_in;
Refresh();
}
void MeterCanvas::setInputValue(float slider_in) {
userInputValue = inputValue = slider_in;
Refresh();
}
bool MeterCanvas::inputChanged() {
@ -87,8 +90,11 @@ void MeterCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
}
void MeterCanvas::OnIdle(wxIdleEvent &event) {
Refresh();
event.RequestMore();
if (mouseTracker.mouseInView()) {
Refresh();
} else {
event.Skip();
}
}
void MeterCanvas::OnMouseMoved(wxMouseEvent& event) {
@ -107,15 +113,18 @@ void MeterCanvas::OnMouseDown(wxMouseEvent& event) {
InteractiveCanvas::OnMouseDown(event);
userInputValue = mouseTracker.getMouseY() * level_max;
mouseTracker.setHorizDragLock(true);
Refresh();
}
void MeterCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
InteractiveCanvas::OnMouseWheelMoved(event);
Refresh();
}
void MeterCanvas::OnMouseReleased(wxMouseEvent& event) {
InteractiveCanvas::OnMouseReleased(event);
userInputValue = mouseTracker.getMouseY() * level_max;
Refresh();
}
void MeterCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
@ -127,6 +136,7 @@ void MeterCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
void MeterCanvas::OnMouseEnterWindow(wxMouseEvent& event) {
InteractiveCanvas::mouseTracker.OnMouseEnterWindow(event);
SetCursor(wxCURSOR_CROSS);
Refresh();
}
void MeterCanvas::setHelpTip(std::string tip) {

View File

@ -79,8 +79,11 @@ void ModeSelectorCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
}
void ModeSelectorCanvas::OnIdle(wxIdleEvent &event) {
Refresh();
event.RequestMore();
if (mouseTracker.mouseInView()) {
Refresh();
} else {
event.Skip();
}
}
void ModeSelectorCanvas::OnMouseMoved(wxMouseEvent& event) {
@ -120,6 +123,7 @@ void ModeSelectorCanvas::OnMouseReleased(wxMouseEvent& event) {
currentSelection = selectedButton;
SetCursor (wxCURSOR_HAND);
Refresh();
}
void ModeSelectorCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
@ -134,6 +138,7 @@ void ModeSelectorCanvas::OnMouseEnterWindow(wxMouseEvent& event) {
if (!helpTip.empty()) {
setStatusText(helpTip);
}
Refresh();
}
void ModeSelectorCanvas::setHelpTip(std::string tip) {
@ -142,6 +147,7 @@ void ModeSelectorCanvas::setHelpTip(std::string tip) {
void ModeSelectorCanvas::setNumChoices(int numChoices_in) {
numChoices = numChoices_in;
Refresh();
}
void ModeSelectorCanvas::addChoice(int value, std::string label) {
@ -157,6 +163,7 @@ void ModeSelectorCanvas::setSelection(int value) {
}
}
currentSelection = -1;
Refresh();
}
int ModeSelectorCanvas::getSelection() {

View File

@ -39,7 +39,9 @@ WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
dragOfs(0), mouseZoom(1), zoom(1), freqMove(0.0), freqMoving(false), hoverAlpha(1.0) {
glContext = new PrimaryGLContext(this, &wxGetApp().GetContext(this));
linesPerSecond = 30;
lpsIndex = 0;
preBuf = false;
SetCursor(wxCURSOR_CROSS);
}
@ -54,6 +56,7 @@ void WaterfallCanvas::setup(int fft_size_in, int waterfall_lines_in) {
waterfall_lines = waterfall_lines_in;
waterfallPanel.setup(fft_size, waterfall_lines);
gTimer.start();
}
WaterfallCanvas::DragState WaterfallCanvas::getDragState() {
@ -74,23 +77,38 @@ void WaterfallCanvas::processInputQueue() {
}
glContext->SetCurrent(*this);
while (!visualDataQueue.empty()) {
SpectrumVisualData *vData;
visualDataQueue.pop(vData);
if (vData) {
waterfallPanel.setPoints(vData->spectrum_points);
waterfallPanel.step();
vData->decRefCount();
gTimer.update();
double targetVis = 1.0 / (double)linesPerSecond;
lpsIndex += gTimer.lastUpdateSeconds();
if (linesPerSecond) {
if (lpsIndex >= targetVis) {
tex_update.lock();
while (lpsIndex >= targetVis) {
SpectrumVisualData *vData;
if (!visualDataQueue.empty()) {
visualDataQueue.pop(vData);
if (vData) {
waterfallPanel.setPoints(vData->spectrum_points);
waterfallPanel.step();
vData->decRefCount();
}
lpsIndex-=targetVis;
} else {
break;
}
}
tex_update.unlock();
}
}
}
}}
void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
// wxClientDC dc(this);
wxPaintDC dc(this);
processInputQueue();
const wxSize ClientSize = GetClientSize();
long double currentZoom = zoom;
@ -193,7 +211,9 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
glContext->BeginDraw(0,0,0);
waterfallPanel.calcTransform(CubicVR::mat4::identity());
tex_update.lock();
waterfallPanel.draw();
tex_update.unlock();
std::vector<DemodulatorInstance *> &demods = wxGetApp().getDemodMgr().getDemodulators();
@ -391,7 +411,9 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
void WaterfallCanvas::OnIdle(wxIdleEvent &event) {
Refresh();
event.RequestMore();
// event.Skip();
if (visualDataQueue.size() > linesPerSecond) {
processInputQueue();
}
}
void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
@ -779,3 +801,17 @@ void WaterfallCanvas::updateCenterFrequency(long long freq) {
}
void WaterfallCanvas::setLinesPerSecond(int lps) {
linesPerSecond = lps;
while (!visualDataQueue.empty()) {
SpectrumVisualData *vData;
visualDataQueue.pop(vData);
if (vData) {
vData->decRefCount();
}
}
}

View File

@ -10,7 +10,7 @@
#include "MouseTracker.h"
#include "SpectrumCanvas.h"
#include "WaterfallPanel.h"
#include "Timer.h"
class WaterfallCanvas: public InteractiveCanvas {
public:
@ -29,6 +29,8 @@ public:
void processInputQueue();
SpectrumVisualDataQueue *getVisualDataQueue();
void setLinesPerSecond(int lps);
private:
void OnPaint(wxPaintEvent& event);
void OnKeyDown(wxKeyEvent& event);
@ -64,9 +66,13 @@ private:
bool freqMoving;
long double freqMove;
float hoverAlpha;
int linesPerSecond;
SpectrumVisualDataQueue visualDataQueue;
Timer gTimer;
double lpsIndex;
bool preBuf;
std::mutex tex_update;
// event table
wxDECLARE_EVENT_TABLE();
};