M17: M17Randomizer code cleanup

pull/1370/head
f4exb 2022-07-31 04:54:39 +02:00
rodzic ca24d1bc57
commit e29581a0b2
7 zmienionych plików z 38 dodań i 307 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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<decltype(trellis_), 4> viterbi_{trellis_};

Wyświetl plik

@ -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<uint8_t, 25> packet
)
{
M17Randomizer<368> randomizer;
M17Randomizer randomizer;
PolynomialInterleaver<45, 92, 368> interleaver;
std::array<uint8_t, 26> packet_assembly;
@ -446,7 +446,7 @@ public:
static void interleave_and_randomize(std::array<int8_t, 368>& punctured)
{
M17Randomizer<368> randomizer;
M17Randomizer randomizer;
PolynomialInterleaver<45, 92, 368> interleaver;
interleaver.interleave(punctured);

Wyświetl plik

@ -0,0 +1,14 @@
#include "M17Randomizer.h"
namespace modemm17
{
const std::array<uint8_t, 46> M17Randomizer::DC = std::array<uint8_t, 46>{
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};
}

Wyświetl plik

@ -9,28 +9,14 @@
namespace modemm17
{
namespace detail
{
// M17 randomization matrix.
static const std::array<uint8_t, 46> DC = std::array<uint8_t, 46>{
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 <size_t N = 368>
struct M17Randomizer
{
std::array<int8_t, N> dc_;
std::array<int8_t, 368> 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<int8_t, N>& frame)
void operator()(std::array<int8_t, 368>& 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<int8_t, N>& frame)
void randomize(std::array<int8_t, 368>& frame)
{
for (size_t i = 0; i != N; ++i)
for (size_t i = 0; i != 368; ++i)
{
frame[i] ^= (dc_[i] == -1);
}
}
};
template <size_t N = 46>
struct M17ByteRandomizer
{
// Randomize and derandomize are the same operation.
void operator()(std::array<uint8_t, N>& 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<uint8_t, 46> DC;
};

Wyświetl plik

@ -21,24 +21,22 @@ template <size_t SampleRate, size_t Frequency, size_t Accuracy = 1000>
class SlidingDFT
{
public:
using ComplexType = std::complex<float>;
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<float>{0, 1} * pi2 * kth);
}
ComplexType operator()(float sample)
std::complex<float> 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<float> 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<float> coeff_;
std::array<float, (SampleRate / Accuracy)> samples_;
ComplexType result_{0,0};
std::complex<float> result_{0,0};
size_t index_ = 0;
size_t prev_index_ = (SampleRate / Accuracy) - 1;
};
@ -69,8 +67,7 @@ template <size_t SampleRate, size_t N, size_t K>
class NSlidingDFT
{
public:
using ComplexType = std::complex<float>;
using result_type = std::array<ComplexType, K>;
using result_type = std::array<std::complex<float>, K>;
/**
* Construct the DFT with an array of frequencies. These frequencies
@ -107,17 +104,17 @@ public:
}
private:
const std::array<ComplexType, K> coeff_;
const std::array<std::complex<float>, K> coeff_;
std::array<float, N> samples_;
std::array<ComplexType, K> result_{0,0};
std::array<std::complex<float>, K> result_{0,0};
size_t index_ = 0;
size_t prev_index_ = N - 1;
static constexpr std::array<ComplexType, K>
static constexpr std::array<std::complex<float>, K>
make_coefficients(const std::array<size_t, K>& frequencies)
{
ComplexType j = ComplexType{0, 1};
std::array<ComplexType, K> result;
std::complex<float> j = std::complex<float>{0, 1};
std::array<std::complex<float>, K> result;
float pi2 = M_PI * 2.0f;
for (size_t i = 0; i != K; ++i)
{

Wyświetl plik

@ -1,251 +0,0 @@
#pragma once
#include <stdexcept>
#include <list>
#include <iterator>
#include <algorithm>
#include <thread>
#include <condition_variable>
#include <mutex>
namespace modemm17
{
/**
* A thread-safe queue
*/
template <typename T, size_t SIZE>
class queue
{
private:
using mutex_type = std::mutex;
using lock_type = std::unique_lock<mutex_type>;
using guard_type = std::lock_guard<mutex_type>;
enum class State {OPEN, CLOSING, CLOSED};
std::list<T> 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<class Clock>
bool get_until(reference val, std::chrono::time_point<Clock> 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<class Rep = int64_t, class Period = std::ratio<1>>
bool get(reference val, std::chrono::duration<Rep, Period> timeout = std::chrono::duration<Rep, Period>::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<typename U, class Rep = int64_t, class Period = std::ratio<1>>
bool put(U&& val, std::chrono::duration<Rep, Period> timeout = std::chrono::duration<Rep, Period>::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<U>(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