Exemple #1
0
/**
 * @brief Configures RF according FSK
 *
 * @param mod_type Modulation order / type; i.e. F2FSK or F4FSK
 * @param srate Data rate
 * @param mod_idx Modulation index
 * @param trx_id Transceiver identifier
 */
retval_t fsk_rfcfg(fsk_mod_type_t mod_type, fsk_data_rate_t srate,
		mod_idx_t mod_idx, trx_id_t trx_id)
{
	retval_t status = MAC_SUCCESS;
	uint16_t reg_offset = RF_BASE_ADDR_OFFSET * trx_id;
	uint8_t srate_midx = (srate << 3) + mod_idx;

	/* TX configuration: */
	/* - PA ramp time +  TX-SSBF fcut */
	/* - DFE sampling rate reduction + TX-DFE fcut */
	{
		uint8_t temp[2];
		PGM_READ_BLOCK(temp, (uint8_t *)&fsk_params_tbl[srate_midx][0],
				2);
		rf_blk_write(reg_offset + RG_RF09_TXCUTC, temp, 2);
	}

	/* - Transmit Power*/
#ifdef IQ_RADIO
	pal_dev_reg_write(RF215_RF, reg_offset + RG_RF09_PAC,
			((3 <<
			PAC_PACUR_SHIFT) |
			(DEFAULT_TX_PWR_REG << PAC_TXPWR_SHIFT)));
#else
	trx_reg_write(reg_offset + RG_RF09_PAC,
			((3 <<
			PAC_PACUR_SHIFT) |
			(DEFAULT_TX_PWR_REG << PAC_TXPWR_SHIFT)));
#endif

	/* RX configuration: */
	/* - RX-SSBF bandwidth + RX-SSBF IF shift */
	/* - DFE sampling rate reduction  + RX-DFE cut-off ratio */
	if (trx_id == RF09) {
		uint8_t temp[2];
		PGM_READ_BLOCK(temp, (uint8_t *)&fsk_params_tbl[srate_midx][5],
				2);
		rf_blk_write(RG_RF09_RXBWC, temp, 2);
	} else {
		uint8_t temp[2];
		PGM_READ_BLOCK(temp, (uint8_t *)&fsk_params_tbl[srate_midx][7],
				2);
		rf_blk_write(RG_RF24_RXBWC, temp, 2);
	}

	/* - AGC input + AGC average period */
	/* - AGC target */
	{
		uint8_t temp[2];
		PGM_READ_BLOCK(temp, (uint8_t *)&fsk_params_tbl[srate_midx][9],
				2);
		rf_blk_write(reg_offset + RG_RF09_AGCC, temp, 2);
	}

#ifndef FWNAME
	uint8_t agcc = (uint8_t)PGM_READ_BYTE(&fsk_params_tbl[srate_midx][9]);
	uint8_t agci = (agcc & AGCC_AGCI_MASK) >> AGCC_AGCI_SHIFT;
	uint8_t avgs = (agcc & AGCC_AVGS_MASK) >> AGCC_AVGS_SHIFT;
	uint8_t rxdfe;
	if (trx_id == RF09) {
		rxdfe = (uint8_t)PGM_READ_BYTE(&fsk_params_tbl[srate_midx][6]);
	} else {
		rxdfe = (uint8_t)PGM_READ_BYTE(&fsk_params_tbl[srate_midx][8]);
	}

	uint8_t sr = rxdfe & RXDFE_SR_MASK;
	tal_pib[trx_id].agc_settle_dur
		= get_agc_settling_period(sr, avgs, agci);
#endif

#if (!defined RF215v2)
	/* Keep compiler happy */
	mod_type = mod_type;
#endif

	return status;
}
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_MS(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
     * - enable transmitters automatic crc16 generation
     * - go into RX AACK state,
     * - configure address filter
     * - enable "receive end" IRQ
     */
    trx_bit_write(SR_CHANNEL,CHANNEL);
    trx_bit_write(SR_TX_AUTO_CRC_ON,1);

    trx_reg_write(RG_PAN_ID_0,(PANID&0xff));
    trx_reg_write(RG_PAN_ID_1,(PANID>>8));

    trx_reg_write(RG_SHORT_ADDR_0,(SHORT_ADDR&0xff));
    trx_reg_write(RG_SHORT_ADDR_1,(SHORT_ADDR>>8));

    trx_reg_write(RG_TRX_STATE,CMD_RX_AACK_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: send a frame each 500ms */
    tx_cnt = 0;
    tx_in_progress = false;
    LED_SET_VALUE(0);

    while(1);

}
Exemple #3
0
/**
 * \brief      Init the radio
 * \return     Returns success/fail
 * \retval 0   Success
 */
int
rf233_init(void)
{
  volatile uint8_t regtemp;
  volatile uint8_t radio_state;  /* don't optimize this away, it's important */
  PRINTF("RF233: init.\r\n");

  /* init SPI and GPIOs, wake up from sleep/power up. */
  //rf233_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(RF233_REG_IRQ_STATUS);
  PRINTF("After wake from sleep\r\n");
  radio_state = rf233_status();
  PRINTF("After arch read reg: state 0x%04x\r\n", radio_state);

  if(radio_state == STATE_P_ON) {
	  trx_reg_write(RF233_REG_TRX_STATE, TRXCMD_TRX_OFF);
	  } 
  /* Assign regtemp to regtemp to avoid compiler warnings */
  regtemp = regtemp;
  trx_irq_init((FUNC_PTR)rf233_interrupt_poll);
  ENABLE_TRX_IRQ();  
  system_interrupt_enable_global();
  /* Configure the radio using the default values except these. */
  trx_reg_write(RF233_REG_TRX_CTRL_1,      RF233_REG_TRX_CTRL_1_CONF);
  trx_reg_write(RF233_REG_PHY_CC_CCA,      RF233_REG_PHY_CC_CCA_CONF);
  trx_reg_write(RF233_REG_PHY_TX_PWR, RF233_REG_PHY_TX_PWR_CONF);
  trx_reg_write(RF233_REG_TRX_CTRL_2,      RF233_REG_TRX_CTRL_2_CONF);
  trx_reg_write(RF233_REG_IRQ_MASK,        RF233_REG_IRQ_MASK_CONF);
  // trx_reg_write(0x17, 0x02);
#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();
  
  for(uint8_t i=0;i<8;i++)
  {
	  regtemp =trx_reg_read(0x24+i);
  }

  /* 11_09_rel */
  trx_reg_write(RF233_REG_TRX_RPC,0xFF); /* Enable RPC feature by default */
  // regtemp = trx_reg_read(RF233_REG_PHY_TX_PWR);
  
  /* start the radio process */
  process_start(&rf233_radio_process, NULL);
  return 0;
}
Exemple #4
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.
	 */
	trx_reg_write(RG_IRQ_MASK, TRX_IRQ_NONE);

	/* Check if supply voltage is within lower range */
	trx_bit_write(SR_BATMON_HR, BATMON_LOW_RANGE);
	trx_bit_write(SR_BATMON_VTH, 0x0F);
	pal_timer_delay(5); /* Wait until Batmon has been settled. */
	if (trx_bit_read(SR_BATMON_OK) == BATMON_BELOW_THRES) {
		/* Lower range */
		/* Check if supply voltage is below lower limit */
		trx_bit_write(SR_BATMON_VTH, 0);
		pal_timer_delay(2); /* Wait until Batmon has been settled. */
		if (trx_bit_read(SR_BATMON_OK) == BATMON_BELOW_THRES) {
			/* below lower limit */
			mv = SUPPLY_VOLTAGE_BELOW_LOWER_LIMIT;
		}

		range = LOW;
	} else {
		/* Higher range */
		trx_bit_write(SR_BATMON_HR, BATMON_HIGH_RANGE);
		/* Check if supply voltage is above upper limit */
		trx_bit_write(SR_BATMON_VTH, 0x0F);
		pal_timer_delay(5); /* Wait until Batmon has been settled. */
		if (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++) {
			trx_bit_write(SR_BATMON_VTH, i);
			pal_timer_delay(2); /* Wait until Batmon has been
			                     * settled. */
			if (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);
		}
	}

	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.
	 */
	trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);

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

	return mv;
}
Exemple #5
0
/**
 * \brief Configures the transceiver
 *
 * This function is called to configure the transceiver after reset.
 */
void trx_config(void)
{
	/* Set pin driver strength */
	trx_bit_write(SR_CLKM_SHA_SEL, CLKM_SHA_DISABLE);
	trx_bit_write(SR_CLKM_CTRL, CLKM_1MHZ);

	/*
	 * 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();
	trx_reg_write(RG_CSMA_SEED_0, (uint8_t)rand_value);
	trx_bit_write(SR_CSMA_SEED_1, (uint8_t)(rand_value >> 8));

	/*
	 * Since the TAL is supporting 802.15.4-2006,
	 * frames with version number 0 (compatible to 802.15.4-2003) and
	 * with version number 1 (compatible to 802.15.4-2006) are acknowledged.
	 */
	trx_bit_write(SR_AACK_FVN_MODE, FRAME_VERSION_01);
	trx_bit_write(SR_AACK_SET_PD, SET_PD); /* ACKs for data requests,
	                                        * indicate pending data */
	trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE); /* Enable
	                                                      * buffer
	                                                      * protection
	                                                      * mode */
	trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT); /* The TRX_END
	                                              * interrupt of the
	                                              * transceiver is
	                                              * enabled. */
	trx_reg_write(RG_TRX_RPC, 0xFF); /* RPC feature configuration. */

#if (ANTENNA_DIVERSITY == 1)
	/* Use antenna diversity */
	trx_bit_write(SR_ANT_CTRL, ANTENNA_DEFAULT);
	trx_bit_write(SR_PDT_THRES, THRES_ANT_DIV_ENABLE);
	trx_bit_write(SR_ANT_DIV_EN, ANT_DIV_ENABLE);
	trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_ENABLE);
#endif  /* ANTENNA_DIVERSITY */
#if (DISABLE_TSTAMP_IRQ == 0)
#if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)
	/* Enable Rx timestamping */
	trx_bit_write(SR_IRQ_2_EXT_EN, RX_TIMESTAMPING_ENABLE);
	/* Enable Tx timestamping */
	trx_bit_write(SR_ARET_TX_TS_EN, TX_ARET_TIMESTAMPING_ENABLE);
#endif  /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */
#endif

#ifdef CCA_ED_THRESHOLD

	/*
	 * Set CCA ED Threshold to other value than standard register due to
	 * board specific loss (see pal_config.h). */
	trx_bit_write(SR_CCA_ED_THRES, CCA_ED_THRESHOLD);
