Adds feature to Swap I/Q

This commit is contained in:
Charles J. Cliffe 2015-05-31 22:13:14 -04:00
parent 3efb036099
commit 8496287455
6 changed files with 72 additions and 31 deletions

View File

@ -130,8 +130,24 @@ AppFrame::AppFrame() :
wxMenuBar *menuBar = new wxMenuBar; wxMenuBar *menuBar = new wxMenuBar;
wxMenu *menu = new wxMenu; wxMenu *menu = new wxMenu;
menu->Append(wxID_SET_FREQ_OFFSET, "Set Frequency Offset"); menu->Append(wxID_OPEN, "&Open Session");
menu->Append(wxID_SET_PPM, "Set Device PPM"); menu->Append(wxID_SAVE, "&Save Session");
menu->Append(wxID_SAVEAS, "Save Session &As..");
menu->AppendSeparator();
menu->Append(wxID_RESET, "&Reset Session");
#ifndef __APPLE__
menu->AppendSeparator();
menu->Append(wxID_CLOSE);
#endif
menuBar->Append(menu, wxT("&File"));
menu = new wxMenu;
menu->Append(wxID_SET_FREQ_OFFSET, "Frequency Offset");
menu->Append(wxID_SET_PPM, "Device PPM");
iqSwapMenuItem = menu->AppendCheckItem(wxID_SET_SWAP_IQ, "Swap I/Q");
wxMenu *dsMenu = new wxMenu; wxMenu *dsMenu = new wxMenu;
@ -141,20 +157,7 @@ AppFrame::AppFrame() :
menu->AppendSubMenu(dsMenu, "Direct Sampling"); menu->AppendSubMenu(dsMenu, "Direct Sampling");
wxMenu *sessionMenu = new wxMenu; menuBar->Append(menu, wxT("&Settings"));
sessionMenu->Append(wxID_OPEN, "&Open Session");
sessionMenu->Append(wxID_SAVE, "&Save Session");
sessionMenu->Append(wxID_SAVEAS, "Save Session &As..");
sessionMenu->AppendSeparator();
sessionMenu->Append(wxID_RESET, "&Reset Session");
menu->AppendSubMenu(sessionMenu, "Session");
menu->AppendSeparator();
menu->Append(wxID_CLOSE);
menuBar->Append(menu, wxT("&File"));
menu = new wxMenu; menu = new wxMenu;
@ -183,7 +186,7 @@ AppFrame::AppFrame() :
outputDeviceMenuItems[mdevices_i->first] = itm; outputDeviceMenuItems[mdevices_i->first] = itm;
} }
menuBar->Append(menu, wxT("Active Demodulator &Output")); menuBar->Append(menu, wxT("Audio &Output"));
menu = new wxMenu; menu = new wxMenu;
@ -340,6 +343,10 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
wxGetApp().setDirectSampling(1); wxGetApp().setDirectSampling(1);
} else if (event.GetId() == wxID_SET_DS_Q) { } else if (event.GetId() == wxID_SET_DS_Q) {
wxGetApp().setDirectSampling(2); wxGetApp().setDirectSampling(2);
} else if (event.GetId() == wxID_SET_SWAP_IQ) {
bool swap_state = !wxGetApp().getSwapIQ();
wxGetApp().setSwapIQ(swap_state);
iqSwapMenuItem->Check(swap_state);
} else if (event.GetId() == wxID_SET_PPM) { } 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)", 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); "Frequency Correction", wxGetApp().getPPM(), -1000, 1000, this);

View File

@ -19,6 +19,7 @@
#define wxID_SET_DS_OFF 2004 #define wxID_SET_DS_OFF 2004
#define wxID_SET_DS_I 2005 #define wxID_SET_DS_I 2005
#define wxID_SET_DS_Q 2006 #define wxID_SET_DS_Q 2006
#define wxID_SET_SWAP_IQ 2007
#define wxID_THEME_DEFAULT 2100 #define wxID_THEME_DEFAULT 2100
#define wxID_THEME_SHARP 2101 #define wxID_THEME_SHARP 2101
@ -78,6 +79,7 @@ private:
std::map<int, wxMenuItem *> outputDeviceMenuItems; std::map<int, wxMenuItem *> outputDeviceMenuItems;
std::map<int, wxMenuItem *> sampleRateMenuItems; std::map<int, wxMenuItem *> sampleRateMenuItems;
std::map<int, wxMenuItem *> audioSampleRateMenuItems; std::map<int, wxMenuItem *> audioSampleRateMenuItems;
wxMenuItem *iqSwapMenuItem;
std::string currentSessionFile; std::string currentSessionFile;

View File

