From 454adee5a45cb7b185d4127c41f77ef4f36a5b8b Mon Sep 17 00:00:00 2001 From: David <stierint@hotmail.com> Date: Thu, 5 Mar 2020 17:01:16 -0600 Subject: [PATCH] added TX RX delay calibration --- DecaRanging.coproj | 16 +++--- EVK1000.bin | Bin 71000 -> 69144 bytes README.MD | 23 +++++++- src/application/dw_main.c | 87 ++++++++++++++++++++++-------- src/application/instance.c | 46 ++++++++++++---- src/application/instance.h | 31 +++++++---- src/application/instance_calib.c | 4 +- src/application/instance_common.c | 40 ++++++++++++-- 8 files changed, 191 insertions(+), 56 deletions(-) diff --git a/DecaRanging.coproj b/DecaRanging.coproj index 4f99c98..93b3496 100644 --- a/DecaRanging.coproj +++ b/DecaRanging.coproj @@ -104,20 +104,20 @@ <File name="src/platform/deca_spi.h" path="src/platform/deca_spi.h" type="1"/> <File name="Libraries/STM32_USB_Device_Library/Core/src/usbd_ioreq.c" path="Libraries/STM32_USB_Device_Library/Core/src/usbd_ioreq.c" type="1"/> <File name="Libraries/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c" path="Libraries/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c" type="1"/> - <File name="Libraries/STM32_USB_Device_Library/Class/cdc/inc/usbd_cdc_core.h" path="Libraries/STM32_USB_Device_Library/Class/cdc/inc/usbd_cdc_core.h" type="1"/> <File name="src/usb/usbd_desc.h" path="src/usb/usbd_desc.h" type="1"/> + <File name="Libraries/STM32_USB_Device_Library/Class/cdc/inc/usbd_cdc_core.h" path="Libraries/STM32_USB_Device_Library/Class/cdc/inc/usbd_cdc_core.h" type="1"/> <File name="src/platform/deca_spi.c" path="src/platform/deca_spi.c" type="1"/> <File name="src/usb" path="" type="2"/> <File name="src/decadriver/deca_version.h" path="src/decadriver/deca_version.h" type="1"/> <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_flash.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_flash.c" type="1"/> - <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_wwdg.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_wwdg.c" type="1"/> <File name="src/application/instance.c" path="src/application/instance.c" type="1"/> + <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_wwdg.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_wwdg.c" type="1"/> <File name="Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_dbgmcu.h" path="Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_dbgmcu.h" type="1"/> - <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_sdio.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_sdio.c" type="1"/> <File name="src/decadriver/deca_device_api.h" path="src/decadriver/deca_device_api.h" type="1"/> + <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_sdio.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_sdio.c" type="1"/> <File name="Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x" path="" type="2"/> - <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_iwdg.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_iwdg.c" type="1"/> <File name="Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_bkp.h" path="Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_bkp.h" type="1"/> + <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_iwdg.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_iwdg.c" type="1"/> <File name="src/compiler/compiler.h" path="src/compiler/compiler.h" type="1"/> <File name="Libraries/STM32_USB_OTG_Driver" path="" type="2"/> <File name="src/platform/deca_mutex.c" path="src/platform/deca_mutex.c" type="1"/> @@ -130,12 +130,12 @@ <File name="Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_sdio.h" path="Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_sdio.h" type="1"/> <File name="Libraries/STM32_USB_OTG_Driver/src/usb_hcd_int.c" path="Libraries/STM32_USB_OTG_Driver/src/usb_hcd_int.c" type="1"/> <File name="src/platform/port.c" path="src/platform/port.c" type="1"/> - <File name="Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.h" path="Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.h" type="1"/> <File name="Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_wwdg.h" path="Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_wwdg.h" type="1"/> + <File name="Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.h" path="Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.h" type="1"/> <File name="src/decadriver/deca_device.c" path="src/decadriver/deca_device.c" type="1"/> <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_exti.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_exti.c" type="1"/> - <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_rtc.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_rtc.c" type="1"/> <File name="Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_adc.h" path="Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_adc.h" type="1"/> + <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_rtc.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_rtc.c" type="1"/> <File name="Libraries/STM32_USB_Device_Library/Core/inc/usbd_req.h" path="Libraries/STM32_USB_Device_Library/Core/inc/usbd_req.h" type="1"/> <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_fsmc.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_fsmc.c" type="1"/> <File name="Libraries/STM32_USB_OTG_Driver/inc/usb_otg.h" path="Libraries/STM32_USB_OTG_Driver/inc/usb_otg.h" type="1"/> @@ -169,8 +169,8 @@ <File name="src/decadriver/deca_param_types.h" path="src/decadriver/deca_param_types.h" type="1"/> <File name="src/usb/deca_usb_bsp_evk1000.c" path="src/usb/deca_usb_bsp_evk1000.c" type="1"/> <File name="Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/startup_stm32f10x_cl.S" path="Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/startup_stm32f10x_cl.S" type="1"/> - <File name="Libraries/STM32_USB_OTG_Driver/inc/usb_bsp.h" path="Libraries/STM32_USB_OTG_Driver/inc/usb_bsp.h" type="1"/> <File name="src/platform/stm32f10x_conf.h" path="src/platform/stm32f10x_conf.h" type="1"/> + <File name="Libraries/STM32_USB_OTG_Driver/inc/usb_bsp.h" path="Libraries/STM32_USB_OTG_Driver/inc/usb_bsp.h" type="1"/> <File name="Libraries/CMSIS/CM3" path="" type="2"/> <File name="Libraries" path="" type="2"/> <File name="src/decadriver/deca_types.h" path="src/decadriver/deca_types.h" type="1"/> @@ -210,8 +210,8 @@ <File name="Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup" path="" type="2"/> <File name="Libraries/STM32_USB_OTG_Driver/inc/usb_core.h" path="Libraries/STM32_USB_OTG_Driver/inc/usb_core.h" type="1"/> <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_bkp.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_bkp.c" type="1"/> - <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_gpio.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_gpio.c" type="1"/> <File name="src/application/dw_main.c" path="src/application/dw_main.c" type="1"/> + <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_gpio.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_gpio.c" type="1"/> <File name="src/platform" path="" type="2"/> <File name="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_tim.c" path="Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_tim.c" type="1"/> <File name="Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_i2c.h" path="Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_i2c.h" type="1"/> diff --git a/EVK1000.bin b/EVK1000.bin index 8fc9c3848a73f83bd3b2ce71e721c6a49fd5370d..93c8b9d584becffe31bc902e33e4af7edd291e37 100644 GIT binary patch delta 13017 zcmbVz33yY*_V~<A+NOJ<EltxcZGck3Qb<cFWhqdvT@Z>O0tHPeV9MH3kU+skHbF!x z1G0+X@>HG(HXv%j;))Aut3Cly2@hoveD5~2+?(7i|1&pfn-+Ng@B86*Ix}a^IdkUB z%$YOi#`A~dyY|Uz5W?!$=Oe`nTan@%Kr4U<fNPNgb@>+nxJWNP3CaS1zk#<6v_9=+ zKJ{mO>TR^%a$!4jmktTP`~Hmolh0Sy9IuSSP?Cu_KHs<V|62bOgzan&!nMSL`!J^& z62uIH!pt%sMaaXrU)@9z86Re0u!6#MsU(9V{|E`=rZu33TN09_M13K<<v`?SlqhGo zKi%Z7=-If=JfX)!GCa`yQY^;ArHUeTs&RNaajVMkICELtiV*pPmIr5<EvbER<OSJ9 zq{=&YgUR^h2Fj>55Wzqa(q=MYB3YHjCVa1>-4i$@1CUda37lIOXc3Jo4d0VXX|aBl zBc9DmCeE}he1&w=Mh{#d%2=dLZxmNw0p68{$h`CMRBUmkiVbKEk;Srs+;oX%P!rGq zPb7J+Z&;2hwc21`y;g`#6<1R(l(JUXo{BYb7EhZ9+q00id*eN*$iMpLct#)WveVHO zAeqYW@WenX7NoT4Bh!H%SdpRxO|II>RPD%UDjGM5)iAMYtP`uK!YcAlt+oa%Rf<K~ z?Z`ZtRaJ#jR29jE^#)&TY?T|ZNF(Y8SX2d4-x5ZYSw&Dl*7|qVUK9+InXZrY;Zx;F zz1HoLM9OoforkKaC<I<zHme|y^n0+T_82-MFOs!>Tc-R*$tJU>*xHj752A+RV5DyA z`|e(S$JZW3N06pkKccX@lg{HN(V1X1!!2<Qxo2N`2eyVzzV(|jV9{$k(2_|eOW0nW zv90wIR^1tE{gn=?S9Qj=o|I^#J7cYXNVMS+wx)drTECj*yA>6knOeV=M7epp3pIpf zft5~47COFOvO>Lnna>JD<}qM_icT1rwNkRn{La{Lt7n#TylA2ypn?;0rh+^*AhAEK zAd#^~=FzkAwbEBXvHGEc59#81DK3z&1|)adQZuN^6%6-|6RR<I#9`FSU{U&u)dr+x z8tGY^Yr)C1Z=%!9-*ye|q*|g519$&UIGJ_)q=)W&JxgUu?Tl}IM;a?Rpluoz1EYpe zM*y4kwygEdvKZKOSf^weF2EMmh4+fY8{WqH;XqZW&l$K=MlKJG#fd~5n4s*yD|IkA zQ+;910*WK)=~3|=opK$+sw%1tQ;kR32=tu@6kdW|##h@2YC91GdkK^)cD50mPLJ|2 zZ$O)b6`Q>To|7CT;Wu=`g-~5V9pxrdCwv&CHAyp&47CD`BnKm5?j;B2vK%rNYac!z zz?~NYnup79N~}K{4=Xr?OdFKYw_~<SNzCj{qLn)3#>c%Fa$t}$%3lcJ{vlKw_8O-r zPA-tf)RVJ=dQ*2@O709woYPg{@Vf*K?SxTD!|FQWl)AW$RR3~k|9j#Wk`;pod4_yv zaL)l9Lq<qu>o7%xE(nZ4MZF~kctvf~#gAX*M2cbn&VdyE+;umC-7C2LxhrnekPpYw zbP6??j?qJD)Mx9d;|wVjecY2;x6+`}2Y7L0o~{r6o)FzYe1Uwb%fW9Fw=QPrcW{OL zQde!D7e;qWwc(<X(S|iqza5)JJ-ApM%Nh-C{zD%+hHJHv@fm&bH)KV|vYKaI0nG|o z_&11K=!h*mC%m2BG1o+0oDpezG)8v8%fPqA8K%dF7I^9P2u@Eh_{aJ(s&i*4vO8sC z>9#@*M`7Maz3%9nqbV?RIa!#g#hGMxW~#^7pJn#chPJE3iD8y=!fR9|Y2W!5?xL=R zq3#7G%ecwr$RQXrn?<rRV@9`X!|siAGW5jJ1<4?5v*u8-v&gM1wa<~1wH_*qGpgVc zQE>Ylr03AS?IY+5Re4l~N*BvUux@^q?Tqj~>S5U_e3Z^;yEmN^j!LxTsiDf)LaB2+ z%vVCTUy-ro$k0rm@#2hFJE()zF;p4%l0dKM(8dAxU>=wq?dw;pv1DR)ba}_J#K9^* z(k_lVuIMgWKjxJlez)|hI3vs`J=5aW(9-{I3i5q+ue8pig~4d=r=PET?;g|%!{V|! zsAbkz7(vBS`aNTEIn&er+*86Uuu&uvN%uSLlcEB$cvvQNhOm7YYfv83dUzHMt~R%i zLQW6s>Dd?8ho!{$jMBb<PQH>P=R|s4D!qVi=?pY(XbwT1G0!X^#W~85hs4LcN&sSM zPD-MWH0!uYvBskKU+dbJQcsTMq<HTI1VS}=mvuqlsYkY}=5eBVx;O*fYDdJO?L8!9 zxJvn%0JBs_vKP@_RUF={0$tQ}L^5)?vSy3GfH&CT4AImt@#B`eliGQ`LDrqwW0iUX zM2bq;#*|pr$)B>fozepWhJ`zp-n|Qt=d2bthIGNpAmX5B)xT{C^oaaxcq(2?oWo;$ zZlboc9@EZG(nmyPdR9j|+#pD$KL<l2@G;)?yvM0zxPxTHhy<;VeecW~8)t+-v!L3r zD}@n}wM}Yd9(5Wm<l_-KpBqbdr&OXJbU*qsC731x@6xEiG&gOjog*MGck+F??M78a zmjLWeDGNhl-TAtxyM)mjI_xfNoKc|-YU&bv-6<s>j7)`Ss3TZo!PC_1Yajv=4ZGBI zqj#Nr=qSygPB`nqDwT0T(e#RW_v5m@LP|$PQj<xZS2CmZwJO!dlA=APY4_u5ZH4go z;lfYgnNxgUnmgdx3koAkAG{xh^;lJ$VRYf7()t={HEE3RJ7K;o8@y3=ky6)<tpPvm z<XeP{`w44pDN`8-6saou{SOLydGzdbIm%k8Sr^jvO1!Isu9xyItY^Kt--V~bL+`>W zjf&2=JG028+-SIVTXU0r0ub1|WlC^2yHZdxooa%u+JJS{`f5Xf_Udol3v+x;0~?c$ z7Sb6DQ=wRh9Xip@BGsb@MT23bBUT4voD&X2(75yr`FOMxKYN|&K94h%o>(OY*`4<@ z{J6IuB-=M;-VZOqY2MX-qr($dkf`CwMQ`@7rXBa~r!n>OoqEBkwmbKIHQ?QInl{{n zfW8AwUGVhAifvli1&ek5K)b99HbII(ks5ItcaUXamtL$32A*?5+`e?II|H+s(}e&Y zs6-r-;Nwo{?K`*Wk*;(Q+XQO+H%;h@w=M;LSqR>87j@X)tEuPU?gmv}9>r2?N~aE7 z7tpHoqwbQhWD+h1E&EyMrO;u1dgmR1<E85&TrCOje^23kx=OHuaFCtSj^CEoqo>dL z1C`<pe%ua-`1Xy7|AB^X9u3H_yxzEpl;%C5%yjq_#cfuyh|6^_MX>vpLo5pMC{a9c zl{qaC?g1t9xj=&0jecjHejH17vV&yBA~Ju&`pNKV(o_%we{U2#9(_6nsZH=OXNpST z9)zeCp5&*^GYh|G209@4rQI|T-Uo0D;3U90fU^MS0e%HI4e+HCk&=gw<J0DD<JZCn z<{cA@Fbr||;h9)TMooGbP|cIJ;y^0!-vGaoO^;j|Hf;(d&j1z!-0lMFq5ZlKt{&=V z0Dc6xF~$6kDevJJN&Dk#=)*WUOzr016XE5_O(9iNbukYKa<I&vCsBjK8?6iO)Sjo! zr=||Xksii%Qt%$kitu!;CGKgNcmv6tzB=YHJC`C$9s&aYv{Um^A*NHO$yd{N<KIbH z$%N!HE~Gwny<#nDfDB<SO2@hVZ&Zw}WfR$_*$_D5{~$k>Ou}18>I@CYESiy&a9+U4 z>U@7L)Q0-l8gWKC>(Biv9C+YA=jEJ%JToI9p}s-R6^RpCOcTTN5ht@jj2!rWGYbE% z3Gn3O83}l}`O=KtGUmS!E$g2gALz(gDdUo4SR2&HXu}(kHmZpR8T7><<9Z4`EFG<d zLby+BkD##RtkiHdvWs<;+K)?dl98oGxgU4IMLsO;4VCjQ@<-`*sN}iGs#!yzlIkMw z&FTl0#V&Gn);yd`CYD8qiFTyPO)(`?DXn(%(y~2RF6Wxv=I(P61GJk&H(&0kc#tOg zAc?B(2f3bffW{i6c3m?aqnRBeI9qt{kdg%&97}2zq$b2>sn`{Uj@T<W?~-mboEZ<@ zrwcChU$_t{Vk?khU=>pIT8b3W0HMo};>wdqp;-<&$;C)vhW?UDq{ty(E!>K4kZFsw z_(!sS(Hppi^k1A7H_rw-@X>a$+&^V{1+51-#c~V@J0+=H+<&GDvT2ZlD-VQTvD^*# z*i^)|G>GM(Z7Th%%Gxs~@CT_48jIzgR2{wt*9G8W=qTJz4MA!L{}d4yXW`d~t|B?< ziXh_#+GJ`O_nLq~iyfd5J={)ygUiWhkgAGoI75dka+qKT`K#j1z!nDsgMBK@Ht(&h z#9*_~syO(YRuv~%&Q|VgIbQO{l8&UbDk<41dYStnPVo_fQ1tC|&#WtZd8iInX+c_P zRV1-gr9-XT(nkWHZQ~+~mnH#j>rzd?NmrZHNOE?mN}`M-%(BUG-P@@9c_f#?Sh1&q zVcwsT%4MlhV)>84>~ReDH>5dZSv7>;iv_Z8SxUbE2uly72Wh)s5Xwb9#vNu6%P$&( zw7J~5b+qT0HrM*YI@%ZLCiZ2$we*!t_b^4B18Kk1iRGSkdiNyNZdE4IhBVS%3n_Z? zAn5q_lSu(vVV&uYi(Ib3D@oS!QhbE$ULFTlKE8Z3qjC~qxf(AfvBm=Y2PrdZ@poja z@#&hfYNWXM)c+k~S0F{q|3^l^D){UGn~-ifCS?y?lwYRH;HHBInR)AqG>lux2P+do z)15N#Gc=28=RYJ@R*sUaA4!H(M@3bLRDcQu(ByMvFNO;j$Ya&xV0!<oE(lOcTQ`<K zYN0qb>nLRV?B$J0I*wfD2X7S{k3fKDi?0=C^p@&b^sbo-F-Zt(FK1f6m7aNsdjl>h z59T`wLuRkqmb%AIh3!rVXjaSoAbzy*FGv_!b1)8QPWR%TAqlGw*SJJE8_J%$(E|&- z0J|m_c0(E~@M>wOUTi${MM2+RqKVxEbtTmQkmz#R0-y_lqtM3lFsy$Fd*+5Z!y~WJ zE1U9s?ISzaOP82&?$H}6=sf8qqyxR@L)gzt7@y&>K>{ccuQ_)k5$F=7J{7A0oEq9z zNnyGmHeMx=15foRr#_<1fHQ{BJ!<Dwux>~z1FwQpJ{9yn#trCVO2kc(hUhT2$4}8! z{Y6^aJ@8lZN+hW!8a!KOO?JR%Zo1ct$g-NTIE#ExlRX%GmPW}&v?Z(>Wj&W=B1M0I z8vw}}p08WA$Dg5>sM^jmkWMl6tT}Fio7M+j@~Qjc+v?wT=|9}1-9~r6^7GF0I>qaq z5uKE|mylB?v)wcRheITyNLq){+ASDOb|Q1unr;|BLkiZW1snRwETVxP3IkcaR)=%U z@2-6W2iMw+Wjlq`^p*4BGtT-198U(W*Wv_HvVI`sf;U4wiJVxk!)kI9{w9;84Un%U zlQv}aYrDU)^}`I+hCO3sKhp9?mCWKPagLIu8GIU4nV;S86b?2lgu72fiWU)($c@PX zw5^0MUpX5yrM`ZUY#a{l>W!IF-#Do+j{LAul|*T$Lcd80crf<}>?Qh8fp0#In9C)> zo8oXbN!_$8FkOk%eE?d_uLCaC0r8dsnp0T_%AuSLrC*WCux5;3qf)Q<0CPbnF&9p* zJ-Zy|lgBsr4<6+X?QLR%dWn1<*|~W%GgKhIY#tMPLUizfu5^fRR*Fv)rL&28NU}rz zxQ=8#mxd$A<Ilz64@vcN1RF{C79H+O#%@Vt0_<ebmZ4dvU2`k`z9xV!R3EB?0hUS* z`V_|^wLTZA^PtR!_BdJsP+g~!-?qdses*$aOJWe61SOU$N#gT~bEquJ(@uYUj5T5j zgcQjU`2xSeE{7b=7F$>$P7cctD?;1C3Z4A-0_H~BQA$XWN{>0KP2|rzgNk;IVHzp* zQ5#arj?NV1BGoTL4tkM;&p%pFZPOUct@?pinrPl<nAEBmcu8t4lv<{wi&Cqf4QVv` ze_eC)mz`>T1jOVapfpunnkgB*^)h~mXlloHTLi}&Y2}SrE%3E=fuBN_*Cvdb4U23# zj*d)dLB(!<u1Et<+Q!@z8-{>%rVnPCO#zt6KA2+iV{PidAMEmc8{i?7gnpgWj~b|j zBmPDfDvim<+@m(nn?X;~UP$US=LMu#0k9TevA28>$`Rgr36vAb!WUkK543N)NW`{9 z%zOtiZA<J?;(#qL{E@lWkZmv;c0Fh`Fx+$(Ikqi>83OSNP?X(+qL+&#lA(-SBvZ+} zBnHy>eiq7)xU+U-fv~zktZs8#5#%z_#Qsf?B4ImHJOGfe!vld(Mv{c>^Ls1=?0SHg z0FDEE3-IT5vVZ$kW|M<#*io#QBvQ>jcaYzAtc&>4MH@AaTnjC$9c0Oiy%nEJ$k`5Z z;Kle6W>;8|%1ATw5y`<taYh;^JNR0O<Uxl*;v4IbdzBsu#_V`##1q?#S!rf5)KYDb zwQj6}?<v5|aEHV;dUyr2(?^kMJ4eKr+WW2u9eoh@?bI=!isaurhjg>;L<+xMNYM=- z0U(W}?V1?;B&@H;z2}nkyK<OGBKc(3dy)SU5X9sR_m^Na2>b>3mZ%_?izChZcYlKM zY*M=S<6(0J#2v7?`F(E0DFu2>(7i@qQ!-YpMBFVwT!FNHjfhLI!Pf;5am!&W`kEr+ z_QeOL3Vz8LV!HLDa$ih}%`u_nG#sgk&KONjMYyIKz9rXJV2xOj191v$Hzzr?Z)A;= z?#grrKgi+WXTqH+E)!QH?U=?0*r}sz4E$BY8FcVjPWpF&6R7nLejJo2*TI{d>3}^U z4dvj!chKRlJ5WOolnOUJPqs!T*)zgApt5xH)Qcs``3^L*Asa|<yS$`OzX0qG>H1b^ z?M+ly2Vd^QR7kOdpX-upxemStYO8^Mri&U%Dcz^0;~PE3GIfUowZu(6dnr8xbKBfF zSq6wE_qP4Lv-91#ntD^dMy$+9h-Jg_MShe!0x%JPk!k8BY#?AW+$dQAT)(>`lKt`> zJSLCtPnKh@yPK@rKcEJ4I`@PY_1GMf5^M^LVAohS1sGdhpex{E2nm+}xSJF=DTfZy zP8$RGOD>cg1%qq?6{*hSK&EM8H|Ti-YN)I;M=;>OppwdRx_1)g2OS@hu`egr)Ho;H zaaYxw;QN;}6Akpd?4mQJs_l_#YN+jyYDrM5m1<PU%`Q3ELGI=30hl$eQ9hXNfLYNA zL#<Z<3RS>}lKrB*22?=DY?vEXi~Pfce>o?746IiOV3Xa{ZN5%MABYY}chL>@F`0Q_ zpgtO?5l~mTVUNP+yPTy8P4!Z&sb5Ne-l1e&{8jsemfQ-=jTHSgIZI$iFM%Ds1gMwL zcQxJ9V@0I}IM%@Am%)lG3uuml*LM(%deup89Z=$W;&(6!uP40@_Q#9Jq=SPBmK{Wj z8h}jzI{*#><idR=@{3(D7E^L4)aJRmTfpd*RM2c!2-Hz!0Ms9I`9r;;QV#X0Wb`Z1 z<lhH-6x;v_w*j00fv><*7{DVjwOwM0kHmN%i9LKIMu5ZwZMch?>y#q`cCg6XodM8# z4~__AmmtyM@ecH-7;e6VY<eYb#4RTSPL5_wLyF=c6!C9z^J5_>&w(%~P}_U~0e_Q= z?r4$!(y4*gbdcuB$f(KXR|Y~xw%e;Qv4@<V+X#iwQRw|=DrJCYKN<aMQm7j4Pw5u4 zh<q=y@YR?S>WMrzV+_cg+Nre}{EEkyp(AQ(9wQ-Cq8M<jlKc%)+5zTKYBccte<1Wm zTEx9)qAkIE>D56p%#&_!ynsJ7zxqZX#&&Y}%{T_T$=7clz?aPP-|B{=e>;Q}l>oGC zgAd3Hhcpl(9zT@H_`ArhLtkJ6G5_-vNUMDN2qSlrl*7ZqyF-roBK%jcr{i5W&p(`o z;}Q3OlYvYM2Ct2{QBIjgk+MdrXFJK!cTz?o?n7rsD1QuMld}MCFQS&AKHI3LiL9q3 z7V5yLm^n_5h*BqsI5Jy~xQ%XNJfeomAvf7~Bp$v<e{dxGQN$IvdsuKvWC3Lw>yEJG z7)mx?tfR~6si{~RFv+Cb&c*M6CG1e;Z?7u1K$SjzNIeu5>ki<0l7gc-ezbLqY&yCr z={H9Q4{FE&JdIQP0rUZAA%ot{>9)v+Mw%X3{q8_KoE(1lOl&`g=bEFOZCq4B3)xb) z^?_2Cpcf4z3dxwzMi;-`&GS<w%uv91euDCZ#m=u0UA(~sea`pw_4LOnztA72Ot-lB zv%oQml$u8{*PY~mc}9&5?wpmC6I$#QJpY2*!C!NVkRkP`kdD9peJV^f7lxk!<!6x2 zIt_62I87<i+mq3VRRPW6G8IdmlAS*<iYruXSOHD#z3B>tn6wXIzZF9YLyDr|nHzq# zkG@=gNPknW*{EIPUx>-2V}3QKym$Li*tts~^cS9j@nD>d?au%@7Mzu08~+u2lXUSf zisChdYLAnna{800vI*Ybyq&qB$dE(-I2SCRNRwT!!A-of!o{!lmMg$C54fHDt8i~p ze5HtLfJ^~*WeJ*5M>A7OsP9E3b(*m=>gZq*(7xzxQ{j|04tx3)&_<Nk+m3*?0LO5z zx2=XY2knbeyQJ=yx+mZ(5*_7Fz#?sU)9j*}oU)LV*#)!nTX~(Uv?!+xZu<Gt6Ni-{ zxT;;(=#YOpr$cb2VrLXYsGWSeV+ypC@Y(+@7~0(I9)+8bX1`@3U`t>-%YPZ~?JspF zf^`_nmmtGwuLh|rK`IZ_)n!!f2hO~rxEiC3Q^?>HG_pnTJ1adk+cgMO#}q++MNf6L zI9<FMa=|=*SrAGE{x#?Or93}KawsK@*%BR19?Te`WMLb*U>PvaXNqTT$e|nsC4*s! znDnA^(9^=7gdoO~*J<U8?KSj)*TMd*i<0&#YT@7VAsYejh#Y+)cwY=g%Q47EwSgh@ zr;y*mr}%R><Qi2$6zsaiPGMFU9PGRMBMU;H|8eNI%?rwR@{2?#|Fc+Mj)rQtHM;o= z&aKy!>~M&9YER|ChR+=nj`n#s<C{>@gFv5cD0ge_NofBBZ`La(oy=A@`S+=>6Yual zAOvmYFF|}`G~D4MZS?O}>F*+eeEreeOpHi!OM8}#7v3D;l@+3Jv4R+I}sSSXUE zrx%1wYDd6NI&YmeGIocTCxz_)IG1rdh~?wHL5!P$$h?&w>LyX2%*YRgG3n{BLv$Dq z_f!NpgP<l)NN4BcJ-xYh$TZSWJqUUOrCtO$4==4L+~)T`S;{a!i)6s(19CqSJDw)= zhrzYSH%W&+TQ62dvh|e^4U`TwwD8C6bh#$Oa>=FK4owcV@VlI3*XIuPeAu5#Xr@X@ z9@qvML9hOJ13`9)fo)J>C&#|%6EoBW)&xig$OZV!jTAH7$b9<??C)<vSW%12_Os)0 z?<6PclgnkS>jOi8LmNB~291Fa4Y^$3b<uBzei^m9h4-_W7k#%4cOM6QZufs{a-kd! z06!<_-q=^(!gm+Uxs6X^W(rKV$$<S=Ndu7HKVI+A!eb$Qu)l!&)AStD1f|^O1-H59 zPez8RMP&cay@B5%kS~9Jj(Nsmo^tMCSx_yoKQVXi+@*-r{qi6AZC-CDuU+IMd_MH$ zA@lxU=V9pRXCooM?;7{1V}WD>E5F1w-&?D9d<zCiXRSQrGI()iE}HZE4e(a}pU^MI zxB1%wN&!tYze%mn;0xIA@gVsJfka$d#cXks=P%7Jw7YKe2Ehcv<~aMZIw;RLsi<Oh z8q`A_0sG}IE1J{&@PH8&6d%xx{bo0!6lIZ>uXCalr159N+1q@SK!#g}>Q}=g4gkCj zfRHfiJe1UC2=&ZGDNh5_Q_hFk5|%Pqd5fDa$A@djutjV-n+=%VpiY1whnn0;u~vSr zq>iWeZIS$B>8ai;Qg+XT6)@ow?)(pa16MJa%>jmgxQX)eM`1=O3rgp1<#XNUKQ5bO z%xDLh`=@%mzr-KZjDr?ND4G?D|H2dJw;SDo-^!;r0@#gg*xs@4qLc$gL)p=Q(@Q() znKi{wUt=G}j)n3M`)>FMX5|Oi$WMQ!_h}YA#tXNtVK=iLwnv?QKseb>74=|{jr6-3 zpO^{qCO1)Sk^0F3D}O`iuz0GI%)Q!kt`(9p)J|5u*+FeIWz9nmAkJo@%Yss7gB`0N zVKb|Uj^?q=e0w-p)yiWhT}+paiuCjx5?}!pkJ~p2egfXyVg1h>gu7Z1V&#=~&ro|D zWWlwQ{&dZbA~N8*GT#dCPtSZ0+EB{JMa}$8w;y}3x%kP^pvFgFpJrG@I(4dul}~h- zSgLNs(|uY0W;E8bi&{nU{Ppu{D<5s^-;J7gREz4JRpW041pe!1INl!H1lY)i8-1Bp z7pc3!f?>}J-$Dl5y8t4!<V?v-6w^#Ub*TPIPqgx{3Z7|aLo(dT50Oadw43>VyNKbh z#Gs#Co^8=$C$)b~1|_BlR0UXl)Xe|o_RMY^9F-WD-HR?Fzu70K#>>-SCqr%y@EXKC z@8(~!&{g2n#{nz_Fq%vM8^GXkq`aAQ6YEjKc0gh<8c*va)cUR5%0F&5|89MjVGdyP zyw;Bxe3qmM^-PJITopLxMK?KbdkucNzuNvi#;eQ^IZnt!O(3NYd=EVQyX))56OgGb z!NHGA8lzsiSUst@K)v$_gQNQ|Rrgx3V5;{|`cSCBA8@>-_rjm(CC6XNPBaJLRECKP zIiU)|W8@F5gK-Y$A;kv(7XbbQXa;Zs1U>*c@K*}uH}yzyq7<HIQ0^>){{v(eQak}= z7C_8wq{sxA1h9PPTVXgZcG@#Yu^Qkqz(Ih(jqoiSVExYDpu3wBs==G!D<!}nfMq)a z!|{Z)neQOQR{;2kC-I(k6e-F9y1k1OGXdy@LjNs1@pL$T&~M0PJ5oG-$AdqKvEqGz P8L(;pH|%sp;pzVmJQZAa delta 14961 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 diff --git a/README.MD b/README.MD index df58582..113cb4a 100644 --- a/README.MD +++ b/README.MD @@ -13,6 +13,9 @@ The software and documentation for the EVK1000 evaluation kit and DW1000 transce ## Getting Started +//TODO add a table of contents... + + ### UWB Configuration The EVB1000 allows for a numer of operational configurations via microswitches and jumpers. For default operations, ensure the EVB1000 is configured as shown in the images below. Consult the EVK1000 documentation for more configuration options. @@ -50,8 +53,26 @@ Then simply click the *Build* button and the EVK1000/Debug/bin/ directory will b ### Interfacing with the iBQR +tx2-ros-examples +The `uwb_interface` ROS package for interfacing with UWB can be found in the `tx2-ros-examples` repository. It is run using the following: + +``` +rosrun uwb_interface uwb_interface_node -p /dev/ttyAMC0 +``` + +**_NOTE:_** Roscore must be running first. +**_NOTE:_** The argument after `-p` is the path to the USB port connection and may not be the same as listed above. See the `tx2-ros-examples` repository for more information. + ### EVB1000 Display In order to save power, the LCD display is disabled by default. It can be reenabled by changing `#define USING_LCD (0)` to `#define USING_LCD (1)` in [src/application/instance.h](src/application/instance.h). When enabled, the LCD will display the range calculated and the address of the TAG/ANCHOR that it ranged with. -### Calibration \ No newline at end of file +### Calibration + +The ranging algorithm depends on RX and TX timestamps to accurately determine the time-of-flight (from which UWB distance can be derived) of the communications signals. For the derived distance calculations to be accurate, the signal propogation time from the antenna to the DW1000 transceiver (RX delay) and from the DW1000 to the antenna (TX delay) must be accounted for. By programming the RX and TX delays to the DW1000 OTP memory, the DW1000 will provide corrected timestamps to the ranging firmware. + +**_NOTE:_** Step-by-step instructions for performing the RX and TX delay calibration can be found in the uwb_delay_calibration package of the tx2-ros-examples repository. + +**_NOTE:_** The range measurements depend on the speed of light through air. For best results, recalibrate the UWBs using the air conditions expected for the intended operating environment. + + diff --git a/src/application/dw_main.c b/src/application/dw_main.c index 557c760..333b3ad 100644 --- a/src/application/dw_main.c +++ b/src/application/dw_main.c @@ -295,7 +295,6 @@ void configure_continuous_txspectrum_mode(uint8 s1switch) int dw_main(void) { int i = 0; - int toggle = 1; double range_result = 0; int canSleep; @@ -304,6 +303,7 @@ int dw_main(void) peripherals_init(); #if (USING_LCD == 1) + int toggle = 1; spi_peripheral_init(1); #else spi_peripheral_init(0); @@ -339,11 +339,22 @@ int dw_main(void) | port_is_switch_on(TA_SW1_7) << 6 | port_is_switch_on(TA_SW1_8) << 7; +// uint8 s13 = port_is_switch_on(TA_SW1_3); +// uint8 s14 = port_is_switch_on(TA_SW1_4); +// uint8 s15 = port_is_switch_on(TA_SW1_5); +// uint8 s16 = port_is_switch_on(TA_SW1_6); +// uint8 s17 = port_is_switch_on(TA_SW1_7); +// uint8 s18 = port_is_switch_on(TA_SW1_8); +// uint8 debug_msg[8]; +// int n = sprintf((char*)&debug_msg[0], "s1switch: %d ", s1switch); +// send_usbmessage(&debug_msg[0], n); +// usb_run(); + if(port_is_switch_on(TA_SW1_3) == S1_SWITCH_OFF) { int j = 1000000; - uint8 command; #if (USING_LCD == 1) + uint8 command; memset(dataseq, 0, LCD_BUFF_LEN); while(j--); @@ -486,12 +497,56 @@ int dw_main(void) if(instancenewrange()) { - int n, /* txl = 0, rxl = 0,*/ aaddr, taddr, txa, rxa, rng, rng_raw; + int n, rng, rng_raw; + uint64 aaddr, taddr; ranging = 1; //send the new range information to LCD and/or USB range_result = instance_get_idist(inst->newRangeUWBIndex); //set_rangeresult(range_result); #if (USING_LCD == 1) +#if (DELAY_CALIB_OUTPUT == 1) + dataseq[0] = 0x2 ; //return cursor home + writetoLCD( 1, 0, dataseq); + + dataseq[0] = 0x2 ; //return cursor home + writetoLCD( 1, 0, dataseq); + memset(dataseq, ' ', LCD_BUFF_LEN); + memset(dataseq1, ' ', LCD_BUFF_LEN); + + int toggle_step = 5; + + if(toggle <= toggle_step) + { + sprintf((char*)&dataseq[1], "ADDRESS - SELF "); + sprintf((char*)&dataseq1[0], "%llX", instance_get_addr()); + } + else if(toggle <= toggle_step*2) + { + sprintf((char*)&dataseq[1], "RANGING WITH "); + if(inst->mode == TAG) + { + sprintf((char*)&dataseq1[0], "%.3u ANCHORS ", instfindnumactiveuwbinlist(inst)); + } + else if(inst->mode == ANCHOR) + { + sprintf((char*)&dataseq1[0], "%.3u TAGS ", instfindnumactiveuwbinlist(inst)); + } + } + else + { + sprintf((char*)&dataseq[0], "TX DELAY: %.5u ", inst->txAntennaDelay); + sprintf((char*)&dataseq1[0], "RX DELAY: %.5u ", inst->rxAntennaDelay); + } + toggle++; + if(toggle > toggle_step*3) + { + toggle = 0; + } + + writetoLCD( 40, 1, dataseq); //send some data + writetoLCD( 16, 1, dataseq1); //send some data +#else + dataseq[0] = 0x2 ; //return cursor home writetoLCD( 1, 0, dataseq); @@ -500,38 +555,27 @@ int dw_main(void) sprintf((char*)&dataseq[1], "LAST: %4.2f m", range_result); writetoLCD( 40, 1, dataseq); //send some data sprintf((char*)&dataseq1[0], "%llX", instance_get_uwbaddr(inst->newRangeUWBIndex)); - // sprintf((char*)&dataseq1[1], " "); - writetoLCD( 16, 1, dataseq1); //send some data +#endif #endif + aaddr = instancenewrangeancadd(); taddr = instancenewrangetagadd(); - txa = instancetxantdly(); - rxa = instancerxantdly(); rng = (int) (range_result*1000); - rng_raw = (int) (instance_get_idistraw(inst->newRangeUWBIndex)*1000); //TODO change this to use actual tag + rng_raw = (int) (instance_get_idistraw(inst->newRangeUWBIndex)*1000); if(instance_mode == TAG) { - //n = sprintf((char*)&dataseq[0], "ia%04x t%04x %04x %04x %04x %04x %04x %02x %02x t", aaddr, taddr, rng, rng_raw, l, txa, rxa, txl, rxl); - // n = sprintf((char*)&dataseq[0], "ia%04x t%04x %08x %08x %04x %04x %04x t", aaddr, taddr, rng, rng_raw, l, txa, rxa); - n = sprintf((char*)&dataseq[0], "ia%04x t%04x %08x %08x %04x %04x t", aaddr, taddr, rng, rng_raw, txa, rxa); - + n = sprintf((char*)&dataseq[0], "t %llX %llX %08X %08X", aaddr, taddr, rng, rng_raw); + } else { - //n = sprintf((char*)&dataseq[0], "ia%04x t%04x %04x %04x %04x %04x %04x %02x %02x a", aaddr, taddr, rng, rng_raw, l, txa, rxa, txl, rxl); - //n = sprintf((char*)&dataseq[0], "ia%04x t%04x %08x %08x %04x %04x %04x %2.2f a", aaddr, taddr, rng, rng_raw, l, txa, rxa, instance_data[0].clockOffset); - // n = sprintf((char*)&dataseq[0], "ia%04x t%04x %08x %08x %04x %04x %04x a", aaddr, taddr, rng, rng_raw, l, txa, rxa); - n = sprintf((char*)&dataseq[0], "ia%04x t%04x %08x %08x %04x %04x a", aaddr, taddr, rng, rng_raw, txa, rxa); - + n = sprintf((char*)&dataseq[0], "a %llX %llX %08X %08X", aaddr, taddr, rng, rng_raw); } - #ifdef USB_SUPPORT //this is set in the port.h file - send_usbmessage(&dataseq[0], n); - // n = sprintf((char*)&dataseq[0], "This is a test"); - // send_usbmessage(&dataseq[0], n); + send_usbmessage(&dataseq[0], n); #endif } @@ -622,7 +666,6 @@ int dw_main(void) #endif #ifdef USB_SUPPORT //this is set in the port.h file - usb_run(); #endif diff --git a/src/application/instance.c b/src/application/instance.c index 7a28461..593e65e 100644 --- a/src/application/instance.c +++ b/src/application/instance.c @@ -21,8 +21,6 @@ #include "instance.h" - - extern void usb_run(void); extern int usb_init(void); extern void usb_printconfig(int, uint8*, int); @@ -676,7 +674,8 @@ int testapprun(instance_data_t *inst, int message) //sometimes the DW1000 tx callback (TXFRS) fails to trigger and the the SYS_STATE register //reads IDLE for for PMSC, RX, and TX so we need another way to timeout since RX FWTO won't be triggered. - uint32 ptc = portGetTickCnt(); + // uint32 ptc = portGetTickCnt(); + uint32 dt = get_dt32(inst->timeofTx, portGetTickCnt()); if(inst->previousState == TA_TXBLINK_WAIT_SEND || inst->previousState == TA_TXFINAL_WAIT_SEND || @@ -684,14 +683,16 @@ int testapprun(instance_data_t *inst, int message) inst->previousState == TA_TXRESPONSE_WAIT_SEND) { //NOTE timeout duration found experimentally, may need to be changed if the delays in instance.h are modified - if(ptc - (uint32)inst->timeofTx > 10) { + // if(ptc - (uint32)inst->timeofTx > 10) { + if(dt > 10) { inst_processtxrxtimeout(inst); } } else if(inst->previousState == TA_TXRANGINGINIT_WAIT_SEND) { //NOTE timeout duration found experimentally, may need to be changed if the delays in instance.h are modified - if(ptc - (uint32)inst->timeofTx > 180) + // if(ptc - (uint32)inst->timeofTx > 180) + if(dt > 180) { inst_processtxrxtimeout(inst); } @@ -916,7 +917,7 @@ int testapprun(instance_data_t *inst, int message) break; } - if (!inst->frameFilteringEnabled) //NOTE this might cause problems... might need to move somewhere else + if (!inst->frameFilteringEnabled) { // if we missed the ACK to the ranging init message we may not have turned frame filtering on dwt_enableframefilter(DWT_FF_DATA_EN | DWT_FF_ACK_EN); //we are starting ranging - enable the filter.... @@ -958,10 +959,10 @@ int testapprun(instance_data_t *inst, int message) memcpy(&inst->tof[inst->uwbToRangeWith], &(messageData[TOFR]), 5); inst->newRangeUWBIndex = inst->uwbToRangeWith; - //TODO remove or update below? - inst->newRangeAncAddress = (uint16) srcAddr[0] + ((uint16) srcAddr[1] << 8); - inst->newRangeTagAddress = (uint16) inst->eui64[0] + ((uint16) inst->eui64[1] << 8); + inst->newRangeAncAddress = instance_get_uwbaddr(inst->uwbToRangeWith); + inst->newRangeTagAddress = instance_get_addr(); + break; } //RTLS_DEMO_MSG_ANCH_RESP case RTLS_DEMO_MSG_TAG_FINAL: @@ -1012,14 +1013,18 @@ int testapprun(instance_data_t *inst, int message) inst->tof[inst->uwbToRangeWith] = (int64) ( RaRbxDaDb/(RbyDb + RayDa) ); inst->newRangeUWBIndex = inst->uwbToRangeWith; + if(reportTOF(inst, inst->newRangeUWBIndex) == 0) { inst->newRange = 1; } //TODO update or remove? - inst->newRangeTagAddress = (uint16) srcAddr[0] + ((uint16) srcAddr[1] << 8); - inst->newRangeAncAddress = (uint16) inst->eui64[0] + ((uint16) inst->eui64[1] << 8); + // inst->newRangeTagAddress = (uint16) srcAddr[0] + ((uint16) srcAddr[1] << 8); + // inst->newRangeAncAddress = (uint16) inst->eui64[0] + ((uint16) inst->eui64[1] << 8); + inst->newRangeTagAddress = instance_get_uwbaddr(inst->uwbToRangeWith); + inst->newRangeAncAddress = instance_get_addr(); + inst->testAppState = TA_RXE_WAIT ; inst->previousState = TA_INIT; @@ -1027,6 +1032,7 @@ int testapprun(instance_data_t *inst, int message) inst->uwbToRangeWith = 255; inst->frameFilteringEnabled = 0; + dwt_enableframefilter(DWT_FF_NOTYPE_EN); dwt_setrxaftertxdelay(0); instancesetantennadelays(); //this will update the antenna delay if it has changed @@ -1304,9 +1310,27 @@ void instance_readaccumulatordata(void) #endif // support_sounding } +//get the time difference between two between two 32-bit unsigned timestamps +//t1 is the first timestamp +//t2 is the second timetamp that occured after t1 +uint32 get_dt32(uint32 t1, uint32 t2) +{ + if(t2 >= t1) + { + return t2 - t1; + } + else + { + //handle timestamp roleover + return 4294967295 - t1 + t2; + } +} + + #endif + /* ========================================================== Notes: diff --git a/src/application/instance.h b/src/application/instance.h index 7a711ce..c377d67 100644 --- a/src/application/instance.h +++ b/src/application/instance.h @@ -32,18 +32,25 @@ extern "C" { #define CORRECT_RANGE_BIAS (1) // Compensate for small bias due to uneven accumulator growth at close up high power + + /****************************************************************************************************************** ******************************************************************************************************************* *******************************************************************************************************************/ #define NUM_INST 1 -#define SPEED_OF_LIGHT (299702547.0) // in m/s in air +#define SPEED_OF_LIGHT (299704644.54) //(299702547.0) // in m/s in air #define MASK_40BIT (0x00FFFFFFFFFF) // DW1000 counter is 40 bits #define MASK_TXDTS (0x00FFFFFFFE00) //The TX timestamp will snap to 8 ns resolution - mask lower 9 bits. +#define DELAY_CALIB (0) // when set to 1 - the LCD display will show information used for TX/RX delay calibration + +#define SET_TXRX_DELAY (0) //when set to 1 - the DW1000 RX and TX delays are set to the TX_DELAY and RX_DELAY defines +#define TX_ANT_DELAY 0 +#define RX_ANT_DELAY 0 #define USING_64BIT_ADDR (1) //when set to 0 - the DecaRanging application will use 16-bit addresses -#define USING_LCD (0) //when set to 0 - the DecaRanging application will not use the LCD display +#define USING_LCD (1) //when set to 0 - the DecaRanging application will not use the LCD display //! callback events #define DWT_SIG_RX_NOERR 0 @@ -390,7 +397,8 @@ typedef struct dwt_txconfig_t configTX ; //DW1000 TX power configuration uint16 txAntennaDelay ; //DW1000 TX antenna delay uint16 rxAntennaDelay ; //DW1000 RX antenna delay - uint8 antennaDelayChanged; + + uint8 antennaDelayChanged; // "MAC" features uint8 frameFilteringEnabled ; //frame filtering is enabled @@ -478,14 +486,14 @@ typedef struct int tofIndex ; int tofCount ; - uint8 newRangeUWBIndex; + uint8 newRangeUWBIndex; //index for most recent ranging exchange int newRange; - int newRangeAncAddress; //last 4 bytes of anchor address - int newRangeTagAddress; //last 4 bytes of tag address + uint64 newRangeAncAddress; //anchor address for most recent ranging exchange + uint64 newRangeTagAddress; //tag address for most recent ranging exchange double idistance[UWB_LIST_SIZE]; double idistanceraw[UWB_LIST_SIZE]; - + //if set to 1 then it means that DW1000 is in DEEP_SLEEP //so the ranging has finished and micro can output on USB/LCD //if sending data to LCD during ranging this limits the speed of ranging @@ -527,6 +535,8 @@ void instclearuwblist(void); int instaddactivateuwbinlist(instance_data_t *inst, uint8 *uwbAddr); int instcheckactiveuwbinlist(instance_data_t *inst, uint8 *uwbAddr); int instfindfirstactiveuwbinlist(instance_data_t *inst, uint8 startindex); +int instfindnumactiveuwbinlist(instance_data_t *inst); + void instance_readaccumulatordata(void); //------------------------------------------------------------------------------------------------------------- @@ -584,8 +594,8 @@ uint64 instance_get_addr(void); //get own address (8 bytes) uint64 instance_get_uwbaddr(uint8 uwb_index); //get uwb address (8 bytes) // uint64 instance_get_anchaddr(void); //get anchor address (that sent the ToF) -int instancenewrangeancadd(void); -int instancenewrangetagadd(void); +uint64 instancenewrangeancadd(void); +uint64 instancenewrangetagadd(void); int instancenewrange(void); int instancesleeping(void); int instanceanchorwaiting(void); @@ -620,9 +630,12 @@ uint16 instancerxantdly(void); int instance_starttxtest(int framePeriod); +// coid instance_ + instance_data_t* instance_get_local_structure_ptr(unsigned int x); +uint32 get_dt32(uint32 t1, uint32 t2); void send_statetousb(instance_data_t *inst); void send_rxmsgtousb(char *data); diff --git a/src/application/instance_calib.c b/src/application/instance_calib.c index b4385d7..0ad907c 100644 --- a/src/application/instance_calib.c +++ b/src/application/instance_calib.c @@ -110,14 +110,14 @@ int instance_starttxtest(int framePeriod) //NOTE: SPI frequency must be < 3MHz port_set_dw1000_slowrate(); //max SPI before PLLs configured is ~4M - // the value here 0x1000 gives a period of 32.82 µs + // the value here 0x1000 gives a period of 32.82 �s //this is setting 0x1000 as frame period (125MHz clock cycles) (time from Tx en - to next - Tx en) dwt_configcontinuousframemode(framePeriod); dwt_writetxdata(127, (uint8 *) msg, 0) ; dwt_writetxfctrl(127, 0, 0); - //to start the first frame - set TXSTRT + //to start the first frame - set TXSTRT dwt_starttx(DWT_START_TX_IMMEDIATE); //measure the power diff --git a/src/application/instance_common.c b/src/application/instance_common.c index e45b0ff..baea76b 100644 --- a/src/application/instance_common.c +++ b/src/application/instance_common.c @@ -273,6 +273,28 @@ int instfindfirstactiveuwbinlist(instance_data_t *inst, uint8 startindex) } +// ------------------------------------------------------------------------------------------------------------------- +// +// function to find the number of UWBs in our list that are not in a timeout status +// +// ------------------------------------------------------------------------------------------------------------------- +int instfindnumactiveuwbinlist(instance_data_t *inst) +{ + uint8 num = 0; + + for(int i=0; i<inst->uwbListLen; i++) + { + if(!inst->uwbTimeout[i]) + { + num++; + } + } + + return num; +} + + + // ------------------------------------------------------------------------------------------------------------------- #if (NUM_INST != 1) #error These functions assume one instance only @@ -314,12 +336,12 @@ int instancenewrange(void) return 0; } -int instancenewrangeancadd(void) +uint64 instancenewrangeancadd(void) { return instance_data[0].newRangeAncAddress; } -int instancenewrangetagadd(void) +uint64 instancenewrangetagadd(void) { return instance_data[0].newRangeTagAddress; } @@ -580,6 +602,7 @@ void instance_config(instanceConfig_t *config) //NOTE: For EVK1000 the OTP stores calibrated antenna and TX power values for configuration modes 3 and 5, + //check if to use the antenna delay calibration values as read from the OTP if(dwt_otprevision() <= 1) //in revision 0, 1 of EVB1000/EVK1000 { @@ -589,11 +612,15 @@ void instance_config(instanceConfig_t *config) //MUST change the SPI to < 3MHz as the dwt_otpread will change to XTAL clock port_set_dw1000_slowrate(); //reduce SPI to < 3MHz +//#if (SET_TXRX_DELAY == 0) dwt_otpread(ANTDLY_ADDRESS, &antennaDelay, 1); instance_data[instance].txAntennaDelay = ((antennaDelay >> (16*(config->pulseRepFreq - DWT_PRF_16M))) & 0xFFFF) >> 1; - instance_data[instance].rxAntennaDelay = instance_data[instance].txAntennaDelay ; +//#else +// instance_data[instance].txAntennaDelay = (uint16)TX_ANT_DELAY; +// instance_data[instance].rxAntennaDelay = (uint16)RX_ANT_DELAY; +//#endif //read any data from the OTP for the TX power dwt_otpread(TXCFG_ADDRESS, otpPower, 12); @@ -603,11 +630,18 @@ void instance_config(instanceConfig_t *config) power = otpPower[(config->pulseRepFreq - DWT_PRF_16M) + (chan_idx[instance_data[instance].configData.chan] * 2)]; } +#if (SET_TXRX_DELAY == 0) // if nothing was actually programmed then set a reasonable value anyway if(instance_data[instance].txAntennaDelay == 0)//otherwise a default values should be used { instance_data[instance].rxAntennaDelay = instance_data[instance].txAntennaDelay = rfDelays[config->pulseRepFreq - DWT_PRF_16M]; } +#else + instance_data[instance].txAntennaDelay = (uint16)TX_ANT_DELAY; + instance_data[instance].rxAntennaDelay = (uint16)RX_ANT_DELAY; +#endif + + // ------------------------------------------------------------------------------------------------------------------- // set the antenna delay, we assume that the RX is the same as TX. -- GitLab