2021-11-20 14:17:56 +01:00
|
|
|
#include "cc_encoder.h"
|
2021-03-31 12:16:38 +02:00
|
|
|
#include "cc_common.h"
|
|
|
|
|
#include <volk/volk.h>
|
|
|
|
|
#include <volk/volk_typedefs.h>
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
namespace viterbi
|
2021-03-31 12:16:38 +02:00
|
|
|
{
|
2022-08-15 17:07:52 +02:00
|
|
|
CCEncoder::CCEncoder(int frame_size, int k, int rate, std::vector<int> polys, int start_state)
|
|
|
|
|
: d_rate(rate),
|
|
|
|
|
d_k(k),
|
|
|
|
|
d_polys(polys),
|
|
|
|
|
d_start_state(start_state)
|
2021-03-31 12:16:38 +02:00
|
|
|
{
|
2022-08-15 17:07:52 +02:00
|
|
|
if (static_cast<size_t>(d_rate) != d_polys.size())
|
|
|
|
|
throw std::runtime_error("cc_encoder: Number of polynomials must be the same as the value of rate");
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
if (d_rate < 2)
|
|
|
|
|
throw std::runtime_error("cc_encoder: inverse rate r must be > 2");
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
if (k < 2 || k > 31)
|
|
|
|
|
throw std::runtime_error("cc_encoder: constraint length K must in be the range [2, 31]");
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
if (d_start_state >= (1u << (d_k - 1)))
|
|
|
|
|
throw std::runtime_error("cc_encoder: start state is invalid; must be in range [0, 2^(K-1)-1] where K is the constraint length");
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
if (frame_size < 1)
|
|
|
|
|
throw std::runtime_error("cc_encoder: frame_size must be > 0");
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
partab_init();
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
d_max_frame_size = frame_size;
|
|
|
|
|
set_frame_size(frame_size);
|
|
|
|
|
}
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
CCEncoder::~CCEncoder()
|
|
|
|
|
{
|
|
|
|
|
}
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
bool CCEncoder::set_frame_size(unsigned int frame_size)
|
|
|
|
|
{
|
|
|
|
|
bool ret = true;
|
|
|
|
|
if (frame_size > d_max_frame_size)
|
2021-11-20 14:17:56 +01:00
|
|
|
{
|
2022-08-15 17:07:52 +02:00
|
|
|
frame_size = d_max_frame_size;
|
|
|
|
|
ret = false;
|
2021-11-20 14:17:56 +01:00
|
|
|
}
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
d_frame_size = frame_size;
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
d_output_size = d_rate * d_frame_size;
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
return ret;
|
|
|
|
|
}
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
double CCEncoder::rate()
|
|
|
|
|
{
|
|
|
|
|
return static_cast<double>(d_rate);
|
|
|
|
|
}
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
int CCEncoder::parity(int x)
|
|
|
|
|
{
|
|
|
|
|
x ^= (x >> 16);
|
|
|
|
|
x ^= (x >> 8);
|
|
|
|
|
return parityb(x);
|
|
|
|
|
}
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
int CCEncoder::parityb(unsigned char x)
|
|
|
|
|
{
|
|
|
|
|
return Partab[x];
|
|
|
|
|
}
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
void CCEncoder::partab_init(void)
|
|
|
|
|
{
|
|
|
|
|
int i, cnt, ti;
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
/* Initialize parity lookup table */
|
|
|
|
|
for (i = 0; i < 256; i++)
|
2021-03-31 12:16:38 +02:00
|
|
|
{
|
2022-08-15 17:07:52 +02:00
|
|
|
cnt = 0;
|
|
|
|
|
ti = i;
|
|
|
|
|
while (ti)
|
2021-03-31 12:16:38 +02:00
|
|
|
{
|
2022-08-15 17:07:52 +02:00
|
|
|
if (ti & 1)
|
|
|
|
|
cnt++;
|
|
|
|
|
ti >>= 1;
|
2021-03-31 12:16:38 +02:00
|
|
|
}
|
2022-08-15 17:07:52 +02:00
|
|
|
Partab[i] = cnt & 1;
|
2021-03-31 12:16:38 +02:00
|
|
|
}
|
2022-08-15 17:07:52 +02:00
|
|
|
}
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
void CCEncoder::work(uint8_t *in, uint8_t *out)
|
|
|
|
|
{
|
|
|
|
|
unsigned int my_state = d_start_state;
|
2021-03-31 12:16:38 +02:00
|
|
|
|
2022-08-15 17:07:52 +02:00
|
|
|
for (unsigned int i = 0; i < d_frame_size; ++i)
|
|
|
|
|
{
|
|
|
|
|
my_state = (my_state << 1) | (in[i] & 1);
|
|
|
|
|
for (unsigned int j = 0; j < d_rate; ++j)
|
|
|
|
|
out[i * d_rate + j] = (d_polys[j] < 0) ^ parity(my_state & abs(d_polys[j])) ? 1 : 0;
|
2021-03-31 12:16:38 +02:00
|
|
|
}
|
2022-08-15 17:07:52 +02:00
|
|
|
|
|
|
|
|
d_start_state = my_state;
|
|
|
|
|
}
|
2022-08-20 15:20:27 +02:00
|
|
|
|
|
|
|
|
void CCEncoder::work(uint8_t *in, uint8_t *out, int size)
|
|
|
|
|
{
|
|
|
|
|
unsigned int my_state = d_start_state;
|
|
|
|
|
|
2022-09-09 13:13:10 +02:00
|
|
|
for (int i = 0; i < size; ++i)
|
2022-08-20 15:20:27 +02:00
|
|
|
{
|
|
|
|
|
my_state = (my_state << 1) | (in[i] & 1);
|
|
|
|
|
for (unsigned int j = 0; j < d_rate; ++j)
|
|
|
|
|
out[i * d_rate + j] = (d_polys[j] < 0) ^ parity(my_state & abs(d_polys[j])) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
d_start_state = my_state;
|
|
|
|
|
}
|
2022-08-15 17:07:52 +02:00
|
|
|
}
|