/* * \brief TAL task handling * * This function * - Checks and allocates the receive buffer. * - Processes the TAL incoming frame queue. * - Implements the TAL state machine. */ void tal_task(void) { /* Check if the receiver needs to be switched on. */ if (tal_rx_on_required && (tal_state == TAL_IDLE)) { /* Check if a receive buffer has not been available before. */ if (tal_rx_buffer == NULL) { tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE); } /* Check if buffer could be allocated */ if (NULL != tal_rx_buffer) { /* * Note: * This flag needs to be reset BEFORE the received is switched on. */ tal_rx_on_required = false; #ifdef PROMISCUOUS_MODE if (tal_pib.PromiscuousMode) { set_trx_state(CMD_RX_ON); } else { set_trx_state(CMD_RX_AACK_ON); } #else /* Normal operation */ set_trx_state(CMD_RX_AACK_ON); #endif } } else { /* no free buffer is available; try next time again */ } /* * If the transceiver has received a frame and it has been placed * into the queue of the TAL, the frame needs to be processed further. */ if (tal_incoming_frame_queue.size > 0) { buffer_t *rx_frame; /* Check if there are any pending data in the incoming_frame_queue. */ rx_frame = qmm_queue_remove(&tal_incoming_frame_queue, NULL); if (NULL != rx_frame) { process_incoming_frame(rx_frame); } } /* Handle the TAL state machines */ switch (tal_state) { case TAL_IDLE: /* Do nothing, but fall through... */ case TAL_TX_AUTO: /* Wait until state is changed to TAL_TX_DONE inside tx end ISR */ break; #ifdef SW_CONTROLLED_CSMA case TAL_BACKOFF: /* Do nothing, but fall through... */ case TAL_CCA: /* Do nothing */ break; case TAL_CSMA_CONTINUE: csma_continue(); break; case TAL_CCA_DONE: cca_done_handling(); break; #endif case TAL_TX_DONE: tx_done_handling(); // see tal_tx.c break; #ifdef BEACON_SUPPORT case TAL_SLOTTED_CSMA: slotted_csma_state_handling(); // see tal_slotted_csma.c break; #endif /* BEACON_SUPPORT */ #if (MAC_SCAN_ED_REQUEST_CONFIRM == 1) case TAL_ED_RUNNING: /* Do nothing here. Wait until ED is completed. */ break; case TAL_ED_DONE: ed_scan_done(); break; #endif /* (MAC_SCAN_ED_REQUEST_CONFIRM == 1) */ default: Assert("tal_state is not handled" == 0); break; } } /* tal_task() */
/* * \brief TAL task handling * * This function * - Checks and allocates the receive buffer. * - Processes the TAL incoming frame queue. * - Implements the TAL state machine. */ void tal_task(void) { /* Check if the receiver needs to be switched on. */ if (tal_rx_on_required && (tal_state == TAL_IDLE)) { /* Check if a receive buffer has not been available before. */ if (tal_rx_buffer == NULL) { tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE); } /* Check if buffer could be allocated */ if (NULL != tal_rx_buffer) { /* * Note: * This flag needs to be reset BEFORE the received is *switched on. */ tal_rx_on_required = false; /* * Release the protected buffer and set it again for *further protection * since the buffer is available now. */ trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_DISABLE); /* *Disable *buffer *protection *mode **/ pal_timer_delay(2); /* Allow pin change to get effective */ trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE); /* *Enable *buffer *protection *mode **/ CONF_REG_WRITE(); #ifdef PROMISCUOUS_MODE if (tal_pib.PromiscuousMode) { set_trx_state(CMD_RX_ON); } else { set_trx_state(CMD_RX_AACK_ON); } #else /* Normal operation */ set_trx_state(CMD_RX_AACK_ON); #endif } } else { /* no free buffer is available; try next time again */ } /* * If the transceiver has received a frame and it has been placed * into the queue of the TAL, the frame needs to be processed further. */ if (tal_incoming_frame_queue.size > 0) { buffer_t *rx_frame; /* Check if there are any pending data in the *incoming_frame_queue. */ rx_frame = qmm_queue_remove(&tal_incoming_frame_queue, NULL); if (NULL != rx_frame) { process_incoming_frame(rx_frame); } } /* Handle the TAL state machines */ switch (tal_state) { case TAL_IDLE: /* Do nothing, but fall through... */ case TAL_TX_AUTO: /* Wait until state is changed to TAL_TX_DONE inside tx end ISR **/ break; case TAL_TX_DONE: tx_done_handling(); /* see tal_tx.c */ break; #ifdef BEACON_SUPPORT case TAL_SLOTTED_CSMA: slotted_csma_state_handling(); /* see tal_slotted_csma.c */ break; #endif /* BEACON_SUPPORT */ #if (MAC_SCAN_ED_REQUEST_CONFIRM == 1) case TAL_ED_RUNNING: /* Do nothing here. Wait until ED is completed. */ break; case TAL_ED_DONE: ed_scan_done(); break; #endif /* (MAC_SCAN_ED_REQUEST_CONFIRM == 1) */ default: Assert("tal_state is not handled" == 0); break; } } /* tal_task() */
/** * @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]); } }