vl53l1_api_calibration.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. /*
  2. * Copyright (c) 2017, STMicroelectronics - All Rights Reserved
  3. *
  4. * This file is part of VL53L1 Core and is dual licensed,
  5. * either 'STMicroelectronics
  6. * Proprietary license'
  7. * or 'BSD 3-clause "New" or "Revised" License' , at your option.
  8. *
  9. ********************************************************************************
  10. *
  11. * 'STMicroelectronics Proprietary license'
  12. *
  13. ********************************************************************************
  14. *
  15. * License terms: STMicroelectronics Proprietary in accordance with licensing
  16. * terms at www.st.com/sla0081
  17. *
  18. * STMicroelectronics confidential
  19. * Reproduction and Communication of this document is strictly prohibited unless
  20. * specifically authorized in writing by STMicroelectronics.
  21. *
  22. *
  23. ********************************************************************************
  24. *
  25. * Alternatively, VL53L1 Core may be distributed under the terms of
  26. * 'BSD 3-clause "New" or "Revised" License', in which case the following
  27. * provisions apply instead of the ones mentioned above :
  28. *
  29. ********************************************************************************
  30. *
  31. * License terms: BSD 3-clause "New" or "Revised" License.
  32. *
  33. * Redistribution and use in source and binary forms, with or without
  34. * modification, are permitted provided that the following conditions are met:
  35. *
  36. * 1. Redistributions of source code must retain the above copyright notice, this
  37. * list of conditions and the following disclaimer.
  38. *
  39. * 2. Redistributions in binary form must reproduce the above copyright notice,
  40. * this list of conditions and the following disclaimer in the documentation
  41. * and/or other materials provided with the distribution.
  42. *
  43. * 3. Neither the name of the copyright holder nor the names of its contributors
  44. * may be used to endorse or promote products derived from this software
  45. * without specific prior written permission.
  46. *
  47. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  48. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  49. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  50. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  51. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  52. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  53. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  54. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  55. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  56. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  57. *
  58. *
  59. ********************************************************************************
  60. *
  61. */
  62. /**
  63. * @file vl53l1_api_core.c
  64. *
  65. * @brief EwokPlus25 low level API function definition
  66. */
  67. #include "vl53l1_ll_def.h"
  68. #include "vl53l1_ll_device.h"
  69. #include "vl53l1_platform.h"
  70. #include "vl53l1_register_map.h"
  71. #include "vl53l1_register_funcs.h"
  72. #include "vl53l1_register_settings.h"
  73. #include "vl53l1_core.h"
  74. #include "vl53l1_wait.h"
  75. #include "vl53l1_api_preset_modes.h"
  76. #include "vl53l1_silicon_core.h"
  77. #include "vl53l1_api_core.h"
  78. #include "vl53l1_api_calibration.h"
  79. #ifdef VL53L1_LOG_ENABLE
  80. #include "vl53l1_api_debug.h"
  81. #endif
  82. #ifdef VL53L1_LOGGING
  83. #include "vl53l1_debug.h"
  84. #endif
  85. #define LOG_FUNCTION_START(fmt, ...) \
  86. _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__)
  87. #define LOG_FUNCTION_END(status, ...) \
  88. _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_CORE, status, ##__VA_ARGS__)
  89. #define LOG_FUNCTION_END_FMT(status, fmt, ...) \
  90. _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_CORE, status, \
  91. fmt, ##__VA_ARGS__)
  92. #define trace_print(level, ...) \
  93. _LOG_TRACE_PRINT(VL53L1_TRACE_MODULE_CORE, \
  94. level, VL53L1_TRACE_FUNCTION_NONE, ##__VA_ARGS__)
  95. #ifndef VL53L1_NOCALIB
  96. VL53L1_Error VL53L1_run_ref_spad_char(
  97. VL53L1_DEV Dev,
  98. VL53L1_Error *pcal_status)
  99. {
  100. /*
  101. * Runs Reference SPAD Characterisation
  102. */
  103. VL53L1_Error status = VL53L1_ERROR_NONE;
  104. VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
  105. uint8_t comms_buffer[6];
  106. VL53L1_refspadchar_config_t *prefspadchar = &(pdev->refspadchar);
  107. LOG_FUNCTION_START("");
  108. /*
  109. * Ensure power force is enabled
  110. */
  111. if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/
  112. status = VL53L1_enable_powerforce(Dev);
  113. /*
  114. * Configure device
  115. */
  116. if (status == VL53L1_ERROR_NONE)
  117. status =
  118. VL53L1_set_ref_spad_char_config(
  119. Dev,
  120. prefspadchar->vcsel_period,
  121. prefspadchar->timeout_us,
  122. prefspadchar->target_count_rate_mcps,
  123. prefspadchar->max_count_rate_limit_mcps,
  124. prefspadchar->min_count_rate_limit_mcps,
  125. pdev->stat_nvm.osc_measured__fast_osc__frequency);
  126. /*
  127. * Run device test
  128. */
  129. if (status == VL53L1_ERROR_NONE)
  130. status = VL53L1_run_device_test(
  131. Dev,
  132. prefspadchar->device_test_mode);
  133. /*
  134. * Read results
  135. */
  136. if (status == VL53L1_ERROR_NONE)
  137. status =
  138. VL53L1_ReadMulti(
  139. Dev,
  140. VL53L1_REF_SPAD_CHAR_RESULT__NUM_ACTUAL_REF_SPADS,
  141. comms_buffer,
  142. 2);
  143. if (status == VL53L1_ERROR_NONE) {
  144. pdev->dbg_results.ref_spad_char_result__num_actual_ref_spads =
  145. comms_buffer[0];
  146. pdev->dbg_results.ref_spad_char_result__ref_location =
  147. comms_buffer[1];
  148. }
  149. /*
  150. * copy results to customer nvm managed G02 registers
  151. */
  152. if (status == VL53L1_ERROR_NONE)
  153. status =
  154. VL53L1_WriteMulti(
  155. Dev,
  156. VL53L1_REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS,
  157. comms_buffer,
  158. 2);
  159. if (status == VL53L1_ERROR_NONE) {
  160. pdev->customer.ref_spad_man__num_requested_ref_spads =
  161. comms_buffer[0];
  162. pdev->customer.ref_spad_man__ref_location =
  163. comms_buffer[1];
  164. }
  165. /* After Ref Spad Char the final set of good SPAD enables
  166. * are stored in the NCY results registers below
  167. *
  168. * - RESULT__SPARE_0_SD_1
  169. * - RESULT__SPARE_1_SD_1
  170. * - RESULT__SPARE_2_SD_1
  171. */
  172. if (status == VL53L1_ERROR_NONE)
  173. status =
  174. VL53L1_ReadMulti(
  175. Dev,
  176. VL53L1_RESULT__SPARE_0_SD1,
  177. comms_buffer,
  178. 6);
  179. /*
  180. * copy reference SPAD enables to customer nvm managed
  181. * G02 registers
  182. */
  183. if (status == VL53L1_ERROR_NONE)
  184. status =
  185. VL53L1_WriteMulti(
  186. Dev,
  187. VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_0,
  188. comms_buffer,
  189. 6);
  190. if (status == VL53L1_ERROR_NONE) {
  191. pdev->customer.global_config__spad_enables_ref_0 =
  192. comms_buffer[0];
  193. pdev->customer.global_config__spad_enables_ref_1 =
  194. comms_buffer[1];
  195. pdev->customer.global_config__spad_enables_ref_2 =
  196. comms_buffer[2];
  197. pdev->customer.global_config__spad_enables_ref_3 =
  198. comms_buffer[3];
  199. pdev->customer.global_config__spad_enables_ref_4 =
  200. comms_buffer[4];
  201. pdev->customer.global_config__spad_enables_ref_5 =
  202. comms_buffer[5];
  203. }
  204. #ifdef VL53L1_LOG_ENABLE
  205. /* Print customer nvm managed data */
  206. if (status == VL53L1_ERROR_NONE)
  207. VL53L1_print_customer_nvm_managed(
  208. &(pdev->customer),
  209. "run_ref_spad_char():pdev->lldata.customer.",
  210. VL53L1_TRACE_MODULE_REF_SPAD_CHAR);
  211. #endif
  212. if (status == VL53L1_ERROR_NONE) {
  213. switch (pdev->sys_results.result__range_status) {
  214. case VL53L1_DEVICEERROR_REFSPADCHARNOTENOUGHDPADS:
  215. status = VL53L1_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS;
  216. break;
  217. case VL53L1_DEVICEERROR_REFSPADCHARMORETHANTARGET:
  218. status = VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH;
  219. break;
  220. case VL53L1_DEVICEERROR_REFSPADCHARLESSTHANTARGET:
  221. status = VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW;
  222. break;
  223. }
  224. }
  225. /*
  226. * Save unfiltered status
  227. */
  228. *pcal_status = status;
  229. /* Status exception code */
  230. IGNORE_STATUS(
  231. IGNORE_REF_SPAD_CHAR_NOT_ENOUGH_SPADS,
  232. VL53L1_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS,
  233. status);
  234. IGNORE_STATUS(
  235. IGNORE_REF_SPAD_CHAR_RATE_TOO_HIGH,
  236. VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH,
  237. status);
  238. IGNORE_STATUS(
  239. IGNORE_REF_SPAD_CHAR_RATE_TOO_LOW,
  240. VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW,
  241. status);
  242. LOG_FUNCTION_END(status);
  243. return status;
  244. }
  245. VL53L1_Error VL53L1_run_offset_calibration(
  246. VL53L1_DEV Dev,
  247. int16_t cal_distance_mm,
  248. VL53L1_Error *pcal_status)
  249. {
  250. /*
  251. * Runs offset calibration
  252. *
  253. * Recommended tuning parm settings:
  254. *
  255. * - pre_num_of_samples = 32
  256. * - mm1_num_of_samples = 100
  257. * - mm2_num_of_samples = 64
  258. * - target_distance_mm = 140mm
  259. * - target reflectance = 5%
  260. *
  261. * Standard Ranging (sigma delta mode):
  262. * - dss_config__target_total_rate_mcps = 20.0 -40.0 Mcps
  263. * - phasecal_config_timeout_us = 1000
  264. * - range_config_timeout_us = 13000
  265. * - mm_config_timeout_us = 13000
  266. *
  267. *
  268. * Note: function parms simplified as part of
  269. * Patch_CalFunctionSimplification_11791
  270. *
  271. */
  272. VL53L1_Error status = VL53L1_ERROR_NONE;
  273. VL53L1_LLDriverData_t *pdev =
  274. VL53L1DevStructGetLLDriverHandle(Dev);
  275. VL53L1_DevicePresetModes device_preset_modes[VL53L1_MAX_OFFSET_RANGE_RESULTS];
  276. VL53L1_range_results_t range_results;
  277. VL53L1_range_results_t *prange_results = &range_results;
  278. VL53L1_range_data_t *prange_data = NULL;
  279. VL53L1_offset_range_data_t *poffset = NULL;
  280. uint8_t i = 0;
  281. uint8_t m = 0;
  282. uint8_t measurement_mode =
  283. VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK;
  284. uint16_t manual_effective_spads =
  285. pdev->gen_cfg.dss_config__manual_effective_spads_select;
  286. uint8_t num_of_samples[VL53L1_MAX_OFFSET_RANGE_RESULTS];
  287. LOG_FUNCTION_START("");
  288. /* select requested offset calibration mode */
  289. switch (pdev->offset_calibration_mode) {
  290. default:
  291. device_preset_modes[0] =
  292. VL53L1_DEVICEPRESETMODE_STANDARD_RANGING;
  293. device_preset_modes[1] =
  294. VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM1_CAL;
  295. device_preset_modes[2] =
  296. VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_MM2_CAL;
  297. break;
  298. }
  299. /* initialise num_of_samples */
  300. /* Start Patch_CalFunctionSimplification_11791 */
  301. num_of_samples[0] = pdev->offsetcal_cfg.pre_num_of_samples;
  302. num_of_samples[1] = pdev->offsetcal_cfg.mm1_num_of_samples;
  303. num_of_samples[2] = pdev->offsetcal_cfg.mm2_num_of_samples;
  304. /* End Patch_CalFunctionSimplification_11791 */
  305. /* force all offsets to zero */
  306. switch (pdev->offset_calibration_mode) {
  307. case VL53L1_OFFSETCALIBRATIONMODE__MM1_MM2__STANDARD_PRE_RANGE_ONLY:
  308. /* only run pre range */
  309. pdev->offset_results.active_results = 1;
  310. break;
  311. default:
  312. pdev->customer.mm_config__inner_offset_mm = 0;
  313. pdev->customer.mm_config__outer_offset_mm = 0;
  314. pdev->offset_results.active_results =
  315. VL53L1_MAX_OFFSET_RANGE_RESULTS;
  316. break;
  317. }
  318. pdev->customer.algo__part_to_part_range_offset_mm = 0;
  319. /* initialise offset range results */
  320. pdev->offset_results.max_results = VL53L1_MAX_OFFSET_RANGE_RESULTS;
  321. pdev->offset_results.cal_distance_mm = cal_distance_mm;
  322. for (m = 0 ; m < VL53L1_MAX_OFFSET_RANGE_RESULTS; m++) {
  323. poffset = &(pdev->offset_results.data[m]);
  324. poffset->preset_mode = 0;
  325. poffset->no_of_samples = 0;
  326. poffset->effective_spads = 0;
  327. poffset->peak_rate_mcps = 0;
  328. poffset->sigma_mm = 0;
  329. poffset->median_range_mm = 0;
  330. }
  331. for (m = 0 ; m < pdev->offset_results.active_results ; m++) {
  332. poffset = &(pdev->offset_results.data[m]);
  333. poffset->preset_mode = device_preset_modes[m];
  334. /* Apply preset mode */
  335. if (status == VL53L1_ERROR_NONE)
  336. status =
  337. VL53L1_set_preset_mode(
  338. Dev,
  339. device_preset_modes[m],
  340. /* Start Patch_CalFunctionSimplification_11791 */
  341. pdev->offsetcal_cfg.dss_config__target_total_rate_mcps,
  342. pdev->offsetcal_cfg.phasecal_config_timeout_us,
  343. pdev->offsetcal_cfg.mm_config_timeout_us,
  344. pdev->offsetcal_cfg.range_config_timeout_us,
  345. /* End Patch_CalFunctionSimplification_11791 */
  346. 100);
  347. pdev->gen_cfg.dss_config__manual_effective_spads_select =
  348. manual_effective_spads;
  349. /* Initialise device and start range */
  350. if (status == VL53L1_ERROR_NONE)
  351. status =
  352. VL53L1_init_and_start_range(
  353. Dev,
  354. measurement_mode,
  355. VL53L1_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS);
  356. for (i = 0 ; i <= (num_of_samples[m]+2) ; i++) {
  357. /* Wait for range completion */
  358. if (status == VL53L1_ERROR_NONE)
  359. status =
  360. VL53L1_wait_for_range_completion(Dev);
  361. /*
  362. * Get Device Results
  363. * - Checks the stream count is the expected one
  364. * - Read device system results
  365. */
  366. if (status == VL53L1_ERROR_NONE)
  367. status =
  368. VL53L1_get_device_results(
  369. Dev,
  370. VL53L1_DEVICERESULTSLEVEL_FULL,
  371. prange_results);
  372. /*
  373. * Ignore 1st two ranges to give the sigma delta initial
  374. * phase time to settle
  375. *
  376. * accummulate range results if range is successful
  377. */
  378. prange_data = &(prange_results->data[0]);
  379. if (prange_results->stream_count > 1) {
  380. if (prange_data->range_status ==
  381. VL53L1_DEVICEERROR_RANGECOMPLETE) {
  382. poffset->no_of_samples++;
  383. poffset->effective_spads +=
  384. (uint32_t)prange_data->actual_effective_spads;
  385. poffset->peak_rate_mcps +=
  386. (uint32_t)prange_data->peak_signal_count_rate_mcps;
  387. poffset->sigma_mm +=
  388. (uint32_t)prange_data->sigma_mm;
  389. poffset->median_range_mm +=
  390. (int32_t)prange_data->median_range_mm;
  391. poffset->dss_config__roi_mode_control =
  392. pdev->gen_cfg.dss_config__roi_mode_control;
  393. poffset->dss_config__manual_effective_spads_select =
  394. pdev->gen_cfg.dss_config__manual_effective_spads_select;
  395. }
  396. }
  397. /*
  398. * Conditional wait for firmware ready. Only waits for timed
  399. * and single shot modes. Mode check is performed inside the
  400. * wait function
  401. */
  402. if (status == VL53L1_ERROR_NONE)
  403. status =
  404. VL53L1_wait_for_firmware_ready(Dev);
  405. /*
  406. * Send ranging handshake
  407. *
  408. * - Update Zone management
  409. * - Update GPH registers
  410. * - Clear current interrupt
  411. * - Initialise SYSTEM__MODE_START for next range (if there is one!)
  412. */
  413. if (status == VL53L1_ERROR_NONE)
  414. status =
  415. VL53L1_clear_interrupt_and_enable_next_range(
  416. Dev,
  417. measurement_mode);
  418. }
  419. /* Stop range */
  420. if (status == VL53L1_ERROR_NONE)
  421. status = VL53L1_stop_range(Dev);
  422. /* Wait for Stop (abort) range to complete */
  423. if (status == VL53L1_ERROR_NONE)
  424. status = VL53L1_WaitUs(Dev, 1000);
  425. /* generate average values */
  426. if (poffset->no_of_samples > 0) {
  427. poffset->effective_spads += (poffset->no_of_samples/2);
  428. poffset->effective_spads /= poffset->no_of_samples;
  429. poffset->peak_rate_mcps += (poffset->no_of_samples/2);
  430. poffset->peak_rate_mcps /= poffset->no_of_samples;
  431. poffset->sigma_mm += (poffset->no_of_samples/2);
  432. poffset->sigma_mm /= poffset->no_of_samples;
  433. poffset->median_range_mm += (poffset->no_of_samples/2);
  434. poffset->median_range_mm /= poffset->no_of_samples;
  435. poffset->range_mm_offset = (int32_t)cal_distance_mm;
  436. poffset->range_mm_offset -= poffset->median_range_mm;
  437. /* remember the number of SPADs for standard ranging */
  438. if (poffset->preset_mode ==
  439. VL53L1_DEVICEPRESETMODE_STANDARD_RANGING)
  440. manual_effective_spads =
  441. (uint16_t)poffset->effective_spads;
  442. }
  443. }
  444. /* Calculate offsets */
  445. switch (pdev->offset_calibration_mode) {
  446. case VL53L1_OFFSETCALIBRATIONMODE__MM1_MM2__STANDARD_PRE_RANGE_ONLY:
  447. /* copy offsets to customer data structure */
  448. pdev->customer.mm_config__inner_offset_mm +=
  449. (int16_t)pdev->offset_results.data[0].range_mm_offset;
  450. pdev->customer.mm_config__outer_offset_mm +=
  451. (int16_t)pdev->offset_results.data[0].range_mm_offset;
  452. break;
  453. default:
  454. /* copy offsets to customer data structure */
  455. pdev->customer.mm_config__inner_offset_mm =
  456. (int16_t)pdev->offset_results.data[1].range_mm_offset;
  457. pdev->customer.mm_config__outer_offset_mm =
  458. (int16_t)pdev->offset_results.data[2].range_mm_offset;
  459. pdev->customer.algo__part_to_part_range_offset_mm = 0;
  460. /* copy average rate and effective SPAD count to
  461. additional offset calibration data structure */
  462. pdev->add_off_cal_data.result__mm_inner_actual_effective_spads =
  463. (uint16_t)pdev->offset_results.data[1].effective_spads;
  464. pdev->add_off_cal_data.result__mm_outer_actual_effective_spads =
  465. (uint16_t)pdev->offset_results.data[2].effective_spads;
  466. pdev->add_off_cal_data.result__mm_inner_peak_signal_count_rtn_mcps =
  467. (uint16_t)pdev->offset_results.data[1].peak_rate_mcps;
  468. pdev->add_off_cal_data.result__mm_outer_peak_signal_count_rtn_mcps =
  469. (uint16_t)pdev->offset_results.data[2].peak_rate_mcps;
  470. break;
  471. }
  472. /* apply to device */
  473. if (status == VL53L1_ERROR_NONE)
  474. status =
  475. VL53L1_set_customer_nvm_managed(
  476. Dev,
  477. &(pdev->customer));
  478. /*
  479. * Check the peak rates, sigma, min spads for each stage
  480. */
  481. for (m = 0 ; m < pdev->offset_results.active_results ; m++) {
  482. poffset = &(pdev->offset_results.data[m]);
  483. if (status == VL53L1_ERROR_NONE) {
  484. pdev->offset_results.cal_report = m;
  485. if (poffset->no_of_samples < num_of_samples[m])
  486. status = VL53L1_WARNING_OFFSET_CAL_MISSING_SAMPLES;
  487. /* only check sigma for the pre-range as
  488. * the it is not calculated by the device
  489. * for the MM1 and MM2 stages
  490. */
  491. if (m == 0 && poffset->sigma_mm >
  492. ((uint32_t)VL53L1_OFFSET_CAL_MAX_SIGMA_MM<<5))
  493. status = VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH;
  494. if (poffset->peak_rate_mcps >
  495. VL53L1_OFFSET_CAL_MAX_PRE_PEAK_RATE_MCPS)
  496. status = VL53L1_WARNING_OFFSET_CAL_RATE_TOO_HIGH;
  497. if (poffset->dss_config__manual_effective_spads_select <
  498. VL53L1_OFFSET_CAL_MIN_EFFECTIVE_SPADS)
  499. status = VL53L1_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW;
  500. if (poffset->dss_config__manual_effective_spads_select == 0)
  501. status = VL53L1_ERROR_OFFSET_CAL_NO_SPADS_ENABLED_FAIL;
  502. if (poffset->no_of_samples == 0)
  503. status = VL53L1_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL;
  504. }
  505. }
  506. /*
  507. * Save unfiltered status
  508. */
  509. pdev->offset_results.cal_status = status;
  510. *pcal_status = pdev->offset_results.cal_status;
  511. /* Status exception codes */
  512. IGNORE_STATUS(
  513. IGNORE_OFFSET_CAL_MISSING_SAMPLES,
  514. VL53L1_WARNING_OFFSET_CAL_MISSING_SAMPLES,
  515. status);
  516. IGNORE_STATUS(
  517. IGNORE_OFFSET_CAL_SIGMA_TOO_HIGH,
  518. VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH,
  519. status);
  520. IGNORE_STATUS(
  521. IGNORE_OFFSET_CAL_RATE_TOO_HIGH,
  522. VL53L1_WARNING_OFFSET_CAL_RATE_TOO_HIGH,
  523. status);
  524. IGNORE_STATUS(
  525. IGNORE_OFFSET_CAL_SPAD_COUNT_TOO_LOW,
  526. VL53L1_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW,
  527. status);
  528. #ifdef VL53L1_LOG_ENABLE
  529. /* Prints out the offset calibration data for debug */
  530. VL53L1_print_customer_nvm_managed(
  531. &(pdev->customer),
  532. "run_offset_calibration():pdev->lldata.customer.",
  533. VL53L1_TRACE_MODULE_OFFSET_DATA);
  534. VL53L1_print_additional_offset_cal_data(
  535. &(pdev->add_off_cal_data),
  536. "run_offset_calibration():pdev->lldata.add_off_cal_data.",
  537. VL53L1_TRACE_MODULE_OFFSET_DATA);
  538. VL53L1_print_offset_range_results(
  539. &(pdev->offset_results),
  540. "run_offset_calibration():pdev->lldata.offset_results.",
  541. VL53L1_TRACE_MODULE_OFFSET_DATA);
  542. #endif
  543. LOG_FUNCTION_END(status);
  544. return status;
  545. }
  546. #endif
  547. #ifndef VL53L1_NOCALIB
  548. VL53L1_Error VL53L1_run_spad_rate_map(
  549. VL53L1_DEV Dev,
  550. VL53L1_DeviceTestMode device_test_mode,
  551. VL53L1_DeviceSscArray array_select,
  552. uint32_t ssc_config_timeout_us,
  553. VL53L1_spad_rate_data_t *pspad_rate_data)
  554. {
  555. /**
  556. * Runs SPAD Rate Map
  557. */
  558. VL53L1_Error status = VL53L1_ERROR_NONE;
  559. VL53L1_LLDriverData_t *pdev =
  560. VL53L1DevStructGetLLDriverHandle(Dev);
  561. LOG_FUNCTION_START("");
  562. /*
  563. * Ensure power force is enabled
  564. */
  565. if (status == VL53L1_ERROR_NONE)
  566. status = VL53L1_enable_powerforce(Dev);
  567. /*
  568. * Configure the test
  569. */
  570. if (status == VL53L1_ERROR_NONE) {
  571. pdev->ssc_cfg.array_select = array_select;
  572. pdev->ssc_cfg.timeout_us = ssc_config_timeout_us;
  573. status =
  574. VL53L1_set_ssc_config(
  575. Dev,
  576. &(pdev->ssc_cfg),
  577. pdev->stat_nvm.osc_measured__fast_osc__frequency);
  578. }
  579. /*
  580. * Run device test
  581. */
  582. if (status == VL53L1_ERROR_NONE)
  583. status =
  584. VL53L1_run_device_test(
  585. Dev,
  586. device_test_mode);
  587. /*
  588. * Read Rate Data from Patch Ram
  589. */
  590. if (status == VL53L1_ERROR_NONE)
  591. status =
  592. VL53L1_get_spad_rate_data(
  593. Dev,
  594. pspad_rate_data);
  595. if (device_test_mode == VL53L1_DEVICETESTMODE_LCR_VCSEL_ON)
  596. pspad_rate_data->fractional_bits = 7;
  597. else
  598. pspad_rate_data->fractional_bits = 15;
  599. /* Ensure power force is disabled */
  600. if (status == VL53L1_ERROR_NONE)
  601. status = VL53L1_disable_powerforce(Dev);
  602. #ifdef VL53L1_LOG_ENABLE
  603. /* Print return rate data and map */
  604. if (status == VL53L1_ERROR_NONE) {
  605. VL53L1_print_spad_rate_data(
  606. pspad_rate_data,
  607. "run_spad_rate_map():",
  608. VL53L1_TRACE_MODULE_SPAD_RATE_MAP);
  609. VL53L1_print_spad_rate_map(
  610. pspad_rate_data,
  611. "run_spad_rate_map():",
  612. VL53L1_TRACE_MODULE_SPAD_RATE_MAP);
  613. }
  614. #endif
  615. LOG_FUNCTION_END(status);
  616. return status;
  617. }
  618. #endif
  619. #ifndef VL53L1_NOCALIB
  620. VL53L1_Error VL53L1_run_device_test(
  621. VL53L1_DEV Dev,
  622. VL53L1_DeviceTestMode device_test_mode)
  623. {
  624. /*
  625. * Runs the selected Device Test Mode
  626. */
  627. VL53L1_Error status = VL53L1_ERROR_NONE;
  628. VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
  629. uint8_t comms_buffer[2];
  630. uint8_t gpio_hv_mux__ctrl = 0;
  631. LOG_FUNCTION_START("");
  632. /*
  633. * Get current interrupt config
  634. */
  635. if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/
  636. status =
  637. VL53L1_RdByte(
  638. Dev,
  639. VL53L1_GPIO_HV_MUX__CTRL,
  640. &gpio_hv_mux__ctrl);
  641. if (status == VL53L1_ERROR_NONE)
  642. pdev->stat_cfg.gpio_hv_mux__ctrl = gpio_hv_mux__ctrl;
  643. /*
  644. * Trigger the test
  645. */
  646. if (status == VL53L1_ERROR_NONE)
  647. status = VL53L1_start_test(
  648. Dev,
  649. device_test_mode);
  650. /*
  651. * Wait for test completion
  652. */
  653. if (status == VL53L1_ERROR_NONE)
  654. status = VL53L1_wait_for_test_completion(Dev);
  655. /*
  656. * Read range and report status
  657. */
  658. if (status == VL53L1_ERROR_NONE)
  659. status =
  660. VL53L1_ReadMulti(
  661. Dev,
  662. VL53L1_RESULT__RANGE_STATUS,
  663. comms_buffer,
  664. 2);
  665. if (status == VL53L1_ERROR_NONE) {
  666. pdev->sys_results.result__range_status = comms_buffer[0];
  667. pdev->sys_results.result__report_status = comms_buffer[1];
  668. }
  669. /* mask range status bits */
  670. pdev->sys_results.result__range_status &=
  671. VL53L1_RANGE_STATUS__RANGE_STATUS_MASK;
  672. if (status == VL53L1_ERROR_NONE) {
  673. trace_print(
  674. VL53L1_TRACE_LEVEL_INFO,
  675. " Device Test Complete:\n\t%-32s = %3u\n\t%-32s = %3u\n",
  676. "result__range_status",
  677. pdev->sys_results.result__range_status,
  678. "result__report_status",
  679. pdev->sys_results.result__report_status);
  680. /*
  681. * Clear interrupt
  682. */
  683. if (status == VL53L1_ERROR_NONE)
  684. status = VL53L1_clear_interrupt(Dev);
  685. }
  686. /*
  687. * Clear test mode register
  688. * - required so that next test command will trigger
  689. * internal MCU interrupt
  690. */
  691. if (status == VL53L1_ERROR_NONE)
  692. status =
  693. VL53L1_start_test(
  694. Dev,
  695. 0x00);
  696. LOG_FUNCTION_END(status);
  697. return status;
  698. }
  699. #endif