/**
 * Function initializing the Timestamp IRQ to get synchronized
 * as required for ranging.
 */
void rtb_tstamp_irq_init(void)
{	
    pal_trx_irq_dis();

    pal_trx_reg_read(RG_IRQ_STATUS);
    pal_trx_bit_write(SR_ARET_TX_TS_EN, 0x01);
    pal_trx_bit_write(SR_IRQ_2_EXT_EN, 0x01); //Enable Timestamping over DIG2 on the at86rf233

    PORTC.INTFLAGS = PORT_INT1IF_bm;

    TCC1_CTRLB &= ~TC1_CCAEN_bm;

    TIMER_SRC_DURING_TRX_AWAKE();

    PORTC.INT1MASK = PIN1_bm; //DIG2 over PortC 1

    /* Reset register, until time out is triggered is 65535 ms */
    TCC1_CNT = 0;

    PORTC.PIN1CTRL = PORT_ISC1_bm;

    TCC1_INTFLAGS = TC1_CCAIF_bm;

    TCC1_INTCTRLB = TC_CCAINTLVL_HI_gc;

    TCC1_CTRLB |= TC1_CCAEN_bm;	
}
Пример #2
0
/**
 * \brief Start CCA.
 *
 * \param parameter Unused callback parameter
 */
static void cca_start(void *parameter)
{
	tal_state = TAL_CCA;

	if (set_trx_state(CMD_PLL_ON) == PLL_ON) {
		tal_trx_status_t trx_state;
		/* No interest in receiving frames while doing CCA */
		pal_trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE); /* disable frame
		                                               * reception
		                                               * indication */
		do {
			trx_state = set_trx_state(CMD_RX_ON);
		} while (trx_state != RX_ON);
		/* Setup interrupt handling for CCA IRQ */
		pal_trx_irq_init((FUNC_PTR)cca_done_irq_handler);
		pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_CCA_ED_READY); /* enable
		                                                       *CCA
		                                                       *interrupt
		                                                       **/
		/* Start CCA */
		pal_trx_bit_write(SR_CCA_REQUEST, CCA_START);
	} else {
		/* Channel is busy, i.e. device is receiving */
		tal_state = TAL_CSMA_CONTINUE;
	}

	/* Keep compiler happy. */
	parameter = parameter;
}
Пример #3
0
trx_retval_t tal_init(void)
{
	if (trx_init() != TRX_SUCCESS) {
		return TRX_FAILURE;
	}

	/*
	 * Do the reset stuff.
	 * Generate random seed.
	 */
	if (internal_tal_reset() != TRX_SUCCESS) {
		return TRX_FAILURE;
	}

	/* Set the default CCA mode. */
	pal_trx_bit_write(SR_CCA_MODE, CCA_MODE_DEFAULT);

	/* Default configuration to perform auto CSMA-CA */
	pal_trx_reg_write(RG_CSMA_BE, ((MAXBE_DEFAULT << 4) | MINBE_DEFAULT));
	pal_trx_bit_write(SR_MAX_CSMA_RETRIES, MAX_CSMA_BACKOFFS_DEFAULT);

	/* Set the trx in promiscuous mode to receive all frame with CRC OK */
	pal_trx_bit_write(SR_AACK_PROM_MODE, PROM_MODE_ENABLE);

	/* Configuration to perform auto CRC for transmission */
	pal_trx_bit_write(SR_TX_AUTO_CRC_ON, TX_AUTO_CRC_ENABLE);

	return TRX_SUCCESS;
}
Пример #4
0
/**
 * @brief Starts continuous transmission on current channel
 */
void tfa_continuous_tx_start(continuous_tx_mode_t tx_mode)
{
    uint8_t txcwdata[127];

    pal_trx_bit_write(SR_TX_AUTO_CRC_ON, TX_AUTO_CRC_DISABLE);
    pal_trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);
    pal_trx_reg_write(0x0176, 0x0F);     /*TST_CTRL_DIGI*/
    /* Here: use 2MBPS mode for PSD measurements.
     * Omit the two following lines, if 250k mode is desired for PRBS mode. */
    pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_2MBPS);
    pal_trx_reg_write(RG_RX_CTRL, 0xA7);
    if (tx_mode == CW_MODE)
    {
        txcwdata[0] = 1;    // length
        // Step 11 - frame buffer write access
        txcwdata[1] = 0x00; // f=fch-0.5 MHz; set value to 0xFF for f=fch+0.5MHz
        pal_trx_frame_write(txcwdata, 2);
    }
    else    // PRBS mode
    {
        txcwdata[0] = 127;   // = max length
        for (uint8_t i = 1; i < 128; i++)
        {
            txcwdata[i] = (uint8_t)rand();
        }
        pal_trx_frame_write(txcwdata, 128);
    }

    pal_trx_reg_write(RG_PART_NUM, 0x54);
    pal_trx_reg_write(RG_PART_NUM, 0x46);
    set_trx_state(CMD_PLL_ON);
    PAL_SLP_TR_HIGH();
    PAL_SLP_TR_LOW();
}
Пример #5
0
/**
 * @brief Perform a single ED measurement
 *
 * @return ed_value Result of the measurement
 *         If the build switch TRX_REG_RAW_VALUE is defined, the transceiver's
 *         register value is returned.
 */
uint8_t tfa_ed_sample(void)
{
    trx_irq_reason_t trx_irq_cause;
    uint8_t ed_value;
    tal_trx_status_t trx_status;

    /* Make sure that receiver is switched on. */
    do
    {
        trx_status = set_trx_state(CMD_RX_ON);
    }
    while (trx_status != RX_ON);

    /*
     * Disable the transceiver interrupts to prevent frame reception
     * while performing ED scan.
     */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE);

    /* Write dummy value to start measurement. */
    pal_trx_reg_write(RG_PHY_ED_LEVEL, 0xFF);

    /* Wait for ED measurement completion. */
    pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US(ED_SAMPLE_DURATION_SYM));
    do
    {
        trx_irq_cause = (trx_irq_reason_t)pal_trx_reg_read(RG_IRQ_STATUS);
    }
    while ((trx_irq_cause & TRX_IRQ_CCA_ED_READY) != TRX_IRQ_CCA_ED_READY);

    /* Read the ED Value. */
    ed_value = pal_trx_reg_read(RG_PHY_ED_LEVEL);

