mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-02-02 21:04:45 +01:00
New alpha version
This commit is contained in:
parent
a7a0be1b83
commit
94074bea98
@ -6,6 +6,9 @@ set(CMAKE_BUILD_TYPE "RelWithDebInfo")
|
|||||||
# Compiler config
|
# Compiler config
|
||||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||||
|
|
||||||
|
# PothosSDR
|
||||||
|
link_directories(sdrpp "C:/Program Files/PothosSDR/lib/")
|
||||||
|
|
||||||
# Volk
|
# Volk
|
||||||
include_directories(sdrpp "C:/Program Files/PothosSDR/include/volk/")
|
include_directories(sdrpp "C:/Program Files/PothosSDR/include/volk/")
|
||||||
link_libraries(volk)
|
link_libraries(volk)
|
||||||
|
14
readme.md
14
readme.md
@ -20,7 +20,19 @@ SDR++ is a cross-platform and open source SDR software with the aim of being blo
|
|||||||
* Recording
|
* Recording
|
||||||
* Light theme (I know you weirdos exist lol)
|
* Light theme (I know you weirdos exist lol)
|
||||||
* Waterfall color scheme editor
|
* Waterfall color scheme editor
|
||||||
*
|
* Switchable fft size
|
||||||
|
* Bias-T enable/disable
|
||||||
|
* other small customisation options
|
||||||
|
* Save waterfall and demod settings between sessions
|
||||||
|
* "Hide sidebar" option
|
||||||
|
|
||||||
|
## Known issues (please check before reporting)
|
||||||
|
* Random crashes (yikes)
|
||||||
|
* Gains aren't stepped
|
||||||
|
* The default gains might contain a bogus value before being adjusted
|
||||||
|
* Clicks in the audio
|
||||||
|
* In some cases, it takes a long time to select a device (RTL-SDR in perticular)
|
||||||
|
* Min and Max buttons can get unachievable values (eg. min > max or min = max);
|
||||||
|
|
||||||
# Building on Windows
|
# Building on Windows
|
||||||
## Requirements
|
## Requirements
|
||||||
|
@ -196,9 +196,9 @@ namespace dsp {
|
|||||||
max = outBuf[i];
|
max = outBuf[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
amp = (max - min);
|
amp = (max - min) / 2.0f;
|
||||||
for (int i = 0; i < _this->_blockSize; i++) {
|
for (int i = 0; i < _this->_blockSize; i++) {
|
||||||
outBuf[i] = (outBuf[i] - min) / (max - min);
|
outBuf[i] = (outBuf[i] - min - amp) / amp;
|
||||||
}
|
}
|
||||||
if (_this->output.write(outBuf, _this->_blockSize) < 0) { break; };
|
if (_this->output.write(outBuf, _this->_blockSize) < 0) { break; };
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ namespace io {
|
|||||||
public:
|
public:
|
||||||
SoapyWrapper() {
|
SoapyWrapper() {
|
||||||
output.init(64000);
|
output.init(64000);
|
||||||
|
currentGains = new float[1];
|
||||||
refresh();
|
refresh();
|
||||||
setDevice(devList[0]);
|
setDevice(devList[0]);
|
||||||
}
|
}
|
||||||
@ -60,6 +61,18 @@ namespace io {
|
|||||||
txtSampleRateList += std::to_string((int)sampleRates[i]);
|
txtSampleRateList += std::to_string((int)sampleRates[i]);
|
||||||
txtSampleRateList += '\0';
|
txtSampleRateList += '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gainList = dev->listGains(SOAPY_SDR_RX, 0);
|
||||||
|
gainRanges.clear();
|
||||||
|
if (gainList.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delete[] currentGains;
|
||||||
|
currentGains = new float[gainList.size()];
|
||||||
|
for (int i = 0; i < gainList.size(); i++) {
|
||||||
|
gainRanges.push_back(dev->getGainRange(SOAPY_SDR_RX, 0, gainList[i]));
|
||||||
|
currentGains[i] = dev->getGain(SOAPY_SDR_RX, 0, gainList[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSampleRate(float sampleRate) {
|
void setSampleRate(float sampleRate) {
|
||||||
@ -74,6 +87,11 @@ namespace io {
|
|||||||
dev->setFrequency(SOAPY_SDR_RX, 0, freq);
|
dev->setFrequency(SOAPY_SDR_RX, 0, freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setGain(int gainId, float gain) {
|
||||||
|
currentGains[gainId] = gain;
|
||||||
|
dev->setGain(SOAPY_SDR_RX, 0, gainList[gainId], gain);
|
||||||
|
}
|
||||||
|
|
||||||
bool isRunning() {
|
bool isRunning() {
|
||||||
return running;
|
return running;
|
||||||
}
|
}
|
||||||
@ -83,6 +101,10 @@ namespace io {
|
|||||||
std::vector<double> sampleRates;
|
std::vector<double> sampleRates;
|
||||||
std::string txtSampleRateList;
|
std::string txtSampleRateList;
|
||||||
|
|
||||||
|
std::vector<std::string> gainList;
|
||||||
|
std::vector<SoapySDR::Range> gainRanges;
|
||||||
|
float* currentGains;
|
||||||
|
|
||||||
dsp::stream<dsp::complex_t> output;
|
dsp::stream<dsp::complex_t> output;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -21,6 +21,8 @@ FrequencySelect fSel;
|
|||||||
fftwf_complex *fft_in, *fft_out;
|
fftwf_complex *fft_in, *fft_out;
|
||||||
fftwf_plan p;
|
fftwf_plan p;
|
||||||
float* tempData;
|
float* tempData;
|
||||||
|
float* uiGains;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
int fftSize = 8192 * 8;
|
int fftSize = 8192 * 8;
|
||||||
|
|
||||||
@ -66,6 +68,8 @@ void windowInit() {
|
|||||||
|
|
||||||
sigPath.init(sampleRate, 20, fftSize, &soapy.output, (dsp::complex_t*)fft_in, fftHandler);
|
sigPath.init(sampleRate, 20, fftSize, &soapy.output, (dsp::complex_t*)fft_in, fftHandler);
|
||||||
sigPath.start();
|
sigPath.start();
|
||||||
|
|
||||||
|
uiGains = new float[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int devId = 0;
|
int devId = 0;
|
||||||
@ -79,7 +83,7 @@ bool showExample = false;
|
|||||||
long freq = 90500000;
|
long freq = 90500000;
|
||||||
long _freq = 90500000;
|
long _freq = 90500000;
|
||||||
|
|
||||||
int demod = 0;
|
int demod = 1;
|
||||||
|
|
||||||
bool state = false;
|
bool state = false;
|
||||||
bool mulstate = true;
|
bool mulstate = true;
|
||||||
@ -220,6 +224,17 @@ void drawWindow() {
|
|||||||
if (devId != _devId) {
|
if (devId != _devId) {
|
||||||
_devId = devId;
|
_devId = devId;
|
||||||
soapy.setDevice(soapy.devList[devId]);
|
soapy.setDevice(soapy.devList[devId]);
|
||||||
|
srId = 0;
|
||||||
|
_srId = -1;
|
||||||
|
soapy.setSampleRate(soapy.sampleRates[0]);
|
||||||
|
if (soapy.gainList.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delete[] uiGains;
|
||||||
|
uiGains = new float[soapy.gainList.size()];
|
||||||
|
for (int i = 0; i < soapy.gainList.size(); i++) {
|
||||||
|
uiGains[i] = soapy.currentGains[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srId != _srId) {
|
if (srId != _srId) {
|
||||||
@ -269,11 +284,6 @@ void drawWindow() {
|
|||||||
|
|
||||||
fSel.draw();
|
fSel.draw();
|
||||||
|
|
||||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 8);
|
|
||||||
ImGui::SameLine(ImGui::GetWindowWidth() - 40);
|
|
||||||
ImGui::Image(icons::LOGO, ImVec2(30, 30));
|
|
||||||
|
|
||||||
|
|
||||||
ImGui::Columns(3, "WindowColumns", false);
|
ImGui::Columns(3, "WindowColumns", false);
|
||||||
ImVec2 winSize = ImGui::GetWindowSize();
|
ImVec2 winSize = ImGui::GetWindowSize();
|
||||||
ImGui::SetColumnWidth(0, 300);
|
ImGui::SetColumnWidth(0, 300);
|
||||||
@ -287,6 +297,7 @@ void drawWindow() {
|
|||||||
ImGui::PushItemWidth(ImGui::GetWindowSize().x);
|
ImGui::PushItemWidth(ImGui::GetWindowSize().x);
|
||||||
ImGui::Combo("##_0_", &devId, soapy.txtDevList.c_str());
|
ImGui::Combo("##_0_", &devId, soapy.txtDevList.c_str());
|
||||||
|
|
||||||
|
ImGui::PopItemWidth();
|
||||||
if (!playing) {
|
if (!playing) {
|
||||||
ImGui::Combo("##_1_", &srId, soapy.txtSampleRateList.c_str());
|
ImGui::Combo("##_1_", &srId, soapy.txtSampleRateList.c_str());
|
||||||
}
|
}
|
||||||
@ -294,10 +305,26 @@ void drawWindow() {
|
|||||||
ImGui::Text("%s Samples/s", soapy.txtSampleRateList.c_str());
|
ImGui::Text("%s Samples/s", soapy.txtSampleRateList.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Refresh")) {
|
if (ImGui::Button("Refresh")) {
|
||||||
soapy.refresh();
|
soapy.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < soapy.gainList.size(); i++) {
|
||||||
|
ImGui::Text("%s gain", soapy.gainList[i].c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
|
sprintf(buf, "##_gain_slide_%d_", i);
|
||||||
|
ImGui::SliderFloat(buf, &uiGains[i], soapy.gainRanges[i].minimum(), soapy.gainRanges[i].maximum());
|
||||||
|
|
||||||
|
// float step = soapy.gainRanges[i].step();
|
||||||
|
// printf("%f\n", step);
|
||||||
|
|
||||||
|
// uiGains[i] = roundf(uiGains[i] / soapy.gainRanges[i].step()) * soapy.gainRanges[i].step();
|
||||||
|
|
||||||
|
if (uiGains[i] != soapy.currentGains[i]) {
|
||||||
|
soapy.setGain(i, uiGains[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Radio")) {
|
if (ImGui::CollapsingHeader("Radio")) {
|
||||||
@ -370,7 +397,7 @@ void drawWindow() {
|
|||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
|
|
||||||
ImGui::Text("Zoom");
|
ImGui::Text("Zoom");
|
||||||
ImGui::VSliderFloat("##_7_", ImVec2(20.0f, 150.0f), &bw, 1000.0f, sampleRate, "");
|
ImGui::VSliderFloat("##_7_", ImVec2(20.0f, 150.0f), &bw, sampleRate, 1000.0f, "");
|
||||||
|
|
||||||
ImGui::NewLine();
|
ImGui::NewLine();
|
||||||
|
|
||||||
|
@ -161,3 +161,7 @@ void SignalPath::start() {
|
|||||||
audioResamp.start();
|
audioResamp.start();
|
||||||
audio.start();
|
audio.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SignalPath::setDCBiasCorrection(bool enabled) {
|
||||||
|
dcBiasRemover.bypass = !enabled;
|
||||||
|
}
|
@ -35,6 +35,7 @@ void doZoom(int offset, int width, int outWidth, std::vector<float> data, float*
|
|||||||
}
|
}
|
||||||
|
|
||||||
float freq_ranges[] = {
|
float freq_ranges[] = {
|
||||||
|
1.0f, 2.0f, 2.5f, 5.0f,
|
||||||
10.0f, 20.0f, 25.0f, 50.0f,
|
10.0f, 20.0f, 25.0f, 50.0f,
|
||||||
100.0f, 200.0f, 250.0f, 500.0f,
|
100.0f, 200.0f, 250.0f, 500.0f,
|
||||||
1000.0f, 2000.0f, 2500.0f, 5000.0f,
|
1000.0f, 2000.0f, 2500.0f, 5000.0f,
|
||||||
@ -44,9 +45,9 @@ float freq_ranges[] = {
|
|||||||
10000000.0f, 20000000.0f, 25000000.0f, 50000000.0f
|
10000000.0f, 20000000.0f, 25000000.0f, 50000000.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
float findBestFreqRange(float bandwidth) {
|
float findBestRange(float bandwidth, int maxSteps) {
|
||||||
for (int i = 0; i < 28; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
if (bandwidth / freq_ranges[i] < 25.0f) {
|
if (bandwidth / freq_ranges[i] < (float)maxSteps) {
|
||||||
return freq_ranges[i];
|
return freq_ranges[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,14 +105,14 @@ namespace ImGui {
|
|||||||
|
|
||||||
void WaterFall::drawFFT() {
|
void WaterFall::drawFFT() {
|
||||||
// Calculate scaling factor
|
// Calculate scaling factor
|
||||||
float startLine = floorf(fftMax / 10.0f) * 10.0f;
|
float startLine = floorf(fftMax / vRange) * vRange;
|
||||||
float vertRange = fftMax - fftMin;
|
float vertRange = fftMax - fftMin;
|
||||||
float scaleFactor = fftHeight / vertRange;
|
float scaleFactor = fftHeight / vertRange;
|
||||||
char buf[100];
|
char buf[100];
|
||||||
|
|
||||||
|
|
||||||
// Vertical scale
|
// Vertical scale
|
||||||
for (float line = startLine; line > fftMin; line -= 10.0f) {
|
for (float line = startLine; line > fftMin; line -= vRange) {
|
||||||
float yPos = widgetPos.y + fftHeight + 10 - ((line - fftMin) * scaleFactor);
|
float yPos = widgetPos.y + fftHeight + 10 - ((line - fftMin) * scaleFactor);
|
||||||
window->DrawList->AddLine(ImVec2(widgetPos.x + 50, roundf(yPos)),
|
window->DrawList->AddLine(ImVec2(widgetPos.x + 50, roundf(yPos)),
|
||||||
ImVec2(widgetPos.x + dataWidth + 50, roundf(yPos)),
|
ImVec2(widgetPos.x + dataWidth + 50, roundf(yPos)),
|
||||||
@ -177,7 +178,7 @@ namespace ImGui {
|
|||||||
|
|
||||||
void WaterFall::drawVFO() {
|
void WaterFall::drawVFO() {
|
||||||
float width = (vfoBandwidth / viewBandwidth) * (float)dataWidth;
|
float width = (vfoBandwidth / viewBandwidth) * (float)dataWidth;
|
||||||
int center = (((vfoOffset - viewOffset) / (viewBandwidth / 2.0f)) + 1.0f) * ((float)dataWidth / 2.0f);
|
int center = roundf((((vfoOffset - viewOffset) / (viewBandwidth / 2.0f)) + 1.0f) * ((float)dataWidth / 2.0f));
|
||||||
int left;
|
int left;
|
||||||
int right;
|
int right;
|
||||||
|
|
||||||
@ -316,6 +317,13 @@ namespace ImGui {
|
|||||||
freqAreaMin = ImVec2(widgetPos.x + 50, widgetPos.y + fftHeight + 11);
|
freqAreaMin = ImVec2(widgetPos.x + 50, widgetPos.y + fftHeight + 11);
|
||||||
freqAreaMax = ImVec2(widgetPos.x + dataWidth + 50, widgetPos.y + fftHeight + 50);
|
freqAreaMax = ImVec2(widgetPos.x + dataWidth + 50, widgetPos.y + fftHeight + 50);
|
||||||
|
|
||||||
|
maxHSteps = dataWidth / 50;
|
||||||
|
maxVSteps = fftHeight / 15;
|
||||||
|
|
||||||
|
range = findBestRange(viewBandwidth, maxHSteps);
|
||||||
|
vRange = findBestRange(fftMax - fftMin, maxVSteps);
|
||||||
|
vRange = 10.0f;
|
||||||
|
|
||||||
printf("Resized: %d %d\n", dataWidth, waterfallHeight);
|
printf("Resized: %d %d\n", dataWidth, waterfallHeight);
|
||||||
|
|
||||||
updateWaterfallFb();
|
updateWaterfallFb();
|
||||||
@ -461,7 +469,7 @@ namespace ImGui {
|
|||||||
viewBandwidth = bandWidth;
|
viewBandwidth = bandWidth;
|
||||||
lowerFreq = (centerFreq + viewOffset) - (viewBandwidth / 2.0f);
|
lowerFreq = (centerFreq + viewOffset) - (viewBandwidth / 2.0f);
|
||||||
upperFreq = (centerFreq + viewOffset) + (viewBandwidth / 2.0f);
|
upperFreq = (centerFreq + viewOffset) + (viewBandwidth / 2.0f);
|
||||||
range = findBestFreqRange(bandWidth);
|
range = findBestRange(bandWidth, maxHSteps);
|
||||||
updateWaterfallFb();
|
updateWaterfallFb();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,6 +499,7 @@ namespace ImGui {
|
|||||||
|
|
||||||
void WaterFall::setFFTMin(float min) {
|
void WaterFall::setFFTMin(float min) {
|
||||||
fftMin = min;
|
fftMin = min;
|
||||||
|
vRange = findBestRange(fftMax - fftMin, maxVSteps);
|
||||||
}
|
}
|
||||||
|
|
||||||
float WaterFall::getFFTMin() {
|
float WaterFall::getFFTMin() {
|
||||||
@ -499,6 +508,7 @@ namespace ImGui {
|
|||||||
|
|
||||||
void WaterFall::setFFTMax(float max) {
|
void WaterFall::setFFTMax(float max) {
|
||||||
fftMax = max;
|
fftMax = max;
|
||||||
|
vRange = findBestRange(fftMax - fftMin, maxVSteps);
|
||||||
}
|
}
|
||||||
|
|
||||||
float WaterFall::getFFTMax() {
|
float WaterFall::getFFTMax() {
|
||||||
|
@ -100,6 +100,11 @@ namespace ImGui {
|
|||||||
|
|
||||||
std::mutex buf_mtx;
|
std::mutex buf_mtx;
|
||||||
|
|
||||||
|
float vRange;
|
||||||
|
|
||||||
|
int maxVSteps;
|
||||||
|
int maxHSteps;
|
||||||
|
|
||||||
int dataWidth; // Width of the FFT and waterfall
|
int dataWidth; // Width of the FFT and waterfall
|
||||||
int fftHeight; // Height of the fft graph
|
int fftHeight; // Height of the fft graph
|
||||||
int waterfallHeight; // Height of the waterfall
|
int waterfallHeight; // Height of the waterfall
|
||||||
|
Loading…
x
Reference in New Issue
Block a user