BERGSONNE

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.

Datasheet

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

Studio
void 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
Initialised tile handle.

tile_sense_tof_wake

Studio
void 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
Sleeping tile handle.

tile_sense_tof_reset

Studio
void tile_sense_tof_reset(tile_t *tile)

Performs a full CPU reset and re-runs the boot sequence. All runtime state including calibration is lost. Call init() again after reset.

tile
Tile handle.

Runtime

tile_sense_tof_start

Studio
void 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
Initialised tile handle.

tile_sense_tof_stop

Studio
void 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
Initialised tile handle.

tile_sense_tof_get_distance_mm

Studio
uint16_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.

tile
Initialised tile handle.

Returns Distance in millimeters, or 0 if no object detected.

tile_sense_tof_get_result_flat

Studio
void 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.

tile
Initialised tile handle.
out
Output buffer (5 int32_t slots).

tile_sense_tof_measure_single_flat

Studio
uint8_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.

tile
Initialised tile handle.
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

Studio
uint8_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().

tile
Initialised tile handle.

Returns 1 if a new result is pending, 0 otherwise.

tile_sense_tof_set_distance_mode

Studio
void 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().

tile
Initialised tile handle.
mode
New distance mode.

tile_sense_tof_set_period

Studio
void tile_sense_tof_set_period(tile_t *tile, uint8_t period_ms)

Stops any active measurement, updates the cached period, and restarts. If no measurement was running, only updates the config for the next start().

tile
Initialised tile handle.
period_ms
New period code (0x00=single, 0x1E=30ms, 0xFE=1s, 0xFF=2s).

tile_sense_tof_set_kilo_iters

Studio
void 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.

tile
Initialised tile handle.
kilo_iters
Iterations in thousands (e.g. 900 = 900k).

tile_sense_tof_set_threshold

Studio
void 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 reports everything. Stops any active measurement, updates the cached value, and restarts.

tile
Initialised tile handle.
threshold
Detection threshold, 0-63.

tile_sense_tof_get_signal_quality_flat

Studio
void tile_sense_tof_get_signal_quality_flat(tile_t *tile, int32_t *reference_hits, int32_t *object_hits, int32_t *crosstalk)

Read signal-quality diagnostics into flat out-params (Studio).

tile
Initialised tile handle.
reference_hits
Reference-channel hit count (or NULL).
object_hits
Object-channel hit count (or NULL).
crosstalk
Cross-talk count (or NULL).

tile_sense_tof_get_sys_clock_ticks

Studio
uint32_t tile_sense_tof_get_sys_clock_ticks(tile_t *tile)

The TMF8806's internal oscillator can drift ±5 % 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).

tile
Initialised tile handle.

Returns 32-bit system-clock tick count (0 if not in App0 / no

tile_sense_tof_is_object_within

Studio
uint8_t tile_sense_tof_is_object_within(tile_t *tile, uint16_t mm)

Performs one blocking single-shot measurement (up to 200 ms) and returns 1 iff the reported distance is non-zero, less than or equal to `mm`, and the reliability is at least low-confidence hit is treated as "no object". Restores the prior measurement period on the way out, so this mixes safely with continuous-mode use. 0 otherwise (no target, low reliability, or bus timeout).

tile
Initialised tile handle.
mm
Distance threshold in millimetres (inclusive).

Returns 1 if an object is within range with adequate confidence,

tile_sense_tof_wait_for_object

Studio
uint8_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.

tile
Initialised tile handle.
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

Studio
uint8_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 the confidence remapped from the chip's 0–63 reliability scale to a 0–100 percent value. Confidence is computed as `(reliability * 100) / 63` — integer math, no floats.

tile
Initialised tile handle.
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

Studio
uint8_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)

tile
Initialised tile handle.
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

Studio
uint8_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.

tile
Initialised tile handle.
timeout_ms
Maximum wait time in milliseconds.

Returns 1 if calibration completed successfully, 0 on timeout or error.

tile_sense_tof_set_calibration

Studio
void 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.

tile
Initialised tile handle.
data
Pointer to 14-byte calibration data array.

