BERGSONNE

Drive.H

LRA/ERM haptic driver for the Drive.H tile (rev a).

Embeds the TI DRV2605 (DEVICE_ID 3 — the non-L part), a haptic driver for LRA (Linear Resonant Actuator) and ERM actuators with a built-in waveform library of 123 effects. The actuator is external, connected via the tile's OUT+ / OUT- pads; V_MOTOR accepts 2.5-5.5 V.

The chip regulates output amplitude itself: the supply rail only sets headroom. Full-scale drive level comes from RATED_VOLTAGE / OD_CLAMP (see tile_drive_h_set_actuator_voltage()), NOT from the voltage applied to V_MOTOR.

Datasheet

Examples

Quick start

  #include "core_tiles.h"

  tile_t haptic;
  tile_drive_h_init(core_tiles_pal(&core_i2c1), 0, &haptic, NULL);
  if (tile_is_ready(&haptic)) {
      tile_drive_h_play(&haptic, 1, 1);  // play effect #1 once
  }

API reference

Initialization

tile_drive_h_find

uint8_t tile_drive_h_find(tiles_pal_t* hal, uint8_t instance)

Check whether a DRV2605L is present on the I2C bus.

hal
Platform HAL handle
instance
Instance index (0 = default, see mapping table)

Returns 1 if device ACKs, 0 otherwise

tile_drive_h_init

void tile_drive_h_init(tiles_pal_t* hal, uint8_t instance, tile_t* tile, const drive_h_cfg_t *cfg)

Verifies the device ID, exits standby, and configures the actuator drive mode. Pass cfg=NULL for defaults (LRA closed-loop, library 6, 1.8 Vrms drive levels).

hal
Platform HAL handle
instance
Instance index (0 = default, see mapping table)
tile
Pointer to tile handle (populated by this function)
cfg
Optional config, or NULL for defaults
  • Blocks for ~500 ms during init. Call once at startup.

Runtime

tile_drive_h_play

Studio
void tile_drive_h_play(tile_t* tile, uint8_t index, uint8_t repeats)

Loads the effect index into sequence slot 0, terminates the sequence, and triggers playback. For repeats > 1, re-triggers with a 200ms gap between plays.

index
[1..123] Library effect index (see datasheet).
repeats
[1..20] Number of times to play (1 = once).

tile_drive_h_play_sequence

Studio
void tile_drive_h_play_sequence(tile_t* tile, const uint8_t *effects, uint8_t count)

Loads effects into the waveform sequencer registers (0x04-0x0B), terminates the sequence, and triggers playback. Returns immediately — use tile_drive_h_is_playing() to poll for completion. DSL pads short sequences with 0 (DRV2605 effect 0 is "stop"), so a 3-effect sequence written as `[5, 10, 15, 0, 0, 0, 0, 0]` plays effects 5/10/15 then halts.

tile
Pointer to tile handle
effects
Array of effect indices (1-123, 0 = stop)
count
Number of effects (1-8)

tile_drive_h_load_sequence

Studio
void tile_drive_h_load_sequence(tile_t* tile, const uint8_t *effects, uint8_t count)

Identical to tile_drive_h_play_sequence() but does NOT assert the GO bit. Use this to pre-load effects before switching to external trigger mode (edge or level).

tile
Pointer to tile handle
effects
Array of effect indices (1-123, 0 = stop)
count
Number of effects (1-8)

tile_drive_h_set_trigger

Studio
void tile_drive_h_set_trigger(tile_t* tile, uint8_t mode)

Selects how the waveform sequencer is triggered: - DRIVE_H_TRIG_INTERNAL (default): I2C GO bit, used by play() and play_sequence(). - DRIVE_H_TRIG_EDGE: a rising edge on the IN/TRIG pin sets GO. A second rising edge while playing cancels. Pre-load effects with tile_drive_h_load_sequence() before entering this mode. - DRIVE_H_TRIG_LEVEL: GO follows the IN/TRIG pin level. High = playing, low = idle. Falling edge cancels. DRIVE_H_TRIG_LEVEL

