Skip to content

Commit 5db334d

Browse files
committed
drivers: sensor: apds9960: Added gesture detection
Created logic to calculate gestures from the APDS9960 sensor Signed-off-by: Thomas Lang <[email protected]>
1 parent 16034d8 commit 5db334d

File tree

1 file changed

+165
-9
lines changed

1 file changed

+165
-9
lines changed

drivers/sensor/apds9960/apds9960.c

Lines changed: 165 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,112 @@ static void apds9960_gpio_callback(const struct device *dev,
4848
}
4949
#endif
5050

51+
#if CONFIG_APDS9960_ENABLE_GESTURE
52+
static int apds9960_gesture_fetch(const struct device *dev)
53+
{
54+
const struct apds9960_config *config = dev->config;
55+
struct apds9960_data *data = dev->data;
56+
57+
uint8_t gesture_fifo_cnt;
58+
uint8_t gstatus;
59+
uint8_t gesture_fifo[4];
60+
int tmp_up;
61+
int tmp_left;
62+
int net_up = 0;
63+
int net_left = 0;
64+
65+
bool up_trig = false;
66+
bool down_trig = false;
67+
bool left_trig = false;
68+
bool right_trig = false;
69+
70+
data->gesture = APDS9960_GESTURE_NONE;
71+
72+
if (i2c_reg_read_byte_dt(&config->i2c,
73+
APDS9960_GSTATUS_REG, &gstatus)) {
74+
return -EIO;
75+
}
76+
77+
while (gstatus & APDS9960_GSTATUS_GVALID) {
78+
if (i2c_reg_read_byte_dt(&config->i2c,
79+
APDS9960_GFLVL_REG, &gesture_fifo_cnt)) {
80+
return -EIO;
81+
}
82+
83+
for (int i = 0; i < gesture_fifo_cnt; ++i) {
84+
/* Read up fifo and adjacent registers */
85+
if (i2c_burst_read_dt(&config->i2c,
86+
APDS9960_GFIFO_U_REG,
87+
(uint8_t *) gesture_fifo,
88+
4)) {
89+
return -EIO;
90+
}
91+
92+
tmp_up = (int) gesture_fifo[0] - (int) gesture_fifo[1];
93+
tmp_left = (int) gesture_fifo[2] - (int) gesture_fifo[3];
94+
95+
if (abs(tmp_up) > config->gesture_config.ir_difference) {
96+
net_up = tmp_up;
97+
}
98+
if (abs(tmp_left) > config->gesture_config.ir_difference) {
99+
net_left = tmp_left;
100+
}
101+
102+
if (net_up > 0) {
103+
if (down_trig) {
104+
data->gesture = APDS9960_GESTURE_DOWN;
105+
up_trig = false;
106+
down_trig = false;
107+
left_trig = false;
108+
right_trig = false;
109+
} else {
110+
up_trig = true;
111+
}
112+
} else if (net_up < 0) {
113+
if (up_trig) {
114+
data->gesture = APDS9960_GESTURE_UP;
115+
up_trig = false;
116+
down_trig = false;
117+
left_trig = false;
118+
right_trig = false;
119+
} else {
120+
down_trig = true;
121+
}
122+
}
123+
if (net_left > 0) {
124+
if (right_trig) {
125+
data->gesture = APDS9960_GESTURE_RIGHT;
126+
up_trig = false;
127+
down_trig = false;
128+
left_trig = false;
129+
right_trig = false;
130+
} else {
131+
left_trig = true;
132+
}
133+
} else if (net_left < 0) {
134+
if (left_trig) {
135+
data->gesture = APDS9960_GESTURE_LEFT;
136+
up_trig = false;
137+
down_trig = false;
138+
left_trig = false;
139+
right_trig = false;
140+
} else {
141+
right_trig = true;
142+
}
143+
}
144+
}
145+
146+
if (i2c_reg_read_byte_dt(&config->i2c,
147+
APDS9960_GSTATUS_REG, &gstatus)) {
148+
return -EIO;
149+
}
150+
}
151+
LOG_DBG("Net up: 0x%x, Net left: 0x%x", net_up, net_left);
152+
153+
return 0;
154+
}
155+
#endif
156+
51157
static int apds9960_sample_fetch(const struct device *dev,
52158
enum sensor_channel chan)
53159
{
@@ -63,6 +169,12 @@ static int apds9960_sample_fetch(const struct device *dev,
63169
return -ENOTSUP;
64170
}
65171

172+
#ifdef CONFIG_APDS9960_ENABLE_GESTURE
173+
if (apds9960_gesture_fetch(dev)) {
174+
return -EIO;
175+
}
176+
#endif
177+
66178
#ifndef CONFIG_APDS9960_TRIGGER
67179
#ifdef CONFIG_APDS9960_FETCH_MODE_INTERRUPT
68180
apds9960_setup_int(config, true);
@@ -90,16 +202,9 @@ static int apds9960_sample_fetch(const struct device *dev,
90202
start_time = k_uptime_get();
91203
#ifdef CONFIG_APDS9960_ENABLE_ALS
92204
while (!(tmp & APDS9960_STATUS_AINT)) {
93-
k_sleep(K_MSEC(APDS9960_DEFAULT_WAIT_TIME));
94-
if (i2c_reg_read_byte_dt(&config->i2c, APDS9960_STATUS_REG, &tmp)) {
95-
return -EIO;
96-
}
97-
if ((k_uptime_get() - start_time) > APDS9960_MAX_WAIT_TIME) {
98-
return -ETIMEDOUT;
99-
}
100-
}
101205
#else
102206
while (!(tmp & APDS9960_STATUS_PINT)) {
207+
#endif
103208
k_sleep(K_MSEC(APDS9960_DEFAULT_WAIT_TIME));
104209
if (i2c_reg_read_byte_dt(&config->i2c, APDS9960_STATUS_REG, &tmp)) {
105210
return -EIO;
@@ -108,7 +213,6 @@ static int apds9960_sample_fetch(const struct device *dev,
108213
return -ETIMEDOUT;
109214
}
110215
}
111-
#endif
112216
#endif
113217

114218
LOG_DBG("status: 0x%x", tmp);
@@ -172,6 +276,12 @@ static int apds9960_channel_get(const struct device *dev,
172276
val->val1 = sys_le16_to_cpu(data->sample_crgb[3]);
173277
val->val2 = 0;
174278
break;
279+
#endif
280+
#ifdef CONFIG_APDS9960_ENABLE_GESTURE
281+
case SENSOR_CHAN_APDS9960_GESTURE:
282+
val->val1 = data->gesture;
283+
val->val2 = 0;
284+
break;
175285
#endif
176286
case SENSOR_CHAN_PROX:
177287
val->val1 = data->pdata;
@@ -304,6 +414,45 @@ static int apds9960_ambient_setup(const struct device *dev)
304414
}
305415
#endif
306416

417+
#ifdef CONFIG_APDS9960_ENABLE_GESTURE
418+
static int apds9960_gesture_setup(const struct device *dev)
419+
{
420+
const struct apds9960_config *config = dev->config;
421+
422+
if (i2c_reg_write_byte_dt(&config->i2c,
423+
APDS9960_GPENTH_REG, config->gesture_config.proximity)) {
424+
LOG_ERR("Gesture proximity enter not set.");
425+
return -EIO;
426+
}
427+
if (i2c_reg_write_byte_dt(&config->i2c,
428+
APDS9960_GEXTH_REG, config->gesture_config.proximity)) {
429+
LOG_ERR("Gesture proximity exit not set.");
430+
return -EIO;
431+
}
432+
if (i2c_reg_write_byte_dt(&config->i2c,
433+
APDS9960_GCONFIG1_REG, 0)) {
434+
LOG_ERR("Gesture config 1 not set.");
435+
return -EIO;
436+
}
437+
if (i2c_reg_write_byte_dt(&config->i2c,
438+
APDS9960_GCONFIG2_REG, APDS9960_GGAIN_4X)) {
439+
LOG_ERR("Gesture config 2 not set.");
440+
return -EIO;
441+
}
442+
if (i2c_reg_write_byte_dt(&config->i2c,
443+
APDS9960_GCONFIG4_REG, 0)) {
444+
LOG_ERR("Gesture config 4 not set.");
445+
return -EIO;
446+
}
447+
if (i2c_reg_update_byte_dt(&config->i2c, APDS9960_ENABLE_REG, APDS9960_ENABLE_GEN,
448+
APDS9960_ENABLE_GEN)) {
449+
LOG_ERR("Gesture on bit not set.");
450+
return -EIO;
451+
}
452+
return 0;
453+
}
454+
#endif
455+
307456
static int apds9960_sensor_setup(const struct device *dev)
308457
{
309458
const struct apds9960_config *config = dev->config;
@@ -385,6 +534,13 @@ static int apds9960_sensor_setup(const struct device *dev)
385534
}
386535
#endif
387536

537+
#ifdef CONFIG_APDS9960_ENABLE_GESTURE
538+
if (apds9960_gesture_setup(dev)) {
539+
LOG_ERR("Failed to setup gesture functionality");
540+
return -EIO;
541+
}
542+
#endif
543+
388544
#ifdef CONFIG_APDS9960_FETCH_MODE_POLL
389545
if (i2c_reg_update_byte_dt(&config->i2c, APDS9960_ENABLE_REG, APDS9960_ENABLE_PON,
390546
APDS9960_ENABLE_PON)) {

0 commit comments

Comments
 (0)