Skip to content

Commit a167c2d

Browse files
jeremydickkartben
authored andcommitted
drivers: input: cap12xx Add properties for sensitivity and guard signal
The Microchip CAP12xx series has a configurable sensitivity and can drive an optional guard signal to reduce noise sensitivity. Signed-off-by: Jeremy Dick <jdick@pivotint.com>
1 parent 6ec7908 commit a167c2d

File tree

3 files changed

+194
-39
lines changed

3 files changed

+194
-39
lines changed

drivers/input/input_cap12xx.c

Lines changed: 140 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,23 @@
1010
#include <zephyr/drivers/gpio.h>
1111
#include <zephyr/input/input.h>
1212
#include <zephyr/logging/log.h>
13+
#include <zephyr/math/ilog2.h>
1314
LOG_MODULE_REGISTER(cap12xx, CONFIG_INPUT_LOG_LEVEL);
1415

15-
#define REG_MAIN_CONTROL 0x00
16-
#define CONTROL_INT 0x01
16+
#define REG_MAIN_CONTROL 0x00
17+
#define MAIN_CONTROL_GAIN_MASK GENMASK(7, 6)
18+
#define MAIN_CONTROL_GAIN_SHIFT 6
19+
20+
#define CONTROL_INT 0x01
1721

1822
#define REG_INPUT_STATUS 0x03
1923

24+
#define REG_SENSITIVITY_CONTROL 0x1F
25+
#define DELTA_SENSE_BITS 3
26+
#define DELTA_SENSE_SHIFT 4
27+
#define DELTA_SENSE_MASK GENMASK(6, 4)
28+
#define DELTA_SENSE_MAX GENMASK(DELTA_SENSE_BITS - 1, 0)
29+
2030
#define REG_INTERRUPT_ENABLE 0x27
2131
#define INTERRUPT_ENABLE 0xFF
2232
#define INTERRUPT_DISABLE 0x00
@@ -25,13 +35,24 @@ LOG_MODULE_REGISTER(cap12xx, CONFIG_INPUT_LOG_LEVEL);
2535
#define REPEAT_ENABLE 0xFF
2636
#define REPEAT_DISABLE 0x00
2737

38+
#define REG_SIGNAL_GUARD_ENABLE 0x29
39+
40+
#define REG_CALIB_SENSITIVITY_CONFIG1 0x80
41+
#define REG_CALIB_SENSITIVITY_CONFIG2 0x81
42+
#define CALSENS_BITS 2
43+
#define NUM_CALSENS_PER_REG 4
44+
2845
struct cap12xx_config {
2946
struct i2c_dt_spec i2c;
3047
const uint8_t input_channels;
3148
const uint16_t *input_codes;
3249
struct gpio_dt_spec *int_gpio;
3350
bool repeat;
3451
const uint16_t poll_interval_ms;
52+
const uint8_t sensor_gain;
53+
const uint8_t sensitivity_delta_sense;
54+
const uint8_t *signal_guard;
55+
const uint8_t *calib_sensitivity;
3556
};
3657

