Squelch slider/signal indicator
This commit is contained in:
parent
4403824e3b
commit
b7793ef905
|
@ -136,6 +136,8 @@ SET (cubicsdr_sources
|
|||
src/util/MouseTracker.cpp
|
||||
src/util/GLFont.cpp
|
||||
src/visual/PrimaryGLContext.cpp
|
||||
src/visual/MeterCanvas.cpp
|
||||
src/visual/MeterContext.cpp
|
||||
src/visual/ScopeCanvas.cpp
|
||||
src/visual/ScopeContext.cpp
|
||||
src/visual/SpectrumCanvas.cpp
|
||||
|
@ -165,6 +167,8 @@ SET (cubicsdr_headers
|
|||
src/util/MouseTracker.h
|
||||
src/util/GLFont.h
|
||||
src/visual/PrimaryGLContext.h
|
||||
src/visual/MeterCanvas.h
|
||||
src/visual/MeterContext.h
|
||||
src/visual/ScopeCanvas.h
|
||||
src/visual/ScopeContext.h
|
||||
src/visual/SpectrumCanvas.h
|
||||
|
|
|
@ -79,12 +79,18 @@ AppFrame::AppFrame() :
|
|||
demodWaterfallCanvas->attachSpectrumCanvas(demodSpectrumCanvas);
|
||||
demodVisuals->Add(demodWaterfallCanvas, 3, wxEXPAND | wxALL, 0);
|
||||
|
||||
demodTray->Add(demodVisuals, 7, wxEXPAND | wxALL, 0);
|
||||
demodTray->Add(demodVisuals, 30, wxEXPAND | wxALL, 0);
|
||||
|
||||
demodTray->AddSpacer(2);
|
||||
|
||||
demodSignalMeter = new MeterCanvas(this, NULL);
|
||||
demodSignalMeter->setMax(0.5);
|
||||
demodTray->Add(demodSignalMeter, 1, wxEXPAND | wxALL, 0);
|
||||
|
||||
demodTray->AddSpacer(2);
|
||||
|
||||
scopeCanvas = new ScopeCanvas(this, NULL);
|
||||
demodTray->Add(scopeCanvas, 7, wxEXPAND | wxALL, 0);
|
||||
demodTray->Add(scopeCanvas, 30, wxEXPAND | wxALL, 0);
|
||||
|
||||
vbox->Add(demodTray, 2, wxEXPAND | wxALL, 0);
|
||||
vbox->AddSpacer(2);
|
||||
|
@ -105,12 +111,42 @@ AppFrame::AppFrame() :
|
|||
// SetIcon(wxICON(sample));
|
||||
|
||||
// Make a menubar
|
||||
wxMenu *menu = new wxMenu;
|
||||
// wxMenu *menu = new wxMenu;
|
||||
// menu->Append(wxID_NEW);
|
||||
// menu->AppendSeparator();
|
||||
menu->Append(wxID_CLOSE);
|
||||
// menu->Append(wxID_CLOSE);
|
||||
// wxMenuBar *menuBar = new wxMenuBar;
|
||||
// menuBar->Append(menu, wxT("&File"));
|
||||
|
||||
wxMenu *menu = new wxMenu;
|
||||
|
||||
std::vector<RtAudio::DeviceInfo> devices;
|
||||
std::vector<RtAudio::DeviceInfo>::iterator devices_i;
|
||||
std::map<int,RtAudio::DeviceInfo>::iterator mdevices_i;
|
||||
AudioThread::enumerateDevices(devices);
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (devices_i = devices.begin(); devices_i != devices.end(); devices_i++) {
|
||||
if (devices_i->inputChannels) {
|
||||
input_devices[i] = *devices_i;
|
||||
}
|
||||
if (devices_i->outputChannels) {
|
||||
output_devices[i] = *devices_i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
for (mdevices_i = output_devices.begin(); mdevices_i != output_devices.end(); mdevices_i++) {
|
||||
wxMenuItem *itm = menu->AppendRadioItem(wxID_RT_AUDIO_DEVICE+i,mdevices_i->second.name,wxT("Description?"));
|
||||
if (mdevices_i->second.isDefaultOutput) {
|
||||
itm->Check(true);
|
||||
}
|
||||
}
|
||||
|
||||
wxMenuBar *menuBar = new wxMenuBar;
|
||||
menuBar->Append(menu, wxT("&File"));
|
||||
menuBar->Append(menu, wxT("&Device"));
|
||||
|
||||
SetMenuBar(menuBar);
|
||||
|
||||
|
@ -155,6 +191,9 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||
|
||||
if (demod) {
|
||||
if (demod != activeDemodulator) {
|
||||
demodSignalMeter->setInputValue(demod->getSquelchLevel());
|
||||
}
|
||||
if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) {
|
||||
if (demod->getParams().frequency != demodWaterfallCanvas->GetCenterFrequency()) {
|
||||
demodWaterfallCanvas->SetCenterFrequency(demod->getParams().frequency);
|
||||
|
@ -169,6 +208,11 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||
demodSpectrumCanvas->SetBandwidth(demodBw);
|
||||
}
|
||||
}
|
||||
demodSignalMeter->setLevel(demod->getSignalLevel());
|
||||
if (demodSignalMeter->inputChanged()) {
|
||||
demod->setSquelchLevel(demodSignalMeter->getInputValue());
|
||||
}
|
||||
activeDemodulator = demod;
|
||||
}
|
||||
|
||||
if (!wxGetApp().getIQVisualQueue()->empty()) {
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
#include "ScopeCanvas.h"
|
||||
#include "SpectrumCanvas.h"
|
||||
#include "WaterfallCanvas.h"
|
||||
#include "MeterCanvas.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#define wxID_RT_AUDIO_DEVICE 10000
|
||||
|
||||
// Define a new frame type
|
||||
class AppFrame: public wxFrame {
|
||||
|
@ -25,7 +30,13 @@ private:
|
|||
WaterfallCanvas *waterfallCanvas;
|
||||
SpectrumCanvas *demodSpectrumCanvas;
|
||||
WaterfallCanvas *demodWaterfallCanvas;
|
||||
|
||||
MeterCanvas *demodSignalMeter;
|
||||
// event table
|
||||
|
||||
DemodulatorInstance *activeDemodulator;
|
||||
|
||||
std::map<int,RtAudio::DeviceInfo> input_devices;
|
||||
std::map<int,RtAudio::DeviceInfo> output_devices;
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#define BUF_SIZE (16384*2)
|
||||
#define SRATE 2000000
|
||||
#else
|
||||
#define BUF_SIZE (16384*4)
|
||||
#define BUF_SIZE (16384*5)
|
||||
#define SRATE 2500000
|
||||
#endif
|
||||
#define DEFAULT_FFT_SIZE 2048
|
||||
|
|
|
@ -211,11 +211,15 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
|||
}
|
||||
#endif
|
||||
|
||||
void AudioThread::enumerateDevices() {
|
||||
int numDevices = dac.getDeviceCount();
|
||||
void AudioThread::enumerateDevices(std::vector<RtAudio::DeviceInfo> &devs) {
|
||||
RtAudio endac;
|
||||
|
||||
int numDevices = endac.getDeviceCount();
|
||||
|
||||
for (int i = 0; i < numDevices; i++) {
|
||||
RtAudio::DeviceInfo info = dac.getDeviceInfo(i);
|
||||
RtAudio::DeviceInfo info = endac.getDeviceInfo(i);
|
||||
|
||||
devs.push_back(info);
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify);
|
||||
~AudioThread();
|
||||
|
||||
void enumerateDevices();
|
||||
static void enumerateDevices(std::vector<RtAudio::DeviceInfo> &devs);
|
||||
|
||||
void threadMain();
|
||||
void terminate();
|
||||
|
|
|
@ -181,3 +181,16 @@ void DemodulatorInstance::setSquelchEnabled(bool state) {
|
|||
squelch = state;
|
||||
}
|
||||
|
||||
float DemodulatorInstance::getSignalLevel() {
|
||||
return demodulatorThread->getSignalLevel();
|
||||
}
|
||||
|
||||
void DemodulatorInstance::setSquelchLevel(float signal_level_in) {
|
||||
demodulatorThread->setSquelchLevel(signal_level_in);
|
||||
}
|
||||
|
||||
|
||||
float DemodulatorInstance::getSquelchLevel() {
|
||||
return demodulatorThread->getSquelchLevel();
|
||||
}
|
||||
|
||||
|
|
|
@ -52,11 +52,20 @@ public:
|
|||
bool isStereo();
|
||||
void setStereo(bool state);
|
||||
|
||||
void squelchAuto();bool isSquelchEnabled();
|
||||
void squelchAuto();
|
||||
bool isSquelchEnabled();
|
||||
void setSquelchEnabled(bool state);
|
||||
|
||||
float getSignalLevel();
|
||||
void setSquelchLevel(float signal_level_in);
|
||||
float getSquelchLevel();
|
||||
|
||||
private:
|
||||
std::atomic<std::string *> label;bool terminated;bool demodTerminated;bool audioTerminated;bool preDemodTerminated;
|
||||
std::atomic<std::string *> label; //
|
||||
bool terminated; //
|
||||
bool demodTerminated; //
|
||||
bool audioTerminated; //
|
||||
bool preDemodTerminated;
|
||||
std::atomic<bool> active;
|
||||
std::atomic<bool> squelch;
|
||||
std::atomic<bool> stereo;
|
||||
|
|
|
@ -9,11 +9,9 @@
|
|||
DemodulatorThread::DemodulatorThread(DemodulatorThreadPostInputQueue* pQueue, DemodulatorThreadControlCommandQueue *threadQueueControl,
|
||||
DemodulatorThreadCommandQueue* threadQueueNotify) :
|
||||
postInputQueue(pQueue), visOutQueue(NULL), audioInputQueue(NULL), agc(NULL), stereo(false), terminated(false), threadQueueNotify(
|
||||
threadQueueNotify), threadQueueControl(threadQueueControl), squelch_level(0), squelch_tolerance(0), squelch_enabled(false) {
|
||||
threadQueueNotify), threadQueueControl(threadQueueControl), squelch_level(0), squelch_tolerance(0), signal_level(0), squelch_enabled(false) {
|
||||
|
||||
float kf = 0.5; // modulation factor
|
||||
fdem = freqdem_create(kf);
|
||||
// freqdem_print(fdem);
|
||||
fdem = freqdem_create(0.5);
|
||||
}
|
||||
DemodulatorThread::~DemodulatorThread() {
|
||||
}
|
||||
|
@ -64,7 +62,7 @@ void DemodulatorThread::threadMain() {
|
|||
double shift_freq = 0;
|
||||
|
||||
agc = agc_crcf_create();
|
||||
agc_crcf_set_bandwidth(agc, 1e-3f);
|
||||
agc_crcf_set_bandwidth(agc, 0.9);
|
||||
|
||||
std::cout << "Demodulator thread started.." << std::endl;
|
||||
|
||||
|
@ -176,10 +174,19 @@ void DemodulatorThread::threadMain() {
|
|||
msresamp_rrrf_execute(stereo_resampler, &demod_output_stereo[0], num_written, &resampled_audio_output_stereo[0], &num_audio_written);
|
||||
}
|
||||
|
||||
float current_level = ((60.0/fabs(agc_crcf_get_rssi(agc)))/15.0 - signal_level); //agc_crcf_get_signal_level(agc);
|
||||
|
||||
if (current_level > signal_level) {
|
||||
signal_level = signal_level + (current_level-signal_level) * 0.5;
|
||||
} else {
|
||||
signal_level = signal_level + (current_level-signal_level) * 0.05;
|
||||
}
|
||||
|
||||
|
||||
AudioThreadInput *ati = NULL;
|
||||
|
||||
if (audioInputQueue != NULL) {
|
||||
if (!squelch_enabled || ((agc_crcf_get_signal_level(agc)) >= 0.1)) {
|
||||
if (!squelch_enabled || (signal_level >= squelch_level)) {
|
||||
|
||||
for (buffers_i = buffers.begin(); buffers_i != buffers.end(); buffers_i++) {
|
||||
if ((*buffers_i)->getRefCount() <= 0) {
|
||||
|
@ -330,3 +337,18 @@ void DemodulatorThread::setStereo(bool state) {
|
|||
bool DemodulatorThread::isStereo() {
|
||||
return stereo;
|
||||
}
|
||||
|
||||
float DemodulatorThread::getSignalLevel() {
|
||||
return signal_level;
|
||||
}
|
||||
|
||||
void DemodulatorThread::setSquelchLevel(float signal_level_in) {
|
||||
if (!squelch_enabled) {
|
||||
squelch_enabled = true;
|
||||
}
|
||||
squelch_level = signal_level_in;
|
||||
}
|
||||
|
||||
float DemodulatorThread::getSquelchLevel() {
|
||||
return squelch_level;
|
||||
}
|
||||
|
|
|
@ -32,12 +32,16 @@ public:
|
|||
}
|
||||
|
||||
void initialize();
|
||||
|
||||
void terminate();
|
||||
|
||||
void setStereo(bool state);
|
||||
bool isStereo();
|
||||
|
||||
float getSignalLevel();
|
||||
void setSquelchLevel(float signal_level_in);
|
||||
float getSquelchLevel();
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
static void *pthread_helper(void *context) {
|
||||
return ((DemodulatorThread *) context)->threadMain();
|
||||
|
@ -57,7 +61,8 @@ protected:
|
|||
|
||||
DemodulatorThreadCommandQueue* threadQueueNotify;
|
||||
DemodulatorThreadControlCommandQueue *threadQueueControl;
|
||||
float squelch_level;
|
||||
std::atomic<float> squelch_level;
|
||||
float squelch_tolerance;
|
||||
std::atomic<float> signal_level;
|
||||
bool squelch_enabled;
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@ void MouseTracker::OnMouseMoved(wxMouseEvent& event) {
|
|||
const wxSize ClientSize = target->GetClientSize();
|
||||
|
||||
mouseX = (float) event.m_x / (float) ClientSize.x;
|
||||
mouseY = (float) event.m_y / (float) ClientSize.y;
|
||||
mouseY = 1.0 - (float) event.m_y / (float) ClientSize.y;
|
||||
|
||||
deltaMouseX = mouseX - lastMouseX;
|
||||
deltaMouseY = mouseY - lastMouseY;
|
||||
|
@ -17,11 +17,11 @@ void MouseTracker::OnMouseMoved(wxMouseEvent& event) {
|
|||
if (isMouseDown) {
|
||||
#ifndef __APPLE__
|
||||
if (horizDragLock && vertDragLock) {
|
||||
target->WarpPointer(originMouseX * ClientSize.x, originMouseY * ClientSize.y);
|
||||
target->WarpPointer(originMouseX * ClientSize.x, (1.0-originMouseY) * ClientSize.y);
|
||||
mouseX = originMouseX;
|
||||
mouseY = originMouseY;
|
||||
} else if (vertDragLock && mouseY != lastMouseY) {
|
||||
target->WarpPointer(event.m_x, originMouseY * ClientSize.y);
|
||||
target->WarpPointer(event.m_x, (1.0-originMouseY) * ClientSize.y);
|
||||
mouseY = originMouseY;
|
||||
} else if (horizDragLock && mouseX != lastMouseX) {
|
||||
target->WarpPointer(originMouseX * ClientSize.x, event.m_y);
|
||||
|
@ -42,7 +42,7 @@ void MouseTracker::OnMouseDown(wxMouseEvent& event) {
|
|||
const wxSize ClientSize = target->GetClientSize();
|
||||
|
||||
mouseX = lastMouseX = (float) event.m_x / (float) ClientSize.x;
|
||||
mouseY = lastMouseY = (float) event.m_y / (float) ClientSize.y;
|
||||
mouseY = lastMouseY = 1.0 - (float) event.m_y / (float) ClientSize.y;
|
||||
|
||||
originMouseX = mouseX;
|
||||
originMouseY = mouseY;
|
||||
|
|
|
@ -42,6 +42,9 @@ WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
|||
nco_shift = nco_crcf_create(LIQUID_NCO);
|
||||
shift_freq = 0;
|
||||
|
||||
fft_ceil_ma = fft_ceil_maa = 100.0;
|
||||
fft_floor_ma = fft_floor_maa = 0.0;
|
||||
|
||||
mTracker.setTarget(this);
|
||||
SetCursor(wxCURSOR_CROSS);
|
||||
}
|
||||
|
@ -81,9 +84,6 @@ void WaterfallCanvas::Setup(int fft_size_in, int waterfall_lines_in) {
|
|||
}
|
||||
plan = fftw_plan_dft_1d(fft_size, in, out, FFTW_FORWARD, FFTW_MEASURE);
|
||||
|
||||
fft_ceil_ma = fft_ceil_maa = 100.0;
|
||||
fft_floor_ma = fft_floor_maa = 0.0;
|
||||
|
||||
glContext->Setup(fft_size, waterfall_lines);
|
||||
timer.start();
|
||||
}
|
||||
|
@ -409,8 +409,13 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
|
|||
}
|
||||
|
||||
for (int i = 0, iMax = fft_size; i < iMax; i++) {
|
||||
fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65;
|
||||
fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65;
|
||||
if (isView) {
|
||||
fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.85;
|
||||
fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.55;
|
||||
} else {
|
||||
fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65;
|
||||
fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65;
|
||||
}
|
||||
|
||||
if (fft_result_maa[i] > fft_ceil) {
|
||||
fft_ceil = fft_result_maa[i];
|
||||
|
@ -423,7 +428,7 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
|
|||
fft_ceil += 1;
|
||||
fft_floor -= 1;
|
||||
|
||||
fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.01;
|
||||
fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.05;
|
||||
fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.01;
|
||||
|
||||
fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.01;
|
||||
|
|
Loading…
Reference in New Issue