vl6180x_api.c 78 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769
  1. /*******************************************************************************
  2. Copyright © 2015, STMicroelectronics International N.V.
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions are met:
  6. * Redistributions of source code must retain the above copyright
  7. notice, this list of conditions and the following disclaimer.
  8. * Redistributions in binary form must reproduce the above copyright
  9. notice, this list of conditions and the following disclaimer in the
  10. documentation and/or other materials provided with the distribution.
  11. * Neither the name of STMicroelectronics nor the
  12. names of its contributors may be used to endorse or promote products
  13. derived from this software without specific prior written permission.
  14. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  15. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
  17. NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
  18. IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
  19. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  22. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  24. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. ********************************************************************************/
  26. /*
  27. * $Date: 2018-07-04 16:49:57 +0200 (Wed, 04 Jul 2018) $
  28. * $Revision: 2768 $
  29. */
  30. #include "vl6180x_api.h"
  31. #define VL6180x_9to7Conv(x) (x)
  32. /* TODO when set all "cached" value with "default init" are updated after init from register read back */
  33. #define REFRESH_CACHED_DATA_AFTER_INIT 1
  34. #define IsValidGPIOFunction(x) ((x) == GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT || (x) == GPIOx_SELECT_OFF)
  35. /** default value ECE factor Molecular */
  36. #define DEF_ECE_FACTOR_M 85
  37. /** default value ECE factor Denominator */
  38. #define DEF_ECE_FACTOR_D 100
  39. /** default value ALS integration time */
  40. #define DEF_INT_PEFRIOD 100
  41. /** default value ALS gain */
  42. #define DEF_ALS_GAIN 1
  43. /** default value ALS scaler */
  44. #define DEF_ALS_SCALER 1
  45. /** default value for DMAX Enable */
  46. #define DEF_DMAX_ENABLE 1
  47. /** default ambient tuning factor %x1000 */
  48. #define DEF_AMBIENT_TUNING 80
  49. #define DEF_CROSS_TALK_VALID_HEIGHT_VALUE 20
  50. #if VL6180x_SINGLE_DEVICE_DRIVER
  51. extern struct VL6180xDevData_t SingleVL6180xDevData;
  52. #define VL6180xDevDataGet(dev, field) (SingleVL6180xDevData.field)
  53. #define VL6180xDevDataSet(dev, field, data) SingleVL6180xDevData.field = (data)
  54. #endif
  55. #define LUXRES_FIX_PREC 8
  56. #define GAIN_FIX_PREC 8 /* ! if not sme as LUX_PREC then :( adjust GetLux */
  57. #define AN_GAIN_MULT (1 << GAIN_FIX_PREC)
  58. static int32_t _GetAveTotalTime(VL6180xDev_t dev);
  59. static int VL6180x_RangeSetEarlyConvergenceEestimateThreshold(VL6180xDev_t dev);
  60. /**
  61. * ScalerLookUP scaling factor-1 to register #RANGE_SCALER lookup
  62. */
  63. static const uint16_t ScalerLookUP[] ROMABLE_DATA = {253, 127, 84}; /* lookup table for scaling->scalar 1x2x 3x */
  64. /**
  65. * scaling factor to Upper limit look up
  66. */
  67. static const uint16_t UpperLimitLookUP[] ROMABLE_DATA = {185, 370, 580}; /* lookup table for scaling->limit 1x2x3x */
  68. /**
  69. * Als Code gain to fix point gain lookup
  70. */
  71. static const uint16_t AlsGainLookUp[8] ROMABLE_DATA = {
  72. (uint16_t)(20.0f * AN_GAIN_MULT),
  73. (uint16_t)(10.0f * AN_GAIN_MULT),
  74. (uint16_t)(5.0f * AN_GAIN_MULT),
  75. (uint16_t)(2.5f * AN_GAIN_MULT),
  76. (uint16_t)(1.67f * AN_GAIN_MULT),
  77. (uint16_t)(1.25f * AN_GAIN_MULT),
  78. (uint16_t)(1.0f * AN_GAIN_MULT),
  79. (uint16_t)(40.0f * AN_GAIN_MULT),
  80. };
  81. #if VL6180x_RANGE_STATUS_ERRSTRING
  82. const char *ROMABLE_DATA VL6180x_RangeStatusErrString[] = {
  83. "No Error",
  84. "VCSEL Continuity Test",
  85. "VCSEL Watchdog Test",
  86. "VCSEL Watchdog",
  87. "PLL1 Lock",
  88. "PLL2 Lock",
  89. "Early Convergence Estimate",
  90. "Max Convergence",
  91. "No Target Ignore",
  92. "Not used 9",
  93. "Not used 10",
  94. "Max Signal To Noise Ratio",
  95. "Raw Ranging Algo Underflow",
  96. "Raw Ranging Algo Overflow",
  97. "Ranging Algo Underflow",
  98. "Ranging Algo Overflow",
  99. "Filtered by post processing (WAF)",
  100. "Ranging filtering (WAF) on-going",
  101. "Data not ready",
  102. };
  103. const char *VL6180x_RangeGetStatusErrString(uint8_t RangeErrCode)
  104. {
  105. if (RangeErrCode > sizeof(VL6180x_RangeStatusErrString) / sizeof(VL6180x_RangeStatusErrString[0]))
  106. return NULL;
  107. return VL6180x_RangeStatusErrString[RangeErrCode];
  108. }
  109. #endif
  110. #if VL6180x_UPSCALE_SUPPORT == 1
  111. #define _GetUpscale(dev, ...) 1
  112. #define _SetUpscale(...) -1
  113. #define DEF_UPSCALE 1
  114. #elif VL6180x_UPSCALE_SUPPORT == 2
  115. #define _GetUpscale(dev, ...) 2
  116. #define _SetUpscale(...)
  117. #define DEF_UPSCALE 2
  118. #elif VL6180x_UPSCALE_SUPPORT == 3
  119. #define _GetUpscale(dev, ...) 3
  120. #define _SetUpscale(...)
  121. #define DEF_UPSCALE 3
  122. #else
  123. #define DEF_UPSCALE (-(VL6180x_UPSCALE_SUPPORT))
  124. #define _GetUpscale(dev, ...) VL6180xDevDataGet(dev, UpscaleFactor)
  125. #define _SetUpscale(dev, Scaling) VL6180xDevDataSet(dev, UpscaleFactor, Scaling)
  126. #endif
  127. #if VL6180x_SINGLE_DEVICE_DRIVER
  128. /**
  129. * the unique driver data When single device driver is active
  130. */
  131. struct VL6180xDevData_t VL6180x_DEV_DATA_ATTR SingleVL6180xDevData = {
  132. .EceFactorM = DEF_ECE_FACTOR_M,
  133. .EceFactorD = DEF_ECE_FACTOR_D,
  134. #ifdef VL6180x_HAVE_UPSCALE_DATA
  135. .UpscaleFactor = DEF_UPSCALE,
  136. #endif
  137. #ifdef VL6180x_HAVE_ALS_DATA
  138. .IntegrationPeriod = DEF_INT_PEFRIOD,
  139. .AlsGainCode = DEF_ALS_GAIN,
  140. .AlsScaler = DEF_ALS_SCALER,
  141. #endif
  142. #ifdef VL6180x_HAVE_DMAX_RANGING
  143. .DMaxEnable = DEF_DMAX_ENABLE,
  144. #endif
  145. };
  146. #endif /* VL6180x_SINGLE_DEVICE_DRIVER */
  147. #define Fix7_2_KCPs(x) ((((uint32_t)(x))*1000)>>7)
  148. #if VL6180x_WRAP_AROUND_FILTER_SUPPORT || VL6180x_HAVE_DMAX_RANGING
  149. static int _GetRateResult(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData);
  150. #endif
  151. #if VL6180x_WRAP_AROUND_FILTER_SUPPORT
  152. static int _filter_Init(VL6180xDev_t dev);
  153. static int _filter_GetResult(VL6180xDev_t dev, VL6180x_RangeData_t *pData);
  154. #define _IsWrapArroundActive(dev) VL6180xDevDataGet(dev, WrapAroundFilterActive)
  155. #else
  156. #define _IsWrapArroundActive(dev) 0
  157. #endif
  158. #if VL6180x_HAVE_DMAX_RANGING
  159. void _DMax_OneTimeInit(VL6180xDev_t dev);
  160. static int _DMax_InitData(VL6180xDev_t dev);
  161. static int _DMax_Compute(VL6180xDev_t dev, VL6180x_RangeData_t *pRange);
  162. #define _IsDMaxActive(dev) VL6180xDevDataGet(dev, DMaxEnable)
  163. #else
  164. #define _DMax_InitData(...) 0 /* success */
  165. #define _DMax_OneTimeInit(...) (void)0
  166. #define _IsDMaxActive(...) 0
  167. #endif
  168. static int VL6180x_RangeStaticInit(VL6180xDev_t dev);
  169. static int VL6180x_UpscaleStaticInit(VL6180xDev_t dev);
  170. int VL6180x_WaitDeviceBooted(VL6180xDev_t dev)
  171. {
  172. uint8_t FreshOutReset;
  173. int status;
  174. LOG_FUNCTION_START("");
  175. do {
  176. status = VL6180x_RdByte(dev, SYSTEM_FRESH_OUT_OF_RESET, &FreshOutReset);
  177. } while (FreshOutReset != 1 && status == 0);
  178. LOG_FUNCTION_END(status);
  179. return status;
  180. }
  181. int VL6180x_InitData(VL6180xDev_t dev)
  182. {
  183. int status, dmax_status ;
  184. int8_t offset;
  185. uint8_t FreshOutReset;
  186. uint32_t CalValue;
  187. uint16_t u16;
  188. uint32_t XTalkCompRate_KCps;
  189. LOG_FUNCTION_START("");
  190. VL6180xDevDataSet(dev, EceFactorM, DEF_ECE_FACTOR_M);
  191. VL6180xDevDataSet(dev, EceFactorD, DEF_ECE_FACTOR_D);
  192. VL6180xDevDataSet(dev, RangeIgnore.Enabled, 0);
  193. #ifdef VL6180x_HAVE_UPSCALE_DATA
  194. VL6180xDevDataSet(dev, UpscaleFactor, DEF_UPSCALE);
  195. #endif
  196. #ifdef VL6180x_HAVE_ALS_DATA
  197. VL6180xDevDataSet(dev, IntegrationPeriod, DEF_INT_PEFRIOD);
  198. VL6180xDevDataSet(dev, AlsGainCode, DEF_ALS_GAIN);
  199. VL6180xDevDataSet(dev, AlsScaler, DEF_ALS_SCALER);
  200. #endif
  201. #ifdef VL6180x_HAVE_WRAP_AROUND_DATA
  202. VL6180xDevDataSet(dev, WrapAroundFilterActive, (VL6180x_WRAP_AROUND_FILTER_SUPPORT > 0));
  203. VL6180xDevDataSet(dev, DMaxEnable, DEF_DMAX_ENABLE);
  204. #endif
  205. _DMax_OneTimeInit(dev);
  206. do {
  207. /* backup offset initial value from nvm these must be done prior any over call that use offset */
  208. status = VL6180x_RdByte(dev, SYSRANGE_PART_TO_PART_RANGE_OFFSET, (uint8_t *)&offset);
  209. if (status) {
  210. VL6180x_ErrLog("SYSRANGE_PART_TO_PART_RANGE_OFFSET rd fail");
  211. break;
  212. }
  213. VL6180xDevDataSet(dev, Part2PartOffsetNVM, offset);
  214. status = VL6180x_RdDWord(dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, &CalValue);
  215. if (status) {
  216. VL6180x_ErrLog("Part2PartAmbNVM rd fail");
  217. break;
  218. }
  219. if ((CalValue&0xFFFF0000) == 0) {
  220. CalValue = 0x00CE03F8;
  221. }
  222. VL6180xDevDataSet(dev, Part2PartAmbNVM, CalValue);
  223. status = VL6180x_RdWord(dev, SYSRANGE_CROSSTALK_COMPENSATION_RATE , &u16);
  224. if (status) {
  225. VL6180x_ErrLog("SYSRANGE_CROSSTALK_COMPENSATION_RATE rd fail ");
  226. break;
  227. }
  228. XTalkCompRate_KCps = Fix7_2_KCPs(u16);
  229. VL6180xDevDataSet(dev, XTalkCompRate_KCps, XTalkCompRate_KCps);
  230. dmax_status = _DMax_InitData(dev);
  231. if (dmax_status < 0) {
  232. VL6180x_ErrLog("DMax init failure");
  233. break;
  234. }
  235. /* Read or wait for fresh out of reset */
  236. status = VL6180x_RdByte(dev, SYSTEM_FRESH_OUT_OF_RESET, &FreshOutReset);
  237. if (status) {
  238. VL6180x_ErrLog("SYSTEM_FRESH_OUT_OF_RESET rd fail");
  239. break;
  240. }
  241. if (FreshOutReset != 1 || dmax_status)
  242. status = CALIBRATION_WARNING;
  243. } while (0);
  244. LOG_FUNCTION_END(status);
  245. return status;
  246. }
  247. int8_t VL6180x_GetOffsetCalibrationData(VL6180xDev_t dev)
  248. {
  249. int8_t offset;
  250. LOG_FUNCTION_START("");
  251. offset = VL6180xDevDataGet(dev, Part2PartOffsetNVM);
  252. LOG_FUNCTION_END(offset);
  253. return offset;
  254. }
  255. int VL6180x_SetOffsetCalibrationData(VL6180xDev_t dev, int8_t offset)
  256. {
  257. int status;
  258. LOG_FUNCTION_START("%d", offset);
  259. VL6180xDevDataSet(dev, Part2PartOffsetNVM, offset);
  260. offset /= _GetUpscale(dev);
  261. status = VL6180x_WrByte(dev, SYSRANGE_PART_TO_PART_RANGE_OFFSET, offset);
  262. LOG_FUNCTION_END(status);
  263. return status;
  264. }
  265. int VL6180x_SetXTalkCompensationRate(VL6180xDev_t dev, FixPoint97_t Rate)
  266. {
  267. int status;
  268. LOG_FUNCTION_START("%d", Rate);
  269. status = VL6180x_WrWord(dev, SYSRANGE_CROSSTALK_COMPENSATION_RATE, Rate);
  270. if (status == 0) {
  271. uint32_t XTalkCompRate_KCps;
  272. XTalkCompRate_KCps = Fix7_2_KCPs(Rate);
  273. VL6180xDevDataSet(dev, XTalkCompRate_KCps, XTalkCompRate_KCps);
  274. /* update dmax whenever xtalk rate changes */
  275. status = _DMax_InitData(dev);
  276. }
  277. LOG_FUNCTION_END(status);
  278. return status;
  279. }
  280. int VL6180x_SetI2CAddress(VL6180xDev_t dev, uint8_t NewAddress)
  281. {
  282. int status;
  283. LOG_FUNCTION_START("");
  284. status = VL6180x_WrByte(dev, I2C_SLAVE_DEVICE_ADDRESS, NewAddress / 2);
  285. if (status) {
  286. VL6180x_ErrLog("new i2c addr Wr fail");
  287. }
  288. LOG_FUNCTION_END(status);
  289. return status;
  290. }
  291. uint16_t VL6180x_GetUpperLimit(VL6180xDev_t dev)
  292. {
  293. uint16_t limit;
  294. int scaling;
  295. LOG_FUNCTION_START("");
  296. scaling = _GetUpscale(dev);
  297. /* FIXME we do assume here _GetUpscale is valid if user call us prior to init we may overflow the LUT mem area */
  298. limit = UpperLimitLookUP[scaling - 1];
  299. LOG_FUNCTION_END((int)limit);
  300. return limit;
  301. }
  302. int VL6180x_StaticInit(VL6180xDev_t dev)
  303. {
  304. int status = 0, init_status;
  305. LOG_FUNCTION_START("");
  306. /* TODO doc When using configurable scaling but using 1x as start condition
  307. * load tunning upscale or not ??? */
  308. if (_GetUpscale(dev) == 1 && !(VL6180x_UPSCALE_SUPPORT < 0))
  309. init_status = VL6180x_RangeStaticInit(dev);
  310. else
  311. init_status = VL6180x_UpscaleStaticInit(dev);
  312. if (init_status < 0) {
  313. VL6180x_ErrLog("StaticInit fail");
  314. goto error;
  315. } else if (init_status > 0) {
  316. VL6180x_ErrLog("StaticInit warning");
  317. }
  318. #if REFRESH_CACHED_DATA_AFTER_INIT
  319. #ifdef VL6180x_HAVE_ALS_DATA
  320. /* update cached value after tuning applied */
  321. do {
  322. uint8_t data;
  323. status = VL6180x_RdByte(dev, FW_ALS_RESULT_SCALER, &data);
  324. if (status)
  325. break;
  326. VL6180xDevDataSet(dev, AlsScaler, data);
  327. status = VL6180x_RdByte(dev, SYSALS_ANALOGUE_GAIN, &data);
  328. if (status)
  329. break;
  330. VL6180x_AlsSetAnalogueGain(dev, data);
  331. } while (0);
  332. #endif
  333. #endif /* REFRESH_CACHED_DATA_AFTER_INIT */
  334. if (status < 0) {
  335. VL6180x_ErrLog("StaticInit fail");
  336. }
  337. if (!status && init_status) {
  338. status = init_status;
  339. }
  340. error:
  341. LOG_FUNCTION_END(status);
  342. return status;
  343. }
  344. int VL6180x_SetGroupParamHold(VL6180xDev_t dev, int Hold)
  345. {
  346. int status;
  347. uint8_t value;
  348. LOG_FUNCTION_START("%d", Hold);
  349. if (Hold)
  350. value = 1;
  351. else
  352. value = 0;
  353. status = VL6180x_WrByte(dev, SYSTEM_GROUPED_PARAMETER_HOLD, value);
  354. LOG_FUNCTION_END(status);
  355. return status;
  356. }
  357. int VL6180x_Prepare(VL6180xDev_t dev)
  358. {
  359. int status;
  360. LOG_FUNCTION_START("");
  361. do {
  362. status = VL6180x_StaticInit(dev);
  363. if (status < 0)
  364. break;
  365. /* set range InterruptMode to new sample */
  366. status = VL6180x_RangeConfigInterrupt(dev, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY);
  367. if (status)
  368. break;
  369. /* set default threshold */
  370. status = VL6180x_RangeSetRawThresholds(dev, 10, 200);
  371. if (status) {
  372. VL6180x_ErrLog("VL6180x_RangeSetRawThresholds fail");
  373. break;
  374. }
  375. #if VL6180x_ALS_SUPPORT
  376. status = VL6180x_AlsSetIntegrationPeriod(dev, 100);
  377. if (status)
  378. break;
  379. status = VL6180x_AlsSetInterMeasurementPeriod(dev, 200);
  380. if (status)
  381. break;
  382. status = VL6180x_AlsSetAnalogueGain(dev, 0);
  383. if (status)
  384. break;
  385. status = VL6180x_AlsSetThresholds(dev, 0, 0xFF);
  386. if (status)
  387. break;
  388. /* set Als InterruptMode to new sample */
  389. status = VL6180x_AlsConfigInterrupt(dev, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY);
  390. if (status) {
  391. VL6180x_ErrLog("VL6180x_AlsConfigInterrupt fail");
  392. break;
  393. }
  394. #endif
  395. #if VL6180x_WRAP_AROUND_FILTER_SUPPORT
  396. _filter_Init(dev);
  397. #endif
  398. /* make sure to reset any left previous condition that can hangs first poll */
  399. status = VL6180x_ClearAllInterrupt(dev);
  400. } while (0);
  401. LOG_FUNCTION_END(status);
  402. return status;
  403. }
  404. #if VL6180x_ALS_SUPPORT
  405. int VL6180x_AlsGetLux(VL6180xDev_t dev, lux_t *pLux)
  406. {
  407. int status;
  408. uint16_t RawAls;
  409. uint32_t luxValue = 0;
  410. uint32_t IntPeriod;
  411. uint32_t AlsAnGain;
  412. uint32_t GainFix;
  413. uint32_t AlsScaler;
  414. #if LUXRES_FIX_PREC != GAIN_FIX_PREC
  415. #error "LUXRES_FIX_PREC != GAIN_FIX_PREC review these code to be correct"
  416. #endif
  417. const uint32_t LuxResxIntIme = (uint32_t)(0.56f * DEF_INT_PEFRIOD * (1 << LUXRES_FIX_PREC));
  418. LOG_FUNCTION_START("%p", pLux);
  419. status = VL6180x_RdWord(dev, RESULT_ALS_VAL, &RawAls);
  420. if (!status) {
  421. /* wer are yet here at no fix point */
  422. IntPeriod = VL6180xDevDataGet(dev, IntegrationPeriod);
  423. AlsScaler = VL6180xDevDataGet(dev, AlsScaler);
  424. IntPeriod++; /* what stored is real time ms -1 and it can be 0 for or 0 or 1ms */
  425. luxValue = (uint32_t)RawAls * LuxResxIntIme; /* max # 16+8bits + 6bit (0.56*100) */
  426. luxValue /= IntPeriod; /* max # 16+8bits + 6bit 16+8+1 to 9 bit */
  427. /* between 29 - 21 bit */
  428. AlsAnGain = VL6180xDevDataGet(dev, AlsGainCode);
  429. GainFix = AlsGainLookUp[AlsAnGain];
  430. luxValue = luxValue / (AlsScaler * GainFix);
  431. *pLux = luxValue;
  432. }
  433. LOG_FUNCTION_END_FMT(status, "%x", (int)*pLux);
  434. return status;
  435. }
  436. int VL6180x_AlsGetMeasurement(VL6180xDev_t dev, VL6180x_AlsData_t *pAlsData)
  437. {
  438. int status;
  439. uint8_t ErrStatus;
  440. LOG_FUNCTION_START("%p", pAlsData);
  441. status = VL6180x_AlsGetLux(dev, &pAlsData->lux);
  442. if (!status) {
  443. status = VL6180x_RdByte(dev, RESULT_ALS_STATUS, &ErrStatus);
  444. pAlsData->errorStatus = ErrStatus >> 4;
  445. }
  446. LOG_FUNCTION_END_FMT(status, "%d %d", (int)pAlsData->lux, (int)pAlsData->errorStatus);
  447. return status;
  448. }
  449. int VL6180x_AlsPollMeasurement(VL6180xDev_t dev, VL6180x_AlsData_t *pAlsData)
  450. {
  451. int status;
  452. int ClrStatus;
  453. uint8_t IntStatus;
  454. LOG_FUNCTION_START("%p", pAlsData);
  455. #if VL6180X_SAFE_POLLING_ENTER
  456. /* if device get stopped with left interrupt uncleared , it is required to clear them now or poll for new condition will never occur*/
  457. status = VL6180x_AlsClearInterrupt(dev);
  458. if (status) {
  459. VL6180x_ErrLog("VL6180x_AlsClearInterrupt fail");
  460. goto over;
  461. }
  462. #endif
  463. status = VL6180x_AlsSetSystemMode(dev, MODE_START_STOP | MODE_SINGLESHOT);
  464. if (status) {
  465. VL6180x_ErrLog("VL6180x_AlsSetSystemMode fail");
  466. goto over;
  467. }
  468. /* poll for new sample ready */
  469. while (1) {
  470. status = VL6180x_AlsGetInterruptStatus(dev, &IntStatus);
  471. if (status) {
  472. break;
  473. }
  474. if (IntStatus == RES_INT_STAT_GPIO_NEW_SAMPLE_READY) {
  475. break; /* break on new data (status is 0) */
  476. }
  477. VL6180x_PollDelay(dev);
  478. };
  479. if (!status) {
  480. status = VL6180x_AlsGetMeasurement(dev, pAlsData);
  481. }
  482. ClrStatus = VL6180x_AlsClearInterrupt(dev);
  483. if (ClrStatus) {
  484. VL6180x_ErrLog("VL6180x_AlsClearInterrupt fail");
  485. if (!status) {
  486. status = ClrStatus; /* leave previous if already on error */
  487. }
  488. }
  489. over:
  490. LOG_FUNCTION_END(status);
  491. return status;
  492. }
  493. int VL6180x_AlsGetInterruptStatus(VL6180xDev_t dev, uint8_t *pIntStatus)
  494. {
  495. int status;
  496. uint8_t IntStatus;
  497. LOG_FUNCTION_START("%p", pIntStatus);
  498. status = VL6180x_RdByte(dev, RESULT_INTERRUPT_STATUS_GPIO, &IntStatus);
  499. *pIntStatus = (IntStatus >> 3) & 0x07;
  500. LOG_FUNCTION_END_FMT(status, "%d", (int)*pIntStatus);
  501. return status;
  502. }
  503. int VL6180x_AlsWaitDeviceReady(VL6180xDev_t dev, int MaxLoop)
  504. {
  505. int status;
  506. int n;
  507. uint8_t u8;
  508. LOG_FUNCTION_START("%d", (int)MaxLoop);
  509. if (MaxLoop < 1) {
  510. status = INVALID_PARAMS;
  511. } else {
  512. for (n = 0; n < MaxLoop; n++) {
  513. status = VL6180x_RdByte(dev, RESULT_ALS_STATUS, &u8);
  514. if (status)
  515. break;
  516. u8 = u8 & ALS_DEVICE_READY_MASK;
  517. if (u8)
  518. break;
  519. }
  520. if (!status && !u8) {
  521. status = TIME_OUT;
  522. }
  523. }
  524. LOG_FUNCTION_END(status);
  525. return status;
  526. }
  527. int VL6180x_AlsSetSystemMode(VL6180xDev_t dev, uint8_t mode)
  528. {
  529. int status;
  530. LOG_FUNCTION_START("%d", (int)mode);
  531. /* FIXME if we are called back to back real fast we are not checking
  532. * if previous mode "set" got absorbed => bit 0 must be 0 so that wr 1 work */
  533. if (mode <= 3) {
  534. status = VL6180x_WrByte(dev, SYSALS_START, mode);
  535. } else {
  536. status = INVALID_PARAMS;
  537. }
  538. LOG_FUNCTION_END(status);
  539. return status;
  540. }
  541. int VL6180x_AlsConfigInterrupt(VL6180xDev_t dev, uint8_t ConfigGpioInt)
  542. {
  543. int status;
  544. if (ConfigGpioInt <= CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY) {
  545. status = VL6180x_UpdateByte(dev, SYSTEM_INTERRUPT_CONFIG_GPIO, (uint8_t)(~CONFIG_GPIO_ALS_MASK), (ConfigGpioInt << 3));
  546. } else {
  547. VL6180x_ErrLog("Invalid config mode param %d", (int)ConfigGpioInt);
  548. status = INVALID_PARAMS;
  549. }
  550. LOG_FUNCTION_END(status);
  551. return status;
  552. }
  553. int VL6180x_AlsSetThresholds(VL6180xDev_t dev, uint8_t low, uint8_t high)
  554. {
  555. int status;
  556. LOG_FUNCTION_START("%d %d", (int)low, (int)high);
  557. status = VL6180x_WrByte(dev, SYSALS_THRESH_LOW, low);
  558. if (!status) {
  559. status = VL6180x_WrByte(dev, SYSALS_THRESH_HIGH, high);
  560. }
  561. LOG_FUNCTION_END(status) ;
  562. return status;
  563. }
  564. int VL6180x_AlsSetAnalogueGain(VL6180xDev_t dev, uint8_t gain)
  565. {
  566. int status;
  567. uint8_t GainTotal;
  568. LOG_FUNCTION_START("%d", (int)gain);
  569. gain &= ~0x40;
  570. if (gain > 7) {
  571. gain = 7;
  572. }
  573. GainTotal = gain | 0x40;
  574. status = VL6180x_WrByte(dev, SYSALS_ANALOGUE_GAIN, GainTotal);
  575. if (!status) {
  576. VL6180xDevDataSet(dev, AlsGainCode, gain);
  577. }
  578. LOG_FUNCTION_END_FMT(status, "%d %d", (int)gain, (int)GainTotal);
  579. return status;
  580. }
  581. int VL6180x_AlsSetInterMeasurementPeriod(VL6180xDev_t dev, uint16_t intermeasurement_period_ms)
  582. {
  583. int status;
  584. LOG_FUNCTION_START("%d", (int)intermeasurement_period_ms);
  585. /* clipping: range is 0-2550ms */
  586. if (intermeasurement_period_ms >= 255 * 10)
  587. intermeasurement_period_ms = 255 * 10;
  588. status = VL6180x_WrByte(dev, SYSALS_INTERMEASUREMENT_PERIOD, (uint8_t)(intermeasurement_period_ms / 10));
  589. LOG_FUNCTION_END_FMT(status, "%d", (int)intermeasurement_period_ms);
  590. return status;
  591. }
  592. int VL6180x_AlsSetIntegrationPeriod(VL6180xDev_t dev, uint16_t period_ms)
  593. {
  594. int status;
  595. uint16_t SetIntegrationPeriod;
  596. LOG_FUNCTION_START("%d", (int)period_ms);
  597. if (period_ms >= 1)
  598. SetIntegrationPeriod = period_ms - 1;
  599. else
  600. SetIntegrationPeriod = period_ms;
  601. if (SetIntegrationPeriod > 464) {
  602. SetIntegrationPeriod = 464;
  603. } else if (SetIntegrationPeriod == 255) {
  604. SetIntegrationPeriod++; /* can't write 255 since this causes the device to lock out.*/
  605. }
  606. status = VL6180x_WrWord(dev, SYSALS_INTEGRATION_PERIOD, SetIntegrationPeriod);
  607. if (!status) {
  608. VL6180xDevDataSet(dev, IntegrationPeriod, SetIntegrationPeriod) ;
  609. }
  610. LOG_FUNCTION_END_FMT(status, "%d", (int)SetIntegrationPeriod);
  611. return status;
  612. }
  613. #endif /* HAVE_ALS_SUPPORT */
  614. int VL6180x_RangePollMeasurement(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData)
  615. {
  616. int status;
  617. int ClrStatus;
  618. IntrStatus_t IntStatus;
  619. LOG_FUNCTION_START("");
  620. /* start single range measurement */
  621. #if VL6180X_SAFE_POLLING_ENTER
  622. /* if device get stopped with left interrupt uncleared , it is required to clear them now or poll for new condition will never occur*/
  623. status = VL6180x_RangeClearInterrupt(dev);
  624. if (status) {
  625. VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail");
  626. goto done;
  627. }
  628. #endif
  629. /* //![single_shot_snipet] */
  630. status = VL6180x_RangeSetSystemMode(dev, MODE_START_STOP | MODE_SINGLESHOT);
  631. if (status) {
  632. VL6180x_ErrLog("VL6180x_RangeSetSystemMode fail");
  633. goto done;
  634. }
  635. /* poll for new sample ready */
  636. while (1) {
  637. status = VL6180x_RangeGetInterruptStatus(dev, &IntStatus.val);
  638. if (status) {
  639. break;
  640. }
  641. if (IntStatus.status.Range == RES_INT_STAT_GPIO_NEW_SAMPLE_READY || IntStatus.status.Error != 0) {
  642. break;
  643. }
  644. VL6180x_PollDelay(dev);
  645. }
  646. /* //![single_shot_snipet] */
  647. if (!status) {
  648. status = VL6180x_RangeGetMeasurement(dev, pRangeData);
  649. }
  650. /* clear range interrupt source */
  651. ClrStatus = VL6180x_RangeClearInterrupt(dev);
  652. if (ClrStatus) {
  653. VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail");
  654. /* leave initial status if already in error */
  655. if (!status) {
  656. status = ClrStatus;
  657. }
  658. }
  659. done:
  660. LOG_FUNCTION_END(status);
  661. return status;
  662. }
  663. #if VL6180x_CACHED_REG
  664. int VL6180x_GetCachedDWord(VL6180xDev_t dev, uint16_t index, uint32_t *pValue)
  665. {
  666. int status;
  667. uint32_t Value;
  668. if (VL6180xDevDataGet(dev, CacheFilled) != 0 &&
  669. index >= VL6180x_FIRST_CACHED_INDEX &&
  670. index <= (VL6180x_LAST_CACHED_INDEX - 3)) {
  671. uint8_t *pBytes = &VL6180xDevDataGet(dev, CachedRegs[index - VL6180x_FIRST_CACHED_INDEX]);
  672. Value = ((uint32_t)pBytes[0] << 24) |
  673. ((uint32_t)pBytes[1] << 16) |
  674. ((uint32_t)pBytes[2] << 8) |
  675. (uint32_t)pBytes[3];
  676. *pValue = Value;
  677. status = 0;
  678. } else {
  679. status = VL6180x_RdDWord(dev, index, pValue);
  680. }
  681. return status;
  682. }
  683. int VL6180x_GetCachedWord(VL6180xDev_t dev, uint16_t index, uint16_t *pValue)
  684. {
  685. int status;
  686. uint32_t Value;
  687. if (VL6180xDevDataGet(dev, CacheFilled) != 0 &&
  688. index >= VL6180x_FIRST_CACHED_INDEX &&
  689. index <= (VL6180x_LAST_CACHED_INDEX - 1)) {
  690. uint8_t *pBytes = &VL6180xDevDataGet(dev, CachedRegs[index - VL6180x_FIRST_CACHED_INDEX]);
  691. Value = ((uint32_t)pBytes[0] << 8) | (uint32_t)pBytes[1];
  692. *pValue = Value;
  693. status = 0;
  694. } else {
  695. status = VL6180x_RdWord(dev, index, pValue);
  696. }
  697. return status;
  698. }
  699. int VL6180x_GetCachedByte(VL6180xDev_t dev, uint16_t index, uint8_t *pValue)
  700. {
  701. int status;
  702. uint8_t Value;
  703. if (VL6180xDevDataGet(dev, CacheFilled) != 0 &&
  704. index >= VL6180x_FIRST_CACHED_INDEX &&
  705. index <= VL6180x_LAST_CACHED_INDEX) {
  706. Value = VL6180xDevDataGet(dev, CachedRegs[index - VL6180x_FIRST_CACHED_INDEX]);
  707. *pValue = Value;
  708. status = 0;
  709. } else {
  710. status = VL6180x_RdByte(dev, index, pValue);
  711. }
  712. return status;
  713. }
  714. int _CachedRegs_Fetch(VL6180xDev_t dev)
  715. {
  716. int status;
  717. uint8_t *Buffer;
  718. if (VL6180xDevDataGet(dev, CacheFilled) == 0) {
  719. VL6180xDevDataSet(dev, CacheFilled, 1);
  720. Buffer = &VL6180xDevDataGet(dev, CachedRegs[0]);
  721. status = VL6180x_RdMulti(dev, VL6180x_FIRST_CACHED_INDEX, Buffer, VL6180x_CACHED_REG_CNT);
  722. } else {
  723. status = 0 ;
  724. }
  725. return status;
  726. }
  727. void _CachedRegs_Flush(VL6180xDev_t dev)
  728. {
  729. VL6180xDevDataSet(dev, CacheFilled, 0);
  730. }
  731. #else
  732. # define _CachedRegs_Fetch(...) 0
  733. # define _CachedRegs_Flush(...) (void)0
  734. # define _Fetch_CachedRegs(...) 0
  735. # define VL6180x_GetCachedByte(dev, index, pValue) VL6180x_RdByte(dev, index, pValue)
  736. # define VL6180x_GetCachedWord(dev, index, pValue) VL6180x_RdWord(dev, index, pValue)
  737. # define VL6180x_GetCachedDWord(dev, index, pValue) VL6180x_RdDWord(dev, index, pValue)
  738. #endif /* VL6180x_CACHED_REG */
  739. int VL6180x_RangeGetMeasurement(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData)
  740. {
  741. int status;
  742. uint16_t RawRate;
  743. uint8_t RawStatus;
  744. LOG_FUNCTION_START("");
  745. status = _CachedRegs_Fetch(dev);
  746. if (status) {
  747. VL6180x_ErrLog("Cache register read fail");
  748. goto error;
  749. }
  750. status = VL6180x_RangeGetResult(dev, &pRangeData->range_mm);
  751. if (!status) {
  752. status = VL6180x_GetCachedWord(dev, RESULT_RANGE_SIGNAL_RATE, &RawRate);
  753. if (!status) {
  754. pRangeData->signalRate_mcps = VL6180x_9to7Conv(RawRate);
  755. status = VL6180x_GetCachedByte(dev, RESULT_RANGE_STATUS, &RawStatus);
  756. if (!status) {
  757. pRangeData->errorStatus = RawStatus >> 4;
  758. } else {
  759. VL6180x_ErrLog("Rd RESULT_RANGE_STATUS fail");
  760. }
  761. #if VL6180x_WRAP_AROUND_FILTER_SUPPORT || VL6180x_HAVE_DMAX_RANGING
  762. status = _GetRateResult(dev, pRangeData);
  763. if (status)
  764. goto error;
  765. #endif
  766. #if VL6180x_WRAP_AROUND_FILTER_SUPPORT
  767. /* if enabled run filter */
  768. if (_IsWrapArroundActive(dev)) {
  769. status = _filter_GetResult(dev, pRangeData);
  770. if (!status) {
  771. /* patch the range status and measure if it is filtered */
  772. if(pRangeData->FilteredData.filterError != NoError) {
  773. pRangeData->errorStatus = pRangeData->FilteredData.filterError;
  774. pRangeData->range_mm = pRangeData->FilteredData.range_mm;
  775. }
  776. }
  777. }
  778. #endif
  779. #if VL6180x_HAVE_DMAX_RANGING
  780. if (_IsDMaxActive(dev)) {
  781. _DMax_Compute(dev, pRangeData);
  782. }
  783. #endif
  784. } else {
  785. VL6180x_ErrLog("Rd RESULT_RANGE_SIGNAL_RATE fail");
  786. }
  787. } else {
  788. VL6180x_ErrLog("VL6180x_GetRangeResult fail");
  789. }
  790. error:
  791. _CachedRegs_Flush(dev);
  792. LOG_FUNCTION_END_FMT(status, "%d %d %d", (int)pRangeData->range_mm, (int)pRangeData->signalRate_mcps, (int)pRangeData->errorStatus) ;
  793. return status;
  794. }
  795. int VL6180x_RangeGetMeasurementIfReady(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData)
  796. {
  797. int status;
  798. IntrStatus_t IntStatus;
  799. LOG_FUNCTION_START();
  800. status = VL6180x_RangeGetInterruptStatus(dev, &IntStatus.val);
  801. if (status == 0) {
  802. if (IntStatus.status.Range == RES_INT_STAT_GPIO_NEW_SAMPLE_READY ||
  803. IntStatus.status.Error != 0) {
  804. status = VL6180x_RangeGetMeasurement(dev, pRangeData);
  805. if (status == 0) {
  806. /* clear range interrupt source */
  807. status = VL6180x_RangeClearInterrupt(dev);
  808. if (status) {
  809. VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail");
  810. }
  811. }
  812. } else {
  813. pRangeData->errorStatus = DataNotReady;
  814. }
  815. } else {
  816. VL6180x_ErrLog("fail to get interrupt status");
  817. }
  818. LOG_FUNCTION_END(status) ;
  819. return status;
  820. }
  821. int VL6180x_FilterSetState(VL6180xDev_t dev, int state)
  822. {
  823. int status;
  824. LOG_FUNCTION_START("%d", state);
  825. #if VL6180x_WRAP_AROUND_FILTER_SUPPORT
  826. VL6180xDevDataSet(dev, WrapAroundFilterActive, state);
  827. status = 0;
  828. #else
  829. status = NOT_SUPPORTED;
  830. #endif
  831. LOG_FUNCTION_END(status);
  832. return status;
  833. }
  834. int VL6180x_FilterGetState(VL6180xDev_t dev)
  835. {
  836. int status;
  837. LOG_FUNCTION_START("");
  838. #if VL6180x_WRAP_AROUND_FILTER_SUPPORT
  839. status = VL6180xDevDataGet(dev, WrapAroundFilterActive);
  840. #else
  841. status = 0;
  842. #endif
  843. LOG_FUNCTION_END(status);
  844. return status;
  845. }
  846. int VL6180x_RangeGetResult(VL6180xDev_t dev, int32_t *pRange_mm)
  847. {
  848. int status;
  849. uint8_t RawRange;
  850. int32_t Upscale;
  851. LOG_FUNCTION_START("%p", pRange_mm);
  852. status = VL6180x_GetCachedByte(dev, RESULT_RANGE_VAL, &RawRange);
  853. if (!status) {
  854. Upscale = _GetUpscale(dev);
  855. *pRange_mm = Upscale * (int32_t)RawRange;
  856. }
  857. LOG_FUNCTION_END_FMT(status, "%d", (int)*pRange_mm);
  858. return status;
  859. }
  860. int VL6180x_RangeSetRawThresholds(VL6180xDev_t dev, uint8_t low, uint8_t high)
  861. {
  862. int status;
  863. LOG_FUNCTION_START("%d %d", (int) low, (int)high);
  864. /* TODO we can optimize here grouping high/low in a word but that's cpu endianness dependent */
  865. status = VL6180x_WrByte(dev, SYSRANGE_THRESH_HIGH, high);
  866. if (!status) {
  867. status = VL6180x_WrByte(dev, SYSRANGE_THRESH_LOW, low);
  868. }
  869. LOG_FUNCTION_END(status);
  870. return status;
  871. }
  872. int VL6180x_RangeSetThresholds(VL6180xDev_t dev, uint16_t low, uint16_t high, int UseSafeParamHold)
  873. {
  874. int status;
  875. int scale;
  876. LOG_FUNCTION_START("%d %d", (int) low, (int)high);
  877. scale = _GetUpscale(dev, UpscaleFactor);
  878. if (low > scale * 255 || high > scale * 255) {
  879. status = INVALID_PARAMS;
  880. } else {
  881. do {
  882. if (UseSafeParamHold) {
  883. status = VL6180x_SetGroupParamHold(dev, 1);
  884. if (status)
  885. break;
  886. }
  887. status = VL6180x_RangeSetRawThresholds(dev, (uint8_t)(low / scale), (uint8_t)(high / scale));
  888. if (status) {
  889. VL6180x_ErrLog("VL6180x_RangeSetRawThresholds fail");
  890. }
  891. if (UseSafeParamHold) {
  892. int HoldStatus;
  893. /* tryt to unset param hold vene if previous fail */
  894. HoldStatus = VL6180x_SetGroupParamHold(dev, 0);
  895. if (!status)
  896. status = HoldStatus;
  897. }
  898. } while (0);
  899. }
  900. LOG_FUNCTION_END(status);
  901. return status;
  902. }
  903. int VL6180x_RangeGetThresholds(VL6180xDev_t dev, uint16_t *low, uint16_t *high)
  904. {
  905. int status = 0;
  906. uint8_t RawLow, RawHigh;
  907. int scale;
  908. LOG_FUNCTION_START("%p %p", low , high);
  909. scale = _GetUpscale(dev, UpscaleFactor);
  910. do {
  911. if (high != NULL) {
  912. status = VL6180x_RdByte(dev, SYSRANGE_THRESH_HIGH, &RawHigh);
  913. if (status) {
  914. VL6180x_ErrLog("rd SYSRANGE_THRESH_HIGH fail");
  915. break;
  916. }
  917. *high = (uint16_t)RawHigh * scale;
  918. }
  919. if (low != NULL) {
  920. status = VL6180x_RdByte(dev, SYSRANGE_THRESH_LOW, &RawLow);
  921. if (status) {
  922. VL6180x_ErrLog("rd SYSRANGE_THRESH_LOW fail");
  923. break;
  924. }
  925. *low = (uint16_t)RawLow * scale;
  926. }
  927. } while (0);
  928. LOG_FUNCTION_END_FMT(status, "%d %d", (int)*low , (int)*high);
  929. return status;
  930. }
  931. int VL6180x_RangeGetInterruptStatus(VL6180xDev_t dev, uint8_t *pIntStatus)
  932. {
  933. int status;
  934. uint8_t IntStatus;
  935. LOG_FUNCTION_START("%p", pIntStatus);
  936. /* FIXME we are grouping "error" with over status the user must check implicitly for it
  937. * not just new sample or over status , that will nevr show up in case of error*/
  938. status = VL6180x_GetCachedByte(dev, RESULT_INTERRUPT_STATUS_GPIO, &IntStatus);
  939. *pIntStatus = IntStatus & 0xC7;
  940. LOG_FUNCTION_END_FMT(status, "%d", (int)*pIntStatus);
  941. return status;
  942. }
  943. int VL6180x_GetInterruptStatus(VL6180xDev_t dev, uint8_t *IntStatus)
  944. {
  945. int status;
  946. LOG_FUNCTION_START("%p" , IntStatus);
  947. status = VL6180x_RdByte(dev, RESULT_INTERRUPT_STATUS_GPIO, IntStatus);
  948. LOG_FUNCTION_END_FMT(status, "%d", (int)*IntStatus);
  949. return status;
  950. }
  951. int VL6180x_ClearInterrupt(VL6180xDev_t dev, uint8_t IntClear)
  952. {
  953. int status;
  954. LOG_FUNCTION_START("%d", (int)IntClear);
  955. if (IntClear <= 7) {
  956. status = VL6180x_WrByte(dev, SYSTEM_INTERRUPT_CLEAR, IntClear);
  957. } else {
  958. status = INVALID_PARAMS;
  959. }
  960. LOG_FUNCTION_END(status);
  961. return status;
  962. }
  963. static int VL6180x_RangeStaticInit(VL6180xDev_t dev)
  964. {
  965. int status;
  966. LOG_FUNCTION_START("");
  967. /* REGISTER_TUNING_SR03_270514_CustomerView.txt */
  968. VL6180x_WrByte(dev, 0x0207, 0x01);
  969. VL6180x_WrByte(dev, 0x0208, 0x01);
  970. VL6180x_WrByte(dev, 0x0096, 0x00);
  971. VL6180x_WrByte(dev, 0x0097, 0xfd);
  972. VL6180x_WrByte(dev, 0x00e3, 0x01);
  973. VL6180x_WrByte(dev, 0x00e4, 0x03);
  974. VL6180x_WrByte(dev, 0x00e5, 0x02);
  975. VL6180x_WrByte(dev, 0x00e6, 0x01);
  976. VL6180x_WrByte(dev, 0x00e7, 0x03);
  977. VL6180x_WrByte(dev, 0x00f5, 0x02);
  978. VL6180x_WrByte(dev, 0x00d9, 0x05);
  979. VL6180x_WrByte(dev, 0x00db, 0xce);
  980. VL6180x_WrByte(dev, 0x00dc, 0x03);
  981. VL6180x_WrByte(dev, 0x00dd, 0xf8);
  982. VL6180x_WrByte(dev, 0x009f, 0x00);
  983. VL6180x_WrByte(dev, 0x00a3, 0x3c);
  984. VL6180x_WrByte(dev, 0x00b7, 0x00);
  985. VL6180x_WrByte(dev, 0x00bb, 0x3c); /*Recommended value = 0x28 in case very fast ranging frequency (~ 100 Hz)*/
  986. VL6180x_WrByte(dev, 0x00b2, 0x09);
  987. VL6180x_WrByte(dev, 0x00ca, 0x09);
  988. VL6180x_WrByte(dev, 0x0198, 0x01);
  989. VL6180x_WrByte(dev, 0x01b0, 0x17);
  990. VL6180x_WrByte(dev, 0x01ad, 0x00);
  991. VL6180x_WrByte(dev, 0x00ff, 0x05);
  992. VL6180x_WrByte(dev, 0x0100, 0x05);
  993. VL6180x_WrByte(dev, 0x0199, 0x05);
  994. VL6180x_WrByte(dev, 0x01a6, 0x1b);
  995. VL6180x_WrByte(dev, 0x01ac, 0x3e);
  996. VL6180x_WrByte(dev, 0x01a7, 0x1f);
  997. VL6180x_WrByte(dev, 0x0030, 0x00);
  998. /* Recommended : Public registers - See data sheet for more detail */
  999. VL6180x_WrByte(dev, 0x0011, 0x10); /* Enables polling for New Sample ready when measurement completes */
  1000. VL6180x_WrByte(dev, 0x010a, 0x30); /* Set the averaging sample period (compromise between lower noise and increased execution time) */
  1001. VL6180x_WrByte(dev, 0x003f, 0x46); /* Sets the light and dark gain (upper nibble). Dark gain should not be changed.*/
  1002. VL6180x_WrByte(dev, 0x0031, 0xFF); /* sets the # of range measurements after which auto calibration of system is performed */
  1003. VL6180x_WrByte(dev, 0x0040, 0x63); /* Set ALS integration time to 100ms */
  1004. VL6180x_WrByte(dev, 0x002e, 0x01); /* perform a single temperature calibration of the ranging sensor */
  1005. /* Optional: Public registers - See data sheet for more detail */
  1006. VL6180x_WrByte(dev, 0x001b, 0x09); /* Set default ranging inter-measurement period to 100ms */
  1007. VL6180x_WrByte(dev, 0x003e, 0x31); /* Set default ALS inter-measurement period to 500ms */
  1008. VL6180x_WrByte(dev, 0x0014, 0x24); /* Configures interrupt on New sample ready */
  1009. status = VL6180x_RangeSetMaxConvergenceTime(dev, 50); /* Calculate ece value on initialization (use max conv) */
  1010. LOG_FUNCTION_END(status);
  1011. return status;
  1012. }
  1013. #if VL6180x_UPSCALE_SUPPORT != 1
  1014. static int _UpscaleInitPatch0(VL6180xDev_t dev)
  1015. {
  1016. int status;
  1017. uint32_t CalValue = 0;
  1018. CalValue = VL6180xDevDataGet(dev, Part2PartAmbNVM);
  1019. status = VL6180x_WrDWord(dev, 0xDA, CalValue);
  1020. return status;
  1021. }
  1022. /* only include up-scaling register setting when up-scale support is configured in */
  1023. int VL6180x_UpscaleRegInit(VL6180xDev_t dev)
  1024. {
  1025. /* apply REGISTER_TUNING_ER02_100614_CustomerView.txt */
  1026. VL6180x_WrByte(dev, 0x0207, 0x01);
  1027. VL6180x_WrByte(dev, 0x0208, 0x01);
  1028. VL6180x_WrByte(dev, 0x0096, 0x00);
  1029. VL6180x_WrByte(dev, 0x0097, 0x54);
  1030. VL6180x_WrByte(dev, 0x00e3, 0x00);
  1031. VL6180x_WrByte(dev, 0x00e4, 0x04);
  1032. VL6180x_WrByte(dev, 0x00e5, 0x02);
  1033. VL6180x_WrByte(dev, 0x00e6, 0x01);
  1034. VL6180x_WrByte(dev, 0x00e7, 0x03);
  1035. VL6180x_WrByte(dev, 0x00f5, 0x02);
  1036. VL6180x_WrByte(dev, 0x00d9, 0x05);
  1037. _UpscaleInitPatch0(dev);
  1038. VL6180x_WrByte(dev, 0x009f, 0x00);
  1039. VL6180x_WrByte(dev, 0x00a3, 0x28);
  1040. VL6180x_WrByte(dev, 0x00b7, 0x00);
  1041. VL6180x_WrByte(dev, 0x00bb, 0x28);
  1042. VL6180x_WrByte(dev, 0x00b2, 0x09);
  1043. VL6180x_WrByte(dev, 0x00ca, 0x09);
  1044. VL6180x_WrByte(dev, 0x0198, 0x01);
  1045. VL6180x_WrByte(dev, 0x01b0, 0x17);
  1046. VL6180x_WrByte(dev, 0x01ad, 0x00);
  1047. VL6180x_WrByte(dev, 0x00ff, 0x05);
  1048. VL6180x_WrByte(dev, 0x0100, 0x05);
  1049. VL6180x_WrByte(dev, 0x0199, 0x05);
  1050. VL6180x_WrByte(dev, 0x01a6, 0x1b);
  1051. VL6180x_WrByte(dev, 0x01ac, 0x3e);
  1052. VL6180x_WrByte(dev, 0x01a7, 0x1f);
  1053. VL6180x_WrByte(dev, 0x0030, 0x00);
  1054. VL6180x_WrByte(dev, 0x0011, 0x10);
  1055. VL6180x_WrByte(dev, 0x010a, 0x30);
  1056. VL6180x_WrByte(dev, 0x003f, 0x46);
  1057. VL6180x_WrByte(dev, 0x0031, 0xFF);
  1058. VL6180x_WrByte(dev, 0x0040, 0x63);
  1059. VL6180x_WrByte(dev, 0x002e, 0x01);
  1060. VL6180x_WrByte(dev, 0x002c, 0xff);
  1061. VL6180x_WrByte(dev, 0x001b, 0x09);
  1062. VL6180x_WrByte(dev, 0x003e, 0x31);
  1063. VL6180x_WrByte(dev, 0x0014, 0x24);
  1064. #if VL6180x_EXTENDED_RANGE
  1065. VL6180x_RangeSetMaxConvergenceTime(dev, 63);
  1066. #else
  1067. VL6180x_RangeSetMaxConvergenceTime(dev, 50);
  1068. #endif
  1069. return 0;
  1070. }
  1071. #else
  1072. #define VL6180x_UpscaleRegInit(...) -1
  1073. #endif
  1074. int VL6180x_UpscaleSetScaling(VL6180xDev_t dev, uint8_t scaling)
  1075. {
  1076. int status;
  1077. uint16_t Scaler;
  1078. uint16_t ValidHeight;
  1079. int8_t Offset;
  1080. LOG_FUNCTION_START("%d", (int)scaling);
  1081. #ifdef VL6180x_HAVE_UPSCALE_DATA
  1082. #define min_scaling 1
  1083. #define max_scaling (sizeof(ScalerLookUP) / sizeof(ScalerLookUP[0]))
  1084. #else
  1085. /* we are in fixed config so only allow configured factor */
  1086. #define min_scaling VL6180x_UPSCALE_SUPPORT
  1087. #define max_scaling VL6180x_UPSCALE_SUPPORT
  1088. #endif
  1089. if (scaling >= min_scaling && scaling <= max_scaling) {
  1090. Scaler = ScalerLookUP[scaling - 1];
  1091. status = VL6180x_WrWord(dev, RANGE_SCALER, Scaler);
  1092. _SetUpscale(dev, scaling);
  1093. /* Apply scaling on part-2-part offset */
  1094. Offset = VL6180xDevDataGet(dev, Part2PartOffsetNVM) / scaling;
  1095. status = VL6180x_WrByte(dev, SYSRANGE_PART_TO_PART_RANGE_OFFSET, Offset);
  1096. /* Apply scaling on CrossTalkValidHeight */
  1097. if (status == 0) {
  1098. status = VL6180x_WrByte(dev, SYSRANGE_CROSSTALK_VALID_HEIGHT,
  1099. DEF_CROSS_TALK_VALID_HEIGHT_VALUE / scaling);
  1100. }
  1101. /* Apply scaling on RangeIgnore ValidHeight if enabled */
  1102. if( status == 0){
  1103. if( VL6180xDevDataGet(dev, RangeIgnore.Enabled) !=0 ){
  1104. ValidHeight = VL6180xDevDataGet(dev, RangeIgnore.ValidHeight);
  1105. ValidHeight /= _GetUpscale(dev);
  1106. if( ValidHeight > 255 )
  1107. ValidHeight = 255;
  1108. status = VL6180x_WrByte(dev, SYSRANGE_RANGE_IGNORE_VALID_HEIGHT,
  1109. ValidHeight );
  1110. }
  1111. }
  1112. #if !VL6180x_EXTENDED_RANGE
  1113. if (status == 0) {
  1114. status = VL6180x_RangeSetEceState(dev, scaling == 1); /* enable ece only at 1x scaling */
  1115. }
  1116. if (status == 0 && !VL6180x_EXTENDED_RANGE && scaling != 1) {
  1117. status = NOT_GUARANTEED ;
  1118. }
  1119. #endif
  1120. } else {
  1121. status = INVALID_PARAMS;
  1122. }
  1123. #undef min_scaling
  1124. #undef max_scaling
  1125. LOG_FUNCTION_END(status);
  1126. return status;
  1127. }
  1128. int VL6180x_UpscaleGetScaling(VL6180xDev_t dev)
  1129. {
  1130. int status;
  1131. LOG_FUNCTION_START("");
  1132. status = _GetUpscale(dev);
  1133. LOG_FUNCTION_END(status);
  1134. return status;
  1135. }
  1136. static int VL6180x_UpscaleStaticInit(VL6180xDev_t dev)
  1137. {
  1138. /* todo make these a fail macro in case only 1x is suppoted */
  1139. int status;
  1140. LOG_FUNCTION_START("");
  1141. do {
  1142. status = VL6180x_UpscaleRegInit(dev);
  1143. if (status) {
  1144. VL6180x_ErrLog("regInit fail");
  1145. break;
  1146. }
  1147. #if VL6180x_EXTENDED_RANGE
  1148. status = VL6180x_RangeSetEceState(dev, 0);
  1149. if (status) {
  1150. VL6180x_ErrLog("VL6180x_RangeSetEceState fail");
  1151. break;
  1152. }
  1153. #endif
  1154. } while (0);
  1155. if (!status) {
  1156. /* must write the scaler at least once to the device to ensure the scaler is in a known state. */
  1157. status = VL6180x_UpscaleSetScaling(dev, _GetUpscale(dev));
  1158. VL6180x_WrByte(dev, 0x016, 0x00); /* change fresh out of set status to 0 */
  1159. }
  1160. LOG_FUNCTION_END(status);
  1161. return status;
  1162. }
  1163. int VL6180x_SetGPIOxPolarity(VL6180xDev_t dev, int pin, int active_high)
  1164. {
  1165. int status;
  1166. LOG_FUNCTION_START("%d %d", (int) pin, (int)active_high);
  1167. if (pin == 0 || pin == 1) {
  1168. uint16_t RegIndex;
  1169. uint8_t DataSet;
  1170. if (pin == 0)
  1171. RegIndex = SYSTEM_MODE_GPIO0;
  1172. else
  1173. RegIndex = SYSTEM_MODE_GPIO1;
  1174. if (active_high)
  1175. DataSet = GPIOx_POLARITY_SELECT_MASK;
  1176. else
  1177. DataSet = 0;
  1178. status = VL6180x_UpdateByte(dev, RegIndex, (uint8_t)~GPIOx_POLARITY_SELECT_MASK, DataSet);
  1179. } else {
  1180. VL6180x_ErrLog("Invalid pin param %d", (int)pin);
  1181. status = INVALID_PARAMS;
  1182. }
  1183. LOG_FUNCTION_END(status);
  1184. return status;
  1185. }
  1186. int VL6180x_SetGPIOxFunctionality(VL6180xDev_t dev, int pin, uint8_t functionality)
  1187. {
  1188. int status;
  1189. LOG_FUNCTION_START("%d %d", (int) pin, (int)functionality);
  1190. if (((pin == 0) || (pin == 1)) && IsValidGPIOFunction(functionality)) {
  1191. uint16_t RegIndex;
  1192. if (pin == 0)
  1193. RegIndex = SYSTEM_MODE_GPIO0;
  1194. else
  1195. RegIndex = SYSTEM_MODE_GPIO1;
  1196. status = VL6180x_UpdateByte(dev, RegIndex, (uint8_t)~GPIOx_FUNCTIONALITY_SELECT_MASK,
  1197. functionality << GPIOx_FUNCTIONALITY_SELECT_SHIFT);
  1198. if (status) {
  1199. VL6180x_ErrLog("Update SYSTEM_MODE_GPIO%d fail", (int)pin);
  1200. }
  1201. } else {
  1202. VL6180x_ErrLog("Invalid pin %d or function %d", (int)pin, (int)functionality);
  1203. status = INVALID_PARAMS;
  1204. }
  1205. LOG_FUNCTION_END(status);
  1206. return status;
  1207. }
  1208. int VL6180x_SetupGPIOx(VL6180xDev_t dev, int pin, uint8_t IntFunction, int ActiveHigh)
  1209. {
  1210. int status;
  1211. LOG_FUNCTION_START("%d %d", (int) pin, (int)IntFunction);
  1212. if (((pin == 0) || (pin == 1)) && IsValidGPIOFunction(IntFunction)) {
  1213. uint16_t RegIndex;
  1214. uint8_t value = 0;
  1215. if (pin == 0)
  1216. RegIndex = SYSTEM_MODE_GPIO0;
  1217. else
  1218. RegIndex = SYSTEM_MODE_GPIO1;
  1219. if (ActiveHigh)
  1220. value |= GPIOx_POLARITY_SELECT_MASK;
  1221. value |= IntFunction << GPIOx_FUNCTIONALITY_SELECT_SHIFT;
  1222. status = VL6180x_WrByte(dev, RegIndex, value);
  1223. if (status) {
  1224. VL6180x_ErrLog("SYSTEM_MODE_GPIO%d wr fail", (int)pin-SYSTEM_MODE_GPIO0);
  1225. }
  1226. } else {
  1227. VL6180x_ErrLog("Invalid pin %d or function %d", (int)pin, (int) IntFunction);
  1228. status = INVALID_PARAMS;
  1229. }
  1230. LOG_FUNCTION_END(status);
  1231. return status;
  1232. }
  1233. int VL6180x_DisableGPIOxOut(VL6180xDev_t dev, int pin)
  1234. {
  1235. int status;
  1236. LOG_FUNCTION_START("%d", (int)pin);
  1237. status = VL6180x_SetGPIOxFunctionality(dev, pin, GPIOx_SELECT_OFF);
  1238. LOG_FUNCTION_END(status);
  1239. return status;
  1240. }
  1241. int VL6180x_SetupGPIO1(VL6180xDev_t dev, uint8_t IntFunction, int ActiveHigh)
  1242. {
  1243. int status;
  1244. LOG_FUNCTION_START("%d %d", (int)IntFunction, (int)ActiveHigh);
  1245. status = VL6180x_SetupGPIOx(dev, 1, IntFunction, ActiveHigh);
  1246. LOG_FUNCTION_END(status);
  1247. return status;
  1248. }
  1249. int VL6180x_RangeConfigInterrupt(VL6180xDev_t dev, uint8_t ConfigGpioInt)
  1250. {
  1251. int status;
  1252. if (ConfigGpioInt <= CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY) {
  1253. status = VL6180x_UpdateByte(dev, SYSTEM_INTERRUPT_CONFIG_GPIO,
  1254. (uint8_t)(~CONFIG_GPIO_RANGE_MASK),
  1255. ConfigGpioInt);
  1256. } else {
  1257. VL6180x_ErrLog("Invalid config mode param %d", (int)ConfigGpioInt);
  1258. status = INVALID_PARAMS;
  1259. }
  1260. LOG_FUNCTION_END(status);
  1261. return status;
  1262. }
  1263. int VL6180x_RangeSetEceFactor(VL6180xDev_t dev, uint16_t FactorM, uint16_t FactorD)
  1264. {
  1265. int status;
  1266. uint8_t u8;
  1267. LOG_FUNCTION_START("%d %d", (int)FactorM, (int)FactorD);
  1268. do {
  1269. /* D cannot be 0 M must be <=D and >= 0 */
  1270. if (FactorM <= FactorD && FactorD > 0) {
  1271. VL6180xDevDataSet(dev, EceFactorM, FactorM);
  1272. VL6180xDevDataSet(dev, EceFactorD, FactorD);
  1273. /* read and re-apply max conv time to get new ece factor set */
  1274. status = VL6180x_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &u8);
  1275. if (status) {
  1276. VL6180x_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail ");
  1277. break;
  1278. }
  1279. status = VL6180x_RangeSetMaxConvergenceTime(dev, u8);
  1280. if (status < 0) {
  1281. VL6180x_ErrLog("fail to apply time after ece m/d change");
  1282. break;
  1283. }
  1284. } else {
  1285. VL6180x_ErrLog("invalid factor %d/%d", (int)FactorM, (int)FactorD);
  1286. status = INVALID_PARAMS;
  1287. }
  1288. } while (0);
  1289. LOG_FUNCTION_END(status);
  1290. return status;
  1291. }
  1292. int VL6180x_RangeSetEceState(VL6180xDev_t dev, int enable)
  1293. {
  1294. int status;
  1295. uint8_t or_mask;
  1296. LOG_FUNCTION_START("%d", (int)enable);
  1297. if (enable)
  1298. or_mask = RANGE_CHECK_ECE_ENABLE_MASK;
  1299. else
  1300. or_mask = 0;
  1301. status = VL6180x_UpdateByte(dev, SYSRANGE_RANGE_CHECK_ENABLES, ~RANGE_CHECK_ECE_ENABLE_MASK, or_mask);
  1302. LOG_FUNCTION_END(status);
  1303. return status;
  1304. }
  1305. int VL6180x_RangeSetMaxConvergenceTime(VL6180xDev_t dev, uint8_t MaxConTime_msec)
  1306. {
  1307. int status = 0;
  1308. LOG_FUNCTION_START("%d", (int)MaxConTime_msec);
  1309. do {
  1310. status = VL6180x_WrByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, MaxConTime_msec);
  1311. if (status) {
  1312. break;
  1313. }
  1314. status = VL6180x_RangeSetEarlyConvergenceEestimateThreshold(dev);
  1315. if (status) {
  1316. break;
  1317. }
  1318. status = _DMax_InitData(dev);
  1319. } while (0);
  1320. LOG_FUNCTION_END(status);
  1321. return status;
  1322. }
  1323. int VL6180x_RangeSetInterMeasPeriod(VL6180xDev_t dev, uint32_t InterMeasTime_msec)
  1324. {
  1325. uint8_t SetTime;
  1326. int status;
  1327. LOG_FUNCTION_START("%d", (int)InterMeasTime_msec);
  1328. do {
  1329. if (InterMeasTime_msec > 2550) {
  1330. status = INVALID_PARAMS;
  1331. break;
  1332. }
  1333. /* doc in not 100% clear and confusing about the limit practically all value are OK but 0
  1334. * that can hang device in continuous mode */
  1335. if (InterMeasTime_msec < 10) {
  1336. InterMeasTime_msec = 10;
  1337. }
  1338. SetTime = (uint8_t)(InterMeasTime_msec / 10);
  1339. status = VL6180x_WrByte(dev, SYSRANGE_INTERMEASUREMENT_PERIOD, SetTime);
  1340. if (status) {
  1341. VL6180x_ErrLog("SYSRANGE_INTERMEASUREMENT_PERIOD wr fail");
  1342. } else if (SetTime != InterMeasTime_msec / 10) {
  1343. status = MIN_CLIPED; /* on success change status to clip if it did */
  1344. }
  1345. } while (0);
  1346. LOG_FUNCTION_END(status);
  1347. return status;
  1348. }
  1349. int VL6180x_RangeGetDeviceReady(VL6180xDev_t dev, int *Ready)
  1350. {
  1351. int status;
  1352. uint8_t u8;
  1353. LOG_FUNCTION_START("%p", (int)Ready);
  1354. status = VL6180x_RdByte(dev, RESULT_RANGE_STATUS, &u8);
  1355. if (!status)
  1356. *Ready = u8&RANGE_DEVICE_READY_MASK;
  1357. LOG_FUNCTION_END_FMT(status, "%d", *Ready);
  1358. return status;
  1359. }
  1360. int VL6180x_RangeWaitDeviceReady(VL6180xDev_t dev, int MaxLoop)
  1361. {
  1362. int status = 0; /* if user specify an invalid <=0 loop count we'll return error */
  1363. int n;
  1364. uint8_t u8;
  1365. LOG_FUNCTION_START("%d", (int)MaxLoop);
  1366. if (MaxLoop < 1) {
  1367. status = INVALID_PARAMS;
  1368. } else {
  1369. for (n = 0; n < MaxLoop ; n++) {
  1370. status = VL6180x_RdByte(dev, RESULT_RANGE_STATUS, &u8);
  1371. if (status)
  1372. break;
  1373. u8 = u8 & RANGE_DEVICE_READY_MASK;
  1374. if (u8)
  1375. break;
  1376. }
  1377. if (!status && !u8) {
  1378. status = TIME_OUT;
  1379. }
  1380. }
  1381. LOG_FUNCTION_END(status);
  1382. return status;
  1383. }
  1384. int VL6180x_RangeSetSystemMode(VL6180xDev_t dev, uint8_t mode)
  1385. {
  1386. int status;
  1387. LOG_FUNCTION_START("%d", (int)mode);
  1388. /* FIXME we are not checking device is ready via @a VL6180x_RangeWaitDeviceReady
  1389. * so if called back to back real fast we are not checking
  1390. * if previous mode "set" got absorbed => bit 0 must be 0 so that it work
  1391. */
  1392. if (mode <= 3) {
  1393. status = VL6180x_WrByte(dev, SYSRANGE_START, mode);
  1394. if (status) {
  1395. VL6180x_ErrLog("SYSRANGE_START wr fail");
  1396. }
  1397. } else {
  1398. status = INVALID_PARAMS;
  1399. }
  1400. LOG_FUNCTION_END(status);
  1401. return status;
  1402. }
  1403. int VL6180x_RangeStartContinuousMode(VL6180xDev_t dev)
  1404. {
  1405. int status;
  1406. LOG_FUNCTION_START("");
  1407. status = VL6180x_RangeSetSystemMode(dev, MODE_START_STOP | MODE_CONTINUOUS);
  1408. LOG_FUNCTION_END(status);
  1409. return status;
  1410. }
  1411. int VL6180x_RangeStartSingleShot(VL6180xDev_t dev)
  1412. {
  1413. int status;
  1414. LOG_FUNCTION_START("");
  1415. status = VL6180x_RangeSetSystemMode(dev, MODE_START_STOP | MODE_SINGLESHOT);
  1416. LOG_FUNCTION_END(status);
  1417. return status;
  1418. }
  1419. static int VL6180x_RangeSetEarlyConvergenceEestimateThreshold(VL6180xDev_t dev)
  1420. {
  1421. int status;
  1422. const uint32_t cMicroSecPerMilliSec = 1000;
  1423. const uint32_t cEceSampleTime_us = 500;
  1424. uint32_t ece_factor_m = VL6180xDevDataGet(dev, EceFactorM);
  1425. uint32_t ece_factor_d = VL6180xDevDataGet(dev, EceFactorD);
  1426. uint32_t convergTime_us;
  1427. uint32_t fineThresh;
  1428. uint32_t eceThresh;
  1429. uint8_t u8;
  1430. uint32_t maxConv_ms;
  1431. int32_t AveTime;
  1432. LOG_FUNCTION_START("");
  1433. do {
  1434. status = VL6180x_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &u8);
  1435. if (status) {
  1436. VL6180x_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail");
  1437. break;
  1438. }
  1439. maxConv_ms = u8;
  1440. AveTime = _GetAveTotalTime(dev);
  1441. if (AveTime < 0) {
  1442. status = -1;
  1443. break;
  1444. }
  1445. convergTime_us = maxConv_ms * cMicroSecPerMilliSec - AveTime;
  1446. status = VL6180x_RdDWord(dev, 0xB8, &fineThresh);
  1447. if (status) {
  1448. VL6180x_ErrLog("reg 0xB8 rd fail");
  1449. break;
  1450. }
  1451. fineThresh *= 256;
  1452. eceThresh = ece_factor_m * cEceSampleTime_us * fineThresh / (convergTime_us * ece_factor_d);
  1453. status = VL6180x_WrWord(dev, SYSRANGE_EARLY_CONVERGENCE_ESTIMATE, (uint16_t)eceThresh);
  1454. } while (0);
  1455. LOG_FUNCTION_END(status);
  1456. return status;
  1457. }
  1458. static int _RangeIgnore_UpdateDevice(VL6180xDev_t dev){
  1459. int status;
  1460. int enable;
  1461. int threshold;
  1462. int range;
  1463. int or_mask;
  1464. enable= VL6180xDevDataGet(dev, RangeIgnore.Enabled);
  1465. if( enable ){
  1466. // if to be nabled program first range value and threshold
  1467. range = VL6180xDevDataGet(dev, RangeIgnore.ValidHeight);
  1468. range /= _GetUpscale(dev);
  1469. if( range > 255 )
  1470. range = 255;
  1471. status = VL6180x_WrByte(dev, SYSRANGE_RANGE_IGNORE_VALID_HEIGHT, range);
  1472. if( status ){
  1473. goto done;
  1474. }
  1475. threshold = VL6180xDevDataGet(dev, RangeIgnore.IgnoreThreshold);
  1476. status = VL6180x_WrWord(dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, threshold);
  1477. if( status ){
  1478. goto done;
  1479. }
  1480. or_mask = RANGE_CHECK_RANGE_ENABLE_MASK;
  1481. }
  1482. else{
  1483. or_mask = 0;
  1484. }
  1485. status = VL6180x_UpdateByte(dev, SYSRANGE_RANGE_CHECK_ENABLES, ~RANGE_CHECK_RANGE_ENABLE_MASK, or_mask);
  1486. _DMax_InitData(dev);
  1487. done:
  1488. return status;
  1489. }
  1490. int VL6180x_RangeIgnoreSetEnable(VL6180xDev_t dev, int EnableState){
  1491. int CurEnable;
  1492. int status;
  1493. LOG_FUNCTION_START("enable %d", EnableState);
  1494. if( EnableState )
  1495. EnableState = 1;
  1496. CurEnable = VL6180xDevDataGet(dev, RangeIgnore.Enabled);
  1497. if( EnableState != CurEnable ){
  1498. VL6180xDevDataSet(dev, RangeIgnore.Enabled, EnableState);
  1499. status = _RangeIgnore_UpdateDevice(dev);
  1500. }
  1501. LOG_FUNCTION_END(status);
  1502. return status;
  1503. }
  1504. int VL6180x_RangeIgnoreConfigure(VL6180xDev_t dev, uint16_t ValidHeight_mm, uint16_t IgnoreThreshold){
  1505. int status;
  1506. int enabled;
  1507. LOG_FUNCTION_START("height= %d Threshold=%d", (int)ValidHeight_mm, (int)Threshold);
  1508. enabled = VL6180xDevDataGet(dev, RangeIgnore.Enabled);
  1509. VL6180xDevDataSet(dev, RangeIgnore.ValidHeight, ValidHeight_mm);
  1510. VL6180xDevDataSet(dev, RangeIgnore.IgnoreThreshold, IgnoreThreshold);
  1511. if( enabled ){
  1512. status = _RangeIgnore_UpdateDevice(dev);
  1513. }
  1514. else{
  1515. status = 0;
  1516. }
  1517. LOG_FUNCTION_END(status);
  1518. return status;
  1519. }
  1520. /*
  1521. * Return >0 = time
  1522. * <0 1 if fail to get read data from device to compute time
  1523. */
  1524. static int32_t _GetAveTotalTime(VL6180xDev_t dev)
  1525. {
  1526. uint32_t cFwOverhead_us = 24;
  1527. uint32_t cVcpSetupTime_us = 70;
  1528. uint32_t cPLL2_StartupDelay_us = 200;
  1529. uint8_t cMeasMask = 0x07;
  1530. uint32_t Samples;
  1531. uint32_t SamplePeriod;
  1532. uint32_t SingleTime_us;
  1533. int32_t TotalAveTime_us;
  1534. uint8_t u8;
  1535. int status;
  1536. LOG_FUNCTION_START("");
  1537. status = VL6180x_RdByte(dev, 0x109, &u8);
  1538. if (status) {
  1539. VL6180x_ErrLog("rd 0x109 fail");
  1540. return -1;
  1541. }
  1542. Samples = u8 & cMeasMask;
  1543. status = VL6180x_RdByte(dev, READOUT_AVERAGING_SAMPLE_PERIOD, &u8);
  1544. if (status) {
  1545. VL6180x_ErrLog("i2c READOUT_AVERAGING_SAMPLE_PERIOD fail");
  1546. return -1;
  1547. }
  1548. SamplePeriod = u8;
  1549. SingleTime_us = cFwOverhead_us + cVcpSetupTime_us + (SamplePeriod * 10);
  1550. TotalAveTime_us = (Samples + 1) * SingleTime_us + cPLL2_StartupDelay_us;
  1551. LOG_FUNCTION_END(TotalAveTime_us);
  1552. return TotalAveTime_us;
  1553. }
  1554. #if VL6180x_HAVE_DMAX_RANGING
  1555. #define _GetDMaxDataRetSignalAt400mm(dev) VL6180xDevDataGet(dev, DMaxData.retSignalAt400mm)
  1556. #else
  1557. #define _GetDMaxDataRetSignalAt400mm(dev) 375 /* Use a default high value */
  1558. #endif
  1559. #if VL6180x_WRAP_AROUND_FILTER_SUPPORT
  1560. #define PRESERVE_DEVICE_ERROR_CODE /* If uncommented, device error code will be preserved on top of wraparound error code, but this may lead to some error code instability like overflow error <==> RangingFilteringOnGoing error oscillations */
  1561. #define SENSITIVE_FILTERING_ON_GOING /* If uncommented, filter will go back to RangingFilteringOnGoing if it must go through the std dev testing */
  1562. #define FILTER_STDDEV_SAMPLES 6
  1563. #define MIN_FILTER_STDDEV_SAMPLES 3
  1564. #define MIN_FILTER_STDDEV_SAMPLES_AFTER_FLUSH_OR_BYPASS 5
  1565. #define STDDEV_BASE_VALUE 150
  1566. #define FILTER_INVALID_DISTANCE 65535
  1567. #define _FilterData(field) VL6180xDevDataGet(dev, FilterData.field)
  1568. /*
  1569. * One time init
  1570. */
  1571. int _filter_Init(VL6180xDev_t dev)
  1572. {
  1573. int i;
  1574. _FilterData(MeasurementIndex) = 0;
  1575. _FilterData(Default_ZeroVal) = 0;
  1576. _FilterData(Default_VAVGVal) = 0;
  1577. _FilterData(NoDelay_ZeroVal) = 0;
  1578. _FilterData(NoDelay_VAVGVal) = 0;
  1579. _FilterData(Previous_VAVGDiff) = 0;
  1580. _FilterData(StdFilteredReads) = 0;
  1581. _FilterData(FilteringOnGoingConsecutiveStates) = 0;
  1582. for (i = 0; i < FILTER_NBOF_SAMPLES; i++) {
  1583. _FilterData(LastTrueRange)[i] = FILTER_INVALID_DISTANCE;
  1584. _FilterData(LastReturnRates)[i] = 0;
  1585. }
  1586. _FilterData(MeasurementsSinceLastFlush)=0;
  1587. return 0;
  1588. }
  1589. static uint32_t _filter_StdDevDamper(uint32_t AmbientRate,
  1590. uint32_t SignalRate,
  1591. const uint32_t StdDevLimitLowLight,
  1592. const uint32_t StdDevLimitLowLightSNR,
  1593. const uint32_t StdDevLimitHighLight,
  1594. const uint32_t StdDevLimitHighLightSNR)
  1595. {
  1596. uint32_t newStdDev;
  1597. uint16_t SNR;
  1598. if (AmbientRate > 0)
  1599. SNR = (uint16_t) ((100 * SignalRate) / AmbientRate);
  1600. else
  1601. SNR = 9999;
  1602. if (SNR >= StdDevLimitLowLightSNR) {
  1603. newStdDev = StdDevLimitLowLight;
  1604. } else {
  1605. if (SNR <= StdDevLimitHighLightSNR)
  1606. newStdDev = StdDevLimitHighLight;
  1607. else {
  1608. newStdDev = (uint32_t)(StdDevLimitHighLight -
  1609. (SNR - StdDevLimitHighLightSNR) *
  1610. (StdDevLimitHighLight - StdDevLimitLowLight) /
  1611. (StdDevLimitLowLightSNR - StdDevLimitHighLightSNR));
  1612. }
  1613. }
  1614. return newStdDev;
  1615. }
  1616. /*
  1617. * Return <0 on error
  1618. */
  1619. static int32_t _filter_Start(VL6180xDev_t dev,
  1620. uint16_t m_trueRange_mm,
  1621. uint16_t m_rawRange_mm,
  1622. uint32_t m_rtnSignalRate,
  1623. uint32_t m_rtnAmbientRate,
  1624. uint16_t errorCode)
  1625. {
  1626. int status;
  1627. uint16_t m_newTrueRange_mm = 0;
  1628. #if VL6180x_HAVE_MULTI_READ
  1629. uint8_t MultiReadBuf[8];
  1630. #endif
  1631. uint16_t i;
  1632. uint16_t bypassFilter = 0;
  1633. uint16_t resetVAVGData = 1;
  1634. uint16_t filterErrorCode = NoError;
  1635. uint16_t filterErrorCodeOnRangingErrorCode = NoError;
  1636. uint16_t registerValue;
  1637. uint32_t register32BitsValue1;
  1638. uint32_t register32BitsValue2;
  1639. uint16_t ValidDistance = 0;
  1640. uint16_t SuspicuousRangingZone = 0;
  1641. uint16_t WrapAroundFlag = 0;
  1642. uint16_t NoWrapAroundFlag = 0;
  1643. uint16_t NoWrapAroundHighConfidenceFlag = 0;
  1644. uint16_t FlushFilter = 0;
  1645. uint32_t RateChange = 0;
  1646. uint16_t StdDevSamplesMinNeeded = 0;
  1647. uint16_t StdDevSamples = 0;
  1648. uint32_t StdDevDistanceSum = 0;
  1649. uint32_t StdDevDistanceMean = 0;
  1650. uint32_t StdDevDistance = 0;
  1651. uint32_t StdDevRateSum = 0;
  1652. uint32_t StdDevRateMean = 0;
  1653. uint32_t StdDevRate = 0;
  1654. uint32_t StdDevLimitWithTargetMove = 0;
  1655. uint32_t VAVGDiff;
  1656. uint32_t IdealVAVGDiff;
  1657. uint32_t MinVAVGDiff;
  1658. uint32_t MaxVAVGDiff;
  1659. /* Filter Parameters */
  1660. static const uint16_t ROMABLE_DATA WrapAroundLowRawRangeLimit = 60;
  1661. static const uint32_t ROMABLE_DATA WrapAroundLowReturnRateLimit_ROM = 800;
  1662. /* Shall be adapted depending on crossTalk */
  1663. static const uint16_t ROMABLE_DATA WrapAroundLowRawRangeLimit2 = 165;
  1664. static const uint32_t ROMABLE_DATA WrapAroundLowReturnRateLimit2_ROM = 180;
  1665. /* Shall be adapted depending on crossTalk and device sensitivity*/
  1666. static const uint32_t ROMABLE_DATA WrapAroundLowRawRangeLimit2SuspicuousAddedSignalRate = 150;
  1667. static const uint32_t ROMABLE_DATA WrapAroundLowReturnRateFilterLimit_ROM = 850;
  1668. /* Shall be adapted depending on crossTalk and device sensitivity*/
  1669. static const uint16_t ROMABLE_DATA WrapAroundHighRawRangeFilterLimit = 350;
  1670. static const uint32_t ROMABLE_DATA WrapAroundHighReturnRateFilterLimit_ROM = 1400;
  1671. /* Shall be adapted depending on crossTalk and device sensitivity*/
  1672. static const uint32_t ROMABLE_DATA WrapAroundMaximumAmbientRateFilterLimit = 15000;
  1673. /* Temporal filter data and flush values */
  1674. static const uint32_t ROMABLE_DATA MinReturnRateFilterFlush = 75;
  1675. static const uint32_t ROMABLE_DATA MaxReturnRateChangeFilterFlush = 50;
  1676. /* STDDEV values and damper values */
  1677. static const uint32_t ROMABLE_DATA StdDevLimitLowLight = STDDEV_BASE_VALUE;
  1678. static const uint32_t ROMABLE_DATA StdDevLimitLowLightSNR = 30; /* 0.3 */
  1679. static const uint32_t ROMABLE_DATA StdDevLimitHighLight = STDDEV_BASE_VALUE*6;
  1680. static const uint32_t ROMABLE_DATA StdDevLimitHighLightSNR = 5; /* 0.05 */
  1681. static const uint32_t ROMABLE_DATA StdDevHighConfidenceSNRLimit = 8;
  1682. static const uint32_t ROMABLE_DATA StdDevNoWrapDetectedMultiplier = 4;
  1683. static const uint32_t ROMABLE_DATA StdDevMovingTargetStdDevLimit = 90000;
  1684. static const uint32_t ROMABLE_DATA StdDevMovingTargetReturnRateLimit = 3500;
  1685. static const uint32_t ROMABLE_DATA StdDevMovingTargetStdDevForReturnRateLimit = STDDEV_BASE_VALUE*25;
  1686. static const uint32_t ROMABLE_DATA MAX_VAVGDiff_ROM = 1800;
  1687. static const uint32_t ROMABLE_DATA SuspicuousMAX_VAVGDiffRatio = 2;
  1688. /* WrapAroundDetection variables */
  1689. static const uint16_t ROMABLE_DATA WrapAroundNoDelayCheckPeriod = 2;
  1690. static const uint16_t ROMABLE_DATA StdFilteredReadsIncrement = 2;
  1691. static const uint16_t ROMABLE_DATA StdFilteredReadsDecrement = 1;
  1692. static const uint16_t ROMABLE_DATA StdMaxFilteredReads = 4;
  1693. uint32_t SignalRateDMax;
  1694. uint32_t WrapAroundLowReturnRateLimit;
  1695. uint32_t WrapAroundLowReturnRateLimit2;
  1696. uint32_t WrapAroundLowReturnRateFilterLimit;
  1697. uint32_t WrapAroundHighReturnRateFilterLimit;
  1698. uint32_t MAX_VAVGDiff = 1800;
  1699. uint8_t u8;//, u8_2;
  1700. uint32_t XTalkCompRate_KCps;
  1701. uint32_t StdDevLimit = 300;
  1702. uint32_t MaxOrInvalidDistance = 255*_GetUpscale(dev);
  1703. /* #define MaxOrInvalidDistance (uint16_t) (255 * 3) */
  1704. /* Check if distance is Valid or not */
  1705. switch (errorCode) {
  1706. case Raw_Ranging_Algo_Underflow:
  1707. case Ranging_Algo_Underflow:
  1708. filterErrorCodeOnRangingErrorCode = RangingFiltered; /* If we have to go through filter, mean we have here a wraparound case */
  1709. ValidDistance = 0;
  1710. break;
  1711. case Raw_Ranging_Algo_Overflow:
  1712. case Ranging_Algo_Overflow:
  1713. filterErrorCodeOnRangingErrorCode = RangingFiltered; /* If we have to go through filter, mean we have here a wraparound case */
  1714. //m_trueRange_mm = MaxOrInvalidDistance;
  1715. m_trueRange_mm = 200*_GetUpscale(dev);
  1716. ValidDistance = 1;
  1717. break;
  1718. default:
  1719. if (m_rawRange_mm >= MaxOrInvalidDistance) {
  1720. ValidDistance = 0;
  1721. bypassFilter = 1; /* Bypass the filter in this case as produced distance is not usable (and also the VAVGVal and ZeroVal values) */
  1722. } else {
  1723. ValidDistance = 1;
  1724. }
  1725. break;
  1726. }
  1727. m_newTrueRange_mm = m_trueRange_mm;
  1728. XTalkCompRate_KCps = VL6180xDevDataGet(dev, XTalkCompRate_KCps);
  1729. /* Update signal rate limits depending on crosstalk */
  1730. SignalRateDMax = (uint32_t)_GetDMaxDataRetSignalAt400mm(dev) ;
  1731. WrapAroundLowReturnRateLimit = WrapAroundLowReturnRateLimit_ROM + XTalkCompRate_KCps;
  1732. WrapAroundLowReturnRateLimit2 = ((WrapAroundLowReturnRateLimit2_ROM *
  1733. SignalRateDMax) / 312) +
  1734. XTalkCompRate_KCps;
  1735. WrapAroundLowReturnRateFilterLimit = ((WrapAroundLowReturnRateFilterLimit_ROM *
  1736. SignalRateDMax) / 312) + XTalkCompRate_KCps;
  1737. WrapAroundHighReturnRateFilterLimit = ((WrapAroundHighReturnRateFilterLimit_ROM *
  1738. SignalRateDMax) / 312) + XTalkCompRate_KCps;
  1739. /* Checks on low range data */
  1740. if ((m_rawRange_mm < WrapAroundLowRawRangeLimit) && (m_rtnSignalRate < WrapAroundLowReturnRateLimit)) {
  1741. filterErrorCode = RangingFiltered; /* On this condition, wraparound case is ensured */
  1742. bypassFilter = 1;
  1743. }
  1744. if ((m_rawRange_mm < WrapAroundLowRawRangeLimit2) && (m_rtnSignalRate < WrapAroundLowReturnRateLimit2)) {
  1745. filterErrorCode = RangingFiltered; /* On this condition, wraparound case is ensured */
  1746. bypassFilter = 1;
  1747. }
  1748. if ((m_rawRange_mm < WrapAroundLowRawRangeLimit2) && (m_rtnSignalRate < (WrapAroundLowReturnRateLimit2 + WrapAroundLowRawRangeLimit2SuspicuousAddedSignalRate))) {
  1749. SuspicuousRangingZone = 1; /* On this area, we are in an highly suspicuous wraparound ares, filter parameter will be stengthen */
  1750. }
  1751. /* Checks on Ambient rate level */
  1752. if (m_rtnAmbientRate > WrapAroundMaximumAmbientRateFilterLimit) {
  1753. /* Too high ambient rate */
  1754. FlushFilter = 1;
  1755. bypassFilter = 1;
  1756. }
  1757. /* Checks on Filter flush */
  1758. if (m_rtnSignalRate < MinReturnRateFilterFlush) {
  1759. /* Completely lost target, so flush the filter */
  1760. FlushFilter = 1;
  1761. bypassFilter = 1;
  1762. }
  1763. if (_FilterData(LastReturnRates)[0] != 0) {
  1764. if (m_rtnSignalRate > _FilterData(LastReturnRates)[0])
  1765. RateChange = (100 *
  1766. (m_rtnSignalRate - _FilterData(LastReturnRates)[0])) /
  1767. _FilterData(LastReturnRates)[0];
  1768. else
  1769. RateChange = (100 *
  1770. (_FilterData(LastReturnRates)[0] - m_rtnSignalRate)) /
  1771. _FilterData(LastReturnRates)[0];
  1772. } else
  1773. RateChange = 0;
  1774. if (RateChange > MaxReturnRateChangeFilterFlush) {
  1775. FlushFilter = 1;
  1776. }
  1777. /* TODO optimize filter using circular buffer */
  1778. if (FlushFilter == 1) {
  1779. _FilterData(MeasurementIndex) = 0;
  1780. for (i = 0; i < FILTER_NBOF_SAMPLES; i++) {
  1781. _FilterData(LastTrueRange)[i] = FILTER_INVALID_DISTANCE;
  1782. _FilterData(LastReturnRates)[i] = 0;
  1783. }
  1784. _FilterData(MeasurementsSinceLastFlush)=0;
  1785. } else {
  1786. for (i = (uint16_t) (FILTER_NBOF_SAMPLES - 1); i > 0; i--) {
  1787. _FilterData(LastTrueRange)[i] = _FilterData(LastTrueRange)[i - 1];
  1788. _FilterData(LastReturnRates)[i] = _FilterData(LastReturnRates)[i - 1];
  1789. }
  1790. }
  1791. if (ValidDistance == 1)
  1792. _FilterData(LastTrueRange)[0] = m_trueRange_mm;
  1793. else
  1794. _FilterData(LastTrueRange)[0] = FILTER_INVALID_DISTANCE;
  1795. _FilterData(LastReturnRates)[0] = m_rtnSignalRate;
  1796. _FilterData(MeasurementsSinceLastFlush)++;
  1797. /* Check if we need to go through the filter or not */
  1798. if (!(((m_rawRange_mm < WrapAroundHighRawRangeFilterLimit) &&
  1799. (m_rtnSignalRate < WrapAroundLowReturnRateFilterLimit)) ||
  1800. ((m_rawRange_mm >= WrapAroundHighRawRangeFilterLimit) &&
  1801. (m_rtnSignalRate < WrapAroundHighReturnRateFilterLimit))))
  1802. bypassFilter = 1;
  1803. else {
  1804. /* if some wraparound filtering due to some ranging error code has been detected, update the filter status and bypass the filter */
  1805. if(filterErrorCodeOnRangingErrorCode!=NoError){
  1806. #ifndef PRESERVE_DEVICE_ERROR_CODE
  1807. filterErrorCode = filterErrorCodeOnRangingErrorCode;
  1808. #else
  1809. if((errorCode==Raw_Ranging_Algo_Underflow) || (errorCode==Ranging_Algo_Underflow)) {
  1810. /* Preserves the error codes except for Raw_Ranging_Algo_Underflow and Ranging_Algo_Underflow */
  1811. filterErrorCode = filterErrorCodeOnRangingErrorCode;
  1812. }
  1813. #endif
  1814. bypassFilter = 1;
  1815. resetVAVGData = 0;
  1816. }
  1817. }
  1818. /* Check which kind of measurement has been made */
  1819. status = VL6180x_RdByte(dev, 0x01AC, &u8);
  1820. if (status) {
  1821. VL6180x_ErrLog("0x01AC rd fail");
  1822. goto done_err;
  1823. }
  1824. registerValue = u8;
  1825. /* Read data for filtering */
  1826. #if VL6180x_HAVE_MULTI_READ
  1827. status = VL6180x_RdMulti(dev, 0x10C, MultiReadBuf, 8); /* read only 8 lsb bits */
  1828. if (status) {
  1829. VL6180x_ErrLog("0x10C multi rd fail");
  1830. goto done_err;
  1831. }
  1832. register32BitsValue1 = ((uint32_t) MultiReadBuf[0] << 24)
  1833. + ((uint32_t) MultiReadBuf[1] << 16)
  1834. + ((uint32_t) MultiReadBuf[2] << 8)
  1835. + ((uint32_t) MultiReadBuf[3] << 0);
  1836. register32BitsValue2 = ((uint32_t) MultiReadBuf[4] << 24)
  1837. + ((uint32_t) MultiReadBuf[5] << 16)
  1838. + ((uint32_t) MultiReadBuf[6] << 8)
  1839. + ((uint32_t) MultiReadBuf[7] << 0);
  1840. #else
  1841. status = VL6180x_RdDWord(dev, 0x10C, &register32BitsValue1); /* read 32 bits, lower 17 bits are the one useful */
  1842. if (status) {
  1843. VL6180x_ErrLog("0x010C rd fail");
  1844. goto done_err;
  1845. }
  1846. status = VL6180x_RdDWord(dev, 0x0110, & register32BitsValue2); /* read 32 bits, lower 17 bits are the one useful */
  1847. if (status) {
  1848. VL6180x_ErrLog("0x0110 rd fail");
  1849. goto done_err;
  1850. }
  1851. #endif
  1852. if ((FlushFilter == 1) || ((bypassFilter == 1) && (resetVAVGData == 1))) {
  1853. if (registerValue != 0x3E) {
  1854. status = VL6180x_WrByte(dev, 0x1AC, 0x3E);
  1855. if (status) {
  1856. VL6180x_ErrLog("0x01AC bypass wr fail");
  1857. goto done_err;
  1858. }
  1859. //status = VL6180x_WrByte(dev, 0x0F2, 0x01);
  1860. //if (status) {
  1861. // VL6180x_ErrLog("0x0F2 bypass wr fail");
  1862. // goto done_err;
  1863. //}
  1864. }
  1865. /* Set both Default and NoDelay To same value */
  1866. _FilterData(Default_ZeroVal) = register32BitsValue1;
  1867. _FilterData(Default_VAVGVal) = register32BitsValue2;
  1868. _FilterData(NoDelay_ZeroVal) = register32BitsValue1;
  1869. _FilterData(NoDelay_VAVGVal) = register32BitsValue2;
  1870. _FilterData(MeasurementIndex) = 0;
  1871. } else {
  1872. if (registerValue == 0x3E) {
  1873. _FilterData(Default_ZeroVal) = register32BitsValue1;
  1874. _FilterData(Default_VAVGVal) = register32BitsValue2;
  1875. } else {
  1876. _FilterData(NoDelay_ZeroVal) = register32BitsValue1;
  1877. _FilterData(NoDelay_VAVGVal) = register32BitsValue2;
  1878. }
  1879. if (_FilterData(MeasurementIndex) % WrapAroundNoDelayCheckPeriod == 0) {
  1880. u8 = 0x3C;
  1881. //u8_2 = 0x05;
  1882. } else {
  1883. u8 = 0x3E;
  1884. //u8_2 = 0x01;
  1885. }
  1886. status = VL6180x_WrByte(dev, 0x01AC, u8);
  1887. if (status) {
  1888. VL6180x_ErrLog("0x01AC wr fail");
  1889. goto done_err;
  1890. }
  1891. //status = VL6180x_WrByte(dev, 0x0F2, u8_2);
  1892. //if (status) {
  1893. // VL6180x_ErrLog("0x0F2 wr fail");
  1894. // goto done_err;
  1895. //}
  1896. _FilterData(MeasurementIndex)++;
  1897. }
  1898. if (bypassFilter == 1) {
  1899. /* Do not go through the filter */
  1900. /* Update filter error code */
  1901. _FilterData(filterError) = filterErrorCode;
  1902. /* Update reported range */
  1903. if(filterErrorCode==RangingFiltered)
  1904. m_newTrueRange_mm = MaxOrInvalidDistance; /* Set to invalid distance */
  1905. return m_newTrueRange_mm;
  1906. }
  1907. /* Computes current VAVGDiff */
  1908. if (_FilterData(Default_VAVGVal) > _FilterData(NoDelay_VAVGVal))
  1909. VAVGDiff = _FilterData(Default_VAVGVal) - _FilterData(NoDelay_VAVGVal);
  1910. else
  1911. VAVGDiff = 0;
  1912. _FilterData(Previous_VAVGDiff) = VAVGDiff;
  1913. if(SuspicuousRangingZone==0)
  1914. MAX_VAVGDiff = MAX_VAVGDiff_ROM;
  1915. else
  1916. /* In suspicuous area, strengthen the filter */
  1917. MAX_VAVGDiff = MAX_VAVGDiff_ROM / SuspicuousMAX_VAVGDiffRatio;
  1918. /* Check the VAVGDiff */
  1919. if (_FilterData(Default_ZeroVal) > _FilterData(NoDelay_ZeroVal))
  1920. IdealVAVGDiff = _FilterData(Default_ZeroVal) - _FilterData(NoDelay_ZeroVal);
  1921. else
  1922. IdealVAVGDiff = _FilterData(NoDelay_ZeroVal) - _FilterData(Default_ZeroVal);
  1923. if (IdealVAVGDiff > MAX_VAVGDiff)
  1924. MinVAVGDiff = IdealVAVGDiff - MAX_VAVGDiff;
  1925. else
  1926. MinVAVGDiff = 0;
  1927. MaxVAVGDiff = IdealVAVGDiff + MAX_VAVGDiff;
  1928. if (VAVGDiff < MinVAVGDiff || VAVGDiff > MaxVAVGDiff) {
  1929. WrapAroundFlag = 1;
  1930. filterErrorCode = RangingFiltered;
  1931. } else {
  1932. /* Go through filtering check */
  1933. if(_FilterData(MeasurementIndex)<=1)
  1934. /* On measurement after a bypass, uses an increase number of samples */
  1935. StdDevSamplesMinNeeded = MIN_FILTER_STDDEV_SAMPLES_AFTER_FLUSH_OR_BYPASS;
  1936. else
  1937. StdDevSamplesMinNeeded = MIN_FILTER_STDDEV_SAMPLES;
  1938. /* StdDevLimit Damper on SNR */
  1939. StdDevLimit = _filter_StdDevDamper(m_rtnAmbientRate, m_rtnSignalRate, StdDevLimitLowLight, StdDevLimitLowLightSNR, StdDevLimitHighLight, StdDevLimitHighLightSNR);
  1940. /* Standard deviations computations */
  1941. StdDevSamples = 0;
  1942. StdDevDistanceSum = 0;
  1943. StdDevDistanceMean = 0;
  1944. StdDevDistance = 0;
  1945. StdDevRateSum = 0;
  1946. StdDevRateMean = 0;
  1947. StdDevRate = 0;
  1948. for (i = 0; (i < FILTER_NBOF_SAMPLES) && (StdDevSamples < FILTER_STDDEV_SAMPLES); i++) {
  1949. if (_FilterData(LastTrueRange)[i] != FILTER_INVALID_DISTANCE) {
  1950. StdDevSamples = (uint16_t) (StdDevSamples + 1);
  1951. StdDevDistanceSum = (uint32_t) (StdDevDistanceSum + _FilterData(LastTrueRange)[i]);
  1952. StdDevRateSum = (uint32_t) (StdDevRateSum + _FilterData(LastReturnRates)[i]);
  1953. }
  1954. }
  1955. if (StdDevSamples > 0) {
  1956. StdDevDistanceMean = (uint32_t) (StdDevDistanceSum / StdDevSamples);
  1957. StdDevRateMean = (uint32_t) (StdDevRateSum / StdDevSamples);
  1958. }
  1959. /* TODO optimize shorten Std dev in aisngle loop computation using sum of x2 - (sum of x)2 */
  1960. StdDevSamples = 0;
  1961. StdDevDistanceSum = 0;
  1962. StdDevRateSum = 0;
  1963. for (i = 0; (i < FILTER_NBOF_SAMPLES) && (StdDevSamples < FILTER_STDDEV_SAMPLES); i++) {
  1964. if (_FilterData(LastTrueRange)[i] != FILTER_INVALID_DISTANCE) {
  1965. StdDevSamples = (uint16_t) (StdDevSamples + 1);
  1966. StdDevDistanceSum = (uint32_t) (StdDevDistanceSum +
  1967. (int)(_FilterData(LastTrueRange)[i] -
  1968. StdDevDistanceMean) *
  1969. (int) (_FilterData(LastTrueRange)[i] -
  1970. StdDevDistanceMean));
  1971. StdDevRateSum = (uint32_t) (StdDevRateSum +
  1972. (int) (_FilterData(LastReturnRates)[i] -
  1973. StdDevRateMean) *
  1974. (int) (_FilterData(LastReturnRates)[i] -
  1975. StdDevRateMean));
  1976. }
  1977. }
  1978. if (StdDevSamples >= StdDevSamplesMinNeeded) {
  1979. StdDevDistance = (uint16_t) (StdDevDistanceSum / StdDevSamples);
  1980. StdDevRate = (uint16_t) (StdDevRateSum / StdDevSamples);
  1981. } else {
  1982. StdDevDistance = 0;
  1983. StdDevRate = 0;
  1984. }
  1985. /* Check Return rate standard deviation */
  1986. if (StdDevRate < StdDevMovingTargetStdDevLimit) {
  1987. if (StdDevSamples < StdDevSamplesMinNeeded) {
  1988. //m_newTrueRange_mm = MaxOrInvalidDistance;
  1989. filterErrorCode = RangingFiltered;
  1990. } else {
  1991. /* Check distance standard deviation */
  1992. if (StdDevRate < StdDevMovingTargetReturnRateLimit)
  1993. StdDevLimitWithTargetMove = StdDevLimit +
  1994. (((StdDevMovingTargetStdDevForReturnRateLimit -
  1995. StdDevLimit) * StdDevRate) /
  1996. StdDevMovingTargetReturnRateLimit);
  1997. else
  1998. StdDevLimitWithTargetMove = StdDevMovingTargetStdDevForReturnRateLimit;
  1999. if(_FilterData(filterError)==NoError){
  2000. /* No wrapAround detected yet, so relax constraints on the std dev */
  2001. StdDevLimitWithTargetMove = StdDevLimitWithTargetMove * StdDevNoWrapDetectedMultiplier;
  2002. }
  2003. if (((StdDevDistance * StdDevHighConfidenceSNRLimit) < StdDevLimit) && (StdDevSamples>=FILTER_STDDEV_SAMPLES)) {
  2004. NoWrapAroundHighConfidenceFlag = 1;
  2005. } else {
  2006. if (StdDevDistance < StdDevLimitWithTargetMove) {
  2007. NoWrapAroundFlag = 1;
  2008. } else {
  2009. WrapAroundFlag = 1;
  2010. filterErrorCode = RangingFiltered;
  2011. }
  2012. }
  2013. }
  2014. } else {
  2015. /* Target moving too fast */
  2016. WrapAroundFlag = 1;
  2017. filterErrorCode = RangingFiltered;
  2018. }
  2019. }
  2020. if (ValidDistance == 0) {
  2021. /* In case of invalid distance */
  2022. if (_FilterData(StdFilteredReads) > 0)
  2023. _FilterData(StdFilteredReads) = (uint16_t) (_FilterData(StdFilteredReads) - 1);
  2024. } else {
  2025. if (WrapAroundFlag == 1) {
  2026. _FilterData(StdFilteredReads) = (uint16_t) (_FilterData(StdFilteredReads) +
  2027. StdFilteredReadsIncrement);
  2028. if (_FilterData(StdFilteredReads) > StdMaxFilteredReads)
  2029. _FilterData(StdFilteredReads) = StdMaxFilteredReads;
  2030. } else {
  2031. if (NoWrapAroundFlag == 1) {
  2032. if (_FilterData(StdFilteredReads) > 0) {
  2033. filterErrorCode = RangingFiltered;
  2034. if (_FilterData(StdFilteredReads) > StdFilteredReadsDecrement)
  2035. _FilterData(StdFilteredReads) = (uint16_t) (_FilterData(StdFilteredReads) -
  2036. StdFilteredReadsDecrement);
  2037. else
  2038. _FilterData(StdFilteredReads) = 0;
  2039. }
  2040. } else {
  2041. if (NoWrapAroundHighConfidenceFlag == 1) {
  2042. _FilterData(StdFilteredReads) = 0;
  2043. }
  2044. }
  2045. }
  2046. }
  2047. /* If we detect a change from no Error to RangingFilteringOnGoing, then it means that
  2048. * the filter detected a change in te scene, so discard all previous measurements.
  2049. */
  2050. if((_FilterData(filterError) == NoError) && (filterErrorCode!=NoError)) {
  2051. for (i = 1; i < FILTER_NBOF_SAMPLES; i++) {
  2052. _FilterData(LastTrueRange)[i] = FILTER_INVALID_DISTANCE;
  2053. _FilterData(LastReturnRates)[i] = 0;
  2054. }
  2055. }
  2056. /* Update filter error code */
  2057. _FilterData(filterError) = filterErrorCode;
  2058. /* Update reported range */
  2059. if(filterErrorCode==RangingFiltered)
  2060. m_newTrueRange_mm = MaxOrInvalidDistance; /* Set to invalid distance */
  2061. return m_newTrueRange_mm;
  2062. done_err:
  2063. return -1;
  2064. #undef MaxOrInvalidDistance
  2065. }
  2066. static int _filter_GetResult(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData)
  2067. {
  2068. uint32_t m_rawRange_mm = 0;
  2069. int32_t FilteredRange;
  2070. const uint8_t scaler = _GetUpscale(dev);
  2071. uint8_t u8;
  2072. int status;
  2073. do {
  2074. status = VL6180x_GetCachedByte(dev, RESULT_RANGE_RAW, &u8);
  2075. if (status) {
  2076. VL6180x_ErrLog("RESULT_RANGE_RAW rd fail");
  2077. break;
  2078. }
  2079. m_rawRange_mm = u8;
  2080. FilteredRange = _filter_Start(dev, pRangeData->range_mm, (m_rawRange_mm * scaler), pRangeData->rtnRate, pRangeData->rtnAmbRate, pRangeData->errorStatus);
  2081. if (FilteredRange < 0) {
  2082. status = -1;
  2083. break;
  2084. }
  2085. pRangeData->FilteredData.range_mm = FilteredRange;
  2086. pRangeData->FilteredData.rawRange_mm = m_rawRange_mm * scaler;
  2087. pRangeData->FilteredData.filterError= _FilterData(filterError);
  2088. } while (0);
  2089. return status;
  2090. }
  2091. #undef _FilterData
  2092. #ifdef PRESERVE_DEVICE_ERROR_CODE
  2093. #undef PRESERVE_DEVICE_ERROR_CODE
  2094. #endif
  2095. #ifdef SENSITIVE_FILTERING_ON_GOING
  2096. #undef SENSITIVE_FILTERING_ON_GOING
  2097. #endif
  2098. #undef FILTER_STDDEV_SAMPLES
  2099. #undef MIN_FILTER_STDDEV_SAMPLES
  2100. #undef MIN_FILTER_STDDEV_SAMPLES_AFTER_FLUSH_OR_BYPASS
  2101. #undef STDDEV_BASE_VALUE
  2102. #undef FILTER_INVALID_DISTANCE
  2103. #endif /* VL6180x_WRAP_AROUND_FILTER_SUPPORT */
  2104. #ifdef VL6180x_HAVE_RATE_DATA
  2105. static int _GetRateResult(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData)
  2106. {
  2107. uint32_t m_rtnConvTime = 0;
  2108. uint32_t m_rtnSignalRate = 0;
  2109. uint32_t m_rtnAmbientRate = 0;
  2110. uint32_t m_rtnSignalCount = 0;
  2111. uint32_t m_rtnAmbientCount = 0;
  2112. uint32_t m_refConvTime = 0;
  2113. uint32_t cRtnSignalCountMax = 0x7FFFFFFF;
  2114. uint32_t cDllPeriods = 6;
  2115. uint32_t calcConvTime = 0;
  2116. int status;
  2117. do {
  2118. status = VL6180x_GetCachedDWord(dev, RESULT_RANGE_RETURN_SIGNAL_COUNT, &m_rtnSignalCount);
  2119. if (status) {
  2120. VL6180x_ErrLog("RESULT_RANGE_RETURN_SIGNAL_COUNT rd fail");
  2121. break;
  2122. }
  2123. if (m_rtnSignalCount > cRtnSignalCountMax) {
  2124. m_rtnSignalCount = 0;
  2125. }
  2126. status = VL6180x_GetCachedDWord(dev, RESULT_RANGE_RETURN_AMB_COUNT, &m_rtnAmbientCount);
  2127. if (status) {
  2128. VL6180x_ErrLog("RESULT_RANGE_RETURN_AMB_COUNTrd fail");
  2129. break;
  2130. }
  2131. status = VL6180x_GetCachedDWord(dev, RESULT_RANGE_RETURN_CONV_TIME, &m_rtnConvTime);
  2132. if (status) {
  2133. VL6180x_ErrLog("RESULT_RANGE_RETURN_CONV_TIME rd fail");
  2134. break;
  2135. }
  2136. status = VL6180x_GetCachedDWord(dev, RESULT_RANGE_REFERENCE_CONV_TIME, &m_refConvTime);
  2137. if (status) {
  2138. VL6180x_ErrLog("RESULT_RANGE_REFERENCE_CONV_TIME rd fail");
  2139. break;
  2140. }
  2141. pRangeData->rtnConvTime = m_rtnConvTime;
  2142. pRangeData->refConvTime = m_refConvTime;
  2143. calcConvTime = m_refConvTime;
  2144. if (m_rtnConvTime > m_refConvTime) {
  2145. calcConvTime = m_rtnConvTime;
  2146. }
  2147. if (calcConvTime == 0)
  2148. calcConvTime = 63000;
  2149. m_rtnSignalRate = (m_rtnSignalCount * 1000) / calcConvTime;
  2150. m_rtnAmbientRate = (m_rtnAmbientCount * cDllPeriods * 1000) / calcConvTime;
  2151. pRangeData->rtnRate = m_rtnSignalRate;
  2152. pRangeData->rtnAmbRate = m_rtnAmbientRate;
  2153. } while (0);
  2154. return status;
  2155. }
  2156. #endif /* VL6180x_HAVE_RATE_DATA */
  2157. int VL6180x_DMaxSetState(VL6180xDev_t dev, int state)
  2158. {
  2159. int status;
  2160. LOG_FUNCTION_START("%d", state);
  2161. #if VL6180x_HAVE_DMAX_RANGING
  2162. VL6180xDevDataSet(dev, DMaxEnable, state);
  2163. if (state) {
  2164. status = _DMax_InitData(dev);
  2165. } else {
  2166. status = 0;
  2167. }
  2168. #else
  2169. status = NOT_SUPPORTED;
  2170. #endif
  2171. LOG_FUNCTION_END(status);
  2172. return status;
  2173. }
  2174. int VL6180x_DMaxGetState(VL6180xDev_t dev)
  2175. {
  2176. int status;
  2177. LOG_FUNCTION_START("");
  2178. #if VL6180x_HAVE_DMAX_RANGING
  2179. status = VL6180xDevDataGet(dev, DMaxEnable);
  2180. #else
  2181. status = 0;
  2182. #endif
  2183. LOG_FUNCTION_END(status);
  2184. return status;
  2185. }
  2186. #if VL6180x_HAVE_DMAX_RANGING
  2187. #define _DMaxData(field) VL6180xDevDataGet(dev, DMaxData.field)
  2188. /*
  2189. * Convert fix point x.7 to KCpount per sec
  2190. */
  2191. #ifndef VL6180x_PLATFORM_PROVIDE_SQRT
  2192. /*
  2193. * 32 bit integer square root with not so bad precision (integer result) and is quite fast
  2194. * see http://en.wikipedia.org/wiki/Methods_of_computing_square_roots
  2195. */
  2196. uint32_t VL6180x_SqrtUint32(uint32_t num)
  2197. {
  2198. uint32_t res = 0;
  2199. uint32_t bit = 1 << 30; /* The second-to-top bit is set: 1 << 30 for 32 bits */
  2200. /* "bit" starts at the highest power of four <= the argument. */
  2201. while (bit > num)
  2202. bit >>= 2;
  2203. while (bit != 0) {
  2204. if (num >= res + bit) {
  2205. num -= res + bit;
  2206. res = (res >> 1) + bit;
  2207. } else
  2208. res >>= 1;
  2209. bit >>= 2;
  2210. }
  2211. return res;
  2212. }
  2213. #endif
  2214. /* DMax one time init */
  2215. void _DMax_OneTimeInit(VL6180xDev_t dev)
  2216. {
  2217. _DMaxData(ambTuningWindowFactor_K) = DEF_AMBIENT_TUNING;
  2218. }
  2219. static uint32_t _DMax_RawValueAtRateKCps(VL6180xDev_t dev, int32_t rate)
  2220. {
  2221. uint32_t snrLimit_K;
  2222. int32_t DMaxSq;
  2223. uint32_t RawDMax;
  2224. DMaxFix_t retSignalAt400mm;
  2225. uint32_t ambTuningWindowFactor_K;
  2226. ambTuningWindowFactor_K = _DMaxData(ambTuningWindowFactor_K);
  2227. snrLimit_K = _DMaxData(snrLimit_K);
  2228. retSignalAt400mm = _DMaxData(retSignalAt400mm);
  2229. /* 12 to 18 bits Kcps */
  2230. if (rate > 0) {
  2231. DMaxSq = 400 * 400 * 1000 / rate - (400 * 400 / 330);
  2232. /* K of (1/RtnAmb -1/330 )=> 30bit- (12-18)bit => 12-18 bits*/
  2233. if (DMaxSq <= 0) {
  2234. RawDMax = 0;
  2235. } else {
  2236. /* value can be more 32 bit so base on raneg apply
  2237. * retSignalAt400mm before or after division to presevr accuracy */
  2238. if (DMaxSq < (2 << 12)) {
  2239. DMaxSq = DMaxSq * retSignalAt400mm /
  2240. (snrLimit_K + ambTuningWindowFactor_K);
  2241. /* max 12 + 12 to 18 -10 => 12-26 bit */
  2242. } else {
  2243. DMaxSq = DMaxSq / (snrLimit_K + ambTuningWindowFactor_K) * retSignalAt400mm;
  2244. /* 12 to 18 -10 + 12 to 18 *=> 12-26 bit */
  2245. }
  2246. RawDMax = VL6180x_SqrtUint32(DMaxSq);
  2247. }
  2248. } else {
  2249. RawDMax = 0x7FFFFFFF; /* bigest possibmle 32bit signed value */
  2250. }
  2251. return RawDMax;
  2252. }
  2253. /*
  2254. * fetch static data from register to avoid re-read
  2255. * precompute all intermediate constant and cliipings
  2256. *
  2257. * to be re-used/call on changes of :
  2258. * 0x2A
  2259. * SYSRANGE_MAX_AMBIENT_LEVEL_MULT
  2260. * Dev Data XtalkComRate_KCPs
  2261. * SYSRANGE_MAX_CONVERGENCE_TIME
  2262. * SYSRANGE_RANGE_CHECK_ENABLES mask RANGE_CHECK_RANGE_ENABLE_MASK
  2263. * range 0xb8-0xbb (0xbb)
  2264. */
  2265. static int _DMax_InitData(VL6180xDev_t dev)
  2266. {
  2267. int status, warning;
  2268. uint8_t u8;
  2269. uint16_t u16;
  2270. uint32_t u32;
  2271. uint32_t Reg2A_KCps;
  2272. uint32_t RegB8;
  2273. uint8_t MaxConvTime;
  2274. uint32_t XTalkCompRate_KCps;
  2275. uint32_t RangeIgnoreThreshold;
  2276. int32_t minSignalNeeded;
  2277. uint8_t SysRangeCheckEn;
  2278. uint8_t snrLimit;
  2279. static const int ROMABLE_DATA MaxConvTimeAdjust = -4;
  2280. warning = 0;
  2281. LOG_FUNCTION_START("");
  2282. do {
  2283. status = VL6180x_RdByte(dev, 0x02A, &u8);
  2284. if (status) {
  2285. VL6180x_ErrLog("Reg 0x02A rd fail");
  2286. break;
  2287. }
  2288. if (u8 == 0) {
  2289. warning = CALIBRATION_WARNING;
  2290. u8 = 40; /* use a default average value */
  2291. }
  2292. Reg2A_KCps = Fix7_2_KCPs(u8); /* convert to KCPs */
  2293. status = VL6180x_RdByte(dev, SYSRANGE_RANGE_CHECK_ENABLES, &SysRangeCheckEn);
  2294. if (status) {
  2295. VL6180x_ErrLog("SYSRANGE_RANGE_CHECK_ENABLES rd fail ");
  2296. break;
  2297. }
  2298. status = VL6180x_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &MaxConvTime);
  2299. if (status) {
  2300. VL6180x_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail ");
  2301. break;
  2302. }
  2303. status = VL6180x_RdDWord(dev, 0x0B8, &RegB8);
  2304. if (status) {
  2305. VL6180x_ErrLog("reg 0x0B8 rd fail ");
  2306. break;
  2307. }
  2308. status = VL6180x_RdByte(dev, SYSRANGE_MAX_AMBIENT_LEVEL_MULT, &snrLimit);
  2309. if (status) {
  2310. VL6180x_ErrLog("SYSRANGE_MAX_AMBIENT_LEVEL_MULT rd fail ");
  2311. break;
  2312. }
  2313. _DMaxData(snrLimit_K) = (int32_t)16 * 1000 / snrLimit;
  2314. XTalkCompRate_KCps = VL6180xDevDataGet(dev, XTalkCompRate_KCps);
  2315. if (Reg2A_KCps >= XTalkCompRate_KCps) {
  2316. _DMaxData(retSignalAt400mm) = Reg2A_KCps;
  2317. } else{
  2318. _DMaxData(retSignalAt400mm) = 0;
  2319. /* Reg2A_K - XTalkCompRate_KCp <0 is invalid */
  2320. }
  2321. /* if xtalk range check is off omit it in snr clipping */
  2322. if (SysRangeCheckEn&RANGE_CHECK_RANGE_ENABLE_MASK) {
  2323. status = VL6180x_RdWord(dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, &u16);
  2324. if (status) {
  2325. VL6180x_ErrLog("SYSRANGE_RANGE_IGNORE_THRESHOLD rd fail ");
  2326. break;
  2327. }
  2328. RangeIgnoreThreshold = Fix7_2_KCPs(u16);
  2329. } else{
  2330. RangeIgnoreThreshold = 0;
  2331. }
  2332. minSignalNeeded = (RegB8 * 256) / ((int32_t)MaxConvTime + (int32_t)MaxConvTimeAdjust);
  2333. /* KCps 8+8 bit -(1 to 6 bit) => 15-10 bit */
  2334. /* minSignalNeeded = max ( minSignalNeeded, RangeIgnoreThreshold - XTalkCompRate_KCps) */
  2335. if (minSignalNeeded <= (int32_t)RangeIgnoreThreshold - (int32_t)XTalkCompRate_KCps)
  2336. minSignalNeeded = RangeIgnoreThreshold - XTalkCompRate_KCps;
  2337. u32 = (minSignalNeeded*(uint32_t)snrLimit) / 16;
  2338. _DMaxData(ClipSnrLimit) = _DMax_RawValueAtRateKCps(dev, u32);
  2339. /* clip to dmax to min signal snr limit rate*/
  2340. } while (0);
  2341. if (!status)
  2342. status = warning;
  2343. LOG_FUNCTION_END(status);
  2344. return status;
  2345. }
  2346. static int _DMax_Compute(VL6180xDev_t dev, VL6180x_RangeData_t *pRange)
  2347. {
  2348. uint32_t rtnAmbRate;
  2349. int32_t DMax;
  2350. int scaling;
  2351. uint16_t HwLimitAtScale;
  2352. static const int ROMABLE_DATA rtnAmbLowLimit_KCps = 330 * 1000;
  2353. rtnAmbRate = pRange->rtnAmbRate;
  2354. if (rtnAmbRate < rtnAmbLowLimit_KCps) {
  2355. DMax = _DMax_RawValueAtRateKCps(dev, rtnAmbRate);
  2356. scaling = _GetUpscale(dev);
  2357. HwLimitAtScale = UpperLimitLookUP[scaling - 1];
  2358. if (DMax > _DMaxData(ClipSnrLimit)) {
  2359. DMax = _DMaxData(ClipSnrLimit);
  2360. }
  2361. if (DMax > HwLimitAtScale) {
  2362. DMax = HwLimitAtScale;
  2363. }
  2364. pRange->DMax = DMax;
  2365. } else {
  2366. pRange->DMax = 0;
  2367. }
  2368. return 0;
  2369. }
  2370. #undef _DMaxData
  2371. #undef Fix7_2_KCPs
  2372. #endif /* VL6180x_HAVE_DMAX_RANGING */