void indirectTxTick(void) { StStatus status = ST_SUCCESS; //Send next available packet if there already isn't a packet in flight. if(txIndirectQ.inUse && txIndirectQ.sendNow && txPacketInFlight==FALSE) { //Linkup our current transmission to the Q. txPacketInUse = &txIndirectQ.inUse; txPacket = txIndirectQ.packet; txPacketSfd = txIndirectQ.sfdPtr; txPacketIsDirect = FALSE; txPacketInFlight = TRUE; txPacketAttemptsLeft = TX_ATTEMPTS_COUNT; //Now send the packet! if(txPacketSfd != NULL) { //Since we're going to inject the TX SFD into the packet, we have to //enable the SfdSentIsrCallback. The SfdSentIsrCallback will then //disable itself when it is done injecting the SFD. ST_RadioEnableSfdSentNotification(TRUE); } status = ST_RadioTransmit(txPacket); assert(status==ST_SUCCESS); txPacketAttemptsLeft--; } }
/******************************************************************************* * Function Name : ST_RadioTransmitCompleteIsrCallback * Description : Radio Transmit callback function * Input : - status: status of the packet transmission * - sfdSentTime: MAC timer when the SFD was sent * - framePending: TRUE if the received ACK indicates that data * is pending for this node * Output : None * Return : None *******************************************************************************/ void ST_RadioTransmitCompleteIsrCallback(StStatus status, u32 sfdSentTime, boolean framePending) { txBufferControl.status = TX_FAILED; switch(status) { case ST_SUCCESS: /* Success for broadcast packets */ txBufferControl.status = TX_SUCCESS; break; case ST_PHY_TX_CCA_FAIL: case ST_MAC_NO_ACK_RECEIVED: if (txBufferControl.retryNumber < txBufferControl.retries) { u8 returnValue; txBufferControl.retryNumber++; txBufferControl.status = TX_PENDING; returnValue = ST_RadioTransmit((u8 *) TX_BUFFER_GET_POINTER(length)); if (returnValue != TX_SUCCESS) { txBufferControl.status = TX_FAILED; } } break; case ST_PHY_ACK_RECEIVED: txBufferControl.status = TX_SUCCESS; break; default: break; } }/* end ST_RadioTransmitCompleteIsrCallback() */
static u8 transmitByte(u8 *data, u8 lastByte) { u8 returnValue = TX_SUCCESS; txBufferControl.payload[txBufferControl.pointer++] = *data; if (lastByte) { if (txBufferControl.broadcast) { txBroadcastBuffer.length = txBufferControl.pointer + 19; txBroadcastBuffer.seqNo = txBufferControl.sequenceCounter++; } else { txBuffer.length = txBufferControl.pointer + 23; txBuffer.seqNo = txBufferControl.sequenceCounter++; } txBufferControl.status = TX_PENDING; txBufferControl.retryNumber = 0; halCommonMemCopy(TX_BUFFER(payload), txBufferControl.payload, txBufferControl.pointer); returnValue = ST_RadioTransmit((u8 *) TX_BUFFER_GET_POINTER(length)); if (returnValue != TX_SUCCESS) { txBufferControl.status = TX_FAILED; } /* Wait for transmission to complete */ while (txBufferControl.status == TX_PENDING); returnValue = txBufferControl.status; txBufferControl.pointer = 0; } return returnValue; }
void ST_RadioTransmitCompleteIsrCallback(StStatus status, u32 txSyncTime, boolean framePending) { ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); ENERGEST_ON(ENERGEST_TYPE_LISTEN); LED_TX_OFF(); last_tx_status = status; if(status == ST_SUCCESS || status == ST_PHY_ACK_RECEIVED){ CLEAN_TXBUF(); } else { if(RETRY_CNT_GTZ()){ // Retransmission LED_TX_ON(); if(ST_RadioTransmit(stm32w_txbuf)==ST_SUCCESS){ ENERGEST_OFF(ENERGEST_TYPE_LISTEN); ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); PRINTF("stm32w: retransmission.\r\n"); DEC_RETRY_CNT(); } else { CLEAN_TXBUF(); LED_TX_OFF(); PRINTF("stm32w: retransmission failed.\r\n"); } } else { CLEAN_TXBUF(); } } /* Debug outputs. */ if(status == ST_SUCCESS || status == ST_PHY_ACK_RECEIVED){ PRINTF("stm32w: return status TX_END\r\n"); } else if (status == ST_MAC_NO_ACK_RECEIVED){ PRINTF("stm32w: return status TX_END_NOACK\r\n"); } else if (status == ST_PHY_TX_CCA_FAIL){ PRINTF("stm32w: return status TX_END_CCA_FAIL\r\n"); } else if(status == ST_PHY_TX_UNDERFLOW){ PRINTF("stm32w: return status TX_END_UNDERFLOW\r\n"); } else { PRINTF("stm32w: return status TX_END_INCOMPLETE\r\n"); } }
/** * @brief This function allows to transmit the data * @param lenght: lenght of the data * @param data: data to be transmitted * @param type: type of data (serial or button) * @retval None */ void sendData(uint8_t length, uint8_t *data, uint8_t type) { while (txComplete == FALSE); txPacket[8] = type; halCommonMemCopy(txPacket+9, data, length); txPacket[0] = length + 2 + 7 + 1; txPacket[3]++; /* increment sequence number */ txComplete = FALSE; ST_RadioTransmit(txPacket); }
/******************************************************************************* * Function Name : sendSerialData * Description : It allows to transmit the data * Input : - lenght of the data * - data to be transmitted * Output : None * Return : None *******************************************************************************/ void sendSerialData(u8 length, u8 *data) { while (txComplete == FALSE); halCommonMemCopy(txPacket+8, data, length); txPacket[0] = length + 2 + 7; txPacket[3]++; /* increment sequence number */ txComplete = FALSE; ST_RadioTransmit(txPacket); }/* end sendSerialData() */
/******************************************************************************* ** 函数名称: Zigbee_Transmit ** 函数功能: zigbee发送函数处理主函数 ** 入口参数: ** 出口参数: ** 备 注: *******************************************************************************/ void Zigbee_Transmit(void) { ST_RadioEnableOverflowNotification(FALSE); ST_RadioSetPowerMode(ST_TX_POWER_MODE_DEFAULT); ST_RadioEnableAddressFiltering(FALSE); ST_RadioEnableAutoAck(FALSE); ST_RadioSetPower(RF_Power); ST_RadioSetChannel(Send_Channel); ST_RadioInit(ST_RADIO_POWER_MODE_OFF); Card_Cmd[10] |= (0x00|(battery.stat<<5)|(help_flag<<7)); //电池电量及求助状态 txBuf[0] =(int8u)(sizeof(Card_Cmd)+2); for(int8u ct = 0; ct < (int8u)sizeof(Card_Cmd); ct++) txBuf[ct + 1] = Card_Cmd[ct]; txPacketInFlight = TRUE; if(ST_RadioTransmit(txBuf)==ST_SUCCESS){ while(txPacketInFlight); ST_RadioSleep(); } else SendFailTime++; }
/*---------------------------------------------------------------------------*/ static int stm32w_radio_transmit(unsigned short payload_len) { stm32w_txbuf[0] = payload_len + CHECKSUM_LEN; INIT_RETRY_CNT(); if(onoroff == OFF) { PRINTF("stm32w: Radio is off, turning it on.\r\n"); ST_RadioWake(); ENERGEST_ON(ENERGEST_TYPE_LISTEN); } #if RADIO_WAIT_FOR_PACKET_SENT GET_LOCK(); #endif /* RADIO_WAIT_FOR_PACKET_SENT */ last_tx_status = -1; LED_TX_ON(); if(ST_RadioTransmit(stm32w_txbuf) == ST_SUCCESS) { ENERGEST_OFF(ENERGEST_TYPE_LISTEN); ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); PRINTF("stm32w: sending %d bytes\r\n", payload_len); #if DEBUG > 1 for(uint8_t c = 1; c <= stm32w_txbuf[0] - 2; c++) { PRINTF("%x:", stm32w_txbuf[c]); } PRINTF("\r\n"); #endif #if RADIO_WAIT_FOR_PACKET_SENT if(wait_for_tx()) { PRINTF("stm32w: unknown tx error.\r\n"); TO_PREV_STATE(); LED_TX_OFF(); RELEASE_LOCK(); return RADIO_TX_ERR; } TO_PREV_STATE(); if(last_tx_status == ST_SUCCESS || last_tx_status == ST_PHY_ACK_RECEIVED || last_tx_status == ST_MAC_NO_ACK_RECEIVED) { RELEASE_LOCK(); if(last_tx_status == ST_PHY_ACK_RECEIVED) { return RADIO_TX_OK; /* ACK status */ } else if(last_tx_status == ST_MAC_NO_ACK_RECEIVED || last_tx_status == ST_SUCCESS) { return RADIO_TX_NOACK; } } LED_TX_OFF(); RELEASE_LOCK(); return RADIO_TX_ERR; #else /* RADIO_WAIT_FOR_PACKET_SENT */ TO_PREV_STATE(); LED_TX_OFF(); return RADIO_TX_OK; #endif /* RADIO_WAIT_FOR_PACKET_SENT */ } #if RADIO_WAIT_FOR_PACKET_SENT RELEASE_LOCK(); #endif /* RADIO_WAIT_FOR_PACKET_SENT */ TO_PREV_STATE(); PRINTF("stm32w: transmission never started.\r\n"); /* TODO: Do we have to retransmit? */ CLEAN_TXBUF(); LED_TX_OFF(); return RADIO_TX_ERR; }
/******************************************************************************* * Function Name : radio_loop * Description : When Radio is idle then checks for packets to be transmitted * Input : None * Output : None * Return : None *******************************************************************************/ void radio_loop() { // if the TX is idle then dequeue next packet and start TX CLEAR_LED(RLED); if ( 1 == stradio_retransmit_req_) { #if defined(_ENABLE_XBEE_COMPAT_4BS_TX_) || defined(_FORCE_XBEE_COMPAT_TX_) #ifdef _FORCE_XBEE_COMPAT_TX_ if (1) #else if (BS_ADDR == txPacket[6]) #endif //_FORCE_XBEE_COMPAT_TX_ { //txPacket[10]++;// = txPacket[3]; /* XBee COMPATIBILITY - increment sequence number */ txPacket[3]++; } #endif // defined(_ENABLE_XBEE_COMPAT_4BS_TX_) || defined(_FORCE_XBEE_COMPAT_TX_) int temp_ret = ST_RadioTransmit(txPacket); if (ST_SUCCESS != temp_ret) { txComplete = TRUE; // FAILED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! stradio_retransmision_result = temp_ret; } else { txComplete = FALSE; stradio_count_failed_retransmissions_++; } stradio_retransmit_req_ = 0; } else if (FALSE == txComplete) { SET_LED(RLED); count_stalled++; if (count_stalled > stalled_reset) { //stalled_reset = count_stalled + STALLED_THRESHOLD; //txComplete = TRUE; } } else if ( 0 != stradio_pending_len_ ) { sendPacketData( stradio_pending_len_, stradio_pending_data_, stradio_pending_dst_); stradio_pending_len_ = 0; } else if ( ( 0 == pkt_to_sent_len ) && ( 0xFF == pkt_to_sent_id ) ) { stalled_reset++; pkt_to_sent_id = que_deQpackets(); if ( 0xFF != pkt_to_sent_id ) { char routed = 0; unsigned int base = QBUFF_BASE ( pkt_to_sent_id ); // fill the TX-related variables pkt_to_sent_len = PAK_GET_TOTAL_LENGTH ( pkt_to_sent_id ); // routing decisions for the packet routed = routing_send_DATA_base ( QBUFF_BASE ( pkt_to_sent_id ) ); // If routing OK then start transmission process -> backoff if ( 1 == routed ) { unsigned int mac_d = get_dst_mac_base ( base ); sent_DATA_ = 1; sendPacketData(pkt_to_sent_len, (sint8_t*)&(QBUFF_ACCESS(base, 0)) , mac_d ); // send via the backoff implementation phy_sent_timeout_ = rtc_get_ticks() + my_tx_timeout_; SET_LED(YLED); } else { if (ROUTING_BEGAN_ROUTE_DISCOVERY == routed) { // re-enqueue the packet if (0 == que_enQpacket (pkt_to_sent_id)) { release_pkt_in_tx(); } else { pkt_to_sent_len = 0; pkt_to_sent_id = 0xFF; } } else { #ifdef _ENABLE_APP_MOD_ app_drop_pkt ( pkt_to_sent_id, MODULE_RTR, REASON_NOROUTE, EVENT_DSEND ); #endif // _ENABLE_APP_MOD_ // drop packet if not routable release_pkt_in_tx(); } } } } }