/* Cesar project {{{ * * Copyright (C) 2008 Spidcom * * <<>> * * }}} */ /** * \file hal/phy/src/tx.c * \brief HAL Phy TX functions. * \ingroup hal_phy */ #include "common/std.h" #include "inc/context.h" #include "inc/regs.h" #include "hal/leon/itc2.h" #include "hal/arch/arch.h" void /*ARCH_ILRAM*/ phy_tx_fc10 (phy_t *ctx, u32 date, u32 fc_10) { dbg_claim (ctx); dbg_claim (BF_CHECK (PHY_DSPSS_TX_FC_10__FC, fc_10)); PHY_TRACE (TX_FC10, fc_10); /* Set FC 1.0, will be created later. */ PHY_DSPSS_TX_FC_10 = BF_SHIFT (PHY_DSPSS_TX_FC_10__FC, fc_10) | BF_MASK (PHY_DSPSS_TX_FC_10__CRC); /* Create FC 1.0. */ PHY_TRACE_DATE_WARNING (date - PHY_FC_10_PREPARATION_DELAY_TCK - PHY_TX_HARDWARE_DELAY_TCK); PHY_PRATIC_TIMER_6_DATE = date - PHY_FC_10_PREPARATION_DELAY_TCK - PHY_TX_HARDWARE_DELAY_TCK; PHY_PRATIC_TIMER_6_CTRL = BF_FILL (PHY_PRATIC_TIMER_X_CTRL, (ACTION, PHY_PRATIC_ACTION__CREATE_FC_10), (VALID, 1)); } static void ARCH_ILRAM phy_tx_param_set_gil (phy_t *ctx, phy_fc_mode_t fc_mode, phy_gil_t gil) { dbg_claim (ctx); dbg_claim (fc_mode < PHY_FC_MODE_NB && gil < PHY_GIL_NB); /* Set GIL and symbol length. */ uint sl; volatile u32 *reg = &PHY_DSPSS_TX_GUARD_LENGTH_0; /* Fill guard lengths. */ if (PHY_FC_MODE_IS_HYBRID (fc_mode)) *reg++ = PHY_DSPSS_TX_GUARD_LENGTH__VALUE_FC_10; *reg++ = PHY_DSPSS_TX_GUARD_LENGTH__VALUE_FC_AV; if (PHY_FC_MODE_IS_TWO_SYMBOLS (fc_mode)) *reg++ = PHY_DSPSS_TX_GUARD_LENGTH__VALUE_FC_AV; *reg++ = PHY_DSPSS_TX_GUARD_LENGTH__VALUE_567; *reg++ = PHY_DSPSS_TX_GUARD_LENGTH__VALUE_567; while (reg != &PHY_DSPSS_TX_SYMB_LENGTH_0) *reg++ = ctx->gil_durations_table[gil]; /* Fill symbol length. */ if (PHY_FC_MODE_IS_HYBRID (fc_mode)) { sl = PHY_DSPSS_TX_SYMB_LENGTH__VALUE_PRE_10; *reg++ = sl; sl += PHY_DSPSS_TX_SYMB_LENGTH__VALUE_FC_10; *reg++ = sl; } else { sl = PHY_DSPSS_TX_SYMB_LENGTH__VALUE_PRE; *reg++ = sl; } sl += PHY_DSPSS_TX_SYMB_LENGTH__VALUE_FC_AV; *reg++ = sl; if (PHY_FC_MODE_IS_TWO_SYMBOLS (fc_mode)) { sl += PHY_DSPSS_TX_SYMB_LENGTH__VALUE_FC_AV; *reg++ = sl; } sl += PHY_DSPSS_TX_SYMB_LENGTH__VALUE_DATA; *reg++ = sl; sl += PHY_DSPSS_TX_SYMB_LENGTH__VALUE_DATA; *reg++ = sl; while (reg != &PHY_DSPSS_TX_SYMB_LENGTH_5 + 1) *reg++ = sl; } extern inline void phy_tx_param_common (phy_t *ctx, phy_fc_mode_t fc_mode, bool short_ppdu, bool sound, uint sound_nb_pb, u32 mod_fecrate_pb_size, phy_gil_t gil) { dbg_claim (ctx); dbg_claim ((!sound && sound_nb_pb == 1) || (sound && !short_ppdu && sound_nb_pb > 0 && sound_nb_pb <= 4)); dbg_claim (fc_mode < PHY_FC_MODE_NB && ((short_ppdu == false && (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) || short_ppdu == true)); /* TX parameters. */ if (short_ppdu) { PHY_DSPSS_TX_PARAM = BF_FILL (PHY_DSPSS_TX_PARAM, (FC_MODE, fc_mode), (LONG_PPDU, 0)) | PHY_DSPSS_TX_PARAM__DEFAULT; } else { PHY_DSPSS_TX_PARAM = BF_FILL (PHY_DSPSS_TX_PARAM, (FC_MODE, fc_mode), (LONG_PPDU, 1), (TMBI, 0), (SOUND_FRAME, sound), (NB_PB_SOUND, sound_nb_pb - 1)) | mod_fecrate_pb_size | PHY_DSPSS_TX_PARAM__DEFAULT; /* Remember GIL. */ ctx->tx_gil = gil; } ctx->tx_fc_mode = fc_mode; /* Set GIL. */ phy_tx_param_set_gil (ctx, fc_mode, ctx->tx_gil); } void ARCH_ILRAM phy_tx_param_ (phy_t *ctx, phy_fc_mode_t fc_mode, u32 mod_fecrate_pb_size, phy_gil_t gil PHY_TRACE_SYMBOL_NB (uint symbol_nb)) { dbg_claim (ctx); PHY_TRACE (TX_PARAM, fc_mode, mod_fecrate_pb_size, gil, symbol_nb); phy_tx_param_common (ctx, fc_mode, false, false, 1, mod_fecrate_pb_size, gil); } void ARCH_ILRAM phy_tx_param_short (phy_t *ctx, phy_fc_mode_t fc_mode) { dbg_claim (ctx); PHY_TRACE (TX_PARAM_SHORT, fc_mode); phy_tx_param_common (ctx, fc_mode, true, false, 1, 0, PHY_GIL_417); } void ARCH_ILRAM phy_tx_param_sound_ (phy_t *ctx, phy_fc_mode_t fc_mode, uint nb_pb, u32 mod_fecrate_pb_size, phy_gil_t gil PHY_TRACE_SYMBOL_NB (uint symbol_nb)) { dbg_claim (ctx); PHY_TRACE (TX_PARAM_SOUND, fc_mode, nb_pb, mod_fecrate_pb_size, gil, symbol_nb); phy_tx_param_common (ctx, fc_mode, false, true, nb_pb, mod_fecrate_pb_size, gil); } void ARCH_ILRAM phy_tx_frame_ (phy_t *ctx, u32 date, u32 want_conf__stop_tx_on_prp_lost, const u32 fc_av[4]) { dbg_claim (ctx); dbg_claim (fc_av); PHY_TRACE (TX_FRAME, phy_date (), date, want_conf__stop_tx_on_prp_lost, fc_av[0]); /* Set FC. */ PHY_DSPSS_TX_FC_AV_0 = fc_av[0]; PHY_DSPSS_TX_FC_AV_1 = fc_av[1]; PHY_DSPSS_TX_FC_AV_2 = fc_av[2]; PHY_DSPSS_TX_FC_AV_3 = fc_av[3]; /* Use CAP 3 if PRP should be ignored. */ if (!(want_conf__stop_tx_on_prp_lost & PHY_STOP_ON_PRP_LOST)) PHY_PRATIC_CSMA = BF_FILL (PHY_PRATIC_CSMA, (MPDU_CAP, 3)); /* Access conf. */ LEON_ITC2_CLEAR = 1 << LEON_ITC2_IT__PRATIC_ACCESS_CONF; if (want_conf__stop_tx_on_prp_lost & PHY_WANT_CONF) LEON_ITC2_MASK |= 1 << LEON_ITC2_IT__PRATIC_ACCESS_CONF; else LEON_ITC2_MASK &= ~(1 << LEON_ITC2_IT__PRATIC_ACCESS_CONF); /* Program TX. */ PHY_TRACE_DATE_WARNING (date - PHY_TX_HARDWARE_DELAY_TCK); PHY_PRATIC_TIMER_2_DATE = date - PHY_TX_HARDWARE_DELAY_TCK; PHY_PRATIC_TIMER_2_CTRL = BF_FILL (PHY_PRATIC_TIMER_X_CTRL, (ACTION, PHY_PRATIC_ACTION__START_TX), (VALID, 1)); /* Cancel FC 1.0 preparation if AV. */ dbg_claim (ctx->tx_fc_mode < PHY_FC_MODE_NB); if (!PHY_FC_MODE_IS_HYBRID (ctx->tx_fc_mode)) PHY_PRATIC_TIMER_6_CTRL = 0; } void ARCH_ILRAM phy_tx_prepare (phy_t *ctx) { dbg_claim (ctx); PHY_TRACE (TX_PREPARE, phy_date ()); PHY_PRATIC_IMMEDIATE_ACTION = PHY_PRATIC_ACTION__PBD_START; } void ARCH_ILRAM phy_tx_cancel (phy_t *ctx) { dbg_claim (ctx); PHY_TRACE (TX_CANCEL); /* Cancel all timers used by TX. */ PHY_PRATIC_TIMER_2_CTRL = 0; PHY_PRATIC_TIMER_6_CTRL = 0; } void phy_tx_scale_adapt_exp_set (phy_t *ctx, u8 exp) { dbg_claim (ctx); PHY_DSPSS_TX_SCALE_ADAPT_BLK_EXP = BF_SET (PHY_DSPSS_TX_SCALE_ADAPT_BLK_EXP, PHY_DSPSS_TX_SCALE_ADAPT_BLK_EXP__STEP, exp); } void phy_tx_scale_adapt_set (phy_t *ctx, u16 value) { dbg_claim (ctx); PHY_DSPSS_TX_SCALE_ADAPT = BF_SET (PHY_DSPSS_TX_SCALE_ADAPT, PHY_DSPSS_TX_SCALE_ADAPT__GAIN, value); }