Drive.P
Piezoelectric haptic driver for the Drive.P tile (rev a).
Embeds the Boréas Technologies BOS1921, a piezoelectric driver with integrated high-voltage boost (190 Vpp differential), waveform synthesizer, 1024-sample FIFO, and piezo sensing.
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 |
|---|---|---|---|---|
| Output voltage range | basic | ±95 V (high voltage), ±13.28 V (init default) | ±13.28 V (init default) | set_output_range(range) |
| Positive voltage limit | basic | 0 to 95 V | 95 | set_voltage_limits(pos_v) |
| Negative voltage limit | basic | 0 to 95 V | 10 | set_voltage_limits(neg_v) |
| Touch sensing resolution | advanced | Coarse (54.5 mV per step), Fine (7.6 mV per step) | Fine (7.6 mV per step) | set_sense_gain(gain) |
| Keep settings while asleep | advanced | on / off | on | set_sleep_retention(retain) |
| Sleep after 4 ms idle | advanced | on / off | off | set_auto_sleep(enabled) |
| Never return energy to the supply | advanced | on / off | off | set_upi(enabled) |
Examples
Quick start
#include "core_tiles.h"
tile_t piezo;
tile_drive_p_init(core_tiles_pal(&core_i2c1), 0, &piezo, NULL);
if (tile_is_ready(&piezo)) {
// init leaves the output in the LOW range (±13.28 V). Opt in to
// ±95 V explicitly, and only for a piezo rated for it:
// tile_drive_p_set_output_range(&piezo, DRIVE_P_OUTPUT_HIGH_V);
// Every sample is limited to +95 V / -10 V by default (PowerHap-safe;
// see tile_drive_p_set_voltage_limits), flattened at the limit.
tile_drive_p_play_click(&piezo, 80);
}API reference
Initialization
tile_drive_p_find
uint8_t tile_drive_p_find(tiles_pal_t* hal, uint8_t instance)Check whether a BOS1921 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_p_init
void tile_drive_p_init(tiles_pal_t* hal, uint8_t instance, tile_t* tile, const drive_p_cfg_t *cfg)Wakes the device, performs a software reset, verifies the chip ID, and configures parasitic capacitance and supply parameters for a 260nF piezo on a 3.7V LiPo supply. The output is left in IDLE in the LOW range (±13.28 V, CONFIG.GAIND = 1) with PARCAP / TI_RISE / I_ON_SCALE tuned for it; call tile_drive_p_set_output_range(tile, DRIVE_P_OUTPUT_HIGH_V) to opt in to ±95 V. The SUP_RISE I2C_ADDR nibble is derived from the instance's address, so a reassigned chip (0x45/0x46) keeps its address — a soft reset doesn't revert it, so init may reset such a chip normally. Ends with a TILE_DRIVE_P_SETTLE_MS (default 100 ms) wait so the supply has settled before the first output (a click right after power-up can brown out a USB-powered Core). Pass cfg=NULL for defaults.
- hal
- Platform HAL handle
- instance
- Instance index (0=0x44, 1=0x45, 2=0x46; see mapping table)
- tile
- Pointer to tile handle (populated by this function)
- cfg
- Optional config, or NULL for defaults
Lifecycle
tile_drive_p_reset
void tile_drive_p_reset(tile_t* tile)Follows the datasheet's safe order (§6.2.8): output to 0 V (Direct / FIFO modes) and OE = 0, wait for IC_STATUS.STATE to leave RUN (bounded at 150 ms: a full FIFO keeps playing 128 ms after OE = 0), then RST. The chip and the driver's shadow return to power-on defaults (the I2C address is kept) and the tile goes to NONE: re-run init() afterwards. To reset and keep your configuration, use @ref tile_drive_p_check_and_recover.
- tile
- Pointer to tile handle
tile_drive_p_sleep
Studiovoid tile_drive_p_sleep(tile_t* tile)Writes CONFIG with DS = 1 and OE = 0 (datasheet §6.2.6): the output stops and the chip drops to SLEEP — ~2.4 µA with retention, ~0.6 µA without (see @ref tile_drive_p_set_sleep_retention). Any I2C traffic wakes the chip, so leave the bus alone until @ref tile_drive_p_wake; set_mode() and the play / sense helpers call wake() for you.
tile_drive_p_wake
Studiouint8_t tile_drive_p_wake(tile_t* tile)Follows the datasheet start-up sequence (§7.4.1 steps 3-6, §7.4.2): a dummy write wakes the chip (its data is ignored, §6.2.6), a 1 ms settle covers the 50 µs SLEEP→IDLE time, then CONFIG (DS = 0, OE = 0, GAINS / GAIND / RET), PARCAP (with UPI), SUP_RISE and COMM (TOUT) are rewritten from the driver's shadow, and CHIP_ID is read back. Rewriting everything covers both retention settings: with retention off (RET = 1) the chip loses its registers in SLEEP; its I2C address survives either way (§6.10.8). RAM contents (RAM-playback / synthesis waveforms) are not restored — re-load them after a no-retention sleep. The tile returns to IDLE mode. Also use it after a COMM.TOUT auto-sleep (@ref tile_drive_p_set_auto_sleep), which leaves the tile READY but the chip asleep. Harmless on an awake chip.
Returns 1 if the chip answered with the expected CHIP_ID (tile READY), 0 otherwise (tile ERROR, or the tile was never initialized)
Runtime
tile_drive_p_set_mode
Studiovoid tile_drive_p_set_mode(tile_t* tile, drive_p_mode_t mode)Set the operating mode.
- mode
- One of the drive_p_mode_t values
tile_drive_p_read
Studiouint16_t tile_drive_p_read(tile_t* tile)Read the current return register value.
Returns 16-bit value from the currently selected return register
tile_drive_p_read_sense
Studioint16_t tile_drive_p_read_sense(tile_t* tile)Must be in SENSE_FINE or SENSE_COARSE mode.
Returns Signed 16-bit sense value (−2048 to +2047)
tile_drive_p_read_status
Studiouint16_t tile_drive_p_read_status(tile_t* tile)Read the IC status register.
Returns 16-bit IC_STATUS value
tile_drive_p_read_clamp_count
Studiouint32_t tile_drive_p_read_clamp_count(tile_t* tile)Counts every sample clamped to +pos / -neg (@ref tile_drive_p_set_voltage_limits) since init or the previous call, and resets it to 0. Nonzero means the waveform hit a limit and was played flattened. Saturates at 4294967295.
Returns Clamped samples since the last call
tile_drive_p_play_click
Studiovoid tile_drive_p_play_click(tile_t* tile, uint8_t intensity_pct)Streams a 2 ms half-sine pulse through the FIFO at 8 ksps in one burst, framed by 0 V samples: two before it (discharges residual piezo charge, §6.2.18) and the pulse itself ends at exactly 0 V, so the output rests at 0 V when the FIFO drains (§6.6). Intensity scales the peak output amplitude in the configured voltage range (±13.28 V after init; see @ref tile_drive_p_set_output_range to opt in to ±95 V). Returns when the FIFO has been written; the chip continues playing the click after the call returns. The output is switched off (OE = 0) right after the last sample is queued; the chip finishes the FIFO first (§6.6), then idles. The next play / set_mode call turns it back on.
- intensity_pct
- [0..100] Percent of full-scale output (100 = ±95 V, or ±13.28 V in the low range), clamped to the voltage limits
tile_drive_p_play_sine
Studiovoid tile_drive_p_play_sine(tile_t* tile, uint16_t freq_hz, uint8_t intensity_pct, uint16_t ms)Generates and streams sine samples at 8 ksps. Frequency is software-quantised to the sample rate (max useful ~3 kHz). The last 2 ms fade linearly to exactly 0 V, so the output never parks at a DC level (§6.6). Streaming paces on FIFO_STATE.FIFO_SPACE and writes 32-sample bursts: the call returns once the last sample is queued, i.e. it blocks for about (ms − 128) ms on long tones and the chip plays out the final ≤ 128 ms after it returns. Gapless output needs a ≥ 400 kHz bus. Stops early if the chip reports ERROR or stops draining for 20 ms. Like play_click(), turns the output off (OE = 0) after queuing the last sample; the chip idles once the FIFO has drained.
- freq_hz
- [1..4000] Sine frequency in Hz (50–3000 useful range)
- intensity_pct
- [0..100] Percent of full-scale output (100 = ±95 V, or ±13.28 V in the low range), clamped to the voltage limits
- ms
- Duration in milliseconds
tile_drive_p_play_buzz
Studiovoid tile_drive_p_play_buzz(tile_t* tile, uint8_t intensity_pct, uint16_t ms)Convenience wrapper for @ref tile_drive_p_play_sine at 150 Hz — a frequency typical small-form-factor piezo actuators feel strongly at. Use `play_sine` directly if you need a specific frequency.
- intensity_pct
- [0..100] Percent of full-scale output (100 = ±95 V, or ±13.28 V in the low range), clamped to the voltage limits
- ms
- Duration in milliseconds
tile_drive_p_play_pulse_train
Studiovoid tile_drive_p_play_pulse_train(tile_t* tile, uint8_t intensity_pct, uint8_t count, uint16_t gap_ms)The classic "tick-tick-tick" pattern. Composes @ref tile_drive_p_play_click with `core_delay_ms` between clicks. The output stays on between clicks and goes off (OE = 0) once, after the last click is queued.
- intensity_pct
- [0..100] Percent of full-scale output (100 = ±95 V, or ±13.28 V in the low range), clamped to the voltage limits
- count
- [1..255] Number of clicks
- gap_ms
- Milliseconds between successive clicks
tile_drive_p_is_touched
Studiouint8_t tile_drive_p_is_touched(tile_t* tile, uint16_t threshold_mv)Switches into sense mode (fine resolution), reads one sense sample, compares the absolute value against `threshold_mv`, and returns the boolean result. Leaves the chip in sense mode after the call — call `tile_drive_p_set_mode(tile, DRIVE_P_MODE_IDLE)` (or any play mode) to return to driving the actuator.
- threshold_mv
- Absolute sense voltage threshold in mV
Returns 1 if |sense| >= threshold (touched), 0 otherwise
- Blocks ~5 ms: every call re-enters sense mode, which waits 5 ms. To poll quickly, call set_mode(DRIVE_P_MODE_SENSE_FINE) once and read_sense() in the loop.
tile_drive_p_play_on_touch
Studiouint8_t tile_drive_p_play_on_touch(tile_t* tile, uint8_t intensity_pct, uint16_t threshold_mv, uint32_t timeout_ms)Polls the sense channel until `threshold_mv` is exceeded, then switches into FIFO mode and plays a click via @ref tile_drive_p_play_click. The classic closed-loop tactile-feedback idiom — press the piezo, feel the click. Enters sense mode once (~5 ms), then reads the sense value about every 1 ms; returns 0 once about `timeout_ms` has elapsed without detection. Leaves the chip in sense mode on a timeout.
- intensity_pct
- [0..100] Percent of full-scale output (100 = ±95 V, or ±13.28 V in the low range), clamped to the voltage limits
- threshold_mv
- Touch threshold in mV
- timeout_ms
- Maximum time to wait
Returns 1 if a touch fired the click, 0 on timeout
tile_drive_p_play_samples
Studiovoid tile_drive_p_play_samples(tile_t* tile, const int16_t* samples, uint16_t count)Switches into FIFO play mode (if not already there) and writes `count` samples to REFERENCE[11:0] (signed 12-bit, two's complement), 8 ksps. Each sample is clamped to the output voltage limits (@ref tile_drive_p_set_voltage_limits; by default +full scale / -10 V) and counted (@ref tile_drive_p_read_clamp_count); ±1743 is full scale of the range. Start and end the waveform at 0: the last sample stays on the output when the FIFO drains, and the driver does not append one (so back-to-back calls can stream a long waveform in pieces). Paced on FIFO_SPACE with 32-sample burst writes; returns once the last sample is queued (up to 128 ms of it still playing). Stops early if the chip reports ERROR or stops draining for 20 ms. Leaves the output on (OE = 1) so calls chain; call set_mode(DRIVE_P_MODE_IDLE) when done to switch it off. Use this for arbitrary waveforms that don't fit the click / sine / buzz / pulse-train idioms — e.g., recorded waveforms or DSP-generated patterns.
- samples
- Buffer of signed samples in REFERENCE codes (±1743 = full scale)
- count
- Number of samples to write
tile_drive_p_read_sense_samples
Studiovoid tile_drive_p_read_sense_samples(tile_t* tile, int16_t* buf, uint16_t count)Switches into fine-resolution sense mode (~5 ms) and reads `count` samples into the caller's buffer, back to back with no pacing. The chip updates SENSE_VALUE continuously (datasheet §6.4.1), so the sample rate is set by the bus (each read is a register write plus a read) and consecutive samples can repeat a value. Use for impedance characterisation, multi-touch pattern detection, or piezo-as-mic experiments beyond the simple `is_touched` API.
- buf
- Output buffer for signed 12-bit sense samples (7.6 mV/LSB)
- count
- Number of samples to read
Config
tile_drive_p_set_output_range
Studiovoid tile_drive_p_set_output_range(tile_t* tile, drive_p_output_range_t range)The tile starts in the LOW range (±13.28 V): init sets it. The HIGH range is ±95 V (190 Vpp across OUT+/OUT-), a shock and piezo-damage hazard, and is only entered by calling this with DRIVE_P_OUTPUT_HIGH_V. Use it only for an actuator rated for that swing. (The chip's own reset value is the high range; the driver overrides it at init.) Writes CONFIG with OE = 0 (output stops; datasheet: set OE = 0 before changing gain), then rewrites PARCAP, SUP_RISE.TI_RISE and ION_BL.I_ON_SCALE for the new FBratio. Use from IDLE before setting a play mode. On a sleeping tile it only updates the driver's shadow; wake() applies it.
- range
- DRIVE_P_OUTPUT_HIGH_V or DRIVE_P_OUTPUT_LOW_V
tile_drive_p_set_sense_gain
Studiovoid tile_drive_p_set_sense_gain(tile_t* tile, drive_p_sense_gain_t gain)Fine gain (7.6 mV LSB) is the BOS1921 default and gives the highest sensing resolution. Coarse gain (54.5 mV LSB) widens the input range — useful when sensing high-amplitude press events that would otherwise saturate at fine gain. Use from IDLE before entering a sense mode.
- gain
- DRIVE_P_SENSE_FINE_GAIN or DRIVE_P_SENSE_COARSE_GAIN
tile_drive_p_set_sleep_retention
Studiovoid tile_drive_p_set_sleep_retention(tile_t* tile, uint8_t retain)Default is retain (~2.4 µA quiescent) so that RAM contents and register configuration survive a sleep cycle. Disabling retention (~0.6 µA) is useful for ultra-low-power applications; wake() rewrites the driver's register configuration either way, but RAM contents are lost. Set this before calling sleep().
- retain
- 1 = retain (default), 0 = clear on sleep
tile_drive_p_set_auto_sleep
Studiovoid tile_drive_p_set_auto_sleep(tile_t* tile, uint8_t enabled)When enabled, the device drops into SLEEP after 4 ms of bus inactivity during Direct or FIFO playback. Useful for unattended one-shot waveforms; harmful for long streaming playback where a host gap would unexpectedly stop the output.
- enabled
- 1 = auto-sleep on idle, 0 = stay awake
- After a timeout-triggered sleep, PLAY_SRATE is reset to 0x7 (8 ksps), which is the rate the driver always uses. The driver's tile state stays READY; the first I2C write after the timeout only wakes the chip and is discarded, so call @ref tile_drive_p_wake before the next command.
tile_drive_p_set_upi
Studiovoid tile_drive_p_set_upi(tile_t* tile, uint8_t enabled)UPI forces the BOS1921 into sink-only operation: energy recovered from piezo discharge is dumped instead of pushed back into the supply. Useful for battery-powered designs where the supply rail can't safely absorb returned energy.
- enabled
- 1 = sink-only (UPI on), 0 = energy recovery (default)
tile_drive_p_set_voltage_limits
Studiovoid tile_drive_p_set_voltage_limits(tile_t* tile, uint8_t pos_v, uint8_t neg_v)Every output sample the driver sends (click, sine, buzz, pulse train, play_samples, write_fifo, and REFERENCE samples through write_reg / wfs_write in Direct / FIFO mode) is clamped to [-neg_v, +pos_v]: a waveform that exceeds a limit still plays, flattened at it, and each flattened sample is counted (@ref tile_drive_p_read_clamp_count). RAM Playback / RAM Synthesis waveforms are not covered (see wfs_write). Init sets +95 V / -10 V: positive up to the range's maximum, negative 10 V, because PowerHap actuators take a high positive voltage but only ~10 V negative. Widen the negative limit only for an actuator rated for it. The limits are kept in volts and converted to REFERENCE codes for the active output range, rounded down so the limit in force never exceeds the one asked for; set_output_range re-derives them. A limit at or above the range's maximum is that maximum (±1743). Resolution: one code is 54.5 mV on the ±95 V range (1 V = ~18.3 codes) and 7.6 mV on the ±13.28 V range (1 V = ~131 codes); e.g. 10 V is code 183 (9.98 V) high, 1313 (10.00 V) low. Driver-side only; nothing is written to the chip. The limits survive set_output_range, sleep and reset; init restores the defaults.
- pos_v
- [0..95] V Largest positive output; values above 95 mean 95
- neg_v
- [0..95] V Largest negative output, as a magnitude; values above 95 mean 95
Advanced
tile_drive_p_write_fifo
Studiovoid tile_drive_p_write_fifo(tile_t* tile, int16_t sample)One REFERENCE write. In Direct / FIFO mode (and IDLE / sense, whose PLAY_MODE is Direct) the sample is limited to the output voltage limits (@ref tile_drive_p_set_voltage_limits) and counted if clamped; a value beyond 12 bits clamps rather than wrapping. In the RAM modes the same register takes WFS command words, which go out unchanged.
- sample
- Signed waveform sample in REFERENCE codes (±1743 = full scale of the range)
tile_drive_p_write_reg
void tile_drive_p_write_reg(tile_t* tile, uint8_t reg, uint16_t value)Two registers are not entirely raw. A REFERENCE (0x00) write in Direct / FIFO mode is a sample: REFERENCE[11:0] is limited like write_fifo()'s. A CONFIG (0x05) write updates the driver's view of the output range and play mode, so the voltage limits stay correct in volts. Changing the range this way does not retune PARCAP / TI_RISE / I_ON_SCALE; use
- tile
- Pointer to tile handle
- reg
- 8-bit register address
- value
- 16-bit value (sent big-endian on the wire)
tile_drive_p_wfs_write
Studiovoid tile_drive_p_wfs_write(tile_t* tile, const uint16_t* words, uint16_t count)In the RAM modes the words are WFS commands and go out unchanged, so the output voltage limits do NOT cover RAM Playback / RAM Synthesis waveforms: keep their samples and AMPLITUDE fields within the limits yourself. In Direct / FIFO mode the words are samples (REFERENCE[11:0]) and are limited like write_fifo()'s.
- words
- Array of 16-bit words (big-endian on wire)
- count
- Number of words (max 8)
tile_drive_p_check_and_recover
Studiouint8_t tile_drive_p_check_and_recover(tile_t* tile, drive_p_mode_t restore_mode)If IC_STATUS shows STATE = ERROR or any fault bit, resets the chip in the §6.2.8 order (see @ref tile_drive_p_reset; blocks up to ~150 ms while a FIFO drains), then rewrites the full configuration — init's tuned PARCAP (with UPI), SUP_RISE, output range, sense gain, sleep retention and auto-sleep — and re-enters restore_mode. A sleeping tile is woken first.
- restore_mode
- Mode to re-enter after recovery
Returns 1 if recovery was performed, 0 if device was healthy
tile_drive_p_get_pos_limit_v
Studiouint8_t tile_drive_p_get_pos_limit_v(tile_t* tile)As set (default 95). The limit in force is the smaller of this and the active range's maximum (±95 V or ±13.28 V).
Returns Positive limit in volts (0..95)
tile_drive_p_get_neg_limit_v
Studiouint8_t tile_drive_p_get_neg_limit_v(tile_t* tile)As set (default 10). The limit in force is the smaller of this and the active range's maximum (±95 V or ±13.28 V).
Returns Negative limit in volts, as a magnitude (0..95)
Other
tile_drive_p_init_at
void tile_drive_p_init_at(tiles_pal_t* hal, uint8_t addr, tile_t* tile, const drive_p_cfg_t *cfg)The address-explicit sibling of tile_drive_p_init(): identical bring-up, but you name the operating address directly instead of an instance index. This decouples a chip from the fixed instance→address table, which a topology- driven bringup needs — e.g. the v1 Ring runs two Drive.P on separate buses, BOTH at 0x44 (no readdress), which the instance map can't express. Shadow state is keyed per-tile, so two chips at the same address on different buses don't collide. Pass cfg=NULL for defaults.
- hal
- Platform HAL handle (the bus this chip lives on)
- addr
- Operating I2C address (e.g. 0x44 / 0x45 / 0x46)
- tile
- Pointer to tile handle (populated by this function)
- cfg
- Optional config, or NULL for defaults
tile_drive_p_reassign_address
uint8_t tile_drive_p_reassign_address(tiles_pal_t* hal, uint8_t cur_addr, uint8_t new_addr)For two BOS1921 sharing a bus (both at 0x44), move each to a unique address. The call wakes the chip(s) still at cur_addr, sets COMM.GPIODIR=1 (GPIO becomes a write-gate), writes the new address into SUP_RISE.I2C_ADDR, and verifies CHIP_ID at new_addr. Only the chip whose GPIO the caller holds low latches the change; the others are untouched. The driver performs the I2C register sequence only; the **caller owns the GPIO** (a board-specific Core pad, not reachable through the tile PAL). Move BOTH chips of a pair off 0x44 (→ 0x45 and 0x46); each call gates a different chip: // chip A → 0x45 : hold A's GPIO low, B's high core_pad_write(GPIO_A, 0); core_pad_write(GPIO_B, 1); tile_drive_p_reassign_address(hal, 0x44, 0x45); // chip B → 0x46 : hold B's GPIO low, A's high (A has left 0x44) core_pad_write(GPIO_A, 1); core_pad_write(GPIO_B, 0); tile_drive_p_reassign_address(hal, 0x44, 0x46); core_pad_input(GPIO_A); core_pad_input(GPIO_B); // release // then init instance 1 (0x45) and 2 (0x46)
- hal
- Platform HAL handle
- cur_addr
- the chip's current 7-bit address (0x44 at power-up)
- new_addr
- desired 7-bit address; only the low nibble is settable, so it must be in 0x40..0x4F (BOS1921_I2C_ADDR_SECOND/THIRD)
Returns 1 if the chip answers at new_addr with the correct CHIP_ID, else 0
- The new address persists until power-on reset; a soft reset will not revert it. Re-running this from 0x44 after a reflash (no power cycle) is a no-op — the chips already left 0x44.
Driver gaps · 3
Chip capabilities this driver doesn’t expose yet.
Enums
drive_p_mode_t
Drive.P operating mode.
- DRIVE_P_MODE_IDLE
- Output disabled, status readback
- DRIVE_P_MODE_SENSE_FINE
- Piezo sensing, 7.6 mV/LSB resolution
- DRIVE_P_MODE_SENSE_COARSE
- Piezo sensing, 54.5 mV/LSB resolution
- DRIVE_P_MODE_PLAY_DIRECT
- Direct waveform output
- DRIVE_P_MODE_PLAY_FIFO
- FIFO-buffered playback, 8 ksps
- DRIVE_P_MODE_PLAY_RAM_SYNTH
- RAM Synthesis waveform playback
drive_p_output_range_t
Output voltage range (CONFIG.GAIND).
- DRIVE_P_OUTPUT_HIGH_V
- ±95 V (high voltage)
- DRIVE_P_OUTPUT_LOW_V
- ±13.28 V (init default)
drive_p_sense_gain_t
Sense-channel resolution (CONFIG.GAINS).
- DRIVE_P_SENSE_COARSE_GAIN
- Coarse (54.5 mV per step)
- DRIVE_P_SENSE_FINE_GAIN
- Fine (7.6 mV per step)
Constants
| TILE_DRIVE_P_VERSION_MAJOR | 3 | |
| TILE_DRIVE_P_VERSION_MINOR | 6 | |
| TILE_DRIVE_P_VERSION_PATCH | 2 | |
| TILE_DRIVE_P_SETTLE_MS | 100 | |
| BOS1921_I2C_ADDR_DEFAULT | 0x44 | |
| BOS1921_I2C_ADDR_SECOND | 0x45 | Instance 1 — first of a pair |
| BOS1921_I2C_ADDR_THIRD | 0x46 | Instance 2 — second of a pair |
| BOS1921_CHIP_ID_DEFAULT | 0x0781 | Expected lower 12 bits of CHIP_ID register. |
| BOS1921_REFERENCE_MAX | 1743 | |
| DRIVE_P_VOLTAGE_LIMIT_MAX_V | 95 | |
| DRIVE_P_POS_LIMIT_DEFAULT_V | 95 | |
| DRIVE_P_NEG_LIMIT_DEFAULT_V | 10 | |
| BOS_STATUS_STATE_MASK | 0x0300 | STATE field in IC_STATUS (bits 9:8). |
| BOS_STATUS_STATE_IDLE | 0x0000 | |
| BOS_STATUS_STATE_CALIB | 0x0100 | |
| BOS_STATUS_STATE_RUNNING | 0x0200 | |
| BOS_STATUS_STATE_ERROR | 0x0300 | |
| BOS_STATUS_FAULT_MASK | 0x00FC | Fault bits in IC_STATUS (bits 7:2, excluding FULL and PLAYST). |
| BOS_FIFO_STATE_SPACE_MASK | 0x03FF | |
| BOS1921_FIFO_DEPTH | 1024 | FIFO depth in samples (chip default; the driver never changes it). |
| BOS_CONFIG_PLAY_MODE_MASK | 0x0600 | |
| BOS_SUP_RISE_I2C_ADDR_POS | 12 | |
| BOS_SUP_RISE_TIMING_DEFAULT | 0x0967 | default with I2C_ADDR nibble cleared |

