Skip to content

Commit

Permalink
implement first version of synchronization of bursts. very unperforma…
Browse files Browse the repository at this point in the history
…nt, but a start
  • Loading branch information
marenz2569 committed Jul 3, 2023
1 parent 5e91c93 commit fe70e99
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 49 deletions.
8 changes: 4 additions & 4 deletions include/fixed_queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ class FixedQueue : public std::queue<T, Container> {

void pop(const T& value) { std::logic_error("Function not implemented"); }

typename Container::iterator begin() { return this->c.begin(); }
typename Container::const_iterator cbegin() { return this->c.cbegin(); }

typename Container::reverse_iterator rbegin() { return this->c.rbegin(); }
typename Container::const_reverse_iterator crbegin() { return this->c.crbegin(); }

typename Container::iterator end() { return this->c.end(); }
typename Container::const_iterator cend() { return this->c.cend(); }

typename Container::reverse_iterator rend() { return this->c.rend(); }
typename Container::const_reverse_iterator crend() { return this->c.crend(); }
};
14 changes: 11 additions & 3 deletions include/iq_stream_decoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include <bit_stream_decoder.hpp>
#include <fixed_queue.hpp>
#include <l2/lower_mac.hpp>

/**
* Tetra downlink decoder for PI/4-DQPSK modulation
Expand All @@ -21,35 +22,42 @@
*/
class IQStreamDecoder {
public:
IQStreamDecoder(std::shared_ptr<BitStreamDecoder> bit_stream_decoder, bool is_uplink)
: bit_stream_decoder_(bit_stream_decoder)
, is_uplink_(is_uplink){};
IQStreamDecoder(std::shared_ptr<LowerMac> lower_mac, std::shared_ptr<BitStreamDecoder> bit_stream_decoder,
bool is_uplink);
~IQStreamDecoder() = default;

void process_complex(std::complex<float> symbol) noexcept;

private:
std::complex<float> hard_decision(std::complex<float> symbol);
std::vector<uint8_t> symbols_to_bitstream(std::vector<std::complex<float>> const& stream);

std::vector<std::complex<float>> convolve_valid(std::vector<std::complex<float>> const& a,
std::vector<std::complex<float>> const& b);

std::vector<std::complex<float>> channel_estimation(std::vector<std::complex<float>> const& stream,
std::vector<std::complex<float>> const& pilots);

FixedQueue<std::complex<float>, 300> symbol_buffer_;
FixedQueue<std::complex<float>, 300> symbol_buffer_hard_decision_;

// 9.4.4.3.2 Normal training sequence
const std::vector<std::complex<float>> training_seq_n_ = {{-1, -1}, {-1, 1}, {1, 1}, {1, 1}, {-1, -1}, {1, -1},
{1, -1}, {-1, 1}, {-1, -1}, {-1, 1}, {1, 1}};
std::vector<std::complex<float>> training_seq_n_reversed_conj_{};
const std::vector<std::complex<float>> training_seq_p_ = {{-1.0, 1.0}, {-1.0, -1.0}, {1.0, -1.0}, {1.0, -1.0},
{-1.0, 1.0}, {1.0, 1.0}, {1.0, 1.0}, {-1.0, -1.0},
{-1.0, 1.0}, {-1.0, -1.0}, {1.0, -1.0}};
std::vector<std::complex<float>> training_seq_p_reversed_conj_{};
// 9.4.4.3.3 Extended training sequence
const std::vector<std::complex<float>> training_seq_x_ = {
{1.0, -1.0}, {-1.0, 1.0}, {-1.0, -1.0}, {-1.0, 1.0}, {1.0, 1.0}, {1.0, 1.0}, {-1.0, -1.0}, {1.0, -1.0},
{1.0, -1.0}, {-1.0, 1.0}, {-1.0, -1.0}, {-1.0, 1.0}, {1.0, 1.0}, {1.0, 1.0}, {-1.0, -1.0}};
std::vector<std::complex<float>> training_seq_x_reversed_conj_{};

const float SEQUENCE_DETECTION_THRESHOLD = 1.5;

std::shared_ptr<LowerMac> lower_mac_{};
std::shared_ptr<BitStreamDecoder> bit_stream_decoder_{};

bool is_uplink_{};
Expand Down
3 changes: 2 additions & 1 deletion src/decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ Decoder::Decoder(unsigned receive_port, unsigned send_port, bool packed, std::op

lower_mac_ = std::make_shared<LowerMac>(reporter_);
bit_stream_decoder_ = std::make_shared<BitStreamDecoder>(lower_mac_, uplink_scrambling_code_.has_value());
iq_stream_decoder_ = std::make_unique<IQStreamDecoder>(bit_stream_decoder_, uplink_scrambling_code_.has_value());
iq_stream_decoder_ =
std::make_unique<IQStreamDecoder>(lower_mac_, bit_stream_decoder_, uplink_scrambling_code_.has_value());

if (uplink_scrambling_code_.has_value()) {
// set scrambling_code for uplink
Expand Down
146 changes: 105 additions & 41 deletions src/iq_stream_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,23 @@
* Tassilo Tanneberger
*/

#include <thread>

#include <iq_stream_decoder.hpp>

IQStreamDecoder::IQStreamDecoder(std::shared_ptr<LowerMac> lower_mac,
std::shared_ptr<BitStreamDecoder> bit_stream_decoder, bool is_uplink)
: lower_mac_(lower_mac)
, bit_stream_decoder_(bit_stream_decoder)
, is_uplink_(is_uplink) {
std::transform(training_seq_n_.crbegin(), training_seq_n_.crend(),
std::back_inserter(training_seq_n_reversed_conj_), [](auto v) { return std::conj(v); });
std::transform(training_seq_p_.crbegin(), training_seq_p_.crend(),
std::back_inserter(training_seq_p_reversed_conj_), [](auto v) { return std::conj(v); });
std::transform(training_seq_x_.crbegin(), training_seq_x_.crend(),
std::back_inserter(training_seq_x_reversed_conj_), [](auto v) { return std::conj(v); });
}

std::complex<float> IQStreamDecoder::hard_decision(std::complex<float> symbol) {
if (symbol.real() > 0) {
if (symbol.imag() > 0) {
Expand All @@ -25,6 +40,40 @@ std::complex<float> IQStreamDecoder::hard_decision(std::complex<float> symbol) {
}
}

std::vector<uint8_t> IQStreamDecoder::symbols_to_bitstream(std::vector<std::complex<float>> const& stream) {
std::vector<uint8_t> bits;

for (auto it = stream.begin(); it != stream.end(); it++) {

auto real = it->real();
auto imag = it->imag();

if (real > 0.0) {
if (imag > 0.0) {
// I
bits.push_back(0);
bits.push_back(0);
} else {
// IV
bits.push_back(1);
bits.push_back(0);
}
} else {
if (imag > 0.0) {
// II
bits.push_back(0);
bits.push_back(1);
} else {
// III
bits.push_back(1);
bits.push_back(1);
}
}
}

return bits;
}

std::vector<std::complex<float>> IQStreamDecoder::convolve_valid(std::vector<std::complex<float>> const& a,
std::vector<std::complex<float>> const& b) {
std::vector<std::complex<float>> res;
Expand All @@ -48,6 +97,12 @@ std::vector<std::complex<float>> IQStreamDecoder::convolve_valid(std::vector<std
return res;
}

std::vector<std::complex<float>> IQStreamDecoder::channel_estimation(std::vector<std::complex<float>> const& stream,
std::vector<std::complex<float>> const& pilots) {
// TODO: implement channel estimation
return stream;
}

void IQStreamDecoder::process_complex(std::complex<float> symbol) noexcept {
if (is_uplink_) {
// Control Uplink Burst or Normal Uplink Burst
Expand All @@ -56,55 +111,64 @@ void IQStreamDecoder::process_complex(std::complex<float> symbol) noexcept {

// convolve hard_decision with flipped conjugate of n, p and x and check if abs > SEQUENCE_DETECTION_THRESHOLD
// to find potential correlation peaks
auto find_n =
convolve_valid({symbol_buffer_hard_decision_.begin(), symbol_buffer_hard_decision_.end()}, training_seq_n_);
auto find_p =
convolve_valid({symbol_buffer_hard_decision_.begin(), symbol_buffer_hard_decision_.end()}, training_seq_p_);
auto find_x =
convolve_valid({symbol_buffer_hard_decision_.begin(), symbol_buffer_hard_decision_.end()}, training_seq_x_);

//
// 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];
// 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];
// find CUB
// 2 tail + 42 coded symbols + middle of 15 training sequence (8) = 52
if (std::abs(find_x[51]) > SEQUENCE_DETECTION_THRESHOLD) {
// potentially found CUB
std::cout << "Potential CUB found" << std::endl;
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];

auto start = symbol_buffer_.cbegin();

if (std::abs(find_x) >= SEQUENCE_DETECTION_THRESHOLD) {
// std::cout << "Potential CUB found" << std::endl;

auto end = start;
std::advance(end, 103);

auto corrected = channel_estimation({start, end}, training_seq_x_reversed_conj_);
lower_mac_->process(symbols_to_bitstream(corrected), BurstType::ControlUplinkBurst);
}

// find NUB
// 2 tail + 108 coded symbols + middle of 11 training sequence (6) = 116
if (std::abs(find_p[115]) > SEQUENCE_DETECTION_THRESHOLD) {
std::cout << "Potential NUB_Split found" << std::endl;
if (std::abs(find_p) >= SEQUENCE_DETECTION_THRESHOLD) {
// std::cout << "Potential NUB_Split found" << std::endl;

auto end = start;
std::advance(end, 231);

auto corrected = channel_estimation({start, end}, training_seq_p_reversed_conj_);
lower_mac_->process(symbols_to_bitstream(corrected), BurstType::NormalUplinkBurstSplit);
}

if (std::abs(find_n[115]) > SEQUENCE_DETECTION_THRESHOLD &&
std::abs(find_x[115]) <= SEQUENCE_DETECTION_THRESHOLD) {
std::cout << "Potential NUB found" << std::endl;
if (std::abs(find_n) >= SEQUENCE_DETECTION_THRESHOLD) {
// std::cout << "Potential NUB found" << std::endl;

auto end = start;
std::advance(end, 231);

auto corrected = channel_estimation({start, end}, training_seq_n_reversed_conj_);
lower_mac_->process(symbols_to_bitstream(corrected), BurstType::NormalUplinkBurst);
}
} else {
// Simple hard decission symbol mapper for now...
auto real = symbol.real();
auto imag = symbol.imag();

if (real > 0.0) {
if (imag > 0.0) {
// I
bit_stream_decoder_->process_bit(0);
bit_stream_decoder_->process_bit(0);
} else {
// IV
bit_stream_decoder_->process_bit(1);
bit_stream_decoder_->process_bit(0);
}
} else {
if (imag > 0.0) {
// II
bit_stream_decoder_->process_bit(0);
bit_stream_decoder_->process_bit(1);
} else {
// III
bit_stream_decoder_->process_bit(1);
bit_stream_decoder_->process_bit(1);
}
auto bits = symbols_to_bitstream({symbol});
for (auto it = bits.begin(); it != bits.end(); ++it) {
bit_stream_decoder_->process_bit(*it);
}
}
}

0 comments on commit fe70e99

Please sign in to comment.