tile
Pointer to tile handle
mode
One of DRIVE_H_TRIG_INTERNAL, DRIVE_H_TRIG_EDGE,

tile_drive_h_is_playing

Studio
uint8_t tile_drive_h_is_playing(tile_t* tile)

Reads the GO bit in register 0x0C. The GO bit remains high until playback completes.

Returns 1 if playing, 0 if idle

tile_drive_h_stop

Studio
void tile_drive_h_stop(tile_t* tile)

Stop any currently playing effect.

tile_drive_h_rtp_start

Studio
void tile_drive_h_rtp_start(tile_t* tile)

Sets DRV2605L MODE register to 0x05 (RTP). The chip drives the LRA at its resonant frequency with amplitude controlled by tile_drive_h_rtp_write(). Call tile_drive_h_rtp_stop() to return to internal trigger mode.

tile_drive_h_rtp_write

Studio
void tile_drive_h_rtp_write(tile_t* tile, uint8_t amplitude)

Write an amplitude value in RTP mode.

amplitude
[0..127] Amplitude (0 = off, 127 = max).

tile_drive_h_rtp_stop

Studio
void tile_drive_h_rtp_stop(tile_t* tile)

Exit RTP mode and return to internal trigger mode.

tile_drive_h_get_status

Studio
uint8_t tile_drive_h_get_status(tile_t* tile)

Contains DEVICE_ID[7:5], DIAG_RESULT[3], FB_STS[2], OVER_TEMP[1], OC_DETECT[0]. Status bits clear on read.

tile
Pointer to tile handle

Returns Raw status byte

tile_drive_h_diagnose

Studio
uint8_t tile_drive_h_diagnose(tile_t* tile)

Enters diagnostic mode (MODE=6), triggers GO, and polls for completion. The DRV2605L checks whether the actuator is present, open, or shorted.

Returns 1 if actuator passed diagnostics, 0 if fault detected

tile_drive_h_calibrate

Studio
uint8_t tile_drive_h_calibrate(tile_t* tile)

Enters calibration mode (MODE=7) with datasheet-recommended parameters, triggers GO, and polls for completion. On success, the DRV2605L stores optimized A_CAL_COMP and A_CAL_BEMF values that improve playback fidelity.

Returns 1 if calibration passed, 0 if it failed to converge

tile_drive_h_get_vbat_mv

Studio
uint16_t tile_drive_h_get_vbat_mv(tile_t* tile)

Reads the VBAT register (0x21). The reading is only valid while the device is actively driving a waveform (RTP, library playback, etc.).

Returns Battery voltage in mV (e.g. 3300 = 3.3 V), 0 if idle

tile_drive_h_get_resonance_hz

Studio
uint16_t tile_drive_h_get_resonance_hz(tile_t* tile)

Reads the LRA_PERIOD register (0x22). The reading is only valid while the device is actively driving a waveform and must not be polled during braking.

Returns Resonant frequency in Hz (e.g. 235), 0 if unavailable

tile_drive_h_standby

Studio
void tile_drive_h_standby(tile_t* tile)

Sets the STANDBY bit in the MODE register. The device retains register values and can be woken quickly with tile_drive_h_wake().

tile_drive_h_wake

Studio
void tile_drive_h_wake(tile_t* tile)

Clears the STANDBY bit in the MODE register. The device returns to the active state, ready for playback.

tile_drive_h_play_click

Studio
void tile_drive_h_play_click(tile_t* tile)

Plays ROM library effect 1 ("Strong Click — 100%") once. Returns immediately; the chip drives the click after the call returns. Use @ref tile_drive_h_is_playing to poll for completion.

tile
Initialised tile handle

tile_drive_h_play_double_tap

Studio
void tile_drive_h_play_double_tap(tile_t* tile)

Loads the sequencer with two strong-click effects (ROM library effect 10 — "Double Click — 100%") and triggers playback. The chip handles the inter-tap timing internally. Returns immediately; use @ref tile_drive_h_is_playing to poll.

tile
Initialised tile handle

tile_drive_h_play_alert

Studio
void tile_drive_h_play_alert(tile_t* tile)

