// Called at the beginning of each listening window for transmitting to // the tag. static void ranging_listening_window_task () { // Check if we are done transmitting to the tag. // Ideally we never get here, as an ack from the tag will cause us to stop // cycling through listening windows and put us back into a ready state. if (_ranging_listening_window_num == NUM_RANGING_CHANNELS) { // Go back to IDLE _state = ASTATE_IDLE; // Stop the timer for the window timer_stop(_anchor_timer); // Restart being an anchor oneway_anchor_start(); } else { // Setup the channel and antenna settings oneway_set_ranging_listening_window_settings(ANCHOR, _ranging_listening_window_num, pp_anc_final_pkt.final_antenna); // Prepare the outgoing packet to send back to the // tag with our TOAs. pp_anc_final_pkt.ieee154_header_unicast.seqNum++; const uint16_t frame_len = sizeof(struct pp_anc_final); // const uint16_t frame_len = sizeof(struct pp_anc_final) - (sizeof(uint64_t)*NUM_RANGING_BROADCASTS); dwt_writetxfctrl(frame_len, 0); // Pick a slot to respond in. Generate a random number and mod it // by the number of slots uint8_t slot_num = ranval(&_prng_state) % (_ranging_operation_config.anchor_reply_window_in_us / _ranging_operation_config.anchor_reply_slot_time_in_us); // Come up with the time to send this packet back to the // tag based on the slot we picked. uint32_t delay_time = dwt_readsystimestamphi32() + DW_DELAY_FROM_US(ANC_FINAL_INITIAL_DELAY_HACK_VALUE + (slot_num*_ranging_operation_config.anchor_reply_slot_time_in_us)); delay_time &= 0xFFFFFFFE; // Record the outgoing time in the packet. Do not take calibration into // account here, as that is done on all of the RX timestamps. pp_anc_final_pkt.dw_time_sent = (((uint64_t) delay_time) << 8); // Set the packet to be transmitted later. dwt_setdelayedtrxtime(delay_time); // Send the response packet // TODO: handle if starttx errors. I'm not sure what to do about it, // other than just wait for the next slot. dwt_starttx(DWT_START_TX_DELAYED); dwt_settxantennadelay(DW1000_ANTENNA_DELAY_TX); dwt_writetxdata(frame_len, (uint8_t*) &pp_anc_final_pkt, 0); _ranging_listening_window_num++; } }
// Called at the beginning of each listening window for transmitting to // the tag. static void ranging_listening_window_task () { // Check if we are done transmitting to the tag. // Ideally we never get here, as an ack from the tag will cause us to stop // cycling through listening windows and put us back into a ready state. if (_ranging_listening_window_num == NUM_RANGING_CHANNELS) { // Go back to IDLE _state = ASTATE_IDLE; // Stop the timer for the window timer_stop(_ranging_broadcast_timer); } else { // Setup the channel and antenna settings dw1000_set_ranging_listening_window_settings(ANCHOR, _ranging_listening_window_num, pp_anc_final_pkt.final_antenna, FALSE); // Prepare the outgoing packet to send back to the // tag with our TOAs. pp_anc_final_pkt.ieee154_header_unicast.seqNum++; const uint16_t frame_len = sizeof(struct pp_anc_final); dwt_writetxfctrl(frame_len, 0); // Pick a slot to respond in. Generate a random number and mod it // by the number of slots uint8_t slot_num = ranval(&_prng_state) % (_ranging_operation_config.anchor_reply_window_in_us / _ranging_operation_config.anchor_reply_slot_time_in_us); // Come up with the time to send this packet back to the // tag based on the slot we picked. uint32_t delay_time = dwt_readsystimestamphi32() + DW_DELAY_FROM_US(ANC_FINAL_INITIAL_DELAY_HACK_VALUE + (slot_num*_ranging_operation_config.anchor_reply_slot_time_in_us)); delay_time &= 0xFFFFFFFE; pp_anc_final_pkt.dw_time_sent = delay_time; dwt_setdelayedtrxtime(delay_time); // Send the response packet int err = dwt_starttx(DWT_START_TX_DELAYED); dwt_settxantennadelay(DW1000_ANTENNA_DELAY_TX); dwt_writetxdata(frame_len, (uint8_t*) &pp_anc_final_pkt, 0); _ranging_listening_window_num++; } }
// 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 {