diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index 95e4a9c385..3b852a1cd4 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -234,6 +234,13 @@ config QENCODER bool "Qencoder" default n +config XEN1210 + bool "Sensixs XEN1210 Magnetometer" + default n + select SPI + ---help--- + Enable driver support for the Sensixs XEN1210 Magnetometer. + config ZEROCROSS bool "Zero Cross Sensor" default n diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs index 5527e98e4f..9c2bce29e8 100644 --- a/drivers/sensors/Make.defs +++ b/drivers/sensors/Make.defs @@ -138,6 +138,12 @@ ifeq ($(CONFIG_QENCODER),y) CSRCS += qencoder.c endif +# Sensixs XEN1210 + +ifeq ($(CONFIG_XEN1210),y) + CSRCS += xen1210.c +endif + # Zero Cross upper half ifeq ($(CONFIG_ZEROCROSS),y) diff --git a/drivers/sensors/xen1210.c b/drivers/sensors/xen1210.c new file mode 100644 index 0000000000..ea4de97fff --- /dev/null +++ b/drivers/sensors/xen1210.c @@ -0,0 +1,490 @@ +/**************************************************************************** + * drivers/sensors/xen1210.c + * + * Copyright (C) 2016 Alan Carvalho de Assis. All rights reserved. + * Author: Alan Carvalho de Assis + * + * This driver is used to interface with Sensixs XEN1210 3D-board. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "xen1210.h" + +#if defined(CONFIG_XEN1210) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Character driver methods */ + +static int xen1210_open(FAR struct file *filep); +static int xen1210_close(FAR struct file *filep); +static ssize_t xen1210_read(FAR struct file *filep, FAR char *buffer, + size_t len); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This the vtable that supports the character driver interface */ + +static const struct file_operations g_xen1210fops = +{ + xen1210_open, /* open */ + xen1210_close, /* close */ + xen1210_read, /* read */ + NULL, /* write */ + NULL, /* seek */ + NULL /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , NULL /* poll */ +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL /* unlink */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: xen1210_configspi + * + * Description: + * + ****************************************************************************/ + +static inline void xen1210_configspi(FAR struct spi_dev_s *spi) +{ + /* Configure SPI for the XEN1210 */ + + SPI_SETMODE(spi, SPIDEV_MODE1); + SPI_SETBITS(spi, 8); + (void)SPI_HWFEATURES(spi, 0); + (void)SPI_SETFREQUENCY(spi, XEN1210_SPI_MAXFREQUENCY); +} + +/**************************************************************************** + * Name: xen1210_open + * + * Description: + * Standard character driver open method. + * + ****************************************************************************/ + +static int xen1210_open(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: xen1210_close + * + * Description: + * Standard character driver close method. + * + ****************************************************************************/ + +static int xen1210_close(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: xen1210_read + * + * Description: + * Standard character driver read method. + * + ****************************************************************************/ + +static ssize_t xen1210_read(FAR struct file *filep, FAR char *buffer, + size_t len) +{ + FAR struct inode *inode; + FAR struct xen1210_dev_s *priv; + struct xen1210_sample_s sample; + uint32_t regval; + int ret; + + sninfo("len=%d\n", len); + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct xen1210_dev_s *)inode->i_private; + + /* Verify that the caller has provided a buffer large enough to receive + * the magnetometer data. + */ + + if (len < sizeof(struct xen1210_sample_s)) + { + /* We could provide logic to break up a touch report into segments and + * handle smaller reads... but why? + */ + + snerr("Failed: Trying to read less bytes than sensor sample!\n"); + return -ENOSYS; + } + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + snerr("Failed: Cannot get exclusive access to driver structure!\n"); + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + sninfo("X = 0x%06X\n", priv->sample.data_x); + sninfo("Y = 0x%06X\n", priv->sample.data_y); + sninfo("Z = 0x%06X\n", priv->sample.data_z); + + /* Return read sample */ + + buffer = (FAR char *) &priv->sample; + + sem_post(&priv->exclsem); + return sizeof(struct xen1210_sample_s); +} + +/**************************************************************************** + * Name: xen1210_worker + * + * Description: + * This is the "bottom half" of the XEN1210 interrupt handler + * + ****************************************************************************/ + +static void xen1210_worker(FAR void *arg) +{ + FAR struct xen1210_dev_s *priv = (FAR struct xen1210_dev_s *)arg; + + DEBUGASSERT(priv && priv->config); + + /* Read the sensors */ + + xen1210_getdata(priv); + + /* Re-enable the XEN1210 GPIO interrupt */ + + priv->config->enable(priv->config, true); +} + +/**************************************************************************** + * Name: xen1210_interrupt + * + * Description: + * The XEN1210 interrupt handler + * + ****************************************************************************/ + +static void xen1210_interrupt(FAR struct xen1210_config_s *config, + FAR void *arg) +{ + FAR struct xen1210_dev_s *priv = (FAR struct xen1210_dev_s *)arg; + int ret; + + DEBUGASSERT(priv && priv->config == config); + + /* Disable further interrupts */ + + config->enable(config, false); + + /* Check if interrupt work is already queue. If it is already busy, then + * we already have interrupt processing in the pipeline and we need to do + * nothing more. + */ + + if (work_available(&priv->work)) + { + /* Yes.. Transfer processing to the worker thread. Since XEN1210 + * interrupts are disabled while the work is pending, no special + * action should be required to protect the work queue. + */ + + ret = work_queue(HPWORK, &priv->work, xen1210_worker, priv, 0); + if (ret != 0) + { + snerr("ERROR: Failed to queue work: %d\n", ret); + } + } + + /* Clear any pending interrupts and return success */ + + config->clear(config); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: xen1210_instantiate + * + * Description: + * Instantiate and configure the XEN1210 device driver to use the provided + * SPI device instance. + * + * Input Parameters: + * dev - An I2C or SPI driver instance + * config - Persistent board configuration data + * + * Returned Value: + * A non-zero handle is returned on success. This handle may then be used + * to configure the XEN1210 driver as necessary. A NULL handle value is + * returned on failure. + * + ****************************************************************************/ + +XEN1210_HANDLE xen1210_instantiate(FAR struct spi_dev_s *dev, + FAR struct xen1210_config_s *config) +{ + FAR struct xen1210_dev_s *priv; + uint32_t regval; + int ret; + + /* Allocate the XEN1210 driver instance */ + + priv = (FAR struct xen1210_dev_s *)kmm_zalloc(sizeof(struct xen1210_dev_s)); + if (!priv) + { + snerr("ERROR: Failed to allocate the device structure!\n"); + return NULL; + } + + /* Initialize the device state structure */ + + sem_init(&priv->exclsem, 0, 1); + priv->config = config; + + priv->spi = dev; + + /* Attach the XEN1210 interrupt handler. */ + + config->attach(config, (xen1210_handler_t)xen1210_interrupt, + (FAR void *)priv); + + /* Device initialization sequence */ + /* Power off */ + + regval = (XEN1210_POWEROFF); + + xen1210_putdata(priv, regval); + + /* Timing */ + + regval = (XEN1210_TIMING); + regval |= 0x131100; + + xen1210_putdata(priv, regval); + + /* Test */ + + regval = (XEN1210_TEST); + regval |= 0x003A00; + + xen1210_putdata(priv, regval); + + /* Power on */ + + regval = (XEN1210_POWERON); + + xen1210_putdata(priv, regval); /* X axis */ + + config->clear(config); + config->enable(config, true); + + /* Return our private data structure as an opaque handle */ + + return (XEN1210_HANDLE)priv; +} + +/**************************************************************************** + * Name: xen1210_register + * + * Description: + * This function will register the touchscreen driver as /dev/accelN where N + * is the minor device number + * + * Input Parameters: + * handle - The handle previously returned by xen1210_register + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int xen1210_register(XEN1210_HANDLE handle, int minor) +{ + FAR struct xen1210_dev_s *priv = (FAR struct xen1210_dev_s *)handle; + char devname[DEV_NAMELEN]; + int ret; + + sninfo("handle=%p minor=%d\n", handle, minor); + DEBUGASSERT(priv); + + /* Get exclusive access to the device structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + int errval = errno; + snerr("ERROR: sem_wait failed: %d\n", errval); + return -errval; + } + + /* Register the character driver */ + + snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); + ret = register_driver(devname, &g_xen1210fops, 0666, priv); + if (ret < 0) + { + snerr("ERROR: Failed to register driver %s: %d\n", devname, ret); + sem_post(&priv->exclsem); + return ret; + } + + /* Indicate that the accelerometer was successfully initialized */ + + priv->status |= XEN1210_STAT_INITIALIZED; /* Accelerometer is initialized */ + sem_post(&priv->exclsem); + return ret; +} + +/**************************************************************************** + * Name: xen1210_getdata + * + * Description: + * Read 24-bit from XEN1210 buffer, read three times (3 sensors) + * + ****************************************************************************/ + +void xen1210_getdata(FAR struct xen1210_dev_s *priv) +{ + uint32_t regval; + + /* If SPI bus is shared then lock and configure it */ + + (void)SPI_LOCK(priv->spi, true); + xen1210_configspi(priv->spi); + + /* Select the XEN1210 */ + + SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER, true); + + /* Read three times 3 bytes = 24 bits * 3 */ + + SPI_RECVBLOCK(priv->spi, ®val, 3); + priv->sample.data_x = regval & 0xFFFFFF; + + SPI_RECVBLOCK(priv->spi, ®val, 3); + priv->sample.data_y = regval & 0xFFFFFF; + + SPI_RECVBLOCK(priv->spi, ®val, 3); + priv->sample.data_z = regval & 0xFFFFFF; + + /* Deselect the XEN1210 */ + + SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER, false); + + /* Unlock bus */ + + (void)SPI_LOCK(priv->spi, false); + +#ifdef CONFIG_XEN1210_REGDEBUG + _err("%02x->%02x\n", regaddr, regval); +#endif + return regval; +} + +/**************************************************************************** + * Name: xen1210_putdata + * + * Description: + * Write 24-bit to XEN1210 buffer, write three times (3 sensors) + * + ****************************************************************************/ + +void xen1210_putdata(FAR struct xen1210_dev_s *priv, uint32_t regval) +{ +#ifdef CONFIG_XEN1210_REGDEBUG + _err("%02x<-%02x\n", regaddr, regval); +#endif + + /* If SPI bus is shared then lock and configure it */ + + (void)SPI_LOCK(priv->spi, true); + xen1210_configspi(priv->spi); + + /* Select the XEN1210 */ + + SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER, true); + + /* We need to write to 3 sensors in the daisy-chain */ + /* Write three times 3 bytes */ + + (void)SPI_SNDBLOCK(priv->spi, ®val, 3); + (void)SPI_SNDBLOCK(priv->spi, ®val, 3); + (void)SPI_SNDBLOCK(priv->spi, ®val, 3); + + /* Deselect the XEN1210 */ + + SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER, false); + + /* Unlock bus */ + + (void)SPI_LOCK(priv->spi, false); +} + +#endif /* CONFIG_SENSORS_XEN1210 */ diff --git a/drivers/sensors/xen1210.h b/drivers/sensors/xen1210.h new file mode 100644 index 0000000000..08e7b4aba4 --- /dev/null +++ b/drivers/sensors/xen1210.h @@ -0,0 +1,129 @@ +/******************************************************************************************** + * drivers/sensors/xen1210.h + * + * Copyright (C) 2014 Alan Carvalho de Assis + * Author: Alan Carvalho de Assis + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __DRIVERS_SENSORS_XEN1210_H +#define __DRIVERS_SENSORS_XEN1210_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include + +#include + +#include +#include +#include +#include + +#if defined(CONFIG_XEN1210) + +/******************************************************************************************** + * Pre-processor Definitions + ********************************************************************************************/ + +/* Driver support ***************************************************************************/ +/* This format is used to construct the /dev/mag[n] device driver path. It is defined here + * so that it will be used consistently in all places. + */ + +#define DEV_FORMAT "/dev/mag%d" +#define DEV_NAMELEN 16 + +/* Driver flags */ + +#define XEN1210_STAT_INITIALIZED 1 /* Device has been initialized */ + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ + +/* This structure describes the results of one XEN1210 sample */ + +struct xen1210_sample_s +{ + uint32_t data_x; /* Measured X-axis magnetic field */ + uint32_t data_y; /* Measured Y-axis magnetic field */ + uint32_t data_z; /* Measured Z-axis magnetic filed */ +}; + +/* This structure represents the state of the XEN1210 driver */ + +struct xen1210_dev_s +{ + /* Common fields */ + + FAR struct xen1210_config_s *config; /* Board configuration data */ + sem_t exclsem; /* Manages exclusive access to this structure */ + FAR struct spi_dev_s *spi; /* Saved SPI driver instance */ + + uint8_t status; /* See XEN1210_STAT_* definitions */ + struct work_s work; /* Supports the interrupt handling "bottom half" */ + + uint8_t nwaiters; /* Number of threads waiting for XEN1210 data */ + + sem_t waitsem; /* Used to wait for the availability of data */ + + struct work_s timeout; /* Supports timeout work */ + struct xen1210_sample_s sample; /* Last sampled accelerometer data */ +}; + +/******************************************************************************************** + * Public Function Prototypes + ********************************************************************************************/ + +/******************************************************************************************** + * Name: xen1210_getdata + * + * Description: + * Read 24-bit from XEN1210 buffer, read three times (3 sensors) + * + ********************************************************************************************/ + +void xen1210_getdata(FAR struct xen1210_dev_s *priv); + +/******************************************************************************************** + * Name: xen1210_putdata + * + * Description: + * Write 24-bit to XEN1210 buffer, write three times (3 sensors) + * + ********************************************************************************************/ + +void xen1210_putdata(FAR struct xen1210_dev_s *priv, uint32_t regval); + +#endif /* CONFIG_SENSORS_XEN1210 */ +#endif /* __DRIVERS_SENSORS_XEN1210_H */ diff --git a/include/nuttx/sensors/xen1210.h b/include/nuttx/sensors/xen1210.h new file mode 100644 index 0000000000..de92cd5225 --- /dev/null +++ b/include/nuttx/sensors/xen1210.h @@ -0,0 +1,210 @@ +/******************************************************************************************** + * include/nuttx/input/xen1210.h + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Alan Carvalho de Assis + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SENSORS_XEN1210_H +#define __INCLUDE_NUTTX_SENSORS_XEN1210_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include +#include + +#if defined(CONFIG_XEN1210) + +/******************************************************************************************** + * Pre-processor Definitions + ********************************************************************************************/ + +/* Configuration ****************************************************************************/ +/* Prerequisites: + * + * CONFIG_SCHED_WORKQUEUE - Work queue support is required + * + * Settings that effect the driver: CONFIG_DISABLE_POLL + * + * CONFIG_XEN1210 + * Enables support for the XEN1210 driver + */ + +#ifdef CONFIG_DISABLE_SIGNALS +# error "Signals are required. CONFIG_DISABLE_SIGNALS must not be selected." +#endif + +#ifndef CONFIG_SCHED_WORKQUEUE +# error "Work queue support required. CONFIG_SCHED_WORKQUEUE must be selected." +#endif + +/* The XEN1210 interfaces with the target CPU via a SPI interface. */ + +/* SPI **************************************************************************************/ +/* The device always operates in mode 1 */ + +#define XEN1210_SPI_MODE SPIDEV_MODE1 /* Mode 1 */ + +/* SPI frequency */ + +#define XEN1210_SPI_MAXFREQUENCY 100000 /* 100KHz */ + +/* XEN1210 Commands ************************************************************************/ +/* Operation Commands */ + +#define XEN1210_RESET 0x10 /* System-Reset command */ +#define XEN1210_POWERON 0x20 /* Power-ON command */ +#define XEN1210_POWEROFF 0x40 /* Power-OFF command */ +#define XEN1210_SINGLESHOT 0x60 /* Single-Shot command */ + +/* Settings Commands */ + +#define XEN1210_TIMING 0x01 /* Timing and biasing settings */ +#define XEN1210_TEST 0x02 /* Testing */ + +/* Timming Cycles */ + +#define XEN1210_1K_CYCLES 0x1113 /* 1024 cycles used be internale ADC */ +#define XEN1210_2K_CYCLES 0x2113 /* 2048 cycles used be internale ADC */ +#define XEN1210_4K_CYCLES 0x3113 /* 4096 cycles used be internale ADC */ +#define XEN1210_8K_CYCLES 0x4113 /* 8192 cycles used be internale ADC */ +#define XEN1210_16K_CYCLES 0x5113 /* 16384 cycles used be internale ADC */ +#define XEN1210_32K_CYCLES 0x6113 /* 32768 cycles used be internale ADC */ +#define XEN1210_64K_CYCLES 0x7113 /* 64536 cycles used be internale ADC */ + +/* Test setting */ + +#define XEN1210_TESTVALUE 0x3A00 /* Default value to be used with Test command */ + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ + +/* Form of the GPIO "interrupt handler" callback. Callbacks do not occur from an interrupt + * handler but rather from the context of the worker thread with interrupts enabled. + */ + +typedef void (*xen1210_handler_t)(FAR struct xen1210_config_s *config, FAR void *arg); + +/* A reference to a structure of this type must be passed to the XEN1210 driver when the + * driver is instantiated. This structure provides information about the configuration of + * the XEN1210 and provides some board-specific hooks. + * + * Memory for this structure is provided by the caller. It is not copied by the driver + * and is presumed to persist while the driver is active. The memory must be writeable + * because, under certain circumstances, the driver may modify the frequency. + */ + +struct xen1210_config_s +{ + /* Device characterization */ + + uint32_t frequency; /* SPI frequency */ + + /* IRQ/GPIO access callbacks. These operations all hidden behind + * callbacks to isolate the XEN1210 driver from differences in GPIO + * interrupt handling by varying boards and MCUs. + * + * attach - Attach the XEN1210 interrupt handler to the GPIO interrupt + * enable - Enable or disable the GPIO interrupt + * clear - Acknowledge/clear any pending GPIO interrupt + */ + + int (*attach)(FAR struct xen1210_config_s *state, xen1210_handler_t handler, + FAR void *arg); + void (*enable)(FAR struct xen1210_config_s *state, bool enable); + void (*clear)(FAR struct xen1210_config_s *state); +}; + +typedef FAR void *XEN1210_HANDLE; + +struct spi_dev_s; + +/******************************************************************************************** + * Public Function Prototypes + ********************************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/******************************************************************************************** + * Name: xen1210_instantiate + * + * Description: + * Instantiate and configure the XEN1210 device driver to use the provided I2C or SPI + * device instance. + * + * Input Parameters: + * dev - A SPI driver instance + * config - Persistent board configuration data + * + * Returned Value: + * A non-zero handle is returned on success. This handle may then be used to configure + * the XEN1210 driver as necessary. A NULL handle value is returned on failure. + * + ********************************************************************************************/ + +XEN1210_HANDLE xen1210_instantiate(FAR struct spi_dev_s *dev, + FAR struct xen1210_config_s *config); + +/******************************************************************************************** + * Name: xen1210_register + * + * Description: + * This function will register the magnetometer driver as /dev/magN + * where N is the minor device number + * + * Input Parameters: + * handle - The handle previously returned by xen1210_instantiate + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned to indicate + * the nature of the failure. + * + ********************************************************************************************/ + +int xen1210_register(XEN1210_HANDLE handle, int minor); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_SENSORS_XEN1210 */ +#endif /* __INCLUDE_NUTTX_SENSORS_XEN1210_H */