Sequences three ROM-library effects to produce a sharp-buzz-sharp notification: effect 14 ("Strong Buzz — 100%" tick) → effect 56 ("Long Buzz for Programmatic Stopping — 100%") → effect 14. Returns immediately; use @ref tile_drive_h_is_playing to poll.

tile
Initialised tile handle

tile_drive_h_play_buzz

Studio
void tile_drive_h_play_buzz(tile_t* tile, uint16_t ms)

Switches into RTP (Real-Time Playback) mode, drives a constant full-amplitude signal for `ms` milliseconds, then stops the RTP stream and returns to internal-trigger mode. / @ref tile_drive_h_rtp_stop.

tile
Initialised tile handle
ms
Duration in milliseconds
  • Blocking call — does not return until the buzz completes. For longer non-blocking patterns, drive RTP directly via

tile_drive_h_is_calibrated

Studio
uint8_t tile_drive_h_is_calibrated(tile_t* tile)

Reads the STATUS register's DIAG_RESULT bit, which the auto- calibration engine populates on completion: 0 = converged (calibration produced valid A_CAL_COMP / A_CAL_BEMF values), 1 = failed. Only meaningful after a prior call to @ref tile_drive_h_calibrate.

tile
Initialised tile handle

Returns 1 if calibration converged, 0 otherwise

  • STATUS bits clear on read, so the result reflects the most recent calibration / diagnostic run.

Config

tile_drive_h_set_sequence_wait

Studio
void tile_drive_h_set_sequence_wait(tile_t* tile, uint8_t slot, uint8_t delay_steps)

The 8 sequencer slots can each be marked as either an effect (MSB=0, low 7 bits = waveform 1..123) or a wait time (MSB=1, low 7 bits × 10 ms = pause). This call rewrites slot @p slot with a wait of @p delay_steps × 10 ms (max 1270 ms). Use it after tile_drive_h_load_sequence() to insert pauses between effects, e.g. play 1, wait 200 ms, play 47. Slot is silently ignored if >= 8; delay_steps is clipped to 0x7F.

tile
Pointer to tile handle
slot
Slot index 0..7
delay_steps
Wait length in 10 ms steps (0 = no wait, 0x7F = 1.27 s)

tile_drive_h_set_library

Studio
void tile_drive_h_set_library(tile_t* tile, uint8_t library)

The DRV2605L ships with 6 ROM libraries: 1–5 are TS2200 ERM libraries (A–E), 6 is the LRA library. Library 0 is empty (silence). This call also updates the FEEDBACK_CTRL N_ERM_LRA bit so the chip drives the correct actuator type.

tile
Pointer to tile handle
library
Library index 0..6 (use DRIVE_H_LIB_* constants)

tile_drive_h_set_actuator_params

Studio
void tile_drive_h_set_actuator_params(tile_t* tile, uint8_t rated_voltage, uint8_t od_clamp, uint8_t fb_brake, uint8_t loop_gain)

Writes the four registers that the auto-calibration engine and smart-loop architecture consume: - rated_voltage (0x16): full-scale RMS drive level (closed-loop ref). - od_clamp (0x17): peak overdrive ceiling (also open-loop ref). - fb_brake (0x1A bits 6:4): feedback brake factor (0=1× .. 6=16×, 7=off). - loop_gain (0x1A bits 3:2): closed-loop gain (0=Low .. 3=Very high). Pass 0 for rated_voltage / od_clamp to leave that register untouched. Pass 0xFF for fb_brake / loop_gain to leave them untouched. Run tile_drive_h_calibrate() afterwards to update A_CAL_COMP / A_CAL_BEMF.

tile
Pointer to tile handle
rated_voltage
RATED_VOLTAGE byte (0 = no change)
od_clamp
OD_CLAMP byte (0 = no change)
fb_brake
Feedback brake factor 0..7 (0xFF = no change)
loop_gain
Loop gain 0..3 (0xFF = no change)

tile_drive_h_set_loop_mode

Studio
void tile_drive_h_set_loop_mode(tile_t* tile, uint8_t closed)