#ifndef TRX_REG_RAW_VALUE
    /*
     * Scale ED result.
     * Clip values to 0xFF if > -35dBm
     */
    if (ed_value > CLIP_VALUE_REG)
    {
        ed_value = 0xFF;
    }
    else
    {
        ed_value = (uint8_t)(((uint16_t)ed_value * 0xFF) / CLIP_VALUE_REG);
    }
#endif

    /* Clear IRQ register */
    pal_trx_reg_read(RG_IRQ_STATUS);
    /* Enable reception agian */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);
    /* Switch receiver off again */
    set_trx_state(CMD_TRX_OFF);

    return ed_value;
}
Пример #6
0
Файл: tal_ed.c Проект: bswe/6.1
/*
 * \brief Starts ED Scan
 *
 * This function starts an ED Scan for the scan duration specified by the
 * MAC layer.
 *
 * \param scan_duration Specifies the ED scan duration in symbols
 *
 * \return MAC_SUCCESS - ED scan duration timer started successfully
 *         TAL_BUSY - TAL is busy servicing the previous request from MAC
 *         TAL_TRX_ASLEEP - Transceiver is currently sleeping
 *         FAILURE otherwise
 */
retval_t tal_ed_start(uint8_t scan_duration)
{
    /*
     * Check if the TAL is in idle state. Only in idle state it can
     * accept and ED request from the MAC.
     */
    if (TAL_IDLE != tal_state)
    {
        if (tal_trx_status == TRX_SLEEP)
        {
            return TAL_TRX_ASLEEP;
        }
        else
        {
            Assert("TAL is TAL_BUSY" == 0);
            return TAL_BUSY;
        }
    }

    /*
     * Disable the transceiver interrupts to prevent frame reception
     * while performing ED scan.
     */
    pal_trx_irq_dis();  /* Disable transceiver main interrupt. */
    set_trx_state(CMD_FORCE_PLL_ON);
    pal_trx_reg_read(RG_IRQ_STATUS);        /* Clear existing interrupts */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE);
    pal_trx_irq_init((FUNC_PTR)trx_ed_irq_handler_cb);
    pal_trx_bit_write(SR_IRQ_MASK, TRX_IRQ_CCA_ED_READY); /* enable interrupt */
    pal_trx_irq_en();   /* Enable main transceiver interrupt. */

    /* Make sure that receiver is switched on. */
    if (set_trx_state(CMD_RX_ON) != RX_ON)
    {
        /* Restore previous configuration */
        pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);
        pal_trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
        pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT); /* enable TRX_END interrupt */
        pal_trx_irq_en();   /* Enable main transceiver interrupt. */

        return FAILURE;
    }

    // write dummy value to start measurement
    pal_trx_reg_write(RG_PHY_ED_LEVEL, 0xFF);

    /* Perform ED in TAL_ED_RUNNING state. */
    tal_state = TAL_ED_RUNNING;

    max_ed_level = 0;   // reset max value

    sampler_counter = CALCULATE_SYMBOL_TIME_SCAN_DURATION(scan_duration) / ED_SAMPLE_DURATION_SYM;

    return MAC_SUCCESS;
}
Пример #7
0
/**
 * @brief Perform a CCA
 *
 * This function performs a CCA request.
 *
 * @return phy_enum_t PHY_IDLE or PHY_BUSY
 */
phy_enum_t tfa_cca_perform(void)
{
    tal_trx_status_t trx_status;
    uint8_t cca_status;
    uint8_t cca_done;

    /* Ensure that trx is not in SLEEP for register access */
    do
    {
        trx_status = set_trx_state(CMD_TRX_OFF);
    }
    while (trx_status != TRX_OFF);

    /* no interest in receiving frames while doing CCA */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE); // disable frame reception indication

    /* Set trx to rx mode. */
    do
    {
        trx_status = set_trx_state(CMD_RX_ON);
    }
    while (trx_status != RX_ON);

    /* Start CCA */
    pal_trx_bit_write(SR_CCA_REQUEST, CCA_START);

    /* wait until CCA is done */
    pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US(CCA_DURATION_SYM));
    do
    {
        /* poll until CCA is really done */
        cca_done = pal_trx_bit_read(SR_CCA_DONE);
    }
    while (cca_done != CCA_COMPLETED);

    set_trx_state(CMD_TRX_OFF);

    /* Check if channel was idle or busy. */
    if (pal_trx_bit_read(SR_CCA_STATUS) == CCA_CH_IDLE)
    {
        cca_status = PHY_IDLE;
    }
    else
    {
        cca_status = PHY_BUSY;
    }

    /* Enable frame reception again. */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);

    return (phy_enum_t)cca_status;
}
Пример #8
0
/**
 * @brief Scan done
 *
 * This function updates the max_ed_level and invokes the callback function
 * tal_ed_end_cb().
 *
 * @param parameter unused callback parameter
 */
void ed_scan_done(void)
{
    /* Restore previous configuration */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);

    tal_state = TAL_IDLE;   // ed scan is done
    set_trx_state(CMD_RX_AACK_ON);

#ifndef TRX_REG_RAW_VALUE
    /*
     * Scale ED result.
     * Clip values to 0xFF if > -35dBm
     */
    if (max_ed_level > CLIP_VALUE_REG)
    {
        max_ed_level = 0xFF;
    }
    else
    {
        max_ed_level = (uint8_t)(((uint16_t)max_ed_level * 0xFF) / CLIP_VALUE_REG);
    }
#endif
    tal_ed_end_cb(max_ed_level);
}
Пример #9
0
/**
 * @brief Sets a TFA PIB attribute
 *
 * This function is called to set the transceiver information base
 * attributes.
 *
 * @param[in] tfa_pib_attribute TFA infobase attribute ID
 * @param[in] value TFA infobase attribute value to be set
 *
 * @return MAC_UNSUPPORTED_ATTRIBUTE if the TFA info base attribute is not found
 *         TAL_BUSY if the TAL is not in TAL_IDLE state.
 *         MAC_SUCCESS if the attempt to set the PIB attribute was successful
 */
