BERGSONNE

Sense.I.6P6

Complete driver for the Sense.I.6P6 tile (ICM-42686-P). Supports I2C, I3C (Core.ST.H5) and SPI bus access via tiles_pal_t.

Supports I2C, I3C (Core.ST.H5) and SPI bus access via tiles_pal_t.

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.

SettingTierValuesDefaultFunction
Accel rangebasic±32 g, ±16 g, ±8 g, ±4 g, ±2 g±8 gset_accel_range(range)
Gyro rangebasic±4000 deg/s, ±2000 deg/s, ±1000 deg/s, ±500 deg/s, ±250 deg/s, ±125 deg/s, ±62.5 deg/s, ±31.25 deg/s±1000 deg/sset_gyro_range(range)
Accel data ratebasic32 kHz, 16 kHz, 8 kHz, 4 kHz, 2 kHz, 1 kHz, 200 Hz, 100 Hz, 50 Hz, 25 Hz, 12.5 Hz, 6.25 Hz (accel LP only), 3.125 Hz (accel LP only), 1.5625 Hz (accel LP only), 500 Hz100 Hzset_accel_odr(odr)
Gyro data ratebasic32 kHz, 16 kHz, 8 kHz, 4 kHz, 2 kHz, 1 kHz, 200 Hz, 100 Hz, 50 Hz, 25 Hz, 12.5 Hz, 500 Hz100 Hzset_gyro_odr(odr)
Motion thresholdbasic1 to 32000set where usedis_moving(threshold_mg)
Accel power modeadvancedPowered off, Accel only: duty-cycled, Low-noise (full performance)Low-noise (full performance)set_power_mode(accel)
Gyro power modeadvancedPowered off, Gyro only: drive on, no output, Low-noise (full performance)Low-noise (full performance)set_power_mode(gyro)
Accel filter bandwidthadvancedODR/2 (Nyquist), max(400 Hz, ODR)/4 (default), max(400 Hz, ODR)/5, max(400 Hz, ODR)/8, max(400 Hz, ODR)/10, max(400 Hz, ODR)/16, max(400 Hz, ODR)/20, max(400 Hz, ODR)/40 (Studio shows the resulting value in Hz)max(400 Hz, ODR)/4 (default)set_filter_bw(accel_bw)
Gyro filter bandwidthadvancedODR/2 (Nyquist), max(400 Hz, ODR)/4 (default), max(400 Hz, ODR)/5, max(400 Hz, ODR)/8, max(400 Hz, ODR)/10, max(400 Hz, ODR)/16, max(400 Hz, ODR)/20, max(400 Hz, ODR)/40 (Studio shows the resulting value in Hz)max(400 Hz, ODR)/4 (default)set_filter_bw(gyro_bw)
Accel filter orderadvanced1st order, 2nd order, 3rd order2nd orderset_filter_order(accel_order)
Gyro filter orderadvanced1st order, 2nd order, 3rd order2nd orderset_filter_order(gyro_order)
Temperature filteradvanced4000 Hz cutoff, 170 Hz cutoff, 82 Hz cutoff, 40 Hz cutoff, 20 Hz cutoff, 10 Hz cutoff, 5 Hz cutoff4000 Hz cutoffset_temp_filter(bw)
Temperature sensoradvancedon / offonset_temp_enabled(enabled)
Tap wait timeoutadvanced1 to 60000 msset where usedwait_for_tap(timeout_ms)
Motion wait timeoutadvanced1 to 60000 msset where usedwait_for_motion(timeout_ms)
FIFO watermarkadvanced1 to 4095set where usedfifo_set_watermark(records)
Wake threshold Xadvanced0 to 1000set where usedwom_config(x_mg)
Wake threshold Yadvanced0 to 1000set where usedwom_config(y_mg)
Wake threshold Zadvanced0 to 1000set where usedwom_config(z_mg)
Wake compareadvancedCompare against first sample, Compare against previous sampleCompare against previous samplewom_config(mode)
Significant motionadvancedDisabled, 1 second WOM window, 3 second WOM windowDisabledsmd_config(mode)
Pedometer rateadvanced25 Hz, 50 Hzset where usedpedometer_enable(dmp_odr)
Tilt delayadvanced0 to 6 sset where usedenable_tilt(wait_seconds)

Rules Studio enforces

  • Below 12.5 Hz the accelerometer only runs in low-power mode. Switch the accel power mode to low-power first.
  • In low-power mode the accelerometer tops out at 500 Hz. Switch the accel power mode to low-noise for faster rates.
  • In low-power mode the accel filter averages instead of low-passing: only the /4 setting (1x averaging) and the /20 setting (16x averaging) are valid.
  • A program may not read or stream faster than the data rate set here.

Examples

Quick start — I2C (polling)

  tile_t imu;
  tile_sense_i_6p6_init(core_tiles_pal(&core_i2c3), 0, &imu, NULL);
  int16_t accel[3], gyro[3];
  tile_sense_i_6p6_get_raw_accels(&imu, accel);
  tile_sense_i_6p6_get_raw_gyros(&imu, gyro);

Quick start — I3C (Core.ST.H5)

  tile_t imu;
  tile_sense_i_6p6_init(core_tiles_pal(&core_i3c1), 0, &imu, NULL);

Quick start — SPI

  tile_t imu;
  tile_sense_i_6p6_init(core_tiles_pal(&core_spi1), 0, &imu, NULL);
  int16_t accel[3];
  tile_sense_i_6p6_get_raw_accels(&imu, accel);