tile_sense_tof_get_calibration

Studio
void 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().

tile
Initialised tile handle.
data
Output buffer for 14 bytes of calibration data.

tile_sense_tof_get_app_version_flat

Studio
void 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.

tile
Initialised tile handle.
major
Output: major version number.
minor
Output: minor version number.
patch
Output: patch version number.

tile_sense_tof_get_serial_number_flat

Studio
void 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.

tile
Initialised tile handle.
out
Output buffer (4 int32_t slots).

tile_sense_tof_save_state

Studio
void 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.

tile
Initialised tile handle (measurement should be stopped).
data
Output buffer for 11 bytes of state data.

tile_sense_tof_restore_state

Studio
void 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.

tile
Initialised tile handle (after wake, before start).
data
Pointer to 11 bytes of previously saved state data.

tile_sense_tof_get_threshold_interrupt

Studio
uint8_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).

tile
Initialised tile handle.
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

Studio
void 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).

tile
Initialised tile handle.
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).
gap10 m extended-range modeDeferred to a dedicated session. TMF8806 App0 firmware supports up to 5 m range out of ROM; 10 m mode requires downloading a binary RAM patch from AMS via the bootloader's W_RAM + RAMREMAP_RESET protocol — non-trivial firmware-loading flow not in scope for this driver-coverage pass.

Driver gaps · 1

Chip capabilities this driver doesn’t expose yet.

nicheGPIO0 / GPIO1 runtime controlGPIO0 is routed to tile pad 3 but is consumed as a hardware strap: a 100 k on-board pull-up to V+ holds GPIO0 high at startup, selecting the 1.8-3.3 V digital-I/O level required by this tile's 2.7-3.6 V rail (TMF8806 datasheet §6.7). It is NOT an I2C-address strap (the address is fixed at 0x41, changed only via command 0x49). Because the strap fixes GPIO0 high, runtime GPIO0 output modes (object-detect / VCSEL-sync, command 0x0F) are not exposed — driving the pad would fight the pull-up and risk changing the I/O level. GPIO1 is not routed to a pad.

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

Constants

TILE_SENSE_TOF_VERSION_MAJOR1
TILE_SENSE_TOF_VERSION_MINOR3
TILE_SENSE_TOF_VERSION_PATCH0
TMF8806_I2C_ADDR0x41Fixed 7-bit I2C address
TMF8806_DEVICE_ID0x09Expected ID value (bits 5:0 only)
TMF8806_ID_MASK0x3FMask for valid ID bits
TMF8806_ENABLE_PON0x01Power-on bit
TMF8806_ENABLE_CPU_READY0x41CPU ready + PON
TMF8806_ENABLE_CPU_RESET0x80CPU reset bit
TMF8806_APPID_BOOTLOADER0x80Bootloader is running
TMF8806_APPID_APP00xC0Measurement application running
TMF8806_CMD_MEASURE0x02Start measurement
TMF8806_CMD_FACTORY_CAL0x0ARun factory calibration
TMF8806_CMD_STOP0xFFStop measurement
TMF8806_CMD_SERIAL0x47Read serial number
TMF8806_FACTORY_CAL_KITERS0xA000
TMF8806_INT_RESULT0x01Result interrupt flag
TMF8806_INT_HISTOGRAM0x02Histogram interrupt flag
TMF8806_CONTENTS_RESULT0x55Result data available
TMF8806_CONTENTS_CALIB0x0ACalibration data available
TMF8806_CONTENTS_SERIAL0x47Serial number available
TMF8806_CALIB_DATA_LEN14Factory calibration data length
TMF8806_STATE_DATA_LEN11Algorithm state data length
TMF8806_BOOT_TIMEOUT_MS500Maximum boot sequence wait
TMF8806_CMD_TIMEOUT_MS1000Maximum command completion wait
TMF8806_POLL_INTERVAL_MS2Polling interval during boot
SENSE_TOF_PRESENCE_RELIABILITY_MIN32
SENSE_TOF_WAIT_POLL_INTERVAL_MS10