Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Identify Chirp Spread Spectrum Signals #1317

Open
alphapats opened this issue Oct 31, 2023 · 2 comments
Open

Identify Chirp Spread Spectrum Signals #1317

alphapats opened this issue Oct 31, 2023 · 2 comments
Labels

Comments

@alphapats
Copy link

I want to modify the code of gqrx to automatically identify the peaks of LoRAWAN (Chirp Spread Signals) in the spectrum. Presently I am able to identify only peaks of NB sigs and same code is identifying multiple peaks for same LoRAWAN signal. Can someone help me with the relevant sections of code where I can carryout these modifications?

@argilo
Copy link
Member

argilo commented Oct 31, 2023

If you'd like to experiment with the peak detection algorithm, you can find the code in plotter.cpp:

gqrx/src/qtgui/plotter.cpp

Lines 1638 to 1738 in 848acef

// Peak detection
if (m_PeakDetectActive)
{
const int pw = PEAK_WINDOW_HALF_WIDTH;
// Use data source appropriate for current display mode
float *_detectSource;
if (m_MaxHoldActive)
_detectSource = m_fftMaxHoldBuf;
else if (m_PlotMode == PLOT_MODE_AVG)
_detectSource = m_fftAvgBuf;
else
_detectSource = m_fftMaxBuf;
const float *detectSource = _detectSource;
// Run peak detection periodically. If overlay will be redrawn, run
// peak detection since zoom/pan may have changed.
if (tnow_ms > tlast_peaks_ms + PEAK_UPDATE_PERIOD || m_DrawOverlay) {
tlast_peaks_ms = tnow_ms;
m_Peaks.clear();
// Narrow peaks
for (i = pw; i < npts - pw; ++i) {
const int ix = i + xmin;
const float vi = detectSource[ix];
float sumV = 0;
float minV = vi;
float maxV = 0;
for (j = -pw; j <= pw; ++j) {
const float vj = detectSource[ix + j];
minV = std::min(minV, vj);
maxV = std::max(maxV, vj);
sumV += vj;
}
const float avgV = sumV / (float)(pw * 2 + 1);
m_peakSmoothBuf[ix] = avgV;
if (vi == maxV && (vi > 2.0f * avgV) && (vi > 4.0f * minV))
{
const qreal y = (qreal)std::max(std::min(
panddBGainFactor * (m_PandMaxdB - 10.0f * log10f(vi)),
(float)plotHeight - 0.0f), 0.0f);
m_Peaks[ix] = y;
}
}
// Use the smoothed curve to find wider peaks
const int pw2 = pw * 5;
for (i = pw2; i < npts - pw2; ++i) {
const int ix = i + xmin;
const float vi = m_peakSmoothBuf[ix];
float sumV = 0;
float minV = vi;
float maxV = 0;
for (j = -pw2; j <= pw2; ++j) {
const float vj = m_peakSmoothBuf[ix + j];
minV = std::min(minV, vj);
maxV = std::max(maxV, vj);
sumV += vj;
}
const float avgV = sumV / (float)(pw2 * 2);
if (vi == maxV && (vi > 2.0f * avgV) && (vi > 4.0f * minV))
{
const qreal y = (qreal)std::max(std::min(
panddBGainFactor * (m_PandMaxdB - 10.0f * log10f(vi)),
(float)plotHeight - 0.0f), 0.0f);
// Show the wider peak only if there is no very close narrow peak
bool found = false;
for (j = -pw; j <= pw; ++j) {
auto it = m_Peaks.find(ix + j);
if (it != m_Peaks.end()) {
found = true;
break;
}
}
if (!found) {
m_Peaks[ix] = y;
}
}
}
}
// Paint peaks with shadow
QPen peakPen(m_maxFftColor, m_DPR);
QPen peakShadowPen(Qt::black, m_DPR);
peakPen.setWidthF(m_DPR);
for(auto peakx : m_Peaks.keys()) {
const qreal peakxPlot = (qreal)peakx;
const qreal peakv = m_Peaks.value(peakx);
painter2.setPen(peakShadowPen);
painter2.drawEllipse(
QRectF(peakxPlot - 5.0 * m_DPR + shadowOffset,
peakv - 5.0 * m_DPR + shadowOffset,
10.0 * m_DPR, 10.0 * m_DPR));
painter2.setPen(peakPen);
painter2.drawEllipse(
QRectF(peakxPlot - 5.0 * m_DPR,
peakv - 5.0 * m_DPR,
10.0 * m_DPR, 10.0 * m_DPR));
}
}

@argilo argilo added the feature label Oct 31, 2023
@alphapats
Copy link
Author

Thanks, will try that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants