Example #1
0
/*
 * \brief Write all shadow PIB variables to the transceiver
 *
 * This function writes all shadow PIB variables to the transceiver.
 * It is assumed that the radio does not sleep.
 */
void write_all_tal_pib_to_trx(void)
{
	uint8_t *ptr_to_reg;

	ptr_to_reg = (uint8_t *)&tal_pib.PANId;
	for (uint8_t i = 0; i < 2; i++) {
		trx_reg_write((RG_PAN_ID_0 + i), *ptr_to_reg);
		ptr_to_reg++;
	}

	ptr_to_reg = (uint8_t *)&tal_pib.IeeeAddress;
	for (uint8_t i = 0; i < 8; i++) {
		trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr_to_reg);
		ptr_to_reg++;
	}

	ptr_to_reg = (uint8_t *)&tal_pib.ShortAddress;
	for (uint8_t i = 0; i < 2; i++) {
		trx_reg_write((RG_SHORT_ADDR_0 + i), *ptr_to_reg);
		ptr_to_reg++;
	}

	/* Configure TX_ARET; CSMA and CCA */
	trx_bit_write(SR_CCA_MODE, tal_pib.CCAMode);

#ifdef SW_CONTROLLED_CSMA

	/*
	 * If receiver is enabled during backoff periods,
	 * CSMA and frame re-transmissions are handled by software.
	 * Setup trx for immediate transmission.
	 */
	trx_bit_write(SR_MAX_FRAME_RETRIES, 0);
	trx_bit_write(SR_MAX_CSMA_RETRIES, 7);
#else
	trx_bit_write(SR_MIN_BE, tal_pib.MinBE);
	trx_bit_write(SR_MAX_BE, tal_pib.MaxBE);
#endif

	trx_bit_write(SR_AACK_I_AM_COORD, tal_pib.PrivatePanCoordinator);

	/* set phy parameter */

	apply_channel_page_configuration(tal_pib.CurrentPage);

	{
		uint8_t reg_value;

		reg_value = convert_phyTransmitPower_to_reg_value(
				tal_pib.TransmitPower);
		trx_reg_write(RG_PHY_TX_PWR, reg_value);
	}

#ifdef PROMISCUOUS_MODE
	if (tal_pib.PromiscuousMode) {
		set_trx_state(CMD_RX_ON);
	}

#endif
}
Example #2
0
/**
 * \brief Set the default Power Values For Respective Pages and Channels
 */
static void set_default_tx_pwr(void)
{
	int8_t dbm_value;

	dbm_value = CONV_phyTransmitPower_TO_DBM(tal_pib.TransmitPower);

	if ((tal_pib.CurrentPage == 5) ||
			(tal_pib.CurrentPage == 18) ||
			(tal_pib.CurrentPage == 19)) {
		if ((tal_pib.CurrentChannel == 0) ||
				(tal_pib.CurrentChannel == 3)) {
			if (dbm_value > DEFAULT_TX_PWR_CHINA_CH_0_3) {
				dbm_value = DEFAULT_TX_PWR_CHINA_CH_0_3;
			}
		} else {
			if ((tal_pib.CurrentPage == 5) ||
					(tal_pib.CurrentPage == 18)) {
				if (dbm_value >
						DEFAULT_TX_PWR_OQPSK_RC_250_500)
				{
					dbm_value
						=
							DEFAULT_TX_PWR_OQPSK_RC_250_500;
				}
			}
		}
	} else if (tal_pib.CurrentPage == 0) {
		if (tal_pib.CurrentChannel == 0) {
			if (dbm_value > DEFAULT_TX_PWR_BPSK_20) {
				dbm_value = DEFAULT_TX_PWR_BPSK_20;
			}
		}
	} else {
		if (tal_pib.CurrentChannel == 0) {
			if (dbm_value >
					DEFAULT_TX_PWR_OQPSK_SIN_RC_100_200_400)
			{
				dbm_value
					=
						DEFAULT_TX_PWR_OQPSK_SIN_RC_100_200_400;
			}
		}
	}

	tal_pib.TransmitPower = TX_PWR_TOLERANCE | CONV_DBM_TO_phyTransmitPower(
			dbm_value);

	/*Handle other Channel and page combinations here*/
	limit_tx_pwr();

	trx_reg_write(RG_PHY_TX_PWR,
			convert_phyTransmitPower_to_reg_value(tal_pib.
			TransmitPower));
}
/**
 * @brief Write all shadow PIB variables to the transceiver
 *
 * This function writes all shadow PIB variables to the transceiver.
 * It is assumed that the radio does not sleep.
 */