retval_t tfa_pib_set(tfa_pib_t tfa_pib_attribute, void *value)
{
    switch (tfa_pib_attribute)
    {
        case TFA_PIB_RX_SENS:
            {
                uint8_t reg_val;

                tfa_pib_rx_sens = *((int8_t *)value);
                if (tfa_pib_rx_sens > -49)
                {
                    reg_val = 0xF;
                    tfa_pib_rx_sens = -49;
                }
                else if (tfa_pib_rx_sens <= RSSI_BASE_VAL_DBM)
                {
                    reg_val = 0x0;
                    tfa_pib_rx_sens = RSSI_BASE_VAL_DBM;
                }
                else
                {
                    reg_val = ((tfa_pib_rx_sens - (RSSI_BASE_VAL_DBM)) / 3) + 1;
                }
                pal_trx_bit_write(SR_RX_PDT_LEVEL, reg_val);
            }
            break;

        default:
            /* Invalid attribute id */
            return MAC_UNSUPPORTED_ATTRIBUTE;
    }

    return MAC_SUCCESS;
}
Пример #10
0
Файл: tal_ed.c Проект: bswe/6.1
/*
 * \brief Scan done
 *
 * This function updates the max_ed_level and invokes the callback function
 * tal_ed_end_cb().
 *
 * \param parameter unused callback parameter
 */
void ed_scan_done(void)
{
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);
    pal_trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT); /* enable TRX_END interrupt */
    pal_trx_irq_en();   /* Enable transceiver main interrupt. */

    tal_state = TAL_IDLE;   // ed scan is done
    set_trx_state(CMD_RX_AACK_ON);

#ifndef TRX_REG_RAW_VALUE
    /*
     * Scale ED result.
     * Clip values to 0xFF if > -35dBm
     */
    if (max_ed_level > CLIP_VALUE_REG)
    {
        max_ed_level = 0xFF;
    }
    else
    {
        max_ed_level = (uint8_t)(((uint16_t)max_ed_level * 0xFF) / CLIP_VALUE_REG);
    }
#endif
    tal_ed_end_cb(max_ed_level);
}
Пример #11
0
/**
 * @brief Starts ED Scan
 *
 * This function starts an ED Scan for the scan duration specified by the
 * MAC layer.
 *
 * @param scan_duration Specifies the ED scan duration in symbols
 *
 * @return MAC_SUCCESS - ED scan duration timer started successfully
 *         TAL_BUSY - TAL is busy servicing the previous request from MAC
 *         TAL_TRX_ASLEEP - Transceiver is currently sleeping
 *         FAILURE otherwise
 */
retval_t tal_ed_start(uint8_t scan_duration)
{
    /*
     * Check if the TAL is in idle state. Only in idle state it can
     * accept and ED request from the MAC.
     */
    if (TAL_IDLE != tal_state)
    {
        if (tal_trx_status == TRX_SLEEP)
        {
            return TAL_TRX_ASLEEP;
        }
        else
        {
            ASSERT("TAL is TAL_BUSY" == 0);
            return TAL_BUSY;
        }
    }

    set_trx_state(CMD_FORCE_PLL_ON);
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE);
    pal_trx_irq_flag_clr_cca_ed();
    pal_trx_irq_init_cca_ed((FUNC_PTR)trx_ed_irq_handler_cb);
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_CCA_ED_READY);

    /* Make sure that receiver is switched on. */
    if (set_trx_state(CMD_RX_ON) != RX_ON)
    {
        /* Restore previous configuration */
        pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);
        pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);

        return FAILURE;
    }

    /* Perform ED in TAL_ED_RUNNING state. */
    tal_state = TAL_ED_RUNNING;

    max_ed_level = 0;   // reset max value

    sampler_counter = CALCULATE_SYMBOL_TIME_SCAN_DURATION(scan_duration) / ED_SAMPLE_DURATION_SYM;

    // write dummy value to start measurement
    pal_trx_reg_write(RG_PHY_ED_LEVEL, 0xFF);

    return MAC_SUCCESS;
}
Пример #12
0
/**
 * @brief Configures the transceiver
 *
 * This function is called to configure the transceiver after reset.
 */
static void trx_config(void)
{
    /* After we have initialized a proper seed for rand(),
     * the transceiver's CSMA seed can be initialized.
     * It needs to be assured that a seed for function rand()
     * had been generated before.
     */
    /*
     * Init the SEED value of the CSMA backoff algorithm.
     */
    uint16_t rand_value = (uint16_t)rand();
    pal_trx_reg_write(RG_CSMA_SEED_0, (uint8_t)rand_value);
    pal_trx_bit_write(SR_CSMA_SEED_1, (uint8_t)(rand_value >> 8));

    pal_trx_bit_write(SR_AACK_SET_PD, PD_ACK_BIT_SET_ENABLE); /* ACKs for data requests, indicate pending data */
    pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE);  /* Enable buffer protection mode */
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);
    pal_trx_reg_write(0x156, 0xFF); /* RPC feature configuration. */

#if (ANTENNA_DIVERSITY == 1)
    // Use antenna diversity
    pal_trx_bit_write(SR_ANT_CTRL, ANTENNA_DEFAULT);
    pal_trx_bit_write(SR_PDT_THRES, THRES_ANT_DIV_ENABLE);
    pal_trx_bit_write(SR_ANT_DIV_EN, ANT_DIV_ENABLE);
    pal_trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_ENABLE);
#endif

#ifdef CCA_ED_THRESHOLD
    /*
     * Set CCA ED Threshold to other value than standard register due to
     * board specific loss (see pal_config.h). */
    pal_trx_bit_write(SR_CCA_ED_THRES, CCA_ED_THRESHOLD);
#endif
}
Пример #13
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
}
Пример #14
0
/**
 * @brief Reset transceiver
 *
 * @return MAC_SUCCESS  if the transceiver state is changed to TRX_OFF
 *         FAILURE otherwise
 */
