Initial commit

This commit is contained in:
ReFil 2021-01-08 19:04:51 +00:00
parent 167600f01d
commit f12244f4bf
5 changed files with 434 additions and 1 deletions

View file

@ -3,3 +3,4 @@
add_subdirectory_ifdef(CONFIG_ZMK_BATTERY_VOLTAGE_DIVIDER battery_voltage_divider)
add_subdirectory_ifdef(CONFIG_EC11 ec11)
add_subdirectory_ifdef(CONFIG_MA730 ma730)

View file

@ -0,0 +1,8 @@
# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
zephyr_include_directories(.)
zephyr_library()
zephyr_library_sources(ma730.c)

View file

@ -0,0 +1,7 @@
config MA730
bool "MA730 Angular position sensor"
depends on SPI
help
Enable angular encoder sensor
The MA730 is a 16-bit contactless magnetic encoder, communicating over spi

View file

@ -0,0 +1,310 @@
#define DT_DRV_COMPAT magalpha_ma730
#include <drivers/spi.h>
#include <device.h>
#include <drivers/gpio.h>
#include <sys/util.h>
#include <kernel.h>
#include <drivers/sensor.h>
#include <sys/__assert.h>
#include <logging/log.h>
LOG_MODULE_DECLARE(MA730, CONFIG_SENSOR_LOG_LEVEL);
static int ma730_raw_read(const struct device *dev,
uint16_t *value)
{
struct ma730_data *data = dev->data;
const struct ma730_config *cfg = dev->config;
const struct spi_config *spi_cfg = &cfg->bus_cfg.spi_cfg->spi_conf;
uint8_t buffer_tx[2] = {0, 0};
const struct spi_buf tx_buf = {
.buf = buffer_tx,
.len = 2,
};
const struct spi_buf_set tx = {
.buffers = &tx_buf,
.count = 1
};
const struct spi_buf rx_buf = {
{
.buf = value,
.len = 16,
}
};
const struct spi_buf_set rx = {
.buffers = rx_buf,
.count = 1
};
if (len > 64) {
return -EIO;
}
if (spi_transceive(data->bus, spi_cfg, &tx, &rx)) {
return -EIO;
}
return 0;
}
static int ma730_reg_read(const struct device *dev, uint8_t reg_addr,
uint8_t *value, uint8_t len)
{
struct ma730_data *data = dev->data;
const struct ma730_config *cfg = dev->config;
const struct spi_config *spi_cfg = &cfg->bus_cfg.spi_cfg->spi_conf;
uint8_t buffer_tx[2] = { reg_addr | 1 << 6 | , 0, 0, 0};
const struct spi_buf tx_buf = {
.buf = buffer_tx,
.len = 4,
};
const struct spi_buf_set tx = {
.buffers = &tx_buf,
.count = 1
};
const struct spi_buf rx_buf[2] = {
{
.buf = NULL,
.len = 2,
},
{
.buf = value,
.len = 1,
},
{
.buf = NULL,
.len = 1,
}
};
const struct spi_buf_set rx = {
.buffers = rx_buf,
.count = 3
};
if (len > 64) {
return -EIO;
}
if (spi_transceive(data->bus, spi_cfg, &tx, &rx)) {
return -EIO;
}
return 0;
}
static int ma730_raw_write(const struct device *dev, uint8_t reg_addr,
uint8_t *value, uint8_t len)
{
struct ma730_data *data = dev->data;
const struct ma730_config *cfg = dev->config;
const struct spi_config *spi_cfg = &cfg->bus_cfg.spi_cfg->spi_conf;
uint8_t buffer_tx[1] = { reg_addr | 1 << 7 };
const struct spi_buf tx_buf[2] = {
{
.buf = buffer_tx,
.len = 1,
},
{
.buf = value,
.len = len,
}
};
const struct spi_buf_set tx = {
.buffers = tx_buf,
.count = 2
};
if (len > 64) {
return -EIO;
}
if (spi_write(data->bus, spi_cfg, &tx)) {
return -EIO;
}
return 0;
}
static int ma730_spi_read_data(const struct device *dev,
uint8_t *value)
{
return ma730_raw_read(dev, value);
}
static int ma730_spi_write_data(const struct device *dev, uint8_t reg_addr,
uint8_t *value, uint8_t len)
{
return ma730_raw_write(dev, reg_addr, value, len);
}
static int ma730_spi_read_reg(const struct device *dev, uint8_t reg_addr,
uint8_t *value)
{
return ma730_reg_read(dev, reg_addr, value, 1);
}
static const struct ma730_transfer_function ma730_spi_transfer_fn = {
.read_data = ma730_spi_read_data,
.read_reg = ma730_spi_read_reg,
.update_reg = ma730_spi_update_reg,
};
int ma730_spi_init(const struct device *dev)
{
struct ma730_data *data = dev->data;
const struct ma730_config *cfg = dev->config;
const struct ma730_spi_cfg *spi_cfg = cfg->bus_cfg.spi_cfg;
data->hw_tf = &ma730_spi_transfer_fn;
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;
}
LOG_DBG("SPI GPIO CS configured on %s:%u",
spi_cfg->cs_gpios_label, data->cs_ctrl.gpio_pin);
}
return 0;
}
static int ma730_sample_fetch(const struct device *dev, enum sensor_channel chan) {
struct ma730_data *drv_data = dev->data;
const struct ma730_config *drv_cfg = dev->config;
uint16_t val;
int8_t delta;
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_ROTATION);
if (ma730_spi_read_data(dev, &value)) {
return -EIO
}
}
static int ma730_channel_get(const struct device *dev, enum sensor_channel chan,
struct sensor_value *val) {
struct ma730_data *drv_data = dev->data;
if (chan != SENSOR_CHAN_ROTATION) {
return -ENOTSUP;
}
val->val1 = drv_data->ticks;
val->val2 = drv_data->delta;
return 0;
}
static const struct sensor_driver_api ma730_driver_api = {
.attr_set = ma730_attr_set,
.sample_fetch = ma730_sample_fetch,
.channel_get = ma730_channel_get,
};
static int ma730_init_chip(const struct device *dev)
{
struct ma730_data *data = dev->data;
return 0;
}
static int ma730_init(const struct device *dev)
{
const struct ma730_config * const config = dev->config;
struct ma730_data *data = dev->data;
data->bus = device_get_binding(config->bus_name);
if (!data->bus) {
LOG_DBG("master not found: %s", config->bus_name);
return -EINVAL;
}
config->bus_init(dev);
if (ma730_init_chip(dev) < 0) {
LOG_DBG("failed to initialize chip");
return -EIO;
}
return 0;
}
#define MA730_HAS_CS(n) DT_INST_SPI_DEV_HAS_CS_GPIOS(n)
#define MA730_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 MA730_DATA_SPI(n) \
COND_CODE_1(MA730_HAS_CS(n), \
(MA730_DATA_SPI_CS(n)), \
({}))
#define MA730_SPI_CS_PTR(n) \
COND_CODE_1(MA730_HAS_CS(n), \
(&(ma730_data_##n.cs_ctrl)), \
(NULL))
#define MA730_SPI_CS_LABEL(n) \
COND_CODE_1(MA730_HAS_CS(n), \
(DT_INST_SPI_DEV_CS_GPIOS_LABEL(n)), (NULL))
#define MA730_SPI_CFG(n) \
(&(struct ma730_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 = MA730_SPI_CS_PTR(n), \
}, \
.cs_gpios_label = MA730_SPI_CS_LABEL(n), \
})
#define MA730_CONFIG_SPI(n) \
{ \
.bus_name = DT_INST_BUS_LABEL(n), \
.bus_init = ma730_spi_init, \
.bus_cfg = { .spi_cfg = MA730_SPI_CFG(n) }, \
COND_CODE_0(DT_INST_NODE_HAS_PROP(n, resolution), (1), (DT_INST_PROP(n, resolution))) \
}
#define MA730_DEFINE_SPI(n) \
static struct ma730_data ma730_data_##n = \
MA730_DATA_SPI(n); \
static const struct ma730_config ma730_config_##n = \
MA730_CONFIG_SPI(n); \
MA730_DEVICE_INIT(n)
#define MA730_INST(n) \
DEVICE_AND_API_INIT(ma730_##n, DT_INST_LABEL(n), ma730_init, &ma730_data_##n, &ma730_cfg_##n, \
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &ma730_driver_api);
DT_INST_FOREACH_STATUS_OKAY(MA730_INST)

View file

@ -0,0 +1,107 @@
#ifndef ZEPHYR_DRIVERS_SENSOR_MA730_MA730_H_
#define ZEPHYR_DRIVERS_SENSOR_MA730_MA730_H_
#include <drivers/sensor.h>
#include <zephyr/types.h>
#include <drivers/gpio.h>
#include <sys/util.h>
#include <drivers/spi.h>
#define MA730_REG_ZERO_OFF_1 0x0
#define MA730_REG_ZERO_OFF_2 0x1
#define MA730_REG_BCT 0x2
#define MA730_REG_ETX_ETY 0x3
#define MA730_REG_PPT_ILIP 0x4
#define MA730_MASK_PPT_ILIP_PPT1 BIT(7)
#define MA730_SHIFT_PPT_ILIP_PPT1 7
#define MA730_MASK_PPT_ILIP_PPT0 BIT(7)
#define MA730_SHIFT_PPT_ILIP_PPT0 6
#define MA730_REG_PPT 0x5
#define MA730_MASK_PPT_PPT9 BIT(7)
#define MA730_SHIFT_PPT_PPT9 7
#define MA730_MASK_PPT_PPT8 BIT(6)
#define MA730_SHIFT_PPT_PPT8 6
#define MA730_MASK_PPT_PPT7 BIT(5)
#define MA730_SHIFT_PPT_PPT7 5
#define MA730_MASK_PPT_PPT6 BIT(4)
#define MA730_SHIFT_PPT_PPT6 4
#define MA730_MASK_PPT_PPT5 BIT(3)
#define MA730_SHIFT_PPT_PPT5 3
#define MA730_MASK_PPT_PPT4 BIT(2)
#define MA730_SHIFT_PPT_PPT4 2
#define MA730_MASK_PPT_PPT3 BIT(1)
#define MA730_SHIFT_PPT_PPT3 1
#define MA730_MASK_PPT_PPT2 BIT(0)
#define MA730_SHIFT_PPT_PPT2 0
#define MA730_REG_MGT 0x6
#define MA730_MASK_MGT_MGLT2 BIT(7)
#define MA730_SHIFT_MGT_MGLT2 7
#define MA730_MASK_MGT_MGLT1 BIT(6)
#define MA730_SHIFT_MGT_MGLT1 6
#define MA730_MASK_MGT_MGLT0 BIT(5)
#define MA730_SHIFT_MGT_MGLT0 5
#define MA730_MASK_MGT_MGHT2 BIT(4)
#define MA730_SHIFT_MGT_MGHT2 4
#define MA730_MASK_MGT_MGHT1 BIT(3)
#define MA730_SHIFT_MGT_MGHT1 3
#define MA730_MASK_MGT_MGHT0 BIT(2)
#define MA730_SHIFT_MGT_MGHT0 2
#define MA730_REG_RD 0x9
#define MA730_MASK_RD_RD BIT(7)
#define MA730_SHIFT_RD_RD 7
#define MA730_REG_MG 0x1B
struct ma730_spi_cfg {
struct spi_config spi_conf;
const char *cs_gpios_label;
};
struct ma730_config {
char *bus_name;
int (*bus_init)(const struct device *dev);
const union ma730_spi_cfg spi_cfg;
int resolution;
};
struct ma730_data;
struct ma730_transfer_function {
int (*read_data)(const struct device *dev,
uint16_t *value);
int (*read_reg)(const struct device *dev, uint8_t reg_addr,
uint8_t *value);
int (*update_reg)(const struct device *dev, uint8_t reg_addr,
uint8_t mask, uint8_t value);
};
struct ma730_data {
const struct device *bus;
struct spi_cs_control cs_ctrl;
float angle;
float velocity;
const struct ma730_transfer_function *hw_tf;
};
int ma730_spi_init(const struct device *dev);
#endif /* ZEPHYR_DRIVERS_SENSOR_MA730_MA730_H_ */