#endif

#ifdef EXT_RF_FRONT_END_CTRL
	/* Enable RF front end control */
	trx_bit_write(SR_PA_EXT_EN, 1);
#endif
}
Exemple #6
0
/**
 * \brief Initializes the transceiver
 *
 * This function is called to initialize the transceiver.
 *
 * \return MAC_SUCCESS  if the transceiver state is changed to TRX_OFF and the
 *                 current device part number and version number are correct;
 *         FAILURE otherwise
 */
static retval_t trx_init(void)
{
	tal_trx_status_t trx_status;
	uint8_t poll_counter = 0;

	/* Ensure control lines have correct levels. */
	TRX_RST_HIGH();
	TRX_SLP_TR_LOW();

	/* Wait typical time of timer TR1. */
	pal_timer_delay(P_ON_TO_CLKM_AVAILABLE_TYP_US);

	/* Apply reset pulse */
	TRX_RST_LOW();
	pal_timer_delay(RST_PULSE_WIDTH_US);
	TRX_RST_HIGH();

	/* Verify that TRX_OFF can be written */
	do {
		/* Wait not more than max. value of TR1. */
		if (poll_counter == P_ON_TO_CLKM_ATTEMPTS) {
			return FAILURE;
		}

		/* Wait a short time interval. */
		pal_timer_delay(TRX_POLL_WAIT_TIME_US);
		poll_counter++;

		/* Check if AT86RF231 is connected; omit manufacturer id check
		**/
	} while ((trx_reg_read(RG_VERSION_NUM) != AT86RF231_VERSION_NUM) ||
			(trx_reg_read(RG_PART_NUM) != AT86RF231_PART_NUM));

	/* Verify that TRX_OFF can be written */
	trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);

	/* Verify that the trx has reached TRX_OFF. */
	poll_counter = 0;
	do {
		/* Wait a short time interval. */
		pal_timer_delay(TRX_POLL_WAIT_TIME_US);

		trx_status = (tal_trx_status_t)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)
			Assert(
					"MAX Attempts to switch to TRX_OFF state reached" ==
					0);
#endif
			return FAILURE;
		}

		poll_counter++;
	} while (trx_status != TRX_OFF);

	tal_trx_status = TRX_OFF;

	return MAC_SUCCESS;
}
Exemple #7
0
// Section 9.8 of the RF233 manual suggests recalibrating filters at
// least every 5 minutes of operation. Transitioning out of sleep
// resets the filters automatically.
void calibrate_filters() {
  PRINTF("RF233: Calibrating filters.\n");
  trx_reg_write(RF233_REG_FTN_CTRL, 0x80);
  while (trx_reg_read(RF233_REG_FTN_CTRL) & 0x80);
}
Exemple #8
0
/**
 * @brief Perform a CCA
 *
 * This blocking function performs a CCA request.
 *
 * @return phy_enum_t PHY_IDLE or PHY_BUSY
 */
phy_enum_t tfa_cca_perform(trx_id_t trx_id)
{
	phy_enum_t ret;

	if (tal_state[trx_id] != TAL_IDLE) {
		ret = PHY_BUSY;
	} else {
		rf_cmd_state_t previous_state = trx_state[trx_id];

		if (trx_state[trx_id] == RF_TRXOFF) {
			switch_to_txprep(trx_id);
		}

		if (trx_state[trx_id] != RF_RX) {
			switch_to_rx(trx_id);
			pal_timer_delay(tal_pib[trx_id].agc_settle_dur); /*
			                                                  * allow
			                                                  * filters
			                                                  * to
			                                                  * settle */
		}

		/* Disable BB */
		uint16_t reg_offset = RF_BASE_ADDR_OFFSET * trx_id;
		trx_bit_write(reg_offset + SR_BBC0_PC_BBEN, 0);

#ifndef BASIC_MODE
		/* Enable EDC interrupt */
		trx_bit_write(reg_offset + SR_RF09_IRQM_EDC, 1);
#endif
		/* Start single ED measurement; use reg_write - it's the only
		 *subregister */
		tal_state[trx_id] = TAL_TFA_CCA;
#ifdef IQ_RADIO
		/* Enable EDC interrupt */
		pal_dev_bit_write(RF215_RF, reg_offset + SR_RF09_IRQM_EDC, 1);
		pal_dev_reg_write(RF215_RF, reg_offset + RG_RF09_EDC,
				RF_EDSINGLE);
#else
		trx_reg_write(reg_offset + RG_RF09_EDC, RF_EDSINGLE);
#endif

		/* Wait until measurement is completed */
		while (TAL_RF_IS_IRQ_SET(trx_id, RF_IRQ_EDC) == false) {
		}
		TAL_RF_IRQ_CLR(trx_id, RF_IRQ_EDC);

#ifndef BASIC_MODE
		/* Disable EDC interrupt again */
		trx_bit_write(reg_offset + SR_RF09_IRQM_EDC, 0);
#endif
#ifdef IQ_RADIO
		pal_dev_bit_write(RF215_RF, reg_offset + SR_RF09_IRQM_EDC, 0);
#endif
		/* Since it is a blocking function, restore TAL state */
		tal_state[trx_id] = TAL_IDLE;

		switch_to_txprep(trx_id); /* Leave Rx mode */

		/* Switch BB on again */
		trx_bit_write(reg_offset + SR_BBC0_PC_BBEN, 1);

		/* Capture ED value for current frame / ED scan */
#ifdef IQ_RADIO
		tal_current_ed_val[trx_id] = pal_dev_reg_read(RF215_RF,
				reg_offset +
				RG_RF09_EDV);
#else
		tal_current_ed_val[trx_id] = trx_reg_read(
				reg_offset + RG_RF09_EDV);
#endif

		if (tal_current_ed_val[trx_id] < tal_pib[trx_id].CCAThreshold) {
			/* Idle */
			ret = PHY_IDLE;
		} else {
			/* Busy */
			ret = PHY_BUSY;
		}

		/* Restore previous trx state */
		if (previous_state == RF_RX) {
			switch_to_rx(trx_id);
		} else {
			/* Switch to TRXOFF */
			trx_reg_write(reg_offset + RG_RF09_CMD, RF_TRXOFF);
#ifdef IQ_RADIO
			pal_dev_reg_write(RF215_RF, reg_offset + RG_RF09_CMD,
					RF_TRXOFF);
#endif
			trx_state[trx_id] = RF_TRXOFF;
		}
	}

	return ret;
}
/**
 * \brief Performs CCA twice
 */
static uint8_t perform_cca_twice(void)
{
	uint8_t cca_status;
	uint8_t cca_done;
	uint8_t CW = 2;
	uint32_t now_time_us;

	do {
		pal_get_current_time(&now_time_us);
	} while (pal_add_time_us(now_time_us,
			(SLEEP_TO_TRX_OFF_TYP_US +
			CCA_PREPARATION_DURATION_US)) <
			cca_starttime_us);

#if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT))
	if (tal_beacon_transmission) {
#if (_DEBUG_ > 0)
		Assert("Ongoing beacon transmission, slotted CSMA busy" == 0);
#endif
		return PHY_BUSY;
	}

#endif /* ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) */

	/* Ensure that trx is at least in TRX_OFF mode at this time. */
	if (tal_trx_status == TRX_SLEEP) {
		set_trx_state(CMD_TRX_OFF);
	}

	do {
		pal_get_current_time(&now_time_us);
	} while (pal_add_time_us(now_time_us,
			(TRX_OFF_TO_PLL_ON_TIME_US +
			CCA_PREPARATION_DURATION_US)) <
			cca_starttime_us);

	/*
	 * Set trx to PLL_ON.
	 * If trx is busy and trx cannot be set to PLL_ON, assess channel as
	 * busy.
	 */
	if (set_trx_state(CMD_PLL_ON) != PLL_ON) {
		return PHY_BUSY;
	}

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

	/* do CCA twice */
	do {
		/* wait here until 16us before backoff boundary */
		/* assume TRX is in PLL_ON */
		do {
			pal_get_current_time(&now_time_us);
		} while (pal_add_time_us(now_time_us,
				CCA_PRE_START_DURATION_US) <
				cca_starttime_us);

		set_trx_state(CMD_RX_ON);

		/* debug pin to switch on: define ENABLE_DEBUG_PINS,
		 * pal_config.h */
		PIN_CCA_START();

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

		/* wait until CCA is done and get status */
		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);

		/* between both CCA switch trx to PLL_ON to reduce power
		 * consumption */
		set_trx_state(CMD_PLL_ON);

		/* debug pin to switch on: define ENABLE_DEBUG_PINS,
		 * pal_config.h */
		PIN_CCA_END();

		/* check if channel was idle or busy */
		if (trx_bit_read(SR_CCA_STATUS) == CCA_CH_IDLE) {
			/* do next CCA at next backoff boundary */
			cca_starttime_us = pal_add_time_us(cca_starttime_us,
					TAL_CONVERT_SYMBOLS_TO_US(
					aUnitBackoffPeriod));
			CW--;
			cca_status = PHY_IDLE;
		} else { /* PHY busy */
			cca_status = PHY_BUSY;
			set_trx_state(CMD_RX_AACK_ON);
			break; /* if channel is busy do no do CCA for the second
			        * time */
		}
	} while (CW > 0);

	/*
	 * Keep trx ready for transmission if channel is idle.
	 * The transceiver is still in PLL_ON.
	 * If the channel is not idle, the trx handling is done in
	 * csma_backoff().
	 */

	/*
	 * Clear CCA interrupt flag.
	 * This is only necessary for debugging, because only in debug mode
	 * interrupt that are not handled cause an assert in the ISR.
	 */
#if (_DEBUG_ > 0)
	trx_reg_write(RG_IRQ_STATUS, 0xFF);
#endif

	/*
	 * Since we are not interested in any frames that might be received
	 * during CCA, reject any information that indicates a previous frame
	 * reception.
	 */
	trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); /* enable frame reception
	                                          * indication */

	return cca_status;
}
Exemple #10
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
 *
 * The comment 'step #' refers to the step mentioned in the RF212's datasheet.
 */