static retval_t trx_reset(void)
{
    tal_trx_status_t trx_status;
    uint8_t poll_counter = 0;
#if (EXTERN_EEPROM_AVAILABLE == 1)
    uint8_t xtal_trim_value;
#endif

    /* Get trim value for 16 MHz xtal; needs to be done before reset */
#if (EXTERN_EEPROM_AVAILABLE == 1)
    pal_ps_get(EXTERN_EEPROM, EE_XTAL_TRIM_ADDR, 1, &xtal_trim_value);
#endif

    /* trx might sleep, so wake it up */
    PAL_SLP_TR_LOW();
    pal_timer_delay(SLEEP_TO_TRX_OFF_TYP_US);

    /* Apply reset pulse */
    PAL_RST_LOW();
    pal_timer_delay(RST_PULSE_WIDTH_US);
    PAL_RST_HIGH();

    /* verify that trx has reached TRX_OFF */
    do
    {
        /* Wait a short time interval. */
        pal_timer_delay(TRX_POLL_WAIT_TIME_US);

        trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);

        /* Wait not more than max. value of TR2. */
        if (poll_counter == SLEEP_TO_TRX_OFF_ATTEMPTS)
        {
#if (DEBUG > 0)
            pal_alert();
#endif
            return FAILURE;
        }
        poll_counter++;
    }
    while (trx_status != TRX_OFF);

    tal_trx_status = TRX_OFF;

    // Write 16MHz xtal trim value to trx.
    // It's only necessary if it differs from the reset value.
#if (EXTERN_EEPROM_AVAILABLE == 1)
    if (xtal_trim_value != 0x00)
    {
        pal_trx_bit_write(SR_XTAL_TRIM, xtal_trim_value);
    }
#endif

    return MAC_SUCCESS;
}
Пример #15
0
/**
 * @brief Generates a 16-bit random number used as initial seed for srand()
 *
 * This function generates a 16-bit random number by means of using the
 * Random Number Generator from the transceiver.
 * The Random Number Generator generates 2-bit random values. These 2-bit
 * random values are concatenated to the required 16-bit random seed.
 *
 * The generated random 16-bit number is feed into function srand()
 * as initial seed.
 *
 * The transceiver state is initally set to RX_ON.
 * After the completion of the random seed generation, the
 * trancseiver is set to TRX_OFF.
 *
 * As a prerequisite the preamble detector must not be disabled.
 *
 * Also in case the function is called from a different state than TRX_OFF,
 * additional trx state handling is required, such as reading the original
 * value and restoring this state after finishing the sequence.
 * Since in our case the function is called from TRX_OFF, this is not required
 * here.
 */
void tal_generate_rand_seed(void)
{
    uint16_t seed = 0;
    uint8_t cur_random_val = 0;

    /* RPC could influence the randomness; therefore disable it here. */
    uint8_t previous_RPC_value = pal_trx_reg_read(RG_TRX_RPC);
    pal_trx_reg_write(RG_TRX_RPC, 0xC1);

    /*
     * We need to disable TRX IRQs while generating random values in RX_ON,
     * we do not want to receive frames at this point of time at all.
     */
    ENTER_TRX_REGION();

    /* Ensure that PLL has locked and receive mode is reached. */
    tal_trx_status_t trx_state;
    do
    {
        trx_state = set_trx_state(CMD_RX_ON);
    }
    while (trx_state != RX_ON);

    /* Ensure that register bit RX_PDT_DIS is set to 0. */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);

    /*
     * The 16-bit random value is generated from various 2-bit random values.
     */
    for (uint8_t i = 0; i < 8; i++)
    {
        /* Now we can safely read the 2-bit random number. */
        cur_random_val = pal_trx_bit_read(SR_RND_VALUE);
        seed = seed << 2;
        seed |= cur_random_val;
        PAL_WAIT_1_US();    // wait that the random value gets updated
    }

    set_trx_state(CMD_FORCE_TRX_OFF);

    /*
     * Now we need to clear potential pending TRX IRQs and
     * enable the TRX IRQs again.
     */
    pal_trx_reg_read(RG_IRQ_STATUS);
    pal_trx_irq_flag_clr();
    LEAVE_TRX_REGION();

    /* Set the seed for the random number generator. */
    srand(seed);

    /* Restore RPC settings. */
    pal_trx_reg_write(RG_TRX_RPC, previous_RPC_value);
}
Пример #16
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
}
Пример #17
0
/**
 * \brief Configures the transceiver
 *
 * This function is called to configure the transceiver after reset.
 */
static void trx_config(void)
{
    /* Set pin driver strength */
    pal_trx_reg_write(RG_TRX_CTRL_0, ((CLKM_2mA << 6) |
                                      (CLKM_2mA << 4) | CLKM_1MHz));               /* fast
	                                                              * change */

    /*
     * Init the SEED value of the CSMA backoff algorithm.
     */
    uint16_t rand_value = (uint16_t)rand();
    pal_trx_reg_write(RG_CSMA_SEED_0, (uint8_t)rand_value);
    pal_trx_bit_write(SR_CSMA_SEED_1, (uint8_t)(rand_value >> 8));

    /*
     * To make sure that the CSMA seed is properly set within the
     *transceiver,
     * put the trx to sleep briefly and wake it up again.
     */
    tal_trx_sleep(SLEEP_MODE_1);
    tal_trx_wakeup();

    pal_trx_bit_write(SR_AACK_SET_PD, PD_ACK_BIT_SET_ENABLE); /* 1 == frame
	                                                           *pending bit
	                                                           *is always
	                                                           *set to 1 */
    pal_trx_bit_write(SR_TX_AUTO_CRC_ON, TX_AUTO_CRC_ENABLE); /* enable auto
	                                                           *crc */
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_TRX_END); /* enable TRX_END
	                                                  *interrupt */

#ifdef CCA_ED_THRESHOLD

    /*
     * Set CCA ED Threshold to other value than standard register due to
     * board specific loss (see pal_config.h). */
    pal_trx_bit_write(SR_CCA_ED_THRES, CCA_ED_THRESHOLD);
#endif
}
Пример #18
0
/**
 * \brief Reset transceiver
 */
static retval_t trx_reset(void)
{
    tal_trx_status_t trx_status;
    uint8_t poll_counter = 0;
#if (EXTERN_EEPROM_AVAILABLE == 1)
    uint8_t xtal_trim_value;
#endif

    /* Get trim value for 16 MHz xtal; needs to be done before reset */
#if (EXTERN_EEPROM_AVAILABLE == 1)
    pal_ps_get(EXTERN_EEPROM, EE_XTAL_TRIM_ADDR, 1, &xtal_trim_value);
#endif

    /* trx might sleep, so wake it up */
    PAL_SLP_TR_LOW();
    pal_timer_delay(SLEEP_TO_TRX_OFF_US);

    PAL_RST_LOW();
    pal_timer_delay(RST_PULSE_WIDTH_US);
    PAL_RST_HIGH();

    /* verify that trx has reached TRX_OFF */
    do {
        trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);
        poll_counter++;
        if (poll_counter > 250) {
#if (_DEBUG_ > 0)
            Assert(
                "MAX Attempts to switch to TRX_OFF state reached" ==
                0);
#endif
            return FAILURE;
        }
    } while (trx_status != TRX_OFF);

    tal_trx_status = TRX_OFF;

    /* Write 16MHz xtal trim value to trx. */
    /* It's only necessary if it differs from the reset value. */
