【DWM1000】 code 解密8一 TAG接收blink response 信号
在分析这个部分前,目前我看到DWM1000 的资料,data可以分为blink和一般无线数据,后面有内容我们再扩充, 上面我们已经看到接收到blink触发的事件为
|
case SIG_RX_BLINK : |
一般数据包应该触发的的是
|
case DWT_SIG_RX_OKAY : |
表示接收到一个无线无线数据包,具体怎么解析这个数据包我们一点点分析。
好了,看TAG收到ANCHOR的blink response,这个数据包为一般数据包,具体数据内容我们前面简单列出来了,这里从TAG接收的角度一点点在分析。
好了,还是上代码
|
event_data_t* dw_event = instance_getevent(15); //get and clear this event uint8 srcAddr[8] = {0,0,0,0,0,0,0,0}; int fcode = 0; int fn_code = 0; uint8 *messageData; inst->stoptimer = 0; //clear the flag, as we have received a message |
首先是获取事件getevent,这个应该是获取到接收数据成功的事件。后面紧随其后是一下变量的生命。后面看用到这些变量再看。
|
switch(dw_event->msgu.frame[1]) |
这个msgu.frame[1] 是啥内容,我们需要回到ANCHOR发送端看了
|
#if (USING_64BIT_ADDR == 1) inst->rng_initmsg.frameCtrl[1] = 0xCC; inst->psduLength += FRAME_CRTL_AND_ADDRESS_L + FRAME_CRC; #else |
我们接着摘录具体的代码
|
case 0xCC: // memcpy(&srcAddr[0], &(dw_event->msgu.rxmsg_ll.sourceAddr[0]), ADDR_BYTE_SIZE_L); fn_code = dw_event->msgu.rxmsg_ll.messageData[FCODE]; messageData = &dw_event->msgu.rxmsg_ll.messageData[0]; |
这个决定了我们从不同地方去srcAddr以及fn_code 和messageData。 后面用到这几个变量再看具体是什么内容
|
if(inst->mode == ANCHOR) { …… } else // LISTENER or TAG { fcode = fn_code; } |
接着后面看
|
switch(fcode) { case RTLS_DEMO_MSG_RNG_INIT: { |
原来fcode是这些家伙,我们再看看ANCHOR发送的时候fcode是什么吧
|
inst->rng_initmsg.messageData[FCODE] = RTLS_DEMO_MSG_RNG_INIT; |
正好是第一个case,直接在拉代码看看做了什么,没看代码前,我们根据发送时的数据(短地址以及两个delay)可以大概猜出来,TAG应该是保持这些数据,因为ANCHOR那边还在等着,所以应该还会发一个数据给ANCHOR。
好,上代码
先修改了两个非常重要的变量,我们记一下,等一会还会用到
|
inst->testAppState = TA_TXE_WAIT; inst->nextState = TA_TXPOLL_WAIT_SEND ; // send next poll |
后面就是从数据包提取短地址和两个delay
|
inst->tagShortAdd = messageData[RNG_INIT_TAG_SHORT_ADDR_LO] + (messageData[RNG_INIT_TAG_SHORT_ADDR_HI] << 8) ; // Get response delays from message and update internal timings accordingly resp_dly[RESP_DLY_ANC] = messageData[RNG_INIT_ANC_RESP_DLY_LO] + (messageData[RNG_INIT_ANC_RESP_DLY_HI] << 8); resp_dly[RESP_DLY_TAG] = messageData[RNG_INIT_TAG_RESP_DLY_LO] + (messageData[RNG_INIT_TAG_RESP_DLY_HI] << 8); |
其中短地址被保存到结构体instance中,而两个delay目前只保存到临时变量里。
后面两个delay在代码中进行了转换,最终计算出了两个delay保存到instance中了
|
// Update delay between poll transmission and response reception. inst->txToRxDelayTag_sy // Update delay between poll transmission and final transmission. inst->finalReplyDelay inst->finalReplyDelay_ms |
后面的inst->sleep_en = 0; 我们姑且认为是吧。 接着分析后面的代码
|
#if (USING_64BIT_ADDR == 1) memcpy(&inst->msg.destAddr[0], &srcAddr[0], ADDR_BYTE_SIZE_L); //set the anchor address for the reply (set destination address) #else |
看代码,用的是64bit 地址,前面分析srcAddr其实是源地址
|
memcpy(&srcAddr[0], &(dw_event->msgu.rxmsg_ll.sourceAddr[0]), ADDR_BYTE_SIZE_L); |
也就是ANCHOR的地址,我们可以看到执行
memcpy(&inst->msg.destAddr[0], &srcAddr[0], ADDR_BYTE_SIZE_L);
也就是destAddr[0]里面存放的ANCHOR的地址
接着看后面依然有个地址复制,我们先记录先来看看是否有用。
|
memcpy(&inst->relpyAddress[0], &srcAddr[0], ADDR_BYTE_SIZE_L); //remember who to send the reply to (set destination address) |
后面的代码就是几个变量的赋值了
|
inst->mode = TAG ; inst->instToSleep = 0; inst->instancetimer_saved = inst->instancetimer = portGetTickCount(); //set timer base |
然后退出testapprun_s,来回分析ANCHOR 和TAG已经忘记done的状态了,我们暂且认为不需要定时器,所以回很快再次进去testapprun_s。首先列一下重要变量
|
inst->testAppState = TA_TXE_WAIT; inst->nextState = TA_TXPOLL_WAIT_SEND ; // send next poll inst->mode = TAG ; |
然后在testapprun_s找案发现场
|
case TA_TXE_WAIT : //either go to sleep or proceed to TX a message //if we are scheduled to go to sleep before next sending then sleep first. if(((inst->nextState == TA_TXPOLL_WAIT_SEND) || (inst->nextState == TA_TXBLINK_WAIT_SEND)) && (inst->instToSleep) //go to sleep before sending the next poll ) { |
根据绿色标出的地方,可以看出,满足if判断
|
//the app should put chip into low power state and wake up in tagSleepTime_ms time... //the app could go to *_IDLE state and wait for uP to wake it up... inst->done = INST_DONE_WAIT_FOR_NEXT_EVENT_TO; //don't sleep here but kick off the TagTimeoutTimer (instancetimer) inst->testAppState = TA_SLEEP_DONE; if(inst->mode == TAG_TDOA) //once we start ranging we want to display the new range { ……不满足条件 } #if (DEEP_SLEEP == 1) 宏定义确实为1 if (inst->sleep_en) 上面我们假定这个参数为0 { ……不满足条件 } #endif //DW1000 gone to sleep - report the received range if(inst->tof > 0) //if ToF == 0 - then no new range to report { …… } |
后面的tof我们之前也没有遇到过,假定为0,也不满足。绕了一圈,发现其实这次进入到testapprun_s只设置两个两个重要变量
|
inst->done = INST_DONE_WAIT_FOR_NEXT_EVENT_TO; inst->testAppState = TA_SLEEP_DONE; |
根据之前分析,由于是INST_DONE_WAIT_FOR_NEXT_EVENT_TO,在instance_run 会开个定时器。我们认为溢出前会先进入testapprun_s,看看在TA_SLEEP_DONE 做了什么吧。接着找作案现场
|
case TA_SLEEP_DONE : { event_data_t* dw_event = instance_getevent(10); //clear the event from the queue // waiting for timout from application to wakup IC if (dw_event->type != DWT_SIG_RX_TIMEOUT) { // if no pause and no wake-up timeout continu waiting for the sleep to be done. inst->done = INST_DONE_WAIT_FOR_NEXT_EVENT; //wait here for sleep timeout break; } |
可以看出如果进来发现不是TIMEOUT,一直break,所以定时器一直需要等待溢出才执行后面的代码。
……等待定时器,等待定时器……溢出。好了,我们看后面的代码
|
inst->done = INST_NOT_DONE_YET; inst->instToSleep = 0; inst->testAppState = inst->nextState; inst->nextState = 0; //clear inst->instancetimer_saved = inst->instancetimer = portGetTickCount(); //set timer base |
有点尴尬nextState好像好久没用到,没事回头找代码
|
case RTLS_DEMO_MSG_RNG_INIT: { if(inst->mode == TAG_TDOA) //only start ranging with someone if not ranging already { uint32 final_reply_delay_us; uint32 resp_dly[RESP_DLY_NB]; int i; inst->testAppState = TA_TXE_WAIT; inst->nextState = TA_TXPOLL_WAIT_SEND ; // send next poll |
根据done = INST_NOT_DONE_YET;退出不加载定时器,根据TA_TXPOLL_WAIT_SEND 我们再找作案现场
|
case TA_TXPOLL_WAIT_SEND : //TAG:send poll message { |
这里主要是发送poll message给ANCHOR
与发送相关的代码
|
inst->msg.seqNum = inst->frame_sn++; setupmacframedata(inst, RTLS_DEMO_MSG_TAG_POLL); #if (USING_64BIT_ADDR==1) inst->psduLength = TAG_POLL_MSG_LEN + FRAME_CRTL_AND_ADDRESS_L + FRAME_CRC; #else dwt_writetxdata(inst->psduLength, (uint8 *) &inst->msg, 0) ; // write the frame data dwt_writetxfctrl(inst->psduLength, 0); dwt_starttx(DWT_START_TX_IMMEDIATE | inst->wait4ack); |
发送具体数据包在meg中了,我们现在具体不看,ANCHOR用到在看,反正是发送了,而且还是个DWT_RESPONSE_EXPECTED
|
inst->wait4ack = DWT_RESPONSE_EXPECTED; |
还设置了两个延时,tx后多久打开接收器等待应答,以及rx 的timeout
|
//set the delayed rx on time (the response message will be sent after this delay) dwt_setrxaftertxdelay(inst->txToRxDelayTag_sy); dwt_setrxtimeout((uint16)inst->fwtoTime_sy); |
发送完poll message等待应答需要转状态,保存重要变量
|
inst->testAppState = TA_TX_WAIT_CONF ; // wait confirmation inst->previousState = TA_TXPOLL_WAIT_SEND ; inst->done = INST_DONE_WAIT_FOR_NEXT_EVENT; //will use RX FWTO to time out (set below) |
根据done,知道退出后不需要启动定时器。
之前我们就分析过TA_TX_WAIT_CONF,不过这个函数会根据previousState有很多岔路,我们接着分析它
|
if(dw_event->type != DWT_SIG_TX_DONE) //wait for TX done confirmation { if(dw_event->type == DWT_SIG_RX_TIMEOUT) { ……没有启动定时器,所以不会执行到这里 } inst->done = INST_DONE_WAIT_FOR_NEXT_EVENT; break; } |
由这段代码可以看出,TAG一直不停的循环,直到等待DWT_SIG_TX_DONE,也就是DWM1000把数据包发送出去。
|
inst->done = INST_NOT_DONE_YET; else { inst->txu.txTimeStamp = dw_event->timeStamp; if(inst->previousState == TA_TXPOLL_WAIT_SEND) { |
可以看出,满足if 判断会接着执行后面的代码,后面很多代码都是计算poll message 发送时间的。
|
uint64 tagCalculatedFinalTxTime ; // Embed into Final message: 40-bit pollTXTime, 40-bit respRxTime, 40-bit finalTxTime tagCalculatedFinalTxTime = (inst->txu.txTimeStamp + inst->finalReplyDelay) & MASK_TXDTS; // time we should send the response inst->delayedReplyTime = tagCalculatedFinalTxTime >> 8; // Calculate Time Final message will be sent and write this field of Final message // Sending time will be delayedReplyTime, snapped to ~125MHz or ~250MHz boundary by // zeroing its low 9 bits, and then having the TX antenna delay added // getting antenna delay from the device and add it to the Calculated TX Time tagCalculatedFinalTxTime = tagCalculatedFinalTxTime + inst->txantennaDelay; tagCalculatedFinalTxTime &= MASK_40BIT; // Write Calculated TX time field of Final message memcpy(&(inst->msg.messageData[FTXT]), (uint8 *)&tagCalculatedFinalTxTime, 5); // Write Poll TX time field of Final message memcpy(&(inst->msg.messageData[PTXT]), (uint8 *)&inst->txu.tagPollTxTime, 5); |
这几个时间我们后面在分析,我们先看代码
|
inst->testAppState = TA_RXE_WAIT ; message = 0; //break ; // end case TA_TX_WAIT_CONF case TA_RXE_WAIT : //enable rx,and wait to recive a message |
接着会执行TA_RXE_WAIT ,根据之前的分析结果,这里只是打开接收器等到数据,所以到此为止,TAG又开始等待了,等待ANCHOR回复。
总结一下该小段: TAG发送poll message给ANCHOR后进入等待状态,ANCHOR应该此时接收数据并回复TAG。
【DWM1000】 code 解密8一 TAG接收blink response 信号的更多相关文章
- 【DWM1000】 code 解密10 一 TAG 发送最后一个消息
更上面ANCHOR发送信息时的RTLS_DEMO_MSG_ANCH_RESP, 我们很快就可以找到如下代码 case RTLS_DEMO_MSG_ANCH_RESP: { 这里面一部分是设置重要变量, ...
- 【DWM1000】 code 解密6一TAG 状态机第一步
我们前面分析过,不论ANCHOR 还是TAG,前面变量的初始化基本都是一样的,只是状态机必须明确区分不同的设备类型.我们从开始看TAG.由于初始化TAG的 testAppState一样初始化为TA_I ...
- 【DWM1000】 code 解密7一ANCHOR接收到BLINK
接着之前ANCHOR的代码分析,但接收到无线数据,应该执行如下代码 case TA_RX_WAIT_DATA : //already recive a message ...
- 底层由于接收到操作系统的信号而停止(the inferior stopped because it triggered an exception)
QT开发内存管理问题: 在linux上提示:底层由于接收到操作系统的信号而停止: 在windows上提示:the inferior stopped because it triggered an ex ...
- 【DWM1000】 code 解密2一 工程初始化代码分析
instance_init 函数追下去,绝大多数的代码都在初始化如下结构体 typedef struct { INST_MODE mode; instance_init -ANCHOR //insta ...
- 【DWM1000】 code 解密1一 去掉Main 函数多余内容
蓝点DWM1000 模块已经打样测试完毕,有兴趣的可以申请购买了,更多信息参见 蓝点论坛 正文: 室内定位兴起,DWM1000 作为超宽带UWB的代表,在国内用的越来越多,但是可见资料非常少. 一方面 ...
- 【DWM1000】 code 解密9一 ANCHOR response poll message
根据上面TAG发送的代码,我直接找到如下代码 case RTLS_DEMO_MSG_TAG_POLL: { if(inst->mode == LISTENER) ...
- 【DWM1000】 code 解密3一ANCHOR RUN起来
int done = INST_NOT_DONE_YET; #define INST_DONE_WAIT_FOR_NEXT_EVENT 1 //this signifies that the curr ...
- 【DWM1000】 code 解密5一ACHOR 第一次回家Main 函数
instance_run(); if((instance_data[0].monitor == 1) && ((portGetTickCnt() - instance_data[0]. ...
随机推荐
- 给servlet类添加源代码
1.按住ctrl键不放.鼠标左键点击HttpServlet. 2.打开 https://mvnrepository.com/下载所需的jar包,要下载带-sources后缀的 3.点击按钮附加源代码 ...
- cnetos 7 mariadb 集群报错分析解答
1.故障1:通过查看/var/log/message 发现报错 2017-04-14 14:44:10 139845276428544 [ERROR] WSREP: It may not be saf ...
- hive和hbase比较(整理)
hive1.可以理解为一种SQL执行引擎,对SQL的支持最终转换为map/reduce任务2.不支持更新.删除操作,但可以插入3.任务不是实时执行,用时一般为数分钟到数小时4.本身可以不存储数据,只存 ...
- 去掉A标签的点击选中边框
非IE a:focus { outline:none; }
- Android实时取景:用SurfaceView实现
对于基于摄像头的Android应用,实时取景是一个基本前提,通过前置或后置摄像头持续获取捕获到的内容,可以进一步做处理(人脸检测.美颜.滤镜等). 所谓实时取景,简单说就是调用android的摄像头, ...
- 如何让微信里的html应用弹出“点击右上角分享到朋友圈”的图片
一个分享按钮,一个隐藏的图片(这个图片绝对定位在右上角)然后就是点击显示,点击隐藏了... <a href="javascript:;" onclick="docu ...
- [转] Webpack的devtool和source maps
source maps Webpack打包生成的.map后缀文件,使得我们的开发调试更加方便,它能帮助我们链接到断点对应的源代码的位置进行调试(//# souceURL),而devtool就是用来指定 ...
- 实际生产用法CMS和G1
java -Xms100m -Xmx100m -Xmn50m -XX:MetaspaceSize=20m -XX:MaxMetaspaceSize=20m -XX:+UseConcMarkSweepG ...
- Python学习(十三) —— 网络编程
一.操作系统基础 操作系统(Operating System):OS是管理和控制计算机硬件和软件资源的计算机程序,是直接运行在“裸机”上的最基本的系统软件,任何其他软件都必须在操作系统的支持下才能运行 ...
- HTML元素粘滞融合效果
.target { filter: url("#goo"); } .ball { width: 150px; height: 150px; border-radius: 50%; ...