void tfa_continuous_tx_start(continuous_tx_mode_t tx_mode, bool random_content)
{
	uint8_t txcwdata[128];
	uint8_t i;

	/* step 3,6: Channel is assumed to be set before */
	trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);
	/* step 7: Enable continuous transmission - step #1 */
	trx_reg_write(0x36, 0x0F);
	if (tx_mode == CW_MODE) {
		/* step 8: Register access: CW at Fc +/- 0.1 MHz */
		if (((tal_pib.CurrentPage == 0) || (tal_pib.CurrentPage == 2) || \
				(tal_pib.CurrentPage == 16) ||
				(tal_pib.CurrentPage == 17)) &&
				(tal_pib.CurrentChannel == 0)) {                                          /*
			                                                                                   *
			                                                                                   *868.3MHz
			                                                                                   **/
			trx_reg_write(RG_TRX_CTRL_2, 0x0A); /* 400 kchip/s
			                                     * mode, step 8
			                                     * ,SUB_MODE = 0 */
		} else {
			trx_reg_write(RG_TRX_CTRL_2, 0x0E); /* 1000kchip/s
			                                     * ,SUB_MODE = 1 */
		}

		txcwdata[0] = 1; /* length */
		txcwdata[1] = 0;
		/* step 9: Frame buffer access */
		trx_frame_write(txcwdata, 2);
	} else { /* PRBS mode */
		 /* step 8: */

		/*
		 * Step 8 is not explicitly written here, because the proper
		 * value is set during reset or by updating the Channel Page.
		 * After finishing CW/PRBS another reset is performed with
		 * parameter set_default_pib set to false, which restores the
		 * original value based on the current Channel Page.
		 *
		 * I.e., in order to use PRBS with a specific data rate,
		 * the Channel Page needs to be udpated before starting PRBS.
		 */

		txcwdata[0] = 127; /* = max length */
		for (i = 1; i < 128; i++) {
			if (random_content) {
				txcwdata[i] = (uint8_t)rand();
			} else {
				txcwdata[i] = 0;
			}
		}
		/* step 9: Frame buffer access */
		trx_frame_write(txcwdata, 128);
	}

	/* step 10: Enable continuous transmission - step #2 */
	trx_reg_write(RG_PART_NUM, 0x54);
	/* step 11: Enable continuous transmission - step #3 */
	trx_reg_write(RG_PART_NUM, 0x46);
	/* step 12, 13: Stwitch PLL on */
	set_trx_state(CMD_PLL_ON);
	/* step 14: Initiate transmission using SLP_TR line */
	TRX_SLP_TR_HIGH();
	TRX_SLP_TR_LOW();
}
Exemple #11
0
/**
 * @brief Resets transceiver(s)
 *
 * @param trx_id Transceiver identifier
 *
 * @return MAC_SUCCESS  if the transceiver returns TRX_OFF
 *         FAILURE otherwise
 */
retval_t trx_reset(trx_id_t trx_id)
{
	ENTER_TRX_REGION();

	uint32_t start_time;
	uint32_t current_time;
	pal_get_current_time(&start_time);

	if (trx_id == RFBOTH) {
		TAL_RF_IRQ_CLR_ALL(RF09);
		TAL_RF_IRQ_CLR_ALL(RF24);
		tal_state[RF09] = TAL_RESET;
		tal_state[RF24] = TAL_RESET;

		/* Apply reset pulse; low active */
#ifdef IQ_RADIO
		RST_LOW();
		PAL_WAIT_1_US();
		PAL_WAIT_1_US();
		RST_HIGH();
#if (BOARD_TYPE == EVAL215_FPGA)
		pal_timer_delay(10000);
#endif
		RST_LOW();
		PAL_WAIT_1_US();
		RST_HIGH();
#else
		RST_LOW();
		PAL_WAIT_1_US();
		RST_HIGH();
#endif

		/* Wait for IRQ line */
		while (1) {
			/*
			 * @ToDo: Use a different macro for IRQ line; the
			 *polarity might be
			 * different after reset
			 */
#ifdef IQ_RADIO
			if ((PAL_DEV_IRQ_GET(RF215_BB) == HIGH) &&
					(PAL_DEV_IRQ_GET(RF215_RF) == HIGH)) {
				break;
			}

#else
			if (TRX_IRQ_GET() == HIGH) {
				break;
			}

#endif

			/* Handle timeout */
			pal_get_current_time(&current_time);
			/* @ToDo: Remove magic number */
			if (pal_sub_time_us(current_time, start_time) > 1000) {
				return FAILURE;
			}
		}
#ifdef IQ_RADIO
		trx_state[RF09] = (rf_cmd_state_t)pal_dev_reg_read(RF215_RF,
				RG_RF09_STATE);
		trx_state[RF24] = (rf_cmd_state_t)pal_dev_reg_read(RF215_RF,
				RG_RF24_STATE);
		rf_cmd_state_t bb_trx_state[NUM_TRX];
		bb_trx_state[RF09] = (rf_cmd_state_t)pal_dev_reg_read(RF215_BB,
				RG_RF09_STATE);
		bb_trx_state[RF24] = (rf_cmd_state_t)pal_dev_reg_read(RF215_BB,
				RG_RF24_STATE);
		if ((bb_trx_state[RF09] != RF_TRXOFF) ||
				(bb_trx_state[RF24] != RF_TRXOFF)) {
			return FAILURE;
		}

#else
		trx_state[RF09] = trx_reg_read(RG_RF09_STATE);
		trx_state[RF24] = trx_reg_read(RG_RF24_STATE);
#endif
		if ((trx_state[RF09] != RF_TRXOFF) ||
				(trx_state[RF24] != RF_TRXOFF)) {
			return FAILURE;
		}

		/* Get all IRQ status information */
#ifdef IQ_RADIO
		bb_irq_handler_cb();
		rf_irq_handler_cb();
#else
		trx_irq_handler_cb();
#endif
		TAL_RF_IRQ_CLR(RF09, RF_IRQ_WAKEUP);
		TAL_RF_IRQ_CLR(RF24, RF_IRQ_WAKEUP);
	} else {
		TAL_RF_IRQ_CLR_ALL(trx_id);
		tal_state[trx_id] = TAL_RESET;

		/* Trigger reset of device */
		uint16_t reg_offset = RF_BASE_ADDR_OFFSET * trx_id;

#ifdef IQ_RADIO
		pal_trx_reg_write(RF215_RF, reg_offset + RG_RF09_CMD, RF_RESET);
		pal_trx_reg_write(RF215_BB, reg_offset + RG_RF09_CMD, RF_RESET);
#else
		trx_reg_write(reg_offset + RG_RF09_CMD, RF_RESET);
#endif

		/* Wait for IRQ line */
		while (1) {
#ifdef IQ_RADIO
			if ((PAL_DEV_IRQ_GET(RF215_BB) == HIGH) &&
					(PAL_DEV_IRQ_GET(RF215_RF) == HIGH)) {
				break;
			}

#else
			if (TRX_IRQ_GET() == HIGH) {
				break;
			}

#endif

			/* Handle timeout */
			pal_get_current_time(&current_time);
			/* @ToDo: Remove magic number */
			if (pal_sub_time_us(current_time, start_time) > 1000) {
				return FAILURE;
			}
		}
		trx_state[trx_id] = RF_TRXOFF;
		/* Get all IRQ status information */
#ifdef IQ_RADIO
		bb_irq_handler_cb();
		rf_irq_handler_cb();
#else
		trx_irq_handler_cb();
#endif
		TAL_RF_IRQ_CLR(trx_id, RF_IRQ_WAKEUP);
	}

#ifdef IQ_RADIO
	pal_trx_irq_flag_clr(RF215_BB);
	pal_trx_irq_flag_clr(RF215_RF);
#else
	pal_trx_irq_flag_clr();
#endif
	LEAVE_TRX_REGION();

	return MAC_SUCCESS;
}
Exemple #12
0
/**
 * @brief Resets TAL state machine and sets the default PIB values if requested
 *
 * @param trx_id Transceiver identifier
 * @param set_default_pib Defines whether PIB values need to be set
 *                        to its default values
 *
 * @return
 *      - @ref MAC_SUCCESS if the transceiver state is changed to TRX_OFF
 *      - @ref FAILURE otherwise
 * @ingroup apiTalApi
 */
retval_t tal_reset(trx_id_t trx_id, bool set_default_pib)
{
	rf_cmd_state_t previous_trx_state[NUM_TRX];

	previous_trx_state[RF09] = trx_state[RF09];
	previous_trx_state[RF24] = trx_state[RF24];

	/* Reset the actual device or part of the device */
	if (trx_reset(trx_id) != MAC_SUCCESS) {
		return FAILURE;
	}

	/* Init Trx if necessary, e.g. trx was in deep sleep */
	if (((previous_trx_state[RF09] == RF_SLEEP) &&
			(previous_trx_state[RF24] == RF_SLEEP)) ||
			(trx_id == RFBOTH)) {
		trx_init(); /* Initialize generic trx functionality */
	}

	if (trx_id == RFBOTH) {
		for (uint8_t i = 0; i < NUM_TRX; i++) {
			/* Clean TAL and removed any pending tasks */
			cleanup_tal((trx_id_t)i);

			/* Configure the transceiver register values. */
			trx_config((trx_id_t)i);

			if (set_default_pib) {
				/* Set the default PIB values */
				init_tal_pib((trx_id_t)i); /* see 'tal_pib.c' */
				calculate_pib_values(trx_id);
			} else {
				/* nothing to do - the current TAL PIB attribute
				 *values are used */
			}

			write_all_tal_pib_to_trx((trx_id_t)i); /* see
			                                        *'tal_pib.c' */
			config_phy((trx_id_t)i);

			/* Reset TAL variables. */
			tal_state[(trx_id_t)i] = TAL_IDLE;
			tx_state[(trx_id_t)i] = TX_IDLE;
#ifdef ENABLE_FTN_PLL_CALIBRATION
			/* Stop FTN timer */
			stop_ftn_timer((trx_id_t)i);
#endif  /* ENABLE_FTN_PLL_CALIBRATION */
		}
	} else {
		/* Maintain other trx */
		trx_id_t other_trx_id;
		if (trx_id == RF09) {
			other_trx_id = RF24;
		} else {
			other_trx_id = RF09;
		}

		if (tal_state[other_trx_id] == TAL_SLEEP) {
			/* Switch other trx back to sleep again */
			uint16_t reg_offset = RF_BASE_ADDR_OFFSET *
					other_trx_id;
#ifdef IQ_RADIO
			pal_dev_reg_write(RF215_BB, reg_offset + RG_RF09_CMD,
					RF_SLEEP);
			pal_dev_reg_write(RF215_RF, reg_offset + RG_RF09_CMD,
					RF_SLEEP);
#else
			trx_reg_write(reg_offset + RG_RF09_CMD, RF_SLEEP);
#endif
			TAL_RF_IRQ_CLR_ALL(trx_id);
		}

		/* Clean TAL and removed any pending tasks */
		cleanup_tal(trx_id);

		/* Configure the transceiver register values. */
		trx_config(trx_id);

		if (set_default_pib) {
			/* Set the default PIB values */
			init_tal_pib(trx_id); /* see 'tal_pib.c' */
			calculate_pib_values(trx_id);
		} else {
			/* nothing to do - the current TAL PIB attribute values
			 *are used */
		}

		write_all_tal_pib_to_trx(trx_id); /* see 'tal_pib.c' */
		config_phy(trx_id);

		/* Reset TAL variables. */
		tal_state[trx_id] = TAL_IDLE;
		tx_state[trx_id] = TX_IDLE;
#ifdef ENABLE_FTN_PLL_CALIBRATION
		/* Stop FTN timer */
		stop_ftn_timer(trx_id);
#endif  /* ENABLE_FTN_PLL_CALIBRATION */
	}

	/*
	 * Configure interrupt handling.
	 * Install a handler for the transceiver interrupt.
	 */
#ifdef IQ_RADIO
	trx_irq_init(RF215_BB, bb_irq_handler_cb);
	trx_irq_init(RF215_RF, rf_irq_handler_cb);
	pal_trx_irq_en(RF215_BB); /* Enable transceiver main interrupt. */
	pal_trx_irq_en(RF215_RF); /* Enable transceiver main interrupt. */
#else
	trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
	pal_trx_irq_en(); /* Enable transceiver main interrupt. */
#endif

	return MAC_SUCCESS;
}
Exemple #13
0
/**
 * @brief Configures the transceiver
 *
 * This function is called to configure a certain transceiver (RF09 or RF24)
 * after trx sleep or reset or power on.
 *
 * @param trx_id Transceiver identifier
 */
