Cleanup, demod limits, prevent negative freq, move iq resampler process back to demodulator pre thread

This commit is contained in:
Charles J. Cliffe 2015-01-04 13:20:31 -05:00
parent e2e261f1c0
commit 44bee1f553
16 changed files with 200 additions and 160 deletions

View File

@ -57,6 +57,7 @@ AppFrame::AppFrame() :
demodSignalMeter = new MeterCanvas(this, NULL); demodSignalMeter = new MeterCanvas(this, NULL);
demodSignalMeter->setMax(0.5); demodSignalMeter->setMax(0.5);
demodSignalMeter->setHelpTip("Current Signal Level. Click / Drag to set Squelch level.");
demodTray->Add(demodSignalMeter, 1, wxEXPAND | wxALL, 0); demodTray->Add(demodSignalMeter, 1, wxEXPAND | wxALL, 0);
demodTray->AddSpacer(2); demodTray->AddSpacer(2);

View File

@ -101,8 +101,10 @@ PrimaryGLContext& CubicSDR::GetContext(wxGLCanvas *canvas) {
} }
void CubicSDR::setFrequency(unsigned int freq) { void CubicSDR::setFrequency(unsigned int freq) {
if (freq < SRATE/2) {
freq = SRATE/2;
}
frequency = freq; frequency = freq;
// demodulatorTest->getParams().frequency = freq;
SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_TUNE); SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_TUNE);
command.int_value = freq; command.int_value = freq;
threadCmdQueueSDR->push(command); threadCmdQueueSDR->push(command);

View File

