BERGSONNE

Sense.T.C

Capacitive touch/proximity driver for the Sense.T.C tile (IQS323).

Examples

Simple polling example (Cores SDK)

  tile_t touch;
  tile_sense_t_c_init(core_tiles_pal(&core_i2c3), 0, &touch, NULL);
  while (1) {
      tile_sense_t_c_process(&touch);
      if (tile_sense_t_c_is_touched(&touch, SENSE_T_C_CH_SURFACE))
          led_on();
      else
          led_off();
      core_delay_ms(30);
  }

Callback example (polled)

  void on_touch(tile_t *t, uint16_t status, void *ctx) {
      if (status & SENSE_T_C_SURFACE_TOUCH)
          led_green();
      else
          led_off();
  }

  sense_t_c_cfg_t cfg = { .on_event = on_touch };
  tile_sense_t_c_init(core_tiles_pal(&core_i2c3), 0, &touch, &cfg);
  while (1) {
      tile_sense_t_c_process(&touch);
      core_delay_ms(30);
  }

Callback example (RDY interrupt)

  sense_t_c_cfg_t cfg = {
      .rdy_pin = 3,
      .on_event = on_touch,
  };
  tile_sense_t_c_init(core_tiles_pal(&core_i2c3), 0, &touch, &cfg);
  while (1) {
      tile_sense_t_c_process(&touch);
      // ... other work — process() returns fast if no RDY event ...
  }

API reference

Initialization

tile_sense_t_c_find

uint8_t tile_sense_t_c_find(tiles_pal_t *hal, uint8_t instance)

Probe the bus for an IQS323 touch controller.

hal
Tiles HAL handle (I2C bus)
instance
Device instance (0 or 1, selects I2C address)

Returns 1 if found, 0 if not

tile_sense_t_c_init

void tile_sense_t_c_init(tiles_pal_t *hal, uint8_t instance, tile_t *tile, const sense_t_c_cfg_t *cfg)

Soft resets, configures CH1 (surface) for self-capacitive touch, sets proximity/touch thresholds, runs ATI.

hal
Tiles HAL handle (I2C bus)
instance
Device instance (0 or 1, selects I2C address)
tile
Tile handle to initialize
cfg
Optional config (thresholds, RDY pin, callback). NULL for defaults.

Lifecycle

tile_sense_t_c_sleep

Studio
void tile_sense_t_c_sleep(tile_t *tile)

Enter low-power sleep mode.

tile_sense_t_c_wake

Studio
void tile_sense_t_c_wake(tile_t *tile)

Wake from sleep mode.

Runtime

tile_sense_t_c_get_status

Studio
uint16_t tile_sense_t_c_get_status(tile_t *tile)

Read the cached System Status word from the last process() call.

tile_sense_t_c_get_gestures

Studio
uint16_t tile_sense_t_c_get_gestures(tile_t *tile)

Read the cached Gesture Status word from the last process() call.

tile_sense_t_c_is_touched

Studio
uint8_t tile_sense_t_c_is_touched(tile_t *tile, uint8_t channel)

Check if the given channel is currently touched.

tile_sense_t_c_is_prox

Studio
uint8_t tile_sense_t_c_is_prox(tile_t *tile, uint8_t channel)

Check if the given channel currently reports proximity.

tile_sense_t_c_get_counts

Studio
uint16_t tile_sense_t_c_get_counts(tile_t *tile, uint8_t channel)

Read the raw counts value for a channel.

tile_sense_t_c_get_lta

Studio
uint16_t tile_sense_t_c_get_lta(tile_t *tile, uint8_t channel)

Read the long-term average (LTA) for a channel.

tile_sense_t_c_get_delta

Studio
int16_t tile_sense_t_c_get_delta(tile_t *tile, uint8_t channel)

Read the delta (counts - LTA) for a channel.

tile_sense_t_c_get_slider

Studio
uint16_t tile_sense_t_c_get_slider(tile_t *tile)

Read the slider position (if a slider is configured).

tile_sense_t_c_set_thresholds

Studio
void tile_sense_t_c_set_thresholds(tile_t *tile, uint8_t channel, uint8_t prox_thresh, uint8_t touch_thresh)