void trx_config(trx_id_t trx_id)
{
	uint16_t reg_offset = RF_BASE_ADDR_OFFSET * trx_id;

#ifdef IQ_RADIO
	/* LVDS interface */
	/* RF part: RF enable, BB disabled, IQIF enabled */
	pal_dev_bit_write(RF215_RF, SR_RF_IQIFC1_CHPM, 0x01);
	/* BB part: RF disable, BB enabled, IQIF enabled */
	pal_dev_bit_write(RF215_BB, SR_RF_IQIFC1_CHPM, 0x03);
	/* Clock Phase I/Q IF Driver at BB */
	pal_dev_bit_write(RF215_BB, SR_RF_IQIFC2_CPHADRV, 0);
	/* Clock Phase I/Q IF Receiver at BB */
	pal_dev_bit_write(RF215_BB, SR_RF_IQIFC2_CPHAREC, 1);
	/* Enable embedded control at RF */
	pal_dev_bit_write(RF215_RF, SR_RF_IQIFC0_EEC, 1);
#if (BOARD_TYPE == EVAL215_FPGA)
	pal_dev_bit_write(RF215_RF, SR_RF_IQIFC0_CMV1V2, 1);
	uint8_t temp = pal_dev_bit_write(RF215_BB, RG_RF_IQIFC1);
	temp = (temp & 0xF3) | (1 << 2); /* SKEWREC = 0ns */
	pal_dev_reg_write(RF215_BB, RG_RF_IQIFC1, temp);
#endif
	/* Configure BB */
	/* Setup IRQ mask: in chip mode, the baseband controls the RF's AGC */
	pal_dev_reg_write(RF215_BB, reg_offset + RG_BBC0_IRQM, BB_IRQ_ALL_IRQ);
	pal_dev_reg_write(RF215_BB, reg_offset + RG_RF09_IRQM, RF_IRQ_ALL_IRQ);
	/* Configure RF */
	pal_dev_reg_write(RF215_RF, reg_offset + RG_BBC0_IRQM, BB_IRQ_ALL_IRQ);
	pal_dev_reg_write(RF215_RF, reg_offset + RG_RF09_IRQM, RF_IRQ_ALL_IRQ);
#else
	/* Configure BB */
	/* Setup IRQ mask */
	trx_reg_write(reg_offset + RG_BBC0_IRQM, TAL_DEFAULT_BB_IRQ_MASK);
	/* Configure RF */
	trx_reg_write(reg_offset + RG_RF09_IRQM, TAL_DEFAULT_RF_IRQ_MASK);
#endif

#if (defined IQ_RADIO) && (BOARD_TYPE == EVAL215_FPGA)
	/* Set clip detector OFF */
	uint8_t agcc = pal_dev_reg_read(RF215_RF, reg_offset + RG_RF09_AGCC);
	agcc |= 0x80;
	pal_dev_reg_write(RF215_RF, reg_offset + RG_RF09_AGCC, agcc);
#endif

	/* Enable frame filter */
	trx_bit_write(reg_offset + SR_BBC0_AFC0_AFEN0, 1);

#ifndef BASIC_MODE
#if (defined MEASURE_TIME_OF_FLIGHT) && (!defined IQ_RADIO)
	/* Enable automatic time of flight measurement */
	/* bit 3 CAPRXS, bit 2 RSTTXS, bit 0 EN */
	uint8_t cnt_cfg = 1 << 0 | 1 << 2 | 1 << 3;
	trx_reg_write(reg_offset + RG_BBC0_CNTC, cnt_cfg);
#endif /* #if (defined MEASURE_TIME_OF_FLIGHT) && (!defined IQ_RADIO) */
#else /* BASIC_MODE */
	/* Enable counter for ACK timing: EN | RSTRXS */
	uint8_t cntc = 0x01 | 0x02;
	trx_reg_write(reg_offset + RG_BBC0_CNTC, cntc);
#endif

#ifndef USE_TXPREP_DURING_BACKOFF
	/* Keep analog voltage regulator on during TRXOFF */
#ifdef IQ_RADIO
	pal_dev_bit_write(RF215_RF, reg_offset + SR_RF09_AUXS_AVEN, 1);
#else
	trx_bit_write(reg_offset + SR_RF09_AUXS_AVEN, 1);
#endif /* #ifdef IQ_RADIO */
#endif

#ifndef BASIC_MODE
	/* Enable AACK */
	trx_reg_write(reg_offset + RG_BBC0_AMCS, AMCS_AACK_MASK);
	/* Set data pending for ACK frames to 1 for all address units */
	trx_reg_write(reg_offset + RG_BBC0_AMAACKPD, 0x0F);
#endif

#ifdef SUPPORT_MODE_SWITCH
	/* Use raw mode for mode switch PPDU in the not-inverted manner */
	trx_bit_write(reg_offset + SR_BBC0_FSKC4_RAWRBIT, 0);
#endif

	/* Workaround for errata reference #4623 */
	if (trx_id == RF09) {
#ifdef IQ_MODE
		pal_dev_reg_write(RF215_RF, 0x129, 0x04);
#else
		trx_reg_write(0x129, 0x04);
#endif
	}
}
Exemple #14
0
/*
 * \brief Write all shadow PIB variables to the transceiver
 *
 * This function writes all shadow PIB variables to the transceiver.
 * It is assumed that the radio does not sleep.
 */