@ -75,14 +75,12 @@ class DemodulatorThreadPostIQData: public ReferenceCounter {
public: public:
std::vector<liquid_float_complex> data; std::vector<liquid_float_complex> data;
int bandwidth; int bandwidth;
msresamp_crcf resampler;
double resamplerRatio;
msresamp_rrrf audioResampler; msresamp_rrrf audioResampler;
msresamp_rrrf stereoResampler; msresamp_rrrf stereoResampler;
double audioResampleRatio; double audioResampleRatio;
DemodulatorThreadPostIQData() : DemodulatorThreadPostIQData() :
bandwidth(0), resampler(NULL), resamplerRatio(0), audioResampler(NULL), stereoResampler(NULL), audioResampleRatio(0) { bandwidth(0), audioResampler(NULL), stereoResampler(NULL), audioResampleRatio(0) {
} }

View File

@ -2,7 +2,7 @@
DemodulatorInstance::DemodulatorInstance() : DemodulatorInstance::DemodulatorInstance() :
t_Demod(NULL), t_PreDemod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL), terminated(false), audioTerminated(false), demodTerminated( t_Demod(NULL), t_PreDemod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL), terminated(false), audioTerminated(false), demodTerminated(
false), preDemodTerminated(false), active(false), squelch(false), stereo(false) { false), preDemodTerminated(false), active(false), squelch(false), stereo(false), currentBandwidth(0), currentFrequency(0) {
label = new std::string("Unnamed"); label = new std::string("Unnamed");
threadQueueDemod = new DemodulatorThreadInputQueue; threadQueueDemod = new DemodulatorThreadInputQueue;
@ -157,7 +157,6 @@ void DemodulatorInstance::setStereo(bool state) {
demodulatorThread->setStereo(state); demodulatorThread->setStereo(state);
} }
void DemodulatorInstance::squelchAuto() { void DemodulatorInstance::squelchAuto() {
DemodulatorThreadControlCommand command; DemodulatorThreadControlCommand command;
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_ON; command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_ON;
@ -191,12 +190,10 @@ void DemodulatorInstance::setSquelchLevel(float signal_level_in) {
demodulatorThread->setSquelchLevel(signal_level_in); demodulatorThread->setSquelchLevel(signal_level_in);
} }
float DemodulatorInstance::getSquelchLevel() { float DemodulatorInstance::getSquelchLevel() {
return demodulatorThread->getSquelchLevel(); return demodulatorThread->getSquelchLevel();
} }
void DemodulatorInstance::setOutputDevice(int device_id) { void DemodulatorInstance::setOutputDevice(int device_id) {
if (audioThread) { if (audioThread) {
AudioThreadCommand command; AudioThreadCommand command;
@ -210,12 +207,19 @@ int DemodulatorInstance::getOutputDevice() {
return audioThread->getOutputDevice(); return audioThread->getOutputDevice();
} }
void DemodulatorInstance::checkBandwidth() {
if ((currentDemodType == DEMOD_TYPE_USB || currentDemodType == DEMOD_TYPE_LSB) && (getBandwidth() > 60000)) {
setBandwidth(60000);
}
}
void DemodulatorInstance::setDemodulatorType(int demod_type_in) { void DemodulatorInstance::setDemodulatorType(int demod_type_in) {
if (demodulatorThread && threadQueueControl) { if (demodulatorThread && threadQueueControl) {
DemodulatorThreadControlCommand command; DemodulatorThreadControlCommand command;
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE; command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE;
currentDemodType = demod_type_in; currentDemodType = demod_type_in;
command.demodType = demod_type_in; command.demodType = demod_type_in;
checkBandwidth();
threadQueueControl->push(command); threadQueueControl->push(command);
} }
} }
@ -224,3 +228,42 @@ int DemodulatorInstance::getDemodulatorType() {
return currentDemodType; return currentDemodType;
} }
void DemodulatorInstance::setBandwidth(int bw) {
if (demodulatorPreThread && threadQueueCommand) {
DemodulatorThreadCommand command;
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH;
currentBandwidth = bw;
checkBandwidth();
command.int_value = currentBandwidth;
threadQueueCommand->push(command);
}
demodulatorPreThread->getParams().bandwidth;
}
int DemodulatorInstance::getBandwidth() {
if (!currentBandwidth) {
currentBandwidth = demodulatorPreThread->getParams().bandwidth;
}
return currentBandwidth;
}
void DemodulatorInstance::setFrequency(unsigned int freq) {
if (((long)freq - getBandwidth()/2) < SRATE/2) {
freq = SRATE/2 - getBandwidth()/2;
}
if (demodulatorPreThread && threadQueueCommand) {
DemodulatorThreadCommand command;
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY;
currentFrequency = freq;
command.int_value = freq;
threadQueueCommand->push(command);
}
demodulatorPreThread->getParams().bandwidth;
}
int DemodulatorInstance::getFrequency() {
if (!currentFrequency) {
currentFrequency = demodulatorPreThread->getParams().frequency;
}
return currentFrequency;
}

View File

@ -66,7 +66,15 @@ public:
void setDemodulatorType(int demod_type_in); void setDemodulatorType(int demod_type_in);
int getDemodulatorType(); int getDemodulatorType();
void setBandwidth(int bw);
int getBandwidth();
void setFrequency(unsigned int freq);
int getFrequency();
private: private:
void checkBandwidth();
std::atomic<std::string *> label; // std::atomic<std::string *> label; //
bool terminated; // bool terminated; //
bool demodTerminated; // bool demodTerminated; //
@ -77,5 +85,6 @@ private:
std::atomic<bool> stereo; std::atomic<bool> stereo;
int currentDemodType; int currentDemodType;
int currentBandwidth;
int currentFrequency;
}; };

View File

@ -173,16 +173,24 @@ void DemodulatorPreThread::threadMain() {
buffers.push_back(resamp); buffers.push_back(resamp);
} }
resamp->setRefCount(1); int out_size = ceil((double) (bufSize) * iqResampleRatio) + 512;
resamp->data.assign(in_buf, in_buf + bufSize);
// firfilt_crcf_execute_block(fir_filter, in_buf, bufSize, &((*resamp.data)[0])); if (resampledData.size() != out_size) {
if (resampledData.capacity() < out_size) {
resampledData.reserve(out_size);
}
resampledData.resize(out_size);
}
unsigned int numWritten;
msresamp_crcf_execute(iqResampler, in_buf, bufSize, &resampledData[0], &numWritten);
resamp->setRefCount(1);
resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten);
resamp->audioResampleRatio = audioResampleRatio; resamp->audioResampleRatio = audioResampleRatio;
resamp->audioResampler = audioResampler; resamp->audioResampler = audioResampler;
resamp->stereoResampler = stereoResampler; resamp->stereoResampler = stereoResampler;
resamp->resamplerRatio = iqResampleRatio;
resamp->resampler = iqResampler;
resamp->bandwidth = params.bandwidth; resamp->bandwidth = params.bandwidth;
iqOutputQueue->push(resamp); iqOutputQueue->push(resamp);
@ -197,6 +205,8 @@ void DemodulatorPreThread::threadMain() {
switch (result.cmd) { switch (result.cmd) {
case DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS: case DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS:
msresamp_crcf_destroy(iqResampler);
iqResampler = result.resampler; iqResampler = result.resampler;
audioResampler = result.audioResampler; audioResampler = result.audioResampler;
stereoResampler = result.stereoResampler; stereoResampler = result.stereoResampler;

View File

@ -48,6 +48,7 @@ protected:
msresamp_crcf iqResampler; msresamp_crcf iqResampler;
double iqResampleRatio; double iqResampleRatio;
std::vector<liquid_float_complex> resampledData;
msresamp_rrrf audioResampler; msresamp_rrrf audioResampler;
msresamp_rrrf stereoResampler; msresamp_rrrf stereoResampler;

View File

@ -35,7 +35,6 @@ void DemodulatorThread::threadMain() {
pthread_setschedparam(tID, SCHED_FIFO, &prio); pthread_setschedparam(tID, SCHED_FIFO, &prio);
#endif #endif
msresamp_crcf resampler = NULL;
msresamp_rrrf audioResampler = NULL; msresamp_rrrf audioResampler = NULL;
msresamp_rrrf stereoResampler = NULL; msresamp_rrrf stereoResampler = NULL;
firfilt_rrrf firStereoLeft = NULL; firfilt_rrrf firStereoLeft = NULL;
@ -104,15 +103,12 @@ void DemodulatorThread::threadMain() {
continue; continue;
} }
if (resampler == NULL) { if (audioResampler == NULL) {
resampler = inp->resampler;
audioResampler = inp->audioResampler; audioResampler = inp->audioResampler;
stereoResampler = inp->stereoResampler; stereoResampler = inp->stereoResampler;
} else if (resampler != inp->resampler) { } else if (audioResampler != inp->audioResampler) {
msresamp_crcf_destroy(resampler);
msresamp_rrrf_destroy(audioResampler); msresamp_rrrf_destroy(audioResampler);
msresamp_rrrf_destroy(stereoResampler); msresamp_rrrf_destroy(stereoResampler);
resampler = inp->resampler;
audioResampler = inp->audioResampler; audioResampler = inp->audioResampler;
stereoResampler = inp->stereoResampler; stereoResampler = inp->stereoResampler;
@ -122,34 +118,27 @@ void DemodulatorThread::threadMain() {
freqdem_reset(demodFM); freqdem_reset(demodFM);
} }
int out_size = ceil((double) (bufSize) * inp->resamplerRatio) + 512; if (agcData.size() != bufSize) {
if (agcData.capacity() < bufSize) {
if (agcData.size() != out_size) { agcData.reserve(bufSize);
if (agcData.capacity() < out_size) { agcAMData.reserve(bufSize);
agcData.reserve(out_size);
agcAMData.reserve(out_size);
resampledData.reserve(out_size);
} }
agcData.resize(out_size); agcData.resize(bufSize);
resampledData.resize(out_size); agcAMData.resize(bufSize);
agcAMData.resize(out_size);
} }
unsigned int numWritten;
msresamp_crcf_execute(resampler, &(inp->data[0]), bufSize, &resampledData[0], &numWritten);
double audio_resample_ratio = inp->audioResampleRatio; double audio_resample_ratio = inp->audioResampleRatio;
if (demodOutputData.size() != numWritten) { if (demodOutputData.size() != bufSize) {
if (demodOutputData.capacity() < numWritten) { if (demodOutputData.capacity() < bufSize) {
demodOutputData.reserve(numWritten); demodOutputData.reserve(bufSize);
} }
demodOutputData.resize(numWritten); demodOutputData.resize(bufSize);
} }
int audio_out_size = ceil((double) (numWritten) * audio_resample_ratio) + 512; int audio_out_size = ceil((double) (bufSize) * audio_resample_ratio) + 512;
agc_crcf_execute_block(iqAutoGain, &resampledData[0], numWritten, &agcData[0]); agc_crcf_execute_block(iqAutoGain, &(inp->data[0]), bufSize, &agcData[0]);
float currentSignalLevel = 0; float currentSignalLevel = 0;
@ -160,27 +149,27 @@ void DemodulatorThread::threadMain() {
} }
if (demodulatorType == DEMOD_TYPE_FM) { if (demodulatorType == DEMOD_TYPE_FM) {
freqdem_demodulate_block(demodFM, &agcData[0], numWritten, &demodOutputData[0]); freqdem_demodulate_block(demodFM, &agcData[0], bufSize, &demodOutputData[0]);
} else { } else {
float p; float p;
switch (demodulatorType.load()) { switch (demodulatorType.load()) {
case DEMOD_TYPE_LSB: case DEMOD_TYPE_LSB:
for (int i = 0; i < numWritten; i++) { // Reject upper band for (int i = 0; i < bufSize; i++) { // Reject upper band
nco_crcf_mix_up(ssbShifterUp, resampledData[i], &x); nco_crcf_mix_up(ssbShifterUp, inp->data[i], &x);
nco_crcf_step(ssbShifterUp); nco_crcf_step(ssbShifterUp);
firfilt_crcf_push(firSSB, x); firfilt_crcf_push(firSSB, x);
firfilt_crcf_execute(firSSB, &x); firfilt_crcf_execute(firSSB, &x);
nco_crcf_mix_down(ssbShifterDown, x, &resampledData[i]); nco_crcf_mix_down(ssbShifterDown, x, &(inp->data[i]));
nco_crcf_step(ssbShifterDown); nco_crcf_step(ssbShifterDown);
} }
break; break;
case DEMOD_TYPE_USB: case DEMOD_TYPE_USB:
for (int i = 0; i < numWritten; i++) { // Reject lower band for (int i = 0; i < bufSize; i++) { // Reject lower band
nco_crcf_mix_down(ssbShifterDown, resampledData[i], &x); nco_crcf_mix_down(ssbShifterDown, inp->data[i], &x);
nco_crcf_step(ssbShifterDown); nco_crcf_step(ssbShifterDown);
firfilt_crcf_push(firSSB, x); firfilt_crcf_push(firSSB, x);
firfilt_crcf_execute(firSSB, &x); firfilt_crcf_execute(firSSB, &x);
nco_crcf_mix_up(ssbShifterUp, x, &resampledData[i]); nco_crcf_mix_up(ssbShifterUp, x, &(inp->data[i]));
nco_crcf_step(ssbShifterUp); nco_crcf_step(ssbShifterUp);
} }
break; break;
@ -190,8 +179,8 @@ void DemodulatorThread::threadMain() {
amOutputCeil = 0; amOutputCeil = 0;
for (int i = 0; i < numWritten; i++) { for (int i = 0; i < bufSize; i++) {
ampmodem_demodulate(demodAM, resampledData[i], &demodOutputData[i]); ampmodem_demodulate(demodAM, inp->data[i], &demodOutputData[i]);
if (demodOutputData[i] > amOutputCeil) { if (demodOutputData[i] > amOutputCeil) {
amOutputCeil = demodOutputData[i]; amOutputCeil = demodOutputData[i];
} }
@ -201,7 +190,7 @@ void DemodulatorThread::threadMain() {
float gain = 0.95 / amOutputCeilMAA; float gain = 0.95 / amOutputCeilMAA;
for (int i = 0; i < numWritten; i++) { for (int i = 0; i < bufSize; i++) {
demodOutputData[i] *= gain; demodOutputData[i] *= gain;
} }
} }
@ -214,14 +203,14 @@ void DemodulatorThread::threadMain() {
} }
unsigned int numAudioWritten; unsigned int numAudioWritten;
msresamp_rrrf_execute(audioResampler, &demodOutputData[0], numWritten, &resampledOutputData[0], &numAudioWritten); msresamp_rrrf_execute(audioResampler, &demodOutputData[0], bufSize, &resampledOutputData[0], &numAudioWritten);
if (stereo) { if (stereo) {
if (demodStereoData.size() != numWritten) { if (demodStereoData.size() != bufSize) {
if (demodStereoData.capacity() < numWritten) { if (demodStereoData.capacity() < bufSize) {
demodStereoData.reserve(numWritten); demodStereoData.reserve(bufSize);
} }
demodStereoData.resize(numWritten); demodStereoData.resize(bufSize);
} }
double freq = (2.0 * M_PI) * (((double) abs(38000)) / ((double) inp->bandwidth)); double freq = (2.0 * M_PI) * (((double) abs(38000)) / ((double) inp->bandwidth));
@ -231,7 +220,7 @@ void DemodulatorThread::threadMain() {
stereoShiftFrequency = freq; stereoShiftFrequency = freq;
} }
for (int i = 0; i < numWritten; i++) { for (int i = 0; i < bufSize; i++) {
firhilbf_r2c_execute(firStereoR2C, demodOutputData[i], &x); firhilbf_r2c_execute(firStereoR2C, demodOutputData[i], &x);
nco_crcf_mix_down(stereoShifter, x, &y); nco_crcf_mix_down(stereoShifter, x, &y);
nco_crcf_step(stereoShifter); nco_crcf_step(stereoShifter);
@ -245,7 +234,7 @@ void DemodulatorThread::threadMain() {
resampledStereoData.resize(audio_out_size); resampledStereoData.resize(audio_out_size);
} }
msresamp_rrrf_execute(stereoResampler, &demodStereoData[0], numWritten, &resampledStereoData[0], &numAudioWritten); msresamp_rrrf_execute(stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten);
} }
if (currentSignalLevel > signalLevel) { if (currentSignalLevel > signalLevel) {
@ -318,15 +307,15 @@ void DemodulatorThread::threadMain() {
} }
} else { } else {
ati_vis->channels = 1; ati_vis->channels = 1;
if (numAudioWritten > numWritten) { if (numAudioWritten > bufSize) {
if (num_vis > numAudioWritten) { if (num_vis > numAudioWritten) {
num_vis = numAudioWritten; num_vis = numAudioWritten;
} }
ati_vis->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + num_vis); ati_vis->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + num_vis);
} else { } else {
if (num_vis > numWritten) { if (num_vis > bufSize) {
num_vis = numWritten; num_vis = bufSize;
} }
ati_vis->data.assign(demodOutputData.begin(), demodOutputData.begin() + num_vis); ati_vis->data.assign(demodOutputData.begin(), demodOutputData.begin() + num_vis);
} }
@ -379,9 +368,6 @@ void DemodulatorThread::threadMain() {
inp->decRefCount(); inp->decRefCount();
} }
if (resampler != NULL) {
msresamp_crcf_destroy(resampler);
}
if (audioResampler != NULL) { if (audioResampler != NULL) {
msresamp_rrrf_destroy(audioResampler); msresamp_rrrf_destroy(audioResampler);
} }

View File

@ -48,7 +48,6 @@ protected:
std::deque<AudioThreadInput *> outputBuffers; std::deque<AudioThreadInput *> outputBuffers;
std::deque<AudioThreadInput *>::iterator outputBuffersI; std::deque<AudioThreadInput *>::iterator outputBuffersI;
std::vector<liquid_float_complex> resampledData;
std::vector<liquid_float_complex> agcData; std::vector<liquid_float_complex> agcData;
std::vector<float> agcAMData; std::vector<float> agcAMData;
std::vector<float> demodOutputData; std::vector<float> demodOutputData;

View File

@ -145,9 +145,12 @@ void SDRThread::threadMain() {
switch (command.cmd) { switch (command.cmd) {
case SDRThreadCommand::SDR_THREAD_CMD_TUNE: case SDRThreadCommand::SDR_THREAD_CMD_TUNE:
std::cout << "Set frequency: " << command.int_value << std::endl;
freq_changed = true; freq_changed = true;
new_freq = command.int_value; new_freq = command.int_value;
if (new_freq < SRATE / 2) {
new_freq = SRATE / 2;
}
std::cout << "Set frequency: " << new_freq << std::endl;
break; break;
default: default:
break; break;

View File

@ -25,11 +25,9 @@ EVT_ENTER_WINDOW(MeterCanvas::OnMouseEnterWindow)
wxEND_EVENT_TABLE() wxEND_EVENT_TABLE()
MeterCanvas::MeterCanvas(wxWindow *parent, int *attribList) : MeterCanvas::MeterCanvas(wxWindow *parent, int *attribList) :
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, InteractiveCanvas(parent, attribList), level(0), level_max(1), inputValue(0), userInputValue(0) {
wxFULL_REPAINT_ON_RESIZE), parent(parent), level(0), level_max(1), inputValue(0), userInputValue(0), shiftDown(false), altDown(false), ctrlDown(false) {
glContext = new MeterContext(this, &wxGetApp().GetContext(this)); glContext = new MeterContext(this, &wxGetApp().GetContext(this));
mTracker.setTarget(this);
} }
MeterCanvas::~MeterCanvas() { MeterCanvas::~MeterCanvas() {
@ -50,9 +48,11 @@ void MeterCanvas::setMax(float max_in) {
bool MeterCanvas::setInputValue(float slider_in) { bool MeterCanvas::setInputValue(float slider_in) {
userInputValue = inputValue = slider_in; userInputValue = inputValue = slider_in;
} }
bool MeterCanvas::inputChanged() { bool MeterCanvas::inputChanged() {
return (inputValue != userInputValue); return (inputValue != userInputValue);
} }
float MeterCanvas::getInputValue() { float MeterCanvas::getInputValue() {
inputValue = userInputValue; inputValue = userInputValue;
return userInputValue; return userInputValue;
@ -66,8 +66,8 @@ void MeterCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
glViewport(0, 0, ClientSize.x, ClientSize.y); glViewport(0, 0, ClientSize.x, ClientSize.y);
glContext->DrawBegin(); glContext->DrawBegin();
if (mTracker.mouseInView()) { if (mouseTracker.mouseInView()) {
glContext->Draw(0.4, 0.4, 0.4, 0.5, mTracker.getMouseY()); glContext->Draw(0.4, 0.4, 0.4, 0.5, mouseTracker.getMouseY());
} }
glContext->Draw(0.1, 0.75, 0.1, 0.5, level / level_max); glContext->Draw(0.1, 0.75, 0.1, 0.5, level / level_max);
@ -84,48 +84,42 @@ void MeterCanvas::OnIdle(wxIdleEvent &event) {
} }
void MeterCanvas::OnMouseMoved(wxMouseEvent& event) { void MeterCanvas::OnMouseMoved(wxMouseEvent& event) {
mTracker.OnMouseMoved(event); InteractiveCanvas::OnMouseMoved(event);
shiftDown = event.ShiftDown(); if (mouseTracker.mouseDown()) {
altDown = event.AltDown(); userInputValue = mouseTracker.getMouseY() * level_max;
ctrlDown = event.ControlDown(); } else {
if (!helpTip.empty()) {
if (mTracker.mouseDown()) { setStatusText(helpTip);
userInputValue = mTracker.getMouseY()*level_max; }
} }
} }
void MeterCanvas::OnMouseDown(wxMouseEvent& event) { void MeterCanvas::OnMouseDown(wxMouseEvent& event) {
mTracker.OnMouseDown(event); InteractiveCanvas::OnMouseDown(event);
userInputValue = mouseTracker.getMouseY() * level_max;
shiftDown = event.ShiftDown(); mouseTracker.setHorizDragLock(true);
altDown = event.AltDown();
ctrlDown = event.ControlDown();
userInputValue = mTracker.getMouseY()*level_max;
mTracker.setHorizDragLock(true);
} }
void MeterCanvas::OnMouseWheelMoved(wxMouseEvent& event) { void MeterCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
mTracker.OnMouseWheelMoved(event); InteractiveCanvas::OnMouseWheelMoved(event);
} }
void MeterCanvas::OnMouseReleased(wxMouseEvent& event) { void MeterCanvas::OnMouseReleased(wxMouseEvent& event) {
mTracker.OnMouseReleased(event); InteractiveCanvas::OnMouseReleased(event);
userInputValue = mouseTracker.getMouseY() * level_max;
shiftDown = event.ShiftDown();
altDown = event.AltDown();
ctrlDown = event.ControlDown();
userInputValue = mTracker.getMouseY()*level_max;
} }
void MeterCanvas::OnMouseLeftWindow(wxMouseEvent& event) { void MeterCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
mTracker.OnMouseLeftWindow(event); InteractiveCanvas::OnMouseLeftWindow(event);
SetCursor(wxCURSOR_CROSS); SetCursor(wxCURSOR_CROSS);
} }
void MeterCanvas::OnMouseEnterWindow(wxMouseEvent& event) { void MeterCanvas::OnMouseEnterWindow(wxMouseEvent& event) {
mTracker.OnMouseEnterWindow(event); InteractiveCanvas::mouseTracker.OnMouseEnterWindow(event);
SetCursor(wxCURSOR_CROSS); SetCursor(wxCURSOR_CROSS);
} }
void MeterCanvas::setHelpTip(std::string tip) {
helpTip = tip;
}

View File

@ -6,16 +6,15 @@
#include <vector> #include <vector>
#include <queue> #include <queue>
#include "InteractiveCanvas.h"
#include "MeterContext.h" #include "MeterContext.h"
#include "MouseTracker.h" #include "MouseTracker.h"
#include "fftw3.h" #include "fftw3.h"
#include "Timer.h" #include "Timer.h"
class MeterCanvas: public wxGLCanvas { class MeterCanvas: public InteractiveCanvas {
public: public:
std::vector<float> waveform_points;
MeterCanvas(wxWindow *parent, int *attribList = NULL); MeterCanvas(wxWindow *parent, int *attribList = NULL);
~MeterCanvas(); ~MeterCanvas();
@ -28,6 +27,8 @@ public:
bool inputChanged(); bool inputChanged();
float getInputValue(); float getInputValue();
void setHelpTip(std::string tip);
private: private:
void OnPaint(wxPaintEvent& event); void OnPaint(wxPaintEvent& event);
void OnIdle(wxIdleEvent &event); void OnIdle(wxIdleEvent &event);
@ -39,8 +40,6 @@ private:
void OnMouseEnterWindow(wxMouseEvent& event); void OnMouseEnterWindow(wxMouseEvent& event);
void OnMouseLeftWindow(wxMouseEvent& event); void OnMouseLeftWindow(wxMouseEvent& event);
MouseTracker mTracker;
wxWindow *parent;
MeterContext *glContext; MeterContext *glContext;
float level; float level;
@ -49,9 +48,8 @@ private:
float inputValue; float inputValue;
float userInputValue; float userInputValue;
bool shiftDown; std::string helpTip;
bool altDown; //
bool ctrlDown;
wxDECLARE_EVENT_TABLE(); wxDECLARE_EVENT_TABLE();
}; };

View File

@ -107,7 +107,7 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, float r, float
center_freq = wxGetApp().getFrequency(); center_freq = wxGetApp().getFrequency();
} }
float uxPos = (float) (demod->getParams().frequency - (center_freq - srate / 2)) / (float) srate; float uxPos = (float) (demod->getFrequency() - (center_freq - srate / 2)) / (float) srate;
uxPos = (uxPos - 0.5) * 2.0; uxPos = (uxPos - 0.5) * 2.0;
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
@ -116,7 +116,7 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, float r, float
glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR); glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);
glColor4f(r, g, b, 0.6); glColor4f(r, g, b, 0.6);
float ofs = ((float) demod->getParams().bandwidth) / (float) srate; float ofs = ((float) demod->getBandwidth()) / (float) srate;
glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR); glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);
glColor4f(r, g, b, 0.2); glColor4f(r, g, b, 0.2);
@ -162,7 +162,7 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, float r, float g, f
center_freq = wxGetApp().getFrequency(); center_freq = wxGetApp().getFrequency();
} }
float uxPos = (float) (demod->getParams().frequency - (center_freq - srate / 2)) / (float) srate; float uxPos = (float) (demod->getFrequency() - (center_freq - srate / 2)) / (float) srate;
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
@ -175,7 +175,7 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, float r, float g, f
glVertex3f((uxPos - 0.5) * 2.0, 1.0, 0.0); glVertex3f((uxPos - 0.5) * 2.0, 1.0, 0.0);
glVertex3f((uxPos - 0.5) * 2.0, -1.0, 0.0); glVertex3f((uxPos - 0.5) * 2.0, -1.0, 0.0);
float ofs = ((float) demod->getParams().bandwidth) / (float) srate; float ofs = ((float) demod->getBandwidth()) / (float) srate;
glVertex3f((uxPos - 0.5) * 2.0 - ofs, 1.0, 0.0); glVertex3f((uxPos - 0.5) * 2.0 - ofs, 1.0, 0.0);
glVertex3f((uxPos - 0.5) * 2.0 - ofs, -1.0, 0.0); glVertex3f((uxPos - 0.5) * 2.0 - ofs, -1.0, 0.0);
@ -254,7 +254,7 @@ void PrimaryGLContext::DrawFreqSelector(float uxPos, float r, float g, float b,
if (!demod) { if (!demod) {
bw = defaultDemodParams.bandwidth; bw = defaultDemodParams.bandwidth;
} else { } else {
bw = demod->getParams().bandwidth; bw = demod->getBandwidth();
} }
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);

