Squelch slider/signal indicator

This commit is contained in:
Charles J. Cliffe 2014-12-31 19:45:01 -05:00
parent 4403824e3b
commit b7793ef905
12 changed files with 148 additions and 31 deletions

View File

@ -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

View File

@ -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()) {

View File

@ -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();
};

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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();
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;

View File

@ -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;