summaryrefslogtreecommitdiff
path: root/cesar/ce/rx/bitloading/src/bitloading.c
diff options
context:
space:
mode:
authordufour2010-01-26 14:01:07 +0000
committerdufour2010-01-26 14:01:07 +0000
commitf98f4150523e924d89deb4b39cbb1cda190c4028 (patch)
tree75539f67888f97244e7efc3965f600f5eadc5f31 /cesar/ce/rx/bitloading/src/bitloading.c
parent69f8884a256d1a9c6fba6bed4eb4cc7cda71bb0e (diff)
cesar/ce/rx/bitloading: rename bit loading function to remove initial
Most of bit loading functions can be used for initial or iterative bit loading algorithm. Update documentation. git-svn-id: svn+ssh://pessac/svn/cesar/trunk@6653 017c9cb6-072f-447c-8318-d5b54f68fe89
Diffstat (limited to 'cesar/ce/rx/bitloading/src/bitloading.c')
-rw-r--r--cesar/ce/rx/bitloading/src/bitloading.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/cesar/ce/rx/bitloading/src/bitloading.c b/cesar/ce/rx/bitloading/src/bitloading.c
index 2d60e4e4f6..b9700d3be0 100644
--- a/cesar/ce/rx/bitloading/src/bitloading.c
+++ b/cesar/ce/rx/bitloading/src/bitloading.c
@@ -12,6 +12,14 @@
*/
#include "common/std.h"
#include "ce_rx_bl_fsm_defs.h"
+#include "ce/rx/bitloading/inc/ber.h"
+#include "ce/rx/bitloading/inc/bitloading.h"
+
+#define LIB_HEAPSORT_USER_TYPE ce_rx_bl_ber_impact_t
+#define LIB_HEAPSORT_USER_COMP_LESSER ce_rx_bl_ber_impact_compare
+#define LIB_HEAPSORT_USER_SWAP ce_rx_bl_ber_impact_swap
+#define LIB_HEAPSORT_USER_PREFIX ce_rx_bl_ber_impact
+#include "lib/heapsort.h"
blk_t *
ce_rx_bl_get_nsr (ce_rx_bitloading_t *bl)
@@ -28,3 +36,234 @@ ce_rx_bl_get_nsr (ce_rx_bitloading_t *bl)
break;
}
}
+
+void
+ce_rx_bl_sort_optimization (ce_rx_bl_ber_impact_t *opti_table,
+ uint size)
+{
+ /* Check parameter. */
+ dbg_assert (opti_table);
+
+ lib_heapsort (opti_table, size);
+}
+
+u64
+ce_rx_bl_update_tone_map_under_ber_consign (u64 ber_pt,
+ tonemask_info_t *tonemask,
+ phy_fecrate_t fec_rate,
+ ce_rx_bitloading_t *bl,
+ tonemap_t *tm,
+ ce_rx_bl_ber_impact_t *opti_table,
+ uint *tone_en)
+{
+ /* Check parameters. */
+ dbg_assert (ber_pt > 0 && ber_pt < CE_RX_BL_BER_DEFAULT_OVER);
+ dbg_assert (tonemask);
+ dbg_assert (tm);
+ dbg_assert (opti_table);
+ dbg_assert (tone_en);
+
+ u8 modulation;
+ u64 ber_weighted_sum = 0;
+ u64 ber_upper;
+ uint i = 0, carrier_index = 0;
+ blk_t *cur_blk = bl->noise_nrj;
+ u32 *nsr_data = (u32 *) cur_blk->data;
+
+ tm->bits_per_symbol = 0;
+ *tone_en = 0;
+
+ /* Go through the tone map. */
+ TONEMAP_ACCESS_BEGIN (tm, tonemask->tonemask)
+ {
+ /* Index of a tone in a word of tones. */
+ uint tm_tone_index_;
+ /* The 8 tones of the word. */
+ u32 tm_word_tone_ = 0;
+ for (tm_tone_index_ = 0;
+ tm_tone_index_ < 8;
+ tm_tone_index_++)
+ {
+ /* If tone enable. */
+ if (!(tk_cur_ & 0x1))
+ {
+ /* Compute BER. */
+ ce_rx_bl_ber_vs_nsr (ce_rx_bl_ber_poly_coef[fec_rate],
+ nsr_data[carrier_index % (BLK_SIZE / 4)], ber_pt,
+ &modulation, &opti_table[i].ber_lower, &ber_upper);
+ /* Fill temporary table. */
+ if (modulation)
+ (*tone_en)++;
+ if (modulation == CE_MOD_COUNT - 1)
+ opti_table[i].ber_diff = -1;
+ else
+ opti_table[i].ber_diff = (ber_upper - opti_table[i].ber_lower) >> 32;
+ opti_table[i].carrier_index = carrier_index;
+ ber_weighted_sum += opti_table[i].ber_lower * CE_BIT_PER_MOD[modulation];
+ tm->bits_per_symbol += CE_BIT_PER_MOD[modulation];
+ i++;
+ }
+ else
+ modulation = 0;
+ /* Write tone. */
+ tm_word_tone_ |= modulation << (4 * tm_tone_index_);
+ /* Next tone mask bit. */
+ tk_cur_ >>= 1;
+ carrier_index++;
+ }
+ *tm_ = tm_word_tone_;
+ /* Next group of tone (grouped by word). */
+ tm_++;
+ }
+ TONEMAP_ACCESS_MIDDLE;
+ /* Get next block of NSR. */
+ /* Dirty? You mean? FIXME */
+ if (!(carrier_index % (BLK_SIZE / 4)))
+ {
+ cur_blk = cur_blk->next;
+ dbg_assert (cur_blk);
+ nsr_data = (u32 *) cur_blk->data;
+ }
+ TONEMAP_ACCESS_END;
+
+ return ber_weighted_sum;
+}
+
+uint
+ce_rx_bl_update_tone_map_at_ber_consign (u64 ber_pt,
+ tonemask_info_t *tonemask,
+ phy_fecrate_t fec_rate,
+ ce_rx_bitloading_t *bl,
+ tonemap_t *tm,
+ ce_rx_bl_ber_impact_t *opti)
+{
+ /* Check parameters. */
+ dbg_assert (ber_pt > 0 && ber_pt < CE_RX_BL_BER_DEFAULT_OVER);
+ dbg_assert (tonemask);
+ dbg_assert (tm);
+ dbg_assert (bl);
+ dbg_assert (opti);
+
+ uint tone_en;
+
+ /* Generate a non optimized version of the initial tone map. */
+ u64 ber_weighted_sum =
+ ce_rx_bl_update_tone_map_under_ber_consign (ber_pt, tonemask,
+ fec_rate, bl, tm, opti,
+ &tone_en);
+
+ /* Sort optimization table. */
+ ce_rx_bl_sort_optimization (opti, tonemask->carrier_nb);
+
+ /* Until we reach the limit. */
+ uint pos = 0;
+ u32 *tone_word;
+ s8 mod = -1;
+ while (ber_pt * tm->bits_per_symbol >= ber_weighted_sum)
+ {
+ /* Get the modulation of the lowest BER impact. */
+ mod = tonemap_get_tone (tm, opti[pos].carrier_index, &tone_word);
+ if (mod == 0)
+ tone_en++;
+ /* If the tone we would like to increase is already at its maximum,
+ * all the remaining tone that can be increase are already at the
+ * maximum too. So basically, we should stop the algorithm here. */
+ if (mod == CE_MOD_COUNT - 1)
+ return tone_en;
+ /* Remove from number of bits of the tone map the current value. */
+ tm->bits_per_symbol -= CE_BIT_PER_MOD[mod];
+ /* Remove from the summed BER of the tone map the current value. */
+ ber_weighted_sum -= opti[pos].ber_lower * CE_BIT_PER_MOD[mod];
+ /* Increase modulation of this tone index. */
+ tonemap_write_tone_to_word (tone_word, opti[pos].carrier_index,
+ ++mod);
+ /* Update number of bits of the tone map. */
+ tm->bits_per_symbol += CE_BIT_PER_MOD[mod];
+ /* Update summed BER of the tone map. */
+ ber_weighted_sum += (opti[pos].ber_lower + ((u64) opti[pos].ber_diff << 32))
+ * CE_BIT_PER_MOD[mod];
+ /* Next one. */
+ pos++;
+ }
+ dbg_assert (mod != -1);
+ /* Remove last one. */
+ tm->bits_per_symbol -= CE_BIT_PER_MOD[mod];
+ tonemap_write_tone_to_word (tone_word, opti[pos - 1].carrier_index,
+ --mod);
+ tm->bits_per_symbol += CE_BIT_PER_MOD[mod];
+ if (mod == 0)
+ tone_en--;
+ return tone_en;
+}
+
+tonemap_t *
+ce_rx_bl_compute_tone_map_iterative (const u64 bpt_initial[PHY_FEC_RATE_NB],
+ uint iteration_max,
+ tonemask_info_t *tonemask,
+ ce_rx_bitloading_t *bl)
+{
+ /* Check parameters. */
+ dbg_assert (bpt_initial);
+ dbg_assert (iteration_max);
+ dbg_assert (tonemask);
+ dbg_assert (bl);
+
+ u64 ber_prev, ber_cur;
+ uint it_count;
+ ce_rx_bl_ber_impact_t opti[PHY_CARRIER_NB];
+ u32 sort[PHY_FEC_RATE_NB];
+ tonemap_t *tm[PHY_FEC_RATE_NB];
+ uint tone_en;
+
+ phy_fecrate_t fec_rate;
+ /* For each FEC rate. */
+ for (fec_rate = PHY_FEC_RATE_1_2; fec_rate < PHY_FEC_RATE_NB; fec_rate++)
+ {
+ it_count = 0;
+ tm[fec_rate] = tonemap_alloc ();
+ /* Start with the lowest BER consign possible (it depends on the FEC
+ * rate). */
+ ber_cur = ce_rx_bl_ber_pt_bpt (fec_rate, bpt_initial[fec_rate]);
+ do
+ {
+ /* Generate a optimized version of the tone map. */
+ tone_en = ce_rx_bl_update_tone_map_at_ber_consign
+ (ber_cur, tonemask, fec_rate, bl, tm[fec_rate], opti);
+ /* Store previous BER consign. */
+ ber_prev = ber_cur;
+ /* Get new BER consign. */
+ ber_cur = ce_rx_bl_ber_pt_bpt
+ (fec_rate, (tm[fec_rate]->bits_per_symbol *
+ CE_RX_BL_BPT_QUANT_FACTOR) / tone_en);
+ }
+ /* Repeat until no modification of the BER consign (or 6 times). */
+ while (++it_count < iteration_max && ber_prev != ber_cur);
+ /* Store tone map generated. */
+ sort[fec_rate] = tm[fec_rate]->bits_per_symbol;
+ }
+
+ /* Choose best fec_rate. */
+ /* 1/2 * 42 -> 21.
+ * 16/21 * 42 -> 32. */
+ phy_fecrate_t good, bad;
+ if ((sort[PHY_FEC_RATE_1_2] * 21)
+ > sort[PHY_FEC_RATE_16_21] * 32)
+ {
+ good = PHY_FEC_RATE_1_2;
+ bad = PHY_FEC_RATE_16_21;
+ }
+ else
+ {
+ good = PHY_FEC_RATE_16_21;
+ bad = PHY_FEC_RATE_1_2;
+ }
+ /* Remove worst tone map. */
+ tonemap_free (tm[bad]);
+ /* Configure generated tone map. */
+ tm[good]->fecrate = good;
+ /* Update pre-computed parameters. */
+ tonemap_update (tm[good], TONEMAP_P_PBERROR_DEFAULT_UF32);
+ /* Return best tone map. */
+ return tm[good];
+}
+