2014-10-27 21:22:29 -04:00
|
|
|
#include "AppFrame.h"
|
|
|
|
|
|
|
|
#include "wx/wxprec.h"
|
|
|
|
|
|
|
|
#ifndef WX_PRECOMP
|
|
|
|
#include "wx/wx.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !wxUSE_GLCANVAS
|
|
|
|
#error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
|
|
|
|
#endif
|
|
|
|
|
2014-10-28 21:39:59 -04:00
|
|
|
#include <vector>
|
|
|
|
#include "SDRThread.h"
|
2014-11-16 16:51:45 -05:00
|
|
|
#include "DemodulatorThread.h"
|
|
|
|
#include "AudioThread.h"
|
2014-10-27 21:22:29 -04:00
|
|
|
|
2014-10-28 21:39:59 -04:00
|
|
|
wxBEGIN_EVENT_TABLE(AppFrame, wxFrame)
|
|
|
|
//EVT_MENU(wxID_NEW, AppFrame::OnNewWindow)
|
2014-10-27 21:22:29 -04:00
|
|
|
EVT_MENU(wxID_CLOSE, AppFrame::OnClose)
|
2014-10-28 21:39:59 -04:00
|
|
|
EVT_THREAD(EVENT_SDR_INPUT, AppFrame::OnEventInput)
|
2014-11-16 16:51:45 -05:00
|
|
|
EVT_THREAD(EVENT_DEMOD_INPUT, AppFrame::OnDemodInput)
|
|
|
|
EVT_THREAD(EVENT_AUDIO_INPUT, AppFrame::OnAudioInput)
|
2014-10-28 21:39:59 -04:00
|
|
|
EVT_IDLE(AppFrame::OnIdle)
|
2014-10-27 21:22:29 -04:00
|
|
|
wxEND_EVENT_TABLE()
|
|
|
|
|
|
|
|
AppFrame::AppFrame() :
|
2014-11-04 19:52:11 -05:00
|
|
|
wxFrame(NULL, wxID_ANY, wxT("CubicSDR")), frequency(DEFAULT_FREQ) {
|
2014-10-27 21:22:29 -04:00
|
|
|
|
2014-11-15 23:41:41 -05:00
|
|
|
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
|
|
|
|
|
|
|
|
scopeCanvas = new ScopeCanvas(this, NULL);
|
|
|
|
vbox->Add(scopeCanvas, 1, wxEXPAND | wxALL, 0);
|
|
|
|
vbox->AddSpacer(2);
|
|
|
|
spectrumCanvas = new SpectrumCanvas(this, NULL);
|
|
|
|
vbox->Add(spectrumCanvas, 1, wxEXPAND | wxALL, 0);
|
|
|
|
vbox->AddSpacer(2);
|
|
|
|
waterfallCanvas = new WaterfallCanvas(this, NULL);
|
|
|
|
vbox->Add(waterfallCanvas, 4, wxEXPAND | wxALL, 0);
|
|
|
|
|
|
|
|
this->SetSizer(vbox);
|
2014-10-27 21:22:29 -04:00
|
|
|
|
2014-10-27 23:52:25 -04:00
|
|
|
// SetIcon(wxICON(sample));
|
2014-10-27 21:22:29 -04:00
|
|
|
|
2014-10-28 21:39:59 -04:00
|
|
|
// Make a menubar
|
2014-10-27 21:22:29 -04:00
|
|
|
wxMenu *menu = new wxMenu;
|
|
|
|
// menu->Append(wxID_NEW);
|
|
|
|
// menu->AppendSeparator();
|
|
|
|
menu->Append(wxID_CLOSE);
|
|
|
|
wxMenuBar *menuBar = new wxMenuBar;
|
|
|
|
menuBar->Append(menu, wxT("&File"));
|
|
|
|
|
|
|
|
SetMenuBar(menuBar);
|
|
|
|
|
|
|
|
CreateStatusBar();
|
2014-10-31 01:37:01 -04:00
|
|
|
SetClientSize(1280, 400);
|
|
|
|
Centre();
|
2014-10-27 21:22:29 -04:00
|
|
|
Show();
|
|
|
|
|
2014-11-16 16:51:45 -05:00
|
|
|
threadQueueSDR = new SDRThreadQueue(this);
|
|
|
|
t_SDR = new SDRThread(threadQueueSDR);
|
2014-11-04 17:25:04 -05:00
|
|
|
if (t_SDR->Run() != wxTHREAD_NO_ERROR) {
|
|
|
|
wxLogError
|
2014-11-16 16:51:45 -05:00
|
|
|
("Can't create the SDR thread!");
|
2014-11-04 17:25:04 -05:00
|
|
|
delete t_SDR;
|
|
|
|
t_SDR = NULL;
|
|
|
|
}
|
|
|
|
|
2014-11-16 16:51:45 -05:00
|
|
|
threadQueueDemod = new DemodulatorThreadQueue(this);
|
|
|
|
t_Demod = new DemodulatorThread(threadQueueDemod);
|
|
|
|
if (t_Demod->Run() != wxTHREAD_NO_ERROR) {
|
|
|
|
wxLogError
|
|
|
|
("Can't create the Demodulator thread!");
|
|
|
|
delete t_Demod;
|
|
|
|
t_Demod = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
threadQueueAudio = new AudioThreadQueue(this);
|
|
|
|
t_Audio = new AudioThread(threadQueueAudio);
|
|
|
|
if (t_Audio->Run() != wxTHREAD_NO_ERROR) {
|
|
|
|
wxLogError
|
|
|
|
("Can't create the Audio thread!");
|
|
|
|
delete t_Audio;
|
|
|
|
t_Audio = NULL;
|
|
|
|
}
|
|
|
|
|
2014-11-04 18:39:08 -05:00
|
|
|
// t_IQBuffer = new IQBufferThread(this);
|
|
|
|
// if (t_IQBuffer->Run() != wxTHREAD_NO_ERROR) {
|
|
|
|
// wxLogError
|
|
|
|
// ("Can't create the thread!");
|
|
|
|
// delete t_IQBuffer;
|
2014-11-16 16:51:45 -05:00
|
|
|
// t_IQBuffer = NULL;
|
2014-11-04 18:39:08 -05:00
|
|
|
// }
|
2014-11-04 17:25:04 -05:00
|
|
|
|
2014-10-27 21:22:29 -04:00
|
|
|
// static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
|
|
|
|
// wxLogStatus("Double-buffered display %s supported", wxGLCanvas::IsDisplaySupported(attribs) ? "is" : "not");
|
|
|
|
// ShowFullScreen(true);
|
|
|
|
}
|
|
|
|
|
2014-11-04 18:39:08 -05:00
|
|
|
AppFrame::~AppFrame() {
|
|
|
|
{
|
|
|
|
wxCriticalSectionLocker enter(m_pThreadCS);
|
|
|
|
if (t_SDR) {
|
|
|
|
wxMessageOutputDebug().Printf("CubicSDR: deleting thread");
|
|
|
|
if (t_SDR->Delete() != wxTHREAD_NO_ERROR) {
|
|
|
|
wxLogError
|
|
|
|
("Can't delete the thread!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-15 23:41:41 -05:00
|
|
|
// {
|
|
|
|
// wxCriticalSectionLocker enter(m_pThreadCS);
|
|
|
|
// if (t_IQBuffer) {
|
|
|
|
// wxMessageOutputDebug().Printf("CubicSDR: deleting thread");
|
|
|
|
// if (t_IQBuffer->Delete() != wxTHREAD_NO_ERROR) {
|
|
|
|
// wxLogError
|
|
|
|
// ("Can't delete the thread!");
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
2014-11-11 20:25:16 -05:00
|
|
|
|
2014-11-16 16:51:45 -05:00
|
|
|
// delete t_SDR;
|
2014-11-11 20:25:16 -05:00
|
|
|
// delete t_IQBuffer;
|
2014-11-16 16:51:45 -05:00
|
|
|
delete threadQueueAudio;
|
|
|
|
delete threadQueueDemod;
|
|
|
|
delete threadQueueSDR;
|
2014-11-11 20:25:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppFrame::OnClose(wxCommandEvent& WXUNUSED(event)) {
|
|
|
|
|
2014-10-27 21:22:29 -04:00
|
|
|
// true is to force the frame to close
|
|
|
|
Close(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppFrame::OnNewWindow(wxCommandEvent& WXUNUSED(event)) {
|
|
|
|
new AppFrame();
|
|
|
|
}
|
2014-10-28 21:39:59 -04:00
|
|
|
|
2014-11-16 16:51:45 -05:00
|
|
|
// SDR IQ -> Demodulator
|
2014-10-28 21:39:59 -04:00
|
|
|
void AppFrame::OnEventInput(wxThreadEvent& event) {
|
2014-10-28 22:59:17 -04:00
|
|
|
std::vector<signed char> *new_buffer = event.GetPayload<std::vector<signed char> *>();
|
2014-11-16 16:51:45 -05:00
|
|
|
// std::cout << new_buffer->size() << std::endl;
|
|
|
|
if (new_buffer->size()) {
|
|
|
|
test_demod.writeBuffer(new_buffer);
|
|
|
|
scopeCanvas->setWaveformPoints(test_demod.waveform_points);
|
|
|
|
spectrumCanvas->setData(new_buffer);
|
|
|
|
waterfallCanvas->setData(new_buffer);
|
|
|
|
} else {
|
|
|
|
std::cout << "Incoming IQ data empty?" << std::endl;
|
|
|
|
}
|
|
|
|
delete new_buffer;
|
|
|
|
}
|
2014-10-28 21:39:59 -04:00
|
|
|
|
|
|
|
|
2014-11-16 16:51:45 -05:00
|
|
|
// Demodulator -> Audio
|
|
|
|
void AppFrame::OnDemodInput(wxThreadEvent& event) {
|
|
|
|
std::vector<float> *new_buffer = event.GetPayload<std::vector<float> *>();
|
|
|
|
|
|
|
|
if (new_buffer->size()) {
|
|
|
|
AudioThreadTask task = AudioThreadTask(AudioThreadTask::AUDIO_THREAD_DATA);
|
|
|
|
task.setData(*new_buffer);
|
|
|
|
threadQueueAudio->addTask(task, AudioThreadQueue::AUDIO_PRIORITY_HIGHEST);
|
|
|
|
} else {
|
|
|
|
std::cout << "Incoming Demod data empty?" << std::endl;
|
|
|
|
}
|
2014-10-28 21:39:59 -04:00
|
|
|
delete new_buffer;
|
|
|
|
}
|
|
|
|
|
2014-11-16 16:51:45 -05:00
|
|
|
// Audio -> Visual
|
|
|
|
void AppFrame::OnAudioInput(wxThreadEvent& event) {
|
|
|
|
// std::vector<float> *new_buffer = event.GetPayload<std::vector<float> *>();
|
|
|
|
//
|
|
|
|
// if (new_buffer->size()) {
|
|
|
|
// AudioThreadTask task = AudioThreadTask(AudioThreadTask::AUDIO_THREAD_DATA);
|
|
|
|
// task.setData(*new_buffer);
|
|
|
|
// threadQueueAudio->addTask(task, AudioThreadQueue::AUDIO_PRIORITY_HIGHEST);
|
|
|
|
// } else {
|
|
|
|
// std::cout << "Incoming Demod data empty?" << std::endl;
|
|
|
|
// }
|
|
|
|
// delete new_buffer;
|
|
|
|
}
|
|
|
|
|
2014-10-28 21:39:59 -04:00
|
|
|
void AppFrame::OnIdle(wxIdleEvent& event) {
|
|
|
|
|
|
|
|
event.Skip();
|
|
|
|
}
|
2014-11-04 19:52:11 -05:00
|
|
|
|
|
|
|
void AppFrame::setFrequency(unsigned int freq) {
|
|
|
|
frequency = freq;
|
|
|
|
SDRThreadTask task = SDRThreadTask(SDRThreadTask::SDR_THREAD_TUNING);
|
|
|
|
task.setUInt(freq);
|
2014-11-16 16:51:45 -05:00
|
|
|
threadQueueSDR->addTask(task, SDRThreadQueue::SDR_PRIORITY_HIGHEST);
|
2014-11-04 19:52:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
int AppFrame::getFrequency() {
|
|
|
|
return frequency;
|
|
|
|
}
|