/* * Allocate and initialize the trellis object * * Initialization consists of generating the outputs and output value of a * given state. Due to trellis symmetry, only one of the transition paths * is used by the butterfly operation in the forward recursion, so only one * set of N outputs is required per state variable. */ static vtrellis generate_trellis(lte_conv_code code) { vtrellis trellis; short * o; int ns = NUM_STATES(code.k); int olen = (code.n == 2) ? 2 : 4; trellis = new vtrellis(); trellis.num_states = ns; trellis.sumsBuffer = UnsafeBuffer.Create(ns, sizeof(short)); trellis.sums = (short *)trellis.sumsBuffer; trellis.outputsBuffer = UnsafeBuffer.Create(ns * olen, sizeof(short)); trellis.outputs = (short *)trellis.outputsBuffer; trellis.valsBuffer = UnsafeBuffer.Create(ns, sizeof(sbyte)); trellis.vals = (sbyte *)trellis.valsBuffer; /* Populate the trellis state objects */ for (int i = 0; i < ns; i++) { o = &trellis.outputs[olen * i]; if (code.rgen != 0) { gen_rec_state_info(code, &trellis.vals[i], i, o); } else { gen_state_info(code, &trellis.vals[i], i, o); } } return(trellis); }
/* * Populate recursive trellis state */ static void gen_rec_state_info(lte_conv_code code, sbyte *val, int reg, short *o) { int i; int prev, rec, mask; /* Previous '0' and '1' states */ prev = vstate_lshift(reg, code.k, 0); /* Compute recursive input value (not the value shifted into register) */ rec = (reg >> (code.k - 2)) & 0x01; if ((int)__builtin_parity(prev & code.rgen) == rec) { *val = 0; } else { *val = 1; } /* Compute outputs and unpack to NRZ */ prev = prev | rec << (code.k - 1); if (code.k == 5) { mask = 0x0f; } else { mask = 0x3f; } /* Check for recursive outputs */ for (i = 0; i < code.n; i++) { if ((code.gen[i] & mask) != 0) { o[i] = (short)(__builtin_parity(prev & code.gen[i]) * 2 - 1); } else { o[i] = (short)(*val * 2 - 1); } } }
public ConvDec(int len) { //Make settings code = new lte_conv_code { n = 3, k = 7, len = len, gen = new int[] { 91, 121, 117, 0 }, term = CONV_TERM.TAIL_BITING, }; //Create vdec = alloc_vdec(code); }
static void reset_vdec(vdecoder dec, lte_conv_code code) { dec.n = code.n; dec.k = code.k; dec.recursive = code.rgen != 0 ? 1 : 0; dec.intrvl = short.MaxValue / (dec.n * sbyte.MaxValue) - dec.k; if (dec.n != 3 || dec.k != 7) { throw new Exception(); } if (code.term == CONV_TERM.FLUSH) { dec.len = code.len + code.k - 1; } else { dec.len = code.len + TAIL_BITING_EXTRA * 2; } }
/* * Allocate decoder object * * Subtract the constraint length K on the normalization interval to * accommodate the initialization path metric at state zero. */ static vdecoder alloc_vdec(lte_conv_code code) { int i, ns; ns = NUM_STATES(code.k); vdecoder dec = new vdecoder(); dec.n = code.n; dec.k = code.k; dec.recursive = code.rgen != 0 ? 1 : 0; dec.intrvl = short.MaxValue / (dec.n * sbyte.MaxValue) - dec.k; if (dec.n != 3 || dec.k != 7) { throw new Exception(); } if (code.term == CONV_TERM.FLUSH) { dec.len = code.len + code.k - 1; } else { dec.len = code.len + TAIL_BITING_EXTRA * 2; } dec.trellis = generate_trellis(code); dec.pathsBuffer = UnsafeBuffer.Create(sizeof(short *) * dec.len * ns); dec.pathsPtr = (short *)dec.pathsBuffer; dec.paths = new short *[dec.len]; for (i = 0; i < dec.len; i++) { dec.paths[i] = &dec.pathsPtr[i * ns]; } return(dec); }
/* * Populate non-recursive trellis state * * For a given state defined by the k-1 length shift register, find the * value of the input bit that drove the trellis to that state. Then * generate the N outputs of the generator polynomial at that state. */ static void gen_state_info(lte_conv_code code, sbyte *val, int reg, short *o) { int i; int prev; /* Previous '0' state */ prev = vstate_lshift(reg, code.k, 0); /* Compute output and unpack to NRZ */ *val = (sbyte)((reg >> (code.k - 2)) & 0x01); prev = prev | (int)*val << (code.k - 1); for (i = 0; i < code.n; i++) { o[i] = (short)(__builtin_parity(prev & code.gen[i]) * 2 - 1); } /*Console.WriteLine($"{__builtin_parity(0)}, {__builtin_parity(1)}, {__builtin_parity(2)}"); * for (i = 0; i < code.n; i++) * Console.WriteLine(o[i]); * Console.ReadLine();*/ }