-
Notifications
You must be signed in to change notification settings - Fork 8
/
viterbi27.cpp
113 lines (97 loc) · 3.6 KB
/
viterbi27.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*
* viterbi27.cpp
*
* Created on: 04/11/2016
* Author: lucas
*/
#include "SatHelper/SIMD/MemoryOp.h"
extern "C" {
#include <correct.h>
#ifdef MEMORY_OP_X86
#include <correct-sse.h>
#endif
}
#include <SatHelper/viterbi27.h>
#include <memory.h>
#include <cstring>
#include <SatHelper/correlator.h>
#include <SatHelper/exceptions/ViterbiCreationException.h>
using namespace SatHelper;
Viterbi27::Viterbi27(int frameBits, int polyA, int polyB) {
this->frameBits = frameBits;
this->polynomials[0] = polyA;
this->polynomials[1] = polyB;
this->BER = 0;
this->calculateErrors = true;
if (SatHelper::Extensions::hasSSE4) {
#ifdef MEMORY_OP_X86
viterbi = correct_convolutional_sse_create(2, 7, new uint16_t[2] { (uint16_t)polyA, (uint16_t)polyB });
this->_encode = &Viterbi27::encode_sse4;
this->_decode = &Viterbi27::decode_sse4;
#endif
} else {
viterbi = correct_convolutional_create(2, 7, new uint16_t[2] { (uint16_t)polyA, (uint16_t)polyB });
this->_encode = &Viterbi27::encode_generic;
this->_decode = &Viterbi27::decode_generic;
}
if (viterbi == NULL) {
throw ViterbiCreationException();
}
this->checkDataPointer = new uint8_t[this->frameBits * 2];
}
Viterbi27::~Viterbi27() {
delete[] this->checkDataPointer;
}
void Viterbi27::encode_sse4(uint8_t *input, uint8_t *output) {
#ifdef MEMORY_OP_X86
const int l = correct_convolutional_sse_encode_len((correct_convolutional_sse *)viterbi, this->DecodedSize());
const int bl = l % 8 == 0 ? l / 8 : (l / 8) + 1;
uint8_t *data = new uint8_t[bl];
correct_convolutional_sse_encode((correct_convolutional_sse *)viterbi, input, this->DecodedSize(), data);
// Convert to soft bits
for (int i=0; i<bl && i*8 < this->EncodedSize(); i++) {
uint8_t d = data[i];
for (int z=7; z>=0; z--) {
output[i*8+(7-z)] = 0 - ( (d & (1 << z)) == 0);
}
}
delete[] data;
#endif
}
void Viterbi27::decode_sse4(uint8_t *input, uint8_t *output) {
#ifdef MEMORY_OP_X86
correct_convolutional_sse_decode_soft((correct_convolutional_sse *)viterbi, input, this->frameBits*2, output);
if (calculateErrors) {
this->encode_sse4(output, this->checkDataPointer);
this->BER = Viterbi27::calculateError(input, this->checkDataPointer, this->frameBits*2);
}
#endif
}
void Viterbi27::encode_generic(uint8_t *input, uint8_t *output) {
const int l = correct_convolutional_encode_len((correct_convolutional *)viterbi, this->DecodedSize());
const int bl = l % 8 == 0 ? l / 8 : (l / 8) + 1;
uint8_t *data = new uint8_t[bl];
correct_convolutional_encode((correct_convolutional *)viterbi, input, this->DecodedSize(), data);
// Convert to soft bits
for (int i=0; i<bl && i*8 < this->EncodedSize(); i++) {
uint8_t d = data[i];
for (int z=7; z>=0; z--) {
output[i*8+(7-z)] = 0 - ( (d & (1 << z)) == 0);
}
}
delete[] data;
}
void Viterbi27::decode_generic(uint8_t *input, uint8_t *output) {
correct_convolutional_decode_soft((correct_convolutional *)viterbi, input, this->frameBits*2, output);
if (calculateErrors) {
this->encode_generic(output, this->checkDataPointer);
this->BER = Viterbi27::calculateError(input, this->checkDataPointer, this->frameBits*2);
}
}
uint32_t Viterbi27::calculateError(uint8_t *original, uint8_t *corrected, int length) {
uint32_t errors = 0;
for (int i = 0; i < length; i++) {
errors += (uint32_t) Correlator::hardCorrelate(original[i], ~corrected[i]);
}
return errors;
}