/** * @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() */
/* * \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 }