From 621f2810ab6589c32daaffbf0dd3f4c05c7ece26 Mon Sep 17 00:00:00 2001 From: ezratl Date: Tue, 24 Sep 2019 11:32:40 -0400 Subject: [PATCH] Rewrote scanning algo for bins of bandwidth --- src/core/ScannerSM.cpp | 41 +++++++----- src/core/ScannerSM.h | 8 +-- src/core/StateMachine.h | 3 +- src/scan/Entry.cpp | 7 ++ src/scan/Entry.h | 37 ++++++++--- src/scan/ListGenerator.h | 4 +- src/scan/RadioSystem.h | 10 +-- src/scan/SentinelFile.cpp | 10 ++- src/scan/SystemList.cpp | 135 ++++++++++++++++++++++++++++++++++++++ src/scan/SystemList.h | 32 +++++++-- 10 files changed, 239 insertions(+), 48 deletions(-) diff --git a/src/core/ScannerSM.cpp b/src/core/ScannerSM.cpp index 5032aac..9dea959 100644 --- a/src/core/ScannerSM.cpp +++ b/src/core/ScannerSM.cpp @@ -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(*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(); diff --git a/src/core/ScannerSM.h b/src/core/ScannerSM.h index 4a1f8e9..ef41f51 100644 --- a/src/core/ScannerSM.h +++ b/src/core/ScannerSM.h @@ -65,10 +65,10 @@ private: MessageReceiver& _centralQueue; //moodycamel::ReaderWriterQueue _msgQueue; SystemList& _systems; - RadioSystem* _currentSystem; - Entry* _currentEntry; - Entry* _manualEntry = nullptr; - size_t _sysCounter = 0, _entryCounter = 0; + //RadioSystem* _currentSystem; + std::shared_ptr _currentEntry; + std::shared_ptr _manualEntry; + //size_t _sysCounter = 0, _entryCounter = 0; ScannerContext _currentContext; std::mutex _contextMutex; diff --git a/src/core/StateMachine.h b/src/core/StateMachine.h index 4f80b67..d54789f 100644 --- a/src/core/StateMachine.h +++ b/src/core/StateMachine.h @@ -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; diff --git a/src/scan/Entry.cpp b/src/scan/Entry.cpp index a669bb7..8e00c6e 100644 --- a/src/scan/Entry.cpp +++ b/src/scan/Entry.cpp @@ -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); diff --git a/src/scan/Entry.h b/src/scan/Entry.h index fe410e7..04702d5 100644 --- a/src/scan/Entry.h +++ b/src/scan/Entry.h @@ -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; }; diff --git a/src/scan/ListGenerator.h b/src/scan/ListGenerator.h index 6bb5bb3..1b574f1 100644 --- a/src/scan/ListGenerator.h +++ b/src/scan/ListGenerator.h @@ -33,8 +33,8 @@ public: void generateSystemList(SystemList& list); private: - SystemList* _list; - RadioSystem* _system; + SystemList* _list = nullptr; + std::shared_ptr _system; void _newAnalogSys(std::vector& tokens); void _newAnalogEntry(std::vector& tokens); diff --git a/src/scan/RadioSystem.h b/src/scan/RadioSystem.h index ae59e1c..09e2563 100644 --- a/src/scan/RadioSystem.h +++ b/src/scan/RadioSystem.h @@ -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 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) = 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 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){ if(entry != nullptr){ entries.push_back(entry); numEntries++; @@ -61,7 +61,7 @@ public: } protected: - std::vector entries; + std::vector> entries; }; } #endif /* RADIOSYSTEM_H_ */ diff --git a/src/scan/SentinelFile.cpp b/src/scan/SentinelFile.cpp index caf413b..c7dd7b3 100644 --- a/src/scan/SentinelFile.cpp +++ b/src/scan/SentinelFile.cpp @@ -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& 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(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& 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(std::stoul(freq), tag, (!lockout.compare(SENTINEL_TRUE)), (delay.compare("0"))); + + entry->setSysIndex(_list->size() - 1); + entry->setEntryIndex(_system->size()); + _system->addEntry(entry); } } diff --git a/src/scan/SystemList.cpp b/src/scan/SystemList.cpp index 97acc64..f9dabc0 100644 --- a/src/scan/SystemList.cpp +++ b/src/scan/SystemList.cpp @@ -18,3 +18,138 @@ SystemList::~SystemList() { // TODO Auto-generated destructor stub } + +std::shared_ptr SystemList::getNextEntry(){ + if(_entryNum == 0 && _retune){ + _retune = false; + return std::make_shared(_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 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 newBin = std::make_shared(); + _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(); + _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 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 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(L[i]->freq()) <= static_cast(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 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(); +} diff --git a/src/scan/SystemList.h b/src/scan/SystemList.h index 9bc1479..c76b550 100644 --- a/src/scan/SystemList.h +++ b/src/scan/SystemList.h @@ -19,19 +19,39 @@ public: SystemList(); ~SystemList(); - RadioSystem* operator[](size_t pos) { return _systems[pos]; }; + std::shared_ptr 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 system) { _systems.push_back(system); } + + std::shared_ptr getNextEntry(); + + void sortBins(int bandwidth); private: - std::vector _systems; + + class EntryBin: public std::vector>{ + public: + EntryBin(){}; + ~EntryBin(){}; + + void sort(); + long getCenterFreq(); + }; + + + std::vector> _systems; //size_t _size = 0; + + std::vector> _bins; + + size_t _binNum = 0, _entryNum = 0; + bool _retune = true; + + void merge(std::shared_ptr arr[], int l, int m, int r); + void mergeSort(std::shared_ptr arr[], int l, int r); }; } #endif /* SYSTEMLIST_H_ */