/** * @brief Starts continuous transmission on current channel */ void tfa_continuous_tx_start(continuous_tx_mode_t tx_mode) { uint8_t txcwdata[127]; pal_trx_bit_write(SR_TX_AUTO_CRC_ON, TX_AUTO_CRC_DISABLE); pal_trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF); pal_trx_reg_write(0x0176, 0x0F); /*TST_CTRL_DIGI*/ /* Here: use 2MBPS mode for PSD measurements. * Omit the two following lines, if 250k mode is desired for PRBS mode. */ pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_2MBPS); pal_trx_reg_write(RG_RX_CTRL, 0xA7); if (tx_mode == CW_MODE) { txcwdata[0] = 1; // length // Step 11 - frame buffer write access txcwdata[1] = 0x00; // f=fch-0.5 MHz; set value to 0xFF for f=fch+0.5MHz pal_trx_frame_write(txcwdata, 2); } else // PRBS mode { txcwdata[0] = 127; // = max length for (uint8_t i = 1; i < 128; i++) { txcwdata[i] = (uint8_t)rand(); } pal_trx_frame_write(txcwdata, 128); } pal_trx_reg_write(RG_PART_NUM, 0x54); pal_trx_reg_write(RG_PART_NUM, 0x46); set_trx_state(CMD_PLL_ON); PAL_SLP_TR_HIGH(); PAL_SLP_TR_LOW(); }
/* * \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 pal_trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF); // step 7: Enable continuous transmission - step #1 pal_trx_reg_write(0x36, 0x0F); if (tx_mode == CW_MODE) { // step 8: Register access: CW at Fc +/- 0.1 MHz pal_trx_reg_write(RG_TRX_CTRL_2, 0x0A); // 400 kbit mode, step 8 txcwdata[0] = 1; // length txcwdata[1] = 0; // step 9: Frame buffer access pal_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 pal_trx_frame_write(txcwdata, 128); } // step 10: Enable continuous transmission - step #2 pal_trx_reg_write(RG_PART_NUM, 0x54); // step 11: Enable continuous transmission - step #3 pal_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 PAL_SLP_TR_HIGH(); PAL_SLP_TR_LOW(); }
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. */ 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); 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 }
/* * \brief Starts continuous transmission on current channel * * \param tx_mode Mode of continuous transmission (CW or PRBS) * \param random_content Use random content if true */ void tfa_continuous_tx_start(continuous_tx_mode_t tx_mode, bool random_content) { uint8_t txcwdata[128]; pal_trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF); pal_trx_bit_write(SR_TX_AUTO_CRC_ON, TX_AUTO_CRC_DISABLE); pal_trx_reg_write(0x36, 0x0F); /* TST_CTRL_DIGI */ if (tx_mode == CW_MODE) { txcwdata[0] = 1; // step 9 txcwdata[1] = 0; pal_trx_frame_write(txcwdata, 2); // Step 10 pal_trx_reg_write(0x3D, 0x80); /* Configure continuous Tx (2) */ } else // PRBS mode { txcwdata[0] = 127; // = max length for (uint8_t i = 1; i < 128; i++) { if (random_content) { txcwdata[i] = (uint8_t)rand(); } else { txcwdata[i] = 0; } } pal_trx_frame_write(txcwdata, 128); pal_trx_reg_write(0x3D, 0x00); /* Configure continuous Tx (2) */ } // set tst pin to high TST_PORT_HIGH(); set_trx_state(CMD_PLL_ON); PAL_SLP_TR_HIGH(); PAL_SLP_TR_LOW(); }
/** * \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 }
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; }
/* * \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 }
/** * \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) { 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)) { pal_trx_bit_write(SR_MAX_CSMA_RETRIES, 7); // immediate transmission } else { pal_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) - TRX_IRQ_DELAY_US - PRE_TX_DURATION_US); last_frame_length = 0; } else { pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US(macMinSIFSPeriod_def) - TRX_IRQ_DELAY_US - PRE_TX_DURATION_US); last_frame_length = 0; } } /* 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); tal_state = TAL_TX_AUTO; #ifndef NON_BLOCKING_SPI pal_trx_irq_en(); #endif }