Set proximity and touch thresholds for a channel.

tile_sense_t_c_is_touched_any

Studio
uint8_t tile_sense_t_c_is_touched_any(tile_t *tile)

Reflects the cached System Status from the most recent process() call — it does not perform an I²C read itself, so it's safe to call from any rate. Returns 1 if any of CH0/CH1/CH2 currently reports touch, 0 otherwise. Pair with @ref tile_sense_t_c_process in your main loop.

tile
Initialised tile handle

Returns 1 if any channel is touched, 0 otherwise

tile_sense_t_c_wait_for_touch

Studio
uint8_t tile_sense_t_c_wait_for_touch(tile_t *tile, uint32_t timeout_ms)

Polls process() at ~5 ms cadence and returns as soon as any channel reports touch. If RDY-mode is configured, process() is a no-op until RDY fires, so the poll is effectively interrupt-paced. In polled mode the cadence determines latency. Returns 0 if `timeout_ms` elapses without a touch event.

tile
Initialised tile handle
timeout_ms
Maximum time to wait, in milliseconds

Returns 1 if a touch was detected, 0 on timeout

tile_sense_t_c_wait_for_gesture

Studio
uint16_t tile_sense_t_c_wait_for_gesture(tile_t *tile, uint32_t timeout_ms)

Polls the Gesture Status register at ~5 ms cadence. Returns the raw 16-bit gesture word as soon as any gesture bit is set (IQS323_GESTURE_TAP / SWIPE_POS / SWIPE_NEG / FLICK_POS / FLICK_NEG / HOLD). Returns 0 on timeout. Gestures require the slider/wheel UI to be configured — a single tile surface alone does not produce gesture events. See the datasheet §7.4 for the slider-config requirements.

tile
Initialised tile handle
timeout_ms
Maximum time to wait, in milliseconds

Returns Raw Gesture Status word (non-zero) on detection, 0 on timeout

tile_sense_t_c_read_slider_pct

Studio
uint8_t tile_sense_t_c_read_slider_pct(tile_t *tile, uint8_t *out_pct)

The IQS323 slider register reports a 10-bit position in the range 0–1023. This helper integer-scales it to a 0–100 percentage and stores the result through `out_pct`. Returns 0 if the read returned an invalid (out-of-window) response — `out_pct` is untouched in that case so callers can keep the previous value. Like @ref tile_sense_t_c_get_slider, this requires a valid slider configuration (multi-channel — two Sense.T.C tiles chained, or pad 8 wired to a second electrode). A single tile surface alone cannot produce a slider output.

tile
Initialised tile handle
out_pct
Pointer to receive the percentage (0–100)

Returns 1 on success, 0 on read failure (out_pct unmodified)

tile_sense_t_c_reseed

Studio
void tile_sense_t_c_reseed(tile_t *tile)

Sets SYSTEM_CONTROL.RESEED (self-clearing). Use after a known environmental change (object placed/removed, cover added) to discard the slow baseline and re-zero the channels immediately, instead of waiting for the LTA filter to drift there.

tile
Initialised tile handle.

Events

tile_sense_t_c_process

Studio
void tile_sense_t_c_process(tile_t *tile)

Call from your main loop. In polled mode: reads status register, fires callback if events present. In RDY mode: returns immediately if no RDY interrupt; reads + fires callback only when the device has new data.

tile
Tile handle

tile_sense_t_c_on_event

Studio
void tile_sense_t_c_on_event(tile_t *tile, sense_t_c_event_cb_t cb, void *ctx)

Register or change the event callback for touch/proximity events.

tile
Tile handle
cb
Callback function (NULL to disable)
ctx
User context passed to callback

Config

tile_sense_t_c_set_power_mode

Studio
void tile_sense_t_c_set_power_mode(tile_t *tile, sense_t_c_power_mode_t mode)

Set the device power mode.

tile_sense_t_c_enable_events

Studio
void tile_sense_t_c_enable_events(tile_t *tile, uint16_t mask)

Set the events-enable mask (which events drive RDY pulses).

