Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions drivers/sensor/apds9960/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,20 @@ config APDS9960_PPULSE_COUNT
range 1 64
default 8

config APDS9960_ENABLE_GESTURE
bool "Gesture Sense"
default n
help
Enable Gesture Sense.

config APDS9960_GESTURE_PROXIMITY
int "Gesture Proximity Enter Threshold"
range 0 255
default 40

config APDS9960_GESTURE_DIFFERENCE
int "Minimum IR diode difference for gesture"
range 0 255
default 5

endif # APDS9960
176 changes: 166 additions & 10 deletions drivers/sensor/apds9960/apds9960.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <string.h>
#include <zephyr/logging/log.h>

#include "apds9960.h"
#include <zephyr/drivers/sensor/apds9960.h>

LOG_MODULE_REGISTER(APDS9960, CONFIG_SENSOR_LOG_LEVEL);

Expand All @@ -48,6 +48,112 @@ static void apds9960_gpio_callback(const struct device *dev,
}
#endif

#if CONFIG_APDS9960_ENABLE_GESTURE
static int apds9960_gesture_fetch(const struct device *dev)
{
const struct apds9960_config *config = dev->config;
struct apds9960_data *data = dev->data;

uint8_t gesture_fifo_cnt;
uint8_t gstatus;
uint8_t gesture_fifo[4];
int tmp_up;
int tmp_left;
int net_up = 0;
int net_left = 0;

bool up_trig = false;
bool down_trig = false;
bool left_trig = false;
bool right_trig = false;

data->gesture = APDS9960_GESTURE_NONE;

if (i2c_reg_read_byte_dt(&config->i2c,
APDS9960_GSTATUS_REG, &gstatus)) {
return -EIO;
}

while (gstatus & APDS9960_GSTATUS_GVALID) {
if (i2c_reg_read_byte_dt(&config->i2c,
APDS9960_GFLVL_REG, &gesture_fifo_cnt)) {
return -EIO;
}

for (int i = 0; i < gesture_fifo_cnt; ++i) {
/* Read up fifo and adjacent registers */
if (i2c_burst_read_dt(&config->i2c,
APDS9960_GFIFO_U_REG,
(uint8_t *) gesture_fifo,
4)) {
return -EIO;
}

tmp_up = (int) gesture_fifo[0] - (int) gesture_fifo[1];
tmp_left = (int) gesture_fifo[2] - (int) gesture_fifo[3];

if (abs(tmp_up) > CONFIG_APDS9960_GESTURE_DIFFERENCE) {
net_up = tmp_up;
}
if (abs(tmp_left) > CONFIG_APDS9960_GESTURE_DIFFERENCE) {
net_left = tmp_left;
}

if (net_up > 0) {
if (down_trig) {
data->gesture = APDS9960_GESTURE_DOWN;
up_trig = false;
down_trig = false;
left_trig = false;
right_trig = false;
} else {
up_trig = true;
}
} else if (net_up < 0) {
if (up_trig) {
data->gesture = APDS9960_GESTURE_UP;
up_trig = false;
down_trig = false;
left_trig = false;
right_trig = false;
} else {
down_trig = true;
}
}
if (net_left > 0) {
if (right_trig) {
data->gesture = APDS9960_GESTURE_RIGHT;
up_trig = false;
down_trig = false;
left_trig = false;
right_trig = false;
} else {
left_trig = true;
}
} else if (net_left < 0) {
if (left_trig) {
data->gesture = APDS9960_GESTURE_LEFT;
up_trig = false;
down_trig = false;
left_trig = false;
right_trig = false;
} else {
right_trig = true;
}
}
}

if (i2c_reg_read_byte_dt(&config->i2c,
APDS9960_GSTATUS_REG, &gstatus)) {
return -EIO;
}
}
LOG_DBG("Net up: 0x%x, Net left: 0x%x", net_up, net_left);

return 0;
}
#endif

