This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit a1d60169620337ba10a848df0217facedf258022 Author: Alan Carvalho de Assis <[email protected]> AuthorDate: Sat Apr 25 16:54:09 2026 -0300 drivers/sensors: Add support to MT6816 This commit adds support to MagTek MT6816 sensor Signed-off-by: Alan C. Assis <[email protected]> --- drivers/sensors/CMakeLists.txt | 4 + drivers/sensors/Kconfig | 9 + drivers/sensors/Make.defs | 4 + drivers/sensors/mt6816.c | 396 +++++++++++++++++++++++++++++++++++++++++ include/nuttx/sensors/mt6816.h | 102 +++++++++++ 5 files changed, 515 insertions(+) diff --git a/drivers/sensors/CMakeLists.txt b/drivers/sensors/CMakeLists.txt index 7e9d91209e6..00b6a1df2ab 100644 --- a/drivers/sensors/CMakeLists.txt +++ b/drivers/sensors/CMakeLists.txt @@ -107,6 +107,10 @@ if(CONFIG_SENSORS) list(APPEND SRCS ak09912.c) endif() + if(CONFIG_SENSORS_MT6816) + list(APPEND SRCS mt6816.c) + endif() + if(CONFIG_SENSORS_AS5048B) list(APPEND SRCS as5048b.c) endif() diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index c8e13eb0075..4f6a42714d7 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -161,6 +161,15 @@ config SENSORS_AK09912 ---help--- Enable driver for AK09911/AK09912 Compass sensor. +config SENSORS_MT6816 + bool "MagTek MT6816 Magnetic Angle Position support" + default n + select SPI + select SENSORS_QENCODER + ---help--- + Enable driver support for the MagTek MT6816 magnetic angle + position (magnetic rotary encoder). + config SENSORS_AS5048B bool "AMS AS5048B Magnetic Rotary Encoder support" default n diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs index cc8cf426056..fa0d02b69c0 100644 --- a/drivers/sensors/Make.defs +++ b/drivers/sensors/Make.defs @@ -388,6 +388,10 @@ ifeq ($(CONFIG_SENSORS_MPL115A),y) CSRCS += mpl115a.c endif +ifeq ($(CONFIG_SENSORS_MT6816),y) + CSRCS += mt6816.c +endif + ifeq ($(CONFIG_SENSORS_LIS3MDL),y) CSRCS += lis3mdl.c endif diff --git a/drivers/sensors/mt6816.c b/drivers/sensors/mt6816.c new file mode 100644 index 00000000000..a69432ef28e --- /dev/null +++ b/drivers/sensors/mt6816.c @@ -0,0 +1,396 @@ +/**************************************************************************** + * drivers/sensors/mt6816.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <assert.h> +#include <errno.h> +#include <nuttx/debug.h> +#include <stdlib.h> + +#include <nuttx/kmalloc.h> +#include <nuttx/fs/fs.h> +#include <nuttx/spi/spi.h> +#include <nuttx/sensors/mt6816.h> + +#if defined(CONFIG_SENSORS_MT6816) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MT6816_REG_ANGLE_LSB 0x03 +#define MT6816_REG_ANGLE_MSB 0x04 +#define MT6816_CMD_READ 0x80 +#define MT6816_NO_MAG_WARN 0x02 +#define MT6816_PARITY_CHECK 0x01 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct mt6816_dev_s +{ + struct qe_lowerhalf_s lower; /* MT6816 quadrature encoder lower half */ + FAR struct spi_dev_s *spi; /* SPI interface */ + + /* Since multiple MT6816 can be connected to the same SPI bus we need + * to use multiple spi device ids which are employed by NuttX to select/ + * deselect the desired MT6816 chip via their chip select inputs. + */ + + int devid; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int mt6816_exchange(FAR struct mt6816_dev_s *priv, + uint8_t regaddr, FAR uint8_t *regval); +static uint16_t calc_even_parity(uint16_t value); +static int mt6816_readang(FAR struct mt6816_dev_s *priv, + FAR uint16_t *ang); + +/* Character Driver Methods */ + +static int mt6816_setup(FAR struct qe_lowerhalf_s *lower); +static int mt6816_shutdown(FAR struct qe_lowerhalf_s *lower); +static int mt6816_position(FAR struct qe_lowerhalf_s *lower, + FAR int32_t *pos); +static int mt6816_reset(FAR struct qe_lowerhalf_s *lower); +static int mt6816_ioctl(FAR struct qe_lowerhalf_s *lower, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct qe_ops_s g_qeops = +{ + mt6816_setup, /* setup */ + mt6816_shutdown, /* shutdown */ + mt6816_position, /* position */ + NULL, /* setposmax */ + mt6816_reset, /* reset */ + NULL, /* setindex */ + mt6816_ioctl /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mt6816_configspi + * + * Description: + * + ****************************************************************************/ + +static inline void mt6816_configspi(FAR struct spi_dev_s *spi) +{ + /* Configure SPI for the MT6816 */ + + SPI_SETMODE(spi, MT6816_SPI_MODE); + SPI_SETBITS(spi, 8); + SPI_HWFEATURES(spi, 0); + SPI_SETFREQUENCY(spi, MT6816_SPI_MAXFREQUENCY); +} + +/**************************************************************************** + * Name: mt6816_exchange + * + * Description: + * Read from 8-bit registers + * + ****************************************************************************/ + +static int mt6816_exchange(FAR struct mt6816_dev_s *priv, + uint8_t regaddr, FAR uint8_t *regval) +{ + uint8_t dat; + + /* If SPI bus is shared then lock and configure it */ + + SPI_LOCK(priv->spi, true); + mt6816_configspi(priv->spi); + + /* Select the MT6816 */ + + SPI_SELECT(priv->spi, SPIDEV_MAG_ENCODER(priv->devid), true); + + /* Send READ command. Received data is thrown away + * this data comes from the previous command (unknown) + */ + + dat = MT6816_CMD_READ | regaddr; + + /* Send register to read and get the next byte */ + + SPI_SEND(priv->spi, dat); + + /* Send NOP command. Received data is the value of regaddr + * from the previous command + */ + + dat = 0x00; /* NOP command */ + *regval = SPI_SEND(priv->spi, dat); + + /* Deselect the MT6816 */ + + SPI_SELECT(priv->spi, SPIDEV_MAG_ENCODER(priv->devid), false); + + /* Unlock bus */ + + SPI_LOCK(priv->spi, false); + + sninfo("addr: %02x value: %02x\n", regaddr, *regval); + return OK; +} + +/**************************************************************************** + * Name: calc_even_parity + * + * Description: + * get the even parity of input value + * + ****************************************************************************/ + +static uint16_t calc_even_parity(uint16_t value) +{ + uint16_t cnt = 0; + uint8_t i; + + for (i = 0; i < 16; i++) + { + if (value & 0x1) + { + cnt++; + } + + value >>= 1; + } + + return cnt & 0x1; +} + +/**************************************************************************** + * Name: mt6816_readang + * + * Description: + * Read from the angle position registers + * + ****************************************************************************/ + +static int mt6816_readang(FAR struct mt6816_dev_s *priv, + FAR uint16_t *ang) +{ + uint8_t hi; + uint8_t lo; + uint16_t value; + bool no_mag; + bool parity; + int ret; + + /* Read the high 8 bits of the 14-bit value */ + + ret = mt6816_exchange(priv, MT6816_REG_ANGLE_LSB, &hi); + if (ret < 0) + { + snerr("ERROR: mt6816_exchange failed: %d\n", ret); + return ret; + } + + /* Read the low 6 bits of the 14-bit value */ + + ret = mt6816_exchange(priv, MT6816_REG_ANGLE_MSB, &lo); + if (ret < 0) + { + snerr("ERROR: mt6816_exchange failed: %d\n", ret); + return ret; + } + + /* Read No Magnetic Error and Parity Check bits first */ + + no_mag = (lo & MT6816_NO_MAG_WARN) >> 1; + parity = (lo & MT6816_PARITY_CHECK); + + value = ((uint16_t)hi << 8 | (uint16_t)lo); + + /* Check if parity is right: + * - Clear the parity bit + * - Check if the calculated parity match with internal parity + */ + + value &= ~MT6816_PARITY_CHECK; + + if (calc_even_parity(value) == parity) + { + sninfo("Parity is correct!\n"); + } + else + { + snerr("Parity error: expected %d got %d", !parity, parity); + } + + /* Save only the angle value */ + + *ang = value >> 2; + + sninfo("angle: %04d, NO_MAG=%d, PC=%d ret: %d\n", + *ang, no_mag, parity, ret); + + return ret; +} + +/**************************************************************************** + * Name: mt6816_setup + * + * Description: + * This method is called when the driver is opened + * + ****************************************************************************/ + +static int mt6816_setup(FAR struct qe_lowerhalf_s *lower) +{ + return OK; +} + +/**************************************************************************** + * Name: mt6816_shutdown + * + * Description: + * This method is called when the driver is closed + * + ****************************************************************************/ + +static int mt6816_shutdown(FAR struct qe_lowerhalf_s *lower) +{ + return OK; +} + +/**************************************************************************** + * Name: mt6816_position + * + * Description: + * Return the current position measurement + * + ****************************************************************************/ + +static int mt6816_position(FAR struct qe_lowerhalf_s *lower, + FAR int32_t *pos) +{ + FAR struct mt6816_dev_s *priv = (FAR struct mt6816_dev_s *)lower; + uint16_t ang; + int ret; + + ret = mt6816_readang(priv, &ang); + if (ret < 0) + { + snerr("ERROR: mt6816_readang failed: %d\n", ret); + return ret; + } + + *pos = (int32_t)ang; + + return ret; +} + +/**************************************************************************** + * Name: mt6816_reset + * + * Description: + * Reset the position measurement to zero + * + ****************************************************************************/ + +static int mt6816_reset(FAR struct qe_lowerhalf_s *lower) +{ + /* Seems like the MT6816 doesn't have a SPI writable register + * to define the zero position. However it has a register to + * flash the zero position using its memory programming (MTP) + * but it requires supply high voltage (7V) to HVPP pin. + */ + + return OK; +} + +/**************************************************************************** + * Name: mt6816_ioctl + ****************************************************************************/ + +static int mt6816_ioctl(FAR struct qe_lowerhalf_s *lower, int cmd, + unsigned long arg) +{ + /* There is nothing we can('t) do! */ + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mt6816_initialize + * + * Description: + * Initialize the MT6816 device. + * + * Input Parameters: + * spi - An SPI driver instance. + * + * Returned Value: + * A new lower half encoder interface for the MT6816 on success; + * NULL on failure. + * + ****************************************************************************/ + +FAR struct qe_lowerhalf_s *mt6816_initialize(FAR struct spi_dev_s *spi, + uint16_t devid) +{ + FAR struct mt6816_dev_s *priv; + + DEBUGASSERT(spi != NULL); + + /* Initialize the device's structure */ + + priv = kmm_malloc(sizeof(*priv)); + if (priv == NULL) + { + snerr("ERROR: Failed to allocate instance\n"); + return NULL; + } + + priv->lower.ops = &g_qeops; + priv->spi = spi; + priv->devid = devid; + + return &priv->lower; +} + +#endif /* CONFIG_SENSORS_MT6816 */ diff --git a/include/nuttx/sensors/mt6816.h b/include/nuttx/sensors/mt6816.h new file mode 100644 index 00000000000..d75c63ed5e6 --- /dev/null +++ b/include/nuttx/sensors/mt6816.h @@ -0,0 +1,102 @@ +/**************************************************************************** + * include/nuttx/sensors/mt6816.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SENSORS_MT6816_H +#define __INCLUDE_NUTTX_SENSORS_MT6816_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/fs/ioctl.h> +#include <nuttx/spi/spi.h> +#include <nuttx/sensors/qencoder.h> + +#if defined(CONFIG_SENSORS_MT6816) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************ + * Prerequisites: + * + * CONFIG_SPI + * Enables support for SPI drivers + * CONFIG_SENSORS_MT6816 + * Enables support for the MT6816 driver + */ + +/* The device always operates in mode 3 */ + +#define MT6816_SPI_MODE SPIDEV_MODE3 /* Mode 3 */ + +/* SPI frequency */ + +#define MT6816_SPI_MAXFREQUENCY 1000000 /* 1MHz */ + +/* Resolution ***************************************************************/ + +#define MT6816_MAX 0x3fff /* Maximum value (14 bits) */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: mt6816_initialize + * + * Description: + * Initialize the MT6816 device. + * + * Input Parameters: + * spi - An SPI driver instance. + * + * Returned Value: + * A new lower half encoder interface for the MT6816 on success; + * NULL on failure. + * + ****************************************************************************/ + +FAR struct qe_lowerhalf_s *mt6816_initialize(FAR struct spi_dev_s *spi, + uint16_t devid); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_SENSORS_MT6816 */ +#endif /* __INCLUDE_NUTTX_SENSORS_MT6816_H */
