CubicSDR/src/CubicSDR.cpp

506 lines
13 KiB
C++
Raw Normal View History

#define OPENGL
#include "CubicSDRDefs.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
#include "CubicSDR.h"
#ifdef _OSX_APP_
#include "CoreFoundation/CoreFoundation.h"
#endif
IMPLEMENT_APP(CubicSDR)
2015-07-27 21:45:24 -04:00
CubicSDR::CubicSDR() : appframe(NULL), m_glContext(NULL), frequency(0), offset(0), ppm(0), snap(1), sampleRate(DEFAULT_SAMPLE_RATE), directSamplingMode(0),
sdrThread(NULL), sdrPostThread(NULL), spectrumVisualThread(NULL), demodVisualThread(NULL), pipeSDRIQData(NULL), pipeIQVisualData(NULL), pipeAudioVisualData(NULL), t_SDR(NULL), t_PostSDR(NULL) {
2015-07-27 21:45:24 -04:00
}
bool CubicSDR::OnInit() {
#ifdef _OSX_APP_
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
char path[PATH_MAX];
if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX))
{
// error!
}
CFRelease(resourcesURL);
chdir(path);
#endif
if (!wxApp::OnInit()) {
return false;
}
2015-04-21 23:19:45 -04:00
wxApp::SetAppName("CubicSDR");
2015-07-21 00:04:04 -04:00
frequency = wxGetApp().getConfig()->getCenterFreq();
offset = 0;
ppm = 0;
directSamplingMode = 0;
devicesReady.store(false);
deviceSelectorOpen.store(false);
// Visual Data
spectrumVisualThread = new SpectrumVisualDataThread();
demodVisualThread = new SpectrumVisualDataThread();
pipeIQVisualData = new DemodulatorThreadInputQueue();
pipeIQVisualData->set_max_num_items(1);
spectrumDistributor.setInput(pipeIQVisualData);
pipeDemodIQVisualData = new DemodulatorThreadInputQueue();
2015-08-11 22:11:54 -04:00
pipeDemodIQVisualData->set_max_num_items(1);
pipeSpectrumIQVisualData = new DemodulatorThreadInputQueue();
2015-08-11 22:11:54 -04:00
pipeSpectrumIQVisualData->set_max_num_items(1);
pipeWaterfallIQVisualData = new DemodulatorThreadInputQueue();
2015-09-10 23:42:22 -04:00
pipeWaterfallIQVisualData->set_max_num_items(128);
spectrumDistributor.attachOutput(pipeDemodIQVisualData);
spectrumDistributor.attachOutput(pipeSpectrumIQVisualData);
getDemodSpectrumProcessor()->setInput(pipeDemodIQVisualData);
getSpectrumProcessor()->setInput(pipeSpectrumIQVisualData);
pipeAudioVisualData = new DemodulatorThreadOutputQueue();
pipeAudioVisualData->set_max_num_items(1);
2015-08-01 11:03:00 -04:00
scopeProcessor.setInput(pipeAudioVisualData);
// I/Q Data
pipeSDRIQData = new SDRThreadIQDataQueue();
pipeSDRIQData->set_max_num_items(100);
sdrThread = new SDRThread();
sdrThread->setOutputQueue("IQDataOutput",pipeSDRIQData);
sdrPostThread = new SDRPostThread();
// sdrPostThread->setNumVisSamples(BUF_SIZE);
sdrPostThread->setInputQueue("IQDataInput", pipeSDRIQData);
sdrPostThread->setOutputQueue("IQVisualDataOutput", pipeIQVisualData);
sdrPostThread->setOutputQueue("IQDataOutput", pipeWaterfallIQVisualData);
t_PostSDR = new std::thread(&SDRPostThread::threadMain, sdrPostThread);
t_SpectrumVisual = new std::thread(&SpectrumVisualDataThread::threadMain, spectrumVisualThread);
t_DemodVisual = new std::thread(&SpectrumVisualDataThread::threadMain, demodVisualThread);
// t_SDR = new std::thread(&SDRThread::threadMain, sdrThread);
sdrEnum = new SDREnumerator();
appframe = new AppFrame();
2015-10-10 01:13:48 -04:00
t_SDREnum = new std::thread(&SDREnumerator::threadMain, sdrEnum);
//#ifdef __APPLE__
// int main_policy;
// struct sched_param main_param;
//
// main_policy = SCHED_RR;
// main_param.sched_priority = sched_get_priority_min(SCHED_RR)+2;
//
// pthread_setschedparam(pthread_self(), main_policy, &main_param);
//#endif
return true;
}
int CubicSDR::OnExit() {
demodMgr.terminateAll();
std::cout << "Terminating SDR thread.." << std::endl;
if (!sdrThread->isTerminated()) {
sdrThread->terminate();
if (t_SDR) {
t_SDR->join();
}
}
std::cout << "Terminating SDR post-processing thread.." << std::endl;
sdrPostThread->terminate();
t_PostSDR->join();
std::cout << "Terminating Visual Processor threads.." << std::endl;
spectrumVisualThread->terminate();
t_SpectrumVisual->join();
demodVisualThread->terminate();
t_DemodVisual->join();
delete sdrThread;
delete sdrPostThread;
delete t_PostSDR;
delete t_SpectrumVisual;
delete spectrumVisualThread;
delete t_DemodVisual;
delete demodVisualThread;
delete pipeIQVisualData;
delete pipeAudioVisualData;
delete pipeSDRIQData;
delete m_glContext;
2015-01-10 21:49:58 -05:00
#ifdef __APPLE__
AudioThread::deviceCleanup();
#endif
return wxApp::OnExit();
}
PrimaryGLContext& CubicSDR::GetContext(wxGLCanvas *canvas) {
PrimaryGLContext *glContext;
if (!m_glContext) {
m_glContext = new PrimaryGLContext(canvas, NULL);
}
glContext = m_glContext;
return *glContext;
}
void CubicSDR::OnInitCmdLine(wxCmdLineParser& parser) {
parser.SetDesc (commandLineInfo);
parser.SetSwitchChars (wxT("-"));
}
bool CubicSDR::OnCmdLineParsed(wxCmdLineParser& parser) {
wxString *confName = new wxString;
if (parser.Found("c",confName)) {
if (confName) {
config.setConfigName(confName->ToStdString());
}
}
config.load();
return true;
}
void CubicSDR::deviceSelector() {
if (deviceSelectorOpen) {
deviceSelectorDialog->Raise();
deviceSelectorDialog->SetFocus();
return;
}
deviceSelectorOpen.store(true);
deviceSelectorDialog = new SDRDevicesDialog(appframe);
deviceSelectorDialog->Show();
}
void CubicSDR::addRemote(std::string remoteAddr) {
SDREnumerator::addRemote(remoteAddr);
devicesReady.store(false);
t_SDREnum = new std::thread(&SDREnumerator::threadMain, sdrEnum);
}
void CubicSDR::removeRemote(std::string remoteAddr) {
SDREnumerator::removeRemote(remoteAddr);
}
void CubicSDR::sdrThreadNotify(SDRThread::SDRThreadState state, std::string message) {
notify_busy.lock();
if (state == SDRThread::SDR_THREAD_MESSAGE) {
notifyMessage = message;
}
if (state == SDRThread::SDR_THREAD_TERMINATED) {
t_SDR->join();
delete t_SDR;
}
if (state == SDRThread::SDR_THREAD_FAILED) {
notifyMessage = message;
// wxMessageDialog *info;
// info = new wxMessageDialog(NULL, message, wxT("Error initializing device"), wxOK | wxICON_ERROR);
// info->ShowModal();
}
//if (appframe) { appframe->SetStatusText(message); }
notify_busy.unlock();
}
void CubicSDR::sdrEnumThreadNotify(SDREnumerator::SDREnumState state, std::string message) {
notify_busy.lock();
if (state == SDREnumerator::SDR_ENUM_MESSAGE) {
notifyMessage = message;
}
if (state == SDREnumerator::SDR_ENUM_DEVICES_READY) {
devs = SDREnumerator::enumerate_devices("", true);
devicesReady.store(true);
}
if (state == SDREnumerator::SDR_ENUM_FAILED) {
notifyMessage = message;
sdrEnum->terminate();
}
//if (appframe) { appframe->SetStatusText(message); }
notify_busy.unlock();
}
void CubicSDR::setFrequency(long long freq) {
2015-01-11 17:08:16 -05:00
if (freq < sampleRate / 2) {
freq = sampleRate / 2;
}
frequency = freq;
sdrThread->setFrequency(freq);
}
long long CubicSDR::getOffset() {
return offset;
}
void CubicSDR::setOffset(long long ofs) {
offset = ofs;
sdrThread->setOffset(offset);
SDRDeviceInfo *dev = getDevice();
config.getDevice(dev->getDeviceId())->setOffset(ofs);
}
void CubicSDR::setDirectSampling(int mode) {
directSamplingMode = mode;
sdrThread->setDirectSampling(mode);
SDRDeviceInfo *dev = getDevice();
config.getDevice(dev->getDeviceId())->setDirectSampling(mode);
}
int CubicSDR::getDirectSampling() {
return directSamplingMode;
}
2015-05-31 22:13:14 -04:00
void CubicSDR::setSwapIQ(bool swapIQ) {
sdrPostThread->setSwapIQ(swapIQ);
SDRDeviceInfo *dev = getDevice();
config.getDevice(dev->getDeviceId())->setIQSwap(swapIQ);
2015-05-31 22:13:14 -04:00
}
bool CubicSDR::getSwapIQ() {
return sdrPostThread->getSwapIQ();
}
long long CubicSDR::getFrequency() {
return frequency;
}
2014-12-10 21:22:13 -05:00
void CubicSDR::setSampleRate(long long rate_in) {
sampleRate = rate_in;
sdrThread->setSampleRate(sampleRate);
setFrequency(frequency);
}
void CubicSDR::setDevice(SDRDeviceInfo *dev) {
if (!sdrThread->isTerminated()) {
sdrThread->terminate();
if (t_SDR) {
t_SDR->join();
delete t_SDR;
}
}
sdrThread->setDevice(dev);
DeviceConfig *devConfig = config.getDevice(dev->getDeviceId());
SDRDeviceChannel *chan = dev->getRxChannel();
if (chan) {
long long freqHigh, freqLow;
freqHigh = chan->getRFRange().getHigh();
freqLow = chan->getRFRange().getLow();
// upconverter settings don't like this, need to handle elsewhere..
// if (frequency > freqHigh) {
// frequency = freqHigh;
// }
// else if (frequency < freqLow) {
// frequency = freqLow;
// }
int rateHigh, rateLow;
rateLow = chan->getSampleRates()[0];
rateHigh = chan->getSampleRates()[chan->getSampleRates().size()-1];
if (sampleRate > rateHigh) {
sampleRate = rateHigh;
} else if (sampleRate < rateLow) {
sampleRate = rateLow;
}
if (frequency < sampleRate/2) {
frequency = sampleRate/2;
}
setFrequency(frequency);
setSampleRate(sampleRate);
setPPM(devConfig->getPPM());
setDirectSampling(devConfig->getDirectSampling());
setSwapIQ(devConfig->getIQSwap());
setOffset(devConfig->getOffset());
t_SDR = new std::thread(&SDRThread::threadMain, sdrThread);
}
}
SDRDeviceInfo *CubicSDR::getDevice() {
return sdrThread->getDevice();
}
2015-08-01 11:03:00 -04:00
ScopeVisualProcessor *CubicSDR::getScopeProcessor() {
return &scopeProcessor;
}
SpectrumVisualProcessor *CubicSDR::getSpectrumProcessor() {
return spectrumVisualThread->getProcessor();
}
SpectrumVisualProcessor *CubicSDR::getDemodSpectrumProcessor() {
return demodVisualThread->getProcessor();
}
VisualDataDistributor<DemodulatorThreadIQData> *CubicSDR::getSpectrumDistributor() {
return &spectrumDistributor;
}
2014-12-10 21:22:13 -05:00
DemodulatorThreadOutputQueue* CubicSDR::getAudioVisualQueue() {
return pipeAudioVisualData;
2014-12-10 21:22:13 -05:00
}
2014-12-26 16:15:35 -05:00
DemodulatorThreadInputQueue* CubicSDR::getIQVisualQueue() {
return pipeIQVisualData;
2014-12-10 21:22:13 -05:00
}
DemodulatorThreadInputQueue* CubicSDR::getWaterfallVisualQueue() {
return pipeWaterfallIQVisualData;
}
2014-12-10 21:22:13 -05:00
DemodulatorMgr &CubicSDR::getDemodMgr() {
return demodMgr;
}
void CubicSDR::bindDemodulator(DemodulatorInstance *demod) {
if (!demod) {
return;
}
sdrPostThread->bindDemodulator(demod);
}
2015-01-11 17:08:16 -05:00
long long CubicSDR::getSampleRate() {
return sampleRate;
}
2014-12-10 21:22:13 -05:00
void CubicSDR::removeDemodulator(DemodulatorInstance *demod) {
if (!demod) {
return;
}
2015-01-22 23:41:33 -05:00
demod->setActive(false);
2014-12-10 21:22:13 -05:00
sdrPostThread->removeDemodulator(demod);
}
2015-01-12 00:40:43 -05:00
std::vector<SDRDeviceInfo*>* CubicSDR::getDevices() {
return devs;
2015-01-12 00:40:43 -05:00
}
AppConfig *CubicSDR::getConfig() {
return &config;
}
2015-04-22 22:54:48 -04:00
void CubicSDR::saveConfig() {
config.save();
2015-04-22 22:54:48 -04:00
}
void CubicSDR::setPPM(int ppm_in) {
ppm = ppm_in;
sdrThread->setPPM(ppm);
SDRDeviceInfo *dev = getDevice();
if (dev) {
config.getDevice(dev->getDeviceId())->setPPM(ppm_in);
}
}
int CubicSDR::getPPM() {
SDRDeviceInfo *dev = sdrThread->getDevice();
if (dev) {
ppm = config.getDevice(dev->getDeviceId())->getPPM();
}
return ppm;
}
2015-05-04 19:44:03 -04:00
void CubicSDR::showFrequencyInput(FrequencyDialog::FrequencyDialogTarget targetMode) {
const wxString demodTitle("Set Demodulator Frequency");
const wxString freqTitle("Set Center Frequency");
const wxString bwTitle("Set Demodulator Bandwidth");
wxString title;
switch (targetMode) {
case FrequencyDialog::FDIALOG_TARGET_DEFAULT:
title = demodMgr.getActiveDemodulator()?demodTitle:freqTitle;
break;
case FrequencyDialog::FDIALOG_TARGET_BANDWIDTH:
title = bwTitle;
break;
default:
break;
}
FrequencyDialog fdialog(appframe, -1, title, demodMgr.getActiveDemodulator(), wxPoint(-100,-100), wxSize(320, 75 ), wxDEFAULT_DIALOG_STYLE, targetMode);
2015-05-10 01:39:10 -04:00
fdialog.ShowModal();
2015-05-04 19:44:03 -04:00
}
2015-05-10 01:39:10 -04:00
AppFrame *CubicSDR::getAppFrame() {
return appframe;
}
void CubicSDR::setFrequencySnap(int snap) {
if (snap > 1000000) {
snap = 1000000;
}
this->snap = snap;
}
int CubicSDR::getFrequencySnap() {
return snap;
}
bool CubicSDR::areDevicesReady() {
return devicesReady.load();
}
bool CubicSDR::areDevicesEnumerating() {
return !sdrEnum->isTerminated();
}
std::string CubicSDR::getNotification() {
std::string msg;
notify_busy.lock();
msg = notifyMessage;
notify_busy.unlock();
return msg;
}
void CubicSDR::setDeviceSelectorClosed() {
deviceSelectorOpen.store(false);
}
2015-10-10 01:13:48 -04:00
bool CubicSDR::isDeviceSelectorOpen() {
return deviceSelectorOpen.load();
}