From fda081c1f03e541256716bbf63b9eafc371929cf Mon Sep 17 00:00:00 2001 From: nitiantuhao <2062405236@qq.com> Date: Wed, 8 Apr 2026 07:38:46 +0800 Subject: [PATCH] 1.0 --- .claude/settings.local.json | 7 + .idea/claudeCodeTabState.xml | 20 + .../UM2356-VL53L1X-User_Manual_rev1.pdf | Bin 0 -> 952926 bytes App/VL53L1X_API/core/inc/vl53l1_api.h | 1142 ++ .../core/inc/vl53l1_api_calibration.h | 236 + App/VL53L1X_API/core/inc/vl53l1_api_core.h | 1183 ++ App/VL53L1X_API/core/inc/vl53l1_api_debug.h | 354 + .../core/inc/vl53l1_api_preset_modes.h | 471 + App/VL53L1X_API/core/inc/vl53l1_api_strings.h | 159 + App/VL53L1X_API/core/inc/vl53l1_core.h | 1090 ++ .../core/inc/vl53l1_core_support.h | 222 + App/VL53L1X_API/core/inc/vl53l1_def.h | 603 + App/VL53L1X_API/core/inc/vl53l1_error_codes.h | 253 + .../core/inc/vl53l1_error_exceptions.h | 93 + .../core/inc/vl53l1_error_strings.h | 209 + App/VL53L1X_API/core/inc/vl53l1_ll_def.h | 1098 ++ App/VL53L1X_API/core/inc/vl53l1_ll_device.h | 698 + App/VL53L1X_API/core/inc/vl53l1_nvm_map.h | 3022 ++++ .../core/inc/vl53l1_preset_setup.h | 72 + .../core/inc/vl53l1_register_funcs.h | 1635 +++ .../core/inc/vl53l1_register_map.h | 11895 ++++++++++++++++ .../core/inc/vl53l1_register_settings.h | 222 + .../core/inc/vl53l1_register_structs.h | 4402 ++++++ .../core/inc/vl53l1_silicon_core.h | 100 + .../core/inc/vl53l1_tuning_parm_defaults.h | 210 + App/VL53L1X_API/core/inc/vl53l1_wait.h | 276 + App/VL53L1X_API/core/src/vl53l1_api.c | 2937 ++++ .../core/src/vl53l1_api_calibration.c | 876 ++ App/VL53L1X_API/core/src/vl53l1_api_core.c | 3533 +++++ App/VL53L1X_API/core/src/vl53l1_api_debug.c | 1741 +++ .../core/src/vl53l1_api_preset_modes.c | 1407 ++ App/VL53L1X_API/core/src/vl53l1_api_strings.c | 220 + App/VL53L1X_API/core/src/vl53l1_core.c | 2349 +++ .../core/src/vl53l1_core_support.c | 445 + .../core/src/vl53l1_error_strings.c | 304 + .../core/src/vl53l1_register_funcs.c | 4489 ++++++ .../core/src/vl53l1_silicon_core.c | 146 + App/VL53L1X_API/core/src/vl53l1_wait.c | 558 + .../platform/inc/vl53l1_platform.h | 431 + .../platform/inc/vl53l1_platform_init.h | 90 + .../inc/vl53l1_platform_ipp_imports.h | 6 + .../platform/inc/vl53l1_platform_log.h | 223 + .../inc/vl53l1_platform_user_config.h | 84 + .../platform/inc/vl53l1_platform_user_data.h | 122 + .../inc/vl53l1_platform_user_defines.h | 95 + App/VL53L1X_API/platform/inc/vl53l1_types.h | 114 + .../platform/src/vl53l1_platform.c | 860 ++ .../platform/src/vl53l1_platform_init.c | 128 + .../platform/src/vl53l1_platform_log.c | 131 + Doc/近墙猛修问题.md | 133 + 修改建议报告.md | 243 + 51 files changed, 51337 insertions(+) create mode 100644 .claude/settings.local.json create mode 100644 .idea/claudeCodeTabState.xml create mode 100644 App/VL53L1X_API/UM2356-VL53L1X-User_Manual_rev1.pdf create mode 100644 App/VL53L1X_API/core/inc/vl53l1_api.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_api_calibration.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_api_core.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_api_debug.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_api_preset_modes.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_api_strings.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_core.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_core_support.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_def.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_error_codes.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_error_exceptions.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_error_strings.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_ll_def.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_ll_device.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_nvm_map.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_preset_setup.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_register_funcs.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_register_map.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_register_settings.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_register_structs.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_silicon_core.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_tuning_parm_defaults.h create mode 100644 App/VL53L1X_API/core/inc/vl53l1_wait.h create mode 100644 App/VL53L1X_API/core/src/vl53l1_api.c create mode 100644 App/VL53L1X_API/core/src/vl53l1_api_calibration.c create mode 100644 App/VL53L1X_API/core/src/vl53l1_api_core.c create mode 100644 App/VL53L1X_API/core/src/vl53l1_api_debug.c create mode 100644 App/VL53L1X_API/core/src/vl53l1_api_preset_modes.c create mode 100644 App/VL53L1X_API/core/src/vl53l1_api_strings.c create mode 100644 App/VL53L1X_API/core/src/vl53l1_core.c create mode 100644 App/VL53L1X_API/core/src/vl53l1_core_support.c create mode 100644 App/VL53L1X_API/core/src/vl53l1_error_strings.c create mode 100644 App/VL53L1X_API/core/src/vl53l1_register_funcs.c create mode 100644 App/VL53L1X_API/core/src/vl53l1_silicon_core.c create mode 100644 App/VL53L1X_API/core/src/vl53l1_wait.c create mode 100644 App/VL53L1X_API/platform/inc/vl53l1_platform.h create mode 100644 App/VL53L1X_API/platform/inc/vl53l1_platform_init.h create mode 100644 App/VL53L1X_API/platform/inc/vl53l1_platform_ipp_imports.h create mode 100644 App/VL53L1X_API/platform/inc/vl53l1_platform_log.h create mode 100644 App/VL53L1X_API/platform/inc/vl53l1_platform_user_config.h create mode 100644 App/VL53L1X_API/platform/inc/vl53l1_platform_user_data.h create mode 100644 App/VL53L1X_API/platform/inc/vl53l1_platform_user_defines.h create mode 100644 App/VL53L1X_API/platform/inc/vl53l1_types.h create mode 100644 App/VL53L1X_API/platform/src/vl53l1_platform.c create mode 100644 App/VL53L1X_API/platform/src/vl53l1_platform_init.c create mode 100644 App/VL53L1X_API/platform/src/vl53l1_platform_log.c create mode 100644 Doc/近墙猛修问题.md create mode 100644 修改建议报告.md diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..2cfb469 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "Bash(xargs wc:*)" + ] + } +} diff --git a/.idea/claudeCodeTabState.xml b/.idea/claudeCodeTabState.xml new file mode 100644 index 0000000..f16edb6 --- /dev/null +++ b/.idea/claudeCodeTabState.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/App/VL53L1X_API/UM2356-VL53L1X-User_Manual_rev1.pdf b/App/VL53L1X_API/UM2356-VL53L1X-User_Manual_rev1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..35d1a8472bdd1efb4780181545c9769ae43082b8 GIT binary patch literal 952926 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

d1qw*?R1|RAhY@ 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 z z4P9oSOs%M7F^jA5kA$a;MUPJ2tDP?U{!YbK6=Ki7 z&IY|-sHxbHMd?<*RS^HV*_0F&9XnwSK(4gFwe&r(o;o*;s_%iDwLYU^Q%!Qp%D+`$ z_1cZis=oi{6xFLiRgu>~PK zIailY_aLH~*>Q1DkCINT%M{*rFeaBX`w%-LcJr1Q%`UdKws>!-;n(yoUc(R0ruQKX zbfhDOy(az-rl25%1rvkfDz*Tn#LF87r%?pQW+&cWFk>S{7WYSqqMvAEszU1tt#<}# zx7_<`Cc;rkVWFs)uibM43&Nqi_wp@PmPnuZm6}lzTk}-J%&Y&2aR^2a>2{_pPVQ(d z`YG^yG4@b2<2!VaeH8kF2tj5Gzsb~_6#qVuSd-J*oTZk;y)#=kaP+*iZJyu1&SIMI zTuQ?v&#)=k2*7RAI%SiFHjutQ;zv*D%xnkl^z9-D;0Zh_2Y?gyr`c5~63k;4e6 zUhS$YyPYrXE^wwfw5@tPtov5R0{IUqhulGWP_1}z=YQqD+N~}0JWH2*kIhV zD=U6^l-Ybpmls(Nyb7*SN6(RLUG*d>3%5u_R9x_3M~>I614vVON^vLB+WDnsT=gx3 z`*ci(cv+yi1DPD}T7T3=EMgZv6IqA$nqL%gZu?*rGx2~gvBY>wo`W9T8lqg@+j1@zzPbsr|hmMtZ=(K8vuvw z!JU%}bR6#Zr>!*s*HNveYj>Unt_p1ZlsezmHd=uT!yTdl!}ksp$d`XVOGV}jkeKdk zmf^dl2XtFcPGoH}q-L%PW2IeD5M^q;u)j;;2^#sL-VriLUfTwYleh-<)c8aBF76%vjFDyXu_C(fuskcKo^Y||E z+vX=n*Kf7S%KLpWK}3q!XE}9`SM~G}zhq9r4l}U_fQ7kduIY4Dc)cgw=qv4L5o3}} zZqexDy=EI(Hz=yW+J$A`9x0dEI?K(K*8u(xM<49u)S>$$&CI|W zWIoA9LyIrm(Ch54B-Gh&EhU3)bd)nW7~MCE%t3M9PP63P73M$&1ltN3Fht=mZobqI zfp(~SZD~1@RgE&T8&W`#3RoUwf7#<&BvZXL+0o-IXcK!lpDZ&5FXS$bD=Ru>v0^#f zn=*$q@5oT;*})qY#8H0Rz0edk0xC7f-%4s$)~~;5u>>>JxWGynsy{q8=1;iGzi{)d+zTnY02+Gx)mwe%jaMx#P(zbNcPq5yDDdjb zIc>qzEbXIVQkvp<`nY|O4lLQ?LR09tP-lx8gV3M2@xvxOFk@94@(nb#ssgjG*_&bX z$v3mw;WIp^8#6CvD?VcV{HF;Sa7)_s_zUY1!TDds$E^1u#G0QRJ zV%>dAHeWA6X^!Z5xW=IldQyki0z#j_G#+7x zGbb~Z-n=8z-L+5Y)Tl-ejaz>SWy7*^^%x5)pwDgT7{Xkb`{`I*ifYH>06srTe-t_k zzQksR=zYQQCxe+~TY+#D@O>)wJGYxz2P*-?8SH)@-E)zvq0I`Zk2%(^^PD%HM-edv zE>!gYO^bY-7MR#*PxVDYjDlS6o96q!x6jAZJ)WgjE&zcb-v=MmWB~mU{0IDSlFh;kflg_sq2h*` z{8}yO9nCxrB2Sm@E8aZ;hdD%_W3rDTjYSv7#O_=tizuuG-yp}70NynxEQU0c45QIU z3eukmBHpRW4=;2X7E=Ik&rwm7eiU5h;XG(hD_15ebV!$rKQkD)CcjgASMa-rF4 zVMKkk0%xArD|yJ8zOBrKb#@%{633YsSj`X!k4(Y07g%3A_Q45M5e1;34QT2M7|YL^ z#|Jh-Pp;5soXKy*8rWW@cj^WeD20Trb0C4`PH=KzwC{}GZqQ1%6(%4o@8WH?r(h{r z>#J@=Y1=2j(q0;64}Qu&a+kHdt}#6ZmU%g97IY0)0p{pX?%jjgNtl_3(A36zF3lv-tCxpLP_FmS9PTg%+w3My6g1-v~mA9Hu%7oi}Ad#~M)%gd7*qJudLZZ>H zcs!mrzaQF9PUx7Tw+DJ@(T+xa?N;q`RyJp9+ubh+Vsi-78LyVe_R{Ggx)p z2Z)av%Xu~}tAG;Asi(Qk0SfW>NG|z4RezAMMBC_k9qs|f32nE4D#tmgwpFIPuN>Ue z4zgYd%Ms%>%_f97+_jGB#O$hsN=*e(1YX1bjvu^-biJZGz`I= zY%{^^zl!xlFqJVeq-6N)`tQq{Wq!%b<)a@ zlBTfv45b2N8RZkFVY+?vbi1zEuL_j$Qr$$R{zC3%!emVL)tVP_*i_jr z@Q6^fFv;X`Y~XFl#ZNLjhq&$>*`xBIw1Wx8v|m7nik)-#jtt?AR1Y_=w3YK++j!ML zf)PJ^vE0{Uwj;>z`GF$=5gk@EjWV(pqD>FY6()Y|v2%G&b8Si2 zKP=73%DxM^_!w-UQt&tTNy}WofUNK=dej9QNGd(XTwR3DSQ(lOvtRN&Xzb}u`B3N( z9}j*;!Jzkz(3f8jTdFjyZK~tCCQ20~*k#NktJ3_5erucWk)HA}XTcR_8!e3iDA8(PuJzp2K>dx;ri zC~X>tf*4y!-YW?1I?)(xd?v+?KKYM`3NandN^KMV=vT-Ned}4ZsLW`8isY=|te|N`g-f6%xr^6ik zmZ|>3K~^XQR9Zc8zdpk~FXx?l8E4L_;&>YAq4?*nt?)pBHq-kJhdEmxncj%w7rr-H zUDvh{+s-bFmIhD*jN&ARW`&nR^ws;hov|iA*|mg?k&pz3g4P-d!-!YboMmrh$4JeZ zhv`N0rW)?InuXlBq{Lse?I^-kn+4|%oZJ&%9 zm-viF6{t=r)(6@8ian)usowT=nFIl1M?_u|_x#&lO5yz*EoB{v+*Ig6-6Z>0?}iz= zn)kQZb=!QU<~QQ%3S7+6*ELie+T)^glZ93*2xr2stxQyWMVi%gSKk7!FmJmcs(aNQ zn(dUV_>{b<8N^dzCa7Kb)u|i&$|?XkgtD7q60&d;#V&z#Iia;mpf8y;ujKF&_xqelhB?^KVDjCuJ4_MUfa&yzHSD$0MZFlud-`BJ3;aB7SJX3dM=S+|v zIR#q0b3A$XeTzlD-byWBYfqh=VN0z1Qhn>;vSNzK+qy~OY};k^g;Lpr2PIJd=FERM zSvwjlAM=;<7#?5Uzo()DBZfn*wf%lseD?T9S@;l%-IFMU{0G&Vb0rL+{CdJt2=Q3p zyOMi%k{7!FJl)ZSs^m+CPQ2bk=bj^K!C{GG(Yatcc6?bb2CN7 z544Qs5M%sWy_efx7mLtWBS}~ir-Zkzq9=3Vi-gGA;XDFn9_{Z=BP_EQGljk=scAgR z-lkmltO>Wnd)hX;_BfXKgew=ugqBdekAgt9i%(nvX&Kssw{nN%aHfLP2z(JW2mKkQy9odj`xbv-5WaK`;ci-}@2(wlNtQpZ0*89noVfBYy`|NGa`l86Mj z)j4YYX7eN6e>k}zgG7j^9BddX7|O!}?l)&KoEP5oJ{}Xf@)+Ih_7%5yHdIq z62D*~n(yaFkP8lj^^R8zTNin;I%j-P2U;_@!1Y|EI4Yr9R~7L(38*`_V+C!l z*&+{eg8uV5TatRFr6-nQS-Op|oaW3zWK*^vpxBNb+o)iF?u;DB;B@ipwT;BdI1KK^ zkF0h&KGh^ze=ozmD$`fuyx|3I{p+_aND#9@@%Au8p9KL}4M9t__GrjCAAv&-bH{gY zWH@;QMqkT8<)lHU({j18PD{O;haD(>x}wwu#-?==~; zQizb_a}_$q?u-!JGPAa5VdE|)jEd}(c|6OEUPX48Ag^+0=6-kzH;zS58g(}4=}H>N zrr&5hJn0U#7XLUC=<~?>0~SbTfA;bo>ryK4z`iz-G>8S~egl-l3ECG$6=+Pw#VX}C zVW^v(mWC&Ac2EG_PyS1(D27gTzg~kO>$S}ODBB&h?2)6#8_>h|a?>rA=%I0N)4E%^W=FUA>S8B% zmjhm@la?5DfcF@?CbOED2}3H_ob4km(*LIcic?F>5_x@gA5-~kBVWb7yDjbcM}=~+ z$`Blwzt=103OTwO#r+zEr7vp-vUI*AgF5azv%0NUh<0m=>NlT~M|GDrY9+6a3yF|N zD2o|rb{-n#l;N2{gJ?Y2U>bVn6#Q7uE-)(r3b$3ZUQhB~1oG_AZv!SFR;#~xFb#-V zb1!2&+1xt$f_mOE8GL=wLAgQ(0IDK13zLocgG@cL$r(`prO!a>I+~7-oxJ6dZFAsP zU-a}A*k;F#EiT0^Db*fgRuHhgJc7#cx6Q)t^?3Y^G!muSu3PJ{n=v}No4<*F|P=9!%{xEegMmcDdfH+H7mb_0M{krJCEd_d|+j8;&Uynf>bd9hq;} zeIHn01nolv%Gqu4vIC|tFD)?&2)mA;1zE5dnVg%oTH}IO`N~NTHrsm1$2Htx-I zIhyS>uXo`yRu2xRjHQdDIpB25Eb6p)d)AmQc|QN)e5R{g3I^2AGK>s8I^?-;@E{u* zAwBB6ZDR0(U6DwP-@Y~ZmhkkR?r1>v!5h2b2C@Jb8IU>&P=y&crTCJtX0bMn8U+VB zCW<-V#B|UJP6!=JgeIG{1(8zUKC_{^Wx+c7CZl^-u9oldGslDnsob(j7}IZ5_`$xs zZ~v(;3u_2Q1Vcs5x29sh!Wra$>4*Zh77b9^@@Dth_|ab@^ksZB z+#&dCx}79MKF0#gh(nCHX5xm?2c)}8r^D}+^m_UhF%#7jFAB>(^#LsEE1d8?ayLmh z!aao#8kFrUYJ3?DHdpuc9xz52AvWY;iqPzpC}2>~nKae#C30jZ^N15ul7AWt%WK)% zc9!fe{nV5GEvy20MG*Y-Cws=m)d`g(4qxUinf5Vnfbi`QBTn+zh|}lqf6{w6`WsP1 z>AMqoKGc~e$Uan9ZUi$=rfJ@#GW*h}k>4MR8wV0i%D0XSU9Mff1>ka%#ysIm(~nMgyIZzoq~@O> z4x=2P`n9m&)&QRcN^B;~25HG`Z^M5QFt5SxJIiFG8T?0A63ir|w?RKt7MEo^qTF%F zdm7B$e0fqS^!kpK2VE>DA}3jfX+@?&dski1Ze?ibB*bC4sPUe&L$kzn^hNwr;+JG( zp@j3{M})o6kK1M4QDo%^wGtx8{`12SoHNTq|Guu8S)oyRmic=xgYuYsO@3+_%x(b< z)+r&Ed!ujDkjc@46iF#&DVM3pr)94?HVMj0WjtlJz{Fsn$R^g^iS`T~*IqzZmyKRL z)9ti9atdk~f4kYb&)JEy+bJDjgPF$+q26bzHGpP~my-U&*{RJDB={(a`%PYWro&x0 zS@eJLb(UdG{^8q4K@e$0x>KaPMhMc~4bnZNyA|oqA>AM)j1HA%bc}8o4YCmq2ES+j z=j{{6j=kBj?ZtiE_xGyvIzJSjntnztl)mEP|GM@|+s+P4b_XB8mGM(^;_XI3LU)eC zMqZN2)wtRiPq7Ue5G6`kMolLzX;;BXkUm7?wT__X*wu3}qN|SDzG|1lw^!Wz^(J+@ z%&jEqIkxtC_jADwE!O!L#O1EWgPw z0R^sCpj@;Ca;2J+yy2IM+?RlP*f>x;s9|KU5DAnJqy z2}D4{>}ZzKxDHq`7z?E?8vT+5k}IQLM7t0Ro5xQlzgVqvJRoai{p8Ks#Rh4u+wA$*_Gf@@uZ+L9{hc}^r+{_uqKKBuoW zQDFZyHhSJo{9(#f$eybQ)0yxSK>?O$G$+pN?J6fcUkQQf-25BXYdC;Db2I5IT_0T` zbinju?8aKlWsXAjSz8Pcm7gViiq|DU}={=o#|^A(-9cY*J@TCm z&noFea}kXG4GR7jv)#-4=@jmK^KZ{L+5a_B(Yf{vpat!aK|iWBrN!Z-XX+%AU6d<< z8JID?sh7SDsX1CbQ*{Uq+;fRt81Ke^X!(452MQ}_FddzIyMQa)!glkz`cv3mp&3mu zuK(ks9Uchcc#y~aFzTAo{C9BD ze=K!;cIo7TNbfRj-`Fm7yQHP5YMSabvS_prI8#Yeq}!Y=lktU>j%^eE?%2fyYN|$i(={bK3Zb7UPohxbX?{&Uxeicis~(0grp%$eYE(4x|*W4 zEK%(0eRI`seg|Y?bRtXYX=5T zSl^}d^yINv20(p_cnMqvCi_b-h>g+nYNimnimwwS&HnsgJWAzyPdX!0JmKzItK$}8 zj~}zu>Y=s4#F`ek=}s4t-wSv?a2Q!$&u#K@hq(hxvs&+@RS}Ejy7WBA(twC$vwy$1 zp3}yU*2=_)yoL{Onwk#LX5!C&RBn93Er*aEOhQl(cc&#io4yE=lCHK*&DpaNevK1n%Uiv+(68uBGjM5ZvOiPW@P4p{`zfkQ zV}XtxMr9oOqy*@0{hTCH>3O7);<<6Ha)|vivUOL+=qOAt%;q?I)u;e4;BIa2Z(EsP z!#eMNS;nu)=xxALH6qbk!>qbJ%!HLx1I>$KwH}Rp4mgiK7^P6oO4!E2W^cM0GqrJH z4@KW0!x?BR&pCsdOZnAY{4ODg_)e#fA5qNEEN+&;dnIvd_qzEIny;IaZzfnmCA(kV zT#5#gLt^2smiF^!R2zZH^#YU_jqoVVm+RB`QkLgW2Qh%Tt(eHm6-syOV87Y=`tl_L z&MztRia_3-GKC`Ts=~c6P7Hrwyy0r!w53nzYmRtr*Efh*ATD_rcUcBqyZ#<~D z%x<-iP(x)Pb~)q#9>(?YTv|bAa~p4HpU4!sh*a8Gc$(&Bg2Ew=h?gceaH)F{rHj zL>}(B z+k~ohpqqdBR#z!AvRiKFgj`6zf@WDqU!{F?H|Sb45G z^7yLshG8cL5F&ZkQP#?}a-lunGwCT)RA`2HF_~4E#RqjW{cvM)5lx)VDuU%dBm{Y9 zd3Q>z3B7d|lDj#md$AQr8=l?kWx~IUMf`GOaI7|m2=|>80Ew7%KUfRr4NTB%T11Tn zR&9!A!J4h=iZm8#&4$<(f!H0k;r4+97d8Gg&0FPyK@GRpd&h2=3{vk!Ce&BsMp!B+ zjSuyA>=r%UJFJ7Wa#8iQNZYY6gM6(X_{KVvzKjXz16lW_$a={jUn*}46 z)-=mU<9p{w4+7*ya|9YM_o|ocgRDntZp;-2fpMd0AJ=FX9F{^(k=`CSMZyYmsQCk0 zUFWZ@oD&+>4lmma#ky)VyM2EVxw^G=eVxjGvkd-GD&?W!U)z;&JF^X;#y0L1p78GX zVnYL@4Yc@Oje^?KeRw5L$->-HOy>(P;r&x>(0y}L^;)eGuW~;r{&(qfE@oPvXMX$r z=BoPQRd;JN5HEWcNTxj`*bAf$>a%Xj4h`0tWnT2{=Uf{LhSk#>JkF2}qV#@0aJOCm znbJ}6e{I36Mx*I|@ujFmeo*Y;DiI?!vmImp^PFAw_4Jk&^oAQpm(HXkL485ETWAT; zB31pWWn^T*)k}6g-g+ZD-x<5jCt>Ad_J@uQ2=@LT1$j=wYsg-r31)_+1xxctycu9* zqR)P@u_wX$u$zKv$uyghEyvwYEcS9YT+^u{c77-H*j$sfwKdzRr$0zxaX{szS^TSE z-0cri$7vKL!L;kz_?mkTV6@SgfU9A)5xO%IW@VPbeH?DIAmz@jC060{T>o7!F&+5N z)~u(CX;_2DMMc5{Sz6GlMLMg(sNTbnjb!zfh?u8pz=V>7WH$i`)2C}3zu?laPs@RL zQ=9sIvu-6_sD=eFo-0Avh5vT8z*MoBYGn0uXhdPIR+WZBUut{Q&c>cCQ_1eH#-wnP ztYdrPcbMqONX(meo>HO+$Bzi`_3CCBj63|p&-S0)$!nUR6JA3O?n|PJnXmLD!Y^oi zekIW+S9p4Gm-V()wqwqHX_&w*c}RA^Z%(7Vkj}@y8lRpMuawaGcM9*9Lu6;c>Ls=& z=(7cmnCJyv(#El}1>Qq>@GO6D$hRqTO^CE?aKk`b6|HFDlw*REC4UPJ9ggt*FJ`-h z&yuQgx_t$fTJ=&>-DtoT_hz8$lx2Gw;IJx*+B{l6Riwn(N5u*4&g(H2q&I+rR*9T) zepZXS;35A`6NaUF|sTSt;sjqv#yd1BmFLk`oK0s6GuD9#D>N-KObfRXJwpXa{s zY}6eWovxxsL_dAH&$J9e^>t?H)E`7!&7OC+3O1H}J_-KHNqp}ed^YSo0MHdx9O+Jb zu$*5>(xT(AW&a!)C{2di6mU%_L5>A~V23D)Ol9?rW&ozj);1~wc0 zU+mG*O~wEFr*^iJeI7G_loB+AeZv20+44Q$b%e#}Bix2^A0P|)vlL!Ga zW9ll*I513#NI4eL;G$|eq8jy8yKQ_@;|LJE)1MC*bG-4Hy-wv8awVv@(HknaegFm^ z@Z~()D`FU@cyjZGPs8^n=sqpVsBR7M)WZtgJIBxPf>cL}v0JAI&<=DKn!4rhU-9GE z@LeS~H!n^Oe2V}+2BXqYSxs<}0=lYN)AIY)9uo^_rBsiA#6rflB03iih|E!BqfTpa zJ=!!U>AbipZM4122xmdE>mn?!{jz7@Mu34AqX1^jhkx_p^e(;ibGM2dnqD-rLAEv% zop2ahg_l150Z@b{Vo%A2Pst(8(4-i|321QUgwCNWDMuE*%m5K84ew20O3KMW5SNk?68m}H@RagcdHS*+VrNI(Do;63J% z^{`2$DQRGz>!j{u?VE7bO$ijgVpXxuPK=ifZ_ZibJVr(f-p48plo@7rN%g(gCw`+> zxTh&ABZK~x%fuhJsTvmQiFV>fUpuW*?wQ!8y#fHAz0k7ke3$X&(=7ax4dIZFJIm`K zZ+FhMY0S7!h0H^yA0-oKJ=myD}{1V*_F!s`%W_wR0A?iq)4ADZOy*1p+M3r_y{T=N$V z;uM!LD_x^&c3QDA6gMSWg#TSgcY#u^B>Bnq=L&<&5PdrvzfX!2Re$n0(D9pX4#@nv zNEZsWm%RJq_J~7+I5}(~38=32-yx8NdkAz19NhKSAZawz1mzbWKG}q^)JU_R66Z zgsb*zM^(&zt%j1pPuqm8pzioSk%?B5nMF_TN_o`(qk9UKPo+u^T2~!BPG_Am*=M%M zBjmyFTs}s-;I5zPAEPgWH@wwauA676>7DNV!(X$-1yv7O#BatD;YV$Gpm&wEzA97kf! z_i={!Tjqo<R-zQ9Cn;+p*0O{~z<0Ej6K|!*eH` z`Pj5A4>dTti-6{YQR9N~tOV8)f*k`I@ck}Ow4A17oI024(I-WS!Z4r3UFTNbcgJBy z^Gu#EZXOq=!+oiLo}E&VynB14mvwNPV*;Y@9HGeA^w=K|ZADg)?Cd>%m~2r)=lDap zLV4UmT30Wox?zttW0%(i5_q2O_Fieibj+U*`Xu~Frv;JSXrefxagsQ*8#S?D3+~EV zUNa_f=rL%k{qx2~(osA^#?_vE2*MyfQ!G91+bQX4#N#b|(6R=IL-HcsD_zLzYLN_T zB6;q>jQah46U9RP@_2EwXIb5cf{Q>Hf~|N-A`*0`y#Qq~i%BbIvm=G6(ba1pIB^{C zt5Vo&mHI|Ky&STws*B?6EiKyq!^jFOA9VvV{+vbCN!<)rRc=-*fyVvttr=dWewqC& zG|vmY*zNq+U`_Iyb>Z#x4u?Tq_37w&UQt%w^(&mpHNKrpTRZRlyk%$qgoC8l4;o27 zeAGsI7tca^Yi2f1ocZu=+tS*fz5am{gP9zh%fp<$xvk{SNnvlWl_fzlm}9>;8KQeI zAx>LR7$p9E`8O6p0z-z{4BE_lcg+}ny%c8J^wYvjwb1tXM_9#Hzvt$DXa*!|k+ zPrxzvVQte8e%3xFmA)S}44Be#L2ZD!ej{#Qwnk>T%j>CdxgljIhL1vXd4~>B~>Ed$bZa+QW|HAB? zEXRAa45k3IRGg3_l&BLr&OdqmI8zX7TFpzUAFG_bugGRe8{f#LckrH$-$Pg&;#qMa z!_^U4Td+ou5U1b54K?rI#P*z7bBnc=QhNQKmlMAu*WC-$KBB`q5Cun=#GA>mwS5Kt zhe6!Y`#Jt(#3i{iQpQPAl7?CPd&NPM|GkGjpUt;RHm>VKb*9rNue&GDhtW9~GVK#k z4$QaUyvG?I*ZCOFq)Zb~nyt;zc_QGCMo$cDiHGSQiS+p(cq*!_RyL-|^6Q-cMl0*? z|5cIKEy9&NkSaLmf}fP(r~dH14}F~Qm7d-evlD{1kPLNP9Q_S0LXKMqBGfdkAdl1# z|31^MIrdQ7(XJD7@2>lEu)}p_g&J3Fg_GoA0c@VP)!kMXeq-AOZp$TVWIK6&X<)rq z&||wZ-bK${C~88nKgiBqPOsof=Y)oVX&p3Xg$sKC%jW>d8^igE875nr9Ivs5Cf1}H z(>J%x+3kh`rzDV?5$?w%$mf3k&=#`YgbRUKSh9G!lt6!lG;w}}fknZPc)%dI?bsGx|=_Q@bY)#*B_4Z(`OH+Jdnq~gb zF16enKOAfl+tUBBGx@N|gjC@2f-ta#Kl|!{djrKdFk~~~*KoIc`nGn$zAeeS`eVdkn!P6@Nco?t+`x8m@c#X(gU$P|OQJSu ze90=jn4&C}xNkWogQy4}_6$35NIzG9REwodcXDYtJ&APJcOV>`#p!4vVhC)w8}0LjSAF+6mXe(2Mw`c8Q5lwU zU`nK|3oI&M5Qexe30qBA1Z|D>c|wK!O?(OjuN5O%oW7zp-*PH{l#0HpF#2sZ1oycc zFIW%M&X2=BY7MuC9O~uJ2(Mh(rQip|Hpo?UgpCB6$h;GRG*0r4yZcXoRNz}hH}rE7 zG5ww#?HUq9f~#Gf}{!M4Mw!@O_Em z)K>7e$k(+A*yeev@1*NHOwYzl;AhVj!O`+YYZ} z3LD=tGHP0z4F^!pXihOItQsZ2->@3kuGg{P%gcWnVWr?|$HN4&<)vo=nZy*`tQ?UhJll?Rs!w)xL*Nn0BCy5gfgm7m3uX32awDDAv`g z9Z2bE$RV7KZkwC?+vC1tc3|nf2uv9#f70(-K-CqjW~nDFvzdSkktvmh;<-041a*uJGMMcsHVG^2w}F zY%l6WfAJdpRdwh_Lq)pfrRw~rM)h+7422ya^_{8#5@_WCzIMPUNZ@YH>&`KXv?24< z7JB>cq_5a}Ya|3`tc5F*?2I@StU-PLwphjv1y_hGTrWu69p09qDtD95y1M;C8HM48 zC!j>TuavI@e6x3j|M`su0PEKc&p@zn+}2#SE>j145+D>V#PeOfJaQ0wr*8#Lgm{1$ zK3O3Ai%@+IAiV5FCa90kvI6Um?H>te@{X=&P|qAiPm&&$t<9s*@;{pDCco~#k{^Ym zcB?=}S_t;ko&k|8?8d5wg75>2Pw{!@c3eE4K;LX$#k?Ig$_Bfp@FKmfW^Z&nYJ@yl z{MvMhbau&Q$i>zTGlizANGthsF>R}E`}|ka1Pc~1??u%6C9dnK5qJo-vCUxk*UTr= z`H-1AW~0Ts_IUp})ggueP;}ngt&UNP(+}RkZ^23BZFjgYsS}zV&pVuV-$$fmzve_s;ANi$ zFr|m_kA92@Q668c3@&>5oH8}*Y?=Z>B?Wua)+Y|0kZAxSrTGH*UZm&}elDDI))XI* zk#GLzc8}wzeB$%TJ5!`&-HIf9%KAu@oX!S5T_}em@sx)}Ri@aQ#50TeR~sjq=GF)l zE+NAK=;oSprSoo5DM`#}kJ1s0_n77Ea~5MQ4Db4ql1k{uO;^cx6QqEUls1|NoBefCmbe@zQB1jw-!|RVeXR&T8WvYHZiPwWbY!ENsH%Q!I^h; z8*b_}`f@Am=t`)W#cl$pL#l2JO%_W)CnT0mi@dGfoj(6z@Mu`Snm7*^qbn^eL+@--z+~86 zBW@!%G-lKGaZMHH!>*=VNd?Y=2(^>t;1L#bIsVnZ1zaxR3azI2W^<8$MMlvtTL4MB|kSfN02V&%c}Nx@lWM0rlT>HQFGcC%aQ+O(-c z7j*7s+harJnS0%ztlw15a~E6}t!ob+ckFK8e*ke0PK~PRkQ^t#vXH!K)(ZmCqRBRC z_gUXi&gm!PMG!A%VAPe7)trGGH8TbF4-p!oa~synkGyW&YYR;YU(y9;M{Q@PBhGVi zSmH#3g~uJvGH=kUC_LcvfawHa2_G7KlUe>kQ?)tnt~ z?9&2;#y@HdhPdFaxj}x}G7vt{uJI_V6}X~>F4(h5_-jNLyt1Nh(vsaeJxR) zdFhJ)OWtI*2X)+))LYJ+Po-j7OoxO+Brtz5+CzuGJ@pp!ZvK6%jx6C=5lu=s*PcqBGFLPKDkB;31 z#^K(}!vRaNjeRTh+#-d)%qD==F)Z0C979jsdH(A&=lM<)?!SP-zSX-RpcAa89{@n*|T4;dfrI#4p2+I2L#(x&ko^0P2Y;#u`fj4^KmZ4 zO+;Zlx4;{pVxc<0!|7;;^7xvdezq@>xZaa;SGoMc_>?XVjb~51ru$caqEgwL++S)r zY9BZBr!_jwQ1U0=U#Y(nuXf{@^7hiOhRx&I$0Qc}b9q93BXy7k2MOXkJuRWaWD73` z`{JKq2Hvt1dbZ|7)%Dk=aI40}hJLl7oBY_b;aRRNr}xR*RP*Q^zTIA=(eD-Oa}tWb zi$o$?r7nePOZ}X@Atlvq;NmT$^rM@Pg}-^mcYi%&&|3M0)}38MNs3!2EQQJB2sY=) zuOtL_UTS?cNxYe)xqbePWdvhbfuw`u$&i0HmF8sRL_W|T5hjdKf)!RY9^YyL#wwjw z9SZ?@EJ@ry{6|Cih1cOC*Bxg-Ib&~)4zPLsNhd4{wf}pua~S#{`whh@VfZK4K7d7;b}$#GG85v>i5UV z_K1?NIQ_{!P&Mg49`UYGLgY|N935WJVM#5N6EQGq+Lz)XonLn9kNF`-&RNO?qd!(r zh1pLbldEuH{DIeO+m(L=Ir1eXxaExC!^n?B#a+1~t}t7qZZHvdV8X}#YhNixHHU?* z3BMED7^kw(%$j0C;`zg4zx~>REVD2t zB|%|EyIzpPpELAn0SJAg#F0QB8ud!oNH`p)Pr;TgL(i=aSKIxsb8*x_#hL}NM z?jmruC1K9o>BZInjQu-u_1%c#hgXs}Q$!VrIYz368aEy=j*Xg>S3rPp# zFCUux2?Utgxg#Dd2M$AZ2d4bd)hgR&f#}$b7Qx8(o;8jNXn*)KJcB)`VE-RU>ztfc z$wuJ~&J9)W>pE4brwZoRINowW%}3aBMwGxM4#NrC$tTx286Kg|`c^R7O{tnJen3V4 zmHsmYR@rKu%V_j88PC;eNonr6*)du974x~O;`;X+G4+q3hEse;BQo58$hyEBy--*4 zs8FQ|i8w1+s!RpjS&13^ovzBtJAt3f=pGl^8V!FW&D+yvhwL#36_3hmhFc^`4A;FL ztKq}umsPI5w8Bqr=8;`b{tsiGXBZ=?rG2jF-vXS4E@7=wBP3}*No^7oZ@Thv%$?d0 zev}d=Hf>r&kH06?ayy{4{Evw8W;94vavAR3YARSLTc}mof5;eq$kS?^C?U4r`Ft__g3DOutB zy0(XnU{c~4lV6B^A5B;MJ07KMXDPr8d?`ti{v}Z(`XfJobJq_q71CxctR(yyi7~8L zWjlLeLmc3_^Ft(45)01a4+g~{!D zrIate9dDs_M^J|iy~SJ3MLGQixWNq$`jizbteQ9rPE-?$P zOM1VwY9BdpouHlt>5eObLZ3r zLwE662w1~})>0`wQ<;zwD|=#-1z`WxD?IW6FTFG1p(kv(G2O^XC{;r8lL|dl`w`csQ=)aGN$q@mq;K6A5YSJaMWWY?IuT|Pg znw_U=|639}`KUL3dQhFC7;PD>_X66BFTlNUM4q5Vd?O{C^=-8@o)((#kkN+DG?M=s z_#Rr9wSqyhyX-IT?of1k~#|1StuOFT0JrG(UeHV$jI2-#JXzgQ;xQ9dldB&Dfx)cv&G8t}met zn-}8lIkKRyFIAOS>TEEWY2RQL+<<_*l9jjo5FhveqHGtwp26vnA?&tletj->_=ewd)v-v zqyrJROY>=1*er7wyhqwR`BITiJ$qX*M=yp!l2rjud#;SyKd^Fr^fjJ0?PJ-?i-VNM z!_Ib{7QVBUjAKDk(M#IN=32OnjifSsE8mBR=f{2J4;FY)p0>t8x9jx3(<9Tt#vYyK ze;~3Gr9P#q?(Bq`cY37s-APKaRi9oS=TS0p5c1gOuzemF;!mjwn$89kRcfG%plpE+ zbK}5oW_EoGJj-<6q?W)d8T$rl4aF5e3(J)X3)N$GY0BFcw|cCIYdYbHBpQAi-Mv-W zGYOo)sxxaqmf)wPytn-a_PXf_cPOmmW#-z338cYBdkeRb&E!UKy=Z%&EsbsF>d<{0~F@>nA4`n>Za-4P5inCp5PGy8>z% z!NOS8{uACpX^_6VYo)6|T4IX1CSJDI5t)N6c$s4r4IVkGq@l!z+b{ozK>+YJM*nOZ zPM+gia*w0jhj>c55$9@bJ^hzGHRW$2uE3|&DssY6FrbM38um>6p4zk+^5nrF>&+vq zRp+&!|2oh)ccfjoU!9#|@D9(f!>3E^*~>pD$OP*5e;6`vP|Kjr-GMPWtC^mJDrHo0 z{7dPdSJlfeoP*q#q~0FzB1ghUr#V+88Z)`UoE>G)UF$zS+88y;iPJ1i11jyjRK3=+ zI@#%zNoYJVET=P35ac1U5w-#=LObPD>iXYM&8^ycV0e&_>g(J&YJul^>PmxfWZ{nm zQD0sqV7-bUBFsy{z+tpRxc!F_zb)OtPNsf-^TadTqDRX zt++q_eKf&@-PhN?D>a4vW#fX@Uv@aLnPk0XmXWtDYFrXOI@sRf)tyKV+;Wb^Zhdd3 zn$8jyLqjd6E1a8MEX@~v-=%%M{T6_^!NnS+Lctn&o*;4bO*wfNdI5Wwp!$*~l)9!g z^y%g$5hZpJvAEk_0wu|7fKmbAOB2NuS`uIds$weWUEVV&sxD)3drAnYSRDR>G)euI@5F?IqmczgK*0Icr4ig%>a)miEIlz_^aCYe^z(bB!$4 ziZ^b#!#yZmZNYJHkjgd$;0UBF=tSkM$7-emdM7jCqQ3Pe4j`WDfpeYj}I z$Q!rClczXxi6oeQO?cnS1gtO^)!c=-AIUb$%QkHdYn!jCkfJ%FXGS<)SC^`E z%NXFxyqhF%gwh8PWct zX|^X5`=+-}#3owr(sh{8*orB0a)kw2E3BF6z6^yJ^#Jvv{ zIb{jn?7EyO+TCOGr_;z;4HCVF2LVh7&1J{qq;!IoGCb--meAzk%l%xy*g*Oz zRYGc{ssgpBF>!HqXNh-1ng8t0Z*UgKb1-)0dQV|=-s(R5EB#Yuf3m!|p4R$*zH zpJAj&5+ID$M&uo6Fj2Oqh_1_%_M3w9)q3J+aHHwtIiBAv-%Nd5S+63i-ldL9IxYLU z8e<|P>|@JGUvo{4+Pmm(IDT@QKWkOHtXY?@UOjQ0RFgXe4yvd7(WJ#r7f6sVx$WDY z-UF56VMbV~Rkv|6G5$efkY{P^9-`9^s{BRs9&_luFuZ9lwCrltS`J~kSqP#u%0F$NfJ!!JR`S)xq%O&kj zKzTbzT&#!i<)_CJB2^ffx!uRvlS?5Jj0l>o5M+$<_|P&-3>$aY z9MCwPw|{Ql(jvandLazoGjTCBEVb2gMi8HBo zOp8QC1R@0-4sDu{OdO4Jz%FATIR$^x?}C; zpUoYO)ppE5m%X246QgjHzoa$`DPi8a_%*gMtG~+=6F7fH8-tF|;WDtoBCIYN zn@L|ajvK?KC7bIMXgwZ^L$qRP9;cU&#Zc?>L?orSr=z!NJ%KXaA!7=y>e1Pf^gMql z5t~}=ldVFD>6&FjoxL}AN5{|hd0Sbg4uM7Hw51BN?j<&|HdFVfq#yManQ`GRGmuiv zOWmoLH(8MO%rfK z3hT^^G8qRZ*S{&&P2-2pMbYz{dAsod%cLq~C4mEx0MbkW@%|*tH$y29=w``G8C<7GR?SxxrqysYz*+Sx8w_&w;#CFWnN)~T5KTEN;koWIz_D5Y&?5wpBvZ4v2 zcF`6U|Kk@OG(4gFD@w5tYjN4X;|0TXlaWcK-2Y*)02*x%)EwYj$CUqrgi^g!afNay z=KYImhPKl3{k+ugkJbb?zcEtJ+YEL};?$L8DC|{~<|-B;!)u#Ax*C0yuBt>65YTIQ zmevT%?s^L|YI;DR;pUn;v_USr9h3%FGI(IQvW~lNXS9ok%$bkoK&Y%%M0vrp8MVEIgp&3+Yv-MgoeSo+yv&%1=6DD1)B!dMMd=Xq%4Gi3En+S4o39uppHH|6z9&>t zx-Qn%`$x2si9&C@2v-Wt7nFcLG*?uG_;kGOPO!II;U*@A;^{S;^(em##5`i$%XeK^ zRmrYy$}j!Na6>KFxzg0tFK93*gq*5kh*i(=O^`b|U8$vH^cPXlITycGx7Wja+F*j0 z!vBz+QiN4u8|6fY#|3hCbAA&sGdjDjKbks&Teit^ru4mS=*hsPi>EbGXO8Jp4C8C2k z!X45pz=Yh7fP~F7$mN=HbQT(ExJ0fvglaHa=vQWi_(dwW2s0{(L-7=zmn8YI{BuzEjQyA~ z`A0xp!wd6V)`iXs+Vki^bYPUl18alVPRt?KCPv?S+&~J$DY&|0mzs}rtSeo@yn9?v zYcwjpzYSG|f7Q)g=XS#VOTo;CmhQ$e1lfFB0#9PXtu#8|n+5K4oefr9VUaNcKZS%Y zMh+Kt+IkyTO;;5vole|^>KOEroDfYX=U+&sRATE>M5y<}nOvT1pfKpo{mGO4V#RA6 z7s#vjvqtxpZ!Y&WJ!x6eFD&ZzQVZorfrqxgcMHLAFn zZ!gc&mV%xK``k6q1e~|#EHpgVUW#WMFLuw+VnI^tA}T9rvuf`@vkwIZtg)!XmBjfjZ95ch!^2=sv=2}Lj(R&r&(G&FVU*SdjM49MdbBZraFL2UR2H(mq6Uuh5 z{HeBKt9N(U5z>2bE;_!dPUTSas+<_5H>nkGbfI#h5bQYK+rQS8yu9#zrQ(7X-HkA| zjnxj9rq7efeR4)EA;M}7=|!!2FRH3XP2U9?N(R*Z9U_)|q4VJ~MnKuD=AY6EWyP~R zE{+d6vM)3jk0bGXaBMT4{V2tF-nwoR`fH5eQo`u(gp!*<^VR{V6)SS7?S)I$@}A0S zl?T31T?B2n&(PaQ-E!X}O`%#hA|6@Puj9=3WM2%zuI}vWzh&5YA(IQmhr{_~-tQoA z(FUcSYgWJ|?SgEp=Y2R*c*|QJf__31-sa5(y;F2$s_e8y=u0xifquKX^ru%^afVr= z4;)a)SH6!;iQ?%N!qLDn)AZKOXh2o>Y zjl`C6qS{#18(yAU8TF7D<0ACLApbv%j7>*W$r2B@ucRT`B0(g-j^S~>>I|B1L;(E3 zyh~|MKys?tuc#JQ@4-74G9b{+0k-d9jyJONTz~U5Q-D7)4a-$iAX;%>LKG~(M#8?> z;Xnw5U`@JX8ToW&P`8t>J=2*J>?p7f)9E(5BFYSkU(Z;Uo-M)FSz!Lz(hK?At(6L;BZm&hyv=7<8z8>}=j$oBGJSNAAu~ zfNpzB)b_>cbz-LADrWQXumH<6&G?raDO-`;!jk!twEAW}I&9@SY+zp)ECy_No(sQL ziY*w)U`z=ekb$D|tB_Tbbn@uxUF}?zo>M{SaH57kW9> zM`rI5d^lgLw0$-^nawZbJ>^N>m91F2-fA!Eq`8g#hkp=zc^4y;XE;AF|L%KPxc-Z0 zZ8SAQXzI*ajNJFZzZ(0c1=(fruapLr zZW+8M921Ffw>mXke>C76iY8XU(vG*g+KwwwKKnq=cPfnXd>+#NkmEO`}EgUA%JQx0)Vj_v$R8BaMtj@=SBzu{fBPk#IO$>&;y*oMO={MgGF)X<;W0 z@=aUmF0C=)hWyF%@FRQ)##Mw!Mq6p0UUDMiFGeQl46>g#F@;=ahIdImkF=&m%6fys zY>iKzEW3Upu5F}lRKB8TF=R(HN0>Jl`Bib!XH$~%hlbS=K7{-mxBhn-PY+Of5< zh-HgFPIx1tZ+spi?I|%KZTbE2RD1|)#%||rKxflBTexL1IFD8 z(Mr#-IUAA%+}N!+be%3i-yn1+p`q@5%*6PlYA(9(|Hzvaez-5Korr87E6TmMFGcgf zR>O}7Tn)gC|BJA*U~B4++c=7%NC_fHH;9yUcXxMpj7~R3D$8ca2VojRx7M z;pG49c>~Y$26lE`=bYd9#(m$P^IaWCC_97wF|K==A^1N3K%9(xZSee8hK$QjwrC!7 zccC*T+$ot_u zZ}PYT719)SGx2Euuuwtx{#}Y?#eXzG zq<==RX@rw2;xq&~2AE+mT$KEb`UX??Lv;BerX(f=6^{==GTy`)UP(JyRqkg}+u+ z)y)I`xZ_5P(R`m5KT) z=bgNjvuwM6$asi|eDRY{u*Ip%kXmzeJg$nwkUX&ImLMd0$&fF<6TejY6Naa1bil4< z(^XK;IM^(UfOR_jOe!QK*Q7-3y0ggFa1?8fs}1A zaqeqfiE;JvLLK4YrMj_HE>981mmjmjV3%GlQdnZ4!4~9&V7U`Gn@?A#s!?d8fR(^~ zJrAaPpg_D-qf+zyi<|f3qXS1*Qy#2RmS%{IOe;bqFQ!4>oQIG6gYpF*@aaJqlOk>g z#ztY-JGs#95VUJH!6H7eN~i6ym-Dxl-sQ7doVt)%%U~@ec)D9Ir!dEZDw^$#wA2&bxjLchxq0{}A3I}b9K=7JArX`ldQ_muoY5SHKjTo37gG%!x z&C#dR0m8qOF&3)Hyy0vx&?0`52W5Mzxu4z^YyrY?Cg|RZDBgCGiK@2zz`@dGIJ`%1 z2=gR@2ro(zQTcT31?R0^Llwi27fHH_g7n{%|IEIJX(A^GW*hk$ivGhmC|nTm^z?;X zXvtj2c1L0u3JL{fFTQio;h)dXqbyid{6I}Y%T>D}hHe&w7Lb}y19(9u?27$N!fxpn zY2V(v;#SV#=&lb`WGGopq&vvVMJF!QS53IpnIR()W-0cvpnF~3XqeTfnzH2FJn>9i zBBCLTkG`;zwxFh5{o_d&1`vS`Dg`2z3E;}^4TBM|YykZM&PV@Yys=btC%a@%o@8&< zR9VVDF{?G5G7P`l)JZWFYRk30C1cRi-r=>3Mj`BlmR#ebf%OVnR$oBeL7EEaJyJa9 z-w8Ko7+`lw-CG+5U`tiay14qO|AqcoN;^aKL&~Wiw`M7$&MVDt(T76m*A@C+=|GW> zslhkl9}gpR`WE;^J2`I#rUN&#g6sW*>>~XVDwmjxfd*M3IBw{3(x80+K~n7FV;w*j zWL;!prqJ+JZffmH<#7KC(0z^?oOSheaYk~w{|kI4LNXIoUbKmHN2o-c1{)R_iwCle zg=?*PHrf7(H2F3@4e~bG89R$i*`X*tnRH@w8d~|R7(?8^z;tDraKvn~^;H|xUW|+h zf{A15#7d>pb}jQMDz{q6ZkTNKItb5IuQ8wVD2E*HTAmVAJ1?$-h)ADF$&f}DF}M%0 z3&$O*<@6e_mLXt&{=MYqVg?3G`9EnQ^eZ~MZ*xp`u~juE-F<=YW0+)8)o=nyGJOb2 zD>js=E|%w0M&VjAe7+AQe;VZE-i^@B2-)UVGV4OO(J3<0*_Ysj+RYvGoBjySc(R#4 zFUJ!jW$Kdm8}qMBpmPIyI6I2xZ^%~FO|W~J^vP~a;x9&Qxk2dV6W#{AoI#Z(+*+0= zSpsdfR&F1_>*edG)P@Dz0Ir9~t(f{-fOE8B2ipLq?COhCk%xg8a&vJG4^zlzbpGh5 z${QlXo$S;UokNA0`SVUfdk%QW;jq6*Mq`LuLm@ZNec_Vhw*L9;!}b{NxsuZ%<9spy z2kKV?k?XhGqx|jY+#-Msi3;YQ2Yav%!*^LLv#jImZT!pX_C{zT%Qi5QU@8_^Hc)7~ zz^F+97JQAmdCReY}!<#9;E$!)*NJ23g)@KeFZ!A?63R4&+7Pj-nG(NJDX@Y&h> znEQB4uAOHFMy15I$@r#5W?W2}Z|Fhil-JG88Av&+%BSS-(p9R+G7dA~re!N_T>hy+ z@Djl^8&;hUFj?vC@~M=w=?K4bayqVfYZv)A9+J^2YQ+r*d=7|ak6qtPrmn;vIS`j+ z0oi{Z(_zH%`!a0JJ%8WqyUM4oaR6^N7F*&&>i}O~qVgNwOB!}Z3%+}~?+eop+!t}> z2(jn$zw>_I5vBCa|0?8Hzt5t_Eti1lR28shk7H%F zKPzE7jX*`>yYM(3K|km}j3+M^cn5qAK|N;KiEz)@=&vj?e;F;BOi)UDSVuZobcDUx z-Me;6N$(im=+Tbe4z~Omqs|a6CLC5qw}e!4*^)<`k~|^2;HIN2-*`5oUU+{*?TNvv zWywWi1xz3MF55i7_6Ps{TroKp^e9QJ>ayPg-kxuB`SQ(RMOi>CF0A}CnI$AQ_24j1 zK0hjT&s^1Xg&+8$yP?vrYMf1>Grf$yq9QNmEag=SpZ<3iqwoTqms-zr{5M(T0tAL> zYIF3wFnw()7ad9yILAPLAq0ItY+Cdu>g2bSJv8-)3_E1Fqh0st!4XY+8A9{fE`5ca z$OAPsgzH1hbP8``mL-bAgwL9SCGQd0Ju?HJS~sx35M< z=`LPyifxz4J3lcm=_OULX0c;^^7Vh=J%N?)3pegh_6Rt3A!Ki#c~KfZN8vHN6nO4A zMk7R(s3_;9nzgFPKUbjHMpc7kvxX44X`lh;oos6~+tWvhG0j6lz0IBmO!6<_dfhxzW_FE})Mw z(V*PJiu|dlG`ogJYs>Nv3xE4kxIdpVs)%6Yp^V$7RC+~0vw{F#=lO7RW%IKsH1&73(}xQ_1T9@k z;+`0{xk$lA%>Q2qR5F(+a(7BHGuUJaybjye5a&{Wyi045xL_!3B354Bo}Dc93C+TED-|L^8|)t(;DYAbJlW+=7uXrI_ZF5- zFiNPx!5YeRRhW`AZH#G@n;q*ExE=W74~f49=hDXijJYGW{^7y7plxH&?Y_oTa4H`S zyoo>75`C}cNTqPxo=@wIW0Hsd3LdXl-WBd^D9BN1Z)=pL0Aw;GG=dVXFF9~Dzee*uJn+vC_3MCP>huQrybP9s#JL8`I1G-oGCNB%R#QH?gl`9YZ~QUv*ZJU@ z$+ujBr#6!_xSvZ9-M!X-6bdB84*TlwItXl>dzC@uzVs6JysG8GyQ1hmRyJf-4yg;L znVf4ld&95!`4sOM891f%%VJ+8sPa#|rX}UwZaTQJ94M-)E~=>m)NXKeAx%E%YBWKQ zNOu+k<*P30HDfcA*6@Gd8hMVr#gHrAkn;62Usns_-AONj=1{w#u{B+JK+u0F(S?DgKnYqSdi6qJ}4yF(x%Pt$>Sk z%K>s(U^lMVa?{R$zroRa*Ee8zH_gH7d%*Bbqib^j6-rZ0zl|8H5_*te@V{yd$*JGSh(C>-m=obx9rVYqRv4@gmm`_)o~y zzg!oQl|L%f#I?maMrSG$G(2k1YIbtTBX+SpbP0Y`wPpIt1w40{FWt2Z)G>ZTul)2c z`f8-QKomjpEd*M7;_6||J%{7!0$LQY6e9>BnL?Q5R&nD}uD-L&7!$|FY{5AZ^CxEezlX(P}HAHYREUamv6!I~d zaTRSEpuCtb&VbL2m0p*?yqLF1-5-9;=WNQ09}{A6$<-RMil1-s&!E+wOK;3XzLQ-j|HYR&oS4ra!T!17 z7C#-}VWXt1o2pWWQRi68=F3m@(I-EKHhCH9Eu$sIODrpj8e8%GTTeYUt&THSzN1Kb z{CBNpyaWB<^HFI>Brx}}hFwO+x>@^Fsx^cDSk|?Zx}clakq;_Zp~% z-E3+*1ZU<^5D{$F)XigZaShlgli!b{uCtySTe7-$*joM5&{DU%JCq&%T9sWVCuuUG zn19oC5;CrOx`u@U;s%*N7oEB|;$n3opN2ad@B(P`Gqo3sJQIl_jCtkqv<7u-vfqyb znxrL4%TM1jola3^B*STlu&fO18-tqT6=U97y}YvRJG*`+gsq@I{1W(F@F=J!1K|Tv!YM=QsQ(3fy)17ia9HkmpsB2JMJDx7dt_^I7A-l!QLGVj%&`Kgxs=V4=3zerS4e11pW_{W4>W?R&U-@lbr*T>toxd?L+M`@SY^`TBOND z)x7sNXgqxO;*<$fwCb9g@~D*rB-X8CU8Cv8XwNl_gWNx}dE%ER$E?4(b9HKt11y{M zuUf4kKes>jkx0cg;}@4`saz*jXVd%l(ePOBoE zJpq*9@7vdshUrl%bj7YB9-FuJqrYPgJ zzIDfC0C{H$>=wmNs()3SaQGalyIkCC#xwg-2ED`*=8%)~f@(x&M+wbQmqa42PRwUh zgyob74>8Bkel^|lohO}Ovn@OaF0Lm%pr|}Kdc2So)|GYIami$gWPEQQZ_h|**^-n` zs??dO*9U)I{*)e2Q@^|u<~Gcl@`Wm~Qn=!mlf3tg|GQjV@3AC4#j}T=PNh@2ee+}~ zQ~??i7!EN&Pxp@)Z$Gwj%}`iQDf3yfKRHddC>iYFAG2mWil@cT8Ehp~6rwgkw4bf+h_z3EFP&azi@S5nT^|o95k>Gbv+l zdf|}~6t!Gm`FQn0&(A_iWi(H}S3*%3H|bA>ZNS#ehR{#jjzjL#z&*LUb20--jr|Ma zXY>VPnr7c1KZcTgpwy>;_ev|o-^y85->1lK398tYI6>ZV(n}qlYiI~GFwjvom^2Zw z4Hvo+v6rabLp6Stm}WZM62&Q!h2OZi{rIUagyODG>{=5LY?r1XWO#i#%6k`Z{+S5! zQA1;v6#arrA9jiDA{B$gbI?$UOwM6bwO8BdaVZQ;KztmQ*erwt%vzcCA z|5#bP&^Z|%7nGG;FjG~ab`+Itc-|?85c{SDD*9uC^ z7VF@jnQd;PE10~L`U6&ZW~VK!_PKpoXJ6KCWf2ECKYou+p9=947p#ly6M=nZ)C{*u zXyg!zUSlUPf{Tylm$Bs0t(>>vVQLPT%9iht8#~=mesgxm!%j&%N!C!Q_VW{EfBbGh zhdXreqOeuWIf;mSh_ft{S21(d@Fa*3fVqWCog&A|S(UJaQ`Y3VC{hf(i?m;4oWGHrS5P#Ly_YDgkco#As243ysb&Z>bj55Q%+N2) zHXfZweg=Q5bEd}$B0qKFi#>}WSXsf7qxK)mIHWdpto3U|qRSc4DS#*y$(ZT_{f)u< zrOxcKJPMo$Bkgnp&6@%7If#ZxAH5N8%=7~Z%UNL0y~=SvB)#}XJB@kWkzB8lR26OR0R~A$`Q;GtFP%Ee5aeIUe!B8rP5fhSK#AjkUYpE>y-f41XcMl%BUt(2cJxc{DMV+T4AMCo9%M2Dwhlc0YSQ=c+E zzlYV#N+oXei<|^=t$tj4BCM%dv9ZluN2n- z4OUkc-NpJ~94`CUeh>hISL|t7dG1*MuWz4te4v_>==urS4-5H&t}^@@xi?}mRIB+m zg)eOq1Swd*B!{=j3o`J`zDZ7FUjtmX8B4v5U-gs>obFvlB4OebGV|7*ZUnN+t+C7y zHy( zuZ5I{6*DA8UW5uRnKmaLvpF-7XzjwI8vR|u@zxj#nb>{uMk5NQo~(Niu*|^fZDh;z zUDL@^;KGFshdrCzz?FJe+HmU&w`*|wu4p7W(o9IU9O#0LT0WW+pQcC}H!fWSj#ebt`$JrnTzffG9L&EEnm{ZBF@yAJ) z&d7%XT6U4Vpi~|q`yW@Qe@&+>Q@gKnz^(m;2>rwBvlYk;$4Zy$;7g}uS=oiRoHE}`ALy(>0v#}AXP|93xCjrqN)I3Nsqb*1fzK98%5tH}a zD0?(0hlz_1jvX_gaKGHsf~Bl>7Yvh>@n*aDx}yi|?H^m{=&w?N$Z2u%l3c?CIFhhcxfEy_X5JZrgO)2reIa(XrwrY*b5-7%#ZF(K*NUT@j;^ znY(*C?0AD9-;aQ6$1Jy2R9xj`+QKTo5E9qvU2}U3h$xLxT582%Eo};9ZKw?7@5|^< z`uy z4ct?F+AIy5VKLL>07gxjfV=fpNcD=p%UJCEmh(RyY^AVbtq8kxf0@@j;)sLI2iHq! z_S+vj%4*KDa}ktHMrizpL0xyR2!|Cr7CVvl+b*{LMMou_30yfJ{k63Gs^dJIV=j#s z%uE|`5o@9h^(9LrF+Dy96Xh2c63J}X9QDnY>2P&Sfx`3}nT z3$T8EXPfVJ$!z5Kkr7OUr|mo^Ow@y_eI_H><$dvYoe3shMEFoA1yi!n*977PwB*N@ z;-~$}D>(blt?Y1yq%4TlM{lSW4d5l=ldEdmtihaC3=X+r*GZ ziKF$KLh-QZ8_5|1$VQ09&`gG#n|QAS+7k~~*gcu$-JqnvP47Iq4xAmH7^$3y?OCEh zGwWxKoI0A3hLevO#qYN|K<|f)rK@*5*jJjXK4D)CS6vlqx4n1j>{gu$-WdZQ?o$=y zU6a%O5nkJSs~kJS_4)Zt^_f|oY$4I7>h;Cu7tiBSJoe1Q=lWBv-)xC-x)WW+ zGDPvVV}*WEoO9SluiIa2u&LB(ZWi@mD;g#_2 zT!{eY_O>5R@qlv;W)sJwLqF8&2tf(^8ImHC?QaUJntU<--MHyQ%fIQmvh5pqw zC?LfzaF-3~GxKOsSs~{)zV#arE}I} zvS)mC$85z0)sNtUZnu&Y>P3F@GdlEkd`I{XN|e^XQsR7vI5BBful}T3S~F)0U@OqU z;wzzXKj3?eH;lt|5T_f{^(bVnLS1nBG0*>3ve_HH zlyU;1sXOI~{^Yt6Y2wJHt*`Hi-mvM`v*k$)$Y&1UEaUfUdX?UdVc~Mel_)=hUlk5; z+6CEa88yf~>ZNvltJkb$S24RL!XNFriFoonLXiK;G)46d^o8S0Wtv+~WlaC%+nbLq zi(C0x6mJ^6lb0x+Z`st9@Jw7l*5lz!ov%3lsJW{ClKtED^}+J&tfwN8)HTPUtGSRl4i7}n zG{ZFcl1CYmMJ>4=l@FEBPhO4}HO=h7MD~+f)?~zLxoO{+luOyXLSJ;imnQ^Fh=`smEbst zwWmY_)~);UbSZxC#m}C^7s9~ewgE|rdTYU?5LP2q=-)(bv8yAB2enM{t@AHUFnO7k zG7ktY-^{10nT`07LrAkJn|D`Na!u1{pNqO+g~l|4Qd+Imkk|waj~Cvd@MFPuQ$JOY z`x(IPb!DyRKPBzInE1Cd!IM*(*Jf~l{3OBte5l9h|n>yUmw5XA0lj?6yVey zu%JNnDVep<*k*c!oAg$*B+9d@YtS#qYD?w%dn>?%eBVxLZNdM;%|1ne$I9*m!8ib| z#M(4js;mC|tiFC*kt_QTCWHNk0i&MpMjO(um-W-KI)$rLq`@{N4uS5V67K%x9ij!8?_N?Gxu}{2**%&WM(o#+>{?kz?{V9gp(oOMfW7zN)SW%$%Y&TI{W^7_qkgpeyBmsq_H# zS`EQPGHlQ|wTU+t=uUB|pNkdbV!hrYrkQhuWx_Ji@<&0`av-cxV7CuCe7URL!uV+L zBUL|v{}_WtgJOos^jC0>+&Bk(GZVambWLlzI-70|vAyYmrkm;abzgd)vZDW( zev7t>JI~Pjvpz7$${;7IaxX*v?I0A ze^jRxe#Twz=78&~fu?$ynw?>q6$1A4l>YX}xW~kGE|;5s9pywk)wfi$iTafp!jC}7 zBFpiC+1-!9VC1K%SqWW_T2-l>qf996oTF!tNa6cU+pi?6>crtj`6)`X!{l0Vr;Z7p z^wp(tRAo1f+{i!$gheW_^vqwm${Fp^+{YqbyQh97(wK>wdwHxHc=UO?B$mzBHG?5w zIKb2AC>d5#w4V5NrQ=zp?&r*HjM>VGUZ&=SV{X|Fie<~Suyic?^}LQR zVd}4SWH1+B3&!)5swtMhY$u2-Bl!i}6;!`Nt&NX0m9?ePdQNk(Y)6>@JtRh1lLFbw|0;-p?JF>99#W`?u%f` zO2%vU;6)Uo2VLl}Ab%j=ArO=I@2=YxBtM@w@Tq3&eGjt7$iNRijK~{nZ6;b!6pQO@ z()6-Cguh|=Efx45hGQbEH78C?qAGfBM`7$7n23U*yHFogbSK(*RLxo2@Fa7l8dPmQ zDe=+wpV^}Vqn3cYuL^bc?bDZe^sborP>qRGZs4trWTx1I=af^|HKUx0tjo#5!y0JM z%uRVlZ$ilbmUWppU_xO`@Z&Q6KKbZ)vdV?bYx^Q`2|H+{%n&y{<_|es`lN664_Ysy z@lJUL1nQFaA9~)VGj(N2yxMto;$x*dl1CI`XMTs8=!ra=%N?k<-!kL6d~rZi=1X7Z zYU$_L(2)J+t^PP;Suy}tj@?O5Yd z`Q7Kw_3-v{rtQaFp+EKTUdh{FddBnl`%{tKAHcoUJeq%9P%05gcU}b-|ZHmeAZc%uN+|v!VCBr><+m^^}#|oR5^>O`|PeY{oLy5=%82%#`EKXE}!|tM_m(~ zzc|L31)JXYG|VQA5&)6Bnv<~}9Kc+-A;M7x;@UXCDRu>`_U#db*VlkDnpB<1gUtWE zqIfqNM<5$*?gZZkIvmVAa{MdVMT%;L8?_QYaBk42+op@pD@%Ce6nIAdYoIB*@a2bY~oU|F}lQaMcg0yv2GdM73NiZd;xI0GhP z#_{~kJi)-HeabmS%2PFU*%OZWtBbE2jaj{=P#u=l-m!|4f>_E$s4#QO6o&1)cg0a<>({wq~ z?jA5eu0=R4c^TnF!M9j-F@DVc!Nk-F7hYLrWqXD~#be3TMszPIR$U^{RJt}(GY55} zbqWSF{U-khO^H5zR_&nMIT4jr(weCV7bvbUohZ||p1`m5w>xZBs)*EjCFOmgbAY;+F%(;crkL~dlBaJ`@y~W!L ziH)m&I7aY`jq69~Af{Y0c9oD-2DNkHNJ#qAK0M)|5rZDSlwaVhBF1kuF@s_KraDxm@F?Y(5&nF(u2u2&YOhUlZ^sf zxP%;i>K!PuFmkalg3m1Uwsz`PZ!jo21A<;_^-R7<;Q%FWAC-$`qvs2jNFQiC@kxQh zD!-(_;AP9Hw)(NL@wk@W+p0z}n|x=ldk0s(A8|sOhPL>>e$mvW-VuzA>{&GU;uLzP&BVTnuE1L0hdJI&>GoWncB~rKxU|LPAVl$;I5P9erv;($ zxL4QPc3A&zD)t#zS~Nz8@wVO*5*Y0!fap3V;YrbQKBP&D&pY%@095zd70Xj$^th!|>zl z5Z4g9MS96#T}kUht@i3?#Hq%0GK|tEmmNv5S-RERhrYrY)D8ddl!ZGyGesvbUtq^{ zn}-5>2MO(Jv(&+f1Vp7(`z&$(yg5-j@CWHH|CIrc2lC-$nM z52zFkBGOigfwv%suA^9hIj7}}8-qs5u30n5orPcPYs9aL+9l0XCYA3AMb@cpkEbPP zT4BCd+$W1n@gs4uEgyb83p-YI<RTl=>h8O4?9Ay!+u6K{#ujkk9p z#6*@`qn5(=AbI1zFN>&t-VO5;2v`JpZ|o0gK88WuN%moDhMBd5STbb^2Nn8J7{dWa zbHC>p4-7fwT(f{a@Y2Z*=7_**b6~>3bR(>fj&FuSKl)q5KUzW$edfI7?!Cn9gTNUJ zj=;%)Rg=tg{+PYKcSPoOjg#;Uo_^MWg={hgvfM=aXhKSdrh+achEQC;iC7)SaqVm5CqI9uw{UQmmP zI^MZRXpXpJs2lw`xdN5qZ~`wmy*Be>d@fTTVW)%0z-vS0<<^&~|6wp~&QS(?z=xx$ z{SypvGqKg@XuuT3I{=fJhJ0iYb45F~}Mw>pub52IV9v7xjuEl4#yyl#w^rksnJ9Quy!(oaftEBGR**64YMw};kM%Dr?;`1 zeHVOtFNR-T1gL#!Wo2_qZ}ZH6N>;bApKMwKEI9DRe5}gbufN_6T6G@6?Q4*$hw52b z*^r!n3}rsKaGz%{jrq$=uY|dY?>pl%xG6WVOsllFacr(Y77>T*_&UpWpUPTf{2U_@F_VH0Y?h|-k<(c?RPr)nplF2 zhLmUJ;PkUXvWu>PsRIRrp`-4aJs~58|5kPAp(e9EIw*w0#|?0#ZmHF^9KzLFKps5c z$ZC8^%c|Isj5Rwcv9dgYpI+mfV}*EGzmo!S0hQO77-@X{7B1yt)(F}YE~otJ8GolN zNQjP_{*070ML1@HV`?^l)$U^TP>Pe=jPG}vF?+|=@0LCnttC>vl zfThQ8@K;tT+Bk=U&k>XZfT9(fozXLjDc-TeZ4q>A=IkG`%Ue|(t3&e*rp*+NCA4ZR z_?#sj*0xlhPH69_vrJKnb%|vQ{o2*lO$Ndc6}O$jltU0eXOoLhO|lm`eE+t!$z1Bd zuu1ogrtaUnKlniLfW2)nb(|T4j*=aO!qUa1$+|q|uxVT)@Z(lGahX8{aH1zdW-Wz&0R~6K>KNu+(Q%mGA#bw zJkD9O2D^mMp?~PP%`2Ry1*t`)bE$eDo8g}cVhyV|{v^mbS!zdkVOA^a0np%S)M%0E zDVQZ@8W>^fa|Cx9<0iwLKaXwdP8q%2xFb2>D68f}Bi{%MiQ2L}>aILm1G5gl|5Y{S zXoy&;Kj9{>G&!ofa|oe%;kZls^+H{Eq(HV<;GYGY{N&y7lNrL7lw?4ArA;-k=h=tn zs$>pY4a0XY6CU)PD-^vEujnUVUl^Q)xjgPkEH)w)avi|0qNuuiD{A#W=7_df@&{Y* z7&FD$T=%ZlF%S3@k9k||KT3B#olj$IKf8(=Fj&Y`RQ6zp7CdKG=Z`r5Hlp`~Vp-Fy z-(*0lcw+T%hOK9NKcjmLMl6}#5mO3i-|+81xA*xrZ#Y+IBIV+Dit0k$zO@fneD`aK z&{ncua$A{K`C8{%k9v|I3+L7NcDr7pLkqTusGWkE=9xsBW4(_P%jcq?(3QnCXiY2f#pzKFl4b`WLFWj_nh*;Hv+lo%f`4^o>M8AYSKkF8C&_oAn-(eK*gC_u~f+ne$~KLLSdbitp_uOfGs}P z!R!)bZ<3h&9)^nUJCat4070ltu zrG^oon`bZnYz^TJ<1>Ztkto^e>f2fC(>}cQS&@EW6l6z1g4(mUb5M9`jE!5_MCIk0 zV(@>-Z56@GuzJi13CpG4IarW_IGg;U4X=gyBnW@<`zPbI^O~2+YgWujN|X!T{)K_H zmZr`dK|N+W=A8+z4XatU&M_`E)gGdd|Bx4rXoY3&*^X65*L-hcxytTu^pKK-UisI$ zW4?58iivxO9hhNwJ&{tm%NXv(i%ys(hzU-7(tR=-f~phx&P|Eyj7^7RfkxWE7f0=u z_f*gxkb%=d-nscpke}#Hg|}&-Q{Clx8`@N6Qa?P~TPN0E7WTpl%q%4_=i;D+buZc} zCL0wgsc8WZT^1V?Ux}&@HVoFXoB=@B@)G%h+;42|cUT@$}RU4#5{jP@a9C$bE> z6%Rg*XZ`{LZ%;rf_2qr_2F`C$IvxJDdnsdPfp9v)_t#ea>Tr)N@J!8ABOuaTQ*Y@5 z=;QA~d86~H*BjZRZSn4=+0-A7-xhWpTxG2%lCoGwyuyM9*E~r-$x0WQm;w{0Cucxs zlamXf>!2&Mn2Dw$#-_8I!-Is=&56EUyY<~%XJJ~L*AF_MS*1kmS|$p#mV4K$D+(Q- z?Z0+Da`_X_*7NRQFE6U?Y4s%V6<(?jgHsnsop5eIF&3?`eF{P{zy&8fV3MC_n*kla zQl|<`qa(!6`(jK`+!1#%bN)cvDHD(M)~uU<5}#{gpVGahj(8!Ug4Vgzzkv2z@%lXI z3|q^OOOV+I+eki|*(g{dEGjodP;55@b|q*jzI|~Xf2*pYxX>CofXmG#uO+gV*5c#w zlE%)VOd;3KIZPo<3+whuCHMnzj^6E^FfDn*G8)BF!3WVu&f=k}$r002 z=e7Guio}BV9+eC6v`ZJ?4Dol6itW2%`eW61Gpiu*wLv$Oy7Wy01?JVf{k?=xZBPq! z&-Xn2!KlsP>~Dak%JxqX-IJ?CE0HQRGop#MIzlC~63IWlnk80Q2F%&sTe6}tvS*{3 zC;oCWAGdjD=;jj0WAlYs@yoFZ&;C1Ni(;fPatv)ko9Oe0Si&V*IATpFnYtjVG___4 zXP`C{mnx_yhul-RsEo;J_^Dzde+Iw zbi-A8`B9D76J5wp~!7&kE`tlRVphX~`Pia-h zsk=?h1iuSUt?3Tu^S?6YuhgX!Rk@Cxt)26&f1ApN-hs5_pt;G!?ov1Vpv1i#bA`ev zc3VSmfrmsm$VZ1hkzwb?gUQr#st7npBaR%K`T?vp>4`Qw6KQ25cBACC*QTc`kdh#M z6;dD{dptk#!e{0afVa2Ky-agUQC8pJRab+837Cx5deUnB81u*Zgql*S+?%x^#jQt^ z4Fn>>03DG!4dO2-tO?dIGI7oUA$2v;R4yOE=FZZs4I#0wUTN%OLzwY8l3V}@i{*=R z&eDE(Ikdmbh95IW<->&Rone@8{Y=GF-3YtCxYT#?A+Ni>0XzR$b4e!|=C2NF%2)A0 z5_cZeNKp$!VUi@jFJOQN8GNORnrqM0nD>*vSzmW8;*qb6!GdpLmogj`2D`$V5&qxG zfT=3kjO4IFyyf!AjzQdL^3szzwxti)n5)V6@rfHZO%oiPvI!wd;(^_g1r&eT;zb@2 zn%yzQ-Ax6mfmue{8A@5Dtkkq|_(ZR53I939uYY3lS^y?!x)HF1SG7TbLwW4ol0{C9WjtQ*<{^!SYy2b-JH@LixN<`Cs~eYpyu z_1H<)7Vj%Ff7j$!-h%#bUY7?qgjdbX%7FeF(mDn(|A(Ot^f8@h{P(Y+ z)>^!|dJE;G7iLz;ZZGB?dODAh;52>FDQ{vnW$)t=fa#U9A(z4Y$7$^|N&zf~;I%v< z&v6z^K?lWgvAGbPH0@57O)zy6#ZZ>rmfXx~ohK|@w|?*r>!f77?MT1qpZmkV&P4dP z>q>KVcS2PNy=F)E>t!1T)s4YMPgY2Kel!A+hSy9H%wLhuuNUGF#psL;nWOp(0T!MKvrQwZnI! zDo!NREgV+ux|jU)vMSmrdFK_TC~_j-AN&c621aR%ln-RMa*2~H-uzzqqwbzZM5EnB z%=m?5$_sk%oTVP~a85SsAeq5-3)I{=8CG?i8Isd)4`1GXDm)sm5AFg$`^>)$Kjvw( zK36*19+M4=5dfWQO*g4!_{NP##_;hy1W>u)%c2+NQ?ixxH(%fi+WYZW_ca^GD;74W zj3v}qW#8{kgxm%A(Qnwkfv-=llc-A8LX1k8iuZ&Cb>MO2k%X#6iaJ&zA=4z???*GM zcBJhqyO?F&7s(i2qwPJ8*qbJ@l!z*&Yl`=iNSc-V&i^n5hncW(2umG%9FGK#0-$Ku z5&AoQTMpmOD29dc=YLx%uV&Y0hM7A3vpKRF_#hMjqd}qxRzV^Pt@AfQy3-xnDeo3y z7j+b6$f9JkI{#AWieSD6rtEOr4s!y3Qk#}<(4YZ8w3jqc2(FWum|;EGjby7FS2YjdnZ=p`&UA^4HC%9BR!R5=qnqW+WJ@Wg}Rs8 z&1E1-I{HwIu(v7)Zyy<@8mcPxCCW7?6x2!Szs|1t_%mUB5Ve4uL6*XLL@Sqi@2i5W z-DBAWz6o4!!m`ruC(m@nK9+yj?r=gap1Hv+D%`cEk@FBO9C|1-tUg!vt;;V(|Ee-Cpd|zvU ze1|gK+WVuXp@lbE(wau1Yeb$1?154_b`x28Q!mZ>*8ebsS7k1&_BYAW$t(BTi^W)b z=5PJxZCd*cMRbz`+;P2(R{zX>=u>voj-fd6z38yaXl44~F^-r?Lq;G0JkX`tJUSb5KPRoV>fd(l2_gH`6xJ7w9Q!fBdVI@ z=1e>W7*kd;$)_g!D(NI0z*oF8#4$`UhWl~YGmPs%f%j#NHfjw*#EXuR0U~6k(4M3I zio*tRm%DMSHxlCk$8NtV7|qgyJXJJqM^SrTkY9*ED0yyMIG-kWSt;P-I#HdA{-sAC zKr-ppC|BUB@w);OhRQm~v&&4A@0y6>0RV^%UMt8WQ3Un*Y@~fzK^->yKox+VEW)gZ z4$sLo=Wde%d_!1TSn695_;#nb&C9j3ODRv(QY%RGR9%c1QZ&BCc_Z8&>N`VKQMP5` zJjZL8Ky0AqN$*3t`MUVICXrTGLDiB1k+j1$Y!N@0U=rfR7-n#~?Z40vE;vy z2vsq%(KC(X#|4Hd5l1lJRGk)LBLYzn71Uv2ONm;YnbpzL$F|5lu3Ks@;U($DQb)SH z*d7r=99x5wGCu55QVAX_ln3fnK(;dFU1(~{hcj9wY%=UVsK=s2{4pGMa%FC^f)Kl5OK=DM^SsEkq0fPYc z#$NE~58bQzo(1s$bU7wEiEOI}L>UY$gmbZ_sP@KldDKh(5)=mnl3Z{N|=-C}O76PMH}JJ<6uEo!o8Nb8$@^YPyoZ(58r z^aoYQ4qGlKt!E}@C0!madTc6BMCi*PZ3}I!j6!m>Ljz^r6h=O;qRUnqIMMDF)P5l9 z;4&5UAI70BG78qmZs~J!@vy(3+T<2*+mXD!%IWaK_WkfwVX=^_4nYf>dgV7eyI|j& z2WKsEhO1fRxb-xT;1QiOa4g6|$60qxfnXaHj3wvk$x_&?a=rMqFiqj3KWi5Qx;Gnw z2SOUqm`V0l0(v=kb_QhN8YkzRVPMJq%$A(bbYobsE}mS2Ja z_wpuv&VF}{9Fbxe(~Di_D?~AD1V}(tAa(hQ1n=_ z!_0eCuk}~<^1{y1Ll`jlt?v5qJuAdZ=T8>!bK7Z?gd>^NhtaQ|=I_403HV`g8pIuo zjE2exA6bD`+Q5>lmd8N$X^wG{>rx)As7e9-zQ!&Dc7b$38LjyG#51pOs`SC#;ijyf z#r(0oQsGTsCow`Q{kAqYuklNMXW&Ekj_X5v$tl2xQX4PPs54An5a&}3;m`|;v)-k^ zQkMs*Oe(E1sn%>`Z-KCVmk3rdHHlYA%>e!{QQveBmx_*d13E+dKz&q2l+jAakZ%nj zMRDF=T}po9*4`%Ai=6njij=^$q{iiI8^QAfSr?lujd9OsUF_jqS!!0&yJ$jG!XPs z>bJtZG2Zp_4LTtdq1`CwC->V+E2>lX1`9Y{7qsfURo~9er4$gZ`{^M&QM{GMy}}gl zn;=VWZ?xoR&x95Q{Cg6LipGBI<+G2NYOe~0z`=`$H&>YljFtiY#0<~o62m-qj&Tg< z{J8jM4m1$4KqgIN)xO5ZB`_+XgrMi!dW7;{dV~KkyxZr>Ey8+SeB=cZKHgolnWYeg zj2A70T6lbr{8Xs*vK_v~wstJ-`_R;;+<)3|-8Ytw0Xcd5 zdsKuPa%CwkUZ?9IunZo>DyNCFu_DHg1-oK6)6#%O{uQPt+sbHS>EXFAf(13qlRG@< z{9t(~t4iGz@hZ<{O+0&>^YAsrMo*x1qpU@wzWD2? zZzJY=f)<8QsadX{dcFd!-YUa*A>0xxR9tiQ)ZD*@GVzYZ$$kW~Vd_>><2ZfN*3I=Y z0KML=`;tCouNFx!!BM zybjB~DKA_wG~h2IPYPA)G&6SHr4BWt4t{iis4->@dwAq5i@kRqXSn*rzZtmy@h)IB zSoH8W%iPgJEX1*-27n1qKUFW>uv`fBszCw`TM`#~nhCDu0zFT!v6JGl{03_W_$GbM zPKil={Q`4ilBI7mGe4+m88H&uX?{?XlauKev$co9qMKUzmc;=;3p}Tr0P7!@zxleefRx` z;_9KCUl3TZ@y*Le?X*gG=3Q_dPr7&aVw+PglcgLYPFcZ8NXp}DK>-B$e800Q(pIV&yvcgeX z5l){wz~4Iy0w|1kYjpQ_R7){N3#L_JIdx z*4F+$CmfmE!BEYm^R-?>ZiHOFXdgS;SW2br+!t2L5)x*gR*#ekb z`gQFbg&$*PgT}<}>s4RqsUy}S@hTQ@`sq_s&q4_*8CAQ;G>2+{j1Z%vJ{AH!g)mnUljU;z@R)q!JxE{inXATr0c|bd;HnZv57L+tm&FMN-hkH>1Cv;wHEi9rZiEPbD*Wvyb~bOj`Rj3XZylI~^Kl zRw8(Q)a#ie7gM;A{uDv?3jxpEnqPUYU08oW+G)XK(#U|eq!X8c0kT9K`k%F9C#Ci7 zGS>0?+G@mLjYkrNK*DDUg7mZ2(El)?v$+G}A?MYAjp;y^3op8CaUTf^53ZFn1(L$A zfglUq?{}nUyJ{19Kz+Wi{Bhh3yQ$81*!!ih(ckN8&RA+H1^Evfr4laIztV=@mhYi zMK+MMc(Bi0ZQ*uO%w0$n>*{0cCZYPS!7U}QY#BOtNXa`kqA*?a<##l{_6I=E)V9J( zUC1niz$%p5eBqG9+)8%X)nGaKSsCVKp)vvn8394M96BS}I_L4ipyw~-jZ6DO$-R6QR58~gYoNAzP)R^<4Igf`02_DuHqb9U8}a zY99W-b|r@v7E(RC(p8U6XJ)7VnfQBWR&9u03;@YX z2-`W##~0i&eKuwlJ&gYz9a#%DcgYRQc;LPp)HMINXiu--m4oxXZ!-pqm-zy8v=gFl z)DK6khxN8^TanMXE~ovPE|;z^3W-fCh}K@O{Oyq&>W(;Wh}wwUpI&f}hxD%Aj^Vt6q|q{q9%d>5Y4H&)2_y)WS@ovOSQFL_@C>>u4NWQ#}< zRgXSnoDifpEA+rHeZ=M81`YV!_r^KT2IgBP-c-Qb+H59iv{7${8X0*oWsOJ)Gg;W0 zutpl~AE@*Z{_GCoH+0)H5MG1y4OF~daU8{c!1~)c(C{ZX@o0TKL)0;+Ulg;00|e%Atn-c*Y3y7 zvqF0|3!=_%kSr0e8ie$_+kgMHRZo%J=igc_IzmPo&wF$DG1+w3rD4V^+l1T&kWYrX zL5`K4YSBBU-N9nFNmJwW7?SMD8e_6a$UlGmJ+ft{WJmZ|Ek6)@dHDJ=B&@&WX7OsF zakeNbe(nn?f^Cha*M|%Ct^tabJYXJ-=ipoQyh&rag7SR%v2Q7D`u%I@h?dGaF=bgT zX@U2I#*eX11$Vi!b|dy*e4Z&2YsGk9{PRtAMPZwX@>e$5P37hr78_>d zfY#%A-Otyr?E>Qy>aPD$eM)|xyL&o4e~?)=pgRtIQbLWaFfK?AfyvN;xT8QGa4~#x zn}hSz$tO~+^>}2-k5fKB#eB^3#iExx&%35&O;^%le#H)S3|z-I2&`vJ z%7tryit%ElVyj~-Ti`_ZKw<0YB-+`|u~Ve$lwJv7jR-FkzoBh%$yGN8ws$MGJ~Y)4 zPnB#W(oPt>4s8+@C^WW$F*xic{oVA5&^`rg+1wcrXl(iJ)Z4Qy zfunPAiCr1?!b)q}oA$u><@1MtI1Cl`;t&JcMq2u3`}KBx5i1d|dQ@*-a;aqB^1N5P zBe6OWu|)f+MGbpj-0 zt%iUi704(J_(+ExU6HqacXl=8A0=Zt^ussTnY7ob0z7u}*Nd|$Tqs^)(F4+A%Tr;^ekemmdv6ckWf7UnQ1wFO?Twy8?t z1%zGdCaU&y)a{frK2Le`ti>M_Tgk4*WhF4%7#QdGH;Zl25z_jHi<0Rf2s85`0;b8E z-)t;|hZf!eJTtju@%6~?$v`v>7d~Bqv{oR#N*>Zli=1We|H(^FjDrJ6wjp@sq? zDAl*##^tXcuje-+QiI~YRAm}PjXqOc&OWcPbR*l*MKgzVj{j8i^&~u>A=2!ItlnZK zrZBt1nQj*R;vVcKH^24HU$mX_Z~%DVlT#TxNUeGJsaXrcf0Cg;I*R-uUoX`J%n@XZ!i^{O!?iUx1gxo2)hoo6`=kuWRPJOBi)f0tu*^|J-6=r-4@|ducRUx+nB7ixak3rhI`p-GdE{gIWCBRE?6TvUX#s~Ca^wE{ zZ1OXoXpR|9R3;q6!7J>UJiKxAb&uJfXGR-2Wj@V?ezcgH=jvpXO!8cWSQo;mdKNAKRo9}!qC$X7}o_)1|o4**m$`yF>qp1dmjyk(hJEha)%g-;ATstk&H@-CX7 zM>JiN#JCqy=70PY9XklqKy51z|p#yDBs>XPqUIGSG* zRV{K^N$5+B+Elu98+Na|1ckQexfa>3FTai9gDbugki?+5el3PGDH6D{{%vIc3GQ}0 zR;KOE^zlE8D-E?F43)4>(|1G`NNRNL(*l+7;tg}}$l$go(=2sq=X1%;3lAiis=C*U zm4TGcrIZOhGE+&cqbL;{Z(si>9(c{bC8$x2 zjG{c6qbupa*DP>0JRD6rbhLi|r1WIrd{0AlcpUSzcW^XarOpCz+j03i)yr7SwYK|o zCasNnL^u=`pzAQnTd1b+b}$Ft>%QWsRWJbD}-_?qE5q{ z7v9Ya<>XXHLMJ}h-^|)FlQaBDS(_~iFpDV(B+Vq=W|=AHlzQz+{XOj4r|a*=-3#tN zv&&YDuxiu%*#K6T4ZV|)X~t3G79Xk5(*1W9Y7US#J_QGZ6kbT#Po6wRgvv4fI}>COM`9lO5)GtElsnz1 zN-J-7l`!A@&_GtQLs+l*tyb_pRjN$Qz5V{~Oq;bk(Mvabpd;G>F10{WER$z*kfWP+vEyzN zYBLTKi;ugbrv!(XjW}21=adoe23B*FFMz8`b>on{AEis2{+a@Ei(CG|N-2-5)M^nX z<*tixv+r6T8qi3-Bw@z(+;KOy7|0N&cuL})R4<|FPY1{Li^Jsik19dt;oM18E@`Y? zb=<`v70*vr#AEWjo-%U*49ZnM4fu0?D&GcOj)>~P=F}LRVab-G461)W%ons!%n+w; zM1P66#n$rc(RZqKOE)9p-8_28D!2fKgLpunZL<2PiDkyouPSUb-*NTd#k(=c}#tZEy*5o9`Vi(QJ?toP`pQo6aqMiytyR zDc#eWrrfM2ReLUH$G_Q{9hkmsP8q=MP2*(G;^;=pC;dE1A-xFenGUWSdFS5bx;~aUt2+ns#?+RrSb8wwR!A9qpQwRE;>v zGO769sdW3L{|BTtk2>!bKATY|^sn#D)XI8HO{6YGJois}v2}Z&ZN;j-Y6hKD?u#26FiD`|uN!EY{Au5UAXn>I5XuV{gG3oGcre7bPCITA z8uO}Cu-6T_f^o$%KIDx2Y&^l(OT)3f{tshp+E}4;uI-E9v}ZUsAkiY%^tRyDZQjWp z`IY+QQoPm?Grq|6SaM3;mh(;pcu%#mX=#_&(tL`&*x0u1u_V{!5L+eIjS!(FM@&MU z+yIh1KlG59>2^xHRX@#Jm4qEm4(DmFa4rfa&-9eX6m4}R2lqUEE}9~8sRs0ntu#~Y zE}ri%`Q@yhU!e#_cPhQ<{@7&tD7pD-K z-!X|>d|xQrRKyF>9di*r-6y?)y~6V^sx0b0I%<&3l#o9-E|k~ODxxGxubL&D72dtw zsi$K-n*2;;)LiCbrjx(^F`?_~ZWt%_+f4wMI40HS# zWCBr>Sl3-R?{Iw_>$eC(!frb5bZ`1Wk4ySg@%Az=Xx0+@Q+$=g%;x{M9d`ssD8T5VNgf(+P*k0p16&++9y^V8A?B0DA)b^vb1 z-GBT&v`_jia@Q^82gPUHJ-Me`pAtsml z216YGTbjGJ)ei(TM^2CP! zVSL$VPbSnP1l%xl_w!rH5a{9^M@mPBf>$diQtWP z%aXsFo7*Vtc7!)wn}qq(7y2w;0c_m>K#$C{>QD^ZCZ!Y9`bWsx;pODHvNosbba@j0 z`iHvt*Y?qMdqSN?64#+8gkJpS8&M9GLs-K1RPPIEl_LHoaz<;0xQaWXcS62OGP!Nk z964}voki+hjumK|GRa>FMFMEMXbPtk!al|@j|>}E@sN84QGO$5e5IQ|2AHAs{k3SgoG zz?C4=fKY4md2qPBf8G8V0PrGZyT0O0dLbI+#YIS`URP^1J(i zbtZ$m8qMZgGyBmAsdFor9*Cpu0BsB8tT6l8YHf>c{d7Xl|Miiv-ye}3aY)2@((jJo zI$3iu)8OJPPn$6Y{lfpK3So}jGo;me&l+7xW%UD4XT9OF%tu-8na_wpKn4o1eO4OL zB^48*f;va-EdPfgBvgR_7QS9{x#JhKQbqOInn^fM>ZmhpWTte8RG62}$v!_)eAU!- zc-m~At>09Y>~LQMk;(9P_PjtvBh|yM-nA1UE0BHe!*&VJdkdGh{^_{CrT6XkNs?aQ zpLmp96Xr1b!%7%D$i=7|x_20d}8u~OAvH_iDGJ+qH5xU^RqzPDW8MR?yj?a*9Hm^+ zFjM?S9Yr8SY^QXN%jF23oIdp}tE&tb*Eats;2DF2N4|>Dve|BPJQ3BR{`*-*ry=5& zqC_G>$U_&B07*`m0Wx)4e{6g>c%LqzCqa9UWv`asB-!1xS_tA9O^$Le*JfM2h#(gI zN-Arup@Sig@gd!s1E8;qP_7^>0&TRYLR+Tf@TmL_M=O1w=7P1Onr>j6hdjj_fjlau z*>+ADqi8e>y0k>)A>SRIHV7iy&&?c-EUD#`pYPwfhP+QSi*7Kg46dE9(wj#Wlnqy| zvd3Zwoo{bKGy1g6oW=_mf>nw-g!HB}bI~$t5jxL-TBcxjhJN}|=*b^2|8M%qx!Vbl zKU(f$6CZVGsN$xK?C0i2qp|zmUHuCE$PvyUqt7+HnL>j3CN|v$^ zxtjxyg`uHW^&m4lw}kG3=23-2vLjdF;}wpp%J&v-R%MUg_2O`sX0evUc5_ z2V2r6c)ihJ)b$|v)n)ryFp2PSgk{oYwDFt0l}g*djf+9jl7+B7>F@QUq?T4&k^*$A zwGmP>G)tS9H~5C#9_^!jKEFU$Kf$ypsq4X{v#mxSLw?bMB)Oj*cLC^9Wu)j!#QBBs zw;H9evjNS*FZ}p9)2cphnOMeU(g);nU%E8NR}G7MijI=0FtT!I}R& zD{EX>`YZmL^X4V9HhfS}a&e@@AxIv9zwU-x?ilRIz@K3j(#xyzftpT}@^k!!Sid6r zii$wL?B>y|s@;q!E3*VCiRtXPkMhNw#)4Jms*rDL)`!FOXvFNxL?=ec&TPh+1kV&LJ%ULG9vY3h z+R(H^C!RvX`JPLI>eN8%{6n`Jp({(Th~6KoFxIZb-JuODyE9$f5ip`Do=E~DoR)#E zNLnjVT4dyY!YUE@=ZR??Le*_I80#MG2c zWJw^~TLgx1>H$eD@t+E)>;ZqW;n`80G zZJ^WxbR@o9H%XUQzO^I4^X^FgvLi{hLLeGY^yG6250)c(cyEm?l-KZ9cOYeS)Lg}p z;anYRZu5=f8*RE=W5XQ@4^HR%XVnC0K#tB%6A4&ty8Llg(CleVrmX+8Xis+0r1eX8 zu>Ft}*{7n|kn z3p$GO$v6B$T7H*#XBn#l&K`PxWF{dqT-fr^A&q|R zsOctn)>AB~KN0P4Iq4?P@xqh@suSS1*LF~pzpcRjXCss~y)=ACyrV|5?2x^EOutWK zaM_{bBU25JOB|?XRH5@h3Z}uhXFZAe% zXE852ewn7oNpcfd<; zT=ExzP`R3s!@zoTj$4&t->bXO6+Jy|E~JFU3fe7_SI5~#FR+bwoM0mUjn|yt+imjm zj;FwwSK_hp2ZHH}b7&S>Eq0HKRQixa8YO!XUiEr3?&<;GJJCYwfjWw@CYn|X8LRjliuj!Zit}B8Ewy&q~&%0BKw@j(mYhm3Us4Lx^rjZR_6A0~$ z;P{z*Q@>`E$LUkhoeN@%6g}vqy);IR!kbOPEZhRJ>5bq@8*&dp8zzxF(e>Lb;byEA zx|LwuYq5sbn}LC@Y~e>D+{MHA3wGB`nsomD=b829K-|%>3&OK&^{=^PxF@xTGJ@OA z4}?EJCjr_0_OZrr$-rFYSO7`)$k~@oOP^1!hgA95CuX@;1XgaE{Myy4YqINE!@pqc zs^2(7FNbRv8h^tIWtA*LR!6_B0M_=`*&yZXq$`BZjy z7A=%6ZCw4b7XYkqxnHk!F)Q}~ZCRNLwgWK`dNfAD+V~&?RpRZ2Gxu*(F9>B@CKJ&v zgQI=}O)tg8nT|4-?jduxT#NYQnfupEtdS>QpI64jZoIO#Oy)>p-G?$gD9AnEUWaad zd6`8OZLiyg&RMWM#9)pD@W$=2b~jJ*ypygj0Spc)78p-H`5G?z&vKo-ppy{$xa7%@ z7R$)7-eWUwzKR4*-L-pF)yH~4aliXmZF7;_q^gyn=By^lM+`W@;q~dAmoSYuK z(8Qdeoga06RYIm{@^0@q!6p?~X;T&hK8e~h>(Lhj2OLOnt$l?OLU+_rT9r1@akdz4d1t-dl7e zx6pSP#sP7E>Le8e&-C-X`~q>mh0(*Nx_1->C$9>vZhu-AStFAB%}^K3ktgQu zeKVRTE!(Vc_@2zy0nIB$qO}Re}+kJ;#6XYhQFCAjQUJo240JZGDo#^ zCu7C8X>+TGlHNj7PJ%R8lfO=SaZxX%7Vm4~+Q=#o7I8_=AuW*|$PZv-;AEk5HgrJ= zsFNPfgG^B;5=!5G`W5;4by*|nt4(WEu2;_M1#QBgXD0$Ka691Jn4#L6XCWI%1?2UU z6l!!{@Yvn|kx8o~%Dkzo%cP!1aR04@rf2gkxp`H8`i@|*{f+?{zA>8sq|v5h79!)P0@4HRY{IAvIVvE3l(P_XGdRHAuVSRFN4zjbh8!+W$79 zdW93>5MzODs>#cLAhoQ$C~2IES@%VQ3Q4AbxBcg+(v=Ism!NK?bR%N6V@4ZIZY z3$We0CaSG%*=~4vj@NleQH|NQOQCZ|3;Dgcc{S$Jck-9iV3FeMp%$_X$VTGJv_dzi zwTi{U;r`Xqu&uq#Kem2FExxMX?FQu{hr_I0h|7Z3e_IkJ^XYgVVi!UUY^POHl$sSi z#8P#ewc|(9^xn}iP|@EHM%A_sjY*Fl;?6I*o`pr2+)+$2e><^r?82}+7Bm$U_oIr< zzPS`e&%9!!1g1JBkC2I)OQ**>%t8!m6rkTOO;Xp{3w_a9n=YWoFjE#asuQp8b<_sR zM9TLRSj~3i&qiL}cg|(y?iXhOqC+~+P8xn^a3Bl|)tey2?IEoxzAb>IUEO|q+m&%% z#`_QJ<|p3}77*Km|7E>o2kDfLYO~H3#?XO1(m|Bdo;fi>0x72ORp-ZT=y!zWG8Y5< zygv`d!?z9yM2w0Np&*BG(T?lYJQ~|6Qgxh#%9LFG&8XWOo|}yHF*6 z?@l}+Yg*o)S22t8#EFv%m;&pNF!CLb*V6DSGe?T`cEIUQ5ehn}8U$H2q_cP-WGZ9{ zJGEbLAV&_geIcc9-|)};0(%sfp>5IcpXR%Ud5#StezQsG6sFW&1{Twok1_Q(Q{JFd zNrp%3vI_^vZ+XD-WLODcz!bi8G0@=FXgUcQ5O^{~lj)5MZhA;Ow&7~B#M?m}O4&mH zgenMljiS6OEL^EPfiSgthBIEJ zY>j)hmFLcvgh?`p`qNF=M^veH_0c}wfF8O2htXcr}k{}bbAcj3)qNppvD z{n_@1de6gv-ubzYanWwSzeMuOWWScwr7m=@T6qcCE&`}e^*bRPGtjPj;aTCL5@%s` zBB120sHtO5P7KXjrh&MJ?hdQ5Nc)^iz#RuZ(2TAe>(1$M!^vBV^Xui+3gzCY!qceg2B}W7FmSQK!nlomwMl|PbQA(VvL_^ zc3)Dg_^#>;wG0med;@~;LClgn9?0Nn@^xrZ#rFEipGP0{57J!~X3E8JOp-=MRjU{R z;3r+=-~k#m8>WtUSFqpFK48iHNHd?hHRr1Gm6>KPU^{bGlL3%4wEj;h8`s(=if}az0ZZTuAOG8_}YDGel{;+4kv|~-j(hPh?IG|8>TV@cuv)^ z6CLEUtabz@%agH8BZD=M_r7}AIOVzp>X`!bwfYG7iJQ%R?4QSR**32w`thp?8buGA zOzp{Hc7b`vBDy$eD$SqyZ>}2IVqj(b!H4DELpvbGnf3)Cqp&`Hj=0p0CEHBZMY?Ak z{k+nwb6Ec({%vT{z?0(sT*_2uIftntVsj?yqal4N`iH+rOClz+rEnNA>eq&Pr_m}; z9@4rZ=rb})Q@`~0VN`FV8!f6~u?3_M(j1Z32cuiY#<3COG+J^(yxP1F-L)fVHQZ94t9AZ!wv zGtO~P^pjwdrmwbaxHBTNcVd&_d<6?TxTCVJglrF!!sG|1OO8PKKEFxX=T! z0wXGt{10PdcIwHtNUtS3MpH6Hiy}X8Us3?D_Lvx@#>c>|kd{%ke7A}CImkyGe?+ep zW*I&s4saVM9)|X)8zt(`+rK$_NKo~pd)SIyH#;kjYWIEqThM5s3}qodu>LN@0D3ya zH?Anz-z;x3juY6mDW992Rs{elErOX96HG4Z(y|#BUWW&ME{!Vc8n;{;Mwq*-c%f54 z{G7SGN_2WV&j8QPS9ln%(s9_bs}e6mO3GY<@XZ>2_?d)^zHM@a%T=9joAqZ7lw0pV z$M&ewjv)vCGM6xcwM1@ij5DF#$!&aL5pn1J`YE<=xZNjp7hWv)HCQ;C-IdjBSg&n_ zI{w1>1yXQt4OgVka^>x7pqhcLbT*US8!adak~9n!gFdDme6!DF=`{Hm$GJQ^Nf!2L z&K>PZ-~udrs4Fks{5wVGBpt=W!cEAy-~MT!%PH)s3d>n;5UMcYy7Z#z2sjydwrcqG z5s;N<62K=I@Z!i1=T`(jc2`QU7^)Fo_oRtxZh_P1gWC$MC&WWkbl^{YG^K26@nK}& zl~2l-bDY2?uDO~wZ+6!3c@wZ`RiHFt z?r;ZqUIK`k5D_P>IG?GsS-Ct|xh+sy=h$LBcI5GLT`I5 zyaYP3(Ml#N4=h-@qP@tIr#8?G`~6~37rc_Cip5!%a^u+0EVmGl>8LfoiV7f{Y-+G(a%W85UzvLS)yV&Qtu-Q;_e`>^Fh`S0G1g z0crq%LX>VS*rRwnvvJP-j%);kIL1l-%u)r2rSYEW3@fq!?>Z zjnqXCx0-{Xa2)g>5DtQu>2){#hd~GkGHKmVpY--dW+CI*tJU3f)ZEMiJ~_)?N!*GJ zgIiDAGXX`@0^k|2U~8g!o|Ed4Xb0WbXA4}ZCD4P(_mf9)#j_!EumV!|6bR8_x_0T4 zm8qHd7P4?6tG`=9l_fpP(evMKZ7|0r|JGQOK<_IQq$d-_2m1Ks6=4)NDedYTbDW|R zs`fmjKgc|&aiij@-GuX|$K>xgXYA*5&6D7K@#VHW5Akuo0-um0Jrgj0+SKm z%uaXQt8h_Ojhxxi{zc^2<;WWfs382+ZW^gu669mb{3Kk}d(A|s+df0I z#+Vl=GIZZI!Ek0o+})i{iED48^DAOCQiKvFGsQE(cwOER5DZ=X8Pnaw&3#qdd->6x0=VfSl8$% zRbZrHqO%Gy);%J|&g02qXeQG@K~WkN5p+4> zWNsMkxLB2NS!af9!q)k%@9>)GWcqJA<{8-8!+n|MfuJimaG@7eKg!2oB-U-8|I_6qm zi#po}=_ZL@^4DA*%(kw~w4<{_m4+D4@>6?K-;= z*kf?_{B^;7s<4ij88)~=qRT9bXv3*q5z=HOyjP}8^jE4&A z-~X`kezTR@?Eg@of>sJvkj978VgIzHjT6oBURjuJS-+9FC|@(dkgYxup79U#COuz# zv;ET{-Bu=4FiC)nzT-M0?~zXQw}B0D=u8Wb+li0jwY`whtX~l$PqrXe01=OClWM>!MMIjH4X>1JsHzc#O^kZ5VOFUlh$2^E2Nba*P*IUej_?N=j`qf} z_WThiNCwtaf~#Gr+WK1>)GC##O-+7XZ>u<9`rc?AX5zmf#5H#dj$X9sTl`@*vZj?e zOmu0fDoNDFODpyK<-I6nuq+10{_l;<45&*s1y-zGYa>>;(BC7Gs$a;Y0hZ~nxm-}9rkABjn z&DYf@n^S2o6nMd3hN-`d6;!#U!I)?ehHKxvV=|<$;=Kmu}B>s7Z>d;o zhF(p5_u0+&T!-7eIVn7SFx)9PlPrSHG9j0te*o&rmcr`6tha}qKVI00X#c6Y@V2D- z4?}LAwX^W)ZKt`!(V;n|l9Aho7cBIr?>8NCI{Aj;65=F!tftTYLSX(ooB9OS6ILOp zv0ixU0?D0=Kl+)sFxhr9Vlf2!pE}+$q!N}e|6{|^>JCVO5=a>OiI1lG8)r`{E!LOS zsNhEykz&*;Sr4%liA20hO^ja!n72{Ma^fz=z@}1Gt05lr=7xdm1$67F9p0+<5q2;@=h+$qcwxFoCNUryms>D6be> zZP<$(-3A0@Hu3j#y{7829H+m*v|_5UXr%m?5Y4-@I~ckm?C`!M_l8JJiLD1t4u(@D z^Xw&u_c&WTKvnd~hu1|hJQ2S#&76|5uFv6v?E^iT1vwz>u`?5!#X?x$d)qy7PUVyt zn^q~6gN$RzdANN$a=eJXc{i^lr!~FI_1?b$U&#|;{%v8-cRE-lW{x9Td^04-WH{%> zv9-S+#LH{v$3>8l5UfY`1|Sxd7y55x>LZdcJugYgeLgs~&KeYe_@^|CIPBLc>J;KX zz6YjpuvfX-i*a%4%pk2W8AdnyRtyIw@I!%S8K0jSTgM8st+E&OvSEOM=5&!m`0uG? zq!e}U7klrM-jDn)$n_rPU#*pL0dwY<*Hcr#)#q;}Z_<-w#+RTH4f;IA{Q#^snEEFC@rl+HPyUh*J~ zDmi?!pelv&^{WR;ww_$cp0{a|uqu?v{ANlO{DI82dvKW-Q_{uXG*8tR+n0B-{V3W- zL*GX?kg1aJv3){vS)i(%R9?4$g+wB$Bu-E@(12F>9YfH9Bp6mAty8lFMcL{v2@Ods zFEyjTgWj85*Z7$f;K)l0rI9LRJO~6;97>5;EjFIJ`!VoYO;w+5`Y2n$O?e+F?aG>z zA3C^3uD67*++r9Vzx$33u9brv4bbpaFdrb~lO>lL(zxhV)u9K!*)$LLCvf}2^@316 z#Xc+9KBhL02cvt%#|<)oNPmclWZ*k74z&B|d*J$1p5vO`&35YeTba%TpWqoGoIwB; zYxQaDW>)+1Au*(WYi6-wH!5F@d4?9_(!hgsZM=F2$JL zR~1$RHb?`j%cZfhJ`u4c(uAOmbj#=lv`)N_N9Bfp(}BdDHa`!`5fp)~%yySGZ=NiI zTt6(aI_Ya1Q>p<866`qfQj156>Pj$KhxeFKw0Ibw@2vFW65@33Kdf2vy_AB`Ixm;o z0&hV+sFzHQ=N6$fgO=Q*2W|Y>r|01z*XKz8BxX!1=g(C(W{iP85iWDs`8>EZ2)4^C zw?5&wobU<_a~da*+|!?awXdL_+#i8dKQmmFT&Z&rDR%6p&Z&bdXFY!9`4eJOxXOK0 zrKN5210<*svMq#AEasUC38;l)V*7}3h$(_0kCz0hlEZ<)iip~A;7Na}PqdN?=Gsel z^0SEd^;>kW;#aCxlPs`HRADgFQ-)cEM`$KhWnldw%%8*-N5z(((d#cZ1#jatRk{kC z3GaNe^{9pQY9XB7YUOM;dx}!9cj`i;1v_pcl4T2wmEBMVb;o=7}_~*febgSZP~X-WUjjn;@ono z2OW`Wu5t(A#woFmoF~`+7!sU)R6xWu9O=wpke8^y%}vu^NaYUT^Sv$ujUclcJzw>N z*UU+6D1x!y?SHdxu&uF{!sS2kOI=l84kA$&HKE$52*AJq-{PafV)KxcprP)fOV8@+ z+$xEJ2h#gP*ZH`GF;jB7O9{GFd|-k8}WhU(qYv_q@5)G(#_s z%zE=X{}J(9S}JyvDu4Z=r+TRR4(srVOh<|I{#s0Gjf*&Yt|Q$}a_yE}y|al4$Mk11 z*=Nc@ICQcz+}I-#Sg*Ao(D&ly1l_sPEfpS}`13Ma)u5=k`>yVyBiDD$!G%Z4OFJdz z1M!eC?(fRitR4|JJo-DAlsr{RdO%P5H9hR4aA6q6A(0Vi4-)+>3+L(Q&s7Y_4z7a- zaY43qw3b7AKwjk^lv+TZ4EnpvF%5Jx?{rMw!1S`~Y9nn}O{}W68s>od22<|X3ANTw zF<~*%r{uPrnhy3ez{3m>`!y(6O_;hThx$scEB#{^A||hV^-8Unol9{3TV0Nr#lcCJ z7lQQuNi!dJ@77LF1>r739J4!>#W2b(DWx#(92B}d`h+LV+%LOPrua9=W7^8W;)?s2 zxJds$EXDLFi}-4N_8wm;D*0ssz|Yx{V-sDKKUN#sEo@1Jo$0Ea>ZH3IBOG(g0&qGV z7g;Z_){?maYaVE*Bc^_H<|UGi-l&1#6t$cjM4Ihx@*5}Y;fxwad|5L_>V>65i* zE^|I4+%yHIYo@rVh*Y{MUx;&8yor$VcPLgwDkmTMwt5JgYc&#yZFJ`?nq|;7#@^YO zQge2B@~!Udzjb~PUgNy45i;T~$7@7!)fWaaz*zhY#nW!hy)<1$7nHcB88w&kKWP7|?q?a6;Gv66zwZ zf9xzngTMS$^NNNcD$BJ$O?*v^0kfe#;scA^nC=|O-N)t%efzFpK5?c&-J=U@&?$EF z3KB`BIuOhXKhoy@=cAMKdx9==RYwkuLC=3RL;!9Fh_VOQ;P?yhzK^}1g>nvn&qow1 zTgo`+SXWS= z7dYj5#J!_d%k(RikE)^O&g7xGh?#!+LfdASz^`?-NAIonNKRj7cjepFXUOg{89>b{ z$@{bPsPb2$r~Ki|?vYIfdim>}t-l14Wbbf|>MpqZK7T=k##Vy@?+g>IkQA^Xh{bXG z$&&It>w-lbxmuH9#{gNC(Leh!-`uit{^_48#3}gSM9gp=aP{(geKWG$F;;TD%=cr; ziq^6L;-?_eHK!n>Eok&tR>a z@aZl!a|1XoDv9SN6~~p_)sLY!cg?ivl(55nNT+DTiMq5Q^0oxt!hBMYF%?$P>A!eF z=qQJ;BKoNlZ@rA>(|yshNe}Ud&2lK)pfkft_)h7|R%sMLe={S_DxELV%kR^pBBE&` zr*lX_Z7u0Od3?YRuobwF6-Z!KpKwZuZvbqC%4Qhd?}s?vWf%dYdcNT&2v2ZCFyDDq zdTf2en8!XYIsS)*zok^#_}-$Xp%Kuj^fsMmvwr%(`^iPFi`x-DD$JsrypA%xZ24nj zhETSo>qU&1y8;zWvAU{cUj-n@(owUg7kz~8LE@h(DK!S><^ZsAek-^e;$<7&ybbyN zEc9cEYR`%rFAvX+22kr6Nnz*VZ*gkYxFFIL+Ds}@ui9| zv$%?z1|55JI{%#j;n(JvsF}e6h4eSX@@p^}exg-#`Onm973wYNX!J1K#A^+KE{i<- zx=*xjFT|RQnUa3bH^eDJJ$9PP&h9G<+#}#boX#yrJQRkJNAgJ6k}f8S>EhCO92hyI zEh%B9Tt}nk(X^?W`y_4YoS0cWeMk;l$Q(V0YjaA2E{IhdMacNj_I2f23%H#A)Hnp{ zQ#GD%-NfuYNj|VYQCO2kKU$%x8N^Wx)5WflieAkpId=x00DM74(zpNcusJY^K__I= zUz;>PEOg*QOQUlK!FmP%@>9&k;rc`<#M)pH_6!g`lXlg{WEw4_y31~swUhn-IoMx9 zZISeeFgj9QjI62aMduKMM%*k2#9v;Y5+1-k@e$|noL`O+|6QSmM&elnO@_9 z{E$=J)iDbpshEH`Pa`VVWMI*4#rOL&xxu9)jx5T?QW^K1r#hr8gdI^%I~F;cqJw|n z8ga>6Rh0|Z0b3Ye#PT^sSKwi9k_%vVqF7Ew(VxfwJ&j&m;%j0bVD3YrGtk5-g-qKY&=-XN&=+e?A1jwj38^m?4-+}I_%nLJjiYfoZD<>$r z7SbZX*#I4Z?V>QN?x1a#eIuo)ix&#i(RvqKN6c%0j|i_Ac}$i8Ty2xII7NyH$VX{o z3Ggj@Oj=LIHD=7uSbb_sc2L5Zd)m2KG_C+kk3XEff*enMOvNkR8b#|8=CX;N9?s<6vM8Sw)Ci8?e6}i&$g8oA~`nG_p{r@fliY^ z%xJ*fMy(9YqvZXfi5E~23i{l z>LpmTNkleSht{a$;?CY3hnt2jG_^<|nUmjc&;0Y({_C;C?y8`#Q2*UGG2j0{xth5a zhIcl=shYay^-F|YmVx#mEiSfGCfGe^RQ2MIqR!@MJkc%AjWY~y2WoOWyQfn_=5e%( z*(Q9`AEv68^fKy{rn2NpXrYs~^y<3UTO+g7>JNZGZ9f>5K|EFF-#jDzgMpDK)ur$C zO}s2K4{N)!`j;fRppdbqyPw2mnToodV?vdoobMe38=d?=?lNZvJPYfw+EWfpMH7Ye zKdR1np0WmW03WPHEE^W{6BDm7DPhQ?_YIh{MI|ka-%srb!CuB(oeSdNyO-8?3Sce9 z9g!^lt>r3|)4`OYn%B_q@;yr%)iv6W@`myt2RBaj>5J17Rstftb+E5c;TfTYR_F3{ z!{k*bWIe-`>)5=G+nux0uT~UTwml21g}#WlWvL$w`Wfk*UcvOodB)8fgo{38$U+Zb zM82qk1JlTNEkb8_?mz%@!>QszlPuw0QMX2PYlD!h-fEPm_le%&S%v-IsA}gWR603Z z{#KeA@8_qSvY))9gjKs}ZhFBzer-K}Ydl5%20ckH-sp)y0!R69f^0XOc`NIHAMrE`DCDabeB8Hro>l&;qm4TNH(c;C>jm z2a}sVUk=YpEQrTO2-&$T=FLjqL-i2L|6x^Kqya|TC&-Rzt=E#cRG3)$%p)ZOX6YMZ zY3)gHYke+xd%7L>DCea7`CO5_xo`%aM;GUU)Qp?NZ54e)UVEb6PrEe8n@y#SG)X0z zPd0wfXPX;w>vC&wvW9UWr!MAMt`?UuSJs&?u@MFH`SMt3tnfUA;sLM9Ssbhg$chC-Sfg@i zJF*CGY!0Z1Reah$?-W*TffSJVllNEYlHX~zr#xzpMdW4ew7thKb9#(e5+dIb^5>cd zoVa2_hKlJezZT~!j}5u^Uxt)dv{s`?#q4MRGkF>K=DaOlhkSqylvH>d+7mL>?gXu$fLFFcxzcg@;u+$iZ_spV}g;U{Uc84}92E0ZDzOWN|^ zHd0W05EEUOyUmi!E)a&M2!0Qh?h8b_(lz}gD|k*P=ktMq?K0oP>%`Un>FMU?N@5P{NNzpyGqPKpZrHMP~ygpi6@z2D{=!of$4-EH#}->~)v^$MTM;vI$RKD&KD~ z*29)t!-!jDY@}}616#!hvkzZl5Q|hc1MZ9yobR4nIDY!Id4517CDxE8dtAdTwznN@Tp++;!sKwXJ_i zQ>4#ND==!3T5J16PPUZr+e{;wBuUX$tit`aLxa4h9d?;XH-aE6x7Zdj4}-;&G&or) zAi3siO+gtOE9NV_(j1I^CS=n2E+Lc~ZuE=)=LZmnj6b>l72Rc>l~LMdgbp^ zwc-2->8raIVd&%MtlPX#Ig2_vI-%w9X+`6N5g(~IbBlv!Btor%@Q6-+9Q z_XhLrrY6QnEq;8dq-aA*HFGjn8{xj{S=)M-?nMK=0*QpG>AtsdWxyC{)Ua#EUjB82 zA77fL?E7}-qEJH=X4|oXt~i9|U8Sa7yozP3E-R;z?ambuz_IXla3OzZ(iHGr?_Qie zy}q!P`V>0jU%ji`%R8{pkkU}dKjHqfn7o9aske05BGdpadT(Z7ra;%-MyqAU z{*k&PJXo7hx?J$7qLCXklQMh!ZSetQ>V)1N@v5u*SULzjw17U{96+@rLc$RL3{9gp zHu-9sH{IG*mQv5x7zn)NfS=j&**b>3USo#Gg9+>&5%*UUBiw@d5t0YHTWg#`&lCPF z(hN)jcEvG~EbS#;bPt?}dy{8#v#M9vq#(Ibs93~c)AL2$2#{*v;-AQcR2;RP=eD~GkI5x;^y(mv7d$5Zw749-ck;VM;hCy5-K)T7EwVINJ zAbA|1`#JX6ivM?tM?)lUp_nSSYxa?p}yq?U!;vI8QfG51>+I%D=Njq^Hi7TW+DC&t2Y*_OkW zRh1l9?TO0eL z&x*YJZ@F-s>|sJh;LVsv=WO7dEAS~PE3u0WKtltk%uGGGD#c*U_NRk#H9LPYjmSWp zfZ~Jv*|`R~;fRQJ>m<|>8T-}uZND{F6l^1S;-w_fGZGPue!{%8R8|^7%N$e|P>mmy z_&PVxy8dJO6PQfxcvS=D*q{=hBYH%=Tk1~w#c>S#BQh|$JH8qegyd3M4emJN_kw|E zM9<5RAI$3-#dXRkiLnws$7GZc@wsJhS~{(Iz;^jD%v?(@%N&tJ%eFqYCexaAM&dr9 zH?>gS7}M!WZfbI(&)Sl9)_My^n>)#HCZb|6*Wi&2@Ti2#nY!SNUIQ5tS%3O|LNJHB zg+_OAAmQ+8h5_SM$S<}HDohT-7{h2J29%fl=$Q8r#vMd&|Mf8v5EByFL+opda&{y$ z*9-B;Vh=HH_r^f~_-eDw6U6$P)y}3+2}KQPXWY|U#PoAhlTVfBK6yMHV>c{y7Gt&R z+l;2r^X$#++Pcjmfi^zf^ev&+oMQ<(xt8rQyXLWwp8nKy^g_k#*-T{W*$=IkD$@y4 za@|jQ`&%PV*~ym_e~*7EFkwy-qv!7YO+(wlYKw;t@7>p7Y2$8D{)wJ#Mrm7wytQ1q zyztXf<88cd(T(2^1?1r2-|-meWfF0q?o83W%T;TV`SnW9wbKisiE9pBJ^lBElhO8= zzed{Hs_a^eWMvD2g(SsTgPCsIsf@S%a>*YP zP4#qz8w-ap-aEmssm+Rm2UCwG2;-=ld3YiruI6A0O@*tojg9T|rgIIdGF$His&(qM z^vUM~kQ(mrPVZA=5upUw_v@M-V4SY2)&jqK+YH}a!m;xe8) zlwPBgUaz!$BT^0piuA4P#;TyM=Cu2tc?&iQ;PN?Zx-A=@E!?d+_h4Pwb3Kj6-P8_A zOFN)!rq0F9Z$cSU0h6!ZRos5P&`ie>eA*;>FxCnWPdx2@G+S$?nbjho*BQt;GheuQ z-8M$|<>{@1=$*tU2BoYck^mB|OfbOX8 z?kSbUjNbar>a-|qQm=g8rpn%q!LGay8`fMx_N>N-O|mYpR%*o>1#okgPb0Fds{$xQ z3iPhoVzpO!02)3vjZQlS>UQ0B9Aox%|0KJg`JVcmt)UNy(1#za3vWqL6m#h#kAh2` zkD-0$BaLRI#5x@EqVaE9Z%8X}4$C7V&s$w^wE72t!WCn*0!MdXQA`Mng%`||fa;KS zE`bQ{KA1aUaAn%Po^}yxI904Kw`kg|xLr)L94B{?sp2iLJ2Z?FRQ?06c`(_h=Cq(V z`|}fib2afwLT45RsDa4$?TngRt87BC6fZ7-QVh@giJWg6VryXGYX-rvIVmg9r~T>a zwb|F!C&oxY4?jV<)3#zJ^WRR3sa<5XGS05k|2w7(hSiRskcSO)()$bGAJnAt99#N4 z@V#H}+9~s(v>S+AkK2DYvTxj(ei*oR+wq-PCBV0#eo)Us1u(j=>QG;f^GSW2P?!t~ z=&i{yYk$Rw?Q$oID(4@i_vk}^4}pO>6=2&8Itgbp=0_`~8EZ4tc52+_@%*(%-p1g; z8vTIr4=#E;=H@4Nx|^oZZ&l>Klr>b({&29~G+XePrtQ78>ERu|9kl)Av6E$nqA^&+ zcrQ+1eK(dqGd%(^%R)gx3nbq^?P8DrxqhyF{k_detx-)nxf-w85C6>Ra&U-HRwWzv zUQw|?_h&Fmvx%t2yWe{=2;CQT0d$K%qWKJvJdhOmb_So8yx4TreQ*fXMApdd{;9Rs zKO!W1Gwweu)R~XO!U43JE&jdraQ7pSYfj966O;udPD3M4R z=m7CgdEr6`V?rfaTr)^S;_E7B8gzW@!SnD9pYXlT?iT6JGA6nf&@OFotcMQGE5;(feiworyT70uFTU| z0DFlf|F+uc`{o9rRj_Wp?Q1l?5|1oZxRh%Kv%JGd#Rz32E0JN%C$etrB1M5(ICj`a@L>4Qg-oWRo`q3rez%gWDv3_2;iKqRG-!g^zgT;;( zVE^Ql??R|HM@cP|$_%eOnhwc$;De15?u<+IviehFb zc-gUQ6(B+3+{jY^AWNSvVAGyx9R*%C7pP>7_B#~S$*=YZU)SEe3FbDu223XLXSvJA z!(aRTV2RDAP4H+jcM?}BINl5`^FqZQc|f-HcQNgAq#!X>rjCDQYhyhJb2jS|Syy|P z22ERlWOsk0q7;j^n)tGjPRvFM!TZsKUGUT@d~I4eVx7i+2;Oid0LoarlJ9HFg(UjW z?PPy4}nKz^woN2vih}I4#UX7&*0(#km37D1jyeHGfT1!>WJV>9a6`kC3 zrY;sAS_9dd{zPBFX2m^3w|MKM5L;Uh-u5pRW8Z$^Pm|Lnl8XX>c=&3%1``;J*m|(_ zUU1CD>SFz#(qJl5zX(sKAzgD2M1>YiWM8Mg2YvddFYX8HZgfN#Y?JIS3jbr;IMcS4 z#BtCzmfz|`C|9wSwp?;`1+M1hs}{h+@rE)XA>wci9e{Le`muRv1#3W{+amb6c-tEv zD#qup0zdwQ$h&K zDJh-2kG{B{RqpDI1iuKR|1fzhJaOjle_K#>Zmj&qA~wlPjnr7$kc=S6ZxS}~E#y*I z(~Lh=f0q#yrH{nT>f{Li*3)xRA?F)B1@yyL@j51VFrYwEf7EyZ5cT8A(`-`-sWDc} zhyLP&hW>)-CH0=wx;{%@!pz}Mt(5x_G12uF(A{m2&zvL=pU_{uFaKegXnoCk=EWKK zl?IM)3ZP^1Bb5HU`ysp?l&Wc$QU)otFw0`f@Ap{0S9X*#2i3qOe7^DHc2-cL*Fo?KN1?X}h6udPpXw4?gd z*LdccGHDh2ikpx9Q<%8oC47VC58e8CQ&G`J7b=rGfyI!iO&-`J(gWtVAHf}s^P7znW_(;cQo@jT_6`&z8tb_nJorydC_;UDldt$3_I`WBj zkc@ah+2=<$qm4EbhcQdc@R3FGH&g*IJ6iXAs9&gKp6O*=9G=4`f2=3^UPhBmES$`_ z0Ze+zhncNdjz3D~TTs)MK}g40lQt!q?}tEYxGK7#l!Z(qh1-aacYJI6TdhGmw%m|f zF}EEg=;0M_X?*yT(0UZjqv!O57Dl$Rn@2O7lXiMP%D)X7N569|e6gX>)m7U>5m_MU zXA4$;GQqged{MkK^Y~H54BUsKp}`D(S$1p|_?(_9TQ{!fDM+-N28RRAH}fE2(z+7H z9>!U&g*`>B+3@@-k1Wq}OEo6t`xsTFPajJ)_2#A(DC5t@2=@!{U|Pxc*lWxhS*n%# zexM+JZv%dJU!9K%sN{(rOxFox9W09{y+eK=)`_1rYuM@KGG4i81m;X=xRb~Ko`zyG zF?8z0cE6t(JI$G?czM*X1xw{V6~Ao+NO{XNp7ywdjpCjfGY0&UFcH1%Xo9e&zW!@a zy+PZaBKu6Eb!jgS1E{?rMUW!s>3Bs4$KYI?%ds6@foq}HEE7x!&9T3!aXmgcwo3`a zTGfifKXtSLrU!boE?CKix^5hr87SB3``r8+(M|}Be})Oma>(EDA+erlDP+-Y>?Tme z_9VqE1H0Gn?Tr|9h}g7Cu|1}HI|AdIl6kuenwY(Vko-sz3SpwprC3Vsc%z2gPK^o5 zoeEW3MCVp1Iogv9UA^4dEg*NeeDZrfQ>yB=#sq2x%j8Zayr54th{F2u4j1_yb$~iJ zl9^8xw?ehdnz-{MW-SPjy*<4(-Y*wYY!Wl5n__K$s!GEsC0OvJb!IR`zwn7QksHCR z^wq!#L^o@YUB)1h+vum5lY+uj_ui`JeC5K>M$?=LJ)Ih^H^R7<7%&p{gp0jF z&HT%5E&pTO;0gD_OemQPSoNy#sEgldqNQ!R?qZ4Bgy>)i;H)2dZnTXEM|-PpJGV`b zeen6zEQRA{l-eLo+lPU#_G-_{ITzIvbG;_wDb+5e+bXQA9L9;qoj!vyTX zsPQ@(ksE$^i3n@Ab#A|Aw$qr=4TtU(3H>C;AKE|uArzVE-CGi{V@uO*PdqKW!nYU-uR`I|ZCu$)tGp9{p`-rPUb^J48tf!GWAH}~O z@8~0Xd-z?cM?DybPfaa~D{pNt@|kIg8T-%sdS`LJ$sn`A$jsQe+yHRSZcgsPj?>^{ z9X#2|F!tcKG!Dc25aR*OEDd-OQ5S0-m5J%#y;+;jJXAeD=vZ8lGLG3-)zll$#>pxZ z`h7PdR>a(D#!|8vH2&%LyEnSxq{yk6jco(e)+OJUebJ&80VX zqt&+T)tij6+WNd%C27mnaekKBZkpjLbSGlCuu4w{bx^lbcYiOb`3L^Lw%OtGG#hnmZL=ay$1!?dLtjIGE<8HWFz6oMq>4KS_>1qO zpjzD^zRrd>-K$L>B^`TXs5`ZBl{xfZ7S{)R{y6P60934U@H{boW|GFzr1FVSZq9^V z^~VR?!a3XX^TR8K0t$HqybeA<8N5WRciO#U7iP8TpBWdi&&usWUx;`E*qtEQasH@b zMz#3)i_kkAmXROD00^FhXVKRrsZ5snPsnYVX-u-!3r;8ir`cvO4*B@IPc=mJU?_=R ziM1IWvoczm@lSb~Aja0o-R8(N?@s~yX=QS<@&={0Zc*la(H9}n$wOfFX}@DO_&qv{ zLVf9QjcvhWHX0p}9^JR(p1XIG#gMoMM89GIECA)h>a}hxWT~1y5lBBTtECqbeX*a; zxKtRcLQhS+g<@&CCS*`WkS9NKEc{xP9O3>c*RVSsn}n!{HVK6oT`kd7Zn}uW4mk*m zE~~Gmj8z#ylmKb^C|K5`&oh}J2;H#zzEpIvSM7*BpE#&unqF=ZU=hZ*eKKqnqXw)h zl-C$Fg~h!meP?vEqBhr26RH&I51Qmz4pl3VX;f`sy|YscC;B2nKh$B6yLm2}tVs0` zb>Z_nNJ8N*Gf5@DB!%xN6@9P<+iC#9q+E@9yV{d?wuO#mJ}*vcMiX5AsK=|(e1a-O zksf(Wk1z0`kI1?!81gGV`}VoTdnh~QlnXbnu#5;>CPEK75%XG-@~q_uyu zNkmSAkC>|#{kSghWzi61$Zb^fnTci?H+r{XIs|LJ?c7ZuAa=;ek67HPKV_u?wqF??mBg1Ww#=^R>ewfCqC4j z*@V*3>FHVZyI@~n&DH%XTV|VAT7y^D5%lZqOSpkD33NKBdJN_ zhAQ%wlMzC;^L^Y4e1I@{hFJ|d7OMq-&d&yq+DFSuHHqpfQZfoT5zfpfTfQT`3xyi} zUA?_AKnrYHVPVErY%{7DkjuT5bLA}IJe<4) zo+rfh{ZMCSz7getXkiCUPr}U9I{k6$Ovxs5N)Wt>Dw(#QVgxN5O@DNpn zg}%OMp6k!gF#RMSjfv#ZxJwE2Iu$7|T`!On=G^?L*JFxE@T^~^U@#l@?}uc1on|sl zX~%jL^N6Q@c8hGFjZth~`J(Z>)^HDXOi`6p;67d`$*!q>=d-_uWuL=ID7HXIJ1;7; z_^lWZIMH+icy{0l!#keZu}huCkQT!*rCJr2ZgMxd*lW!MRS)g(44nNgz{Kvx6zQ1X zo7bnW%~Kn9Mo6DBCa-6yxF4EyYgi--jXG%B;fjA^{fNale@TkAVSUCu69Q(Ue4s~O!j)E!J;E_Al_DkqK*8ZvvO+P7hNA@RV-{?!8 z{YgscQ%PV+Xd5XJh^X26(9`KgZ;7n@4=eAU;V%T~KB1HXT9o12kdHd+Nv`5DvOCZv z_iM5GOL9uc(dZ`K^clDsB;b*jTvqg=?3o{dFa%bD7fX~eK^q~h;&81hc`dotblRVs z`!~^SF?bv&9hXyTw(CciD2Ig52Ukr=gwjxVPqP)ueHjwEwrLn8t9D7vX3?o10;thl zE~P`V;4m@iv2SQlh41GEQXmD@z=)O%w=jM*to+2BeYn`(`j65@5v#)_<`G}p^@;RhX4S1>_k17MF@v7}WG^sMj-NKtbW6sT%R@RUJ67K#=|FVS5 zDR+3%3mRcnqSACVyUi^9Q)z>I3Y8qnh8svwl-Z^_sTE*4qHJPp@_a>fbi%!n{h?y{ z`fLF9^RjcB1{t^s4++rBx_7p%JGppFq!z;}^DM=xc?l?_tSC8?Ki*#SmDH0nQpS!i zU3ZXH#nVU#Dq&yOaXFln;X_Xa-LrK9`7~1@ZOQa%qtvmi1!ft;m8uB$5m=;M%4!f7 zG~O;%qc_EgrO(W;&2v=W2-`;ea1t64`Fy>qpKYfH7*ze;5g#->?rJf0QPJ&LVvvQy zL&RROP?u6{*7&{1<0AK3Yog8r$jF`RqDmXvcB(Q=sr)`IOZz`8TQTiu<1vo5Y`{sg zkOr8;$|XnqBDN|ZFvDwbaa%X%l@sNa?kho)<%`R%B8LzL`8~&aOi!|^!|=f-c8sm> z6iZ@>Z$2_ucDB?uBCg!y(g@+0JJ{xTc*Q*Owvg|7TLIEvGD zZt%*+H_;Q>dtWq>%R7(nTwjyUr8n%WgBjmV&&xb|p-RvaFsQ(%&NxWz8Ff^o2huPe+w1F zXks~==29I~+P4v+nD}DP%0-vil^Z(WhOKifdvzZqrL5c}lJwm8{>3~?Xh_(cG%6LL zkKt}yQp`MBuG(=`fl?^VpzcnbYUaz-DCRV;4eYenVlOVtRLP&Jq1;*izrA@zw_^Dl2@ zi<$vp+=Y?kuK0=me;XBegtG%fs4irt{=-5|%|om)Pe{>Q6?)kc6XeiXUlw(H4cU-S}=xM`rYD2|_osr*1HA-l3QJ%_ zz+=4#>qlUTQ@qW*O`7Bj6HM3dSSluyR^ZZWns@Usj}kW-$uO=14BOG%IsNP;q{gM- zec{6nO8{0d8HU z=2M)cBhlRwlM)>=xuDPgJz}wh8L2j$1=4M@SUQPk-BPr!9XQ4~#P>#7ofUwh@ackz zXe$(>7Vf*M3$5R8p4`ufcyB^a0}VxT#LFjs>^%L$Qd2McPe@c|n%;ILxTAIhR00vX zqZY0!-wrGYIn~u6ElPOL7}(n*{t&1>n1LGl>Y# z+2mhr)SI*0O9rrpWT+VwYKn>Od{^wE25`qB9(SPTt;Gw=@$eWiC!JsZ|vVKEj)C^^3IWYxZs zJ7sk$TN_<=Q~v1kKJY4?{p#``oqr1zsUY*N|Dz(Rdd(bNi5QQn+_ZGv z6EAOdbysmgxc?|}83_!$US9Xx6(#85f`fUt!1=txb#N*2O)<%KeLiKHUOO4u;OEkO z*t?v)iL4%nONET3xNplW6ZxjY#82+6VV(S2D12k^dr*y5Z?A~pNx%!xgh*rPbj0nC z>&fc;ik&mB-ILY5xw=Zlt2Y!31J>G1Q&FTkaRlE-QheeC$cAUd9QY?0_9S9P0zR*j?W#bEJ znnF<7bCoK_ZG`};?AQ^Ktjbr=jx5_BKV(ED`+}-L4Ty0mnp1P5%Yl$u5D?@3Tn(&> zMs|L)8do*uvi@?Z%w^+&QxU>el}V?C{uZa%!+<{`L1NlQ7pykr-1ftpo#u~+>epV` zVVeZdKa9dA+gI!9*-TqY#tqT5#YyAGhc~lqIW;w{dQ{0;Z$w7rqrxq&CEulQf9UGT z6G}V))(WXCr#QKenX}Wld9zRo><^7txs~%voGXY8wj$S-tD_+OFEQ+yY|P;%)FRa! z@oiaU<*0pySnLDaV$poVkbpDubpNZi`@jtkc;`^JtCSICU?P5UxL$|dl+;jU+qwrkc^RLx|9qXq} zD5FGuP%~`FUFdk}G~lcA?7jpOb{%5?gsCv;j(93>+7{xwz`7j9+Y(&%(s`BMYXO5( z9Kon$lJ@;lHZO4NJgK_P>AwE}^hKh#?oZE7$FViLI9VAwofrFvW-@2ow`pT5R#*|k zb+8vgT*qf2f8DbKk^SPe7HXIixWt3BsD zGe$cX6o6JgoyNz;9K6gOJO)b~AmZ7P$qHTx@a%6wGpEZx1OPU=8HwW|ykA*+GPV0Y zSKrr$XymPbz=S@C=r>GW$J0qbJ&!x+;|D{nkYD?H^kueo+)}+4=&Wf zOdw93RP=6cSA&uVr&R-$%@QwAh2v8uiuKJ&gzr?T2#0im{Ps9#!k+ioP*ANct3nBK8%$-Wyol;IL;4o*Eak1c3asqwbAeM}Yie6}FGi{C|Fu&dvn zZY6<7{YjG_@Y#E}CdMdDgSNMM=yK#$iX@h@Fn#7>;x6YYz1)J(g%uR7W!G=cF}!TB zWVT7Z*XAzdsbY`{6f|FMx&(-FdpIU6goSyL4gA4Z$K@LjcW4i(iV>)r@uD}B^M8GQ z{yUC^PGzeJb|v{}ic)uFU=49pd+m}kr+<54$?V{f!0|NG+D)`OX7<_OY{e{=oMa>Pg8IDx0RG`yOHIe|DwM#J>$9lfP0&ofVsbSIPzv?tSH> z^+Jo%I32lh4Qxsx-yEnaqy2mxucbTNo2ZEau_Ws6$2Ra|r0FBI9 zLwe$oY7KFI_K4P#g@gpupQMQ`b)KdDxsPl*A>XMN|7jaKfEQ2lX7;L!MohA>EYun` zVi+&E27lmGy?jPwIyR5h7%Z~3olxQtuK`{x#x4&~g< zGymxh!{ld_7rh|=3P+o;3Xp{=(k;^pbfC6mTO!xG{3L~SXtA0zVJ))ZPuWA+F!4!o z?g>qhQ_JS`yP5+Jzn@Kn&yvwT1`S_SYtMt$^9ovThyY3rJy{-pkX^13IM;=N)(rqC zDbOSO?HQDjhQYS@5_9wuLh|e+qB`oG#FPINFbJP4S&aT#l}H>A|Df^~onVHAf}3>o z1@p*7NT`OC?F5OG#7edmD~6Q)<~yRRPWFRszd|Z5LA7JPaY+|UD{OMF7)KB5Xx_IJ z4Qxrf{U1F1JYCqFW2l`-Rv3>;*13mtO&#c>vZJq0Utz3f{7K)Q&Sp*nB|X6om4oPp z(|l%(gp>@TP&HQ{39Op&f2#-NPRs)aa%3??e7!Z4A(q}iIBFw?Vv4ZOHV^r$_H;Md z;~ANH`PA&7)!TxcJ}e(Cb%=9DGEYN|E8#m=8xm-y^dr6KfVQasNI%- z$^7Zt3<&LmngiyH~nAj=)#%{$f{lV?C{dTF{fPW!4o+?B_C(iPjshgfoolwS4 zqxCzs{$J1w<;C%}(|*72-EDECTq0&PeNrdkDk;&7@((BUiDfRE@@@Z6wRUINdW@Tm>xI%S73i?QJVRHx<*BcqbHuJz9 z6NWYd+m_M5^kO8!B-0mjGdNKLx<$0m$$`O)Bo|vRZ|74Us%~RNfG*lcpYl8r)c#x?ljn2gS+w}eVo5% zUhF3g+uPJ~FXn;F+g4)0&Vc_^_?mwlc6^gpSIa;8JR^UT4@S^ip;-f+U|o&ynISK| zseW1yH`5-gsFB{;ww>(XV~i55*eyPVrFFY+B$`y*R+>3`UlP>0;3Nu;_p-7|p6 z+$%f?p!(S-2?M=S&bwTp#iB<2ZZBrE{)eQqjBE0J+c*eDCEbh~9ZHXGq$M__VIv$)e$W1&=f(Z*esjllU1uEU_fWn*ifak|kASK6 z)oCxb(R833-#Q}THU6Jez3DaSG}z(L;MHlLA$Wt-uD$y3Pg1_=}!R!U)NXa(xDAxJ@$*GoRS zM5n@Hkyp(ZKVj5;z4x!&XD@J?YSZJ%)-*>8OdQjZi8{D(^Y^f-*lGFl@ea4A*R#VO6}hHijt4XCbS38acE$GYeW8CORB2Tuv-#l zSzS1`Q<;r9pZxraJ0$5V;-?}Z?ho#$uRZN%^iH|Y)4FR#FZ2%Xb^<@}V>bND)1hdr&(fND zV`KZ$RoLi6*4e{Hv%{aN6ZAvY_R~F`rX~eo&&T48?w>OyDD5>I&i+R*AY^;%n%vUG zSTGD+h%#OF8YNkbw9>!uSkr z$_8t!vsl(PFW*ybV|#GJD?V%cY7O0gmI@mVKYz} zX$nr0ZOztW1fCXK^T|G6$@Na4cCpCGC(n21#BCLa6i45`Gu^%XXoZqa&b67Cx>lQV z>um3YyhZKk#`1Qjb;zBnQGBn*(4=~!@EE%f#Ns7NhA7st_(X%% z_)4q+T0v*dwCKe%H^oI}{}Yx9!7S5weuE1o2h_+TCu!#qvzJes=aqPax|kWKp#C1` zxpm|g6y-;mK^zOM?SE{jBEC+iK_i;$K>_B#na<|lS>|Z}1@6yFG8_SKIf)z-WD~AB z{0=ZgL&|5E4NTsjgrfG&pQOhxw=%m^v31yYL0fong}oABQ*EwL51o`HR+qo77a9M9 znxu9%)s!2Ya%5DICm{kX`Dv|K0bQKLWli}SiW<{70p`PVgf^#a=(#>H21XUZ}&Kh8jcMCO~hnF-G2~KuaSY9pJhpe zGk2%g)L0yL7F0eP-*ifCA8`p9k5mb=i`f_Tk>UP3#}h|8)8i`gB7N{IX06X{rogug zw}6gD>HSBLzo`{{3GacWAD3gIQ@Q0Ct!6nti`gC2v;){Etl|QP@dWwb`sNb_)(Zl} zR;_6l*5l+#JW%(M;d3nt>4q24(|pnm{ZC00>l5Il?x}jNLUPz;lLlNdu74hkxWAln zRv!d_UG;EDPtL92HN}(_5B|h{iF_e`^102}X2cr=0P)?bN+i+gFB1946l83XSR@mV zr2O=nB@<;*yjDYcKOKi|<%5$^XS{$`SXkvGsOsoC^uw;e&$fRXKU!kD+U&gw#!(N0 z1UwO$p|G!BEO!H%;e1P>oKhlVwNFrQB?VZGavH{;KTvfX3INc%LmODcSTj+xxOD8| zJ}XBAK-&$;s3b8`SIBSuL+mg(>#>c$r#P#7XjxpkfjH5NwpGx4-EQ=fWlIXn+?fr0 zj~%2&M>ZCkYS8he?yIy4k)vna-3>eaqkX4>L88;&S6eTz#Wzz04j8%$Z=gKO`_`T& zj8q1MSAH-R{u3_zpdt*={~>kMK7%x(-OY`w!lA+%6!$9BY^eAXsCeIvAFOjfJ!T^@ z>}DeGz1w%a#JHa~4Tu-?zT>Ib?s?mGbof5XwFDcc7$5d%b>q+m8)*=`BLAaovzfp2 zJKF1o4r}9rgZkTe07Vk~9ZEs#g*`Jz2j}b?z5w0* zxZIKk*)IZ0;bG~9Mq5GrVegrwdiz@28w%fKPV(bMfIvcT*E!S6a>9>(vXO7`;1v?v zOh0Nar_D6|v-Z<>n{xZFt@I%xXj%fU=Av^K@e|QT z7?RxDjo%@Pz>eUy4*1pcQo1zdu4exiY6T^aXXKkvO2S*4ntOdh9?+AGu{ySfmdsP< z=eO;INiB~lB!??Luf9j|(ez1C~SLzhZkBs_HH^z!tZO`d0Ny0Oa?7t#qmHV%>>KCxi z`!cMCs@a2-)?7+OfqxbFG%)we7N?Rct@+1&88ogqGKhGeYBoN22LU<1Sx|e-dE#mn+W8(dN%r(RTW)(%L&EpVEdSRaZ*TQTlFjJgrJU;9vP`;wl zX58!C;$>#Rg^fmUjV8TwO8fh?jL&3rTO(BF1zewjKKrEBSu9!~Sqcg89xRBnvBC-9 ztGleF?!%=lD@|zNc$nv({mwKLl4DY) zs0YWj$MZT-bYdLV1~RcTiyd_J`#5OC6nLfwH;q9Rp=t`{*FnX%_F^0B@cu1M^lN^~ z(o`lJvM-66{nYN=5e&w{-KzRmL2jJw?TC%*g2FwBzyb7iUsj=J1AM0TBy$P<;>o02 zVB+g57s}_irKc0x9%oi(g{FOqK>qGCd_BFn+OsqD7Iskg^!4J&o+RQiy~dcWtX~E5dP~R74ej$jG_{%Ll0MA8BGzt^S!?p%_*W-`tO4@gfkBJj zkJ64W&^dpkh#KiXxV-?|)IN5KI_ zKm20@p|(w&B==}w#XR-)xcaL@zl-~xl>%zHraX3BL4Ozu7m#_J1uO=VB}^4htsC|I zTw2k{yFPK@BVU2hPiQ&N`^^#s6>@`8LffctC444*AMtQHiHxYZS@lWFwFVPd*$in^B}5N$Ud+5#!Cq*uES1)mY@jPK&a`lzd2s~ zdUiCJZXP=Ks}iqaluyLJA8n+k5-+|tq6#WDZO-AB&~{wYY|^g9|~; zjILN0fy!zjm3L{`wi7EAeDj{4BaPGw_6B(-sE@tDKP0JQEGS&Q_0Dn8=b!bO9f^I_ zD#xuVyNXrzj_F$!X4xCzWiWhi8Xq1a!nr(=Nt?DhE5MfVcGe|tAybREhRWSZ)9f1F z3UP@)`VYSDGR>a-bNI?BrurWNAs;zPH1L>VFWRceHfI?rGYoO%B-tF)E?Zn`?|FE9k-C-3zlvp-DxCnhSkGO0O=brGDQg<|)3%eO=hIo;0f4rKrcUTBU+? z-3}Bi>jor@J{qD_S;+UEn@k1D;_X9e`1ID@`*UsYhawa^vNKqc|R5Ub6P`!(CQ406$e z-ahpNd~5~Las8;4AGgDW$gUaz!wINKz(GXav5Pq9Yq}QCM(WjshNt1!p$do>rv=|tuiHc0h^ zKG(ZGciQql-Ph*!)^(E?!5K~ko-?l%L9&AQNahB4V~1vy_Fj4an_zD8I{5g;tDVJ@B?VOl$@8h$S0*|oj!cw;&Y%B~R)h-P zP`N$?rh6AOK0``nfp=Mo0_qykdA$xZ>@CUj9ltWOn5t`@(j8L%%wHTB_p7$C8e;w$ za?0iI#M-I+_hPF-+9f5;eLgo{^N};9XG=aM!W*3E0tM{<^QM|3%J$>8iGUXU2y#9Dr_!Uj&)OaSBe2LGYwn&x*N|M%$4ZdEtF{z5 zLDj3fdJFIkR+Hw3w_FFuu3t@bA5y9+$nzGItZ*zKUGj zLB4&4HmlAEp2(-;CH;qN>PZU)M|ZkewwRDq+(pUSI-(MrX1)Lv(EhjBJOCdmf)+ls zVz?(v{ASdG`StK#4yKY092M_bzF z{QUlvWh$Y&1>vAShohhA9E_hDXa~{gH!$?}*Sy)99O+f-7bcFJ{O~cgzFJB#YzDmh z3LDhjC9nmpD@vL=(%0O*x_>{xRrxg!g)Ea%sU(GW7$9V9I0C%0-r!+;6In*p>vm8r zvcvHXxie=F=6jkF5tlw0X^t+aDj|nR{Ui^De-*9P_F~H6gomEa&X@%C|C2okT>DwS zG3ei%MIB^C-B4kGeW*Toac{3+I&a6_->ugReKK9xT@!}f;M0X34(PUhT0Q-J@w6pw zi|MM;LAh%i*_qke(Jndu0wj}WzGKFH9c{(3QaomG&1|4`K2{J?V|W!FratGibn2Zs zHesFg;zMSafkz#3qQ;AH~C!Zi|mG!9&$6?wta8(5Q+^Ep|9O!K6`P z`W?Y~dIMwLA2@ae8|{aM@5?9&!|iJ=-BXL#Kyu@068i8KHvqR$n~dS`_dpl})a5*u zaA|*fSWlCCA;Oq@ToNB!WU<(^wWgbP3Kj%lwAfmH#Yyy(+>LST+_3jxlE;=q7yop$ z=S;rhOzj;L`oP>Y%SLi4G5<1(k&4HC4$v9Y;(~M$R_&vyA73wAju0 zsnN9H@Zl=v z&T96z;sl&d?|9)n3Jpi&n>Gu$p-PpqgKJb+)#?YbS^|!>M9SvK z>S{05JwYvo&QiM9Z>d74F)Ef)x8`iek~&|1@{zgI_%}Tp1Hyb) zC+ueM=km{_j+b_XG^_B7F;;og<_!IsxOQ`h&({grxWWqBAW0%v%;ai5Rnn`|tCMxt zDi)ILn&i=BrcI?NekRG^p4mHTrz4DTO)nmsPzGk47zAJZhe93=f-lH6La)nBLubGj zW>Kh$idKiliy?Dnj5oUe)vn#2^|UUjX_oxjb)^oS1+0xp~|e{K?RAHm?7I;~ul_ zG()$##qa&VhS)C(po70AfB6b(jzb!h3X_woR+&k|+Gc-i5+c%5_O4;0TL@cYO!Nfb z(L*nAe%WYU-C=h~D5UcR%#yL9^}U$YV*M3)S50nBMR$8XcFRs{uvz42x#4=cG)zd1 zf|947XpZE^{B;|^=+|(_*=fXGgwdVR?_0CT(v|vD%0!pq;`+!UHnJ}!kT5BouD7Lm zSy;`nawE#d$~a5>qSt8U06jPbldLrV94vql)l9lY3E@@2e0X8--lrQATp5}cal1oE zl@s*m0WVd82=zkJo-+zmaHtXY{QWQ~17&<_>NkOJWMH*2ORIy~f1&6-{$Dl2wT3db zUC=+_mgVCtSTKg1IuMG6~1v)feWN3qzP+BsTSnbfhzT=lc#uN*g}%E8(1YbyZ_1!ZF9O=dir z=P<&$Crn>M*dz^~Da#k-dtR6L;f+9K_jb4}!nFYEUoom4`d~4m=cmV9kE(4oCctNB z@v+244FpDQ;urn*C9*HHYk$~Ae;=7+r9M@;DSt^kXxl}A%~gYlgRCb)X+~1|8ZxO3 zJ~u&KWTKfKK^T1&BaN8ozZvqq{<)!$agx6trcjG`1)hxr-nb1aNsipg3J5L$nk?1< z-hO2sH)%<#fRl}^v_D|+Y3tdei^DJ_rX4}B1p4Q{X^OQ_cZcOEX2VKwNJJ-OO4`B- zG-8GEw>gS5YF!XG?nV@WA{e8-I7x}Xsu%@_dy5&2xqHnqR8VoCAYgg*^%C^fJbf?S zc#h#vJPGSlRxMTf&)N14G4XLAk`O^pCWo^VGmj8?Ld$^$8KMMwbM_&VLSi7b313eZ z3(OW2wgX?X)(UQ)-D`*v{=Tjub3dh;KQ_ygP~Ka2v|_Qy#Cb(Ap5TPT=9LECq6nK=fMnh)zS#=Y1bK* z9a5(;T!GV`EvxE3=6z<}2`c2)3y(Hg*@F;&ck|($HA8rN?viyTT%24aRVP(Br2mMw zBx-)5(-tS-35;ORWQ;XRbWV)5FuDb+G}4zb`Hx74+ggsY>J^=a(sh*@hF9LH-MQRZ zd0ex&F3V@p{!1z;1EASb`OA~%)89f@yDJkuG*p0v8)jiwa`AOadh?tJ(VD+aKb83 zF~9QVmTEZkHHDX9|mMJA)^sL2~%P6YT2 z3~PTuAL$Jsny^QcR{JRPRCrF^<(YVdz0N9gAu1`KEZoOd7$$M~JiMHSI8SCCJY55c zmd85`3HJ9D%MXwtYF2D`AT_swoUR{}SLA{xCf+<9;Tb$(or~46*n9M4*^C~)gls@k z7<2SACLIGbOS-XW%Q}=bXe0QwT4XU{rg33n0xe9KZw2!8L(A(Z3d*eWNhkb9z5zOs z7v#6HW*aV~?+6?WW8z%c3V8b2jP^I5o46r4Z>Fs55^ctV*GTWPHXa#`Zd6KSu#|MicG<_H`$Pg zkb`;dN1IK~YHY&uzRbBZ! zc4o*9!<2&$E+q1_ZK}H(*ruQ2LZY-7(wwuPFwcL$H$7=fyZXV3i7hWYpGk0iXqxMl zxm>>UmHqb`hRTe-kL_)0>6$yM{aHox%*c?Dj`TYD8zI&;I3@9Wa8Ewp6PiEicm8p7 znOo>HvqBYbqBl@xow3`W?SW1}euHxMhkukpwXply-Ocy}9gfYyCZbp+*4=Nt3o?*v z%mHtkA}1J13qBj`di!4Vl`wg7))LZiazFOyu6{tHX~;VYT^V7p$)Q}YyTl``6>$}N zJyc_F);*V@1K zmumLnue@Ig0PX?Iqz)Ja=08C~4r_$(N58J$cQ7sp=va_=C_YQRr7e&#I4!qUlKQM3 zFxkVV8udb%E5Df~fV<#SxWThzQM`uFblEjgV5(4}#c!=z7Q^-PQzda%^Q$!XhtqiU z@|0YJL4;X^6ClLS9XE*SbZ@{0{}ZUk&&D)Z@}DD~r*V09a8eAbGV2sa{R#HIM$Gq% zKI1S!0en@Ja~P-!`=peFhN3w+p6v>|Py!2~}=_`5_vl`@eoVwz(7re{axq=NN&PUyTTLNQ&3cV*l98tak#UT6`A;u!cgT? ziWb`f19diol7{iq5Y#R}JIUbbX}B7`qARCRn2-0FE5i$LzraT_yw1F?+JyvmL=Z3X z$d!zK9E|F8SCZ_859>nq6}y{Sdp*&lc_s1Ni{eN5f(NroK4YdCyH(pTP^FO zDBka3Cr6^)mK>}H9vjGw(n zS+#y}ycnGuoYlmJ?&`xC#%+Ew#=2xO*4*FtYBPW^{m$|#WZE7wMFVQG<-indsbt<- zdVvQ@HV#^6Wr{;nzI16+#5`_bl}F4WxgySyzZK~DdNB65y|eU_E%fG*oj%vxv}x<& z_Ckqh^xF~#l+b;Qj~$R#^!Cq@hIkRi|-s|j9d&g9A8ro%M7-YV%HsC^g|-%naZV;286 z2IT?1XIc8TEAE^l93y9@6}8qDyi~d~%)x@!f8vj@JhvGM1#>%$Yt^?ccw0_jBAr_C z0O5ZGdI4gDelMFA{NL}G(VUDjU6A5-VW^7iKJM-#7e9w8L=8yEI#V1YmG!7%_R@t- zVdCNZ!Uv!73xSV*7#B)_RB%-& z82^w&Zx-s$NxaRv%^K0~fe3fT#P5}gkJNyANA{SnTlszX7Gv)_^l;VQI5|uVR5Kdy z{{*G0cE9^#;=KD^_h-3M7kkGKVAp)~WN;^&pIYdt_ldW2K=ym*MMjDFk|(%$yewj4 z4qU>OgR%|X8ZG?V2Mvh1;_K?@Xfh=BXCr?Cd~{;Mc2yjAJ^kWv*(wUg8t1b1}^5lR9Gs3;Fpk5I~29l4gvUa_xD+T0m=I} z9%>;RIqjL$TLIo}uD;%(>d#K!eTGO@&db zs-iOCw8?VaY#2~r&nVC`U*M40$s|g;wd`Uki)$Y;#_NC==ZZ)1(X1;_ZTJ%V4mt^1C@N?=sn!b-0JfqfYzP?Co7~-lxoKDSHI#+r5pF z`CM%^)3gb)6p=CbQ{cnxEFHN(N&8jb}oJ+Z-# zSVZY|P0CG3!CSjqP0PG}9K6TLf~1pk0^R2CU`z~?y;bB^Ws^0kgHq3a7O|{QQ?u+H zXgyu$z`HTX?^YZ#)HZo28h6iB^eku;)^}f+ZTRq>D`*`WT$R7Bb$cQt#mQa1o};<4 z=3{SQ{Pb-_O@cOK?-zUv6r%aS>&d#EP1$1C%4^@jmt%$TH{wNmVjB=lA|!=16O!F) zRA_?{n7GYs1O%QRGJpg8Vx3k>_I9lPW381nhvF&@wJtyL~UhjqbBc5|!DcP)sb~g_aGjZCrE3K^o7zqn3KW%V&{NqEhwPV_Pb;6S_-P^B+AjOjr4HsQ*{g zqFug5Kw4e}*!67lSV=^BhMFoX2q+24wauwm3OYK`FyANuY;<0&wjgGpi)14JAPqka zZ>DsH{?l*2MYcKCSD4;17WO2k+uj!JKl6-DE%oDm>2vHs;jiic@xd{#4`&mCVd3I_ z(!%+0+PjB0a{PU~7L}qSgY+p7qr|u83*cKhlGhyVmeld84~fnFRE<~56~wR&)6C$?g!A(#frq?e6%#2IiT%Yj^FK3wrfc2PVxchKLS9>?-9i| z!xjizP)t3z4S6K<@`TpXn&RdEBe6oETq$F!&aABJckchksM|4B;7tBoAl*y^a8Vz)uVaMaPo1*fc6<& z7wurDVWEJT0C2Ll+(IFYmNc$|Mnl2VW;H55h$Ow7zBE%>PPb@uud~ zYb5@2avuVB{--CMKDuSSiw=;TkWz@j7oxY~# z5O^)W+pDj$$kOlkmvSJqV2}yVJExI(28e$v>Lj|SvUPFl7#eR)4}jJ*32vI3viU!e z;oS6{$H5^G+k30KDl@JCL9f$-4X76M-2BFLodKV*n5~OTom*vlpSp6S!BtN#c&5Tk z6Y>Y*orQ~U^M`sXkl{||)*EWN^S#eGqZ672M{fK@*gwzLhqvL67B5UFb^skVW-cUE z7gnMg=&ey++hkFwFB4J~9~mz5J3P7aqNPDWx#T>Yqwz{nG4sjcebz`!$&{=KR4NtThNO+H&G#=s;aOO*B7iLE-f|uoGXaT{SeZ&KwIRG% zQ|z18RS{@piXU-kByg_7jIsd^^z^# zO^YTv_UI%sIbmjxY5jT4La36K5<7%#ZpIQ+Ga)&4JgDvB;n}-LsWO^SYY|?(>}asU zZ?rLr5R_USYgA!S=6I-lZ@9~kRfEM{(Y|;2tnTuk>^Z1wKHeV$e27&`xL zIta^(UYN^}1h-q*Kk3n=iGBP`^*S_MFjHDH7rTkO z#ob~c`_s9nK_{VyTH^5`B6uCvY~yWDEm_3Vk$1MytDMgD0MGM}Lz+M)yFOL<=Sz-cpKM)=r!v?=jn8-?lzr%&O6OKG9CVA+&&J| zdE*%Mp{Pi1H{|byZs4I9!`nz&-=nvD8F6jL5x73QscBpY{*AqvJ<08B1Hakr{nv!p z0(Q}44tXXN9s3pq1D%#f$XXTgI`bkc;DTcv%SzJV^68K@8*}tD58gC&e6!%EssF#t zpIarg_1FWOkuY_+y1|kwqJr4tD-(n|9)tzJ|Byz;oGsi?E&cnA%fMC4b=Q>vJSh`da>@XeB(Y@| zB~M5&lN&jm+shfG~8m{lGHYe9nOk2okl|8<>6(=SLabX!Py|IP=Sm5C2__3@W> z>t{hFL5L8r2PnL$dEnW(?gaom^_m?V@Cp3eTs$2hF~rvPrm>9HNRohXE|M7U!GXs{ z9<)Lo!^4d7CjF0HpxV>C^iz9{a*YxLCqnvhR61OpWXsC8(*`PLg|7LCgHIYWx?~ut zY#*W0v|k4kvw-71lb8nc;5y>y6^+Xw=oqLpja+xMC`oz+8M{Y)o}{>_U;o3obFDRJ9SD< zh}K;t!&w9j#FE8>Pxr4|9inWW>MVxDK3_;QFm&vi>Y6dEyJ`pv>ub{$QADc|q7qk+pZJ+}R?Aj+>m-V?fqH&)_T$ILbK7I?g=>V_m z+c-(D%S2)JAh?O2 ze9whdx}Z?X{DkC_Y{GN+=f@5QoFSk-J*9n0@Q=Mf_zd`JU*7=-2VxcETUW2vb@Z&F zazjCCv>Oxv#^(FtYtqN8-z28FJg=cc2)uh6I3|@VwL7tm5c1S8EXe6`N8xMGed;;W8e+Mp zYaCXk&{H_FOLtVTwom=Hd8&#+iJ$eCXS7HTs+R98*v@%}gktd9M^20^cL{QgKZaz~ zzppU;#jCcSVJ%6K{}H4>#O1e;YiEL>Z0r$+Tz{crUVez_^Uw8{bf$BF`-OoIhYZ$&4-|6jK2hQ6QsmMm5F@?0oP6{e%;Ry;(X zHNY{%-Y}4+PLFPnu5O!4lBJ_6h(jxcm=bHCQaSqGRlRZW%%=Z6JIN9!C`5FeS!}e^ z^k4}h;Ozt9!$U&3xXo#LgujafqZx=uHZ&zV_Rn zEq&op+h6nb>5S|wiY{*Kg1YCNZWJp|OOw&ZI&PD6;$~ z{CJms?6g%$u`*skcLI{5=+xSao6(n4Fh?^^%#G0QsOcJtuF8r%_x4`>xc9|fpD#@= zQAra$nHh7v+6;=Dw`~YZ)YT#`IcTevej=|;@g~&8Mr5cR1-YNdRG=QA59#S2KbON-a&F7h*rBsYKB_6mSny2H z3=j_ETOIlas%I>jgbD0@9-)}XSpVlJ@orNPmdh*%WME9Pmiwoul12kc0!HE~Nq7g~ z)4o>_F}w-ZQ){&{Y?5(3Hq={c`_mG{Jnwpz@LK&z;fG+=4s;vFaC9j`6SsuvL;kxo z*DgP}F((>FC&x~h=;4G1EXI$+@07`=P5ftuV9t2TZr$o?o;}N+hd3SBj9~aMB=S*^`66#eD=%L zU}VZ+#FinM>lWdqTq1va;|c0d$en+yB@ChjUaquPo*Az$&kEvK|M0#iv7Ls);rwI4 zdwd|xf>HQv=Z`7>@{A{`kFecw!==6XYXd2+UQBCC!}F5Jt-(-78d2%o^Qpv3)XBXm-mKxX2zipjLq ztKCjcmc@)c4*3`KvCbb&|J=Tt1>g6Chq>}=`-Un`FL<9qG(ED|iGr>+*>{3N`D;@@ zmwpIznqO1Ew>zcX@W#jdSjMS4yik?a)69w_zs9{0!F)3DNg4%R4JwAkXQalwdH8dF zOH5ycK39S1gwEo7uACyi%A1#ju7{z3Y#@$Hip-K~8-P_p>RpnHDC2v#n1!Xjcj6we z01M7-nE5;Z{|Jnu?b>FPID^J*g~rYPBk1kLJd)&C>gX-d$nKo1A&K=A6`eTMD!8KJAQi8_*9vt?qpL#TLLw?ont&*F>POteWCp~}Uq z3C}l~11jt=)wF;yCSC)>61i{T&4m&C_@k`g`QnSd`BRhX(V6^@kLYa(b!gYXh#z04 zexMjztYFU{gQ6qvf+DQk?^FxNSNFfx!=CCc4#oyK1!}@7JS0yLMNf+4vm$xTj^1q2 zV*>E4mr)U{7zQ%QVl{uPE@^y75m0QYTuac}Vn!s7 zuNzuv>RD$Wa*$zS8Dr=#@WyUkuZsKOH^qd~vA-}u`O*5tDVJKT=LD2ElePR(?jJSq z4ZJoqv86SUpY!61!!kn`&+cV(mVOze&n22HqBpLGAx-%IxhetCKV6=ACMATaxqC%KkV zK%ZMi%o>)nf;FU04nrwn$0ijAOwe0d-J`9a1T@CBz2{CPU)nv4%yIJd)Ohm6g^_^# z&tA=)zn#7if)$hYA3>&F;77WtQ+x_;XnaZ2vg|r_zBa}fQ(0I28TO&Vt3X*^1>?1- zr6%tD^-gy(pf2JyXiL3UH&*;Vf?8Ym^Fw3p{^4P{afqGZ>sHv3;j6G^1p)j5Qo$P6 z-+ABJ18$WvirR8*=OuDIj~wLV$+E*`9I`_b8&;J!abW+@1XsVc{EpCCO@5w$_sM&1 zg@MUTX!l+7TKU<{U`&7I3B-B~r zd6Y2k$P!@p!#&xitWAoguBa7@0TpIR2Btb^}B6Wqf0Ym6w}miD4h0WZzgOkIp~Reo-a8LvFSxk+u&Ag zMKOrbsn|-pH9*RtWSW(lUyy*KZfptrhE0+l6+3ThXbtA?oxc#mzOdDb3JJ>+ubCt} zx?FhH8Ua{#jhZ6|acHvx-%9K4$MaYC4K8#6B>e{d_4J8?~z~0rriayhZNC= zNt2}szI~4Oq4_QKlugkV^Q?;DOC#`Yh}hc1^Il(&Auz;-eCkp=qOmh@>u>$SOuxHa5bjwhng`{5s3 z;{Eh~!wBLTSIU~_VgwA_8KQTFBOz%=h!gwF2b(^#g3h=>^vQKe6}JChOSqeLY}VoE zZ76YDw*~Y|`0LkBm?0o;nPTvktvzjt+U?y^IOP$bUkjG7t+7(&{Cu2yczc7) z$~eKTRU<0g3$wBkQs;)Rk(|kv&8aE{4+TnGMLHY3aRHsbl~M}x@7^uEMQx1u4v1?uLDBV4XVJMK>HqtuM7XgQp6r}|I8 z(At0`D=zMe-13ur5+c8yad1Hv)^IjCjB^v3dD#$KE3V*5D49{s!N2?%XFR<7epHcGX6`{O+3yP|j-`YL^C%KS zxn|zmiOE7iGT_$va+55EeR0;|63bsQ7W5Q&e;0o$6^HP@Y~hD=cH8A=?8TI21CrSwP&L&(5S znyHmTQS{Dsp{C2H^$r~ACstMGqXw!n4~g8$zUy7Y@6R6DXG`J-IUyN^ zhGEP06NdcRXDznMN+musjZ81UR1;MajVKJ@zm6%&TTUC}1_fs)l~alQxK%R@=FXDV ze`LaqwU#ynh+pg`S)ljqm1o^#6Y(-jGf`F=d}+f7uzLNi*97C!;3J`x1%0 zX`H%yLsPo(0(GL~u~e{8+M5>g$*+$Y8)*^ushPSq;)}-x9Ap29DeF?gM>9n$Pi^C^ zZyTvuB_2p|wWq4UgoxYDfl!hC_QF}4KDk)Tmees)hy!Dz?*t@+CS@@Wy`%CK$JtkT^@tCVG z);TQfZ&(rF|2X=}xF+BCZ463Ex+J8#JEcn)-60(#q!}?9q`NyOE#T--0qGo_Uurby z2I6q=d-i``-0$}0{_MKX>pYM12p9IhFSK=W6}`*+mwqaxxYO+*Tf*h6eGBq$76oVV z{)hFm3#`3N#&vUxNrd-`oF#C;p6Ob}tFC_0b3_z$mE#qu-t~X1tuhw#eMEhmmj}Q2 zG+eHE_vrb#Ny4%(jA!|vz!nVPv;T&laCjARbKF)2K|>MLMS=X%W=Qf$%d*Sj#5^(H zB;|8bE8b8;+4?Kv`v08tXdvbE7X(}L+Z&>4Zq_mKs*29?8J<6rgk?*JM2jjz^L3lg zL%k~+L5j1X)CGsSn7A+j^mpuJQrgZQOMJH0?E=VRlmHz$MaPdTF1I{^#e~JavLvKn~t`e#$V4%Hg<2YsF${l{I+%O0W2iPN^W?|NQK;kLT-}NvSEQh7cb1Y#Dl)S(p z^fM{VD8THT?WR@Cs}0{zzy2HlKm)_JupMlU**FbASemDB|9j7+?&ddAVn9J5H-CH~ z4}70touH@SlOXl=QBR7qv9QL$ICi(vbx9EQokSWx@+Vj`bIt9piQ~zGvb*%|K0|V7 z#=|Fr^lbPvbk9ZfO3sdH;jcdu<88Qf`Y>0~Bt$y?S?x^h#UEOpNCxETP~bd9E-b-w z`J%y24Ko65rkRB7e9iZ+2!* z2My>oFw`Wl#3=1HyoI!IYg*^er*B#N&B*UC@ZHuX4?6;ugz zox2IfR~#lhYA@-AXtSQb(MYwn+8d}=@@#MZ^n&Ml!p!Seg+4UqeDgr65W%wyNfVjy z|5Dp=^}?cmNnD;0j-UwfYGn!LM7nvPq%yn$eKtQ9FygmdHr~b zkSs#?!|iy^=qd_)ss}o=H`x_(p4$gnibzJk43IX^n9RZxa|oW;do2bM&TWp8sTLnJ zB$8m2yBXDw3SI3zSDe^!oz5qluLZoa@VF1th}1Ev{W;>f;30DQcS${D=})_tsZg4*={c6u&HNNt<+Wp&xTH)+gSt9Kv@ zkN9o+hoNJljs)PTZ`tP6(TAS5*58ZtA#B#)-y7iyvFGXMtv?*1^u*FQulE6CKyc2k zWqJImJxZHp!;-)7y%zU)Ynf}_n_RW9N1Dd#@{@6)G1GkUsk3DmWuW<0KE>VdF&hKe zx4SU|eA(wSL6uK5#PB@b3J0Y_6>F6_@CPWmXNkYfhvomWXOeU3P7!nuys(ub^+R-~ zKlG2!Mth?IhrMIvP4G_62Cly9$yXIlgknx0K;gpIJ%|gwp($B_2dyrjz77}tG30?% zsA@fzG?O$V@&^SRZSV9O!@kj7;(9*lY(%)?d=%3j z12GS1QLd=QeRJ$8^I=B2!@|6WA#yL9&KnpL-gN9Vc=-9;z5tMMV4glJN*oK`a&^Y1 zCDU6*xwOf3#}Vbs)M1DS70B#tkO%iLW;hTKShABi$0BmY#4*}Pu&!v(r8`AzEEcQh zEp2WxDYNT0(J;dN~F|kGl0FHpL7( ze{$yUOX<>Nl(EX|hP_E`j(+d4>)0|>1)u&(I@k4avtNE-Y4*%itqz;_clZ~igsB&ssmQkpa6E@- z3v^ThWjG6+Pr1w(BF5EalFY ztHco06x?be?1%LJROQnzm&D$Z9~<1X>*2*wRM*g({iIe^O>!Mm9E=-YfeIZpp9hjZ zs5@cRT7z(0o*d*vt{%kZ!j&Hs_|Z#9>vC@!e=E}MM?1s3oC{r6RZKtQ*3P|7hVw?P z8q_@xc8i^4RDseZ3#KdOx z6!;Xlxifnl`T$l%yv#N{vFyu;G{~;GH(?@Y= zPf2+Pmi~qNsj9JTyZ)_NKRqK#QI#IK!}$tij$--$uqw<9+!!tWQJ^EdH<(2GNBX>$ zX8nfhha5q2)@S>fP4n|qF%Pui(8{wui89yeb4yQ&Q%mNPL*-?;+`rC;FJ~n4uUJS2 z$2Z4YFvtO8U_TU?Apz{p@b^2gTjDUy=T-?gn$db0b|QkrEe!Axoe%tMclO%c?)?}< zlRTL$G!ysz9Cps@f9-EpqRO}MB~DSx&Bm^v^J9r0nq9z>Mks zM>9j1r!yUY-eigaY$JBtobGats`khD_yoo71`>o2%&6Ylx+jxBh12%nmiKD79GG7dz`i=Jeb@97}MOWM2xY8oZlKC9K$w}gzW zb@aw31rRLfzw{|jX&R{jaKEVxP1sdJJO&)|2^VewUrgMAGcY)WUEz~Ix(qR1a909g zUw^U#dH6^UCdAF(@f*GGe>OT=%q+K(84G*SfpYjU8E~P)`|l$A_|9rl$t*B{u$?dR z2J7~H@sIg6j{FHN zf%RH-YOPAF5pG|Etu<*Fql$^w0}X!Fi_olnlJOfBD^k}N&e~=u^vM^uVVWsdUz5wJ zM@=dU*P$Dc*tJiVFfytX{dU-o0V6h}9#dB)H_|<}&7jIniGKFo9Gr@vA%~^(q6i3< zJdLIE0o`D6lU+HparCHC`*2o$bSh02@A}r1c-U5jIM`Yt{=^Ns^A=OZ(OZgz1Ksd4 z8%CXf7c?$rfjsUL>Mi4Vx3kKycZiH4x%SU)64di>i!4uQ4(Eec{A@p|X4gLfVzW;n z!osaAAe1yK*!0g%u;H?zFy{NjbcPtT7g$j2fnuBo3}BqDTi72-8r}Su+3P&8Mfhoa z7D{my>OK~O3+m2_LoN2yoK|Jf$?-#7w6UzvP@y`B=~_;_PYzqcIaEHrN+_~F z_OhD+hahj@*cY}ae)JT^Q~21*Y6q_b(3dQFSNP4Qrz1UWi#Xs)0yb;<5Y@jttOR^A zTM8Mg8zViAAY+(k;j#$LTFv`4&PP10ZAkg()l|9kDyE>(DvDhzVs1dmuMFDPf44xv zGneJINXj~?u^+(%FK1+4Pz+cV=noXsyvZ;3AItP*=moFwYUIR#Z)1@ah<*UF;Fz)f zxC~d*LT>W-%mrCr(5NdYE&qaEe74kkD|3qIwbz7T)VxRJob!|UF8vMPQve7&>wO(Q zOyI8I)y_T3(TOqDsrw*90kR!Um|>vu;X>6Q zTxW0Y_$6nk@f%TAGg&=aUmul)npnt`jwu?GwVx)jhuuz$F=bND+$-{gDSXiPW&G9g zz^XUv@!0d|NGTrP1#Uy0y(Z4;VLZEv-J>%;N2;;m6Luz(0rY>%Z&wb|0!?7IVW3?q zQTzr+tYpj9(E(>&>bnyR#9$|~i!wq&5HN!!S}PSKVSI07TH^sH)dheYv@f@_{> z5HlNGm1B-s=@yLdKZH+i_*JmO{cjM^EKFV*FW!99L#V@9)ETpUw5rQqlt~9Zh&IP5ZL}MnlSwezP#Eyk*dVu+3?7R|xDvdOi#_ zQk!Ed_M{!^Rne^IFNhkcQQ*_Ug#0MQqETJ>QW~nqRAiKk=$HKYg zy?Tq+B6^9Ym*&SjpR@+<+q$#D(;9#UsRc6Xaqx|!c!dsj3m0QO4;i!N=g=(~$rHsR z&XPzD`sr?4w`I>jNBCQRHm?ut!YXWxg~DI6c}zZKG9F=N{_v$@x@``? z3wAI+4|UDI?VlwLsAy6PWS_3h7W4CCUll+86_eN+EQtEnPo#|L6vRBTMgqkCMG8z3 z9nX_3Bo?3VRHfCP5`=mi2maNSXtk+%nA@TI$77fe3N||nsX!kKKu8h!DRo~rBVa@Z zw!7vCk~8#t$0Ws$kXA)rXs-^uc30A^F*|j8cJ{s>SO?OU)WN z)^zS2Y<$w~w_^gZ~t z;qL=@XKCsBAM2z=q9&dZ2fg>5f2|afm>nq`j@jr+p_)-^la}KJhl8-YatW~Og3k*z zL0K?3eysM^8~5;thL^X2K7d6W<%(iB8b*!l0*o+mB*So`f#Tc;p!=fE#|B4dpJ#4I zx#}5g*}89qqwrWAG+q@Sy^V8}Q-#`pXHaZZBZp(8T;gC)H@e{CihQ}6srlPdv$1{C z-l3i{GRWYeWMFbTIhY>Rs8y&%_aj{Dj_kNkG0Or4H$)>a ze+ar(CbuXSEEcnLutECH!^HK!EFO{8l|A2~;HG)hoR8FLsCwSMMbSb|cz_y~?NJib82n6D!+<%2=w_xK z?9qqrLV(+kZ#Yodf8?2_%Rh)Rs56LQc*={v5Ak_0cbQp|*3Mq((or^*d?63yQ)gD^Uc~wvmYWEJaPXkK6OOMd7V9(A;Hq z%9Yn-Q#7$%*jlE4blJ(T2hmp>}SBx%M}lv!^3hex)_*{@7q>opHZh6WS4;F2!! zea+?UOK9zKW5OdAetr?E0;O0BdV%hTiQy~R={q?l`_75%c{p!s2wR(41mCbN^)eoipsq=V2p^?tF znFUnu*Q_wsQr}Vk2VU-@KyFA78I!n2-?pSnnA=)>OAf2f>_N`5!%TC(Y0(NAg83D- z^P5u)rSrrBO4gv!{l!jO8ao&}jl>#`{HNA3E8pY0xY->n^~EjV;4pR0Y=s+Hfj)_Z z{{QWh9Xb&)!nrcgm*LjkAuj1UBZXo6_GYiQ_lF|W8qAh9={%MA8xZ=*;E2W62*8i)ppS|)n z>j95{yL+fl{_VTfP2y;Khz8AHqObUjBin@I`CO*oo7g(C{IWncJ6FfI3Bax1Hg>O> zPFY!>VM9HF;elc}mt$(C>ANLTgV}Hy`@JSP(sXIE;0?Uc!xkS#aR-{UyywEFdYV+y zLcgh9QzK6#&`n|wO!;y5Nj$NLSiIWi`U zG?hse1NTaT>c^*T{ReW47OU61EPq&i7DMUs`g;AYQdwqX@BC3wFk}M*lm%Sz&ig4; z)ShSUsMt4rEw3PmS2Lo%heo;Z7Li~JuDlQK355N2iLqd?$>d2d8qYI{7xpc@e z%F7j*AMZ-tprZx5pSXP1LSp$rs2m6rpaY&clu?~)HQ#Z?Xw9~4*JB|6yz1cg= zI^PKJf*8N-Ex&+~v8&6QQMyY6$k0`Z|fuCXnCpC+eD#p*-P( zKk>tE8aC+wjNa$YOJmYD6r-%;hd(oX*t<|IXI<#=CK-km+iop{Y+5XCYor|A+s>Xl z9_mn_G%+<uXUt0G7TlE$NfS)(Jbk_X#U5%F}{O9V=H|KRk7Mg#r z-N8civ=l?Uaq|2#H7H$}+UhlWkR>jI=u6$Ps91C@)?4O`<9bW$9+fz|F!R#yMUGq{ zlZ;3Ata#33f?&Pz<+tY6iTuCSbQ?)L)2>H-dV)BAYxw?atnsZ0UJsm%dgZ1q+yAC= zBDGUEF~v_i@B`p|t6Cdds_r+d4tZ2jC1>$4U-(81^P%up5OaPWFCS|$>Akb9TstWj z5@-DTk0|mKW?d zF=4B^oe(?q81!FtJRc|A{*Hwn8U2$_f}27ZHo+8jw>KqIUefYpse^JpYBEMV?zYH1 zNEV0}ahmo(v!Z&LsT3(ZndYrk2fYOdD?%my!p$PmoY_Dj!Yn%}E!3YyBfi8VTU+UGiSjSgUahbh{-2R1_48 z{nKFcbgHeZ{zdl6{uO6t7_IkU5>#HGW zGXv)HcnaQJ%rQ(Y708$e?;LpKw4DS<)>N&h_^MW7QF7zW1)%oLi&_s-pnmntHz9gD z7zdlwr;iYF#tbQpq70`KW!7ko*OF0pPN(c3!cU@XnL84o(b4piaN))8>|k1F(|r=5 zY+$62@7F#8$hjvps&b$HA5%EbnwXV*C@ZV_7aQisVo&O~)0YpgYE%oZVRV}dDf=ez^9Qt(~092D``%qs6GC)2ociORMT3_hTS zmR2I=Jkdv+YEMP7X%g25G&lT_?gTiO1VS`Bt$LF~GT5EOoLQ^p1kE-OnYkiA z4+V41=yW~(u-aP=?xqzLI-ly-X$43kn*0m9vrt0lO>qbyA( zkzeDQh)dG?90<7qg!s0#q)C}T25s zMPew~g_5#$oYI=aXPo!*uX>*D%L=;VE8Y8FV^*vqXFu2WsEFk|&UJmY1R&v!4vD5^ zvUfASCf|&Pc4?JMo(9;h9zn*q^rn4Yg||#?ueyha492X`#HN&blN2ufv>P!^yiI-2XIvIZX5WX!C6rN^o*>xcu(3Segj68$on%K=lCi zp!{R!2-pYd-2(SA{ey{Q8wmUN@7`UY?agZ5V;%z*(PYhSWz-M~zoY3)06as%? zCLAXi%-2B=nYs&|`#O{u+CysUt8lPgM+Nbh|0e9^#Zc{`n^;{*SM1+~AIz zh3t=wXIlnB`2bV*Z;#7jwiwIVeHe?h*Q{KTULH9r$g0tr9U33|x`6sFcd8>IyQYC- zP}ZKfGLygGYFapxQW1X#v)F$lmGpddH~M%ZkXt-NFyKP`t8=-6I)A;e&byI}=wBCE z{B+#jH_1l#)hT4IF@*l0$-<`V5fVtO-*(JC{c~h?h;tXaK6sgzo>Vvx49%* z4lU-_e!xZ?*waaW2^zu7jIFe= zNf{$>ai0jbad&&So+1A7Ld#w%RV*#{TTcai8&T?T2H<|yYB@nQLNg>5RmE8E{DXQE+KJN%V%ot3X9T5 zTaS9W>TsQQzbmn}In6o;EpLdQKM)Tux$$jNWY}e-AV`FS@2sJ27P7VHb|9nFw8{LI z8ddb};xOJ1mm=TLUcduSObXQTMMoYQCSnGFrH1~n81I{?jVD^FA-jwID?puP|8@K` z3dVtrw3MeVV|0t%17Y-sT#!|RD{-&DC&Nj>Z0Acq!NP}$tDM_H zUw5F&UpO}kzFyoO9V7!V^t-}*P~(`2mVkU=3F4eDXmD@aiYCr#>8%Y;`lCD%%2%`3 z3iA27I~BqPhsA36Nw4*u{gZ@NWy{e@-wICb&CO5tEAngax+6520*}MG1VIoXh1T+u z7F^TB?}>Ve@?$i~o;Q?J6eV)b#zO}y1F12w_KHGKk@6qG*g zD*Xw8FfRv;{|_sO4Kp*n(dAum5PzXTbIfGS!A9RND#qIM{2k342U~!|9ER_S9%ssv zyFX6zJ7DkWfDWbw(!1_Bb>%+zHHELFhi6*_!Ad4&{*GJiJPdMqr+k$atn6>k6Z-{lR`V3T{S3qWX>+zkbq#i z;x^CXGEm--vL~NQ1;e+gAlLh=QDZw9j8k{v-nE%+SD_a+smqqM_rdHq|A)0kj|y)yB!N%Ht8%g4u86rgQ~ z7sR+^Py^7{=x)SLVqwl~eh?9=;I;~jX#$v;KWZHndF zD;GFhhE~_|TgH~e(UH`s1+3ta7AcG}#tP^*FzMRJWEm3m_>fEKQ2SWyqE4gpT9oWy zxE=EL?`y=cw9U@Nrua}vo2>^^rtJsxaF-XSR?k_jt(w13I$oX9K=aCj5Y{7igxLM1 zQ}Px-%vf72YgCsCvNbL^@@axrvv!(7;`zf~v3rv)%JHZSleH|6QnLx98!oW*mi zU|-YgU*V5(SM^wiFl!x%*zj#)PEhPYhMAWwy_b&eGKF7Attk-$;EL$e2Z?%`aS0Yj zQs1En^Fu14%ioWb;qj<(a+~o8FO)q7#4EWHv_(wEK8V0M?etXBETiA7Ww%$oG`45! z)N0}dk}wPy+FDDOFU=DAs*dLT;t#62%6XA2XVxo@arF7dyXw6uC#zZ6?eo8x<1(h4sj}cVMkuH%8|kcj$!`zFhx_GoieTi0a~a zNUd=!53y2LZSwM22_LPTxdB{4013#JZeRO0EHx|}Ug3o@Kz$Kc4O-a#Yh;54}j|n_+Kl8&errt52R(rL^@k<#q5=v6*5_=nUMK* znRa=7FZ&da?(8+Hd`D?z|)&)t`4WD(i zL249U=VOR_Yu@$Cg6u@2Pj}I`d0L<*}mbbm? zE{-K0n6@Ci#VTDm6}=;snz#f)Rl-xIpIl%e9-(TOgt*zsm}$!pQ&h{52*vH{yY$7j zg#R2_doyOJhiz8G-Mw9wDR+U>N#$B^R0q;5&aLc~hAdLph>;km-CnqtYGh#d$rWK* z5e5PIOd)jqD`$Nu@XxB!X$AJ;yz5!qo{5XUXjOyCi<;8CFTVASM_fw!ek*PpnPe*9 znr07s^W)%)Jt;4{l%L~oRq6RMe+taHeY(YHvH%?L6%nx{KMwallcbi($Z@?R${lLy z)v8JlqVR~G%G+vve`hx%8#$99xnTop#J{6>WMXI;Tr0R**Wvr3y!gW^=B~|p*rd+O+n^-TXp3gy9ex90JA`{b~_g#rUa+$4)}3gkCn&Ei*jtUmYxS{bVjI9J+c z<6;k(PW`-N9FW1usDo)ONWKrFSWTj|!{2E;m(B))d4Zh_KpioV-?-*P>J1rpmFw+BgIs#^#i1DTTHR`?x#EW-Algkv-%SU?iT!r~ zlfhY_j>E|o0)>ViB#!vy-EvxQ$bYKY z{q_Rjphwyl24+#ZsOTz`-Fw7QpF}|oqy*{;b&;f_8gRZ7;O9^ItWbJk7Z=bPQM_F4 z|B|18@2BKZ2f30mZ>dHacX4h{Q`3Tboa!gp0I)qn5+f~L%%89v8SAMV>iQ6&jlN49 za=oPx`_vbt{pK&3)J@DsODlr(!7@hUT^34RJ!8c|ge9enDH~PpY!nykfvv<;?WDY9 zM-1r}Ag;UmziGO|q|k5?K4%g*Nm%>pDVsWoDJSt@AE2!Mf^y0&nO;^J1D;3bvtV*o zG>UI6@LfB*9!=_P?S^kmb!nv2Xyk%X>vHT?+96rHXY>i!_g zLFi0_Guxh-0jp;kJ7t%Aqlk2;b>B_rw9_?rJFF^px?3ipt#%y%@8Q#H@DbyBHBZza zqKuCf?o1@4-Vfv`YS5@Vr~1?Wog(GsW?nlntuEJ5takEIPju#|o%|I%Bj741g>2g04_cKr zBvncZ^UYeuckBti`Xy*pJ;@g?{ql1X$zc8|)dK(?nG--V!|;kXQgD0EM%NjxOYD#k z*q{DohjXkyo!>TZzGFCR=%by?lP*ej#z^1#QPa}K7@^Rth;#BYR<7G1%3)H@45){zU+T3qCG*KLKX%7 z6|%-QgLO&9u&SnB6&fy}cPEc6{I=D%z4Ob@9hM%`jy~~+A7A~M&(ybkZ;w@R$%09& zLD(bhHx&$uQUe|30Hk6GA3tHc&FSW1uCiIKAjJCh?>~?Eobu!w<%=?9xG{i6oWXtg zW8L@f4RH^8lD{FRcId;_76_<7AMun1rw?&jLXXwhxIfq+v>p1tuJY%=?(}1LmeeU+ zd3uv~-8fgg-rx(sow9d{@~qMCI{wg~XpN22C)I=xR4A;d{=^uE>h-PN>H;+pOr=+* z7dne#w|y`SZJd@P|Lv4CYm5h@VY>Kp=ub;4K*$Zz?Ngi>H}y+?CKk#6G{U1NU6=n` ze^Y|Qsj3EH($-87rX?IzpJ}NMjjT5E>4)EmQ+iXW7!Im&=XWD#$HckPtB8xptt>QS zGhS;!1j)0~YZ5fm$h#)etfpkxK5F?MJ=!XA?4jlm7(OJ-d#f1wn#w!@{Z5J;kbE$E zjorp2;9X-shRY$GGc+y|67|xrTT!7YgPO$8{iG~tZI=5O6}TE}u^8SNNNBV@_1*w~ z!Qhq5B}q6F@yrA|0 zN+qmH-A>J4yo1L`9$H2lCAl~GQUr_qFiABg=M50QDPH0n%v`_+3_L2te?GUh`LfK? zXQit|cc|MRhW>)hgP#z);cnBcT)r^rJXjZsVF3BRyg6aEP^q9QMQ?v zLxxk8yP9U`9G<)1LI>^~ACE_!@fsMq&i$`R&@CxUDE$gd+K$`b|6wIWYOW5GtPKhR zmfFyxXxdY|a;BW$|HG<@WV|V#uLFB4=KpT1Lq|eUYfseu|HGn(f4e7O!QcG)HQvK$&2rvKd>EyXZ7KNgvoTI; zxibbJXXF!=N7NvwO5W^e;kgig)_um((Q^^cN2SGq??)B$J_3_99=}w4 zLMMOy+}80sr(qoQZvgqv1g)ivt>bGR{2u!6kv4-S+pVWpxUk@4?WE!;u@D^_#wXF)>2V>>y>E$$@d>&Et5&Dq#8tZ`p06F*!PT=+owb|pnNzGo$qM9W zm+pMw8e5F4FH}CVZ)J?i_$ZTnLb)UgkYj1d`W@XD6S*z>i3^-GqjIJyYHG6B>Sk*a zRD_=8#ziGw7Tu61}sblRzm+_`dk zGL*70q9?t|`Wzw@>T`uLM2tRjRg)H3xy_%(Y-sdji2wVSs+PMN7x*pS@^?y|yo?h*`sbl!OJ3%zl`VfstpV4v2 z&p{#HFjBN%`iXZDyOo}-vvJ5lYrQ$8g4C;Sn})q{DigN!WhOv40~vNhJ{HqB6Fd#5 zgYIAS5-&5Lx;G!zvs6f%O66YCO4J{2lf54Mqw4&fNDs79R`q~Eid}-lIy1<^R5{BH z5koB}HVzEb+D1RsaSjgR;_S$k*5u?*n552!+*SmjM0&rkZ(JRJXKR{VCd*>UxI)7O zFMEFCxMye{5h!e5O}JN~A{3Xw<5wBzLlX3%LeY_p$h^gBbF6iq1%Hk2Z&}9lEi){T z&ouvMoWY@EhPao;lYA5YVAF)UmBpJW}N3YKZVYeU|^cr%$ksh zpJvOoJkUzXm@sdn^siBu#+7q|T0YHD{`Z)6B4$3F*#BhA2z8N!(^4x}0{o1-=l(v; zH8Q+){T~hEh~h)@q!_CHjy7gncTSKOds1XdLVU_!W39J|y$|-Iap}JEx`n3W=JE}b z_o$1#$*{}EjArtq>ObUVcKEL}ZmzGAh;7nmu0t0bzpIb4fm&evU$-2oI>TCQyP86D zHr(&`Ey?KwF5bM$CVAV=${ae{9xJD0&F2`!CsXmJ@A-FUhFy$pWdtzz;xsfm%z|UE zN9!b-WVG^6!+M41i{m8=@0TBG-v|k8f0jCO9MF-gF1kN?DDeVJyWAV-5YT#QZ*Jiw zIcJj1=rBG>!{oYOB0$Iqs-^E|KQ>GC8aRIr<2QIcpgRc!78(Bhcxe#+ca6^D$r9}6 zq3@y4a!Kc8dhL~46=|wpDRjvt3JwJ&5CP{OE@Q}n{HgH0WI>u8vk%*0Z)ShsB@GP} zB#hPXAybFm4|gHTx+)i}JS-y%Qvhr{v1_So@%XHlu<(6w^)$Cgi_*4`Jh5}(m1oq( z-OVZL_JZq5tf7a+i@k`FLf&|-p5U(NbLz{}ntl17rjCNqjw4oe24|~OH5aD*94SqH zE#LkB^%e%TC9ru-`-RLm(*MD)6EW+WiHnigvsBNgw=pHJm$?>Xf#4{}I-2CEsE@Q6 z%MY15c){At_&~;ks(Q3mCiaId;@*_p-cyZ^S91Jf)~rXLL`4w{UEva*V~BLk^7^z`m6hI96WPyiqswq$ThH^j zaZ9{+8goFOSa-g{+Y$W{Uhfsp$6uoNoZH z_dfh$H*=sg&i9Ubl?_hs{WXjPPW5Tz%iY0;7mHhREyFFxmV@qtNX~_{NE%aqWm8}+ z&rNS!E@im>Afr?rW&G`u(R=bQj6>`Ez3Th#pTwtXvAQoYn`Mm(xsww?Hut@P&F&ni z;tXf|m##rfI&5=g!kE`vmt=Q`tf)IK)^98)Mr&Ww6vk&|j=GH8x(J`FbXES9GzyXp+a!p^NJN-V!=tNaGKBypv7=@F^+ekJei9qL)7GuDjINT@ zXrgH6)+PE5t_z%Ev>rgzwPvAWTRcQl@NcbtrHE|`e!lSaCCAb{Fuuu#z@R;HU&=%K z(@%_H0N&g17TE2l-{4ydi$9(&dZ&HUrid0uvX}>B$?g!#99TgG)_W)~{qx>~7 z>$@w#Kre+8z2}n9{%+?U6<^s)L(9zREnNQl!fvyh-Wz?Y(EhztE%^N}SGF~H?++xk12VMHt`XHD%y{j-&bL^i=o@bnO9~(n%FJv{x zQf7TVlBceYH8P6YDxqnd4O96@??`v&DKe-|iU8=rCeXzU*lFboz3&dWC?>Ql6*(*3 zv~2dmKBsi6hgxDeyIu~Jg4G)xw^Pr;k1y8)PW~*os<2y z`FSSjV&YF|MwusckK-(=WxVk10P?A{D?P~{NOOSBjC#hAEB}js;mg;~jQ5>M#aBnv zexT^}#@EJ(XtSz=up=n*J3K$}aP1Jty%8G%`ZRo^bI~@#Bt#Di_~*}AaCuc8J?Ak3O}##-S=-h5ZiPfY8jS1+R){ zyBMalevG>~J*urP&-4ZFp!v`0Pmu8pPuOoVu56@(9LLCA=$htYcz4s*LDKSRbQfmhHZzRi#E9D?1#gGhBzjvDrng@eB6Bz|vDudE2nYmCvv6X`*nWDyLjO=YDE=kczeTFQ?f+4Z2P< z>MnWSo_eA4DmS$}^ChVZNX^Gy(WwqhO|y_1hLIaZi`$U>QyCci+NS{`H8mH^331k< z5Tdk<3ZCX9PrW7?u8CAgQjbO@9!E-@SrS(P!(6>6IwGu$5nGB65v3Ey49Oi0Je6R1 z5stOBtg{xLpR8TQwuD;x(yi!_>qx@dpMx4c8N0_H#t!C3qBv}p@3CRwUFE(NDt#-d z_dzn@!P#wfY{?7O#N1+jj6B#RV=9RU7slCtG&Bo9zV{o|KIpNoa}68QaXY8S6YW|+B1ST>OL=*plv!4}_8lv%j z8zZhrJbqBcDgN;_t<*6i>&fu$id<1G-+XZ5xy&DE(-iEyco1GCdW`^xPH62lu>Cy( zJo!n!f0RcFpD;DP%h@@jnrw1k48_n~!<;UJ{(`mr&=1MK5Z^u)zGvv~rTF6{b;n4N zu}TQ`%s_1ZArO=U`L?+Nfdtc|?aLgd`sK`QkuUGvdi})+}>+Z*={M_4mfUv21Tz0Kf9BqR}cD0%*R;UDy?_+B)=ZT zTT(wXxzQa$r>59gf4&W(S7+{lL12(q7XcXr4cmEH?nA2Hga9+*596FPgTt2lTi`O{ za7XkwBJq^LZf=v|mjv~$!OEsC8y5Lm*8qD?hO!&5yl7pf(B-lx_WuDkLCL=LVeAdMsH_&p(Wj=80ymnyRDqcoEUiy066Nv+ebLYG0ZC^#uG%at)wp!PgbfIUc z{dZ8a)?m99!pl*(Qg();)hsuqGw8qk;MbUq$CdomS;z$mkF-9CEYZuR#g`r2M+vv)@BHP?k!Nf9k8i73dh$oC*de-}VM8SFl8(b+ zu@ui|YI<`9dPoII@QJn*9Z1a)1~TC-x=lck9bYM&2O7A6VOBDuwN_FpRF0$NfcZDd zQL`>o?77srjnMF9+3CGO?@W?mA=i<1SzsUPtV6!cqo66)xf`Z8w-9z?Zj&^ThYKL1 z!!X=!`#6~|ibWDOC zoMu~bTN9USaU#dHJ!KC@0KZ8vRz1_q~*j98lKrnnYJWf zCP%O8@1c2GJFPH9ZGE6x%OrNZJyOG}6hb#U^v7y?blPOf%O@Kfi5V6}Z-nvjKdUN~ zNfv;7w^s5;o%HWIX_rvlSc!bwq`@7-BgMvKd6t~xQZ`aL;e~`|Ks`guElgZ@paXBm zHTk3sw2(nyo@}~HOP4x)EoCHtCF4rGS)Hm42h*OfhtE2k-}8%Fhmh7q=cjqb&e~gg z{{Yge_8YB17q9#N)sAG2(7w$$@07s!8=vTRgR}|k!;h$#kIv=#A15}Qq_5_zTDh8E zs!eMot1S;Nt;Wd-A9IZQ`FnQ_g`L&x@+45&#PZ7|j1^QOl1me?8R)N|lTVm4AR zJau?lM~pKQAQWfree-dQfE+i}`hV^P#E?d*132_z>^A#39n>_a?m=0QI=CEOoifpo zRWbyJq)Sb?FQC17e8AGD{(BqU?A zFQ;}vq3hc3koAjAb3)W4u)eZ!Ev3XHg^+clP|$|UF;aq-}&WgM&cyo-g~l1l!&S8Qn~p&uiQ2I)g+vR|(RoWf^ z3Rf1^e9NVNUFo*^{<8#knw`TR(7F?~7@B-D$~y1|@6ONJuEd68#<6{(N{Oz@pHUGtYAkH@PgVQ)54&Byv{NaNYb*F0E&} z(>V{(sL_A}IOxQR(0CjVeJ!n=Hpy!X&l&ion!g70uPR_0?19ZS(JgPa8~f??E4XZA z0i%Z8fMhDY0uHopnG*92yWC48ki_y^sQBbwwIY;1EVCJuY%(5~wfc?Esruwae0v_&I$aG#`wAC9^BYt(gOPzB1vi)uX^^Z_H z$sjxOVlyWMeHA1?8uNO$JNI3m@C%xST#ga)3-x|g^e-B(xk9SE!kUA)4?PLKfH`na1T?JH=`)@ z=RTC9?7wUR!Z%;0jYhzWtszbAfv9^!v!~1*@V-#WID)Kz(~!p`wx)4~TwA5`QSoO&uj_$Gt zxo!;VodSWs#Y~k!WoI~;EyF_;QS<%y-K0BF2;ROKM2|u(m66Hi_d2$%W^H6xBD$Js zh*q<2?&0jxjm0U~#A1GHO>5(Yg&C1X#cl9=C*;58CzNzcjeJ{vS!w$9tg;J@ZtZO16U0ZLq+EXc^qyzchTH0hpV{E+i!k+sjupD_ObjlVB{G?rUUBrM$ZT`JF3RF-6k zqclZ<*_0aXgoti68<LU*{#;eLuN|vu&Q(n1;RDuim zrfYlYZGvmiOIG!+qWD9B*zo{U2$<#Yro9ehizozoM-OTB7G>)XgG_RC$I z*ESHBi31w~hVIa7VaM@fUS)&H`cLL|m*yWg>Cx&pC(p9jXu7_dgfrM(+W=wI2;JkR z>r4S@=8a2F^6shSyM03TT`$ar89c+F-6$}L)KzDRznEk)V1_(GFqakdT)L=A#?%=N z&X9cB=UpSsGHKpk@{;~v&3fOLzH{>Qyl*bxwcEAlu*@X&~lE{z|YI|2tUnm^7SX!Gv5Z=qRgwz^Hd?c5UF`It=-&8J@3 zb5bI96#=AL@6;R-rP%wA>l6tCnDFn(NELFT{7{Y{|JHD4@f#amU-^%&R$x@vq)5Z|wC zT1!nDZ!g@ZZjDe5?T;G(rvzD2|(%m8XNUI{tjj{EK;&|uXBmiu!~1R}IU(4%j1J(XO;6)3nJoYh7~RP|~gS zTH3gEw0U-DWd8sudyLr2gTvq(fH}E1>m)>gt1$MZMLen|80msZ10)_lTz$)tIjAjK?htyP0da*a>}gZ77fjp^5O zYr3TIYnRv0CCV^cxnyZ2HvoJ**~uoS-zB8Y*JHO|N_6z6wwutnG1i@a*{@E! z;TiTjaz8gdSoXW-%cJt9p|4$7Ug>gucS-Xuj5UoH>$FK!vT_!@RFG&z0ouK2Fvn3z zv@b9St>#;)Aw-d`EgHPzl|iT@wGQ~7s>gQD4ox`EjF4#lI)wA@vc4NdeQhE8Q8?-_ zg8t{rSC%?`N?$m63Mc886Mv*U={JG{Yt9h1KHU9uE*d0em z(k`5=dX2O#St5=90GuxPArqQHGm(i0XQk7~!z5=q-~@4Z(LC9Hv45iZ7xM>7yS@Cr z&>zTtaJq|1^FNy{tyQmdjZ*Olf>IQ0hC(P$U!y*weocNzeno2@MDk~zwC^Qb%`UyB zTi;CAM9KxjMmq%wx40VRyW>ioXhm8OrXQ4Fv4=(w9h&;WZ*w~pK zjF#~tSKgpzwi2Q$Ap6=S<7eL_j=|!S++19_mg0FQkd5S#%Q2^FlY(w__E?k{3{LWJ zcR#WT$;wtfnqdtgGv|9D@fqfJkuEJHWhGfiD!|Z!JJ+^+IP+GI zclmqg?=pFI6&X=j#xm(>n5htn6+<%la(*2&*jQ_AByx%-6nt^5>L1$8W9LL9Y3e$~uphHQggtfo0Ns!+UKDM+`U4 zb_|_VpA1Uw`qK7oYt8l=y~XaK`d&Ho{Yv!lnUiA1Rp`|shciEPYUFsYuHORr_Ol3v zP72U+lb&PpC6<$=PvqO>^HzhUf2GFPa-#^I)%WzuDX6Dx9k1$o z&DNdftuEio_ZE6|zgE^Qq*;Mz9!d#a2vH6Fj>RR;EYCcle7gMx6Ww(i4ZK1ggJ_(>8FFc4{$!61~lr1Kzl0_Wr zbi$6Luf~VRk4(bU;}MCLDUd*S*!bc&;&^3r54r3*7Mtc>J59RtP4DRc042kxYFC;g z=unW>QYes%d#H~<((Gz8={Nl0H=M0CZz6fO^6(Eu{FkT+bm$n>{;767MI+cT&MUVB zVV+=e$OOUjs!fm*?hUCT>`p=<;|HNq#CWg2;PSX^qqF&PD!lH zsGH?aBXJ$|&+L4U{{T59ALWmpzb-ZDbj!PqJM%;Giu%sa zTGD1xR`o7N8>WrAA4t)?v+JeW-UNv1QKXZ^%!?#o(1zGoIGmD^^v`Jzwb)`9i6Ve;xVcNZhLyFBe&sQ50BbVCM3Bx;GD)KpJl*kG6eH3ChC#Nj8 z)qFfIJoQ-R5ksy1$6;0ev*kZ8MGT&0^B$L{%(YH)+(w0mKqyUXl?+kht{`N34eR8! zn<*m{Wk+1n?X|Y8Kbh|>*_o{L z*o?=S>Y=Gj+G+bASE!Kiph)jNk@mKJPFVn+T#<+!Y&~PjACO;~9&(pUI)9fXvar?N z7SC3{BHq}E4FM881vkzE=AZe`ElrKO`BU=sY~j04RvYbJKtnAy_*19Tn`nD4s(>=h zI6^FNXSTMnhtu?A{g*G)ftzm2?93W+G7x1k z$e!ny?Oxl*I0)j8hu^*1-+Zmco)2?nZk#`gDcz)2hy2T?Mp;oAY1uU z%@VWRY11O!YZB72$2*cENh!YPVUim?M%Pz%hWgGVxR08N#=)yy*q-3!UOZ-MPNq>0 z2lG#nb+5~d4L@1(mzXZ^G;6a3*|U*3OBoa)5}WX4BBKkm`&qqtEuL3PaO}~UKe}T| z0&^6`HbYpii#GG8n5{oU*z0z-HnM9I+QSZ|9gzb1HDU`OrsBPDWSV@#Ot_FzW!}cL{{T2?htHa9FXg%JV$^KWB%b0u;zb*?Gk42}Ope(s<@(XM z`rK@0j0zZ>9k<9sayWNHY}gx>+V7n1wYl~CG|*wwCD5;9T`udFsr9>c0FnUvvDUXw zq{AdL&uepMBa+Zh@ik9%@XN7a)nz1Oh57Vy;i1ixfFgb9Pcd0(o^sSJHA_7^SkXMg z6j8?>p{75guBt(#fKsBP8D%bvs?KGWSE({Yp9+9aPnKfpyE8U0N!YtQe$Pr$0&<|3 z>)L;xbtbpBlGeuB1yoyGx&ArJDChnvrOO|+7FpA$zOm8g|o zRq70kY44W}7C*=n!fS{hu#dgy2VrUa1BUwD`S1D*=7+Y|59Xb=ly9du>8DN;{TrmM zJY2tbO3?8e`)AbO&Yv)T}^2&qb z?Dfv|SL$QZQV+w&GPJO_UzSg4{HN0zSuZcBtOC(RDr&vGtDG#mNF8Vu ziu?|Ib2N%^-tQbS!q&1DW{x)HENVJ0hrhNb=_Gs}R|ZB}aZ^$A$%t_aRquZ8(m`!( z%L2bMD+)PY)xej!d{>aXa-csC_mrhF$i`7hYvu1X&!TEDUupBr4CyE#P|~G)P#&4g zFSNVeE>m-FEmaLeF5iAbQI0YjY+Io_*uP1?DgOXGG#|`uG5nq9n>%}ttj1w6+<;a^ zr2yZd_sPGPeBmVP4xe&TITZX?I|eJ^T*iTv2@>2VE+HM_`J?`F5B_n6%gXZ4=PxRW zuJl{eNVG`Q%N$G(Ri$Z@7lh2scW*Bj9jmjBw8)SS&ON?XwZ0Z;x<;*Q>p>v+*+EJO8(Lu@~>&Vj=|di z&NU3fuYbMh^?jcl!_T39b$)$+&Nu15n5OSq(j$*V^PRM1VU=jHUKQVjp?jXkJ!7Wo zb{gG`T85c$w-&OfJe2MafgU3~FSR=>QQ4WiEaH#f<{oP{8Dcdc{IAw@U0cg~rPhnB zS-p;>Wac^TWli}YrDtD)_#agKC(Bi75pp#D@U@#P^yL|9g zzpZKi0GGNt>pIeM)pZzH=o(U=jgM)c!AIkr$Fn}q45RZog~WX^{&Dm2cb%2lGSwa_ zZ4j8~9$wV^+o{E+>2R}>L7rNCD83~Atnjyp<|OB7fhNsE-u91Q~Kf<+H+cj>O$AK_QA%9 zZt-t7d4d_P>~z6z`bBiP1;X16!^}41)cv1qbKFG=tE_&EJ6oBWrbjiWC9hm)f|Mk7 z7dNiT(k;cplYF+((P4!S`j!0{{U0E)Fif!&h0Gk9ZPu#Z%b+e9O|ywn_VQzT-K z9eRK}97j-=Nf{N#)$GX&BnY&l4yA{VSO&_gpuulyw+{oQ?y3Vc7qhW$Xu_%^uS)ph zH}lS5iq_WJ-p(*Wq@e!tcI@1Iaxo^@L;>nHndq8!kS=D_bzAL2R+%F*U0WE>)$Es} zBfm;lIrB1UI_DR;VwZeH)T(~V6Z|q#2AqicgX?WR3$M&?${8ewN{95HmED^_vzY@d z&?3<9`yh^)FZ!j0B)-SpO#tH-J6(Q4OPSh}{< zuDQ3>WDg~Y9YeDA7)sMg6qO2MaDK~lIbnk!^@~kD*HP2Or1M9rSe5uMV%_2gv-lB? z^<$i~ND4@LQ>H|UNm5%2{T?KS!T!HvA*8C`ZAXA79#!F?a0<8CZybzf4&73w){x#S zwUo~s@NGS#R2{wYn&5FMz!g2Q7|7~?t81q@nJ@k;d$1_3zhw5@bU0e(q)^l!vM^3S z?Asllv*rCgt*zv~y9$NJ_rijd_V=cAA1-P3?Pn~Kw3hcvNqt!RC%E^@=U`Vxi5>0n z2j^#8UZ_@Kk0BNAOHI6P~ypMnxO!?YG$pkSEHF>V~@5{r>+GV7EThgp<-aA{1HQ{k} z>9M3`x|2cI#{}wMQ@s|*{{U4DW5~}rh!e-E@F#D-F!E_*kldoc;)J)51yjl%Wb-eU zW4v1%oA+H-KSNEoY0m^QR7+l^eah0fQEjWq9-{`Oq{-=A>GB!kxkyzdg@C6nB7wmj zSHm!Mou3?{qv?=w^&Oj!G-{}xM1D4UZK=4j((d$cJ4N-aGt8E2rnpO%c;$#cB>|X| z11nd9bgx~p2e8$jPn%bo%FbITuAX<+W2G79s{un!r1U)w+0M=x@Lv!Ica_xPo}PRX z6j`Otv*ek4!DXRoeqr-Hz3!`|TIo`GV&oCV7=8zCN=T(BY7XNIe7~pLUF-T|Ye?3* zezg_EZX$XbusjV1Kv;ClojEg~4^qZCFNaaIg=H=q-te-)bzxE}5anbcJ z%N-K`0LxZTUTPOMaeZITUR{Dln&(TixR`o3)(mQ9RXdO?wiW97cbI)mGfvi4-r+Sw zGwJchM5ZXCa-jo_>9P7VUzaT8K$#SG6z$=q#f}_M9J=@X8Sj&IugU)aE@_@>^Y7)Q z#;>Jno=H#9USgU+)~l)BT|g^z*6l?EH9KK6y7jz}$)vPa=GRNP_3XVy<2srZbmh0h zy>n_b8E21=_(v}%IA}q}BreX(nY@>(XxCa6xOE*;$IKs^8cJFDw&vE^r_(1Ay2%B@ zMnMTR1u7|l?poVixQ^!5!t&LxU1GSi(<5ni1L19f>U(ChOWHbI8E+<7*gJ=H+5Lg6 z&vC~auCmz{H7!^2n?uyRm3ih*E%}&vY6rja?!V?aV}jvsU8^K~Y7KZ22HDVjsrgO$ zyXFhadu=Q7{{UB#%37p4mECQXB_sE4L8jh0i`w4M_ErcJk0hr%)G6tm>&xHsgZ}`Q(AwOum^Hme zT+}X+=`nvu2?(KXBd+)9fHsNa2XpBLwe21v9|jc9%=h8b2%QdUQ4#&yw|d^m~sn!o*E+Z5t5~ zxK9OIZ=L60Yhl`22v09CO_AlXd5+)g_~`XUBk7!YhsU|}zvX4W<`0`>^9HHpsAJZ& z&pl{&8vVzVwRlV0E&k^1>|b%}nE@aSDcAhA-dEOqwW4{3)WN0eGNz%U>(=uLEpBY5 z19Sk84HubHh0*-0aqp2NpRhn>wd_g0zCXX{*o{JPDLE+{{UQF-L z_8w-B&cB#?W#^TBXtd}wonrFRCnm>I(%6Q#s}F`bZKVVf4*B$_{&1hqQ2CGYlUVX= zIg23|TispA63WfO1^|V2ZIri-4kEz?$;0U;G5U|#9fGcn z%vSKAF_NgpS?fYodT|~&2))>2j7-lzbFl@LeIjQ607zzE-I3G-+Rl+&fPWNZb zZ~4p33ADe?iw$XDShVjtSS7k%`h2N8Bp#i~8PR(upTN}S#AHB_;|>>Zc6rqHTxEO0 zUm7pCKj$3vU(+9!9((famk)J6lI~N?T7HCX1-jhDG8<{a$VlQ;xN7@nmMy)uF@P1kieuNLa!!%>2d9FVvqF+>C~9dd8wZCgx}&RWgJtL1Bz z^5iz}VQ;5LG4!qH3PO6M^-$jxGb=@oW>X>+9=3TpKMJvf%>7RW{N?iQk)!@iepxn~ z`H^L>er5TV<-EZ>@LPnQ{?=NRk|qM7)a~z_(X0-Msp~e9UPp6rr^!hg1IRQ^PSJRP zF&I2KO2G9Wd(r8$oY0A`Lf=|yes8?|*YY3b9-utEE`g$JwvQZ>UMHt*`a;QQ8uFCl zU4SZc)8F%l-eewC{P4B2xwlyKkIaoR^!+?WGaP2@4#k z8OQR;?d)1F4glxXwt-{al6*5m8@>cHifSt091pg~}rDXJDAXEA@t#fQYh-h3Q`c zG6#1WSw)Bry$iF0{{YTdd0zKX{F=G*J&MOJx#U?FSkvVyE5y|t523ndc9LJ0)?mvm zp~NFEbiYGRF&$5drmdzce(?40$ocf={Ke389ddIAm%QUL=vv|AR2XjER92tmh0mAT zzLjODd4I~jYL9{+Hd{zOu#$iU!nejHj30%8J6AnlStvqhfZv~!=UUiLA09ailuy~@ z{R#4ZtND}pdFJ0g{#5JsCT$Dy>sX6Yw$a|)&ve>is`^W5D*{?6g$VMYNg1ctARVv}y_V>Kppk*rn(+{|k{{UM2!1G4A zZ=rdU&c0UDHQP;h%gd%k#`jEXsAXB9jyCv=OF#$$n^!sZujMQKD_*&=yh~!5JeJ?2 zWL6Ccj^F|wqhh<|xWJf~4#p&WotI^6cw^znZ!52O>F<3Pwf_Lj zO)FeaEeInf_6zMS@=H*p8cIiO2XU?HmiD@Ix>324%zjGOAk_32ZGkI2rM#;nARo#? zo$zCx9FdkRqtlWSjsE~PRBPs5$Jx%*#h}&0CUOKN>79?H9goL$=lrqI?!3oys!2AR zZRD@b{{SMLKhE0ruvI0~e9+M{p=Jh)Grbm_bLm%^Kj%OH04em#Ejm3fLDqc9tling zE#;&zdT~QDDCCAm*wELearwQU)at*w#2^UXbC40Z^RBN&mKr@YPHeh}h!aA+QX{6p z@VAsd=K}u#J$%`7sgq}?XnH=IesuZui|dsM>IS0K6!M`P)b`FV=D+#RAIy35>s#L` zeqZUnS+>6t3ww*__2=Z9SAzclOwT^e%E<1r?4BauFsm$LZ> z{%{w{y04x*(d3Ub{%ylHt>ihP9%@Z4+>2F)QCh`wFT&hwxCc1SzxlQQ067=ti~TJ5 z%g-8zmOQ(zsxs>K5&d4)KU7s?W=c@MP4i_RWVHA=Wt!(16LOK<_j1`8J*&YiXC4et zgzkq^@3*69Uz8v7iP|@ly!ozvTj^2$ZhmWiThDV0-CAl`msZrybS!m;?#Td6EqxWe zILfK7)r;|A+L$j;yYj{Do{G1&66l^_uvz2P^*CFccWKM_eAIL*qbP>57$`{52fpv# z^M9M2$YYT)mGeJ!puD%Eerwrjo^sQFEG@L}KK@wwhT_iiLDTh!jkWfdaNs-rL6{HS z2i$hao~`7lbPaz`ODnrgN6Y%Ij<@;^$bV8PgD&dAq^qk`Q!1XWcPRr=JJ)-n&Dt40 zl4t|b;M$Mo*0ZjDSzV`^rn-;wH$n4Y)4boP*~RruM#2*>75Jm#C5e`Ro$@Jf5+o~p zAZMC43q6zWuAtPdJ@XLiWhh-yaPsO&G);@N`&!j6F11tTXVvZ7MYxaax=)y+KfZ=i zp9_f(Mji4&J$8LCQ6rs|1$zX{5KdH|%7d822HoQ^&w% zxO7?al6XH;b}r7(m{5sLbn729-P`$k#?CEQR$nZ`=;-%XWT0p%#YDro01PR(^B$RN z62|0Xx{QXTYu&rB$JiNp$ckm!XXR&`bvwEBl(Dzarn^ozw@NuP zQ@96e;T*nn4HG53y4xu`sT)@}7`>H@2ojeNbK%(7F@a=~&GgU7Xx?aUwJZ5=ZsT4t zxjd?;s332Vo4+*b6F;O}m8C-iN@n99W9aZlhyV|FH)D%UiUZRZwE0i+6>e0Ee=giy zeP9xoER+VFMM&w9+4XzoW_Ov1@BU{tVBoG8f%iF40By>dhH7=XXvm1;jSdXZP^v|~6^eD0q`NY%t zHTC5G03Q_|VLI0%>7OtFSSK!D-GnCIwWU5fcFbP}JUlhCox*$f?|uva0MOa#-}E_u z^e~^{n7_dP0H!{z{uT72ujndz6ye66uOHu2`Mw&{B|o0?7(D22TKNPPIwVF*L;U7R zir4kyA!G*|HSs_JL#m6ruC*Shp!P{f|<6{LW6}fW%Q5b>{3|S z+DRN@DG@0!I|nV}kW(~KFjm^5YK?)(@b@*-)+4mKx{c-d6%_noA95>EigP@nXw_xg z_rK(fo-l5dgbcB#rE-@p(H3B^9;A`{F~+7k^94;q1C|ctQUw$DtQH4CtH~S=o+kiZ zTg4=9B_F$Grw)R?)ydl+X^`mJwe6MFv)M?(_9v`U0%|McOy(N4k2RAC;Ve^fwAhbq zWdW1k+YGd5zeN84CBHrFbxTp@Z#X=2GLJ}^fFab19gpkDCzrg^k*s#N;gg^aI**=f z_)JPN;sXzOyZ&-s5goske=#o#Jmc!xf0(5;1PzfS_dP3-ST6Xtr8Pq?!O!Z>XSKT< z#{K3KN2q-lv3;UEJ{Epm3+z8K`4$~g57OEjud5=4cmr}tm#BEi=~0~r%3gBRysdJw zT1@jBPwEx6dS%Q=IvZk*G;o;PMD#0N*?|hjR4qg zaYMT9cFNwgrWI^-JM_)J&jPx;8fBbS-3Iv6(BTT;YxBzjq#wT&hgYZv9tA#}3rh*= z4jWx+o>=l`gLUQ~HM320RIitOx`vN+FK2$?0nW?Wp1{Sc;>)PM5y*cy{-<-Nl6zA;FX!Jp>YiuSXTH=f&BfgHSdgEB-XZo; z2Vgp9yZbNf$eaZ73V`GtzisxsJ2x1`hPcm9(*1h>0Gv+$0GwsBv$u=PUSO~*r`mCJ z^;VC0Cs0L2c-FZGu(7$mnGz_>(nxB|ML@4sJ_9`pb@XG|@@(3IWM`6ANk4%5-_Cw_ z^55m>muJ=W+t~EID^HDum9QW*gb#)&*KVeRI?j`&+vu@+5fMGy#0!hH8_@p1%+bRE zUpGmTa>z-SC*(iopXPU&{{T6)xAQiz@>png1=GvETal|A2&RHk2>`PJ-zIuinQrFd zYql>83F-t!<605$Wm%<64fJ?EwXa_fs@hm8M>X7@gUc%NAX8}vfCr{C%sPwBEHK99 zEn=aD(N58*-h_20C5}B-D4!Em8qbg>08cvl4p>1Z`jk8?c0BByn>9FZaLuup*%Cy5}GEmft^uZ4~k#BA$j%#&gSRg9j0Bx&M zcHbE8s2FS(-hBs6v7XZYVDjHyB#1pgtS#c+i|GqqYOcd^ z-BvPA5O1GqlLfl zh1{qG)uFVKipFFV<~vrH*yS@-VvM=yO*`Z=5;-QoO`FTQPL&IV1_s z<_X^$8j+Z<*6O9=zYoXz-pT1D}3qsvH8KZ{{WXfxUyR4@y35h>dXDl=$gx3CqtwXdgkh$->)2m$H_SCVupxiy(n;>~|o)Ah3^lYi>zI*S8wrAs3h zD-r7}p3eRU4lb@PY$f`da+g%qfNNh#s3TL*u^lOt#7BgZi0;NTtv1tM39HE>Sb0~< zY{`El@$!=9ML!b8zqHN0aTs*1J{OATQifTzH$I*FNPShR{gQ{}Oo)_*#XMW>$vD-# z;jd~o*E&CywFoq?DBBZpq1svlYam&7m1a>&wR@ap#-P?qJh4nu>puaFM#K%Mas*mJ zrjg~*teY!o?S!XIRhjNxgB2_{Wv^V0+)b;_<|}AIdgJ3PX+iVJfn3WlL({aKKl1X% z*k0?`R}vjHztEwDK`kXuT6V8o6$QMuaa6krTc-UFLTiy5m9&>u)@=3Lv@yXMw6+8= z;1DowpAWZB#}2g5PIR6Nr01u(4|$|>D6{b&-Xng@gSU=g>vWOIH`tD@KC4X}@!^>G z^$8W;wRz>+-8$<^m`$rf3hA2rz_UwYWMRf8Ruy=*-1hB-mylY=qFhm$F zxg28z))_0hy4Qcdrf4zg{5cUVkAFv*mWp^YdWWa)d%u^py;ke<8_OPb*Y0A~yu4s* z4?KAlEs^=$$r_JdB#csMrV3d|`E>+i^xrdim&x#5L1}($TULobODajuJE*sybgd6x z45nu$Iho(3=T|WUwbUne1Z98`Q@oeW27#tCY7PR-M^P~f2)05>6d>CpO0oh zrFIp`x8=v=7v@Lj2AQjBUP)UP(q_E$Zf-7S^u!W@$k9Ql*!Il?yJ8xA#EcS=j^J_| z{G_P7ZYZ$FV26}zU$UZn06EA0DbyyH%U_jR9*?J7IhOX??0Vl?lZgu?$h1;McJD9$ z0L~QtL}+K%)$DJ4$9oqUCA__vxUoOvjknBy3E z^Ozs=kUnO%Z9acL-RZhWjbVdK)56jH1Te~erkp&l1}FP%TUy6vfYvgT72)R>l&`La`&3PrE{rWNO?T>GBl1)jaZzJ z-fJQyg4LsBl1dh6#=v$1ED)e<_^QXEF_-4MrV0ib&$``>f_>8G*wehfMQAK z+{4qrK#w!_wTf8kQ@r8YDBV&0D2kr7J#fZn9JqkLf14b-ScuR&^DXwzm!I>L{!a4e zlYcaP@v8ZQMuPIo&iX~Zt)e-b({;JFaJNYs*Wz|jws$_k>M}xFjU>ep>jSzc_PU>H zwSF#>O_T$0JTf43>2JKh=NvVU%nvi@ens-1<@KCw)U2~ijPWr zkL8F=XvFL@%lG%1Ftv`tOS_xDD_dJjKa^5p#^Tahn6QYGy%mmh__E?AQJFWrd*46p z40DxaiL+zk`ro zM1v9t{;3Ri^1D{je=h$3GyL6k<=gwO`A|M+x7KfLrJY&g@~*QFAuYY))09i9idJmL!3DaBD&CZW{l1rdnT7Yh?Z{i#t3$z=67!Y#pW*kxxj6js79nUIy4G*hM zXjL8WsQ0ri2|qIb06Ki8b&n-^c26&PugfsQr2cPtcT;kjR<)sCNYdJB8eEd~JWnA{ z9P}Uj;cuGb^7rSQx-aQeI)9(^H(8>m6no2Wi2$kV@f_g0a7Tw8UR)%=pXkVK_Pw98 z`Npe3pAlQsMQ04p|wfB9$T3ylTtrkmEexUjqd;gN{1 z!O2ZNdG%XRR7VRNe(jGI=hmaP`Nraj02{k@x>Lj~hva$ty|4@185$_=Err#;sJx=+ ziU(41;%Uo_C>{e+ubZ;2j8on`QnFlHf~{==d^}Y3B;z=RgiK&7X?1owb88wq1Tn`O zks2T*wMN+ix4AgD$@|@j#ALoOTS}{M7ZS!&M*MmTj`hitaY-@647r}?Vz3LDW#A)u zRah*k8Te0uCnHDTTC++q7EL=m(fU8b}-3mS0ErcOrp{_M-uxH+;|LFERPYP}cn0=51QuFEHL&#Rj492wr2y_ie(0od)AQ z2QDnK%x`In18!hGU1m{{$Ts3TU%~n-4)BgY_{MmVIe7SO_R+r1tNNyr%l-9Ig zgbe3b+IF}3ZLa8#tmsAc{XX}d#iYNzg7yQjuZoa%$l`z)_Z2ApB=Y!oyG<5YW-}j5 zcxZdyTWFqT@~`~lm51iHmi)cu+if%Qr&sda5@`0keG9KG>hb>Z8?{Lz;uv#v2EFB9 zGwFU{(QI2wz4ET1Yp>l|w6$0RxROst!Ac&PrPktxx*2hs6EWxgE@A9_mF-W;YT`22 z20`JUk0+8v=8q=%!}9xF^7rN+nC-m5b>~ew`^r8**R;D63t!Eqp-VAzKp(sksH1n! zx>owFrnR8y`t^WUxAP5*S60$33l)_Ejwh#l^USsYKf-?TvHM-=!f|If%fTbP;~n|T^J;c-SsQ$|t`aB!d?Hv9x-+5^efombm2>;UJ95iWZb49bGCh#`2K z#wv%V;`m;B@2lc0H%$@=%7Z7=1#u%61|!o^L@ zoSh1Qya5#lHW)i2QLo1=dT7fa5xc4Y^dz3=XQ%9)MxIg4l*R(V^+*q}z1Q;h{&Dy7 z!_D{l4x!~g%gtKtE^pvnGg6iog4w1F9V;x90BzSkOzHkx^7f;v`A^F~Ub^z$pRYkA z)80)ls}!uR?E}OC_*y^}O6RU=G;zm|7|FvaZ~-DY17D+)!FG`&Hhj3w!bgYW_wM~V zxcuDw-_ksj`JMTnsOWl6nEdbgGj_TxiF0Sd^G{jhiW#H3LIxlhb!M79 z_JgSDb494Ou56>SxP+N5AgPUHx8y6#8h#n9%fpP0BgI7W?s#nCQIL?|nKj;%>mEn* zJpOU=f999v@0}M@(C>VW{vy5Cw8?}PdUmj!ZZ0gfRYO4xiWmywH+FhmrmyAwKK|nR z!%4r9?6sXv^%-jvL|2jVO6D$1AkGqj;fdScdy%9Q$7UTj9`cxeUFyDk^B@{{ZH`oug`gbBoFsP-z}owvKx( zZ78dIqDbOCOUJE2-@`K{i!?BpP5{7PtaInd+~w3}5{zXVi5{-td(sar`HS*DU-O@n ze=hESF=o^(zd5X~FFg0ZX@3vRv`Bg&pt^Vgll&z5|#JH4Kufv+v^Wj|Gnjn+V1(OG*_HCpdzf0J>D85!^N z)3xlc4_~SP%8Yp?Nc*$akm z%Ka`aM%z%9>s+`=8EkLhZXt(2Sa;0)p2BvnY?ldCN&1iKW2&AE+r~UK-1V(P&7bp> z9&5YO?>xPzT6r?TtJi07h-AQ(8=lEU;hA{SJ3sAMZdkgym?#- z24V$AN(_qMd7DtYXJ?t3U)dbH{IhYV(_zC@1s^A3G@}^wz&?i2zvmeAZ7w*WvC_+W z48I9Z9DwS?k-kQy)vuh8%oT{Ma<0QNh8$3%%z0Mr*y1Vg`UmA7m(l?pzMB+xaH$f> zB7zVBzg$i^F0Ka{Qc33hfQU&scr&m-*{Y!v>L?9I%KreB{$BMZ^B`-Zcq7It_)n7`-dUQ}%| z_8%nvUth_oM;RJ?*Ny4KMSjx_sZo-vKg#_U+7jB09$8EXu@NHJhySD zkoVK(KQVvKcYb?$ourRLme0!evZnUYr>Mn`Q_S|ya{mC%4}MQ*dXJrNyy|qmI)9Pq zx@*Y1mGueLg0LsNXiI#`oWs`YWt7>g>rMI?c$4u7y8GWC{&;?A`TNZ9+UY)K^KI_3 zx2U%lHmxgqLWZDvV{Oms&#ifY?q4)#&Hn)T$gOoPeAVaSZX*uYHa5~ue$ZiM4Ms4C zGH`PrQBE|gC%V0|hlwIexC6Kc`!m2-uG8F0PlyxObJypaY<07OUrOn*EwzLIfEWNs z9ch3X6_PW_L3KVDMEFTUbhF5>5Q0PXXHW^L1e4g{H-a%&9vV%6u!9$e<^w#ZTH5@0FR{tro8na*jyh^=4LbuIu|h*^0NPG9GFuKFX1Z znYBTxO=3ZYLKp+;GH!a4THq<{;JQAPia3R>GV^0`%_JkV?Q-`^<93eao%eM#Vh?bA zvz==i1d$UxvVc{pzbuYO@onDQ43)F*FUbD@`N(T~PeViVOvdX?by&;E)DDy+`(yM^ zFg2~og6y$CyC*;C7w4XWoeZ14;8)$uLAL}>vwzrv%g zbqHE3`()zEB>PdieW70rup4p7=={{xVAMRdsN6+!9LW-rlcd6k$~x3^1mKjoFiMc! zMhmFpT5TZru0+`6#*i3^N)Y?loy^^HhxU=-Q1TN5F#BvUS{Pbw=IBw6&22V43gTOGX@J< zaVDI8{MGi4XXDfhsv+(B8`=*8(Ias$zV#g&K=ZY#%c5PRw+w;p=TZt>Ar<5gzD)EV zG3q)M)OXr!<~LRx(zRC}1Xnm7)$E98iNUCkrd|I4q3;KStAHbTp1seJe>MLACNy6- zTi)oNX0RzVNW#+eDD@(4%#BUPdh5zQbkh9OV*nQm9<0bs&5@-+9v(H%pZ%rwS3hLT z%nQO!(*18et~6)&tdO002RCckotr&mhe(cP z9i!;_mzebkwCyh4=6M(gkwrod4_j2a|So`{2`27L$Y zx3d=!Jc6;iuGa0WU6+r-!Y*g=Z`WV>#ozhF%R6fbJi+FenkyQlt7^iM+`8{WQL>za z+39z;%*GpLnTh@6fF2^gC%|W=!Z%Td(GQjC^}IyNa=91Wo^$-v@*m~CnvrXo#jc#T z(3G^%;$UUsqv1et@?Y~) z^IOaxoE~QVHLFD?m!ViYCWoMsct(n9CUM=EZ$py1T_Sh_T--)Ptfot7kHuPasLJ{7 z*LLw;SIt(pO)j5e!R`G)7NKw`fCJQwFt})ME-du$64j#yYpaGlQ5bJef0hs{p6kdY zRuSE4wmOcorc1wB*3V9|9~_e_ZOf%aI~)N#w)&FX&atesDKWgO@cSzPmO)5NZQ#^& z8EkB4X1BMS)156`7YslJgBqF;J7GMDE89zLGZ^EAxkxMa*mN6q$@3{YGP_%gYdh<0 zR?;+@=Jpd5GO`9sc$@98uED%1g;7jZ<$>jBOvqMdM<Qsn+a|$tnVPV zj`Uc{C9+vy3bT<)@)WNjzW5>8W3%Rld)OkU))Wu0PQdTslEws%+XV*sr9@9IuJK&Q zW1?yo1e+O^s3ec=GLjFD*kMYwztjs#u>~(F6fetgIF7VE^0Fw}2YE?7LFj59rqU}p zZ(2lKK~`86Ge#mpO*sKjGUpdBaL8TmZrB#Qj=WI^^4H~-4b)N&)%5u6(qBeBJ5G(n zdR*jlnr5v%UtkW{QEMb{$o~Ml{o9^Q?blwv?8V2teJGe=*AC!z#XPvzm5&mELQ7KyOQQrUsH*mHQiVqi_6C?gs57uy%)?A z>6$i+Z>L8omerjsE~Mm=M8Nz~6sSCQ+afn!T+)n<>ISwdImD_7R#JKsk{Jg?iAnC- z2j_R@jh&2e+3T`j!0+hXiKZdpbp(frN$Fmr3#Ibin#t-LLl6WAYEQ*p`5zym+?lrsaj+}Y_S>J2Iu)HNO)RDHOukcx9|+`HsA zza$O!J28DfN7X#b7MXwM%camfy3_JJfQs)@kQ(|?3UcBpOix3!NF1X|m-?om8uFQr zz#gNKKM28_ySXUwFcFj)vmd|UiY7aiVvcy{EIMtKUC*lhzJAB3lHX;EPy})UnG0mW9DdK^p1l76oFwxg(7!OhF#iB8Qu1pl zwd*9-^ovWO$M?{`2@{E>2n;%SXP@@=mpx<3Bm`w~uIk(ZeEJ8w>}^IZS7k&H3Bx)d zbKsWu^LW4f=2ecd=T9eoReo?uVQSX!S|2Fuy0)DsuWdEmqASB7kXF8;^KH#@=%%l6 zKBF8qbIcNJKi5DZyd57C6&Gn>Yf<_ z2_5c4U^t13up>sM40`$zUvoCHw!r!F|kVvSR>wE2Qu#sYr&BhKamHd>9T zlaxtYI$f5pHj!)Qy%z4y_DBc~ zC!&oiB}hF;>(@LRBn`YhjL9B^^1tqw(&2*XOSz{$}f5Uh>|j{{T4R)>_AszcFq!-FsHI zitzrI6Im5$2dT=Y6eIV5_++oinns(b`8&$qeZABy*G}?|yC#F?tubr*Lc+%7YX+cN zys60SM{L5Ef?>xwSdZgpp2>z{B=Lbcavps{5&X!}Jm2L106KnU`4TO3#i{;q=++)= z^7}?3T`N}BEjYE_mKK~hQN)APUuw#eBpKZyX3t~O7nl3yvyZX zA{}o_(0rqP<+~=go6B>>Wf7jkR7ij_Tl$p=?T@^ZM)I$iApG9)o}e@XY)ab1RP|ksjhvu z)TW00EOiTgK1pJ}wTkjK2jK}ahf}xDJg|rfdZ0ld8ux(i@WA0R#%3%?$K*@#Rn?K% zToq(AWj%=MFu6T8i|X>$G-|gc=o*^_BO&zcT#`-LTbe6-SYdT}TjD~#s}ohPT4ZE8 zld??aWGFifW=6Ay-ohDPLFtJTP;u~q?_99Nit}-xd{S}|$klhd16)`#CHr6UNZ)O6WW-r#`1$-|Upr`!yuQ8GaTV-dx-GgRYfwF4HW6FiBd_Z08Ty1beO zyQ1rmr>QQHeFfUYYe)2CSK?{efT7Qcnx>_pUdN@2$&L1~G|4pIJ4ZTjdkeijK%wDb zO7lUUzYO|)Trp+FPwyfRm_1%2w)-dYy4=u?(Brt@UM}w^>-UlTxA~8t`DR}*c}1@D z>o`2sYp#A*tS%o-)~tNMpB|I`Oqy|`s(uGjD%Rj@Ux2ULem{YGG>U3hbJEn zc;k_g7CBd$q0d$wbL)@%;m@3`eEazmr0LM!8LoVbJpNz1 zx{!e&7VJb!!1Uyl&KFbJ*>hye34sv_nMB^)IXC?;r}mVlC5uzB@n9vk`;DYM_8*yF z^Ob%<^B0gmI{epZ<}Cp{xpC$vhN(`@e=$C><-<(q#;Uh{^N zrHE3q8SZ08B9#>tu4*+}7=SMzq0fYI6Y|-|$E4M2WM_{NKROQx)ASv0R(MlQ(eE_| zxMLh5-U%hMVokr3z91I@{XfSi$rT(HJT?;kIF+;orm#gESYPs~18^1aWKC(t!t zIY9IIZarO=)ozk91B5J2;=L(c^X9q#06zuPuI=KB$Ul|-loO4$J!*PJ3I6~gXny?5 z9fzyM9vt$7C3Rm>Y?F&q*QBtyO&(Y6BA>Q@;Be=EFzq z=7<5rXPQInzf4EEomcuX)9Ggcr_#s2izi=$*F3xb064YzH{~x=P#$0Z0F{R%Rgd$}oHJUC| z9Ej{Qec5^~HisO~4Q4^}RAHn;VWZkt^C?x{^wSAxUqCwiMfWM$Z0gQ>A(nUPo^w%gsP) zN83^L)*02E|a=d)|GjerbMSr=GmmbNQ*Sd3F}_*O#ySy$6%l*uW*X zq-_=L%cVKEkM@mnN#@Tr-0Oa2^5mM%wJp@%RkS*Wje8xkqsOQ_tG&DN0<@(;%jcgL z2_*25unxZ@jB!{y-t0T_lgfJclfNRo^%s&>%&+D~tlnJnj*)kHSmw}HH!G=HtGC1P z8WD>>n7r+;c_UErCH{vOnRMy37u9SvX`)rSwUT-nm1Wq`hQ_Bgv+Xkp@W^p(b=+FN zK5~e}K-e7=Ut0X9^7o(oljq$F&rA7Psri3Ohf3D8%W_^T>1+oGC-f47de(=&7Q+5? z(yYasdGdWDPg`?k9*sTo+(x#{J}CV%#1-jGf0Q%j$9x8f+zTPfh7ES45#f?PJ2!LZ zZz6fqRC%TRqr3dT)t=?AC-YvPV7hFRU55_^!%B*@Dn|Y}9Wr@V#t6sOrqzwPD)GR) zR;Q@0Y~$H8F&mL1yRy^vCUPorjD75q+S~KT%^LOZ9WP7rQtIfY3!PcT#lbNTgo^K4 z3YjGi%2^4*xhM*Jen|vO}=A40_6u+g&2QYRH97p$=47{qB zFXX?TwcDrEKQMnY=e^YLXT7~ei4>Mp}er;Z`}sDgX?y(h@u^NZe7xI~!wM*CdVR!>OYY6#Q1 znvaMx*RDe!R2Ojm{h8)!mXdFXu|I!&*m&~AlK!aoMuj;N(`3oh-uiyW{&9lxD{EME z>sw7BV+WGG2E(W-qLjjwxVv`rmPC~SqN0u@Q{|aiwRqzjjASHz@@EV_A2xrYenO2R zBX{O+Fj(7ZwyIuv)FrYYr&f3ChBg{4=A<4Nbo-l!EwE5&_vS8LM!1l0iua0ags{VD zZVF$odC&fFhw|#r>mGCS){`tr@u*9Mxsj-L0T7&&TK-u1uIw+PZ5@PBZ(E1oe*x`> z42-YyCv&#RI^0l|LE_$P{{Wwaf6g}fDQ%+i7MZDe!dDGLWo{yf5IzuCjGtP5Rq0li zr|bH(w|b#k28>cPsNW+okCaF4ar0{@lyLF^@yDD00O#XBo!)HKS+s2nOY+B+1l-`T zBbCblejabv4)ot8d1k^cbJ~8Al{!4f_+?@-;;<>l97lVnkNM~Raml=vDv)mbyKZv+?@M?`3w1Szm@+0mR?@+z$VaazURQKR!mk zrupm7HXdWPk_)X%RhLk-W*a@Tu@Ev5u^a#c?(39kGR{&lkfIOFI(g1gnFnI^uPNEv z+{>hDR?-UE!fo!MrFghCuhZ8&&Iu}@o=)At=}g_5EDrBx90SNzKuE{O?_QW9MNr5< zB#nvr;6ffJc@k7&7B;C+d`E@_c#Oq^Mku`p%M>G_yB2{QN*WTIES*JvJhayYeS|h{{>?%4j#00Ma1xhOH z2p!II{Zl~Y&P!4hnwCb(rUb~gVs!fR@{9BG`^oa9hN9AH8d)f^arl4-Y8v5Yk*-|n zmjVf@2QDiyI{-bi7FhTX5cxMx5RkB5?fIYiH|75T&95)Z=5Hy?f`37-XVXzv<2-A& zz}MS4ly~;Jj8rVrw%nOTO8p}Ulw>W(A^Eqd`Db79h5rB>*gr>x<>=Z>2rd+mc_s_> zr?!?TZr6+szqy;Q%DG%+V#hGR?v*~DVX0eBd8CkT2KSbP_x+;2*&5gUu@&ky<)sqh zI+jk&lHnvC_RLw1GruR$ACcelkvfm%)}?Eq>&Z3mmM4)B3j9-AQ0`+V_CW2N#*bwq zDoP+4P)waq97LM|i$q z{LuWX()HUr&n@|~%ak``j8c#*U)gj%Bd&VW${(2eFPN;}W8Oe(E+->xLwhVV2N<6RVKRmi#gHyMD~<$!ev((dvrQ zG<`?RT9g`AlM798aKTxI;YW!hpwAL{=g&Hqn{`R=ukKn|9;>#jp9sSahpfeRp553k_A(WM7Km$8k~i zayOyq6Kd0X*8!umR;-fm@p~?MjvRiFAOMJbmtEQf$dYbn?0pyc<@xueeo|@c<=-x} zSDtXYgN2QRYz%ftMFg_};oCZx;RG>RT0#51ks=S{-z|(pc{(l0-T8%gcc|;SjsF0d zJi&TywM&<2Z!YJ0pC5*`pdQ&T(e!wp3#sl@{bt=cEui>n2YR0QR!oI2GV>Rhrx!Ll zeT3?^H*y7<`|T22Y84-{JK!sgW?M;QwUs3J;|4aZ8BwXQBdst%Y?@50{HblK+uQ0E z)53*jWR@jgf=O5Gvnf9aG{84($t*ER3pcE##N6vuZk*3-wmi|zF|dv)Z0~R3yhUqC z7B8p>NMj449y8Qz({OscU_xU9=MtV}?YnByEFK zjfN$2ZzOi@b7NT}lveU(6>a*U2gAn+T!8WG`ovoOXTNxB-R+Ek~4^N}Z zzzWx{G$n*q(M=VsmbVI|#*-gY)KRf#1En%VAd;y)=C^f!bzwHQ4x?iu(rGPFz%87L z@rJ!>C=a#?43SCdd~#cX%tZeH2$D*7_89a*2~kNd;t&xGckaRgaTmna@P_@KT^RV{ z7MGXG(_LDmA!8?i1L7RIfnN-O-Q|ek~sdakySG-K@%o;PtWo84fDsPt8 z4RK=Vk^E7ydDxm3XV`M@lM>kgaG?gAx^BG#Pjm3jqAMgt98n?_ArD2{d>0+E%O#S# zt+9znYgm?{2_I;md;}oLESFV#cr}w9yJ`=8F!Xgxm*UcdYVcM603>%9$&q1M5-U*~ zLP4HZJftiBNFF&TZ^>z>E*|Q8d2V$HU2caPTO}Tx3oR+}u^aL0m2EtdEYmvw43!lTUW) zkz1e&W@2f?cmd)t%z^+6xQs(2(){=4zbR?Yqj`SXD+@g>8f%NUCPlVUQeH}uBrRTt z5Y#jeFz8XsHN0zer+WNS);9G=Fe}8ibU_|$dh0;ablqyh zOwqqExLQwiV~XPX4@l0tvq~jhfu`Hw%ROQgx`sQQ9!r~FOnR`$z9OFuIt+mwN(@CE z(!EQ`*DYmxCY|SNTYXMB+v>ByDGKVRe^CC@Q+x<6QKUAFp~x;Hki0h%F<9eLei1>} zF0yxC5#FyRl?}a$>Z|9dWwg14QtM5%i`2NdVY8FVrub(7n^TSLwOgsIwDoYuPqkhm zUdF5ic;#e}EUl#16KTF$xQ6q}x^1qptvnSTV$~cxmd@L#5j9eywL!rX=~{h+Qww6& zumG|$C@LL#QOi`eF`bHI?@D6xN0>F+`)i#_QLJhecq6!#mCQ61tSe42iuepFxwy1~ zDUFnSb*}l*e>ybQ^kjOPUOAG1C7u0N|lubRfUJoyL$D3} za1X0@Z*y-oyR=OU0UV)?LRPdRxUb!nOBkF?d)p#um}zs_2rp)ngWO1kq_*^v(vm^7 zNnq7x8&jd^cFDJr{Lvqj{{S(3h39pK=3PR=%rQr--iPGlPP|`6P{XT4u2k|JJLd!2 zU60{ub5SH$81gah_&q1F_~9K^Ong8`E;1;e;vAXf&XEHRlr*(>Ew|A^&oT*jYVfLq2jV4v}ilDoUy2zt?Fs*C!=ax=Bt|7?p z^LF}K$_Lf_CHa6s1nfrrGAP#16k#A{kVW>SW3_w+G4gh>%f?9}iEA%~CWM;$Wh)^E zqaSRXk|nVY#hDAJwLn8xkR9kSbZf9ZMcHt?(m_3?yrHIv#Gp9pK-gmvXoN~4G7>z9 zr($x$cDL5IlRy?ZfLrM!`(X6=M|_mBSP}W7jt3l|4UxDG$d~88lP2@GD_GA6M9p$Il4sahVE<^vnF<&c7`@)c#2G z=aoFvu*GmRZAKa9x0rH`Z;3JWgylWj+|~ zAa8zQs#SZO=M1<-cRN!r6V?XQ@w{GEMJ|Yq zdF$}&6UO2r;Ugh4x#RnNWHTO``E&LL>_go2Zk@G6>A5rR{h*}M!<7vAhK zlG{;~iIBINk9Siy0(K6cWPGGq}E;w9H*@c0QE9$|3LkUyQj zm2&7Go_=)FuC!_8vGZ#s$CIM8D-sLK=Mnz&or)G}9PE9J7mqdxW2xeoQ~W3Cr%UZr z@#Hu%-tzRHd-TilgY)u8KO=mD<&85_hfdc#m99-Un;z^v!JkF4Q*{#BC2Jh9gd`ER z*~;|)059ni>KeondAj5B`^&&)qHSm{t&dE@e@%fFnTm)>sky`H`0Pd>rI(_EG!1hLILQ2_7h zt!l^RggOP*ucPUf`nH96D#@vO+9ke~8*`S9q+B77daH`lHP}u}c{roQdF<<@J{j;= z4SKJk-(>IeHs49}2b=Evv*(KqD@Yn;y|0{gKgBMS>p~hfDy&C_0bzoAcK=7=M?x`ST1yK9Bjt>bb6NgK0q zbt0La{wsjP1YkDX(mpg2m*uv;v-1X`I05-g*`6>C0=g2=Nyvd^Z z+wy5wuc{y$@*8oB1PDN(B(eO~r2=MTz=Vz%=io;fXd6qj(HlzE zyrFvst8=I=&1rQMjbBZpAQMchPulpqJ~?vg0f3ksBl*d}*qx^xH~4W9%P*vkQSyAn z`R}Cp{{Zr5NBp|c{{T8x%J1_dRo5Zc{IB_sWp&Oy7RnhZbzv+qZ6IosMji4U^-Di6!yUAd%X8?g6WbH%PT&#Ds_njOH2%f8JGGz7Eq~0PmOg0wyz^pcr$vReDBjZ1rdyZ2DJ9ZIl{`7PVm^4N{{Rly z>6#_XcUoqLs%bGaT8y^x30m>0ekL2x(9q`Cc6Ps11mg)`n5SQdv$dIT(s)mM%5{G^ zdB@E<=bH2zn=O0JURLt~g|sMdmEv179~J}}RE1$tkZ1ExlQgHEB)Ph}M6y&f#PHlK2K6zFZ0jN(Avm6xecYv3l*)VsXd6A zY9e|;5=jQYuU)XNZ_QL;3TV1?3&#&_L{rq&q?eAVhGgb;-j}mV;;uS!XB_> zM|yOB=Nt9AOIa^`*w>~djX_DS#k49xt18D4T6OF&s`Jf$WV}YMr9G{z+e-j*7^ida z(>5A!X7oC9#lyugO<8krcrmdE50f_1{F~%$Hs&ikKPqYWt`QPD>uW)GKd66bGXiUo zd#y^_lHD2UBtHU`C77>rYE5%H2*;;^#3BvvTTqvCWJY7@7BAo*MR{}bNAokx*HJ^J zd4B%@O3?xamhR{X5y7PhRRg9J9Zu@y&Aot@c+2y2j2e^Smqf>hh{OpUz0H4?hCT8h zwd|1oKzVP;_jY=Z=0BXREiG(<%->kKNY!@fQq`x99BDp8*Yz~@tn?d{mRI;?bHQuZ zdgGJxx#S_@L_l;up{qQh#5hf`?=^qUR)5YNeoe$5Co-X$%H499Ns_XkNNrk0FiX*E~EUr{H?#$+tW{| zzM$gX7X)lVs0Sva^1DKT5iTz#yPby83M%nASn$7u9lP6(T!(O9C+dIm@Xz_konrR- z>rZ_z%Qm-7{_?|aC6XF$su}B&4J*n%SCcZ>)fkVri zRg!lvn|$&4!TG=Wp(WaR@ACsy)NC%#Ikd>8cy0bJgM?%$1Lcx~bMZ6Av0Dc_#}WnJ zzbwO^X-i{g%@G2qys|9{*4~UmU2)jSAuYrXf{bt+mk+tA1RcpHgXfXkswgMWY2i<% zC=`!^FaQT`)W-VgD(g2sTQD2fC3n#xD}JWnDm*29I+f&hrFO2LaC_7X+F)6$7>dx;81*j1#O*h?R&n z8cw7W(`+v!^7RCi0QCGaQX-N9bsQB{iLIHXI~En#_BrcM`NRJJ%SH3&<{SB&QM3)^ z{{SMG?p`@XMAytu)qvWBDN^U;Ghdz{0lw~Lj}^;_=iizdZBjkM9bHHG>DZSJA% zBrHbY?NQZw9rHFh#I`QFK)}?WM|pQ$)3uvneQra)5Vv-$emK}<2?-W5%vWTp>}`y(rXyAHd^k zu-jpR(n~{B77uL{H{9ZJQ3sQiux6zdWSHgF3tF2S=?_JP*(dBJs{dFHLP36&P zD@Oo&m6nHMqz&tuHET+lPpfCk`_83LYWropcE*y)it7XmbQXG`UQG!U5`))|U``Y3 z{#&%x;ulfKvEG6EvVwuWc|39i8w~N~mN{+9tJFUye>^YLQ8(d27|@sOa;# zV4$CgqpfIjlFb$7m3YuiZbeTPQ~JhW>vS;Gz>J#_$?5wSw z)9SG6G4Vrqyf@DNN=t|?JiX>yQE_2%jIqd8psNZ34Jb3zoRa3(JfW%G9YuEVIo9~C0aM5kP)CM&Oo54`(bAXA^`YU=^u&suhqp{^3bmy>Vnl6F zJLIh(t_OO1V*oTGrF)zu7rSS->dOM11_T!q*!~$~Y7fH|0mSTRewvOyV{g$qeLs7DBJ^0n=%DpE(snnqxplQU4j6a$yME2= z$?D_>Ag!m^UTZh8Y1(`ZG}90{C?qET0BF-ZMd!~x>ON`JWV*hQk5sg@3_?K={e)hF z-#y#ee`X~(gFo)#?>kquFm_fEiUZbpKU@C*=M?_{=M~v4ExgOC+Xk?R`poRKl6eIP zrA2syk-ZN>pIEpu8m+p}%P}8l_zd+uJ_10DMMM|LJ4dt)lXo-rKA8OY{Pxg)C$x3Z zbg>oJn=Ybg^vy8{D`qJ{B%pMsP&{*`#v`|lZSBXW9CSp4QkCw0oY

7oW0sFUwnt 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

~QmE_1}u-NyxIPmXseSiM|INSdK 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

pWo_ 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 literal 0 HcmV?d00001 diff --git a/App/VL53L1X_API/core/inc/vl53l1_api.h b/App/VL53L1X_API/core/inc/vl53l1_api.h new file mode 100644 index 0000000..34a3ecb --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_api.h @@ -0,0 +1,1142 @@ + +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/****************************************************************************** + * Copyright (c) 2020, STMicroelectronics - All Rights Reserved + + This file is part of VL53L1 and is dual licensed, + either GPL-2.0+ + or 'BSD 3-clause "New" or "Revised" License' , at your option. + ****************************************************************************** + */ + +#ifndef _VL53L1_API_H_ +#define _VL53L1_API_H_ + +#include "vl53l1_api_strings.h" +#include "vl53l1_api_core.h" +#include "vl53l1_preset_setup.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if !defined(VL53L1DevDataGet) +#warning "PALDevDataGet is deprecated define VL53L1DevDataGet instead" +#define VL53L1DevDataGet(Dev, field) (Dev->Data.field) +#endif + +#if !defined(VL53L1DevDataSet) +#warning "PALDevDataSet is deprecated define VL53L1DevDataSet instead" +#define VL53L1DevDataSet(Dev, field, data) ((Dev->Data.field) = (data)) +#endif + +/** @defgroup VL53L1_cut11_group VL53L1 cut1.1 Function Definition + * @brief VL53L1 cut1.1 Function Definition + * @{ + */ + +/** @defgroup VL53L1_general_group VL53L1 General Functions + * @brief General functions and definitions + * @{ + */ + +/** + * @brief Return the VL53L1 driver Version + * + * @note This function doesn't access to the device + * + * @param pVersion Rer to current driver Version + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetVersion(VL53L1_Version_t *pVersion); + +/** + * @brief Reads the Product Revision for a for given Device + * This function can be used to distinguish cut1.0 from cut1.1. + * + * @param Dev Device Handle + * @param pProductRevisionMajor Pointer to Product Revision Major + * for a given Device + * @param pProductRevisionMinor Pointer to Product Revision Minor + * for a given Device + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetProductRevision(VL53L1_DEV Dev, + uint8_t *pProductRevisionMajor, uint8_t *pProductRevisionMinor); + +/** + * @brief Reads the Device information for given Device + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @param pVL53L1_DeviceInfo Pointer to current device info for a given + * Device + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetDeviceInfo(VL53L1_DEV Dev, + VL53L1_DeviceInfo_t *pVL53L1_DeviceInfo); + +/** + * @brief Reads the Device unique identifier + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @param pUid Pointer to current device unique ID + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetUID(VL53L1_DEV Dev, uint64_t *pUid); + +/** + * @brief Human readable Range Status string for a given RangeStatus + * + * @note This function doesn't access to the device + * + * @param RangeStatus The RangeStatus code as stored on + * @a VL53L1_RangingMeasurementData_t + * @param pRangeStatusString The returned RangeStatus string. Shall be + * defined as char buf[VL53L1_MAX_STRING_LENGTH] + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetRangeStatusString(uint8_t RangeStatus, + char *pRangeStatusString); + +/** + * @brief Human readable error string for driver error status + * + * @note This function doesn't access to the device + * + * @param PalErrorCode The error code as stored on @a VL53L1_Error + * @param pPalErrorString The error string corresponding to the + * PalErrorCode. Shall be defined as char buf[VL53L1_MAX_STRING_LENGTH] + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetPalErrorString(VL53L1_Error PalErrorCode, + char *pPalErrorString); + +/** + * @brief Human readable driver State string + * + * @note This function doesn't access to the device + * + * @param PalStateCode The State code as stored on @a VL53L1_State + * @param pPalStateString The State string corresponding to the + * PalStateCode. Shall be defined as char buf[VL53L1_MAX_STRING_LENGTH] + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetPalStateString(VL53L1_State PalStateCode, + char *pPalStateString); + +/** + * @brief Reads the internal state of the driver for a given Device + * + * @note This function doesn't access to the device + * + * @param Dev Device Handle + * @param pPalState Pointer to current state of the PAL for a + * given Device + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetPalState(VL53L1_DEV Dev, + VL53L1_State *pPalState); + + + +/** @} VL53L1_general_group */ + +/** @defgroup VL53L1_init_group VL53L1 Init Functions + * @brief VL53L1 Init Functions + * @{ + */ + +/** + * @brief Set new device address + * + * After completion the device will answer to the new address programmed. + * This function should be called when several devices are used in parallel + * before start programming the sensor. + * When a single device us used, there is no need to call this function. + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @param DeviceAddress The new Device address + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_SetDeviceAddress(VL53L1_DEV Dev, + uint8_t DeviceAddress); + +/** + * + * @brief One time device initialization + * + * To be called after device has been powered on and booted + * see @a VL53L1_WaitDeviceBooted() + * + * @par Function Description + * When not used after a fresh device "power up", it may return + * @a #VL53L1_ERROR_CALIBRATION_WARNING meaning wrong calibration data + * may have been fetched from device that can result in ranging offset error\n + * If VL53L1_DataInit is called several times then the application must restore + * calibration calling @a VL53L1_SetOffsetCalibrationData() + * It implies application has gathered calibration data thanks to + * @a VL53L1_GetOffsetCalibrationData() after an initial calibration stage. + * This function will change the VL53L1_State from VL53L1_STATE_POWERDOWN to + * VL53L1_STATE_WAIT_STATICINIT. + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_DataInit(VL53L1_DEV Dev); + + +/** + * @brief Do basic device init (and eventually patch loading) + * This function will change the VL53L1_State from + * VL53L1_STATE_WAIT_STATICINIT to VL53L1_STATE_IDLE. + * In this stage all default setting will be applied. + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_StaticInit(VL53L1_DEV Dev); + +/** + * @brief Wait for device booted after chip enable (hardware standby) + * This function can be run only when VL53L1_State is VL53L1_STATE_POWERDOWN. + * + * @param Dev Device Handle + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + * + */ +VL53L1_Error VL53L1_WaitDeviceBooted(VL53L1_DEV Dev); + + +/** @} VL53L1_init_group */ + +/** @defgroup VL53L1_parameters_group VL53L1 Parameters Functions + * @brief Functions used to prepare and setup the device + * @{ + */ + +/** + * @brief Set the interrupt polarity bit in + * + * @param[in] Dev Device handle + * @param[in] interrupt_polarity active HIGH or LOW + * VL53L1_DEVICEINTERRUPTPOLARITY_ACTIVE_HIGH or + * VL53L1_DEVICEINTERRUPTPOLARITY_ACTIVE_LOW + * VL53L1_DataInit() sets it to LOW + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_SetInterruptPolarity(VL53L1_DEV Dev, + VL53L1_DeviceInterruptPolarity interrupt_polarity); + + +/** + * @brief Get the interrupt polarity bit state + * + * @param[in] Dev Device handle + * @param[out] pinterrupt_polarity Interrupt Polarity Bit value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_GetInterruptPolarity(VL53L1_DEV Dev, + VL53L1_DeviceInterruptPolarity *pinterrupt_polarity); + +/** + * @brief Set a new Preset Mode + * @par Function Description + * Set device to a new Operating Mode (High speed ranging, Multi objects ...) + * + * @note This function doesn't Access to the device + * + * @warning This function change the timing budget to 16 ms and the inter- + * measurement period to 1000 ms. Also the VL53L1_DISTANCEMODE_LONG is used. + * + * @param Dev Device Handle + * @param PresetMode New Preset mode to apply + *
Valid values are: + */ +/** + * @li VL53L1_PRESETMODE_LITE_RANGING + * @li VL53L1_PRESETMODE_AUTONOMOUS + * @li VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS + */ +/** + * + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_ERROR_MODE_NOT_SUPPORTED This error occurs when PresetMode is + * not in the supported list + */ +VL53L1_Error VL53L1_SetPresetMode(VL53L1_DEV Dev, + VL53L1_PresetModes PresetMode); + +/** + * @brief Get current Preset Mode + * @par Function Description + * Get actual mode of the device(ranging, histogram ...) + * + * @note This function doesn't Access to the device + * + * @param Dev Device Handle + * @param pPresetMode Pointer to current apply mode value + * + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_ERROR_MODE_NOT_SUPPORTED This error occurs when + * DeviceMode is not in the supported list + */ +VL53L1_Error VL53L1_GetPresetMode(VL53L1_DEV Dev, + VL53L1_PresetModes *pPresetMode); + + +/** + * @brief Set the distance mode + * @par Function Description + * Set the distance mode to be used for the next ranging.
+ * The modes Short, Medium and Long are used to optimize the ranging accuracy + * in a specific range of distance.
The user select one of these modes to + * select the distance range. + * @note This function doesn't Access to the device + * + * @warning This function should be called after @a VL53L1_SetPresetMode(). + + * @param Dev Device Handle + * @param DistanceMode Distance mode to apply, valid values are: + * @li VL53L1_DISTANCEMODE_SHORT + * @li VL53L1_DISTANCEMODE_MEDIUM + * @li VL53L1_DISTANCEMODE_LONG + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_ERROR_MODE_NOT_SUPPORTED This error occurs when DistanceMode + * is not in the supported list + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_SetDistanceMode(VL53L1_DEV Dev, + VL53L1_DistanceModes DistanceMode); + +/** + * @brief Get the distance mode + * @par Function Description + * Get the distance mode used for the next ranging. + * + * @param Dev Device Handle + * @param *pDistanceMode Pointer to Distance mode + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetDistanceMode(VL53L1_DEV Dev, + VL53L1_DistanceModes *pDistanceMode); + + + + +/** + * @brief Set Ranging Timing Budget in microseconds + * + * @par Function Description + * Defines the maximum time allowed by the user to the device to run a + * full ranging sequence for the current mode (ranging, histogram, ASL ...) + * + * @param Dev Device Handle + * @param MeasurementTimingBudgetMicroSeconds Max measurement time in + * microseconds. + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_ERROR_INVALID_PARAMS Error timing parameter not + * supported. + * The maximum accepted value for the + * computed timing budget is 10 seconds + * the minimum value depends on the preset + * mode selected. + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_SetMeasurementTimingBudgetMicroSeconds( + VL53L1_DEV Dev, uint32_t MeasurementTimingBudgetMicroSeconds); + +/** + * @brief Get Ranging Timing Budget in microseconds + * + * @par Function Description + * Returns the programmed the maximum time allowed by the user to the + * device to run a full ranging sequence for the current mode + * (ranging, histogram, ASL ...) + * + * @param Dev Device Handle + * @param pMeasurementTimingBudgetMicroSeconds Max measurement time in + * microseconds. + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetMeasurementTimingBudgetMicroSeconds( + VL53L1_DEV Dev, uint32_t *pMeasurementTimingBudgetMicroSeconds); + + +/** + * Program continuous mode Inter-Measurement period in milliseconds + * + * @par Function Description + * When trying to set too short time return INVALID_PARAMS minimal value + * + * @param Dev Device Handle + * @param InterMeasurementPeriodMilliSeconds Inter-Measurement Period in ms. + * this value should be greater than the duration set in + * @a VL53L1_SetMeasurementTimingBudgetMicroSeconds() to ensure smooth ranging + * operation. + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_SetInterMeasurementPeriodMilliSeconds( + VL53L1_DEV Dev, uint32_t InterMeasurementPeriodMilliSeconds); + +/** + * Get continuous mode Inter-Measurement period in milliseconds + * + * @par Function Description + * + * @param Dev Device Handle + * @param pInterMeasurementPeriodMilliSeconds Pointer to programmed + * Inter-Measurement Period in milliseconds. + * @return VL53L1_ERROR_NONE + */ +VL53L1_Error VL53L1_GetInterMeasurementPeriodMilliSeconds( + VL53L1_DEV Dev, uint32_t *pInterMeasurementPeriodMilliSeconds); + + +/** @} VL53L1_parameters_group */ + + +/** @defgroup VL53L1_limitcheck_group VL53L1 Limit Check Functions + * @brief Functions used for the Limit checks + * @{ + */ + + + +/** + * @brief Get the number of the check limit managed by a given Device + * + * @par Function Description + * This function give the number of the check limit managed by the Device + * + * @param pNumberOfLimitCheck Pointer to the number of check limit. + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetNumberOfLimitCheck( + uint16_t *pNumberOfLimitCheck); + +/** + * @brief Return a description string for a given limit check number + * + * @par Function Description + * This function returns a description string for a given limit check number. + * The limit check is identified with the LimitCheckId. + * + * @param LimitCheckId Limit Check ID + * (0<= LimitCheckId < VL53L1_GetNumberOfLimitCheck() ). + * @param pLimitCheckString Pointer to the description string of + * the given check limit. Shall be defined as char buf[VL53L1_MAX_STRING_LENGTH] + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetLimitCheckInfo(uint16_t LimitCheckId, + char *pLimitCheckString); + +/** + * @brief Return a the Status of the specified check limit + * + * @par Function Description + * This function returns the Status of the specified check limit. + * The value indicate if the check is fail or not. + * The limit check is identified with the LimitCheckId. + * + * @param Dev Device Handle + * @param LimitCheckId Limit Check ID + (0<= LimitCheckId < VL53L1_GetNumberOfLimitCheck() ). + * @param pLimitCheckStatus Pointer to the + Limit Check Status of the given check limit. + * LimitCheckStatus : + * 0 the check is not fail or not enabled + * 1 the check if fail + * + *

+ * + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetLimitCheckStatus(VL53L1_DEV Dev, + uint16_t LimitCheckId, uint8_t *pLimitCheckStatus); + +/** + * @brief Enable/Disable a specific limit check + * + * @par Function Description + * This function Enable/Disable a specific limit check. + * The limit check is identified with the LimitCheckId. + * + * @note This function doesn't Access to the device + * + * @param Dev Device Handle + * @param LimitCheckId Limit Check ID + * (0<= LimitCheckId < VL53L1_GetNumberOfLimitCheck() ). + * @param LimitCheckEnable + * @li set LimitCheckEnable=1 enables the LimitCheckId limit + * @li set LimitCheckEnable=0 disables the LimitCheckId limit + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_ERROR_INVALID_PARAMS This error is returned + * when LimitCheckId value is out of range. + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_SetLimitCheckEnable(VL53L1_DEV Dev, + uint16_t LimitCheckId, uint8_t LimitCheckEnable); + +/** + * @brief Get specific limit check enable state + * + * @par Function Description + * This function get the enable state of a specific limit check. + * The limit check is identified with the LimitCheckId. + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @param LimitCheckId Limit Check ID + * (0<= LimitCheckId < VL53L1_GetNumberOfLimitCheck() ). + * @param pLimitCheckEnable Pointer to the check limit enable + * value. + * @li if 1 the check limit corresponding to LimitCheckId is Enabled + * @li if 0 the check limit corresponding to LimitCheckId is disabled + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_ERROR_INVALID_PARAMS This error is returned + * when LimitCheckId value is out of range. + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetLimitCheckEnable(VL53L1_DEV Dev, + uint16_t LimitCheckId, uint8_t *pLimitCheckEnable); + +/** + * @brief Set a specific limit check value + * + * @par Function Description + * This function set a specific limit check value. + * The limit check is identified with the LimitCheckId. + * + * @note Note that the value written with that function will not be applied if + * the limit is not enabled. In other words this function will not enable the + * limit but change only the value. In case the limit is not enabled the value + * is saved internally and applied with VL53L1_SetLimitCheckEnable. + * + * @param Dev Device Handle + * @param LimitCheckId Limit Check ID + * (0<= LimitCheckId < VL53L1_GetNumberOfLimitCheck() ). + * @param LimitCheckValue Limit check Value for a given + * LimitCheckId + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_SetLimitCheckValue(VL53L1_DEV Dev, + uint16_t LimitCheckId, FixPoint1616_t LimitCheckValue); + +/** + * @brief Get a specific limit check value + * + * @par Function Description + * This function get a specific limit check value from device then it updates + * internal values and check enables. + * The limit check is identified with the LimitCheckId. + * + * @note This function get the current value from device if zero then the value + * returned is the one stored by the user, but in that case the check is store + * as disabled. If the value from device is not zero, this is returned and set + * into the memory at the same way that user call VL53L1_SetLimitCheckValue() + * + * @param Dev Device Handle + * @param LimitCheckId Limit Check ID + * (0<= LimitCheckId < VL53L1_GetNumberOfLimitCheck() ). + * @param pLimitCheckValue Pointer to Limit + * check Value for a given LimitCheckId. + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetLimitCheckValue(VL53L1_DEV Dev, + uint16_t LimitCheckId, FixPoint1616_t *pLimitCheckValue); + +/** + * @brief Get the current value of the signal used for the limit check + * + * @par Function Description + * This function get a the current value of the signal used for the limit check. + * To obtain the latest value you should run a valid ranging before. + * The value reported is linked to the limit check identified with the + * LimitCheckId. + * + * @param Dev Device Handle + * @param LimitCheckId Limit Check ID + * (0<= LimitCheckId < VL53L1_GetNumberOfLimitCheck() ). + * @param pLimitCheckCurrent Pointer to current Value for a + * given LimitCheckId. + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetLimitCheckCurrent(VL53L1_DEV Dev, + uint16_t LimitCheckId, FixPoint1616_t *pLimitCheckCurrent); + +/** @} VL53L1_limitcheck_group */ + + + +/** @defgroup VL53L1_ROI_group VL53L1 ROI Functions + * @brief Functions used to select ROIs + * @{ + */ + +/** + * @brief Set the ROI to be used for ranging + * + * @par Function Description + * The user defined ROI is a rectangle described as per the following system + * from the Top Left corner to the Bottom Right corner. + *
Minimal ROI size is 4x4 spads + * @image html roi_coord.png + * + * @param Dev Device Handle + * @param pUserROi Pointer to the Structure defining the ROI + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_SetUserROI(VL53L1_DEV Dev, + VL53L1_UserRoi_t *pUserROi); + +/** + * @brief Get the ROI managed by the Device + * + * @par Function Description + * Get the ROI managed by the Device + * + * @param Dev Device Handle + * @param pUserROi Pointer to the Structure defining the ROI + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetUserROI(VL53L1_DEV Dev, + VL53L1_UserRoi_t *pUserROi); + +/** @} VL53L1_ROI_group */ + +/* \internal */ +/** @defgroup VL53L1_sequencestep_group VL53L1 Sequence Step Functions + * @brief Functions used to select Steps done on each ranging + * @{ + */ + +/** + * @brief Gets number of sequence steps managed by the API. + * + * @par Function Description + * This function retrieves the number of sequence steps currently managed + * by the API + * + * @note This function Accesses the device + * + * @param Dev Device Handle + * @param pNumberOfSequenceSteps Out parameter reporting the number of + * sequence steps. + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetNumberOfSequenceSteps(VL53L1_DEV Dev, + uint8_t *pNumberOfSequenceSteps); + +/** + * @brief Gets the name of a given sequence step. + * + * @par Function Description + * This function retrieves the name of sequence steps corresponding to + * SequenceStepId. + * + * @note This function doesn't Accesses the device + * + * @param SequenceStepId Sequence step identifier. + * @param pSequenceStepsString Pointer to Info string. Shall be + * defined as char buf[VL53L1_MAX_STRING_LENGTH] + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetSequenceStepsInfo( + VL53L1_SequenceStepId SequenceStepId, char *pSequenceStepsString); + + + +/** + * @brief Sets the (on/off) state of a requested sequence step. + * + * @par Function Description + * This function enables/disables a requested sequence step. + * + * @note This function Accesses the device + * + * @param Dev Device Handle + * @param SequenceStepId Sequence step identifier. + * @param SequenceStepEnabled Demanded state {0=Off,1=On} + * is enabled. + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_ERROR_INVALID_PARAMS Error SequenceStepId parameter not + * supported. + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_SetSequenceStepEnable(VL53L1_DEV Dev, + VL53L1_SequenceStepId SequenceStepId, uint8_t SequenceStepEnabled); + +/** + * @brief Gets the (on/off) state of a requested sequence step. + * + * @par Function Description + * This function retrieves the state of a requested sequence step, i.e. on/off. + * + * @note This function Accesses the device + * + * @param Dev Device Handle + * @param SequenceStepId Sequence step identifier. + * @param pSequenceStepEnabled Out parameter reporting if the sequence step + * is enabled {0=Off,1=On}. + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_ERROR_INVALID_PARAMS Error SequenceStepId parameter not + * supported. + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetSequenceStepEnable(VL53L1_DEV Dev, + VL53L1_SequenceStepId SequenceStepId, uint8_t *pSequenceStepEnabled); + + +/** @} VL53L1_sequencestep_group */ +/* \endinternal */ + + + +/** @defgroup VL53L1_measurement_group VL53L1 Measurement Functions + * @brief Functions used for the measurements + * @{ + */ + +/** + * @brief Start device measurement + * + * @details Started measurement will depend on preset parameters set through + * @a VL53L1_SetPreseMode() + * This function will change the VL53L1_State from VL53L1_STATE_IDLE to + * VL53L1_STATE_RUNNING. + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_ERROR_MODE_NOT_SUPPORTED This error occurs when + * PresetMode programmed with @a VL53L1_SetPresetMode + * @return VL53L1_ERROR_TIME_OUT Time out on start measurement + * @return VL53L1_ERROR_INVALID_PARAMS This error might occur in timed mode + * when inter measurement period is smaller or too close to the timing budget. + * In such case measurements are not started and user must correct the timings + * passed to @a VL53L1_SetMeasurementTimingBudgetMicroSeconds() and + * @a VL53L1_SetInterMeasurementPeriodMilliSeconds() functions. + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_StartMeasurement(VL53L1_DEV Dev); + +/** + * @brief Stop device measurement + * + * @details Will set the device in standby mode at end of current measurement\n + * Not necessary in single mode as device shall return automatically + * in standby mode at end of measurement. + * This function will change the VL53L1_State from VL53L1_STATE_RUNNING + * to VL53L1_STATE_IDLE. + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_StopMeasurement(VL53L1_DEV Dev); + +/** + * @brief Clear the Interrupt flag and start new measurement + * * + * @note This function Access to the device + * + * @param Dev Device Handle + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_ClearInterruptAndStartMeasurement(VL53L1_DEV Dev); + +/** + * @brief Return Measurement Data Ready + * + * @par Function Description + * This function indicate that a measurement data is ready. + * This function is used for non-blocking capture. + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @param pMeasurementDataReady Pointer to Measurement Data Ready. + * 0 = data not ready, 1 = data ready + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetMeasurementDataReady(VL53L1_DEV Dev, + uint8_t *pMeasurementDataReady); + +/** + * @brief Wait for measurement data ready. + * Blocking function. + * Note that the timeout is given by: + * VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS defined in def.h + * + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_ERROR_TIME_OUT In case of timeout + */ +VL53L1_Error VL53L1_WaitMeasurementDataReady(VL53L1_DEV Dev); + + +/** + * @brief Retrieve the measurements from device for a given setup + * + * @par Function Description + * Get data from last successful Ranging measurement + */ +/** + * + * @warning USER must call @a VL53L1_ClearInterruptAndStartMeasurement() prior + * to call again this function + * + * @note This function Access to the device + * + * @note The first valid value returned by this function will have a range + * status equal to VL53L1_RANGESTATUS_RANGE_VALID_NO_WRAP_CHECK which means that + * the data is valid but no wrap around check have been done. User should take + * care about that. + * + * @param Dev Device Handle + * @param pRangingMeasurementData Pointer to the data structure to fill up. + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_ERROR_MODE_NOT_SUPPORTED in case of MULTIZONES_SCANNING + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetRangingMeasurementData(VL53L1_DEV Dev, + VL53L1_RangingMeasurementData_t *pRangingMeasurementData); + + + +/** @} VL53L1_measurement_group */ + +/** @defgroup VL53L1_Calibration_group VL53L1 Calibration Functions + * @brief Functions used for Calibration + * @{ + */ + + +/** + * @brief Set Tuning Parameter value for a given parameter ID + * + * @par Function Description + * This function is used to improve the performance of the device. It permit to + * change a particular value used for a timeout or a threshold or a constant + * in an algorithm. The function will change the value of the parameter + * identified by an unique ID. + * + * @note This function doesn't Access to the device + * + * @param Dev Device Handle + * @param TuningParameterId Tuning Parameter ID + * @param TuningParameterValue Tuning Parameter Value + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_SetTuningParameter(VL53L1_DEV Dev, + uint16_t TuningParameterId, int32_t TuningParameterValue); + +/** + * @brief Get Tuning Parameter value for a given parameter ID + * + * @par Function Description + * This function is used to get the value of the parameter + * identified by an unique ID. + * + * @note This function doesn't Access to the device + * + * @param Dev Device Handle + * @param TuningParameterId Tuning Parameter ID + * @param pTuningParameterValue Pointer to Tuning Parameter Value + * for a given TuningParameterId. + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetTuningParameter(VL53L1_DEV Dev, + uint16_t TuningParameterId, int32_t *pTuningParameterValue); + +/** + * @brief Performs Reference Spad Management + * + * @par Function Description + * The reference SPAD initialization procedure determines the minimum amount + * of reference spads to be enables to achieve a target reference signal rate + * and should be performed once during initialization. + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_PerformRefSpadManagement(VL53L1_DEV Dev); + + +/** + * @brief Enable/Disable Cross talk compensation feature + * + * Enable/Disable Cross Talk correction. + * + * @param Dev Device Handle + * @param XTalkCompensationEnable Cross talk compensation + * to be set 0 = disabled or 1 = enabled. + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_SetXTalkCompensationEnable(VL53L1_DEV Dev, +uint8_t XTalkCompensationEnable); + +/** + * @brief Get Cross talk compensation rate enable + * + * Get if the Cross Talk is Enabled or Disabled. + * + * @note This function doesn't access to the device + * + * @param Dev Device Handle + * @param pXTalkCompensationEnable Pointer to the Cross talk compensation + * state 0=disabled or 1 = enabled + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetXTalkCompensationEnable(VL53L1_DEV Dev, + uint8_t *pXTalkCompensationEnable); + +/** + * @brief Perform XTalk Calibration + * + * @details Perform a XTalk calibration of the Device. + * This function will launch a ranging measurement, if interrupts + * are enabled an interrupt will be done. + * This function will clear the interrupt generated automatically. + * This function will program a new value for the XTalk compensation + * and it will enable the cross talk before exit. + * + * @warning This function is a blocking function + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @param CalDistanceMilliMeter Target distance in mm + * The calibration uses current preset and distance mode without altering them. + *
User must call @a VL53L1_SetPresetMode() with + * VL53L1_PRESETMODE_AUTONOMOUS, VL53L1_PRESETMODE_LITE_RANGING or + * VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS parameter prior to launch calibration + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_PerformSingleTargetXTalkCalibration(VL53L1_DEV Dev, + int32_t CalDistanceMilliMeter); + + + + + +/** + * @brief Perform Offset simple Calibration + * + * @details Perform a very simple offset calibration of the Device. + * This function will launch few ranging measurements and computes offset + * calibration. The preset mode and the distance mode MUST be set by the + * application before to call this function. + * + * @warning This function is a blocking function + * + * @note This function Access to the device + * + * @param Dev Device Handle + * @param CalDistanceMilliMeter Calibration distance value used for the + * offset compensation. + * + * @return VL53L1_ERROR_NONE + * @return VL53L1_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL the calibration failed by + * lack of valid measurements + * @return VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH means that the target + * distance combined to the number of loops performed in the calibration lead to + * an internal overflow. Try to reduce the distance of the target (140 mm) + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_PerformOffsetSimpleCalibration(VL53L1_DEV Dev, + int32_t CalDistanceMilliMeter); + +/** + * @brief Perform Offset simple Calibration with a "zero distance" target + * + * @details Perform a simple offset calibration of the Device. + * This function will launch few ranging measurements and computes offset + * calibration. The preset mode and the distance mode MUST be set by the + * application before to call this function. + * A target must be place very close to the device. + * Ideally the target shall be touching the coverglass. + * + * @warning This function is a blocking function + * + * @note This function Access to the device + * + * @param Dev Device Handle + * + * @return VL53L1_ERROR_NONE + * @return VL53L1_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL the calibration failed by + * lack of valid measurements + * @return VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH means that the target + * distance is too large, try to put the target closer to the device + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_PerformOffsetZeroDistanceCalibration(VL53L1_DEV Dev); + +/** + * @brief Sets the Calibration Data. + * + * @par Function Description + * This function set all the Calibration Data issued from the functions + * @a VL53L1_PerformRefSpadManagement(), @a VL53L1_PerformXTalkCalibration, + * @a VL53L1_PerformOffsetCalibration() + * + * @note This function doesn't Accesses the device + * + * @param Dev Device Handle + * @param *pCalibrationData Pointer to Calibration data to be set. + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_ERROR_INVALID_PARAMS pCalibrationData points to an older + * version of the inner structure. Need for support to convert its content. + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_SetCalibrationData(VL53L1_DEV Dev, + VL53L1_CalibrationData_t *pCalibrationData); + +/** + * @brief Gets the Calibration Data. + * + * @par Function Description + * This function get all the Calibration Data issued from the functions + * @a VL53L1_PerformRefSpadManagement(), @a VL53L1_PerformXTalkCalibration, + * @a VL53L1_PerformOffsetCalibration() + * + * @note This function doesn't Accesses the device + * + * @param Dev Device Handle + * @param *pCalibrationData pointer where to store Calibration + * data. + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetCalibrationData(VL53L1_DEV Dev, + VL53L1_CalibrationData_t *pCalibrationData); + +/** + * @brief Gets the optical center. + * + * @par Function Description + * This function get the optical center issued from the nvm set at FTM stage + * expressed in the same coordinate system as the ROI are + * + * @note This function doesn't Accesses the device + * + * @param Dev Device Handle + * @param pOpticalCenterX pointer to the X position of center + * in 16.16 fix point + * @param pOpticalCenterY pointer to the Y position of center + * in 16.16 fix point + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetOpticalCenter(VL53L1_DEV Dev, + FixPoint1616_t *pOpticalCenterX, + FixPoint1616_t *pOpticalCenterY); + +/** @} VL53L1_Calibration_group */ + +/** @defgroup VL53L1_Thresholds_group VL53L1 IRQ Triggered events Functions + * @brief Functions used to configure interrupt to be triggered only when + * a measurement satisfies some thresholds parameters + * @{ + */ + +/** + * @brief Configure the interrupt config, from the given structure + * + * @param[in] Dev : Device Handle + * @param[in] pConfig : pointer to configuration structure + */ + +VL53L1_Error VL53L1_SetThresholdConfig(VL53L1_DEV Dev, + VL53L1_DetectionConfig_t *pConfig); + +/** + * @brief Retrieves the interrupt config structure currently programmed + * into the API + * + * @param[in] Dev : Device Handle + * @param[out] pConfig : pointer to configuration structure + */ + +VL53L1_Error VL53L1_GetThresholdConfig(VL53L1_DEV Dev, + VL53L1_DetectionConfig_t *pConfig); + + +/** @} VL53L1_Thresholds_group */ + + +/** @} VL53L1_cut11_group */ + +#ifdef __cplusplus +} +#endif + +#endif /* _VL53L1_API_H_ */ diff --git a/App/VL53L1X_API/core/inc/vl53l1_api_calibration.h b/App/VL53L1X_API/core/inc/vl53l1_api_calibration.h new file mode 100644 index 0000000..f36a1fe --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_api_calibration.h @@ -0,0 +1,236 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_api_core.h + * + * @brief EwokPlus25 low level API function definitions + */ + +#ifndef _VL53L1_API_CALIBRATION_H_ +#define _VL53L1_API_CALIBRATION_H_ + +#include "vl53l1_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Run Reference Array SPAD Characterisation. + * + * This function finds the required number of reference SPAD + * to meet the input required peak reference rate. + * + * The algorithm first tries the non apertured reference SPAD's, + * if the rate is too high for the minimum allowed SPAD count (5) + * then the algo switches to 5x apertured SPAD's and if the rate + * is still to high then the 10x apertured SPAD are selected. + * + * The function reads the following results from the device and + * both caches the values in the pdev->customer structure and + * writes the data into the G02 customer register group. + * + * - num_ref_spads + * - ref_location + * - DCR SPAD enables for selected reference location + * + * Note power force is enabled as the function needs to read + * data from the Patch RAM. + * + * Should only be called once per part with coverglass attached to + * generate the required num of SPAD, Ref location and DCR SPAD enable + * data + * + * @param[in] Dev : Device Handle + * @param[out] pcal_status : Pointer to unfiltered calibration status + * + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS + * Less than 5 Good SPAD available, output not valid + * @return VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH + * At end of search reference rate > 40.0 Mcps + * Offset stability may be degraded. + * @return VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW + * At end of search reference rate < 10.0 Mcps + * Offset stability may be degraded. + * + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_run_ref_spad_char(VL53L1_DEV Dev, VL53L1_Error *pcal_status); +#endif + + +/** + * @brief Runs the input Device Test + * + * Calls + * + * - VL53L1_enable_powerforce() + * - VL53L1_start_test() + * - VL53L1_poll_for_range_completion() + * + * @param[in] Dev : Device handle + * @param[in] device_test_mode : Device test mode register value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_run_device_test( + VL53L1_DEV Dev, + VL53L1_DeviceTestMode device_test_mode); +#endif + + +/** + * @brief Runs SPAD rate map + * + * Output structure contains SPAD rate data in SPAD number order + * + * @param[in] Dev : Device handle + * @param[in] device_test_mode : Device test mode register value. + * Valid options: \n + * - VL53L1_DEVICETESTMODE_LCR_VCSEL_OFF \n + * - VL53L1_DEVICETESTMODE_LCR_VCSEL_ON + * @param[in] array_select : Device SPAD array select + * Valid options: \n + * - VL53L1_DEVICESSCARRAY_RTN \n + * - VL53L1_DEVICESSCARRAY_REF + * @param[in] ssc_config_timeout_us : SSC timeout in [us] e.g 36000us + * @param[out] pspad_rate_data : pointer to output rates structure + * 1.15 format for LCR_VCSEL_OFF + * 9.7 format for LCR_VCSEL_ON + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_run_spad_rate_map( + VL53L1_DEV Dev, + VL53L1_DeviceTestMode device_test_mode, + VL53L1_DeviceSscArray array_select, + uint32_t ssc_config_timeout_us, + VL53L1_spad_rate_data_t *pspad_rate_data); +#endif + + +/** + * @brief Run offset calibration + * + * Runs the standard ranging MM1 and MM2 calibration presets + * to generate the MM1 and MM2 range offset data + * + * The range config timeout is used for both MM1 and MM2 so that + * the sigma delta settling is the same as for the 'real' range + * + * Places results into VL53L1_customer_nvm_managed_t within pdev + * + * Use VL53L1_get_part_to_part_data() to get the offset calibration + * results + * + * Current FMT settings: + * + * - offset_calibration_mode = VL53L1_OFFSETCALIBRATIONMODE__STANDARD_RANGING + * - dss_config__target_total_rate_mcps = 0x0A00 (20.0Mcps) to 0x1400 (40.0Mcps) + * - phasecal_config_timeout_us = 1000 + * - range_config_timeout_us = 13000 + * - pre_num_of_samples = 32 + * - mm1_num_of_samples = 100 + * - mm2_range_num_of_samples = 64 + * - target_distance_mm = 140 mm + * - target reflectance = 5% + * + * Note: function parms simplified as part of Patch_CalFunctionSimplification_11791 + * + * @param[in] Dev : Device handle + * @param[in] cal_distance_mm : Distance to target in [mm] - the ground truth + * @param[out] pcal_status : Pointer to unfiltered calibration status + * + * @return VL53L1_ERROR_NONE Success + * @return VL53L1_WARNING_OFFSET_CAL_INSUFFICIENT_MM1_SPADS + * Effective MM1 SPAD count too low (<5.0). + * Out with recommended calibration condition. + * Accuracy of offset calibration may be degraded. + * @return VL53L1_WARNING_OFFSET_CAL_PRE_RANGE_RATE_TOO_HIGH + * Pre range too high (>40.0) in pile up region. + * Out with recommended calibration condition. + * Accuracy of offset calibration may be degraded. + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_run_offset_calibration( + VL53L1_DEV Dev, + int16_t cal_distance_mm, + VL53L1_Error *pcal_status); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _VL53L1_API_CALIBRATION_H_ */ diff --git a/App/VL53L1X_API/core/inc/vl53l1_api_core.h b/App/VL53L1X_API/core/inc/vl53l1_api_core.h new file mode 100644 index 0000000..8452d86 --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_api_core.h @@ -0,0 +1,1183 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_api_core.h + * + * @brief EwokPlus25 low level API function definitions + */ + +#ifndef _VL53L1_API_CORE_H_ +#define _VL53L1_API_CORE_H_ + +#include "vl53l1_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Get LL Driver version information + * + * @param[in] Dev : Device handle + * @param[out] pversion : pointer to VL53L1_ll_version_t + * + * @return VL53L1_ERROR_NONE Success + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_version( + VL53L1_DEV Dev, + VL53L1_ll_version_t *pversion); + +/** + * @brief Gets Device Firmware version + * + * @param[in] Dev : Device handle + * @param[out] pfw_version : pointer to uint16_t FW version + * + * @return VL53L1_ERROR_NONE Success + */ + +VL53L1_Error VL53L1_get_device_firmware_version( + VL53L1_DEV Dev, + uint16_t *pfw_version); +#endif + + +/** + * @brief Initialises pdev structure and optionally read the + * part to part information form he device G02 registers + * + * Important: VL53L1_platform_initialise() *must* called before calling + * this function + * + * @param[in] Dev : Device handle + * @param[out] read_p2p_data : if > 0 then reads and caches P2P data + * + * @return VL53L1_ERROR_NONE Success + */ + +VL53L1_Error VL53L1_data_init( + VL53L1_DEV Dev, + uint8_t read_p2p_data); + + +/** + * @brief For C-API one time initialization only reads device + * G02 registers containing data copied from NVM + * + * Contains the key NVM data e.g identification info + * fast oscillator freq, max trim and laser safety info + * + * Function all only be called after the device has finished booting + * + * @param[in] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + */ + +VL53L1_Error VL53L1_read_p2p_data( + VL53L1_DEV Dev); + + +/** + * @brief Performs device software reset and then waits for the firmware + * to finish booting + * + * @param[in] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_software_reset( + VL53L1_DEV Dev); + + +/** + * @brief Sets the customer part to part data + * + * Important: does **not** apply the settings to the device. + * Updates the following structures in the device structure + * + * Just an internal memcpy to + * + * + * @param[in] Dev : Device handle + * @param[in] pcal_data : pointer to VL53L1_calibration_data_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_part_to_part_data( + VL53L1_DEV Dev, + VL53L1_calibration_data_t *pcal_data); + + +/** + * @brief Gets the customer part to part data + * + * Just an internal memory copy + * + * @param[in] Dev : Device handle + * @param[out] pcal_data : pointer to VL53L1_calibration_data_t + * + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_part_to_part_data( + VL53L1_DEV Dev, + VL53L1_calibration_data_t *pcal_data); + + +/** + * @brief Gets the tuning parm part to part data + * + * Just an internal copy + * + * @param[in] Dev : Device handle + * @param[out] ptun_data : pointer to VL53L1_tuning_parameters_t + * + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_tuning_debug_data( + VL53L1_DEV Dev, + VL53L1_tuning_parameters_t *ptun_data); +#endif + + +/** + * @brief Sets the inter measurement period in the VL53L1_timing_config_t structure + * + * Uses the pdev->dbg_results.result__osc_calibrate_val value convert from [ms] + * + * @param[in] Dev : Device handle + * @param[in] inter_measurement_period_ms : requested inter measurement period in [ms] + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_inter_measurement_period_ms( + VL53L1_DEV Dev, + uint32_t inter_measurement_period_ms); + + +/** + * @brief Gets inter measurement period from the VL53L1_timing_config_t structure + * + * Uses the pdev->dbg_results.result__osc_calibrate_val value convert into [ms] + * + * @param[in] Dev : Device handle + * @param[out] pinter_measurement_period_ms : current inter measurement period in [ms] + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_inter_measurement_period_ms( + VL53L1_DEV Dev, + uint32_t *pinter_measurement_period_ms); + + +/** + * @brief Sets the phasecal, mode mitigation and ranging timeouts + * in the VL53L1_timing_config_t structure + * + * Uses the pdev->stat_nvm.osc_measured__fast_osc__frequency value convert from [us] + * + * @param[in] Dev : Device handle + * @param[in] phasecal_config_timeout_us : requested Phase Cal Timeout e.g. 1000us + * @param[in] mm_config_timeout_us : requested MM Timeout e.g. 2000us + * @param[in] range_config_timeout_us : requested Ranging Timeout e.g 13000us + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_timeouts_us( + VL53L1_DEV Dev, + uint32_t phasecal_config_timeout_us, + uint32_t mm_config_timeout_us, + uint32_t range_config_timeout_us); + + +/** + * @brief Gets the phasecal, mode mitigation and ranging timeouts + * for the VL53L1_timing_config_t structure + * + * Uses the pdev->stat_nvm.osc_measured__fast_osc__frequency convert into [us] + * + * @param[in] Dev : Device handle + * @param[out] pphasecal_config_timeout_us : current Phase Cal Timeout in [us] + * @param[out] pmm_config_timeout_us : current MM Timeout in [us] + * @param[out] prange_config_timeout_us : current Ranging Timeout in [us] + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_timeouts_us( + VL53L1_DEV Dev, + uint32_t *pphasecal_config_timeout_us, + uint32_t *pmm_config_timeout_us, + uint32_t *prange_config_timeout_us); + + +/** + * @brief Sets the 12-bit calibration repeat period value + * + * Sets the repeat period for VHV and phasecal in ranges. + * Setting to zero to disables the repeat, but the VHV + * and PhaseCal is still run on the very first range in + * this case. + * + * Only even values should be set + * + * The max value is 4094 i.e. every + * + * @param[in] Dev : Device handle + * @param[in] cal_config__repeat_period : current calibration config repeat period + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_calibration_repeat_period( + VL53L1_DEV Dev, + uint16_t cal_config__repeat_period); + + +/** + * @brief Gets the current 12-bit calibration repeat period value + * + * @param[in] Dev : Device handle + * @param[out] pcal_config__repeat_period : current calibration config repeat period + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_calibration_repeat_period( + VL53L1_DEV Dev, + uint16_t *pcal_config__repeat_period); + + +/** + * @brief Set system sequence config bit value + * + * @param[in] Dev : Device handle + * @param[in] bit_id : VL53L1_DeviceSequenceConfig bit id + * @param[in] value : Input Bit value = 0 or 1 + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_sequence_config_bit( + VL53L1_DEV Dev, + VL53L1_DeviceSequenceConfig bit_id, + uint8_t value); + + +/** + * @brief Get system sequence config bit value + * + * @param[in] Dev : Device handle + * @param[in] bit_id : VL53L1_DeviceSequenceConfig bit id + * @param[out] pvalue : Output Bit value = 0 or 1 + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_sequence_config_bit( + VL53L1_DEV Dev, + VL53L1_DeviceSequenceConfig bit_id, + uint8_t *pvalue); + + +/** + * @brief Set the interrupt polarity bit in + * + * @param[in] Dev : Device handle + * @param[in] interrupt_polarity : Interrupt Polarity + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_interrupt_polarity( + VL53L1_DEV Dev, + VL53L1_DeviceInterruptPolarity interrupt_polarity); + + +/** + * @brief Get the interrupt polarity bit state + * + * @param[in] Dev : Device handle + * @param[out] pinterrupt_polarity : Interrupt Polarity Bit value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_interrupt_polarity( + VL53L1_DEV Dev, + VL53L1_DeviceInterruptPolarity *pinterrupt_polarity); + +/** + * @brief Set the Ref spad char cfg struct internal to pdev + * + * @param[in] Dev : Device handle + * @param[in] pdata : Input pointer to VL53L1_refspadchar_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_get_refspadchar_config_struct( + VL53L1_DEV Dev, + VL53L1_refspadchar_config_t *pdata); +#endif + +/** + * @brief Extract the Ref spad char cfg struct from pdev + * + * @param[in] Dev : Device handle + * @param[out] pdata : Output pointer to VL53L1_refspadchar_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_set_refspadchar_config_struct( + VL53L1_DEV Dev, + VL53L1_refspadchar_config_t *pdata); +#endif + +/** + * @brief Set the Range Ignore Threshold Rate value + * + * @param[in] Dev : Device handle + * @param[in] range_ignore_thresh_mult : Input RIT Mult value, in \ + * 3.5 fractional value + * @param[in] range_ignore_threshold_mcps : Range Ignore Threshold value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_range_ignore_threshold( + VL53L1_DEV Dev, + uint8_t range_ignore_thresh_mult, + uint16_t range_ignore_threshold_mcps); + +/** + * @brief Get the Range Ignore Threshold Rate value + * + * + * + * @param[in] Dev : Device handle + * @param[out] prange_ignore_thresh_mult : \ + * Range ignore threshold internal multiplier value in \ + * 3.5 fractional format. + * @param[out] prange_ignore_threshold_mcps_internal : \ + * Range Ignore Threshold Rate value generated from \ + * current xtalk parms + * @param[out] prange_ignore_threshold_mcps_current : \ + * Range Ignore Threshold Rate value generated from \ + * device static config struct + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_range_ignore_threshold( + VL53L1_DEV Dev, + uint8_t *prange_ignore_thresh_mult, + uint16_t *prange_ignore_threshold_mcps_internal, + uint16_t *prange_ignore_threshold_mcps_current); + + +/** + * @brief Sets the current user Zone (ROI) configuration structure data + * + * @param[in] Dev : Device handle + * @param[in] puser_zone : pointer to user Zone (ROI) data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_user_zone( + VL53L1_DEV Dev, + VL53L1_user_zone_t *puser_zone); + + +/** + * @brief Gets the current user zone (ROI) configuration structure data + * + * @param[in] Dev : Device handle + * @param[out] puser_zone : pointer to user zone (ROI) data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_user_zone( + VL53L1_DEV Dev, + VL53L1_user_zone_t *puser_zone); + + +/** + * @brief Gets the current mode mitigation zone (ROI) configuration structure data + * + * @param[in] Dev : Device handle + * @param[out] pmm_roi : pointer to user zone (ROI) data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_mode_mitigation_roi( + VL53L1_DEV Dev, + VL53L1_user_zone_t *pmm_roi); + + +/** + * @brief Initialises the configuration data structures for + * the selected preset mode + * + * Important: does **not** apply the settings to the device. + * Updates the following structures in the device structure + * + * - static config : pdev->stat_cfg + * - dynamic config : pdev->dyn_cfg + * - system_control :pdev->sys_ctrl + * + * Uses osc_measured__fast_osc__frequency in pdev->stat_nvm to + * convert the input timeouts in [us] to internal macro period + * timeout values. + * + * Please call VL53L1_init_and_start_range() to update device + * and start a range + * + * @param[in] Dev : Device handle + * @param[in] device_preset_mode : selected device preset mode + * @param[in] dss_config__target_total_rate_mcps : DSS target rate in 9.7 format e.g 0x0A00 -> 20.0 Mcps + * @param[in] phasecal_config_timeout_us : requested Phase Cal Timeout e.g. 1000us + * @param[in] mm_config_timeout_us : requested MM Timeout e.g. 2000us + * @param[in] range_config_timeout_us : requested Ranging Timeout e.g 10000us + * @param[in] inter_measurement_period_ms : requested timed mode repeat rate e.g 100ms + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_preset_mode( + VL53L1_DEV Dev, + VL53L1_DevicePresetModes device_preset_mode, + uint16_t dss_config__target_total_rate_mcps, + uint32_t phasecal_config_timeout_us, + uint32_t mm_config_timeout_us, + uint32_t range_config_timeout_us, + uint32_t inter_measurement_period_ms); + + +/** + * @brief Gets the requested preset mode configuration tuning parameters + * + * Function Added as part of Patch_TuningParmPresetModeAddition_11839 + * + * @param[in] Dev : Device Handle + * @param[in] device_preset_mode : selected device preset mode + * @param[out] pdss_config__target_total_rate_mcps : dss rate output value + * @param[out] pphasecal_config_timeout_us : phasecal timeout output value + * @param[out] pmm_config_timeout_us : mm timeout output value + * @param[out] prange_config_timeout_us : range timeout output value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_preset_mode_timing_cfg( + VL53L1_DEV Dev, + VL53L1_DevicePresetModes device_preset_mode, + uint16_t *pdss_config__target_total_rate_mcps, + uint32_t *pphasecal_config_timeout_us, + uint32_t *pmm_config_timeout_us, + uint32_t *prange_config_timeout_us); + +/** + * @brief Simple function to enable xtalk compensation + * + * Applies xtalk compensation to hist post processing, + * and applies settings to device, + * + * @param[in] Dev : Device Handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_enable_xtalk_compensation( + VL53L1_DEV Dev); + +/** + * @brief Simple function to disable xtalk compensation + * + * Disables xtalk compensation from hist post processing, + * and clears settings to device + * + * @param[in] Dev : Device Handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_disable_xtalk_compensation( + VL53L1_DEV Dev); + + +/** + * @brief Simple function to retrieve xtalk compensation + * status + * + * @param[in] Dev : Device Handle + * @param[out] pcrosstalk_compensation_enable : pointer to \ + * uint8 type, returns crosstalk compensation status \ + * where 0 means disabled and 1 means enabled. + * + */ + +void VL53L1_get_xtalk_compensation_enable( + VL53L1_DEV Dev, + uint8_t *pcrosstalk_compensation_enable); + +/** + * @brief Builds and sends the I2C buffer to initialize the device + * and start a range measurement + * + * The device_config_level input controls the level of initialization + * applied to the device + * + * - System control only + * - Dynamic Onwards + * - dynamic_config and system_control + * - Static Onwards + * - static_config, dynamic_config & system_control + * - software standby mode only + * - Customer Onwards + * - customer_nvm_managed, static_config, dynamic_config & system_control + * - software standby mode only + * - Full + * - static_nvm_managed, customer_nvm_managed, static_config, dynamic_config & system_control + * - software standby mode only + * + * The system_control register group is always written as the last + * register of this group SYSTEM__MODE_START decides what happens next ... + * + * @param[in] Dev : Device handle + * @param[in] measurement_mode : Options: \n + * VL53L1_DEVICEMEASUREMENTMODE_STOP \n + * VL53L1_DEVICEMEASUREMENTMODE_SINGLESHOT \n + * VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK \n + * VL53L1_DEVICEMEASUREMENTMODE_TIMED + * @param[in] device_config_level : Options: \n + * VL53L1_DEVICECONFIGLEVEL_SYSTEM_CONTROL \n + * VL53L1_DEVICECONFIGLEVEL_DYNAMIC_ONWARDS \n + * VL53L1_DEVICECONFIGLEVEL_TIMING_ONWARDS \n + * VL53L1_DEVICECONFIGLEVEL_STATIC_ONWARDS \n + * VL53L1_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS \n + * VL53L1_DEVICECONFIGLEVEL_FULL + * + * The system_control register group is always written as the last + * register of this group SYSTEM__MODE_START decides what happens next .. + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_init_and_start_range( + VL53L1_DEV Dev, + uint8_t measurement_mode, + VL53L1_DeviceConfigLevel device_config_level); + + +/** + * @brief Sends an abort command to stop the in progress range. + * Also clears all of the measurement mode bits. + * + * @param[in] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_stop_range( + VL53L1_DEV Dev); + + +/** + * @brief Get range measurement result data + * + * Reads the required number of registers as single multi byte read + * transaction and decodes the data into the data structures + * + * range_result_level controls which result data is read back from the + * device + * + * - Full + * - both system and core results are read back + * - System Results + * - only system results are read back + * - only the system_results structure is updated in this case + * + * @param[in] Dev : Device Handle + * @param[in] device_result_level : Options: \n + * VL53L1_DEVICERESULTSLEVEL_FULL \n + * VL53L1_DEVICERESULTSLEVEL_UPTO_CORE \n + * VL53L1_DEVICERESULTSLEVEL_SYSTEM_RESULTS + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_measurement_results( + VL53L1_DEV Dev, + VL53L1_DeviceResultsLevel device_result_level); + + +/** + * @brief Get device system results, updates GPH registers and + * clears interrupt and configures SYSTEM__MODE_START + * based on the input measurement mode + * + * Internally uses the following functions: + * + * - VL53L1_get_measurement_results() + * - VLS3L1_init_and_start_range() + * + * The system_control register group is always written as the last + * register of this group SYSTEM__MODE_START decides what happens next ... + * + * @param[in] Dev : Device Handle + * @param[in] device_result_level : Options: \n + * VL53L1_DEVICERESULTSLEVEL_FULL \n + * VL53L1_DEVICERESULTSLEVEL_UPTO_CORE \n + * VL53L1_DEVICERESULTSLEVEL_SYSTEM_RESULTS + * @param[out] prange_results : pointer to VL53L1_range_results_t + + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_device_results( + VL53L1_DEV Dev, + VL53L1_DeviceResultsLevel device_result_level, + VL53L1_range_results_t *prange_results); + + +/** + * @brief Sends the ranging handshake to clear the interrupt + * allow the device to move onto the next range + * + * updates GPH registers and clears interrupt and configures + * SYSTEM__MODE_START register based on the input measurement mode + * + * Internally uses the following functions: + * + * - VLS3L1_init_and_start_range() + * + * The system_control register group is always written as the last + * register of this group SYSTEM__MODE_START decides what happens next ... + * + * @param[in] Dev : Device Handle + * @param[in] measurement_mode : Options: \n + * VL53L1_DEVICEMEASUREMENTMODE_STOP \n + * VL53L1_DEVICEMEASUREMENTMODE_SINGLESHOT \n + * VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK \n + * VL53L1_DEVICEMEASUREMENTMODE_TIMED + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_clear_interrupt_and_enable_next_range( + VL53L1_DEV Dev, + uint8_t measurement_mode); + + +/** + * @brief Copies system and core results to range results data structure + * + * @param[in] gain_factor : gain correction factor 1.11 format + * @param[in] psys : pointer to VL53L1_system_results_t + * @param[in] pcore : pointer to VL53L1_core_results_t + * @param[out] presults : pointer to VL53L1_range_results_t + */ + +void VL53L1_copy_sys_and_core_results_to_range_results( + int32_t gain_factor, + VL53L1_system_results_t *psys, + VL53L1_core_results_t *pcore, + VL53L1_range_results_t *presults); + +/** + * @brief Configure the GPIO interrupt config, from the given input + * + * @param[in] Dev : Device Handle + * @param[in] intr_mode_distance : distance interrupt mode + * @param[in] intr_mode_rate : rate interrupt mode + * @param[in] intr_new_measure_ready : trigger when new interrupt ready + * @param[in] intr_no_target : trigger when no target found + * @param[in] intr_combined_mode : switch on combined mode + * @param[in] thresh_distance_high : High distance threshold in mm + * @param[in] thresh_distance_low : Low distance threshold in mm + * @param[in] thresh_rate_high : High rate threshold in 9.7 Mcps + * @param[in] thresh_rate_low : Low rate threshold in 9.7 Mcps + */ + +VL53L1_Error VL53L1_set_GPIO_interrupt_config( + VL53L1_DEV Dev, + VL53L1_GPIO_Interrupt_Mode intr_mode_distance, + VL53L1_GPIO_Interrupt_Mode intr_mode_rate, + uint8_t intr_new_measure_ready, + uint8_t intr_no_target, + uint8_t intr_combined_mode, + uint16_t thresh_distance_high, + uint16_t thresh_distance_low, + uint16_t thresh_rate_high, + uint16_t thresh_rate_low + ); + +/** + * @brief Configure the GPIO interrupt config, from the given structure + * + * @param[in] Dev : Device Handle + * @param[in] intconf : input structure (note, not a pointer) + */ + +VL53L1_Error VL53L1_set_GPIO_interrupt_config_struct( + VL53L1_DEV Dev, + VL53L1_GPIO_interrupt_config_t intconf); + +/** + * @brief Retrieves the GPIO interrupt config structure currently programmed + * into the API + * + * @param[in] Dev : Device Handle + * @param[out] pintconf : output pointer to structure (note, pointer) + */ + +VL53L1_Error VL53L1_get_GPIO_interrupt_config( + VL53L1_DEV Dev, + VL53L1_GPIO_interrupt_config_t *pintconf); + +/** + * @brief Set function for offset calibration mode + * + * @param[in] Dev : Device Handle + * @param[in] offset_cal_mode : input calibration mode + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_offset_calibration_mode( + VL53L1_DEV Dev, + VL53L1_OffsetCalibrationMode offset_cal_mode); + + +/** + * @brief Get function for offset calibration mode + * + * @param[in] Dev : Device Handle + * @param[out] poffset_cal_mode : output pointer for calibration mode + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_offset_calibration_mode( + VL53L1_DEV Dev, + VL53L1_OffsetCalibrationMode *poffset_cal_mode); + + +/** + * @brief Set function for offset correction mode + * + * @param[in] Dev : Device Handle + * @param[in] offset_cor_mode : input correction mode + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_offset_correction_mode( + VL53L1_DEV Dev, + VL53L1_OffsetCalibrationMode offset_cor_mode); + + +/** + * @brief Get function for offset correction mode + * + * @param[in] Dev : Device Handle + * @param[out] poffset_cor_mode : output pointer for correction mode + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_offset_correction_mode( + VL53L1_DEV Dev, + VL53L1_OffsetCorrectionMode *poffset_cor_mode); + +/** + * @brief Get function for Xtalk Margin setting + * Histogram Mode version + * + * @param[in] Dev : Device Handle + * @param[out] pxtalk_margin : output pointer for int16_t xtalk_margin factor \ + * in fixed point 7.9 Kcps. + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_lite_xtalk_margin_kcps( + VL53L1_DEV Dev, + int16_t *pxtalk_margin); + +/** + * @brief Set function for Xtalk Margin setting + * Histogram Mode version + * + * @param[in] Dev : Device Handle + * @param[in] xtalk_margin : Input int16_t xtalk_margin factor \ + * in fixed point 7.9 Kcps. + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_lite_xtalk_margin_kcps( + VL53L1_DEV Dev, + int16_t xtalk_margin); + +/** + * @brief Get function for Lite Mode Minimum Count Rate + * parameter, used to filter and validate ranges based on + * signal rate + * + * Note: the min count rate value is overwritten when setting preset + * modes, and should only be altered after preset mode has been + * selected when running Lite Mode. + * + * @param[in] Dev : Device Handle + * @param[out] plite_mincountrate : Output pointer for uint16_t min count rate\ + * in fixed point 9.7 Mcps + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_lite_min_count_rate( + VL53L1_DEV Dev, + uint16_t *plite_mincountrate); + + +/** + * @brief Set function for Lite Mode Minimum Count Rate + * parameter, used to filter and validate ranges based on + * signal rate + * + * Note: the min count rate value is overwritten when setting preset + * modes, and should only be altered after preset mode has been + * selected when running Lite Mode. + * + * @param[in] Dev : Device Handle + * @param[in] lite_mincountrate : Input uint16_t min count rate + * in fixed point 9.7 Mcps + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_lite_min_count_rate( + VL53L1_DEV Dev, + uint16_t lite_mincountrate); + + +/** + * @brief Get function for Lite Mode Max Sigma Threshold + * parameter, used to filter and validate ranges based on + * estimated sigma level + * + * Note: the sigma thresh value is overwritten when setting preset + * modes, and should only be altered after preset mode has been + * selected when running Lite Mode. + * + * @param[in] Dev : Device Handle + * @param[out] plite_sigma : Output pointer for uint16_t sigma thresh\ + * in fixed point 14.2 mm + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + + +VL53L1_Error VL53L1_get_lite_sigma_threshold( + VL53L1_DEV Dev, + uint16_t *plite_sigma); + + +/** + * @brief Set function for Lite Mode Max Sigma Threshold + * parameter, used to filter and validate ranges based on + * estimated sigma level + * + * Note: the sigma thresh value is overwritten when setting preset + * modes, and should only be altered after preset mode has been + * selected when running Lite Mode. + * + * @param[in] Dev : Device Handle + * @param[in] lite_sigma : Input uint16_t sigma thresh\ + * in fixed point 14.2 mm + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_lite_sigma_threshold( + VL53L1_DEV Dev, + uint16_t lite_sigma); + + +/** + * @brief Function to restore the plane_offset, x gradient and y gradient + * values to original NVM values. + * + * This function does not recalculate all xtalk parms derived from the + * rates in question. In order to ensure correct ranging, a call to + * VL53L1_enable_xtalk_compensation should always be called prior + * to starting the ranging process. + * + * @param[in] Dev : Device Handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_restore_xtalk_nvm_default( + VL53L1_DEV Dev); + +/** + * @brief Set function for VHV Config values + * sets two parms into individual internal byte + * + * init_en - enables use of the init value instead of latest setting + * init_value - custom vhv setting or populated from nvm + * + * @param[in] Dev : Device Handle + * @param[in] vhv_init_en : input init_en setting + * @param[in] vhv_init_value : input vhv custom value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_vhv_config( + VL53L1_DEV Dev, + uint8_t vhv_init_en, + uint8_t vhv_init_value); + +/** + * @brief Get function for VHV Config values + * extracts two parms from individual internal byte + * + * init_en - enables use of the init value instead of latest setting + * init_value - custom vhv setting or populated from nvm + * + * @param[in] Dev : Device Handle + * @param[out] pvhv_init_en : Output pointer to uint8_t value + * @param[out] pvhv_init_value : Output pointer to uint8_t value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_vhv_config( + VL53L1_DEV Dev, + uint8_t *pvhv_init_en, + uint8_t *pvhv_init_value); + +/** + * @brief Set function for VHV loopbound config + * + * Loopbound sets the number of +/- vhv settings to try + * around the vhv init value during vhv search + * i.e. if init_value = 10 and loopbound = 2 + * vhv search will run from 10-2 to 10+2 + * 8 to 12. + * + * @param[in] Dev : Device Handle + * @param[in] vhv_loopbound : input loopbound value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_vhv_loopbound( + VL53L1_DEV Dev, + uint8_t vhv_loopbound); + +/** + * @brief Get function for VHV loopbound config + * + * Loopbound sets the number of +/- vhv settings to try + * around the vhv init value during vhv search + * i.e. if init_value = 10 and loopbound = 2 + * vhv search will run from 10-2 to 10+2 + * 8 to 12. + * + * @param[in] Dev : Device Handle + * @param[out] pvhv_loopbound : pointer to byte to extract loopbound + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_vhv_loopbound( + VL53L1_DEV Dev, + uint8_t *pvhv_loopbound); + +/** + * @brief Generic Tuning Parameter extraction function + * + * User passes a key input to retrieve a specific tuning parameter + * value, this will be cast to the int32_t type and output via + * the ptuning_parm_value pointer + * + * If the key does not match any tuning parameter, status is returned + * with VL53L1_ERROR_INVALID_PARAMS + * + * Patch_AddedTuningParms_11761 + * + * @param[in] Dev : Device Handle + * @param[in] tuning_parm_key : Key value to access specific tuning parm + * @param[out] ptuning_parm_value : Pointer to output int32_t type, retrieves \ + * requested tuning parm + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_tuning_parm( + VL53L1_DEV Dev, + VL53L1_TuningParms tuning_parm_key, + int32_t *ptuning_parm_value); + +/** + * @brief Generic Tuning Parameter set function + * + * User passes a key input to set a specific tuning parameter + * value, this will be cast to the internal data type from the + * input int32_t data type. + * + * If the key does not match any tuning parameter, status is returned + * with VL53L1_ERROR_INVALID_PARAMS + * + * Patch_AddedTuningParms_11761 + * + * @param[in] Dev : Device Handle + * @param[in] tuning_parm_key : Key value to access specific tuning parm + * @param[in] tuning_parm_value : Input tuning parm value of int32_t type, \ + * sets requested tuning parm. + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_tuning_parm( + VL53L1_DEV Dev, + VL53L1_TuningParms tuning_parm_key, + int32_t tuning_parm_value); + + +#ifdef __cplusplus +} +#endif + +#endif /* _VL53L1_API_CORE_H_ */ diff --git a/App/VL53L1X_API/core/inc/vl53l1_api_debug.h b/App/VL53L1X_API/core/inc/vl53l1_api_debug.h new file mode 100644 index 0000000..3782cfb --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_api_debug.h @@ -0,0 +1,354 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_api_debug.h + * + * @brief EwokPlus25 low level API function definitions + */ + +#ifndef _VL53L1_API_DEBUG_H_ +#define _VL53L1_API_DEBUG_H_ + +#include "vl53l1_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/* Start Patch_AdditionalDebugData_11823 */ + +/** + * @brief Gets the current LL Driver configuration parameters and the last + * set of histogram data for debug + * + * @param[in] Dev : Device Handle + * @param[out] pdata : pointer to VL53L1_additional_data_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_additional_data( + VL53L1_DEV Dev, + VL53L1_additional_data_t *pdata); + +/* End Patch_AdditionalDebugData_11823 */ + + +#ifdef VL53L1_LOG_ENABLE + +/** + * @brief Implements an sprintf function for signed fixed point numbers + * + * @param[in] fp_value : input signed fixed point number + * @param[in] frac_bits : number of fixed point fractional bits + * @param[in] buf_size : size of supplied text buffer + * @param[out] pbuffer : pointer to text buffer + * + */ + +void VL53L1_signed_fixed_point_sprintf( + int32_t fp_value, + uint8_t frac_bits, + uint16_t buf_size, + char *pbuffer); + + +/** + * @brief Convenience function to print out VL53L1_static_nvm_managed_t for debug + * + * @param[in] pdata : pointer to VL53L1_static_nvm_managed_t + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_static_nvm_managed( + VL53L1_static_nvm_managed_t *pdata, + char *pprefix, + uint32_t trace_flags); + + +/** + * @brief Convenience function to print out VL53L1_customer_nvm_managed_t for debug + * + * @param[in] pdata : pointer to VL53L1_customer_nvm_managed_t + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_customer_nvm_managed( + VL53L1_customer_nvm_managed_t *pdata, + char *pprefix, + uint32_t trace_flags); + + +/** + * @brief Convenience function to print out VL53L1_nvm_copy_data_t for debug + * + * @param[in] pdata : pointer to VL53L1_nvm_copy_data_t + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_nvm_copy_data( + VL53L1_nvm_copy_data_t *pdata, + char *pprefix, + uint32_t trace_flags); + + +/** + * @brief Convenience function to print out the contents of + * the Range Results structure for debug + * + * @param[in] pdata : pointer to a VL53L1_range_results_t structure + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_range_results( + VL53L1_range_results_t *pdata, + char *pprefix, + uint32_t trace_flags); + +/** + * @brief Convenience function to print out the contents of + * the Range Data structure for debug + * + * @param[in] pdata : pointer to a VL53L1_range_data_t structure + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_range_data( + VL53L1_range_data_t *pdata, + char *pprefix, + uint32_t trace_flags); + +/** + * @brief Convenience function to print out the contents of + * the offset range results structure for debug + * + * @param[in] pdata : pointer to a VL53L1_offset_range_results_t structure + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_offset_range_results( + VL53L1_offset_range_results_t *pdata, + char *pprefix, + uint32_t trace_flags); + +/** + * @brief Convenience function to print out the contents of + * the offset range data structure for debug + * + * @param[in] pdata : pointer to a VL53L1_offset_range_data_t structure + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_offset_range_data( + VL53L1_offset_range_data_t *pdata, + char *pprefix, + uint32_t trace_flags); + + +/** + * @brief Convenience function to print out the contents of + * the peak rate map calibration data structure + * + * @param[in] pdata : pointer to a VL53L1_cal_peak_rate_map_t structure + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_cal_peak_rate_map( + VL53L1_cal_peak_rate_map_t *pdata, + char *pprefix, + uint32_t trace_flags); + + +/** + * @brief Convenience function to print out the contents of + * the additional offset calibration data structure + * + * @param[in] pdata : pointer to a VL53L1_additional_offset_cal_data_t structure + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_additional_offset_cal_data( + VL53L1_additional_offset_cal_data_t *pdata, + char *pprefix, + uint32_t trace_flags); + +/** + * @brief Convenience function to print out the contents of + * the additional data structure + * + * @param[in] pdata : pointer to a VL53L1_additional_data_t structure + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_additional_data( + VL53L1_additional_data_t *pdata, + char *pprefix, + uint32_t trace_flags); + + +/** + * @brief Convenience function to print out the contents of + * the LL driver gain calibration data structure + * + * @param[in] pdata : pointer to a VL53L1_gain_calibration_data_t structure + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_gain_calibration_data( + VL53L1_gain_calibration_data_t *pdata, + char *pprefix, + uint32_t trace_flags); + + +/** + * @brief Convenience function to print out the contents of + * the xtalk configuration data for debug + * + * @param[in] pdata : pointer to a VL53L1_xtalk_config_t Structure + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_xtalk_config( + VL53L1_xtalk_config_t *pdata, + char *pprefix, + uint32_t trace_flags); + +/** + * @brief Convenience function to print out the contents of + * the Optical Centre structure for debug + * + * @param[in] pdata : pointer to a VL53L1_optical_centre_t structure + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_optical_centre( + VL53L1_optical_centre_t *pdata, + char *pprefix, + uint32_t trace_flags); + + +/** + * @brief Convenience function to print out the contents of + * the User Zone (ROI) structure for debug + * + * @param[in] pdata : pointer to a VL53L1_user_zone_t structure + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_user_zone( + VL53L1_user_zone_t *pdata, + char *pprefix, + uint32_t trace_flags); + +/** + * @brief Convenience function for printing out VL53L1_spad_rate_data_t + * + * @param[in] pspad_rates : pointer to VL53L1_spad_rate_data_t + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_spad_rate_data( + VL53L1_spad_rate_data_t *pspad_rates, + char *pprefix, + uint32_t trace_flags); + + +/** + * @brief Convenience function for printing out VL53L1_spad_rate_map_t + * + * @param[in] pspad_rates : pointer to VL53L1_spad_rate_map_t + * @param[in] pprefix : pointer to name prefix string + * @param[in] trace_flags : logging module enable bit flags + */ + +void VL53L1_print_spad_rate_map( + VL53L1_spad_rate_data_t *pspad_rates, + char *pprefix, + uint32_t trace_flags); + + +#endif /* VL53L1_LOG_ENABLE */ + +#ifdef __cplusplus +} +#endif + +#endif /* _VL53L1_API_DEBUG_H_ */ diff --git a/App/VL53L1X_API/core/inc/vl53l1_api_preset_modes.h b/App/VL53L1X_API/core/inc/vl53l1_api_preset_modes.h new file mode 100644 index 0000000..7a11532 --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_api_preset_modes.h @@ -0,0 +1,471 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_api_preset_modes.h + * + * @brief EwokPlus25 API core function definition + */ + +#ifndef _VL53L1_API_PRESET_MODES_H_ +#define _VL53L1_API_PRESET_MODES_H_ + +#include "vl53l1_ll_def.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Initializes Ref SPAD Char Configuration Parameters + * + * @param[out] pdata : pointer to VL53L1_refspadchar_config_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_init_refspadchar_config_struct( + VL53L1_refspadchar_config_t *pdata); +#endif + + +/** + * @brief Initializes SPAD Self Check (SSC) Configuration Parameters + * + * @param[out] pdata : pointer to VL53L1_ssc_config_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_init_ssc_config_struct( + VL53L1_ssc_config_t *pdata); + +/** + * @brief Initializes Xtalk Configuration Parameters + * + * @param[in] pnvm : pointer to VL53L1_customer_nvm_managed_t data structure + * @param[out] pdata : pointer to VL53L1_xtalk_config_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_init_xtalk_config_struct( + VL53L1_customer_nvm_managed_t *pnvm, + VL53L1_xtalk_config_t *pdata); + +/** + * @brief Initializes Offset Calibration Configuration Parameters + * + * @param[out] pdata : pointer to VL53L1_offsetcal_config_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_init_offset_cal_config_struct( + VL53L1_offsetcal_config_t *pdata); +#endif + + +/** + * @brief Initializes Tuning Parameter Storage Values + * + * @param[out] pdata : pointer to VL53L1_tuning_parm_storage_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_init_tuning_parm_storage_struct( + VL53L1_tuning_parm_storage_t *pdata); + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_STANDARD_RANGING + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_preset_mode_standard_ranging( + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms); + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_SHORT_RANGE + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_preset_mode_standard_ranging_short_range( + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms); + + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_LONG_RANGE + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_preset_mode_standard_ranging_long_range( + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms); + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM1_CAL + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_preset_mode_standard_ranging_mm1_cal( + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms); +#endif + + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM2_CAL + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_preset_mode_standard_ranging_mm2_cal( + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms); +#endif + + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_TIMED_RANGING + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_preset_mode_timed_ranging( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms); + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_TIMED_RANGING_SHORT_RANGE + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_preset_mode_timed_ranging_short_range( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms); + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_TIMED_RANGING_LONG_RANGE + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_preset_mode_timed_ranging_long_range( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms); + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_MEDIUM_RANGE + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * @param[out] plpadata : pointer to VL53L1_low_power_auto_data_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_preset_mode_low_power_auto_ranging( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms, + VL53L1_low_power_auto_data_t *plpadata); + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_SHORT_RANGE + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * @param[out] plpadata : pointer to VL53L1_low_power_auto_data_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_preset_mode_low_power_auto_short_ranging( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms, + VL53L1_low_power_auto_data_t *plpadata); + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_LONG_RANGE + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * @param[out] plpadata : pointer to VL53L1_low_power_auto_data_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_preset_mode_low_power_auto_long_ranging( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms, + VL53L1_low_power_auto_data_t *plpadata); + + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_OLT + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_preset_mode_olt( + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms); + +/** + * @brief Initializes static and dynamic configuration settings for + * preset mode VL53L1_DEVICEPRESETMODE_SINGLESHOT_RANGING + * + * @param[out] pstatic : pointer to VL53L1_static_config_t data structure + * @param[out] pgeneral : pointer to VL53L1_general_config_t data structure + * @param[out] ptiming : pointer to VL53L1_timing_config_t data structure + * @param[out] pdynamic : pointer to VL53L1_dynamic_config_t data structure + * @param[out] psystem : pointer to VL53L1_system_control_t data structure + * @param[out] ptuning_parms : pointer to VL53L1_tuning_parms_storage_t structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_preset_mode_singleshot_ranging( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms); + +#ifdef __cplusplus +} +#endif + +#endif /* _VL53L1_API_CORE_H_ */ diff --git a/App/VL53L1X_API/core/inc/vl53l1_api_strings.h b/App/VL53L1X_API/core/inc/vl53l1_api_strings.h new file mode 100644 index 0000000..eb9904c --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_api_strings.h @@ -0,0 +1,159 @@ + +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/****************************************************************************** + * Copyright (c) 2020, STMicroelectronics - All Rights Reserved + + This file is part of VL53L1 and is dual licensed, + either GPL-2.0+ + or 'BSD 3-clause "New" or "Revised" License' , at your option. + ****************************************************************************** + */ + +/** + * @file vl53l1_api_strings.h + * @brief VL53L1 API function declarations for decoding error codes to a + * text strings + */ + + +#ifndef VL53L1_API_STRINGS_H_ +#define VL53L1_API_STRINGS_H_ + +#include "vl53l1_def.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/** + * @brief Generates a string for the input device range status code + * + * @param[in] RangeStatus : Device Range AStatus Code + * @param[out] pRangeStatusString : pointer to character buffer + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_range_status_string( + uint8_t RangeStatus, + char *pRangeStatusString); + +/** + * @brief Generates an error string for the input PAL error code + * + * @param[in] PalErrorCode : PAL Error Code + * @param[out] pPalErrorString : pointer to character buffer + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_pal_error_string( + VL53L1_Error PalErrorCode, + char *pPalErrorString); + +/** + * @brief Generates a string for the input PAL State code + * + * @param[in] PalStateCode : PAL State Code + * @param[out] pPalStateString : pointer to character buffer + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_pal_state_string( + VL53L1_State PalStateCode, + char *pPalStateString); + + +/** + * @brief Generates a string for the sequence step Id + * + * @param[in] SequenceStepId : Sequence Step Id + * @param[out] pSequenceStepsString : pointer to character buffer + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_get_sequence_steps_info( + VL53L1_SequenceStepId SequenceStepId, + char *pSequenceStepsString); + +/** + * @brief Generates a string for the limit check Id + * + * @param[in] LimitCheckId : Limit check Id + * @param[out] pLimitCheckString : pointer to character buffer + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_get_limit_check_info(uint16_t LimitCheckId, + char *pLimitCheckString); + +#ifndef VL53L1_USE_EMPTY_STRING + #define VL53L1_STRING_DEVICE_INFO_NAME0 "VL53L1 cut1.0" + #define VL53L1_STRING_DEVICE_INFO_NAME1 "VL53L1 cut1.1" + #define VL53L1_STRING_DEVICE_INFO_TYPE "VL53L1" + + /* Range Status */ + #define VL53L1_STRING_RANGESTATUS_NONE "No Update" + #define VL53L1_STRING_RANGESTATUS_RANGEVALID "Range Valid" + #define VL53L1_STRING_RANGESTATUS_SIGMA "Sigma Fail" + #define VL53L1_STRING_RANGESTATUS_SIGNAL "Signal Fail" + #define VL53L1_STRING_RANGESTATUS_MINRANGE "Min Range Fail" + #define VL53L1_STRING_RANGESTATUS_PHASE "Phase Fail" + #define VL53L1_STRING_RANGESTATUS_HW "Hardware Fail" + + + /* Range Status */ + #define VL53L1_STRING_STATE_POWERDOWN "POWERDOWN State" + #define VL53L1_STRING_STATE_WAIT_STATICINIT \ + "Wait for staticinit State" + #define VL53L1_STRING_STATE_STANDBY "STANDBY State" + #define VL53L1_STRING_STATE_IDLE "IDLE State" + #define VL53L1_STRING_STATE_RUNNING "RUNNING State" + #define VL53L1_STRING_STATE_RESET "RESET State" + #define VL53L1_STRING_STATE_UNKNOWN "UNKNOWN State" + #define VL53L1_STRING_STATE_ERROR "ERROR State" + + + + /* Check Enable */ + #define VL53L1_STRING_CHECKENABLE_SIGMA_FINAL_RANGE \ + "SIGMA FINAL RANGE" + #define VL53L1_STRING_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE \ + "SIGNAL RATE FINAL RANGE" + #define VL53L1_STRING_CHECKENABLE_SIGNAL_MIN_CLIP \ + "SIGNAL MIN CLIP" + #define VL53L1_STRING_CHECKENABLE_RANGE_IGNORE_THRESHOLD \ + "RANGE IGNORE THRESHOLD" + #define VL53L1_STRING_CHECKENABLE_RANGE_PHASE_HIGH \ + "RANGE PHASE HIGH" + #define VL53L1_STRING_CHECKENABLE_RANGE_PHASE_LOW \ + "RANGE PHASE LOW" + #define VL53L1_STRING_CHECKENABLE_RANGE_PHASE_CONSISTENCY \ + "RANGE PHASE CONSISTENCY" + + /* Sequence Step */ + #define VL53L1_STRING_SEQUENCESTEP_VHV "VHV" + #define VL53L1_STRING_SEQUENCESTEP_PHASECAL "PHASE CAL" + #define VL53L1_STRING_SEQUENCESTEP_REFPHASE "REF PHASE" + #define VL53L1_STRING_SEQUENCESTEP_DSS1 "DSS1" + #define VL53L1_STRING_SEQUENCESTEP_DSS2 "DSS2" + #define VL53L1_STRING_SEQUENCESTEP_MM1 "MM1" + #define VL53L1_STRING_SEQUENCESTEP_MM2 "MM2" + #define VL53L1_STRING_SEQUENCESTEP_RANGE "RANGE" +#endif /* VL53L1_USE_EMPTY_STRING */ + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/App/VL53L1X_API/core/inc/vl53l1_core.h b/App/VL53L1X_API/core/inc/vl53l1_core.h new file mode 100644 index 0000000..3e58d77 --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_core.h @@ -0,0 +1,1090 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_core.h + * + * @brief EwokPlus25 core function definitions + */ + +#ifndef _VL53L1_CORE_H_ +#define _VL53L1_CORE_H_ + +#include "vl53l1_platform.h" +#include "vl53l1_core_support.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Initialise version info in pdev + * + * @param[out] Dev : Device handle + */ + +void VL53L1_init_version( + VL53L1_DEV Dev); + + +/** + * @brief Initialise LL Driver State + * + * @param[out] Dev : Device handle + * @param[in] ll_state : Device state + */ + +void VL53L1_init_ll_driver_state( + VL53L1_DEV Dev, + VL53L1_DeviceState ll_state); + + +/** + * @brief Update LL Driver Read State + * + * @param[out] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_update_ll_driver_rd_state( + VL53L1_DEV Dev); + + +/** + * @brief Checks if the LL Driver Read state and expected stream count + * matches the state and stream count received from the device + * + * @param[out] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_check_ll_driver_rd_state( + VL53L1_DEV Dev); + + +/** + * @brief Update LL Driver Configuration State + * + * @param[out] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_update_ll_driver_cfg_state( + VL53L1_DEV Dev); + + +/** + * @brief Convenience function to copy return SPAD enables to buffer + * + * @param[in ] pdata : pointer to VL53L1_nvm_copy_data_t + * @param[out] pbuffer : pointer to buffer + */ + +void VL53L1_copy_rtn_good_spads_to_buffer( + VL53L1_nvm_copy_data_t *pdata, + uint8_t *pbuffer); + + +/** + * @brief Initialise system results structure to all ones + * + * This mimics what the device firmware does the the results registers + * at the start of each range + * + * @param[out] pdata : pointer to VL53L1_system_results_t + */ + +void VL53L1_init_system_results( + VL53L1_system_results_t *pdata); + + +/** + * @brief Initialise zone dynamic config DSS control values + * + * @param[in] Dev : Device handler + */ + +void V53L1_init_zone_dss_configs( + VL53L1_DEV Dev); + + +/** + * @brief Encodes a uint16_t register value into an I2C write buffer + * + * The register is encoded MS byte first is the buffer i.e as per the device register map + * + * @param[in] ip_value : input uint16_t value + * @param[in] count : register size of in bytes (1, 2, 3 or 4) + * @param[out] pbuffer : uint8_t pointer to the I2C write buffer + */ + +void VL53L1_i2c_encode_uint16_t( + uint16_t ip_value, + uint16_t count, + uint8_t *pbuffer); + + +/** + * @brief Decodes a uint16_t register value from an I2C read buffer + * + * The I2C read buffer is assumed to be MS byte first i.e. matching the device register map + * + * @param[in] count : register size of in bytes (1, 2, 3 or 4) + * @param[in] pbuffer : uint8_t pointer to the I2C read buffer + * + * @return value : decoded uint16_t value + */ + +uint16_t VL53L1_i2c_decode_uint16_t( + uint16_t count, + uint8_t *pbuffer); + + +/** + * @brief Encodes a int16_t register value into an I2C write buffer + * + * The register is encoded MS byte first is the buffer i.e as per the device register map + * + * @param[in] ip_value : input int16_t value + * @param[in] count : register size of in bytes (1, 2, 3 or 4) + * @param[out] pbuffer : uint8_t pointer to the I2C write buffer + */ + +void VL53L1_i2c_encode_int16_t( + int16_t ip_value, + uint16_t count, + uint8_t *pbuffer); + + +/** + * @brief Decodes a int16_t register value from an I2C read buffer + * + * The I2C read buffer is assumed to be MS byte first i.e. matching the device register map + * + * @param[in] count : register size of in bytes (1, 2, 3 or 4) + * @param[in] pbuffer : uint8_t pointer to the I2C read buffer + * + * @return value : decoded int16_t value + */ + +int16_t VL53L1_i2c_decode_int16_t( + uint16_t count, + uint8_t *pbuffer); + + +/** + * @brief Encodes a uint32_t register value into an I2C write buffer + * + * The register is encoded MS byte first is the buffer i.e as per the device register map + * + * @param[in] ip_value : input uint32_t value + * @param[in] count : register size of in bytes (1, 2, 3 or 4) + * @param[out] pbuffer : uint8_t pointer to the I2C write buffer + */ + +void VL53L1_i2c_encode_uint32_t( + uint32_t ip_value, + uint16_t count, + uint8_t *pbuffer); + + +/** + * @brief Decodes a uint32_t register value from an I2C read buffer + * + * The I2C read buffer is assumed to be MS byte first i.e. matching the device register map + * + * @param[in] count : register size of in bytes (1, 2, 3 or 4) + * @param[in] pbuffer : uint8_t pointer to the I2C read buffer + * + * @return value : decoded uint32_t value + */ + +uint32_t VL53L1_i2c_decode_uint32_t( + uint16_t count, + uint8_t *pbuffer); + + +/** + * @brief Decodes an integer register value from an I2C read buffer + * + * The I2C read buffer is assumed to be MS byte first i.e. matching the device register map + * + * @param[in] count : integer size of in bytes (1, 2, 3 or 4) + * @param[in] pbuffer : uint8_t pointer to the I2C read buffer + * @param[in] bit_mask : bit mask to apply + * @param[in] down_shift : down shift to apply + * @param[in] offset : offset to apply after the down shift + * + * @return value : decoded integer value + */ + +uint32_t VL53L1_i2c_decode_with_mask( + uint16_t count, + uint8_t *pbuffer, + uint32_t bit_mask, + uint32_t down_shift, + uint32_t offset); + + +/** + * @brief Encodes a int32_t register value into an I2C write buffer + * + * The register is encoded MS byte first is the buffer i.e as per the device register map + * + * @param[in] ip_value : input int32_t value + * @param[in] count : register size of in bytes (1, 2, 3 or 4) + * @param[out] pbuffer : uint8_t pointer to the I2C write buffer + */ + +void VL53L1_i2c_encode_int32_t( + int32_t ip_value, + uint16_t count, + uint8_t *pbuffer); + + +/** + * @brief Decodes a int32_t register value from an I2C read buffer + * + * The I2C read buffer is assumed to be MS byte first i.e. matching the device register map + * + * @param[in] count : register size of in bytes (1, 2, 3 or 4) + * @param[in] pbuffer : uint8_t pointer to the I2C read buffer + * + * @return value : decoded int32_t value + */ + +int32_t VL53L1_i2c_decode_int32_t( + uint16_t count, + uint8_t *pbuffer); + + +/** + * @brief Triggers the start of the provided test_mode. + * + * @param[in] Dev : Device handle + * @param[in] test_mode__ctrl : VL53L1_TEST_MODE__CTRL register value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_start_test( + VL53L1_DEV Dev, + uint8_t test_mode__ctrl); +#endif + + +/** + * @brief Set firmware enable register + * + * Wrapper for setting power force register state + * Also updates pdev->sys_ctrl.firmware__enable + * + * @param[in] Dev : Device handle + * @param[in] value : register value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_firmware_enable_register( + VL53L1_DEV Dev, + uint8_t value); + + +/** + * @brief Enables MCU firmware + * + * @param[in] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_enable_firmware( + VL53L1_DEV Dev); + + +/** + * @brief Disables MCU firmware + * + * This required to write to MCU G02, G01 registers and access the patch RAM + * + * @param[in] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_disable_firmware( + VL53L1_DEV Dev); + + +/** + * @brief Set power force register + * + * Wrapper for setting power force register state + * Also updates pdev->sys_ctrl.power_management__go1_power_force + * + * @param[in] Dev : Device handle + * @param[in] value : register value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_powerforce_register( + VL53L1_DEV Dev, + uint8_t value); + + +/** + * @brief Enables power force + * + * This prevents the G01 and patch RAM from powering down between + * ranges to enable reading of G01 and patch RAM data + * + * Calls VL53L1_set_powerforce_register() + * + * @param[in] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + + +VL53L1_Error VL53L1_enable_powerforce( + VL53L1_DEV Dev); + +/** + * @brief Disables power force + * + * @param[in] Dev : Device handle + * + * Disable power force + * + * Calls VL53L1_set_powerforce_register() + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_disable_powerforce( + VL53L1_DEV Dev); + + +/** + * @brief Clears Ranging Interrupt + * + * @param[in] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + + +VL53L1_Error VL53L1_clear_interrupt( + VL53L1_DEV Dev); + + +/** + * @brief Forces shadow stream count to zero + * + * @param[in] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_force_shadow_stream_count_to_zero( + VL53L1_DEV Dev); +#endif + +/** + * @brief Calculates the macro period in [us] for the input + * fast_osc_frequency and VCSEL period register value + * + * Processing steps: + * + * 1. PLL period from fast_osc_frequency + * 2. VCSEL period + * 3. Macro period + * + * @param[in] fast_osc_frequency : fast oscillator frequency in 4.12 MHz format + * @param[in] vcsel_period : VCSEL period register value + * + * @return macro_period_us : macro period in [us] 12.12 format + */ + +uint32_t VL53L1_calc_macro_period_us( + uint16_t fast_osc_frequency, + uint8_t vcsel_period); + + +/** + * @brief Calculates the Xtalk Range Ignore Threshold + * rate per spad in 3.13Mcps + * + * This is done by calculating the worst case xtalk seen on the array + * and applying a user specified fractional multiplier. + * + * @param[in] central_rate : xtalk central rate in 9.9u Kcps format + * @param[in] x_gradient : xtalk xgradient rate in 4.11s Kcps format + * @param[in] y_gradient : xtalk ygradient rate in 4.11s Kcps format + * @param[in] rate_mult : rate multiplier in 2.5 fractional format + * + * @return range_ignore_threshold_kcps : rate per spad in mcps 3.13 + */ + +uint16_t VL53L1_calc_range_ignore_threshold( + uint32_t central_rate, + int16_t x_gradient, + int16_t y_gradient, + uint8_t rate_mult); + + +/** + * @brief Calculates the timeout value in macro period based on the input + * timeout period in milliseconds and the macro period in us + * + * @param[in] timeout_us : timeout period in microseconds + * @param[in] macro_period_us : macro period in microseconds 12.12 + * + * @return timeout_mclks : timeout in macro periods + */ + +uint32_t VL53L1_calc_timeout_mclks( + uint32_t timeout_us, + uint32_t macro_period_us); + +/** + * @brief Calculates the encoded timeout register value based on the input + * timeout period in milliseconds and the macro period in us + * + * @param[in] timeout_us : timeout period in microseconds + * @param[in] macro_period_us : macro period in microseconds 12.12 + * + * @return timeout_encoded : encoded timeout register value + */ + +uint16_t VL53L1_calc_encoded_timeout( + uint32_t timeout_us, + uint32_t macro_period_us); + + +/** + * @brief Calculates the timeout in us based on the input + * timeout im macro periods value and the macro period in us + * + * @param[in] timeout_mclks : timeout im macro periods + * @param[in] macro_period_us : macro period in microseconds 12.12 + * + * @return timeout_us : encoded timeout register value + */ + +uint32_t VL53L1_calc_timeout_us( + uint32_t timeout_mclks, + uint32_t macro_period_us); + +/** + * @brief Calculates the decoded timeout in us based on the input + * encoded timeout register value and the macro period in us + * + * @param[in] timeout_encoded : encoded timeout register value + * @param[in] macro_period_us : macro period in microseconds 12.12 + * + * @return timeout_us : encoded timeout register value + */ + +uint32_t VL53L1_calc_decoded_timeout_us( + uint16_t timeout_encoded, + uint32_t macro_period_us); + + +/** + * @brief Encode timeout in (LSByte * 2^MSByte) + 1 register format. + * + * @param[in] timeout_mclks : uint32_t timeout value (macro periods) + * + * @return encoded_timeout : 16-bit encoded value + */ + +uint16_t VL53L1_encode_timeout( + uint32_t timeout_mclks); + + +/** + * @brief Decode 16-bit timeout register value. + * + * @param[in] encoded_timeout : 16-bit timeout register value + * + * @return timeout_macro_clks : uint32_t decoded value + * + */ + +uint32_t VL53L1_decode_timeout( + uint16_t encoded_timeout); + + +/** + * @brief Converts the input MM and range timeouts in [us] + * into the appropriate register values + * + * Must also be run after the VCSEL period settings are changed + * + * @param[in] phasecal_config_timeout_us : requested Phase Cal Timeout e.g. 1000us + * @param[in] mm_config_timeout_us : requested MM Timeout e.g. 2000us + * @param[in] range_config_timeout_us : requested Ranging Timeout e.g 10000us + * @param[in] fast_osc_frequency : fast oscillator frequency in 4.12 MHz format + * @param[out] pgeneral : general data struct + * @param[out] ptiming : timing data struct with input vcsel period data + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_calc_timeout_register_values( + uint32_t phasecal_config_timeout_us, + uint32_t mm_config_timeout_us, + uint32_t range_config_timeout_us, + uint16_t fast_osc_frequency, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming); + + +/** + * @brief Encodes the real period in PLL clocks into the register value + * + * @param[in] vcsel_period_pclks : 8-bit value + * + * @return vcsel_period_reg : 8-bit encoded value + * + */ + +uint8_t VL53L1_encode_vcsel_period( + uint8_t vcsel_period_pclks); + + +/** + * @brief Decodes an unsigned integer from a uint8_t buffer 16-bit, 24-bit or 32-bit integers. + * + * Assumes MS Byte first + * + * @param[in] pbuffer : pointer to start of integer uint8_t data + * @param[in] no_of_bytes : size of integer in bytes + * + * @return decoded_value : decoded integer value + * + */ + +uint32_t VL53L1_decode_unsigned_integer( + uint8_t *pbuffer, + uint8_t no_of_bytes); + + +/** + * @brief Encodes an unsigned integer into a uint8_t buffer MS byte first + * + * @param[in] ip_value : input unsigned integer + * @param[in] no_of_bytes : size of integer storage in bytes + * @param[out] pbuffer : pointer to output buffer + * + */ + +void VL53L1_encode_unsigned_integer( + uint32_t ip_value, + uint8_t no_of_bytes, + uint8_t *pbuffer); + +/** + * @brief Get the SPAD number, byte index (0-31) and bit index (0-7) for + * + * Takes the map index (0 - 255) and calculated the SPAD number, byte index + * within the SPAD enable byte array and but position within the SPAD enable + * byte + * + * + * @param[in] spad_number : spad number + * @param[out] pbyte_index : pointer to output 0-31 byte index for SPAD enables + * @param[out] pbit_index : pointer to output 0-7 bit index + * @param[out] pbit_mask : pointer to output bit mask for the byte + * + */ + +void VL53L1_spad_number_to_byte_bit_index( + uint8_t spad_number, + uint8_t *pbyte_index, + uint8_t *pbit_index, + uint8_t *pbit_mask); + + +/** + * @brief Encodes a (col,row) coord value into ByteIndex.BitIndex format + * + * + * @param[in] row : Row + * @param[in] col : Column + * @param[out] pspad_number : Encoded Coord in Byte.Bit format + * + */ + +void VL53L1_encode_row_col( + uint8_t row, + uint8_t col, + uint8_t *pspad_number); + + +/** + * @brief Decodes encoded zone size format into width and height values + * + * @param[in] encoded_xy_size : Encoded zone size + * @param[out] pwidth : Decoded zone width + * @param[out] pheight : Decoded zone height + * + */ + +void VL53L1_decode_zone_size( + uint8_t encoded_xy_size, + uint8_t *pwidth, + uint8_t *pheight); + + +/** + * @brief Encodes a zone width & height into encoded size format + * + * @param[in] width : Zone Width + * @param[in] height : Zone height + * @param[out] pencoded_xy_size : Encoded zone size + * + */ + +void VL53L1_encode_zone_size( + uint8_t width, + uint8_t height, + uint8_t *pencoded_xy_size); + + +/** + * @brief Decodes encoded zone info into min/max limits + * + * Note both the lower left and upper right coordinated lie within + * the zone (inclusive) + * + * @param[in] encoded_xy_centre : Encoded zone centre (spad number) + * @param[in] encoded_xy_size : Encoded zone size + * @param[out] px_ll : Decoded zone lower left x coord + * @param[out] py_ll : Decoded zone lower left y coord + * @param[out] px_ur : Decoded zone upper right x coord + * @param[out] py_ur : Decoded zone upper right y coord + */ + +void VL53L1_decode_zone_limits( + uint8_t encoded_xy_centre, + uint8_t encoded_xy_size, + int16_t *px_ll, + int16_t *py_ll, + int16_t *px_ur, + int16_t *py_ur); + + +/** + * @brief Returns > 0 if input (row,col) location is an apertured SPAD + * + * @param[in] row : Row + * @param[in] col : Column + * + * @return is_aperture : if > 0 the location is an apertured SPAD + */ + +uint8_t VL53L1_is_aperture_location( + uint8_t row, + uint8_t col); + + +/** + * @brief Calculates the effective SPAD counts for the MM inner and outer + * regions based on the input MM ROI, Zone info and return good + * SPAD map + * + * @param[in] encoded_mm_roi_centre : Encoded MM ROI centre - spad number + * @param[in] encoded_mm_roi_size : Encoded MM ROI size + * @param[in] encoded_zone_centre : Encoded Zone centre - spad number + * @param[in] encoded_zone_size : Encoded Zone size + * @param[in] pgood_spads : Return array good SPAD map (32 bytes) + * @param[in] aperture_attenuation : Aperture attenuation value, Format 8.8 + * @param[out] pmm_inner_effective_spads : MM Inner effective SPADs, Format 8.8 + * @param[out] pmm_outer_effective_spads : MM Outer effective SPADs, Format 8.8 + * + */ + +void VL53L1_calc_mm_effective_spads( + uint8_t encoded_mm_roi_centre, + uint8_t encoded_mm_roi_size, + uint8_t encoded_zone_centre, + uint8_t encoded_zone_size, + uint8_t *pgood_spads, + uint16_t aperture_attenuation, + uint16_t *pmm_inner_effective_spads, + uint16_t *pmm_outer_effective_spads); + +/** + * @brief Function to save dynamic config data per zone at init and start range + * + * @param[in] Dev : Pointer to data structure + * + * + * @return VL53L1_ERROR_NONE Success + * + */ + +VL53L1_Error VL53L1_save_cfg_data( + VL53L1_DEV Dev); + + +/** + * @brief Encodes VL53L1_GPIO_interrupt_config_t structure to FW register format + * + * @param[in] pintconf : pointer to gpio interrupt config structure + * @return The encoded system__interrupt_config_gpio byte + */ + +uint8_t VL53L1_encode_GPIO_interrupt_config( + VL53L1_GPIO_interrupt_config_t *pintconf); + +/** + * @brief Decodes FW register to VL53L1_GPIO_interrupt_config_t structure + * + * @param[in] system__interrupt_config : interrupt config register byte + * @return The decoded structure + */ + +VL53L1_GPIO_interrupt_config_t VL53L1_decode_GPIO_interrupt_config( + uint8_t system__interrupt_config); + +/** + * @brief SET GPIO distance threshold + * + * @param[in] Dev : Device Handle + * @param[in] threshold_high : High distance threshold in mm + * @param[in] threshold_low : Low distance threshold in mm + */ + +VL53L1_Error VL53L1_set_GPIO_distance_threshold( + VL53L1_DEV Dev, + uint16_t threshold_high, + uint16_t threshold_low); + +/** + * @brief SET GPIO rate threshold + * + * @param[in] Dev : Device Handle + * @param[in] threshold_high : High rate threshold in 9.7 Mcps + * @param[in] threshold_low : Low rate threshold in 9.7 Mcps + */ + +VL53L1_Error VL53L1_set_GPIO_rate_threshold( + VL53L1_DEV Dev, + uint16_t threshold_high, + uint16_t threshold_low); + +/** + * @brief SET GPIO thresholds from structure. Sets both rate and distance + * thresholds + * + * @param[in] Dev : Device Handle + * @param[in] pintconf : Pointer to structure + */ + +VL53L1_Error VL53L1_set_GPIO_thresholds_from_struct( + VL53L1_DEV Dev, + VL53L1_GPIO_interrupt_config_t *pintconf); + + +/** + * @brief Set Ref SPAD Characterisation Config + * + * Initialises the timeout and VCSEL period for the Reference + * SPAD Characterisation test mode. + * + * Register Mapping: + * + * - timeout -> VL53L1_PHASECAL_CONFIG__TIMEOUT_MACROP + * - vcsel_period -> VL53L1_RANGE_CONFIG__VCSEL_PERIOD_A \n + * -> VL53L1_SD_CONFIG__WOI_SD0 \n + * -> VL53L1_SD_CONFIG__WOI_SD1 + * - total_rate_target_mcps -> VL53L1_REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS + * - max_count_rate_rtn_limit_mcps -> VL53L1_RANGE_CONFIG__SIGMA_THRESH + * - min_count_rate_rtn_limit_mcps -> VL53L1_SRANGE_CONFIG__SIGMA_THRESH + * + * @param[in] Dev : Device handle + * @param[in] vcsel_period_a : VCSEL period A register value + * @param[in] phasecal_timeout_us : requested PhaseCal Timeout in [us] + * e.g 1000us + * @param[in] total_rate_target_mcps : Target reference rate [Mcps] 9.7 format + * @param[in] max_count_rate_rtn_limit_mcps : Max rate final check limit [Mcps] 9.7 format + * @param[in] min_count_rate_rtn_limit_mcps : Min rate final check limit [Mcps] 9.7 format + * @param[in] fast_osc_frequency : Fast Osc Frequency (4.12) format + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_set_ref_spad_char_config( + VL53L1_DEV Dev, + uint8_t vcsel_period_a, + uint32_t phasecal_timeout_us, + uint16_t total_rate_target_mcps, + uint16_t max_count_rate_rtn_limit_mcps, + uint16_t min_count_rate_rtn_limit_mcps, + uint16_t fast_osc_frequency); +#endif + + +/** + * @brief Applies SSC (SPAD Self Check) configuration to device. + * + * Prior to calling this function it is assumed both the Fast Osc + * and VCSEL have already been trimmed and the register values set. + * + * Internally the required timeout in macro periods is calculated + * from the input VCSEL period, fast_osc_frequency and requested + * timeout in microseconds. + * + * Register Mapping: + * + * - rate_select -> VL53L1_NVM_BIST__CTRL + * - timeout -> VL53L1_RANGE_CONFIG__TIMEOUT_MACROP_ B_HI & _LO + * - vcsel_period -> VL53L1_RANGE_CONFIG__VCSEL_PERIOD_B \n + * -> VL53L1_SD_CONFIG__WOI_SD0 \n + * -> VL53L1_SD_CONFIG__WOI_SD1 + * - vcsel_start -> VL53L1_CAL_CONFIG__VCSEL_START + * - vcsel_width -> VL53L1_GLOBAL_CONFIG__VCSEL_WIDTH + * - ssc_limit_mcps -> VL53L1_RANGE_CONFIG__SIGMA_THRESH + * + * ssc_rate_limit_mcps format: + * + * - 1.15 for DCR/LCR test modes with VCSEL off + * - 9.7 LCR test mode with VCSEL on + * + * The configuration is set to the device via a 5-byte multi byte write. + * + * @param[in] Dev : Device handle + * @param[in] pssc_cfg : pointer to VL53L1_ssc_config_t + * @param[in] fast_osc_frequency : Fast Osc Frequency (4.12) format + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_set_ssc_config( + VL53L1_DEV Dev, + VL53L1_ssc_config_t *pssc_cfg, + uint16_t fast_osc_frequency); +#endif + + +/** + * @brief Gets the 256 return array SSC rates from the Patch RAM + * + * Each SSC rate is 1.15 or 9.7 dependent on test run. + * Total of 512 bytes to read! + * + * ssc_rate_mcps buffer format: + * + * - 1.15 for DCR/LCR test modes with VCSEL off (ambient) + * - 9.7 LCR test mode with VCSEL on (which rate?) + * + * Assumes that power force has already been enabled + * + * Function disables firmware at start to allow patch RAM to be read + * and then enables the firmware before returning + * + * The order of the rates is in SPAD number order (increasing) + * + * @param[in] Dev : Device handle + * @param[out] pspad_rates : pointer to VL53L1_spad_rate_data_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_get_spad_rate_data( + VL53L1_DEV Dev, + VL53L1_spad_rate_data_t *pspad_rates); +#endif + +/** + * @brief Function to add signed margin to the + * xtalk plane offset value, dealing with signed and unsigned + * value mixing + * + * Clips output to 0 if negative + * Clips to max possible value of 9.9 Kcps if exceeds this limitation + * + * @param[in] plane_offset_kcps : xtalk plane offset (9.9 format) Kcps + * @param[in] margin_offset_kcps : margin offset signed (6.9 format) Kcps + * + * @return plane_offset_with_margin in Kcps (7.9 format) + */ + +uint32_t VL53L1_calc_crosstalk_plane_offset_with_margin( + uint32_t plane_offset_kcps, + int16_t margin_offset_kcps); + +/** + * @brief Initialize the Low Power Auto data structure + * + * Patch_LowPowerAutoMode + * + * @param[in] Dev : Device Handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_low_power_auto_data_init( + VL53L1_DEV Dev + ); + +/** + * @brief Reset internal state but leave low_power_auto mode intact + * + * Patch_LowPowerAutoMode + * + * @param[in] Dev : Device Handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_low_power_auto_data_stop_range( + VL53L1_DEV Dev + ); + +/** + * @brief Initialize the config strcutures when low power auto preset modes are + * selected + * + * Patch_LowPowerAutoMode + * + * @param[in] pgeneral : pointer to the general config structure + * @param[in] pdynamic : pointer to the dynamic config structure + * @param[in] plpadata : pointer to the low power auto config structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_config_low_power_auto_mode( + VL53L1_general_config_t *pgeneral, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_low_power_auto_data_t *plpadata + ); + +/** + * @brief Setup ranges after the first one in low power auto mode by turning + * off FW calibration steps and programming static values + * + * Patch_LowPowerAutoMode + * + * @param[out] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_low_power_auto_setup_manual_calibration( + VL53L1_DEV Dev); + +/** + * @brief Do a DSS calculation and update manual config + * + * Patch_LowPowerAutoMode + * + * @param[out] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_low_power_auto_update_DSS( + VL53L1_DEV Dev); + +#ifdef __cplusplus +} +#endif + +#endif /* _VL53L1_API_CORE_H_ */ diff --git a/App/VL53L1X_API/core/inc/vl53l1_core_support.h b/App/VL53L1X_API/core/inc/vl53l1_core_support.h new file mode 100644 index 0000000..1f24c6e --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_core_support.h @@ -0,0 +1,222 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_core_support.h + * + * @brief EwokPlus25 core function definitions + */ + +#ifndef _VL53L1_CORE_SUPPORT_H_ +#define _VL53L1_CORE_SUPPORT_H_ + +#include "vl53l1_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Calculates the PLL period in [us] from the input + * fast_osc_frequency + * + * @param[in] fast_osc_frequency : fast oscillator frequency in 4.12 MHz format + * + * @return pll_period_us : PLL period in [us] 8.24 format + */ + +uint32_t VL53L1_calc_pll_period_us( + uint16_t fast_osc_frequency); + + + +#ifdef PAL_EXTENDED +/** + * @brief Calculates the ranging duration in ns using fixed point maths + * * + * Uses a temporary uint64_t variable internally + * + * @param[in] pll_period_us : PLL Period in [us] 0.25 format + * @param[in] vcsel_parm_pclks : period, width or WOI window in PLL clocks + * in 6.4 format. + * @param[in] window_vclks : ranging or ambient window duration in VCSEL clocks + * @param[in] periods_elapsed_mclks : elapsed time in macro clocks + * + * @return duration_us : uint32_t containing the duration time in us + */ + +uint32_t VL53L1_duration_maths( + uint32_t pll_period_us, + uint32_t vcsel_parm_pclks, + uint32_t window_vclks, + uint32_t periods_elapsed_mclks); + + +/** + * @brief Calculates the square root of the input integer + * + * Reference : http://en.wikipedia.org/wiki/Methods_of_computing_square_roots + * + * @param[in] num : input integer + * + * @return res : square root result + */ + +uint32_t VL53L1_isqrt( + uint32_t num); + +/** + * @brief Calculates the count rate using fixed point maths + * + * Uses a temporary uint64_t variable internally + * Any negative negative rates are clipped to 0. + * + * @param[in] events : accumulated SPAD events + * @param[in] time_us : elapsed time in us + * + * @return rate_mcps : uint16_t count rate in 9.7 format + */ + +uint16_t VL53L1_rate_maths( + int32_t events, + uint32_t time_us); + +/** + * @brief Calculates the Rate per spad + * + * Uses a temporary uint32_t variable internally + * Any output rates larger than 16 bit are clipped to 0xFFFF. + * + * @param[in] frac_bits : required output fractional precision - 7 \ + * due to inherent resolution of pk_rate + * @param[in] peak_count_rate : peak signal count rate in mcps + * @param[in] num_spads : actual effective spads in 8.8 + * @param[in] max_output_value : User set value to clip output + * + * @return rate_per_spad : uint16_t count rate in variable fractional format + */ + +uint16_t VL53L1_rate_per_spad_maths( + uint32_t frac_bits, + uint32_t peak_count_rate, + uint16_t num_spads, + uint32_t max_output_value); + + +/** + * @brief Calculates the range from the phase data + * + * Uses a temporary int64_t variable internally + * + * @param[in] fast_osc_frequency : Fast oscillator freq [MHz] 4.12 format + * @param[in] phase : phase in 5.11 format + * @param[in] zero_distance_phase : zero distance phase in 5.11 format + * @param[in] fractional_bits : valid options : 0, 1, 2 + * @param[in] gain_factor : gain correction factor 1.11 format + * @param[in] range_offset_mm : range offset [mm] 14.2 format + + * @return range_mm : signed range in [mm] + * format depends on fractional_bits input + */ + +int32_t VL53L1_range_maths( + uint16_t fast_osc_frequency, + uint16_t phase, + uint16_t zero_distance_phase, + uint8_t fractional_bits, + int32_t gain_factor, + int32_t range_offset_mm); +#endif + + +/** + * @brief Decodes VCSEL period register value into the real period in PLL clocks + * + * @param[in] vcsel_period_reg : 8 -bit register value + * + * @return vcsel_period_pclks : 8-bit decoded value + * + */ + +uint8_t VL53L1_decode_vcsel_period( + uint8_t vcsel_period_reg); + +/** + * @brief Decodes the Byte.Bit coord encoding into an (x,y) coord value + * + * @param[in] spad_number : Coord location in Byte.Bit format + * @param[out] prow : Decoded row + * @param[out] pcol : Decoded column + * + */ + +void VL53L1_decode_row_col( + uint8_t spad_number, + uint8_t *prow, + uint8_t *pcol); + +#ifdef __cplusplus +} +#endif + +#endif /* _VL53L1_CORE_SUPPORT_H_ */ diff --git a/App/VL53L1X_API/core/inc/vl53l1_def.h b/App/VL53L1X_API/core/inc/vl53l1_def.h new file mode 100644 index 0000000..a00e00b --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_def.h @@ -0,0 +1,603 @@ + +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/****************************************************************************** + * Copyright (c) 2020, STMicroelectronics - All Rights Reserved + + This file is part of VL53L1 and is dual licensed, + either GPL-2.0+ + or 'BSD 3-clause "New" or "Revised" License' , at your option. + ****************************************************************************** + */ + +/** + * @file vl53l1_def.h + * + * @brief Type definitions for VL53L1 API. + * + */ + + +#ifndef _VL53L1_DEF_H_ +#define _VL53L1_DEF_H_ + +#include "vl53l1_ll_def.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup VL53L1_globaldefine_group VL53L1 Defines + * @brief VL53L1 Defines + * @{ + */ + + +/** VL53L1 IMPLEMENTATION major version */ +#define VL53L1_IMPLEMENTATION_VER_MAJOR 2 +/** VL53L1 IMPLEMENTATION minor version */ +#define VL53L1_IMPLEMENTATION_VER_MINOR 4 +/** VL53L1 IMPLEMENTATION sub version */ +#define VL53L1_IMPLEMENTATION_VER_SUB 5 +/** VL53L1 IMPLEMENTATION sub version */ +#define VL53L1_IMPLEMENTATION_VER_REVISION 2548 + +/**************************************** + * PRIVATE define do not edit + ****************************************/ + +/** @brief Defines the parameters of the Get Version Functions + */ +typedef struct { + uint32_t revision; /*!< revision number */ + uint8_t major; /*!< major number */ + uint8_t minor; /*!< minor number */ + uint8_t build; /*!< build number */ +} VL53L1_Version_t; + + +#define VL53L1_DEVINFO_STRLEN 32 + +/** @brief Defines the parameters of the Get Device Info Functions + */ +typedef struct { + char Name[VL53L1_DEVINFO_STRLEN]; + /*!< Full Name of the Device e.g. VL53L1 cut1.1 */ + char Type[VL53L1_DEVINFO_STRLEN]; + /*!< Type of the Device e.g VL53L1 */ + char ProductId[VL53L1_DEVINFO_STRLEN]; + /*!< Product Identifier String + * @warning Not yet implemented + */ + uint8_t ProductType; + /*!< Product Type, VL53L1 = 0xCC, VL53L3 = 0xAA + * Stands as module_type in the datasheet + */ + uint8_t ProductRevisionMajor; + /*!< Product revision major */ + uint8_t ProductRevisionMinor; + /*!< Product revision minor */ +} VL53L1_DeviceInfo_t; + + + +/** @defgroup VL53L1_define_PresetModes_group Defines Preset modes + * Defines all possible preset modes for the device + * @{ + */ +typedef uint8_t VL53L1_PresetModes; + +#define VL53L1_PRESETMODE_AUTONOMOUS ((VL53L1_PresetModes) 3) +#define VL53L1_PRESETMODE_LITE_RANGING ((VL53L1_PresetModes) 4) +#define VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS ((VL53L1_PresetModes) 8) + + /* ... Modes to be added depending on device */ +/** @} VL53L1_define_PresetModes_group */ + + +/** @defgroup VL53L1_define_DistanceModes_group Defines Distance modes + * Defines all possible Distance modes for the device + * @{ + */ +typedef uint8_t VL53L1_DistanceModes; + +#define VL53L1_DISTANCEMODE_SHORT ((VL53L1_DistanceModes) 1) +#define VL53L1_DISTANCEMODE_MEDIUM ((VL53L1_DistanceModes) 2) +#define VL53L1_DISTANCEMODE_LONG ((VL53L1_DistanceModes) 3) +/** @} VL53L1_define_DistanceModes_group */ + + +/** @defgroup VL53L1_define_XtalkCal_group Defines Xtalk Calibration modes + * Defines all possible Offset Calibration modes for the device + * @{ + */ +typedef uint8_t VL53L1_XtalkCalibrationModes; + +#define VL53L1_XTALKCALIBRATIONMODE_NO_TARGET \ + ((VL53L1_OffsetCalibrationModes) 0) +/*!< To perform Xtalk calibration with no target below 80 cm */ +#define VL53L1_XTALKCALIBRATIONMODE_SINGLE_TARGET \ + ((VL53L1_OffsetCalibrationModes) 1) +/*!< To perform Xtalk calibration with one target */ +#define VL53L1_XTALKCALIBRATIONMODE_FULL_ROI \ + ((VL53L1_OffsetCalibrationModes) 2) +/*!< To perform Xtalk calibration based on histogram with full ROI */ + +/** @} VL53L1_define_XtalkCal_group */ + +/** @defgroup VL53L1_define_OffsetCal_group Defines Offset Calibration modes + * Defines all possible Offset Calibration modes for the device + * @{ + */ +typedef uint8_t VL53L1_OffsetCalibrationModes; + +#define VL53L1_OFFSETCALIBRATIONMODE_STANDARD \ + ((VL53L1_OffsetCalibrationModes) 1) +#define VL53L1_OFFSETCALIBRATIONMODE_PRERANGE_ONLY \ + ((VL53L1_OffsetCalibrationModes) 2) + +/** @} VL53L1_define_OffsetCal_group */ + + + + + +/** @defgroup VL53L1_CheckEnable_group Check Enable list + * @brief Check Enable code + * + * Define used to specify the LimitCheckId. + * Use @a VL53L1_GetLimitCheckInfo() to get the string. + * @{ + */ + +#define VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE 0 +#define VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE 1 + +#define VL53L1_CHECKENABLE_NUMBER_OF_CHECKS 2 + +/** @} end of VL53L1_CheckEnable_group */ + + +/** @defgroup VL53L1_ThresholdMode_gropup Detection Functionality + * @brief Defines the different functionalities for the detection feature + * @{ + */ +typedef uint8_t VL53L1_ThresholdMode; + +#define VL53L1_THRESHOLD_CROSSED_LOW \ + ((VL53L1_ThresholdMode) 0) + /*!< Trigger interrupt if value < thresh_low */ +#define VL53L1_THRESHOLD_CROSSED_HIGH \ + ((VL53L1_ThresholdMode) 1) + /*!< Trigger interrupt if value > thresh_high */ +#define VL53L1_THRESHOLD_OUT_OF_WINDOW \ + ((VL53L1_ThresholdMode) 2) + /*!< Trigger interrupt if value < thresh_low OR value > thresh_high */ +#define VL53L1_THRESHOLD_IN_WINDOW \ + ((VL53L1_ThresholdMode) 3) + /*!< Trigger interrupt if value > thresh_low AND value < thresh_high */ + +/** @} end of VL53L1_ThresholdMode_gropup */ + +/** @brief Defines parameters for Distance detection Thresholds configuration + */ +typedef struct { + VL53L1_ThresholdMode CrossMode; + uint16_t High; /*!< Distance threshold high limit in mm */ + uint16_t Low; /*!< Distance threshold low limit in mm */ +} VL53L1_DistanceThreshold_t; + +/** @brief Defines parameters for Signal rate detection Thresholds configuration + */ +typedef struct { + VL53L1_ThresholdMode CrossMode; + FixPoint1616_t High; /*!< Signal rate threshold high limit */ + FixPoint1616_t Low; /*!< Signal rate threshold low limit */ +} VL53L1_RateThreshold_t; + +/** @defgroup VL53L1_DetectionMode_group Gpio Functionality + * @brief Defines conditions leading to device's IT on GPIO + * @{ + */ +typedef uint8_t VL53L1_DetectionMode; + +#define VL53L1_DETECTION_NORMAL_RUN \ + ((VL53L1_DetectionMode) 0) + /*!< Trigger interrupt on new measurement regardless of threshold + * just like after a VL53L1_SetPresetMode() call + */ +#define VL53L1_DETECTION_DISTANCE_ONLY \ + ((VL53L1_DetectionMode) 1) + /*!< Trigger interrupt if "threshold event" occurs on distance */ +#define VL53L1_DETECTION_RATE_ONLY \ + ((VL53L1_DetectionMode) 2) + /*!< Trigger interrupt if "threshold event" occurs on signal rate */ +#define VL53L1_DETECTION_DISTANCE_AND_RATE \ + ((VL53L1_DetectionMode) 3) + /*!< Trigger interrupt if "threshold event" occurs on distance AND rate + */ +#define VL53L1_DETECTION_DISTANCE_OR_RATE \ + ((VL53L1_DetectionMode) 4) + /*!< Trigger interrupt if "threshold event" occurs on distance OR rate + */ + +/** @} end of VL53L1_DetectionMode_group */ + +/** @brief Defines parameters for User/object Detection configuration + */ +typedef struct { + VL53L1_DetectionMode DetectionMode; /*!< See #VL53L1_DetectionMode*/ + uint8_t IntrNoTarget; /*!< 1 to trigger IT in case of no target found */ + VL53L1_DistanceThreshold_t Distance; /*!< limits in mm */ + VL53L1_RateThreshold_t Rate;/*!< limits in FixPoint1616_t */ +} VL53L1_DetectionConfig_t; + + +/** @brief Defines all parameters for the device + */ +typedef struct { + VL53L1_PresetModes PresetMode; + /*!< Defines the operating mode to be used for the next measure */ + VL53L1_DistanceModes DistanceMode; + /*!< Defines the operating mode to be used for the next measure */ + uint32_t MeasurementTimingBudgetMicroSeconds; + /*!< Defines the allowed total time for a single measurement */ + uint8_t LimitChecksEnable[VL53L1_CHECKENABLE_NUMBER_OF_CHECKS]; + /*!< This Array store all the Limit Check enable for this device. */ + uint8_t LimitChecksStatus[VL53L1_CHECKENABLE_NUMBER_OF_CHECKS]; + /*!< This Array stores all the Status of the check linked to last + * measurement. + */ + FixPoint1616_t LimitChecksValue[VL53L1_CHECKENABLE_NUMBER_OF_CHECKS]; + /*!< This Array stores all the Limit Check value for this device */ + FixPoint1616_t LimitChecksCurrent[VL53L1_CHECKENABLE_NUMBER_OF_CHECKS]; + /*!< This Array stores all the Limit Check current value from latest + * ranging + */ +} VL53L1_DeviceParameters_t; + + +/** @defgroup VL53L1_define_State_group Defines the current status of the device + * Defines the current status of the device + * @{ + */ + +typedef uint8_t VL53L1_State; + +#define VL53L1_STATE_POWERDOWN ((VL53L1_State) 0) + /*!< Device is in HW reset */ +#define VL53L1_STATE_WAIT_STATICINIT ((VL53L1_State) 1) + /*!< Device is initialized and wait for static initialization */ +#define VL53L1_STATE_STANDBY ((VL53L1_State) 2) + /*!< Device is in Low power Standby mode */ +#define VL53L1_STATE_IDLE ((VL53L1_State) 3) + /*!< Device has been initialized and ready to do measurements */ +#define VL53L1_STATE_RUNNING ((VL53L1_State) 4) + /*!< Device is performing measurement */ +#define VL53L1_STATE_RESET ((VL53L1_State) 5) + /*!< Soft reset has been run on Device */ +#define VL53L1_STATE_UNKNOWN ((VL53L1_State) 98) + /*!< Device is in unknown state and need to be rebooted */ +#define VL53L1_STATE_ERROR ((VL53L1_State) 99) + /*!< Device is in error state and need to be rebooted */ + +/** @} VL53L1_define_State_group */ + + + +/** + * @struct VL53L1_RangingMeasurementData_t + * @brief Single Range measurement data. + */ +typedef struct { + uint32_t TimeStamp; + /*!< 32-bit time stamp. + * @warning Not yet implemented + */ + + uint8_t StreamCount; + /*!< 8-bit Stream Count. */ + + uint8_t RangeQualityLevel; + /*!< indicate a quality level in percentage from 0 to 100 + * @warning Not yet implemented + */ + + FixPoint1616_t SignalRateRtnMegaCps; + /*!< Return signal rate (MCPS)\n these is a 16.16 fix point + * value, which is effectively a measure of target + * reflectance. + */ + + FixPoint1616_t AmbientRateRtnMegaCps; + /*!< Return ambient rate (MCPS)\n these is a 16.16 fix point + * value, which is effectively a measure of the ambient + * light. + */ + + uint16_t EffectiveSpadRtnCount; + /*!< Return the effective SPAD count for the return signal. + * To obtain Real value it should be divided by 256 + */ + + FixPoint1616_t SigmaMilliMeter; + /*!< Return the Sigma value in millimeter */ + + int16_t RangeMilliMeter; + /*!< range distance in millimeter. This should be between + * RangeMinMilliMeter and RangeMaxMilliMeter + */ + + uint8_t RangeFractionalPart; + /*!< Fractional part of range distance. Final value is a + * RangeMilliMeter + RangeFractionalPart/256. + * @warning Not yet implemented + */ + + uint8_t RangeStatus; + /*!< Range Status for the current measurement. This is device + * dependent. Value = 0 means value is valid. + */ +} VL53L1_RangingMeasurementData_t; + + + +/** @brief Defines User Zone(ROI) parameters + * + */ +typedef struct { + + uint8_t TopLeftX; /*!< Top Left x coordinate: 0-15 range */ + uint8_t TopLeftY; /*!< Top Left y coordinate: 0-15 range */ + uint8_t BotRightX; /*!< Bot Right x coordinate: 0-15 range */ + uint8_t BotRightY; /*!< Bot Right y coordinate: 0-15 range */ + +} VL53L1_UserRoi_t; + + +/** @brief Defines ROI configuration parameters + * + * Support up a max of 16 zones, Each Zone has the same size + * + */ + +/** + * @struct VL53L1_CustomerNvmManaged_t + * + */ + +typedef struct { + uint8_t global_config__spad_enables_ref_0; + uint8_t global_config__spad_enables_ref_1; + uint8_t global_config__spad_enables_ref_2; + uint8_t global_config__spad_enables_ref_3; + uint8_t global_config__spad_enables_ref_4; + uint8_t global_config__spad_enables_ref_5; + uint8_t global_config__ref_en_start_select; + uint8_t ref_spad_man__num_requested_ref_spads; + uint8_t ref_spad_man__ref_location; + uint32_t algo__crosstalk_compensation_plane_offset_kcps; + int16_t algo__crosstalk_compensation_x_plane_gradient_kcps; + int16_t algo__crosstalk_compensation_y_plane_gradient_kcps; + uint16_t ref_spad_char__total_rate_target_mcps; + int16_t algo__part_to_part_range_offset_mm; + int16_t mm_config__inner_offset_mm; + int16_t mm_config__outer_offset_mm; +} VL53L1_CustomerNvmManaged_t; + +/** + * @struct VL53L1_CalibrationData_t + * @brief Structure for storing the Calibration Data + * + */ + +typedef struct { + + uint32_t struct_version; + VL53L1_CustomerNvmManaged_t customer; + VL53L1_additional_offset_cal_data_t add_off_cal_data; + VL53L1_optical_centre_t optical_centre; + VL53L1_gain_calibration_data_t gain_cal; + VL53L1_cal_peak_rate_map_t cal_peak_rate_map; +} VL53L1_CalibrationData_t; + +#define VL53L1_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION 0x20 +/** VL53L1 additional Calibration Data struct version final struct version + * is given by adding it to VL53L1_LL_CALIBRATION_DATA_STRUCT_VERSION + */ + +#define VL53L1_CALIBRATION_DATA_STRUCT_VERSION \ + (VL53L1_LL_CALIBRATION_DATA_STRUCT_VERSION + \ + VL53L1_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION) +/* VL53L1 Calibration Data struct version */ + +/** + * @struct VL53L1_AdditionalData_t + * @brief Structure for storing the Additional Data + * + */ +typedef VL53L1_additional_data_t VL53L1_AdditionalData_t; + + +typedef uint8_t VL53L1_SequenceStepId; + +#define VL53L1_SEQUENCESTEP_VHV ((VL53L1_SequenceStepId) 0) +/*!>12)&0xFFFF) +#define VL53L1_FIXPOINT44TOFIXPOINT1616(Value) \ + (FixPoint1616_t)((uint32_t)Value<<12) + +#define VL53L1_FIXPOINT1616TOFIXPOINT72(Value) \ + (uint16_t)((Value>>14)&0xFFFF) +#define VL53L1_FIXPOINT72TOFIXPOINT1616(Value) \ + (FixPoint1616_t)((uint32_t)Value<<14) + +#define VL53L1_FIXPOINT1616TOFIXPOINT97(Value) \ + (uint16_t)((Value>>9)&0xFFFF) +#define VL53L1_FIXPOINT97TOFIXPOINT1616(Value) \ + (FixPoint1616_t)((uint32_t)Value<<9) + +#define VL53L1_FIXPOINT1616TOFIXPOINT88(Value) \ + (uint16_t)((Value>>8)&0xFFFF) +#define VL53L1_FIXPOINT88TOFIXPOINT1616(Value) \ + (FixPoint1616_t)((uint32_t)Value<<8) + +#define VL53L1_FIXPOINT1616TOFIXPOINT412(Value) \ + (uint16_t)((Value>>4)&0xFFFF) +#define VL53L1_FIXPOINT412TOFIXPOINT1616(Value) \ + (FixPoint1616_t)((uint32_t)Value<<4) + +#define VL53L1_FIXPOINT1616TOFIXPOINT313(Value) \ + (uint16_t)((Value>>3)&0xFFFF) +#define VL53L1_FIXPOINT313TOFIXPOINT1616(Value) \ + (FixPoint1616_t)((uint32_t)Value<<3) + +#define VL53L1_FIXPOINT1616TOFIXPOINT08(Value) \ + (uint8_t)((Value>>8)&0x00FF) +#define VL53L1_FIXPOINT08TOFIXPOINT1616(Value) \ + (FixPoint1616_t)((uint32_t)Value<<8) + +#define VL53L1_FIXPOINT1616TOFIXPOINT53(Value) \ + (uint8_t)((Value>>13)&0x00FF) +#define VL53L1_FIXPOINT53TOFIXPOINT1616(Value) \ + (FixPoint1616_t)((uint32_t)Value<<13) + +#define VL53L1_FIXPOINT1616TOFIXPOINT102(Value) \ + (uint16_t)((Value>>14)&0x0FFF) +#define VL53L1_FIXPOINT102TOFIXPOINT1616(Value) \ + (FixPoint1616_t)((uint32_t)Value<<14) + +#define VL53L1_FIXPOINT1616TOFIXPOINT142(Value) \ + (uint16_t)((Value>>14)&0xFFFF) +#define VL53L1_FIXPOINT142TOFIXPOINT1616(Value) \ + (FixPoint1616_t)((uint32_t)Value<<14) + +#define VL53L1_FIXPOINT1616TOFIXPOINT160(Value) \ + (uint16_t)((Value>>16)&0xFFFF) +#define VL53L1_FIXPOINT160TOFIXPOINT1616(Value) \ + (FixPoint1616_t)((uint32_t)Value<<16) + +#define VL53L1_MAKEUINT16(lsb, msb) (uint16_t)((((uint16_t)msb)<<8) + \ + (uint16_t)lsb) + +#ifndef SUPPRESS_UNUSED_WARNING +#define SUPPRESS_UNUSED_WARNING(x) ((void) (x)) +#endif + +/** @} VL53L1_define_GeneralMacro_group */ + +/** @} VL53L1_globaldefine_group */ + + + +#ifdef __cplusplus +} +#endif + + +#endif /* _VL53L1_DEF_H_ */ diff --git a/App/VL53L1X_API/core/inc/vl53l1_error_codes.h b/App/VL53L1X_API/core/inc/vl53l1_error_codes.h new file mode 100644 index 0000000..cdc1ec9 --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_error_codes.h @@ -0,0 +1,253 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_error_codes.h + * + * @brief Error Code definitions for VL53L1 API. + * + */ + +#ifndef _VL53L1_ERROR_CODES_H_ +#define _VL53L1_ERROR_CODES_H_ + +#include "vl53l1_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**************************************** + * PRIVATE define do not edit + ****************************************/ + +/** @defgroup VL53L1_define_Error_group Error and Warning code returned by API + * The following DEFINE are used to identify the PAL ERROR + * @{ + */ + +typedef int8_t VL53L1_Error; + +#define VL53L1_ERROR_NONE ((VL53L1_Error) 0) +#define VL53L1_ERROR_CALIBRATION_WARNING ((VL53L1_Error) - 1) + /*!< Warning invalid calibration data may be in used + \a VL53L1_InitData() + \a VL53L1_GetOffsetCalibrationData + \a VL53L1_SetOffsetCalibrationData */ +#define VL53L1_ERROR_MIN_CLIPPED ((VL53L1_Error) - 2) + /*!< Warning parameter passed was clipped to min before to be applied */ + +#define VL53L1_ERROR_UNDEFINED ((VL53L1_Error) - 3) + /*!< Unqualified error */ +#define VL53L1_ERROR_INVALID_PARAMS ((VL53L1_Error) - 4) + /*!< Parameter passed is invalid or out of range */ +#define VL53L1_ERROR_NOT_SUPPORTED ((VL53L1_Error) - 5) + /*!< Function is not supported in current mode or configuration */ +#define VL53L1_ERROR_RANGE_ERROR ((VL53L1_Error) - 6) + /*!< Device report a ranging error interrupt status */ +#define VL53L1_ERROR_TIME_OUT ((VL53L1_Error) - 7) + /*!< Aborted due to time out */ +#define VL53L1_ERROR_MODE_NOT_SUPPORTED ((VL53L1_Error) - 8) + /*!< Asked mode is not supported by the device */ +#define VL53L1_ERROR_BUFFER_TOO_SMALL ((VL53L1_Error) - 9) + /*!< ... */ +#define VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL ((VL53L1_Error) - 10) + /*!< Supplied buffer is larger than I2C supports */ +#define VL53L1_ERROR_GPIO_NOT_EXISTING ((VL53L1_Error) - 11) + /*!< User tried to setup a non-existing GPIO pin */ +#define VL53L1_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED ((VL53L1_Error) - 12) + /*!< unsupported GPIO functionality */ +#define VL53L1_ERROR_CONTROL_INTERFACE ((VL53L1_Error) - 13) + /*!< error reported from IO functions */ +#define VL53L1_ERROR_INVALID_COMMAND ((VL53L1_Error) - 14) + /*!< The command is not allowed in the current device state + * (power down) */ +#define VL53L1_ERROR_DIVISION_BY_ZERO ((VL53L1_Error) - 15) + /*!< In the function a division by zero occurs */ +#define VL53L1_ERROR_REF_SPAD_INIT ((VL53L1_Error) - 16) + /*!< Error during reference SPAD initialization */ +#define VL53L1_ERROR_GPH_SYNC_CHECK_FAIL ((VL53L1_Error) - 17) + /*!< GPH sync interrupt check fail - API out of sync with device*/ +#define VL53L1_ERROR_STREAM_COUNT_CHECK_FAIL ((VL53L1_Error) - 18) + /*!< Stream count check fail - API out of sync with device */ +#define VL53L1_ERROR_GPH_ID_CHECK_FAIL ((VL53L1_Error) - 19) + /*!< GPH ID check fail - API out of sync with device */ +#define VL53L1_ERROR_ZONE_STREAM_COUNT_CHECK_FAIL ((VL53L1_Error) - 20) + /*!< Zone dynamic config stream count check failed - API out of sync */ +#define VL53L1_ERROR_ZONE_GPH_ID_CHECK_FAIL ((VL53L1_Error) - 21) + /*!< Zone dynamic config GPH ID check failed - API out of sync */ + +#define VL53L1_ERROR_XTALK_EXTRACTION_NO_SAMPLE_FAIL ((VL53L1_Error) - 22) + /*!< Thrown when run_xtalk_extraction fn has 0 succesful samples + * when using the full array to sample the xtalk. In this case there is + * not enough information to generate new Xtalk parm info. The function + * will exit and leave the current xtalk parameters unaltered */ +#define VL53L1_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL ((VL53L1_Error) - 23) + /*!< Thrown when run_xtalk_extraction fn has found that the + * avg sigma estimate of the full array xtalk sample is > than the + * maximal limit allowed. In this case the xtalk sample is too noisy for + * measurement. The function will exit and leave the current xtalk parameters + * unaltered. */ + + +#define VL53L1_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL ((VL53L1_Error) - 24) + /*!< Thrown if there one of stages has no valid offset calibration + * samples. A fatal error calibration not valid */ +#define VL53L1_ERROR_OFFSET_CAL_NO_SPADS_ENABLED_FAIL ((VL53L1_Error) - 25) + /*!< Thrown if there one of stages has zero effective SPADS + * Traps the case when MM1 SPADs is zero. + * A fatal error calibration not valid */ +#define VL53L1_ERROR_ZONE_CAL_NO_SAMPLE_FAIL ((VL53L1_Error) - 26) + /*!< Thrown if then some of the zones have no valid samples + * A fatal error calibration not valid */ + +#define VL53L1_ERROR_TUNING_PARM_KEY_MISMATCH ((VL53L1_Error) - 27) + /*!< Thrown if the tuning file key table version does not match with + * expected value. The driver expects the key table version to match + * the compiled default version number in the define + * #VL53L1_TUNINGPARM_KEY_TABLE_VERSION_DEFAULT + * */ + +#define VL53L1_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS ((VL53L1_Error) - 28) + /*!< Thrown if there are less than 5 good SPADs are available. */ +#define VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH ((VL53L1_Error) - 29) + /*!< Thrown if the final reference rate is greater than + the upper reference rate limit - default is 40 Mcps. + Implies a minimum Q3 (x10) SPAD (5) selected */ +#define VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW ((VL53L1_Error) - 30) + /*!< Thrown if the final reference rate is less than + the lower reference rate limit - default is 10 Mcps. + Implies maximum Q1 (x1) SPADs selected */ + + +#define VL53L1_WARNING_OFFSET_CAL_MISSING_SAMPLES ((VL53L1_Error) - 31) + /*!< Thrown if there is less than the requested number of + * valid samples. */ +#define VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH ((VL53L1_Error) - 32) + /*!< Thrown if the offset calibration range sigma estimate is greater + * than 8.0 mm. This is the recommended min value to yield a stable + * offset measurement */ +#define VL53L1_WARNING_OFFSET_CAL_RATE_TOO_HIGH ((VL53L1_Error) - 33) + /*!< Thrown when VL53L1_run_offset_calibration() peak rate is greater + than that 50.0Mcps. This is the recommended max rate to avoid + pile-up influencing the offset measurement */ +#define VL53L1_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW ((VL53L1_Error) - 34) + /*!< Thrown when VL53L1_run_offset_calibration() when one of stages + range has less that 5.0 effective SPADS. This is the recommended + min value to yield a stable offset */ + + +#define VL53L1_WARNING_ZONE_CAL_MISSING_SAMPLES ((VL53L1_Error) - 35) + /*!< Thrown if one of more of the zones have less than + the requested number of valid samples */ +#define VL53L1_WARNING_ZONE_CAL_SIGMA_TOO_HIGH ((VL53L1_Error) - 36) + /*!< Thrown if one or more zones have sigma estimate value greater + * than 8.0 mm. This is the recommended min value to yield a stable + * offset measurement */ +#define VL53L1_WARNING_ZONE_CAL_RATE_TOO_HIGH ((VL53L1_Error) - 37) + /*!< Thrown if one of more zones have peak rate higher than + that 50.0Mcps. This is the recommended max rate to avoid + pile-up influencing the offset measurement */ + + +#define VL53L1_WARNING_XTALK_MISSING_SAMPLES ((VL53L1_Error) - 38) + /*!< Thrown to notify that some of the xtalk samples did not yield + * valid ranging pulse data while attempting to measure + * the xtalk signal in vl53l1_run_xtalk_extract(). This can signify any of + * the zones are missing samples, for further debug information the + * xtalk_results struct should be referred to. This warning is for + * notification only, the xtalk pulse and shape have still been generated + */ +#define VL53L1_WARNING_XTALK_NO_SAMPLES_FOR_GRADIENT ((VL53L1_Error) - 39) + /*!< Thrown to notify that some of teh xtalk samples used for gradient + * generation did not yield valid ranging pulse data while attempting to + * measure the xtalk signal in vl53l1_run_xtalk_extract(). This can signify + * that any one of the zones 0-3 yielded no successful samples. The + * xtalk_results struct should be referred to for further debug info. + * This warning is for notification only, the xtalk pulse and shape + * have still been generated. + */ +#define VL53L1_WARNING_XTALK_SIGMA_LIMIT_FOR_GRADIENT ((VL53L1_Error) - 40) +/*!< Thrown to notify that some of the xtalk samples used for gradient + * generation did not pass the sigma limit check while attempting to + * measure the xtalk signal in vl53l1_run_xtalk_extract(). This can signify + * that any one of the zones 0-3 yielded an avg sigma_mm value > the limit. + * The xtalk_results struct should be referred to for further debug info. + * This warning is for notification only, the xtalk pulse and shape + * have still been generated. + */ + +#define VL53L1_ERROR_NOT_IMPLEMENTED ((VL53L1_Error) - 41) + /*!< Tells requested functionality has not been implemented yet or + * not compatible with the device */ +#define VL53L1_ERROR_PLATFORM_SPECIFIC_START ((VL53L1_Error) - 60) + /*!< Tells the starting code for platform */ +/** @} VL53L1_define_Error_group */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* _VL53L1_ERROR_CODES_H_ */ diff --git a/App/VL53L1X_API/core/inc/vl53l1_error_exceptions.h b/App/VL53L1X_API/core/inc/vl53l1_error_exceptions.h new file mode 100644 index 0000000..b4992c9 --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_error_exceptions.h @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_error_exceptions.h + * + * @brief EwokPlus25 LL Driver definitions for control of error handling in LL driver + */ + +#ifndef _VL53L1_ERROR_EXCEPTIONS_H_ +#define _VL53L1_ERROR_EXCEPTIONS_H_ + +#define IGNORE_DIVISION_BY_ZERO 0 + +#define IGNORE_XTALK_EXTRACTION_NO_SAMPLE_FAIL 0 +#define IGNORE_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL 0 +#define IGNORE_XTALK_EXTRACTION_NO_SAMPLE_FOR_GRADIENT_WARN 0 +#define IGNORE_XTALK_EXTRACTION_SIGMA_LIMIT_FOR_GRADIENT_WARN 0 +#define IGNORE_XTALK_EXTRACTION_MISSING_SAMPLES_WARN 0 + +#define IGNORE_REF_SPAD_CHAR_NOT_ENOUGH_SPADS 0 +#define IGNORE_REF_SPAD_CHAR_RATE_TOO_HIGH 0 +#define IGNORE_REF_SPAD_CHAR_RATE_TOO_LOW 0 + +#define IGNORE_OFFSET_CAL_MISSING_SAMPLES 0 +#define IGNORE_OFFSET_CAL_SIGMA_TOO_HIGH 0 +#define IGNORE_OFFSET_CAL_RATE_TOO_HIGH 0 +#define IGNORE_OFFSET_CAL_SPAD_COUNT_TOO_LOW 0 + +#define IGNORE_ZONE_CAL_MISSING_SAMPLES 0 +#define IGNORE_ZONE_CAL_SIGMA_TOO_HIGH 0 +#define IGNORE_ZONE_CAL_RATE_TOO_HIGH 0 + +#endif /* _VL53L1_ERROR_EXCEPTIONS_H_ */ diff --git a/App/VL53L1X_API/core/inc/vl53l1_error_strings.h b/App/VL53L1X_API/core/inc/vl53l1_error_strings.h new file mode 100644 index 0000000..192bb9b --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_error_strings.h @@ -0,0 +1,209 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_error_strings.h + * @brief VL53L1 function declarations for decoding error codes to a + * text strings + */ + + +#ifndef VL53L1_ERROR_STRINGS_H_ +#define VL53L1_ERROR_STRINGS_H_ + +#include "vl53l1_error_codes.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Generates an error string for the input PAL error code + * + * @param[in] PalErrorCode : PAL Error Code + * @param[out] pPalErrorString : pointer to character buffer + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_pal_error_string( + VL53L1_Error PalErrorCode, + char *pPalErrorString); + + +#ifndef VL53L1_USE_EMPTY_STRING + + /* PAL ERROR strings */ + #define VL53L1_STRING_ERROR_NONE \ + "No Error" + #define VL53L1_STRING_ERROR_CALIBRATION_WARNING \ + "Calibration Warning Error" + #define VL53L1_STRING_ERROR_MIN_CLIPPED \ + "Min clipped error" + #define VL53L1_STRING_ERROR_UNDEFINED \ + "Undefined error" + #define VL53L1_STRING_ERROR_INVALID_PARAMS \ + "Invalid parameters error" + #define VL53L1_STRING_ERROR_NOT_SUPPORTED \ + "Not supported error" + #define VL53L1_STRING_ERROR_RANGE_ERROR \ + "Range error" + #define VL53L1_STRING_ERROR_TIME_OUT \ + "Time out error" + #define VL53L1_STRING_ERROR_MODE_NOT_SUPPORTED \ + "Mode not supported error" + #define VL53L1_STRING_ERROR_BUFFER_TOO_SMALL \ + "Buffer too small" + #define VL53L1_STRING_ERROR_COMMS_BUFFER_TOO_SMALL \ + "Comms Buffer too small" + #define VL53L1_STRING_ERROR_GPIO_NOT_EXISTING \ + "GPIO not existing" + #define VL53L1_STRING_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED \ + "GPIO funct not supported" + #define VL53L1_STRING_ERROR_CONTROL_INTERFACE \ + "Control Interface Error" + #define VL53L1_STRING_ERROR_INVALID_COMMAND \ + "Invalid Command Error" + #define VL53L1_STRING_ERROR_DIVISION_BY_ZERO \ + "Division by zero Error" + #define VL53L1_STRING_ERROR_REF_SPAD_INIT \ + "Reference Spad Init Error" + #define VL53L1_STRING_ERROR_GPH_SYNC_CHECK_FAIL \ + "GPH Sync Check Fail - API out of sync" + #define VL53L1_STRING_ERROR_STREAM_COUNT_CHECK_FAIL \ + "Stream Count Check Fail - API out of sync" + #define VL53L1_STRING_ERROR_GPH_ID_CHECK_FAIL \ + "GPH ID Check Fail - API out of sync" + #define VL53L1_STRING_ERROR_ZONE_STREAM_COUNT_CHECK_FAIL \ + "Zone Stream Count Check Fail - API out of sync" + #define VL53L1_STRING_ERROR_ZONE_GPH_ID_CHECK_FAIL \ + "Zone GPH ID Check Fail - API out of sync" + + #define VL53L1_STRING_ERROR_XTALK_EXTRACTION_NO_SAMPLES_FAIL \ + "No Xtalk using full array - Xtalk Extract Fail" + #define VL53L1_STRING_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL \ + "Xtalk does not meet required sigma limit - Xtalk Extract Fail" + + #define VL53L1_STRING_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL \ + "Offset Cal - one of more stages with no valid samples - fatal" + #define VL53L1_STRING_ERROR_OFFSET_CAL_NO_SPADS_ENABLED_FAIL \ + "Offset Cal - one of more stages with no SPADS enables - fatal" + #define VL53L1_STRING_ERROR_ZONE_CAL_NO_SAMPLE_FAIL \ + "Zone Cal - one of more zones with no valid samples - fatal" + + #define VL53L1_STRING_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS \ + "Ref SPAD Char - Not Enough Good SPADs" + #define VL53L1_STRING_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH \ + "Ref SPAD Char - Final Ref Rate too high" + #define VL53L1_STRING_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW \ + "Ref SPAD Char - Final Ref Rate too low" + + #define VL53L1_STRING_WARNING_OFFSET_CAL_MISSING_SAMPLES \ + "Offset Cal - Less than the requested number of valid samples" + #define VL53L1_STRING_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH \ + "Offset Cal - Sigma estimate value too high - offset not stable" + #define VL53L1_STRING_WARNING_OFFSET_CAL_RATE_TOO_HIGH \ + "Offset Cal - Rate too high - in pile up" + #define VL53L1_STRING_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW \ + "Offset Cal - Insufficient SPADs - offset may not be stable" + + #define VL53L1_STRING_WARNING_ZONE_CAL_MISSING_SAMPLES \ + "Zone Cal - One or more zone with less than requested valid samples" + #define VL53L1_STRING_WARNING_ZONE_CAL_SIGMA_TOO_HIGH \ + "Zone Cal - One of more zones the sigma estimate too high" + #define VL53L1_STRING_WARNING_ZONE_CAL_RATE_TOO_HIGH \ + "Zone Cal - One of more zones with rate too high - in pile up" + + #define VL53L1_STRING_WARNING_XTALK_NO_SAMPLES_FOR_GRADIENT \ + "Xtalk - Gradient sample num = 0" + #define VL53L1_STRING_WARNING_XTALK_SIGMA_LIMIT_FOR_GRADIENT \ + "Xtalk - Gradient Sigma > Limit" + #define VL53L1_STRING_WARNING_XTALK_MISSING_SAMPLES \ + "Xtalk - Some missing and invalid samples" + + #define VL53L1_STRING_ERROR_DEVICE_FIRMWARE_TOO_OLD \ + "Device Firmware too old" + #define VL53L1_STRING_ERROR_DEVICE_FIRMWARE_TOO_NEW \ + "Device Firmware too new" + #define VL53L1_STRING_ERROR_UNIT_TEST_FAIL \ + "Unit Test Fail" + #define VL53L1_STRING_ERROR_FILE_READ_FAIL \ + "File Read Fail" + #define VL53L1_STRING_ERROR_FILE_WRITE_FAIL \ + "File Write Fail" + + #define VL53L1_STRING_ERROR_NOT_IMPLEMENTED \ + "Not implemented error" + #define VL53L1_STRING_UNKNOW_ERROR_CODE \ + "Unknown Error Code" + +#endif /* VL53L1_USE_EMPTY_STRING */ + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/App/VL53L1X_API/core/inc/vl53l1_ll_def.h b/App/VL53L1X_API/core/inc/vl53l1_ll_def.h new file mode 100644 index 0000000..e515fe2 --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_ll_def.h @@ -0,0 +1,1098 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_ll_def.h + * + * @brief Type definitions for VL53L1 LL Driver. + * + */ + + +#ifndef _VL53L1_LL_DEF_H_ +#define _VL53L1_LL_DEF_H_ + +#include "vl53l1_ll_device.h" +#include "vl53l1_error_codes.h" +#include "vl53l1_register_structs.h" +#include "vl53l1_platform_user_config.h" +#include "vl53l1_platform_user_defines.h" +#include "vl53l1_error_exceptions.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup VL53L1_globalLLDriverDefine_group VL53L1 Defines + * @brief VL53L1 LL Driver Defines + * @{ + */ + +/** VL53L1 Low Level Driver IMPLEMENTATION major version */ +#define VL53L1_LL_API_IMPLEMENTATION_VER_MAJOR 1 +/** VL53L1 Low Level DriverI IMPLEMENTATION minor version */ +#define VL53L1_LL_API_IMPLEMENTATION_VER_MINOR 2 +/** VL53L1 Low Level DriverI IMPLEMENTATION sub version */ +#define VL53L1_LL_API_IMPLEMENTATION_VER_SUB 13 +/** VL53L1 Low Level Driver IMPLEMENTATION sub version */ +#define VL53L1_LL_API_IMPLEMENTATION_VER_REVISION 2190 + +#define VL53L1_LL_API_IMPLEMENTATION_VER_STRING "1.2.13.2190" + +/** VL53L1_FIRMWARE min and max compatible revisions */ +#define VL53L1_FIRMWARE_VER_MINIMUM 398 +#define VL53L1_FIRMWARE_VER_MAXIMUM 400 + + +/**************************************** + * PRIVATE define do not edit + ****************************************/ + +#define VL53L1_LL_CALIBRATION_DATA_STRUCT_VERSION 0xECAB0102 + /** VL53L1 Calibration Data struct version */ + +/* Start Patch_ZoneCalDataStructVersion_11854 */ + +#define VL53L1_LL_ZONE_CALIBRATION_DATA_STRUCT_VERSION 0xECAE0101 + /** VL53L1 Zone Calibration Data struct version */ + +/* End Patch_ZoneCalDataStructVersion_11854 */ + +#define VL53L1_MAX_OFFSET_RANGE_RESULTS 3 + /*!< Sets the maximum number of offset range results + required for the offset calibration. + Order is RANGE, MM1, MM2 */ + +#define VL53L1_NVM_MAX_FMT_RANGE_DATA 4 + /*!< The number of FMT range data points stored in NVM */ + +#define VL53L1_NVM_PEAK_RATE_MAP_SAMPLES 25 + /*!< The number of samples in the NVM peak rate signal map */ +#define VL53L1_NVM_PEAK_RATE_MAP_WIDTH 5 + /*!< Array width of NVM peak rate signal map */ +#define VL53L1_NVM_PEAK_RATE_MAP_HEIGHT 5 + /*!< Array height the NVM peak rate signal map */ + +/** @defgroup VL53L1_defineExtraError_group Error and Warning code returned by API + * The following DEFINE are used to identify the PAL ERROR + * @{ + */ + +#define VL53L1_ERROR_DEVICE_FIRMWARE_TOO_OLD ((VL53L1_Error) - 80) + /*!< Device Firmware too old .. */ +#define VL53L1_ERROR_DEVICE_FIRMWARE_TOO_NEW ((VL53L1_Error) - 85) + /*!< Device Firmware too new .. */ +#define VL53L1_ERROR_UNIT_TEST_FAIL ((VL53L1_Error) - 90) + /*!< Unit Test Fail */ +#define VL53L1_ERROR_FILE_READ_FAIL ((VL53L1_Error) - 95) + /*!< File Read Fail */ +#define VL53L1_ERROR_FILE_WRITE_FAIL ((VL53L1_Error) - 96) + /*!< File Write Fail */ + /*!< Tells requested functionality has not been implemented yet or + * not compatible with the device */ +/** @} VL53L1_defineExtraError_group */ + + +/** @brief Defines the parameters of the LL driver Get Version Functions + */ +typedef struct { + uint32_t ll_revision; /*!< revision number */ + uint8_t ll_major; /*!< major number */ + uint8_t ll_minor; /*!< minor number */ + uint8_t ll_build; /*!< build number */ +} VL53L1_ll_version_t; + + +/** @brief Reference SPAD Characterization (RefSpadChar) Config + */ + +typedef struct { + + uint8_t device_test_mode; /*!< Device test mode */ + uint8_t vcsel_period; /*!< VCSEL period (register) value */ + uint32_t timeout_us; /*!< timeout in [us] */ + uint16_t target_count_rate_mcps; + /*!< Target reference total count rate in [Mcps] - 9.7 format */ + uint16_t min_count_rate_limit_mcps; + /*!< Min valid reference rate [Mcps] - 9.7 format */ + uint16_t max_count_rate_limit_mcps; + /*!< Max valid reference rate [Mcps] - 9.7 format */ + +} VL53L1_refspadchar_config_t; + + +/** @brief SPAD Self Check (SSC) Config data structure + */ + + +typedef struct { + + VL53L1_DeviceSscArray array_select; + /*!< SPAD Array select + * 0 - store RTN array count rates \n + * 1 - store REF array count rates */ + uint8_t vcsel_period; + /*!< VCSEL period (register) value */ + uint8_t vcsel_start; + /*!< VCSEL start register value */ + uint8_t vcsel_width; + /*!< VCSEL ssc_timeout_us width register value e.g. 2 */ + uint32_t timeout_us; + /*!< requested Ranging Timeout in [us] e.g 100000us */ + uint16_t rate_limit_mcps; + /*!< Rate limit for checks either 1.15 or + * 9.7 dependent on test_mode + */ + +} VL53L1_ssc_config_t; + + +/** @brief Xtalk Extraction and Paramter Config + */ + +typedef struct { + + + uint32_t algo__crosstalk_compensation_plane_offset_kcps; + /*!< Private crosstalk_compensation_plane_offset_kcps (fixed point 9.9) */ + int16_t algo__crosstalk_compensation_x_plane_gradient_kcps; + /*!< Private crosstalk_compensation_x_plane_gradient_kcps (fixed point 5.11) */ + int16_t algo__crosstalk_compensation_y_plane_gradient_kcps; + /*!< Private crosstalk_compensation_y_plane_gradient_kcps (fixed point 5.11) */ + uint32_t nvm_default__crosstalk_compensation_plane_offset_kcps; + /*!< NVm stored crosstalk_compensation_plane_offset_kcps (fixed point 9.9) */ + int16_t nvm_default__crosstalk_compensation_x_plane_gradient_kcps; + /*!< NVM stored crosstalk_compensation_x_plane_gradient_kcps (fixed point 5.11) */ + int16_t nvm_default__crosstalk_compensation_y_plane_gradient_kcps; + /*!< NVM stored crosstalk_compensation_y_plane_gradient_kcps (fixed point 5.11) */ + uint8_t global_crosstalk_compensation_enable; + /*!< Enable switch for crosstalk compensation in all modes */ + int16_t lite_mode_crosstalk_margin_kcps; + /*!< Additional xtalk factor rate, added to plane_offset value in both + * SD mode, applied as a seperate addition at point of + * application to the device, plane_offset + * value remains unaltered. (fixed point 7.9) + */ + uint8_t crosstalk_range_ignore_threshold_mult; + /*!< User set multiplier for range ignore threshold setting (fixed point 3.5) */ + uint16_t crosstalk_range_ignore_threshold_rate_mcps; + /*!< Generated range ignore threshold rate in Mcps per spad (fixed + * point 3.13) + */ + +} VL53L1_xtalk_config_t; + + +/** @brief TuningParameter Storage + * + * - Storage structure for any LLD tuning parms + * which are dynamically altered by low level functions + * mostly when programming directly to the device + * + *- Added as part of Patch_AddingTuningParmStorage_11821 + */ + +typedef struct { + + + uint16_t tp_tuning_parm_version; + /*!< Programmed Global tuning version num for debug + */ + uint16_t tp_tuning_parm_key_table_version; + /*!< Key Table tuning structure \ + * version + */ + uint16_t tp_tuning_parm_lld_version; + /*!< Programmed LLD version to ensure matching tuning structure \ + * key table + */ + uint8_t tp_init_phase_rtn_lite_long; + /*!< initial phase value for rtn array \ + * in Lite Long Ranging Mode + */ + uint8_t tp_init_phase_rtn_lite_med; + /*!< initial phase value for rtn array \ + * in Lite Medium Ranging Mode + */ + uint8_t tp_init_phase_rtn_lite_short; + /*!< initial phase value for rtn array \ + * in Lite Short Ranging Mode + */ + uint8_t tp_init_phase_ref_lite_long; + /*!< initial phase value for ref array \ + * in Lite Long Ranging Mode + */ + uint8_t tp_init_phase_ref_lite_med; + /*!< initial phase value for ref array \ + * in Lite Medium Ranging Mode + */ + uint8_t tp_init_phase_ref_lite_short; + /*!< initial phase value for ref array \ + * in Lite short Ranging Mode + */ + + uint8_t tp_consistency_lite_phase_tolerance; + /*!< Phase tolerance consistency value to be used \ + * in Lite modes + */ + uint8_t tp_phasecal_target; + /*!< Phasecal target value + */ + uint16_t tp_cal_repeat_rate; + /*!< Auto VHV/Calibration repeat rate for \ + * use in Lite mode + */ + uint8_t tp_lite_min_clip; + /*!< Min Clip value in mm applied to device in Lite \ + * modes + */ + + uint16_t tp_lite_long_sigma_thresh_mm; + /*!< Sigma threshold limit for Lite Long mode \ + * in 14.2 format mm + */ + uint16_t tp_lite_med_sigma_thresh_mm; + /*!< Sigma threshold limit for Lite Medium mode \ + * in 14.2 format mm + */ + uint16_t tp_lite_short_sigma_thresh_mm; + /*!< Sigma threshold limit for Lite Short mode \ + * in 14.2 format mm + */ + + uint16_t tp_lite_long_min_count_rate_rtn_mcps; + /*!< Min count rate level used in lite long mode \ + * in 9.7 Mcps format + */ + uint16_t tp_lite_med_min_count_rate_rtn_mcps; + /*!< Min count rate level used in lite medium mode \ + * in 9.7 Mcps format + */ + uint16_t tp_lite_short_min_count_rate_rtn_mcps; + /*!< Min count rate level used in lite short mode \ + * in 9.7 Mcps format + */ + + uint8_t tp_lite_sigma_est_pulse_width_ns; + /*!< Sigma thresholding tunign parm for Lite mode + */ + uint8_t tp_lite_sigma_est_amb_width_ns; + /*!< Sigma thresholding tunign parm for Lite mode + */ + uint8_t tp_lite_sigma_ref_mm; + /*!< Sigma thresholding tunign parm for Lite mode + */ + uint8_t tp_lite_seed_cfg; + /*!< Lite Mode Seed mode switch + */ + uint8_t tp_timed_seed_cfg; + /*!< Timed Mode Seed mode switch + */ + + uint8_t tp_lite_quantifier; + /*!< Low level quantifier setting for lite modes + */ + uint8_t tp_lite_first_order_select; + /*!< Low level First order select setting for lite modes + */ + + uint16_t tp_dss_target_lite_mcps; + /*!< DSS Target rate in 9.7 format Mcps for lite modes + */ + uint16_t tp_dss_target_timed_mcps; + /*!< DSS Target rate in 9.7 format Mcps for Timed modes + */ + + uint32_t tp_phasecal_timeout_lite_us; + /*!< Phasecal timeout in us for lite modes + */ + + uint32_t tp_phasecal_timeout_timed_us; + /*!< Phasecal timeout in us for Timed modes + */ + + uint32_t tp_mm_timeout_lite_us; + /*!< MM stage timeout in us for Lite modes + */ + uint32_t tp_mm_timeout_timed_us; + /*!< MM stage timeout in us for Timed modes + */ + uint32_t tp_mm_timeout_lpa_us; + /*!< MM stage timeout in us for Low Power Auto modes + */ + + uint32_t tp_range_timeout_lite_us; + /*!< Ranging stage timeout in us for Lite modes + */ + uint32_t tp_range_timeout_timed_us; + /*!< Ranging stage timeout in us for Timed modes + */ + uint32_t tp_range_timeout_lpa_us; + /*!< Ranging stage timeout in us for Low Power Auto modes + */ + +} VL53L1_tuning_parm_storage_t; + + + +/** @brief Optical Centre data + * + */ + +typedef struct { + + uint8_t x_centre; /*!< Optical x centre : 4.4 format */ + uint8_t y_centre; /*!< Optical y centre : 4.4 format */ + +} VL53L1_optical_centre_t; + + +/** @brief Defines User Zone(ROI) parameters + * + */ + +typedef struct { + + uint8_t x_centre; /*!< Zone x centre : 0-15 range */ + uint8_t y_centre; /*!< Zone y centre : 0-15 range */ + uint8_t width; /*!< Width of Zone 0 = 1, 7 = 8, 15 = 16 */ + uint8_t height; /*!< Height of Zone 0 = 1, 7 = 8, 15 = 16 */ + +} VL53L1_user_zone_t; + + +/** + * @struct VL53L1_GPIO_interrupt_config_t + * + * @brief Structure to configure conditions when GPIO interrupt is trigerred + * + */ + +typedef struct { + + /*! Distance interrupt mode */ + VL53L1_GPIO_Interrupt_Mode intr_mode_distance; + + /*! Rate interrupt mode */ + VL53L1_GPIO_Interrupt_Mode intr_mode_rate; + + /*! trigger interrupt if a new measurement is ready + * __WARNING!__ will override other settings + */ + uint8_t intr_new_measure_ready; + + /*! Trigger interrupt if no target found */ + uint8_t intr_no_target; + + /*! If set to 0, interrupts will only be triggered if BOTH rate AND + * distance thresholds are triggered (combined mode). If set to 1, + * interrupts will be triggered if EITHER rate OR distance thresholds + * are triggered (independent mode). */ + uint8_t intr_combined_mode; + + /* -- thresholds -- */ + /* The struct holds a copy of the thresholds but they are written when + * this structure is set using VL53L1_set_GPIO_interrupt_config/_struct + * */ + + /*! Distance threshold high limit (mm) */ + uint16_t threshold_distance_high; + + /*! Distance threshold low limit (mm) */ + uint16_t threshold_distance_low; + + /*! Rate threshold high limit (9.7 Mcps) */ + uint16_t threshold_rate_high; + + /*! Rate threshold low limit (9.7 Mcps) */ + uint16_t threshold_rate_low; + +} VL53L1_GPIO_interrupt_config_t; + +/* Start Patch_LowPowerAutoMode */ +/** + * @struct VL53L1_low_power_auto_data_t + * + * @brief Structure to hold state, tuning and output variables for the low + * power auto mode (Presence) + * + */ + +typedef struct { + + /*! Tuning variable for the VHV loop bound setting in low power auto + * mode. This is zero based, so the number of loops in VHV is this + 1. + * Please note, the first range will run with default VHV settings. + * Only lower 6 bits are allowed */ + uint8_t vhv_loop_bound; + + /*! Indicates if we are or are not in low power auto mode */ + uint8_t is_low_power_auto_mode; + + /*! Used to check if we're running the first range or not. Not to be + * used as a stream count */ + uint8_t low_power_auto_range_count; + + /*! saved interrupt config byte to restore */ + uint8_t saved_interrupt_config; + + /*! saved vhv config init byte to restore */ + uint8_t saved_vhv_init; + + /*! saved vhv config timeout byte to restore */ + uint8_t saved_vhv_timeout; + + /*! phase cal resutl from the first range */ + uint8_t first_run_phasecal_result; + + /*! DSS. Total rate per spad given from the current range */ + uint32_t dss__total_rate_per_spad_mcps; + + /*! DSS. Calculated required SPADs value */ + uint16_t dss__required_spads; + +} VL53L1_low_power_auto_data_t; + +/* End Patch_LowPowerAutoMode */ + +/** + * @struct VL53L1_range_data_t + * @brief Internal data structure for storing post processed ranges + * + */ + +typedef struct { + + /* Info size */ + + uint8_t range_id; + /*!< Range Result id e.g 0, 1, 2 */ + uint32_t time_stamp; + /*!< 32-bit time stamp */ + + uint16_t width; + /*!< VCSEL pulse width in [PLL clocks] 6.4 format */ + uint8_t woi; + /*!< WOI width in [PLL clocks] */ + + uint16_t fast_osc_frequency; + /*!< Oscillator frequency in 4.12 format */ + uint16_t zero_distance_phase; + /*!< Zero Distance phase in 5.11 format */ + uint16_t actual_effective_spads; + /*!< effective SPAD count in 8.8 format */ + + uint32_t total_periods_elapsed; + /*!< Elapsed time in macro periods for readout channel */ + + uint32_t peak_duration_us; + /*!< Peak VCSEL width time in us */ + + uint32_t woi_duration_us; + /*!< WOI duration time in us */ + + + /* Event counts */ + + uint32_t ambient_window_events; + /*!< Return event count for the ambient window */ + uint32_t ranging_total_events; + /*!< Return ranging event count for the ranging window. + This includes both VCSEL and ambient contributions */ + int32_t signal_total_events; + /*!< Return event count for the ranging window with ambient + subtracted, Note it is 32-bit signed register */ + + /* Rates */ + + uint16_t peak_signal_count_rate_mcps; + /*! Peak signal (VCSEL) Rate in 9.7 format */ + uint16_t avg_signal_count_rate_mcps; + /*! Average signal (VCSEL) Rate in 9.7 format */ + uint16_t ambient_count_rate_mcps; + /*! Ambient Rate in 9.7 format */ + uint16_t total_rate_per_spad_mcps; + /*! Total Rate Per SPAD in 3.13 format */ + uint32_t peak_rate_per_spad_kcps; + /*! Peak Rate Per SPAD in 13.11 format */ + + /* Sigma */ + + uint16_t sigma_mm; + /*!< Range sigma Estimate [mm] 9.7 format */ + + /* Phase */ + + uint16_t median_phase; + /*!< Median Phase in 5.11 format */ + + /* Range */ + + int16_t median_range_mm; + /*!< Median Range in [mm] by default there are no fractional bits + Optionally 1 or 2 fractional can be enabled via the + VL53L1_SYSTEM__FRACTIONAL_ENABLE register */ + + /* Range status */ + + uint8_t range_status; + +} VL53L1_range_data_t; + + +/** + * @struct VL53L1_range_results_t + * @brief Structure for storing the set of range results + * + */ + +typedef struct { + + VL53L1_DeviceState cfg_device_state; + /*!< Configuration Device State */ + VL53L1_DeviceState rd_device_state; + /*!< Read Device State */ + uint8_t stream_count; + /*!< 8-bit stream count */ + + uint8_t device_status; + /*!< Global device status for result set */ + + VL53L1_range_data_t data[2]; + /*!< Range data each target distance */ + +} VL53L1_range_results_t; + +/** + * @struct VL53L1_offset_range_data_t + * @brief Structure for storing the set of range results + * required for the mm1 and mm2 offset calibration + * functions + * + */ + +typedef struct { + + uint8_t preset_mode; + /*!< Preset Mode use for range */ + uint8_t dss_config__roi_mode_control; + /*!< Dynamic SPAD selection mode */ + uint16_t dss_config__manual_effective_spads_select; + /*!< Requested number of manual effective SPAD's */ + uint8_t no_of_samples; + /*!< Number of ranges */ + uint32_t effective_spads; + /*!< Average effective SPAD's 8.8 format */ + uint32_t peak_rate_mcps; + /*!< Average peak rate Mcps 9.7 format */ + uint32_t sigma_mm; + /*!< Average sigma in [mm] 14.2 format */ + int32_t median_range_mm; + /*!< Avg of median range over all ranges \ + note value is signed */ + int32_t range_mm_offset; + /*!< The calculated range offset value */ + +} VL53L1_offset_range_data_t; + + +/** + * @struct VL53L1_offset_range_results_t + * @brief Structure for storing the set of range results + * required for the offset calibration functions + * + */ + +typedef struct { + + int16_t cal_distance_mm; + /*!< the calibration distance in [mm]*/ + VL53L1_Error cal_status; + /*!< Calibration status, check for warning codes */ + uint8_t cal_report; + /*!< Stage for above cal status - 0 Pre, 1 = MM1, 2 = MM2 */ + uint8_t max_results; + /*!< Array size for histogram range data i.e. max number + of results */ + uint8_t active_results; + /*!< Number of active measurements */ + VL53L1_offset_range_data_t data[VL53L1_MAX_OFFSET_RANGE_RESULTS]; + /*!< Range results for each offset measurement */ + +} VL53L1_offset_range_results_t; + +/** + * @struct VL53L1_additional_offset_cal_data_t + * @brief Additional Offset Calibration Data + * + * Additional offset calibration data. Contains the rate + * and effective SPAD counts for the MM inner and outer + * calibration steps. + */ + +typedef struct { + + uint16_t result__mm_inner_actual_effective_spads; + /*!< MM Inner actual effective SPADs, 8.8 format */ + uint16_t result__mm_outer_actual_effective_spads; + /*!< MM Outer actual effective SPADs, 8.8 format */ + uint16_t result__mm_inner_peak_signal_count_rtn_mcps; + /*!< Mean value of MM Inner return peak rate in [Mcps], 9.7 format */ + uint16_t result__mm_outer_peak_signal_count_rtn_mcps; + /*!< Mean value of MM Outer return peak rate in [Mcps], 9.7 format */ + +} VL53L1_additional_offset_cal_data_t; + + +/** + * @struct VL53L1_cal_peak_rate_map_t + * @brief Structure for storing the calibration peak rate map + * Used by DMAX to understand the spatial roll off + * in the signal rate map towards the corner of the + * SPAD array. + */ + +typedef struct { + + int16_t cal_distance_mm; + /*!< calibration distance in [mm], 14.2 format */ + uint16_t max_samples; + /*!< Array size for rate map i.e. max number samples */ + uint16_t width; + /*!< Array width */ + uint16_t height; + /*!< Array height */ + uint16_t peak_rate_mcps[VL53L1_NVM_PEAK_RATE_MAP_SAMPLES]; + /*!< Array of rate map samples */ + +} VL53L1_cal_peak_rate_map_t; + + +/** + * @struct VL53L1_gain_calibration_data_t + * + * @brief Gain calibration data + * + */ + +typedef struct { + + uint16_t standard_ranging_gain_factor; + /*!< Standard ranging gain correction factor 1.11 format */ + +} VL53L1_gain_calibration_data_t; + + +/** + * @struct VL53L1_ll_driver_state_t + * + * @brief Contains the driver state information + * + */ + +typedef struct { + + VL53L1_DeviceState cfg_device_state; + /*!< Configuration Device State */ + uint8_t cfg_stream_count; + /*!< configuration stream count, becomes expected + stream count for zone */ + uint8_t cfg_gph_id; + /*!< Config Grouped Parameter Hold ID */ + uint8_t cfg_timing_status; + /*!< Timing A or B flag 0 = A, 1 = B */ + + VL53L1_DeviceState rd_device_state; + /*!< Read Device State */ + uint8_t rd_stream_count; + /*!< rd stream count, used to check actual stream count */ + uint8_t rd_gph_id; + /*!< Read Grouped Parameter Hold ID */ + uint8_t rd_timing_status; + /*!< Timing A or B flag 0 = A, 1 = B */ + +} VL53L1_ll_driver_state_t; + +/** @brief Run Offset Cal Function (offsetcal) Config + */ + +typedef struct { + + uint16_t dss_config__target_total_rate_mcps; + /*!< DSS Target rate in MCPS (9.7 format) used \ + * during run_offset_calibration() */ + uint32_t phasecal_config_timeout_us; + /*!< Phasecal timeout in us \ + * used during run_offset_calibration() */ + uint32_t range_config_timeout_us; + /*!< Range timeout in us used during \ + * run_offset_calibration() */ + uint32_t mm_config_timeout_us; + /*!< MM timeout in us used during \ + * run_offset_calibration() \ + * Added as part of Patch_AddedOffsetCalMMTuningParm_11791 */ + uint8_t pre_num_of_samples; + /*!< Number of Ranging samples used during \ + * run_offset_calibration() */ + uint8_t mm1_num_of_samples; + /*!< Number of MM1 samples used during \ + * run_offset_calibration() */ + uint8_t mm2_num_of_samples; + /*!< Number of MM2 samples used during \ + * run_offset_calibration() */ + +} VL53L1_offsetcal_config_t; + + + +/** + * @struct VL53L1_LLDriverData_t + * + * @brief VL53L1 LL Driver ST private data structure \n + * + */ + +typedef struct { + + uint8_t wait_method; + /*!< Wait type : blocking or non blocking */ + VL53L1_DevicePresetModes preset_mode; + /*!< Current preset mode */ + VL53L1_DeviceMeasurementModes measurement_mode; + /*!< Current measurement mode */ + VL53L1_OffsetCalibrationMode offset_calibration_mode; + /*!< Current offset calibration mode */ + VL53L1_OffsetCorrectionMode offset_correction_mode; + /*!< Current offset_ correction mode */ + uint32_t phasecal_config_timeout_us; + /*!< requested Phase Cal Timeout e.g. 1000us */ + uint32_t mm_config_timeout_us; + /*!< requested MM Timeout e.g. 2000us */ + uint32_t range_config_timeout_us; + /*!< requested Ranging Timeout e.g 13000us */ + uint32_t inter_measurement_period_ms; + /*!< requested Timing mode repeat period e.g 100ms */ + uint16_t dss_config__target_total_rate_mcps; + /*!< requested DSS Target Total Rate in 9.7 format e.g. 40.0Mcps + * - Patch_ChangingPresetModeInputParms_11780 */ + uint32_t fw_ready_poll_duration_ms; + /*!< FW ready poll duration in ms*/ + uint8_t fw_ready; + /*!< Result of FW ready check */ + uint8_t debug_mode; + /*!< Internal Only - read extra debug data */ + + /*!< version info structure */ + VL53L1_ll_version_t version; + + /*!< version info structure */ + VL53L1_ll_driver_state_t ll_state; + + /*!< decoded GPIO interrupt config */ + VL53L1_GPIO_interrupt_config_t gpio_interrupt_config; + + /*!< public register data structures */ + VL53L1_customer_nvm_managed_t customer; + VL53L1_cal_peak_rate_map_t cal_peak_rate_map; + VL53L1_additional_offset_cal_data_t add_off_cal_data; + VL53L1_gain_calibration_data_t gain_cal; + VL53L1_user_zone_t mm_roi; + VL53L1_optical_centre_t optical_centre; + + /*!< tuning parameter storage */ + VL53L1_tuning_parm_storage_t tuning_parms; + + /*!< private return good SPAD map */ + uint8_t rtn_good_spads[VL53L1_RTN_SPAD_BUFFER_SIZE]; + + /*!< private internal configuration structures */ + VL53L1_refspadchar_config_t refspadchar; + VL53L1_ssc_config_t ssc_cfg; + VL53L1_xtalk_config_t xtalk_cfg; + VL53L1_offsetcal_config_t offsetcal_cfg; + + /*!< private internal register data structures */ + VL53L1_static_nvm_managed_t stat_nvm; + VL53L1_static_config_t stat_cfg; + VL53L1_general_config_t gen_cfg; + VL53L1_timing_config_t tim_cfg; + VL53L1_dynamic_config_t dyn_cfg; + VL53L1_system_control_t sys_ctrl; + VL53L1_system_results_t sys_results; + VL53L1_nvm_copy_data_t nvm_copy_data; + + /*!< Private Offset structure */ + VL53L1_offset_range_results_t offset_results; + + /*!< private debug register data structures */ + VL53L1_core_results_t core_results; + VL53L1_debug_results_t dbg_results; + + /* Start Patch_LowPowerAutoMode */ + /*!< Low Powr Auto Mode Data */ + VL53L1_low_power_auto_data_t low_power_auto_data; + /* End Patch_LowPowerAutoMode */ + +#ifdef PAL_EXTENDED + /* Patch Debug Data */ + VL53L1_patch_results_t patch_results; + VL53L1_shadow_core_results_t shadow_core_results; + VL53L1_shadow_system_results_t shadow_sys_results; + VL53L1_prev_shadow_core_results_t prev_shadow_core_results; + VL53L1_prev_shadow_system_results_t prev_shadow_sys_results; +#endif + +} VL53L1_LLDriverData_t; + + +/** + * @struct VL53L1_LLDriverResults_t + * + * @brief VL53L1 LL Driver ST private results structure + * + */ + +typedef struct { + + /* Private last range results */ + VL53L1_range_results_t range_results; + +} VL53L1_LLDriverResults_t; + +/** + * @struct VL53L1_calibration_data_t + * + * @brief Per Part calibration data + * + */ + +typedef struct { + + uint32_t struct_version; + VL53L1_customer_nvm_managed_t customer; + VL53L1_additional_offset_cal_data_t add_off_cal_data; + VL53L1_optical_centre_t optical_centre; + VL53L1_gain_calibration_data_t gain_cal; + VL53L1_cal_peak_rate_map_t cal_peak_rate_map; + +} VL53L1_calibration_data_t; + + +/** + * @struct VL53L1_tuning_parameters_t + * + * @brief Tuning Parameters Debug data + * + */ + +typedef struct { + uint16_t vl53l1_tuningparm_version; + uint16_t vl53l1_tuningparm_key_table_version; + uint16_t vl53l1_tuningparm_lld_version; + uint8_t vl53l1_tuningparm_consistency_lite_phase_tolerance; + uint8_t vl53l1_tuningparm_phasecal_target; + uint16_t vl53l1_tuningparm_lite_cal_repeat_rate; + uint16_t vl53l1_tuningparm_lite_ranging_gain_factor; + uint8_t vl53l1_tuningparm_lite_min_clip_mm; + uint16_t vl53l1_tuningparm_lite_long_sigma_thresh_mm; + uint16_t vl53l1_tuningparm_lite_med_sigma_thresh_mm; + uint16_t vl53l1_tuningparm_lite_short_sigma_thresh_mm; + uint16_t vl53l1_tuningparm_lite_long_min_count_rate_rtn_mcps; + uint16_t vl53l1_tuningparm_lite_med_min_count_rate_rtn_mcps; + uint16_t vl53l1_tuningparm_lite_short_min_count_rate_rtn_mcps; + uint8_t vl53l1_tuningparm_lite_sigma_est_pulse_width; + uint8_t vl53l1_tuningparm_lite_sigma_est_amb_width_ns; + uint8_t vl53l1_tuningparm_lite_sigma_ref_mm; + uint8_t vl53l1_tuningparm_lite_rit_mult; + uint8_t vl53l1_tuningparm_lite_seed_config; + uint8_t vl53l1_tuningparm_lite_quantifier; + uint8_t vl53l1_tuningparm_lite_first_order_select; + int16_t vl53l1_tuningparm_lite_xtalk_margin_kcps; + uint8_t vl53l1_tuningparm_initial_phase_rtn_lite_long_range; + uint8_t vl53l1_tuningparm_initial_phase_rtn_lite_med_range; + uint8_t vl53l1_tuningparm_initial_phase_rtn_lite_short_range; + uint8_t vl53l1_tuningparm_initial_phase_ref_lite_long_range; + uint8_t vl53l1_tuningparm_initial_phase_ref_lite_med_range; + uint8_t vl53l1_tuningparm_initial_phase_ref_lite_short_range; + uint8_t vl53l1_tuningparm_timed_seed_config; + uint8_t vl53l1_tuningparm_vhv_loopbound; + uint8_t vl53l1_tuningparm_refspadchar_device_test_mode; + uint8_t vl53l1_tuningparm_refspadchar_vcsel_period; + uint32_t vl53l1_tuningparm_refspadchar_phasecal_timeout_us; + uint16_t vl53l1_tuningparm_refspadchar_target_count_rate_mcps; + uint16_t vl53l1_tuningparm_refspadchar_min_countrate_limit_mcps; + uint16_t vl53l1_tuningparm_refspadchar_max_countrate_limit_mcps; + uint16_t vl53l1_tuningparm_offset_cal_dss_rate_mcps; + uint32_t vl53l1_tuningparm_offset_cal_phasecal_timeout_us; + uint32_t vl53l1_tuningparm_offset_cal_mm_timeout_us; + uint32_t vl53l1_tuningparm_offset_cal_range_timeout_us; + uint8_t vl53l1_tuningparm_offset_cal_pre_samples; + uint8_t vl53l1_tuningparm_offset_cal_mm1_samples; + uint8_t vl53l1_tuningparm_offset_cal_mm2_samples; + uint8_t vl53l1_tuningparm_spadmap_vcsel_period; + uint8_t vl53l1_tuningparm_spadmap_vcsel_start; + uint16_t vl53l1_tuningparm_spadmap_rate_limit_mcps; + uint16_t vl53l1_tuningparm_lite_dss_config_target_total_rate_mcps; + uint16_t vl53l1_tuningparm_timed_dss_config_target_total_rate_mcps; + uint32_t vl53l1_tuningparm_lite_phasecal_config_timeout_us; + uint32_t vl53l1_tuningparm_timed_phasecal_config_timeout_us; + uint32_t vl53l1_tuningparm_lite_mm_config_timeout_us; + uint32_t vl53l1_tuningparm_timed_mm_config_timeout_us; + uint32_t vl53l1_tuningparm_lite_range_config_timeout_us; + uint32_t vl53l1_tuningparm_timed_range_config_timeout_us; + uint8_t vl53l1_tuningparm_lowpowerauto_vhv_loop_bound; + uint32_t vl53l1_tuningparm_lowpowerauto_mm_config_timeout_us; + uint32_t vl53l1_tuningparm_lowpowerauto_range_config_timeout_us; +} VL53L1_tuning_parameters_t; + + +/** + * @struct VL53L1_spad_rate_data_t + * @brief SPAD Rate Data output by SSC + * + * Container for the SPAD Rate data output by SPAD select check (SSC) + * The data is stored in the buffer in SPAD number order and not + * raster order + * + * Rate data is it either 1.15 or 9.7 fixed point format + */ + +typedef struct { + + uint8_t spad_type; + /*!< Type of rate data stored */ + uint16_t buffer_size; + /*!< SPAD buffer size : should be at least 256 for EwokPlus25 */ + uint16_t rate_data[VL53L1_NO_OF_SPAD_ENABLES]; + /*!< word buffer containing the SPAD rates */ + uint16_t no_of_values; + /*!< Number of bytes used in the buffer */ + uint8_t fractional_bits; + /*!< Number of fractional bits either 7 or 15 */ + uint8_t error_status; + /*!< Set if supplied buffer is too small */ + +} VL53L1_spad_rate_data_t; + + +/* Start Patch_AdditionalDebugData_11823 */ + +/** + * @struct VL53L1_additional_data_t + * @brief Additional debug data + * + * Contains the LL Driver configuration information + */ + +typedef struct { + + VL53L1_DevicePresetModes preset_mode; + /*!< Current preset mode */ + VL53L1_DeviceMeasurementModes measurement_mode; + /*!< Current measurement mode */ + + uint32_t phasecal_config_timeout_us; + /*!< requested Phase Cal Timeout e.g. 1000us */ + uint32_t mm_config_timeout_us; + /*!< requested MM Timeout e.g. 2000us */ + uint32_t range_config_timeout_us; + /*!< requested Ranging Timeout e.g 13000us */ + uint32_t inter_measurement_period_ms; + /*!< requested Timing mode repeat period e.g 100ms */ + uint16_t dss_config__target_total_rate_mcps; + /*!< requested DSS Target Total Rate in 9.7 format e.g. 40.0Mcps*/ + +} VL53L1_additional_data_t; + +/* End Patch_AdditionalDebugData_11823 */ + + +/** @} VL53L1_globalLLDriverDefine_group */ + + +#define SUPPRESS_UNUSED_WARNING(x) \ + ((void) (x)) + + +#define IGNORE_STATUS(__FUNCTION_ID__, __ERROR_STATUS_CHECK__, __STATUS__) \ + do { \ + DISABLE_WARNINGS(); \ + if (__FUNCTION_ID__) { \ + if (__STATUS__ == __ERROR_STATUS_CHECK__) { \ + __STATUS__ = VL53L1_ERROR_NONE; \ + WARN_OVERRIDE_STATUS(__FUNCTION_ID__); \ + } \ + } \ + ENABLE_WARNINGS(); \ + } \ + while (0) + +#define VL53L1_COPYSTRING(str, ...) \ + (strncpy(str, ##__VA_ARGS__, VL53L1_MAX_STRING_LENGTH-1)) + +#ifdef __cplusplus +} +#endif + +#endif /* _VL53L1_LL_DEF_H_ */ + + diff --git a/App/VL53L1X_API/core/inc/vl53l1_ll_device.h b/App/VL53L1X_API/core/inc/vl53l1_ll_device.h new file mode 100644 index 0000000..45490cc --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_ll_device.h @@ -0,0 +1,698 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_ll_device.h + * + * @brief LL Driver Device specific defines. To be adapted by implementer for the + * targeted device. + */ + +#ifndef _VL53L1_LL_DEVICE_H_ +#define _VL53L1_LL_DEVICE_H_ + +#include "vl53l1_types.h" +#include "vl53l1_platform_user_config.h" + +#define VL53L1_I2C 0x01 +#define VL53L1_SPI 0x00 + + +/** @defgroup VL53L1_DevSpecDefines_group VL53L1 Device Specific Defines + * @brief VL53L1 cut1.0 Device Specific Defines + * @{ + */ + +/** @defgroup VL53L1_define_WaitMethod_group Defines Wait method used + * For example blocking versus non blocking + * @{ + */ +typedef uint8_t VL53L1_WaitMethod; + +#define VL53L1_WAIT_METHOD_BLOCKING ((VL53L1_WaitMethod) 0) +#define VL53L1_WAIT_METHOD_NON_BLOCKING ((VL53L1_WaitMethod) 1) + +/** @} end of VL53L1_define_WaitMethod_group */ + +/** @defgroup VL53L1_define_DeviceState_group Device State + * + * @brief Defines all possible device states for the device + * @{ + */ +typedef uint8_t VL53L1_DeviceState; + +#define VL53L1_DEVICESTATE_POWERDOWN ((VL53L1_DeviceState) 0) +#define VL53L1_DEVICESTATE_HW_STANDBY ((VL53L1_DeviceState) 1) +#define VL53L1_DEVICESTATE_FW_COLDBOOT ((VL53L1_DeviceState) 2) +#define VL53L1_DEVICESTATE_SW_STANDBY ((VL53L1_DeviceState) 3) +#define VL53L1_DEVICESTATE_RANGING_DSS_AUTO ((VL53L1_DeviceState) 4) +#define VL53L1_DEVICESTATE_RANGING_DSS_MANUAL ((VL53L1_DeviceState) 5) +#define VL53L1_DEVICESTATE_RANGING_WAIT_GPH_SYNC ((VL53L1_DeviceState) 6) +#define VL53L1_DEVICESTATE_RANGING_GATHER_DATA ((VL53L1_DeviceState) 7) +#define VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA ((VL53L1_DeviceState) 8) + +#define VL53L1_DEVICESTATE_UNKNOWN ((VL53L1_DeviceState) 98) +#define VL53L1_DEVICESTATE_ERROR ((VL53L1_DeviceState) 99) + +/** @} end of VL53L1_define_DeviceState_group */ + + +/** @defgroup VL53L1_define_DevicePresetModes_group Device Preset Modes + * + * @brief Defines all possible device preset modes. The integer values are + * kept the same as main EwokPlus driver branch + * @{ + */ +typedef uint8_t VL53L1_DevicePresetModes; + +#define VL53L1_DEVICEPRESETMODE_NONE ((VL53L1_DevicePresetModes) 0) +#define VL53L1_DEVICEPRESETMODE_STANDARD_RANGING ((VL53L1_DevicePresetModes) 1) +#define VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_SHORT_RANGE ((VL53L1_DevicePresetModes) 2) +#define VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_LONG_RANGE ((VL53L1_DevicePresetModes) 3) +#define VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM1_CAL ((VL53L1_DevicePresetModes) 4) +#define VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM2_CAL ((VL53L1_DevicePresetModes) 5) +#define VL53L1_DEVICEPRESETMODE_TIMED_RANGING ((VL53L1_DevicePresetModes) 6) +#define VL53L1_DEVICEPRESETMODE_TIMED_RANGING_SHORT_RANGE ((VL53L1_DevicePresetModes) 7) +#define VL53L1_DEVICEPRESETMODE_TIMED_RANGING_LONG_RANGE ((VL53L1_DevicePresetModes) 8) +#define VL53L1_DEVICEPRESETMODE_OLT ((VL53L1_DevicePresetModes) 17) +#define VL53L1_DEVICEPRESETMODE_SINGLESHOT_RANGING ((VL53L1_DevicePresetModes) 18) +#define VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_SHORT_RANGE ((VL53L1_DevicePresetModes) 36) +#define VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_MEDIUM_RANGE ((VL53L1_DevicePresetModes) 37) +#define VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_LONG_RANGE ((VL53L1_DevicePresetModes) 38) + +/** @} end of VL53L1_define_DevicePresetModes_group */ + + +/** @defgroup VL53L1_define_DeviceMeasurementModes_group Device Measurement Modes + * + * @brief Defines all possible measurement modes for the device + * @{ + */ +typedef uint8_t VL53L1_DeviceMeasurementModes; + +#define VL53L1_DEVICEMEASUREMENTMODE_STOP ((VL53L1_DeviceMeasurementModes) 0x00) +#define VL53L1_DEVICEMEASUREMENTMODE_SINGLESHOT ((VL53L1_DeviceMeasurementModes) 0x10) +#define VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK ((VL53L1_DeviceMeasurementModes) 0x20) +#define VL53L1_DEVICEMEASUREMENTMODE_TIMED ((VL53L1_DeviceMeasurementModes) 0x40) +#define VL53L1_DEVICEMEASUREMENTMODE_ABORT ((VL53L1_DeviceMeasurementModes) 0x80) + +/** @} VL53L1_define_DeviceMeasurementModes_group */ + +/** @defgroup VL53L1_define_OffsetCalibrationModes_group Device Offset Calibration Mode + * + * @brief Defines possible offset calibration modes for the device + * @{ + */ +typedef uint8_t VL53L1_OffsetCalibrationMode; + +#define VL53L1_OFFSETCALIBRATIONMODE__NONE ((VL53L1_OffsetCalibrationMode) 0) +#define VL53L1_OFFSETCALIBRATIONMODE__MM1_MM2__STANDARD ((VL53L1_OffsetCalibrationMode) 1) +#define VL53L1_OFFSETCALIBRATIONMODE__MM1_MM2__HISTOGRAM ((VL53L1_OffsetCalibrationMode) 2) +#define VL53L1_OFFSETCALIBRATIONMODE__MM1_MM2__STANDARD_PRE_RANGE_ONLY ((VL53L1_OffsetCalibrationMode) 3) +#define VL53L1_OFFSETCALIBRATIONMODE__MM1_MM2__HISTOGRAM_PRE_RANGE_ONLY ((VL53L1_OffsetCalibrationMode) 4) +#define VL53L1_OFFSETCALIBRATIONMODE__PER_ZONE ((VL53L1_OffsetCalibrationMode) 5) + +/** @} VL53L1_define_OffsetCalibrationModes_group */ + + +/** @defgroup VL53L1_define_OffsetCalibrationModes_group Device Offset Correction Mode + * + * @brief Defines all possible offset correction modes for the device + * @{ + */ +typedef uint8_t VL53L1_OffsetCorrectionMode; + +#define VL53L1_OFFSETCORRECTIONMODE__NONE ((VL53L1_OffsetCorrectionMode) 0) +#define VL53L1_OFFSETCORRECTIONMODE__MM1_MM2_OFFSETS ((VL53L1_OffsetCorrectionMode) 1) +#define VL53L1_OFFSETCORRECTIONMODE__PER_ZONE_OFFSETS ((VL53L1_OffsetCorrectionMode) 2) + +/** @} VL53L1_define_OffsetCalibrationModes_group */ + + + +/** @defgroup VL53L1_DeviceSequenceConfig_group Device Sequence Config + * + * @brief Individual bit enables for each stage in the ranging scheduler + * The values below encode the bit shift for each bit + * @{ + */ +typedef uint8_t VL53L1_DeviceSequenceConfig; + +#define VL53L1_DEVICESEQUENCECONFIG_VHV ((VL53L1_DeviceSequenceConfig) 0) +#define VL53L1_DEVICESEQUENCECONFIG_PHASECAL ((VL53L1_DeviceSequenceConfig) 1) +#define VL53L1_DEVICESEQUENCECONFIG_REFERENCE_PHASE ((VL53L1_DeviceSequenceConfig) 2) +#define VL53L1_DEVICESEQUENCECONFIG_DSS1 ((VL53L1_DeviceSequenceConfig) 3) +#define VL53L1_DEVICESEQUENCECONFIG_DSS2 ((VL53L1_DeviceSequenceConfig) 4) +#define VL53L1_DEVICESEQUENCECONFIG_MM1 ((VL53L1_DeviceSequenceConfig) 5) +#define VL53L1_DEVICESEQUENCECONFIG_MM2 ((VL53L1_DeviceSequenceConfig) 6) +#define VL53L1_DEVICESEQUENCECONFIG_RANGE ((VL53L1_DeviceSequenceConfig) 7) + +/** @} VL53L1_DeviceSequenceConfig_group */ + + +/** @defgroup VL53L1_DeviceInterruptPolarity_group Device Interrupt Polarity + * + * @brief Device Interrupt Polarity + * @{ + */ +typedef uint8_t VL53L1_DeviceInterruptPolarity; + +#define VL53L1_DEVICEINTERRUPTPOLARITY_ACTIVE_HIGH ((VL53L1_DeviceInterruptPolarity) 0x00) +#define VL53L1_DEVICEINTERRUPTPOLARITY_ACTIVE_LOW ((VL53L1_DeviceInterruptPolarity) 0x10) +#define VL53L1_DEVICEINTERRUPTPOLARITY_BIT_MASK ((VL53L1_DeviceInterruptPolarity) 0x10) +#define VL53L1_DEVICEINTERRUPTPOLARITY_CLEAR_MASK ((VL53L1_DeviceInterruptPolarity) 0xEF) + +/** @} VL53L1_DeviceInterruptPolarity_group */ + + +/** @defgroup VL53L1_DeviceGpioMode_group Device GPIO Mode + * + * @brief Device Gpio Mode + * @{ + */ +typedef uint8_t VL53L1_DeviceGpioMode; + +#define VL53L1_DEVICEGPIOMODE_OUTPUT_CONSTANT_ZERO ((VL53L1_DeviceGpioMode) 0x00) +#define VL53L1_DEVICEGPIOMODE_OUTPUT_RANGE_AND_ERROR_INTERRUPTS ((VL53L1_DeviceGpioMode) 0x01) +#define VL53L1_DEVICEGPIOMODE_OUTPUT_TIMIER_INTERRUPTS ((VL53L1_DeviceGpioMode) 0x02) +#define VL53L1_DEVICEGPIOMODE_OUTPUT_RANGE_MODE_INTERRUPT_STATUS ((VL53L1_DeviceGpioMode) 0x03) +#define VL53L1_DEVICEGPIOMODE_OUTPUT_SLOW_OSCILLATOR_CLOCK ((VL53L1_DeviceGpioMode) 0x04) +#define VL53L1_DEVICEGPIOMODE_BIT_MASK ((VL53L1_DeviceGpioMode) 0x0F) +#define VL53L1_DEVICEGPIOMODE_CLEAR_MASK ((VL53L1_DeviceGpioMode) 0xF0) + +/** @} VL53L1_DeviceGpioMode_group */ + + +/** @defgroup VL53L1_DeviceError_group Device Error + * + * @brief Device Error code in the range status + * + * This enum is Device specific it should be updated in the implementation + * Use @a VL53L1_GetStatusErrorString() to get the string. + * It is related to Status Register of the Device. + * @{ + */ +typedef uint8_t VL53L1_DeviceError; + +#define VL53L1_DEVICEERROR_NOUPDATE ((VL53L1_DeviceError) 0) + /*!< 0 No Update */ +#define VL53L1_DEVICEERROR_VCSELCONTINUITYTESTFAILURE ((VL53L1_DeviceError) 1) +#define VL53L1_DEVICEERROR_VCSELWATCHDOGTESTFAILURE ((VL53L1_DeviceError) 2) +#define VL53L1_DEVICEERROR_NOVHVVALUEFOUND ((VL53L1_DeviceError) 3) +#define VL53L1_DEVICEERROR_MSRCNOTARGET ((VL53L1_DeviceError) 4) +#define VL53L1_DEVICEERROR_RANGEPHASECHECK ((VL53L1_DeviceError) 5) +#define VL53L1_DEVICEERROR_SIGMATHRESHOLDCHECK ((VL53L1_DeviceError) 6) +#define VL53L1_DEVICEERROR_PHASECONSISTENCY ((VL53L1_DeviceError) 7) +#define VL53L1_DEVICEERROR_MINCLIP ((VL53L1_DeviceError) 8) +#define VL53L1_DEVICEERROR_RANGECOMPLETE ((VL53L1_DeviceError) 9) +#define VL53L1_DEVICEERROR_ALGOUNDERFLOW ((VL53L1_DeviceError) 10) +#define VL53L1_DEVICEERROR_ALGOOVERFLOW ((VL53L1_DeviceError) 11) +#define VL53L1_DEVICEERROR_RANGEIGNORETHRESHOLD ((VL53L1_DeviceError) 12) +#define VL53L1_DEVICEERROR_USERROICLIP ((VL53L1_DeviceError) 13) +#define VL53L1_DEVICEERROR_REFSPADCHARNOTENOUGHDPADS ((VL53L1_DeviceError) 14) +#define VL53L1_DEVICEERROR_REFSPADCHARMORETHANTARGET ((VL53L1_DeviceError) 15) +#define VL53L1_DEVICEERROR_REFSPADCHARLESSTHANTARGET ((VL53L1_DeviceError) 16) +#define VL53L1_DEVICEERROR_MULTCLIPFAIL ((VL53L1_DeviceError) 17) +#define VL53L1_DEVICEERROR_GPHSTREAMCOUNT0READY ((VL53L1_DeviceError) 18) +#define VL53L1_DEVICEERROR_RANGECOMPLETE_NO_WRAP_CHECK ((VL53L1_DeviceError) 19) +#define VL53L1_DEVICEERROR_EVENTCONSISTENCY ((VL53L1_DeviceError) 20) +#define VL53L1_DEVICEERROR_MINSIGNALEVENTCHECK ((VL53L1_DeviceError) 21) +#define VL53L1_DEVICEERROR_RANGECOMPLETE_MERGED_PULSE ((VL53L1_DeviceError) 22) + +/* Patch_NewDeviceErrorCodePrevRangeNoTargets_11786 */ +#define VL53L1_DEVICEERROR_PREV_RANGE_NO_TARGETS ((VL53L1_DeviceError) 23) + +/** @} end of VL53L1_DeviceError_group */ + + +/** @defgroup VL53L1_DeviceReportStatus_group Device Report Status + * @brief Device Report Status code + * + * @{ + */ +typedef uint8_t VL53L1_DeviceReportStatus; + +#define VL53L1_DEVICEREPORTSTATUS_NOUPDATE ((VL53L1_DeviceReportStatus) 0) + /*!< 0 No Update */ +#define VL53L1_DEVICEREPORTSTATUS_ROI_SETUP ((VL53L1_DeviceReportStatus) 1) +#define VL53L1_DEVICEREPORTSTATUS_VHV ((VL53L1_DeviceReportStatus) 2) +#define VL53L1_DEVICEREPORTSTATUS_PHASECAL ((VL53L1_DeviceReportStatus) 3) +#define VL53L1_DEVICEREPORTSTATUS_REFERENCE_PHASE ((VL53L1_DeviceReportStatus) 4) +#define VL53L1_DEVICEREPORTSTATUS_DSS1 ((VL53L1_DeviceReportStatus) 5) +#define VL53L1_DEVICEREPORTSTATUS_DSS2 ((VL53L1_DeviceReportStatus) 6) +#define VL53L1_DEVICEREPORTSTATUS_MM1 ((VL53L1_DeviceReportStatus) 7) +#define VL53L1_DEVICEREPORTSTATUS_MM2 ((VL53L1_DeviceReportStatus) 8) +#define VL53L1_DEVICEREPORTSTATUS_RANGE ((VL53L1_DeviceReportStatus) 9) +#define VL53L1_DEVICEREPORTSTATUS_HISTOGRAM ((VL53L1_DeviceReportStatus) 10) + +/** @} end of VL53L1_DeviceReportStatus_group */ + +/** @defgroup VL53L1_DeviceDssMode_group Dynamic SPAD Selection Mode + * @brief Selects the device Dynamic SPAD Selection Mode + * @{ + */ + +typedef uint8_t VL53L1_DeviceDssMode; + +#define VL53L1_DEVICEDSSMODE__DISABLED \ + ((VL53L1_DeviceDssMode) 0) +#define VL53L1_DEVICEDSSMODE__TARGET_RATE \ + ((VL53L1_DeviceDssMode) 1) +#define VL53L1_DEVICEDSSMODE__REQUESTED_EFFFECTIVE_SPADS \ + ((VL53L1_DeviceDssMode) 2) +#define VL53L1_DEVICEDSSMODE__BLOCK_SELECT \ + ((VL53L1_DeviceDssMode) 3) + +/** @} end of VL53L1_DeviceDssMode_group */ + +/** @defgroup VL53L1_DeviceConfigLevel_group Device Config Level + * + * @brief Defines the contents of the config & start range I2C multi byte transaction + * @{ + */ +typedef uint8_t VL53L1_DeviceConfigLevel; + +#define VL53L1_DEVICECONFIGLEVEL_SYSTEM_CONTROL \ + ((VL53L1_DeviceConfigLevel) 0) + /*!< Configs system control & start range */ +#define VL53L1_DEVICECONFIGLEVEL_DYNAMIC_ONWARDS \ + ((VL53L1_DeviceConfigLevel) 1) + /*!< Dynamic config onwards (dynamic_config, system_control) & start range */ +#define VL53L1_DEVICECONFIGLEVEL_TIMING_ONWARDS \ + ((VL53L1_DeviceConfigLevel) 2) + /*!< Dynamic config onwards (timing config, dynamic_config, system_control) & + start range */ +#define VL53L1_DEVICECONFIGLEVEL_GENERAL_ONWARDS \ + ((VL53L1_DeviceConfigLevel) 3) + /*!< General config onwards (general_config, timing config, dynamic_config, + system_control) & start range */ +#define VL53L1_DEVICECONFIGLEVEL_STATIC_ONWARDS \ + ((VL53L1_DeviceConfigLevel) 4) + /*!< Static config onwards (static_config, general_config, timing_config, + dynamic_config, system_control) & start range */ +#define VL53L1_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS \ + ((VL53L1_DeviceConfigLevel) 5) + /*!< Full device config (customer_nvm_managed, static_config, general_config, + timing config, dynamic_config, system_control) & start range */ +#define VL53L1_DEVICECONFIGLEVEL_FULL \ + ((VL53L1_DeviceConfigLevel) 6) + /*!< Full device config (static_nvm_managed, customer_nvm_managed, static_config, + general_config, timing config, dynamic_config, system_control) & start range */ + +/** @} end of VL53L1_DeviceConfigLevel_group */ + + +/** @defgroup VL53L1_DeviceResultsLevel_group Device Results Level + * + * @brief Defines the contents of the read results I2C multi byte transaction + * @{ + */ +typedef uint8_t VL53L1_DeviceResultsLevel; + +#define VL53L1_DEVICERESULTSLEVEL_SYSTEM_RESULTS \ + ((VL53L1_DeviceResultsLevel) 0) + /*!< Read just system_results */ +#define VL53L1_DEVICERESULTSLEVEL_UPTO_CORE \ + ((VL53L1_DeviceResultsLevel) 1) + /*!< Read both system and core results */ +#define VL53L1_DEVICERESULTSLEVEL_FULL \ + ((VL53L1_DeviceResultsLevel) 2) + /*!< Read system, core and debug results */ + +/** @} end of VL53L1_DeviceResultsLevel_group */ + + +/** @defgroup VL53L1_DeviceTestMode_group Device Test Mode + * + * @brief Values below match the the TEST_MODE__CTRL register + * do not change + * @{ + */ + +typedef uint8_t VL53L1_DeviceTestMode; + +#define VL53L1_DEVICETESTMODE_NONE \ + ((VL53L1_DeviceTestMode) 0x00) + /*!< Idle */ +#define VL53L1_DEVICETESTMODE_NVM_ZERO \ + ((VL53L1_DeviceTestMode) 0x01) + /*!< NVM zero */ +#define VL53L1_DEVICETESTMODE_NVM_COPY \ + ((VL53L1_DeviceTestMode) 0x02) + /*!< NVM copy */ +#define VL53L1_DEVICETESTMODE_PATCH \ + ((VL53L1_DeviceTestMode) 0x03) + /*!< Patch */ +#define VL53L1_DEVICETESTMODE_DCR \ + ((VL53L1_DeviceTestMode) 0x04) + /*!< DCR - SPAD Self-Check (Pass if Count Rate is less than Threshold) */ +#define VL53L1_DEVICETESTMODE_LCR_VCSEL_OFF \ + ((VL53L1_DeviceTestMode) 0x05) + /*!< LCR - SPAD Self-Check (Pass if Count Rate is greater than Threshold + and VCSEL off) */ +#define VL53L1_DEVICETESTMODE_LCR_VCSEL_ON \ + ((VL53L1_DeviceTestMode) 0x06) + /*!< LCR - SPAD Self-Check (Pass if Count Rate is greater than Threshold + and VCSEL on) */ +#define VL53L1_DEVICETESTMODE_SPOT_CENTRE_LOCATE \ + ((VL53L1_DeviceTestMode) 0x07) + /*!< Spot centre locate */ +#define VL53L1_DEVICETESTMODE_REF_SPAD_CHAR_WITH_PRE_VHV \ + ((VL53L1_DeviceTestMode) 0x08) + /*! 0.200000 * 256 = 51 = 0x33 + Measured: 4.6x -> 0.217391 * 256 = 56 = 0x38 */ + +#define VL53L1_SPAD_TOTAL_COUNT_MAX ((0x01 << 29) - 1) + /*!< Maximum SPAD count - 512Mcps * 1sec = 29bits) */ +#define VL53L1_SPAD_TOTAL_COUNT_RES_THRES (0x01 << 24) + /*!< SPAD count threshold for reduced 3-bit fractional resolution */ +#define VL53L1_COUNT_RATE_INTERNAL_MAX ((0x01 << 24) - 1) + /*!< Maximum internal count rate is a 17.7 (24-b) value */ +#define VL53L1_SPEED_OF_LIGHT_IN_AIR 299704 + /*!< Speed of light in air in mm/sec */ +#define VL53L1_SPEED_OF_LIGHT_IN_AIR_DIV_8 (299704 >> 3) + /*!< Speed of light in air in divided by 8, 2 for round trip + and 4 as an additional scaling factor */ + +/** @} end of VL53L1_ApiCore_group */ + +/** @} end of VL53L1_DevSpecDefines_group */ + +/** @defgroup VL53L1_GPIO_Interrupt_Mode_group Interrupt modes + * @brief Selects between four interrupt modes + * @{ + */ + +typedef uint8_t VL53L1_GPIO_Interrupt_Mode; + +#define VL53L1_GPIOINTMODE_LEVEL_LOW \ + ((VL53L1_GPIO_Interrupt_Mode) 0) + /*!< Trigger interupt if value < thresh_low */ +#define VL53L1_GPIOINTMODE_LEVEL_HIGH \ + ((VL53L1_GPIO_Interrupt_Mode) 1) + /*!< Trigger interupt if value > thresh_high */ +#define VL53L1_GPIOINTMODE_OUT_OF_WINDOW \ + ((VL53L1_GPIO_Interrupt_Mode) 2) + /*!< Trigger interupt if value < thresh_low OR value > thresh_high */ +#define VL53L1_GPIOINTMODE_IN_WINDOW \ + ((VL53L1_GPIO_Interrupt_Mode) 3) + /*!< Trigger interupt if value > thresh_low AND value < thresh_high */ + +/** @} end of VL53L1_GPIO_Interrupt_Mode_group */ + +/** @defgroup VL53L1_TuningParms_group Tuning Parameters + * @brief Selects specific tuning parameter inputs to get/set \ + * Added as part of Patch_AddedTuningParms_11761 + * @{ + */ + +typedef uint16_t VL53L1_TuningParms; + +#define VL53L1_TUNINGPARMS_LLD_PUBLIC_MIN_ADDRESS \ + ((VL53L1_TuningParms) VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS) +#define VL53L1_TUNINGPARMS_LLD_PUBLIC_MAX_ADDRESS \ + ((VL53L1_TuningParms) VL53L1_TUNINGPARM_LOWPOWERAUTO_RANGE_CONFIG_TIMEOUT_US) + +#define VL53L1_TUNINGPARMS_LLD_PRIVATE_MIN_ADDRESS \ + ((VL53L1_TuningParms) VL53L1_TUNINGPARM_PRIVATE_PAGE_BASE_ADDRESS) +#define VL53L1_TUNINGPARMS_LLD_PRIVATE_MAX_ADDRESS \ + ((VL53L1_TuningParms) VL53L1_TUNINGPARMS_LLD_PRIVATE_MIN_ADDRESS) + +#define VL53L1_TUNINGPARM_VERSION \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 0)) +#define VL53L1_TUNINGPARM_KEY_TABLE_VERSION \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 1)) +#define VL53L1_TUNINGPARM_LLD_VERSION \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 2)) +#define VL53L1_TUNINGPARM_CONSISTENCY_LITE_PHASE_TOLERANCE \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 3)) +#define VL53L1_TUNINGPARM_PHASECAL_TARGET \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 4)) +#define VL53L1_TUNINGPARM_LITE_CAL_REPEAT_RATE \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 5)) +#define VL53L1_TUNINGPARM_LITE_RANGING_GAIN_FACTOR \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 6)) +#define VL53L1_TUNINGPARM_LITE_MIN_CLIP_MM \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 7)) +#define VL53L1_TUNINGPARM_LITE_LONG_SIGMA_THRESH_MM \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 8)) +#define VL53L1_TUNINGPARM_LITE_MED_SIGMA_THRESH_MM \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 9)) +#define VL53L1_TUNINGPARM_LITE_SHORT_SIGMA_THRESH_MM \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 10)) +#define VL53L1_TUNINGPARM_LITE_LONG_MIN_COUNT_RATE_RTN_MCPS \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 11)) +#define VL53L1_TUNINGPARM_LITE_MED_MIN_COUNT_RATE_RTN_MCPS \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 12)) +#define VL53L1_TUNINGPARM_LITE_SHORT_MIN_COUNT_RATE_RTN_MCPS \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 13)) +#define VL53L1_TUNINGPARM_LITE_SIGMA_EST_PULSE_WIDTH \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 14)) +#define VL53L1_TUNINGPARM_LITE_SIGMA_EST_AMB_WIDTH_NS \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 15)) +#define VL53L1_TUNINGPARM_LITE_SIGMA_REF_MM \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 16)) +#define VL53L1_TUNINGPARM_LITE_RIT_MULT \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 17)) +#define VL53L1_TUNINGPARM_LITE_SEED_CONFIG \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 18)) +#define VL53L1_TUNINGPARM_LITE_QUANTIFIER \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 19)) +#define VL53L1_TUNINGPARM_LITE_FIRST_ORDER_SELECT \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 20)) +#define VL53L1_TUNINGPARM_LITE_XTALK_MARGIN_KCPS \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 21)) +#define VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_LONG_RANGE \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 22)) +#define VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_MED_RANGE \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 23)) +#define VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_SHORT_RANGE \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 24)) +#define VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_LONG_RANGE \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 25)) +#define VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_MED_RANGE \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 26)) +#define VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_SHORT_RANGE \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 27)) +#define VL53L1_TUNINGPARM_TIMED_SEED_CONFIG \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 28)) +#define VL53L1_TUNINGPARM_VHV_LOOPBOUND \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 29)) +#define VL53L1_TUNINGPARM_REFSPADCHAR_DEVICE_TEST_MODE \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 30)) +#define VL53L1_TUNINGPARM_REFSPADCHAR_VCSEL_PERIOD \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 31)) +#define VL53L1_TUNINGPARM_REFSPADCHAR_PHASECAL_TIMEOUT_US \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 32)) +#define VL53L1_TUNINGPARM_REFSPADCHAR_TARGET_COUNT_RATE_MCPS \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 33)) +#define VL53L1_TUNINGPARM_REFSPADCHAR_MIN_COUNTRATE_LIMIT_MCPS \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 34)) +#define VL53L1_TUNINGPARM_REFSPADCHAR_MAX_COUNTRATE_LIMIT_MCPS \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 35)) +#define VL53L1_TUNINGPARM_OFFSET_CAL_DSS_RATE_MCPS \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 36)) +#define VL53L1_TUNINGPARM_OFFSET_CAL_PHASECAL_TIMEOUT_US \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 37)) +#define VL53L1_TUNINGPARM_OFFSET_CAL_MM_TIMEOUT_US \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 38)) +#define VL53L1_TUNINGPARM_OFFSET_CAL_RANGE_TIMEOUT_US \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 39)) +#define VL53L1_TUNINGPARM_OFFSET_CAL_PRE_SAMPLES \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 40)) +#define VL53L1_TUNINGPARM_OFFSET_CAL_MM1_SAMPLES \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 41)) +#define VL53L1_TUNINGPARM_OFFSET_CAL_MM2_SAMPLES \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 42)) +#define VL53L1_TUNINGPARM_SPADMAP_VCSEL_PERIOD \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 43)) +#define VL53L1_TUNINGPARM_SPADMAP_VCSEL_START \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 44)) +#define VL53L1_TUNINGPARM_SPADMAP_RATE_LIMIT_MCPS \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 45)) +#define VL53L1_TUNINGPARM_LITE_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 46)) +#define VL53L1_TUNINGPARM_TIMED_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 47)) +#define VL53L1_TUNINGPARM_LITE_PHASECAL_CONFIG_TIMEOUT_US \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 48)) +#define VL53L1_TUNINGPARM_TIMED_PHASECAL_CONFIG_TIMEOUT_US \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 49)) +#define VL53L1_TUNINGPARM_LITE_MM_CONFIG_TIMEOUT_US \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 50)) +#define VL53L1_TUNINGPARM_TIMED_MM_CONFIG_TIMEOUT_US \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 51)) +#define VL53L1_TUNINGPARM_LITE_RANGE_CONFIG_TIMEOUT_US \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 52)) +#define VL53L1_TUNINGPARM_TIMED_RANGE_CONFIG_TIMEOUT_US \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 53)) +#define VL53L1_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 54)) +#define VL53L1_TUNINGPARM_LOWPOWERAUTO_MM_CONFIG_TIMEOUT_US \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 55)) +#define VL53L1_TUNINGPARM_LOWPOWERAUTO_RANGE_CONFIG_TIMEOUT_US \ + ((VL53L1_TuningParms) (VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 56)) + + +/** @} end of VL53L1_TuningParms_group */ + + +#endif + +/* _VL53L1_DEVICE_H_ */ + + diff --git a/App/VL53L1X_API/core/inc/vl53l1_nvm_map.h b/App/VL53L1X_API/core/inc/vl53l1_nvm_map.h new file mode 100644 index 0000000..62672d5 --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_nvm_map.h @@ -0,0 +1,3022 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_nvm_map.h + * @brief NVM Map definitions for EwokPlus25 NVM Interface Functions. + * + */ + +/* + * Include platform specific and register map definitions + */ + + +#ifndef _VL53L1_NVM_MAP_H_ +#define _VL53L1_NVM_MAP_H_ + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @defgroup VL53L1_nvm_DefineRegisters_group Define Registers * @brief List of all the defined registers + * @{ + */ + +#define VL53L1_NVM__IDENTIFICATION__MODEL_ID 0x0008 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__identification_model_id +*/ +#define VL53L1_NVM__IDENTIFICATION__MODULE_TYPE 0x000C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__identification_module_type +*/ +#define VL53L1_NVM__IDENTIFICATION__REVISION_ID 0x000D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [3:0] = nvm__identification_revision_id +*/ +#define VL53L1_NVM__IDENTIFICATION__MODULE_ID 0x000E +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__identification_module_id +*/ +#define VL53L1_NVM__I2C_VALID 0x0010 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__i2c_valid +*/ +#define VL53L1_NVM__I2C_SLAVE__DEVICE_ADDRESS 0x0011 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__i2c_device_address_ews +*/ +#define VL53L1_NVM__EWS__OSC_MEASURED__FAST_OSC_FREQUENCY 0x0014 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__ews__fast_osc_frequency (fixed point 4.12) +*/ +#define VL53L1_NVM__EWS__FAST_OSC_TRIM_MAX 0x0016 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [6:0] = nvm__ews__fast_osc_trim_max +*/ +#define VL53L1_NVM__EWS__FAST_OSC_FREQ_SET 0x0017 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [2:0] = nvm__ews__fast_osc_freq_set +*/ +#define VL53L1_NVM__EWS__SLOW_OSC_CALIBRATION 0x0018 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 9 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [9:0] = nvm__ews__slow_osc_calibration +*/ +#define VL53L1_NVM__FMT__OSC_MEASURED__FAST_OSC_FREQUENCY 0x001C +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__fmt__fast_osc_frequency (fixed point 4.12) +*/ +#define VL53L1_NVM__FMT__FAST_OSC_TRIM_MAX 0x001E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [6:0] = nvm__fmt__fast_osc_trim_max +*/ +#define VL53L1_NVM__FMT__FAST_OSC_FREQ_SET 0x001F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [2:0] = nvm__fmt__fast_osc_freq_set +*/ +#define VL53L1_NVM__FMT__SLOW_OSC_CALIBRATION 0x0020 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 9 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [9:0] = nvm__fmt__slow_osc_calibration +*/ +#define VL53L1_NVM__VHV_CONFIG_UNLOCK 0x0028 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__vhv_config_unlock +*/ +#define VL53L1_NVM__REF_SELVDDPIX 0x0029 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [3:0] = nvm__ref_selvddpix +*/ +#define VL53L1_NVM__REF_SELVQUENCH 0x002A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 6 + - lsb = 3 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [6:3] = nvm__ref_selvquench +*/ +#define VL53L1_NVM__REGAVDD1V2_SEL_REGDVDD1V2_SEL 0x002B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [3:2] = nvm__regavdd1v2_sel + - [1:0] = nvm__regdvdd1v2_sel +*/ +#define VL53L1_NVM__VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND 0x002C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [1:0] = nvm__vhv_timeout__macrop + - [7:2] = nvm__vhv_loop_bound +*/ +#define VL53L1_NVM__VHV_CONFIG__COUNT_THRESH 0x002D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__vhv_count_threshold +*/ +#define VL53L1_NVM__VHV_CONFIG__OFFSET 0x002E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [5:0] = nvm__vhv_offset +*/ +#define VL53L1_NVM__VHV_CONFIG__INIT 0x002F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7] = nvm__vhv_init_enable + - [5:0] = nvm__vhv_init_value +*/ +#define VL53L1_NVM__LASER_SAFETY__VCSEL_TRIM_LL 0x0030 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [2:0] = nvm__laser_safety_vcsel_trim_ll +*/ +#define VL53L1_NVM__LASER_SAFETY__VCSEL_SELION_LL 0x0031 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [5:0] = nvm__laser_safety_vcsel_selion_ll +*/ +#define VL53L1_NVM__LASER_SAFETY__VCSEL_SELION_MAX_LL 0x0032 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [5:0] = nvm__laser_safety_vcsel_selion_max_ll +*/ +#define VL53L1_NVM__LASER_SAFETY__MULT_LL 0x0034 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [5:0] = nvm__laser_safety_mult_ll +*/ +#define VL53L1_NVM__LASER_SAFETY__CLIP_LL 0x0035 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [5:0] = nvm__laser_safety_clip_ll +*/ +#define VL53L1_NVM__LASER_SAFETY__VCSEL_TRIM_LD 0x0038 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [2:0] = nvm__laser_safety_vcsel_trim_ld +*/ +#define VL53L1_NVM__LASER_SAFETY__VCSEL_SELION_LD 0x0039 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [5:0] = nvm__laser_safety_vcsel_selion_ld +*/ +#define VL53L1_NVM__LASER_SAFETY__VCSEL_SELION_MAX_LD 0x003A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [5:0] = nvm__laser_safety_vcsel_selion_max_ld +*/ +#define VL53L1_NVM__LASER_SAFETY__MULT_LD 0x003C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [5:0] = nvm__laser_safety_mult_ld +*/ +#define VL53L1_NVM__LASER_SAFETY__CLIP_LD 0x003D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [5:0] = nvm__laser_safety_clip_ld +*/ +#define VL53L1_NVM__LASER_SAFETY_LOCK_BYTE 0x0040 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__laser_safety_lock_byte +*/ +#define VL53L1_NVM__LASER_SAFETY_UNLOCK_BYTE 0x0044 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__laser_safety_unlock_byte +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_0_ 0x0048 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_0_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_1_ 0x0049 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_1_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_2_ 0x004A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_2_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_3_ 0x004B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_3_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_4_ 0x004C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_4_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_5_ 0x004D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_5_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_6_ 0x004E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_6_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_7_ 0x004F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_7_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_8_ 0x0050 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_8_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_9_ 0x0051 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_9_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_10_ 0x0052 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_10_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_11_ 0x0053 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_11_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_12_ 0x0054 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_12_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_13_ 0x0055 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_13_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_14_ 0x0056 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_14_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_15_ 0x0057 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_15_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_16_ 0x0058 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_16_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_17_ 0x0059 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_17_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_18_ 0x005A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_18_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_19_ 0x005B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_19_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_20_ 0x005C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_20_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_21_ 0x005D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_21_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_22_ 0x005E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_22_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_23_ 0x005F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_23_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_24_ 0x0060 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_24_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_25_ 0x0061 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_25_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_26_ 0x0062 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_26_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_27_ 0x0063 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_27_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_28_ 0x0064 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_28_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_29_ 0x0065 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_29_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_30_ 0x0066 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_30_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_RTN_31_ 0x0067 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_rtn_31_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC1_0_ 0x0068 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc1_0_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC1_1_ 0x0069 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc1_1_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC1_2_ 0x006A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc1_2_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC1_3_ 0x006B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc1_3_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC1_4_ 0x006C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc1_4_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC1_5_ 0x006D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc1_5_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC2_0_ 0x0070 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc2_0_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC2_1_ 0x0071 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc2_1_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC2_2_ 0x0072 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc2_2_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC2_3_ 0x0073 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc2_3_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC2_4_ 0x0074 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc2_4_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC2_5_ 0x0075 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc2_5_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC3_0_ 0x0078 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc3_0_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC3_1_ 0x0079 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc3_1_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC3_2_ 0x007A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc3_2_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC3_3_ 0x007B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc3_3_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC3_4_ 0x007C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc3_4_ +*/ +#define VL53L1_NVM__EWS__SPAD_ENABLES_REF__LOC3_5_ 0x007D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__spad_enables_ref__loc3_5_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_0_ 0x0080 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_0_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_1_ 0x0081 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_1_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_2_ 0x0082 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_2_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_3_ 0x0083 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_3_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_4_ 0x0084 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_4_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_5_ 0x0085 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_5_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_6_ 0x0086 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_6_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_7_ 0x0087 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_7_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_8_ 0x0088 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_8_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_9_ 0x0089 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_9_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_10_ 0x008A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_10_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_11_ 0x008B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_11_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_12_ 0x008C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_12_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_13_ 0x008D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_13_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_14_ 0x008E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_14_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_15_ 0x008F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_15_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_16_ 0x0090 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_16_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_17_ 0x0091 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_17_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_18_ 0x0092 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_18_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_19_ 0x0093 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_19_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_20_ 0x0094 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_20_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_21_ 0x0095 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_21_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_22_ 0x0096 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_22_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_23_ 0x0097 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_23_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_24_ 0x0098 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_24_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_25_ 0x0099 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_25_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_26_ 0x009A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_26_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_27_ 0x009B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_27_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_28_ 0x009C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_28_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_29_ 0x009D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_29_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_30_ 0x009E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_30_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_RTN_31_ 0x009F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_rtn_31_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC1_0_ 0x00A0 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc1_0_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC1_1_ 0x00A1 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc1_1_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC1_2_ 0x00A2 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc1_2_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC1_3_ 0x00A3 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc1_3_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC1_4_ 0x00A4 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc1_4_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC1_5_ 0x00A5 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc1_5_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC2_0_ 0x00A8 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc2_0_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC2_1_ 0x00A9 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc2_1_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC2_2_ 0x00AA +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc2_2_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC2_3_ 0x00AB +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc2_3_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC2_4_ 0x00AC +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc2_4_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC2_5_ 0x00AD +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc2_5_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC3_0_ 0x00B0 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc3_0_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC3_1_ 0x00B1 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc3_1_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC3_2_ 0x00B2 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc3_2_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC3_3_ 0x00B3 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc3_3_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC3_4_ 0x00B4 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc3_4_ +*/ +#define VL53L1_NVM__FMT__SPAD_ENABLES_REF__LOC3_5_ 0x00B5 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spad_enables_ref__loc3_5_ +*/ +#define VL53L1_NVM__FMT__ROI_CONFIG__MODE_ROI_CENTRE_SPAD 0x00B8 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__roi_config__mode_roi_centre_spad +*/ +#define VL53L1_NVM__FMT__ROI_CONFIG__MODE_ROI_XY_SIZE 0x00B9 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:4] = nvm__fmt__roi_config__mode_roi_x_size + - [3:0] = nvm__fmt__roi_config__mode_roi_y_size +*/ +#define VL53L1_NVM__FMT__REF_SPAD_APPLY__NUM_REQUESTED_REF_SPAD 0x00BC +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__ref_spad_apply__num_requested_ref_spad +*/ +#define VL53L1_NVM__FMT__REF_SPAD_MAN__REF_LOCATION 0x00BD +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [1:0] = nvm__fmt__ref_spad_man__ref_location +*/ +#define VL53L1_NVM__FMT__MM_CONFIG__INNER_OFFSET_MM 0x00C0 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__fmt__mm_config__inner_offset_mm +*/ +#define VL53L1_NVM__FMT__MM_CONFIG__OUTER_OFFSET_MM 0x00C2 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__fmt__mm_config__outer_offset_mm +*/ +#define VL53L1_NVM__FMT__ALGO__PART_TO_PART_RANGE_OFFSET_MM 0x00C4 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 11 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [11:0] = nvm__fmt__algo_part_to_part_range_offset_mm (fixed point 10.2) +*/ +#define VL53L1_NVM__FMT__ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS 0x00C8 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__fmt__algo__crosstalk_compensation_plane_offset_kcps (fixed point 7.9) +*/ +#define VL53L1_NVM__FMT__ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS 0x00CA +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__fmt__algo__crosstalk_compensation_x_plane_gradient_kcps (fixed point 5.11) +*/ +#define VL53L1_NVM__FMT__ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS 0x00CC +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__fmt__algo__crosstalk_compensation_y_plane_gradient_kcps (fixed point 5.11) +*/ +#define VL53L1_NVM__FMT__SPARE_HOST_CONFIG__NVM_CONFIG_SPARE_0 0x00CE +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spare__host_config__nvm_config_spare_0 +*/ +#define VL53L1_NVM__FMT__SPARE_HOST_CONFIG__NVM_CONFIG_SPARE_1 0x00CF +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__spare__host_config__nvm_config_spare_1 +*/ +#define VL53L1_NVM__CUSTOMER_NVM_SPACE_PROGRAMMED 0x00E0 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__customer_space_programmed +*/ +#define VL53L1_NVM__CUST__I2C_SLAVE__DEVICE_ADDRESS 0x00E4 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__cust__i2c_device_address +*/ +#define VL53L1_NVM__CUST__REF_SPAD_APPLY__NUM_REQUESTED_REF_SPAD 0x00E8 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__cust__ref_spad_apply__num_requested_ref_spad +*/ +#define VL53L1_NVM__CUST__REF_SPAD_MAN__REF_LOCATION 0x00E9 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [1:0] = nvm__cust__ref_spad_man__ref_location +*/ +#define VL53L1_NVM__CUST__MM_CONFIG__INNER_OFFSET_MM 0x00EC +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__cust__mm_config__inner_offset_mm +*/ +#define VL53L1_NVM__CUST__MM_CONFIG__OUTER_OFFSET_MM 0x00EE +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__cust__mm_config__outer_offset_mm +*/ +#define VL53L1_NVM__CUST__ALGO__PART_TO_PART_RANGE_OFFSET_MM 0x00F0 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 11 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [11:0] = nvm__cust__algo_part_to_part_range_offset_mm (fixed point 10.2) +*/ +#define VL53L1_NVM__CUST__ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS 0x00F4 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__cust__algo__crosstalk_compensation_plane_offset_kcps (fixed point 7.9) +*/ +#define VL53L1_NVM__CUST__ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS 0x00F6 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__cust__algo__crosstalk_compensation_x_plane_gradient_kcps (fixed point 5.11) +*/ +#define VL53L1_NVM__CUST__ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS 0x00F8 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__cust__algo__crosstalk_compensation_y_plane_gradient_kcps (fixed point 5.11) +*/ +#define VL53L1_NVM__CUST__SPARE_HOST_CONFIG__NVM_CONFIG_SPARE_0 0x00FA +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__cust__spare__host_config__nvm_config_spare_0 +*/ +#define VL53L1_NVM__CUST__SPARE_HOST_CONFIG__NVM_CONFIG_SPARE_1 0x00FB +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__cust__spare__host_config__nvm_config_spare_1 +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_0 0x01DC +/*!< + type: char \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 1 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:1] = nvm__fmt__fgc_0_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_1 0x01DD +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 8 + - lsb = 2 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [8:2] = nvm__fmt__fgc_1_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_2 0x01DE +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 9 + - lsb = 3 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [9:3] = nvm__fmt__fgc_2_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_3 0x01DF +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 10 + - lsb = 4 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [10:4] = nvm__fmt__fgc_3_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_4 0x01E0 +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 11 + - lsb = 5 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [11:5] = nvm__fmt__fgc_4_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_5 0x01E1 +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 12 + - lsb = 6 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [12:6] = nvm__fmt__fgc_5_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_6 0x01E2 +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 13 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [13:7] = nvm__fmt__fgc_6_ + - [6:0] = nvm__fmt__fgc_7_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_7 0x01E3 +/*!< + type: char \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 1 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:1] = nvm__fmt__fgc_8_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_8 0x01E4 +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 8 + - lsb = 2 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [8:2] = nvm__fmt__fgc_9_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_9 0x01E5 +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 9 + - lsb = 3 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [9:3] = nvm__fmt__fgc_10_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_10 0x01E6 +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 10 + - lsb = 4 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [10:4] = nvm__fmt__fgc_11_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_11 0x01E7 +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 11 + - lsb = 5 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [11:5] = nvm__fmt__fgc_12_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_12 0x01E8 +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 12 + - lsb = 6 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [12:6] = nvm__fmt__fgc_13_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_13 0x01E9 +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 13 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [13:7] = nvm__fmt__fgc_14_ + - [6:0] = nvm__fmt__fgc_15_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_14 0x01EA +/*!< + type: char \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 1 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:1] = nvm__fmt__fgc_16_ +*/ +#define VL53L1_NVM__FMT__FGC__BYTE_15 0x01EB +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 8 + - lsb = 2 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [8:2] = nvm__fmt__fgc_17_ +*/ +#define VL53L1_NVM__FMT__TEST_PROGRAM_MAJOR_MINOR 0x01EC +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:5] = nvm__fmt__test_program_major + - [4:0] = nvm__fmt__test_program_minor +*/ +#define VL53L1_NVM__FMT__MAP_MAJOR_MINOR 0x01ED +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:5] = nvm__fmt__map_major + - [4:0] = nvm__fmt__map_minor +*/ +#define VL53L1_NVM__FMT__YEAR_MONTH 0x01EE +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:4] = nvm__fmt__year + - [3:0] = nvm__fmt__month +*/ +#define VL53L1_NVM__FMT__DAY_MODULE_DATE_PHASE 0x01EF +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:3] = nvm__fmt__day + - [2:0] = nvm__fmt__module_date_phase +*/ +#define VL53L1_NVM__FMT__TIME 0x01F0 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [15:0] = nvm__fmt__time +*/ +#define VL53L1_NVM__FMT__TESTER_ID 0x01F2 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__tester_id +*/ +#define VL53L1_NVM__FMT__SITE_ID 0x01F3 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__fmt__site_id +*/ +#define VL53L1_NVM__EWS__TEST_PROGRAM_MAJOR_MINOR 0x01F4 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:5] = nvm__ews__test_program_major + - [4:0] = nvm__ews__test_program_minor +*/ +#define VL53L1_NVM__EWS__PROBE_CARD_MAJOR_MINOR 0x01F5 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:4] = nvm__ews__probe_card_major + - [3:0] = nvm__ews__probe_card_minor +*/ +#define VL53L1_NVM__EWS__TESTER_ID 0x01F6 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__tester_id +*/ +#define VL53L1_NVM__EWS__LOT__BYTE_0 0x01F8 +/*!< + type: char \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 2 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:2] = nvm__ews__lot_6_ +*/ +#define VL53L1_NVM__EWS__LOT__BYTE_1 0x01F9 +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 9 + - lsb = 4 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [9:4] = nvm__ews__lot_5_ +*/ +#define VL53L1_NVM__EWS__LOT__BYTE_2 0x01FA +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 11 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [11:6] = nvm__ews__lot_4_ + - [5:0] = nvm__ews__lot_3_ +*/ +#define VL53L1_NVM__EWS__LOT__BYTE_3 0x01FB +/*!< + type: char \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 2 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:2] = nvm__ews__lot_2_ +*/ +#define VL53L1_NVM__EWS__LOT__BYTE_4 0x01FC +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 9 + - lsb = 4 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [9:4] = nvm__ews__lot_1_ +*/ +#define VL53L1_NVM__EWS__LOT__BYTE_5 0x01FD +/*!< + type: char \n + default: 0x0000 \n + info: \n + - msb = 11 + - lsb = 6 + - i2c_size = 2 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [11:6] = nvm__ews__lot_0_ +*/ +#define VL53L1_NVM__EWS__WAFER 0x01FD +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [4:0] = nvm__ews__wafer +*/ +#define VL53L1_NVM__EWS__XCOORD 0x01FE +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__xcoord +*/ +#define VL53L1_NVM__EWS__YCOORD 0x01FF +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['decoded_nvm_data'] + + fields: \n + - [7:0] = nvm__ews__ycoord +*/ + +#define VL53L1_NVM__FMT__OPTICAL_CENTRE_DATA_INDEX 0x00B8 +#define VL53L1_NVM__FMT__OPTICAL_CENTRE_DATA_SIZE 4 + +#define VL53L1_NVM__FMT__CAL_PEAK_RATE_MAP_DATA_INDEX 0x015C +#define VL53L1_NVM__FMT__CAL_PEAK_RATE_MAP_DATA_SIZE 56 + +#define VL53L1_NVM__FMT__ADDITIONAL_OFFSET_CAL_DATA_INDEX 0x0194 +#define VL53L1_NVM__FMT__ADDITIONAL_OFFSET_CAL_DATA_SIZE 8 + +#define VL53L1_NVM__FMT__RANGE_RESULTS__140MM_MM_PRE_RANGE 0x019C +#define VL53L1_NVM__FMT__RANGE_RESULTS__140MM_DARK 0x01AC +#define VL53L1_NVM__FMT__RANGE_RESULTS__400MM_DARK 0x01BC +#define VL53L1_NVM__FMT__RANGE_RESULTS__400MM_AMBIENT 0x01CC +#define VL53L1_NVM__FMT__RANGE_RESULTS__SIZE_BYTES 16 + +/** @} VL53L1_nvm_DefineRegisters_group */ + + + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/App/VL53L1X_API/core/inc/vl53l1_preset_setup.h b/App/VL53L1X_API/core/inc/vl53l1_preset_setup.h new file mode 100644 index 0000000..150575a --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_preset_setup.h @@ -0,0 +1,72 @@ + +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/****************************************************************************** + * Copyright (c) 2020, STMicroelectronics - All Rights Reserved + + This file is part of VL53L1 and is dual licensed, + either GPL-2.0+ + or 'BSD 3-clause "New" or "Revised" License' , at your option. + ****************************************************************************** + */ + +#ifndef _VL53L1_PRESET_SETUP_H_ +#define _VL53L1_PRESET_SETUP_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* indexes for the bare driver tuning setting API function */ +enum VL53L1_Tuning_t { + VL53L1_TUNING_VERSION = 0, + VL53L1_TUNING_PROXY_MIN, + VL53L1_TUNING_SINGLE_TARGET_XTALK_TARGET_DISTANCE_MM, + VL53L1_TUNING_SINGLE_TARGET_XTALK_SAMPLE_NUMBER, + VL53L1_TUNING_MIN_AMBIENT_DMAX_VALID, + VL53L1_TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER, + VL53L1_TUNING_XTALK_FULL_ROI_TARGET_DISTANCE_MM, + VL53L1_TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT, + VL53L1_TUNING_XTALK_FULL_ROI_BIN_SUM_MARGIN, + VL53L1_TUNING_XTALK_FULL_ROI_DEFAULT_OFFSET, + VL53L1_TUNING_ZERO_DISTANCE_OFFSET_NON_LINEAR_FACTOR, + VL53L1_TUNING_PHASECAL_PATCH_POWER, + VL53L1_TUNING_MAX_TUNABLE_KEY +}; + +/* default values for the tuning settings parameters */ +#define TUNING_VERSION 0x0007 + +#define TUNING_PROXY_MIN -30 /* min distance in mm */ +#define TUNING_SINGLE_TARGET_XTALK_TARGET_DISTANCE_MM 600 +/* Target distance in mm for single target Xtalk */ +#define TUNING_SINGLE_TARGET_XTALK_SAMPLE_NUMBER 50 +/* Number of sample used for single target Xtalk */ +#define TUNING_MIN_AMBIENT_DMAX_VALID 8 +/* Minimum ambient level to state the Dmax returned by the device is valid */ +#define TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER 50 +/* Maximum loops to perform simple offset calibration */ +#define TUNING_XTALK_FULL_ROI_TARGET_DISTANCE_MM 600 +/* Target distance in mm for target Xtalk from Bins method*/ +#define TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT 1 +/* Number of loops done during the simple offset calibration*/ +#define TUNING_ZERO_DISTANCE_OFFSET_NON_LINEAR_FACTOR_DEFAULT 9 +/* zero distance offset calibration non linear compensation default value */ + +/* The following settings are related to the fix for ticket EwokP #558410 */ +#define TUNING_XTALK_FULL_ROI_BIN_SUM_MARGIN 24 +/* Acceptance margin for the xtalk_shape bin_data sum computation */ +#define TUNING_XTALK_FULL_ROI_DEFAULT_OFFSET 50 +/* Recovery value for Xtalk compensation plane offset in kcps */ +/* 50 stands for ~0.10 kcps cover glass in 7.9 format */ +/* End of settings related to the fix for ticket EwokP #558410 */ +#define TUNING_PHASECAL_PATCH_POWER 0 +/* PhaseCal duration patch tuning param + * 0 default duration 15ms, 1 leads to 60ms, 2 for 240ms and 3 for 3580ms + */ + +#ifdef __cplusplus +} +#endif + +#endif /* _VL53L1_PRESET_SETUP_H_ */ diff --git a/App/VL53L1X_API/core/inc/vl53l1_register_funcs.h b/App/VL53L1X_API/core/inc/vl53l1_register_funcs.h new file mode 100644 index 0000000..e58e4f0 --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_register_funcs.h @@ -0,0 +1,1635 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_register_funcs.h + * @brief VL53L1 Register Function declarations + */ + +#ifndef _VL53L1_REGISTER_FUNCS_H_ +#define _VL53L1_REGISTER_FUNCS_H_ + +#include "vl53l1_platform.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** + * @brief Encodes data structure VL53L1_static_nvm_managed_t into a I2C write buffer + * + * Buffer must be at least 11 bytes + * + * @param[in] pdata : pointer to VL53L1_static_nvm_managed_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +VL53L1_Error VL53L1_i2c_encode_static_nvm_managed( + VL53L1_static_nvm_managed_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_static_nvm_managed_t from the input I2C read buffer + * + * Buffer must be at least 11 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_static_nvm_managed_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_static_nvm_managed( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_static_nvm_managed_t *pdata); + + +/** + * @brief Sets static_nvm_managed register group + * + * Serailises (encodes) VL53L1_static_nvm_managed_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_static_nvm_managed_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_static_nvm_managed( + VL53L1_DEV Dev, + VL53L1_static_nvm_managed_t *pdata); + + +/** + * @brief Gets static_nvm_managed register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_static_nvm_managed_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_static_nvm_managed_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_static_nvm_managed( + VL53L1_DEV Dev, + VL53L1_static_nvm_managed_t *pdata); + + +/** + * @brief Encodes data structure VL53L1_customer_nvm_managed_t into a I2C write buffer + * + * Buffer must be at least 23 bytes + * + * @param[in] pdata : pointer to VL53L1_customer_nvm_managed_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +VL53L1_Error VL53L1_i2c_encode_customer_nvm_managed( + VL53L1_customer_nvm_managed_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_customer_nvm_managed_t from the input I2C read buffer + * + * Buffer must be at least 23 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_customer_nvm_managed_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_customer_nvm_managed( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_customer_nvm_managed_t *pdata); + + +/** + * @brief Sets customer_nvm_managed register group + * + * Serailises (encodes) VL53L1_customer_nvm_managed_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_customer_nvm_managed_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_customer_nvm_managed( + VL53L1_DEV Dev, + VL53L1_customer_nvm_managed_t *pdata); + + +/** + * @brief Gets customer_nvm_managed register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_customer_nvm_managed_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_customer_nvm_managed_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_customer_nvm_managed( + VL53L1_DEV Dev, + VL53L1_customer_nvm_managed_t *pdata); + + +/** + * @brief Encodes data structure VL53L1_static_config_t into a I2C write buffer + * + * Buffer must be at least 32 bytes + * + * @param[in] pdata : pointer to VL53L1_static_config_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +VL53L1_Error VL53L1_i2c_encode_static_config( + VL53L1_static_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_static_config_t from the input I2C read buffer + * + * Buffer must be at least 32 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_static_config_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_static_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_static_config_t *pdata); + + +/** + * @brief Sets static_config register group + * + * Serailises (encodes) VL53L1_static_config_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_static_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_static_config( + VL53L1_DEV Dev, + VL53L1_static_config_t *pdata); + + +/** + * @brief Gets static_config register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_static_config_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_static_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_static_config( + VL53L1_DEV Dev, + VL53L1_static_config_t *pdata); +#endif + + +/** + * @brief Encodes data structure VL53L1_general_config_t into a I2C write buffer + * + * Buffer must be at least 22 bytes + * + * @param[in] pdata : pointer to VL53L1_general_config_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +VL53L1_Error VL53L1_i2c_encode_general_config( + VL53L1_general_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_general_config_t from the input I2C read buffer + * + * Buffer must be at least 22 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_general_config_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_general_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_general_config_t *pdata); + + +/** + * @brief Sets general_config register group + * + * Serailises (encodes) VL53L1_general_config_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_general_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_general_config( + VL53L1_DEV Dev, + VL53L1_general_config_t *pdata); + + +/** + * @brief Gets general_config register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_general_config_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_general_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_general_config( + VL53L1_DEV Dev, + VL53L1_general_config_t *pdata); +#endif + + +/** + * @brief Encodes data structure VL53L1_timing_config_t into a I2C write buffer + * + * Buffer must be at least 23 bytes + * + * @param[in] pdata : pointer to VL53L1_timing_config_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +VL53L1_Error VL53L1_i2c_encode_timing_config( + VL53L1_timing_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_timing_config_t from the input I2C read buffer + * + * Buffer must be at least 23 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_timing_config_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_decode_timing_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_timing_config_t *pdata); +#endif + + +/** + * @brief Sets timing_config register group + * + * Serailises (encodes) VL53L1_timing_config_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_timing_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_set_timing_config( + VL53L1_DEV Dev, + VL53L1_timing_config_t *pdata); +#endif + + +/** + * @brief Gets timing_config register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_timing_config_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_timing_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_timing_config( + VL53L1_DEV Dev, + VL53L1_timing_config_t *pdata); +#endif + + +/** + * @brief Encodes data structure VL53L1_dynamic_config_t into a I2C write buffer + * + * Buffer must be at least 18 bytes + * + * @param[in] pdata : pointer to VL53L1_dynamic_config_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +VL53L1_Error VL53L1_i2c_encode_dynamic_config( + VL53L1_dynamic_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_dynamic_config_t from the input I2C read buffer + * + * Buffer must be at least 18 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_dynamic_config_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_decode_dynamic_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_dynamic_config_t *pdata); +#endif + + +/** + * @brief Sets dynamic_config register group + * + * Serailises (encodes) VL53L1_dynamic_config_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_dynamic_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_dynamic_config( + VL53L1_DEV Dev, + VL53L1_dynamic_config_t *pdata); + + +/** + * @brief Gets dynamic_config register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_dynamic_config_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_dynamic_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_dynamic_config( + VL53L1_DEV Dev, + VL53L1_dynamic_config_t *pdata); +#endif + +/** + * @brief Encodes data structure VL53L1_system_control_t into a I2C write buffer + * + * Buffer must be at least 5 bytes + * + * @param[in] pdata : pointer to VL53L1_system_control_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +VL53L1_Error VL53L1_i2c_encode_system_control( + VL53L1_system_control_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_system_control_t from the input I2C read buffer + * + * Buffer must be at least 5 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_system_control_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_decode_system_control( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_system_control_t *pdata); +#endif + + +/** + * @brief Sets system_control register group + * + * Serailises (encodes) VL53L1_system_control_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_system_control_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_system_control( + VL53L1_DEV Dev, + VL53L1_system_control_t *pdata); + + +/** + * @brief Gets system_control register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_system_control_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_system_control_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_system_control( + VL53L1_DEV Dev, + VL53L1_system_control_t *pdata); +#endif + + +/** + * @brief Encodes data structure VL53L1_system_results_t into a I2C write buffer + * + * Buffer must be at least 44 bytes + * + * @param[in] pdata : pointer to VL53L1_system_results_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_encode_system_results( + VL53L1_system_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); +#endif + + +/** + * @brief Decodes data structure VL53L1_system_results_t from the input I2C read buffer + * + * Buffer must be at least 44 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_system_results_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_system_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_system_results_t *pdata); + + +/** + * @brief Sets system_results register group + * + * Serailises (encodes) VL53L1_system_results_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_system_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_set_system_results( + VL53L1_DEV Dev, + VL53L1_system_results_t *pdata); +#endif + + +/** + * @brief Gets system_results register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_system_results_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_system_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_system_results( + VL53L1_DEV Dev, + VL53L1_system_results_t *pdata); + + +/** + * @brief Encodes data structure VL53L1_core_results_t into a I2C write buffer + * + * Buffer must be at least 33 bytes + * + * @param[in] pdata : pointer to VL53L1_core_results_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_encode_core_results( + VL53L1_core_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); +#endif + + +/** + * @brief Decodes data structure VL53L1_core_results_t from the input I2C read buffer + * + * Buffer must be at least 33 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_core_results_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_core_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_core_results_t *pdata); + + +/** + * @brief Sets core_results register group + * + * Serailises (encodes) VL53L1_core_results_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_core_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_set_core_results( + VL53L1_DEV Dev, + VL53L1_core_results_t *pdata); +#endif + + +/** + * @brief Gets core_results register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_core_results_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_core_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_get_core_results( + VL53L1_DEV Dev, + VL53L1_core_results_t *pdata); +#endif + + +/** + * @brief Encodes data structure VL53L1_debug_results_t into a I2C write buffer + * + * Buffer must be at least 56 bytes + * + * @param[in] pdata : pointer to VL53L1_debug_results_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_i2c_encode_debug_results( + VL53L1_debug_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); +#endif + +/** + * @brief Decodes data structure VL53L1_debug_results_t from the input I2C read buffer + * + * Buffer must be at least 56 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_debug_results_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_debug_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_debug_results_t *pdata); + + +/** + * @brief Sets debug_results register group + * + * Serailises (encodes) VL53L1_debug_results_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_debug_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_set_debug_results( + VL53L1_DEV Dev, + VL53L1_debug_results_t *pdata); + +/** + * @brief Gets debug_results register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_debug_results_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_debug_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_debug_results( + VL53L1_DEV Dev, + VL53L1_debug_results_t *pdata); + +#endif + +/** + * @brief Encodes data structure VL53L1_nvm_copy_data_t into a I2C write buffer + * + * Buffer must be at least 49 bytes + * + * @param[in] pdata : pointer to VL53L1_nvm_copy_data_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_encode_nvm_copy_data( + VL53L1_nvm_copy_data_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); +#endif + + +/** + * @brief Decodes data structure VL53L1_nvm_copy_data_t from the input I2C read buffer + * + * Buffer must be at least 49 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_nvm_copy_data_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_nvm_copy_data( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_nvm_copy_data_t *pdata); + + +/** + * @brief Sets nvm_copy_data register group + * + * Serailises (encodes) VL53L1_nvm_copy_data_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_nvm_copy_data_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_set_nvm_copy_data( + VL53L1_DEV Dev, + VL53L1_nvm_copy_data_t *pdata); +#endif + + +/** + * @brief Gets nvm_copy_data register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_nvm_copy_data_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_nvm_copy_data_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_nvm_copy_data( + VL53L1_DEV Dev, + VL53L1_nvm_copy_data_t *pdata); + + +/** + * @brief Encodes data structure VL53L1_prev_shadow_system_results_t into a I2C write buffer + * + * Buffer must be at least 44 bytes + * + * @param[in] pdata : pointer to VL53L1_prev_shadow_system_results_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_i2c_encode_prev_shadow_system_results( + VL53L1_prev_shadow_system_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_prev_shadow_system_results_t from the input I2C read buffer + * + * Buffer must be at least 44 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_prev_shadow_system_results_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_prev_shadow_system_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_prev_shadow_system_results_t *pdata); + + +/** + * @brief Sets prev_shadow_system_results register group + * + * Serailises (encodes) VL53L1_prev_shadow_system_results_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_prev_shadow_system_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_prev_shadow_system_results( + VL53L1_DEV Dev, + VL53L1_prev_shadow_system_results_t *pdata); + + +/** + * @brief Gets prev_shadow_system_results register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_prev_shadow_system_results_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_prev_shadow_system_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_prev_shadow_system_results( + VL53L1_DEV Dev, + VL53L1_prev_shadow_system_results_t *pdata); + +/** + * @brief Encodes data structure VL53L1_prev_shadow_core_results_t into a I2C write buffer + * + * Buffer must be at least 33 bytes + * + * @param[in] pdata : pointer to VL53L1_prev_shadow_core_results_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +VL53L1_Error VL53L1_i2c_encode_prev_shadow_core_results( + VL53L1_prev_shadow_core_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_prev_shadow_core_results_t from the input I2C read buffer + * + * Buffer must be at least 33 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_prev_shadow_core_results_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_prev_shadow_core_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_prev_shadow_core_results_t *pdata); + + +/** + * @brief Sets prev_shadow_core_results register group + * + * Serailises (encodes) VL53L1_prev_shadow_core_results_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_prev_shadow_core_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_prev_shadow_core_results( + VL53L1_DEV Dev, + VL53L1_prev_shadow_core_results_t *pdata); + + +/** + * @brief Gets prev_shadow_core_results register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_prev_shadow_core_results_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_prev_shadow_core_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_get_prev_shadow_core_results( + VL53L1_DEV Dev, + VL53L1_prev_shadow_core_results_t *pdata); + + +/** + * @brief Encodes data structure VL53L1_patch_debug_t into a I2C write buffer + * + * Buffer must be at least 2 bytes + * + * @param[in] pdata : pointer to VL53L1_patch_debug_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +VL53L1_Error VL53L1_i2c_encode_patch_debug( + VL53L1_patch_debug_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_patch_debug_t from the input I2C read buffer + * + * Buffer must be at least 2 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_patch_debug_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_patch_debug( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_patch_debug_t *pdata); + + +/** + * @brief Sets patch_debug register group + * + * Serailises (encodes) VL53L1_patch_debug_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_patch_debug_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_patch_debug( + VL53L1_DEV Dev, + VL53L1_patch_debug_t *pdata); + + +/** + * @brief Gets patch_debug register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_patch_debug_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_patch_debug_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_patch_debug( + VL53L1_DEV Dev, + VL53L1_patch_debug_t *pdata); + +#endif + +/** + * @brief Encodes data structure VL53L1_gph_general_config_t into a I2C write buffer + * + * Buffer must be at least 5 bytes + * + * @param[in] pdata : pointer to VL53L1_gph_general_config_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_encode_gph_general_config( + VL53L1_gph_general_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); +#endif + + +/** + * @brief Decodes data structure VL53L1_gph_general_config_t from the input I2C read buffer + * + * Buffer must be at least 5 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_gph_general_config_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_decode_gph_general_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_gph_general_config_t *pdata); +#endif + + +/** + * @brief Sets gph_general_config register group + * + * Serailises (encodes) VL53L1_gph_general_config_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_gph_general_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_set_gph_general_config( + VL53L1_DEV Dev, + VL53L1_gph_general_config_t *pdata); +#endif + +/** + * @brief Gets gph_general_config register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_gph_general_config_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_gph_general_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_get_gph_general_config( + VL53L1_DEV Dev, + VL53L1_gph_general_config_t *pdata); +#endif + + +/** + * @brief Encodes data structure VL53L1_gph_static_config_t into a I2C write buffer + * + * Buffer must be at least 6 bytes + * + * @param[in] pdata : pointer to VL53L1_gph_static_config_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_encode_gph_static_config( + VL53L1_gph_static_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); +#endif + + +/** + * @brief Decodes data structure VL53L1_gph_static_config_t from the input I2C read buffer + * + * Buffer must be at least 6 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_gph_static_config_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_decode_gph_static_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_gph_static_config_t *pdata); +#endif + + +/** + * @brief Sets gph_static_config register group + * + * Serailises (encodes) VL53L1_gph_static_config_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_gph_static_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_set_gph_static_config( + VL53L1_DEV Dev, + VL53L1_gph_static_config_t *pdata); +#endif + + +/** + * @brief Gets gph_static_config register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_gph_static_config_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_gph_static_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_get_gph_static_config( + VL53L1_DEV Dev, + VL53L1_gph_static_config_t *pdata); +#endif + + +/** + * @brief Encodes data structure VL53L1_gph_timing_config_t into a I2C write buffer + * + * Buffer must be at least 16 bytes + * + * @param[in] pdata : pointer to VL53L1_gph_timing_config_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_encode_gph_timing_config( + VL53L1_gph_timing_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); +#endif + + +/** + * @brief Decodes data structure VL53L1_gph_timing_config_t from the input I2C read buffer + * + * Buffer must be at least 16 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_gph_timing_config_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_decode_gph_timing_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_gph_timing_config_t *pdata); +#endif + + +/** + * @brief Sets gph_timing_config register group + * + * Serailises (encodes) VL53L1_gph_timing_config_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_gph_timing_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_set_gph_timing_config( + VL53L1_DEV Dev, + VL53L1_gph_timing_config_t *pdata); +#endif + + +/** + * @brief Gets gph_timing_config register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_gph_timing_config_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_gph_timing_config_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_get_gph_timing_config( + VL53L1_DEV Dev, + VL53L1_gph_timing_config_t *pdata); +#endif + + +/** + * @brief Encodes data structure VL53L1_fw_internal_t into a I2C write buffer + * + * Buffer must be at least 2 bytes + * + * @param[in] pdata : pointer to VL53L1_fw_internal_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_i2c_encode_fw_internal( + VL53L1_fw_internal_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_fw_internal_t from the input I2C read buffer + * + * Buffer must be at least 2 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_fw_internal_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_fw_internal( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_fw_internal_t *pdata); + + +/** + * @brief Sets fw_internal register group + * + * Serailises (encodes) VL53L1_fw_internal_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_fw_internal_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_fw_internal( + VL53L1_DEV Dev, + VL53L1_fw_internal_t *pdata); + + +/** + * @brief Gets fw_internal register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_fw_internal_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_fw_internal_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_fw_internal( + VL53L1_DEV Dev, + VL53L1_fw_internal_t *pdata); + + + +/** + * @brief Encodes data structure VL53L1_patch_results_t into a I2C write buffer + * + * Buffer must be at least 90 bytes + * + * @param[in] pdata : pointer to VL53L1_patch_results_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +VL53L1_Error VL53L1_i2c_encode_patch_results( + VL53L1_patch_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_patch_results_t from the input I2C read buffer + * + * Buffer must be at least 90 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_patch_results_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_patch_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_patch_results_t *pdata); + + +/** + * @brief Sets patch_results register group + * + * Serailises (encodes) VL53L1_patch_results_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_patch_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_patch_results( + VL53L1_DEV Dev, + VL53L1_patch_results_t *pdata); + + +/** + * @brief Gets patch_results register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_patch_results_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_patch_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_patch_results( + VL53L1_DEV Dev, + VL53L1_patch_results_t *pdata); +#endif + + +/** + * @brief Encodes data structure VL53L1_shadow_system_results_t into a I2C write buffer + * + * Buffer must be at least 82 bytes + * + * @param[in] pdata : pointer to VL53L1_shadow_system_results_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_i2c_encode_shadow_system_results( + VL53L1_shadow_system_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_shadow_system_results_t from the input I2C read buffer + * + * Buffer must be at least 82 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_shadow_system_results_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_shadow_system_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_shadow_system_results_t *pdata); + + +/** + * @brief Sets shadow_system_results register group + * + * Serailises (encodes) VL53L1_shadow_system_results_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_shadow_system_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_shadow_system_results( + VL53L1_DEV Dev, + VL53L1_shadow_system_results_t *pdata); + + +/** + * @brief Gets shadow_system_results register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_shadow_system_results_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_shadow_system_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_shadow_system_results( + VL53L1_DEV Dev, + VL53L1_shadow_system_results_t *pdata); + + +/** + * @brief Encodes data structure VL53L1_shadow_core_results_t into a I2C write buffer + * + * Buffer must be at least 33 bytes + * + * @param[in] pdata : pointer to VL53L1_shadow_core_results_t data structure + * @param[in] buf_size : size of input buffer + * @param[out] pbuffer : uint8_t buffer to write serialised data into (I2C Write Buffer) + */ + +VL53L1_Error VL53L1_i2c_encode_shadow_core_results( + VL53L1_shadow_core_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer); + + +/** + * @brief Decodes data structure VL53L1_shadow_core_results_t from the input I2C read buffer + * + * Buffer must be at least 33 bytes + * + * @param[in] buf_size : size of input buffer + * @param[in] pbuffer : uint8_t buffer contain input serialised data (I2C read buffer) + * @param[out] pdata : pointer to VL53L1_shadow_core_results_t data structure + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_i2c_decode_shadow_core_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_shadow_core_results_t *pdata); + + +/** + * @brief Sets shadow_core_results register group + * + * Serailises (encodes) VL53L1_shadow_core_results_t structure into a I2C write data buffer + * and sends the buffer to the device via a multi byte I2C write transaction + * + * @param[in] Dev : device handle + * @param[in] pdata : pointer to VL53L1_shadow_core_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_set_shadow_core_results( + VL53L1_DEV Dev, + VL53L1_shadow_core_results_t *pdata); + + +/** + * @brief Gets shadow_core_results register group + * + * Reads register info from the device via a multi byte I2C read transaction and + * deserialises (decodes) the data into the VL53L1_shadow_core_results_t structure + * + * @param[in] Dev : device handle + * @param[out] pdata : pointer to VL53L1_shadow_core_results_t + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_get_shadow_core_results( + VL53L1_DEV Dev, + VL53L1_shadow_core_results_t *pdata); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/App/VL53L1X_API/core/inc/vl53l1_register_map.h b/App/VL53L1X_API/core/inc/vl53l1_register_map.h new file mode 100644 index 0000000..32ae94f --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_register_map.h @@ -0,0 +1,11895 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_register_map.h + * @brief VL53L1 Register Map definitions + */ + +#ifndef _VL53L1_REGISTER_MAP_H_ +#define _VL53L1_REGISTER_MAP_H_ + +/** @defgroup VL53L1_register_DefineRegisters_group Define Registers * @brief List of all the defined registers + * @{ + */ + +#define VL53L1_SOFT_RESET 0x0000 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_I2C_SLAVE__DEVICE_ADDRESS 0x0001 +/*!< + type: uint8_t \n + default: EWOK_I2C_DEV_ADDR_DEFAULT \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_nvm_managed', 'system_config'] + + fields: \n + - [6:0] = i2c_slave_device_address +*/ +#define VL53L1_ANA_CONFIG__VHV_REF_SEL_VDDPIX 0x0002 +/*!< + type: uint8_t \n + default: 0x02 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_nvm_managed', 'analog_config'] + + fields: \n + - [3:0] = ref_sel_vddpix +*/ +#define VL53L1_ANA_CONFIG__VHV_REF_SEL_VQUENCH 0x0003 +/*!< + type: uint8_t \n + default: 0x10 \n + info: \n + - msb = 6 + - lsb = 3 + - i2c_size = 1 + + groups: \n + ['static_nvm_managed', 'analog_config'] + + fields: \n + - [6:3] = ref_sel_vquench +*/ +#define VL53L1_ANA_CONFIG__REG_AVDD1V2_SEL 0x0004 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_nvm_managed', 'analog_config'] + + fields: \n + - [1:0] = reg_avdd1v2_sel +*/ +#define VL53L1_ANA_CONFIG__FAST_OSC__TRIM 0x0005 +/*!< + type: uint8_t \n + default: 0x48 \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_nvm_managed', 'analog_config'] + + fields: \n + - [6:0] = fast_osc_trim +*/ +#define VL53L1_OSC_MEASURED__FAST_OSC__FREQUENCY 0x0006 +/*!< + type: uint16_t \n + default: OSC_FREQUENCY \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['static_nvm_managed', 'analog_config'] + + fields: \n + - [15:0] = osc_frequency (fixed point 4.12) +*/ +#define VL53L1_OSC_MEASURED__FAST_OSC__FREQUENCY_HI 0x0006 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_OSC_MEASURED__FAST_OSC__FREQUENCY_LO 0x0007 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND 0x0008 +/*!< + type: uint8_t \n + default: 0x81 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_nvm_managed', 'vhv_config'] + + fields: \n + - [1:0] = vhv_timeout__macrop + - [7:2] = vhv_loop_bound +*/ +#define VL53L1_VHV_CONFIG__COUNT_THRESH 0x0009 +/*!< + type: uint8_t \n + default: 0x80 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_nvm_managed', 'vhv_config'] + + fields: \n + - [7:0] = vhv_count_thresh +*/ +#define VL53L1_VHV_CONFIG__OFFSET 0x000A +/*!< + type: uint8_t \n + default: 0x07 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_nvm_managed', 'vhv_config'] + + fields: \n + - [5:0] = vhv_step_val +*/ +#define VL53L1_VHV_CONFIG__INIT 0x000B +/*!< + type: uint8_t \n + default: 0x20 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_nvm_managed', 'vhv_config'] + + fields: \n + - [7] = vhv0_init_enable + - [5:0] = vhv0_init_value +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_0 0x000D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['customer_nvm_managed', 'ref_spad_en'] + + fields: \n + - [7:0] = spad_enables_ref_0 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_1 0x000E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['customer_nvm_managed', 'ref_spad_en'] + + fields: \n + - [7:0] = spad_enables_ref_1 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_2 0x000F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['customer_nvm_managed', 'ref_spad_en'] + + fields: \n + - [7:0] = spad_enables_ref_2 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_3 0x0010 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['customer_nvm_managed', 'ref_spad_en'] + + fields: \n + - [7:0] = spad_enables_ref_3 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_4 0x0011 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['customer_nvm_managed', 'ref_spad_en'] + + fields: \n + - [7:0] = spad_enables_ref_4 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_5 0x0012 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['customer_nvm_managed', 'ref_spad_en'] + + fields: \n + - [3:0] = spad_enables_ref_5 +*/ +#define VL53L1_GLOBAL_CONFIG__REF_EN_START_SELECT 0x0013 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['customer_nvm_managed', 'ref_spad_start'] + + fields: \n + - [7:0] = ref_en_start_select +*/ +#define VL53L1_REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS 0x0014 +/*!< + type: uint8_t \n + default: 0x2C \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['customer_nvm_managed', 'ref_spad_config'] + + fields: \n + - [5:0] = ref_spad_man__num_requested_ref_spad +*/ +#define VL53L1_REF_SPAD_MAN__REF_LOCATION 0x0015 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['customer_nvm_managed', 'ref_spad_config'] + + fields: \n + - [1:0] = ref_spad_man__ref_location +*/ +#define VL53L1_ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS 0x0016 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['customer_nvm_managed', 'algo_config'] + + fields: \n + - [15:0] = crosstalk_compensation_plane_offset_kcps (fixed point 7.9) +*/ +#define VL53L1_ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS_HI 0x0016 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS_LO 0x0017 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS 0x0018 +/*!< + type: int16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['customer_nvm_managed', 'algo_config'] + + fields: \n + - [15:0] = crosstalk_compensation_x_plane_gradient_kcps (fixed point 5.11) +*/ +#define VL53L1_ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS_HI 0x0018 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS_LO 0x0019 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS 0x001A +/*!< + type: int16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['customer_nvm_managed', 'algo_config'] + + fields: \n + - [15:0] = crosstalk_compensation_y_plane_gradient_kcps (fixed point 5.11) +*/ +#define VL53L1_ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS_HI 0x001A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS_LO 0x001B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS 0x001C +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['customer_nvm_managed', 'ref_spad_char'] + + fields: \n + - [15:0] = ref_spad_char__total_rate_target_mcps (fixed point 9.7) +*/ +#define VL53L1_REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS_HI 0x001C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS_LO 0x001D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_ALGO__PART_TO_PART_RANGE_OFFSET_MM 0x001E +/*!< + type: int16_t \n + default: 0x0000 \n + info: \n + - msb = 12 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['customer_nvm_managed', 'algo_config'] + + fields: \n + - [12:0] = part_to_part_offset_mm (fixed point 11.2) +*/ +#define VL53L1_ALGO__PART_TO_PART_RANGE_OFFSET_MM_HI 0x001E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_ALGO__PART_TO_PART_RANGE_OFFSET_MM_LO 0x001F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MM_CONFIG__INNER_OFFSET_MM 0x0020 +/*!< + type: int16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['customer_nvm_managed', 'mm_config'] + + fields: \n + - [15:0] = mm_config__inner_offset_mm +*/ +#define VL53L1_MM_CONFIG__INNER_OFFSET_MM_HI 0x0020 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MM_CONFIG__INNER_OFFSET_MM_LO 0x0021 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MM_CONFIG__OUTER_OFFSET_MM 0x0022 +/*!< + type: int16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['customer_nvm_managed', 'mm_config'] + + fields: \n + - [15:0] = mm_config__outer_offset_mm +*/ +#define VL53L1_MM_CONFIG__OUTER_OFFSET_MM_HI 0x0022 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MM_CONFIG__OUTER_OFFSET_MM_LO 0x0023 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_DSS_CONFIG__TARGET_TOTAL_RATE_MCPS 0x0024 +/*!< + type: uint16_t \n + default: 0x0380 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['static_config', 'dss_config'] + + fields: \n + - [15:0] = dss_config__target_total_rate_mcps (fixed point 9.7) +*/ +#define VL53L1_DSS_CONFIG__TARGET_TOTAL_RATE_MCPS_HI 0x0024 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_DSS_CONFIG__TARGET_TOTAL_RATE_MCPS_LO 0x0025 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_DEBUG__CTRL 0x0026 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'debug_config'] + + fields: \n + - [0] = enable_result_logging +*/ +#define VL53L1_TEST_MODE__CTRL 0x0027 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'test_mode_config'] + + fields: \n + - [3:0] = test_mode__cmd +*/ +#define VL53L1_CLK_GATING__CTRL 0x0028 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'clk_config'] + + fields: \n + - [0] = clk_gate_en__mcu_bank + - [1] = clk_gate_en__mcu_patch_ctrl + - [2] = clk_gate_en__mcu_timers + - [3] = clk_gate_en__mcu_mult_div +*/ +#define VL53L1_NVM_BIST__CTRL 0x0029 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'nvm_bist_config'] + + fields: \n + - [2:0] = nvm_bist__cmd + - [4] = nvm_bist__ctrl +*/ +#define VL53L1_NVM_BIST__NUM_NVM_WORDS 0x002A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'nvm_bist_config'] + + fields: \n + - [6:0] = nvm_bist__num_nvm_words +*/ +#define VL53L1_NVM_BIST__START_ADDRESS 0x002B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'nvm_bist_config'] + + fields: \n + - [6:0] = nvm_bist__start_address +*/ +#define VL53L1_HOST_IF__STATUS 0x002C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'system_status'] + + fields: \n + - [0] = host_interface +*/ +#define VL53L1_PAD_I2C_HV__CONFIG 0x002D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'gpio_config'] + + fields: \n + - [0] = pad_scl_sda__vmodeint_hv + - [1] = i2c_pad__test_hv + - [2] = pad_scl__fpen_hv + - [4:3] = pad_scl__progdel_hv + - [5] = pad_sda__fpen_hv + - [7:6] = pad_sda__progdel_hv +*/ +#define VL53L1_PAD_I2C_HV__EXTSUP_CONFIG 0x002E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'gpio_config'] + + fields: \n + - [0] = pad_scl_sda__extsup_hv +*/ +#define VL53L1_GPIO_HV_PAD__CTRL 0x002F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'gpio_config'] + + fields: \n + - [0] = gpio__extsup_hv + - [1] = gpio__vmodeint_hv +*/ +#define VL53L1_GPIO_HV_MUX__CTRL 0x0030 +/*!< + type: uint8_t \n + default: 0x11 \n + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'gpio_config'] + + fields: \n + - [3:0] = gpio__mux_select_hv + - [4] = gpio__mux_active_high_hv +*/ +#define VL53L1_GPIO__TIO_HV_STATUS 0x0031 +/*!< + type: uint8_t \n + default: 0x02 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'gpio_config'] + + fields: \n + - [0] = gpio__tio_hv + - [1] = fresh_out_of_reset +*/ +#define VL53L1_GPIO__FIO_HV_STATUS 0x0032 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 1 + - i2c_size = 1 + + groups: \n + ['static_config', 'gpio_config'] + + fields: \n + - [1] = gpio__fio_hv +*/ +#define VL53L1_ANA_CONFIG__SPAD_SEL_PSWIDTH 0x0033 +/*!< + type: uint8_t \n + default: 0x02 \n + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'analog_config'] + + fields: \n + - [2:0] = spad_sel_pswidth +*/ +#define VL53L1_ANA_CONFIG__VCSEL_PULSE_WIDTH_OFFSET 0x0034 +/*!< + type: uint8_t \n + default: 0x08 \n + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'analog_config'] + + fields: \n + - [4:0] = vcsel_pulse_width_offset (fixed point 1.4) +*/ +#define VL53L1_ANA_CONFIG__FAST_OSC__CONFIG_CTRL 0x0035 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'analog_config'] + + fields: \n + - [0] = osc_config__latch_bypass +*/ +#define VL53L1_SIGMA_ESTIMATOR__EFFECTIVE_PULSE_WIDTH_NS 0x0036 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'algo_config'] + + fields: \n + - [7:0] = sigma_estimator__eff_pulse_width +*/ +#define VL53L1_SIGMA_ESTIMATOR__EFFECTIVE_AMBIENT_WIDTH_NS 0x0037 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'algo_config'] + + fields: \n + - [7:0] = sigma_estimator__eff_ambient_width +*/ +#define VL53L1_SIGMA_ESTIMATOR__SIGMA_REF_MM 0x0038 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'algo_config'] + + fields: \n + - [7:0] = sigma_estimator__sigma_ref +*/ +#define VL53L1_ALGO__CROSSTALK_COMPENSATION_VALID_HEIGHT_MM 0x0039 +/*!< + type: uint8_t \n + default: 0x14 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'algo_config'] + + fields: \n + - [7:0] = crosstalk_compensation_valid_height_mm +*/ +#define VL53L1_SPARE_HOST_CONFIG__STATIC_CONFIG_SPARE_0 0x003A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'algo_config'] + + fields: \n + - [7:0] = static_config_spare_0 +*/ +#define VL53L1_SPARE_HOST_CONFIG__STATIC_CONFIG_SPARE_1 0x003B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'algo_config'] + + fields: \n + - [7:0] = static_config_spare_1 +*/ +#define VL53L1_ALGO__RANGE_IGNORE_THRESHOLD_MCPS 0x003C +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['static_config', 'algo_config'] + + fields: \n + - [15:0] = range_ignore_thresh_mcps (fixed point 3.13) +*/ +#define VL53L1_ALGO__RANGE_IGNORE_THRESHOLD_MCPS_HI 0x003C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_ALGO__RANGE_IGNORE_THRESHOLD_MCPS_LO 0x003D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_ALGO__RANGE_IGNORE_VALID_HEIGHT_MM 0x003E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'algo_config'] + + fields: \n + - [7:0] = range_ignore_height_mm +*/ +#define VL53L1_ALGO__RANGE_MIN_CLIP 0x003F +/*!< + type: uint8_t \n + default: 0x8D \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'algo_config'] + + fields: \n + - [0] = algo__range_min_clip_enable + - [7:1] = algo__range_min_clip_value_mm +*/ +#define VL53L1_ALGO__CONSISTENCY_CHECK__TOLERANCE 0x0040 +/*!< + type: uint8_t \n + default: 0x08 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'algo_config'] + + fields: \n + - [3:0] = consistency_check_tolerance (fixed point 1.3) +*/ +#define VL53L1_SPARE_HOST_CONFIG__STATIC_CONFIG_SPARE_2 0x0041 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'algo_config'] + + fields: \n + - [7:0] = static_config_spare_2 +*/ +#define VL53L1_SD_CONFIG__RESET_STAGES_MSB 0x0042 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'sigmadelta_config'] + + fields: \n + - [3:0] = loop_init__clear_stage +*/ +#define VL53L1_SD_CONFIG__RESET_STAGES_LSB 0x0043 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['static_config', 'sigmadelta_config'] + + fields: \n + - [7:4] = accum_reset__clear_stage + - [3:0] = count_reset__clear_stage +*/ +#define VL53L1_GPH_CONFIG__STREAM_COUNT_UPDATE_VALUE 0x0044 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'roi_config'] + + fields: \n + - [7:0] = stream_count_update_value +*/ +#define VL53L1_GLOBAL_CONFIG__STREAM_DIVIDER 0x0045 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'roi_config'] + + fields: \n + - [7:0] = stream_count_internal_div +*/ +#define VL53L1_SYSTEM__INTERRUPT_CONFIG_GPIO 0x0046 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'gph_config'] + + fields: \n + - [1:0] = int_mode_distance + - [3:2] = int_mode_rate + - [4] = int_spare + - [5] = int_new_measure_ready + - [6] = int_no_target_en + - [7] = int_combined_mode +*/ +#define VL53L1_CAL_CONFIG__VCSEL_START 0x0047 +/*!< + type: uint8_t \n + default: 0x0B \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'cal_config'] + + fields: \n + - [6:0] = cal_config__vcsel_start +*/ +#define VL53L1_CAL_CONFIG__REPEAT_RATE 0x0048 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 11 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['general_config', 'cal_config'] + + fields: \n + - [11:0] = cal_config__repeat_rate +*/ +#define VL53L1_CAL_CONFIG__REPEAT_RATE_HI 0x0048 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_CAL_CONFIG__REPEAT_RATE_LO 0x0049 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GLOBAL_CONFIG__VCSEL_WIDTH 0x004A +/*!< + type: uint8_t \n + default: 0x02 \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'global_config'] + + fields: \n + - [6:0] = global_config__vcsel_width +*/ +#define VL53L1_PHASECAL_CONFIG__TIMEOUT_MACROP 0x004B +/*!< + type: uint8_t \n + default: 0x04 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'phasecal_config'] + + fields: \n + - [7:0] = phasecal_config__timeout_macrop +*/ +#define VL53L1_PHASECAL_CONFIG__TARGET 0x004C +/*!< + type: uint8_t \n + default: 0x21 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'phasecal_config'] + + fields: \n + - [7:0] = algo_phasecal_lim +*/ +#define VL53L1_PHASECAL_CONFIG__OVERRIDE 0x004D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'phasecal_config'] + + fields: \n + - [0] = phasecal_config__override +*/ +#define VL53L1_DSS_CONFIG__ROI_MODE_CONTROL 0x004F +/*!< + type: uint8_t \n + default: 0x01 \n + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'dss_config'] + + fields: \n + - [1:0] = dss_config__input_mode + - [2] = calculate_roi_enable +*/ +#define VL53L1_SYSTEM__THRESH_RATE_HIGH 0x0050 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['general_config', 'gph_config'] + + fields: \n + - [15:0] = thresh_rate_high (fixed point 9.7) +*/ +#define VL53L1_SYSTEM__THRESH_RATE_HIGH_HI 0x0050 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SYSTEM__THRESH_RATE_HIGH_LO 0x0051 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SYSTEM__THRESH_RATE_LOW 0x0052 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['general_config', 'gph_config'] + + fields: \n + - [15:0] = thresh_rate_low (fixed point 9.7) +*/ +#define VL53L1_SYSTEM__THRESH_RATE_LOW_HI 0x0052 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SYSTEM__THRESH_RATE_LOW_LO 0x0053 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT 0x0054 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['general_config', 'dss_config'] + + fields: \n + - [15:0] = dss_config__manual_effective_spads_select +*/ +#define VL53L1_DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT_HI 0x0054 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT_LO 0x0055 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_DSS_CONFIG__MANUAL_BLOCK_SELECT 0x0056 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'dss_config'] + + fields: \n + - [7:0] = dss_config__manual_block_select +*/ +#define VL53L1_DSS_CONFIG__APERTURE_ATTENUATION 0x0057 +/*!< + type: uint8_t \n + default: 0x33 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'dss_config'] + + fields: \n + - [7:0] = dss_config__aperture_attenuation +*/ +#define VL53L1_DSS_CONFIG__MAX_SPADS_LIMIT 0x0058 +/*!< + type: uint8_t \n + default: 0xFF \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'dss_config'] + + fields: \n + - [7:0] = dss_config__max_spads_limit +*/ +#define VL53L1_DSS_CONFIG__MIN_SPADS_LIMIT 0x0059 +/*!< + type: uint8_t \n + default: 0x01 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['general_config', 'dss_config'] + + fields: \n + - [7:0] = dss_config__min_spads_limit +*/ +#define VL53L1_MM_CONFIG__TIMEOUT_MACROP_A_HI 0x005A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'mm_config'] + + fields: \n + - [3:0] = mm_config__config_timeout_macrop_a_hi +*/ +#define VL53L1_MM_CONFIG__TIMEOUT_MACROP_A_LO 0x005B +/*!< + type: uint8_t \n + default: 0x06 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'mm_config'] + + fields: \n + - [7:0] = mm_config__config_timeout_macrop_a_lo +*/ +#define VL53L1_MM_CONFIG__TIMEOUT_MACROP_B_HI 0x005C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'mm_config'] + + fields: \n + - [3:0] = mm_config__config_timeout_macrop_b_hi +*/ +#define VL53L1_MM_CONFIG__TIMEOUT_MACROP_B_LO 0x005D +/*!< + type: uint8_t \n + default: 0x06 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'mm_config'] + + fields: \n + - [7:0] = mm_config__config_timeout_macrop_b_lo +*/ +#define VL53L1_RANGE_CONFIG__TIMEOUT_MACROP_A_HI 0x005E +/*!< + type: uint8_t \n + default: 0x01 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'range_config'] + + fields: \n + - [3:0] = range_timeout_overall_periods_macrop_a_hi +*/ +#define VL53L1_RANGE_CONFIG__TIMEOUT_MACROP_A_LO 0x005F +/*!< + type: uint8_t \n + default: 0x92 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'range_config'] + + fields: \n + - [7:0] = range_timeout_overall_periods_macrop_a_lo +*/ +#define VL53L1_RANGE_CONFIG__VCSEL_PERIOD_A 0x0060 +/*!< + type: uint8_t \n + default: 0x0B \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'range_config'] + + fields: \n + - [5:0] = range_config__vcsel_period_a +*/ +#define VL53L1_RANGE_CONFIG__TIMEOUT_MACROP_B_HI 0x0061 +/*!< + type: uint8_t \n + default: 0x01 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'range_config'] + + fields: \n + - [3:0] = range_timeout_overall_periods_macrop_b_hi +*/ +#define VL53L1_RANGE_CONFIG__TIMEOUT_MACROP_B_LO 0x0062 +/*!< + type: uint8_t \n + default: 0x92 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'range_config'] + + fields: \n + - [7:0] = range_timeout_overall_periods_macrop_b_lo +*/ +#define VL53L1_RANGE_CONFIG__VCSEL_PERIOD_B 0x0063 +/*!< + type: uint8_t \n + default: 0x09 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'range_config'] + + fields: \n + - [5:0] = range_config__vcsel_period_b +*/ +#define VL53L1_RANGE_CONFIG__SIGMA_THRESH 0x0064 +/*!< + type: uint16_t \n + default: 0x0080 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['timing_config', 'range_config'] + + fields: \n + - [15:0] = range_config__sigma_thresh (fixed point 14.2) +*/ +#define VL53L1_RANGE_CONFIG__SIGMA_THRESH_HI 0x0064 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGE_CONFIG__SIGMA_THRESH_LO 0x0065 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS 0x0066 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['timing_config', 'range_config'] + + fields: \n + - [15:0] = range_config__min_count_rate_rtn_limit_mcps (fixed point 9.7) +*/ +#define VL53L1_RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS_HI 0x0066 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS_LO 0x0067 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGE_CONFIG__VALID_PHASE_LOW 0x0068 +/*!< + type: uint8_t \n + default: 0x08 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'range_config'] + + fields: \n + - [7:0] = range_config__valid_phase_low (fixed point 5.3) +*/ +#define VL53L1_RANGE_CONFIG__VALID_PHASE_HIGH 0x0069 +/*!< + type: uint8_t \n + default: 0x80 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'range_config'] + + fields: \n + - [7:0] = range_config__valid_phase_high (fixed point 5.3) +*/ +#define VL53L1_SYSTEM__INTERMEASUREMENT_PERIOD 0x006C +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['timing_config', 'system_config'] + + fields: \n + - [31:0] = intermeasurement_period +*/ +#define VL53L1_SYSTEM__INTERMEASUREMENT_PERIOD_3 0x006C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SYSTEM__INTERMEASUREMENT_PERIOD_2 0x006D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SYSTEM__INTERMEASUREMENT_PERIOD_1 0x006E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SYSTEM__INTERMEASUREMENT_PERIOD_0 0x006F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SYSTEM__FRACTIONAL_ENABLE 0x0070 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['timing_config', 'system_config'] + + fields: \n + - [0] = range_fractional_enable +*/ +#define VL53L1_SYSTEM__GROUPED_PARAMETER_HOLD_0 0x0071 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [0] = grouped_parameter_hold + - [1] = grouped_parameter_hold_id +*/ +#define VL53L1_SYSTEM__THRESH_HIGH 0x0072 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [15:0] = thresh_high +*/ +#define VL53L1_SYSTEM__THRESH_HIGH_HI 0x0072 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SYSTEM__THRESH_HIGH_LO 0x0073 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SYSTEM__THRESH_LOW 0x0074 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [15:0] = thresh_low +*/ +#define VL53L1_SYSTEM__THRESH_LOW_HI 0x0074 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SYSTEM__THRESH_LOW_LO 0x0075 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SYSTEM__ENABLE_XTALK_PER_QUADRANT 0x0076 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [0] = system__enable_xtalk_per_quadrant +*/ +#define VL53L1_SYSTEM__SEED_CONFIG 0x0077 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [1:0] = system__seed_config + - [2] = system__fw_pause_ctrl +*/ +#define VL53L1_SD_CONFIG__WOI_SD0 0x0078 +/*!< + type: uint8_t \n + default: 0x04 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [7:0] = sd_config__woi_sd0 +*/ +#define VL53L1_SD_CONFIG__WOI_SD1 0x0079 +/*!< + type: uint8_t \n + default: 0x04 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [7:0] = sd_config__woi_sd1 +*/ +#define VL53L1_SD_CONFIG__INITIAL_PHASE_SD0 0x007A +/*!< + type: uint8_t \n + default: 0x03 \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [6:0] = sd_config__initial_phase_sd0 +*/ +#define VL53L1_SD_CONFIG__INITIAL_PHASE_SD1 0x007B +/*!< + type: uint8_t \n + default: 0x03 \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [6:0] = sd_config__initial_phase_sd1 +*/ +#define VL53L1_SYSTEM__GROUPED_PARAMETER_HOLD_1 0x007C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [0] = grouped_parameter_hold + - [1] = grouped_parameter_hold_id +*/ +#define VL53L1_SD_CONFIG__FIRST_ORDER_SELECT 0x007D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [0] = sd_config__first_order_select_rtn + - [1] = sd_config__first_order_select_ref +*/ +#define VL53L1_SD_CONFIG__QUANTIFIER 0x007E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [3:0] = sd_config__quantifier +*/ +#define VL53L1_ROI_CONFIG__USER_ROI_CENTRE_SPAD 0x007F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [7:0] = user_roi_center_spad +*/ +#define VL53L1_ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE 0x0080 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [7:0] = roi_config__user_roi_requested_global_xy_size +*/ +#define VL53L1_SYSTEM__SEQUENCE_CONFIG 0x0081 +/*!< + type: uint8_t \n + default: 0xFF \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [0] = sequence_vhv_en + - [1] = sequence_phasecal_en + - [2] = sequence_reference_phase_en + - [3] = sequence_dss1_en + - [4] = sequence_dss2_en + - [5] = sequence_mm1_en + - [6] = sequence_mm2_en + - [7] = sequence_range_en +*/ +#define VL53L1_SYSTEM__GROUPED_PARAMETER_HOLD 0x0082 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['dynamic_config', 'gph_config'] + + fields: \n + - [0] = grouped_parameter_hold + - [1] = grouped_parameter_hold_id +*/ +#define VL53L1_POWER_MANAGEMENT__GO1_POWER_FORCE 0x0083 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['system_control', 'pwrman_ctrl'] + + fields: \n + - [0] = go1_dig_powerforce +*/ +#define VL53L1_SYSTEM__STREAM_COUNT_CTRL 0x0084 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['system_control', 'stream_ctrl'] + + fields: \n + - [0] = retain_stream_count +*/ +#define VL53L1_FIRMWARE__ENABLE 0x0085 +/*!< + type: uint8_t \n + default: 0x01 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['system_control', 'firmware_ctrl'] + + fields: \n + - [0] = firmware_enable +*/ +#define VL53L1_SYSTEM__INTERRUPT_CLEAR 0x0086 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['system_control', 'system_int_clr'] + + fields: \n + - [0] = sys_interrupt_clear_range + - [1] = sys_interrupt_clear_error +*/ +#define VL53L1_SYSTEM__MODE_START 0x0087 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['system_control', 'system_start'] + + fields: \n + - [1:0] = scheduler_mode + - [3:2] = readout_mode + - [4] = mode_range__single_shot + - [5] = mode_range__back_to_back + - [6] = mode_range__timed + - [7] = mode_range__abort +*/ +#define VL53L1_RESULT__INTERRUPT_STATUS 0x0088 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [2:0] = int_status + - [4:3] = int_error_status + - [5] = gph_id_gpio_status +*/ +#define VL53L1_RESULT__RANGE_STATUS 0x0089 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [4:0] = range_status + - [5] = max_threshold_hit + - [6] = min_threshold_hit + - [7] = gph_id_range_status +*/ +#define VL53L1_RESULT__REPORT_STATUS 0x008A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [3:0] = report_status +*/ +#define VL53L1_RESULT__STREAM_COUNT 0x008B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [7:0] = result__stream_count +*/ +#define VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 0x008C +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__dss_actual_effective_spads_sd0 (fixed point 8.8) +*/ +#define VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x008C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x008D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0 0x008E +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__peak_signal_count_rate_mcps_sd0 (fixed point 9.7) +*/ +#define VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_HI 0x008E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_LO 0x008F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0 0x0090 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__ambient_count_rate_mcps_sd0 (fixed point 9.7) +*/ +#define VL53L1_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_HI 0x0090 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_LO 0x0091 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__SIGMA_SD0 0x0092 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__sigma_sd0 (fixed point 14.2) +*/ +#define VL53L1_RESULT__SIGMA_SD0_HI 0x0092 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__SIGMA_SD0_LO 0x0093 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__PHASE_SD0 0x0094 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__phase_sd0 (fixed point 5.11) +*/ +#define VL53L1_RESULT__PHASE_SD0_HI 0x0094 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__PHASE_SD0_LO 0x0095 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 0x0096 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__final_crosstalk_corrected_range_mm_sd0 +*/ +#define VL53L1_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_HI 0x0096 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_LO 0x0097 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 0x0098 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 (fixed point 9.7) +*/ +#define VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_HI 0x0098 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_LO 0x0099 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0 0x009A +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__mm_inner_actual_effective_spads_sd0 (fixed point 8.8) +*/ +#define VL53L1_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x009A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x009B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0 0x009C +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__mm_outer_actual_effective_spads_sd0 (fixed point 8.8) +*/ +#define VL53L1_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x009C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x009D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0 0x009E +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__avg_signal_count_rate_mcps_sd0 (fixed point 9.7) +*/ +#define VL53L1_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_HI 0x009E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_LO 0x009F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1 0x00A0 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__dss_actual_effective_spads_sd1 (fixed point 8.8) +*/ +#define VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_HI 0x00A0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_LO 0x00A1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1 0x00A2 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__peak_signal_count_rate_mcps_sd1 (fixed point 9.7) +*/ +#define VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_HI 0x00A2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_LO 0x00A3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1 0x00A4 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__ambient_count_rate_mcps_sd1 (fixed point 9.7) +*/ +#define VL53L1_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_HI 0x00A4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_LO 0x00A5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__SIGMA_SD1 0x00A6 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__sigma_sd1 (fixed point 14.2) +*/ +#define VL53L1_RESULT__SIGMA_SD1_HI 0x00A6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__SIGMA_SD1_LO 0x00A7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__PHASE_SD1 0x00A8 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__phase_sd1 (fixed point 5.11) +*/ +#define VL53L1_RESULT__PHASE_SD1_HI 0x00A8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__PHASE_SD1_LO 0x00A9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1 0x00AA +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__final_crosstalk_corrected_range_mm_sd1 +*/ +#define VL53L1_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_HI 0x00AA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_LO 0x00AB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__SPARE_0_SD1 0x00AC +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__spare_0_sd1 +*/ +#define VL53L1_RESULT__SPARE_0_SD1_HI 0x00AC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__SPARE_0_SD1_LO 0x00AD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__SPARE_1_SD1 0x00AE +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__spare_1_sd1 +*/ +#define VL53L1_RESULT__SPARE_1_SD1_HI 0x00AE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__SPARE_1_SD1_LO 0x00AF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__SPARE_2_SD1 0x00B0 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [15:0] = result__spare_2_sd1 +*/ +#define VL53L1_RESULT__SPARE_2_SD1_HI 0x00B0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__SPARE_2_SD1_LO 0x00B1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__SPARE_3_SD1 0x00B2 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [7:0] = result__spare_3_sd1 +*/ +#define VL53L1_RESULT__THRESH_INFO 0x00B3 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['system_results', 'results'] + + fields: \n + - [3:0] = result__distance_int_info + - [7:4] = result__rate_int_info +*/ +#define VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 0x00B4 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = result_core__ambient_window_events_sd0 +*/ +#define VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_3 0x00B4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_2 0x00B5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_1 0x00B6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_0 0x00B7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0 0x00B8 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = result_core__ranging_total_events_sd0 +*/ +#define VL53L1_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_3 0x00B8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_2 0x00B9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_1 0x00BA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_0 0x00BB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0 0x00BC +/*!< + type: int32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = result_core__signal_total_events_sd0 +*/ +#define VL53L1_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_3 0x00BC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_2 0x00BD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_1 0x00BE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_0 0x00BF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0 0x00C0 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = result_core__total_periods_elapsed_sd0 +*/ +#define VL53L1_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_3 0x00C0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_2 0x00C1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_1 0x00C2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_0 0x00C3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1 0x00C4 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = result_core__ambient_window_events_sd1 +*/ +#define VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_3 0x00C4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_2 0x00C5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_1 0x00C6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_0 0x00C7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1 0x00C8 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = result_core__ranging_total_events_sd1 +*/ +#define VL53L1_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_3 0x00C8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_2 0x00C9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_1 0x00CA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_0 0x00CB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1 0x00CC +/*!< + type: int32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = result_core__signal_total_events_sd1 +*/ +#define VL53L1_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_3 0x00CC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_2 0x00CD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_1 0x00CE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_0 0x00CF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1 0x00D0 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = result_core__total_periods_elapsed_sd1 +*/ +#define VL53L1_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_3 0x00D0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_2 0x00D1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_1 0x00D2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_0 0x00D3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT_CORE__SPARE_0 0x00D4 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['core_results', 'ranging_core_results'] + + fields: \n + - [7:0] = result_core__spare_0 +*/ +#define VL53L1_PHASECAL_RESULT__REFERENCE_PHASE 0x00D6 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['debug_results', 'phasecal_results'] + + fields: \n + - [15:0] = result_phasecal__reference_phase (fixed point 5.11) +*/ +#define VL53L1_PHASECAL_RESULT__REFERENCE_PHASE_HI 0x00D6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PHASECAL_RESULT__REFERENCE_PHASE_LO 0x00D7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PHASECAL_RESULT__VCSEL_START 0x00D8 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'phasecal_results'] + + fields: \n + - [6:0] = result_phasecal__vcsel_start +*/ +#define VL53L1_REF_SPAD_CHAR_RESULT__NUM_ACTUAL_REF_SPADS 0x00D9 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'ref_spad_status'] + + fields: \n + - [5:0] = ref_spad_char_result__num_actual_ref_spads +*/ +#define VL53L1_REF_SPAD_CHAR_RESULT__REF_LOCATION 0x00DA +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'ref_spad_status'] + + fields: \n + - [1:0] = ref_spad_char_result__ref_location +*/ +#define VL53L1_VHV_RESULT__COLDBOOT_STATUS 0x00DB +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'vhv_results'] + + fields: \n + - [0] = vhv_result__coldboot_status +*/ +#define VL53L1_VHV_RESULT__SEARCH_RESULT 0x00DC +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'vhv_results'] + + fields: \n + - [5:0] = cp_sel_result +*/ +#define VL53L1_VHV_RESULT__LATEST_SETTING 0x00DD +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'vhv_results'] + + fields: \n + - [5:0] = cp_sel_latest_setting +*/ +#define VL53L1_RESULT__OSC_CALIBRATE_VAL 0x00DE +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 9 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['debug_results', 'misc_results'] + + fields: \n + - [9:0] = osc_calibrate_val +*/ +#define VL53L1_RESULT__OSC_CALIBRATE_VAL_HI 0x00DE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RESULT__OSC_CALIBRATE_VAL_LO 0x00DF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_ANA_CONFIG__POWERDOWN_GO1 0x00E0 +/*!< + type: uint8_t \n + default: 0x02 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'analog_config'] + + fields: \n + - [0] = go2_ref_bg_disable_avdd + - [1] = go2_regdvdd1v2_enable_avdd +*/ +#define VL53L1_ANA_CONFIG__REF_BG_CTRL 0x00E1 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'analog_config'] + + fields: \n + - [0] = go2_ref_overdrvbg_avdd + - [1] = go2_ref_forcebgison_avdd +*/ +#define VL53L1_ANA_CONFIG__REGDVDD1V2_CTRL 0x00E2 +/*!< + type: uint8_t \n + default: 0x01 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'analog_config'] + + fields: \n + - [0] = go2_regdvdd1v2_sel_pulldown_avdd + - [1] = go2_regdvdd1v2_sel_boost_avdd + - [3:2] = go2_regdvdd1v2_selv_avdd +*/ +#define VL53L1_ANA_CONFIG__OSC_SLOW_CTRL 0x00E3 +/*!< + type: uint8_t \n + default: 0x02 \n + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'analog_config'] + + fields: \n + - [0] = osc_slow_en + - [1] = osc_slow_op_en + - [2] = osc_slow_freq_sel +*/ +#define VL53L1_TEST_MODE__STATUS 0x00E4 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'test_mode_status'] + + fields: \n + - [0] = test_mode_status +*/ +#define VL53L1_FIRMWARE__SYSTEM_STATUS 0x00E5 +/*!< + type: uint8_t \n + default: 0x02 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'firmware_status'] + + fields: \n + - [0] = firmware_bootup + - [1] = firmware_first_range +*/ +#define VL53L1_FIRMWARE__MODE_STATUS 0x00E6 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'firmware_status'] + + fields: \n + - [7:0] = firmware_mode_status +*/ +#define VL53L1_FIRMWARE__SECONDARY_MODE_STATUS 0x00E7 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'firmware_status'] + + fields: \n + - [7:0] = fw_secondary_mode_status +*/ +#define VL53L1_FIRMWARE__CAL_REPEAT_RATE_COUNTER 0x00E8 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 11 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['debug_results', 'firmware_status'] + + fields: \n + - [11:0] = firmware_cal_repeat_rate +*/ +#define VL53L1_FIRMWARE__CAL_REPEAT_RATE_COUNTER_HI 0x00E8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_FIRMWARE__CAL_REPEAT_RATE_COUNTER_LO 0x00E9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_FIRMWARE__HISTOGRAM_BIN 0x00EA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__SYSTEM__THRESH_HIGH 0x00EC +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [15:0] = shadow_thresh_high +*/ +#define VL53L1_GPH__SYSTEM__THRESH_HIGH_HI 0x00EC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__SYSTEM__THRESH_HIGH_LO 0x00ED +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__SYSTEM__THRESH_LOW 0x00EE +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [15:0] = shadow_thresh_low +*/ +#define VL53L1_GPH__SYSTEM__THRESH_LOW_HI 0x00EE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__SYSTEM__THRESH_LOW_LO 0x00EF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__SYSTEM__ENABLE_XTALK_PER_QUADRANT 0x00F0 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [0] = shadow__enable_xtalk_per_quadrant +*/ +#define VL53L1_GPH__SPARE_0 0x00F1 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [0] = fw_safe_to_disable + - [1] = shadow__spare_0 + - [2] = shadow__spare_1 +*/ +#define VL53L1_GPH__SD_CONFIG__WOI_SD0 0x00F2 +/*!< + type: uint8_t \n + default: 0x04 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [7:0] = shadow_sd_config__woi_sd0 +*/ +#define VL53L1_GPH__SD_CONFIG__WOI_SD1 0x00F3 +/*!< + type: uint8_t \n + default: 0x04 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [7:0] = shadow_sd_config__woi_sd1 +*/ +#define VL53L1_GPH__SD_CONFIG__INITIAL_PHASE_SD0 0x00F4 +/*!< + type: uint8_t \n + default: 0x03 \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [6:0] = shadow_sd_config__initial_phase_sd0 +*/ +#define VL53L1_GPH__SD_CONFIG__INITIAL_PHASE_SD1 0x00F5 +/*!< + type: uint8_t \n + default: 0x03 \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [6:0] = shadow_sd_config__initial_phase_sd1 +*/ +#define VL53L1_GPH__SD_CONFIG__FIRST_ORDER_SELECT 0x00F6 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [0] = shadow_sd_config__first_order_select_rtn + - [1] = shadow_sd_config__first_order_select_ref +*/ +#define VL53L1_GPH__SD_CONFIG__QUANTIFIER 0x00F7 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [3:0] = shadow_sd_config__quantifier +*/ +#define VL53L1_GPH__ROI_CONFIG__USER_ROI_CENTRE_SPAD 0x00F8 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [7:0] = shadow_user_roi_center_spad_q0 +*/ +#define VL53L1_GPH__ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE 0x00F9 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [7:0] = shadow_user_roi_requested_global_xy_size +*/ +#define VL53L1_GPH__SYSTEM__SEQUENCE_CONFIG 0x00FA +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [0] = shadow_sequence_vhv_en + - [1] = shadow_sequence_phasecal_en + - [2] = shadow_sequence_reference_phase_en + - [3] = shadow_sequence_dss1_en + - [4] = shadow_sequence_dss2_en + - [5] = shadow_sequence_mm1_en + - [6] = shadow_sequence_mm2_en + - [7] = shadow_sequence_range_en +*/ +#define VL53L1_GPH__GPH_ID 0x00FB +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'gph_actual'] + + fields: \n + - [0] = shadow_gph_id +*/ +#define VL53L1_SYSTEM__INTERRUPT_SET 0x00FC +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'system_int_set'] + + fields: \n + - [0] = sys_interrupt_set_range + - [1] = sys_interrupt_set_error +*/ +#define VL53L1_INTERRUPT_MANAGER__ENABLES 0x00FD +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'interrupt_manager'] + + fields: \n + - [0] = interrupt_enable__single_shot + - [1] = interrupt_enable__back_to_back + - [2] = interrupt_enable__timed + - [3] = interrupt_enable__abort + - [4] = interrupt_enable__test +*/ +#define VL53L1_INTERRUPT_MANAGER__CLEAR 0x00FE +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'interrupt_manager'] + + fields: \n + - [0] = interrupt_clear__single_shot + - [1] = interrupt_clear__back_to_back + - [2] = interrupt_clear__timed + - [3] = interrupt_clear__abort + - [4] = interrupt_clear__test +*/ +#define VL53L1_INTERRUPT_MANAGER__STATUS 0x00FF +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'interrupt_manager'] + + fields: \n + - [0] = interrupt_status__single_shot + - [1] = interrupt_status__back_to_back + - [2] = interrupt_status__timed + - [3] = interrupt_status__abort + - [4] = interrupt_status__test +*/ +#define VL53L1_MCU_TO_HOST_BANK__WR_ACCESS_EN 0x0100 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'host_bank_ctrl'] + + fields: \n + - [0] = mcu_to_host_bank_wr_en +*/ +#define VL53L1_POWER_MANAGEMENT__GO1_RESET_STATUS 0x0101 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'power_man_status'] + + fields: \n + - [0] = go1_status +*/ +#define VL53L1_PAD_STARTUP_MODE__VALUE_RO 0x0102 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'pad_config'] + + fields: \n + - [0] = pad_atest1_val_ro + - [1] = pad_atest2_val_ro +*/ +#define VL53L1_PAD_STARTUP_MODE__VALUE_CTRL 0x0103 +/*!< + type: uint8_t \n + default: 0x30 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'pad_config'] + + fields: \n + - [0] = pad_atest1_val + - [1] = pad_atest2_val + - [4] = pad_atest1_dig_enable + - [5] = pad_atest2_dig_enable +*/ +#define VL53L1_PLL_PERIOD_US 0x0104 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 17 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['debug_results', 'pll_config'] + + fields: \n + - [17:0] = pll_period_us (fixed point 0.24) +*/ +#define VL53L1_PLL_PERIOD_US_3 0x0104 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PLL_PERIOD_US_2 0x0105 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PLL_PERIOD_US_1 0x0106 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PLL_PERIOD_US_0 0x0107 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_INTERRUPT_SCHEDULER__DATA_OUT 0x0108 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['debug_results', 'debug_timer'] + + fields: \n + - [31:0] = interrupt_scheduler_data_out +*/ +#define VL53L1_INTERRUPT_SCHEDULER__DATA_OUT_3 0x0108 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_INTERRUPT_SCHEDULER__DATA_OUT_2 0x0109 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_INTERRUPT_SCHEDULER__DATA_OUT_1 0x010A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_INTERRUPT_SCHEDULER__DATA_OUT_0 0x010B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_NVM_BIST__COMPLETE 0x010C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'nvm_bist_status'] + + fields: \n + - [0] = nvm_bist__complete +*/ +#define VL53L1_NVM_BIST__STATUS 0x010D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['debug_results', 'nvm_bist_status'] + + fields: \n + - [0] = nvm_bist__status +*/ +#define VL53L1_IDENTIFICATION__MODEL_ID 0x010F +/*!< + type: uint8_t \n + default: 0xEA \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'identification'] + + fields: \n + - [7:0] = model_id +*/ +#define VL53L1_IDENTIFICATION__MODULE_TYPE 0x0110 +/*!< + type: uint8_t \n + default: 0xAA \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'identification'] + + fields: \n + - [7:0] = module_type +*/ +#define VL53L1_IDENTIFICATION__REVISION_ID 0x0111 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'identification'] + + fields: \n + - [3:0] = nvm_revision_id + - [7:4] = mask_revision_id +*/ +#define VL53L1_IDENTIFICATION__MODULE_ID 0x0112 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['nvm_copy_data', 'identification'] + + fields: \n + - [15:0] = module_id +*/ +#define VL53L1_IDENTIFICATION__MODULE_ID_HI 0x0112 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_IDENTIFICATION__MODULE_ID_LO 0x0113 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_ANA_CONFIG__FAST_OSC__TRIM_MAX 0x0114 +/*!< + type: uint8_t \n + default: OSC_TRIM_DEFAULT \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'analog_config'] + + fields: \n + - [6:0] = osc_trim_max +*/ +#define VL53L1_ANA_CONFIG__FAST_OSC__FREQ_SET 0x0115 +/*!< + type: uint8_t \n + default: OSC_FREQ_SET_DEFAULT \n + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'analog_config'] + + fields: \n + - [2:0] = osc_freq_set +*/ +#define VL53L1_ANA_CONFIG__VCSEL_TRIM 0x0116 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'analog_config'] + + fields: \n + - [2:0] = vcsel_trim +*/ +#define VL53L1_ANA_CONFIG__VCSEL_SELION 0x0117 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'analog_config'] + + fields: \n + - [5:0] = vcsel_selion +*/ +#define VL53L1_ANA_CONFIG__VCSEL_SELION_MAX 0x0118 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'analog_config'] + + fields: \n + - [5:0] = vcsel_selion_max +*/ +#define VL53L1_PROTECTED_LASER_SAFETY__LOCK_BIT 0x0119 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'laser_safety'] + + fields: \n + - [0] = laser_safety__lock_bit +*/ +#define VL53L1_LASER_SAFETY__KEY 0x011A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'laser_safety'] + + fields: \n + - [6:0] = laser_safety__key +*/ +#define VL53L1_LASER_SAFETY__KEY_RO 0x011B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'laser_safety'] + + fields: \n + - [0] = laser_safety__key_ro +*/ +#define VL53L1_LASER_SAFETY__CLIP 0x011C +/*!< + type: uint8_t \n + default: 0x02 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'laser_safety'] + + fields: \n + - [5:0] = vcsel_pulse_width_clip +*/ +#define VL53L1_LASER_SAFETY__MULT 0x011D +/*!< + type: uint8_t \n + default: 0x32 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'laser_safety'] + + fields: \n + - [5:0] = vcsel_pulse_width_mult +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_0 0x011E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_0 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_1 0x011F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_1 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_2 0x0120 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_2 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_3 0x0121 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_3 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_4 0x0122 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_4 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_5 0x0123 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_5 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_6 0x0124 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_6 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_7 0x0125 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_7 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_8 0x0126 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_8 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_9 0x0127 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_9 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_10 0x0128 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_10 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_11 0x0129 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_11 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_12 0x012A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_12 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_13 0x012B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_13 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_14 0x012C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_14 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_15 0x012D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_15 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_16 0x012E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_16 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_17 0x012F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_17 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_18 0x0130 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_18 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_19 0x0131 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_19 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_20 0x0132 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_20 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_21 0x0133 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_21 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_22 0x0134 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_22 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_23 0x0135 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_23 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_24 0x0136 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_24 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_25 0x0137 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_25 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_26 0x0138 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_26 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_27 0x0139 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_27 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_28 0x013A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_28 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_29 0x013B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_29 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_30 0x013C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_30 +*/ +#define VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_RTN_31 0x013D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'ret_spad_config'] + + fields: \n + - [7:0] = spad_enables_rtn_31 +*/ +#define VL53L1_ROI_CONFIG__MODE_ROI_CENTRE_SPAD 0x013E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'roi_config'] + + fields: \n + - [7:0] = mode_roi_center_spad +*/ +#define VL53L1_ROI_CONFIG__MODE_ROI_XY_SIZE 0x013F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['nvm_copy_data', 'roi_config'] + + fields: \n + - [7:0] = mode_roi_xy_size +*/ +#define VL53L1_GO2_HOST_BANK_ACCESS__OVERRIDE 0x0300 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__MULTIPLICAND 0x0400 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__MULTIPLICAND_3 0x0400 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__MULTIPLICAND_2 0x0401 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__MULTIPLICAND_1 0x0402 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__MULTIPLICAND_0 0x0403 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__MULTIPLIER 0x0404 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__MULTIPLIER_3 0x0404 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__MULTIPLIER_2 0x0405 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__MULTIPLIER_1 0x0406 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__MULTIPLIER_0 0x0407 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__PRODUCT_HI 0x0408 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__PRODUCT_HI_3 0x0408 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__PRODUCT_HI_2 0x0409 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__PRODUCT_HI_1 0x040A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__PRODUCT_HI_0 0x040B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__PRODUCT_LO 0x040C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__PRODUCT_LO_3 0x040C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__PRODUCT_LO_2 0x040D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__PRODUCT_LO_1 0x040E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__PRODUCT_LO_0 0x040F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__START 0x0410 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_MULTIPLIER__STATUS 0x0411 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__START 0x0412 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__STATUS 0x0413 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__DIVIDEND 0x0414 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__DIVIDEND_3 0x0414 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__DIVIDEND_2 0x0415 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__DIVIDEND_1 0x0416 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__DIVIDEND_0 0x0417 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__DIVISOR 0x0418 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__DIVISOR_3 0x0418 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__DIVISOR_2 0x0419 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__DIVISOR_1 0x041A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__DIVISOR_0 0x041B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__QUOTIENT 0x041C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__QUOTIENT_3 0x041C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__QUOTIENT_2 0x041D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__QUOTIENT_1 0x041E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_UTIL_DIVIDER__QUOTIENT_0 0x041F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TIMER0__VALUE_IN 0x0420 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TIMER0__VALUE_IN_3 0x0420 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TIMER0__VALUE_IN_2 0x0421 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TIMER0__VALUE_IN_1 0x0422 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TIMER0__VALUE_IN_0 0x0423 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TIMER1__VALUE_IN 0x0424 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TIMER1__VALUE_IN_3 0x0424 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TIMER1__VALUE_IN_2 0x0425 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TIMER1__VALUE_IN_1 0x0426 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TIMER1__VALUE_IN_0 0x0427 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TIMER0__CTRL 0x0428 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TIMER1__CTRL 0x0429 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_GENERAL_PURPOSE__GP_0 0x042C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = mcu_gp_0 +*/ +#define VL53L1_MCU_GENERAL_PURPOSE__GP_1 0x042D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = mcu_gp_1 +*/ +#define VL53L1_MCU_GENERAL_PURPOSE__GP_2 0x042E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = mcu_gp_2 +*/ +#define VL53L1_MCU_GENERAL_PURPOSE__GP_3 0x042F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = mcu_gp_3 +*/ +#define VL53L1_MCU_RANGE_CALC__CONFIG 0x0430 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [0] = fw_calc__sigma_delta_sel + - [2] = fw_calc__phase_output_en + - [3] = fw_calc__peak_signal_rate_en + - [4] = fw_calc__ambient_rate_en + - [5] = fw_calc__total_rate_per_spad_en + - [6] = fw_calc__snr_avg_signal_rate_en + - [7] = fw_calc__sigma_en +*/ +#define VL53L1_MCU_RANGE_CALC__OFFSET_CORRECTED_RANGE 0x0432 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + [''] + + fields: \n + - [15:0] = offset_corrected_range +*/ +#define VL53L1_MCU_RANGE_CALC__OFFSET_CORRECTED_RANGE_HI 0x0432 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__OFFSET_CORRECTED_RANGE_LO 0x0433 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_4 0x0434 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 16 + - lsb = 0 + - i2c_size = 4 + + groups: \n + [''] + + fields: \n + - [16:0] = mcu_calc__spare_4 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_4_3 0x0434 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_4_2 0x0435 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_4_1 0x0436 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_4_0 0x0437 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__AMBIENT_DURATION_PRE_CALC 0x0438 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 13 + - lsb = 0 + - i2c_size = 2 + + groups: \n + [''] + + fields: \n + - [13:0] = ambient_duration_prec_calc +*/ +#define VL53L1_MCU_RANGE_CALC__AMBIENT_DURATION_PRE_CALC_HI 0x0438 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__AMBIENT_DURATION_PRE_CALC_LO 0x0439 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_VCSEL_PERIOD 0x043C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = algo_vcsel_period +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_5 0x043D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = mcu_calc__spare_5 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_TOTAL_PERIODS 0x043E +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + [''] + + fields: \n + - [15:0] = algo_total_periods +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_TOTAL_PERIODS_HI 0x043E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_TOTAL_PERIODS_LO 0x043F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_ACCUM_PHASE 0x0440 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + [''] + + fields: \n + - [31:0] = algo_accum_phase +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_ACCUM_PHASE_3 0x0440 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_ACCUM_PHASE_2 0x0441 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_ACCUM_PHASE_1 0x0442 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_ACCUM_PHASE_0 0x0443 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS 0x0444 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + [''] + + fields: \n + - [31:0] = algo_signal_events +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS_3 0x0444 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS_2 0x0445 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS_1 0x0446 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS_0 0x0447 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS 0x0448 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + [''] + + fields: \n + - [31:0] = algo_ambient_events +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS_3 0x0448 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS_2 0x0449 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS_1 0x044A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS_0 0x044B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_6 0x044C +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + [''] + + fields: \n + - [15:0] = mcu_calc__spare_6 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_6_HI 0x044C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_6_LO 0x044D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_ADJUST_VCSEL_PERIOD 0x044E +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + [''] + + fields: \n + - [15:0] = algo_adjust_vcsel_period +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_ADJUST_VCSEL_PERIOD_HI 0x044E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__ALGO_ADJUST_VCSEL_PERIOD_LO 0x044F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__NUM_SPADS 0x0450 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + [''] + + fields: \n + - [15:0] = num_spads +*/ +#define VL53L1_MCU_RANGE_CALC__NUM_SPADS_HI 0x0450 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__NUM_SPADS_LO 0x0451 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__PHASE_OUTPUT 0x0452 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + [''] + + fields: \n + - [15:0] = phase_output +*/ +#define VL53L1_MCU_RANGE_CALC__PHASE_OUTPUT_HI 0x0452 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__PHASE_OUTPUT_LO 0x0453 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__RATE_PER_SPAD_MCPS 0x0454 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 19 + - lsb = 0 + - i2c_size = 4 + + groups: \n + [''] + + fields: \n + - [19:0] = rate_per_spad_mcps +*/ +#define VL53L1_MCU_RANGE_CALC__RATE_PER_SPAD_MCPS_3 0x0454 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__RATE_PER_SPAD_MCPS_2 0x0455 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__RATE_PER_SPAD_MCPS_1 0x0456 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__RATE_PER_SPAD_MCPS_0 0x0457 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_7 0x0458 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = mcu_calc__spare_7 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_8 0x0459 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = mcu_calc__spare_8 +*/ +#define VL53L1_MCU_RANGE_CALC__PEAK_SIGNAL_RATE_MCPS 0x045A +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + [''] + + fields: \n + - [15:0] = peak_signal_rate +*/ +#define VL53L1_MCU_RANGE_CALC__PEAK_SIGNAL_RATE_MCPS_HI 0x045A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__PEAK_SIGNAL_RATE_MCPS_LO 0x045B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__AVG_SIGNAL_RATE_MCPS 0x045C +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + [''] + + fields: \n + - [15:0] = avg_signal_rate +*/ +#define VL53L1_MCU_RANGE_CALC__AVG_SIGNAL_RATE_MCPS_HI 0x045C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__AVG_SIGNAL_RATE_MCPS_LO 0x045D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__AMBIENT_RATE_MCPS 0x045E +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + [''] + + fields: \n + - [15:0] = ambient_rate +*/ +#define VL53L1_MCU_RANGE_CALC__AMBIENT_RATE_MCPS_HI 0x045E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__AMBIENT_RATE_MCPS_LO 0x045F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__XTALK 0x0460 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + [''] + + fields: \n + - [15:0] = crosstalk (fixed point 9.7) +*/ +#define VL53L1_MCU_RANGE_CALC__XTALK_HI 0x0460 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__XTALK_LO 0x0461 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__CALC_STATUS 0x0462 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = calc_status +*/ +#define VL53L1_MCU_RANGE_CALC__DEBUG 0x0463 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [0] = calc_debug__divide_by_zero +*/ +#define VL53L1_MCU_RANGE_CALC__PEAK_SIGNAL_RATE_XTALK_CORR_MCPS 0x0464 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + [''] + + fields: \n + - [15:0] = peak_signal_rate_xtalk_corr +*/ +#define VL53L1_MCU_RANGE_CALC__PEAK_SIGNAL_RATE_XTALK_CORR_MCPS_HI 0x0464 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__PEAK_SIGNAL_RATE_XTALK_CORR_MCPS_LO 0x0465 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_0 0x0468 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = mcu_calc__spare_0 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_1 0x0469 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = mcu_calc__spare_1 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_2 0x046A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = mcu_calc__spare_2 +*/ +#define VL53L1_MCU_RANGE_CALC__SPARE_3 0x046B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [7:0] = mcu_calc__spare_3 +*/ +#define VL53L1_PATCH__CTRL 0x0470 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__JMP_ENABLES 0x0472 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__JMP_ENABLES_HI 0x0472 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__JMP_ENABLES_LO 0x0473 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__DATA_ENABLES 0x0474 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__DATA_ENABLES_HI 0x0474 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__DATA_ENABLES_LO 0x0475 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_0 0x0476 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_0_HI 0x0476 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_0_LO 0x0477 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_1 0x0478 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_1_HI 0x0478 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_1_LO 0x0479 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_2 0x047A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_2_HI 0x047A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_2_LO 0x047B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_3 0x047C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_3_HI 0x047C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_3_LO 0x047D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_4 0x047E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_4_HI 0x047E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_4_LO 0x047F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_5 0x0480 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_5_HI 0x0480 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_5_LO 0x0481 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_6 0x0482 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_6_HI 0x0482 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_6_LO 0x0483 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_7 0x0484 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_7_HI 0x0484 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_7_LO 0x0485 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_8 0x0486 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_8_HI 0x0486 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_8_LO 0x0487 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_9 0x0488 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_9_HI 0x0488 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_9_LO 0x0489 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_10 0x048A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_10_HI 0x048A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_10_LO 0x048B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_11 0x048C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_11_HI 0x048C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_11_LO 0x048D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_12 0x048E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_12_HI 0x048E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_12_LO 0x048F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_13 0x0490 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_13_HI 0x0490 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_13_LO 0x0491 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_14 0x0492 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_14_HI 0x0492 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_14_LO 0x0493 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_15 0x0494 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_15_HI 0x0494 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__OFFSET_15_LO 0x0495 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_0 0x0496 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_0_HI 0x0496 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_0_LO 0x0497 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_1 0x0498 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_1_HI 0x0498 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_1_LO 0x0499 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_2 0x049A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_2_HI 0x049A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_2_LO 0x049B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_3 0x049C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_3_HI 0x049C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_3_LO 0x049D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_4 0x049E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_4_HI 0x049E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_4_LO 0x049F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_5 0x04A0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_5_HI 0x04A0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_5_LO 0x04A1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_6 0x04A2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_6_HI 0x04A2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_6_LO 0x04A3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_7 0x04A4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_7_HI 0x04A4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_7_LO 0x04A5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_8 0x04A6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_8_HI 0x04A6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_8_LO 0x04A7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_9 0x04A8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_9_HI 0x04A8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_9_LO 0x04A9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_10 0x04AA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_10_HI 0x04AA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_10_LO 0x04AB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_11 0x04AC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_11_HI 0x04AC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_11_LO 0x04AD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_12 0x04AE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_12_HI 0x04AE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_12_LO 0x04AF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_13 0x04B0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_13_HI 0x04B0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_13_LO 0x04B1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_14 0x04B2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_14_HI 0x04B2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_14_LO 0x04B3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_15 0x04B4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_15_HI 0x04B4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PATCH__ADDRESS_15_LO 0x04B5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SPI_ASYNC_MUX__CTRL 0x04C0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_CLK__CONFIG 0x04C4 +/*!< + type: uint8_t \n + default: 0x01 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [0] = clk_mcu_en +*/ +#define VL53L1_GPIO_LV_MUX__CTRL 0x04CC +/*!< + type: uint8_t \n + default: 0x08 \n + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [3:0] = gpio__mux_select_lv + - [4] = gpio__mux_active_high_lv +*/ +#define VL53L1_GPIO_LV_PAD__CTRL 0x04CD +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [0] = gpio__extsup_lv +*/ +#define VL53L1_PAD_I2C_LV__CONFIG 0x04D0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PAD_STARTUP_MODE__VALUE_RO_GO1 0x04D4 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [0] = pad_spi_csn_val_ro +*/ +#define VL53L1_HOST_IF__STATUS_GO1 0x04D5 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [0] = host_interface_lv +*/ +#define VL53L1_MCU_CLK_GATING__CTRL 0x04D8 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + [''] + + fields: \n + - [0] = clk_gate_en__go1_mcu_bank + - [1] = clk_gate_en__go1_mcu_patch_ctrl + - [2] = clk_gate_en__go1_mcu_timers + - [3] = clk_gate_en__go1_mcu_mult_div +*/ +#define VL53L1_TEST__BIST_ROM_CTRL 0x04E0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__BIST_ROM_RESULT 0x04E1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__BIST_ROM_MCU_SIG 0x04E2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__BIST_ROM_MCU_SIG_HI 0x04E2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__BIST_ROM_MCU_SIG_LO 0x04E3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__BIST_RAM_CTRL 0x04E4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__BIST_RAM_RESULT 0x04E5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__TMC 0x04E8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__PLL_BIST_MIN_THRESHOLD 0x04F0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__PLL_BIST_MIN_THRESHOLD_HI 0x04F0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__PLL_BIST_MIN_THRESHOLD_LO 0x04F1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__PLL_BIST_MAX_THRESHOLD 0x04F2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__PLL_BIST_MAX_THRESHOLD_HI 0x04F2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__PLL_BIST_MAX_THRESHOLD_LO 0x04F3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__PLL_BIST_COUNT_OUT 0x04F4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__PLL_BIST_COUNT_OUT_HI 0x04F4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__PLL_BIST_COUNT_OUT_LO 0x04F5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__PLL_BIST_GONOGO 0x04F6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_TEST__PLL_BIST_CTRL 0x04F7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__DEVICE_ID 0x0680 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REVISION_ID 0x0681 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CLK_CTRL1 0x0683 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CLK_CTRL2 0x0684 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__WOI_1 0x0685 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__WOI_REF_1 0x0686 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__START_RANGING 0x0687 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__LOW_LIMIT_1 0x0690 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__HIGH_LIMIT_1 0x0691 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__LOW_LIMIT_REF_1 0x0692 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__HIGH_LIMIT_REF_1 0x0693 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__QUANTIFIER_1_MSB 0x0694 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__QUANTIFIER_1_LSB 0x0695 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__QUANTIFIER_REF_1_MSB 0x0696 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__QUANTIFIER_REF_1_LSB 0x0697 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_OFFSET_1_MSB 0x0698 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_OFFSET_1_LSB 0x0699 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_OFFSET_REF_1_MSB 0x069A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_OFFSET_REF_1_LSB 0x069B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__FILTER_STRENGTH_1 0x069C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__FILTER_STRENGTH_REF_1 0x069D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SIGNAL_EVENT_LIMIT_1_MSB 0x069E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SIGNAL_EVENT_LIMIT_1_LSB 0x069F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SIGNAL_EVENT_LIMIT_REF_1_MSB 0x06A0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SIGNAL_EVENT_LIMIT_REF_1_LSB 0x06A1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TIMEOUT_OVERALL_PERIODS_MSB 0x06A4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TIMEOUT_OVERALL_PERIODS_LSB 0x06A5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__INVERT_HW 0x06A6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__FORCE_HW 0x06A7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__STATIC_HW_VALUE 0x06A8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__FORCE_CONTINUOUS_AMBIENT 0x06A9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TEST_PHASE_SELECT_TO_FILTER 0x06AA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TEST_PHASE_SELECT_TO_TIMING_GEN 0x06AB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__INITIAL_PHASE_VALUE_1 0x06AC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__INITIAL_PHASE_VALUE_REF_1 0x06AD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__FORCE_UP_IN 0x06AE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__FORCE_DN_IN 0x06AF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__STATIC_UP_VALUE_1 0x06B0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__STATIC_UP_VALUE_REF_1 0x06B1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__STATIC_DN_VALUE_1 0x06B2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__STATIC_DN_VALUE_REF_1 0x06B3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__MONITOR_UP_DN 0x06B4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__INVERT_UP_DN 0x06B5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CPUMP_1 0x06B6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CPUMP_2 0x06B7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CPUMP_3 0x06B8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__OSC_1 0x06B9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__PLL_1 0x06BB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__PLL_2 0x06BC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REFERENCE_1 0x06BD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REFERENCE_3 0x06BF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REFERENCE_4 0x06C0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REFERENCE_5 0x06C1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REGAVDD1V2 0x06C3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CALIB_1 0x06C4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CALIB_2 0x06C5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CALIB_3 0x06C6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TST_MUX_SEL1 0x06C9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TST_MUX_SEL2 0x06CA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TST_MUX 0x06CB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__GPIO_OUT_TESTMUX 0x06CC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CUSTOM_FE 0x06CD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CUSTOM_FE_2 0x06CE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SPAD_READOUT 0x06CF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SPAD_READOUT_1 0x06D0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SPAD_READOUT_2 0x06D1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SPAD_PS 0x06D2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__LASER_SAFETY_2 0x06D4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__MODE 0x0780 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__PDN 0x0781 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__PROGN 0x0782 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__READN 0x0783 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__PULSE_WIDTH_MSB 0x0784 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__PULSE_WIDTH_LSB 0x0785 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__HV_RISE_MSB 0x0786 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__HV_RISE_LSB 0x0787 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__HV_FALL_MSB 0x0788 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__HV_FALL_LSB 0x0789 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__TST 0x078A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__TESTREAD 0x078B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__DATAIN_MMM 0x078C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__DATAIN_LMM 0x078D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__DATAIN_LLM 0x078E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__DATAIN_LLL 0x078F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__DATAOUT_MMM 0x0790 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__DATAOUT_LMM 0x0791 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__DATAOUT_LLM 0x0792 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__DATAOUT_LLL 0x0793 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__ADDR 0x0794 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__NVM_CTRL__DATAOUT_ECC 0x0795 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_0 0x0796 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_1 0x0797 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_2 0x0798 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_3 0x0799 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_4 0x079A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_5 0x079B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_6 0x079C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_7 0x079D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_8 0x079E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_9 0x079F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_10 0x07A0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_11 0x07A1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_12 0x07A2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_13 0x07A3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_14 0x07A4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_15 0x07A5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_16 0x07A6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_17 0x07A7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SPAD_SHIFT_EN 0x07BA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SPAD_DISABLE_CTRL 0x07BB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SPAD_EN_SHIFT_OUT_DEBUG 0x07BC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SPI_MODE 0x07BD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__GPIO_DIR 0x07BE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__VCSEL_PERIOD 0x0880 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__VCSEL_START 0x0881 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__VCSEL_STOP 0x0882 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__VCSEL_1 0x0885 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__VCSEL_STATUS 0x088D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__STATUS 0x0980 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__LASER_CONTINUITY_STATE 0x0981 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGE_1_MMM 0x0982 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGE_1_LMM 0x0983 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGE_1_LLM 0x0984 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGE_1_LLL 0x0985 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGE_REF_1_MMM 0x0986 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGE_REF_1_LMM 0x0987 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGE_REF_1_LLM 0x0988 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGE_REF_1_LLL 0x0989 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_WINDOW_EVENTS_1_MMM 0x098A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_WINDOW_EVENTS_1_LMM 0x098B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_WINDOW_EVENTS_1_LLM 0x098C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_WINDOW_EVENTS_1_LLL 0x098D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGING_TOTAL_EVENTS_1_MMM 0x098E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGING_TOTAL_EVENTS_1_LMM 0x098F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGING_TOTAL_EVENTS_1_LLM 0x0990 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGING_TOTAL_EVENTS_1_LLL 0x0991 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SIGNAL_TOTAL_EVENTS_1_MMM 0x0992 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SIGNAL_TOTAL_EVENTS_1_LMM 0x0993 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SIGNAL_TOTAL_EVENTS_1_LLM 0x0994 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SIGNAL_TOTAL_EVENTS_1_LLL 0x0995 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TOTAL_PERIODS_ELAPSED_1_MM 0x0996 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TOTAL_PERIODS_ELAPSED_1_LM 0x0997 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TOTAL_PERIODS_ELAPSED_1_LL 0x0998 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_MISMATCH_MM 0x0999 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_MISMATCH_LM 0x099A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_MISMATCH_LL 0x099B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_WINDOW_EVENTS_REF_1_MMM 0x099C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_WINDOW_EVENTS_REF_1_LMM 0x099D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_WINDOW_EVENTS_REF_1_LLM 0x099E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_WINDOW_EVENTS_REF_1_LLL 0x099F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGING_TOTAL_EVENTS_REF_1_MMM 0x09A0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGING_TOTAL_EVENTS_REF_1_LMM 0x09A1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGING_TOTAL_EVENTS_REF_1_LLM 0x09A2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RANGING_TOTAL_EVENTS_REF_1_LLL 0x09A3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SIGNAL_TOTAL_EVENTS_REF_1_MMM 0x09A4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SIGNAL_TOTAL_EVENTS_REF_1_LMM 0x09A5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SIGNAL_TOTAL_EVENTS_REF_1_LLM 0x09A6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SIGNAL_TOTAL_EVENTS_REF_1_LLL 0x09A7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TOTAL_PERIODS_ELAPSED_REF_1_MM 0x09A8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TOTAL_PERIODS_ELAPSED_REF_1_LM 0x09A9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TOTAL_PERIODS_ELAPSED_REF_1_LL 0x09AA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_MISMATCH_REF_MM 0x09AB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_MISMATCH_REF_LM 0x09AC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__AMBIENT_MISMATCH_REF_LL 0x09AD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__GPIO_CONFIG__A0 0x0A00 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RESET_CONTROL__A0 0x0A01 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__INTR_MANAGER__A0 0x0A02 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__POWER_FSM_TIME_OSC__A0 0x0A06 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__VCSEL_ATEST__A0 0x0A07 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__VCSEL_PERIOD_CLIPPED__A0 0x0A08 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__VCSEL_STOP_CLIPPED__A0 0x0A09 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CALIB_2__A0 0x0A0A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__STOP_CONDITION__A0 0x0A0B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__STATUS_RESET__A0 0x0A0C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__READOUT_CFG__A0 0x0A0D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__WINDOW_SETTING__A0 0x0A0E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__VCSEL_DELAY__A0 0x0A1A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REFERENCE_2__A0 0x0A1B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REGAVDD1V2__A0 0x0A1D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__TST_MUX__A0 0x0A1F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CUSTOM_FE_2__A0 0x0A20 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SPAD_READOUT__A0 0x0A21 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__CPUMP_1__A0 0x0A22 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__SPARE_REGISTER__A0 0x0A23 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__VCSEL_CONT_STAGE5_BYPASS__A0 0x0A24 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_18 0x0A25 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_19 0x0A26 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_20 0x0A27 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_21 0x0A28 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_22 0x0A29 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_23 0x0A2A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_24 0x0A2B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_25 0x0A2C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_26 0x0A2D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_27 0x0A2E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_28 0x0A2F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_29 0x0A30 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_30 0x0A31 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__RET_SPAD_EN_31 0x0A32 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REF_SPAD_EN_0__EWOK 0x0A33 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REF_SPAD_EN_1__EWOK 0x0A34 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REF_SPAD_EN_2__EWOK 0x0A35 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REF_SPAD_EN_3__EWOK 0x0A36 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REF_SPAD_EN_4__EWOK 0x0A37 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REF_SPAD_EN_5__EWOK 0x0A38 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REF_EN_START_SELECT 0x0A39 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGING_CORE__REGDVDD1V2_ATEST__EWOK 0x0A41 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SOFT_RESET_GO1 0x0B00 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PRIVATE__PATCH_BASE_ADDR_RSLV 0x0E00 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__INTERRUPT_STATUS 0x0ED0 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [2:0] = prev_shadow_int_status + - [4:3] = prev_shadow_int_error_status + - [5] = prev_shadow_gph_id_gpio_status +*/ +#define VL53L1_PREV_SHADOW_RESULT__RANGE_STATUS 0x0ED1 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [4:0] = prev_shadow_range_status + - [5] = prev_shadow_max_threshold_hit + - [6] = prev_shadow_min_threshold_hit + - [7] = prev_shadow_gph_id_range_status +*/ +#define VL53L1_PREV_SHADOW_RESULT__REPORT_STATUS 0x0ED2 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [3:0] = prev_shadow_report_status +*/ +#define VL53L1_PREV_SHADOW_RESULT__STREAM_COUNT 0x0ED3 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [7:0] = prev_shadow_result__stream_count +*/ +#define VL53L1_PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 0x0ED4 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__dss_actual_effective_spads_sd0 (fixed point 8.8) +*/ +#define VL53L1_PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x0ED4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x0ED5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0 0x0ED6 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__peak_signal_count_rate_mcps_sd0 (fixed point 9.7) +*/ +#define VL53L1_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_HI 0x0ED6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_LO 0x0ED7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0 0x0ED8 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__ambient_count_rate_mcps_sd0 (fixed point 9.7) +*/ +#define VL53L1_PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_HI 0x0ED8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_LO 0x0ED9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SIGMA_SD0 0x0EDA +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__sigma_sd0 (fixed point 14.2) +*/ +#define VL53L1_PREV_SHADOW_RESULT__SIGMA_SD0_HI 0x0EDA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SIGMA_SD0_LO 0x0EDB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__PHASE_SD0 0x0EDC +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__phase_sd0 (fixed point 5.11) +*/ +#define VL53L1_PREV_SHADOW_RESULT__PHASE_SD0_HI 0x0EDC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__PHASE_SD0_LO 0x0EDD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 0x0EDE +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__final_crosstalk_corrected_range_mm_sd0 +*/ +#define VL53L1_PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_HI 0x0EDE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_LO 0x0EDF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 0x0EE0 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 (fixed point 9.7) +*/ +#define VL53L1_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_HI 0x0EE0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_LO 0x0EE1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0 0x0EE2 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__mm_inner_actual_effective_spads_sd0 (fixed point 8.8) +*/ +#define VL53L1_PREV_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x0EE2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x0EE3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0 0x0EE4 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__mm_outer_actual_effective_spads_sd0 (fixed point 8.8) +*/ +#define VL53L1_PREV_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x0EE4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x0EE5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0 0x0EE6 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__avg_signal_count_rate_mcps_sd0 (fixed point 9.7) +*/ +#define VL53L1_PREV_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_HI 0x0EE6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_LO 0x0EE7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1 0x0EE8 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__dss_actual_effective_spads_sd1 (fixed point 8.8) +*/ +#define VL53L1_PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_HI 0x0EE8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_LO 0x0EE9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1 0x0EEA +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__peak_signal_count_rate_mcps_sd1 (fixed point 9.7) +*/ +#define VL53L1_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_HI 0x0EEA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_LO 0x0EEB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1 0x0EEC +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__ambient_count_rate_mcps_sd1 (fixed point 9.7) +*/ +#define VL53L1_PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_HI 0x0EEC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_LO 0x0EED +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SIGMA_SD1 0x0EEE +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__sigma_sd1 (fixed point 14.2) +*/ +#define VL53L1_PREV_SHADOW_RESULT__SIGMA_SD1_HI 0x0EEE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SIGMA_SD1_LO 0x0EEF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__PHASE_SD1 0x0EF0 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__phase_sd1 (fixed point 5.11) +*/ +#define VL53L1_PREV_SHADOW_RESULT__PHASE_SD1_HI 0x0EF0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__PHASE_SD1_LO 0x0EF1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1 0x0EF2 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__final_crosstalk_corrected_range_mm_sd1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_HI 0x0EF2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_LO 0x0EF3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SPARE_0_SD1 0x0EF4 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__spare_0_sd1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SPARE_0_SD1_HI 0x0EF4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SPARE_0_SD1_LO 0x0EF5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SPARE_1_SD1 0x0EF6 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__spare_1_sd1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SPARE_1_SD1_HI 0x0EF6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SPARE_1_SD1_LO 0x0EF7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SPARE_2_SD1 0x0EF8 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__spare_2_sd1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SPARE_2_SD1_HI 0x0EF8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SPARE_2_SD1_LO 0x0EF9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SPARE_3_SD1 0x0EFA +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['prev_shadow_system_results', 'results'] + + fields: \n + - [15:0] = prev_shadow_result__spare_3_sd1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SPARE_3_SD1_HI 0x0EFA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT__SPARE_3_SD1_LO 0x0EFB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 0x0EFC +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['prev_shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = prev_shadow_result_core__ambient_window_events_sd0 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_3 0x0EFC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_2 0x0EFD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_1 0x0EFE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_0 0x0EFF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0 0x0F00 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['prev_shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = prev_shadow_result_core__ranging_total_events_sd0 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_3 0x0F00 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_2 0x0F01 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_1 0x0F02 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_0 0x0F03 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0 0x0F04 +/*!< + type: int32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['prev_shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = prev_shadow_result_core__signal_total_events_sd0 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_3 0x0F04 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_2 0x0F05 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_1 0x0F06 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_0 0x0F07 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0 0x0F08 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['prev_shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = prev_shadow_result_core__total_periods_elapsed_sd0 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_3 0x0F08 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_2 0x0F09 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_1 0x0F0A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_0 0x0F0B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1 0x0F0C +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['prev_shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = prev_shadow_result_core__ambient_window_events_sd1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_3 0x0F0C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_2 0x0F0D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_1 0x0F0E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_0 0x0F0F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1 0x0F10 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['prev_shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = prev_shadow_result_core__ranging_total_events_sd1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_3 0x0F10 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_2 0x0F11 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_1 0x0F12 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_0 0x0F13 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1 0x0F14 +/*!< + type: int32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['prev_shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = prev_shadow_result_core__signal_total_events_sd1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_3 0x0F14 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_2 0x0F15 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_1 0x0F16 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_0 0x0F17 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1 0x0F18 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['prev_shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = prev_shadow_result_core__total_periods_elapsed_sd1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_3 0x0F18 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_2 0x0F19 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_1 0x0F1A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_0 0x0F1B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PREV_SHADOW_RESULT_CORE__SPARE_0 0x0F1C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['prev_shadow_core_results', 'ranging_core_results'] + + fields: \n + - [7:0] = prev_shadow_result_core__spare_0 +*/ +#define VL53L1_RESULT__DEBUG_STATUS 0x0F20 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_debug', 'misc_results'] + + fields: \n + - [7:0] = result_debug_status +*/ +#define VL53L1_RESULT__DEBUG_STAGE 0x0F21 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_debug', 'misc_results'] + + fields: \n + - [7:0] = result_debug_stage +*/ +#define VL53L1_GPH__SYSTEM__THRESH_RATE_HIGH 0x0F24 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['gph_general_config', 'dss_config'] + + fields: \n + - [15:0] = gph__system_thresh_rate_high (fixed point 9.7) +*/ +#define VL53L1_GPH__SYSTEM__THRESH_RATE_HIGH_HI 0x0F24 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__SYSTEM__THRESH_RATE_HIGH_LO 0x0F25 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__SYSTEM__THRESH_RATE_LOW 0x0F26 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['gph_general_config', 'dss_config'] + + fields: \n + - [15:0] = gph__system_thresh_rate_low (fixed point 9.7) +*/ +#define VL53L1_GPH__SYSTEM__THRESH_RATE_LOW_HI 0x0F26 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__SYSTEM__THRESH_RATE_LOW_LO 0x0F27 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__SYSTEM__INTERRUPT_CONFIG_GPIO 0x0F28 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_general_config', 'gph_config'] + + fields: \n + - [1:0] = gph__int_mode_distance + - [3:2] = gph__int_mode_rate + - [4] = gph__int_spare + - [5] = gph__int_new_measure_ready + - [6] = gph__int_no_target_en + - [7] = gph__int_combined_mode +*/ +#define VL53L1_GPH__DSS_CONFIG__ROI_MODE_CONTROL 0x0F2F +/*!< + type: uint8_t \n + default: 0x01 \n + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_static_config', 'dss_config'] + + fields: \n + - [1:0] = gph__dss_config__input_mode + - [2] = gph__calculate_roi_enable +*/ +#define VL53L1_GPH__DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT 0x0F30 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['gph_static_config', 'dss_config'] + + fields: \n + - [15:0] = gph__dss_config__manual_effective_spads_select +*/ +#define VL53L1_GPH__DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT_HI 0x0F30 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT_LO 0x0F31 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__DSS_CONFIG__MANUAL_BLOCK_SELECT 0x0F32 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_static_config', 'dss_config'] + + fields: \n + - [7:0] = gph__dss_config__manual_block_select +*/ +#define VL53L1_GPH__DSS_CONFIG__MAX_SPADS_LIMIT 0x0F33 +/*!< + type: uint8_t \n + default: 0xFF \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_static_config', 'dss_config'] + + fields: \n + - [7:0] = gph__dss_config__max_spads_limit +*/ +#define VL53L1_GPH__DSS_CONFIG__MIN_SPADS_LIMIT 0x0F34 +/*!< + type: uint8_t \n + default: 0x01 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_static_config', 'dss_config'] + + fields: \n + - [7:0] = gph__dss_config__min_spads_limit +*/ +#define VL53L1_GPH__MM_CONFIG__TIMEOUT_MACROP_A_HI 0x0F36 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_timing_config', 'mm_config'] + + fields: \n + - [3:0] = gph_mm_config__config_timeout_macrop_a_hi +*/ +#define VL53L1_GPH__MM_CONFIG__TIMEOUT_MACROP_A_LO 0x0F37 +/*!< + type: uint8_t \n + default: 0x06 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_timing_config', 'mm_config'] + + fields: \n + - [7:0] = gph_mm_config__config_timeout_macrop_a_lo +*/ +#define VL53L1_GPH__MM_CONFIG__TIMEOUT_MACROP_B_HI 0x0F38 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_timing_config', 'mm_config'] + + fields: \n + - [3:0] = gph_mm_config__config_timeout_macrop_b_hi +*/ +#define VL53L1_GPH__MM_CONFIG__TIMEOUT_MACROP_B_LO 0x0F39 +/*!< + type: uint8_t \n + default: 0x06 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_timing_config', 'mm_config'] + + fields: \n + - [7:0] = gph_mm_config__config_timeout_macrop_b_lo +*/ +#define VL53L1_GPH__RANGE_CONFIG__TIMEOUT_MACROP_A_HI 0x0F3A +/*!< + type: uint8_t \n + default: 0x01 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_timing_config', 'range_config'] + + fields: \n + - [3:0] = gph_range_timeout_overall_periods_macrop_a_hi +*/ +#define VL53L1_GPH__RANGE_CONFIG__TIMEOUT_MACROP_A_LO 0x0F3B +/*!< + type: uint8_t \n + default: 0x92 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_timing_config', 'range_config'] + + fields: \n + - [7:0] = gph_range_timeout_overall_periods_macrop_a_lo +*/ +#define VL53L1_GPH__RANGE_CONFIG__VCSEL_PERIOD_A 0x0F3C +/*!< + type: uint8_t \n + default: 0x0B \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_timing_config', 'range_config'] + + fields: \n + - [5:0] = gph_range_config__vcsel_period_a +*/ +#define VL53L1_GPH__RANGE_CONFIG__VCSEL_PERIOD_B 0x0F3D +/*!< + type: uint8_t \n + default: 0x09 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_timing_config', 'range_config'] + + fields: \n + - [5:0] = gph_range_config__vcsel_period_b +*/ +#define VL53L1_GPH__RANGE_CONFIG__TIMEOUT_MACROP_B_HI 0x0F3E +/*!< + type: uint8_t \n + default: 0x01 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_timing_config', 'range_config'] + + fields: \n + - [3:0] = gph_range_timeout_overall_periods_macrop_b_hi +*/ +#define VL53L1_GPH__RANGE_CONFIG__TIMEOUT_MACROP_B_LO 0x0F3F +/*!< + type: uint8_t \n + default: 0x92 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_timing_config', 'range_config'] + + fields: \n + - [7:0] = gph_range_timeout_overall_periods_macrop_b_lo +*/ +#define VL53L1_GPH__RANGE_CONFIG__SIGMA_THRESH 0x0F40 +/*!< + type: uint16_t \n + default: 0x0080 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['gph_timing_config', 'range_config'] + + fields: \n + - [15:0] = gph_range_config__sigma_thresh (fixed point 14.2) +*/ +#define VL53L1_GPH__RANGE_CONFIG__SIGMA_THRESH_HI 0x0F40 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__RANGE_CONFIG__SIGMA_THRESH_LO 0x0F41 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS 0x0F42 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['gph_timing_config', 'range_config'] + + fields: \n + - [15:0] = gph_range_config__min_count_rate_rtn_limit_mcps (fixed point 9.7) +*/ +#define VL53L1_GPH__RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS_HI 0x0F42 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS_LO 0x0F43 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_GPH__RANGE_CONFIG__VALID_PHASE_LOW 0x0F44 +/*!< + type: uint8_t \n + default: 0x08 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_timing_config', 'range_config'] + + fields: \n + - [7:0] = gph_range_config__valid_phase_low (fixed point 5.3) +*/ +#define VL53L1_GPH__RANGE_CONFIG__VALID_PHASE_HIGH 0x0F45 +/*!< + type: uint8_t \n + default: 0x80 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['gph_timing_config', 'range_config'] + + fields: \n + - [7:0] = gph_range_config__valid_phase_high (fixed point 5.3) +*/ +#define VL53L1_FIRMWARE__INTERNAL_STREAM_COUNT_DIV 0x0F46 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['fw_internal'] + + fields: \n + - [7:0] = fw__internal_stream_count_div +*/ +#define VL53L1_FIRMWARE__INTERNAL_STREAM_COUNTER_VAL 0x0F47 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['fw_internal'] + + fields: \n + - [7:0] = fw__internal_stream_counter_val +*/ +#define VL53L1_DSS_CALC__ROI_CTRL 0x0F54 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [0] = dss_calc__roi_intersect_enable + - [1] = dss_calc__roi_subtract_enable +*/ +#define VL53L1_DSS_CALC__SPARE_1 0x0F55 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__spare_1 +*/ +#define VL53L1_DSS_CALC__SPARE_2 0x0F56 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__spare_2 +*/ +#define VL53L1_DSS_CALC__SPARE_3 0x0F57 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__spare_3 +*/ +#define VL53L1_DSS_CALC__SPARE_4 0x0F58 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__spare_4 +*/ +#define VL53L1_DSS_CALC__SPARE_5 0x0F59 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__spare_5 +*/ +#define VL53L1_DSS_CALC__SPARE_6 0x0F5A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__spare_6 +*/ +#define VL53L1_DSS_CALC__SPARE_7 0x0F5B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__spare_7 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_0 0x0F5C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_0 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_1 0x0F5D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_1 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_2 0x0F5E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_2 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_3 0x0F5F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_3 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_4 0x0F60 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_4 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_5 0x0F61 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_5 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_6 0x0F62 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_6 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_7 0x0F63 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_7 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_8 0x0F64 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_8 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_9 0x0F65 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_9 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_10 0x0F66 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_10 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_11 0x0F67 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_11 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_12 0x0F68 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_12 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_13 0x0F69 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_13 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_14 0x0F6A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_14 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_15 0x0F6B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_15 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_16 0x0F6C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_16 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_17 0x0F6D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_17 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_18 0x0F6E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_18 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_19 0x0F6F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_19 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_20 0x0F70 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_20 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_21 0x0F71 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_21 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_22 0x0F72 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_22 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_23 0x0F73 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_23 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_24 0x0F74 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_24 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_25 0x0F75 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_25 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_26 0x0F76 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_26 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_27 0x0F77 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_27 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_28 0x0F78 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_28 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_29 0x0F79 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_29 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_30 0x0F7A +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_30 +*/ +#define VL53L1_DSS_CALC__USER_ROI_SPAD_EN_31 0x0F7B +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_31 +*/ +#define VL53L1_DSS_CALC__USER_ROI_0 0x0F7C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_0 +*/ +#define VL53L1_DSS_CALC__USER_ROI_1 0x0F7D +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__user_roi_1 +*/ +#define VL53L1_DSS_CALC__MODE_ROI_0 0x0F7E +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__mode_roi_0 +*/ +#define VL53L1_DSS_CALC__MODE_ROI_1 0x0F7F +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_calc'] + + fields: \n + - [7:0] = dss_calc__mode_roi_1 +*/ +#define VL53L1_SIGMA_ESTIMATOR_CALC__SPARE_0 0x0F80 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'sigma_est_spare'] + + fields: \n + - [7:0] = sigma_estimator_calc__spare_0 +*/ +#define VL53L1_VHV_RESULT__PEAK_SIGNAL_RATE_MCPS 0x0F82 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['patch_results', 'vhv_results'] + + fields: \n + - [15:0] = vhv_result__peak_signal_rate_mcps +*/ +#define VL53L1_VHV_RESULT__PEAK_SIGNAL_RATE_MCPS_HI 0x0F82 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_VHV_RESULT__PEAK_SIGNAL_RATE_MCPS_LO 0x0F83 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF 0x0F84 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['patch_results', 'vhv_results'] + + fields: \n + - [31:0] = vhv_result__signal_total_events_ref +*/ +#define VL53L1_VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF_3 0x0F84 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF_2 0x0F85 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF_1 0x0F86 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF_0 0x0F87 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PHASECAL_RESULT__PHASE_OUTPUT_REF 0x0F88 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['patch_results', 'phasecal_results'] + + fields: \n + - [15:0] = phasecal_result__normalised_phase_ref +*/ +#define VL53L1_PHASECAL_RESULT__PHASE_OUTPUT_REF_HI 0x0F88 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_PHASECAL_RESULT__PHASE_OUTPUT_REF_LO 0x0F89 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_DSS_RESULT__TOTAL_RATE_PER_SPAD 0x0F8A +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['patch_results', 'dss_results'] + + fields: \n + - [15:0] = dss_result__total_rate_per_spad +*/ +#define VL53L1_DSS_RESULT__TOTAL_RATE_PER_SPAD_HI 0x0F8A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_DSS_RESULT__TOTAL_RATE_PER_SPAD_LO 0x0F8B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_DSS_RESULT__ENABLED_BLOCKS 0x0F8C +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['patch_results', 'dss_results'] + + fields: \n + - [7:0] = dss_result__enabled_blocks +*/ +#define VL53L1_DSS_RESULT__NUM_REQUESTED_SPADS 0x0F8E +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['patch_results', 'dss_results'] + + fields: \n + - [15:0] = dss_result__num_requested_spads (fixed point 8.8) +*/ +#define VL53L1_DSS_RESULT__NUM_REQUESTED_SPADS_HI 0x0F8E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_DSS_RESULT__NUM_REQUESTED_SPADS_LO 0x0F8F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MM_RESULT__INNER_INTERSECTION_RATE 0x0F92 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['patch_results', 'mm_results'] + + fields: \n + - [15:0] = mm_result__inner_intersection_rate +*/ +#define VL53L1_MM_RESULT__INNER_INTERSECTION_RATE_HI 0x0F92 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MM_RESULT__INNER_INTERSECTION_RATE_LO 0x0F93 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MM_RESULT__OUTER_COMPLEMENT_RATE 0x0F94 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['patch_results', 'mm_results'] + + fields: \n + - [15:0] = mm_result__outer_complement_rate +*/ +#define VL53L1_MM_RESULT__OUTER_COMPLEMENT_RATE_HI 0x0F94 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MM_RESULT__OUTER_COMPLEMENT_RATE_LO 0x0F95 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MM_RESULT__TOTAL_OFFSET 0x0F96 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['patch_results', 'mm_results'] + + fields: \n + - [15:0] = mm_result__total_offset +*/ +#define VL53L1_MM_RESULT__TOTAL_OFFSET_HI 0x0F96 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_MM_RESULT__TOTAL_OFFSET_LO 0x0F97 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_CALC__XTALK_FOR_ENABLED_SPADS 0x0F98 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 23 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['patch_results', 'xtalk_calc'] + + fields: \n + - [23:0] = xtalk_calc__xtalk_for_enabled_spads (fixed point 11.13) +*/ +#define VL53L1_XTALK_CALC__XTALK_FOR_ENABLED_SPADS_3 0x0F98 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_CALC__XTALK_FOR_ENABLED_SPADS_2 0x0F99 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_CALC__XTALK_FOR_ENABLED_SPADS_1 0x0F9A +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_CALC__XTALK_FOR_ENABLED_SPADS_0 0x0F9B +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS 0x0F9C +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 23 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['patch_results', 'xtalk_results'] + + fields: \n + - [23:0] = xtalk_result__avg_xtalk_user_roi_kcps (fixed point 11.13) +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS_3 0x0F9C +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS_2 0x0F9D +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS_1 0x0F9E +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS_0 0x0F9F +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS 0x0FA0 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 23 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['patch_results', 'xtalk_results'] + + fields: \n + - [23:0] = xtalk_result__avg_xtalk_mm_inner_roi_kcps (fixed point 11.13) +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS_3 0x0FA0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS_2 0x0FA1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS_1 0x0FA2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS_0 0x0FA3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS 0x0FA4 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 23 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['patch_results', 'xtalk_results'] + + fields: \n + - [23:0] = xtalk_result__avg_xtalk_mm_outer_roi_kcps (fixed point 11.13) +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS_3 0x0FA4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS_2 0x0FA5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS_1 0x0FA6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS_0 0x0FA7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGE_RESULT__ACCUM_PHASE 0x0FA8 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['patch_results', 'range_results'] + + fields: \n + - [31:0] = range_result__accum_phase +*/ +#define VL53L1_RANGE_RESULT__ACCUM_PHASE_3 0x0FA8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGE_RESULT__ACCUM_PHASE_2 0x0FA9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGE_RESULT__ACCUM_PHASE_1 0x0FAA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGE_RESULT__ACCUM_PHASE_0 0x0FAB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGE_RESULT__OFFSET_CORRECTED_RANGE 0x0FAC +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['patch_results', 'range_results'] + + fields: \n + - [15:0] = range_result__offset_corrected_range +*/ +#define VL53L1_RANGE_RESULT__OFFSET_CORRECTED_RANGE_HI 0x0FAC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_RANGE_RESULT__OFFSET_CORRECTED_RANGE_LO 0x0FAD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_PHASECAL_RESULT__VCSEL_START 0x0FAE +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['shadow_system_results', 'histogram_results'] + + fields: \n + - [7:0] = shadow_phasecal_result__vcsel_start +*/ +#define VL53L1_SHADOW_RESULT__INTERRUPT_STATUS 0x0FB0 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [2:0] = shadow_int_status + - [4:3] = shadow_int_error_status + - [5] = shadow_gph_id_gpio_status +*/ +#define VL53L1_SHADOW_RESULT__RANGE_STATUS 0x0FB1 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [4:0] = shadow_range_status + - [5] = shadow_max_threshold_hit + - [6] = shadow_min_threshold_hit + - [7] = shadow_gph_id_range_status +*/ +#define VL53L1_SHADOW_RESULT__REPORT_STATUS 0x0FB2 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [3:0] = shadow_report_status +*/ +#define VL53L1_SHADOW_RESULT__STREAM_COUNT 0x0FB3 +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [7:0] = shadow_result__stream_count +*/ +#define VL53L1_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 0x0FB4 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__dss_actual_effective_spads_sd0 (fixed point 8.8) +*/ +#define VL53L1_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x0FB4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x0FB5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0 0x0FB6 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__peak_signal_count_rate_mcps_sd0 (fixed point 9.7) +*/ +#define VL53L1_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_HI 0x0FB6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_LO 0x0FB7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0 0x0FB8 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__ambient_count_rate_mcps_sd0 (fixed point 9.7) +*/ +#define VL53L1_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_HI 0x0FB8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_LO 0x0FB9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__SIGMA_SD0 0x0FBA +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__sigma_sd0 (fixed point 14.2) +*/ +#define VL53L1_SHADOW_RESULT__SIGMA_SD0_HI 0x0FBA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__SIGMA_SD0_LO 0x0FBB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__PHASE_SD0 0x0FBC +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__phase_sd0 (fixed point 5.11) +*/ +#define VL53L1_SHADOW_RESULT__PHASE_SD0_HI 0x0FBC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__PHASE_SD0_LO 0x0FBD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 0x0FBE +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__final_crosstalk_corrected_range_mm_sd0 +*/ +#define VL53L1_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_HI 0x0FBE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_LO 0x0FBF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 0x0FC0 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 (fixed point 9.7) +*/ +#define VL53L1_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_HI 0x0FC0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_LO 0x0FC1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0 0x0FC2 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__mm_inner_actual_effective_spads_sd0 (fixed point 8.8) +*/ +#define VL53L1_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x0FC2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x0FC3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0 0x0FC4 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__mm_outer_actual_effective_spads_sd0 (fixed point 8.8) +*/ +#define VL53L1_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x0FC4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x0FC5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0 0x0FC6 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__avg_signal_count_rate_mcps_sd0 (fixed point 9.7) +*/ +#define VL53L1_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_HI 0x0FC6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_LO 0x0FC7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1 0x0FC8 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__dss_actual_effective_spads_sd1 (fixed point 8.8) +*/ +#define VL53L1_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_HI 0x0FC8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_LO 0x0FC9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1 0x0FCA +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__peak_signal_count_rate_mcps_sd1 (fixed point 9.7) +*/ +#define VL53L1_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_HI 0x0FCA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_LO 0x0FCB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1 0x0FCC +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__ambient_count_rate_mcps_sd1 (fixed point 9.7) +*/ +#define VL53L1_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_HI 0x0FCC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_LO 0x0FCD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__SIGMA_SD1 0x0FCE +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__sigma_sd1 (fixed point 14.2) +*/ +#define VL53L1_SHADOW_RESULT__SIGMA_SD1_HI 0x0FCE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__SIGMA_SD1_LO 0x0FCF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__PHASE_SD1 0x0FD0 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__phase_sd1 (fixed point 5.11) +*/ +#define VL53L1_SHADOW_RESULT__PHASE_SD1_HI 0x0FD0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__PHASE_SD1_LO 0x0FD1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1 0x0FD2 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__final_crosstalk_corrected_range_mm_sd1 +*/ +#define VL53L1_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_HI 0x0FD2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_LO 0x0FD3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__SPARE_0_SD1 0x0FD4 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__spare_0_sd1 +*/ +#define VL53L1_SHADOW_RESULT__SPARE_0_SD1_HI 0x0FD4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__SPARE_0_SD1_LO 0x0FD5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__SPARE_1_SD1 0x0FD6 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__spare_1_sd1 +*/ +#define VL53L1_SHADOW_RESULT__SPARE_1_SD1_HI 0x0FD6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__SPARE_1_SD1_LO 0x0FD7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__SPARE_2_SD1 0x0FD8 +/*!< + type: uint16_t \n + default: 0x0000 \n + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [15:0] = shadow_result__spare_2_sd1 +*/ +#define VL53L1_SHADOW_RESULT__SPARE_2_SD1_HI 0x0FD8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__SPARE_2_SD1_LO 0x0FD9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT__SPARE_3_SD1 0x0FDA +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [7:0] = shadow_result__spare_3_sd1 +*/ +#define VL53L1_SHADOW_RESULT__THRESH_INFO 0x0FDB +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['shadow_system_results', 'results'] + + fields: \n + - [3:0] = shadow_result__distance_int_info + - [7:4] = shadow_result__rate_int_info +*/ +#define VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 0x0FDC +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = shadow_result_core__ambient_window_events_sd0 +*/ +#define VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_3 0x0FDC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_2 0x0FDD +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_1 0x0FDE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_0 0x0FDF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0 0x0FE0 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = shadow_result_core__ranging_total_events_sd0 +*/ +#define VL53L1_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_3 0x0FE0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_2 0x0FE1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_1 0x0FE2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_0 0x0FE3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0 0x0FE4 +/*!< + type: int32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = shadow_result_core__signal_total_events_sd0 +*/ +#define VL53L1_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_3 0x0FE4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_2 0x0FE5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_1 0x0FE6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_0 0x0FE7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0 0x0FE8 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = shadow_result_core__total_periods_elapsed_sd0 +*/ +#define VL53L1_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_3 0x0FE8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_2 0x0FE9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_1 0x0FEA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_0 0x0FEB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1 0x0FEC +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = shadow_result_core__ambient_window_events_sd1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_3 0x0FEC +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_2 0x0FED +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_1 0x0FEE +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_0 0x0FEF +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1 0x0FF0 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = shadow_result_core__ranging_total_events_sd1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_3 0x0FF0 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_2 0x0FF1 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_1 0x0FF2 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_0 0x0FF3 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1 0x0FF4 +/*!< + type: int32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = shadow_result_core__signal_total_events_sd1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_3 0x0FF4 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_2 0x0FF5 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_1 0x0FF6 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_0 0x0FF7 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1 0x0FF8 +/*!< + type: uint32_t \n + default: 0x00000000 \n + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + groups: \n + ['shadow_core_results', 'ranging_core_results'] + + fields: \n + - [31:0] = shadow_result_core__total_periods_elapsed_sd1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_3 0x0FF8 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_2 0x0FF9 +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_1 0x0FFA +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_0 0x0FFB +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 +*/ +#define VL53L1_SHADOW_RESULT_CORE__SPARE_0 0x0FFC +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['shadow_core_results', 'ranging_core_results'] + + fields: \n + - [7:0] = shadow_result_core__spare_0 +*/ +#define VL53L1_SHADOW_PHASECAL_RESULT__REFERENCE_PHASE_HI 0x0FFE +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['shadow_system_results', 'histogram_results'] + + fields: \n + - [7:0] = shadow_phasecal_result__reference_phase_hi +*/ +#define VL53L1_SHADOW_PHASECAL_RESULT__REFERENCE_PHASE_LO 0x0FFF +/*!< + type: uint8_t \n + default: 0x00 \n + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + groups: \n + ['shadow_system_results', 'histogram_results'] + + fields: \n + - [7:0] = shadow_phasecal_result__reference_phase_lo +*/ + +/** @} VL53L1_register_DefineRegisters_group */ + + +#endif + diff --git a/App/VL53L1X_API/core/inc/vl53l1_register_settings.h b/App/VL53L1X_API/core/inc/vl53l1_register_settings.h new file mode 100644 index 0000000..166ee5b --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_register_settings.h @@ -0,0 +1,222 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_register_settings.h + * + * @brief Device register setting defines. + */ + +#ifndef _VL53L1_REGISTER_SETTINGS_H_ +#define _VL53L1_REGISTER_SETTINGS_H_ + + +/** @defgroup VL53L1_RegisterSettings_group Functionality + * @brief Defines the register settings for key device + * configuration registers + * @{ + */ + +/** @defgroup VL53L1_DeviceSchedulerMode_group - Pseudo, Streaming & Hist + * @brief Values below match the bit positions in the SYSTEM__MODE_START + * register do not change + * @{ + */ + +#define VL53L1_DEVICESCHEDULERMODE_PSEUDO_SOLO 0x00 +#define VL53L1_DEVICESCHEDULERMODE_STREAMING 0x01 +#define VL53L1_DEVICESCHEDULERMODE_HISTOGRAM 0x02 + +/** @} end of VL53L1_DeviceReadoutMode_group */ + +/** @defgroup VL53L1_DeviceReadoutMode_group - Single, Dual, Split & Manual + * @brief Values below match the bit positions in the SYSTEM__MODE_START + * register do not change + * @{ + */ + +#define VL53L1_DEVICEREADOUTMODE_SINGLE_SD (0x00 << 2) +#define VL53L1_DEVICEREADOUTMODE_DUAL_SD (0x01 << 2) +#define VL53L1_DEVICEREADOUTMODE_SPLIT_READOUT (0x02 << 2) +#define VL53L1_DEVICEREADOUTMODE_SPLIT_MANUAL (0x03 << 2) + +/** @} end of VL53L1_DeviceReadoutMode_group */ + +/** @defgroup VL53L1_DeviceMeasurementMode_group - SingleShot, BackToBack & timed + * @brief Values below match the bit positions in the SYSTEM__MODE_START + * register do not change + * @{ + */ + +/* +#define VL53L1_DEVICEMEASUREMENTMODE_STOP 0x00 +#define VL53L1_DEVICEMEASUREMENTMODE_SINGLESHOT 0x10 +#define VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK 0x20 +#define VL53L1_DEVICEMEASUREMENTMODE_TIMED 0x40 +#define VL53L1_DEVICEMEASUREMENTMODE_ABORT 0x80 +*/ +#define VL53L1_DEVICEMEASUREMENTMODE_MODE_MASK 0xF0 +#define VL53L1_DEVICEMEASUREMENTMODE_STOP_MASK 0x0F + +#define VL53L1_GROUPEDPARAMETERHOLD_ID_MASK 0x02 + +/** @} end of VL53L1_DeviceMeasurementMode_group */ + +#define VL53L1_EWOK_I2C_DEV_ADDR_DEFAULT 0x29 + /*!< Device default 7-bit I2C address */ +#define VL53L1_OSC_FREQUENCY 0x00 +#define VL53L1_OSC_TRIM_DEFAULT 0x00 +#define VL53L1_OSC_FREQ_SET_DEFAULT 0x00 + +#define VL53L1_RANGE_HISTOGRAM_REF 0x08 +#define VL53L1_RANGE_HISTOGRAM_RET 0x10 +#define VL53L1_RANGE_HISTOGRAM_BOTH 0x18 +#define VL53L1_RANGE_HISTOGRAM_INIT 0x20 +#define VL53L1_RANGE_VHV_INIT 0x40 + +/* Result Status */ +#define VL53L1_RESULT_RANGE_STATUS 0x1F + +/* */ +#define VL53L1_SYSTEM__SEED_CONFIG__MANUAL 0x00 +#define VL53L1_SYSTEM__SEED_CONFIG__STANDARD 0x01 +#define VL53L1_SYSTEM__SEED_CONFIG__EVEN_UPDATE_ONLY 0x02 + +/* Interrupt Config */ +#define VL53L1_INTERRUPT_CONFIG_LEVEL_LOW 0x00 +#define VL53L1_INTERRUPT_CONFIG_LEVEL_HIGH 0x01 +#define VL53L1_INTERRUPT_CONFIG_OUT_OF_WINDOW 0x02 +#define VL53L1_INTERRUPT_CONFIG_IN_WINDOW 0x03 +#define VL53L1_INTERRUPT_CONFIG_NEW_SAMPLE_READY 0x20 + +/* Interrupt Clear */ +#define VL53L1_CLEAR_RANGE_INT 0x01 +#define VL53L1_CLEAR_ERROR_INT 0x02 + +/* Sequence Config */ +#define VL53L1_SEQUENCE_VHV_EN 0x01 +#define VL53L1_SEQUENCE_PHASECAL_EN 0x02 +#define VL53L1_SEQUENCE_REFERENCE_PHASE_EN 0x04 +#define VL53L1_SEQUENCE_DSS1_EN 0x08 +#define VL53L1_SEQUENCE_DSS2_EN 0x10 +#define VL53L1_SEQUENCE_MM1_EN 0x20 +#define VL53L1_SEQUENCE_MM2_EN 0x40 +#define VL53L1_SEQUENCE_RANGE_EN 0x80 + +/* defines for DSS__ROI_CONTROL */ +#define VL53L1_DSS_CONTROL__ROI_SUBTRACT 0x20 +#define VL53L1_DSS_CONTROL__ROI_INTERSECT 0x10 + +#define VL53L1_DSS_CONTROL__MODE_DISABLED 0x00 +#define VL53L1_DSS_CONTROL__MODE_TARGET_RATE 0x01 +#define VL53L1_DSS_CONTROL__MODE_EFFSPADS 0x02 +#define VL53L1_DSS_CONTROL__MODE_BLOCKSELECT 0x03 + +/* SPAD Readout defines + * + * 7:6 - SPAD_IN_SEL_REF + * 5:4 - SPAD_IN_SEL_RTN + * 2 - SPAD_PS_BYPASS + * 0 - SPAD_EN_PULSE_EXTENDER + */ + +#define VL53L1_RANGING_CORE__SPAD_READOUT__STANDARD 0x45 +#define VL53L1_RANGING_CORE__SPAD_READOUT__RETURN_ARRAY_ONLY 0x05 +#define VL53L1_RANGING_CORE__SPAD_READOUT__REFERENCE_ARRAY_ONLY 0x55 +#define VL53L1_RANGING_CORE__SPAD_READOUT__RETURN_SPLIT_ARRAY 0x25 +#define VL53L1_RANGING_CORE__SPAD_READOUT__CALIB_PULSES 0xF5 + + +#define VL53L1_LASER_SAFETY__KEY_VALUE 0x6C + +/* Range Status defines + * + * 7 - GPH ID + * 6 - Min threshold hit + * 5 - Max threshold hit + * 4:0 - Range Status + */ + +#define VL53L1_RANGE_STATUS__RANGE_STATUS_MASK 0x1F +#define VL53L1_RANGE_STATUS__MAX_THRESHOLD_HIT_MASK 0x20 +#define VL53L1_RANGE_STATUS__MIN_THRESHOLD_HIT_MASK 0x40 +#define VL53L1_RANGE_STATUS__GPH_ID_RANGE_STATUS_MASK 0x80 + +/* Interrupt Status defines + * + * 5 - GPH ID + * 4:3 - Interrupt Error Status + * 2:0 - Interrupt Status + */ + +#define VL53L1_INTERRUPT_STATUS__INT_STATUS_MASK 0x07 +#define VL53L1_INTERRUPT_STATUS__INT_ERROR_STATUS_MASK 0x18 +#define VL53L1_INTERRUPT_STATUS__GPH_ID_INT_STATUS_MASK 0x20 + +/** @} end of VL53L1_RegisterSettings_group */ + + +#endif + +/* _VL53L1_REGISTER_SETTINGS_H_ */ + + diff --git a/App/VL53L1X_API/core/inc/vl53l1_register_structs.h b/App/VL53L1X_API/core/inc/vl53l1_register_structs.h new file mode 100644 index 0000000..bf300e3 --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_register_structs.h @@ -0,0 +1,4402 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_register_structs.h + * @brief VL53L1 Register Structure definitions + */ + +#ifndef _VL53L1_REGISTER_STRUCTS_H_ +#define _VL53L1_REGISTER_STRUCTS_H_ + +#include "vl53l1_types.h" +#include "vl53l1_register_map.h" + +#define VL53L1_STATIC_NVM_MANAGED_I2C_INDEX VL53L1_I2C_SLAVE__DEVICE_ADDRESS +#define VL53L1_CUSTOMER_NVM_MANAGED_I2C_INDEX VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_0 +#define VL53L1_STATIC_CONFIG_I2C_INDEX VL53L1_DSS_CONFIG__TARGET_TOTAL_RATE_MCPS +#define VL53L1_GENERAL_CONFIG_I2C_INDEX VL53L1_GPH_CONFIG__STREAM_COUNT_UPDATE_VALUE +#define VL53L1_TIMING_CONFIG_I2C_INDEX VL53L1_MM_CONFIG__TIMEOUT_MACROP_A_HI +#define VL53L1_DYNAMIC_CONFIG_I2C_INDEX VL53L1_SYSTEM__GROUPED_PARAMETER_HOLD_0 +#define VL53L1_SYSTEM_CONTROL_I2C_INDEX VL53L1_POWER_MANAGEMENT__GO1_POWER_FORCE +#define VL53L1_SYSTEM_RESULTS_I2C_INDEX VL53L1_RESULT__INTERRUPT_STATUS +#define VL53L1_CORE_RESULTS_I2C_INDEX VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 +#define VL53L1_DEBUG_RESULTS_I2C_INDEX VL53L1_PHASECAL_RESULT__REFERENCE_PHASE +#define VL53L1_NVM_COPY_DATA_I2C_INDEX VL53L1_IDENTIFICATION__MODEL_ID +#define VL53L1_PREV_SHADOW_SYSTEM_RESULTS_I2C_INDEX VL53L1_PREV_SHADOW_RESULT__INTERRUPT_STATUS +#define VL53L1_PREV_SHADOW_CORE_RESULTS_I2C_INDEX VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 +#define VL53L1_PATCH_DEBUG_I2C_INDEX VL53L1_RESULT__DEBUG_STATUS +#define VL53L1_GPH_GENERAL_CONFIG_I2C_INDEX VL53L1_GPH__SYSTEM__THRESH_RATE_HIGH +#define VL53L1_GPH_STATIC_CONFIG_I2C_INDEX VL53L1_GPH__DSS_CONFIG__ROI_MODE_CONTROL +#define VL53L1_GPH_TIMING_CONFIG_I2C_INDEX VL53L1_GPH__MM_CONFIG__TIMEOUT_MACROP_A_HI +#define VL53L1_FW_INTERNAL_I2C_INDEX VL53L1_FIRMWARE__INTERNAL_STREAM_COUNT_DIV +#define VL53L1_PATCH_RESULTS_I2C_INDEX VL53L1_DSS_CALC__ROI_CTRL +#define VL53L1_SHADOW_SYSTEM_RESULTS_I2C_INDEX VL53L1_SHADOW_PHASECAL_RESULT__VCSEL_START +#define VL53L1_SHADOW_CORE_RESULTS_I2C_INDEX VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 + +#define VL53L1_STATIC_NVM_MANAGED_I2C_SIZE_BYTES 11 +#define VL53L1_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES 23 +#define VL53L1_STATIC_CONFIG_I2C_SIZE_BYTES 32 +#define VL53L1_GENERAL_CONFIG_I2C_SIZE_BYTES 22 +#define VL53L1_TIMING_CONFIG_I2C_SIZE_BYTES 23 +#define VL53L1_DYNAMIC_CONFIG_I2C_SIZE_BYTES 18 +#define VL53L1_SYSTEM_CONTROL_I2C_SIZE_BYTES 5 +#define VL53L1_SYSTEM_RESULTS_I2C_SIZE_BYTES 44 +#define VL53L1_CORE_RESULTS_I2C_SIZE_BYTES 33 +#define VL53L1_DEBUG_RESULTS_I2C_SIZE_BYTES 56 +#define VL53L1_NVM_COPY_DATA_I2C_SIZE_BYTES 49 +#define VL53L1_PREV_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES 44 +#define VL53L1_PREV_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES 33 +#define VL53L1_PATCH_DEBUG_I2C_SIZE_BYTES 2 +#define VL53L1_GPH_GENERAL_CONFIG_I2C_SIZE_BYTES 5 +#define VL53L1_GPH_STATIC_CONFIG_I2C_SIZE_BYTES 6 +#define VL53L1_GPH_TIMING_CONFIG_I2C_SIZE_BYTES 16 +#define VL53L1_FW_INTERNAL_I2C_SIZE_BYTES 2 +#define VL53L1_PATCH_RESULTS_I2C_SIZE_BYTES 90 +#define VL53L1_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES 82 +#define VL53L1_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES 33 + + +/** + * @struct VL53L1_static_nvm_managed_t + * + * - registers = 10 + * - first_index = 1 (0x0001) + * - last _index = 11 (0x000B) + * - i2c_size = 11 + */ + +typedef struct { + uint8_t i2c_slave__device_address; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = i2c_slave_device_address +*/ + uint8_t ana_config__vhv_ref_sel_vddpix; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = ref_sel_vddpix +*/ + uint8_t ana_config__vhv_ref_sel_vquench; +/*!< + info: \n + - msb = 6 + - lsb = 3 + - i2c_size = 1 + + fields: \n + - [6:3] = ref_sel_vquench +*/ + uint8_t ana_config__reg_avdd1v2_sel; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [1:0] = reg_avdd1v2_sel +*/ + uint8_t ana_config__fast_osc__trim; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = fast_osc_trim +*/ + uint16_t osc_measured__fast_osc__frequency; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = osc_frequency (fixed point 4.12) +*/ + uint8_t vhv_config__timeout_macrop_loop_bound; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [1:0] = vhv_timeout__macrop + - [7:2] = vhv_loop_bound +*/ + uint8_t vhv_config__count_thresh; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = vhv_count_thresh +*/ + uint8_t vhv_config__offset; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = vhv_step_val +*/ + uint8_t vhv_config__init; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7] = vhv0_init_enable + - [5:0] = vhv0_init_value +*/ +} VL53L1_static_nvm_managed_t; + + +/** + * @struct VL53L1_customer_nvm_managed_t + * + * - registers = 16 + * - first_index = 13 (0x000D) + * - last _index = 34 (0x0022) + * - i2c_size = 23 + */ + +typedef struct { + uint8_t global_config__spad_enables_ref_0; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_ref_0 +*/ + uint8_t global_config__spad_enables_ref_1; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_ref_1 +*/ + uint8_t global_config__spad_enables_ref_2; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_ref_2 +*/ + uint8_t global_config__spad_enables_ref_3; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_ref_3 +*/ + uint8_t global_config__spad_enables_ref_4; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_ref_4 +*/ + uint8_t global_config__spad_enables_ref_5; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = spad_enables_ref_5 +*/ + uint8_t global_config__ref_en_start_select; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = ref_en_start_select +*/ + uint8_t ref_spad_man__num_requested_ref_spads; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = ref_spad_man__num_requested_ref_spad +*/ + uint8_t ref_spad_man__ref_location; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [1:0] = ref_spad_man__ref_location +*/ + uint16_t algo__crosstalk_compensation_plane_offset_kcps; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = crosstalk_compensation_plane_offset_kcps (fixed point 7.9) +*/ + int16_t algo__crosstalk_compensation_x_plane_gradient_kcps; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = crosstalk_compensation_x_plane_gradient_kcps (fixed point 5.11) +*/ + int16_t algo__crosstalk_compensation_y_plane_gradient_kcps; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = crosstalk_compensation_y_plane_gradient_kcps (fixed point 5.11) +*/ + uint16_t ref_spad_char__total_rate_target_mcps; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = ref_spad_char__total_rate_target_mcps (fixed point 9.7) +*/ + int16_t algo__part_to_part_range_offset_mm; +/*!< + info: \n + - msb = 12 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [12:0] = part_to_part_offset_mm (fixed point 11.2) +*/ + int16_t mm_config__inner_offset_mm; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = mm_config__inner_offset_mm +*/ + int16_t mm_config__outer_offset_mm; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = mm_config__outer_offset_mm +*/ +} VL53L1_customer_nvm_managed_t; + + +/** + * @struct VL53L1_static_config_t + * + * - registers = 30 + * - first_index = 36 (0x0024) + * - last _index = 67 (0x0043) + * - i2c_size = 32 + */ + +typedef struct { + uint16_t dss_config__target_total_rate_mcps; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = dss_config__target_total_rate_mcps (fixed point 9.7) +*/ + uint8_t debug__ctrl; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = enable_result_logging +*/ + uint8_t test_mode__ctrl; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = test_mode__cmd +*/ + uint8_t clk_gating__ctrl; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = clk_gate_en__mcu_bank + - [1] = clk_gate_en__mcu_patch_ctrl + - [2] = clk_gate_en__mcu_timers + - [3] = clk_gate_en__mcu_mult_div +*/ + uint8_t nvm_bist__ctrl; +/*!< + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [2:0] = nvm_bist__cmd + - [4] = nvm_bist__ctrl +*/ + uint8_t nvm_bist__num_nvm_words; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = nvm_bist__num_nvm_words +*/ + uint8_t nvm_bist__start_address; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = nvm_bist__start_address +*/ + uint8_t host_if__status; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = host_interface +*/ + uint8_t pad_i2c_hv__config; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = pad_scl_sda__vmodeint_hv + - [1] = i2c_pad__test_hv + - [2] = pad_scl__fpen_hv + - [4:3] = pad_scl__progdel_hv + - [5] = pad_sda__fpen_hv + - [7:6] = pad_sda__progdel_hv +*/ + uint8_t pad_i2c_hv__extsup_config; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = pad_scl_sda__extsup_hv +*/ + uint8_t gpio_hv_pad__ctrl; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = gpio__extsup_hv + - [1] = gpio__vmodeint_hv +*/ + uint8_t gpio_hv_mux__ctrl; +/*!< + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = gpio__mux_select_hv + - [4] = gpio__mux_active_high_hv +*/ + uint8_t gpio__tio_hv_status; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = gpio__tio_hv + - [1] = fresh_out_of_reset +*/ + uint8_t gpio__fio_hv_status; +/*!< + info: \n + - msb = 1 + - lsb = 1 + - i2c_size = 1 + + fields: \n + - [1] = gpio__fio_hv +*/ + uint8_t ana_config__spad_sel_pswidth; +/*!< + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [2:0] = spad_sel_pswidth +*/ + uint8_t ana_config__vcsel_pulse_width_offset; +/*!< + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [4:0] = vcsel_pulse_width_offset (fixed point 1.4) +*/ + uint8_t ana_config__fast_osc__config_ctrl; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = osc_config__latch_bypass +*/ + uint8_t sigma_estimator__effective_pulse_width_ns; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = sigma_estimator__eff_pulse_width +*/ + uint8_t sigma_estimator__effective_ambient_width_ns; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = sigma_estimator__eff_ambient_width +*/ + uint8_t sigma_estimator__sigma_ref_mm; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = sigma_estimator__sigma_ref +*/ + uint8_t algo__crosstalk_compensation_valid_height_mm; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = crosstalk_compensation_valid_height_mm +*/ + uint8_t spare_host_config__static_config_spare_0; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = static_config_spare_0 +*/ + uint8_t spare_host_config__static_config_spare_1; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = static_config_spare_1 +*/ + uint16_t algo__range_ignore_threshold_mcps; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = range_ignore_thresh_mcps (fixed point 3.13) +*/ + uint8_t algo__range_ignore_valid_height_mm; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = range_ignore_height_mm +*/ + uint8_t algo__range_min_clip; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = algo__range_min_clip_enable + - [7:1] = algo__range_min_clip_value_mm +*/ + uint8_t algo__consistency_check__tolerance; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = consistency_check_tolerance (fixed point 1.3) +*/ + uint8_t spare_host_config__static_config_spare_2; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = static_config_spare_2 +*/ + uint8_t sd_config__reset_stages_msb; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = loop_init__clear_stage +*/ + uint8_t sd_config__reset_stages_lsb; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:4] = accum_reset__clear_stage + - [3:0] = count_reset__clear_stage +*/ +} VL53L1_static_config_t; + + +/** + * @struct VL53L1_general_config_t + * + * - registers = 17 + * - first_index = 68 (0x0044) + * - last _index = 89 (0x0059) + * - i2c_size = 22 + */ + +typedef struct { + uint8_t gph_config__stream_count_update_value; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = stream_count_update_value +*/ + uint8_t global_config__stream_divider; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = stream_count_internal_div +*/ + uint8_t system__interrupt_config_gpio; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [1:0] = int_mode_distance + - [3:2] = int_mode_rate + - [4] = int_spare + - [5] = int_new_measure_ready + - [6] = int_no_target_en + - [7] = int_combined_mode +*/ + uint8_t cal_config__vcsel_start; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = cal_config__vcsel_start +*/ + uint16_t cal_config__repeat_rate; +/*!< + info: \n + - msb = 11 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [11:0] = cal_config__repeat_rate +*/ + uint8_t global_config__vcsel_width; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = global_config__vcsel_width +*/ + uint8_t phasecal_config__timeout_macrop; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = phasecal_config__timeout_macrop +*/ + uint8_t phasecal_config__target; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = algo_phasecal_lim +*/ + uint8_t phasecal_config__override; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = phasecal_config__override +*/ + uint8_t dss_config__roi_mode_control; +/*!< + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [1:0] = dss_config__input_mode + - [2] = calculate_roi_enable +*/ + uint16_t system__thresh_rate_high; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = thresh_rate_high (fixed point 9.7) +*/ + uint16_t system__thresh_rate_low; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = thresh_rate_low (fixed point 9.7) +*/ + uint16_t dss_config__manual_effective_spads_select; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = dss_config__manual_effective_spads_select +*/ + uint8_t dss_config__manual_block_select; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_config__manual_block_select +*/ + uint8_t dss_config__aperture_attenuation; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_config__aperture_attenuation +*/ + uint8_t dss_config__max_spads_limit; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_config__max_spads_limit +*/ + uint8_t dss_config__min_spads_limit; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_config__min_spads_limit +*/ +} VL53L1_general_config_t; + + +/** + * @struct VL53L1_timing_config_t + * + * - registers = 16 + * - first_index = 90 (0x005A) + * - last _index = 112 (0x0070) + * - i2c_size = 23 + */ + +typedef struct { + uint8_t mm_config__timeout_macrop_a_hi; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = mm_config__config_timeout_macrop_a_hi +*/ + uint8_t mm_config__timeout_macrop_a_lo; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = mm_config__config_timeout_macrop_a_lo +*/ + uint8_t mm_config__timeout_macrop_b_hi; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = mm_config__config_timeout_macrop_b_hi +*/ + uint8_t mm_config__timeout_macrop_b_lo; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = mm_config__config_timeout_macrop_b_lo +*/ + uint8_t range_config__timeout_macrop_a_hi; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = range_timeout_overall_periods_macrop_a_hi +*/ + uint8_t range_config__timeout_macrop_a_lo; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = range_timeout_overall_periods_macrop_a_lo +*/ + uint8_t range_config__vcsel_period_a; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = range_config__vcsel_period_a +*/ + uint8_t range_config__timeout_macrop_b_hi; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = range_timeout_overall_periods_macrop_b_hi +*/ + uint8_t range_config__timeout_macrop_b_lo; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = range_timeout_overall_periods_macrop_b_lo +*/ + uint8_t range_config__vcsel_period_b; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = range_config__vcsel_period_b +*/ + uint16_t range_config__sigma_thresh; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = range_config__sigma_thresh (fixed point 14.2) +*/ + uint16_t range_config__min_count_rate_rtn_limit_mcps; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = range_config__min_count_rate_rtn_limit_mcps (fixed point 9.7) +*/ + uint8_t range_config__valid_phase_low; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = range_config__valid_phase_low (fixed point 5.3) +*/ + uint8_t range_config__valid_phase_high; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = range_config__valid_phase_high (fixed point 5.3) +*/ + uint32_t system__intermeasurement_period; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = intermeasurement_period +*/ + uint8_t system__fractional_enable; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = range_fractional_enable +*/ +} VL53L1_timing_config_t; + + +/** + * @struct VL53L1_dynamic_config_t + * + * - registers = 16 + * - first_index = 113 (0x0071) + * - last _index = 130 (0x0082) + * - i2c_size = 18 + */ + +typedef struct { + uint8_t system__grouped_parameter_hold_0; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = grouped_parameter_hold + - [1] = grouped_parameter_hold_id +*/ + uint16_t system__thresh_high; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = thresh_high +*/ + uint16_t system__thresh_low; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = thresh_low +*/ + uint8_t system__enable_xtalk_per_quadrant; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = system__enable_xtalk_per_quadrant +*/ + uint8_t system__seed_config; +/*!< + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [1:0] = system__seed_config + - [2] = system__fw_pause_ctrl +*/ + uint8_t sd_config__woi_sd0; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = sd_config__woi_sd0 +*/ + uint8_t sd_config__woi_sd1; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = sd_config__woi_sd1 +*/ + uint8_t sd_config__initial_phase_sd0; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = sd_config__initial_phase_sd0 +*/ + uint8_t sd_config__initial_phase_sd1; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = sd_config__initial_phase_sd1 +*/ + uint8_t system__grouped_parameter_hold_1; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = grouped_parameter_hold + - [1] = grouped_parameter_hold_id +*/ + uint8_t sd_config__first_order_select; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = sd_config__first_order_select_rtn + - [1] = sd_config__first_order_select_ref +*/ + uint8_t sd_config__quantifier; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = sd_config__quantifier +*/ + uint8_t roi_config__user_roi_centre_spad; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = user_roi_center_spad +*/ + uint8_t roi_config__user_roi_requested_global_xy_size; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = roi_config__user_roi_requested_global_xy_size +*/ + uint8_t system__sequence_config; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = sequence_vhv_en + - [1] = sequence_phasecal_en + - [2] = sequence_reference_phase_en + - [3] = sequence_dss1_en + - [4] = sequence_dss2_en + - [5] = sequence_mm1_en + - [6] = sequence_mm2_en + - [7] = sequence_range_en +*/ + uint8_t system__grouped_parameter_hold; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = grouped_parameter_hold + - [1] = grouped_parameter_hold_id +*/ +} VL53L1_dynamic_config_t; + + +/** + * @struct VL53L1_system_control_t + * + * - registers = 5 + * - first_index = 131 (0x0083) + * - last _index = 135 (0x0087) + * - i2c_size = 5 + */ + +typedef struct { + uint8_t power_management__go1_power_force; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = go1_dig_powerforce +*/ + uint8_t system__stream_count_ctrl; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = retain_stream_count +*/ + uint8_t firmware__enable; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = firmware_enable +*/ + uint8_t system__interrupt_clear; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = sys_interrupt_clear_range + - [1] = sys_interrupt_clear_error +*/ + uint8_t system__mode_start; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [1:0] = scheduler_mode + - [3:2] = readout_mode + - [4] = mode_range__single_shot + - [5] = mode_range__back_to_back + - [6] = mode_range__timed + - [7] = mode_range__abort +*/ +} VL53L1_system_control_t; + + +/** + * @struct VL53L1_system_results_t + * + * - registers = 25 + * - first_index = 136 (0x0088) + * - last _index = 179 (0x00B3) + * - i2c_size = 44 + */ + +typedef struct { + uint8_t result__interrupt_status; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [2:0] = int_status + - [4:3] = int_error_status + - [5] = gph_id_gpio_status +*/ + uint8_t result__range_status; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [4:0] = range_status + - [5] = max_threshold_hit + - [6] = min_threshold_hit + - [7] = gph_id_range_status +*/ + uint8_t result__report_status; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = report_status +*/ + uint8_t result__stream_count; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = result__stream_count +*/ + uint16_t result__dss_actual_effective_spads_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__dss_actual_effective_spads_sd0 (fixed point 8.8) +*/ + uint16_t result__peak_signal_count_rate_mcps_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__peak_signal_count_rate_mcps_sd0 (fixed point 9.7) +*/ + uint16_t result__ambient_count_rate_mcps_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__ambient_count_rate_mcps_sd0 (fixed point 9.7) +*/ + uint16_t result__sigma_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__sigma_sd0 (fixed point 14.2) +*/ + uint16_t result__phase_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__phase_sd0 (fixed point 5.11) +*/ + uint16_t result__final_crosstalk_corrected_range_mm_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__final_crosstalk_corrected_range_mm_sd0 +*/ + uint16_t result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 (fixed point 9.7) +*/ + uint16_t result__mm_inner_actual_effective_spads_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__mm_inner_actual_effective_spads_sd0 (fixed point 8.8) +*/ + uint16_t result__mm_outer_actual_effective_spads_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__mm_outer_actual_effective_spads_sd0 (fixed point 8.8) +*/ + uint16_t result__avg_signal_count_rate_mcps_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__avg_signal_count_rate_mcps_sd0 (fixed point 9.7) +*/ + uint16_t result__dss_actual_effective_spads_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__dss_actual_effective_spads_sd1 (fixed point 8.8) +*/ + uint16_t result__peak_signal_count_rate_mcps_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__peak_signal_count_rate_mcps_sd1 (fixed point 9.7) +*/ + uint16_t result__ambient_count_rate_mcps_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__ambient_count_rate_mcps_sd1 (fixed point 9.7) +*/ + uint16_t result__sigma_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__sigma_sd1 (fixed point 14.2) +*/ + uint16_t result__phase_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__phase_sd1 (fixed point 5.11) +*/ + uint16_t result__final_crosstalk_corrected_range_mm_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__final_crosstalk_corrected_range_mm_sd1 +*/ + uint16_t result__spare_0_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__spare_0_sd1 +*/ + uint16_t result__spare_1_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__spare_1_sd1 +*/ + uint16_t result__spare_2_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result__spare_2_sd1 +*/ + uint8_t result__spare_3_sd1; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = result__spare_3_sd1 +*/ + uint8_t result__thresh_info; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = result__distance_int_info + - [7:4] = result__rate_int_info +*/ +} VL53L1_system_results_t; + + +/** + * @struct VL53L1_core_results_t + * + * - registers = 9 + * - first_index = 180 (0x00B4) + * - last _index = 212 (0x00D4) + * - i2c_size = 33 + */ + +typedef struct { + uint32_t result_core__ambient_window_events_sd0; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = result_core__ambient_window_events_sd0 +*/ + uint32_t result_core__ranging_total_events_sd0; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = result_core__ranging_total_events_sd0 +*/ + int32_t result_core__signal_total_events_sd0; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = result_core__signal_total_events_sd0 +*/ + uint32_t result_core__total_periods_elapsed_sd0; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = result_core__total_periods_elapsed_sd0 +*/ + uint32_t result_core__ambient_window_events_sd1; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = result_core__ambient_window_events_sd1 +*/ + uint32_t result_core__ranging_total_events_sd1; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = result_core__ranging_total_events_sd1 +*/ + int32_t result_core__signal_total_events_sd1; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = result_core__signal_total_events_sd1 +*/ + uint32_t result_core__total_periods_elapsed_sd1; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = result_core__total_periods_elapsed_sd1 +*/ + uint8_t result_core__spare_0; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = result_core__spare_0 +*/ +} VL53L1_core_results_t; + + +/** + * @struct VL53L1_debug_results_t + * + * - registers = 43 + * - first_index = 214 (0x00D6) + * - last _index = 269 (0x010D) + * - i2c_size = 56 + */ + +typedef struct { + uint16_t phasecal_result__reference_phase; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = result_phasecal__reference_phase (fixed point 5.11) +*/ + uint8_t phasecal_result__vcsel_start; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = result_phasecal__vcsel_start +*/ + uint8_t ref_spad_char_result__num_actual_ref_spads; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = ref_spad_char_result__num_actual_ref_spads +*/ + uint8_t ref_spad_char_result__ref_location; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [1:0] = ref_spad_char_result__ref_location +*/ + uint8_t vhv_result__coldboot_status; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = vhv_result__coldboot_status +*/ + uint8_t vhv_result__search_result; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = cp_sel_result +*/ + uint8_t vhv_result__latest_setting; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = cp_sel_latest_setting +*/ + uint16_t result__osc_calibrate_val; +/*!< + info: \n + - msb = 9 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [9:0] = osc_calibrate_val +*/ + uint8_t ana_config__powerdown_go1; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = go2_ref_bg_disable_avdd + - [1] = go2_regdvdd1v2_enable_avdd +*/ + uint8_t ana_config__ref_bg_ctrl; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = go2_ref_overdrvbg_avdd + - [1] = go2_ref_forcebgison_avdd +*/ + uint8_t ana_config__regdvdd1v2_ctrl; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = go2_regdvdd1v2_sel_pulldown_avdd + - [1] = go2_regdvdd1v2_sel_boost_avdd + - [3:2] = go2_regdvdd1v2_selv_avdd +*/ + uint8_t ana_config__osc_slow_ctrl; +/*!< + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = osc_slow_en + - [1] = osc_slow_op_en + - [2] = osc_slow_freq_sel +*/ + uint8_t test_mode__status; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = test_mode_status +*/ + uint8_t firmware__system_status; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = firmware_bootup + - [1] = firmware_first_range +*/ + uint8_t firmware__mode_status; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = firmware_mode_status +*/ + uint8_t firmware__secondary_mode_status; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = fw_secondary_mode_status +*/ + uint16_t firmware__cal_repeat_rate_counter; +/*!< + info: \n + - msb = 11 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [11:0] = firmware_cal_repeat_rate +*/ + uint16_t gph__system__thresh_high; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_thresh_high +*/ + uint16_t gph__system__thresh_low; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_thresh_low +*/ + uint8_t gph__system__enable_xtalk_per_quadrant; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = shadow__enable_xtalk_per_quadrant +*/ + uint8_t gph__spare_0; +/*!< + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = fw_safe_to_disable + - [1] = shadow__spare_0 + - [2] = shadow__spare_1 +*/ + uint8_t gph__sd_config__woi_sd0; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = shadow_sd_config__woi_sd0 +*/ + uint8_t gph__sd_config__woi_sd1; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = shadow_sd_config__woi_sd1 +*/ + uint8_t gph__sd_config__initial_phase_sd0; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = shadow_sd_config__initial_phase_sd0 +*/ + uint8_t gph__sd_config__initial_phase_sd1; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = shadow_sd_config__initial_phase_sd1 +*/ + uint8_t gph__sd_config__first_order_select; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = shadow_sd_config__first_order_select_rtn + - [1] = shadow_sd_config__first_order_select_ref +*/ + uint8_t gph__sd_config__quantifier; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = shadow_sd_config__quantifier +*/ + uint8_t gph__roi_config__user_roi_centre_spad; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = shadow_user_roi_center_spad_q0 +*/ + uint8_t gph__roi_config__user_roi_requested_global_xy_size; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = shadow_user_roi_requested_global_xy_size +*/ + uint8_t gph__system__sequence_config; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = shadow_sequence_vhv_en + - [1] = shadow_sequence_phasecal_en + - [2] = shadow_sequence_reference_phase_en + - [3] = shadow_sequence_dss1_en + - [4] = shadow_sequence_dss2_en + - [5] = shadow_sequence_mm1_en + - [6] = shadow_sequence_mm2_en + - [7] = shadow_sequence_range_en +*/ + uint8_t gph__gph_id; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = shadow_gph_id +*/ + uint8_t system__interrupt_set; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = sys_interrupt_set_range + - [1] = sys_interrupt_set_error +*/ + uint8_t interrupt_manager__enables; +/*!< + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = interrupt_enable__single_shot + - [1] = interrupt_enable__back_to_back + - [2] = interrupt_enable__timed + - [3] = interrupt_enable__abort + - [4] = interrupt_enable__test +*/ + uint8_t interrupt_manager__clear; +/*!< + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = interrupt_clear__single_shot + - [1] = interrupt_clear__back_to_back + - [2] = interrupt_clear__timed + - [3] = interrupt_clear__abort + - [4] = interrupt_clear__test +*/ + uint8_t interrupt_manager__status; +/*!< + info: \n + - msb = 4 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = interrupt_status__single_shot + - [1] = interrupt_status__back_to_back + - [2] = interrupt_status__timed + - [3] = interrupt_status__abort + - [4] = interrupt_status__test +*/ + uint8_t mcu_to_host_bank__wr_access_en; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = mcu_to_host_bank_wr_en +*/ + uint8_t power_management__go1_reset_status; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = go1_status +*/ + uint8_t pad_startup_mode__value_ro; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = pad_atest1_val_ro + - [1] = pad_atest2_val_ro +*/ + uint8_t pad_startup_mode__value_ctrl; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = pad_atest1_val + - [1] = pad_atest2_val + - [4] = pad_atest1_dig_enable + - [5] = pad_atest2_dig_enable +*/ + uint32_t pll_period_us; +/*!< + info: \n + - msb = 17 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [17:0] = pll_period_us (fixed point 0.24) +*/ + uint32_t interrupt_scheduler__data_out; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = interrupt_scheduler_data_out +*/ + uint8_t nvm_bist__complete; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = nvm_bist__complete +*/ + uint8_t nvm_bist__status; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = nvm_bist__status +*/ +} VL53L1_debug_results_t; + + +/** + * @struct VL53L1_nvm_copy_data_t + * + * - registers = 48 + * - first_index = 271 (0x010F) + * - last _index = 319 (0x013F) + * - i2c_size = 49 + */ + +typedef struct { + uint8_t identification__model_id; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = model_id +*/ + uint8_t identification__module_type; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = module_type +*/ + uint8_t identification__revision_id; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = nvm_revision_id + - [7:4] = mask_revision_id +*/ + uint16_t identification__module_id; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = module_id +*/ + uint8_t ana_config__fast_osc__trim_max; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = osc_trim_max +*/ + uint8_t ana_config__fast_osc__freq_set; +/*!< + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [2:0] = osc_freq_set +*/ + uint8_t ana_config__vcsel_trim; +/*!< + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [2:0] = vcsel_trim +*/ + uint8_t ana_config__vcsel_selion; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = vcsel_selion +*/ + uint8_t ana_config__vcsel_selion_max; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = vcsel_selion_max +*/ + uint8_t protected_laser_safety__lock_bit; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = laser_safety__lock_bit +*/ + uint8_t laser_safety__key; +/*!< + info: \n + - msb = 6 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [6:0] = laser_safety__key +*/ + uint8_t laser_safety__key_ro; +/*!< + info: \n + - msb = 0 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = laser_safety__key_ro +*/ + uint8_t laser_safety__clip; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = vcsel_pulse_width_clip +*/ + uint8_t laser_safety__mult; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = vcsel_pulse_width_mult +*/ + uint8_t global_config__spad_enables_rtn_0; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_0 +*/ + uint8_t global_config__spad_enables_rtn_1; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_1 +*/ + uint8_t global_config__spad_enables_rtn_2; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_2 +*/ + uint8_t global_config__spad_enables_rtn_3; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_3 +*/ + uint8_t global_config__spad_enables_rtn_4; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_4 +*/ + uint8_t global_config__spad_enables_rtn_5; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_5 +*/ + uint8_t global_config__spad_enables_rtn_6; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_6 +*/ + uint8_t global_config__spad_enables_rtn_7; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_7 +*/ + uint8_t global_config__spad_enables_rtn_8; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_8 +*/ + uint8_t global_config__spad_enables_rtn_9; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_9 +*/ + uint8_t global_config__spad_enables_rtn_10; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_10 +*/ + uint8_t global_config__spad_enables_rtn_11; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_11 +*/ + uint8_t global_config__spad_enables_rtn_12; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_12 +*/ + uint8_t global_config__spad_enables_rtn_13; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_13 +*/ + uint8_t global_config__spad_enables_rtn_14; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_14 +*/ + uint8_t global_config__spad_enables_rtn_15; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_15 +*/ + uint8_t global_config__spad_enables_rtn_16; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_16 +*/ + uint8_t global_config__spad_enables_rtn_17; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_17 +*/ + uint8_t global_config__spad_enables_rtn_18; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_18 +*/ + uint8_t global_config__spad_enables_rtn_19; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_19 +*/ + uint8_t global_config__spad_enables_rtn_20; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_20 +*/ + uint8_t global_config__spad_enables_rtn_21; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_21 +*/ + uint8_t global_config__spad_enables_rtn_22; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_22 +*/ + uint8_t global_config__spad_enables_rtn_23; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_23 +*/ + uint8_t global_config__spad_enables_rtn_24; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_24 +*/ + uint8_t global_config__spad_enables_rtn_25; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_25 +*/ + uint8_t global_config__spad_enables_rtn_26; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_26 +*/ + uint8_t global_config__spad_enables_rtn_27; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_27 +*/ + uint8_t global_config__spad_enables_rtn_28; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_28 +*/ + uint8_t global_config__spad_enables_rtn_29; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_29 +*/ + uint8_t global_config__spad_enables_rtn_30; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_30 +*/ + uint8_t global_config__spad_enables_rtn_31; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = spad_enables_rtn_31 +*/ + uint8_t roi_config__mode_roi_centre_spad; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = mode_roi_center_spad +*/ + uint8_t roi_config__mode_roi_xy_size; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = mode_roi_xy_size +*/ +} VL53L1_nvm_copy_data_t; + + +/** + * @struct VL53L1_prev_shadow_system_results_t + * + * - registers = 24 + * - first_index = 3792 (0x0ED0) + * - last _index = 3834 (0x0EFA) + * - i2c_size = 44 + */ + +typedef struct { + uint8_t prev_shadow_result__interrupt_status; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [2:0] = prev_shadow_int_status + - [4:3] = prev_shadow_int_error_status + - [5] = prev_shadow_gph_id_gpio_status +*/ + uint8_t prev_shadow_result__range_status; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [4:0] = prev_shadow_range_status + - [5] = prev_shadow_max_threshold_hit + - [6] = prev_shadow_min_threshold_hit + - [7] = prev_shadow_gph_id_range_status +*/ + uint8_t prev_shadow_result__report_status; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = prev_shadow_report_status +*/ + uint8_t prev_shadow_result__stream_count; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = prev_shadow_result__stream_count +*/ + uint16_t prev_shadow_result__dss_actual_effective_spads_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__dss_actual_effective_spads_sd0 (fixed point 8.8) +*/ + uint16_t prev_shadow_result__peak_signal_count_rate_mcps_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__peak_signal_count_rate_mcps_sd0 (fixed point 9.7) +*/ + uint16_t prev_shadow_result__ambient_count_rate_mcps_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__ambient_count_rate_mcps_sd0 (fixed point 9.7) +*/ + uint16_t prev_shadow_result__sigma_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__sigma_sd0 (fixed point 14.2) +*/ + uint16_t prev_shadow_result__phase_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__phase_sd0 (fixed point 5.11) +*/ + uint16_t prev_shadow_result__final_crosstalk_corrected_range_mm_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__final_crosstalk_corrected_range_mm_sd0 +*/ + uint16_t prev_shadow_result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 (fixed point 9.7) +*/ + uint16_t prev_shadow_result__mm_inner_actual_effective_spads_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__mm_inner_actual_effective_spads_sd0 (fixed point 8.8) +*/ + uint16_t prev_shadow_result__mm_outer_actual_effective_spads_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__mm_outer_actual_effective_spads_sd0 (fixed point 8.8) +*/ + uint16_t prev_shadow_result__avg_signal_count_rate_mcps_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__avg_signal_count_rate_mcps_sd0 (fixed point 9.7) +*/ + uint16_t prev_shadow_result__dss_actual_effective_spads_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__dss_actual_effective_spads_sd1 (fixed point 8.8) +*/ + uint16_t prev_shadow_result__peak_signal_count_rate_mcps_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__peak_signal_count_rate_mcps_sd1 (fixed point 9.7) +*/ + uint16_t prev_shadow_result__ambient_count_rate_mcps_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__ambient_count_rate_mcps_sd1 (fixed point 9.7) +*/ + uint16_t prev_shadow_result__sigma_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__sigma_sd1 (fixed point 14.2) +*/ + uint16_t prev_shadow_result__phase_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__phase_sd1 (fixed point 5.11) +*/ + uint16_t prev_shadow_result__final_crosstalk_corrected_range_mm_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__final_crosstalk_corrected_range_mm_sd1 +*/ + uint16_t prev_shadow_result__spare_0_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__spare_0_sd1 +*/ + uint16_t prev_shadow_result__spare_1_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__spare_1_sd1 +*/ + uint16_t prev_shadow_result__spare_2_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__spare_2_sd1 +*/ + uint16_t prev_shadow_result__spare_3_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = prev_shadow_result__spare_3_sd1 +*/ +} VL53L1_prev_shadow_system_results_t; + + +/** + * @struct VL53L1_prev_shadow_core_results_t + * + * - registers = 9 + * - first_index = 3836 (0x0EFC) + * - last _index = 3868 (0x0F1C) + * - i2c_size = 33 + */ + +typedef struct { + uint32_t prev_shadow_result_core__ambient_window_events_sd0; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = prev_shadow_result_core__ambient_window_events_sd0 +*/ + uint32_t prev_shadow_result_core__ranging_total_events_sd0; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = prev_shadow_result_core__ranging_total_events_sd0 +*/ + int32_t prev_shadow_result_core__signal_total_events_sd0; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = prev_shadow_result_core__signal_total_events_sd0 +*/ + uint32_t prev_shadow_result_core__total_periods_elapsed_sd0; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = prev_shadow_result_core__total_periods_elapsed_sd0 +*/ + uint32_t prev_shadow_result_core__ambient_window_events_sd1; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = prev_shadow_result_core__ambient_window_events_sd1 +*/ + uint32_t prev_shadow_result_core__ranging_total_events_sd1; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = prev_shadow_result_core__ranging_total_events_sd1 +*/ + int32_t prev_shadow_result_core__signal_total_events_sd1; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = prev_shadow_result_core__signal_total_events_sd1 +*/ + uint32_t prev_shadow_result_core__total_periods_elapsed_sd1; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = prev_shadow_result_core__total_periods_elapsed_sd1 +*/ + uint8_t prev_shadow_result_core__spare_0; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = prev_shadow_result_core__spare_0 +*/ +} VL53L1_prev_shadow_core_results_t; + + +/** + * @struct VL53L1_patch_debug_t + * + * - registers = 2 + * - first_index = 3872 (0x0F20) + * - last _index = 3873 (0x0F21) + * - i2c_size = 2 + */ + +typedef struct { + uint8_t result__debug_status; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = result_debug_status +*/ + uint8_t result__debug_stage; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = result_debug_stage +*/ +} VL53L1_patch_debug_t; + + +/** + * @struct VL53L1_gph_general_config_t + * + * - registers = 3 + * - first_index = 3876 (0x0F24) + * - last _index = 3880 (0x0F28) + * - i2c_size = 5 + */ + +typedef struct { + uint16_t gph__system__thresh_rate_high; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = gph__system_thresh_rate_high (fixed point 9.7) +*/ + uint16_t gph__system__thresh_rate_low; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = gph__system_thresh_rate_low (fixed point 9.7) +*/ + uint8_t gph__system__interrupt_config_gpio; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [1:0] = gph__int_mode_distance + - [3:2] = gph__int_mode_rate + - [4] = gph__int_spare + - [5] = gph__int_new_measure_ready + - [6] = gph__int_no_target_en + - [7] = gph__int_combined_mode +*/ +} VL53L1_gph_general_config_t; + + +/** + * @struct VL53L1_gph_static_config_t + * + * - registers = 5 + * - first_index = 3887 (0x0F2F) + * - last _index = 3892 (0x0F34) + * - i2c_size = 6 + */ + +typedef struct { + uint8_t gph__dss_config__roi_mode_control; +/*!< + info: \n + - msb = 2 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [1:0] = gph__dss_config__input_mode + - [2] = gph__calculate_roi_enable +*/ + uint16_t gph__dss_config__manual_effective_spads_select; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = gph__dss_config__manual_effective_spads_select +*/ + uint8_t gph__dss_config__manual_block_select; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = gph__dss_config__manual_block_select +*/ + uint8_t gph__dss_config__max_spads_limit; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = gph__dss_config__max_spads_limit +*/ + uint8_t gph__dss_config__min_spads_limit; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = gph__dss_config__min_spads_limit +*/ +} VL53L1_gph_static_config_t; + + +/** + * @struct VL53L1_gph_timing_config_t + * + * - registers = 14 + * - first_index = 3894 (0x0F36) + * - last _index = 3909 (0x0F45) + * - i2c_size = 16 + */ + +typedef struct { + uint8_t gph__mm_config__timeout_macrop_a_hi; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = gph_mm_config__config_timeout_macrop_a_hi +*/ + uint8_t gph__mm_config__timeout_macrop_a_lo; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = gph_mm_config__config_timeout_macrop_a_lo +*/ + uint8_t gph__mm_config__timeout_macrop_b_hi; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = gph_mm_config__config_timeout_macrop_b_hi +*/ + uint8_t gph__mm_config__timeout_macrop_b_lo; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = gph_mm_config__config_timeout_macrop_b_lo +*/ + uint8_t gph__range_config__timeout_macrop_a_hi; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = gph_range_timeout_overall_periods_macrop_a_hi +*/ + uint8_t gph__range_config__timeout_macrop_a_lo; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = gph_range_timeout_overall_periods_macrop_a_lo +*/ + uint8_t gph__range_config__vcsel_period_a; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = gph_range_config__vcsel_period_a +*/ + uint8_t gph__range_config__vcsel_period_b; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [5:0] = gph_range_config__vcsel_period_b +*/ + uint8_t gph__range_config__timeout_macrop_b_hi; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = gph_range_timeout_overall_periods_macrop_b_hi +*/ + uint8_t gph__range_config__timeout_macrop_b_lo; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = gph_range_timeout_overall_periods_macrop_b_lo +*/ + uint16_t gph__range_config__sigma_thresh; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = gph_range_config__sigma_thresh (fixed point 14.2) +*/ + uint16_t gph__range_config__min_count_rate_rtn_limit_mcps; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = gph_range_config__min_count_rate_rtn_limit_mcps (fixed point 9.7) +*/ + uint8_t gph__range_config__valid_phase_low; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = gph_range_config__valid_phase_low (fixed point 5.3) +*/ + uint8_t gph__range_config__valid_phase_high; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = gph_range_config__valid_phase_high (fixed point 5.3) +*/ +} VL53L1_gph_timing_config_t; + + +/** + * @struct VL53L1_fw_internal_t + * + * - registers = 2 + * - first_index = 3910 (0x0F46) + * - last _index = 3911 (0x0F47) + * - i2c_size = 2 + */ + +typedef struct { + uint8_t firmware__internal_stream_count_div; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = fw__internal_stream_count_div +*/ + uint8_t firmware__internal_stream_counter_val; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = fw__internal_stream_counter_val +*/ +} VL53L1_fw_internal_t; + + +/** + * @struct VL53L1_patch_results_t + * + * - registers = 60 + * - first_index = 3924 (0x0F54) + * - last _index = 4012 (0x0FAC) + * - i2c_size = 90 + */ + +typedef struct { + uint8_t dss_calc__roi_ctrl; +/*!< + info: \n + - msb = 1 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [0] = dss_calc__roi_intersect_enable + - [1] = dss_calc__roi_subtract_enable +*/ + uint8_t dss_calc__spare_1; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__spare_1 +*/ + uint8_t dss_calc__spare_2; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__spare_2 +*/ + uint8_t dss_calc__spare_3; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__spare_3 +*/ + uint8_t dss_calc__spare_4; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__spare_4 +*/ + uint8_t dss_calc__spare_5; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__spare_5 +*/ + uint8_t dss_calc__spare_6; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__spare_6 +*/ + uint8_t dss_calc__spare_7; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__spare_7 +*/ + uint8_t dss_calc__user_roi_spad_en_0; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_0 +*/ + uint8_t dss_calc__user_roi_spad_en_1; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_1 +*/ + uint8_t dss_calc__user_roi_spad_en_2; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_2 +*/ + uint8_t dss_calc__user_roi_spad_en_3; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_3 +*/ + uint8_t dss_calc__user_roi_spad_en_4; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_4 +*/ + uint8_t dss_calc__user_roi_spad_en_5; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_5 +*/ + uint8_t dss_calc__user_roi_spad_en_6; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_6 +*/ + uint8_t dss_calc__user_roi_spad_en_7; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_7 +*/ + uint8_t dss_calc__user_roi_spad_en_8; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_8 +*/ + uint8_t dss_calc__user_roi_spad_en_9; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_9 +*/ + uint8_t dss_calc__user_roi_spad_en_10; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_10 +*/ + uint8_t dss_calc__user_roi_spad_en_11; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_11 +*/ + uint8_t dss_calc__user_roi_spad_en_12; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_12 +*/ + uint8_t dss_calc__user_roi_spad_en_13; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_13 +*/ + uint8_t dss_calc__user_roi_spad_en_14; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_14 +*/ + uint8_t dss_calc__user_roi_spad_en_15; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_15 +*/ + uint8_t dss_calc__user_roi_spad_en_16; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_16 +*/ + uint8_t dss_calc__user_roi_spad_en_17; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_17 +*/ + uint8_t dss_calc__user_roi_spad_en_18; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_18 +*/ + uint8_t dss_calc__user_roi_spad_en_19; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_19 +*/ + uint8_t dss_calc__user_roi_spad_en_20; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_20 +*/ + uint8_t dss_calc__user_roi_spad_en_21; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_21 +*/ + uint8_t dss_calc__user_roi_spad_en_22; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_22 +*/ + uint8_t dss_calc__user_roi_spad_en_23; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_23 +*/ + uint8_t dss_calc__user_roi_spad_en_24; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_24 +*/ + uint8_t dss_calc__user_roi_spad_en_25; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_25 +*/ + uint8_t dss_calc__user_roi_spad_en_26; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_26 +*/ + uint8_t dss_calc__user_roi_spad_en_27; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_27 +*/ + uint8_t dss_calc__user_roi_spad_en_28; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_28 +*/ + uint8_t dss_calc__user_roi_spad_en_29; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_29 +*/ + uint8_t dss_calc__user_roi_spad_en_30; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_30 +*/ + uint8_t dss_calc__user_roi_spad_en_31; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_spad_en_31 +*/ + uint8_t dss_calc__user_roi_0; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_0 +*/ + uint8_t dss_calc__user_roi_1; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__user_roi_1 +*/ + uint8_t dss_calc__mode_roi_0; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__mode_roi_0 +*/ + uint8_t dss_calc__mode_roi_1; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_calc__mode_roi_1 +*/ + uint8_t sigma_estimator_calc__spare_0; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = sigma_estimator_calc__spare_0 +*/ + uint16_t vhv_result__peak_signal_rate_mcps; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = vhv_result__peak_signal_rate_mcps +*/ + uint32_t vhv_result__signal_total_events_ref; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = vhv_result__signal_total_events_ref +*/ + uint16_t phasecal_result__phase_output_ref; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = phasecal_result__normalised_phase_ref +*/ + uint16_t dss_result__total_rate_per_spad; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = dss_result__total_rate_per_spad +*/ + uint8_t dss_result__enabled_blocks; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = dss_result__enabled_blocks +*/ + uint16_t dss_result__num_requested_spads; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = dss_result__num_requested_spads (fixed point 8.8) +*/ + uint16_t mm_result__inner_intersection_rate; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = mm_result__inner_intersection_rate +*/ + uint16_t mm_result__outer_complement_rate; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = mm_result__outer_complement_rate +*/ + uint16_t mm_result__total_offset; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = mm_result__total_offset +*/ + uint32_t xtalk_calc__xtalk_for_enabled_spads; +/*!< + info: \n + - msb = 23 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [23:0] = xtalk_calc__xtalk_for_enabled_spads (fixed point 11.13) +*/ + uint32_t xtalk_result__avg_xtalk_user_roi_kcps; +/*!< + info: \n + - msb = 23 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [23:0] = xtalk_result__avg_xtalk_user_roi_kcps (fixed point 11.13) +*/ + uint32_t xtalk_result__avg_xtalk_mm_inner_roi_kcps; +/*!< + info: \n + - msb = 23 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [23:0] = xtalk_result__avg_xtalk_mm_inner_roi_kcps (fixed point 11.13) +*/ + uint32_t xtalk_result__avg_xtalk_mm_outer_roi_kcps; +/*!< + info: \n + - msb = 23 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [23:0] = xtalk_result__avg_xtalk_mm_outer_roi_kcps (fixed point 11.13) +*/ + uint32_t range_result__accum_phase; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = range_result__accum_phase +*/ + uint16_t range_result__offset_corrected_range; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = range_result__offset_corrected_range +*/ +} VL53L1_patch_results_t; + + +/** + * @struct VL53L1_shadow_system_results_t + * + * - registers = 28 + * - first_index = 4014 (0x0FAE) + * - last _index = 4095 (0x0FFF) + * - i2c_size = 82 + */ + +typedef struct { + uint8_t shadow_phasecal_result__vcsel_start; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = shadow_phasecal_result__vcsel_start +*/ + uint8_t shadow_result__interrupt_status; +/*!< + info: \n + - msb = 5 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [2:0] = shadow_int_status + - [4:3] = shadow_int_error_status + - [5] = shadow_gph_id_gpio_status +*/ + uint8_t shadow_result__range_status; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [4:0] = shadow_range_status + - [5] = shadow_max_threshold_hit + - [6] = shadow_min_threshold_hit + - [7] = shadow_gph_id_range_status +*/ + uint8_t shadow_result__report_status; +/*!< + info: \n + - msb = 3 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = shadow_report_status +*/ + uint8_t shadow_result__stream_count; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = shadow_result__stream_count +*/ + uint16_t shadow_result__dss_actual_effective_spads_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__dss_actual_effective_spads_sd0 (fixed point 8.8) +*/ + uint16_t shadow_result__peak_signal_count_rate_mcps_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__peak_signal_count_rate_mcps_sd0 (fixed point 9.7) +*/ + uint16_t shadow_result__ambient_count_rate_mcps_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__ambient_count_rate_mcps_sd0 (fixed point 9.7) +*/ + uint16_t shadow_result__sigma_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__sigma_sd0 (fixed point 14.2) +*/ + uint16_t shadow_result__phase_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__phase_sd0 (fixed point 5.11) +*/ + uint16_t shadow_result__final_crosstalk_corrected_range_mm_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__final_crosstalk_corrected_range_mm_sd0 +*/ + uint16_t shadow_result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 (fixed point 9.7) +*/ + uint16_t shadow_result__mm_inner_actual_effective_spads_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__mm_inner_actual_effective_spads_sd0 (fixed point 8.8) +*/ + uint16_t shadow_result__mm_outer_actual_effective_spads_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__mm_outer_actual_effective_spads_sd0 (fixed point 8.8) +*/ + uint16_t shadow_result__avg_signal_count_rate_mcps_sd0; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__avg_signal_count_rate_mcps_sd0 (fixed point 9.7) +*/ + uint16_t shadow_result__dss_actual_effective_spads_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__dss_actual_effective_spads_sd1 (fixed point 8.8) +*/ + uint16_t shadow_result__peak_signal_count_rate_mcps_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__peak_signal_count_rate_mcps_sd1 (fixed point 9.7) +*/ + uint16_t shadow_result__ambient_count_rate_mcps_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__ambient_count_rate_mcps_sd1 (fixed point 9.7) +*/ + uint16_t shadow_result__sigma_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__sigma_sd1 (fixed point 14.2) +*/ + uint16_t shadow_result__phase_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__phase_sd1 (fixed point 5.11) +*/ + uint16_t shadow_result__final_crosstalk_corrected_range_mm_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__final_crosstalk_corrected_range_mm_sd1 +*/ + uint16_t shadow_result__spare_0_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__spare_0_sd1 +*/ + uint16_t shadow_result__spare_1_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__spare_1_sd1 +*/ + uint16_t shadow_result__spare_2_sd1; +/*!< + info: \n + - msb = 15 + - lsb = 0 + - i2c_size = 2 + + fields: \n + - [15:0] = shadow_result__spare_2_sd1 +*/ + uint8_t shadow_result__spare_3_sd1; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = shadow_result__spare_3_sd1 +*/ + uint8_t shadow_result__thresh_info; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [3:0] = shadow_result__distance_int_info + - [7:4] = shadow_result__rate_int_info +*/ + uint8_t shadow_phasecal_result__reference_phase_hi; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = shadow_phasecal_result__reference_phase_hi +*/ + uint8_t shadow_phasecal_result__reference_phase_lo; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = shadow_phasecal_result__reference_phase_lo +*/ +} VL53L1_shadow_system_results_t; + + +/** + * @struct VL53L1_shadow_core_results_t + * + * - registers = 9 + * - first_index = 4060 (0x0FDC) + * - last _index = 4092 (0x0FFC) + * - i2c_size = 33 + */ + +typedef struct { + uint32_t shadow_result_core__ambient_window_events_sd0; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = shadow_result_core__ambient_window_events_sd0 +*/ + uint32_t shadow_result_core__ranging_total_events_sd0; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = shadow_result_core__ranging_total_events_sd0 +*/ + int32_t shadow_result_core__signal_total_events_sd0; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = shadow_result_core__signal_total_events_sd0 +*/ + uint32_t shadow_result_core__total_periods_elapsed_sd0; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = shadow_result_core__total_periods_elapsed_sd0 +*/ + uint32_t shadow_result_core__ambient_window_events_sd1; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = shadow_result_core__ambient_window_events_sd1 +*/ + uint32_t shadow_result_core__ranging_total_events_sd1; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = shadow_result_core__ranging_total_events_sd1 +*/ + int32_t shadow_result_core__signal_total_events_sd1; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = shadow_result_core__signal_total_events_sd1 +*/ + uint32_t shadow_result_core__total_periods_elapsed_sd1; +/*!< + info: \n + - msb = 31 + - lsb = 0 + - i2c_size = 4 + + fields: \n + - [31:0] = shadow_result_core__total_periods_elapsed_sd1 +*/ + uint8_t shadow_result_core__spare_0; +/*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7:0] = shadow_result_core__spare_0 +*/ +} VL53L1_shadow_core_results_t; + + +#endif + diff --git a/App/VL53L1X_API/core/inc/vl53l1_silicon_core.h b/App/VL53L1X_API/core/inc/vl53l1_silicon_core.h new file mode 100644 index 0000000..2ba70cc --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_silicon_core.h @@ -0,0 +1,100 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_silicon_core.h + * + * @brief EwokPlus25 low level silicon specific API function definitions + */ + +#ifndef _VL53L1_SILICON_CORE_H_ +#define _VL53L1_SILICON_CORE_H_ + +#include "vl53l1_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Checks if the firmware is ready for ranging (Silicon variant) + * + * @param[in] Dev : Device Handle + * @param[out] pready : pointer to data ready flag \n + * 0 = firmware not ready \n + * 1 = firmware ready + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_is_firmware_ready_silicon( + VL53L1_DEV Dev, + uint8_t *pready); + + +#ifdef __cplusplus +} +#endif + +#endif /* _VL53L1_SILICON_CORE_H_ */ diff --git a/App/VL53L1X_API/core/inc/vl53l1_tuning_parm_defaults.h b/App/VL53L1X_API/core/inc/vl53l1_tuning_parm_defaults.h new file mode 100644 index 0000000..5090a5c --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_tuning_parm_defaults.h @@ -0,0 +1,210 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_tuning_parm_defaults.h + * + * @brief Define defaults for tuning parm list + * + * - Ensures coherence of internal defaults to tuning table + * - Allows reduction of tuning parm list to only changes from the + * standard settings defined below + * + */ + + +#ifndef _VL53L1_TUNING_PARM_DEFAULTS_H_ +#define _VL53L1_TUNING_PARM_DEFAULTS_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup VL53L1_tuningparmdefault_group VL53L1 Defines + * @brief VL53L1 Tuning Parm Default Values + * @{ + */ + +#define VL53L1_TUNINGPARM_VERSION_DEFAULT \ +((uint16_t) 32771) +#define VL53L1_TUNINGPARM_KEY_TABLE_VERSION_DEFAULT \ +((uint16_t) 32769) +#define VL53L1_TUNINGPARM_LLD_VERSION_DEFAULT \ +((uint16_t) 32833) +#define VL53L1_TUNINGPARM_CONSISTENCY_LITE_PHASE_TOLERANCE_DEFAULT \ +((uint8_t) 2) +#define VL53L1_TUNINGPARM_PHASECAL_TARGET_DEFAULT \ +((uint8_t) 33) +#define VL53L1_TUNINGPARM_LITE_CAL_REPEAT_RATE_DEFAULT \ +((uint16_t) 0) +#define VL53L1_TUNINGPARM_LITE_RANGING_GAIN_FACTOR_DEFAULT \ +((uint16_t) 2011) +#define VL53L1_TUNINGPARM_LITE_MIN_CLIP_MM_DEFAULT \ +((uint8_t) 0) +#define VL53L1_TUNINGPARM_LITE_LONG_SIGMA_THRESH_MM_DEFAULT \ +((uint16_t) 360) +#define VL53L1_TUNINGPARM_LITE_MED_SIGMA_THRESH_MM_DEFAULT \ +((uint16_t) 360) +#define VL53L1_TUNINGPARM_LITE_SHORT_SIGMA_THRESH_MM_DEFAULT \ +((uint16_t) 360) +#define VL53L1_TUNINGPARM_LITE_LONG_MIN_COUNT_RATE_RTN_MCPS_DEFAULT \ +((uint16_t) 192) +#define VL53L1_TUNINGPARM_LITE_MED_MIN_COUNT_RATE_RTN_MCPS_DEFAULT \ +((uint16_t) 192) +#define VL53L1_TUNINGPARM_LITE_SHORT_MIN_COUNT_RATE_RTN_MCPS_DEFAULT \ +((uint16_t) 192) +#define VL53L1_TUNINGPARM_LITE_SIGMA_EST_PULSE_WIDTH_DEFAULT \ +((uint8_t) 8) +#define VL53L1_TUNINGPARM_LITE_SIGMA_EST_AMB_WIDTH_NS_DEFAULT \ +((uint8_t) 16) +#define VL53L1_TUNINGPARM_LITE_SIGMA_REF_MM_DEFAULT \ +((uint8_t) 1) +#define VL53L1_TUNINGPARM_LITE_RIT_MULT_DEFAULT \ +((uint8_t) 64) +#define VL53L1_TUNINGPARM_LITE_SEED_CONFIG_DEFAULT \ +((uint8_t) 2) +#define VL53L1_TUNINGPARM_LITE_QUANTIFIER_DEFAULT \ +((uint8_t) 2) +#define VL53L1_TUNINGPARM_LITE_FIRST_ORDER_SELECT_DEFAULT \ +((uint8_t) 0) +#define VL53L1_TUNINGPARM_LITE_XTALK_MARGIN_KCPS_DEFAULT \ +((int16_t) 0) +#define VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_LONG_RANGE_DEFAULT \ +((uint8_t) 14) +#define VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_MED_RANGE_DEFAULT \ +((uint8_t) 10) +#define VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_SHORT_RANGE_DEFAULT \ +((uint8_t) 6) +#define VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_LONG_RANGE_DEFAULT \ +((uint8_t) 14) +#define VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_MED_RANGE_DEFAULT \ +((uint8_t) 10) +#define VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_SHORT_RANGE_DEFAULT \ +((uint8_t) 6) +#define VL53L1_TUNINGPARM_TIMED_SEED_CONFIG_DEFAULT \ +((uint8_t) 1) +#define VL53L1_TUNINGPARM_VHV_LOOPBOUND_DEFAULT \ +((uint8_t) 32) +#define VL53L1_TUNINGPARM_REFSPADCHAR_DEVICE_TEST_MODE_DEFAULT \ +((uint8_t) 8) +#define VL53L1_TUNINGPARM_REFSPADCHAR_VCSEL_PERIOD_DEFAULT \ +((uint8_t) 11) +#define VL53L1_TUNINGPARM_REFSPADCHAR_PHASECAL_TIMEOUT_US_DEFAULT \ +((uint32_t) 1000) +#define VL53L1_TUNINGPARM_REFSPADCHAR_TARGET_COUNT_RATE_MCPS_DEFAULT \ +((uint16_t) 2560) +#define VL53L1_TUNINGPARM_REFSPADCHAR_MIN_COUNTRATE_LIMIT_MCPS_DEFAULT \ +((uint16_t) 1280) +#define VL53L1_TUNINGPARM_REFSPADCHAR_MAX_COUNTRATE_LIMIT_MCPS_DEFAULT \ +((uint16_t) 5120) +#define VL53L1_TUNINGPARM_OFFSET_CAL_DSS_RATE_MCPS_DEFAULT \ +((uint16_t) 2560) +#define VL53L1_TUNINGPARM_OFFSET_CAL_PHASECAL_TIMEOUT_US_DEFAULT \ +((uint32_t) 1000) +#define VL53L1_TUNINGPARM_OFFSET_CAL_MM_TIMEOUT_US_DEFAULT \ +((uint32_t) 13000) +#define VL53L1_TUNINGPARM_OFFSET_CAL_RANGE_TIMEOUT_US_DEFAULT \ +((uint32_t) 13000) +#define VL53L1_TUNINGPARM_OFFSET_CAL_PRE_SAMPLES_DEFAULT \ +((uint8_t) 8) +#define VL53L1_TUNINGPARM_OFFSET_CAL_MM1_SAMPLES_DEFAULT \ +((uint8_t) 40) +#define VL53L1_TUNINGPARM_OFFSET_CAL_MM2_SAMPLES_DEFAULT \ +((uint8_t) 9) +#define VL53L1_TUNINGPARM_SPADMAP_VCSEL_PERIOD_DEFAULT \ +((uint8_t) 18) +#define VL53L1_TUNINGPARM_SPADMAP_VCSEL_START_DEFAULT \ +((uint8_t) 15) +#define VL53L1_TUNINGPARM_SPADMAP_RATE_LIMIT_MCPS_DEFAULT \ +((uint16_t) 12) +#define VL53L1_TUNINGPARM_LITE_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS_DEFAULT \ +((uint16_t) 2560) +#define VL53L1_TUNINGPARM_TIMED_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS_DEFAULT \ +((uint16_t) 2560) +#define VL53L1_TUNINGPARM_LITE_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 1000) +#define VL53L1_TUNINGPARM_TIMED_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 1000) +#define VL53L1_TUNINGPARM_LITE_MM_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 2000) +#define VL53L1_TUNINGPARM_TIMED_MM_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 2000) +#define VL53L1_TUNINGPARM_LITE_RANGE_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 63000) +#define VL53L1_TUNINGPARM_TIMED_RANGE_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 13000) +#define VL53L1_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND_DEFAULT \ +((uint8_t) 3) +#define VL53L1_TUNINGPARM_LOWPOWERAUTO_MM_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 700) +#define VL53L1_TUNINGPARM_LOWPOWERAUTO_RANGE_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 8000) + + +#ifdef __cplusplus +} +#endif + +#endif /* _VL53L1_LL_DEF_H_ */ + + diff --git a/App/VL53L1X_API/core/inc/vl53l1_wait.h b/App/VL53L1X_API/core/inc/vl53l1_wait.h new file mode 100644 index 0000000..b631381 --- /dev/null +++ b/App/VL53L1X_API/core/inc/vl53l1_wait.h @@ -0,0 +1,276 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_wait.h + * + * @brief EwokPlus25 low level Driver wait function definitions + */ + +#ifndef _VL53L1_WAIT_H_ +#define _VL53L1_WAIT_H_ + +#include "vl53l1_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Wait for initial firmware boot to finish + * + * Calls VL53L1_poll_for_boot_completion() + * + * @param[in] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_wait_for_boot_completion( + VL53L1_DEV Dev); + + +/** + * @brief Waits for initial firmware ready + * + * Only waits to see if the firmware is ready in timed and + * single shot modes. + * + * Calls VL53L1_poll_for_firmware_ready() + * + * @param[in] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_wait_for_firmware_ready( + VL53L1_DEV Dev); + + +/** + * @brief Waits for the next ranging interrupt + * + * Calls VL53L1_poll_for_range_completion() + * + * @param[in] Dev : Device handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_wait_for_range_completion( + VL53L1_DEV Dev); + + +/** + * @brief Waits for a device test mode to complete. + + * Calls VL53L1_poll_for_test_completion() + * + * @param[in] Dev : Device Handle + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_wait_for_test_completion( + VL53L1_DEV Dev); + + + + +/** + * @brief Reads FIRMWARE__SYSTEM_STATUS register to detect if the + * firmware was finished booting + * + * @param[in] Dev : Device handle + * @param[out] pready : pointer to data ready flag \n + * 0 = boot not complete \n + * 1 = boot complete + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_is_boot_complete( + VL53L1_DEV Dev, + uint8_t *pready); + +/** + * @brief Reads FIRMWARE__SYSTEM_STATUS register to detect if the + * firmware is ready for ranging. + * + * @param[in] Dev : Device handle + * @param[out] pready : pointer to data ready flag \n + * 0 = firmware not ready \n + * 1 = firmware ready + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_is_firmware_ready( + VL53L1_DEV Dev, + uint8_t *pready); + + +/** + * @brief Reads bit 0 of VL53L1_GPIO__TIO_HV_STATUS register to determine + * if new range data is ready (available). + * + * Interrupt may be either active high or active low. The behaviour of bit 0 + * of the VL53L1_GPIO__TIO_HV_STATUS register is the same as the interrupt + * signal generated on the GPIO pin. + * + * pdev->stat_cfg.gpio_hv_mux_ctrl bit 4 is used to select required check level + * + * + * @param[in] Dev : Device handle + * @param[out] pready : pointer to data ready flag \n + * 0 = data not ready \n + * 1 = new range data available + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_is_new_data_ready( + VL53L1_DEV Dev, + uint8_t *pready); + + + + +/** + * @brief Waits (polls) for initial firmware boot to finish + * + * After power on or a device reset via XSHUTDOWN EwokPlus25 firmware takes + * about 2ms to boot. During this boot sequence elected NVM data is copied + * to the device's Host & MCU G02 registers + * + * This function polls the FIRMWARE__SYSTEM_STATUS register to detect when + * firmware is ready. + * + * Polling is implemented using VL53L1_WaitValueMaskEx() + * + * @param[in] Dev : Device handle + * @param[in] timeout_ms : Wait timeout in [ms] + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_poll_for_boot_completion( + VL53L1_DEV Dev, + uint32_t timeout_ms); + + +/** + * @brief Waits (polls) for initial firmware ready + * + * Polling is implemented using VL53L1_WaitValueMaskEx() + * + * @param[in] Dev : Device handle + * @param[in] timeout_ms : Wait timeout in [ms] + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_poll_for_firmware_ready( + VL53L1_DEV Dev, + uint32_t timeout_ms); + + +/** + * @brief Polls bit 0 of VL53L1_GPIO__TIO_HV_STATUS register to determine + * the state of the GPIO (Interrupt) pin. + * + * Interrupt may be either active high or active low. The behaviour of bit 0 + * of the VL53L1_GPIO__TIO_HV_STATUS register is the same as the interrupt + * signal generated on the GPIO pin. + * + * pdev->stat_cfg.gpio_hv_mux_ctrl bit 4 is used to select required check level + * + * Polling is implemented using VL53L1_WaitValueMaskEx() + * + * @param[in] Dev : Device handle + * @param[in] timeout_ms : Wait timeout in [ms] + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_poll_for_range_completion( + VL53L1_DEV Dev, + uint32_t timeout_ms); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _VL53L1_WAIT_H_ */ diff --git a/App/VL53L1X_API/core/src/vl53l1_api.c b/App/VL53L1X_API/core/src/vl53l1_api.c new file mode 100644 index 0000000..2383e72 --- /dev/null +++ b/App/VL53L1X_API/core/src/vl53l1_api.c @@ -0,0 +1,2937 @@ + +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/****************************************************************************** + * Copyright (c) 2020, STMicroelectronics - All Rights Reserved + + This file is part of VL53L1 and is dual licensed, + either GPL-2.0+ + or 'BSD 3-clause "New" or "Revised" License' , at your option. + ****************************************************************************** + */ + +#include "vl53l1_api.h" +#include "vl53l1_api_strings.h" +#include "vl53l1_register_settings.h" +#include "vl53l1_register_funcs.h" +#include "vl53l1_core.h" +#include "vl53l1_api_calibration.h" +#include "vl53l1_wait.h" +#include "vl53l1_preset_setup.h" +#include "vl53l1_api_debug.h" +#include "vl53l1_api_core.h" + +/* Check for minimum user zone requested by Xtalk calibration */ +/* no need for VL53L1_MAX_USER_ZONES check, set 5 to pass the test */ +#define ZONE_CHECK 5 + +#if ZONE_CHECK < 5 +#error Must define at least 5 zones in MAX_USER_ZONES constant +#endif + +#define LOG_FUNCTION_START(fmt, ...) \ + _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_API, fmt, ##__VA_ARGS__) +#define LOG_FUNCTION_END(status, ...) \ + _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_API, status, ##__VA_ARGS__) +#define LOG_FUNCTION_END_FMT(status, fmt, ...) \ + _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_API, status, \ + fmt, ##__VA_ARGS__) + +#ifdef VL53L1_LOG_ENABLE +#define trace_print(level, ...) trace_print_module_function(\ + VL53L1_TRACE_MODULE_API, level, VL53L1_TRACE_FUNCTION_NONE, \ + ##__VA_ARGS__) +#endif + +#ifndef MIN +#define MIN(v1, v2) ((v1) < (v2) ? (v1) : (v2)) +#endif +#ifndef MAX +#define MAX(v1, v2) ((v1) < (v2) ? (v2) : (v1)) +#endif + +#define DMAX_REFLECTANCE_IDX 2 +/* Use Dmax index 2 because it's the 50% reflectance case by default */ + +/* Following LOWPOWER_AUTO figures have been measured observing vcsel + * emissions on an actual device + */ +#define LOWPOWER_AUTO_VHV_LOOP_DURATION_US 245 +#define LOWPOWER_AUTO_OVERHEAD_BEFORE_A_RANGING 1448 +#define LOWPOWER_AUTO_OVERHEAD_BETWEEN_A_B_RANGING 2100 + +#define FDA_MAX_TIMING_BUDGET_US 550000 +/* Maximum timing budget allowed codex #456189*/ + + +/* local static utilities functions */ + +/* Bare Driver Tuning parameter table indexed with VL53L1_Tuning_t */ +static int32_t BDTable[VL53L1_TUNING_MAX_TUNABLE_KEY] = { + TUNING_VERSION, + TUNING_PROXY_MIN, + TUNING_SINGLE_TARGET_XTALK_TARGET_DISTANCE_MM, + TUNING_SINGLE_TARGET_XTALK_SAMPLE_NUMBER, + TUNING_MIN_AMBIENT_DMAX_VALID, + TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER, + TUNING_XTALK_FULL_ROI_TARGET_DISTANCE_MM, + TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT, + TUNING_XTALK_FULL_ROI_BIN_SUM_MARGIN, + TUNING_XTALK_FULL_ROI_DEFAULT_OFFSET, + TUNING_ZERO_DISTANCE_OFFSET_NON_LINEAR_FACTOR_DEFAULT, + TUNING_PHASECAL_PATCH_POWER +}; + + + static VL53L1_Error VL53L1_LoadPatch(VL53L1_DEV Dev); + static VL53L1_Error VL53L1_UnloadPatch(VL53L1_DEV Dev); + +#define VL53L1_NVM_POWER_UP_DELAY_US 50 +#define VL53L1_NVM_READ_TRIGGER_DELAY_US 5 + +static VL53L1_Error VL53L1_nvm_enable( + VL53L1_DEV Dev, + uint16_t nvm_ctrl_pulse_width, + int32_t nvm_power_up_delay_us) +{ + /* + * Sequence below enables NVM for reading + * + * - Enable power force + * - Disable firmware + * - Power up NVM + * - Wait for 50us while the NVM powers up + * - Configure for reading and set the pulse width (16-bit) + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + + /* Disable Firmware */ + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + + + /* Enable Power Force */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_powerforce(Dev); + + /* Wait the required time for the regulators, bandgap, + * oscillator to wake up and settle + */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WaitUs(Dev, + VL53L1_ENABLE_POWERFORCE_SETTLING_TIME_US); + + /* Power up NVM */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte(Dev, VL53L1_RANGING_CORE__NVM_CTRL__PDN, + 0x01); + + /* Enable NVM Clock */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte(Dev, VL53L1_RANGING_CORE__CLK_CTRL1, + 0x05); + + /* Wait the required time for NVM to power up*/ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WaitUs(Dev, nvm_power_up_delay_us); + + /* Select read mode and set control pulse width */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte(Dev, VL53L1_RANGING_CORE__NVM_CTRL__MODE, + 0x01); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrWord(Dev, + VL53L1_RANGING_CORE__NVM_CTRL__PULSE_WIDTH_MSB, + nvm_ctrl_pulse_width); + + LOG_FUNCTION_END(status); + + return status; + +} + + +static VL53L1_Error VL53L1_nvm_read( + VL53L1_DEV Dev, + uint8_t start_address, + uint8_t count, + uint8_t *pdata) +{ + /* + * Sequence per 32-bit NVM read access: + * + * - Set up the 5-bit (0-127) NVM Address + * - Trigger the read of the NVM data by toggling NVM_CTRL__READN + * - Read the NVM data - 4 bytes wide read/write interface + * - Increment data byte pointer by 4 ready for the next loop + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t nvm_addr = 0; + uint8_t start = start_address; + uint8_t end = start_address + count; + + LOG_FUNCTION_START(""); + + for (nvm_addr = start; nvm_addr < end; nvm_addr++) { + + /* Step 1 : set address */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte(Dev, + VL53L1_RANGING_CORE__NVM_CTRL__ADDR, + nvm_addr); + + /* Step 2 : trigger reading of data */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte(Dev, + VL53L1_RANGING_CORE__NVM_CTRL__READN, + 0x00); + + /* Step 3 : wait the required time */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WaitUs(Dev, + VL53L1_NVM_READ_TRIGGER_DELAY_US); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte(Dev, + VL53L1_RANGING_CORE__NVM_CTRL__READN, + 0x01); + + /* Step 3 : read 4-byte wide data register */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_ReadMulti(Dev, + VL53L1_RANGING_CORE__NVM_CTRL__DATAOUT_MMM, + pdata, 4); + + /* Step 4 : increment byte buffer pointer */ + pdata = pdata + 4; + + } + + LOG_FUNCTION_END(status); + + return status; +} + +static VL53L1_Error VL53L1_nvm_disable( + VL53L1_DEV Dev) +{ + /* + * Power down NVM (OTP) to extend lifetime + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_WrByte( + Dev, + VL53L1_RANGING_CORE__NVM_CTRL__READN, + 0x01); + + /* Power down NVM */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte( + Dev, + VL53L1_RANGING_CORE__NVM_CTRL__PDN, + 0x00); + + /* Keep power force enabled */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_powerforce(Dev); + + /* (Re)Enable Firmware */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; + +} + +static VL53L1_Error VL53L1_read_nvm_raw_data( + VL53L1_DEV Dev, + uint8_t start_address, + uint8_t count, + uint8_t *pnvm_raw_data) +{ + + /* + * Reads ALL 512 bytes of NVM data + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* + * Enable NVM and set control pulse width + */ + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_nvm_enable( + Dev, + 0x0004, + VL53L1_NVM_POWER_UP_DELAY_US); + + /* + * Read the raw NVM data + * - currently all of 128 * 4 bytes = 512 bytes are read + */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_nvm_read( + Dev, + start_address, + count, + pnvm_raw_data); + + /* + * Disable NVM + */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_nvm_disable(Dev); + + LOG_FUNCTION_END(status); + + return status; + +} + +static VL53L1_Error SingleTargetXTalkCalibration(VL53L1_DEV Dev) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + uint32_t sum_ranging = 0; + uint32_t sum_spads = 0; + FixPoint1616_t sum_signalRate = 0; + FixPoint1616_t total_count = 0; + uint8_t xtalk_meas = 0; + uint8_t xtalk_measmax = + BDTable[VL53L1_TUNING_SINGLE_TARGET_XTALK_SAMPLE_NUMBER]; + VL53L1_RangingMeasurementData_t RMData; + FixPoint1616_t xTalkStoredMeanSignalRate; + FixPoint1616_t xTalkStoredMeanRange; + FixPoint1616_t xTalkStoredMeanRtnSpads; + uint32_t xTalkStoredMeanRtnSpadsAsInt; + uint32_t xTalkCalDistanceAsInt; + FixPoint1616_t XTalkCompensationRateMegaCps; + uint32_t signalXTalkTotalPerSpad; + VL53L1_PresetModes PresetMode; + VL53L1_CalibrationData_t CalibrationData; + VL53L1_CustomerNvmManaged_t *pC; + + + LOG_FUNCTION_START(""); + + /* check if the following are selected + * VL53L1_PRESETMODE_AUTONOMOUS, + * VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS + * VL53L1_PRESETMODE_LITE_RANGING + */ + PresetMode = VL53L1DevDataGet(Dev, CurrentParameters.PresetMode); + + if ((PresetMode != VL53L1_PRESETMODE_AUTONOMOUS) && + (PresetMode != VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS) && + (PresetMode != VL53L1_PRESETMODE_LITE_RANGING)) { + Status = VL53L1_ERROR_MODE_NOT_SUPPORTED; + goto ENDFUNC; + } + + /* disable crosstalk calibration */ + Status = VL53L1_disable_xtalk_compensation(Dev); + + if (Status != VL53L1_ERROR_NONE) + goto ENDFUNC; + + Status = VL53L1_StartMeasurement(Dev); + + if (Status != VL53L1_ERROR_NONE) + goto ENDFUNC; + + /* First measurement is never relevant */ + VL53L1_WaitMeasurementDataReady(Dev); + VL53L1_GetRangingMeasurementData(Dev, &RMData); + VL53L1_ClearInterruptAndStartMeasurement(Dev); + + sum_ranging = 0; + sum_spads = 0; + sum_signalRate = 0; + total_count = 0; + for (xtalk_meas = 0; xtalk_meas < xtalk_measmax; xtalk_meas++) { + VL53L1_WaitMeasurementDataReady(Dev); + VL53L1_GetRangingMeasurementData(Dev, &RMData); + VL53L1_ClearInterruptAndStartMeasurement(Dev); + if (RMData.RangeStatus == VL53L1_RANGESTATUS_RANGE_VALID) { + sum_ranging += RMData.RangeMilliMeter; + sum_signalRate += RMData.SignalRateRtnMegaCps; + sum_spads += RMData.EffectiveSpadRtnCount / 256; + total_count++; + } + } + Status = VL53L1_StopMeasurement(Dev); + + if (total_count > 0) { + /* FixPoint1616_t / uint16_t = FixPoint1616_t */ + xTalkStoredMeanSignalRate = sum_signalRate / total_count; + xTalkStoredMeanRange = (FixPoint1616_t)(sum_ranging << 16); + xTalkStoredMeanRange /= total_count; + xTalkStoredMeanRtnSpads = (FixPoint1616_t)(sum_spads << 16); + xTalkStoredMeanRtnSpads /= total_count; + + /* Round Mean Spads to Whole Number. + * Typically the calculated mean SPAD count is a whole number + * or very close to a whole + * number, therefore any truncation will not result in a + * significant loss in accuracy. + * Also, for a grey target at a typical distance of around + * 400mm, around 220 SPADs will + * be enabled, therefore, any truncation will result in a loss + * of accuracy of less than + * 0.5%. + */ + xTalkStoredMeanRtnSpadsAsInt = (xTalkStoredMeanRtnSpads + + 0x8000) >> 16; + + /* Round Cal Distance to Whole Number. + * Note that the cal distance is in mm, therefore no resolution + * is lost. + */ + xTalkCalDistanceAsInt = ((uint32_t)BDTable[ + VL53L1_TUNING_SINGLE_TARGET_XTALK_TARGET_DISTANCE_MM]); + if (xTalkStoredMeanRtnSpadsAsInt == 0 || + xTalkCalDistanceAsInt == 0 || + xTalkStoredMeanRange >= (xTalkCalDistanceAsInt << 16)) { + XTalkCompensationRateMegaCps = 0; + } else { + /* Apply division by mean spad count early in the + * calculation to keep the numbers small. + * This ensures we can maintain a 32bit calculation. + * Fixed1616 / int := Fixed1616 + */ + signalXTalkTotalPerSpad = (xTalkStoredMeanSignalRate) / + xTalkStoredMeanRtnSpadsAsInt; + + /* Complete the calculation for total Signal XTalk per + * SPAD + * Fixed1616 * (Fixed1616 - Fixed1616/int) := + * (2^16 * Fixed1616) + */ + signalXTalkTotalPerSpad *= (((uint32_t)1 << 16) - + (xTalkStoredMeanRange / xTalkCalDistanceAsInt)); + + /* Round from 2^16 * Fixed1616, to Fixed1616. */ + XTalkCompensationRateMegaCps = (signalXTalkTotalPerSpad + + 0x8000) >> 16; + } + + + Status = VL53L1_GetCalibrationData(Dev, &CalibrationData); + + if (Status != VL53L1_ERROR_NONE) + goto ENDFUNC; + + pC = &CalibrationData.customer; + + pC->algo__crosstalk_compensation_plane_offset_kcps = + (uint32_t)(1000 * ((XTalkCompensationRateMegaCps + + ((uint32_t)1<<6)) >> (16-9))); + + Status = VL53L1_SetCalibrationData(Dev, &CalibrationData); + + if (Status != VL53L1_ERROR_NONE) + goto ENDFUNC; + + Status = VL53L1_enable_xtalk_compensation(Dev); + + } else + /* return error because no valid data found */ + Status = VL53L1_ERROR_XTALK_EXTRACTION_NO_SAMPLE_FAIL; + +ENDFUNC: + LOG_FUNCTION_END(Status); + return Status; + +} + +/* Check Rectangle in user's coordinate system: + * 15 TL(x,y) o-----* + * ^ | | + * | *-----o BR(x,y) + * 0------------------------- >15 + * check Rectangle definition conforms to the (0,15,15) coordinate system + * with a minimum of 4x4 size + */ +static VL53L1_Error CheckValidRectRoi(VL53L1_UserRoi_t ROI) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Negative check are not necessary because value is unsigned */ + if ((ROI.TopLeftX > 15) || (ROI.TopLeftY > 15) || + (ROI.BotRightX > 15) || (ROI.BotRightY > 15)) + Status = VL53L1_ERROR_INVALID_PARAMS; + + if ((ROI.TopLeftX > ROI.BotRightX) || (ROI.TopLeftY < ROI.BotRightY)) + Status = VL53L1_ERROR_INVALID_PARAMS; + + LOG_FUNCTION_END(Status); + return Status; +} + +static VL53L1_GPIO_Interrupt_Mode ConvertModeToLLD(VL53L1_Error *pStatus, + VL53L1_ThresholdMode CrossMode) +{ + VL53L1_GPIO_Interrupt_Mode Mode; + + switch (CrossMode) { + case VL53L1_THRESHOLD_CROSSED_LOW: + Mode = VL53L1_GPIOINTMODE_LEVEL_LOW; + break; + case VL53L1_THRESHOLD_CROSSED_HIGH: + Mode = VL53L1_GPIOINTMODE_LEVEL_HIGH; + break; + case VL53L1_THRESHOLD_OUT_OF_WINDOW: + Mode = VL53L1_GPIOINTMODE_OUT_OF_WINDOW; + break; + case VL53L1_THRESHOLD_IN_WINDOW: + Mode = VL53L1_GPIOINTMODE_IN_WINDOW; + break; + default: + /* define Mode to avoid warning but actual value doesn't mind */ + Mode = VL53L1_GPIOINTMODE_LEVEL_HIGH; + *pStatus = VL53L1_ERROR_INVALID_PARAMS; + } + return Mode; +} + +static VL53L1_ThresholdMode ConvertModeFromLLD(VL53L1_Error *pStatus, + VL53L1_GPIO_Interrupt_Mode CrossMode) +{ + VL53L1_ThresholdMode Mode; + + switch (CrossMode) { + case VL53L1_GPIOINTMODE_LEVEL_LOW: + Mode = VL53L1_THRESHOLD_CROSSED_LOW; + break; + case VL53L1_GPIOINTMODE_LEVEL_HIGH: + Mode = VL53L1_THRESHOLD_CROSSED_HIGH; + break; + case VL53L1_GPIOINTMODE_OUT_OF_WINDOW: + Mode = VL53L1_THRESHOLD_OUT_OF_WINDOW; + break; + case VL53L1_GPIOINTMODE_IN_WINDOW: + Mode = VL53L1_THRESHOLD_IN_WINDOW; + break; + default: + /* define Mode to avoid warning but actual value doesn't mind */ + Mode = VL53L1_THRESHOLD_CROSSED_HIGH; + *pStatus = VL53L1_ERROR_UNDEFINED; + } + return Mode; +} + +/* Group PAL General Functions */ + +VL53L1_Error VL53L1_GetVersion(VL53L1_Version_t *pVersion) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + pVersion->major = VL53L1_IMPLEMENTATION_VER_MAJOR; + pVersion->minor = VL53L1_IMPLEMENTATION_VER_MINOR; + pVersion->build = VL53L1_IMPLEMENTATION_VER_SUB; + + pVersion->revision = VL53L1_IMPLEMENTATION_VER_REVISION; + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetProductRevision(VL53L1_DEV Dev, + uint8_t *pProductRevisionMajor, uint8_t *pProductRevisionMinor) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t revision_id; + VL53L1_LLDriverData_t *pLLData; + + LOG_FUNCTION_START(""); + + pLLData = VL53L1DevStructGetLLDriverHandle(Dev); + revision_id = pLLData->nvm_copy_data.identification__revision_id; + *pProductRevisionMajor = 1; + *pProductRevisionMinor = (revision_id & 0xF0) >> 4; + + LOG_FUNCTION_END(Status); + return Status; + +} + +VL53L1_Error VL53L1_GetDeviceInfo(VL53L1_DEV Dev, + VL53L1_DeviceInfo_t *pVL53L1_DeviceInfo) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t revision_id; + VL53L1_LLDriverData_t *pLLData; + + LOG_FUNCTION_START(""); + + pLLData = VL53L1DevStructGetLLDriverHandle(Dev); + + strncpy(pVL53L1_DeviceInfo->ProductId, "", + VL53L1_DEVINFO_STRLEN-1); + pVL53L1_DeviceInfo->ProductType = + pLLData->nvm_copy_data.identification__module_type; + + revision_id = pLLData->nvm_copy_data.identification__revision_id; + pVL53L1_DeviceInfo->ProductRevisionMajor = 1; + pVL53L1_DeviceInfo->ProductRevisionMinor = (revision_id & 0xF0) >> 4; + +#ifndef VL53L1_USE_EMPTY_STRING + if (pVL53L1_DeviceInfo->ProductRevisionMinor == 0) + strncpy(pVL53L1_DeviceInfo->Name, + VL53L1_STRING_DEVICE_INFO_NAME0, + VL53L1_DEVINFO_STRLEN-1); + else + strncpy(pVL53L1_DeviceInfo->Name, + VL53L1_STRING_DEVICE_INFO_NAME1, + VL53L1_DEVINFO_STRLEN-1); + strncpy(pVL53L1_DeviceInfo->Type, + VL53L1_STRING_DEVICE_INFO_TYPE, + VL53L1_DEVINFO_STRLEN-1); + /* Is module_type (ProductType) "evo" aka VL53L3 instead of VL53L1 ? */ + if (pVL53L1_DeviceInfo->ProductType == 0xAA) { + pVL53L1_DeviceInfo->Name[5] = '3'; + pVL53L1_DeviceInfo->Type[5] = '3'; + } +#else + pVL53L1_DeviceInfo->Name[0] = 0; + pVL53L1_DeviceInfo->Type[0] = 0; +#endif + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetUID(VL53L1_DEV Dev, uint64_t *pUid) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t fmtdata[8]; + + LOG_FUNCTION_START(""); + + Status = VL53L1_read_nvm_raw_data(Dev, + (uint8_t)(0x1F8 >> 2), + (uint8_t)(8 >> 2), + fmtdata); + memcpy(pUid, fmtdata, sizeof(uint64_t)); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetRangeStatusString(uint8_t RangeStatus, + char *pRangeStatusString) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + Status = VL53L1_get_range_status_string(RangeStatus, + pRangeStatusString); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetPalErrorString(VL53L1_Error PalErrorCode, + char *pPalErrorString) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + Status = VL53L1_get_pal_error_string(PalErrorCode, pPalErrorString); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetPalStateString(VL53L1_State PalStateCode, + char *pPalStateString) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + Status = VL53L1_get_pal_state_string(PalStateCode, pPalStateString); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetPalState(VL53L1_DEV Dev, VL53L1_State *pPalState) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + *pPalState = VL53L1DevDataGet(Dev, PalState); + + LOG_FUNCTION_END(Status); + return Status; +} + +/* End Group PAL General Functions */ + +/* Group PAL Init Functions */ +VL53L1_Error VL53L1_SetDeviceAddress(VL53L1_DEV Dev, uint8_t DeviceAddress) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + VL53L1_static_nvm_managed_t *pdata = &(pdev->stat_nvm); + + LOG_FUNCTION_START(""); + + Status = VL53L1_WrByte(Dev, VL53L1_I2C_SLAVE__DEVICE_ADDRESS, + DeviceAddress / 2); + + pdata->i2c_slave__device_address = (DeviceAddress / 2) & 0x7F; + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_DataInit(VL53L1_DEV Dev) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t i; + + LOG_FUNCTION_START(""); + + /* 2V8 power mode selection codex 447463 */ +#ifdef USE_I2C_2V8 + Status = VL53L1_RdByte(Dev, VL53L1_PAD_I2C_HV__EXTSUP_CONFIG, &i); + if (Status == VL53L1_ERROR_NONE) { + i = (i & 0xfe) | 0x01; + Status = VL53L1_WrByte(Dev, VL53L1_PAD_I2C_HV__EXTSUP_CONFIG, + i); + } +#endif + + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_data_init(Dev, 1); + + + if (Status == VL53L1_ERROR_NONE) + VL53L1DevDataSet(Dev, PalState, VL53L1_STATE_WAIT_STATICINIT); + + /* Enable all check */ + for (i = 0; i < VL53L1_CHECKENABLE_NUMBER_OF_CHECKS; i++) { + if (Status == VL53L1_ERROR_NONE) + Status |= VL53L1_SetLimitCheckEnable(Dev, i, 1); + else + break; + + } + + + LOG_FUNCTION_END(Status); + return Status; +} + + +VL53L1_Error VL53L1_StaticInit(VL53L1_DEV Dev) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t measurement_mode; + + LOG_FUNCTION_START(""); + + VL53L1DevDataSet(Dev, PalState, VL53L1_STATE_IDLE); + + measurement_mode = VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK; + VL53L1DevDataSet(Dev, LLData.measurement_mode, measurement_mode); + + /* ticket 472728 fix */ + Status = VL53L1_SetPresetMode(Dev, + VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS); + VL53L1DevDataSet(Dev, CurrentParameters.PresetMode, + VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS); + /* end of ticket 472728 fix */ + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_WaitDeviceBooted(VL53L1_DEV Dev) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + Status = VL53L1_poll_for_boot_completion(Dev, + VL53L1_BOOT_COMPLETION_POLLING_TIMEOUT_MS); + + LOG_FUNCTION_END(Status); + return Status; +} + +/* End Group PAL Init Functions */ + +/* Group PAL Parameters Functions */ +static VL53L1_Error ComputeDevicePresetMode( + VL53L1_PresetModes PresetMode, + VL53L1_DistanceModes DistanceMode, + VL53L1_DevicePresetModes *pDevicePresetMode) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + uint8_t DistIdx; + VL53L1_DevicePresetModes LightModes[3] = { + VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_SHORT_RANGE, + VL53L1_DEVICEPRESETMODE_STANDARD_RANGING, + VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_LONG_RANGE}; + + + VL53L1_DevicePresetModes TimedModes[3] = { + VL53L1_DEVICEPRESETMODE_TIMED_RANGING_SHORT_RANGE, + VL53L1_DEVICEPRESETMODE_TIMED_RANGING, + VL53L1_DEVICEPRESETMODE_TIMED_RANGING_LONG_RANGE}; + + VL53L1_DevicePresetModes LowPowerTimedModes[3] = { + VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_SHORT_RANGE, + VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_MEDIUM_RANGE, + VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_LONG_RANGE}; + + *pDevicePresetMode = VL53L1_DEVICEPRESETMODE_STANDARD_RANGING; + + switch (DistanceMode) { + case VL53L1_DISTANCEMODE_SHORT: + DistIdx = 0; + break; + case VL53L1_DISTANCEMODE_MEDIUM: + DistIdx = 1; + break; + default: + DistIdx = 2; + } + + switch (PresetMode) { + case VL53L1_PRESETMODE_LITE_RANGING: + *pDevicePresetMode = LightModes[DistIdx]; + break; + + + case VL53L1_PRESETMODE_AUTONOMOUS: + *pDevicePresetMode = TimedModes[DistIdx]; + break; + + case VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS: + *pDevicePresetMode = LowPowerTimedModes[DistIdx]; + break; + + default: + /* Unsupported mode */ + Status = VL53L1_ERROR_MODE_NOT_SUPPORTED; + } + + return Status; +} + +static VL53L1_Error SetPresetMode(VL53L1_DEV Dev, + VL53L1_PresetModes PresetMode, + VL53L1_DistanceModes DistanceMode, + uint32_t inter_measurement_period_ms) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_DevicePresetModes device_preset_mode; + uint8_t measurement_mode; + uint16_t dss_config__target_total_rate_mcps = 0; + uint32_t phasecal_config_timeout_us = 0; + uint32_t mm_config_timeout_us = 0; + uint32_t lld_range_config_timeout_us = 0; + + LOG_FUNCTION_START("%d", (int)PresetMode); + + if ((PresetMode == VL53L1_PRESETMODE_AUTONOMOUS) || + (PresetMode == VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS)) + measurement_mode = VL53L1_DEVICEMEASUREMENTMODE_TIMED; + else + measurement_mode = VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK; + + + Status = ComputeDevicePresetMode(PresetMode, DistanceMode, + &device_preset_mode); + + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_get_preset_mode_timing_cfg(Dev, + device_preset_mode, + &dss_config__target_total_rate_mcps, + &phasecal_config_timeout_us, + &mm_config_timeout_us, + &lld_range_config_timeout_us); + + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_set_preset_mode( + Dev, + device_preset_mode, + dss_config__target_total_rate_mcps, + phasecal_config_timeout_us, + mm_config_timeout_us, + lld_range_config_timeout_us, + inter_measurement_period_ms); + + if (Status == VL53L1_ERROR_NONE) + VL53L1DevDataSet(Dev, LLData.measurement_mode, + measurement_mode); + + if (Status == VL53L1_ERROR_NONE) + VL53L1DevDataSet(Dev, CurrentParameters.PresetMode, PresetMode); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_SetInterruptPolarity(VL53L1_DEV Dev, + VL53L1_DeviceInterruptPolarity interrupt_polarity) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + Status = VL53L1_set_interrupt_polarity(Dev, interrupt_polarity); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetInterruptPolarity(VL53L1_DEV Dev, + VL53L1_DeviceInterruptPolarity *pinterrupt_polarity) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + Status = VL53L1_get_interrupt_polarity(Dev, pinterrupt_polarity); + + LOG_FUNCTION_END(Status); + return Status; +} + + +VL53L1_Error VL53L1_SetPresetMode(VL53L1_DEV Dev, VL53L1_PresetModes PresetMode) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_DistanceModes DistanceMode = VL53L1_DISTANCEMODE_LONG; + + LOG_FUNCTION_START("%d", (int)PresetMode); + + /* fix for bug 495690 */ + Status = VL53L1_low_power_auto_data_init(Dev); + + Status = SetPresetMode(Dev, + PresetMode, + DistanceMode, + 1000); + + if (Status == VL53L1_ERROR_NONE) { + if ((PresetMode == VL53L1_PRESETMODE_LITE_RANGING) || + (PresetMode == VL53L1_PRESETMODE_AUTONOMOUS) || + (PresetMode == VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS)) + Status = VL53L1_SetMeasurementTimingBudgetMicroSeconds( + Dev, 41000); + else + /* Set default timing budget to 30Hz (33.33 ms)*/ + Status = VL53L1_SetMeasurementTimingBudgetMicroSeconds( + Dev, 33333); + } + + if (Status == VL53L1_ERROR_NONE) { + /* Set default intermeasurement period to 1000 ms */ + Status = VL53L1_SetInterMeasurementPeriodMilliSeconds(Dev, + 1000); + } + + LOG_FUNCTION_END(Status); + return Status; +} + + +VL53L1_Error VL53L1_GetPresetMode(VL53L1_DEV Dev, + VL53L1_PresetModes *pPresetMode) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + *pPresetMode = VL53L1DevDataGet(Dev, CurrentParameters.PresetMode); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_SetDistanceMode(VL53L1_DEV Dev, + VL53L1_DistanceModes DistanceMode) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_PresetModes PresetMode; + uint32_t inter_measurement_period_ms; + uint32_t TimingBudget = 0; + uint32_t MmTimeoutUs = 0; + uint32_t PhaseCalTimeoutUs = 0; + VL53L1_user_zone_t user_zone; + + LOG_FUNCTION_START("%d", (int)DistanceMode); + + PresetMode = VL53L1DevDataGet(Dev, CurrentParameters.PresetMode); + + /* when the distance mode is valid: + * Manual Mode: all modes + * AUTO AUTO_LITE : LITE_RANGING, RANGING + */ + + if ((DistanceMode != VL53L1_DISTANCEMODE_SHORT) && + (DistanceMode != VL53L1_DISTANCEMODE_MEDIUM) && + (DistanceMode != VL53L1_DISTANCEMODE_LONG)) + return VL53L1_ERROR_INVALID_PARAMS; + + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_get_user_zone(Dev, &user_zone); + + inter_measurement_period_ms = VL53L1DevDataGet(Dev, + LLData.inter_measurement_period_ms); + + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_get_timeouts_us(Dev, &PhaseCalTimeoutUs, + &MmTimeoutUs, &TimingBudget); + + if (Status == VL53L1_ERROR_NONE) + Status = SetPresetMode(Dev, + PresetMode, + DistanceMode, + inter_measurement_period_ms); + + if (Status == VL53L1_ERROR_NONE) { + VL53L1DevDataSet(Dev, CurrentParameters.DistanceMode, + DistanceMode); + } + + if (Status == VL53L1_ERROR_NONE) { + Status = VL53L1_set_timeouts_us(Dev, PhaseCalTimeoutUs, + MmTimeoutUs, TimingBudget); + + if (Status == VL53L1_ERROR_NONE) + VL53L1DevDataSet(Dev, LLData.range_config_timeout_us, + TimingBudget); + } + + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_set_user_zone(Dev, &user_zone); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetDistanceMode(VL53L1_DEV Dev, + VL53L1_DistanceModes *pDistanceMode) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + *pDistanceMode = VL53L1DevDataGet(Dev, CurrentParameters.DistanceMode); + + LOG_FUNCTION_END(Status); + return Status; +} + + + + +VL53L1_Error VL53L1_SetMeasurementTimingBudgetMicroSeconds(VL53L1_DEV Dev, + uint32_t MeasurementTimingBudgetMicroSeconds) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t Mm1Enabled = 0; + uint8_t Mm2Enabled = 0; + uint32_t TimingGuard; + uint32_t divisor; + uint32_t TimingBudget = 0; + uint32_t MmTimeoutUs = 0; + VL53L1_PresetModes PresetMode; + uint32_t PhaseCalTimeoutUs = 0; + uint32_t vhv; + int32_t vhv_loops; + uint32_t FDAMaxTimingBudgetUs = FDA_MAX_TIMING_BUDGET_US; + + LOG_FUNCTION_START(""); + + /* Timing budget is limited to 10 seconds */ + if (MeasurementTimingBudgetMicroSeconds > 10000000) + Status = VL53L1_ERROR_INVALID_PARAMS; + + if (Status == VL53L1_ERROR_NONE) { + Status = VL53L1_GetSequenceStepEnable(Dev, + VL53L1_SEQUENCESTEP_MM1, &Mm1Enabled); + } + + if (Status == VL53L1_ERROR_NONE) { + Status = VL53L1_GetSequenceStepEnable(Dev, + VL53L1_SEQUENCESTEP_MM2, &Mm2Enabled); + } + + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_get_timeouts_us(Dev, + &PhaseCalTimeoutUs, + &MmTimeoutUs, + &TimingBudget); + + if (Status == VL53L1_ERROR_NONE) { + PresetMode = VL53L1DevDataGet(Dev, + CurrentParameters.PresetMode); + + TimingGuard = 0; + divisor = 1; + switch (PresetMode) { + case VL53L1_PRESETMODE_LITE_RANGING: + if ((Mm1Enabled == 1) || (Mm2Enabled == 1)) + TimingGuard = 5000; + else + TimingGuard = 1000; + break; + + case VL53L1_PRESETMODE_AUTONOMOUS: + FDAMaxTimingBudgetUs *= 2; + if ((Mm1Enabled == 1) || (Mm2Enabled == 1)) + TimingGuard = 26600; + else + TimingGuard = 21600; + divisor = 2; + break; + + case VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS: + FDAMaxTimingBudgetUs *= 2; + vhv = LOWPOWER_AUTO_VHV_LOOP_DURATION_US; + VL53L1_get_tuning_parm(Dev, + VL53L1_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND, + &vhv_loops); + if (vhv_loops > 0) { + vhv += vhv_loops * + LOWPOWER_AUTO_VHV_LOOP_DURATION_US; + } + TimingGuard = LOWPOWER_AUTO_OVERHEAD_BEFORE_A_RANGING + + LOWPOWER_AUTO_OVERHEAD_BETWEEN_A_B_RANGING + + vhv; + divisor = 2; + break; + + default: + /* Unsupported mode */ + Status = VL53L1_ERROR_MODE_NOT_SUPPORTED; + } + + if (MeasurementTimingBudgetMicroSeconds <= TimingGuard) + Status = VL53L1_ERROR_INVALID_PARAMS; + else { + TimingBudget = (MeasurementTimingBudgetMicroSeconds + - TimingGuard); + } + + if (Status == VL53L1_ERROR_NONE) { + if (TimingBudget > FDAMaxTimingBudgetUs) + Status = VL53L1_ERROR_INVALID_PARAMS; + else { + TimingBudget /= divisor; + Status = VL53L1_set_timeouts_us( + Dev, + PhaseCalTimeoutUs, + MmTimeoutUs, + TimingBudget); + } + + if (Status == VL53L1_ERROR_NONE) + VL53L1DevDataSet(Dev, + LLData.range_config_timeout_us, + TimingBudget); + } + } + if (Status == VL53L1_ERROR_NONE) { + VL53L1DevDataSet(Dev, + CurrentParameters.MeasurementTimingBudgetMicroSeconds, + MeasurementTimingBudgetMicroSeconds); + } + + LOG_FUNCTION_END(Status); + return Status; +} + + +VL53L1_Error VL53L1_GetMeasurementTimingBudgetMicroSeconds(VL53L1_DEV Dev, + uint32_t *pMeasurementTimingBudgetMicroSeconds) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t Mm1Enabled = 0; + uint8_t Mm2Enabled = 0; + uint32_t MmTimeoutUs = 0; + uint32_t RangeTimeoutUs = 0; + uint32_t MeasTimingBdg = 0; + uint32_t PhaseCalTimeoutUs = 0; + VL53L1_PresetModes PresetMode; + uint32_t TimingGuard; + uint32_t vhv; + int32_t vhv_loops; + + LOG_FUNCTION_START(""); + + *pMeasurementTimingBudgetMicroSeconds = 0; + + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_GetSequenceStepEnable(Dev, + VL53L1_SEQUENCESTEP_MM1, &Mm1Enabled); + + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_GetSequenceStepEnable(Dev, + VL53L1_SEQUENCESTEP_MM2, &Mm2Enabled); + + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_get_timeouts_us(Dev, + &PhaseCalTimeoutUs, + &MmTimeoutUs, + &RangeTimeoutUs); + + if (Status == VL53L1_ERROR_NONE) { + PresetMode = VL53L1DevDataGet(Dev, + CurrentParameters.PresetMode); + + switch (PresetMode) { + case VL53L1_PRESETMODE_LITE_RANGING: + if ((Mm1Enabled == 1) || (Mm2Enabled == 1)) + MeasTimingBdg = RangeTimeoutUs + 5000; + else + MeasTimingBdg = RangeTimeoutUs + 1000; + + break; + + case VL53L1_PRESETMODE_AUTONOMOUS: + if ((Mm1Enabled == 1) || (Mm2Enabled == 1)) + MeasTimingBdg = 2 * RangeTimeoutUs + 26600; + else + MeasTimingBdg = 2 * RangeTimeoutUs + 21600; + + break; + + case VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS: + vhv = LOWPOWER_AUTO_VHV_LOOP_DURATION_US; + VL53L1_get_tuning_parm(Dev, + VL53L1_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND, + &vhv_loops); + if (vhv_loops > 0) { + vhv += vhv_loops * + LOWPOWER_AUTO_VHV_LOOP_DURATION_US; + } + TimingGuard = LOWPOWER_AUTO_OVERHEAD_BEFORE_A_RANGING + + LOWPOWER_AUTO_OVERHEAD_BETWEEN_A_B_RANGING + + vhv; + MeasTimingBdg = 2 * RangeTimeoutUs + TimingGuard; + break; + + default: + /* Unsupported mode */ + Status = VL53L1_ERROR_MODE_NOT_SUPPORTED; + } + } + if (Status == VL53L1_ERROR_NONE) + *pMeasurementTimingBudgetMicroSeconds = MeasTimingBdg; + + LOG_FUNCTION_END(Status); + return Status; +} + + + +VL53L1_Error VL53L1_SetInterMeasurementPeriodMilliSeconds(VL53L1_DEV Dev, + uint32_t InterMeasurementPeriodMilliSeconds) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint32_t adjustedIMP; + + LOG_FUNCTION_START(""); + + /* Fix for Ticket 468205 actual measurement period shorter than set */ + adjustedIMP = InterMeasurementPeriodMilliSeconds; + adjustedIMP += (adjustedIMP * 64) / 1000; + /* End of fix for Ticket 468205 */ + Status = VL53L1_set_inter_measurement_period_ms(Dev, + adjustedIMP); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetInterMeasurementPeriodMilliSeconds(VL53L1_DEV Dev, + uint32_t *pInterMeasurementPeriodMilliSeconds) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint32_t adjustedIMP; + + LOG_FUNCTION_START(""); + + Status = VL53L1_get_inter_measurement_period_ms(Dev, &adjustedIMP); + /* Fix for Ticket 468205 actual measurement period shorter than set */ + adjustedIMP -= (adjustedIMP * 64) / 1000; + *pInterMeasurementPeriodMilliSeconds = adjustedIMP; + /* End of fix for Ticket 468205 */ + + LOG_FUNCTION_END(Status); + return Status; +} + + +/* End Group PAL Parameters Functions */ + + +/* Group Limit check Functions */ + +VL53L1_Error VL53L1_GetNumberOfLimitCheck(uint16_t *pNumberOfLimitCheck) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + *pNumberOfLimitCheck = VL53L1_CHECKENABLE_NUMBER_OF_CHECKS; + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetLimitCheckInfo(uint16_t LimitCheckId, + char *pLimitCheckString) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + Status = VL53L1_get_limit_check_info(LimitCheckId, + pLimitCheckString); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetLimitCheckStatus(VL53L1_DEV Dev, uint16_t LimitCheckId, + uint8_t *pLimitCheckStatus) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t Temp8; + + LOG_FUNCTION_START(""); + + if (LimitCheckId >= VL53L1_CHECKENABLE_NUMBER_OF_CHECKS) { + Status = VL53L1_ERROR_INVALID_PARAMS; + } else { + VL53L1_GETARRAYPARAMETERFIELD(Dev, LimitChecksStatus, + LimitCheckId, Temp8); + *pLimitCheckStatus = Temp8; + } + + LOG_FUNCTION_END(Status); + return Status; +} + +static VL53L1_Error SetLimitValue(VL53L1_DEV Dev, uint16_t LimitCheckId, + FixPoint1616_t value) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint16_t tmpuint16; /* temporary variable */ + + LOG_FUNCTION_START(""); + + switch (LimitCheckId) { + case VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE: + tmpuint16 = VL53L1_FIXPOINT1616TOFIXPOINT142(value); + VL53L1_set_lite_sigma_threshold(Dev, tmpuint16); + break; + case VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: + tmpuint16 = VL53L1_FIXPOINT1616TOFIXPOINT97(value); + VL53L1_set_lite_min_count_rate(Dev, tmpuint16); + break; + default: + Status = VL53L1_ERROR_INVALID_PARAMS; + } + + LOG_FUNCTION_END(Status); + return Status; +} + + +VL53L1_Error VL53L1_SetLimitCheckEnable(VL53L1_DEV Dev, uint16_t LimitCheckId, + uint8_t LimitCheckEnable) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + FixPoint1616_t TempFix1616 = 0; + + LOG_FUNCTION_START(""); + + + if (LimitCheckId >= VL53L1_CHECKENABLE_NUMBER_OF_CHECKS) { + Status = VL53L1_ERROR_INVALID_PARAMS; + } else { + /* TempFix1616 contains either 0 or the limit value */ + if (LimitCheckEnable == 0) + TempFix1616 = 0; + else + VL53L1_GETARRAYPARAMETERFIELD(Dev, LimitChecksValue, + LimitCheckId, TempFix1616); + + Status = SetLimitValue(Dev, LimitCheckId, TempFix1616); + } + + if (Status == VL53L1_ERROR_NONE) + VL53L1_SETARRAYPARAMETERFIELD(Dev, + LimitChecksEnable, + LimitCheckId, + ((LimitCheckEnable == 0) ? 0 : 1)); + + + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetLimitCheckEnable(VL53L1_DEV Dev, uint16_t LimitCheckId, + uint8_t *pLimitCheckEnable) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t Temp8; + + LOG_FUNCTION_START(""); + + if (LimitCheckId >= VL53L1_CHECKENABLE_NUMBER_OF_CHECKS) { + Status = VL53L1_ERROR_INVALID_PARAMS; + *pLimitCheckEnable = 0; + } else { + VL53L1_GETARRAYPARAMETERFIELD(Dev, LimitChecksEnable, + LimitCheckId, Temp8); + *pLimitCheckEnable = Temp8; + } + + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_SetLimitCheckValue(VL53L1_DEV Dev, uint16_t LimitCheckId, + FixPoint1616_t LimitCheckValue) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t LimitChecksEnable; + + LOG_FUNCTION_START(""); + + if (LimitCheckId >= VL53L1_CHECKENABLE_NUMBER_OF_CHECKS) { + Status = VL53L1_ERROR_INVALID_PARAMS; + } else { + + VL53L1_GETARRAYPARAMETERFIELD(Dev, LimitChecksEnable, + LimitCheckId, + LimitChecksEnable); + + if (LimitChecksEnable == 0) { + /* disabled write only internal value */ + VL53L1_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue, + LimitCheckId, LimitCheckValue); + } else { + + Status = SetLimitValue(Dev, LimitCheckId, + LimitCheckValue); + + if (Status == VL53L1_ERROR_NONE) { + VL53L1_SETARRAYPARAMETERFIELD(Dev, + LimitChecksValue, + LimitCheckId, LimitCheckValue); + } + } + } + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetLimitCheckValue(VL53L1_DEV Dev, uint16_t LimitCheckId, + FixPoint1616_t *pLimitCheckValue) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint16_t MinCountRate; + FixPoint1616_t TempFix1616 = 0; + uint16_t SigmaThresh; + + LOG_FUNCTION_START(""); + + switch (LimitCheckId) { + case VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE: + Status = VL53L1_get_lite_sigma_threshold(Dev, &SigmaThresh); + TempFix1616 = VL53L1_FIXPOINT142TOFIXPOINT1616(SigmaThresh); + break; + case VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: + Status = VL53L1_get_lite_min_count_rate(Dev, &MinCountRate); + TempFix1616 = VL53L1_FIXPOINT97TOFIXPOINT1616(MinCountRate); + break; + default: + Status = VL53L1_ERROR_INVALID_PARAMS; + } + + if (Status == VL53L1_ERROR_NONE) { + + if (TempFix1616 == 0) { + /* disabled: return value from memory */ + VL53L1_GETARRAYPARAMETERFIELD(Dev, + LimitChecksValue, LimitCheckId, + TempFix1616); + *pLimitCheckValue = TempFix1616; + VL53L1_SETARRAYPARAMETERFIELD(Dev, + LimitChecksEnable, LimitCheckId, 0); + } else { + *pLimitCheckValue = TempFix1616; + VL53L1_SETARRAYPARAMETERFIELD(Dev, + LimitChecksValue, LimitCheckId, + TempFix1616); + VL53L1_SETARRAYPARAMETERFIELD(Dev, + LimitChecksEnable, LimitCheckId, 1); + } + } + LOG_FUNCTION_END(Status); + return Status; + +} + +VL53L1_Error VL53L1_GetLimitCheckCurrent(VL53L1_DEV Dev, uint16_t LimitCheckId, + FixPoint1616_t *pLimitCheckCurrent) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + FixPoint1616_t TempFix1616 = 0; + + LOG_FUNCTION_START(""); + + if (LimitCheckId >= VL53L1_CHECKENABLE_NUMBER_OF_CHECKS) { + Status = VL53L1_ERROR_INVALID_PARAMS; + } else { + VL53L1_GETARRAYPARAMETERFIELD(Dev, LimitChecksCurrent, + LimitCheckId, TempFix1616); + *pLimitCheckCurrent = TempFix1616; + } + + LOG_FUNCTION_END(Status); + return Status; + +} + +/* End Group Limit check Functions */ + + + +/* Group ROI Functions */ + +VL53L1_Error VL53L1_SetUserROI(VL53L1_DEV Dev, + VL53L1_UserRoi_t *pRoi) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_user_zone_t user_zone; + + Status = CheckValidRectRoi(*pRoi); + if (Status != VL53L1_ERROR_NONE) + return VL53L1_ERROR_INVALID_PARAMS; + + user_zone.x_centre = (pRoi->BotRightX + pRoi->TopLeftX + 1) / 2; + user_zone.y_centre = (pRoi->TopLeftY + pRoi->BotRightY + 1) / 2; + user_zone.width = (pRoi->BotRightX - pRoi->TopLeftX); + user_zone.height = (pRoi->TopLeftY - pRoi->BotRightY); + if ((user_zone.width < 3) || (user_zone.height < 3)) + Status = VL53L1_ERROR_INVALID_PARAMS; + else + Status = VL53L1_set_user_zone(Dev, &user_zone); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetUserROI(VL53L1_DEV Dev, + VL53L1_UserRoi_t *pRoi) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_user_zone_t user_zone; + + Status = VL53L1_get_user_zone(Dev, &user_zone); + + pRoi->TopLeftX = (2 * user_zone.x_centre - user_zone.width) >> 1; + pRoi->TopLeftY = (2 * user_zone.y_centre + user_zone.height) >> 1; + pRoi->BotRightX = (2 * user_zone.x_centre + user_zone.width) >> 1; + pRoi->BotRightY = (2 * user_zone.y_centre - user_zone.height) >> 1; + + LOG_FUNCTION_END(Status); + return Status; +} + + + +/* End Group ROI Functions */ + + +/* Group Sequence Step Functions */ + +VL53L1_Error VL53L1_GetNumberOfSequenceSteps(VL53L1_DEV Dev, + uint8_t *pNumberOfSequenceSteps) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + SUPPRESS_UNUSED_WARNING(Dev); + + LOG_FUNCTION_START(""); + + *pNumberOfSequenceSteps = VL53L1_SEQUENCESTEP_NUMBER_OF_ITEMS; + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetSequenceStepsInfo(VL53L1_SequenceStepId SequenceStepId, + char *pSequenceStepsString) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + Status = VL53L1_get_sequence_steps_info( + SequenceStepId, + pSequenceStepsString); + + LOG_FUNCTION_END(Status); + + return Status; +} + +VL53L1_Error VL53L1_SetSequenceStepEnable(VL53L1_DEV Dev, + VL53L1_SequenceStepId SequenceStepId, uint8_t SequenceStepEnabled) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint32_t MeasurementTimingBudgetMicroSeconds; + + LOG_FUNCTION_START(""); + + /* the VL53L1_SequenceStepId correspond to the LLD + * VL53L1_DeviceSequenceConfig + */ + + Status = VL53L1_set_sequence_config_bit(Dev, + (VL53L1_DeviceSequenceConfig)SequenceStepId, + SequenceStepEnabled); + + /* Apply New Setting */ + if (Status == VL53L1_ERROR_NONE) { + + /* Recalculate timing budget */ + MeasurementTimingBudgetMicroSeconds = VL53L1DevDataGet(Dev, + CurrentParameters.MeasurementTimingBudgetMicroSeconds); + + VL53L1_SetMeasurementTimingBudgetMicroSeconds(Dev, + MeasurementTimingBudgetMicroSeconds); + } + + LOG_FUNCTION_END(Status); + + return Status; +} + + +VL53L1_Error VL53L1_GetSequenceStepEnable(VL53L1_DEV Dev, + VL53L1_SequenceStepId SequenceStepId, uint8_t *pSequenceStepEnabled) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + Status = VL53L1_get_sequence_config_bit(Dev, + (VL53L1_DeviceSequenceConfig)SequenceStepId, + pSequenceStepEnabled); + + LOG_FUNCTION_END(Status); + return Status; +} + + +/* End Group Sequence Step Functions Functions */ + + + +/* Group PAL Measurement Functions */ + + + +VL53L1_Error VL53L1_StartMeasurement(VL53L1_DEV Dev) +{ +#define TIMED_MODE_TIMING_GUARD_MILLISECONDS 4 + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t DeviceMeasurementMode; + VL53L1_State CurrPalState; + VL53L1_Error lStatus; + uint32_t MTBus, IMPms; + + + LOG_FUNCTION_START(""); + + DeviceMeasurementMode = VL53L1DevDataGet(Dev, LLData.measurement_mode); + if (DeviceMeasurementMode != VL53L1_DEVICEMEASUREMENTMODE_TIMED) + VL53L1_LoadPatch(Dev); + CurrPalState = VL53L1DevDataGet(Dev, PalState); + switch (CurrPalState) { + case VL53L1_STATE_IDLE: + Status = VL53L1_ERROR_NONE; + break; + case VL53L1_STATE_POWERDOWN: + case VL53L1_STATE_WAIT_STATICINIT: + case VL53L1_STATE_STANDBY: + case VL53L1_STATE_RUNNING: + case VL53L1_STATE_RESET: + case VL53L1_STATE_UNKNOWN: + case VL53L1_STATE_ERROR: + Status = VL53L1_ERROR_INVALID_COMMAND; + break; + default: + Status = VL53L1_ERROR_UNDEFINED; + } + + /* Check timing configuration between timing budget and + * inter measurement period */ + if ((Status == VL53L1_ERROR_NONE) && + (DeviceMeasurementMode == VL53L1_DEVICEMEASUREMENTMODE_TIMED)) { + lStatus = VL53L1_GetMeasurementTimingBudgetMicroSeconds(Dev, + &MTBus); + /* convert timing budget in ms */ + MTBus /= 1000; + lStatus = VL53L1_GetInterMeasurementPeriodMilliSeconds(Dev, + &IMPms); + /* trick to get rid of compiler "set but not used" warning */ + SUPPRESS_UNUSED_WARNING(lStatus); + if (IMPms < MTBus + TIMED_MODE_TIMING_GUARD_MILLISECONDS) + Status = VL53L1_ERROR_INVALID_PARAMS; + } + + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_init_and_start_range( + Dev, + DeviceMeasurementMode, + VL53L1_DEVICECONFIGLEVEL_FULL); + + /* Set PAL State to Running */ + if (Status == VL53L1_ERROR_NONE) + VL53L1DevDataSet(Dev, PalState, VL53L1_STATE_RUNNING); + + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_StopMeasurement(VL53L1_DEV Dev) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t DeviceMeasurementMode; + + LOG_FUNCTION_START(""); + + Status = VL53L1_stop_range(Dev); + DeviceMeasurementMode = VL53L1DevDataGet(Dev, LLData.measurement_mode); + if (DeviceMeasurementMode != VL53L1_DEVICEMEASUREMENTMODE_TIMED) + VL53L1_UnloadPatch(Dev); + /* Set PAL State to Idle */ + if (Status == VL53L1_ERROR_NONE) + VL53L1DevDataSet(Dev, PalState, VL53L1_STATE_IDLE); + + LOG_FUNCTION_END(Status); + return Status; +} + + +VL53L1_Error VL53L1_ClearInterruptAndStartMeasurement(VL53L1_DEV Dev) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t DeviceMeasurementMode; + + LOG_FUNCTION_START(""); + + DeviceMeasurementMode = VL53L1DevDataGet(Dev, LLData.measurement_mode); + + Status = VL53L1_clear_interrupt_and_enable_next_range(Dev, + DeviceMeasurementMode); + + LOG_FUNCTION_END(Status); + return Status; +} + + +VL53L1_Error VL53L1_GetMeasurementDataReady(VL53L1_DEV Dev, + uint8_t *pMeasurementDataReady) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + Status = VL53L1_is_new_data_ready(Dev, pMeasurementDataReady); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_WaitMeasurementDataReady(VL53L1_DEV Dev) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Note that the timeout is given by: + * VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS defined in def.h + */ + + Status = VL53L1_poll_for_range_completion(Dev, + VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS); + + LOG_FUNCTION_END(Status); + return Status; +} + + + +static uint8_t ComputeRQL(uint8_t active_results, + uint8_t FilteredRangeStatus, + VL53L1_range_data_t *presults_data) +{ + int16_t SRL = 300; + uint16_t SRAS = 30; + FixPoint1616_t RAS; + FixPoint1616_t SRQL; + FixPoint1616_t GI = 7713587; /* 117.7 * 65536 */ + FixPoint1616_t GGm = 3198157; /* 48.8 * 65536 */ + FixPoint1616_t LRAP = 6554; /* 0.1 * 65536 */ + FixPoint1616_t partial; + uint8_t finalvalue; + uint8_t returnvalue; + + if (active_results == 0) + returnvalue = 0; + else if (FilteredRangeStatus == VL53L1_DEVICEERROR_PHASECONSISTENCY) + returnvalue = 50; + else { + if (presults_data->median_range_mm < SRL) + RAS = SRAS * 65536; + else + RAS = LRAP * presults_data->median_range_mm; + + /* Fix1616 + (fix1616 * uint16_t / fix1616) * 65536 = fix1616 */ + if (RAS != 0) { + partial = (GGm * presults_data->sigma_mm); + partial = partial + (RAS >> 1); + partial = partial / RAS; + partial = partial * 65536; + if (partial <= GI) + SRQL = GI - partial; + else + SRQL = 50 * 65536; + } else + SRQL = 100 * 65536; + + finalvalue = (uint8_t)(SRQL >> 16); + returnvalue = MAX(50, MIN(100, finalvalue)); + } + + return returnvalue; +} + + +static uint8_t ConvertStatusLite(uint8_t FilteredRangeStatus) +{ + uint8_t RangeStatus; + + switch (FilteredRangeStatus) { + case VL53L1_DEVICEERROR_GPHSTREAMCOUNT0READY: + RangeStatus = VL53L1_RANGESTATUS_SYNCRONISATION_INT; + break; + case VL53L1_DEVICEERROR_RANGECOMPLETE_NO_WRAP_CHECK: + RangeStatus = VL53L1_RANGESTATUS_RANGE_VALID_NO_WRAP_CHECK_FAIL; + break; + case VL53L1_DEVICEERROR_RANGEPHASECHECK: + RangeStatus = VL53L1_RANGESTATUS_OUTOFBOUNDS_FAIL; + break; + case VL53L1_DEVICEERROR_MSRCNOTARGET: + RangeStatus = VL53L1_RANGESTATUS_SIGNAL_FAIL; + break; + case VL53L1_DEVICEERROR_SIGMATHRESHOLDCHECK: + RangeStatus = VL53L1_RANGESTATUS_SIGMA_FAIL; + break; + case VL53L1_DEVICEERROR_PHASECONSISTENCY: + RangeStatus = VL53L1_RANGESTATUS_WRAP_TARGET_FAIL; + break; + case VL53L1_DEVICEERROR_RANGEIGNORETHRESHOLD: + RangeStatus = VL53L1_RANGESTATUS_XTALK_SIGNAL_FAIL; + break; + case VL53L1_DEVICEERROR_MINCLIP: + RangeStatus = VL53L1_RANGESTATUS_RANGE_VALID_MIN_RANGE_CLIPPED; + break; + case VL53L1_DEVICEERROR_RANGECOMPLETE: + RangeStatus = VL53L1_RANGESTATUS_RANGE_VALID; + break; + default: + RangeStatus = VL53L1_RANGESTATUS_NONE; + } + + return RangeStatus; +} + + + +static VL53L1_Error SetSimpleData(VL53L1_DEV Dev, + uint8_t active_results, uint8_t device_status, + VL53L1_range_data_t *presults_data, + VL53L1_RangingMeasurementData_t *pRangeData) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t FilteredRangeStatus; + uint8_t SigmaLimitflag; + uint8_t SignalLimitflag; + uint8_t Temp8Enable; + uint8_t Temp8; + FixPoint1616_t AmbientRate; + FixPoint1616_t SignalRate; + FixPoint1616_t TempFix1616; + FixPoint1616_t LimitCheckValue; + int16_t Range; + + pRangeData->TimeStamp = presults_data->time_stamp; + + FilteredRangeStatus = presults_data->range_status & 0x1F; + + pRangeData->RangeQualityLevel = ComputeRQL(active_results, + FilteredRangeStatus, + presults_data); + + SignalRate = VL53L1_FIXPOINT97TOFIXPOINT1616( + presults_data->peak_signal_count_rate_mcps); + pRangeData->SignalRateRtnMegaCps + = SignalRate; + + AmbientRate = VL53L1_FIXPOINT97TOFIXPOINT1616( + presults_data->ambient_count_rate_mcps); + pRangeData->AmbientRateRtnMegaCps = AmbientRate; + + pRangeData->EffectiveSpadRtnCount = + presults_data->actual_effective_spads; + + TempFix1616 = VL53L1_FIXPOINT97TOFIXPOINT1616( + presults_data->sigma_mm); + + pRangeData->SigmaMilliMeter = TempFix1616; + + pRangeData->RangeMilliMeter = presults_data->median_range_mm; + + pRangeData->RangeFractionalPart = 0; + + /* Treat device error status first */ + switch (device_status) { + case VL53L1_DEVICEERROR_MULTCLIPFAIL: + case VL53L1_DEVICEERROR_VCSELWATCHDOGTESTFAILURE: + case VL53L1_DEVICEERROR_VCSELCONTINUITYTESTFAILURE: + case VL53L1_DEVICEERROR_NOVHVVALUEFOUND: + pRangeData->RangeStatus = VL53L1_RANGESTATUS_HARDWARE_FAIL; + break; + case VL53L1_DEVICEERROR_USERROICLIP: + pRangeData->RangeStatus = VL53L1_RANGESTATUS_MIN_RANGE_FAIL; + break; + default: + pRangeData->RangeStatus = VL53L1_RANGESTATUS_RANGE_VALID; + } + + /* Now deal with range status according to the ranging preset */ + if (pRangeData->RangeStatus == VL53L1_RANGESTATUS_RANGE_VALID) { + pRangeData->RangeStatus = + ConvertStatusLite(FilteredRangeStatus); + } + + /* Update current Limit Check */ + TempFix1616 = VL53L1_FIXPOINT97TOFIXPOINT1616( + presults_data->sigma_mm); + VL53L1_SETARRAYPARAMETERFIELD(Dev, + LimitChecksCurrent, VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE, + TempFix1616); + + TempFix1616 = VL53L1_FIXPOINT97TOFIXPOINT1616( + presults_data->peak_signal_count_rate_mcps); + VL53L1_SETARRAYPARAMETERFIELD(Dev, + LimitChecksCurrent, VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, + TempFix1616); + + /* Update Limit Check Status */ + /* Sigma */ + VL53L1_GetLimitCheckValue(Dev, + VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE, + &LimitCheckValue); + + SigmaLimitflag = (FilteredRangeStatus == + VL53L1_DEVICEERROR_SIGMATHRESHOLDCHECK) + ? 1 : 0; + + VL53L1_GetLimitCheckEnable(Dev, + VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE, + &Temp8Enable); + + Temp8 = ((Temp8Enable == 1) && (SigmaLimitflag == 1)) ? 1 : 0; + VL53L1_SETARRAYPARAMETERFIELD(Dev, LimitChecksStatus, + VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE, Temp8); + + /* Signal Rate */ + VL53L1_GetLimitCheckValue(Dev, + VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, + &LimitCheckValue); + + SignalLimitflag = (FilteredRangeStatus == + VL53L1_DEVICEERROR_MSRCNOTARGET) + ? 1 : 0; + + VL53L1_GetLimitCheckEnable(Dev, + VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, + &Temp8Enable); + + Temp8 = ((Temp8Enable == 1) && (SignalLimitflag == 1)) ? 1 : 0; + VL53L1_SETARRAYPARAMETERFIELD(Dev, LimitChecksStatus, + VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, Temp8); + + Range = pRangeData->RangeMilliMeter; + if ((pRangeData->RangeStatus == VL53L1_RANGESTATUS_RANGE_VALID) && + (Range < 0)) { + if (Range < BDTable[VL53L1_TUNING_PROXY_MIN]) + pRangeData->RangeStatus = + VL53L1_RANGESTATUS_RANGE_INVALID; + else + pRangeData->RangeMilliMeter = 0; + } + + return Status; +} + + + +VL53L1_Error VL53L1_GetRangingMeasurementData(VL53L1_DEV Dev, + VL53L1_RangingMeasurementData_t *pRangingMeasurementData) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_range_results_t results; + VL53L1_range_results_t *presults = &results; + VL53L1_range_data_t *presults_data; + + LOG_FUNCTION_START(""); + + + /* Clear Ranging Data */ + memset(pRangingMeasurementData, 0xFF, + sizeof(VL53L1_RangingMeasurementData_t)); + + /* Get Ranging Data */ + Status = VL53L1_get_device_results( + Dev, + VL53L1_DEVICERESULTSLEVEL_FULL, + presults); + + if (Status == VL53L1_ERROR_NONE) { + pRangingMeasurementData->StreamCount = presults->stream_count; + + /* in case of lite ranging or autonomous the following function + * returns index = 0 + */ + presults_data = &(presults->data[0]); + Status = SetSimpleData(Dev, 1, + presults->device_status, + presults_data, + pRangingMeasurementData); + } + + LOG_FUNCTION_END(Status); + return Status; +} + + + + + +/* End Group PAL Measurement Functions */ + + +/* Group Calibration functions */ +VL53L1_Error VL53L1_SetTuningParameter(VL53L1_DEV Dev, + uint16_t TuningParameterId, int32_t TuningParameterValue) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + if (TuningParameterId >= 32768) + Status = VL53L1_set_tuning_parm(Dev, + TuningParameterId, + TuningParameterValue); + else { + if (TuningParameterId < VL53L1_TUNING_MAX_TUNABLE_KEY) + BDTable[TuningParameterId] = TuningParameterValue; + else + Status = VL53L1_ERROR_INVALID_PARAMS; + } + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_GetTuningParameter(VL53L1_DEV Dev, + uint16_t TuningParameterId, int32_t *pTuningParameterValue) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (TuningParameterId >= 32768) + Status = VL53L1_get_tuning_parm(Dev, + TuningParameterId, + pTuningParameterValue); + else { + if (TuningParameterId < VL53L1_TUNING_MAX_TUNABLE_KEY) + *pTuningParameterValue = BDTable[TuningParameterId]; + else + Status = VL53L1_ERROR_INVALID_PARAMS; + } + + LOG_FUNCTION_END(Status); + return Status; +} + + +VL53L1_Error VL53L1_PerformRefSpadManagement(VL53L1_DEV Dev) +{ +#ifdef VL53L1_NOCALIB + VL53L1_Error Status = VL53L1_ERROR_NOT_SUPPORTED; + + SUPPRESS_UNUSED_WARNING(Dev); + + LOG_FUNCTION_START(""); +#else + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_Error RawStatus; + uint8_t dcrbuffer[24]; + uint8_t *commbuf; + uint8_t numloc[2] = {5, 3}; + VL53L1_LLDriverData_t *pdev; + VL53L1_customer_nvm_managed_t *pc; + VL53L1_PresetModes PresetMode; + + LOG_FUNCTION_START(""); + + pdev = VL53L1DevStructGetLLDriverHandle(Dev); + pc = &pdev->customer; + + if (Status == VL53L1_ERROR_NONE) { + PresetMode = VL53L1DevDataGet(Dev, + CurrentParameters.PresetMode); + Status = VL53L1_run_ref_spad_char(Dev, &RawStatus); + /* We discovered RefSpad mngt badly breaks some preset mode + * The WA is to apply again the current one + */ + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_SetPresetMode(Dev, PresetMode); + } + + if (Status == VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH) { + /* Fix ticket #466282 RefSpad management error/warning -29 + * force usage of location 3 and 5 refspads in registers + */ + Status = VL53L1_read_nvm_raw_data(Dev, + (uint8_t)(0xA0 >> 2), + (uint8_t)(24 >> 2), + dcrbuffer); + + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_WriteMulti(Dev, + VL53L1_REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS, + numloc, 2); + + if (Status == VL53L1_ERROR_NONE) { + pc->ref_spad_man__num_requested_ref_spads = numloc[0]; + pc->ref_spad_man__ref_location = numloc[1]; + } + + commbuf = &dcrbuffer[16]; + /* + * update & copy reference SPAD enables to customer nvm managed + */ + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_WriteMulti(Dev, + VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_0, + commbuf, 6); + + if (Status == VL53L1_ERROR_NONE) { + pc->global_config__spad_enables_ref_0 = commbuf[0]; + pc->global_config__spad_enables_ref_1 = commbuf[1]; + pc->global_config__spad_enables_ref_2 = commbuf[2]; + pc->global_config__spad_enables_ref_3 = commbuf[3]; + pc->global_config__spad_enables_ref_4 = commbuf[4]; + pc->global_config__spad_enables_ref_5 = commbuf[5]; + } + /* End of fix ticket #466282 */ + } + +#endif + + LOG_FUNCTION_END(Status); + return Status; +} + + +VL53L1_Error VL53L1_SetXTalkCompensationEnable(VL53L1_DEV Dev, + uint8_t XTalkCompensationEnable) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (XTalkCompensationEnable == 0) + Status = VL53L1_disable_xtalk_compensation(Dev); + else + Status = VL53L1_enable_xtalk_compensation(Dev); + + LOG_FUNCTION_END(Status); + return Status; +} + + +VL53L1_Error VL53L1_GetXTalkCompensationEnable(VL53L1_DEV Dev, + uint8_t *pXTalkCompensationEnable) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + VL53L1_get_xtalk_compensation_enable( + Dev, + pXTalkCompensationEnable); + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_PerformSingleTargetXTalkCalibration(VL53L1_DEV Dev, + int32_t CalDistanceMilliMeter) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (CalDistanceMilliMeter > 0) { + BDTable[VL53L1_TUNING_SINGLE_TARGET_XTALK_TARGET_DISTANCE_MM] = + CalDistanceMilliMeter; + Status = SingleTargetXTalkCalibration(Dev); + } else + Status = VL53L1_ERROR_INVALID_PARAMS; + + LOG_FUNCTION_END(Status); + return Status; +} + + + + + +VL53L1_Error VL53L1_PerformOffsetSimpleCalibration(VL53L1_DEV Dev, + int32_t CalDistanceMilliMeter) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + int32_t sum_ranging; + uint8_t offset_meas; + int16_t Max, UnderMax, OverMax, Repeat; + int32_t total_count, inloopcount; + int32_t IncRounding; + int16_t meanDistance_mm; + int16_t offset; + VL53L1_RangingMeasurementData_t RangingMeasurementData; + VL53L1_LLDriverData_t *pdev; + uint8_t goodmeas; + + LOG_FUNCTION_START(""); + + pdev = VL53L1DevStructGetLLDriverHandle(Dev); + /* Disable any offsets */ + pdev->customer.algo__part_to_part_range_offset_mm = 0; + pdev->customer.mm_config__inner_offset_mm = 0; + pdev->customer.mm_config__outer_offset_mm = 0; + Repeat = BDTable[VL53L1_TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT]; + Max = BDTable[ + VL53L1_TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER]; + UnderMax = 1 + (Max / 2); + OverMax = Max + (Max / 2); + sum_ranging = 0; + total_count = 0; + + while ((Repeat > 0) && (Status == VL53L1_ERROR_NONE)) { + Status = VL53L1_StartMeasurement(Dev); + /* Very first ranging completion interrupt must be ignored */ + if (Status == VL53L1_ERROR_NONE) { + VL53L1_WaitMeasurementDataReady(Dev); + VL53L1_GetRangingMeasurementData(Dev, + &RangingMeasurementData); + VL53L1_ClearInterruptAndStartMeasurement(Dev); + } + /* offset calibration main loop */ + inloopcount = 0; + offset_meas = 0; + while ((Status == VL53L1_ERROR_NONE) && (inloopcount < Max) && + (offset_meas < OverMax)) { + Status = VL53L1_WaitMeasurementDataReady(Dev); + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_GetRangingMeasurementData(Dev, + &RangingMeasurementData); + goodmeas = (RangingMeasurementData.RangeStatus == + VL53L1_RANGESTATUS_RANGE_VALID); + if ((Status == VL53L1_ERROR_NONE) && goodmeas) { + sum_ranging = sum_ranging + + RangingMeasurementData.RangeMilliMeter; + inloopcount++; + } + Status = VL53L1_ClearInterruptAndStartMeasurement(Dev); + offset_meas++; + } + total_count += inloopcount; + + /* no enough valid values found */ + if (inloopcount < UnderMax) + Status = VL53L1_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL; + + VL53L1_StopMeasurement(Dev); + + Repeat--; + + } + /* check overflow (unlikely if target is near to the device) */ + if ((sum_ranging < 0) || + (sum_ranging > ((int32_t) total_count * 0xffff))) + Status = VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH; + + if ((Status == VL53L1_ERROR_NONE) && (total_count > 0)) { + IncRounding = total_count / 2; + meanDistance_mm = (int16_t)((sum_ranging + IncRounding) + / total_count); + offset = (int16_t)CalDistanceMilliMeter - meanDistance_mm; + pdev->customer.algo__part_to_part_range_offset_mm = 0; + pdev->customer.mm_config__inner_offset_mm = offset; + pdev->customer.mm_config__outer_offset_mm = offset; + + Status = VL53L1_set_customer_nvm_managed(Dev, + &(pdev->customer)); + } + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_PerformOffsetZeroDistanceCalibration(VL53L1_DEV Dev) +{ + #define START_OFFSET 50 + VL53L1_Error Status = VL53L1_ERROR_NONE; + int32_t sum_ranging; + uint8_t offset_meas; + int16_t Max, UnderMax, OverMax, Repeat; + int32_t total_count, inloopcount; + int32_t IncRounding; + int16_t meanDistance_mm; + int16_t offset, ZeroDistanceOffset; + VL53L1_RangingMeasurementData_t RangingMeasurementData; + VL53L1_LLDriverData_t *pdev; + uint8_t goodmeas; + + LOG_FUNCTION_START(""); + + pdev = VL53L1DevStructGetLLDriverHandle(Dev); + pdev->customer.algo__part_to_part_range_offset_mm = 0; + pdev->customer.mm_config__inner_offset_mm = START_OFFSET; + pdev->customer.mm_config__outer_offset_mm = START_OFFSET; + ZeroDistanceOffset = BDTable[ + VL53L1_TUNING_ZERO_DISTANCE_OFFSET_NON_LINEAR_FACTOR]; + Repeat = BDTable[VL53L1_TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT]; + Max = BDTable[ + VL53L1_TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER]; + UnderMax = 1 + (Max / 2); + OverMax = Max + (Max / 2); + sum_ranging = 0; + total_count = 0; + + while ((Repeat > 0) && (Status == VL53L1_ERROR_NONE)) { + Status = VL53L1_StartMeasurement(Dev); + if (Status == VL53L1_ERROR_NONE) { + VL53L1_WaitMeasurementDataReady(Dev); + VL53L1_GetRangingMeasurementData(Dev, + &RangingMeasurementData); + VL53L1_ClearInterruptAndStartMeasurement(Dev); + } + inloopcount = 0; + offset_meas = 0; + while ((Status == VL53L1_ERROR_NONE) && (inloopcount < Max) && + (offset_meas < OverMax)) { + Status = VL53L1_WaitMeasurementDataReady(Dev); + if (Status == VL53L1_ERROR_NONE) + Status = VL53L1_GetRangingMeasurementData(Dev, + &RangingMeasurementData); + goodmeas = (RangingMeasurementData.RangeStatus == + VL53L1_RANGESTATUS_RANGE_VALID); + if ((Status == VL53L1_ERROR_NONE) && goodmeas) { + sum_ranging = sum_ranging + + RangingMeasurementData.RangeMilliMeter; + inloopcount++; + } + Status = VL53L1_ClearInterruptAndStartMeasurement(Dev); + offset_meas++; + } + total_count += inloopcount; + if (inloopcount < UnderMax) + Status = VL53L1_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL; + VL53L1_StopMeasurement(Dev); + Repeat--; + } + if ((sum_ranging < 0) || + (sum_ranging > ((int32_t) total_count * 0xffff))) + Status = VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH; + + if ((Status == VL53L1_ERROR_NONE) && (total_count > 0)) { + IncRounding = total_count / 2; + meanDistance_mm = (int16_t) + ((sum_ranging + IncRounding) / total_count); + offset = START_OFFSET - meanDistance_mm + ZeroDistanceOffset; + pdev->customer.algo__part_to_part_range_offset_mm = 0; + pdev->customer.mm_config__inner_offset_mm = offset; + pdev->customer.mm_config__outer_offset_mm = offset; + Status = VL53L1_set_customer_nvm_managed(Dev, + &(pdev->customer)); + } + + LOG_FUNCTION_END(Status); + return Status; +} + +VL53L1_Error VL53L1_SetCalibrationData(VL53L1_DEV Dev, + VL53L1_CalibrationData_t *pCalibrationData) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_CustomerNvmManaged_t *pC; + VL53L1_calibration_data_t cal_data; + uint32_t x, IncomeVersion, CurrentVersion; + + LOG_FUNCTION_START(""); + + cal_data.struct_version = pCalibrationData->struct_version - + VL53L1_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION; + /* adjust version for old calibration data */ + IncomeVersion = pCalibrationData->struct_version; + CurrentVersion = VL53L1_LL_CALIBRATION_DATA_STRUCT_VERSION + + VL53L1_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION; + + if ((IncomeVersion < CurrentVersion) && + ((IncomeVersion & 0xFFFFFF0F) == + (CurrentVersion & 0xFFFFFF0F))) { + cal_data.struct_version = + VL53L1_LL_CALIBRATION_DATA_STRUCT_VERSION; + } + + + /* memcpy(DEST, SRC, N) */ + memcpy( + &(cal_data.add_off_cal_data), + &(pCalibrationData->add_off_cal_data), + sizeof(VL53L1_additional_offset_cal_data_t)); + + /* memcpy (DEST, SRC, N) */ + memcpy( + &(cal_data.optical_centre), + &(pCalibrationData->optical_centre), + sizeof(VL53L1_optical_centre_t)); + + /* memcpy (DEST, SRC, N) */ + memcpy( + &(cal_data.gain_cal), + &(pCalibrationData->gain_cal), + sizeof(VL53L1_gain_calibration_data_t)); + + /* memcpy (DEST, SRC, N) */ + memcpy( + &(cal_data.cal_peak_rate_map), + &(pCalibrationData->cal_peak_rate_map), + sizeof(VL53L1_cal_peak_rate_map_t)); + + + pC = &pCalibrationData->customer; + x = pC->algo__crosstalk_compensation_plane_offset_kcps; + cal_data.customer.algo__crosstalk_compensation_plane_offset_kcps = + (uint16_t)(x&0x0000FFFF); + + cal_data.customer.global_config__spad_enables_ref_0 = + pC->global_config__spad_enables_ref_0; + cal_data.customer.global_config__spad_enables_ref_1 = + pC->global_config__spad_enables_ref_1; + cal_data.customer.global_config__spad_enables_ref_2 = + pC->global_config__spad_enables_ref_2; + cal_data.customer.global_config__spad_enables_ref_3 = + pC->global_config__spad_enables_ref_3; + cal_data.customer.global_config__spad_enables_ref_4 = + pC->global_config__spad_enables_ref_4; + cal_data.customer.global_config__spad_enables_ref_5 = + pC->global_config__spad_enables_ref_5; + cal_data.customer.global_config__ref_en_start_select = + pC->global_config__ref_en_start_select; + cal_data.customer.ref_spad_man__num_requested_ref_spads = + pC->ref_spad_man__num_requested_ref_spads; + cal_data.customer.ref_spad_man__ref_location = + pC->ref_spad_man__ref_location; + cal_data.customer.algo__crosstalk_compensation_x_plane_gradient_kcps = + pC->algo__crosstalk_compensation_x_plane_gradient_kcps; + cal_data.customer.algo__crosstalk_compensation_y_plane_gradient_kcps = + pC->algo__crosstalk_compensation_y_plane_gradient_kcps; + cal_data.customer.ref_spad_char__total_rate_target_mcps = + pC->ref_spad_char__total_rate_target_mcps; + cal_data.customer.algo__part_to_part_range_offset_mm = + pC->algo__part_to_part_range_offset_mm; + cal_data.customer.mm_config__inner_offset_mm = + pC->mm_config__inner_offset_mm; + cal_data.customer.mm_config__outer_offset_mm = + pC->mm_config__outer_offset_mm; + + Status = VL53L1_set_part_to_part_data(Dev, &cal_data); + LOG_FUNCTION_END(Status); + return Status; + +} + +VL53L1_Error VL53L1_GetCalibrationData(VL53L1_DEV Dev, + VL53L1_CalibrationData_t *pCalibrationData) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_calibration_data_t cal_data; + VL53L1_CustomerNvmManaged_t *pC; + VL53L1_customer_nvm_managed_t *pC2; + + LOG_FUNCTION_START(""); + + /* struct_version is filled inside get part to part function */ + Status = VL53L1_get_part_to_part_data(Dev, &cal_data); + + pCalibrationData->struct_version = cal_data.struct_version + + VL53L1_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION; + + + /* memcpy(DEST, SRC, N) */ + memcpy( + &(pCalibrationData->add_off_cal_data), + &(cal_data.add_off_cal_data), + sizeof(VL53L1_additional_offset_cal_data_t)); + + /* memcpy (DEST, SRC, N) */ + memcpy( + &(pCalibrationData->optical_centre), + &(cal_data.optical_centre), + sizeof(VL53L1_optical_centre_t)); + + /* memcpy (DEST, SRC, N) */ + memcpy( + &(pCalibrationData->gain_cal), + &(cal_data.gain_cal), + sizeof(VL53L1_gain_calibration_data_t)); + + /* memcpy (DEST, SRC, N) */ + memcpy( + &(pCalibrationData->cal_peak_rate_map), + &(cal_data.cal_peak_rate_map), + sizeof(VL53L1_cal_peak_rate_map_t)); + + + pC = &pCalibrationData->customer; + pC2 = &cal_data.customer; + pC->global_config__spad_enables_ref_0 = + pC2->global_config__spad_enables_ref_0; + pC->global_config__spad_enables_ref_1 = + pC2->global_config__spad_enables_ref_1; + pC->global_config__spad_enables_ref_2 = + pC2->global_config__spad_enables_ref_2; + pC->global_config__spad_enables_ref_3 = + pC2->global_config__spad_enables_ref_3; + pC->global_config__spad_enables_ref_4 = + pC2->global_config__spad_enables_ref_4; + pC->global_config__spad_enables_ref_5 = + pC2->global_config__spad_enables_ref_5; + pC->global_config__ref_en_start_select = + pC2->global_config__ref_en_start_select; + pC->ref_spad_man__num_requested_ref_spads = + pC2->ref_spad_man__num_requested_ref_spads; + pC->ref_spad_man__ref_location = + pC2->ref_spad_man__ref_location; + pC->algo__crosstalk_compensation_x_plane_gradient_kcps = + pC2->algo__crosstalk_compensation_x_plane_gradient_kcps; + pC->algo__crosstalk_compensation_y_plane_gradient_kcps = + pC2->algo__crosstalk_compensation_y_plane_gradient_kcps; + pC->ref_spad_char__total_rate_target_mcps = + pC2->ref_spad_char__total_rate_target_mcps; + pC->algo__part_to_part_range_offset_mm = + pC2->algo__part_to_part_range_offset_mm; + pC->mm_config__inner_offset_mm = + pC2->mm_config__inner_offset_mm; + pC->mm_config__outer_offset_mm = + pC2->mm_config__outer_offset_mm; + + pC->algo__crosstalk_compensation_plane_offset_kcps = + (uint32_t)( + pC2->algo__crosstalk_compensation_plane_offset_kcps); + LOG_FUNCTION_END(Status); + return Status; +} + + + +VL53L1_Error VL53L1_GetOpticalCenter(VL53L1_DEV Dev, + FixPoint1616_t *pOpticalCenterX, + FixPoint1616_t *pOpticalCenterY) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_calibration_data_t CalibrationData; + + LOG_FUNCTION_START(""); + + *pOpticalCenterX = 0; + *pOpticalCenterY = 0; + Status = VL53L1_get_part_to_part_data(Dev, &CalibrationData); + if (Status == VL53L1_ERROR_NONE) { + *pOpticalCenterX = VL53L1_FIXPOINT44TOFIXPOINT1616( + CalibrationData.optical_centre.x_centre); + *pOpticalCenterY = VL53L1_FIXPOINT44TOFIXPOINT1616( + CalibrationData.optical_centre.y_centre); + } + + LOG_FUNCTION_END(Status); + return Status; +} + +/* END Group Calibration functions */ + + +/* Group PAL detection triggered events Functions */ + +VL53L1_Error VL53L1_SetThresholdConfig(VL53L1_DEV Dev, + VL53L1_DetectionConfig_t *pConfig) +{ +#define BADTHRESBOUNDS(T) \ + (((T.CrossMode == VL53L1_THRESHOLD_OUT_OF_WINDOW) || \ + (T.CrossMode == VL53L1_THRESHOLD_IN_WINDOW)) && (T.Low > T.High)) + + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_GPIO_interrupt_config_t Cfg; + uint16_t g; + FixPoint1616_t gain, high1616, low1616; + VL53L1_LLDriverData_t *pdev; + + LOG_FUNCTION_START(""); + + pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + Status = VL53L1_get_GPIO_interrupt_config(Dev, &Cfg); + if (Status != VL53L1_ERROR_NONE) + return Status; + + if (pConfig->DetectionMode == VL53L1_DETECTION_NORMAL_RUN) { + Cfg.intr_new_measure_ready = 1; + Status = VL53L1_set_GPIO_interrupt_config_struct(Dev, + Cfg); + } else { + if (BADTHRESBOUNDS(pConfig->Distance)) + Status = VL53L1_ERROR_INVALID_PARAMS; + if ((Status == VL53L1_ERROR_NONE) && + (BADTHRESBOUNDS(pConfig->Rate))) + Status = VL53L1_ERROR_INVALID_PARAMS; + if (Status == VL53L1_ERROR_NONE) { + Cfg.intr_new_measure_ready = 0; + Cfg.intr_no_target = pConfig->IntrNoTarget; + /* fix ticket 466238 Apply invert distance gain to thresholds */ + g = pdev->gain_cal.standard_ranging_gain_factor; + if (g != 0) { + /* gain is ufix 5.11, convert to 16.16 */ + gain = (FixPoint1616_t) ((uint32_t)g << 5); + high1616 = (FixPoint1616_t) ((uint32_t) + pConfig->Distance.High << 16); + low1616 = (FixPoint1616_t) ((uint32_t) + pConfig->Distance.Low << 16); + /* +32768 to round the results*/ + high1616 = (high1616 + 32768) / gain; + low1616 = (low1616 + 32768) / gain; + Cfg.threshold_distance_high = (uint16_t) + (high1616 & 0xFFFF); + Cfg.threshold_distance_low = (uint16_t) + (low1616 & 0xFFFF); + } /* end fix ticket 466238 */ + Cfg.threshold_rate_high = + VL53L1_FIXPOINT1616TOFIXPOINT97( + pConfig->Rate.High); + Cfg.threshold_rate_low = + VL53L1_FIXPOINT1616TOFIXPOINT97( + pConfig->Rate.Low); + + Cfg.intr_mode_distance = ConvertModeToLLD( + &Status, + pConfig->Distance.CrossMode); + if (Status == VL53L1_ERROR_NONE) + Cfg.intr_mode_rate = ConvertModeToLLD( + &Status, + pConfig->Rate.CrossMode); + } + + /* Refine thresholds combination now */ + if (Status == VL53L1_ERROR_NONE) { + Cfg.intr_combined_mode = 1; + switch (pConfig->DetectionMode) { + case VL53L1_DETECTION_DISTANCE_ONLY: + Cfg.threshold_rate_high = 0; + Cfg.threshold_rate_low = 0; + break; + case VL53L1_DETECTION_RATE_ONLY: + Cfg.threshold_distance_high = 0; + Cfg.threshold_distance_low = 0; + break; + case VL53L1_DETECTION_DISTANCE_OR_RATE: + /* Nothing to do all is already in place */ + break; + case VL53L1_DETECTION_DISTANCE_AND_RATE: + Cfg.intr_combined_mode = 0; + break; + default: + Status = VL53L1_ERROR_INVALID_PARAMS; + } + } + + if (Status == VL53L1_ERROR_NONE) + Status = + VL53L1_set_GPIO_interrupt_config_struct(Dev, Cfg); + + } + + LOG_FUNCTION_END(Status); + return Status; +} + + +VL53L1_Error VL53L1_GetThresholdConfig(VL53L1_DEV Dev, + VL53L1_DetectionConfig_t *pConfig) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + VL53L1_GPIO_interrupt_config_t Cfg; + + LOG_FUNCTION_START(""); + + Status = VL53L1_get_GPIO_interrupt_config(Dev, &Cfg); + + if (Status != VL53L1_ERROR_NONE) { + LOG_FUNCTION_END(Status); + return Status; + } + + pConfig->IntrNoTarget = Cfg.intr_no_target; + pConfig->Distance.High = Cfg.threshold_distance_high; + pConfig->Distance.Low = Cfg.threshold_distance_low; + pConfig->Rate.High = + VL53L1_FIXPOINT97TOFIXPOINT1616( + Cfg.threshold_rate_high); + pConfig->Rate.Low = + VL53L1_FIXPOINT97TOFIXPOINT1616(Cfg.threshold_rate_low); + pConfig->Distance.CrossMode = + ConvertModeFromLLD(&Status, Cfg.intr_mode_distance); + if (Status == VL53L1_ERROR_NONE) + pConfig->Rate.CrossMode = + ConvertModeFromLLD(&Status, Cfg.intr_mode_rate); + + if (Cfg.intr_new_measure_ready == 1) { + pConfig->DetectionMode = VL53L1_DETECTION_NORMAL_RUN; + } else { + /* Refine thresholds combination now */ + if (Status == VL53L1_ERROR_NONE) { + if (Cfg.intr_combined_mode == 0) + pConfig->DetectionMode = + VL53L1_DETECTION_DISTANCE_AND_RATE; + else { + if ((Cfg.threshold_distance_high == 0) && + (Cfg.threshold_distance_low == 0)) + pConfig->DetectionMode = + VL53L1_DETECTION_RATE_ONLY; + else if ((Cfg.threshold_rate_high == 0) && + (Cfg.threshold_rate_low == 0)) + pConfig->DetectionMode = + VL53L1_DETECTION_DISTANCE_ONLY; + else + pConfig->DetectionMode = + VL53L1_DETECTION_DISTANCE_OR_RATE; + } + } + } + + LOG_FUNCTION_END(Status); + return Status; +} + + +/* End Group PAL IRQ Triggered events Functions */ + + +static VL53L1_Error VL53L1_LoadPatch(VL53L1_DEV Dev) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + uint32_t patch_tuning = 0; + uint8_t comms_buffer[256]; + uint32_t patch_power; + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte( + Dev, + VL53L1_FIRMWARE__ENABLE, + 0x00); + /* Force GO1 on */ + if (status == VL53L1_ERROR_NONE) + VL53L1_enable_powerforce(Dev); + + patch_tuning = BDTable[VL53L1_TUNING_PHASECAL_PATCH_POWER]; + + switch(patch_tuning) { + case 0: + patch_power = 0x00; + break; + case 1: + patch_power = 0x10; + break; + case 2: + patch_power = 0x20; + break; + case 3: + patch_power = 0x40; + break; + default: + patch_power = 0x00; + } + /* Set patch RAM offsets */ + if (status == VL53L1_ERROR_NONE) { + /* Package up MultiByte transaction */ + comms_buffer[0] = 0x29; + comms_buffer[1] = 0xC9; + comms_buffer[2] = 0x0E; + comms_buffer[3] = 0x40; + comms_buffer[4] = 0x28; + comms_buffer[5] = patch_power; + /* 0x10 for 60ms, 0x20 for 240ms and 0x40 for 3580ms */ + status = VL53L1_WriteMulti( + Dev, + VL53L1_PATCH__OFFSET_0, + comms_buffer, + 6); + } + /* Set patch breakpoints */ + if (status == VL53L1_ERROR_NONE) { + comms_buffer[0] = 0x03; + comms_buffer[1] = 0x6D; + comms_buffer[2] = 0x03; + comms_buffer[3] = 0x6F; + comms_buffer[4] = 0x07; + comms_buffer[5] = 0x29; + status = VL53L1_WriteMulti( + Dev, + VL53L1_PATCH__ADDRESS_0, + comms_buffer, + 6); + } + /* Enable patch JMP patches */ + if (status == VL53L1_ERROR_NONE) { + comms_buffer[0] = 0x00; + comms_buffer[1] = 0x07; + status = VL53L1_WriteMulti( + Dev, + VL53L1_PATCH__JMP_ENABLES, + comms_buffer, + 2); + } + /* Enable patch DATA patches */ + if (status == VL53L1_ERROR_NONE) { + comms_buffer[0] = 0x00; + comms_buffer[1] = 0x07; + status = VL53L1_WriteMulti( + Dev, + VL53L1_PATCH__DATA_ENABLES, + comms_buffer, + 2); + } + /* Enable firmware patching */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte( + Dev, + VL53L1_PATCH__CTRL, + 0x01); + /* Enable Firmware */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte( + Dev, + VL53L1_FIRMWARE__ENABLE, + 0x01); + + LOG_FUNCTION_END(status); + + return status; +} + +static VL53L1_Error VL53L1_UnloadPatch(VL53L1_DEV Dev) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + /* Disable Firmware (allow full write access) */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte( + Dev, + VL53L1_FIRMWARE__ENABLE, + 0x00); + /* Force GO1 off */ + if (status == VL53L1_ERROR_NONE) + VL53L1_disable_powerforce(Dev); + /* Disable firmware patching */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte( + Dev, + VL53L1_PATCH__CTRL, + 0x00); + /* Enable Firmware */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte( + Dev, + VL53L1_FIRMWARE__ENABLE, + 0x01); + + LOG_FUNCTION_END(status); + + return status; +} diff --git a/App/VL53L1X_API/core/src/vl53l1_api_calibration.c b/App/VL53L1X_API/core/src/vl53l1_api_calibration.c new file mode 100644 index 0000000..b0fe93d --- /dev/null +++ b/App/VL53L1X_API/core/src/vl53l1_api_calibration.c @@ -0,0 +1,876 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_api_core.c + * + * @brief EwokPlus25 low level API function definition + */ + + +#include "vl53l1_ll_def.h" +#include "vl53l1_ll_device.h" +#include "vl53l1_platform.h" +#include "vl53l1_register_map.h" +#include "vl53l1_register_funcs.h" +#include "vl53l1_register_settings.h" +#include "vl53l1_core.h" +#include "vl53l1_wait.h" +#include "vl53l1_api_preset_modes.h" +#include "vl53l1_silicon_core.h" +#include "vl53l1_api_core.h" +#include "vl53l1_api_calibration.h" + +#ifdef VL53L1_LOG_ENABLE + #include "vl53l1_api_debug.h" +#endif +#ifdef VL53L1_LOGGING + #include "vl53l1_debug.h" +#endif + +#define LOG_FUNCTION_START(fmt, ...) \ + _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__) +#define LOG_FUNCTION_END(status, ...) \ + _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_CORE, status, ##__VA_ARGS__) +#define LOG_FUNCTION_END_FMT(status, fmt, ...) \ + _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_CORE, status, \ + fmt, ##__VA_ARGS__) + +#define trace_print(level, ...) \ + _LOG_TRACE_PRINT(VL53L1_TRACE_MODULE_CORE, \ + level, VL53L1_TRACE_FUNCTION_NONE, ##__VA_ARGS__) + + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_run_ref_spad_char( + VL53L1_DEV Dev, + VL53L1_Error *pcal_status) +{ + /* + * Runs Reference SPAD Characterisation + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t comms_buffer[6]; + + VL53L1_refspadchar_config_t *prefspadchar = &(pdev->refspadchar); + + LOG_FUNCTION_START(""); + + /* + * Ensure power force is enabled + */ + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_enable_powerforce(Dev); + + /* + * Configure device + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_set_ref_spad_char_config( + Dev, + prefspadchar->vcsel_period, + prefspadchar->timeout_us, + prefspadchar->target_count_rate_mcps, + prefspadchar->max_count_rate_limit_mcps, + prefspadchar->min_count_rate_limit_mcps, + pdev->stat_nvm.osc_measured__fast_osc__frequency); + + /* + * Run device test + */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_run_device_test( + Dev, + prefspadchar->device_test_mode); + + /* + * Read results + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_ReadMulti( + Dev, + VL53L1_REF_SPAD_CHAR_RESULT__NUM_ACTUAL_REF_SPADS, + comms_buffer, + 2); + + if (status == VL53L1_ERROR_NONE) { + pdev->dbg_results.ref_spad_char_result__num_actual_ref_spads = + comms_buffer[0]; + pdev->dbg_results.ref_spad_char_result__ref_location = + comms_buffer[1]; + } + + /* + * copy results to customer nvm managed G02 registers + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WriteMulti( + Dev, + VL53L1_REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS, + comms_buffer, + 2); + + if (status == VL53L1_ERROR_NONE) { + pdev->customer.ref_spad_man__num_requested_ref_spads = + comms_buffer[0]; + pdev->customer.ref_spad_man__ref_location = + comms_buffer[1]; + } + + /* After Ref Spad Char the final set of good SPAD enables + * are stored in the NCY results registers below + * + * - RESULT__SPARE_0_SD_1 + * - RESULT__SPARE_1_SD_1 + * - RESULT__SPARE_2_SD_1 + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_ReadMulti( + Dev, + VL53L1_RESULT__SPARE_0_SD1, + comms_buffer, + 6); + + /* + * copy reference SPAD enables to customer nvm managed + * G02 registers + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WriteMulti( + Dev, + VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_0, + comms_buffer, + 6); + + if (status == VL53L1_ERROR_NONE) { + pdev->customer.global_config__spad_enables_ref_0 = + comms_buffer[0]; + pdev->customer.global_config__spad_enables_ref_1 = + comms_buffer[1]; + pdev->customer.global_config__spad_enables_ref_2 = + comms_buffer[2]; + pdev->customer.global_config__spad_enables_ref_3 = + comms_buffer[3]; + pdev->customer.global_config__spad_enables_ref_4 = + comms_buffer[4]; + pdev->customer.global_config__spad_enables_ref_5 = + comms_buffer[5]; + } + +#ifdef VL53L1_LOG_ENABLE + /* Print customer nvm managed data */ + if (status == VL53L1_ERROR_NONE) + VL53L1_print_customer_nvm_managed( + &(pdev->customer), + "run_ref_spad_char():pdev->lldata.customer.", + VL53L1_TRACE_MODULE_REF_SPAD_CHAR); +#endif + + if (status == VL53L1_ERROR_NONE) { + + switch (pdev->sys_results.result__range_status) { + + case VL53L1_DEVICEERROR_REFSPADCHARNOTENOUGHDPADS: + status = VL53L1_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS; + break; + + case VL53L1_DEVICEERROR_REFSPADCHARMORETHANTARGET: + status = VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH; + break; + + case VL53L1_DEVICEERROR_REFSPADCHARLESSTHANTARGET: + status = VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW; + break; + } + } + + /* + * Save unfiltered status + */ + + *pcal_status = status; + + /* Status exception code */ + + IGNORE_STATUS( + IGNORE_REF_SPAD_CHAR_NOT_ENOUGH_SPADS, + VL53L1_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS, + status); + + IGNORE_STATUS( + IGNORE_REF_SPAD_CHAR_RATE_TOO_HIGH, + VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH, + status); + + IGNORE_STATUS( + IGNORE_REF_SPAD_CHAR_RATE_TOO_LOW, + VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW, + status); + + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_run_offset_calibration( + VL53L1_DEV Dev, + int16_t cal_distance_mm, + VL53L1_Error *pcal_status) +{ + /* + * Runs offset calibration + * + * Recommended tuning parm settings: + * + * - pre_num_of_samples = 32 + * - mm1_num_of_samples = 100 + * - mm2_num_of_samples = 64 + * - target_distance_mm = 140mm + * - target reflectance = 5% + * + * Standard Ranging (sigma delta mode): + * - dss_config__target_total_rate_mcps = 20.0 -40.0 Mcps + * - phasecal_config_timeout_us = 1000 + * - range_config_timeout_us = 13000 + * - mm_config_timeout_us = 13000 + * + * + * Note: function parms simplified as part of + * Patch_CalFunctionSimplification_11791 + * + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + VL53L1_DevicePresetModes device_preset_modes[VL53L1_MAX_OFFSET_RANGE_RESULTS]; + + VL53L1_range_results_t range_results; + VL53L1_range_results_t *prange_results = &range_results; + VL53L1_range_data_t *prange_data = NULL; + VL53L1_offset_range_data_t *poffset = NULL; + + uint8_t i = 0; + uint8_t m = 0; + uint8_t measurement_mode = + VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK; + uint16_t manual_effective_spads = + pdev->gen_cfg.dss_config__manual_effective_spads_select; + + uint8_t num_of_samples[VL53L1_MAX_OFFSET_RANGE_RESULTS]; + + LOG_FUNCTION_START(""); + + /* select requested offset calibration mode */ + + switch (pdev->offset_calibration_mode) { + + default: + device_preset_modes[0] = + VL53L1_DEVICEPRESETMODE_STANDARD_RANGING; + device_preset_modes[1] = + VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM1_CAL; + device_preset_modes[2] = + VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM2_CAL; + break; + } + + /* initialise num_of_samples */ + /* Start Patch_CalFunctionSimplification_11791 */ + num_of_samples[0] = pdev->offsetcal_cfg.pre_num_of_samples; + num_of_samples[1] = pdev->offsetcal_cfg.mm1_num_of_samples; + num_of_samples[2] = pdev->offsetcal_cfg.mm2_num_of_samples; + /* End Patch_CalFunctionSimplification_11791 */ + + /* force all offsets to zero */ + + switch (pdev->offset_calibration_mode) { + + case VL53L1_OFFSETCALIBRATIONMODE__MM1_MM2__STANDARD_PRE_RANGE_ONLY: + /* only run pre range */ + pdev->offset_results.active_results = 1; + + break; + + default: + + pdev->customer.mm_config__inner_offset_mm = 0; + pdev->customer.mm_config__outer_offset_mm = 0; + pdev->offset_results.active_results = + VL53L1_MAX_OFFSET_RANGE_RESULTS; + + break; + } + + pdev->customer.algo__part_to_part_range_offset_mm = 0; + + /* initialise offset range results */ + + pdev->offset_results.max_results = VL53L1_MAX_OFFSET_RANGE_RESULTS; + pdev->offset_results.cal_distance_mm = cal_distance_mm; + + for (m = 0 ; m < VL53L1_MAX_OFFSET_RANGE_RESULTS; m++) { + + poffset = &(pdev->offset_results.data[m]); + poffset->preset_mode = 0; + poffset->no_of_samples = 0; + poffset->effective_spads = 0; + poffset->peak_rate_mcps = 0; + poffset->sigma_mm = 0; + poffset->median_range_mm = 0; + } + + for (m = 0 ; m < pdev->offset_results.active_results ; m++) { + + poffset = &(pdev->offset_results.data[m]); + + poffset->preset_mode = device_preset_modes[m]; + + /* Apply preset mode */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_set_preset_mode( + Dev, + device_preset_modes[m], + /* Start Patch_CalFunctionSimplification_11791 */ + pdev->offsetcal_cfg.dss_config__target_total_rate_mcps, + pdev->offsetcal_cfg.phasecal_config_timeout_us, + pdev->offsetcal_cfg.mm_config_timeout_us, + pdev->offsetcal_cfg.range_config_timeout_us, + /* End Patch_CalFunctionSimplification_11791 */ + 100); + + pdev->gen_cfg.dss_config__manual_effective_spads_select = + manual_effective_spads; + + /* Initialise device and start range */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_init_and_start_range( + Dev, + measurement_mode, + VL53L1_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS); + + for (i = 0 ; i <= (num_of_samples[m]+2) ; i++) { + + /* Wait for range completion */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_wait_for_range_completion(Dev); + + /* + * Get Device Results + * - Checks the stream count is the expected one + * - Read device system results + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_get_device_results( + Dev, + VL53L1_DEVICERESULTSLEVEL_FULL, + prange_results); + + /* + * Ignore 1st two ranges to give the sigma delta initial + * phase time to settle + * + * accummulate range results if range is successful + */ + + prange_data = &(prange_results->data[0]); + + if (prange_results->stream_count > 1) { + + if (prange_data->range_status == + VL53L1_DEVICEERROR_RANGECOMPLETE) { + + poffset->no_of_samples++; + poffset->effective_spads += + (uint32_t)prange_data->actual_effective_spads; + poffset->peak_rate_mcps += + (uint32_t)prange_data->peak_signal_count_rate_mcps; + poffset->sigma_mm += + (uint32_t)prange_data->sigma_mm; + poffset->median_range_mm += + (int32_t)prange_data->median_range_mm; + + poffset->dss_config__roi_mode_control = + pdev->gen_cfg.dss_config__roi_mode_control; + poffset->dss_config__manual_effective_spads_select = + pdev->gen_cfg.dss_config__manual_effective_spads_select; + } + } + + /* + * Conditional wait for firmware ready. Only waits for timed + * and single shot modes. Mode check is performed inside the + * wait function + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_wait_for_firmware_ready(Dev); + + /* + * Send ranging handshake + * + * - Update Zone management + * - Update GPH registers + * - Clear current interrupt + * - Initialise SYSTEM__MODE_START for next range (if there is one!) + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_clear_interrupt_and_enable_next_range( + Dev, + measurement_mode); + } + + /* Stop range */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_stop_range(Dev); + + /* Wait for Stop (abort) range to complete */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WaitUs(Dev, 1000); + + /* generate average values */ + if (poffset->no_of_samples > 0) { + + poffset->effective_spads += (poffset->no_of_samples/2); + poffset->effective_spads /= poffset->no_of_samples; + + poffset->peak_rate_mcps += (poffset->no_of_samples/2); + poffset->peak_rate_mcps /= poffset->no_of_samples; + + poffset->sigma_mm += (poffset->no_of_samples/2); + poffset->sigma_mm /= poffset->no_of_samples; + + poffset->median_range_mm += (poffset->no_of_samples/2); + poffset->median_range_mm /= poffset->no_of_samples; + + poffset->range_mm_offset = (int32_t)cal_distance_mm; + poffset->range_mm_offset -= poffset->median_range_mm; + + /* remember the number of SPADs for standard ranging */ + if (poffset->preset_mode == + VL53L1_DEVICEPRESETMODE_STANDARD_RANGING) + manual_effective_spads = + (uint16_t)poffset->effective_spads; + } + } + + /* Calculate offsets */ + + switch (pdev->offset_calibration_mode) { + + case VL53L1_OFFSETCALIBRATIONMODE__MM1_MM2__STANDARD_PRE_RANGE_ONLY: + + /* copy offsets to customer data structure */ + pdev->customer.mm_config__inner_offset_mm += + (int16_t)pdev->offset_results.data[0].range_mm_offset; + pdev->customer.mm_config__outer_offset_mm += + (int16_t)pdev->offset_results.data[0].range_mm_offset; + break; + + default: + /* copy offsets to customer data structure */ + pdev->customer.mm_config__inner_offset_mm = + (int16_t)pdev->offset_results.data[1].range_mm_offset; + pdev->customer.mm_config__outer_offset_mm = + (int16_t)pdev->offset_results.data[2].range_mm_offset; + pdev->customer.algo__part_to_part_range_offset_mm = 0; + + /* copy average rate and effective SPAD count to + additional offset calibration data structure */ + + pdev->add_off_cal_data.result__mm_inner_actual_effective_spads = + (uint16_t)pdev->offset_results.data[1].effective_spads; + pdev->add_off_cal_data.result__mm_outer_actual_effective_spads = + (uint16_t)pdev->offset_results.data[2].effective_spads; + + pdev->add_off_cal_data.result__mm_inner_peak_signal_count_rtn_mcps = + (uint16_t)pdev->offset_results.data[1].peak_rate_mcps; + pdev->add_off_cal_data.result__mm_outer_peak_signal_count_rtn_mcps = + (uint16_t)pdev->offset_results.data[2].peak_rate_mcps; + + break; + } + + + /* apply to device */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_set_customer_nvm_managed( + Dev, + &(pdev->customer)); + + /* + * Check the peak rates, sigma, min spads for each stage + */ + + for (m = 0 ; m < pdev->offset_results.active_results ; m++) { + + poffset = &(pdev->offset_results.data[m]); + + if (status == VL53L1_ERROR_NONE) { + + pdev->offset_results.cal_report = m; + + if (poffset->no_of_samples < num_of_samples[m]) + status = VL53L1_WARNING_OFFSET_CAL_MISSING_SAMPLES; + + /* only check sigma for the pre-range as + * the it is not calculated by the device + * for the MM1 and MM2 stages + */ + if (m == 0 && poffset->sigma_mm > + ((uint32_t)VL53L1_OFFSET_CAL_MAX_SIGMA_MM<<5)) + status = VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH; + + if (poffset->peak_rate_mcps > + VL53L1_OFFSET_CAL_MAX_PRE_PEAK_RATE_MCPS) + status = VL53L1_WARNING_OFFSET_CAL_RATE_TOO_HIGH; + + if (poffset->dss_config__manual_effective_spads_select < + VL53L1_OFFSET_CAL_MIN_EFFECTIVE_SPADS) + status = VL53L1_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW; + + if (poffset->dss_config__manual_effective_spads_select == 0) + status = VL53L1_ERROR_OFFSET_CAL_NO_SPADS_ENABLED_FAIL; + + if (poffset->no_of_samples == 0) + status = VL53L1_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL; + } + } + + /* + * Save unfiltered status + */ + + pdev->offset_results.cal_status = status; + *pcal_status = pdev->offset_results.cal_status; + + /* Status exception codes */ + + IGNORE_STATUS( + IGNORE_OFFSET_CAL_MISSING_SAMPLES, + VL53L1_WARNING_OFFSET_CAL_MISSING_SAMPLES, + status); + + IGNORE_STATUS( + IGNORE_OFFSET_CAL_SIGMA_TOO_HIGH, + VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH, + status); + + IGNORE_STATUS( + IGNORE_OFFSET_CAL_RATE_TOO_HIGH, + VL53L1_WARNING_OFFSET_CAL_RATE_TOO_HIGH, + status); + + IGNORE_STATUS( + IGNORE_OFFSET_CAL_SPAD_COUNT_TOO_LOW, + VL53L1_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW, + status); + +#ifdef VL53L1_LOG_ENABLE + + /* Prints out the offset calibration data for debug */ + + VL53L1_print_customer_nvm_managed( + &(pdev->customer), + "run_offset_calibration():pdev->lldata.customer.", + VL53L1_TRACE_MODULE_OFFSET_DATA); + + VL53L1_print_additional_offset_cal_data( + &(pdev->add_off_cal_data), + "run_offset_calibration():pdev->lldata.add_off_cal_data.", + VL53L1_TRACE_MODULE_OFFSET_DATA); + + VL53L1_print_offset_range_results( + &(pdev->offset_results), + "run_offset_calibration():pdev->lldata.offset_results.", + VL53L1_TRACE_MODULE_OFFSET_DATA); +#endif + + LOG_FUNCTION_END(status); + + return status; +} +#endif + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_run_spad_rate_map( + VL53L1_DEV Dev, + VL53L1_DeviceTestMode device_test_mode, + VL53L1_DeviceSscArray array_select, + uint32_t ssc_config_timeout_us, + VL53L1_spad_rate_data_t *pspad_rate_data) +{ + + /** + * Runs SPAD Rate Map + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + /* + * Ensure power force is enabled + */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_powerforce(Dev); + + /* + * Configure the test + */ + + if (status == VL53L1_ERROR_NONE) { + pdev->ssc_cfg.array_select = array_select; + pdev->ssc_cfg.timeout_us = ssc_config_timeout_us; + status = + VL53L1_set_ssc_config( + Dev, + &(pdev->ssc_cfg), + pdev->stat_nvm.osc_measured__fast_osc__frequency); + } + + /* + * Run device test + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_run_device_test( + Dev, + device_test_mode); + + /* + * Read Rate Data from Patch Ram + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_get_spad_rate_data( + Dev, + pspad_rate_data); + + if (device_test_mode == VL53L1_DEVICETESTMODE_LCR_VCSEL_ON) + pspad_rate_data->fractional_bits = 7; + else + pspad_rate_data->fractional_bits = 15; + + /* Ensure power force is disabled */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_powerforce(Dev); + +#ifdef VL53L1_LOG_ENABLE + /* Print return rate data and map */ + + if (status == VL53L1_ERROR_NONE) { + VL53L1_print_spad_rate_data( + pspad_rate_data, + "run_spad_rate_map():", + VL53L1_TRACE_MODULE_SPAD_RATE_MAP); + VL53L1_print_spad_rate_map( + pspad_rate_data, + "run_spad_rate_map():", + VL53L1_TRACE_MODULE_SPAD_RATE_MAP); + } +#endif + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_run_device_test( + VL53L1_DEV Dev, + VL53L1_DeviceTestMode device_test_mode) +{ + /* + * Runs the selected Device Test Mode + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t comms_buffer[2]; + uint8_t gpio_hv_mux__ctrl = 0; + + LOG_FUNCTION_START(""); + + /* + * Get current interrupt config + */ + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = + VL53L1_RdByte( + Dev, + VL53L1_GPIO_HV_MUX__CTRL, + &gpio_hv_mux__ctrl); + + if (status == VL53L1_ERROR_NONE) + pdev->stat_cfg.gpio_hv_mux__ctrl = gpio_hv_mux__ctrl; + + /* + * Trigger the test + */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_start_test( + Dev, + device_test_mode); + + /* + * Wait for test completion + */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_wait_for_test_completion(Dev); + + /* + * Read range and report status + */ + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_ReadMulti( + Dev, + VL53L1_RESULT__RANGE_STATUS, + comms_buffer, + 2); + + if (status == VL53L1_ERROR_NONE) { + pdev->sys_results.result__range_status = comms_buffer[0]; + pdev->sys_results.result__report_status = comms_buffer[1]; + } + + /* mask range status bits */ + + pdev->sys_results.result__range_status &= + VL53L1_RANGE_STATUS__RANGE_STATUS_MASK; + + if (status == VL53L1_ERROR_NONE) { + trace_print( + VL53L1_TRACE_LEVEL_INFO, + " Device Test Complete:\n\t%-32s = %3u\n\t%-32s = %3u\n", + "result__range_status", + pdev->sys_results.result__range_status, + "result__report_status", + pdev->sys_results.result__report_status); + + /* + * Clear interrupt + */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_clear_interrupt(Dev); + } + + /* + * Clear test mode register + * - required so that next test command will trigger + * internal MCU interrupt + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_start_test( + Dev, + 0x00); + + LOG_FUNCTION_END(status); + + return status; +} +#endif diff --git a/App/VL53L1X_API/core/src/vl53l1_api_core.c b/App/VL53L1X_API/core/src/vl53l1_api_core.c new file mode 100644 index 0000000..50ac043 --- /dev/null +++ b/App/VL53L1X_API/core/src/vl53l1_api_core.c @@ -0,0 +1,3533 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_api_core.c + * + * @brief EwokPlus25 low level API function definition + */ + + +#include "vl53l1_ll_def.h" +#include "vl53l1_ll_device.h" +#include "vl53l1_platform.h" +#include "vl53l1_register_map.h" +#include "vl53l1_register_settings.h" +#include "vl53l1_register_funcs.h" +#include "vl53l1_nvm_map.h" +#include "vl53l1_core.h" +#include "vl53l1_wait.h" +#include "vl53l1_api_preset_modes.h" +#include "vl53l1_silicon_core.h" +#include "vl53l1_api_core.h" +#include "vl53l1_tuning_parm_defaults.h" + +#ifdef VL53L1_LOG_ENABLE +#include "vl53l1_api_debug.h" +#endif + +#define LOG_FUNCTION_START(fmt, ...) \ + _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__) +#define LOG_FUNCTION_END(status, ...) \ + _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_CORE, status, ##__VA_ARGS__) +#define LOG_FUNCTION_END_FMT(status, fmt, ...) \ + _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_CORE, status, \ + fmt, ##__VA_ARGS__) + +#define trace_print(level, ...) \ + _LOG_TRACE_PRINT(VL53L1_TRACE_MODULE_CORE, \ + level, VL53L1_TRACE_FUNCTION_NONE, ##__VA_ARGS__) + +#define VL53L1_MAX_I2C_XFER_SIZE 256 + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_version( + VL53L1_DEV Dev, + VL53L1_ll_version_t *pdata) +{ + /* + * respond with the #define values from version.h + * using memcpy(dst, src, size in bytes) + */ + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + VL53L1_init_version(Dev); + + memcpy(pdata, &(pdev->version), sizeof(VL53L1_ll_version_t)); + + return VL53L1_ERROR_NONE; +} + +VL53L1_Error VL53L1_get_device_firmware_version( + VL53L1_DEV Dev, + uint16_t *pfw_version) +{ + /* + * Read Firmware version from device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_RdWord( + Dev, + VL53L1_MCU_GENERAL_PURPOSE__GP_0, + pfw_version); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_data_init( + VL53L1_DEV Dev, + uint8_t read_p2p_data) +{ + /* + * Initialise pdev data structure + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + VL53L1_init_ll_driver_state( + Dev, + VL53L1_DEVICESTATE_UNKNOWN); + + pdev->wait_method = VL53L1_WAIT_METHOD_BLOCKING; + pdev->preset_mode = VL53L1_DEVICEPRESETMODE_STANDARD_RANGING; + pdev->measurement_mode = VL53L1_DEVICEMEASUREMENTMODE_STOP; + + pdev->offset_calibration_mode = + VL53L1_OFFSETCALIBRATIONMODE__MM1_MM2__STANDARD; + pdev->offset_correction_mode = + VL53L1_OFFSETCORRECTIONMODE__MM1_MM2_OFFSETS; + + pdev->phasecal_config_timeout_us = 1000; + pdev->mm_config_timeout_us = 2000; + pdev->range_config_timeout_us = 13000; + pdev->inter_measurement_period_ms = 100; + pdev->dss_config__target_total_rate_mcps = 0x0A00; + pdev->debug_mode = 0x00; + + /* initialise gain calibration values to tuning parameter values */ + + pdev->gain_cal.standard_ranging_gain_factor = + VL53L1_TUNINGPARM_LITE_RANGING_GAIN_FACTOR_DEFAULT; + + /* + * Initialise version structure + */ + VL53L1_init_version(Dev); + + /* + * For C-API one time initialization only read device G02 registers + * containing data copied from NVM + * + * Contains the key NVM data e.g identification info fast oscillator + * freq, max trim and laser safety info + */ + + if (read_p2p_data > 0 && status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_read_p2p_data(Dev); + + /* Initialise Ref SPAD Char configuration structure */ +#ifndef VL53L1_NOCALIB + status = + VL53L1_init_refspadchar_config_struct( + &(pdev->refspadchar)); +#endif + + /* Initialise SPAD Self Check (SSC) configuration structure */ +#ifndef VL53L1_NOCALIB + status = + VL53L1_init_ssc_config_struct( + &(pdev->ssc_cfg)); +#endif + + /* Initialise Private Xtalk configuration structure + * - Fill with customer NVM data to begin + */ + status = + VL53L1_init_xtalk_config_struct( + &(pdev->customer), + &(pdev->xtalk_cfg)); + + /* Initialise Offset Calibration configuration structure + */ +#ifndef VL53L1_NOCALIB + status = + VL53L1_init_offset_cal_config_struct( + &(pdev->offsetcal_cfg)); +#endif + + /* Initialise Tuning Parameter structure + * - Added as part of Patch_AddingTuningParmStorage_11821 + */ + status = + VL53L1_init_tuning_parm_storage_struct( + &(pdev->tuning_parms)); + + status = VL53L1_set_vhv_loopbound(Dev, + VL53L1_TUNINGPARM_VHV_LOOPBOUND_DEFAULT); + + /* + * Initialise default settings - much happen *after* + * reading /setting of static_nvm_managed + */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_set_preset_mode( + Dev, + pdev->preset_mode, + pdev->dss_config__target_total_rate_mcps, /* 9.7 format 20Mcps */ + pdev->phasecal_config_timeout_us, + pdev->mm_config_timeout_us, + pdev->range_config_timeout_us, + pdev->inter_measurement_period_ms); + + /* Initial Low Power Auto Mode data structures */ + /* Added for Patch_LowPowerAutoMode */ + VL53L1_low_power_auto_data_init( + Dev + ); + +#ifdef VL53L1_LOG_ENABLE + + /* Prints out the initial calibration data for debug */ + + VL53L1_print_static_nvm_managed( + &(pdev->stat_nvm), + "data_init():pdev->lldata.stat_nvm.", + VL53L1_TRACE_MODULE_DATA_INIT); + + VL53L1_print_customer_nvm_managed( + &(pdev->customer), + "data_init():pdev->lldata.customer.", + VL53L1_TRACE_MODULE_DATA_INIT); + + VL53L1_print_nvm_copy_data( + &(pdev->nvm_copy_data), + "data_init():pdev->lldata.nvm_copy_data.", + VL53L1_TRACE_MODULE_DATA_INIT); + + VL53L1_print_additional_offset_cal_data( + &(pdev->add_off_cal_data), + "data_init():pdev->lldata.add_off_cal_data.", + VL53L1_TRACE_MODULE_DATA_INIT); + + VL53L1_print_user_zone( + &(pdev->mm_roi), + "data_init():pdev->lldata.mm_roi.", + VL53L1_TRACE_MODULE_DATA_INIT); + + VL53L1_print_optical_centre( + &(pdev->optical_centre), + "data_init():pdev->lldata.optical_centre.", + VL53L1_TRACE_MODULE_DATA_INIT); + + VL53L1_print_cal_peak_rate_map( + &(pdev->cal_peak_rate_map), + "data_init():pdev->lldata.cal_peak_rate_map.", + VL53L1_TRACE_MODULE_DATA_INIT); + +#endif + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_read_p2p_data( + VL53L1_DEV Dev) +{ + + /* + * For C-API one time initialization only reads device + * G02 registers containing data copied from NVM + * + * Contains the key NVM data e.g identification info + * fast oscillator freq, max trim and laser safety info + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_get_static_nvm_managed( + Dev, + &(pdev->stat_nvm)); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_get_customer_nvm_managed( + Dev, + &(pdev->customer)); + + if (status == VL53L1_ERROR_NONE) { + + status = VL53L1_get_nvm_copy_data( + Dev, + &(pdev->nvm_copy_data)); + + /* copy Return Good SPADs to buffer */ + if (status == VL53L1_ERROR_NONE) + VL53L1_copy_rtn_good_spads_to_buffer( + &(pdev->nvm_copy_data), + &(pdev->rtn_good_spads[0])); + } + + /* + * read slow osc calibration value + * counts per ms + */ + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_RdWord( + Dev, + VL53L1_RESULT__OSC_CALIBRATE_VAL, + &(pdev->dbg_results.result__osc_calibrate_val)); + + /* + * Check if there a sensible value for osc_measured__fast_osc__frequency + */ + + if (pdev->stat_nvm.osc_measured__fast_osc__frequency < 0x1000) { + trace_print( + VL53L1_TRACE_LEVEL_WARNING, + "\nInvalid %s value (0x%04X) - forcing to 0x%04X\n\n", + "pdev->stat_nvm.osc_measured__fast_osc__frequency", + pdev->stat_nvm.osc_measured__fast_osc__frequency, + 0xBCCC); + pdev->stat_nvm.osc_measured__fast_osc__frequency = 0xBCCC; + } + + /* + * Get MM ROI - contains optical centre as SPAD number + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_get_mode_mitigation_roi( + Dev, + &(pdev->mm_roi)); + + /* catch parts where the optical centre is + * no programmed in to the NVM + */ + + if (pdev->optical_centre.x_centre == 0 && + pdev->optical_centre.y_centre == 0) { + pdev->optical_centre.x_centre = + pdev->mm_roi.x_centre << 4; + pdev->optical_centre.y_centre = + pdev->mm_roi.y_centre << 4; + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_software_reset( + VL53L1_DEV Dev) +{ + /** + * Sets and clears the software reset register VL53L1_SOFT_RESET. + * and waits for the firmware to boot + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* apply reset - note despite the name soft reset is active low! */ + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_WrByte( + Dev, + VL53L1_SOFT_RESET, + 0x00); + + /* wait for a while before releasing the reset */ + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WaitUs( + Dev, + VL53L1_SOFTWARE_RESET_DURATION_US); + + /* release reset */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WrByte( + Dev, + VL53L1_SOFT_RESET, + 0x01); + + /* wait for firmware boot to complete */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_wait_for_boot_completion(Dev); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_part_to_part_data( + VL53L1_DEV Dev, + VL53L1_calibration_data_t *pcal_data) +{ + /** + * Uses memcpy to copy input data to pdev->customer + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint32_t tempu32; + + LOG_FUNCTION_START(""); + + if (pcal_data->struct_version != + VL53L1_LL_CALIBRATION_DATA_STRUCT_VERSION) { + status = VL53L1_ERROR_INVALID_PARAMS; + } + + if (status == VL53L1_ERROR_NONE) { + + /* memcpy(DEST, SRC, N) */ + memcpy( + &(pdev->customer), + &(pcal_data->customer), + sizeof(VL53L1_customer_nvm_managed_t)); + + /* memcpy(DEST, SRC, N) */ + memcpy( + &(pdev->add_off_cal_data), + &(pcal_data->add_off_cal_data), + sizeof(VL53L1_additional_offset_cal_data_t)); + + /* memcpy(DEST, SRC, N) */ + memcpy( + &(pdev->gain_cal), + &(pcal_data->gain_cal), + sizeof(VL53L1_gain_calibration_data_t)); + + /* memcpy(DEST, SRC, N) */ + memcpy( + &(pdev->cal_peak_rate_map), + &(pcal_data->cal_peak_rate_map), + sizeof(VL53L1_cal_peak_rate_map_t)); + + /* + * Update internal xtalk data structures + */ + + pdev->xtalk_cfg.algo__crosstalk_compensation_plane_offset_kcps = + pdev->customer.algo__crosstalk_compensation_plane_offset_kcps; + pdev->xtalk_cfg.algo__crosstalk_compensation_x_plane_gradient_kcps = + pdev->customer.algo__crosstalk_compensation_x_plane_gradient_kcps; + pdev->xtalk_cfg.algo__crosstalk_compensation_y_plane_gradient_kcps = + pdev->customer.algo__crosstalk_compensation_y_plane_gradient_kcps; + + /* Assess and update customer packet xtalk parameters */ + + if (pdev->xtalk_cfg.global_crosstalk_compensation_enable == 0x00) { + pdev->customer.algo__crosstalk_compensation_plane_offset_kcps = + 0x00; + pdev->customer.algo__crosstalk_compensation_x_plane_gradient_kcps = + 0x00; + pdev->customer.algo__crosstalk_compensation_y_plane_gradient_kcps = + 0x00; + } else { + tempu32 = VL53L1_calc_crosstalk_plane_offset_with_margin( + pdev->xtalk_cfg.algo__crosstalk_compensation_plane_offset_kcps, + pdev->xtalk_cfg.lite_mode_crosstalk_margin_kcps); + if (tempu32 > 0xFFFF) { /* clip to 16 bits */ + tempu32 = 0xFFFF; + } + pdev->customer.algo__crosstalk_compensation_plane_offset_kcps = + (uint16_t)tempu32; + } + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_part_to_part_data( + VL53L1_DEV Dev, + VL53L1_calibration_data_t *pcal_data) +{ + /** + * Uses memcpy to copy pdev->customer to output data + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pcal_data->struct_version = + VL53L1_LL_CALIBRATION_DATA_STRUCT_VERSION; + + /* memcpy(DEST, SRC, N) */ + memcpy( + &(pcal_data->customer), + &(pdev->customer), + sizeof(VL53L1_customer_nvm_managed_t)); + + /* Overwrite Struct with xtalk config parameters */ + /* - customer struct versions are not golden copy */ + + if (pdev->xtalk_cfg.algo__crosstalk_compensation_plane_offset_kcps > 0xFFFF) { + pcal_data->customer.algo__crosstalk_compensation_plane_offset_kcps = + 0xFFFF; + } else { + pcal_data->customer.algo__crosstalk_compensation_plane_offset_kcps = + (uint16_t)pdev->xtalk_cfg.algo__crosstalk_compensation_plane_offset_kcps; + } + pcal_data->customer.algo__crosstalk_compensation_x_plane_gradient_kcps = + pdev->xtalk_cfg.algo__crosstalk_compensation_x_plane_gradient_kcps; + pcal_data->customer.algo__crosstalk_compensation_y_plane_gradient_kcps = + pdev->xtalk_cfg.algo__crosstalk_compensation_y_plane_gradient_kcps; + + /* memcpy(DEST, SRC, N) */ + memcpy( + &(pcal_data->add_off_cal_data), + &(pdev->add_off_cal_data), + sizeof(VL53L1_additional_offset_cal_data_t)); + + /* memcpy(DEST, SRC, N) */ + memcpy( + &(pcal_data->optical_centre), + &(pdev->optical_centre), + sizeof(VL53L1_optical_centre_t)); + + /* memcpy(DEST, SRC, N) */ + memcpy( + &(pcal_data->gain_cal), + &(pdev->gain_cal), + sizeof(VL53L1_gain_calibration_data_t)); + + /* memcpy(DEST, SRC, N) */ + memcpy( + &(pcal_data->cal_peak_rate_map), + &(pdev->cal_peak_rate_map), + sizeof(VL53L1_cal_peak_rate_map_t)); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_inter_measurement_period_ms( + VL53L1_DEV Dev, + uint32_t inter_measurement_period_ms) +{ + /** + * Convenience function for setting the inter measurement period + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + if (pdev->dbg_results.result__osc_calibrate_val == 0) + status = VL53L1_ERROR_DIVISION_BY_ZERO; + + if (status == VL53L1_ERROR_NONE) { + pdev->inter_measurement_period_ms = inter_measurement_period_ms; + pdev->tim_cfg.system__intermeasurement_period = \ + inter_measurement_period_ms * + (uint32_t)pdev->dbg_results.result__osc_calibrate_val; + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_inter_measurement_period_ms( + VL53L1_DEV Dev, + uint32_t *pinter_measurement_period_ms) +{ + /** + * Convenience function for getting the inter measurement period + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + if (pdev->dbg_results.result__osc_calibrate_val == 0) + status = VL53L1_ERROR_DIVISION_BY_ZERO; + + if (status == VL53L1_ERROR_NONE) + *pinter_measurement_period_ms = \ + pdev->tim_cfg.system__intermeasurement_period / + (uint32_t)pdev->dbg_results.result__osc_calibrate_val; + + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_timeouts_us( + VL53L1_DEV Dev, + uint32_t phasecal_config_timeout_us, + uint32_t mm_config_timeout_us, + uint32_t range_config_timeout_us) +{ + /** + * Convenience function for setting the MM and range + * timeouts + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + if (pdev->stat_nvm.osc_measured__fast_osc__frequency == 0) + status = VL53L1_ERROR_DIVISION_BY_ZERO; + + if (status == VL53L1_ERROR_NONE) { + + pdev->phasecal_config_timeout_us = phasecal_config_timeout_us; + pdev->mm_config_timeout_us = mm_config_timeout_us; + pdev->range_config_timeout_us = range_config_timeout_us; + + status = + VL53L1_calc_timeout_register_values( + phasecal_config_timeout_us, + mm_config_timeout_us, + range_config_timeout_us, + pdev->stat_nvm.osc_measured__fast_osc__frequency, + &(pdev->gen_cfg), + &(pdev->tim_cfg)); + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_timeouts_us( + VL53L1_DEV Dev, + uint32_t *pphasecal_config_timeout_us, + uint32_t *pmm_config_timeout_us, + uint32_t *prange_config_timeout_us) +{ + /** + * Convenience function for getting the MM and range + * timeouts + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + uint32_t macro_period_us = 0; + uint16_t timeout_encoded = 0; + + LOG_FUNCTION_START(""); + + if (pdev->stat_nvm.osc_measured__fast_osc__frequency == 0) + status = VL53L1_ERROR_DIVISION_BY_ZERO; + + if (status == VL53L1_ERROR_NONE) { + + /* Update Macro Period for Range A VCSEL Period */ + macro_period_us = + VL53L1_calc_macro_period_us( + pdev->stat_nvm.osc_measured__fast_osc__frequency, + pdev->tim_cfg.range_config__vcsel_period_a); + + /* Get Phase Cal Timing A timeout */ + + *pphasecal_config_timeout_us = + VL53L1_calc_timeout_us( + (uint32_t)pdev->gen_cfg.phasecal_config__timeout_macrop, + macro_period_us); + + /* Get MM Timing A timeout */ + + timeout_encoded = + (uint16_t)pdev->tim_cfg.mm_config__timeout_macrop_a_hi; + timeout_encoded = (timeout_encoded << 8) + + (uint16_t)pdev->tim_cfg.mm_config__timeout_macrop_a_lo; + + *pmm_config_timeout_us = + VL53L1_calc_decoded_timeout_us( + timeout_encoded, + macro_period_us); + + /* Get Range Timing A timeout */ + + timeout_encoded = + (uint16_t)pdev->tim_cfg.range_config__timeout_macrop_a_hi; + timeout_encoded = (timeout_encoded << 8) + + (uint16_t)pdev->tim_cfg.range_config__timeout_macrop_a_lo; + + *prange_config_timeout_us = + VL53L1_calc_decoded_timeout_us( + timeout_encoded, + macro_period_us); + + pdev->phasecal_config_timeout_us = *pphasecal_config_timeout_us; + pdev->mm_config_timeout_us = *pmm_config_timeout_us; + pdev->range_config_timeout_us = *prange_config_timeout_us; + + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_calibration_repeat_period( + VL53L1_DEV Dev, + uint16_t cal_config__repeat_period) +{ + /** + * Convenience function for setting calibration repeat period + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + pdev->gen_cfg.cal_config__repeat_rate = cal_config__repeat_period; + + return status; + +} + + +VL53L1_Error VL53L1_get_calibration_repeat_period( + VL53L1_DEV Dev, + uint16_t *pcal_config__repeat_period) +{ + /** + * Convenience function for getting calibration repeat period + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + *pcal_config__repeat_period = pdev->gen_cfg.cal_config__repeat_rate; + + return status; + +} + + +VL53L1_Error VL53L1_set_sequence_config_bit( + VL53L1_DEV Dev, + VL53L1_DeviceSequenceConfig bit_id, + uint8_t value) +{ + /** + * Convenience function for setting sequence + * config enable bits + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t bit_mask = 0x01; + uint8_t clr_mask = 0xFF - bit_mask; + uint8_t bit_value = value & bit_mask; + + if (bit_id <= VL53L1_DEVICESEQUENCECONFIG_RANGE) { + + if (bit_id > 0) { + bit_mask = 0x01 << bit_id; + bit_value = bit_value << bit_id; + clr_mask = 0xFF - bit_mask; + } + + pdev->dyn_cfg.system__sequence_config = \ + (pdev->dyn_cfg.system__sequence_config & clr_mask) | \ + bit_value; + + } else { + status = VL53L1_ERROR_INVALID_PARAMS; + } + + return status; + +} + + +VL53L1_Error VL53L1_get_sequence_config_bit( + VL53L1_DEV Dev, + VL53L1_DeviceSequenceConfig bit_id, + uint8_t *pvalue) +{ + /** + * Convenience function for getting sequence + * config enable bits + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t bit_mask = 0x01; + + if (bit_id <= VL53L1_DEVICESEQUENCECONFIG_RANGE) { + + if (bit_id > 0) { + bit_mask = 0x01 << bit_id; + } + + *pvalue = + pdev->dyn_cfg.system__sequence_config & bit_mask; + + if (bit_id > 0) { + *pvalue = *pvalue >> bit_id; + } + + } else { + status = VL53L1_ERROR_INVALID_PARAMS; + } + + return status; +} + + +VL53L1_Error VL53L1_set_interrupt_polarity( + VL53L1_DEV Dev, + VL53L1_DeviceInterruptPolarity interrupt_polarity) +{ + /** + * Convenience function for setting interrupt polarity + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + pdev->stat_cfg.gpio_hv_mux__ctrl = \ + (pdev->stat_cfg.gpio_hv_mux__ctrl & \ + VL53L1_DEVICEINTERRUPTPOLARITY_CLEAR_MASK) | \ + (interrupt_polarity & \ + VL53L1_DEVICEINTERRUPTPOLARITY_BIT_MASK); + + return status; + +} + + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_set_refspadchar_config_struct( + VL53L1_DEV Dev, + VL53L1_refspadchar_config_t *pdata) +{ + /* + * Allows user config of Ref SPAD Char data structure + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->refspadchar.device_test_mode = pdata->device_test_mode; + pdev->refspadchar.vcsel_period = pdata->vcsel_period; + pdev->refspadchar.timeout_us = pdata->timeout_us; + pdev->refspadchar.target_count_rate_mcps = + pdata->target_count_rate_mcps; + pdev->refspadchar.min_count_rate_limit_mcps = + pdata->min_count_rate_limit_mcps; + pdev->refspadchar.max_count_rate_limit_mcps = + pdata->max_count_rate_limit_mcps; + + LOG_FUNCTION_END(status); + + return status; +} +#endif + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_get_refspadchar_config_struct( + VL53L1_DEV Dev, + VL53L1_refspadchar_config_t *pdata) +{ + /* + * Allows user config of Ref SPAD Char data structure + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdata->device_test_mode = pdev->refspadchar.device_test_mode; + pdata->vcsel_period = pdev->refspadchar.vcsel_period; + pdata->timeout_us = pdev->refspadchar.timeout_us; + pdata->target_count_rate_mcps = pdev->refspadchar.target_count_rate_mcps; + pdata->min_count_rate_limit_mcps = + pdev->refspadchar.min_count_rate_limit_mcps; + pdata->max_count_rate_limit_mcps = + pdev->refspadchar.max_count_rate_limit_mcps; + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_set_range_ignore_threshold( + VL53L1_DEV Dev, + uint8_t range_ignore_thresh_mult, + uint16_t range_ignore_threshold_mcps) +{ + /** + * Convenience function for setting Range Ignore Threshold + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + pdev->xtalk_cfg.crosstalk_range_ignore_threshold_rate_mcps = + range_ignore_threshold_mcps; + + pdev->xtalk_cfg.crosstalk_range_ignore_threshold_mult = + range_ignore_thresh_mult; + + return status; + +} + +VL53L1_Error VL53L1_get_range_ignore_threshold( + VL53L1_DEV Dev, + uint8_t *prange_ignore_thresh_mult, + uint16_t *prange_ignore_threshold_mcps_internal, + uint16_t *prange_ignore_threshold_mcps_current) +{ + /** + * Convenience function for retrieving Range Ignore Threshold + * - Returns both the calculated internal value + * - and the value currently applied to device reg settings + * + * Values both in fixed point 3.13 Mcps per spad + * + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + *prange_ignore_thresh_mult = + pdev->xtalk_cfg.crosstalk_range_ignore_threshold_mult; + + *prange_ignore_threshold_mcps_current = + pdev->stat_cfg.algo__range_ignore_threshold_mcps; + + *prange_ignore_threshold_mcps_internal = + pdev->xtalk_cfg.crosstalk_range_ignore_threshold_rate_mcps; + + return status; + +} + + + +VL53L1_Error VL53L1_get_interrupt_polarity( + VL53L1_DEV Dev, + VL53L1_DeviceInterruptPolarity *pinterrupt_polarity) +{ + /** + * Convenience function for getting interrupt polarity + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + *pinterrupt_polarity = \ + pdev->stat_cfg.gpio_hv_mux__ctrl & \ + VL53L1_DEVICEINTERRUPTPOLARITY_BIT_MASK ; + + return status; + +} + + +VL53L1_Error VL53L1_set_user_zone( + VL53L1_DEV Dev, + VL53L1_user_zone_t *puser_zone) +{ + /** + * Convenience function for setting the user ROI + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + /* convert (row,col) location into a SPAD number */ + VL53L1_encode_row_col( + puser_zone->y_centre, + puser_zone->x_centre, + &(pdev->dyn_cfg.roi_config__user_roi_centre_spad)); + + /* merge x and y sizes */ + VL53L1_encode_zone_size( + puser_zone->width, + puser_zone->height, + &(pdev->dyn_cfg.roi_config__user_roi_requested_global_xy_size)); + + /* need to add checks to ensure ROI is within array */ + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_user_zone( + VL53L1_DEV Dev, + VL53L1_user_zone_t *puser_zone) +{ + /** + * Convenience function for getting the user ROI + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + /* convert SPAD number into (row,col) location*/ + VL53L1_decode_row_col( + pdev->dyn_cfg.roi_config__user_roi_centre_spad, + &(puser_zone->y_centre), + &(puser_zone->x_centre)); + + /* extract x and y sizes */ + VL53L1_decode_zone_size( + pdev->dyn_cfg.roi_config__user_roi_requested_global_xy_size, + &(puser_zone->width), + &(puser_zone->height)); + + LOG_FUNCTION_END(status); + + return status; +} + + + +VL53L1_Error VL53L1_get_mode_mitigation_roi( + VL53L1_DEV Dev, + VL53L1_user_zone_t *pmm_roi) +{ + /** + * Convenience function for getting the mode mitigation ROI + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t x = 0; + uint8_t y = 0; + uint8_t xy_size = 0; + + LOG_FUNCTION_START(""); + + /* convert SPAD number into (row,col) location */ + VL53L1_decode_row_col( + pdev->nvm_copy_data.roi_config__mode_roi_centre_spad, + &y, + &x); + + pmm_roi->x_centre = x; + pmm_roi->y_centre = y; + + /* extract x and y sizes + * + * Important: the sense of the device width and height is swapped + * versus the API sense + * + * MS Nibble = height + * LS Nibble = width + */ + xy_size = pdev->nvm_copy_data.roi_config__mode_roi_xy_size; + + pmm_roi->height = xy_size >> 4; + pmm_roi->width = xy_size & 0x0F; + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_get_preset_mode_timing_cfg( + VL53L1_DEV Dev, + VL53L1_DevicePresetModes device_preset_mode, + uint16_t *pdss_config__target_total_rate_mcps, + uint32_t *pphasecal_config_timeout_us, + uint32_t *pmm_config_timeout_us, + uint32_t *prange_config_timeout_us) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + + switch (device_preset_mode) { + + case VL53L1_DEVICEPRESETMODE_STANDARD_RANGING: + case VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_SHORT_RANGE: + case VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_LONG_RANGE: + case VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM1_CAL: + case VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM2_CAL: + case VL53L1_DEVICEPRESETMODE_OLT: + *pdss_config__target_total_rate_mcps = + pdev->tuning_parms.tp_dss_target_lite_mcps; + *pphasecal_config_timeout_us = + pdev->tuning_parms.tp_phasecal_timeout_lite_us; + *pmm_config_timeout_us = + pdev->tuning_parms.tp_mm_timeout_lite_us; + *prange_config_timeout_us = + pdev->tuning_parms.tp_range_timeout_lite_us; + break; + + case VL53L1_DEVICEPRESETMODE_TIMED_RANGING: + case VL53L1_DEVICEPRESETMODE_TIMED_RANGING_SHORT_RANGE: + case VL53L1_DEVICEPRESETMODE_TIMED_RANGING_LONG_RANGE: + case VL53L1_DEVICEPRESETMODE_SINGLESHOT_RANGING: + *pdss_config__target_total_rate_mcps = + pdev->tuning_parms.tp_dss_target_timed_mcps; + *pphasecal_config_timeout_us = + pdev->tuning_parms.tp_phasecal_timeout_timed_us; + *pmm_config_timeout_us = + pdev->tuning_parms.tp_mm_timeout_timed_us; + *prange_config_timeout_us = + pdev->tuning_parms.tp_range_timeout_timed_us; + break; + + case VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_SHORT_RANGE: + case VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_MEDIUM_RANGE: + case VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_LONG_RANGE: + *pdss_config__target_total_rate_mcps = + pdev->tuning_parms.tp_dss_target_timed_mcps; + *pphasecal_config_timeout_us = + pdev->tuning_parms.tp_phasecal_timeout_timed_us; + *pmm_config_timeout_us = + pdev->tuning_parms.tp_mm_timeout_lpa_us; + *prange_config_timeout_us = + pdev->tuning_parms.tp_range_timeout_lpa_us; + break; + + default: + status = VL53L1_ERROR_INVALID_PARAMS; + break; + + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_preset_mode( + VL53L1_DEV Dev, + VL53L1_DevicePresetModes device_preset_mode, + uint16_t dss_config__target_total_rate_mcps, + uint32_t phasecal_config_timeout_us, + uint32_t mm_config_timeout_us, + uint32_t range_config_timeout_us, + uint32_t inter_measurement_period_ms) +{ + /** + * Initializes static and dynamic data structures for + * the provided preset mode + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + VL53L1_static_config_t *pstatic = &(pdev->stat_cfg); + VL53L1_general_config_t *pgeneral = &(pdev->gen_cfg); + VL53L1_timing_config_t *ptiming = &(pdev->tim_cfg); + VL53L1_dynamic_config_t *pdynamic = &(pdev->dyn_cfg); + VL53L1_system_control_t *psystem = &(pdev->sys_ctrl); + VL53L1_tuning_parm_storage_t *ptuning_parms = &(pdev->tuning_parms); + VL53L1_low_power_auto_data_t *plpadata = + &(pdev->low_power_auto_data); + + LOG_FUNCTION_START(""); + + /* save input settings */ + pdev->preset_mode = device_preset_mode; + pdev->mm_config_timeout_us = mm_config_timeout_us; + pdev->range_config_timeout_us = range_config_timeout_us; + pdev->inter_measurement_period_ms = inter_measurement_period_ms; + + /* Reset LL Driver state variables */ + + VL53L1_init_ll_driver_state( + Dev, + VL53L1_DEVICESTATE_SW_STANDBY); + + /* apply selected preset */ + + switch (device_preset_mode) { + + case VL53L1_DEVICEPRESETMODE_STANDARD_RANGING: + status = VL53L1_preset_mode_standard_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + break; + + case VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_SHORT_RANGE: + status = VL53L1_preset_mode_standard_ranging_short_range( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + break; + + case VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_LONG_RANGE: + status = VL53L1_preset_mode_standard_ranging_long_range( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + break; + +#ifndef VL53L1_NOCALIB + case VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM1_CAL: + status = VL53L1_preset_mode_standard_ranging_mm1_cal( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + break; + + case VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM2_CAL: + status = VL53L1_preset_mode_standard_ranging_mm2_cal( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + break; +#endif + + case VL53L1_DEVICEPRESETMODE_TIMED_RANGING: + status = VL53L1_preset_mode_timed_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + break; + + case VL53L1_DEVICEPRESETMODE_TIMED_RANGING_SHORT_RANGE: + status = VL53L1_preset_mode_timed_ranging_short_range( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + break; + + case VL53L1_DEVICEPRESETMODE_TIMED_RANGING_LONG_RANGE: + status = VL53L1_preset_mode_timed_ranging_long_range( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + break; + + case VL53L1_DEVICEPRESETMODE_OLT: + status = VL53L1_preset_mode_olt( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + break; + + case VL53L1_DEVICEPRESETMODE_SINGLESHOT_RANGING: + status = VL53L1_preset_mode_singleshot_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + break; + + case VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_SHORT_RANGE: + status = VL53L1_preset_mode_low_power_auto_short_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms, + plpadata); + break; + + case VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_MEDIUM_RANGE: + status = VL53L1_preset_mode_low_power_auto_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms, + plpadata); + break; + + case VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_LONG_RANGE: + status = VL53L1_preset_mode_low_power_auto_long_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms, + plpadata); + break; + + default: + status = VL53L1_ERROR_INVALID_PARAMS; + break; + + } + + /* update DSS target */ + + if (status == VL53L1_ERROR_NONE) { + + pstatic->dss_config__target_total_rate_mcps = + dss_config__target_total_rate_mcps; + pdev->dss_config__target_total_rate_mcps = + dss_config__target_total_rate_mcps; + + } + + /* + * Update the register timeout values based on input + * real time values and preset mode VCSEL periods + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_set_timeouts_us( + Dev, + phasecal_config_timeout_us, + mm_config_timeout_us, + range_config_timeout_us); + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_set_inter_measurement_period_ms( + Dev, + inter_measurement_period_ms); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_enable_xtalk_compensation( + VL53L1_DEV Dev) +{ + /** + * Currently a very simple function to copy + * private xtalk parms into customer section and apply to device + * + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint32_t tempu32; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + /* Fill Public customer NVM data with Xtalk parms */ + tempu32 = VL53L1_calc_crosstalk_plane_offset_with_margin( + pdev->xtalk_cfg.algo__crosstalk_compensation_plane_offset_kcps, + pdev->xtalk_cfg.lite_mode_crosstalk_margin_kcps); + if (tempu32 > 0xFFFF) { + tempu32 = 0xFFFF; + } + pdev->customer.algo__crosstalk_compensation_plane_offset_kcps = + (uint16_t)tempu32; + + pdev->customer.algo__crosstalk_compensation_x_plane_gradient_kcps = + pdev->xtalk_cfg.algo__crosstalk_compensation_x_plane_gradient_kcps; + + pdev->customer.algo__crosstalk_compensation_y_plane_gradient_kcps = + pdev->xtalk_cfg.algo__crosstalk_compensation_y_plane_gradient_kcps; + + /* Enable Xtalk compensation */ + pdev->xtalk_cfg.global_crosstalk_compensation_enable = 0x01; + + /* Update Range Ignore Threshold Xtalk Parameter */ + + if (status == VL53L1_ERROR_NONE) { + pdev->xtalk_cfg.crosstalk_range_ignore_threshold_rate_mcps = + VL53L1_calc_range_ignore_threshold( + pdev->xtalk_cfg.algo__crosstalk_compensation_plane_offset_kcps, + pdev->xtalk_cfg.algo__crosstalk_compensation_x_plane_gradient_kcps, + pdev->xtalk_cfg.algo__crosstalk_compensation_y_plane_gradient_kcps, + pdev->xtalk_cfg.crosstalk_range_ignore_threshold_mult); + } + + /* Apply to device */ + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = + VL53L1_set_customer_nvm_managed( + Dev, + &(pdev->customer)); + + LOG_FUNCTION_END(status); + + return status; + +} + +void VL53L1_get_xtalk_compensation_enable( + VL53L1_DEV Dev, + uint8_t *pcrosstalk_compensation_enable) +{ + /** + * Currently a very simple function to return + * + * - this flags whether xtalk compensation is enabled for all modes + * or not. + * + * #1 - Enabled + * #0 - Disabled + * + */ + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + /* Extract Xtalk Compensation Enable Status*/ + + *pcrosstalk_compensation_enable = + pdev->xtalk_cfg.global_crosstalk_compensation_enable; + +} + + +VL53L1_Error VL53L1_get_lite_xtalk_margin_kcps( + VL53L1_DEV Dev, + int16_t *pxtalk_margin) +{ + + /* + * Gets the Xtalk Margin Factor in Kcps (fixed point 9.7) + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + *pxtalk_margin = pdev->xtalk_cfg.lite_mode_crosstalk_margin_kcps; + + LOG_FUNCTION_END(status); + + return status; + +} + +VL53L1_Error VL53L1_set_lite_xtalk_margin_kcps( + VL53L1_DEV Dev, + int16_t xtalk_margin) +{ + + /* + * Sets the offset calibration mode + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->xtalk_cfg.lite_mode_crosstalk_margin_kcps = xtalk_margin; + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_restore_xtalk_nvm_default( + VL53L1_DEV Dev) +{ + + /* + * Returns xtalk rate values to defaults as extracted from device NVM + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->xtalk_cfg.algo__crosstalk_compensation_plane_offset_kcps = + pdev->xtalk_cfg.nvm_default__crosstalk_compensation_plane_offset_kcps; + pdev->xtalk_cfg.algo__crosstalk_compensation_x_plane_gradient_kcps = + pdev->xtalk_cfg.nvm_default__crosstalk_compensation_x_plane_gradient_kcps; + pdev->xtalk_cfg.algo__crosstalk_compensation_y_plane_gradient_kcps = + pdev->xtalk_cfg.nvm_default__crosstalk_compensation_y_plane_gradient_kcps; + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_disable_xtalk_compensation( + VL53L1_DEV Dev) +{ + /** + * Currently a very simple function to clear + * customer xtalk parms and apply to device + * + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + /* Fill Public customer NVM data with Xtalk parms */ + pdev->customer.algo__crosstalk_compensation_plane_offset_kcps = + 0x00; + + pdev->customer.algo__crosstalk_compensation_x_plane_gradient_kcps = + 0x00; + + pdev->customer.algo__crosstalk_compensation_y_plane_gradient_kcps = + 0x00; + + + /* Disable Global Xtalk comnpensation */ + pdev->xtalk_cfg.global_crosstalk_compensation_enable = 0x00; + + /* Update Range Ignore Threshold Xtalk Parameter */ + + if (status == VL53L1_ERROR_NONE) { + pdev->xtalk_cfg.crosstalk_range_ignore_threshold_rate_mcps = + 0x0000; + } + + /* Apply to device */ + + if (status == VL53L1_ERROR_NONE) { /*lint !e774 always true*/ + status = + VL53L1_set_customer_nvm_managed( + Dev, + &(pdev->customer)); + } + LOG_FUNCTION_END(status); + + return status; + +} + +VL53L1_Error VL53L1_get_lite_sigma_threshold( + VL53L1_DEV Dev, + uint16_t *plite_sigma) +{ + + /* + * Gets the Sigma Threshold value for Lite Mode + * + * (fixed point 14.2) + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + *plite_sigma = + pdev->tim_cfg.range_config__sigma_thresh; + + LOG_FUNCTION_END(status); + + return status; + +} + +VL53L1_Error VL53L1_set_lite_sigma_threshold( + VL53L1_DEV Dev, + uint16_t lite_sigma) +{ + + /* + * Sets the Sigma threshold value for Lite mode + * + * (fixed point 14.2) + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->tim_cfg.range_config__sigma_thresh = lite_sigma; + + LOG_FUNCTION_END(status); + + return status; + +} + +VL53L1_Error VL53L1_get_lite_min_count_rate( + VL53L1_DEV Dev, + uint16_t *plite_mincountrate) +{ + + /* + * Gets the Min Count Rate value for Lite Mode + * + * (fixed point 9.7 Mcps) + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + *plite_mincountrate = + pdev->tim_cfg.range_config__min_count_rate_rtn_limit_mcps; + + LOG_FUNCTION_END(status); + + return status; + +} + +VL53L1_Error VL53L1_set_lite_min_count_rate( + VL53L1_DEV Dev, + uint16_t lite_mincountrate) +{ + + /* + * Sets the Min COunt Rate value for Lite mode + * + * (fixed point 19.7Mcps) + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->tim_cfg.range_config__min_count_rate_rtn_limit_mcps = + lite_mincountrate; + + LOG_FUNCTION_END(status); + + return status; + +} + +VL53L1_Error VL53L1_get_vhv_loopbound( + VL53L1_DEV Dev, + uint8_t *pvhv_loopbound) +{ + + /* + * Gets the VHV Loop bound parm + * - extracts only bits 7:2 from internal stat nvm parm + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + *pvhv_loopbound = pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound / 4 ; + + LOG_FUNCTION_END(status); + + return status; + +} + + + +VL53L1_Error VL53L1_set_vhv_loopbound( + VL53L1_DEV Dev, + uint8_t vhv_loopbound) +{ + + /* + * Sets the VHV Loop bound parm + * - sets only bits 7:2 + * - bits 1:0 remain unchanged + * - ensure that any change here is followed by a + * init_and_start_range with full i2c packet + * configuration. + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound = + (pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound & 0x03) + + (vhv_loopbound * 4); + + LOG_FUNCTION_END(status); + + return status; + +} + + + +VL53L1_Error VL53L1_get_vhv_config( + VL53L1_DEV Dev, + uint8_t *pvhv_init_en, + uint8_t *pvhv_init_value) +{ + + /* + * Gets the VHV config init data + */ + + /*!< + info: \n + - msb = 7 + - lsb = 0 + - i2c_size = 1 + + fields: \n + - [7] = vhv0_init_enable + - [5:0] = vhv0_init_value + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + *pvhv_init_en = (pdev->stat_nvm.vhv_config__init & 0x80) >> 7; + *pvhv_init_value = + (pdev->stat_nvm.vhv_config__init & 0x7F); + + LOG_FUNCTION_END(status); + + return status; + +} + + + +VL53L1_Error VL53L1_set_vhv_config( + VL53L1_DEV Dev, + uint8_t vhv_init_en, + uint8_t vhv_init_value) +{ + + /* + * Sets the VHV Config init + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->stat_nvm.vhv_config__init = + ((vhv_init_en & 0x01) << 7) + + (vhv_init_value & 0x7F); + + LOG_FUNCTION_END(status); + + return status; + +} + + + +VL53L1_Error VL53L1_init_and_start_range( + VL53L1_DEV Dev, + uint8_t measurement_mode, + VL53L1_DeviceConfigLevel device_config_level) +{ + /* + * Builds and sends a single I2C multiple byte transaction to + * initialize the device and start a range measurement. + * + * The level of initialization is controlled by the + * device_config_level input parameter + * + * system_control is always sent as the last byte of this + * register group (mode_start) either triggers the range + * or enables the next range + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t buffer[VL53L1_MAX_I2C_XFER_SIZE]; + + VL53L1_static_nvm_managed_t *pstatic_nvm = &(pdev->stat_nvm); + VL53L1_customer_nvm_managed_t *pcustomer_nvm = &(pdev->customer); + VL53L1_static_config_t *pstatic = &(pdev->stat_cfg); + VL53L1_general_config_t *pgeneral = &(pdev->gen_cfg); + VL53L1_timing_config_t *ptiming = &(pdev->tim_cfg); + VL53L1_dynamic_config_t *pdynamic = &(pdev->dyn_cfg); + VL53L1_system_control_t *psystem = &(pdev->sys_ctrl); + + VL53L1_ll_driver_state_t *pstate = &(pdev->ll_state); + + uint8_t *pbuffer = &buffer[0]; + uint16_t i = 0; + uint16_t i2c_index = 0; + uint16_t i2c_buffer_offset_bytes = 0; + uint16_t i2c_buffer_size_bytes = 0; + + LOG_FUNCTION_START(""); + + /* save measurement mode */ + pdev->measurement_mode = measurement_mode; + + /* Merge measurement mode with mode_start */ + + psystem->system__mode_start = + (psystem->system__mode_start & + VL53L1_DEVICEMEASUREMENTMODE_STOP_MASK) | + measurement_mode; + + /* copy in rit from xtalk config */ + + pdev->stat_cfg.algo__range_ignore_threshold_mcps = + pdev->xtalk_cfg.crosstalk_range_ignore_threshold_rate_mcps; + + /* Start Patch_LowPowerAutoMode */ + + /* doing this ensures stop_range followed by a get_device_results does + * not mess up the counters */ + + if (pdev->low_power_auto_data.low_power_auto_range_count == 0xFF) { + pdev->low_power_auto_data.low_power_auto_range_count = 0x0; + } + + /* For Presence. Override threshold config */ + if ((pdev->low_power_auto_data.is_low_power_auto_mode == 1) && + (pdev->low_power_auto_data.low_power_auto_range_count == 0)) { + /* save interrupt config */ + pdev->low_power_auto_data.saved_interrupt_config = + pdev->gen_cfg.system__interrupt_config_gpio; + /* set intr_new_measure_ready */ + pdev->gen_cfg.system__interrupt_config_gpio = 1 << 5; + /* check MM1/MM2 disabled? */ + if ((pdev->dyn_cfg.system__sequence_config & ( + VL53L1_SEQUENCE_MM1_EN | VL53L1_SEQUENCE_MM2_EN)) == + 0x0) { + pdev->customer.algo__part_to_part_range_offset_mm = + pdev->customer.mm_config__outer_offset_mm * 4; + } else { + pdev->customer.algo__part_to_part_range_offset_mm = 0x0; + } + + /* make sure config gets written out */ + if (device_config_level < + VL53L1_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS) { + device_config_level = + VL53L1_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS; + } + } + + if ((pdev->low_power_auto_data.is_low_power_auto_mode == 1) && + (pdev->low_power_auto_data.low_power_auto_range_count == 1)) { + /* restore interrupt config */ + pdev->gen_cfg.system__interrupt_config_gpio = + pdev->low_power_auto_data.saved_interrupt_config; + + /* make sure config gets written out including VHV config */ + device_config_level = VL53L1_DEVICECONFIGLEVEL_FULL; + } + + /* End Patch_LowPowerAutoMode */ + + /* + * Determine Initial I2C index + */ + + switch (device_config_level) { + case VL53L1_DEVICECONFIGLEVEL_FULL: + i2c_index = VL53L1_STATIC_NVM_MANAGED_I2C_INDEX; + break; + case VL53L1_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS: + i2c_index = VL53L1_CUSTOMER_NVM_MANAGED_I2C_INDEX; + break; + case VL53L1_DEVICECONFIGLEVEL_STATIC_ONWARDS: + i2c_index = VL53L1_STATIC_CONFIG_I2C_INDEX; + break; + case VL53L1_DEVICECONFIGLEVEL_GENERAL_ONWARDS: + i2c_index = VL53L1_GENERAL_CONFIG_I2C_INDEX; + break; + case VL53L1_DEVICECONFIGLEVEL_TIMING_ONWARDS: + i2c_index = VL53L1_TIMING_CONFIG_I2C_INDEX; + break; + case VL53L1_DEVICECONFIGLEVEL_DYNAMIC_ONWARDS: + i2c_index = VL53L1_DYNAMIC_CONFIG_I2C_INDEX; + break; + default: + i2c_index = VL53L1_SYSTEM_CONTROL_I2C_INDEX; + break; + } + + /* I2C Buffer size */ + + i2c_buffer_size_bytes = \ + (VL53L1_SYSTEM_CONTROL_I2C_INDEX + + VL53L1_SYSTEM_CONTROL_I2C_SIZE_BYTES) - + i2c_index; + + /* Initialize buffer */ + + pbuffer = &buffer[0]; + for (i = 0 ; i < i2c_buffer_size_bytes ; i++) { + *pbuffer++ = 0; + } + + /* Build I2C buffer */ + + if (device_config_level >= VL53L1_DEVICECONFIGLEVEL_FULL && + status == VL53L1_ERROR_NONE) { + + i2c_buffer_offset_bytes = \ + VL53L1_STATIC_NVM_MANAGED_I2C_INDEX - i2c_index; + + status = + VL53L1_i2c_encode_static_nvm_managed( + pstatic_nvm, + VL53L1_STATIC_NVM_MANAGED_I2C_SIZE_BYTES, + &buffer[i2c_buffer_offset_bytes]); + } + + if (device_config_level >= VL53L1_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS && + status == VL53L1_ERROR_NONE) { + + i2c_buffer_offset_bytes = \ + VL53L1_CUSTOMER_NVM_MANAGED_I2C_INDEX - i2c_index; + + status = + VL53L1_i2c_encode_customer_nvm_managed( + pcustomer_nvm, + VL53L1_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES, + &buffer[i2c_buffer_offset_bytes]); + } + + if (device_config_level >= VL53L1_DEVICECONFIGLEVEL_STATIC_ONWARDS && + status == VL53L1_ERROR_NONE) { + + i2c_buffer_offset_bytes = \ + VL53L1_STATIC_CONFIG_I2C_INDEX - i2c_index; + + status = + VL53L1_i2c_encode_static_config( + pstatic, + VL53L1_STATIC_CONFIG_I2C_SIZE_BYTES, + &buffer[i2c_buffer_offset_bytes]); + } + + if (device_config_level >= VL53L1_DEVICECONFIGLEVEL_GENERAL_ONWARDS && + status == VL53L1_ERROR_NONE) { + + i2c_buffer_offset_bytes = + VL53L1_GENERAL_CONFIG_I2C_INDEX - i2c_index; + + status = + VL53L1_i2c_encode_general_config( + pgeneral, + VL53L1_GENERAL_CONFIG_I2C_SIZE_BYTES, + &buffer[i2c_buffer_offset_bytes]); + } + + if (device_config_level >= VL53L1_DEVICECONFIGLEVEL_TIMING_ONWARDS && + status == VL53L1_ERROR_NONE) { + + i2c_buffer_offset_bytes = \ + VL53L1_TIMING_CONFIG_I2C_INDEX - i2c_index; + + status = + VL53L1_i2c_encode_timing_config( + ptiming, + VL53L1_TIMING_CONFIG_I2C_SIZE_BYTES, + &buffer[i2c_buffer_offset_bytes]); + } + + if (device_config_level >= VL53L1_DEVICECONFIGLEVEL_DYNAMIC_ONWARDS && + status == VL53L1_ERROR_NONE) { + + i2c_buffer_offset_bytes = \ + VL53L1_DYNAMIC_CONFIG_I2C_INDEX - i2c_index; + + /* If in back to back mode, use GPH ID from cfg_state */ + if ((psystem->system__mode_start & + VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK) == + VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK) { + pdynamic->system__grouped_parameter_hold_0 = pstate->cfg_gph_id | 0x01; + pdynamic->system__grouped_parameter_hold_1 = pstate->cfg_gph_id | 0x01; + pdynamic->system__grouped_parameter_hold = pstate->cfg_gph_id; + } + status = + VL53L1_i2c_encode_dynamic_config( + pdynamic, + VL53L1_DYNAMIC_CONFIG_I2C_SIZE_BYTES, + &buffer[i2c_buffer_offset_bytes]); + } + + if (status == VL53L1_ERROR_NONE) { + + i2c_buffer_offset_bytes = \ + VL53L1_SYSTEM_CONTROL_I2C_INDEX - i2c_index; + + status = + VL53L1_i2c_encode_system_control( + psystem, + VL53L1_SYSTEM_CONTROL_I2C_SIZE_BYTES, + &buffer[i2c_buffer_offset_bytes]); + } + + /* Send I2C Buffer */ + + if (status == VL53L1_ERROR_NONE) { + status = + VL53L1_WriteMulti( + Dev, + i2c_index, + buffer, + (uint32_t)i2c_buffer_size_bytes); + } + + /* + * Update LL Driver State + */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_update_ll_driver_rd_state(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_update_ll_driver_cfg_state(Dev); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_stop_range( + VL53L1_DEV Dev) +{ + /* + * Stops any in process range using the ABORT command + * Also clears all of the measurement mode bits + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + /* Merge ABORT mode with mode_start */ + + pdev->sys_ctrl.system__mode_start = + (pdev->sys_ctrl.system__mode_start & VL53L1_DEVICEMEASUREMENTMODE_STOP_MASK) | + VL53L1_DEVICEMEASUREMENTMODE_ABORT; + + status = VL53L1_set_system_control( + Dev, + &pdev->sys_ctrl); + + /* Abort bit is auto clear so clear register group structure to match */ + pdev->sys_ctrl.system__mode_start = + (pdev->sys_ctrl.system__mode_start & VL53L1_DEVICEMEASUREMENTMODE_STOP_MASK); + + /* reset zone dynamic info */ + VL53L1_init_ll_driver_state( + Dev, + VL53L1_DEVICESTATE_SW_STANDBY); + + /* reset low power auto */ + if (pdev->low_power_auto_data.is_low_power_auto_mode == 1) + VL53L1_low_power_auto_data_stop_range(Dev); + + return status; +} + + +VL53L1_Error VL53L1_get_measurement_results( + VL53L1_DEV Dev, + VL53L1_DeviceResultsLevel device_results_level) +{ + /* + * Read via a single I2C multiple byte transaction all + * of the requested device measurement data results + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t buffer[VL53L1_MAX_I2C_XFER_SIZE]; + + VL53L1_system_results_t *psystem_results = &(pdev->sys_results); + VL53L1_core_results_t *pcore_results = &(pdev->core_results); + VL53L1_debug_results_t *pdebug_results = &(pdev->dbg_results); + + uint16_t i2c_index = VL53L1_SYSTEM_RESULTS_I2C_INDEX; + uint16_t i2c_buffer_offset_bytes = 0; + uint16_t i2c_buffer_size_bytes = 0; + + LOG_FUNCTION_START(""); + + /* Determine multi byte read transaction size */ + + switch (device_results_level) { + case VL53L1_DEVICERESULTSLEVEL_FULL: + i2c_buffer_size_bytes = + (VL53L1_DEBUG_RESULTS_I2C_INDEX + + VL53L1_DEBUG_RESULTS_I2C_SIZE_BYTES) - + i2c_index; + break; + case VL53L1_DEVICERESULTSLEVEL_UPTO_CORE: + i2c_buffer_size_bytes = + (VL53L1_CORE_RESULTS_I2C_INDEX + + VL53L1_CORE_RESULTS_I2C_SIZE_BYTES) - + i2c_index; + break; + default: + i2c_buffer_size_bytes = + VL53L1_SYSTEM_RESULTS_I2C_SIZE_BYTES; + break; + } + + /* Read Result Data */ + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = + VL53L1_ReadMulti( + Dev, + i2c_index, + buffer, + (uint32_t)i2c_buffer_size_bytes); + + /* Decode I2C buffer */ + + if (device_results_level >= VL53L1_DEVICERESULTSLEVEL_FULL && + status == VL53L1_ERROR_NONE) { + + i2c_buffer_offset_bytes = + VL53L1_DEBUG_RESULTS_I2C_INDEX - i2c_index; + + status = + VL53L1_i2c_decode_debug_results( + VL53L1_DEBUG_RESULTS_I2C_SIZE_BYTES, + &buffer[i2c_buffer_offset_bytes], + pdebug_results); + } + + if (device_results_level >= VL53L1_DEVICERESULTSLEVEL_UPTO_CORE && + status == VL53L1_ERROR_NONE) { + + i2c_buffer_offset_bytes = + VL53L1_CORE_RESULTS_I2C_INDEX - i2c_index; + + status = + VL53L1_i2c_decode_core_results( + VL53L1_CORE_RESULTS_I2C_SIZE_BYTES, + &buffer[i2c_buffer_offset_bytes], + pcore_results); + } + + if (status == VL53L1_ERROR_NONE) { + + i2c_buffer_offset_bytes = 0; + status = + VL53L1_i2c_decode_system_results( + VL53L1_SYSTEM_RESULTS_I2C_SIZE_BYTES, + &buffer[i2c_buffer_offset_bytes], + psystem_results); + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_device_results( + VL53L1_DEV Dev, + VL53L1_DeviceResultsLevel device_results_level, + VL53L1_range_results_t *prange_results) +{ + /* + * Wrapper function using the functions below + * + * VL53L1_get_measurement_results() + * VL53L1_init_and_start_range() + * VL53L1_copy_sys_and_core_results_to_range_results() + * + * The input measurement mode controls what happens next ... + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + VL53L1_LLDriverResults_t *pres = + VL53L1DevStructGetLLResultsHandle(Dev); + + VL53L1_range_results_t *presults = &(pres->range_results); + + LOG_FUNCTION_START(""); + + /* Get device results */ + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_get_measurement_results( + Dev, + device_results_level); + + if (status == VL53L1_ERROR_NONE) + VL53L1_copy_sys_and_core_results_to_range_results( + (int32_t)pdev->gain_cal.standard_ranging_gain_factor, + &(pdev->sys_results), + &(pdev->core_results), + presults); + + /* Start Patch_LowPowerAutoMode */ + /* process results from first range of low power auto */ + if (pdev->low_power_auto_data.is_low_power_auto_mode == 1) { + /* change to manual calibrations. Only needed on the + * first range out */ + if ((status == VL53L1_ERROR_NONE) && + (pdev->low_power_auto_data.low_power_auto_range_count == 0)) { + status = VL53L1_low_power_auto_setup_manual_calibration( + Dev); + pdev->low_power_auto_data.low_power_auto_range_count = 1; + } else if ((status == VL53L1_ERROR_NONE) && + (pdev->low_power_auto_data.low_power_auto_range_count == 1)) { + pdev->low_power_auto_data.low_power_auto_range_count = 2; + } + + } + /* End Patch_LowPowerAutoMode */ + + /* copy current state into results */ + + presults->cfg_device_state = pdev->ll_state.cfg_device_state; + presults->rd_device_state = pdev->ll_state.rd_device_state; + + /* copy internal structure to supplied output pointer */ + + memcpy( + prange_results, + presults, + sizeof(VL53L1_range_results_t)); + + /* + * Check LL driver and Device are in Sync + * If not an error is raised + */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_check_ll_driver_rd_state(Dev); + +#ifdef VL53L1_LOG_ENABLE + if (status == VL53L1_ERROR_NONE) + VL53L1_print_range_results( + presults, + "get_device_results():pdev->llresults.range_results.", + VL53L1_TRACE_MODULE_RANGE_RESULTS_DATA); +#endif + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_clear_interrupt_and_enable_next_range( + VL53L1_DEV Dev, + uint8_t measurement_mode) +{ + + /* + * Enable next range by sending handshake which + * clears the interrupt + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Dynamic Management */ + /* Current results analysis and generate next settings */ + + + /* Dynamic GPH Management */ + /* Setup GPH absorption point and config values for next measurement */ + + /* Update GPH registers, clear interrupt and set measurement mode */ + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_init_and_start_range( + Dev, + measurement_mode, + VL53L1_DEVICECONFIGLEVEL_GENERAL_ONWARDS); + + LOG_FUNCTION_END(status); + + return status; +} + + +void VL53L1_copy_sys_and_core_results_to_range_results( + int32_t gain_factor, + VL53L1_system_results_t *psys, + VL53L1_core_results_t *pcore, + VL53L1_range_results_t *presults) +{ + uint8_t i = 0; + + VL53L1_range_data_t *pdata; + int32_t range_mm = 0; + uint32_t tmpu32 = 0; + + LOG_FUNCTION_START(""); + + /* copy results */ + + presults->stream_count = psys->result__stream_count; + + pdata = &(presults->data[0]); + + for (i = 0 ; i < 2 ; i++) { + + pdata->range_id = i; + pdata->time_stamp = 0; + + if ((psys->result__stream_count == 0) && + ((psys->result__range_status & VL53L1_RANGE_STATUS__RANGE_STATUS_MASK) == + VL53L1_DEVICEERROR_RANGECOMPLETE)) { + pdata->range_status = VL53L1_DEVICEERROR_RANGECOMPLETE_NO_WRAP_CHECK; + } else { + pdata->range_status = + psys->result__range_status & VL53L1_RANGE_STATUS__RANGE_STATUS_MASK; + } + + switch (i) { + + case 0: + + if (psys->result__report_status == VL53L1_DEVICEREPORTSTATUS_MM1) + pdata->actual_effective_spads = + psys->result__mm_inner_actual_effective_spads_sd0; + else if (psys->result__report_status == VL53L1_DEVICEREPORTSTATUS_MM2) + pdata->actual_effective_spads = + psys->result__mm_outer_actual_effective_spads_sd0; + else + pdata->actual_effective_spads = + psys->result__dss_actual_effective_spads_sd0; + + pdata->peak_signal_count_rate_mcps = + psys->result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0; + pdata->avg_signal_count_rate_mcps = + psys->result__avg_signal_count_rate_mcps_sd0; + pdata->ambient_count_rate_mcps = + psys->result__ambient_count_rate_mcps_sd0; + + /* Start Patch_SigmaEstimateAccuracyImprovement */ + + /* shift up sigma estimate to 7 bit fractional and clip to 9 bit int */ + tmpu32 = ((uint32_t)psys->result__sigma_sd0 << 5); + if (tmpu32 > 0xFFFF) { + tmpu32 = 0xFFFF; + } + pdata->sigma_mm = (uint16_t)tmpu32; + + /* End Patch_SigmaEstimateAccuracyImprovement */ + + pdata->median_phase = + psys->result__phase_sd0; + + range_mm = + (int32_t)psys->result__final_crosstalk_corrected_range_mm_sd0; + + /* apply correction gain */ + range_mm *= gain_factor; + range_mm += 0x0400; + range_mm /= 0x0800; + + pdata->median_range_mm = (int16_t)range_mm; + + pdata->ranging_total_events = + pcore->result_core__ranging_total_events_sd0; + pdata->signal_total_events = + pcore->result_core__signal_total_events_sd0; + pdata->total_periods_elapsed = + pcore->result_core__total_periods_elapsed_sd0; + pdata->ambient_window_events = + pcore->result_core__ambient_window_events_sd0; + + break; + case 1: + + pdata->actual_effective_spads = + psys->result__dss_actual_effective_spads_sd1; + pdata->peak_signal_count_rate_mcps = + psys->result__peak_signal_count_rate_mcps_sd1; + pdata->avg_signal_count_rate_mcps = + 0xFFFF; + pdata->ambient_count_rate_mcps = + psys->result__ambient_count_rate_mcps_sd1; + + /* Start Patch_SigmaEstimateAccuracyImprovement */ + + /* shift up sigma estimate to 7 bit fractional and clip to 9 bit int */ + tmpu32 = ((uint32_t)psys->result__sigma_sd1 << 5); + if (tmpu32 > 0xFFFF) { + tmpu32 = 0xFFFF; + } + pdata->sigma_mm = (uint16_t)tmpu32; + + /* End Patch_SigmaEstimateAccuracyImprovement */ + + pdata->median_phase = + psys->result__phase_sd1; + + range_mm = + (int32_t)psys->result__final_crosstalk_corrected_range_mm_sd1; + + /* apply correction gain */ + range_mm *= gain_factor; + range_mm += 0x0400; + range_mm /= 0x0800; + + pdata->median_range_mm = (int16_t)range_mm; + + pdata->ranging_total_events = + pcore->result_core__ranging_total_events_sd1; + pdata->signal_total_events = + pcore->result_core__signal_total_events_sd1; + pdata->total_periods_elapsed = + pcore->result_core__total_periods_elapsed_sd1; + pdata->ambient_window_events = + pcore->result_core__ambient_window_events_sd1; + + break; + } + + pdata++; + } + + /* Update Global Device Status for results + * - Default to no update + */ + + presults->device_status = VL53L1_DEVICEERROR_NOUPDATE; + + /* Check range status + * - If device error condition, update device status + * - Remove device status from range status output this should + * only contain information relating to range data + */ + + switch (psys->result__range_status & + VL53L1_RANGE_STATUS__RANGE_STATUS_MASK) { + + case VL53L1_DEVICEERROR_VCSELCONTINUITYTESTFAILURE: + case VL53L1_DEVICEERROR_VCSELWATCHDOGTESTFAILURE: + case VL53L1_DEVICEERROR_NOVHVVALUEFOUND: + case VL53L1_DEVICEERROR_USERROICLIP: + case VL53L1_DEVICEERROR_MULTCLIPFAIL: + + presults->device_status = (psys->result__range_status & + VL53L1_RANGE_STATUS__RANGE_STATUS_MASK); + + presults->data[0].range_status = VL53L1_DEVICEERROR_NOUPDATE; + break; + + } + + LOG_FUNCTION_END(0); +} + +/* + * Configure the GPIO interrupt config, from the given input + */ + +VL53L1_Error VL53L1_set_GPIO_interrupt_config( + VL53L1_DEV Dev, + VL53L1_GPIO_Interrupt_Mode intr_mode_distance, + VL53L1_GPIO_Interrupt_Mode intr_mode_rate, + uint8_t intr_new_measure_ready, + uint8_t intr_no_target, + uint8_t intr_combined_mode, + uint16_t thresh_distance_high, + uint16_t thresh_distance_low, + uint16_t thresh_rate_high, + uint16_t thresh_rate_low + ) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + VL53L1_GPIO_interrupt_config_t *pintconf = &(pdev->gpio_interrupt_config); + + LOG_FUNCTION_START(""); + + /* update local data structure */ + pintconf->intr_mode_distance = intr_mode_distance; + pintconf->intr_mode_rate = intr_mode_rate; + pintconf->intr_new_measure_ready = intr_new_measure_ready; + pintconf->intr_no_target = intr_no_target; + pintconf->intr_combined_mode = intr_combined_mode; + pintconf->threshold_distance_high = thresh_distance_high; + pintconf->threshold_distance_low = thresh_distance_low; + pintconf->threshold_rate_high = thresh_rate_high; + pintconf->threshold_rate_low = thresh_rate_low; + + /* encoded interrupt config */ + pdev->gen_cfg.system__interrupt_config_gpio = + VL53L1_encode_GPIO_interrupt_config(pintconf); + + + /* set thresholds */ + status = VL53L1_set_GPIO_thresholds_from_struct( + Dev, + pintconf); + + LOG_FUNCTION_END(status); + return status; +} + +/* + * Configure the GPIO interrupt config, from the given structure + */ + +VL53L1_Error VL53L1_set_GPIO_interrupt_config_struct( + VL53L1_DEV Dev, + VL53L1_GPIO_interrupt_config_t intconf) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + VL53L1_GPIO_interrupt_config_t *pintconf = &(pdev->gpio_interrupt_config); + + LOG_FUNCTION_START(""); + + /* using memcpy(dst, src, size in bytes) */ + memcpy(pintconf, &(intconf), sizeof(VL53L1_GPIO_interrupt_config_t)); + + /* encoded interrupt config */ + pdev->gen_cfg.system__interrupt_config_gpio = + VL53L1_encode_GPIO_interrupt_config(pintconf); + + /* set thresholds */ + status = VL53L1_set_GPIO_thresholds_from_struct( + Dev, + pintconf); + + LOG_FUNCTION_END(status); + return status; +} + +/* + * Retrieve GPIO interrupt config structure + */ + +VL53L1_Error VL53L1_get_GPIO_interrupt_config( + VL53L1_DEV Dev, + VL53L1_GPIO_interrupt_config_t *pintconf) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + /* + * Decode the system__interrupt_config_gpio register + * This makes sure the structure is in line with the register + */ + pdev->gpio_interrupt_config = VL53L1_decode_GPIO_interrupt_config( + pdev->gen_cfg.system__interrupt_config_gpio); + + /* + * Readout the system thresholds + */ + pdev->gpio_interrupt_config.threshold_distance_high = + pdev->dyn_cfg.system__thresh_high; + pdev->gpio_interrupt_config.threshold_distance_low = + pdev->dyn_cfg.system__thresh_low; + + pdev->gpio_interrupt_config.threshold_rate_high = + pdev->gen_cfg.system__thresh_rate_high; + pdev->gpio_interrupt_config.threshold_rate_low = + pdev->gen_cfg.system__thresh_rate_low; + + if (pintconf == &(pdev->gpio_interrupt_config)) { + /* Cowardly refusing to copy the same memory locations */ + } else { + + /* using memcpy(dst, src, size in bytes) */ + memcpy(pintconf, &(pdev->gpio_interrupt_config), + sizeof(VL53L1_GPIO_interrupt_config_t)); + } + + LOG_FUNCTION_END(status); + return status; +} + +VL53L1_Error VL53L1_set_offset_calibration_mode( + VL53L1_DEV Dev, + VL53L1_OffsetCalibrationMode offset_cal_mode) +{ + + /* + * Sets the offset calibration mode + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->offset_calibration_mode = offset_cal_mode; + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_offset_calibration_mode( + VL53L1_DEV Dev, + VL53L1_OffsetCalibrationMode *poffset_cal_mode) +{ + + /* + * Gets the offset calibration mode + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + *poffset_cal_mode = pdev->offset_calibration_mode; + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_offset_correction_mode( + VL53L1_DEV Dev, + VL53L1_OffsetCorrectionMode offset_cor_mode) +{ + + /* + * Sets the offset correction mode + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->offset_correction_mode = offset_cor_mode; + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_offset_correction_mode( + VL53L1_DEV Dev, + VL53L1_OffsetCorrectionMode *poffset_cor_mode) +{ + + /* + * Gets the offset correction mode + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + *poffset_cor_mode = pdev->offset_correction_mode; + + LOG_FUNCTION_END(status); + + return status; +} + + +/* Start Patch_AddedTuningParms_11761 */ +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_tuning_debug_data( + VL53L1_DEV Dev, + VL53L1_tuning_parameters_t *ptun_data) +{ + /* + * Helper function to extract all tuning parm values + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + ptun_data->vl53l1_tuningparm_version = + pdev->tuning_parms.tp_tuning_parm_version; + + ptun_data->vl53l1_tuningparm_key_table_version = + pdev->tuning_parms.tp_tuning_parm_key_table_version; + + + ptun_data->vl53l1_tuningparm_lld_version = + pdev->tuning_parms.tp_tuning_parm_lld_version; + + ptun_data->vl53l1_tuningparm_lite_min_clip_mm = + pdev->tuning_parms.tp_lite_min_clip; + + ptun_data->vl53l1_tuningparm_lite_long_sigma_thresh_mm = + pdev->tuning_parms.tp_lite_long_sigma_thresh_mm; + + ptun_data->vl53l1_tuningparm_lite_med_sigma_thresh_mm = + pdev->tuning_parms.tp_lite_med_sigma_thresh_mm; + + ptun_data->vl53l1_tuningparm_lite_short_sigma_thresh_mm = + pdev->tuning_parms.tp_lite_short_sigma_thresh_mm; + + ptun_data->vl53l1_tuningparm_lite_long_min_count_rate_rtn_mcps = + pdev->tuning_parms.tp_lite_long_min_count_rate_rtn_mcps; + + ptun_data->vl53l1_tuningparm_lite_med_min_count_rate_rtn_mcps = + pdev->tuning_parms.tp_lite_med_min_count_rate_rtn_mcps; + + ptun_data->vl53l1_tuningparm_lite_short_min_count_rate_rtn_mcps = + pdev->tuning_parms.tp_lite_short_min_count_rate_rtn_mcps; + + ptun_data->vl53l1_tuningparm_lite_sigma_est_pulse_width = + pdev->tuning_parms.tp_lite_sigma_est_pulse_width_ns; + + ptun_data->vl53l1_tuningparm_lite_sigma_est_amb_width_ns = + pdev->tuning_parms.tp_lite_sigma_est_amb_width_ns; + + ptun_data->vl53l1_tuningparm_lite_sigma_ref_mm = + pdev->tuning_parms.tp_lite_sigma_ref_mm; + + ptun_data->vl53l1_tuningparm_lite_rit_mult = + pdev->xtalk_cfg.crosstalk_range_ignore_threshold_mult; + + ptun_data->vl53l1_tuningparm_lite_seed_config = + pdev->tuning_parms.tp_lite_seed_cfg ; + + ptun_data->vl53l1_tuningparm_lite_quantifier = + pdev->tuning_parms.tp_lite_quantifier; + + ptun_data->vl53l1_tuningparm_lite_first_order_select = + pdev->tuning_parms.tp_lite_first_order_select; + + ptun_data->vl53l1_tuningparm_lite_xtalk_margin_kcps = + pdev->xtalk_cfg.lite_mode_crosstalk_margin_kcps; + + ptun_data->vl53l1_tuningparm_initial_phase_rtn_lite_long_range = + pdev->tuning_parms.tp_init_phase_rtn_lite_long; + + ptun_data->vl53l1_tuningparm_initial_phase_rtn_lite_med_range = + pdev->tuning_parms.tp_init_phase_rtn_lite_med; + + ptun_data->vl53l1_tuningparm_initial_phase_rtn_lite_short_range = + pdev->tuning_parms.tp_init_phase_rtn_lite_short; + + ptun_data->vl53l1_tuningparm_initial_phase_ref_lite_long_range = + pdev->tuning_parms.tp_init_phase_ref_lite_long; + + ptun_data->vl53l1_tuningparm_initial_phase_ref_lite_med_range = + pdev->tuning_parms.tp_init_phase_ref_lite_med; + + ptun_data->vl53l1_tuningparm_initial_phase_ref_lite_short_range = + pdev->tuning_parms.tp_init_phase_ref_lite_short; + + ptun_data->vl53l1_tuningparm_timed_seed_config = + pdev->tuning_parms.tp_timed_seed_cfg; + + ptun_data->vl53l1_tuningparm_vhv_loopbound = + pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound; + + ptun_data->vl53l1_tuningparm_refspadchar_device_test_mode = + pdev->refspadchar.device_test_mode; + + ptun_data->vl53l1_tuningparm_refspadchar_vcsel_period = + pdev->refspadchar.vcsel_period; + + ptun_data->vl53l1_tuningparm_refspadchar_phasecal_timeout_us = + pdev->refspadchar.timeout_us; + + ptun_data->vl53l1_tuningparm_refspadchar_target_count_rate_mcps = + pdev->refspadchar.target_count_rate_mcps; + + ptun_data->vl53l1_tuningparm_refspadchar_min_countrate_limit_mcps = + pdev->refspadchar.min_count_rate_limit_mcps; + + ptun_data->vl53l1_tuningparm_refspadchar_max_countrate_limit_mcps = + pdev->refspadchar.max_count_rate_limit_mcps; + + ptun_data->vl53l1_tuningparm_offset_cal_dss_rate_mcps = + pdev->offsetcal_cfg.dss_config__target_total_rate_mcps; + + ptun_data->vl53l1_tuningparm_offset_cal_phasecal_timeout_us = + pdev->offsetcal_cfg.phasecal_config_timeout_us; + + ptun_data->vl53l1_tuningparm_offset_cal_mm_timeout_us = + pdev->offsetcal_cfg.mm_config_timeout_us; + + ptun_data->vl53l1_tuningparm_offset_cal_range_timeout_us = + pdev->offsetcal_cfg.range_config_timeout_us; + + ptun_data->vl53l1_tuningparm_offset_cal_pre_samples = + pdev->offsetcal_cfg.pre_num_of_samples; + + ptun_data->vl53l1_tuningparm_offset_cal_mm1_samples = + pdev->offsetcal_cfg.mm1_num_of_samples; + + ptun_data->vl53l1_tuningparm_offset_cal_mm2_samples = + pdev->offsetcal_cfg.mm2_num_of_samples; + + ptun_data->vl53l1_tuningparm_spadmap_vcsel_period = + pdev->ssc_cfg.vcsel_period; + + ptun_data->vl53l1_tuningparm_spadmap_vcsel_start = + pdev->ssc_cfg.vcsel_start; + + ptun_data->vl53l1_tuningparm_spadmap_rate_limit_mcps = + pdev->ssc_cfg.rate_limit_mcps; + + ptun_data->vl53l1_tuningparm_lite_dss_config_target_total_rate_mcps = + pdev->tuning_parms.tp_dss_target_lite_mcps; + + ptun_data->vl53l1_tuningparm_timed_dss_config_target_total_rate_mcps = + pdev->tuning_parms.tp_dss_target_timed_mcps; + + ptun_data->vl53l1_tuningparm_lite_phasecal_config_timeout_us = + pdev->tuning_parms.tp_phasecal_timeout_lite_us; + + ptun_data->vl53l1_tuningparm_timed_phasecal_config_timeout_us = + pdev->tuning_parms.tp_phasecal_timeout_timed_us; + + ptun_data->vl53l1_tuningparm_lite_mm_config_timeout_us = + pdev->tuning_parms.tp_mm_timeout_lite_us; + + ptun_data->vl53l1_tuningparm_timed_mm_config_timeout_us = + pdev->tuning_parms.tp_mm_timeout_timed_us; + + ptun_data->vl53l1_tuningparm_lite_range_config_timeout_us = + pdev->tuning_parms.tp_range_timeout_lite_us; + + ptun_data->vl53l1_tuningparm_timed_range_config_timeout_us = + pdev->tuning_parms.tp_range_timeout_timed_us; + + ptun_data->vl53l1_tuningparm_lowpowerauto_vhv_loop_bound = + pdev->low_power_auto_data.vhv_loop_bound; + + ptun_data->vl53l1_tuningparm_lowpowerauto_mm_config_timeout_us = + pdev->tuning_parms.tp_mm_timeout_lpa_us; + + ptun_data->vl53l1_tuningparm_lowpowerauto_range_config_timeout_us = + pdev->tuning_parms.tp_range_timeout_lpa_us; + + LOG_FUNCTION_END(status); + + return status; +} +#endif + +VL53L1_Error VL53L1_get_tuning_parm( + VL53L1_DEV Dev, + VL53L1_TuningParms tuning_parm_key, + int32_t *ptuning_parm_value) +{ + + /* + * Gets the requested tuning parm value + * - Large case statement for returns + * - if key does not match, INVALID parm error returned + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + switch (tuning_parm_key) { + + case VL53L1_TUNINGPARM_VERSION: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_tuning_parm_version; + break; + case VL53L1_TUNINGPARM_KEY_TABLE_VERSION: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_tuning_parm_key_table_version; + break; + case VL53L1_TUNINGPARM_LLD_VERSION: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_tuning_parm_lld_version; + break; + case VL53L1_TUNINGPARM_CONSISTENCY_LITE_PHASE_TOLERANCE: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_consistency_lite_phase_tolerance; + break; + case VL53L1_TUNINGPARM_PHASECAL_TARGET: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_phasecal_target; + break; + case VL53L1_TUNINGPARM_LITE_CAL_REPEAT_RATE: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_cal_repeat_rate; + break; + case VL53L1_TUNINGPARM_LITE_RANGING_GAIN_FACTOR: + *ptuning_parm_value = + (int32_t)pdev->gain_cal.standard_ranging_gain_factor; + break; + case VL53L1_TUNINGPARM_LITE_MIN_CLIP_MM: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_min_clip; + break; + case VL53L1_TUNINGPARM_LITE_LONG_SIGMA_THRESH_MM: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_long_sigma_thresh_mm; + break; + case VL53L1_TUNINGPARM_LITE_MED_SIGMA_THRESH_MM: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_med_sigma_thresh_mm; + break; + case VL53L1_TUNINGPARM_LITE_SHORT_SIGMA_THRESH_MM: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_short_sigma_thresh_mm; + break; + case VL53L1_TUNINGPARM_LITE_LONG_MIN_COUNT_RATE_RTN_MCPS: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_long_min_count_rate_rtn_mcps; + break; + case VL53L1_TUNINGPARM_LITE_MED_MIN_COUNT_RATE_RTN_MCPS: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_med_min_count_rate_rtn_mcps; + break; + case VL53L1_TUNINGPARM_LITE_SHORT_MIN_COUNT_RATE_RTN_MCPS: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_short_min_count_rate_rtn_mcps; + break; + case VL53L1_TUNINGPARM_LITE_SIGMA_EST_PULSE_WIDTH: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_sigma_est_pulse_width_ns; + break; + case VL53L1_TUNINGPARM_LITE_SIGMA_EST_AMB_WIDTH_NS: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_sigma_est_amb_width_ns; + break; + case VL53L1_TUNINGPARM_LITE_SIGMA_REF_MM: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_sigma_ref_mm; + break; + case VL53L1_TUNINGPARM_LITE_RIT_MULT: + *ptuning_parm_value = + (int32_t)pdev->xtalk_cfg.crosstalk_range_ignore_threshold_mult; + break; + case VL53L1_TUNINGPARM_LITE_SEED_CONFIG: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_seed_cfg ; + break; + case VL53L1_TUNINGPARM_LITE_QUANTIFIER: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_quantifier; + break; + case VL53L1_TUNINGPARM_LITE_FIRST_ORDER_SELECT: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_lite_first_order_select; + break; + case VL53L1_TUNINGPARM_LITE_XTALK_MARGIN_KCPS: + *ptuning_parm_value = + (int32_t)pdev->xtalk_cfg.lite_mode_crosstalk_margin_kcps; + break; + case VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_LONG_RANGE: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_init_phase_rtn_lite_long; + break; + case VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_MED_RANGE: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_init_phase_rtn_lite_med; + break; + case VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_SHORT_RANGE: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_init_phase_rtn_lite_short; + break; + case VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_LONG_RANGE: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_init_phase_ref_lite_long; + break; + case VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_MED_RANGE: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_init_phase_ref_lite_med; + break; + case VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_SHORT_RANGE: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_init_phase_ref_lite_short; + break; + case VL53L1_TUNINGPARM_TIMED_SEED_CONFIG: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_timed_seed_cfg; + break; + case VL53L1_TUNINGPARM_VHV_LOOPBOUND: + *ptuning_parm_value = + (int32_t)pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound; + break; + case VL53L1_TUNINGPARM_REFSPADCHAR_DEVICE_TEST_MODE: + *ptuning_parm_value = + (int32_t)pdev->refspadchar.device_test_mode; + break; + case VL53L1_TUNINGPARM_REFSPADCHAR_VCSEL_PERIOD: + *ptuning_parm_value = + (int32_t)pdev->refspadchar.vcsel_period; + break; + case VL53L1_TUNINGPARM_REFSPADCHAR_PHASECAL_TIMEOUT_US: + *ptuning_parm_value = + (int32_t)pdev->refspadchar.timeout_us; + break; + case VL53L1_TUNINGPARM_REFSPADCHAR_TARGET_COUNT_RATE_MCPS: + *ptuning_parm_value = + (int32_t)pdev->refspadchar.target_count_rate_mcps; + break; + case VL53L1_TUNINGPARM_REFSPADCHAR_MIN_COUNTRATE_LIMIT_MCPS: + *ptuning_parm_value = + (int32_t)pdev->refspadchar.min_count_rate_limit_mcps; + break; + case VL53L1_TUNINGPARM_REFSPADCHAR_MAX_COUNTRATE_LIMIT_MCPS: + *ptuning_parm_value = + (int32_t)pdev->refspadchar.max_count_rate_limit_mcps; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_DSS_RATE_MCPS: + *ptuning_parm_value = + (int32_t)pdev->offsetcal_cfg.dss_config__target_total_rate_mcps;; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_PHASECAL_TIMEOUT_US: + *ptuning_parm_value = + (int32_t)pdev->offsetcal_cfg.phasecal_config_timeout_us; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_MM_TIMEOUT_US: + *ptuning_parm_value = + (int32_t)pdev->offsetcal_cfg.mm_config_timeout_us; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_RANGE_TIMEOUT_US: + *ptuning_parm_value = + (int32_t)pdev->offsetcal_cfg.range_config_timeout_us; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_PRE_SAMPLES: + *ptuning_parm_value = + (int32_t)pdev->offsetcal_cfg.pre_num_of_samples; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_MM1_SAMPLES: + *ptuning_parm_value = + (int32_t)pdev->offsetcal_cfg.mm1_num_of_samples; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_MM2_SAMPLES: + *ptuning_parm_value = + (int32_t)pdev->offsetcal_cfg.mm2_num_of_samples; + break; + case VL53L1_TUNINGPARM_SPADMAP_VCSEL_PERIOD: + *ptuning_parm_value = + (int32_t)pdev->ssc_cfg.vcsel_period; + break; + case VL53L1_TUNINGPARM_SPADMAP_VCSEL_START: + *ptuning_parm_value = + (int32_t)pdev->ssc_cfg.vcsel_start; + break; + case VL53L1_TUNINGPARM_SPADMAP_RATE_LIMIT_MCPS: + *ptuning_parm_value = + (int32_t)pdev->ssc_cfg.rate_limit_mcps; + break; + case VL53L1_TUNINGPARM_LITE_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_dss_target_lite_mcps; + break; + case VL53L1_TUNINGPARM_TIMED_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_dss_target_timed_mcps; + break; + case VL53L1_TUNINGPARM_LITE_PHASECAL_CONFIG_TIMEOUT_US: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_phasecal_timeout_lite_us; + break; + case VL53L1_TUNINGPARM_TIMED_PHASECAL_CONFIG_TIMEOUT_US: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_phasecal_timeout_timed_us; + break; + case VL53L1_TUNINGPARM_LITE_MM_CONFIG_TIMEOUT_US: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_mm_timeout_lite_us; + break; + case VL53L1_TUNINGPARM_TIMED_MM_CONFIG_TIMEOUT_US: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_mm_timeout_timed_us; + break; + case VL53L1_TUNINGPARM_LITE_RANGE_CONFIG_TIMEOUT_US: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_range_timeout_lite_us; + break; + case VL53L1_TUNINGPARM_TIMED_RANGE_CONFIG_TIMEOUT_US: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_range_timeout_timed_us; + break; + case VL53L1_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND: + *ptuning_parm_value = + (int32_t)pdev->low_power_auto_data.vhv_loop_bound; + break; + case VL53L1_TUNINGPARM_LOWPOWERAUTO_MM_CONFIG_TIMEOUT_US: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_mm_timeout_lpa_us; + break; + case VL53L1_TUNINGPARM_LOWPOWERAUTO_RANGE_CONFIG_TIMEOUT_US: + *ptuning_parm_value = + (int32_t)pdev->tuning_parms.tp_range_timeout_lpa_us; + break; + + + default: + *ptuning_parm_value = 0x7FFFFFFF; + status = VL53L1_ERROR_INVALID_PARAMS; + break; + + } + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_set_tuning_parm( + VL53L1_DEV Dev, + VL53L1_TuningParms tuning_parm_key, + int32_t tuning_parm_value) +{ + + /* + * Sets the requested tuning parm value + * - Large case statement for set value + * - if key does not match, INVALID parm error returned + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + switch (tuning_parm_key) { + + case VL53L1_TUNINGPARM_VERSION: + pdev->tuning_parms.tp_tuning_parm_version = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_KEY_TABLE_VERSION: + pdev->tuning_parms.tp_tuning_parm_key_table_version = + (uint16_t)tuning_parm_value; + + /* Perform Key Table Check + * + * - If does not match default, key table + * format does not match tuning file, + * error should be thrown + * + */ + + if ((uint16_t)tuning_parm_value + != VL53L1_TUNINGPARM_KEY_TABLE_VERSION_DEFAULT) { + status = VL53L1_ERROR_TUNING_PARM_KEY_MISMATCH; + } + break; + case VL53L1_TUNINGPARM_LLD_VERSION: + pdev->tuning_parms.tp_tuning_parm_lld_version = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_CONSISTENCY_LITE_PHASE_TOLERANCE: + pdev->tuning_parms.tp_consistency_lite_phase_tolerance = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_PHASECAL_TARGET: + pdev->tuning_parms.tp_phasecal_target = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_CAL_REPEAT_RATE: + pdev->tuning_parms.tp_cal_repeat_rate = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_RANGING_GAIN_FACTOR: + pdev->gain_cal.standard_ranging_gain_factor = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_MIN_CLIP_MM: + pdev->tuning_parms.tp_lite_min_clip = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_LONG_SIGMA_THRESH_MM: + pdev->tuning_parms.tp_lite_long_sigma_thresh_mm = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_MED_SIGMA_THRESH_MM: + pdev->tuning_parms.tp_lite_med_sigma_thresh_mm = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_SHORT_SIGMA_THRESH_MM: + pdev->tuning_parms.tp_lite_short_sigma_thresh_mm = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_LONG_MIN_COUNT_RATE_RTN_MCPS: + pdev->tuning_parms.tp_lite_long_min_count_rate_rtn_mcps = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_MED_MIN_COUNT_RATE_RTN_MCPS: + pdev->tuning_parms.tp_lite_med_min_count_rate_rtn_mcps = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_SHORT_MIN_COUNT_RATE_RTN_MCPS: + pdev->tuning_parms.tp_lite_short_min_count_rate_rtn_mcps = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_SIGMA_EST_PULSE_WIDTH: + pdev->tuning_parms.tp_lite_sigma_est_pulse_width_ns = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_SIGMA_EST_AMB_WIDTH_NS: + pdev->tuning_parms.tp_lite_sigma_est_amb_width_ns = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_SIGMA_REF_MM: + pdev->tuning_parms.tp_lite_sigma_ref_mm = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_RIT_MULT: + pdev->xtalk_cfg.crosstalk_range_ignore_threshold_mult = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_SEED_CONFIG: + pdev->tuning_parms.tp_lite_seed_cfg = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_QUANTIFIER: + pdev->tuning_parms.tp_lite_quantifier = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_FIRST_ORDER_SELECT: + pdev->tuning_parms.tp_lite_first_order_select = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_XTALK_MARGIN_KCPS: + pdev->xtalk_cfg.lite_mode_crosstalk_margin_kcps = + (int16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_LONG_RANGE: + pdev->tuning_parms.tp_init_phase_rtn_lite_long = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_MED_RANGE: + pdev->tuning_parms.tp_init_phase_rtn_lite_med = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_SHORT_RANGE: + pdev->tuning_parms.tp_init_phase_rtn_lite_short = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_LONG_RANGE: + pdev->tuning_parms.tp_init_phase_ref_lite_long = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_MED_RANGE: + pdev->tuning_parms.tp_init_phase_ref_lite_med = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_SHORT_RANGE: + pdev->tuning_parms.tp_init_phase_ref_lite_short = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_TIMED_SEED_CONFIG: + pdev->tuning_parms.tp_timed_seed_cfg = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_VHV_LOOPBOUND: + pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_REFSPADCHAR_DEVICE_TEST_MODE: + pdev->refspadchar.device_test_mode = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_REFSPADCHAR_VCSEL_PERIOD: + pdev->refspadchar.vcsel_period = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_REFSPADCHAR_PHASECAL_TIMEOUT_US: + pdev->refspadchar.timeout_us = + (uint32_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_REFSPADCHAR_TARGET_COUNT_RATE_MCPS: + pdev->refspadchar.target_count_rate_mcps = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_REFSPADCHAR_MIN_COUNTRATE_LIMIT_MCPS: + pdev->refspadchar.min_count_rate_limit_mcps = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_REFSPADCHAR_MAX_COUNTRATE_LIMIT_MCPS: + pdev->refspadchar.max_count_rate_limit_mcps = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_DSS_RATE_MCPS: + pdev->offsetcal_cfg.dss_config__target_total_rate_mcps = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_PHASECAL_TIMEOUT_US: + pdev->offsetcal_cfg.phasecal_config_timeout_us = + (uint32_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_MM_TIMEOUT_US: + pdev->offsetcal_cfg.mm_config_timeout_us = + (uint32_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_RANGE_TIMEOUT_US: + pdev->offsetcal_cfg.range_config_timeout_us = + (uint32_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_PRE_SAMPLES: + pdev->offsetcal_cfg.pre_num_of_samples = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_MM1_SAMPLES: + pdev->offsetcal_cfg.mm1_num_of_samples = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_OFFSET_CAL_MM2_SAMPLES: + pdev->offsetcal_cfg.mm2_num_of_samples = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_SPADMAP_VCSEL_PERIOD: + pdev->ssc_cfg.vcsel_period = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_SPADMAP_VCSEL_START: + pdev->ssc_cfg.vcsel_start = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_SPADMAP_RATE_LIMIT_MCPS: + pdev->ssc_cfg.rate_limit_mcps = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS: + pdev->tuning_parms.tp_dss_target_lite_mcps = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_TIMED_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS: + pdev->tuning_parms.tp_dss_target_timed_mcps = + (uint16_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_PHASECAL_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_phasecal_timeout_lite_us = + (uint32_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_TIMED_PHASECAL_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_phasecal_timeout_timed_us = + (uint32_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_MM_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_mm_timeout_lite_us = + (uint32_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_TIMED_MM_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_mm_timeout_timed_us = + (uint32_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LITE_RANGE_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_range_timeout_lite_us = + (uint32_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_TIMED_RANGE_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_range_timeout_timed_us = + (uint32_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND: + pdev->low_power_auto_data.vhv_loop_bound = + (uint8_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LOWPOWERAUTO_MM_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_mm_timeout_lpa_us = + (uint32_t)tuning_parm_value; + break; + case VL53L1_TUNINGPARM_LOWPOWERAUTO_RANGE_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_range_timeout_lpa_us = + (uint32_t)tuning_parm_value; + break; + + + default: + status = VL53L1_ERROR_INVALID_PARAMS; + break; + + } + + LOG_FUNCTION_END(status); + + return status; +} + +/* End Patch_AddedTuningParms_11761 */ diff --git a/App/VL53L1X_API/core/src/vl53l1_api_debug.c b/App/VL53L1X_API/core/src/vl53l1_api_debug.c new file mode 100644 index 0000000..93f61f5 --- /dev/null +++ b/App/VL53L1X_API/core/src/vl53l1_api_debug.c @@ -0,0 +1,1741 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_api_debug.c + * @brief EwokPlus25 low level Driver debug function definition + */ + +#include "vl53l1_ll_def.h" +#include "vl53l1_ll_device.h" +#include "vl53l1_register_structs.h" +#include "vl53l1_core.h" +#include "vl53l1_api_debug.h" + +#define LOG_FUNCTION_START(fmt, ...) \ + _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__) +#define LOG_FUNCTION_END(status, ...) \ + _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_CORE, status, ##__VA_ARGS__) +#define LOG_FUNCTION_END_FMT(status, fmt, ...) \ + _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_CORE, status, \ + fmt, ##__VA_ARGS__) + +#define trace_print(level, ...) \ + _LOG_TRACE_PRINT(trace_flags, \ + level, VL53L1_TRACE_FUNCTION_NONE, ##__VA_ARGS__) + + +/* Start Patch_AdditionalDebugData_11823 */ + +VL53L1_Error VL53L1_get_additional_data( + VL53L1_DEV Dev, + VL53L1_additional_data_t *pdata) +{ + /* + * Gets the addition debug data + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + /* get LL Driver configuration parameters */ + + pdata->preset_mode = pdev->preset_mode; + pdata->measurement_mode = pdev->measurement_mode; + + pdata->phasecal_config_timeout_us = pdev->phasecal_config_timeout_us; + pdata->mm_config_timeout_us = pdev->mm_config_timeout_us; + pdata->range_config_timeout_us = pdev->range_config_timeout_us; + pdata->inter_measurement_period_ms = pdev->inter_measurement_period_ms; + pdata->dss_config__target_total_rate_mcps = + pdev->dss_config__target_total_rate_mcps; + + LOG_FUNCTION_END(status); + + return status; +} + +/* End Patch_AdditionalDebugData_11823 */ + +#ifdef VL53L1_LOG_ENABLE + +void VL53L1_signed_fixed_point_sprintf( + int32_t signed_fp_value, + uint8_t frac_bits, + uint16_t buf_size, + char *pbuffer) +{ + /* + * Converts input signed fixed point number into a string + */ + + uint32_t fp_value = 0; + uint32_t unity_fp_value = 0; + uint32_t sign_bit = 0; + uint32_t int_part = 0; + uint32_t frac_part = 0; + uint32_t dec_points = 0; + uint32_t dec_scaler = 0; + uint32_t dec_part = 0; + + uint64_t tmp_long_int = 0; + + char fmt[VL53L1_MAX_STRING_LENGTH]; + + SUPPRESS_UNUSED_WARNING(buf_size); + + /* split into integer and fractional values */ + + sign_bit = signed_fp_value >> 31; + + if (sign_bit > 0) { + fp_value = 0x80000000 - + (0x7FFFFFFF & (uint32_t)signed_fp_value); + } else + fp_value = (uint32_t)signed_fp_value; + + int_part = fp_value >> frac_bits; + unity_fp_value = 0x01 << frac_bits; + frac_part = fp_value & (unity_fp_value-1); + + /* Calculate decimal scale factor and required decimal points + * min number of displayed places is 2 + */ + dec_points = 2; + dec_scaler = 100; + + while (dec_scaler < unity_fp_value) { + dec_points++; + dec_scaler *= 10; + } + + /* Build format string */ + if (sign_bit > 0) + sprintf(fmt, "-%%u.%%0%uu", dec_points); + else + sprintf(fmt, "%%u.%%0%uu", dec_points); + + /* Convert fractional part into a decimal + * need 64-bit head room at this point + */ + tmp_long_int = (uint64_t)frac_part * (uint64_t)dec_scaler; + tmp_long_int += (uint64_t)unity_fp_value/2; + + tmp_long_int = do_division_u(tmp_long_int, (uint64_t)unity_fp_value); + + dec_part = (uint32_t)tmp_long_int; + + /* Generate string for fixed point number */ + sprintf( + pbuffer, + fmt, + int_part, + dec_part); +} + + +void VL53L1_print_static_nvm_managed( + VL53L1_static_nvm_managed_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + /** + * Prints out VL53L1_static_nvm_managed_t for debug + */ + + char fp_text[VL53L1_MAX_STRING_LENGTH]; + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = 0x%02X\n", + pprefix, + "i2c_slave__device_address", + pdata->i2c_slave__device_address); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "ana_config__vhv_ref_sel_vddpix", + pdata->ana_config__vhv_ref_sel_vddpix); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "ana_config__vhv_ref_sel_vquench", + pdata->ana_config__vhv_ref_sel_vquench); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "ana_config__reg_avdd1v2_sel", + pdata->ana_config__reg_avdd1v2_sel); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "ana_config__fast_osc__trim", + pdata->ana_config__fast_osc__trim); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->osc_measured__fast_osc__frequency, + 12, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "osc_measured__fast_osc__frequency", + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "vhv_config__timeout_macrop_loop_bound", + pdata->vhv_config__timeout_macrop_loop_bound); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "vhv_config__count_thresh", + pdata->vhv_config__count_thresh); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "vhv_config__offset", + pdata->vhv_config__offset); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "vhv_config__init", + pdata->vhv_config__init); +} + + +void VL53L1_print_customer_nvm_managed( + VL53L1_customer_nvm_managed_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + /* + * Prints out VL53L1_customer_nvm_managed_t for debug + */ + + char fp_text[VL53L1_MAX_STRING_LENGTH]; + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_ref_0", + pdata->global_config__spad_enables_ref_0); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_ref_1", + pdata->global_config__spad_enables_ref_1); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_ref_2", + pdata->global_config__spad_enables_ref_2); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_ref_3", + pdata->global_config__spad_enables_ref_3); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_ref_4", + pdata->global_config__spad_enables_ref_4); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_ref_5", + pdata->global_config__spad_enables_ref_5); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__ref_en_start_select", + pdata->global_config__ref_en_start_select); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "ref_spad_man__num_requested_ref_spads", + pdata->ref_spad_man__num_requested_ref_spads); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "ref_spad_man__ref_location", + pdata->ref_spad_man__ref_location); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->algo__crosstalk_compensation_plane_offset_kcps, + 9, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "algo__crosstalk_compensation_plane_offset_kcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->algo__crosstalk_compensation_x_plane_gradient_kcps, + 11, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "algo__crosstalk_compensation_x_plane_gradient_kcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->algo__crosstalk_compensation_y_plane_gradient_kcps, + 11, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "algo__crosstalk_compensation_y_plane_gradient_kcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->ref_spad_char__total_rate_target_mcps, + 7, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "ref_spad_char__total_rate_target_mcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->algo__part_to_part_range_offset_mm, + 2, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "algo__part_to_part_range_offset_mm", + fp_text); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %d\n", + pprefix, + "mm_config__inner_offset_mm", + pdata->mm_config__inner_offset_mm); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %d\n", + pprefix, + "mm_config__outer_offset_mm", + pdata->mm_config__outer_offset_mm); +} + + +void VL53L1_print_nvm_copy_data( + VL53L1_nvm_copy_data_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + /** + * Prints out VL53L1_nvm_copy_data_t for debug + */ + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "identification__model_id", + pdata->identification__model_id); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "identification__module_type", + pdata->identification__module_type); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "identification__revision_id", + pdata->identification__revision_id); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "identification__module_id", + pdata->identification__module_id); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "ana_config__fast_osc__trim_max", + pdata->ana_config__fast_osc__trim_max); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "ana_config__fast_osc__freq_set", + pdata->ana_config__fast_osc__freq_set); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "ana_config__vcsel_trim", + pdata->ana_config__vcsel_trim); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "ana_config__vcsel_selion", + pdata->ana_config__vcsel_selion); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "ana_config__vcsel_selion_max", + pdata->ana_config__vcsel_selion_max); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "protected_laser_safety__lock_bit", + pdata->protected_laser_safety__lock_bit); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "laser_safety__key", + pdata->laser_safety__key); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "laser_safety__key_ro", + pdata->laser_safety__key_ro); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "laser_safety__clip", + pdata->laser_safety__clip); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "laser_safety__mult", + pdata->laser_safety__mult); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_0", + pdata->global_config__spad_enables_rtn_0); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_1", + pdata->global_config__spad_enables_rtn_1); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_2", + pdata->global_config__spad_enables_rtn_2); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_3", + pdata->global_config__spad_enables_rtn_3); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_4", + pdata->global_config__spad_enables_rtn_4); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_5", + pdata->global_config__spad_enables_rtn_5); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_6", + pdata->global_config__spad_enables_rtn_6); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_7", + pdata->global_config__spad_enables_rtn_7); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_8", + pdata->global_config__spad_enables_rtn_8); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_9", + pdata->global_config__spad_enables_rtn_9); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_10", + pdata->global_config__spad_enables_rtn_10); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_11", + pdata->global_config__spad_enables_rtn_11); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_12", + pdata->global_config__spad_enables_rtn_12); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_13", + pdata->global_config__spad_enables_rtn_13); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_14", + pdata->global_config__spad_enables_rtn_14); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_15", + pdata->global_config__spad_enables_rtn_15); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_16", + pdata->global_config__spad_enables_rtn_16); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_17", + pdata->global_config__spad_enables_rtn_17); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_18", + pdata->global_config__spad_enables_rtn_18); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_19", + pdata->global_config__spad_enables_rtn_19); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_20", + pdata->global_config__spad_enables_rtn_20); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_21", + pdata->global_config__spad_enables_rtn_21); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_22", + pdata->global_config__spad_enables_rtn_22); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_23", + pdata->global_config__spad_enables_rtn_23); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_24", + pdata->global_config__spad_enables_rtn_24); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_25", + pdata->global_config__spad_enables_rtn_25); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_26", + pdata->global_config__spad_enables_rtn_26); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_27", + pdata->global_config__spad_enables_rtn_27); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_28", + pdata->global_config__spad_enables_rtn_28); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_29", + pdata->global_config__spad_enables_rtn_29); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_30", + pdata->global_config__spad_enables_rtn_30); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_config__spad_enables_rtn_31", + pdata->global_config__spad_enables_rtn_31); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "roi_config__mode_roi_centre_spad", + pdata->roi_config__mode_roi_centre_spad); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = 0x%02X\n", + pprefix, + "roi_config__mode_roi_xy_size", + pdata->roi_config__mode_roi_xy_size); +} + + +void VL53L1_print_range_data( + VL53L1_range_data_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + /* + * Prints out the range data structure for debug + */ + + char fp_text[VL53L1_MAX_STRING_LENGTH]; + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "range_id", + pdata->range_id); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "time_stamp", + pdata->time_stamp); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->width, + 4, VL53L1_MAX_STRING_LENGTH, fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "width", + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "woi", + pdata->woi); + + /* Fast Oscillator Frequency */ + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->fast_osc_frequency, + 12, VL53L1_MAX_STRING_LENGTH, fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "fast_osc_frequency", + fp_text); + + /* Zero Distance Phase */ + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->zero_distance_phase, + 11, VL53L1_MAX_STRING_LENGTH, fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "zero_distance_phase", + fp_text); + + /* Actual effective SPAD count */ + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->actual_effective_spads, + 8, VL53L1_MAX_STRING_LENGTH, fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "actual_effective_spad", + fp_text); + + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "total_periods_elapsed", + pdata->total_periods_elapsed); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "peak_duration_us", + pdata->peak_duration_us); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "woi_duration_us", + pdata->woi_duration_us); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %d\n", + pprefix, + "ambient_window_events", + pdata->ambient_window_events); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %d\n", + pprefix, + "ranging_total_events", + pdata->ranging_total_events); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %d\n", + pprefix, + "signal_total_events", + pdata->signal_total_events); + + /* Rates */ + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->peak_signal_count_rate_mcps, + 7, VL53L1_MAX_STRING_LENGTH, fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "peak_signal_count_rate_mcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->avg_signal_count_rate_mcps, + 7, VL53L1_MAX_STRING_LENGTH, fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "avg_signal_count_rate_mcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->ambient_count_rate_mcps, + 7, VL53L1_MAX_STRING_LENGTH, fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "ambient_count_rate_mcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->total_rate_per_spad_mcps, + 13, VL53L1_MAX_STRING_LENGTH, fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "total_rate_per_spad_mcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->peak_rate_per_spad_kcps, + 11, VL53L1_MAX_STRING_LENGTH, fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "peak_rate_per_spad_kcps", + fp_text); + + /* Sigma */ + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->sigma_mm, + 2, VL53L1_MAX_STRING_LENGTH, fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "sigma_mm", + fp_text); + + /* Phase */ + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->median_phase, + 11, VL53L1_MAX_STRING_LENGTH, fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "median_phase", + fp_text); + + /* Offset Corrected Range */ + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %d\n", + pprefix, + "median_range_mm", + pdata->median_range_mm); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "range_status", + pdata->range_status); +} + + +void VL53L1_print_range_results( + VL53L1_range_results_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + /* + * Prints out the range results data structure for debug + */ + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "cfg_device_state", + pdata->cfg_device_state); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "rd_device_state", + pdata->rd_device_state); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "stream_count", + pdata->stream_count); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "device_status", + pdata->device_status); + +} + +void VL53L1_print_offset_range_results( + VL53L1_offset_range_results_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + /* + * Prints out the offset range results data structure for debug + */ + + char pre_text[VL53L1_MAX_STRING_LENGTH]; + char *ppre_text = &(pre_text[0]); + + uint8_t i = 0; + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "cal_distance_mm", + pdata->cal_distance_mm); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "cal_status", + pdata->cal_status); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "cal_report", + pdata->cal_report); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "max_results", + pdata->max_results); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "active_results", + pdata->active_results); + + for (i = 0 ; i < pdata->active_results ; i++) { + sprintf(ppre_text, "%sdata[%u].", pprefix, i); + VL53L1_print_offset_range_data( + &(pdata->data[i]), + ppre_text, trace_flags); + } +} + +void VL53L1_print_offset_range_data( + VL53L1_offset_range_data_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + /* + * Prints out the xtalk range (ROI) data structure for debug + */ + + char fp_text[VL53L1_MAX_STRING_LENGTH]; + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "preset_mode", + pdata->preset_mode); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "dss_config__roi_mode_control", + pdata->dss_config__roi_mode_control); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->dss_config__manual_effective_spads_select, + 8, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "dss_config__manual_effective_spads_select", + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "no_of_samples", + pdata->no_of_samples); + + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->effective_spads, + 8, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "effective_spads", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->peak_rate_mcps, + 7, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "peak_rate_mcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->sigma_mm, + 2, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "sigma_mm", + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %d\n", + pprefix, + "median_range_mm", + pdata->median_range_mm); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %d\n", + pprefix, + "range_mm_offset", + pdata->range_mm_offset); +} + +void VL53L1_print_additional_offset_cal_data( + VL53L1_additional_offset_cal_data_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + /* + * Prints out the xtalk range (ROI) data structure for debug + */ + + char fp_text[VL53L1_MAX_STRING_LENGTH]; + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->result__mm_inner_actual_effective_spads, + 8, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "result__mm_inner_actual_effective_spads", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->result__mm_outer_actual_effective_spads, + 8, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "result__mm_outer_actual_effective_spads", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->result__mm_inner_peak_signal_count_rtn_mcps, + 7, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "result__mm_inner_peak_signal_count_rtn_mcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->result__mm_outer_peak_signal_count_rtn_mcps, + 7, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "result__mm_outer_peak_signal_count_rtn_mcps", + fp_text); +} + + +void VL53L1_print_cal_peak_rate_map( + VL53L1_cal_peak_rate_map_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + /* + * Prints out peak rate map structure for debug + */ + + char fp_text[VL53L1_MAX_STRING_LENGTH]; + char pre_text[VL53L1_MAX_STRING_LENGTH]; + char *ppre_text = &(pre_text[0]); + + uint8_t i = 0; + uint8_t x = 0; + uint8_t y = 0; + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->cal_distance_mm, + 2, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "cal_distance_mm", + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "max_samples", + pdata->max_samples); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "width", + pdata->width); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "height", + pdata->height); + + i = 0; + for (y = 0 ; y < pdata->height ; y++) { + for (x = 0 ; x < pdata->width ; x++) { + + sprintf(ppre_text, "%speak_rate_mcps[%u]", pprefix, i); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->peak_rate_mcps[i], + 7, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s = %s\n", + ppre_text, + fp_text); + + i++; + } + } +} + +void VL53L1_print_additional_data( + VL53L1_additional_data_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + + /* + * Prints out the Additional data structure for debug + */ + + char fp_text[VL53L1_MAX_STRING_LENGTH]; + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "preset_mode", + pdata->preset_mode); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "measurement_mode", + pdata->measurement_mode); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "phasecal_config_timeout_us", + pdata->phasecal_config_timeout_us); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "mm_config_timeout_us", + pdata->mm_config_timeout_us); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "range_config_timeout_us", + pdata->range_config_timeout_us); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "inter_measurement_period_ms", + pdata->inter_measurement_period_ms); + + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->dss_config__target_total_rate_mcps, + 7, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "dss_config__target_total_rate_mcps", + fp_text); + +} + + +void VL53L1_print_gain_calibration_data( + VL53L1_gain_calibration_data_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + /* + * Prints out the LL Driver state data for debug + */ + + char fp_text[VL53L1_MAX_STRING_LENGTH]; + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->standard_ranging_gain_factor, + 11, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "standard_ranging_gain_factor", + fp_text); + +} + + +void VL53L1_print_xtalk_config( + VL53L1_xtalk_config_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + /* + * Prints out the xtalk config data structure for debug + */ + + char fp_text[VL53L1_MAX_STRING_LENGTH]; + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->algo__crosstalk_compensation_plane_offset_kcps, + 9, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "algo__crosstalk_compensation_plane_offset_kcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->algo__crosstalk_compensation_x_plane_gradient_kcps, + 11, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "algo__crosstalk_compensation_x_plane_gradient_kcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->algo__crosstalk_compensation_y_plane_gradient_kcps, + 11, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "algo__crosstalk_compensation_y_plane_gradient_kcps", + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "global_crosstalk_compensation_enable", + pdata->global_crosstalk_compensation_enable); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->lite_mode_crosstalk_margin_kcps, + 9, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "lite_mode_crosstalk_margin_kcps", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->crosstalk_range_ignore_threshold_mult, + 5, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "crosstalk_range_ignore_threshold_mult", + fp_text); + + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->crosstalk_range_ignore_threshold_rate_mcps, + 13, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "crosstalk_range_ignore_threshold_rate_mcps", + fp_text); + +} + + + +void VL53L1_print_optical_centre( + VL53L1_optical_centre_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + + /* Prints out the optical centre data structure for debug + */ + + char fp_text[VL53L1_MAX_STRING_LENGTH]; + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->x_centre, + 4, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "x_centre", + fp_text); + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pdata->y_centre, + 4, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %s\n", + pprefix, + "y_centre", + fp_text); +} + + +void VL53L1_print_user_zone( + VL53L1_user_zone_t *pdata, + char *pprefix, + uint32_t trace_flags) +{ + + /* Prints out the zone (ROI) data structure for debug + */ + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "x_centre", + pdata->x_centre); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "y_centre", + pdata->y_centre); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "width", + pdata->width); + + trace_print(VL53L1_TRACE_LEVEL_INFO, + "%s%s = %u\n", + pprefix, + "height", + pdata->height); +} + + +void VL53L1_print_spad_rate_data( + VL53L1_spad_rate_data_t *pspad_rates, + char *pprefix, + uint32_t trace_flags) +{ + + /** + * Print per SPAD rates generated by SSC + */ + + uint16_t spad_no = 0; + uint8_t row = 0; + uint8_t col = 0; + + char fp_text[VL53L1_MAX_STRING_LENGTH]; + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%8s,%4s,%4s, %s\n", + pprefix, + "spad_no", + "row", + "col", + "peak_rate_mcps"); + + for (spad_no = 0 ; spad_no < pspad_rates->no_of_values ; spad_no++) { + + /* generate row / col location from SPAD number */ + VL53L1_decode_row_col( + (uint8_t)spad_no, + &row, + &col); + + /* Convert fixed point rate value to string */ + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pspad_rates->rate_data[spad_no], + pspad_rates->fractional_bits, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + /* Print data */ + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%8u,%4u,%4u, %s\n", + pprefix, + spad_no, + row, + col, + fp_text); + } +} + + +void VL53L1_print_spad_rate_map( + VL53L1_spad_rate_data_t *pspad_rates, + char *pprefix, + uint32_t trace_flags) +{ + + /** + * Print per SPAD rates generated by SSC as a map + */ + + uint8_t spad_no = 0; + uint8_t row = 0; + uint8_t col = 0; + + char fp_text[VL53L1_MAX_STRING_LENGTH]; + + /* Print column headers */ + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%4s", + pprefix, + " "); + + for (col = 0 ; col < VL53L1_SPAD_ARRAY_WIDTH ; col++) + trace_print( + VL53L1_TRACE_LEVEL_INFO, + ",%8u", + col); + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "\n"); + + /* Print rate data */ + + for (row = 0 ; row < VL53L1_SPAD_ARRAY_HEIGHT ; row++) { + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "%s%4u", + pprefix, + row); + + for (col = 0 ; col < VL53L1_SPAD_ARRAY_HEIGHT ; col++) { + + /* generate SPAD number from (row, col) location */ + + VL53L1_encode_row_col( + row, + col, + &spad_no); + + /* Convert fixed point rate value to string */ + + VL53L1_signed_fixed_point_sprintf( + (int32_t)pspad_rates->rate_data[spad_no], + pspad_rates->fractional_bits, + VL53L1_MAX_STRING_LENGTH, + fp_text); + + /* Print data */ + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + ",%8s", + fp_text); + } + + trace_print( + VL53L1_TRACE_LEVEL_INFO, + "\n"); + } +} + + +#endif /* VL53L1_LOG_ENABLE */ + diff --git a/App/VL53L1X_API/core/src/vl53l1_api_preset_modes.c b/App/VL53L1X_API/core/src/vl53l1_api_preset_modes.c new file mode 100644 index 0000000..f345c89 --- /dev/null +++ b/App/VL53L1X_API/core/src/vl53l1_api_preset_modes.c @@ -0,0 +1,1407 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_api_preset_modes.c + * + * @brief EwokPlus25 API Preset Modes definitions + */ + +#include "vl53l1_ll_def.h" +#include "vl53l1_platform_log.h" +#include "vl53l1_register_structs.h" +#include "vl53l1_register_settings.h" +#include "vl53l1_core.h" +#include "vl53l1_api_preset_modes.h" +#include "vl53l1_tuning_parm_defaults.h" + + +#define LOG_FUNCTION_START(fmt, ...) \ + _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_API, fmt, ##__VA_ARGS__) +#define LOG_FUNCTION_END(status, ...) \ + _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_API, status, ##__VA_ARGS__) +#define LOG_FUNCTION_END_FMT(status, fmt, ...) \ + _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_API, status, fmt, ##__VA_ARGS__) + + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_init_refspadchar_config_struct( + VL53L1_refspadchar_config_t *pdata) +{ + /* + * Initializes Ref SPAD Char data structures preset mode + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Reference SPAD Char Configuration + * + * vcsel_period = 0x0B - 24 clock VCSEL period + * timeout_us = 1000 - Set 1000us phase cal timeout + * target_count_rate_mcps = 0x0A00 - 9.7 -> 20.0 Mcps + * min_count_rate_limit_mcps = 0x0500 - 9.7 -> 10.0 Mcps + * max_count_rate_limit_mcps = 0x1400 - 9.7 -> 40.0 Mcps + */ + + pdata->device_test_mode = + VL53L1_TUNINGPARM_REFSPADCHAR_DEVICE_TEST_MODE_DEFAULT; + pdata->vcsel_period = + VL53L1_TUNINGPARM_REFSPADCHAR_VCSEL_PERIOD_DEFAULT; + pdata->timeout_us = + VL53L1_TUNINGPARM_REFSPADCHAR_PHASECAL_TIMEOUT_US_DEFAULT; + pdata->target_count_rate_mcps = + VL53L1_TUNINGPARM_REFSPADCHAR_TARGET_COUNT_RATE_MCPS_DEFAULT; + pdata->min_count_rate_limit_mcps = + VL53L1_TUNINGPARM_REFSPADCHAR_MIN_COUNTRATE_LIMIT_MCPS_DEFAULT; + pdata->max_count_rate_limit_mcps = + VL53L1_TUNINGPARM_REFSPADCHAR_MAX_COUNTRATE_LIMIT_MCPS_DEFAULT; + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_init_ssc_config_struct( + VL53L1_ssc_config_t *pdata) +{ + /* + * Initializes SPAD Self Check (SSC) data structure + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* SPAD Select Check Configuration */ + + /* 0 - store RTN count rates + * 1 - store REF count rates + */ + pdata->array_select = VL53L1_DEVICESSCARRAY_RTN; + + /* VCSEL period register value 0x12 (18) -> 38 VCSEL clocks */ + pdata->vcsel_period = + VL53L1_TUNINGPARM_SPADMAP_VCSEL_PERIOD_DEFAULT; + + /* VCSEL pulse start */ + pdata->vcsel_start = + VL53L1_TUNINGPARM_SPADMAP_VCSEL_START_DEFAULT; + + /* VCSEL pulse width */ + pdata->vcsel_width = 0x02; + + /* SSC timeout [us] */ + pdata->timeout_us = 36000; + + /* SSC rate limit [Mcps] + * - 9.7 for VCSEL ON + * - 1.15 for VCSEL OFF + */ + pdata->rate_limit_mcps = + VL53L1_TUNINGPARM_SPADMAP_RATE_LIMIT_MCPS_DEFAULT; + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_init_xtalk_config_struct( + VL53L1_customer_nvm_managed_t *pnvm, + VL53L1_xtalk_config_t *pdata) +{ + /* + * Initializes Xtalk Config structure + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Xtalk default configuration + * + * algo__crosstalk_compensation_plane_offset_kcps + * = pdev->customer.algo__crosstalk_compensation_plane_offset_kcps + * algo__crosstalk_compensation_x_plane_gradient_kcps + * = pdev->customer.algo__crosstalk_compensation_x_plane_gradient_kcps + * algo__crosstalk_compensation_y_plane_gradient_kcps + * = pdev->customer.algo__crosstalk_compensation_y_plane_gradient_kcps + * + */ + + /* Store xtalk data into golden copy */ + + pdata->algo__crosstalk_compensation_plane_offset_kcps = + pnvm->algo__crosstalk_compensation_plane_offset_kcps; + pdata->algo__crosstalk_compensation_x_plane_gradient_kcps = + pnvm->algo__crosstalk_compensation_x_plane_gradient_kcps; + pdata->algo__crosstalk_compensation_y_plane_gradient_kcps = + pnvm->algo__crosstalk_compensation_y_plane_gradient_kcps; + + /* Store NVM defaults for later use */ + + pdata->nvm_default__crosstalk_compensation_plane_offset_kcps = + (uint32_t)pnvm->algo__crosstalk_compensation_plane_offset_kcps; + pdata->nvm_default__crosstalk_compensation_x_plane_gradient_kcps = + pnvm->algo__crosstalk_compensation_x_plane_gradient_kcps; + pdata->nvm_default__crosstalk_compensation_y_plane_gradient_kcps = + pnvm->algo__crosstalk_compensation_y_plane_gradient_kcps; + + pdata->lite_mode_crosstalk_margin_kcps = + VL53L1_TUNINGPARM_LITE_XTALK_MARGIN_KCPS_DEFAULT; + + /* Default for Range Ignore Threshold Mult = 2.0 */ + + pdata->crosstalk_range_ignore_threshold_mult = + VL53L1_TUNINGPARM_LITE_RIT_MULT_DEFAULT; + + if ((pdata->algo__crosstalk_compensation_plane_offset_kcps == 0x00) + && (pdata->algo__crosstalk_compensation_x_plane_gradient_kcps == 0x00) + && (pdata->algo__crosstalk_compensation_y_plane_gradient_kcps == 0x00)) + pdata->global_crosstalk_compensation_enable = 0x00; + else + pdata->global_crosstalk_compensation_enable = 0x01; + + + if ((status == VL53L1_ERROR_NONE) && + (pdata->global_crosstalk_compensation_enable == 0x01)) { + pdata->crosstalk_range_ignore_threshold_rate_mcps = + VL53L1_calc_range_ignore_threshold( + pdata->algo__crosstalk_compensation_plane_offset_kcps, + pdata->algo__crosstalk_compensation_x_plane_gradient_kcps, + pdata->algo__crosstalk_compensation_y_plane_gradient_kcps, + pdata->crosstalk_range_ignore_threshold_mult); + } else { + pdata->crosstalk_range_ignore_threshold_rate_mcps = 0; + } + + LOG_FUNCTION_END(status); + + return status; +} + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_init_offset_cal_config_struct( + VL53L1_offsetcal_config_t *pdata) +{ + /* + * Initializes Offset Calibration Config structure + * - for use with VL53L1_run_offset_calibration() + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Preset Timeout and DSS defaults */ + + pdata->dss_config__target_total_rate_mcps = + VL53L1_TUNINGPARM_OFFSET_CAL_DSS_RATE_MCPS_DEFAULT; + /* 20.0 Mcps */ + pdata->phasecal_config_timeout_us = + VL53L1_TUNINGPARM_OFFSET_CAL_PHASECAL_TIMEOUT_US_DEFAULT; + /* 1000 us */ + pdata->range_config_timeout_us = + VL53L1_TUNINGPARM_OFFSET_CAL_RANGE_TIMEOUT_US_DEFAULT; + /* 13000 us */ + pdata->mm_config_timeout_us = + VL53L1_TUNINGPARM_OFFSET_CAL_MM_TIMEOUT_US_DEFAULT; + /* 13000 us - Added as part of Patch_AddedOffsetCalMMTuningParm_11791 */ + + /* Init number of averaged samples */ + + pdata->pre_num_of_samples = + VL53L1_TUNINGPARM_OFFSET_CAL_PRE_SAMPLES_DEFAULT; + pdata->mm1_num_of_samples = + VL53L1_TUNINGPARM_OFFSET_CAL_MM1_SAMPLES_DEFAULT; + pdata->mm2_num_of_samples = + VL53L1_TUNINGPARM_OFFSET_CAL_MM2_SAMPLES_DEFAULT; + + LOG_FUNCTION_END(status); + + return status; +} +#endif + +VL53L1_Error VL53L1_init_tuning_parm_storage_struct( + VL53L1_tuning_parm_storage_t *pdata) +{ + /* + * Initializes Tuning Param storage structure + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Default configuration + * + * - Custom overwrite possible from vl53l1_set_tuning_parms() + * - via tuning file input + */ + + pdata->tp_tuning_parm_version = + VL53L1_TUNINGPARM_VERSION_DEFAULT; + pdata->tp_tuning_parm_key_table_version = + VL53L1_TUNINGPARM_KEY_TABLE_VERSION_DEFAULT; + pdata->tp_tuning_parm_lld_version = + VL53L1_TUNINGPARM_LLD_VERSION_DEFAULT; + pdata->tp_init_phase_rtn_lite_long = + VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_LONG_RANGE_DEFAULT; + pdata->tp_init_phase_rtn_lite_med = + VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_MED_RANGE_DEFAULT; + pdata->tp_init_phase_rtn_lite_short = + VL53L1_TUNINGPARM_INITIAL_PHASE_RTN_LITE_SHORT_RANGE_DEFAULT; + pdata->tp_init_phase_ref_lite_long = + VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_LONG_RANGE_DEFAULT; + pdata->tp_init_phase_ref_lite_med = + VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_MED_RANGE_DEFAULT; + pdata->tp_init_phase_ref_lite_short = + VL53L1_TUNINGPARM_INITIAL_PHASE_REF_LITE_SHORT_RANGE_DEFAULT; + pdata->tp_consistency_lite_phase_tolerance = + VL53L1_TUNINGPARM_CONSISTENCY_LITE_PHASE_TOLERANCE_DEFAULT; + pdata->tp_phasecal_target = + VL53L1_TUNINGPARM_PHASECAL_TARGET_DEFAULT; + pdata->tp_cal_repeat_rate = + VL53L1_TUNINGPARM_LITE_CAL_REPEAT_RATE_DEFAULT; + pdata->tp_lite_min_clip = + VL53L1_TUNINGPARM_LITE_MIN_CLIP_MM_DEFAULT; + pdata->tp_lite_long_sigma_thresh_mm = + VL53L1_TUNINGPARM_LITE_LONG_SIGMA_THRESH_MM_DEFAULT; + pdata->tp_lite_med_sigma_thresh_mm = + VL53L1_TUNINGPARM_LITE_MED_SIGMA_THRESH_MM_DEFAULT; + pdata->tp_lite_short_sigma_thresh_mm = + VL53L1_TUNINGPARM_LITE_SHORT_SIGMA_THRESH_MM_DEFAULT; + pdata->tp_lite_long_min_count_rate_rtn_mcps = + VL53L1_TUNINGPARM_LITE_LONG_MIN_COUNT_RATE_RTN_MCPS_DEFAULT; + pdata->tp_lite_med_min_count_rate_rtn_mcps = + VL53L1_TUNINGPARM_LITE_MED_MIN_COUNT_RATE_RTN_MCPS_DEFAULT; + pdata->tp_lite_short_min_count_rate_rtn_mcps = + VL53L1_TUNINGPARM_LITE_SHORT_MIN_COUNT_RATE_RTN_MCPS_DEFAULT; + pdata->tp_lite_sigma_est_pulse_width_ns = + VL53L1_TUNINGPARM_LITE_SIGMA_EST_PULSE_WIDTH_DEFAULT; + pdata->tp_lite_sigma_est_amb_width_ns = + VL53L1_TUNINGPARM_LITE_SIGMA_EST_AMB_WIDTH_NS_DEFAULT; + pdata->tp_lite_sigma_ref_mm = + VL53L1_TUNINGPARM_LITE_SIGMA_REF_MM_DEFAULT; + pdata->tp_lite_seed_cfg = + VL53L1_TUNINGPARM_LITE_SEED_CONFIG_DEFAULT; + pdata->tp_timed_seed_cfg = + VL53L1_TUNINGPARM_TIMED_SEED_CONFIG_DEFAULT; + pdata->tp_lite_quantifier = + VL53L1_TUNINGPARM_LITE_QUANTIFIER_DEFAULT; + pdata->tp_lite_first_order_select = + VL53L1_TUNINGPARM_LITE_FIRST_ORDER_SELECT_DEFAULT; + + /* Preset Mode Configurations */ + /* - New parms added as part of Patch_TuningParmPresetModeAddition_11839 */ + + pdata->tp_dss_target_lite_mcps = + VL53L1_TUNINGPARM_LITE_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS_DEFAULT; + pdata->tp_dss_target_timed_mcps = + VL53L1_TUNINGPARM_TIMED_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS_DEFAULT; + pdata->tp_phasecal_timeout_lite_us = + VL53L1_TUNINGPARM_LITE_PHASECAL_CONFIG_TIMEOUT_US; + pdata->tp_phasecal_timeout_timed_us = + VL53L1_TUNINGPARM_TIMED_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_mm_timeout_lite_us = + VL53L1_TUNINGPARM_LITE_MM_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_mm_timeout_timed_us = + VL53L1_TUNINGPARM_TIMED_MM_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_range_timeout_lite_us = + VL53L1_TUNINGPARM_LITE_RANGE_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_range_timeout_timed_us = + VL53L1_TUNINGPARM_TIMED_RANGE_CONFIG_TIMEOUT_US_DEFAULT; + + /* Added for Patch_LowPowerAutoMode */ + + pdata->tp_mm_timeout_lpa_us = + VL53L1_TUNINGPARM_LOWPOWERAUTO_MM_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_range_timeout_lpa_us = + VL53L1_TUNINGPARM_LOWPOWERAUTO_RANGE_CONFIG_TIMEOUT_US_DEFAULT; + + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_preset_mode_standard_ranging( + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms) +{ + /* + * Initializes static and dynamic data structures fordevice preset mode + * VL53L1_DEVICEPRESETMODE_STANDARD_RANGING + * + * - streaming + * - single sigma delta + * - back to back + * + * PLEASE NOTE THE SETTINGS BELOW AT PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Static Configuration */ + + /* dss_config__target_total_rate_mcps = 20.0 Mcps 9.7 fp */ + pstatic->dss_config__target_total_rate_mcps = 0x0A00; + pstatic->debug__ctrl = 0x00; + pstatic->test_mode__ctrl = 0x00; + pstatic->clk_gating__ctrl = 0x00; + pstatic->nvm_bist__ctrl = 0x00; + pstatic->nvm_bist__num_nvm_words = 0x00; + pstatic->nvm_bist__start_address = 0x00; + pstatic->host_if__status = 0x00; + pstatic->pad_i2c_hv__config = 0x00; + pstatic->pad_i2c_hv__extsup_config = 0x00; + + /* + * 0 - gpio__extsup_hv + * 1 - gpio__vmodeint_hv + */ + pstatic->gpio_hv_pad__ctrl = 0x00; + + /* + * Set interrupt active low + * + * 3:0 - gpio__mux_select_hv + * 4 - gpio__mux_active_high_hv + */ + pstatic->gpio_hv_mux__ctrl = \ + VL53L1_DEVICEINTERRUPTPOLARITY_ACTIVE_LOW | \ + VL53L1_DEVICEGPIOMODE_OUTPUT_RANGE_AND_ERROR_INTERRUPTS; + + pstatic->gpio__tio_hv_status = 0x02; + pstatic->gpio__fio_hv_status = 0x00; + pstatic->ana_config__spad_sel_pswidth = 0x02; + pstatic->ana_config__vcsel_pulse_width_offset = 0x08; + pstatic->ana_config__fast_osc__config_ctrl = 0x00; + + pstatic->sigma_estimator__effective_pulse_width_ns = + ptuning_parms->tp_lite_sigma_est_pulse_width_ns; + pstatic->sigma_estimator__effective_ambient_width_ns = + ptuning_parms->tp_lite_sigma_est_amb_width_ns; + pstatic->sigma_estimator__sigma_ref_mm = + ptuning_parms->tp_lite_sigma_ref_mm; + /* Minimum allowable value of 1 - 0 disables the feature */ + pstatic->algo__crosstalk_compensation_valid_height_mm = 0x01; + pstatic->spare_host_config__static_config_spare_0 = 0x00; + pstatic->spare_host_config__static_config_spare_1 = 0x00; + + pstatic->algo__range_ignore_threshold_mcps = 0x0000; + + /* set RIT distance to 20 mm */ + pstatic->algo__range_ignore_valid_height_mm = 0xff; + pstatic->algo__range_min_clip = + ptuning_parms->tp_lite_min_clip; + /* + * Phase consistency check limit - format 1.3 fp + * 0x02 -> 0.25 + * 0x08 -> 1.00 + */ + pstatic->algo__consistency_check__tolerance = + ptuning_parms->tp_consistency_lite_phase_tolerance; + pstatic->spare_host_config__static_config_spare_2 = 0x00; + pstatic->sd_config__reset_stages_msb = 0x00; + pstatic->sd_config__reset_stages_lsb = 0x00; + + pgeneral->gph_config__stream_count_update_value = 0x00; + pgeneral->global_config__stream_divider = 0x00; + pgeneral->system__interrupt_config_gpio = + VL53L1_INTERRUPT_CONFIG_NEW_SAMPLE_READY; + pgeneral->cal_config__vcsel_start = 0x0B; + + /* + * Set VHV / Phase Cal repeat rate to 1 every + * 60 * 60 ranges (once every minute @ 60Hz) + * 0 - disables + * 12-bit value -> 4095 max + */ + pgeneral->cal_config__repeat_rate = + ptuning_parms->tp_cal_repeat_rate; + pgeneral->global_config__vcsel_width = 0x02; + /* 13 macro periods gives a timeout of 1ms */ + pgeneral->phasecal_config__timeout_macrop = 0x0D; + /* Phase cal target phase 2.0625 - 4.4 fp -> 0x21*/ + pgeneral->phasecal_config__target = + ptuning_parms->tp_phasecal_target; + pgeneral->phasecal_config__override = 0x00; + pgeneral->dss_config__roi_mode_control = + VL53L1_DEVICEDSSMODE__TARGET_RATE; + /* format for threshold high and low is 9.7 fp */ + pgeneral->system__thresh_rate_high = 0x0000; + pgeneral->system__thresh_rate_low = 0x0000; + /* The format for manual effective spads is 8.8 -> 0x8C00 = 140.00 */ + pgeneral->dss_config__manual_effective_spads_select = 0x8C00; + pgeneral->dss_config__manual_block_select = 0x00; + + /* + * Aperture attenuation value - format 0.8 + * + * Nominal: 5x -> 0.200000 * 256 = 51 = 0x33 + * Measured: 4.6x -> 0.217391 * 256 = 56 = 0x38 + */ + pgeneral->dss_config__aperture_attenuation = 0x38; + pgeneral->dss_config__max_spads_limit = 0xFF; + pgeneral->dss_config__min_spads_limit = 0x01; + + /* Timing Configuration */ + + /* Default timing of 2ms */ + ptiming->mm_config__timeout_macrop_a_hi = 0x00; + ptiming->mm_config__timeout_macrop_a_lo = 0x1a; + ptiming->mm_config__timeout_macrop_b_hi = 0x00; + ptiming->mm_config__timeout_macrop_b_lo = 0x20; + /* Setup for 30ms default */ + ptiming->range_config__timeout_macrop_a_hi = 0x01; + ptiming->range_config__timeout_macrop_a_lo = 0xCC; + /* register value 11 gives a 24 VCSEL period */ + ptiming->range_config__vcsel_period_a = 0x0B; + /* Setup for 30ms default */ + ptiming->range_config__timeout_macrop_b_hi = 0x01; + ptiming->range_config__timeout_macrop_b_lo = 0xF5; + /* register value 09 gives a 20 VCSEL period */ + ptiming->range_config__vcsel_period_b = 0x09; + /* + * Sigma thresh register - format 14.2 + * + * 0x003C -> 15.0 mm + * 0x0050 -> 20.0 mm + */ + ptiming->range_config__sigma_thresh = + ptuning_parms->tp_lite_med_sigma_thresh_mm; + /* + * Rate Limit - format 9.7fp + * 0x0020 -> 0.250 Mcps + * 0x0080 -> 1.000 Mcps + */ + ptiming->range_config__min_count_rate_rtn_limit_mcps = + ptuning_parms->tp_lite_med_min_count_rate_rtn_mcps; + + /* Phase limit register formats = 5.3 + * low = 0x08 -> 1.0 + * high = 0x78 -> 15.0 -> 3.0m + */ + ptiming->range_config__valid_phase_low = 0x08; + ptiming->range_config__valid_phase_high = 0x78; + ptiming->system__intermeasurement_period = 0x00000000; + ptiming->system__fractional_enable = 0x00; + + /* Dynamic Configuration */ + + pdynamic->system__grouped_parameter_hold_0 = 0x01; + + pdynamic->system__thresh_high = 0x0000; + pdynamic->system__thresh_low = 0x0000; + pdynamic->system__enable_xtalk_per_quadrant = 0x00; + pdynamic->system__seed_config = + ptuning_parms->tp_lite_seed_cfg; + + /* Timing A */ + pdynamic->sd_config__woi_sd0 = 0x0B; + /* Timing B */ + pdynamic->sd_config__woi_sd1 = 0x09; + + pdynamic->sd_config__initial_phase_sd0 = + ptuning_parms->tp_init_phase_rtn_lite_med; + pdynamic->sd_config__initial_phase_sd1 = + ptuning_parms->tp_init_phase_ref_lite_med;; + + pdynamic->system__grouped_parameter_hold_1 = 0x01; + + /* + * Quantifier settings + * + * sd_config__first_order_select + * bit 0 - return sigma delta + * bit 1 - reference sigma delta + * + * sd_config__first_order_select = 0x03 (1st order) + * + * sd_config__quantifier options + * 0 + * 1 -> 64 + * 2 -> 128 + * 3 -> 256 + * + * sd_config__first_order_select = 0x00 (2nd order) + * + * sd_config__quantifier options + * 0 + * 1 -> 256 + * 2 -> 1024 + * 3 -> 4095 + * + * Setting below 2nd order, Quantifier = 1024 + */ + + pdynamic->sd_config__first_order_select = + ptuning_parms->tp_lite_first_order_select; + pdynamic->sd_config__quantifier = + ptuning_parms->tp_lite_quantifier; + + /* Below defaults will be overwritten by zone_cfg + * Spad no = 199 (0xC7) + * Spad no = 63 (0x3F) + */ + pdynamic->roi_config__user_roi_centre_spad = 0xC7; + /* 16x16 ROI */ + pdynamic->roi_config__user_roi_requested_global_xy_size = 0xFF; + + + pdynamic->system__sequence_config = \ + VL53L1_SEQUENCE_VHV_EN | \ + VL53L1_SEQUENCE_PHASECAL_EN | \ + VL53L1_SEQUENCE_DSS1_EN | \ + VL53L1_SEQUENCE_DSS2_EN | \ + VL53L1_SEQUENCE_MM2_EN | \ + VL53L1_SEQUENCE_RANGE_EN; + + pdynamic->system__grouped_parameter_hold = 0x02; + + /* System control */ + + + psystem->system__stream_count_ctrl = 0x00; + psystem->firmware__enable = 0x01; + psystem->system__interrupt_clear = \ + VL53L1_CLEAR_RANGE_INT; + + psystem->system__mode_start = \ + VL53L1_DEVICESCHEDULERMODE_STREAMING | \ + VL53L1_DEVICEREADOUTMODE_SINGLE_SD | \ + VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK; + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_preset_mode_standard_ranging_short_range( + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms) +{ + /* + * Initializes static and dynamic data structures for + * device preset mode + * + * VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_SHORT_RANGE + * (up to 1.4 metres) + * + * PLEASE NOTE THE SETTINGS BELOW AT PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Call standard ranging configuration followed by + * overrides for the short range configuration + */ + + status = VL53L1_preset_mode_standard_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + + /* now override standard ranging specific registers */ + + if (status == VL53L1_ERROR_NONE) { + + /* Timing Configuration + * + * vcsel_period_a = 7 -> 16 period + * vcsel_period_b = 5 -> 12 period + * sigma_thresh = 0x003C -> 14.2fp -> 15.0 mm + * min_count_rate_rtn_limit_mcps = 0x0080 -> 9.7fp -> 1.0 Mcps + * valid_phase_low = 0x08 -> 5.3fp -> 1.0 + * valid_phase_high = 0x38 -> 5.3fp -> 7.0 -> 1.4m + */ + + ptiming->range_config__vcsel_period_a = 0x07; + ptiming->range_config__vcsel_period_b = 0x05; + ptiming->range_config__sigma_thresh = + ptuning_parms->tp_lite_short_sigma_thresh_mm; + ptiming->range_config__min_count_rate_rtn_limit_mcps = + ptuning_parms->tp_lite_short_min_count_rate_rtn_mcps; + ptiming->range_config__valid_phase_low = 0x08; + ptiming->range_config__valid_phase_high = 0x38; + + /* Dynamic Configuration + * SD0 -> Timing A + * SD1 -> Timing B + */ + + pdynamic->sd_config__woi_sd0 = 0x07; + pdynamic->sd_config__woi_sd1 = 0x05; + pdynamic->sd_config__initial_phase_sd0 = + ptuning_parms->tp_init_phase_rtn_lite_short; + pdynamic->sd_config__initial_phase_sd1 = + ptuning_parms->tp_init_phase_ref_lite_short; + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_preset_mode_standard_ranging_long_range( + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms) +{ + /* + * Initializes static and dynamic data structures for + * device preset mode + * + * VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_LONG_RANGE + * (up to 4.8 metres) + * + * PLEASE NOTE THE SETTINGS BELOW AT PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Call standard ranging configuration with + * overrides for long range configuration + */ + + status = VL53L1_preset_mode_standard_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + + /* now override standard ranging specific registers */ + + if (status == VL53L1_ERROR_NONE) { + + /* Timing Configuration + * + * vcsel_period_a = 15 -> 32 period + * vcsel_period_b = 13 -> 28 period + * sigma_thresh = 0x003C -> 14.2fp -> 15.0 mm + * min_count_rate_rtn_limit_mcps = 0x0080 -> 9.7fp -> 1.0 Mcps + * valid_phase_low = 0x08 -> 5.3fp -> 1.0 + * valid_phase_high = 0xB8 -> 5.3fp -> 23.0 -> 4.6m + */ + + ptiming->range_config__vcsel_period_a = 0x0F; + ptiming->range_config__vcsel_period_b = 0x0D; + ptiming->range_config__sigma_thresh = + ptuning_parms->tp_lite_long_sigma_thresh_mm; + ptiming->range_config__min_count_rate_rtn_limit_mcps = + ptuning_parms->tp_lite_long_min_count_rate_rtn_mcps; + ptiming->range_config__valid_phase_low = 0x08; + ptiming->range_config__valid_phase_high = 0xB8; + + /* Dynamic Configuration + * SD0 -> Timing A + * SD1 -> Timing B + */ + + pdynamic->sd_config__woi_sd0 = 0x0F; + pdynamic->sd_config__woi_sd1 = 0x0D; + pdynamic->sd_config__initial_phase_sd0 = + ptuning_parms->tp_init_phase_rtn_lite_long; + pdynamic->sd_config__initial_phase_sd1 = + ptuning_parms->tp_init_phase_ref_lite_long; + } + + LOG_FUNCTION_END(status); + + return status; +} + + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_preset_mode_standard_ranging_mm1_cal( + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms) +{ + /* + * Initializes static and dynamic data structures for + * device preset mode + * + * VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM1_CAL + * + * PLEASE NOTE THE SETTINGS BELOW AT PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Call standard ranging configuration with + * overrides for long range configuration + */ + + status = VL53L1_preset_mode_standard_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + + /* now override standard ranging specific registers */ + + if (status == VL53L1_ERROR_NONE) { + + pgeneral->dss_config__roi_mode_control = + VL53L1_DEVICEDSSMODE__REQUESTED_EFFFECTIVE_SPADS; + + pdynamic->system__sequence_config = \ + VL53L1_SEQUENCE_VHV_EN | \ + VL53L1_SEQUENCE_PHASECAL_EN | \ + VL53L1_SEQUENCE_DSS1_EN | \ + VL53L1_SEQUENCE_DSS2_EN | \ + VL53L1_SEQUENCE_MM1_EN; + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_preset_mode_standard_ranging_mm2_cal( + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms) +{ + /* + * Initializes static and dynamic data structures for + * device preset mode + * + * VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM2_CAL + * + * PLEASE NOTE THE SETTINGS BELOW AT PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Call standard ranging configuration with + * overrides for long range configuration + */ + + status = VL53L1_preset_mode_standard_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + + /* now override standard ranging specific registers */ + + if (status == VL53L1_ERROR_NONE) { + + pgeneral->dss_config__roi_mode_control = + VL53L1_DEVICEDSSMODE__REQUESTED_EFFFECTIVE_SPADS; + + pdynamic->system__sequence_config = \ + VL53L1_SEQUENCE_VHV_EN | \ + VL53L1_SEQUENCE_PHASECAL_EN | \ + VL53L1_SEQUENCE_DSS1_EN | \ + VL53L1_SEQUENCE_DSS2_EN | \ + VL53L1_SEQUENCE_MM2_EN; + } + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_preset_mode_timed_ranging( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms) +{ + /* + * Initializes static and dynamic data structures for + * device preset mode + * + * VL53L1_DEVICEPRESETMODE_TIMED_RANGING + * + * - pseudo-solo + * - single sigma delta + * - timed + * + * PLEASE NOTE THE SETTINGS BELOW AT PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Call standard ranging configuration */ + + status = VL53L1_preset_mode_standard_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + + /* now override standard ranging specific registers */ + + if (status == VL53L1_ERROR_NONE) { + + /* Dynamic Configuration */ + + /* Disable GPH */ + pdynamic->system__grouped_parameter_hold = 0x00; + + /* Re-Configure timing budget default for 13ms */ + ptiming->range_config__timeout_macrop_a_hi = 0x00; + ptiming->range_config__timeout_macrop_a_lo = 0xB1; + /* Setup for 13ms default */ + ptiming->range_config__timeout_macrop_b_hi = 0x00; + ptiming->range_config__timeout_macrop_b_lo = 0xD4; + + /* Timing Configuration */ + + ptiming->system__intermeasurement_period = 0x00000600; + pdynamic->system__seed_config = + ptuning_parms->tp_timed_seed_cfg; + + /* System control */ + + /* Configure Timed/Psuedo-solo mode */ + psystem->system__mode_start = + VL53L1_DEVICESCHEDULERMODE_PSEUDO_SOLO | \ + VL53L1_DEVICEREADOUTMODE_SINGLE_SD | \ + VL53L1_DEVICEMEASUREMENTMODE_TIMED; + } + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_preset_mode_timed_ranging_short_range( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms) +{ + /* + * Initializes static and dynamic data structures for + * device preset mode + * + * VL53L1_DEVICEPRESETMODE_TIMED_RANGING_SHORT_RANGE + * + * - pseudo-solo + * - single sigma delta + * - timed + * + * PLEASE NOTE THE SETTINGS BELOW AT PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Call standard ranging configuration */ + + status = VL53L1_preset_mode_standard_ranging_short_range( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + + /* now override standard ranging specific registers */ + + if (status == VL53L1_ERROR_NONE) { + + /* Dynamic Configuration */ + + /* Disable GPH */ + pdynamic->system__grouped_parameter_hold = 0x00; + + + /* Timing Configuration */ + + /* Re-Configure timing budget default for 13ms */ + ptiming->range_config__timeout_macrop_a_hi = 0x01; + ptiming->range_config__timeout_macrop_a_lo = 0x84; + /* Setup for 13ms default */ + ptiming->range_config__timeout_macrop_b_hi = 0x01; + ptiming->range_config__timeout_macrop_b_lo = 0xB1; + + ptiming->system__intermeasurement_period = 0x00000600; + pdynamic->system__seed_config = + ptuning_parms->tp_timed_seed_cfg; + + /* System control */ + + /* Configure Timed/Psuedo-solo mode */ + psystem->system__mode_start = + VL53L1_DEVICESCHEDULERMODE_PSEUDO_SOLO | \ + VL53L1_DEVICEREADOUTMODE_SINGLE_SD | \ + VL53L1_DEVICEMEASUREMENTMODE_TIMED; + } + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_preset_mode_timed_ranging_long_range( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms) +{ + /* + * Initializes static and dynamic data structures for + * device preset mode + * + * VL53L1_DEVICEPRESETMODE_TIMED_RANGING_LONG_RANGE + * + * - pseudo-solo + * - single sigma delta + * - timed + * + * PLEASE NOTE THE SETTINGS BELOW AT PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Call standard ranging configuration */ + + status = VL53L1_preset_mode_standard_ranging_long_range( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + + /* now override standard ranging specific registers */ + + if (status == VL53L1_ERROR_NONE) { + + /* Dynamic Configuration */ + + /* Disable GPH */ + pdynamic->system__grouped_parameter_hold = 0x00; + + + /* Timing Configuration */ + + /* Re-Configure timing budget default for 13ms */ + ptiming->range_config__timeout_macrop_a_hi = 0x00; + ptiming->range_config__timeout_macrop_a_lo = 0x97; + /* Setup for 13ms default */ + ptiming->range_config__timeout_macrop_b_hi = 0x00; + ptiming->range_config__timeout_macrop_b_lo = 0xB1; + + ptiming->system__intermeasurement_period = 0x00000600; + pdynamic->system__seed_config = + ptuning_parms->tp_timed_seed_cfg; + + /* System control */ + + /* Configure Timed/Psuedo-solo mode */ + psystem->system__mode_start = + VL53L1_DEVICESCHEDULERMODE_PSEUDO_SOLO | \ + VL53L1_DEVICEREADOUTMODE_SINGLE_SD | \ + VL53L1_DEVICEMEASUREMENTMODE_TIMED; + } + + LOG_FUNCTION_END(status); + + return status; +} + +/* Start Patch_LowPowerAutoMode */ +VL53L1_Error VL53L1_preset_mode_low_power_auto_ranging( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms, + VL53L1_low_power_auto_data_t *plpadata) +{ + /* + * Initializes static and dynamic data structures for + * device preset mode + * + * VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_MEDIUM_RANGE + * + * - pseudo-solo + * - single sigma delta + * - timed + * - special low power auto mode for Presence application + * + * PLEASE NOTE THE SETTINGS BELOW ARE PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Call standard ranging configuration */ + + status = VL53L1_preset_mode_timed_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + + /* now setup the low power auto mode */ + + if (status == VL53L1_ERROR_NONE) { + status = VL53L1_config_low_power_auto_mode( + pgeneral, + pdynamic, + plpadata + ); + } + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_preset_mode_low_power_auto_short_ranging( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms, + VL53L1_low_power_auto_data_t *plpadata) +{ + /* + * Initializes static and dynamic data structures for + * device preset mode + * + * VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_SHORT_RANGE + * + * - pseudo-solo + * - single sigma delta + * - timed + * - special low power auto mode for Presence application + * + * PLEASE NOTE THE SETTINGS BELOW ARE PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Call standard ranging configuration */ + + status = VL53L1_preset_mode_timed_ranging_short_range( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + + /* now setup the low power auto mode */ + + if (status == VL53L1_ERROR_NONE) { + status = VL53L1_config_low_power_auto_mode( + pgeneral, + pdynamic, + plpadata + ); + } + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_preset_mode_low_power_auto_long_ranging( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms, + VL53L1_low_power_auto_data_t *plpadata) +{ + /* + * Initializes static and dynamic data structures for + * device preset mode + * + * VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_LONG_RANGE + * + * - pseudo-solo + * - single sigma delta + * - timed + * - special low power auto mode for Presence application + * + * PLEASE NOTE THE SETTINGS BELOW ARE PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Call standard ranging configuration */ + + status = VL53L1_preset_mode_timed_ranging_long_range( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + + /* now setup the low power auto mode */ + + if (status == VL53L1_ERROR_NONE) { + status = VL53L1_config_low_power_auto_mode( + pgeneral, + pdynamic, + plpadata + ); + } + + LOG_FUNCTION_END(status); + + return status; +} + +/* End Patch_LowPowerAutoMode */ + +VL53L1_Error VL53L1_preset_mode_singleshot_ranging( + + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms) +{ + /* + * Initializes static and dynamic data structures for device preset mode + * VL53L1_DEVICEPRESETMODE_TIMED_RANGING + * + * - pseudo-solo + * - single sigma delta + * - timed + * + * PLEASE NOTE THE SETTINGS BELOW AT PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Call standard ranging configuration */ + + status = VL53L1_preset_mode_standard_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + + /* now override standard ranging specific registers */ + + if (status == VL53L1_ERROR_NONE) { + + /* Dynamic Configuration */ + + /* Disable GPH */ + pdynamic->system__grouped_parameter_hold = 0x00; + + /* Timing Configuration */ + + /* Re-Configure timing budget default for 13ms */ + ptiming->range_config__timeout_macrop_a_hi = 0x00; + ptiming->range_config__timeout_macrop_a_lo = 0xB1; + /* Setup for 13ms default */ + ptiming->range_config__timeout_macrop_b_hi = 0x00; + ptiming->range_config__timeout_macrop_b_lo = 0xD4; + + pdynamic->system__seed_config = + ptuning_parms->tp_timed_seed_cfg; + + /* System control */ + + /* Configure Timed/Psuedo-solo mode */ + psystem->system__mode_start = \ + VL53L1_DEVICESCHEDULERMODE_PSEUDO_SOLO | \ + VL53L1_DEVICEREADOUTMODE_SINGLE_SD | \ + VL53L1_DEVICEMEASUREMENTMODE_SINGLESHOT; + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_preset_mode_olt( + VL53L1_static_config_t *pstatic, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_system_control_t *psystem, + VL53L1_tuning_parm_storage_t *ptuning_parms) +{ + /** + * Initializes static and dynamic data structures for device preset mode + * VL53L1_DEVICEPRESETMODE_OLT + * + * PLEASE NOTE THE SETTINGS BELOW AT PROVISIONAL AND WILL CHANGE! + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* Call standard ranging configuration */ + + status = VL53L1_preset_mode_standard_ranging( + pstatic, + pgeneral, + ptiming, + pdynamic, + psystem, + ptuning_parms); + + /* now override OLT specific registers */ + + if (status == VL53L1_ERROR_NONE) { + + /* Disables requirement for host handshake */ + psystem->system__stream_count_ctrl = 0x01; + } + + LOG_FUNCTION_END(status); + + return status; +} diff --git a/App/VL53L1X_API/core/src/vl53l1_api_strings.c b/App/VL53L1X_API/core/src/vl53l1_api_strings.c new file mode 100644 index 0000000..0a9a324 --- /dev/null +++ b/App/VL53L1X_API/core/src/vl53l1_api_strings.c @@ -0,0 +1,220 @@ + +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/****************************************************************************** + * Copyright (c) 2020, STMicroelectronics - All Rights Reserved + + This file is part of VL53L1 and is dual licensed, + either GPL-2.0+ + or 'BSD 3-clause "New" or "Revised" License' , at your option. + ****************************************************************************** + */ + +/** + * @file vl53l1_api_strings.c + * @brief VL53L1 API functions for decoding error codes to a text string + */ + +#include "vl53l1_api_core.h" +#include "vl53l1_api_strings.h" +#include "vl53l1_error_codes.h" +#include "vl53l1_error_strings.h" + +#define LOG_FUNCTION_START(fmt, ...) \ + _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_API, fmt, ##__VA_ARGS__) +#define LOG_FUNCTION_END(status, ...) \ + _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_API, status, ##__VA_ARGS__) +#define LOG_FUNCTION_END_FMT(status, fmt, ...) \ + _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_API, status, fmt, \ + ##__VA_ARGS__) + + +VL53L1_Error VL53L1_get_range_status_string( + uint8_t RangeStatus, + char *pRangeStatusString) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + +#ifdef VL53L1_USE_EMPTY_STRING + SUPPRESS_UNUSED_WARNING(RangeStatus); + VL53L1_COPYSTRING(pRangeStatusString, ""); +#else + switch (RangeStatus) { + case 0: + VL53L1_COPYSTRING(pRangeStatusString, + VL53L1_STRING_RANGESTATUS_RANGEVALID); + break; + case 1: + VL53L1_COPYSTRING(pRangeStatusString, + VL53L1_STRING_RANGESTATUS_SIGMA); + break; + case 2: + VL53L1_COPYSTRING(pRangeStatusString, + VL53L1_STRING_RANGESTATUS_SIGNAL); + break; + case 3: + VL53L1_COPYSTRING(pRangeStatusString, + VL53L1_STRING_RANGESTATUS_MINRANGE); + break; + case 4: + VL53L1_COPYSTRING(pRangeStatusString, + VL53L1_STRING_RANGESTATUS_PHASE); + break; + case 5: + VL53L1_COPYSTRING(pRangeStatusString, + VL53L1_STRING_RANGESTATUS_HW); + break; + + default: /**/ + VL53L1_COPYSTRING(pRangeStatusString, + VL53L1_STRING_RANGESTATUS_NONE); + } +#endif + + LOG_FUNCTION_END(status); + return status; +} + + +VL53L1_Error VL53L1_get_pal_state_string( + VL53L1_State PalStateCode, + char *pPalStateString) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + +#ifdef VL53L1_USE_EMPTY_STRING + SUPPRESS_UNUSED_WARNING(PalStateCode); + VL53L1_COPYSTRING(pPalStateString, ""); +#else + switch (PalStateCode) { + case VL53L1_STATE_POWERDOWN: + VL53L1_COPYSTRING(pPalStateString, + VL53L1_STRING_STATE_POWERDOWN); + break; + case VL53L1_STATE_WAIT_STATICINIT: + VL53L1_COPYSTRING(pPalStateString, + VL53L1_STRING_STATE_WAIT_STATICINIT); + break; + case VL53L1_STATE_STANDBY: + VL53L1_COPYSTRING(pPalStateString, + VL53L1_STRING_STATE_STANDBY); + break; + case VL53L1_STATE_IDLE: + VL53L1_COPYSTRING(pPalStateString, + VL53L1_STRING_STATE_IDLE); + break; + case VL53L1_STATE_RUNNING: + VL53L1_COPYSTRING(pPalStateString, + VL53L1_STRING_STATE_RUNNING); + break; + case VL53L1_STATE_RESET: + VL53L1_COPYSTRING(pPalStateString, + VL53L1_STRING_STATE_RESET); + break; + case VL53L1_STATE_UNKNOWN: + VL53L1_COPYSTRING(pPalStateString, + VL53L1_STRING_STATE_UNKNOWN); + break; + case VL53L1_STATE_ERROR: + VL53L1_COPYSTRING(pPalStateString, + VL53L1_STRING_STATE_ERROR); + break; + + default: + VL53L1_COPYSTRING(pPalStateString, + VL53L1_STRING_STATE_UNKNOWN); + } +#endif + + LOG_FUNCTION_END(status); + return status; +} + +VL53L1_Error VL53L1_get_sequence_steps_info( + VL53L1_SequenceStepId SequenceStepId, + char *pSequenceStepsString) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + +#ifdef VL53L1_USE_EMPTY_STRING + SUPPRESS_UNUSED_WARNING(SequenceStepId); + VL53L1_COPYSTRING(pSequenceStepsString, ""); +#else + switch (SequenceStepId) { + case VL53L1_SEQUENCESTEP_VHV: + VL53L1_COPYSTRING(pSequenceStepsString, + VL53L1_STRING_SEQUENCESTEP_VHV); + break; + case VL53L1_SEQUENCESTEP_PHASECAL: + VL53L1_COPYSTRING(pSequenceStepsString, + VL53L1_STRING_SEQUENCESTEP_PHASECAL); + break; + case VL53L1_SEQUENCESTEP_REFPHASE: + VL53L1_COPYSTRING(pSequenceStepsString, + VL53L1_STRING_SEQUENCESTEP_DSS1); + break; + case VL53L1_SEQUENCESTEP_DSS1: + VL53L1_COPYSTRING(pSequenceStepsString, + VL53L1_STRING_SEQUENCESTEP_DSS1); + break; + case VL53L1_SEQUENCESTEP_DSS2: + VL53L1_COPYSTRING(pSequenceStepsString, + VL53L1_STRING_SEQUENCESTEP_DSS2); + break; + case VL53L1_SEQUENCESTEP_MM1: + VL53L1_COPYSTRING(pSequenceStepsString, + VL53L1_STRING_SEQUENCESTEP_MM1); + break; + case VL53L1_SEQUENCESTEP_MM2: + VL53L1_COPYSTRING(pSequenceStepsString, + VL53L1_STRING_SEQUENCESTEP_MM2); + break; + case VL53L1_SEQUENCESTEP_RANGE: + VL53L1_COPYSTRING(pSequenceStepsString, + VL53L1_STRING_SEQUENCESTEP_RANGE); + break; + default: + Status = VL53L1_ERROR_INVALID_PARAMS; + } +#endif + + LOG_FUNCTION_END(Status); + + return Status; +} + +VL53L1_Error VL53L1_get_limit_check_info(uint16_t LimitCheckId, + char *pLimitCheckString) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + +#ifdef VL53L1_USE_EMPTY_STRING + SUPPRESS_UNUSED_WARNING(LimitCheckId); + VL53L1_COPYSTRING(pLimitCheckString, ""); +#else + switch (LimitCheckId) { + case VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE: + VL53L1_COPYSTRING(pLimitCheckString, + VL53L1_STRING_CHECKENABLE_SIGMA_FINAL_RANGE); + break; + case VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: + VL53L1_COPYSTRING(pLimitCheckString, + VL53L1_STRING_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE); + break; + default: + VL53L1_COPYSTRING(pLimitCheckString, + VL53L1_STRING_UNKNOW_ERROR_CODE); + } +#endif + + LOG_FUNCTION_END(Status); + return Status; +} + diff --git a/App/VL53L1X_API/core/src/vl53l1_core.c b/App/VL53L1X_API/core/src/vl53l1_core.c new file mode 100644 index 0000000..9f2d5d4 --- /dev/null +++ b/App/VL53L1X_API/core/src/vl53l1_core.c @@ -0,0 +1,2349 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_core.c + * + * @brief EwokPlus25 core function definition + */ + +#include "vl53l1_ll_def.h" +#include "vl53l1_ll_device.h" +#include "vl53l1_platform.h" +#include "vl53l1_register_map.h" +#include "vl53l1_register_funcs.h" +#include "vl53l1_register_settings.h" +#include "vl53l1_api_preset_modes.h" +#include "vl53l1_core.h" +#include "vl53l1_tuning_parm_defaults.h" + +#ifdef VL53L1_LOGGING +#include "vl53l1_api_debug.h" +#include "vl53l1_debug.h" +#include "vl53l1_register_debug.h" +#endif + +#define LOG_FUNCTION_START(fmt, ...) \ + _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__) +#define LOG_FUNCTION_END(status, ...) \ + _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_CORE, status, ##__VA_ARGS__) +#define LOG_FUNCTION_END_FMT(status, fmt, ...) \ + _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_CORE, \ + status, fmt, ##__VA_ARGS__) + +#define trace_print(level, ...) \ + _LOG_TRACE_PRINT(VL53L1_TRACE_MODULE_CORE, \ + level, VL53L1_TRACE_FUNCTION_NONE, ##__VA_ARGS__) + + +void VL53L1_init_version( + VL53L1_DEV Dev) +{ + /** + * Initialise version structure + */ + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + pdev->version.ll_major = VL53L1_LL_API_IMPLEMENTATION_VER_MAJOR; + pdev->version.ll_minor = VL53L1_LL_API_IMPLEMENTATION_VER_MINOR; + pdev->version.ll_build = VL53L1_LL_API_IMPLEMENTATION_VER_SUB; + pdev->version.ll_revision = VL53L1_LL_API_IMPLEMENTATION_VER_REVISION; +} + + +void VL53L1_init_ll_driver_state( + VL53L1_DEV Dev, + VL53L1_DeviceState device_state) +{ + /** + * Initialise LL Driver state variables + */ + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + VL53L1_ll_driver_state_t *pstate = &(pdev->ll_state); + + pstate->cfg_device_state = device_state; + pstate->cfg_stream_count = 0; + pstate->cfg_gph_id = VL53L1_GROUPEDPARAMETERHOLD_ID_MASK; + pstate->cfg_timing_status = 0; + + pstate->rd_device_state = device_state; + pstate->rd_stream_count = 0; + pstate->rd_gph_id = VL53L1_GROUPEDPARAMETERHOLD_ID_MASK; + pstate->rd_timing_status = 0; + +} + + +VL53L1_Error VL53L1_update_ll_driver_rd_state( + VL53L1_DEV Dev) +{ + /** + * State machine for read device state + * + * VL53L1_DEVICESTATE_SW_STANDBY + * VL53L1_DEVICESTATE_RANGING_WAIT_GPH_SYNC + * VL53L1_DEVICESTATE_RANGING_GATHER_DATA + * VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + VL53L1_ll_driver_state_t *pstate = &(pdev->ll_state); + + /* if top bits of mode start reset are zero then in standby state */ + + LOG_FUNCTION_START(""); + +#ifdef VL53L1_LOGGING + VL53L1_print_ll_driver_state(pstate); +#endif + + if ((pdev->sys_ctrl.system__mode_start & + VL53L1_DEVICEMEASUREMENTMODE_MODE_MASK) == 0x00) { + + pstate->rd_device_state = VL53L1_DEVICESTATE_SW_STANDBY; + pstate->rd_stream_count = 0; + pstate->rd_gph_id = VL53L1_GROUPEDPARAMETERHOLD_ID_MASK; + pstate->rd_timing_status = 0; + + } else { + + /* + * implement read stream count + */ + + if (pstate->rd_stream_count == 0xFF) { + pstate->rd_stream_count = 0x80; + } else { + pstate->rd_stream_count++; + } + + + /* + * Toggle grouped parameter hold ID + */ + + pstate->rd_gph_id ^= VL53L1_GROUPEDPARAMETERHOLD_ID_MASK; + + /* Ok now ranging */ + + switch (pstate->rd_device_state) { + + case VL53L1_DEVICESTATE_SW_STANDBY: + + if ((pdev->dyn_cfg.system__grouped_parameter_hold & + VL53L1_GROUPEDPARAMETERHOLD_ID_MASK) > 0) { + pstate->rd_device_state = + VL53L1_DEVICESTATE_RANGING_WAIT_GPH_SYNC; + } else { + pstate->rd_device_state = + VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA; + } + + pstate->rd_stream_count = 0; + pstate->rd_timing_status = 0; + + break; + + case VL53L1_DEVICESTATE_RANGING_WAIT_GPH_SYNC: + + pstate->rd_stream_count = 0; + pstate->rd_device_state = + VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA; + + break; + + case VL53L1_DEVICESTATE_RANGING_GATHER_DATA: + + pstate->rd_device_state = + VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA; + + break; + + case VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA: + + pstate->rd_timing_status ^= 0x01; + + pstate->rd_device_state = + VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA; + + break; + + default: + + pstate->rd_device_state = + VL53L1_DEVICESTATE_SW_STANDBY; + pstate->rd_stream_count = 0; + pstate->rd_gph_id = VL53L1_GROUPEDPARAMETERHOLD_ID_MASK; + pstate->rd_timing_status = 0; + + break; + } + } + +#ifdef VL53L1_LOGGING + VL53L1_print_ll_driver_state(pstate); +#endif + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_check_ll_driver_rd_state( + VL53L1_DEV Dev) +{ + /* + * Checks if the LL Driver Read state and expected stream count + * matches the state and stream count received from the device + * + * Check is only use in back to back mode + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + VL53L1_ll_driver_state_t *pstate = &(pdev->ll_state); + VL53L1_system_results_t *psys_results = &(pdev->sys_results); + + uint8_t device_range_status = 0; + uint8_t device_stream_count = 0; + uint8_t device_gph_id = 0; + + LOG_FUNCTION_START(""); + +#ifdef VL53L1_LOGGING + VL53L1_print_ll_driver_state(pstate); +#endif + + device_range_status = + psys_results->result__range_status & + VL53L1_RANGE_STATUS__RANGE_STATUS_MASK; + + device_stream_count = psys_results->result__stream_count; + + /* load the correct GPH ID */ + device_gph_id = (psys_results->result__interrupt_status & + VL53L1_INTERRUPT_STATUS__GPH_ID_INT_STATUS_MASK) >> 4; + + /* only apply checks in back to back mode */ + + if ((pdev->sys_ctrl.system__mode_start & + VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK) == + VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK) { + + /* if read state is wait for GPH sync interrupt then check the + * device returns a GPH range status value otherwise check that + * the stream count matches + * + * In theory the stream count should zero for the GPH interrupt + * but that is not the case after at abort .... + */ + + if (pstate->rd_device_state == + VL53L1_DEVICESTATE_RANGING_WAIT_GPH_SYNC) { + + if (device_range_status != + VL53L1_DEVICEERROR_GPHSTREAMCOUNT0READY) { + status = VL53L1_ERROR_GPH_SYNC_CHECK_FAIL; + } + } else { + if (pstate->rd_stream_count != device_stream_count) { + status = VL53L1_ERROR_STREAM_COUNT_CHECK_FAIL; + } + + /* + * Check Read state GPH ID + */ + + if (pstate->rd_gph_id != device_gph_id) { + status = VL53L1_ERROR_GPH_ID_CHECK_FAIL; +#ifdef VL53L1_LOGGING + trace_print(VL53L1_TRACE_LEVEL_ALL, + " RDSTATECHECK: Check failed: rd_gph_id: %d, device_gph_id: %d\n", + pstate->rd_gph_id, + device_gph_id); +#endif + } else { +#ifdef VL53L1_LOGGING + trace_print(VL53L1_TRACE_LEVEL_ALL, + " RDSTATECHECK: Check passed: rd_gph_id: %d, device_gph_id: %d\n", + pstate->rd_gph_id, + device_gph_id); +#endif + } + + } /* else (not in WAIT_GPH_SYNC) */ + + } /* if back to back */ + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_update_ll_driver_cfg_state( + VL53L1_DEV Dev) +{ + /** + * State machine for configuration device state + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = + VL53L1DevStructGetLLDriverHandle(Dev); + + VL53L1_ll_driver_state_t *pstate = &(pdev->ll_state); + + LOG_FUNCTION_START(""); + +#ifdef VL53L1_LOGGING + VL53L1_print_ll_driver_state(pstate); +#endif + + /* if top bits of mode start reset are zero then in standby state */ + + if ((pdev->sys_ctrl.system__mode_start & + VL53L1_DEVICEMEASUREMENTMODE_MODE_MASK) == 0x00) { + + pstate->cfg_device_state = VL53L1_DEVICESTATE_SW_STANDBY; + pstate->cfg_stream_count = 0; + pstate->cfg_gph_id = VL53L1_GROUPEDPARAMETERHOLD_ID_MASK; + pstate->cfg_timing_status = 0; + + } else { + + /* + * implement configuration stream count + */ + + if (pstate->cfg_stream_count == 0xFF) { + pstate->cfg_stream_count = 0x80; + } else { + pstate->cfg_stream_count++; + } + + /* + * Toggle grouped parameter hold ID + */ + + pstate->cfg_gph_id ^= VL53L1_GROUPEDPARAMETERHOLD_ID_MASK; + + /* + * Implement configuration state machine + */ + + switch (pstate->cfg_device_state) { + + case VL53L1_DEVICESTATE_SW_STANDBY: + + pstate->cfg_timing_status ^= 0x01; + pstate->cfg_stream_count = 1; + + pstate->cfg_device_state = VL53L1_DEVICESTATE_RANGING_DSS_AUTO; + break; + + case VL53L1_DEVICESTATE_RANGING_DSS_AUTO: + + pstate->cfg_timing_status ^= 0x01; + + break; + + default: + + pstate->cfg_device_state = VL53L1_DEVICESTATE_SW_STANDBY; + pstate->cfg_stream_count = 0; + pstate->cfg_gph_id = VL53L1_GROUPEDPARAMETERHOLD_ID_MASK; + pstate->cfg_timing_status = 0; + + break; + } + } + +#ifdef VL53L1_LOGGING + VL53L1_print_ll_driver_state(pstate); +#endif + + LOG_FUNCTION_END(status); + + return status; +} + + +void VL53L1_copy_rtn_good_spads_to_buffer( + VL53L1_nvm_copy_data_t *pdata, + uint8_t *pbuffer) +{ + /* + * Convenience function to copy return SPAD enables to buffer + */ + + *(pbuffer + 0) = pdata->global_config__spad_enables_rtn_0; + *(pbuffer + 1) = pdata->global_config__spad_enables_rtn_1; + *(pbuffer + 2) = pdata->global_config__spad_enables_rtn_2; + *(pbuffer + 3) = pdata->global_config__spad_enables_rtn_3; + *(pbuffer + 4) = pdata->global_config__spad_enables_rtn_4; + *(pbuffer + 5) = pdata->global_config__spad_enables_rtn_5; + *(pbuffer + 6) = pdata->global_config__spad_enables_rtn_6; + *(pbuffer + 7) = pdata->global_config__spad_enables_rtn_7; + *(pbuffer + 8) = pdata->global_config__spad_enables_rtn_8; + *(pbuffer + 9) = pdata->global_config__spad_enables_rtn_9; + *(pbuffer + 10) = pdata->global_config__spad_enables_rtn_10; + *(pbuffer + 11) = pdata->global_config__spad_enables_rtn_11; + *(pbuffer + 12) = pdata->global_config__spad_enables_rtn_12; + *(pbuffer + 13) = pdata->global_config__spad_enables_rtn_13; + *(pbuffer + 14) = pdata->global_config__spad_enables_rtn_14; + *(pbuffer + 15) = pdata->global_config__spad_enables_rtn_15; + *(pbuffer + 16) = pdata->global_config__spad_enables_rtn_16; + *(pbuffer + 17) = pdata->global_config__spad_enables_rtn_17; + *(pbuffer + 18) = pdata->global_config__spad_enables_rtn_18; + *(pbuffer + 19) = pdata->global_config__spad_enables_rtn_19; + *(pbuffer + 20) = pdata->global_config__spad_enables_rtn_20; + *(pbuffer + 21) = pdata->global_config__spad_enables_rtn_21; + *(pbuffer + 22) = pdata->global_config__spad_enables_rtn_22; + *(pbuffer + 23) = pdata->global_config__spad_enables_rtn_23; + *(pbuffer + 24) = pdata->global_config__spad_enables_rtn_24; + *(pbuffer + 25) = pdata->global_config__spad_enables_rtn_25; + *(pbuffer + 26) = pdata->global_config__spad_enables_rtn_26; + *(pbuffer + 27) = pdata->global_config__spad_enables_rtn_27; + *(pbuffer + 28) = pdata->global_config__spad_enables_rtn_28; + *(pbuffer + 29) = pdata->global_config__spad_enables_rtn_29; + *(pbuffer + 30) = pdata->global_config__spad_enables_rtn_30; + *(pbuffer + 31) = pdata->global_config__spad_enables_rtn_31; +} + + +void VL53L1_init_system_results( + VL53L1_system_results_t *pdata) +{ + /* + * Initialises the system results to all 0xFF just like the + * device firmware does a the start of a range + */ + + pdata->result__interrupt_status = 0xFF; + pdata->result__range_status = 0xFF; + pdata->result__report_status = 0xFF; + pdata->result__stream_count = 0xFF; + + pdata->result__dss_actual_effective_spads_sd0 = 0xFFFF; + pdata->result__peak_signal_count_rate_mcps_sd0 = 0xFFFF; + pdata->result__ambient_count_rate_mcps_sd0 = 0xFFFF; + pdata->result__sigma_sd0 = 0xFFFF; + pdata->result__phase_sd0 = 0xFFFF; + pdata->result__final_crosstalk_corrected_range_mm_sd0 = 0xFFFF; + pdata->result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 = + 0xFFFF; + pdata->result__mm_inner_actual_effective_spads_sd0 = 0xFFFF; + pdata->result__mm_outer_actual_effective_spads_sd0 = 0xFFFF; + pdata->result__avg_signal_count_rate_mcps_sd0 = 0xFFFF; + + pdata->result__dss_actual_effective_spads_sd1 = 0xFFFF; + pdata->result__peak_signal_count_rate_mcps_sd1 = 0xFFFF; + pdata->result__ambient_count_rate_mcps_sd1 = 0xFFFF; + pdata->result__sigma_sd1 = 0xFFFF; + pdata->result__phase_sd1 = 0xFFFF; + pdata->result__final_crosstalk_corrected_range_mm_sd1 = 0xFFFF; + pdata->result__spare_0_sd1 = 0xFFFF; + pdata->result__spare_1_sd1 = 0xFFFF; + pdata->result__spare_2_sd1 = 0xFFFF; + pdata->result__spare_3_sd1 = 0xFF; + +} + + +void VL53L1_i2c_encode_uint16_t( + uint16_t ip_value, + uint16_t count, + uint8_t *pbuffer) +{ + /* + * Encodes a uint16_t register value into an I2C write buffer + * MS byte first order (as per I2C register map. + */ + + uint16_t i = 0; + uint16_t data = 0; + + data = ip_value; + + for (i = 0; i < count ; i++) { + pbuffer[count-i-1] = (uint8_t)(data & 0x00FF); + data = data >> 8; + } +} + +uint16_t VL53L1_i2c_decode_uint16_t( + uint16_t count, + uint8_t *pbuffer) +{ + /* + * Decodes a uint16_t from the input I2C read buffer + * (MS byte first order) + */ + + uint16_t value = 0x00; + + while (count-- > 0) { + value = (value << 8) | (uint16_t)*pbuffer++; + } + + return value; +} + + +void VL53L1_i2c_encode_int16_t( + int16_t ip_value, + uint16_t count, + uint8_t *pbuffer) +{ + /* + * Encodes a int16_t register value into an I2C write buffer + * MS byte first order (as per I2C register map. + */ + + uint16_t i = 0; + int16_t data = 0; + + data = ip_value; + + for (i = 0; i < count ; i++) { + pbuffer[count-i-1] = (uint8_t)(data & 0x00FF); + data = data >> 8; + } +} + +int16_t VL53L1_i2c_decode_int16_t( + uint16_t count, + uint8_t *pbuffer) +{ + /* + * Decodes a int16_t from the input I2C read buffer + * (MS byte first order) + */ + + int16_t value = 0x00; + + /* implement sign extension */ + if (*pbuffer >= 0x80) { + value = 0xFFFF; + } + + while (count-- > 0) { + value = (value << 8) | (int16_t)*pbuffer++; + } + + return value; +} + +void VL53L1_i2c_encode_uint32_t( + uint32_t ip_value, + uint16_t count, + uint8_t *pbuffer) +{ + /* + * Encodes a uint32_t register value into an I2C write buffer + * MS byte first order (as per I2C register map. + */ + + uint16_t i = 0; + uint32_t data = 0; + + data = ip_value; + + for (i = 0; i < count ; i++) { + pbuffer[count-i-1] = (uint8_t)(data & 0x00FF); + data = data >> 8; + } +} + +uint32_t VL53L1_i2c_decode_uint32_t( + uint16_t count, + uint8_t *pbuffer) +{ + /* + * Decodes a uint32_t from the input I2C read buffer + * (MS byte first order) + */ + + uint32_t value = 0x00; + + while (count-- > 0) { + value = (value << 8) | (uint32_t)*pbuffer++; + } + + return value; +} + + +uint32_t VL53L1_i2c_decode_with_mask( + uint16_t count, + uint8_t *pbuffer, + uint32_t bit_mask, + uint32_t down_shift, + uint32_t offset) +{ + /* + * Decodes an integer from the input I2C read buffer + * (MS byte first order) + */ + + uint32_t value = 0x00; + + /* extract from buffer */ + while (count-- > 0) { + value = (value << 8) | (uint32_t)*pbuffer++; + } + + /* Apply bit mask and down shift */ + value = value & bit_mask; + if (down_shift > 0) { + value = value >> down_shift; + } + + /* add offset */ + value = value + offset; + + return value; +} + + +void VL53L1_i2c_encode_int32_t( + int32_t ip_value, + uint16_t count, + uint8_t *pbuffer) +{ + /* + * Encodes a int32_t register value into an I2C write buffer + * MS byte first order (as per I2C register map. + */ + + uint16_t i = 0; + int32_t data = 0; + + data = ip_value; + + for (i = 0; i < count ; i++) { + pbuffer[count-i-1] = (uint8_t)(data & 0x00FF); + data = data >> 8; + } +} + +int32_t VL53L1_i2c_decode_int32_t( + uint16_t count, + uint8_t *pbuffer) +{ + /* + * Decodes a int32_t from the input I2C read buffer + * (MS byte first order) + */ + + int32_t value = 0x00; + + /* implement sign extension */ + if (*pbuffer >= 0x80) { + value = 0xFFFFFFFF; + } + + while (count-- > 0) { + value = (value << 8) | (int32_t)*pbuffer++; + } + + return value; +} + + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_start_test( + VL53L1_DEV Dev, + uint8_t test_mode__ctrl) +{ + /* + * Triggers the start of a test mode + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) { /*lint !e774 always true*/ + status = VL53L1_WrByte( + Dev, + VL53L1_TEST_MODE__CTRL, + test_mode__ctrl); + } + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_set_firmware_enable_register( + VL53L1_DEV Dev, + uint8_t value) +{ + /* + * Set FIRMWARE__ENABLE register + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + pdev->sys_ctrl.firmware__enable = value; + + status = VL53L1_WrByte( + Dev, + VL53L1_FIRMWARE__ENABLE, + pdev->sys_ctrl.firmware__enable); + + return status; +} + +VL53L1_Error VL53L1_enable_firmware( + VL53L1_DEV Dev) +{ + /* + * Enable firmware + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + status = VL53L1_set_firmware_enable_register(Dev, 0x01); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_disable_firmware( + VL53L1_DEV Dev) +{ + /* + * Disable firmware + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + status = VL53L1_set_firmware_enable_register(Dev, 0x00); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_powerforce_register( + VL53L1_DEV Dev, + uint8_t value) +{ + /* + * Set power force register + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + pdev->sys_ctrl.power_management__go1_power_force = value; + + status = VL53L1_WrByte( + Dev, + VL53L1_POWER_MANAGEMENT__GO1_POWER_FORCE, + pdev->sys_ctrl.power_management__go1_power_force); + + return status; +} + + +VL53L1_Error VL53L1_enable_powerforce( + VL53L1_DEV Dev) +{ + /* + * Enable power force + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + status = VL53L1_set_powerforce_register(Dev, 0x01); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_disable_powerforce( + VL53L1_DEV Dev) +{ + /* + * Disable power force + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + status = VL53L1_set_powerforce_register(Dev, 0x00); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_clear_interrupt( + VL53L1_DEV Dev) +{ + /* + * Clear Ranging interrupt by writing to + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->sys_ctrl.system__interrupt_clear = VL53L1_CLEAR_RANGE_INT; + + status = VL53L1_WrByte( + Dev, + VL53L1_SYSTEM__INTERRUPT_CLEAR, + pdev->sys_ctrl.system__interrupt_clear); + + LOG_FUNCTION_END(status); + + return status; +} + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_force_shadow_stream_count_to_zero( + VL53L1_DEV Dev) +{ + /* + * Forces shadow stream count to zero + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + if (status == VL53L1_ERROR_NONE) { /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + } + + if (status == VL53L1_ERROR_NONE) { + status = VL53L1_WrByte( + Dev, + VL53L1_SHADOW_RESULT__STREAM_COUNT, + 0x00); + } + + if (status == VL53L1_ERROR_NONE) { + status = VL53L1_enable_firmware(Dev); + } + + return status; +} +#endif + +uint32_t VL53L1_calc_macro_period_us( + uint16_t fast_osc_frequency, + uint8_t vcsel_period) +{ + /* Calculates macro period in [us] from the input fast oscillator + * frequency and VCSEL period + * + * Macro period fixed point format = unsigned 12.12 + * Maximum supported macro period = 4095.9999 us + */ + + uint32_t pll_period_us = 0; + uint8_t vcsel_period_pclks = 0; + uint32_t macro_period_us = 0; + + LOG_FUNCTION_START(""); + + /* Calculate PLL period in [us] from the fast_osc_frequency + * Fast osc frequency fixed point format = unsigned 4.12 + */ + + pll_period_us = VL53L1_calc_pll_period_us(fast_osc_frequency); + + /* VCSEL period + * - the real VCSEL period in PLL clocks = 2*(VCSEL_PERIOD+1) + */ + + vcsel_period_pclks = VL53L1_decode_vcsel_period(vcsel_period); + + /* Macro period + * - PLL period [us] = 0.24 format + * - for 1.0 MHz fast oscillator freq + * - max PLL period = 1/64 (6-bits) + * - i.e only the lower 18-bits of PLL Period value are used + * - Macro period [vclks] = 2304 (12-bits) + * + * Max bits (24 - 6) + 12 = 30-bits usage + * + * Downshift by 6 before multiplying by the VCSEL Period + */ + + macro_period_us = + (uint32_t)VL53L1_MACRO_PERIOD_VCSEL_PERIODS * + pll_period_us; + macro_period_us = macro_period_us >> 6; + + macro_period_us = macro_period_us * (uint32_t)vcsel_period_pclks; + macro_period_us = macro_period_us >> 6; + +#ifdef VL53L1_LOGGING + trace_print(VL53L1_TRACE_LEVEL_DEBUG, + " %-48s : %10u\n", "pll_period_us", + pll_period_us); + trace_print(VL53L1_TRACE_LEVEL_DEBUG, + " %-48s : %10u\n", "vcsel_period_pclks", + vcsel_period_pclks); + trace_print(VL53L1_TRACE_LEVEL_DEBUG, + " %-48s : %10u\n", "macro_period_us", + macro_period_us); +#endif + + LOG_FUNCTION_END(0); + + return macro_period_us; +} + + +uint16_t VL53L1_calc_range_ignore_threshold( + uint32_t central_rate, + int16_t x_gradient, + int16_t y_gradient, + uint8_t rate_mult) +{ + /* Calculates Range Ignore Threshold rate per spad + * in Mcps - 3.13 format + * + * Calculates worst case xtalk rate per spad in array corner + * based on input central xtalk and x and y gradients + * + * Worst case rate = central rate + (8*(magnitude(xgrad)) + + * (8*(magnitude(ygrad))) + * + * Range ignore threshold rate is then multiplied by user input + * rate_mult (in 3.5 fractional format) + * + */ + + int32_t range_ignore_thresh_int = 0; + uint16_t range_ignore_thresh_kcps = 0; + int32_t central_rate_int = 0; + int16_t x_gradient_int = 0; + int16_t y_gradient_int = 0; + + LOG_FUNCTION_START(""); + + /* Shift central_rate to .13 fractional for simple addition */ + + central_rate_int = ((int32_t)central_rate * (1 << 4)) / (1000); + + if (x_gradient < 0) { + x_gradient_int = x_gradient * -1; + } + + if (y_gradient < 0) { + y_gradient_int = y_gradient * -1; + } + + /* Calculate full rate per spad - worst case from measured xtalk */ + /* Generated here from .11 fractional kcps */ + /* Additional factor of 4 applied to bring fractional precision to .13 */ + + range_ignore_thresh_int = (8 * x_gradient_int * 4) + (8 * y_gradient_int * 4); + + /* Convert Kcps to Mcps */ + + range_ignore_thresh_int = range_ignore_thresh_int / 1000; + + /* Combine with Central Rate - Mcps .13 format*/ + + range_ignore_thresh_int = range_ignore_thresh_int + central_rate_int; + + /* Mult by user input */ + + range_ignore_thresh_int = (int32_t)rate_mult * range_ignore_thresh_int; + + range_ignore_thresh_int = (range_ignore_thresh_int + (1<<4)) / (1<<5); + + /* Finally clip and output in correct format */ + + if (range_ignore_thresh_int > 0xFFFF) { + range_ignore_thresh_kcps = 0xFFFF; + } else { + range_ignore_thresh_kcps = (uint16_t)range_ignore_thresh_int; + } + +#ifdef VL53L1_LOGGING + trace_print(VL53L1_TRACE_LEVEL_DEBUG, + " %-48s : %10u\n", "range_ignore_thresh_kcps", + range_ignore_thresh_kcps); +#endif + + LOG_FUNCTION_END(0); + + return range_ignore_thresh_kcps; +} + + +uint32_t VL53L1_calc_timeout_mclks( + uint32_t timeout_us, + uint32_t macro_period_us) +{ + /* Calculates the timeout value in macro periods based on the input + * timeout period in milliseconds and the macro period in [us] + * + * Max timeout supported is 1000000 us (1 sec) -> 20-bits + * Max timeout in 20.12 format = 32-bits + * + * Macro period [us] = 12.12 format + */ + + uint32_t timeout_mclks = 0; + + LOG_FUNCTION_START(""); + + timeout_mclks = + ((timeout_us << 12) + (macro_period_us>>1)) / + macro_period_us; + + LOG_FUNCTION_END(0); + + return timeout_mclks; +} + + +uint16_t VL53L1_calc_encoded_timeout( + uint32_t timeout_us, + uint32_t macro_period_us) +{ + /* Calculates the encoded timeout register value based on the input + * timeout period in milliseconds and the macro period in [us] + * + * Max timeout supported is 1000000 us (1 sec) -> 20-bits + * Max timeout in 20.12 format = 32-bits + * + * Macro period [us] = 12.12 format + */ + + uint32_t timeout_mclks = 0; + uint16_t timeout_encoded = 0; + + LOG_FUNCTION_START(""); + + timeout_mclks = + VL53L1_calc_timeout_mclks(timeout_us, macro_period_us); + + timeout_encoded = + VL53L1_encode_timeout(timeout_mclks); + +#ifdef VL53L1_LOGGING + trace_print(VL53L1_TRACE_LEVEL_DEBUG, + " %-48s : %10u (0x%04X)\n", "timeout_mclks", + timeout_mclks, timeout_mclks); + trace_print(VL53L1_TRACE_LEVEL_DEBUG, + " %-48s : %10u (0x%04X)\n", "timeout_encoded", + timeout_encoded, timeout_encoded); +#endif + + LOG_FUNCTION_END(0); + + return timeout_encoded; +} + + +uint32_t VL53L1_calc_timeout_us( + uint32_t timeout_mclks, + uint32_t macro_period_us) +{ + /* Calculates the timeout in [us] based on the input + * encoded timeout and the macro period in [us] + * + * Max timeout supported is 1000000 us (1 sec) -> 20-bits + * Max timeout in 20.12 format = 32-bits + * + * Macro period [us] = 12.12 format + */ + + uint32_t timeout_us = 0; + uint64_t tmp = 0; + + LOG_FUNCTION_START(""); + + tmp = (uint64_t)timeout_mclks * (uint64_t)macro_period_us; + tmp += 0x00800; + tmp = tmp >> 12; + + timeout_us = (uint32_t)tmp; + +#ifdef VL53L1_LOGGING + trace_print(VL53L1_TRACE_LEVEL_DEBUG, + " %-48s : %10u (0x%04X)\n", "timeout_mclks", + timeout_mclks, timeout_mclks); + + trace_print(VL53L1_TRACE_LEVEL_DEBUG, + " %-48s : %10u us\n", "timeout_us", + timeout_us, timeout_us); +#endif + + LOG_FUNCTION_END(0); + + return timeout_us; +} + +uint32_t VL53L1_calc_crosstalk_plane_offset_with_margin( + uint32_t plane_offset_kcps, + int16_t margin_offset_kcps) +{ + uint32_t plane_offset_with_margin = 0; + int32_t plane_offset_kcps_temp = 0; + + LOG_FUNCTION_START(""); + + plane_offset_kcps_temp = + (int32_t)plane_offset_kcps + + (int32_t)margin_offset_kcps; + + if (plane_offset_kcps_temp < 0) { + plane_offset_kcps_temp = 0; + } else { + if (plane_offset_kcps_temp > 0x3FFFF) { + plane_offset_kcps_temp = 0x3FFFF; + } + } + + plane_offset_with_margin = (uint32_t) plane_offset_kcps_temp; + + LOG_FUNCTION_END(0); + + return plane_offset_with_margin; + +} + +uint32_t VL53L1_calc_decoded_timeout_us( + uint16_t timeout_encoded, + uint32_t macro_period_us) +{ + /* Calculates the timeout in [us] based on the input + * encoded timeout and the macro period in [us] + * + * Max timeout supported is 1000000 us (1 sec) -> 20-bits + * Max timeout in 20.12 format = 32-bits + * + * Macro period [us] = 12.12 format + */ + + uint32_t timeout_mclks = 0; + uint32_t timeout_us = 0; + + LOG_FUNCTION_START(""); + + timeout_mclks = + VL53L1_decode_timeout(timeout_encoded); + + timeout_us = + VL53L1_calc_timeout_us(timeout_mclks, macro_period_us); + + LOG_FUNCTION_END(0); + + return timeout_us; +} + + +uint16_t VL53L1_encode_timeout(uint32_t timeout_mclks) +{ + /* + * Encode timeout in macro periods in (LSByte * 2^MSByte) + 1 format + */ + + uint16_t encoded_timeout = 0; + uint32_t ls_byte = 0; + uint16_t ms_byte = 0; + + if (timeout_mclks > 0) { + ls_byte = timeout_mclks - 1; + + while ((ls_byte & 0xFFFFFF00) > 0) { + ls_byte = ls_byte >> 1; + ms_byte++; + } + + encoded_timeout = (ms_byte << 8) + + (uint16_t) (ls_byte & 0x000000FF); + } + + return encoded_timeout; +} + + +uint32_t VL53L1_decode_timeout(uint16_t encoded_timeout) +{ + /* + * Decode 16-bit timeout register value + * format (LSByte * 2^MSByte) + 1 + */ + + uint32_t timeout_macro_clks = 0; + + timeout_macro_clks = ((uint32_t) (encoded_timeout & 0x00FF) + << (uint32_t) ((encoded_timeout & 0xFF00) >> 8)) + 1; + + return timeout_macro_clks; +} + + +VL53L1_Error VL53L1_calc_timeout_register_values( + uint32_t phasecal_config_timeout_us, + uint32_t mm_config_timeout_us, + uint32_t range_config_timeout_us, + uint16_t fast_osc_frequency, + VL53L1_general_config_t *pgeneral, + VL53L1_timing_config_t *ptiming) +{ + /* + * Converts the input MM and range timeouts in [us] + * into the appropriate register values + * + * Must also be run after the VCSEL period settings are changed + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + uint32_t macro_period_us = 0; + uint32_t timeout_mclks = 0; + uint16_t timeout_encoded = 0; + + LOG_FUNCTION_START(""); + + if (fast_osc_frequency == 0) { + status = VL53L1_ERROR_DIVISION_BY_ZERO; + } else { + /* Update Macro Period for Range A VCSEL Period */ + macro_period_us = + VL53L1_calc_macro_period_us( + fast_osc_frequency, + ptiming->range_config__vcsel_period_a); + + /* Update Phase timeout - uses Timing A */ + timeout_mclks = + VL53L1_calc_timeout_mclks( + phasecal_config_timeout_us, + macro_period_us); + + /* clip as the phase cal timeout register is only 8-bits */ + if (timeout_mclks > 0xFF) + timeout_mclks = 0xFF; + + pgeneral->phasecal_config__timeout_macrop = + (uint8_t)timeout_mclks; + + /* Update MM Timing A timeout */ + timeout_encoded = + VL53L1_calc_encoded_timeout( + mm_config_timeout_us, + macro_period_us); + + ptiming->mm_config__timeout_macrop_a_hi = + (uint8_t)((timeout_encoded & 0xFF00) >> 8); + ptiming->mm_config__timeout_macrop_a_lo = + (uint8_t) (timeout_encoded & 0x00FF); + + /* Update Range Timing A timeout */ + timeout_encoded = + VL53L1_calc_encoded_timeout( + range_config_timeout_us, + macro_period_us); + + ptiming->range_config__timeout_macrop_a_hi = + (uint8_t)((timeout_encoded & 0xFF00) >> 8); + ptiming->range_config__timeout_macrop_a_lo = + (uint8_t) (timeout_encoded & 0x00FF); + + /* Update Macro Period for Range B VCSEL Period */ + macro_period_us = + VL53L1_calc_macro_period_us( + fast_osc_frequency, + ptiming->range_config__vcsel_period_b); + + /* Update MM Timing B timeout */ + timeout_encoded = + VL53L1_calc_encoded_timeout( + mm_config_timeout_us, + macro_period_us); + + ptiming->mm_config__timeout_macrop_b_hi = + (uint8_t)((timeout_encoded & 0xFF00) >> 8); + ptiming->mm_config__timeout_macrop_b_lo = + (uint8_t) (timeout_encoded & 0x00FF); + + /* Update Range Timing B timeout */ + timeout_encoded = VL53L1_calc_encoded_timeout( + range_config_timeout_us, + macro_period_us); + + ptiming->range_config__timeout_macrop_b_hi = + (uint8_t)((timeout_encoded & 0xFF00) >> 8); + ptiming->range_config__timeout_macrop_b_lo = + (uint8_t) (timeout_encoded & 0x00FF); + } + + LOG_FUNCTION_END(0); + + return status; + +} + + +uint8_t VL53L1_encode_vcsel_period(uint8_t vcsel_period_pclks) +{ + /* + * Converts the encoded VCSEL period register value into + * the real period in PLL clocks + */ + + uint8_t vcsel_period_reg = 0; + + vcsel_period_reg = (vcsel_period_pclks >> 1) - 1; + + return vcsel_period_reg; +} + + +uint32_t VL53L1_decode_unsigned_integer( + uint8_t *pbuffer, + uint8_t no_of_bytes) +{ + /* + * Decodes a integer number from the buffer + */ + + uint8_t i = 0; + uint32_t decoded_value = 0; + + for (i = 0 ; i < no_of_bytes ; i++) { + decoded_value = (decoded_value << 8) + (uint32_t)pbuffer[i]; + } + + return decoded_value; +} + + +void VL53L1_encode_unsigned_integer( + uint32_t ip_value, + uint8_t no_of_bytes, + uint8_t *pbuffer) +{ + /* + * Encodes an integer number into the buffer + */ + + uint8_t i = 0; + uint32_t data = 0; + + data = ip_value; + for (i = 0; i < no_of_bytes ; i++) { + pbuffer[no_of_bytes-i-1] = data & 0x00FF; + data = data >> 8; + } +} + + +void VL53L1_spad_number_to_byte_bit_index( + uint8_t spad_number, + uint8_t *pbyte_index, + uint8_t *pbit_index, + uint8_t *pbit_mask) +{ + + /** + * Converts the input SPAD number into the SPAD Enable byte index, bit index and bit mask + * + * byte_index = (spad_no >> 3) + * bit_index = spad_no & 0x07 + * bit_mask = 0x01 << bit_index + */ + + *pbyte_index = spad_number >> 3; + *pbit_index = spad_number & 0x07; + *pbit_mask = 0x01 << *pbit_index; + +} + + +void VL53L1_encode_row_col( + uint8_t row, + uint8_t col, + uint8_t *pspad_number) +{ + /** + * Encodes the input array(row,col) location as SPAD number. + */ + + if (row > 7) { + *pspad_number = 128 + (col << 3) + (15-row); + } else { + *pspad_number = ((15-col) << 3) + row; + } +} + + +void VL53L1_decode_zone_size( + uint8_t encoded_xy_size, + uint8_t *pwidth, + uint8_t *pheight) +{ + + /* extract x and y sizes + * + * Important: the sense of the device width and height is swapped + * versus the API sense + * + * MS Nibble = height + * LS Nibble = width + */ + + *pheight = encoded_xy_size >> 4; + *pwidth = encoded_xy_size & 0x0F; + +} + + +void VL53L1_encode_zone_size( + uint8_t width, + uint8_t height, + uint8_t *pencoded_xy_size) +{ + /* merge x and y sizes + * + * Important: the sense of the device width and height is swapped + * versus the API sense + * + * MS Nibble = height + * LS Nibble = width + */ + + *pencoded_xy_size = (height << 4) + width; + +} + + +void VL53L1_decode_zone_limits( + uint8_t encoded_xy_centre, + uint8_t encoded_xy_size, + int16_t *px_ll, + int16_t *py_ll, + int16_t *px_ur, + int16_t *py_ur) +{ + + /* + * compute zone lower left and upper right limits + * + * centre (8,8) width = 16, height = 16 -> (0,0) -> (15,15) + * centre (8,8) width = 14, height = 16 -> (1,0) -> (14,15) + */ + + uint8_t x_centre = 0; + uint8_t y_centre = 0; + uint8_t width = 0; + uint8_t height = 0; + + /* decode zone centre and size information */ + + VL53L1_decode_row_col( + encoded_xy_centre, + &y_centre, + &x_centre); + + VL53L1_decode_zone_size( + encoded_xy_size, + &width, + &height); + + /* compute bounds and clip */ + + *px_ll = (int16_t)x_centre - ((int16_t)width + 1) / 2; + if (*px_ll < 0) + *px_ll = 0; + + *px_ur = *px_ll + (int16_t)width; + if (*px_ur > (VL53L1_SPAD_ARRAY_WIDTH-1)) + *px_ur = VL53L1_SPAD_ARRAY_WIDTH-1; + + *py_ll = (int16_t)y_centre - ((int16_t)height + 1) / 2; + if (*py_ll < 0) + *py_ll = 0; + + *py_ur = *py_ll + (int16_t)height; + if (*py_ur > (VL53L1_SPAD_ARRAY_HEIGHT-1)) + *py_ur = VL53L1_SPAD_ARRAY_HEIGHT-1; +} + + +uint8_t VL53L1_is_aperture_location( + uint8_t row, + uint8_t col) +{ + /* + * Returns > 0 if input (row,col) location is an aperture + */ + + uint8_t is_aperture = 0; + uint8_t mod_row = row % 4; + uint8_t mod_col = col % 4; + + if (mod_row == 0 && mod_col == 2) + is_aperture = 1; + + if (mod_row == 2 && mod_col == 0) + is_aperture = 1; + + return is_aperture; +} + + +void VL53L1_calc_mm_effective_spads( + uint8_t encoded_mm_roi_centre, + uint8_t encoded_mm_roi_size, + uint8_t encoded_zone_centre, + uint8_t encoded_zone_size, + uint8_t *pgood_spads, + uint16_t aperture_attenuation, + uint16_t *pmm_inner_effective_spads, + uint16_t *pmm_outer_effective_spads) +{ + + /* Calculates the effective SPAD counts for the MM inner and outer + * regions based on the input MM ROI, Zone info and return good + * SPAD map + */ + + int16_t x = 0; + int16_t y = 0; + + int16_t mm_x_ll = 0; + int16_t mm_y_ll = 0; + int16_t mm_x_ur = 0; + int16_t mm_y_ur = 0; + + int16_t zone_x_ll = 0; + int16_t zone_y_ll = 0; + int16_t zone_x_ur = 0; + int16_t zone_y_ur = 0; + + uint8_t spad_number = 0; + uint8_t byte_index = 0; + uint8_t bit_index = 0; + uint8_t bit_mask = 0; + + uint8_t is_aperture = 0; + uint16_t spad_attenuation = 0; + + /* decode the MM ROI and Zone limits */ + + VL53L1_decode_zone_limits( + encoded_mm_roi_centre, + encoded_mm_roi_size, + &mm_x_ll, + &mm_y_ll, + &mm_x_ur, + &mm_y_ur); + + VL53L1_decode_zone_limits( + encoded_zone_centre, + encoded_zone_size, + &zone_x_ll, + &zone_y_ll, + &zone_x_ur, + &zone_y_ur); + + /* + * Loop though all SPAD within the zone. Check if it is + * a good SPAD then add the transmission value to either + * the inner or outer effective SPAD count dependent if + * the SPAD lies within the MM ROI. + */ + + *pmm_inner_effective_spads = 0; + *pmm_outer_effective_spads = 0; + + for (y = zone_y_ll ; y <= zone_y_ur ; y++) { + for (x = zone_x_ll ; x <= zone_x_ur ; x++) { + + /* Convert location into SPAD number */ + + VL53L1_encode_row_col( + (uint8_t)y, + (uint8_t)x, + &spad_number); + + /* Convert spad number into byte and bit index + * this is required to look up the appropriate + * SPAD enable bit with the 32-byte good SPAD + * enable buffer + */ + + VL53L1_spad_number_to_byte_bit_index( + spad_number, + &byte_index, + &bit_index, + &bit_mask); + + /* If spad is good then add it */ + + if ((pgood_spads[byte_index] & bit_mask) > 0) { + /* determine if apertured SPAD or not */ + + is_aperture = VL53L1_is_aperture_location( + (uint8_t)y, + (uint8_t)x); + + if (is_aperture > 0) + spad_attenuation = aperture_attenuation; + else + spad_attenuation = 0x0100; + + /* + * if inside MM roi add to inner effective SPAD count + * otherwise add to outer effective SPAD Count + */ + + if (x >= mm_x_ll && x <= mm_x_ur && + y >= mm_y_ll && y <= mm_y_ur) + *pmm_inner_effective_spads += + spad_attenuation; + else + *pmm_outer_effective_spads += + spad_attenuation; + } + } + } +} + + +/* + * Encodes VL53L1_GPIO_interrupt_config_t structure to FW register format + */ + +uint8_t VL53L1_encode_GPIO_interrupt_config( + VL53L1_GPIO_interrupt_config_t *pintconf) +{ + uint8_t system__interrupt_config; + + system__interrupt_config = pintconf->intr_mode_distance; + system__interrupt_config |= ((pintconf->intr_mode_rate) << 2); + system__interrupt_config |= ((pintconf->intr_new_measure_ready) << 5); + system__interrupt_config |= ((pintconf->intr_no_target) << 6); + system__interrupt_config |= ((pintconf->intr_combined_mode) << 7); + + return system__interrupt_config; +} + +/* + * Decodes FW register to VL53L1_GPIO_interrupt_config_t structure + */ + +VL53L1_GPIO_interrupt_config_t VL53L1_decode_GPIO_interrupt_config( + uint8_t system__interrupt_config) +{ + VL53L1_GPIO_interrupt_config_t intconf; + + intconf.intr_mode_distance = system__interrupt_config & 0x03; + intconf.intr_mode_rate = (system__interrupt_config >> 2) & 0x03; + intconf.intr_new_measure_ready = (system__interrupt_config >> 5) & 0x01; + intconf.intr_no_target = (system__interrupt_config >> 6) & 0x01; + intconf.intr_combined_mode = (system__interrupt_config >> 7) & 0x01; + + /* set some default values */ + intconf.threshold_rate_low = 0; + intconf.threshold_rate_high = 0; + intconf.threshold_distance_low = 0; + intconf.threshold_distance_high = 0; + + return intconf; +} + +/* + * Set GPIO distance threshold + */ + +VL53L1_Error VL53L1_set_GPIO_distance_threshold( + VL53L1_DEV Dev, + uint16_t threshold_high, + uint16_t threshold_low) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->dyn_cfg.system__thresh_high = threshold_high; + pdev->dyn_cfg.system__thresh_low = threshold_low; + + LOG_FUNCTION_END(status); + return status; +} + +/* + * Set GPIO rate threshold + */ + +VL53L1_Error VL53L1_set_GPIO_rate_threshold( + VL53L1_DEV Dev, + uint16_t threshold_high, + uint16_t threshold_low) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->gen_cfg.system__thresh_rate_high = threshold_high; + pdev->gen_cfg.system__thresh_rate_low = threshold_low; + + LOG_FUNCTION_END(status); + return status; +} + +/* + * Set GPIO thresholds from structure + */ + +VL53L1_Error VL53L1_set_GPIO_thresholds_from_struct( + VL53L1_DEV Dev, + VL53L1_GPIO_interrupt_config_t *pintconf) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + status = VL53L1_set_GPIO_distance_threshold( + Dev, + pintconf->threshold_distance_high, + pintconf->threshold_distance_low); + + if (status == VL53L1_ERROR_NONE) { + status = + VL53L1_set_GPIO_rate_threshold( + Dev, + pintconf->threshold_rate_high, + pintconf->threshold_rate_low); + } + + LOG_FUNCTION_END(status); + return status; +} + + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_set_ref_spad_char_config( + VL53L1_DEV Dev, + uint8_t vcsel_period_a, + uint32_t phasecal_timeout_us, + uint16_t total_rate_target_mcps, + uint16_t max_count_rate_rtn_limit_mcps, + uint16_t min_count_rate_rtn_limit_mcps, + uint16_t fast_osc_frequency) +{ + /* + * Initialises the VCSEL period A and phasecal timeout registers + * for the Reference SPAD Characterisation test + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t buffer[2]; + + uint32_t macro_period_us = 0; + uint32_t timeout_mclks = 0; + + LOG_FUNCTION_START(""); + + /* + * Update Macro Period for Range A VCSEL Period + */ + macro_period_us = + VL53L1_calc_macro_period_us( + fast_osc_frequency, + vcsel_period_a); + + /* + * Calculate PhaseCal timeout and clip to max of 255 macro periods + */ + + timeout_mclks = phasecal_timeout_us << 12; + timeout_mclks = timeout_mclks + (macro_period_us>>1); + timeout_mclks = timeout_mclks / macro_period_us; + + if (timeout_mclks > 0xFF) + pdev->gen_cfg.phasecal_config__timeout_macrop = 0xFF; + else + pdev->gen_cfg.phasecal_config__timeout_macrop = + (uint8_t)timeout_mclks; + + pdev->tim_cfg.range_config__vcsel_period_a = vcsel_period_a; + + /* + * Update device settings + */ + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = + VL53L1_WrByte( + Dev, + VL53L1_PHASECAL_CONFIG__TIMEOUT_MACROP, + pdev->gen_cfg.phasecal_config__timeout_macrop); + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WrByte( + Dev, + VL53L1_RANGE_CONFIG__VCSEL_PERIOD_A, + pdev->tim_cfg.range_config__vcsel_period_a); + + /* + * Copy vcsel register value to the WOI registers to ensure that + * it is correctly set for the specified VCSEL period + */ + + buffer[0] = pdev->tim_cfg.range_config__vcsel_period_a; + buffer[1] = pdev->tim_cfg.range_config__vcsel_period_a; + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WriteMulti( + Dev, + VL53L1_SD_CONFIG__WOI_SD0, + buffer, + 2); /* It should be be replaced with a define */ + + /* + * Set min, target and max rate limits + */ + + pdev->customer.ref_spad_char__total_rate_target_mcps = + total_rate_target_mcps; + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WrWord( + Dev, + VL53L1_REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS, + total_rate_target_mcps); /* 9.7 format */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WrWord( + Dev, + VL53L1_RANGE_CONFIG__SIGMA_THRESH, + max_count_rate_rtn_limit_mcps); + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WrWord( + Dev, + VL53L1_RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS, + min_count_rate_rtn_limit_mcps); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_ssc_config( + VL53L1_DEV Dev, + VL53L1_ssc_config_t *pssc_cfg, + uint16_t fast_osc_frequency) +{ + /** + * Builds and sends a single I2C multiple byte transaction to + * initialize the device for SSC. + * + * The function also sets the WOI registers based on the input + * vcsel period register value. + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t buffer[5]; + + uint32_t macro_period_us = 0; + uint16_t timeout_encoded = 0; + + LOG_FUNCTION_START(""); + + /* + * Update Macro Period for Range A VCSEL Period + */ + macro_period_us = + VL53L1_calc_macro_period_us( + fast_osc_frequency, + pssc_cfg->vcsel_period); + + /* + * Update MM Timing A timeout + */ + timeout_encoded = + VL53L1_calc_encoded_timeout( + pssc_cfg->timeout_us, + macro_period_us); + + /* update VCSEL timings */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WrByte( + Dev, + VL53L1_CAL_CONFIG__VCSEL_START, + pssc_cfg->vcsel_start); + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WrByte( + Dev, + VL53L1_GLOBAL_CONFIG__VCSEL_WIDTH, + pssc_cfg->vcsel_width); + + /* build buffer for timeouts, period and rate limit */ + + buffer[0] = (uint8_t)((timeout_encoded & 0x0000FF00) >> 8); + buffer[1] = (uint8_t) (timeout_encoded & 0x000000FF); + buffer[2] = pssc_cfg->vcsel_period; + buffer[3] = (uint8_t)((pssc_cfg->rate_limit_mcps & 0x0000FF00) >> 8); + buffer[4] = (uint8_t) (pssc_cfg->rate_limit_mcps & 0x000000FF); + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WriteMulti( + Dev, + VL53L1_RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + buffer, + 5); + + /* + * Copy vcsel register value to the WOI registers to ensure that + * it is correctly set for the specified VCSEL period + */ + + buffer[0] = pssc_cfg->vcsel_period; + buffer[1] = pssc_cfg->vcsel_period; + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WriteMulti( + Dev, + VL53L1_SD_CONFIG__WOI_SD0, + buffer, + 2); + + /* + * Write zero to NVM_BIST_CTRL to send RTN CountRate to Patch RAM + * or 1 to write REF CountRate to Patch RAM + */ + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WrByte( + Dev, + VL53L1_NVM_BIST__CTRL, + pssc_cfg->array_select); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifndef VL53L1_NOCALIB +VL53L1_Error VL53L1_get_spad_rate_data( + VL53L1_DEV Dev, + VL53L1_spad_rate_data_t *pspad_rates) +{ + + /** + * Gets the SSC rate map output + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + int i = 0; + + uint8_t data[512]; + uint8_t *pdata = &data[0]; + + LOG_FUNCTION_START(""); + + /* Disable Firmware to Read Patch Ram */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + /* + * Read Return SPADs Rates from patch RAM. + * Note : platform layer splits the I2C comms into smaller chunks + */ + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_ReadMulti( + Dev, + VL53L1_PRIVATE__PATCH_BASE_ADDR_RSLV, + pdata, + 512); + + /* now convert into 16-bit number */ + pdata = &data[0]; + for (i = 0 ; i < VL53L1_NO_OF_SPAD_ENABLES ; i++) { + pspad_rates->rate_data[i] = + (uint16_t)VL53L1_decode_unsigned_integer(pdata, 2); + pdata += 2; + } + + /* Initialise structure info */ + + pspad_rates->buffer_size = VL53L1_NO_OF_SPAD_ENABLES; + pspad_rates->no_of_values = VL53L1_NO_OF_SPAD_ENABLES; + pspad_rates->fractional_bits = 15; + + /* Re-enable Firmware */ + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + +/* Start Patch_LowPowerAutoMode */ + +VL53L1_Error VL53L1_low_power_auto_data_init( + VL53L1_DEV Dev + ) +{ + + /* + * Initializes internal data structures for low power auto mode + */ + + /* don't really use this here */ + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + pdev->low_power_auto_data.vhv_loop_bound = + VL53L1_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND_DEFAULT; + pdev->low_power_auto_data.is_low_power_auto_mode = 0; + pdev->low_power_auto_data.low_power_auto_range_count = 0; + pdev->low_power_auto_data.saved_interrupt_config = 0; + pdev->low_power_auto_data.saved_vhv_init = 0; + pdev->low_power_auto_data.saved_vhv_timeout = 0; + pdev->low_power_auto_data.first_run_phasecal_result = 0; + pdev->low_power_auto_data.dss__total_rate_per_spad_mcps = 0; + pdev->low_power_auto_data.dss__required_spads = 0; + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_low_power_auto_data_stop_range( + VL53L1_DEV Dev + ) +{ + + /* + * Range has been paused but may continue later + */ + + /* don't really use this here */ + VL53L1_Error status = VL53L1_ERROR_NONE; + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + /* doing this ensures stop_range followed by a get_device_results does + * not mess up the counters */ + + pdev->low_power_auto_data.low_power_auto_range_count = 0xFF; + + pdev->low_power_auto_data.first_run_phasecal_result = 0; + pdev->low_power_auto_data.dss__total_rate_per_spad_mcps = 0; + pdev->low_power_auto_data.dss__required_spads = 0; + + /* restore vhv configs */ + if (pdev->low_power_auto_data.saved_vhv_init != 0) + pdev->stat_nvm.vhv_config__init = + pdev->low_power_auto_data.saved_vhv_init; + if (pdev->low_power_auto_data.saved_vhv_timeout != 0) + pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound = + pdev->low_power_auto_data.saved_vhv_timeout; + + /* remove phasecal override */ + pdev->gen_cfg.phasecal_config__override = 0x00; + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_config_low_power_auto_mode( + VL53L1_general_config_t *pgeneral, + VL53L1_dynamic_config_t *pdynamic, + VL53L1_low_power_auto_data_t *plpadata + ) +{ + + /* + * Initializes configs for when low power auto presets are selected + */ + + /* don't really use this here */ + VL53L1_Error status = VL53L1_ERROR_NONE; + + SUPPRESS_UNUSED_WARNING(pgeneral); + + LOG_FUNCTION_START(""); + + /* set low power auto mode */ + plpadata->is_low_power_auto_mode = 1; + + /* set low power range count to 0 */ + plpadata->low_power_auto_range_count = 0; + + /* Turn off MM1/MM2 and DSS2 */ + pdynamic->system__sequence_config = \ + VL53L1_SEQUENCE_VHV_EN | \ + VL53L1_SEQUENCE_PHASECAL_EN | \ + VL53L1_SEQUENCE_DSS1_EN | \ + VL53L1_SEQUENCE_DSS2_EN | \ + /* VL53L1_SEQUENCE_MM1_EN | \*/ + /* VL53L1_SEQUENCE_MM2_EN | \*/ + VL53L1_SEQUENCE_RANGE_EN; + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_low_power_auto_setup_manual_calibration( + VL53L1_DEV Dev) +{ + + /* + * Setup ranges after the first one in low power auto mode by turning + * off FW calibration steps and programming static values + */ + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + /* don't really use this here */ + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* save original vhv configs */ + pdev->low_power_auto_data.saved_vhv_init = + pdev->stat_nvm.vhv_config__init; + pdev->low_power_auto_data.saved_vhv_timeout = + pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound; + + /* disable VHV init */ + pdev->stat_nvm.vhv_config__init &= 0x7F; + /* set loop bound to tuning param */ + pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound = + (pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound & 0x03) + + (pdev->low_power_auto_data.vhv_loop_bound << 2); + /* override phasecal */ + pdev->gen_cfg.phasecal_config__override = 0x01; + pdev->low_power_auto_data.first_run_phasecal_result = + pdev->dbg_results.phasecal_result__vcsel_start; + pdev->gen_cfg.cal_config__vcsel_start = + pdev->low_power_auto_data.first_run_phasecal_result; + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_low_power_auto_update_DSS( + VL53L1_DEV Dev) +{ + + /* + * Do a DSS calculation and update manual config + */ + + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + /* don't really use this here */ + VL53L1_Error status = VL53L1_ERROR_NONE; + + uint32_t utemp32a; + + LOG_FUNCTION_START(""); + + /* Calc total rate per spad */ + + /* 9.7 format */ + utemp32a = pdev->sys_results.result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 + + pdev->sys_results.result__ambient_count_rate_mcps_sd0; + + /* clip to 16 bits */ + if (utemp32a > 0xFFFF) + utemp32a = 0xFFFF; + + /* shift up to take advantage of 32 bits */ + /* 9.23 format */ + utemp32a = utemp32a << 16; + + /* check SPAD count */ + if (pdev->sys_results.result__dss_actual_effective_spads_sd0 == 0) + status = VL53L1_ERROR_DIVISION_BY_ZERO; + else { + /* format 17.15 */ + utemp32a = utemp32a / + pdev->sys_results.result__dss_actual_effective_spads_sd0; + /* save intermediate result */ + pdev->low_power_auto_data.dss__total_rate_per_spad_mcps = + utemp32a; + + /* get the target rate and shift up by 16 + * format 9.23 */ + utemp32a = pdev->stat_cfg.dss_config__target_total_rate_mcps; + utemp32a = utemp32a << 16; + + /* check for divide by zero */ + if (pdev->low_power_auto_data.dss__total_rate_per_spad_mcps == 0) + status = VL53L1_ERROR_DIVISION_BY_ZERO; + else { + /* divide by rate per spad + * format 24.8 */ + utemp32a = utemp32a / + pdev->low_power_auto_data.dss__total_rate_per_spad_mcps; + + /* clip to 16 bit */ + if (utemp32a > 0xFFFF) + utemp32a = 0xFFFF; + + /* save result in low power auto data */ + pdev->low_power_auto_data.dss__required_spads = + (uint16_t)utemp32a; + + /* override DSS config */ + pdev->gen_cfg.dss_config__manual_effective_spads_select = + pdev->low_power_auto_data.dss__required_spads; + pdev->gen_cfg.dss_config__roi_mode_control = + VL53L1_DEVICEDSSMODE__REQUESTED_EFFFECTIVE_SPADS; + } + + } + + if (status == VL53L1_ERROR_DIVISION_BY_ZERO) { + /* We want to gracefully set a spad target, not just exit with + * an error */ + + /* set target to mid point */ + pdev->low_power_auto_data.dss__required_spads = 0x8000; + + /* override DSS config */ + pdev->gen_cfg.dss_config__manual_effective_spads_select = + pdev->low_power_auto_data.dss__required_spads; + pdev->gen_cfg.dss_config__roi_mode_control = + VL53L1_DEVICEDSSMODE__REQUESTED_EFFFECTIVE_SPADS; + + /* reset error */ + status = VL53L1_ERROR_NONE; + } + + LOG_FUNCTION_END(status); + + return status; +} + + +/* End Patch_LowPowerAutoMode */ diff --git a/App/VL53L1X_API/core/src/vl53l1_core_support.c b/App/VL53L1X_API/core/src/vl53l1_core_support.c new file mode 100644 index 0000000..23a4615 --- /dev/null +++ b/App/VL53L1X_API/core/src/vl53l1_core_support.c @@ -0,0 +1,445 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_core_support.c + * + * @brief EwokPlus25 core function definition + */ + +#include "vl53l1_ll_def.h" +#include "vl53l1_ll_device.h" +#include "vl53l1_platform_log.h" +#include "vl53l1_core_support.h" +#include "vl53l1_platform_user_data.h" +#include "vl53l1_platform_user_defines.h" + +#ifdef VL53L1_LOGGING +#include "vl53l1_debug.h" +#include "vl53l1_register_debug.h" +#endif + +#define LOG_FUNCTION_START(fmt, ...) \ + _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__) +#define LOG_FUNCTION_END(status, ...) \ + _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_CORE, status, ##__VA_ARGS__) +#define LOG_FUNCTION_END_FMT(status, fmt, ...) \ + _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_CORE, \ + status, fmt, ##__VA_ARGS__) + +#define trace_print(level, ...) \ + _LOG_TRACE_PRINT(VL53L1_TRACE_MODULE_CORE, \ + level, VL53L1_TRACE_FUNCTION_NONE, ##__VA_ARGS__) + + +uint32_t VL53L1_calc_pll_period_us( + uint16_t fast_osc_frequency) +{ + /* Calculates PLL frequency using NVM fast_osc_frequency + * Fast osc frequency fixed point format = unsigned 4.12 + * + * PLL period fixed point format = unsigned 0.24 + * Min input fast osc frequency = 1 MHz + * PLL Multiplier = 64 (fixed) + * Min PLL freq = 64.0MHz + * -> max PLL period = 1/ 64 + * -> only the 18 LS bits are used + * + * 2^30 = (2^24) (1.0us) * 4096 (2^12) / 64 (PLL Multiplier) + */ + + uint32_t pll_period_us = 0; + + LOG_FUNCTION_START(""); + + pll_period_us = (0x01 << 30) / fast_osc_frequency; + +#ifdef VL53L1_LOGGING + trace_print(VL53L1_TRACE_LEVEL_DEBUG, + " %-48s : %10u\n", "pll_period_us", + pll_period_us); +#endif + + LOG_FUNCTION_END(0); + + return pll_period_us; +} + + +#ifdef PAL_EXTENDED +uint32_t VL53L1_duration_maths( + uint32_t pll_period_us, + uint32_t vcsel_parm_pclks, + uint32_t window_vclks, + uint32_t elapsed_mclks) +{ + /* + * Generates the ranging duration in us + * + * duration_us = elapsed_mclks * vcsel_perm_pclks * + * window_vclks * pll_period_us + * + * returned value in [us] with no fraction bits + */ + + uint64_t tmp_long_int = 0; + uint32_t duration_us = 0; + + /* PLL period us = 0.24 18 LS bits used + * window_vclks = 12.0 (2304 max) + * output 30b (6.24) + */ + duration_us = window_vclks * pll_period_us; + + /* down shift by 12 + * output 18b (6.12) + */ + duration_us = duration_us >> 12; + + /* Save first part of the calc (#1) */ + tmp_long_int = (uint64_t)duration_us; + + /* Multiply elapsed macro periods (22-bit) + * by VCSEL parameter 6.4 (max 63.9999) + * output 32b (28.4) + */ + duration_us = elapsed_mclks * vcsel_parm_pclks; + + /* down shift by 4 to remove fractional bits (#2) + * output 28b (28.0) + */ + duration_us = duration_us >> 4; + + /* Multiply #1 18b (6.12) by #2 28b (28.0) + * output 46b (34.12) + */ + tmp_long_int = tmp_long_int * (uint64_t)duration_us; + + /* Remove fractional part + * output 34b (34.0) + */ + tmp_long_int = tmp_long_int >> 12; + + /* Clip to 32-bits */ + if (tmp_long_int > 0xFFFFFFFF) { + tmp_long_int = 0xFFFFFFFF; + } + + duration_us = (uint32_t)tmp_long_int; + + return duration_us; +} + + +uint32_t VL53L1_isqrt(uint32_t num) +{ + + /* + * Implements an integer square root + * + * From: http://en.wikipedia.org/wiki/Methods_of_computing_square_roots + */ + + uint32_t res = 0; + uint32_t bit = 1 << 30; /* The second-to-top bit is set: 1 << 14 for 16-bits, 1 << 30 for 32 bits */ + + /* "bit" starts at the highest power of four <= the argument. */ + while (bit > num) { + bit >>= 2; + } + + while (bit != 0) { + if (num >= res + bit) { + num -= res + bit; + res = (res >> 1) + bit; + } else { + res >>= 1; + } + bit >>= 2; + } + + return res; +} + + +uint16_t VL53L1_rate_maths( + int32_t events, + uint32_t time_us) +{ + /* + * Converts events into count rate + * + * Max events = 512 Mcps * 1sec + * = 512,000,000 events + * = 29b + * + * If events > 2^24 use 3-bit fractional bits is used internally + * otherwise 7-bit fractional bits are used + */ + + uint32_t tmp_int = 0; + uint32_t frac_bits = 7; + uint16_t rate_mcps = 0; /* 9.7 format */ + + /* + * Clip input event range + */ + + if (events > VL53L1_SPAD_TOTAL_COUNT_MAX) { + tmp_int = VL53L1_SPAD_TOTAL_COUNT_MAX; + } else if (events > 0) { + tmp_int = (uint32_t)events; + } + + /* + * if events > VL53L1_SPAD_TOTAL_COUNT_RES_THRES use 3 rather + * than 7 fractional bits internal to function + */ + + if (events > VL53L1_SPAD_TOTAL_COUNT_RES_THRES) { + frac_bits = 3; + } else { + frac_bits = 7; + } + + /* + * Create 3 or 7 fractional bits + * output 32b (29.3 or 25.7) + * Divide by range duration in [us] - no fractional bits + */ + if (time_us > 0) { + tmp_int = ((tmp_int << frac_bits) + (time_us / 2)) / time_us; + } + + /* + * Re align if reduced resolution + */ + if (events > VL53L1_SPAD_TOTAL_COUNT_RES_THRES) { + tmp_int = tmp_int << 4; + } + + /* + * Firmware internal count is 17.7 (24b) but it this + * case clip to 16-bit value for reporting + */ + + if (tmp_int > 0xFFFF) { + tmp_int = 0xFFFF; + } + + rate_mcps = (uint16_t)tmp_int; + + return rate_mcps; +} + +uint16_t VL53L1_rate_per_spad_maths( + uint32_t frac_bits, + uint32_t peak_count_rate, + uint16_t num_spads, + uint32_t max_output_value) +{ + + uint32_t tmp_int = 0; + + /* rate_per_spad Format varies with prog frac_bits */ + uint16_t rate_per_spad = 0; + + /* Calculate rate per spad with variable fractional bits */ + + /* Frac_bits should be programmed as final frac_bits - 7 as + * the pk_rate contains an inherent 7 bit resolution + */ + + if (num_spads > 0) { + tmp_int = (peak_count_rate << 8) << frac_bits; + tmp_int = (tmp_int + ((uint32_t)num_spads / 2)) / (uint32_t)num_spads; + } else { + tmp_int = ((peak_count_rate) << frac_bits); + } + + /* Clip in case of overwrap - special code */ + + if (tmp_int > max_output_value) { + tmp_int = max_output_value; + } + + rate_per_spad = (uint16_t)tmp_int; + + return rate_per_spad; +} + +int32_t VL53L1_range_maths( + uint16_t fast_osc_frequency, + uint16_t phase, + uint16_t zero_distance_phase, + uint8_t fractional_bits, + int32_t gain_factor, + int32_t range_offset_mm) +{ + /* + * Converts phase information into distance in [mm] + */ + + uint32_t pll_period_us = 0; /* 0.24 format */ + int64_t tmp_long_int = 0; + int32_t range_mm = 0; + + /* Calculate PLL period in [ps] */ + + pll_period_us = VL53L1_calc_pll_period_us(fast_osc_frequency); + + /* Raw range in [mm] + * + * calculate the phase difference between return and reference phases + * + * phases 16b (5.11) + * output 17b including sign bit + */ + + tmp_long_int = (int64_t)phase - (int64_t)zero_distance_phase; + + /* + * multiply by the PLL period + * + * PLL period 24bit (0.24) but only 18 LS bits used + * + * Output 35b (0.35) (17b + 18b) + */ + + tmp_long_int = tmp_long_int * (int64_t)pll_period_us; + + /* + * Down shift by 9 - Output 26b (0.26) + */ + + tmp_long_int = tmp_long_int / (0x01 << 9); + + /* + * multiply by speed of light in air divided by 8 + * Factor of 8 includes 2 for the round trip and 4 scaling + * + * VL53L1_SPEED_OF_LIGHT_IN_AIR_DIV_8 = 16b (16.2) + * + * Output 42b (18.24) (16b + 26b) + */ + + tmp_long_int = tmp_long_int * VL53L1_SPEED_OF_LIGHT_IN_AIR_DIV_8; + + /* + * Down shift by 22 - Output 20b (18.2) + */ + + tmp_long_int = tmp_long_int / (0x01 << 22); + + /* Add range offset */ + range_mm = (int32_t)tmp_long_int + range_offset_mm; + + /* apply correction gain */ + range_mm *= gain_factor; + range_mm += 0x0400; + range_mm /= 0x0800; + + /* Remove fractional bits */ + if (fractional_bits == 0) + range_mm = range_mm / (0x01 << 2); + else if (fractional_bits == 1) + range_mm = range_mm / (0x01 << 1); + + return range_mm; +} +#endif + +uint8_t VL53L1_decode_vcsel_period(uint8_t vcsel_period_reg) +{ + /* + * Converts the encoded VCSEL period register value into + * the real period in PLL clocks + */ + + uint8_t vcsel_period_pclks = 0; + + vcsel_period_pclks = (vcsel_period_reg + 1) << 1; + + return vcsel_period_pclks; +} + + +void VL53L1_decode_row_col( + uint8_t spad_number, + uint8_t *prow, + uint8_t *pcol) +{ + + /** + * Decodes the array (row,col) location from + * the input SPAD number + */ + + if (spad_number > 127) { + *prow = 8 + ((255-spad_number) & 0x07); + *pcol = (spad_number-128) >> 3; + } else { + *prow = spad_number & 0x07; + *pcol = (127-spad_number) >> 3; + } +} + diff --git a/App/VL53L1X_API/core/src/vl53l1_error_strings.c b/App/VL53L1X_API/core/src/vl53l1_error_strings.c new file mode 100644 index 0000000..307fb67 --- /dev/null +++ b/App/VL53L1X_API/core/src/vl53l1_error_strings.c @@ -0,0 +1,304 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_error_strings.c + * @brief VL53L1 API functions for decoding error codes to a text string + */ + +#include "vl53l1_error_codes.h" +#include "vl53l1_error_strings.h" +#include "vl53l1_platform_log.h" +#include "vl53l1_ll_def.h" + +#define LOG_FUNCTION_START(fmt, ...) \ + _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_API, fmt, ##__VA_ARGS__) +#define LOG_FUNCTION_END(status, ...) \ + _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_API, status, ##__VA_ARGS__) +#define LOG_FUNCTION_END_FMT(status, fmt, ...) \ + _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_API, \ + status, fmt, ##__VA_ARGS__) + + +#ifndef VL53L1_DEBUG + #define VL53L1_USE_EMPTY_STRING +#endif + +VL53L1_Error VL53L1_get_pal_error_string( + VL53L1_Error PalErrorCode, + char *pPalErrorString) +{ + VL53L1_Error Status = VL53L1_ERROR_NONE; + +#ifdef VL53L1_USE_EMPTY_STRING + SUPPRESS_UNUSED_WARNING(PalErrorCode); +#endif + + LOG_FUNCTION_START(""); + +#ifdef VL53L1_USE_EMPTY_STRING + VL53L1_COPYSTRING(pPalErrorString, ""); +#else + + switch (PalErrorCode) { + case VL53L1_ERROR_NONE: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_NONE); + break; + case VL53L1_ERROR_CALIBRATION_WARNING: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_CALIBRATION_WARNING); + break; + case VL53L1_ERROR_MIN_CLIPPED: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_MIN_CLIPPED); + break; + case VL53L1_ERROR_UNDEFINED: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_UNDEFINED); + break; + case VL53L1_ERROR_INVALID_PARAMS: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_INVALID_PARAMS); + break; + case VL53L1_ERROR_NOT_SUPPORTED: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_NOT_SUPPORTED); + break; + case VL53L1_ERROR_RANGE_ERROR: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_RANGE_ERROR); + break; + case VL53L1_ERROR_TIME_OUT: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_TIME_OUT); + break; + case VL53L1_ERROR_MODE_NOT_SUPPORTED: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_MODE_NOT_SUPPORTED); + break; + case VL53L1_ERROR_BUFFER_TOO_SMALL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_BUFFER_TOO_SMALL); + break; + case VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_COMMS_BUFFER_TOO_SMALL); + break; + case VL53L1_ERROR_GPIO_NOT_EXISTING: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_GPIO_NOT_EXISTING); + break; + case VL53L1_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED); + break; + case VL53L1_ERROR_CONTROL_INTERFACE: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_CONTROL_INTERFACE); + break; + case VL53L1_ERROR_INVALID_COMMAND: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_INVALID_COMMAND); + break; + case VL53L1_ERROR_DIVISION_BY_ZERO: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_DIVISION_BY_ZERO); + break; + case VL53L1_ERROR_REF_SPAD_INIT: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_REF_SPAD_INIT); + break; + case VL53L1_ERROR_GPH_SYNC_CHECK_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_GPH_SYNC_CHECK_FAIL); + break; + case VL53L1_ERROR_STREAM_COUNT_CHECK_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_STREAM_COUNT_CHECK_FAIL); + break; + case VL53L1_ERROR_GPH_ID_CHECK_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_GPH_ID_CHECK_FAIL); + break; + case VL53L1_ERROR_ZONE_STREAM_COUNT_CHECK_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_ZONE_STREAM_COUNT_CHECK_FAIL); + break; + case VL53L1_ERROR_ZONE_GPH_ID_CHECK_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_ZONE_GPH_ID_CHECK_FAIL); + break; + + case VL53L1_ERROR_XTALK_EXTRACTION_NO_SAMPLE_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_XTALK_EXTRACTION_NO_SAMPLES_FAIL); + break; + case VL53L1_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL); + break; + + case VL53L1_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL); + break; + case VL53L1_ERROR_OFFSET_CAL_NO_SPADS_ENABLED_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_OFFSET_CAL_NO_SPADS_ENABLED_FAIL); + break; + case VL53L1_ERROR_ZONE_CAL_NO_SAMPLE_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_ZONE_CAL_NO_SAMPLE_FAIL); + break; + + case VL53L1_WARNING_OFFSET_CAL_MISSING_SAMPLES: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_OFFSET_CAL_MISSING_SAMPLES); + break; + case VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH); + break; + case VL53L1_WARNING_OFFSET_CAL_RATE_TOO_HIGH: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_OFFSET_CAL_RATE_TOO_HIGH); + break; + case VL53L1_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW); + break; + + case VL53L1_WARNING_ZONE_CAL_MISSING_SAMPLES: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_ZONE_CAL_MISSING_SAMPLES); + break; + case VL53L1_WARNING_ZONE_CAL_SIGMA_TOO_HIGH: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_ZONE_CAL_SIGMA_TOO_HIGH); + break; + case VL53L1_WARNING_ZONE_CAL_RATE_TOO_HIGH: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_ZONE_CAL_RATE_TOO_HIGH); + break; + + case VL53L1_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS); + break; + case VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH); + break; + case VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW); + break; + + case VL53L1_WARNING_XTALK_MISSING_SAMPLES: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_XTALK_MISSING_SAMPLES); + break; + case VL53L1_WARNING_XTALK_NO_SAMPLES_FOR_GRADIENT: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_XTALK_NO_SAMPLES_FOR_GRADIENT); + break; + case VL53L1_WARNING_XTALK_SIGMA_LIMIT_FOR_GRADIENT: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_WARNING_XTALK_SIGMA_LIMIT_FOR_GRADIENT); + break; + + case VL53L1_ERROR_DEVICE_FIRMWARE_TOO_OLD: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_DEVICE_FIRMWARE_TOO_OLD); + break; + case VL53L1_ERROR_DEVICE_FIRMWARE_TOO_NEW: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_DEVICE_FIRMWARE_TOO_NEW); + break; + case VL53L1_ERROR_UNIT_TEST_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_UNIT_TEST_FAIL); + break; + case VL53L1_ERROR_FILE_READ_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_FILE_READ_FAIL); + break; + case VL53L1_ERROR_FILE_WRITE_FAIL: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_FILE_WRITE_FAIL); + break; + case VL53L1_ERROR_NOT_IMPLEMENTED: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_ERROR_NOT_IMPLEMENTED); + break; + default: + VL53L1_COPYSTRING(pPalErrorString, + VL53L1_STRING_UNKNOW_ERROR_CODE); + } + +#endif + + LOG_FUNCTION_END(Status); + + return Status; +} diff --git a/App/VL53L1X_API/core/src/vl53l1_register_funcs.c b/App/VL53L1X_API/core/src/vl53l1_register_funcs.c new file mode 100644 index 0000000..c6e0e82 --- /dev/null +++ b/App/VL53L1X_API/core/src/vl53l1_register_funcs.c @@ -0,0 +1,4489 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_register_funcs.c + * @brief VL53L1 Register Function definitions + */ + +#include "vl53l1_ll_def.h" +#include "vl53l1_platform.h" +#include "vl53l1_platform_log.h" +#include "vl53l1_core.h" +#include "vl53l1_register_map.h" +#include "vl53l1_register_structs.h" +#include "vl53l1_register_funcs.h" + +#define LOG_FUNCTION_START(fmt, ...) \ + _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_REGISTERS, fmt, ##__VA_ARGS__) +#define LOG_FUNCTION_END(status, ...) \ + _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_REGISTERS, status, ##__VA_ARGS__) +#define LOG_FUNCTION_END_FMT(status, fmt, ...) \ + _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_REGISTERS, status, fmt, ##__VA_ARGS__) + + +VL53L1_Error VL53L1_i2c_encode_static_nvm_managed( + VL53L1_static_nvm_managed_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_static_nvm_managed_t into a I2C write buffer + * Buffer must be at least 11 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_STATIC_NVM_MANAGED_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->i2c_slave__device_address & 0x7F; + *(pbuffer + 1) = + pdata->ana_config__vhv_ref_sel_vddpix & 0xF; + *(pbuffer + 2) = + pdata->ana_config__vhv_ref_sel_vquench & 0x7F; + *(pbuffer + 3) = + pdata->ana_config__reg_avdd1v2_sel & 0x3; + *(pbuffer + 4) = + pdata->ana_config__fast_osc__trim & 0x7F; + VL53L1_i2c_encode_uint16_t( + pdata->osc_measured__fast_osc__frequency, + 2, + pbuffer + 5); + *(pbuffer + 7) = + pdata->vhv_config__timeout_macrop_loop_bound; + *(pbuffer + 8) = + pdata->vhv_config__count_thresh; + *(pbuffer + 9) = + pdata->vhv_config__offset & 0x3F; + *(pbuffer + 10) = + pdata->vhv_config__init; + LOG_FUNCTION_END(status); + + + return status; +} + + +VL53L1_Error VL53L1_i2c_decode_static_nvm_managed( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_static_nvm_managed_t *pdata) +{ + /** + * Decodes data structure VL53L1_static_nvm_managed_t from the input I2C read buffer + * Buffer must be at least 11 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_STATIC_NVM_MANAGED_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->i2c_slave__device_address = + (*(pbuffer + 0)) & 0x7F; + pdata->ana_config__vhv_ref_sel_vddpix = + (*(pbuffer + 1)) & 0xF; + pdata->ana_config__vhv_ref_sel_vquench = + (*(pbuffer + 2)) & 0x7F; + pdata->ana_config__reg_avdd1v2_sel = + (*(pbuffer + 3)) & 0x3; + pdata->ana_config__fast_osc__trim = + (*(pbuffer + 4)) & 0x7F; + pdata->osc_measured__fast_osc__frequency = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 5)); + pdata->vhv_config__timeout_macrop_loop_bound = + (*(pbuffer + 7)); + pdata->vhv_config__count_thresh = + (*(pbuffer + 8)); + pdata->vhv_config__offset = + (*(pbuffer + 9)) & 0x3F; + pdata->vhv_config__init = + (*(pbuffer + 10)); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_static_nvm_managed( + VL53L1_DEV Dev, + VL53L1_static_nvm_managed_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_static_nvm_managed_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_STATIC_NVM_MANAGED_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_static_nvm_managed( + pdata, + VL53L1_STATIC_NVM_MANAGED_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_I2C_SLAVE__DEVICE_ADDRESS, + comms_buffer, + VL53L1_STATIC_NVM_MANAGED_I2C_SIZE_BYTES); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_static_nvm_managed( + VL53L1_DEV Dev, + VL53L1_static_nvm_managed_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_static_nvm_managed_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_STATIC_NVM_MANAGED_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_ReadMulti( + Dev, + VL53L1_I2C_SLAVE__DEVICE_ADDRESS, + comms_buffer, + VL53L1_STATIC_NVM_MANAGED_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_static_nvm_managed( + VL53L1_STATIC_NVM_MANAGED_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_i2c_encode_customer_nvm_managed( + VL53L1_customer_nvm_managed_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_customer_nvm_managed_t into a I2C write buffer + * Buffer must be at least 23 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->global_config__spad_enables_ref_0; + *(pbuffer + 1) = + pdata->global_config__spad_enables_ref_1; + *(pbuffer + 2) = + pdata->global_config__spad_enables_ref_2; + *(pbuffer + 3) = + pdata->global_config__spad_enables_ref_3; + *(pbuffer + 4) = + pdata->global_config__spad_enables_ref_4; + *(pbuffer + 5) = + pdata->global_config__spad_enables_ref_5 & 0xF; + *(pbuffer + 6) = + pdata->global_config__ref_en_start_select; + *(pbuffer + 7) = + pdata->ref_spad_man__num_requested_ref_spads & 0x3F; + *(pbuffer + 8) = + pdata->ref_spad_man__ref_location & 0x3; + VL53L1_i2c_encode_uint16_t( + pdata->algo__crosstalk_compensation_plane_offset_kcps, + 2, + pbuffer + 9); + VL53L1_i2c_encode_int16_t( + pdata->algo__crosstalk_compensation_x_plane_gradient_kcps, + 2, + pbuffer + 11); + VL53L1_i2c_encode_int16_t( + pdata->algo__crosstalk_compensation_y_plane_gradient_kcps, + 2, + pbuffer + 13); + VL53L1_i2c_encode_uint16_t( + pdata->ref_spad_char__total_rate_target_mcps, + 2, + pbuffer + 15); + VL53L1_i2c_encode_int16_t( + pdata->algo__part_to_part_range_offset_mm & 0x1FFF, + 2, + pbuffer + 17); + VL53L1_i2c_encode_int16_t( + pdata->mm_config__inner_offset_mm, + 2, + pbuffer + 19); + VL53L1_i2c_encode_int16_t( + pdata->mm_config__outer_offset_mm, + 2, + pbuffer + 21); + LOG_FUNCTION_END(status); + + + return status; +} + + +VL53L1_Error VL53L1_i2c_decode_customer_nvm_managed( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_customer_nvm_managed_t *pdata) +{ + /** + * Decodes data structure VL53L1_customer_nvm_managed_t from the input I2C read buffer + * Buffer must be at least 23 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->global_config__spad_enables_ref_0 = + (*(pbuffer + 0)); + pdata->global_config__spad_enables_ref_1 = + (*(pbuffer + 1)); + pdata->global_config__spad_enables_ref_2 = + (*(pbuffer + 2)); + pdata->global_config__spad_enables_ref_3 = + (*(pbuffer + 3)); + pdata->global_config__spad_enables_ref_4 = + (*(pbuffer + 4)); + pdata->global_config__spad_enables_ref_5 = + (*(pbuffer + 5)) & 0xF; + pdata->global_config__ref_en_start_select = + (*(pbuffer + 6)); + pdata->ref_spad_man__num_requested_ref_spads = + (*(pbuffer + 7)) & 0x3F; + pdata->ref_spad_man__ref_location = + (*(pbuffer + 8)) & 0x3; + pdata->algo__crosstalk_compensation_plane_offset_kcps = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 9)); + pdata->algo__crosstalk_compensation_x_plane_gradient_kcps = + (VL53L1_i2c_decode_int16_t(2, pbuffer + 11)); + pdata->algo__crosstalk_compensation_y_plane_gradient_kcps = + (VL53L1_i2c_decode_int16_t(2, pbuffer + 13)); + pdata->ref_spad_char__total_rate_target_mcps = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 15)); + pdata->algo__part_to_part_range_offset_mm = + (VL53L1_i2c_decode_int16_t(2, pbuffer + 17)) & 0x1FFF; + pdata->mm_config__inner_offset_mm = + (VL53L1_i2c_decode_int16_t(2, pbuffer + 19)); + pdata->mm_config__outer_offset_mm = + (VL53L1_i2c_decode_int16_t(2, pbuffer + 21)); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_customer_nvm_managed( + VL53L1_DEV Dev, + VL53L1_customer_nvm_managed_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_customer_nvm_managed_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_customer_nvm_managed( + pdata, + VL53L1_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_0, + comms_buffer, + VL53L1_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_customer_nvm_managed( + VL53L1_DEV Dev, + VL53L1_customer_nvm_managed_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_customer_nvm_managed_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_ReadMulti( + Dev, + VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_0, + comms_buffer, + VL53L1_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_customer_nvm_managed( + VL53L1_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_i2c_encode_static_config( + VL53L1_static_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_static_config_t into a I2C write buffer + * Buffer must be at least 32 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_STATIC_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + VL53L1_i2c_encode_uint16_t( + pdata->dss_config__target_total_rate_mcps, + 2, + pbuffer + 0); + *(pbuffer + 2) = + pdata->debug__ctrl & 0x1; + *(pbuffer + 3) = + pdata->test_mode__ctrl & 0xF; + *(pbuffer + 4) = + pdata->clk_gating__ctrl & 0xF; + *(pbuffer + 5) = + pdata->nvm_bist__ctrl & 0x1F; + *(pbuffer + 6) = + pdata->nvm_bist__num_nvm_words & 0x7F; + *(pbuffer + 7) = + pdata->nvm_bist__start_address & 0x7F; + *(pbuffer + 8) = + pdata->host_if__status & 0x1; + *(pbuffer + 9) = + pdata->pad_i2c_hv__config; + *(pbuffer + 10) = + pdata->pad_i2c_hv__extsup_config & 0x1; + *(pbuffer + 11) = + pdata->gpio_hv_pad__ctrl & 0x3; + *(pbuffer + 12) = + pdata->gpio_hv_mux__ctrl & 0x1F; + *(pbuffer + 13) = + pdata->gpio__tio_hv_status & 0x3; + *(pbuffer + 14) = + pdata->gpio__fio_hv_status & 0x3; + *(pbuffer + 15) = + pdata->ana_config__spad_sel_pswidth & 0x7; + *(pbuffer + 16) = + pdata->ana_config__vcsel_pulse_width_offset & 0x1F; + *(pbuffer + 17) = + pdata->ana_config__fast_osc__config_ctrl & 0x1; + *(pbuffer + 18) = + pdata->sigma_estimator__effective_pulse_width_ns; + *(pbuffer + 19) = + pdata->sigma_estimator__effective_ambient_width_ns; + *(pbuffer + 20) = + pdata->sigma_estimator__sigma_ref_mm; + *(pbuffer + 21) = + pdata->algo__crosstalk_compensation_valid_height_mm; + *(pbuffer + 22) = + pdata->spare_host_config__static_config_spare_0; + *(pbuffer + 23) = + pdata->spare_host_config__static_config_spare_1; + VL53L1_i2c_encode_uint16_t( + pdata->algo__range_ignore_threshold_mcps, + 2, + pbuffer + 24); + *(pbuffer + 26) = + pdata->algo__range_ignore_valid_height_mm; + *(pbuffer + 27) = + pdata->algo__range_min_clip; + *(pbuffer + 28) = + pdata->algo__consistency_check__tolerance & 0xF; + *(pbuffer + 29) = + pdata->spare_host_config__static_config_spare_2; + *(pbuffer + 30) = + pdata->sd_config__reset_stages_msb & 0xF; + *(pbuffer + 31) = + pdata->sd_config__reset_stages_lsb; + LOG_FUNCTION_END(status); + + + return status; +} + + +VL53L1_Error VL53L1_i2c_decode_static_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_static_config_t *pdata) +{ + /** + * Decodes data structure VL53L1_static_config_t from the input I2C read buffer + * Buffer must be at least 32 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_STATIC_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->dss_config__target_total_rate_mcps = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 0)); + pdata->debug__ctrl = + (*(pbuffer + 2)) & 0x1; + pdata->test_mode__ctrl = + (*(pbuffer + 3)) & 0xF; + pdata->clk_gating__ctrl = + (*(pbuffer + 4)) & 0xF; + pdata->nvm_bist__ctrl = + (*(pbuffer + 5)) & 0x1F; + pdata->nvm_bist__num_nvm_words = + (*(pbuffer + 6)) & 0x7F; + pdata->nvm_bist__start_address = + (*(pbuffer + 7)) & 0x7F; + pdata->host_if__status = + (*(pbuffer + 8)) & 0x1; + pdata->pad_i2c_hv__config = + (*(pbuffer + 9)); + pdata->pad_i2c_hv__extsup_config = + (*(pbuffer + 10)) & 0x1; + pdata->gpio_hv_pad__ctrl = + (*(pbuffer + 11)) & 0x3; + pdata->gpio_hv_mux__ctrl = + (*(pbuffer + 12)) & 0x1F; + pdata->gpio__tio_hv_status = + (*(pbuffer + 13)) & 0x3; + pdata->gpio__fio_hv_status = + (*(pbuffer + 14)) & 0x3; + pdata->ana_config__spad_sel_pswidth = + (*(pbuffer + 15)) & 0x7; + pdata->ana_config__vcsel_pulse_width_offset = + (*(pbuffer + 16)) & 0x1F; + pdata->ana_config__fast_osc__config_ctrl = + (*(pbuffer + 17)) & 0x1; + pdata->sigma_estimator__effective_pulse_width_ns = + (*(pbuffer + 18)); + pdata->sigma_estimator__effective_ambient_width_ns = + (*(pbuffer + 19)); + pdata->sigma_estimator__sigma_ref_mm = + (*(pbuffer + 20)); + pdata->algo__crosstalk_compensation_valid_height_mm = + (*(pbuffer + 21)); + pdata->spare_host_config__static_config_spare_0 = + (*(pbuffer + 22)); + pdata->spare_host_config__static_config_spare_1 = + (*(pbuffer + 23)); + pdata->algo__range_ignore_threshold_mcps = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 24)); + pdata->algo__range_ignore_valid_height_mm = + (*(pbuffer + 26)); + pdata->algo__range_min_clip = + (*(pbuffer + 27)); + pdata->algo__consistency_check__tolerance = + (*(pbuffer + 28)) & 0xF; + pdata->spare_host_config__static_config_spare_2 = + (*(pbuffer + 29)); + pdata->sd_config__reset_stages_msb = + (*(pbuffer + 30)) & 0xF; + pdata->sd_config__reset_stages_lsb = + (*(pbuffer + 31)); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_static_config( + VL53L1_DEV Dev, + VL53L1_static_config_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_static_config_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_STATIC_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_static_config( + pdata, + VL53L1_STATIC_CONFIG_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_DSS_CONFIG__TARGET_TOTAL_RATE_MCPS, + comms_buffer, + VL53L1_STATIC_CONFIG_I2C_SIZE_BYTES); + + LOG_FUNCTION_END(status); + + return status; +} + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_static_config( + VL53L1_DEV Dev, + VL53L1_static_config_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_static_config_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_STATIC_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_ReadMulti( + Dev, + VL53L1_DSS_CONFIG__TARGET_TOTAL_RATE_MCPS, + comms_buffer, + VL53L1_STATIC_CONFIG_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_static_config( + VL53L1_STATIC_CONFIG_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_i2c_encode_general_config( + VL53L1_general_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_general_config_t into a I2C write buffer + * Buffer must be at least 22 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_GENERAL_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->gph_config__stream_count_update_value; + *(pbuffer + 1) = + pdata->global_config__stream_divider; + *(pbuffer + 2) = + pdata->system__interrupt_config_gpio; + *(pbuffer + 3) = + pdata->cal_config__vcsel_start & 0x7F; + VL53L1_i2c_encode_uint16_t( + pdata->cal_config__repeat_rate & 0xFFF, + 2, + pbuffer + 4); + *(pbuffer + 6) = + pdata->global_config__vcsel_width & 0x7F; + *(pbuffer + 7) = + pdata->phasecal_config__timeout_macrop; + *(pbuffer + 8) = + pdata->phasecal_config__target; + *(pbuffer + 9) = + pdata->phasecal_config__override & 0x1; + *(pbuffer + 11) = + pdata->dss_config__roi_mode_control & 0x7; + VL53L1_i2c_encode_uint16_t( + pdata->system__thresh_rate_high, + 2, + pbuffer + 12); + VL53L1_i2c_encode_uint16_t( + pdata->system__thresh_rate_low, + 2, + pbuffer + 14); + VL53L1_i2c_encode_uint16_t( + pdata->dss_config__manual_effective_spads_select, + 2, + pbuffer + 16); + *(pbuffer + 18) = + pdata->dss_config__manual_block_select; + *(pbuffer + 19) = + pdata->dss_config__aperture_attenuation; + *(pbuffer + 20) = + pdata->dss_config__max_spads_limit; + *(pbuffer + 21) = + pdata->dss_config__min_spads_limit; + LOG_FUNCTION_END(status); + + + return status; +} + + +VL53L1_Error VL53L1_i2c_decode_general_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_general_config_t *pdata) +{ + /** + * Decodes data structure VL53L1_general_config_t from the input I2C read buffer + * Buffer must be at least 22 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_GENERAL_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->gph_config__stream_count_update_value = + (*(pbuffer + 0)); + pdata->global_config__stream_divider = + (*(pbuffer + 1)); + pdata->system__interrupt_config_gpio = + (*(pbuffer + 2)); + pdata->cal_config__vcsel_start = + (*(pbuffer + 3)) & 0x7F; + pdata->cal_config__repeat_rate = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 4)) & 0xFFF; + pdata->global_config__vcsel_width = + (*(pbuffer + 6)) & 0x7F; + pdata->phasecal_config__timeout_macrop = + (*(pbuffer + 7)); + pdata->phasecal_config__target = + (*(pbuffer + 8)); + pdata->phasecal_config__override = + (*(pbuffer + 9)) & 0x1; + pdata->dss_config__roi_mode_control = + (*(pbuffer + 11)) & 0x7; + pdata->system__thresh_rate_high = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 12)); + pdata->system__thresh_rate_low = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 14)); + pdata->dss_config__manual_effective_spads_select = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 16)); + pdata->dss_config__manual_block_select = + (*(pbuffer + 18)); + pdata->dss_config__aperture_attenuation = + (*(pbuffer + 19)); + pdata->dss_config__max_spads_limit = + (*(pbuffer + 20)); + pdata->dss_config__min_spads_limit = + (*(pbuffer + 21)); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_general_config( + VL53L1_DEV Dev, + VL53L1_general_config_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_general_config_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_GENERAL_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_general_config( + pdata, + VL53L1_GENERAL_CONFIG_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_GPH_CONFIG__STREAM_COUNT_UPDATE_VALUE, + comms_buffer, + VL53L1_GENERAL_CONFIG_I2C_SIZE_BYTES); + + LOG_FUNCTION_END(status); + + return status; +} + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_general_config( + VL53L1_DEV Dev, + VL53L1_general_config_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_general_config_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_GENERAL_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_ReadMulti( + Dev, + VL53L1_GPH_CONFIG__STREAM_COUNT_UPDATE_VALUE, + comms_buffer, + VL53L1_GENERAL_CONFIG_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_general_config( + VL53L1_GENERAL_CONFIG_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_i2c_encode_timing_config( + VL53L1_timing_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_timing_config_t into a I2C write buffer + * Buffer must be at least 23 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_TIMING_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->mm_config__timeout_macrop_a_hi & 0xF; + *(pbuffer + 1) = + pdata->mm_config__timeout_macrop_a_lo; + *(pbuffer + 2) = + pdata->mm_config__timeout_macrop_b_hi & 0xF; + *(pbuffer + 3) = + pdata->mm_config__timeout_macrop_b_lo; + *(pbuffer + 4) = + pdata->range_config__timeout_macrop_a_hi & 0xF; + *(pbuffer + 5) = + pdata->range_config__timeout_macrop_a_lo; + *(pbuffer + 6) = + pdata->range_config__vcsel_period_a & 0x3F; + *(pbuffer + 7) = + pdata->range_config__timeout_macrop_b_hi & 0xF; + *(pbuffer + 8) = + pdata->range_config__timeout_macrop_b_lo; + *(pbuffer + 9) = + pdata->range_config__vcsel_period_b & 0x3F; + VL53L1_i2c_encode_uint16_t( + pdata->range_config__sigma_thresh, + 2, + pbuffer + 10); + VL53L1_i2c_encode_uint16_t( + pdata->range_config__min_count_rate_rtn_limit_mcps, + 2, + pbuffer + 12); + *(pbuffer + 14) = + pdata->range_config__valid_phase_low; + *(pbuffer + 15) = + pdata->range_config__valid_phase_high; + VL53L1_i2c_encode_uint32_t( + pdata->system__intermeasurement_period, + 4, + pbuffer + 18); + *(pbuffer + 22) = + pdata->system__fractional_enable & 0x1; + LOG_FUNCTION_END(status); + + + return status; +} + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_decode_timing_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_timing_config_t *pdata) +{ + /** + * Decodes data structure VL53L1_timing_config_t from the input I2C read buffer + * Buffer must be at least 23 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_TIMING_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->mm_config__timeout_macrop_a_hi = + (*(pbuffer + 0)) & 0xF; + pdata->mm_config__timeout_macrop_a_lo = + (*(pbuffer + 1)); + pdata->mm_config__timeout_macrop_b_hi = + (*(pbuffer + 2)) & 0xF; + pdata->mm_config__timeout_macrop_b_lo = + (*(pbuffer + 3)); + pdata->range_config__timeout_macrop_a_hi = + (*(pbuffer + 4)) & 0xF; + pdata->range_config__timeout_macrop_a_lo = + (*(pbuffer + 5)); + pdata->range_config__vcsel_period_a = + (*(pbuffer + 6)) & 0x3F; + pdata->range_config__timeout_macrop_b_hi = + (*(pbuffer + 7)) & 0xF; + pdata->range_config__timeout_macrop_b_lo = + (*(pbuffer + 8)); + pdata->range_config__vcsel_period_b = + (*(pbuffer + 9)) & 0x3F; + pdata->range_config__sigma_thresh = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 10)); + pdata->range_config__min_count_rate_rtn_limit_mcps = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 12)); + pdata->range_config__valid_phase_low = + (*(pbuffer + 14)); + pdata->range_config__valid_phase_high = + (*(pbuffer + 15)); + pdata->system__intermeasurement_period = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 18)); + pdata->system__fractional_enable = + (*(pbuffer + 22)) & 0x1; + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_set_timing_config( + VL53L1_DEV Dev, + VL53L1_timing_config_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_timing_config_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_TIMING_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_timing_config( + pdata, + VL53L1_TIMING_CONFIG_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_MM_CONFIG__TIMEOUT_MACROP_A_HI, + comms_buffer, + VL53L1_TIMING_CONFIG_I2C_SIZE_BYTES); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_timing_config( + VL53L1_DEV Dev, + VL53L1_timing_config_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_timing_config_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_TIMING_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_ReadMulti( + Dev, + VL53L1_MM_CONFIG__TIMEOUT_MACROP_A_HI, + comms_buffer, + VL53L1_TIMING_CONFIG_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_timing_config( + VL53L1_TIMING_CONFIG_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_i2c_encode_dynamic_config( + VL53L1_dynamic_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_dynamic_config_t into a I2C write buffer + * Buffer must be at least 18 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_DYNAMIC_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->system__grouped_parameter_hold_0 & 0x3; + VL53L1_i2c_encode_uint16_t( + pdata->system__thresh_high, + 2, + pbuffer + 1); + VL53L1_i2c_encode_uint16_t( + pdata->system__thresh_low, + 2, + pbuffer + 3); + *(pbuffer + 5) = + pdata->system__enable_xtalk_per_quadrant & 0x1; + *(pbuffer + 6) = + pdata->system__seed_config & 0x7; + *(pbuffer + 7) = + pdata->sd_config__woi_sd0; + *(pbuffer + 8) = + pdata->sd_config__woi_sd1; + *(pbuffer + 9) = + pdata->sd_config__initial_phase_sd0 & 0x7F; + *(pbuffer + 10) = + pdata->sd_config__initial_phase_sd1 & 0x7F; + *(pbuffer + 11) = + pdata->system__grouped_parameter_hold_1 & 0x3; + *(pbuffer + 12) = + pdata->sd_config__first_order_select & 0x3; + *(pbuffer + 13) = + pdata->sd_config__quantifier & 0xF; + *(pbuffer + 14) = + pdata->roi_config__user_roi_centre_spad; + *(pbuffer + 15) = + pdata->roi_config__user_roi_requested_global_xy_size; + *(pbuffer + 16) = + pdata->system__sequence_config; + *(pbuffer + 17) = + pdata->system__grouped_parameter_hold & 0x3; + LOG_FUNCTION_END(status); + + + return status; +} + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_decode_dynamic_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_dynamic_config_t *pdata) +{ + /** + * Decodes data structure VL53L1_dynamic_config_t from the input I2C read buffer + * Buffer must be at least 18 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_DYNAMIC_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->system__grouped_parameter_hold_0 = + (*(pbuffer + 0)) & 0x3; + pdata->system__thresh_high = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 1)); + pdata->system__thresh_low = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 3)); + pdata->system__enable_xtalk_per_quadrant = + (*(pbuffer + 5)) & 0x1; + pdata->system__seed_config = + (*(pbuffer + 6)) & 0x7; + pdata->sd_config__woi_sd0 = + (*(pbuffer + 7)); + pdata->sd_config__woi_sd1 = + (*(pbuffer + 8)); + pdata->sd_config__initial_phase_sd0 = + (*(pbuffer + 9)) & 0x7F; + pdata->sd_config__initial_phase_sd1 = + (*(pbuffer + 10)) & 0x7F; + pdata->system__grouped_parameter_hold_1 = + (*(pbuffer + 11)) & 0x3; + pdata->sd_config__first_order_select = + (*(pbuffer + 12)) & 0x3; + pdata->sd_config__quantifier = + (*(pbuffer + 13)) & 0xF; + pdata->roi_config__user_roi_centre_spad = + (*(pbuffer + 14)); + pdata->roi_config__user_roi_requested_global_xy_size = + (*(pbuffer + 15)); + pdata->system__sequence_config = + (*(pbuffer + 16)); + pdata->system__grouped_parameter_hold = + (*(pbuffer + 17)) & 0x3; + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_set_dynamic_config( + VL53L1_DEV Dev, + VL53L1_dynamic_config_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_dynamic_config_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_DYNAMIC_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_dynamic_config( + pdata, + VL53L1_DYNAMIC_CONFIG_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_SYSTEM__GROUPED_PARAMETER_HOLD_0, + comms_buffer, + VL53L1_DYNAMIC_CONFIG_I2C_SIZE_BYTES); + + LOG_FUNCTION_END(status); + + return status; +} + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_dynamic_config( + VL53L1_DEV Dev, + VL53L1_dynamic_config_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_dynamic_config_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_DYNAMIC_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_ReadMulti( + Dev, + VL53L1_SYSTEM__GROUPED_PARAMETER_HOLD_0, + comms_buffer, + VL53L1_DYNAMIC_CONFIG_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_dynamic_config( + VL53L1_DYNAMIC_CONFIG_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_i2c_encode_system_control( + VL53L1_system_control_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_system_control_t into a I2C write buffer + * Buffer must be at least 5 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_SYSTEM_CONTROL_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->power_management__go1_power_force & 0x1; + *(pbuffer + 1) = + pdata->system__stream_count_ctrl & 0x1; + *(pbuffer + 2) = + pdata->firmware__enable & 0x1; + *(pbuffer + 3) = + pdata->system__interrupt_clear & 0x3; + *(pbuffer + 4) = + pdata->system__mode_start; + LOG_FUNCTION_END(status); + + + return status; +} + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_decode_system_control( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_system_control_t *pdata) +{ + /** + * Decodes data structure VL53L1_system_control_t from the input I2C read buffer + * Buffer must be at least 5 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_SYSTEM_CONTROL_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->power_management__go1_power_force = + (*(pbuffer + 0)) & 0x1; + pdata->system__stream_count_ctrl = + (*(pbuffer + 1)) & 0x1; + pdata->firmware__enable = + (*(pbuffer + 2)) & 0x1; + pdata->system__interrupt_clear = + (*(pbuffer + 3)) & 0x3; + pdata->system__mode_start = + (*(pbuffer + 4)); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_set_system_control( + VL53L1_DEV Dev, + VL53L1_system_control_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_system_control_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_SYSTEM_CONTROL_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_system_control( + pdata, + VL53L1_SYSTEM_CONTROL_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_POWER_MANAGEMENT__GO1_POWER_FORCE, + comms_buffer, + VL53L1_SYSTEM_CONTROL_I2C_SIZE_BYTES); + + LOG_FUNCTION_END(status); + + return status; +} + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_get_system_control( + VL53L1_DEV Dev, + VL53L1_system_control_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_system_control_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_SYSTEM_CONTROL_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_ReadMulti( + Dev, + VL53L1_POWER_MANAGEMENT__GO1_POWER_FORCE, + comms_buffer, + VL53L1_SYSTEM_CONTROL_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_system_control( + VL53L1_SYSTEM_CONTROL_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_encode_system_results( + VL53L1_system_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_system_results_t into a I2C write buffer + * Buffer must be at least 44 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_SYSTEM_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->result__interrupt_status & 0x3F; + *(pbuffer + 1) = + pdata->result__range_status; + *(pbuffer + 2) = + pdata->result__report_status & 0xF; + *(pbuffer + 3) = + pdata->result__stream_count; + VL53L1_i2c_encode_uint16_t( + pdata->result__dss_actual_effective_spads_sd0, + 2, + pbuffer + 4); + VL53L1_i2c_encode_uint16_t( + pdata->result__peak_signal_count_rate_mcps_sd0, + 2, + pbuffer + 6); + VL53L1_i2c_encode_uint16_t( + pdata->result__ambient_count_rate_mcps_sd0, + 2, + pbuffer + 8); + VL53L1_i2c_encode_uint16_t( + pdata->result__sigma_sd0, + 2, + pbuffer + 10); + VL53L1_i2c_encode_uint16_t( + pdata->result__phase_sd0, + 2, + pbuffer + 12); + VL53L1_i2c_encode_uint16_t( + pdata->result__final_crosstalk_corrected_range_mm_sd0, + 2, + pbuffer + 14); + VL53L1_i2c_encode_uint16_t( + pdata->result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0, + 2, + pbuffer + 16); + VL53L1_i2c_encode_uint16_t( + pdata->result__mm_inner_actual_effective_spads_sd0, + 2, + pbuffer + 18); + VL53L1_i2c_encode_uint16_t( + pdata->result__mm_outer_actual_effective_spads_sd0, + 2, + pbuffer + 20); + VL53L1_i2c_encode_uint16_t( + pdata->result__avg_signal_count_rate_mcps_sd0, + 2, + pbuffer + 22); + VL53L1_i2c_encode_uint16_t( + pdata->result__dss_actual_effective_spads_sd1, + 2, + pbuffer + 24); + VL53L1_i2c_encode_uint16_t( + pdata->result__peak_signal_count_rate_mcps_sd1, + 2, + pbuffer + 26); + VL53L1_i2c_encode_uint16_t( + pdata->result__ambient_count_rate_mcps_sd1, + 2, + pbuffer + 28); + VL53L1_i2c_encode_uint16_t( + pdata->result__sigma_sd1, + 2, + pbuffer + 30); + VL53L1_i2c_encode_uint16_t( + pdata->result__phase_sd1, + 2, + pbuffer + 32); + VL53L1_i2c_encode_uint16_t( + pdata->result__final_crosstalk_corrected_range_mm_sd1, + 2, + pbuffer + 34); + VL53L1_i2c_encode_uint16_t( + pdata->result__spare_0_sd1, + 2, + pbuffer + 36); + VL53L1_i2c_encode_uint16_t( + pdata->result__spare_1_sd1, + 2, + pbuffer + 38); + VL53L1_i2c_encode_uint16_t( + pdata->result__spare_2_sd1, + 2, + pbuffer + 40); + *(pbuffer + 42) = + pdata->result__spare_3_sd1; + *(pbuffer + 43) = + pdata->result__thresh_info; + LOG_FUNCTION_END(status); + + + return status; +} +#endif + + +VL53L1_Error VL53L1_i2c_decode_system_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_system_results_t *pdata) +{ + /** + * Decodes data structure VL53L1_system_results_t from the input I2C read buffer + * Buffer must be at least 44 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_SYSTEM_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->result__interrupt_status = + (*(pbuffer + 0)) & 0x3F; + pdata->result__range_status = + (*(pbuffer + 1)); + pdata->result__report_status = + (*(pbuffer + 2)) & 0xF; + pdata->result__stream_count = + (*(pbuffer + 3)); + pdata->result__dss_actual_effective_spads_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 4)); + pdata->result__peak_signal_count_rate_mcps_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 6)); + pdata->result__ambient_count_rate_mcps_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 8)); + pdata->result__sigma_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 10)); + pdata->result__phase_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 12)); + pdata->result__final_crosstalk_corrected_range_mm_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 14)); + pdata->result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 16)); + pdata->result__mm_inner_actual_effective_spads_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 18)); + pdata->result__mm_outer_actual_effective_spads_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 20)); + pdata->result__avg_signal_count_rate_mcps_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 22)); + pdata->result__dss_actual_effective_spads_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 24)); + pdata->result__peak_signal_count_rate_mcps_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 26)); + pdata->result__ambient_count_rate_mcps_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 28)); + pdata->result__sigma_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 30)); + pdata->result__phase_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 32)); + pdata->result__final_crosstalk_corrected_range_mm_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 34)); + pdata->result__spare_0_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 36)); + pdata->result__spare_1_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 38)); + pdata->result__spare_2_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 40)); + pdata->result__spare_3_sd1 = + (*(pbuffer + 42)); + pdata->result__thresh_info = + (*(pbuffer + 43)); + + LOG_FUNCTION_END(status); + + return status; +} + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_set_system_results( + VL53L1_DEV Dev, + VL53L1_system_results_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_system_results_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_SYSTEM_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_system_results( + pdata, + VL53L1_SYSTEM_RESULTS_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_RESULT__INTERRUPT_STATUS, + comms_buffer, + VL53L1_SYSTEM_RESULTS_I2C_SIZE_BYTES); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_get_system_results( + VL53L1_DEV Dev, + VL53L1_system_results_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_system_results_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_SYSTEM_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_ReadMulti( + Dev, + VL53L1_RESULT__INTERRUPT_STATUS, + comms_buffer, + VL53L1_SYSTEM_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_system_results( + VL53L1_SYSTEM_RESULTS_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_encode_core_results( + VL53L1_core_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_core_results_t into a I2C write buffer + * Buffer must be at least 33 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_CORE_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + VL53L1_i2c_encode_uint32_t( + pdata->result_core__ambient_window_events_sd0, + 4, + pbuffer + 0); + VL53L1_i2c_encode_uint32_t( + pdata->result_core__ranging_total_events_sd0, + 4, + pbuffer + 4); + VL53L1_i2c_encode_int32_t( + pdata->result_core__signal_total_events_sd0, + 4, + pbuffer + 8); + VL53L1_i2c_encode_uint32_t( + pdata->result_core__total_periods_elapsed_sd0, + 4, + pbuffer + 12); + VL53L1_i2c_encode_uint32_t( + pdata->result_core__ambient_window_events_sd1, + 4, + pbuffer + 16); + VL53L1_i2c_encode_uint32_t( + pdata->result_core__ranging_total_events_sd1, + 4, + pbuffer + 20); + VL53L1_i2c_encode_int32_t( + pdata->result_core__signal_total_events_sd1, + 4, + pbuffer + 24); + VL53L1_i2c_encode_uint32_t( + pdata->result_core__total_periods_elapsed_sd1, + 4, + pbuffer + 28); + *(pbuffer + 32) = + pdata->result_core__spare_0; + LOG_FUNCTION_END(status); + + + return status; +} +#endif + + +VL53L1_Error VL53L1_i2c_decode_core_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_core_results_t *pdata) +{ + /** + * Decodes data structure VL53L1_core_results_t from the input I2C read buffer + * Buffer must be at least 33 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_CORE_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->result_core__ambient_window_events_sd0 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 0)); + pdata->result_core__ranging_total_events_sd0 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 4)); + pdata->result_core__signal_total_events_sd0 = + (VL53L1_i2c_decode_int32_t(4, pbuffer + 8)); + pdata->result_core__total_periods_elapsed_sd0 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 12)); + pdata->result_core__ambient_window_events_sd1 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 16)); + pdata->result_core__ranging_total_events_sd1 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 20)); + pdata->result_core__signal_total_events_sd1 = + (VL53L1_i2c_decode_int32_t(4, pbuffer + 24)); + pdata->result_core__total_periods_elapsed_sd1 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 28)); + pdata->result_core__spare_0 = + (*(pbuffer + 32)); + + LOG_FUNCTION_END(status); + + return status; +} + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_set_core_results( + VL53L1_DEV Dev, + VL53L1_core_results_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_core_results_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_CORE_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_core_results( + pdata, + VL53L1_CORE_RESULTS_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0, + comms_buffer, + VL53L1_CORE_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_get_core_results( + VL53L1_DEV Dev, + VL53L1_core_results_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_core_results_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_CORE_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_ReadMulti( + Dev, + VL53L1_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0, + comms_buffer, + VL53L1_CORE_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_core_results( + VL53L1_CORE_RESULTS_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_i2c_encode_debug_results( + VL53L1_debug_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_debug_results_t into a I2C write buffer + * Buffer must be at least 56 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_DEBUG_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + VL53L1_i2c_encode_uint16_t( + pdata->phasecal_result__reference_phase, + 2, + pbuffer + 0); + *(pbuffer + 2) = + pdata->phasecal_result__vcsel_start & 0x7F; + *(pbuffer + 3) = + pdata->ref_spad_char_result__num_actual_ref_spads & 0x3F; + *(pbuffer + 4) = + pdata->ref_spad_char_result__ref_location & 0x3; + *(pbuffer + 5) = + pdata->vhv_result__coldboot_status & 0x1; + *(pbuffer + 6) = + pdata->vhv_result__search_result & 0x3F; + *(pbuffer + 7) = + pdata->vhv_result__latest_setting & 0x3F; + VL53L1_i2c_encode_uint16_t( + pdata->result__osc_calibrate_val & 0x3FF, + 2, + pbuffer + 8); + *(pbuffer + 10) = + pdata->ana_config__powerdown_go1 & 0x3; + *(pbuffer + 11) = + pdata->ana_config__ref_bg_ctrl & 0x3; + *(pbuffer + 12) = + pdata->ana_config__regdvdd1v2_ctrl & 0xF; + *(pbuffer + 13) = + pdata->ana_config__osc_slow_ctrl & 0x7; + *(pbuffer + 14) = + pdata->test_mode__status & 0x1; + *(pbuffer + 15) = + pdata->firmware__system_status & 0x3; + *(pbuffer + 16) = + pdata->firmware__mode_status; + *(pbuffer + 17) = + pdata->firmware__secondary_mode_status; + VL53L1_i2c_encode_uint16_t( + pdata->firmware__cal_repeat_rate_counter & 0xFFF, + 2, + pbuffer + 18); + VL53L1_i2c_encode_uint16_t( + pdata->gph__system__thresh_high, + 2, + pbuffer + 22); + VL53L1_i2c_encode_uint16_t( + pdata->gph__system__thresh_low, + 2, + pbuffer + 24); + *(pbuffer + 26) = + pdata->gph__system__enable_xtalk_per_quadrant & 0x1; + *(pbuffer + 27) = + pdata->gph__spare_0 & 0x7; + *(pbuffer + 28) = + pdata->gph__sd_config__woi_sd0; + *(pbuffer + 29) = + pdata->gph__sd_config__woi_sd1; + *(pbuffer + 30) = + pdata->gph__sd_config__initial_phase_sd0 & 0x7F; + *(pbuffer + 31) = + pdata->gph__sd_config__initial_phase_sd1 & 0x7F; + *(pbuffer + 32) = + pdata->gph__sd_config__first_order_select & 0x3; + *(pbuffer + 33) = + pdata->gph__sd_config__quantifier & 0xF; + *(pbuffer + 34) = + pdata->gph__roi_config__user_roi_centre_spad; + *(pbuffer + 35) = + pdata->gph__roi_config__user_roi_requested_global_xy_size; + *(pbuffer + 36) = + pdata->gph__system__sequence_config; + *(pbuffer + 37) = + pdata->gph__gph_id & 0x1; + *(pbuffer + 38) = + pdata->system__interrupt_set & 0x3; + *(pbuffer + 39) = + pdata->interrupt_manager__enables & 0x1F; + *(pbuffer + 40) = + pdata->interrupt_manager__clear & 0x1F; + *(pbuffer + 41) = + pdata->interrupt_manager__status & 0x1F; + *(pbuffer + 42) = + pdata->mcu_to_host_bank__wr_access_en & 0x1; + *(pbuffer + 43) = + pdata->power_management__go1_reset_status & 0x1; + *(pbuffer + 44) = + pdata->pad_startup_mode__value_ro & 0x3; + *(pbuffer + 45) = + pdata->pad_startup_mode__value_ctrl & 0x3F; + VL53L1_i2c_encode_uint32_t( + pdata->pll_period_us & 0x3FFFF, + 4, + pbuffer + 46); + VL53L1_i2c_encode_uint32_t( + pdata->interrupt_scheduler__data_out, + 4, + pbuffer + 50); + *(pbuffer + 54) = + pdata->nvm_bist__complete & 0x1; + *(pbuffer + 55) = + pdata->nvm_bist__status & 0x1; + LOG_FUNCTION_END(status); + + + return status; +} +#endif + + +VL53L1_Error VL53L1_i2c_decode_debug_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_debug_results_t *pdata) +{ + /** + * Decodes data structure VL53L1_debug_results_t from the input I2C read buffer + * Buffer must be at least 56 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_DEBUG_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->phasecal_result__reference_phase = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 0)); + pdata->phasecal_result__vcsel_start = + (*(pbuffer + 2)) & 0x7F; + pdata->ref_spad_char_result__num_actual_ref_spads = + (*(pbuffer + 3)) & 0x3F; + pdata->ref_spad_char_result__ref_location = + (*(pbuffer + 4)) & 0x3; + pdata->vhv_result__coldboot_status = + (*(pbuffer + 5)) & 0x1; + pdata->vhv_result__search_result = + (*(pbuffer + 6)) & 0x3F; + pdata->vhv_result__latest_setting = + (*(pbuffer + 7)) & 0x3F; + pdata->result__osc_calibrate_val = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 8)) & 0x3FF; + pdata->ana_config__powerdown_go1 = + (*(pbuffer + 10)) & 0x3; + pdata->ana_config__ref_bg_ctrl = + (*(pbuffer + 11)) & 0x3; + pdata->ana_config__regdvdd1v2_ctrl = + (*(pbuffer + 12)) & 0xF; + pdata->ana_config__osc_slow_ctrl = + (*(pbuffer + 13)) & 0x7; + pdata->test_mode__status = + (*(pbuffer + 14)) & 0x1; + pdata->firmware__system_status = + (*(pbuffer + 15)) & 0x3; + pdata->firmware__mode_status = + (*(pbuffer + 16)); + pdata->firmware__secondary_mode_status = + (*(pbuffer + 17)); + pdata->firmware__cal_repeat_rate_counter = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 18)) & 0xFFF; + pdata->gph__system__thresh_high = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 22)); + pdata->gph__system__thresh_low = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 24)); + pdata->gph__system__enable_xtalk_per_quadrant = + (*(pbuffer + 26)) & 0x1; + pdata->gph__spare_0 = + (*(pbuffer + 27)) & 0x7; + pdata->gph__sd_config__woi_sd0 = + (*(pbuffer + 28)); + pdata->gph__sd_config__woi_sd1 = + (*(pbuffer + 29)); + pdata->gph__sd_config__initial_phase_sd0 = + (*(pbuffer + 30)) & 0x7F; + pdata->gph__sd_config__initial_phase_sd1 = + (*(pbuffer + 31)) & 0x7F; + pdata->gph__sd_config__first_order_select = + (*(pbuffer + 32)) & 0x3; + pdata->gph__sd_config__quantifier = + (*(pbuffer + 33)) & 0xF; + pdata->gph__roi_config__user_roi_centre_spad = + (*(pbuffer + 34)); + pdata->gph__roi_config__user_roi_requested_global_xy_size = + (*(pbuffer + 35)); + pdata->gph__system__sequence_config = + (*(pbuffer + 36)); + pdata->gph__gph_id = + (*(pbuffer + 37)) & 0x1; + pdata->system__interrupt_set = + (*(pbuffer + 38)) & 0x3; + pdata->interrupt_manager__enables = + (*(pbuffer + 39)) & 0x1F; + pdata->interrupt_manager__clear = + (*(pbuffer + 40)) & 0x1F; + pdata->interrupt_manager__status = + (*(pbuffer + 41)) & 0x1F; + pdata->mcu_to_host_bank__wr_access_en = + (*(pbuffer + 42)) & 0x1; + pdata->power_management__go1_reset_status = + (*(pbuffer + 43)) & 0x1; + pdata->pad_startup_mode__value_ro = + (*(pbuffer + 44)) & 0x3; + pdata->pad_startup_mode__value_ctrl = + (*(pbuffer + 45)) & 0x3F; + pdata->pll_period_us = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 46)) & 0x3FFFF; + pdata->interrupt_scheduler__data_out = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 50)); + pdata->nvm_bist__complete = + (*(pbuffer + 54)) & 0x1; + pdata->nvm_bist__status = + (*(pbuffer + 55)) & 0x1; + + LOG_FUNCTION_END(status); + + return status; +} + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_set_debug_results( + VL53L1_DEV Dev, + VL53L1_debug_results_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_debug_results_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_DEBUG_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_debug_results( + pdata, + VL53L1_DEBUG_RESULTS_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_PHASECAL_RESULT__REFERENCE_PHASE, + comms_buffer, + VL53L1_DEBUG_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_debug_results( + VL53L1_DEV Dev, + VL53L1_debug_results_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_debug_results_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_DEBUG_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_ReadMulti( + Dev, + VL53L1_PHASECAL_RESULT__REFERENCE_PHASE, + comms_buffer, + VL53L1_DEBUG_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_debug_results( + VL53L1_DEBUG_RESULTS_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_encode_nvm_copy_data( + VL53L1_nvm_copy_data_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_nvm_copy_data_t into a I2C write buffer + * Buffer must be at least 49 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_NVM_COPY_DATA_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->identification__model_id; + *(pbuffer + 1) = + pdata->identification__module_type; + *(pbuffer + 2) = + pdata->identification__revision_id; + VL53L1_i2c_encode_uint16_t( + pdata->identification__module_id, + 2, + pbuffer + 3); + *(pbuffer + 5) = + pdata->ana_config__fast_osc__trim_max & 0x7F; + *(pbuffer + 6) = + pdata->ana_config__fast_osc__freq_set & 0x7; + *(pbuffer + 7) = + pdata->ana_config__vcsel_trim & 0x7; + *(pbuffer + 8) = + pdata->ana_config__vcsel_selion & 0x3F; + *(pbuffer + 9) = + pdata->ana_config__vcsel_selion_max & 0x3F; + *(pbuffer + 10) = + pdata->protected_laser_safety__lock_bit & 0x1; + *(pbuffer + 11) = + pdata->laser_safety__key & 0x7F; + *(pbuffer + 12) = + pdata->laser_safety__key_ro & 0x1; + *(pbuffer + 13) = + pdata->laser_safety__clip & 0x3F; + *(pbuffer + 14) = + pdata->laser_safety__mult & 0x3F; + *(pbuffer + 15) = + pdata->global_config__spad_enables_rtn_0; + *(pbuffer + 16) = + pdata->global_config__spad_enables_rtn_1; + *(pbuffer + 17) = + pdata->global_config__spad_enables_rtn_2; + *(pbuffer + 18) = + pdata->global_config__spad_enables_rtn_3; + *(pbuffer + 19) = + pdata->global_config__spad_enables_rtn_4; + *(pbuffer + 20) = + pdata->global_config__spad_enables_rtn_5; + *(pbuffer + 21) = + pdata->global_config__spad_enables_rtn_6; + *(pbuffer + 22) = + pdata->global_config__spad_enables_rtn_7; + *(pbuffer + 23) = + pdata->global_config__spad_enables_rtn_8; + *(pbuffer + 24) = + pdata->global_config__spad_enables_rtn_9; + *(pbuffer + 25) = + pdata->global_config__spad_enables_rtn_10; + *(pbuffer + 26) = + pdata->global_config__spad_enables_rtn_11; + *(pbuffer + 27) = + pdata->global_config__spad_enables_rtn_12; + *(pbuffer + 28) = + pdata->global_config__spad_enables_rtn_13; + *(pbuffer + 29) = + pdata->global_config__spad_enables_rtn_14; + *(pbuffer + 30) = + pdata->global_config__spad_enables_rtn_15; + *(pbuffer + 31) = + pdata->global_config__spad_enables_rtn_16; + *(pbuffer + 32) = + pdata->global_config__spad_enables_rtn_17; + *(pbuffer + 33) = + pdata->global_config__spad_enables_rtn_18; + *(pbuffer + 34) = + pdata->global_config__spad_enables_rtn_19; + *(pbuffer + 35) = + pdata->global_config__spad_enables_rtn_20; + *(pbuffer + 36) = + pdata->global_config__spad_enables_rtn_21; + *(pbuffer + 37) = + pdata->global_config__spad_enables_rtn_22; + *(pbuffer + 38) = + pdata->global_config__spad_enables_rtn_23; + *(pbuffer + 39) = + pdata->global_config__spad_enables_rtn_24; + *(pbuffer + 40) = + pdata->global_config__spad_enables_rtn_25; + *(pbuffer + 41) = + pdata->global_config__spad_enables_rtn_26; + *(pbuffer + 42) = + pdata->global_config__spad_enables_rtn_27; + *(pbuffer + 43) = + pdata->global_config__spad_enables_rtn_28; + *(pbuffer + 44) = + pdata->global_config__spad_enables_rtn_29; + *(pbuffer + 45) = + pdata->global_config__spad_enables_rtn_30; + *(pbuffer + 46) = + pdata->global_config__spad_enables_rtn_31; + *(pbuffer + 47) = + pdata->roi_config__mode_roi_centre_spad; + *(pbuffer + 48) = + pdata->roi_config__mode_roi_xy_size; + LOG_FUNCTION_END(status); + + + return status; +} +#endif + + +VL53L1_Error VL53L1_i2c_decode_nvm_copy_data( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_nvm_copy_data_t *pdata) +{ + /** + * Decodes data structure VL53L1_nvm_copy_data_t from the input I2C read buffer + * Buffer must be at least 49 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_NVM_COPY_DATA_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->identification__model_id = + (*(pbuffer + 0)); + pdata->identification__module_type = + (*(pbuffer + 1)); + pdata->identification__revision_id = + (*(pbuffer + 2)); + pdata->identification__module_id = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 3)); + pdata->ana_config__fast_osc__trim_max = + (*(pbuffer + 5)) & 0x7F; + pdata->ana_config__fast_osc__freq_set = + (*(pbuffer + 6)) & 0x7; + pdata->ana_config__vcsel_trim = + (*(pbuffer + 7)) & 0x7; + pdata->ana_config__vcsel_selion = + (*(pbuffer + 8)) & 0x3F; + pdata->ana_config__vcsel_selion_max = + (*(pbuffer + 9)) & 0x3F; + pdata->protected_laser_safety__lock_bit = + (*(pbuffer + 10)) & 0x1; + pdata->laser_safety__key = + (*(pbuffer + 11)) & 0x7F; + pdata->laser_safety__key_ro = + (*(pbuffer + 12)) & 0x1; + pdata->laser_safety__clip = + (*(pbuffer + 13)) & 0x3F; + pdata->laser_safety__mult = + (*(pbuffer + 14)) & 0x3F; + pdata->global_config__spad_enables_rtn_0 = + (*(pbuffer + 15)); + pdata->global_config__spad_enables_rtn_1 = + (*(pbuffer + 16)); + pdata->global_config__spad_enables_rtn_2 = + (*(pbuffer + 17)); + pdata->global_config__spad_enables_rtn_3 = + (*(pbuffer + 18)); + pdata->global_config__spad_enables_rtn_4 = + (*(pbuffer + 19)); + pdata->global_config__spad_enables_rtn_5 = + (*(pbuffer + 20)); + pdata->global_config__spad_enables_rtn_6 = + (*(pbuffer + 21)); + pdata->global_config__spad_enables_rtn_7 = + (*(pbuffer + 22)); + pdata->global_config__spad_enables_rtn_8 = + (*(pbuffer + 23)); + pdata->global_config__spad_enables_rtn_9 = + (*(pbuffer + 24)); + pdata->global_config__spad_enables_rtn_10 = + (*(pbuffer + 25)); + pdata->global_config__spad_enables_rtn_11 = + (*(pbuffer + 26)); + pdata->global_config__spad_enables_rtn_12 = + (*(pbuffer + 27)); + pdata->global_config__spad_enables_rtn_13 = + (*(pbuffer + 28)); + pdata->global_config__spad_enables_rtn_14 = + (*(pbuffer + 29)); + pdata->global_config__spad_enables_rtn_15 = + (*(pbuffer + 30)); + pdata->global_config__spad_enables_rtn_16 = + (*(pbuffer + 31)); + pdata->global_config__spad_enables_rtn_17 = + (*(pbuffer + 32)); + pdata->global_config__spad_enables_rtn_18 = + (*(pbuffer + 33)); + pdata->global_config__spad_enables_rtn_19 = + (*(pbuffer + 34)); + pdata->global_config__spad_enables_rtn_20 = + (*(pbuffer + 35)); + pdata->global_config__spad_enables_rtn_21 = + (*(pbuffer + 36)); + pdata->global_config__spad_enables_rtn_22 = + (*(pbuffer + 37)); + pdata->global_config__spad_enables_rtn_23 = + (*(pbuffer + 38)); + pdata->global_config__spad_enables_rtn_24 = + (*(pbuffer + 39)); + pdata->global_config__spad_enables_rtn_25 = + (*(pbuffer + 40)); + pdata->global_config__spad_enables_rtn_26 = + (*(pbuffer + 41)); + pdata->global_config__spad_enables_rtn_27 = + (*(pbuffer + 42)); + pdata->global_config__spad_enables_rtn_28 = + (*(pbuffer + 43)); + pdata->global_config__spad_enables_rtn_29 = + (*(pbuffer + 44)); + pdata->global_config__spad_enables_rtn_30 = + (*(pbuffer + 45)); + pdata->global_config__spad_enables_rtn_31 = + (*(pbuffer + 46)); + pdata->roi_config__mode_roi_centre_spad = + (*(pbuffer + 47)); + pdata->roi_config__mode_roi_xy_size = + (*(pbuffer + 48)); + + LOG_FUNCTION_END(status); + + return status; +} + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_set_nvm_copy_data( + VL53L1_DEV Dev, + VL53L1_nvm_copy_data_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_nvm_copy_data_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_NVM_COPY_DATA_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_nvm_copy_data( + pdata, + VL53L1_NVM_COPY_DATA_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_IDENTIFICATION__MODEL_ID, + comms_buffer, + VL53L1_NVM_COPY_DATA_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +VL53L1_Error VL53L1_get_nvm_copy_data( + VL53L1_DEV Dev, + VL53L1_nvm_copy_data_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_nvm_copy_data_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_NVM_COPY_DATA_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_ReadMulti( + Dev, + VL53L1_IDENTIFICATION__MODEL_ID, + comms_buffer, + VL53L1_NVM_COPY_DATA_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_nvm_copy_data( + VL53L1_NVM_COPY_DATA_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_i2c_encode_prev_shadow_system_results( + VL53L1_prev_shadow_system_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_prev_shadow_system_results_t into a I2C write buffer + * Buffer must be at least 44 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_PREV_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->prev_shadow_result__interrupt_status & 0x3F; + *(pbuffer + 1) = + pdata->prev_shadow_result__range_status; + *(pbuffer + 2) = + pdata->prev_shadow_result__report_status & 0xF; + *(pbuffer + 3) = + pdata->prev_shadow_result__stream_count; + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__dss_actual_effective_spads_sd0, + 2, + pbuffer + 4); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__peak_signal_count_rate_mcps_sd0, + 2, + pbuffer + 6); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__ambient_count_rate_mcps_sd0, + 2, + pbuffer + 8); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__sigma_sd0, + 2, + pbuffer + 10); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__phase_sd0, + 2, + pbuffer + 12); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__final_crosstalk_corrected_range_mm_sd0, + 2, + pbuffer + 14); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0, + 2, + pbuffer + 16); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__mm_inner_actual_effective_spads_sd0, + 2, + pbuffer + 18); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__mm_outer_actual_effective_spads_sd0, + 2, + pbuffer + 20); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__avg_signal_count_rate_mcps_sd0, + 2, + pbuffer + 22); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__dss_actual_effective_spads_sd1, + 2, + pbuffer + 24); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__peak_signal_count_rate_mcps_sd1, + 2, + pbuffer + 26); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__ambient_count_rate_mcps_sd1, + 2, + pbuffer + 28); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__sigma_sd1, + 2, + pbuffer + 30); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__phase_sd1, + 2, + pbuffer + 32); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__final_crosstalk_corrected_range_mm_sd1, + 2, + pbuffer + 34); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__spare_0_sd1, + 2, + pbuffer + 36); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__spare_1_sd1, + 2, + pbuffer + 38); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__spare_2_sd1, + 2, + pbuffer + 40); + VL53L1_i2c_encode_uint16_t( + pdata->prev_shadow_result__spare_3_sd1, + 2, + pbuffer + 42); + LOG_FUNCTION_END(status); + + + return status; +} + + +VL53L1_Error VL53L1_i2c_decode_prev_shadow_system_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_prev_shadow_system_results_t *pdata) +{ + /** + * Decodes data structure VL53L1_prev_shadow_system_results_t from the input I2C read buffer + * Buffer must be at least 44 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_PREV_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->prev_shadow_result__interrupt_status = + (*(pbuffer + 0)) & 0x3F; + pdata->prev_shadow_result__range_status = + (*(pbuffer + 1)); + pdata->prev_shadow_result__report_status = + (*(pbuffer + 2)) & 0xF; + pdata->prev_shadow_result__stream_count = + (*(pbuffer + 3)); + pdata->prev_shadow_result__dss_actual_effective_spads_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 4)); + pdata->prev_shadow_result__peak_signal_count_rate_mcps_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 6)); + pdata->prev_shadow_result__ambient_count_rate_mcps_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 8)); + pdata->prev_shadow_result__sigma_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 10)); + pdata->prev_shadow_result__phase_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 12)); + pdata->prev_shadow_result__final_crosstalk_corrected_range_mm_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 14)); + pdata->prev_shadow_result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 16)); + pdata->prev_shadow_result__mm_inner_actual_effective_spads_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 18)); + pdata->prev_shadow_result__mm_outer_actual_effective_spads_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 20)); + pdata->prev_shadow_result__avg_signal_count_rate_mcps_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 22)); + pdata->prev_shadow_result__dss_actual_effective_spads_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 24)); + pdata->prev_shadow_result__peak_signal_count_rate_mcps_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 26)); + pdata->prev_shadow_result__ambient_count_rate_mcps_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 28)); + pdata->prev_shadow_result__sigma_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 30)); + pdata->prev_shadow_result__phase_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 32)); + pdata->prev_shadow_result__final_crosstalk_corrected_range_mm_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 34)); + pdata->prev_shadow_result__spare_0_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 36)); + pdata->prev_shadow_result__spare_1_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 38)); + pdata->prev_shadow_result__spare_2_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 40)); + pdata->prev_shadow_result__spare_3_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 42)); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_prev_shadow_system_results( + VL53L1_DEV Dev, + VL53L1_prev_shadow_system_results_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_prev_shadow_system_results_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_PREV_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_prev_shadow_system_results( + pdata, + VL53L1_PREV_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_PREV_SHADOW_RESULT__INTERRUPT_STATUS, + comms_buffer, + VL53L1_PREV_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_prev_shadow_system_results( + VL53L1_DEV Dev, + VL53L1_prev_shadow_system_results_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_prev_shadow_system_results_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_PREV_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_ReadMulti( + Dev, + VL53L1_PREV_SHADOW_RESULT__INTERRUPT_STATUS, + comms_buffer, + VL53L1_PREV_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_prev_shadow_system_results( + VL53L1_PREV_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_i2c_encode_prev_shadow_core_results( + VL53L1_prev_shadow_core_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_prev_shadow_core_results_t into a I2C write buffer + * Buffer must be at least 33 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_PREV_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + VL53L1_i2c_encode_uint32_t( + pdata->prev_shadow_result_core__ambient_window_events_sd0, + 4, + pbuffer + 0); + VL53L1_i2c_encode_uint32_t( + pdata->prev_shadow_result_core__ranging_total_events_sd0, + 4, + pbuffer + 4); + VL53L1_i2c_encode_int32_t( + pdata->prev_shadow_result_core__signal_total_events_sd0, + 4, + pbuffer + 8); + VL53L1_i2c_encode_uint32_t( + pdata->prev_shadow_result_core__total_periods_elapsed_sd0, + 4, + pbuffer + 12); + VL53L1_i2c_encode_uint32_t( + pdata->prev_shadow_result_core__ambient_window_events_sd1, + 4, + pbuffer + 16); + VL53L1_i2c_encode_uint32_t( + pdata->prev_shadow_result_core__ranging_total_events_sd1, + 4, + pbuffer + 20); + VL53L1_i2c_encode_int32_t( + pdata->prev_shadow_result_core__signal_total_events_sd1, + 4, + pbuffer + 24); + VL53L1_i2c_encode_uint32_t( + pdata->prev_shadow_result_core__total_periods_elapsed_sd1, + 4, + pbuffer + 28); + *(pbuffer + 32) = + pdata->prev_shadow_result_core__spare_0; + LOG_FUNCTION_END(status); + + + return status; +} + + +VL53L1_Error VL53L1_i2c_decode_prev_shadow_core_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_prev_shadow_core_results_t *pdata) +{ + /** + * Decodes data structure VL53L1_prev_shadow_core_results_t from the input I2C read buffer + * Buffer must be at least 33 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_PREV_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->prev_shadow_result_core__ambient_window_events_sd0 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 0)); + pdata->prev_shadow_result_core__ranging_total_events_sd0 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 4)); + pdata->prev_shadow_result_core__signal_total_events_sd0 = + (VL53L1_i2c_decode_int32_t(4, pbuffer + 8)); + pdata->prev_shadow_result_core__total_periods_elapsed_sd0 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 12)); + pdata->prev_shadow_result_core__ambient_window_events_sd1 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 16)); + pdata->prev_shadow_result_core__ranging_total_events_sd1 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 20)); + pdata->prev_shadow_result_core__signal_total_events_sd1 = + (VL53L1_i2c_decode_int32_t(4, pbuffer + 24)); + pdata->prev_shadow_result_core__total_periods_elapsed_sd1 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 28)); + pdata->prev_shadow_result_core__spare_0 = + (*(pbuffer + 32)); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_prev_shadow_core_results( + VL53L1_DEV Dev, + VL53L1_prev_shadow_core_results_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_prev_shadow_core_results_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_PREV_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_prev_shadow_core_results( + pdata, + VL53L1_PREV_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0, + comms_buffer, + VL53L1_PREV_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_prev_shadow_core_results( + VL53L1_DEV Dev, + VL53L1_prev_shadow_core_results_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_prev_shadow_core_results_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_PREV_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_ReadMulti( + Dev, + VL53L1_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0, + comms_buffer, + VL53L1_PREV_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_prev_shadow_core_results( + VL53L1_PREV_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_i2c_encode_patch_debug( + VL53L1_patch_debug_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_patch_debug_t into a I2C write buffer + * Buffer must be at least 2 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_PATCH_DEBUG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->result__debug_status; + *(pbuffer + 1) = + pdata->result__debug_stage; + LOG_FUNCTION_END(status); + + + return status; +} + +VL53L1_Error VL53L1_i2c_decode_patch_debug( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_patch_debug_t *pdata) +{ + /** + * Decodes data structure VL53L1_patch_debug_t from the input I2C read buffer + * Buffer must be at least 2 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_PATCH_DEBUG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->result__debug_status = + (*(pbuffer + 0)); + pdata->result__debug_stage = + (*(pbuffer + 1)); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_patch_debug( + VL53L1_DEV Dev, + VL53L1_patch_debug_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_patch_debug_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_PATCH_DEBUG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_patch_debug( + pdata, + VL53L1_PATCH_DEBUG_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_RESULT__DEBUG_STATUS, + comms_buffer, + VL53L1_PATCH_DEBUG_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_patch_debug( + VL53L1_DEV Dev, + VL53L1_patch_debug_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_patch_debug_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_PATCH_DEBUG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_ReadMulti( + Dev, + VL53L1_RESULT__DEBUG_STATUS, + comms_buffer, + VL53L1_PATCH_DEBUG_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_patch_debug( + VL53L1_PATCH_DEBUG_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_encode_gph_general_config( + VL53L1_gph_general_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_gph_general_config_t into a I2C write buffer + * Buffer must be at least 5 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_GPH_GENERAL_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + VL53L1_i2c_encode_uint16_t( + pdata->gph__system__thresh_rate_high, + 2, + pbuffer + 0); + VL53L1_i2c_encode_uint16_t( + pdata->gph__system__thresh_rate_low, + 2, + pbuffer + 2); + *(pbuffer + 4) = + pdata->gph__system__interrupt_config_gpio; + LOG_FUNCTION_END(status); + + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_decode_gph_general_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_gph_general_config_t *pdata) +{ + /** + * Decodes data structure VL53L1_gph_general_config_t from the input I2C read buffer + * Buffer must be at least 5 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_GPH_GENERAL_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->gph__system__thresh_rate_high = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 0)); + pdata->gph__system__thresh_rate_low = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 2)); + pdata->gph__system__interrupt_config_gpio = + (*(pbuffer + 4)); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_set_gph_general_config( + VL53L1_DEV Dev, + VL53L1_gph_general_config_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_gph_general_config_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_GPH_GENERAL_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_gph_general_config( + pdata, + VL53L1_GPH_GENERAL_CONFIG_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_GPH__SYSTEM__THRESH_RATE_HIGH, + comms_buffer, + VL53L1_GPH_GENERAL_CONFIG_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_get_gph_general_config( + VL53L1_DEV Dev, + VL53L1_gph_general_config_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_gph_general_config_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_GPH_GENERAL_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_ReadMulti( + Dev, + VL53L1_GPH__SYSTEM__THRESH_RATE_HIGH, + comms_buffer, + VL53L1_GPH_GENERAL_CONFIG_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_gph_general_config( + VL53L1_GPH_GENERAL_CONFIG_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_encode_gph_static_config( + VL53L1_gph_static_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_gph_static_config_t into a I2C write buffer + * Buffer must be at least 6 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_GPH_STATIC_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->gph__dss_config__roi_mode_control & 0x7; + VL53L1_i2c_encode_uint16_t( + pdata->gph__dss_config__manual_effective_spads_select, + 2, + pbuffer + 1); + *(pbuffer + 3) = + pdata->gph__dss_config__manual_block_select; + *(pbuffer + 4) = + pdata->gph__dss_config__max_spads_limit; + *(pbuffer + 5) = + pdata->gph__dss_config__min_spads_limit; + LOG_FUNCTION_END(status); + + + return status; +} +#endif + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_decode_gph_static_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_gph_static_config_t *pdata) +{ + /** + * Decodes data structure VL53L1_gph_static_config_t from the input I2C read buffer + * Buffer must be at least 6 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_GPH_STATIC_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->gph__dss_config__roi_mode_control = + (*(pbuffer + 0)) & 0x7; + pdata->gph__dss_config__manual_effective_spads_select = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 1)); + pdata->gph__dss_config__manual_block_select = + (*(pbuffer + 3)); + pdata->gph__dss_config__max_spads_limit = + (*(pbuffer + 4)); + pdata->gph__dss_config__min_spads_limit = + (*(pbuffer + 5)); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_set_gph_static_config( + VL53L1_DEV Dev, + VL53L1_gph_static_config_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_gph_static_config_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_GPH_STATIC_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_gph_static_config( + pdata, + VL53L1_GPH_STATIC_CONFIG_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_GPH__DSS_CONFIG__ROI_MODE_CONTROL, + comms_buffer, + VL53L1_GPH_STATIC_CONFIG_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_get_gph_static_config( + VL53L1_DEV Dev, + VL53L1_gph_static_config_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_gph_static_config_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_GPH_STATIC_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_ReadMulti( + Dev, + VL53L1_GPH__DSS_CONFIG__ROI_MODE_CONTROL, + comms_buffer, + VL53L1_GPH_STATIC_CONFIG_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_gph_static_config( + VL53L1_GPH_STATIC_CONFIG_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_encode_gph_timing_config( + VL53L1_gph_timing_config_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_gph_timing_config_t into a I2C write buffer + * Buffer must be at least 16 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_GPH_TIMING_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->gph__mm_config__timeout_macrop_a_hi & 0xF; + *(pbuffer + 1) = + pdata->gph__mm_config__timeout_macrop_a_lo; + *(pbuffer + 2) = + pdata->gph__mm_config__timeout_macrop_b_hi & 0xF; + *(pbuffer + 3) = + pdata->gph__mm_config__timeout_macrop_b_lo; + *(pbuffer + 4) = + pdata->gph__range_config__timeout_macrop_a_hi & 0xF; + *(pbuffer + 5) = + pdata->gph__range_config__timeout_macrop_a_lo; + *(pbuffer + 6) = + pdata->gph__range_config__vcsel_period_a & 0x3F; + *(pbuffer + 7) = + pdata->gph__range_config__vcsel_period_b & 0x3F; + *(pbuffer + 8) = + pdata->gph__range_config__timeout_macrop_b_hi & 0xF; + *(pbuffer + 9) = + pdata->gph__range_config__timeout_macrop_b_lo; + VL53L1_i2c_encode_uint16_t( + pdata->gph__range_config__sigma_thresh, + 2, + pbuffer + 10); + VL53L1_i2c_encode_uint16_t( + pdata->gph__range_config__min_count_rate_rtn_limit_mcps, + 2, + pbuffer + 12); + *(pbuffer + 14) = + pdata->gph__range_config__valid_phase_low; + *(pbuffer + 15) = + pdata->gph__range_config__valid_phase_high; + LOG_FUNCTION_END(status); + + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_i2c_decode_gph_timing_config( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_gph_timing_config_t *pdata) +{ + /** + * Decodes data structure VL53L1_gph_timing_config_t from the input I2C read buffer + * Buffer must be at least 16 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_GPH_TIMING_CONFIG_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->gph__mm_config__timeout_macrop_a_hi = + (*(pbuffer + 0)) & 0xF; + pdata->gph__mm_config__timeout_macrop_a_lo = + (*(pbuffer + 1)); + pdata->gph__mm_config__timeout_macrop_b_hi = + (*(pbuffer + 2)) & 0xF; + pdata->gph__mm_config__timeout_macrop_b_lo = + (*(pbuffer + 3)); + pdata->gph__range_config__timeout_macrop_a_hi = + (*(pbuffer + 4)) & 0xF; + pdata->gph__range_config__timeout_macrop_a_lo = + (*(pbuffer + 5)); + pdata->gph__range_config__vcsel_period_a = + (*(pbuffer + 6)) & 0x3F; + pdata->gph__range_config__vcsel_period_b = + (*(pbuffer + 7)) & 0x3F; + pdata->gph__range_config__timeout_macrop_b_hi = + (*(pbuffer + 8)) & 0xF; + pdata->gph__range_config__timeout_macrop_b_lo = + (*(pbuffer + 9)); + pdata->gph__range_config__sigma_thresh = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 10)); + pdata->gph__range_config__min_count_rate_rtn_limit_mcps = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 12)); + pdata->gph__range_config__valid_phase_low = + (*(pbuffer + 14)); + pdata->gph__range_config__valid_phase_high = + (*(pbuffer + 15)); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_set_gph_timing_config( + VL53L1_DEV Dev, + VL53L1_gph_timing_config_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_gph_timing_config_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_GPH_TIMING_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_gph_timing_config( + pdata, + VL53L1_GPH_TIMING_CONFIG_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_GPH__MM_CONFIG__TIMEOUT_MACROP_A_HI, + comms_buffer, + VL53L1_GPH_TIMING_CONFIG_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef PAL_EXTENDED +VL53L1_Error VL53L1_get_gph_timing_config( + VL53L1_DEV Dev, + VL53L1_gph_timing_config_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_gph_timing_config_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_GPH_TIMING_CONFIG_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_ReadMulti( + Dev, + VL53L1_GPH__MM_CONFIG__TIMEOUT_MACROP_A_HI, + comms_buffer, + VL53L1_GPH_TIMING_CONFIG_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_gph_timing_config( + VL53L1_GPH_TIMING_CONFIG_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} +#endif + + +#ifdef VL53L1_DEBUG +VL53L1_Error VL53L1_i2c_encode_fw_internal( + VL53L1_fw_internal_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_fw_internal_t into a I2C write buffer + * Buffer must be at least 2 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_FW_INTERNAL_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->firmware__internal_stream_count_div; + *(pbuffer + 1) = + pdata->firmware__internal_stream_counter_val; + LOG_FUNCTION_END(status); + + + return status; +} + + +VL53L1_Error VL53L1_i2c_decode_fw_internal( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_fw_internal_t *pdata) +{ + /** + * Decodes data structure VL53L1_fw_internal_t from the input I2C read buffer + * Buffer must be at least 2 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_FW_INTERNAL_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->firmware__internal_stream_count_div = + (*(pbuffer + 0)); + pdata->firmware__internal_stream_counter_val = + (*(pbuffer + 1)); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_fw_internal( + VL53L1_DEV Dev, + VL53L1_fw_internal_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_fw_internal_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_FW_INTERNAL_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_fw_internal( + pdata, + VL53L1_FW_INTERNAL_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_FIRMWARE__INTERNAL_STREAM_COUNT_DIV, + comms_buffer, + VL53L1_FW_INTERNAL_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_get_fw_internal( + VL53L1_DEV Dev, + VL53L1_fw_internal_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_fw_internal_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_FW_INTERNAL_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_ReadMulti( + Dev, + VL53L1_FIRMWARE__INTERNAL_STREAM_COUNT_DIV, + comms_buffer, + VL53L1_FW_INTERNAL_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_fw_internal( + VL53L1_FW_INTERNAL_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_i2c_encode_patch_results( + VL53L1_patch_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_patch_results_t into a I2C write buffer + * Buffer must be at least 90 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_PATCH_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->dss_calc__roi_ctrl & 0x3; + *(pbuffer + 1) = + pdata->dss_calc__spare_1; + *(pbuffer + 2) = + pdata->dss_calc__spare_2; + *(pbuffer + 3) = + pdata->dss_calc__spare_3; + *(pbuffer + 4) = + pdata->dss_calc__spare_4; + *(pbuffer + 5) = + pdata->dss_calc__spare_5; + *(pbuffer + 6) = + pdata->dss_calc__spare_6; + *(pbuffer + 7) = + pdata->dss_calc__spare_7; + *(pbuffer + 8) = + pdata->dss_calc__user_roi_spad_en_0; + *(pbuffer + 9) = + pdata->dss_calc__user_roi_spad_en_1; + *(pbuffer + 10) = + pdata->dss_calc__user_roi_spad_en_2; + *(pbuffer + 11) = + pdata->dss_calc__user_roi_spad_en_3; + *(pbuffer + 12) = + pdata->dss_calc__user_roi_spad_en_4; + *(pbuffer + 13) = + pdata->dss_calc__user_roi_spad_en_5; + *(pbuffer + 14) = + pdata->dss_calc__user_roi_spad_en_6; + *(pbuffer + 15) = + pdata->dss_calc__user_roi_spad_en_7; + *(pbuffer + 16) = + pdata->dss_calc__user_roi_spad_en_8; + *(pbuffer + 17) = + pdata->dss_calc__user_roi_spad_en_9; + *(pbuffer + 18) = + pdata->dss_calc__user_roi_spad_en_10; + *(pbuffer + 19) = + pdata->dss_calc__user_roi_spad_en_11; + *(pbuffer + 20) = + pdata->dss_calc__user_roi_spad_en_12; + *(pbuffer + 21) = + pdata->dss_calc__user_roi_spad_en_13; + *(pbuffer + 22) = + pdata->dss_calc__user_roi_spad_en_14; + *(pbuffer + 23) = + pdata->dss_calc__user_roi_spad_en_15; + *(pbuffer + 24) = + pdata->dss_calc__user_roi_spad_en_16; + *(pbuffer + 25) = + pdata->dss_calc__user_roi_spad_en_17; + *(pbuffer + 26) = + pdata->dss_calc__user_roi_spad_en_18; + *(pbuffer + 27) = + pdata->dss_calc__user_roi_spad_en_19; + *(pbuffer + 28) = + pdata->dss_calc__user_roi_spad_en_20; + *(pbuffer + 29) = + pdata->dss_calc__user_roi_spad_en_21; + *(pbuffer + 30) = + pdata->dss_calc__user_roi_spad_en_22; + *(pbuffer + 31) = + pdata->dss_calc__user_roi_spad_en_23; + *(pbuffer + 32) = + pdata->dss_calc__user_roi_spad_en_24; + *(pbuffer + 33) = + pdata->dss_calc__user_roi_spad_en_25; + *(pbuffer + 34) = + pdata->dss_calc__user_roi_spad_en_26; + *(pbuffer + 35) = + pdata->dss_calc__user_roi_spad_en_27; + *(pbuffer + 36) = + pdata->dss_calc__user_roi_spad_en_28; + *(pbuffer + 37) = + pdata->dss_calc__user_roi_spad_en_29; + *(pbuffer + 38) = + pdata->dss_calc__user_roi_spad_en_30; + *(pbuffer + 39) = + pdata->dss_calc__user_roi_spad_en_31; + *(pbuffer + 40) = + pdata->dss_calc__user_roi_0; + *(pbuffer + 41) = + pdata->dss_calc__user_roi_1; + *(pbuffer + 42) = + pdata->dss_calc__mode_roi_0; + *(pbuffer + 43) = + pdata->dss_calc__mode_roi_1; + *(pbuffer + 44) = + pdata->sigma_estimator_calc__spare_0; + VL53L1_i2c_encode_uint16_t( + pdata->vhv_result__peak_signal_rate_mcps, + 2, + pbuffer + 46); + VL53L1_i2c_encode_uint32_t( + pdata->vhv_result__signal_total_events_ref, + 4, + pbuffer + 48); + VL53L1_i2c_encode_uint16_t( + pdata->phasecal_result__phase_output_ref, + 2, + pbuffer + 52); + VL53L1_i2c_encode_uint16_t( + pdata->dss_result__total_rate_per_spad, + 2, + pbuffer + 54); + *(pbuffer + 56) = + pdata->dss_result__enabled_blocks; + VL53L1_i2c_encode_uint16_t( + pdata->dss_result__num_requested_spads, + 2, + pbuffer + 58); + VL53L1_i2c_encode_uint16_t( + pdata->mm_result__inner_intersection_rate, + 2, + pbuffer + 62); + VL53L1_i2c_encode_uint16_t( + pdata->mm_result__outer_complement_rate, + 2, + pbuffer + 64); + VL53L1_i2c_encode_uint16_t( + pdata->mm_result__total_offset, + 2, + pbuffer + 66); + VL53L1_i2c_encode_uint32_t( + pdata->xtalk_calc__xtalk_for_enabled_spads & 0xFFFFFF, + 4, + pbuffer + 68); + VL53L1_i2c_encode_uint32_t( + pdata->xtalk_result__avg_xtalk_user_roi_kcps & 0xFFFFFF, + 4, + pbuffer + 72); + VL53L1_i2c_encode_uint32_t( + pdata->xtalk_result__avg_xtalk_mm_inner_roi_kcps & 0xFFFFFF, + 4, + pbuffer + 76); + VL53L1_i2c_encode_uint32_t( + pdata->xtalk_result__avg_xtalk_mm_outer_roi_kcps & 0xFFFFFF, + 4, + pbuffer + 80); + VL53L1_i2c_encode_uint32_t( + pdata->range_result__accum_phase, + 4, + pbuffer + 84); + VL53L1_i2c_encode_uint16_t( + pdata->range_result__offset_corrected_range, + 2, + pbuffer + 88); + LOG_FUNCTION_END(status); + + + return status; +} + + +VL53L1_Error VL53L1_i2c_decode_patch_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_patch_results_t *pdata) +{ + /** + * Decodes data structure VL53L1_patch_results_t from the input I2C read buffer + * Buffer must be at least 90 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_PATCH_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->dss_calc__roi_ctrl = + (*(pbuffer + 0)) & 0x3; + pdata->dss_calc__spare_1 = + (*(pbuffer + 1)); + pdata->dss_calc__spare_2 = + (*(pbuffer + 2)); + pdata->dss_calc__spare_3 = + (*(pbuffer + 3)); + pdata->dss_calc__spare_4 = + (*(pbuffer + 4)); + pdata->dss_calc__spare_5 = + (*(pbuffer + 5)); + pdata->dss_calc__spare_6 = + (*(pbuffer + 6)); + pdata->dss_calc__spare_7 = + (*(pbuffer + 7)); + pdata->dss_calc__user_roi_spad_en_0 = + (*(pbuffer + 8)); + pdata->dss_calc__user_roi_spad_en_1 = + (*(pbuffer + 9)); + pdata->dss_calc__user_roi_spad_en_2 = + (*(pbuffer + 10)); + pdata->dss_calc__user_roi_spad_en_3 = + (*(pbuffer + 11)); + pdata->dss_calc__user_roi_spad_en_4 = + (*(pbuffer + 12)); + pdata->dss_calc__user_roi_spad_en_5 = + (*(pbuffer + 13)); + pdata->dss_calc__user_roi_spad_en_6 = + (*(pbuffer + 14)); + pdata->dss_calc__user_roi_spad_en_7 = + (*(pbuffer + 15)); + pdata->dss_calc__user_roi_spad_en_8 = + (*(pbuffer + 16)); + pdata->dss_calc__user_roi_spad_en_9 = + (*(pbuffer + 17)); + pdata->dss_calc__user_roi_spad_en_10 = + (*(pbuffer + 18)); + pdata->dss_calc__user_roi_spad_en_11 = + (*(pbuffer + 19)); + pdata->dss_calc__user_roi_spad_en_12 = + (*(pbuffer + 20)); + pdata->dss_calc__user_roi_spad_en_13 = + (*(pbuffer + 21)); + pdata->dss_calc__user_roi_spad_en_14 = + (*(pbuffer + 22)); + pdata->dss_calc__user_roi_spad_en_15 = + (*(pbuffer + 23)); + pdata->dss_calc__user_roi_spad_en_16 = + (*(pbuffer + 24)); + pdata->dss_calc__user_roi_spad_en_17 = + (*(pbuffer + 25)); + pdata->dss_calc__user_roi_spad_en_18 = + (*(pbuffer + 26)); + pdata->dss_calc__user_roi_spad_en_19 = + (*(pbuffer + 27)); + pdata->dss_calc__user_roi_spad_en_20 = + (*(pbuffer + 28)); + pdata->dss_calc__user_roi_spad_en_21 = + (*(pbuffer + 29)); + pdata->dss_calc__user_roi_spad_en_22 = + (*(pbuffer + 30)); + pdata->dss_calc__user_roi_spad_en_23 = + (*(pbuffer + 31)); + pdata->dss_calc__user_roi_spad_en_24 = + (*(pbuffer + 32)); + pdata->dss_calc__user_roi_spad_en_25 = + (*(pbuffer + 33)); + pdata->dss_calc__user_roi_spad_en_26 = + (*(pbuffer + 34)); + pdata->dss_calc__user_roi_spad_en_27 = + (*(pbuffer + 35)); + pdata->dss_calc__user_roi_spad_en_28 = + (*(pbuffer + 36)); + pdata->dss_calc__user_roi_spad_en_29 = + (*(pbuffer + 37)); + pdata->dss_calc__user_roi_spad_en_30 = + (*(pbuffer + 38)); + pdata->dss_calc__user_roi_spad_en_31 = + (*(pbuffer + 39)); + pdata->dss_calc__user_roi_0 = + (*(pbuffer + 40)); + pdata->dss_calc__user_roi_1 = + (*(pbuffer + 41)); + pdata->dss_calc__mode_roi_0 = + (*(pbuffer + 42)); + pdata->dss_calc__mode_roi_1 = + (*(pbuffer + 43)); + pdata->sigma_estimator_calc__spare_0 = + (*(pbuffer + 44)); + pdata->vhv_result__peak_signal_rate_mcps = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 46)); + pdata->vhv_result__signal_total_events_ref = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 48)); + pdata->phasecal_result__phase_output_ref = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 52)); + pdata->dss_result__total_rate_per_spad = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 54)); + pdata->dss_result__enabled_blocks = + (*(pbuffer + 56)); + pdata->dss_result__num_requested_spads = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 58)); + pdata->mm_result__inner_intersection_rate = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 62)); + pdata->mm_result__outer_complement_rate = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 64)); + pdata->mm_result__total_offset = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 66)); + pdata->xtalk_calc__xtalk_for_enabled_spads = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 68)) & 0xFFFFFF; + pdata->xtalk_result__avg_xtalk_user_roi_kcps = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 72)) & 0xFFFFFF; + pdata->xtalk_result__avg_xtalk_mm_inner_roi_kcps = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 76)) & 0xFFFFFF; + pdata->xtalk_result__avg_xtalk_mm_outer_roi_kcps = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 80)) & 0xFFFFFF; + pdata->range_result__accum_phase = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 84)); + pdata->range_result__offset_corrected_range = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 88)); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_patch_results( + VL53L1_DEV Dev, + VL53L1_patch_results_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_patch_results_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_PATCH_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_patch_results( + pdata, + VL53L1_PATCH_RESULTS_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_DSS_CALC__ROI_CTRL, + comms_buffer, + VL53L1_PATCH_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_get_patch_results( + VL53L1_DEV Dev, + VL53L1_patch_results_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_patch_results_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_PATCH_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_ReadMulti( + Dev, + VL53L1_DSS_CALC__ROI_CTRL, + comms_buffer, + VL53L1_PATCH_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_patch_results( + VL53L1_PATCH_RESULTS_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_i2c_encode_shadow_system_results( + VL53L1_shadow_system_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_shadow_system_results_t into a I2C write buffer + * Buffer must be at least 82 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = + pdata->shadow_phasecal_result__vcsel_start; + *(pbuffer + 2) = + pdata->shadow_result__interrupt_status & 0x3F; + *(pbuffer + 3) = + pdata->shadow_result__range_status; + *(pbuffer + 4) = + pdata->shadow_result__report_status & 0xF; + *(pbuffer + 5) = + pdata->shadow_result__stream_count; + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__dss_actual_effective_spads_sd0, + 2, + pbuffer + 6); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__peak_signal_count_rate_mcps_sd0, + 2, + pbuffer + 8); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__ambient_count_rate_mcps_sd0, + 2, + pbuffer + 10); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__sigma_sd0, + 2, + pbuffer + 12); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__phase_sd0, + 2, + pbuffer + 14); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__final_crosstalk_corrected_range_mm_sd0, + 2, + pbuffer + 16); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0, + 2, + pbuffer + 18); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__mm_inner_actual_effective_spads_sd0, + 2, + pbuffer + 20); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__mm_outer_actual_effective_spads_sd0, + 2, + pbuffer + 22); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__avg_signal_count_rate_mcps_sd0, + 2, + pbuffer + 24); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__dss_actual_effective_spads_sd1, + 2, + pbuffer + 26); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__peak_signal_count_rate_mcps_sd1, + 2, + pbuffer + 28); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__ambient_count_rate_mcps_sd1, + 2, + pbuffer + 30); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__sigma_sd1, + 2, + pbuffer + 32); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__phase_sd1, + 2, + pbuffer + 34); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__final_crosstalk_corrected_range_mm_sd1, + 2, + pbuffer + 36); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__spare_0_sd1, + 2, + pbuffer + 38); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__spare_1_sd1, + 2, + pbuffer + 40); + VL53L1_i2c_encode_uint16_t( + pdata->shadow_result__spare_2_sd1, + 2, + pbuffer + 42); + *(pbuffer + 44) = + pdata->shadow_result__spare_3_sd1; + *(pbuffer + 45) = + pdata->shadow_result__thresh_info; + *(pbuffer + 80) = + pdata->shadow_phasecal_result__reference_phase_hi; + *(pbuffer + 81) = + pdata->shadow_phasecal_result__reference_phase_lo; + LOG_FUNCTION_END(status); + + + return status; +} + + +VL53L1_Error VL53L1_i2c_decode_shadow_system_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_shadow_system_results_t *pdata) +{ + /** + * Decodes data structure VL53L1_shadow_system_results_t from the input I2C read buffer + * Buffer must be at least 82 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->shadow_phasecal_result__vcsel_start = + (*(pbuffer + 0)); + pdata->shadow_result__interrupt_status = + (*(pbuffer + 2)) & 0x3F; + pdata->shadow_result__range_status = + (*(pbuffer + 3)); + pdata->shadow_result__report_status = + (*(pbuffer + 4)) & 0xF; + pdata->shadow_result__stream_count = + (*(pbuffer + 5)); + pdata->shadow_result__dss_actual_effective_spads_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 6)); + pdata->shadow_result__peak_signal_count_rate_mcps_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 8)); + pdata->shadow_result__ambient_count_rate_mcps_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 10)); + pdata->shadow_result__sigma_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 12)); + pdata->shadow_result__phase_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 14)); + pdata->shadow_result__final_crosstalk_corrected_range_mm_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 16)); + pdata->shadow_result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 18)); + pdata->shadow_result__mm_inner_actual_effective_spads_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 20)); + pdata->shadow_result__mm_outer_actual_effective_spads_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 22)); + pdata->shadow_result__avg_signal_count_rate_mcps_sd0 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 24)); + pdata->shadow_result__dss_actual_effective_spads_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 26)); + pdata->shadow_result__peak_signal_count_rate_mcps_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 28)); + pdata->shadow_result__ambient_count_rate_mcps_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 30)); + pdata->shadow_result__sigma_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 32)); + pdata->shadow_result__phase_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 34)); + pdata->shadow_result__final_crosstalk_corrected_range_mm_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 36)); + pdata->shadow_result__spare_0_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 38)); + pdata->shadow_result__spare_1_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 40)); + pdata->shadow_result__spare_2_sd1 = + (VL53L1_i2c_decode_uint16_t(2, pbuffer + 42)); + pdata->shadow_result__spare_3_sd1 = + (*(pbuffer + 44)); + pdata->shadow_result__thresh_info = + (*(pbuffer + 45)); + pdata->shadow_phasecal_result__reference_phase_hi = + (*(pbuffer + 80)); + pdata->shadow_phasecal_result__reference_phase_lo = + (*(pbuffer + 81)); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_shadow_system_results( + VL53L1_DEV Dev, + VL53L1_shadow_system_results_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_shadow_system_results_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_shadow_system_results( + pdata, + VL53L1_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_SHADOW_PHASECAL_RESULT__VCSEL_START, + comms_buffer, + VL53L1_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} + +VL53L1_Error VL53L1_get_shadow_system_results( + VL53L1_DEV Dev, + VL53L1_shadow_system_results_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_shadow_system_results_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_ReadMulti( + Dev, + VL53L1_SHADOW_PHASECAL_RESULT__VCSEL_START, + comms_buffer, + VL53L1_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_shadow_system_results( + VL53L1_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_i2c_encode_shadow_core_results( + VL53L1_shadow_core_results_t *pdata, + uint16_t buf_size, + uint8_t *pbuffer) +{ + /** + * Encodes data structure VL53L1_shadow_core_results_t into a I2C write buffer + * Buffer must be at least 33 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + VL53L1_i2c_encode_uint32_t( + pdata->shadow_result_core__ambient_window_events_sd0, + 4, + pbuffer + 0); + VL53L1_i2c_encode_uint32_t( + pdata->shadow_result_core__ranging_total_events_sd0, + 4, + pbuffer + 4); + VL53L1_i2c_encode_int32_t( + pdata->shadow_result_core__signal_total_events_sd0, + 4, + pbuffer + 8); + VL53L1_i2c_encode_uint32_t( + pdata->shadow_result_core__total_periods_elapsed_sd0, + 4, + pbuffer + 12); + VL53L1_i2c_encode_uint32_t( + pdata->shadow_result_core__ambient_window_events_sd1, + 4, + pbuffer + 16); + VL53L1_i2c_encode_uint32_t( + pdata->shadow_result_core__ranging_total_events_sd1, + 4, + pbuffer + 20); + VL53L1_i2c_encode_int32_t( + pdata->shadow_result_core__signal_total_events_sd1, + 4, + pbuffer + 24); + VL53L1_i2c_encode_uint32_t( + pdata->shadow_result_core__total_periods_elapsed_sd1, + 4, + pbuffer + 28); + *(pbuffer + 32) = + pdata->shadow_result_core__spare_0; + LOG_FUNCTION_END(status); + + + return status; +} + + +VL53L1_Error VL53L1_i2c_decode_shadow_core_results( + uint16_t buf_size, + uint8_t *pbuffer, + VL53L1_shadow_core_results_t *pdata) +{ + /** + * Decodes data structure VL53L1_shadow_core_results_t from the input I2C read buffer + * Buffer must be at least 33 bytes + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + if (VL53L1_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES > buf_size) + return VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->shadow_result_core__ambient_window_events_sd0 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 0)); + pdata->shadow_result_core__ranging_total_events_sd0 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 4)); + pdata->shadow_result_core__signal_total_events_sd0 = + (VL53L1_i2c_decode_int32_t(4, pbuffer + 8)); + pdata->shadow_result_core__total_periods_elapsed_sd0 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 12)); + pdata->shadow_result_core__ambient_window_events_sd1 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 16)); + pdata->shadow_result_core__ranging_total_events_sd1 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 20)); + pdata->shadow_result_core__signal_total_events_sd1 = + (VL53L1_i2c_decode_int32_t(4, pbuffer + 24)); + pdata->shadow_result_core__total_periods_elapsed_sd1 = + (VL53L1_i2c_decode_uint32_t(4, pbuffer + 28)); + pdata->shadow_result_core__spare_0 = + (*(pbuffer + 32)); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_set_shadow_core_results( + VL53L1_DEV Dev, + VL53L1_shadow_core_results_t *pdata) +{ + /** + * Serialises and sends the contents of VL53L1_shadow_core_results_t + * data structure to the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_i2c_encode_shadow_core_results( + pdata, + VL53L1_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES, + comms_buffer); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WriteMulti( + Dev, + VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0, + comms_buffer, + VL53L1_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_get_shadow_core_results( + VL53L1_DEV Dev, + VL53L1_shadow_core_results_t *pdata) +{ + /** + * Reads and de-serialises the contents of VL53L1_shadow_core_results_t + * data structure from the device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t comms_buffer[VL53L1_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES]; + + LOG_FUNCTION_START(""); + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_disable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_ReadMulti( + Dev, + VL53L1_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0, + comms_buffer, + VL53L1_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_enable_firmware(Dev); + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_i2c_decode_shadow_core_results( + VL53L1_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES, + comms_buffer, + pdata); + + LOG_FUNCTION_END(status); + + return status; +} +#endif diff --git a/App/VL53L1X_API/core/src/vl53l1_silicon_core.c b/App/VL53L1X_API/core/src/vl53l1_silicon_core.c new file mode 100644 index 0000000..343b001 --- /dev/null +++ b/App/VL53L1X_API/core/src/vl53l1_silicon_core.c @@ -0,0 +1,146 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_silicon_core.c + * + * @brief EwokPlus25 low level silicon LL Driver function definition + */ + + +#include "vl53l1_ll_def.h" +#include "vl53l1_platform.h" +#include "vl53l1_register_map.h" +#include "vl53l1_core.h" +#include "vl53l1_silicon_core.h" + + +#define LOG_FUNCTION_START(fmt, ...) \ + _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__) +#define LOG_FUNCTION_END(status, ...) \ + _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_CORE, status, ##__VA_ARGS__) +#define LOG_FUNCTION_END_FMT(status, fmt, ...) \ + _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_CORE, status, fmt, ##__VA_ARGS__) + + +VL53L1_Error VL53L1_is_firmware_ready_silicon( + VL53L1_DEV Dev, + uint8_t *pready) +{ + /** + * Determines if the firmware is ready to range + * + * There are 2 different behaviors depending on whether + * power force is enabled or not + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t comms_buffer[5]; + + LOG_FUNCTION_START(""); + + /* read interrupt and power force reset status */ + + status = VL53L1_ReadMulti( + Dev, + VL53L1_INTERRUPT_MANAGER__ENABLES, + comms_buffer, + 5); + + if (status == VL53L1_ERROR_NONE) { + + pdev->dbg_results.interrupt_manager__enables = + comms_buffer[0]; + pdev->dbg_results.interrupt_manager__clear = + comms_buffer[1]; + pdev->dbg_results.interrupt_manager__status = + comms_buffer[2]; + pdev->dbg_results.mcu_to_host_bank__wr_access_en = + comms_buffer[3]; + pdev->dbg_results.power_management__go1_reset_status = + comms_buffer[4]; + + if ((pdev->sys_ctrl.power_management__go1_power_force & 0x01) == 0x01) { + + if (((pdev->dbg_results.interrupt_manager__enables & 0x1F) == 0x1F) && + ((pdev->dbg_results.interrupt_manager__clear & 0x1F) == 0x1F)) + *pready = 0x01; + else + *pready = 0x00; + + } else { + + /* set ready flag if bit 0 is zero i.g G01 is in reset */ + if ((pdev->dbg_results.power_management__go1_reset_status & 0x01) == 0x00) + *pready = 0x01; + else + *pready = 0x00; + } + + } + + LOG_FUNCTION_END(status); + + return status; +} diff --git a/App/VL53L1X_API/core/src/vl53l1_wait.c b/App/VL53L1X_API/core/src/vl53l1_wait.c new file mode 100644 index 0000000..93ac9c6 --- /dev/null +++ b/App/VL53L1X_API/core/src/vl53l1_wait.c @@ -0,0 +1,558 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +******************************************************************************** +* +*/ + +/** + * @file vl53l1_wait.c + * + * @brief EwokPlus25 low level Driver wait function definition + */ + + +#include "vl53l1_ll_def.h" +#include "vl53l1_ll_device.h" +#include "vl53l1_platform.h" +#include "vl53l1_core.h" +#include "vl53l1_silicon_core.h" +#include "vl53l1_wait.h" +#include "vl53l1_register_settings.h" + + +#define LOG_FUNCTION_START(fmt, ...) \ + _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__) +#define LOG_FUNCTION_END(status, ...) \ + _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_CORE, status, ##__VA_ARGS__) +#define LOG_FUNCTION_END_FMT(status, fmt, ...) \ + _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_CORE, status, \ + fmt, ##__VA_ARGS__) + + +VL53L1_Error VL53L1_wait_for_boot_completion( + VL53L1_DEV Dev) +{ + + /* Waits for firmware boot to finish + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t fw_ready = 0; + + LOG_FUNCTION_START(""); + + if (pdev->wait_method == VL53L1_WAIT_METHOD_BLOCKING) { + + /* blocking version */ + + status = + VL53L1_poll_for_boot_completion( + Dev, + VL53L1_BOOT_COMPLETION_POLLING_TIMEOUT_MS); + + } else { + + /* implement non blocking version below */ + + fw_ready = 0; + while (fw_ready == 0x00 && status == VL53L1_ERROR_NONE) { + status = VL53L1_is_boot_complete( + Dev, + &fw_ready); + + if (status == VL53L1_ERROR_NONE) { + status = VL53L1_WaitMs( + Dev, + VL53L1_POLLING_DELAY_MS); + } + } + } + + LOG_FUNCTION_END(status); + + return status; + +} + + +VL53L1_Error VL53L1_wait_for_firmware_ready( + VL53L1_DEV Dev) +{ + + /* If in timed mode or single shot then check firmware is ready + * before sending handshake + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t fw_ready = 0; + uint8_t mode_start = 0; + + LOG_FUNCTION_START(""); + + /* Filter out tje measure mode part of the mode + * start register + */ + mode_start = + pdev->sys_ctrl.system__mode_start & + VL53L1_DEVICEMEASUREMENTMODE_MODE_MASK; + + /* + * conditional wait for firmware ready + * only waits for timed and single shot modes + */ + + if ((mode_start == VL53L1_DEVICEMEASUREMENTMODE_TIMED) || + (mode_start == VL53L1_DEVICEMEASUREMENTMODE_SINGLESHOT)) { + + if (pdev->wait_method == VL53L1_WAIT_METHOD_BLOCKING) { + + /* blocking version */ + + status = + VL53L1_poll_for_firmware_ready( + Dev, + VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS); + + } else { + + /* implement non blocking version below */ + + fw_ready = 0; + while (fw_ready == 0x00 && status == VL53L1_ERROR_NONE) { + status = VL53L1_is_firmware_ready( + Dev, + &fw_ready); + + if (status == VL53L1_ERROR_NONE) { + status = VL53L1_WaitMs( + Dev, + VL53L1_POLLING_DELAY_MS); + } + } + } + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_wait_for_range_completion( + VL53L1_DEV Dev) +{ + + /* Wrapper function for waiting for range completion + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t data_ready = 0; + + LOG_FUNCTION_START(""); + + if (pdev->wait_method == VL53L1_WAIT_METHOD_BLOCKING) { + + /* blocking version */ + + status = + VL53L1_poll_for_range_completion( + Dev, + VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS); + + } else { + + /* implement non blocking version below */ + + data_ready = 0; + while (data_ready == 0x00 && status == VL53L1_ERROR_NONE) { + status = VL53L1_is_new_data_ready( + Dev, + &data_ready); + + if (status == VL53L1_ERROR_NONE) { + status = VL53L1_WaitMs( + Dev, + VL53L1_POLLING_DELAY_MS); + } + } + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_wait_for_test_completion( + VL53L1_DEV Dev) +{ + + /* Wrapper function for waiting for test mode completion + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t data_ready = 0; + + LOG_FUNCTION_START(""); + + if (pdev->wait_method == VL53L1_WAIT_METHOD_BLOCKING) { + + /* blocking version */ + + status = + VL53L1_poll_for_range_completion( + Dev, + VL53L1_TEST_COMPLETION_POLLING_TIMEOUT_MS); + + } else { + + /* implement non blocking version below */ + + data_ready = 0; + while (data_ready == 0x00 && status == VL53L1_ERROR_NONE) { + status = VL53L1_is_new_data_ready( + Dev, + &data_ready); + + if (status == VL53L1_ERROR_NONE) { + status = VL53L1_WaitMs( + Dev, + VL53L1_POLLING_DELAY_MS); + } + } + } + + LOG_FUNCTION_END(status); + + return status; +} + + + + +VL53L1_Error VL53L1_is_boot_complete( + VL53L1_DEV Dev, + uint8_t *pready) +{ + /** + * Determines if the firmware finished booting by reading + * bit 0 of firmware__system_status register + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t firmware__system_status = 0; + + LOG_FUNCTION_START(""); + + /* read current range interrupt state */ + + status = + VL53L1_RdByte( + Dev, + VL53L1_FIRMWARE__SYSTEM_STATUS, + &firmware__system_status); + + /* set *pready = 1 if new range data ready complete + * zero otherwise + */ + + if ((firmware__system_status & 0x01) == 0x01) { + *pready = 0x01; + VL53L1_init_ll_driver_state( + Dev, + VL53L1_DEVICESTATE_SW_STANDBY); + } else { + *pready = 0x00; + VL53L1_init_ll_driver_state( + Dev, + VL53L1_DEVICESTATE_FW_COLDBOOT); + } + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_is_firmware_ready( + VL53L1_DEV Dev, + uint8_t *pready) +{ + /** + * Determines if the firmware is ready to range + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + LOG_FUNCTION_START(""); + + status = VL53L1_is_firmware_ready_silicon( + Dev, + pready); + + pdev->fw_ready = *pready; + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_is_new_data_ready( + VL53L1_DEV Dev, + uint8_t *pready) +{ + /** + * Determines if new range data is ready by reading bit 0 of + * VL53L1_GPIO__TIO_HV_STATUS to determine the current state + * of output interrupt pin + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t gpio__mux_active_high_hv = 0; + uint8_t gpio__tio_hv_status = 0; + uint8_t interrupt_ready = 0; + + LOG_FUNCTION_START(""); + + gpio__mux_active_high_hv = + pdev->stat_cfg.gpio_hv_mux__ctrl & + VL53L1_DEVICEINTERRUPTLEVEL_ACTIVE_MASK; + + if (gpio__mux_active_high_hv == VL53L1_DEVICEINTERRUPTLEVEL_ACTIVE_HIGH) + interrupt_ready = 0x01; + else + interrupt_ready = 0x00; + + /* read current range interrupt state */ + + status = VL53L1_RdByte( + Dev, + VL53L1_GPIO__TIO_HV_STATUS, + &gpio__tio_hv_status); + + /* set *pready = 1 if new range data ready complete zero otherwise */ + + if ((gpio__tio_hv_status & 0x01) == interrupt_ready) + *pready = 0x01; + else + *pready = 0x00; + + LOG_FUNCTION_END(status); + + return status; +} + + + + +VL53L1_Error VL53L1_poll_for_boot_completion( + VL53L1_DEV Dev, + uint32_t timeout_ms) +{ + /** + * Polls the bit 0 of the FIRMWARE__SYSTEM_STATUS register to see if + * the firmware is ready. + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + LOG_FUNCTION_START(""); + + /* after reset for the firmware blocks I2C access while + * it copies the NVM data into the G02 host register banks + * The host must wait the required time to allow the copy + * to complete before attempting to read the firmware status + */ + + status = VL53L1_WaitUs( + Dev, + VL53L1_FIRMWARE_BOOT_TIME_US); + + if (status == VL53L1_ERROR_NONE) + status = + VL53L1_WaitValueMaskEx( + Dev, + timeout_ms, + VL53L1_FIRMWARE__SYSTEM_STATUS, + 0x01, + 0x01, + VL53L1_POLLING_DELAY_MS); + + if (status == VL53L1_ERROR_NONE) + VL53L1_init_ll_driver_state(Dev, VL53L1_DEVICESTATE_SW_STANDBY); + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_poll_for_firmware_ready( + VL53L1_DEV Dev, + uint32_t timeout_ms) +{ + /** + * Polls the bit 0 of the FIRMWARE__SYSTEM_STATUS register to see if + * the firmware is ready. + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint32_t start_time_ms = 0; + uint32_t current_time_ms = 0; + int32_t poll_delay_ms = VL53L1_POLLING_DELAY_MS; + uint8_t fw_ready = 0; + + /* calculate time limit in absolute time */ + + VL53L1_GetTickCount(Dev, &start_time_ms); /*lint !e534 ignoring return*/ + pdev->fw_ready_poll_duration_ms = 0; + + /* wait until firmware is ready, timeout reached on error occurred */ + + while ((status == VL53L1_ERROR_NONE) && + (pdev->fw_ready_poll_duration_ms < timeout_ms) && + (fw_ready == 0)) { + + status = VL53L1_is_firmware_ready( + Dev, + &fw_ready); + + if (status == VL53L1_ERROR_NONE && + fw_ready == 0 && + poll_delay_ms > 0) { + status = VL53L1_WaitMs( + Dev, + poll_delay_ms); + } + + /* + * Update polling time (Compare difference rather than + * absolute to negate 32bit wrap around issue) + */ + VL53L1_GetTickCount(Dev, ¤t_time_ms); /*lint !e534 ignoring return*/ + pdev->fw_ready_poll_duration_ms = + current_time_ms - start_time_ms; + } + + if (fw_ready == 0 && status == VL53L1_ERROR_NONE) + status = VL53L1_ERROR_TIME_OUT; + + LOG_FUNCTION_END(status); + + return status; +} + + +VL53L1_Error VL53L1_poll_for_range_completion( + VL53L1_DEV Dev, + uint32_t timeout_ms) +{ + /** + * Polls bit 0 of VL53L1_GPIO__TIO_HV_STATUS to determine + * the state of output interrupt pin + * + * Interrupt may be either active high or active low. Use active_high to + * select the required level check + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev); + + uint8_t gpio__mux_active_high_hv = 0; + uint8_t interrupt_ready = 0; + + LOG_FUNCTION_START(""); + + gpio__mux_active_high_hv = + pdev->stat_cfg.gpio_hv_mux__ctrl & + VL53L1_DEVICEINTERRUPTLEVEL_ACTIVE_MASK; + + if (gpio__mux_active_high_hv == VL53L1_DEVICEINTERRUPTLEVEL_ACTIVE_HIGH) + interrupt_ready = 0x01; + else + interrupt_ready = 0x00; + + status = + VL53L1_WaitValueMaskEx( + Dev, + timeout_ms, + VL53L1_GPIO__TIO_HV_STATUS, + interrupt_ready, + 0x01, + VL53L1_POLLING_DELAY_MS); + + LOG_FUNCTION_END(status); + + return status; +} + diff --git a/App/VL53L1X_API/platform/inc/vl53l1_platform.h b/App/VL53L1X_API/platform/inc/vl53l1_platform.h new file mode 100644 index 0000000..3c738cd --- /dev/null +++ b/App/VL53L1X_API/platform/inc/vl53l1_platform.h @@ -0,0 +1,431 @@ +/******************************************************************************* + Copyright (C) 2016, STMicroelectronics International N.V. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of STMicroelectronics nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND + NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. + IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + + +#ifndef _VL53L1_PLATFORM_H_ +#define _VL53L1_PLATFORM_H_ + +#include "vl53l1_ll_def.h" +#include "vl53l1_platform_log.h" + +#define VL53L1_IPP_API +#include "vl53l1_platform_ipp_imports.h" +#include "vl53l1_platform_user_data.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @file vl53l1_platform.h + * + * @brief All end user OS/platform/application porting + */ + + + +/** + * @brief Initialise platform comms. + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] comms_type : selects between I2C and SPI + * @param[in] comms_speed_khz : unsigned short containing the I2C speed in kHz + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_CommsInitialise( + VL53L1_Dev_t *pdev, + uint8_t comms_type, + uint16_t comms_speed_khz); + + +/** + * @brief Close platform comms. + * + * @param[in] pdev : pointer to device structure (device handle) + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_CommsClose( + VL53L1_Dev_t *pdev); + + +/** + * @brief Writes the supplied byte buffer to the device + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] index : uint16_t register index value + * @param[in] pdata : pointer to uint8_t (byte) buffer containing the data to be written + * @param[in] count : number of bytes in the supplied byte buffer + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_WriteMulti( + VL53L1_Dev_t *pdev, + uint16_t index, + uint8_t *pdata, + uint32_t count); + + +/** + * @brief Reads the requested number of bytes from the device + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] index : uint16_t register index value + * @param[out] pdata : pointer to the uint8_t (byte) buffer to store read data + * @param[in] count : number of bytes to read + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_ReadMulti( + VL53L1_Dev_t *pdev, + uint16_t index, + uint8_t *pdata, + uint32_t count); + + +/** + * @brief Writes a single byte to the device + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] index : uint16_t register index value + * @param[in] data : uint8_t data value to write + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_WrByte( + VL53L1_Dev_t *pdev, + uint16_t index, + uint8_t data); + + +/** + * @brief Writes a single word (16-bit unsigned) to the device + * + * Manages the big-endian nature of the device register map + * (first byte written is the MS byte). + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] index : uint16_t register index value + * @param[in] data : uin16_t data value write + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_WrWord( + VL53L1_Dev_t *pdev, + uint16_t index, + uint16_t data); + + +/** + * @brief Writes a single dword (32-bit unsigned) to the device + * + * Manages the big-endian nature of the device register map + * (first byte written is the MS byte). + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] index : uint16_t register index value + * @param[in] data : uint32_t data value to write + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_WrDWord( + VL53L1_Dev_t *pdev, + uint16_t index, + uint32_t data); + + + +/** + * @brief Reads a single byte from the device + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] index : uint16_t register index + * @param[out] pdata : pointer to uint8_t data value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + * + */ + +VL53L1_Error VL53L1_RdByte( + VL53L1_Dev_t *pdev, + uint16_t index, + uint8_t *pdata); + + +/** + * @brief Reads a single word (16-bit unsigned) from the device + * + * Manages the big-endian nature of the device (first byte read is the MS byte). + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] index : uint16_t register index value + * @param[out] pdata : pointer to uint16_t data value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_RdWord( + VL53L1_Dev_t *pdev, + uint16_t index, + uint16_t *pdata); + + +/** + * @brief Reads a single dword (32-bit unsigned) from the device + * + * Manages the big-endian nature of the device (first byte read is the MS byte). + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] index : uint16_t register index value + * @param[out] pdata : pointer to uint32_t data value + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_RdDWord( + VL53L1_Dev_t *pdev, + uint16_t index, + uint32_t *pdata); + + + +/** + * @brief Implements a programmable wait in us + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] wait_us : integer wait in micro seconds + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_WaitUs( + VL53L1_Dev_t *pdev, + int32_t wait_us); + + +/** + * @brief Implements a programmable wait in ms + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] wait_ms : integer wait in milliseconds + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_WaitMs( + VL53L1_Dev_t *pdev, + int32_t wait_ms); + + +/** +* @brief Get the frequency of the timer used for ranging results time stamps +* +* @param[out] ptimer_freq_hz : pointer for timer frequency +* + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error +*/ + +VL53L1_Error VL53L1_GetTimerFrequency(int32_t *ptimer_freq_hz); + +/** +* @brief Get the timer value in units of timer_freq_hz (see VL53L1_get_timestamp_frequency()) +* +* @param[out] ptimer_count : pointer for timer count value +* + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error +*/ + +VL53L1_Error VL53L1_GetTimerValue(int32_t *ptimer_count); + + +/** + * @brief Set the mode of a specified GPIO pin + * + * @param pin - an identifier specifying the pin being modified - defined per platform + * + * @param mode - an identifier specifying the requested mode - defined per platform + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_GpioSetMode(uint8_t pin, uint8_t mode); + + +/** + * @brief Set the value of a specified GPIO pin + * + * @param pin - an identifier specifying the pin being modified - defined per platform + * + * @param value - a value to set on the GPIO pin - typically 0 or 1 + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_GpioSetValue(uint8_t pin, uint8_t value); + + +/** + * @brief Get the value of a specified GPIO pin + * + * @param pin - an identifier specifying the pin being modified - defined per platform + * + * @param pvalue - a value retrieved from the GPIO pin - typically 0 or 1 + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_GpioGetValue(uint8_t pin, uint8_t *pvalue); + + +/** + * @brief Sets and clears the XShutdown pin on the Ewok + * + * @param value - the value for xshutdown - 0 = in reset, 1 = operational + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_GpioXshutdown(uint8_t value); + + +/** + * @brief Sets and clears the Comms Mode pin (NCS) on the Ewok + * + * @param value - the value for comms select - 0 = I2C, 1 = SPI + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_GpioCommsSelect(uint8_t value); + + +/** + * @brief Enables and disables the power to the Ewok module + * + * @param value - the state of the power supply - 0 = power off, 1 = power on + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_GpioPowerEnable(uint8_t value); + +/** + * @brief Enables callbacks to the supplied funtion pointer when Ewok interrupts ocurr + * + * @param function - a function callback supplies by the caller, for interrupt notification + * @param edge_type - falling edge or rising edge interrupt detection + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_GpioInterruptEnable(void (*function)(void), uint8_t edge_type); + + +/** + * @brief Disables the callback on Ewok interrupts + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_GpioInterruptDisable(void); + + +/* + * @brief Gets current system tick count in [ms] + * + * @return time_ms : current time in [ms] + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_GetTickCount( + uint32_t *ptime_ms); + + +/** + * @brief Register "wait for value" polling routine + * + * Port of the V2WReg Script function WaitValueMaskEx() + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] timeout_ms : timeout in [ms] + * @param[in] index : uint16_t register index value + * @param[in] value : value to wait for + * @param[in] mask : mask to be applied before comparison with value + * @param[in] poll_delay_ms : polling delay been each read transaction in [ms] + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_WaitValueMaskEx( + VL53L1_Dev_t *pdev, + uint32_t timeout_ms, + uint16_t index, + uint8_t value, + uint8_t mask, + uint32_t poll_delay_ms); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/App/VL53L1X_API/platform/inc/vl53l1_platform_init.h b/App/VL53L1X_API/platform/inc/vl53l1_platform_init.h new file mode 100644 index 0000000..223c53f --- /dev/null +++ b/App/VL53L1X_API/platform/inc/vl53l1_platform_init.h @@ -0,0 +1,90 @@ +/******************************************************************************* + Copyright (C) 2016, STMicroelectronics International N.V. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of STMicroelectronics nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND + NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. + IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + + +#ifndef _VL53L1_PLATFORM_INIT_H_ +#define _VL53L1_PLATFORM_INIT_H_ + +#include "vl53l1_platform.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @file vl53l1_platform_init.h + * + * @brief EwokPlus25 comms and GPIO init + */ + + +/** + * @brief Initialise platform comms, GPIO and reset device + * + * Initialises comms, sets the states of GPIO (xshutdown, ncs, + * EVK device power regulator enable) and resets the device + * + * @param[in] pdev : pointer to device structure (device handle) + * @param[in] i2c_slave_address : I2C slave address + * @param[in] comms_type : Comms type: VL53L1_I2C or VL53L1_SPI + * @param[in] comms_speed_khz : 400kHz recommended for I2C + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_platform_init( + VL53L1_Dev_t *pdev, + uint8_t i2c_slave_address, + uint8_t comms_type, + uint16_t comms_speed_khz); + + +/** + * @brief Close platform comms and GPIO + * + * Puts the device into reset, disables the EVK device power regulator + * and closes comms + * + * @param[in] pdev : pointer to device structure (device handle) + * + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ + +VL53L1_Error VL53L1_platform_terminate( + VL53L1_Dev_t *pdev); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/App/VL53L1X_API/platform/inc/vl53l1_platform_ipp_imports.h b/App/VL53L1X_API/platform/inc/vl53l1_platform_ipp_imports.h new file mode 100644 index 0000000..a7ec271 --- /dev/null +++ b/App/VL53L1X_API/platform/inc/vl53l1_platform_ipp_imports.h @@ -0,0 +1,6 @@ + +#ifdef VL53L1_NEEDS_IPP +# undef VL53L1_IPP_API +# define VL53L1_IPP_API __declspec(dllimport) +# pragma comment (lib, "EwokPlus25API_IPP") +#endif diff --git a/App/VL53L1X_API/platform/inc/vl53l1_platform_log.h b/App/VL53L1X_API/platform/inc/vl53l1_platform_log.h new file mode 100644 index 0000000..5bff5bd --- /dev/null +++ b/App/VL53L1X_API/platform/inc/vl53l1_platform_log.h @@ -0,0 +1,223 @@ +/******************************************************************************* +Copyright (C) 2015, STMicroelectronics International N.V. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of STMicroelectronics nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. +IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +********************************************************************************/ + +/** + * @file vl53l1_platform_log.h + * + * @brief EwokPlus25 platform logging function definition + */ + + +#ifndef _VL53L1_PLATFORM_LOG_H_ +#define _VL53L1_PLATFORM_LOG_H_ + + +#ifdef VL53L1_LOG_ENABLE + #include "vl53l1_platform_user_config.h" + + #ifdef _MSC_VER + # define EWOKPLUS_EXPORTS __declspec(dllexport) + #else + # define EWOKPLUS_EXPORTS + #endif + + #include "vl53l1_types.h" + + #ifdef __cplusplus + extern "C" { + #endif + + #include + + /** + * @brief Set the level, output and specific functions for module logging. + * + * + * @param filename - full path of output log file, NULL for print to stdout + * + * @param modules - Module or None or All to trace + * VL53L1_TRACE_MODULE_NONE + * VL53L1_TRACE_MODULE_API + * VL53L1_TRACE_MODULE_CORE + * VL53L1_TRACE_MODULE_TUNING + * VL53L1_TRACE_MODULE_CHARACTERISATION + * VL53L1_TRACE_MODULE_PLATFORM + * VL53L1_TRACE_MODULE_ALL + * + * @param level - trace level + * VL53L1_TRACE_LEVEL_NONE + * VL53L1_TRACE_LEVEL_ERRORS + * VL53L1_TRACE_LEVEL_WARNING + * VL53L1_TRACE_LEVEL_INFO + * VL53L1_TRACE_LEVEL_DEBUG + * VL53L1_TRACE_LEVEL_ALL + * VL53L1_TRACE_LEVEL_IGNORE + * + * @param functions - function level to trace; + * VL53L1_TRACE_FUNCTION_NONE + * VL53L1_TRACE_FUNCTION_I2C + * VL53L1_TRACE_FUNCTION_ALL + * + * @return status - always VL53L1_ERROR_NONE + * + */ + + #define VL53L1_TRACE_LEVEL_NONE 0x00000000 + #define VL53L1_TRACE_LEVEL_ERRORS 0x00000001 + #define VL53L1_TRACE_LEVEL_WARNING 0x00000002 + #define VL53L1_TRACE_LEVEL_INFO 0x00000004 + #define VL53L1_TRACE_LEVEL_DEBUG 0x00000008 + #define VL53L1_TRACE_LEVEL_ALL 0x00000010 + #define VL53L1_TRACE_LEVEL_IGNORE 0x00000020 + + #define VL53L1_TRACE_FUNCTION_NONE 0x00000000 + #define VL53L1_TRACE_FUNCTION_I2C 0x00000001 + #define VL53L1_TRACE_FUNCTION_ALL 0x7fffffff + + #define VL53L1_TRACE_MODULE_NONE 0x00000000 + #define VL53L1_TRACE_MODULE_API 0x00000001 + #define VL53L1_TRACE_MODULE_CORE 0x00000002 + #define VL53L1_TRACE_MODULE_PROTECTED 0x00000004 + #define VL53L1_TRACE_MODULE_HISTOGRAM 0x00000008 + #define VL53L1_TRACE_MODULE_REGISTERS 0x00000010 + #define VL53L1_TRACE_MODULE_PLATFORM 0x00000020 + #define VL53L1_TRACE_MODULE_NVM 0x00000040 + #define VL53L1_TRACE_MODULE_CALIBRATION_DATA 0x00000080 + #define VL53L1_TRACE_MODULE_NVM_DATA 0x00000100 + #define VL53L1_TRACE_MODULE_HISTOGRAM_DATA 0x00000200 + #define VL53L1_TRACE_MODULE_RANGE_RESULTS_DATA 0x00000400 + #define VL53L1_TRACE_MODULE_XTALK_DATA 0x00000800 + #define VL53L1_TRACE_MODULE_OFFSET_DATA 0x00001000 + #define VL53L1_TRACE_MODULE_DATA_INIT 0x00002000 + #define VL53L1_TRACE_MODULE_REF_SPAD_CHAR 0x00004000 + #define VL53L1_TRACE_MODULE_SPAD_RATE_MAP 0x00008000 + #ifdef PAL_EXTENDED + #define VL53L1_TRACE_MODULE_SPAD 0x01000000 + #define VL53L1_TRACE_MODULE_FMT 0x02000000 + #define VL53L1_TRACE_MODULE_UTILS 0x04000000 + #define VL53L1_TRACE_MODULE_BENCH_FUNCS 0x08000000 + #endif + #define VL53L1_TRACE_MODULE_CUSTOMER_API 0x40000000 + #define VL53L1_TRACE_MODULE_ALL 0x7fffffff + + + extern uint32_t _trace_level; + + /* + * NOTE: dynamically exported if we enable logging. + * this way, Python interfaces can access this function, but we don't + * need to include it in the .def files. + */ + EWOKPLUS_EXPORTS int8_t VL53L1_trace_config( + char *filename, + uint32_t modules, + uint32_t level, + uint32_t functions); + + /** + * @brief Print trace module function. + * + * @param module - ?? + * @param level - ?? + * @param function - ?? + * @param format - ?? + * + */ + + EWOKPLUS_EXPORTS void VL53L1_trace_print_module_function( + uint32_t module, + uint32_t level, + uint32_t function, + const char *format, ...); + + /** + * @brief Get global _trace_functions parameter + * + * @return _trace_functions + */ + + uint32_t VL53L1_get_trace_functions(void); + + /** + * @brief Set global _trace_functions parameter + * + * @param[in] function : new function code + */ + + void VL53L1_set_trace_functions(uint32_t function); + + + /* + * @brief Returns the current system tick count in [ms] + * + * @return time_ms : current time in [ms] + * + */ + + uint32_t VL53L1_clock(void); + + #define LOG_GET_TIME() \ + ((int)VL53L1_clock()) + + #define _LOG_TRACE_PRINT(module, level, function, ...) \ + VL53L1_trace_print_module_function(module, level, function, ##__VA_ARGS__); + + #define _LOG_FUNCTION_START(module, fmt, ...) \ + VL53L1_trace_print_module_function(module, _trace_level, VL53L1_TRACE_FUNCTION_ALL, "%6ld %s "fmt"\n", LOG_GET_TIME(), __FUNCTION__, ##__VA_ARGS__); + + #define _LOG_FUNCTION_END(module, status, ...)\ + VL53L1_trace_print_module_function(module, _trace_level, VL53L1_TRACE_FUNCTION_ALL, "%6ld %s %d\n", LOG_GET_TIME(), __FUNCTION__, (int)status, ##__VA_ARGS__) + + #define _LOG_FUNCTION_END_FMT(module, status, fmt, ...)\ + VL53L1_trace_print_module_function(module, _trace_level, VL53L1_TRACE_FUNCTION_ALL, "%6ld %s %d "fmt"\n", LOG_GET_TIME(), __FUNCTION__, (int)status, ##__VA_ARGS__) + + #define _LOG_GET_TRACE_FUNCTIONS()\ + VL53L1_get_trace_functions() + + #define _LOG_SET_TRACE_FUNCTIONS(functions)\ + VL53L1_set_trace_functions(functions) + + #define _LOG_STRING_BUFFER(x) char x[VL53L1_MAX_STRING_LENGTH] + + #ifdef __cplusplus + } + #endif + +#else /* VL53L1_LOG_ENABLE - no logging */ + + #define _LOG_TRACE_PRINT(module, level, function, ...) + #define _LOG_FUNCTION_START(module, fmt, ...) + #define _LOG_FUNCTION_END(module, status, ...) + #define _LOG_FUNCTION_END_FMT(module, status, fmt, ...) + #define _LOG_GET_TRACE_FUNCTIONS() 0 + #define _LOG_SET_TRACE_FUNCTIONS(functions) + #define _LOG_STRING_BUFFER(x) + +#endif /* VL53L1_LOG_ENABLE */ + +#endif /* _VL53L1_PLATFORM_LOG_H_ */ diff --git a/App/VL53L1X_API/platform/inc/vl53l1_platform_user_config.h b/App/VL53L1X_API/platform/inc/vl53l1_platform_user_config.h new file mode 100644 index 0000000..e73bb91 --- /dev/null +++ b/App/VL53L1X_API/platform/inc/vl53l1_platform_user_config.h @@ -0,0 +1,84 @@ +/******************************************************************************* +Copyright (C) 2015, STMicroelectronics International N.V. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of STMicroelectronics nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. +IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +********************************************************************************/ + +/** + * @file vl53l1_platform_user_config.h + * + * @brief EwokPlus compile time user modifiable configuration + */ + + +#ifndef _VL53L1_PLATFORM_USER_CONFIG_H_ +#define _VL53L1_PLATFORM_USER_CONFIG_H_ + +#define VL53L1_BYTES_PER_WORD 2 +#define VL53L1_BYTES_PER_DWORD 4 + +/* Define polling delays */ +#define VL53L1_BOOT_COMPLETION_POLLING_TIMEOUT_MS 500 +#define VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS 2000 +#define VL53L1_TEST_COMPLETION_POLLING_TIMEOUT_MS 60000 + +#define VL53L1_POLLING_DELAY_MS 1 + +/* Define LLD TuningParms Page Base Address + * - Part of Patch_AddedTuningParms_11761 + */ +#define VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS 0x8000 +#define VL53L1_TUNINGPARM_PRIVATE_PAGE_BASE_ADDRESS 0xC000 + +#define VL53L1_GAIN_FACTOR__STANDARD_DEFAULT 0x0800 + /*!< Default standard ranging gain correction factor + 1.11 format. 1.0 = 0x0800, 0.980 = 0x07D7 */ + +#define VL53L1_OFFSET_CAL_MIN_EFFECTIVE_SPADS 0x0500 + /*!< Lower Limit for the MM1 effective SPAD count during offset + calibration Format 8.8 0x0500 -> 5.0 effective SPADs */ + +#define VL53L1_OFFSET_CAL_MAX_PRE_PEAK_RATE_MCPS 0x1900 + /*!< Max Limit for the pre range peak rate during offset + calibration Format 9.7 0x1900 -> 50.0 Mcps. + If larger then in pile up */ + +#define VL53L1_OFFSET_CAL_MAX_SIGMA_MM 0x0040 + /*!< Max sigma estimate limit during offset calibration + Check applies to pre-range, mm1 and mm2 ranges + Format 14.2 0x0040 -> 16.0mm. */ + +#define VL53L1_MAX_USER_ZONES 1 + /*!< Max number of user Zones - maximal limitation from + FW stream divide - value of 254 */ + +#define VL53L1_MAX_RANGE_RESULTS 2 + /*!< Allocates storage for return and reference restults */ + + +#define VL53L1_MAX_STRING_LENGTH 512 + +#endif /* _VL53L1_PLATFORM_USER_CONFIG_H_ */ + diff --git a/App/VL53L1X_API/platform/inc/vl53l1_platform_user_data.h b/App/VL53L1X_API/platform/inc/vl53l1_platform_user_data.h new file mode 100644 index 0000000..2810890 --- /dev/null +++ b/App/VL53L1X_API/platform/inc/vl53l1_platform_user_data.h @@ -0,0 +1,122 @@ +/******************************************************************************* + Copyright (C) 2016, STMicroelectronics International N.V. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of STMicroelectronics nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND + NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. + IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + + +#ifndef _VL53L1_PLATFORM_USER_DATA_H_ +#define _VL53L1_PLATFORM_USER_DATA_H_ + +#ifndef __KERNEL__ +#include +#endif + +#include "vl53l1_def.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @file vl53l1_platform_user_data.h + * + * @brief All end user OS/platform/application porting + */ + +/** @brief Contains the current state and internal values of the API + */ + +typedef struct { + + VL53L1_DevData_t Data; + /*!< Low Level Driver data structure */ + + uint8_t i2c_slave_address; + /*!< i2c device address user specific field */ + uint8_t comms_type; + /*!< Type of comms : VL53L1_I2C or VL53L1_SPI */ + uint16_t comms_speed_khz; + /*!< Comms speed [kHz] : typically 400kHz for I2C */ + + uint32_t new_data_ready_poll_duration_ms; + /*!< New data ready poll duration in ms - for debug */ +} VL53L1_Dev_t; + + +/** + * @brief Declare the device Handle as a pointer of the structure @a VL53L1_Dev_t. + * + */ +typedef VL53L1_Dev_t *VL53L1_DEV; + +/** + * @def PALDevDataGet + * @brief Get ST private structure @a VL53L1_DevData_t data access + * + * @param Dev Device Handle + * @param field ST structure field name + * It maybe used and as real data "ref" not just as "get" for sub-structure item + * like PALDevDataGet(FilterData.field)[i] or + * PALDevDataGet(FilterData.MeasurementIndex)++ + */ +#define PALDevDataGet(Dev, field) (Dev->Data.field) + + +/** + * @def PALDevDataSet(Dev, field, data) + * @brief Set ST private structure @a VL53L1_DevData_t data field + * @param Dev Device Handle + * @param field ST structure field name + * @param data Data to be set + */ +#define PALDevDataSet(Dev, field, data) ((Dev->Data.field) = (data)) + + +/** + * @def VL53L1DevStructGetLLDriverHandle + * @brief Get LL Driver handle @a VL53L0_Dev_t data access + * + * @param Dev Device Handle + */ +#define VL53L1DevStructGetLLDriverHandle(Dev) (&Dev->Data.LLData) + +/** + * @def VL53L1DevStructGetLLResultsHandle + * @brief Get LL Results handle @a VL53L0_Dev_t data access + * + * @param Dev Device Handle + */ +#define VL53L1DevStructGetLLResultsHandle(Dev) (&Dev->Data.llresults) + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/App/VL53L1X_API/platform/inc/vl53l1_platform_user_defines.h b/App/VL53L1X_API/platform/inc/vl53l1_platform_user_defines.h new file mode 100644 index 0000000..04ad850 --- /dev/null +++ b/App/VL53L1X_API/platform/inc/vl53l1_platform_user_defines.h @@ -0,0 +1,95 @@ +/******************************************************************************* + Copyright (C) 2016, STMicroelectronics International N.V. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of STMicroelectronics nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND + NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. + IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + + +#ifndef _VL53L1_PLATFORM_USER_DEFINES_H_ +#define _VL53L1_PLATFORM_USER_DEFINES_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @file vl53l1_platform_user_defines.h + * + * @brief All end user OS/platform/application definitions + */ + + +/** + * @def do_division_u + * @brief customer supplied division operation - 64-bit unsigned + * + * @param dividend unsigned 64-bit numerator + * @param divisor unsigned 64-bit denominator + */ +#define do_division_u(dividend, divisor) (dividend / divisor) + + +/** + * @def do_division_s + * @brief customer supplied division operation - 64-bit signed + * + * @param dividend signed 64-bit numerator + * @param divisor signed 64-bit denominator + */ +#define do_division_s(dividend, divisor) (dividend / divisor) + + +/** + * @def WARN_OVERRIDE_STATUS + * @brief customer supplied macro to optionally output info when a specific + error has been overridden with success within the EwokPlus driver + * + * @param __X__ the macro which enabled the suppression + */ +#define WARN_OVERRIDE_STATUS(__X__)\ + trace_print (VL53L1_TRACE_LEVEL_WARNING, #__X__); + + +#ifdef _MSC_VER +#define DISABLE_WARNINGS() { \ + __pragma (warning (push)); \ + __pragma (warning (disable:4127)); \ + } +#define ENABLE_WARNINGS() { \ + __pragma (warning (pop)); \ + } +#else + #define DISABLE_WARNINGS() + #define ENABLE_WARNINGS() +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // _VL53L1_PLATFORM_USER_DEFINES_H_ + diff --git a/App/VL53L1X_API/platform/inc/vl53l1_types.h b/App/VL53L1X_API/platform/inc/vl53l1_types.h new file mode 100644 index 0000000..c0603b7 --- /dev/null +++ b/App/VL53L1X_API/platform/inc/vl53l1_types.h @@ -0,0 +1,114 @@ +/******************************************************************************* +Copyright (C) 2015, STMicroelectronics International N.V. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of STMicroelectronics nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. +IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +********************************************************************************/ +/** + * @file vl53l1_types.h + * @brief VL53L1 types definition + */ + +#ifndef _VL53L1_TYPES_H_ +#define _VL53L1_TYPES_H_ + +/** @defgroup porting_type Basic type definition + * @ingroup api_platform + * + * @brief file vl53l1_types.h files hold basic type definition that may requires porting + * + * contains type that must be defined for the platform\n + * when target platform and compiler provide stdint.h and stddef.h it is enough to include it.\n + * If stdint.h is not available review and adapt all signed and unsigned 8/16/32 bits basic types. \n + * If stddef.h is not available review and adapt NULL definition . + */ +#include +#include +#include +#include +#include + +#ifndef NULL +#error "Error NULL definition should be done. Please add required include " +#endif + + +#if !defined(STDINT_H) && !defined(_STDINT_H) && !defined(_GCC_STDINT_H) && !defined(__STDINT_DECLS) && !defined(_GCC_WRAP_STDINT_H) && !defined(_STDINT) + + #pragma message("Please review type definition of STDINT define for your platform and add to list above ") + + /* + * target platform do not provide stdint or use a different #define than above + * to avoid seeing the message below addapt the #define list above or implement + * all type and delete these pragma + */ + +/** \ingroup VL53L1_portingType_group + * @{ + */ + + +typedef unsigned long long uint64_t; + + +/** @brief Typedef defining 32 bit unsigned int type.\n + * The developer should modify this to suit the platform being deployed. + */ +typedef unsigned int uint32_t; + +/** @brief Typedef defining 32 bit int type.\n + * The developer should modify this to suit the platform being deployed. + */ +typedef int int32_t; + +/** @brief Typedef defining 16 bit unsigned short type.\n + * The developer should modify this to suit the platform being deployed. + */ +typedef unsigned short uint16_t; + +/** @brief Typedef defining 16 bit short type.\n + * The developer should modify this to suit the platform being deployed. + */ +typedef short int16_t; + +/** @brief Typedef defining 8 bit unsigned char type.\n + * The developer should modify this to suit the platform being deployed. + */ +typedef unsigned char uint8_t; + +/** @brief Typedef defining 8 bit char type.\n + * The developer should modify this to suit the platform being deployed. + */ +typedef signed char int8_t; + +/** @} */ +#endif /* _STDINT_H */ + + +/** use where fractional values are expected + * + * Given a floating point value f it's .16 bit point is (int)(f*(1<<16))*/ +typedef uint32_t FixPoint1616_t; + +#endif /* VL53L1_TYPES_H_ */ diff --git a/App/VL53L1X_API/platform/src/vl53l1_platform.c b/App/VL53L1X_API/platform/src/vl53l1_platform.c new file mode 100644 index 0000000..d648e98 --- /dev/null +++ b/App/VL53L1X_API/platform/src/vl53l1_platform.c @@ -0,0 +1,860 @@ +/******************************************************************************* + Copyright (C) 2016, STMicroelectronics International N.V. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of STMicroelectronics nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND + NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. + IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +/** + * @file vl53l1_platform.c + * @brief Code function definitions for EwokPlus25 Platform Layer + * RANGING SENSOR VERSION + * + */ +#include + +#include // sprintf(), vsnprintf(), printf() +#include +#include // strncpy(), strnlen() + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +#include "vl53l1_platform.h" +#include "vl53l1_platform_log.h" + +#ifdef PAL_EXTENDED + #include "vl53l1_register_strings.h" +#else + #define VL53L1_get_register_name(a,b) +#endif + +#include "ranging_sensor_comms.h" +#include "power_board_defs.h" + +// flag to indicate if power board has been accessed +const uint32_t _power_board_in_use = 0; + +// flag to indicate if we can use the extended voltage ranges (not laser safe!) +uint32_t _power_board_extended = 0; + +// cache of the comms type flag +uint8_t global_comms_type = 0; + +#define VL53L1_COMMS_CHUNK_SIZE 56 +#define VL53L1_COMMS_BUFFER_SIZE 64 + +#define GPIO_INTERRUPT RS_GPIO62 +#define GPIO_POWER_ENABLE RS_GPIO60 +#define GPIO_XSHUTDOWN RS_GPIO61 +#define GPIO_SPI_CHIP_SELECT RS_GPIO51 + +/*! + * The intent of this Abstraction layer is to provide the same API + * to the underlying SystemVerilog tasks as the C driver will have + * to ST Comms DLL's for the talking to Ewok via the USB + STM32 + * or if the C-driver is implemented directly on the STM32 + */ + +#define trace_print(level, ...) \ + _LOG_TRACE_PRINT(VL53L1_TRACE_MODULE_PLATFORM, \ + level, VL53L1_TRACE_FUNCTION_NONE, ##__VA_ARGS__) + +#define trace_i2c(...) \ + _LOG_TRACE_PRINT(VL53L1_TRACE_MODULE_NONE, \ + VL53L1_TRACE_LEVEL_NONE, VL53L1_TRACE_FUNCTION_I2C, ##__VA_ARGS__) + + +VL53L1_Error VL53L1_CommsInitialise( + VL53L1_Dev_t *pdev, + uint8_t comms_type, + uint16_t comms_speed_khz) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + char comms_error_string[ERROR_TEXT_LENGTH]; + + SUPPRESS_UNUSED_WARNING(pdev); + SUPPRESS_UNUSED_WARNING(comms_speed_khz); + + global_comms_type = comms_type; + + if(global_comms_type == VL53L1_I2C) + { + if ((CP_STATUS)RANGING_SENSOR_COMMS_Init_CCI(0, 0, 0) != CP_STATUS_OK) + { + RANGING_SENSOR_COMMS_Get_Error_Text(comms_error_string); /*lint !e534 ignoring return value */ + trace_i2c("VL53L1_CommsInitialise: RANGING_SENSOR_COMMS_Init_CCI() failed\n"); + trace_i2c(comms_error_string); + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } + else if(global_comms_type == VL53L1_SPI) + { + if ((CP_STATUS)RANGING_SENSOR_COMMS_Init_SPI_V2W8(0, 0, 0) != CP_STATUS_OK) + { + RANGING_SENSOR_COMMS_Get_Error_Text(comms_error_string); /*lint !e534 ignoring return value */ + trace_i2c("VL53L1_CommsInitialise: RANGING_SENSOR_COMMS_Init_SPI_V2W8() failed\n"); + trace_i2c(comms_error_string); + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } + else + { + trace_i2c("VL53L1_CommsInitialise: Comms must be one of VL53L1_I2C or VL53L1_SPI\n"); + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + + return status; +} + + +VL53L1_Error VL53L1_CommsClose( + VL53L1_Dev_t *pdev) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + char comms_error_string[ERROR_TEXT_LENGTH]; + + SUPPRESS_UNUSED_WARNING(pdev); + + if(global_comms_type == VL53L1_I2C) + { + if((CP_STATUS)RANGING_SENSOR_COMMS_Fini_CCI() != CP_STATUS_OK) + { + RANGING_SENSOR_COMMS_Get_Error_Text(comms_error_string); /*lint !e534 ignoring return value */ + trace_i2c("VL53L1_CommsClose: RANGING_SENSOR_COMMS_Fini_CCI() failed\n"); + trace_i2c(comms_error_string); + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } + else if(global_comms_type == VL53L1_SPI) + { + if((CP_STATUS)RANGING_SENSOR_COMMS_Fini_SPI_V2W8() != CP_STATUS_OK) + { + RANGING_SENSOR_COMMS_Get_Error_Text(comms_error_string); /*lint !e534 ignoring return value */ + trace_i2c("VL53L1_CommsClose: RANGING_SENSOR_COMMS_Fini_SPI_V2W8() failed\n"); + trace_i2c(comms_error_string); + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } + else + { + trace_i2c("VL53L1_CommsClose: Comms must be one of VL53L1_I2C or VL53L1_SPI\n"); + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + + return status; +} + +/* + * ----------------- COMMS FUNCTIONS ----------------- + */ + +VL53L1_Error VL53L1_WriteMulti( + VL53L1_Dev_t *pdev, + uint16_t index, + uint8_t *pdata, + uint32_t count) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + uint32_t position = 0; + uint32_t data_size = 0; + + char comms_error_string[ERROR_TEXT_LENGTH]; + + _LOG_STRING_BUFFER(register_name); + _LOG_STRING_BUFFER(value_as_str); + + if(global_comms_type == VL53L1_I2C) + { + for(position=0; position VL53L1_COMMS_CHUNK_SIZE) + { + if((position + VL53L1_COMMS_CHUNK_SIZE) > count) + { + data_size = count - position; + } + else + { + data_size = VL53L1_COMMS_CHUNK_SIZE; + } + } + else + { + data_size = count; + } + + if (status == VL53L1_ERROR_NONE) + { + if( RANGING_SENSOR_COMMS_Write_CCI( + pdev->i2c_slave_address, + 0, + index+position, + pdata+position, + data_size) != 0 ) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } + +#ifdef VL53L1_LOG_ENABLE + if (status == VL53L1_ERROR_NONE) { + char* pvalue_as_str; + uint32_t i; + + /*lint --e{661} Suppress out of bounds walkthrough warning */ + /*lint --e{662} Suppress out of bounds walkthrough warning */ + + // Build value as string; + pvalue_as_str = value_as_str; + for(i = 0 ; i < data_size ; i++) + { + sprintf(pvalue_as_str, ", 0x%02X", *(pdata+position+i)); + pvalue_as_str = pvalue_as_str + 6; + } + + register_name[0] = 0; + VL53L1_get_register_name( + index+(uint16_t)position, + register_name); + + trace_i2c( + /* "WriteAutoIncrement(0x%04X%s); // %3u bytes\n", + index+(uint16_t)position, */ + "WriteAutoIncrement(%s%s); // %3u bytes\n", + register_name, + value_as_str, + data_size); + } +#endif // VL53L1_LOG_ENABLE + } + + if(status != VL53L1_ERROR_NONE) + { + RANGING_SENSOR_COMMS_Get_Error_Text(comms_error_string); /*lint !e534 ignoring return value */ + trace_i2c("VL53L1_WriteMulti RANGING_SENSOR_COMMS_Write_CCI() failed\n"); + trace_i2c(comms_error_string); + } + } + else if(global_comms_type == VL53L1_SPI) + { + if((CP_STATUS)RANGING_SENSOR_COMMS_Write_SPI_16I(0, 0, index, pdata, count) != CP_STATUS_OK) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + + if(status != VL53L1_ERROR_NONE) + { + RANGING_SENSOR_COMMS_Get_Error_Text(comms_error_string); /*lint !e534 ignoring return value */ + trace_i2c("VL53L1_WriteMulti RANGING_SENSOR_COMMS_Write_SPI_16I() failed\n"); + trace_i2c(comms_error_string); + } + } + else + { + trace_i2c("VL53L1_WriteMulti: Comms must be one of VL53L1_I2C or VL53L1_SPI\n"); + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + + return status; +} + + +VL53L1_Error VL53L1_ReadMulti( + VL53L1_Dev_t *pdev, + uint16_t index, + uint8_t *pdata, + uint32_t count) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + uint32_t position = 0; + uint32_t data_size = 0; + + char comms_error_string[ERROR_TEXT_LENGTH]; + + _LOG_STRING_BUFFER(register_name); + _LOG_STRING_BUFFER(value_as_str); + + if(global_comms_type == VL53L1_I2C) + { + for(position=0; position VL53L1_COMMS_CHUNK_SIZE) + { + if((position + VL53L1_COMMS_CHUNK_SIZE) > count) + { + data_size = count - position; + } + else + { + data_size = VL53L1_COMMS_CHUNK_SIZE; + } + } + else + data_size = count; + + if(status == VL53L1_ERROR_NONE) + { + if( RANGING_SENSOR_COMMS_Read_CCI( + pdev->i2c_slave_address, + 0, + index+position, + pdata+position, + data_size) != 0 ) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } +#ifdef VL53L1_LOG_ENABLE + if(status == VL53L1_ERROR_NONE) + { + char* pvalue_as_str; + uint32_t i; + + /*lint --e{661} Suppress out of bounds walkthrough warning */ + /*lint --e{662} Suppress out of bounds walkthrough warning */ + pvalue_as_str = value_as_str; + for(i = 0 ; i < data_size ; i++) { + sprintf(pvalue_as_str, "0x%02X", *(pdata+position+i)); + if (i == 0) { + pvalue_as_str = pvalue_as_str + 4; + } + else { + pvalue_as_str = pvalue_as_str + 6; + } + } + + register_name[0] = 0; + VL53L1_get_register_name( + index+(uint16_t)position, + register_name); + + trace_i2c( + /* "ReadAutoIncrement(0x%04X,%3u); // = (%s)\n", + index+(uint16_t)position, */ + "ReadAutoIncrement(%s,%3u); // = (%s)\n", + register_name, + data_size, + value_as_str); + } +#endif // VL53L1_LOG_ENABLE + } + + if(status != VL53L1_ERROR_NONE) + { + RANGING_SENSOR_COMMS_Get_Error_Text(comms_error_string); /*lint !e534 ignoring return value */ + trace_i2c("VL53L1_ReadMulti: RANGING_SENSOR_COMMS_Read_CCI() failed\n"); + trace_i2c(comms_error_string); + } + } + else if(global_comms_type == VL53L1_SPI) + { + if((CP_STATUS)RANGING_SENSOR_COMMS_Read_SPI_16I(0, 0, index, pdata, count) != CP_STATUS_OK) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + + if(status != VL53L1_ERROR_NONE) + { + RANGING_SENSOR_COMMS_Get_Error_Text(comms_error_string); /*lint !e534 ignoring return value */ + trace_i2c("VL53L1_ReadMulti: RANGING_SENSOR_COMMS_Read_SPI_16I() failed\n"); + trace_i2c(comms_error_string); + } + } + else + { + trace_i2c("VL53L1_ReadMulti: Comms must be one of VL53L1_I2C or VL53L1_SPI\n"); + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + + return status; +} + + +VL53L1_Error VL53L1_WrByte( + VL53L1_Dev_t *pdev, + uint16_t index, + uint8_t data) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t buffer[1]; + + // Split 16-bit word into MS and LS uint8_t + buffer[0] = (uint8_t)(data); + + status = VL53L1_WriteMulti(pdev, index, buffer, 1); + + return status; +} + + +VL53L1_Error VL53L1_WrWord( + VL53L1_Dev_t *pdev, + uint16_t index, + uint16_t data) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t buffer[2]; + + // Split 16-bit word into MS and LS uint8_t + buffer[0] = (uint8_t)(data >> 8); + buffer[1] = (uint8_t)(data & 0x00FF); + + status = VL53L1_WriteMulti(pdev, index, buffer, VL53L1_BYTES_PER_WORD); + + return status; +} + + +VL53L1_Error VL53L1_WrDWord( + VL53L1_Dev_t *pdev, + uint16_t index, + uint32_t data) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t buffer[4]; + + // Split 32-bit word into MS ... LS bytes + buffer[0] = (uint8_t) (data >> 24); + buffer[1] = (uint8_t)((data & 0x00FF0000) >> 16); + buffer[2] = (uint8_t)((data & 0x0000FF00) >> 8); + buffer[3] = (uint8_t) (data & 0x000000FF); + + status = VL53L1_WriteMulti(pdev, index, buffer, VL53L1_BYTES_PER_DWORD); + + return status; +} + + +VL53L1_Error VL53L1_RdByte( + VL53L1_Dev_t *pdev, + uint16_t index, + uint8_t *pdata) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t buffer[1]; + + status = VL53L1_ReadMulti(pdev, index, buffer, 1); + + *pdata = buffer[0]; + + return status; +} + + +VL53L1_Error VL53L1_RdWord( + VL53L1_Dev_t *pdev, + uint16_t index, + uint16_t *pdata) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t buffer[2]; + + status = VL53L1_ReadMulti( + pdev, + index, + buffer, + VL53L1_BYTES_PER_WORD); + + *pdata = (uint16_t)(((uint16_t)(buffer[0])<<8) + (uint16_t)buffer[1]); + + return status; +} + + +VL53L1_Error VL53L1_RdDWord( + VL53L1_Dev_t *pdev, + uint16_t index, + uint32_t *pdata) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + uint8_t buffer[4]; + + status = VL53L1_ReadMulti( + pdev, + index, + buffer, + VL53L1_BYTES_PER_DWORD); + + *pdata = ((uint32_t)buffer[0]<<24) + ((uint32_t)buffer[1]<<16) + ((uint32_t)buffer[2]<<8) + (uint32_t)buffer[3]; + + return status; +} + +/* + * ----------------- HOST TIMING FUNCTIONS ----------------- + */ + +VL53L1_Error VL53L1_WaitUs( + VL53L1_Dev_t *pdev, + int32_t wait_us) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + float wait_ms = (float)wait_us/1000.0f; /*lint !e586 float in windows platform*/ + HANDLE hEvent = CreateEvent(0, TRUE, FALSE, 0); + + SUPPRESS_UNUSED_WARNING(pdev); + + /* + * Use windows event handling to perform non-blocking wait. + */ + WaitForSingleObject(hEvent, (DWORD)(wait_ms + 0.5f)); /*lint !e534 ignoring return value */ + + trace_i2c("WaitUs(%6d);\n", wait_us); + + return status; +} + + +VL53L1_Error VL53L1_WaitMs( + VL53L1_Dev_t *pdev, + int32_t wait_ms) +{ + return VL53L1_WaitUs(pdev, wait_ms * 1000); +} + +/* + * ----------------- DEVICE TIMING FUNCTIONS ----------------- + */ + +VL53L1_Error VL53L1_GetTimerFrequency(int32_t *ptimer_freq_hz) +{ + *ptimer_freq_hz = 0; + + trace_print(VL53L1_TRACE_LEVEL_INFO, "VL53L1_GetTimerFrequency: Freq : %dHz\n", *ptimer_freq_hz); + return VL53L1_ERROR_NONE; +} + + +VL53L1_Error VL53L1_GetTimerValue(int32_t *ptimer_count) +{ + *ptimer_count = 0; + + trace_print(VL53L1_TRACE_LEVEL_INFO, "VL53L1_GetTimerValue: Freq : %dHz\n", *ptimer_count); + return VL53L1_ERROR_NONE; +} + + +/* + * ----------------- GPIO FUNCTIONS ----------------- + */ + +VL53L1_Error VL53L1_GpioSetMode(uint8_t pin, uint8_t mode) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + if((CP_STATUS)RANGING_SENSOR_COMMS_GPIO_Set_Mode((RS_GPIO_Pin)pin, (RS_GPIO_Mode)mode) != CP_STATUS_OK) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + + trace_print(VL53L1_TRACE_LEVEL_INFO, "VL53L1_GpioSetMode: Status %d. Pin %d, Mode %d\n", status, pin, mode); + return status; +} + + +VL53L1_Error VL53L1_GpioSetValue(uint8_t pin, uint8_t value) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + if((CP_STATUS)RANGING_SENSOR_COMMS_GPIO_Set_Value((RS_GPIO_Pin)pin, value) != CP_STATUS_OK) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + + trace_print(VL53L1_TRACE_LEVEL_INFO, "VL53L1_GpioSetValue: Status %d. Pin %d, Mode %d\n", status, pin, value); + return status; + +} + + +VL53L1_Error VL53L1_GpioGetValue(uint8_t pin, uint8_t *pvalue) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + DWORD value = 0; + + if((CP_STATUS)RANGING_SENSOR_COMMS_GPIO_Get_Value((RS_GPIO_Pin)pin, &value) != CP_STATUS_OK) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + else + { + *pvalue = (uint8_t)value; + } + + trace_print(VL53L1_TRACE_LEVEL_INFO, "VL53L1_GpioGetValue: Status %d. Pin %d, Mode %d\n", status, pin, *pvalue); + return status; +} + +/* + * ----------------- HARDWARE STATE FUNCTIONS ----------------- + */ + +VL53L1_Error VL53L1_GpioXshutdown(uint8_t value) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + if(status == VL53L1_ERROR_NONE) /*lint !e774 always true */ + { + status = VL53L1_GpioSetMode((uint8_t)GPIO_XSHUTDOWN, (uint8_t)GPIO_OutputPP); + } + + if(status == VL53L1_ERROR_NONE) + { + if(value) + { + if ((CP_STATUS)RANGING_SENSOR_COMMS_GPIO_Set_Value(GPIO_XSHUTDOWN, (DWORD)Pin_State_High) != CP_STATUS_OK) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } + else + { + if ((CP_STATUS)RANGING_SENSOR_COMMS_GPIO_Set_Value(GPIO_XSHUTDOWN, (DWORD)Pin_State_Low) != CP_STATUS_OK) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } + } + + trace_print(VL53L1_TRACE_LEVEL_INFO, "VL53L1_GpioXShutdown: Status %d. Value %d\n", status, value); + return status; +} + + +VL53L1_Error VL53L1_GpioCommsSelect(uint8_t value) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + if(status == VL53L1_ERROR_NONE) /*lint !e774 always true */ + { + status = VL53L1_GpioSetMode((uint8_t)GPIO_SPI_CHIP_SELECT, (uint8_t)GPIO_OutputPP); + } + + if(status == VL53L1_ERROR_NONE) + { + if(value) + { + if((CP_STATUS)RANGING_SENSOR_COMMS_GPIO_Set_Value(GPIO_SPI_CHIP_SELECT, (DWORD)Pin_State_High) != CP_STATUS_OK) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } + else + { + if((CP_STATUS)RANGING_SENSOR_COMMS_GPIO_Set_Value(GPIO_SPI_CHIP_SELECT, (DWORD)Pin_State_Low) != CP_STATUS_OK) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } + } + + trace_print(VL53L1_TRACE_LEVEL_INFO, "VL53L1_GpioCommsSelect: Status %d. Value %d\n", status, value); + return status; +} + + +VL53L1_Error VL53L1_GpioPowerEnable(uint8_t value) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + POWER_BOARD_CMD power_cmd; + + if(status == VL53L1_ERROR_NONE) /*lint !e774 always true */ + { + status = VL53L1_GpioSetMode((uint8_t)GPIO_POWER_ENABLE, (uint8_t)GPIO_OutputPP); + } + + if(status == VL53L1_ERROR_NONE) + { + if(value) + { + if((CP_STATUS)RANGING_SENSOR_COMMS_GPIO_Set_Value(GPIO_POWER_ENABLE, (DWORD)Pin_State_High) != CP_STATUS_OK) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } + else + { + if((CP_STATUS)RANGING_SENSOR_COMMS_GPIO_Set_Value(GPIO_POWER_ENABLE, (DWORD)Pin_State_Low) != CP_STATUS_OK) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } + } + + if(status == VL53L1_ERROR_NONE && _power_board_in_use == 1 && value) /*lint !e506 !e845 !e774*/ + { + memset(&power_cmd, 0, sizeof(POWER_BOARD_CMD)); + power_cmd.command = ENABLE_DUT_POWER; + + if((CP_STATUS)RANGING_SENSOR_COMMS_Write_System_I2C( + POWER_BOARD_I2C_ADDRESS, sizeof(POWER_BOARD_CMD), (uint8_t*)&power_cmd) != CP_STATUS_OK) + { + status = VL53L1_ERROR_CONTROL_INTERFACE; + } + } + + trace_print(VL53L1_TRACE_LEVEL_INFO, "VL53L1_GpioPowerEnable: Status %d. Value %d\n", status, value); + return status; +} + + +VL53L1_Error VL53L1_GpioInterruptEnable(void (*function)(void), uint8_t edge_type) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + SUPPRESS_UNUSED_WARNING(function); + SUPPRESS_UNUSED_WARNING(edge_type); + + return status; +} + + +VL53L1_Error VL53L1_GpioInterruptDisable(void) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + return status; +} + + +VL53L1_Error VL53L1_GetTickCount( + uint32_t *ptick_count_ms) +{ + + /* Returns current tick count in [ms] */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + *ptick_count_ms = timeGetTime(); + + trace_print( + VL53L1_TRACE_LEVEL_DEBUG, + "VL53L1_GetTickCount() = %5u ms;\n", + *ptick_count_ms); + + return status; + +} + + +VL53L1_Error VL53L1_WaitValueMaskEx( + VL53L1_Dev_t *pdev, + uint32_t timeout_ms, + uint16_t index, + uint8_t value, + uint8_t mask, + uint32_t poll_delay_ms) +{ + /* + * Platform implementation of WaitValueMaskEx V2WReg script command + * + * WaitValueMaskEx( + * duration_ms, + * index, + * value, + * mask, + * poll_delay_ms); + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint32_t start_time_ms = 0; + uint32_t current_time_ms = 0; + uint8_t byte_value = 0; + uint8_t found = 0; +#ifdef VL53L1_LOG_ENABLE + uint32_t trace_functions = 0; +#endif + + _LOG_STRING_BUFFER(register_name); + + SUPPRESS_UNUSED_WARNING(poll_delay_ms); + +#ifdef VL53L1_LOG_ENABLE + /* look up register name */ + VL53L1_get_register_name( + index, + register_name); + + /* Output to I2C logger for FMT/DFT */ + trace_i2c("WaitValueMaskEx(%5d, %s, 0x%02X, 0x%02X, %5d);\n", + timeout_ms, register_name, value, mask, poll_delay_ms); +#endif // VL53L1_LOG_ENABLE + + /* calculate time limit in absolute time */ + + VL53L1_GetTickCount(&start_time_ms); + pdev->new_data_ready_poll_duration_ms = 0; + + /* remember current trace functions and temporarily disable + * function logging + */ + +#ifdef VL53L1_LOG_ENABLE + trace_functions = _LOG_GET_TRACE_FUNCTIONS(); +#endif + _LOG_SET_TRACE_FUNCTIONS(VL53L1_TRACE_FUNCTION_NONE); + + /* wait until value is found, timeout reached on error occurred */ + + while ((status == VL53L1_ERROR_NONE) && + (pdev->new_data_ready_poll_duration_ms < timeout_ms) && + (found == 0)) + { + status = VL53L1_RdByte( + pdev, + index, + &byte_value); + + if ((byte_value & mask) == value) + { + found = 1; + } + + /*if (status == VL53L1_ERROR_NONE && + found == 0 && + poll_delay_ms > 0) + status = VL53L1_WaitMs( + pdev, + poll_delay_ms); + */ + + /* Update polling time (Compare difference rather than absolute to + negate 32bit wrap around issue) */ + VL53L1_GetTickCount(¤t_time_ms); + pdev->new_data_ready_poll_duration_ms = current_time_ms - start_time_ms; + } + + /* Restore function logging */ + _LOG_SET_TRACE_FUNCTIONS(trace_functions); + + if (found == 0 && status == VL53L1_ERROR_NONE) + status = VL53L1_ERROR_TIME_OUT; + + return status; +} + diff --git a/App/VL53L1X_API/platform/src/vl53l1_platform_init.c b/App/VL53L1X_API/platform/src/vl53l1_platform_init.c new file mode 100644 index 0000000..ded7370 --- /dev/null +++ b/App/VL53L1X_API/platform/src/vl53l1_platform_init.c @@ -0,0 +1,128 @@ +/******************************************************************************* + Copyright (C) 2016, STMicroelectronics International N.V. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of STMicroelectronics nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND + NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. + IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +/** + * @file vl53l1_platform_init.c + * @brief EwokPlus25 comms and GPIO init + * + */ + + +#include "vl53l1_ll_def.h" +#include "vl53l1_platform.h" +#include "vl53l1_platform_init.h" + + +VL53L1_Error VL53L1_platform_init( + VL53L1_Dev_t *pdev, + uint8_t i2c_slave_address, + uint8_t comms_type, + uint16_t comms_speed_khz) +{ + /* + * Initialise comms, GPIOs (xshutdown, ncs, EVK power regulator enable) + * and reset Device + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + /* remember comms settings */ + + pdev->i2c_slave_address = i2c_slave_address; + pdev->comms_type = comms_type; + pdev->comms_speed_khz = comms_speed_khz; + + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = + VL53L1_CommsInitialise( + pdev, + pdev->comms_type, + pdev->comms_speed_khz); + + /* Ensure device is in reset */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_GpioXshutdown(0); + + /* disable the platform regulators */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_GpioPowerEnable(0); + + /* set the NCS pin for I2C mode */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_GpioCommsSelect(0); + + /* 1ms Wait to ensure XSHUTD / NCS are in the right state */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WaitUs(pdev, 1000); + + /* enable the platform regulators */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_GpioPowerEnable(1); + + /* 1ms Wait for power regs to settle */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WaitUs(pdev, 1000); + + /* finally, bring the device out of reset */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_GpioXshutdown(1); + + /* Wait 100us for device to exit reset */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_WaitUs(pdev, 100); + + return status; +} + + +VL53L1_Error VL53L1_platform_terminate( + VL53L1_Dev_t *pdev) +{ + /* + * Puts the device into reset, disables EVK power regulator + * and closes comms + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + /* put device in reset */ + if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/ + status = VL53L1_GpioXshutdown(0); + + /* disable the platform regulators */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_GpioPowerEnable(0); + + /* close the comms interfaces */ + if (status == VL53L1_ERROR_NONE) + status = VL53L1_CommsClose(pdev); + + return status; +} + + diff --git a/App/VL53L1X_API/platform/src/vl53l1_platform_log.c b/App/VL53L1X_API/platform/src/vl53l1_platform_log.c new file mode 100644 index 0000000..f627d3d --- /dev/null +++ b/App/VL53L1X_API/platform/src/vl53l1_platform_log.c @@ -0,0 +1,131 @@ +/* + * COPYRIGHT (C) STMicroelectronics 2015. All rights reserved. + * + * This software is the confidential and proprietary information of + * STMicroelectronics ("Confidential Information"). You shall not + * disclose such Confidential Information and shall use it only in + * accordance with the terms of the license agreement you entered into + * with STMicroelectronics + * + * Programming Golden Rule: Keep it Simple! + * + */ + +/** + * @file vl53l1_platform_log.c + * + * @brief Code function definitions for EwokPlus25 Platform Logging Layer + */ + +#include // sprintf(), vsnprintf(), printf() +#include +#include +#include + +#include "vl53l1_platform_log.h" +#include "vl53l1_platform_user_config.h" + +#ifdef VL53L1_LOG_ENABLE + + char * _trace_filename = NULL; + FILE *_tracefile = NULL; + + uint32_t _trace_level = VL53L1_TRACE_LEVEL_WARNING; + uint32_t _trace_modules = VL53L1_TRACE_MODULE_NONE; + uint32_t _trace_functions = VL53L1_TRACE_FUNCTION_ALL; + + int8_t VL53L1_trace_config( + char *filename, + uint32_t modules, + uint32_t level, + uint32_t functions) + { + int8_t status = 0; + + // // Something in the commented out code below causes ncsim to crash! + // + // if (((_trace_filename != NULL) && (_trace_filename != filename)) ||strcmp(filename,"")==0) + // { + // if ( _tracefile != NULL ) + // { + // fclose(_tracefile); + // _tracefile = NULL; + // } + // free(_trace_filename); + // _trace_filename = NULL; + // } + // + + if (((filename != NULL) && (_tracefile == NULL)) && strcmp(filename,"")) + { + _tracefile = fopen(filename, "w+"); + + //TODO: Add time and header banner to the log file to indicate we've just opened a new log session + + if ( _tracefile != NULL ) + { + _trace_filename = (char*)malloc((strlen(filename) + 1) * sizeof(char)); + strcpy(_trace_filename, filename); + } + else + { + printf("VL53L1_trace_config(): failed to open log file (%s)\n", filename); + status = 1; + } + } + + _trace_modules = modules; + _trace_level = level; + _trace_functions = functions; + + return status; + } + + void VL53L1_trace_print_module_function(uint32_t module, uint32_t level, uint32_t function, const char *format, ...) + { + if ( ((level <=_trace_level) && ((module & _trace_modules) > 0)) + || ((function & _trace_functions) > 0) ) + { + va_list arg_list; + char message[VL53L1_MAX_STRING_LENGTH]; + + va_start(arg_list, format); + vsnprintf(message, VL53L1_MAX_STRING_LENGTH-1, format, arg_list); /*lint !e534 ignore return*/ + va_end(arg_list); + + if (_tracefile != NULL) + { + fprintf(_tracefile, message); /*lint !e592 ignore format specifier*/ + } + else + { + printf(message); /*lint !e592 ignore format specifier*/ + } + + // if (_tracefile != NULL) + // fprintf(_tracefile, message); + // else + // printf(message); + } /*lint !e438 ignore issues with arg_list*/ + } + + + uint32_t VL53L1_get_trace_functions(void) + { + return _trace_functions; + } + + + void VL53L1_set_trace_functions(uint32_t function) + { + _trace_functions = function; + } + + + uint32_t VL53L1_clock(void) + { + /* Returns current tick count in [ms] */ + uint32_t tick_count_ms = (uint32_t)clock(); + return tick_count_ms; + } +#endif // VL53L1_LOG_ENABLE diff --git a/Doc/近墙猛修问题.md b/Doc/近墙猛修问题.md new file mode 100644 index 0000000..59a3da4 --- /dev/null +++ b/Doc/近墙猛修问题.md @@ -0,0 +1,133 @@ +# 近墙猛修问题记录 + +## 现象 + +- 在两侧均为约 `40cm` 墙壁的测试环境中,只要车辆初始摆位明显偏向某一侧,就会出现明显的向另一侧猛打方向现象。 +- 具体表现为: +- 车身非常靠近左侧墙时,会明显向右转。 +- 车身非常靠近右侧墙时,会明显向左转。 +- 当距离墙面非常近时,修正会过猛,看起来像“突然拧过去”。 + +## 当前判断 + +- “靠左往右修、靠右往左修”这个方向关系本身是符合居中控制逻辑的,不是转向方向定义反了。 +- 真正的问题在于:侧向 VL53 在近墙区域的观测仍然被当作可信几何信息使用,导致横向误差 `e_y` 被一次性拉得过大,控制器再把这个大误差直接转换成较大的转向角速度。 +- 因此,当前故障更接近“近墙观测过激 -> 状态估计偏大 -> 控制输出过猛”,而不是“状态机无故乱转”。 + +## 代码链路 + +### 1. 侧向 VL53 近墙仍可能被判有效 + +文件:`App/preproc/corridor_preproc.h` + +- 当前侧向最小有效距离为:`PREPROC_MIN_SIDE_RANGE_M = 0.02f` +- 也就是只要大于 `2cm`,观测就可能继续进入后续 EKF。 + +这对 40cm 通道、20cm 车体来说偏激进,因为车辆一旦贴边,`2cm ~ 3cm` 这个区间很容易出现安装偏差、角度误差、近距非线性等问题。 + +### 2. EKF 直接把侧向距离变成横向偏差观测 + +文件:`App/est/corridor_ekf.c` + +核心逻辑: + +```c +float d_center = (W - Rw) / 2.0f + inset; + +if (left_ok) { + z_ey += d_center - ((d_lf + d_lr) / 2.0f) - yoff; +} + +if (right_ok) { + z_ey += ((d_rf + d_rr) / 2.0f) - d_center - yoff; +} +``` + +- 在当前参数下,理论居中时单侧读数大约为 `0.10m`。 +- 如果左侧因为近墙读到 `0.02m ~ 0.03m`,则 `z_ey` 会立刻表现为“明显偏左”,量级可达数厘米。 +- 只要该观测没有被马氏距离检验拒绝,就会被吸收到状态 `e_y` 中。 + +### 3. 控制器直接用 `e_y` 生成转向命令 + +文件:`App/nav/corridor_ctrl.c` + +```c +float w_cmd = -(s_cfg.kp_theta * state->e_th + + s_cfg.kd_theta * imu_wz + + s_cfg.kp_y * state->e_y); +``` + +- 当 `e_y` 被近墙观测拉得过大时,`w_cmd` 会立刻增大。 +- 因此表现出来就是: +- 贴左墙时明显向右修。 +- 贴右墙时明显向左修。 +- 靠得非常近时会“修得过猛”。 + +## 为什么这不是“方向反了” + +- 如果控制方向反了,现象应该是:靠左还继续往左,靠右还继续往右。 +- 实际观测恰好相反,说明控制方向是对的,只是近墙时误差量级过大。 + +## 与此前“上电就左转/右转”的关系 + +- 之前怀疑过状态机提前切换、IMU 保直、前向激光异常等路径。 +- 结合实车现象后,当前更值得优先处理的是: +- 车辆一旦被放在明显偏向某一侧的位置,系统会把它当成正常走廊纠偏问题来处理。 +- 当侧向 VL53 处于近墙区时,这个纠偏会被放大得过于激进。 + +这意味着当前问题更像“近墙过激纠偏”,而不是“无条件自主转向”。 + +## 高概率根因 + +1. 侧向 VL53 的最小可信距离阈值过低,近墙失真数据仍被当作有效观测。 +2. EKF 对单拍横向观测 `z_ey` 缺少足够的近墙限幅或退化策略。 +3. 控制层对“近墙高风险状态”没有额外保险,导致 `e_y` 一大就直接猛打方向。 + +## 建议修复方向 + +### 方案 A:预处理层加近墙保护 + +- 提高侧向最小可信距离阈值,不再把极近距离观测直接当正常数据使用。 +- 或新增“近墙退化区”,在该区间内降低观测可信度,而不是简单二值有效/无效。 + +这是最前面的止血点。 + +### 方案 B:EKF 观测限幅 + +- 对 `z_ey` 或单拍新息 `y_ey` 增加限幅。 +- 防止单次近墙异常读数把 `e_y` 猛拉到过大值。 + +这是最直接针对“状态一下被拉偏”的修复。 + +### 方案 C:控制层保险 + +- 在近墙状态下限制 `w_cmd` 的幅度或变化速度。 +- 同时降低线速度,避免“边贴墙边急拧”。 + +这是最后一道保险,不应单独依赖,但建议保留。 + +## 建议优先级 + +1. 预处理层近墙保护 +2. EKF 横向观测限幅 +3. 控制层近墙保险 + +## 建议调试观测量 + +后续复现时建议同步观察以下量: + +- 四颗侧向 VL53 原始距离 +- `obs.valid_mask` +- `obs.d_lf / d_lr / d_rf / d_rr` +- `corridor_state.e_y` +- `corridor_state.e_th` +- `raw_cmd.w` +- `safe_w` + +重点确认: + +- 近墙时是否有某一侧距离突然跌到极小值。 +- `e_y` 是否在同一时刻明显跃迁。 +- `raw_cmd.w` 是否跟着立刻增大。 + +如果这三者时间上连续对应,就可以基本坐实当前分析。 diff --git a/修改建议报告.md b/修改建议报告.md new file mode 100644 index 0000000..74248bf --- /dev/null +++ b/修改建议报告.md @@ -0,0 +1,243 @@ +# CAN/里程计频率修改建议报告 + +## 1. 结论 + +建议采用以下组合修改,而不是单独只改一边: + +1. 下位机 `FDR-Core` 将 `0x200 Odom Delta` 从当前约 `60ms` 提升到 `20ms` 固定发送。 +2. 上位机 `ARES` 将 `0x200` 的消费与 `Odom_Update()` 从 `monitorTask(100ms)` 挪到 `navTask(20ms)`。 +3. `0x182/0x183` 保持低频轮询即可,不需要跟着一起提到 `20ms`。 +4. 当前阶段不建议把 `0x200` 进一步提到 `10ms`,先做到 `20ms` 即可。 + +一句话概括:当前 odom 不够实时,不是总线带宽不够,而是“下位机发送慢 + 上位机消费慢”叠加导致的;最合适的修法是把两端都对齐到 `20ms`。 + +## 2. 本次核对到的事实 + +### 2.1 下位机当前真实行为 + +下位机工程:`C:\Users\Falling_jasmine\CLionProjects\FDR-Core` + +实际实现文件:`Core/Src/f4_can_app.c` + +关键实现如下: + +1. `CAN_Send_Telemetry_20ms()` 每 `20ms` 调一次。 +2. `0x181` 状态帧固定每次都发。 +3. `0x182 / 0x183 / 0x200` 通过 `s_telem_slot` 三选一轮询发送。 +4. 所以 `0x200` 实际发送周期约为 `60ms`,不是 `20ms`。 +5. `0x184` 通过 `s_comm_diag_divider` 每 `100ms` 发送一次。 + +对应代码位置: + +1. `C:\Users\Falling_jasmine\CLionProjects\FDR-Core\Core\Src\f4_can_app.c:925-966` +2. `C:\Users\Falling_jasmine\CLionProjects\FDR-Core\Core\Src\f4_can_app.c:907-923` + +另外,下位机头文件注释和实际实现已经出现漂移: + +1. `f4_can_app.h` 注释写的是 `0x181/0x182/0x183/0x200` 都在 `20ms` 周期发送。 +2. 但真实代码并不是这样,而是只有 `0x181` 固定 `20ms`。 + +对应位置: + +1. `C:\Users\Falling_jasmine\CLionProjects\FDR-Core\Core\Inc\f4_can_app.h:165-173` +2. `C:\Users\Falling_jasmine\CLionProjects\FDR-Core\Core\Src\f4_can_app.c:925-966` + +### 2.2 下位机 odom 数据源没有问题 + +下位机 `motor.c` 中,编码器增量在控制周期中持续累加到 `s_odom_acc_ticks[]`: + +1. 每次电机更新时都会把四轮增量累加到 odom 累加器。 +2. `CAN_Send_OdomFrame()` 发送 `0x200` 时,通过 `Motor_Get_And_Clear_Delta_Ticks()` 原子取走并清零。 + +这说明: + +1. `0x200` 本质是“自上次发送以来的积分增量”。 +2. 如果把 `0x200` 发送频率从 `60ms` 提高到 `20ms`,语义仍然正确,只是每帧覆盖的时间窗变短、实时性更高。 + +对应位置: + +1. `C:\Users\Falling_jasmine\CLionProjects\FDR-Core\Core\Src\motor.c:225-245` +2. `C:\Users\Falling_jasmine\CLionProjects\FDR-Core\Core\Src\motor.c:263-295` +3. `C:\Users\Falling_jasmine\CLionProjects\FDR-Core\Core\Src\f4_can_app.c:907-923` + +### 2.3 上位机当前真实行为 + +上位机工程:`D:\ARES` + +当前 `0x200` 的消费模型是: + +1. CAN ISR 收到每帧 `0x200` 后,不直接覆盖,而是累加到 `odom_accum`。 +2. `monitorTask` 每 `100ms` 调用 `SNC_CAN_ConsumeOdomDelta()` 原子取走累计值。 +3. 然后再调用 `Odom_Update()` 推送黑板。 +4. `navTask` 本身跑在 `20ms`,但它读到的 `board.odom_vx` 很多拍都是旧值。 + +对应位置: + +1. `D:\ARES\App\Can\snc_can_app.c:185-225` +2. `D:\ARES\App\app_tasks.c:145-167` +3. `D:\ARES\App\app_tasks.c:295-340` + +## 3. 问题本质 + +当前 odom 实时性差,来自两个串联环节: + +1. 下位机发送 `0x200` 只有约 `60ms` 一次。 +2. 上位机又只在 `100ms` 的 `monitorTask` 中消费一次。 + +所以当前 `odom_vx` 的有效刷新节拍,不是 `navTask` 的 `20ms`,而是被这两个环节一起拖慢了。 + +这会直接影响: + +1. `CorridorEKF_Predict()` 中 `odom_vx` 的实时性。 +2. 沿程 `s` 的连续性。 +3. 车体加减速或转向阶段时,状态传播的平滑度。 + +## 4. 是否需要把 CAN 提得更高频 + +当前不建议先追求高于 `20ms` 的 CAN 频率。 + +原因: + +1. 上位机 `navTask` / EKF 当前就是 `20ms / 50Hz`。 +2. `0x100` 速度命令协议推荐节拍也是 `20ms`。 +3. `0x200` 先做到 `20ms`,就已经与主导航闭环对齐。 +4. 再往 `10ms` 提,边际收益明显变小,且会引入更多调度与验证成本。 + +在你当前系统中,更合理的目标是: + +1. `0x100` 保持 `20ms` +2. `0x181` 保持 `20ms` +3. `0x200` 提到 `20ms` +4. `0x182/0x183/0x184` 维持低频 + +## 5. 总线负载是否会成为问题 + +基于你补充的信息:总线上只有两个单片机,且 CAN 速率为 `1 Mbps`。 + +在这个前提下,把 `0x200` 提到 `20ms` 是合理的,风险较低。 + +主要原因: + +1. 当前实时关键帧就只有 `0x100`、`0x181`、`0x200`。 +2. 即便这三类帧都在 `20ms` 发送,总线占用通常仍远低于饱和。 +3. 下位机当前发送代码本身也把遥测帧视为“允许丢”的低优先级消息,不会因短时发不出去而阻塞主循环。 + +对应代码: + +1. `C:\Users\Falling_jasmine\CLionProjects\FDR-Core\Core\Src\f4_can_app.c:808-821` + +## 6. 推荐修改方案 + +### 6.1 下位机修改建议 + +修改文件: + +1. `C:\Users\Falling_jasmine\CLionProjects\FDR-Core\Core\Src\f4_can_app.c` +2. `C:\Users\Falling_jasmine\CLionProjects\FDR-Core\Core\Inc\f4_can_app.h` + +修改目标: + +1. `0x181` 每 `20ms` 固定发送。 +2. `0x200` 每 `20ms` 固定发送。 +3. `0x182/0x183` 改成低频轮询发送。 +4. `0x184` 继续 `100ms`。 + +最小改法建议如下: + +1. 保留 `CAN_Send_StatusFrame()` 每拍都发。 +2. 在 `CAN_Send_Telemetry_20ms()` 中,每拍额外固定调用 `CAN_Send_OdomFrame()`。 +3. 把原来的 `s_telem_slot` 轮询从 `0x182/0x183/0x200` 三选一,改成只在 `0x182/0x183` 两者之间轮询。 +4. 更新头文件中的注释,避免文档/实现再次漂移。 + +推荐把 `CAN_Send_Telemetry_20ms()` 的逻辑改成: + +1. 先发 `0x181` +2. 再发 `0x200` +3. 再按 slot 发 `0x182` 或 `0x183` +4. 每 5 拍发一次 `0x184` + +这样改的优点: + +1. `0x200` 得到稳定 `20ms` 周期。 +2. `0x182/0x183` 仍然保留,但不抢实时关键链路。 +3. 代码改动很小,不需要碰控制内环和接收协议。 + +### 6.2 上位机修改建议 + +修改文件: + +1. `D:\ARES\App\app_tasks.c` + +修改目标: + +1. `SNC_CAN_ConsumeOdomDelta()` 不再由 `monitorTask(100ms)` 调用。 +2. odom 消费与 `Odom_Update()` 挪到 `navTask(20ms)`。 + +具体建议: + +1. 删除 `AppTasks_RunMonitorTask()` 中 `145-167` 这段 odom 消费代码。 +2. 在 `AppTasks_RunNavTask_Impl()` 中、`Blackboard_GetSnapshot(&board)` 之前插入同样的 odom 消费逻辑。 +3. 保持 `SNC_CAN_ConsumeOdomDelta()` 全系统只有一个消费者。 + +推荐新顺序: + +1. `now_ms = HAL_GetTick()` +2. `SNC_CAN_ConsumeOdomDelta(...)` +3. `Odom_Update(...)` 或 `Odom_HandleTimeout(...)` +4. `Blackboard_GetSnapshot(&board)` +5. `CorridorPreproc_ExtractObs(...)` +6. `CorridorFilter_Update(...)` + +这样可以保证: + +1. `navTask` 每一拍都能第一时间消费已到达的 `0x200`。 +2. 当下位机把 `0x200` 提到 `20ms` 后,上位机不会再被 `100ms monitorTask` 卡住。 + +## 7. 不建议的修改方式 + +### 7.1 只改上位机,不改下位机 + +这样只能把 odom 的消费延迟从 `100ms` 降下来,但 `0x200` 源头仍是约 `60ms`,收益有限。 + +### 7.2 只改下位机,不改上位机 + +这样虽然 `0x200` 更快到达了,但上位机仍在 `100ms` 才取走一次,实时性改善不完整。 + +### 7.3 直接把 `0x200` 提到 `10ms` + +现阶段不建议。原因: + +1. 上位机 `navTask` 仍是 `20ms`。 +2. EKF 和控制链路当前主频也是 `20ms`。 +3. 先把 `20ms` 跑顺、验证完,再决定是否需要更高频更合理。 + +## 8. 推荐实施顺序 + +建议按下面顺序改: + +1. 先改下位机 `f4_can_app.c`,让 `0x200` 固定 `20ms` 发送。 +2. 同步修正下位机 `f4_can_app.h` 注释。 +3. 再改上位机 `app_tasks.c`,把 odom 消费搬进 `navTask`。 +4. 实车或日志确认 `0x200` 到达间隔、`odom_vx` 刷新节拍和 EKF 状态表现。 + +## 9. 验收建议 + +改完后至少验证以下几点: + +1. 上位机收到的 `0x200` 时间戳间隔是否接近 `20ms`。 +2. `SNC_CAN_ConsumeOdomDelta()` 是否只在 `navTask` 被调用一次。 +3. `board.odom_vx` 是否不再长时间停留旧值。 +4. `EKF` 的 `s` 和 `e_y` 传播是否更连续。 +5. `s_can_tx_drop_total` 是否没有明显上升。 +6. `0x181`、`0x184`、`0x100` 协议行为是否保持兼容。 + +## 10. 最终建议 + +最终建议如下: + +1. 下位机把 `0x200` 改成 `20ms` 固定发送。 +2. 上位机把 odom 消费改到 `navTask(20ms)`。 +3. `0x182/0x183` 保持低频,不必提频。 +4. 先不要把 `0x200` 提到 `10ms`。 + +这是当前这两套代码下,改动最小、收益最大、工程风险也最低的方案。