Quick start — interrupt-driven with callback

  void on_data(tile_t *t, uint8_t events, void *ctx) {
      int16_t buf[7];
      tile_sense_i_6p6_get_raw_all(t, buf);
  }
  sense_i_6p6_cfg_t cfg = {
      .on_event = on_data,
      .int1_pin = 9,  // Core pad connected to INT1
  };
  tile_sense_i_6p6_init(core_tiles_pal(&core_i2c3), 0, &imu, &cfg);
  tile_sense_i_6p6_int1_data_ready(&imu, 1);
  while (1) { tile_sense_i_6p6_process(&imu); }

API reference

Initialization

tile_sense_i_6p6_find

uint8_t tile_sense_i_6p6_find(tiles_pal_t *hal, uint8_t instance)

Check if a Sense.I.6P6 is present on the bus (address probe only).

tile_sense_i_6p6_init

void tile_sense_i_6p6_init(tiles_pal_t *hal, uint8_t instance, tile_t *tile, const sense_i_6p6_cfg_t *cfg)

Performs soft reset, verifies WHO_AM_I, configures sensor ranges and ODR. Pass cfg=NULL for defaults (±8g, ±1000dps, 100Hz, polled). Applies the datasheet's per-bus driver settings (DS-000639 §12.3): on I2C it turns the chip's I3C slave off (INTF_CONFIG6 SDR/DDR = 0, which brings back its I2C glitch filter) and sets both slew rates to 1, retrying until they read back. If they never stick the tile still gets configured, but its state is TILE_STATE_ERROR and on_error is called. On I3C it sets the SDA slew to 3 (4-12 ns); on SPI, SPI_SLEW_RATE 5.

  • Blocks for ~12 ms (reset). Call once at startup.

Lifecycle

tile_sense_i_6p6_sleep

Studio
void tile_sense_i_6p6_sleep(tile_t *tile)

Enter sleep mode (accel + gyro off). ~7.5 µA.

tile_sense_i_6p6_wake

Studio
void tile_sense_i_6p6_wake(tile_t *tile)

Wake from sleep, restore low-noise mode. Range/ODR preserved.

tile_sense_i_6p6_reset

Studio
void tile_sense_i_6p6_reset(tile_t *tile)

Software reset. Blocks ~2 ms. Must call init() again after.

Runtime

tile_sense_i_6p6_set_accel_range

Studio
void tile_sense_i_6p6_set_accel_range(tile_t *tile, sense_i_6p6_accel_range_t range)

Set accelerometer full-scale range.

range
Full-scale range (sense_i_6p6_accel_range_t).

tile_sense_i_6p6_set_gyro_range

Studio
void tile_sense_i_6p6_set_gyro_range(tile_t *tile, sense_i_6p6_gyro_range_t range)

Set gyroscope full-scale range.

range
Full-scale range (sense_i_6p6_gyro_range_t).

tile_sense_i_6p6_set_accel_odr

Studio
void tile_sense_i_6p6_set_accel_odr(tile_t *tile, sense_i_6p6_odr_t odr)

Set accelerometer output data rate.

odr
Output data rate (sense_i_6p6_odr_t).

tile_sense_i_6p6_set_gyro_odr

Studio
void tile_sense_i_6p6_set_gyro_odr(tile_t *tile, sense_i_6p6_odr_t odr)

Set gyroscope output data rate.

odr
Output data rate (sense_i_6p6_odr_t).

tile_sense_i_6p6_set_power_mode

Studio
void tile_sense_i_6p6_set_power_mode(tile_t *tile, sense_i_6p6_power_mode_t accel, sense_i_6p6_power_mode_t gyro)

Set power mode independently for accel and gyro.

accel
Accel power mode (off, low-power or low-noise).
gyro
Gyro power mode (off, standby or low-noise).
  • Wait 200 µs after changing mode before accessing other registers.

tile_sense_i_6p6_data_ready

Studio
uint8_t tile_sense_i_6p6_data_ready(tile_t *tile)

Check if new sensor data is available.

tile_sense_i_6p6_get_raw_accels

Studio
void tile_sense_i_6p6_get_raw_accels(tile_t *tile, int16_t *buffer)

Read raw accelerometer [X, Y, Z]. Convert: g = raw / sensitivity.

buffer
Output: 3 raw accel counts [X, Y, Z].

tile_sense_i_6p6_get_raw_gyros

Studio
void tile_sense_i_6p6_get_raw_gyros(tile_t *tile, int16_t *buffer)

Read raw gyroscope [X, Y, Z]. Convert: dps = raw / sensitivity.

buffer
Output: 3 raw gyro counts [X, Y, Z].

tile_sense_i_6p6_get_raw_6dof

Studio
void tile_sense_i_6p6_get_raw_6dof(tile_t *tile, int16_t *buffer)

Burst read accel + gyro [AX, AY, AZ, GX, GY, GZ]. One transaction.

buffer
Output: 6 raw counts [AX, AY, AZ, GX, GY, GZ].

tile_sense_i_6p6_get_temperature

Studio
int16_t tile_sense_i_6p6_get_temperature(tile_t *tile)

Read temperature. Convert: degC = raw / 132.48 + 25.0

tile_sense_i_6p6_get_raw_all

Studio
void tile_sense_i_6p6_get_raw_all(tile_t *tile, int16_t *buffer)

Read all 7 channels [Temp, AX, AY, AZ, GX, GY, GZ] in one burst.

buffer
Output: 7 raw counts [Temp, AX, AY, AZ, GX, GY, GZ].

tile_sense_i_6p6_is_face_up

Studio
uint8_t tile_sense_i_6p6_is_face_up(tile_t *tile)

