示例#1
0
cph_deca_msg_header_t * cph_deca_read_frame(uint8_t * rx_buffer, uint32_t *frame_len) {

	/* Clear good RX frame event in the DW1000 status register. */
	dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);

	/* A frame has been received, read it into the local buffer. */
	*frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
	if (*frame_len <= CPH_MAX_MSG_SIZE) {
		dwt_readrxdata(rx_buffer, *frame_len, 0);

#if defined(DEBUG_PRINT_RXFRAME)
		printf("FRM: ");
		for (int i=0;i<*frame_len;i++)
			printf("%02X ", rx_buffer[i]);
		printf("\r\n");
#endif

		return (cph_deca_msg_header_t*)rx_buffer;
	}
	else {
		TRACE("Bad length: %04X\r\n", *frame_len);
		return 0;
	}

}
static void rxcallback(const dwt_callback_data_t *rxd) {
	if (rxd->event == DWT_SIG_RX_OKAY) {
		dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);
		if (rxd->datalength <= MAX_BUFF_SIZE) {
			dwt_readrxdata(rx_buffer, rxd->datalength, 0);
			irq_status = STATUS_RCV;
			frame_len = rxd->datalength;}
		else {
			irq_status = STATUS_ERR;
			frame_len = rxd->datalength;
		}}
	else {
		dwt_readrxdata(rx_buffer, 20, 0);
		frame_len = 20;
		irq_status = STATUS_ERR;
	}
}
示例#3
0
cph_deca_msg_header_t * cph_deca_read_frame(uint8_t * rx_buffer, uint32_t *frame_len) {

	/* Clear good RX frame event in the DW1000 status register. */
	dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);

	/* A frame has been received, read it into the local buffer. */
	*frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
	if (*frame_len <= CPH_MAX_MSG_SIZE) {
		dwt_readrxdata(rx_buffer, *frame_len, 0);
		return (cph_deca_msg_header_t*)rx_buffer;
	}
	else {
		return 0;
	}

}
示例#4
0
static void rxcallback(const dwt_callback_data_t *rxd) {
	if (rxd->event == DWT_SIG_RX_OKAY) {
		dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);
		if (rxd->datalength <= MAXRXSIXZE) {
			dwt_readrxdata(rx_buffer, rxd->datalength, 0);
			trx_signal = SIGNAL_RCV;
			frame_len = rxd->datalength;
		} else {
			trx_signal = SIGNAL_ERR_LEN;
			error_status_reg = rxd->status;
		}
	}
	else {
		trx_signal = SIGNAL_ERR;
		error_status_reg = rxd->status;
	}
}
示例#5
0
void cph_deca_rxcallback(const dwt_callback_data_t *rxd) {
	cph_deca_event_t ev;

	memcpy(&ev.info, rxd, sizeof(dwt_callback_data_t));

	if (rxd->event == DWT_SIG_RX_OKAY) {
		if (rxd->datalength <= CPH_MAX_MSG_SIZE) {
			ev.status = CPH_EVENT_RX;
			dwt_readrxdata(ev.data, rxd->datalength, 0);
			ev.timestamp = get_rx_timestamp_u64();
			cph_queue_push(&event_queue, &ev);
		}
	}
	else {
		ev.status = CPH_EVENT_ERR;
		cph_queue_push(&event_queue, &ev);
		// Auto enable should be on, so don't bother dwt_rxenable
	}

	TRACE("%02X\r\n", ev.status);

}
示例#6
0
bool DWM1000_Anchor::dispatch(Msg& msg) {
	PT_BEGIN()
	PT_WAIT_UNTIL(msg.is(0, SIG_INIT));
	init();
	while (true) {

		WAIT_POLL: {
			dwt_setrxtimeout(0); /* Clear reception timeout to start next ranging process. */
			dwt_rxenable(0); /* Activate reception immediately. */
//			dwt_setinterrupt(DWT_INT_RFCG, 1);	// enable RXD interrupt

			while (true) { /* Poll for reception of a frame or error/timeout. See NOTE 7 below. */
				timeout(1000);/* This is the delay from the end of the frame transmission to the enable of the receiver, as programmed for the DW1000's wait for response feature. */
				clearInterrupt();
				PT_YIELD_UNTIL(timeout() || isInterruptDetected());
				status_reg = _status_reg;
				LOG<< HEX << " status reg.:" << status_reg << " ,interrupts : " << interruptCount << FLUSH;
				status_reg = dwt_read32bitreg(SYS_STATUS_ID);
				LOG<< HEX << " IRQ pin : " << digitalRead(D2) << " status_reg DWM1000 	" << status_reg << FLUSH;// PULL LOW

				if (status_reg & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR))
					break;
			}
		}
		///____________________________________________________________________________

		if (status_reg & SYS_STATUS_RXFCG) {
			LOG<< " $ "<<FLUSH;
			uint32 frame_len;
			dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG); /* Clear good RX frame event in the DW1000 status register. */

			/* A frame has been received, read it into the local buffer. */
			frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
			if (frame_len <= RX_BUFFER_LEN) {
				dwt_readrxdata(rx_buffer, frame_len, 0);
			}

			/* Check that the frame is a poll sent by "DS TWR initiator" example.
			 * As the sequence number field of the frame is not relevant, it is cleared to simplify the validation of the frame. */
			rx_buffer[ALL_MSG_SN_IDX] = 0;
			if (memcmp(rx_buffer, rx_poll_msg, ALL_MSG_COMMON_LEN) == 0) {
				LOG<< " $$ "<<FLUSH;
				uint32 resp_tx_time;

				poll_rx_ts = get_rx_timestamp_u64(); /* Retrieve poll reception timestamp. */

				/* Set send time for response. See NOTE 8 below. */
				resp_tx_time = (poll_rx_ts
						+ (POLL_RX_TO_RESP_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8;
				dwt_setdelayedtrxtime(resp_tx_time);

				/* Set expected delay and timeout for final message reception. */
				dwt_setrxaftertxdelay(RESP_TX_TO_FINAL_RX_DLY_UUS);
				dwt_setrxtimeout(FINAL_RX_TIMEOUT_UUS);

				/* Write and send the response message. See NOTE 9 below.*/
				tx_resp_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
				dwt_writetxdata(sizeof(tx_resp_msg), tx_resp_msg, 0);
				dwt_writetxfctrl(sizeof(tx_resp_msg), 0);
				dwt_starttx(DWT_START_TX_DELAYED | DWT_RESPONSE_EXPECTED);

				/* We assume that the transmission is achieved correctly, now poll for reception of expected "final" frame or error/timeout.
				 * See NOTE 7 below. */
//				while (true) { /* Poll for reception of a frame or error/timeout. See NOTE 7 below. */
				timeout(10);
				dwt_setinterrupt(DWT_INT_RFCG, 1);// enable
				clearInterrupt();
//				PT_YIELD_UNTIL(timeout() || isInterruptDetected());
				status_reg = dwt_read32bitreg(SYS_STATUS_ID);
//				status_reg = _status_reg;
				LOG<< HEX << " status reg2:" << status_reg << FLUSH;
//					if (status_reg & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR))
//						break;
//				}
//               while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR)))
//               { };

				/* Increment frame sequence number after transmission of the response message (modulo 256). */
				frame_seq_nb++;

				if (status_reg & SYS_STATUS_RXFCG) {
					LOG<< " $$$ "<<FLUSH;
					/* Clear good RX frame event and TX frame sent in the DW1000 status register. */
					dwt_write32bitreg(SYS_STATUS_ID,
							SYS_STATUS_RXFCG | SYS_STATUS_TXFRS);

					/* A frame has been received, read it into the local buffer. */
					frame_len = dwt_read32bitreg(
							RX_FINFO_ID) & RX_FINFO_RXFLEN_MASK;
					if (frame_len <= RX_BUF_LEN) {
						dwt_readrxdata(rx_buffer, frame_len, 0);
					}

					/* Check that the frame is a final message sent by "DS TWR initiator" example.
					 * As the sequence number field of the frame is not used in this example, it can be zeroed to ease the validation of the frame. */
					rx_buffer[ALL_MSG_SN_IDX] = 0;
					if (memcmp(rx_buffer, rx_final_msg, ALL_MSG_COMMON_LEN)
							== 0) {
						uint32 poll_tx_ts, resp_rx_ts, final_tx_ts;
						uint32 poll_rx_ts_32, resp_tx_ts_32, final_rx_ts_32;
						double Ra, Rb, Da, Db;
						int64 tof_dtu;

						/* Retrieve response transmission and final reception timestamps. */
						resp_tx_ts = get_tx_timestamp_u64();
						final_rx_ts = get_rx_timestamp_u64();

						/* Get timestamps embedded in the final message. */
						final_msg_get_ts(&rx_buffer[FINAL_MSG_POLL_TX_TS_IDX],
								&poll_tx_ts);
						final_msg_get_ts(&rx_buffer[FINAL_MSG_RESP_RX_TS_IDX],
								&resp_rx_ts);
						final_msg_get_ts(&rx_buffer[FINAL_MSG_FINAL_TX_TS_IDX],
								&final_tx_ts);

						/* Compute time of flight. 32-bit subtractions give correct answers even if clock has wrapped. See NOTE 10 below. */
						poll_rx_ts_32 = (uint32) poll_rx_ts;
						resp_tx_ts_32 = (uint32) resp_tx_ts;
						final_rx_ts_32 = (uint32) final_rx_ts;
						Ra = (double) (resp_rx_ts - poll_tx_ts);
						Rb = (double) (final_rx_ts_32 - resp_tx_ts_32);
						Da = (double) (final_tx_ts - resp_rx_ts);
						Db = (double) (resp_tx_ts_32 - poll_rx_ts_32);
						tof_dtu = (int64) ((Ra * Rb - Da * Db)
								/ (Ra + Rb + Da + Db));

						tof = tof_dtu * DWT_TIME_UNITS;
						distance = tof * SPEED_OF_LIGHT;

						/* Display computed distance on LCD. */
//						char dist_str[20];
//						sprintf(dist_str,"%3.2f", distance);
						//                      lcd_display_str(dist_str);
						LOG<< " distance : " << (float)distance << "m. " << FLUSH;
					}
				} else {
					/* Clear RX error events in the DW1000 status register. */
					dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR);
				}
			}
		} else {
示例#7
0
/**
 * Application entry point.
 */
int rxWait(void)
{
    /* Reset and initialise DW1000.
     * For initialisation, DW1000 clocks must be temporarily set to crystal speed. After initialisation SPI rate can be increased for optimum
     * performance. */
	int i;

    reset_DW1000(); /* Target specific drive of RSTn line into DW1000 low for a period. */
    //spi_set_rate_low();
    dwt_initialise(DWT_LOADNONE);
    //spi_set_rate_high();

    /* Configure DW1000. See NOTE 2 below. */
    dwt_configure(&config);

    /* Loop forever sending and receiving frames periodically. */
    while (1)
    {
        /* Activate reception immediately. See NOTE 3 below. */
        dwt_rxenable(0);

        /* Poll until a frame is properly received or an error occurs. See NOTE 4 below.
         * STATUS register is 5 bytes long but, as the events we are looking at are in the lower bytes of the register, we can use this simplest API
         * function to access it. */
        while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR)))
        { };
        printf("Status reg now 0x%x\r\n",status_reg);

        if (status_reg & SYS_STATUS_RXFCG)
        {
            /* A frame has been received, read it into the local buffer. */
            frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
            if (frame_len <= FRAME_LEN_MAX)
            {
                dwt_readrxdata(rx_buffer, frame_len, 0);
            }

            /* Clear good RX frame event in the DW1000 status register. */
            dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);

            for (i=0;i<frame_len;i++) {
            	printf("%x ",rx_buffer[i]);
            }
            printf("\r\n");

            /* Validate the frame is the one expected as sent by "TX then wait for a response" example. */
            if ((frame_len == 14) && (rx_buffer[0] == 0xC5) && (rx_buffer[10] == 0x43) && (rx_buffer[11] == 0x2))
            {
                int i;

                /* Copy source address of blink in response destination address. */
                for (i = 0; i < 8; i++)
                {
                    tx_msg[DATA_FRAME_DEST_IDX + i] = rx_buffer[BLINK_FRAME_SRC_IDX + i];
                }

                /* Write response frame data to DW1000 and prepare transmission. See NOTE 5 below.*/
                dwt_writetxdata(sizeof(tx_msg), tx_msg, 0);
                dwt_writetxfctrl(sizeof(tx_msg), 0);

                /* Send the response. */
                dwt_starttx(DWT_START_TX_IMMEDIATE);

                /* Poll DW1000 until TX frame sent event set. */
                while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS))
                { };

                /* Clear TX frame sent event. */
                dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);

                /* Increment the data frame sequence number (modulo 256). */
                tx_msg[DATA_FRAME_SN_IDX]++;
            }
        }
        else
        {
            /* Clear RX error events in the DW1000 status register. */
            dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR);
            printf("Some RX errors ...\r\n");
        }
    }
}
示例#8
0
void listener_run(void) {

	uint32_t announce_coord_ts = 0;
	uint32_t elapsed = 0;
	uint32_t last_ts = 0;
	uint32_t count = 0;

	irq_init();
	pio_disable_interrupt(DW_IRQ_PIO, DW_IRQ_MASK);



	// Setup DW1000
	dwt_txconfig_t txconfig;

	// Setup DECAWAVE
	reset_DW1000();
	spi_set_rate_low();
	dwt_initialise(DWT_LOADUCODE);
	spi_set_rate_high();

	dwt_configure(&cph_config->dwt_config);

	dwt_setpanid(0x4350);
	dwt_setaddress16(0x1234);

	// Clear CLKPLL_LL
	dwt_write32bitreg(SYS_STATUS_ID, 0x02000000);

	uint32_t id = dwt_readdevid();
	printf("Device ID: %08X\r\n", id);


#if 1

	dwt_setcallbacks(0, rxcallback);
	dwt_setinterrupt(
			DWT_INT_TFRS | DWT_INT_RFCG
					| (DWT_INT_ARFE | DWT_INT_RFSL | DWT_INT_SFDT | DWT_INT_RPHE | DWT_INT_RFCE | DWT_INT_RFTO /*| DWT_INT_RXPTO*/),
			1);

	pio_enable_interrupt(DW_IRQ_PIO, DW_IRQ_MASK);

	dwt_rxenable(0);

	while (1) {

		elapsed = cph_get_millis() - last_ts;
		if (elapsed > 5000) {
			printf("alive %d\r\n", count++);
			last_ts = cph_get_millis();
		}

		if (trx_signal == SIGNAL_RCV) {
			printf("[RCV] %d - ", frame_len);
			for (int i = 0; i < frame_len; i++) {
				printf("%02X ", rx_buffer[i]);
			}
			printf("\r\n");
			trx_signal = SIGNAL_EMPTY;
			dwt_rxenable(0);
		}
		else if(trx_signal == SIGNAL_ERR) {
			printf("ERROR: %08X\r\n", error_status_reg);
			trx_signal = SIGNAL_EMPTY;
			dwt_rxenable(0);
		}
		else if(trx_signal == SIGNAL_ERR_LEN) {
			printf("ERROR LENGTH: %08X\r\n", error_status_reg);
			trx_signal = SIGNAL_EMPTY;
			dwt_rxenable(0);
		}
	}

#else

	while (1) {

		/* Activate reception immediately. */
		dwt_rxenable(0);

		while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR))) {
		};

		if (status_reg & SYS_STATUS_RXFCG) {
			uint32 frame_len;

			dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);

			frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
			if (frame_len <= MAXRXSIXZE) {
				dwt_readrxdata(rx_buffer, frame_len, 0);
			} else {
				frame_len = 0;
			}

			if (frame_len > 0) {
				printf("[RCV] ");
				for (int i = 0; i < frame_len; i++) {
					printf("%02X ", rx_buffer[i]);
				}
				printf("\r\n");
			} else {
				printf("ERROR: frame_len == %d\r\n", frame_len);
			}

		} else {

			printf("ERROR: dwt_rxenable has status of %08X\r\n", status_reg);
			/* Clear RX error events in the DW1000 status register. */
			dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR | SYS_STATUS_CLKPLL_LL);
		}
	}
