// Called when the radio has received a packet. static void anchor_rxcallback (const dwt_callback_data_t *rxd) { if (rxd->event == DWT_SIG_RX_OKAY) { // Read in parameters of this packet reception uint64_t dw_rx_timestamp; uint8_t buf[ONEWAY_ANCHOR_MAX_RX_PKT_LEN]; uint8_t message_type; // Get the received time of this packet first dwt_readrxtimestamp(buf); dw_rx_timestamp = DW_TIMESTAMP_TO_UINT64(buf); // Get the actual packet bytes dwt_readrxdata(buf, MIN(ONEWAY_ANCHOR_MAX_RX_PKT_LEN, rxd->datalength), 0); // We process based on the first byte in the packet. How very active // message like... message_type = buf[offsetof(struct pp_tag_poll, message_type)]; if (message_type == MSG_TYPE_PP_NOSLOTS_TAG_POLL) { // This is one of the broadcast ranging packets from the tag struct pp_tag_poll* rx_poll_pkt = (struct pp_tag_poll*) buf; // Decide what to do with this packet if (_state == ASTATE_IDLE) { // We are currently not ranging with any tags. if (rx_poll_pkt->subsequence < NUM_RANGING_CHANNELS) { // We are idle and this is one of the first packets // that the tag sent. Start listening for this tag's // ranging broadcast packets. _state = ASTATE_RANGING; // Clear memory for this new tag ranging event memset(pp_anc_final_pkt.TOAs, 0, sizeof(pp_anc_final_pkt.TOAs)); memset(_anchor_antenna_recv_num, 0, sizeof(_anchor_antenna_recv_num)); // Record the EUI of the tag so that we don't get mixed up memcpy(pp_anc_final_pkt.ieee154_header_unicast.destAddr, rx_poll_pkt->header.sourceAddr, 8); // Record which ranging subsequence the tag is on _ranging_broadcast_ss_num = rx_poll_pkt->subsequence; // Record the timestamp. Need to subtract off the TX+RX delay from each recorded // timestamp. pp_anc_final_pkt.TOAs[_ranging_broadcast_ss_num] = dw_rx_timestamp - oneway_get_txrxdelay_from_subsequence(ANCHOR, _ranging_broadcast_ss_num); // Also record parameters the tag has sent us about how to respond // (or other operational parameters). _ranging_operation_config.reply_after_subsequence = rx_poll_pkt->reply_after_subsequence; _ranging_operation_config.anchor_reply_window_in_us = rx_poll_pkt->anchor_reply_window_in_us; _ranging_operation_config.anchor_reply_slot_time_in_us = rx_poll_pkt->anchor_reply_slot_time_in_us; // Update the statistics we keep about which antenna // receives the most packets from the tag uint8_t recv_antenna_index = oneway_subsequence_number_to_antenna(ANCHOR, rx_poll_pkt->subsequence); _anchor_antenna_recv_num[recv_antenna_index]++; // Now we need to start our own state machine to iterate // through the antenna / channel combinations while listening // for packets from the same tag. timer_start(_anchor_timer, RANGING_BROADCASTS_PERIOD_US, ranging_broadcast_subsequence_task); } else { // We found this tag ranging sequence late. We don't want // to use this because we won't get enough range estimates. // Just stay idle, but we do need to re-enable RX to // keep receiving packets. dwt_rxenable(0); } } else if (_state == ASTATE_RANGING) { // We are currently ranging with a tag, waiting for the various // ranging broadcast packets. // First check if this is from the same tag if (memcmp(pp_anc_final_pkt.ieee154_header_unicast.destAddr, rx_poll_pkt->header.sourceAddr, 8) == 0) { // Same tag if (rx_poll_pkt->subsequence == _ranging_broadcast_ss_num) { // This is the packet we were expecting from the tag. // Record the TOA, and adjust it with the calibration value. pp_anc_final_pkt.TOAs[_ranging_broadcast_ss_num] = dw_rx_timestamp - oneway_get_txrxdelay_from_subsequence(ANCHOR, _ranging_broadcast_ss_num); // Update the statistics we keep about which antenna // receives the most packets from the tag uint8_t recv_antenna_index = oneway_subsequence_number_to_antenna(ANCHOR, _ranging_broadcast_ss_num); _anchor_antenna_recv_num[recv_antenna_index]++; } else { // Some how we got out of sync with the tag. Ignore the // range and catch up. _ranging_broadcast_ss_num = rx_poll_pkt->subsequence; } // Check to see if we got the last of the ranging broadcasts if (_ranging_broadcast_ss_num == _ranging_operation_config.reply_after_subsequence) { // We did! ranging_listening_window_setup(); } } else { // Not the same tag, ignore } } else { // We are in some other state, not sure what that means } } else { // Other message types go here, if they get added // We do want to enter RX mode again, however dwt_rxenable(0); } } else {
// Called when the radio has received a packet. void dw1000_anchor_rxcallback (const dwt_callback_data_t *rxd) { if (rxd->event == DWT_SIG_RX_OKAY) { // Read in parameters of this packet reception uint64_t dw_rx_timestamp; uint8_t buf[DW1000_ANCHOR_MAX_RX_PKT_LEN]; uint8_t message_type; // Get the received time of this packet first dwt_readrxtimestamp(buf); dw_rx_timestamp = DW_TIMESTAMP_TO_UINT64(buf); // Get the actual packet bytes dwt_readrxdata(buf, MIN(DW1000_ANCHOR_MAX_RX_PKT_LEN, rxd->datalength), 0); // We process based on the first byte in the packet. How very active // message like... message_type = buf[offsetof(struct pp_tag_poll, message_type)]; if (message_type == MSG_TYPE_PP_NOSLOTS_TAG_POLL) { // This is one of the broadcast ranging packets from the tag struct pp_tag_poll* rx_poll_pkt = (struct pp_tag_poll*) buf; // Decide what to do with this packet if (_state == ASTATE_IDLE) { // We are currently not ranging with any tags. if (rx_poll_pkt->subsequence < NUM_RANGING_CHANNELS) { // We are idle and this is one of the first packets // that the tag sent. Start listening for this tag's // ranging broadcast packets. _state = ASTATE_RANGING; // Clear memory for this new tag ranging event memset(pp_anc_final_pkt.TOAs, 0, sizeof(pp_anc_final_pkt.TOAs)); memset(_anchor_antenna_recv_num, 0, sizeof(_anchor_antenna_recv_num)); // Record the EUI of the tag so that we don't get mixed up memcpy(pp_anc_final_pkt.ieee154_header_unicast.destAddr, rx_poll_pkt->header.sourceAddr, 8); // Record which ranging subsequence the tag is on _ranging_broadcast_ss_num = rx_poll_pkt->subsequence; // Record the timestamp pp_anc_final_pkt.TOAs[_ranging_broadcast_ss_num] = dw_rx_timestamp; // Also record parameters the tag has sent us about how to respond // (or other operational parameters). _ranging_operation_config.reply_after_subsequence = rx_poll_pkt->reply_after_subsequence; _ranging_operation_config.anchor_reply_window_in_us = rx_poll_pkt->anchor_reply_window_in_us; _ranging_operation_config.anchor_reply_slot_time_in_us = rx_poll_pkt->anchor_reply_slot_time_in_us; // Update the statistics we keep about which antenna // receives the most packets from the tag uint8_t recv_antenna_index = subsequence_number_to_antenna(ANCHOR, rx_poll_pkt->subsequence); _anchor_antenna_recv_num[recv_antenna_index]++; // Now we need to start our own state machine to iterate // through the antenna / channel combinations while listening // for packets from the same tag. _ranging_broadcast_ss_num++; dw1000_set_ranging_broadcast_subsequence_settings(ANCHOR, _ranging_broadcast_ss_num, FALSE); timer_start(_ranging_broadcast_timer, RANGING_BROADCASTS_PERIOD_US, ranging_broadcast_subsequence_task); } else { // We found this tag ranging sequence late. We don't want // to use this because we won't get enough range estimates. // Just stay idle. } } else if (_state == ASTATE_RANGING) { // We are currently ranging with a tag, waiting for the various // ranging broadcast packets. // First check if this is from the same tag if (memcmp(pp_anc_final_pkt.ieee154_header_unicast.destAddr, rx_poll_pkt->header.sourceAddr, 8) == 0) { // Same tag if (rx_poll_pkt->subsequence == _ranging_broadcast_ss_num) { // This is the packet we were expecting from the tag. // Record the TOA. pp_anc_final_pkt.TOAs[_ranging_broadcast_ss_num] = dw_rx_timestamp; // Update the statistics we keep about which antenna // receives the most packets from the tag uint8_t recv_antenna_index = subsequence_number_to_antenna(ANCHOR, _ranging_broadcast_ss_num); _anchor_antenna_recv_num[recv_antenna_index]++; } else { // Some how we got out of sync with the tag. Ignore the // range and catch up. _ranging_broadcast_ss_num = rx_poll_pkt->subsequence; } // Check to see if we got the last of the ranging broadcasts if (_ranging_broadcast_ss_num == _ranging_operation_config.reply_after_subsequence) { // We did! // Stop iterating through timing channels timer_stop(_ranging_broadcast_timer); // We no longer need to receive and need to instead // start transmitting. dwt_forcetrxoff(); // Update our state to the TX response state _state = ASTATE_RESPONDING; // Set the listening window index _ranging_listening_window_num = 0; // Determine which antenna we are going to use for // the response. uint8_t max_packets = 0; uint8_t max_index = 0; for (uint8_t i=0; i<NUM_ANTENNAS; i++) { if (_anchor_antenna_recv_num[i] > max_packets) { max_packets = _anchor_antenna_recv_num[i]; max_index = i; } } pp_anc_final_pkt.final_antenna = max_index; // Now we need to setup a timer to iterate through // the response windows so we can send a packet // back to the tag timer_start(_ranging_broadcast_timer, _ranging_operation_config.anchor_reply_window_in_us, ranging_listening_window_task); } } else { // Not the same tag, ignore } } else { // We are in some other state, not sure what that means } } else { // Other message types go here, if they get added } } else {