#if (EXTERN_EEPROM_AVAILABLE == 1)
    if (xtal_trim_value != 0x00) {
        pal_trx_bit_write(SR_XTAL_TRIM, xtal_trim_value);
    }

#endif

    return MAC_SUCCESS;
}
Пример #19
0
/*
 * \brief handling of CCA result.
 */
void cca_done_handling(void)
{
	set_trx_state(CMD_PLL_ON); /* leave RX_ON */
	/* Restore IRQ handling */
	pal_trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
	pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);
	pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); /* Enable frame reception.
	                                              **/

	/* Check if channel was idle or busy */
	if (pal_trx_bit_read(SR_CCA_STATUS) == CCA_STATUS_CHANNEL_IS_IDLE) {
		tx_frame();
	} else {
		tal_state = TAL_CSMA_CONTINUE;
	}
}
Пример #20
0
/**
 * @brief Generates a 16-bit random number used as initial seed for srand()
 *
 * This function generates a 16-bit random number by means of using the
 * Random Number Generator from the transceiver.
 * The Random Number Generator generates 2-bit random values. These 2-bit
 * random values are concatenated to the required 16-bit random seed.
 *
 * The generated random 16-bit number is feed into function srand()
 * as initial seed.
 *
 * The transceiver state is initally set to RX_ON.
 * After the completion of the random seed generation, the
 * trancseiver is set to TRX_OFF.
 *
 * As a prerequisite the preamble detector must not be disabled.
 *
 * Also in case the function is called from a different state than TRX_OFF,
 * additional trx state handling is required, such as reading the original
 * value and restoring this state after finishing the sequence.
 * Since in our case the function is called from TRX_OFF, this is not required
 * here.
 */
void tal_generate_rand_seed(void)
{
    uint16_t seed = 0;
    uint8_t cur_random_val = 0;

    /* Ensure that PLL has locked and receive mode is reached. */
    tal_trx_status_t trx_state;
    do
    {
        trx_state = set_trx_state(CMD_RX_ON);
    }
    while (trx_state != RX_ON);

    /* Ensure that register bit RX_PDT_DIS is set to 0. */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);

    /*
     * We need to disable TRX IRQs while generating random values in RX_ON,
     * we do not want to receive frames at this point of time at all.
     */
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_NONE);

    /*
     * The 16-bit random value is generated from various 2-bit random values.
     */
    for (uint8_t i = 0; i < 8; i++)
    {
        /* Now we can safely read the 2-bit random number. */
        cur_random_val = pal_trx_bit_read(SR_RND_VALUE);
        seed = seed << 2;
        seed |= cur_random_val;
        PAL_WAIT_1_US();    // wait that the random value gets updated
    }

    set_trx_state(CMD_FORCE_TRX_OFF);

    /*
     * Now we need to clear potential pending TRX IRQs and
     * enable the TRX IRQs again.
     */
    pal_trx_reg_write(RG_IRQ_STATUS, 0xFF);
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);

    /* Set the seed for the random number generator. */
    srand(seed);
}
Пример #21
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++)
    {
        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
}
Пример #22
0
/**
 * @brief Apply channel page configuartion to transceiver
 *
 * @param ch_page Channel page
 *
 * @return true if changes could be applied else false
 */
static bool apply_channel_page_configuration(uint8_t ch_page)
{
    /*
     * Before updating the transceiver a number of TAL PIB attributes need
     * to be updated depending on the channel page.
     */
    tal_pib.MaxFrameDuration = MAX_FRAME_DURATION;
    tal_pib.SHRDuration = NO_OF_SYMBOLS_PREAMBLE_SFD;
    tal_pib.SymbolsPerOctet = SYMBOLS_PER_OCTET;

    switch (ch_page)
    {
        case 0: /* compliant O-QPSK */
            pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_250_KBPS);
            // Apply compliant ACK timing
            pal_trx_bit_write(SR_AACK_ACK_TIME, ACK_TIME_12_SYMBOLS);
            break;

        case 2: /* non-compliant OQPSK mode 1 */
            pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_500_KBPS);
            // Apply reduced ACK timing
            pal_trx_bit_write(SR_AACK_ACK_TIME, ACK_TIME_2_SYMBOLS);
            break;

        case 16:    /* non-compliant OQPSK mode 2 */
            pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_1_MBPS);
            // Apply reduced ACK timing
            pal_trx_bit_write(SR_AACK_ACK_TIME, ACK_TIME_2_SYMBOLS);
            break;

        case 17:    /* non-compliant OQPSK mode 3 */
            pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_2_MBPS);
            // Apply reduced ACK timing
            pal_trx_bit_write(SR_AACK_ACK_TIME, ACK_TIME_2_SYMBOLS);
            break;

        default:
            return false;
    }

    return true;
}
Пример #23
0
/*
 * \brief Starts continuous transmission on current channel
 *
 * \param tx_mode Mode of continuous transmission (CW or PRBS)
 * \param random_content Use random content if true
 */