Reads the accelerometer once and returns 1 when Z is within ±200 mg of +1 g and X/Y are within ±300 mg of 0. Uses the current ACCEL_CONFIG0 full-scale range to compute thresholds at runtime, so the helper stays correct after `set_accel_range`. Integer math only.

Returns 1 if face-up, 0 otherwise.

tile_sense_i_6p6_is_face_down

Studio
uint8_t tile_sense_i_6p6_is_face_down(tile_t *tile)

Mirror of `is_face_up` with an inverted Z target. Same ±200 mg / ±300 mg tolerance bands; same range-aware thresholding.

Returns 1 if face-down, 0 otherwise.

tile_sense_i_6p6_is_moving

Studio
uint8_t tile_sense_i_6p6_is_moving(tile_t *tile, uint16_t threshold_mg)

Reads the accelerometer, computes the squared magnitude in raw counts, and compares against the squared 1-g + threshold band. Squared-form keeps the math integer (no sqrt). Threshold is symmetric around 1 g so the helper triggers on both lift and drop. Range-aware.

threshold_mg
[1..32000] Deviation threshold in milli-g (typical: 50–200).

Returns 1 if moving, 0 otherwise.

tile_sense_i_6p6_read_tilt_centi_degrees_flat

Studio
uint8_t tile_sense_i_6p6_read_tilt_centi_degrees_flat(tile_t *tile, uint8_t axis, int32_t *out_centi_deg)

Flat-output variant of read_tilt_centi_degrees(): same computation, but the angle is written through an int32_t so Studio's 32-bit out-scalar locals receive it without a width mismatch.

axis
[0..2] 0 = X, 1 = Y, 2 = Z.
out_centi_deg
Output: elevation of the axis in 0.01° (−9000..+9000).

Returns 1 on success, 0 on bad axis or zero vector.

Events

tile_sense_i_6p6_process

Studio
void tile_sense_i_6p6_process(tile_t *tile)

Reads INT_STATUS, INT_STATUS2 and INT_STATUS3, composes the event word (SENSE_I_6P6_EV_*) and fires the callback when it is non-zero. In interrupt mode: returns immediately if no INT1 interrupt fired. In polled mode: reads the three registers every call. All three registers clear on read, so process() consumes the WOM, SMD, step, tilt and tap flags. Don't mix it with get_int_status2(), get_int_status3(), wait_for_tap() or wait_for_motion(): whichever reads first takes the flag.

tile_sense_i_6p6_on_event

Studio
void tile_sense_i_6p6_on_event(tile_t *tile, sense_i_6p6_event_cb_t cb, void *ctx)

Register or change the event callback.

cb
Callback to fire on interrupt events. NULL to clear.
ctx
Opaque user pointer passed to the callback.

Config

tile_sense_i_6p6_set_filter_bw

Studio
void tile_sense_i_6p6_set_filter_bw(tile_t *tile, sense_i_6p6_filter_bw_t accel_bw, sense_i_6p6_filter_bw_t gyro_bw)

Set UI filter bandwidth for both accel and gyro.

accel_bw
Accel UI filter bandwidth.
gyro_bw
Gyro UI filter bandwidth.

tile_sense_i_6p6_set_filter_order

Studio
void tile_sense_i_6p6_set_filter_order(tile_t *tile, sense_i_6p6_filter_order_t accel_order, sense_i_6p6_filter_order_t gyro_order)

Set UI filter order for accel and gyro (1st, 2nd, or 3rd).

accel_order
Accel UI filter order.
gyro_order
Gyro UI filter order.

tile_sense_i_6p6_set_temp_filter

Studio
void tile_sense_i_6p6_set_temp_filter(tile_t *tile, sense_i_6p6_temp_filter_t bw)

Set temperature sensor filter bandwidth.

bw
Temperature filter bandwidth.

tile_sense_i_6p6_set_temp_enabled

Studio
void tile_sense_i_6p6_set_temp_enabled(tile_t *tile, uint8_t enabled)

Enable or disable the temperature sensor.

enabled
[0..1] 1 = on, 0 = off.

FIFO

tile_sense_i_6p6_fifo_config

Studio
void tile_sense_i_6p6_fifo_config(tile_t *tile, sense_i_6p6_fifo_mode_t mode, uint8_t accel, uint8_t gyro, uint8_t temp, uint8_t hires)

Accel and gyro are enabled together: if either is requested, both go in, so every packet is the 16-byte accel + gyro + temp + timestamp format that fifo_read_packet() parses (an accel-only or gyro-only stream would be 8-byte packets, DS-000639 §6.4). Both 0 stops FIFO writes.

mode
FIFO operating mode (bypass/stream/stop-on-full)
accel
Include accel data in FIFO packets
gyro
Include gyro data in FIFO packets
temp
Include temperature in FIFO packets
hires
Reserved, ignored. 20-bit packets are not supported (see the "FIFO 20-bit hi-res mode" gap); FIFO_HIRES_EN stays 0.

tile_sense_i_6p6_fifo_set_watermark

Studio
void tile_sense_i_6p6_fifo_set_watermark(tile_t *tile, uint16_t records)

Set the FIFO watermark threshold in records (1–4095).

records
[1..4095] Records in the FIFO that raise the watermark interrupt.

tile_sense_i_6p6_fifo_flush

Studio
void tile_sense_i_6p6_fifo_flush(tile_t *tile)

Flush the FIFO (discard all data).

tile_sense_i_6p6_fifo_read_packet_flat

Studio
void tile_sense_i_6p6_fifo_read_packet_flat(tile_t *tile, int32_t *out)