#endif

}
示例#9
0
/*! ------------------------------------------------------------------------------------------------------------------
 * @fn main()
 *
 * @brief Application entry point.
 *
 * @param  none
 *
 * @return none
 */
int ssTwrInit(void)
{

    /* Reset and initialise DW1000.
     * For initialisation, DW1000 clocks must be temporarily set to crystal speed. After initialisation SPI rate can be increased for optimum
     * performance. */
	int status;

	reset_DW1000(); /* Target specific drive of RSTn line into DW1000 low for a period. */
    //spi_set_rate_low();
    status = dwt_initialise(DWT_LOADUCODE);
    if (DWT_SUCCESS != status) printf("API error line %d\r\n",__LINE__);
    //spi_set_rate_high();

    /* Configure DW1000. See NOTE 6 below. */
    status = dwt_configure(&config);
    if (DWT_SUCCESS != status) printf("API error line %d\r\n",__LINE__);

    // read otp
    uint32_t otpVal[0x20];
    dwt_otpread(0,otpVal,0x20);
    printf("OTP   6: 0x%x\r\n",otpVal[6]);
    printf("OTP   7: 0x%x\r\n",otpVal[7]);
    printf("OTP x16: 0x%x\r\n",otpVal[0x16]);
    printf("OTP x17: 0x%x\r\n",otpVal[0x17]);

    /* Apply default antenna delay value. See NOTE 2 below. */
    printf("antenna delays: default TX: %d, default RX: %d, evk 16m: %d, evk 64m: %d\r\n",TX_ANT_DLY,RX_ANT_DLY,DWT_RF_DELAY_16M,DWT_RF_DELAY_64M);
    tx_delay = TX_ANT_DLY;
    rx_delay = RX_ANT_DLY;
    dwt_setrxantennadelay(rx_delay);
    dwt_settxantennadelay(tx_delay);

    /* Set expected response's delay and timeout. See NOTE 1 and 5 below.
     * As this example only handles one incoming frame with always the same delay and timeout, those values can be set here once for all. */
    dwt_setrxaftertxdelay(POLL_TX_TO_RESP_RX_DLY_UUS);
    dwt_setrxtimeout(RESP_RX_TIMEOUT_UUS);

    btn = buttons();

    printf("%s entering main loop\r\n",__FUNCTION__);

    /* Loop forever initiating ranging exchanges. */
    while (1)
    {
        /* Write frame data to DW1000 and prepare transmission. See NOTE 7 below. */
        tx_poll_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
        status = dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);
        if (DWT_SUCCESS != status) printf("API error line %d\r\n",__LINE__);
        status = dwt_writetxdata(sizeof(tx_poll_msg), tx_poll_msg, 0);
        if (DWT_SUCCESS != status) printf("API error line %d\r\n",__LINE__);
        status = dwt_writetxfctrl(sizeof(tx_poll_msg), 0);
        if (DWT_SUCCESS != status) printf("API error line %d\r\n",__LINE__);

        /* Start transmission, indicating that a response is expected so that reception is enabled automatically after the frame is sent and the delay
         * set by dwt_setrxaftertxdelay() has elapsed. */
        status = dwt_starttx(DWT_START_TX_IMMEDIATE | DWT_RESPONSE_EXPECTED);
        if (DWT_SUCCESS != status) printf("API error line %d\r\n",__LINE__);

        /* We assume that the transmission is achieved correctly, poll for reception of a frame or error/timeout. See NOTE 8 below. */
        while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR)))
        { } ; // printf("Waiting. status reg 0x%x\r\n",status_reg); };
        //printf("Status reg now 0x%x\r\n",status_reg);

        if (SYS_STATUS_RXRFTO & status_reg)
            printf("RX timeout\r\n");

        /* Increment frame sequence number after transmission of the poll message (modulo 256). */
        frame_seq_nb++;

        if (status_reg & SYS_STATUS_RXFCG)
        {
            uint32 frame_len;

            //printf("Check RX\r\n");
            /* Clear good RX frame event in the DW1000 status register. */
            dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);

            /* A frame has been received, read it into the local buffer. */
            frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFLEN_MASK;
            if (frame_len <= RX_BUF_LEN)
            {
                dwt_readrxdata(rx_buffer, frame_len, 0);
            }

            /* Check that the frame is the expected response from the companion "SS TWR responder" example.
             * As the sequence number field of the frame is not relevant, it is cleared to simplify the validation of the frame. */
            rx_buffer[ALL_MSG_SN_IDX] = 0;
            if (memcmp(rx_buffer, rx_resp_msg, ALL_MSG_COMMON_LEN) == 0)
            {
                uint32 poll_tx_ts, resp_rx_ts, poll_rx_ts, resp_tx_ts;
                int32 rtd_init, rtd_resp;

                /* Retrieve poll transmission and response reception timestamps. See NOTE 9 below. */
                poll_tx_ts = dwt_readtxtimestamplo32();
                resp_rx_ts = dwt_readrxtimestamplo32();

                /* Get timestamps embedded in response message. */
                resp_msg_get_ts(&rx_buffer[RESP_MSG_POLL_RX_TS_IDX], &poll_rx_ts);
                resp_msg_get_ts(&rx_buffer[RESP_MSG_RESP_TX_TS_IDX], &resp_tx_ts);

                /* Compute time of flight and distance. */
                rtd_init = resp_rx_ts - poll_tx_ts;
                rtd_resp = resp_tx_ts - poll_rx_ts;

                tof = ((rtd_init - rtd_resp) / 2.0) * DWT_TIME_UNITS;
                distance = tof * SPEED_OF_LIGHT;

                /* Display computed distance on LCD. */
                //sprintf(dist_str, "DIST: %3.2f m", distance);
                sprintf(dist_str, "%3.2f", distance);
                printf("%s\r\n",dist_str);
                //lcd_display_str(dist_str);

            }
        }
        else
        {
            /* Clear RX error events in the DW1000 status register. */
            printf("Errors occured. Clearing up\r\n");
            dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR);
        }

        /* Execute a delay between ranging exchanges. */
        //printf("Delay %dms\r\n",RNG_DELAY_MS);
        deca_sleep(RNG_DELAY_MS);

        // toggle led
		ledToggle();
		// update antenna
		if (buttons() & 1) {
		    tx_delay -= 10; // >>= 1;
		    rx_delay -= 10; //>>= 1;
		    dwt_setrxantennadelay(rx_delay);
		    dwt_settxantennadelay(tx_delay);
		    printf("Decreased antenna delay to 0x%x\r\n",tx_delay);
		}
		if (buttons() & 2) {
			tx_delay += 10;
			rx_delay += 10;
		    dwt_setrxantennadelay(rx_delay);
		    dwt_settxantennadelay(tx_delay);
		    printf("Increased antenna delay to 0x%x\r\n",tx_delay);
		}

    }
}
示例#10
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 {
示例#11
0
bool DWM1000_Tag::dispatch(Msg& msg) {
	PT_BEGIN()
	PT_WAIT_UNTIL(msg.is(0, SIG_INIT));
	init();

	POLL_SEND: {
		while (true) {
			timeout(1000);				// delay  between POLL
			PT_YIELD_UNTIL(timeout());
			/* Write frame data to DW1000 and prepare transmission. See NOTE 7 below. */
			tx_poll_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
			dwt_writetxdata(sizeof(tx_poll_msg), tx_poll_msg, 0);
			dwt_writetxfctrl(sizeof(tx_poll_msg), 0);

			/* Start transmission, indicating that a response is expected so that reception is enabled automatically after the frame is sent and the delay
			 * set by dwt_setrxaftertxdelay() has elapsed. */
			LOG<< " Start TXF " << FLUSH;
			dwt_starttx(DWT_START_TX_IMMEDIATE | DWT_RESPONSE_EXPECTED);// SEND POLL MSG
			dwt_setinterrupt(DWT_INT_TFRS, 0);
			dwt_setinterrupt(DWT_INT_RFCG, 1);	// enable
			clearInterrupt();
			_timeoutCounter = 0;

			/* We assume that the transmission is achieved correctly, poll for reception of a frame or error/timeout. See NOTE 8 below. */
			timeout(10);
			PT_YIELD_UNTIL(timeout() || isInterruptDetected());	// WAIT RESP MSG

			if (isInterruptDetected())
				LOG<< " INTERRUPT DETECTED " << FLUSH;

			status_reg = dwt_read32bitreg(SYS_STATUS_ID);
			LOG<< HEX <<" SYS_STATUS " << status_reg << FLUSH;
			if (status_reg == 0xDEADDEAD) {
				init();
			} else if (status_reg & SYS_STATUS_RXFCG)
				goto RESP_RECEIVED;
			else if (status_reg & SYS_STATUS_ALL_RX_ERR) {

				if (status_reg & SYS_STATUS_RXRFTO)
					INFO(" RX Timeout");
				else
					INFO(" RX error ");
				dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR); /* Clear RX error events in the DW1000 status register. */

			}
		}

	}
	RESP_RECEIVED: {

		LOG<< " Received " <<FLUSH;

		frame_seq_nb++; /* Increment frame sequence number after transmission of the poll message (modulo 256). */
		uint32 frame_len;

		/* Clear good RX frame event and TX frame sent in the DW1000 status register. */
		dwt_write32bitreg(SYS_STATUS_ID,
				SYS_STATUS_RXFCG | SYS_STATUS_TXFRS);

		/* A frame has been received, read iCHANGEt into the local buffer. */
		frame_len =
		dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFLEN_MASK;
		if (frame_len <= RX_BUF_LEN) {
			dwt_readrxdata(rx_buffer, frame_len, 0);
		}

		/* Check that the frame is the expected response from the companion "DS TWR responder" example.
		 * As the sequence number field of the frame is not relevant, it is cleared to simplify the validation of the frame. */
		rx_buffer[ALL_MSG_SN_IDX] = 0;
		if (memcmp(rx_buffer, rx_resp_msg, ALL_MSG_COMMON_LEN) == 0) {	// CHECK RESP MSG
			uint32 final_tx_time;

			/* Retrieve poll transmission and response reception timestamp. */
			poll_tx_ts = get_tx_timestamp_u64();
			resp_rx_ts = get_rx_timestamp_u64();

			/* Compute final message transmission time. See NOTE 9 below. */
			final_tx_time = (resp_rx_ts
					+ (RESP_RX_TO_FINAL_TX_DLY_UUS * UUS_TO_DWT_TIME))
			>> 8;
			dwt_setdelayedtrxtime(final_tx_time);

			/* Final TX timestamp is the transmission time we programmed plus the TX antenna delay. */
			final_tx_ts = (((uint64) (final_tx_time & 0xFFFFFFFE)) << 8)
			+ TX_ANT_DLY;

			/* Write all timestamps in the final message. See NOTE 10 below. */
			final_msg_set_ts(&tx_final_msg[FINAL_MSG_POLL_TX_TS_IDX],
					poll_tx_ts);
			final_msg_set_ts(&tx_final_msg[FINAL_MSG_RESP_RX_TS_IDX],
					resp_rx_ts);
			final_msg_set_ts(&tx_final_msg[FINAL_MSG_FINAL_TX_TS_IDX],
					final_tx_ts);

			/* Write and send final message. See NOTE 7 below. */
			tx_final_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
			dwt_writetxdata(sizeof(tx_final_msg), tx_final_msg, 0);
			dwt_writetxfctrl(sizeof(tx_final_msg), 0);
			dwt_starttx(DWT_START_TX_DELAYED);				// SEND FINAL MSG

			/* Poll DW1000 until TX frame sent event set. See NOTE 8 below. */
			timeout(10);
			PT_YIELD_UNTIL((dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS) || timeout());;
			/* Clear TXFRS event. */
			dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);

			/* Increment frame sequence number after transmission of the final message (modulo 256). */
			frame_seq_nb++;
		} else {
示例#12
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 {
示例#13
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 {
示例#14
0
/*! ------------------------------------------------------------------------------------------------------------------
 * @fn main()
 *
 * @brief Application entry point.
 *
 * @param  none
 *
 * @return none
 */
int ssTwrResp(void)
{

    /* Reset and initialise DW1000.
     * For initialisation, DW1000 clocks must be temporarily set to crystal speed. After initialisation SPI rate can be increased for optimum
     * performance. */
	int i;
	int status;

    reset_DW1000(); /* Target specific drive of RSTn line into DW1000 low for a period. */
    //spi_set_rate_low();
    dwt_initialise(DWT_LOADUCODE);
    //spi_set_rate_high();

    /* Configure DW1000. See NOTE 5 below. */
    dwt_configure(&config);

    uint32_t otpVal[0x20];
    dwt_otpread(0,otpVal,0x20);
    printf("OTP   6: 0x%x\r\n",otpVal[6]);
    printf("OTP   7: 0x%x\r\n",otpVal[7]);
    printf("OTP x16: 0x%x\r\n",otpVal[0x16]);
    printf("OTP x17: 0x%x\r\n",otpVal[0x17]);

    /* Apply default antenna delay value. See NOTE 2 below. */
    printf("antenna delays: default TX: %d, default RX: %d, evk 16m: %d, evk 64m: %d\r\n",TX_ANT_DLY,RX_ANT_DLY,DWT_RF_DELAY_16M,DWT_RF_DELAY_64M);
    tx_delay = TX_ANT_DLY;
    rx_delay = RX_ANT_DLY;
    dwt_setrxantennadelay(rx_delay);
    dwt_settxantennadelay(tx_delay);

    btn = buttons();


    printf("%s entering main loop\r\n",__FUNCTION__);
    /* Loop forever responding to ranging requests. */
    while (1)
    {
        /* Activate reception immediately. */
        dwt_rxenable(0);

        /* Poll for reception of a frame or error/timeout. See NOTE 6 below. */
        while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR)))
        { } ; //printf("Waiting. status reg 0x%x\r\n",status_reg); };
        //printf("Status reg now 0x%x\r\n",status_reg);

        if (status_reg & SYS_STATUS_RXFCG)
        {
            uint32 frame_len;

            //printf("Check RX\r\n");
            /* Clear good RX frame event in the DW1000 status register. */
            dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);

            /* A frame has been received, read it into the local buffer. */
            frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
            //printf("Frame length %d\r\n",frame_len);
            if (frame_len <= RX_BUFFER_LEN)
            {
                dwt_readrxdata(rx_buffer, frame_len, 0);
            }
            /*
            for (i=0;i<frame_len;i++) {
            	printf("%x ",rx_buffer[i]);
            }
        	printf("\r\n");
            */

            /* Check that the frame is a poll sent by "SS TWR initiator" example.
             * As the sequence number field of the frame is not relevant, it is cleared to simplify the validation of the frame. */
            rx_buffer[ALL_MSG_SN_IDX] = 0;
            if (memcmp(rx_buffer, rx_poll_msg, ALL_MSG_COMMON_LEN) == 0)
            {
                uint32 resp_tx_time;
                //printf("Poll MSG\r\n");

                /* Retrieve poll reception timestamp. */
                poll_rx_ts = get_rx_timestamp_u64();
                //printf("RX timestamp: %lld\r\n",poll_rx_ts);

                /* Compute final message transmission time. See NOTE 7 below. */
                resp_tx_time = (poll_rx_ts + (POLL_RX_TO_RESP_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8;
                dwt_setdelayedtrxtime(resp_tx_time);
                //printf("TX time: %d\r\n",resp_tx_time);

                /* Response TX timestamp is the transmission time we programmed plus the antenna delay. */
                resp_tx_ts = (((uint64)(resp_tx_time & 0xFFFFFFFE)) << 8) + TX_ANT_DLY;
                //printf("TX timestamp: %lld\r\n",resp_tx_ts);

                /* Write all timestamps in the final message. See NOTE 8 below. */
                resp_msg_set_ts(&tx_resp_msg[RESP_MSG_POLL_RX_TS_IDX], poll_rx_ts);
                resp_msg_set_ts(&tx_resp_msg[RESP_MSG_RESP_TX_TS_IDX], resp_tx_ts);

                /* Write and send the response message. See NOTE 9 below. */
                tx_resp_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
                status = dwt_writetxdata(sizeof(tx_resp_msg), tx_resp_msg, 0);
                if (DWT_SUCCESS != status) printf("API error line %d\r\n",__LINE__);
                status = dwt_writetxfctrl(sizeof(tx_resp_msg), 0);
                if (DWT_SUCCESS != status) printf("API error line %d\r\n",__LINE__);
                status = dwt_starttx(DWT_START_TX_DELAYED);
                if (DWT_SUCCESS != status) {
                	printf("API error line %d\r\n",__LINE__);
                    printf("RX timestamp: %llu\r\n",poll_rx_ts);
                    printf("TX time: %llu\r\n",((uint64)resp_tx_time) << 8);
                    printf("TX timestamp: %llu\r\n",resp_tx_ts);

                }

                // poll only if starttx was OK
                if (DWT_SUCCESS == status) {
					/* Poll DW1000 until TX frame sent event set. See NOTE 6 below. */
					u32 tx_stat;
					while (!(tx_stat = dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS))
					{ }; //printf("Waiting. status reg 0x%x\r\n",tx_stat); }
					//printf("After Poll: status reg now 0x%x\r\n",tx_stat);
                }

                /* Clear TXFRS event. */
                dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);

                /* Increment frame sequence number after transmission of the poll message (modulo 256). */
                frame_seq_nb++;
            }
        }