diff --git a/modemm17/CMakeLists.txt b/modemm17/CMakeLists.txt index aa7205461..fa04e8ecf 100644 --- a/modemm17/CMakeLists.txt +++ b/modemm17/CMakeLists.txt @@ -8,6 +8,7 @@ set(modemm17_SOURCES LinkSetupFrame.cpp M17Demodulator.cpp M17Modulator.cpp + M17Randomizer.cpp ) set(modemm17_HEADERS @@ -35,7 +36,6 @@ set(modemm17_HEADERS M17Synchronizer.h PhaseEstimator.h PolynomialInterleaver.h - queue.h SlidingDFT.h SymbolEvm.h Trellis.h diff --git a/modemm17/M17FrameDecoder.h b/modemm17/M17FrameDecoder.h index 081fa8375..ed9c033b7 100644 --- a/modemm17/M17FrameDecoder.h +++ b/modemm17/M17FrameDecoder.h @@ -41,7 +41,7 @@ struct M17FrameDecoder { static const size_t MAX_LICH_FRAGMENT = 5; - M17Randomizer<368> derandomize_; + M17Randomizer derandomize_; PolynomialInterleaver<45, 92, 368> interleaver_; Trellis<4,2> trellis_{makeTrellis<4, 2>({031,027})}; Viterbi viterbi_{trellis_}; diff --git a/modemm17/M17Modulator.h b/modemm17/M17Modulator.h index 378e0817f..45260a994 100644 --- a/modemm17/M17Modulator.h +++ b/modemm17/M17Modulator.h @@ -118,7 +118,7 @@ public: { lsf.fill(0); - M17Randomizer<368> randomizer; + M17Randomizer randomizer; PolynomialInterleaver<45, 92, 368> interleaver; CRC16 crc(0x5935, 0xFFFF); @@ -289,7 +289,7 @@ public: const std::array packet ) { - M17Randomizer<368> randomizer; + M17Randomizer randomizer; PolynomialInterleaver<45, 92, 368> interleaver; std::array packet_assembly; @@ -446,7 +446,7 @@ public: static void interleave_and_randomize(std::array& punctured) { - M17Randomizer<368> randomizer; + M17Randomizer randomizer; PolynomialInterleaver<45, 92, 368> interleaver; interleaver.interleave(punctured); diff --git a/modemm17/M17Randomizer.cpp b/modemm17/M17Randomizer.cpp new file mode 100644 index 000000000..91d9ec2cc --- /dev/null +++ b/modemm17/M17Randomizer.cpp @@ -0,0 +1,14 @@ +#include "M17Randomizer.h" + +namespace modemm17 +{ + +const std::array M17Randomizer::DC = std::array{ + 0xd6, 0xb5, 0xe2, 0x30, 0x82, 0xFF, 0x84, 0x62, + 0xba, 0x4e, 0x96, 0x90, 0xd8, 0x98, 0xdd, 0x5d, + 0x0c, 0xc8, 0x52, 0x43, 0x91, 0x1d, 0xf8, 0x6e, + 0x68, 0x2F, 0x35, 0xda, 0x14, 0xea, 0xcd, 0x76, + 0x19, 0x8d, 0xd5, 0x80, 0xd1, 0x33, 0x87, 0x13, + 0x57, 0x18, 0x2d, 0x29, 0x78, 0xc3}; + +} diff --git a/modemm17/M17Randomizer.h b/modemm17/M17Randomizer.h index b7996023a..a77b8374b 100644 --- a/modemm17/M17Randomizer.h +++ b/modemm17/M17Randomizer.h @@ -9,28 +9,14 @@ namespace modemm17 { -namespace detail -{ - -// M17 randomization matrix. -static const std::array DC = std::array{ - 0xd6, 0xb5, 0xe2, 0x30, 0x82, 0xFF, 0x84, 0x62, - 0xba, 0x4e, 0x96, 0x90, 0xd8, 0x98, 0xdd, 0x5d, - 0x0c, 0xc8, 0x52, 0x43, 0x91, 0x1d, 0xf8, 0x6e, - 0x68, 0x2F, 0x35, 0xda, 0x14, 0xea, 0xcd, 0x76, - 0x19, 0x8d, 0xd5, 0x80, 0xd1, 0x33, 0x87, 0x13, - 0x57, 0x18, 0x2d, 0x29, 0x78, 0xc3}; -} - -template struct M17Randomizer { - std::array dc_; + std::array dc_; M17Randomizer() { size_t i = 0; - for (auto b : detail::DC) + for (auto b : DC) { for (size_t j = 0; j != 8; ++j) { @@ -40,39 +26,24 @@ struct M17Randomizer } // Randomize and derandomize are the same operation. - void operator()(std::array& frame) + void operator()(std::array& frame) { - for (size_t i = 0; i != N; ++i) + for (size_t i = 0; i != 368; ++i) { frame[i] *= dc_[i]; } } - void randomize(std::array& frame) + void randomize(std::array& frame) { - for (size_t i = 0; i != N; ++i) + for (size_t i = 0; i != 368; ++i) { frame[i] ^= (dc_[i] == -1); } } -}; - -template -struct M17ByteRandomizer -{ - // Randomize and derandomize are the same operation. - void operator()(std::array& frame) - { - for (size_t i = 0; i != N; ++i) - { - for (size_t j = 8; j != 0; --j) - { - uint8_t mask = 1 << (j - 1); - frame[i] = (frame[i] & ~mask) | ((frame[i] & mask) ^ (detail::DC[i] & mask)); - } - } - } +private: + static const std::array DC; }; diff --git a/modemm17/SlidingDFT.h b/modemm17/SlidingDFT.h index 9c6118e4c..1582bb0f6 100644 --- a/modemm17/SlidingDFT.h +++ b/modemm17/SlidingDFT.h @@ -21,24 +21,22 @@ template class SlidingDFT { public: - using ComplexType = std::complex; - SlidingDFT() { samples_.fill(0); float pi2 = M_PI * 2.0f; float kth = float(Frequency) / float(SampleRate); - coeff_ = std::exp(-ComplexType{0, 1} * pi2 * kth); + coeff_ = std::exp(-std::complex{0, 1} * pi2 * kth); } - ComplexType operator()(float sample) + std::complex operator()(float sample) { auto index = index_; index_ += 1; if (index_ == (SampleRate / Accuracy)) index_ = 0; float delta = sample - samples_[index]; - ComplexType result = (result_ + delta) * coeff_; + std::complex result = (result_ + delta) * coeff_; result_ = result * float(0.999999999999999); samples_[index] = sample; prev_index_ = index; @@ -46,9 +44,9 @@ public: } private: - ComplexType coeff_; + std::complex coeff_; std::array samples_; - ComplexType result_{0,0}; + std::complex result_{0,0}; size_t index_ = 0; size_t prev_index_ = (SampleRate / Accuracy) - 1; }; @@ -69,8 +67,7 @@ template class NSlidingDFT { public: - using ComplexType = std::complex; - using result_type = std::array; + using result_type = std::array, K>; /** * Construct the DFT with an array of frequencies. These frequencies @@ -107,17 +104,17 @@ public: } private: - const std::array coeff_; + const std::array, K> coeff_; std::array samples_; - std::array result_{0,0}; + std::array, K> result_{0,0}; size_t index_ = 0; size_t prev_index_ = N - 1; - static constexpr std::array + static constexpr std::array, K> make_coefficients(const std::array& frequencies) { - ComplexType j = ComplexType{0, 1}; - std::array result; + std::complex j = std::complex{0, 1}; + std::array, K> result; float pi2 = M_PI * 2.0f; for (size_t i = 0; i != K; ++i) { diff --git a/modemm17/queue.h b/modemm17/queue.h deleted file mode 100644 index 65502b601..000000000 --- a/modemm17/queue.h +++ /dev/null @@ -1,251 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -namespace modemm17 -{ - -/** - * A thread-safe queue - */ -template -class queue -{ -private: - - using mutex_type = std::mutex; - using lock_type = std::unique_lock; - using guard_type = std::lock_guard; - - enum class State {OPEN, CLOSING, CLOSED}; - - std::list queue_; - size_t size_ = 0; - State state_ = State::OPEN; - mutable mutex_type mutex_; - std::condition_variable full_; - std::condition_variable empty_; - - queue(queue&) = delete; - queue& operator=(const queue&) = delete; - -public: - - static constexpr auto forever = std::chrono::seconds::max(); - - /// The data type stored in the queue. - using value_type = T; - - /// A reference to an element stored in the queue. - using reference = value_type&; - - /// A const reference to an element stored in the queue. - using const_reference = value_type const&; - - /// A pointer to an element stored in a Queue. - using pointer = value_type*; - - /// A pointer to an element stored in a Queue. - using const_pointer = const value_type*; - - queue() - {} - - /** - * Get the next item in the queue. - * - * @param[out] val is an object into which the object will be moved - * or copied. - * @param[in] timeout is the duration to wait for an item to appear - * in the queue (default is forever, duration::max()). - * - * @return true if a value was returned, otherwise false. - * - * @note The return value me be false if either the timeout expires - * or the queue is closed. - */ - template - bool get_until(reference val, std::chrono::time_point when) - { - lock_type lock(mutex_); - - while (queue_.empty()) - { - if (State::CLOSED == state_) - { - return false; - } - - if (empty_.wait_until(lock, when) == std::cv_status::timeout) - { - return false; - } - } - - val = std::move(queue_.front()); - queue_.pop_front(); - size_ -= 1; - - if (state_ == State::CLOSING && queue_.empty()) - { - state_ == State::CLOSED; - } - - full_.notify_one(); - - return true; - } - - /** - * Get the next item in the queue. - * - * @param[out] val is an object into which the object will be moved - * or copied. - * @param[in] timeout is the duration to wait for an item to appear - * in the queue (default is forever, duration::max()). - * - * @return true if a value was returned, otherwise false. - * - * @note The return value me be false if either the timeout expires - * or the queue is closed. - */ - template> - bool get(reference val, std::chrono::duration timeout = std::chrono::duration::max()) - { - lock_type lock(mutex_); - - while (queue_.empty()) - { - if (State::CLOSED == state_) - { - return false; - } - - if (empty_.wait_for(lock, timeout) == std::cv_status::timeout) - { - return false; - } - } - - val = std::move(queue_.front()); - queue_.pop_front(); - size_ -= 1; - - if (state_ == State::CLOSING && queue_.empty()) - { - state_ == State::CLOSED; - } - - full_.notify_one(); - - return true; - }; - - /** - * Put an item on the queue. - * - * @param[in] val is the element to be appended to the queue. - * @param[in] timeout is the duration to wait until queue there is room - * for more items on the queue (default is forever -- duration::max()). - * - * @return true if a value was put on the queue, otherwise false. - * - * @note The return value me be false if either the timeout expires - * or the queue is closed. - */ - template> - bool put(U&& val, std::chrono::duration timeout = std::chrono::duration::max()) - { - // Get the queue mutex. - lock_type lock(mutex_); - - if (SIZE == size_) - { - if (timeout.count() == 0) - { - return false; - } - - auto expiration = std::chrono::system_clock::now() + timeout; - - while (SIZE == size_) - { - if (State::OPEN != state_) - { - return false; - } - - if (full_.wait_until(lock, expiration) == std::cv_status::timeout) - { - return false; - } - } - } - - if (State::OPEN != state_) - { - return false; - } - - queue_.emplace_back(std::forward(val)); - size_ += 1; - - empty_.notify_one(); - - return true; - }; - - void close() - { - guard_type lock(mutex_); - - state_ = (queue_.empty() ? State::CLOSED : State::CLOSING); - - full_.notify_all(); - empty_.notify_all(); - } - - bool is_open() const - { - return State::OPEN == state_; - } - - bool is_closed() const - { - return State::CLOSED == state_; - } - - /** - * @return the number of items in the queue. - */ - size_t size() const - { - guard_type lock(mutex_); - return size_; - } - - /** - * @return the number of items in the queue. - */ - bool empty() const - { - guard_type lock(mutex_); - return size_ == 0; - } - - /** - * @return the capacity of the queue. - */ - static constexpr size_t capacity() - { - return SIZE; - } -}; - -} // modemm17