#ifndef ce_rx_bitloading_bitloading_h #define ce_rx_bitloading_bitloading_h /* Cesar project {{{ * * Copyright (C) 2009 Spidcom * * <<>> * * }}} */ /** * \file ce/rx/bitloading/bitloading.h * \brief CE RX bit-loading (public declaration). * \ingroup ce_rx * * This module is responsible to manage the bit-loading state and data per * station. * * Basically, a structure is added to the sta_t with some information (like * the state of the bit-loading). */ #include "lib/blk.h" #include "lib/blk_table.h" #include "ce/rx/bitloading/pber.h" #include "ce/rx/bitloading/ber_margin_update.h" #include "common/module.h" typedef enum ce_rx_bitloading_ber_sliding_mean_t { /** BER sliding mean fast index. */ CE_RX_BL_BER_SLIDING_MEAN_FAST, /** BER sliding mean slow index. */ CE_RX_BL_BER_SLIDING_MEAN_SLOW, /** BER sliding mean count. */ CE_RX_BL_BER_SLIDING_MEAN_NB, } ce_rx_bitloading_ber_sliding_mean_t; /** * Restart reason of the CE. * Fields order is important for VS_GET_CE_STATS MME. */ typedef enum ce_rx_bitloading_restart_reason_t { /** * CE restarted because BER is too low. */ CE_RX_BL_RESTART_REASON_BER_LOW = 0, /** * CE restarted because PB error rate is too high. */ CE_RX_BL_RESTART_REASON_PBERR_HIGH = 1, /** * CE restarted because peer requested it (frame sound received). */ CE_RX_BL_RESTART_REASON_PEER_REQUEST = 2, /** * CE restarted because a tone map update has occurred. */ CE_RX_BL_RESTART_REASON_TONEMAP_UPDATE = 3, /** * CE restarted because a BER margin update has occurred. */ CE_RX_BL_RESTART_REASON_BER_MARGIN_UPDATE = 4, /** * Number of reason to restart the CE. * Should not be moved to keep numeration. */ CE_RX_BL_RESTART_REASON_NB, /** * No restart yet. */ CE_RX_BL_RESTART_REASON_NO_RESTART = 255 } ce_rx_bitloading_restart_reason_t; /** * Next dates we are allowed to restart the CE. */ typedef enum ce_rx_bitloading_date_criteria_t { /** * PBErrorRate criteria. */ CE_RX_BL_DATE_CRITERIA_PBER, /** * BER criteria. */ CE_RX_BL_DATE_CRITERIA_BER, /** * BER margin update criteria. */ CE_RX_BL_DATE_BER_MARGIN_UPDATE, /** * Number of date used in bit loading algorithm. */ CE_RX_BL_DATE_CRITERIA_NB, } ce_rx_bitloading_date_criteria_t; /** * Statistics of the CE/RX bit-loading. */ typedef struct ce_rx_bitloading_stats_t { /** * Number of PB in the last received frame. */ u8 curr_nb_pb; /** * Number of PB with CRC false in the last received frame. */ u8 curr_nb_pb_crc_false; /** * BER sum in the last frame received. */ uint curr_ber_sum; /** * Last BER sliding means after the last frame received. */ u64 curr_ber_mean[CE_RX_BL_BER_SLIDING_MEAN_NB]; /** * Last PB error rate mean after the last frame received. */ u32 curr_pberr_rate_mean; /** * Number of restart of the CE for each reasons. * Those counters can overflow. */ uint restart_reason[CE_RX_BL_RESTART_REASON_NB]; /** * Previous BER target, before the last CE restart. */ u64 prev_ber_target; /** * Previous BER reached, before the last CE restart. */ u64 prev_ber_target_reached; /** * BER sliding means of the previous tone map. */ u64 prev_ber_mean[CE_RX_BL_BER_SLIDING_MEAN_NB]; /** * PB Error Rate of the previous tone map. */ u32 prev_pberr_rate_mean; /** * Last CE restart reason. */ ce_rx_bitloading_restart_reason_t last_restart_reason; /** * Count of times when bit-loading can not optimize tone map as much as * possible (out of optimization table). */ uint optimization_failure; } ce_rx_bitloading_stats_t; /** * Bit-loading data per station. */ typedef struct ce_rx_bitloading_t { /** State of the bit loading. */ u32 fsm; /** Mean of the noise NRJ (on multiple blk) per intervals. */ blk_t *noise_nrj; /** Number of allocated block for the noise NRJ. */ u8 noise_nrj_blk_count; /** Mean count. */ u32 mean_count; /** Counter of frame with high PB error rate. */ uint high_pb_error_rate_frame_counter; /** BER sliding means (-1 if they are reseted). */ s64 ber_sliding_mean[CE_RX_BL_BER_SLIDING_MEAN_NB]; /** Next time we are allowed to restart the CE. */ u32 next_date_min_for_restart_rtc_date[CE_RX_BL_DATE_CRITERIA_NB]; /** Optimisation table of the station, this table only contain the index * of the carrier sorted by impact on the ber. */ blk_table_t *opti_table; /** Index of the optimization cursor in the optimization table. */ uint opti_table_cursor; /** Statistics of the bit-loading. */ ce_rx_bitloading_stats_t stats; /** PBER context. */ ce_rx_bl_pber_t pber; /** Need to resend tone map to TX? */ bool resend_tm; /** Timer to know when to re-send the tone map (if TX peer does not use * default TMI). */ uint resend_tm_date; /** BER margin update context. */ ce_rx_bl_bmu_t bmu; /** Actual bit-loading failed to optimize tone map as much as possible. */ bool optimization_failed; } ce_rx_bitloading_t; /** * Comparisons factors to know when to restart CE. */ extern uint ce_rx_bl_pb_false_factor_; extern uint ce_rx_bl_pb_total_factor_; /** * Minimum PB per frame (for high PB error rate criteria). */ extern uint ce_rx_bl_min_pb_per_frame_; /** * How many frames with "high PB error rate" we must have before restarting * CE. */ extern uint ce_rx_bl_min_frame_with_high_pb_err_rate_; /** * BER lower bound. * In CE_RX_BL_BER_LOWER_BOUND_UNIT of BER consign. */ extern uint ce_rx_bl_ber_lower_bound_; BEGIN_DECLS /** * Reset BER sliding means. * \param bl the bit loading structure of the station */ extern inline void ce_rx_bl_ber_sliding_mean_reset (ce_rx_bitloading_t *bl) { /* Check parameter. */ dbg_assert (bl); uint i; for (i = 0; i < CE_RX_BL_BER_SLIDING_MEAN_NB; i++) bl->ber_sliding_mean[i] = -1; } /** * Initialize bit-loading statistics. */ extern inline void ce_rx_bl_stats_init (ce_rx_bitloading_t *bl) { /* Check parameter. */ dbg_assert (bl); uint i; bl->stats.curr_nb_pb = 0; bl->stats.curr_nb_pb_crc_false = 0; bl->stats.curr_ber_sum = 0; for (i = 0; i < CE_RX_BL_BER_SLIDING_MEAN_NB; i++) { bl->stats.curr_ber_mean[i] = 0; bl->stats.prev_ber_mean[i] = 0; } bl->stats.curr_pberr_rate_mean = 0; for (i = 0; i < CE_RX_BL_RESTART_REASON_NB; i++) bl->stats.restart_reason[i] = 0; bl->stats.prev_ber_target = 0; bl->stats.prev_ber_target_reached = 0; bl->stats.prev_pberr_rate_mean = 0; bl->stats.last_restart_reason = CE_RX_BL_RESTART_REASON_NO_RESTART; bl->stats.optimization_failure = 0; } /** * Initialize bit-loading data. * \param bt the bit-loading data & state structure. * @note the structure must be already allocated. */ extern inline void ce_rx_bitloading_init (ce_rx_bitloading_t *bt) { /* Check parameter. */ dbg_assert (bt); /* Initialize. */ bt->fsm = 0; bt->noise_nrj_blk_count = 0; dbg_invalid_ptr (bt->noise_nrj); bt->high_pb_error_rate_frame_counter = 0; ce_rx_bl_ber_sliding_mean_reset (bt); ce_rx_bl_stats_init (bt); bt->opti_table = NULL; #if MODULE_INCLUDED (ce_rx_bitloading) ce_rx_bl_pber_reset (&bt->pber); #endif bt->resend_tm = false; bt->resend_tm_date = 0; ce_rx_bl_bmu_reset (&bt->bmu); bt->optimization_failed = false; } /** * Clean NSR mean. * \param bl the bit loading context of the peer */ extern inline void ce_rx_bl_nsr_clean (ce_rx_bitloading_t *bl) { /* Check parameter. */ dbg_assert (bl); dbg_assert (bl->noise_nrj_blk_count); dbg_assert_ptr (bl->noise_nrj); blk_release_desc_range_nb (bl->noise_nrj, bl->noise_nrj_blk_count); dbg_invalid_ptr (bl->noise_nrj); bl->noise_nrj_blk_count = 0; } /** * Un-initialize bit-loading data. * \param bt the bit-loading data & state structure. * @note this function does not delete the structure itself, just clean the * structure. */ extern inline void ce_rx_bitloading_uninit (ce_rx_bitloading_t *bt) { /* Check parameter. */ dbg_assert (bt); /* Clean if needed. */ if (bt->noise_nrj_blk_count) { ce_rx_bl_nsr_clean (bt); } /* Letting the FSM in its current state. */ /* Free optimization table. */ if (bt->opti_table != NULL) blk_table_free (bt->opti_table); } /** * Get the current NSR used by the bit loading. * \param ctx the bit loading context of the station. * \return the NSR if available (NULL otherwise). */ blk_t * ce_rx_bl_get_nsr (ce_rx_bitloading_t *bl); END_DECLS #endif /* ce_rx_bitloading_bitloading_h */