satdump/src-core/common/codings/viterbi/depuncture.cpp
2021-11-20 14:17:56 +01:00

82 lines
2.8 KiB
C++

/* -*- c++ -*- */
/*
* Copyright 2013-2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
#include "depuncture.h"
#include <volk/volk.h>
#include <string>
namespace fec
{
depuncture_bb_impl::depuncture_bb_impl(int puncsize, int puncpat, int delay, uint8_t symbol)
: d_puncsize(puncsize),
d_delay(delay),
d_sym(symbol)
{
// Create a mask of all 1's of puncsize length
int mask = 0;
for (int i = 0; i < d_puncsize; i++)
mask |= 1 << i;
// Rotate the pattern for the delay value; then mask it if there
// are any excess 1's in the pattern.
for (int i = 0; i < d_delay; ++i)
puncpat = ((puncpat & 1) << (d_puncsize - 1)) + (puncpat >> 1);
d_puncpat = puncpat & mask;
// Calculate the number of holes in the pattern. The mask is all
// 1's given puncsize and puncpat is a pattern with >= puncsize
// 0's (masked to ensure this). The difference between the
// number of 1's in the mask and the puncpat is the number of
// holes.
uint32_t count_mask = 0, count_pat = 0;
volk_32u_popcnt(&count_mask, static_cast<uint32_t>(mask));
volk_32u_popcnt(&count_pat, static_cast<uint32_t>(d_puncpat));
d_puncholes = count_mask - count_pat;
}
depuncture_bb_impl::~depuncture_bb_impl() {}
int depuncture_bb_impl::fixed_rate_ninput_to_noutput(int ninput)
{
return std::lround((d_puncsize / (double)(d_puncsize - d_puncholes)) * ninput);
}
int depuncture_bb_impl::fixed_rate_noutput_to_ninput(int noutput)
{
return std::lround(((d_puncsize - d_puncholes) / (double)(d_puncsize)) * noutput);
}
void depuncture_bb_impl::forecast(int noutput_items, int &ninput_items_required)
{
ninput_items_required = std::lround(((d_puncsize - d_puncholes) / (double)(d_puncsize)) * noutput_items);
}
int depuncture_bb_impl::general_work(int ninput_items, uint8_t *input_items, uint8_t *output_items)
{
d_buffer.insert(d_buffer.end(), &input_items[0], &input_items[ninput_items]);
int noutput_items = std::lround(d_buffer.size() / ((d_puncsize - d_puncholes) / (double)(d_puncsize)));
int consumed = 0;
for (int i = 0, k = 0; i < noutput_items / d_puncsize; ++i)
{
for (int j = 0; j < d_puncsize; ++j)
{
output_items[i * d_puncsize + j] = ((d_puncpat >> (d_puncsize - 1 - j)) & 1) ? d_buffer[k++] : d_sym;
if (((d_puncpat >> (d_puncsize - 1 - j)) & 1))
consumed++;
}
}
d_buffer.erase(d_buffer.begin(), d_buffer.begin() + consumed);
return noutput_items;
}
} /* namespace fec */