void tfa_continuous_tx_start(continuous_tx_mode_t tx_mode, bool random_content)
{
    uint8_t txcwdata[128];

    pal_trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);
    pal_trx_bit_write(SR_TX_AUTO_CRC_ON, TX_AUTO_CRC_DISABLE);
    pal_trx_reg_write(0x36, 0x0F);     /* TST_CTRL_DIGI */

    if (tx_mode == CW_MODE)
    {
        txcwdata[0] = 1;    // step 9
        txcwdata[1] = 0;
        pal_trx_frame_write(txcwdata, 2);
        // Step 10
        pal_trx_reg_write(0x3D, 0x80);  /* Configure continuous Tx (2) */
    }
    else    // PRBS mode
    {
        txcwdata[0] = 127;   // = max length
        for (uint8_t i = 1; i < 128; i++)
        {
            if (random_content)
            {
                txcwdata[i] = (uint8_t)rand();
            }
            else
            {
                txcwdata[i] = 0;
            }
        }
        pal_trx_frame_write(txcwdata, 128);
        pal_trx_reg_write(0x3D, 0x00);  /* Configure continuous Tx (2) */
    }

    // set tst pin to high
    TST_PORT_HIGH();

    set_trx_state(CMD_PLL_ON);
    PAL_SLP_TR_HIGH();
    PAL_SLP_TR_LOW();
}
Пример #24
0
static void trx_config(void)
{
	/* Set pin driver strength */
	pal_trx_bit_write(SR_PAD_IO_CLKM, PAD_CLKM_2_MA);
	pal_trx_bit_write(SR_CLKM_SHA_SEL, CLKM_SHA_DISABLE);
	pal_trx_bit_write(SR_CLKM_CTRL, CLKM_1MHZ);

	/* ACKs for data requests, indicate pending data */
	pal_trx_bit_write(SR_AACK_SET_PD, SET_PD);

	/* Enable buffer protection mode */
	pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE);

	/* Enable poll mode */
	pal_trx_bit_write(SR_IRQ_MASK_MODE, IRQ_MASK_MODE_ON);

	/* The TRX_END interrupt of the transceiver is enabled. */
	pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);
}
Пример #25
0
/**
 * @brief Filter tuning calibration implementation
 */
static void do_ftn_calibration(void)
{
    pal_trx_bit_write(SR_FTN_START, 1);
    /* Wait tTR16 (FTN calibration time). */
    pal_timer_delay(25);
}
Пример #26
0
/**
 * @brief Sets transceiver state
 *
 * @param trx_cmd needs to be one of the trx commands
 *
 * @return current trx state
 */
tal_trx_status_t set_trx_state(trx_cmd_t trx_cmd)
{
    if (tal_trx_status == TRX_SLEEP)
    {
        /*
         * Since the wake-up procedure relies on the Awake IRQ and
         * the global interrupts may be disabled at this point of time,
         * we need to make sure that the global interrupts are enabled
         * during wake-up procedure.
         * Once the TRX is awake, the original state of the global interrupts
         * will be restored.
         */
        /* Reset wake-up interrupt flag. */
        tal_awake_end_flag = false;
        /* Set callback function for the awake interrupt. */
        pal_trx_irq_init(trx_irq_awake_handler_cb);
        /* The pending transceiver interrupts on the microcontroller are cleared. */
        pal_trx_irq_flag_clr();
        pal_trx_irq_en();     /* Enable transceiver main interrupt. */
        /* Save current state of global interrupts. */
        ENTER_CRITICAL_REGION();
        /* Force enabling of global interrupts. */
        ENABLE_GLOBAL_IRQ();
        /* Leave trx sleep mode. */
        PAL_SLP_TR_LOW();
        /* Poll wake-up interrupt flag until set within ISR. */
        while (!tal_awake_end_flag);
        /* Restore original state of global interrupts. */
        LEAVE_CRITICAL_REGION();
        /* Clear existing interrupts */
        pal_trx_reg_read(RG_IRQ_STATUS);
        /* Re-install default IRQ handler for main interrupt. */
        pal_trx_irq_init(trx_irq_handler_cb);
        /* Re-enable TRX_END interrupt */
        pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);
#if (ANTENNA_DIVERSITY == 1)
        /* Enable antenna diversity. */
        pal_trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_ENABLE);
#endif

#ifdef EXT_RF_FRONT_END_CTRL
        /* Enable RF front end control */
        pal_trx_bit_write(SR_PA_EXT_EN, 1);
#endif

        tal_trx_status = TRX_OFF;
        if ((trx_cmd == CMD_TRX_OFF) || (trx_cmd == CMD_FORCE_TRX_OFF))
        {
            return TRX_OFF;
        }
    }
#ifdef ENABLE_DEEP_SLEEP
    else if (tal_trx_status == TRX_DEEP_SLEEP)
    {
        /* Leave trx sleep mode. */
        PAL_SLP_TR_LOW();
        /* Check if trx has left deep sleep. */
        tal_trx_status_t trx_state;
        do
        {
            trx_state = (tal_trx_status_t)pal_trx_reg_read(RG_TRX_STATUS);
        }
        while (trx_state != TRX_OFF);
        tal_trx_status = TRX_OFF;
        /* Using deep sleep, the transceiver's registers need to be restored. */
        trx_config();
        /*
         * Write all PIB values to the transceiver
         * that are needed by the transceiver itself.
         */
        write_all_tal_pib_to_trx(); /* implementation can be found in 'tal_pib.c' */
        if ((trx_cmd == CMD_TRX_OFF) || (trx_cmd == CMD_FORCE_TRX_OFF))
        {
            return TRX_OFF;
        }
    }
#endif

    switch (trx_cmd)    /* requested state */
    {
        case CMD_SLEEP:
#ifdef ENABLE_DEEP_SLEEP
            /* Fall through. */
        case CMD_DEEP_SLEEP:
#endif
            pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);

#if (ANTENNA_DIVERSITY == 1)
            /*
             *  Disable antenna diversity: to reduce the power consumption or
             *  avoid leakage current of an external RF switch during SLEEP.
             */
            pal_trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_DISABLE);
#endif
#ifdef EXT_RF_FRONT_END_CTRL
            /* Disable RF front end control */
            pal_trx_bit_write(SR_PA_EXT_EN, 0);
#endif
            /* Clear existing interrupts */
            pal_trx_reg_read(RG_IRQ_STATUS);
            /*
             * Enable Awake_end interrupt.
             * This is used for save wake-up from sleep later.
             */
            pal_trx_bit_write(SR_IRQ_MASK, TRX_IRQ_4_CCA_ED_DONE);

#ifdef ENABLE_DEEP_SLEEP
            if (trx_cmd == CMD_DEEP_SLEEP)
            {
                pal_trx_reg_write(RG_TRX_STATE, CMD_PREP_DEEP_SLEEP);
                tal_trx_status = TRX_DEEP_SLEEP;
            }
            else
            {
                /*
                 * Enable Awake_end interrupt.
                 * This is used for save wake-up from sleep later.
                 */
                pal_trx_bit_write(SR_IRQ_MASK, TRX_IRQ_4_CCA_ED_DONE);
                tal_trx_status = TRX_SLEEP;
            }