Drops the struct in favor of a positional int[8] array — the DSL doesn't have a struct ABI yet, so the per-field outputs come back indexed. Layout: out[0..2] = accel x,y,z (raw int16 widened to int32) out[3..5] = gyro x,y,z (raw int16 widened to int32) out[6] = temp (raw int8 widened to int32) out[7] = timestamp (raw uint16) Drops the success bool — call fifo_count() first to know whether there's data. On an empty FIFO, the slots are left untouched.

out
Output buffer (8 int32_t slots).

tile_sense_i_6p6_fifo_read_packets_flat

Studio
uint16_t tile_sense_i_6p6_fifo_read_packets_flat(tile_t *tile, int32_t *out, uint16_t cap_ints)

Drains up to N packets from the FIFO into the caller's int32 buffer, 8 ints per packet (same layout as fifo_read_packet_flat). Returns the number of *packets* read (not ints), so callers can iterate with `for i in 0..n { let ax = buf[i*8 + 0]; ... }`. The caller's array length is the int-cap (N packets × 8 ints), not the packet count — `cap_ints / 8` packets are attempted. Mirrors the cap-mode array-OUT convention (`cap_param`) other FIFO drivers use.

out
Output buffer; must be sized N × 8 ints.
cap_ints
Buffer capacity in int slots (= packets × 8).

Returns Number of packets actually drained from the FIFO.

tile_sense_i_6p6_fifo_count

Studio
uint16_t tile_sense_i_6p6_fifo_count(tile_t *tile)

init() sets INTF_CONFIG0.FIFO_COUNT_REC, so FIFO_COUNT is in records.

tile_sense_i_6p6_fifo_lost_count

Studio
uint16_t tile_sense_i_6p6_fifo_lost_count(tile_t *tile)

Get the number of lost FIFO packets since last check.

Interrupts

tile_sense_i_6p6_int1_config

Studio
void tile_sense_i_6p6_int1_config(tile_t *tile, uint8_t config)

Configure INT1 pin behavior.

config
OR'd flags: ACTIVE_HIGH|PUSH_PULL|LATCHED etc.

tile_sense_i_6p6_int1_data_ready

Studio
void tile_sense_i_6p6_int1_data_ready(tile_t *tile, uint8_t enabled)

Route data-ready interrupt to INT1.

enabled
1 to enable, 0 to disable

tile_sense_i_6p6_int1_fifo_ths

Studio
void tile_sense_i_6p6_int1_fifo_ths(tile_t *tile, uint8_t enabled)

Route FIFO watermark interrupt to INT1.

enabled
1 to enable, 0 to disable

tile_sense_i_6p6_int1_wom

Studio
void tile_sense_i_6p6_int1_wom(tile_t *tile, uint8_t enabled)

Route WOM (wake-on-motion) interrupt to INT1.

enabled
1 to enable, 0 to disable

tile_sense_i_6p6_int2_config

Studio
void tile_sense_i_6p6_int2_config(tile_t *tile, uint8_t config)

Mirrors int1_config for the chip's second interrupt pin (tile pad 8). INT_CONFIG bits [5:3] hold INT2's polarity / drive / mode bits.

config
OR'd flags: ACTIVE_HIGH|PUSH_PULL|LATCHED etc. (same layout as int1_config; the driver shifts the bits into the INT2 positions internally).

tile_sense_i_6p6_int2_data_ready

Studio
void tile_sense_i_6p6_int2_data_ready(tile_t *tile, uint8_t enabled)

Route data-ready interrupt to INT2.

enabled
1 to enable, 0 to disable

tile_sense_i_6p6_int2_fifo_ths

Studio
void tile_sense_i_6p6_int2_fifo_ths(tile_t *tile, uint8_t enabled)

Route FIFO watermark interrupt to INT2.

enabled
1 to enable, 0 to disable

tile_sense_i_6p6_int2_wom

Studio
void tile_sense_i_6p6_int2_wom(tile_t *tile, uint8_t enabled)

Route WOM (wake-on-motion) interrupt to INT2.

enabled
1 to enable, 0 to disable

tile_sense_i_6p6_set_int_pulse_duration

Studio
void tile_sense_i_6p6_set_int_pulse_duration(tile_t *tile, sense_i_6p6_int_pulse_t pulse)

