From feba05832792abdfe4c3da4aacb256c5ff56cb5a Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 24 Jan 2024 21:55:08 +0100 Subject: [PATCH] optimize conv for detection --- include/fixed_queue.hpp | 24 ++++++++------ include/iq_stream_decoder.hpp | 10 +++--- src/iq_stream_decoder.cpp | 61 +++++++++++++---------------------- 3 files changed, 42 insertions(+), 53 deletions(-) diff --git a/include/fixed_queue.hpp b/include/fixed_queue.hpp index 9557f15..73a8260 100644 --- a/include/fixed_queue.hpp +++ b/include/fixed_queue.hpp @@ -2,30 +2,34 @@ #include #include -template > -class FixedQueue : public std::queue { +template > class FixedQueue { + private: + Container queue{}; + public: FixedQueue() { for (auto i = 0; i < MaxLen; i++) { T default_value{}; - std::queue::push(default_value); + queue.push_back(default_value); } } void push(const T& value) { - if (this->size() == MaxLen) { - this->c.pop_front(); + if (queue.size() == MaxLen) { + queue.pop_front(); } - std::queue::push(value); + queue.push_back(value); } void pop(const T& value) { std::logic_error("Function not implemented"); } - typename Container::const_iterator cbegin() { return this->c.cbegin(); } + typename Container::const_iterator cbegin() { return queue.cbegin(); } + + typename Container::const_reverse_iterator crbegin() { return queue.crbegin(); } - typename Container::const_reverse_iterator crbegin() { return this->c.crbegin(); } + typename Container::const_iterator cend() { return queue.cend(); } - typename Container::const_iterator cend() { return this->c.cend(); } + typename Container::const_reverse_iterator crend() { return queue.crend(); } - typename Container::const_reverse_iterator crend() { return this->c.crend(); } + typename Container::const_reference operator[](typename Container::size_type pos) const { return queue[pos]; } }; diff --git a/include/iq_stream_decoder.hpp b/include/iq_stream_decoder.hpp index 81d3474..50cf43c 100644 --- a/include/iq_stream_decoder.hpp +++ b/include/iq_stream_decoder.hpp @@ -33,19 +33,21 @@ class IQStreamDecoder { void process_complex(std::complex symbol) noexcept; private: + using QueueT = FixedQueue, 300>; + void upperMacWorker(); std::complex hard_decision(std::complex symbol); std::vector symbols_to_bitstream(std::vector> const& stream); - std::vector> convolve_valid(std::vector> const& a, - std::vector> const& b); + void abs_convolve_same_length(const QueueT& queueA, const std::size_t offsetA, const std::complex* itb, + const std::size_t len, float* res); std::vector> channel_estimation(std::vector> const& stream, std::vector> const& pilots); - FixedQueue, 300> symbol_buffer_; - FixedQueue, 300> symbol_buffer_hard_decision_; + QueueT symbol_buffer_; + QueueT symbol_buffer_hard_decision_; // 9.4.4.3.2 Normal training sequence const std::vector> training_seq_n_ = {{-1, -1}, {-1, 1}, {1, 1}, {1, 1}, {-1, -1}, {1, -1}, diff --git a/src/iq_stream_decoder.cpp b/src/iq_stream_decoder.cpp index d9c8841..ce3540f 100644 --- a/src/iq_stream_decoder.cpp +++ b/src/iq_stream_decoder.cpp @@ -37,7 +37,8 @@ IQStreamDecoder::IQStreamDecoder(std::shared_ptr lower_mac, } IQStreamDecoder::~IQStreamDecoder() { - // TODO: replace this crude hack that keeps the StreamingOrderedOutputThreadPoolExecutor<...> get function from blocking on programm stop + // TODO: replace this crude hack that keeps the StreamingOrderedOutputThreadPoolExecutor<...> get function from + // blocking on programm stop threadPool_->queueWork([]() { return std::vector>(); }); upperMacWorkerThread_.join(); } @@ -100,27 +101,14 @@ std::vector IQStreamDecoder::symbols_to_bitstream(std::vector> IQStreamDecoder::convolve_valid(std::vector> const& a, - std::vector> const& b) { - std::vector> res; - - // make shure a is longer equal than b - if (b.size() > a.size()) { - return convolve_valid(b, a); - } - - for (int i = 0; i < a.size() - b.size() + 1; i++) { - std::complex v{}; - auto ita = a.begin(); - std::advance(ita, i); - auto itb = b.rbegin(); - for (; itb != b.rend(); ita++, itb++) { - v += *ita * *itb; - } - res.push_back(v); +void IQStreamDecoder::abs_convolve_same_length(const QueueT& queueA, const std::size_t offsetA, + const std::complex* const itb, const std::size_t len, + float* res) { + std::complex acc = {0.0, 0.0}; + for (std::size_t i = 0; i < len; ++i) { + acc += queueA[offsetA + i] * itb[i]; } - - return res; + *res = std::abs(acc); } std::vector> IQStreamDecoder::channel_estimation(std::vector> const& stream, @@ -131,6 +119,10 @@ std::vector> IQStreamDecoder::channel_estimation(std::vector void IQStreamDecoder::process_complex(std::complex symbol) noexcept { if (is_uplink_) { + float detectedN; + float detectedP; + float detectedX; + // Control Uplink Burst or Normal Uplink Burst symbol_buffer_.push(symbol); symbol_buffer_hard_decision_.push(hard_decision(symbol)); @@ -140,30 +132,21 @@ void IQStreamDecoder::process_complex(std::complex symbol) noexcept { // // find NUB // 2 tail + 108 coded symbols + middle of 11 training sequence (6) = 116 - auto start_n = symbol_buffer_hard_decision_.cbegin(); - std::advance(start_n, 109); - auto end_n = start_n; - std::advance(end_n, 11); - auto find_n = convolve_valid({start_n, end_n}, training_seq_n_reversed_conj_)[0]; + abs_convolve_same_length(symbol_buffer_hard_decision_, 109, training_seq_n_reversed_conj_.data(), + training_seq_n_reversed_conj_.size(), &detectedN); // find NUB_Split // 2 tail + 108 coded symbols + middle of 11 training sequence (6) = 116 - auto start_p = symbol_buffer_hard_decision_.cbegin(); - std::advance(start_p, 109); - auto end_p = start_p; - std::advance(end_p, 11); - auto find_p = convolve_valid({start_p, end_p}, training_seq_p_reversed_conj_)[0]; + abs_convolve_same_length(symbol_buffer_hard_decision_, 109, training_seq_p_reversed_conj_.data(), + training_seq_p_reversed_conj_.size(), &detectedP); // find CUB // 2 tail + 42 coded symbols + middle of 15 training sequence (8) = 52 - auto start_x = symbol_buffer_hard_decision_.cbegin(); - std::advance(start_x, 44); - auto end_x = start_x; - std::advance(end_x, 15); - auto find_x = convolve_valid({start_x, end_x}, training_seq_x_reversed_conj_)[0]; + abs_convolve_same_length(symbol_buffer_hard_decision_, 44, training_seq_x_reversed_conj_.data(), + training_seq_x_reversed_conj_.size(), &detectedX); // use actual signal for further processing auto start = symbol_buffer_.cbegin(); - if (std::abs(find_x) >= SEQUENCE_DETECTION_THRESHOLD) { + if (detectedX >= SEQUENCE_DETECTION_THRESHOLD) { // std::cout << "Potential CUB found" << std::endl; auto end = start; @@ -174,7 +157,7 @@ void IQStreamDecoder::process_complex(std::complex symbol) noexcept { threadPool_->queueWork(std::bind(&LowerMac::process, lower_mac_, bitstream, BurstType::ControlUplinkBurst)); } - if (std::abs(find_p) >= SEQUENCE_DETECTION_THRESHOLD) { + if (detectedP >= SEQUENCE_DETECTION_THRESHOLD) { // std::cout << "Potential NUB_Split found" << std::endl; auto end = start; @@ -185,7 +168,7 @@ void IQStreamDecoder::process_complex(std::complex symbol) noexcept { BurstType::NormalUplinkBurstSplit)); } - if (std::abs(find_n) >= SEQUENCE_DETECTION_THRESHOLD) { + if (detectedN >= SEQUENCE_DETECTION_THRESHOLD) { // std::cout << "Potential NUB found" << std::endl; auto end = start;