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

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

    PORTC.INTFLAGS = PORT_INT1IF_bm;

    TCC1_CTRLB &= ~TC1_CCAEN_bm;

    TIMER_SRC_DURING_TRX_AWAKE();

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

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

    PORTC.PIN1CTRL = PORT_ISC1_bm;

    TCC1_INTFLAGS = TC1_CCAIF_bm;

    TCC1_INTCTRLB = TC_CCAINTLVL_HI_gc;

    TCC1_CTRLB |= TC1_CCAEN_bm;	
}
Esempio n. 2
0
void tal_tx_beacon(frame_info_t *tx_frame)
{
	tal_trx_status_t trx_status;

	/* Set pointer to actual mpdu to be downloaded to the transceiver. */
	uint8_t *tal_beacon_to_tx = tx_frame->mpdu;

	/* Avoid that the beacon is transmitted while other transmision is
	 * on-going. */
	if (tal_state == TAL_TX_AUTO) {
		Assert(
				"trying to transmit beacon while ongoing transmission" ==
				0);
		return;
	}

	/* Send the pre-created beacon frame to the transceiver. */
	do {
		trx_status = set_trx_state(CMD_PLL_ON);
#if (_DEBUG_ > 1)
		if (trx_status != PLL_ON) {
			Assert("PLL_ON failed for beacon transmission" == 0);
		}
#endif
	} while (trx_status != PLL_ON);

	/* \TODO wait for talbeaconTxTime */

	pal_trx_irq_dis();

	/* 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.
	 * The actual length of the frame to be downloaded
	 * (parameter two of trx_frame_write)
	 * is
	 * 1 octet frame length octet
	 * + n octets frame (i.e. value of frame_tx[0])
	 * + 1 extra octet (see datasheet)
	 * - 2 octets FCS
	 */
	trx_frame_write(tal_beacon_to_tx, tal_beacon_to_tx[0]);

	tal_beacon_transmission = true;

#ifndef NON_BLOCKING_SPI
	pal_trx_irq_en();
#endif
#ifdef TX_OCTET_COUNTER
	tal_tx_octet_cnt += PHY_OVERHEAD + LENGTH_FIELD_LEN +
			tal_beacon_to_tx[0];
#endif
}
Esempio n. 3
0
/*
 * \brief Perform a single ED measurement
 *
 * \return ed_value Result of the measurement
 *         If the build switch TRX_REG_RAW_VALUE is defined, the transceiver's
 *         register value is returned.
 */
uint8_t tfa_ed_sample(void)
{
    uint8_t ed_value;
    tal_trx_status_t trx_status;

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

    /*
     * Disable the transceiver interrupts to prevent frame reception
     * while performing ED scan.
     */
    pal_trx_irq_dis();

    /*
     * Initiate ED operation by writing any value into transceiver register
     * PHY_ED_LEVEL.
     */
    pal_trx_reg_write(RG_PHY_ED_LEVEL, 0x00);

    /*
     * Start timer for reading ED value from the transceiver after
     * 140 microseconds.
     */
    pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US(ED_SAMPLE_DURATION_SYM + 1));

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

    /* Clear IRQ register */
    pal_trx_reg_read(RG_IRQ_STATUS);
    /* Enable reception agian */
    pal_trx_irq_flag_clr();
    pal_trx_irq_en();
    /* 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;
}
Esempio n. 4
0
File: tal_ed.c Progetto: bswe/6.1
/*
 * \brief Starts ED Scan
 *
 * This function starts an ED Scan for the scan duration specified by the
 * MAC layer.
 *
 * \param scan_duration Specifies the ED scan duration in symbols
 *
 * \return MAC_SUCCESS - ED scan duration timer started successfully
 *         TAL_BUSY - TAL is busy servicing the previous request from MAC
 *         TAL_TRX_ASLEEP - Transceiver is currently sleeping
 *         FAILURE otherwise
 */
retval_t tal_ed_start(uint8_t scan_duration)
{
    /*
     * Check if the TAL is in idle state. Only in idle state it can
     * accept and ED request from the MAC.
     */
    if (TAL_IDLE != tal_state)
    {
        if (tal_trx_status == TRX_SLEEP)
        {
            return TAL_TRX_ASLEEP;
        }
        else
        {
            Assert("TAL is TAL_BUSY" == 0);
            return TAL_BUSY;
        }
    }

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

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

        return FAILURE;
    }

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

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

    max_ed_level = 0;   // reset max value

    sampler_counter = CALCULATE_SYMBOL_TIME_SCAN_DURATION(scan_duration) / ED_SAMPLE_DURATION_SYM;

    return MAC_SUCCESS;
}
/**
 * @brief todo
 *
 */
