37#include "../functors.h"
39#include "../realtime_timer.h"
41#include "../utilities.h"
42#include "../i2c_handler.h"
43#include "../i2c_device.h"
44#include "../i2c_device_utilities.h"
45#include "vl53l0x_internals.h"
46#include "vl53l0x_registers.h"
67 namespace internals = vl53l0x_internals;
107 template<
typename MANAGER>
112 using ABSTRACT_FUTURE =
typename MANAGER::ABSTRACT_FUTURE;
114 template<Register REGISTER,
typename T = u
int8_t>
117 template<Register REGISTER,
typename T = u
int8_t>
145 static constexpr uint8_t ADDRESS_MASK = 0x7F;
147 device_address &= ADDRESS_MASK;
148 if (!this->
template sync_write<SetAddressFuture>(device_address))
return false;
149 this->
set_device(uint8_t(device_address << 1));
177 static constexpr uint8_t LONG_RANGE_MASK = 0x01;
178 static constexpr uint8_t ACCURATE_MASK = 0x02;
179 static constexpr uint8_t FAST_MASK = 0x04;
180 static constexpr uint32_t ACCURATE_TIMING_BUDGET = 200'000UL;
181 static constexpr uint32_t FAST_TIMING_BUDGET = 20'000UL;
182 static constexpr uint8_t LONG_RANGE_VCSEL_PERIOD_PRE = 18;
183 static constexpr uint8_t LONG_RANGE_VCSEL_PERIOD_FINAL = 14;
186 uint8_t prof = uint8_t(profile);
191 if (prof & LONG_RANGE_MASK)
194 if (!set_vcsel_pulse_period<VcselPeriodType::PRE_RANGE>(LONG_RANGE_VCSEL_PERIOD_PRE))
return false;
195 if (!set_vcsel_pulse_period<VcselPeriodType::FINAL_RANGE>(LONG_RANGE_VCSEL_PERIOD_FINAL))
return false;
198 if (prof & ACCURATE_MASK)
203 else if (prof & FAST_MASK)
233 template<board::Timer TIMER>
239 if (!use_stop_variable())
return false;
240 if (!this->
template sync_write<WRITE_SYSRANGE>(uint8_t(0x01)))
return false;
242 while (rtt.
time() < end)
244 uint8_t sys_range = 0;
245 if (!this->
template sync_read<READ_SYSRANGE>(sys_range))
return false;
246 if ((sys_range & 0x01) == 0)
250 timeout_ms = (end > now) ? (end - now).
millis() : 0;
251 if (timeout_ms == 0) timeout_ms = 1U;
292 if (!use_stop_variable())
return false;
293 uint8_t sys_range_start = 0x02;
296 uint16_t osc_calibrate = 0;
297 if (!this->
template sync_read<READ_OSC_CAL>(osc_calibrate))
return false;
298 uint32_t actual_period = period_ms;
299 if (osc_calibrate) actual_period *= osc_calibrate;
300 if (!this->
template sync_write<WRITE_PERIOD>(actual_period))
return false;
301 sys_range_start = 0x04;
303 return this->
template sync_write<WRITE_SYSRANGE>(sys_range_start);
330 timer::RTT<TIMER>& rtt, uint16_t& range_mm, uint16_t timeout_ms = DEFAULT_TIMEOUT_MS)
350 return await_same_future_group(
351 internals::stop_continuous_ranging::BUFFER, internals::stop_continuous_ranging::BUFFER_SIZE);
372 static constexpr uint16_t RESET_DELAY_US = 100U;
375 if (!this->
template sync_write<WRITE_RESET>(uint8_t(0x00)))
return false;
377 uint8_t model = 0xFF;
386 if (!this->
template sync_write<WRITE_RESET>(uint8_t(0x01)))
return false;
425 if (!force_io_2_8V())
return false;
427 if (!set_I2C_mode())
return false;
429 if (!read_stop_variable())
return false;
431 if (!disable_signal_rate_limit_check())
return false;
470 calculate_reference_SPADs(ref_spads.
spad_refs(), info);
473 if (!load_tuning_settings())
return false;
477 uint32_t budget_us = 0UL;
503 static constexpr uint8_t CODE_VHV_CALIBRATION = 0x01;
504 static constexpr uint8_t CODE_PHASE_CALIBRATION = 0x02;
510 if (!this->
template sync_write<WRITE_STEPS>(CODE_VHV_CALIBRATION))
return false;
512 if (!perform_single_ref_calibration(SingleRefCalibrationTarget::VHV_CALIBRATION))
return false;
514 if (!this->
template sync_write<WRITE_STEPS>(CODE_PHASE_CALIBRATION))
return false;
516 if (!perform_single_ref_calibration(SingleRefCalibrationTarget::PHASE_CALIBRATION))
return false;
561 return this->
template sync_read<GetRangeStatusFuture>(range_status);
576 PARENT::init(futures_);
585 static constexpr uint8_t GPIO_ACTIVE_LEVEL_MASK = 0x10;
589 read_config_.get(function);
590 uint8_t active_high = 0;
591 read_GPIO_active_high_.get(active_high);
592 uint16_t low_threshold = 0;
593 read_low_threshold_.get(low_threshold);
594 uint16_t high_threshold = 0;
595 read_high_threshold_.get(high_threshold);
597 function, bool(active_high & GPIO_ACTIVE_LEVEL_MASK), low_threshold, high_threshold};
608 static constexpr uint8_t NUM_FUTURES = 4;
609 ABSTRACT_FUTURE* futures_[NUM_FUTURES] =
612 &read_GPIO_active_high_,
613 &read_low_threshold_,
614 &read_high_threshold_
659 return future.get(settings);
672 :
PARENT{futures_, NUM_FUTURES},
676 write_GPIO_active_high_{uint8_t(settings.
high_polarity() ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW)},
682 PARENT::init(futures_);
691 static constexpr uint8_t GPIO_LEVEL_HIGH = 0x11;
692 static constexpr uint8_t GPIO_LEVEL_LOW = 0x01;
699 static constexpr uint8_t NUM_FUTURES = 5;
700 ABSTRACT_FUTURE* futures_[NUM_FUTURES] =
703 &write_GPIO_active_high_,
704 &write_low_threshold_,
705 &write_high_threshold_,
794 return this->
template sync_read<GetInterruptStatusFuture>(status);
838 return this->
template sync_write<ClearInterruptFuture>(clear_mask);
857 template<board::Timer TIMER>
861 while (rtt.
time() < end)
863 InterruptStatus status;
864 if (!this->
template sync_read<GetInterruptStatusFuture>(status))
return false;
865 if (uint8_t(status) != 0)
928 return this->
template sync_read<GetDirectRangeFuture>(range_mm);
955 uint16_t budget = calculate_final_range_timeout(steps, timeouts, budget_us);
956 if (budget == 0)
return false;
957 return this->
template sync_write<WRITE_BUDGET>(budget);
983 budget_us = calculate_measurement_budget_us(
true, steps, timeouts);
1003 return this->
template sync_write<SetSequenceStepsFuture>(sequence_steps);
1023 return this->
template sync_read<GetSequenceStepsFuture>(sequence_steps);
1044 template<VcselPeriodType TYPE>
1065 template<VcselPeriodType TYPE>
1069 if (!this->
template sync_read<GetVcselPulsePeriodFuture>(period))
return false;
1070 period = decode_vcsel_period(period);
1091 if ((signal_rate <= 0.0) || (signal_rate > 1.0))
return false;
1092 using SetSignalRateLimitFuture =
1115 using GetSignalRateLimitFuture =
1118 if (!this->
template sync_read<GetSignalRateLimitFuture>(temp))
return false;
1135 return this->
template sync_read<GetPowerModeFuture>(power_mode);
1152 return this->
template sync_read<GetModelFuture>(model);
1169 return this->
template sync_read<GetRevisionFuture>(revision);
1193 InterruptStatus status;
1194 if (!this->
template sync_read<GetInterruptStatusFuture>(status))
return false;
1195 if (uint8_t(status) != 0)
1254 if (!use_stop_variable())
return false;
1255 if (!this->
template sync_write<WRITE_SYSRANGE>(uint8_t(0x01)))
return false;
1259 uint8_t sys_range = 0;
1260 if (!this->
template sync_read<READ_SYSRANGE>(sys_range))
return false;
1261 if ((sys_range & 0x01) == 0)
1282 using GetReferenceSPADsFuture =
1284 return this->
template sync_read<GetReferenceSPADsFuture, SPADReference>(spad_ref);
1301 using SetReferenceSPADsFuture =
1303 if (!await_same_future_group(
1304 internals::set_reference_spads::BUFFER, internals::set_reference_spads::BUFFER_SIZE))
1306 return this->
template sync_write<SetReferenceSPADsFuture, SPADReference>(spad_ref);
1326 if (!await_same_future_group(internals::spad_info::BUFFER1, internals::spad_info::BUFFER1_SIZE))
1330 if (!this->
template sync_read<READ_STROBE>(strobe))
return false;
1332 if (!this->
template sync_write<WRITE_STROBE>(strobe))
return false;
1334 if (!await_same_future_group(internals::spad_info::BUFFER2, internals::spad_info::BUFFER2_SIZE))
1337 if (!await_device_strobe())
return false;
1339 if (!this->
template sync_read<READ_SPAD>(info))
return false;
1341 if (!await_same_future_group(internals::spad_info::BUFFER3, internals::spad_info::BUFFER3_SIZE))
1345 if (!this->
template sync_read<READ_STROBE>(strobe))
return false;
1347 if (!this->
template sync_write<WRITE_STROBE>(strobe))
return false;
1349 return await_same_future_group(internals::spad_info::BUFFER4, internals::spad_info::BUFFER4_SIZE);
1367 using READ_FINALRANGE_TIMEOUT =
1370 uint8_t pre_range_vcsel_period_pclks = 0;
1371 if (!get_vcsel_pulse_period<VcselPeriodType::PRE_RANGE>(pre_range_vcsel_period_pclks))
return false;
1372 uint8_t final_range_vcsel_period_pclks = 0;
1373 if (!get_vcsel_pulse_period<VcselPeriodType::FINAL_RANGE>(final_range_vcsel_period_pclks))
return false;
1374 uint8_t msrc_dss_tcc_mclks = 0;
1375 if (!this->
template sync_read<READ_MSRC_TIMEOUT>(msrc_dss_tcc_mclks))
return false;
1376 uint16_t pre_range_mclks = 0;
1377 if (!this->
template sync_read<READ_PRERANGE_TIMEOUT>(pre_range_mclks))
return false;
1378 uint16_t final_range_mclks = 0;
1379 if (!this->
template sync_read<READ_FINALRANGE_TIMEOUT>(final_range_mclks))
return false;
1382 pre_range_vcsel_period_pclks, final_range_vcsel_period_pclks,
1383 msrc_dss_tcc_mclks, pre_range_mclks, final_range_mclks};
1407 template<Register REGISTER,
typename T = u
int8_t>
1433 template<Register REGISTER,
typename T = u
int8_t>
1456 template<Register REGISTER,
typename T = u
int8_t>
1460 return this->
template sync_read<GetRegisterFuture>(value);
1479 template<Register REGISTER,
typename T = u
int8_t>
1483 return this->
template sync_write<SetRegisterFuture>(value);
1487 bool force_io_2_8V()
1489 using READ_VHV_CONFIG = TReadRegisterFuture<Register::VHV_CONFIG_PAD_SCL_SDA_EXTSUP_HV>;
1490 using WRITE_VHV_CONFIG = TWriteRegisterFuture<Register::VHV_CONFIG_PAD_SCL_SDA_EXTSUP_HV>;
1492 if (!this->
template sync_read<READ_VHV_CONFIG>(config))
return false;
1494 return this->
template sync_write<WRITE_VHV_CONFIG>(config);
1499 using WRITE_I2C_MODE = TWriteRegisterFuture<Register::SYSTEM_CONFIG_I2C_MODE>;
1500 return this->
template sync_write<WRITE_I2C_MODE>(uint8_t(0x00));
1503 bool read_stop_variable()
1506 if (!await_same_future_group(
1507 internals::stop_variable::PRE_BUFFER, internals::stop_variable::PRE_BUFFER_SIZE))
1511 using READ_STOP_VAR = TReadRegisterFuture<Register::SYSTEM_STOP_VARIABLE>;
1512 if (!this->
template sync_read<READ_STOP_VAR>(stop_variable_))
return false;
1515 return await_same_future_group(
1516 internals::stop_variable::POST_BUFFER, internals::stop_variable::POST_BUFFER_SIZE);
1519 bool use_stop_variable()
1522 if (!await_same_future_group(
1523 internals::stop_variable::PRE_BUFFER, internals::stop_variable::PRE_BUFFER_SIZE))
1527 using WRITE_STOP_VAR = TWriteRegisterFuture<Register::SYSTEM_STOP_VARIABLE>;
1528 if (!this->
template sync_write<WRITE_STOP_VAR>(stop_variable_))
return false;
1531 return await_same_future_group(
1532 internals::stop_variable::POST_BUFFER, internals::stop_variable::POST_BUFFER_SIZE);
1535 bool disable_signal_rate_limit_check()
1537 using READ_MSRC_CONFIG = TReadRegisterFuture<Register::MSRC_CONFIG_CONTROL>;
1538 using WRITE_MSRC_CONFIG = TWriteRegisterFuture<Register::MSRC_CONFIG_CONTROL>;
1540 if (!this->
template sync_read<READ_MSRC_CONFIG>(config))
return false;
1542 return this->
template sync_write<WRITE_MSRC_CONFIG>(config);
1545 bool load_tuning_settings()
1547 return await_same_future_group(
1548 internals::load_tuning_settings::BUFFER, internals::load_tuning_settings::BUFFER_SIZE);
1551 static constexpr const uint16_t MAX_LOOP = 2000;
1552 static constexpr uint16_t DEFAULT_TIMEOUT_MS = 100;
1554 enum class SingleRefCalibrationTarget : uint8_t
1556 PHASE_CALIBRATION = 0x01,
1557 VHV_CALIBRATION = 0x41
1560 bool perform_single_ref_calibration(SingleRefCalibrationTarget target)
1562 using WRITE_SYS_RANGE = TWriteRegisterFuture<Register::SYSRANGE_START>;
1564 if (!this->
template sync_write<WRITE_SYS_RANGE>(uint8_t(target)))
return false;
1566 uint16_t loops = MAX_LOOP;
1569 InterruptStatus status;
1571 if (uint8_t(status) != 0)
1576 return this->
template sync_write<WRITE_SYS_RANGE>(uint8_t(0x00));
1582 bool await_same_future_group(
const uint8_t* buffer, uint8_t size)
1584 return i2c::await_same_future_group<MANAGER>(*
this, buffer, size);
1587 bool await_device_strobe()
1589 using READ_STROBE = TReadRegisterFuture<Register::DEVICE_STROBE>;
1590 using WRITE_STROBE = TWriteRegisterFuture<Register::DEVICE_STROBE>;
1592 if (!this->
template sync_write<WRITE_STROBE>(uint8_t(0x00)))
return false;
1594 uint16_t loops = MAX_LOOP;
1598 if (!this->
template sync_read<READ_STROBE>(strobe))
return false;
1601 return this->
template sync_write<WRITE_STROBE>(uint8_t(0x01));
1609 if (!check_vcsel_period(type, period))
return false;
1611 uint8_t vcsel_period = encode_vcsel_period(period);
1613 uint32_t timing_budget = 0UL;
1616 SequenceSteps steps;
1619 SequenceStepsTimeout timeouts;
1621 if (type == VcselPeriodType::PRE_RANGE)
1623 if (!set_vcsel_period_pre_range(period, vcsel_period, timeouts))
return false;
1627 if (!set_vcsel_period_final_range(period, vcsel_period, steps.is_pre_range(), timeouts))
1633 using WRITE_STEPS = TWriteRegisterFuture<Register::SYSTEM_SEQUENCE_CONFIG>;
1634 if (!this->
template sync_write<WRITE_STEPS>(uint8_t(0x02)))
return false;
1635 perform_single_ref_calibration(SingleRefCalibrationTarget::PHASE_CALIBRATION);
1640 bool set_vcsel_period_pre_range(
1641 uint8_t period, uint8_t vcsel_period,
const SequenceStepsTimeout& timeouts)
1644 using WRITE_PHASE_HIGH = TWriteRegisterFuture<Register::PRE_RANGE_CONFIG_VALID_PHASE_HIGH>;
1645 using WRITE_PHASE_LOW = TWriteRegisterFuture<Register::PRE_RANGE_CONFIG_VALID_PHASE_LOW>;
1646 using WRITE_VCSEL = TWriteRegisterFuture<Register::PRE_RANGE_CONFIG_VCSEL_PERIOD>;
1647 using WRITE_RANGE_TIMEOUT = TWriteRegisterFuture<Register::PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI, uint16_t>;
1648 using WRITE_MSRC_TIMEOUT = TWriteRegisterFuture<Register::MSRC_CONFIG_TIMEOUT_MACROP>;
1651 uint8_t phase_high = 0;
1673 if (!this->
template sync_write<WRITE_PHASE_HIGH>(phase_high))
return false;
1675 if (!this->
template sync_write<WRITE_PHASE_LOW>(uint8_t(0x08)))
return false;
1677 if (!this->
template sync_write<WRITE_VCSEL>(vcsel_period))
return false;
1680 uint16_t pre_range_mclks = vl53l0x::TimeoutUtilities::encode_timeout(
1681 vl53l0x::TimeoutUtilities::calculate_timeout_mclks(timeouts.pre_range_us(), period));
1682 if (!this->
template sync_write<WRITE_RANGE_TIMEOUT>(pre_range_mclks))
return false;
1685 uint16_t msrc_mclks = vl53l0x::TimeoutUtilities::calculate_timeout_mclks(
1686 timeouts.msrc_dss_tcc_us(), period);
1687 msrc_mclks = (msrc_mclks > (UINT8_MAX + 1)) ? UINT8_MAX : (msrc_mclks - 1);
1688 return this->
template sync_write<WRITE_MSRC_TIMEOUT>(uint8_t(msrc_mclks));
1691 bool set_vcsel_period_final_range(
1692 uint8_t period, uint8_t vcsel_period,
bool has_pre_range,
const SequenceStepsTimeout& timeouts)
1695 using WRITE_PHASE_HIGH = TWriteRegisterFuture<Register::FINAL_RANGE_CONFIG_VALID_PHASE_HIGH>;
1696 using WRITE_PHASE_LOW = TWriteRegisterFuture<Register::FINAL_RANGE_CONFIG_VALID_PHASE_LOW>;
1697 using WRITE_VCSEL_WIDTH = TWriteRegisterFuture<Register::GLOBAL_CONFIG_VCSEL_WIDTH>;
1698 using WRITE_PHASECAL_TIMEOUT = TWriteRegisterFuture<Register::ALGO_PHASECAL_CONFIG_TIMEOUT>;
1699 using WRITE_PHASECAL_LIMIT = TWriteRegisterFuture<Register::ALGO_PHASECAL_LIM>;
1700 using WRITE_RANGE_TIMEOUT = TWriteRegisterFuture<Register::FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI, uint16_t>;
1701 using WRITE_VCSEL = TWriteRegisterFuture<Register::FINAL_RANGE_CONFIG_VCSEL_PERIOD>;
1703 uint8_t phase_high = 0;
1704 uint8_t vcsel_width = 0;
1705 uint8_t phasecal_timeout = 0;
1706 uint8_t phasecal_limit = 0;
1712 phasecal_timeout = 0x0C;
1713 phasecal_limit = 0x30;
1719 phasecal_timeout = 0x09;
1720 phasecal_limit = 0x20;
1726 phasecal_timeout = 0x08;
1727 phasecal_limit = 0x20;
1733 phasecal_timeout = 0x07;
1734 phasecal_limit = 0x20;
1741 if (!this->
template sync_write<WRITE_PHASE_HIGH>(phase_high))
return false;
1743 if (!this->
template sync_write<WRITE_PHASE_LOW>(uint8_t(0x08)))
return false;
1745 if (!this->
template sync_write<WRITE_VCSEL_WIDTH>(vcsel_width))
return false;
1747 if (!this->
template sync_write<WRITE_PHASECAL_TIMEOUT>(phasecal_timeout))
return false;
1749 if (!this->
template sync_write<WRITE_PHASECAL_LIMIT>(phasecal_limit))
return false;
1751 if (!this->
template sync_write<WRITE_VCSEL>(vcsel_period))
return false;
1754 uint16_t final_range_mclks = vl53l0x::TimeoutUtilities::encode_timeout(
1755 vl53l0x::TimeoutUtilities::calculate_timeout_mclks(
1756 timeouts.final_range_us(has_pre_range), period));
1757 return this->
template sync_write<WRITE_RANGE_TIMEOUT>(final_range_mclks);
1760 static constexpr bool check_vcsel_period(
VcselPeriodType type, uint8_t period)
1762 if (type == VcselPeriodType::PRE_RANGE)
1763 return check_vcsel_period_pre_range(period);
1765 return check_vcsel_period_final_range(period);
1768 static constexpr bool check_vcsel_period_pre_range(uint8_t period)
1783 static constexpr bool check_vcsel_period_final_range(uint8_t period)
1798 static constexpr uint8_t encode_vcsel_period(uint8_t period)
1800 return (period >> 1U) - 1U;
1802 static constexpr uint8_t decode_vcsel_period(uint8_t value)
1804 return (value + 1U) << 1U;
1807 static constexpr const uint8_t NUM_REF_SPADS = 48;
1808 static constexpr const uint8_t SPADS_PER_BYTE = 8;
1809 static constexpr const uint8_t NUM_REF_SPADS_BYTES = NUM_REF_SPADS / SPADS_PER_BYTE;
1811 static constexpr const uint8_t FIRST_APERTURE_SPAD = 12;
1812 static void calculate_reference_SPADs(uint8_t ref_spads[NUM_REF_SPADS_BYTES], vl53l0x::SPADInfo info)
1814 const uint8_t count = info.count();
1815 const uint8_t first_spad = (info.is_aperture() ? FIRST_APERTURE_SPAD : 0);
1816 uint8_t enabled_spads = 0;
1818 for (uint8_t i = 0; i < NUM_REF_SPADS_BYTES; ++i)
1820 uint8_t& ref_spad = ref_spads[i];
1821 for (uint8_t j = 0; j < SPADS_PER_BYTE; ++j)
1823 if ((spad < first_spad) || (enabled_spads == count))
1834 static constexpr const uint32_t MIN_TIMING_BUDGET = 20'000UL;
1835 static constexpr const uint16_t START_OVERHEAD_SET = 1320U;
1836 static constexpr const uint16_t START_OVERHEAD_GET = 1910U;
1837 static constexpr const uint16_t END_OVERHEAD = 960U;
1838 static constexpr const uint16_t MSRC_OVERHEAD = 660U;
1839 static constexpr const uint16_t TCC_OVERHEAD = 590U;
1840 static constexpr const uint16_t DSS_OVERHEAD = 690U;
1841 static constexpr const uint16_t PRE_RANGE_OVERHEAD = 660U;
1842 static constexpr const uint16_t FINAL_RANGE_OVERHEAD = 550U;
1844 static uint32_t calculate_measurement_budget_us(
1845 bool get,
const vl53l0x::SequenceSteps steps,
const vl53l0x::SequenceStepsTimeout& timeouts)
1848 uint32_t budget_us = (get ? START_OVERHEAD_GET : START_OVERHEAD_SET) + END_OVERHEAD;
1851 budget_us += timeouts.msrc_dss_tcc_us() + TCC_OVERHEAD;
1854 budget_us += 2 * (timeouts.msrc_dss_tcc_us() + DSS_OVERHEAD);
1855 else if (steps.is_msrc())
1856 budget_us += timeouts.msrc_dss_tcc_us() + MSRC_OVERHEAD;
1858 if (steps.is_pre_range())
1859 budget_us += timeouts.pre_range_us() + PRE_RANGE_OVERHEAD;
1861 if (steps.is_final_range())
1862 budget_us += timeouts.final_range_us(steps.is_pre_range()) + FINAL_RANGE_OVERHEAD;
1867 static uint16_t calculate_final_range_timeout(
1868 const vl53l0x::SequenceSteps steps,
const vl53l0x::SequenceStepsTimeout& timeouts, uint32_t budget_us)
1871 if (budget_us < MIN_TIMING_BUDGET)
return 0;
1873 if (!steps.is_final_range())
return 0;
1876 uint32_t used_budget_us =
1877 calculate_measurement_budget_us(
false, steps.no_final_range(), timeouts);
1880 used_budget_us += FINAL_RANGE_OVERHEAD;
1882 if (used_budget_us > budget_us)
return 0;
1885 const uint32_t final_range_timeout_us = budget_us - used_budget_us;
1888 uint32_t final_range_timeout_mclks = vl53l0x::TimeoutUtilities::calculate_timeout_mclks(
1889 final_range_timeout_us, timeouts.final_range_vcsel_period_pclks());
1890 if (steps.is_pre_range())
1891 final_range_timeout_mclks += timeouts.pre_range_mclks();
1893 return vl53l0x::TimeoutUtilities::encode_timeout(final_range_timeout_mclks);
1896 static constexpr const uint8_t DEFAULT_DEVICE_ADDRESS = 0x52;
1899 uint8_t stop_variable_ = 0;
Status of device as retrieved by VL53L0X::get_range_status().
static constexpr uint16_t convert(float value)
Convert a float value into an 9.7 fix-point.
Settings for behavior of VL53L0X GPIO pin.
bool high_polarity() const
Return the current polarity level of GPIO interrupts.
static constexpr GPIOSettings sample_ready(bool high_polarity=false)
Create GPIOSettings for interrupt triggered when range sample is ready.
static constexpr GPIOSettings low_threshold(uint16_t threshold, bool high_polarity=false)
Create GPIOSettings for interrupt triggered when range is under threshold.
static constexpr GPIOSettings high_threshold(uint16_t threshold, bool high_polarity=false)
Create GPIOSettings for interrupt triggered when range is above threshold.
GPIOFunction function() const
Return the current GPIO interrupt trigger source.
Hold SPAD information from VL53L0X device.
Hold reference SPADs (Single Photon Avalanche Diode).
const uint8_t * spad_refs() const
Get a pointer to the 6-byte array stored in this SPADReference instance.
Hold VL53L0X sequence steps to use for ranging.
static constexpr SequenceSteps create()
Create an empty step sequence for further adding individual steps.
Hold VL53L0X sequence steps timeouts and other related settings used for ranging.
Future to get device current GPIO settings.
Future to set device GPIO settings.
I2C device driver for the VL53L0X ToF ranging chip.
TWriteRegisterFuture< Register::SYSTEM_INTERRUPT_CLEAR > ClearInterruptFuture
Future to clear device interrupt status.
bool get_sequence_steps(SequenceSteps &sequence_steps)
Get current measurement steps executed in sequence by the device during ranging.
bool get_vcsel_pulse_period(uint8_t &period)
Get current pulse period of the VCSEL for pre-range or final-range step.
bool get_SPAD_info(SPADInfo &info)
Get current SPAD information (number of SPAD aperture or not).
bool get_measurement_timing_budget(uint32_t &budget_us)
Get current "measurement timing budget" for this device.
bool set_GPIO_settings(const GPIOSettings &settings)
Set new GPIOSettings for this device.
int get_register(TReadRegisterFuture< REGISTER, T > &future)
Directly get value of a VL53L0X register.
bool init_data_first()
Perform 1st stage initialization of this VL53L0X device.
bool await_interrupt(uint16_t loops=MAX_LOOP)
Wait for an interrupt condition on VL53L0X device.
int get_GPIO_settings(GetGPIOSettingsFuture &future)
Get current GPIOSettings from this device.
bool set_register(T value)
Directly set value of a VL53L0X register.
bool get_register(T &value)
Directly get value of a VL53L0X register.
bool get_range_status(DeviceStatus &range_status)
Get current DeviceStatus from this device.
bool get_signal_rate_limit(float &signal_rate)
Get current signal rate limit for ranging.
bool set_vcsel_pulse_period(uint8_t period)
Set new pulse period of the VCSEL for pre-range or final-range step.
bool get_sequence_steps_timeout(SequenceStepsTimeout &timeouts)
Get current timeouts associated to each ranging step.
bool init_static_second(const GPIOSettings &settings, SequenceSteps steps=SequenceSteps::create().pre_range().final_range().dss())
Perform 2nd stage initialization of this VL53L0X device.
bool get_direct_range(uint16_t &range_mm)
Get range measured by this device.
bool set_address(uint8_t device_address)
Change the I2C address of this VL53L0X device.
bool set_measurement_timing_budget(uint32_t budget_us)
Set new "measurement timing budget" for this device.
bool get_interrupt_status(InterruptStatus &status)
Get current InterruptStatus from this device.
bool clear_interrupt(uint8_t clear_mask=0x01)
Clear interrupt status from this device.
bool get_model(uint8_t &model)
Get model of this VL53L0X register.
bool perform_ref_calibration()
Perform VL53L0X VHV and Phase calibration.
bool stop_continuous_ranging()
Stop continuous ranging on this VL53L0X device.
bool set_signal_rate_limit(float signal_rate)
Set new signal rate limit for ranging.
bool set_sequence_steps(SequenceSteps sequence_steps)
Set measurement steps to be executed in sequence by the device during ranging.
bool begin(Profile profile)
Fully initialize this VL53L0X device and configures it with provided profile.
bool await_continuous_range(timer::RTT< TIMER > &rtt, uint16_t &range_mm, uint16_t timeout_ms=DEFAULT_TIMEOUT_MS)
Wait for the next continuous ranging measure on VL53L0X device to be ready and return the result.
bool await_continuous_range(uint16_t &range_mm, uint16_t loops=MAX_LOOP)
Wait for the next continuous ranging measure on VL53L0X device to be ready and return the result.
int get_range_status(GetRangeStatusFuture &future)
Get current DeviceStatus from this device.
bool await_single_range(uint16_t &range_mm, uint16_t loops=MAX_LOOP)
Perform a single range action on VL53L0X device, and wait for the measurement result.
bool start_continuous_ranging(uint16_t period_ms=0)
Start continuous ranging on this VL53L0X device.
bool get_reference_SPADs(SPADReference &spad_ref)
Get the reference SPADs status (enabled or not).
bool get_GPIO_settings(GPIOSettings &settings)
Get current GPIOSettings from this device.
bool await_interrupt(timer::RTT< TIMER > &rtt, uint16_t timeout_ms=DEFAULT_TIMEOUT_MS)
Wait for an interrupt condition on VL53L0X device.
bool get_revision(uint8_t &revision)
Get revision of this VL53L0X register.
bool await_single_range(timer::RTT< TIMER > &rtt, uint16_t &range_mm, uint16_t timeout_ms=DEFAULT_TIMEOUT_MS)
Perform a single range action on VL53L0X device, and wait for the measurement result.
int set_register(TWriteRegisterFuture< REGISTER, T > &future)
Directly set value of a VL53L0X register.
bool get_power_mode(PowerMode &power_mode)
Get current power mode of this VL53L0X register.
bool set_reference_SPADs(const SPADReference &spad_ref)
Set the reference SPADs status (enabled or not).
int get_direct_range(GetDirectRangeFuture &future)
Get range measured by this device.
int set_GPIO_settings(SetGPIOSettingsFuture &future)
Set new GPIOSettings for this device.
int clear_interrupt(ClearInterruptFuture &future)
Clear interrupt status from this device.
VL53L0X(MANAGER &manager)
Create a new device driver for a VL53L0X chip.
int get_interrupt_status(GetInterruptStatusFuture &future)
Get current InterruptStatus from this device.
bool reset_device()
Reset VL53L0X device.
Endianness change functor: will change from big to little or little to big endian format on integer t...
Base class for all I2C devices.
void set_device(uint8_t device)
Change the I2C address of this device.
int async_write(F &future, bool stop=true)
Helper method that asynchronously launches I2C commands for a simple Future performing only one write...
MANAGER MANAGER
the type of I2C Manager that can handle this device.
int async_read(F &future, bool stop=true)
Helper method that asynchronously launches I2C commands for a simple Future performing one write foll...
Abstract class to allow aggregation of several futures in relation to I2C transactions.
Generic Future that can be used to read an I2C device register.
Generic Future that can be used to write to an I2C device register.
Structure used to hold a time value with microsecond precision.
uint32_t millis() const
Number of elapsed milliseconds.
API to handle a real-time timer.
time::RTTTime time() const
Elapsed time, in milliseconds and microseconds, since this timer has started.
#define DECL_FUTURE_LISTENERS_FRIEND
This macro shall be used in a class containing a private callback method void on_status_change(const ...
static constexpr uint8_t CBV8(uint8_t bit)
Create a uint8_t inverted bitmask for the given bit number.
static constexpr uint8_t BV8(uint8_t bit)
Create a uint8_t bitmask for the given bit number.
Defines API for VL53L0X Time-of-Flight ranging sensor chip usage.
VcselPeriodType
Type of pulse period configured for VL53L0X device VCSEL (Vertical Cavity Surface Emitting Laser).
PowerMode
Possible power modes of VL53L0X device as returned by VL53L0X::get_power_mode().
GPIOFunction
Possible triggers for VL53L0X GPIO pin.
@ DISABLED
No interrupt triggered on GPIO pin.
Profile
Possible profiles of ranging for VL53L0X top-level API VL53L0X::begin().
Defines all API for all external devices supported by FastArduino.
Contains the API around Future implementation.
@ READY
The status of a Future once its output value has been fully set by a provider.
Define API to define and manage I2C devices.
void register_handler(Handler &handler)
Register a class instance containing methods that shall be called back by an ISR.
void unregister_handler(Handler &handler)
Unregister a class instance that was previously registered with interrupt::register_handler.
void delay_us(uint16_t us) INLINE
Delay program execution for the given amount of microseconds.
API to handle Time-of-Flight ranging sensor VL53L0X I2C chip.