Sense.TOF
TMF8806 time-of-flight distance sensor.
Platform-agnostic driver for the AMS/Sciosense TMF8806 direct time-of-flight (dToF) sensor with integrated VCSEL emitter and SPAD detector array.
Vibe Settings
What Studio’s Vibe interface lets you change on this tile, in plain language or from the tile inspector. Each one is an argument of a driver function below, so the same setting is available from Blocks, the DSL and C. Basic settings are shown by default; advanced ones sit behind the inspector’s Advanced toggle.
| Setting | Tier | Values | Default | Function |
|---|---|---|---|---|
| Distance range | basic | Short range, ~200 mm max, lowest power, Medium range up to 2500 mm (default), Long range up to 5000 mm | Medium range up to 2500 mm (default) | set_distance_mode(mode) |
| Measurement rate | basic | Every 30 ms, ~33 per second (default), Every 50 ms, 20 per second, Every 100 ms, 10 per second, Every 250 ms, 4 per second, Every second, Every 2 seconds | Every 30 ms, ~33 per second (default) | set_period(period) |
| Iterations (thousands) | advanced | 10 to 4000 | 900 | set_kilo_iters(kilo_iters) |
| Detection threshold | advanced | 0 to 63 | 6 | set_threshold(threshold) |
Examples
Quick start
#include "core.h"
#include "core_tiles.h"
#include "tile_sense_tof.h"
tile_t tof;
sense_tof_cfg_t cfg = { .mode = SENSE_TOF_RANGE_2500MM };
tile_sense_tof_init(core_tiles_pal(&core_i2c1), 0, &tof, &cfg);
tile_sense_tof_start(&tof);
// ... poll or wait for interrupt ...
uint16_t dist = tile_sense_tof_get_distance_mm(&tof);
// Single-shot convenience:
sense_tof_result_t res;
tile_sense_tof_measure_single(&tof, &res, 500);API reference
Initialization
tile_sense_tof_find
uint8_t tile_sense_tof_find(tiles_pal_t *hal, uint8_t instance)Probes the I2C address and reads the ID register. The TMF8806 has a single fixed address (0x41), so only instance 0 is valid.
- hal
- Platform HAL handle.
- instance
- Must be 0 (single-address device).
Returns 1 if device ACKs and ID matches (0x09), 0 otherwise.
tile_sense_tof_init
void tile_sense_tof_init(tiles_pal_t *hal, uint8_t instance, tile_t *tile, const sense_tof_cfg_t *cfg)Performs the full TMF8806 boot sequence: 1. Waits for bootloader to enter sleep (ENABLE == 0x00) 2. Wakes the bootloader (PON = 1) 3. Waits for CPU ready (ENABLE == 0x41) 4. Requests App0 measurement application 5. Waits for App0 to start (APPID == 0xC0) 6. Enables result interrupt Does NOT start measurements — call tile_sense_tof_start() after init. Does NOT software-reset to preserve any existing calibration data.
- hal
- Platform HAL handle.
- instance
- Must be 0 (single-address device).
- tile
- Tile handle to initialise.
- cfg
- Configuration (NULL for defaults: 2.5 m, 30 ms, 900k iters).
Lifecycle
tile_sense_tof_sleep
Studiovoid tile_sense_tof_sleep(tile_t *tile)Stops any active measurement and powers down the sensor. Use tile_sense_tof_wake() to resume without full re-initialisation.
tile_sense_tof_wake
Studiovoid tile_sense_tof_wake(tile_t *tile)Re-executes the bootloader wake and App0 request sequence. Does not restart measurements — call tile_sense_tof_start() after waking.
tile_sense_tof_reset
Studiovoid tile_sense_tof_reset(tile_t *tile)Performs a full CPU reset and re-runs the boot sequence, so the tile is ready again afterwards. Calibration and saved algorithm state are dropped; the measurement configuration (mode, period, iterations, threshold) is kept. Ranging is stopped: call start() to resume.
Runtime
tile_sense_tof_start
Studiovoid tile_sense_tof_start(tile_t *tile)Writes the factory calibration data (if loaded), configures the measurement command payload from the current cfg, and issues the measurement command. Results are signaled via the result interrupt. If period_ms == 0x00 in the config, a single measurement is taken. Otherwise measurements repeat at the configured period.
tile_sense_tof_stop
Studiovoid tile_sense_tof_stop(tile_t *tile)Sends the stop command and waits for the sensor to acknowledge. No-op if no measurement is active.
tile_sense_tof_get_distance_mm
Studiouint16_t tile_sense_tof_get_distance_mm(tile_t *tile)Returns the peak distance in millimeters. Does not check whether new data is available — call tile_sense_tof_result_ready() first or use tile_sense_tof_get_result() for full status. When nothing is in range the sensor reports 0; this SATURATES that to tile_sense_tof_max_range_mm() rather than returning 0, so `if (distance < threshold)` behaves correctly with no special case — "out of range" reads as "very far away", which is what it physically means. Use tile_sense_tof_get_result() when you need to tell "no target" from "target at max range"; that reports the raw value.
Returns Distance in millimeters, saturating at the configured max range.
tile_sense_tof_max_range_mm
Studiouint16_t tile_sense_tof_max_range_mm(tile_t *tile)200 mm (short range), 2500 mm, or 5000 mm. This is the value tile_sense_tof_get_distance_mm() saturates to when no object is detected, so `distance >= max_range_mm()` is the explicit "nothing in range" test.
Returns Maximum range in millimeters.
tile_sense_tof_get_result_flat
Studiovoid tile_sense_tof_get_result_flat(tile_t *tile, int32_t *out)Drops the struct in favor of a positional int[5] array — the DSL doesn't have a struct ABI yet, so the per-field outputs come back indexed. Layout: out[0]=distance_mm, out[1]=status, out[2]=reliability, out[3]=temperature_c, out[4]=result_number. The temperature is widened from int8_t to int32_t so negative values sign-extend correctly.
- out
- Output buffer (5 int32_t slots).
tile_sense_tof_measure_single_flat
Studiouint8_t tile_sense_tof_measure_single_flat(tile_t *tile, int32_t *mm, int32_t *status, int32_t *reliability, int32_t *temp_c, int32_t *seq, uint32_t timeout_ms)Combines a single-shot measurement with positional int outputs. Same layout convention as get_result_flat — the per-field values land in five out-scalar slots. Returns the chip's success flag.
- mm
- Output: distance in millimetres.
- status
- Output: result status code.
- reliability
- Output: 0–63 reliability score.
- temp_c
- Output: die temperature in degrees Celsius.
- seq
- Output: monotonic result counter.
- timeout_ms
- Maximum wait for the measurement to complete.
Returns 1 on a valid result, 0 on timeout / bus error.
tile_sense_tof_result_ready
Studiouint8_t tile_sense_tof_result_ready(tile_t *tile)Reads the INT_STATUS register and checks the result interrupt bit. Does not clear the interrupt — that is done by get_result() or get_distance_mm().
Returns 1 if a new result is pending, 0 otherwise.
tile_sense_tof_set_distance_mode
Studiovoid tile_sense_tof_set_distance_mode(tile_t *tile, sense_tof_distance_mode_t mode)Stops any active measurement, updates the cached mode, and restarts. If no measurement was running, only updates the config for the next start().
- mode
- New distance mode.
tile_sense_tof_set_period
Studiovoid tile_sense_tof_set_period(tile_t *tile, sense_tof_period_t period)Slower rates save most of the power: the laser only fires for the ranging time (~24 ms at the default 900k iterations), and the chip idles at ~140 uA for the rest of each period. Stops any active measurement, updates the cached period, and restarts. If no measurement was running, only updates the config for the next start().
- period
- New repetition period (sense_tof_period_t, or 1-253 ms).
tile_sense_tof_set_kilo_iters
Studiovoid tile_sense_tof_set_kilo_iters(tile_t *tile, uint16_t kilo_iters)Iterations (in thousands) trade power for SNR/range: more iterations give a stronger return and longer reach at higher current draw. Typical range 10-4000 (10k-4M); the ranging default is 900. Stops any active measurement, updates the cached value, and restarts.
- kilo_iters
- [10..4000] Iterations in thousands (e.g. 900 = 900k).
tile_sense_tof_set_threshold
Studiovoid tile_sense_tof_set_threshold(tile_t *tile, uint8_t threshold)Sets cmd_data3[5:0] — the minimum confidence for a reported target. Higher values reject weak/spurious returns. 0 is not "everything": the chip uses 6 instead (datasheet §6.9.3). Stops any active measurement, updates the cached value, and restarts.
- threshold
- [0..63] Detection threshold, 0-63.
tile_sense_tof_get_signal_quality_flat
Studiovoid tile_sense_tof_get_signal_quality_flat(tile_t *tile, int32_t *reference_hits, int32_t *object_hits, int32_t *crosstalk)Reads the most recent result block (one 10-byte burst). Reference and object hits are zero when no object was detected (datasheet §7.3.11 to §7.3.18). Crosstalk is only meaningful with low ambient light and no target within 40 cm (§7.3.19). Call after a result is ready.
- reference_hits
- Output: reference-channel SPAD hit sum (or NULL).
- object_hits
- Output: object-channel SPAD hit sum (or NULL).
- crosstalk
- Output: crosstalk peak value, 0-65535 (or NULL).
tile_sense_tof_get_sys_clock_ticks
Studiouint32_t tile_sense_tof_get_sys_clock_ticks(tile_t *tile)The TMF8806's internal oscillator can drift ±4 % over temperature, which biases distance readings if the host's measurement period doesn't compensate. Reading this register set after each measurement lets the host compute the actual elapsed chip-time vs. its own elapsed wall-time and apply a software correction (HostDriverCommunication §10). Reads SYS_CLOCK_0..3 (0x24–0x27) as a single 4-byte burst. measurement yet).
Returns 32-bit system-clock tick count (0 if not in App0 / no
tile_sense_tof_is_object_within
Studiouint8_t tile_sense_tof_is_object_within(tile_t *tile, uint16_t mm)Performs one blocking single-shot measurement (up to 300 ms) and returns 1 iff the reported distance is non-zero, less than or equal to `mm`, and the result counts as a detection: a short-range result (reliability 1 or 10, which is what short-range mode and any object within ~200 mm give) or a long-range result with reliability of at least @ref SENSE_TOF_PRESENCE_RELIABILITY_MIN. If continuous ranging was running it is paused for the shot and resumed afterwards. 0 otherwise (no target, low reliability, or bus timeout).
- mm
- Distance threshold in millimetres (inclusive).
Returns 1 if an object is within range with adequate confidence,
tile_sense_tof_wait_for_object
Studiouint8_t tile_sense_tof_wait_for_object(tile_t *tile, uint16_t mm, uint32_t timeout_ms)Polls single-shot measurements until one matches the `is_object_within` predicate or `timeout_ms` elapses. Polls every single-shot measurement adds ~30 ms of its own.
- mm
- Distance threshold in millimetres (inclusive).
- timeout_ms
- Maximum wait time in milliseconds.
Returns 1 if an object entered range before timeout, 0 otherwise.
- v1 implementation polls — keeps the helper self-contained and avoids the need to wire the chip's INT pin into the tile pad map. A future revision could swap to the chip's threshold-INT (see @ref tile_sense_tof_set_threshold_interrupt) to let a sleeping host stay asleep until proximity wakes it.
tile_sense_tof_read_distance_with_confidence
Studiouint8_t tile_sense_tof_read_distance_with_confidence(tile_t *tile, uint16_t *mm, uint8_t *confidence_pct)Performs a single-shot measurement and writes the distance (mm) and a 0–100 percent confidence. A long-range result maps its 0–63 reliability as `(reliability * 100) / 63`; the short-range codes are not a scale, so 10 (calibrated) reads as 100 and 1 (uncalibrated) as 50. Integer math, no floats.
- mm
- Output: distance in millimetres (NULL allowed).
- confidence_pct
- Output: 0–100 confidence (NULL allowed).
Returns 1 on a successful measurement, 0 on timeout / bus error.
Config
tile_sense_tof_set_threshold_interrupt
Studiouint8_t tile_sense_tof_set_threshold_interrupt(tile_t *tile, uint8_t persistence, uint16_t low_mm, uint16_t high_mm)Without this configured, the chip fires INT on every measurement completion. With it: INT only fires when an object is detected in the [low_mm, high_mm] range for `persistence` consecutive measurements. Lets a sleeping host stay asleep until something gets close. Per HostDriverCommunication §8.12 (cmd 0x08 = WR_ADD_CONFIG): - persistence = 0 → interrupt every measurement (default) - persistence = N → require N consecutive in-range hits - low_mm > high_mm → no interrupts (no valid range)
- persistence
- 0–255; 0 = disabled (every-measurement INT).
- low_mm
- Lower bound (inclusive), millimetres.
- high_mm
- Upper bound (inclusive), millimetres.
Returns 1 on success, 0 on bus / command-execution timeout.
Advanced
tile_sense_tof_factory_calibrate
Studiouint8_t tile_sense_tof_factory_calibrate(tile_t *tile, uint32_t timeout_ms)Performs a calibration measurement using the current mode settings. The sensor must be positioned with a known target or open field per the TMF8806 calibration guidelines. Results are stored internally and can be retrieved with tile_sense_tof_get_calibration(). This is a blocking call that waits for the calibration to complete: about 1.1 s in 2.5 m mode and 2.2 s in 5 m mode (40.96 M iterations), so a timeout below 3000 ms is raised to 3000. Continuous ranging is paused and resumed. The calibration belongs to the current mode's family: short range and 2.5 m share one, 5 m needs its own (datasheet §6.4), and switching across that line drops it.
- timeout_ms
- Maximum wait time in milliseconds.
Returns 1 if calibration completed successfully, 0 on timeout or error.
tile_sense_tof_set_calibration
Studiovoid tile_sense_tof_set_calibration(tile_t *tile, const uint8_t *data)Stores a 14-byte calibration dataset that will be written to the sensor before each measurement start. Call this after init() to restore calibration from non-volatile storage.
- data
- Pointer to 14-byte calibration data array.
tile_sense_tof_get_calibration
Studiovoid tile_sense_tof_get_calibration(tile_t *tile, uint8_t *data)Reads 14 bytes of calibration data from the sensor's calibration registers. Typically called after tile_sense_tof_factory_calibrate() to save the data for later reloading via set_calibration().
- data
- Output buffer for 14 bytes of calibration data.
tile_sense_tof_get_app_version_flat
Studiovoid tile_sense_tof_get_app_version_flat(tile_t *tile, int32_t *major, int32_t *minor, int32_t *patch)Drops the struct in favor of three positional out-scalars.
- major
- Output: major version number.
- minor
- Output: minor version number.
- patch
- Output: patch version number.
tile_sense_tof_get_serial_number_flat
Studiovoid tile_sense_tof_get_serial_number_flat(tile_t *tile, int32_t *out)Drops the success bool — on bus error, the buffer comes back as all-zeros, which is invalid as a real serial number so callers can detect failure by checking for a zero serial. Bytes widen to int32 for DSL int compatibility.
- out
- Output buffer (4 int32_t slots).
tile_sense_tof_save_state
Studiovoid tile_sense_tof_save_state(tile_t *tile, uint8_t *data)Reads 11 bytes of algorithm state data from the sensor (registers 0x28-0x32). This state should be saved before entering sleep in ultra-low-power mode, and restored after wake via restore_state(). Preserving algorithm state across power cycles avoids the ~8 ms re-initialisation penalty and maintains measurement accuracy.
- data
- Output buffer for 11 bytes of state data.
tile_sense_tof_restore_state
Studiovoid tile_sense_tof_restore_state(tile_t *tile, const uint8_t *data)Writes 11 bytes of previously saved algorithm state to the sensor (registers 0x2E-0x38). Call this after wake() and before start() to resume from the saved algorithm state. The calibration data bitmask in the measurement command (cmd_data7) is automatically updated to include algState when state data has been restored.
- data
- Pointer to 11 bytes of previously saved state data.
tile_sense_tof_get_threshold_interrupt
Studiouint8_t tile_sense_tof_get_threshold_interrupt(tile_t *tile, uint8_t *persistence, uint16_t *low_mm, uint16_t *high_mm)Per HostDriverCommunication §8.12.2 (cmd 0x09 = RD_ADD_CONFIG).
- persistence
- Output (may be NULL).
- low_mm
- Output (may be NULL).
- high_mm
- Output (may be NULL).
Returns 1 on success, 0 on timeout.
tile_sense_tof_read_histogram_flat
Studiovoid tile_sense_tof_read_histogram_flat(tile_t *tile, uint8_t hist_type, uint32_t timeout_ms, int32_t *out)Drops the success bool — on timeout / bus error the buffer comes back zero-filled. Bytes widen to int32 for DSL int compatibility. Caller passes hist_type and timeout_ms as scalar args; the buffer is the function's output (collapsed into the int[128] return).
- hist_type
- Histogram-type byte (see read_histogram() docs).
- timeout_ms
- Maximum wait for the histogram-ready interrupt.
- out
- Output buffer (128 int32_t slots).
Driver gaps · 6
Chip capabilities this driver doesn’t expose yet.
Enums
sense_tof_distance_mode_t
Distance mode selection.
- SENSE_TOF_SHORT_RANGE
- Short range, ~200 mm max, lowest power
- SENSE_TOF_RANGE_2500MM
- Medium range up to 2500 mm (default)
- SENSE_TOF_RANGE_5000MM
- Long range up to 5000 mm
sense_tof_period_t
Measurement repetition period (cmd_data2, `repetitionPeriodMs`).
- SENSE_TOF_PERIOD_30MS
- Every 30 ms, ~33 per second (default) @studio value=33.3
- SENSE_TOF_PERIOD_50MS
- Every 50 ms, 20 per second @studio value=20
- SENSE_TOF_PERIOD_100MS
- Every 100 ms, 10 per second @studio value=10
- SENSE_TOF_PERIOD_250MS
- Every 250 ms, 4 per second @studio value=4
- SENSE_TOF_PERIOD_1S
- Every second @studio value=1
- SENSE_TOF_PERIOD_2S
- Every 2 seconds @studio value=0.5
Constants
| TILE_SENSE_TOF_VERSION_MAJOR | 1 | |
| TILE_SENSE_TOF_VERSION_MINOR | 6 | |
| TILE_SENSE_TOF_VERSION_PATCH | 0 | |
| TMF8806_I2C_ADDR | 0x41 | Fixed 7-bit I2C address |
| TMF8806_DEVICE_ID | 0x09 | Expected ID value (bits 5:0 only) |
| TMF8806_ID_MASK | 0x3F | Mask for valid ID bits |
| TMF8806_ENABLE_PON | 0x01 | Power-on bit |
| TMF8806_ENABLE_CPU_READY | 0x41 | CPU ready + PON |
| TMF8806_ENABLE_CPU_RESET | 0x80 | CPU reset bit |
| TMF8806_APPID_BOOTLOADER | 0x80 | Bootloader is running |
| TMF8806_APPID_APP0 | 0xC0 | Measurement application running |
| TMF8806_CMD_MEASURE | 0x02 | Start measurement |
| TMF8806_CMD_FACTORY_CAL | 0x0A | Run factory calibration |
| TMF8806_CMD_STOP | 0xFF | Stop measurement |
| TMF8806_CMD_SERIAL | 0x47 | Read serial number |
| TMF8806_FACTORY_CAL_KITERS | 0xA000 | |
| TMF8806_INT_RESULT | 0x01 | Result interrupt flag |
| TMF8806_INT_HISTOGRAM | 0x02 | Histogram interrupt flag |
| TMF8806_CONTENTS_RESULT | 0x55 | Result data available |
| TMF8806_CONTENTS_CALIB | 0x0A | Calibration data available |
| TMF8806_CONTENTS_SERIAL | 0x47 | Serial number available |
| TMF8806_CALIB_DATA_LEN | 14 | Factory calibration data length |
| TMF8806_STATE_DATA_LEN | 11 | Algorithm state data length |
| TMF8806_BOOT_TIMEOUT_MS | 500 | Maximum boot sequence wait |
| TMF8806_CMD_TIMEOUT_MS | 1000 | Maximum command completion wait |
| TMF8806_POLL_INTERVAL_MS | 2 | Polling interval during boot |
| SENSE_TOF_PRESENCE_RELIABILITY_MIN | 32 | |
| SENSE_TOF_WAIT_POLL_INTERVAL_MS | 10 |

