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: 11 additions & 5 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,18 @@ config PMW3610_INVERT_X
config PMW3610_INVERT_Y
bool "Invert the Y axis of PMW3610 sensor"

config PMW3610_INIT_POWER_UP_EXTRA_DELAY_MS
int "Extra power up init delay (ms)"
default 0
config PMW3610_INIT_RETRY_COUNT
int "Number of times to retry PMW3610 init"
default 50
help
Default minimum init power up delay is 10ms.
Use this config to postpone init power up sequence if needs longer bootup time.
How many times the driver should attempt to re-initialize
the PMW3610 sensor if initialization fails.

config PMW3610_INIT_RETRY_DELAY_MS
int "Delay between retries (ms)"
default 100
help
How long the driver waits between retry attempts in milliseconds.

config PMW3610_REPORT_INTERVAL_MIN
int "PMW3610's default minimum report rate"
Expand Down
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,6 @@ CONFIG_PMW3610=y
# CONFIG_PMW3610_INVERT_Y=y // <-- deprecated, use invert-y; instead
# CONFIG_PMW3610_REPORT_INTERVAL_MIN=12
# CONFIG_PMW3610_LOG_LEVEL_DBG=y
# CONFIG_PMW3610_INIT_POWER_UP_EXTRA_DELAY_MS=300 // <--see Troubleshooting
# CONFIG_PMW3610_INIT_RETRY_COUNT=50
# CONFIG_PMW3610_INIT_RETRY_DELAY_MS=100
```

## Troubleshooting

If you are getting `Incorrect product id 0xFF (expecting 0x3E)!` on `nice_nano_v2` board from the log, you'd want to apply `CONFIG_PMW3610_INIT_POWER_UP_EXTRA_DELAY_MS=1000` in your shield .conf/.overlay file. Due to this driver doesn't offer module dependancy setting, that would ensure external power (to enable VCC pin on board) is ready, the `CONFIG_PMW3610_INIT_POWER_UP_EXTRA_DELAY_MS` would use to add extra one second delay of power up.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
description: |
Sensor driver for the pixart PMW3610 mouse sensor
Sensor driver for the pixart PMW3610 mouse sensor

compatible: "pixart,pmw3610"
compatible: "cyboard,pmw3610"

include: spi-device.yaml

Expand Down
1 change: 1 addition & 0 deletions src/pixart.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct pixart_data {

bool ready; // whether init is finished successfully
int err; // error code during async init
int retries; // number of retries of the initialization sequence
};

// device config data structure
Expand Down
23 changes: 20 additions & 3 deletions src/pmw3610.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
*/

#define DT_DRV_COMPAT pixart_pmw3610
#define DT_DRV_COMPAT cyboard_pmw3610

#include <zephyr/kernel.h>
#include <zephyr/sys/byteorder.h>
Expand Down Expand Up @@ -34,7 +34,7 @@ enum pmw3610_init_step {
// - Since MCU is not involved in the sensor init process, i is allowed to do other tasks.
// Thus, k_sleep or delayed schedule can be used.
static const int32_t async_init_delay[ASYNC_INIT_STEP_COUNT] = {
[ASYNC_INIT_STEP_POWER_UP] = 10 + CONFIG_PMW3610_INIT_POWER_UP_EXTRA_DELAY_MS, // >10ms needed
[ASYNC_INIT_STEP_POWER_UP] = 10, // >10ms needed
[ASYNC_INIT_STEP_CLEAR_OB1] = 200, // 150 us required, test shows too short,
// also power-up reset is added in this step, thus using 50 ms
[ASYNC_INIT_STEP_CHECK_OB1] = 50, // 10 ms required in spec,
Expand Down Expand Up @@ -450,6 +450,23 @@ static void pmw3610_async_init(struct k_work *work) {
data->err = async_init_fn[data->async_init_step](dev);
if (data->err) {
LOG_ERR("PMW3610 initialization failed in step %d", data->async_init_step);

/* If we haven’t exceeded our retry budget, reset to step 0 and try again */
if (data->retries < CONFIG_PMW3610_INIT_RETRY_COUNT) {
data->retries++;
data->async_init_step = 0;
LOG_WRN("Retrying PMW3610 init (attempt %d/%d) in %d ms...",
data->retries,
CONFIG_PMW3610_INIT_RETRY_COUNT,
CONFIG_PMW3610_INIT_RETRY_DELAY_MS);

/* Schedule the next attempt after a delay */
k_work_schedule(&data->init_work,
K_MSEC(CONFIG_PMW3610_INIT_RETRY_DELAY_MS));
} else {
LOG_ERR("PMW3610 init failed after %d retries; giving up.", data->retries);
/* At this point, we do NOT re-schedule, so init stops. data->ready stays false */
}
} else {
data->async_init_step++;

Expand Down Expand Up @@ -729,7 +746,7 @@ DT_INST_FOREACH_STATUS_OKAY(PMW3610_DEFINE)
#define GET_PMW3610_DEV(node_id) DEVICE_DT_GET(node_id),

static const struct device *pmw3610_devs[] = {
DT_FOREACH_STATUS_OKAY(pixart_pmw3610, GET_PMW3610_DEV)
DT_FOREACH_STATUS_OKAY(cyboard_pmw3610, GET_PMW3610_DEV)
};

static int on_activity_state(const zmk_event_t *eh) {
Expand Down