Skip to content

Commit ab91156

Browse files
committed
use soft decision decoder for iq data
1 parent ac29912 commit ab91156

File tree

4 files changed

+89
-22
lines changed

4 files changed

+89
-22
lines changed

include/l2/lower_mac.hpp

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,22 @@ class LowerMac {
3131
std::optional<uint32_t> scrambling_code = std::nullopt);
3232
~LowerMac() = default;
3333

34+
/// Get the correct viterbi decoder either for hard decision for bit or soft decision for soft bits.
35+
/// \targ DataType with bool (bits) the hard decision decoder is returned, with int16_t we have soft bits and return
36+
/// the soft decision decoder
37+
template <typename DataType> [[nodiscard]] auto getViterbi() const -> const ViterbiCodec& {
38+
if constexpr (std::is_same_v<DataType, bool>) {
39+
return viter_bi_codec_1614_hard_decision_;
40+
}
41+
if constexpr (std::is_same_v<DataType, int16_t>) {
42+
return viter_bi_codec_1614_soft_decision_;
43+
}
44+
assert(false && "Compiling descramble with template paramater not bool or int16_t");
45+
}
46+
3447
/// handles the decoding of the synchronization bursts and once synchronized passes the data to the decoding of the
3548
/// channels. keeps track of the current network time
36-
/// \targ DataType with bool is selected we have bits, with int16_t we have symbols
49+
/// \targ DataType with bool is selected we have bits, with int16_t we have soft bits
3750
template <typename DataType>
3851
[[nodiscard]] auto process(std::vector<DataType> frame, BurstType burst_type) -> return_type {
3952
// Set to true if there was some decoding error in the lower MAC
@@ -61,8 +74,8 @@ class LowerMac {
6174
};
6275

6376
auto sb_bits = LowerMacCoding::viter_bi_decode_1614(
64-
viter_bi_codec_1614_, LowerMacCoding::depuncture23(LowerMacCoding::deinterleave(
65-
LowerMacCoding::descramble(sb_input, 0x0003), 11)));
77+
getViterbi<DataType>(), LowerMacCoding::depuncture23(LowerMacCoding::deinterleave(
78+
LowerMacCoding::descramble(sb_input, 0x0003), 11)));
6679

