diff --git a/samples/sensor/paj7620_gesture/CMakeLists.txt b/samples/sensor/paj7620_gesture/CMakeLists.txt new file mode 100644 index 00000000000..c1f0bfcb580 --- /dev/null +++ b/samples/sensor/paj7620_gesture/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2025 Paul Timke +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(paj7620_gesture) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/sensor/paj7620_gesture/Kconfig b/samples/sensor/paj7620_gesture/Kconfig new file mode 100644 index 00000000000..b977690ddf3 --- /dev/null +++ b/samples/sensor/paj7620_gesture/Kconfig @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Paul Timke +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "PAJ7620 sample application" + +config APP_USE_POLLING + bool "Select y to use polling, otherwise the sample will use triggers" + default y + +source "Kconfig.zephyr" diff --git a/samples/sensor/paj7620_gesture/README.rst b/samples/sensor/paj7620_gesture/README.rst new file mode 100644 index 00000000000..788e7561888 --- /dev/null +++ b/samples/sensor/paj7620_gesture/README.rst @@ -0,0 +1,41 @@ +.. zephyr:code-sample:: paj7620_gesture + :name: PAJ7620 Gesture Sensor + :relevant-api: sensor_interface + + Get hand gesture data from PAJ7620 sensor. + +Overview +******** + +This sample application gets the output of a gesture sensor (paj7620) using either polling or +triggers (depending on CONFIG_APP_USE_POLLING) and outputs the corresponding gesture to the +console, each time one is detected. + +Requirements +************ + +To use this sample, the following hardware is required: + +* A board with I2C support and GPIO to detect external interrutps +* PAJ7620 sensor + +Building and Running +******************** + +This sample outputs data to the console. It requires a PAJ7620 sensor. + +.. zephyr-app-commands:: + :zephyr-app: samples/sensor/paj7620_gesture + :board: nucleo_f334r8 + :goals: build + :compact: + +Sample Output +============= + +.. code-block:: console + + Gesture LEFT + Gesture RIGHT + Gesture UP + Gesture DOWN diff --git a/samples/sensor/paj7620_gesture/boards/nucleo_f334r8.overlay b/samples/sensor/paj7620_gesture/boards/nucleo_f334r8.overlay new file mode 100644 index 00000000000..0e67fa6a052 --- /dev/null +++ b/samples/sensor/paj7620_gesture/boards/nucleo_f334r8.overlay @@ -0,0 +1,13 @@ +&gpioa { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + + paj7620: paj7620@73 { + compatible = "pixart,paj7620"; + reg = <0x73>; + int-gpios = <&gpioa 9 (GPIO_PULL_UP)>; + }; +}; diff --git a/samples/sensor/paj7620_gesture/prj.conf b/samples/sensor/paj7620_gesture/prj.conf new file mode 100644 index 00000000000..845bcc219b1 --- /dev/null +++ b/samples/sensor/paj7620_gesture/prj.conf @@ -0,0 +1,5 @@ +CONFIG_GPIO=y +CONFIG_STDOUT_CONSOLE=y +CONFIG_I2C=y +CONFIG_SENSOR=y +CONFIG_PAJ7620_TRIGGER_OWN_THREAD=y diff --git a/samples/sensor/paj7620_gesture/sample.yaml b/samples/sensor/paj7620_gesture/sample.yaml new file mode 100644 index 00000000000..33ee9743178 --- /dev/null +++ b/samples/sensor/paj7620_gesture/sample.yaml @@ -0,0 +1,17 @@ +sample: + name: PAJ7620 gesture trigger sample +tests: + sample.sensor.paj7620_gesture_trig: + build_only: true + tags: sensors + platform_allow: nucleo_f334r8 + depends_on: + - i2c + - gpio + filter: dt_compat_enabled("pixart,paj7620") + sample.sensor.paj7620_gesture_polling: + build_only: true + tags: sensors + platform_allow: nucleo_f334r8 + depends_on: i2c + filter: dt_compat_enabled("pixart,paj7620") diff --git a/samples/sensor/paj7620_gesture/src/main.c b/samples/sensor/paj7620_gesture/src/main.c new file mode 100644 index 00000000000..c0dbdc735c2 --- /dev/null +++ b/samples/sensor/paj7620_gesture/src/main.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2025 Paul Timke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#define GESTURE_POLL_TIME_MS 100 + +K_SEM_DEFINE(sem, 0, 1); /* starts off "not available" */ + +static void trigger_handler(const struct device *dev, const struct sensor_trigger *trigger) +{ + ARG_UNUSED(trigger); + + if (sensor_sample_fetch(dev) < 0) { + printf("sensor_sample_fetch failed\n"); + return; + } + + k_sem_give(&sem); +} + +static void print_hand_gesture(uint16_t gest_flags) +{ + if ((gest_flags & PAJ7620_FLAG_GES_UP) != 0) { + printf("Gesture UP\n"); + } + if ((gest_flags & PAJ7620_FLAG_GES_DOWN) != 0) { + printf("Gesture DOWN\n"); + } + if ((gest_flags & PAJ7620_FLAG_GES_LEFT) != 0) { + printf("Gesture LEFT\n"); + } + if ((gest_flags & PAJ7620_FLAG_GES_RIGHT) != 0) { + printf("Gesture RIGHT\n"); + } + if ((gest_flags & PAJ7620_FLAG_GES_FORWARD) != 0) { + printf("Gesture FORWARD\n"); + } + if ((gest_flags & PAJ7620_FLAG_GES_BACKWARD) != 0) { + printf("Gesture BACKWARD\n"); + } + if ((gest_flags & PAJ7620_FLAG_GES_CLOCKWISE) != 0) { + printf("Gesture CLOCKWISE\n"); + } + if ((gest_flags & PAJ7620_FLAG_GES_COUNTERCLOCKWISE) != 0) { + printf("Gesture COUNTER CLOCKWISE\n"); + } +} + +static void trigger_main_loop(const struct device *dev) +{ + struct sensor_value data; + + while (1) { + k_sem_take(&sem, K_FOREVER); + + (void)sensor_channel_get(dev, (enum sensor_channel)SENSOR_CHAN_PAJ7620_GESTURES, + &data); + + print_hand_gesture(data.val1); + } +} + +static void polling_main_loop(const struct device *dev) +{ + struct sensor_value data; + + while (1) { + (void)sensor_sample_fetch(dev); + (void)sensor_channel_get(dev, (enum sensor_channel)SENSOR_CHAN_PAJ7620_GESTURES, + &data); + + print_hand_gesture(data.val1); + k_msleep(GESTURE_POLL_TIME_MS); + } +} + +int main(void) +{ + int ret; + const struct device *dev = DEVICE_DT_GET_ONE(pixart_paj7620); + + struct sensor_trigger trig = { + .type = SENSOR_TRIG_MOTION, + .chan = (enum sensor_channel)SENSOR_CHAN_PAJ7620_GESTURES, + }; + + if (!device_is_ready(dev)) { + printf("Device %s is not ready\n", dev->name); + return -ENODEV; + } + + if (IS_ENABLED(CONFIG_APP_USE_POLLING)) { + polling_main_loop(dev); + } else { + /* App was configured to NOT use polling, so use triggers */ + ret = sensor_trigger_set(dev, &trig, trigger_handler); + if (ret < 0) { + printf("Could not set trigger\n"); + return ret; + } + + trigger_main_loop(dev); + } +}