/**
 * @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_bool;
            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:
#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;
#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:
                    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);
                        uint8_t 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:
                    tal_pib.IeeeAddress = value->pib_value_64bit;
                    {
                        uint8_t *ptr;
                        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:
                    /*
                     * AT86RF233 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 #2
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 */

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

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

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

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