/* * \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; } trx_bit_write(SR_RX_PDT_LEVEL, reg_val); CONF_REG_WRITE(); } break; default: /* Invalid attribute id */ return MAC_UNSUPPORTED_ATTRIBUTE; } return MAC_SUCCESS; }
/* * \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. */ trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE); CONF_REG_WRITE(); /* Write dummy value to start measurement. */ 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)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 = 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 */ trx_reg_read(RG_IRQ_STATUS); /* Enable reception agian */ trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); /* Switch receiver off again */ set_trx_state(CMD_TRX_OFF); return ed_value; }
/* * \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); #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); } CONF_REG_WRITE(); #ifdef PROMISCUOUS_MODE if (tal_pib.PromiscuousMode) { set_trx_state(CMD_RX_ON); } #endif }
retval_t tal_ext_pa_ctrl(bool pa_ext_sw_ctrl) { bool temp; trx_bit_write(SR_PA_EXT_EN, pa_ext_sw_ctrl); #if (TAL_TYPE == ATMEGARFA1) CONF_REG_WRITE(); #endif /* TAL_TYPE == ATMEGA128RFA1 */ /* Read the PA_EXT_EN bit to check the configuration */ temp = /*(bool)*/ trx_bit_read(SR_PA_EXT_EN); if (pa_ext_sw_ctrl == temp) { /* return success if the configuration is done correctly */ return MAC_SUCCESS; } else { /* return success if the configuration is not done correctly */ return FAILURE; } }
/* * \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 */ 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 */ 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 = 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 (trx_bit_read(SR_CCA_STATUS) == CCA_CH_IDLE) { cca_status = PHY_IDLE; } else { cca_status = PHY_BUSY; } /* Enable frame reception again. */ trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); CONF_REG_WRITE(); return (phy_enum_t)cca_status; }
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; } }
/* * \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. */ trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_DISABLE); /* Disable *buffer *protection *mode */ CONF_REG_WRITE(); pal_timer_delay(2); /* Allow pin change to get effective */ trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE); /* Enable *buffer *protection *mode */ CONF_REG_WRITE(); return; } receive_frame = (frame_info_t *)BMM_BUFFER_POINTER(tal_rx_buffer); #ifdef PROMISCUOUS_MODE if (tal_pib.PromiscuousMode) { /* Check for valid FCS */ if (trx_bit_read(SR_RX_CRC_VALID) == CRC16_NOT_VALID) { return; } } #endif /* Get ED value; needed to normalize LQI. */ ed_value = trx_reg_read(RG_PHY_ED_LEVEL); /* Get frame length from transceiver. */ phy_frame_len = ext_frame_length = 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. */ 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) { /* 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. */ /* 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 */ 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 */ trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE); /* Enable *buffer *protection *mode */ CONF_REG_WRITE(); } /* * 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(); }
/* * \brief Sends frame * * \param use_csma Flag indicating if CSMA is requested * \param tx_retries Flag indicating if transmission retries are requested * by the MAC layer */ void send_frame(csma_mode_t csma_mode, bool tx_retries) { tal_trx_status_t trx_status; /* Configure tx according to tx_retries */ if (tx_retries) { trx_bit_write(SR_MAX_FRAME_RETRIES, tal_pib.MaxFrameRetries); } else { trx_bit_write(SR_MAX_FRAME_RETRIES, 0); } /* Configure tx according to csma usage */ if ((csma_mode == NO_CSMA_NO_IFS) || (csma_mode == NO_CSMA_WITH_IFS)) { if (tx_retries) { trx_bit_write(SR_MAX_CSMA_RETRIES, tal_pib.MaxCSMABackoffs); trx_reg_write(RG_CSMA_BE, 0x00); } else { trx_bit_write(SR_MAX_CSMA_RETRIES, 7); } } else { trx_reg_write(RG_CSMA_BE, ((tal_pib.MaxBE << 4) | tal_pib.MinBE)); trx_bit_write(SR_MAX_CSMA_RETRIES, tal_pib.MaxCSMABackoffs); } CONF_REG_WRITE(); do { trx_status = set_trx_state(CMD_TX_ARET_ON); } while (trx_status != TX_ARET_ON); /* Handle interframe spacing */ if (csma_mode == NO_CSMA_WITH_IFS) { if (last_frame_length > aMaxSIFSFrameSize) { pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US( macMinLIFSPeriod_def) - IRQ_PROCESSING_DLY_US - PRE_TX_DURATION_US); last_frame_length = 0; } else { pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US( macMinSIFSPeriod_def) - IRQ_PROCESSING_DLY_US - PRE_TX_DURATION_US); last_frame_length = 0; } } else { /* * If no delay is applied after switching to TX_ARET_ON, * a short delay is required that allows that a pending TX_END *IRQ for * ACK transmission gets served. */ pal_timer_delay(TRX_IRQ_DELAY_US); } ENTER_CRITICAL_REGION(); /* prevent from buffer underrun */ /* Toggle the SLP_TR pin triggering transmission. */ TRX_SLP_TR_HIGH(); PAL_WAIT_65_NS(); TRX_SLP_TR_LOW(); /* * Send the frame to the transceiver. * Note: The PhyHeader is the first byte of the frame to * be sent to the transceiver and this contains the frame * length. */ trx_frame_write(tal_frame_to_tx, tal_frame_to_tx[0] - 1); tal_state = TAL_TX_AUTO; LEAVE_CRITICAL_REGION(); }
/* * \brief TAL task handling * * This function * - Checks and allocates the receive buffer. * - Processes the TAL incoming frame queue. * - Implements the TAL state machine. */ void tal_task(void) { /* Check if the receiver needs to be switched on. */ if (tal_rx_on_required && (tal_state == TAL_IDLE)) { /* Check if a receive buffer has not been available before. */ if (tal_rx_buffer == NULL) { tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE); } /* Check if buffer could be allocated */ if (NULL != tal_rx_buffer) { /* * Note: * This flag needs to be reset BEFORE the received is *switched on. */ tal_rx_on_required = false; /* * Release the protected buffer and set it again for *further protection * since the buffer is available now. */ 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 */ trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE); /* *Enable *buffer *protection *mode **/ CONF_REG_WRITE(); #ifdef PROMISCUOUS_MODE if (tal_pib.PromiscuousMode) { set_trx_state(CMD_RX_ON); } else { set_trx_state(CMD_RX_AACK_ON); } #else /* Normal operation */ set_trx_state(CMD_RX_AACK_ON); #endif } } else { /* no free buffer is available; try next time again */ } /* * If the transceiver has received a frame and it has been placed * into the queue of the TAL, the frame needs to be processed further. */ if (tal_incoming_frame_queue.size > 0) { buffer_t *rx_frame; /* Check if there are any pending data in the *incoming_frame_queue. */ rx_frame = qmm_queue_remove(&tal_incoming_frame_queue, NULL); if (NULL != rx_frame) { process_incoming_frame(rx_frame); } } /* Handle the TAL state machines */ switch (tal_state) { case TAL_IDLE: /* Do nothing, but fall through... */ case TAL_TX_AUTO: /* Wait until state is changed to TAL_TX_DONE inside tx end ISR **/ break; case TAL_TX_DONE: tx_done_handling(); /* see tal_tx.c */ break; #ifdef BEACON_SUPPORT case TAL_SLOTTED_CSMA: slotted_csma_state_handling(); /* see tal_slotted_csma.c */ break; #endif /* BEACON_SUPPORT */ #if (MAC_SCAN_ED_REQUEST_CONFIRM == 1) case TAL_ED_RUNNING: /* Do nothing here. Wait until ED is completed. */ break; case TAL_ED_DONE: ed_scan_done(); break; #endif /* (MAC_SCAN_ED_REQUEST_CONFIRM == 1) */ default: Assert("tal_state is not handled" == 0); break; } } /* tal_task() */
/* * \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 ((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: { 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)' */ } CONF_REG_WRITE(); return MAC_SUCCESS; } /* tal_pib_set() */
retval_t tal_ant_div_config(bool div_ctrl, uint8_t ant_ctrl) { retval_t return_var = FAILURE; if (true == div_ctrl) { /* do the configurations if diversity has to be enabled */ trx_bit_write(SR_ANT_CTRL, ANT_CTRL_0); trx_bit_write(SR_ANT_DIV_EN, ANT_DIV_ENABLE); #if ((TAL_TYPE != AT86RF212) && (TAL_TYPE != AT86RF212B)) trx_bit_write(SR_PDT_THRES, THRES_ANT_DIV_ENABLE); #endif /* End of ((TAL_TYPE != AT86RF212) && (TAL_TYPE!= AT86RF212B)) */ trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_ENABLE); #if (TAL_TYPE == ATMEGARFA1) CONF_REG_WRITE(); #endif /* TAL_TYPE == ATMEGA128RFA1 */ /* check the values written in transceiver registers */ if ((trx_bit_read(SR_ANT_CTRL) == ANT_CTRL_0) && (trx_bit_read(SR_ANT_DIV_EN) == ANT_DIV_ENABLE) && \ (trx_bit_read(SR_ANT_EXT_SW_EN) == ANT_EXT_SW_ENABLE)) { #if ((TAL_TYPE != AT86RF212) && (TAL_TYPE != AT86RF212B)) if ((trx_bit_read(SR_PDT_THRES) == THRES_ANT_DIV_ENABLE)) #endif return_var = MAC_SUCCESS; } else { return_var = FAILURE; } } else { /* do the configurations if diversity has to be disabled */ trx_bit_write(SR_ANT_DIV_EN, ANT_DIV_DISABLE); #if ((TAL_TYPE != AT86RF212) && (TAL_TYPE != AT86RF212B)) trx_bit_write(SR_PDT_THRES, THRES_ANT_DIV_DISABLE); #endif trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_ENABLE); if (ant_ctrl == ANT_CTRL_1) { /* Enable A1/X2 */ trx_bit_write(SR_ANT_CTRL, ANT_CTRL_1); } else if (ant_ctrl == ANT_CTRL_2) { /* Enable A2/X3 */ trx_bit_write(SR_ANT_CTRL, ANT_CTRL_2); } else if (ant_ctrl == ANT_CTRL_0 || ant_ctrl == ANT_CTRL_3) { trx_bit_write(SR_ANT_CTRL, ANT_CTRL_0); ant_ctrl = 0; } else { return_var = MAC_INVALID_PARAMETER; } #if (TAL_TYPE == ATMEGARFA1) CONF_REG_WRITE(); #endif /* TAL_TYPE == ATMEGA128RFA1 */ /* check the values written in transceiver registers */ if ((trx_bit_read(SR_ANT_CTRL) == ant_ctrl) && (trx_bit_read(SR_ANT_DIV_EN) == ANT_DIV_DISABLE) && \ (trx_bit_read(SR_ANT_EXT_SW_EN) == ANT_EXT_SW_DISABLE)) { #if ((TAL_TYPE != AT86RF212) && (TAL_TYPE != AT86RF212B)) if ((trx_bit_read(SR_PDT_THRES) == THRES_ANT_DIV_ENABLE)) #endif return_var = MAC_SUCCESS; } else { return_var = FAILURE; } } return return_var; }