Closed loop (recommended for LRAs) enables smart-loop back-EMF feedback: automatic resonance tracking, overdrive, and braking, with full-scale amplitude referenced to RATED_VOLTAGE. Open loop drives blind: amplitude is referenced to OD_CLAMP, RATED_VOLTAGE is ignored, and LRA playback does NOT resonance-track on this part — the commutation frequency comes from DRIVE_TIME (see tile_drive_h_set_resonance_hz()). Applies to whichever actuator type is currently selected (set_library() / FEEDBACK_CTRL N_ERM_LRA).

tile
Pointer to tile handle
closed
1 = closed-loop (smart-loop), 0 = open-loop

tile_drive_h_set_actuator_voltage

Studio
void tile_drive_h_set_actuator_voltage(tile_t* tile, uint16_t rated_mv, uint16_t overdrive_mv)

The friendly-units version of tile_drive_h_set_actuator_params(): converts voltages to the RATED_VOLTAGE (0x16) and OD_CLAMP (0x17) register values using the DRV2605 datasheet equations (section 7.5.2, Eq. 2-5), honouring the currently selected actuator type (ERM vs LRA) and, for LRAs, the drive frequency currently programmed via tile_drive_h_set_resonance_hz(). - rated_mv: steady-state full-scale level (RMS for LRA, average for ERM). Closed-loop reference. - overdrive_mv: peak ceiling for overdrive/braking; also the full-scale reference in open-loop mode. Must be >= rated_mv; typically 1.3-1.5x for LRAs. Run tile_drive_h_calibrate() afterwards — the datasheet requires recalibration whenever these references change.

tile
Pointer to tile handle
rated_mv
[300..3600] Rated drive level in mV
overdrive_mv
[300..5000] Overdrive clamp in mV

tile_drive_h_set_resonance_hz

Studio
void tile_drive_h_set_resonance_hz(tile_t* tile, uint16_t hz)

Programs CONTROL1 DRIVE_TIME to half the LRA period — the datasheet-optimal value. In closed-loop mode this seeds the auto-resonance tracker (which then follows the real resonance); in open-loop mode it directly sets the commutation frequency. Read the actuator's actual resonance with tile_drive_h_get_resonance_hz() while driving in closed loop.

tile
Pointer to tile handle
hz
[125..300] LRA resonant frequency in Hz

tile_drive_h_set_resonance_params

Studio
void tile_drive_h_set_resonance_params(tile_t* tile, uint8_t sample_time, uint8_t blanking_time, uint8_t idiss_time)

Writes Control2 (0x1C) bits for sample / blanking / current- dissipation timing. Default values (3 / 1 / 1) work for most coin-type LRAs at 175–235 Hz. Tune only if calibration fails to converge or the actuator runs at the edges of the 125–300 Hz window. Pass 0xFF for any field to leave that register slice untouched.

tile
Pointer to tile handle
sample_time
Sample time 0..3 (0=150µs, 3=300µs; 0xFF = no change)
blanking_time
Blanking time 0..3 (0xFF = no change)
idiss_time
Current-dissipation time 0..3 (0xFF = no change)

tile_drive_h_set_waveform_timing

Studio
void tile_drive_h_set_waveform_timing(tile_t* tile, int8_t overdrive, int8_t sustain_pos, int8_t sustain_neg, int8_t brake)

Adds signed offsets (in 5 ms steps) to the overdrive, sustain, and brake portions of every library effect. Offsets are 8-bit two's complement, so range is -640..+635 ms per knob. These offsets are only honoured in open-loop mode — closed-loop mode generates them automatically from back-EMF feedback.

tile
Pointer to tile handle
overdrive
Overdrive Time Offset (0x0D, signed × 5 ms)
sustain_pos
Sustain-Time Positive Offset (0x0E, signed × 5 ms)
sustain_neg
Sustain-Time Negative Offset (0x0F, signed × 5 ms)
brake
Brake Time Offset (0x10, signed × 5 ms)

tile_drive_h_set_rtp_format

Studio
void tile_drive_h_set_rtp_format(tile_t* tile, uint8_t unsigned_, uint8_t bidir)