tile_sense_t_c_ati

Studio
void tile_sense_t_c_ati(tile_t *tile)

Trigger an ATI (auto-tuning) cycle and wait for completion.

tile_sense_t_c_set_ati_setup

Studio
void tile_sense_t_c_set_ati_setup(tile_t *tile, uint8_t channel, uint16_t value)

Writes the raw 16-bit ATI Setup register (0x36 + ch·0x10) for the channel. Bit layout (datasheet §A.12): - Bits 15-4: ATI Target / Resolution Factor - Bit 3: ATI Band (0 = 1/16, 1 = 1/8) - Bits 2-0: ATI Mode (0 disabled, 1 comp-only, 2 from-comp-divider, 3 partial, 4 full) (The coarse/fine multipliers and dividers live in the separate ATI Multipliers/Dividers register at 0x38 — see IQS323_REG_ATI_MULTI; the compensation divider lives at 0x39 — see set_compensation.) After changing ATI parameters, call @ref tile_sense_t_c_ati to re-run the auto-tuning sequence with the new values. Useful when ambient capacitance shifts (cover-glass thickness, mounting substrate) push the working point off the chip's defaults.

tile
Initialised tile handle
channel
0–2
value
Raw 16-bit ATI Setup register value

tile_sense_t_c_set_counts_filter

Studio
void tile_sense_t_c_set_counts_filter(tile_t *tile, uint16_t beta)

Datasheet §A.26. Higher beta = more aggressive smoothing on the raw counts (lower noise, slower response). Default is tuned for typical electrode geometries; tune up for noisy environments, tune down for fast-response applications.

tile
Initialised tile handle
beta
Raw 16-bit Counts Filter Betas register value

tile_sense_t_c_set_conversion_freq

Studio
void tile_sense_t_c_set_conversion_freq(tile_t *tile, uint8_t channel, uint16_t value)

Datasheet §A.4. Controls charge-transfer frequency and dead time. Tune for unusual electrode geometries, large capacitance loads, or when self-capacitance interactions push beyond the chip's default Conversion Frequency Fraction.

tile
Initialised tile handle
channel
0–2
value
Raw 16-bit Conversion Frequency register value

tile_sense_t_c_set_channel_mode

Studio
void tile_sense_t_c_set_channel_mode(tile_t *tile, uint8_t channel, sense_t_c_channel_mode_t mode, uint8_t reference_id)

Reference channels measure ambient capacitance (e.g., temperature / humidity drift on the substrate). Follower channels subtract the reference's LTA delta from their own, eliminating common-mode drift. Datasheet §7.3 describes the design pattern. For follower channels, `reference_id` selects which channel to follow (encoded in Channel Setup bits [7:4]). For independent / reference channels, `reference_id` is unused — pass 0. Apply to all participating channels (set the reference channel to REFERENCE first, then set followers). Re-run @ref tile_sense_t_c_ati after changing channel modes.

tile
Initialised tile handle
channel
0–2
mode
Channel role
reference_id
Which channel to follow (only used for FOLLOWER)

tile_sense_t_c_set_comm_mode

Studio
void tile_sense_t_c_set_comm_mode(tile_t *tile, sense_t_c_comm_mode_t mode)

Event mode (default) waits for the RDY line to assert before communication; lowest power, lowest CPU overhead. Streaming mode reports samples at every report-rate tick regardless of activity; higher current, lower latency. Use streaming for continuous logging or for hosts that can't handle interrupt-driven I²C cleanly.

tile
Initialised tile handle
mode
Event or streaming

tile_sense_t_c_set_report_rate

Studio
void tile_sense_t_c_set_report_rate(tile_t *tile, sense_t_c_power_mode_t mode, uint16_t ms)

Writes the per-mode report-rate register (NP 0xC1 / LP 0xC2 / ULP 0xC3 / HALT 0xC4) in plain milliseconds (clamped 0-3000). This is the tile's headline power/latency knob — faster rate = lower latency, higher current. Only the four reporting modes have a rate; AUTO/AUTO_NO_ULP are ignored.

