/** * \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 */ 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 */ trx_irq_init((FUNC_PTR)cca_done_irq_handler); trx_reg_write(RG_IRQ_MASK, TRX_IRQ_CCA_ED_READY); /* enable * CCA * interrupt **/ /* Start CCA */ 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; }
/** * @brief Triggers CCA measurement at transceiver * * @param trx_id Transceiver identifier */ static void trigger_cca_meaurement(trx_id_t trx_id) { /* Trigger CCA measurement */ uint16_t reg_offset = RF_BASE_ADDR_OFFSET * trx_id; /* Cancel any ongoing reception and ensure that TXPREP is reached. */ if (trx_state[trx_id] == RF_TRXOFF) { switch_to_txprep(trx_id); } /* Disable BB */ trx_bit_write(reg_offset + SR_BBC0_PC_BBEN, 0); /* Enable IRQ EDC */ trx_bit_write(reg_offset + SR_RF09_IRQM_EDC, 1); /* CCA duration is already set by default; see apply_phy_settings() */ /* Setup and start energy detection */ trx_bit_write(reg_offset + SR_RF09_AGCC_FRZC, 0); /* Ensure AGC is not * hold */ if (trx_state[trx_id] != RF_RX) { trx_reg_write(reg_offset + RG_RF09_CMD, RF_RX); pal_timer_delay(tal_pib[trx_id].agc_settle_dur); /* allow * filters to * settle */ trx_state[trx_id] = RF_RX; } tx_state[trx_id] = TX_CCA; /* Start single ED measurement; use reg_write - it's the only *subregister */ trx_reg_write(reg_offset + RG_RF09_EDC, RF_EDSINGLE); /* Wait for EDC IRQ and handle it within cca_done_handling() */ }
void radio_init(uint8_t * rxbuf, uint8_t rxbufsz) { trx_regval_t status; /* init cpu peripherals and global IRQ enable */ radiostatus.rxframe = rxbuf; radiostatus.rxframesz = rxbufsz; //trx_set_irq_handler(radio_irq_handler); /* transceiver initialization */ TRX_RESET_LOW(); TRX_SLPTR_LOW(); DELAY_US(TRX_RESET_TIME_US); #if defined(CUSTOM_RESET_TIME_MS) DELAY_MS(CUSTOM_RESET_TIME_MS); #endif TRX_RESET_HIGH(); /* disable IRQ and clear any pending IRQs */ trx_reg_write(RG_IRQ_MASK, 0); trx_reg_read(RG_IRQ_STATUS); trx_bit_write(SR_TRX_CMD, CMD_TRX_OFF); DELAY_US(510); status = trx_bit_read(SR_TRX_STATUS); if (status != TRX_OFF) { radio_error(STATE_SET_FAILED); } trx_bit_write(SR_TX_AUTO_CRC_ON, 1); trx_reg_write(RG_IRQ_MASK, TRX_IRQ_RX_START | TRX_IRQ_RX_END | TRX_IRQ_TX_END); radiostatus.state = STATE_OFF; radiostatus.idle_state = STATE_OFF; }
/* * \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); /* 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); /* 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); #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 return ed_value; }
void radio_init(uint8_t * rxbuf, uint8_t rxbufsz) { trx_regval_t status; /* init cpu peripherals and global IRQ enable */ radiostatus.rxframe = rxbuf; radiostatus.rxframesz = rxbufsz; trx_io_init(DEFAULT_SPI_RATE); trx_set_irq_handler(radio_irq_handler); /* transceiver initialization */ TRX_RESET_LOW(); TRX_SLPTR_LOW(); DELAY_US(TRX_RESET_TIME_US); #if defined(CUSTOM_RESET_TIME_MS) DELAY_MS(CUSTOM_RESET_TIME_MS); #endif TRX_RESET_HIGH(); /* disable IRQ and clear any pending IRQs */ trx_reg_write(RG_IRQ_MASK, 0); trx_reg_read(RG_IRQ_STATUS); #if RADIO_TYPE == RADIO_AT86RF212 trx_reg_write(RG_TRX_CTRL_0, 0x19); #ifdef CHINABAND trx_reg_write(RG_CC_CTRL_1, CCBAND ); trx_reg_write(RG_CC_CTRL_0, CCNUMBER);//channel 0 trx_reg_write(RG_TRX_CTRL_2, TRX_OQPSK250); /*trx_bit_write(SR_OQPSK_SUB1_RC_EN,1); trx_bit_write(SR_BPSK_OQPSK,1); trx_bit_write(SR_SUB_MODE,1); trx_bit_write(SR_OQPSK_DATA_RATE,0); trx_bit_write(SR_CC_BAND,CCBAND); */ DELAY_US(510); #endif trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF); DELAY_US(510); #else trx_bit_write(SR_TRX_CMD, CMD_TRX_OFF); DELAY_US(510); #endif do { status = trx_bit_read(SR_TRX_STATUS); } while (status != TRX_OFF); trx_bit_write(SR_TX_AUTO_CRC_ON, 1); trx_reg_write(RG_IRQ_MASK, TRX_IRQ_RX_START | TRX_IRQ_TRX_END); radiostatus.state = STATE_OFF; radiostatus.idle_state = STATE_OFF; }
/** * \brief Init the radio * \return Returns success/fail * \retval 0 Success */ static int rf212_init(void) { volatile uint8_t regtemp; uint8_t radio_state; /* don't optimize this away, it's important */ //uint8_t temp; PRINTF("RF212: init.\n"); /* init SPI and GPIOs, wake up from sleep/power up. */ //rf212_arch_init(); trx_spi_init(); /* reset will put us into TRX_OFF state */ /* reset the radio core */ port_pin_set_output_level(AT86RFX_RST_PIN, false); delay_cycles_ms(1); port_pin_set_output_level(AT86RFX_RST_PIN, true); port_pin_set_output_level(AT86RFX_SLP_PIN, false); /*wakeup from sleep*/ /* before enabling interrupts, make sure we have cleared IRQ status */ regtemp = trx_reg_read(RF212_REG_IRQ_STATUS); printf("After wake from sleep\n"); radio_state = rf212_status(); printf("After arch read reg: state 0x%04x\n", radio_state); /* Assign regtemp to regtemp to avoid compiler warnings */ regtemp = regtemp; if(radio_state == STATE_P_ON) { trx_reg_write(RF212_REG_TRX_STATE, TRXCMD_TRX_OFF); } trx_irq_init((FUNC_PTR)rf212_interrupt_poll); ENABLE_TRX_IRQ(); system_interrupt_enable_global(); /* Configure the radio using the default values except these. */ trx_reg_write(RF212_REG_TRX_CTRL_1, RF212_REG_TRX_CTRL_1_CONF); trx_reg_write(RF212_REG_PHY_CC_CCA, RF212_REG_PHY_CC_CCA_CONF); trx_reg_write(RF212_REG_PHY_TX_PWR_CONF, RF212_REG_PHY_TX_PWR_CONF); //temp = rf212_arch_read_reg(RF212_REG_TRX_CTRL_2); trx_reg_write(RF212_REG_TRX_CTRL_2, RF212_REG_TRX_CTRL_2_CONF); trx_reg_write(RF212_REG_IRQ_MASK, RF212_REG_IRQ_MASK_CONF); #if HW_CSMA_FRAME_RETRIES trx_bit_write(SR_MAX_FRAME_RETRIES, 3); trx_bit_write(SR_MAX_CSMA_RETRIES, 4); #else trx_bit_write(SR_MAX_FRAME_RETRIES, 0); trx_bit_write(SR_MAX_CSMA_RETRIES, 7); #endif SetPanId(IEEE802154_CONF_PANID); rf_generate_random_seed(); /* start the radio process */ process_start(&rf212_radio_process, NULL); return 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; } } /* * 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); trx_reg_read(RG_IRQ_STATUS); /* Clear existing interrupts */ trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE); trx_irq_init((FUNC_PTR)trx_ed_irq_handler_cb); trx_bit_write(SR_IRQ_MASK, TRX_IRQ_4_CCA_ED_DONE); /* 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 */ trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); trx_irq_init((FUNC_PTR)trx_irq_handler_cb); 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 */ 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; }
/* * \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); } break; default: /* Invalid attribute id */ return MAC_UNSUPPORTED_ATTRIBUTE; } return MAC_SUCCESS; }
/* * \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 */ trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); 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); }
/* * \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) { trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); trx_irq_init((FUNC_PTR)trx_irq_handler_cb); 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); }
/* * \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_DETECTION_DONE); set_trx_state(CMD_TRX_OFF); /* Check if channel was idle or busy. */ if (trx_bit_read(SR_CCA_STATUS) == CCA_STATUS_CHANNEL_IS_IDLE) { cca_status = PHY_IDLE; } else { cca_status = PHY_BUSY; } /* Enable frame reception again. */ trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); return (phy_enum_t)cca_status; }
/* * \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; int8_t rssi_base_val; switch (tal_pib.CurrentPage) { case 0: /* BPSK */ if (tal_pib.CurrentChannel == 0) { rssi_base_val = RSSI_BASE_VAL_BPSK_20_DBM; } else { rssi_base_val = RSSI_BASE_VAL_BPSK_40_DBM; } break; case 2: /* O-QPSK */ if (tal_pib.CurrentChannel == 0) { rssi_base_val = RSSI_BASE_VAL_OQPSK_100_DBM; } else { rssi_base_val = RSSI_BASE_VAL_OQPSK_SIN_250_DBM; } break; case 5: /* Chinese band */ default: /* High data rate modes */ rssi_base_val = RSSI_BASE_VAL_OQPSK_RC_250_DBM; break; } tfa_pib_rx_sens = *((int8_t *)value); if (tfa_pib_rx_sens > (rssi_base_val + 45)) { reg_val = 0xF; tfa_pib_rx_sens = (rssi_base_val + 45); } else if (tfa_pib_rx_sens <= rssi_base_val) { reg_val = 0x0; tfa_pib_rx_sens = rssi_base_val; } else { reg_val = ((tfa_pib_rx_sens - (rssi_base_val)) / 3) + 1; } trx_bit_write(SR_RX_PDT_LEVEL, reg_val); } break; default: /* Invalid attribute id */ return MAC_UNSUPPORTED_ATTRIBUTE; } return MAC_SUCCESS; }
/* * \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); 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); 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 */ trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); 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 */ trx_reg_write(RG_PHY_ED_LEVEL, 0xFF); return MAC_SUCCESS; }
/** * @brief Stops CW transmission * * @param trx_id Identifier of the transceiver */ void tfa_continuous_tx_stop(trx_id_t trx_id) { uint16_t reg_offset = BB_BASE_ADDR_OFFSET * trx_id; /* Stop continuous transmission */ trx_bit_write(reg_offset + SR_BBC0_PC_CTX, 0); #ifdef IQ_RADIO /* Allow command via SPI */ pal_dev_bit_write(RF215_RF, SR_RF_IQIFC0_EEC, 0); #endif switch_to_txprep(trx_id); /* Disable carrier transmission - even if it has not been used. */ uint8_t dac_config[2] = {0x00, 0x00}; uint16_t rft_reg_offset = RFT_TST_ADDR_OFFSET * trx_id; #ifdef IQ_RADIO pal_dev_write(RF215_RF, rft_reg_offset + RG_RF09_TXDACI, dac_config, 2); /* Enable embedded TX control again */ pal_dev_bit_write(RF215_RF, SR_RF_IQIFC0_EEC, 1); #else trx_write(rft_reg_offset + RG_RF09_TXDACI, dac_config, 2); /* Disable baseband bypass */ trx_bit_write( SR_RF_IQIFC1_CHPM, 0); #endif /* Restore previous settings */ if (tal_state[trx_id] == TAL_TFA_CW_RX) { tal_state[trx_id] = TAL_IDLE; switch_to_rx(trx_id); } else { tal_state[trx_id] = TAL_IDLE; /* Switch to TRXOFF */ #ifdef IQ_RADIO pal_dev_reg_write(RF215_RF, reg_offset + RG_RF09_CMD, RF_TRXOFF); pal_dev_reg_write(RF215_BB, reg_offset + RG_RF09_CMD, RF_TRXOFF); #else trx_reg_write(reg_offset + RG_RF09_CMD, RF_TRXOFF); #endif trx_state[trx_id] = RF_TRXOFF; } }
/** * @brief Initializes the transceiver * * This function is called to initialize the general transceiver functionality * after power or IC reset. */ static void trx_init(void) { /* * Configure generic trx functionality * Configure Trx registers that are reset during DEEP_SLEEP and IC reset * I.e.: RF_CFG, RF_BMDVC, RF_XOC, RF_IQIFC0, RF_IQIFC1, RF_IQIFC2 */ #ifdef TRX_IRQ_POLARITY #if (TRX_IRQ_POLARITY == 0) trx_bit_write(SR_RF_CFG_IRQP, 0); #endif #endif #if (TRX_CLOCK_OUTPUT_SELECTION != 1) #ifdef IQ_RADIO pal_dev_bit_write(RF215_RF, SR_RF_CLKO_OS, TRX_CLOCK_OUTPUT_SELECTION); #else trx_bit_write(SR_RF_CLKO_OS, TRX_CLOCK_OUTPUT_SELECTION); #endif #endif }
/* * \brief Write all shadow PIB variables to the transceiver * * This function writes all shadow PIB variables to the transceiver. * It is assumed that the radio does not sleep. */ void write_all_tal_pib_to_trx(void) { uint8_t *ptr_to_reg; ptr_to_reg = (uint8_t *)&tal_pib.PANId; for (uint8_t i = 0; i < 2; i++) { trx_reg_write((RG_PAN_ID_0 + i), *ptr_to_reg); ptr_to_reg++; } ptr_to_reg = (uint8_t *)&tal_pib.IeeeAddress; for (uint8_t i = 0; i < 8; i++) { trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr_to_reg); ptr_to_reg++; } ptr_to_reg = (uint8_t *)&tal_pib.ShortAddress; for (uint8_t i = 0; i < 2; i++) { trx_reg_write((RG_SHORT_ADDR_0 + i), *ptr_to_reg); ptr_to_reg++; } /* Configure TX_ARET; CSMA and CCA */ trx_bit_write(SR_CCA_MODE, tal_pib.CCAMode); #ifdef SW_CONTROLLED_CSMA /* * If receiver is enabled during backoff periods, * CSMA and frame re-transmissions are handled by software. * Setup trx for immediate transmission. */ trx_bit_write(SR_MAX_FRAME_RETRIES, 0); trx_bit_write(SR_MAX_CSMA_RETRIES, 7); #else trx_bit_write(SR_MIN_BE, tal_pib.MinBE); trx_bit_write(SR_MAX_BE, tal_pib.MaxBE); #endif trx_bit_write(SR_AACK_I_AM_COORD, tal_pib.PrivatePanCoordinator); /* set phy parameter */ apply_channel_page_configuration(tal_pib.CurrentPage); { uint8_t reg_value; reg_value = convert_phyTransmitPower_to_reg_value( tal_pib.TransmitPower); trx_reg_write(RG_PHY_TX_PWR, reg_value); } #ifdef PROMISCUOUS_MODE if (tal_pib.PromiscuousMode) { set_trx_state(CMD_RX_ON); } #endif }
void cMxRadio::begin(channel_t chan,uint16_t panid,uint16_t localaddress,bool needackval,bool autotxval,bool autorxval,char autoretrycount) { setautotx=autotxval; setautorx=autorxval; needack=needackval; radio_init(rxFrameBuffer, MAX_FRAME_SIZE); ////////////////////////////// #ifdef SR_MAX_FRAME_RETRES trx_bit_write(SR_MAX_FRAME_RETRES,autoretrycount & 0Xf);//for auto wake up ////////////////////////////// #endif if(!needack) txTmpBuffer[0] = 0x41; else txTmpBuffer[0] = 0x61; //ack required txTmpBuffer[1] = 0x88; txTmpBuffer[2] = 0; txTmpBuffer[3]=(uint8_t)(panid & 0xFF ); txTmpBuffer[4]=(uint8_t)((panid>>8) & 0xFF ); txTmpBuffer[5] = 0xFF; //dest address low byte txTmpBuffer[6] = 0xFF; //dest address hight byte txTmpBuffer[7] = (uint8_t)(localaddress & 0xFF ); txTmpBuffer[8] = (uint8_t)((localaddress>>8) & 0xFF ); setParam(phyPanId,(uint16_t)panid ); setParam(phyShortAddr,(uint16_t)localaddress ); radio_set_param(RP_CHANNEL(chan)); // default to receiver if (setautorx) radio_set_state(STATE_RXAUTO); else radio_set_state(STATE_RX); #ifdef ENABLE_DIG3_DIG4 trx_bit_write(SR_PA_EXT_EN, 1); #endif }
/* * \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 = trx_reg_read(RG_TRX_RPC); 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. */ 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 = 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. */ 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. */ trx_reg_write(RG_TRX_RPC, previous_RPC_value); }
/* * \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]; trx_bit_write(SR_TX_AUTO_CRC_ON, TX_AUTO_CRC_DISABLE); trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF); trx_bit_write(SR_TST_CTRL_DIG, TST_CONT_TX); /* Here: use 2MBPS mode for PSD measurements. * Omit the two following lines, if 250k mode is desired for PRBS mode. **/ trx_reg_write(RG_TRX_CTRL_2, 0x03); trx_reg_write(RG_RX_CTRL, 0x37); if (tx_mode == CW_MODE) { txcwdata[0] = 1; /* length */ /* Step 12 - frame buffer write access */ txcwdata[1] = 0x00; /* f=fch-0.5 MHz; set value to 0xFF for * f=fch+0.5MHz */ trx_frame_write(txcwdata, 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; } } trx_frame_write(txcwdata, 128); } trx_reg_write(RG_PART_NUM, 0x54); trx_reg_write(RG_PART_NUM, 0x46); set_trx_state(CMD_PLL_ON); TRX_SLP_TR_HIGH(); TRX_SLP_TR_LOW(); }
int main(void) { trx_regval_t rval; /* This will stop the application before initializing the radio transceiver * (ISP issue with MISO pin, see FAQ) */ trap_if_key_pressed(); /* Step 0: init MCU peripherals */ LED_INIT(); trx_io_init(SPI_RATE_1_2); LED_SET_VALUE(LED_MAX_VALUE); LED_SET_VALUE(0); /* Step 1: initialize the transceiver */ TRX_RESET_LOW(); TRX_SLPTR_LOW(); DELAY_US(TRX_RESET_TIME_US); TRX_RESET_HIGH(); trx_reg_write(RG_TRX_STATE,CMD_TRX_OFF); DELAY_US(TRX_INIT_TIME_US); rval = trx_bit_read(SR_TRX_STATUS); ERR_CHECK(TRX_OFF!=rval); LED_SET_VALUE(1); /* Step 2: setup transmitter * - configure radio channel * - go into RX state, * - enable "receive end" IRQ */ trx_bit_write(SR_CHANNEL,CHANNEL); trx_reg_write(RG_TRX_STATE,CMD_RX_ON); #if defined(TRX_IRQ_TRX_END) trx_reg_write(RG_IRQ_MASK,TRX_IRQ_TRX_END); #elif defined(TRX_IRQ_RX_END) trx_reg_write(RG_IRQ_MASK,TRX_IRQ_RX_END); #else # error "Unknown IRQ bits" #endif sei(); LED_SET_VALUE(2); /* Step 3: Going to receive frames */ rxcnt = 0; LED_SET_VALUE(0); while(1); }
/* * \brief handling of CCA result. */ void cca_done_handling(void) { set_trx_state(CMD_PLL_ON); /* leave RX_ON */ /* Restore IRQ handling */ trx_irq_init((FUNC_PTR)trx_irq_handler_cb); trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT); trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); /* Enable frame reception. **/ /* Check if channel was idle or busy */ if (trx_bit_read(SR_CCA_STATUS) == CCA_STATUS_CHANNEL_IS_IDLE) { tx_frame(); } else { tal_state = TAL_CSMA_CONTINUE; } }
radio_cca_t radio_do_cca(void) { uint8_t tmp, trxcmd, trxstatus; radio_cca_t ret = RADIO_CCA_FREE; trxcmd = trx_reg_read(RG_TRX_STATE); trx_reg_write(RG_TRX_STATE, CMD_RX_ON); tmp = 130; do { trxstatus = trx_bit_read(SR_TRX_STATUS); if ((RX_ON == trxstatus) || (BUSY_RX == trxstatus)) { break; } DELAY_US(32); /* wait for one octett */ } while(--tmp); trx_reg_write(RG_TRX_STATE, CMD_PLL_ON); trx_reg_write(RG_TRX_STATE, CMD_RX_ON); trx_bit_write(SR_CCA_REQUEST,1); DELAY_US(140); /* we need to read the whole status register * because CCA_DONE and CCA_STATUS are valid * only for one read, after the read they are reset */ tmp = trx_reg_read(RG_TRX_STATUS); if(0 == (tmp & 0x80)) { ret = RADIO_CCA_FAIL; } else if (tmp & 0x40) { ret = RADIO_CCA_FREE; } else { ret = RADIO_CCA_BUSY; } trx_reg_write(RG_TRX_STATE, trxcmd); return ret; }
/** * @brief Callback function for CCA completion. * * @param trx_id Transceiver identifier */ void cca_done_handling(trx_id_t trx_id) { switch_to_txprep(trx_id); /* Leave state Rx */ /* Switch BB on again */ uint16_t reg_offset = RF_BASE_ADDR_OFFSET * trx_id; trx_bit_write(reg_offset + SR_BBC0_PC_BBEN, 1); /* Determine if channel is idle */ if (tal_current_ed_val[trx_id] < tal_pib[trx_id].CCAThreshold) { /* Idle */ tx_ms_ppdu(trx_id); } else { /* Busy */ csma_continue(trx_id); } }
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 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. */ 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. */ 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 = 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. */ trx_reg_write(RG_IRQ_STATUS, 0xFF); trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT); /* Set the seed for the random number generator. */ srand(seed); }
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 Radio Initialization * * Overload for radio initalization that allows for the user to set a custom frame header * * @param chan channel number for the radio to use, 11 to 26 * @param frameHeader HeadSize byte custom frame header */ void cMxRadio::begin(channel_t chan, uint8_t* frameHeader) { radio_init(rxFrameBuffer, MAX_FRAME_SIZE); if (frameHeader) { // copy custom frame header int i; for (i = 0; i < HeadSize; i++) txTmpBuffer[i] = frameHeader[i]; } else { txTmpBuffer[0] = 0x41; txTmpBuffer[1] = 0x88; txTmpBuffer[2] = 0; txTmpBuffer[3]=0xCD; txTmpBuffer[4]=0xAB; txTmpBuffer[5] = 0xFF; //dest address low byte txTmpBuffer[6] = 0xFF; //dest address hight byte txTmpBuffer[7] = 0x01;; txTmpBuffer[8] = 0x00;; } // set the channel radio_set_param(RP_CHANNEL(chan)); // default to receiver if (setautorx) radio_set_state(STATE_RXAUTO); else radio_set_state(STATE_RX); #ifdef ENABLE_DIG3_DIG4 trx_bit_write(SR_PA_EXT_EN, 1); #endif }
/* * \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; trx_reg_write(RG_PAN_ID_0, (uint8_t)tal_pib.PANId); 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++) { trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr_to_reg); ptr_to_reg++; } trx_reg_write(RG_SHORT_ADDR_0, (uint8_t)tal_pib.ShortAddress); trx_reg_write(RG_SHORT_ADDR_1, (uint8_t)(tal_pib.ShortAddress >> 8)); /* configure TX_ARET; CSMA and CCA */ trx_bit_write(SR_CCA_MODE, tal_pib.CCAMode); trx_bit_write(SR_MIN_BE, tal_pib.MinBE); trx_bit_write(SR_AACK_I_AM_COORD, tal_pib.PrivatePanCoordinator); /* set phy parameter */ trx_bit_write(SR_MAX_BE, tal_pib.MaxBE); #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 }
/** * @brief Radio Initialization * * The function initializes all IO ressources, * needed for the usage of the radio and performs * a reset to the radio. * It prepares the frame header. * Then it sets the channel number and defaults to RX state. * * @param chan channel number for the radio to use, 11 to 26 * @param frameHeader 7 byte custom frame header, or null if you want to use a default frame header */ void zr_init(channel_t chan, uint8_t* frameHeader) { user_radio_error = 0; user_radio_irq = 0; zr_attach_receive_frame(zr_onReceiveFrame); zr_attach_tx_done(zr_onTxDone); radio_init(zr_rxFrameBuffer, MAX_FRAME_SIZE); if (frameHeader) { // copy custom frame header int i; for (i = 0; i < 7; i++) zr_txTmpBuffer[i] = frameHeader[i]; } else { // fixed frame header zr_txTmpBuffer[0] = 0x01; zr_txTmpBuffer[1] = 0x80; zr_txTmpBuffer[2] = 0; zr_txTmpBuffer[3] = 0x11; zr_txTmpBuffer[4] = 0x22; zr_txTmpBuffer[5] = 0x33; zr_txTmpBuffer[6] = 0x44; } // set the channel radio_set_param(RP_CHANNEL(chan)); // default to receiver radio_set_state(STATE_RX); #ifdef ENABLE_DIG3_DIG4 trx_bit_write(SR_PA_EXT_EN, 1); #endif ZR_RFRX_LED_OUTPUT(); ZR_RFTX_LED_OUTPUT(); ZR_RFRX_LED_OFF(); ZR_RFTX_LED_OFF(); }
/* * \brief Generates a 16-bit random number used as initial seed for srand() * */ static void rf_generate_random_seed(void) { uint16_t seed = 0; uint8_t cur_random_val = 0; /* * 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(); do { trx_reg_write(RF233_REG_TRX_STATE, TRXCMD_TRX_OFF); } while (TRXCMD_TRX_OFF != rf233_status()); do { /* Ensure that PLL has locked and receive mode is reached. */ trx_reg_write(RF233_REG_TRX_STATE, TRXCMD_PLL_ON); } while (TRXCMD_PLL_ON != rf233_status()); do { trx_reg_write(RF233_REG_TRX_STATE, TRXCMD_RX_ON); } while (TRXCMD_RX_ON != rf233_status()); /* Ensure that register bit RX_PDT_DIS is set to 0. */ 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 = trx_bit_read(SR_RND_VALUE); seed = seed << 2; seed |= cur_random_val; delay_us(1); /* wait that the random value gets updated */ } do { /* Ensure that PLL has locked and receive mode is reached. */ trx_reg_write(RF233_REG_TRX_STATE, TRXCMD_TRX_OFF); } while (TRXCMD_TRX_OFF != rf233_status()); /* * Now we need to clear potential pending TRX IRQs and * enable the TRX IRQs again. */ trx_reg_read(RF233_REG_IRQ_STATUS); trx_irq_flag_clr(); LEAVE_TRX_REGION(); /* Set the seed for the random number generator. */ srand(seed); }