void tal_rampdown(void)
{
    /*
     * Deactivate interrupt handling.
     */
    pal_trx_irq_dis();   /* Enable transceiver main interrupt. */

#if ((defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)) && (DISABLE_TSTAMP_IRQ == 0)
    /* Configure time stamp interrupt. */
    pal_trx_irq_dis_tstamp();    /* Enable timestamp interrupt. */
#endif

    pal_trx_uninit(false);      /* release SPI interface */

} /* tal_rampdown() */
Esempio n. 6
0
/**
 * @brief Switches the PLL on
 */
static void switch_pll_on(void)
{
    trx_irq_reason_t irq_status;
    uint32_t start_time, now;

    /* Check if trx is in TRX_OFF; only from PLL_ON the following procedure is applicable */
    if (pal_trx_bit_read(SR_TRX_STATUS) != TRX_OFF)
    {
        ASSERT("Switch PLL_ON failed, because trx is not in TRX_OFF" == 0);
        return;
    }

    /* use the IRQ status register checking for the actual PLL status */
    pal_trx_irq_dis();
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_PLL_LOCK);  /* allow PLL lock IRQ only*/
    pal_trx_reg_read(RG_IRQ_STATUS);    /* clear PLL lock bit */

    /* Switch PLL on */
    pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);

    /* Check if PLL has been locked. */
    pal_get_current_time(&start_time);
    while (1)
    {
        irq_status = (trx_irq_reason_t)pal_trx_reg_read(RG_IRQ_STATUS);
        if (irq_status & TRX_IRQ_PLL_LOCK)
        {
            break;  // PLL is locked now
        }

        /* Check if polling needs too much time. */
        pal_get_current_time(&now);
        if (pal_sub_time_us(now, start_time) > (10 * PLL_LOCK_TIME_US))
        {
            /* leave poll loop and throw assertion */
#if (DEBUG > 0)
            ASSERT("PLL switch failed" == 0);
#endif
            break;
        }
    }
    pal_trx_irq_flag_clr();
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_TRX_END); /* enable TRX_END interrupt */

    pal_trx_irq_en();
}
Esempio n. 7
0
/**
 * \brief Transmits the frame over-the-air
 */
static void tx_frame(void)
{
    tal_trx_status_t trx_status;

    /*
     * Trigger transmission
     * In case of an ongoing reception,
     * the incoming frame is handled first within ISR.
     */
    do
    {
        trx_status = set_trx_state(CMD_TX_ARET_ON);
    }
    while (trx_status != TX_ARET_ON);

    pal_trx_irq_dis();

    /* Toggle the SLP_TR pin triggering transmission. */
    PAL_SLP_TR_HIGH();
    PAL_WAIT_65_NS();
    PAL_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.
     * The actual length of the frame to be downloaded
     * (parameter two of pal_trx_frame_write)
     * is
     * 1 octet frame length octet
     * + n octets frame (i.e. value of frame_tx[0])
     * + 1 extra octet (see datasheet)
     * - 2 octets FCS
     */
    pal_trx_frame_write(tal_frame_to_tx, tal_frame_to_tx[0]);

    tal_state = TAL_TX_AUTO;

#ifndef NON_BLOCKING_SPI
    pal_trx_irq_en();
#endif
#ifdef TX_OCTET_COUNTER
    tal_tx_octet_cnt += PHY_OVERHEAD + LENGTH_FIELD_LEN + tal_frame_to_tx[0];
#endif
}
Esempio n. 8
0
/*
 * \brief Get the transceiver's supply voltage
 *
 * \return mv Milli Volt; 0 if below threshold, 0xFFFF if above threshold
 */
uint16_t tfa_get_batmon_voltage(void)
{
	tal_trx_status_t previous_trx_status;
	uint8_t vth_val;
	uint8_t i;
	uint16_t mv = 1; /* 1 used as indicator flag */
	bool range;

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

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

	/* 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);

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

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

	return mv;
}
Esempio n. 9
0
/*
 * \brief Sends frame using trx features to handle CSMA and re-transmissions
 *
 * \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)) {
		trx_bit_write(SR_MAX_CSMA_RETRIES, 7); /* immediate
		                                        * transmission */
	} else {
		trx_bit_write(SR_MAX_CSMA_RETRIES, tal_pib.MaxCSMABackoffs);
	}

	do {
		trx_status = set_trx_state(CMD_TX_ARET_ON);
	} while (trx_status != TX_ARET_ON);

	pal_trx_irq_dis();

	/* 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;
		}
	}

	/* 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.
	 * The actual length of the frame to be downloaded
	 * (parameter two of trx_frame_write)
	 * is
	 * 1 octet frame length octet
	 * + n octets frame (i.e. value of frame_tx[0])
	 * - 2 octets FCS
	 */
	trx_frame_write(tal_frame_to_tx, tal_frame_to_tx[0] - 1);

	tal_state = TAL_TX_AUTO;

