From f12244f4bfedd2673765178ff3dc60027777f8b4 Mon Sep 17 00:00:00 2001 From: ReFil <31960031+ReFil@users.noreply.github.com> Date: Fri, 8 Jan 2021 19:04:51 +0000 Subject: [PATCH] Initial commit --- app/drivers/sensor/CMakeLists.txt | 3 +- app/drivers/sensor/ma730/CMakeLists.txt | 8 + app/drivers/sensor/ma730/Kconfig | 7 + app/drivers/sensor/ma730/ma730.c | 310 ++++++++++++++++++++++++ app/drivers/sensor/ma730/ma730.h | 107 ++++++++ 5 files changed, 434 insertions(+), 1 deletion(-) create mode 100644 app/drivers/sensor/ma730/CMakeLists.txt create mode 100644 app/drivers/sensor/ma730/Kconfig create mode 100644 app/drivers/sensor/ma730/ma730.c create mode 100644 app/drivers/sensor/ma730/ma730.h diff --git a/app/drivers/sensor/CMakeLists.txt b/app/drivers/sensor/CMakeLists.txt index a4c2ba89..b2e1368d 100644 --- a/app/drivers/sensor/CMakeLists.txt +++ b/app/drivers/sensor/CMakeLists.txt @@ -2,4 +2,5 @@ # SPDX-License-Identifier: MIT add_subdirectory_ifdef(CONFIG_ZMK_BATTERY_VOLTAGE_DIVIDER battery_voltage_divider) -add_subdirectory_ifdef(CONFIG_EC11 ec11) \ No newline at end of file +add_subdirectory_ifdef(CONFIG_EC11 ec11) +add_subdirectory_ifdef(CONFIG_MA730 ma730) diff --git a/app/drivers/sensor/ma730/CMakeLists.txt b/app/drivers/sensor/ma730/CMakeLists.txt new file mode 100644 index 00000000..e72243f1 --- /dev/null +++ b/app/drivers/sensor/ma730/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +zephyr_include_directories(.) + +zephyr_library() + +zephyr_library_sources(ma730.c) diff --git a/app/drivers/sensor/ma730/Kconfig b/app/drivers/sensor/ma730/Kconfig new file mode 100644 index 00000000..e7bfe3ee --- /dev/null +++ b/app/drivers/sensor/ma730/Kconfig @@ -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 diff --git a/app/drivers/sensor/ma730/ma730.c b/app/drivers/sensor/ma730/ma730.c new file mode 100644 index 00000000..fae00848 --- /dev/null +++ b/app/drivers/sensor/ma730/ma730.c @@ -0,0 +1,310 @@ + + +#define DT_DRV_COMPAT magalpha_ma730 + +#include +#include +#include +#include +#include +#include +#include +#include + + + + +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) diff --git a/app/drivers/sensor/ma730/ma730.h b/app/drivers/sensor/ma730/ma730.h new file mode 100644 index 00000000..b86cf558 --- /dev/null +++ b/app/drivers/sensor/ma730/ma730.h @@ -0,0 +1,107 @@ +#ifndef ZEPHYR_DRIVERS_SENSOR_MA730_MA730_H_ +#define ZEPHYR_DRIVERS_SENSOR_MA730_MA730_H_ + +#include +#include +#include +#include +#include + + + + +#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_ */