Selects how RTP_INPUT bytes are interpreted: - signed (default for closed-loop bidirectional): 0x80 = full reverse, 0x00 = mid-scale (no drive), 0x7F = full forward. - unsigned (recommended for closed-loop unidirectional and open-loop): 0x00 = no drive, 0xFF = full drive. Also exposes the BIDIR_INPUT bit (CONTROL2[7]) which selects unidirectional vs bidirectional input interpretation; tie this to the same convention as the format flag.

tile
Pointer to tile handle
unsigned_
1 = unsigned data format, 0 = signed (default)
bidir
1 = bidirectional input (default), 0 = unidirectional

tile_drive_h_set_audio_params

Studio
void tile_drive_h_set_audio_params(tile_t* tile, uint8_t peak_time, uint8_t filter, uint8_t min_input, uint8_t max_input, uint8_t min_drive, uint8_t max_drive)

Configures the four ATV control registers: - ATV_CTRL (0x11): peak-detect time (0=10ms..3=40ms) and low-pass filter cutoff (0=100Hz..3=200Hz). - ATV_MIN_INPUT (0x12): minimum input level below which the envelope is gated (output silent). raw × 1.8/255 V. - ATV_MAX_INPUT (0x13): full-scale input level. raw × 1.8/255 V. - ATV_MIN_DRIVE (0x14): minimum output drive once unmuted. raw / 255 × 100 %. - ATV_MAX_DRIVE (0x15): maximum output drive at full input. raw / 255 × 100 %. Pass 0xFF for any field to leave it untouched.

tile
Pointer to tile handle
peak_time
ATH_PEAK_TIME 0..3 (10/20/30/40 ms; 0xFF = no change)
filter
ATH_FILTER 0..3 (100/125/150/200 Hz; 0xFF = no change)
min_input
Minimum input gate (0xFF = no change)
max_input
Full-scale input level (0xFF = no change)
min_drive
Minimum output drive once active (0xFF = no change)
max_drive
Full-scale output drive (0xFF = no change)

Other

tile_drive_h_pwm_input_start

Studio
void tile_drive_h_pwm_input_start(tile_t* tile)

Sets MODE=3 with N_PWM_ANALOG=0. The chip accepts a 10–250 kHz PWM signal: duty cycle directly modulates output amplitude (50 % = no drive in bidirectional mode; 0 % = no drive in unidirectional mode). Useful for offloading waveform generation to a hardware timer or audio rendering pipeline. Call tile_drive_h_set_rtp_format() first if you need to change the unidirectional / bidirectional interpretation.

tile_drive_h_analog_input_start

Studio
void tile_drive_h_analog_input_start(tile_t* tile)

Sets MODE=3 with N_PWM_ANALOG=1. Reference voltage is 1.8 V: 0 V → 0 % drive, 0.9 V → 50 %, 1.8 V → 100 %. Useful for waveform synthesis from a DAC or analog signal source.

  • Pad 2 (TRIG) is a digital pad on the tile. The chip pin itself accepts 0–1.8 V analog, but the driving Core must output a clean analog level — Drive.H has no input filter or AC-coupling cap on TRIG.

tile_drive_h_pwm_input_stop

Studio
void tile_drive_h_pwm_input_stop(tile_t* tile)

Returns to internal-trigger mode (MODE=0). Same effect as tile_drive_h_audio_stop(); both modes share the IN/TRIG pin.

tile_drive_h_audio_start

Studio
void tile_drive_h_audio_start(tile_t* tile)

Sets MODE=4 (audio-to-vibe), N_PWM_ANALOG=1 (analog), and AC_COUPLE=1 (0.9 V common-mode bias on IN/TRIG). The chip envelope-detects the audio and drives haptic vibration at matching intensity.

  • The DRV2605L expects an AC-coupled line-level audio source (1.8 Vpp full-scale). Drive.H rev a does not include a series capacitor on pad 2 — users wanting audio-to-vibe must add their own external 1 µF AC-coupling cap between the audio source and pad 2.

tile_drive_h_audio_stop

Studio
void tile_drive_h_audio_stop(tile_t* tile)

