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

@ -129,33 +129,36 @@ AppFrame::AppFrame() :
// Make a menubar
wxMenuBar *menuBar = new wxMenuBar;
wxMenu *menu = new wxMenu;
menu->Append(wxID_SET_FREQ_OFFSET, "Set Frequency Offset");
menu->Append(wxID_SET_PPM, "Set Device PPM");
wxMenu *dsMenu = new wxMenu;
menu->Append(wxID_OPEN, "&Open Session");
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;
dsMenu->AppendRadioItem(wxID_SET_DS_OFF, "Off");
dsMenu->AppendRadioItem(wxID_SET_DS_I, "I-ADC");
dsMenu->AppendRadioItem(wxID_SET_DS_Q, "Q-ADC");
menu->AppendSubMenu(dsMenu, "Direct Sampling");
wxMenu *sessionMenu = new wxMenu;
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(dsMenu, "Direct Sampling");
menu->AppendSubMenu(sessionMenu, "Session");
menuBar->Append(menu, wxT("&Settings"));
menu->AppendSeparator();
menu->Append(wxID_CLOSE);
menuBar->Append(menu, wxT("&File"));
menu = new wxMenu;
std::vector<RtAudio::DeviceInfo>::iterator devices_i;
@ -183,7 +186,7 @@ AppFrame::AppFrame() :
outputDeviceMenuItems[mdevices_i->first] = itm;
}
menuBar->Append(menu, wxT("Active Demodulator &Output"));
menuBar->Append(menu, wxT("Audio &Output"));
menu = new wxMenu;
@ -340,6 +343,10 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
wxGetApp().setDirectSampling(1);
} else if (event.GetId() == wxID_SET_DS_Q) {
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) {
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);

View File

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

View File

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

View File

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

View File

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

View File

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