Exemplo n.º 1
0
// Prepare to transmit a response to the TAG.
// TODO: check to see if we should even bother. Did we get enough packets?
static void ranging_listening_window_setup () {
	// Stop iterating through timing channels
	timer_stop(_anchor_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(_anchor_timer,
	            _ranging_operation_config.anchor_reply_window_in_us,
	            ranging_listening_window_task);
}
Exemplo n.º 2
0
// Update the Antenna and Channel settings to correspond with the settings
// for the given subsequence number.
//
// role:       anchor or tag
// subseq_num: where in the sequence we are
void oneway_set_ranging_broadcast_subsequence_settings (dw1000_role_e role,
        uint8_t subseq_num) {
    // Stop the transceiver on the anchor. Don't know why.
    if (role == ANCHOR) {
        dwt_forcetrxoff();
    }

    // Change the channel depending on what subsequence number we're at
    dw1000_update_channel(subsequence_number_to_channel(subseq_num));

    // Change what antenna we're listening/sending on
    dw1000_choose_antenna(oneway_subsequence_number_to_antenna(role, subseq_num));
}
Exemplo n.º 3
0
void oneway_anchor_init () {
	// Make sure the SPI speed is slow for this function
	dw1000_spi_slow();

	// Setup callbacks to this ANCHOR
	dwt_setcallbacks(anchor_txcallback, anchor_rxcallback);

	// Make sure the radio starts off
	dwt_forcetrxoff();

	// Set the anchor so it only receives data and ack packets
	dwt_enableframefilter(DWT_FF_DATA_EN | DWT_FF_ACK_EN);

	// // Set the ID and PAN ID for this anchor
	uint8_t eui_array[8];
	dw1000_read_eui(eui_array);
	// dwt_seteui(eui_array);
	// dwt_setpanid(POLYPOINT_PANID);

	// Automatically go back to receive
	dwt_setautorxreenable(TRUE);

	// Don't use these
	dwt_setdblrxbuffmode(FALSE);
	dwt_setrxtimeout(FALSE);

	// Load our EUI into the outgoing packet
	dw1000_read_eui(pp_anc_final_pkt.ieee154_header_unicast.sourceAddr);

	// Need a timer
	if (_anchor_timer == NULL) {
		_anchor_timer = timer_init();
	}

	// Init the PRNG for determining when to respond to the tag
	raninit(&_prng_state, eui_array[0]<<8|eui_array[1]);

	// Make SPI fast now that everything has been setup
	dw1000_spi_fast();

	// Reset our state because nothing should be in progress if we call init()
	_state = ASTATE_IDLE;
}
Exemplo n.º 4
0
dw1000_err_e dw1000_anchor_init () {
	uint8_t eui_array[8];

	// Make sure the radio starts off
	dwt_forcetrxoff();

	// Set the anchor so it only receives data and ack packets
	dwt_enableframefilter(DWT_FF_DATA_EN | DWT_FF_ACK_EN);

	// Set the ID and PAN ID for this anchor
	dw1000_read_eui(eui_array);
	dwt_seteui(eui_array);
	dwt_setpanid(POLYPOINT_PANID);

	// Automatically go back to receive
	dwt_setautorxreenable(TRUE);

	// Don't use these
	dwt_setdblrxbuffmode(FALSE);
	dwt_setrxtimeout(FALSE);

	// Don't receive at first
	dwt_rxenable(FALSE);

	// Load our EUI into the outgoing packet
	dw1000_read_eui(pp_anc_final_pkt.ieee154_header_unicast.sourceAddr);

	// Need a timer
	_ranging_broadcast_timer = timer_init();

	// Init the PRNG for determining when to respond to the tag
	raninit(&_prng_state, eui_array[0]<<8|eui_array[1]);

	// Make SPI fast now that everything has been setup
	dw1000_spi_fast();

	return DW1000_NO_ERR;
}
Exemplo n.º 5
0
int process_usbmessage(void)
{
	int result = 0;
	switch(application_mode)
	{
		case STAND_ALONE:
		{
			if(local_buff_length == 5)
			{
				//d (from "deca")
				if((local_buff[0] == 100) && (result == 0)) //d (from "deca")
				{
					if(local_buff[4] == 63)
					{
						int i = sizeof(SOFTWARE_VER_STRINGUSB);
						//change mode to  USB_TO_SPI and send a reply "y"
						tx_buff[0] = 121;
						memcpy(&tx_buff[1], SOFTWARE_VER_STRINGUSB, i);
						tx_buff[i+2] = 0;
						tx_buff_length = i + 2;
						application_mode = USB_TO_SPI;
						result = 2;
						//led_off(LED_ALL);
						led_on(LED_PC7); //turn on LED to indicate connection to PC application
					}
				}
			}
		}
		break;


		case USB_TO_SPI:
		{
			//first byte specifies the SPI speed and SPI read/write operation
			//bit 0 = 1 for write, 0 for read
			//bit 1 = 1 for high speed, 0 for low speed

			//<STX>   <ETX>
			//
			//to read from the device (e.g. 4 bytes), total length is = 1 + 1 + length_of_command (2) + length_of_data_to_read (2) + header length (1/2) + 1
			//
			//to write to the device (e.g. 4 bytes),  total length is = 1 + 1 + length_of_command (2) + length_of_data_to_write (2) + header length (1/2) + data length + 1
			//
			//LBS comes first:   0x2, 0x2, 0x7, 0x0, 0x04, 0x00, 0x3

			if(local_buff_length)
			{
				//0x2 = STX - start of SPI transaction data
				if(local_buff[0] == 0x2)
				{
					//configure SPI speed
					configSPIspeed(((local_buff[1]>>1) & 0x1));

					if((local_buff[1] & 0x1) == 0) //SPI read
					{
						int msglength = local_buff[2] + (local_buff[3]<<8);
						int datalength = local_buff[4] + (local_buff[5]<<8);

						//led_on(LED_PC6);
						tx_buff[0] = 0x2;
						tx_buff[datalength+2] = 0x3;

						//max data we can read in a single SPI transaction is 4093 as the USB/VCP tx buffer is only 4096 bytes long
						if((local_buff[msglength-1] != 0x3) || (datalength > 4093))
						{
							tx_buff[1] = 0x1; // if no ETX (0x3) indicate error
						}
						else
						{
							// do the read from the SPI
							readfromspi(msglength-7, &local_buff[6], datalength, &tx_buff[2]);  // result is stored in the buffer

							tx_buff[1] = 0x0; // no error
						}

						tx_buff_length = datalength + 3;
						result = 2;
					}

					if((local_buff[1] & 0x1) == 1) //SPI write
					{
						int msglength = local_buff[2] + (local_buff[3]<<8);
						int datalength = local_buff[4] + (local_buff[5]<<8);
						int headerlength = msglength - 7 - datalength;

						if(local_buff_length == msglength) //we got the whole message (sent from the PC)
						{
							local_buff_offset = 0;

							led_off(LED_PC6);
							tx_buff[0] = 0x2;
							tx_buff[2] = 0x3;

							if(local_buff[msglength-1] != 0x3)
							{
								tx_buff[1] = 0x1; // if no ETX (0x3) indicate error
							}
							else
							{
								// do the write to the SPI
								writetospi(headerlength, &local_buff[6], datalength, &local_buff[6+headerlength]);  // result is stored in the buffer

								tx_buff[1] = 0x0; // no error
							}

							tx_buff_length = 3;
							result = 2;
						}
						else //wait for the whole message
						{
							led_on(LED_PC6);
						}
					}
				}

				if((local_buff[0] == 100) && (result == 0)) //d (from "deca")
				{
					if(local_buff[4] == 63)
					{
						int i = sizeof(SOFTWARE_VER_STRINGUSB);
						//change mode to  USB_TO_SPI and send a reply "y"
						tx_buff[0] = 121;
						memcpy(&tx_buff[1], SOFTWARE_VER_STRINGUSB, i);
						tx_buff[i+2] = 0;
						tx_buff_length = i + 2;
						application_mode = USB_TO_SPI;
						result = 2;
						//led_off(LED_ALL);
						led_on(LED_PC7); //turn on LED to indicate connection to PC application
					}

				}

				if((local_buff[0] == 114) && (result == 0)) //r - flush the USB buffers...
				{
					DCD_EP_Flush(&USB_OTG_dev, CDC_IN_EP);
					result = 0;
				}
			}
		}
		break;

		case USB_PRINT_ONLY:
			if(local_buff_length && (result == 0))
			{
				if((local_buff[0] == 0x5) && (local_buff[5] == 0x5))
				{
					uint16 txantennadelay = local_buff[1] + (local_buff[2]<<8);
					uint16 rxantennadelay = local_buff[3] + (local_buff[4]<<8);
					instanceconfigantennadelays(txantennadelay, rxantennadelay);
				}
				if((local_buff[0] == 0x7) && (local_buff[5] == 0x7))
				{
					//not used in EVK
				}
				if((local_buff[0] == 0x6) && (local_buff[2] == 0x6))
				{
					uint8 switchS1 = local_buff[1];

					//disable DW1000 IRQ
					port_DisableEXT_IRQ(); //disable IRQ until we configure the device
					//turn DW1000 off
					dwt_forcetrxoff();
					//re-configure the instance
					inittestapplication(switchS1);
					//save the new setting
					s1configswitch = switchS1;
					//set the LDC
					setLCDline1(switchS1);
					//enable DW1000 IRQ
					port_EnableEXT_IRQ(); //enable IRQ before starting

					ranging = 0;

				}
				//d (from "deca")
				if(local_buff[0] == 100) //d (from "deca")
				{
					if(local_buff[4] == 63)
					{
						int i = sizeof(SOFTWARE_VER_STRINGUSB);
						//send a reply "n"
						tx_buff[0] = 110;
						memcpy(&tx_buff[1], SOFTWARE_VER_STRINGUSB, i);
						tx_buff[i+2] = 0;
						tx_buff_length = i + 2;
						result = 2;
					}
					if(local_buff[4] == 36) //"$"
					{
						//send a reply "n"
						tx_buff[0] = 110;
						memcpy(&tx_buff[1], version, version_size);
						tx_buff[version_size+1] = s1configswitch & 0xff;
						tx_buff[version_size+2] = '\r';
						tx_buff[version_size+3] = '\n';
						tx_buff_length = version_size + 4;
						result = 2;
					}
					if(local_buff[4] == 33) //"!"
					{
						//send back the DW1000 partID and lotID
						uint32 partID = dwt_getpartid();
						uint32 lotID = dwt_getlotid();
						tx_buff[0] = 110;
						memcpy(&tx_buff[1], &partID, 4);
						memcpy(&tx_buff[5], &lotID, 4);
						tx_buff[9] = '\r';
						tx_buff[10] = '\n';
						tx_buff_length = 11;
						result = 2;
					}
				}
			}
			break;

		default:
			break;
	}
Exemplo n.º 6
0
// Triggered when we receive a packet
void app_dw1000_rxcallback (const dwt_callback_data_t *rxd) {
	// First grab a copy of local time when this arrived
	rtimer_clock_t rt_timestamp = RTIMER_NOW();
	DEBUG_B6_HIGH;

	if (rxd->event == DWT_SIG_RX_OKAY) {
		leds_toggle(LEDS_BLUE);

		uint8_t packet_type;
		uint64_t dw_timestamp;
		uint8_t recv_pkt_buf[RX_PKT_BUF_LEN];

		// Get the dw_timestamp first
		uint8_t txTimeStamp[5] = {0, 0, 0, 0, 0};
		dwt_readrxtimestamp(txTimeStamp);
		dw_timestamp = ((uint64_t) (*((uint32_t*) txTimeStamp))) | (((uint64_t) txTimeStamp[4]) << 32);

		// Get the packet
		dwt_readrxdata(recv_pkt_buf, MIN(RX_PKT_BUF_LEN, rxd->datalength), 0);
		packet_type = recv_pkt_buf[offsetof(struct pp_tag_poll, message_type)];
		global_round_num = recv_pkt_buf[offsetof(struct pp_tag_poll, roundNum)];

		if (packet_type == MSG_TYPE_PP_ONEWAY_TAG_POLL) {
			struct pp_tag_poll* pkt = (struct pp_tag_poll*) recv_pkt_buf;
			DEBUG_P("TAG_POLL rx: %u\r\n", pkt->subsequence);

			if (global_subseq_num == pkt->subsequence) {
				// Configurations matched, record arrival time
				pp_anc_final_pkt.TOAs[global_subseq_num] = dw_timestamp;
			} else {
				// Tag/anchor weren't on same settings, so we
				// drop this sample and catch the anchor up
				global_subseq_num = pkt->subsequence;
			}

			if (!global_round_active) {
				DEBUG_B4_LOW;
				DEBUG_B5_LOW;
				memset(antenna_statistics, 0, sizeof(antenna_statistics));
				global_round_active = true;
				start_of_new_subseq = true;
				substate_timer_fired = true;
				/*
				subseq_start_time = rt_timestamp - US_TO_RT(TAG_SQ_START_TO_POLL_SFD_HIGH_US);
				rtimer_clock_t set_to = subseq_start_time + US_TO_RT(POLL_TO_SS_US+SS_TO_SQ_US);
				*/
				rtimer_clock_t set_to = rt_timestamp + US_TO_RT(
						POLL_TO_SS_US + SS_TO_SQ_US
						- TAG_SQ_START_TO_POLL_SFD_HIGH_US
						- ANC_MYSTERY_STARTUP_DELAY_US);
				rtimer_set(&subsequence_timer,
						set_to,
						1,
						(rtimer_callback_t)subsequence_task,
						NULL);
			}

			//Keep a running total of the number of packets seen from each antenna
			antenna_statistics[subseq_num_to_anchor_sel(global_subseq_num)]++;
		} else if (packet_type == MSG_TYPE_PP_ONEWAY_TAG_FINAL) {
			if (!global_round_active) {
				// The first packet we happened to receive was
				// an ANC_FINAL. We have nothing interesting to
				// reply with, so don't. But we *do* need to set
				// receive mode again so that a new poll will be
				// caught
				dwt_rxenable(0);
				return;
			}

			//We're likely in RX mode, so we need to exit before transmission
			dwt_forcetrxoff();

			pp_anc_final_pkt.TOAs[NUM_MEASUREMENTS] = dw_timestamp;

			pp_anc_final_pkt.header.seqNum++;
			const uint16 frame_len = sizeof(struct pp_anc_final);
			dwt_writetxfctrl(frame_len, 0);

			//Schedule this transmission for our scheduled time slot
			DEBUG_B6_LOW;
			uint32_t temp = dwt_readsystimestamphi32();
			uint32_t delay_time = temp +
				DW_DELAY_FROM_US(
					ANC_FINAL_INITIAL_DELAY_HACK_VALUE +
					(ANC_FINAL_RX_TIME_ON_TAG*(ANCHOR_EUI-1))
					);
				/* I don't understand what exactly is going on
				 * here. The chip seems to want way longer for
				 * this preamble than others -- maybe something
				 * to do with the large payload? From empirical
				 * measurements, the 300 base delay is about the
				 * minimum (250 next tested as not working)
				DW_DELAY_FROM_US(
					REVISED_DELAY_FROM_PKT_LEN_US(frame_len) +
					(2*ANC_FINAL_RX_TIME_ON_TAG*(ANCHOR_EUI-1))
					);
				*/
			delay_time &= 0xFFFFFFFE;
			pp_anc_final_pkt.dw_time_sent = delay_time;
			dwt_setdelayedtrxtime(delay_time);

			int err = dwt_starttx(DWT_START_TX_DELAYED);
			dwt_settxantennadelay(TX_ANTENNA_DELAY);
			dwt_writetxdata(frame_len, (uint8_t*) &pp_anc_final_pkt, 0);
			DEBUG_B6_HIGH;

#ifdef DW_DEBUG
			// No printing until after all dwt timing op's
			struct pp_tag_poll* pkt = (struct pp_tag_poll*) recv_pkt_buf;
			DEBUG_P("TAG_FINAL rx: %u\r\n", pkt->subsequence);
#endif

			if (err) {
#ifdef DW_DEBUG
				uint32_t now = dwt_readsystimestamphi32();
				DEBUG_P("Could not send anchor response\r\n");
				DEBUG_P(" -- sched time %lu, now %lu (diff %lu)\r\n", delay_time, now, now-delay_time);
				leds_on(LEDS_RED);
#endif
			} else {
				DEBUG_P("Send ANC_FINAL\r\n");
				leds_off(LEDS_RED);
			}
		} else {
			DEBUG_P("*** ERR: RX Unknown packet type: 0x%X\r\n", packet_type);
		}
	} else {
Exemplo n.º 7
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 {