static int apds9960_sample_fetch(const struct device *dev,
enum sensor_channel chan)
{
Expand All @@ -63,6 +169,12 @@ static int apds9960_sample_fetch(const struct device *dev,
return -ENOTSUP;
}

#ifdef CONFIG_APDS9960_ENABLE_GESTURE
if (apds9960_gesture_fetch(dev)) {
return -EIO;
}
#endif

#ifndef CONFIG_APDS9960_TRIGGER
#ifdef CONFIG_APDS9960_FETCH_MODE_INTERRUPT
apds9960_setup_int(config, true);
Expand Down Expand Up @@ -90,16 +202,9 @@ static int apds9960_sample_fetch(const struct device *dev,
start_time = k_uptime_get();
#ifdef CONFIG_APDS9960_ENABLE_ALS
while (!(tmp & APDS9960_STATUS_AINT)) {
k_sleep(K_MSEC(APDS9960_DEFAULT_WAIT_TIME));
if (i2c_reg_read_byte_dt(&config->i2c, APDS9960_STATUS_REG, &tmp)) {
return -EIO;
}
if ((k_uptime_get() - start_time) > APDS9960_MAX_WAIT_TIME) {
return -ETIMEDOUT;
}
}
#else
while (!(tmp & APDS9960_STATUS_PINT)) {
#endif
k_sleep(K_MSEC(APDS9960_DEFAULT_WAIT_TIME));
if (i2c_reg_read_byte_dt(&config->i2c, APDS9960_STATUS_REG, &tmp)) {
return -EIO;
Expand All @@ -108,7 +213,6 @@ static int apds9960_sample_fetch(const struct device *dev,
return -ETIMEDOUT;
}
}
#endif
#endif

LOG_DBG("status: 0x%x", tmp);
Expand Down Expand Up @@ -172,6 +276,12 @@ static int apds9960_channel_get(const struct device *dev,
val->val1 = sys_le16_to_cpu(data->sample_crgb[3]);
val->val2 = 0;
break;
#endif
#ifdef CONFIG_APDS9960_ENABLE_GESTURE
case SENSOR_CHAN_APDS9960_GESTURE:
val->val1 = data->gesture;
val->val2 = 0;
break;
#endif
case SENSOR_CHAN_PROX:
val->val1 = data->pdata;
Expand Down Expand Up @@ -304,6 +414,45 @@ static int apds9960_ambient_setup(const struct device *dev)
}
#endif

#ifdef CONFIG_APDS9960_ENABLE_GESTURE
static int apds9960_gesture_setup(const struct device *dev)
{
const struct apds9960_config *config = dev->config;

if (i2c_reg_write_byte_dt(&config->i2c,
APDS9960_GPENTH_REG, CONFIG_APDS9960_GESTURE_PROXIMITY)) {
LOG_ERR("Gesture proximity enter not set.");
return -EIO;
}
if (i2c_reg_write_byte_dt(&config->i2c,
APDS9960_GEXTH_REG, CONFIG_APDS9960_GESTURE_PROXIMITY)) {
LOG_ERR("Gesture interrupt not set.");
return -EIO;
}
if (i2c_reg_write_byte_dt(&config->i2c,
APDS9960_GCONFIG1_REG, 0)) {
LOG_ERR("Gesture interrupt not set.");
return -EIO;
}
if (i2c_reg_write_byte_dt(&config->i2c,
APDS9960_GCONFIG2_REG, APDS9960_GGAIN_4X)) {
LOG_ERR("Gesture interrupt not set.");
return -EIO;
}
if (i2c_reg_write_byte_dt(&config->i2c,
APDS9960_GCONFIG4_REG, 0)) {
LOG_ERR("Gesture interrupt not set.");
return -EIO;
}
if (i2c_reg_update_byte_dt(&config->i2c, APDS9960_ENABLE_REG, APDS9960_ENABLE_GEN,
APDS9960_ENABLE_GEN)) {
LOG_ERR("Gesture on bit not set.");
return -EIO;
}
return 0;
}
#endif

static int apds9960_sensor_setup(const struct device *dev)
{
const struct apds9960_config *config = dev->config;
Expand Down Expand Up @@ -385,6 +534,13 @@ static int apds9960_sensor_setup(const struct device *dev)
}
#endif

#ifdef CONFIG_APDS9960_ENABLE_GESTURE
if (apds9960_gesture_setup(dev)) {
LOG_ERR("Failed to setup gesture functionality");
return -EIO;
}
#endif

#ifdef CONFIG_APDS9960_FETCH_MODE_POLL
if (i2c_reg_update_byte_dt(&config->i2c, APDS9960_ENABLE_REG, APDS9960_ENABLE_PON,
APDS9960_ENABLE_PON)) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/sensor/apds9960/apds9960_trigger.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <zephyr/sys/util.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/sensor.h>
#include "apds9960.h"
#include <zephyr/drivers/sensor/apds9960.h>

extern struct apds9960_data apds9960_driver;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define ZEPHYR_DRIVERS_SENSOR_APDS9960_APDS9960_H_

#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/i2c.h>

#define APDS9960_ENABLE_REG 0x80
#define APDS9960_ENABLE_GEN BIT(6)
Expand Down Expand Up @@ -227,12 +228,26 @@ struct apds9960_config {
uint8_t pled_boost;
};

/* apds9960 specific channels */
enum sensor_channel_apds9960 {
SENSOR_CHAN_APDS9960_GESTURE = SENSOR_CHAN_PRIV_START,
};

enum apds9960_gesture {
APDS9960_GESTURE_NONE,
APDS9960_GESTURE_UP,
APDS9960_GESTURE_DOWN,
APDS9960_GESTURE_LEFT,
APDS9960_GESTURE_RIGHT,
};

struct apds9960_data {
struct gpio_callback gpio_cb;
struct k_work work;
const struct device *dev;
uint16_t sample_crgb[4];
uint8_t pdata;
enum apds9960_gesture gesture;

#ifdef CONFIG_APDS9960_TRIGGER
sensor_trigger_handler_t p_th_handler;
Expand Down
2 changes: 2 additions & 0 deletions samples/sensor/apds9960/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ CONFIG_I2C_LOG_LEVEL_INF=y

CONFIG_APDS9960_TRIGGER_GLOBAL_THREAD=n
CONFIG_PM_DEVICE=n

CONFIG_APDS9960_ENABLE_GESTURE=n
16 changes: 13 additions & 3 deletions samples/sensor/apds9960/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <zephyr/kernel.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/sensor/apds9960.h>
#include <zephyr/device.h>
#include <stdio.h>
#include <zephyr/sys/printk.h>
Expand All @@ -24,10 +25,18 @@ static void trigger_handler(const struct device *dev,
}
#endif

char states[5][6] = {
"NONE",
"UP",
"DOWN",
"LEFT",
"RIGHT",
};

int main(void)
{
const struct device *dev;
struct sensor_value intensity, pdata;
struct sensor_value intensity, pdata, gesture;

printk("APDS9960 sample application\n");
dev = DEVICE_DT_GET_ONE(avago_apds9960);
Expand Down Expand Up @@ -72,9 +81,10 @@ int main(void)

sensor_channel_get(dev, SENSOR_CHAN_LIGHT, &intensity);
sensor_channel_get(dev, SENSOR_CHAN_PROX, &pdata);
sensor_channel_get(dev, SENSOR_CHAN_APDS9960_GESTURE, &gesture);

printk("ambient light intensity %d, proximity %d\n",
intensity.val1, pdata.val1);
printk("ambient light intensity %d, proximity %d, gesture %s\n",
intensity.val1, pdata.val1, states[gesture.val1]);

#ifdef CONFIG_PM_DEVICE
pm_device_action_run(dev, PM_DEVICE_ACTION_SUSPEND);
Expand Down