feat(sensor): Add Pimoroni PIM447 trackball driver.
This commit is contained in:
parent
621ecc5450
commit
b9f900faa7
5 changed files with 183 additions and 2 deletions
|
@ -2,4 +2,5 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
|
||||
add_subdirectory_ifdef(CONFIG_ZMK_BATTERY battery)
|
||||
add_subdirectory_ifdef(CONFIG_EC11 ec11)
|
||||
add_subdirectory_ifdef(CONFIG_EC11 ec11)
|
||||
add_subdirectory_ifdef(CONFIG_ZMK_TRACKBALL_PIM447 trackball_pim447)
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
|
||||
rsource "battery/Kconfig"
|
||||
rsource "ec11/Kconfig"
|
||||
rsource "ec11/Kconfig"
|
||||
rsource "trackball_pim447/Kconfig"
|
||||
|
|
4
app/drivers/sensor/trackball_pim447/CMakeLists.txt
Normal file
4
app/drivers/sensor/trackball_pim447/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
zephyr_library_sources(trackball_pim447.c)
|
8
app/drivers/sensor/trackball_pim447/Kconfig
Normal file
8
app/drivers/sensor/trackball_pim447/Kconfig
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2021 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config ZMK_TRACKBALL_PIM447
|
||||
bool "ZMK PIM447 trackball"
|
||||
depends on I2C
|
||||
help
|
||||
Enable I2C-based driver for Pimoroni PIM447 trackball.
|
167
app/drivers/sensor/trackball_pim447/trackball_pim447.c
Normal file
167
app/drivers/sensor/trackball_pim447/trackball_pim447.c
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT pimoroni_trackball_pim447
|
||||
|
||||
#include <drivers/i2c.h>
|
||||
#include <drivers/sensor.h>
|
||||
|
||||
#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(trackball_pim447);
|
||||
|
||||
#define TRACKBALL_PIM447_REG_LEFT 0x04
|
||||
#define TRACKBALL_PIM447_REG_RIGHT 0x05
|
||||
#define TRACKBALL_PIM447_REG_UP 0x06
|
||||
#define TRACKBALL_PIM447_REG_DOWN 0x07
|
||||
#define TRACKBALL_PIM447_REG_SWITCH 0x08
|
||||
|
||||
#define TRACKBALL_PIM447_REG_MIN TRACKBALL_PIM447_REG_LEFT
|
||||
#define TRACKBALL_PIM447_REG_MAX TRACKBALL_PIM447_REG_SWITCH
|
||||
|
||||
struct trackball_pim447_data {
|
||||
const struct device *i2c_dev;
|
||||
int32_t dx;
|
||||
int32_t dy;
|
||||
int32_t dz;
|
||||
};
|
||||
|
||||
static int trackball_pim447_read_reg(const struct device *dev,
|
||||
uint8_t reg, uint8_t *value)
|
||||
{
|
||||
struct trackball_pim447_data *data = dev->data;
|
||||
|
||||
if (reg < TRACKBALL_PIM447_REG_MIN || reg > TRACKBALL_PIM447_REG_MAX) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int status = i2c_reg_read_byte(data->i2c_dev, DT_INST_REG_ADDR(0),
|
||||
reg, value);
|
||||
if (status < 0) {
|
||||
LOG_ERR("Sensor reg read byte failed");
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trackball_pim447_read_axis(const struct device *dev,
|
||||
uint8_t reg_negative,
|
||||
uint8_t reg_positive,
|
||||
int32_t *value)
|
||||
{
|
||||
uint8_t value_negative;
|
||||
uint8_t value_positive;
|
||||
int status;
|
||||
|
||||
status = trackball_pim447_read_reg(dev, reg_negative, &value_negative);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = trackball_pim447_read_reg(dev, reg_positive, &value_positive);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
*value = value_positive - value_negative;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trackball_pim447_sample_fetch(const struct device *dev,
|
||||
enum sensor_channel chan)
|
||||
{
|
||||
struct trackball_pim447_data *data = dev->data;
|
||||
int status;
|
||||
|
||||
if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_POS_DX) {
|
||||
status = trackball_pim447_read_axis(dev,
|
||||
TRACKBALL_PIM447_REG_LEFT,
|
||||
TRACKBALL_PIM447_REG_RIGHT,
|
||||
&data->dx);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_POS_DY) {
|
||||
status = trackball_pim447_read_axis(dev,
|
||||
TRACKBALL_PIM447_REG_UP,
|
||||
TRACKBALL_PIM447_REG_DOWN,
|
||||
&data->dy);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_POS_DZ) {
|
||||
uint8_t value;
|
||||
status = trackball_pim447_read_reg(dev,
|
||||
TRACKBALL_PIM447_REG_SWITCH,
|
||||
&value);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
data->dz = value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trackball_pim447_channel_get(const struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
struct trackball_pim447_data *data = dev->data;
|
||||
|
||||
/* Not used. */
|
||||
val->val2 = 0;
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_POS_DX:
|
||||
val->val1 = data->dx;
|
||||
break;
|
||||
|
||||
case SENSOR_CHAN_POS_DY:
|
||||
val->val1 = data->dy;
|
||||
break;
|
||||
|
||||
case SENSOR_CHAN_POS_DZ:
|
||||
val->val1 = data->dz;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trackball_pim447_init(const struct device *dev)
|
||||
{
|
||||
struct trackball_pim447_data *data = dev->data;
|
||||
|
||||
data->i2c_dev = device_get_binding(DT_INST_BUS_LABEL(0));
|
||||
if (data->i2c_dev == NULL) {
|
||||
LOG_ERR("Failed to get I2C device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct trackball_pim447_data trackball_pim447_data;
|
||||
|
||||
static const struct sensor_driver_api trackball_pim447_api = {
|
||||
.sample_fetch = trackball_pim447_sample_fetch,
|
||||
.channel_get = trackball_pim447_channel_get,
|
||||
};
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, &trackball_pim447_init, device_pm_control_nop,
|
||||
&trackball_pim447_data, NULL, POST_KERNEL,
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &trackball_pim447_api);
|
Loading…
Add table
Reference in a new issue