Returns to internal-trigger mode (MODE=0) and clears the AC_COUPLE bit. Same physical effect as tile_drive_h_pwm_input_stop().

tile_drive_h_program_otp

uint8_t tile_drive_h_program_otp(tile_t* tile)

Writes the current contents of registers 0x16–0x1A (RATED_VOLTAGE, OD_CLAMP, A_CAL_COMP, A_CAL_BEMF, FEEDBACK_CTRL) to the DRV2605L's nonvolatile OTP cells. After this, those values become the power-on defaults — the chip skips run-time calibration on subsequent boots. once per device. A bad programming run permanently mistunes the chip. NOT exposed to Studio by design. Pre-conditions: - Run tile_drive_h_calibrate() first and confirm pass. - VDD must be 4.0–4.4 V at the moment of programming (datasheet section 7.5.7). Lower VDD silently corrupts the cells. Returns 1 if the OTP_STATUS bit reads 1 after programming, 0 if the burn failed or OTP was already programmed.

tile
Pointer to tile handle

Returns 1 on success, 0 on failure / already-programmed

tile_drive_h_get_otp_status

Studio
uint8_t tile_drive_h_get_otp_status(tile_t* tile)

Returns 1 if the chip's OTP cells have already been programmed (registers 0x16–0x1A boot from OTP rather than chip defaults).

Returns 1 if OTP is programmed, 0 if unprogrammed

Driver gaps · 1

Chip capabilities this driver doesn’t expose yet.

nicheOTP waveform burningThe DRV2605L can burn custom waveforms into one-time-programmable memory. This is implemented in firmware (tile_drive_h_program_otp()) but intentionally NOT exposed to Studio: it permanently and irreversibly modifies the chip. Driver-deferred by policy, not a hardware gap — call it from C if you really need it.

Constants

TILE_DRIVE_H_VERSION_MAJOR4
TILE_DRIVE_H_VERSION_MINOR2
TILE_DRIVE_H_VERSION_PATCH0
DRV2605L_I2C_ADDR_DEFAULT0x5A
DRV2605L_STATUS_DEFAULT0x60Expected default STATUS register value (DEVICE_ID = 3).
DRV2605L_STATUS_DEVICE_ID0xE0Bits 7:5 — device ID
DRV2605L_STATUS_DIAG_RESULT0x08Bit 3 — diagnostic result
DRV2605L_STATUS_OVER_TEMP0x02Bit 1 — over-temperature
DRV2605L_STATUS_OC_DETECT0x01Bit 0 — overcurrent detect
DRV2605L_MODE_INTERNAL_TRIG0x00Internal trigger (I2C GO)
DRV2605L_MODE_EXT_EDGE0x01External trigger, edge mode
DRV2605L_MODE_EXT_LEVEL0x02External trigger, level mode
DRV2605L_MODE_PWM_ANALOG0x03PWM or analog input on TRIG
DRV2605L_MODE_AUDIO0x04Audio-to-vibe on TRIG
DRV2605L_MODE_RTP0x05Real-time playback
DRV2605L_MODE_DIAGNOSTICS0x06Actuator diagnostics
DRV2605L_MODE_CALIBRATION0x07Auto-calibration
DRV2605L_MODE_STANDBY0x40STANDBY bit (bit 6)
DRIVE_H_TRIG_INTERNAL0
DRIVE_H_TRIG_EDGE1
DRIVE_H_TRIG_LEVEL2
DRV2605L_SEQ_MAX8
DRIVE_H_LIB_EMPTY0Empty library (silence).
DRIVE_H_LIB_ERM_A1TS2200 Library A (ERM, fixed open-loop overdrive).
DRIVE_H_LIB_ERM_B2TS2200 Library B (ERM, no overdrive).
DRIVE_H_LIB_ERM_C3TS2200 Library C (ERM, no overdrive).
DRIVE_H_LIB_ERM_D4TS2200 Library D (ERM, no overdrive).
DRIVE_H_LIB_ERM_E5TS2200 Library E (ERM, no overdrive).
DRIVE_H_LIB_LRA6LRA Library (auto-resonance).