void write_all_tal_pib_to_trx(void)
{
    uint8_t *ptr_to_reg;

    ptr_to_reg = (uint8_t *)&tal_pib.PANId;
    for (uint8_t i = 0; i < 2; i++) {
        trx_reg_write((RG_PAN_ID_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    ptr_to_reg = (uint8_t *)&tal_pib.IeeeAddress;
    for (uint8_t i = 0; i < 8; i++) {
        trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    ptr_to_reg = (uint8_t *)&tal_pib.ShortAddress;
    for (uint8_t i = 0; i < 2; i++) {
        trx_reg_write((RG_SHORT_ADDR_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    /* Configure TX_ARET; CSMA and CCA */
    trx_bit_write(SR_CCA_MODE, tal_pib.CCAMode);

#ifdef SW_CONTROLLED_CSMA

    /*
     * If receiver is enabled during backoff periods,
     * CSMA and frame re-transmissions are handled by software.
     * Setup trx for immediate transmission.
     */
    trx_bit_write(SR_MAX_FRAME_RETRIES, 0);
    trx_bit_write(SR_MAX_CSMA_RETRIES, 7);
#else
    trx_bit_write(SR_MIN_BE, tal_pib.MinBE);
    trx_bit_write(SR_MAX_BE, tal_pib.MaxBE);
#endif

    trx_bit_write(SR_AACK_I_AM_COORD, tal_pib.PrivatePanCoordinator);

    /* set phy parameter */

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

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

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

#ifdef PROMISCUOUS_MODE
    if (tal_pib.PromiscuousMode) {
        set_trx_state(CMD_RX_ON);
    }
#endif
}
Exemple #15
0
/**
 * \brief      Init the radio
 * \return     Returns success/fail
 * \retval 0   Success
 */
int rf233_init(void) {
  volatile uint8_t regtemp;
  volatile uint8_t radio_state;  /* don't optimize this away, it's important */
  PRINTF("RF233: init.\n");

  /* init SPI and GPIOs, wake up from sleep/power up. */

  spi_init();
  // RF233 expects line low for CS, this is default SAM4L behavior
  //spi_set_chip_select(3);
  // POL = 0 means idle is low
  spi_set_chip_select(3);
  spi_set_polarity(0);
  // PHASE = 0 means sample leading edge
  spi_set_phase(0);
  spi_set_rate(400000);

    /* reset will put us into TRX_OFF state */
  /* reset the radio core */
  gpio_enable_output(RST_PIN);
  gpio_enable_output(SLP_PIN);
  gpio_clear(RST_PIN);
  delay_ms(1);
  gpio_set(RST_PIN);
  gpio_clear(SLP_PIN); /* be awake from sleep*/

  
  /* Read the PART_NUM register to verify that the radio is
   * working/responding. Could check in software, I just look at
   * the bus. If this is working, the first write should be 0x9C x00
   * and the return bytes should be 0x00 0x0B. - pal*/
  regtemp = trx_reg_read(RF233_REG_PART_NUM);

  /* before enabling interrupts, make sure we have cleared IRQ status */
  regtemp = trx_reg_read(RF233_REG_IRQ_STATUS);
  PRINTF("RF233: After wake from sleep\n");
  radio_state = rf233_status();
  PRINTF("RF233: Radio state 0x%04x\n", radio_state);
  calibrate_filters();
  if (radio_state == STATE_P_ON) {
    trx_reg_write(RF233_REG_TRX_STATE, TRXCMD_TRX_OFF);
  } 
  /* Assign regtemp to regtemp to avoid compiler warnings */
  regtemp = regtemp;
  // Set up interrupts
  gpio_interrupt_callback(interrupt_callback, NULL);
  gpio_enable_input(RADIO_IRQ, PullNone);
  gpio_clear(RADIO_IRQ);
  gpio_enable_interrupt(RADIO_IRQ, PullNone, RisingEdge);

  /* Configure the radio using the default values except these. */
  trx_reg_write(RF233_REG_TRX_CTRL_1,      RF233_REG_TRX_CTRL_1_CONF);
  trx_reg_write(RF233_REG_PHY_CC_CCA,      RF233_REG_PHY_CC_CCA_CONF);
  trx_reg_write(RF233_REG_PHY_TX_PWR, RF233_REG_PHY_TX_PWR_CONF);
  trx_reg_write(RF233_REG_TRX_CTRL_2,      RF233_REG_TRX_CTRL_2_CONF);
  trx_reg_write(RF233_REG_IRQ_MASK,        RF233_REG_IRQ_MASK_CONF);
  trx_reg_write(RF233_REG_XAH_CTRL_1,      0x02);
  trx_bit_write(SR_MAX_FRAME_RETRIES, 0);
  trx_bit_write(SR_MAX_CSMA_RETRIES, 0);
  PRINTF("RF233: Configured transciever.\n");
  {
    uint8_t addr[8];
    addr[0] = 0x22;
    addr[1] = 0x22;
    addr[2] = 0x22;
    addr[3] = 0x22;
    addr[4] = 0x22;
    addr[5] = 0x22;
    addr[6] = 0x22;
    addr[7] = 0x22;
    SetPanId(IEEE802154_CONF_PANID);
    
    SetIEEEAddr(addr);
    SetShortAddr(0x2222);
  }
  rf_generate_random_seed();
  
  for (uint8_t i = 0; i < 8; i++)   {
    regtemp = trx_reg_read(0x24 + i);
  }

  /* 11_09_rel */
  trx_reg_write(RF233_REG_TRX_RPC, 0xFF); /* Enable RPC feature by default */
  PRINTF("RF233: Installed addresses. Turning on radio.");
  rf233_on();
  return 0;
}
Exemple #16
0
/**
 * @brief Starts continuous transmission on current channel
 *
 * @param trx_id Identifier of the transceiver
 * @param tx_mode Transmission mode
 */
void tfa_continuous_tx_start(trx_id_t trx_id, continuous_tx_mode_t tx_mode)
{
	uint16_t len;

	if (tal_state[trx_id] != TAL_IDLE) {
		return;
	}

#ifdef IQ_RADIO
	if (trx_id == RF09) {
		/* Check if the other radio is currently in use */
		if (trx_state[RF24] == RF_TX) {
			return;
		} else {
			/* Select corresponding baseband core */
			pal_dev_bit_write(RF215_BB, SR_RF_IQIFC2_CSELTX, RF09); /*
			                                                         * RF09
			                                                         * is
			                                                         * selected */
		}
	} else {
		/* Check if the other radio is currently in use */
		if (trx_state[RF09] == RF_TX) {
			return;
		} else {
			/* Select corresponding baseband core */
			pal_dev_bit_write(RF215_BB, SR_RF_IQIFC2_CSELTX, RF24); /*
			                                                         * RF24
			                                                         * is
			                                                         * selected */
		}
	}

#endif

	if (trx_state[trx_id] == RF_RX) {
		tal_state[trx_id] = TAL_TFA_CW_RX;
	} else {
		tal_state[trx_id] = TAL_TFA_CW;
	}

	/* Set to TxPREP state */
	switch_to_txprep(trx_id);

	uint16_t reg_offset = RF_BASE_ADDR_OFFSET * trx_id;

	if (tx_mode == CW_MODE) {
#ifdef IQ_RADIO
		/* Disable embedded TX control */
		pal_dev_bit_write(RF215_RF, SR_RF_IQIFC0_EEC, 0);
#else
		/* Enable baseband bypass */
		trx_bit_write(SR_RF_IQIFC1_CHPM, 1);
#endif

		/* Configure DAC to generate carrier signal */
		uint8_t dac_config[2] = {(0x7E | 0x80), (0x3F | 0x80)};
#ifdef IQ_RADIO
		pal_dev_write(RF215_RF, reg_offset + RG_RF09_TXDACI, dac_config,
				2);
#else
		trx_write(reg_offset + RG_RF09_TXDACI, dac_config, 2);
#endif

		/* Trigger Tx start */
#ifdef IQ_RADIO
		pal_dev_reg_write(RF215_RF, reg_offset + RG_RF09_CMD, RF_TX);
#else
		trx_reg_write(reg_offset + RG_RF09_CMD, RF_TX);
#endif
		trx_state[trx_id] = RF_TX;
	} else { /* PRBS mode */
		/* Enable continuous transmission mode */
		trx_bit_write(reg_offset + SR_BBC0_PC_CTX, 1);

		/* Fill length field */
#ifdef SUPPORT_LEGACY_OQPSK
		if (tal_pib[trx_id].phy.modulation == LEG_OQPSK) {
			len = 127;
		} else
#endif
		{
			len = 2047;
		}

		trx_write(reg_offset + RG_BBC0_TXFLL, (uint8_t *)&len, 2);
		trx_reg_write(reg_offset + RG_RF09_CMD, RF_TX);
		trx_state[trx_id] = RF_TX;

		/* Fill frame buffer */
		uint16_t tx_frm_buf_offset = BB_TX_FRM_BUF_OFFSET * trx_id;
		uint8_t data[10];
		for (uint16_t k = 0; k < (len / 10); k++) {
			for (uint16_t i = 0; i < 10; i++) {
				data[i] = (uint8_t)rand();
			}
			trx_write(tx_frm_buf_offset + RG_BBC0_FBTXS, data, 10);
			tx_frm_buf_offset += 10;
		}
		uint16_t remaining_bytes = len % 10;
		for (uint16_t i = 0; i < remaining_bytes; i++) {
			data[i] = (uint8_t)rand();
		}
		trx_write(tx_frm_buf_offset + RG_BBC0_FBTXS, data,
				remaining_bytes);
	}
}
Exemple #17
0
void SetPanId(uint16_t panId) {
  uint8_t *d = (uint8_t *)&panId;
  
  trx_reg_write(0x22, d[0]);
  trx_reg_write(0x23, d[1]);
}
Exemple #18
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_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 */

			trx_bit_write(SR_MIN_BE, tal_pib.MinBE);
			break;

		case macPANId:
			tal_pib.PANId = value->pib_value_16bit;
			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));
			break;

		case macShortAddress:
			tal_pib.ShortAddress = value->pib_value_16bit;
			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));
			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;
				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 */
			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);
			trx_bit_write(SR_TX_PWR, reg_value);
		}
		break;

		case phyCCAMode:
			tal_pib.CCAMode = value->pib_value_8bit;
			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++) {
				trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr);
				ptr++;
			}
		}
		break;

		case mac_i_pan_coordinator:
			tal_pib.PrivatePanCoordinator = value->pib_value_bool;
			trx_bit_write(SR_AACK_I_AM_COORD,
					tal_pib.PrivatePanCoordinator);
			break;

		case macAckWaitDuration:

			/*
			 * ATmegaRFA2 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() */
Exemple #19
0
/**
 * \brief      prepare a frame and the radio for immediate transmission 
 * \param payload         Pointer to data to copy/send
 * \param payload_len     length of data to copy
 * \return     Returns success/fail, refer to radio.h for explanation
 */
