Sense.T.C
Capacitive touch/proximity driver for the Sense.T.C tile (IQS323).
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 |
|---|---|---|---|---|
| Touch threshold | basic | 1 to 255 | 40 | set_touch_threshold(threshold) |
| Proximity threshold | advanced | 1 to 255 | 20 | set_prox_threshold(threshold) |
| Power mode | advanced | Normal power mode, Low power mode, Ultra-low power mode, Halt (lowest power), Auto power mode switching, Auto mode, skip ultra-low power | Auto power mode switching | set_power_mode(mode) |
| I2C reporting | advanced | Continuous reporting at the configured power-mode rate (the chip's reset default), RDY pulses only on enabled events (what init() selects) | RDY pulses only on enabled events (what init() selects) | set_comm_mode(mode) |
| Idle time before low power | advanced | 0 to 65000 | 2000 | set_power_timeout(ms) |
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)Instance 0 is 0x44 (order code IQS323-001, this tile); instance 1 is 0x58 (IQS323-002). The address is fixed by the order code, not a strap.
- 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, then configures the chip (see the file header): channels, thresholds, filters, report rates, AUTO power, ATI, event mode. Takes roughly 0.5-2 s, most of it ATI and the forced communication windows.
- 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
Studiovoid tile_sense_t_c_sleep(tile_t *tile)The chip stops sensing; process() does nothing until wake().
tile_sense_t_c_wake
Studiovoid tile_sense_t_c_wake(tile_t *tile)Restores the power mode last chosen with set_power_mode() (init: AUTO).
tile_sense_t_c_reset
void tile_sense_t_c_reset(tile_t *tile)All registers return to their reset values (thresholds, report rates and filters 0, every channel on CRx0) and the tile leaves the READY state. Call init() again afterwards.
Runtime
tile_sense_t_c_get_status
Studiouint16_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
Studiouint16_t tile_sense_t_c_get_gestures(tile_t *tile)Read the Gesture Status word (a live read, not cached).
tile_sense_t_c_is_touched
Studiouint8_t tile_sense_t_c_is_touched(tile_t *tile, uint8_t channel)Reads the cached System Status from the last process() call.
- channel
- [0..2] 0 = pad 8 electrode, 1 = tile surface, 2 = not routed
Returns 1 if touched, 0 otherwise
tile_sense_t_c_is_prox
Studiouint8_t tile_sense_t_c_is_prox(tile_t *tile, uint8_t channel)Reads the cached System Status from the last process() call.
- channel
- [0..2] 0 = pad 8 electrode, 1 = tile surface, 2 = not routed
Returns 1 if in proximity, 0 otherwise
tile_sense_t_c_get_counts
Studiouint16_t tile_sense_t_c_get_counts(tile_t *tile, uint8_t channel)Self-capacitance counts DROP when a finger approaches.
- channel
- [0..2] Channel
Returns Filtered counts, or 0 for a bad channel
tile_sense_t_c_get_lta
Studiouint16_t tile_sense_t_c_get_lta(tile_t *tile, uint8_t channel)Read the long-term average (LTA) for a channel.
- channel
- [0..2] Channel
Returns LTA baseline in counts
tile_sense_t_c_get_delta
Studioint16_t tile_sense_t_c_get_delta(tile_t *tile, uint8_t channel)Read the delta (counts - LTA) for a channel.
- channel
- [0..2] Channel
Returns counts - LTA; negative when a finger is near a self-cap channel
tile_sense_t_c_get_slider
Studiouint16_t tile_sense_t_c_get_slider(tile_t *tile)Raw Slider Position register (0x12): 0..Slider Resolution (0x93). Stays 0 until a slider is configured (see the slider note above).
Returns Slider position
tile_sense_t_c_set_thresholds
Studiovoid tile_sense_t_c_set_thresholds(tile_t *tile, uint8_t channel, uint8_t prox_thresh, uint8_t touch_thresh)Prox is an absolute delta in counts (A.16, written with 4/4 debounce); touch is relative, threshold/256 of the LTA (A.17). A 0 leaves that register unchanged. Azoteq's EV-kit uses prox 20, touch 40. These per-channel values are lost if the chip resets (process() re-applies the all-channel thresholds from init / set_touch_threshold / set_prox_threshold).
- channel
- [0..2] Channel
- prox_thresh
- [0..255] Prox threshold, delta counts (0 = unchanged)
- touch_thresh
- [0..255] Touch threshold, x/256 of LTA (0 = unchanged)
tile_sense_t_c_is_touched_any
Studiouint8_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.
Returns 1 if any channel is touched, 0 otherwise
tile_sense_t_c_wait_for_touch
Studiouint8_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.
- 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
Studiouint16_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.
- 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
Studiouint8_t tile_sense_t_c_read_slider_pct(tile_t *tile, uint8_t *out_pct)The IQS323 slider position runs 0..Slider Resolution (register 0x93, datasheet §7.4). This helper reads both and integer-scales the position to 0–100 through `out_pct`. Returns 0 if either read returned an invalid (out-of-window) response, or if the resolution is 0 (no slider configured): `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 on this chip (the surface plus an electrode on pad 8). A single tile surface alone cannot produce a slider output.
- 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
Studiovoid 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.
Events
tile_sense_t_c_process
Studiovoid 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_sense_t_c_on_event
Studiovoid 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.
- cb
- Callback function (NULL to disable)
- ctx
- User context passed to callback
Config
tile_sense_t_c_set_touch_threshold
Studiovoid tile_sense_t_c_set_touch_threshold(tile_t *tile, uint8_t threshold)The touch threshold is relative: a touch registers when the counts drop by threshold/256 of the channel's baseline (A.17). Lower is more sensitive (a touch through thicker covers); higher rejects near misses. Kept by the driver, so it survives a chip reset. 0 is ignored.
- threshold
- [1..255] x/256 of the LTA (default 40, about 16 %)
tile_sense_t_c_set_prox_threshold
Studiovoid tile_sense_t_c_set_prox_threshold(tile_t *tile, uint8_t threshold)Proximity is an absolute drop in counts (A.16), written with Azoteq's 4/4 debounce. Lower detects a hand from further away. Kept by the driver, so it survives a chip reset. 0 is ignored.
- threshold
- [1..255] delta counts (default 20)
tile_sense_t_c_set_power_mode
Studiovoid tile_sense_t_c_set_power_mode(tile_t *tile, sense_t_c_power_mode_t mode)AUTO steps from normal to low and ultra-low power after the power timeout without activity, and back on a touch (datasheet §5.3). Typical draw (3 self-cap channels, EV-kit rates): normal 125 µA, low 37.5 µA, ultra-low 4 µA, halt 2 µA. Values above 5 are ignored.
- mode
- Power mode (System Control bits 6-4); init selects AUTO
tile_sense_t_c_enable_events
Studiovoid tile_sense_t_c_enable_events(tile_t *tile, uint16_t mask)Set the events-enable mask (which events drive RDY pulses).
- mask
- Event bits (IQS323_STATUS_*_EVENT); init enables touch + prox
tile_sense_t_c_ati
Studiovoid 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
Studiovoid 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.
- channel
- 0–2
- value
- Raw 16-bit ATI Setup register value
tile_sense_t_c_set_counts_filter
Studiovoid 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.
- beta
- Raw 16-bit Counts Filter Betas register value
tile_sense_t_c_set_conversion_freq
Studiovoid 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.
- channel
- 0–2
- value
- Raw 16-bit Conversion Frequency register value
tile_sense_t_c_set_channel_mode
Studiovoid 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.
- channel
- 0–2
- mode
- Channel role
- reference_id
- Which channel to follow (only used for FOLLOWER)
tile_sense_t_c_set_comm_mode
Studiovoid tile_sense_t_c_set_comm_mode(tile_t *tile, sense_t_c_comm_mode_t mode)Event mode opens a communication window (RDY low) only for an enabled event (touch or prox change, a reset); lowest power, lowest CPU overhead. init() selects event mode. Streaming mode opens one every report cycle; the chip then waits up to the I2C timeout (200 ms) for the host each time, so use it only with the RDY pin and a host that services every window (continuous logging of counts).
- mode
- Event or streaming
tile_sense_t_c_set_report_rate
Studiovoid 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. init() writes Azoteq's EV-kit values, NP 16 ms, LP 60 ms, ULP 160 ms, Halt 3000 ms (the chip's reset value is 0 for all four). These are lost if the chip resets; process() restores the defaults.
- 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
Studiovoid 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. init() writes Azoteq's EV-kit 2000 ms (the chip's reset value is 0).
- ms
- [0..65000] Inactivity timeout in milliseconds (0 = off).
Advanced
tile_sense_t_c_read_reg
Studiouint16_t tile_sense_t_c_read_reg(tile_t *tile, uint8_t reg)Read a raw 16-bit IQS323 register.
- reg
- [0..255] Register address (datasheet §9 memory map)
Returns Register value, 0xEEEE if no comms window opened
tile_sense_t_c_write_reg
Studiovoid tile_sense_t_c_write_reg(tile_t *tile, uint8_t reg, uint16_t value)Write a raw 16-bit IQS323 register.
- reg
- [0..255] Register address (datasheet §9 memory map)
- value
- 16-bit value
tile_sense_t_c_get_compensation
Studiouint16_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.
- channel
- 0-2.
Returns Raw 16-bit compensation register, or 0 on a bad channel.
tile_sense_t_c_set_compensation
Studiovoid 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.
- channel
- 0-2.
- value
- Compensation value (0-1023).
- divider
- Compensation divider (0-31).
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 (the chip's reset default)
- SENSE_T_C_COMM_EVENT
- RDY pulses only on enabled events (what init() selects)
Constants
| TILE_SENSE_T_C_VERSION_MAJOR | 1 | |
| TILE_SENSE_T_C_VERSION_MINOR | 4 | |
| TILE_SENSE_T_C_VERSION_PATCH | 0 | |
| IQS323_I2C_ADDR_001 | 0x44 | |
| IQS323_I2C_ADDR_002 | 0x58 | |
| SENSE_T_C_CH0 | 0 | CRx0/CTx0 -- pad 8 (external) |
| SENSE_T_C_CH1 | 1 | CRx1/CTx1 -- tile top surface |
| SENSE_T_C_CH2 | 2 | CRx2/CTx2 -- not routed on this tile; always disabled |
| SENSE_T_C_NUM_CHANNELS | 3 | |
| IQS323_STATUS_POWER_SHIFT | 14 | |
| IQS323_EVENTS_DEFINED | 0x005F | |
| IQS323_INVALID_RESPONSE | 0xEEEE | |
| IQS323_CTRL_POWER_SHIFT | 4 | |
| IQS323_HW_ID_3DD | 0xF003 | |
| IQS323_HW_ID_3ED | 0xF004 |