#else
            /*
             * Enable Awake_end interrupt.
             * This is used for save wake-up from sleep later.
             */
            pal_trx_bit_write(SR_IRQ_MASK, TRX_IRQ_4_CCA_ED_DONE);
            tal_trx_status = TRX_SLEEP;
#endif
            PAL_WAIT_1_US();
            PAL_SLP_TR_HIGH();
            pal_timer_delay(TRX_OFF_TO_SLEEP_TIME_CLKM_CYCLES);
            /* Transceiver register cannot be read during TRX_SLEEP or DEEP_SLEEP. */
            return tal_trx_status;

        case CMD_TRX_OFF:
            switch (tal_trx_status)
            {
                case TRX_OFF:
                    break;

                default:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);
                    PAL_WAIT_1_US();
                    break;
            }
            break;

        case CMD_FORCE_TRX_OFF:
            switch (tal_trx_status)
            {
                case TRX_OFF:
                    break;

                default:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
                    PAL_WAIT_1_US();
                    break;
            }
            break;

        case CMD_PLL_ON:
            switch (tal_trx_status)
            {
                case PLL_ON:
                    break;

                case TRX_OFF:
                    switch_pll_on();
                    break;

                case RX_ON:
                case RX_AACK_ON:
                case TX_ARET_ON:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
                    PAL_WAIT_1_US();
                    break;

                case BUSY_RX:
                case BUSY_TX:
                case BUSY_RX_AACK:
                case BUSY_TX_ARET:
                    /* do nothing if trx is busy */
                    break;

                default:
                    ASSERT("state transition not handled" == 0);
                    break;
            }
            break;

        case CMD_FORCE_PLL_ON:
            switch (tal_trx_status)
            {
                case TRX_OFF:
                    switch_pll_on();
                    break;

                case PLL_ON:
                    break;

                default:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_PLL_ON);
                    break;
            }
            break;

        case CMD_RX_ON:
            switch (tal_trx_status)
            {
                case RX_ON:
                    break;

                case PLL_ON:
                case RX_AACK_ON:
                case TX_ARET_ON:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_RX_ON);
                    PAL_WAIT_1_US();
                    break;

                case TRX_OFF:
                    switch_pll_on();
                    pal_trx_reg_write(RG_TRX_STATE, CMD_RX_ON);
                    PAL_WAIT_1_US();
                    break;

                case BUSY_RX:
                case BUSY_TX:
                case BUSY_RX_AACK:
                case BUSY_TX_ARET:
                    /* do nothing if trx is busy */
                    break;

                default:
                    ASSERT("state transition not handled" == 0);
                    break;
            }
            break;

        case CMD_RX_AACK_ON:
            switch (tal_trx_status)
            {
                case RX_AACK_ON:
                    break;

                case TX_ARET_ON:
                case PLL_ON:
                case RX_ON:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
                    PAL_WAIT_1_US();
                    break;

                case TRX_OFF:
                    switch_pll_on(); // state change from TRX_OFF to RX_AACK_ON can be done directly, too
                    pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
                    PAL_WAIT_1_US();
                    break;

                case BUSY_RX:
                case BUSY_TX:
                case BUSY_RX_AACK:
                case BUSY_TX_ARET:
                    /* do nothing if trx is busy */
                    break;

                default:
                    ASSERT("state transition not handled" == 0);
                    break;
            }
            break;

        case CMD_TX_ARET_ON:
            switch (tal_trx_status)
            {
                case TX_ARET_ON:
                    break;

                case PLL_ON:
                case RX_ON:
                case RX_AACK_ON:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_TX_ARET_ON);
                    PAL_WAIT_1_US();
                    break;

                case TRX_OFF:
                    switch_pll_on(); // state change from TRX_OFF to TX_ARET_ON can be done directly, too
                    pal_trx_reg_write(RG_TRX_STATE, CMD_TX_ARET_ON);
                    PAL_WAIT_1_US();
                    break;

                case BUSY_RX:
                case BUSY_TX:
                case BUSY_RX_AACK:
                case BUSY_TX_ARET:
                    /* do nothing if trx is busy */
                    break;

                default:
                    ASSERT("state transition not handled" == 0);
                    break;
            }
            break;

        default:
            /* CMD_NOP, CMD_TX_START */
            ASSERT("trx command not handled" == 0);
            break;
    }

    do
    {
        tal_trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);
    }
    while (tal_trx_status == STATE_TRANSITION_IN_PROGRESS);

    return tal_trx_status;
} /* set_trx_state() */
Пример #27
0
/*
 * \brief Handle received frame interrupt
 *
 * This function handles transceiver interrupts for received frames and
 * uploads the frames from the trx.
 */
void handle_received_frame_irq(void)
{
    uint8_t ed_value;
    /* Actual frame length of received frame. */
    uint8_t phy_frame_len;
    /* Extended frame length appended by LQI and ED. */
    uint8_t ext_frame_length;
    frame_info_t *receive_frame;
    uint8_t *frame_ptr;

    if (tal_rx_buffer == NULL)
    {
        Assert("no tal_rx_buffer available" == 0);
        /*
         * Although the buffer protection mode is enabled and the receiver has
         * been switched to PLL_ON, the next incoming frame was faster.
         * It cannot be handled and is discarded.
         */
        pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_DISABLE);  /* Disable buffer protection mode */
        pal_timer_delay(2); // Allow pin change to get effective
        pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE);  /* Enable buffer protection mode */
        return;
    }

    receive_frame = (frame_info_t *)BMM_BUFFER_POINTER(tal_rx_buffer);

#ifdef PROMISCUOUS_MODE
    if (tal_pib.PromiscuousMode)
    {
        /* Check for valid FCS */
        if (pal_trx_bit_read(SR_RX_CRC_VALID) == CRC16_NOT_VALID)
        {
            return;
        }
    }
