//ex_05a_ds_twr_init
#ifdef EX_05A_DEF
#include <string.h>
#include "deca_device_api.h"
#include "deca_regs.h"
//#include "lcd.h"
#include "deca_spi.h"
#include "port.h"
/* Example application name and version to display on LCD screen. */
#define APP_NAME "DS TWR INIT v1.2"
/* Inter-ranging delay period, in milliseconds. */
/*测距之间的延迟周期,以毫秒为单位*/
#define RNG_DELAY_MS 1000
/* Default communication configuration. We use here EVK1000's default mode (mode 3). */
static dwt_config_t config = {
2, /* Channel number. */
DWT_PRF_64M, /* Pulse repetition frequency.脉冲重复频率。 */
DWT_PLEN_1024, /* Preamble length. Used in TX only. */
DWT_PAC32, /* Preamble acquisition chunk size. Used in RX only. */
9, /* TX preamble code. Used in TX only. */
9, /* RX preamble code. Used in RX only. */
1, /* 0 to use standard SFD, 1 to use non-standard SFD. */
DWT_BR_110K, /* Data rate. */
DWT_PHRMODE_STD, /* PHY header mode. */
(1025 + 64 - 32) /* SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. */
};
/* Default antenna delay values for 64 MHz PRF. See NOTE 1 below. */
/*1.这些值的总和是TX到RX天线延迟,通过校准过程实验确定。在这里,我们使用硬编码的典型值,
*但在实际应用中,每个设备都应该有自己的天线延迟,以便在执行距离测量时获得最佳精度。*/
#define TX_ANT_DLY 16436
#define RX_ANT_DLY 16436
/* Frames used in the ranging process. See NOTE 2 below. */
/*NOTE 2 a poll message sent by the initiator发起者 to trigger the ranging exchange.
* - a response message sent by the responder响应者 allowing the initiator发起者 to go on with the process 继续这个过程
* - a final message sent by the initiator to complete the exchange and provide all information needed by the responder to compute the
* time-of-flight (distance) estimate估算.
* The first 10 bytes of those frame are common and are composed of the following fields:
* - byte 0/1: frame control (0x8841 to indicate a data frame using 16-bit addressing使用 16 位寻址数据帧).
* - byte 2: sequence number, incremented for each new frame.序列号按每个新帧递增
* - byte 3/4: PAN ID (0xDECA). 理解为组ID 相当于一个公司用的厂家标识,
* - byte 5/6: destination address, see NOTE 3 below. 目的地址
* NOTE 3.在此示例中,源地址和目标地址是硬编码常量,以保持简单,但对于实际产品,每个设备都应具有唯一的 ID。
* 在这里,16位寻址用于使消息尽可能短,但在实际应用中,只有在交换用于为参与范围交换的每个设备定义这些短地址的特定消息之后,才应执行此操作。
* - byte 7/8: source address, see NOTE 3 below. //源地址
* - byte 9: function code (specific values to indicate which message it is in the ranging process).
指示它在测距过程中的消息的特定值
* The remaining bytes are specific to each message as follows:
* Poll message:
* - no more data
* Response message:
* - byte 10: activity code (0x02 to tell the initiator发起人 to go on with the ranging exchange 继续测距交换).
* - byte 11/12: activity parameter 活动参数, not used here for activity code 0x02.
* Final message:
* - byte 10 -> 13: poll message transmission timestamp.
* - byte 14 -> 17: response message reception timestamp.
* - byte 18 -> 21: final message transmission timestamp.
* All messages end with a 2-byte checksum automatically set by DW1000.
*/
// wa目的地址ve源地址 0X21 功能码
static uint8 tx_poll_msg[] = {
0x41, 0x88, //使用 16 位寻址数据帧01
0, //帧的序号2
0xCA, 0xDE,//理解为厂家的ID 3 4
'W', 'A',//目的地址 5 6
'V', 'E', //源地址 7 8 实际产品,每个设备都应具有唯一的 ID
0x21, //指示它在测距过程中的消息的特定值9 我的理解是0X21表示 poll消息
0,0};//最后两个字节是校验和
static uint8 rx_resp_msg[] = {
0x41, 0x88, //使用 16 位寻址数据帧01
0,//帧的序列号2
0xCA, 0xDE, //理解为厂家的ID 3 4
'V', 'E',//目的地址 5 6
'W', 'A', //源地址 7 8 实际产品,每个设备都应具有唯一的 ID
0x10, //9 我的理解是0X10表示 resp消息
0x02, //10 0x02 告诉发起人继续测距交换,告诉对方我还需要你的响应 一般只用到resp帧
0, 0, //活动参数, not used here for activity code 0x02.
0, 0}; //最后两个字节是校验和
static uint8 tx_final_msg[] = {
0x41, 0x88, //使用 16 位寻址数据帧01
0, //帧的序列号2
0xCA, 0xDE, //理解为厂家的ID 3 4
'W', 'A',//目的地址 5 6
'V', 'E', //源地址 7 8 实际产品,每个设备都应具有唯一的 ID
0x23, //9 我的理解是0x23表示 final消息
0, 0, 0, 0, //10-13 poll时间戳
0, 0, 0, 0, //14-17 resp时间戳
0, 0, 0, 0, //18-21 final时间戳
0, 0}; //最后两个字节是校验和
/* Length of the common part of the message (up to and including the function code, see NOTE 2 below). */
/*消息公共部分的长度(包括功能代码,请参阅下面的注释 2)*/
#define ALL_MSG_COMMON_LEN 10
/* Indexes to access some of the fields in the frames defined above. */
/*用于访问上面定义的框架中的某些字段的索引*/
#define ALL_MSG_SN_IDX 2 //消息序列号的索引
#define FINAL_MSG_POLL_TX_TS_IDX 10 //final消息中的 poll时间戳开始
#define FINAL_MSG_RESP_RX_TS_IDX 14//final消息中的 resp时间戳开始
#define FINAL_MSG_FINAL_TX_TS_IDX 18//final消息中的 final时间戳开始
#define FINAL_MSG_TS_LEN 4//final中时间戳的长度
/* Frame sequence number, incremented after each transmission. */
static uint8 frame_seq_nb = 0;
/*Buffer to store received response message.
* Its size is adjusted to longest frame that this example code is supposed to handle.
* 它的大小调整为此示例代码应该处理的最长帧 */
#define RX_BUF_LEN 20
static uint8 rx_buffer[RX_BUF_LEN];
/*
*Hold copy of status register state here for reference so that it can be examined at a debug breakpoint.
*在此处保存状态寄存器状态的副本以供参考,以便可以在调试断点处对其进行检查。
*/
static uint32 status_reg = 0;
/* UWB microsecond (uus) to device time unit (dtu, around 15.65 ps) conversion factor.
* 1 uus = 512 / 499.2 祍 and 1 祍 = 499.2 * 128 dtu. */
#define UUS_TO_DWT_TIME 65536
/* Delay between frames, in UWB microseconds. See NOTE 4 below. */
/*4.此处选择了帧之间的延迟,以确保发起方和响应方之间帧的传输和接收正确同步,
并确保计算距离的正确精度。用户可参阅 DecaRangerangeARM 源代码指南,
了解有关测距过程中涉及的时间的更多详细信息。*/
/* 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.
*这是从帧传输结束到接收器使能的延迟,已针对 DW1000 的等待响应功能进行编程*/
#define POLL_TX_TO_RESP_RX_DLY_UUS 300//我的理解是poll发送到resp接收之间的延时
/* This is the delay from Frame RX timestamp to TX reply timestamp used for calculating/setting the DW1000's delayed TX function. This includes the
* frame length of approximately 2.66 ms with above configuration.
*这是从resp帧 RX 时间戳到 final的TX时间戳的延迟,用于计算/设置 DW1000 的延迟 TX 函数。这包括上述配置下大约 2.66 毫秒的帧长度。
*/
#define RESP_RX_TO_FINAL_TX_DLY_UUS 3100
/* Receive response timeout. See NOTE 5 below.
* 5.此超时用于完全接收帧,即超时持续时间必须考虑预期帧的长度。这里的值
*是任意的,但选择足够大,以确保有足够的时间接收响应方以使用的 110k 数据速率(大约 3 毫秒)发送的完整响应帧。
*/
#define RESP_RX_TIMEOUT_UUS 2700 //发送完poll后等待resp的最长时间
/* Preamble timeout, in multiple of PAC size. See NOTE 6 below.
* 6.前导码超时允许接收方在报头未启动的情况下停止侦听
(这可能是因为响应方超出范围或未收到要响应的消息)。这样可以节省监听未传入消息的电力浪费。
对于短距离应用,我们建议最小前导码超时为 5 个 PAC,对于更具挑战性的长距离、NLOS 或嘈杂环境,
我们建议使用更大的值(例如,在前导码长度的 50% 到 80% 范围内)。 */
#define PRE_TIMEOUT 8
/* Time-stamps of frames transmission/reception, expressed in device time units.
* As they are 40-bit wide, we need to define a 64-bit int type to handle them.
*帧传输/接收的时间戳,以设备时间单位表示。由于它们是 40 位宽的,
我们需要定义一个 64 位的 int 类型来处理它们。
*/
//typedef unsigned long long uint64;
static uint64 poll_tx_ts;
static uint64 resp_rx_ts;
static uint64 final_tx_ts;
/* Declaration of static functions. */
static uint64 get_tx_timestamp_u64(void);
static uint64 get_rx_timestamp_u64(void);
static void final_msg_set_ts(uint8 *ts_field, uint64 ts);
/*! ------------------------------------------------------------------------------------------------------------------
* @fn main()
*
* @brief Application entry point.
*
* @param none
*
* @return none
*/
int dw_main(void)
{
/* Display application name on LCD. */
//lcd_display_str(APP_NAME);
/* 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. */
reset_DW1000(); /* Target specific drive of RSTn line into DW1000 low for a period. */
port_set_dw1000_slowrate();
if (dwt_initialise(DWT_LOADUCODE) == DWT_ERROR)
{
// lcd_display_str("INIT FAILED");
while (1)
{ };
}
dwt_setlnapamode(DWT_LNA_ENABLE | DWT_PA_ENABLE);//enable GPIO5 GPIO6
dwt_setfinegraintxseq(0);
port_set_dw1000_fastrate();
/* Configure DW1000. See NOTE 7 below. */
/* 7.在实际应用中,为了在监管限制范围内获得最佳性能,
*可能需要将 TX 脉冲带宽和 TX 功率(使用 dwt_configuretxrf API 调用)设置为目标系统或 DW1000 OTP 存储器中保存的每个设备的校准值。*/
dwt_configure(&config);
/* Apply default antenna delay value. See NOTE 1 below. */
/*1. 这些值的总和是 TX 到 RX 天线延迟,由校准过程通过实验确定。
*这里我们使用硬编码的典型值,但在实际应用中,
*每个设备都应正确校准自己的天线延迟,以便在执行距离测量时获得最佳精度。*/
dwt_setrxantennadelay(RX_ANT_DLY);
dwt_settxantennadelay(TX_ANT_DLY);
/* Set expected response's delay and timeout. See NOTE 4, 5 and 6 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. */
/*请参阅下面的注释 4、5 和 6。由于此示例仅处理一个始终具有相同延迟和超时的传入帧,因此可以在此处为所有值设置一次*/
/* 4.此处选择了帧之间的延迟,以确保发起方和响应方之间帧的传输和接收正确同步,并确保计算距离的正确精度。
*用户可参阅 DecaRangerangeARM 源代码指南,了解有关测距过程中涉及的时间的更多详细信息。*/
/* 5.此超时用于完全接收帧,即超时持续时间必须考虑预期帧的长度。这里的值是任意的,但选择得足够大,
以确保有充足的时间接收响应者以使用的 110k 数据速率(大约 3 毫秒)发送的完整的RESP帧。*/
/* 6.前导码超时允许接收方在报头未启动的情况下停止侦听(这可能是因为响应方超出范围或未收到要响应的消息)。这样可以节省监听未传入消息的电力浪费。
*对于短距离应用,我们建议最小前导码超时为 5 个 PAC,对于更具挑战性的长距离、NLOS 或嘈杂环境,我们建议使用更大的值(例如,在前导码长度的 50% 到 80% 范围内).
*/
/*这将设置接收在帧发送后的开启延迟时间POLL_TX第一次发送的帧,RESP_RX是发送后的接收的帧*/
dwt_setrxaftertxdelay(POLL_TX_TO_RESP_RX_DLY_UUS);//我的理解是poll发送后开启resp接收的延迟时间.
//接收超时
dwt_setrxtimeout(RESP_RX_TIMEOUT_UUS); //并设定resp接收的超时时间
//设置前导码检测超时,超过这个时间dw1000进入休眠
dwt_setpreambledetecttimeout(PRE_TIMEOUT);
/* Loop forever initiating ranging exchanges. */
while (1)
{
/* Write frame data to DW1000 and prepare transmission. See NOTE 8 below. */
/* 8.dwt_writetxdata()将消息的完整大小作为参数,但仅复制(大小 - 2)字节,因为帧末尾的校验和由 DW1000 自动追加。
*这意味着我们的变量可以短两个字节而不会丢失任何数据(但是 sizeof 将不再起作用,因为我们仍然必须向 dwt_writetxdata()指示帧的完整长度)。*/
tx_poll_msg[ALL_MSG_SN_IDX] = frame_seq_nb;//帧的序号 实际项目中,每次发送都要叠加,
dwt_writetxdata(sizeof(tx_poll_msg), tx_poll_msg, 0); /* Zero offset in TX buffer. 主备发送poll帧 */
/*写发送帧控制寄存器:::发送前要配置发送帧控制寄存器,要发送的帧长度 如果是测距帧 第三个参数为1*/
dwt_writetxfctrl(sizeof(tx_poll_msg), 0, 1); /* Zero offset in TX buffer, ranging. */
/* 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. */
/*开始传输,表示预期响应,以便在发送帧后自动启用接收,并且 dwt_setrxaftertxdelay() 设置的延迟已过。*/
dwt_starttx(DWT_START_TX_IMMEDIATE | DWT_RESPONSE_EXPECTED);//立即发送,期望收到RESP帧
/* We assume that the transmission is achieved correctly, poll for reception of a frame or error/timeout. See NOTE 9 below. */
/*我们假设传输正确实现,轮询接收帧或错误/超时。见下文注9。*/
/* 9.我们在这里使用轮询操作模式,以使示例尽可能简单,但所有状态事件都可用于生成中断。有关“中断”的更多详细信息,请参阅 DW1000 用户手册。
*还需要注意的是,STATUS寄存器的长度为 5 个字节,但由于我们使用的事件都在寄存器的第一个字节中,
*因此我们可以使用简单的 dwt_read32bitreg() API 调用来访问它,而不是读取整个 5 个字节。*/
while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR)))
{ };
/* Increment frame sequence number after transmission of the poll message (modulo 256). */
/*在传输轮询消息后增加帧序列号(模 256)*/
frame_seq_nb++;
if (status_reg & SYS_STATUS_RXFCG)//如果是接收到了正确的完整的帧
{
uint32 frame_len;
/* Clear good RX frame event and TX frame sent in the DW1000 status register. */
/*清除 DW1000 状态寄存器中发送的良好 RX 帧事件和 TX 帧。*/
/*Transmit Frame Sent: This is set when the transmitter has completed the sending of a frame
*SYS_STATUS_TXFRS 一个帧被发送完毕后,这个SYS_STATUS_TXFRS会被置位
*/
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)//如果帧长度小于20
{
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. */
/*检查帧是否是配套“DS TWR responder”示例的预期响应。由于帧的序列号字段不相关,因此清除该字段以简化帧的验证*/
rx_buffer[ALL_MSG_SN_IDX] = 0;//清除接收帧中的帧序列号. 为了实验简单.
if (memcmp(rx_buffer, rx_resp_msg, ALL_MSG_COMMON_LEN) == 0)//对比前10个 字节,接收帧和本地的resp帧公共部分是否一致.
{
uint32 final_tx_time;//如果一致, 表示接收的帧,是我想要的,否则过滤掉.
int ret;
/* Retrieve poll transmission and response reception timestamp. */
/*检索轮询传输和响应接收时间戳。*/
poll_tx_ts = get_tx_timestamp_u64();//获取POLL时间戳 对应T1
resp_rx_ts = get_rx_timestamp_u64();//获取RESP时间戳 对应T4
/* Compute final message transmission time. See NOTE 10 below. */
/*计算最终消息传输时间。见下文注10。*/
/* 10.由于我们想在最终消息中发送最终的TX时间戳,我们必须提前计算它,而不是依赖于DW1000寄存器的读取。
*时间戳和延迟传输时间都以设备时间单位表示,因此我们只需将所需的响应延迟添加到响应 RX 时间戳即可获得最终传输时间。
*延迟传输时间分辨率为 512 个设备时间单位,这意味着所获得值的较低 9 位必须归零。
*这也允许通过将全零的低 8 位移动来对 32 位字中的 40 位值进行编码。*/
final_tx_time = (resp_rx_ts + (RESP_RX_TO_FINAL_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8; //resp接收时间戳到+RESP_RX_TO_FINAL_TX_DLY_UUS对应的延迟,
/*此API函数按时配置延迟传输时间或延迟 RX*/
dwt_setdelayedtrxtime(final_tx_time);//计算发送final的时间
/* Final TX timestamp is the transmission time we programmed plus the TX antenna delay. */
/*最终的TX时间戳是我们编程的传输时间加上TX天线延迟。*/
final_tx_ts = (((uint64)(final_tx_time & 0xFFFFFFFEUL)) << 8) + TX_ANT_DLY;//加天线的发送延时才是真正的final发送时间戳
/* Write all timestamps in the final message. See NOTE 11 below. */
/*在最后一条消息中写入所有时间戳。见下文注11。*/
/* 11.在此操作中,将丢弃每个 40 位时间戳的高位字节。这是可以接受的,
*因为这些时间戳之间的间隔不超过 2**32 个设备时间单位(大约 67 毫秒),
*这意味着往返延迟的计算(飞行时间计算中需要)可以通过 32 位减法来处理。*/
/*最后的消息中, 写入所有时间戳 */
final_msg_set_ts(&tx_final_msg[FINAL_MSG_POLL_TX_TS_IDX], poll_tx_ts); //在final发送帧中装入三个时间戳
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 8 below. */
/*8.dwt_writetxdata() 将消息的完整大小作为参数,但仅复制(大小 - 2)字节,以为最后两个字节是校验和
*因为帧末尾的校验和是由 DW1000 自动追加。这意味着我们的变量可以短两个字节而不会丢失任何数据(
*但是 sizeof 将不再起作用,因为我们仍然必须向 dwt_writetxdata()指示帧的完整长度)。*/
tx_final_msg[ALL_MSG_SN_IDX] = frame_seq_nb;//消息序号
dwt_writetxdata(sizeof(tx_final_msg), tx_final_msg, 0); /* Zero offset in TX buffer. */
/*此 API 函数在传输帧之前配置 TX 帧控制寄存器*/
//第三个参数1,表示这是个测距帧.
dwt_writetxfctrl(sizeof(tx_final_msg), 0, 1); /* Zero offset in TX buffer, ranging. */
ret = dwt_starttx(DWT_START_TX_DELAYED);//实际就是T4-T5之间的延时
/* If dwt_starttx() returns an error, abandon this ranging exchange and proceed to the next one. See NOTE 12 below. */
/*如果 dwt_starttx() 返回错误,请放弃此测距交换并继续下一个交换。见下文注12。*/
/*12.在提供RESP_RX_TO_FINAL_TX_DLY响应延迟的EVB1000平台上运行此示例时,dwt_starttx()始终成功。
*但是,如果延迟太短(或其他原因中断了代码流),则 dwt_starttx() 对于配置的开始时间来说可能太晚了。
*下面的代码提供了如何处理这种情况的示例: 在这种情况下,它会放弃测距交换,在 1 秒后尝试另一个交换。
*如果此错误处理代码不在此处,则延迟的 dwt_starttx() 将导致代码流卡住,等待永远不会发生的 TX 帧发送事件。
*配套的“响应者”示例 (ex_05b) 应从等待“最终”中超时,并继续使其接收方准备好轮询以下交换*/
if (ret == DWT_SUCCESS)
{
/* Poll DW1000 until TX frame sent event set. See NOTE 9 below. */
/*9.我们在这里使用轮询操作模式,以使示例尽可能简单,
*但所有状态事件都可用于生成中断。有关“中断”的更多详细信息,
*请参阅 DW1000 用户手册。还需要注意的是,STATUS 寄存器的长度为 5 个字节,
*但由于我们使用的事件都在寄存器的第一个字节中,因此我们可以使用简单的 dwt_read32bitreg() API 调用来访问它,
*而不是读取整个 5 个字节。*/
//SYS_STATUS_TXFRS:这是在发射器完成帧发送时设置的 等待发送帧完全发送完成.
while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS))
{ };
/* Clear TXFRS event 清除帧发送完成事件标志位. 这是在发射器完成帧发送时设置的. */
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);
/* Increment frame sequence number after transmission of the final message (modulo 256). */
/*传输完毕 final 消息后递增帧序列号(模数 256)*/
frame_seq_nb++;
}
}
}
else
{
/* Clear RX error/timeout events in the DW1000 status register. */
/*清除 DW1000 状态寄存器中的 RX 错误/超时事件*/
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR);
/* Reset RX to properly reinitialise LDE operation. */
/*重置 RX 以正确重新初始化 LDE 操作*/
dwt_rxreset();
}
/* Execute a delay between ranging exchanges. */
Sleep(RNG_DELAY_MS); /*在测距交换之间执行延迟*/
}
}
/*! ------------------------------------------------------------------------------------------------------------------
* @fn get_tx_timestamp_u64()
*
* @brief Get the TX time-stamp in a 64-bit variable.
* /!\ This function assumes that length of time-stamps is 40 bits, for both TX and RX!
*
* @param none
*
* @return 64-bit value of the read time-stamp.
*/
static uint64 get_tx_timestamp_u64(void)
{
uint8 ts_tab[5];
uint64 ts = 0;
int i;
dwt_readtxtimestamp(ts_tab);
for (i = 4; i >= 0; i--)
{
ts <<= 8;
ts |= ts_tab[i];
}
return ts;
}
/*! ------------------------------------------------------------------------------------------------------------------
* @fn get_rx_timestamp_u64()
*
* @brief Get the RX time-stamp in a 64-bit variable.
* /!\ This function assumes that length of time-stamps is 40 bits, for both TX and RX!
*
* @param none
*
* @return 64-bit value of the read time-stamp.
*/
static uint64 get_rx_timestamp_u64(void)
{
uint8 ts_tab[5];
uint64 ts = 0;
int i;
dwt_readrxtimestamp(ts_tab);
for (i = 4; i >= 0; i--)
{
ts <<= 8;
ts |= ts_tab[i];
}
return ts;
}
/*! ------------------------------------------------------------------------------------------------------------------
* @fn final_msg_set_ts()
*
* @brief Fill a given timestamp field in the final message with the given value. In the timestamp fields of the final
* message, the least significant byte is at the lower address.
使用给定值填充最终消息中的给定时间戳字段。在最终的时间戳字段中
消息,最低有效字节位于较低的地址。
*
* @param ts_field pointer on the first byte of the timestamp field to fill
* ts timestamp value
*
* @return none
*/
static void final_msg_set_ts(uint8 *ts_field, uint64 ts)
{
int i;
for (i = 0; i < FINAL_MSG_TS_LEN; i++)
{
ts_field[i] = (uint8) ts;
ts >>= 8;
}
}
#endif
/*****************************************************************************************************************************************************
* NOTES:
*
* 1. The sum of the values is the TX to RX antenna delay, experimentally determined by a calibration process. Here we use a hard coded typical value
* but, in a real application, each device should have its own antenna delay properly calibrated to get the best possible precision when performing
* range measurements.
* 2. The messages here are similar to those used in the DecaRanging ARM application (shipped with EVK1000 kit). They comply with the IEEE
* 802.15.4 standard MAC data frame encoding and they are following the ISO/IEC:24730-62:2013 standard. The messages used are:
* - a poll message sent by the initiator to trigger the ranging exchange.
* - a response message sent by the responder allowing the initiator to go on with the process
* - a final message sent by the initiator to complete the exchange and provide all information needed by the responder to compute the
* time-of-flight (distance) estimate.
* The first 10 bytes of those frame are common and are composed of the following fields:
* - byte 0/1: frame control (0x8841 to indicate a data frame using 16-bit addressing).
* - byte 2: sequence number, incremented for each new frame.
* - byte 3/4: PAN ID (0xDECA).
* - byte 5/6: destination address, see NOTE 3 below.
* - byte 7/8: source address, see NOTE 3 below.
* - byte 9: function code (specific values to indicate which message it is in the ranging process).
* The remaining bytes are specific to each message as follows:
* Poll message:
* - no more data
* Response message:
* - byte 10: activity code (0x02 to tell the initiator to go on with the ranging exchange).
* - byte 11/12: activity parameter, not used here for activity code 0x02.
* Final message:
* - byte 10 -> 13: poll message transmission timestamp.
* - byte 14 -> 17: response message reception timestamp.
* - byte 18 -> 21: final message transmission timestamp.
* All messages end with a 2-byte checksum automatically set by DW1000.
* 3. Source and destination addresses are hard coded constants in this example to keep it simple but for a real product every device should have a
* unique ID. Here, 16-bit addressing is used to keep the messages as short as possible but, in an actual application, this should be done only
* after an exchange of specific messages used to define those short addresses for each device participating to the ranging exchange.
* 4. Delays between frames have been chosen here to ensure proper synchronisation of transmission and reception of the frames between the initiator
* and the responder and to ensure a correct accuracy of the computed distance. The user is referred to DecaRanging ARM Source Code Guide for more
* details about the timings involved in the ranging process.
* 5. This timeout is for complete reception of a frame, i.e. timeout duration must take into account the length of the expected frame. Here the value
* is arbitrary but chosen large enough to make sure that there is enough time to receive the complete response frame sent by the responder at the
* 110k data rate used (around 3 ms).
* 6. The preamble timeout allows the receiver to stop listening in situations where preamble is not starting (which might be because the responder is
* out of range or did not receive the message to respond to). This saves the power waste of listening for a message that is not coming. We
* recommend a minimum preamble timeout of 5 PACs for short range applications and a larger value (e.g. in the range of 50% to 80% of the preamble
* length) for more challenging longer range, NLOS or noisy environments.
* 7. In a real application, for optimum performance within regulatory limits, it may be necessary to set TX pulse bandwidth and TX power, (using
* the dwt_configuretxrf API call) to per device calibrated values saved in the target system or the DW1000 OTP memory.
* 8. dwt_writetxdata() takes the full size of the message as a parameter but only copies (size - 2) bytes as the check-sum at the end of the frame is
* automatically appended by the DW1000. This means that our variable could be two bytes shorter without losing any data (but the sizeof would not
* work anymore then as we would still have to indicate the full length of the frame to dwt_writetxdata()).
* 9. We use polled mode of operation here to keep the example as simple as possible but all status events can be used to generate interrupts. Please
* refer to DW1000 User Manual for more details on "interrupts". It is also to be noted that STATUS register is 5 bytes long but, as the event we
* use are all in the first bytes of the register, we can use the simple dwt_read32bitreg() API call to access it instead of reading the whole 5
* bytes.
* 10. As we want to send final TX timestamp in the final message, we have to compute it in advance instead of relying on the reading of DW1000
* register. Timestamps and delayed transmission time are both expressed in device time units so we just have to add the desired response delay to
* response RX timestamp to get final transmission time. The delayed transmission time resolution is 512 device time units which means that the
* lower 9 bits of the obtained value must be zeroed. This also allows to encode the 40-bit value in a 32-bit words by shifting the all-zero lower
* 8 bits.
* 11. In this operation, the high order byte of each 40-bit timestamps is discarded. This is acceptable as those time-stamps are not separated by
* more than 2**32 device time units (which is around 67 ms) which means that the calculation of the round-trip delays (needed in the
* time-of-flight computation) can be handled by a 32-bit subtraction.
* 12. When running this example on the EVB1000 platform with the RESP_RX_TO_FINAL_TX_DLY response delay provided, the dwt_starttx() is always
* successful. However, in cases where the delay is too short (or something else interrupts the code flow), then the dwt_starttx() might be issued
* too late for the configured start time. The code below provides an example of how to handle this condition: In this case it abandons the
* ranging exchange to try another one after 1 second. If this error handling code was not here, a late dwt_starttx() would result in the code
* flow getting stuck waiting for a TX frame sent event that will never come. The companion "responder" example (ex_05b) should timeout from
* awaiting the "final" and proceed to have its receiver on ready to poll of the following exchange.
* 13. The user is referred to DecaRanging ARM application (distributed with EVK1000 product) for additional practical example of usage, and to the
* DW1000 API Guide for more details on the DW1000 driver functions.
****************************************************************************************************************************************************/