static int
rf212_prepare(const void *payload, unsigned short payload_len)
{
#if DEBUG_PRINTDATA
  int i;
#endif  /* DEBUG_PRINTDATA */
  uint8_t templen;
  uint8_t radio_status;
  uint8_t data[130];

#if USE_HW_FCS_CHECK
  /* Add length of the FCS (2 bytes) */
  templen = payload_len + 2;
#else   /* USE_HW_FCS_CHECK */
  /* FCS is assumed to already be included in the payload */
  templen = payload_len;
#endif  /* USE_HW_FCS_CHECK */
data[0] = templen;
memcpy(&data[1],payload,templen);
#if DEBUG_PRINTDATA
  PRINTF("RF212 prepare (%u/%u): 0x", payload_len, templen);
  for(i = 0; i < templen; i++) {
    PRINTF("%02x", *(uint8_t *)(payload + i));
  }
  PRINTF("\n");
#endif  /* DEBUG_PRINTDATA */

  PRINTF("RF212: prepare %u\n", payload_len);
  if(payload_len > MAX_PACKET_LEN) {
    PRINTF("RF212: error, frame too large to tx\n");
    return RADIO_TX_ERR;
  }

  /* check that the FIFO is clear to access */
  radio_status = rf212_status();
  #if NULLRDC_CONF_802154_AUTOACK_HW
  if(radio_status == STATE_BUSY_RX_AACK || radio_status == STATE_BUSY_TX_ARET) {
	  PRINTF("RF212B: TRX buffer unavailable: prep when %s\n", radio_status == STATE_BUSY_RX_AACK ? "rx" : "tx");
  #else
   if(radio_status == STATE_BUSY_RX || radio_status == STATE_BUSY_TX) {
	   PRINTF("RF212B: TRX buffer unavailable: prep when %s\n", radio_status == STATE_BUSY_RX? "rx" : "tx");
  #endif
    return RADIO_TX_ERR;
  }

  /* Write packet to TX FIFO. */
  PRINTF("RF212 len = %u\n", payload_len);
  trx_frame_write((uint8_t *)data, templen+1);
  return RADIO_TX_OK;
}
/*---------------------------------------------------------------------------*/
/**
 * \brief      Transmit a frame already put in the radio with 'prepare'
 * \param payload_len    Length of the frame to send
 * \return     Returns success/fail, refer to radio.h for explanation
 */
static int
rf212_transmit(unsigned short payload_len)
{
  uint8_t status_now;//,temp;
  PRINTF("RF212: tx %u\n", payload_len);

  /* prepare for TX */
  status_now = rf212_status();
  #if NULLRDC_CONF_802154_AUTOACK_HW
  if(status_now == STATE_BUSY_RX_AACK || status_now == STATE_BUSY_TX_ARET) {
  #else
  if(status_now == STATE_BUSY_RX || status_now == STATE_BUSY_TX) {
  #endif
    PRINTF("RF212: collision, was receiving\n");
    /* NOTE: to avoid loops */
    return RADIO_TX_ERR;
    // return RADIO_TX_COLLISION;
  }
  if(status_now != STATE_PLL_ON) {
    /* prepare for going to state TX, should take max 80 us */
    //RF212_COMMAND(TRXCMD_PLL_ON);
	trx_reg_write(RF212_REG_TRX_STATE,0x09);
	do 
   {
	   status_now = trx_bit_read(0x01, 0x1F, 0);
   } while (status_now == 0x1f);
    //BUSYWAIT_UNTIL(RF212_STATUS() == STATE_PLL_ON, 1 * RTIMER_SECOND/1000);
  }

  if(rf212_status() != STATE_PLL_ON) {
    /* failed moving into PLL_ON state, gracefully try to recover */
    PRINTF("RF212: failed going to PLLON\n");
    RF212_COMMAND(TRXCMD_PLL_ON);   /* try again */
    if(rf212_status() != STATE_PLL_ON) {
      /* give up and signal big fail (should perhaps reset radio core instead?) */
      PRINTF("RF212: graceful recovery (in tx) failed, giving up. State: 0x%02X\n", RF212_STATUS());
      return RADIO_TX_ERR;
    }
  }

  /* perform transmission */
  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
#if NULLRDC_CONF_802154_AUTOACK_HW
  RF212_COMMAND(TRXCMD_TX_ARET_ON);
#endif  
  RF212_COMMAND(TRXCMD_TX_START);
  flag_transmit=1;

#if !NULLRDC_CONF_802154_AUTOACK_HW  
  BUSYWAIT_UNTIL(RF212_STATUS() == STATE_BUSY_TX, RTIMER_SECOND/2000);
  BUSYWAIT_UNTIL(RF212_STATUS() != STATE_BUSY_TX, 10 * RTIMER_SECOND/1000);
  #if (DATA_RATE==BPSK_20||BPSK_40||OQPSK_SIN_RC_100)
  BUSYWAIT_UNTIL(RF212_STATUS() != STATE_BUSY_TX, 10 * RTIMER_SECOND/1000);
  BUSYWAIT_UNTIL(RF212_STATUS() != STATE_BUSY_TX, 10 * RTIMER_SECOND/1000);
  BUSYWAIT_UNTIL(RF212_STATUS() != STATE_BUSY_TX, 10 * RTIMER_SECOND/1000);
  #endif
#endif  
  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
#if !NULLRDC_CONF_802154_AUTOACK_HW  
  if(RF212_STATUS() != STATE_PLL_ON) {
    /* something has failed */
    printf("RF212: radio fatal err after tx\n");
    radiocore_hard_recovery();
	return RADIO_TX_ERR;
  }
 // printf("#RTIMER_SECOND");
  RF212_COMMAND(TRXCMD_RX_ON);
#else
	BUSYWAIT_UNTIL(ack_status == 1, 10 * RTIMER_SECOND/1000);
	if((ack_status))
	{
	//	printf("\r\nrf233 sent\r\n ");
		ack_status=0;
	//	printf("\nACK received");
		return RADIO_TX_OK;
	}
	else
	{
	//	printf("\nNOACK received");		
		return RADIO_TX_NOACK;
	}
	
#endif  

 PRINTF("RF212: tx ok\n");
  return RADIO_TX_OK;
}
void
goto_sleep(void)
{
	port_pin_set_output_level(AT86RFX_SLP_PIN, true);
}
Exemple #20
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. */
		if (CMD_SLEEP == trx_cmd) {
			return TRX_SLEEP;
		}

		tal_awake_end_flag = false;
		/* Set callback function for the awake interrupt. */
		trx_irq_init((FUNC_PTR)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. */
		TRX_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 */
		trx_reg_read(RG_IRQ_STATUS);
		/* Re-install default IRQ handler for main interrupt. */
		trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
		/* Re-enable TRX_END interrupt */
		trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);
#if (ANTENNA_DIVERSITY == 1)
		/* Enable antenna diversity. */
		trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_ENABLE);
#endif

#ifdef EXT_RF_FRONT_END_CTRL
		/* Enable RF front end control */
		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) {
		if (CMD_DEEP_SLEEP == trx_cmd) {
			return TRX_DEEP_SLEEP;
		}

		/* Leave trx sleep mode. */
		TRX_SLP_TR_LOW();
		/* Check if trx has left deep sleep. */
		tal_trx_status_t trx_state;
		do {
			trx_state = 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
		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.
		 */
		trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_DISABLE);
#endif
#ifdef EXT_RF_FRONT_END_CTRL
		/* Disable RF front end control */
		trx_bit_write(SR_PA_EXT_EN, 0);
#endif
		/* Clear existing interrupts */
		trx_reg_read(RG_IRQ_STATUS);

		/*
		 * Enable Awake_end interrupt.
		 * This is used for save wake-up from sleep later.
		 */
		trx_bit_write(SR_IRQ_MASK, TRX_IRQ_4_CCA_ED_DONE);

#ifdef ENABLE_DEEP_SLEEP
		if (trx_cmd == CMD_DEEP_SLEEP) {
			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.
			 */
			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.
		 */
		trx_bit_write(SR_IRQ_MASK, TRX_IRQ_4_CCA_ED_DONE);
		tal_trx_status = TRX_SLEEP;
#endif
		PAL_WAIT_1_US();
		TRX_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:
			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:
			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:
			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:
			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:
			trx_reg_write(RG_TRX_STATE, CMD_RX_ON);
			PAL_WAIT_1_US();
			break;

		case TRX_OFF:
			switch_pll_on();
			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:
			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
			                  **/
			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:
			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
			                  **/
			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) */ trx_bit_read(
				SR_TRX_STATUS);
	} while (tal_trx_status == STATE_TRANSITION_IN_PROGRESS);

	return tal_trx_status;
} /* set_trx_state() */
Exemple #21
0
void SetShortAddr(uint16_t addr)
{
	uint8_t *d = (uint8_t *)&addr;
	trx_reg_write(0x20, d[0]);
	trx_reg_write(0x21, d[1]);
}
Exemple #22
0
/**
 * \brief Configures the transceiver
 *
 * This function is called to configure the transceiver after reset.
 */
static void trx_config(void)
{
	/* Set pin driver strength */
	trx_bit_write(SR_PAD_IO_CLKM, PAD_CLKM_2_MA);
	trx_bit_write(SR_CLKM_SHA_SEL, CLKM_SHA_DISABLE);
	trx_bit_write(SR_CLKM_CTRL, CLKM_1MHZ);

#ifndef SW_CONTROLLED_CSMA

	/* 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();
	trx_reg_write(RG_CSMA_SEED_0, (uint8_t)rand_value);
	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();
#endif

	trx_bit_write(SR_AACK_SET_PD, PD_ACK_BIT_SET_ENABLE); /* ACKs for
	                                                       * data
	                                                       * requests,
	                                                       * indicate
	                                                       * pending data
	                                                       **/
	trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE); /* Enable
	                                                      * buffer
	                                                      * protection
	                                                      * mode */
	trx_bit_write(SR_IRQ_MASK_MODE, IRQ_MASK_MODE_ON); /* Enable poll
	                                                    * mode */
	trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT); /* The TRX_END
	                                              * interrupt of the
	                                              * transceiver is
	                                              * enabled. */

#if (ANTENNA_DIVERSITY == 1)
	/* Use antenna diversity */
	trx_bit_write(SR_ANT_CTRL, ANTENNA_DEFAULT);
	trx_bit_write(SR_PDT_THRES, THRES_ANT_DIV_ENABLE);
	trx_bit_write(SR_ANT_DIV_EN, ANT_DIV_ENABLE);
	trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_ENABLE);
#elif (DISABLE_TSTAMP_IRQ == 0)
#if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)

	/*
	 * Use timestamping.
	 * The timestamping is only required for beaconing networks
	 * or if timestamping is explicitly enabled.
	 */
	trx_bit_write(SR_IRQ_2_EXT_EN, TIMESTAMPING_ENABLE); /* Enable
	                                                      * timestamping
	                                                      * output
	                                                      * signal. */
#endif  /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */
#endif

#ifdef CCA_ED_THRESHOLD

	/*
	 * Set CCA ED Threshold to other value than standard register due to
	 * board specific loss (see pal_config.h). */
	trx_bit_write(SR_CCA_ED_THRES, CCA_ED_THRESHOLD);
#endif

#ifdef EXT_RF_FRONT_END_CTRL
	/* Enable RF front end control */
	trx_bit_write(SR_PA_EXT_EN, PA_EXT_ENABLE);
#endif
}
Exemple #23
0
/**
 * @brief Read Energy Detection Level Now
 *
 * forces a reading of the ED level
 *
 * range is between -90 and -6 dBm
 * where -6 is the best
 *
 * @return ED level
 */
int8_t cMxRadio::getEdNow()
{
	trx_reg_write(RG_PHY_ED_LEVEL, 0); // forces a reading

	return getLastEd();
}
Exemple #24
0
/**
 * \brief      prepare a frame and the radio for immediate transmission 
 * \param payload         Pointer to data to copy/send
 * \param payload_len     length of data to copy
 * \return     Returns success/fail, refer to radio.h for explanation
 */