#endif

    /* Get ED value; needed to normalize LQI. */
    ed_value = pal_trx_reg_read(RG_PHY_ED_LEVEL);

    /* Get frame length from transceiver. */
    phy_frame_len = ext_frame_length = pal_trx_reg_read(RG_TST_RX_LENGTH);

    /* Check for valid frame length. */
    if (phy_frame_len > 127)
    {
        return;
    }

    /*
     * The PHY header is also included in the frame (length field), hence the frame length
     * is incremented.
     * In addition to that, the LQI and ED value are uploaded, too.
     */
    ext_frame_length += LQI_LEN + ED_VAL_LEN;

    /* Update payload pointer to store received frame. */
    frame_ptr = (uint8_t *)receive_frame + LARGE_BUFFER_SIZE - ext_frame_length;

    /*
     * Note: The following code is different from other non-single chip
     * transceivers, where reading the frame via SPI contains the length field
     * in the first octet.
     */
    pal_trx_frame_read(frame_ptr, phy_frame_len + LQI_LEN);
    frame_ptr--;
    *frame_ptr = phy_frame_len;
    receive_frame->mpdu = frame_ptr;
    /* Add ED value at the end of the frame buffer. */
    receive_frame->mpdu[phy_frame_len + LQI_LEN + ED_VAL_LEN] = ed_value;


#if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)
    /*
     * Store the timestamp.
     * The timestamping is only required for beaconing networks
     * or if timestamping is explicitly enabled.
     */
    receive_frame->time_stamp = tal_rx_timestamp;
#endif  /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */

    /* Append received frame to incoming_frame_queue and get new rx buffer. */
    qmm_queue_append(&tal_incoming_frame_queue, tal_rx_buffer);

    /* The previous buffer is eaten up and a new buffer is not assigned yet. */
    tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    /* Check if receive buffer is available */
    if (NULL == tal_rx_buffer)
    {
        /*
         * Turn off the receiver until a buffer is available again.
         * tal_task() will take care of eventually reactivating it.
         * Due to ongoing ACK transmission do not force to switch it off.
         */

        /* Do not change the state since buffer protection mode is not re-enabled yet.
         * Buffer protection will be re-enabled after buffer becomes available
         */
        //set_trx_state(CMD_PLL_ON);
        tal_rx_on_required = true;
    }
    else
    {
        /*
         * Trx returns to RX_AACK_ON automatically, if this was its previous state.
         * Keep the following as a reminder, if receiver is used with RX_ON instead.
         */
        //pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
        /*
         * Release the protected buffer and set it again for further protection since
         * the buffer is available
         */
        pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_DISABLE);  /* Disable buffer protection mode */
        pal_timer_delay(2); // Allow pin change to get effective
        pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE);  /* Enable buffer protection mode */
    }

    /*
     * Clear pending TX_END IRQ: The TX_END IRQ is envoked for the transmission
     * end of an automatically sent ACK frame. This implementation does not use
     * this feature.
     */
    pal_trx_irq_flag_clr_tx_end();
}
Пример #28
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() */
Пример #29
0
/**
 * @brief Get the transceiver's supply voltage
 *
 * @return mv Milli Volt; 0 if below threshold, 0xFFFF if above threshold
 */
uint16_t tfa_get_batmon_voltage(void)
{
    tal_trx_status_t previous_trx_status;
    uint8_t vth_val;
    uint8_t i;
    uint16_t mv = 1;    // 1 used as indicator flag
    bool range;

    previous_trx_status = tal_trx_status;
    if (tal_trx_status == TRX_SLEEP)
    {
        set_trx_state(CMD_TRX_OFF);
    }

    /*
     * Disable all trx interrupts.
     * This needs to be done AFTER the transceiver has been woken up.
     */
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_NONE);

    /* Check if supply voltage is within lower range */
    pal_trx_bit_write(SR_BATMON_HR, BATMON_LOW_RANGE);
    pal_trx_bit_write(SR_BATMON_VTH, 0x0F);
    pal_timer_delay(5); /* Wait until Batmon has been settled. */
    if (pal_trx_bit_read(SR_BATMON_OK) == BATMON_BELOW_THRES)
    {
        /* Lower range */
        /* Check if supply voltage is below lower limit */
        pal_trx_bit_write(SR_BATMON_VTH, 0);
        pal_timer_delay(2); /* Wait until Batmon has been settled. */
        if (pal_trx_bit_read(SR_BATMON_OK) == BATMON_BELOW_THRES)
        {
            /* below lower limit */
            mv = SUPPLY_VOLTAGE_BELOW_LOWER_LIMIT;
        }
        range = LOW;
    }
    else
    {
        /* Higher range */
        pal_trx_bit_write(SR_BATMON_HR, BATMON_HIGH_RANGE);
        /* Check if supply voltage is above upper limit */
        pal_trx_bit_write(SR_BATMON_VTH, 0x0F);
        pal_timer_delay(5); /* Wait until Batmon has been settled. */
        if (pal_trx_bit_read(SR_BATMON_OK) == BATMON_ABOVE_THRES)
        {
            /* above upper limit */
            mv = SUPPLY_VOLTAGE_ABOVE_UPPER_LIMIT;
        }
        range = HIGH;
    }

    /* Scan through the current range for the matching threshold. */
    if (mv == 1)
    {
        vth_val = 0x0F;
        for (i = 0; i < 16; i++)
        {
            pal_trx_bit_write(SR_BATMON_VTH, i);
            pal_timer_delay(2); /* Wait until Batmon has been settled. */
            if (pal_trx_bit_read(SR_BATMON_OK) == BATMON_BELOW_THRES)
            {
                if (i > 0)
                {
                    vth_val = i - 1;
                }
                else
                {
                    vth_val = i;
                }
                break;
            }
        }

        if (range == HIGH)
        {
            mv = 2550 + (75 * vth_val);
        }
        else
        {
            mv = 1700 + (50 * vth_val);
        }
    }

    pal_trx_reg_read(RG_IRQ_STATUS);

    /* Clear all pending interrupts. */
    pal_trx_irq_flag_clr_rx_end();
    pal_trx_irq_flag_clr_tx_end();
    pal_trx_irq_flag_clr_tstamp();

    /*
     * Enable all trx interrupts.
     * This needs to be done BEFORE putting the transceiver back to slee.
     */
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);

    if (previous_trx_status == TRX_SLEEP)
    {
        set_trx_state(CMD_SLEEP);
    }

    return mv;
}
Пример #30
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() */