Rewrote scanning algo for bins of bandwidth

This commit is contained in:
ezratl 2019-09-24 11:32:40 -04:00
parent 9dbf2fb763
commit 621f2810ab
10 changed files with 239 additions and 48 deletions

View File

@ -17,7 +17,7 @@
using namespace piscan;
ScannerSM::ScannerSM(MessageReceiver& central, SystemList& dataSource) :
StateMachine(7), _centralQueue(central), _systems(dataSource), _currentSystem(nullptr), _currentEntry(nullptr) {
StateMachine(7), _centralQueue(central), _systems(dataSource) {
}
void ScannerSM::startScan(){
@ -82,7 +82,8 @@ void ScannerSM::ST_Load(EventData* data){
generator->generateSystemList(_systems);
LOG_F(INFO, "Loaded %u systems", _systems.size());
_currentSystem = _systems[0];
//_currentSystem = _systems[0];
_systems.sortBins(2000000);
// do not issue event - SM will wait until an event is generated before proceeding
//InternalEvent(ST_SCAN);
@ -107,22 +108,24 @@ void ScannerSM::ST_Scan(EventData* data){
// incremental scan pattern
if(!_squelchHits || (currentState != lastState)){
_entryCounter = (_entryCounter + 1) % _currentSystem->size();
//_entryCounter = (_entryCounter + 1) % _currentSystem->size();
if(_entryCounter == 0){
_sysCounter = (_sysCounter + 1) % _systems.size();
// if(_entryCounter == 0){
// _sysCounter = (_sysCounter + 1) % _systems.size();
//
// _currentSystem = _systems[_sysCounter];
// assert(_currentSystem != nullptr);
//
// //_broadcastContextUpdate();
// }
_currentSystem = _systems[_sysCounter];
assert(_currentSystem != nullptr);
//CHECK_F(_currentSystem->size() > 0);
//_currentEntry = _currentSystem->operator[](_entryCounter);
//CHECK_F(_currentEntry != NULL);
//_broadcastContextUpdate();
}
CHECK_F(_currentSystem->size() > 0);
_currentEntry = _currentSystem->operator[](_entryCounter);
CHECK_F(_currentEntry != NULL);
_currentEntry = _systems.getNextEntry();
}
@ -216,15 +219,16 @@ void ScannerSM::ST_Manual(EventData* data){
LOG_F(1, "Setting manual frequency to %.4lfMHz", (*freq / 1E6));
/* delete old manual entry */
if(_manualEntry != nullptr)
delete _manualEntry;
//if(_manualEntry != nullptr)
//delete _manualEntry;
_manualEntry = new FMChannel(*freq, "", false, false);
_manualEntry = std::make_shared<FMChannel>(*freq, "", false, false);
delete freq;
_currentEntry = _manualEntry;
_externalHold = true;
_manualMode = true;
InternalEvent(ST_HOLD);
}
void ScannerSM::ST_SaveAll(EventData* data){
@ -257,9 +261,10 @@ void ScannerSM::_broadcastContextUpdate() {
}
else
{
_currentContext.systemTag = _currentSystem->tag();
//_currentContext.systemTag = _currentSystem->tag();
_currentContext.systemTag = _systems[_currentEntry->getSysIndex()]->tag();
_currentContext.entryTag = _currentEntry->tag();
_currentContext.entryIndex = std::to_string(_sysCounter) + "-" + std::to_string(_entryCounter);
_currentContext.entryIndex = std::to_string(_currentEntry->getSysIndex()) + "-" + std::to_string(_currentEntry->getEntryIndex());
}
_currentContext.frequency = _currentEntry->freq();
_currentContext.modulation = _currentEntry->modulation();

View File

@ -65,10 +65,10 @@ private:
MessageReceiver& _centralQueue;
//moodycamel::ReaderWriterQueue<Message> _msgQueue;
SystemList& _systems;
RadioSystem* _currentSystem;
Entry* _currentEntry;
Entry* _manualEntry = nullptr;
size_t _sysCounter = 0, _entryCounter = 0;
//RadioSystem* _currentSystem;
std::shared_ptr<Entry> _currentEntry;
std::shared_ptr<Entry> _manualEntry;
//size_t _sysCounter = 0, _entryCounter = 0;
ScannerContext _currentContext;
std::mutex _contextMutex;

View File

@ -45,13 +45,14 @@ protected:
void ExternalEvent(unsigned char, EventData* = NULL);
void InternalEvent(unsigned char, EventData* = NULL);
virtual const StateStruct* GetStateMap() = 0;
std::thread _stateMachineThread;
private:
const int _maxStates;
bool _eventGenerated;
EventData* _pEventData;
void StateEngine(void);
void StateThreadFunc(void);
std::thread _stateMachineThread;
std::mutex _eventMutex;
std::condition_variable _cv;
bool _run = false;

View File

@ -14,6 +14,13 @@ using namespace piscan;
DemodInterface* Entry::demod = nullptr;
bool DummyChannel::hasSignal(){
if(!demod->setFrequency(this->frequency))
return false;
return false;
}
bool FMChannel::hasSignal(void){
assert(demod != nullptr);

View File

@ -25,13 +25,19 @@ public:
bool useDelay() { return _scanDelay; }
void lockout(bool val = true) { _lockedOut = val; }
virtual bool hasSignal() = 0;
virtual unsigned long freq() = 0;
virtual long freq() = 0;
size_t getSysIndex() { return _sysIndex; };
void setSysIndex(size_t index) { _sysIndex = index; };
size_t getEntryIndex() { return _entryIndex; };
void setEntryIndex(size_t index) { _entryIndex = index; };
private:
std::string _tag;
bool _lockedOut;
bool _scanDelay;
size_t _sysIndex = 0;
size_t _entryIndex = 0;
protected:
static DemodInterface* demod;
friend void setDemodulator(DemodInterface* demod);
@ -39,16 +45,29 @@ protected:
class Channel: public Entry {
public:
Channel(unsigned long freq, std::string tag, bool lo, bool del) : Entry(tag, lo, del), frequency(freq){}
Channel(long freq, std::string tag, bool lo, bool del) : Entry(tag, lo, del), frequency(freq){}
virtual ~Channel() {};
virtual unsigned long freq() { return frequency; };
virtual long freq() { return frequency; };
protected:
const unsigned long frequency;
const long frequency;
};
class DummyChannel: public Channel {
public:
DummyChannel(long freq) : Channel(freq, "", false, false){
}
~DummyChannel(){};
std::string modulation() { return ""; };
bool hasSignal();
};
class FMChannel : public Channel {
public:
FMChannel(unsigned long freq, std::string tag, bool lo, bool del) : Channel(freq, tag, lo, del){}
FMChannel(long freq, std::string tag, bool lo, bool del) : Channel(freq, tag, lo, del){}
~FMChannel() {};
std::string modulation() {
@ -60,7 +79,7 @@ public:
class PLChannel: public FMChannel {
public:
PLChannel(unsigned long freq, float tn, std::string tag, bool lo, bool del) :
PLChannel(long freq, float tn, std::string tag, bool lo, bool del) :
FMChannel(freq, tag, lo, del), tone(tn) {
}
~PLChannel() {};
@ -72,7 +91,7 @@ protected:
class DCChannel : public FMChannel {
public:
DCChannel(unsigned long freq, unsigned int tn, std::string tag, bool lo, bool del) :
DCChannel(long freq, unsigned int tn, std::string tag, bool lo, bool del) :
FMChannel(freq, tag, lo, del), code(tn) {
}
~DCChannel() {};
@ -84,7 +103,7 @@ protected:
class AMChannel : public Channel {
public:
AMChannel(unsigned long freq, std::string tag, bool lo, bool del) : Channel(freq, tag, lo, del){}
AMChannel(long freq, std::string tag, bool lo, bool del) : Channel(freq, tag, lo, del){}
~AMChannel() {};
bool hasSignal() { return false; };

View File

@ -33,8 +33,8 @@ public:
void generateSystemList(SystemList& list);
private:
SystemList* _list;
RadioSystem* _system;
SystemList* _list = nullptr;
std::shared_ptr<RadioSystem> _system;
void _newAnalogSys(std::vector<std::string>& tokens);
void _newAnalogEntry(std::vector<std::string>& tokens);

View File

@ -26,13 +26,13 @@ public:
RadioSystem(std::string tag, bool lo) : _tag(tag), _lockout(lo) {};
virtual ~RadioSystem() {};
virtual Entry* operator[](size_t pos) = 0;
virtual std::shared_ptr<Entry> operator[](size_t pos) = 0;
virtual size_t size() { return numEntries; }
std::string tag() { return _tag; };
virtual void addEntry(Entry* entry) = 0;
virtual void addEntry(std::shared_ptr<Entry> entry) = 0;
private:
//const RadioSystemType type;
const std::string _tag;
@ -47,13 +47,13 @@ public:
AnalogSystem(std::string tag, bool lo) : RadioSystem(tag, lo) {};
~AnalogSystem() {};
virtual Entry* operator[](size_t pos) { return entries[pos]; };
virtual std::shared_ptr<Entry> operator[](size_t pos) { return entries[pos]; };
/*virtual size_t size() {
return entries.size();
}*/
virtual void addEntry(Entry* entry){
virtual void addEntry(std::shared_ptr<Entry> entry){
if(entry != nullptr){
entries.push_back(entry);
numEntries++;
@ -61,7 +61,7 @@ public:
}
protected:
std::vector<Entry*> entries;
std::vector<std::shared_ptr<Entry>> entries;
};
}
#endif /* RADIOSYSTEM_H_ */

View File

@ -72,7 +72,7 @@ void SentinelFile::generateSystemList(SystemList& list) {
std::string& type = tokens[0];
if(!type.compare(C_GROUP))
_newAnalogSys(tokens);
else if(!type.compare(C_FREQ))
else if(!type.compare(C_FREQ) && _system != nullptr)
_newAnalogEntry(tokens);
@ -84,7 +84,7 @@ void SentinelFile::generateSystemList(SystemList& list) {
void SentinelFile::_newAnalogSys(std::vector<std::string>& tokens){
LOG_F(4, "New AnalogSystem: %s", tokens[C_GROUP_TAG_POS].c_str());
_system = new AnalogSystem(tokens[C_GROUP_TAG_POS], (!tokens[C_GROUP_LO_POS].compare(SENTINEL_TRUE)));
_system = std::make_shared<AnalogSystem>(tokens[C_GROUP_TAG_POS], (!tokens[C_GROUP_LO_POS].compare(SENTINEL_TRUE)));
_list->addSystem(_system);
}
@ -102,8 +102,12 @@ void SentinelFile::_newAnalogEntry(std::vector<std::string>& tokens){
LOG_F(4, "Entry: %s - Freq: %s", tag.c_str(), freq.c_str());
if(!mode.compare(SENTINEL_NFM) || !mode.compare(SENTINEL_FM) || !mode.compare(SENTINEL_AUTO)) {
Entry* entry = new FMChannel(std::stoul(freq), tag,
auto entry = std::make_shared<FMChannel>(std::stoul(freq), tag,
(!lockout.compare(SENTINEL_TRUE)), (delay.compare("0")));
entry->setSysIndex(_list->size() - 1);
entry->setEntryIndex(_system->size());
_system->addEntry(entry);
}
}

View File

@ -18,3 +18,138 @@ SystemList::~SystemList() {
// TODO Auto-generated destructor stub
}
std::shared_ptr<Entry> SystemList::getNextEntry(){
if(_entryNum == 0 && _retune){
_retune = false;
return std::make_shared<DummyChannel>(_bins[_binNum]->getCenterFreq());
}
auto entry = _bins[_binNum]->operator [](_entryNum);
_entryNum = (_entryNum + 1) % _bins[_binNum]->size();
if(_entryNum == 0){
_binNum = (_binNum + 1) % _bins.size();
_retune = true;
}
return entry;
}
void SystemList::sortBins(int bandwidth){
size_t numEntries = 0;
for(size_t i = 0; i < _systems.size(); i++)
for(size_t k = 0; k < _systems[i]->size(); k++)
numEntries++;
std::shared_ptr<Entry> entries[numEntries];
numEntries = 0;
for(size_t i = 0; i < _systems.size(); i++)
for(size_t k = 0; k < _systems[i]->size(); k++){
//entries.push_back(_systems[i]->operator [](k));
entries[numEntries] = _systems[i]->operator [](k);
numEntries++;
}
mergeSort(entries, 0, numEntries - 1);
std::shared_ptr<EntryBin> newBin = std::make_shared<EntryBin>();
_bins.push_back(newBin);
long lastFreq = 0;
for(size_t i = 0; i < numEntries; i++){
if(newBin->size() && entries[i]->freq() >= (newBin->front()->freq() + bandwidth)){
newBin = std::make_shared<EntryBin>();
_bins.push_back(newBin);
}
if(entries[i]->freq() < lastFreq)
LOG_F(WARNING, "Entries not sorted properly!");
lastFreq = entries[i]->freq();
newBin->push_back(entries[i]);
}
}
void SystemList::merge(std::shared_ptr<Entry> arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
std::shared_ptr<Entry> L[n1], R[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1+ j];
/* Merge the temp arrays back into arr[l..r]*/
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2)
{
if (static_cast<long>(L[i]->freq()) <= static_cast<long>(R[j]->freq()))
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there
are any */
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there
are any */
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
}
}
/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void SystemList::mergeSort(std::shared_ptr<Entry> arr[], int l, int r)
{
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l+(r-l)/2;
// Sort first and second halves
mergeSort(arr, l, m);
mergeSort(arr, m+1, r);
merge(arr, l, m, r);
}
}
long SystemList::EntryBin::getCenterFreq(){
if(this->size() > 1){
long range = this->back()->freq() + this->front()->freq();
return (range) / 2;
}
else
return this->front()->freq();
}

View File

@ -19,19 +19,39 @@ public:
SystemList();
~SystemList();
RadioSystem* operator[](size_t pos) { return _systems[pos]; };
std::shared_ptr<RadioSystem> operator[](size_t pos) { return _systems[pos]; };
size_t size(){ return _systems.size(); }
void addSystem(RadioSystem& system){
addSystem(&system);
}
void addSystem(RadioSystem* system) {
void addSystem(std::shared_ptr<RadioSystem> system) {
_systems.push_back(system);
}
std::shared_ptr<Entry> getNextEntry();
void sortBins(int bandwidth);
private:
std::vector<RadioSystem*> _systems;
class EntryBin: public std::vector<std::shared_ptr<Entry>>{
public:
EntryBin(){};
~EntryBin(){};
void sort();
long getCenterFreq();
};
std::vector<std::shared_ptr<RadioSystem>> _systems;
//size_t _size = 0;
std::vector<std::shared_ptr<EntryBin>> _bins;
size_t _binNum = 0, _entryNum = 0;
bool _retune = true;
void merge(std::shared_ptr<Entry> arr[], int l, int m, int r);
void mergeSort(std::shared_ptr<Entry> arr[], int l, int r);
};
}
#endif /* SYSTEMLIST_H_ */