#ifndef NON_BLOCKING_SPI
	pal_trx_irq_en();
#endif
#ifdef TX_OCTET_COUNTER
	tal_tx_octet_cnt += PHY_OVERHEAD + LENGTH_FIELD_LEN + frame_tx[0];
#endif
}
Esempio n. 10
0
void tal_tx_beacon(frame_info_t *tx_frame)
{
	tal_trx_status_t trx_status;

	/* Set pointer to actual mpdu to be downloaded to the transceiver. */
	uint8_t *tal_beacon_to_tx = tx_frame->mpdu;

	/*
	 * Avoid that the beacon is transmitted while transmitting
	 * a frame using slotted CSMA.
	 */
	if ((tal_csma_state == FRAME_SENDING_WITH_ACK) ||
			(tal_csma_state == FRAME_SENDING_NO_ACK) ||
			(tal_csma_state == WAITING_FOR_ACK)) {
		Assert(
				"trying to transmit beacon while ongoing transmission" ==
				0);
		return;
	}

	/* Send the pre-created beacon frame to the transceiver. */
	/* debug pin to switch on: define ENABLE_DEBUG_PINS, pal_config.h */
	PIN_BEACON_START();

	/* \TODO wait for talbeaconTxTime */
	do {
		trx_status = set_trx_state(CMD_FORCE_PLL_ON);
#if (_DEBUG_ > 1)
		if (trx_status != PLL_ON) {
			Assert("PLL_ON failed for beacon transmission" == 0);
		}

#endif
	} while (trx_status != PLL_ON);

	pal_trx_irq_dis();

	/* Toggle the SLP_TR pin triggering transmission. */
	PAL_SLP_TR_HIGH();
	PAL_WAIT_65_NS();
	PAL_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.
	 * The actual length of the frame to be downloaded
	 * (parameter two of pal_trx_frame_write)
	 * is
	 * 1 octet frame length octet
	 * + n octets frame (i.e. value of frame_tx[0])
	 * - 2 octets FCS
	 */
	pal_trx_frame_write(tal_beacon_to_tx, tal_beacon_to_tx[0] - 1);

#ifndef NON_BLOCKING_SPI
	pal_trx_irq_en();
#endif

	tal_state = TAL_TX_BEACON;
}
Esempio n. 11
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;

#ifdef BEACON_SUPPORT
	/* Handle frame transmission in slotted CSMA via basic mode */
	if (tal_csma_state != CSMA_IDLE) {
		do {
			trx_status = set_trx_state(CMD_PLL_ON);
		} while (trx_status != PLL_ON);

		tal_state = TAL_TX_BASIC;
	} else
#endif
	{
		/* Configure tx according to tx_retries */
		if (tx_retries) {
			pal_trx_bit_write(SR_MAX_FRAME_RETRIES,
					tal_pib.MaxFrameRetries);
		} else {
			pal_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)) {
			/*
			 * RF230B does not support "no" CSMA mode,
			 * therefore use shortest CSMA mode: CCA w/o backoff
			 */
			pal_trx_bit_write(SR_MIN_BE, 0x00);
			pal_trx_bit_write(SR_MAX_CSMA_RETRIES, 0);
		} else {
			pal_trx_bit_write(SR_MIN_BE, tal_pib.MinBE);
			pal_trx_bit_write(SR_MAX_CSMA_RETRIES,
					tal_pib.MaxCSMABackoffs);

			/*
			 * Handle interframe spacing
			 * Reduce IFS duration, since RF230B does CCA
			 */
			if (csma_mode == NO_CSMA_WITH_IFS) {
				if (last_frame_length > aMaxSIFSFrameSize) {
					pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US(
							macMinLIFSPeriod_def -
							CCA_DURATION_SYM)
							- IRQ_PROCESSING_DLY_US -
							PRE_TX_DURATION_US);
				} else {
					/*
					 * No delay required, since processing
					 *delay and CCA_DURATION_SYM
					 * delay the handling enough.
					 */
				}
			}
		}

		do {
			trx_status = set_trx_state(CMD_TX_ARET_ON);
		} while (trx_status != TX_ARET_ON);

		tal_state = TAL_TX_AUTO;
	}

	pal_trx_irq_dis();

	/* Toggle the SLP_TR pin triggering transmission. */
	PAL_SLP_TR_HIGH();
	PAL_WAIT_65_NS();
	PAL_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.
	 * The actual length of the frame to be downloaded
	 * (parameter two of pal_trx_frame_write)
	 * is
	 * 1 octet frame length octet
	 * + n octets frame (i.e. value of frame_tx[0])
	 * - 2 octets FCS
	 */
	pal_trx_frame_write(tal_frame_to_tx, tal_frame_to_tx[0] - 1);

