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
Studiovoid tile_sense_t_c_sleep(tile_t *tile)Enter low-power sleep mode.
tile_sense_t_c_wake
Studiovoid tile_sense_t_c_wake(tile_t *tile)Wake from sleep mode.
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 cached Gesture Status word from the last process() call.
tile_sense_t_c_is_touched
Studiouint8_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
Studiouint8_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
Studiouint16_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
Studiouint16_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
Studioint16_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
Studiouint16_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
Studiovoid 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
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.
- tile
- Initialised tile handle
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.
- 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
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.
- 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
Studiouint8_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
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.
- tile
- Initialised tile handle.
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
- Tile handle
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.
- tile
- Tile handle
- cb
- Callback function (NULL to disable)
- ctx
- User context passed to callback
Config
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)Set the device power mode.
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).
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.
- tile
- Initialised tile handle
- 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.
- tile
- Initialised tile handle
- 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.
- tile
- Initialised tile handle
- 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.
- 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
Studiovoid 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
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.
- 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
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.
- tile
- Initialised tile handle.
- ms
- Inactivity timeout in milliseconds (0-65000, 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.
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.
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.
- 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
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.
- tile
- Initialised tile handle.
- 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
- SENSE_T_C_COMM_EVENT
- RDY pulses only on enabled events (default)
Constants
| TILE_SENSE_T_C_VERSION_MAJOR | 1 | |
| TILE_SENSE_T_C_VERSION_MINOR | 3 | |
| 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/Bias |
| SENSE_T_C_NUM_CHANNELS | 3 | |
| IQS323_STATUS_POWER_SHIFT | 14 | |
| IQS323_INVALID_RESPONSE | 0xEEEE | |
| IQS323_CTRL_POWER_SHIFT | 4 | |
| IQS323_HW_ID_3DD | 0xF003 | |
| IQS323_HW_ID_3ED | 0xF004 |