6780
if (LowerMacCoding::check_crc_16_ccitt<76>(sb_bits)) {
6881
current_sync = BroadcastSynchronizationChannel(
@@ -140,8 +153,8 @@ class LowerMac {
140153
}
141154

142155
auto bkn2_bits = LowerMacCoding::viter_bi_decode_1614(
143-
viter_bi_codec_1614_, LowerMacCoding::depuncture23(LowerMacCoding::deinterleave(
144-
LowerMacCoding::descramble(bkn2_input, bsc.scrambling_code), 101)));
156+
getViterbi<DataType>(), LowerMacCoding::depuncture23(LowerMacCoding::deinterleave(
157+
LowerMacCoding::descramble(bkn2_input, bsc.scrambling_code), 101)));
145158

146159
slots = Slots(burst_type, SlotType::kOneSubslot,
147160
Slot(LogicalChannelDataAndCrc{
@@ -174,7 +187,7 @@ class LowerMac {
174187
auto bkn1_descrambled_bits = LowerMacCoding::softbits_to_bits(bkn1_descrambled);
175188

176189
auto bkn1_bits = LowerMacCoding::viter_bi_decode_1614(
177-
viter_bi_codec_1614_,
190+
getViterbi<DataType>(),
178191
LowerMacCoding::depuncture23(LowerMacCoding::deinterleave(bkn1_descrambled, 103)));
179192

180193
if (aach.downlink_usage == DownlinkUsage::Traffic) {
@@ -216,8 +229,8 @@ class LowerMac {
216229
};
217230

218231
auto bkn1_bits = LowerMacCoding::viter_bi_decode_1614(
219-
viter_bi_codec_1614_, LowerMacCoding::depuncture23(LowerMacCoding::deinterleave(
220-
LowerMacCoding::descramble(bkn1_input, bsc.scrambling_code), 101)));
232+
getViterbi<DataType>(), LowerMacCoding::depuncture23(LowerMacCoding::deinterleave(
233+
LowerMacCoding::descramble(bkn1_input, bsc.scrambling_code), 101)));
221234

222235
std::array<DataType, 216> bkn2_input{};
223236
for (auto i = 0; i < 216; i++) {
@@ -227,7 +240,7 @@ class LowerMac {
227240
auto bkn2_deinterleaved =
228241
LowerMacCoding::deinterleave(LowerMacCoding::descramble(bkn2_input, bsc.scrambling_code), 101);
229242
auto bkn2_deinterleaved_bits = LowerMacCoding::softbits_to_bits(bkn2_deinterleaved);
230-
auto bkn2_bits = LowerMacCoding::viter_bi_decode_1614(viter_bi_codec_1614_,
243+
auto bkn2_bits = LowerMacCoding::viter_bi_decode_1614(getViterbi<DataType>(),
231244
LowerMacCoding::depuncture23(bkn2_deinterleaved));
232245

233246
// Half slot traffic channel defines type 3 bits (deinterleaved)
@@ -274,8 +287,8 @@ class LowerMac {
274287
};
275288

276289
auto cb_bits = LowerMacCoding::viter_bi_decode_1614(
277-
viter_bi_codec_1614_, LowerMacCoding::depuncture23(LowerMacCoding::deinterleave(
278-
LowerMacCoding::descramble(cb_input, bsc.scrambling_code), 13)));
290+
getViterbi<DataType>(), LowerMacCoding::depuncture23(LowerMacCoding::deinterleave(
291+
LowerMacCoding::descramble(cb_input, bsc.scrambling_code), 13)));
279292

280293
// SCH/HU
281294
slots = Slots(burst_type, SlotType::kOneSubslot,
@@ -297,7 +310,7 @@ class LowerMac {
297310
auto bkn1_descrambled_bits = LowerMacCoding::softbits_to_bits(bkn1_descrambled);
298311

299312
auto bkn1_bits = LowerMacCoding::viter_bi_decode_1614(
300-
viter_bi_codec_1614_,
313+
getViterbi<DataType>(),
301314
LowerMacCoding::depuncture23(LowerMacCoding::deinterleave(bkn1_descrambled, 103)));
302315

303316
slots = Slots(
@@ -321,8 +334,8 @@ class LowerMac {
321334
}
322335

323336
auto bkn1_bits = LowerMacCoding::viter_bi_decode_1614(
324-
viter_bi_codec_1614_, LowerMacCoding::depuncture23(LowerMacCoding::deinterleave(
325-
LowerMacCoding::descramble(bkn1_input, bsc.scrambling_code), 101)));
337+
getViterbi<DataType>(), LowerMacCoding::depuncture23(LowerMacCoding::deinterleave(
338+
LowerMacCoding::descramble(bkn1_input, bsc.scrambling_code), 101)));
326339

327340
std::array<DataType, 216> bkn2_input{};
328341
for (auto i = 0; i < 216; i++) {
@@ -332,7 +345,7 @@ class LowerMac {
332345
auto bkn2_deinterleaved =
333346
LowerMacCoding::deinterleave(LowerMacCoding::descramble(bkn2_input, bsc.scrambling_code), 101);
334347
auto bkn2_deinterleaved_bits = LowerMacCoding::softbits_to_bits(bkn2_deinterleaved);
335-
auto bkn2_bits = LowerMacCoding::viter_bi_decode_1614(viter_bi_codec_1614_,
348+
auto bkn2_bits = LowerMacCoding::viter_bi_decode_1614(getViterbi<DataType>(),
336349
LowerMacCoding::depuncture23(bkn2_deinterleaved));
337350

338351
// STCH + TCH
@@ -361,7 +374,8 @@ class LowerMac {
361374
return *slots;
362375
}
363376

364-
const ViterbiCodec viter_bi_codec_1614_;
377+
const ViterbiCodecHardDecision viter_bi_codec_1614_hard_decision_;
378+
const ViterbiCodecSoftDecision viter_bi_codec_1614_soft_decision_;
365379

366380
std::unique_ptr<LowerMacMetrics> metrics_;
367381

include/utils/viter_bi_codec.hpp

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,26 @@
2020

2121
class ViterbiCodec {
2222
public:
23-
ViterbiCodec() = default;
24-
[[nodiscard]] auto Decode(const std::vector<int16_t>& bits) const -> std::vector<uint8_t>;
23+
virtual ~ViterbiCodec() = default;
2524

2625
static constexpr size_t K = 5;
2726
static constexpr size_t R = 4;
2827

29-
private:
28+
[[nodiscard]] virtual auto Decode(const std::vector<int16_t>& bits) const -> std::vector<uint8_t> = 0;
29+
30+
protected:
31+
ViterbiCodec() = default;
32+
3033
const std::vector<uint8_t> G = {19, 29, 23, 27};
34+
};
3135

36+
class ViterbiCodecHardDecision : public ViterbiCodec {
37+
public:
38+
ViterbiCodecHardDecision() = default;
39+
40+
[[nodiscard]] auto Decode(const std::vector<int16_t>& bits) const -> std::vector<uint8_t> override;
41+
42+
private:
3243
const int16_t soft_decision_high = +1;
3344
const int16_t soft_decision_low = -1;
3445
const uint16_t max_error = static_cast<uint16_t>(soft_decision_high - soft_decision_low) * static_cast<uint16_t>(R);
@@ -43,3 +54,24 @@ class ViterbiCodec {
4354
const ViterbiBranchTable<K, R, int16_t> branch_table =
4455
ViterbiBranchTable<K, R, int16_t>(G.data(), soft_decision_high, soft_decision_low);
4556
};
57+
58+
class ViterbiCodecSoftDecision : public ViterbiCodec {
59+
public:
60+
ViterbiCodecSoftDecision() = default;
61+
[[nodiscard]] auto Decode(const std::vector<int16_t>& bits) const -> std::vector<uint8_t> override;
62+
63+
private:
64+
const int16_t soft_decision_high = +127;
65+
const int16_t soft_decision_low = -127;
66+
const uint16_t max_error = static_cast<uint16_t>(soft_decision_high - soft_decision_low) * static_cast<uint16_t>(R);
67+
const uint16_t error_margin = max_error * static_cast<uint16_t>(5U);
68+
69+
const ViterbiDecoder_Config<uint16_t> config = {
70+
.soft_decision_max_error = max_error,
71+
.initial_start_error = std::numeric_limits<uint16_t>::min(),
72+
.initial_non_start_error = static_cast<uint16_t>(std::numeric_limits<uint16_t>::min() + error_margin),
73+
.renormalisation_threshold = static_cast<uint16_t>(std::numeric_limits<uint16_t>::max() - error_margin)};
74+
75+
const ViterbiBranchTable<K, R, int16_t> branch_table =
76+
ViterbiBranchTable<K, R, int16_t>(G.data(), soft_decision_high, soft_decision_low);
77+
};

src/iq_stream_decoder.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ auto IQStreamDecoder::symbols_to_softstream(iterator_type it) -> std::vector<int
7070
// symbol 1:
7171
// real > 0 -> 0 -> -1
7272
// real <= 0 -> 1 -> 1
73-
soft_bits[i * 2] = -1 * it->imag();
74-
soft_bits[(i * 2) + 1] = -1 * it->real();
73+
soft_bits[i * 2] = -127 * it->imag();
74+
soft_bits[(i * 2) + 1] = -127 * it->real();
7575
}
7676
return soft_bits;
7777
}

src/utils/viter_bi_codec.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,28 @@
99

1010
#include "utils/viter_bi_codec.hpp"
1111

12-
auto ViterbiCodec::Decode(const std::vector<int16_t>& bits) const -> std::vector<uint8_t> {
12+
auto ViterbiCodecHardDecision::Decode(const std::vector<int16_t>& bits) const -> std::vector<uint8_t> {
13+
auto vitdec = ViterbiDecoder_Core<K, R, uint16_t, int16_t>(branch_table, config);
14+
using Decoder = ViterbiDecoder_SSE_u16<K, R>;
15+
16+
const size_t total_bits = bits.size() / R;
17+
const size_t total_tail_bits = K - 1u;
18+
const size_t total_data_bits = total_bits - total_tail_bits;
19+
20+
std::vector<uint8_t> output_bytes(total_bits / 8);
21+
22+
vitdec.set_traceback_length(total_data_bits);
23+
24+
vitdec.reset();
25+
Decoder::template update<uint64_t>(vitdec, bits.data(), bits.size());
26+
vitdec.chainback(output_bytes.data(), total_data_bits, 0);
27+
const uint64_t error = vitdec.get_error();
28+
// std::cout << "error=" << error << std::endl;
29+
30+
return output_bytes;
31+
}
32+
33+
auto ViterbiCodecSoftDecision::Decode(const std::vector<int16_t>& bits) const -> std::vector<uint8_t> {
1334
auto vitdec = ViterbiDecoder_Core<K, R, uint16_t, int16_t>(branch_table, config);
1435
using Decoder = ViterbiDecoder_SSE_u16<K, R>;
1536

0 commit comments

Comments
 (0)