/* * 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); }
/* * Forward trellis recursion * * Generate branch metrics and path metrics with a combined function. Only * accumulated path metric sums and path selections are stored. Normalize on * the interval specified by the decoder. */ static void _conv_decode(vdecoder dec, sbyte *seq, CONV_TERM term, int len) { int i, j = 0; vtrellis trellis = dec.trellis; if (term == CONV_TERM.TAIL_BITING) { j = len - TAIL_BITING_EXTRA; } for (i = 0; i < dec.len; i++, j++) { if (term == CONV_TERM.TAIL_BITING && j == len) { j = 0; } gen_metrics_k7_n3(&seq[dec.n * j], trellis.outputs, trellis.sums, dec.paths[i], ((i % dec.intrvl) != 0 ? 0 : 1)); //flipped on purpose } }
/* Release the trellis */ static void free_trellis(vtrellis trellis) { trellis.outputsBuffer.Dispose(); trellis.sumsBuffer.Dispose(); trellis.valsBuffer.Dispose(); }