/* Cesar project {{{ * * Copyright (C) 2008 Spidcom * * <<>> * * }}} */ /** * \file hal/phy/src/rx.c * \brief HAL Phy RX functions. * \ingroup hal_phy */ #include "common/std.h" #include "inc/context.h" #include "inc/regs.h" #include "hal_phy_params.h" #include "hal/arch/arch.h" void ARCH_ILRAM phy_rx_param (phy_t *ctx, phy_fc_mode_t fc_mode) { dbg_claim (ctx); dbg_claim (fc_mode < PHY_FC_MODE_NB); PHY_TRACE (RX_PARAM, fc_mode); PHY_DSPSS_RX_PARAM = BF_FILL (PHY_DSPSS_RX_PARAM, (FC_MODE, fc_mode)) | PHY_DSPSS_RX_PARAM__DEFAULT; ctx->rx_fc_mode = fc_mode; } void ARCH_ILRAM phy_rx_activate (phy_t *ctx, bool now, u32 date, bool flag) { dbg_claim (ctx); /* Cancel previous programed action. */ PHY_PRATIC_TIMER_3_CTRL = 0; PHY_PRATIC_TIMER_4_CTRL = 0; /* Program new action. */ if (now) { PHY_TRACE (RX_ACTIVATE_NOW, phy_date (ctx), flag); if (flag) PHY_PRATIC_IMMEDIATE_ACTION = PHY_PRATIC_ACTION__SEARCH_PRE; else PHY_PRATIC_IMMEDIATE_ACTION = PHY_PRATIC_ACTION__STOP_MAFADESE; } else { PHY_TRACE (RX_ACTIVATE, date, flag); PHY_PRATIC_TIMER_4_DATE = date; if (flag) { PHY_PRATIC_TIMER_3_DATE = date - PHY_START_MAFADESE_DELAY_TCK; PHY_PRATIC_TIMER_3_CTRL = BF_SHIFT (PHY_PRATIC_TIMER_X_CTRL__ACTION, PHY_PRATIC_ACTION__START_MAFADESE) | BF_MASK (PHY_PRATIC_TIMER_X_CTRL__VALID); PHY_PRATIC_TIMER_4_CTRL = BF_SHIFT (PHY_PRATIC_TIMER_X_CTRL__ACTION, PHY_PRATIC_ACTION__SEARCH_PRE) | BF_MASK (PHY_PRATIC_TIMER_X_CTRL__VALID); } else { PHY_PRATIC_TIMER_4_CTRL = BF_SHIFT (PHY_PRATIC_TIMER_X_CTRL__ACTION, PHY_PRATIC_ACTION__STOP_MAFADESE) | BF_MASK (PHY_PRATIC_TIMER_X_CTRL__VALID); } } } extern inline void phy_rx_prepare_common (phy_t *ctx, bool short_ppdu, bool sound, uint nb_pb, u32 mod_fecrate_pb_size, phy_gil_t gil, uint symbol_nb, uint tcc_halfit) { dbg_claim (ctx); dbg_claim (ctx->rx_fc_mode < PHY_FC_MODE_NB); dbg_claim (!sound || (sound && !short_ppdu)); dbg_claim ((short_ppdu && nb_pb == 0 && symbol_nb == 0 && tcc_halfit == 0) || (!short_ppdu && (BF_GET (PHY_COMBO_PARAMS__MOD, mod_fecrate_pb_size) < PHY_MOD_NONE) && (BF_GET (PHY_COMBO_PARAMS__FECRATE, mod_fecrate_pb_size) < PHY_FEC_RATE_NONE) && (BF_GET (PHY_COMBO_PARAMS__PB_SIZE, mod_fecrate_pb_size) < PHY_PB_SIZE_NONE) && (mod_fecrate_pb_size & ~(BF_MASK (PHY_COMBO_PARAMS__MOD) | BF_MASK (PHY_COMBO_PARAMS__FECRATE) | BF_MASK (PHY_COMBO_PARAMS__PB_SIZE))) == 0 && gil < PHY_GIL_NB && BF_CHECK (PHY_DSPSS_RESYS_PARAM__LAST_SYMB_INDEX, symbol_nb) && ((!sound && nb_pb > 0 && nb_pb < 255 && tcc_halfit > 0 && tcc_halfit <= 31) || (sound && nb_pb == 0 && tcc_halfit == 0)))); /* Set RX parameters. */ if (short_ppdu) { PHY_DSPSS_RX_PARAM = BF_FILL (PHY_DSPSS_RX_PARAM, (FC_MODE, ctx->rx_fc_mode), (LONG_PPDU, 0)) | PHY_DSPSS_RX_PARAM__DEFAULT; } else { PHY_DSPSS_RX_PARAM = BF_FILL (PHY_DSPSS_RX_PARAM, (FC_MODE, ctx->rx_fc_mode), (LONG_PPDU, 1), (TMBI, 0), (SOUND_FRAME, sound ? 1 : 0), (SOUND_ENABLE, sound ? 1 : 0)) | mod_fecrate_pb_size | PHY_DSPSS_RX_PARAM__DEFAULT; /* TCC decoder parameters. */ if (!sound) { PHY_DSPSS_TCC_HALF_IT_LAST_PB = BF_FILL (PHY_DSPSS_TCC_HALF_IT_LAST_PB, (VALUE, PHY_PARAM_RX_FEC_PARAM__TCC_HALF_IT_DATA_LAST_PB), (ENABLED, 1), (PB_NB, nb_pb)); PHY_DSPSS_RX_FEC_PARAM = PHY_PARAMS (PHY_DSPSS, RX_FEC_PARAM, ME10DOI_MAX_IT, TCC_HALF_IT_FC, TCC_DYN_STOP, TCC_BER_PERIOD, TCC_THRESHOLD) | BF_FILL (PHY_DSPSS_RX_FEC_PARAM, (TCC_HALF_IT_DATA, tcc_halfit)); } } /* Freeze RESYS to write offset table. */ PHY_DSPSS_RESYS_PARAM = BF_FILL (PHY_DSPSS_RESYS_PARAM, (RESYS_ON, 1), (RESYS_FREEZE, 1)); /* Write offset table for GIL. */ (&PHY_BASE_ADDR_RESYS_OFFSET)[PHY_RESYS_GIL_OFFSET] = ctx->resys_gil_table[gil]; /* Unlock RESYS. */ PHY_DSPSS_RESYS_PARAM = BF_FILL (PHY_DSPSS_RESYS_PARAM, (RESYS_ON, 1), (RESYS_COND, 1), (LAST_SYMB_INDEX, ctx->fc_symbol_nb[ctx->rx_fc_mode] + symbol_nb)); } void ARCH_ILRAM phy_rx_prepare (phy_t *ctx, uint nb_pb, u32 mod_fecrate_pb_size, phy_gil_t gil, uint symbol_nb, uint tcc_halfit) { dbg_claim (ctx); /* Prepare. */ phy_rx_prepare_common (ctx, false, false, nb_pb, mod_fecrate_pb_size, gil, symbol_nb, tcc_halfit); /* Trace when done. */ PHY_TRACE (RX_PREPARE, phy_date (ctx), mod_fecrate_pb_size, gil, symbol_nb); } void ARCH_ILRAM phy_rx_prepare_short (phy_t *ctx) { dbg_claim (ctx); /* Prepare. */ phy_rx_prepare_common (ctx, true, false, 0, 0, PHY_GIL_417, 0, 0); /* Trace when done. */ PHY_TRACE (RX_PREPARE_SHORT, phy_date (ctx)); } void ARCH_ILRAM phy_rx_prepare_sound (phy_t *ctx, uint nb_pb, u32 mod_fecrate_pb_size, phy_gil_t gil, uint symbol_nb) { dbg_claim (ctx); /* Prepare. */ phy_tx_param_sound (ctx, ctx->rx_fc_mode, nb_pb, mod_fecrate_pb_size, gil); phy_rx_prepare_common (ctx, false, true, 0, mod_fecrate_pb_size, gil, symbol_nb, 0); /* Need to start PBDMA. */ ctx->pbdma_start_on_resys_it = true; /* Trace when done. */ PHY_TRACE (RX_PREPARE_SOUND, phy_date (ctx), nb_pb, mod_fecrate_pb_size, gil, symbol_nb); } u32 ARCH_ILRAM phy_rx_fc10 (phy_t *ctx) { dbg_claim (ctx); u32 fc10 = PHY_DSPSS_RX_FC_10; if ((fc10 & PHY_DSPSS_RX_FC_10__OK_MASK) == PHY_DSPSS_RX_FC_10__OK_MASK) { return BF_GET (PHY_DSPSS_RX_FC_10__FC, PHY_DSPSS_RX_FC_10); } else { return (u32) -1; } } u32 ARCH_ILRAM phy_rx_sysdate (phy_t *ctx) { dbg_claim (ctx); return PHY_PRATIC_SYS_LAST_RECEIVED_FRAME_DATE - BF_GET (PHY_DSPSS_RESYS_DETECT_OFFSET__PREAMBLE, PHY_DSPSS_RESYS_DETECT_OFFSET); }