3758
struct cap12xx_data {
@@ -45,11 +66,11 @@ struct cap12xx_data {
4566
static int cap12xx_clear_interrupt(const struct i2c_dt_spec *i2c)
4667
{
4768
uint8_t ctrl;
48-
int r;
69+
int ret;
4970

50-
r = i2c_reg_read_byte_dt(i2c, REG_MAIN_CONTROL, &ctrl);
51-
if (r < 0) {
52-
return r;
71+
ret = i2c_reg_read_byte_dt(i2c, REG_MAIN_CONTROL, &ctrl);
72+
if (ret < 0) {
73+
return ret;
5374
}
5475

5576
ctrl = ctrl & ~CONTROL_INT;
@@ -63,25 +84,65 @@ static int cap12xx_enable_interrupt(const struct i2c_dt_spec *i2c, bool enable)
6384
return i2c_reg_write_byte_dt(i2c, REG_INTERRUPT_ENABLE, intr);
6485
}
6586

87+
static int cap12xx_set_sensor_gain(const struct i2c_dt_spec *i2c, uint8_t gain)
88+
{
89+
uint8_t regval = gain << MAIN_CONTROL_GAIN_SHIFT;
90+
91+
return i2c_reg_update_byte_dt(i2c, REG_MAIN_CONTROL, MAIN_CONTROL_GAIN_MASK, regval);
92+
}
93+
94+
static int cap12xx_set_sensitivity(const struct i2c_dt_spec *i2c, uint8_t sensitivity)
95+
{
96+
uint8_t regval = sensitivity << DELTA_SENSE_SHIFT;
97+
98+
return i2c_reg_update_byte_dt(i2c, REG_SENSITIVITY_CONTROL, DELTA_SENSE_MASK, regval);
99+
}
100+
101+
static int cap12xx_set_calsens(const struct i2c_dt_spec *i2c, const uint8_t *calsens,
102+
uint8_t channels)
103+
{
104+
int ret;
105+
uint8_t regval;
106+
107+
for (uint8_t i = 0; i < channels; i += NUM_CALSENS_PER_REG) {
108+
regval = 0;
109+
for (uint8_t j = 0; j < NUM_CALSENS_PER_REG && i + j < channels; j++) {
110+
/* Convert the enumerated sensitivity to the corresponding register value */
111+
regval |= (ilog2(calsens[i + j]) << (CALSENS_BITS * j));
112+
}
113+
if (i == 0) {
114+
ret = i2c_reg_write_byte_dt(i2c, REG_CALIB_SENSITIVITY_CONFIG1, regval);
115+
} else {
116+
ret = i2c_reg_write_byte_dt(i2c, REG_CALIB_SENSITIVITY_CONFIG2, regval);
117+
}
118+
119+
if (ret) {
120+
return ret;
121+
}
122+
}
123+
124+
return 0;
125+
}
126+
66127
static int cap12xx_process(const struct device *dev)
67128
{
68129
const struct cap12xx_config *config = dev->config;
69130
struct cap12xx_data *data = dev->data;
70-
int r;
131+
int ret;
71132
uint8_t input_state;
72133

73134
/*
74135
* Clear INT bit to clear SENSOR INPUT STATUS bits.
75136
* Note that this is also required in polling mode.
76137
*/
77-
r = cap12xx_clear_interrupt(&config->i2c);
138+
ret = cap12xx_clear_interrupt(&config->i2c);
78139

79-
if (r < 0) {
80-
return r;
140+
if (ret < 0) {
141+
return ret;
81142
}
82-
r = i2c_reg_read_byte_dt(&config->i2c, REG_INPUT_STATUS, &input_state);
83-
if (r < 0) {
84-
return r;
143+
ret = i2c_reg_read_byte_dt(&config->i2c, REG_INPUT_STATUS, &input_state);
144+
if (ret < 0) {
145+
return ret;
85146
}
86147

87148
if (config->int_gpio == NULL) {
@@ -129,7 +190,8 @@ static int cap12xx_init(const struct device *dev)
129190
{
130191
const struct cap12xx_config *config = dev->config;
131192
struct cap12xx_data *data = dev->data;
132-
int r;
193+
uint8_t guarded_channels = 0;
194+
int ret;
133195

134196
if (!device_is_ready(config->i2c.bus)) {
135197
LOG_ERR("I2C controller device not ready");
@@ -140,13 +202,43 @@ static int cap12xx_init(const struct device *dev)
140202

141203
k_work_init(&data->work, cap12xx_work_handler);
142204

205+
for (uint8_t i = 0; i < config->input_channels; i++) {
206+
if (config->signal_guard[i]) {
207+
guarded_channels |= BIT(i);
208+
}
209+
}
210+
ret = i2c_reg_write_byte_dt(&config->i2c, REG_SIGNAL_GUARD_ENABLE, guarded_channels);
211+
if (ret < 0) {
212+
LOG_ERR("Could not set guarded channels");
213+
return ret;
214+
}
215+
ret = cap12xx_set_calsens(&config->i2c, config->calib_sensitivity, config->input_channels);
216+
if (ret < 0) {
217+
LOG_ERR("Could not set calibration sensitivities");
218+
return ret;
219+
}
220+
/* Convert the enumerated gain to the corresponding register value */
221+
ret = cap12xx_set_sensor_gain(&config->i2c, ilog2(config->sensor_gain));
222+
if (ret < 0) {
223+
LOG_ERR("Could not set analog gain");
224+
return ret;
225+
}
226+
/* Convert the enumerated sensitivity to the corresponding register value,
227+
* which is in reverse order
228+
*/
229+
ret = cap12xx_set_sensitivity(&config->i2c,
230+
DELTA_SENSE_MAX - ilog2(config->sensitivity_delta_sense));
231+
if (ret < 0) {
232+
LOG_ERR("Could not set sensitivity");
233+
return ret;
234+
}
143235
if (config->int_gpio == NULL) {
144236
LOG_DBG("cap12xx driver in polling mode");
145237
k_timer_init(&data->poll_timer, cap12xx_timer_handler, NULL);
146-
r = cap12xx_enable_interrupt(&config->i2c, true);
147-
if (r < 0) {
238+
ret = cap12xx_enable_interrupt(&config->i2c, true);
239+
if (ret < 0) {
148240
LOG_ERR("Could not configure interrupt");
149-
return r;
241+
return ret;
150242
}
151243
k_timer_start(&data->poll_timer, K_MSEC(config->poll_interval_ms),
152244
K_MSEC(config->poll_interval_ms));
@@ -158,49 +250,50 @@ static int cap12xx_init(const struct device *dev)
158250
return -ENODEV;
159251
}
160252

161-
r = gpio_pin_configure_dt(config->int_gpio, GPIO_INPUT);
162-
if (r < 0) {
253+
ret = gpio_pin_configure_dt(config->int_gpio, GPIO_INPUT);
254+
if (ret < 0) {
163255
LOG_ERR("Could not configure interrupt GPIO pin");
164-
return r;
256+
return ret;
165257
}
166258

167-
r = gpio_pin_interrupt_configure_dt(config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE);
168-
if (r < 0) {
259+
ret = gpio_pin_interrupt_configure_dt(config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE);
260+
if (ret < 0) {
169261
LOG_ERR("Could not configure interrupt GPIO interrupt");
170-
return r;
262+
return ret;
171263
}
172264

173265
gpio_init_callback(&data->int_gpio_cb, cap12xx_isr_handler,
174266
BIT(config->int_gpio->pin));
175267

176-
r = gpio_add_callback_dt(config->int_gpio, &data->int_gpio_cb);
177-
if (r < 0) {
268+
ret = gpio_add_callback_dt(config->int_gpio, &data->int_gpio_cb);
269+
if (ret < 0) {
178270
LOG_ERR("Could not set gpio callback");
179-
return r;
271+
return ret;
180272
}
181273

182-
r = cap12xx_clear_interrupt(&config->i2c);
183-
if (r < 0) {
274+
ret = cap12xx_clear_interrupt(&config->i2c);
275+
if (ret < 0) {
184276
LOG_ERR("Could not clear interrupt");
185-
return r;
277+
return ret;
186278
}
187-
r = cap12xx_enable_interrupt(&config->i2c, true);
188-
if (r < 0) {
279+
ret = cap12xx_enable_interrupt(&config->i2c, true);
280+
if (ret < 0) {
189281
LOG_ERR("Could not configure interrupt");
190-
return r;
282+
return ret;
191283
}
192284
if (config->repeat) {
193-
r = i2c_reg_write_byte_dt(&config->i2c, REG_REPEAT_ENABLE, REPEAT_ENABLE);
194-
if (r < 0) {
285+
ret = i2c_reg_write_byte_dt(&config->i2c, REG_REPEAT_ENABLE, REPEAT_ENABLE);
286+
if (ret < 0) {
195287
LOG_ERR("Could not disable repeated interrupts");
196-
return r;
288+
return ret;
197289
}
198290
LOG_DBG("cap12xx enabled repeated interrupts");
199291
} else {
200-
r = i2c_reg_write_byte_dt(&config->i2c, REG_REPEAT_ENABLE, REPEAT_DISABLE);
201-
if (r < 0) {
292+
ret = i2c_reg_write_byte_dt(&config->i2c, REG_REPEAT_ENABLE,
293+
REPEAT_DISABLE);
294+
if (ret < 0) {
202295
LOG_ERR("Could not enable repeated interrupts");
203-
return r;
296+
return ret;
204297
}
205298
LOG_DBG("cap12xx disabled repeated interrupts");
206299
}
@@ -214,14 +307,22 @@ static int cap12xx_init(const struct device *dev)
214307
static struct gpio_dt_spec cap12xx_int_gpio_##index = \
215308
GPIO_DT_SPEC_INST_GET(index, int_gpios);)) \
216309
static const uint16_t cap12xx_input_codes_##index[] = DT_INST_PROP(index, input_codes); \
310+
static const uint8_t cap12xx_signal_guard_##index[] = \
311+
DT_INST_PROP(index, signal_guard); \
312+
static const uint8_t cap12xx_calib_sensitivity_##index[] = \
313+
DT_INST_PROP(index, calib_sensitivity); \
217314
static const struct cap12xx_config cap12xx_config_##index = { \
218315
.i2c = I2C_DT_SPEC_INST_GET(index), \
219316
.input_channels = DT_INST_PROP_LEN(index, input_codes), \
220317
.input_codes = cap12xx_input_codes_##index, \
221318
IF_ENABLED(DT_INST_NODE_HAS_PROP(index, int_gpios), ( \
222319
.int_gpio = &cap12xx_int_gpio_##index,)) \
223320
.repeat = DT_INST_PROP(index, repeat), \
224-
.poll_interval_ms = DT_INST_PROP_OR(index, poll_interval_ms, 10)}; \
321+
.poll_interval_ms = DT_INST_PROP(index, poll_interval_ms), \
322+
.sensor_gain = DT_INST_PROP(index, sensor_gain), \
323+
.sensitivity_delta_sense = DT_INST_PROP(index, sensitivity_delta_sense), \
324+
.signal_guard = cap12xx_signal_guard_##index, \
325+
.calib_sensitivity = cap12xx_calib_sensitivity_##index}; \
225326
static struct cap12xx_data cap12xx_data_##index; \
226327
DEVICE_DT_INST_DEFINE(index, cap12xx_init, NULL, &cap12xx_data_##index, \
227328
&cap12xx_config_##index, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \

dts/bindings/input/microchip,cap12xx.yaml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ properties:
2020
2121
poll-interval-ms:
2222
type: int
23+
default: 10
2324
description: |
2425
Polling interval in ms when not using interrupt mode.
2526
@@ -28,3 +29,52 @@ properties:
2829
required: true
2930
description: |
3031
Array of input event key codes (INPUT_KEY_* or INPUT_BTN_*).
32+
33+
sensor-gain:
34+
type: int
35+
enum:
36+
- 1
37+
- 2
38+
- 4
39+
- 8
40+
default: 1
41+
description: |
42+
Defines the gain of the sensor circuitry. This
43+
effectively controls the sensitivity, as a
44+
smaller delta capacitance is required to
45+
generate the same delta count values.
46+
47+
sensitivity-delta-sense:
48+
type: int
49+
enum: [1, 2, 4, 8, 16, 32, 64, 128]
50+
default: 32
51+
description:
52+
Controls the sensitivity multiplier of a touch detection.
53+
Higher value means more sensitive settings.
54+
At the more sensitive settings, touches are detected for a smaller delta
55+
capacitance corresponding to a "lighter" touch.
56+
57+
signal-guard:
58+
type: array
59+
enum: [0, 1]
60+
default: [0, 0, 0]
61+
description: |
62+
0 - off
63+
1 - on
64+
The signal guard isolates the signal from virtual grounds.
65+
If enabled then the behavior of the channel is changed to signal guard.
66+
The number of entries must correspond to the number of channels.
67+
68+
calib-sensitivity:
69+
type: array
70+
enum: [1, 2, 4]
71+
default: [1, 1, 1]
72+
description: |
73+
Specifies an array of numeric values that controls the gain
74+
used by the calibration routine to enable sensor inputs
75+
to be more sensitive for proximity detection.
76+
Gain is based on touch pad capacitance range
77+
1 - 5-50pF
78+
2 - 0-25pF
79+
4 - 0-12.5pF
80+
The number of entries must correspond to the number of channels.

tests/drivers/build_all/input/app.overlay

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,10 @@
215215
reg = <0x3>;
216216
int-gpios = <&test_gpio 0 0>;
217217
input-codes = <0 1 2>;
218+
sensor-gain = <1>;
219+
sensitivity-delta-sense = <32>;
220+
signal-guard = <0 0 0>;
221+
calib-sensitivity = <1 1 1>;
218222
};
219223

220224
stmpe811@4 {

0 commit comments

Comments
 (0)