@ -182,6 +182,14 @@ int CubicSDR::getDirectSampling() {
return directSamplingMode; return directSamplingMode;
} }
void CubicSDR::setSwapIQ(bool swapIQ) {
sdrPostThread->setSwapIQ(swapIQ);
}
bool CubicSDR::getSwapIQ() {
return sdrPostThread->getSwapIQ();
}
long long CubicSDR::getFrequency() { long long CubicSDR::getFrequency() {
return frequency; return frequency;
} }

View File

@ -40,6 +40,9 @@ public:
void setDirectSampling(int mode); void setDirectSampling(int mode);
int getDirectSampling(); int getDirectSampling();
void setSwapIQ(bool swapIQ);
bool getSwapIQ();
void setSampleRate(long long rate_in); void setSampleRate(long long rate_in);
long long getSampleRate(); long long getSampleRate();

View File

@ -6,19 +6,21 @@
#include <deque> #include <deque>
SDRPostThread::SDRPostThread() : SDRPostThread::SDRPostThread() :
iqDataOutQueue(NULL), iqDataInQueue(NULL), iqVisualQueue(NULL), terminated(false), dcFilter(NULL), num_vis_samples(16384*2) { iqDataInQueue(NULL), iqDataOutQueue(NULL), iqVisualQueue(NULL), terminated(false), dcFilter(NULL), num_vis_samples(16384*2), swapIQ(false) {
// create a lookup table // create a lookup table
for (unsigned int i = 0; i <= 0xffff; i++) { for (unsigned int i = 0; i <= 0xffff; i++) {
liquid_float_complex tmp; liquid_float_complex tmp,tmp_swap;
# if (__BYTE_ORDER == __LITTLE_ENDIAN) # if (__BYTE_ORDER == __LITTLE_ENDIAN)
tmp.real = (float(i & 0xff) - 127.4f) * (1.0f/128.0f); tmp_swap.imag = tmp.real = (float(i & 0xff) - 127.4f) * (1.0f/128.0f);
tmp.imag = (float(i >> 8) - 127.4f) * (1.0f/128.0f); tmp_swap.real = tmp.imag = (float(i >> 8) - 127.4f) * (1.0f/128.0f);
_lut.push_back(tmp); _lut.push_back(tmp);
_lut_swap.push_back(tmp_swap);
#else // BIG_ENDIAN #else // BIG_ENDIAN
tmp.real = (float(i >> 8) - 127.4f) * (1.0f/128.0f); tmp_swap.imag = tmp.real = (float(i >> 8) - 127.4f) * (1.0f/128.0f);
tmp.imag = (float(i & 0xff) - 127.4f) * (1.0f/128.0f); tmp_swap.real = tmp.imag = (float(i & 0xff) - 127.4f) * (1.0f/128.0f);
_lut.push_back(tmp); _lut.push_back(tmp);
_lut_swap.push_back(tmp_swap);
#endif #endif
} }
} }
@ -64,6 +66,14 @@ int SDRPostThread::getNumVisSamples() {
return num_vis_samples; return num_vis_samples;
} }
void SDRPostThread::setSwapIQ(bool swapIQ) {
this->swapIQ.store(swapIQ);
}
bool SDRPostThread::getSwapIQ() {
return this->swapIQ.load();
}
void SDRPostThread::threadMain() { void SDRPostThread::threadMain() {
int n_read; int n_read;
double seconds = 0.0; double seconds = 0.0;
@ -103,9 +113,15 @@ void SDRPostThread::threadMain() {
dataOut.resize(dataSize); dataOut.resize(dataSize);
} }
for (int i = 0, iMax = dataSize; i < iMax; i++) { if (swapIQ) {
for (int i = 0; i < dataSize; i++) {
fpData[i] = _lut_swap[*((uint16_t*)&data_in->data[2*i])];
}
} else {
for (int i = 0; i < dataSize; i++) {
fpData[i] = _lut[*((uint16_t*)&data_in->data[2*i])]; fpData[i] = _lut[*((uint16_t*)&data_in->data[2*i])];
} }
}
iirfilt_crcf_execute_block(dcFilter, &fpData[0], dataSize, &dataOut[0]); iirfilt_crcf_execute_block(dcFilter, &fpData[0], dataSize, &dataOut[0]);

View File

@ -18,6 +18,9 @@ public:
void setNumVisSamples(int num_vis_samples_in); void setNumVisSamples(int num_vis_samples_in);
int getNumVisSamples(); int getNumVisSamples();
void setSwapIQ(bool swapIQ);
bool getSwapIQ();
void threadMain(); void threadMain();
void terminate(); void terminate();
@ -31,7 +34,9 @@ protected:
std::atomic<bool> terminated; std::atomic<bool> terminated;
iirfilt_crcf dcFilter; iirfilt_crcf dcFilter;
int num_vis_samples; int num_vis_samples;
std::atomic<bool> swapIQ;
private: private:
std::vector<liquid_float_complex> _lut; std::vector<liquid_float_complex> _lut;
std::vector<liquid_float_complex> _lut_swap;
}; };