summaryrefslogtreecommitdiff
path: root/gr-fec/lib/tpc_encoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gr-fec/lib/tpc_encoder.cc')
-rwxr-xr-xgr-fec/lib/tpc_encoder.cc334
1 files changed, 334 insertions, 0 deletions
diff --git a/gr-fec/lib/tpc_encoder.cc b/gr-fec/lib/tpc_encoder.cc
new file mode 100755
index 0000000000..94046540ae
--- /dev/null
+++ b/gr-fec/lib/tpc_encoder.cc
@@ -0,0 +1,334 @@
+#include <gnuradio/fec/tpc_encoder.h>
+#include <gnuradio/fec/tpc_common.h>
+#include <gnuradio/fec/generic_encoder.h>
+
+#include <math.h>
+#include <boost/assign/list_of.hpp>
+#include <volk/volk.h>
+#include <sstream>
+#include <stdio.h>
+#include <vector>
+
+#include <algorithm> // for std::reverse
+#include <string.h> // for memcpy
+
+
+/**
+ * This code borrows from the CML library for the CC Encode functionality,
+ * and for the RSC_Encode functionality. Please have a look @:
+ * https://code.google.com/p/iscml
+ *
+ */
+namespace gr {
+namespace fec {
+generic_encoder::sptr
+tpc_encoder::make(std::vector<int> row_polys, std::vector<int> col_polys, int krow, int kcol, int bval, int qval)
+{
+ return generic_encoder::sptr(new tpc_encoder(row_polys, col_polys, krow, kcol, bval, qval));
+}
+
+tpc_encoder::tpc_encoder (std::vector<int> row_polys, std::vector<int> col_polys, int krow, int kcol, int bval, int qval)
+ : d_rowpolys(row_polys), d_colpolys(col_polys), d_krow(krow), d_kcol(kcol),
+ d_bval(bval), d_qval(qval)
+{
+ // first we operate on data chunks of get_input_size()
+ // TODO: should we verify this and throw an error if it doesn't match? YES
+ // hwo do we do that?
+
+ // calculate the input and output sizes
+ inputSize = (d_krow*d_kcol - (d_bval+d_qval));
+ rowEncoder_K = ceil(log(d_rowpolys[0])/log(2)); // rowEncoder_K is the constraint length of the row encoder polynomial
+ rowEncoder_n = d_rowpolys.size();
+ rowEncoder_m = rowEncoder_K - 1;
+ colEncoder_K = ceil(log(d_colpolys[0])/log(2)); // colEncoder_K is the constraint length of the col encoder polynomial
+ colEncoder_n = d_colpolys.size();
+ colEncoder_m = colEncoder_K - 1;
+
+ outputSize = ((d_krow+rowEncoder_m)*rowEncoder_n)*((d_kcol+colEncoder_m)*colEncoder_n) - d_bval;
+
+ //DEBUG_PRINT("inputSize=%d outputSize=%d\n", inputSize, outputSize);
+ fp = fopen("c_encoder_output.txt", "w");
+
+ // resize internal matrices
+ rowNumStates = 1 << (rowEncoder_K-1); // 2^(row_mm)
+ colNumStates = 1 << (colEncoder_K-1); // 2^(col_mm)
+ rowOutputs.resize(2, std::vector<int>(rowNumStates,0));
+ rowNextStates.resize(2, std::vector<int>(rowNumStates,0));
+ colOutputs.resize(2, std::vector<int>(colNumStates,0));
+ colNextStates.resize(2, std::vector<int>(colNumStates,0));;
+
+ rowTail.resize(rowNumStates, 0);
+ colTail.resize(colNumStates, 0);
+
+ // precalculate the state transition matrix for the row polynomial
+ tpc_common::precomputeStateTransitionMatrix_RSCPoly(rowNumStates, d_rowpolys, rowEncoder_K, rowEncoder_n,
+ rowOutputs, rowNextStates);
+
+ // calculate the tail for the row
+ tpc_common::rsc_tail(rowTail, d_rowpolys, rowNumStates, rowEncoder_m);
+
+ // precalculate the state transition matrix for the column polynomial
+ tpc_common::precomputeStateTransitionMatrix_RSCPoly(colNumStates, d_colpolys, colEncoder_K, colEncoder_n,
+ colOutputs, colNextStates);
+ // calculate the tail for the col
+ tpc_common::rsc_tail(colTail, d_colpolys, colNumStates, colEncoder_m);
+
+ // pre-allocate memory we use for encoding
+ inputSizeWithPad = d_bval+d_qval+inputSize;
+ inputWithPad.resize(inputSizeWithPad, 0);
+
+ numRowsToEncode = inputSizeWithPad/d_krow; // this should be OK w/ integer division -- TODO: check this?
+ rowToEncode.resize(d_krow,0);
+ rowEncoded_block.resize(d_krow+(rowEncoder_m*rowEncoder_n), 0);
+ rowEncodedBits.resize(d_kcol, std::vector<float>(rowEncoder_m*rowEncoder_n,0) );
+
+ numColsToEncode = d_krow+(rowEncoder_m*rowEncoder_n);
+ colToEncode.resize(d_kcol,0);
+ colEncoded_block.resize(d_kcol+(colEncoder_m*colEncoder_n), 0);
+ colEncodedBits.resize(d_krow+(rowEncoder_m*rowEncoder_n), std::vector<float>(colEncoder_m*colEncoder_n,0) );
+}
+
+int tpc_encoder::get_output_size() {
+ return outputSize;
+}
+
+int tpc_encoder::get_input_size() {
+ return inputSize;
+}
+
+void tpc_encoder::block_conv_encode( std::vector<float> &output,
+ std::vector<unsigned char> input,
+ std::vector< std::vector<int> > transOutputVec,
+ std::vector< std::vector<int> > transNextStateVec,
+ std::vector<int> tail,
+ int KK,
+ int nn)
+{
+ int outsym, ii, jj;
+ int state = 0;
+ int LL = input.size();
+
+ std::vector<int> binVec(nn,0);
+
+ // encode data bits one bit at a time
+ for (ii=0; ii<LL; ii++) {
+
+ // determine the output symbol
+ outsym = transOutputVec[(int)input[ii]][state];
+ // determine the next state
+ state = transNextStateVec[(int)input[ii]][state];
+
+ // Convert symbol to a binary vector
+ tpc_common::itob( binVec, outsym, nn );
+
+ // Assign to output : TODO: investigate using memcpy for this?
+ for (jj=0;jj<nn;jj++) {
+ output[nn*ii+jj] = (float) binVec[jj];
+ }
+ }
+
+ // encode tail
+ for (ii=LL;ii<LL+KK-1;ii++) {
+
+ // determine the output symbol
+ outsym = transOutputVec[tail[state]][state];
+ // determine the next state
+ state = transNextStateVec[tail[state]][state];
+
+ // Convert symbol to a binary vector
+ tpc_common::itob( binVec, outsym, nn );
+
+ // Assign to output : TODO: investigate using memcpy for this?
+ for (jj=0;jj<nn;jj++) {
+ output[nn*ii+jj] = (float) binVec[jj];
+ }
+ }
+}
+
+void tpc_encoder::generic_work(void *inBuffer, void *outBuffer) {
+ const unsigned char *in = (const unsigned char *) inBuffer;
+ float *out = (float *) outBuffer;
+
+ int ii, jj; // indexing var
+ int tmp;
+
+ //DEBUG_PRINT_UCHAR_ARRAY(in, inputSize);
+
+ // TODO: probably a better way to do this than memcpy?
+ memcpy(&inputWithPad[d_bval+d_qval], in, sizeof(unsigned char)*inputSize);
+
+ //DEBUG_PRINT("Input with Pad -->\n");
+ //DEBUG_PRINT_UCHAR_ARRAY(&inputWithPad[0], inputSizeWithPad);
+ //DEBUG_PRINT_F(fp, "Input with Pad -->\n");
+ //DEBUG_PRINT_UCHAR_ARRAY_F(fp, &inputWithPad[0], inputSizeWithPad);
+
+ // encode the row data
+ for(ii=0; ii<numRowsToEncode; ii++) {
+ // populate rowToEncode
+ memcpy(&rowToEncode[0], &inputWithPad[ii*d_krow], sizeof(unsigned char)*d_krow);
+
+ //DEBUG_PRINT("Encoding row=[%d] -->\n",ii);
+ //DEBUG_PRINT_UCHAR_ARRAY(&rowToEncode[0], d_krow);
+ //DEBUG_PRINT_F(fp, "Encoding row=[%d] -->\n",ii);
+ //DEBUG_PRINT_UCHAR_ARRAY_F(fp, &rowToEncode[0], d_krow);
+
+ // encode it
+ block_conv_encode( rowEncoded_block,
+ rowToEncode,
+ rowOutputs,
+ rowNextStates,
+ rowTail,
+ rowEncoder_K,
+ rowEncoder_n);
+
+ //DEBUG_PRINT("Row Encoded Block=[%d] -->\n",ii);
+ tmp = rowEncoded_block.size();
+ //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(&rowEncoded_block[0], tmp);
+ //DEBUG_PRINT_F(fp, "Row Encoded Block=[%d] -->\n",ii);
+ //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR_F(fp, &rowEncoded_block[0], tmp);
+
+ // store only the encoded bits, b/c we read out the data in a special way
+ memcpy(&rowEncodedBits[ii][0], &rowEncoded_block[d_krow], sizeof(float)*(rowEncoder_m*rowEncoder_n));
+
+// DEBUG_PRINT("Row Encoded Bits");
+// tmp = rowEncoder_m*rowEncoder_n;
+// DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(&rowEncodedBits[ii][0], tmp);
+ }
+
+ // encode the column data
+ int numDataColsToEncode = d_krow;
+ int numCheckColsToEncode = numColsToEncode-numDataColsToEncode;
+ for(ii=0; ii<numDataColsToEncode; ii++) {
+ // populate colToEncode
+ for(jj=0; jj<d_kcol; jj++) {
+ colToEncode[jj] = inputWithPad[jj*d_krow+ii];
+ }
+
+ //DEBUG_PRINT("Encoding col=[%d] -->\n",ii);
+ //DEBUG_PRINT_UCHAR_ARRAY(&colToEncode[0], d_kcol);
+ //DEBUG_PRINT_F(fp, "Encoding col=[%d] -->\n",ii);
+ //DEBUG_PRINT_UCHAR_ARRAY_F(fp, &colToEncode[0], d_kcol);
+
+ // encode it
+ block_conv_encode( colEncoded_block,
+ colToEncode,
+ colOutputs,
+ colNextStates,
+ colTail,
+ colEncoder_K,
+ colEncoder_n);
+
+ //DEBUG_PRINT("Col Encoded Block=[%d] -->\n",ii);
+ tmp = colEncoded_block.size();
+ //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(&colEncoded_block[0], tmp);
+ //DEBUG_PRINT_F(fp, "Col Encoded Block=[%d] -->\n",ii);
+ //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR_F(fp, &colEncoded_block[0], tmp);
+
+ // store only the encoded bits, b/c we read the data out in a special way
+ memcpy(&colEncodedBits[ii][0], &colEncoded_block[d_kcol], sizeof(float)*(colEncoder_m*colEncoder_n));
+
+// DEBUG_PRINT("Col Encoded Bits");
+// tmp = colEncoder_m*colEncoder_n;
+// DEBUG_PRINT_FLOAT_ARRAY(&colEncodedBits[ii][0], tmp);
+ }
+
+ // encode checks on checks (encode the row-encoded bits)
+ for(ii=0; ii<numCheckColsToEncode; ii++) {
+ // populate colToEncode
+ for(jj=0; jj<d_kcol; jj++) {
+ colToEncode[jj] = rowEncodedBits[jj][ii]; // indexing is wierd b/c of the way we declared the vector :(
+ }
+
+ //DEBUG_PRINT("Encoding col=[%d] -->\n",ii+numDataColsToEncode);
+ //DEBUG_PRINT_UCHAR_ARRAY(&colToEncode[0], d_kcol);
+ //DEBUG_PRINT_F(fp, "Encoding col=[%d] -->\n",ii+numDataColsToEncode);
+ //DEBUG_PRINT_UCHAR_ARRAY_F(fp, &colToEncode[0], d_kcol);
+
+ // encode it
+ block_conv_encode( colEncoded_block,
+ colToEncode,
+ colOutputs,
+ colNextStates,
+ colTail,
+ colEncoder_K,
+ colEncoder_n);
+
+ //DEBUG_PRINT("Col Encoded Block=[%d] -->\n",ii+numDataColsToEncode);
+ tmp = colEncoded_block.size();
+ //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(&colEncoded_block[0], tmp);
+
+ //DEBUG_PRINT_F(fp, "Col Encoded Block=[%d] -->\n",ii+numDataColsToEncode);
+ //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR_F(fp, &colEncoded_block[0], tmp);
+
+
+ // store only the encoded bits, b/c we read the data out in a special way
+ memcpy(&colEncodedBits[ii+numDataColsToEncode][0], &colEncoded_block[d_kcol], sizeof(float)*(colEncoder_m*colEncoder_n));
+
+// DEBUG_PRINT("Col Encoded Bits");
+// tmp = colEncoder_m*colEncoder_n;
+// DEBUG_PRINT_FLOAT_ARRAY(&colEncodedBits[ii][0], tmp);
+ }
+
+ unsigned char* inputDataPtr;
+ float *outputDataPtr = out;
+ float *tmpPtr = outputDataPtr;
+
+ int curRowInRowEncodedBits = 0;
+ // read out the data along the rows into the "out" array
+
+ // skip B zeros & do the first row
+ inputDataPtr = &inputWithPad[d_bval];
+ int firstRowRemainingBits = d_krow-d_bval;
+ for(ii=0; ii<firstRowRemainingBits; ii++) {
+ *outputDataPtr++ = (float)(*inputDataPtr++);
+ }
+
+ // copy the encoded bits
+ memcpy(outputDataPtr, &rowEncodedBits[curRowInRowEncodedBits++][0],
+ sizeof(float)*(rowEncoder_m*rowEncoder_n));
+
+ outputDataPtr += (rowEncoder_m*rowEncoder_n);
+ tmpPtr = outputDataPtr;
+
+ // copy out the rest of the data
+ for(ii=1; ii<d_kcol; ii++) { // ii starts at 1, b/c we already did idx=0
+ // copy systematic bits
+ for(jj=0; jj<d_krow; jj++) {
+ *outputDataPtr++ = (float)(*inputDataPtr++);
+ }
+
+ // copy the encoded bits
+ memcpy(outputDataPtr, &rowEncodedBits[curRowInRowEncodedBits++][0],
+ sizeof(float)*(rowEncoder_m*rowEncoder_n));
+
+ outputDataPtr += (rowEncoder_m*rowEncoder_n);
+ tmpPtr = outputDataPtr;
+ }
+
+ // copy the encoded cols
+ for(ii=0; ii<(colEncoder_m*colEncoder_n); ii++) {
+ // copy checks
+ for(jj=0; jj<d_krow; jj++) {
+ *outputDataPtr++ = colEncodedBits[jj][ii];
+ }
+ int kk = jj;
+ // copy checks on checks
+ for(jj=0; jj<(rowEncoder_m*rowEncoder_n); jj++) {
+ *outputDataPtr++ = colEncodedBits[kk++][ii];
+ }
+ }
+
+ //DEBUG_PRINT("Output\n");
+ //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(out, outputSize);
+ //DEBUG_PRINT_F(fp, "Output\n");
+ //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR_F(fp, out, outputSize);
+}
+
+
+tpc_encoder::~tpc_encoder()
+{
+ fclose(fp);
+}
+
+}
+}