New alpha version

This commit is contained in:
Ryzerth 2020-07-19 21:26:37 +02:00
parent a7a0be1b83
commit 94074bea98
8 changed files with 101 additions and 18 deletions

View File

@ -6,6 +6,9 @@ set(CMAKE_BUILD_TYPE "RelWithDebInfo")
# Compiler config
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
# PothosSDR
link_directories(sdrpp "C:/Program Files/PothosSDR/lib/")
# Volk
include_directories(sdrpp "C:/Program Files/PothosSDR/include/volk/")
link_libraries(volk)

View File

@ -20,7 +20,19 @@ SDR++ is a cross-platform and open source SDR software with the aim of being blo
* Recording
* Light theme (I know you weirdos exist lol)
* 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
## Requirements

View File

@ -196,9 +196,9 @@ namespace dsp {
max = outBuf[i];
}
}
amp = (max - min);
amp = (max - min) / 2.0f;
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; };
}

View File

@ -9,6 +9,7 @@ namespace io {
public:
SoapyWrapper() {
output.init(64000);
currentGains = new float[1];
refresh();
setDevice(devList[0]);
}
@ -60,6 +61,18 @@ namespace io {
txtSampleRateList += std::to_string((int)sampleRates[i]);
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) {
@ -74,6 +87,11 @@ namespace io {
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() {
return running;
}
@ -83,6 +101,10 @@ namespace io {
std::vector<double> sampleRates;
std::string txtSampleRateList;
std::vector<std::string> gainList;
std::vector<SoapySDR::Range> gainRanges;
float* currentGains;
dsp::stream<dsp::complex_t> output;
private:

View File

@ -21,6 +21,8 @@ FrequencySelect fSel;
fftwf_complex *fft_in, *fft_out;
fftwf_plan p;
float* tempData;
float* uiGains;
char buf[1024];
int fftSize = 8192 * 8;
@ -66,6 +68,8 @@ void windowInit() {
sigPath.init(sampleRate, 20, fftSize, &soapy.output, (dsp::complex_t*)fft_in, fftHandler);
sigPath.start();
uiGains = new float[1];
}
int devId = 0;
@ -79,7 +83,7 @@ bool showExample = false;
long freq = 90500000;
long _freq = 90500000;
int demod = 0;
int demod = 1;
bool state = false;
bool mulstate = true;
@ -220,6 +224,17 @@ void drawWindow() {
if (devId != _devId) {
_devId = 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) {
@ -269,11 +284,6 @@ void drawWindow() {
fSel.draw();
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 8);
ImGui::SameLine(ImGui::GetWindowWidth() - 40);
ImGui::Image(icons::LOGO, ImVec2(30, 30));
ImGui::Columns(3, "WindowColumns", false);
ImVec2 winSize = ImGui::GetWindowSize();
ImGui::SetColumnWidth(0, 300);
@ -287,17 +297,34 @@ void drawWindow() {
ImGui::PushItemWidth(ImGui::GetWindowSize().x);
ImGui::Combo("##_0_", &devId, soapy.txtDevList.c_str());
ImGui::PopItemWidth();
if (!playing) {
ImGui::Combo("##_1_", &srId, soapy.txtSampleRateList.c_str());
}
else {
ImGui::Text("%s Samples/s", soapy.txtSampleRateList.c_str());
}
ImGui::SameLine();
if (ImGui::Button("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")) {
@ -370,7 +397,7 @@ void drawWindow() {
ImGui::NextColumn();
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();

View File

@ -160,4 +160,8 @@ void SignalPath::start() {
audioResamp.start();
audio.start();
}
void SignalPath::setDCBiasCorrection(bool enabled) {
dcBiasRemover.bypass = !enabled;
}

View File

@ -35,6 +35,7 @@ void doZoom(int offset, int width, int outWidth, std::vector<float> data, float*
}
float freq_ranges[] = {
1.0f, 2.0f, 2.5f, 5.0f,
10.0f, 20.0f, 25.0f, 50.0f,
100.0f, 200.0f, 250.0f, 500.0f,
1000.0f, 2000.0f, 2500.0f, 5000.0f,
@ -44,9 +45,9 @@ float freq_ranges[] = {
10000000.0f, 20000000.0f, 25000000.0f, 50000000.0f
};
float findBestFreqRange(float bandwidth) {
for (int i = 0; i < 28; i++) {
if (bandwidth / freq_ranges[i] < 25.0f) {
float findBestRange(float bandwidth, int maxSteps) {
for (int i = 0; i < 32; i++) {
if (bandwidth / freq_ranges[i] < (float)maxSteps) {
return freq_ranges[i];
}
}
@ -104,14 +105,14 @@ namespace ImGui {
void WaterFall::drawFFT() {
// Calculate scaling factor
float startLine = floorf(fftMax / 10.0f) * 10.0f;
float startLine = floorf(fftMax / vRange) * vRange;
float vertRange = fftMax - fftMin;
float scaleFactor = fftHeight / vertRange;
char buf[100];
// 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);
window->DrawList->AddLine(ImVec2(widgetPos.x + 50, roundf(yPos)),
ImVec2(widgetPos.x + dataWidth + 50, roundf(yPos)),
@ -177,7 +178,7 @@ namespace ImGui {
void WaterFall::drawVFO() {
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 right;
@ -316,6 +317,13 @@ namespace ImGui {
freqAreaMin = ImVec2(widgetPos.x + 50, widgetPos.y + fftHeight + 11);
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);
updateWaterfallFb();
@ -461,7 +469,7 @@ namespace ImGui {
viewBandwidth = bandWidth;
lowerFreq = (centerFreq + viewOffset) - (viewBandwidth / 2.0f);
upperFreq = (centerFreq + viewOffset) + (viewBandwidth / 2.0f);
range = findBestFreqRange(bandWidth);
range = findBestRange(bandWidth, maxHSteps);
updateWaterfallFb();
}
@ -491,6 +499,7 @@ namespace ImGui {
void WaterFall::setFFTMin(float min) {
fftMin = min;
vRange = findBestRange(fftMax - fftMin, maxVSteps);
}
float WaterFall::getFFTMin() {
@ -499,6 +508,7 @@ namespace ImGui {
void WaterFall::setFFTMax(float max) {
fftMax = max;
vRange = findBestRange(fftMax - fftMin, maxVSteps);
}
float WaterFall::getFFTMax() {

View File

@ -100,6 +100,11 @@ namespace ImGui {
std::mutex buf_mtx;
float vRange;
int maxVSteps;
int maxHSteps;
int dataWidth; // Width of the FFT and waterfall
int fftHeight; // Height of the fft graph
int waterfallHeight; // Height of the waterfall