int
rf233_prepare(const void *payload, unsigned short payload_len)
{
#if DEBUG_PRINTDATA
  int i;
#endif  /* DEBUG_PRINTDATA */
  uint8_t templen;
  uint8_t radio_status;
  uint8_t data[130];

#if USE_HW_FCS_CHECK
  /* Add length of the FCS (2 bytes) */
  templen = payload_len + 2;
#else   /* USE_HW_FCS_CHECK */
  /* FCS is assumed to already be included in the payload */
  templen = payload_len;
#endif  /* USE_HW_FCS_CHECK */
 //data = templen;
 
/*
for(i = 0; i < templen; i++) {
	data++;
	data =(uint8_t *)(payload + i);
	
}*/
//memcpy(data,&templen,1);
data[0] = templen;
memcpy(&data[1],payload,templen);
//data--;
#if DEBUG_PRINTDATA
  PRINTF("RF233 prepare (%u/%u): 0x", payload_len, templen);
  for(i = 0; i < templen; i++) {
    PRINTF("%02x", *(uint8_t *)(payload + i));
  }
  PRINTF("\r\n");
#endif  /* DEBUG_PRINTDATA */
   
  PRINTF("RF233: prepare %u\r\n", payload_len);
  if(payload_len > MAX_PACKET_LEN) {
    PRINTF("RF233: error, frame too large to tx\r\n");
    return RADIO_TX_ERR;
  }

  /* check that the FIFO is clear to access */
  radio_status=rf233_status();
  #if NULLRDC_CONF_802154_AUTOACK_HW
  if(radio_status == STATE_BUSY_RX_AACK || radio_status == STATE_BUSY_TX_ARET) {
	  PRINTF("RF233: TRX buffer unavailable: prep when %s\r\n", radio_status == STATE_BUSY_RX_AACK ? "rx" : "tx");
  #else
   if(radio_status == STATE_BUSY_RX || radio_status == STATE_BUSY_TX) {
	   PRINTF("RF233: TRX buffer unavailable: prep when %s\r\n", radio_status == STATE_BUSY_RX? "rx" : "tx");
  #endif
    
    return RADIO_TX_ERR;
  }

  /* Write packet to TX FIFO. */
  PRINTF("RF233 len = %u\r\n", payload_len);
  trx_frame_write((uint8_t *)data, templen+1);
  return RADIO_TX_OK;
}
/*---------------------------------------------------------------------------*/
/**
 * \brief      Transmit a frame already put in the radio with 'prepare'
 * \param payload_len    Length of the frame to send
 * \return     Returns success/fail, refer to radio.h for explanation
 */
int
rf233_transmit(unsigned short payload_len)
{
  static uint8_t status_now;
  PRINTF("RF233: tx %u\r\n", payload_len);

  /* prepare for TX */
  
  status_now = rf233_status();
   //status_now = trx_reg_read(RF233_REG_TRX_RPC);
  #if NULLRDC_CONF_802154_AUTOACK_HW
  if(status_now == STATE_BUSY_RX_AACK || status_now == STATE_BUSY_TX_ARET) {
  #else
  if(status_now == STATE_BUSY_RX || status_now == STATE_BUSY_TX) {
  #endif
    PRINTF("RF233: collision, was receiving 0x%02X\r\n",status_now);
    /* NOTE: to avoid loops */
    return RADIO_TX_ERR;;
    // return RADIO_TX_COLLISION;
  }
  if(status_now != STATE_PLL_ON) {
    /* prepare for going to state TX, should take max 80 us */
    //RF233_COMMAND(TRXCMD_PLL_ON);
	trx_reg_write(RF233_REG_TRX_STATE,0x09);
   // BUSYWAIT_UNTIL(trx_reg_read(RF233_REG_TRX_STATUS) == STATE_PLL_ON, 1 * RTIMER_SECOND/1000);
   //delay_ms(10);
   //status_now = trx_reg_read(RF233_REG_TRX_STATE);
   do 
   {
	   status_now = trx_bit_read(0x01, 0x1F, 0);
   } while (status_now == 0x1f);
  }

  if(rf233_status() != STATE_PLL_ON) {
    /* failed moving into PLL_ON state, gracefully try to recover */
    PRINTF("RF233: failed going to PLLON\r\n");
    RF233_COMMAND(TRXCMD_PLL_ON);   /* try again */
	static uint8_t state;
	state = rf233_status();
    if(state != STATE_PLL_ON) {
      /* give up and signal big fail (should perhaps reset radio core instead?) */
      PRINTF("RF233: graceful recovery (in tx) failed, giving up. State: 0x%02X\r\n", rf233_status());
      return RADIO_TX_ERR;
    }
  }

  /* perform transmission */
  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
#if NULLRDC_CONF_802154_AUTOACK_HW
  RF233_COMMAND(TRXCMD_TX_ARET_ON);
#endif
  RF233_COMMAND(TRXCMD_TX_START);
   flag_transmit=1;
   //delay_ms(5);
  //printf("RTIMER value %d",RTIMER_NOW());

#if !NULLRDC_CONF_802154_AUTOACK_HW
    BUSYWAIT_UNTIL(rf233_status() == STATE_BUSY_TX, RTIMER_SECOND/2000);
   // printf("RTIMER value1 %d",RTIMER_NOW());
   // printf("\r\nSTATE_BUSY_TX");
  BUSYWAIT_UNTIL(rf233_status() != STATE_BUSY_TX, 10 * RTIMER_SECOND/1000);
  // printf("RTIMER value2 %d",RTIMER_NOW());
#endif

  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
  ENERGEST_ON(ENERGEST_TYPE_LISTEN);

#if !NULLRDC_CONF_802154_AUTOACK_HW
   if(rf233_status() != STATE_PLL_ON) {
    // something has failed 
    PRINTF("RF233: radio fatal err after tx\r\n");
    radiocore_hard_recovery();
    return RADIO_TX_ERR;
  }
  RF233_COMMAND(TRXCMD_RX_ON);
#else
	BUSYWAIT_UNTIL(ack_status == 1, 10 * RTIMER_SECOND/1000);
	if((ack_status))
	{
	//	printf("\r\nrf233 sent\r\n ");
		ack_status=0;
	//	printf("\nACK received");
		return RADIO_TX_OK;
	}
	else
	{
	//	printf("\nNOACK received");		
		return RADIO_TX_NOACK;
	}
	
#endif

  PRINTF("RF233: tx ok\r\n");
  return RADIO_TX_OK;
}
/*---------------------------------------------------------------------------*/
/**
 * \brief      Send data: first prepares, then transmits
 * \param payload         Pointer to data to copy/send
 * \param payload_len     length of data to copy
 * \return     Returns success/fail, refer to radio.h for explanation
 */
int
rf233_send(const void *payload, unsigned short payload_len)
{
  PRINTF("RF233: send %u\r\n", payload_len);
  if(rf233_prepare(payload, payload_len) == RADIO_TX_ERR) {
  return RADIO_TX_ERR;
  } 
  return rf233_transmit(payload_len);
}
/*---------------------------------------------------------------------------*/
/**
 * \brief      read a received frame out of the radio buffer 
 * \param buf         pointer to where to copy received data
 * \param bufsize     Maximum size we can copy into bufsize
 * \return     Returns length of data read (> 0) if successful
 * \retval -1  Failed, was transmitting so FIFO is invalid
 * \retval -2  Failed, rx timed out (stuck in rx?)
 * \retval -3  Failed, too large frame for buffer
 * \retval -4  Failed, CRC/FCS failed (if USE_HW_FCS_CHECK is true)
 */
int
rf233_read(void *buf, unsigned short bufsize)
{
//  uint8_t radio_state;
  uint8_t ed;       /* frame metadata */
  uint8_t frame_len = 0;
  uint8_t len = 0;
  int rssi;
#if DEBUG_PRINTDATA
  uint8_t tempreadlen;
#endif  /* DEBUG_PRINTDATA */

  if(pending_frame == 0) {
    return 0;
  }
  pending_frame = 0;

 /* / * check that data in FIFO is valid * /
  radio_state = RF233_STATUS();
  if(radio_state == STATE_BUSY_TX) {
    / * data is invalid, bail out * /
    PRINTF("RF233: read while in BUSY_TX ie invalid, dropping.\n");
    return -1;
  }
  if(radio_state == STATE_BUSY_RX) {
    / * still receiving - data is invalid, wait for it to finish * /
    PRINTF("RF233: read while BUSY_RX, waiting.\n");
    BUSYWAIT_UNTIL(RF233_STATUS() != STATE_BUSY_RX, 10 * RTIMER_SECOND/1000);
	if(RF233_STATUS() == STATE_BUSY_RX) {
      PRINTF("RF233: timed out, still BUSY_RX, dropping.\n");
      return -2;
    }
  }
*/

  /* get length of data in FIFO */
  trx_frame_read(&frame_len, 1);
#if DEBUG_PRINTDATA
  tempreadlen = frame_len;
#endif  /* DEBUG_PRINTDATA */
  if(frame_len == 1) {
    frame_len = 0;
  }

  len = frame_len;
#if USE_HW_FCS_CHECK
  /* FCS has already been stripped */
  len = frame_len - 2;
#endif  /* USE_HW_FCS_CHECK */

  if(frame_len == 0) {
    return 0;
  }
  if(len > bufsize) {
    /* too large frame for the buffer, drop */
    PRINTF("RF233: too large frame for buffer, dropping (%u > %u).\r\n", frame_len, bufsize);
    flush_buffer();
    return -3;
  }
  PRINTF("RF233 read %u B\r\n", frame_len);

  /* read out the data into the buffer, disregarding the length and metadata bytes */
  trx_sram_read(1,(uint8_t *)buf, len);
#if DEBUG_PRINTDATA
  {
    int k;
    PRINTF("RF233: Read frame (%u/%u): ", tempreadlen, frame_len);
    for(k = 0; k < frame_len; k++) {
      PRINTF("%02x", *((uint8_t *)buf + k));
    }
    PRINTF("\r\n");
  }
#endif  /* DEBUG_PRINTDATA */

  /* 
   * Energy level during reception, ranges from 0x00 to 0x53 (=83d) with a
   * resolution of 1dB and accuracy of +/- 5dB. 0xFF means invalid measurement.
   * 0x00 means <= RSSI(base_val), which is -91dBm (typ). See datasheet 12.7.
   * Ergo, real RSSI is (ed-91) dBm or less.
   */
  #define RSSI_OFFSET       (91)
  ed = trx_reg_read(RF233_REG_PHY_ED_LEVEL);
  rssi = (int) ed - RSSI_OFFSET;
  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
  flush_buffer();

/*
#if USE_HW_FCS_CHECK
  {
    uint8_t crc_ok;   / * frame metadata * /
    crc_ok = rf233_arch_read_reg(RF233_REG_PHY_RSSI) & PHY_RSSI_CRC_VALID;
    if(crc_ok == 0) {
      / * CRC/FCS fail, drop * /
      PRINTF("RF233: CRC/FCS fail, dropping.\n");
      flush_buffer();
      return -4;
    }
  }
#endif  / * USE_HW_FCS_CHECK * /*/

  return len;
}
Exemple #25
0
/**
 * \brief Initializes the transceiver
 *
 * This function is called to initialize the transceiver.
 *
 * \return MAC_SUCCESS  if the transceiver state is changed to TRX_OFF and the
 *                 current device part number and version number are correct;
 *         FAILURE otherwise
 */
static retval_t trx_init(void)
{
	tal_trx_status_t trx_status;
	uint8_t poll_counter = 0;

	/* Ensure control lines have correct levels. */
	TRX_RST_HIGH();
	TRX_SLP_TR_LOW();

	/* Wait typical time of timer TR1. */
	pal_timer_delay(P_ON_TO_CLKM_AVAILABLE_TYP_US);

#if !(defined FPGA_EMULATION)
	do {
		/* Apply reset pulse */
		TRX_RST_LOW();
		pal_timer_delay(RST_PULSE_WIDTH_US);
		TRX_RST_HIGH();

		/* Wait not more than max. value of TR1. */
		if (poll_counter == P_ON_TO_CLKM_ATTEMPTS) {
			return FAILURE;
		}

		/* Wait a short time interval. */
		pal_timer_delay(TRX_POLL_WAIT_TIME_US);
		poll_counter++;

		/* Check if AT86RF212 is connected; omit manufacturer id check
		**/
	} while (trx_reg_read(RG_PART_NUM) != PART_NUM_AT86RF212);
#endif  /* !defined FPGA_EMULATION */

	/* Ensure right CLKM value for external timer clock source, i.e. 1 MHz
	**/
	trx_bit_write(SR_CLKM_CTRL, CLKM_1MHZ);

	/* Set trx to off mode */
	trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);

	/* Verify that the trx has reached TRX_OFF. */
	poll_counter = 0;
	do {
		/* Wait a short time interval. */
		pal_timer_delay(TRX_POLL_WAIT_TIME_US);

		trx_status = (tal_trx_status_t)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)
			Assert(
					"MAX Attempts to switch to TRX_OFF state reached" ==
					0);
#endif
			return FAILURE;
		}

		poll_counter++;
	} while (trx_status != TRX_OFF);

	tal_trx_status = TRX_OFF;

	return MAC_SUCCESS;
}
void radio_set_param(radio_attribute_t attr, radio_param_t parm)
{
    switch (attr)
    {
        case phyCurrentChannel:
            if (((int)parm.channel >= TRX_MIN_CHANNEL) &&
                ((int)parm.channel <= TRX_MAX_CHANNEL))
            {
                trx_bit_write(SR_CHANNEL, parm.channel);
                radiostatus.channel = parm.channel;
            }
            else
            {
                radio_error(SET_PARM_FAILED);
            }
            break;

        case phyTransmitPower:
            if (parm.tx_pwr >= -17 && parm.tx_pwr <= 3)
            {
                /** @todo move this into a radio-specific header file */
                static const uint8_t pwrtable[] =
                {
                    0x0F, 0x0F, 0x0F, 0x0F, 0x0F, /* -17...-13 dBm */
                    0x0E, 0x0E, 0x0E,             /* -12...-10 dBm */
                    0x0D, 0x0D,                   /* -9...-8 dBm */
                    0x0C, 0x0C,                   /* -7...-6 dBm */
                    0x0B,                         /* -5 dBm */
                    0x0A,                         /* -4 dBm */
                    0x09,                         /* -3 dBm */
                    0x08,                         /* -2 dBm */
                    0x07,                         /* -1 dBm */
                    0x06,                         /* 0 dBm */
                    0x04,                         /* 1 dBm */
                    0x02,                         /* 2 dBm */
                    0x00                          /* 3 dBm */
                };
                radiostatus.tx_pwr = parm.tx_pwr;
                uint8_t idx = parm.tx_pwr + 17;
                uint8_t pwrval = pgm_read_byte(pwrtable[idx]);
                trx_bit_write(SR_TX_PWR, pwrval);
            }
            else
            {
                radio_error(SET_PARM_FAILED);
            }
            break;

        case phyCCAMode:
            if (parm.cca_mode <= 3)
            {
                radiostatus.cca_mode = parm.cca_mode;
                trx_bit_write(SR_CCA_MODE, radiostatus.cca_mode);
            }
            else
            {
                radio_error(SET_PARM_FAILED);
            }
            break;

        case phyIdleState:
            radiostatus.idle_state = parm.idle_state;
            radio_set_state(parm.idle_state);
            break;

        case phyChannelsSupported:
            break;

        case phyPanId:
            trx_set_panid(parm.pan_id);
            break;

        case phyShortAddr:
            trx_set_shortaddr(parm.short_addr);
            break;

        case phyLongAddr:
        {
            uint8_t regno, *ap;
            for (regno = RG_IEEE_ADDR_0, ap = (uint8_t *)parm.long_addr;
                 regno <= RG_IEEE_ADDR_7;
                 regno++, ap++)
                trx_reg_write(regno, *ap);
            break;
        }

        case phyDataRate:
            trx_set_datarate(parm.data_rate);
            break;

#ifdef TRX_TX_PA_EI
        case phyTxPa:
            radiostatus.tx_pa = parm.tx_pa;
            break;
#endif
#ifdef TRX_RX_LNA_EI
        case phyRxLna:
            radiostatus.rx_lna = parm.rx_lna;
            break;
#endif

        default:
            radio_error(SET_PARM_FAILED);
            break;
    }
}
Exemple #27
0
/*
 * \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();
}
Exemple #28
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. */
		if (CMD_SLEEP == trx_cmd) {
			return TRX_SLEEP;
		}

		tal_awake_end_flag = false;
		/* Set callback function for the awake interrupt. */
		pal_trx_irq_init_awake((FUNC_PTR)trx_awake_handler_cb);
		/* Save current state of global interrupts. */
		ENTER_CRITICAL_REGION();
		/* Force enabling of global interrupts. */
		ENABLE_GLOBAL_IRQ();
		/* Leave trx sleep mode. */
		TRX_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 */
		trx_reg_write(RG_IRQ_STATUS, 0xFF);
		/* Re-enable TRX_END interrupt */
		trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);