void write_all_tal_pib_to_trx(void)
{
    uint8_t *ptr_to_reg;

    ptr_to_reg = (uint8_t *)&tal_pib.PANId;
    for (uint8_t i = 0; i < 2; i++)
    {
        pal_trx_reg_write((RG_PAN_ID_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    ptr_to_reg = (uint8_t *)&tal_pib.IeeeAddress;
    for (uint8_t i = 0; i < 8; i++)
    {
        pal_trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    ptr_to_reg = (uint8_t *)&tal_pib.ShortAddress;
    for (uint8_t i = 0; i < 2; i++)
    {
        pal_trx_reg_write((RG_SHORT_ADDR_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    /* configure TX_ARET; CSMA and CCA */
    pal_trx_bit_write(SR_CCA_MODE, tal_pib.CCAMode);
    pal_trx_bit_write(SR_MIN_BE, tal_pib.MinBE);

    pal_trx_bit_write(SR_AACK_I_AM_COORD, tal_pib.PrivatePanCoordinator);

    /* set phy parameter */
    pal_trx_bit_write(SR_MAX_BE, tal_pib.MaxBE);

#ifdef HIGH_DATA_RATE_SUPPORT
    apply_channel_page_configuration(tal_pib.CurrentPage);
#endif

    pal_trx_bit_write(SR_CHANNEL, tal_pib.CurrentChannel);
    {
        uint8_t reg_value;

        reg_value = convert_phyTransmitPower_to_reg_value(tal_pib.TransmitPower);
        pal_trx_bit_write(SR_TX_PWR, reg_value);
    }

#ifdef PROMISCUOUS_MODE
    if (tal_pib.PromiscuousMode)
    {
        set_trx_state(CMD_RX_ON);
    }
#endif
}
Example #4
0
/**
 * @brief Write all shadow PIB variables to the transceiver
 *
 * This function writes all shadow PIB variables to the transceiver.
 * It is assumed that the radio does not sleep.
 */
void write_all_tal_pib_to_trx(void)
{
    uint8_t *ptr_to_reg;

    /* configure RX_AACK */
    ptr_to_reg = (uint8_t *)&tal_pib.PANId;
    for (uint8_t i = 0; i < 2; i++)
    {
        pal_trx_reg_write((RG_PAN_ID_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    ptr_to_reg = (uint8_t *)&tal_pib.IeeeAddress;
    for (uint8_t i = 0; i < 8; i++)
    {
        pal_trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    ptr_to_reg = (uint8_t *)&tal_pib.ShortAddress;
    for (uint8_t i = 0; i < 2; i++)
    {
        pal_trx_reg_write((RG_SHORT_ADDR_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    /* configure TX_ARET; CSMA and CCA */
    {
        uint8_t reg_value;

        reg_value = convert_phyTransmitPower_to_reg_value(tal_pib.TransmitPower);
        pal_trx_bit_write(SR_TX_PWR, reg_value);
    }
    pal_trx_bit_write(SR_CCA_MODE, tal_pib.CCAMode);
    pal_trx_bit_write(SR_CHANNEL, tal_pib.CurrentChannel);
    pal_trx_bit_write(SR_MIN_BE, tal_pib.MinBE);

#ifdef PROMISCUOUS_MODE
    if (tal_pib.PromiscuousMode)
    {
        set_trx_state(CMD_RX_ON);
    }
#endif
}
Example #5
0
/**
 * @brief Write all shadow PIB variables to the transceiver
 *
 * This function writes all shadow PIB variables to the transceiver.
 * It is assumed that the radio does not sleep.
 */
void write_all_tal_pib_to_trx(void)
{
    uint8_t *ptr_to_reg;

    pal_trx_reg_write(RG_PAN_ID_0, (uint8_t)tal_pib_PANId);
    pal_trx_reg_write(RG_PAN_ID_1, (uint8_t)(tal_pib_PANId >> 8));

    ptr_to_reg = (uint8_t *)&tal_pib_IeeeAddress;
    for (uint8_t i = 0; i < 8; i++)
    {
        pal_trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    pal_trx_reg_write(RG_SHORT_ADDR_0, (uint8_t)tal_pib_ShortAddress);
    pal_trx_reg_write(RG_SHORT_ADDR_1, (uint8_t)(tal_pib_ShortAddress >> 8));

    /* configure TX_ARET; CSMA and CCA */
    pal_trx_bit_write(SR_CCA_MODE, tal_pib_CCAMode);
    pal_trx_bit_write(SR_MIN_BE, tal_pib_MinBE);

    pal_trx_bit_write(SR_AACK_I_AM_COORD, tal_pib_PrivatePanCoordinator);

    /* set phy parameter */
    pal_trx_bit_write(SR_MAX_BE, tal_pib_MaxBE);
    apply_channel_page_configuration(tal_pib_CurrentPage);

    {
        uint8_t reg_value;

        reg_value = convert_phyTransmitPower_to_reg_value(tal_pib_TransmitPower);
        pal_trx_reg_write(RG_PHY_TX_PWR, reg_value);
    }

#ifdef PROMISCUOUS_MODE
    if (tal_pib_PromiscuousMode)
    {
        set_trx_state(CMD_RX_ON);
    }
#endif
}
Example #6
0
retval_t tal_set_tx_pwr(bool type, int8_t pwr_value)
{
	uint64_t temp_var;
	int8_t tx_pwr_dbm = 0;
	/* modify the register for tx_pwr and set the tal_pib accordingly */
	if (true == type) {
		if (MAC_SUCCESS ==
				tal_convert_reg_value_to_dBm(pwr_value,
				&tx_pwr_dbm)) {
			temp_var = CONV_DBM_TO_phyTransmitPower(tx_pwr_dbm);
			tal_pib_set(phyTransmitPower, (pib_value_t *)&temp_var);

			/* To make sure that TX_PWR register is updated with the
			 * value whatever user povided.Otherwise lowest dBm
			 * power
			 * (highest reg value will be taken)
			 */
			trx_bit_write(SR_TX_PWR, pwr_value);
#if (TAL_TYPE == ATMEGARFA1)
			CONF_REG_WRITE();
#endif /* TAL_TYPE == ATMEGA128RFA1 */
			return MAC_SUCCESS;
		} else {
			/* return invalid parameter if out of range */
			return MAC_INVALID_PARAMETER;
		}
	} else {
		temp_var = CONV_DBM_TO_phyTransmitPower(pwr_value);
		tal_pib_set(phyTransmitPower, (pib_value_t *)&temp_var);
	}

	uint8_t reg_value = convert_phyTransmitPower_to_reg_value(
			tal_pib.TransmitPower);
	/* check the value written in the transceiver register */
	uint8_t temp = trx_bit_read(SR_TX_PWR);
	if (temp == reg_value) {
		return MAC_SUCCESS;
	} else {
		return FAILURE;
	}
}
Example #7
0
/*
 * \brief Sets a TAL PIB attribute
 *
 * This function is called to set the transceiver information base
 * attributes.
 *
 * \param attribute TAL infobase attribute ID
 * \param value TAL infobase attribute value to be set
 *
 * \return MAC_UNSUPPORTED_ATTRIBUTE if the TAL info base attribute is not found
 *         TAL_BUSY if the TAL is not in TAL_IDLE state. An exception is
 *         macBeaconTxTime which can be accepted by TAL even if TAL is not
 *         in TAL_IDLE state.
 *         MAC_SUCCESS if the attempt to set the PIB attribute was successful
 *         TAL_TRX_ASLEEP if trx is in SLEEP mode and access to trx is required
 */
retval_t tal_pib_set(uint8_t attribute, pib_value_t *value)
{
	/*
	 * Do not allow any changes while ED or TX is done.
	 * We allow changes during RX, but it's on the user's own risk.
	 */
#if (MAC_SCAN_ED_REQUEST_CONFIRM == 1)
	if (tal_state == TAL_ED) {
		Assert("TAL is busy" == 0);
		return TAL_BUSY;
	}

#endif /* (MAC_SCAN_ED_REQUEST_CONFIRM == 1) */

	/*
	 * Distinguish between PIBs that need to be changed in trx directly
	 * and those that are simple variable udpates.
	 * Ensure that the transceiver is not in SLEEP.
	 * If it is in SLEEP, change it to TRX_OFF.
	 * For all other state force TRX_OFF.
	 * Abort any TAL_BUSY state, because the change might have an impact to
	 * ongoing transactions.
	 */

	switch (attribute) {
	case macMaxFrameRetries:

		/*
		 * The new PIB value is not immediately written to the
		 * transceiver. This is done on a frame-by-frame base.
		 */
		tal_pib.MaxFrameRetries = value->pib_value_8bit;
		break;

	case macMaxCSMABackoffs:

		/*
		 * The new PIB value is not immediately written to the
		 * transceiver. This is done on a frame-by-frame base.
		 */
		tal_pib.MaxCSMABackoffs = value->pib_value_8bit;
		break;

#ifdef BEACON_SUPPORT
	case macBattLifeExt:
		tal_pib.BattLifeExt = value->pib_value_bool;
		break;

	case macBeaconOrder:
		tal_pib.BeaconOrder = value->pib_value_8bit;
		break;

	case macSuperframeOrder:
		tal_pib.SuperFrameOrder = value->pib_value_8bit;
		break;

	case macBeaconTxTime:
		tal_pib.BeaconTxTime = value->pib_value_32bit;
		break;

#endif  /* BEACON_SUPPORT */
#ifdef PROMISCUOUS_MODE
	case macPromiscuousMode:
		tal_pib.PromiscuousMode = value->pib_value_8bit;
		if (tal_pib.PromiscuousMode) {
			tal_trx_wakeup();

			/* Check if receive buffer is available or queue is not
			 *full. */
			if (NULL == tal_rx_buffer) {
				set_trx_state(CMD_PLL_ON);
				tal_rx_on_required = true;
			} else {
				set_trx_state(CMD_RX_ON);
			}
		} else {
			set_trx_state(CMD_TRX_OFF);
			tal_rx_on_required = false;
		}
		break;
#endif

	default:

		/*
		 * Following PIBs require access to trx.
		 * Therefore trx must be at least in TRX_OFF.
		 */

		if (tal_trx_status == TRX_SLEEP) {
			/* While trx is in SLEEP, register cannot be accessed.
			 **/
			return TAL_TRX_ASLEEP;
		}

		switch (attribute) {
		case macMinBE:
			tal_pib.MinBE = value->pib_value_8bit;

#ifndef REDUCED_PARAM_CHECK

			/*
			 * macMinBE must not be larger than macMaxBE or
			 *calculation
			 * of macMaxFrameWaitTotalTime will fail.
			 */
			if (tal_pib.MinBE > tal_pib.MaxBE) {
				tal_pib.MinBE = tal_pib.MaxBE;
			}

#endif  /* REDUCED_PARAM_CHECK */

			pal_trx_bit_write(SR_MIN_BE, tal_pib.MinBE);
			break;

		case macPANId:
			tal_pib.PANId = value->pib_value_16bit;
			uint8_t *ptr_pan;
			ptr_pan = (uint8_t *)&tal_pib.PANId;
			for (uint8_t i = 0; i < 2; i++) {
				pal_trx_reg_write((RG_PAN_ID_0 + i), *ptr_pan);
				ptr_pan++;
			}
			break;

		case macShortAddress:
			tal_pib.ShortAddress = value->pib_value_16bit;
			uint8_t *ptr_shrt;
			ptr_shrt = (uint8_t *)&tal_pib.ShortAddress;
			for (uint8_t i = 0; i < 2; i++) {
				pal_trx_reg_write((RG_SHORT_ADDR_0 + i),
						*ptr_shrt);
				ptr_shrt++;
			}
			break;

		case phyCurrentChannel:
			if (tal_state != TAL_IDLE) {
				return TAL_BUSY;
			}

			if ((uint32_t)TRX_SUPPORTED_CHANNELS &
					((uint32_t)0x01 <<
					value->pib_value_8bit)) {
				tal_trx_status_t previous_trx_status = TRX_OFF;

				/*
				 * Set trx to "soft" off avoiding that ongoing
				 * transaction (e.g. ACK) are interrupted.
				 */
				if (tal_trx_status != TRX_OFF) {
					previous_trx_status = RX_AACK_ON; /* any
					                                   *other
					                                   *than
					                                   *TRX_OFF
					                                   *state
					                                   **/
					do {
						/* set TRX_OFF until it could be
						 * set;
						 * trx might be busy */
					} while (set_trx_state(CMD_TRX_OFF) !=
							TRX_OFF);
				}

				tal_pib.CurrentChannel = value->pib_value_8bit;
				pal_trx_bit_write(SR_CHANNEL,
						tal_pib.CurrentChannel);
				/* Re-store previous trx state */
				if (previous_trx_status != TRX_OFF) {
					/* Set to default state */
					set_trx_state(CMD_RX_AACK_ON);
				}
			} else {
				return MAC_INVALID_PARAMETER;
			}

			break;

		case phyCurrentPage:

			if (tal_state != TAL_IDLE) {
				return TAL_BUSY;
			} else {
				uint8_t page;

				page = value->pib_value_8bit;
				if (page != 0) {
					return MAC_INVALID_PARAMETER;
				}
			}

			break;

		case macMaxBE:
			tal_pib.MaxBE = value->pib_value_8bit;
#ifndef REDUCED_PARAM_CHECK

			/*
			 * macMinBE must not be larger than macMaxBE or
			 *calculation
			 * of macMaxFrameWaitTotalTime will fail.
			 */
			if (tal_pib.MaxBE < tal_pib.MinBE) {
				tal_pib.MinBE = tal_pib.MaxBE;
			}

#endif  /* REDUCED_PARAM_CHECK */
			break;

		case phyTransmitPower:
		{
			uint8_t reg_value;

			tal_pib.TransmitPower = value->pib_value_8bit;

			/* Limit tal_pib.TransmitPower to max/min trx values */
			tal_pib.TransmitPower = limit_tx_pwr(
					tal_pib.TransmitPower);
			reg_value = convert_phyTransmitPower_to_reg_value(
					tal_pib.TransmitPower);
			pal_trx_bit_write(SR_TX_PWR, reg_value);
		}
		break;

		case phyCCAMode:
			tal_pib.CCAMode = value->pib_value_8bit;
			pal_trx_bit_write(SR_CCA_MODE, tal_pib.CCAMode);
			break;

		case macIeeeAddress:
		{
			uint8_t *ptr;
			tal_pib.IeeeAddress = value->pib_value_64bit;
			ptr = (uint8_t *)&tal_pib.IeeeAddress;
			for (uint8_t i = 0; i < 8; i++) {
				pal_trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr);
				ptr++;
			}
		}
		break;

		case mac_i_pan_coordinator:
			tal_pib.PrivatePanCoordinator = value->pib_value_bool;
			pal_trx_bit_write(SR_I_AM_COORD,
					tal_pib.PrivatePanCoordinator);
			break;

		case macAckWaitDuration:
			/* AT86RF230B does not support changing this value */
			return MAC_UNSUPPORTED_ATTRIBUTE;

		default:
			return MAC_UNSUPPORTED_ATTRIBUTE;
		}

		break; /* end of 'default' from 'switch (attribute)' */
	}
	return MAC_SUCCESS;
} /* tal_pib_set() */
Example #8
0
/**
 * @brief Sets a TAL PIB attribute
 *
 * This function is called to set the transceiver information base
 * attributes.
 *
 * @param attribute TAL infobase attribute ID
 * @param value TAL infobase attribute value to be set
 *
 * @return MAC_UNSUPPORTED_ATTRIBUTE if the TAL info base attribute is not found
 *         TAL_BUSY if the TAL is not in TAL_IDLE state. An exception is
 *         macBeaconTxTime which can be accepted by TAL even if TAL is not
 *         in TAL_IDLE state.
 *         MAC_SUCCESS if the attempt to set the PIB attribute was successful
 *         TAL_TRX_ASLEEP if trx is in SLEEP mode and access to trx is required
 */
retval_t tal_pib_set(uint8_t attribute, pib_value_t *value)
{
    /*
     * Distinguish between PIBs that need to be changed in trx directly
     * and those that are simple variable udpates.
     * Ensure that the transceiver is not in SLEEP.
     * If it is in SLEEP, change it to TRX_OFF.
     */

    switch (attribute)
    {
        case macMaxFrameRetries:
                    /*
                     * The new PIB value is not immediately written to the
                     * transceiver. This is done on a frame-by-frame base.
                     */
                    tal_pib_MaxFrameRetries = value->pib_value_8bit;
                    break;

        case macMaxCSMABackoffs:
                    /*
                     * The new PIB value is not immediately written to the
                     * transceiver. This is done on a frame-by-frame base.
                     */
                    tal_pib_MaxCSMABackoffs = value->pib_value_8bit;
                    break;

        default:
            /*
             * Following PIBs require access to trx.
             * Therefore trx must be at least in TRX_OFF.
             */

            if (tal_trx_status == TRX_SLEEP)
            {
                /* While trx is in SLEEP, register cannot be accessed. */
                return TAL_TRX_ASLEEP;
            }

            switch (attribute)
            {
                case macMinBE:
                    tal_pib_MinBE = value->pib_value_8bit;
                    pal_trx_bit_write(SR_MIN_BE, tal_pib_MinBE);
                    break;

                case macPANId:
                    tal_pib_PANId = value->pib_value_16bit;
                    pal_trx_reg_write(RG_PAN_ID_0, (uint8_t)tal_pib_PANId);
                    pal_trx_reg_write(RG_PAN_ID_1, (uint8_t)(tal_pib_PANId >> 8));
                    break;

                case macShortAddress:
                    tal_pib_ShortAddress = value->pib_value_16bit;
                    pal_trx_reg_write(RG_SHORT_ADDR_0, (uint8_t)tal_pib_ShortAddress);
                    pal_trx_reg_write(RG_SHORT_ADDR_1, (uint8_t)(tal_pib_ShortAddress >> 8));
                    break;

                case phyCurrentChannel:
                    if (tal_state != TAL_IDLE)
                    {
                        return TAL_BUSY;
                    }
                    if ((uint32_t)TRX_SUPPORTED_CHANNELS & ((uint32_t)0x01 << value->pib_value_8bit))
                    {
                        tal_trx_status_t previous_trx_status = TRX_OFF;
                        /*
                         * Set trx to "soft" off avoiding that ongoing
                         * transaction (e.g. ACK) are interrupted.
                         */
                        if (tal_trx_status != TRX_OFF)
                        {
                            previous_trx_status = RX_AACK_ON;   /* any other than TRX_OFF state */
                            do
                            {
                                /* set TRX_OFF until it could be set;
                                 * trx might be busy */
                            } while (set_trx_state(CMD_TRX_OFF) != TRX_OFF);
                        }
                        tal_pib_CurrentChannel = value->pib_value_8bit;
                        pal_trx_bit_write(SR_CHANNEL, tal_pib_CurrentChannel);
                        /* Re-store previous trx state */
                        if (previous_trx_status != TRX_OFF)
                        {
                            /* Set to default state */
                            set_trx_state(CMD_RX_AACK_ON);
                        }
                    }
                    else
                    {
                        return MAC_INVALID_PARAMETER;
                    }
                    break;

                case phyCurrentPage:
#ifdef HIGH_DATA_RATE_SUPPORT
                    if (tal_state != TAL_IDLE)
                    {
                        return TAL_BUSY;
                    }
                    else
                    {
                        uint8_t page;
                        tal_trx_status_t previous_trx_status = TRX_OFF;
                        bool ret_val;

                        /*
                         * Changing the channel, channel page or modulation
                         * requires that TRX is in TRX_OFF.
                         * Store current trx state and return to default state
                         * after channel page has been set.
                         */
                        if (tal_trx_status != TRX_OFF)
                        {
                            previous_trx_status = RX_AACK_ON;   /* any other than TRX_OFF state */
                            do
                            {
                                /* set TRX_OFF until it could be set;
                                 * trx might be busy */
                            } while (set_trx_state(CMD_TRX_OFF) != TRX_OFF);
                        }

                        page = value->pib_value_8bit;

                        ret_val = apply_channel_page_configuration(page);

                        if (previous_trx_status != TRX_OFF)
                        {
                            /* Set to default state */
                            set_trx_state(CMD_RX_AACK_ON);
                        }

                        if (ret_val)
                        {
                            tal_pib_CurrentPage = page;
                        }
                        else
                        {
                            return MAC_INVALID_PARAMETER;
                        }
                    }
#else
                if (tal_state != TAL_IDLE)
                {
                    return TAL_BUSY;
                }
                else
                {
                    uint8_t page;

                    page = value->pib_value_8bit;
                    if (page != 0)
                    {
                        return MAC_INVALID_PARAMETER;
                    }
                }
#endif  /* #ifdef HIGH_DATA_RATE_SUPPORT */
                    break;

                case macMaxBE:
                    tal_pib_MaxBE = value->pib_value_8bit;
                    pal_trx_bit_write(SR_MAX_BE, tal_pib_MaxBE);
                    break;

                case phyTransmitPower:
                    {
                        uint8_t reg_value;

                        tal_pib_TransmitPower = value->pib_value_8bit;

                        /* Limit tal_pib_TransmitPower to max/min trx values */
                        tal_pib_TransmitPower = limit_tx_pwr(tal_pib_TransmitPower);
                        reg_value = convert_phyTransmitPower_to_reg_value(tal_pib_TransmitPower);
                        pal_trx_bit_write(SR_TX_PWR, reg_value);
                    }
                    break;

                case phyCCAMode:
                    tal_pib_CCAMode = value->pib_value_8bit;
                    pal_trx_bit_write(SR_CCA_MODE, tal_pib_CCAMode);
                    break;

                case macIeeeAddress:
                    {
                        uint8_t *ptr;

                        tal_pib_IeeeAddress = value->pib_value_64bit;
                        ptr = (uint8_t *)&tal_pib_IeeeAddress;

                        for (uint8_t i = 0; i < 8; i++)
                        {
                            pal_trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr);
                            ptr++;
                        }
                    }
                    break;

                case mac_i_pan_coordinator:
                    tal_pib_PrivatePanCoordinator = value->pib_value_bool;
                    pal_trx_bit_write(SR_AACK_I_AM_COORD, tal_pib_PrivatePanCoordinator);
                    break;

                case macAckWaitDuration:
                    /*
                     * ATmega128RFA1 does not support changing this value w.r.t.
                     * compliance operation.
                     * The ACK timing can be reduced to 2 symbols using TFA function.
                     */
                    return MAC_UNSUPPORTED_ATTRIBUTE;

                default:
                    return MAC_UNSUPPORTED_ATTRIBUTE;
            }

            break; /* end of 'default' from 'switch (attribute)' */
    }
    return MAC_SUCCESS;
} /* tal_pib_set() */
Example #9
0
/**
 * @brief Sets a TAL PIB attribute
 *
 * This function is called to set the transceiver information base
 * attributes.
 *
 * @param attribute TAL infobase attribute ID
 * @param value TAL infobase attribute value to be set
 *
 * @return MAC_UNSUPPORTED_ATTRIBUTE if the TAL info base attribute is not found
 *         TAL_BUSY if the TAL is not in TAL_IDLE state. An exception is
 *         macBeaconTxTime which can be accepted by TAL even if TAL is not
 *         in TAL_IDLE state.
 *         MAC_SUCCESS if the attempt to set the PIB attribute was successful
 *         TAL_TRX_ASLEEP if trx is in SLEEP mode and access to trx is required
 */
retval_t tal_pib_set(uint8_t attribute, pib_value_t *value)
{
    /*
     * Do not allow any changes while ED or TX is done.
     * We allow changes during RX, but it's on the user's own risk.
     */
#if (MAC_SCAN_ED_REQUEST_CONFIRM == 1)
    if (tal_state == TAL_ED_RUNNING)
    {
        ASSERT("TAL is busy" == 0);
        return TAL_BUSY;
    }
#endif /* (MAC_SCAN_ED_REQUEST_CONFIRM == 1) */

    /*
     * Distinguish between PIBs that need to be changed in trx directly
     * and those that are simple variable udpates.
     * Ensure that the transceiver is not in SLEEP.
     * If it is in SLEEP, change it to TRX_OFF.
     */

    switch (attribute)
    {
        case macMaxFrameRetries:
                    /*
                     * The new PIB value is not immediately written to the
                     * transceiver. This is done on a frame-by-frame base.
                     */
                    tal_pib_MaxFrameRetries = value->pib_value_8bit;
                    break;

        case macMaxCSMABackoffs:
                    /*
                     * The new PIB value is not immediately written to the
                     * transceiver. This is done on a frame-by-frame base.
                     */
                    tal_pib_MaxCSMABackoffs = value->pib_value_8bit;
                    break;

#ifdef BEACON_SUPPORT
        case macBattLifeExt:
            tal_pib_BattLifeExt = value->pib_value_bool;
            break;

        case macBeaconOrder:
            tal_pib_BeaconOrder = value->pib_value_8bit;
            break;

        case macSuperframeOrder:
            tal_pib_SuperFrameOrder = value->pib_value_8bit;
            break;

        case macBeaconTxTime:
            tal_pib_BeaconTxTime = value->pib_value_32bit;
            break;

#endif  /* BEACON_SUPPORT */
#ifdef PROMISCUOUS_MODE
        case macPromiscuousMode:
            tal_pib_PromiscuousMode = value->pib_value_8bit;
            if (tal_pib_PromiscuousMode)
            {
                tal_trx_wakeup();

                /* Check if receive buffer is available or queue is not full. */
                if (NULL == tal_rx_buffer)
                {
                    set_trx_state(CMD_PLL_ON);
                    tal_rx_on_required = true;
                }
                else
                {
                    set_trx_state(CMD_RX_ON);
                }
            }
            else
            {
                set_trx_state(CMD_TRX_OFF);
                tal_rx_on_required = false;
            }
            break;
#endif

        default:
            /*
             * Following PIBs require access to trx.
             * Therefore trx must be at least in TRX_OFF.
             */

            if (tal_trx_status == TRX_SLEEP)
            {
                /* While trx is in SLEEP, register cannot be accessed. */
                return TAL_TRX_ASLEEP;
            }

            switch (attribute)
            {
                case macMinBE:
                    tal_pib_MinBE = value->pib_value_8bit;

#ifndef REDUCED_PARAM_CHECK
                    /*
                     * macMinBE must not be larger than macMaxBE or calculation
                     * of macMaxFrameWaitTotalTime will fail.
                     */
                    if (tal_pib_MinBE > tal_pib_MaxBE)
                    {
                        tal_pib_MinBE = tal_pib_MaxBE;
                    }
#endif  /* REDUCED_PARAM_CHECK */

                    pal_trx_bit_write(SR_MIN_BE, tal_pib_MinBE);
                    break;

                case macPANId:
                    tal_pib_PANId = value->pib_value_16bit;
                    pal_trx_reg_write(RG_PAN_ID_0, (uint8_t)tal_pib_PANId);
                    pal_trx_reg_write(RG_PAN_ID_1, (uint8_t)(tal_pib_PANId >> 8));
                    break;

                case macShortAddress:
                    tal_pib_ShortAddress = value->pib_value_16bit;
                    pal_trx_reg_write(RG_SHORT_ADDR_0, (uint8_t)tal_pib_ShortAddress);
                    pal_trx_reg_write(RG_SHORT_ADDR_1, (uint8_t)(tal_pib_ShortAddress >> 8));
                    break;

                case phyCurrentChannel:
                    if (tal_state != TAL_IDLE)
                    {
                        return TAL_BUSY;
                    }

                    if (tal_pib_CurrentPage == 5)
                    {
                        if (((uint32_t)TRX_SUPPORTED_CHANNELS_CHINA & ((uint32_t)0x01 << value->pib_value_8bit)) == false)
                        {
                            return MAC_INVALID_PARAMETER;
                        }
                    }
                    else
                    {
                        if (((uint32_t)TRX_SUPPORTED_CHANNELS & ((uint32_t)0x01 << value->pib_value_8bit)) == false)
                        {
                            return MAC_INVALID_PARAMETER;
                        }
                    }

                    {
                        uint8_t previous_channel;
                        tal_trx_status_t previous_trx_status = TRX_OFF;

                        previous_channel = tal_pib_CurrentChannel;
                        tal_pib_CurrentChannel = value->pib_value_8bit;

                        /*
                         * Set trx to "soft" off avoiding that ongoing
                         * transaction (e.g. ACK) are interrupted.
                         */
                        if (tal_trx_status != TRX_OFF)
                        {
                            previous_trx_status = RX_AACK_ON;   /* any other than TRX_OFF state */
                            do
                            {
                                /* set TRX_OFF until it could be set;
                                 * trx might be busy */
                            } while (set_trx_state(CMD_TRX_OFF) != TRX_OFF);
                        }

                        /* Check if frequency band/modulation is changed. */
                        if (tal_pib_CurrentPage == 5)
                        {
                            pal_trx_bit_write(SR_CC_NUMBER, GET_CHINA_FREQ(tal_pib_CurrentChannel));
                        }
                        else if ((tal_pib_CurrentChannel > 0) && (previous_channel > 0))
                        {
                            pal_trx_bit_write(SR_CHANNEL, tal_pib_CurrentChannel);
                        }
                        else
                        {
                            uint8_t reg_value;

                            /* Set modulation and channel */
                            apply_channel_page_configuration(tal_pib_CurrentPage);
                            limit_tx_pwr();
                            reg_value = convert_phyTransmitPower_to_reg_value(tal_pib_TransmitPower);
                            pal_trx_reg_write(RG_PHY_TX_PWR, reg_value);
                        }

                        /* Re-store previous trx state */
                        if (previous_trx_status != TRX_OFF)
                        {
                            /* Set to default state */
                            set_trx_state(CMD_RX_AACK_ON);
                        }
                    }
                    break;

                case phyCurrentPage:
                    if (tal_state != TAL_IDLE)
                    {
                        return TAL_BUSY;
                    }
                    else
                    {
                        uint8_t page;
                        tal_trx_status_t previous_trx_status = TRX_OFF;
                        bool ret_val;
                        uint8_t reg_value;

                        /*
                         * Changing the channel, channel page or modulation
                         * requires that TRX is in TRX_OFF.
                         * Store current trx state and return to default state
                         * after channel page has been set.
                         */
                        if (tal_trx_status != TRX_OFF)
                        {
                            previous_trx_status = RX_AACK_ON;   /* any other than TRX_OFF state */
                            do
                            {
                                /* set TRX_OFF until it could be set;
                                 * trx might be busy */
                            } while (set_trx_state(CMD_TRX_OFF) != TRX_OFF);
                        }

                        page = value->pib_value_8bit;

                        ret_val = apply_channel_page_configuration(page);

                        if (previous_trx_status != TRX_OFF)
                        {
                            /* Set to default state */
                            set_trx_state(CMD_RX_AACK_ON);
                        }

                        if (ret_val)
                        {
                            tal_pib_CurrentPage = page;
                        }
                        else
                        {
                            return MAC_INVALID_PARAMETER;
                        }
                        limit_tx_pwr();
                        reg_value = convert_phyTransmitPower_to_reg_value(tal_pib_TransmitPower);
                        pal_trx_reg_write(RG_PHY_TX_PWR, reg_value);
                    }
                    break;

                case macMaxBE:
                    tal_pib_MaxBE = value->pib_value_8bit;
#ifndef REDUCED_PARAM_CHECK
                    /*
                     * macMinBE must not be larger than macMaxBE or calculation
                     * of macMaxFrameWaitTotalTime will fail.
                     */
                    if (tal_pib_MaxBE < tal_pib_MinBE)
                    {
                        tal_pib_MinBE = tal_pib_MaxBE;
                    }
#endif  /* REDUCED_PARAM_CHECK */
                    pal_trx_bit_write(SR_MAX_BE, tal_pib_MaxBE);
                    break;

                case phyTransmitPower:
                    {
                        uint8_t reg_value;

                        tal_pib_TransmitPower = value->pib_value_8bit;

                        /* Limit tal_pib_TransmitPower to max/min trx values */
                        limit_tx_pwr();
                        reg_value = convert_phyTransmitPower_to_reg_value(tal_pib_TransmitPower);
                        pal_trx_reg_write(RG_PHY_TX_PWR, reg_value);
                    }
                    break;

                case phyCCAMode:
                    tal_pib_CCAMode = value->pib_value_8bit;
                    pal_trx_bit_write(SR_CCA_MODE, tal_pib_CCAMode);
                    break;

                case macIeeeAddress:
                    {
                        uint8_t *ptr;

                        tal_pib_IeeeAddress = value->pib_value_64bit;
                        ptr = (uint8_t *)&tal_pib_IeeeAddress;

                        for (uint8_t i = 0; i < 8; i++)
                        {
                            pal_trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr);
                            ptr++;
                        }
                    }
                    break;

                case mac_i_pan_coordinator:
                    tal_pib_PrivatePanCoordinator = value->pib_value_bool;
                    pal_trx_bit_write(SR_AACK_I_AM_COORD, tal_pib_PrivatePanCoordinator);
                    break;

                case macAckWaitDuration:
                    /*
                     * AT86RF212 does not support changing this value w.r.t.
                     * compliance operation.
                     */
                    return MAC_UNSUPPORTED_ATTRIBUTE;

                default:
                    return MAC_UNSUPPORTED_ATTRIBUTE;
            }

            break; /* end of 'default' from 'switch (attribute)' */
    }
    return MAC_SUCCESS;
} /* tal_pib_set() */