View File

@ -179,7 +179,7 @@ void SpectrumCanvas::OnMouseMoved(wxMouseEvent& event) {
int freqChange = mouseTracker.getDeltaMouseX() * getBandwidth(); int freqChange = mouseTracker.getDeltaMouseX() * getBandwidth();
if (freqChange != 0) { if (freqChange != 0) {
int freq = wxGetApp().getFrequency(); unsigned int freq = wxGetApp().getFrequency();
if (isView) { if (isView) {
centerFreq = centerFreq - freqChange; centerFreq = centerFreq - freqChange;
@ -187,19 +187,23 @@ void SpectrumCanvas::OnMouseMoved(wxMouseEvent& event) {
waterfallCanvas->setCenterFrequency(centerFreq); waterfallCanvas->setCenterFrequency(centerFreq);
} }
int bw = (int) bandwidth; long bw = (long) bandwidth;
int bwOfs = ((int) centerFreq > freq) ? ((int) bandwidth / 2) : (-(int) bandwidth / 2); long bwOfs = (centerFreq > freq) ? ((long) bandwidth / 2) : (-(long) bandwidth / 2);
int freqEdge = ((int) centerFreq + bwOfs); long freqEdge = ((long) centerFreq + bwOfs);
if (abs(freq - freqEdge) > (SRATE / 2)) { if (abs((long) freq - freqEdge) > (SRATE / 2)) {
freqChange = -(((int) centerFreq > freq) ? (freqEdge - freq - (SRATE / 2)) : (freqEdge - freq + (SRATE / 2))); freqChange = -((centerFreq > freq) ? (freqEdge - (long)freq - (SRATE / 2)) : (freqEdge - (long)freq + (SRATE / 2)));
} else { } else {
freqChange = 0; freqChange = 0;
} }
} }
if (freqChange) { if (freqChange) {
if ((long)freq - freqChange < SRATE/2) {
freq = SRATE/2;
} else {
freq -= freqChange; freq -= freqChange;
}
wxGetApp().setFrequency(freq); wxGetApp().setFrequency(freq);
setStatusText("Set center frequency: %s", freq); setStatusText("Set center frequency: %s", freq);
} }

View File

@ -33,7 +33,7 @@ EVT_ENTER_WINDOW(WaterfallCanvas::OnMouseEnterWindow)
wxEND_EVENT_TABLE() wxEND_EVENT_TABLE()
WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) : WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
InteractiveCanvas(parent, attribList), spectrumCanvas(NULL), activeDemodulatorBandwidth(0), activeDemodulatorFrequency(0), dragState( InteractiveCanvas(parent, attribList), spectrumCanvas(NULL), dragState(
WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines(0), plan( WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines(0), plan(
NULL), in(NULL), out(NULL), resampler(NULL), resamplerRatio(0), lastInputBandwidth(0), zoom(1), mouseZoom(1) { NULL), in(NULL), out(NULL), resampler(NULL), resamplerRatio(0), lastInputBandwidth(0), zoom(1), mouseZoom(1) {
@ -228,15 +228,23 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
case WXK_LEFT: case WXK_LEFT:
freq = wxGetApp().getFrequency(); freq = wxGetApp().getFrequency();
if (shiftDown) { if (shiftDown) {
if (((long) freq - SRATE * 10) < SRATE / 2) {
freq = SRATE / 2;
} else {
freq -= SRATE * 10; freq -= SRATE * 10;
}
if (isView) { if (isView) {
setView(centerFreq - SRATE * 10, getBandwidth()); setView(centerFreq - SRATE * 10, getBandwidth());
if (spectrumCanvas) { if (spectrumCanvas) {
spectrumCanvas->setView(getCenterFrequency(), getBandwidth()); spectrumCanvas->setView(getCenterFrequency(), getBandwidth());
} }
} }
} else {
if (((long) freq - SRATE / 2) < SRATE / 2) {
freq = SRATE / 2;
} else { } else {
freq -= SRATE / 2; freq -= SRATE / 2;
}
if (isView) { if (isView) {
setView(centerFreq - SRATE / 2, getBandwidth()); setView(centerFreq - SRATE / 2, getBandwidth());
if (spectrumCanvas) { if (spectrumCanvas) {
@ -539,42 +547,31 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
bwDiff = -bwDiff; bwDiff = -bwDiff;
} }
if (!activeDemodulatorBandwidth) { int currentBW = demod->getBandwidth();
activeDemodulatorBandwidth = demod->getParams().bandwidth;
currentBW = currentBW + bwDiff;
if (currentBW > SRATE) {
currentBW = SRATE;
}
if (currentBW < MIN_BANDWIDTH) {
currentBW = MIN_BANDWIDTH;
} }
DemodulatorThreadCommand command; demod->setBandwidth(currentBW);
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH; setStatusText("Set demodulator bandwidth: %s", demod->getBandwidth());
activeDemodulatorBandwidth = activeDemodulatorBandwidth + bwDiff;
if (activeDemodulatorBandwidth > SRATE) {
activeDemodulatorBandwidth = SRATE;
}
if (activeDemodulatorBandwidth < MIN_BANDWIDTH) {
activeDemodulatorBandwidth = MIN_BANDWIDTH;
}
command.int_value = activeDemodulatorBandwidth;
demod->getCommandQueue()->push(command);
setStatusText("Set demodulator bandwidth: %s", activeDemodulatorBandwidth);
} }
if (dragState == WF_DRAG_FREQUENCY) { if (dragState == WF_DRAG_FREQUENCY) {
int bwDiff = (int) (mouseTracker.getDeltaMouseX() * (float) getBandwidth()); int bwDiff = (int) (mouseTracker.getDeltaMouseX() * (float) getBandwidth());
if (!activeDemodulatorFrequency) { unsigned int currentFreq = demod->getFrequency();
activeDemodulatorFrequency = demod->getParams().frequency;
}
DemodulatorThreadCommand command; currentFreq = (unsigned int)((int)currentFreq + bwDiff);
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY;
activeDemodulatorFrequency = activeDemodulatorFrequency + bwDiff;
command.int_value = activeDemodulatorFrequency; demod->setFrequency(currentFreq);
demod->getCommandQueue()->push(command); demod->updateLabel(currentFreq);
demod->updateLabel(activeDemodulatorFrequency); setStatusText("Set demodulator frequency: %s", demod->getFrequency());
setStatusText("Set demodulator frequency: %s", activeDemodulatorFrequency);
} }
} else if (mouseTracker.mouseRightDown()) { } else if (mouseTracker.mouseRightDown()) {
mouseZoom = mouseZoom + ((1.0 - (mouseTracker.getDeltaMouseY() * 4.0)) - mouseZoom) * 0.1; mouseZoom = mouseZoom + ((1.0 - (mouseTracker.getDeltaMouseY() * 4.0)) - mouseZoom) * 0.1;
@ -655,7 +652,8 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
if (shiftDown) { if (shiftDown) {
setStatusText("Click to create a new demodulator or hold ALT to drag range."); setStatusText("Click to create a new demodulator or hold ALT to drag range.");
} else { } else {
setStatusText("Click to move active demodulator frequency or hold ALT to drag range; hold SHIFT to create new. Right drag or A / Z to Zoom. Arrow keys (+SHIFT) to move center frequency."); setStatusText(
"Click to move active demodulator frequency or hold ALT to drag range; hold SHIFT to create new. Right drag or A / Z to Zoom. Arrow keys (+SHIFT) to move center frequency.");
} }
} }
@ -671,9 +669,6 @@ void WaterfallCanvas::OnMouseDown(wxMouseEvent& event) {
if (dragState && dragState != WF_DRAG_RANGE) { if (dragState && dragState != WF_DRAG_RANGE) {
wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getActiveDemodulator(), false); wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getActiveDemodulator(), false);
} }
activeDemodulatorBandwidth = 0;
activeDemodulatorFrequency = 0;
} }
void WaterfallCanvas::OnMouseWheelMoved(wxMouseEvent& event) { void WaterfallCanvas::OnMouseWheelMoved(wxMouseEvent& event) {

View File

@ -61,9 +61,6 @@ private:
WaterfallContext *glContext; WaterfallContext *glContext;
int activeDemodulatorBandwidth;
int activeDemodulatorFrequency;
DragState dragState; DragState dragState;
DragState nextDragState; DragState nextDragState;