#ifndef NON_BLOCKING_SPI
	pal_trx_irq_en();
#endif
}
Esempio n. 12
0
/**
 * \brief Performs CCA twice
 */
static uint8_t perform_cca_twice(void)
{
	tal_trx_status_t trx_status;
	uint8_t cca_status;
	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_US + CCA_PREPARATION_DURATION_US)) <
			cca_starttime_us);

	/* 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,
			(PLL_LOCK_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 trx interrupts while doing CCA */
	pal_trx_irq_dis();

	/* 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 by writing any dummy value to this register */
		pal_trx_bit_write(SR_CCA_REQUEST, 1);

		/* 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; */
			trx_status = (tal_trx_status_t)pal_trx_reg_read(
					RG_TRX_STATUS);
		} while ((trx_status & CCA_DONE_BIT) != CCA_DONE_BIT);

		/* 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_status & CCA_STATUS_BIT) {
			/* 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().
	 */

	/*
	 * Since we are not interested in any frames that might be received
	 * during CCA, reject any information that indicates a previous frame
	 * reception.
	 */
	pal_trx_reg_read(RG_IRQ_STATUS);
	pal_trx_irq_flag_clr();
	pal_trx_irq_en();

	return cca_status;
}
Esempio n. 13
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;

    pal_trx_irq_dis();

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

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

    if (mv == 1)
    {
        vth_val = 0x0F;
        for (i = 0; i < 16; i++)
        {
            pal_trx_bit_write(SR_BATMON_VTH, i);
            if (pal_trx_bit_read(SR_BATMON_OK) == BATMON_BELOW_THRES)
            {
                if (i > 0)
                {
                    vth_val = i - 1;
                }
                else
                {
                    vth_val = i;
                }
                break;
            }
        }

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

    pal_trx_reg_read(RG_IRQ_STATUS);
    if (previous_trx_status == TRX_SLEEP)
    {
        set_trx_state(CMD_TRX_SLEEP);
    }

    pal_trx_irq_en();

    return mv;
}
Esempio n. 14
0
/*
 * \brief Perform a CCA
 *
 * This function performs a CCA request.
 *
 * \return phy_enum_t PHY_IDLE or PHY_BUSY
 */
phy_enum_t tfa_cca_perform(void)
{
    tal_trx_status_t trx_status;
    uint8_t cca_status;

    /* 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 trx interrupts while doing CCA
    pal_trx_irq_dis();

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

    /* Start CCA by writing any dummy value to this register */
    pal_trx_bit_write(SR_CCA_REQUEST, 1);

    /* wait until CCA is done */
    pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US(CCA_DURATION_SYM));

    do
    {
        /*
         * Poll until CCA is really done.
         * Do NOT use bit read here!
         */
        trx_status = (tal_trx_status_t)pal_trx_reg_read(RG_TRX_STATUS);
    }
    while ((trx_status & CCA_DONE_BIT) != CCA_DONE_BIT);

    set_trx_state(CMD_TRX_OFF);

    /* Check if channel was idle or busy. */
    if (trx_status & CCA_STATUS_BIT)
    {
        cca_status = PHY_IDLE;
    }
    else
    {
        cca_status = PHY_BUSY;
    }

    /*
     * Since we are not interested in any frames that might be received
     * during CCA, reject any information that indicates a previous frame
     * reception.
     */
    pal_trx_reg_read(RG_IRQ_STATUS);
    pal_trx_irq_flag_clr();
    pal_trx_irq_en();

    return (phy_enum_t)cca_status;
}
Esempio n. 15
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;
    uint16_t mv = 1;    // 1 used as indicator flag
    bool range;

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

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

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

    /* Scan through the current range for the matching threshold. */
    if (mv == 1)    // 1 = indicates that voltage is within supported range
    {
        vth_val = 0x0F;
        for (uint8_t i = 0; i < 16; i++)
        {
            pal_trx_bit_write(SR_BATMON_VTH, vth_val);
            pal_timer_delay(2); /* Wait until Batmon has been settled. */
            if (pal_trx_bit_read(SR_BATMON_OK) == BATMON_VALID)
            {
                break;
            }
            vth_val--;
        }

        /* Calculate voltage based on register value and range. */
        if (range == HIGH)
        {
            mv = 2550 + (75 * vth_val);
        }
        else
        {
            mv = 1700 + (50 * vth_val);
        }
    }

    pal_trx_reg_read(RG_IRQ_STATUS);

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

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

    return mv;
}