tile
Initialised tile handle.
mode
Which power mode's rate to set (NORMAL/LOW/ULTRA_LOW/HALT).
ms
Report interval in milliseconds (0-3000).

tile_sense_t_c_set_power_timeout

Studio
void tile_sense_t_c_set_power_timeout(tile_t *tile, uint16_t ms)

Writes POWER_TIMEOUT (0xC5) in milliseconds. In AUTO / AUTO_NO_ULP the chip steps down a power mode after this much inactivity; 0 disables auto step-down.

tile
Initialised tile handle.
ms
Inactivity timeout in milliseconds (0-65000, 0 = off).
gapPer-gesture threshold tuningIQS323 gesture timing (tap touch/release time, hold duration, swipe distance, flick velocity) is packed across several GESTURE_* registers with chip-specific encodings. The driver reports gesture events but doesn't surface a typed API for timing / threshold tuning — closing this properly needs a dedicated pass with Azoteq's gesture-config guide. Raw write_reg works for advanced users in the interim.

Advanced

tile_sense_t_c_read_reg

Studio
uint16_t tile_sense_t_c_read_reg(tile_t *tile, uint8_t reg)

Read a raw 16-bit IQS323 register.

tile_sense_t_c_write_reg

Studio
void tile_sense_t_c_write_reg(tile_t *tile, uint8_t reg, uint16_t value)

Write a raw 16-bit IQS323 register.

tile_sense_t_c_get_compensation

Studio
uint16_t tile_sense_t_c_get_compensation(tile_t *tile, uint8_t channel)

Returns the raw Compensation register (0x39 + ch·0x10). The low 10 bits are the compensation value; bits 15-11 are the divider. Normally set by ATI — read it to capture a tuned working point.

tile
Initialised tile handle.
channel
0-2.

Returns Raw 16-bit compensation register, or 0 on a bad channel.

tile_sense_t_c_set_compensation

Studio
void tile_sense_t_c_set_compensation(tile_t *tile, uint8_t channel, uint16_t value, uint8_t divider)

Writes the Compensation register (0x39 + ch·0x10): value (0-1023) in bits 9-0, divider (0-31) in bits 15-11. NOTE: a subsequent full ATI overwrites this — to hold a fixed offset, set the channel's ATI Mode (set_ati_setup) to a non-full mode first.

tile
Initialised tile handle.
channel
0-2.
value
Compensation value (0-1023).
divider
Compensation divider (0-31).
gapPer-channel timeout / OutA event-indicatorChannel-timeout disable bits (auto-reseed on timeout) and the OutA pin's event-indicator output mode aren't exposed. Most applications don't need them; raw write_reg covers the niche cases that do.

Enums

sense_t_c_channel_mode_t

Channel Mode for the Reference UI (datasheet §A.15 bits [3:0]).

SENSE_T_C_CHANNEL_INDEPENDENT
Stand-alone sensing channel
SENSE_T_C_CHANNEL_FOLLOWER
Subtracts a reference channel's LTA
SENSE_T_C_CHANNEL_REFERENCE
Acts as ambient reference for followers

sense_t_c_comm_mode_t

I²C communication mode (System Control register §A.30 bit 7).

SENSE_T_C_COMM_STREAM
Continuous reporting at the configured power-mode rate
SENSE_T_C_COMM_EVENT
RDY pulses only on enabled events (default)

Constants

TILE_SENSE_T_C_VERSION_MAJOR1
TILE_SENSE_T_C_VERSION_MINOR3
TILE_SENSE_T_C_VERSION_PATCH0
IQS323_I2C_ADDR_0010x44
IQS323_I2C_ADDR_0020x58
SENSE_T_C_CH00CRx0/CTx0 -- pad 8 (external)
SENSE_T_C_CH11CRx1/CTx1 -- tile top surface
SENSE_T_C_CH22CRx2/CTx2/Bias
SENSE_T_C_NUM_CHANNELS3
IQS323_STATUS_POWER_SHIFT14
IQS323_INVALID_RESPONSE0xEEEE
IQS323_CTRL_POWER_SHIFT4
IQS323_HW_ID_3DD0xF003
IQS323_HW_ID_3ED0xF004