+ int qm = 8;
+ int qam = 256;
+ int m, k;
+ double I, Q, p0, p1, llr_, b[qm], log_syml_prob[qam];
+ /* 5.1.4 of TS38.211 */
+ const double symbols_I[256] = {
+ 5, 5, 7, 7, 5, 5, 7, 7, 3, 3, 1, 1, 3, 3, 1, 1, 5,
+ 5, 7, 7, 5, 5, 7, 7, 3, 3, 1, 1, 3, 3, 1, 1, 11,
+ 11, 9, 9, 11, 11, 9, 9, 13, 13, 15, 15, 13, 13,
+ 15, 15, 11, 11, 9, 9, 11, 11, 9, 9, 13, 13, 15,
+ 15, 13, 13, 15, 15, 5, 5, 7, 7, 5, 5, 7, 7, 3, 3,
+ 1, 1, 3, 3, 1, 1, 5, 5, 7, 7, 5, 5, 7, 7, 3, 3, 1,
+ 1, 3, 3, 1, 1, 11, 11, 9, 9, 11, 11, 9, 9, 13, 13,
+ 15, 15, 13, 13, 15, 15, 11, 11, 9, 9, 11, 11, 9, 9,
+ 13, 13, 15, 15, 13, 13, 15, 15, -5, -5, -7, -7, -5,
+ -5, -7, -7, -3, -3, -1, -1, -3, -3, -1, -1, -5, -5,
+ -7, -7, -5, -5, -7, -7, -3, -3, -1, -1, -3, -3,
+ -1, -1, -11, -11, -9, -9, -11, -11, -9, -9, -13,
+ -13, -15, -15, -13, -13, -15, -15, -11, -11, -9,
+ -9, -11, -11, -9, -9, -13, -13, -15, -15, -13,
+ -13, -15, -15, -5, -5, -7, -7, -5, -5, -7, -7, -3,
+ -3, -1, -1, -3, -3, -1, -1, -5, -5, -7, -7, -5, -5,
+ -7, -7, -3, -3, -1, -1, -3, -3, -1, -1, -11, -11,
+ -9, -9, -11, -11, -9, -9, -13, -13, -15, -15, -13,
+ -13, -15, -15, -11, -11, -9, -9, -11, -11, -9, -9,
+ -13, -13, -15, -15, -13, -13, -15, -15};
+ const double symbols_Q[256] = {
+ 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1, 11,
+ 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9, 13, 15, 13,
+ 15, 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1,
+ 11, 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9, 13,
+ 15, 13, 15, -5, -7, -5, -7, -3, -1, -3, -1, -5,
+ -7, -5, -7, -3, -1, -3, -1, -11, -9, -11, -9, -13,
+ -15, -13, -15, -11, -9, -11, -9, -13, -15, -13,
+ -15, -5, -7, -5, -7, -3, -1, -3, -1, -5, -7, -5,
+ -7, -3, -1, -3, -1, -11, -9, -11, -9, -13, -15,
+ -13, -15, -11, -9, -11, -9, -13, -15, -13, -15, 5,
+ 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1, 11,
+ 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9, 13, 15,
+ 13, 15, 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1,
+ 3, 1, 11, 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9,
+ 13, 15, 13, 15, -5, -7, -5, -7, -3, -1, -3, -1,
+ -5, -7, -5, -7, -3, -1, -3, -1, -11, -9, -11, -9,
+ -13, -15, -13, -15, -11, -9, -11, -9, -13, -15,
+ -13, -15, -5, -7, -5, -7, -3, -1, -3, -1, -5, -7,
+ -5, -7, -3, -1, -3, -1, -11, -9, -11, -9, -13, -15,
+ -13, -15, -11, -9, -11, -9, -13, -15, -13, -15};
+ /* Average constellation point energy */
+ N0 *= 170.0;
+ for (k = 0; k < qm; k++)
+ b[k] = llrs[qm * i + k] < 0 ? 1.0 : 0.0;
+ /* 5.1.4 of TS38.211 */
+ I = (1 - 2 * b[0]) * (8 - (1 - 2 * b[2]) *
+ (4 - (1 - 2 * b[4]) * (2 - (1 - 2 * b[6]))));
+ Q = (1 - 2 * b[1]) * (8 - (1 - 2 * b[3]) *
+ (4 - (1 - 2 * b[5]) * (2 - (1 - 2 * b[7]))));
+ /* AWGN channel */
+ I += sqrt(N0 / 2) * randn(0);
+ Q += sqrt(N0 / 2) * randn(1);
+ /*
+ * Calculate the log of the probability that each of
+ * the constellation points was transmitted
+ */
+ for (m = 0; m < qam; m++)
+ log_syml_prob[m] = -(pow(I - symbols_I[m], 2.0)
+ + pow(Q - symbols_Q[m], 2.0)) / N0;
+ /* Calculate an LLR for each of the k_64QAM bits in the set */
+ for (k = 0; k < qm; k++) {
+ p0 = -999999;
+ p1 = -999999;
+ /* For each constellation point */
+ for (m = 0; m < qam; m++) {
+ if ((m >> (qm - k - 1)) & 1)
+ p1 = maxstar(p1, log_syml_prob[m]);
+ else
+ p0 = maxstar(p0, log_syml_prob[m]);
+ }
+ /* Calculate the LLR */
+ llr_ = p0 - p1;
+ llr_ *= (1 << ldpc_llr_decimals);
+ llr_ = round(llr_);
+ if (llr_ > llr_max)
+ llr_ = llr_max;
+ if (llr_ < -llr_max)
+ llr_ = -llr_max;
+ llrs[qm * i + k] = (int8_t) llr_;
+ }
+}