Applies to both INT1 and INT2 (it's a chip-wide setting in INT_CONFIG1 bit 6). Only affects pulse-mode interrupts; in latched mode the line stays asserted until the status register is read.

pulse
Pulse-width selector

tile_sense_i_6p6_get_int_status

Studio
uint8_t tile_sense_i_6p6_get_int_status(tile_t *tile)

Read and clear INT_STATUS register.

tile_sense_i_6p6_get_int_status2

Studio
uint8_t tile_sense_i_6p6_get_int_status2(tile_t *tile)

Read and clear INT_STATUS2 (WOM/SMD flags).

tile_sense_i_6p6_get_int_status3

Studio
uint8_t tile_sense_i_6p6_get_int_status3(tile_t *tile)

Read and clear INT_STATUS3 (APEX: step/tilt/tap flags).

Wake on Motion

tile_sense_i_6p6_wait_for_motion

Studio
uint8_t tile_sense_i_6p6_wait_for_motion(tile_t *tile, uint32_t timeout_ms)

Polls INT_STATUS2 at ~1 ms cadence. WOM must be configured (thresholds + enable) first. Returns on any-axis WOM. The status read clears the latch.

timeout_ms
[1..60000] ms Max time to wait, in ms. Use 0 for a single-shot poll.

Returns 1 if motion was detected, 0 on timeout.

tile_sense_i_6p6_wom_config

Studio
void tile_sense_i_6p6_wom_config(tile_t *tile, uint16_t x_mg, uint16_t y_mg, uint16_t z_mg, sense_i_6p6_wom_mode_t mode)

Configure Wake-on-Motion thresholds.

x_mg
[0..1000] X-axis threshold in mg (resolution ~3.9 mg; values above ~996 mg clamp to the register maximum 255)
y_mg
[0..1000] Y-axis threshold in mg
z_mg
[0..1000] Z-axis threshold in mg
mode
Compare against initial or previous sample
  • Requires accel to be running (LN or LP mode).

tile_sense_i_6p6_wom_enable

Studio
void tile_sense_i_6p6_wom_enable(tile_t *tile)

Keeps the compare mode set by wom_config() and any SMD mode already set.

tile_sense_i_6p6_wom_disable

Studio
void tile_sense_i_6p6_wom_disable(tile_t *tile)

Thresholds are kept, so wom_enable() re-arms with the last config.

Motion Detection

tile_sense_i_6p6_smd_config

Studio
void tile_sense_i_6p6_smd_config(tile_t *tile, sense_i_6p6_smd_mode_t mode)

Configure and enable SMD. WOM thresholds must be set first.

mode
SMD mode (sense_i_6p6_smd_mode_t); disabled turns it off.

Pedometer

tile_sense_i_6p6_pedometer_enable

Studio
void tile_sense_i_6p6_pedometer_enable(tile_t *tile, sense_i_6p6_dmp_odr_t dmp_odr)

Requires accel at ≥25 Hz. Initializes the DMP if not already running.

dmp_odr
DMP processing rate (25 or 50 Hz)
  • APEX_CONFIG0.DMP_POWER_SAVE resets to 1 and the driver leaves it set. Per DS-000639 §8.2 the APEX features then run only after a WOM event (WOM must be enabled). Not yet bench-verified.

tile_sense_i_6p6_pedometer_disable

Studio
void tile_sense_i_6p6_pedometer_disable(tile_t *tile)

Disable the pedometer.

tile_sense_i_6p6_get_step_count

Studio
uint16_t tile_sense_i_6p6_get_step_count(tile_t *tile)

Read the step count.

Returns 16-bit step count (resets on power cycle or DMP reset)

tile_sense_i_6p6_get_step_cadence

Studio
uint8_t tile_sense_i_6p6_get_step_cadence(tile_t *tile)

Read the step cadence.

Returns Cadence in samples per step, u6.2 fixed point (divide by 4 for samples; DS-000639 §14.27). At 50 Hz ODR and 2 steps/s it reads 100 (25 samples). Steps per second = ODR × 4 / value.

tile_sense_i_6p6_get_activity

Studio
sense_i_6p6_activity_t tile_sense_i_6p6_get_activity(tile_t *tile)

Read the activity classification.

Returns 0=unknown, 1=walk, 2=run

Tilt Detection

tile_sense_i_6p6_tilt_enable

Studio
void tile_sense_i_6p6_tilt_enable(tile_t *tile, uint8_t wait_seconds)

Triggers when device tilts >35° for the configured wait time. Requires accel at ≥25 Hz. Initializes DMP if needed.

wait_seconds
[0..6] s Time the tilt must be sustained (0, 2, 4, or 6).
  • APEX_CONFIG0.DMP_POWER_SAVE resets to 1 and the driver leaves it set. Per DS-000639 §8.2 the APEX features then run only after a WOM event (WOM must be enabled). Not yet bench-verified.

tile_sense_i_6p6_tilt_disable

Studio
void tile_sense_i_6p6_tilt_disable(tile_t *tile)

Disable tilt detection.

Tap Detection

tile_sense_i_6p6_wait_for_tap

Studio
uint8_t tile_sense_i_6p6_wait_for_tap(tile_t *tile, uint32_t timeout_ms)

Polls INT_STATUS3 at ~1 ms cadence (delay_ms(1)). Tap detection must be enabled first via `tile_sense_i_6p6_tap_enable`. The status read is destructive (clear-on-read), so call `get_tap_result` immediately after a positive return to retrieve count/axis/direction.

timeout_ms
[1..60000] ms Max time to wait, in ms. Use 0 for a single-shot poll.

Returns 1 if a tap was detected, 0 on timeout.

tile_sense_i_6p6_tap_enable

Studio
void tile_sense_i_6p6_tap_enable(tile_t *tile)

Requires accel in LN mode at 200 Hz, 500 Hz, or 1 kHz. Initializes DMP if needed.

  • APEX_CONFIG0.DMP_POWER_SAVE resets to 1 and the driver leaves it set. Per DS-000639 §8.2 the APEX features then run only after a WOM event (WOM must be enabled). Not yet bench-verified.

tile_sense_i_6p6_tap_disable

Studio
void tile_sense_i_6p6_tap_disable(tile_t *tile)

Disable tap detection.

tile_sense_i_6p6_get_tap_result_flat

Studio
void tile_sense_i_6p6_get_tap_result_flat(tile_t *tile, int32_t *count, int32_t *axis, int32_t *direction, int32_t *timing)

Same data, four positional out-scalars instead of a struct. Useful for polling-style flows; event-driven flows already get these values via the `Sense.I.6P6.tap` event payload.

count
Output: 0 = none, 1 = single tap, 2 = double.
axis
Output: 0 = X, 1 = Y, 2 = Z.
direction
Output: 0 = positive, 1 = negative.
timing
Output: double-tap timing (chip-specific units).

Advanced

tile_sense_i_6p6_subsystem_reset

Studio
void tile_sense_i_6p6_subsystem_reset(tile_t *tile, sense_i_6p6_subsystem_t which)

Issues the relevant SIGNAL_PATH_RESET bits. Distinct from the driver's full `reset()` (which re-initialises the whole chip) and from `fifo_flush()` (which targets just the FIFO, also a subsystem reset but already exposed). - APEX: DMP_MEM_RESET_EN, 1 ms, then DMP_INIT_EN (DS-000639 §8.3/§14.33); blocks ~51 ms. Clears the step count. Use after reconfiguring pedometer / tilt / tap features. - TEMP: does nothing. SIGNAL_PATH_RESET has no temperature bit on this part; kept only for source compatibility.

which
Subsystem to reset

tile_sense_i_6p6_set_gyro_offset

Studio
void tile_sense_i_6p6_set_gyro_offset(tile_t *tile, int16_t x_dps16, int16_t y_dps16, int16_t z_dps16)

Set user-programmable gyro offset.

x_dps16
X offset in dps × 16 (12-bit signed, ±128 dps max, 0.0625 dps resolution)
y_dps16
Y offset in dps × 16
z_dps16
Z offset in dps × 16

tile_sense_i_6p6_set_accel_offset

Studio
void tile_sense_i_6p6_set_accel_offset(tile_t *tile, int16_t x_mg, int16_t y_mg, int16_t z_mg)

Set user-programmable accel offset.

x_mg
X offset in mg (12-bit signed, ±2000 mg max, 1 mg resolution)
y_mg
Y offset
z_mg
Z offset

tile_sense_i_6p6_self_test

Studio
uint8_t tile_sense_i_6p6_self_test(tile_t *tile, uint8_t *accel_pass, uint8_t *gyro_pass)

Runs the built-in self-test for both accel and gyro. Switches to ±4 g, ±250 dps, 1 kHz and low-noise for the test (~0.6 s), then restores the previous ranges, data rates and power mode. Returns 0 (both outputs 0) if the sensor stops reporting data-ready for 20 ms.

accel_pass
Output: 1 if accel self-test passed, 0 if failed (per-axis OR'd)
gyro_pass
Output: 1 if gyro self-test passed, 0 if failed

Returns 1 if both passed, 0 if either failed

tile_sense_i_6p6_read_reg

Studio
uint8_t tile_sense_i_6p6_read_reg(tile_t *tile, uint8_t bank, uint8_t reg)

Automatically switches to the specified bank and back to bank 0. For advanced/debug use.

bank
Bank index (0, 1, 2, or 4).
reg
Register address within the bank.

tile_sense_i_6p6_write_reg

Studio
void tile_sense_i_6p6_write_reg(tile_t *tile, uint8_t bank, uint8_t reg, uint8_t val)

Automatically switches to the specified bank and back to bank 0. For advanced/debug use.

bank
Bank index (0, 1, 2, or 4).
reg
Register address within the bank.
val
Byte to write.

Driver gaps · 6

Chip capabilities this driver doesn’t expose yet.

advancedExternal timing pins (FSYNC / CLKIN)Hardware-gated (not a driver gap). The ICM-42686-P can take a 31–50 kHz FSYNC input (TIMESTAMP_FSYNC_EN) for sample time-stamping and a ~32 kHz external CLKIN (RTC) for precise ODR. Neither pin is routed to a tile pad on Sense-I-6P6-a, so the capability simply isn't wired out — closing requires a tile hardware revision, not driver work.
nicheFIFO 20-bit hi-res modeDesign-gated. FIFO_HIRES_EN switches FIFO packets to 20-bit accel + 20-bit gyro (Packet 4 with 3-byte extensions) at higher sensitivity scale factors. Closing properly requires extending sense_i_6p6_fifo_packet_t to represent 20-bit fields and reworking the read_packet parser; toggling the bit alone breaks the existing 16-bit parsing path. Deferred to a future driver pass.
nicheI3C: HDR-DDR, IBI routing, StudioI3C SDR works on Core.ST.H5 (driver 1.4.0): core_tiles_pal(&core_i3c1) runs this driver unchanged at up to 12.4 MHz, with dynamic addressing, and in-band interrupts through core_i3c_ibi_enable() + ENEC. What is left: HDR-DDR (the chip has it; the H5 I3C peripheral is SDR-only, so it is hardware-gated on every Core); no driver call routes events to IBI (write INT_SOURCE8/9 in bank 4 with write_reg); and Studio cannot put a bus on I3C yet (config.json can: "i3c": true on the I2C bus).
advancedAPEX raise-to-wake / raise-to-sleepDriver-deferred (true driver gap — hardware supports it). The APEX engine detects raise-to-wake / raise-to-sleep gestures (RWR), routable to INT via INT_SOURCE6/7. The driver wraps pedometer / tilt / tap / WOM / SMD but not RWR; no hardware or framework blocker — closing is a driver pass.
advancedUI notch / anti-alias filter tuningDriver-deferred (true driver gap). set_filter_bw / set_filter_order expose the UI filter bandwidth and order, but not the notch-filter centre frequency / Q (Bank-1 GYRO_CFG_STATIC registers) for rejecting a specific vibration band.
nicheStandalone timestamp (TMSTVAL) readDriver-deferred (true driver gap). FIFO packets carry a 16-bit timestamp, but the chip's free-running timestamp counter (Bank-1 TMSTVAL0-2) isn't exposed as a direct read.

Events

data_ready
fifo_watermark
tilt
tap
wake_on_motion

Enums

sense_i_6p6_accel_range_t

Accelerometer full-scale range.

SENSE_I_6P6_ACCEL_32G
+/- 32g
SENSE_I_6P6_ACCEL_16G
+/- 16g
SENSE_I_6P6_ACCEL_8G
+/- 8g
SENSE_I_6P6_ACCEL_4G
+/- 4g
SENSE_I_6P6_ACCEL_2G
+/- 2g

sense_i_6p6_gyro_range_t

Gyroscope full-scale range.

SENSE_I_6P6_GYRO_4000DPS
+/- 4000 deg/s
SENSE_I_6P6_GYRO_2000DPS
+/- 2000 deg/s
SENSE_I_6P6_GYRO_1000DPS
+/- 1000 deg/s
SENSE_I_6P6_GYRO_500DPS
+/- 500 deg/s
SENSE_I_6P6_GYRO_250DPS
+/- 250 deg/s
SENSE_I_6P6_GYRO_125DPS
+/- 125 deg/s
SENSE_I_6P6_GYRO_62_5DPS
+/- 62.5 deg/s
SENSE_I_6P6_GYRO_31_25DPS
+/- 31.25 deg/s

sense_i_6p6_odr_t

Output data rate selection.

SENSE_I_6P6_ODR_32KHZ
32 kHz @studio value=32000
SENSE_I_6P6_ODR_16KHZ
16 kHz @studio value=16000
SENSE_I_6P6_ODR_8KHZ
8 kHz @studio value=8000
SENSE_I_6P6_ODR_4KHZ
4 kHz @studio value=4000
SENSE_I_6P6_ODR_2KHZ
2 kHz @studio value=2000
SENSE_I_6P6_ODR_1KHZ
1 kHz @studio value=1000
SENSE_I_6P6_ODR_200HZ
200 Hz @studio value=200
SENSE_I_6P6_ODR_100HZ
100 Hz @studio value=100
SENSE_I_6P6_ODR_50HZ
50 Hz @studio value=50
SENSE_I_6P6_ODR_25HZ
25 Hz @studio value=25
SENSE_I_6P6_ODR_12_5HZ
12.5 Hz @studio value=12.5
SENSE_I_6P6_ODR_6_25HZ
6.25 Hz (accel LP only) @studio value=6.25
SENSE_I_6P6_ODR_3_125HZ
3.125 Hz (accel LP only) @studio value=3.125
SENSE_I_6P6_ODR_1_5625HZ
1.5625 Hz (accel LP only) @studio value=1.5625
SENSE_I_6P6_ODR_500HZ
500 Hz @studio value=500

sense_i_6p6_power_mode_t

Power mode for accel/gyro independently.

SENSE_I_6P6_MODE_OFF
Powered off
SENSE_I_6P6_MODE_STANDBY
Gyro only: drive on, no output
SENSE_I_6P6_MODE_LP
Accel only: duty-cycled
SENSE_I_6P6_MODE_LN
Low-noise (full performance)

sense_i_6p6_filter_bw_t

UI filter bandwidth selection.

SENSE_I_6P6_FILT_BW_ODR_2
ODR/2 (Nyquist) @studio value=2
SENSE_I_6P6_FILT_BW_ODR_4
max(400 Hz, ODR)/4 (default) @studio value=4
SENSE_I_6P6_FILT_BW_ODR_5
max(400 Hz, ODR)/5 @studio value=5
SENSE_I_6P6_FILT_BW_ODR_8
max(400 Hz, ODR)/8 @studio value=8
SENSE_I_6P6_FILT_BW_ODR_10
max(400 Hz, ODR)/10 @studio value=10
SENSE_I_6P6_FILT_BW_ODR_16
max(400 Hz, ODR)/16 @studio value=16
SENSE_I_6P6_FILT_BW_ODR_20
max(400 Hz, ODR)/20 @studio value=20
SENSE_I_6P6_FILT_BW_ODR_40
max(400 Hz, ODR)/40 @studio value=40
SENSE_I_6P6_FILT_LP_1X_AVG
LP mode: 1× averaging (default)
SENSE_I_6P6_FILT_LP_16X_AVG
LP mode: 16× averaging

sense_i_6p6_filter_order_t

UI filter order.

SENSE_I_6P6_FILT_ORDER_1ST
1st order
SENSE_I_6P6_FILT_ORDER_2ND
2nd order
SENSE_I_6P6_FILT_ORDER_3RD
3rd order

sense_i_6p6_temp_filter_t

Temperature filter bandwidth.

SENSE_I_6P6_TEMP_FILT_4000HZ
4000 Hz cutoff @studio value=4000
SENSE_I_6P6_TEMP_FILT_170HZ
170 Hz cutoff @studio value=170
SENSE_I_6P6_TEMP_FILT_82HZ
82 Hz cutoff @studio value=82
SENSE_I_6P6_TEMP_FILT_40HZ
40 Hz cutoff @studio value=40
SENSE_I_6P6_TEMP_FILT_20HZ
20 Hz cutoff @studio value=20
SENSE_I_6P6_TEMP_FILT_10HZ
10 Hz cutoff @studio value=10
SENSE_I_6P6_TEMP_FILT_5HZ
5 Hz cutoff @studio value=5

sense_i_6p6_fifo_mode_t

FIFO mode.

SENSE_I_6P6_FIFO_BYPASS
FIFO disabled
SENSE_I_6P6_FIFO_STREAM
Stream mode (oldest data replaced)
SENSE_I_6P6_FIFO_STOP_ON_FULL
Stop on full

sense_i_6p6_dmp_odr_t

APEX DMP output data rate.

SENSE_I_6P6_DMP_ODR_25HZ
25 Hz
SENSE_I_6P6_DMP_ODR_50HZ
50 Hz

sense_i_6p6_wom_mode_t

WOM (Wake-on-Motion) compare mode.

SENSE_I_6P6_WOM_INITIAL
Compare against first sample
SENSE_I_6P6_WOM_PREVIOUS
Compare against previous sample

sense_i_6p6_smd_mode_t

SMD (Significant Motion Detection) mode.

SENSE_I_6P6_SMD_DISABLED
Disabled
SENSE_I_6P6_SMD_SHORT
1 second WOM window
SENSE_I_6P6_SMD_LONG
3 second WOM window

sense_i_6p6_int_config_t

Interrupt pin configuration.

SENSE_I_6P6_INT_ACTIVE_LOW
Active low
SENSE_I_6P6_INT_ACTIVE_HIGH
Active high
SENSE_I_6P6_INT_OPEN_DRAIN
Open drain
SENSE_I_6P6_INT_PUSH_PULL
Push-pull
SENSE_I_6P6_INT_PULSED
Pulsed
SENSE_I_6P6_INT_LATCHED
Latched

sense_i_6p6_activity_t

APEX activity classification.

SENSE_I_6P6_ACTIVITY_UNKNOWN
Unknown
SENSE_I_6P6_ACTIVITY_WALK
Walking
SENSE_I_6P6_ACTIVITY_RUN
Running

sense_i_6p6_int_pulse_t

Pulse-width selector for INT pin pulse mode.

SENSE_I_6P6_INT_PULSE_100US
100 µs pulse (default)
SENSE_I_6P6_INT_PULSE_8US
8 µs pulse — for fast hosts

sense_i_6p6_subsystem_t

Subsystem selector for scoped resets.

SENSE_I_6P6_RESET_APEX
APEX (DMP) memory + state
SENSE_I_6P6_RESET_TEMP
No-op: the ICM-42686-P has no temperature-path reset

Constants

TILE_SENSE_I_6P6_VERSION_MAJOR1
TILE_SENSE_I_6P6_VERSION_MINOR5
TILE_SENSE_I_6P6_VERSION_PATCH0
ICM42686P_I2C_ADDR_DEFAULT0x69
ICM42686P_I2C_ADDR_ALT0x68
ICM42686P_B1_SENSOR_CONFIG00x03
ICM42686P_B1_GYRO_CFG_STATIC20x0B
ICM42686P_B1_GYRO_CFG_STATIC30x0C
ICM42686P_B1_GYRO_CFG_STATIC40x0D
ICM42686P_B1_GYRO_CFG_STATIC50x0E
ICM42686P_B1_GYRO_NF_COSWZ_X0x0F
ICM42686P_B1_GYRO_NF_COSWZ_Y0x10
ICM42686P_B1_GYRO_NF_COSWZ_Z0x11
ICM42686P_B1_GYRO_CFG_STATIC90x12
ICM42686P_B1_GYRO_CFG_STATIC100x13
ICM42686P_B1_XG_ST_DATA0x5F
ICM42686P_B1_YG_ST_DATA0x60
ICM42686P_B1_ZG_ST_DATA0x61
ICM42686P_B1_TMSTVAL00x62
ICM42686P_B1_TMSTVAL10x63
ICM42686P_B1_TMSTVAL20x64
ICM42686P_B1_INTF_CONFIG40x7A
ICM42686P_B1_INTF_CONFIG50x7B
ICM42686P_B1_INTF_CONFIG60x7C
ICM42686P_INTF_CONFIG6_I2C0x5CINTF_CONFIG6 on I2C (DS-000639 §12.3 "I2C driver setting"): reset value 0x5F with I3C_DDR_EN (bit 1) and I3C_SDR_EN (bit 0) cleared
ICM42686P_DRIVE_CONFIG_I2C0x09DRIVE_CONFIG on I2C (§12.3): I2C_SLEW_RATE (bits 5:3) = 1, SPI_SLEW_RATE (bits 2:0) = 1
ICM42686P_B2_ACCEL_CFG_STATIC20x03
ICM42686P_B2_ACCEL_CFG_STATIC30x04
ICM42686P_B2_ACCEL_CFG_STATIC40x05
ICM42686P_B2_XA_ST_DATA0x3B
ICM42686P_B2_YA_ST_DATA0x3C
ICM42686P_B2_ZA_ST_DATA0x3D
ICM42686P_B4_APEX_CONFIG10x40
ICM42686P_B4_APEX_CONFIG20x41
ICM42686P_B4_APEX_CONFIG30x42
ICM42686P_B4_APEX_CONFIG40x43
ICM42686P_B4_APEX_CONFIG70x46
ICM42686P_B4_APEX_CONFIG80x47
ICM42686P_B4_APEX_CONFIG90x48
ICM42686P_B4_WOM_X_THR0x4A
ICM42686P_B4_WOM_Y_THR0x4B
ICM42686P_B4_WOM_Z_THR0x4C
ICM42686P_B4_INT_SOURCE60x4D
ICM42686P_B4_INT_SOURCE70x4E
ICM42686P_B4_INT_SOURCE80x4F
ICM42686P_B4_INT_SOURCE90x50
ICM42686P_B4_INT_SOURCE100x51
ICM42686P_B4_OFFSET_USER00x77
ICM42686P_B4_OFFSET_USER10x78
ICM42686P_B4_OFFSET_USER20x79
ICM42686P_B4_OFFSET_USER30x7A
ICM42686P_B4_OFFSET_USER40x7B
ICM42686P_B4_OFFSET_USER50x7C
ICM42686P_B4_OFFSET_USER60x7D
ICM42686P_B4_OFFSET_USER70x7E
ICM42686P_B4_OFFSET_USER80x7F
ICM42686P_WHOAMI_DEFAULT0x44