switch to multi device pmw33xx driver
This commit is contained in:
parent
f6af5a531f
commit
f398f02e57
15 changed files with 1042 additions and 544 deletions
|
@ -3,4 +3,4 @@
|
||||||
|
|
||||||
add_subdirectory_ifdef(CONFIG_ZMK_BATTERY battery)
|
add_subdirectory_ifdef(CONFIG_ZMK_BATTERY battery)
|
||||||
add_subdirectory_ifdef(CONFIG_EC11 ec11)
|
add_subdirectory_ifdef(CONFIG_EC11 ec11)
|
||||||
add_subdirectory_ifdef(CONFIG_PMW3389 pmw3389)
|
add_subdirectory_ifdef(CONFIG_PMW33xx pmw33xx)
|
||||||
|
|
|
@ -3,4 +3,4 @@
|
||||||
|
|
||||||
rsource "battery/Kconfig"
|
rsource "battery/Kconfig"
|
||||||
rsource "ec11/Kconfig"
|
rsource "ec11/Kconfig"
|
||||||
rsource "pmw3389/Kconfig"
|
rsource "pmw33xx/Kconfig"
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
# Copyright (c) 2020 The ZMK Contributors
|
|
||||||
# SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
zephyr_include_directories(.)
|
|
||||||
|
|
||||||
zephyr_library()
|
|
||||||
|
|
||||||
zephyr_library_sources(pmw3389.c)
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_PMW3389_TRIGGER pmw3389_trigger.c)
|
|
|
@ -1,49 +0,0 @@
|
||||||
config PMW3389
|
|
||||||
bool "PMW3389 Mouse Sensor"
|
|
||||||
depends on SPI
|
|
||||||
help
|
|
||||||
Enable mouse sensor
|
|
||||||
|
|
||||||
The PMW3389 is a 16-bit optical mouse sensor
|
|
||||||
|
|
||||||
if PMW3389
|
|
||||||
|
|
||||||
choice
|
|
||||||
prompt "Trigger mode"
|
|
||||||
default PMW3389_TRIGGER_NONE
|
|
||||||
help
|
|
||||||
Specify the type of triggering to be used by the driver.
|
|
||||||
|
|
||||||
config PMW3389_TRIGGER_NONE
|
|
||||||
bool "No trigger"
|
|
||||||
|
|
||||||
config PMW3389_TRIGGER_GLOBAL_THREAD
|
|
||||||
bool "Use global thread"
|
|
||||||
depends on GPIO
|
|
||||||
select PMW3389_TRIGGER
|
|
||||||
|
|
||||||
config PMW3389_TRIGGER_OWN_THREAD
|
|
||||||
bool "Use own thread"
|
|
||||||
depends on GPIO
|
|
||||||
select PMW3389_TRIGGER
|
|
||||||
|
|
||||||
endchoice
|
|
||||||
|
|
||||||
config PMW3389_TRIGGER
|
|
||||||
bool
|
|
||||||
|
|
||||||
config PMW3389_THREAD_PRIORITY
|
|
||||||
int "Thread priority"
|
|
||||||
depends on PMW3389_TRIGGER_OWN_THREAD
|
|
||||||
default 10
|
|
||||||
help
|
|
||||||
Priority of thread used by the driver to handle interrupts.
|
|
||||||
|
|
||||||
config PMW3389_THREAD_STACK_SIZE
|
|
||||||
int "Thread stack size"
|
|
||||||
depends on PMW3389_TRIGGER_OWN_THREAD
|
|
||||||
default 1024
|
|
||||||
help
|
|
||||||
Stack size of thread used by the driver to handle interrupts.
|
|
||||||
|
|
||||||
endif # PMW3389
|
|
|
@ -1,260 +0,0 @@
|
||||||
|
|
||||||
#define DT_DRV_COMPAT pixart_pmw3389
|
|
||||||
|
|
||||||
#include <drivers/spi.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <device.h>
|
|
||||||
#include <drivers/gpio.h>
|
|
||||||
#include <sys/util.h>
|
|
||||||
#include <sys/byteorder.h>
|
|
||||||
#include <kernel.h>
|
|
||||||
#include <drivers/sensor.h>
|
|
||||||
#include <sys/__assert.h>
|
|
||||||
#include <logging/log.h>
|
|
||||||
|
|
||||||
#include "pmw3389.h"
|
|
||||||
|
|
||||||
LOG_MODULE_REGISTER(PMW3389, CONFIG_SENSOR_LOG_LEVEL);
|
|
||||||
|
|
||||||
static int pmw3389_access(const struct device *dev, uint8_t reg, uint8_t *value) {
|
|
||||||
struct pmw3389_data *data = dev->data;
|
|
||||||
const struct pmw3389_config *cfg = dev->config;
|
|
||||||
const struct spi_config *spi_cfg = &cfg->bus_cfg.spi_cfg->spi_conf;
|
|
||||||
uint8_t access[1] = {reg};
|
|
||||||
struct spi_buf bufs[] = {
|
|
||||||
{
|
|
||||||
.buf = access,
|
|
||||||
.len = 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.buf = value,
|
|
||||||
.len = 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
struct spi_buf_set tx = {
|
|
||||||
.buffers = bufs,
|
|
||||||
.count = 2,
|
|
||||||
};
|
|
||||||
struct spi_buf_set *rx;
|
|
||||||
if (reg & PMW3389_WR_MASK > 0) {
|
|
||||||
rx = &(struct spi_buf_set){
|
|
||||||
.buffers = bufs,
|
|
||||||
.count = 2,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return spi_transceive(data->bus, spi_cfg, &tx, rx);
|
|
||||||
}
|
|
||||||
static int pmw3389_read_reg(const struct device *dev, const uint8_t reg, uint8_t *value) {
|
|
||||||
return pmw3389_access(dev, reg, value);
|
|
||||||
}
|
|
||||||
static int pmw3389_write_reg(const struct device *dev, const uint8_t reg, const uint8_t value) {
|
|
||||||
return pmw3389_access(dev, reg & PMW3389_WR_MASK, &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// converts twos complement data to an int16
|
|
||||||
static int16_t pmw3389_raw_to_int16(const uint8_t src[2]) {
|
|
||||||
int16_t res = sys_get_be16(src[2]);
|
|
||||||
if (res > BIT_MASK(15))
|
|
||||||
res -= BIT(16);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pmw3389_read_raw(const struct device *dev, const uint8_t reg_high, const uint8_t reg_low,
|
|
||||||
int16_t *value) {
|
|
||||||
uint8_t raw[2] = {0x0, 0x0};
|
|
||||||
int err;
|
|
||||||
err = pmw3389_read_reg(dev, reg_high, &raw[0]);
|
|
||||||
if (err) {
|
|
||||||
LOG_ERR("could not read high byte at %x", reg_high);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
err = pmw3389_read_reg(dev, reg_low, &raw[1]);
|
|
||||||
if (err) {
|
|
||||||
LOG_ERR("could not read low byte at %x", reg_low);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
*value = pmw3389_raw_to_int16(raw);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool pmw3389_spi_check_id(const struct device *dev) {
|
|
||||||
int err;
|
|
||||||
uint8_t val;
|
|
||||||
err = pmw3389_read_reg(dev, &val, PMW3389_REG_PID);
|
|
||||||
if (err) {
|
|
||||||
LOG_ERR("could not read PID");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (val != PMW3389_PID) {
|
|
||||||
LOG_ERR("invalid PID");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
err = pmw3389_read_reg(dev, &val, PMW3389_REG_REV);
|
|
||||||
if (err) {
|
|
||||||
LOG_ERR("could not read REV");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (val != PMW3389_REV) {
|
|
||||||
LOG_ERR("invalid REV");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pmw3389_spi_init(const struct device *dev) {
|
|
||||||
struct pmw3389_data *data = dev->data;
|
|
||||||
const struct pmw3389_config *cfg = dev->config;
|
|
||||||
const struct pmw3389_spi_cfg *spi_cfg = cfg->bus_cfg.spi_cfg;
|
|
||||||
|
|
||||||
if (spi_cfg->cs_gpios_label != NULL) {
|
|
||||||
|
|
||||||
/* handle SPI CS thru GPIO if it is the case */
|
|
||||||
data->cs_ctrl.gpio_dev = device_get_binding(spi_cfg->cs_gpios_label);
|
|
||||||
if (!data->cs_ctrl.gpio_dev) {
|
|
||||||
LOG_ERR("Unable to get GPIO SPI CS device");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pmw3389_sample_fetch(const struct device *dev, enum sensor_channel chan) {
|
|
||||||
struct pmw3389_data *data = dev->data;
|
|
||||||
const struct pmw3389_config *cfg = dev->config;
|
|
||||||
uint16_t dx = 0, dy = 0;
|
|
||||||
|
|
||||||
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_POS_DX && chan != SENSOR_CHAN_POS_DY)
|
|
||||||
return -ENOTSUP;
|
|
||||||
if (!pmw3389_spi_check_id(dev))
|
|
||||||
return -EINVAL;
|
|
||||||
int err;
|
|
||||||
if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_POS_DX) {
|
|
||||||
err = pmw3389_read_raw(dev, PMW3389_REG_DX_H, PMW3389_REG_DX_L, &dx);
|
|
||||||
if (err) {
|
|
||||||
LOG_DBG("could not read x motion");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_POS_DY) {
|
|
||||||
err = pmw3389_read_raw(dev, PMW3389_REG_DY_H, PMW3389_REG_DY_L, &dy);
|
|
||||||
if (err) {
|
|
||||||
LOG_DBG("could not read y motion");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data->dx = dx;
|
|
||||||
data->dy = dy;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pmw3389_channel_get(const struct device *dev, enum sensor_channel chan,
|
|
||||||
struct sensor_value *val) {
|
|
||||||
struct pmw3389_data *data = dev->data;
|
|
||||||
const struct pmw3389_config *cfg = dev->config;
|
|
||||||
|
|
||||||
switch (chan) {
|
|
||||||
case SENSOR_CHAN_POS_DX:
|
|
||||||
val->val1 = data->dx;
|
|
||||||
case SENSOR_CHAN_POS_DY:
|
|
||||||
val->val1 = data->dy;
|
|
||||||
default:
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct sensor_driver_api pmw3389_driver_api = {
|
|
||||||
#ifdef CONFIG_PMW3389_TRIGGER
|
|
||||||
.trigger_set = pmw3389_trigger_set,
|
|
||||||
#endif
|
|
||||||
// .attr_set = pmw3389_attr_set,
|
|
||||||
.sample_fetch = pmw3389_sample_fetch,
|
|
||||||
.channel_get = pmw3389_channel_get,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int pmw3389_init_chip(const struct device *dev) {
|
|
||||||
struct pmw3389_data *data = dev->data;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pmw3389_init(const struct device *dev) {
|
|
||||||
const struct pmw3389_config *const config = dev->config;
|
|
||||||
struct pmw3389_data *data = dev->data;
|
|
||||||
|
|
||||||
data->bus = device_get_binding(config->bus_name);
|
|
||||||
if (!data->bus) {
|
|
||||||
LOG_DBG("master not found: %s", log_strdup(config->bus_name));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
config->bus_init(dev);
|
|
||||||
|
|
||||||
if (pmw3389_init_chip(dev) < 0) {
|
|
||||||
LOG_DBG("failed to initialize chip");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_PMW3389_TRIGGER
|
|
||||||
if (pmw3389_init_interrupt(dev) < 0) {
|
|
||||||
LOG_DBG("Failed to initialize interrupt!");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PMW3389_HAS_CS(n) DT_INST_SPI_DEV_HAS_CS_GPIOS(n)
|
|
||||||
|
|
||||||
#define PMW3389_DATA_SPI_CS(n) \
|
|
||||||
{ \
|
|
||||||
.cs_ctrl = { \
|
|
||||||
.gpio_pin = DT_INST_SPI_DEV_CS_GPIOS_PIN(n), \
|
|
||||||
.gpio_dt_flags = DT_INST_SPI_DEV_CS_GPIOS_FLAGS(n), \
|
|
||||||
}, \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PMW3389_DATA_SPI(n) COND_CODE_1(PMW3389_HAS_CS(n), (PMW3389_DATA_SPI_CS(n)), ({}))
|
|
||||||
|
|
||||||
#define PMW3389_SPI_CS_PTR(n) COND_CODE_1(PMW3389_HAS_CS(n), (&(pmw3389_data_##n.cs_ctrl)), (NULL))
|
|
||||||
|
|
||||||
#define PMW3389_SPI_CS_LABEL(n) \
|
|
||||||
COND_CODE_1(PMW3389_HAS_CS(n), (DT_INST_SPI_DEV_CS_GPIOS_LABEL(n)), (NULL))
|
|
||||||
|
|
||||||
#define PMW3389_SPI_CFG(n) \
|
|
||||||
(&(struct pmw3389_spi_cfg){ \
|
|
||||||
.spi_conf = \
|
|
||||||
{ \
|
|
||||||
.frequency = DT_INST_PROP(n, spi_max_frequency), \
|
|
||||||
.operation = \
|
|
||||||
(SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA), \
|
|
||||||
.slave = DT_INST_REG_ADDR(n), \
|
|
||||||
.cs = PMW3389_SPI_CS_PTR(n), \
|
|
||||||
}, \
|
|
||||||
.cs_gpios_label = PMW3389_SPI_CS_LABEL(n), \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define PMW3389_GPIO_DT_SPEC_GET_BY_IDX(node_id, prop, idx) \
|
|
||||||
{ \
|
|
||||||
.port = DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(node_id, prop, idx)), \
|
|
||||||
.pin = DT_GPIO_PIN_BY_IDX(node_id, prop, idx), \
|
|
||||||
.dt_flags = DT_GPIO_FLAGS_BY_IDX(node_id, prop, idx), \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PMW3389_CONFIG_SPI(n) \
|
|
||||||
{ \
|
|
||||||
.bus_name = DT_INST_BUS_LABEL(n), .bus_init = pmw3389_spi_init, \
|
|
||||||
.bus_cfg = {.spi_cfg = PMW3389_SPI_CFG(n)}, \
|
|
||||||
COND_CODE_1(CONFIG_MA730_TRIGGER, \
|
|
||||||
(, PMW3389_GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(n), motswk_gpios, 0)), ()) \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PMW3389_INST(n) \
|
|
||||||
static struct pmw3389_data pmw3389_data_##n = PMW3389_DATA_SPI(n); \
|
|
||||||
static const struct pmw3389_config pmw3389_cfg_##n = PMW3389_CONFIG_SPI(n); \
|
|
||||||
DEVICE_DT_INST_DEFINE(n, pmw3389_init, device_pm_control_nop, &pmw3389_data_##n, \
|
|
||||||
&pmw3389_cfg_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
|
|
||||||
&pmw3389_driver_api);
|
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(PMW3389_INST)
|
|
|
@ -1,92 +0,0 @@
|
||||||
#ifndef ZEPHYR_DRIVERS_SENSOR_PIXART_PMW3389_H_
|
|
||||||
#define ZEPHYR_DRIVERS_SENSOR_PIXART_PMW3389_H_
|
|
||||||
|
|
||||||
#include <drivers/sensor.h>
|
|
||||||
#include <zephyr/types.h>
|
|
||||||
#include <drivers/gpio.h>
|
|
||||||
#include <sys/util.h>
|
|
||||||
#include <drivers/spi.h>
|
|
||||||
|
|
||||||
#define PMW3389_WR_MASK 0x80
|
|
||||||
|
|
||||||
#define PMW3389_PID 0x47
|
|
||||||
#define PMW3389_REV 0x01
|
|
||||||
|
|
||||||
#define PMW3389_REG_PID 0x00
|
|
||||||
#define PMW3389_REG_REV 0x01
|
|
||||||
|
|
||||||
#define PMW3389_REG_DX_L 0x2A
|
|
||||||
#define PMW3389_REG_DX_H 0x2B
|
|
||||||
#define PMW3389_REG_DY_L 0x2C
|
|
||||||
#define PMW3389_REG_DY_H 0x2D
|
|
||||||
|
|
||||||
struct pmw3389_gpio_dt_spec {
|
|
||||||
const struct device *port;
|
|
||||||
gpio_pin_t pin;
|
|
||||||
gpio_dt_flags_t dt_flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pmw3389_spi_cfg {
|
|
||||||
struct spi_config spi_conf;
|
|
||||||
const char *cs_gpios_label;
|
|
||||||
};
|
|
||||||
|
|
||||||
union pmw3389_bus_cfg {
|
|
||||||
struct pmw3389_spi_cfg *spi_cfg;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pmw3389_config {
|
|
||||||
char *bus_name;
|
|
||||||
int (*bus_init)(const struct device *dev);
|
|
||||||
const union pmw3389_bus_cfg bus_cfg;
|
|
||||||
int resolution;
|
|
||||||
struct pmw3389_gpio_dt_spec reset_spec;
|
|
||||||
#if CONFIG_PMW3389_TRIGGER
|
|
||||||
struct pmw3389_gpio_dt_spec motswk_spec;
|
|
||||||
#endif // CONFIG_PMW3389_TRIGGER
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pmw3389_data;
|
|
||||||
|
|
||||||
struct pmw3389_transfer_function {
|
|
||||||
int (*read_data)(const struct device *dev, uint16_t *value);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pmw3389_data {
|
|
||||||
const struct device *bus;
|
|
||||||
struct spi_cs_control cs_ctrl;
|
|
||||||
|
|
||||||
uint16_t dx;
|
|
||||||
uint16_t dy;
|
|
||||||
|
|
||||||
const struct pmw3389_transfer_function *hw_tf;
|
|
||||||
|
|
||||||
#ifdef CONFIG_PMW3389_TRIGGER
|
|
||||||
|
|
||||||
struct gpio_callback motswk_gpio_cb;
|
|
||||||
const struct device *dev;
|
|
||||||
|
|
||||||
sensor_trigger_handler_t handler;
|
|
||||||
const struct sensor_trigger *trigger;
|
|
||||||
|
|
||||||
#if defined(CONFIG_PMW3389_TRIGGER_OWN_THREAD)
|
|
||||||
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_PMW3389_THREAD_STACK_SIZE);
|
|
||||||
struct k_sem gpio_sem;
|
|
||||||
struct k_thread thread;
|
|
||||||
#elif defined(CONFIG_PMW3389_TRIGGER_GLOBAL_THREAD)
|
|
||||||
struct k_work work;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* CONFIG_PMW3389_TRIGGER */
|
|
||||||
};
|
|
||||||
|
|
||||||
int pmw3389_spi_init(const struct device *dev);
|
|
||||||
#ifdef CONFIG_PMW3389_TRIGGER
|
|
||||||
|
|
||||||
int pmw3389_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
|
|
||||||
sensor_trigger_handler_t handler);
|
|
||||||
|
|
||||||
int pmw3389_init_interrupt(const struct device *dev);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* ZEPHYR_DRIVERS_SENSOR_PIXART_PMW3389_H_ */
|
|
|
@ -1,123 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2020 The ZMK Contributors
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define DT_DRV_COMPAT pixart_pmw3389
|
|
||||||
|
|
||||||
#include <device.h>
|
|
||||||
#include <drivers/gpio.h>
|
|
||||||
#include <sys/util.h>
|
|
||||||
#include <kernel.h>
|
|
||||||
#include <drivers/sensor.h>
|
|
||||||
|
|
||||||
#include "pmw3389.h"
|
|
||||||
|
|
||||||
// extern struct pmw3389_data pmw3389_driver;
|
|
||||||
|
|
||||||
#include <logging/log.h>
|
|
||||||
LOG_MODULE_DECLARE(PMW3389, CONFIG_SENSOR_LOG_LEVEL);
|
|
||||||
|
|
||||||
static inline void setup_int(const struct device *dev, bool enable) {
|
|
||||||
struct pmw3389_data *data = dev->data;
|
|
||||||
const struct pmw3389_config *cfg = dev->config;
|
|
||||||
|
|
||||||
if (gpio_pin_interrupt_configure(cfg->motswk_spec.port, cfg->motswk_spec.pin,
|
|
||||||
enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE)) {
|
|
||||||
LOG_WRN("Unable to set MOTSWK GPIO interrupt");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pmw3389_motswk_gpio_callback(const struct device *dev, struct gpio_callback *cb,
|
|
||||||
uint32_t pins) {
|
|
||||||
struct pmw3389_data *drv_data = CONTAINER_OF(cb, struct pmw3389_data, motswk_gpio_cb);
|
|
||||||
|
|
||||||
LOG_DBG("");
|
|
||||||
|
|
||||||
setup_int(drv_data->dev, false);
|
|
||||||
|
|
||||||
#if defined(CONFIG_PMW3389_TRIGGER_OWN_THREAD)
|
|
||||||
k_sem_give(&drv_data->gpio_sem);
|
|
||||||
#elif defined(CONFIG_PMW3389_TRIGGER_GLOBAL_THREAD)
|
|
||||||
k_work_submit(&drv_data->work);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pmw3389_thread_cb(const struct device *dev) {
|
|
||||||
struct pmw3389_data *drv_data = dev->data;
|
|
||||||
|
|
||||||
LOG_DBG("%p", drv_data->handler);
|
|
||||||
drv_data->handler(dev, drv_data->trigger);
|
|
||||||
|
|
||||||
// Enable once the wall/spam of interrupts is solved
|
|
||||||
setup_int(dev, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_PMW3389_TRIGGER_OWN_THREAD
|
|
||||||
static void pmw3389_thread(int dev_ptr, int unused) {
|
|
||||||
const struct device *dev = INT_TO_POINTER(dev_ptr);
|
|
||||||
struct pmw3389_data *drv_data = dev->data;
|
|
||||||
|
|
||||||
ARG_UNUSED(unused);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
k_sem_take(&drv_data->gpio_sem, K_FOREVER);
|
|
||||||
pmw3389_thread_cb(dev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_PMW3389_TRIGGER_GLOBAL_THREAD
|
|
||||||
static void pmw3389_work_cb(struct k_work *work) {
|
|
||||||
struct pmw3389_data *drv_data = CONTAINER_OF(work, struct pmw3389_data, work);
|
|
||||||
|
|
||||||
LOG_DBG("");
|
|
||||||
|
|
||||||
pmw3389_thread_cb(drv_data->dev);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int pmw3389_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
|
|
||||||
sensor_trigger_handler_t handler) {
|
|
||||||
struct pmw3389_data *drv_data = dev->data;
|
|
||||||
|
|
||||||
setup_int(dev, false);
|
|
||||||
|
|
||||||
k_msleep(5);
|
|
||||||
|
|
||||||
drv_data->trigger = trig;
|
|
||||||
drv_data->handler = handler;
|
|
||||||
|
|
||||||
setup_int(dev, true);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pmw3389_init_interrupt(const struct device *dev) {
|
|
||||||
struct pmw3389_data *drv_data = dev->data;
|
|
||||||
const struct pmw3389_config *drv_cfg = dev->config;
|
|
||||||
|
|
||||||
drv_data->dev = dev;
|
|
||||||
/* setup gpio interrupt */
|
|
||||||
|
|
||||||
gpio_init_callback(&drv_data->motswk_gpio_cb, pmw3389_motswk_gpio_callback,
|
|
||||||
BIT(drv_cfg->motswk_spec.pin));
|
|
||||||
|
|
||||||
if (gpio_add_callback(drv_cfg->motswk_spec.port, &drv_data->motswk_gpio_cb) < 0) {
|
|
||||||
LOG_DBG("Failed to set MOTSWK callback!");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONFIG_PMW3389_TRIGGER_OWN_THREAD)
|
|
||||||
k_sem_init(&drv_data->gpio_sem, 0, UINT_MAX);
|
|
||||||
|
|
||||||
k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_PMW3389_THREAD_STACK_SIZE,
|
|
||||||
(k_thread_entry_t)pmw3389_thread, dev, 0, NULL,
|
|
||||||
K_PRIO_COOP(CONFIG_PMW3389_THREAD_PRIORITY), 0, K_NO_WAIT);
|
|
||||||
#elif defined(CONFIG_PMW3389_TRIGGER_GLOBAL_THREAD)
|
|
||||||
k_work_init(&drv_data->work, pmw3389_work_cb);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
1
app/drivers/sensor/pmw33xx/.gitignore
vendored
Normal file
1
app/drivers/sensor/pmw33xx/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pmw3389_srom.h
|
10
app/drivers/sensor/pmw33xx/CMakeLists.txt
Normal file
10
app/drivers/sensor/pmw33xx/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
zephyr_include_directories(.)
|
||||||
|
zephyr_include_directories_ifdef(CONFIG_PMW33XX_3389 CONFIG_PMW33XX_3389_SROM_INCLUDE_DIR)
|
||||||
|
|
||||||
|
zephyr_library()
|
||||||
|
|
||||||
|
zephyr_library_sources(pmw33xx.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_PMW33XX_TRIGGER pmw33xx_trigger.c)
|
67
app/drivers/sensor/pmw33xx/Kconfig
Normal file
67
app/drivers/sensor/pmw33xx/Kconfig
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
config PMW33XX
|
||||||
|
bool "PMW33XX Mouse Sensor"
|
||||||
|
depends on SPI
|
||||||
|
help
|
||||||
|
Enable mouse sensor
|
||||||
|
|
||||||
|
The PMW33XX is a 16-bit optical mouse sensor
|
||||||
|
|
||||||
|
if PMW33XX
|
||||||
|
choice
|
||||||
|
prompt "Sensor"
|
||||||
|
default PMW33XX_3360
|
||||||
|
|
||||||
|
config PMW33XX_3360
|
||||||
|
bool "Enable PMW3360"
|
||||||
|
|
||||||
|
config PMW33XX_3389
|
||||||
|
bool "Enable PMW3389"
|
||||||
|
help
|
||||||
|
PMW3389 requires an external srom included in `pmw3389_srom.h` which we cannot currently include in zmk
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config PMW33XX_3389_SROM_INCLUDE_DIR
|
||||||
|
string "PMW3389 SROM Include Dir"
|
||||||
|
default "."
|
||||||
|
help
|
||||||
|
directory where the header with the pmw3389 srom file is located
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Trigger mode"
|
||||||
|
default PMW33XX_TRIGGER_NONE
|
||||||
|
help
|
||||||
|
Specify the type of triggering to be used by the driver.
|
||||||
|
|
||||||
|
config PMW33XX_TRIGGER_NONE
|
||||||
|
bool "No trigger"
|
||||||
|
|
||||||
|
config PMW33XX_TRIGGER_GLOBAL_THREAD
|
||||||
|
bool "Use global thread"
|
||||||
|
depends on GPIO
|
||||||
|
select PMW33XX_TRIGGER
|
||||||
|
|
||||||
|
config PMW33XX_TRIGGER_OWN_THREAD
|
||||||
|
bool "Use own thread"
|
||||||
|
depends on GPIO
|
||||||
|
select PMW33XX_TRIGGER
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config PMW33XX_TRIGGER
|
||||||
|
bool
|
||||||
|
|
||||||
|
config PMW33XX_THREAD_PRIORITY
|
||||||
|
int "Thread priority"
|
||||||
|
depends on PMW33XX_TRIGGER_OWN_THREAD
|
||||||
|
default 10
|
||||||
|
help
|
||||||
|
Priority of thread used by the driver to handle interrupts.
|
||||||
|
|
||||||
|
config PMW33XX_THREAD_STACK_SIZE
|
||||||
|
int "Thread stack size"
|
||||||
|
depends on PMW33XX_TRIGGER_OWN_THREAD
|
||||||
|
default 1024
|
||||||
|
help
|
||||||
|
Stack size of thread used by the driver to handle interrupts.
|
||||||
|
|
||||||
|
endif # PMW33XX
|
291
app/drivers/sensor/pmw33xx/pmw3360_srom.h
Normal file
291
app/drivers/sensor/pmw33xx/pmw3360_srom.h
Normal file
|
@ -0,0 +1,291 @@
|
||||||
|
/*
|
||||||
|
This SROM is provided "AS IS" by PixArt Imaging Inc., WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||||
|
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL PIXART
|
||||||
|
IMAGING INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THIS
|
||||||
|
SROM OR THE USE OR OTHER DEALINGS IN THIS SROM.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_DRIVERS_SENSOR_PIXART_PMW33XX_PMW3360_SROM_H_
|
||||||
|
#define ZEPHYR_DRIVERS_SENSOR_PIXART_PMW33XX_PMW3360_SROM_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
static const uint8_t SROM[] = {
|
||||||
|
0x01, 0x05, 0x8d, 0x92, 0x66, 0x67, 0x1e, 0xbe, 0xfe, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,
|
||||||
|
0xff, 0x5d, 0x38, 0xf2, 0x46, 0x0c, 0x98, 0x97, 0x8d, 0x79, 0x51, 0x20, 0xc2, 0x06, 0x8e,
|
||||||
|
0x9e, 0xbe, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xd3, 0x24, 0xca, 0x16, 0x8f, 0x7d, 0x78, 0x53,
|
||||||
|
0x05, 0x88, 0x73, 0x45, 0xe9, 0x55, 0x22, 0xa7, 0xae, 0xd8, 0x32, 0xe6, 0x2f, 0xbd, 0xf8,
|
||||||
|
0x72, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x56, 0x2e, 0xbf, 0xdd, 0x38, 0xd5, 0x20, 0xca, 0x16,
|
||||||
|
0xae, 0xde, 0x1f, 0x9d, 0xb8, 0xf2, 0x47, 0x0c, 0x7b, 0x55, 0x28, 0xd2, 0x26, 0xaf, 0xdc,
|
||||||
|
0x3a, 0xd7, 0x2c, 0xbb, 0xd5, 0x09, 0x90, 0xa2, 0xa7, 0xcc, 0xfb, 0x74, 0x4b, 0xf5, 0x49,
|
||||||
|
0x10, 0x83, 0x84, 0x8a, 0x77, 0x4d, 0x18, 0xb2, 0xe6, 0x4e, 0x1e, 0x9f, 0xbc, 0xfa, 0x6a,
|
||||||
|
0xea, 0xab, 0x55, 0x91, 0xa9, 0xda, 0x58, 0xa9, 0xe1, 0x1a, 0xc2, 0x52, 0x1c, 0x0d, 0xef,
|
||||||
|
0x50, 0x71, 0x04, 0x21, 0x93, 0x87, 0x0e, 0xb1, 0xa9, 0x4a, 0xc0, 0x24, 0xaf, 0xe3, 0x26,
|
||||||
|
0xa2, 0x8d, 0xa1, 0x6d, 0xf2, 0x88, 0x9e, 0x99, 0xbb, 0xf2, 0x62, 0x38, 0xfe, 0x78, 0x1d,
|
||||||
|
0x58, 0x19, 0x9b, 0xbe, 0x10, 0x6c, 0x15, 0x9e, 0x50, 0x8b, 0x99, 0x40, 0x92, 0x01, 0x38,
|
||||||
|
0xb6, 0x97, 0x83, 0x51, 0x59, 0xa6, 0xb7, 0xc9, 0x48, 0xfd, 0x68, 0x21, 0x78, 0xf4, 0x2e,
|
||||||
|
0x86, 0x61, 0xb0, 0xb2, 0x2b, 0x5b, 0xf0, 0x1b, 0x71, 0xa3, 0x0a, 0xd5, 0xd6, 0x30, 0x7a,
|
||||||
|
0x0c, 0xf8, 0xaf, 0xc6, 0x54, 0x6b, 0x89, 0x30, 0x58, 0xe8, 0xe2, 0x0d, 0x39, 0x2f, 0x47,
|
||||||
|
0xa0, 0x41, 0x74, 0x5d, 0xd6, 0xf3, 0x85, 0xb7, 0x66, 0x59, 0x51, 0x74, 0x3d, 0xfe, 0xee,
|
||||||
|
0x3a, 0x1e, 0x2a, 0x5f, 0x93, 0x0c, 0x3f, 0xd4, 0x4d, 0x24, 0x13, 0x2c, 0xf2, 0x7b, 0x4d,
|
||||||
|
0x06, 0x60, 0x2e, 0x39, 0xa9, 0xd4, 0x72, 0x36, 0xb6, 0x4d, 0xea, 0x8c, 0xd9, 0xa7, 0xbc,
|
||||||
|
0x38, 0xe7, 0xbb, 0xb7, 0x7b, 0x04, 0x08, 0x83, 0x5a, 0x27, 0x6f, 0x42, 0xc6, 0x7e, 0xbd,
|
||||||
|
0x97, 0x0e, 0x55, 0xdc, 0x79, 0x63, 0xd8, 0x89, 0xc1, 0x83, 0x3d, 0x34, 0x01, 0x76, 0xff,
|
||||||
|
0xde, 0x7f, 0x65, 0x4b, 0xb3, 0x46, 0x56, 0x8d, 0x9e, 0x6f, 0x1f, 0x2b, 0xa4, 0x69, 0x54,
|
||||||
|
0xde, 0x1c, 0x2d, 0xa8, 0x51, 0x7e, 0xdf, 0xbb, 0x18, 0x90, 0x27, 0xaf, 0x79, 0xd1, 0x86,
|
||||||
|
0x4f, 0x44, 0x88, 0x7f, 0xb9, 0x80, 0x21, 0xa9, 0x5d, 0x7b, 0xd4, 0x81, 0x21, 0xa9, 0x13,
|
||||||
|
0x59, 0x72, 0x58, 0x11, 0xe3, 0xf2, 0xf7, 0xae, 0xc3, 0xc2, 0x64, 0x1d, 0xfb, 0xd8, 0x91,
|
||||||
|
0x2d, 0x13, 0xb5, 0x0e, 0x67, 0xdb, 0xbc, 0x63, 0xde, 0xa0, 0x86, 0x49, 0x6c, 0x40, 0x82,
|
||||||
|
0x82, 0x3f, 0xeb, 0x38, 0x22, 0xa8, 0x20, 0x1e, 0xc5, 0x5f, 0x25, 0xea, 0xaf, 0xe6, 0x78,
|
||||||
|
0x1c, 0x41, 0x0b, 0x5a, 0x94, 0xcc, 0x8d, 0x0d, 0xc5, 0xb8, 0x9c, 0x1a, 0x9f, 0x6d, 0xa8,
|
||||||
|
0x57, 0xe9, 0x1a, 0xf0, 0xad, 0x6c, 0x26, 0x5f, 0xb8, 0x38, 0x16, 0x0e, 0x28, 0xd6, 0x76,
|
||||||
|
0x5a, 0xc2, 0xb7, 0x6a, 0x9e, 0x26, 0x9d, 0x3e, 0x1f, 0x25, 0xb0, 0x14, 0x46, 0xcd, 0x67,
|
||||||
|
0x49, 0x93, 0x13, 0x81, 0x01, 0x46, 0x72, 0x31, 0x42, 0x91, 0x87, 0x6c, 0x1c, 0xb8, 0x08,
|
||||||
|
0x72, 0x6a, 0x33, 0x64, 0xed, 0xc0, 0x99, 0xb9, 0xf6, 0x34, 0xe9, 0xa5, 0x6c, 0x57, 0x9a,
|
||||||
|
0x72, 0x18, 0x48, 0x62, 0xc1, 0x88, 0xcf, 0xa3, 0x50, 0x53, 0x50, 0xdf, 0xc8, 0x9f, 0xf0,
|
||||||
|
0xb6, 0xa2, 0x23, 0xc4, 0xaa, 0xe3, 0xd0, 0xe2, 0xab, 0x76, 0xc8, 0x4a, 0x02, 0x21, 0xdd,
|
||||||
|
0xf3, 0x59, 0xdc, 0x30, 0x6e, 0xb5, 0x42, 0xe2, 0x9d, 0x8a, 0xdf, 0xfd, 0xa5, 0x41, 0x75,
|
||||||
|
0x01, 0x83, 0xbe, 0x47, 0xa5, 0x21, 0x30, 0x3b, 0x0e, 0x33, 0x2e, 0x74, 0xaf, 0x27, 0x90,
|
||||||
|
0xf4, 0x20, 0xa7, 0x1b, 0xff, 0x77, 0x01, 0xab, 0x79, 0x0a, 0xfb, 0x86, 0x1e, 0x1f, 0x22,
|
||||||
|
0x6d, 0x75, 0x75, 0xfc, 0xe0, 0x8c, 0xa2, 0x72, 0x0f, 0x45, 0x48, 0xf9, 0x43, 0x10, 0xf0,
|
||||||
|
0x57, 0x15, 0x17, 0x74, 0x40, 0x8f, 0x77, 0x69, 0x8a, 0xd4, 0x0f, 0x25, 0x27, 0x0a, 0xe8,
|
||||||
|
0x84, 0x73, 0x41, 0xb9, 0x5f, 0xb6, 0xc8, 0x2f, 0x02, 0x83, 0xdc, 0x1e, 0x1c, 0xdb, 0x3f,
|
||||||
|
0x2d, 0x58, 0xf7, 0x5e, 0xfd, 0x6f, 0xda, 0xad, 0xdc, 0x43, 0x01, 0x22, 0xc6, 0x45, 0x9c,
|
||||||
|
0xec, 0x56, 0x8a, 0x1a, 0x4e, 0xaa, 0xae, 0x3a, 0xa1, 0xf3, 0xf1, 0x9a, 0x97, 0x8d, 0x79,
|
||||||
|
0x51, 0x01, 0xf5, 0x31, 0x04, 0xcd, 0x2a, 0xbc, 0xfd, 0xac, 0x59, 0x1b, 0x0a, 0xe2, 0x26,
|
||||||
|
0xdd, 0x2f, 0x96, 0xaa, 0x62, 0xc5, 0x6d, 0xb8, 0xe1, 0x72, 0x4e, 0x4e, 0xb7, 0x4f, 0x9f,
|
||||||
|
0xaa, 0x33, 0x75, 0x8b, 0x43, 0x44, 0x0a, 0xc3, 0x0a, 0x5e, 0x9c, 0xdb, 0x1e, 0x4e, 0xbd,
|
||||||
|
0x0f, 0xec, 0x09, 0x96, 0x5a, 0x37, 0x6d, 0x10, 0x44, 0xd4, 0x91, 0xc0, 0xc3, 0x0d, 0x35,
|
||||||
|
0x62, 0xcf, 0x0a, 0xb1, 0x1a, 0x8a, 0xda, 0xa8, 0xcf, 0xbc, 0x3a, 0xb2, 0x4f, 0x59, 0x29,
|
||||||
|
0xd9, 0x91, 0x96, 0x0d, 0x6b, 0x9c, 0xcf, 0x34, 0x5b, 0x76, 0x7b, 0xb2, 0xb2, 0xce, 0xbf,
|
||||||
|
0x72, 0xd9, 0x96, 0x4a, 0xc0, 0x2d, 0x89, 0x33, 0xd0, 0xe4, 0xbe, 0x69, 0x7f, 0x1c, 0x9e,
|
||||||
|
0x71, 0x19, 0x12, 0xf6, 0x74, 0xfb, 0xd6, 0x41, 0x95, 0x69, 0xf0, 0xe9, 0xa7, 0x50, 0x82,
|
||||||
|
0x04, 0x78, 0x4d, 0x99, 0xb3, 0xa7, 0xfe, 0xee, 0x7f, 0xed, 0x56, 0x57, 0x57, 0xe9, 0xd3,
|
||||||
|
0x6a, 0x43, 0xf4, 0x0b, 0x6d, 0xba, 0x34, 0xde, 0xf8, 0x4c, 0x45, 0xae, 0x00, 0x32, 0x1a,
|
||||||
|
0x4e, 0xff, 0x54, 0x60, 0x6a, 0xd9, 0x59, 0x18, 0xd3, 0xbe, 0x5a, 0x94, 0x16, 0x9d, 0xec,
|
||||||
|
0xdf, 0xb4, 0x48, 0x8e, 0x6f, 0x19, 0xf8, 0xe6, 0xec, 0x7f, 0xb7, 0x49, 0x92, 0xb3, 0xb6,
|
||||||
|
0xec, 0x7e, 0xdc, 0x08, 0x3b, 0xe5, 0x5b, 0x88, 0xf9, 0x92, 0xf3, 0x7c, 0x9d, 0x7c, 0x22,
|
||||||
|
0xf2, 0x5d, 0x7d, 0x76, 0x07, 0x2e, 0x42, 0xd6, 0x9e, 0x5a, 0xbc, 0x7d, 0xfd, 0xb5, 0x92,
|
||||||
|
0x4a, 0x7f, 0xbf, 0xac, 0xc0, 0xb6, 0x18, 0x8b, 0x02, 0x71, 0xae, 0xc7, 0xa8, 0x8c, 0x19,
|
||||||
|
0xc1, 0x0a, 0x36, 0x3e, 0xa4, 0x2d, 0xa6, 0xbb, 0xe8, 0x77, 0x34, 0x45, 0xca, 0x60, 0x52,
|
||||||
|
0xf0, 0x26, 0xf7, 0x58, 0x68, 0x34, 0x28, 0xb5, 0x29, 0xe5, 0xb8, 0x65, 0x0f, 0xc8, 0xc2,
|
||||||
|
0x64, 0x50, 0x91, 0x12, 0xa1, 0x7b, 0xd7, 0x09, 0x74, 0x5f, 0xcc, 0xac, 0x9d, 0xac, 0x0a,
|
||||||
|
0xd1, 0x46, 0xbe, 0xc2, 0x2d, 0xa6, 0x67, 0x69, 0x69, 0x55, 0x8a, 0xbd, 0x67, 0xd9, 0x31,
|
||||||
|
0xc7, 0x80, 0x7c, 0xd5, 0xb2, 0xbe, 0x83, 0x17, 0x7a, 0x2e, 0xf4, 0x3e, 0x14, 0xa5, 0x62,
|
||||||
|
0x77, 0xa5, 0xdb, 0x77, 0x58, 0x35, 0x5f, 0xc4, 0x6c, 0xd2, 0xf2, 0x38, 0x91, 0x74, 0x80,
|
||||||
|
0x95, 0x52, 0xd2, 0xaf, 0xe2, 0x1b, 0x12, 0xfe, 0x4b, 0x5f, 0x84, 0x5f, 0x7d, 0x7e, 0x0b,
|
||||||
|
0xd9, 0x42, 0x72, 0xf1, 0x32, 0x1d, 0x8d, 0x5c, 0xcb, 0x20, 0x05, 0x4f, 0xbe, 0xbf, 0x40,
|
||||||
|
0xe9, 0xa6, 0x9f, 0xff, 0x05, 0xe1, 0x73, 0x52, 0x65, 0xb4, 0x59, 0x45, 0x04, 0x10, 0xe1,
|
||||||
|
0xdc, 0x0b, 0x30, 0xaa, 0x23, 0x4d, 0xb9, 0x58, 0xe5, 0xf1, 0xa3, 0x9c, 0xf2, 0xf7, 0xaf,
|
||||||
|
0xbc, 0xe3, 0xa7, 0x0d, 0x68, 0x97, 0x6c, 0x2b, 0x33, 0x60, 0xe3, 0xce, 0x7c, 0xda, 0xd1,
|
||||||
|
0x2d, 0x78, 0x52, 0x10, 0xa0, 0xf7, 0x9a, 0xf4, 0x79, 0xdb, 0xa5, 0x2a, 0x71, 0xc6, 0xcf,
|
||||||
|
0xa0, 0x68, 0xd0, 0x32, 0x2a, 0xd3, 0xb2, 0xe8, 0x03, 0x27, 0xbe, 0x55, 0xfd, 0x0e, 0x90,
|
||||||
|
0xa2, 0x76, 0x8c, 0xdc, 0xbd, 0x69, 0x9c, 0xb6, 0x18, 0x92, 0xe3, 0xb3, 0x23, 0x1d, 0x3c,
|
||||||
|
0x85, 0x2a, 0x2b, 0x04, 0x3a, 0xf5, 0xee, 0xf8, 0xd2, 0xdd, 0x6d, 0x52, 0xa2, 0x45, 0x75,
|
||||||
|
0xd9, 0xa1, 0x03, 0x23, 0x83, 0x24, 0x04, 0xe7, 0xee, 0xa2, 0x14, 0x4e, 0xa9, 0xde, 0x4e,
|
||||||
|
0x9d, 0x24, 0x1a, 0x63, 0xd3, 0x4b, 0xf7, 0x71, 0xc1, 0xe7, 0xfb, 0x48, 0xa4, 0x7c, 0x39,
|
||||||
|
0xcb, 0x80, 0xdd, 0x5e, 0xaf, 0x0d, 0xca, 0xef, 0x58, 0x17, 0xf4, 0xca, 0x0c, 0x00, 0x30,
|
||||||
|
0x68, 0x3e, 0x5d, 0x9b, 0xc3, 0x19, 0x27, 0x7a, 0x35, 0x32, 0x5c, 0x7b, 0x92, 0x16, 0x7f,
|
||||||
|
0x6e, 0x86, 0x6b, 0x50, 0x7a, 0xd6, 0x15, 0x10, 0x16, 0xa8, 0x28, 0xb1, 0xa1, 0xd8, 0xda,
|
||||||
|
0xc8, 0xfd, 0x5b, 0xe2, 0xc0, 0xd6, 0x8d, 0x75, 0xbd, 0x1c, 0x0b, 0x27, 0xfe, 0x1d, 0x09,
|
||||||
|
0x23, 0x13, 0x4f, 0x5a, 0x5a, 0xf8, 0xbe, 0x5d, 0x31, 0x8a, 0x81, 0xaf, 0xbe, 0xed, 0x00,
|
||||||
|
0x43, 0x14, 0x8f, 0xa5, 0x4a, 0xfe, 0x90, 0xe1, 0x67, 0x25, 0x29, 0x52, 0x2f, 0x26, 0x17,
|
||||||
|
0xef, 0x6e, 0xe6, 0x1e, 0xaf, 0x7f, 0x4a, 0x40, 0x15, 0xc7, 0x6e, 0x8d, 0x60, 0x92, 0xd6,
|
||||||
|
0x8d, 0x95, 0xca, 0xff, 0x8e, 0xfe, 0x4b, 0x8d, 0x1a, 0x83, 0x40, 0xe6, 0xb7, 0xbc, 0x6b,
|
||||||
|
0xd6, 0x39, 0x53, 0xd0, 0x4a, 0xe6, 0x1f, 0x1f, 0xb1, 0x16, 0x6a, 0xae, 0x6a, 0x6d, 0xe3,
|
||||||
|
0xe6, 0xed, 0x4e, 0xff, 0x49, 0x28, 0xc7, 0xaf, 0xb4, 0x14, 0x9f, 0x85, 0x9f, 0xfe, 0x6a,
|
||||||
|
0x92, 0x93, 0x9c, 0x6f, 0xff, 0x4a, 0xd4, 0x3e, 0x26, 0xd9, 0x72, 0x4f, 0x01, 0xe2, 0x54,
|
||||||
|
0x06, 0xc6, 0x7d, 0xb8, 0xef, 0x0b, 0x04, 0x56, 0x3a, 0x51, 0x41, 0xe2, 0x1d, 0xc2, 0x96,
|
||||||
|
0x95, 0xd1, 0x66, 0x16, 0x3b, 0x50, 0x36, 0x3f, 0x2e, 0xf2, 0xb2, 0x25, 0x2d, 0x59, 0x0f,
|
||||||
|
0x23, 0xf2, 0x9d, 0xb0, 0xee, 0x59, 0x89, 0xd0, 0x79, 0x30, 0xc7, 0x54, 0x9b, 0xec, 0xf8,
|
||||||
|
0xd7, 0xdc, 0x5a, 0x11, 0x1d, 0xfb, 0xf0, 0x82, 0x33, 0x3c, 0xff, 0x17, 0xff, 0xfc, 0x92,
|
||||||
|
0xc6, 0x6f, 0x3d, 0x5d, 0x99, 0x85, 0x2a, 0xa1, 0x04, 0xe8, 0x21, 0xed, 0x12, 0x2b, 0x7d,
|
||||||
|
0xbc, 0xa3, 0x36, 0x9b, 0x9f, 0xfd, 0x5d, 0x60, 0x66, 0xe9, 0x39, 0x5e, 0x34, 0x29, 0xa7,
|
||||||
|
0x08, 0x56, 0xf7, 0x4d, 0x19, 0x8d, 0x91, 0xff, 0xc8, 0x8a, 0xe7, 0xe8, 0x22, 0x00, 0x35,
|
||||||
|
0x68, 0x34, 0x93, 0xe7, 0x3b, 0x41, 0xbb, 0xf6, 0x58, 0x2f, 0x10, 0x66, 0x77, 0x69, 0xcd,
|
||||||
|
0x94, 0xb9, 0xbe, 0x59, 0x73, 0x4f, 0xc3, 0x11, 0xa1, 0xb3, 0x13, 0xe2, 0x82, 0xf1, 0x05,
|
||||||
|
0xcb, 0xa7, 0x75, 0xf6, 0x01, 0xb2, 0x24, 0xa9, 0x59, 0x05, 0x59, 0x46, 0xc9, 0x25, 0x39,
|
||||||
|
0x36, 0xee, 0x48, 0x90, 0x83, 0x89, 0xc4, 0xdb, 0xa3, 0x83, 0xd0, 0xd3, 0x62, 0x3f, 0x5e,
|
||||||
|
0x0e, 0x0c, 0xb7, 0x77, 0xb3, 0xd6, 0xbb, 0x37, 0x70, 0xb2, 0xb3, 0x87, 0x60, 0xd7, 0x8a,
|
||||||
|
0xe2, 0x99, 0xa9, 0x0f, 0x18, 0x16, 0xf6, 0xcd, 0x14, 0x4e, 0x2c, 0x7e, 0xfe, 0xf9, 0xa4,
|
||||||
|
0x48, 0xfb, 0xb9, 0x60, 0x13, 0x01, 0xd2, 0x6e, 0xdc, 0x3f, 0xe7, 0x2d, 0x7f, 0xe1, 0x11,
|
||||||
|
0x96, 0x12, 0x9a, 0x90, 0x48, 0x2b, 0x76, 0x78, 0xa6, 0xdd, 0x67, 0x48, 0x68, 0x42, 0xfd,
|
||||||
|
0x74, 0xb6, 0x51, 0xd7, 0x99, 0x07, 0x7d, 0x8b, 0x02, 0xd6, 0x68, 0x36, 0x97, 0x6d, 0x49,
|
||||||
|
0x28, 0xbf, 0xcc, 0x23, 0x8f, 0xed, 0x78, 0x4c, 0x49, 0xb0, 0xd1, 0x9a, 0x3d, 0x1c, 0xdd,
|
||||||
|
0xf0, 0xeb, 0xd5, 0xd4, 0xc2, 0x12, 0xae, 0x5d, 0x00, 0xe0, 0xf4, 0x84, 0x10, 0x08, 0x76,
|
||||||
|
0x28, 0x5a, 0x5e, 0xde, 0xe3, 0xad, 0x4e, 0x56, 0xcc, 0x22, 0x85, 0x5f, 0xa9, 0xca, 0xa5,
|
||||||
|
0x4e, 0xc6, 0x82, 0xf0, 0xbb, 0x5a, 0x82, 0xbf, 0x32, 0x54, 0xd2, 0x8a, 0x12, 0x05, 0x6f,
|
||||||
|
0xd8, 0xd1, 0xc0, 0x60, 0x00, 0x41, 0x03, 0xf4, 0xa8, 0xd6, 0xee, 0x9e, 0x5a, 0x75, 0xea,
|
||||||
|
0x76, 0x88, 0xf1, 0x2d, 0x8d, 0x63, 0xfc, 0x14, 0xe9, 0x7b, 0xeb, 0x0b, 0x49, 0xa4, 0x8b,
|
||||||
|
0x86, 0xf4, 0x97, 0x61, 0x22, 0x29, 0x32, 0x23, 0x80, 0x2e, 0x59, 0x44, 0xea, 0xf5, 0x56,
|
||||||
|
0x18, 0x51, 0xc0, 0x60, 0xe1, 0x83, 0x66, 0x1f, 0x1f, 0xa1, 0x13, 0x64, 0xae, 0xbc, 0x59,
|
||||||
|
0xd0, 0xc4, 0x38, 0x70, 0x3f, 0xb5, 0xb5, 0xa2, 0xdc, 0x89, 0x77, 0x70, 0x5a, 0x86, 0xb7,
|
||||||
|
0xde, 0x67, 0x3c, 0x22, 0x83, 0xc8, 0x62, 0x77, 0xb6, 0x5d, 0x7e, 0x41, 0x99, 0x70, 0x7d,
|
||||||
|
0xc3, 0x27, 0x90, 0x7f, 0x3c, 0xc6, 0x90, 0xc7, 0xb9, 0x32, 0xd8, 0x01, 0xdf, 0x02, 0x20,
|
||||||
|
0x27, 0x8f, 0x7b, 0x76, 0xb3, 0x0d, 0xfa, 0x93, 0x46, 0x6f, 0xde, 0x23, 0x12, 0xb9, 0x4e,
|
||||||
|
0xb8, 0x36, 0x8e, 0x9c, 0x3a, 0x2f, 0xd4, 0x2b, 0x54, 0xab, 0x63, 0xe6, 0xf1, 0x62, 0x8c,
|
||||||
|
0xd1, 0x1e, 0x87, 0x48, 0x2d, 0x83, 0x93, 0xfe, 0xac, 0x29, 0x82, 0xc2, 0x3c, 0x4f, 0xd0,
|
||||||
|
0x19, 0xe7, 0xa3, 0x99, 0x8d, 0x7d, 0x64, 0x15, 0xde, 0x64, 0xdb, 0xc1, 0x73, 0xe0, 0x78,
|
||||||
|
0x24, 0x23, 0x9e, 0x8a, 0xfb, 0xe2, 0xea, 0xd5, 0x0f, 0x93, 0x51, 0x62, 0x38, 0x41, 0x3e,
|
||||||
|
0x40, 0xa4, 0x2f, 0x7e, 0xb8, 0x11, 0x5c, 0xd3, 0x46, 0x0a, 0x74, 0xcb, 0xb7, 0xd0, 0x15,
|
||||||
|
0x96, 0xf1, 0xe7, 0x48, 0x32, 0x05, 0x69, 0xa8, 0xda, 0x56, 0xee, 0x9f, 0x6a, 0x95, 0xe6,
|
||||||
|
0x0d, 0xd2, 0x2c, 0xc1, 0xc2, 0xa5, 0xf4, 0xd8, 0xc6, 0xd7, 0xf6, 0x1f, 0x6f, 0x88, 0x78,
|
||||||
|
0xab, 0xd4, 0x1f, 0x53, 0xa0, 0xa1, 0x3b, 0x03, 0xb1, 0x4a, 0xcd, 0xbe, 0x25, 0x1c, 0x6f,
|
||||||
|
0xb4, 0x30, 0x41, 0xb5, 0x4a, 0xaa, 0xa5, 0x38, 0x91, 0x77, 0xce, 0x48, 0xc8, 0xe1, 0x34,
|
||||||
|
0xc2, 0x85, 0xdc, 0x9b, 0x24, 0x6f, 0x63, 0x12, 0xaa, 0x97, 0xaf, 0x9e, 0x37, 0x1e, 0xaf,
|
||||||
|
0x94, 0x2c, 0x5c, 0x43, 0xa6, 0x93, 0x17, 0x7d, 0x1c, 0x77, 0x18, 0x0f, 0xb5, 0xf2, 0x66,
|
||||||
|
0x4a, 0xaf, 0xd9, 0x92, 0xfb, 0x47, 0xfc, 0x1f, 0x7a, 0xdb, 0x77, 0x0b, 0x11, 0x61, 0xe0,
|
||||||
|
0x85, 0x12, 0x96, 0xf7, 0x55, 0x09, 0x90, 0xa2, 0x77, 0xdb, 0x9c, 0x9c, 0x8b, 0x04, 0x55,
|
||||||
|
0x45, 0x39, 0x64, 0x4e, 0x46, 0x5f, 0xa2, 0x98, 0xbc, 0xd6, 0x1b, 0x5d, 0x5f, 0x67, 0x21,
|
||||||
|
0xc7, 0x12, 0xe5, 0xe6, 0x13, 0x93, 0x7b, 0x83, 0xd8, 0x5b, 0xcc, 0x2e, 0x77, 0xce, 0x56,
|
||||||
|
0x97, 0xdc, 0x96, 0x70, 0xcc, 0x47, 0x1a, 0x79, 0x1f, 0xb0, 0x6a, 0xe4, 0x7c, 0xd6, 0xa7,
|
||||||
|
0x28, 0x72, 0x7a, 0x1e, 0xac, 0x54, 0xc0, 0x5d, 0x8c, 0xa1, 0x00, 0xf4, 0x2e, 0x86, 0x28,
|
||||||
|
0x3a, 0x82, 0xce, 0xbc, 0xf0, 0xfd, 0x2d, 0xb1, 0xc4, 0x9f, 0x6d, 0x6b, 0xba, 0x9e, 0x9b,
|
||||||
|
0xec, 0xb5, 0x38, 0xe2, 0xe9, 0xf8, 0x57, 0x74, 0xa6, 0x9b, 0x7b, 0xec, 0xe2, 0x90, 0x0d,
|
||||||
|
0xec, 0x3e, 0xf0, 0x1b, 0x2b, 0x38, 0x9c, 0x82, 0xd9, 0xd1, 0xbe, 0xe1, 0x08, 0x7f, 0x02,
|
||||||
|
0x54, 0xbc, 0x0b, 0x90, 0x14, 0x57, 0xa2, 0x4e, 0x56, 0xbe, 0x1b, 0xdf, 0x48, 0x9c, 0x17,
|
||||||
|
0xa1, 0x70, 0xa2, 0x8c, 0x74, 0x74, 0x24, 0xbf, 0xe0, 0x46, 0xb7, 0xdc, 0xa4, 0xb5, 0x66,
|
||||||
|
0x44, 0xb3, 0x53, 0x0e, 0xa4, 0xe5, 0xb4, 0x83, 0x06, 0x1f, 0x78, 0x2a, 0xe2, 0x16, 0x5c,
|
||||||
|
0x79, 0x00, 0xab, 0x0a, 0x08, 0x57, 0xe5, 0xbc, 0x2c, 0x9b, 0x91, 0x19, 0xf6, 0x1d, 0x31,
|
||||||
|
0x25, 0xbb, 0x9b, 0xb5, 0x89, 0x32, 0xb7, 0x53, 0xb9, 0x49, 0xa4, 0x55, 0xc5, 0x9d, 0x2b,
|
||||||
|
0xa1, 0xeb, 0xd5, 0xec, 0x02, 0x40, 0x14, 0x44, 0x35, 0xc1, 0x65, 0xd7, 0xae, 0x4c, 0xf8,
|
||||||
|
0x16, 0xf5, 0x70, 0x62, 0x28, 0xcd, 0x58, 0x71, 0x01, 0xcb, 0x85, 0x09, 0x24, 0x91, 0xf0,
|
||||||
|
0x18, 0xfa, 0xc6, 0x37, 0x07, 0xde, 0xe7, 0x43, 0xed, 0x3a, 0xeb, 0x98, 0x97, 0xf4, 0xc5,
|
||||||
|
0xf3, 0x60, 0xa5, 0x83, 0x60, 0x1a, 0xf1, 0x81, 0x03, 0x06, 0x2c, 0x1f, 0x38, 0x71, 0x61,
|
||||||
|
0x30, 0x21, 0x8a, 0x49, 0xb4, 0x2a, 0xa6, 0x03, 0x0e, 0x1d, 0x1d, 0x79, 0xc0, 0xe5, 0x5d,
|
||||||
|
0xd1, 0x82, 0x37, 0x1b, 0x70, 0x3a, 0xd2, 0x65, 0x48, 0x59, 0xc0, 0xa2, 0xf3, 0x8b, 0x82,
|
||||||
|
0x24, 0xf5, 0xfe, 0x2a, 0xdd, 0x8d, 0x3a, 0xe9, 0xe5, 0x1c, 0x92, 0xc7, 0x6a, 0x43, 0xde,
|
||||||
|
0x78, 0xb3, 0x33, 0xa0, 0x9a, 0x78, 0x4a, 0x54, 0xba, 0x01, 0x84, 0xd2, 0xb2, 0xa4, 0x6f,
|
||||||
|
0x28, 0x21, 0xf2, 0xc4, 0x21, 0x9f, 0x18, 0x72, 0x16, 0x46, 0x6d, 0xfa, 0xf2, 0xa7, 0x7c,
|
||||||
|
0x99, 0xa4, 0x2c, 0x93, 0x4d, 0xba, 0xdd, 0xa7, 0x59, 0x50, 0x0b, 0x34, 0x48, 0x63, 0x6f,
|
||||||
|
0x0d, 0x4b, 0x81, 0x22, 0x3b, 0x24, 0x9b, 0x37, 0x4b, 0xd3, 0x94, 0x23, 0xc0, 0x71, 0x39,
|
||||||
|
0x91, 0xd0, 0x06, 0x2e, 0xd2, 0xae, 0x7c, 0xfd, 0xfd, 0x4d, 0x4a, 0x95, 0x0a, 0xd0, 0x84,
|
||||||
|
0xbf, 0x8c, 0x5c, 0xe4, 0xc1, 0x10, 0xfa, 0xe6, 0x26, 0x18, 0xea, 0x75, 0x3e, 0x7d, 0x0b,
|
||||||
|
0xc5, 0x9d, 0xbb, 0x14, 0x3c, 0xa5, 0xe3, 0x19, 0x2b, 0xdd, 0xcd, 0xbb, 0xb4, 0x48, 0x9e,
|
||||||
|
0x8c, 0xa5, 0xf2, 0xcb, 0x19, 0xa9, 0x8f, 0x0c, 0x0b, 0x36, 0x73, 0xd7, 0x78, 0x2b, 0x64,
|
||||||
|
0xc9, 0x8c, 0x4a, 0xb2, 0x8f, 0xe9, 0xd9, 0x51, 0xb1, 0x84, 0x49, 0xd1, 0xec, 0x73, 0xa6,
|
||||||
|
0xb1, 0x41, 0x70, 0xa0, 0xd3, 0xea, 0xb4, 0xf8, 0x50, 0x57, 0xb6, 0x69, 0xda, 0x4a, 0xe6,
|
||||||
|
0xe0, 0x73, 0xba, 0xdc, 0x98, 0xc4, 0x0e, 0xab, 0xc7, 0xbd, 0x8a, 0xf6, 0xe3, 0xc1, 0x0b,
|
||||||
|
0xc3, 0x5b, 0x48, 0xa1, 0x79, 0xab, 0xae, 0x9b, 0x17, 0xbd, 0x56, 0x3b, 0x0c, 0x38, 0xbd,
|
||||||
|
0xed, 0x86, 0x95, 0x05, 0xf4, 0x32, 0xf9, 0xdc, 0x87, 0x4f, 0x78, 0x9a, 0xb0, 0x6f, 0x2b,
|
||||||
|
0x76, 0xd2, 0xf4, 0x1f, 0x65, 0xf8, 0xd0, 0x9f, 0x8d, 0x3c, 0xb2, 0x53, 0x8c, 0xca, 0xa0,
|
||||||
|
0x2b, 0x6d, 0xfb, 0x65, 0x96, 0xde, 0x7c, 0x64, 0xbb, 0xf7, 0x7e, 0x3d, 0x8d, 0xfb, 0xd1,
|
||||||
|
0x2d, 0xf1, 0xc3, 0x1a, 0x66, 0x8a, 0x8f, 0x5e, 0x89, 0x37, 0x19, 0xe7, 0x9b, 0xee, 0xf0,
|
||||||
|
0xc1, 0xe7, 0xac, 0xe5, 0x15, 0x2f, 0x6d, 0xfb, 0x57, 0xca, 0x78, 0xd0, 0xaa, 0x19, 0xc0,
|
||||||
|
0x80, 0x67, 0xc9, 0x2f, 0x81, 0x26, 0x7f, 0xbe, 0xdf, 0xde, 0x50, 0x00, 0x2b, 0x1b, 0x17,
|
||||||
|
0x2a, 0x5d, 0x54, 0xfa, 0x46, 0xc1, 0x3f, 0xb7, 0x2f, 0xc8, 0x31, 0xf4, 0x58, 0x43, 0x36,
|
||||||
|
0xae, 0x91, 0xc4, 0x46, 0xc4, 0x93, 0xaf, 0x05, 0x9e, 0xa3, 0xba, 0x0c, 0x07, 0x2f, 0x0c,
|
||||||
|
0xeb, 0x2f, 0x4d, 0x4a, 0x90, 0xd8, 0xc0, 0x51, 0x0f, 0xa5, 0x97, 0x09, 0x16, 0xfa, 0x24,
|
||||||
|
0xc3, 0x99, 0xe6, 0x1c, 0x9e, 0xed, 0x03, 0x76, 0x57, 0xce, 0x29, 0x73, 0x54, 0x19, 0x5a,
|
||||||
|
0x20, 0x65, 0x52, 0xa6, 0xfa, 0x97, 0x00, 0x52, 0x23, 0xbb, 0x74, 0x9b, 0x6e, 0xf3, 0x25,
|
||||||
|
0x94, 0x9c, 0x66, 0x0f, 0x8b, 0x67, 0x62, 0x1a, 0x13, 0xdb, 0xd5, 0xdb, 0xdb, 0xb9, 0x11,
|
||||||
|
0x02, 0x13, 0x63, 0xe4, 0x6e, 0x41, 0x8a, 0xa0, 0xc2, 0x52, 0x71, 0x66, 0xde, 0x3b, 0x3d,
|
||||||
|
0x6c, 0xd3, 0xaa, 0x5f, 0x78, 0x3b, 0xf2, 0x7b, 0xad, 0x71, 0x48, 0x2e, 0x06, 0x90, 0x4c,
|
||||||
|
0x76, 0x89, 0x99, 0xb5, 0x91, 0x61, 0x29, 0x74, 0x8d, 0x90, 0xd6, 0x1b, 0x60, 0x11, 0xf6,
|
||||||
|
0xc0, 0xa0, 0xc7, 0x3c, 0x1e, 0xf6, 0xec, 0x80, 0x91, 0xe8, 0x6d, 0x46, 0xe0, 0x2c, 0xda,
|
||||||
|
0x25, 0xdb, 0x18, 0xdb, 0xb1, 0xbe, 0x7c, 0x87, 0x14, 0xa9, 0xa3, 0x46, 0xdb, 0x6e, 0xeb,
|
||||||
|
0x5d, 0x98, 0xd2, 0x4c, 0xfa, 0x09, 0x13, 0x71, 0xee, 0x51, 0xae, 0x5d, 0x57, 0x79, 0x80,
|
||||||
|
0x02, 0x43, 0x7b, 0xf7, 0x92, 0x3c, 0xf9, 0x03, 0x07, 0x4f, 0x6a, 0x53, 0x9e, 0x35, 0x2d,
|
||||||
|
0x40, 0x29, 0x7d, 0x44, 0x39, 0xd2, 0xb4, 0x48, 0xa7, 0x4f, 0xa5, 0x90, 0x9d, 0xb7, 0x4e,
|
||||||
|
0xa0, 0xb5, 0xb7, 0x92, 0x0f, 0x1c, 0x18, 0xdd, 0x4c, 0xff, 0xd4, 0xf9, 0x53, 0xd1, 0x82,
|
||||||
|
0x38, 0xc5, 0xcc, 0xe2, 0x36, 0x2d, 0xf7, 0x18, 0x07, 0xda, 0x5b, 0xf6, 0xef, 0xe5, 0xcb,
|
||||||
|
0xaa, 0x90, 0xd2, 0x84, 0x25, 0xbc, 0x4f, 0x4a, 0x3b, 0x10, 0x0f, 0x81, 0x92, 0xe4, 0xda,
|
||||||
|
0x84, 0xad, 0x8b, 0xbb, 0x94, 0xc5, 0xf4, 0x4c, 0x25, 0xd2, 0x08, 0x97, 0xe0, 0x98, 0x0b,
|
||||||
|
0xbe, 0xe7, 0xaa, 0x40, 0x06, 0xfa, 0xe4, 0x79, 0xab, 0x76, 0x1f, 0xb6, 0x7f, 0x72, 0x48,
|
||||||
|
0x5c, 0x27, 0x8b, 0xab, 0xef, 0x13, 0xe1, 0x0c, 0xb1, 0x79, 0x7b, 0x6d, 0x8f, 0x0b, 0x90,
|
||||||
|
0x22, 0x7f, 0x2f, 0xa5, 0x71, 0xca, 0xb7, 0xc0, 0xbb, 0x31, 0x23, 0x03, 0x44, 0xd2, 0x51,
|
||||||
|
0x74, 0x08, 0x85, 0xad, 0x1e, 0xfb, 0xc3, 0xa2, 0xa1, 0xe1, 0x3e, 0x14, 0x0e, 0xf2, 0x0a,
|
||||||
|
0xb3, 0x9d, 0x74, 0x14, 0x50, 0xff, 0xfe, 0x95, 0xed, 0x02, 0x76, 0xe6, 0xf7, 0x0b, 0x32,
|
||||||
|
0x4e, 0x40, 0xb0, 0xd2, 0x67, 0x74, 0x92, 0x51, 0x1e, 0x54, 0x6f, 0x30, 0x6f, 0x58, 0x6a,
|
||||||
|
0xbb, 0x8a, 0x6c, 0xa6, 0x6d, 0x92, 0xe3, 0x3e, 0x0c, 0x33, 0x7c, 0xfc, 0x87, 0x12, 0xb8,
|
||||||
|
0x61, 0x70, 0xa6, 0x6c, 0x28, 0xad, 0xa2, 0x55, 0x81, 0x58, 0xd5, 0xc7, 0xb6, 0xd1, 0xdf,
|
||||||
|
0x47, 0x5d, 0x07, 0x1f, 0xed, 0xfd, 0x4e, 0x0f, 0x3c, 0xe3, 0x9d, 0xae, 0xeb, 0xf6, 0x3a,
|
||||||
|
0xb6, 0x0e, 0x5e, 0xc9, 0x9f, 0xc9, 0x5e, 0xbc, 0x37, 0xcf, 0x81, 0x04, 0x60, 0x26, 0xe4,
|
||||||
|
0x8b, 0x90, 0xdb, 0xf1, 0xc2, 0x66, 0x87, 0xd2, 0x29, 0x72, 0x01, 0xa6, 0xcd, 0x01, 0xdf,
|
||||||
|
0x9a, 0xfb, 0x4d, 0x62, 0xcb, 0x4d, 0x59, 0x18, 0xd2, 0x3f, 0x79, 0xf7, 0xaf, 0xda, 0x10,
|
||||||
|
0x66, 0xb6, 0x3e, 0x7e, 0x7b, 0xcb, 0xb6, 0xa0, 0xd7, 0xa8, 0x5b, 0xe7, 0x8e, 0xa0, 0x24,
|
||||||
|
0xf4, 0x55, 0x43, 0x00, 0xda, 0x86, 0x50, 0xec, 0x0a, 0x04, 0x27, 0xb1, 0x98, 0x40, 0x5c,
|
||||||
|
0xb1, 0xa5, 0x18, 0x87, 0xa9, 0x88, 0x87, 0x85, 0xe0, 0x89, 0xd5, 0xe2, 0x24, 0xef, 0x65,
|
||||||
|
0xac, 0x2c, 0xd1, 0x3a, 0xe7, 0x67, 0xee, 0xc4, 0xd6, 0x3a, 0x76, 0x2a, 0x55, 0x03, 0x5b,
|
||||||
|
0x0b, 0xde, 0x5e, 0x38, 0x5a, 0xb7, 0x7d, 0xb3, 0x82, 0x39, 0x5c, 0x98, 0xc3, 0x2f, 0x8d,
|
||||||
|
0x53, 0xa0, 0x41, 0x7d, 0xa8, 0x83, 0x47, 0x4a, 0xb0, 0x42, 0xc8, 0xeb, 0xf4, 0xfb, 0x9e,
|
||||||
|
0xe9, 0x82, 0xe3, 0xf6, 0x4d, 0x16, 0xe4, 0xd9, 0xd1, 0xca, 0x56, 0xae, 0x09, 0xe7, 0xcf,
|
||||||
|
0xaa, 0x25, 0x15, 0x91, 0xce, 0x15, 0xa9, 0x87, 0x50, 0x80, 0x38, 0xcd, 0x6a, 0x64, 0x4d,
|
||||||
|
0xb5, 0x55, 0x63, 0xc7, 0x9c, 0xb0, 0x52, 0xb0, 0x3d, 0x5a, 0x8b, 0x65, 0x19, 0x33, 0x43,
|
||||||
|
0xa2, 0x97, 0x20, 0xad, 0x79, 0xa6, 0xe8, 0x82, 0x06, 0x39, 0x45, 0x8b, 0x22, 0x35, 0x28,
|
||||||
|
0x72, 0x45, 0xc8, 0xca, 0xa4, 0xc3, 0x10, 0x20, 0x22, 0x83, 0x8f, 0x39, 0x49, 0x83, 0x72,
|
||||||
|
0x6d, 0xf4, 0x56, 0xfd, 0x55, 0x43, 0x60, 0x3d, 0x75, 0xa3, 0x4e, 0x14, 0x5b, 0xb8, 0xff,
|
||||||
|
0x4f, 0x17, 0xd9, 0x93, 0xd7, 0xc0, 0xaf, 0x5c, 0xb9, 0x65, 0xa5, 0x86, 0x8a, 0x9a, 0x35,
|
||||||
|
0x5d, 0x95, 0x30, 0x21, 0xc3, 0x38, 0x82, 0x05, 0x0b, 0xb8, 0x02, 0x20, 0xf1, 0x8a, 0x37,
|
||||||
|
0x15, 0x0a, 0xc2, 0x46, 0x8a, 0x16, 0x6f, 0x0d, 0x3a, 0x5b, 0x12, 0x6e, 0xee, 0xbf, 0xaf,
|
||||||
|
0xfb, 0x04, 0xe5, 0x34, 0xcc, 0x44, 0x2c, 0x3c, 0x22, 0x7c, 0x4f, 0xd7, 0xad, 0xe1, 0xe2,
|
||||||
|
0x12, 0xe6, 0xda, 0x69, 0x6f, 0x9c, 0xc8, 0x1f, 0xb9, 0x7e, 0x42, 0x20, 0x7d, 0x21, 0x0a,
|
||||||
|
0x0f, 0xb6, 0x16, 0x59, 0x01, 0x91, 0x16, 0xfe, 0xa4, 0x7b, 0xb6, 0x36, 0x43, 0x72, 0xbf,
|
||||||
|
0x33, 0x71, 0xb8, 0x5d, 0x8a, 0x4f, 0x91, 0xe0, 0x79, 0xb5, 0x40, 0xda, 0x9f, 0x02, 0xbe,
|
||||||
|
0x35, 0x60, 0xc0, 0xef, 0xc9, 0x2f, 0x42, 0xd3, 0xcd, 0xef, 0xde, 0x10, 0x71, 0x14, 0x8d,
|
||||||
|
0x86, 0x29, 0xcd, 0x31, 0x39, 0x90, 0xe0, 0x2d, 0x28, 0x97, 0xe4, 0xb3, 0xe5, 0xd7, 0x61,
|
||||||
|
0xe3, 0x2b, 0x21, 0xe7, 0xc5, 0x4b, 0xd6, 0xe9, 0xdb, 0x51, 0x03, 0xa2, 0x0e, 0x7c, 0x7e,
|
||||||
|
0x95, 0xa8, 0xf6, 0x8b, 0x95, 0x8f, 0x6e, 0xfd, 0x54, 0xfd, 0x28, 0x71, 0x4a, 0xfc, 0x75,
|
||||||
|
0x54, 0x19, 0x8c, 0xd3, 0x8a, 0x9b, 0x94, 0xcd, 0x33, 0x60, 0x80, 0x7a, 0xd4, 0x68, 0x38,
|
||||||
|
0x29, 0x0e, 0xf0, 0xc1, 0xeb, 0xac, 0xaf, 0xb1, 0xe6, 0xce, 0xbd, 0xd1, 0xfd, 0xbc, 0x23,
|
||||||
|
0x85, 0x8d, 0x97, 0xf4, 0xc9, 0xf9, 0xbd, 0x69, 0xd2, 0x0c, 0x60, 0x12, 0x05, 0x82, 0x6e,
|
||||||
|
0x5a, 0x6e, 0xfd, 0x55, 0xcc, 0xd8, 0xe6, 0xed, 0x54, 0xde, 0xdb, 0xcc, 0xf9, 0x85, 0x0b,
|
||||||
|
0xf6, 0x42, 0x39, 0x76, 0xde, 0xab, 0x08, 0xd7, 0x65, 0xe8, 0x19, 0xbd, 0x72, 0xec, 0x53,
|
||||||
|
0x7d, 0xc8, 0xa6, 0x00, 0xb3, 0x3e, 0x5b, 0x7d, 0xa0, 0x7b, 0xaa, 0x6e, 0xc5, 0x45, 0x12,
|
||||||
|
0xe3, 0xac, 0x02, 0x1c, 0x01, 0xb8, 0x2b, 0x2b, 0xd6, 0xf8, 0x2e, 0x96, 0x3a, 0x5e, 0x6e,
|
||||||
|
0xda, 0xf9, 0x6c, 0xac, 0x36, 0xf8, 0xcd, 0xef, 0x05, 0x8d, 0x8f, 0xe7, 0x6c, 0x39, 0x24,
|
||||||
|
0xb3, 0x8d, 0xed, 0xd1, 0x70, 0xa6, 0x20, 0x1e, 0x2b, 0x1d, 0x2c, 0x40, 0x16, 0xd6, 0x23,
|
||||||
|
0xb0, 0x99, 0xaa, 0x74, 0x31, 0xbe, 0xdc, 0x28, 0xd4, 0x64, 0xfa, 0xd2, 0x8d, 0xdb, 0xa1,
|
||||||
|
0x32, 0xaf, 0xdc, 0xb1, 0x71, 0xb3, 0x4d, 0x0a, 0x3a, 0x3a, 0x53, 0x11, 0x8c, 0x11, 0x8c,
|
||||||
|
0xe7, 0xd5, 0xdb, 0xdd, 0x67, 0xb8, 0x1a, 0x39, 0x0e, 0xf6, 0x69, 0xd8, 0x1b, 0xcb, 0xe5,
|
||||||
|
0xc5, 0xa6, 0x3d, 0x3b, 0xfe, 0xe1, 0x05, 0x48, 0x83, 0x67, 0x7f, 0xf1, 0x9c, 0x70, 0x7e,
|
||||||
|
0x70, 0x5c, 0xc4, 0xd3, 0x78, 0x8b, 0x80, 0x87, 0xf5, 0x94, 0x2d, 0x0a, 0xbf, 0x82, 0x13,
|
||||||
|
0xad, 0x36, 0x10, 0x0a, 0x60, 0xaa, 0xc4, 0xa3, 0xcd, 0xf1, 0xa9, 0xa1, 0x49, 0xf5, 0x41,
|
||||||
|
0x14, 0xd6, 0xd1, 0xa7, 0xe0, 0x50, 0xce, 0xe2, 0x76, 0xbe, 0x09, 0xc4, 0x3a, 0x68, 0xc5,
|
||||||
|
0x8a, 0x1f, 0x8e, 0xd0, 0x4d, 0x90, 0x92, 0xc8, 0x3b, 0x63, 0xae, 0xc2, 0xfe, 0x77, 0x8c,
|
||||||
|
0x4b, 0xa6, 0x6c, 0x04, 0xff, 0x62, 0xe1, 0x32, 0x04, 0xb8, 0xfd, 0xb3, 0x34, 0x47, 0x85,
|
||||||
|
0x32, 0x6b, 0x50, 0xce, 0xcf, 0x4f, 0x0f, 0x72, 0x41, 0x09, 0x7f, 0xde, 0x5c, 0xe7, 0x08,
|
||||||
|
0xdf, 0x63, 0x09, 0x89, 0xd1, 0x23, 0xb6, 0xe3, 0xbc, 0xff, 0xe4, 0x88, 0x61, 0x67, 0x8e,
|
||||||
|
0x4a, 0xb6, 0x86, 0x08, 0x33, 0xad, 0xac, 0x9f, 0xf3, 0x37, 0xbd, 0xcc, 0xd6, 0x0e, 0x3e,
|
||||||
|
0x4e, 0x4f, 0xc9, 0xff, 0xc8, 0xf6, 0xd8, 0x2a, 0x43, 0x3d, 0x79, 0xf2, 0x5d, 0x87, 0x33,
|
||||||
|
0x1d, 0xf4, 0xfd, 0x80, 0x2c, 0x4f, 0xc4, 0xa5, 0x3a, 0x2f, 0x51, 0xb1, 0x19, 0xf8, 0xed,
|
||||||
|
0xe0, 0xc9, 0x6c, 0x82, 0x2d, 0x43, 0xdd, 0x71, 0x27, 0x32, 0x8b, 0x51, 0x3d, 0xbc, 0x83,
|
||||||
|
0x6b, 0xa8, 0xda, 0x2b, 0xbb, 0xb0, 0xba, 0x5b, 0x30, 0x4f, 0x44, 0xad, 0x99, 0xb7, 0x47,
|
||||||
|
0x35, 0x6f, 0x1f, 0xbe, 0x5f, 0x24, 0x4e, 0xba, 0x92, 0x89, 0xc8, 0xb6, 0x45, 0x12, 0x19,
|
||||||
|
0xee, 0xe7, 0xd8, 0x74, 0xb3, 0x33, 0x41, 0x39, 0x26, 0x4c, 0xc3, 0xb0, 0x22, 0x1e, 0xee,
|
||||||
|
0xd0, 0xfb, 0xc6, 0xa3, 0x7d, 0xaa, 0x7d, 0xa1, 0x51, 0x98, 0xe8, 0xcc, 0x58, 0x39, 0x22,
|
||||||
|
0x1e, 0xe7, 0xf0, 0xb4, 0xd3, 0x7c, 0xa4, 0xa6, 0x10, 0xba, 0x2f, 0x41, 0xd6, 0x17, 0x95,
|
||||||
|
0x76, 0xe1, 0xbb, 0xec, 0x43, 0x99, 0x87, 0xd4, 0x13, 0x9b, 0x85, 0x4f, 0x44, 0x32, 0x5a,
|
||||||
|
0xe0, 0x9a, 0xee, 0x29, 0x15, 0x45, 0x05, 0xf7, 0xe4, 0xc9, 0x4d, 0x6b, 0x45, 0xad, 0x1f,
|
||||||
|
0x13, 0x06, 0x29, 0xb4, 0x2b, 0x74, 0x83, 0xe1, 0xdb, 0x3d, 0x99, 0x28, 0xbd, 0x4f, 0xfb,
|
||||||
|
0x0d, 0x03, 0x4d, 0x79, 0x09, 0x7f, 0x12, 0x91, 0xe9, 0x69, 0x40, 0x84, 0xc7, 0x10, 0xd5,
|
||||||
|
0xce, 0xae, 0xbb, 0xa5, 0xb2, 0x35, 0xdb, 0x24, 0xa4, 0x0e, 0xe4, 0x6f, 0x80, 0xb4, 0xb6,
|
||||||
|
0x94, 0xf7, 0x51, 0x5b, 0x0c, 0x5b, 0xae, 0x3f, 0xa5, 0x17, 0xe0, 0x9c, 0xd1, 0x05, 0x31,
|
||||||
|
0x05, 0xc4, 0x14, 0xdd, 0xde, 0x6f, 0x39, 0xa1, 0x9a, 0x46, 0x3d, 0x68, 0x3c, 0xfe, 0x04,
|
||||||
|
0x8e, 0xc2, 0x11, 0x9d, 0xc2, 0x3a, 0xaa, 0xcf, 0x22, 0x26, 0x54, 0xcb, 0x8d, 0x47, 0x61,
|
||||||
|
0x9e, 0xf4, 0x2e, 0xe7, 0x3c, 0xe6, 0xf0, 0xd6, 0x1a, 0xe5, 0x18, 0xbd, 0x9f, 0xa4, 0x3e,
|
||||||
|
0x47, 0xdb, 0x85, 0xe0, 0x8c, 0xbf, 0xdd, 0x19, 0x91, 0x81, 0x80, 0x63, 0x44, 0x0a, 0x96,
|
||||||
|
0xae, 0xde, 0x1f, 0xbc, 0xdb, 0x15, 0x89, 0x71, 0x60, 0x23, 0xc4, 0x0a, 0x96, 0xae, 0xbf,
|
||||||
|
0xfc, 0x7a, 0x76, 0x4f, 0x1c, 0x9b, 0xb4, 0xcb, 0x14, 0x8b, 0x94, 0x8b, 0x94, 0xaa, 0xd6,
|
||||||
|
0x0f, 0x7d, 0x78, 0x72, 0x47, 0x0c, 0x9a, 0x97, 0xac, 0xbb, 0xf4, 0x6a, 0x56, 0x0f, 0x7d,
|
||||||
|
0x59, 0x30, 0xc3, 0x04, 0x6b, 0x54, 0x0b, 0x75, 0x49, 0x10, 0xa2, 0xa7, 0xad, 0xd8, 0x13,
|
||||||
|
0x85, 0x88, 0x73, 0x45, 0xe9, 0x31, 0xc1, 0x00, 0x82, 0x67, 0x4c, 0xfb, 0x74, 0x6a, 0x56,
|
||||||
|
0x2e, 0xbf, 0xdd, 0x19, 0x91, 0x81, 0x80, 0x82, 0x86, 0x6f, 0x5c, 0x3a, 0xf6, 0x4f, 0x1c,
|
||||||
|
0xba, 0xf6, 0x4f, 0xfd, 0x59, 0x11, 0x81, 0x61, 0x21, 0xa1, 0xc0, 0x02, 0x86, 0x6f, 0x3d,
|
||||||
|
0xf8, 0x53, 0x24, 0xca, 0xf7, 0x6c, 0x5a, 0x36, 0xcf, 0xfd, 0x59, 0x11, 0xa0, 0xa3, 0xc4,
|
||||||
|
0x0a, 0x96, 0x8f, 0x9c, 0xba, 0xd7, 0x0d, 0x98, 0xb2, 0xc7, 0xed, 0x58, 0x32, 0xc7, 0xed,
|
||||||
|
0x39, 0xf0, 0x43, 0x04, 0x6b, 0x54, 0x2a, 0xb7, 0xec, 0x5a, 0x36, 0xee, 0x3f, 0xfc, 0x7a,
|
||||||
|
0x76, 0x6e, 0x5e, 0x1f, 0x9d, 0x99, 0x91, 0x81, 0x80, 0x82, 0x86, 0x6f, 0x5c, 0x1b, 0x95,
|
||||||
|
0x89, 0x90, 0xa2, 0xa7, 0xcc, 0x1a, 0x97, 0xac, 0xbb, 0xf4, 0x6a, 0x37, 0xec, 0x3b, 0xf4,
|
||||||
|
0x6a, 0x37, 0xec, 0x3b, 0xf4, 0x4b, 0xf5, 0x49, 0xf1, 0x60, 0x23, 0xa5, 0xa9, 0xb1, 0xc1,
|
||||||
|
0xe1, 0x21, 0xa1, 0xa1, 0xc0, 0xe3, 0x25, 0xa9, 0xb1, 0xe0, 0x42, 0xe7, 0x4c, 0xfb, 0x74,
|
||||||
|
0x6a, 0x37, 0xec, 0x5a, 0x17, 0xac, 0xbb, 0xd5, 0x28, 0xd2, 0x07, 0x6d, 0x58, 0x13, 0x85,
|
||||||
|
0x69, 0x31, 0xe0, 0x42, 0xe7, 0x4c, 0xfb, 0x55, 0x28, 0xd2, 0x07, 0x8c, 0x7b, 0x74, 0x4b,
|
||||||
|
0x14, 0xaa, 0xd6, 0x2e, 0xde, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x47, 0x0c, 0x7b,
|
||||||
|
0x55, 0x09, 0x90, 0x83, 0x65, 0x48, 0x12, 0x87, 0x6d, 0x39, 0xf0, 0x62, 0x46, 0x0e, 0x9e,
|
||||||
|
0x9f, 0xbc, 0xfa, 0x57, 0x2c, 0xbb, 0xd5, 0x09, 0x71, 0x60, 0x5b, 0x08, 0xf7, 0x2b,
|
||||||
|
};
|
||||||
|
#endif
|
396
app/drivers/sensor/pmw33xx/pmw33xx.c
Normal file
396
app/drivers/sensor/pmw33xx/pmw33xx.c
Normal file
|
@ -0,0 +1,396 @@
|
||||||
|
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT pixart_pmw33xx
|
||||||
|
|
||||||
|
#include <drivers/spi.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <device.h>
|
||||||
|
#include <drivers/gpio.h>
|
||||||
|
#include <sys/util.h>
|
||||||
|
#include <sys/byteorder.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <drivers/sensor.h>
|
||||||
|
#include <sys/__assert.h>
|
||||||
|
#include <logging/log.h>
|
||||||
|
#ifdef CONFIG_PMW33XX_3389
|
||||||
|
#include <pmw3389_srom.h>
|
||||||
|
#elif CONFIG_PMW33XX_3360
|
||||||
|
#include <pmw3360_srom.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "pmw33xx.h"
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(PMW33XX, CONFIG_SENSOR_LOG_LEVEL);
|
||||||
|
#define PMW33XX_PID COND_CODE_1(CONFIG_PMW33XX_3389, (PMW33XX_3389_PID), (PMW33XX_3360_PID))
|
||||||
|
|
||||||
|
struct pmw33xx_motion_burst {
|
||||||
|
uint8_t motion;
|
||||||
|
uint8_t observation;
|
||||||
|
int16_t dx;
|
||||||
|
int16_t dy;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
static inline int pmw33xx_cs_select(const struct pmw33xx_gpio_dt_spec *cs_gpio_cfg,
|
||||||
|
const uint8_t value)
|
||||||
|
{
|
||||||
|
return gpio_pin_set(cs_gpio_cfg->port, cs_gpio_cfg->pin, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pmw33xx_access(const struct device *dev, const uint8_t reg, uint8_t *value)
|
||||||
|
{
|
||||||
|
struct pmw33xx_data *data = dev->data;
|
||||||
|
const struct pmw33xx_config *cfg = dev->config;
|
||||||
|
const struct spi_config *spi_cfg = &cfg->bus_cfg.spi_cfg->spi_conf;
|
||||||
|
const struct pmw33xx_gpio_dt_spec *cs_gpio_cfg = &cfg->bus_cfg.spi_cfg->cs_spec;
|
||||||
|
|
||||||
|
uint8_t access[1] = { reg };
|
||||||
|
struct spi_buf_set tx = {
|
||||||
|
.buffers = { &(struct spi_buf){
|
||||||
|
.buf = access,
|
||||||
|
.len = 1,
|
||||||
|
} },
|
||||||
|
.count = 1,
|
||||||
|
};
|
||||||
|
uint8_t result[1] = { *value };
|
||||||
|
struct spi_buf_set rx = {
|
||||||
|
.buffers = { &(struct spi_buf){
|
||||||
|
.buf = result,
|
||||||
|
.len = 1,
|
||||||
|
} },
|
||||||
|
.count = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
pmw33xx_cs_select(cs_gpio_cfg, 0);
|
||||||
|
|
||||||
|
int err = spi_write(data->bus, spi_cfg, &tx);
|
||||||
|
k_sleep(K_USEC(120)); //Tsrad
|
||||||
|
if (err) {
|
||||||
|
pmw33xx_cs_select(cs_gpio_cfg, 1);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((reg & PMW33XX_WR_MASK))
|
||||||
|
err = spi_write(data->bus, spi_cfg, &rx);
|
||||||
|
else
|
||||||
|
err = spi_read(data->bus, spi_cfg, &rx);
|
||||||
|
pmw33xx_cs_select(cs_gpio_cfg, 1);
|
||||||
|
k_sleep(K_USEC(160));
|
||||||
|
if ((reg & PMW33XX_WR_MASK) == 0)
|
||||||
|
*value = result[0];
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
static int pmw33xx_read_reg(const struct device *dev, const uint8_t reg, uint8_t *value)
|
||||||
|
{
|
||||||
|
return pmw33xx_access(dev, reg & PMW33XX_RD_MASK, value);
|
||||||
|
}
|
||||||
|
static int pmw33xx_write_reg(const struct device *dev, const uint8_t reg, const uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t v = value;
|
||||||
|
return pmw33xx_access(dev, reg | PMW33XX_WR_MASK, &v);
|
||||||
|
}
|
||||||
|
static int pmw33xx_write_srom(const struct device *dev)
|
||||||
|
{
|
||||||
|
struct pmw33xx_data *data = dev->data;
|
||||||
|
const struct pmw33xx_config *cfg = dev->config;
|
||||||
|
const struct spi_config *spi_cfg = &cfg->bus_cfg.spi_cfg->spi_conf;
|
||||||
|
const struct pmw33xx_gpio_dt_spec *cs_gpio_cfg = &cfg->bus_cfg.spi_cfg->cs_spec;
|
||||||
|
uint8_t access[1] = { PMW33XX_REG_SROM_BURST | PMW33XX_WR_MASK };
|
||||||
|
struct spi_buf_set tx = {
|
||||||
|
.buffers = { &(struct spi_buf){
|
||||||
|
.buf = access,
|
||||||
|
.len = 1,
|
||||||
|
} },
|
||||||
|
.count = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
pmw33xx_write_reg(dev, PMW33XX_REG_SROM_EN, PMW33XX_SROM_DWNLD_CMD);
|
||||||
|
k_sleep(K_USEC(15));
|
||||||
|
pmw33xx_write_reg(dev, PMW33XX_REG_SROM_EN, PMW33XX_SROM_DWNLD_START_CMD);
|
||||||
|
|
||||||
|
pmw33xx_cs_select(cs_gpio_cfg, 0);
|
||||||
|
|
||||||
|
int err = spi_write(data->bus, spi_cfg, &tx);
|
||||||
|
|
||||||
|
k_sleep(K_USEC(15));
|
||||||
|
if (err) {
|
||||||
|
pmw33xx_cs_select(cs_gpio_cfg, 1);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < sizeof(SROM); i++) {
|
||||||
|
access[0] = SROM[i];
|
||||||
|
err = spi_write(data->bus, spi_cfg, &tx);
|
||||||
|
k_sleep(K_USEC(15));
|
||||||
|
if (err) {
|
||||||
|
pmw33xx_cs_select(cs_gpio_cfg, 1);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pmw33xx_cs_select(cs_gpio_cfg, 1);
|
||||||
|
k_sleep(K_MSEC(2)); //Tbexit
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pmw33xx_read_motion_burst(const struct device *dev, struct pmw33xx_motion_burst *burst)
|
||||||
|
{
|
||||||
|
struct pmw33xx_data *data = dev->data;
|
||||||
|
const struct pmw33xx_config *cfg = dev->config;
|
||||||
|
const struct spi_config *spi_cfg = &cfg->bus_cfg.spi_cfg->spi_conf;
|
||||||
|
const struct pmw33xx_gpio_dt_spec *cs_gpio_cfg = &cfg->bus_cfg.spi_cfg->cs_spec;
|
||||||
|
|
||||||
|
uint8_t access[1] = { PMW33XX_REG_BURST };
|
||||||
|
struct spi_buf_set tx = {
|
||||||
|
.buffers = { &(struct spi_buf){
|
||||||
|
.buf = access,
|
||||||
|
.len = 1,
|
||||||
|
} },
|
||||||
|
.count = 1,
|
||||||
|
};
|
||||||
|
struct spi_buf_set rx = {
|
||||||
|
.buffers = { &(struct spi_buf){
|
||||||
|
.buf = (uint8_t *)burst,
|
||||||
|
.len = sizeof(struct pmw33xx_motion_burst),
|
||||||
|
} },
|
||||||
|
.count = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
pmw33xx_cs_select(cs_gpio_cfg, 0);
|
||||||
|
|
||||||
|
int err = spi_write(data->bus, spi_cfg, &tx);
|
||||||
|
k_sleep(K_USEC(35)); // tsrad motbr
|
||||||
|
if (err) {
|
||||||
|
pmw33xx_cs_select(cs_gpio_cfg, 1);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
err = spi_read(data->bus, spi_cfg, &rx);
|
||||||
|
pmw33xx_cs_select(cs_gpio_cfg, 1);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts twos complement data to an int16
|
||||||
|
static int16_t pmw33xx_raw_to_int16(const uint8_t src[2])
|
||||||
|
{
|
||||||
|
int16_t res = sys_get_be16(src);
|
||||||
|
if (res > BIT_MASK(15))
|
||||||
|
res -= BIT(16);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pmw33xx_read_raw(const struct device *dev, const uint8_t reg_high, const uint8_t reg_low,
|
||||||
|
int16_t *value)
|
||||||
|
{
|
||||||
|
uint8_t raw[2] = { 0x0, 0x0 };
|
||||||
|
int err;
|
||||||
|
err = pmw33xx_read_reg(dev, reg_high, &raw[0]);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("could not read high byte at %x", reg_high);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
k_sleep(K_USEC(100));
|
||||||
|
err = pmw33xx_read_reg(dev, reg_low, &raw[1]);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("could not read low byte at %x", reg_low);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
k_sleep(K_USEC(100));
|
||||||
|
*value = pmw33xx_raw_to_int16(raw);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pmw33xx_spi_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
struct pmw33xx_data *data = dev->data;
|
||||||
|
const struct pmw33xx_config *cfg = dev->config;
|
||||||
|
const struct pmw33xx_spi_cfg *spi_cfg = cfg->bus_cfg.spi_cfg;
|
||||||
|
const struct pmw33xx_gpio_dt_spec *cs_gpio_cfg = &cfg->bus_cfg.spi_cfg->cs_spec;
|
||||||
|
|
||||||
|
int err;
|
||||||
|
err = gpio_pin_configure(cs_gpio_cfg->port, cs_gpio_cfg->pin, GPIO_OUTPUT_ACTIVE);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("could configure cs pin %d", err);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pmw33xx_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
||||||
|
{
|
||||||
|
struct pmw33xx_data *data = dev->data;
|
||||||
|
const struct pmw33xx_config *cfg = dev->config;
|
||||||
|
struct pmw33xx_motion_burst burst;
|
||||||
|
|
||||||
|
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_POS_DX && chan != SENSOR_CHAN_POS_DY)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
int err = pmw33xx_read_motion_burst(dev, &burst);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_POS_DX)
|
||||||
|
data->dx = burst.dx;
|
||||||
|
if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_POS_DY)
|
||||||
|
data->dy = burst.dy;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pmw33xx_channel_get(const struct device *dev, enum sensor_channel chan,
|
||||||
|
struct sensor_value *val)
|
||||||
|
{
|
||||||
|
struct pmw33xx_data *data = dev->data;
|
||||||
|
const struct pmw33xx_config *cfg = dev->config;
|
||||||
|
|
||||||
|
switch (chan) {
|
||||||
|
case SENSOR_CHAN_POS_DX:
|
||||||
|
val->val1 = data->dx;
|
||||||
|
data->dx = 0;
|
||||||
|
break;
|
||||||
|
case SENSOR_CHAN_POS_DY:
|
||||||
|
val->val1 = data->dy;
|
||||||
|
data->dy = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct sensor_driver_api pmw33xx_driver_api = {
|
||||||
|
#ifdef CONFIG_PMW33XX_TRIGGER
|
||||||
|
.trigger_set = pmw33xx_trigger_set,
|
||||||
|
#endif
|
||||||
|
// .attr_set = pmw33xx_attr_set,
|
||||||
|
.sample_fetch = pmw33xx_sample_fetch,
|
||||||
|
.channel_get = pmw33xx_channel_get,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pmw33xx_init_chip(const struct device *dev)
|
||||||
|
{
|
||||||
|
struct pmw33xx_data *data = dev->data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pmw33xx_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct pmw33xx_config *const config = dev->config;
|
||||||
|
struct pmw33xx_data *data = dev->data;
|
||||||
|
|
||||||
|
data->bus = device_get_binding(config->bus_name);
|
||||||
|
if (!data->bus) {
|
||||||
|
LOG_DBG("master not found: %s", log_strdup(config->bus_name));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
config->bus_init(dev);
|
||||||
|
|
||||||
|
if (pmw33xx_init_chip(dev) < 0) {
|
||||||
|
LOG_DBG("failed to initialize chip");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct pmw33xx_gpio_dt_spec *cs_gpio_cfg = &config->bus_cfg.spi_cfg->cs_spec;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PMW33XX_TRIGGER
|
||||||
|
if (pmw33xx_init_interrupt(dev) < 0) {
|
||||||
|
LOG_DBG("Failed to initialize interrupt!");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pmw33xx_cs_select(cs_gpio_cfg, 1);
|
||||||
|
k_sleep(K_MSEC(1));
|
||||||
|
|
||||||
|
int err = pmw33xx_write_reg(dev, PMW33XX_REG_PWR_UP_RST, PMW33XX_RESET_CMD);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("could not reset %d", err);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
uint8_t pid = 0x0;
|
||||||
|
err = pmw33xx_read_reg(dev, PMW33XX_REG_PID, &pid);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("could not reset %d", err);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
if (pid != PMW33XX_PID) {
|
||||||
|
LOG_ERR("pid does not match expected: got (%x), expected(%x)", pid, PMW33XX_PID);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
pmw33xx_write_reg(dev, PMW33XX_REG_CONFIG2, 0x00); // clear rest enable
|
||||||
|
|
||||||
|
err = pmw33xx_write_srom(dev);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("could not upload srom %d", err);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
uint8_t srom_run = 0x0;
|
||||||
|
err = pmw33xx_read_reg(dev, PMW33XX_REG_OBSERVATION, &srom_run);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("could not check srom status %d", err);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
if (!(srom_run & PMW33XX_SROM_RUN)) {
|
||||||
|
LOG_ERR("srom status invalid %d", srom_run);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t srom_id = 0x0;
|
||||||
|
err = pmw33xx_read_reg(dev, PMW33XX_REG_SROM_ID, &srom_id);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("could not check srom id %d", err);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
if (!srom_id) {
|
||||||
|
LOG_ERR("srom id invalid %d", srom_id);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmw33xx_write_reg(dev, PMW33XX_REG_CONFIG2, 0x00); // clear rest enable
|
||||||
|
pmw33xx_write_reg(dev, PMW33XX_REG_BURST, 0x01); // clear rest enable
|
||||||
|
struct pmw33xx_motion_burst val;
|
||||||
|
pmw33xx_read_motion_burst(dev, &val); // read and throwout initial motion data
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PMW33XX_DATA_SPI(n) \
|
||||||
|
{ \
|
||||||
|
.cs_ctrl = {}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PMW33XX_SPI_CFG(n) \
|
||||||
|
(&(struct pmw33xx_spi_cfg){ \
|
||||||
|
.spi_conf = \
|
||||||
|
{ \
|
||||||
|
.frequency = DT_INST_PROP(n, spi_max_frequency), \
|
||||||
|
.operation = \
|
||||||
|
(SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA), \
|
||||||
|
.slave = DT_INST_REG_ADDR(n), \
|
||||||
|
}, \
|
||||||
|
.cs_spec = PMW33XX_GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(n), cs_gpios, 0), \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define PMW33XX_GPIO_DT_SPEC_GET_BY_IDX(node_id, prop, idx) \
|
||||||
|
{ \
|
||||||
|
.port = DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(node_id, prop, idx)), \
|
||||||
|
.pin = DT_GPIO_PIN_BY_IDX(node_id, prop, idx), \
|
||||||
|
.dt_flags = DT_GPIO_FLAGS_BY_IDX(node_id, prop, idx), \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PMW33XX_CONFIG_SPI(n) \
|
||||||
|
{ \
|
||||||
|
.bus_name = DT_INST_BUS_LABEL(n), .bus_init = pmw33xx_spi_init, \
|
||||||
|
.bus_cfg = { .spi_cfg = PMW33XX_SPI_CFG(n) }, \
|
||||||
|
COND_CODE_1(CONFIG_MA730_TRIGGER, \
|
||||||
|
(, PMW33XX_GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(n), motswk_gpios, 0)), \
|
||||||
|
()) \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PMW33XX_INST(n) \
|
||||||
|
static struct pmw33xx_data pmw33xx_data_##n = PMW33XX_DATA_SPI(n); \
|
||||||
|
static const struct pmw33xx_config pmw33xx_cfg_##n = PMW33XX_CONFIG_SPI(n); \
|
||||||
|
DEVICE_DT_INST_DEFINE(n, pmw33xx_init, device_pm_control_nop, &pmw33xx_data_##n, \
|
||||||
|
&pmw33xx_cfg_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
|
||||||
|
&pmw33xx_driver_api);
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(PMW33XX_INST)
|
136
app/drivers/sensor/pmw33xx/pmw33xx.h
Normal file
136
app/drivers/sensor/pmw33xx/pmw33xx.h
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
#ifndef ZEPHYR_DRIVERS_SENSOR_PIXART_PMW33XX_H_
|
||||||
|
#define ZEPHYR_DRIVERS_SENSOR_PIXART_PMW33XX_H_
|
||||||
|
|
||||||
|
#include <drivers/sensor.h>
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
#include <drivers/gpio.h>
|
||||||
|
#include <sys/util.h>
|
||||||
|
#include <drivers/spi.h>
|
||||||
|
|
||||||
|
#define PMW33XX_WR_MASK 0x80
|
||||||
|
#define PMW33XX_RD_MASK 0x7F
|
||||||
|
|
||||||
|
#define PMW33XX_3389_PID 0x47
|
||||||
|
#define PMW33XX_3360_PID 0x45
|
||||||
|
#define PMW33XX_REV 0x01
|
||||||
|
|
||||||
|
/* General Registers */
|
||||||
|
#define PMW33XX_REG_PID 0x00
|
||||||
|
#define PMW33XX_REG_REV_ID 0x01
|
||||||
|
#define PMW33XX_REG_PWR_UP_RST 0x3A
|
||||||
|
|
||||||
|
/* Motion Registers */
|
||||||
|
#define PMW33XX_REG_MOTION 0x02
|
||||||
|
#define PMW33XX_REG_DX_L 0x03
|
||||||
|
#define PMW33XX_REG_DX_H 0x04
|
||||||
|
#define PMW33XX_REG_DY_L 0x05
|
||||||
|
#define PMW33XX_REG_DY_H 0x06
|
||||||
|
#define PMW33XX_REG_BURST 0x50
|
||||||
|
|
||||||
|
/* Motion bits */
|
||||||
|
#define PMW33XX_MOTION (1 << 8)
|
||||||
|
#define PMW33XX_OPMODE_RUN (0)
|
||||||
|
#define PMW33XX_OPMODE_REST1 (0b01 << 1)
|
||||||
|
#define PMW33XX_OPMODE_REST2 (0b10 << 1)
|
||||||
|
#define PMW33XX_OPMODE_REST3 (0b11 << 1)
|
||||||
|
|
||||||
|
/* SROM Registers */
|
||||||
|
#define PMW33XX_REG_SROM_EN 0x13
|
||||||
|
#define PMW33XX_REG_SROM_ID 0x2A
|
||||||
|
#define PMW33XX_REG_SROM_BURST 0x62
|
||||||
|
|
||||||
|
/* SROM CMDs */
|
||||||
|
#define PMW33XX_SROM_CRC_CMD 0x15
|
||||||
|
#define PMW33XX_SROM_DWNLD_CMD 0x1D
|
||||||
|
#define PMW33XX_SROM_DWNLD_START_CMD 0x18
|
||||||
|
|
||||||
|
/* CPI Registers */
|
||||||
|
#define PMW33XX_3360_REG_CPI 0x0F
|
||||||
|
#define PMW33XX_3389_REG_CPI_L 0x0E
|
||||||
|
#define PMW33XX_3389_REG_CPI_H 0x0F
|
||||||
|
|
||||||
|
/* Config Registers */
|
||||||
|
#define PMW33XX_REG_CONFIG2 0x10
|
||||||
|
#define PMW33XX_REG_OBSERVATION 0x24
|
||||||
|
#define PMW33XX_REG_DOUT_L 0x25
|
||||||
|
#define PMW33XX_REG_DOUT_H 0x26
|
||||||
|
|
||||||
|
/* Config2 Bits */
|
||||||
|
#define PMW33XX_RESTEN 0x20
|
||||||
|
#define PMW33XX_RPT_MOD 0x04
|
||||||
|
|
||||||
|
/* Observation Bits */
|
||||||
|
#define PMW33XX_SROM_RUN 0x40
|
||||||
|
|
||||||
|
/* power up reset cmd */
|
||||||
|
#define PMW33XX_RESET_CMD 0x5A
|
||||||
|
|
||||||
|
struct pmw33xx_gpio_dt_spec {
|
||||||
|
const struct device *port;
|
||||||
|
gpio_pin_t pin;
|
||||||
|
gpio_dt_flags_t dt_flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pmw33xx_spi_cfg {
|
||||||
|
struct spi_config spi_conf;
|
||||||
|
struct pmw33xx_gpio_dt_spec cs_spec;
|
||||||
|
};
|
||||||
|
|
||||||
|
union pmw33xx_bus_cfg {
|
||||||
|
struct pmw33xx_spi_cfg *spi_cfg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pmw33xx_config {
|
||||||
|
char *bus_name;
|
||||||
|
int (*bus_init)(const struct device *dev);
|
||||||
|
const union pmw33xx_bus_cfg bus_cfg;
|
||||||
|
int resolution;
|
||||||
|
#if CONFIG_PMW33XX_TRIGGER
|
||||||
|
struct pmw33xx_gpio_dt_spec motswk_spec;
|
||||||
|
#endif // CONFIG_PMW33XX_TRIGGER
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pmw33xx_data;
|
||||||
|
|
||||||
|
struct pmw33xx_transfer_function {
|
||||||
|
int (*read_data)(const struct device *dev, uint16_t *value);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pmw33xx_data {
|
||||||
|
const struct device *bus;
|
||||||
|
struct spi_cs_control cs_ctrl;
|
||||||
|
|
||||||
|
int16_t dx;
|
||||||
|
int16_t dy;
|
||||||
|
|
||||||
|
const struct pmw33xx_transfer_function *hw_tf;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PMW33XX_TRIGGER
|
||||||
|
|
||||||
|
struct gpio_callback motswk_gpio_cb;
|
||||||
|
const struct device *dev;
|
||||||
|
|
||||||
|
sensor_trigger_handler_t handler;
|
||||||
|
const struct sensor_trigger *trigger;
|
||||||
|
|
||||||
|
#if defined(CONFIG_PMW33XX_TRIGGER_OWN_THREAD)
|
||||||
|
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_PMW33XX_THREAD_STACK_SIZE);
|
||||||
|
struct k_sem gpio_sem;
|
||||||
|
struct k_thread thread;
|
||||||
|
#elif defined(CONFIG_PMW33XX_TRIGGER_GLOBAL_THREAD)
|
||||||
|
struct k_work work;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONFIG_PMW33XX_TRIGGER */
|
||||||
|
};
|
||||||
|
|
||||||
|
int pmw33xx_spi_init(const struct device *dev);
|
||||||
|
#ifdef CONFIG_PMW33XX_TRIGGER
|
||||||
|
|
||||||
|
int pmw33xx_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
|
||||||
|
sensor_trigger_handler_t handler);
|
||||||
|
|
||||||
|
int pmw33xx_init_interrupt(const struct device *dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_DRIVERS_SENSOR_PIXART_PMW33XX_H_ */
|
130
app/drivers/sensor/pmw33xx/pmw33xx_trigger.c
Normal file
130
app/drivers/sensor/pmw33xx/pmw33xx_trigger.c
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT pixart_pmw3389
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <drivers/gpio.h>
|
||||||
|
#include <sys/util.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <drivers/sensor.h>
|
||||||
|
|
||||||
|
#include "pmw3389.h"
|
||||||
|
|
||||||
|
// extern struct pmw3389_data pmw3389_driver;
|
||||||
|
|
||||||
|
#include <logging/log.h>
|
||||||
|
LOG_MODULE_DECLARE(PMW3389, CONFIG_SENSOR_LOG_LEVEL);
|
||||||
|
|
||||||
|
static inline void setup_int(const struct device *dev, bool enable)
|
||||||
|
{
|
||||||
|
struct pmw3389_data *data = dev->data;
|
||||||
|
const struct pmw3389_config *cfg = dev->config;
|
||||||
|
|
||||||
|
if (gpio_pin_interrupt_configure(cfg->motswk_spec.port, cfg->motswk_spec.pin,
|
||||||
|
enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE)) {
|
||||||
|
LOG_WRN("Unable to set MOTSWK GPIO interrupt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pmw3389_motswk_gpio_callback(const struct device *dev, struct gpio_callback *cb,
|
||||||
|
uint32_t pins)
|
||||||
|
{
|
||||||
|
struct pmw3389_data *drv_data = CONTAINER_OF(cb, struct pmw3389_data, motswk_gpio_cb);
|
||||||
|
|
||||||
|
LOG_DBG("");
|
||||||
|
|
||||||
|
setup_int(drv_data->dev, false);
|
||||||
|
|
||||||
|
#if defined(CONFIG_PMW3389_TRIGGER_OWN_THREAD)
|
||||||
|
k_sem_give(&drv_data->gpio_sem);
|
||||||
|
#elif defined(CONFIG_PMW3389_TRIGGER_GLOBAL_THREAD)
|
||||||
|
k_work_submit(&drv_data->work);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pmw3389_thread_cb(const struct device *dev)
|
||||||
|
{
|
||||||
|
struct pmw3389_data *drv_data = dev->data;
|
||||||
|
|
||||||
|
LOG_DBG("%p", drv_data->handler);
|
||||||
|
drv_data->handler(dev, drv_data->trigger);
|
||||||
|
|
||||||
|
// Enable once the wall/spam of interrupts is solved
|
||||||
|
setup_int(dev, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PMW3389_TRIGGER_OWN_THREAD
|
||||||
|
static void pmw3389_thread(int dev_ptr, int unused)
|
||||||
|
{
|
||||||
|
const struct device *dev = INT_TO_POINTER(dev_ptr);
|
||||||
|
struct pmw3389_data *drv_data = dev->data;
|
||||||
|
|
||||||
|
ARG_UNUSED(unused);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
k_sem_take(&drv_data->gpio_sem, K_FOREVER);
|
||||||
|
pmw3389_thread_cb(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PMW3389_TRIGGER_GLOBAL_THREAD
|
||||||
|
static void pmw3389_work_cb(struct k_work *work)
|
||||||
|
{
|
||||||
|
struct pmw3389_data *drv_data = CONTAINER_OF(work, struct pmw3389_data, work);
|
||||||
|
|
||||||
|
LOG_DBG("");
|
||||||
|
|
||||||
|
pmw3389_thread_cb(drv_data->dev);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int pmw3389_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
|
||||||
|
sensor_trigger_handler_t handler)
|
||||||
|
{
|
||||||
|
struct pmw3389_data *drv_data = dev->data;
|
||||||
|
|
||||||
|
setup_int(dev, false);
|
||||||
|
|
||||||
|
k_msleep(5);
|
||||||
|
|
||||||
|
drv_data->trigger = trig;
|
||||||
|
drv_data->handler = handler;
|
||||||
|
|
||||||
|
setup_int(dev, true);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pmw3389_init_interrupt(const struct device *dev)
|
||||||
|
{
|
||||||
|
struct pmw3389_data *drv_data = dev->data;
|
||||||
|
const struct pmw3389_config *drv_cfg = dev->config;
|
||||||
|
|
||||||
|
drv_data->dev = dev;
|
||||||
|
/* setup gpio interrupt */
|
||||||
|
|
||||||
|
gpio_init_callback(&drv_data->motswk_gpio_cb, pmw3389_motswk_gpio_callback,
|
||||||
|
BIT(drv_cfg->motswk_spec.pin));
|
||||||
|
|
||||||
|
if (gpio_add_callback(drv_cfg->motswk_spec.port, &drv_data->motswk_gpio_cb) < 0) {
|
||||||
|
LOG_DBG("Failed to set MOTSWK callback!");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_PMW3389_TRIGGER_OWN_THREAD)
|
||||||
|
k_sem_init(&drv_data->gpio_sem, 0, UINT_MAX);
|
||||||
|
|
||||||
|
k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_PMW3389_THREAD_STACK_SIZE,
|
||||||
|
(k_thread_entry_t)pmw3389_thread, dev, 0, NULL,
|
||||||
|
K_PRIO_COOP(CONFIG_PMW3389_THREAD_PRIORITY), 0, K_NO_WAIT);
|
||||||
|
#elif defined(CONFIG_PMW3389_TRIGGER_GLOBAL_THREAD)
|
||||||
|
k_work_init(&drv_data->work, pmw3389_work_cb);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
description: |
|
description: |
|
||||||
Sensor driver for the pixart PMW3389 optical mouse sensor
|
Sensor driver for the pixart PMW33XX optical mouse sensor supports 3360 built in, and 3389 with external srom
|
||||||
compatible: "pixart,pmw3389"
|
compatible: "pixart,pmw33xx"
|
||||||
|
|
||||||
include: spi-device.yaml
|
include: spi-device.yaml
|
||||||
|
|
||||||
|
@ -8,15 +8,15 @@ properties:
|
||||||
label:
|
label:
|
||||||
type: string
|
type: string
|
||||||
required: true
|
required: true
|
||||||
|
cs-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: chip select pin for the sensor
|
||||||
motswk-gpios:
|
motswk-gpios:
|
||||||
type: phandle-array
|
type: phandle-array
|
||||||
required: false
|
required: false
|
||||||
description: interrupt pin for motion
|
description: interrupt pin for motion
|
||||||
reset-gpios:
|
cpi:
|
||||||
type: phandle-array
|
|
||||||
required: false
|
|
||||||
description: A pin for the encoder
|
|
||||||
resolution:
|
|
||||||
type: int
|
type: int
|
||||||
description: mouse resolution
|
description: mouse cpi
|
||||||
required: false
|
required: false
|
Loading…
Add table
Reference in a new issue