#if (ANTENNA_DIVERSITY == 1)
		/* Enable antenna diversity. */
		trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_ENABLE);
#endif

		if ((trx_cmd == CMD_TRX_OFF) ||
				(trx_cmd == CMD_FORCE_TRX_OFF)) {
			tal_trx_status = TRX_OFF;
			return TRX_OFF;
		}
	}

	switch (trx_cmd) { /* requested state */
	case CMD_SLEEP:
		trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
#if (ANTENNA_DIVERSITY == 1)
		/* Disable antenna diversity: sets pulls */
		trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_DISABLE);
#endif
		{
			uint16_t rand_value;

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

		/*
		 * Clear existing interrupts to have clear interrupt flags
		 * during wake-up.
		 */
		trx_reg_write(RG_IRQ_STATUS, 0xFF);

		/*
		 * Enable Awake_end interrupt.
		 * This is used for save wake-up from sleep later.
		 */
		trx_reg_write(RG_IRQ_MASK, TRX_IRQ_AWAKE_ONLY);

		PAL_WAIT_1_US();
		TRX_SLP_TR_HIGH();
		pal_timer_delay(TRX_OFF_TO_SLEEP_TIME_CLKM_CYCLES);
		tal_trx_status = TRX_SLEEP;
		return TRX_SLEEP; /* transceiver register cannot be read during
		                   *TRX_SLEEP */

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

		default:
			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:
			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:
			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:
			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:
			trx_reg_write(RG_TRX_STATE, CMD_RX_ON);
			PAL_WAIT_1_US();
			break;

		case TRX_OFF:
			switch_pll_on();
			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:
			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 */
			trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
			PAL_WAIT_1_US();
			break;

		case RX_ON:
			trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
			PAL_WAIT_1_US();
			/* check if state change could be applied */
			tal_trx_status = (tal_trx_status_t)trx_bit_read(
					SR_TRX_STATUS);
			if (tal_trx_status != PLL_ON) {
				return tal_trx_status;
			}

			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:
			trx_reg_write(RG_TRX_STATE, CMD_TX_ARET_ON);
			PAL_WAIT_1_US();
			break;

		case RX_ON:
		case RX_AACK_ON:
			trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
			PAL_WAIT_1_US();
			/* check if state change could be applied */
			tal_trx_status = (tal_trx_status_t)trx_bit_read(
					SR_TRX_STATUS);
			if (tal_trx_status != PLL_ON) {
				return tal_trx_status;
			}

			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 */
			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)trx_bit_read(SR_TRX_STATUS);
	} while (tal_trx_status == STATE_TRANSITION_IN_PROGRESS);

	return tal_trx_status;
} /* set_trx_state() */
Exemple #29
0
/**
 * @brief Starts the timer for the backoff period and enables receiver.
 *
 * @param trx_id Transceiver identifier
 */
static void start_backoff(trx_id_t trx_id)
{
	/* Start backoff timer to trigger CCA */
	uint8_t backoff_8;
	backoff_8  = (uint8_t)(rand() & (((uint16_t)1 << BE[trx_id]) - 1));
	if (backoff_8 > 0) {
		uint8_t timer_id;
		uint16_t backoff_16;
		uint32_t backoff_duration_us;
		backoff_16 = backoff_8 * aUnitBackoffPeriod;
		backoff_duration_us
			= (uint32_t)tal_pib[trx_id].SymbolDuration_us *
				(uint32_t)backoff_16;
#ifdef REDUCED_BACKOFF_DURATION
		backoff_duration_us = REDUCED_BACKOFF_DURATION;
#endif
		if (trx_id == RF09) {
			timer_id = TAL_T_0;
		} else {
			timer_id = TAL_T_1;
		}

		retval_t status
			= pal_timer_start(timer_id, backoff_duration_us,
				TIMEOUT_RELATIVE,
				(FUNC_PTR)cca_start,
				(void *)&timer_cb_parameter[trx_id]);
		if (status != MAC_SUCCESS) {
			tx_done_handling(trx_id, status);
			return;
		}

		tx_state[trx_id] = TX_BACKOFF;

#ifdef RX_WHILE_BACKOFF
		/* Keep receiver on during backoff */
		if ((trx_default_state[trx_id] == RF_RX) &&
				(tal_pib[trx_id].NumRxFramesDuringBackoff <
				tal_pib[trx_id].MaxNumRxFramesDuringBackoff)) {
			if (trx_state[trx_id] != RF_RX) {
				if (trx_state[trx_id] == RF_TRXOFF) {
					switch_to_txprep(trx_id);
				}

				switch_to_rx(trx_id);
			}
		} else
#endif
		{
#ifdef USE_TXPREP_DURING_BACKOFF
			/* Switch to TXPREP during backoff */

			if (trx_state[trx_id] != RF_TXPREP) {
				switch_to_txprep(trx_id);
			}

#else
			/* Switch to TRXOFF during backoff */
			if (trx_state[trx_id] != RF_TRXOFF) {
				uint16_t reg_offset = RF_BASE_ADDR_OFFSET *
						trx_id;
				trx_reg_write(reg_offset + RG_RF09_CMD,
						RF_TRXOFF);
				trx_state[trx_id] = RF_TRXOFF;
			}

#endif
		}
	} else { /* no backoff required */
		/* Start CCA immediately - no backoff */
		cca_start((void *)&timer_cb_parameter[trx_id]);
	}
}