Skip to content

Commit

Permalink
Merge pull request #71 from cjcliffe/ppm_correction
Browse files Browse the repository at this point in the history
PPM menu dialog and tuning bar tool
  • Loading branch information
cjcliffe committed Apr 24, 2015
2 parents 4f2b9d9 + 8589a39 commit bad45a7
Show file tree
Hide file tree
Showing 23 changed files with 459 additions and 63 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ ENDIF (APPLE)
SET (cubicsdr_sources
src/CubicSDR.cpp
src/AppFrame.cpp
src/AppConfig.cpp
src/sdr/SDRThread.cpp
src/sdr/SDRPostThread.cpp
src/demod/DemodulatorPreThread.cpp
Expand Down Expand Up @@ -267,6 +268,7 @@ SET (cubicsdr_headers
src/CubicSDRDefs.h
src/CubicSDR.h
src/AppFrame.h
src/AppConfig.h
src/sdr/SDRThread.h
src/sdr/SDRPostThread.h
src/demod/DemodulatorPreThread.h
Expand Down
133 changes: 133 additions & 0 deletions src/AppConfig.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#include "AppConfig.h"

DeviceConfig::DeviceConfig() : ppm(0), deviceId("") {

}

DeviceConfig::DeviceConfig(std::string deviceId) : ppm(0) {
this->deviceId = deviceId;
}

void DeviceConfig::setPPM(int ppm) {
this->ppm = ppm;
}

int DeviceConfig::getPPM() {
return ppm;
}

void DeviceConfig::setDeviceId(std::string deviceId) {
this->deviceId = deviceId;
}

std::string DeviceConfig::getDeviceId() {
return deviceId;
}

void DeviceConfig::save(DataNode *node) {
node->newChild("id")->element()->set(deviceId);
DataNode *ppm_node = node->newChild("ppm");
ppm_node->element()->set((int)ppm);
}

void DeviceConfig::load(DataNode *node) {
if (node->hasAnother("ppm")) {
DataNode *ppm_node = node->getNext("ppm");
int ppmValue = 0;
ppm_node->element()->get(ppmValue);
setPPM(ppmValue);
std::cout << "Loaded PPM for device '" << deviceId << "' at " << ppmValue << "ppm" << std::endl;
}
}


DeviceConfig *AppConfig::getDevice(std::string deviceId) {
DeviceConfig *conf = &deviceConfig[deviceId];
conf->setDeviceId(deviceId);
return conf;
}

std::string AppConfig::getConfigDir() {
std::string dataDir = wxStandardPaths::Get().GetUserDataDir().ToStdString();

bool mkStatus = false;

if (!wxDir::Exists(dataDir)) {
mkStatus = wxDir::Make(dataDir);
} else {
mkStatus = true;
}

if (!mkStatus) {
std::cout << "Warning, unable to initialize user data directory." << std::endl;
}

return dataDir;
}

bool AppConfig::save() {
DataTree cfg;

cfg.rootNode()->setName("cubicsdr_config");
DataNode *devices_node = cfg.rootNode()->newChild("devices");

std::map<std::string, DeviceConfig>::iterator device_config_i;
for (device_config_i = deviceConfig.begin(); device_config_i != deviceConfig.end(); device_config_i++) {
DataNode *device_node = devices_node->newChild("device");
device_config_i->second.save(device_node);
}

std::string cfgFileDir = getConfigDir();

wxFileName cfgFile = wxFileName(cfgFileDir, "config.xml");
std::string cfgFileName = cfgFile.GetFullPath(wxPATH_NATIVE).ToStdString();

if (!cfg.SaveToFileXML(cfgFileName)) {
std::cout << "Error saving :: configuration file '" << cfgFileName << "' is not writable!" << std::endl;
return false;
}

return true;
}

bool AppConfig::load() {
DataTree cfg;
std::string cfgFileDir = getConfigDir();

wxFileName cfgFile = wxFileName(cfgFileDir, "config.xml");
std::string cfgFileName = cfgFile.GetFullPath(wxPATH_NATIVE).ToStdString();

if (!cfgFile.Exists()) {
return true;
}

if (cfgFile.IsFileReadable()) {
std::cout << "Loading:: configuration file '" << cfgFileName << "'" << std::endl;

cfg.LoadFromFileXML(cfgFileName);
} else {
std::cout << "Error loading:: configuration file '" << cfgFileName << "' is not readable!" << std::endl;
return false;
}

if (cfg.rootNode()->hasAnother("devices")) {
DataNode *devices_node = cfg.rootNode()->getNext("devices");

while (devices_node->hasAnother("device")) {
DataNode *device_node = devices_node->getNext("device");
if (device_node->hasAnother("id")) {
std::string deviceId;
device_node->getNext("id")->element()->get(deviceId);

getDevice(deviceId)->load(device_node);
}
}
}

return true;
}

bool AppConfig::reset() {

return true;
}
40 changes: 40 additions & 0 deletions src/AppConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include <wx/stdpaths.h>
#include <wx/dir.h>
#include <wx/filename.h>

#include "DataTree.h"


class DeviceConfig {
public:
DeviceConfig();
DeviceConfig(std::string deviceId);

void setPPM(int ppm);
int getPPM();

void setDeviceId(std::string deviceId);
std::string getDeviceId();

void save(DataNode *node);
void load(DataNode *node);

private:
std::string deviceId;
int ppm;
};

class AppConfig {
public:
std::string getConfigDir();
DeviceConfig *getDevice(std::string deviceId);

bool save();
bool load();
bool reset();

private:
std::map<std::string, DeviceConfig> deviceConfig;
};
28 changes: 28 additions & 0 deletions src/AppFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ AppFrame::AppFrame() :
wxMenu *menu = new wxMenu;
// menu->Append(wxID_NEW);
menu->Append(wxID_SET_FREQ_OFFSET, "Set Frequency Offset");
menu->Append(wxID_SET_PPM, "Set Device PPM");
menu->Append(wxID_OPEN, "&Open Session");
menu->Append(wxID_SAVE, "&Save Session");
menu->Append(wxID_SAVEAS, "Save Session &As..");
Expand Down Expand Up @@ -318,6 +319,11 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
if (ofs != -1) {
wxGetApp().setOffset(ofs);
}
} else if (event.GetId() == wxID_SET_PPM) {
long ofs = wxGetNumberFromUser("Frequency correction for device in PPM.\ni.e. -51 for -51 PPM\n\nNote: you can adjust PPM interactively\nby holding ALT over the frequency tuning bar.\n", "Parts per million (PPM)",
"Frequency Correction", wxGetApp().getPPM(), -1000, 1000, this);
wxGetApp().setPPM(ofs);
wxGetApp().saveConfig();
} else if (event.GetId() == wxID_SAVE) {
if (!currentSessionFile.empty()) {
saveSession(currentSessionFile);
Expand Down Expand Up @@ -440,6 +446,26 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();

if (demod) {
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();

if (demod->isTracking()) {
if (spectrumCanvas->getViewState()) {
long long diff = abs(demod->getFrequency() - spectrumCanvas->getCenterFrequency()) + (demod->getBandwidth()/2) + (demod->getBandwidth()/4);

if (diff > spectrumCanvas->getBandwidth()/2) {
if (demod->getBandwidth() > spectrumCanvas->getBandwidth()) {
diff = abs(demod->getFrequency() - spectrumCanvas->getCenterFrequency());
} else {
diff = diff - spectrumCanvas->getBandwidth()/2;
}
spectrumCanvas->moveCenterFrequency((demod->getFrequency() < spectrumCanvas->getCenterFrequency())?diff:-diff);
demod->setTracking(false);
}
} else {
demod->setTracking(false);
}
}

if (demod != activeDemodulator) {
demodSignalMeter->setInputValue(demod->getSquelchLevel());
demodGainMeter->setInputValue(demod->getGain());
Expand Down Expand Up @@ -526,6 +552,8 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
waterfallCanvas->SetFocus();
}

scopeCanvas->setPPMMode(demodTuner->isAltDown());

event.Skip();
}

Expand Down
1 change: 1 addition & 0 deletions src/AppFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define wxID_RT_AUDIO_DEVICE 1000
#define wxID_SET_FREQ_OFFSET 2001
#define wxID_RESET 2002
#define wxID_SET_PPM 2003

#define wxID_THEME_DEFAULT 2100
#define wxID_THEME_SHARP 2101
Expand Down
58 changes: 54 additions & 4 deletions src/CubicSDR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,18 @@ bool CubicSDR::OnInit() {
CFRelease(resourcesURL);
chdir(path);
#endif
if (!wxApp::OnInit())

if (!wxApp::OnInit()) {
return false;
}

wxApp::SetAppName("CubicSDR");

config.load();

frequency = DEFAULT_FREQ;
offset = 0;
ppm = 0;

audioVisualQueue = new DemodulatorThreadOutputQueue();
audioVisualQueue->set_max_num_items(1);
Expand All @@ -47,7 +53,7 @@ bool CubicSDR::OnInit() {
sdrThread = new SDRThread(threadCmdQueueSDR);

sdrPostThread = new SDRPostThread();
sdrPostThread->setNumVisSamples(16384*2);
sdrPostThread->setNumVisSamples(16384 * 2);

iqPostDataQueue = new SDRThreadIQDataQueue;
iqVisualQueue = new DemodulatorThreadInputQueue;
Expand Down Expand Up @@ -77,7 +83,7 @@ bool CubicSDR::OnInit() {
choices.Add(devName);
}

int devId = wxGetSingleChoiceIndex(wxT("Devices"),wxT("Choose Input Device"),choices);
int devId = wxGetSingleChoiceIndex(wxT("Devices"), wxT("Choose Input Device"), choices);

std::cout << "Chosen: " << devId << std::endl;
sdrThread->setDeviceId(devId);
Expand Down Expand Up @@ -216,8 +222,52 @@ void CubicSDR::setDevice(int deviceId) {
SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_SET_DEVICE);
command.llong_value = deviceId;
threadCmdQueueSDR->push(command);

SDRDeviceInfo *dev = (*getDevices())[deviceId];

SDRThreadCommand command_ppm(SDRThreadCommand::SDR_THREAD_CMD_SET_PPM);
ppm = config.getDevice(dev->getDeviceId())->getPPM();
command_ppm.llong_value = ppm;
threadCmdQueueSDR->push(command_ppm);
}

int CubicSDR::getDevice() {
return sdrThread->getDeviceId();
}

AppConfig *CubicSDR::getConfig() {
return &config;
}

void CubicSDR::saveConfig() {
config.save();
}

void CubicSDR::setPPM(int ppm_in) {
if (sdrThread->getDeviceId() < 0) {
return;
}
ppm = ppm_in;

SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_SET_PPM);
command.llong_value = ppm;
threadCmdQueueSDR->push(command);

SDRDeviceInfo *dev = (*getDevices())[getDevice()];

config.getDevice(dev->getDeviceId())->setPPM(ppm_in);
config.save();
}

int CubicSDR::getPPM() {
if (sdrThread->getDeviceId() < 0) {
return 0;
}
SDRDeviceInfo *dev = (*getDevices())[getDevice()];

SDRThreadCommand command_ppm(SDRThreadCommand::SDR_THREAD_CMD_SET_PPM);
ppm = config.getDevice(dev->getDeviceId())->getPPM();

return ppm;
}

9 changes: 9 additions & 0 deletions src/CubicSDR.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "SDRPostThread.h"
#include "AudioThread.h"
#include "DemodulatorMgr.h"
#include "AppConfig.h"

#define NUM_DEMODULATORS 1

Expand Down Expand Up @@ -49,14 +50,22 @@ class CubicSDR: public wxApp {
void bindDemodulator(DemodulatorInstance *demod);
void removeDemodulator(DemodulatorInstance *demod);

AppConfig *getConfig();
void saveConfig();

void setPPM(int ppm_in);
int getPPM();

private:
AppConfig config;
PrimaryGLContext *m_glContext;
std::vector<SDRDeviceInfo *> devs;

DemodulatorMgr demodMgr;

long long frequency;
long long offset;
int ppm;
long long sampleRate;

SDRThread *sdrThread;
Expand Down
11 changes: 11 additions & 0 deletions src/demod/DemodulatorInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ void DemodulatorInstance::setActive(bool state) {
} else if (!active && state) {
audioThread->setActive(state);
}
if (!state) {
tracking = false;
}
active = state;
}

Expand Down Expand Up @@ -343,3 +346,11 @@ bool DemodulatorInstance::isFollow() {
void DemodulatorInstance::setFollow(bool follow) {
this->follow = follow;
}

bool DemodulatorInstance::isTracking() {
return tracking;
}

void DemodulatorInstance::setTracking(bool tracking) {
this->tracking = tracking;
}
Loading

0 comments on commit bad45a7

Please sign in to comment.