-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsignaldetector.cpp
executable file
·374 lines (320 loc) · 11.3 KB
/
signaldetector.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
#include "signaldetector.h"
#include <time.h>
#include "math.h"
#include <iostream>
//#include <utils.h>
using std::cout;
static int idgen = 0;
/*
Now, there's a few techniques we can use here to detect signals.
Narrow band signals can be somewhat easily detected by looking for energy peaks - peakdetector
each one of these peaks can be visited to walk fro mthe center outward in bins of the fft
we can detect bandwidth this way for nice, peaked signals pretty easily.
The local noise floor of surrounding the peak of the singal to the upper /lower freqs provide
a basis to detect peaks using the sum of square and standard deviation of the local area
if there are too many local signals, the noise floor may be distorted to be a higher level.
This would be reflected through in the max standard devation. This might be use to detect when to change
the detection approach from local noise floor to absolute noise floor.
Maybe the abs noise floor can be mixed with a ration to determine proper local noise floor
We should use a different method for detecting wide band signals. We can walk the fft bins from left to right -
low to high, and see when the signal triggers the noise floor and thresholds
Process:
-IQ to fft
-Peak detection on fft bins
For each Detection:
detect narrow band signal from walking sides to abs or wide noise floor
Use FFT Bin map to mark off sections
Detect wide signals first and add to map
detect narrow signals
Try to re-detect or re-identify signals previously seen and update count and last seen.
look for signals that appear periodiacally,
age off old signals
We're looking for signals in the X->Y Frequency plane just as much as we're looking for signals progressing through the Y Time plane
*/
void *SignalDetectorProcessThread(void *dat);
SignalDescriptorEntry::SignalDescriptorEntry()
{
lastseen = clock();
count = 1;
threshhigh = -150;
threshlow = 0;
classcount = 0; // how man times has this been classified / verified
classified = false; // hjas this been classified
extractedcount = 0;
}
void SignalDescriptorEntry::Dump()
{
cout << "ID:" << identifier << " CF:" << centerfreqHz << " BW:" << bwHz << "\r\n";
}
void SignalDescriptorEntry::Merge(SignalDescriptorEntry *sde)
{
}
//SignalDetector::SignalDetector(QObject *parent) :
// QObject(parent)
SignalDetector::SignalDetector(int binsize)
{
m_maplen = 0;
m_binsize = binsize;
pfft = nullptr;
m_map = new char[m_binsize];
m_sdemap = new SignalDescriptorEntry*[m_binsize];
for(int c =0; c < m_binsize; c++)
m_sdemap[c] = nullptr;
}
/*
This function is for detecting chnages in the bandwidth or center frequency
*/
void SignalDetector::DetectChange()
{
if(m_curCF != pfft->GetCenterFreqHz() || m_curBW != pfft->GetBWHz()) //for detecting changes in the cf or bw
{
//reset detection map
m_curCF = pfft->GetCenterFreqHz();
m_curBW = pfft->GetBWHz();
m_entries.clear(); // remove previous entries
}
}
/*
We should have multiple levels of signal detection
The first level takes a look at the instantaneous results in the peak detect, and converts them somewhat blindly into potential
signals (PotentialSignalList)
*/
void SignalDetector::Update(float peaksensistivity)
{
DetectChange();
pfft->Lock();
InitMap(); // initialize the fft map;
//walk the frequencies from low to high
SignalDescriptorEntry *sd;
int cntridx;
float cntrfreqHz;
// float stddev[pfft->GetBinSize()];
pfft->CalcNoiseFloor(0);
float *localnoisefloor = pfft->GetNoiseFloor();
// iterate through all the detected peaks
QMap<int,float> peaks = pfft->DetectPeaks(peaksensistivity);
for(QMap<int,float>::iterator it = peaks.begin(); it != peaks.end(); ++it)
{
cntridx = it.key(); // the the center bin index
cntrfreqHz = pfft->GetFreqHz(cntridx); // get the frequency at that bin
sd = new SignalDescriptorEntry();
sd->centerfreqHz = cntrfreqHz;//
//starting at the center frequency, walk the index to the left / right to determine bandwidth
//should we impose a max BW, or just 'let it happen'?
// we should figure out the RBW
// this gets into the question about how wide can our engery detector reliably work.
bool done = false;
bool valid = true;
int leftidx = cntridx;
int rightidx = cntridx;
float curdbm;
float sf,ef,sb,eb,tf;
float rbw = pfft->GetRBWHz();// get resolution bandwidth
sd->localnoisefloor = localnoisefloor[cntridx];
// get the power at the center
float centerdbm = pfft->AvgData()[cntridx];
// find the range of the signal based on the local noise floor
float dbmrange = centerdbm - localnoisefloor[cntridx];
float lowthreshold = ((dbmrange / 3) + localnoisefloor[cntridx]);
// walk the index to the left (lower freq) until we pass the threshold
while(!done)
{
curdbm = pfft->AvgData()[leftidx]; // get the value
// printf("Current Left DBm %f at idx %d\r\n",curdbm,leftidx);
if(curdbm < lowthreshold)
{
done = true;
sd->startf = pfft->GetFreqHz(leftidx);
// printf("Found New Left IDX : %d, freq: %f\r\n",leftidx,sd->startf);
// interpolate the frequency
sf = pfft->GetFreqHz(leftidx);
ef = pfft->GetFreqHz(leftidx + 1);
sb = pfft->AvgData()[leftidx];
eb = pfft->AvgData()[leftidx + 1];
tf = sf + (ef - sf) * ((lowthreshold - sb)/(eb-sb));
// printf("Interpolated Left Freq = %f\r\n",tf);
sd->startf = tf;
}else
{
leftidx--; // move to the left
if(leftidx <= 0)
{
//cut off...
// printf("!!!!!!!!!Left Cut OFF\r\n");
done = true;
valid = false;
}
}
}
done = false;
while(!done)
{
curdbm = pfft->AvgData()[rightidx]; // get the value
if(curdbm < lowthreshold)
{
done = true;
//sd->endf = pfft->GetFreqHz(rightidx);
// printf("Found New Right IDX : %d, Freq = %f \r\n",rightidx,sd->endf);
sf = pfft->GetFreqHz(rightidx - 1);
ef = pfft->GetFreqHz(rightidx);
sb = pfft->AvgData()[rightidx - 1];
eb = pfft->AvgData()[rightidx];
tf = sf + (ef - sf) * ((lowthreshold - sb)/(eb-sb));
// printf("Interpolated Right Freq = %f\r\n",tf);
sd->endf = tf;
}else
{
rightidx++; // move to the right
if(rightidx >= pfft->GetBinSize() - 1)
{
done = true;
// printf("!!!!!!!!!Right Cut OFF\r\n");
valid = false;
}
}
}
sd->bwHz = sd->endf - sd->startf;
if(sd->bwHz < MIN_SIGNAL_WIDTH) // why are we getting negative values?
{
valid = false;
}
if(valid)
{
AddDetection(sd);
}else
{
delete sd;
}
}
UpdateMinMax();
pfft->Unlock();
}
// monitor and determine high / low thresholds
void SignalDetector::UpdateMinMax()
{
for(int c = 0 ;c < m_entries.size(); c++)
{
SignalDescriptorEntry *sd = m_entries.at(c);
int idx = pfft->GetBinIndex( sd->centerfreqHz);
if(idx != -1)
{
// look at the dBM value at the center
float dbm = pfft->AvgData()[idx];
if(dbm > sd->threshhigh) sd->threshhigh = dbm;
if(dbm < sd->threshlow) sd->threshlow = dbm;
}
}
}
bool CheckSimilarFreq(float f1Hz,float f2Hz, float tolerance)
{
if(f2Hz >= f1Hz - tolerance &&
f2Hz <= f1Hz + tolerance)
{
return true;
}
return false;
}
void SignalDetector::AddDetection(SignalDescriptorEntry *entry)
{
if(CheckMap(entry) == false)//no entry in the map yet, enter one.
{
UpdateMap(entry);
m_entries.append(entry);
entry->identifier = idgen++;
}else
{
SignalDescriptorEntry *found = CheckMapEntry(entry); //find the previous entry if any
if(found != nullptr)
{
found->count ++; // increment it's usage count
found->lastseen = clock(); // update the last time it was seen
}
}
}
SignalDetector::~SignalDetector()
{
delete []m_map;
delete []m_sdemap;
m_entries.clear();
}
void SignalDetector::Dump()
{
cout << "SignalDetector::Dump\r\n";
for (int c = 0; c < m_entries.size(); c++)
{
SignalDescriptorEntry * sde = m_entries[c];
sde->Dump();
}
}
bool SignalDetector::IsActive(SignalDescriptorEntry *sd)
{
int idx = pfft->GetBinIndex( sd->centerfreqHz);
if(idx != -1)
{
// look at the dBM value at the center
float dbm = pfft->AvgData()[idx];
float range = sd->threshhigh - sd->threshlow;
if(dbm > (sd->threshlow + (range * .66)))
return true;
}
return false;
}
void SignalDetector::InitMap()
{
// create the map if needed
if(m_maplen != pfft->GetBinSize())
{
m_maplen = pfft->GetBinSize();
}
//clear old data
for(int c =0; c < m_binsize; c++)
m_map[c] = 0;
// now iterate through all entries and place them on the map.
for(int c = 0 ;c < m_entries.size(); c++)
{
SignalDescriptorEntry *sd = m_entries.at(c);
// we can just add in the entries here without checking them, because
// they were checked when they first got on the list
UpdateMap(sd);
}
}
// returns true if any portion of the index range is taken
bool SignalDetector::CheckMap(SignalDescriptorEntry *sde)
{
// convert the bandwidth to start and stop indexes
int flow,fhigh;
//get the indexes
flow = pfft->GetBinIndex(sde->startf);
fhigh = pfft->GetBinIndex(sde->endf);
if(flow == -1) return true;
if(fhigh == -1) return true;
for(int c = flow; c < fhigh; c++)
{
if(m_map[c] != 0)
return true;
}
return false; // no entries
}
SignalDescriptorEntry *SignalDetector::CheckMapEntry(SignalDescriptorEntry *sde)
{
int fcenter;
//get the indexes
fcenter = pfft->GetBinIndex(sde->centerfreqHz);
if(fcenter == -1) return nullptr;
return m_sdemap[fcenter];
}
void SignalDetector::UpdateMap(SignalDescriptorEntry *sde)
{
int flow,fhigh;
//get the indexes
flow = pfft->GetBinIndex(sde->startf);
fhigh = pfft->GetBinIndex(sde->endf);
if(flow == -1) return;
if(fhigh == -1) return;
for(int c = flow; c < fhigh; c++)
{
m_map[c] = 1; //mark as used
m_sdemap[c] = sde;
}
return; // no entries
}