Example #1
0
// 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 {
Example #2
0
// 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 {