From 520128162ecf271c5622be19e71e26dd426cab79 Mon Sep 17 00:00:00 2001 From: Joaquim Broquetas Date: Mon, 7 Mar 2022 17:05:33 +0100 Subject: [PATCH] Add CFR to srsue LTE UL (#3865) lte,phy: Add CFR to srsue LTE UL This commit adds the configuration steps needed to enable and configure the CFR module for the srsue's uplink signal. Parsing of the CFR manual threshold has been streamlined. --- lib/examples/pdsch_enodeb.c | 17 +++--------- .../srsran/interfaces/ue_phy_interfaces.h | 11 ++++++++ lib/include/srsran/phy/cfr/cfr.h | 20 +++++++++++--- lib/include/srsran/phy/ue/ue_ul.h | 4 +++ lib/src/phy/cfr/cfr.c | 26 ++++++++++++++++++ lib/src/phy/cfr/test/cfr_test.c | 24 +++++++---------- lib/src/phy/dft/ofdm.c | 3 ++- lib/src/phy/ue/ue_ul.c | 19 +++++++++++++ srsenb/src/main.cc | 17 ++++-------- srsue/hdr/phy/phy_common.h | 4 +++ srsue/src/main.cc | 18 ++++++++++++- srsue/src/phy/lte/cc_worker.cc | 7 +++++ srsue/src/phy/phy_common.cc | 8 ++++++ srsue/src/ue.cc | 27 +++++++++++++++++++ srsue/ue.conf.example | 27 +++++++++++++++++++ 15 files changed, 187 insertions(+), 45 deletions(-) diff --git a/lib/examples/pdsch_enodeb.c b/lib/examples/pdsch_enodeb.c index 291ab1f61..f53400959 100644 --- a/lib/examples/pdsch_enodeb.c +++ b/lib/examples/pdsch_enodeb.c @@ -77,10 +77,6 @@ static bool enable_256qam = false; static float output_file_snr = +INFINITY; static bool use_standard_lte_rate = false; -// CFR type test args -static char cfr_manual_str[] = "manual"; -static char cfr_auto_cma_str[] = "auto_cma"; -static char cfr_auto_ema_str[] = "auto_ema"; // CFR runtime control flags static bool cfr_thr_inc = false; @@ -96,7 +92,7 @@ typedef struct { } cfr_args_t; static cfr_args_t cfr_args = {.enable = 0, - .mode = cfr_manual_str, + .mode = "manual", .manual_thres = 1.0f, .strength = 1.0f, .auto_target_papr = 8.0f, @@ -292,14 +288,9 @@ static int parse_cfr_args() cfr_config.alpha = cfr_args.strength; cfr_config.ema_alpha = cfr_args.ema_alpha; - if (!strcmp(cfr_args.mode, cfr_manual_str)) { - cfr_config.cfr_mode = SRSRAN_CFR_THR_MANUAL; - } else if (!strcmp(cfr_args.mode, cfr_auto_cma_str)) { - cfr_config.cfr_mode = SRSRAN_CFR_THR_AUTO_CMA; - } else if (!strcmp(cfr_args.mode, cfr_auto_ema_str)) { - cfr_config.cfr_mode = SRSRAN_CFR_THR_AUTO_EMA; - } else { - ERROR("CFR mode is not recognised"); + cfr_config.cfr_mode = srsran_cfr_str2mode(cfr_args.mode); + if (cfr_config.cfr_mode == SRSRAN_CFR_THR_INVALID) { + ERROR("CFR mode not recognised"); return SRSRAN_ERROR; } diff --git a/lib/include/srsran/interfaces/ue_phy_interfaces.h b/lib/include/srsran/interfaces/ue_phy_interfaces.h index 06dac7979..7dfaa22eb 100644 --- a/lib/include/srsran/interfaces/ue_phy_interfaces.h +++ b/lib/include/srsran/interfaces/ue_phy_interfaces.h @@ -26,6 +26,15 @@ namespace srsue { +struct cfr_args_t { + bool enable = false; + srsran_cfr_mode_t mode = SRSRAN_CFR_THR_MANUAL; + float manual_thres = 2.0f; + float strength = 1.0f; + float auto_target_papr = 7.0f; + float ema_alpha = 1.0f / (float)SRSRAN_CP_NORM_NSYMB; +}; + struct phy_args_t { std::string type = "lte"; srsran::phy_log_args_t log; @@ -96,6 +105,8 @@ struct phy_args_t { srsran::channel::args_t dl_channel_args; srsran::channel::args_t ul_channel_args; + + cfr_args_t cfr_args; ///< Stores user-defined CFR configuration }; /* RAT agnostic Interface MAC -> PHY */ diff --git a/lib/include/srsran/phy/cfr/cfr.h b/lib/include/srsran/phy/cfr/cfr.h index a53204de5..c3744c67d 100644 --- a/lib/include/srsran/phy/cfr/cfr.h +++ b/lib/include/srsran/phy/cfr/cfr.h @@ -20,12 +20,14 @@ #define CFR_EMA_INIT_AVG_PWR 0.1 /** - * @brief CFR manual threshold or PAPR limiting with Moving Average or EMA power averaging + * @brief CFR manual threshold or PAPR limiting with CMA or EMA power averaging */ typedef enum SRSRAN_API { - SRSRAN_CFR_THR_MANUAL = 1, - SRSRAN_CFR_THR_AUTO_CMA = 2, - SRSRAN_CFR_THR_AUTO_EMA = 3 + SRSRAN_CFR_THR_INVALID, + SRSRAN_CFR_THR_MANUAL, + SRSRAN_CFR_THR_AUTO_CMA, + SRSRAN_CFR_THR_AUTO_EMA, + SRSRAN_CFR_NOF_MODES } srsran_cfr_mode_t; /** @@ -115,4 +117,14 @@ SRSRAN_API int srsran_cfr_set_threshold(srsran_cfr_t* q, float thres); */ SRSRAN_API int srsran_cfr_set_papr(srsran_cfr_t* q, float papr); +/** + * @brief Converts a string representing a CFR mode from the config files into srsran_cfr_mode_t type + * + * @param[in] mode_str the cfr.mode string coming from the config file + * @return SRSRAN_CFR_THR_INVALID if mode_str is empty, + * SRSRAN_CFR_THR_INVALID if mode_str is not recognised, + * otherwise it returns the corresponding srsran_cfr_mode_t value. + */ +SRSRAN_API srsran_cfr_mode_t srsran_cfr_str2mode(const char* mode_str); + #endif // SRSRAN_CFR_H diff --git a/lib/include/srsran/phy/ue/ue_ul.h b/lib/include/srsran/phy/ue/ue_ul.h index bc8567af1..f1f01f4e8 100644 --- a/lib/include/srsran/phy/ue/ue_ul.h +++ b/lib/include/srsran/phy/ue/ue_ul.h @@ -99,6 +99,8 @@ typedef struct SRSRAN_API { srsran_ra_ul_pusch_hopping_t hopping; + srsran_cfr_cfg_t cfr_config; + cf_t* out_buffer; cf_t* refsignal; cf_t* srs_signal; @@ -112,6 +114,8 @@ SRSRAN_API void srsran_ue_ul_free(srsran_ue_ul_t* q); SRSRAN_API int srsran_ue_ul_set_cell(srsran_ue_ul_t* q, srsran_cell_t cell); +SRSRAN_API int srsran_ue_ul_set_cfr(srsran_ue_ul_t* q, const srsran_cfr_cfg_t* cfr); + SRSRAN_API int srsran_ue_ul_pregen_signals(srsran_ue_ul_t* q, srsran_ue_ul_cfg_t* cfg); SRSRAN_API int srsran_ue_ul_dci_to_pusch_grant(srsran_ue_ul_t* q, diff --git a/lib/src/phy/cfr/cfr.c b/lib/src/phy/cfr/cfr.c index 325c3cc2a..82c202716 100644 --- a/lib/src/phy/cfr/cfr.c +++ b/lib/src/phy/cfr/cfr.c @@ -153,6 +153,10 @@ int srsran_cfr_init(srsran_cfr_t* q, srsran_cfr_cfg_t* cfg) ERROR("Error, invalid configuration"); goto clean_exit; } + if (cfg->cfr_mode == SRSRAN_CFR_THR_INVALID) { + ERROR("Error, invalid CFR mode"); + goto clean_exit; + } if (cfg->cfr_mode == SRSRAN_CFR_THR_MANUAL && cfg->manual_thr <= 0) { ERROR("Error, invalid configuration for manual threshold"); goto clean_exit; @@ -321,6 +325,9 @@ bool srsran_cfr_params_valid(srsran_cfr_cfg_t* cfr_conf) if (cfr_conf == NULL) { return false; } + if (cfr_conf->cfr_mode == SRSRAN_CFR_THR_INVALID) { + return false; + } if (cfr_conf->alpha < 0 || cfr_conf->alpha > 1) { return false; } @@ -365,3 +372,22 @@ int srsran_cfr_set_papr(srsran_cfr_t* q, float papr) q->max_papr_lin = srsran_convert_dB_to_power(q->cfg.max_papr_db); return SRSRAN_SUCCESS; } + +srsran_cfr_mode_t srsran_cfr_str2mode(const char* mode_str) +{ + srsran_cfr_mode_t ret; + if (strcmp(mode_str, "")) { + if (!strcmp(mode_str, "manual")) { + ret = SRSRAN_CFR_THR_MANUAL; + } else if (!strcmp(mode_str, "auto_cma")) { + ret = SRSRAN_CFR_THR_AUTO_CMA; + } else if (!strcmp(mode_str, "auto_ema")) { + ret = SRSRAN_CFR_THR_AUTO_EMA; + } else { + ret = SRSRAN_CFR_THR_INVALID; // mode_str is not recognised + } + } else { + ret = SRSRAN_CFR_THR_INVALID; // mode_str is empty + } + return ret; +} diff --git a/lib/src/phy/cfr/test/cfr_test.c b/lib/src/phy/cfr/test/cfr_test.c index 368178457..5e9a758fc 100644 --- a/lib/src/phy/cfr/test/cfr_test.c +++ b/lib/src/phy/cfr/test/cfr_test.c @@ -21,13 +21,9 @@ #define MAX_ACPR_DB -100 -// CFR type test args -static char cfr_manual_str[] = "manual"; -static char cfr_auto_cma_str[] = "auto_cma"; -static char cfr_auto_ema_str[] = "auto_ema"; // Default CFR type -static char* cfr_type_arg = cfr_manual_str; +static char* cfr_mode_str = "manual"; static int nof_prb = -1; static srsran_cp_t cp = SRSRAN_CP_NORM; @@ -60,7 +56,7 @@ static void usage(char* prog) printf("\t-e extended cyclic prefix [Default Normal]\n"); printf("\t-f Number of frames [Default %d]\n", nof_frames); printf("\t-r Number of repetitions [Default %d]\n", nof_repetitions); - printf("\t-m CFR mode: %s, %s, %s [Default %s]\n", cfr_manual_str, cfr_auto_cma_str, cfr_auto_ema_str, cfr_type_arg); + printf("\t-m CFR mode: manual, auto_cma, auto_ema [Default %s]\n", cfr_mode_str); printf("\t-d Use DC subcarrier: [Default DC empty]\n"); printf("\t-a CFR alpha: [Default %.2f]\n", alpha); printf("\t-t CFR manual threshold: [Default %.2f]\n", thr_manual); @@ -89,7 +85,7 @@ static int parse_args(int argc, char** argv) nof_frames = (int)strtol(argv[optind], NULL, 10); break; case 'm': - cfr_type_arg = argv[optind]; + cfr_mode_str = argv[optind]; break; case 'a': alpha = strtof(argv[optind], NULL); @@ -140,13 +136,8 @@ int main(int argc, char** argv) goto clean_exit; } - if (!strcmp(cfr_type_arg, cfr_manual_str)) { - cfr_mode = SRSRAN_CFR_THR_MANUAL; - } else if (!strcmp(cfr_type_arg, cfr_auto_cma_str)) { - cfr_mode = SRSRAN_CFR_THR_AUTO_CMA; - } else if (!strcmp(cfr_type_arg, cfr_auto_ema_str)) { - cfr_mode = SRSRAN_CFR_THR_AUTO_EMA; - } else { + cfr_mode = srsran_cfr_str2mode(cfr_mode_str); + if (cfr_mode == SRSRAN_CFR_THR_INVALID) { ERROR("CFR mode is not recognised"); goto clean_exit; } @@ -193,6 +184,11 @@ int main(int argc, char** argv) cfr_tx_cfg.ema_alpha = ema_alpha; cfr_tx_cfg.dc_sc = dc_empty; + if (!srsran_cfr_params_valid(&cfr_tx_cfg)) { + ERROR("Invalid CFR configuration"); + goto clean_exit; + } + if (srsran_cfr_init(&cfr, &cfr_tx_cfg)) { ERROR("Error initializing CFR"); goto clean_exit; diff --git a/lib/src/phy/dft/ofdm.c b/lib/src/phy/dft/ofdm.c index fa349fb31..0e2315b6f 100644 --- a/lib/src/phy/dft/ofdm.c +++ b/lib/src/phy/dft/ofdm.c @@ -702,7 +702,8 @@ int srsran_ofdm_set_cfr(srsran_ofdm_t* q, srsran_cfr_cfg_t* cfr) q->cfg.cfr_tx_cfg.symbol_sz = q->cfg.symbol_sz; q->cfg.cfr_tx_cfg.symbol_bw = q->nof_re; - // in the DL, the DC carrier is empty but still counts when designing the filter BW + // in the LTE DL, the DC carrier is empty but still counts when designing the filter BW + // in the LTE UL, the DC carrier is used q->cfg.cfr_tx_cfg.dc_sc = (!q->cfg.keep_dc) && (!isnormal(q->cfg.freq_shift_f)); if (q->cfg.cfr_tx_cfg.cfr_enable) { if (srsran_cfr_init(&q->tx_cfr, &q->cfg.cfr_tx_cfg) < SRSRAN_SUCCESS) { diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index ea821a6f2..c71567506 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -165,6 +165,25 @@ int srsran_ue_ul_set_cell(srsran_ue_ul_t* q, srsran_cell_t cell) return ret; } +int srsran_ue_ul_set_cfr(srsran_ue_ul_t* q, const srsran_cfr_cfg_t* cfr) +{ + if (q == NULL || cfr == NULL) { + ERROR("Error, invalid inputs"); + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Copy the cfr config into the UE + q->cfr_config = *cfr; + + // Set the cfr for the fft's + if (srsran_ofdm_set_cfr(&q->fft, &q->cfr_config) < SRSRAN_SUCCESS) { + ERROR("Error setting the CFR for the fft"); + return SRSRAN_ERROR; + } + + return SRSRAN_SUCCESS; +} + int srsran_ue_ul_pregen_signals(srsran_ue_ul_t* q, srsran_ue_ul_cfg_t* cfg) { if (q->signals_pregenerated) { diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 0cc0e0db9..2118e1048 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -378,18 +378,11 @@ void parse_args(all_args_t* args, int argc, char* argv[]) exit(1); } - // convert CFR mode - if (!cfr_mode.empty()) { - if (cfr_mode == "manual") { - args->phy.cfr_args.mode = SRSRAN_CFR_THR_MANUAL; - } else if (cfr_mode == "auto_cma") { - args->phy.cfr_args.mode = SRSRAN_CFR_THR_AUTO_CMA; - } else if (cfr_mode == "auto_ema") { - args->phy.cfr_args.mode = SRSRAN_CFR_THR_AUTO_EMA; - } else { - cout << "Error, invalid CFR mode: " << cfr_mode << endl; - exit(1); - } + // parse the CFR mode string + args->phy.cfr_args.mode = srsran_cfr_str2mode(cfr_mode.c_str()); + if (args->phy.cfr_args.mode == SRSRAN_CFR_THR_INVALID) { + cout << "Error, invalid CFR mode: " << cfr_mode << endl; + exit(1); } // Apply all_level to any unset layers diff --git a/srsue/hdr/phy/phy_common.h b/srsue/hdr/phy/phy_common.h index 167c607b5..6de05adec 100644 --- a/srsue/hdr/phy/phy_common.h +++ b/srsue/hdr/phy/phy_common.h @@ -306,6 +306,8 @@ public: } } + srsran_cfr_cfg_t get_cfr_config() { return cfr_config; } + private: std::mutex meas_mutex; @@ -323,6 +325,8 @@ private: std::array avg_noise = {}; std::array avg_rsrp_neigh = {}; + srsran_cfr_cfg_t cfr_config = {}; + static constexpr uint32_t pcell_report_period = 20; static constexpr uint32_t update_rxgain_period = 10; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 8d89be9b4..d6dbe5e25 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -59,8 +59,9 @@ string config_file; static int parse_args(all_args_t* args, int argc, char* argv[]) { - bool use_standard_lte_rates = false; + bool use_standard_lte_rates = false; std::string scs_khz, ssb_scs_khz; // temporary value to store integer + std::string cfr_mode; // Command line only options bpo::options_description general("General options"); @@ -239,6 +240,14 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("channel.ul.hst.fd_hz", bpo::value(&args->phy.ul_channel_args.hst_fd_hz)->default_value(+750.0f), "Doppler frequency in Hz") ("channel.ul.hst.init_time_s", bpo::value(&args->phy.ul_channel_args.hst_init_time_s)->default_value(0), "Initial time in seconds") + /* CFR section */ + ("cfr.enable", bpo::value(&args->phy.cfr_args.enable)->default_value(args->phy.cfr_args.enable), "CFR enable") + ("cfr.mode", bpo::value(&cfr_mode)->default_value("manual"), "CFR mode") + ("cfr.manual_thres", bpo::value(&args->phy.cfr_args.manual_thres)->default_value(args->phy.cfr_args.manual_thres), "Fixed manual clipping threshold for CFR manual mode") + ("cfr.strength", bpo::value(&args->phy.cfr_args.strength)->default_value(args->phy.cfr_args.strength), "CFR ratio between amplitude-limited vs original signal (0 to 1)") + ("cfr.auto_target_papr", bpo::value(&args->phy.cfr_args.auto_target_papr)->default_value(args->phy.cfr_args.auto_target_papr), "Signal PAPR target (in dB) in CFR auto modes") + ("cfr.ema_alpha", bpo::value(&args->phy.cfr_args.ema_alpha)->default_value(args->phy.cfr_args.ema_alpha), "Alpha coefficient for the power average in auto_ema mode (0 to 1)") + /* PHY section */ ("phy.worker_cpu_mask", bpo::value(&args->phy.worker_cpu_mask)->default_value(-1), @@ -548,6 +557,13 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) args->stack.usim.using_op = vm.count("usim.op"); } + // parse the CFR mode string + args->phy.cfr_args.mode = srsran_cfr_str2mode(cfr_mode.c_str()); + if (args->phy.cfr_args.mode == SRSRAN_CFR_THR_INVALID) { + cout << "Error, invalid CFR mode: " << cfr_mode << endl; + exit(1); + } + // Apply all_level to any unset layers if (vm.count("log.all_level")) { if (!vm.count("log.rf_level")) { diff --git a/srsue/src/phy/lte/cc_worker.cc b/srsue/src/phy/lte/cc_worker.cc index e06bbde39..26880884d 100644 --- a/srsue/src/phy/lte/cc_worker.cc +++ b/srsue/src/phy/lte/cc_worker.cc @@ -47,6 +47,8 @@ cc_worker::cc_worker(uint32_t cc_idx_, uint32_t max_prb, srsue::phy_common* phy_ cc_idx = cc_idx_; phy = phy_; + srsran_cfr_cfg_t cfr_config = phy->get_cfr_config(); + signal_buffer_max_samples = 3 * SRSRAN_SF_LEN_PRB(max_prb); for (uint32_t i = 0; i < phy->args->nof_rx_ant; i++) { @@ -72,6 +74,11 @@ cc_worker::cc_worker(uint32_t cc_idx_, uint32_t max_prb, srsue::phy_common* phy_ return; } + if (srsran_ue_ul_set_cfr(&ue_ul, &cfr_config) < SRSRAN_SUCCESS) { + Error("Setting the CFR"); + return; + } + phy->set_ue_dl_cfg(&ue_dl_cfg); phy->set_ue_ul_cfg(&ue_ul_cfg); phy->set_pdsch_cfg(&ue_dl_cfg.cfg.pdsch); diff --git a/srsue/src/phy/phy_common.cc b/srsue/src/phy/phy_common.cc index 653180e4d..0ca17c9ec 100644 --- a/srsue/src/phy/phy_common.cc +++ b/srsue/src/phy/phy_common.cc @@ -56,6 +56,14 @@ void phy_common::init(phy_args_t* _args, ul_channel = srsran::channel_ptr( new srsran::channel(args->ul_channel_args, args->nof_lte_carriers * args->nof_rx_ant, logger)); } + + // Init the CFR config struct with the CFR args + cfr_config.cfr_enable = args->cfr_args.enable; + cfr_config.cfr_mode = args->cfr_args.mode; + cfr_config.alpha = args->cfr_args.strength; + cfr_config.manual_thr = args->cfr_args.manual_thres; + cfr_config.max_papr_db = args->cfr_args.auto_target_papr; + cfr_config.ema_alpha = args->cfr_args.ema_alpha; } void phy_common::set_ue_dl_cfg(srsran_ue_dl_cfg_t* ue_dl_cfg) diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 8e6f2709f..f51ee9e47 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -284,6 +284,33 @@ int ue::parse_args(const all_args_t& args_) args.stack.nas_5g.pdu_session_cfgs.push_back({args.stack.nas.apn_name}); } + // Validate the CFR args + srsran_cfr_cfg_t cfr_test_cfg = {}; + cfr_test_cfg.cfr_enable = args.phy.cfr_args.enable; + cfr_test_cfg.cfr_mode = args.phy.cfr_args.mode; + cfr_test_cfg.alpha = args.phy.cfr_args.strength; + cfr_test_cfg.manual_thr = args.phy.cfr_args.manual_thres; + cfr_test_cfg.max_papr_db = args.phy.cfr_args.auto_target_papr; + cfr_test_cfg.ema_alpha = args.phy.cfr_args.ema_alpha; + + if (!srsran_cfr_params_valid(&cfr_test_cfg)) { + srsran::console("Invalid CFR parameters: cfr_mode=%d, alpha=%.2f, manual_thr=%.2f, \n " + "max_papr_db=%.2f, ema_alpha=%.2f\n", + cfr_test_cfg.cfr_mode, + cfr_test_cfg.alpha, + cfr_test_cfg.manual_thr, + cfr_test_cfg.max_papr_db, + cfr_test_cfg.ema_alpha); + + logger.error("Invalid CFR parameters: cfr_mode=%d, alpha=%.2f, manual_thr=%.2f, max_papr_db=%.2f, ema_alpha=%.2f\n", + cfr_test_cfg.cfr_mode, + cfr_test_cfg.alpha, + cfr_test_cfg.manual_thr, + cfr_test_cfg.max_papr_db, + cfr_test_cfg.ema_alpha); + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; } diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 59f36dacd..746c45979 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -389,6 +389,33 @@ enable = false [phy.nr] #store_pdsch_ko = false +##################################################################### +# CFR configuration options +# +# The CFR module provides crest factor reduction for the transmitted signal. +# +# enable: Enable or disable the CFR. Default: disabled +# +# mode: manual: CFR threshold is set by cfr_manual_thres (default). +# auto_ema: CFR threshold is adaptive based on the signal PAPR. Power avg. with Exponential Moving Average. +# The time constant of the averaging can be tweaked with the ema_alpha parameter. +# auto_cma: CFR threshold is adaptive based on the signal PAPR. Power avg. with Cumulative Moving Average. +# Use with care, as CMA's increasingly slow response may be unsuitable for most use cases. +# +# strength: Ratio between amplitude-limited vs unprocessed signal (0 to 1). Default: 1 +# manual_thres: Fixed manual clipping threshold for CFR manual mode. Default: 2 +# auto_target_papr: Signal PAPR target (in dB) in CFR auto modes. output PAPR can be higher due to peak smoothing. Default: 7 +# ema_alpha: Alpha coefficient for the power average in auto_ema mode. Default: 1/7 +# +##################################################################### +[cfr] +#enable = false +#mode = manual +#manual_thres = 2.0 +#strength = 1.0 +#auto_target_papr = 7.0 +#ema_alpha = 0.0143 + ##################################################################### # Simulation configuration options #